[Intel-gfx] [PATCH] drm/i915: fastboot support for HSW and BDW

Jesse Barnes jbarnes at virtuousgeek.org
Mon Jan 13 21:40:03 CET 2014


On Mon, 13 Jan 2014 17:55:27 -0200
Paulo Zanoni <przanoni at gmail.com> wrote:

> 2014/1/8 Jesse Barnes <jbarnes at virtuousgeek.org>:
> > No idea if this is correct or not, all the WRPLL programming is new to
> > me.  Paulo, can you take a look?  At least it doesn't complain on my BDW
> > here...
> 
> As a side note: can't we add some debugfs interface that, when read,
> would trigger a HW state readout, and then would compare it against
> what we have? It would be the perfect thing to validate patches like
> the one you wrote... And it would make QA easier (just write a test
> case that sets modes and reads the debugfs interface! Or just modify
> kms_setmode/testdisplay to do it everywhere).
> 
> Some comments:
> 
> - I guess the commit message could be improved :)
> - We probably need to do something about the VGA output, which uses
> the old intel_crt encoder instead of intel_digital_port. If this patch
> doesn't regress anything, we could do it on a separate patch.
> - Don't we also need to patch intel_pipe_config_compare() so it checks
> the now-used adjusted_mode.crtc_clock?
> - Based on that, don't we also need HW readout support for port_clock?
> - You should probably compare your patch against "[PATCH 2/2]
> drm/i915: add fast boot support for Haswell" sent by Furquan Shaikh in
> August, and also check the reviews we gave to it.
> - I tried booting it on my HSW machine that only has an eDP output,
> and the driver doesn't load:
> 
> I get:
> 
> [   62.635700] WARNING: CPU: 0 PID: 1120 at
> drivers/gpu/drm/i915/intel_ddi.c:431
> intel_ddi_get_crtc_encoder+0x95/0xa0 [i915]()
> [   62.635703] 0 encoders on crtc for pipe A
> 
> Then later I see:
> 
> [   62.636200] kernel BUG at drivers/gpu/drm/i915/intel_ddi.c:433!
> [   62.636249] invalid opcode: 0000 [#1] SMP
> 
> Which is the "BUG_ON(ret == NULL);" line
> 
> Please notice that I'm not using the i915_fastboot command line argument.
> 
> More below:
> 
> >
> > Thanks,
> > Jesse
> > ---
> >  drivers/gpu/drm/i915/i915_reg.h      |  6 ++++
> >  drivers/gpu/drm/i915/intel_ddi.c     |  2 +-
> >  drivers/gpu/drm/i915/intel_display.c | 61 ++++++++++++++++++++++++++++++++++--
> >  drivers/gpu/drm/i915/intel_drv.h     |  1 +
> >  4 files changed, 67 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> > index a699efd..644e4f9 100644
> > --- a/drivers/gpu/drm/i915/i915_reg.h
> > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > @@ -5318,8 +5318,13 @@
> >  #define  WRPLL_PLL_SELECT_LCPLL_2700   (0x03<<28)
> >  /* WRPLL divider programming */
> >  #define  WRPLL_DIVIDER_REFERENCE(x)    ((x)<<0)
> > +#define  WRPLL_DIVIDER_REF_MASK                (0xff)
> >  #define  WRPLL_DIVIDER_POST(x)         ((x)<<8)
> > +#define  WRPLL_DIVIDER_POST_MASK       (0x3f<<8)
> > +#define  WRPLL_DIVIDER_POST_SHIFT      8
> >  #define  WRPLL_DIVIDER_FEEDBACK(x)     ((x)<<16)
> > +#define  WRPLL_DIVIDER_FB_SHIFT                16
> > +#define  WRPLL_DIVIDER_FB_MASK         (0xff<<16)
> >
> >  /* Port clock selection */
> >  #define PORT_CLK_SEL_A                 0x46100
> > @@ -5332,6 +5337,7 @@
> >  #define  PORT_CLK_SEL_WRPLL1           (4<<29)
> >  #define  PORT_CLK_SEL_WRPLL2           (5<<29)
> >  #define  PORT_CLK_SEL_NONE             (7<<29)
> > +#define  PORT_CLK_SEL_MASK             (7<<29)
> >
> >  /* Transcoder clock selection */
> >  #define TRANS_CLK_SEL_A                        0x46140
> > diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> > index 1488b28..f3d7b42 100644
> > --- a/drivers/gpu/drm/i915/intel_ddi.c
> > +++ b/drivers/gpu/drm/i915/intel_ddi.c
> > @@ -413,7 +413,7 @@ static void intel_ddi_mode_set(struct intel_encoder *encoder)
> >         }
> >  }
> >
> > -static struct intel_encoder *
> > +struct intel_encoder *
> >  intel_ddi_get_crtc_encoder(struct drm_crtc *crtc)
> >  {
> >         struct drm_device *dev = crtc->dev;
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index 74137d5..f87244d 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -48,6 +48,8 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
> >                                 struct intel_crtc_config *pipe_config);
> >  static void ironlake_pch_clock_get(struct intel_crtc *crtc,
> >                                    struct intel_crtc_config *pipe_config);
> > +static void haswell_ddi_clock_get(struct intel_crtc *crtc,
> > +                                 struct intel_crtc_config *pipe_config);
> >
> >  static int intel_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode,
> >                           int x, int y, struct drm_framebuffer *old_fb);
> > @@ -6994,10 +6996,11 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
> >                 tmp = I915_READ(FDI_RX_CTL(PIPE_A));
> >                 pipe_config->fdi_lanes = ((FDI_DP_PORT_WIDTH_MASK & tmp) >>
> >                                           FDI_DP_PORT_WIDTH_SHIFT) + 1;
> > -
> > -               ironlake_get_fdi_m_n_config(crtc, pipe_config);
> >         }
> >
> > +       ironlake_get_fdi_m_n_config(crtc, pipe_config);
> 
> This is a little confusing, probably wrong, because FDI is only used
> when has_pch_encoder is true, but you're calling this code on all
> cases.
> 
> Function ironlake_get_fdi_m_n_config() calls
> intel_cpu_transcoder_get_m_n() for eDP/DP/HDMI.
> However, we have encoder->get_config which calls
> intel_ddi_get_config() which calls intel_dp_get_m_n(), which will call
> intel_cpu_transcoder_get_m_n() again on the same cases. So we call the
> same thing twice.
> 
> I would imagine you probably don't need to move this line above, but I
> may be wrong. If something is wrong, you probably need to fix some
> other code that's assuming that "gen5+ DP m/n registers are on the
> PCH" or something like that.
> 
> 
> > +       haswell_ddi_clock_get(crtc, pipe_config);
> > +
> >         intel_get_pipe_timings(crtc, pipe_config);
> >
> >         pfit_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe);
> > @@ -8034,6 +8037,60 @@ static void ironlake_pch_clock_get(struct intel_crtc *crtc,
> >                                          &pipe_config->fdi_m_n);
> >  }
> >
> > +#define LC_FREQ 2700
> > +
> > +static int intel_ddi_calc_wrpll_link(u32 wrpll)
> > +{
> > +       int n, p, r;
> > +
> > +       r = wrpll & WRPLL_DIVIDER_REF_MASK;
> > +       p = (wrpll & WRPLL_DIVIDER_POST_MASK) >> WRPLL_DIVIDER_POST_SHIFT;
> > +       n = (wrpll & WRPLL_DIVIDER_FB_MASK) >> WRPLL_DIVIDER_FB_SHIFT;
> > +
> > +       return (LC_FREQ * n) / (p * r);
> > +}
> > +
> > +static void haswell_ddi_clock_get(struct intel_crtc *crtc,
> > +                                 struct intel_crtc_config *pipe_config)
> > +{
> > +       struct intel_encoder *intel_encoder =
> > +               intel_ddi_get_crtc_encoder(&crtc->base);
> > +       struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
> > +       enum port port = intel_ddi_get_encoder_port(intel_encoder);
> > +       int link_clock;
> > +       u32 val, pll;
> > +
> > +       val = I915_READ(PORT_CLK_SEL(port));
> > +       switch (val & PORT_CLK_SEL_MASK) {
> > +       case PORT_CLK_SEL_LCPLL_810:
> > +               link_clock = 81000;
> > +               break;
> > +       case PORT_CLK_SEL_LCPLL_1350:
> > +               link_clock = 135000;
> > +               break;
> > +       case PORT_CLK_SEL_LCPLL_2700:
> > +               link_clock = 270000;
> > +               break;
> > +       case PORT_CLK_SEL_WRPLL1:
> > +               pll = I915_READ(WRPLL_CTL1);
> > +               link_clock = intel_ddi_calc_wrpll_link(pll);
> > +               break;
> > +       case PORT_CLK_SEL_WRPLL2:
> > +               pll = I915_READ(WRPLL_CTL2);
> > +               link_clock = intel_ddi_calc_wrpll_link(pll);
> > +               break;
> > +       case PORT_CLK_SEL_SPLL:
> > +               link_clock = 135000;
> > +               break;
> > +       default:
> > +               WARN(1, "bad port clock sel\n");
> > +               return;
> > +       }
> > +
> > +       pipe_config->adjusted_mode.crtc_clock =
> > +               intel_dotclock_calculate(link_clock, &pipe_config->fdi_m_n);
> > +}
> > +
> >  /** Returns the currently programmed mode of the given pipe. */
> >  struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
> >                                              struct drm_crtc *crtc)
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index 46aea6c..7bfc19a 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -604,6 +604,7 @@ void intel_prepare_ddi(struct drm_device *dev);
> >  void hsw_fdi_link_train(struct drm_crtc *crtc);
> >  void intel_ddi_init(struct drm_device *dev, enum port port);
> >  enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder);
> > +struct intel_encoder *intel_ddi_get_crtc_encoder(struct drm_crtc *crtc);
> >  bool intel_ddi_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe);
> >  int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv);
> >  void intel_ddi_pll_init(struct drm_device *dev);
> > --

Ok, I only tried it on BDW, I'll check again w/o the fastboot param and
see what happens.

Agree on the other points.

-- 
Jesse Barnes, Intel Open Source Technology Center



More information about the Intel-gfx mailing list