• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright � 2006 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  *
23  * Authors:
24  *    Eric Anholt <eric@anholt.net>
25  *
26  */
27 
28 #include <ctype.h>
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <getopt.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <unistd.h>
36 #include <sys/mman.h>
37 #include <sys/stat.h>
38 #include <sys/types.h>
39 
40 #include "igt_aux.h"
41 #include "intel_io.h"
42 #include "intel_chipset.h"
43 #include "drmtest.h"
44 
45 /* kernel types for intel_vbt_defs.h */
46 typedef uint8_t u8;
47 typedef uint16_t u16;
48 typedef uint32_t u32;
49 typedef uint64_t u64;
50 #define __packed __attribute__ ((packed))
51 
52 #define _INTEL_BIOS_PRIVATE
53 #include "intel_vbt_defs.h"
54 
55 /* no bother to include "edid.h" */
56 #define _H_ACTIVE(x) (x[2] + ((x[4] & 0xF0) << 4))
57 #define _H_SYNC_OFF(x) (x[8] + ((x[11] & 0xC0) << 2))
58 #define _H_SYNC_WIDTH(x) (x[9] + ((x[11] & 0x30) << 4))
59 #define _H_BLANK(x) (x[3] + ((x[4] & 0x0F) << 8))
60 #define _V_ACTIVE(x) (x[5] + ((x[7] & 0xF0) << 4))
61 #define _V_SYNC_OFF(x) ((x[10] >> 4) + ((x[11] & 0x0C) << 2))
62 #define _V_SYNC_WIDTH(x) ((x[10] & 0x0F) + ((x[11] & 0x03) << 4))
63 #define _V_BLANK(x) (x[6] + ((x[7] & 0x0F) << 8))
64 #define _PIXEL_CLOCK(x) (x[0] + (x[1] << 8)) * 10000
65 
66 #define YESNO(val) ((val) ? "yes" : "no")
67 
68 /* This is not for mapping to memory layout. */
69 struct bdb_block {
70 	uint8_t id;
71 	uint32_t size;
72 	const void *data;
73 };
74 
75 struct context {
76 	const struct vbt_header *vbt;
77 	const struct bdb_header *bdb;
78 	int size;
79 
80 	uint32_t devid;
81 	int panel_type;
82 	bool dump_all_panel_types;
83 	bool hexdump;
84 };
85 
86 /* Get BDB block size given a pointer to Block ID. */
_get_blocksize(const uint8_t * block_base)87 static uint32_t _get_blocksize(const uint8_t *block_base)
88 {
89 	/* The MIPI Sequence Block v3+ has a separate size field. */
90 	if (*block_base == BDB_MIPI_SEQUENCE && *(block_base + 3) >= 3)
91 		return *((const uint32_t *)(block_base + 4));
92 	else
93 		return *((const uint16_t *)(block_base + 1));
94 }
95 
find_section(struct context * context,int section_id)96 static struct bdb_block *find_section(struct context *context, int section_id)
97 {
98 	const struct bdb_header *bdb = context->bdb;
99 	int length = context->size;
100 	struct bdb_block *block;
101 	const uint8_t *base = (const uint8_t *)bdb;
102 	int index = 0;
103 	uint32_t total, current_size;
104 	unsigned char current_id;
105 
106 	/* skip to first section */
107 	index += bdb->header_size;
108 	total = bdb->bdb_size;
109 	if (total > length)
110 		total = length;
111 
112 	block = malloc(sizeof(*block));
113 	if (!block) {
114 		fprintf(stderr, "out of memory\n");
115 		exit(EXIT_FAILURE);
116 	}
117 
118 	/* walk the sections looking for section_id */
119 	while (index + 3 < total) {
120 		current_id = *(base + index);
121 		current_size = _get_blocksize(base + index);
122 		index += 3;
123 
124 		if (index + current_size > total)
125 			return NULL;
126 
127 		if (current_id == section_id) {
128 			block->id = current_id;
129 			block->size = current_size;
130 			block->data = base + index;
131 			return block;
132 		}
133 
134 		index += current_size;
135 	}
136 
137 	free(block);
138 	return NULL;
139 }
140 
dump_general_features(struct context * context,const struct bdb_block * block)141 static void dump_general_features(struct context *context,
142 				  const struct bdb_block *block)
143 {
144 	const struct bdb_general_features *features = block->data;
145 
146 	printf("\tPanel fitting: ");
147 	switch (features->panel_fitting) {
148 	case 0:
149 		printf("disabled\n");
150 		break;
151 	case 1:
152 		printf("text only\n");
153 		break;
154 	case 2:
155 		printf("graphics only\n");
156 		break;
157 	case 3:
158 		printf("text & graphics\n");
159 		break;
160 	}
161 	printf("\tFlexaim: %s\n", YESNO(features->flexaim));
162 	printf("\tMessage: %s\n", YESNO(features->msg_enable));
163 	printf("\tClear screen: %d\n", features->clear_screen);
164 	printf("\tDVO color flip required: %s\n", YESNO(features->color_flip));
165 
166 	printf("\tExternal VBT: %s\n", YESNO(features->download_ext_vbt));
167 	printf("\tEnable SSC: %s\n", YESNO(features->enable_ssc));
168 	if (features->enable_ssc) {
169 		if (!context->devid)
170 			printf("\tSSC frequency: <unknown platform>\n");
171 		else if (IS_VALLEYVIEW(context->devid) ||
172 			 IS_CHERRYVIEW(context->devid) ||
173 			 IS_BROXTON(context->devid))
174 			printf("\tSSC frequency: 100 MHz\n");
175 		else if (HAS_PCH_SPLIT(context->devid))
176 			printf("\tSSC frequency: %s\n", features->ssc_freq ?
177 			       "100 MHz" : "120 MHz");
178 		else
179 			printf("\tSSC frequency: %s\n", features->ssc_freq ?
180 			       "100 MHz (66 MHz on 855)" : "96 MHz (48 MHz on 855)");
181 	}
182 	printf("\tLFP on override: %s\n",
183 	       YESNO(features->enable_lfp_on_override));
184 	printf("\tDisable SSC on clone: %s\n",
185 	       YESNO(features->disable_ssc_ddt));
186 	printf("\tUnderscan support for VGA timings: %s\n",
187 	       YESNO(features->underscan_vga_timings));
188 	if (context->bdb->version >= 183)
189 		printf("\tDynamic CD clock: %s\n", YESNO(features->display_clock_mode));
190 	printf("\tHotplug support in VBIOS: %s\n",
191 	       YESNO(features->vbios_hotplug_support));
192 
193 	printf("\tDisable smooth vision: %s\n",
194 	       YESNO(features->disable_smooth_vision));
195 	printf("\tSingle DVI for CRT/DVI: %s\n", YESNO(features->single_dvi));
196 	if (context->bdb->version >= 181)
197 		printf("\tEnable 180 degree rotation: %s\n", YESNO(features->rotate_180));
198 	printf("\tInverted FDI Rx polarity: %s\n", YESNO(features->fdi_rx_polarity_inverted));
199 	if (context->bdb->version >= 160) {
200 		printf("\tExtended VBIOS mode: %s\n", YESNO(features->vbios_extended_mode));
201 		printf("\tCopy iLFP DTD to SDVO LVDS DTD: %s\n", YESNO(features->copy_ilfp_dtd_to_sdvo_lvds_dtd));
202 		printf("\tBest fit panel timing algorithm: %s\n", YESNO(features->panel_best_fit_timing));
203 		printf("\tIgnore strap state: %s\n", YESNO(features->ignore_strap_state));
204 	}
205 
206 	printf("\tLegacy monitor detect: %s\n",
207 	       YESNO(features->legacy_monitor_detect));
208 
209 	printf("\tIntegrated CRT: %s\n", YESNO(features->int_crt_support));
210 	printf("\tIntegrated TV: %s\n", YESNO(features->int_tv_support));
211 	printf("\tIntegrated EFP: %s\n", YESNO(features->int_efp_support));
212 	printf("\tDP SSC enable: %s\n", YESNO(features->dp_ssc_enable));
213 	if (features->dp_ssc_enable) {
214 		if (IS_VALLEYVIEW(context->devid) || IS_CHERRYVIEW(context->devid) ||
215 		    IS_BROXTON(context->devid))
216 			printf("\tSSC frequency: 100 MHz\n");
217 		else if (HAS_PCH_SPLIT(context->devid))
218 			printf("\tSSC frequency: %s\n", features->dp_ssc_freq ?
219 			       "100 MHz" : "120 MHz");
220 		else
221 			printf("\tSSC frequency: %s\n", features->dp_ssc_freq ?
222 			       "100 MHz" : "96 MHz");
223 	}
224 	printf("\tDP SSC dongle supported: %s\n", YESNO(features->dp_ssc_dongle_supported));
225 }
226 
dump_backlight_info(struct context * context,const struct bdb_block * block)227 static void dump_backlight_info(struct context *context,
228 				const struct bdb_block *block)
229 {
230 	const struct bdb_lfp_backlight_data *backlight = block->data;
231 	const struct lfp_backlight_data_entry *blc;
232 
233 	if (sizeof(*blc) != backlight->entry_size) {
234 		printf("\tBacklight struct sizes don't match (expected %zu, got %u), skipping\n",
235 		     sizeof(*blc), backlight->entry_size);
236 		return;
237 	}
238 
239 	blc = &backlight->data[context->panel_type];
240 
241 	printf("\tInverter type: %d\n", blc->type);
242 	printf("\t     polarity: %d\n", blc->active_low_pwm);
243 	printf("\t     PWM freq: %d\n", blc->pwm_freq_hz);
244 	printf("\tMinimum brightness: %d\n", blc->min_brightness);
245 }
246 
247 static const struct {
248 	unsigned short type;
249 	const char *name;
250 } child_device_types[] = {
251 	{ DEVICE_TYPE_NONE, "none" },
252 	{ DEVICE_TYPE_CRT, "CRT" },
253 	{ DEVICE_TYPE_TV, "TV" },
254 	{ DEVICE_TYPE_EFP, "EFP" },
255 	{ DEVICE_TYPE_LFP, "LFP" },
256 	{ DEVICE_TYPE_CRT_DPMS, "CRT" },
257 	{ DEVICE_TYPE_CRT_DPMS_HOTPLUG, "CRT" },
258 	{ DEVICE_TYPE_TV_COMPOSITE, "TV composite" },
259 	{ DEVICE_TYPE_TV_MACROVISION, "TV" },
260 	{ DEVICE_TYPE_TV_RF_COMPOSITE, "TV" },
261 	{ DEVICE_TYPE_TV_SVIDEO_COMPOSITE, "TV S-Video" },
262 	{ DEVICE_TYPE_TV_SCART, "TV SCART" },
263 	{ DEVICE_TYPE_TV_CODEC_HOTPLUG_PWR, "TV" },
264 	{ DEVICE_TYPE_EFP_HOTPLUG_PWR, "EFP" },
265 	{ DEVICE_TYPE_EFP_DVI_HOTPLUG_PWR, "DVI" },
266 	{ DEVICE_TYPE_EFP_DVI_I, "DVI-I" },
267 	{ DEVICE_TYPE_EFP_DVI_D_DUAL, "DL-DVI-D" },
268 	{ DEVICE_TYPE_EFP_DVI_D_HDCP, "DVI-D" },
269 	{ DEVICE_TYPE_OPENLDI_HOTPLUG_PWR, "OpenLDI" },
270 	{ DEVICE_TYPE_OPENLDI_DUALPIX, "OpenLDI" },
271 	{ DEVICE_TYPE_LFP_PANELLINK, "PanelLink" },
272 	{ DEVICE_TYPE_LFP_CMOS_PWR, "CMOS LFP" },
273 	{ DEVICE_TYPE_LFP_LVDS_PWR, "LVDS" },
274 	{ DEVICE_TYPE_LFP_LVDS_DUAL, "LVDS" },
275 	{ DEVICE_TYPE_LFP_LVDS_DUAL_HDCP, "LVDS" },
276 	{ DEVICE_TYPE_INT_LFP, "LFP" },
277 	{ DEVICE_TYPE_INT_TV, "TV" },
278 	{ DEVICE_TYPE_DP, "DisplayPort" },
279 	{ DEVICE_TYPE_DP_DUAL_MODE, "DisplayPort/HDMI/DVI" },
280 	{ DEVICE_TYPE_DP_DVI, "DisplayPort/DVI" },
281 	{ DEVICE_TYPE_HDMI, "HDMI/DVI" },
282 	{ DEVICE_TYPE_DVI, "DVI" },
283 	{ DEVICE_TYPE_eDP, "eDP" },
284 	{ DEVICE_TYPE_MIPI, "MIPI" },
285 };
286 static const int num_child_device_types =
287 	sizeof(child_device_types) / sizeof(child_device_types[0]);
288 
child_device_type(unsigned short type)289 static const char *child_device_type(unsigned short type)
290 {
291 	int i;
292 
293 	for (i = 0; i < num_child_device_types; i++)
294 		if (child_device_types[i].type == type)
295 			return child_device_types[i].name;
296 
297 	return "unknown";
298 }
299 
300 static const struct {
301 	unsigned short mask;
302 	const char *name;
303 } child_device_type_bits[] = {
304 	{ DEVICE_TYPE_CLASS_EXTENSION, "Class extension" },
305 	{ DEVICE_TYPE_POWER_MANAGEMENT, "Power management" },
306 	{ DEVICE_TYPE_HOTPLUG_SIGNALING, "Hotplug signaling" },
307 	{ DEVICE_TYPE_INTERNAL_CONNECTOR, "Internal connector" },
308 	{ DEVICE_TYPE_NOT_HDMI_OUTPUT, "HDMI output" }, /* decoded as inverse */
309 	{ DEVICE_TYPE_MIPI_OUTPUT, "MIPI output" },
310 	{ DEVICE_TYPE_COMPOSITE_OUTPUT, "Composite output" },
311 	{ DEVICE_TYPE_DUAL_CHANNEL, "Dual channel" },
312 	{ 1 << 7, "Content protection" },
313 	{ DEVICE_TYPE_HIGH_SPEED_LINK, "High speed link" },
314 	{ DEVICE_TYPE_LVDS_SIGNALING, "LVDS signaling" },
315 	{ DEVICE_TYPE_TMDS_DVI_SIGNALING, "TMDS/DVI signaling" },
316 	{ DEVICE_TYPE_VIDEO_SIGNALING, "Video signaling" },
317 	{ DEVICE_TYPE_DISPLAYPORT_OUTPUT, "DisplayPort output" },
318 	{ DEVICE_TYPE_DIGITAL_OUTPUT, "Digital output" },
319 	{ DEVICE_TYPE_ANALOG_OUTPUT, "Analog output" },
320 };
321 
dump_child_device_type_bits(uint16_t type)322 static void dump_child_device_type_bits(uint16_t type)
323 {
324 	int i;
325 
326 	type ^= DEVICE_TYPE_NOT_HDMI_OUTPUT;
327 
328 	for (i = 0; i < ARRAY_SIZE(child_device_type_bits); i++) {
329 		if (child_device_type_bits[i].mask & type)
330 			printf("\t\t\t%s\n", child_device_type_bits[i].name);
331 	}
332 }
333 
334 static const struct {
335 	unsigned char handle;
336 	const char *name;
337 } child_device_handles[] = {
338 	{ DEVICE_HANDLE_CRT, "CRT" },
339 	{ DEVICE_HANDLE_EFP1, "EFP 1 (HDMI/DVI/DP)" },
340 	{ DEVICE_HANDLE_EFP2, "EFP 2 (HDMI/DVI/DP)" },
341 	{ DEVICE_HANDLE_EFP3, "EFP 3 (HDMI/DVI/DP)" },
342 	{ DEVICE_HANDLE_EFP4, "EFP 4 (HDMI/DVI/DP)" },
343 	{ DEVICE_HANDLE_LPF1, "LFP 1 (eDP)" },
344 	{ DEVICE_HANDLE_LFP2, "LFP 2 (eDP)" },
345 };
346 static const int num_child_device_handles =
347 	sizeof(child_device_handles) / sizeof(child_device_handles[0]);
348 
child_device_handle(unsigned char handle)349 static const char *child_device_handle(unsigned char handle)
350 {
351 	int i;
352 
353 	for (i = 0; i < num_child_device_handles; i++)
354 		if (child_device_handles[i].handle == handle)
355 			return child_device_handles[i].name;
356 
357 	return "unknown";
358 }
359 
360 static const char *dvo_port_names[] = {
361 	[DVO_PORT_HDMIA] = "HDMI-A",
362 	[DVO_PORT_HDMIB] = "HDMI-B",
363 	[DVO_PORT_HDMIC] = "HDMI-C",
364 	[DVO_PORT_HDMID] = "HDMI-D",
365 	[DVO_PORT_LVDS] = "LVDS",
366 	[DVO_PORT_TV] = "TV",
367 	[DVO_PORT_CRT] = "CRT",
368 	[DVO_PORT_DPB] = "DP-B",
369 	[DVO_PORT_DPC] = "DP-C",
370 	[DVO_PORT_DPD] = "DP-D",
371 	[DVO_PORT_DPA] = "DP-A",
372 	[DVO_PORT_DPE] = "DP-E",
373 	[DVO_PORT_HDMIE] = "HDMI-E",
374 	[DVO_PORT_MIPIA] = "MIPI-A",
375 	[DVO_PORT_MIPIB] = "MIPI-B",
376 	[DVO_PORT_MIPIC] = "MIPI-C",
377 	[DVO_PORT_MIPID] = "MIPI-D",
378 };
379 
dvo_port(uint8_t type)380 static const char *dvo_port(uint8_t type)
381 {
382 	if (type < ARRAY_SIZE(dvo_port_names) && dvo_port_names[type])
383 		return dvo_port_names[type];
384 	else
385 		return "unknown";
386 }
387 
mipi_bridge_type(uint8_t type)388 static const char *mipi_bridge_type(uint8_t type)
389 {
390 	switch (type) {
391 	case 1:
392 		return "ASUS";
393 	case 2:
394 		return "Toshiba";
395 	case 3:
396 		return "Renesas";
397 	default:
398 		return "unknown";
399 	}
400 }
401 
dump_hmdi_max_data_rate(uint8_t hdmi_max_data_rate)402 static void dump_hmdi_max_data_rate(uint8_t hdmi_max_data_rate)
403 {
404 	static const uint16_t max_data_rate[] = {
405 		[HDMI_MAX_DATA_RATE_PLATFORM] = 0,
406 		[HDMI_MAX_DATA_RATE_297] = 297,
407 		[HDMI_MAX_DATA_RATE_165] = 165,
408 	};
409 
410 	if (hdmi_max_data_rate >= ARRAY_SIZE(max_data_rate))
411 		printf("\t\tHDMI max data rate: <unknown> (0x%02x)\n",
412 		       hdmi_max_data_rate);
413 	else if (hdmi_max_data_rate == HDMI_MAX_DATA_RATE_PLATFORM)
414 		printf("\t\tHDMI max data rate: <platform max> (0x%02x)\n",
415 		       hdmi_max_data_rate);
416 	else
417 		printf("\t\tHDMI max data rate: %d MHz (0x%02x)\n",
418 		       max_data_rate[hdmi_max_data_rate],
419 		       hdmi_max_data_rate);
420 }
421 
dump_child_device(struct context * context,const struct child_device_config * child)422 static void dump_child_device(struct context *context,
423 			      const struct child_device_config *child)
424 {
425 	if (!child->device_type)
426 		return;
427 
428 	printf("\tChild device info:\n");
429 	printf("\t\tDevice handle: 0x%04x (%s)\n", child->handle,
430 	       child_device_handle(child->handle));
431 	printf("\t\tDevice type: 0x%04x (%s)\n", child->device_type,
432 	       child_device_type(child->device_type));
433 	dump_child_device_type_bits(child->device_type);
434 
435 	if (context->bdb->version < 152) {
436 		printf("\t\tSignature: %.*s\n", (int)sizeof(child->device_id), child->device_id);
437 	} else {
438 		printf("\t\tI2C speed: 0x%02x\n", child->i2c_speed);
439 		printf("\t\tDP onboard redriver: 0x%02x\n", child->dp_onboard_redriver);
440 		printf("\t\tDP ondock redriver: 0x%02x\n", child->dp_ondock_redriver);
441 		printf("\t\tHDMI level shifter value: 0x%02x\n", child->hdmi_level_shifter_value);
442 		dump_hmdi_max_data_rate(child->hdmi_max_data_rate);
443 		printf("\t\tOffset to DTD buffer for edidless CHILD: 0x%02x\n", child->dtd_buf_ptr);
444 		printf("\t\tEdidless EFP: %s\n", YESNO(child->edidless_efp));
445 		printf("\t\tCompression enable: %s\n", YESNO(child->compression_enable));
446 		printf("\t\tCompression method CPS: %s\n", YESNO(child->compression_method));
447 		printf("\t\tDual pipe ganged eDP: %s\n", YESNO(child->ganged_edp));
448 		printf("\t\tCompression structure index: 0x%02x)\n", child->compression_structure_index);
449 		printf("\t\tSlave DDI port: 0x%02x (%s)\n", child->slave_port, dvo_port(child->slave_port));
450 	}
451 
452 	printf("\t\tAIM offset: %d\n", child->addin_offset);
453 	printf("\t\tDVO Port: 0x%02x (%s)\n", child->dvo_port, dvo_port(child->dvo_port));
454 
455 	printf("\t\tAIM I2C pin: 0x%02x\n", child->i2c_pin);
456 	printf("\t\tAIM Slave address: 0x%02x\n", child->slave_addr);
457 	printf("\t\tDDC pin: 0x%02x\n", child->ddc_pin);
458 	printf("\t\tEDID buffer ptr: 0x%02x\n", child->edid_ptr);
459 	printf("\t\tDVO config: 0x%02x\n", child->dvo_cfg);
460 
461 	if (context->bdb->version < 155) {
462 		printf("\t\tDVO2 Port: 0x%02x (%s)\n", child->dvo2_port, dvo_port(child->dvo2_port));
463 		printf("\t\tI2C2 pin: 0x%02x\n", child->i2c2_pin);
464 		printf("\t\tSlave2 address: 0x%02x\n", child->slave2_addr);
465 		printf("\t\tDDC2 pin: 0x%02x\n", child->ddc2_pin);
466 	} else {
467 		printf("\t\tEFP routed through dock: %s\n", YESNO(child->efp_routed));
468 		printf("\t\tLane reversal: %s\n", YESNO(child->lane_reversal));
469 		printf("\t\tOnboard LSPCON: %s\n", YESNO(child->lspcon));
470 		printf("\t\tIboost enable: %s\n", YESNO(child->iboost));
471 		printf("\t\tHPD sense invert: %s\n", YESNO(child->hpd_invert));
472 		printf("\t\tHDMI compatible? %s\n", YESNO(child->hdmi_support));
473 		printf("\t\tDP compatible? %s\n", YESNO(child->dp_support));
474 		printf("\t\tTMDS compatible? %s\n", YESNO(child->tmds_support));
475 		printf("\t\tAux channel: 0x%02x\n", child->aux_channel);
476 		printf("\t\tDongle detect: 0x%02x\n", child->dongle_detect);
477 	}
478 
479 	printf("\t\tPipe capabilities: 0x%02x\n", child->pipe_cap);
480 	printf("\t\tSDVO stall signal available: %s\n", YESNO(child->sdvo_stall));
481 	printf("\t\tHotplug connect status: 0x%02x\n", child->hpd_status);
482 	printf("\t\tIntegrated encoder instead of SDVO: %s\n", YESNO(child->integrated_encoder));
483 	printf("\t\tDVO wiring: 0x%02x\n", child->dvo_wiring);
484 
485 	if (context->bdb->version < 171) {
486 		printf("\t\tDVO2 wiring: 0x%02x\n", child->dvo2_wiring);
487 	} else {
488 		printf("\t\tMIPI bridge type: %02x (%s)\n", child->mipi_bridge_type,
489 		       mipi_bridge_type(child->mipi_bridge_type));
490 	}
491 
492 	printf("\t\tDevice class extension: 0x%02x\n", child->extended_type);
493 	printf("\t\tDVO function: 0x%02x\n", child->dvo_function);
494 
495 	if (context->bdb->version >= 195) {
496 		printf("\t\tDP USB type C support: %s\n", YESNO(child->dp_usb_type_c));
497 		printf("\t\t2X DP GPIO index: 0x%02x\n", child->dp_gpio_index);
498 		printf("\t\t2X DP GPIO pin number: 0x%02x\n", child->dp_gpio_pin_num);
499 	}
500 
501 	if (context->bdb->version >= 196) {
502 		printf("\t\tIBoost level for HDMI: 0x%02x\n", child->hdmi_iboost_level);
503 		printf("\t\tIBoost level for DP/eDP: 0x%02x\n", child->dp_iboost_level);
504 	}
505 }
506 
507 
dump_child_devices(struct context * context,const uint8_t * devices,uint8_t child_dev_num,uint8_t child_dev_size)508 static void dump_child_devices(struct context *context, const uint8_t *devices,
509 			       uint8_t child_dev_num, uint8_t child_dev_size)
510 {
511 	struct child_device_config *child;
512 	int i;
513 
514 	/*
515 	 * Use a temp buffer so dump_child_device() doesn't have to worry about
516 	 * accessing the struct beyond child_dev_size. The tail, if any, remains
517 	 * initialized to zero.
518 	 */
519 	child = calloc(1, sizeof(*child));
520 
521 	for (i = 0; i < child_dev_num; i++) {
522 		memcpy(child, devices + i * child_dev_size,
523 		       min(sizeof(*child), child_dev_size));
524 
525 		dump_child_device(context, child);
526 	}
527 
528 	free(child);
529 }
530 
dump_general_definitions(struct context * context,const struct bdb_block * block)531 static void dump_general_definitions(struct context *context,
532 				     const struct bdb_block *block)
533 {
534 	const struct bdb_general_definitions *defs = block->data;
535 	int child_dev_num;
536 
537 	child_dev_num = (block->size - sizeof(*defs)) / defs->child_dev_size;
538 
539 	printf("\tCRT DDC GMBUS addr: 0x%02x\n", defs->crt_ddc_gmbus_pin);
540 	printf("\tUse ACPI DPMS CRT power states: %s\n",
541 	       YESNO(defs->dpms_acpi));
542 	printf("\tSkip CRT detect at boot: %s\n",
543 	       YESNO(defs->skip_boot_crt_detect));
544 	printf("\tUse DPMS on AIM devices: %s\n", YESNO(defs->dpms_aim));
545 	printf("\tBoot display type: 0x%02x%02x\n", defs->boot_display[1],
546 	       defs->boot_display[0]);
547 	printf("\tChild device size: %d\n", defs->child_dev_size);
548 	printf("\tChild device count: %d\n", child_dev_num);
549 
550 	dump_child_devices(context, defs->devices,
551 			   child_dev_num, defs->child_dev_size);
552 }
553 
dump_legacy_child_devices(struct context * context,const struct bdb_block * block)554 static void dump_legacy_child_devices(struct context *context,
555 				      const struct bdb_block *block)
556 {
557 	const struct bdb_legacy_child_devices *defs = block->data;
558 	int child_dev_num;
559 
560 	child_dev_num = (block->size - sizeof(*defs)) / defs->child_dev_size;
561 
562 	printf("\tChild device size: %d\n", defs->child_dev_size);
563 	printf("\tChild device count: %d\n", child_dev_num);
564 
565 	dump_child_devices(context, defs->devices,
566 			   child_dev_num, defs->child_dev_size);
567 }
568 
dump_lvds_options(struct context * context,const struct bdb_block * block)569 static void dump_lvds_options(struct context *context,
570 			      const struct bdb_block *block)
571 {
572 	const struct bdb_lvds_options *options = block->data;
573 
574 	if (context->panel_type == options->panel_type)
575 		printf("\tPanel type: %d\n", options->panel_type);
576 	else
577 		printf("\tPanel type: %d (override %d)\n",
578 		       options->panel_type, context->panel_type);
579 	printf("\tLVDS EDID available: %s\n", YESNO(options->lvds_edid));
580 	printf("\tPixel dither: %s\n", YESNO(options->pixel_dither));
581 	printf("\tPFIT auto ratio: %s\n", YESNO(options->pfit_ratio_auto));
582 	printf("\tPFIT enhanced graphics mode: %s\n",
583 	       YESNO(options->pfit_gfx_mode_enhanced));
584 	printf("\tPFIT enhanced text mode: %s\n",
585 	       YESNO(options->pfit_text_mode_enhanced));
586 	printf("\tPFIT mode: %d\n", options->pfit_mode);
587 }
588 
dump_lvds_ptr_data(struct context * context,const struct bdb_block * block)589 static void dump_lvds_ptr_data(struct context *context,
590 			       const struct bdb_block *block)
591 {
592 	const struct bdb_lvds_lfp_data_ptrs *ptrs = block->data;
593 
594 	printf("\tNumber of entries: %d\n", ptrs->lvds_entries);
595 }
596 
dump_lvds_data(struct context * context,const struct bdb_block * block)597 static void dump_lvds_data(struct context *context,
598 			   const struct bdb_block *block)
599 {
600 	const struct bdb_lvds_lfp_data *lvds_data = block->data;
601 	struct bdb_block *ptrs_block;
602 	const struct bdb_lvds_lfp_data_ptrs *ptrs;
603 	int num_entries;
604 	int i;
605 	int hdisplay, hsyncstart, hsyncend, htotal;
606 	int vdisplay, vsyncstart, vsyncend, vtotal;
607 	float clock;
608 	int lfp_data_size, dvo_offset;
609 
610 	ptrs_block = find_section(context, BDB_LVDS_LFP_DATA_PTRS);
611 	if (!ptrs_block) {
612 		printf("No LVDS ptr block\n");
613 		return;
614 	}
615 
616 	ptrs = ptrs_block->data;
617 
618 	lfp_data_size =
619 	    ptrs->ptr[1].fp_timing_offset - ptrs->ptr[0].fp_timing_offset;
620 	dvo_offset =
621 	    ptrs->ptr[0].dvo_timing_offset - ptrs->ptr[0].fp_timing_offset;
622 
623 	num_entries = block->size / lfp_data_size;
624 
625 	printf("  Number of entries: %d (preferred block marked with '*')\n",
626 	       num_entries);
627 
628 	for (i = 0; i < num_entries; i++) {
629 		const uint8_t *lfp_data_ptr =
630 		    (const uint8_t *) lvds_data->data + lfp_data_size * i;
631 		const uint8_t *timing_data = lfp_data_ptr + dvo_offset;
632 		const struct lvds_lfp_data_entry *lfp_data =
633 		    (const struct lvds_lfp_data_entry *)lfp_data_ptr;
634 		char marker;
635 
636 		if (i != context->panel_type && !context->dump_all_panel_types)
637 			continue;
638 
639 		if (i == context->panel_type)
640 			marker = '*';
641 		else
642 			marker = ' ';
643 
644 		hdisplay = _H_ACTIVE(timing_data);
645 		hsyncstart = hdisplay + _H_SYNC_OFF(timing_data);
646 		hsyncend = hsyncstart + _H_SYNC_WIDTH(timing_data);
647 		htotal = hdisplay + _H_BLANK(timing_data);
648 
649 		vdisplay = _V_ACTIVE(timing_data);
650 		vsyncstart = vdisplay + _V_SYNC_OFF(timing_data);
651 		vsyncend = vsyncstart + _V_SYNC_WIDTH(timing_data);
652 		vtotal = vdisplay + _V_BLANK(timing_data);
653 		clock = _PIXEL_CLOCK(timing_data) / 1000;
654 
655 		printf("%c\tpanel type %02i: %dx%d clock %d\n", marker,
656 		       i, lfp_data->fp_timing.x_res, lfp_data->fp_timing.y_res,
657 		       _PIXEL_CLOCK(timing_data));
658 		printf("\t\tinfo:\n");
659 		printf("\t\t  LVDS: 0x%08lx\n",
660 		       (unsigned long)lfp_data->fp_timing.lvds_reg_val);
661 		printf("\t\t  PP_ON_DELAYS: 0x%08lx\n",
662 		       (unsigned long)lfp_data->fp_timing.pp_on_reg_val);
663 		printf("\t\t  PP_OFF_DELAYS: 0x%08lx\n",
664 		       (unsigned long)lfp_data->fp_timing.pp_off_reg_val);
665 		printf("\t\t  PP_DIVISOR: 0x%08lx\n",
666 		       (unsigned long)lfp_data->fp_timing.pp_cycle_reg_val);
667 		printf("\t\t  PFIT: 0x%08lx\n",
668 		       (unsigned long)lfp_data->fp_timing.pfit_reg_val);
669 		printf("\t\ttimings: %d %d %d %d %d %d %d %d %.2f (%s)\n",
670 		       hdisplay, hsyncstart, hsyncend, htotal,
671 		       vdisplay, vsyncstart, vsyncend, vtotal, clock,
672 		       (hsyncend > htotal || vsyncend > vtotal) ?
673 		       "BAD!" : "good");
674 	}
675 
676 	free(ptrs_block);
677 }
678 
dump_driver_feature(struct context * context,const struct bdb_block * block)679 static void dump_driver_feature(struct context *context,
680 				const struct bdb_block *block)
681 {
682 	const struct bdb_driver_features *feature = block->data;
683 
684 	printf("\tBoot Device Algorithm: %s\n", feature->boot_dev_algorithm ?
685 	       "driver default" : "os default");
686 	printf("\tBlock display switching when DVD active: %s\n",
687 	       YESNO(feature->block_display_switch));
688 	printf("\tAllow display switching when in Full Screen DOS: %s\n",
689 	       YESNO(feature->allow_display_switch));
690 	printf("\tHot Plug DVO: %s\n", YESNO(feature->hotplug_dvo));
691 	printf("\tDual View Zoom: %s\n", YESNO(feature->dual_view_zoom));
692 	printf("\tDriver INT 15h hook: %s\n", YESNO(feature->int15h_hook));
693 	printf("\tEnable Sprite in Clone Mode: %s\n",
694 	       YESNO(feature->sprite_in_clone));
695 	printf("\tUse 00000110h ID for Primary LFP: %s\n",
696 	       YESNO(feature->primary_lfp_id));
697 	printf("\tBoot Mode X: %u\n", feature->boot_mode_x);
698 	printf("\tBoot Mode Y: %u\n", feature->boot_mode_y);
699 	printf("\tBoot Mode Bpp: %u\n", feature->boot_mode_bpp);
700 	printf("\tBoot Mode Refresh: %u\n", feature->boot_mode_refresh);
701 	printf("\tEnable LFP as primary: %s\n",
702 	       YESNO(feature->enable_lfp_primary));
703 	printf("\tSelective Mode Pruning: %s\n",
704 	       YESNO(feature->selective_mode_pruning));
705 	printf("\tDual-Frequency Graphics Technology: %s\n",
706 	       YESNO(feature->dual_frequency));
707 	printf("\tDefault Render Clock Frequency: %s\n",
708 	       feature->render_clock_freq ? "low" : "high");
709 	printf("\tNT 4.0 Dual Display Clone Support: %s\n",
710 	       YESNO(feature->nt_clone_support));
711 	printf("\tDefault Power Scheme user interface: %s\n",
712 	       feature->power_scheme_ui ? "3rd party" : "CUI");
713 	printf
714 	    ("\tSprite Display Assignment when Overlay is Active in Clone Mode: %s\n",
715 	     feature->sprite_display_assign ? "primary" : "secondary");
716 	printf("\tDisplay Maintain Aspect Scaling via CUI: %s\n",
717 	       YESNO(feature->cui_aspect_scaling));
718 	printf("\tPreserve Aspect Ratio: %s\n",
719 	       YESNO(feature->preserve_aspect_ratio));
720 	printf("\tEnable SDVO device power down: %s\n",
721 	       YESNO(feature->sdvo_device_power_down));
722 	printf("\tCRT hotplug: %s\n", YESNO(feature->crt_hotplug));
723 	printf("\tLVDS config: ");
724 	switch (feature->lvds_config) {
725 	case BDB_DRIVER_NO_LVDS:
726 		printf("No LVDS\n");
727 		break;
728 	case BDB_DRIVER_INT_LVDS:
729 		printf("Integrated LVDS\n");
730 		break;
731 	case BDB_DRIVER_SDVO_LVDS:
732 		printf("SDVO LVDS\n");
733 		break;
734 	case BDB_DRIVER_EDP:
735 		printf("Embedded DisplayPort\n");
736 		break;
737 	}
738 	printf("\tDefine Display statically: %s\n",
739 	       YESNO(feature->static_display));
740 	printf("\tLegacy CRT max X: %d\n", feature->legacy_crt_max_x);
741 	printf("\tLegacy CRT max Y: %d\n", feature->legacy_crt_max_y);
742 	printf("\tLegacy CRT max refresh: %d\n",
743 	       feature->legacy_crt_max_refresh);
744 	printf("\tEnable DRRS: %s\n", YESNO(feature->drrs_enabled));
745 	printf("\tEnable PSR: %s\n", YESNO(feature->psr_enabled));
746 }
747 
dump_edp(struct context * context,const struct bdb_block * block)748 static void dump_edp(struct context *context,
749 		     const struct bdb_block *block)
750 {
751 	const struct bdb_edp *edp = block->data;
752 	int bpp, msa;
753 	int i;
754 
755 	for (i = 0; i < 16; i++) {
756 		if (i != context->panel_type && !context->dump_all_panel_types)
757 			continue;
758 
759 		printf("\tPanel %d%s\n", i, context->panel_type == i ? " *" : "");
760 
761 		printf("\t\tPower Sequence: T3 %d T7 %d T9 %d T10 %d T12 %d\n",
762 		       edp->power_seqs[i].t3,
763 		       edp->power_seqs[i].t7,
764 		       edp->power_seqs[i].t9,
765 		       edp->power_seqs[i].t10,
766 		       edp->power_seqs[i].t12);
767 
768 		bpp = (edp->color_depth >> (i * 2)) & 3;
769 
770 		printf("\t\tPanel color depth: ");
771 		switch (bpp) {
772 		case EDP_18BPP:
773 			printf("18 bpp\n");
774 			break;
775 		case EDP_24BPP:
776 			printf("24 bpp\n");
777 			break;
778 		case EDP_30BPP:
779 			printf("30 bpp\n");
780 			break;
781 		default:
782 			printf("(unknown value %d)\n", bpp);
783 			break;
784 		}
785 
786 		msa = (edp->sdrrs_msa_timing_delay >> (i * 2)) & 3;
787 		printf("\t\teDP sDRRS MSA Delay: Lane %d\n", msa + 1);
788 
789 		printf("\t\tFast link params:\n");
790 		printf("\t\t\trate: ");
791 		if (edp->fast_link_params[i].rate == EDP_RATE_1_62)
792 			printf("1.62G\n");
793 		else if (edp->fast_link_params[i].rate == EDP_RATE_2_7)
794 			printf("2.7G\n");
795 		printf("\t\t\tlanes: ");
796 		switch (edp->fast_link_params[i].lanes) {
797 		case EDP_LANE_1:
798 			printf("x1 mode\n");
799 			break;
800 		case EDP_LANE_2:
801 			printf("x2 mode\n");
802 			break;
803 		case EDP_LANE_4:
804 			printf("x4 mode\n");
805 			break;
806 		default:
807 			printf("(unknown value %d)\n",
808 			       edp->fast_link_params[i].lanes);
809 			break;
810 		}
811 		printf("\t\t\tpre-emphasis: ");
812 		switch (edp->fast_link_params[i].preemphasis) {
813 		case EDP_PREEMPHASIS_NONE:
814 			printf("none\n");
815 			break;
816 		case EDP_PREEMPHASIS_3_5dB:
817 			printf("3.5dB\n");
818 			break;
819 		case EDP_PREEMPHASIS_6dB:
820 			printf("6dB\n");
821 			break;
822 		case EDP_PREEMPHASIS_9_5dB:
823 			printf("9.5dB\n");
824 			break;
825 		default:
826 			printf("(unknown value %d)\n",
827 			       edp->fast_link_params[i].preemphasis);
828 			break;
829 		}
830 		printf("\t\t\tvswing: ");
831 		switch (edp->fast_link_params[i].vswing) {
832 		case EDP_VSWING_0_4V:
833 			printf("0.4V\n");
834 			break;
835 		case EDP_VSWING_0_6V:
836 			printf("0.6V\n");
837 			break;
838 		case EDP_VSWING_0_8V:
839 			printf("0.8V\n");
840 			break;
841 		case EDP_VSWING_1_2V:
842 			printf("1.2V\n");
843 			break;
844 		default:
845 			printf("(unknown value %d)\n",
846 			       edp->fast_link_params[i].vswing);
847 			break;
848 		}
849 
850 		if (context->bdb->version >= 162) {
851 			bool val = (edp->edp_s3d_feature >> i) & 1;
852 			printf("\t\tStereo 3D feature: %s\n", YESNO(val));
853 		}
854 
855 		if (context->bdb->version >= 165) {
856 			bool val = (edp->edp_t3_optimization >> i) & 1;
857 			printf("\t\tT3 optimization: %s\n", YESNO(val));
858 		}
859 
860 		if (context->bdb->version >= 173) {
861 			int val = (edp->edp_vswing_preemph >> (i * 4)) & 0xf;
862 
863 			printf("\t\tVswing/preemphasis table selection: ");
864 			switch (val) {
865 			case 0:
866 				printf("Low power (200 mV)\n");
867 				break;
868 			case 1:
869 				printf("Default (400 mV)\n");
870 				break;
871 			default:
872 				printf("(unknown value %d)\n", val);
873 				break;
874 			}
875 		}
876 
877 		if (context->bdb->version >= 182) {
878 			bool val = (edp->fast_link_training >> i) & 1;
879 			printf("\t\tFast link training: %s\n", YESNO(val));
880 		}
881 
882 		if (context->bdb->version >= 185) {
883 			bool val = (edp->dpcd_600h_write_required >> i) & 1;
884 			printf("\t\tDPCD 600h write required: %s\n", YESNO(val));
885 		}
886 
887 		if (context->bdb->version >= 186) {
888 			printf("\t\tPWM delays:\n"
889 			       "\t\t\tPWM on to backlight enable: %d\n"
890 			       "\t\t\tBacklight disable to PWM off: %d\n",
891 			       edp->pwm_delays[i].pwm_on_to_backlight_enable,
892 			       edp->pwm_delays[i].backlight_disable_to_pwm_off);
893 		}
894 
895 		if (context->bdb->version >= 199) {
896 			bool val = (edp->full_link_params_provided >> i) & 1;
897 
898 			printf("\t\tFull link params provided: %s\n", YESNO(val));
899 			printf("\t\tFull link params:\n");
900 			printf("\t\t\tpre-emphasis: ");
901 			switch (edp->full_link_params[i].preemphasis) {
902 			case EDP_PREEMPHASIS_NONE:
903 				printf("none\n");
904 				break;
905 			case EDP_PREEMPHASIS_3_5dB:
906 				printf("3.5dB\n");
907 				break;
908 			case EDP_PREEMPHASIS_6dB:
909 				printf("6dB\n");
910 				break;
911 			case EDP_PREEMPHASIS_9_5dB:
912 				printf("9.5dB\n");
913 				break;
914 			default:
915 				printf("(unknown value %d)\n",
916 				       edp->full_link_params[i].preemphasis);
917 				break;
918 			}
919 			printf("\t\t\tvswing: ");
920 			switch (edp->full_link_params[i].vswing) {
921 			case EDP_VSWING_0_4V:
922 				printf("0.4V\n");
923 				break;
924 			case EDP_VSWING_0_6V:
925 				printf("0.6V\n");
926 				break;
927 			case EDP_VSWING_0_8V:
928 				printf("0.8V\n");
929 				break;
930 			case EDP_VSWING_1_2V:
931 				printf("1.2V\n");
932 				break;
933 			default:
934 				printf("(unknown value %d)\n",
935 				       edp->full_link_params[i].vswing);
936 				break;
937 			}
938 		}
939 	}
940 }
941 
dump_psr(struct context * context,const struct bdb_block * block)942 static void dump_psr(struct context *context,
943 		     const struct bdb_block *block)
944 {
945 	const struct bdb_psr *psr_block = block->data;
946 	int i;
947 	uint32_t psr2_tp_time;
948 
949 	/* The same block ID was used for something else before? */
950 	if (context->bdb->version < 165)
951 		return;
952 
953 	psr2_tp_time = psr_block->psr2_tp2_tp3_wakeup_time;
954 	for (i = 0; i < 16; i++) {
955 		const struct psr_table *psr = &psr_block->psr_table[i];
956 
957 		if (i != context->panel_type && !context->dump_all_panel_types)
958 			continue;
959 
960 		printf("\tPanel %d%s\n", i, context->panel_type == i ? " *" : "");
961 
962 		printf("\t\tFull link: %s\n", YESNO(psr->full_link));
963 		printf("\t\tRequire AUX to wakeup: %s\n", YESNO(psr->require_aux_to_wakeup));
964 
965 		switch (psr->lines_to_wait) {
966 		case 0:
967 		case 1:
968 			printf("\t\tLines to wait before link standby: %d\n",
969 			       psr->lines_to_wait);
970 			break;
971 		case 2:
972 		case 3:
973 			printf("\t\tLines to wait before link standby: %d\n",
974 			       1 << psr->lines_to_wait);
975 			break;
976 		default:
977 			printf("\t\tLines to wait before link standby: (unknown) (0x%x)\n",
978 			       psr->lines_to_wait);
979 			break;
980 		}
981 
982 		printf("\t\tIdle frames to for PSR enable: %d\n",
983 		       psr->idle_frames);
984 
985 		printf("\t\tTP1 wakeup time: %d usec (0x%x)\n",
986 		       psr->tp1_wakeup_time * 100,
987 		       psr->tp1_wakeup_time);
988 
989 		printf("\t\tTP2/TP3 wakeup time: %d usec (0x%x)\n",
990 		       psr->tp2_tp3_wakeup_time * 100,
991 		       psr->tp2_tp3_wakeup_time);
992 
993 		if (context->bdb->version >= 226) {
994 			int index;
995 			static const uint16_t psr2_tp_times[] = {500, 100, 2500, 5};
996 
997 			index = (psr2_tp_time >> (i * 2)) & 0x3;
998 			printf("\t\tPSR2 TP2/TP3 wakeup time: %d usec (0x%x)\n",
999 			       psr2_tp_times[index], index);
1000 		}
1001 	}
1002 }
1003 
1004 static void
print_detail_timing_data(const struct lvds_dvo_timing * dvo_timing)1005 print_detail_timing_data(const struct lvds_dvo_timing *dvo_timing)
1006 {
1007 	int display, sync_start, sync_end, total;
1008 
1009 	display = (dvo_timing->hactive_hi << 8) | dvo_timing->hactive_lo;
1010 	sync_start = display +
1011 		((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo);
1012 	sync_end = sync_start + ((dvo_timing->hsync_pulse_width_hi << 8) |
1013 				 dvo_timing->hsync_pulse_width_lo);
1014 	total = display +
1015 		((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo);
1016 	printf("\thdisplay: %d\n", display);
1017 	printf("\thsync [%d, %d] %s\n", sync_start, sync_end,
1018 	       dvo_timing->hsync_positive ? "+sync" : "-sync");
1019 	printf("\thtotal: %d\n", total);
1020 
1021 	display = (dvo_timing->vactive_hi << 8) | dvo_timing->vactive_lo;
1022 	sync_start = display + ((dvo_timing->vsync_off_hi << 8) |
1023 				dvo_timing->vsync_off_lo);
1024 	sync_end = sync_start + ((dvo_timing->vsync_pulse_width_hi << 8) |
1025 				 dvo_timing->vsync_pulse_width_lo);
1026 	total = display +
1027 		((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo);
1028 	printf("\tvdisplay: %d\n", display);
1029 	printf("\tvsync [%d, %d] %s\n", sync_start, sync_end,
1030 	       dvo_timing->vsync_positive ? "+sync" : "-sync");
1031 	printf("\tvtotal: %d\n", total);
1032 
1033 	printf("\tclock: %d\n", dvo_timing->clock * 10);
1034 }
1035 
dump_sdvo_panel_dtds(struct context * context,const struct bdb_block * block)1036 static void dump_sdvo_panel_dtds(struct context *context,
1037 				 const struct bdb_block *block)
1038 {
1039 	const struct lvds_dvo_timing *dvo_timing = block->data;
1040 	int n, count;
1041 
1042 	count = block->size / sizeof(struct lvds_dvo_timing);
1043 	for (n = 0; n < count; n++) {
1044 		printf("%d:\n", n);
1045 		print_detail_timing_data(dvo_timing++);
1046 	}
1047 }
1048 
dump_sdvo_lvds_options(struct context * context,const struct bdb_block * block)1049 static void dump_sdvo_lvds_options(struct context *context,
1050 				   const struct bdb_block *block)
1051 {
1052 	const struct bdb_sdvo_lvds_options *options = block->data;
1053 
1054 	printf("\tbacklight: %d\n", options->panel_backlight);
1055 	printf("\th40 type: %d\n", options->h40_set_panel_type);
1056 	printf("\ttype: %d\n", options->panel_type);
1057 	printf("\tssc_clk_freq: %d\n", options->ssc_clk_freq);
1058 	printf("\tals_low_trip: %d\n", options->als_low_trip);
1059 	printf("\tals_high_trip: %d\n", options->als_high_trip);
1060 	/*
1061 	u8 sclalarcoeff_tab_row_num;
1062 	u8 sclalarcoeff_tab_row_size;
1063 	u8 coefficient[8];
1064 	*/
1065 	printf("\tmisc[0]: %x\n", options->panel_misc_bits_1);
1066 	printf("\tmisc[1]: %x\n", options->panel_misc_bits_2);
1067 	printf("\tmisc[2]: %x\n", options->panel_misc_bits_3);
1068 	printf("\tmisc[3]: %x\n", options->panel_misc_bits_4);
1069 }
1070 
dump_mipi_config(struct context * context,const struct bdb_block * block)1071 static void dump_mipi_config(struct context *context,
1072 			     const struct bdb_block *block)
1073 {
1074 	const struct bdb_mipi_config *start = block->data;
1075 	const struct mipi_config *config;
1076 	const struct mipi_pps_data *pps;
1077 
1078 	config = &start->config[context->panel_type];
1079 	pps = &start->pps[context->panel_type];
1080 
1081 	printf("\tGeneral Param\n");
1082 	printf("\t\t BTA disable: %s\n", config->bta ? "Disabled" : "Enabled");
1083 	printf("\t\t Panel Rotation: %d degrees\n", config->rotation * 90);
1084 
1085 	printf("\t\t Video Mode Color Format: ");
1086 	if (config->videomode_color_format == 0)
1087 		printf("Not supported\n");
1088 	else if (config->videomode_color_format == 1)
1089 		printf("RGB565\n");
1090 	else if (config->videomode_color_format == 2)
1091 		printf("RGB666\n");
1092 	else if (config->videomode_color_format == 3)
1093 		printf("RGB666 Loosely Packed\n");
1094 	else if (config->videomode_color_format == 4)
1095 		printf("RGB888\n");
1096 	printf("\t\t PPS GPIO Pins: %s \n", config->pwm_blc ? "Using SOC" : "Using PMIC");
1097 	printf("\t\t CABC Support: %s\n", config->cabc ? "supported" : "not supported");
1098 	printf("\t\t Mode: %s\n", config->cmd_mode ? "COMMAND" : "VIDEO");
1099 	printf("\t\t Video transfer mode: %s (0x%x)\n",
1100 	       config->vtm == 1 ? "non-burst with sync pulse" :
1101 	       config->vtm == 2 ? "non-burst with sync events" :
1102 	       config->vtm == 3 ? "burst" : "<unknown>",
1103 	       config->vtm);
1104 	printf("\t\t Dithering: %s\n", config->dithering ? "done in Display Controller" : "done in Panel Controller");
1105 
1106 	printf("\tPort Desc\n");
1107 	printf("\t\t Pixel overlap: %d\n", config->pixel_overlap);
1108 	printf("\t\t Lane Count: %d\n", config->lane_cnt + 1);
1109 	printf("\t\t Dual Link Support: ");
1110 	if (config->dual_link == 0)
1111 		printf("not supported\n");
1112 	else if (config->dual_link == 1)
1113 		printf("Front Back mode\n");
1114 	else
1115 		printf("Pixel Alternative Mode\n");
1116 
1117 	printf("\tDphy Flags\n");
1118 	printf("\t\t Clock Stop: %s\n", config->clk_stop ? "ENABLED" : "DISABLED");
1119 	printf("\t\t EOT disabled: %s\n\n", config->eot_disabled ? "EOT not to be sent" : "EOT to be sent");
1120 
1121 	printf("\tHSTxTimeOut: 0x%x\n", config->hs_tx_timeout);
1122 	printf("\tLPRXTimeOut: 0x%x\n", config->lp_rx_timeout);
1123 	printf("\tTurnAroundTimeOut: 0x%x\n", config->turn_around_timeout);
1124 	printf("\tDeviceResetTimer: 0x%x\n", config->device_reset_timer);
1125 	printf("\tMasterinitTimer: 0x%x\n", config->master_init_timer);
1126 	printf("\tDBIBandwidthTimer: 0x%x\n", config->dbi_bw_timer);
1127 	printf("\tLpByteClkValue: 0x%x\n\n", config->lp_byte_clk_val);
1128 
1129 	printf("\tDphy Params\n");
1130 	printf("\t\tExit to zero Count: 0x%x\n", config->exit_zero_cnt);
1131 	printf("\t\tTrail Count: 0x%X\n", config->trail_cnt);
1132 	printf("\t\tClk zero count: 0x%x\n", config->clk_zero_cnt);
1133 	printf("\t\tPrepare count:0x%x\n\n", config->prepare_cnt);
1134 
1135 	printf("\tClockLaneSwitchingCount: 0x%x\n", config->clk_lane_switch_cnt);
1136 	printf("\tHighToLowSwitchingCount: 0x%x\n\n", config->hl_switch_cnt);
1137 
1138 	printf("\tTimings based on Dphy spec\n");
1139 	printf("\t\tTClkMiss: 0x%x\n", config->tclk_miss);
1140 	printf("\t\tTClkPost: 0x%x\n", config->tclk_post);
1141 	printf("\t\tTClkPre: 0x%x\n", config->tclk_pre);
1142 	printf("\t\tTClkPrepare: 0x%x\n", config->tclk_prepare);
1143 	printf("\t\tTClkSettle: 0x%x\n", config->tclk_settle);
1144 	printf("\t\tTClkTermEnable: 0x%x\n\n", config->tclk_term_enable);
1145 
1146 	printf("\tTClkTrail: 0x%x\n", config->tclk_trail);
1147 	printf("\tTClkPrepareTClkZero: 0x%x\n", config->tclk_prepare_clkzero);
1148 	printf("\tTHSExit: 0x%x\n", config->ths_exit);
1149 	printf("\tTHsPrepare: 0x%x\n", config->ths_prepare);
1150 	printf("\tTHsPrepareTHsZero: 0x%x\n", config->ths_prepare_hszero);
1151 	printf("\tTHSSettle: 0x%x\n", config->ths_settle);
1152 	printf("\tTHSSkip: 0x%x\n", config->ths_skip);
1153 	printf("\tTHsTrail: 0x%x\n", config->ths_trail);
1154 	printf("\tTInit: 0x%x\n", config->tinit);
1155 	printf("\tTLPX: 0x%x\n", config->tlpx);
1156 
1157 	printf("\tMIPI PPS\n");
1158 	printf("\t\tPanel power ON delay: %d\n", pps->panel_on_delay);
1159 	printf("\t\tPanel power on to Backlight enable delay: %d\n", pps->bl_enable_delay);
1160 	printf("\t\tBacklight disable to Panel power OFF delay: %d\n", pps->bl_disable_delay);
1161 	printf("\t\tPanel power OFF delay: %d\n", pps->panel_off_delay);
1162 	printf("\t\tPanel power cycle delay: %d\n", pps->panel_power_cycle_delay);
1163 }
1164 
mipi_dump_send_packet(const uint8_t * data,uint8_t seq_version)1165 static const uint8_t *mipi_dump_send_packet(const uint8_t *data, uint8_t seq_version)
1166 {
1167 	uint8_t flags, type;
1168 	uint16_t len, i;
1169 
1170 	flags = *data++;
1171 	type = *data++;
1172 	len = *((const uint16_t *) data);
1173 	data += 2;
1174 
1175 	printf("\t\tSend DCS: Port %s, VC %d, %s, Type %02x, Length %u, Data",
1176 	       (flags >> 3) & 1 ? "C" : "A",
1177 	       (flags >> 1) & 3,
1178 	       flags & 1 ? "HS" : "LP",
1179 	       type,
1180 	       len);
1181 	for (i = 0; i < len; i++)
1182 		printf(" %02x", *data++);
1183 	printf("\n");
1184 
1185 	return data;
1186 }
1187 
mipi_dump_delay(const uint8_t * data,uint8_t seq_version)1188 static const uint8_t *mipi_dump_delay(const uint8_t *data, uint8_t seq_version)
1189 {
1190 	printf("\t\tDelay: %u us\n", *((const uint32_t *)data));
1191 
1192 	return data + 4;
1193 }
1194 
mipi_dump_gpio(const uint8_t * data,uint8_t seq_version)1195 static const uint8_t *mipi_dump_gpio(const uint8_t *data, uint8_t seq_version)
1196 {
1197 	uint8_t index, number, flags;
1198 
1199 	if (seq_version >= 3) {
1200 		index = *data++;
1201 		number = *data++;
1202 		flags = *data++;
1203 
1204 		printf("\t\tGPIO index %u, number %u, set %d (0x%02x)\n",
1205 		       index, number, flags & 1, flags);
1206 	} else {
1207 		index = *data++;
1208 		flags = *data++;
1209 
1210 		printf("\t\tGPIO index %u, source %d, set %d (0x%02x)\n",
1211 		       index, (flags >> 1) & 3, flags & 1, flags);
1212 	}
1213 
1214 	return data;
1215 }
1216 
mipi_dump_i2c(const uint8_t * data,uint8_t seq_version)1217 static const uint8_t *mipi_dump_i2c(const uint8_t *data, uint8_t seq_version)
1218 {
1219 	uint8_t flags, index, bus, offset, len, i;
1220 	uint16_t address;
1221 
1222 	flags = *data++;
1223 	index = *data++;
1224 	bus = *data++;
1225 	address = *((const uint16_t *) data);
1226 	data += 2;
1227 	offset = *data++;
1228 	len = *data++;
1229 
1230 	printf("\t\tSend I2C: Flags %02x, Index %02x, Bus %02x, Address %04x, Offset %02x, Length %u, Data",
1231 	       flags, index, bus, address, offset, len);
1232 	for (i = 0; i < len; i++)
1233 		printf(" %02x", *data++);
1234 	printf("\n");
1235 
1236 	return data;
1237 }
1238 
1239 typedef const uint8_t * (*fn_mipi_elem_dump)(const uint8_t *data, uint8_t seq_version);
1240 
1241 static const fn_mipi_elem_dump dump_elem[] = {
1242 	[MIPI_SEQ_ELEM_SEND_PKT] = mipi_dump_send_packet,
1243 	[MIPI_SEQ_ELEM_DELAY] = mipi_dump_delay,
1244 	[MIPI_SEQ_ELEM_GPIO] = mipi_dump_gpio,
1245 	[MIPI_SEQ_ELEM_I2C] = mipi_dump_i2c,
1246 };
1247 
1248 static const char * const seq_name[] = {
1249 	[MIPI_SEQ_ASSERT_RESET] = "MIPI_SEQ_ASSERT_RESET",
1250 	[MIPI_SEQ_INIT_OTP] = "MIPI_SEQ_INIT_OTP",
1251 	[MIPI_SEQ_DISPLAY_ON] = "MIPI_SEQ_DISPLAY_ON",
1252 	[MIPI_SEQ_DISPLAY_OFF]  = "MIPI_SEQ_DISPLAY_OFF",
1253 	[MIPI_SEQ_DEASSERT_RESET] = "MIPI_SEQ_DEASSERT_RESET",
1254 	[MIPI_SEQ_BACKLIGHT_ON] = "MIPI_SEQ_BACKLIGHT_ON",
1255 	[MIPI_SEQ_BACKLIGHT_OFF] = "MIPI_SEQ_BACKLIGHT_OFF",
1256 	[MIPI_SEQ_TEAR_ON] = "MIPI_SEQ_TEAR_ON",
1257 	[MIPI_SEQ_TEAR_OFF] = "MIPI_SEQ_TEAR_OFF",
1258 	[MIPI_SEQ_POWER_ON] = "MIPI_SEQ_POWER_ON",
1259 	[MIPI_SEQ_POWER_OFF] = "MIPI_SEQ_POWER_OFF",
1260 };
1261 
sequence_name(enum mipi_seq seq_id)1262 static const char *sequence_name(enum mipi_seq seq_id)
1263 {
1264 	if (seq_id < ARRAY_SIZE(seq_name) && seq_name[seq_id])
1265 		return seq_name[seq_id];
1266 	else
1267 		return "(unknown)";
1268 }
1269 
dump_sequence(const uint8_t * data,uint8_t seq_version)1270 static const uint8_t *dump_sequence(const uint8_t *data, uint8_t seq_version)
1271 {
1272 	fn_mipi_elem_dump mipi_elem_dump;
1273 
1274 	printf("\tSequence %u - %s\n", *data, sequence_name(*data));
1275 
1276 	/* Skip Sequence Byte. */
1277 	data++;
1278 
1279 	/* Skip Size of Sequence. */
1280 	if (seq_version >= 3)
1281 		data += 4;
1282 
1283 	while (1) {
1284 		uint8_t operation_byte = *data++;
1285 		uint8_t operation_size = 0;
1286 
1287 		if (operation_byte == MIPI_SEQ_ELEM_END)
1288 			break;
1289 
1290 		if (operation_byte < ARRAY_SIZE(dump_elem))
1291 			mipi_elem_dump = dump_elem[operation_byte];
1292 		else
1293 			mipi_elem_dump = NULL;
1294 
1295 		/* Size of Operation. */
1296 		if (seq_version >= 3)
1297 			operation_size = *data++;
1298 
1299 		if (mipi_elem_dump) {
1300 			const uint8_t *next = data + operation_size;
1301 
1302 			data = mipi_elem_dump(data, seq_version);
1303 
1304 			if (operation_size && next != data)
1305 				printf("Error: Inconsistent operation size: %d\n",
1306 					operation_size);
1307 		} else if (operation_size) {
1308 			/* We have size, skip. */
1309 			data += operation_size;
1310 		} else {
1311 			/* No size, can't skip without parsing. */
1312 			printf("Error: Unsupported MIPI element %u\n",
1313 			       operation_byte);
1314 			return NULL;
1315 		}
1316 	}
1317 
1318 	return data;
1319 }
1320 
1321 /* Find the sequence block and size for the given panel. */
1322 static const uint8_t *
find_panel_sequence_block(const struct bdb_mipi_sequence * sequence,uint16_t panel_id,uint32_t total,uint32_t * seq_size)1323 find_panel_sequence_block(const struct bdb_mipi_sequence *sequence,
1324 			  uint16_t panel_id, uint32_t total, uint32_t *seq_size)
1325 {
1326 	const uint8_t *data = &sequence->data[0];
1327 	uint8_t current_id;
1328 	uint32_t current_size;
1329 	int header_size = sequence->version >= 3 ? 5 : 3;
1330 	int index = 0;
1331 	int i;
1332 
1333 	/* skip new block size */
1334 	if (sequence->version >= 3)
1335 		data += 4;
1336 
1337 	for (i = 0; i < MAX_MIPI_CONFIGURATIONS && index < total; i++) {
1338 		if (index + header_size > total) {
1339 			fprintf(stderr, "Invalid sequence block (header)\n");
1340 			return NULL;
1341 		}
1342 
1343 		current_id = *(data + index);
1344 		if (sequence->version >= 3)
1345 			current_size = *((const uint32_t *)(data + index + 1));
1346 		else
1347 			current_size = *((const uint16_t *)(data + index + 1));
1348 
1349 		index += header_size;
1350 
1351 		if (index + current_size > total) {
1352 			fprintf(stderr, "Invalid sequence block\n");
1353 			return NULL;
1354 		}
1355 
1356 		if (current_id == panel_id) {
1357 			*seq_size = current_size;
1358 			return data + index;
1359 		}
1360 
1361 		index += current_size;
1362 	}
1363 
1364 	fprintf(stderr, "Sequence block detected but no valid configuration\n");
1365 
1366 	return NULL;
1367 }
1368 
goto_next_sequence(const uint8_t * data,int index,int total)1369 static int goto_next_sequence(const uint8_t *data, int index, int total)
1370 {
1371 	uint16_t len;
1372 
1373 	/* Skip Sequence Byte. */
1374 	for (index = index + 1; index < total; index += len) {
1375 		uint8_t operation_byte = *(data + index);
1376 		index++;
1377 
1378 		switch (operation_byte) {
1379 		case MIPI_SEQ_ELEM_END:
1380 			return index;
1381 		case MIPI_SEQ_ELEM_SEND_PKT:
1382 			if (index + 4 > total)
1383 				return 0;
1384 
1385 			len = *((const uint16_t *)(data + index + 2)) + 4;
1386 			break;
1387 		case MIPI_SEQ_ELEM_DELAY:
1388 			len = 4;
1389 			break;
1390 		case MIPI_SEQ_ELEM_GPIO:
1391 			len = 2;
1392 			break;
1393 		case MIPI_SEQ_ELEM_I2C:
1394 			if (index + 7 > total)
1395 				return 0;
1396 			len = *(data + index + 6) + 7;
1397 			break;
1398 		default:
1399 			fprintf(stderr, "Unknown operation byte\n");
1400 			return 0;
1401 		}
1402 	}
1403 
1404 	return 0;
1405 }
1406 
goto_next_sequence_v3(const uint8_t * data,int index,int total)1407 static int goto_next_sequence_v3(const uint8_t *data, int index, int total)
1408 {
1409 	int seq_end;
1410 	uint16_t len;
1411 	uint32_t size_of_sequence;
1412 
1413 	/*
1414 	 * Could skip sequence based on Size of Sequence alone, but also do some
1415 	 * checking on the structure.
1416 	 */
1417 	if (total < 5) {
1418 		fprintf(stderr, "Too small sequence size\n");
1419 		return 0;
1420 	}
1421 
1422 	/* Skip Sequence Byte. */
1423 	index++;
1424 
1425 	/*
1426 	 * Size of Sequence. Excludes the Sequence Byte and the size itself,
1427 	 * includes MIPI_SEQ_ELEM_END byte, excludes the final MIPI_SEQ_END
1428 	 * byte.
1429 	 */
1430 	size_of_sequence = *((const uint32_t *)(data + index));
1431 	index += 4;
1432 
1433 	seq_end = index + size_of_sequence;
1434 	if (seq_end > total) {
1435 		fprintf(stderr, "Invalid sequence size\n");
1436 		return 0;
1437 	}
1438 
1439 	for (; index < total; index += len) {
1440 		uint8_t operation_byte = *(data + index);
1441 		index++;
1442 
1443 		if (operation_byte == MIPI_SEQ_ELEM_END) {
1444 			if (index != seq_end) {
1445 				fprintf(stderr, "Invalid element structure\n");
1446 				return 0;
1447 			}
1448 			return index;
1449 		}
1450 
1451 		len = *(data + index);
1452 		index++;
1453 
1454 		/*
1455 		 * FIXME: Would be nice to check elements like for v1/v2 in
1456 		 * goto_next_sequence() above.
1457 		 */
1458 		switch (operation_byte) {
1459 		case MIPI_SEQ_ELEM_SEND_PKT:
1460 		case MIPI_SEQ_ELEM_DELAY:
1461 		case MIPI_SEQ_ELEM_GPIO:
1462 		case MIPI_SEQ_ELEM_I2C:
1463 		case MIPI_SEQ_ELEM_SPI:
1464 		case MIPI_SEQ_ELEM_PMIC:
1465 			break;
1466 		default:
1467 			fprintf(stderr, "Unknown operation byte %u\n",
1468 				operation_byte);
1469 			break;
1470 		}
1471 	}
1472 
1473 	return 0;
1474 }
1475 
dump_mipi_sequence(struct context * context,const struct bdb_block * block)1476 static void dump_mipi_sequence(struct context *context,
1477 			       const struct bdb_block *block)
1478 {
1479 	const struct bdb_mipi_sequence *sequence = block->data;
1480 	const uint8_t *data;
1481 	uint32_t seq_size;
1482 	int index = 0, i;
1483 	const uint8_t *sequence_ptrs[MIPI_SEQ_MAX] = {};
1484 
1485 	/* Check if we have sequence block as well */
1486 	if (!sequence) {
1487 		printf("No MIPI Sequence found\n");
1488 		return;
1489 	}
1490 
1491 	printf("\tSequence block version v%u\n", sequence->version);
1492 
1493 	/* Fail gracefully for forward incompatible sequence block. */
1494 	if (sequence->version >= 4) {
1495 		fprintf(stderr, "Unable to parse MIPI Sequence Block v%u\n",
1496 			sequence->version);
1497 		return;
1498 	}
1499 
1500 	data = find_panel_sequence_block(sequence, context->panel_type,
1501 					 block->size, &seq_size);
1502 	if (!data)
1503 		return;
1504 
1505 	/* Parse the sequences. Corresponds to VBT parsing in the kernel. */
1506 	for (;;) {
1507 		uint8_t seq_id = *(data + index);
1508 		if (seq_id == MIPI_SEQ_END)
1509 			break;
1510 
1511 		if (seq_id >= MIPI_SEQ_MAX) {
1512 			fprintf(stderr, "Unknown sequence %u\n", seq_id);
1513 			return;
1514 		}
1515 
1516 		sequence_ptrs[seq_id] = data + index;
1517 
1518 		if (sequence->version >= 3)
1519 			index = goto_next_sequence_v3(data, index, seq_size);
1520 		else
1521 			index = goto_next_sequence(data, index, seq_size);
1522 		if (!index) {
1523 			fprintf(stderr, "Invalid sequence %u\n", seq_id);
1524 			return;
1525 		}
1526 	}
1527 
1528 	/* Dump the sequences. Corresponds to sequence execution in kernel. */
1529 	for (i = 0; i < ARRAY_SIZE(sequence_ptrs); i++)
1530 		if (sequence_ptrs[i])
1531 			dump_sequence(sequence_ptrs[i], sequence->version);
1532 }
1533 
1534 /* get panel type from lvds options block, or -1 if block not found */
get_panel_type(struct context * context)1535 static int get_panel_type(struct context *context)
1536 {
1537 	struct bdb_block *block;
1538 	const struct bdb_lvds_options *options;
1539 	int panel_type;
1540 
1541 	block = find_section(context, BDB_LVDS_OPTIONS);
1542 	if (!block)
1543 		return -1;
1544 
1545 	options = block->data;
1546 	panel_type = options->panel_type;
1547 
1548 	free(block);
1549 
1550 	return panel_type;
1551 }
1552 
1553 static int
get_device_id(unsigned char * bios,int size)1554 get_device_id(unsigned char *bios, int size)
1555 {
1556     int device;
1557     int offset = (bios[0x19] << 8) + bios[0x18];
1558 
1559     if (offset + 7 >= size)
1560 	return -1;
1561 
1562     if (bios[offset] != 'P' ||
1563 	bios[offset+1] != 'C' ||
1564 	bios[offset+2] != 'I' ||
1565 	bios[offset+3] != 'R')
1566 	return -1;
1567 
1568     device = (bios[offset+7] << 8) + bios[offset+6];
1569 
1570     return device;
1571 }
1572 
1573 struct dumper {
1574 	uint8_t id;
1575 	const char *name;
1576 	void (*dump)(struct context *context,
1577 		     const struct bdb_block *block);
1578 };
1579 
1580 struct dumper dumpers[] = {
1581 	{
1582 		.id = BDB_GENERAL_FEATURES,
1583 		.name = "General features block",
1584 		.dump = dump_general_features,
1585 	},
1586 	{
1587 		.id = BDB_GENERAL_DEFINITIONS,
1588 		.name = "General definitions block",
1589 		.dump = dump_general_definitions,
1590 	},
1591 	{
1592 		.id = BDB_CHILD_DEVICE_TABLE,
1593 		.name = "Legacy child devices block",
1594 		.dump = dump_legacy_child_devices,
1595 	},
1596 	{
1597 		.id = BDB_LVDS_OPTIONS,
1598 		.name = "LVDS options block",
1599 		.dump = dump_lvds_options,
1600 	},
1601 	{
1602 		.id = BDB_LVDS_LFP_DATA_PTRS,
1603 		.name = "LVDS timing pointer data",
1604 		.dump = dump_lvds_ptr_data,
1605 	},
1606 	{
1607 		.id = BDB_LVDS_LFP_DATA,
1608 		.name = "LVDS panel data block",
1609 		.dump = dump_lvds_data,
1610 	},
1611 	{
1612 		.id = BDB_LVDS_BACKLIGHT,
1613 		.name = "Backlight info block",
1614 		.dump = dump_backlight_info,
1615 	},
1616 	{
1617 		.id = BDB_SDVO_LVDS_OPTIONS,
1618 		.name = "SDVO LVDS options block",
1619 		.dump = dump_sdvo_lvds_options,
1620 	},
1621 	{
1622 		.id = BDB_SDVO_PANEL_DTDS,
1623 		.name = "SDVO panel dtds",
1624 		.dump = dump_sdvo_panel_dtds,
1625 	},
1626 	{
1627 		.id = BDB_DRIVER_FEATURES,
1628 		.name = "Driver feature data block",
1629 		.dump = dump_driver_feature,
1630 	},
1631 	{
1632 		.id = BDB_EDP,
1633 		.name = "eDP block",
1634 		.dump = dump_edp,
1635 	},
1636 	{
1637 		.id = BDB_PSR,
1638 		.name = "PSR block",
1639 		.dump = dump_psr,
1640 	},
1641 	{
1642 		.id = BDB_MIPI_CONFIG,
1643 		.name = "MIPI configuration block",
1644 		.dump = dump_mipi_config,
1645 	},
1646 	{
1647 		.id = BDB_MIPI_SEQUENCE,
1648 		.name = "MIPI sequence block",
1649 		.dump = dump_mipi_sequence,
1650 	},
1651 };
1652 
hex_dump(const void * data,uint32_t size)1653 static void hex_dump(const void *data, uint32_t size)
1654 {
1655 	int i;
1656 	const uint8_t *p = data;
1657 
1658 	for (i = 0; i < size; i++) {
1659 		if (i % 16 == 0)
1660 			printf("\t%04x: ", i);
1661 		printf("%02x", p[i]);
1662 		if (i % 16 == 15) {
1663 			if (i + 1 < size)
1664 				printf("\n");
1665 		} else if (i % 8 == 7) {
1666 			printf("  ");
1667 		} else {
1668 			printf(" ");
1669 		}
1670 	}
1671 	printf("\n\n");
1672 }
1673 
hex_dump_block(const struct bdb_block * block)1674 static void hex_dump_block(const struct bdb_block *block)
1675 {
1676 	hex_dump(block->data, block->size);
1677 }
1678 
dump_section(struct context * context,int section_id)1679 static bool dump_section(struct context *context, int section_id)
1680 {
1681 	struct dumper *dumper = NULL;
1682 	struct bdb_block *block;
1683 	int i;
1684 
1685 	block = find_section(context, section_id);
1686 	if (!block)
1687 		return false;
1688 
1689 	for (i = 0; i < ARRAY_SIZE(dumpers); i++) {
1690 		if (block->id == dumpers[i].id) {
1691 			dumper = &dumpers[i];
1692 			break;
1693 		}
1694 	}
1695 
1696 	if (dumper && dumper->name)
1697 		printf("BDB block %d - %s:\n", block->id, dumper->name);
1698 	else
1699 		printf("BDB block %d - Unknown, no decoding available:\n",
1700 		       block->id);
1701 
1702 	if (context->hexdump)
1703 		hex_dump_block(block);
1704 	if (dumper && dumper->dump)
1705 		dumper->dump(context, block);
1706 	printf("\n");
1707 
1708 	free(block);
1709 
1710 	return true;
1711 }
1712 
1713 /* print a description of the VBT of the form <bdb-version>-<vbt-signature> */
print_description(struct context * context)1714 static void print_description(struct context *context)
1715 {
1716 	const struct vbt_header *vbt = context->vbt;
1717 	const struct bdb_header *bdb = context->bdb;
1718 	char *desc = strndup((char *)vbt->signature, sizeof(vbt->signature));
1719 	char *p;
1720 
1721 	for (p = desc + strlen(desc) - 1; p >= desc && isspace(*p); p--)
1722 		*p = '\0';
1723 
1724 	for (p = desc; *p; p++) {
1725 		if (!isalnum(*p))
1726 			*p = '-';
1727 		else
1728 			*p = tolower(*p);
1729 	}
1730 
1731 	p = desc;
1732 	if (strncmp(p, "-vbt-", 5) == 0)
1733 		p += 5;
1734 
1735 	printf("%d-%s\n", bdb->version, p);
1736 
1737 	free (desc);
1738 }
1739 
dump_headers(struct context * context)1740 static void dump_headers(struct context *context)
1741 {
1742 	const struct vbt_header *vbt = context->vbt;
1743 	const struct bdb_header *bdb = context->bdb;
1744 	int i, j = 0;
1745 
1746 	printf("VBT header:\n");
1747 	if (context->hexdump)
1748 		hex_dump(vbt, vbt->header_size);
1749 
1750 	printf("\tVBT signature:\t\t\"%.*s\"\n",
1751 	       (int)sizeof(vbt->signature), vbt->signature);
1752 	printf("\tVBT version:\t\t0x%04x (%d.%d)\n", vbt->version,
1753 	       vbt->version / 100, vbt->version % 100);
1754 	printf("\tVBT header size:\t0x%04x (%u)\n",
1755 	       vbt->header_size, vbt->header_size);
1756 	printf("\tVBT size:\t\t0x%04x (%u)\n", vbt->vbt_size, vbt->vbt_size);
1757 	printf("\tVBT checksum:\t\t0x%02x\n", vbt->vbt_checksum);
1758 	printf("\tBDB offset:\t\t0x%08x (%u)\n", vbt->bdb_offset, vbt->bdb_offset);
1759 
1760 	printf("\n");
1761 
1762 	printf("BDB header:\n");
1763 	if (context->hexdump)
1764 		hex_dump(bdb, bdb->header_size);
1765 
1766 	printf("\tBDB signature:\t\t\"%.*s\"\n",
1767 	       (int)sizeof(bdb->signature), bdb->signature);
1768 	printf("\tBDB version:\t\t%d\n", bdb->version);
1769 	printf("\tBDB header size:\t0x%04x (%u)\n",
1770 	       bdb->header_size, bdb->header_size);
1771 	printf("\tBDB size:\t\t0x%04x (%u)\n", bdb->bdb_size, bdb->bdb_size);
1772 	printf("\n");
1773 
1774 	printf("BDB blocks present:");
1775 	for (i = 0; i < 256; i++) {
1776 		struct bdb_block *block;
1777 
1778 		block = find_section(context, i);
1779 		if (!block)
1780 			continue;
1781 
1782 		if (j++ % 16)
1783 			printf(" %3d", i);
1784 		else
1785 			printf("\n\t%3d", i);
1786 
1787 		free(block);
1788 	}
1789 	printf("\n\n");
1790 }
1791 
1792 enum opt {
1793 	OPT_UNKNOWN = '?',
1794 	OPT_END = -1,
1795 	OPT_FILE,
1796 	OPT_DEVID,
1797 	OPT_PANEL_TYPE,
1798 	OPT_ALL_PANELS,
1799 	OPT_HEXDUMP,
1800 	OPT_BLOCK,
1801 	OPT_USAGE,
1802 	OPT_HEADER,
1803 	OPT_DESCRIBE,
1804 };
1805 
usage(const char * toolname)1806 static void usage(const char *toolname)
1807 {
1808 	fprintf(stderr, "usage: %s", toolname);
1809 	fprintf(stderr, " --file=<rom_file>"
1810 			" [--devid=<device_id>]"
1811 			" [--panel-type=<panel_type>]"
1812 			" [--all-panels]"
1813 			" [--hexdump]"
1814 			" [--block=<block_no>]"
1815 			" [--header]"
1816 			" [--describe]"
1817 			" [--help]\n");
1818 }
1819 
main(int argc,char ** argv)1820 int main(int argc, char **argv)
1821 {
1822 	uint8_t *VBIOS;
1823 	int index;
1824 	enum opt opt;
1825 	int fd;
1826 	struct vbt_header *vbt = NULL;
1827 	int vbt_off, bdb_off, i;
1828 	const char *filename = NULL;
1829 	const char *toolname = argv[0];
1830 	struct stat finfo;
1831 	int size;
1832 	struct context context = {
1833 		.panel_type = -1,
1834 	};
1835 	char *endp;
1836 	int block_number = -1;
1837 	bool header_only = false, describe = false;
1838 
1839 	static struct option options[] = {
1840 		{ "file",	required_argument,	NULL,	OPT_FILE },
1841 		{ "devid",	required_argument,	NULL,	OPT_DEVID },
1842 		{ "panel-type",	required_argument,	NULL,	OPT_PANEL_TYPE },
1843 		{ "all-panels",	no_argument,		NULL,	OPT_ALL_PANELS },
1844 		{ "hexdump",	no_argument,		NULL,	OPT_HEXDUMP },
1845 		{ "block",	required_argument,	NULL,	OPT_BLOCK },
1846 		{ "header",	no_argument,		NULL,	OPT_HEADER },
1847 		{ "describe",	no_argument,		NULL,	OPT_DESCRIBE },
1848 		{ "help",	no_argument,		NULL,	OPT_USAGE },
1849 		{ 0 }
1850 	};
1851 
1852 	for (opt = 0; opt != OPT_END; ) {
1853 		opt = getopt_long(argc, argv, "", options, &index);
1854 
1855 		switch (opt) {
1856 		case OPT_FILE:
1857 			filename = optarg;
1858 			break;
1859 		case OPT_DEVID:
1860 			context.devid = strtoul(optarg, &endp, 16);
1861 			if (!context.devid || *endp) {
1862 				fprintf(stderr, "invalid devid '%s'\n", optarg);
1863 				return EXIT_FAILURE;
1864 			}
1865 			break;
1866 		case OPT_PANEL_TYPE:
1867 			context.panel_type = strtoul(optarg, &endp, 0);
1868 			if (*endp || context.panel_type > 15) {
1869 				fprintf(stderr, "invalid panel type '%s'\n",
1870 					optarg);
1871 				return EXIT_FAILURE;
1872 			}
1873 			break;
1874 		case OPT_ALL_PANELS:
1875 			context.dump_all_panel_types = true;
1876 			break;
1877 		case OPT_HEXDUMP:
1878 			context.hexdump = true;
1879 			break;
1880 		case OPT_BLOCK:
1881 			block_number = strtoul(optarg, &endp, 0);
1882 			if (*endp) {
1883 				fprintf(stderr, "invalid block number '%s'\n",
1884 					optarg);
1885 				return EXIT_FAILURE;
1886 			}
1887 			break;
1888 		case OPT_HEADER:
1889 			header_only = true;
1890 			break;
1891 		case OPT_DESCRIBE:
1892 			describe = true;
1893 			break;
1894 		case OPT_END:
1895 			break;
1896 		case OPT_USAGE: /* fall-through */
1897 		case OPT_UNKNOWN:
1898 			usage(toolname);
1899 			return EXIT_FAILURE;
1900 		}
1901 	}
1902 
1903 	argc -= optind;
1904 	argv += optind;
1905 
1906 	if (!filename) {
1907 		if (argc == 1) {
1908 			/* for backwards compatibility */
1909 			filename = argv[0];
1910 		} else {
1911 			usage(toolname);
1912 			return EXIT_FAILURE;
1913 		}
1914 	}
1915 
1916 	fd = open(filename, O_RDONLY);
1917 	if (fd == -1) {
1918 		fprintf(stderr, "Couldn't open \"%s\": %s\n",
1919 			filename, strerror(errno));
1920 		return EXIT_FAILURE;
1921 	}
1922 
1923 	if (stat(filename, &finfo)) {
1924 		fprintf(stderr, "Failed to stat \"%s\": %s\n",
1925 			filename, strerror(errno));
1926 		return EXIT_FAILURE;
1927 	}
1928 	size = finfo.st_size;
1929 
1930 	if (size == 0) {
1931 		int len = 0, ret;
1932 		size = 8192;
1933 		VBIOS = malloc (size);
1934 		while ((ret = read(fd, VBIOS + len, size - len))) {
1935 			if (ret < 0) {
1936 				fprintf(stderr, "Failed to read \"%s\": %s\n",
1937 					filename, strerror(errno));
1938 				return EXIT_FAILURE;
1939 			}
1940 
1941 			len += ret;
1942 			if (len == size) {
1943 				size *= 2;
1944 				VBIOS = realloc(VBIOS, size);
1945 			}
1946 		}
1947 	} else {
1948 		VBIOS = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
1949 		if (VBIOS == MAP_FAILED) {
1950 			fprintf(stderr, "Failed to map \"%s\": %s\n",
1951 				filename, strerror(errno));
1952 			return EXIT_FAILURE;
1953 		}
1954 	}
1955 
1956 	/* Scour memory looking for the VBT signature */
1957 	for (i = 0; i + 4 < size; i++) {
1958 		if (!memcmp(VBIOS + i, "$VBT", 4)) {
1959 			vbt_off = i;
1960 			vbt = (struct vbt_header *)(VBIOS + i);
1961 			break;
1962 		}
1963 	}
1964 
1965 	if (!vbt) {
1966 		fprintf(stderr, "VBT signature missing\n");
1967 		return EXIT_FAILURE;
1968 	}
1969 
1970 	bdb_off = vbt_off + vbt->bdb_offset;
1971 	if (bdb_off >= size - sizeof(struct bdb_header)) {
1972 		fprintf(stderr, "Invalid VBT found, BDB points beyond end of data block\n");
1973 		return EXIT_FAILURE;
1974 	}
1975 
1976 	context.vbt = vbt;
1977 	context.bdb = (const struct bdb_header *)(VBIOS + bdb_off);
1978 	context.size = size;
1979 
1980 	if (!context.devid) {
1981 		const char *devid_string = getenv("DEVICE");
1982 		if (devid_string)
1983 			context.devid = strtoul(devid_string, NULL, 16);
1984 	}
1985 	if (!context.devid)
1986 		context.devid = get_device_id(VBIOS, size);
1987 	if (!context.devid)
1988 		fprintf(stderr, "Warning: could not find PCI device ID!\n");
1989 
1990 	if (context.panel_type == -1)
1991 		context.panel_type = get_panel_type(&context);
1992 	if (context.panel_type == -1) {
1993 		fprintf(stderr, "Warning: panel type not set, using 0\n");
1994 		context.panel_type = 0;
1995 	}
1996 
1997 	if (describe) {
1998 		print_description(&context);
1999 	} else if (header_only) {
2000 		dump_headers(&context);
2001 	} else if (block_number != -1) {
2002 		/* dump specific section only */
2003 		if (!dump_section(&context, block_number)) {
2004 			fprintf(stderr, "Block %d not found\n", block_number);
2005 			return EXIT_FAILURE;
2006 		}
2007 	} else {
2008 		dump_headers(&context);
2009 
2010 		/* dump all sections  */
2011 		for (i = 0; i < 256; i++)
2012 			dump_section(&context, i);
2013 	}
2014 
2015 	return 0;
2016 }
2017