xref: /linux/drivers/gpu/drm/i915/display/intel_bios.c (revision 4ec5abe960ca08aca02897b67682a39321d0a432)
1df0566a6SJani Nikula /*
2df0566a6SJani Nikula  * Copyright © 2006 Intel Corporation
3df0566a6SJani Nikula  *
4df0566a6SJani Nikula  * Permission is hereby granted, free of charge, to any person obtaining a
5df0566a6SJani Nikula  * copy of this software and associated documentation files (the "Software"),
6df0566a6SJani Nikula  * to deal in the Software without restriction, including without limitation
7df0566a6SJani Nikula  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8df0566a6SJani Nikula  * and/or sell copies of the Software, and to permit persons to whom the
9df0566a6SJani Nikula  * Software is furnished to do so, subject to the following conditions:
10df0566a6SJani Nikula  *
11df0566a6SJani Nikula  * The above copyright notice and this permission notice (including the next
12df0566a6SJani Nikula  * paragraph) shall be included in all copies or substantial portions of the
13df0566a6SJani Nikula  * Software.
14df0566a6SJani Nikula  *
15df0566a6SJani Nikula  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16df0566a6SJani Nikula  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17df0566a6SJani Nikula  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18df0566a6SJani Nikula  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19df0566a6SJani Nikula  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20df0566a6SJani Nikula  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21df0566a6SJani Nikula  * SOFTWARE.
22df0566a6SJani Nikula  *
23df0566a6SJani Nikula  * Authors:
24df0566a6SJani Nikula  *    Eric Anholt <eric@anholt.net>
25df0566a6SJani Nikula  *
26df0566a6SJani Nikula  */
27df0566a6SJani Nikula 
28df0566a6SJani Nikula #include <drm/drm_dp_helper.h>
29df0566a6SJani Nikula #include <drm/i915_drm.h>
30df0566a6SJani Nikula 
31d8fe2ab6SMatt Roper #include "display/intel_display.h"
321bf2f3bfSJani Nikula #include "display/intel_display_types.h"
33df0566a6SJani Nikula #include "display/intel_gmbus.h"
34df0566a6SJani Nikula 
35df0566a6SJani Nikula #include "i915_drv.h"
36df0566a6SJani Nikula 
37df0566a6SJani Nikula #define _INTEL_BIOS_PRIVATE
38df0566a6SJani Nikula #include "intel_vbt_defs.h"
39df0566a6SJani Nikula 
40df0566a6SJani Nikula /**
41df0566a6SJani Nikula  * DOC: Video BIOS Table (VBT)
42df0566a6SJani Nikula  *
43df0566a6SJani Nikula  * The Video BIOS Table, or VBT, provides platform and board specific
44df0566a6SJani Nikula  * configuration information to the driver that is not discoverable or available
45df0566a6SJani Nikula  * through other means. The configuration is mostly related to display
46df0566a6SJani Nikula  * hardware. The VBT is available via the ACPI OpRegion or, on older systems, in
47df0566a6SJani Nikula  * the PCI ROM.
48df0566a6SJani Nikula  *
49df0566a6SJani Nikula  * The VBT consists of a VBT Header (defined as &struct vbt_header), a BDB
50df0566a6SJani Nikula  * Header (&struct bdb_header), and a number of BIOS Data Blocks (BDB) that
51df0566a6SJani Nikula  * contain the actual configuration information. The VBT Header, and thus the
52df0566a6SJani Nikula  * VBT, begins with "$VBT" signature. The VBT Header contains the offset of the
53df0566a6SJani Nikula  * BDB Header. The data blocks are concatenated after the BDB Header. The data
54df0566a6SJani Nikula  * blocks have a 1-byte Block ID, 2-byte Block Size, and Block Size bytes of
55df0566a6SJani Nikula  * data. (Block 53, the MIPI Sequence Block is an exception.)
56df0566a6SJani Nikula  *
57df0566a6SJani Nikula  * The driver parses the VBT during load. The relevant information is stored in
58df0566a6SJani Nikula  * driver private data for ease of use, and the actual VBT is not read after
59df0566a6SJani Nikula  * that.
60df0566a6SJani Nikula  */
61df0566a6SJani Nikula 
620d9ef19bSJani Nikula /* Wrapper for VBT child device config */
630d9ef19bSJani Nikula struct display_device_data {
640d9ef19bSJani Nikula 	struct child_device_config child;
656e0d46e9SJani Nikula 	struct dsc_compression_parameters_entry *dsc;
660d9ef19bSJani Nikula 	struct list_head node;
670d9ef19bSJani Nikula };
680d9ef19bSJani Nikula 
69df0566a6SJani Nikula #define	SLAVE_ADDR1	0x70
70df0566a6SJani Nikula #define	SLAVE_ADDR2	0x72
71df0566a6SJani Nikula 
72df0566a6SJani Nikula /* Get BDB block size given a pointer to Block ID. */
73df0566a6SJani Nikula static u32 _get_blocksize(const u8 *block_base)
74df0566a6SJani Nikula {
75df0566a6SJani Nikula 	/* The MIPI Sequence Block v3+ has a separate size field. */
76df0566a6SJani Nikula 	if (*block_base == BDB_MIPI_SEQUENCE && *(block_base + 3) >= 3)
77df0566a6SJani Nikula 		return *((const u32 *)(block_base + 4));
78df0566a6SJani Nikula 	else
79df0566a6SJani Nikula 		return *((const u16 *)(block_base + 1));
80df0566a6SJani Nikula }
81df0566a6SJani Nikula 
82df0566a6SJani Nikula /* Get BDB block size give a pointer to data after Block ID and Block Size. */
83df0566a6SJani Nikula static u32 get_blocksize(const void *block_data)
84df0566a6SJani Nikula {
85df0566a6SJani Nikula 	return _get_blocksize(block_data - 3);
86df0566a6SJani Nikula }
87df0566a6SJani Nikula 
88df0566a6SJani Nikula static const void *
89df0566a6SJani Nikula find_section(const void *_bdb, enum bdb_block_id section_id)
90df0566a6SJani Nikula {
91df0566a6SJani Nikula 	const struct bdb_header *bdb = _bdb;
92df0566a6SJani Nikula 	const u8 *base = _bdb;
93df0566a6SJani Nikula 	int index = 0;
94df0566a6SJani Nikula 	u32 total, current_size;
95df0566a6SJani Nikula 	enum bdb_block_id current_id;
96df0566a6SJani Nikula 
97df0566a6SJani Nikula 	/* skip to first section */
98df0566a6SJani Nikula 	index += bdb->header_size;
99df0566a6SJani Nikula 	total = bdb->bdb_size;
100df0566a6SJani Nikula 
101df0566a6SJani Nikula 	/* walk the sections looking for section_id */
102df0566a6SJani Nikula 	while (index + 3 < total) {
103df0566a6SJani Nikula 		current_id = *(base + index);
104df0566a6SJani Nikula 		current_size = _get_blocksize(base + index);
105df0566a6SJani Nikula 		index += 3;
106df0566a6SJani Nikula 
107df0566a6SJani Nikula 		if (index + current_size > total)
108df0566a6SJani Nikula 			return NULL;
109df0566a6SJani Nikula 
110df0566a6SJani Nikula 		if (current_id == section_id)
111df0566a6SJani Nikula 			return base + index;
112df0566a6SJani Nikula 
113df0566a6SJani Nikula 		index += current_size;
114df0566a6SJani Nikula 	}
115df0566a6SJani Nikula 
116df0566a6SJani Nikula 	return NULL;
117df0566a6SJani Nikula }
118df0566a6SJani Nikula 
119df0566a6SJani Nikula static void
120df0566a6SJani Nikula fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
121df0566a6SJani Nikula 			const struct lvds_dvo_timing *dvo_timing)
122df0566a6SJani Nikula {
123df0566a6SJani Nikula 	panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) |
124df0566a6SJani Nikula 		dvo_timing->hactive_lo;
125df0566a6SJani Nikula 	panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay +
126df0566a6SJani Nikula 		((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo);
127df0566a6SJani Nikula 	panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start +
128df0566a6SJani Nikula 		((dvo_timing->hsync_pulse_width_hi << 8) |
129df0566a6SJani Nikula 			dvo_timing->hsync_pulse_width_lo);
130df0566a6SJani Nikula 	panel_fixed_mode->htotal = panel_fixed_mode->hdisplay +
131df0566a6SJani Nikula 		((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo);
132df0566a6SJani Nikula 
133df0566a6SJani Nikula 	panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) |
134df0566a6SJani Nikula 		dvo_timing->vactive_lo;
135df0566a6SJani Nikula 	panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay +
136df0566a6SJani Nikula 		((dvo_timing->vsync_off_hi << 4) | dvo_timing->vsync_off_lo);
137df0566a6SJani Nikula 	panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start +
138df0566a6SJani Nikula 		((dvo_timing->vsync_pulse_width_hi << 4) |
139df0566a6SJani Nikula 			dvo_timing->vsync_pulse_width_lo);
140df0566a6SJani Nikula 	panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay +
141df0566a6SJani Nikula 		((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo);
142df0566a6SJani Nikula 	panel_fixed_mode->clock = dvo_timing->clock * 10;
143df0566a6SJani Nikula 	panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED;
144df0566a6SJani Nikula 
145df0566a6SJani Nikula 	if (dvo_timing->hsync_positive)
146df0566a6SJani Nikula 		panel_fixed_mode->flags |= DRM_MODE_FLAG_PHSYNC;
147df0566a6SJani Nikula 	else
148df0566a6SJani Nikula 		panel_fixed_mode->flags |= DRM_MODE_FLAG_NHSYNC;
149df0566a6SJani Nikula 
150df0566a6SJani Nikula 	if (dvo_timing->vsync_positive)
151df0566a6SJani Nikula 		panel_fixed_mode->flags |= DRM_MODE_FLAG_PVSYNC;
152df0566a6SJani Nikula 	else
153df0566a6SJani Nikula 		panel_fixed_mode->flags |= DRM_MODE_FLAG_NVSYNC;
154df0566a6SJani Nikula 
155df0566a6SJani Nikula 	panel_fixed_mode->width_mm = (dvo_timing->himage_hi << 8) |
156df0566a6SJani Nikula 		dvo_timing->himage_lo;
157df0566a6SJani Nikula 	panel_fixed_mode->height_mm = (dvo_timing->vimage_hi << 8) |
158df0566a6SJani Nikula 		dvo_timing->vimage_lo;
159df0566a6SJani Nikula 
160df0566a6SJani Nikula 	/* Some VBTs have bogus h/vtotal values */
161df0566a6SJani Nikula 	if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
162df0566a6SJani Nikula 		panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
163df0566a6SJani Nikula 	if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal)
164df0566a6SJani Nikula 		panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1;
165df0566a6SJani Nikula 
166df0566a6SJani Nikula 	drm_mode_set_name(panel_fixed_mode);
167df0566a6SJani Nikula }
168df0566a6SJani Nikula 
169df0566a6SJani Nikula static const struct lvds_dvo_timing *
170df0566a6SJani Nikula get_lvds_dvo_timing(const struct bdb_lvds_lfp_data *lvds_lfp_data,
171df0566a6SJani Nikula 		    const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs,
172df0566a6SJani Nikula 		    int index)
173df0566a6SJani Nikula {
174df0566a6SJani Nikula 	/*
175df0566a6SJani Nikula 	 * the size of fp_timing varies on the different platform.
176df0566a6SJani Nikula 	 * So calculate the DVO timing relative offset in LVDS data
177df0566a6SJani Nikula 	 * entry to get the DVO timing entry
178df0566a6SJani Nikula 	 */
179df0566a6SJani Nikula 
180df0566a6SJani Nikula 	int lfp_data_size =
181df0566a6SJani Nikula 		lvds_lfp_data_ptrs->ptr[1].dvo_timing_offset -
182df0566a6SJani Nikula 		lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset;
183df0566a6SJani Nikula 	int dvo_timing_offset =
184df0566a6SJani Nikula 		lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset -
185df0566a6SJani Nikula 		lvds_lfp_data_ptrs->ptr[0].fp_timing_offset;
186df0566a6SJani Nikula 	char *entry = (char *)lvds_lfp_data->data + lfp_data_size * index;
187df0566a6SJani Nikula 
188df0566a6SJani Nikula 	return (struct lvds_dvo_timing *)(entry + dvo_timing_offset);
189df0566a6SJani Nikula }
190df0566a6SJani Nikula 
191df0566a6SJani Nikula /* get lvds_fp_timing entry
192df0566a6SJani Nikula  * this function may return NULL if the corresponding entry is invalid
193df0566a6SJani Nikula  */
194df0566a6SJani Nikula static const struct lvds_fp_timing *
195df0566a6SJani Nikula get_lvds_fp_timing(const struct bdb_header *bdb,
196df0566a6SJani Nikula 		   const struct bdb_lvds_lfp_data *data,
197df0566a6SJani Nikula 		   const struct bdb_lvds_lfp_data_ptrs *ptrs,
198df0566a6SJani Nikula 		   int index)
199df0566a6SJani Nikula {
200df0566a6SJani Nikula 	size_t data_ofs = (const u8 *)data - (const u8 *)bdb;
201df0566a6SJani Nikula 	u16 data_size = ((const u16 *)data)[-1]; /* stored in header */
202df0566a6SJani Nikula 	size_t ofs;
203df0566a6SJani Nikula 
204df0566a6SJani Nikula 	if (index >= ARRAY_SIZE(ptrs->ptr))
205df0566a6SJani Nikula 		return NULL;
206df0566a6SJani Nikula 	ofs = ptrs->ptr[index].fp_timing_offset;
207df0566a6SJani Nikula 	if (ofs < data_ofs ||
208df0566a6SJani Nikula 	    ofs + sizeof(struct lvds_fp_timing) > data_ofs + data_size)
209df0566a6SJani Nikula 		return NULL;
210df0566a6SJani Nikula 	return (const struct lvds_fp_timing *)((const u8 *)bdb + ofs);
211df0566a6SJani Nikula }
212df0566a6SJani Nikula 
2139e7ecedfSMatt Roper /* Parse general panel options */
214df0566a6SJani Nikula static void
2159e7ecedfSMatt Roper parse_panel_options(struct drm_i915_private *dev_priv,
216df0566a6SJani Nikula 		    const struct bdb_header *bdb)
217df0566a6SJani Nikula {
218df0566a6SJani Nikula 	const struct bdb_lvds_options *lvds_options;
219df0566a6SJani Nikula 	int panel_type;
220df0566a6SJani Nikula 	int drrs_mode;
221df0566a6SJani Nikula 	int ret;
222df0566a6SJani Nikula 
223df0566a6SJani Nikula 	lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);
224df0566a6SJani Nikula 	if (!lvds_options)
225df0566a6SJani Nikula 		return;
226df0566a6SJani Nikula 
227df0566a6SJani Nikula 	dev_priv->vbt.lvds_dither = lvds_options->pixel_dither;
228df0566a6SJani Nikula 
229df0566a6SJani Nikula 	ret = intel_opregion_get_panel_type(dev_priv);
230df0566a6SJani Nikula 	if (ret >= 0) {
231df0566a6SJani Nikula 		WARN_ON(ret > 0xf);
232df0566a6SJani Nikula 		panel_type = ret;
233df0566a6SJani Nikula 		DRM_DEBUG_KMS("Panel type: %d (OpRegion)\n", panel_type);
234df0566a6SJani Nikula 	} else {
235df0566a6SJani Nikula 		if (lvds_options->panel_type > 0xf) {
236df0566a6SJani Nikula 			DRM_DEBUG_KMS("Invalid VBT panel type 0x%x\n",
237df0566a6SJani Nikula 				      lvds_options->panel_type);
238df0566a6SJani Nikula 			return;
239df0566a6SJani Nikula 		}
240df0566a6SJani Nikula 		panel_type = lvds_options->panel_type;
241df0566a6SJani Nikula 		DRM_DEBUG_KMS("Panel type: %d (VBT)\n", panel_type);
242df0566a6SJani Nikula 	}
243df0566a6SJani Nikula 
244df0566a6SJani Nikula 	dev_priv->vbt.panel_type = panel_type;
245df0566a6SJani Nikula 
246df0566a6SJani Nikula 	drrs_mode = (lvds_options->dps_panel_type_bits
247df0566a6SJani Nikula 				>> (panel_type * 2)) & MODE_MASK;
248df0566a6SJani Nikula 	/*
249df0566a6SJani Nikula 	 * VBT has static DRRS = 0 and seamless DRRS = 2.
250df0566a6SJani Nikula 	 * The below piece of code is required to adjust vbt.drrs_type
251df0566a6SJani Nikula 	 * to match the enum drrs_support_type.
252df0566a6SJani Nikula 	 */
253df0566a6SJani Nikula 	switch (drrs_mode) {
254df0566a6SJani Nikula 	case 0:
255df0566a6SJani Nikula 		dev_priv->vbt.drrs_type = STATIC_DRRS_SUPPORT;
256df0566a6SJani Nikula 		DRM_DEBUG_KMS("DRRS supported mode is static\n");
257df0566a6SJani Nikula 		break;
258df0566a6SJani Nikula 	case 2:
259df0566a6SJani Nikula 		dev_priv->vbt.drrs_type = SEAMLESS_DRRS_SUPPORT;
260df0566a6SJani Nikula 		DRM_DEBUG_KMS("DRRS supported mode is seamless\n");
261df0566a6SJani Nikula 		break;
262df0566a6SJani Nikula 	default:
263df0566a6SJani Nikula 		dev_priv->vbt.drrs_type = DRRS_NOT_SUPPORTED;
264df0566a6SJani Nikula 		DRM_DEBUG_KMS("DRRS not supported (VBT input)\n");
265df0566a6SJani Nikula 		break;
266df0566a6SJani Nikula 	}
2679e7ecedfSMatt Roper }
2689e7ecedfSMatt Roper 
2699e7ecedfSMatt Roper /* Try to find integrated panel timing data */
2709e7ecedfSMatt Roper static void
2719e7ecedfSMatt Roper parse_lfp_panel_dtd(struct drm_i915_private *dev_priv,
2729e7ecedfSMatt Roper 		    const struct bdb_header *bdb)
2739e7ecedfSMatt Roper {
2749e7ecedfSMatt Roper 	const struct bdb_lvds_lfp_data *lvds_lfp_data;
2759e7ecedfSMatt Roper 	const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs;
2769e7ecedfSMatt Roper 	const struct lvds_dvo_timing *panel_dvo_timing;
2779e7ecedfSMatt Roper 	const struct lvds_fp_timing *fp_timing;
2789e7ecedfSMatt Roper 	struct drm_display_mode *panel_fixed_mode;
2799e7ecedfSMatt Roper 	int panel_type = dev_priv->vbt.panel_type;
280df0566a6SJani Nikula 
281df0566a6SJani Nikula 	lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA);
282df0566a6SJani Nikula 	if (!lvds_lfp_data)
283df0566a6SJani Nikula 		return;
284df0566a6SJani Nikula 
285df0566a6SJani Nikula 	lvds_lfp_data_ptrs = find_section(bdb, BDB_LVDS_LFP_DATA_PTRS);
286df0566a6SJani Nikula 	if (!lvds_lfp_data_ptrs)
287df0566a6SJani Nikula 		return;
288df0566a6SJani Nikula 
289df0566a6SJani Nikula 	panel_dvo_timing = get_lvds_dvo_timing(lvds_lfp_data,
290df0566a6SJani Nikula 					       lvds_lfp_data_ptrs,
291df0566a6SJani Nikula 					       panel_type);
292df0566a6SJani Nikula 
293df0566a6SJani Nikula 	panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
294df0566a6SJani Nikula 	if (!panel_fixed_mode)
295df0566a6SJani Nikula 		return;
296df0566a6SJani Nikula 
297df0566a6SJani Nikula 	fill_detail_timing_data(panel_fixed_mode, panel_dvo_timing);
298df0566a6SJani Nikula 
299df0566a6SJani Nikula 	dev_priv->vbt.lfp_lvds_vbt_mode = panel_fixed_mode;
300df0566a6SJani Nikula 
30133ef6d4fSMatt Roper 	DRM_DEBUG_KMS("Found panel mode in BIOS VBT legacy lfp table:\n");
302df0566a6SJani Nikula 	drm_mode_debug_printmodeline(panel_fixed_mode);
303df0566a6SJani Nikula 
304df0566a6SJani Nikula 	fp_timing = get_lvds_fp_timing(bdb, lvds_lfp_data,
305df0566a6SJani Nikula 				       lvds_lfp_data_ptrs,
306df0566a6SJani Nikula 				       panel_type);
307df0566a6SJani Nikula 	if (fp_timing) {
308df0566a6SJani Nikula 		/* check the resolution, just to be sure */
309df0566a6SJani Nikula 		if (fp_timing->x_res == panel_fixed_mode->hdisplay &&
310df0566a6SJani Nikula 		    fp_timing->y_res == panel_fixed_mode->vdisplay) {
311df0566a6SJani Nikula 			dev_priv->vbt.bios_lvds_val = fp_timing->lvds_reg_val;
312df0566a6SJani Nikula 			DRM_DEBUG_KMS("VBT initial LVDS value %x\n",
313df0566a6SJani Nikula 				      dev_priv->vbt.bios_lvds_val);
314df0566a6SJani Nikula 		}
315df0566a6SJani Nikula 	}
316df0566a6SJani Nikula }
317df0566a6SJani Nikula 
318df0566a6SJani Nikula static void
31933ef6d4fSMatt Roper parse_generic_dtd(struct drm_i915_private *dev_priv,
32033ef6d4fSMatt Roper 		  const struct bdb_header *bdb)
32133ef6d4fSMatt Roper {
32233ef6d4fSMatt Roper 	const struct bdb_generic_dtd *generic_dtd;
32333ef6d4fSMatt Roper 	const struct generic_dtd_entry *dtd;
32433ef6d4fSMatt Roper 	struct drm_display_mode *panel_fixed_mode;
32533ef6d4fSMatt Roper 	int num_dtd;
32633ef6d4fSMatt Roper 
32733ef6d4fSMatt Roper 	generic_dtd = find_section(bdb, BDB_GENERIC_DTD);
32833ef6d4fSMatt Roper 	if (!generic_dtd)
32933ef6d4fSMatt Roper 		return;
33033ef6d4fSMatt Roper 
33133ef6d4fSMatt Roper 	if (generic_dtd->gdtd_size < sizeof(struct generic_dtd_entry)) {
33233ef6d4fSMatt Roper 		DRM_ERROR("GDTD size %u is too small.\n",
33333ef6d4fSMatt Roper 			  generic_dtd->gdtd_size);
33433ef6d4fSMatt Roper 		return;
33533ef6d4fSMatt Roper 	} else if (generic_dtd->gdtd_size !=
33633ef6d4fSMatt Roper 		   sizeof(struct generic_dtd_entry)) {
33733ef6d4fSMatt Roper 		DRM_ERROR("Unexpected GDTD size %u\n", generic_dtd->gdtd_size);
33833ef6d4fSMatt Roper 		/* DTD has unknown fields, but keep going */
33933ef6d4fSMatt Roper 	}
34033ef6d4fSMatt Roper 
34133ef6d4fSMatt Roper 	num_dtd = (get_blocksize(generic_dtd) -
34233ef6d4fSMatt Roper 		   sizeof(struct bdb_generic_dtd)) / generic_dtd->gdtd_size;
3438c8a854dSDan Carpenter 	if (dev_priv->vbt.panel_type >= num_dtd) {
34433ef6d4fSMatt Roper 		DRM_ERROR("Panel type %d not found in table of %d DTD's\n",
34533ef6d4fSMatt Roper 			  dev_priv->vbt.panel_type, num_dtd);
34633ef6d4fSMatt Roper 		return;
34733ef6d4fSMatt Roper 	}
34833ef6d4fSMatt Roper 
34933ef6d4fSMatt Roper 	dtd = &generic_dtd->dtd[dev_priv->vbt.panel_type];
35033ef6d4fSMatt Roper 
35133ef6d4fSMatt Roper 	panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
35233ef6d4fSMatt Roper 	if (!panel_fixed_mode)
35333ef6d4fSMatt Roper 		return;
35433ef6d4fSMatt Roper 
35533ef6d4fSMatt Roper 	panel_fixed_mode->hdisplay = dtd->hactive;
35633ef6d4fSMatt Roper 	panel_fixed_mode->hsync_start =
35733ef6d4fSMatt Roper 		panel_fixed_mode->hdisplay + dtd->hfront_porch;
35833ef6d4fSMatt Roper 	panel_fixed_mode->hsync_end =
35933ef6d4fSMatt Roper 		panel_fixed_mode->hsync_start + dtd->hsync;
36033ef6d4fSMatt Roper 	panel_fixed_mode->htotal = panel_fixed_mode->hsync_end;
36133ef6d4fSMatt Roper 
36233ef6d4fSMatt Roper 	panel_fixed_mode->vdisplay = dtd->vactive;
36333ef6d4fSMatt Roper 	panel_fixed_mode->vsync_start =
36433ef6d4fSMatt Roper 		panel_fixed_mode->vdisplay + dtd->vfront_porch;
36533ef6d4fSMatt Roper 	panel_fixed_mode->vsync_end =
36633ef6d4fSMatt Roper 		panel_fixed_mode->vsync_start + dtd->vsync;
36733ef6d4fSMatt Roper 	panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end;
36833ef6d4fSMatt Roper 
36933ef6d4fSMatt Roper 	panel_fixed_mode->clock = dtd->pixel_clock;
37033ef6d4fSMatt Roper 	panel_fixed_mode->width_mm = dtd->width_mm;
37133ef6d4fSMatt Roper 	panel_fixed_mode->height_mm = dtd->height_mm;
37233ef6d4fSMatt Roper 
37333ef6d4fSMatt Roper 	panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED;
37433ef6d4fSMatt Roper 	drm_mode_set_name(panel_fixed_mode);
37533ef6d4fSMatt Roper 
37633ef6d4fSMatt Roper 	if (dtd->hsync_positive_polarity)
37733ef6d4fSMatt Roper 		panel_fixed_mode->flags |= DRM_MODE_FLAG_PHSYNC;
37833ef6d4fSMatt Roper 	else
37933ef6d4fSMatt Roper 		panel_fixed_mode->flags |= DRM_MODE_FLAG_NHSYNC;
38033ef6d4fSMatt Roper 
38133ef6d4fSMatt Roper 	if (dtd->vsync_positive_polarity)
38233ef6d4fSMatt Roper 		panel_fixed_mode->flags |= DRM_MODE_FLAG_PVSYNC;
38333ef6d4fSMatt Roper 	else
38433ef6d4fSMatt Roper 		panel_fixed_mode->flags |= DRM_MODE_FLAG_NVSYNC;
38533ef6d4fSMatt Roper 
38633ef6d4fSMatt Roper 	DRM_DEBUG_KMS("Found panel mode in BIOS VBT generic dtd table:\n");
38733ef6d4fSMatt Roper 	drm_mode_debug_printmodeline(panel_fixed_mode);
38833ef6d4fSMatt Roper 
38933ef6d4fSMatt Roper 	dev_priv->vbt.lfp_lvds_vbt_mode = panel_fixed_mode;
39033ef6d4fSMatt Roper }
39133ef6d4fSMatt Roper 
39233ef6d4fSMatt Roper static void
39333ef6d4fSMatt Roper parse_panel_dtd(struct drm_i915_private *dev_priv,
39433ef6d4fSMatt Roper 		const struct bdb_header *bdb)
39533ef6d4fSMatt Roper {
39633ef6d4fSMatt Roper 	/*
39733ef6d4fSMatt Roper 	 * Older VBTs provided provided DTD information for internal displays
39833ef6d4fSMatt Roper 	 * through the "LFP panel DTD" block (42).  As of VBT revision 229,
39933ef6d4fSMatt Roper 	 * that block is now deprecated and DTD information should be provided
40033ef6d4fSMatt Roper 	 * via a newer "generic DTD" block (58).  Just to be safe, we'll
40133ef6d4fSMatt Roper 	 * try the new generic DTD block first on VBT >= 229, but still fall
40233ef6d4fSMatt Roper 	 * back to trying the old LFP block if that fails.
40333ef6d4fSMatt Roper 	 */
40433ef6d4fSMatt Roper 	if (bdb->version >= 229)
40533ef6d4fSMatt Roper 		parse_generic_dtd(dev_priv, bdb);
40633ef6d4fSMatt Roper 	if (!dev_priv->vbt.lfp_lvds_vbt_mode)
40733ef6d4fSMatt Roper 		parse_lfp_panel_dtd(dev_priv, bdb);
40833ef6d4fSMatt Roper }
40933ef6d4fSMatt Roper 
41033ef6d4fSMatt Roper static void
411df0566a6SJani Nikula parse_lfp_backlight(struct drm_i915_private *dev_priv,
412df0566a6SJani Nikula 		    const struct bdb_header *bdb)
413df0566a6SJani Nikula {
414df0566a6SJani Nikula 	const struct bdb_lfp_backlight_data *backlight_data;
415df0566a6SJani Nikula 	const struct lfp_backlight_data_entry *entry;
416df0566a6SJani Nikula 	int panel_type = dev_priv->vbt.panel_type;
417df0566a6SJani Nikula 
418df0566a6SJani Nikula 	backlight_data = find_section(bdb, BDB_LVDS_BACKLIGHT);
419df0566a6SJani Nikula 	if (!backlight_data)
420df0566a6SJani Nikula 		return;
421df0566a6SJani Nikula 
422df0566a6SJani Nikula 	if (backlight_data->entry_size != sizeof(backlight_data->data[0])) {
423df0566a6SJani Nikula 		DRM_DEBUG_KMS("Unsupported backlight data entry size %u\n",
424df0566a6SJani Nikula 			      backlight_data->entry_size);
425df0566a6SJani Nikula 		return;
426df0566a6SJani Nikula 	}
427df0566a6SJani Nikula 
428df0566a6SJani Nikula 	entry = &backlight_data->data[panel_type];
429df0566a6SJani Nikula 
430df0566a6SJani Nikula 	dev_priv->vbt.backlight.present = entry->type == BDB_BACKLIGHT_TYPE_PWM;
431df0566a6SJani Nikula 	if (!dev_priv->vbt.backlight.present) {
432df0566a6SJani Nikula 		DRM_DEBUG_KMS("PWM backlight not present in VBT (type %u)\n",
433df0566a6SJani Nikula 			      entry->type);
434df0566a6SJani Nikula 		return;
435df0566a6SJani Nikula 	}
436df0566a6SJani Nikula 
437df0566a6SJani Nikula 	dev_priv->vbt.backlight.type = INTEL_BACKLIGHT_DISPLAY_DDI;
438df0566a6SJani Nikula 	if (bdb->version >= 191 &&
439df0566a6SJani Nikula 	    get_blocksize(backlight_data) >= sizeof(*backlight_data)) {
440df0566a6SJani Nikula 		const struct lfp_backlight_control_method *method;
441df0566a6SJani Nikula 
442df0566a6SJani Nikula 		method = &backlight_data->backlight_control[panel_type];
443df0566a6SJani Nikula 		dev_priv->vbt.backlight.type = method->type;
444df0566a6SJani Nikula 		dev_priv->vbt.backlight.controller = method->controller;
445df0566a6SJani Nikula 	}
446df0566a6SJani Nikula 
447df0566a6SJani Nikula 	dev_priv->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz;
448df0566a6SJani Nikula 	dev_priv->vbt.backlight.active_low_pwm = entry->active_low_pwm;
449df0566a6SJani Nikula 	dev_priv->vbt.backlight.min_brightness = entry->min_brightness;
450df0566a6SJani Nikula 	DRM_DEBUG_KMS("VBT backlight PWM modulation frequency %u Hz, "
451df0566a6SJani Nikula 		      "active %s, min brightness %u, level %u, controller %u\n",
452df0566a6SJani Nikula 		      dev_priv->vbt.backlight.pwm_freq_hz,
453df0566a6SJani Nikula 		      dev_priv->vbt.backlight.active_low_pwm ? "low" : "high",
454df0566a6SJani Nikula 		      dev_priv->vbt.backlight.min_brightness,
455df0566a6SJani Nikula 		      backlight_data->level[panel_type],
456df0566a6SJani Nikula 		      dev_priv->vbt.backlight.controller);
457df0566a6SJani Nikula }
458df0566a6SJani Nikula 
459df0566a6SJani Nikula /* Try to find sdvo panel data */
460df0566a6SJani Nikula static void
461df0566a6SJani Nikula parse_sdvo_panel_data(struct drm_i915_private *dev_priv,
462df0566a6SJani Nikula 		      const struct bdb_header *bdb)
463df0566a6SJani Nikula {
464df0566a6SJani Nikula 	const struct bdb_sdvo_panel_dtds *dtds;
465df0566a6SJani Nikula 	struct drm_display_mode *panel_fixed_mode;
466df0566a6SJani Nikula 	int index;
467df0566a6SJani Nikula 
468df0566a6SJani Nikula 	index = i915_modparams.vbt_sdvo_panel_type;
469df0566a6SJani Nikula 	if (index == -2) {
470df0566a6SJani Nikula 		DRM_DEBUG_KMS("Ignore SDVO panel mode from BIOS VBT tables.\n");
471df0566a6SJani Nikula 		return;
472df0566a6SJani Nikula 	}
473df0566a6SJani Nikula 
474df0566a6SJani Nikula 	if (index == -1) {
475df0566a6SJani Nikula 		const struct bdb_sdvo_lvds_options *sdvo_lvds_options;
476df0566a6SJani Nikula 
477df0566a6SJani Nikula 		sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS);
478df0566a6SJani Nikula 		if (!sdvo_lvds_options)
479df0566a6SJani Nikula 			return;
480df0566a6SJani Nikula 
481df0566a6SJani Nikula 		index = sdvo_lvds_options->panel_type;
482df0566a6SJani Nikula 	}
483df0566a6SJani Nikula 
484df0566a6SJani Nikula 	dtds = find_section(bdb, BDB_SDVO_PANEL_DTDS);
485df0566a6SJani Nikula 	if (!dtds)
486df0566a6SJani Nikula 		return;
487df0566a6SJani Nikula 
488df0566a6SJani Nikula 	panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
489df0566a6SJani Nikula 	if (!panel_fixed_mode)
490df0566a6SJani Nikula 		return;
491df0566a6SJani Nikula 
492df0566a6SJani Nikula 	fill_detail_timing_data(panel_fixed_mode, &dtds->dtds[index]);
493df0566a6SJani Nikula 
494df0566a6SJani Nikula 	dev_priv->vbt.sdvo_lvds_vbt_mode = panel_fixed_mode;
495df0566a6SJani Nikula 
496df0566a6SJani Nikula 	DRM_DEBUG_KMS("Found SDVO panel mode in BIOS VBT tables:\n");
497df0566a6SJani Nikula 	drm_mode_debug_printmodeline(panel_fixed_mode);
498df0566a6SJani Nikula }
499df0566a6SJani Nikula 
500df0566a6SJani Nikula static int intel_bios_ssc_frequency(struct drm_i915_private *dev_priv,
501df0566a6SJani Nikula 				    bool alternate)
502df0566a6SJani Nikula {
503df0566a6SJani Nikula 	switch (INTEL_GEN(dev_priv)) {
504df0566a6SJani Nikula 	case 2:
505df0566a6SJani Nikula 		return alternate ? 66667 : 48000;
506df0566a6SJani Nikula 	case 3:
507df0566a6SJani Nikula 	case 4:
508df0566a6SJani Nikula 		return alternate ? 100000 : 96000;
509df0566a6SJani Nikula 	default:
510df0566a6SJani Nikula 		return alternate ? 100000 : 120000;
511df0566a6SJani Nikula 	}
512df0566a6SJani Nikula }
513df0566a6SJani Nikula 
514df0566a6SJani Nikula static void
515df0566a6SJani Nikula parse_general_features(struct drm_i915_private *dev_priv,
516df0566a6SJani Nikula 		       const struct bdb_header *bdb)
517df0566a6SJani Nikula {
518df0566a6SJani Nikula 	const struct bdb_general_features *general;
519df0566a6SJani Nikula 
520df0566a6SJani Nikula 	general = find_section(bdb, BDB_GENERAL_FEATURES);
521df0566a6SJani Nikula 	if (!general)
522df0566a6SJani Nikula 		return;
523df0566a6SJani Nikula 
524df0566a6SJani Nikula 	dev_priv->vbt.int_tv_support = general->int_tv_support;
525df0566a6SJani Nikula 	/* int_crt_support can't be trusted on earlier platforms */
526df0566a6SJani Nikula 	if (bdb->version >= 155 &&
527df0566a6SJani Nikula 	    (HAS_DDI(dev_priv) || IS_VALLEYVIEW(dev_priv)))
528df0566a6SJani Nikula 		dev_priv->vbt.int_crt_support = general->int_crt_support;
529df0566a6SJani Nikula 	dev_priv->vbt.lvds_use_ssc = general->enable_ssc;
530df0566a6SJani Nikula 	dev_priv->vbt.lvds_ssc_freq =
531df0566a6SJani Nikula 		intel_bios_ssc_frequency(dev_priv, general->ssc_freq);
532df0566a6SJani Nikula 	dev_priv->vbt.display_clock_mode = general->display_clock_mode;
533df0566a6SJani Nikula 	dev_priv->vbt.fdi_rx_polarity_inverted = general->fdi_rx_polarity_inverted;
534df0566a6SJani Nikula 	if (bdb->version >= 181) {
535df0566a6SJani Nikula 		dev_priv->vbt.orientation = general->rotate_180 ?
536df0566a6SJani Nikula 			DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP :
537df0566a6SJani Nikula 			DRM_MODE_PANEL_ORIENTATION_NORMAL;
538df0566a6SJani Nikula 	} else {
539df0566a6SJani Nikula 		dev_priv->vbt.orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
540df0566a6SJani Nikula 	}
541df0566a6SJani Nikula 	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",
542df0566a6SJani Nikula 		      dev_priv->vbt.int_tv_support,
543df0566a6SJani Nikula 		      dev_priv->vbt.int_crt_support,
544df0566a6SJani Nikula 		      dev_priv->vbt.lvds_use_ssc,
545df0566a6SJani Nikula 		      dev_priv->vbt.lvds_ssc_freq,
546df0566a6SJani Nikula 		      dev_priv->vbt.display_clock_mode,
547df0566a6SJani Nikula 		      dev_priv->vbt.fdi_rx_polarity_inverted);
548df0566a6SJani Nikula }
549df0566a6SJani Nikula 
550df0566a6SJani Nikula static const struct child_device_config *
551df0566a6SJani Nikula child_device_ptr(const struct bdb_general_definitions *defs, int i)
552df0566a6SJani Nikula {
553df0566a6SJani Nikula 	return (const void *) &defs->devices[i * defs->child_dev_size];
554df0566a6SJani Nikula }
555df0566a6SJani Nikula 
556df0566a6SJani Nikula static void
557df0566a6SJani Nikula parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, u8 bdb_version)
558df0566a6SJani Nikula {
559df0566a6SJani Nikula 	struct sdvo_device_mapping *mapping;
5600d9ef19bSJani Nikula 	const struct display_device_data *devdata;
561df0566a6SJani Nikula 	const struct child_device_config *child;
5620d9ef19bSJani Nikula 	int count = 0;
563df0566a6SJani Nikula 
564df0566a6SJani Nikula 	/*
565df0566a6SJani Nikula 	 * Only parse SDVO mappings on gens that could have SDVO. This isn't
566df0566a6SJani Nikula 	 * accurate and doesn't have to be, as long as it's not too strict.
567df0566a6SJani Nikula 	 */
568df0566a6SJani Nikula 	if (!IS_GEN_RANGE(dev_priv, 3, 7)) {
569df0566a6SJani Nikula 		DRM_DEBUG_KMS("Skipping SDVO device mapping\n");
570df0566a6SJani Nikula 		return;
571df0566a6SJani Nikula 	}
572df0566a6SJani Nikula 
5730d9ef19bSJani Nikula 	list_for_each_entry(devdata, &dev_priv->vbt.display_devices, node) {
5740d9ef19bSJani Nikula 		child = &devdata->child;
575df0566a6SJani Nikula 
576df0566a6SJani Nikula 		if (child->slave_addr != SLAVE_ADDR1 &&
577df0566a6SJani Nikula 		    child->slave_addr != SLAVE_ADDR2) {
578df0566a6SJani Nikula 			/*
579df0566a6SJani Nikula 			 * If the slave address is neither 0x70 nor 0x72,
580df0566a6SJani Nikula 			 * it is not a SDVO device. Skip it.
581df0566a6SJani Nikula 			 */
582df0566a6SJani Nikula 			continue;
583df0566a6SJani Nikula 		}
584df0566a6SJani Nikula 		if (child->dvo_port != DEVICE_PORT_DVOB &&
585df0566a6SJani Nikula 		    child->dvo_port != DEVICE_PORT_DVOC) {
586df0566a6SJani Nikula 			/* skip the incorrect SDVO port */
587df0566a6SJani Nikula 			DRM_DEBUG_KMS("Incorrect SDVO port. Skip it\n");
588df0566a6SJani Nikula 			continue;
589df0566a6SJani Nikula 		}
590df0566a6SJani Nikula 		DRM_DEBUG_KMS("the SDVO device with slave addr %2x is found on"
591df0566a6SJani Nikula 			      " %s port\n",
592df0566a6SJani Nikula 			      child->slave_addr,
593df0566a6SJani Nikula 			      (child->dvo_port == DEVICE_PORT_DVOB) ?
594df0566a6SJani Nikula 			      "SDVOB" : "SDVOC");
595df0566a6SJani Nikula 		mapping = &dev_priv->vbt.sdvo_mappings[child->dvo_port - 1];
596df0566a6SJani Nikula 		if (!mapping->initialized) {
597df0566a6SJani Nikula 			mapping->dvo_port = child->dvo_port;
598df0566a6SJani Nikula 			mapping->slave_addr = child->slave_addr;
599df0566a6SJani Nikula 			mapping->dvo_wiring = child->dvo_wiring;
600df0566a6SJani Nikula 			mapping->ddc_pin = child->ddc_pin;
601df0566a6SJani Nikula 			mapping->i2c_pin = child->i2c_pin;
602df0566a6SJani Nikula 			mapping->initialized = 1;
603df0566a6SJani Nikula 			DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d\n",
604df0566a6SJani Nikula 				      mapping->dvo_port,
605df0566a6SJani Nikula 				      mapping->slave_addr,
606df0566a6SJani Nikula 				      mapping->dvo_wiring,
607df0566a6SJani Nikula 				      mapping->ddc_pin,
608df0566a6SJani Nikula 				      mapping->i2c_pin);
609df0566a6SJani Nikula 		} else {
610df0566a6SJani Nikula 			DRM_DEBUG_KMS("Maybe one SDVO port is shared by "
611df0566a6SJani Nikula 					 "two SDVO device.\n");
612df0566a6SJani Nikula 		}
613df0566a6SJani Nikula 		if (child->slave2_addr) {
614df0566a6SJani Nikula 			/* Maybe this is a SDVO device with multiple inputs */
615df0566a6SJani Nikula 			/* And the mapping info is not added */
616df0566a6SJani Nikula 			DRM_DEBUG_KMS("there exists the slave2_addr. Maybe this"
617df0566a6SJani Nikula 				" is a SDVO device with multiple inputs.\n");
618df0566a6SJani Nikula 		}
619df0566a6SJani Nikula 		count++;
620df0566a6SJani Nikula 	}
621df0566a6SJani Nikula 
622df0566a6SJani Nikula 	if (!count) {
623df0566a6SJani Nikula 		/* No SDVO device info is found */
624df0566a6SJani Nikula 		DRM_DEBUG_KMS("No SDVO device info is found in VBT\n");
625df0566a6SJani Nikula 	}
626df0566a6SJani Nikula }
627df0566a6SJani Nikula 
628df0566a6SJani Nikula static void
629df0566a6SJani Nikula parse_driver_features(struct drm_i915_private *dev_priv,
630df0566a6SJani Nikula 		      const struct bdb_header *bdb)
631df0566a6SJani Nikula {
632df0566a6SJani Nikula 	const struct bdb_driver_features *driver;
633df0566a6SJani Nikula 
634df0566a6SJani Nikula 	driver = find_section(bdb, BDB_DRIVER_FEATURES);
635df0566a6SJani Nikula 	if (!driver)
636df0566a6SJani Nikula 		return;
637df0566a6SJani Nikula 
638df0566a6SJani Nikula 	if (INTEL_GEN(dev_priv) >= 5) {
639df0566a6SJani Nikula 		/*
640df0566a6SJani Nikula 		 * Note that we consider BDB_DRIVER_FEATURE_INT_SDVO_LVDS
641df0566a6SJani Nikula 		 * to mean "eDP". The VBT spec doesn't agree with that
642df0566a6SJani Nikula 		 * interpretation, but real world VBTs seem to.
643df0566a6SJani Nikula 		 */
644df0566a6SJani Nikula 		if (driver->lvds_config != BDB_DRIVER_FEATURE_INT_LVDS)
645df0566a6SJani Nikula 			dev_priv->vbt.int_lvds_support = 0;
646df0566a6SJani Nikula 	} else {
647df0566a6SJani Nikula 		/*
648df0566a6SJani Nikula 		 * FIXME it's not clear which BDB version has the LVDS config
649df0566a6SJani Nikula 		 * bits defined. Revision history in the VBT spec says:
650df0566a6SJani Nikula 		 * "0.92 | Add two definitions for VBT value of LVDS Active
651df0566a6SJani Nikula 		 *  Config (00b and 11b values defined) | 06/13/2005"
652df0566a6SJani Nikula 		 * but does not the specify the BDB version.
653df0566a6SJani Nikula 		 *
654df0566a6SJani Nikula 		 * So far version 134 (on i945gm) is the oldest VBT observed
655df0566a6SJani Nikula 		 * in the wild with the bits correctly populated. Version
656df0566a6SJani Nikula 		 * 108 (on i85x) does not have the bits correctly populated.
657df0566a6SJani Nikula 		 */
658df0566a6SJani Nikula 		if (bdb->version >= 134 &&
659df0566a6SJani Nikula 		    driver->lvds_config != BDB_DRIVER_FEATURE_INT_LVDS &&
660df0566a6SJani Nikula 		    driver->lvds_config != BDB_DRIVER_FEATURE_INT_SDVO_LVDS)
661df0566a6SJani Nikula 			dev_priv->vbt.int_lvds_support = 0;
662df0566a6SJani Nikula 	}
663df0566a6SJani Nikula 
664551fb93dSJosé Roberto de Souza 	if (bdb->version < 228) {
665df0566a6SJani Nikula 		DRM_DEBUG_KMS("DRRS State Enabled:%d\n", driver->drrs_enabled);
666df0566a6SJani Nikula 		/*
667df0566a6SJani Nikula 		 * If DRRS is not supported, drrs_type has to be set to 0.
668df0566a6SJani Nikula 		 * This is because, VBT is configured in such a way that
669df0566a6SJani Nikula 		 * static DRRS is 0 and DRRS not supported is represented by
670df0566a6SJani Nikula 		 * driver->drrs_enabled=false
671df0566a6SJani Nikula 		 */
672df0566a6SJani Nikula 		if (!driver->drrs_enabled)
673df0566a6SJani Nikula 			dev_priv->vbt.drrs_type = DRRS_NOT_SUPPORTED;
674551fb93dSJosé Roberto de Souza 
675df0566a6SJani Nikula 		dev_priv->vbt.psr.enable = driver->psr_enabled;
676df0566a6SJani Nikula 	}
677551fb93dSJosé Roberto de Souza }
678551fb93dSJosé Roberto de Souza 
679551fb93dSJosé Roberto de Souza static void
680551fb93dSJosé Roberto de Souza parse_power_conservation_features(struct drm_i915_private *dev_priv,
681551fb93dSJosé Roberto de Souza 				  const struct bdb_header *bdb)
682551fb93dSJosé Roberto de Souza {
683551fb93dSJosé Roberto de Souza 	const struct bdb_lfp_power *power;
684551fb93dSJosé Roberto de Souza 	u8 panel_type = dev_priv->vbt.panel_type;
685551fb93dSJosé Roberto de Souza 
686551fb93dSJosé Roberto de Souza 	if (bdb->version < 228)
687551fb93dSJosé Roberto de Souza 		return;
688551fb93dSJosé Roberto de Souza 
689*4ec5abe9SJosé Roberto de Souza 	power = find_section(bdb, BDB_LFP_POWER);
690551fb93dSJosé Roberto de Souza 	if (!power)
691551fb93dSJosé Roberto de Souza 		return;
692551fb93dSJosé Roberto de Souza 
693551fb93dSJosé Roberto de Souza 	dev_priv->vbt.psr.enable = power->psr & BIT(panel_type);
694551fb93dSJosé Roberto de Souza 
695551fb93dSJosé Roberto de Souza 	/*
696551fb93dSJosé Roberto de Souza 	 * If DRRS is not supported, drrs_type has to be set to 0.
697551fb93dSJosé Roberto de Souza 	 * This is because, VBT is configured in such a way that
698551fb93dSJosé Roberto de Souza 	 * static DRRS is 0 and DRRS not supported is represented by
699551fb93dSJosé Roberto de Souza 	 * power->drrs & BIT(panel_type)=false
700551fb93dSJosé Roberto de Souza 	 */
701551fb93dSJosé Roberto de Souza 	if (!(power->drrs & BIT(panel_type)))
702551fb93dSJosé Roberto de Souza 		dev_priv->vbt.drrs_type = DRRS_NOT_SUPPORTED;
703551fb93dSJosé Roberto de Souza }
704df0566a6SJani Nikula 
705df0566a6SJani Nikula static void
706df0566a6SJani Nikula parse_edp(struct drm_i915_private *dev_priv, const struct bdb_header *bdb)
707df0566a6SJani Nikula {
708df0566a6SJani Nikula 	const struct bdb_edp *edp;
709df0566a6SJani Nikula 	const struct edp_power_seq *edp_pps;
710df0566a6SJani Nikula 	const struct edp_fast_link_params *edp_link_params;
711df0566a6SJani Nikula 	int panel_type = dev_priv->vbt.panel_type;
712df0566a6SJani Nikula 
713df0566a6SJani Nikula 	edp = find_section(bdb, BDB_EDP);
714df0566a6SJani Nikula 	if (!edp)
715df0566a6SJani Nikula 		return;
716df0566a6SJani Nikula 
717df0566a6SJani Nikula 	switch ((edp->color_depth >> (panel_type * 2)) & 3) {
718df0566a6SJani Nikula 	case EDP_18BPP:
719df0566a6SJani Nikula 		dev_priv->vbt.edp.bpp = 18;
720df0566a6SJani Nikula 		break;
721df0566a6SJani Nikula 	case EDP_24BPP:
722df0566a6SJani Nikula 		dev_priv->vbt.edp.bpp = 24;
723df0566a6SJani Nikula 		break;
724df0566a6SJani Nikula 	case EDP_30BPP:
725df0566a6SJani Nikula 		dev_priv->vbt.edp.bpp = 30;
726df0566a6SJani Nikula 		break;
727df0566a6SJani Nikula 	}
728df0566a6SJani Nikula 
729df0566a6SJani Nikula 	/* Get the eDP sequencing and link info */
730df0566a6SJani Nikula 	edp_pps = &edp->power_seqs[panel_type];
731df0566a6SJani Nikula 	edp_link_params = &edp->fast_link_params[panel_type];
732df0566a6SJani Nikula 
733df0566a6SJani Nikula 	dev_priv->vbt.edp.pps = *edp_pps;
734df0566a6SJani Nikula 
735df0566a6SJani Nikula 	switch (edp_link_params->rate) {
736df0566a6SJani Nikula 	case EDP_RATE_1_62:
737df0566a6SJani Nikula 		dev_priv->vbt.edp.rate = DP_LINK_BW_1_62;
738df0566a6SJani Nikula 		break;
739df0566a6SJani Nikula 	case EDP_RATE_2_7:
740df0566a6SJani Nikula 		dev_priv->vbt.edp.rate = DP_LINK_BW_2_7;
741df0566a6SJani Nikula 		break;
742df0566a6SJani Nikula 	default:
743df0566a6SJani Nikula 		DRM_DEBUG_KMS("VBT has unknown eDP link rate value %u\n",
744df0566a6SJani Nikula 			      edp_link_params->rate);
745df0566a6SJani Nikula 		break;
746df0566a6SJani Nikula 	}
747df0566a6SJani Nikula 
748df0566a6SJani Nikula 	switch (edp_link_params->lanes) {
749df0566a6SJani Nikula 	case EDP_LANE_1:
750df0566a6SJani Nikula 		dev_priv->vbt.edp.lanes = 1;
751df0566a6SJani Nikula 		break;
752df0566a6SJani Nikula 	case EDP_LANE_2:
753df0566a6SJani Nikula 		dev_priv->vbt.edp.lanes = 2;
754df0566a6SJani Nikula 		break;
755df0566a6SJani Nikula 	case EDP_LANE_4:
756df0566a6SJani Nikula 		dev_priv->vbt.edp.lanes = 4;
757df0566a6SJani Nikula 		break;
758df0566a6SJani Nikula 	default:
759df0566a6SJani Nikula 		DRM_DEBUG_KMS("VBT has unknown eDP lane count value %u\n",
760df0566a6SJani Nikula 			      edp_link_params->lanes);
761df0566a6SJani Nikula 		break;
762df0566a6SJani Nikula 	}
763df0566a6SJani Nikula 
764df0566a6SJani Nikula 	switch (edp_link_params->preemphasis) {
765df0566a6SJani Nikula 	case EDP_PREEMPHASIS_NONE:
766df0566a6SJani Nikula 		dev_priv->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_0;
767df0566a6SJani Nikula 		break;
768df0566a6SJani Nikula 	case EDP_PREEMPHASIS_3_5dB:
769df0566a6SJani Nikula 		dev_priv->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_1;
770df0566a6SJani Nikula 		break;
771df0566a6SJani Nikula 	case EDP_PREEMPHASIS_6dB:
772df0566a6SJani Nikula 		dev_priv->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_2;
773df0566a6SJani Nikula 		break;
774df0566a6SJani Nikula 	case EDP_PREEMPHASIS_9_5dB:
775df0566a6SJani Nikula 		dev_priv->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_3;
776df0566a6SJani Nikula 		break;
777df0566a6SJani Nikula 	default:
778df0566a6SJani Nikula 		DRM_DEBUG_KMS("VBT has unknown eDP pre-emphasis value %u\n",
779df0566a6SJani Nikula 			      edp_link_params->preemphasis);
780df0566a6SJani Nikula 		break;
781df0566a6SJani Nikula 	}
782df0566a6SJani Nikula 
783df0566a6SJani Nikula 	switch (edp_link_params->vswing) {
784df0566a6SJani Nikula 	case EDP_VSWING_0_4V:
785df0566a6SJani Nikula 		dev_priv->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_0;
786df0566a6SJani Nikula 		break;
787df0566a6SJani Nikula 	case EDP_VSWING_0_6V:
788df0566a6SJani Nikula 		dev_priv->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_1;
789df0566a6SJani Nikula 		break;
790df0566a6SJani Nikula 	case EDP_VSWING_0_8V:
791df0566a6SJani Nikula 		dev_priv->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
792df0566a6SJani Nikula 		break;
793df0566a6SJani Nikula 	case EDP_VSWING_1_2V:
794df0566a6SJani Nikula 		dev_priv->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
795df0566a6SJani Nikula 		break;
796df0566a6SJani Nikula 	default:
797df0566a6SJani Nikula 		DRM_DEBUG_KMS("VBT has unknown eDP voltage swing value %u\n",
798df0566a6SJani Nikula 			      edp_link_params->vswing);
799df0566a6SJani Nikula 		break;
800df0566a6SJani Nikula 	}
801df0566a6SJani Nikula 
802df0566a6SJani Nikula 	if (bdb->version >= 173) {
803df0566a6SJani Nikula 		u8 vswing;
804df0566a6SJani Nikula 
805df0566a6SJani Nikula 		/* Don't read from VBT if module parameter has valid value*/
806df0566a6SJani Nikula 		if (i915_modparams.edp_vswing) {
807df0566a6SJani Nikula 			dev_priv->vbt.edp.low_vswing =
808df0566a6SJani Nikula 				i915_modparams.edp_vswing == 1;
809df0566a6SJani Nikula 		} else {
810df0566a6SJani Nikula 			vswing = (edp->edp_vswing_preemph >> (panel_type * 4)) & 0xF;
811df0566a6SJani Nikula 			dev_priv->vbt.edp.low_vswing = vswing == 0;
812df0566a6SJani Nikula 		}
813df0566a6SJani Nikula 	}
814df0566a6SJani Nikula }
815df0566a6SJani Nikula 
816df0566a6SJani Nikula static void
817df0566a6SJani Nikula parse_psr(struct drm_i915_private *dev_priv, const struct bdb_header *bdb)
818df0566a6SJani Nikula {
819df0566a6SJani Nikula 	const struct bdb_psr *psr;
820df0566a6SJani Nikula 	const struct psr_table *psr_table;
821df0566a6SJani Nikula 	int panel_type = dev_priv->vbt.panel_type;
822df0566a6SJani Nikula 
823df0566a6SJani Nikula 	psr = find_section(bdb, BDB_PSR);
824df0566a6SJani Nikula 	if (!psr) {
825df0566a6SJani Nikula 		DRM_DEBUG_KMS("No PSR BDB found.\n");
826df0566a6SJani Nikula 		return;
827df0566a6SJani Nikula 	}
828df0566a6SJani Nikula 
829df0566a6SJani Nikula 	psr_table = &psr->psr_table[panel_type];
830df0566a6SJani Nikula 
831df0566a6SJani Nikula 	dev_priv->vbt.psr.full_link = psr_table->full_link;
832df0566a6SJani Nikula 	dev_priv->vbt.psr.require_aux_wakeup = psr_table->require_aux_to_wakeup;
833df0566a6SJani Nikula 
834df0566a6SJani Nikula 	/* Allowed VBT values goes from 0 to 15 */
835df0566a6SJani Nikula 	dev_priv->vbt.psr.idle_frames = psr_table->idle_frames < 0 ? 0 :
836df0566a6SJani Nikula 		psr_table->idle_frames > 15 ? 15 : psr_table->idle_frames;
837df0566a6SJani Nikula 
838df0566a6SJani Nikula 	switch (psr_table->lines_to_wait) {
839df0566a6SJani Nikula 	case 0:
840df0566a6SJani Nikula 		dev_priv->vbt.psr.lines_to_wait = PSR_0_LINES_TO_WAIT;
841df0566a6SJani Nikula 		break;
842df0566a6SJani Nikula 	case 1:
843df0566a6SJani Nikula 		dev_priv->vbt.psr.lines_to_wait = PSR_1_LINE_TO_WAIT;
844df0566a6SJani Nikula 		break;
845df0566a6SJani Nikula 	case 2:
846df0566a6SJani Nikula 		dev_priv->vbt.psr.lines_to_wait = PSR_4_LINES_TO_WAIT;
847df0566a6SJani Nikula 		break;
848df0566a6SJani Nikula 	case 3:
849df0566a6SJani Nikula 		dev_priv->vbt.psr.lines_to_wait = PSR_8_LINES_TO_WAIT;
850df0566a6SJani Nikula 		break;
851df0566a6SJani Nikula 	default:
852df0566a6SJani Nikula 		DRM_DEBUG_KMS("VBT has unknown PSR lines to wait %u\n",
853df0566a6SJani Nikula 			      psr_table->lines_to_wait);
854df0566a6SJani Nikula 		break;
855df0566a6SJani Nikula 	}
856df0566a6SJani Nikula 
857df0566a6SJani Nikula 	/*
858df0566a6SJani Nikula 	 * New psr options 0=500us, 1=100us, 2=2500us, 3=0us
859df0566a6SJani Nikula 	 * Old decimal value is wake up time in multiples of 100 us.
860df0566a6SJani Nikula 	 */
861df0566a6SJani Nikula 	if (bdb->version >= 205 &&
862df0566a6SJani Nikula 	    (IS_GEN9_BC(dev_priv) || IS_GEMINILAKE(dev_priv) ||
863df0566a6SJani Nikula 	     INTEL_GEN(dev_priv) >= 10)) {
864df0566a6SJani Nikula 		switch (psr_table->tp1_wakeup_time) {
865df0566a6SJani Nikula 		case 0:
866df0566a6SJani Nikula 			dev_priv->vbt.psr.tp1_wakeup_time_us = 500;
867df0566a6SJani Nikula 			break;
868df0566a6SJani Nikula 		case 1:
869df0566a6SJani Nikula 			dev_priv->vbt.psr.tp1_wakeup_time_us = 100;
870df0566a6SJani Nikula 			break;
871df0566a6SJani Nikula 		case 3:
872df0566a6SJani Nikula 			dev_priv->vbt.psr.tp1_wakeup_time_us = 0;
873df0566a6SJani Nikula 			break;
874df0566a6SJani Nikula 		default:
875df0566a6SJani Nikula 			DRM_DEBUG_KMS("VBT tp1 wakeup time value %d is outside range[0-3], defaulting to max value 2500us\n",
876df0566a6SJani Nikula 					psr_table->tp1_wakeup_time);
877df0566a6SJani Nikula 			/* fallthrough */
878df0566a6SJani Nikula 		case 2:
879df0566a6SJani Nikula 			dev_priv->vbt.psr.tp1_wakeup_time_us = 2500;
880df0566a6SJani Nikula 			break;
881df0566a6SJani Nikula 		}
882df0566a6SJani Nikula 
883df0566a6SJani Nikula 		switch (psr_table->tp2_tp3_wakeup_time) {
884df0566a6SJani Nikula 		case 0:
885df0566a6SJani Nikula 			dev_priv->vbt.psr.tp2_tp3_wakeup_time_us = 500;
886df0566a6SJani Nikula 			break;
887df0566a6SJani Nikula 		case 1:
888df0566a6SJani Nikula 			dev_priv->vbt.psr.tp2_tp3_wakeup_time_us = 100;
889df0566a6SJani Nikula 			break;
890df0566a6SJani Nikula 		case 3:
891df0566a6SJani Nikula 			dev_priv->vbt.psr.tp2_tp3_wakeup_time_us = 0;
892df0566a6SJani Nikula 			break;
893df0566a6SJani Nikula 		default:
894df0566a6SJani Nikula 			DRM_DEBUG_KMS("VBT tp2_tp3 wakeup time value %d is outside range[0-3], defaulting to max value 2500us\n",
895df0566a6SJani Nikula 					psr_table->tp2_tp3_wakeup_time);
896df0566a6SJani Nikula 			/* fallthrough */
897df0566a6SJani Nikula 		case 2:
898df0566a6SJani Nikula 			dev_priv->vbt.psr.tp2_tp3_wakeup_time_us = 2500;
899df0566a6SJani Nikula 		break;
900df0566a6SJani Nikula 		}
901df0566a6SJani Nikula 	} else {
902df0566a6SJani Nikula 		dev_priv->vbt.psr.tp1_wakeup_time_us = psr_table->tp1_wakeup_time * 100;
903df0566a6SJani Nikula 		dev_priv->vbt.psr.tp2_tp3_wakeup_time_us = psr_table->tp2_tp3_wakeup_time * 100;
904df0566a6SJani Nikula 	}
905df0566a6SJani Nikula 
906df0566a6SJani Nikula 	if (bdb->version >= 226) {
907b5ea9c93SDhinakaran Pandiyan 		u32 wakeup_time = psr->psr2_tp2_tp3_wakeup_time;
908df0566a6SJani Nikula 
909df0566a6SJani Nikula 		wakeup_time = (wakeup_time >> (2 * panel_type)) & 0x3;
910df0566a6SJani Nikula 		switch (wakeup_time) {
911df0566a6SJani Nikula 		case 0:
912df0566a6SJani Nikula 			wakeup_time = 500;
913df0566a6SJani Nikula 			break;
914df0566a6SJani Nikula 		case 1:
915df0566a6SJani Nikula 			wakeup_time = 100;
916df0566a6SJani Nikula 			break;
917df0566a6SJani Nikula 		case 3:
918df0566a6SJani Nikula 			wakeup_time = 50;
919df0566a6SJani Nikula 			break;
920df0566a6SJani Nikula 		default:
921df0566a6SJani Nikula 		case 2:
922df0566a6SJani Nikula 			wakeup_time = 2500;
923df0566a6SJani Nikula 			break;
924df0566a6SJani Nikula 		}
925df0566a6SJani Nikula 		dev_priv->vbt.psr.psr2_tp2_tp3_wakeup_time_us = wakeup_time;
926df0566a6SJani Nikula 	} else {
927df0566a6SJani Nikula 		/* Reusing PSR1 wakeup time for PSR2 in older VBTs */
928df0566a6SJani Nikula 		dev_priv->vbt.psr.psr2_tp2_tp3_wakeup_time_us = dev_priv->vbt.psr.tp2_tp3_wakeup_time_us;
929df0566a6SJani Nikula 	}
930df0566a6SJani Nikula }
931df0566a6SJani Nikula 
932df0566a6SJani Nikula static void parse_dsi_backlight_ports(struct drm_i915_private *dev_priv,
933df0566a6SJani Nikula 				      u16 version, enum port port)
934df0566a6SJani Nikula {
935df0566a6SJani Nikula 	if (!dev_priv->vbt.dsi.config->dual_link || version < 197) {
936df0566a6SJani Nikula 		dev_priv->vbt.dsi.bl_ports = BIT(port);
937df0566a6SJani Nikula 		if (dev_priv->vbt.dsi.config->cabc_supported)
938df0566a6SJani Nikula 			dev_priv->vbt.dsi.cabc_ports = BIT(port);
939df0566a6SJani Nikula 
940df0566a6SJani Nikula 		return;
941df0566a6SJani Nikula 	}
942df0566a6SJani Nikula 
943df0566a6SJani Nikula 	switch (dev_priv->vbt.dsi.config->dl_dcs_backlight_ports) {
944df0566a6SJani Nikula 	case DL_DCS_PORT_A:
945df0566a6SJani Nikula 		dev_priv->vbt.dsi.bl_ports = BIT(PORT_A);
946df0566a6SJani Nikula 		break;
947df0566a6SJani Nikula 	case DL_DCS_PORT_C:
948df0566a6SJani Nikula 		dev_priv->vbt.dsi.bl_ports = BIT(PORT_C);
949df0566a6SJani Nikula 		break;
950df0566a6SJani Nikula 	default:
951df0566a6SJani Nikula 	case DL_DCS_PORT_A_AND_C:
952df0566a6SJani Nikula 		dev_priv->vbt.dsi.bl_ports = BIT(PORT_A) | BIT(PORT_C);
953df0566a6SJani Nikula 		break;
954df0566a6SJani Nikula 	}
955df0566a6SJani Nikula 
956df0566a6SJani Nikula 	if (!dev_priv->vbt.dsi.config->cabc_supported)
957df0566a6SJani Nikula 		return;
958df0566a6SJani Nikula 
959df0566a6SJani Nikula 	switch (dev_priv->vbt.dsi.config->dl_dcs_cabc_ports) {
960df0566a6SJani Nikula 	case DL_DCS_PORT_A:
961df0566a6SJani Nikula 		dev_priv->vbt.dsi.cabc_ports = BIT(PORT_A);
962df0566a6SJani Nikula 		break;
963df0566a6SJani Nikula 	case DL_DCS_PORT_C:
964df0566a6SJani Nikula 		dev_priv->vbt.dsi.cabc_ports = BIT(PORT_C);
965df0566a6SJani Nikula 		break;
966df0566a6SJani Nikula 	default:
967df0566a6SJani Nikula 	case DL_DCS_PORT_A_AND_C:
968df0566a6SJani Nikula 		dev_priv->vbt.dsi.cabc_ports =
969df0566a6SJani Nikula 					BIT(PORT_A) | BIT(PORT_C);
970df0566a6SJani Nikula 		break;
971df0566a6SJani Nikula 	}
972df0566a6SJani Nikula }
973df0566a6SJani Nikula 
974df0566a6SJani Nikula static void
975df0566a6SJani Nikula parse_mipi_config(struct drm_i915_private *dev_priv,
976df0566a6SJani Nikula 		  const struct bdb_header *bdb)
977df0566a6SJani Nikula {
978df0566a6SJani Nikula 	const struct bdb_mipi_config *start;
979df0566a6SJani Nikula 	const struct mipi_config *config;
980df0566a6SJani Nikula 	const struct mipi_pps_data *pps;
981df0566a6SJani Nikula 	int panel_type = dev_priv->vbt.panel_type;
982df0566a6SJani Nikula 	enum port port;
983df0566a6SJani Nikula 
984df0566a6SJani Nikula 	/* parse MIPI blocks only if LFP type is MIPI */
985df0566a6SJani Nikula 	if (!intel_bios_is_dsi_present(dev_priv, &port))
986df0566a6SJani Nikula 		return;
987df0566a6SJani Nikula 
988df0566a6SJani Nikula 	/* Initialize this to undefined indicating no generic MIPI support */
989df0566a6SJani Nikula 	dev_priv->vbt.dsi.panel_id = MIPI_DSI_UNDEFINED_PANEL_ID;
990df0566a6SJani Nikula 
991df0566a6SJani Nikula 	/* Block #40 is already parsed and panel_fixed_mode is
992df0566a6SJani Nikula 	 * stored in dev_priv->lfp_lvds_vbt_mode
993df0566a6SJani Nikula 	 * resuse this when needed
994df0566a6SJani Nikula 	 */
995df0566a6SJani Nikula 
996df0566a6SJani Nikula 	/* Parse #52 for panel index used from panel_type already
997df0566a6SJani Nikula 	 * parsed
998df0566a6SJani Nikula 	 */
999df0566a6SJani Nikula 	start = find_section(bdb, BDB_MIPI_CONFIG);
1000df0566a6SJani Nikula 	if (!start) {
1001df0566a6SJani Nikula 		DRM_DEBUG_KMS("No MIPI config BDB found");
1002df0566a6SJani Nikula 		return;
1003df0566a6SJani Nikula 	}
1004df0566a6SJani Nikula 
1005df0566a6SJani Nikula 	DRM_DEBUG_DRIVER("Found MIPI Config block, panel index = %d\n",
1006df0566a6SJani Nikula 								panel_type);
1007df0566a6SJani Nikula 
1008df0566a6SJani Nikula 	/*
1009df0566a6SJani Nikula 	 * get hold of the correct configuration block and pps data as per
1010df0566a6SJani Nikula 	 * the panel_type as index
1011df0566a6SJani Nikula 	 */
1012df0566a6SJani Nikula 	config = &start->config[panel_type];
1013df0566a6SJani Nikula 	pps = &start->pps[panel_type];
1014df0566a6SJani Nikula 
1015df0566a6SJani Nikula 	/* store as of now full data. Trim when we realise all is not needed */
1016df0566a6SJani Nikula 	dev_priv->vbt.dsi.config = kmemdup(config, sizeof(struct mipi_config), GFP_KERNEL);
1017df0566a6SJani Nikula 	if (!dev_priv->vbt.dsi.config)
1018df0566a6SJani Nikula 		return;
1019df0566a6SJani Nikula 
1020df0566a6SJani Nikula 	dev_priv->vbt.dsi.pps = kmemdup(pps, sizeof(struct mipi_pps_data), GFP_KERNEL);
1021df0566a6SJani Nikula 	if (!dev_priv->vbt.dsi.pps) {
1022df0566a6SJani Nikula 		kfree(dev_priv->vbt.dsi.config);
1023df0566a6SJani Nikula 		return;
1024df0566a6SJani Nikula 	}
1025df0566a6SJani Nikula 
1026df0566a6SJani Nikula 	parse_dsi_backlight_ports(dev_priv, bdb->version, port);
1027df0566a6SJani Nikula 
1028df0566a6SJani Nikula 	/* FIXME is the 90 vs. 270 correct? */
1029df0566a6SJani Nikula 	switch (config->rotation) {
1030df0566a6SJani Nikula 	case ENABLE_ROTATION_0:
1031df0566a6SJani Nikula 		/*
1032df0566a6SJani Nikula 		 * Most (all?) VBTs claim 0 degrees despite having
1033df0566a6SJani Nikula 		 * an upside down panel, thus we do not trust this.
1034df0566a6SJani Nikula 		 */
1035df0566a6SJani Nikula 		dev_priv->vbt.dsi.orientation =
1036df0566a6SJani Nikula 			DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
1037df0566a6SJani Nikula 		break;
1038df0566a6SJani Nikula 	case ENABLE_ROTATION_90:
1039df0566a6SJani Nikula 		dev_priv->vbt.dsi.orientation =
1040df0566a6SJani Nikula 			DRM_MODE_PANEL_ORIENTATION_RIGHT_UP;
1041df0566a6SJani Nikula 		break;
1042df0566a6SJani Nikula 	case ENABLE_ROTATION_180:
1043df0566a6SJani Nikula 		dev_priv->vbt.dsi.orientation =
1044df0566a6SJani Nikula 			DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP;
1045df0566a6SJani Nikula 		break;
1046df0566a6SJani Nikula 	case ENABLE_ROTATION_270:
1047df0566a6SJani Nikula 		dev_priv->vbt.dsi.orientation =
1048df0566a6SJani Nikula 			DRM_MODE_PANEL_ORIENTATION_LEFT_UP;
1049df0566a6SJani Nikula 		break;
1050df0566a6SJani Nikula 	}
1051df0566a6SJani Nikula 
1052df0566a6SJani Nikula 	/* We have mandatory mipi config blocks. Initialize as generic panel */
1053df0566a6SJani Nikula 	dev_priv->vbt.dsi.panel_id = MIPI_DSI_GENERIC_PANEL_ID;
1054df0566a6SJani Nikula }
1055df0566a6SJani Nikula 
1056df0566a6SJani Nikula /* Find the sequence block and size for the given panel. */
1057df0566a6SJani Nikula static const u8 *
1058df0566a6SJani Nikula find_panel_sequence_block(const struct bdb_mipi_sequence *sequence,
1059df0566a6SJani Nikula 			  u16 panel_id, u32 *seq_size)
1060df0566a6SJani Nikula {
1061df0566a6SJani Nikula 	u32 total = get_blocksize(sequence);
1062df0566a6SJani Nikula 	const u8 *data = &sequence->data[0];
1063df0566a6SJani Nikula 	u8 current_id;
1064df0566a6SJani Nikula 	u32 current_size;
1065df0566a6SJani Nikula 	int header_size = sequence->version >= 3 ? 5 : 3;
1066df0566a6SJani Nikula 	int index = 0;
1067df0566a6SJani Nikula 	int i;
1068df0566a6SJani Nikula 
1069df0566a6SJani Nikula 	/* skip new block size */
1070df0566a6SJani Nikula 	if (sequence->version >= 3)
1071df0566a6SJani Nikula 		data += 4;
1072df0566a6SJani Nikula 
1073df0566a6SJani Nikula 	for (i = 0; i < MAX_MIPI_CONFIGURATIONS && index < total; i++) {
1074df0566a6SJani Nikula 		if (index + header_size > total) {
1075df0566a6SJani Nikula 			DRM_ERROR("Invalid sequence block (header)\n");
1076df0566a6SJani Nikula 			return NULL;
1077df0566a6SJani Nikula 		}
1078df0566a6SJani Nikula 
1079df0566a6SJani Nikula 		current_id = *(data + index);
1080df0566a6SJani Nikula 		if (sequence->version >= 3)
1081df0566a6SJani Nikula 			current_size = *((const u32 *)(data + index + 1));
1082df0566a6SJani Nikula 		else
1083df0566a6SJani Nikula 			current_size = *((const u16 *)(data + index + 1));
1084df0566a6SJani Nikula 
1085df0566a6SJani Nikula 		index += header_size;
1086df0566a6SJani Nikula 
1087df0566a6SJani Nikula 		if (index + current_size > total) {
1088df0566a6SJani Nikula 			DRM_ERROR("Invalid sequence block\n");
1089df0566a6SJani Nikula 			return NULL;
1090df0566a6SJani Nikula 		}
1091df0566a6SJani Nikula 
1092df0566a6SJani Nikula 		if (current_id == panel_id) {
1093df0566a6SJani Nikula 			*seq_size = current_size;
1094df0566a6SJani Nikula 			return data + index;
1095df0566a6SJani Nikula 		}
1096df0566a6SJani Nikula 
1097df0566a6SJani Nikula 		index += current_size;
1098df0566a6SJani Nikula 	}
1099df0566a6SJani Nikula 
1100df0566a6SJani Nikula 	DRM_ERROR("Sequence block detected but no valid configuration\n");
1101df0566a6SJani Nikula 
1102df0566a6SJani Nikula 	return NULL;
1103df0566a6SJani Nikula }
1104df0566a6SJani Nikula 
1105df0566a6SJani Nikula static int goto_next_sequence(const u8 *data, int index, int total)
1106df0566a6SJani Nikula {
1107df0566a6SJani Nikula 	u16 len;
1108df0566a6SJani Nikula 
1109df0566a6SJani Nikula 	/* Skip Sequence Byte. */
1110df0566a6SJani Nikula 	for (index = index + 1; index < total; index += len) {
1111df0566a6SJani Nikula 		u8 operation_byte = *(data + index);
1112df0566a6SJani Nikula 		index++;
1113df0566a6SJani Nikula 
1114df0566a6SJani Nikula 		switch (operation_byte) {
1115df0566a6SJani Nikula 		case MIPI_SEQ_ELEM_END:
1116df0566a6SJani Nikula 			return index;
1117df0566a6SJani Nikula 		case MIPI_SEQ_ELEM_SEND_PKT:
1118df0566a6SJani Nikula 			if (index + 4 > total)
1119df0566a6SJani Nikula 				return 0;
1120df0566a6SJani Nikula 
1121df0566a6SJani Nikula 			len = *((const u16 *)(data + index + 2)) + 4;
1122df0566a6SJani Nikula 			break;
1123df0566a6SJani Nikula 		case MIPI_SEQ_ELEM_DELAY:
1124df0566a6SJani Nikula 			len = 4;
1125df0566a6SJani Nikula 			break;
1126df0566a6SJani Nikula 		case MIPI_SEQ_ELEM_GPIO:
1127df0566a6SJani Nikula 			len = 2;
1128df0566a6SJani Nikula 			break;
1129df0566a6SJani Nikula 		case MIPI_SEQ_ELEM_I2C:
1130df0566a6SJani Nikula 			if (index + 7 > total)
1131df0566a6SJani Nikula 				return 0;
1132df0566a6SJani Nikula 			len = *(data + index + 6) + 7;
1133df0566a6SJani Nikula 			break;
1134df0566a6SJani Nikula 		default:
1135df0566a6SJani Nikula 			DRM_ERROR("Unknown operation byte\n");
1136df0566a6SJani Nikula 			return 0;
1137df0566a6SJani Nikula 		}
1138df0566a6SJani Nikula 	}
1139df0566a6SJani Nikula 
1140df0566a6SJani Nikula 	return 0;
1141df0566a6SJani Nikula }
1142df0566a6SJani Nikula 
1143df0566a6SJani Nikula static int goto_next_sequence_v3(const u8 *data, int index, int total)
1144df0566a6SJani Nikula {
1145df0566a6SJani Nikula 	int seq_end;
1146df0566a6SJani Nikula 	u16 len;
1147df0566a6SJani Nikula 	u32 size_of_sequence;
1148df0566a6SJani Nikula 
1149df0566a6SJani Nikula 	/*
1150df0566a6SJani Nikula 	 * Could skip sequence based on Size of Sequence alone, but also do some
1151df0566a6SJani Nikula 	 * checking on the structure.
1152df0566a6SJani Nikula 	 */
1153df0566a6SJani Nikula 	if (total < 5) {
1154df0566a6SJani Nikula 		DRM_ERROR("Too small sequence size\n");
1155df0566a6SJani Nikula 		return 0;
1156df0566a6SJani Nikula 	}
1157df0566a6SJani Nikula 
1158df0566a6SJani Nikula 	/* Skip Sequence Byte. */
1159df0566a6SJani Nikula 	index++;
1160df0566a6SJani Nikula 
1161df0566a6SJani Nikula 	/*
1162df0566a6SJani Nikula 	 * Size of Sequence. Excludes the Sequence Byte and the size itself,
1163df0566a6SJani Nikula 	 * includes MIPI_SEQ_ELEM_END byte, excludes the final MIPI_SEQ_END
1164df0566a6SJani Nikula 	 * byte.
1165df0566a6SJani Nikula 	 */
1166df0566a6SJani Nikula 	size_of_sequence = *((const u32 *)(data + index));
1167df0566a6SJani Nikula 	index += 4;
1168df0566a6SJani Nikula 
1169df0566a6SJani Nikula 	seq_end = index + size_of_sequence;
1170df0566a6SJani Nikula 	if (seq_end > total) {
1171df0566a6SJani Nikula 		DRM_ERROR("Invalid sequence size\n");
1172df0566a6SJani Nikula 		return 0;
1173df0566a6SJani Nikula 	}
1174df0566a6SJani Nikula 
1175df0566a6SJani Nikula 	for (; index < total; index += len) {
1176df0566a6SJani Nikula 		u8 operation_byte = *(data + index);
1177df0566a6SJani Nikula 		index++;
1178df0566a6SJani Nikula 
1179df0566a6SJani Nikula 		if (operation_byte == MIPI_SEQ_ELEM_END) {
1180df0566a6SJani Nikula 			if (index != seq_end) {
1181df0566a6SJani Nikula 				DRM_ERROR("Invalid element structure\n");
1182df0566a6SJani Nikula 				return 0;
1183df0566a6SJani Nikula 			}
1184df0566a6SJani Nikula 			return index;
1185df0566a6SJani Nikula 		}
1186df0566a6SJani Nikula 
1187df0566a6SJani Nikula 		len = *(data + index);
1188df0566a6SJani Nikula 		index++;
1189df0566a6SJani Nikula 
1190df0566a6SJani Nikula 		/*
1191df0566a6SJani Nikula 		 * FIXME: Would be nice to check elements like for v1/v2 in
1192df0566a6SJani Nikula 		 * goto_next_sequence() above.
1193df0566a6SJani Nikula 		 */
1194df0566a6SJani Nikula 		switch (operation_byte) {
1195df0566a6SJani Nikula 		case MIPI_SEQ_ELEM_SEND_PKT:
1196df0566a6SJani Nikula 		case MIPI_SEQ_ELEM_DELAY:
1197df0566a6SJani Nikula 		case MIPI_SEQ_ELEM_GPIO:
1198df0566a6SJani Nikula 		case MIPI_SEQ_ELEM_I2C:
1199df0566a6SJani Nikula 		case MIPI_SEQ_ELEM_SPI:
1200df0566a6SJani Nikula 		case MIPI_SEQ_ELEM_PMIC:
1201df0566a6SJani Nikula 			break;
1202df0566a6SJani Nikula 		default:
1203df0566a6SJani Nikula 			DRM_ERROR("Unknown operation byte %u\n",
1204df0566a6SJani Nikula 				  operation_byte);
1205df0566a6SJani Nikula 			break;
1206df0566a6SJani Nikula 		}
1207df0566a6SJani Nikula 	}
1208df0566a6SJani Nikula 
1209df0566a6SJani Nikula 	return 0;
1210df0566a6SJani Nikula }
1211df0566a6SJani Nikula 
1212df0566a6SJani Nikula /*
1213df0566a6SJani Nikula  * Get len of pre-fixed deassert fragment from a v1 init OTP sequence,
1214df0566a6SJani Nikula  * skip all delay + gpio operands and stop at the first DSI packet op.
1215df0566a6SJani Nikula  */
1216df0566a6SJani Nikula static int get_init_otp_deassert_fragment_len(struct drm_i915_private *dev_priv)
1217df0566a6SJani Nikula {
1218df0566a6SJani Nikula 	const u8 *data = dev_priv->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP];
1219df0566a6SJani Nikula 	int index, len;
1220df0566a6SJani Nikula 
1221df0566a6SJani Nikula 	if (WARN_ON(!data || dev_priv->vbt.dsi.seq_version != 1))
1222df0566a6SJani Nikula 		return 0;
1223df0566a6SJani Nikula 
1224df0566a6SJani Nikula 	/* index = 1 to skip sequence byte */
1225df0566a6SJani Nikula 	for (index = 1; data[index] != MIPI_SEQ_ELEM_END; index += len) {
1226df0566a6SJani Nikula 		switch (data[index]) {
1227df0566a6SJani Nikula 		case MIPI_SEQ_ELEM_SEND_PKT:
1228df0566a6SJani Nikula 			return index == 1 ? 0 : index;
1229df0566a6SJani Nikula 		case MIPI_SEQ_ELEM_DELAY:
1230df0566a6SJani Nikula 			len = 5; /* 1 byte for operand + uint32 */
1231df0566a6SJani Nikula 			break;
1232df0566a6SJani Nikula 		case MIPI_SEQ_ELEM_GPIO:
1233df0566a6SJani Nikula 			len = 3; /* 1 byte for op, 1 for gpio_nr, 1 for value */
1234df0566a6SJani Nikula 			break;
1235df0566a6SJani Nikula 		default:
1236df0566a6SJani Nikula 			return 0;
1237df0566a6SJani Nikula 		}
1238df0566a6SJani Nikula 	}
1239df0566a6SJani Nikula 
1240df0566a6SJani Nikula 	return 0;
1241df0566a6SJani Nikula }
1242df0566a6SJani Nikula 
1243df0566a6SJani Nikula /*
1244df0566a6SJani Nikula  * Some v1 VBT MIPI sequences do the deassert in the init OTP sequence.
1245df0566a6SJani Nikula  * The deassert must be done before calling intel_dsi_device_ready, so for
1246df0566a6SJani Nikula  * these devices we split the init OTP sequence into a deassert sequence and
1247df0566a6SJani Nikula  * the actual init OTP part.
1248df0566a6SJani Nikula  */
1249df0566a6SJani Nikula static void fixup_mipi_sequences(struct drm_i915_private *dev_priv)
1250df0566a6SJani Nikula {
1251df0566a6SJani Nikula 	u8 *init_otp;
1252df0566a6SJani Nikula 	int len;
1253df0566a6SJani Nikula 
1254df0566a6SJani Nikula 	/* Limit this to VLV for now. */
1255df0566a6SJani Nikula 	if (!IS_VALLEYVIEW(dev_priv))
1256df0566a6SJani Nikula 		return;
1257df0566a6SJani Nikula 
1258df0566a6SJani Nikula 	/* Limit this to v1 vid-mode sequences */
1259df0566a6SJani Nikula 	if (dev_priv->vbt.dsi.config->is_cmd_mode ||
1260df0566a6SJani Nikula 	    dev_priv->vbt.dsi.seq_version != 1)
1261df0566a6SJani Nikula 		return;
1262df0566a6SJani Nikula 
1263df0566a6SJani Nikula 	/* Only do this if there are otp and assert seqs and no deassert seq */
1264df0566a6SJani Nikula 	if (!dev_priv->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP] ||
1265df0566a6SJani Nikula 	    !dev_priv->vbt.dsi.sequence[MIPI_SEQ_ASSERT_RESET] ||
1266df0566a6SJani Nikula 	    dev_priv->vbt.dsi.sequence[MIPI_SEQ_DEASSERT_RESET])
1267df0566a6SJani Nikula 		return;
1268df0566a6SJani Nikula 
1269df0566a6SJani Nikula 	/* The deassert-sequence ends at the first DSI packet */
1270df0566a6SJani Nikula 	len = get_init_otp_deassert_fragment_len(dev_priv);
1271df0566a6SJani Nikula 	if (!len)
1272df0566a6SJani Nikula 		return;
1273df0566a6SJani Nikula 
1274df0566a6SJani Nikula 	DRM_DEBUG_KMS("Using init OTP fragment to deassert reset\n");
1275df0566a6SJani Nikula 
1276df0566a6SJani Nikula 	/* Copy the fragment, update seq byte and terminate it */
1277df0566a6SJani Nikula 	init_otp = (u8 *)dev_priv->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP];
1278df0566a6SJani Nikula 	dev_priv->vbt.dsi.deassert_seq = kmemdup(init_otp, len + 1, GFP_KERNEL);
1279df0566a6SJani Nikula 	if (!dev_priv->vbt.dsi.deassert_seq)
1280df0566a6SJani Nikula 		return;
1281df0566a6SJani Nikula 	dev_priv->vbt.dsi.deassert_seq[0] = MIPI_SEQ_DEASSERT_RESET;
1282df0566a6SJani Nikula 	dev_priv->vbt.dsi.deassert_seq[len] = MIPI_SEQ_ELEM_END;
1283df0566a6SJani Nikula 	/* Use the copy for deassert */
1284df0566a6SJani Nikula 	dev_priv->vbt.dsi.sequence[MIPI_SEQ_DEASSERT_RESET] =
1285df0566a6SJani Nikula 		dev_priv->vbt.dsi.deassert_seq;
1286df0566a6SJani Nikula 	/* Replace the last byte of the fragment with init OTP seq byte */
1287df0566a6SJani Nikula 	init_otp[len - 1] = MIPI_SEQ_INIT_OTP;
1288df0566a6SJani Nikula 	/* And make MIPI_MIPI_SEQ_INIT_OTP point to it */
1289df0566a6SJani Nikula 	dev_priv->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP] = init_otp + len - 1;
1290df0566a6SJani Nikula }
1291df0566a6SJani Nikula 
1292df0566a6SJani Nikula static void
1293df0566a6SJani Nikula parse_mipi_sequence(struct drm_i915_private *dev_priv,
1294df0566a6SJani Nikula 		    const struct bdb_header *bdb)
1295df0566a6SJani Nikula {
1296df0566a6SJani Nikula 	int panel_type = dev_priv->vbt.panel_type;
1297df0566a6SJani Nikula 	const struct bdb_mipi_sequence *sequence;
1298df0566a6SJani Nikula 	const u8 *seq_data;
1299df0566a6SJani Nikula 	u32 seq_size;
1300df0566a6SJani Nikula 	u8 *data;
1301df0566a6SJani Nikula 	int index = 0;
1302df0566a6SJani Nikula 
1303df0566a6SJani Nikula 	/* Only our generic panel driver uses the sequence block. */
1304df0566a6SJani Nikula 	if (dev_priv->vbt.dsi.panel_id != MIPI_DSI_GENERIC_PANEL_ID)
1305df0566a6SJani Nikula 		return;
1306df0566a6SJani Nikula 
1307df0566a6SJani Nikula 	sequence = find_section(bdb, BDB_MIPI_SEQUENCE);
1308df0566a6SJani Nikula 	if (!sequence) {
1309df0566a6SJani Nikula 		DRM_DEBUG_KMS("No MIPI Sequence found, parsing complete\n");
1310df0566a6SJani Nikula 		return;
1311df0566a6SJani Nikula 	}
1312df0566a6SJani Nikula 
1313df0566a6SJani Nikula 	/* Fail gracefully for forward incompatible sequence block. */
1314df0566a6SJani Nikula 	if (sequence->version >= 4) {
1315df0566a6SJani Nikula 		DRM_ERROR("Unable to parse MIPI Sequence Block v%u\n",
1316df0566a6SJani Nikula 			  sequence->version);
1317df0566a6SJani Nikula 		return;
1318df0566a6SJani Nikula 	}
1319df0566a6SJani Nikula 
1320df0566a6SJani Nikula 	DRM_DEBUG_DRIVER("Found MIPI sequence block v%u\n", sequence->version);
1321df0566a6SJani Nikula 
1322df0566a6SJani Nikula 	seq_data = find_panel_sequence_block(sequence, panel_type, &seq_size);
1323df0566a6SJani Nikula 	if (!seq_data)
1324df0566a6SJani Nikula 		return;
1325df0566a6SJani Nikula 
1326df0566a6SJani Nikula 	data = kmemdup(seq_data, seq_size, GFP_KERNEL);
1327df0566a6SJani Nikula 	if (!data)
1328df0566a6SJani Nikula 		return;
1329df0566a6SJani Nikula 
1330df0566a6SJani Nikula 	/* Parse the sequences, store pointers to each sequence. */
1331df0566a6SJani Nikula 	for (;;) {
1332df0566a6SJani Nikula 		u8 seq_id = *(data + index);
1333df0566a6SJani Nikula 		if (seq_id == MIPI_SEQ_END)
1334df0566a6SJani Nikula 			break;
1335df0566a6SJani Nikula 
1336df0566a6SJani Nikula 		if (seq_id >= MIPI_SEQ_MAX) {
1337df0566a6SJani Nikula 			DRM_ERROR("Unknown sequence %u\n", seq_id);
1338df0566a6SJani Nikula 			goto err;
1339df0566a6SJani Nikula 		}
1340df0566a6SJani Nikula 
1341df0566a6SJani Nikula 		/* Log about presence of sequences we won't run. */
1342df0566a6SJani Nikula 		if (seq_id == MIPI_SEQ_TEAR_ON || seq_id == MIPI_SEQ_TEAR_OFF)
1343df0566a6SJani Nikula 			DRM_DEBUG_KMS("Unsupported sequence %u\n", seq_id);
1344df0566a6SJani Nikula 
1345df0566a6SJani Nikula 		dev_priv->vbt.dsi.sequence[seq_id] = data + index;
1346df0566a6SJani Nikula 
1347df0566a6SJani Nikula 		if (sequence->version >= 3)
1348df0566a6SJani Nikula 			index = goto_next_sequence_v3(data, index, seq_size);
1349df0566a6SJani Nikula 		else
1350df0566a6SJani Nikula 			index = goto_next_sequence(data, index, seq_size);
1351df0566a6SJani Nikula 		if (!index) {
1352df0566a6SJani Nikula 			DRM_ERROR("Invalid sequence %u\n", seq_id);
1353df0566a6SJani Nikula 			goto err;
1354df0566a6SJani Nikula 		}
1355df0566a6SJani Nikula 	}
1356df0566a6SJani Nikula 
1357df0566a6SJani Nikula 	dev_priv->vbt.dsi.data = data;
1358df0566a6SJani Nikula 	dev_priv->vbt.dsi.size = seq_size;
1359df0566a6SJani Nikula 	dev_priv->vbt.dsi.seq_version = sequence->version;
1360df0566a6SJani Nikula 
1361df0566a6SJani Nikula 	fixup_mipi_sequences(dev_priv);
1362df0566a6SJani Nikula 
1363df0566a6SJani Nikula 	DRM_DEBUG_DRIVER("MIPI related VBT parsing complete\n");
1364df0566a6SJani Nikula 	return;
1365df0566a6SJani Nikula 
1366df0566a6SJani Nikula err:
1367df0566a6SJani Nikula 	kfree(data);
1368df0566a6SJani Nikula 	memset(dev_priv->vbt.dsi.sequence, 0, sizeof(dev_priv->vbt.dsi.sequence));
1369df0566a6SJani Nikula }
1370df0566a6SJani Nikula 
13716e0d46e9SJani Nikula static void
13726e0d46e9SJani Nikula parse_compression_parameters(struct drm_i915_private *i915,
13736e0d46e9SJani Nikula 			     const struct bdb_header *bdb)
13746e0d46e9SJani Nikula {
13756e0d46e9SJani Nikula 	const struct bdb_compression_parameters *params;
13766e0d46e9SJani Nikula 	struct display_device_data *devdata;
13776e0d46e9SJani Nikula 	const struct child_device_config *child;
13786e0d46e9SJani Nikula 	u16 block_size;
13796e0d46e9SJani Nikula 	int index;
13806e0d46e9SJani Nikula 
13816e0d46e9SJani Nikula 	if (bdb->version < 198)
13826e0d46e9SJani Nikula 		return;
13836e0d46e9SJani Nikula 
13846e0d46e9SJani Nikula 	params = find_section(bdb, BDB_COMPRESSION_PARAMETERS);
13856e0d46e9SJani Nikula 	if (params) {
13866e0d46e9SJani Nikula 		/* Sanity checks */
13876e0d46e9SJani Nikula 		if (params->entry_size != sizeof(params->data[0])) {
13886e0d46e9SJani Nikula 			DRM_DEBUG_KMS("VBT: unsupported compression param entry size\n");
13896e0d46e9SJani Nikula 			return;
13906e0d46e9SJani Nikula 		}
13916e0d46e9SJani Nikula 
13926e0d46e9SJani Nikula 		block_size = get_blocksize(params);
13936e0d46e9SJani Nikula 		if (block_size < sizeof(*params)) {
13946e0d46e9SJani Nikula 			DRM_DEBUG_KMS("VBT: expected 16 compression param entries\n");
13956e0d46e9SJani Nikula 			return;
13966e0d46e9SJani Nikula 		}
13976e0d46e9SJani Nikula 	}
13986e0d46e9SJani Nikula 
13996e0d46e9SJani Nikula 	list_for_each_entry(devdata, &i915->vbt.display_devices, node) {
14006e0d46e9SJani Nikula 		child = &devdata->child;
14016e0d46e9SJani Nikula 
14026e0d46e9SJani Nikula 		if (!child->compression_enable)
14036e0d46e9SJani Nikula 			continue;
14046e0d46e9SJani Nikula 
14056e0d46e9SJani Nikula 		if (!params) {
14066e0d46e9SJani Nikula 			DRM_DEBUG_KMS("VBT: compression params not available\n");
14076e0d46e9SJani Nikula 			continue;
14086e0d46e9SJani Nikula 		}
14096e0d46e9SJani Nikula 
14106e0d46e9SJani Nikula 		if (child->compression_method_cps) {
14116e0d46e9SJani Nikula 			DRM_DEBUG_KMS("VBT: CPS compression not supported\n");
14126e0d46e9SJani Nikula 			continue;
14136e0d46e9SJani Nikula 		}
14146e0d46e9SJani Nikula 
14156e0d46e9SJani Nikula 		index = child->compression_structure_index;
14166e0d46e9SJani Nikula 
14176e0d46e9SJani Nikula 		devdata->dsc = kmemdup(&params->data[index],
14186e0d46e9SJani Nikula 				       sizeof(*devdata->dsc), GFP_KERNEL);
14196e0d46e9SJani Nikula 	}
14206e0d46e9SJani Nikula }
14216e0d46e9SJani Nikula 
1422df0566a6SJani Nikula static u8 translate_iboost(u8 val)
1423df0566a6SJani Nikula {
1424df0566a6SJani Nikula 	static const u8 mapping[] = { 1, 3, 7 }; /* See VBT spec */
1425df0566a6SJani Nikula 
1426df0566a6SJani Nikula 	if (val >= ARRAY_SIZE(mapping)) {
1427df0566a6SJani Nikula 		DRM_DEBUG_KMS("Unsupported I_boost value found in VBT (%d), display may not work properly\n", val);
1428df0566a6SJani Nikula 		return 0;
1429df0566a6SJani Nikula 	}
1430df0566a6SJani Nikula 	return mapping[val];
1431df0566a6SJani Nikula }
1432df0566a6SJani Nikula 
1433df0566a6SJani Nikula static enum port get_port_by_ddc_pin(struct drm_i915_private *i915, u8 ddc_pin)
1434df0566a6SJani Nikula {
1435df0566a6SJani Nikula 	const struct ddi_vbt_port_info *info;
1436df0566a6SJani Nikula 	enum port port;
1437df0566a6SJani Nikula 
1438c4a774c4SJani Nikula 	for_each_port(port) {
1439df0566a6SJani Nikula 		info = &i915->vbt.ddi_port_info[port];
1440df0566a6SJani Nikula 
1441df0566a6SJani Nikula 		if (info->child && ddc_pin == info->alternate_ddc_pin)
1442df0566a6SJani Nikula 			return port;
1443df0566a6SJani Nikula 	}
1444df0566a6SJani Nikula 
1445df0566a6SJani Nikula 	return PORT_NONE;
1446df0566a6SJani Nikula }
1447df0566a6SJani Nikula 
1448df0566a6SJani Nikula static void sanitize_ddc_pin(struct drm_i915_private *dev_priv,
1449df0566a6SJani Nikula 			     enum port port)
1450df0566a6SJani Nikula {
1451df0566a6SJani Nikula 	struct ddi_vbt_port_info *info = &dev_priv->vbt.ddi_port_info[port];
1452df0566a6SJani Nikula 	enum port p;
1453df0566a6SJani Nikula 
1454df0566a6SJani Nikula 	if (!info->alternate_ddc_pin)
1455df0566a6SJani Nikula 		return;
1456df0566a6SJani Nikula 
1457df0566a6SJani Nikula 	p = get_port_by_ddc_pin(dev_priv, info->alternate_ddc_pin);
1458df0566a6SJani Nikula 	if (p != PORT_NONE) {
1459df0566a6SJani Nikula 		DRM_DEBUG_KMS("port %c trying to use the same DDC pin (0x%x) as port %c, "
1460df0566a6SJani Nikula 			      "disabling port %c DVI/HDMI support\n",
1461df0566a6SJani Nikula 			      port_name(port), info->alternate_ddc_pin,
146241e35ffbSVille Syrjälä 			      port_name(p), port_name(p));
1463df0566a6SJani Nikula 
1464df0566a6SJani Nikula 		/*
1465df0566a6SJani Nikula 		 * If we have multiple ports supposedly sharing the
1466df0566a6SJani Nikula 		 * pin, then dvi/hdmi couldn't exist on the shared
1467df0566a6SJani Nikula 		 * port. Otherwise they share the same ddc bin and
1468df0566a6SJani Nikula 		 * system couldn't communicate with them separately.
1469df0566a6SJani Nikula 		 *
147041e35ffbSVille Syrjälä 		 * Give inverse child device order the priority,
147141e35ffbSVille Syrjälä 		 * last one wins. Yes, there are real machines
147241e35ffbSVille Syrjälä 		 * (eg. Asrock B250M-HDV) where VBT has both
147341e35ffbSVille Syrjälä 		 * port A and port E with the same AUX ch and
147441e35ffbSVille Syrjälä 		 * we must pick port E :(
1475df0566a6SJani Nikula 		 */
147641e35ffbSVille Syrjälä 		info = &dev_priv->vbt.ddi_port_info[p];
147741e35ffbSVille Syrjälä 
1478df0566a6SJani Nikula 		info->supports_dvi = false;
1479df0566a6SJani Nikula 		info->supports_hdmi = false;
1480df0566a6SJani Nikula 		info->alternate_ddc_pin = 0;
1481df0566a6SJani Nikula 	}
1482df0566a6SJani Nikula }
1483df0566a6SJani Nikula 
1484df0566a6SJani Nikula static enum port get_port_by_aux_ch(struct drm_i915_private *i915, u8 aux_ch)
1485df0566a6SJani Nikula {
1486df0566a6SJani Nikula 	const struct ddi_vbt_port_info *info;
1487df0566a6SJani Nikula 	enum port port;
1488df0566a6SJani Nikula 
1489c4a774c4SJani Nikula 	for_each_port(port) {
1490df0566a6SJani Nikula 		info = &i915->vbt.ddi_port_info[port];
1491df0566a6SJani Nikula 
1492df0566a6SJani Nikula 		if (info->child && aux_ch == info->alternate_aux_channel)
1493df0566a6SJani Nikula 			return port;
1494df0566a6SJani Nikula 	}
1495df0566a6SJani Nikula 
1496df0566a6SJani Nikula 	return PORT_NONE;
1497df0566a6SJani Nikula }
1498df0566a6SJani Nikula 
1499df0566a6SJani Nikula static void sanitize_aux_ch(struct drm_i915_private *dev_priv,
1500df0566a6SJani Nikula 			    enum port port)
1501df0566a6SJani Nikula {
1502df0566a6SJani Nikula 	struct ddi_vbt_port_info *info = &dev_priv->vbt.ddi_port_info[port];
1503df0566a6SJani Nikula 	enum port p;
1504df0566a6SJani Nikula 
1505df0566a6SJani Nikula 	if (!info->alternate_aux_channel)
1506df0566a6SJani Nikula 		return;
1507df0566a6SJani Nikula 
1508df0566a6SJani Nikula 	p = get_port_by_aux_ch(dev_priv, info->alternate_aux_channel);
1509df0566a6SJani Nikula 	if (p != PORT_NONE) {
1510df0566a6SJani Nikula 		DRM_DEBUG_KMS("port %c trying to use the same AUX CH (0x%x) as port %c, "
1511df0566a6SJani Nikula 			      "disabling port %c DP support\n",
1512df0566a6SJani Nikula 			      port_name(port), info->alternate_aux_channel,
151341e35ffbSVille Syrjälä 			      port_name(p), port_name(p));
1514df0566a6SJani Nikula 
1515df0566a6SJani Nikula 		/*
1516df0566a6SJani Nikula 		 * If we have multiple ports supposedlt sharing the
1517df0566a6SJani Nikula 		 * aux channel, then DP couldn't exist on the shared
1518df0566a6SJani Nikula 		 * port. Otherwise they share the same aux channel
1519df0566a6SJani Nikula 		 * and system couldn't communicate with them separately.
1520df0566a6SJani Nikula 		 *
152141e35ffbSVille Syrjälä 		 * Give inverse child device order the priority,
152241e35ffbSVille Syrjälä 		 * last one wins. Yes, there are real machines
152341e35ffbSVille Syrjälä 		 * (eg. Asrock B250M-HDV) where VBT has both
152441e35ffbSVille Syrjälä 		 * port A and port E with the same AUX ch and
152541e35ffbSVille Syrjälä 		 * we must pick port E :(
1526df0566a6SJani Nikula 		 */
152741e35ffbSVille Syrjälä 		info = &dev_priv->vbt.ddi_port_info[p];
152841e35ffbSVille Syrjälä 
1529df0566a6SJani Nikula 		info->supports_dp = false;
1530df0566a6SJani Nikula 		info->alternate_aux_channel = 0;
1531df0566a6SJani Nikula 	}
1532df0566a6SJani Nikula }
1533df0566a6SJani Nikula 
1534df0566a6SJani Nikula static const u8 cnp_ddc_pin_map[] = {
1535df0566a6SJani Nikula 	[0] = 0, /* N/A */
1536df0566a6SJani Nikula 	[DDC_BUS_DDI_B] = GMBUS_PIN_1_BXT,
1537df0566a6SJani Nikula 	[DDC_BUS_DDI_C] = GMBUS_PIN_2_BXT,
1538df0566a6SJani Nikula 	[DDC_BUS_DDI_D] = GMBUS_PIN_4_CNP, /* sic */
1539df0566a6SJani Nikula 	[DDC_BUS_DDI_F] = GMBUS_PIN_3_BXT, /* sic */
1540df0566a6SJani Nikula };
1541df0566a6SJani Nikula 
1542df0566a6SJani Nikula static const u8 icp_ddc_pin_map[] = {
1543df0566a6SJani Nikula 	[ICL_DDC_BUS_DDI_A] = GMBUS_PIN_1_BXT,
1544df0566a6SJani Nikula 	[ICL_DDC_BUS_DDI_B] = GMBUS_PIN_2_BXT,
1545d757535eSMahesh Kumar 	[TGL_DDC_BUS_DDI_C] = GMBUS_PIN_3_BXT,
1546d757535eSMahesh Kumar 	[ICL_DDC_BUS_PORT_1] = GMBUS_PIN_9_TC1_ICP,
1547d757535eSMahesh Kumar 	[ICL_DDC_BUS_PORT_2] = GMBUS_PIN_10_TC2_ICP,
1548d757535eSMahesh Kumar 	[ICL_DDC_BUS_PORT_3] = GMBUS_PIN_11_TC3_ICP,
1549d757535eSMahesh Kumar 	[ICL_DDC_BUS_PORT_4] = GMBUS_PIN_12_TC4_ICP,
1550d757535eSMahesh Kumar 	[TGL_DDC_BUS_PORT_5] = GMBUS_PIN_13_TC5_TGP,
1551d757535eSMahesh Kumar 	[TGL_DDC_BUS_PORT_6] = GMBUS_PIN_14_TC6_TGP,
1552d757535eSMahesh Kumar };
1553d757535eSMahesh Kumar 
1554df0566a6SJani Nikula static u8 map_ddc_pin(struct drm_i915_private *dev_priv, u8 vbt_pin)
1555df0566a6SJani Nikula {
1556df0566a6SJani Nikula 	const u8 *ddc_pin_map;
1557df0566a6SJani Nikula 	int n_entries;
1558df0566a6SJani Nikula 
15595a6b7ef6SMatt Roper 	if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) {
1560df0566a6SJani Nikula 		ddc_pin_map = icp_ddc_pin_map;
1561df0566a6SJani Nikula 		n_entries = ARRAY_SIZE(icp_ddc_pin_map);
1562df0566a6SJani Nikula 	} else if (HAS_PCH_CNP(dev_priv)) {
1563df0566a6SJani Nikula 		ddc_pin_map = cnp_ddc_pin_map;
1564df0566a6SJani Nikula 		n_entries = ARRAY_SIZE(cnp_ddc_pin_map);
1565df0566a6SJani Nikula 	} else {
1566df0566a6SJani Nikula 		/* Assuming direct map */
1567df0566a6SJani Nikula 		return vbt_pin;
1568df0566a6SJani Nikula 	}
1569df0566a6SJani Nikula 
1570df0566a6SJani Nikula 	if (vbt_pin < n_entries && ddc_pin_map[vbt_pin] != 0)
1571df0566a6SJani Nikula 		return ddc_pin_map[vbt_pin];
1572df0566a6SJani Nikula 
1573df0566a6SJani Nikula 	DRM_DEBUG_KMS("Ignoring alternate pin: VBT claims DDC pin %d, which is not valid for this platform\n",
1574df0566a6SJani Nikula 		      vbt_pin);
1575df0566a6SJani Nikula 	return 0;
1576df0566a6SJani Nikula }
1577df0566a6SJani Nikula 
1578df0566a6SJani Nikula static enum port dvo_port_to_port(u8 dvo_port)
1579df0566a6SJani Nikula {
1580df0566a6SJani Nikula 	/*
1581df0566a6SJani Nikula 	 * Each DDI port can have more than one value on the "DVO Port" field,
1582df0566a6SJani Nikula 	 * so look for all the possible values for each port.
1583df0566a6SJani Nikula 	 */
1584df0566a6SJani Nikula 	static const int dvo_ports[][3] = {
1585df0566a6SJani Nikula 		[PORT_A] = { DVO_PORT_HDMIA, DVO_PORT_DPA, -1},
1586df0566a6SJani Nikula 		[PORT_B] = { DVO_PORT_HDMIB, DVO_PORT_DPB, -1},
1587df0566a6SJani Nikula 		[PORT_C] = { DVO_PORT_HDMIC, DVO_PORT_DPC, -1},
1588df0566a6SJani Nikula 		[PORT_D] = { DVO_PORT_HDMID, DVO_PORT_DPD, -1},
1589df0566a6SJani Nikula 		[PORT_E] = { DVO_PORT_CRT, DVO_PORT_HDMIE, DVO_PORT_DPE},
1590df0566a6SJani Nikula 		[PORT_F] = { DVO_PORT_HDMIF, DVO_PORT_DPF, -1},
1591eb8de23cSKhaled Almahallawy 		[PORT_G] = { DVO_PORT_HDMIG, DVO_PORT_DPG, -1},
1592df0566a6SJani Nikula 	};
1593df0566a6SJani Nikula 	enum port port;
1594df0566a6SJani Nikula 	int i;
1595df0566a6SJani Nikula 
1596df0566a6SJani Nikula 	for (port = PORT_A; port < ARRAY_SIZE(dvo_ports); port++) {
1597df0566a6SJani Nikula 		for (i = 0; i < ARRAY_SIZE(dvo_ports[port]); i++) {
1598df0566a6SJani Nikula 			if (dvo_ports[port][i] == -1)
1599df0566a6SJani Nikula 				break;
1600df0566a6SJani Nikula 
1601df0566a6SJani Nikula 			if (dvo_port == dvo_ports[port][i])
1602df0566a6SJani Nikula 				return port;
1603df0566a6SJani Nikula 		}
1604df0566a6SJani Nikula 	}
1605df0566a6SJani Nikula 
1606df0566a6SJani Nikula 	return PORT_NONE;
1607df0566a6SJani Nikula }
1608df0566a6SJani Nikula 
1609df0566a6SJani Nikula static void parse_ddi_port(struct drm_i915_private *dev_priv,
1610d1dad6f4SJani Nikula 			   struct display_device_data *devdata,
1611df0566a6SJani Nikula 			   u8 bdb_version)
1612df0566a6SJani Nikula {
1613d1dad6f4SJani Nikula 	const struct child_device_config *child = &devdata->child;
1614df0566a6SJani Nikula 	struct ddi_vbt_port_info *info;
1615df0566a6SJani Nikula 	bool is_dvi, is_hdmi, is_dp, is_edp, is_crt;
1616df0566a6SJani Nikula 	enum port port;
1617df0566a6SJani Nikula 
1618df0566a6SJani Nikula 	port = dvo_port_to_port(child->dvo_port);
1619df0566a6SJani Nikula 	if (port == PORT_NONE)
1620df0566a6SJani Nikula 		return;
1621df0566a6SJani Nikula 
1622df0566a6SJani Nikula 	info = &dev_priv->vbt.ddi_port_info[port];
1623df0566a6SJani Nikula 
1624df0566a6SJani Nikula 	if (info->child) {
1625df0566a6SJani Nikula 		DRM_DEBUG_KMS("More than one child device for port %c in VBT, using the first.\n",
1626df0566a6SJani Nikula 			      port_name(port));
1627df0566a6SJani Nikula 		return;
1628df0566a6SJani Nikula 	}
1629df0566a6SJani Nikula 
1630df0566a6SJani Nikula 	is_dvi = child->device_type & DEVICE_TYPE_TMDS_DVI_SIGNALING;
1631df0566a6SJani Nikula 	is_dp = child->device_type & DEVICE_TYPE_DISPLAYPORT_OUTPUT;
1632df0566a6SJani Nikula 	is_crt = child->device_type & DEVICE_TYPE_ANALOG_OUTPUT;
1633df0566a6SJani Nikula 	is_hdmi = is_dvi && (child->device_type & DEVICE_TYPE_NOT_HDMI_OUTPUT) == 0;
1634df0566a6SJani Nikula 	is_edp = is_dp && (child->device_type & DEVICE_TYPE_INTERNAL_CONNECTOR);
1635df0566a6SJani Nikula 
1636523e0cc8SLucas De Marchi 	if (port == PORT_A && is_dvi && INTEL_GEN(dev_priv) < 12) {
1637df0566a6SJani Nikula 		DRM_DEBUG_KMS("VBT claims port A supports DVI%s, ignoring\n",
1638df0566a6SJani Nikula 			      is_hdmi ? "/HDMI" : "");
1639df0566a6SJani Nikula 		is_dvi = false;
1640df0566a6SJani Nikula 		is_hdmi = false;
1641df0566a6SJani Nikula 	}
1642df0566a6SJani Nikula 
1643df0566a6SJani Nikula 	info->supports_dvi = is_dvi;
1644df0566a6SJani Nikula 	info->supports_hdmi = is_hdmi;
1645df0566a6SJani Nikula 	info->supports_dp = is_dp;
1646df0566a6SJani Nikula 	info->supports_edp = is_edp;
1647df0566a6SJani Nikula 
1648df0566a6SJani Nikula 	if (bdb_version >= 195)
1649df0566a6SJani Nikula 		info->supports_typec_usb = child->dp_usb_type_c;
1650df0566a6SJani Nikula 
1651df0566a6SJani Nikula 	if (bdb_version >= 209)
1652df0566a6SJani Nikula 		info->supports_tbt = child->tbt;
1653df0566a6SJani Nikula 
16546e0d46e9SJani Nikula 	DRM_DEBUG_KMS("Port %c VBT info: CRT:%d DVI:%d HDMI:%d DP:%d eDP:%d LSPCON:%d USB-Type-C:%d TBT:%d DSC:%d\n",
1655df0566a6SJani Nikula 		      port_name(port), is_crt, is_dvi, is_hdmi, is_dp, is_edp,
1656df0566a6SJani Nikula 		      HAS_LSPCON(dev_priv) && child->lspcon,
16576e0d46e9SJani Nikula 		      info->supports_typec_usb, info->supports_tbt,
16586e0d46e9SJani Nikula 		      devdata->dsc != NULL);
1659df0566a6SJani Nikula 
1660df0566a6SJani Nikula 	if (is_dvi) {
1661df0566a6SJani Nikula 		u8 ddc_pin;
1662df0566a6SJani Nikula 
1663df0566a6SJani Nikula 		ddc_pin = map_ddc_pin(dev_priv, child->ddc_pin);
1664df0566a6SJani Nikula 		if (intel_gmbus_is_valid_pin(dev_priv, ddc_pin)) {
1665df0566a6SJani Nikula 			info->alternate_ddc_pin = ddc_pin;
1666df0566a6SJani Nikula 			sanitize_ddc_pin(dev_priv, port);
1667df0566a6SJani Nikula 		} else {
1668df0566a6SJani Nikula 			DRM_DEBUG_KMS("Port %c has invalid DDC pin %d, "
1669df0566a6SJani Nikula 				      "sticking to defaults\n",
1670df0566a6SJani Nikula 				      port_name(port), ddc_pin);
1671df0566a6SJani Nikula 		}
1672df0566a6SJani Nikula 	}
1673df0566a6SJani Nikula 
1674df0566a6SJani Nikula 	if (is_dp) {
1675df0566a6SJani Nikula 		info->alternate_aux_channel = child->aux_channel;
1676df0566a6SJani Nikula 
1677df0566a6SJani Nikula 		sanitize_aux_ch(dev_priv, port);
1678df0566a6SJani Nikula 	}
1679df0566a6SJani Nikula 
1680df0566a6SJani Nikula 	if (bdb_version >= 158) {
1681df0566a6SJani Nikula 		/* The VBT HDMI level shift values match the table we have. */
1682df0566a6SJani Nikula 		u8 hdmi_level_shift = child->hdmi_level_shifter_value;
1683df0566a6SJani Nikula 		DRM_DEBUG_KMS("VBT HDMI level shift for port %c: %d\n",
1684df0566a6SJani Nikula 			      port_name(port),
1685df0566a6SJani Nikula 			      hdmi_level_shift);
1686df0566a6SJani Nikula 		info->hdmi_level_shift = hdmi_level_shift;
16877a0073d6SJani Nikula 		info->hdmi_level_shift_set = true;
1688df0566a6SJani Nikula 	}
1689df0566a6SJani Nikula 
1690df0566a6SJani Nikula 	if (bdb_version >= 204) {
1691df0566a6SJani Nikula 		int max_tmds_clock;
1692df0566a6SJani Nikula 
1693df0566a6SJani Nikula 		switch (child->hdmi_max_data_rate) {
1694df0566a6SJani Nikula 		default:
1695df0566a6SJani Nikula 			MISSING_CASE(child->hdmi_max_data_rate);
1696df0566a6SJani Nikula 			/* fall through */
1697df0566a6SJani Nikula 		case HDMI_MAX_DATA_RATE_PLATFORM:
1698df0566a6SJani Nikula 			max_tmds_clock = 0;
1699df0566a6SJani Nikula 			break;
1700df0566a6SJani Nikula 		case HDMI_MAX_DATA_RATE_297:
1701df0566a6SJani Nikula 			max_tmds_clock = 297000;
1702df0566a6SJani Nikula 			break;
1703df0566a6SJani Nikula 		case HDMI_MAX_DATA_RATE_165:
1704df0566a6SJani Nikula 			max_tmds_clock = 165000;
1705df0566a6SJani Nikula 			break;
1706df0566a6SJani Nikula 		}
1707df0566a6SJani Nikula 
1708df0566a6SJani Nikula 		if (max_tmds_clock)
1709df0566a6SJani Nikula 			DRM_DEBUG_KMS("VBT HDMI max TMDS clock for port %c: %d kHz\n",
1710df0566a6SJani Nikula 				      port_name(port), max_tmds_clock);
1711df0566a6SJani Nikula 		info->max_tmds_clock = max_tmds_clock;
1712df0566a6SJani Nikula 	}
1713df0566a6SJani Nikula 
1714df0566a6SJani Nikula 	/* Parse the I_boost config for SKL and above */
1715df0566a6SJani Nikula 	if (bdb_version >= 196 && child->iboost) {
1716df0566a6SJani Nikula 		info->dp_boost_level = translate_iboost(child->dp_iboost_level);
1717df0566a6SJani Nikula 		DRM_DEBUG_KMS("VBT (e)DP boost level for port %c: %d\n",
1718df0566a6SJani Nikula 			      port_name(port), info->dp_boost_level);
1719df0566a6SJani Nikula 		info->hdmi_boost_level = translate_iboost(child->hdmi_iboost_level);
1720df0566a6SJani Nikula 		DRM_DEBUG_KMS("VBT HDMI boost level for port %c: %d\n",
1721df0566a6SJani Nikula 			      port_name(port), info->hdmi_boost_level);
1722df0566a6SJani Nikula 	}
1723df0566a6SJani Nikula 
1724df0566a6SJani Nikula 	/* DP max link rate for CNL+ */
1725df0566a6SJani Nikula 	if (bdb_version >= 216) {
1726df0566a6SJani Nikula 		switch (child->dp_max_link_rate) {
1727df0566a6SJani Nikula 		default:
1728df0566a6SJani Nikula 		case VBT_DP_MAX_LINK_RATE_HBR3:
1729df0566a6SJani Nikula 			info->dp_max_link_rate = 810000;
1730df0566a6SJani Nikula 			break;
1731df0566a6SJani Nikula 		case VBT_DP_MAX_LINK_RATE_HBR2:
1732df0566a6SJani Nikula 			info->dp_max_link_rate = 540000;
1733df0566a6SJani Nikula 			break;
1734df0566a6SJani Nikula 		case VBT_DP_MAX_LINK_RATE_HBR:
1735df0566a6SJani Nikula 			info->dp_max_link_rate = 270000;
1736df0566a6SJani Nikula 			break;
1737df0566a6SJani Nikula 		case VBT_DP_MAX_LINK_RATE_LBR:
1738df0566a6SJani Nikula 			info->dp_max_link_rate = 162000;
1739df0566a6SJani Nikula 			break;
1740df0566a6SJani Nikula 		}
1741df0566a6SJani Nikula 		DRM_DEBUG_KMS("VBT DP max link rate for port %c: %d\n",
1742df0566a6SJani Nikula 			      port_name(port), info->dp_max_link_rate);
1743df0566a6SJani Nikula 	}
1744df0566a6SJani Nikula 
1745df0566a6SJani Nikula 	info->child = child;
1746df0566a6SJani Nikula }
1747df0566a6SJani Nikula 
1748df0566a6SJani Nikula static void parse_ddi_ports(struct drm_i915_private *dev_priv, u8 bdb_version)
1749df0566a6SJani Nikula {
1750d1dad6f4SJani Nikula 	struct display_device_data *devdata;
1751df0566a6SJani Nikula 
1752df0566a6SJani Nikula 	if (!HAS_DDI(dev_priv) && !IS_CHERRYVIEW(dev_priv))
1753df0566a6SJani Nikula 		return;
1754df0566a6SJani Nikula 
1755df0566a6SJani Nikula 	if (bdb_version < 155)
1756df0566a6SJani Nikula 		return;
1757df0566a6SJani Nikula 
17580d9ef19bSJani Nikula 	list_for_each_entry(devdata, &dev_priv->vbt.display_devices, node)
1759d1dad6f4SJani Nikula 		parse_ddi_port(dev_priv, devdata, bdb_version);
1760df0566a6SJani Nikula }
1761df0566a6SJani Nikula 
1762df0566a6SJani Nikula static void
1763df0566a6SJani Nikula parse_general_definitions(struct drm_i915_private *dev_priv,
1764df0566a6SJani Nikula 			  const struct bdb_header *bdb)
1765df0566a6SJani Nikula {
1766df0566a6SJani Nikula 	const struct bdb_general_definitions *defs;
17670d9ef19bSJani Nikula 	struct display_device_data *devdata;
1768df0566a6SJani Nikula 	const struct child_device_config *child;
17690d9ef19bSJani Nikula 	int i, child_device_num;
1770df0566a6SJani Nikula 	u8 expected_size;
1771df0566a6SJani Nikula 	u16 block_size;
1772df0566a6SJani Nikula 	int bus_pin;
1773df0566a6SJani Nikula 
1774df0566a6SJani Nikula 	defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
1775df0566a6SJani Nikula 	if (!defs) {
1776df0566a6SJani Nikula 		DRM_DEBUG_KMS("No general definition block is found, no devices defined.\n");
1777df0566a6SJani Nikula 		return;
1778df0566a6SJani Nikula 	}
1779df0566a6SJani Nikula 
1780df0566a6SJani Nikula 	block_size = get_blocksize(defs);
1781df0566a6SJani Nikula 	if (block_size < sizeof(*defs)) {
1782df0566a6SJani Nikula 		DRM_DEBUG_KMS("General definitions block too small (%u)\n",
1783df0566a6SJani Nikula 			      block_size);
1784df0566a6SJani Nikula 		return;
1785df0566a6SJani Nikula 	}
1786df0566a6SJani Nikula 
1787df0566a6SJani Nikula 	bus_pin = defs->crt_ddc_gmbus_pin;
1788df0566a6SJani Nikula 	DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin);
1789df0566a6SJani Nikula 	if (intel_gmbus_is_valid_pin(dev_priv, bus_pin))
1790df0566a6SJani Nikula 		dev_priv->vbt.crt_ddc_pin = bus_pin;
1791df0566a6SJani Nikula 
1792df0566a6SJani Nikula 	if (bdb->version < 106) {
1793df0566a6SJani Nikula 		expected_size = 22;
1794df0566a6SJani Nikula 	} else if (bdb->version < 111) {
1795df0566a6SJani Nikula 		expected_size = 27;
1796df0566a6SJani Nikula 	} else if (bdb->version < 195) {
1797df0566a6SJani Nikula 		expected_size = LEGACY_CHILD_DEVICE_CONFIG_SIZE;
1798df0566a6SJani Nikula 	} else if (bdb->version == 195) {
1799df0566a6SJani Nikula 		expected_size = 37;
1800df0566a6SJani Nikula 	} else if (bdb->version <= 215) {
1801df0566a6SJani Nikula 		expected_size = 38;
18023aec2c6aSMatt Roper 	} else if (bdb->version <= 229) {
1803df0566a6SJani Nikula 		expected_size = 39;
1804df0566a6SJani Nikula 	} else {
1805df0566a6SJani Nikula 		expected_size = sizeof(*child);
1806df0566a6SJani Nikula 		BUILD_BUG_ON(sizeof(*child) < 39);
1807df0566a6SJani Nikula 		DRM_DEBUG_DRIVER("Expected child device config size for VBT version %u not known; assuming %u\n",
1808df0566a6SJani Nikula 				 bdb->version, expected_size);
1809df0566a6SJani Nikula 	}
1810df0566a6SJani Nikula 
1811df0566a6SJani Nikula 	/* Flag an error for unexpected size, but continue anyway. */
1812df0566a6SJani Nikula 	if (defs->child_dev_size != expected_size)
1813df0566a6SJani Nikula 		DRM_ERROR("Unexpected child device config size %u (expected %u for VBT version %u)\n",
1814df0566a6SJani Nikula 			  defs->child_dev_size, expected_size, bdb->version);
1815df0566a6SJani Nikula 
1816df0566a6SJani Nikula 	/* The legacy sized child device config is the minimum we need. */
1817df0566a6SJani Nikula 	if (defs->child_dev_size < LEGACY_CHILD_DEVICE_CONFIG_SIZE) {
1818df0566a6SJani Nikula 		DRM_DEBUG_KMS("Child device config size %u is too small.\n",
1819df0566a6SJani Nikula 			      defs->child_dev_size);
1820df0566a6SJani Nikula 		return;
1821df0566a6SJani Nikula 	}
1822df0566a6SJani Nikula 
1823df0566a6SJani Nikula 	/* get the number of child device */
1824df0566a6SJani Nikula 	child_device_num = (block_size - sizeof(*defs)) / defs->child_dev_size;
1825df0566a6SJani Nikula 
1826df0566a6SJani Nikula 	for (i = 0; i < child_device_num; i++) {
1827df0566a6SJani Nikula 		child = child_device_ptr(defs, i);
1828df0566a6SJani Nikula 		if (!child->device_type)
1829df0566a6SJani Nikula 			continue;
1830df0566a6SJani Nikula 
1831bdeb18dbSMatt Roper 		DRM_DEBUG_KMS("Found VBT child device with type 0x%x\n",
1832bdeb18dbSMatt Roper 			      child->device_type);
1833bdeb18dbSMatt Roper 
18340d9ef19bSJani Nikula 		devdata = kzalloc(sizeof(*devdata), GFP_KERNEL);
18350d9ef19bSJani Nikula 		if (!devdata)
18360d9ef19bSJani Nikula 			break;
18370d9ef19bSJani Nikula 
1838df0566a6SJani Nikula 		/*
1839df0566a6SJani Nikula 		 * Copy as much as we know (sizeof) and is available
18400d9ef19bSJani Nikula 		 * (child_dev_size) of the child device config. Accessing the
18410d9ef19bSJani Nikula 		 * data must depend on VBT version.
1842df0566a6SJani Nikula 		 */
18430d9ef19bSJani Nikula 		memcpy(&devdata->child, child,
1844df0566a6SJani Nikula 		       min_t(size_t, defs->child_dev_size, sizeof(*child)));
18450d9ef19bSJani Nikula 
18460d9ef19bSJani Nikula 		list_add_tail(&devdata->node, &dev_priv->vbt.display_devices);
1847df0566a6SJani Nikula 	}
18480d9ef19bSJani Nikula 
18490d9ef19bSJani Nikula 	if (list_empty(&dev_priv->vbt.display_devices))
18500d9ef19bSJani Nikula 		DRM_DEBUG_KMS("no child dev is parsed from VBT\n");
1851df0566a6SJani Nikula }
1852df0566a6SJani Nikula 
1853df0566a6SJani Nikula /* Common defaults which may be overridden by VBT. */
1854df0566a6SJani Nikula static void
1855df0566a6SJani Nikula init_vbt_defaults(struct drm_i915_private *dev_priv)
1856df0566a6SJani Nikula {
1857df0566a6SJani Nikula 	dev_priv->vbt.crt_ddc_pin = GMBUS_PIN_VGADDC;
1858df0566a6SJani Nikula 
1859df0566a6SJani Nikula 	/* Default to having backlight */
1860df0566a6SJani Nikula 	dev_priv->vbt.backlight.present = true;
1861df0566a6SJani Nikula 
1862df0566a6SJani Nikula 	/* LFP panel data */
1863df0566a6SJani Nikula 	dev_priv->vbt.lvds_dither = 1;
1864df0566a6SJani Nikula 
1865df0566a6SJani Nikula 	/* SDVO panel data */
1866df0566a6SJani Nikula 	dev_priv->vbt.sdvo_lvds_vbt_mode = NULL;
1867df0566a6SJani Nikula 
1868df0566a6SJani Nikula 	/* general features */
1869df0566a6SJani Nikula 	dev_priv->vbt.int_tv_support = 1;
1870df0566a6SJani Nikula 	dev_priv->vbt.int_crt_support = 1;
1871df0566a6SJani Nikula 
1872df0566a6SJani Nikula 	/* driver features */
1873df0566a6SJani Nikula 	dev_priv->vbt.int_lvds_support = 1;
1874df0566a6SJani Nikula 
1875df0566a6SJani Nikula 	/* Default to using SSC */
1876df0566a6SJani Nikula 	dev_priv->vbt.lvds_use_ssc = 1;
1877df0566a6SJani Nikula 	/*
1878df0566a6SJani Nikula 	 * Core/SandyBridge/IvyBridge use alternative (120MHz) reference
1879df0566a6SJani Nikula 	 * clock for LVDS.
1880df0566a6SJani Nikula 	 */
1881df0566a6SJani Nikula 	dev_priv->vbt.lvds_ssc_freq = intel_bios_ssc_frequency(dev_priv,
1882df0566a6SJani Nikula 			!HAS_PCH_SPLIT(dev_priv));
1883df0566a6SJani Nikula 	DRM_DEBUG_KMS("Set default to SSC at %d kHz\n", dev_priv->vbt.lvds_ssc_freq);
1884df0566a6SJani Nikula }
1885df0566a6SJani Nikula 
1886df0566a6SJani Nikula /* Defaults to initialize only if there is no VBT. */
1887df0566a6SJani Nikula static void
1888df0566a6SJani Nikula init_vbt_missing_defaults(struct drm_i915_private *dev_priv)
1889df0566a6SJani Nikula {
1890df0566a6SJani Nikula 	enum port port;
1891df0566a6SJani Nikula 
1892c4a774c4SJani Nikula 	for_each_port(port) {
1893df0566a6SJani Nikula 		struct ddi_vbt_port_info *info =
1894df0566a6SJani Nikula 			&dev_priv->vbt.ddi_port_info[port];
1895d8fe2ab6SMatt Roper 		enum phy phy = intel_port_to_phy(dev_priv, port);
1896df0566a6SJani Nikula 
1897df0566a6SJani Nikula 		/*
1898df0566a6SJani Nikula 		 * VBT has the TypeC mode (native,TBT/USB) and we don't want
1899df0566a6SJani Nikula 		 * to detect it.
1900df0566a6SJani Nikula 		 */
1901d8fe2ab6SMatt Roper 		if (intel_phy_is_tc(dev_priv, phy))
1902df0566a6SJani Nikula 			continue;
1903df0566a6SJani Nikula 
1904df0566a6SJani Nikula 		info->supports_dvi = (port != PORT_A && port != PORT_E);
1905df0566a6SJani Nikula 		info->supports_hdmi = info->supports_dvi;
1906df0566a6SJani Nikula 		info->supports_dp = (port != PORT_E);
1907df0566a6SJani Nikula 		info->supports_edp = (port == PORT_A);
1908df0566a6SJani Nikula 	}
1909df0566a6SJani Nikula }
1910df0566a6SJani Nikula 
1911df0566a6SJani Nikula static const struct bdb_header *get_bdb_header(const struct vbt_header *vbt)
1912df0566a6SJani Nikula {
1913df0566a6SJani Nikula 	const void *_vbt = vbt;
1914df0566a6SJani Nikula 
1915df0566a6SJani Nikula 	return _vbt + vbt->bdb_offset;
1916df0566a6SJani Nikula }
1917df0566a6SJani Nikula 
1918df0566a6SJani Nikula /**
1919df0566a6SJani Nikula  * intel_bios_is_valid_vbt - does the given buffer contain a valid VBT
1920df0566a6SJani Nikula  * @buf:	pointer to a buffer to validate
1921df0566a6SJani Nikula  * @size:	size of the buffer
1922df0566a6SJani Nikula  *
1923df0566a6SJani Nikula  * Returns true on valid VBT.
1924df0566a6SJani Nikula  */
1925df0566a6SJani Nikula bool intel_bios_is_valid_vbt(const void *buf, size_t size)
1926df0566a6SJani Nikula {
1927df0566a6SJani Nikula 	const struct vbt_header *vbt = buf;
1928df0566a6SJani Nikula 	const struct bdb_header *bdb;
1929df0566a6SJani Nikula 
1930df0566a6SJani Nikula 	if (!vbt)
1931df0566a6SJani Nikula 		return false;
1932df0566a6SJani Nikula 
1933df0566a6SJani Nikula 	if (sizeof(struct vbt_header) > size) {
1934df0566a6SJani Nikula 		DRM_DEBUG_DRIVER("VBT header incomplete\n");
1935df0566a6SJani Nikula 		return false;
1936df0566a6SJani Nikula 	}
1937df0566a6SJani Nikula 
1938df0566a6SJani Nikula 	if (memcmp(vbt->signature, "$VBT", 4)) {
1939df0566a6SJani Nikula 		DRM_DEBUG_DRIVER("VBT invalid signature\n");
1940df0566a6SJani Nikula 		return false;
1941df0566a6SJani Nikula 	}
1942df0566a6SJani Nikula 
1943ff00ff96SLucas De Marchi 	if (vbt->vbt_size > size) {
1944ff00ff96SLucas De Marchi 		DRM_DEBUG_DRIVER("VBT incomplete (vbt_size overflows)\n");
1945ff00ff96SLucas De Marchi 		return false;
1946ff00ff96SLucas De Marchi 	}
1947ff00ff96SLucas De Marchi 
1948ff00ff96SLucas De Marchi 	size = vbt->vbt_size;
1949ff00ff96SLucas De Marchi 
1950df0566a6SJani Nikula 	if (range_overflows_t(size_t,
1951df0566a6SJani Nikula 			      vbt->bdb_offset,
1952df0566a6SJani Nikula 			      sizeof(struct bdb_header),
1953df0566a6SJani Nikula 			      size)) {
1954df0566a6SJani Nikula 		DRM_DEBUG_DRIVER("BDB header incomplete\n");
1955df0566a6SJani Nikula 		return false;
1956df0566a6SJani Nikula 	}
1957df0566a6SJani Nikula 
1958df0566a6SJani Nikula 	bdb = get_bdb_header(vbt);
1959df0566a6SJani Nikula 	if (range_overflows_t(size_t, vbt->bdb_offset, bdb->bdb_size, size)) {
1960df0566a6SJani Nikula 		DRM_DEBUG_DRIVER("BDB incomplete\n");
1961df0566a6SJani Nikula 		return false;
1962df0566a6SJani Nikula 	}
1963df0566a6SJani Nikula 
1964df0566a6SJani Nikula 	return vbt;
1965df0566a6SJani Nikula }
1966df0566a6SJani Nikula 
19672cded152SLucas De Marchi static struct vbt_header *oprom_get_vbt(struct drm_i915_private *dev_priv)
1968df0566a6SJani Nikula {
19692cded152SLucas De Marchi 	struct pci_dev *pdev = dev_priv->drm.pdev;
19702cded152SLucas De Marchi 	void __iomem *p = NULL, *oprom;
1971fd0186ceSLucas De Marchi 	struct vbt_header *vbt;
1972fd0186ceSLucas De Marchi 	u16 vbt_size;
19732cded152SLucas De Marchi 	size_t i, size;
19742cded152SLucas De Marchi 
19752cded152SLucas De Marchi 	oprom = pci_map_rom(pdev, &size);
19762cded152SLucas De Marchi 	if (!oprom)
19772cded152SLucas De Marchi 		return NULL;
1978df0566a6SJani Nikula 
1979df0566a6SJani Nikula 	/* Scour memory looking for the VBT signature. */
198098cf5c9aSLucas De Marchi 	for (i = 0; i + 4 < size; i += 4) {
1981496f50a6SLucas De Marchi 		if (ioread32(oprom + i) != *((const u32 *)"$VBT"))
1982df0566a6SJani Nikula 			continue;
1983df0566a6SJani Nikula 
1984fd0186ceSLucas De Marchi 		p = oprom + i;
1985fd0186ceSLucas De Marchi 		size -= i;
1986df0566a6SJani Nikula 		break;
1987df0566a6SJani Nikula 	}
1988df0566a6SJani Nikula 
1989fd0186ceSLucas De Marchi 	if (!p)
19902cded152SLucas De Marchi 		goto err_unmap_oprom;
1991fd0186ceSLucas De Marchi 
1992fd0186ceSLucas De Marchi 	if (sizeof(struct vbt_header) > size) {
1993fd0186ceSLucas De Marchi 		DRM_DEBUG_DRIVER("VBT header incomplete\n");
19942cded152SLucas De Marchi 		goto err_unmap_oprom;
1995fd0186ceSLucas De Marchi 	}
1996fd0186ceSLucas De Marchi 
1997fd0186ceSLucas De Marchi 	vbt_size = ioread16(p + offsetof(struct vbt_header, vbt_size));
1998fd0186ceSLucas De Marchi 	if (vbt_size > size) {
1999fd0186ceSLucas De Marchi 		DRM_DEBUG_DRIVER("VBT incomplete (vbt_size overflows)\n");
20002cded152SLucas De Marchi 		goto err_unmap_oprom;
2001fd0186ceSLucas De Marchi 	}
2002fd0186ceSLucas De Marchi 
2003fd0186ceSLucas De Marchi 	/* The rest will be validated by intel_bios_is_valid_vbt() */
2004fd0186ceSLucas De Marchi 	vbt = kmalloc(vbt_size, GFP_KERNEL);
2005fd0186ceSLucas De Marchi 	if (!vbt)
20062cded152SLucas De Marchi 		goto err_unmap_oprom;
2007fd0186ceSLucas De Marchi 
2008fd0186ceSLucas De Marchi 	memcpy_fromio(vbt, p, vbt_size);
2009fd0186ceSLucas De Marchi 
2010fd0186ceSLucas De Marchi 	if (!intel_bios_is_valid_vbt(vbt, vbt_size))
2011fd0186ceSLucas De Marchi 		goto err_free_vbt;
2012fd0186ceSLucas De Marchi 
20132cded152SLucas De Marchi 	pci_unmap_rom(pdev, oprom);
20142cded152SLucas De Marchi 
2015fd0186ceSLucas De Marchi 	return vbt;
2016fd0186ceSLucas De Marchi 
2017fd0186ceSLucas De Marchi err_free_vbt:
2018fd0186ceSLucas De Marchi 	kfree(vbt);
20192cded152SLucas De Marchi err_unmap_oprom:
20202cded152SLucas De Marchi 	pci_unmap_rom(pdev, oprom);
2021fd0186ceSLucas De Marchi 
2022df0566a6SJani Nikula 	return NULL;
2023df0566a6SJani Nikula }
2024df0566a6SJani Nikula 
2025df0566a6SJani Nikula /**
2026df0566a6SJani Nikula  * intel_bios_init - find VBT and initialize settings from the BIOS
2027df0566a6SJani Nikula  * @dev_priv: i915 device instance
2028df0566a6SJani Nikula  *
2029df0566a6SJani Nikula  * Parse and initialize settings from the Video BIOS Tables (VBT). If the VBT
2030df0566a6SJani Nikula  * was not found in ACPI OpRegion, try to find it in PCI ROM first. Also
2031df0566a6SJani Nikula  * initialize some defaults if the VBT is not present at all.
2032df0566a6SJani Nikula  */
2033df0566a6SJani Nikula void intel_bios_init(struct drm_i915_private *dev_priv)
2034df0566a6SJani Nikula {
2035df0566a6SJani Nikula 	const struct vbt_header *vbt = dev_priv->opregion.vbt;
20362cded152SLucas De Marchi 	struct vbt_header *oprom_vbt = NULL;
2037df0566a6SJani Nikula 	const struct bdb_header *bdb;
2038df0566a6SJani Nikula 
20390d9ef19bSJani Nikula 	INIT_LIST_HEAD(&dev_priv->vbt.display_devices);
20400d9ef19bSJani Nikula 
2041a2b69ea4SJani Nikula 	if (!HAS_DISPLAY(dev_priv) || !INTEL_DISPLAY_ENABLED(dev_priv)) {
2042df0566a6SJani Nikula 		DRM_DEBUG_KMS("Skipping VBT init due to disabled display.\n");
2043df0566a6SJani Nikula 		return;
2044df0566a6SJani Nikula 	}
2045df0566a6SJani Nikula 
2046df0566a6SJani Nikula 	init_vbt_defaults(dev_priv);
2047df0566a6SJani Nikula 
2048df0566a6SJani Nikula 	/* If the OpRegion does not have VBT, look in PCI ROM. */
2049df0566a6SJani Nikula 	if (!vbt) {
20502cded152SLucas De Marchi 		oprom_vbt = oprom_get_vbt(dev_priv);
20512cded152SLucas De Marchi 		if (!oprom_vbt)
2052df0566a6SJani Nikula 			goto out;
2053df0566a6SJani Nikula 
20542cded152SLucas De Marchi 		vbt = oprom_vbt;
2055df0566a6SJani Nikula 
2056df0566a6SJani Nikula 		DRM_DEBUG_KMS("Found valid VBT in PCI ROM\n");
2057df0566a6SJani Nikula 	}
2058df0566a6SJani Nikula 
2059df0566a6SJani Nikula 	bdb = get_bdb_header(vbt);
2060df0566a6SJani Nikula 
2061df0566a6SJani Nikula 	DRM_DEBUG_KMS("VBT signature \"%.*s\", BDB version %d\n",
2062df0566a6SJani Nikula 		      (int)sizeof(vbt->signature), vbt->signature, bdb->version);
2063df0566a6SJani Nikula 
2064df0566a6SJani Nikula 	/* Grab useful general definitions */
2065df0566a6SJani Nikula 	parse_general_features(dev_priv, bdb);
2066df0566a6SJani Nikula 	parse_general_definitions(dev_priv, bdb);
20679e7ecedfSMatt Roper 	parse_panel_options(dev_priv, bdb);
206833ef6d4fSMatt Roper 	parse_panel_dtd(dev_priv, bdb);
2069df0566a6SJani Nikula 	parse_lfp_backlight(dev_priv, bdb);
2070df0566a6SJani Nikula 	parse_sdvo_panel_data(dev_priv, bdb);
2071df0566a6SJani Nikula 	parse_driver_features(dev_priv, bdb);
2072551fb93dSJosé Roberto de Souza 	parse_power_conservation_features(dev_priv, bdb);
2073df0566a6SJani Nikula 	parse_edp(dev_priv, bdb);
2074df0566a6SJani Nikula 	parse_psr(dev_priv, bdb);
2075df0566a6SJani Nikula 	parse_mipi_config(dev_priv, bdb);
2076df0566a6SJani Nikula 	parse_mipi_sequence(dev_priv, bdb);
2077df0566a6SJani Nikula 
20786e0d46e9SJani Nikula 	/* Depends on child device list */
20796e0d46e9SJani Nikula 	parse_compression_parameters(dev_priv, bdb);
20806e0d46e9SJani Nikula 
2081df0566a6SJani Nikula 	/* Further processing on pre-parsed data */
2082df0566a6SJani Nikula 	parse_sdvo_device_mapping(dev_priv, bdb->version);
2083df0566a6SJani Nikula 	parse_ddi_ports(dev_priv, bdb->version);
2084df0566a6SJani Nikula 
2085df0566a6SJani Nikula out:
2086df0566a6SJani Nikula 	if (!vbt) {
2087df0566a6SJani Nikula 		DRM_INFO("Failed to find VBIOS tables (VBT)\n");
2088df0566a6SJani Nikula 		init_vbt_missing_defaults(dev_priv);
2089df0566a6SJani Nikula 	}
2090df0566a6SJani Nikula 
20912cded152SLucas De Marchi 	kfree(oprom_vbt);
2092df0566a6SJani Nikula }
2093df0566a6SJani Nikula 
2094df0566a6SJani Nikula /**
209578dae1acSJanusz Krzysztofik  * intel_bios_driver_remove - Free any resources allocated by intel_bios_init()
2096df0566a6SJani Nikula  * @dev_priv: i915 device instance
2097df0566a6SJani Nikula  */
209878dae1acSJanusz Krzysztofik void intel_bios_driver_remove(struct drm_i915_private *dev_priv)
2099df0566a6SJani Nikula {
21000d9ef19bSJani Nikula 	struct display_device_data *devdata, *n;
21010d9ef19bSJani Nikula 
21020d9ef19bSJani Nikula 	list_for_each_entry_safe(devdata, n, &dev_priv->vbt.display_devices, node) {
21030d9ef19bSJani Nikula 		list_del(&devdata->node);
21046e0d46e9SJani Nikula 		kfree(devdata->dsc);
21050d9ef19bSJani Nikula 		kfree(devdata);
21060d9ef19bSJani Nikula 	}
21070d9ef19bSJani Nikula 
2108df0566a6SJani Nikula 	kfree(dev_priv->vbt.sdvo_lvds_vbt_mode);
2109df0566a6SJani Nikula 	dev_priv->vbt.sdvo_lvds_vbt_mode = NULL;
2110df0566a6SJani Nikula 	kfree(dev_priv->vbt.lfp_lvds_vbt_mode);
2111df0566a6SJani Nikula 	dev_priv->vbt.lfp_lvds_vbt_mode = NULL;
2112df0566a6SJani Nikula 	kfree(dev_priv->vbt.dsi.data);
2113df0566a6SJani Nikula 	dev_priv->vbt.dsi.data = NULL;
2114df0566a6SJani Nikula 	kfree(dev_priv->vbt.dsi.pps);
2115df0566a6SJani Nikula 	dev_priv->vbt.dsi.pps = NULL;
2116df0566a6SJani Nikula 	kfree(dev_priv->vbt.dsi.config);
2117df0566a6SJani Nikula 	dev_priv->vbt.dsi.config = NULL;
2118df0566a6SJani Nikula 	kfree(dev_priv->vbt.dsi.deassert_seq);
2119df0566a6SJani Nikula 	dev_priv->vbt.dsi.deassert_seq = NULL;
2120df0566a6SJani Nikula }
2121df0566a6SJani Nikula 
2122df0566a6SJani Nikula /**
2123df0566a6SJani Nikula  * intel_bios_is_tv_present - is integrated TV present in VBT
2124df0566a6SJani Nikula  * @dev_priv:	i915 device instance
2125df0566a6SJani Nikula  *
2126df0566a6SJani Nikula  * Return true if TV is present. If no child devices were parsed from VBT,
2127df0566a6SJani Nikula  * assume TV is present.
2128df0566a6SJani Nikula  */
2129df0566a6SJani Nikula bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv)
2130df0566a6SJani Nikula {
21310d9ef19bSJani Nikula 	const struct display_device_data *devdata;
2132df0566a6SJani Nikula 	const struct child_device_config *child;
2133df0566a6SJani Nikula 
2134df0566a6SJani Nikula 	if (!dev_priv->vbt.int_tv_support)
2135df0566a6SJani Nikula 		return false;
2136df0566a6SJani Nikula 
21370d9ef19bSJani Nikula 	if (list_empty(&dev_priv->vbt.display_devices))
2138df0566a6SJani Nikula 		return true;
2139df0566a6SJani Nikula 
21400d9ef19bSJani Nikula 	list_for_each_entry(devdata, &dev_priv->vbt.display_devices, node) {
21410d9ef19bSJani Nikula 		child = &devdata->child;
21420d9ef19bSJani Nikula 
2143df0566a6SJani Nikula 		/*
2144df0566a6SJani Nikula 		 * If the device type is not TV, continue.
2145df0566a6SJani Nikula 		 */
2146df0566a6SJani Nikula 		switch (child->device_type) {
2147df0566a6SJani Nikula 		case DEVICE_TYPE_INT_TV:
2148df0566a6SJani Nikula 		case DEVICE_TYPE_TV:
2149df0566a6SJani Nikula 		case DEVICE_TYPE_TV_SVIDEO_COMPOSITE:
2150df0566a6SJani Nikula 			break;
2151df0566a6SJani Nikula 		default:
2152df0566a6SJani Nikula 			continue;
2153df0566a6SJani Nikula 		}
2154df0566a6SJani Nikula 		/* Only when the addin_offset is non-zero, it is regarded
2155df0566a6SJani Nikula 		 * as present.
2156df0566a6SJani Nikula 		 */
2157df0566a6SJani Nikula 		if (child->addin_offset)
2158df0566a6SJani Nikula 			return true;
2159df0566a6SJani Nikula 	}
2160df0566a6SJani Nikula 
2161df0566a6SJani Nikula 	return false;
2162df0566a6SJani Nikula }
2163df0566a6SJani Nikula 
2164df0566a6SJani Nikula /**
2165df0566a6SJani Nikula  * intel_bios_is_lvds_present - is LVDS present in VBT
2166df0566a6SJani Nikula  * @dev_priv:	i915 device instance
2167df0566a6SJani Nikula  * @i2c_pin:	i2c pin for LVDS if present
2168df0566a6SJani Nikula  *
2169df0566a6SJani Nikula  * Return true if LVDS is present. If no child devices were parsed from VBT,
2170df0566a6SJani Nikula  * assume LVDS is present.
2171df0566a6SJani Nikula  */
2172df0566a6SJani Nikula bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin)
2173df0566a6SJani Nikula {
21740d9ef19bSJani Nikula 	const struct display_device_data *devdata;
2175df0566a6SJani Nikula 	const struct child_device_config *child;
2176df0566a6SJani Nikula 
21770d9ef19bSJani Nikula 	if (list_empty(&dev_priv->vbt.display_devices))
2178df0566a6SJani Nikula 		return true;
2179df0566a6SJani Nikula 
21800d9ef19bSJani Nikula 	list_for_each_entry(devdata, &dev_priv->vbt.display_devices, node) {
21810d9ef19bSJani Nikula 		child = &devdata->child;
2182df0566a6SJani Nikula 
2183df0566a6SJani Nikula 		/* If the device type is not LFP, continue.
2184df0566a6SJani Nikula 		 * We have to check both the new identifiers as well as the
2185df0566a6SJani Nikula 		 * old for compatibility with some BIOSes.
2186df0566a6SJani Nikula 		 */
2187df0566a6SJani Nikula 		if (child->device_type != DEVICE_TYPE_INT_LFP &&
2188df0566a6SJani Nikula 		    child->device_type != DEVICE_TYPE_LFP)
2189df0566a6SJani Nikula 			continue;
2190df0566a6SJani Nikula 
2191df0566a6SJani Nikula 		if (intel_gmbus_is_valid_pin(dev_priv, child->i2c_pin))
2192df0566a6SJani Nikula 			*i2c_pin = child->i2c_pin;
2193df0566a6SJani Nikula 
2194df0566a6SJani Nikula 		/* However, we cannot trust the BIOS writers to populate
2195df0566a6SJani Nikula 		 * the VBT correctly.  Since LVDS requires additional
2196df0566a6SJani Nikula 		 * information from AIM blocks, a non-zero addin offset is
2197df0566a6SJani Nikula 		 * a good indicator that the LVDS is actually present.
2198df0566a6SJani Nikula 		 */
2199df0566a6SJani Nikula 		if (child->addin_offset)
2200df0566a6SJani Nikula 			return true;
2201df0566a6SJani Nikula 
2202df0566a6SJani Nikula 		/* But even then some BIOS writers perform some black magic
2203df0566a6SJani Nikula 		 * and instantiate the device without reference to any
2204df0566a6SJani Nikula 		 * additional data.  Trust that if the VBT was written into
2205df0566a6SJani Nikula 		 * the OpRegion then they have validated the LVDS's existence.
2206df0566a6SJani Nikula 		 */
2207df0566a6SJani Nikula 		if (dev_priv->opregion.vbt)
2208df0566a6SJani Nikula 			return true;
2209df0566a6SJani Nikula 	}
2210df0566a6SJani Nikula 
2211df0566a6SJani Nikula 	return false;
2212df0566a6SJani Nikula }
2213df0566a6SJani Nikula 
2214df0566a6SJani Nikula /**
2215df0566a6SJani Nikula  * intel_bios_is_port_present - is the specified digital port present
2216df0566a6SJani Nikula  * @dev_priv:	i915 device instance
2217df0566a6SJani Nikula  * @port:	port to check
2218df0566a6SJani Nikula  *
2219df0566a6SJani Nikula  * Return true if the device in %port is present.
2220df0566a6SJani Nikula  */
2221df0566a6SJani Nikula bool intel_bios_is_port_present(struct drm_i915_private *dev_priv, enum port port)
2222df0566a6SJani Nikula {
22230d9ef19bSJani Nikula 	const struct display_device_data *devdata;
2224df0566a6SJani Nikula 	const struct child_device_config *child;
2225df0566a6SJani Nikula 	static const struct {
2226df0566a6SJani Nikula 		u16 dp, hdmi;
2227df0566a6SJani Nikula 	} port_mapping[] = {
2228df0566a6SJani Nikula 		[PORT_B] = { DVO_PORT_DPB, DVO_PORT_HDMIB, },
2229df0566a6SJani Nikula 		[PORT_C] = { DVO_PORT_DPC, DVO_PORT_HDMIC, },
2230df0566a6SJani Nikula 		[PORT_D] = { DVO_PORT_DPD, DVO_PORT_HDMID, },
2231df0566a6SJani Nikula 		[PORT_E] = { DVO_PORT_DPE, DVO_PORT_HDMIE, },
2232df0566a6SJani Nikula 		[PORT_F] = { DVO_PORT_DPF, DVO_PORT_HDMIF, },
2233df0566a6SJani Nikula 	};
2234df0566a6SJani Nikula 
2235df0566a6SJani Nikula 	if (HAS_DDI(dev_priv)) {
2236df0566a6SJani Nikula 		const struct ddi_vbt_port_info *port_info =
2237df0566a6SJani Nikula 			&dev_priv->vbt.ddi_port_info[port];
2238df0566a6SJani Nikula 
2239df0566a6SJani Nikula 		return port_info->supports_dp ||
2240df0566a6SJani Nikula 		       port_info->supports_dvi ||
2241df0566a6SJani Nikula 		       port_info->supports_hdmi;
2242df0566a6SJani Nikula 	}
2243df0566a6SJani Nikula 
2244df0566a6SJani Nikula 	/* FIXME maybe deal with port A as well? */
2245df0566a6SJani Nikula 	if (WARN_ON(port == PORT_A) || port >= ARRAY_SIZE(port_mapping))
2246df0566a6SJani Nikula 		return false;
2247df0566a6SJani Nikula 
22480d9ef19bSJani Nikula 	list_for_each_entry(devdata, &dev_priv->vbt.display_devices, node) {
22490d9ef19bSJani Nikula 		child = &devdata->child;
2250df0566a6SJani Nikula 
2251df0566a6SJani Nikula 		if ((child->dvo_port == port_mapping[port].dp ||
2252df0566a6SJani Nikula 		     child->dvo_port == port_mapping[port].hdmi) &&
2253df0566a6SJani Nikula 		    (child->device_type & (DEVICE_TYPE_TMDS_DVI_SIGNALING |
2254df0566a6SJani Nikula 					   DEVICE_TYPE_DISPLAYPORT_OUTPUT)))
2255df0566a6SJani Nikula 			return true;
2256df0566a6SJani Nikula 	}
2257df0566a6SJani Nikula 
2258df0566a6SJani Nikula 	return false;
2259df0566a6SJani Nikula }
2260df0566a6SJani Nikula 
2261df0566a6SJani Nikula /**
2262df0566a6SJani Nikula  * intel_bios_is_port_edp - is the device in given port eDP
2263df0566a6SJani Nikula  * @dev_priv:	i915 device instance
2264df0566a6SJani Nikula  * @port:	port to check
2265df0566a6SJani Nikula  *
2266df0566a6SJani Nikula  * Return true if the device in %port is eDP.
2267df0566a6SJani Nikula  */
2268df0566a6SJani Nikula bool intel_bios_is_port_edp(struct drm_i915_private *dev_priv, enum port port)
2269df0566a6SJani Nikula {
22700d9ef19bSJani Nikula 	const struct display_device_data *devdata;
2271df0566a6SJani Nikula 	const struct child_device_config *child;
2272df0566a6SJani Nikula 	static const short port_mapping[] = {
2273df0566a6SJani Nikula 		[PORT_B] = DVO_PORT_DPB,
2274df0566a6SJani Nikula 		[PORT_C] = DVO_PORT_DPC,
2275df0566a6SJani Nikula 		[PORT_D] = DVO_PORT_DPD,
2276df0566a6SJani Nikula 		[PORT_E] = DVO_PORT_DPE,
2277df0566a6SJani Nikula 		[PORT_F] = DVO_PORT_DPF,
2278df0566a6SJani Nikula 	};
2279df0566a6SJani Nikula 
2280df0566a6SJani Nikula 	if (HAS_DDI(dev_priv))
2281df0566a6SJani Nikula 		return dev_priv->vbt.ddi_port_info[port].supports_edp;
2282df0566a6SJani Nikula 
22830d9ef19bSJani Nikula 	list_for_each_entry(devdata, &dev_priv->vbt.display_devices, node) {
22840d9ef19bSJani Nikula 		child = &devdata->child;
2285df0566a6SJani Nikula 
2286df0566a6SJani Nikula 		if (child->dvo_port == port_mapping[port] &&
2287df0566a6SJani Nikula 		    (child->device_type & DEVICE_TYPE_eDP_BITS) ==
2288df0566a6SJani Nikula 		    (DEVICE_TYPE_eDP & DEVICE_TYPE_eDP_BITS))
2289df0566a6SJani Nikula 			return true;
2290df0566a6SJani Nikula 	}
2291df0566a6SJani Nikula 
2292df0566a6SJani Nikula 	return false;
2293df0566a6SJani Nikula }
2294df0566a6SJani Nikula 
2295df0566a6SJani Nikula static bool child_dev_is_dp_dual_mode(const struct child_device_config *child,
2296df0566a6SJani Nikula 				      enum port port)
2297df0566a6SJani Nikula {
2298df0566a6SJani Nikula 	static const struct {
2299df0566a6SJani Nikula 		u16 dp, hdmi;
2300df0566a6SJani Nikula 	} port_mapping[] = {
2301df0566a6SJani Nikula 		/*
2302df0566a6SJani Nikula 		 * Buggy VBTs may declare DP ports as having
2303df0566a6SJani Nikula 		 * HDMI type dvo_port :( So let's check both.
2304df0566a6SJani Nikula 		 */
2305df0566a6SJani Nikula 		[PORT_B] = { DVO_PORT_DPB, DVO_PORT_HDMIB, },
2306df0566a6SJani Nikula 		[PORT_C] = { DVO_PORT_DPC, DVO_PORT_HDMIC, },
2307df0566a6SJani Nikula 		[PORT_D] = { DVO_PORT_DPD, DVO_PORT_HDMID, },
2308df0566a6SJani Nikula 		[PORT_E] = { DVO_PORT_DPE, DVO_PORT_HDMIE, },
2309df0566a6SJani Nikula 		[PORT_F] = { DVO_PORT_DPF, DVO_PORT_HDMIF, },
2310df0566a6SJani Nikula 	};
2311df0566a6SJani Nikula 
2312df0566a6SJani Nikula 	if (port == PORT_A || port >= ARRAY_SIZE(port_mapping))
2313df0566a6SJani Nikula 		return false;
2314df0566a6SJani Nikula 
2315df0566a6SJani Nikula 	if ((child->device_type & DEVICE_TYPE_DP_DUAL_MODE_BITS) !=
2316df0566a6SJani Nikula 	    (DEVICE_TYPE_DP_DUAL_MODE & DEVICE_TYPE_DP_DUAL_MODE_BITS))
2317df0566a6SJani Nikula 		return false;
2318df0566a6SJani Nikula 
2319df0566a6SJani Nikula 	if (child->dvo_port == port_mapping[port].dp)
2320df0566a6SJani Nikula 		return true;
2321df0566a6SJani Nikula 
2322df0566a6SJani Nikula 	/* Only accept a HDMI dvo_port as DP++ if it has an AUX channel */
2323df0566a6SJani Nikula 	if (child->dvo_port == port_mapping[port].hdmi &&
2324df0566a6SJani Nikula 	    child->aux_channel != 0)
2325df0566a6SJani Nikula 		return true;
2326df0566a6SJani Nikula 
2327df0566a6SJani Nikula 	return false;
2328df0566a6SJani Nikula }
2329df0566a6SJani Nikula 
2330df0566a6SJani Nikula bool intel_bios_is_port_dp_dual_mode(struct drm_i915_private *dev_priv,
2331df0566a6SJani Nikula 				     enum port port)
2332df0566a6SJani Nikula {
23330d9ef19bSJani Nikula 	const struct display_device_data *devdata;
2334df0566a6SJani Nikula 
23350d9ef19bSJani Nikula 	list_for_each_entry(devdata, &dev_priv->vbt.display_devices, node) {
23360d9ef19bSJani Nikula 		if (child_dev_is_dp_dual_mode(&devdata->child, port))
2337df0566a6SJani Nikula 			return true;
2338df0566a6SJani Nikula 	}
2339df0566a6SJani Nikula 
2340df0566a6SJani Nikula 	return false;
2341df0566a6SJani Nikula }
2342df0566a6SJani Nikula 
2343df0566a6SJani Nikula /**
2344df0566a6SJani Nikula  * intel_bios_is_dsi_present - is DSI present in VBT
2345df0566a6SJani Nikula  * @dev_priv:	i915 device instance
2346df0566a6SJani Nikula  * @port:	port for DSI if present
2347df0566a6SJani Nikula  *
2348df0566a6SJani Nikula  * Return true if DSI is present, and return the port in %port.
2349df0566a6SJani Nikula  */
2350df0566a6SJani Nikula bool intel_bios_is_dsi_present(struct drm_i915_private *dev_priv,
2351df0566a6SJani Nikula 			       enum port *port)
2352df0566a6SJani Nikula {
23530d9ef19bSJani Nikula 	const struct display_device_data *devdata;
2354df0566a6SJani Nikula 	const struct child_device_config *child;
2355df0566a6SJani Nikula 	u8 dvo_port;
2356df0566a6SJani Nikula 
23570d9ef19bSJani Nikula 	list_for_each_entry(devdata, &dev_priv->vbt.display_devices, node) {
23580d9ef19bSJani Nikula 		child = &devdata->child;
2359df0566a6SJani Nikula 
2360df0566a6SJani Nikula 		if (!(child->device_type & DEVICE_TYPE_MIPI_OUTPUT))
2361df0566a6SJani Nikula 			continue;
2362df0566a6SJani Nikula 
2363df0566a6SJani Nikula 		dvo_port = child->dvo_port;
2364df0566a6SJani Nikula 
2365df0566a6SJani Nikula 		if (dvo_port == DVO_PORT_MIPIA ||
2366df0566a6SJani Nikula 		    (dvo_port == DVO_PORT_MIPIB && INTEL_GEN(dev_priv) >= 11) ||
2367df0566a6SJani Nikula 		    (dvo_port == DVO_PORT_MIPIC && INTEL_GEN(dev_priv) < 11)) {
2368df0566a6SJani Nikula 			if (port)
2369df0566a6SJani Nikula 				*port = dvo_port - DVO_PORT_MIPIA;
2370df0566a6SJani Nikula 			return true;
2371df0566a6SJani Nikula 		} else if (dvo_port == DVO_PORT_MIPIB ||
2372df0566a6SJani Nikula 			   dvo_port == DVO_PORT_MIPIC ||
2373df0566a6SJani Nikula 			   dvo_port == DVO_PORT_MIPID) {
2374df0566a6SJani Nikula 			DRM_DEBUG_KMS("VBT has unsupported DSI port %c\n",
2375df0566a6SJani Nikula 				      port_name(dvo_port - DVO_PORT_MIPIA));
2376df0566a6SJani Nikula 		}
2377df0566a6SJani Nikula 	}
2378df0566a6SJani Nikula 
2379df0566a6SJani Nikula 	return false;
2380df0566a6SJani Nikula }
2381df0566a6SJani Nikula 
23821bf2f3bfSJani Nikula static void fill_dsc(struct intel_crtc_state *crtc_state,
23831bf2f3bfSJani Nikula 		     struct dsc_compression_parameters_entry *dsc,
23841bf2f3bfSJani Nikula 		     int dsc_max_bpc)
23851bf2f3bfSJani Nikula {
23861bf2f3bfSJani Nikula 	struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config;
23871bf2f3bfSJani Nikula 	int bpc = 8;
23881bf2f3bfSJani Nikula 
23891bf2f3bfSJani Nikula 	vdsc_cfg->dsc_version_major = dsc->version_major;
23901bf2f3bfSJani Nikula 	vdsc_cfg->dsc_version_minor = dsc->version_minor;
23911bf2f3bfSJani Nikula 
23921bf2f3bfSJani Nikula 	if (dsc->support_12bpc && dsc_max_bpc >= 12)
23931bf2f3bfSJani Nikula 		bpc = 12;
23941bf2f3bfSJani Nikula 	else if (dsc->support_10bpc && dsc_max_bpc >= 10)
23951bf2f3bfSJani Nikula 		bpc = 10;
23961bf2f3bfSJani Nikula 	else if (dsc->support_8bpc && dsc_max_bpc >= 8)
23971bf2f3bfSJani Nikula 		bpc = 8;
23981bf2f3bfSJani Nikula 	else
23991bf2f3bfSJani Nikula 		DRM_DEBUG_KMS("VBT: Unsupported BPC %d for DCS\n",
24001bf2f3bfSJani Nikula 			      dsc_max_bpc);
24011bf2f3bfSJani Nikula 
24021bf2f3bfSJani Nikula 	crtc_state->pipe_bpp = bpc * 3;
24031bf2f3bfSJani Nikula 
24041bf2f3bfSJani Nikula 	crtc_state->dsc.compressed_bpp = min(crtc_state->pipe_bpp,
24051bf2f3bfSJani Nikula 					     VBT_DSC_MAX_BPP(dsc->max_bpp));
24061bf2f3bfSJani Nikula 
24071bf2f3bfSJani Nikula 	/*
24081bf2f3bfSJani Nikula 	 * FIXME: This is ugly, and slice count should take DSC engine
24091bf2f3bfSJani Nikula 	 * throughput etc. into account.
24101bf2f3bfSJani Nikula 	 *
24111bf2f3bfSJani Nikula 	 * Also, per spec DSI supports 1, 2, 3 or 4 horizontal slices.
24121bf2f3bfSJani Nikula 	 */
24131bf2f3bfSJani Nikula 	if (dsc->slices_per_line & BIT(2)) {
24141bf2f3bfSJani Nikula 		crtc_state->dsc.slice_count = 4;
24151bf2f3bfSJani Nikula 	} else if (dsc->slices_per_line & BIT(1)) {
24161bf2f3bfSJani Nikula 		crtc_state->dsc.slice_count = 2;
24171bf2f3bfSJani Nikula 	} else {
24181bf2f3bfSJani Nikula 		/* FIXME */
24191bf2f3bfSJani Nikula 		if (!(dsc->slices_per_line & BIT(0)))
24201bf2f3bfSJani Nikula 			DRM_DEBUG_KMS("VBT: Unsupported DSC slice count for DSI\n");
24211bf2f3bfSJani Nikula 
24221bf2f3bfSJani Nikula 		crtc_state->dsc.slice_count = 1;
24231bf2f3bfSJani Nikula 	}
24241bf2f3bfSJani Nikula 
24251bf2f3bfSJani Nikula 	if (crtc_state->hw.adjusted_mode.crtc_hdisplay %
24261bf2f3bfSJani Nikula 	    crtc_state->dsc.slice_count != 0)
24271bf2f3bfSJani Nikula 		DRM_DEBUG_KMS("VBT: DSC hdisplay %d not divisible by slice count %d\n",
24281bf2f3bfSJani Nikula 			      crtc_state->hw.adjusted_mode.crtc_hdisplay,
24291bf2f3bfSJani Nikula 			      crtc_state->dsc.slice_count);
24301bf2f3bfSJani Nikula 
24311bf2f3bfSJani Nikula 	/*
24321bf2f3bfSJani Nikula 	 * FIXME: Use VBT rc_buffer_block_size and rc_buffer_size for the
24331bf2f3bfSJani Nikula 	 * implementation specific physical rate buffer size. Currently we use
24341bf2f3bfSJani Nikula 	 * the required rate buffer model size calculated in
24351bf2f3bfSJani Nikula 	 * drm_dsc_compute_rc_parameters() according to VESA DSC Annex E.
24361bf2f3bfSJani Nikula 	 *
24371bf2f3bfSJani Nikula 	 * The VBT rc_buffer_block_size and rc_buffer_size definitions
24381bf2f3bfSJani Nikula 	 * correspond to DP 1.4 DPCD offsets 0x62 and 0x63. The DP DSC
24391bf2f3bfSJani Nikula 	 * implementation should also use the DPCD (or perhaps VBT for eDP)
24401bf2f3bfSJani Nikula 	 * provided value for the buffer size.
24411bf2f3bfSJani Nikula 	 */
24421bf2f3bfSJani Nikula 
24431bf2f3bfSJani Nikula 	/* FIXME: DSI spec says bpc + 1 for this one */
24441bf2f3bfSJani Nikula 	vdsc_cfg->line_buf_depth = VBT_DSC_LINE_BUFFER_DEPTH(dsc->line_buffer_depth);
24451bf2f3bfSJani Nikula 
24461bf2f3bfSJani Nikula 	vdsc_cfg->block_pred_enable = dsc->block_prediction_enable;
24471bf2f3bfSJani Nikula 
24481bf2f3bfSJani Nikula 	vdsc_cfg->slice_height = dsc->slice_height;
24491bf2f3bfSJani Nikula }
24501bf2f3bfSJani Nikula 
24511bf2f3bfSJani Nikula /* FIXME: initially DSI specific */
24521bf2f3bfSJani Nikula bool intel_bios_get_dsc_params(struct intel_encoder *encoder,
24531bf2f3bfSJani Nikula 			       struct intel_crtc_state *crtc_state,
24541bf2f3bfSJani Nikula 			       int dsc_max_bpc)
24551bf2f3bfSJani Nikula {
24561bf2f3bfSJani Nikula 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
24571bf2f3bfSJani Nikula 	const struct display_device_data *devdata;
24581bf2f3bfSJani Nikula 	const struct child_device_config *child;
24591bf2f3bfSJani Nikula 
24601bf2f3bfSJani Nikula 	list_for_each_entry(devdata, &i915->vbt.display_devices, node) {
24611bf2f3bfSJani Nikula 		child = &devdata->child;
24621bf2f3bfSJani Nikula 
24631bf2f3bfSJani Nikula 		if (!(child->device_type & DEVICE_TYPE_MIPI_OUTPUT))
24641bf2f3bfSJani Nikula 			continue;
24651bf2f3bfSJani Nikula 
24661bf2f3bfSJani Nikula 		if (child->dvo_port - DVO_PORT_MIPIA == encoder->port) {
24671bf2f3bfSJani Nikula 			if (!devdata->dsc)
24681bf2f3bfSJani Nikula 				return false;
24691bf2f3bfSJani Nikula 
24701bf2f3bfSJani Nikula 			if (crtc_state)
24711bf2f3bfSJani Nikula 				fill_dsc(crtc_state, devdata->dsc, dsc_max_bpc);
24721bf2f3bfSJani Nikula 
24731bf2f3bfSJani Nikula 			return true;
24741bf2f3bfSJani Nikula 		}
24751bf2f3bfSJani Nikula 	}
24761bf2f3bfSJani Nikula 
24771bf2f3bfSJani Nikula 	return false;
24781bf2f3bfSJani Nikula }
24791bf2f3bfSJani Nikula 
2480df0566a6SJani Nikula /**
2481df0566a6SJani Nikula  * intel_bios_is_port_hpd_inverted - is HPD inverted for %port
2482df0566a6SJani Nikula  * @i915:	i915 device instance
2483df0566a6SJani Nikula  * @port:	port to check
2484df0566a6SJani Nikula  *
2485df0566a6SJani Nikula  * Return true if HPD should be inverted for %port.
2486df0566a6SJani Nikula  */
2487df0566a6SJani Nikula bool
2488df0566a6SJani Nikula intel_bios_is_port_hpd_inverted(const struct drm_i915_private *i915,
2489df0566a6SJani Nikula 				enum port port)
2490df0566a6SJani Nikula {
2491df0566a6SJani Nikula 	const struct child_device_config *child =
2492df0566a6SJani Nikula 		i915->vbt.ddi_port_info[port].child;
2493df0566a6SJani Nikula 
2494df0566a6SJani Nikula 	if (WARN_ON_ONCE(!IS_GEN9_LP(i915)))
2495df0566a6SJani Nikula 		return false;
2496df0566a6SJani Nikula 
2497df0566a6SJani Nikula 	return child && child->hpd_invert;
2498df0566a6SJani Nikula }
2499df0566a6SJani Nikula 
2500df0566a6SJani Nikula /**
2501df0566a6SJani Nikula  * intel_bios_is_lspcon_present - if LSPCON is attached on %port
2502df0566a6SJani Nikula  * @i915:	i915 device instance
2503df0566a6SJani Nikula  * @port:	port to check
2504df0566a6SJani Nikula  *
2505df0566a6SJani Nikula  * Return true if LSPCON is present on this port
2506df0566a6SJani Nikula  */
2507df0566a6SJani Nikula bool
2508df0566a6SJani Nikula intel_bios_is_lspcon_present(const struct drm_i915_private *i915,
2509df0566a6SJani Nikula 			     enum port port)
2510df0566a6SJani Nikula {
2511df0566a6SJani Nikula 	const struct child_device_config *child =
2512df0566a6SJani Nikula 		i915->vbt.ddi_port_info[port].child;
2513df0566a6SJani Nikula 
2514df0566a6SJani Nikula 	return HAS_LSPCON(i915) && child && child->lspcon;
2515df0566a6SJani Nikula }
2516df0566a6SJani Nikula 
2517df0566a6SJani Nikula enum aux_ch intel_bios_port_aux_ch(struct drm_i915_private *dev_priv,
2518df0566a6SJani Nikula 				   enum port port)
2519df0566a6SJani Nikula {
2520df0566a6SJani Nikula 	const struct ddi_vbt_port_info *info =
2521df0566a6SJani Nikula 		&dev_priv->vbt.ddi_port_info[port];
2522df0566a6SJani Nikula 	enum aux_ch aux_ch;
2523df0566a6SJani Nikula 
2524df0566a6SJani Nikula 	if (!info->alternate_aux_channel) {
2525df0566a6SJani Nikula 		aux_ch = (enum aux_ch)port;
2526df0566a6SJani Nikula 
2527df0566a6SJani Nikula 		DRM_DEBUG_KMS("using AUX %c for port %c (platform default)\n",
2528df0566a6SJani Nikula 			      aux_ch_name(aux_ch), port_name(port));
2529df0566a6SJani Nikula 		return aux_ch;
2530df0566a6SJani Nikula 	}
2531df0566a6SJani Nikula 
2532df0566a6SJani Nikula 	switch (info->alternate_aux_channel) {
2533df0566a6SJani Nikula 	case DP_AUX_A:
2534df0566a6SJani Nikula 		aux_ch = AUX_CH_A;
2535df0566a6SJani Nikula 		break;
2536df0566a6SJani Nikula 	case DP_AUX_B:
2537df0566a6SJani Nikula 		aux_ch = AUX_CH_B;
2538df0566a6SJani Nikula 		break;
2539df0566a6SJani Nikula 	case DP_AUX_C:
2540df0566a6SJani Nikula 		aux_ch = AUX_CH_C;
2541df0566a6SJani Nikula 		break;
2542df0566a6SJani Nikula 	case DP_AUX_D:
2543df0566a6SJani Nikula 		aux_ch = AUX_CH_D;
2544df0566a6SJani Nikula 		break;
2545df0566a6SJani Nikula 	case DP_AUX_E:
2546df0566a6SJani Nikula 		aux_ch = AUX_CH_E;
2547df0566a6SJani Nikula 		break;
2548df0566a6SJani Nikula 	case DP_AUX_F:
2549df0566a6SJani Nikula 		aux_ch = AUX_CH_F;
2550df0566a6SJani Nikula 		break;
2551eb8de23cSKhaled Almahallawy 	case DP_AUX_G:
2552eb8de23cSKhaled Almahallawy 		aux_ch = AUX_CH_G;
2553eb8de23cSKhaled Almahallawy 		break;
2554df0566a6SJani Nikula 	default:
2555df0566a6SJani Nikula 		MISSING_CASE(info->alternate_aux_channel);
2556df0566a6SJani Nikula 		aux_ch = AUX_CH_A;
2557df0566a6SJani Nikula 		break;
2558df0566a6SJani Nikula 	}
2559df0566a6SJani Nikula 
2560df0566a6SJani Nikula 	DRM_DEBUG_KMS("using AUX %c for port %c (VBT)\n",
2561df0566a6SJani Nikula 		      aux_ch_name(aux_ch), port_name(port));
2562df0566a6SJani Nikula 
2563df0566a6SJani Nikula 	return aux_ch;
2564df0566a6SJani Nikula }
2565