diff mbox

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

Message ID 20171104140828.32469-6-hdegoede@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Hans de Goede Nov. 4, 2017, 2:08 p.m. UTC
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@redhat.com>
---
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(+)

Comments

Daniel Vetter Nov. 6, 2017, 10:17 a.m. UTC | #1
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@redhat.com>
> ---
> 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@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Hans de Goede Nov. 25, 2017, 3:10 p.m. UTC | #2
Hi,

On 11/06/2017 11:17 AM, Daniel Vetter wrote:
> 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@redhat.com>
>> ---
>> 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.

So I've finally been able to make some time to look at this (and your other
review comments) I've changes this so that the hardware read-out happens
from intel_dsi_init(), mirroring the lvds fixed mode readout from
intel_lvds_init().

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

It is the otherway around, hardware readout is used to set an initial
value and then the quirk table gets checked for any matches which then
override the initial value. The end result is the same though :)

I hope to post a v6 of the patch-set with this and your other remarks
addressed this weekend.

Regards,

Hans






> -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@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

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);
 
 	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)