You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1262 lines
32 KiB
1262 lines
32 KiB
/*
|
|
* Copyright © 2012 Intel Corporation
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice (including the next
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
* Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
*
|
|
* Authors:
|
|
* Paulo Zanoni <paulo.r.zanoni@intel.com>
|
|
*
|
|
*/
|
|
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <getopt.h>
|
|
#include "intel_io.h"
|
|
#include "intel_chipset.h"
|
|
#include "drmtest.h"
|
|
|
|
typedef enum {
|
|
TRANSC_A = 0,
|
|
TRANSC_B = 1,
|
|
TRANSC_C = 2,
|
|
TRANSC_INVALID
|
|
} Transcoder;
|
|
|
|
typedef enum {
|
|
REG_HDMIB_GEN4 = 0x61140,
|
|
REG_HDMIC_GEN4 = 0x61160,
|
|
REG_HDMIB_VLV = 0x1e1140,
|
|
REG_HDMIC_VLV = 0x1e1160,
|
|
REG_HDMIB_PCH = 0xe1140,
|
|
REG_HDMIC_PCH = 0xe1150,
|
|
REG_HDMID_PCH = 0xe1160,
|
|
REG_DIP_CTL_GEN4 = 0x61170,
|
|
REG_DIP_CTL_A_VLV = 0x1e0200,
|
|
REG_DIP_CTL_B_VLV = 0x1e1170,
|
|
REG_DIP_CTL_A = 0xe0200,
|
|
REG_DIP_CTL_B = 0xe1200,
|
|
REG_DIP_CTL_C = 0xe2200,
|
|
REG_DIP_DATA_GEN4 = 0x61178,
|
|
REG_DIP_DATA_A_VLV = 0x1e0208,
|
|
REG_DIP_DATA_B_VLV = 0x1e1174,
|
|
REG_DIP_DATA_A = 0xe0208,
|
|
REG_DIP_DATA_B = 0xe1208,
|
|
REG_DIP_DATA_C = 0xe2208,
|
|
} Register;
|
|
|
|
typedef enum {
|
|
DIP_AVI = 0,
|
|
DIP_VENDOR = 1,
|
|
DIP_GAMUT = 2,
|
|
DIP_SPD = 3,
|
|
DIP_INVALID,
|
|
} DipType;
|
|
|
|
typedef enum {
|
|
DIP_FREQ_ONCE = 0,
|
|
DIP_FREQ_EVERY_VSYNC = 1,
|
|
DIP_FREQ_EVERY_OTHER_VSYNC = 2,
|
|
DIP_FREQ_RESERVED = 3,
|
|
} DipFrequency;
|
|
|
|
typedef enum {
|
|
SOURCE_DEVICE_UNKNOWN = 0x00,
|
|
SOURCE_DEVICE_DIGITAL_STB = 0x01,
|
|
SOURCE_DEVICE_DVD_PLAYER = 0x02,
|
|
SOURCE_DEVICE_D_VHS = 0x03,
|
|
SOURCE_DEVICE_HDD_VIDEORECORDER = 0x04,
|
|
SOURCE_DEVICE_DVC = 0x05,
|
|
SOURCE_DEVICE_DSC = 0x06,
|
|
SOURCE_DEVICE_VIDEO_CD = 0x07,
|
|
SOURCE_DEVICE_GAME = 0x08,
|
|
SOURCE_DEVICE_PC_GENERAL = 0x09,
|
|
SOURCE_DEVICE_BLU_RAY_DISK = 0x0a,
|
|
SOURCE_DEVICE_SUPER_AUDIO_CD = 0x0b,
|
|
SOURCE_DEVICE_RESERVED = 0x0c
|
|
} SourceDevice;
|
|
|
|
#define HDMI_PORT_ENABLE (1 << 31)
|
|
#define HDMI_PORT_TRANSCODER_GEN4 (1 << 30)
|
|
#define HDMI_PORT_TRANSCODER_IBX (1 << 30)
|
|
#define HDMI_PORT_TRANSCODER_CPT (3 << 29)
|
|
#define HDMI_PORT_ENCODING (3 << 10)
|
|
#define HDMI_PORT_MODE (1 << 9)
|
|
#define HDMI_PORT_AUDIO (1 << 6)
|
|
#define HDMI_PORT_DETECTED (1 << 2)
|
|
|
|
#define DIP_CTL_ENABLE (1 << 31)
|
|
#define DIP_CTL_GCP_ENABLE (1 << 25)
|
|
#define DIP_CTL_SPD_ENABLE (1 << 24)
|
|
#define DIP_CTL_GAMUT_ENABLE (1 << 23)
|
|
#define DIP_CTL_VENDOR_ENABLE (1 << 22)
|
|
#define DIP_CTL_AVI_ENABLE (1 << 21)
|
|
#define DIP_CTL_BUFFER_INDEX (3 << 19)
|
|
#define DIP_CTL_BUFFER_AVI (0 << 19)
|
|
#define DIP_CTL_BUFFER_VENDOR (1 << 19)
|
|
#define DIP_CTL_BUFFER_GAMUT (2 << 19)
|
|
#define DIP_CTL_BUFFER_SPD (3 << 19)
|
|
#define DIP_CTL_FREQUENCY (3 << 16)
|
|
#define DIP_CTL_FREQ_ONCE (0 << 16)
|
|
#define DIP_CTL_FREQ_EVERY (1 << 16)
|
|
#define DIP_CTL_FREQ_EVERY_OTHER (2 << 16)
|
|
#define DIP_CTL_BUFFER_SIZE (15 << 8)
|
|
#define DIP_CTL_ACCESS_ADDR (15 << 0)
|
|
|
|
#define DIP_CTL_PORT_SEL_MASK_GEN4 (3 << 29)
|
|
#define DIP_CTL_PORT_SEL_B_GEN4 (1 << 29)
|
|
#define DIP_CTL_PORT_SEL_C_GEN4 (2 << 29)
|
|
#define DIP_CTL_BUFFER_TRANS_ACTIVE_GEN4 (1 << 28)
|
|
|
|
#define AVI_INFOFRAME_TYPE 0x82
|
|
#define AVI_INFOFRAME_VERSION 0x02
|
|
#define AVI_INFOFRAME_LENGTH 0x0d
|
|
#define SPD_INFOFRAME_TYPE 0x83
|
|
#define SPD_INFOFRAME_VERSION 0x01
|
|
#define SPD_INFOFRAME_LENGTH 0x19
|
|
|
|
#define VENDOR_ID_HDMI 0x000c03
|
|
|
|
typedef struct {
|
|
uint8_t type;
|
|
uint8_t version;
|
|
uint8_t length;
|
|
uint8_t ecc;
|
|
} DipInfoFrameHeader;
|
|
|
|
typedef union {
|
|
struct {
|
|
DipInfoFrameHeader header;
|
|
uint8_t checksum;
|
|
|
|
uint8_t S :2;
|
|
uint8_t B :2;
|
|
uint8_t A :1;
|
|
uint8_t Y :2;
|
|
uint8_t Rsvd0 :1;
|
|
|
|
uint8_t R :4;
|
|
uint8_t M :2;
|
|
uint8_t C :2;
|
|
|
|
uint8_t SC :2;
|
|
uint8_t Q :2;
|
|
uint8_t EC :3;
|
|
uint8_t ITC :1;
|
|
|
|
uint8_t VIC :7;
|
|
uint8_t Rsvd1 :1;
|
|
|
|
uint8_t PR :4;
|
|
uint8_t Rsvd2 :4;
|
|
|
|
uint16_t top;
|
|
uint16_t bottom;
|
|
uint16_t left;
|
|
uint16_t right;
|
|
|
|
uint16_t Rsvd3;
|
|
uint32_t Rsvd4[3];
|
|
} avi;
|
|
struct {
|
|
DipInfoFrameHeader header;
|
|
uint8_t checksum;
|
|
uint8_t vendor[8];
|
|
uint8_t description[16];
|
|
uint8_t source;
|
|
} __attribute__((packed)) spd;
|
|
struct {
|
|
DipInfoFrameHeader header;
|
|
uint8_t checksum;
|
|
|
|
uint8_t id[3];
|
|
|
|
uint8_t Rsvd0 :5;
|
|
uint8_t video_format :3;
|
|
|
|
union {
|
|
uint8_t vic;
|
|
struct {
|
|
uint8_t Rsvd1 :4;
|
|
uint8_t s3d_structure :4;
|
|
} s3d;
|
|
} pb5;
|
|
|
|
uint8_t Rsvd2 :4;
|
|
uint8_t s3d_ext_data :4;
|
|
} __attribute__((packed)) vendor;
|
|
struct {
|
|
DipInfoFrameHeader header;
|
|
uint8_t body[27];
|
|
} generic;
|
|
uint8_t data8[128];
|
|
uint32_t data32[16];
|
|
} DipInfoFrame;
|
|
|
|
Register vlv_hdmi_ports[] = {
|
|
REG_HDMIB_VLV,
|
|
REG_HDMIC_VLV,
|
|
};
|
|
|
|
Register vlv_dip_ctl_regs[] = {
|
|
REG_DIP_CTL_A_VLV,
|
|
REG_DIP_CTL_B_VLV,
|
|
};
|
|
|
|
Register vlv_dip_data_regs[] = {
|
|
REG_DIP_DATA_A_VLV,
|
|
REG_DIP_DATA_B_VLV,
|
|
};
|
|
|
|
Register gen4_hdmi_ports[] = {
|
|
REG_HDMIB_GEN4,
|
|
REG_HDMIC_GEN4,
|
|
};
|
|
Register pch_hdmi_ports[] = {
|
|
REG_HDMIB_PCH,
|
|
REG_HDMIC_PCH,
|
|
REG_HDMID_PCH
|
|
};
|
|
Register pch_dip_ctl_regs[] = {
|
|
REG_DIP_CTL_A,
|
|
REG_DIP_CTL_B,
|
|
REG_DIP_CTL_C
|
|
};
|
|
Register pch_dip_data_regs[] = {
|
|
REG_DIP_DATA_A,
|
|
REG_DIP_DATA_B,
|
|
REG_DIP_DATA_C
|
|
};
|
|
const char *hdmi_port_names[] = {
|
|
"HDMIB",
|
|
"HDMIC",
|
|
"HDMID"
|
|
};
|
|
const char *transcoder_names[] = {
|
|
"A",
|
|
"B",
|
|
"C"
|
|
};
|
|
const char *dip_frequency_names[] = {
|
|
"once",
|
|
"every vsync",
|
|
"every other vsync",
|
|
"reserved (invalid)"
|
|
};
|
|
|
|
struct pci_device *pci_dev;
|
|
int gen = 0;
|
|
|
|
static const char *spd_source_to_string(SourceDevice source)
|
|
{
|
|
switch (source) {
|
|
case SOURCE_DEVICE_UNKNOWN:
|
|
return "unknown";
|
|
case SOURCE_DEVICE_DIGITAL_STB:
|
|
return "digital stb";
|
|
case SOURCE_DEVICE_DVD_PLAYER:
|
|
return "dvd player";
|
|
case SOURCE_DEVICE_D_VHS:
|
|
return "d vhs";
|
|
case SOURCE_DEVICE_HDD_VIDEORECORDER:
|
|
return "hdd videorecorder";
|
|
case SOURCE_DEVICE_DVC:
|
|
return "dvc";
|
|
case SOURCE_DEVICE_DSC:
|
|
return "dsc";
|
|
case SOURCE_DEVICE_VIDEO_CD:
|
|
return "video cd";
|
|
case SOURCE_DEVICE_GAME:
|
|
return "game";
|
|
case SOURCE_DEVICE_PC_GENERAL:
|
|
return "pc general";
|
|
case SOURCE_DEVICE_BLU_RAY_DISK:
|
|
return "blu-ray disk";
|
|
case SOURCE_DEVICE_SUPER_AUDIO_CD:
|
|
return "super audio cd";
|
|
default:
|
|
return "reserved";
|
|
}
|
|
}
|
|
|
|
static Register get_dip_ctl_reg(Transcoder transcoder)
|
|
{
|
|
if (IS_VALLEYVIEW(pci_dev->device_id))
|
|
return vlv_dip_ctl_regs[transcoder];
|
|
else if (gen == 4)
|
|
return REG_DIP_CTL_GEN4;
|
|
else
|
|
return pch_dip_ctl_regs[transcoder];
|
|
}
|
|
|
|
static Register get_dip_data_reg(Transcoder transcoder)
|
|
{
|
|
if (IS_VALLEYVIEW(pci_dev->device_id))
|
|
return vlv_dip_data_regs[transcoder];
|
|
else if (gen == 4)
|
|
return REG_DIP_DATA_GEN4;
|
|
else
|
|
return pch_dip_data_regs[transcoder];
|
|
}
|
|
|
|
static Register get_hdmi_port(int hdmi_port_index)
|
|
{
|
|
if (IS_VALLEYVIEW(pci_dev->device_id))
|
|
return vlv_hdmi_ports[hdmi_port_index];
|
|
else if (gen == 4) {
|
|
assert(hdmi_port_index < 2);
|
|
return gen4_hdmi_ports[hdmi_port_index];
|
|
} else {
|
|
return pch_hdmi_ports[hdmi_port_index];
|
|
}
|
|
}
|
|
|
|
static void load_infoframe(Transcoder transcoder, DipInfoFrame *frame,
|
|
DipType type)
|
|
{
|
|
Register ctl_reg = get_dip_ctl_reg(transcoder);
|
|
Register data_reg = get_dip_data_reg(transcoder);
|
|
uint32_t ctl_val;
|
|
uint32_t i;
|
|
|
|
ctl_val = INREG(ctl_reg);
|
|
|
|
ctl_val &= ~DIP_CTL_BUFFER_INDEX;
|
|
ctl_val |= type << 19;
|
|
OUTREG(ctl_reg, ctl_val);
|
|
ctl_val = INREG(ctl_reg);
|
|
|
|
ctl_val &= ~DIP_CTL_ACCESS_ADDR;
|
|
OUTREG(ctl_reg, ctl_val);
|
|
|
|
for (i = 0; i < 16; i++) {
|
|
ctl_val = INREG(ctl_reg);
|
|
assert((ctl_val & DIP_CTL_ACCESS_ADDR) == i);
|
|
frame->data32[i] = INREG(data_reg);
|
|
}
|
|
}
|
|
|
|
static int infoframe_valid_checksum(DipInfoFrame *frame)
|
|
{
|
|
int i;
|
|
int length = frame->generic.header.length;
|
|
uint8_t csum;
|
|
|
|
csum = frame->generic.header.type + frame->generic.header.version +
|
|
frame->generic.header.length; /* no ecc */
|
|
for (i = 0; i < length + 1; i++)
|
|
csum += frame->generic.body[i];
|
|
|
|
return (csum == 0);
|
|
}
|
|
|
|
static void infoframe_fix_checksum(DipInfoFrame *frame)
|
|
{
|
|
int i;
|
|
int length = frame->generic.header.length;
|
|
uint8_t csum;
|
|
|
|
csum = frame->generic.header.type + frame->generic.header.version +
|
|
frame->generic.header.length; /* no ecc */
|
|
/* Length does not include the header field nor the checksum */
|
|
for (i = 1; i < length + 1; i++)
|
|
csum += frame->generic.body[i];
|
|
frame->generic.body[0] = 0x100 - csum;
|
|
}
|
|
|
|
static void dump_port_info(int hdmi_port_index)
|
|
{
|
|
Register port = get_hdmi_port(hdmi_port_index);
|
|
uint32_t val = INREG(port);
|
|
Transcoder transcoder;
|
|
|
|
printf("\nPort %s:\n", hdmi_port_names[hdmi_port_index]);
|
|
printf("- %sdetected\n", val & HDMI_PORT_DETECTED ? "" : "not ");
|
|
printf("- %s\n", val & HDMI_PORT_ENABLE ? "enabled" : "disabled");
|
|
|
|
if (!(val & HDMI_PORT_ENABLE))
|
|
return;
|
|
|
|
if (gen == 4 || IS_VALLEYVIEW(pci_dev->device_id))
|
|
transcoder = (val & HDMI_PORT_TRANSCODER_GEN4) >> 30;
|
|
else if (intel_pch >= PCH_CPT)
|
|
transcoder = (val & HDMI_PORT_TRANSCODER_CPT) >> 29;
|
|
else
|
|
transcoder = (val & HDMI_PORT_TRANSCODER_IBX) >> 30;
|
|
printf("- transcoder: %s\n", transcoder_names[transcoder]);
|
|
|
|
switch ((val & HDMI_PORT_ENCODING) >> 10) {
|
|
case 0:
|
|
printf("- mode: SDVO\n");
|
|
break;
|
|
case 2:
|
|
printf("- mode: TMDS\n");
|
|
break;
|
|
default:
|
|
printf("- mode: INVALID!\n");
|
|
}
|
|
|
|
printf("- mode: %s\n", val & HDMI_PORT_MODE ? "HDMI" : "DVI");
|
|
printf("- audio: %s\n", val & HDMI_PORT_AUDIO ? "enabled" : "disabled");
|
|
}
|
|
|
|
static void dump_raw_infoframe(DipInfoFrame *frame)
|
|
{
|
|
unsigned int i;
|
|
printf("- raw:");
|
|
for (i = 0; i < 16; i++) {
|
|
if (i % 4 == 0)
|
|
printf("\n ");
|
|
printf(" %08x", frame->data32[i]);
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
static void dump_avi_info(Transcoder transcoder)
|
|
{
|
|
Register reg = get_dip_ctl_reg(transcoder);
|
|
uint32_t val;
|
|
DipFrequency freq;
|
|
DipInfoFrame frame;
|
|
|
|
load_infoframe(transcoder, &frame, DIP_AVI);
|
|
val = INREG(reg);
|
|
|
|
printf("AVI InfoFrame:\n");
|
|
|
|
if (gen == 4) {
|
|
printf("- %sbeing transmitted\n",
|
|
val & DIP_CTL_BUFFER_TRANS_ACTIVE_GEN4 ? "" : "not ");
|
|
}
|
|
|
|
freq = (val & DIP_CTL_FREQUENCY) >> 16;
|
|
printf("- frequency: %s\n", dip_frequency_names[freq]);
|
|
|
|
dump_raw_infoframe(&frame);
|
|
|
|
printf("- type: %x, version: %x, length: %x, ecc: %x, checksum: %x\n",
|
|
frame.avi.header.type, frame.avi.header.version,
|
|
frame.avi.header.length, frame.avi.header.ecc,
|
|
frame.avi.checksum);
|
|
printf("- S: %x, B: %x, A: %x, Y: %x, Rsvd0: %x\n",
|
|
frame.avi.S, frame.avi.B, frame.avi.A, frame.avi.Y,
|
|
frame.avi.Rsvd0);
|
|
printf("- R: %x, M: %x, C: %x\n",
|
|
frame.avi.R, frame.avi.M, frame.avi.C);
|
|
printf("- SC: %x, Q: %x, EC: %x, ITC: %x\n",
|
|
frame.avi.SC, frame.avi.Q, frame.avi.EC, frame.avi.ITC);
|
|
printf("- VIC: %d, Rsvd1: %x\n", frame.avi.VIC, frame.avi.Rsvd1);
|
|
printf("- PR: %x, Rsvd2: %x\n", frame.avi.PR, frame.avi.Rsvd2);
|
|
printf("- top: %x, bottom: %x, left: %x, right: %x\n",
|
|
frame.avi.top, frame.avi.bottom, frame.avi.left,
|
|
frame.avi.right);
|
|
printf("- Rsvd3: %x, Rsvd4[0]: %x, Rsvd4[1]: %x, Rsvd4[2]: %x\n",
|
|
frame.avi.Rsvd3, frame.avi.Rsvd4[0], frame.avi.Rsvd4[1],
|
|
frame.avi.Rsvd4[2]);
|
|
|
|
if (!infoframe_valid_checksum(&frame))
|
|
printf("Invalid InfoFrame checksum!\n");
|
|
}
|
|
|
|
static const char *vendor_id_to_string(uint32_t id)
|
|
{
|
|
switch (id) {
|
|
case VENDOR_ID_HDMI:
|
|
return "HDMI";
|
|
default:
|
|
return "Unknown";
|
|
}
|
|
}
|
|
|
|
static const char *s3d_structure_to_string(int format)
|
|
{
|
|
switch (format) {
|
|
case 0:
|
|
return "Frame Packing";
|
|
case 6:
|
|
return "Top Bottom";
|
|
case 8:
|
|
return "Side By Side (half)";
|
|
default:
|
|
return "Reserved";
|
|
}
|
|
}
|
|
|
|
static void dump_vendor_hdmi(DipInfoFrame *frame)
|
|
{
|
|
int vic_present = frame->vendor.video_format & 0x1;
|
|
int s3d_present = frame->vendor.video_format & 0x2;
|
|
|
|
printf("- video format: 0x%03x %s\n", frame->vendor.video_format,
|
|
s3d_present ? "(3D)" : "");
|
|
|
|
if (vic_present && s3d_present) {
|
|
printf("Error: HDMI VIC and S3D bits set. Only one of those "
|
|
" at a time is valid\n");
|
|
return;
|
|
}
|
|
|
|
if (vic_present)
|
|
printf("- HDMI VIC: %d\n", frame->vendor.pb5.vic);
|
|
else if (s3d_present) {
|
|
int s3d_structure = frame->vendor.pb5.s3d.s3d_structure;
|
|
|
|
printf("- 3D Format: %s\n",
|
|
s3d_structure_to_string(s3d_structure));
|
|
|
|
/* Side-by-side (half) */
|
|
if (s3d_structure >= 8)
|
|
printf("- 3D Ext Data 0x%x\n",
|
|
frame->vendor.s3d_ext_data);
|
|
}
|
|
}
|
|
|
|
static void dump_vendor_info(Transcoder transcoder)
|
|
{
|
|
Register reg = get_dip_ctl_reg(transcoder);
|
|
uint32_t val, vendor_id;
|
|
DipFrequency freq;
|
|
DipInfoFrame frame;
|
|
|
|
load_infoframe(transcoder, &frame, DIP_VENDOR);
|
|
val = INREG(reg);
|
|
|
|
printf("Vendor InfoFrame:\n");
|
|
|
|
if (gen == 4) {
|
|
printf("- %sbeing transmitted\n",
|
|
val & DIP_CTL_BUFFER_TRANS_ACTIVE_GEN4 ? "" : "not ");
|
|
}
|
|
|
|
freq = (val & DIP_CTL_FREQUENCY) >> 16;
|
|
printf("- frequency: %s\n", dip_frequency_names[freq]);
|
|
|
|
dump_raw_infoframe(&frame);
|
|
|
|
vendor_id = frame.vendor.id[2] << 16 | frame.vendor.id[1] << 8 |
|
|
frame.vendor.id[0];
|
|
|
|
printf("- vendor Id: 0x%06x (%s)\n", vendor_id,
|
|
vendor_id_to_string(vendor_id));
|
|
|
|
if (vendor_id == VENDOR_ID_HDMI)
|
|
dump_vendor_hdmi(&frame);
|
|
|
|
if (!infoframe_valid_checksum(&frame))
|
|
printf("Invalid InfoFrame checksum!\n");
|
|
}
|
|
|
|
static void dump_gamut_info(Transcoder transcoder)
|
|
{
|
|
Register reg = get_dip_ctl_reg(transcoder);
|
|
uint32_t val;
|
|
DipFrequency freq;
|
|
DipInfoFrame frame;
|
|
|
|
load_infoframe(transcoder, &frame, DIP_GAMUT);
|
|
val = INREG(reg);
|
|
|
|
printf("Gamut InfoFrame:\n");
|
|
|
|
if (gen == 4) {
|
|
printf("- %sbeing transmitted\n",
|
|
val & DIP_CTL_BUFFER_TRANS_ACTIVE_GEN4 ? "" : "not ");
|
|
}
|
|
|
|
freq = (val & DIP_CTL_FREQUENCY) >> 16;
|
|
printf("- frequency: %s\n", dip_frequency_names[freq]);
|
|
|
|
dump_raw_infoframe(&frame);
|
|
|
|
if (!infoframe_valid_checksum(&frame))
|
|
printf("Invalid InfoFrame checksum!\n");
|
|
}
|
|
|
|
static void dump_spd_info(Transcoder transcoder)
|
|
{
|
|
Register reg = get_dip_ctl_reg(transcoder);
|
|
uint32_t val;
|
|
DipFrequency freq;
|
|
DipInfoFrame frame;
|
|
char vendor[9];
|
|
char description[17];
|
|
|
|
load_infoframe(transcoder, &frame, DIP_SPD);
|
|
val = INREG(reg);
|
|
|
|
printf("SPD InfoFrame:\n");
|
|
|
|
if (gen == 4) {
|
|
printf("- %sbeing transmitted\n",
|
|
val & DIP_CTL_BUFFER_TRANS_ACTIVE_GEN4 ? "" : "not ");
|
|
}
|
|
|
|
freq = (val & DIP_CTL_FREQUENCY) >> 16;
|
|
printf("- frequency: %s\n", dip_frequency_names[freq]);
|
|
|
|
dump_raw_infoframe(&frame);
|
|
|
|
printf("- type: %x, version: %x, length: %x, ecc: %x, checksum: %x\n",
|
|
frame.spd.header.type, frame.spd.header.version,
|
|
frame.spd.header.length, frame.spd.header.ecc,
|
|
frame.spd.checksum);
|
|
|
|
memcpy(vendor, frame.spd.vendor, 8);
|
|
vendor[8] = '\0';
|
|
memcpy(description, frame.spd.description, 16);
|
|
description[16] = '\0';
|
|
|
|
printf("- vendor: %s\n", vendor);
|
|
printf("- description: %s\n", description);
|
|
printf("- source: %s\n", spd_source_to_string(frame.spd.source));
|
|
|
|
if (!infoframe_valid_checksum(&frame))
|
|
printf("Invalid InfoFrame checksum!\n");
|
|
}
|
|
|
|
static void dump_transcoder_info(Transcoder transcoder)
|
|
{
|
|
Register reg = get_dip_ctl_reg(transcoder);
|
|
uint32_t val = INREG(reg);
|
|
|
|
if (gen == 4) {
|
|
printf("\nDIP information:\n");
|
|
switch (val & DIP_CTL_PORT_SEL_MASK_GEN4) {
|
|
case DIP_CTL_PORT_SEL_B_GEN4:
|
|
printf("- port B\n");
|
|
break;
|
|
case DIP_CTL_PORT_SEL_C_GEN4:
|
|
printf("- port C\n");
|
|
break;
|
|
default:
|
|
printf("- INVALID port!\n");
|
|
}
|
|
} else {
|
|
printf("\nTranscoder %s:\n", transcoder_names[transcoder]);
|
|
}
|
|
printf("- %s\n", val & DIP_CTL_ENABLE ? "enabled" : "disabled");
|
|
if (!(val & DIP_CTL_ENABLE))
|
|
return;
|
|
|
|
printf("- GCP: %s\n", val & DIP_CTL_GCP_ENABLE ?
|
|
"enabled" : "disabled");
|
|
|
|
if (val & DIP_CTL_AVI_ENABLE)
|
|
dump_avi_info(transcoder);
|
|
if (val & DIP_CTL_VENDOR_ENABLE)
|
|
dump_vendor_info(transcoder);
|
|
if (val & DIP_CTL_GAMUT_ENABLE)
|
|
dump_gamut_info(transcoder);
|
|
if (val & DIP_CTL_SPD_ENABLE)
|
|
dump_spd_info(transcoder);
|
|
}
|
|
|
|
static void dump_all_info(void)
|
|
{
|
|
unsigned int i;
|
|
|
|
if (IS_VALLEYVIEW(pci_dev->device_id)) {
|
|
for (i = 0; i < ARRAY_SIZE(vlv_hdmi_ports); i++)
|
|
dump_port_info(i);
|
|
for (i = 0; i < ARRAY_SIZE(vlv_dip_ctl_regs); i++)
|
|
dump_transcoder_info(i);
|
|
} else if (gen == 4) {
|
|
for (i = 0; i < ARRAY_SIZE(gen4_hdmi_ports); i++)
|
|
dump_port_info(i);
|
|
dump_transcoder_info(0);
|
|
} else {
|
|
for (i = 0; i < ARRAY_SIZE(pch_hdmi_ports); i++)
|
|
dump_port_info(i);
|
|
for (i = 0; i < ARRAY_SIZE(pch_dip_ctl_regs); i++)
|
|
dump_transcoder_info(i);
|
|
}
|
|
}
|
|
|
|
static void write_infoframe(Transcoder transcoder, DipType type,
|
|
DipInfoFrame *frame)
|
|
{
|
|
Register ctl_reg = get_dip_ctl_reg(transcoder);
|
|
Register data_reg = get_dip_data_reg(transcoder);
|
|
uint32_t ctl_val;
|
|
unsigned int i;
|
|
|
|
ctl_val = INREG(ctl_reg);
|
|
ctl_val &= ~DIP_CTL_BUFFER_INDEX;
|
|
ctl_val |= (type << 19);
|
|
ctl_val &= ~DIP_CTL_ACCESS_ADDR;
|
|
OUTREG(ctl_reg, ctl_val);
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
ctl_val = INREG(ctl_reg);
|
|
assert((ctl_val & DIP_CTL_ACCESS_ADDR) == i);
|
|
OUTREG(data_reg, frame->data32[i]);
|
|
}
|
|
}
|
|
|
|
static void disable_infoframe(Transcoder transcoder, DipType type)
|
|
{
|
|
Register reg = get_dip_ctl_reg(transcoder);
|
|
uint32_t val = INREG(reg);
|
|
if (gen != 4 && type == DIP_AVI)
|
|
val &= ~DIP_CTL_ENABLE;
|
|
val &= ~(1 << (21 + type));
|
|
OUTREG(reg, val);
|
|
}
|
|
|
|
static void enable_infoframe(Transcoder transcoder, DipType type)
|
|
{
|
|
Register reg = get_dip_ctl_reg(transcoder);
|
|
uint32_t val = INREG(reg);
|
|
if (gen != 4 && type == DIP_AVI)
|
|
val |= DIP_CTL_ENABLE;
|
|
val |= (1 << (21 + type));
|
|
OUTREG(reg, val);
|
|
}
|
|
|
|
static int parse_infoframe_option_u(const char *name, const char *s,
|
|
uint32_t min, uint32_t max,
|
|
uint32_t *value, char **commands)
|
|
{
|
|
int read, rc;
|
|
if (!strcmp(name, s)) {
|
|
rc = sscanf(*commands, "%x%n", value, &read);
|
|
*commands = &(*commands)[read];
|
|
if (rc != 1) {
|
|
printf("Invalid value.\n");
|
|
return 0;
|
|
}
|
|
|
|
if (*value < min || *value > max) {
|
|
printf("Value outside allowed range.\n");
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int parse_infoframe_option_s(const char *name, const char *s,
|
|
int min_size, int max_size,
|
|
char *value, char **commands)
|
|
{
|
|
int size, read, rc;
|
|
if (!strcmp(name, s)) {
|
|
rc = sscanf(*commands, "%31s%n", value, &read);
|
|
*commands = &(*commands)[read];
|
|
if (rc != 1) {
|
|
printf("Invalid value.\n");
|
|
return 0;
|
|
}
|
|
|
|
size = strlen(value);
|
|
if (size < min_size || size > max_size) {
|
|
printf("String either too big or too small.\n");
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void change_avi_infoframe(Transcoder transcoder, char *commands)
|
|
{
|
|
Register reg = get_dip_ctl_reg(transcoder);
|
|
uint32_t val;
|
|
DipInfoFrame frame;
|
|
char option[32];
|
|
uint32_t option_val;
|
|
int rc, read;
|
|
char *current = commands;
|
|
|
|
load_infoframe(transcoder, &frame, DIP_AVI);
|
|
val = INREG(reg);
|
|
|
|
while (1) {
|
|
rc = sscanf(current, "%31s%n", option, &read);
|
|
current = ¤t[read];
|
|
if (rc == EOF) {
|
|
break;
|
|
} else if (rc != 1) {
|
|
printf("Invalid option: %s\n", option);
|
|
continue;
|
|
}
|
|
|
|
if (parse_infoframe_option_u("S", option, 0, 2, &option_val,
|
|
¤t))
|
|
frame.avi.S = option_val;
|
|
else if (parse_infoframe_option_u("B", option, 0, 3,
|
|
&option_val, ¤t))
|
|
frame.avi.B = option_val;
|
|
else if (parse_infoframe_option_u("A", option, 0, 1,
|
|
&option_val, ¤t))
|
|
frame.avi.A = option_val;
|
|
else if (parse_infoframe_option_u("Y", option, 0, 2,
|
|
&option_val, ¤t))
|
|
frame.avi.Y = option_val;
|
|
else if (parse_infoframe_option_u("R", option, 0, 15,
|
|
&option_val, ¤t))
|
|
frame.avi.R = option_val;
|
|
else if (parse_infoframe_option_u("M", option, 0, 2,
|
|
&option_val, ¤t))
|
|
frame.avi.M = option_val;
|
|
else if (parse_infoframe_option_u("C", option, 0, 3,
|
|
&option_val, ¤t))
|
|
frame.avi.C = option_val;
|
|
else if (parse_infoframe_option_u("SC", option, 0, 3,
|
|
&option_val, ¤t))
|
|
frame.avi.SC = option_val;
|
|
else if (parse_infoframe_option_u("Q", option, 0, 2,
|
|
&option_val, ¤t))
|
|
frame.avi.Q = option_val;
|
|
else if (parse_infoframe_option_u("EC", option, 0, 1,
|
|
&option_val,¤t))
|
|
frame.avi.EC = option_val;
|
|
else if (parse_infoframe_option_u("ITC", option, 0, 1,
|
|
&option_val, ¤t))
|
|
frame.avi.ITC = option_val;
|
|
else if (parse_infoframe_option_u("VIC", option, 0, 127,
|
|
&option_val, ¤t))
|
|
frame.avi.VIC = option_val;
|
|
else if (parse_infoframe_option_u("PR", option, 0, 15,
|
|
&option_val, ¤t))
|
|
frame.avi.PR = option_val;
|
|
else if (parse_infoframe_option_u("top", option, 0, 65535,
|
|
&option_val, ¤t))
|
|
frame.avi.top = option_val;
|
|
else if (parse_infoframe_option_u("bottom", option, 0, 65535,
|
|
&option_val, ¤t))
|
|
frame.avi.bottom = option_val;
|
|
else if (parse_infoframe_option_u("left", option, 0, 65535,
|
|
&option_val, ¤t))
|
|
frame.avi.left = option_val;
|
|
else if (parse_infoframe_option_u("right", option, 0, 65535,
|
|
&option_val, ¤t))
|
|
frame.avi.right = option_val;
|
|
else
|
|
printf("Unrecognized option: %s\n", option);
|
|
}
|
|
|
|
val &= ~DIP_CTL_FREQUENCY;
|
|
val |= DIP_CTL_FREQ_EVERY;
|
|
OUTREG(reg, val);
|
|
|
|
frame.avi.header.type = AVI_INFOFRAME_TYPE;
|
|
frame.avi.header.version = AVI_INFOFRAME_VERSION;
|
|
frame.avi.header.length = AVI_INFOFRAME_LENGTH;
|
|
frame.avi.Rsvd0 = 0;
|
|
frame.avi.Rsvd1 = 0;
|
|
frame.avi.Rsvd2 = 0;
|
|
frame.avi.Rsvd3 = 0;
|
|
frame.avi.Rsvd4[0] = 0;
|
|
frame.avi.Rsvd4[1] = 0;
|
|
frame.avi.Rsvd4[2] = 0;
|
|
|
|
infoframe_fix_checksum(&frame);
|
|
|
|
disable_infoframe(transcoder, DIP_AVI);
|
|
write_infoframe(transcoder, DIP_AVI, &frame);
|
|
enable_infoframe(transcoder, DIP_AVI);
|
|
}
|
|
|
|
static void change_spd_infoframe(Transcoder transcoder, char *commands)
|
|
{
|
|
Register reg = get_dip_ctl_reg(transcoder);
|
|
uint32_t val;
|
|
DipInfoFrame frame;
|
|
char option[16];
|
|
char option_val_s[32];
|
|
uint32_t option_val_i;
|
|
int rc, read;
|
|
char *current = commands;
|
|
|
|
load_infoframe(transcoder, &frame, DIP_SPD);
|
|
val = INREG(reg);
|
|
|
|
while (1) {
|
|
rc = sscanf(current, "%15s%n", option, &read);
|
|
current = ¤t[read];
|
|
if (rc == EOF) {
|
|
break;
|
|
} else if (rc != 1) {
|
|
printf("Invalid option: %s\n", option);
|
|
continue;
|
|
}
|
|
|
|
memset(option_val_s, 0, 32);
|
|
|
|
if (parse_infoframe_option_s("vendor", option, 0, 8,
|
|
option_val_s, ¤t))
|
|
memcpy(frame.spd.vendor, option_val_s, 8);
|
|
else if (parse_infoframe_option_s("description", option, 0, 16,
|
|
option_val_s, ¤t))
|
|
memcpy(frame.spd.description, option_val_s, 16);
|
|
else if (parse_infoframe_option_u("source", option, 0, 0x0c,
|
|
&option_val_i, ¤t))
|
|
frame.spd.source = option_val_i;
|
|
else
|
|
printf("Unrecognized option: %s\n", option);
|
|
}
|
|
|
|
val &= ~DIP_CTL_FREQUENCY;
|
|
val |= DIP_CTL_FREQ_EVERY_OTHER;
|
|
OUTREG(reg, val);
|
|
|
|
frame.spd.header.type = SPD_INFOFRAME_TYPE;
|
|
frame.spd.header.version = SPD_INFOFRAME_VERSION;
|
|
frame.spd.header.length = SPD_INFOFRAME_LENGTH;
|
|
|
|
infoframe_fix_checksum(&frame);
|
|
|
|
disable_infoframe(transcoder, DIP_SPD);
|
|
write_infoframe(transcoder, DIP_SPD, &frame);
|
|
enable_infoframe(transcoder, DIP_SPD);
|
|
}
|
|
|
|
static void change_infoframe_checksum(Transcoder transcoder, DipType type,
|
|
uint32_t selected_csum)
|
|
{
|
|
DipInfoFrame frame;
|
|
|
|
load_infoframe(transcoder, &frame, type);
|
|
frame.generic.body[0] = selected_csum;
|
|
disable_infoframe(transcoder, type);
|
|
write_infoframe(transcoder, type, &frame);
|
|
enable_infoframe(transcoder, type);
|
|
}
|
|
|
|
static void change_infoframe_frequency(Transcoder transcoder, DipType type,
|
|
DipFrequency frequency)
|
|
{
|
|
Register reg = get_dip_ctl_reg(transcoder);
|
|
uint32_t val = INREG(reg);
|
|
|
|
if (type == DIP_AVI && frequency != DIP_FREQ_EVERY_VSYNC) {
|
|
printf("Error: AVI infoframe must be sent every VSync!\n");
|
|
frequency = DIP_FREQ_EVERY_VSYNC;
|
|
}
|
|
|
|
val &= ~DIP_CTL_FREQUENCY;
|
|
val |= (frequency << 16);
|
|
OUTREG(reg, val);
|
|
}
|
|
|
|
static void disable_dip(Transcoder transcoder)
|
|
{
|
|
Register reg = get_dip_ctl_reg(transcoder);
|
|
uint32_t val = INREG(reg);
|
|
val &= ~DIP_CTL_ENABLE;
|
|
OUTREG(reg, val);
|
|
}
|
|
|
|
static void enable_dip(Transcoder transcoder)
|
|
{
|
|
Register reg = get_dip_ctl_reg(transcoder);
|
|
uint32_t val = INREG(reg);
|
|
val |= DIP_CTL_ENABLE;
|
|
OUTREG(reg, val);
|
|
}
|
|
|
|
static void disable_hdmi_port(Register reg)
|
|
{
|
|
uint32_t val = INREG(reg);
|
|
val &= ~HDMI_PORT_ENABLE;
|
|
OUTREG(reg, val);
|
|
}
|
|
|
|
static void enable_hdmi_port(Register reg)
|
|
{
|
|
uint32_t val = INREG(reg);
|
|
val |= HDMI_PORT_ENABLE;
|
|
OUTREG(reg, val);
|
|
}
|
|
|
|
static void print_usage(void)
|
|
{
|
|
printf("Options:\n"
|
|
" -d, --dump\n"
|
|
" dump information about all transcoders\n"
|
|
" -c, --change-fields [fields]\n"
|
|
" change infoframe fields from selected transcoder\n"
|
|
" -k, --change-checksum [checksum]\n"
|
|
" change infoframe checksum (value in hex)\n"
|
|
" -q, --change-frequency [frequency]\n"
|
|
" change infoframe frequency (once, everyvsync or everyothervsync)\n"
|
|
" -n, --disable\n"
|
|
" disable the selected infoframe from the selected transcoder\n"
|
|
" -N, --enable\n"
|
|
" enable the selected infoframe from the selected transcoder\n"
|
|
" -x, --disable-infoframes\n"
|
|
" disable all infoframes from selected transcoder\n"
|
|
" -X, --enable-infoframes\n"
|
|
" enable sending infoframes on the selected transcoder\n"
|
|
" -p, --disable-hdmi-port [port]\n"
|
|
" disable hdmi port on the selected transcoder (B, C or D)\n"
|
|
" -P, --enable-hdmi-port [port]\n"
|
|
" enable hdmi port on the selected transcoder (B, C or D)\n"
|
|
" -t, --transcoder\n"
|
|
" select transcoder (A, B or C)\n"
|
|
" -f, --infoframe\n"
|
|
" select infoframe (AVI, Vendor, Gamut or SPD)\n"
|
|
" -h, --help\n"
|
|
" prints this message\n"
|
|
"\n"
|
|
"Examples:\n"
|
|
"\n"
|
|
" Dump information:\n"
|
|
" intel_infoframes\n"
|
|
"\n"
|
|
" Disable overscan and set ITC on transcoder B:\n"
|
|
" intel_infoframes -t B -f AVI -c 'S 2 ITC 1'\n"
|
|
"\n"
|
|
" Many actions on the same command:\n"
|
|
" - enable overscan on transcoder A\n"
|
|
" - enable overscan and change description on transcoder B\n"
|
|
" - disable all infoframes on transcoder C\n"
|
|
" - dump the resulting state:\n"
|
|
" intel_infoframes -t A -f AVI -c 'S 1' \\\n"
|
|
" -t B -f AVI -c 'S 2' \\\n"
|
|
" -f SPD -c 'description Linux' \\\n"
|
|
" -t C --disable-infoframes \\\n"
|
|
" -d\n"
|
|
"\n"
|
|
" Even more:\n"
|
|
" - print the help message\n"
|
|
" - completely disable all infoframes on all transcoders\n"
|
|
" - dump the state"
|
|
" - enable sending infoframes on transcoder B, but disable all infoframes\n"
|
|
" - enable AVI infoframes transcoder B, use underscan and declare ITC\n"
|
|
" - also enable SPD infoframes on the same transcoder, change frequency to\n"
|
|
" every vsync and change vendor, description and source\n"
|
|
" - dump the state again\n"
|
|
" intel_infoframes -h \\\n"
|
|
" -t A -x -t B -x -t C -x \\\n"
|
|
" -d \\\n"
|
|
" -t A -X -f AVI -n -f Vendor -n \\\n"
|
|
" -f Gamut -n -f SPD -n \\\n"
|
|
" -f AVI -N -c 'S 2 ITC 1'\\\n"
|
|
" -f SPD -q everyvsync \\\n"
|
|
" -c 'vendor me description mine source 0x09' \\\n"
|
|
" -d\n"
|
|
"\n"
|
|
"Infoframe fields used by the --change-fields option:\n"
|
|
" - AVI infoframe fields:\n"
|
|
" S B A Y R M C SC Q EC ITC VIC PR top bottom left right\n"
|
|
" - SPD infoframe fields:\n"
|
|
" vendor description source\n"
|
|
" - Other infoframe fields are not implemented yet.\n");
|
|
}
|
|
|
|
#define CHECK_TRANSCODER(transcoder) \
|
|
if (transcoder == TRANSC_INVALID) { \
|
|
printf("Transcoder not selected.\n"); \
|
|
ret = 1; \
|
|
goto out; \
|
|
}
|
|
|
|
#define CHECK_DIP(dip) \
|
|
if (dip == DIP_INVALID) { \
|
|
printf("Infoframe not selected.\n"); \
|
|
ret = 1; \
|
|
goto out; \
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
int opt;
|
|
int ret = 0;
|
|
Transcoder transcoder = TRANSC_INVALID;
|
|
DipType dip = DIP_INVALID;
|
|
Register hdmi_port;
|
|
|
|
char short_opts[] = "dc:k:q:nNxXp:P:t:f:h";
|
|
struct option long_opts[] = {
|
|
{ "dump", no_argument, NULL, 'd' },
|
|
{ "change-fields", required_argument, NULL, 'c' },
|
|
{ "change-checksum", required_argument, NULL, 'k' },
|
|
{ "change-frequency", required_argument, NULL, 'q' },
|
|
{ "disable", no_argument, NULL, 'n' },
|
|
{ "enable", no_argument, NULL, 'N' },
|
|
{ "disable-infoframes", no_argument, NULL, 'x' },
|
|
{ "enable-infoframes", no_argument, NULL, 'X' },
|
|
{ "disable-hdmi-port", required_argument, NULL, 'p' },
|
|
{ "enable-hdmi-port", required_argument, NULL, 'P' },
|
|
{ "transcoder" , required_argument, NULL, 't' },
|
|
{ "infoframe", required_argument, NULL, 'f' },
|
|
{ "help", no_argument, NULL, 'h' },
|
|
{ 0 }
|
|
};
|
|
|
|
printf("WARNING: This is just a debugging tool! Don't expect it to work"
|
|
" perfectly: the Kernel might undo our changes.\n");
|
|
|
|
pci_dev = intel_get_pci_device();
|
|
intel_register_access_init(pci_dev, 0, -1);
|
|
intel_check_pch();
|
|
|
|
if (IS_GEN4(pci_dev->device_id))
|
|
gen = 4;
|
|
else if (IS_GEN5(pci_dev->device_id))
|
|
gen = 5;
|
|
else if (IS_GEN6(pci_dev->device_id))
|
|
gen = 6;
|
|
else if (IS_GEN7(pci_dev->device_id))
|
|
gen = 7;
|
|
else {
|
|
printf("This program does not support your hardware yet.\n");
|
|
ret = 1;
|
|
goto out;
|
|
}
|
|
|
|
while (1) {
|
|
opt = getopt_long(argc, argv, short_opts, long_opts, NULL);
|
|
if (opt == -1)
|
|
break;
|
|
|
|
switch (opt) {
|
|
case 'd':
|
|
dump_all_info();
|
|
break;
|
|
case 'c':
|
|
if (transcoder == TRANSC_INVALID) {
|
|
printf("Transcoder not selected.\n");
|
|
ret = 1;
|
|
goto out;
|
|
}
|
|
switch (dip) {
|
|
case DIP_AVI:
|
|
change_avi_infoframe(transcoder, optarg);
|
|
break;
|
|
case DIP_VENDOR:
|
|
case DIP_GAMUT:
|
|
printf("Option not implemented yet.\n");
|
|
ret = 1;
|
|
goto out;
|
|
case DIP_SPD:
|
|
change_spd_infoframe(transcoder, optarg);
|
|
break;
|
|
case DIP_INVALID:
|
|
printf("Infoframe not selected.\n");
|
|
ret = 1;
|
|
goto out;
|
|
}
|
|
break;
|
|
case 'k':
|
|
CHECK_TRANSCODER(transcoder);
|
|
CHECK_DIP(dip);
|
|
change_infoframe_checksum(transcoder, dip, atoi(optarg));
|
|
break;
|
|
case 'q':
|
|
CHECK_TRANSCODER(transcoder);
|
|
CHECK_DIP(dip);
|
|
if (!strcmp(optarg, "once"))
|
|
change_infoframe_frequency(transcoder, dip,
|
|
DIP_FREQ_ONCE);
|
|
else if (!strcmp(optarg, "everyvsync"))
|
|
change_infoframe_frequency(transcoder, dip,
|
|
DIP_FREQ_EVERY_VSYNC);
|
|
else if (!strcmp(optarg, "everyothervsync"))
|
|
change_infoframe_frequency(transcoder, dip,
|
|
DIP_FREQ_EVERY_OTHER_VSYNC);
|
|
else {
|
|
printf("Invalid frequency.\n");
|
|
ret = 1;
|
|
goto out;
|
|
}
|
|
break;
|
|
case 'n':
|
|
CHECK_TRANSCODER(transcoder);
|
|
CHECK_DIP(dip);
|
|
disable_infoframe(transcoder, dip);
|
|
break;
|
|
case 'N':
|
|
CHECK_TRANSCODER(transcoder);
|
|
CHECK_DIP(dip);
|
|
enable_infoframe(transcoder, dip);
|
|
break;
|
|
case 'x':
|
|
CHECK_TRANSCODER(transcoder);
|
|
disable_dip(transcoder);
|
|
break;
|
|
case 'X':
|
|
CHECK_TRANSCODER(transcoder);
|
|
enable_dip(transcoder);
|
|
break;
|
|
case 'p':
|
|
case 'P':
|
|
if (!strcmp(optarg, "B"))
|
|
hdmi_port = get_hdmi_port(0);
|
|
else if (!strcmp(optarg, "C"))
|
|
hdmi_port = get_hdmi_port(1);
|
|
else if (!strcmp(optarg, "D"))
|
|
hdmi_port = get_hdmi_port(2);
|
|
else {
|
|
printf("Invalid HDMI port.\n");
|
|
ret = 1;
|
|
goto out;
|
|
}
|
|
if (opt == 'p')
|
|
disable_hdmi_port(hdmi_port);
|
|
else
|
|
enable_hdmi_port(hdmi_port);
|
|
break;
|
|
case 't':
|
|
if (!strcmp(optarg, "A"))
|
|
transcoder = TRANSC_A;
|
|
else if (!strcmp(optarg, "B"))
|
|
transcoder = TRANSC_B;
|
|
else if (intel_pch >= PCH_CPT && !strcmp(optarg, "C")) {
|
|
transcoder = TRANSC_C;
|
|
} else {
|
|
printf("Invalid transcoder.\n");
|
|
ret = 1;
|
|
goto out;
|
|
}
|
|
break;
|
|
case 'f':
|
|
if (!strcmp(optarg, "AVI"))
|
|
dip = DIP_AVI;
|
|
else if (!strcmp(optarg, "Vendor"))
|
|
dip = DIP_VENDOR;
|
|
else if (!strcmp(optarg, "Gamut"))
|
|
dip = DIP_GAMUT;
|
|
else if (!strcmp(optarg, "SPD"))
|
|
dip = DIP_SPD;
|
|
else {
|
|
printf("Invalid infoframe.\n");
|
|
ret = 1;
|
|
goto out;
|
|
}
|
|
break;
|
|
case 'h':
|
|
print_usage();
|
|
break;
|
|
default:
|
|
print_usage();
|
|
ret = 1;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
out:
|
|
intel_register_access_fini();
|
|
return ret;
|
|
}
|