On Sat, Nov 04, 2017 at 03:08:26PM +0100, Hans de Goede wrote:
> Ideally we could use the VBT for this, that would be simple, in
> intel_dsi_init() check dev_priv->vbt.dsi.config->rotation, set
> connector->display_info.panel_orientation accordingly and call
> drm_connector_init_panel_orientation_property(), done.
> 
> Unfortunately vbt.dsi.config->rotation is always 0 even on tablets
> with an upside down LCD and where the GOP is properly rotating the
> EFI fb in hardware.
> 
> So instead we end up reading the rotation from the primary plane.
> To read the info from the primary plane, we need to know which crtc
> the panel is hooked up to, so we do this the first time the panel
> encoder's get_config function get called, as by then the encoder
> crtc routing has been set up.
> 
> This commit only implements the panel orientation property for DSI
> panels on BYT / CHT / BXT hardware, as all known non normal oriented
> panels are only found on this hardware.
> 
> Signed-off-by: Hans de Goede <[email protected]>
> ---
> Changes in v2:
> -Read back the rotation applied by the GOP from the primary plane
>  instead of relying on dev_priv->vbt.dsi.config->rotation, because it
>  seems that the VBT rotation filed is always 0 even on devices where the
>  GOP does apply a rotation
> 
> Changes in v3:
> -Rewrite the code to read back the orientation from the primary
>  plane to contain all of this in intel_dsi.c instead of poking a bunch
>  of holes between all the different layers
> ---
>  drivers/gpu/drm/i915/intel_drv.h   |  1 +
>  drivers/gpu/drm/i915/intel_dsi.c   | 48 
> ++++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_dsi.h   |  2 ++
>  drivers/gpu/drm/i915/intel_panel.c | 16 +++++++++++++
>  4 files changed, 67 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_drv.h 
> b/drivers/gpu/drm/i915/intel_drv.h
> index 47d022d48718..11efc6cb74c8 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1727,6 +1727,7 @@ void intel_panel_enable_backlight(const struct 
> intel_crtc_state *crtc_state,
>                                 const struct drm_connector_state *conn_state);
>  void intel_panel_disable_backlight(const struct drm_connector_state 
> *old_conn_state);
>  void intel_panel_destroy_backlight(struct drm_connector *connector);
> +void intel_panel_set_orientation(struct intel_panel *panel, int orientation);
>  enum drm_connector_status intel_panel_detect(struct drm_i915_private 
> *dev_priv);
>  extern struct drm_display_mode *intel_find_panel_downclock(
>                               struct drm_i915_private *dev_priv,
> diff --git a/drivers/gpu/drm/i915/intel_dsi.c 
> b/drivers/gpu/drm/i915/intel_dsi.c
> index 83f15848098a..3e2f12db8d15 100644
> --- a/drivers/gpu/drm/i915/intel_dsi.c
> +++ b/drivers/gpu/drm/i915/intel_dsi.c
> @@ -1084,13 +1084,16 @@ static void bxt_dsi_get_pipe_config(struct 
> intel_encoder *encoder,
>       struct drm_display_mode *adjusted_mode_sw;
>       struct intel_crtc *intel_crtc;
>       struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
> +     struct intel_panel *panel = &intel_dsi->attached_connector->panel;
>       unsigned int lane_count = intel_dsi->lane_count;
>       unsigned int bpp, fmt;
> +     int orientation;
>       enum port port;
>       u16 hactive, hfp, hsync, hbp, vfp, vsync, vbp;
>       u16 hfp_sw, hsync_sw, hbp_sw;
>       u16 crtc_htotal_sw, crtc_hsync_start_sw, crtc_hsync_end_sw,
>                               crtc_hblank_start_sw, crtc_hblank_end_sw;
> +     u32 val;
>  
>       /* FIXME: hw readout should not depend on SW state */
>       intel_crtc = to_intel_crtc(encoder->base.crtc);
> @@ -1234,6 +1237,49 @@ static void bxt_dsi_get_pipe_config(struct 
> intel_encoder *encoder,
>       if (adjusted_mode->crtc_hblank_end == crtc_hblank_end_sw)
>               adjusted_mode->crtc_hblank_end =
>                                       adjusted_mode_sw->crtc_hblank_end;
> +
> +     if (!intel_dsi->got_panel_orientation) {
> +             val = I915_READ(PLANE_CTL(intel_crtc->pipe, 0));
> +             /* The rotation is used to correct for the panel orientation */
> +             switch (val & PLANE_CTL_ROTATE_MASK) {
> +             case PLANE_CTL_ROTATE_0:
> +                     orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL;
> +                     break;
> +             case PLANE_CTL_ROTATE_90:
> +                     orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP;
> +                     break;
> +             case PLANE_CTL_ROTATE_180:
> +                     orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP;
> +                     break;
> +             case PLANE_CTL_ROTATE_270:
> +                     orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP;
> +                     break;
> +             }
> +             intel_panel_set_orientation(panel, orientation);
> +             intel_dsi->got_panel_orientation = true;
> +     }
> +}
> +
> +static void vlv_dsi_get_pipe_config(struct intel_encoder *encoder)
> +{
> +     struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> +     struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
> +     struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
> +     struct intel_panel *panel = &intel_dsi->attached_connector->panel;
> +     int orientation;
> +     u32 val;
> +
> +     if (!intel_dsi->got_panel_orientation) {
> +             val = I915_READ(DSPCNTR(intel_crtc->plane));
> +
> +             if (val & DISPPLANE_ROTATE_180)
> +                     orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP;
> +             else
> +                     orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL;
> +
> +             intel_panel_set_orientation(panel, orientation);
> +             intel_dsi->got_panel_orientation = true;
> +     }
>  }
>  
>  static void intel_dsi_get_config(struct intel_encoder *encoder,
> @@ -1245,6 +1291,8 @@ static void intel_dsi_get_config(struct intel_encoder 
> *encoder,
>  
>       if (IS_GEN9_LP(dev_priv))
>               bxt_dsi_get_pipe_config(encoder, pipe_config);
> +     else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> +             vlv_dsi_get_pipe_config(encoder);

get_config gets called all the time, this feels like the wrong place for
this. I assume you want this somewhere at init time? We also don't have
funny hacks for the fixed_mode readout in intel_lvds.c.

Also I'd kinda assume you'd only do this as a fallback, for when the quirk
table doesn't have an entry?
-Daniel

>  
>       pclk = intel_dsi_get_pclk(encoder, pipe_config->pipe_bpp,
>                                 pipe_config);
> diff --git a/drivers/gpu/drm/i915/intel_dsi.h 
> b/drivers/gpu/drm/i915/intel_dsi.h
> index 7afeb9580f41..92c2fe31f3fd 100644
> --- a/drivers/gpu/drm/i915/intel_dsi.h
> +++ b/drivers/gpu/drm/i915/intel_dsi.h
> @@ -52,6 +52,8 @@ struct intel_dsi {
>       /* if true, use HS mode, otherwise LP */
>       bool hs;
>  
> +     bool got_panel_orientation;
> +
>       /* virtual channel */
>       int channel;
>  
> diff --git a/drivers/gpu/drm/i915/intel_panel.c 
> b/drivers/gpu/drm/i915/intel_panel.c
> index adc51e452e3e..7d571bef847e 100644
> --- a/drivers/gpu/drm/i915/intel_panel.c
> +++ b/drivers/gpu/drm/i915/intel_panel.c
> @@ -1842,6 +1842,22 @@ void intel_panel_destroy_backlight(struct 
> drm_connector *connector)
>       panel->backlight.present = false;
>  }
>  
> +void intel_panel_set_orientation(struct intel_panel *panel, int orientation)
> +{
> +     struct intel_connector *panel_conn;
> +     int width = 0, height = 0;
> +
> +     if (panel->fixed_mode) {
> +             width = panel->fixed_mode->hdisplay;
> +             height = panel->fixed_mode->vdisplay;
> +     }
> +
> +     panel_conn = container_of(panel, struct intel_connector, panel);
> +     panel_conn->base.display_info.panel_orientation = orientation;
> +     drm_connector_init_panel_orientation_property(&panel_conn->base,
> +                                                   width, height);
> +}
> +
>  /* Set up chip specific backlight functions */
>  static void
>  intel_panel_init_backlight_funcs(struct intel_panel *panel)
> -- 
> 2.14.3
> 
> _______________________________________________
> Intel-gfx mailing list
> [email protected]
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to