* Author: Jani Nikula <jani.nikula@intel.com>
  */
 
+#include <linux/dmi.h>
 #include <linux/slab.h>
 
 #include <drm/drm_atomic_helper.h>
        intel_dsi_log_params(intel_dsi);
 }
 
+typedef void (*vlv_dsi_dmi_quirk_func)(struct intel_dsi *intel_dsi);
+
+/*
+ * Vtotal is wrong on the Asus TF103C leading to the last line of the display
+ * being shown as the first line. The factory installed Android has a hardcoded
+ * modeline, causing it to not suffer from this BIOS bug.
+ *
+ * Original mode: "1280x800": 60 67700 1280 1312 1328 1376 800 808 812 820 0x8 0xa
+ * Fixed    mode: "1280x800": 60 67700 1280 1312 1328 1376 800 808 812 816 0x8 0xa
+ *
+ * https://gitlab.freedesktop.org/drm/intel/-/issues/9381
+ */
+static void vlv_dsi_asus_tf103c_mode_fixup(struct intel_dsi *intel_dsi)
+{
+       /* Cast away the const as we want to fixup the mode */
+       struct drm_display_mode *fixed_mode = (struct drm_display_mode *)
+               intel_panel_preferred_fixed_mode(intel_dsi->attached_connector);
+
+       if (fixed_mode->vtotal == 820)
+               fixed_mode->vtotal -= 4;
+}
+
+static const struct dmi_system_id vlv_dsi_dmi_quirk_table[] = {
+       {
+               /* Asus Transformer Pad TF103C */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "TF103C"),
+               },
+               .driver_data = (void *)vlv_dsi_asus_tf103c_mode_fixup,
+       },
+       { }
+};
+
 void vlv_dsi_init(struct drm_i915_private *dev_priv)
 {
        struct intel_dsi *intel_dsi;
        struct intel_connector *intel_connector;
        struct drm_connector *connector;
        struct drm_display_mode *current_mode;
+       const struct dmi_system_id *dmi_id;
        enum port port;
        enum pipe pipe;
 
                goto err_cleanup_connector;
        }
 
+       dmi_id = dmi_first_match(vlv_dsi_dmi_quirk_table);
+       if (dmi_id) {
+               vlv_dsi_dmi_quirk_func quirk_func =
+                       (vlv_dsi_dmi_quirk_func)dmi_id->driver_data;
+
+               quirk_func(intel_dsi);
+       }
+
        intel_panel_init(intel_connector, NULL);
 
        intel_backlight_setup(intel_connector, INVALID_PIPE);