Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/i915: Fix the VLV/CHV DSI panel orientation hw readout

Let's make sure the DSI port is actually on before we go
poking at the plane register to determine which way
it's rotated. Otherwise we could be looking at a plane
that is feeding a HDMI port for instance.

And in order to read the plane register we need the power
well to be on. Make sure that is indeed the case. We'll
also make sure the plane is actually enabled before we
trust the rotation bit to tell us the truth.

v2: s/intel_dsi/vlv_dsi/

Cc: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20181022141953.3889-1-ville.syrjala@linux.intel.com
Tested-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> #irc

+43 -13
+43 -13
drivers/gpu/drm/i915/vlv_dsi.c
··· 1566 1566 .atomic_duplicate_state = intel_digital_connector_duplicate_state, 1567 1567 }; 1568 1568 1569 - static int intel_dsi_get_panel_orientation(struct intel_connector *connector) 1569 + static enum drm_panel_orientation 1570 + vlv_dsi_get_hw_panel_orientation(struct intel_connector *connector) 1570 1571 { 1571 1572 struct drm_i915_private *dev_priv = to_i915(connector->base.dev); 1572 - int orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL; 1573 - enum i9xx_plane_id i9xx_plane; 1573 + struct intel_encoder *encoder = connector->encoder; 1574 + enum intel_display_power_domain power_domain; 1575 + enum drm_panel_orientation orientation; 1576 + struct intel_plane *plane; 1577 + struct intel_crtc *crtc; 1578 + enum pipe pipe; 1574 1579 u32 val; 1575 1580 1576 - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { 1577 - if (connector->encoder->crtc_mask == BIT(PIPE_B)) 1578 - i9xx_plane = PLANE_B; 1579 - else 1580 - i9xx_plane = PLANE_A; 1581 + if (!encoder->get_hw_state(encoder, &pipe)) 1582 + return DRM_MODE_PANEL_ORIENTATION_UNKNOWN; 1581 1583 1582 - val = I915_READ(DSPCNTR(i9xx_plane)); 1583 - if (val & DISPPLANE_ROTATE_180) 1584 - orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP; 1585 - } 1584 + crtc = intel_get_crtc_for_pipe(dev_priv, pipe); 1585 + plane = to_intel_plane(crtc->base.primary); 1586 + 1587 + power_domain = POWER_DOMAIN_PIPE(pipe); 1588 + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) 1589 + return DRM_MODE_PANEL_ORIENTATION_UNKNOWN; 1590 + 1591 + val = I915_READ(DSPCNTR(plane->i9xx_plane)); 1592 + 1593 + if (!(val & DISPLAY_PLANE_ENABLE)) 1594 + orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN; 1595 + else if (val & DISPPLANE_ROTATE_180) 1596 + orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP; 1597 + else 1598 + orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL; 1599 + 1600 + intel_display_power_put(dev_priv, power_domain); 1586 1601 1587 1602 return orientation; 1603 + } 1604 + 1605 + static enum drm_panel_orientation 1606 + vlv_dsi_get_panel_orientation(struct intel_connector *connector) 1607 + { 1608 + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); 1609 + enum drm_panel_orientation orientation; 1610 + 1611 + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { 1612 + orientation = vlv_dsi_get_hw_panel_orientation(connector); 1613 + if (orientation != DRM_MODE_PANEL_ORIENTATION_UNKNOWN) 1614 + return orientation; 1615 + } 1616 + 1617 + return DRM_MODE_PANEL_ORIENTATION_NORMAL; 1588 1618 } 1589 1619 1590 1620 static void intel_dsi_add_properties(struct intel_connector *connector) ··· 1634 1604 connector->base.state->scaling_mode = DRM_MODE_SCALE_ASPECT; 1635 1605 1636 1606 connector->base.display_info.panel_orientation = 1637 - intel_dsi_get_panel_orientation(connector); 1607 + vlv_dsi_get_panel_orientation(connector); 1638 1608 drm_connector_init_panel_orientation_property( 1639 1609 &connector->base, 1640 1610 connector->panel.fixed_mode->hdisplay,