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

drm/i915: Determine DSI panel orientation from VBT

VBT appears to have two (or possibly three) ways to indicate the panel
rotation. The first is in the MIPI config block, but that apparenly
usually (maybe always?) indicates 0 degrees despite the actual panel
orientation. The second way to indicate this is in the general features
block, which can just indicate whether 180 degress rotation is used.
The third might be a separate rotation data block, but that is not
at all documented so who knows what it may contain.

Let's try the first two. We first try the DSI specicic VBT
information, and it it doesn't look trustworthy (ie. indicates
0 degrees) we fall back to the 180 degree thing. Just to avoid too
many changes in one go we shall also keep the hardware readout path
for now.

If this works for more than just my VLV FFRD the question becomes
how many of the panel orientation quirks are now redundant?

v2: Move the code into intel_dsi.c (Jani)

Cc: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20181022142015.4026-1-ville.syrjala@linux.intel.com
Tested-by: Hans de Goede <hdegoede@redhat.com>

+53 -1
+2
drivers/gpu/drm/i915/i915_drv.h
··· 1110 1110 unsigned int panel_type:4; 1111 1111 int lvds_ssc_freq; 1112 1112 unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */ 1113 + enum drm_panel_orientation orientation; 1113 1114 1114 1115 enum drrs_support_type drrs_type; 1115 1116 ··· 1156 1155 u8 *data; 1157 1156 const u8 *sequence[MIPI_SEQ_MAX]; 1158 1157 u8 *deassert_seq; /* Used by fixup_mipi_sequences() */ 1158 + enum drm_panel_orientation orientation; 1159 1159 } dsi; 1160 1160 1161 1161 int crt_ddc_pin;
+31
drivers/gpu/drm/i915/intel_bios.c
··· 420 420 intel_bios_ssc_frequency(dev_priv, general->ssc_freq); 421 421 dev_priv->vbt.display_clock_mode = general->display_clock_mode; 422 422 dev_priv->vbt.fdi_rx_polarity_inverted = general->fdi_rx_polarity_inverted; 423 + if (bdb->version >= 181) { 424 + dev_priv->vbt.orientation = general->rotate_180 ? 425 + DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP : 426 + DRM_MODE_PANEL_ORIENTATION_NORMAL; 427 + } else { 428 + dev_priv->vbt.orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN; 429 + } 423 430 DRM_DEBUG_KMS("BDB_GENERAL_FEATURES int_tv_support %d int_crt_support %d lvds_use_ssc %d lvds_ssc_freq %d display_clock_mode %d fdi_rx_polarity_inverted %d\n", 424 431 dev_priv->vbt.int_tv_support, 425 432 dev_priv->vbt.int_crt_support, ··· 858 851 } 859 852 860 853 parse_dsi_backlight_ports(dev_priv, bdb->version, port); 854 + 855 + /* FIXME is the 90 vs. 270 correct? */ 856 + switch (config->rotation) { 857 + case ENABLE_ROTATION_0: 858 + /* 859 + * Most (all?) VBTs claim 0 degrees despite having 860 + * an upside down panel, thus we do not trust this. 861 + */ 862 + dev_priv->vbt.dsi.orientation = 863 + DRM_MODE_PANEL_ORIENTATION_UNKNOWN; 864 + break; 865 + case ENABLE_ROTATION_90: 866 + dev_priv->vbt.dsi.orientation = 867 + DRM_MODE_PANEL_ORIENTATION_RIGHT_UP; 868 + break; 869 + case ENABLE_ROTATION_180: 870 + dev_priv->vbt.dsi.orientation = 871 + DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP; 872 + break; 873 + case ENABLE_ROTATION_270: 874 + dev_priv->vbt.dsi.orientation = 875 + DRM_MODE_PANEL_ORIENTATION_LEFT_UP; 876 + break; 877 + } 861 878 862 879 /* We have mandatory mipi config blocks. Initialize as generic panel */ 863 880 dev_priv->vbt.dsi.panel_id = MIPI_DSI_GENERIC_PANEL_ID;
+17
drivers/gpu/drm/i915/intel_dsi.c
··· 109 109 110 110 return host; 111 111 } 112 + 113 + enum drm_panel_orientation 114 + intel_dsi_get_panel_orientation(struct intel_connector *connector) 115 + { 116 + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); 117 + enum drm_panel_orientation orientation; 118 + 119 + orientation = dev_priv->vbt.dsi.orientation; 120 + if (orientation != DRM_MODE_PANEL_ORIENTATION_UNKNOWN) 121 + return orientation; 122 + 123 + orientation = dev_priv->vbt.orientation; 124 + if (orientation != DRM_MODE_PANEL_ORIENTATION_UNKNOWN) 125 + return orientation; 126 + 127 + return DRM_MODE_PANEL_ORIENTATION_NORMAL; 128 + }
+2
drivers/gpu/drm/i915/intel_dsi.h
··· 149 149 /* intel_dsi.c */ 150 150 int intel_dsi_bitrate(const struct intel_dsi *intel_dsi); 151 151 int intel_dsi_tlpx_ns(const struct intel_dsi *intel_dsi); 152 + enum drm_panel_orientation 153 + intel_dsi_get_panel_orientation(struct intel_connector *connector); 152 154 153 155 /* vlv_dsi.c */ 154 156 void vlv_dsi_wait_for_fifo_empty(struct intel_dsi *intel_dsi, enum port port);
+1 -1
drivers/gpu/drm/i915/vlv_dsi.c
··· 1614 1614 return orientation; 1615 1615 } 1616 1616 1617 - return DRM_MODE_PANEL_ORIENTATION_NORMAL; 1617 + return intel_dsi_get_panel_orientation(connector); 1618 1618 } 1619 1619 1620 1620 static void intel_dsi_add_properties(struct intel_connector *connector)