/* Parse general panel options */
 static void
-parse_panel_options(struct drm_i915_private *i915)
+parse_panel_options(struct drm_i915_private *i915,
+                   struct intel_panel *panel)
 {
        const struct bdb_lvds_options *lvds_options;
        int panel_type;
        if (!lvds_options)
                return;
 
-       i915->vbt.lvds_dither = lvds_options->pixel_dither;
+       panel->vbt.lvds_dither = lvds_options->pixel_dither;
 
        panel_type = get_panel_type(i915);
 
-       i915->vbt.panel_type = panel_type;
+       panel->vbt.panel_type = panel_type;
 
        drrs_mode = (lvds_options->dps_panel_type_bits
                                >> (panel_type * 2)) & MODE_MASK;
         */
        switch (drrs_mode) {
        case 0:
-               i915->vbt.drrs_type = DRRS_TYPE_STATIC;
+               panel->vbt.drrs_type = DRRS_TYPE_STATIC;
                drm_dbg_kms(&i915->drm, "DRRS supported mode is static\n");
                break;
        case 2:
-               i915->vbt.drrs_type = DRRS_TYPE_SEAMLESS;
+               panel->vbt.drrs_type = DRRS_TYPE_SEAMLESS;
                drm_dbg_kms(&i915->drm,
                            "DRRS supported mode is seamless\n");
                break;
        default:
-               i915->vbt.drrs_type = DRRS_TYPE_NONE;
+               panel->vbt.drrs_type = DRRS_TYPE_NONE;
                drm_dbg_kms(&i915->drm,
                            "DRRS not supported (VBT input)\n");
                break;
 
 static void
 parse_lfp_panel_dtd(struct drm_i915_private *i915,
+                   struct intel_panel *panel,
                    const struct bdb_lvds_lfp_data *lvds_lfp_data,
                    const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs)
 {
        const struct lvds_dvo_timing *panel_dvo_timing;
        const struct lvds_fp_timing *fp_timing;
        struct drm_display_mode *panel_fixed_mode;
-       int panel_type = i915->vbt.panel_type;
+       int panel_type = panel->vbt.panel_type;
 
        panel_dvo_timing = get_lvds_dvo_timing(lvds_lfp_data,
                                               lvds_lfp_data_ptrs,
 
        fill_detail_timing_data(panel_fixed_mode, panel_dvo_timing);
 
-       i915->vbt.lfp_lvds_vbt_mode = panel_fixed_mode;
+       panel->vbt.lfp_lvds_vbt_mode = panel_fixed_mode;
 
        drm_dbg_kms(&i915->drm,
                    "Found panel mode in BIOS VBT legacy lfp table: " DRM_MODE_FMT "\n",
        /* check the resolution, just to be sure */
        if (fp_timing->x_res == panel_fixed_mode->hdisplay &&
            fp_timing->y_res == panel_fixed_mode->vdisplay) {
-               i915->vbt.bios_lvds_val = fp_timing->lvds_reg_val;
+               panel->vbt.bios_lvds_val = fp_timing->lvds_reg_val;
                drm_dbg_kms(&i915->drm,
                            "VBT initial LVDS value %x\n",
-                           i915->vbt.bios_lvds_val);
+                           panel->vbt.bios_lvds_val);
        }
 }
 
 static void
-parse_lfp_data(struct drm_i915_private *i915)
+parse_lfp_data(struct drm_i915_private *i915,
+              struct intel_panel *panel)
 {
        const struct bdb_lvds_lfp_data *data;
        const struct bdb_lvds_lfp_data_tail *tail;
        const struct bdb_lvds_lfp_data_ptrs *ptrs;
-       int panel_type = i915->vbt.panel_type;
+       int panel_type = panel->vbt.panel_type;
 
        ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
        if (!ptrs)
        if (!data)
                return;
 
-       if (!i915->vbt.lfp_lvds_vbt_mode)
-               parse_lfp_panel_dtd(i915, data, ptrs);
+       if (!panel->vbt.lfp_lvds_vbt_mode)
+               parse_lfp_panel_dtd(i915, panel, data, ptrs);
 
        tail = get_lfp_data_tail(data, ptrs);
        if (!tail)
                return;
 
        if (i915->vbt.version >= 188) {
-               i915->vbt.seamless_drrs_min_refresh_rate =
+               panel->vbt.seamless_drrs_min_refresh_rate =
                        tail->seamless_drrs_min_refresh_rate[panel_type];
                drm_dbg_kms(&i915->drm,
                            "Seamless DRRS min refresh rate: %d Hz\n",
-                           i915->vbt.seamless_drrs_min_refresh_rate);
+                           panel->vbt.seamless_drrs_min_refresh_rate);
        }
 }
 
 static void
-parse_generic_dtd(struct drm_i915_private *i915)
+parse_generic_dtd(struct drm_i915_private *i915,
+                 struct intel_panel *panel)
 {
        const struct bdb_generic_dtd *generic_dtd;
        const struct generic_dtd_entry *dtd;
 
        num_dtd = (get_blocksize(generic_dtd) -
                   sizeof(struct bdb_generic_dtd)) / generic_dtd->gdtd_size;
-       if (i915->vbt.panel_type >= num_dtd) {
+       if (panel->vbt.panel_type >= num_dtd) {
                drm_err(&i915->drm,
                        "Panel type %d not found in table of %d DTD's\n",
-                       i915->vbt.panel_type, num_dtd);
+                       panel->vbt.panel_type, num_dtd);
                return;
        }
 
-       dtd = &generic_dtd->dtd[i915->vbt.panel_type];
+       dtd = &generic_dtd->dtd[panel->vbt.panel_type];
 
        panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
        if (!panel_fixed_mode)
                    "Found panel mode in BIOS VBT generic dtd table: " DRM_MODE_FMT "\n",
                    DRM_MODE_ARG(panel_fixed_mode));
 
-       i915->vbt.lfp_lvds_vbt_mode = panel_fixed_mode;
+       panel->vbt.lfp_lvds_vbt_mode = panel_fixed_mode;
 }
 
 static void
-parse_lfp_backlight(struct drm_i915_private *i915)
+parse_lfp_backlight(struct drm_i915_private *i915,
+                   struct intel_panel *panel)
 {
        const struct bdb_lfp_backlight_data *backlight_data;
        const struct lfp_backlight_data_entry *entry;
-       int panel_type = i915->vbt.panel_type;
+       int panel_type = panel->vbt.panel_type;
        u16 level;
 
        backlight_data = find_section(i915, BDB_LVDS_BACKLIGHT);
 
        entry = &backlight_data->data[panel_type];
 
-       i915->vbt.backlight.present = entry->type == BDB_BACKLIGHT_TYPE_PWM;
-       if (!i915->vbt.backlight.present) {
+       panel->vbt.backlight.present = entry->type == BDB_BACKLIGHT_TYPE_PWM;
+       if (!panel->vbt.backlight.present) {
                drm_dbg_kms(&i915->drm,
                            "PWM backlight not present in VBT (type %u)\n",
                            entry->type);
                return;
        }
 
-       i915->vbt.backlight.type = INTEL_BACKLIGHT_DISPLAY_DDI;
+       panel->vbt.backlight.type = INTEL_BACKLIGHT_DISPLAY_DDI;
        if (i915->vbt.version >= 191) {
                size_t exp_size;
 
                        const struct lfp_backlight_control_method *method;
 
                        method = &backlight_data->backlight_control[panel_type];
-                       i915->vbt.backlight.type = method->type;
-                       i915->vbt.backlight.controller = method->controller;
+                       panel->vbt.backlight.type = method->type;
+                       panel->vbt.backlight.controller = method->controller;
                }
        }
 
-       i915->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz;
-       i915->vbt.backlight.active_low_pwm = entry->active_low_pwm;
+       panel->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz;
+       panel->vbt.backlight.active_low_pwm = entry->active_low_pwm;
 
        if (i915->vbt.version >= 234) {
                u16 min_level;
                        drm_warn(&i915->drm, "Brightness min level > 255\n");
                        level = 255;
                }
-               i915->vbt.backlight.min_brightness = min_level;
+               panel->vbt.backlight.min_brightness = min_level;
 
-               i915->vbt.backlight.brightness_precision_bits =
+               panel->vbt.backlight.brightness_precision_bits =
                        backlight_data->brightness_precision_bits[panel_type];
        } else {
                level = backlight_data->level[panel_type];
-               i915->vbt.backlight.min_brightness = entry->min_brightness;
+               panel->vbt.backlight.min_brightness = entry->min_brightness;
        }
 
        drm_dbg_kms(&i915->drm,
                    "VBT backlight PWM modulation frequency %u Hz, "
                    "active %s, min brightness %u, level %u, controller %u\n",
-                   i915->vbt.backlight.pwm_freq_hz,
-                   i915->vbt.backlight.active_low_pwm ? "low" : "high",
-                   i915->vbt.backlight.min_brightness,
+                   panel->vbt.backlight.pwm_freq_hz,
+                   panel->vbt.backlight.active_low_pwm ? "low" : "high",
+                   panel->vbt.backlight.min_brightness,
                    level,
-                   i915->vbt.backlight.controller);
+                   panel->vbt.backlight.controller);
 }
 
 /* Try to find sdvo panel data */
 static void
-parse_sdvo_panel_data(struct drm_i915_private *i915)
+parse_sdvo_panel_data(struct drm_i915_private *i915,
+                     struct intel_panel *panel)
 {
        const struct bdb_sdvo_panel_dtds *dtds;
        struct drm_display_mode *panel_fixed_mode;
 
        fill_detail_timing_data(panel_fixed_mode, &dtds->dtds[index]);
 
-       i915->vbt.sdvo_lvds_vbt_mode = panel_fixed_mode;
+       panel->vbt.sdvo_lvds_vbt_mode = panel_fixed_mode;
 
        drm_dbg_kms(&i915->drm,
                    "Found SDVO panel mode in BIOS VBT tables: " DRM_MODE_FMT "\n",
 }
 
 static void
-parse_panel_driver_features(struct drm_i915_private *i915)
+parse_panel_driver_features(struct drm_i915_private *i915,
+                           struct intel_panel *panel)
 {
        const struct bdb_driver_features *driver;
 
                 * driver->drrs_enabled=false
                 */
                if (!driver->drrs_enabled)
-                       i915->vbt.drrs_type = DRRS_TYPE_NONE;
+                       panel->vbt.drrs_type = DRRS_TYPE_NONE;
 
-               i915->vbt.psr.enable = driver->psr_enabled;
+               panel->vbt.psr.enable = driver->psr_enabled;
        }
 }
 
 static void
-parse_power_conservation_features(struct drm_i915_private *i915)
+parse_power_conservation_features(struct drm_i915_private *i915,
+                                 struct intel_panel *panel)
 {
        const struct bdb_lfp_power *power;
-       u8 panel_type = i915->vbt.panel_type;
+       u8 panel_type = panel->vbt.panel_type;
 
        if (i915->vbt.version < 228)
                return;
        if (!power)
                return;
 
-       i915->vbt.psr.enable = power->psr & BIT(panel_type);
+       panel->vbt.psr.enable = power->psr & BIT(panel_type);
 
        /*
         * If DRRS is not supported, drrs_type has to be set to 0.
         * power->drrs & BIT(panel_type)=false
         */
        if (!(power->drrs & BIT(panel_type)))
-               i915->vbt.drrs_type = DRRS_TYPE_NONE;
+               panel->vbt.drrs_type = DRRS_TYPE_NONE;
 
        if (i915->vbt.version >= 232)
-               i915->vbt.edp.hobl = power->hobl & BIT(panel_type);
+               panel->vbt.edp.hobl = power->hobl & BIT(panel_type);
 }
 
 static void
-parse_edp(struct drm_i915_private *i915)
+parse_edp(struct drm_i915_private *i915,
+         struct intel_panel *panel)
 {
        const struct bdb_edp *edp;
        const struct edp_power_seq *edp_pps;
        const struct edp_fast_link_params *edp_link_params;
-       int panel_type = i915->vbt.panel_type;
+       int panel_type = panel->vbt.panel_type;
 
        edp = find_section(i915, BDB_EDP);
        if (!edp)
 
        switch ((edp->color_depth >> (panel_type * 2)) & 3) {
        case EDP_18BPP:
-               i915->vbt.edp.bpp = 18;
+               panel->vbt.edp.bpp = 18;
                break;
        case EDP_24BPP:
-               i915->vbt.edp.bpp = 24;
+               panel->vbt.edp.bpp = 24;
                break;
        case EDP_30BPP:
-               i915->vbt.edp.bpp = 30;
+               panel->vbt.edp.bpp = 30;
                break;
        }
 
        edp_pps = &edp->power_seqs[panel_type];
        edp_link_params = &edp->fast_link_params[panel_type];
 
-       i915->vbt.edp.pps = *edp_pps;
+       panel->vbt.edp.pps = *edp_pps;
 
        switch (edp_link_params->rate) {
        case EDP_RATE_1_62:
-               i915->vbt.edp.rate = DP_LINK_BW_1_62;
+               panel->vbt.edp.rate = DP_LINK_BW_1_62;
                break;
        case EDP_RATE_2_7:
-               i915->vbt.edp.rate = DP_LINK_BW_2_7;
+               panel->vbt.edp.rate = DP_LINK_BW_2_7;
                break;
        default:
                drm_dbg_kms(&i915->drm,
 
        switch (edp_link_params->lanes) {
        case EDP_LANE_1:
-               i915->vbt.edp.lanes = 1;
+               panel->vbt.edp.lanes = 1;
                break;
        case EDP_LANE_2:
-               i915->vbt.edp.lanes = 2;
+               panel->vbt.edp.lanes = 2;
                break;
        case EDP_LANE_4:
-               i915->vbt.edp.lanes = 4;
+               panel->vbt.edp.lanes = 4;
                break;
        default:
                drm_dbg_kms(&i915->drm,
 
        switch (edp_link_params->preemphasis) {
        case EDP_PREEMPHASIS_NONE:
-               i915->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_0;
+               panel->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_0;
                break;
        case EDP_PREEMPHASIS_3_5dB:
-               i915->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_1;
+               panel->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_1;
                break;
        case EDP_PREEMPHASIS_6dB:
-               i915->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_2;
+               panel->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_2;
                break;
        case EDP_PREEMPHASIS_9_5dB:
-               i915->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_3;
+               panel->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_3;
                break;
        default:
                drm_dbg_kms(&i915->drm,
 
        switch (edp_link_params->vswing) {
        case EDP_VSWING_0_4V:
-               i915->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_0;
+               panel->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_0;
                break;
        case EDP_VSWING_0_6V:
-               i915->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_1;
+               panel->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_1;
                break;
        case EDP_VSWING_0_8V:
-               i915->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
+               panel->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
                break;
        case EDP_VSWING_1_2V:
-               i915->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
+               panel->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
                break;
        default:
                drm_dbg_kms(&i915->drm,
 
                /* Don't read from VBT if module parameter has valid value*/
                if (i915->params.edp_vswing) {
-                       i915->vbt.edp.low_vswing =
+                       panel->vbt.edp.low_vswing =
                                i915->params.edp_vswing == 1;
                } else {
                        vswing = (edp->edp_vswing_preemph >> (panel_type * 4)) & 0xF;
-                       i915->vbt.edp.low_vswing = vswing == 0;
+                       panel->vbt.edp.low_vswing = vswing == 0;
                }
        }
 
-       i915->vbt.edp.drrs_msa_timing_delay =
+       panel->vbt.edp.drrs_msa_timing_delay =
                (edp->sdrrs_msa_timing_delay >> (panel_type * 2)) & 3;
 }
 
 static void
-parse_psr(struct drm_i915_private *i915)
+parse_psr(struct drm_i915_private *i915,
+         struct intel_panel *panel)
 {
        const struct bdb_psr *psr;
        const struct psr_table *psr_table;
-       int panel_type = i915->vbt.panel_type;
+       int panel_type = panel->vbt.panel_type;
 
        psr = find_section(i915, BDB_PSR);
        if (!psr) {
 
        psr_table = &psr->psr_table[panel_type];
 
-       i915->vbt.psr.full_link = psr_table->full_link;
-       i915->vbt.psr.require_aux_wakeup = psr_table->require_aux_to_wakeup;
+       panel->vbt.psr.full_link = psr_table->full_link;
+       panel->vbt.psr.require_aux_wakeup = psr_table->require_aux_to_wakeup;
 
        /* Allowed VBT values goes from 0 to 15 */
-       i915->vbt.psr.idle_frames = psr_table->idle_frames < 0 ? 0 :
+       panel->vbt.psr.idle_frames = psr_table->idle_frames < 0 ? 0 :
                psr_table->idle_frames > 15 ? 15 : psr_table->idle_frames;
 
        /*
            (DISPLAY_VER(i915) >= 9 && !IS_BROXTON(i915))) {
                switch (psr_table->tp1_wakeup_time) {
                case 0:
-                       i915->vbt.psr.tp1_wakeup_time_us = 500;
+                       panel->vbt.psr.tp1_wakeup_time_us = 500;
                        break;
                case 1:
-                       i915->vbt.psr.tp1_wakeup_time_us = 100;
+                       panel->vbt.psr.tp1_wakeup_time_us = 100;
                        break;
                case 3:
-                       i915->vbt.psr.tp1_wakeup_time_us = 0;
+                       panel->vbt.psr.tp1_wakeup_time_us = 0;
                        break;
                default:
                        drm_dbg_kms(&i915->drm,
                                    psr_table->tp1_wakeup_time);
                        fallthrough;
                case 2:
-                       i915->vbt.psr.tp1_wakeup_time_us = 2500;
+                       panel->vbt.psr.tp1_wakeup_time_us = 2500;
                        break;
                }
 
                switch (psr_table->tp2_tp3_wakeup_time) {
                case 0:
-                       i915->vbt.psr.tp2_tp3_wakeup_time_us = 500;
+                       panel->vbt.psr.tp2_tp3_wakeup_time_us = 500;
                        break;
                case 1:
-                       i915->vbt.psr.tp2_tp3_wakeup_time_us = 100;
+                       panel->vbt.psr.tp2_tp3_wakeup_time_us = 100;
                        break;
                case 3:
-                       i915->vbt.psr.tp2_tp3_wakeup_time_us = 0;
+                       panel->vbt.psr.tp2_tp3_wakeup_time_us = 0;
                        break;
                default:
                        drm_dbg_kms(&i915->drm,
                                    psr_table->tp2_tp3_wakeup_time);
                        fallthrough;
                case 2:
-                       i915->vbt.psr.tp2_tp3_wakeup_time_us = 2500;
+                       panel->vbt.psr.tp2_tp3_wakeup_time_us = 2500;
                break;
                }
        } else {
-               i915->vbt.psr.tp1_wakeup_time_us = psr_table->tp1_wakeup_time * 100;
-               i915->vbt.psr.tp2_tp3_wakeup_time_us = psr_table->tp2_tp3_wakeup_time * 100;
+               panel->vbt.psr.tp1_wakeup_time_us = psr_table->tp1_wakeup_time * 100;
+               panel->vbt.psr.tp2_tp3_wakeup_time_us = psr_table->tp2_tp3_wakeup_time * 100;
        }
 
        if (i915->vbt.version >= 226) {
                        wakeup_time = 2500;
                        break;
                }
-               i915->vbt.psr.psr2_tp2_tp3_wakeup_time_us = wakeup_time;
+               panel->vbt.psr.psr2_tp2_tp3_wakeup_time_us = wakeup_time;
        } else {
                /* Reusing PSR1 wakeup time for PSR2 in older VBTs */
-               i915->vbt.psr.psr2_tp2_tp3_wakeup_time_us = i915->vbt.psr.tp2_tp3_wakeup_time_us;
+               panel->vbt.psr.psr2_tp2_tp3_wakeup_time_us = panel->vbt.psr.tp2_tp3_wakeup_time_us;
        }
 }
 
 static void parse_dsi_backlight_ports(struct drm_i915_private *i915,
-                                     u16 version, enum port port)
+                                     struct intel_panel *panel,
+                                     enum port port)
 {
-       if (!i915->vbt.dsi.config->dual_link || version < 197) {
-               i915->vbt.dsi.bl_ports = BIT(port);
-               if (i915->vbt.dsi.config->cabc_supported)
-                       i915->vbt.dsi.cabc_ports = BIT(port);
+       if (!panel->vbt.dsi.config->dual_link || i915->vbt.version < 197) {
+               panel->vbt.dsi.bl_ports = BIT(port);
+               if (panel->vbt.dsi.config->cabc_supported)
+                       panel->vbt.dsi.cabc_ports = BIT(port);
 
                return;
        }
 
-       switch (i915->vbt.dsi.config->dl_dcs_backlight_ports) {
+       switch (panel->vbt.dsi.config->dl_dcs_backlight_ports) {
        case DL_DCS_PORT_A:
-               i915->vbt.dsi.bl_ports = BIT(PORT_A);
+               panel->vbt.dsi.bl_ports = BIT(PORT_A);
                break;
        case DL_DCS_PORT_C:
-               i915->vbt.dsi.bl_ports = BIT(PORT_C);
+               panel->vbt.dsi.bl_ports = BIT(PORT_C);
                break;
        default:
        case DL_DCS_PORT_A_AND_C:
-               i915->vbt.dsi.bl_ports = BIT(PORT_A) | BIT(PORT_C);
+               panel->vbt.dsi.bl_ports = BIT(PORT_A) | BIT(PORT_C);
                break;
        }
 
-       if (!i915->vbt.dsi.config->cabc_supported)
+       if (!panel->vbt.dsi.config->cabc_supported)
                return;
 
-       switch (i915->vbt.dsi.config->dl_dcs_cabc_ports) {
+       switch (panel->vbt.dsi.config->dl_dcs_cabc_ports) {
        case DL_DCS_PORT_A:
-               i915->vbt.dsi.cabc_ports = BIT(PORT_A);
+               panel->vbt.dsi.cabc_ports = BIT(PORT_A);
                break;
        case DL_DCS_PORT_C:
-               i915->vbt.dsi.cabc_ports = BIT(PORT_C);
+               panel->vbt.dsi.cabc_ports = BIT(PORT_C);
                break;
        default:
        case DL_DCS_PORT_A_AND_C:
-               i915->vbt.dsi.cabc_ports =
+               panel->vbt.dsi.cabc_ports =
                                        BIT(PORT_A) | BIT(PORT_C);
                break;
        }
 }
 
 static void
-parse_mipi_config(struct drm_i915_private *i915)
+parse_mipi_config(struct drm_i915_private *i915,
+                 struct intel_panel *panel)
 {
        const struct bdb_mipi_config *start;
        const struct mipi_config *config;
        const struct mipi_pps_data *pps;
-       int panel_type = i915->vbt.panel_type;
+       int panel_type = panel->vbt.panel_type;
        enum port port;
 
        /* parse MIPI blocks only if LFP type is MIPI */
                return;
 
        /* Initialize this to undefined indicating no generic MIPI support */
-       i915->vbt.dsi.panel_id = MIPI_DSI_UNDEFINED_PANEL_ID;
+       panel->vbt.dsi.panel_id = MIPI_DSI_UNDEFINED_PANEL_ID;
 
        /* Block #40 is already parsed and panel_fixed_mode is
         * stored in i915->lfp_lvds_vbt_mode
        pps = &start->pps[panel_type];
 
        /* store as of now full data. Trim when we realise all is not needed */
-       i915->vbt.dsi.config = kmemdup(config, sizeof(struct mipi_config), GFP_KERNEL);
-       if (!i915->vbt.dsi.config)
+       panel->vbt.dsi.config = kmemdup(config, sizeof(struct mipi_config), GFP_KERNEL);
+       if (!panel->vbt.dsi.config)
                return;
 
-       i915->vbt.dsi.pps = kmemdup(pps, sizeof(struct mipi_pps_data), GFP_KERNEL);
-       if (!i915->vbt.dsi.pps) {
-               kfree(i915->vbt.dsi.config);
+       panel->vbt.dsi.pps = kmemdup(pps, sizeof(struct mipi_pps_data), GFP_KERNEL);
+       if (!panel->vbt.dsi.pps) {
+               kfree(panel->vbt.dsi.config);
                return;
        }
 
-       parse_dsi_backlight_ports(i915, i915->vbt.version, port);
+       parse_dsi_backlight_ports(i915, panel, port);
 
        /* FIXME is the 90 vs. 270 correct? */
        switch (config->rotation) {
                 * Most (all?) VBTs claim 0 degrees despite having
                 * an upside down panel, thus we do not trust this.
                 */
-               i915->vbt.dsi.orientation =
+               panel->vbt.dsi.orientation =
                        DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
                break;
        case ENABLE_ROTATION_90:
-               i915->vbt.dsi.orientation =
+               panel->vbt.dsi.orientation =
                        DRM_MODE_PANEL_ORIENTATION_RIGHT_UP;
                break;
        case ENABLE_ROTATION_180:
-               i915->vbt.dsi.orientation =
+               panel->vbt.dsi.orientation =
                        DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP;
                break;
        case ENABLE_ROTATION_270:
-               i915->vbt.dsi.orientation =
+               panel->vbt.dsi.orientation =
                        DRM_MODE_PANEL_ORIENTATION_LEFT_UP;
                break;
        }
 
        /* We have mandatory mipi config blocks. Initialize as generic panel */
-       i915->vbt.dsi.panel_id = MIPI_DSI_GENERIC_PANEL_ID;
+       panel->vbt.dsi.panel_id = MIPI_DSI_GENERIC_PANEL_ID;
 }
 
 /* Find the sequence block and size for the given panel. */
  * Get len of pre-fixed deassert fragment from a v1 init OTP sequence,
  * skip all delay + gpio operands and stop at the first DSI packet op.
  */
-static int get_init_otp_deassert_fragment_len(struct drm_i915_private *i915)
+static int get_init_otp_deassert_fragment_len(struct drm_i915_private *i915,
+                                             struct intel_panel *panel)
 {
-       const u8 *data = i915->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP];
+       const u8 *data = panel->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP];
        int index, len;
 
        if (drm_WARN_ON(&i915->drm,
-                       !data || i915->vbt.dsi.seq_version != 1))
+                       !data || panel->vbt.dsi.seq_version != 1))
                return 0;
 
        /* index = 1 to skip sequence byte */
  * these devices we split the init OTP sequence into a deassert sequence and
  * the actual init OTP part.
  */
-static void fixup_mipi_sequences(struct drm_i915_private *i915)
+static void fixup_mipi_sequences(struct drm_i915_private *i915,
+                                struct intel_panel *panel)
 {
        u8 *init_otp;
        int len;
                return;
 
        /* Limit this to v1 vid-mode sequences */
-       if (i915->vbt.dsi.config->is_cmd_mode ||
-           i915->vbt.dsi.seq_version != 1)
+       if (panel->vbt.dsi.config->is_cmd_mode ||
+           panel->vbt.dsi.seq_version != 1)
                return;
 
        /* Only do this if there are otp and assert seqs and no deassert seq */
-       if (!i915->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP] ||
-           !i915->vbt.dsi.sequence[MIPI_SEQ_ASSERT_RESET] ||
-           i915->vbt.dsi.sequence[MIPI_SEQ_DEASSERT_RESET])
+       if (!panel->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP] ||
+           !panel->vbt.dsi.sequence[MIPI_SEQ_ASSERT_RESET] ||
+           panel->vbt.dsi.sequence[MIPI_SEQ_DEASSERT_RESET])
                return;
 
        /* The deassert-sequence ends at the first DSI packet */
-       len = get_init_otp_deassert_fragment_len(i915);
+       len = get_init_otp_deassert_fragment_len(i915, panel);
        if (!len)
                return;
 
                    "Using init OTP fragment to deassert reset\n");
 
        /* Copy the fragment, update seq byte and terminate it */
-       init_otp = (u8 *)i915->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP];
-       i915->vbt.dsi.deassert_seq = kmemdup(init_otp, len + 1, GFP_KERNEL);
-       if (!i915->vbt.dsi.deassert_seq)
+       init_otp = (u8 *)panel->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP];
+       panel->vbt.dsi.deassert_seq = kmemdup(init_otp, len + 1, GFP_KERNEL);
+       if (!panel->vbt.dsi.deassert_seq)
                return;
-       i915->vbt.dsi.deassert_seq[0] = MIPI_SEQ_DEASSERT_RESET;
-       i915->vbt.dsi.deassert_seq[len] = MIPI_SEQ_ELEM_END;
+       panel->vbt.dsi.deassert_seq[0] = MIPI_SEQ_DEASSERT_RESET;
+       panel->vbt.dsi.deassert_seq[len] = MIPI_SEQ_ELEM_END;
        /* Use the copy for deassert */
-       i915->vbt.dsi.sequence[MIPI_SEQ_DEASSERT_RESET] =
-               i915->vbt.dsi.deassert_seq;
+       panel->vbt.dsi.sequence[MIPI_SEQ_DEASSERT_RESET] =
+               panel->vbt.dsi.deassert_seq;
        /* Replace the last byte of the fragment with init OTP seq byte */
        init_otp[len - 1] = MIPI_SEQ_INIT_OTP;
        /* And make MIPI_MIPI_SEQ_INIT_OTP point to it */
-       i915->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP] = init_otp + len - 1;
+       panel->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP] = init_otp + len - 1;
 }
 
 static void
-parse_mipi_sequence(struct drm_i915_private *i915)
+parse_mipi_sequence(struct drm_i915_private *i915,
+                   struct intel_panel *panel)
 {
-       int panel_type = i915->vbt.panel_type;
+       int panel_type = panel->vbt.panel_type;
        const struct bdb_mipi_sequence *sequence;
        const u8 *seq_data;
        u32 seq_size;
        int index = 0;
 
        /* Only our generic panel driver uses the sequence block. */
-       if (i915->vbt.dsi.panel_id != MIPI_DSI_GENERIC_PANEL_ID)
+       if (panel->vbt.dsi.panel_id != MIPI_DSI_GENERIC_PANEL_ID)
                return;
 
        sequence = find_section(i915, BDB_MIPI_SEQUENCE);
                        drm_dbg_kms(&i915->drm,
                                    "Unsupported sequence %u\n", seq_id);
 
-               i915->vbt.dsi.sequence[seq_id] = data + index;
+               panel->vbt.dsi.sequence[seq_id] = data + index;
 
                if (sequence->version >= 3)
                        index = goto_next_sequence_v3(data, index, seq_size);
                }
        }
 
-       i915->vbt.dsi.data = data;
-       i915->vbt.dsi.size = seq_size;
-       i915->vbt.dsi.seq_version = sequence->version;
+       panel->vbt.dsi.data = data;
+       panel->vbt.dsi.size = seq_size;
+       panel->vbt.dsi.seq_version = sequence->version;
 
-       fixup_mipi_sequences(i915);
+       fixup_mipi_sequences(i915, panel);
 
        drm_dbg(&i915->drm, "MIPI related VBT parsing complete\n");
        return;
 
 err:
        kfree(data);
-       memset(i915->vbt.dsi.sequence, 0, sizeof(i915->vbt.dsi.sequence));
+       memset(panel->vbt.dsi.sequence, 0, sizeof(panel->vbt.dsi.sequence));
 }
 
 static void
 {
        i915->vbt.crt_ddc_pin = GMBUS_PIN_VGADDC;
 
-       /* Default to having backlight */
-       i915->vbt.backlight.present = true;
-
-       /* LFP panel data */
-       i915->vbt.lvds_dither = 1;
-
-       /* SDVO panel data */
-       i915->vbt.sdvo_lvds_vbt_mode = NULL;
-
        /* general features */
        i915->vbt.int_tv_support = 1;
        i915->vbt.int_crt_support = 1;
                    i915->vbt.lvds_ssc_freq);
 }
 
+/* Common defaults which may be overridden by VBT. */
+static void
+init_vbt_panel_defaults(struct intel_panel *panel)
+{
+       /* Default to having backlight */
+       panel->vbt.backlight.present = true;
+
+       /* LFP panel data */
+       panel->vbt.lvds_dither = true;
+}
+
 /* Defaults to initialize only if there is no VBT. */
 static void
 init_vbt_missing_defaults(struct drm_i915_private *i915)
        kfree(oprom_vbt);
 }
 
-void intel_bios_init_panel(struct drm_i915_private *i915)
+void intel_bios_init_panel(struct drm_i915_private *i915,
+                          struct intel_panel *panel)
 {
-       parse_panel_options(i915);
-       parse_generic_dtd(i915);
-       parse_lfp_data(i915);
-       parse_lfp_backlight(i915);
-       parse_sdvo_panel_data(i915);
-       parse_panel_driver_features(i915);
-       parse_power_conservation_features(i915);
-       parse_edp(i915);
-       parse_psr(i915);
-       parse_mipi_config(i915);
-       parse_mipi_sequence(i915);
+       init_vbt_panel_defaults(panel);
+
+       parse_panel_options(i915, panel);
+       parse_generic_dtd(i915, panel);
+       parse_lfp_data(i915, panel);
+       parse_lfp_backlight(i915, panel);
+       parse_sdvo_panel_data(i915, panel);
+       parse_panel_driver_features(i915, panel);
+       parse_power_conservation_features(i915, panel);
+       parse_edp(i915, panel);
+       parse_psr(i915, panel);
+       parse_mipi_config(i915, panel);
+       parse_mipi_sequence(i915, panel);
 }
 
 /**
                list_del(&entry->node);
                kfree(entry);
        }
+}
 
-       kfree(i915->vbt.sdvo_lvds_vbt_mode);
-       i915->vbt.sdvo_lvds_vbt_mode = NULL;
-       kfree(i915->vbt.lfp_lvds_vbt_mode);
-       i915->vbt.lfp_lvds_vbt_mode = NULL;
-       kfree(i915->vbt.dsi.data);
-       i915->vbt.dsi.data = NULL;
-       kfree(i915->vbt.dsi.pps);
-       i915->vbt.dsi.pps = NULL;
-       kfree(i915->vbt.dsi.config);
-       i915->vbt.dsi.config = NULL;
-       kfree(i915->vbt.dsi.deassert_seq);
-       i915->vbt.dsi.deassert_seq = NULL;
+void intel_bios_fini_panel(struct intel_panel *panel)
+{
+       kfree(panel->vbt.sdvo_lvds_vbt_mode);
+       panel->vbt.sdvo_lvds_vbt_mode = NULL;
+       kfree(panel->vbt.lfp_lvds_vbt_mode);
+       panel->vbt.lfp_lvds_vbt_mode = NULL;
+       kfree(panel->vbt.dsi.data);
+       panel->vbt.dsi.data = NULL;
+       kfree(panel->vbt.dsi.pps);
+       panel->vbt.dsi.pps = NULL;
+       kfree(panel->vbt.dsi.config);
+       panel->vbt.dsi.config = NULL;
+       kfree(panel->vbt.dsi.deassert_seq);
+       panel->vbt.dsi.deassert_seq = NULL;
 }
 
 /**
 
        return data;
 }
 
-static void vlv_exec_gpio(struct drm_i915_private *dev_priv,
+static void vlv_exec_gpio(struct intel_connector *connector,
                          u8 gpio_source, u8 gpio_index, bool value)
 {
+       struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
        struct gpio_map *map;
        u16 pconf0, padval;
        u32 tmp;
 
        map = &vlv_gpio_table[gpio_index];
 
-       if (dev_priv->vbt.dsi.seq_version >= 3) {
+       if (connector->panel.vbt.dsi.seq_version >= 3) {
                /* XXX: this assumes vlv_gpio_table only has NC GPIOs. */
                port = IOSF_PORT_GPIO_NC;
        } else {
        vlv_iosf_sb_put(dev_priv, BIT(VLV_IOSF_SB_GPIO));
 }
 
-static void chv_exec_gpio(struct drm_i915_private *dev_priv,
+static void chv_exec_gpio(struct intel_connector *connector,
                          u8 gpio_source, u8 gpio_index, bool value)
 {
+       struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
        u16 cfg0, cfg1;
        u16 family_num;
        u8 port;
 
-       if (dev_priv->vbt.dsi.seq_version >= 3) {
+       if (connector->panel.vbt.dsi.seq_version >= 3) {
                if (gpio_index >= CHV_GPIO_IDX_START_SE) {
                        /* XXX: it's unclear whether 255->57 is part of SE. */
                        gpio_index -= CHV_GPIO_IDX_START_SE;
        vlv_iosf_sb_put(dev_priv, BIT(VLV_IOSF_SB_GPIO));
 }
 
-static void bxt_exec_gpio(struct drm_i915_private *dev_priv,
+static void bxt_exec_gpio(struct intel_connector *connector,
                          u8 gpio_source, u8 gpio_index, bool value)
 {
+       struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
        /* XXX: this table is a quick ugly hack. */
        static struct gpio_desc *bxt_gpio_table[U8_MAX + 1];
        struct gpio_desc *gpio_desc = bxt_gpio_table[gpio_index];
        gpiod_set_value(gpio_desc, value);
 }
 
-static void icl_exec_gpio(struct drm_i915_private *dev_priv,
+static void icl_exec_gpio(struct intel_connector *connector,
                          u8 gpio_source, u8 gpio_index, bool value)
 {
+       struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+
        drm_dbg_kms(&dev_priv->drm, "Skipping ICL GPIO element execution\n");
 }
 
 {
        struct drm_device *dev = intel_dsi->base.base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
+       struct intel_connector *connector = intel_dsi->attached_connector;
        u8 gpio_source, gpio_index = 0, gpio_number;
        bool value;
 
        drm_dbg_kms(&dev_priv->drm, "\n");
 
-       if (dev_priv->vbt.dsi.seq_version >= 3)
+       if (connector->panel.vbt.dsi.seq_version >= 3)
                gpio_index = *data++;
 
        gpio_number = *data++;
 
        /* gpio source in sequence v2 only */
-       if (dev_priv->vbt.dsi.seq_version == 2)
+       if (connector->panel.vbt.dsi.seq_version == 2)
                gpio_source = (*data >> 1) & 3;
        else
                gpio_source = 0;
        value = *data++ & 1;
 
        if (DISPLAY_VER(dev_priv) >= 11)
-               icl_exec_gpio(dev_priv, gpio_source, gpio_index, value);
+               icl_exec_gpio(connector, gpio_source, gpio_index, value);
        else if (IS_VALLEYVIEW(dev_priv))
-               vlv_exec_gpio(dev_priv, gpio_source, gpio_number, value);
+               vlv_exec_gpio(connector, gpio_source, gpio_number, value);
        else if (IS_CHERRYVIEW(dev_priv))
-               chv_exec_gpio(dev_priv, gpio_source, gpio_number, value);
+               chv_exec_gpio(connector, gpio_source, gpio_number, value);
        else
-               bxt_exec_gpio(dev_priv, gpio_source, gpio_index, value);
+               bxt_exec_gpio(connector, gpio_source, gpio_index, value);
 
        return data;
 }
                               enum mipi_seq seq_id)
 {
        struct drm_i915_private *dev_priv = to_i915(intel_dsi->base.base.dev);
+       struct intel_connector *connector = intel_dsi->attached_connector;
        const u8 *data;
        fn_mipi_elem_exec mipi_elem_exec;
 
        if (drm_WARN_ON(&dev_priv->drm,
-                       seq_id >= ARRAY_SIZE(dev_priv->vbt.dsi.sequence)))
+                       seq_id >= ARRAY_SIZE(connector->panel.vbt.dsi.sequence)))
                return;
 
-       data = dev_priv->vbt.dsi.sequence[seq_id];
+       data = connector->panel.vbt.dsi.sequence[seq_id];
        if (!data)
                return;
 
        data++;
 
        /* Skip Size of Sequence. */
-       if (dev_priv->vbt.dsi.seq_version >= 3)
+       if (connector->panel.vbt.dsi.seq_version >= 3)
                data += 4;
 
        while (1) {
                        mipi_elem_exec = NULL;
 
                /* Size of Operation. */
-               if (dev_priv->vbt.dsi.seq_version >= 3)
+               if (connector->panel.vbt.dsi.seq_version >= 3)
                        operation_size = *data++;
 
                if (mipi_elem_exec) {
 
 void intel_dsi_msleep(struct intel_dsi *intel_dsi, int msec)
 {
-       struct drm_i915_private *dev_priv = to_i915(intel_dsi->base.base.dev);
+       struct intel_connector *connector = intel_dsi->attached_connector;
 
        /* For v3 VBTs in vid-mode the delays are part of the VBT sequences */
-       if (is_vid_mode(intel_dsi) && dev_priv->vbt.dsi.seq_version >= 3)
+       if (is_vid_mode(intel_dsi) && connector->panel.vbt.dsi.seq_version >= 3)
                return;
 
        msleep(msec);
 {
        struct drm_device *dev = intel_dsi->base.base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
-       struct mipi_config *mipi_config = dev_priv->vbt.dsi.config;
-       struct mipi_pps_data *pps = dev_priv->vbt.dsi.pps;
-       struct drm_display_mode *mode = dev_priv->vbt.lfp_lvds_vbt_mode;
+       struct intel_connector *connector = intel_dsi->attached_connector;
+       struct mipi_config *mipi_config = connector->panel.vbt.dsi.config;
+       struct mipi_pps_data *pps = connector->panel.vbt.dsi.pps;
+       struct drm_display_mode *mode = connector->panel.vbt.lfp_lvds_vbt_mode;
        u16 burst_mode_ratio;
        enum port port;
 
 {
        struct drm_device *dev = intel_dsi->base.base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
-       struct mipi_config *mipi_config = dev_priv->vbt.dsi.config;
+       struct intel_connector *connector = intel_dsi->attached_connector;
+       struct mipi_config *mipi_config = connector->panel.vbt.dsi.config;
        enum gpiod_flags flags = panel_is_on ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW;
        bool want_backlight_gpio = false;
        bool want_panel_gpio = false;
 {
        struct drm_device *dev = intel_dsi->base.base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
-       struct mipi_config *mipi_config = dev_priv->vbt.dsi.config;
+       struct intel_connector *connector = intel_dsi->attached_connector;
+       struct mipi_config *mipi_config = connector->panel.vbt.dsi.config;
 
        if (intel_dsi->gpio_panel) {
                gpiod_put(intel_dsi->gpio_panel);