Re: [PATCH v5 5/7] drm/i915: Add "panel orientation" property to the panel connector

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 <hdegoede@xxxxxxxxxx>
> ---
> 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
> Intel-gfx@xxxxxxxxxxxxxxxxxxxxx
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux