2 * Copyright © 2012 Intel Corporation
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:
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
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.
24 * Paulo Zanoni <paulo.r.zanoni@intel.com>
34 #include "intel_chipset.h"
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,
76 DIP_FREQ_EVERY_VSYNC = 1,
77 DIP_FREQ_EVERY_OTHER_VSYNC = 2,
78 DIP_FREQ_RESERVED = 3,
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
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)
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)
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)
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
136 #define VENDOR_ID_HDMI 0x000c03
143 } DipInfoFrameHeader;
147 DipInfoFrameHeader header;
180 DipInfoFrameHeader header;
183 uint8_t description[16];
185 } __attribute__((packed)) spd;
187 DipInfoFrameHeader header;
193 uint8_t video_format :3;
199 uint8_t s3d_structure :4;
204 uint8_t s3d_ext_data :4;
205 } __attribute__((packed)) vendor;
207 DipInfoFrameHeader header;
214 Register vlv_hdmi_ports[] = {
219 Register vlv_dip_ctl_regs[] = {
224 Register vlv_dip_data_regs[] = {
229 Register gen4_hdmi_ports[] = {
233 Register pch_hdmi_ports[] = {
238 Register pch_dip_ctl_regs[] = {
243 Register pch_dip_data_regs[] = {
248 const char *hdmi_port_names[] = {
253 const char *transcoder_names[] = {
258 const char *dip_frequency_names[] = {
265 struct pci_device *pci_dev;
268 static const char *spd_source_to_string(SourceDevice source)
271 case SOURCE_DEVICE_UNKNOWN:
273 case SOURCE_DEVICE_DIGITAL_STB:
274 return "digital stb";
275 case SOURCE_DEVICE_DVD_PLAYER:
277 case SOURCE_DEVICE_D_VHS:
279 case SOURCE_DEVICE_HDD_VIDEORECORDER:
280 return "hdd videorecorder";
281 case SOURCE_DEVICE_DVC:
283 case SOURCE_DEVICE_DSC:
285 case SOURCE_DEVICE_VIDEO_CD:
287 case SOURCE_DEVICE_GAME:
289 case SOURCE_DEVICE_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";
300 static Register get_dip_ctl_reg(Transcoder transcoder)
302 if (IS_VALLEYVIEW(pci_dev->device_id))
303 return vlv_dip_ctl_regs[transcoder];
305 return REG_DIP_CTL_GEN4;
307 return pch_dip_ctl_regs[transcoder];
310 static Register get_dip_data_reg(Transcoder transcoder)
312 if (IS_VALLEYVIEW(pci_dev->device_id))
313 return vlv_dip_data_regs[transcoder];
315 return REG_DIP_DATA_GEN4;
317 return pch_dip_data_regs[transcoder];
320 static Register get_hdmi_port(int hdmi_port_index)
322 if (IS_VALLEYVIEW(pci_dev->device_id))
323 return vlv_hdmi_ports[hdmi_port_index];
325 assert(hdmi_port_index < 2);
326 return gen4_hdmi_ports[hdmi_port_index];
328 return pch_hdmi_ports[hdmi_port_index];
332 static void load_infoframe(Transcoder transcoder, DipInfoFrame *frame,
335 Register ctl_reg = get_dip_ctl_reg(transcoder);
336 Register data_reg = get_dip_data_reg(transcoder);
340 ctl_val = INREG(ctl_reg);
342 ctl_val &= ~DIP_CTL_BUFFER_INDEX;
343 ctl_val |= type << 19;
344 OUTREG(ctl_reg, ctl_val);
345 ctl_val = INREG(ctl_reg);
347 ctl_val &= ~DIP_CTL_ACCESS_ADDR;
348 OUTREG(ctl_reg, ctl_val);
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);
357 static int infoframe_valid_checksum(DipInfoFrame *frame)
360 int length = frame->generic.header.length;
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];
371 static void infoframe_fix_checksum(DipInfoFrame *frame)
374 int length = frame->generic.header.length;
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;
385 static void dump_port_info(int hdmi_port_index)
387 Register port = get_hdmi_port(hdmi_port_index);
388 uint32_t val = INREG(port);
389 Transcoder transcoder;
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");
395 if (!(val & HDMI_PORT_ENABLE))
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;
403 transcoder = (val & HDMI_PORT_TRANSCODER_IBX) >> 30;
404 printf("- transcoder: %s\n", transcoder_names[transcoder]);
406 switch ((val & HDMI_PORT_ENCODING) >> 10) {
408 printf("- mode: SDVO\n");
411 printf("- mode: TMDS\n");
414 printf("- mode: INVALID!\n");
417 printf("- mode: %s\n", val & HDMI_PORT_MODE ? "HDMI" : "DVI");
418 printf("- audio: %s\n", val & HDMI_PORT_AUDIO ? "enabled" : "disabled");
421 static void dump_raw_infoframe(DipInfoFrame *frame)
425 for (i = 0; i < 16; i++) {
428 printf(" %08x", frame->data32[i]);
433 static void dump_avi_info(Transcoder transcoder)
435 Register reg = get_dip_ctl_reg(transcoder);
440 load_infoframe(transcoder, &frame, DIP_AVI);
443 printf("AVI InfoFrame:\n");
446 printf("- %sbeing transmitted\n",
447 val & DIP_CTL_BUFFER_TRANS_ACTIVE_GEN4 ? "" : "not ");
450 freq = (val & DIP_CTL_FREQUENCY) >> 16;
451 printf("- frequency: %s\n", dip_frequency_names[freq]);
453 dump_raw_infoframe(&frame);
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,
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,
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,
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],
475 if (!infoframe_valid_checksum(&frame))
476 printf("Invalid InfoFrame checksum!\n");
479 static const char *vendor_id_to_string(uint32_t id)
489 static const char *s3d_structure_to_string(int format)
493 return "Frame Packing";
497 return "Side By Side (half)";
503 static void dump_vendor_hdmi(DipInfoFrame *frame)
505 int vic_present = frame->vendor.video_format & 0x1;
506 int s3d_present = frame->vendor.video_format & 0x2;
508 printf("- video format: 0x%03x %s\n", frame->vendor.video_format,
509 s3d_present ? "(3D)" : "");
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");
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;
522 printf("- 3D Format: %s\n",
523 s3d_structure_to_string(s3d_structure));
525 /* Side-by-side (half) */
526 if (s3d_structure >= 8)
527 printf("- 3D Ext Data 0x%x\n",
528 frame->vendor.s3d_ext_data);
532 static void dump_vendor_info(Transcoder transcoder)
534 Register reg = get_dip_ctl_reg(transcoder);
535 uint32_t val, vendor_id;
539 load_infoframe(transcoder, &frame, DIP_VENDOR);
542 printf("Vendor InfoFrame:\n");
545 printf("- %sbeing transmitted\n",
546 val & DIP_CTL_BUFFER_TRANS_ACTIVE_GEN4 ? "" : "not ");
549 freq = (val & DIP_CTL_FREQUENCY) >> 16;
550 printf("- frequency: %s\n", dip_frequency_names[freq]);
552 dump_raw_infoframe(&frame);
554 vendor_id = frame.vendor.id[2] << 16 | frame.vendor.id[1] << 8 |
557 printf("- vendor Id: 0x%06x (%s)\n", vendor_id,
558 vendor_id_to_string(vendor_id));
560 if (vendor_id == VENDOR_ID_HDMI)
561 dump_vendor_hdmi(&frame);
563 if (!infoframe_valid_checksum(&frame))
564 printf("Invalid InfoFrame checksum!\n");
567 static void dump_gamut_info(Transcoder transcoder)
569 Register reg = get_dip_ctl_reg(transcoder);
574 load_infoframe(transcoder, &frame, DIP_GAMUT);
577 printf("Gamut InfoFrame:\n");
580 printf("- %sbeing transmitted\n",
581 val & DIP_CTL_BUFFER_TRANS_ACTIVE_GEN4 ? "" : "not ");
584 freq = (val & DIP_CTL_FREQUENCY) >> 16;
585 printf("- frequency: %s\n", dip_frequency_names[freq]);
587 dump_raw_infoframe(&frame);
589 if (!infoframe_valid_checksum(&frame))
590 printf("Invalid InfoFrame checksum!\n");
593 static void dump_spd_info(Transcoder transcoder)
595 Register reg = get_dip_ctl_reg(transcoder);
600 char description[17];
602 load_infoframe(transcoder, &frame, DIP_SPD);
605 printf("SPD InfoFrame:\n");
608 printf("- %sbeing transmitted\n",
609 val & DIP_CTL_BUFFER_TRANS_ACTIVE_GEN4 ? "" : "not ");
612 freq = (val & DIP_CTL_FREQUENCY) >> 16;
613 printf("- frequency: %s\n", dip_frequency_names[freq]);
615 dump_raw_infoframe(&frame);
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,
622 memcpy(vendor, frame.spd.vendor, 8);
624 memcpy(description, frame.spd.description, 16);
625 description[16] = '\0';
627 printf("- vendor: %s\n", vendor);
628 printf("- description: %s\n", description);
629 printf("- source: %s\n", spd_source_to_string(frame.spd.source));
631 if (!infoframe_valid_checksum(&frame))
632 printf("Invalid InfoFrame checksum!\n");
635 static void dump_transcoder_info(Transcoder transcoder)
637 Register reg = get_dip_ctl_reg(transcoder);
638 uint32_t val = INREG(reg);
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");
646 case DIP_CTL_PORT_SEL_C_GEN4:
647 printf("- port C\n");
650 printf("- INVALID port!\n");
653 printf("\nTranscoder %s:\n", transcoder_names[transcoder]);
655 printf("- %s\n", val & DIP_CTL_ENABLE ? "enabled" : "disabled");
656 if (!(val & DIP_CTL_ENABLE))
659 printf("- GCP: %s\n", val & DIP_CTL_GCP_ENABLE ?
660 "enabled" : "disabled");
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);
672 static void dump_all_info(void)
676 if (IS_VALLEYVIEW(pci_dev->device_id)) {
677 for (i = 0; i < ARRAY_SIZE(vlv_hdmi_ports); 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++)
684 dump_transcoder_info(0);
686 for (i = 0; i < ARRAY_SIZE(pch_hdmi_ports); i++)
688 for (i = 0; i < ARRAY_SIZE(pch_dip_ctl_regs); i++)
689 dump_transcoder_info(i);
693 static void write_infoframe(Transcoder transcoder, DipType type,
696 Register ctl_reg = get_dip_ctl_reg(transcoder);
697 Register data_reg = get_dip_data_reg(transcoder);
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);
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]);
714 static void disable_infoframe(Transcoder transcoder, DipType type)
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));
724 static void enable_infoframe(Transcoder transcoder, DipType type)
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));
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)
739 if (!strcmp(name, s)) {
740 rc = sscanf(*commands, "%x%n", value, &read);
741 *commands = &(*commands)[read];
743 printf("Invalid value.\n");
747 if (*value < min || *value > max) {
748 printf("Value outside allowed range.\n");
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)
761 if (!strcmp(name, s)) {
762 rc = sscanf(*commands, "%31s%n", value, &read);
763 *commands = &(*commands)[read];
765 printf("Invalid value.\n");
769 size = strlen(value);
770 if (size < min_size || size > max_size) {
771 printf("String either too big or too small.\n");
779 static void change_avi_infoframe(Transcoder transcoder, char *commands)
781 Register reg = get_dip_ctl_reg(transcoder);
787 char *current = commands;
789 load_infoframe(transcoder, &frame, DIP_AVI);
793 rc = sscanf(current, "%31s%n", option, &read);
794 current = ¤t[read];
797 } else if (rc != 1) {
798 printf("Invalid option: %s\n", option);
802 if (parse_infoframe_option_u("S", option, 0, 2, &option_val,
804 frame.avi.S = option_val;
805 else if (parse_infoframe_option_u("B", option, 0, 3,
806 &option_val, ¤t))
807 frame.avi.B = option_val;
808 else if (parse_infoframe_option_u("A", option, 0, 1,
809 &option_val, ¤t))
810 frame.avi.A = option_val;
811 else if (parse_infoframe_option_u("Y", option, 0, 2,
812 &option_val, ¤t))
813 frame.avi.Y = option_val;
814 else if (parse_infoframe_option_u("R", option, 0, 15,
815 &option_val, ¤t))
816 frame.avi.R = option_val;
817 else if (parse_infoframe_option_u("M", option, 0, 2,
818 &option_val, ¤t))
819 frame.avi.M = option_val;
820 else if (parse_infoframe_option_u("C", option, 0, 3,
821 &option_val, ¤t))
822 frame.avi.C = option_val;
823 else if (parse_infoframe_option_u("SC", option, 0, 3,
824 &option_val, ¤t))
825 frame.avi.SC = option_val;
826 else if (parse_infoframe_option_u("Q", option, 0, 2,
827 &option_val, ¤t))
828 frame.avi.Q = option_val;
829 else if (parse_infoframe_option_u("EC", option, 0, 1,
830 &option_val,¤t))
831 frame.avi.EC = option_val;
832 else if (parse_infoframe_option_u("ITC", option, 0, 1,
833 &option_val, ¤t))
834 frame.avi.ITC = option_val;
835 else if (parse_infoframe_option_u("VIC", option, 0, 127,
836 &option_val, ¤t))
837 frame.avi.VIC = option_val;
838 else if (parse_infoframe_option_u("PR", option, 0, 15,
839 &option_val, ¤t))
840 frame.avi.PR = option_val;
841 else if (parse_infoframe_option_u("top", option, 0, 65535,
842 &option_val, ¤t))
843 frame.avi.top = option_val;
844 else if (parse_infoframe_option_u("bottom", option, 0, 65535,
845 &option_val, ¤t))
846 frame.avi.bottom = option_val;
847 else if (parse_infoframe_option_u("left", option, 0, 65535,
848 &option_val, ¤t))
849 frame.avi.left = option_val;
850 else if (parse_infoframe_option_u("right", option, 0, 65535,
851 &option_val, ¤t))
852 frame.avi.right = option_val;
854 printf("Unrecognized option: %s\n", option);
857 val &= ~DIP_CTL_FREQUENCY;
858 val |= DIP_CTL_FREQ_EVERY;
861 frame.avi.header.type = AVI_INFOFRAME_TYPE;
862 frame.avi.header.version = AVI_INFOFRAME_VERSION;
863 frame.avi.header.length = AVI_INFOFRAME_LENGTH;
868 frame.avi.Rsvd4[0] = 0;
869 frame.avi.Rsvd4[1] = 0;
870 frame.avi.Rsvd4[2] = 0;
872 infoframe_fix_checksum(&frame);
874 disable_infoframe(transcoder, DIP_AVI);
875 write_infoframe(transcoder, DIP_AVI, &frame);
876 enable_infoframe(transcoder, DIP_AVI);
879 static void change_spd_infoframe(Transcoder transcoder, char *commands)
881 Register reg = get_dip_ctl_reg(transcoder);
885 char option_val_s[32];
886 uint32_t option_val_i;
888 char *current = commands;
890 load_infoframe(transcoder, &frame, DIP_SPD);
894 rc = sscanf(current, "%15s%n", option, &read);
895 current = ¤t[read];
898 } else if (rc != 1) {
899 printf("Invalid option: %s\n", option);
903 memset(option_val_s, 0, 32);
905 if (parse_infoframe_option_s("vendor", option, 0, 8,
906 option_val_s, ¤t))
907 memcpy(frame.spd.vendor, option_val_s, 8);
908 else if (parse_infoframe_option_s("description", option, 0, 16,
909 option_val_s, ¤t))
910 memcpy(frame.spd.description, option_val_s, 16);
911 else if (parse_infoframe_option_u("source", option, 0, 0x0c,
912 &option_val_i, ¤t))
913 frame.spd.source = option_val_i;
915 printf("Unrecognized option: %s\n", option);
918 val &= ~DIP_CTL_FREQUENCY;
919 val |= DIP_CTL_FREQ_EVERY_OTHER;
922 frame.spd.header.type = SPD_INFOFRAME_TYPE;
923 frame.spd.header.version = SPD_INFOFRAME_VERSION;
924 frame.spd.header.length = SPD_INFOFRAME_LENGTH;
926 infoframe_fix_checksum(&frame);
928 disable_infoframe(transcoder, DIP_SPD);
929 write_infoframe(transcoder, DIP_SPD, &frame);
930 enable_infoframe(transcoder, DIP_SPD);
933 static void change_infoframe_checksum(Transcoder transcoder, DipType type,
934 uint32_t selected_csum)
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);
945 static void change_infoframe_frequency(Transcoder transcoder, DipType type,
946 DipFrequency frequency)
948 Register reg = get_dip_ctl_reg(transcoder);
949 uint32_t val = INREG(reg);
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;
956 val &= ~DIP_CTL_FREQUENCY;
957 val |= (frequency << 16);
961 static void disable_dip(Transcoder transcoder)
963 Register reg = get_dip_ctl_reg(transcoder);
964 uint32_t val = INREG(reg);
965 val &= ~DIP_CTL_ENABLE;
969 static void enable_dip(Transcoder transcoder)
971 Register reg = get_dip_ctl_reg(transcoder);
972 uint32_t val = INREG(reg);
973 val |= DIP_CTL_ENABLE;
977 static void disable_hdmi_port(Register reg)
979 uint32_t val = INREG(reg);
980 val &= ~HDMI_PORT_ENABLE;
984 static void enable_hdmi_port(Register reg)
986 uint32_t val = INREG(reg);
987 val |= HDMI_PORT_ENABLE;
991 static void print_usage(void)
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"
1003 " disable the selected infoframe from the selected transcoder\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"
1019 " prints this message\n"
1023 " Dump information:\n"
1024 " intel_infoframes\n"
1026 " Disable overscan and set ITC on transcoder B:\n"
1027 " intel_infoframes -t B -f AVI -c 'S 2 ITC 1'\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"
1041 " - print the help message\n"
1042 " - completely disable all infoframes on all transcoders\n"
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"
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"
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");
1067 #define CHECK_TRANSCODER(transcoder) \
1068 if (transcoder == TRANSC_INVALID) { \
1069 printf("Transcoder not selected.\n"); \
1074 #define CHECK_DIP(dip) \
1075 if (dip == DIP_INVALID) { \
1076 printf("Infoframe not selected.\n"); \
1081 int main(int argc, char *argv[])
1085 Transcoder transcoder = TRANSC_INVALID;
1086 DipType dip = DIP_INVALID;
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' },
1106 printf("WARNING: This is just a debugging tool! Don't expect it to work"
1107 " perfectly: the Kernel might undo our changes.\n");
1109 pci_dev = intel_get_pci_device();
1110 intel_register_access_init(pci_dev, 0);
1113 if (IS_GEN4(pci_dev->device_id))
1115 else if (IS_GEN5(pci_dev->device_id))
1117 else if (IS_GEN6(pci_dev->device_id))
1119 else if (IS_GEN7(pci_dev->device_id))
1122 printf("This program does not support your hardware yet.\n");
1128 opt = getopt_long(argc, argv, short_opts, long_opts, NULL);
1137 if (transcoder == TRANSC_INVALID) {
1138 printf("Transcoder not selected.\n");
1144 change_avi_infoframe(transcoder, optarg);
1148 printf("Option not implemented yet.\n");
1152 change_spd_infoframe(transcoder, optarg);
1155 printf("Infoframe not selected.\n");
1161 CHECK_TRANSCODER(transcoder);
1163 change_infoframe_checksum(transcoder, dip, atoi(optarg));
1166 CHECK_TRANSCODER(transcoder);
1168 if (!strcmp(optarg, "once"))
1169 change_infoframe_frequency(transcoder, dip,
1171 else if (!strcmp(optarg, "everyvsync"))
1172 change_infoframe_frequency(transcoder, dip,
1173 DIP_FREQ_EVERY_VSYNC);
1174 else if (!strcmp(optarg, "everyothervsync"))
1175 change_infoframe_frequency(transcoder, dip,
1176 DIP_FREQ_EVERY_OTHER_VSYNC);
1178 printf("Invalid frequency.\n");
1184 CHECK_TRANSCODER(transcoder);
1186 disable_infoframe(transcoder, dip);
1189 CHECK_TRANSCODER(transcoder);
1191 enable_infoframe(transcoder, dip);
1194 CHECK_TRANSCODER(transcoder);
1195 disable_dip(transcoder);
1198 CHECK_TRANSCODER(transcoder);
1199 enable_dip(transcoder);
1203 if (!strcmp(optarg, "B"))
1204 hdmi_port = get_hdmi_port(0);
1205 else if (!strcmp(optarg, "C"))
1206 hdmi_port = get_hdmi_port(1);
1207 else if (!strcmp(optarg, "D"))
1208 hdmi_port = get_hdmi_port(2);
1210 printf("Invalid HDMI port.\n");
1215 disable_hdmi_port(hdmi_port);
1217 enable_hdmi_port(hdmi_port);
1220 if (!strcmp(optarg, "A"))
1221 transcoder = TRANSC_A;
1222 else if (!strcmp(optarg, "B"))
1223 transcoder = TRANSC_B;
1224 else if (intel_pch >= PCH_CPT && !strcmp(optarg, "C")) {
1225 transcoder = TRANSC_C;
1227 printf("Invalid transcoder.\n");
1233 if (!strcmp(optarg, "AVI"))
1235 else if (!strcmp(optarg, "Vendor"))
1237 else if (!strcmp(optarg, "Gamut"))
1239 else if (!strcmp(optarg, "SPD"))
1242 printf("Invalid infoframe.\n");
1258 intel_register_access_fini();