xref: /aosp_15_r20/external/igt-gpu-tools/tools/intel_infoframes.c (revision d83cc019efdc2edc6c4b16e9034a3ceb8d35d77c)
1 /*
2  * Copyright © 2012 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
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  *
23  * Authors:
24  *      Paulo Zanoni <[email protected]>
25  *
26  */
27 
28 #include <assert.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <getopt.h>
33 #include "intel_io.h"
34 #include "intel_chipset.h"
35 #include "drmtest.h"
36 
37 typedef enum {
38 	TRANSC_A = 0,
39 	TRANSC_B = 1,
40 	TRANSC_C = 2,
41 	TRANSC_INVALID
42 } Transcoder;
43 
44 typedef enum {
45 	REG_HDMIB_GEN4    = 0x61140,
46 	REG_HDMIC_GEN4    = 0x61160,
47 	REG_HDMIB_VLV     = 0x1e1140,
48 	REG_HDMIC_VLV     = 0x1e1160,
49 	REG_HDMIB_PCH     = 0xe1140,
50 	REG_HDMIC_PCH     = 0xe1150,
51 	REG_HDMID_PCH     = 0xe1160,
52 	REG_DIP_CTL_GEN4  = 0x61170,
53 	REG_DIP_CTL_A_VLV   = 0x1e0200,
54 	REG_DIP_CTL_B_VLV   = 0x1e1170,
55 	REG_DIP_CTL_A     = 0xe0200,
56 	REG_DIP_CTL_B     = 0xe1200,
57 	REG_DIP_CTL_C     = 0xe2200,
58 	REG_DIP_DATA_GEN4 = 0x61178,
59 	REG_DIP_DATA_A_VLV  = 0x1e0208,
60 	REG_DIP_DATA_B_VLV  = 0x1e1174,
61 	REG_DIP_DATA_A    = 0xe0208,
62 	REG_DIP_DATA_B    = 0xe1208,
63 	REG_DIP_DATA_C    = 0xe2208,
64 } Register;
65 
66 typedef enum {
67 	DIP_AVI    = 0,
68 	DIP_VENDOR = 1,
69 	DIP_GAMUT  = 2,
70 	DIP_SPD    = 3,
71 	DIP_INVALID,
72 } DipType;
73 
74 typedef enum {
75 	DIP_FREQ_ONCE              = 0,
76 	DIP_FREQ_EVERY_VSYNC       = 1,
77 	DIP_FREQ_EVERY_OTHER_VSYNC = 2,
78 	DIP_FREQ_RESERVED          = 3,
79 } DipFrequency;
80 
81 typedef enum {
82 	SOURCE_DEVICE_UNKNOWN           = 0x00,
83 	SOURCE_DEVICE_DIGITAL_STB       = 0x01,
84 	SOURCE_DEVICE_DVD_PLAYER        = 0x02,
85 	SOURCE_DEVICE_D_VHS             = 0x03,
86 	SOURCE_DEVICE_HDD_VIDEORECORDER = 0x04,
87 	SOURCE_DEVICE_DVC               = 0x05,
88 	SOURCE_DEVICE_DSC               = 0x06,
89 	SOURCE_DEVICE_VIDEO_CD          = 0x07,
90 	SOURCE_DEVICE_GAME              = 0x08,
91 	SOURCE_DEVICE_PC_GENERAL        = 0x09,
92 	SOURCE_DEVICE_BLU_RAY_DISK      = 0x0a,
93 	SOURCE_DEVICE_SUPER_AUDIO_CD    = 0x0b,
94 	SOURCE_DEVICE_RESERVED          = 0x0c
95 } SourceDevice;
96 
97 #define HDMI_PORT_ENABLE          (1 << 31)
98 #define HDMI_PORT_TRANSCODER_GEN4 (1 << 30)
99 #define HDMI_PORT_TRANSCODER_IBX  (1 << 30)
100 #define HDMI_PORT_TRANSCODER_CPT  (3 << 29)
101 #define HDMI_PORT_ENCODING        (3 << 10)
102 #define HDMI_PORT_MODE            (1 << 9)
103 #define HDMI_PORT_AUDIO           (1 << 6)
104 #define HDMI_PORT_DETECTED        (1 << 2)
105 
106 #define DIP_CTL_ENABLE           (1 << 31)
107 #define DIP_CTL_GCP_ENABLE       (1 << 25)
108 #define DIP_CTL_SPD_ENABLE       (1 << 24)
109 #define DIP_CTL_GAMUT_ENABLE     (1 << 23)
110 #define DIP_CTL_VENDOR_ENABLE    (1 << 22)
111 #define DIP_CTL_AVI_ENABLE       (1 << 21)
112 #define DIP_CTL_BUFFER_INDEX     (3 << 19)
113 #define DIP_CTL_BUFFER_AVI       (0 << 19)
114 #define DIP_CTL_BUFFER_VENDOR    (1 << 19)
115 #define DIP_CTL_BUFFER_GAMUT     (2 << 19)
116 #define DIP_CTL_BUFFER_SPD       (3 << 19)
117 #define DIP_CTL_FREQUENCY        (3 << 16)
118 #define DIP_CTL_FREQ_ONCE        (0 << 16)
119 #define DIP_CTL_FREQ_EVERY       (1 << 16)
120 #define DIP_CTL_FREQ_EVERY_OTHER (2 << 16)
121 #define DIP_CTL_BUFFER_SIZE      (15 << 8)
122 #define DIP_CTL_ACCESS_ADDR      (15 << 0)
123 
124 #define DIP_CTL_PORT_SEL_MASK_GEN4       (3 << 29)
125 #define DIP_CTL_PORT_SEL_B_GEN4          (1 << 29)
126 #define DIP_CTL_PORT_SEL_C_GEN4          (2 << 29)
127 #define DIP_CTL_BUFFER_TRANS_ACTIVE_GEN4 (1 << 28)
128 
129 #define AVI_INFOFRAME_TYPE    0x82
130 #define AVI_INFOFRAME_VERSION 0x02
131 #define AVI_INFOFRAME_LENGTH  0x0d
132 #define SPD_INFOFRAME_TYPE    0x83
133 #define SPD_INFOFRAME_VERSION 0x01
134 #define SPD_INFOFRAME_LENGTH  0x19
135 
136 #define VENDOR_ID_HDMI	0x000c03
137 
138 typedef struct {
139 	uint8_t type;
140 	uint8_t version;
141 	uint8_t length;
142 	uint8_t ecc;
143 } DipInfoFrameHeader;
144 
145 typedef union {
146 	struct {
147 		DipInfoFrameHeader header;
148 		uint8_t checksum;
149 
150 		uint8_t S     :2;
151 		uint8_t B     :2;
152 		uint8_t A     :1;
153 		uint8_t Y     :2;
154 		uint8_t Rsvd0 :1;
155 
156 		uint8_t R :4;
157 		uint8_t M :2;
158 		uint8_t C :2;
159 
160 		uint8_t SC  :2;
161 		uint8_t Q   :2;
162 		uint8_t EC  :3;
163 		uint8_t ITC :1;
164 
165 		uint8_t VIC   :7;
166 		uint8_t Rsvd1 :1;
167 
168 		uint8_t PR    :4;
169 		uint8_t Rsvd2 :4;
170 
171 		uint16_t top;
172 		uint16_t bottom;
173 		uint16_t left;
174 		uint16_t right;
175 
176 		uint16_t Rsvd3;
177 		uint32_t Rsvd4[3];
178 	} avi;
179 	struct {
180 		DipInfoFrameHeader header;
181 		uint8_t checksum;
182 		uint8_t vendor[8];
183 		uint8_t description[16];
184 		uint8_t source;
185 	} __attribute__((packed)) spd;
186 	struct {
187 		DipInfoFrameHeader header;
188 		uint8_t checksum;
189 
190 		uint8_t id[3];
191 
192 		uint8_t Rsvd0        :5;
193 		uint8_t video_format :3;
194 
195 		union {
196 			uint8_t vic;
197 			struct {
198 				uint8_t Rsvd1         :4;
199 				uint8_t s3d_structure :4;
200 			} s3d;
201 		} pb5;
202 
203 		uint8_t Rsvd2        :4;
204 		uint8_t s3d_ext_data :4;
205 	} __attribute__((packed)) vendor;
206 	struct {
207 		DipInfoFrameHeader header;
208 		uint8_t body[27];
209 	} generic;
210 	uint8_t data8[128];
211 	uint32_t data32[16];
212 } DipInfoFrame;
213 
214 Register vlv_hdmi_ports[] = {
215 	REG_HDMIB_VLV,
216 	REG_HDMIC_VLV,
217 };
218 
219 Register vlv_dip_ctl_regs[] = {
220 	REG_DIP_CTL_A_VLV,
221 	REG_DIP_CTL_B_VLV,
222 };
223 
224 Register vlv_dip_data_regs[] = {
225 	REG_DIP_DATA_A_VLV,
226 	REG_DIP_DATA_B_VLV,
227 };
228 
229 Register gen4_hdmi_ports[] = {
230 	REG_HDMIB_GEN4,
231 	REG_HDMIC_GEN4,
232 };
233 Register pch_hdmi_ports[] = {
234 	REG_HDMIB_PCH,
235 	REG_HDMIC_PCH,
236 	REG_HDMID_PCH
237 };
238 Register pch_dip_ctl_regs[] = {
239 	REG_DIP_CTL_A,
240 	REG_DIP_CTL_B,
241 	REG_DIP_CTL_C
242 };
243 Register pch_dip_data_regs[] = {
244 	REG_DIP_DATA_A,
245 	REG_DIP_DATA_B,
246 	REG_DIP_DATA_C
247 };
248 const char *hdmi_port_names[] = {
249 	"HDMIB",
250 	"HDMIC",
251 	"HDMID"
252 };
253 const char *transcoder_names[] = {
254 	"A",
255 	"B",
256 	"C"
257 };
258 const char *dip_frequency_names[] = {
259 	"once",
260 	"every vsync",
261 	"every other vsync",
262 	"reserved (invalid)"
263 };
264 
265 struct pci_device *pci_dev;
266 int gen = 0;
267 
spd_source_to_string(SourceDevice source)268 static const char *spd_source_to_string(SourceDevice source)
269 {
270 	switch (source) {
271 	case SOURCE_DEVICE_UNKNOWN:
272 		return "unknown";
273 	case SOURCE_DEVICE_DIGITAL_STB:
274 		return "digital stb";
275 	case SOURCE_DEVICE_DVD_PLAYER:
276 		return "dvd player";
277 	case SOURCE_DEVICE_D_VHS:
278 		return "d vhs";
279 	case SOURCE_DEVICE_HDD_VIDEORECORDER:
280 		return "hdd videorecorder";
281 	case SOURCE_DEVICE_DVC:
282 		return "dvc";
283 	case SOURCE_DEVICE_DSC:
284 		return "dsc";
285 	case SOURCE_DEVICE_VIDEO_CD:
286 		return "video cd";
287 	case SOURCE_DEVICE_GAME:
288 		return "game";
289 	case SOURCE_DEVICE_PC_GENERAL:
290 		return "pc general";
291 	case SOURCE_DEVICE_BLU_RAY_DISK:
292 		return "blu-ray disk";
293 	case SOURCE_DEVICE_SUPER_AUDIO_CD:
294 		return "super audio cd";
295 	default:
296 		return "reserved";
297 	}
298 }
299 
get_dip_ctl_reg(Transcoder transcoder)300 static Register get_dip_ctl_reg(Transcoder transcoder)
301 {
302 	if (IS_VALLEYVIEW(pci_dev->device_id))
303 		return vlv_dip_ctl_regs[transcoder];
304 	else if (gen == 4)
305 		return REG_DIP_CTL_GEN4;
306 	else
307 		return pch_dip_ctl_regs[transcoder];
308 }
309 
get_dip_data_reg(Transcoder transcoder)310 static Register get_dip_data_reg(Transcoder transcoder)
311 {
312 	if (IS_VALLEYVIEW(pci_dev->device_id))
313 		return vlv_dip_data_regs[transcoder];
314 	else if (gen == 4)
315 		return REG_DIP_DATA_GEN4;
316 	else
317 		return pch_dip_data_regs[transcoder];
318 }
319 
get_hdmi_port(int hdmi_port_index)320 static Register get_hdmi_port(int hdmi_port_index)
321 {
322 	if (IS_VALLEYVIEW(pci_dev->device_id))
323 		return vlv_hdmi_ports[hdmi_port_index];
324 	else if (gen == 4) {
325 		assert(hdmi_port_index < 2);
326 		return gen4_hdmi_ports[hdmi_port_index];
327 	} else {
328 		return pch_hdmi_ports[hdmi_port_index];
329 	}
330 }
331 
load_infoframe(Transcoder transcoder,DipInfoFrame * frame,DipType type)332 static void load_infoframe(Transcoder transcoder, DipInfoFrame *frame,
333 			   DipType type)
334 {
335 	Register ctl_reg = get_dip_ctl_reg(transcoder);
336 	Register data_reg = get_dip_data_reg(transcoder);
337 	uint32_t ctl_val;
338 	uint32_t i;
339 
340 	ctl_val = INREG(ctl_reg);
341 
342 	ctl_val &= ~DIP_CTL_BUFFER_INDEX;
343 	ctl_val |= type << 19;
344 	OUTREG(ctl_reg, ctl_val);
345 	ctl_val = INREG(ctl_reg);
346 
347 	ctl_val &= ~DIP_CTL_ACCESS_ADDR;
348 	OUTREG(ctl_reg, ctl_val);
349 
350 	for (i = 0; i < 16; i++) {
351 		ctl_val = INREG(ctl_reg);
352 		assert((ctl_val & DIP_CTL_ACCESS_ADDR) == i);
353 		frame->data32[i] = INREG(data_reg);
354 	}
355 }
356 
infoframe_valid_checksum(DipInfoFrame * frame)357 static int infoframe_valid_checksum(DipInfoFrame *frame)
358 {
359 	int i;
360 	int length = frame->generic.header.length;
361 	uint8_t csum;
362 
363 	csum = frame->generic.header.type + frame->generic.header.version +
364 	       frame->generic.header.length; /* no ecc */
365 	for (i = 0; i < length + 1; i++)
366 		csum += frame->generic.body[i];
367 
368 	return (csum == 0);
369 }
370 
infoframe_fix_checksum(DipInfoFrame * frame)371 static void infoframe_fix_checksum(DipInfoFrame *frame)
372 {
373 	int i;
374 	int length = frame->generic.header.length;
375 	uint8_t csum;
376 
377 	csum = frame->generic.header.type + frame->generic.header.version +
378 	       frame->generic.header.length; /* no ecc */
379 	/* Length does not include the header field nor the checksum */
380 	for (i = 1; i < length + 1; i++)
381 		csum += frame->generic.body[i];
382 	frame->generic.body[0] = 0x100 - csum;
383 }
384 
dump_port_info(int hdmi_port_index)385 static void dump_port_info(int hdmi_port_index)
386 {
387 	Register port = get_hdmi_port(hdmi_port_index);
388 	uint32_t val = INREG(port);
389 	Transcoder transcoder;
390 
391 	printf("\nPort %s:\n", hdmi_port_names[hdmi_port_index]);
392 	printf("- %sdetected\n", val & HDMI_PORT_DETECTED ? "" : "not ");
393 	printf("- %s\n", val & HDMI_PORT_ENABLE ? "enabled" : "disabled");
394 
395 	if (!(val & HDMI_PORT_ENABLE))
396 		return;
397 
398 	if (gen == 4 || IS_VALLEYVIEW(pci_dev->device_id))
399 		transcoder = (val & HDMI_PORT_TRANSCODER_GEN4) >> 30;
400 	else if (intel_pch >= PCH_CPT)
401 		transcoder = (val & HDMI_PORT_TRANSCODER_CPT) >> 29;
402 	else
403 		transcoder = (val & HDMI_PORT_TRANSCODER_IBX) >> 30;
404 	printf("- transcoder: %s\n", transcoder_names[transcoder]);
405 
406 	switch ((val & HDMI_PORT_ENCODING) >> 10) {
407 	case 0:
408 		printf("- mode: SDVO\n");
409 		break;
410 	case 2:
411 		printf("- mode: TMDS\n");
412 		break;
413 	default:
414 		printf("- mode: INVALID!\n");
415 	}
416 
417 	printf("- mode: %s\n", val & HDMI_PORT_MODE ? "HDMI" : "DVI");
418 	printf("- audio: %s\n", val & HDMI_PORT_AUDIO ? "enabled" : "disabled");
419 }
420 
dump_raw_infoframe(DipInfoFrame * frame)421 static void dump_raw_infoframe(DipInfoFrame *frame)
422 {
423 	unsigned int i;
424 	printf("- raw:");
425 	for (i = 0; i < 16; i++) {
426 		if (i % 4 == 0)
427 			printf("\n ");
428 		printf(" %08x", frame->data32[i]);
429 	}
430 	printf("\n");
431 }
432 
dump_avi_info(Transcoder transcoder)433 static void dump_avi_info(Transcoder transcoder)
434 {
435 	Register reg = get_dip_ctl_reg(transcoder);
436 	uint32_t val;
437 	DipFrequency freq;
438 	DipInfoFrame frame;
439 
440 	load_infoframe(transcoder, &frame, DIP_AVI);
441 	val = INREG(reg);
442 
443 	printf("AVI InfoFrame:\n");
444 
445 	if (gen == 4) {
446 		printf("- %sbeing transmitted\n",
447 		       val & DIP_CTL_BUFFER_TRANS_ACTIVE_GEN4 ? "" : "not ");
448 	}
449 
450 	freq = (val & DIP_CTL_FREQUENCY) >> 16;
451 	printf("- frequency: %s\n", dip_frequency_names[freq]);
452 
453 	dump_raw_infoframe(&frame);
454 
455 	printf("- type: %x, version: %x, length: %x, ecc: %x, checksum: %x\n",
456 	       frame.avi.header.type, frame.avi.header.version,
457 	       frame.avi.header.length, frame.avi.header.ecc,
458 	       frame.avi.checksum);
459 	printf("- S: %x, B: %x, A: %x, Y: %x, Rsvd0: %x\n",
460 	       frame.avi.S, frame.avi.B, frame.avi.A, frame.avi.Y,
461 	       frame.avi.Rsvd0);
462 	printf("- R: %x, M: %x, C: %x\n",
463 	       frame.avi.R, frame.avi.M, frame.avi.C);
464 	printf("- SC: %x, Q: %x, EC: %x, ITC: %x\n",
465 	       frame.avi.SC, frame.avi.Q, frame.avi.EC, frame.avi.ITC);
466 	printf("- VIC: %d, Rsvd1: %x\n", frame.avi.VIC, frame.avi.Rsvd1);
467 	printf("- PR: %x, Rsvd2: %x\n", frame.avi.PR, frame.avi.Rsvd2);
468 	printf("- top: %x, bottom: %x, left: %x, right: %x\n",
469 	       frame.avi.top, frame.avi.bottom, frame.avi.left,
470 	       frame.avi.right);
471 	printf("- Rsvd3: %x, Rsvd4[0]: %x, Rsvd4[1]: %x, Rsvd4[2]: %x\n",
472 	       frame.avi.Rsvd3, frame.avi.Rsvd4[0], frame.avi.Rsvd4[1],
473 	       frame.avi.Rsvd4[2]);
474 
475 	if (!infoframe_valid_checksum(&frame))
476 		printf("Invalid InfoFrame checksum!\n");
477 }
478 
vendor_id_to_string(uint32_t id)479 static const char *vendor_id_to_string(uint32_t id)
480 {
481 	switch (id) {
482 	case VENDOR_ID_HDMI:
483 		return "HDMI";
484 	default:
485 		return "Unknown";
486 	}
487 }
488 
s3d_structure_to_string(int format)489 static const char *s3d_structure_to_string(int format)
490 {
491 	switch (format) {
492 	case 0:
493 		return "Frame Packing";
494 	case 6:
495 		return "Top Bottom";
496 	case 8:
497 		return "Side By Side (half)";
498 	default:
499 		return "Reserved";
500 	}
501 }
502 
dump_vendor_hdmi(DipInfoFrame * frame)503 static void dump_vendor_hdmi(DipInfoFrame *frame)
504 {
505 	int vic_present = frame->vendor.video_format & 0x1;
506 	int s3d_present = frame->vendor.video_format & 0x2;
507 
508 	printf("- video format: 0x%03x %s\n", frame->vendor.video_format,
509 	       s3d_present ? "(3D)" : "");
510 
511 	if (vic_present && s3d_present) {
512 		printf("Error: HDMI VIC and S3D bits set. Only one of those "
513 		       " at a time is valid\n");
514 		return;
515 	}
516 
517 	if (vic_present)
518 		printf("- HDMI VIC: %d\n", frame->vendor.pb5.vic);
519 	else if (s3d_present) {
520 		int s3d_structure = frame->vendor.pb5.s3d.s3d_structure;
521 
522 		printf("- 3D Format: %s\n",
523 		       s3d_structure_to_string(s3d_structure));
524 
525 		/* Side-by-side (half) */
526 		if (s3d_structure >= 8)
527 			printf("- 3D Ext Data 0x%x\n",
528 			       frame->vendor.s3d_ext_data);
529 	}
530 }
531 
dump_vendor_info(Transcoder transcoder)532 static void dump_vendor_info(Transcoder transcoder)
533 {
534 	Register reg = get_dip_ctl_reg(transcoder);
535 	uint32_t val, vendor_id;
536 	DipFrequency freq;
537 	DipInfoFrame frame;
538 
539 	load_infoframe(transcoder, &frame, DIP_VENDOR);
540 	val = INREG(reg);
541 
542 	printf("Vendor InfoFrame:\n");
543 
544 	if (gen == 4) {
545 		printf("- %sbeing transmitted\n",
546 		       val & DIP_CTL_BUFFER_TRANS_ACTIVE_GEN4 ? "" : "not ");
547 	}
548 
549 	freq = (val & DIP_CTL_FREQUENCY) >> 16;
550 	printf("- frequency: %s\n", dip_frequency_names[freq]);
551 
552 	dump_raw_infoframe(&frame);
553 
554 	vendor_id = frame.vendor.id[2] << 16 | frame.vendor.id[1] << 8 |
555 		    frame.vendor.id[0];
556 
557 	printf("- vendor Id: 0x%06x (%s)\n", vendor_id,
558 	       vendor_id_to_string(vendor_id));
559 
560 	if (vendor_id == VENDOR_ID_HDMI)
561 		dump_vendor_hdmi(&frame);
562 
563 	if (!infoframe_valid_checksum(&frame))
564 		printf("Invalid InfoFrame checksum!\n");
565 }
566 
dump_gamut_info(Transcoder transcoder)567 static void dump_gamut_info(Transcoder transcoder)
568 {
569 	Register reg = get_dip_ctl_reg(transcoder);
570 	uint32_t val;
571 	DipFrequency freq;
572 	DipInfoFrame frame;
573 
574 	load_infoframe(transcoder, &frame, DIP_GAMUT);
575 	val = INREG(reg);
576 
577 	printf("Gamut InfoFrame:\n");
578 
579 	if (gen == 4) {
580 		printf("- %sbeing transmitted\n",
581 		       val & DIP_CTL_BUFFER_TRANS_ACTIVE_GEN4 ? "" : "not ");
582 	}
583 
584 	freq = (val & DIP_CTL_FREQUENCY) >> 16;
585 	printf("- frequency: %s\n", dip_frequency_names[freq]);
586 
587 	dump_raw_infoframe(&frame);
588 
589 	if (!infoframe_valid_checksum(&frame))
590 		printf("Invalid InfoFrame checksum!\n");
591 }
592 
dump_spd_info(Transcoder transcoder)593 static void dump_spd_info(Transcoder transcoder)
594 {
595 	Register reg = get_dip_ctl_reg(transcoder);
596 	uint32_t val;
597 	DipFrequency freq;
598 	DipInfoFrame frame;
599 	char vendor[9];
600 	char description[17];
601 
602 	load_infoframe(transcoder, &frame, DIP_SPD);
603 	val = INREG(reg);
604 
605 	printf("SPD InfoFrame:\n");
606 
607 	if (gen == 4) {
608 		printf("- %sbeing transmitted\n",
609 		       val & DIP_CTL_BUFFER_TRANS_ACTIVE_GEN4 ? "" : "not ");
610 	}
611 
612 	freq = (val & DIP_CTL_FREQUENCY) >> 16;
613 	printf("- frequency: %s\n", dip_frequency_names[freq]);
614 
615 	dump_raw_infoframe(&frame);
616 
617 	printf("- type: %x, version: %x, length: %x, ecc: %x, checksum: %x\n",
618 	       frame.spd.header.type, frame.spd.header.version,
619 	       frame.spd.header.length, frame.spd.header.ecc,
620 	       frame.spd.checksum);
621 
622 	memcpy(vendor, frame.spd.vendor, 8);
623 	vendor[8] = '\0';
624 	memcpy(description, frame.spd.description, 16);
625 	description[16] = '\0';
626 
627 	printf("- vendor: %s\n", vendor);
628 	printf("- description: %s\n", description);
629 	printf("- source: %s\n", spd_source_to_string(frame.spd.source));
630 
631 	if (!infoframe_valid_checksum(&frame))
632 		printf("Invalid InfoFrame checksum!\n");
633 }
634 
dump_transcoder_info(Transcoder transcoder)635 static void dump_transcoder_info(Transcoder transcoder)
636 {
637 	Register reg = get_dip_ctl_reg(transcoder);
638 	uint32_t val = INREG(reg);
639 
640 	if (gen == 4) {
641 		printf("\nDIP information:\n");
642 		switch (val & DIP_CTL_PORT_SEL_MASK_GEN4) {
643 		case DIP_CTL_PORT_SEL_B_GEN4:
644 			printf("- port B\n");
645 			break;
646 		case DIP_CTL_PORT_SEL_C_GEN4:
647 			printf("- port C\n");
648 			break;
649 		default:
650 			printf("- INVALID port!\n");
651 		}
652 	} else {
653 		printf("\nTranscoder %s:\n", transcoder_names[transcoder]);
654 	}
655 	printf("- %s\n", val & DIP_CTL_ENABLE ? "enabled" : "disabled");
656 	if (!(val & DIP_CTL_ENABLE))
657 		return;
658 
659 	printf("- GCP: %s\n", val & DIP_CTL_GCP_ENABLE ?
660 	       "enabled" : "disabled");
661 
662 	if (val & DIP_CTL_AVI_ENABLE)
663 		dump_avi_info(transcoder);
664 	if (val & DIP_CTL_VENDOR_ENABLE)
665 		dump_vendor_info(transcoder);
666 	if (val & DIP_CTL_GAMUT_ENABLE)
667 		dump_gamut_info(transcoder);
668 	if (val & DIP_CTL_SPD_ENABLE)
669 		dump_spd_info(transcoder);
670 }
671 
dump_all_info(void)672 static void dump_all_info(void)
673 {
674 	unsigned int i;
675 
676 	if (IS_VALLEYVIEW(pci_dev->device_id)) {
677 		for (i = 0; i < ARRAY_SIZE(vlv_hdmi_ports); i++)
678 			dump_port_info(i);
679 		for (i = 0; i < ARRAY_SIZE(vlv_dip_ctl_regs); i++)
680 			dump_transcoder_info(i);
681 	} else if (gen == 4) {
682 		for (i = 0; i < ARRAY_SIZE(gen4_hdmi_ports); i++)
683 			dump_port_info(i);
684 		dump_transcoder_info(0);
685 	} else {
686 		for (i = 0; i < ARRAY_SIZE(pch_hdmi_ports); i++)
687 			dump_port_info(i);
688 		for (i = 0; i < ARRAY_SIZE(pch_dip_ctl_regs); i++)
689 			dump_transcoder_info(i);
690 	}
691 }
692 
write_infoframe(Transcoder transcoder,DipType type,DipInfoFrame * frame)693 static void write_infoframe(Transcoder transcoder, DipType type,
694 			    DipInfoFrame *frame)
695 {
696 	Register ctl_reg = get_dip_ctl_reg(transcoder);
697 	Register data_reg = get_dip_data_reg(transcoder);
698 	uint32_t ctl_val;
699 	unsigned int i;
700 
701 	ctl_val = INREG(ctl_reg);
702 	ctl_val &= ~DIP_CTL_BUFFER_INDEX;
703 	ctl_val |= (type << 19);
704 	ctl_val &= ~DIP_CTL_ACCESS_ADDR;
705 	OUTREG(ctl_reg, ctl_val);
706 
707 	for (i = 0; i < 8; i++) {
708 		ctl_val = INREG(ctl_reg);
709 		assert((ctl_val & DIP_CTL_ACCESS_ADDR) == i);
710 		OUTREG(data_reg, frame->data32[i]);
711 	}
712 }
713 
disable_infoframe(Transcoder transcoder,DipType type)714 static void disable_infoframe(Transcoder transcoder, DipType type)
715 {
716 	Register reg = get_dip_ctl_reg(transcoder);
717 	uint32_t val = INREG(reg);
718 	if (gen != 4 && type == DIP_AVI)
719 		val &= ~DIP_CTL_ENABLE;
720 	val &= ~(1 << (21 + type));
721 	OUTREG(reg, val);
722 }
723 
enable_infoframe(Transcoder transcoder,DipType type)724 static void enable_infoframe(Transcoder transcoder, DipType type)
725 {
726 	Register reg = get_dip_ctl_reg(transcoder);
727 	uint32_t val = INREG(reg);
728 	if (gen != 4 && type == DIP_AVI)
729 		val |= DIP_CTL_ENABLE;
730 	val |= (1 << (21 + type));
731 	OUTREG(reg, val);
732 }
733 
parse_infoframe_option_u(const char * name,const char * s,uint32_t min,uint32_t max,uint32_t * value,char ** commands)734 static int parse_infoframe_option_u(const char *name, const char *s,
735 				    uint32_t min, uint32_t max,
736 				    uint32_t *value, char **commands)
737 {
738 	int read, rc;
739 	if (!strcmp(name, s)) {
740 		rc = sscanf(*commands, "%x%n", value, &read);
741 		*commands = &(*commands)[read];
742 		if (rc != 1) {
743 			printf("Invalid value.\n");
744 			return 0;
745 		}
746 
747 		if (*value < min || *value > max) {
748 			printf("Value outside allowed range.\n");
749 			return 0;
750 		}
751 		return 1;
752 	}
753 	return 0;
754 }
755 
parse_infoframe_option_s(const char * name,const char * s,int min_size,int max_size,char * value,char ** commands)756 static int parse_infoframe_option_s(const char *name, const char *s,
757 				    int min_size, int max_size,
758 				    char *value, char **commands)
759 {
760 	int size, read, rc;
761 	if (!strcmp(name, s)) {
762 		rc = sscanf(*commands, "%31s%n", value, &read);
763 		*commands = &(*commands)[read];
764 		if (rc != 1) {
765 			printf("Invalid value.\n");
766 			return 0;
767 		}
768 
769 		size = strlen(value);
770 		if (size < min_size || size > max_size) {
771 			printf("String either too big or too small.\n");
772 			return 0;
773 		}
774 		return 1;
775 	}
776 	return 0;
777 }
778 
change_avi_infoframe(Transcoder transcoder,char * commands)779 static void change_avi_infoframe(Transcoder transcoder, char *commands)
780 {
781 	Register reg = get_dip_ctl_reg(transcoder);
782 	uint32_t val;
783 	DipInfoFrame frame;
784 	char option[32];
785 	uint32_t option_val;
786 	int rc, read;
787 	char *current = commands;
788 
789 	load_infoframe(transcoder, &frame, DIP_AVI);
790 	val = INREG(reg);
791 
792 	while (1) {
793 		rc = sscanf(current, "%31s%n", option, &read);
794 		current = &current[read];
795 		if (rc == EOF) {
796 			break;
797 		} else if (rc != 1) {
798 			printf("Invalid option: %s\n", option);
799 			continue;
800 		}
801 
802 		if (parse_infoframe_option_u("S", option, 0, 2, &option_val,
803 					     &current))
804 			frame.avi.S = option_val;
805 		else if (parse_infoframe_option_u("B", option, 0, 3,
806 						  &option_val, &current))
807 			frame.avi.B = option_val;
808 		else if (parse_infoframe_option_u("A", option, 0, 1,
809 						  &option_val, &current))
810 			frame.avi.A = option_val;
811 		else if (parse_infoframe_option_u("Y", option, 0, 2,
812 						  &option_val, &current))
813 			frame.avi.Y = option_val;
814 		else if (parse_infoframe_option_u("R", option, 0, 15,
815 						  &option_val, &current))
816 			frame.avi.R = option_val;
817 		else if (parse_infoframe_option_u("M", option, 0, 2,
818 						  &option_val, &current))
819 			frame.avi.M = option_val;
820 		else if (parse_infoframe_option_u("C", option, 0, 3,
821 						  &option_val, &current))
822 			frame.avi.C = option_val;
823 		else if (parse_infoframe_option_u("SC", option, 0, 3,
824 						  &option_val, &current))
825 			frame.avi.SC = option_val;
826 		else if (parse_infoframe_option_u("Q", option, 0, 2,
827 						  &option_val, &current))
828 			frame.avi.Q = option_val;
829 		else if (parse_infoframe_option_u("EC", option, 0, 1,
830 						  &option_val,&current))
831 			frame.avi.EC = option_val;
832 		else if (parse_infoframe_option_u("ITC", option, 0, 1,
833 						  &option_val, &current))
834 			frame.avi.ITC = option_val;
835 		else if (parse_infoframe_option_u("VIC", option, 0, 127,
836 						  &option_val, &current))
837 			frame.avi.VIC = option_val;
838 		else if (parse_infoframe_option_u("PR", option, 0, 15,
839 						  &option_val, &current))
840 			frame.avi.PR = option_val;
841 		else if (parse_infoframe_option_u("top", option, 0, 65535,
842 						  &option_val, &current))
843 			frame.avi.top = option_val;
844 		else if (parse_infoframe_option_u("bottom", option, 0, 65535,
845 						  &option_val, &current))
846 			frame.avi.bottom = option_val;
847 		else if (parse_infoframe_option_u("left", option, 0, 65535,
848 						  &option_val, &current))
849 			frame.avi.left = option_val;
850 		else if (parse_infoframe_option_u("right", option, 0, 65535,
851 						  &option_val, &current))
852 			frame.avi.right = option_val;
853 		else
854 			printf("Unrecognized option: %s\n", option);
855 	}
856 
857 	val &= ~DIP_CTL_FREQUENCY;
858 	val |= DIP_CTL_FREQ_EVERY;
859 	OUTREG(reg, val);
860 
861 	frame.avi.header.type = AVI_INFOFRAME_TYPE;
862 	frame.avi.header.version = AVI_INFOFRAME_VERSION;
863 	frame.avi.header.length = AVI_INFOFRAME_LENGTH;
864 	frame.avi.Rsvd0 = 0;
865 	frame.avi.Rsvd1 = 0;
866 	frame.avi.Rsvd2 = 0;
867 	frame.avi.Rsvd3 = 0;
868 	frame.avi.Rsvd4[0] = 0;
869 	frame.avi.Rsvd4[1] = 0;
870 	frame.avi.Rsvd4[2] = 0;
871 
872 	infoframe_fix_checksum(&frame);
873 
874 	disable_infoframe(transcoder, DIP_AVI);
875 	write_infoframe(transcoder, DIP_AVI, &frame);
876 	enable_infoframe(transcoder, DIP_AVI);
877 }
878 
change_spd_infoframe(Transcoder transcoder,char * commands)879 static void change_spd_infoframe(Transcoder transcoder, char *commands)
880 {
881 	Register reg = get_dip_ctl_reg(transcoder);
882 	uint32_t val;
883 	DipInfoFrame frame;
884 	char option[16];
885 	char option_val_s[32];
886 	uint32_t option_val_i;
887 	int rc, read;
888 	char *current = commands;
889 
890 	load_infoframe(transcoder, &frame, DIP_SPD);
891 	val = INREG(reg);
892 
893 	while (1) {
894 		rc = sscanf(current, "%15s%n", option, &read);
895 		current = &current[read];
896 		if (rc == EOF) {
897 			break;
898 		} else if (rc != 1) {
899 			printf("Invalid option: %s\n", option);
900 			continue;
901 		}
902 
903 		memset(option_val_s, 0, 32);
904 
905 		if (parse_infoframe_option_s("vendor", option, 0, 8,
906 					     option_val_s, &current))
907 			memcpy(frame.spd.vendor, option_val_s, 8);
908 		else if (parse_infoframe_option_s("description", option, 0, 16,
909 						  option_val_s, &current))
910 			memcpy(frame.spd.description, option_val_s, 16);
911 		else if (parse_infoframe_option_u("source", option, 0, 0x0c,
912 						  &option_val_i, &current))
913 			frame.spd.source = option_val_i;
914 		else
915 			printf("Unrecognized option: %s\n", option);
916 	}
917 
918 	val &= ~DIP_CTL_FREQUENCY;
919 	val |= DIP_CTL_FREQ_EVERY_OTHER;
920 	OUTREG(reg, val);
921 
922 	frame.spd.header.type = SPD_INFOFRAME_TYPE;
923 	frame.spd.header.version = SPD_INFOFRAME_VERSION;
924 	frame.spd.header.length = SPD_INFOFRAME_LENGTH;
925 
926 	infoframe_fix_checksum(&frame);
927 
928 	disable_infoframe(transcoder, DIP_SPD);
929 	write_infoframe(transcoder, DIP_SPD, &frame);
930 	enable_infoframe(transcoder, DIP_SPD);
931 }
932 
change_infoframe_checksum(Transcoder transcoder,DipType type,uint32_t selected_csum)933 static void change_infoframe_checksum(Transcoder transcoder, DipType type,
934 				      uint32_t selected_csum)
935 {
936 	DipInfoFrame frame;
937 
938 	load_infoframe(transcoder, &frame, type);
939 	frame.generic.body[0] = selected_csum;
940 	disable_infoframe(transcoder, type);
941 	write_infoframe(transcoder, type, &frame);
942 	enable_infoframe(transcoder, type);
943 }
944 
change_infoframe_frequency(Transcoder transcoder,DipType type,DipFrequency frequency)945 static void change_infoframe_frequency(Transcoder transcoder, DipType type,
946 				       DipFrequency frequency)
947 {
948 	Register reg = get_dip_ctl_reg(transcoder);
949 	uint32_t val = INREG(reg);
950 
951 	if (type == DIP_AVI && frequency != DIP_FREQ_EVERY_VSYNC) {
952 		printf("Error: AVI infoframe must be sent every VSync!\n");
953 		frequency = DIP_FREQ_EVERY_VSYNC;
954 	}
955 
956 	val &= ~DIP_CTL_FREQUENCY;
957 	val |= (frequency << 16);
958 	OUTREG(reg, val);
959 }
960 
disable_dip(Transcoder transcoder)961 static void disable_dip(Transcoder transcoder)
962 {
963 	Register reg = get_dip_ctl_reg(transcoder);
964 	uint32_t val = INREG(reg);
965 	val &= ~DIP_CTL_ENABLE;
966 	OUTREG(reg, val);
967 }
968 
enable_dip(Transcoder transcoder)969 static void enable_dip(Transcoder transcoder)
970 {
971 	Register reg = get_dip_ctl_reg(transcoder);
972 	uint32_t val = INREG(reg);
973 	val |= DIP_CTL_ENABLE;
974 	OUTREG(reg, val);
975 }
976 
disable_hdmi_port(Register reg)977 static void disable_hdmi_port(Register reg)
978 {
979 	uint32_t val = INREG(reg);
980 	val &= ~HDMI_PORT_ENABLE;
981 	OUTREG(reg, val);
982 }
983 
enable_hdmi_port(Register reg)984 static void enable_hdmi_port(Register reg)
985 {
986 	uint32_t val = INREG(reg);
987 	val |= HDMI_PORT_ENABLE;
988 	OUTREG(reg, val);
989 }
990 
print_usage(void)991 static void print_usage(void)
992 {
993 printf("Options:\n"
994 "  -d, --dump\n"
995 "          dump information about all transcoders\n"
996 "  -c, --change-fields [fields]\n"
997 "          change infoframe fields from selected transcoder\n"
998 "  -k, --change-checksum [checksum]\n"
999 "          change infoframe checksum (value in hex)\n"
1000 "  -q, --change-frequency [frequency]\n"
1001 "          change infoframe frequency (once, everyvsync or everyothervsync)\n"
1002 "  -n, --disable\n"
1003 "          disable the selected infoframe from the selected transcoder\n"
1004 "  -N, --enable\n"
1005 "          enable the selected infoframe from the selected transcoder\n"
1006 "  -x, --disable-infoframes\n"
1007 "          disable all infoframes from selected transcoder\n"
1008 "  -X, --enable-infoframes\n"
1009 "          enable sending infoframes on the selected transcoder\n"
1010 "  -p, --disable-hdmi-port [port]\n"
1011 "          disable hdmi port on the selected transcoder (B, C or D)\n"
1012 "  -P, --enable-hdmi-port [port]\n"
1013 "          enable hdmi port on the selected transcoder (B, C or D)\n"
1014 "  -t, --transcoder\n"
1015 "          select transcoder (A, B or C)\n"
1016 "  -f, --infoframe\n"
1017 "          select infoframe (AVI, Vendor, Gamut or SPD)\n"
1018 "  -h, --help\n"
1019 "          prints this message\n"
1020 "\n"
1021 "Examples:\n"
1022 "\n"
1023 "  Dump information:\n"
1024 "          intel_infoframes\n"
1025 "\n"
1026 "  Disable overscan and set ITC on transcoder B:\n"
1027 "          intel_infoframes -t B -f AVI -c 'S 2 ITC 1'\n"
1028 "\n"
1029 "  Many actions on the same command:\n"
1030 "  - enable overscan on transcoder A\n"
1031 "  - enable overscan and change description on transcoder B\n"
1032 "  - disable all infoframes on transcoder C\n"
1033 "  - dump the resulting state:\n"
1034 "          intel_infoframes -t A -f AVI -c 'S 1' \\\n"
1035 "                           -t B -f AVI -c 'S 2' \\\n"
1036 "                                -f SPD -c 'description Linux' \\\n"
1037 "                           -t C --disable-infoframes \\\n"
1038 "                           -d\n"
1039 "\n"
1040 "  Even more:\n"
1041 "  - print the help message\n"
1042 "  - completely disable all infoframes on all transcoders\n"
1043 "  - dump the state"
1044 "  - enable sending infoframes on transcoder B, but disable all infoframes\n"
1045 "  - enable AVI infoframes transcoder B, use underscan and declare ITC\n"
1046 "  - also enable SPD infoframes on the same transcoder, change frequency to\n"
1047 "    every vsync and change vendor, description and source\n"
1048 "  - dump the state again\n"
1049 "          intel_infoframes -h \\\n"
1050 "                           -t A -x -t B -x -t C -x \\\n"
1051 "                           -d \\\n"
1052 "                           -t A -X -f AVI -n -f Vendor -n \\\n"
1053 "                           -f Gamut -n -f SPD -n \\\n"
1054 "                           -f AVI -N -c 'S 2 ITC 1'\\\n"
1055 "                           -f SPD -q everyvsync \\\n"
1056 "                           -c 'vendor me description mine source 0x09' \\\n"
1057 "                           -d\n"
1058 "\n"
1059 "Infoframe fields used by the --change-fields option:\n"
1060 "  - AVI infoframe fields:\n"
1061 "          S B A Y R M C SC Q EC ITC VIC PR top bottom left right\n"
1062 "  - SPD infoframe fields:\n"
1063 "          vendor description source\n"
1064 "  - Other infoframe fields are not implemented yet.\n");
1065 }
1066 
1067 #define CHECK_TRANSCODER(transcoder)                  \
1068 	if (transcoder == TRANSC_INVALID) {           \
1069 		printf("Transcoder not selected.\n"); \
1070 		ret = 1;                              \
1071 		goto out;                             \
1072 	}
1073 
1074 #define CHECK_DIP(dip)                                \
1075 	if (dip == DIP_INVALID) {                     \
1076 		printf("Infoframe not selected.\n");  \
1077 		ret = 1;                              \
1078 		goto out;                             \
1079 	}
1080 
main(int argc,char * argv[])1081 int main(int argc, char *argv[])
1082 {
1083 	int opt;
1084 	int ret = 0;
1085 	Transcoder transcoder = TRANSC_INVALID;
1086 	DipType dip = DIP_INVALID;
1087 	Register hdmi_port;
1088 
1089 	char short_opts[] = "dc:k:q:nNxXp:P:t:f:h";
1090 	struct option long_opts[] = {
1091 		{ "dump",               no_argument,       NULL, 'd' },
1092 		{ "change-fields",      required_argument, NULL, 'c' },
1093 		{ "change-checksum",    required_argument, NULL, 'k' },
1094 		{ "change-frequency",   required_argument, NULL, 'q' },
1095 		{ "disable",            no_argument,       NULL, 'n' },
1096 		{ "enable",             no_argument,       NULL, 'N' },
1097 		{ "disable-infoframes", no_argument,       NULL, 'x' },
1098 		{ "enable-infoframes",  no_argument,       NULL, 'X' },
1099 		{ "disable-hdmi-port",  required_argument, NULL, 'p' },
1100 		{ "enable-hdmi-port",   required_argument, NULL, 'P' },
1101 		{ "transcoder" ,        required_argument, NULL, 't' },
1102 		{ "infoframe",          required_argument, NULL, 'f' },
1103 		{ "help",               no_argument,       NULL, 'h' },
1104 		{ 0 }
1105 	};
1106 
1107 	printf("WARNING: This is just a debugging tool! Don't expect it to work"
1108 	       " perfectly: the Kernel might undo our changes.\n");
1109 
1110 	pci_dev = intel_get_pci_device();
1111 	intel_register_access_init(pci_dev, 0, -1);
1112 	intel_check_pch();
1113 
1114 	if (IS_GEN4(pci_dev->device_id))
1115 		gen = 4;
1116 	else if (IS_GEN5(pci_dev->device_id))
1117 		gen = 5;
1118 	else if (IS_GEN6(pci_dev->device_id))
1119 		gen = 6;
1120 	else if (IS_GEN7(pci_dev->device_id))
1121 		gen = 7;
1122 	else {
1123 		printf("This program does not support your hardware yet.\n");
1124 		ret = 1;
1125 		goto out;
1126 	}
1127 
1128 	while (1) {
1129 		opt = getopt_long(argc, argv, short_opts, long_opts, NULL);
1130 		if (opt == -1)
1131 			break;
1132 
1133 		switch (opt) {
1134 		case 'd':
1135 			dump_all_info();
1136 			break;
1137 		case 'c':
1138 			if (transcoder == TRANSC_INVALID) {
1139 				printf("Transcoder not selected.\n");
1140 				ret = 1;
1141 				goto out;
1142 			}
1143 			switch (dip) {
1144 			case DIP_AVI:
1145 				change_avi_infoframe(transcoder, optarg);
1146 				break;
1147 			case DIP_VENDOR:
1148 			case DIP_GAMUT:
1149 				printf("Option not implemented yet.\n");
1150 				ret = 1;
1151 				goto out;
1152 			case DIP_SPD:
1153 				change_spd_infoframe(transcoder, optarg);
1154 				break;
1155 			case DIP_INVALID:
1156 				printf("Infoframe not selected.\n");
1157 				ret = 1;
1158 				goto out;
1159 			}
1160 			break;
1161 		case 'k':
1162 			CHECK_TRANSCODER(transcoder);
1163 			CHECK_DIP(dip);
1164 			change_infoframe_checksum(transcoder, dip, atoi(optarg));
1165 			break;
1166 		case 'q':
1167 			CHECK_TRANSCODER(transcoder);
1168 			CHECK_DIP(dip);
1169 			if (!strcmp(optarg, "once"))
1170 				change_infoframe_frequency(transcoder, dip,
1171 						DIP_FREQ_ONCE);
1172 			else if (!strcmp(optarg, "everyvsync"))
1173 				change_infoframe_frequency(transcoder, dip,
1174 						DIP_FREQ_EVERY_VSYNC);
1175 			else if (!strcmp(optarg, "everyothervsync"))
1176 				change_infoframe_frequency(transcoder, dip,
1177 						DIP_FREQ_EVERY_OTHER_VSYNC);
1178 			else {
1179 				printf("Invalid frequency.\n");
1180 				ret = 1;
1181 				goto out;
1182 			}
1183 			break;
1184 		case 'n':
1185 			CHECK_TRANSCODER(transcoder);
1186 			CHECK_DIP(dip);
1187 			disable_infoframe(transcoder, dip);
1188 			break;
1189 		case 'N':
1190 			CHECK_TRANSCODER(transcoder);
1191 			CHECK_DIP(dip);
1192 			enable_infoframe(transcoder, dip);
1193 			break;
1194 		case 'x':
1195 			CHECK_TRANSCODER(transcoder);
1196 			disable_dip(transcoder);
1197 			break;
1198 		case 'X':
1199 			CHECK_TRANSCODER(transcoder);
1200 			enable_dip(transcoder);
1201 			break;
1202 		case 'p':
1203 		case 'P':
1204 			if (!strcmp(optarg, "B"))
1205 				hdmi_port = get_hdmi_port(0);
1206 			else if (!strcmp(optarg, "C"))
1207 				hdmi_port = get_hdmi_port(1);
1208 			else if (!strcmp(optarg, "D"))
1209 				hdmi_port = get_hdmi_port(2);
1210 			else {
1211 				printf("Invalid HDMI port.\n");
1212 				ret = 1;
1213 				goto out;
1214 			}
1215 			if (opt == 'p')
1216 				disable_hdmi_port(hdmi_port);
1217 			else
1218 				enable_hdmi_port(hdmi_port);
1219 			break;
1220 		case 't':
1221 			if (!strcmp(optarg, "A"))
1222 				transcoder = TRANSC_A;
1223 			else if (!strcmp(optarg, "B"))
1224 				transcoder = TRANSC_B;
1225 			else if (intel_pch >= PCH_CPT && !strcmp(optarg, "C")) {
1226 				transcoder = TRANSC_C;
1227 			} else {
1228 				printf("Invalid transcoder.\n");
1229 				ret = 1;
1230 				goto out;
1231 			}
1232 			break;
1233 		case 'f':
1234 			if (!strcmp(optarg, "AVI"))
1235 				dip = DIP_AVI;
1236 			else if (!strcmp(optarg, "Vendor"))
1237 				dip = DIP_VENDOR;
1238 			else if (!strcmp(optarg, "Gamut"))
1239 				dip = DIP_GAMUT;
1240 			else if (!strcmp(optarg, "SPD"))
1241 				dip = DIP_SPD;
1242 			else {
1243 				printf("Invalid infoframe.\n");
1244 				ret = 1;
1245 				goto out;
1246 			}
1247 			break;
1248 		case 'h':
1249 			print_usage();
1250 			break;
1251 		default:
1252 			print_usage();
1253 			ret = 1;
1254 			goto out;
1255 		}
1256 	}
1257 
1258 out:
1259 	intel_register_access_fini();
1260 	return ret;
1261 }
1262