drm/i915: Determine DSI panel orientation from VBT
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Mon, 22 Oct 2018 14:20:15 +0000 (17:20 +0300)
committerVille Syrjälä <ville.syrjala@linux.intel.com>
Tue, 13 Nov 2018 15:20:32 +0000 (17:20 +0200)
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>
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/intel_bios.c
drivers/gpu/drm/i915/intel_dsi.c
drivers/gpu/drm/i915/intel_dsi.h
drivers/gpu/drm/i915/vlv_dsi.c

index 08d25aa480f72a56bf1c6d2cc582d7a540f94758..5d686b585a950be7fe77bc64b22bd9c1eac2b46d 100644 (file)
@@ -1110,6 +1110,7 @@ struct intel_vbt_data {
        unsigned int panel_type:4;
        int lvds_ssc_freq;
        unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */
+       enum drm_panel_orientation orientation;
 
        enum drrs_support_type drrs_type;
 
@@ -1155,6 +1156,7 @@ struct intel_vbt_data {
                u8 *data;
                const u8 *sequence[MIPI_SEQ_MAX];
                u8 *deassert_seq; /* Used by fixup_mipi_sequences() */
+               enum drm_panel_orientation orientation;
        } dsi;
 
        int crt_ddc_pin;
index 0ad2304457ab2e4c3e08e8772f6bd6b67975042e..bd7b2da714192f0aa4e418cb09fa3fb469323d10 100644 (file)
@@ -420,6 +420,13 @@ parse_general_features(struct drm_i915_private *dev_priv,
                intel_bios_ssc_frequency(dev_priv, general->ssc_freq);
        dev_priv->vbt.display_clock_mode = general->display_clock_mode;
        dev_priv->vbt.fdi_rx_polarity_inverted = general->fdi_rx_polarity_inverted;
+       if (bdb->version >= 181) {
+               dev_priv->vbt.orientation = general->rotate_180 ?
+                       DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP :
+                       DRM_MODE_PANEL_ORIENTATION_NORMAL;
+       } else {
+               dev_priv->vbt.orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
+       }
        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",
                      dev_priv->vbt.int_tv_support,
                      dev_priv->vbt.int_crt_support,
@@ -852,6 +859,30 @@ parse_mipi_config(struct drm_i915_private *dev_priv,
 
        parse_dsi_backlight_ports(dev_priv, bdb->version, port);
 
+       /* FIXME is the 90 vs. 270 correct? */
+       switch (config->rotation) {
+       case ENABLE_ROTATION_0:
+               /*
+                * Most (all?) VBTs claim 0 degrees despite having
+                * an upside down panel, thus we do not trust this.
+                */
+               dev_priv->vbt.dsi.orientation =
+                       DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
+               break;
+       case ENABLE_ROTATION_90:
+               dev_priv->vbt.dsi.orientation =
+                       DRM_MODE_PANEL_ORIENTATION_RIGHT_UP;
+               break;
+       case ENABLE_ROTATION_180:
+               dev_priv->vbt.dsi.orientation =
+                       DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP;
+               break;
+       case ENABLE_ROTATION_270:
+               dev_priv->vbt.dsi.orientation =
+                       DRM_MODE_PANEL_ORIENTATION_LEFT_UP;
+               break;
+       }
+
        /* We have mandatory mipi config blocks. Initialize as generic panel */
        dev_priv->vbt.dsi.panel_id = MIPI_DSI_GENERIC_PANEL_ID;
 }
index b9d5ef79015e2bb615b0237961ae9bfaf9d98060..5fec02aceaed9146f99a6d8685a356ef8f1ed2b7 100644 (file)
@@ -109,3 +109,20 @@ struct intel_dsi_host *intel_dsi_host_init(struct intel_dsi *intel_dsi,
 
        return host;
 }
+
+enum drm_panel_orientation
+intel_dsi_get_panel_orientation(struct intel_connector *connector)
+{
+       struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+       enum drm_panel_orientation orientation;
+
+       orientation = dev_priv->vbt.dsi.orientation;
+       if (orientation != DRM_MODE_PANEL_ORIENTATION_UNKNOWN)
+               return orientation;
+
+       orientation = dev_priv->vbt.orientation;
+       if (orientation != DRM_MODE_PANEL_ORIENTATION_UNKNOWN)
+               return orientation;
+
+       return DRM_MODE_PANEL_ORIENTATION_NORMAL;
+}
index f2a3ddedcc5dbb4e5878187f982cdec20fee842a..ee93137f4433d3c3b7a482d7ea428f6a92fb602d 100644 (file)
@@ -149,6 +149,8 @@ static inline bool is_cmd_mode(struct intel_dsi *intel_dsi)
 /* intel_dsi.c */
 int intel_dsi_bitrate(const struct intel_dsi *intel_dsi);
 int intel_dsi_tlpx_ns(const struct intel_dsi *intel_dsi);
+enum drm_panel_orientation
+intel_dsi_get_panel_orientation(struct intel_connector *connector);
 
 /* vlv_dsi.c */
 void vlv_dsi_wait_for_fifo_empty(struct intel_dsi *intel_dsi, enum port port);
index f1eedc974dbc8151881d2d5a39c5bc455f0c857f..361e962a7969044aba1c8464096edfa493b4d0c7 100644 (file)
@@ -1614,7 +1614,7 @@ vlv_dsi_get_panel_orientation(struct intel_connector *connector)
                        return orientation;
        }
 
-       return DRM_MODE_PANEL_ORIENTATION_NORMAL;
+       return intel_dsi_get_panel_orientation(connector);
 }
 
 static void intel_dsi_add_properties(struct intel_connector *connector)