summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/.gitignore24
-rw-r--r--tools/Makefile.am42
-rw-r--r--tools/intel_audio_dump.c1969
-rw-r--r--tools/intel_backlight.c69
-rw-r--r--tools/intel_bios.h731
-rw-r--r--tools/intel_bios_dumper.c112
-rw-r--r--tools/intel_bios_reader.c947
-rw-r--r--tools/intel_disable_clock_gating.c71
-rw-r--r--tools/intel_dpio_read.c68
-rw-r--r--tools/intel_dpio_write.c67
-rw-r--r--tools/intel_dump_decode.c211
-rw-r--r--tools/intel_error_decode.c515
-rw-r--r--tools/intel_forcewaked.c106
-rwxr-xr-xtools/intel_gpu_abrt45
-rw-r--r--tools/intel_gpu_time.c110
-rw-r--r--tools/intel_gpu_top.c716
-rw-r--r--tools/intel_gtt.c134
-rw-r--r--tools/intel_infoframes.c1142
-rw-r--r--tools/intel_l3_parity.c159
-rw-r--r--tools/intel_lid.c144
-rw-r--r--tools/intel_panel_fitter.c344
-rw-r--r--tools/intel_reg_checker.c399
-rw-r--r--tools/intel_reg_dumper.c2246
-rw-r--r--tools/intel_reg_read.c142
-rw-r--r--tools/intel_reg_snapshot.c48
-rw-r--r--tools/intel_reg_write.c58
-rw-r--r--tools/intel_stepping.c294
27 files changed, 10913 insertions, 0 deletions
diff --git a/tools/.gitignore b/tools/.gitignore
new file mode 100644
index 00000000..c15e3c36
--- /dev/null
+++ b/tools/.gitignore
@@ -0,0 +1,24 @@
+forcewaked
+intel_audio_dump
+intel_backlight
+intel_bios_dumper
+intel_bios_reader
+intel_disable_clock_gating
+intel_dump_decode
+intel_error_decode
+intel_forcewaked
+intel_gpu_dump
+intel_gpu_time
+intel_gpu_top
+intel_gtt
+intel_infoframes
+intel_l3_parity
+intel_lid
+intel_panel_fitter
+intel_reg_checker
+intel_reg_dumper
+intel_reg_read
+intel_reg_snapshot
+intel_reg_write
+intel_stepping
+# Please keep sorted alphabetically
diff --git a/tools/Makefile.am b/tools/Makefile.am
new file mode 100644
index 00000000..71fb087f
--- /dev/null
+++ b/tools/Makefile.am
@@ -0,0 +1,42 @@
+bin_PROGRAMS = \
+ intel_disable_clock_gating \
+ intel_audio_dump \
+ intel_backlight \
+ intel_bios_dumper \
+ intel_bios_reader \
+ intel_error_decode \
+ intel_gpu_top \
+ intel_gpu_time \
+ intel_gtt \
+ intel_stepping \
+ intel_reg_checker \
+ intel_reg_dumper \
+ intel_reg_snapshot \
+ intel_reg_write \
+ intel_reg_read \
+ intel_forcewaked \
+ intel_dpio_read \
+ intel_dpio_write \
+ intel_l3_parity
+
+noinst_PROGRAMS = \
+ intel_dump_decode \
+ intel_infoframes \
+ intel_lid \
+ intel_panel_fitter
+
+dist_bin_SCRIPTS = intel_gpu_abrt
+
+AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/lib
+AM_CFLAGS = $(DRM_CFLAGS) $(PCIACCESS_CFLAGS) $(CWARNFLAGS) $(CAIRO_CFLAGS)
+LDADD = $(top_builddir)/lib/libintel_tools.la $(DRM_LIBS) $(PCIACCESS_LIBS) $(CAIRO_LIBS)
+
+intel_dump_decode_SOURCES = \
+ intel_dump_decode.c
+
+intel_error_decode_SOURCES = \
+ intel_error_decode.c
+
+intel_bios_reader_SOURCES = \
+ intel_bios_reader.c \
+ intel_bios.h
diff --git a/tools/intel_audio_dump.c b/tools/intel_audio_dump.c
new file mode 100644
index 00000000..8b9da303
--- /dev/null
+++ b/tools/intel_audio_dump.c
@@ -0,0 +1,1969 @@
+/*
+ * Copyright © 2009 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:
+ * Zhenyu Wang <zhenyu.z.wang@intel.com>
+ * Wu Fengguang <fengguang.wu@intel.com>
+ *
+ */
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <err.h>
+#include <arpa/inet.h>
+#include "intel_gpu_tools.h"
+
+static uint32_t devid;
+
+
+#define BITSTO(n) (n >= sizeof(long) * 8 ? ~0 : (1UL << (n)) - 1)
+#define BITMASK(high, low) (BITSTO(high+1) & ~BITSTO(low))
+#define BITS(reg, high, low) (((reg) & (BITMASK(high, low))) >> (low))
+#define BIT(reg, n) BITS(reg, n, n)
+
+#define min_t(type, x, y) ({ \
+ type __min1 = (x); \
+ type __min2 = (y); \
+ __min1 < __min2 ? __min1: __min2; })
+
+#define OPNAME(names, index) \
+ names[min_t(unsigned int, index, ARRAY_SIZE(names) - 1)]
+
+#define dump_reg(reg, desc) \
+ do { \
+ dword = INREG(reg); \
+ printf("%-21s 0x%08x %s\n", # reg, dword, desc); \
+ } while (0)
+
+
+static const char *pixel_clock[] = {
+ [0] = "25.2 / 1.001 MHz",
+ [1] = "25.2 MHz",
+ [2] = "27 MHz",
+ [3] = "27 * 1.001 MHz",
+ [4] = "54 MHz",
+ [5] = "54 * 1.001 MHz",
+ [6] = "74.25 / 1.001 MHz",
+ [7] = "74.25 MHz",
+ [8] = "148.5 / 1.001 MHz",
+ [9] = "148.5 MHz",
+ [10] = "Reserved",
+};
+
+static const char *power_state[] = {
+ [0] = "D0",
+ [1] = "D1",
+ [2] = "D2",
+ [3] = "D3",
+};
+
+static const char *stream_type[] = {
+ [0] = "default samples",
+ [1] = "one bit stream",
+ [2] = "DST stream",
+ [3] = "MLP stream",
+ [4] = "Reserved",
+};
+
+static const char *dip_port[] = {
+ [0] = "Reserved",
+ [1] = "Digital Port B",
+ [2] = "Digital Port C",
+ [3] = "Digital Port D",
+};
+
+static const char *dip_type[] = {
+ [0] = "Audio DIP Disabled",
+ [1] = "Audio DIP Enabled",
+};
+
+static const char *dip_index[] = {
+ [0] = "Audio DIP",
+ [1] = "ACP DIP",
+ [2] = "ISRC1 DIP",
+ [3] = "ISRC2 DIP",
+ [4] = "Reserved",
+};
+
+static const char *dip_trans[] = {
+ [0] = "disabled",
+ [1] = "reserved",
+ [2] = "send once",
+ [3] = "best effort",
+};
+
+static const char *video_dip_index[] = {
+ [0] = "AVI DIP",
+ [1] = "Vendor-specific DIP",
+ [2] = "Gamut Metadata DIP",
+ [3] = "Source Product Description DIP",
+};
+
+static const char *video_dip_trans[] = {
+ [0] = "send once",
+ [1] = "send every vsync",
+ [2] = "send at least every other vsync",
+ [3] = "reserved",
+};
+
+static const char *trans_to_port_sel[] = {
+ [0] = "no port",
+ [1] = "Digital Port B",
+ [2] = "Digital Port C",
+ [3] = "Digital Port D",
+ [4] = "reserved",
+ [5] = "reserved",
+ [6] = "reserved",
+ [7] = "reserved",
+};
+
+static const char *ddi_mode[] = {
+ [0] = "HDMI mode",
+ [1] = "DVI mode",
+ [2] = "DP SST mode",
+ [3] = "DP MST mode",
+ [4] = "DP FDI mode",
+ [5] = "reserved",
+ [6] = "reserved",
+ [7] = "reserved",
+};
+
+static const char *transcoder_select[] = {
+ [0] = "Transcoder A",
+ [1] = "Transcoder B",
+ [2] = "Transcoder C",
+ [3] = "reserved",
+};
+
+static const char *dp_port_width[] = {
+ [0] = "x1 mode",
+ [1] = "x2 mode",
+ [2] = "reserved",
+ [3] = "x4 mode",
+ [4] = "reserved",
+ [5] = "reserved",
+ [6] = "reserved",
+ [7] = "reserved",
+};
+
+static const char *bits_per_sample[] = {
+ [0] = "reserved",
+ [1] = "16 bits",
+ [2] = "24 bits",
+ [3] = "32 bits",
+ [4] = "20 bits",
+ [5] = "reserved",
+};
+
+static const char *sdvo_hdmi_encoding[] = {
+ [0] = "SDVO",
+ [1] = "reserved",
+ [2] = "TMDS",
+ [3] = "reserved",
+};
+
+static const char *n_index_value[] = {
+ [0] = "HDMI",
+ [1] = "DisplayPort",
+};
+
+static void do_self_tests(void)
+{
+ if (BIT(1, 0) != 1)
+ exit(1);
+ if (BIT(0x80000000, 31) != 1)
+ exit(2);
+ if (BITS(0xc0000000, 31, 30) != 3)
+ exit(3);
+}
+
+/*
+ * EagleLake registers
+ */
+#define AUD_CONFIG 0x62000
+#define AUD_DEBUG 0x62010
+#define AUD_VID_DID 0x62020
+#define AUD_RID 0x62024
+#define AUD_SUBN_CNT 0x62028
+#define AUD_FUNC_GRP 0x62040
+#define AUD_SUBN_CNT2 0x62044
+#define AUD_GRP_CAP 0x62048
+#define AUD_PWRST 0x6204c
+#define AUD_SUPPWR 0x62050
+#define AUD_SID 0x62054
+#define AUD_OUT_CWCAP 0x62070
+#define AUD_OUT_PCMSIZE 0x62074
+#define AUD_OUT_STR 0x62078
+#define AUD_OUT_DIG_CNVT 0x6207c
+#define AUD_OUT_CH_STR 0x62080
+#define AUD_OUT_STR_DESC 0x62084
+#define AUD_PINW_CAP 0x620a0
+#define AUD_PIN_CAP 0x620a4
+#define AUD_PINW_CONNLNG 0x620a8
+#define AUD_PINW_CONNLST 0x620ac
+#define AUD_PINW_CNTR 0x620b0
+#define AUD_PINW_UNSOLRESP 0x620b8
+#define AUD_CNTL_ST 0x620b4
+#define AUD_PINW_CONFIG 0x620bc
+#define AUD_HDMIW_STATUS 0x620d4
+#define AUD_HDMIW_HDMIEDID 0x6210c
+#define AUD_HDMIW_INFOFR 0x62118
+#define AUD_CONV_CHCNT 0x62120
+#define AUD_CTS_ENABLE 0x62128
+
+#define VIDEO_DIP_CTL 0x61170
+#define VIDEO_DIP_ENABLE (1<<31)
+#define VIDEO_DIP_ENABLE_AVI (1<<21)
+#define VIDEO_DIP_ENABLE_VENDOR (1<<22)
+#define VIDEO_DIP_ENABLE_SPD (1<<24)
+#define VIDEO_DIP_BUF_AVI (0<<19)
+#define VIDEO_DIP_BUF_VENDOR (1<<19)
+#define VIDEO_DIP_BUF_SPD (3<<19)
+#define VIDEO_DIP_TRANS_ONCE (0<<16)
+#define VIDEO_DIP_TRANS_1 (1<<16)
+#define VIDEO_DIP_TRANS_2 (2<<16)
+
+#define AUDIO_HOTPLUG_EN (1<<24)
+
+
+static void dump_eaglelake(void)
+{
+ uint32_t dword;
+ int i;
+
+ /* printf("%-18s %8s %s\n\n", "register name", "raw value", "description"); */
+
+ dump_reg(VIDEO_DIP_CTL, "Video DIP Control");
+ dump_reg(SDVOB, "Digital Display Port B Control Register");
+ dump_reg(SDVOC, "Digital Display Port C Control Register");
+ dump_reg(PORT_HOTPLUG_EN, "Hot Plug Detect Enable");
+
+ dump_reg(AUD_CONFIG, "Audio Configuration");
+ dump_reg(AUD_DEBUG, "Audio Debug");
+ dump_reg(AUD_VID_DID, "Audio Vendor ID / Device ID");
+ dump_reg(AUD_RID, "Audio Revision ID");
+ dump_reg(AUD_SUBN_CNT, "Audio Subordinate Node Count");
+ dump_reg(AUD_FUNC_GRP, "Audio Function Group Type");
+ dump_reg(AUD_SUBN_CNT2, "Audio Subordinate Node Count");
+ dump_reg(AUD_GRP_CAP, "Audio Function Group Capabilities");
+ dump_reg(AUD_PWRST, "Audio Power State");
+ dump_reg(AUD_SUPPWR, "Audio Supported Power States");
+ dump_reg(AUD_SID, "Audio Root Node Subsystem ID");
+ dump_reg(AUD_OUT_CWCAP, "Audio Output Converter Widget Capabilities");
+ dump_reg(AUD_OUT_PCMSIZE, "Audio PCM Size and Rates");
+ dump_reg(AUD_OUT_STR, "Audio Stream Formats");
+ dump_reg(AUD_OUT_DIG_CNVT, "Audio Digital Converter");
+ dump_reg(AUD_OUT_CH_STR, "Audio Channel ID and Stream ID");
+ dump_reg(AUD_OUT_STR_DESC, "Audio Stream Descriptor Format");
+ dump_reg(AUD_PINW_CAP, "Audio Pin Complex Widget Capabilities");
+ dump_reg(AUD_PIN_CAP, "Audio Pin Capabilities");
+ dump_reg(AUD_PINW_CONNLNG, "Audio Connection List Length");
+ dump_reg(AUD_PINW_CONNLST, "Audio Connection List Entry");
+ dump_reg(AUD_PINW_CNTR, "Audio Pin Widget Control");
+ dump_reg(AUD_PINW_UNSOLRESP,"Audio Unsolicited Response Enable");
+ dump_reg(AUD_CNTL_ST, "Audio Control State Register");
+ dump_reg(AUD_PINW_CONFIG, "Audio Configuration Default");
+ dump_reg(AUD_HDMIW_STATUS, "Audio HDMI Status");
+ dump_reg(AUD_HDMIW_HDMIEDID,"Audio HDMI Data EDID Block");
+ dump_reg(AUD_HDMIW_INFOFR, "Audio HDMI Widget Data Island Packet");
+ dump_reg(AUD_CONV_CHCNT, "Audio Converter Channel Count");
+ dump_reg(AUD_CTS_ENABLE, "Audio CTS Programming Enable");
+
+ printf("\nDetails:\n\n");
+
+ dword = INREG(AUD_VID_DID);
+ printf("AUD_VID_DID vendor id\t\t\t0x%x\n", dword >> 16);
+ printf("AUD_VID_DID device id\t\t\t0x%x\n", dword & 0xffff);
+
+ dword = INREG(AUD_RID);
+ printf("AUD_RID major revision\t\t\t0x%lx\n", BITS(dword, 23, 20));
+ printf("AUD_RID minor revision\t\t\t0x%lx\n", BITS(dword, 19, 16));
+ printf("AUD_RID revision id\t\t\t0x%lx\n", BITS(dword, 15, 8));
+ printf("AUD_RID stepping id\t\t\t0x%lx\n", BITS(dword, 7, 0));
+
+ dword = INREG(SDVOB);
+ printf("SDVOB enable\t\t\t\t%u\n", !!(dword & SDVO_ENABLE));
+ printf("SDVOB HDMI encoding\t\t\t%u\n", !!(dword & SDVO_ENCODING_HDMI));
+ printf("SDVOB SDVO encoding\t\t\t%u\n", !!(dword & SDVO_ENCODING_SDVO));
+ printf("SDVOB null packets\t\t\t%u\n", !!(dword & SDVO_NULL_PACKETS_DURING_VSYNC));
+ printf("SDVOB audio enabled\t\t\t%u\n", !!(dword & SDVO_AUDIO_ENABLE));
+
+ dword = INREG(SDVOC);
+ printf("SDVOC enable\t\t\t\t%u\n", !!(dword & SDVO_ENABLE));
+ printf("SDVOC HDMI encoding\t\t\t%u\n", !!(dword & SDVO_ENCODING_HDMI));
+ printf("SDVOC SDVO encoding\t\t\t%u\n", !!(dword & SDVO_ENCODING_SDVO));
+ printf("SDVOC null packets\t\t\t%u\n", !!(dword & SDVO_NULL_PACKETS_DURING_VSYNC));
+ printf("SDVOC audio enabled\t\t\t%u\n", !!(dword & SDVO_AUDIO_ENABLE));
+
+ dword = INREG(PORT_HOTPLUG_EN);
+ printf("PORT_HOTPLUG_EN DisplayPort/HDMI port B\t%ld\n", BIT(dword, 29)),
+ printf("PORT_HOTPLUG_EN DisplayPort/HDMI port C\t%ld\n", BIT(dword, 28)),
+ printf("PORT_HOTPLUG_EN DisplayPort port D\t%ld\n", BIT(dword, 27)),
+ printf("PORT_HOTPLUG_EN SDVOB\t\t\t%ld\n", BIT(dword, 26)),
+ printf("PORT_HOTPLUG_EN SDVOC\t\t\t%ld\n", BIT(dword, 25)),
+ printf("PORT_HOTPLUG_EN audio\t\t\t%ld\n", BIT(dword, 24)),
+ printf("PORT_HOTPLUG_EN TV\t\t\t%ld\n", BIT(dword, 23)),
+ printf("PORT_HOTPLUG_EN CRT\t\t\t%ld\n", BIT(dword, 9)),
+
+ dword = INREG(VIDEO_DIP_CTL);
+ printf("VIDEO_DIP_CTL enable graphics DIP\t%ld\n", BIT(dword, 31)),
+ printf("VIDEO_DIP_CTL port select\t\t[0x%lx] %s\n",
+ BITS(dword, 30, 29), dip_port[BITS(dword, 30, 29)]);
+ printf("VIDEO_DIP_CTL DIP buffer trans active\t%lu\n", BIT(dword, 28));
+ printf("VIDEO_DIP_CTL AVI DIP enabled\t\t%lu\n", BIT(dword, 21));
+ printf("VIDEO_DIP_CTL vendor DIP enabled\t%lu\n", BIT(dword, 22));
+ printf("VIDEO_DIP_CTL SPD DIP enabled\t\t%lu\n", BIT(dword, 24));
+ printf("VIDEO_DIP_CTL DIP buffer index\t\t[0x%lx] %s\n",
+ BITS(dword, 20, 19), video_dip_index[BITS(dword, 20, 19)]);
+ printf("VIDEO_DIP_CTL DIP trans freq\t\t[0x%lx] %s\n",
+ BITS(dword, 17, 16), video_dip_trans[BITS(dword, 17, 16)]);
+ printf("VIDEO_DIP_CTL DIP buffer size\t\t%lu\n", BITS(dword, 11, 8));
+ printf("VIDEO_DIP_CTL DIP address\t\t%lu\n", BITS(dword, 3, 0));
+
+ dword = INREG(AUD_CONFIG);
+ printf("AUD_CONFIG pixel clock\t\t\t[0x%lx] %s\n", BITS(dword, 19, 16),
+ OPNAME(pixel_clock, BITS(dword, 19, 16)));
+ printf("AUD_CONFIG fabrication enabled\t\t%lu\n", BITS(dword, 2, 2));
+ printf("AUD_CONFIG professional use allowed\t%lu\n", BIT(dword, 1));
+ printf("AUD_CONFIG fuse enabled\t\t\t%lu\n", BIT(dword, 0));
+
+ dword = INREG(AUD_DEBUG);
+ printf("AUD_DEBUG function reset\t\t%lu\n", BIT(dword, 0));
+
+ dword = INREG(AUD_SUBN_CNT);
+ printf("AUD_SUBN_CNT starting node number\t0x%lx\n", BITS(dword, 23, 16));
+ printf("AUD_SUBN_CNT total number of nodes\t0x%lx\n", BITS(dword, 7, 0));
+
+ dword = INREG(AUD_SUBN_CNT2);
+ printf("AUD_SUBN_CNT2 starting node number\t0x%lx\n", BITS(dword, 24, 16));
+ printf("AUD_SUBN_CNT2 total number of nodes\t0x%lx\n", BITS(dword, 7, 0));
+
+ dword = INREG(AUD_FUNC_GRP);
+ printf("AUD_FUNC_GRP unsol capable\t\t%lu\n", BIT(dword, 8));
+ printf("AUD_FUNC_GRP node type\t\t\t0x%lx\n", BITS(dword, 7, 0));
+
+ dword = INREG(AUD_GRP_CAP);
+ printf("AUD_GRP_CAP beep 0\t\t\t%lu\n", BIT(dword, 16));
+ printf("AUD_GRP_CAP input delay\t\t\t%lu\n", BITS(dword, 11, 8));
+ printf("AUD_GRP_CAP output delay\t\t%lu\n", BITS(dword, 3, 0));
+
+ dword = INREG(AUD_PWRST);
+ printf("AUD_PWRST device power state\t\t%s\n",
+ power_state[BITS(dword, 5, 4)]);
+ printf("AUD_PWRST device power state setting\t%s\n",
+ power_state[BITS(dword, 1, 0)]);
+
+ dword = INREG(AUD_SUPPWR);
+ printf("AUD_SUPPWR support D0\t\t\t%lu\n", BIT(dword, 0));
+ printf("AUD_SUPPWR support D1\t\t\t%lu\n", BIT(dword, 1));
+ printf("AUD_SUPPWR support D2\t\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_SUPPWR support D3\t\t\t%lu\n", BIT(dword, 3));
+
+ dword = INREG(AUD_OUT_CWCAP);
+ printf("AUD_OUT_CWCAP widget type\t\t0x%lx\n", BITS(dword, 23, 20));
+ printf("AUD_OUT_CWCAP sample delay\t\t0x%lx\n", BITS(dword, 19, 16));
+ printf("AUD_OUT_CWCAP channel count\t\t%lu\n",
+ BITS(dword, 15, 13) * 2 + BIT(dword, 0) + 1);
+ printf("AUD_OUT_CWCAP L-R swap\t\t\t%lu\n", BIT(dword, 11));
+ printf("AUD_OUT_CWCAP power control\t\t%lu\n", BIT(dword, 10));
+ printf("AUD_OUT_CWCAP digital\t\t\t%lu\n", BIT(dword, 9));
+ printf("AUD_OUT_CWCAP conn list\t\t\t%lu\n", BIT(dword, 8));
+ printf("AUD_OUT_CWCAP unsol\t\t\t%lu\n", BIT(dword, 7));
+ printf("AUD_OUT_CWCAP mute\t\t\t%lu\n", BIT(dword, 5));
+ printf("AUD_OUT_CWCAP format override\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_OUT_CWCAP amp param override\t%lu\n", BIT(dword, 3));
+ printf("AUD_OUT_CWCAP out amp present\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_OUT_CWCAP in amp present\t\t%lu\n", BIT(dword, 1));
+
+ dword = INREG(AUD_OUT_DIG_CNVT);
+ printf("AUD_OUT_DIG_CNVT SPDIF category\t\t0x%lx\n", BITS(dword, 14, 8));
+ printf("AUD_OUT_DIG_CNVT SPDIF level\t\t%lu\n", BIT(dword, 7));
+ printf("AUD_OUT_DIG_CNVT professional\t\t%lu\n", BIT(dword, 6));
+ printf("AUD_OUT_DIG_CNVT non PCM\t\t%lu\n", BIT(dword, 5));
+ printf("AUD_OUT_DIG_CNVT copyright asserted\t%lu\n", BIT(dword, 4));
+ printf("AUD_OUT_DIG_CNVT filter preemphasis\t%lu\n", BIT(dword, 3));
+ printf("AUD_OUT_DIG_CNVT validity config\t%lu\n", BIT(dword, 2));
+ printf("AUD_OUT_DIG_CNVT validity flag\t\t%lu\n", BIT(dword, 1));
+ printf("AUD_OUT_DIG_CNVT digital enable\t\t%lu\n", BIT(dword, 0));
+
+ dword = INREG(AUD_OUT_CH_STR);
+ printf("AUD_OUT_CH_STR stream id\t\t0x%lx\n", BITS(dword, 7, 4));
+ printf("AUD_OUT_CH_STR lowest channel\t\t%lu\n", BITS(dword, 3, 0));
+
+ dword = INREG(AUD_OUT_STR_DESC);
+ printf("AUD_OUT_STR_DESC stream channels\t%lu\n", BITS(dword, 3, 0) + 1);
+ printf("AUD_OUT_STR_DESC Bits per Sample\t[%#lx] %s\n",
+ BITS(dword, 6, 4), OPNAME(bits_per_sample, BITS(dword, 6, 4)));
+
+ dword = INREG(AUD_PINW_CAP);
+ printf("AUD_PINW_CAP widget type\t\t0x%lx\n", BITS(dword, 23, 20));
+ printf("AUD_PINW_CAP sample delay\t\t0x%lx\n", BITS(dword, 19, 16));
+ printf("AUD_PINW_CAP channel count\t\t%lu\n",
+ BITS(dword, 15, 13) * 2 + BIT(dword, 0) + 1);
+ printf("AUD_PINW_CAP HDCP\t\t\t%lu\n", BIT(dword, 12));
+ printf("AUD_PINW_CAP L-R swap\t\t\t%lu\n", BIT(dword, 11));
+ printf("AUD_PINW_CAP power control\t\t%lu\n", BIT(dword, 10));
+ printf("AUD_PINW_CAP digital\t\t\t%lu\n", BIT(dword, 9));
+ printf("AUD_PINW_CAP conn list\t\t\t%lu\n", BIT(dword, 8));
+ printf("AUD_PINW_CAP unsol\t\t\t%lu\n", BIT(dword, 7));
+ printf("AUD_PINW_CAP mute\t\t\t%lu\n", BIT(dword, 5));
+ printf("AUD_PINW_CAP format override\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_PINW_CAP amp param override\t\t%lu\n", BIT(dword, 3));
+ printf("AUD_PINW_CAP out amp present\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_PINW_CAP in amp present\t\t%lu\n", BIT(dword, 1));
+
+
+ dword = INREG(AUD_PIN_CAP);
+ printf("AUD_PIN_CAP EAPD\t\t\t%lu\n", BIT(dword, 16));
+ printf("AUD_PIN_CAP HDMI\t\t\t%lu\n", BIT(dword, 7));
+ printf("AUD_PIN_CAP output\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_PIN_CAP presence detect\t\t%lu\n", BIT(dword, 2));
+
+ dword = INREG(AUD_PINW_CNTR);
+ printf("AUD_PINW_CNTR mute status\t\t%lu\n", BIT(dword, 8));
+ printf("AUD_PINW_CNTR out enable\t\t%lu\n", BIT(dword, 6));
+ printf("AUD_PINW_CNTR amp mute status\t\t%lu\n", BIT(dword, 8));
+ printf("AUD_PINW_CNTR amp mute status\t\t%lu\n", BIT(dword, 8));
+ printf("AUD_PINW_CNTR stream type\t\t[0x%lx] %s\n",
+ BITS(dword, 2, 0),
+ OPNAME(stream_type, BITS(dword, 2, 0)));
+
+ dword = INREG(AUD_PINW_UNSOLRESP);
+ printf("AUD_PINW_UNSOLRESP enable unsol resp\t%lu\n", BIT(dword, 31));
+
+ dword = INREG(AUD_CNTL_ST);
+ printf("AUD_CNTL_ST DIP audio enabled\t\t%lu\n", BIT(dword, 21));
+ printf("AUD_CNTL_ST DIP ACP enabled\t\t%lu\n", BIT(dword, 22));
+ printf("AUD_CNTL_ST DIP ISRCx enabled\t\t%lu\n", BIT(dword, 23));
+ printf("AUD_CNTL_ST DIP port select\t\t[0x%lx] %s\n",
+ BITS(dword, 30, 29), dip_port[BITS(dword, 30, 29)]);
+ printf("AUD_CNTL_ST DIP buffer index\t\t[0x%lx] %s\n",
+ BITS(dword, 20, 18), OPNAME(dip_index, BITS(dword, 20, 18)));
+ printf("AUD_CNTL_ST DIP trans freq\t\t[0x%lx] %s\n",
+ BITS(dword, 17, 16), dip_trans[BITS(dword, 17, 16)]);
+ printf("AUD_CNTL_ST DIP address\t\t\t%lu\n", BITS(dword, 3, 0));
+ printf("AUD_CNTL_ST CP ready\t\t\t%lu\n", BIT(dword, 15));
+ printf("AUD_CNTL_ST ELD valid\t\t\t%lu\n", BIT(dword, 14));
+ printf("AUD_CNTL_ST ELD ack\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_CNTL_ST ELD bufsize\t\t\t%lu\n", BITS(dword, 13, 9));
+ printf("AUD_CNTL_ST ELD address\t\t\t%lu\n", BITS(dword, 8, 5));
+
+ dword = INREG(AUD_HDMIW_STATUS);
+ printf("AUD_HDMIW_STATUS CDCLK/DOTCLK underrun\t%lu\n", BIT(dword, 31));
+ printf("AUD_HDMIW_STATUS CDCLK/DOTCLK overrun\t%lu\n", BIT(dword, 30));
+ printf("AUD_HDMIW_STATUS BCLK/CDCLK underrun\t%lu\n", BIT(dword, 29));
+ printf("AUD_HDMIW_STATUS BCLK/CDCLK overrun\t%lu\n", BIT(dword, 28));
+
+ dword = INREG(AUD_CONV_CHCNT);
+ printf("AUD_CONV_CHCNT HDMI HBR enabled\t\t%lu\n", BITS(dword, 15, 14));
+ printf("AUD_CONV_CHCNT HDMI channel count\t%lu\n", BITS(dword, 11, 8) + 1);
+
+ printf("AUD_CONV_CHCNT HDMI channel mapping:\n");
+ for (i = 0; i < 8; i++) {
+ OUTREG(AUD_CONV_CHCNT, i);
+ dword = INREG(AUD_CONV_CHCNT);
+ printf("\t\t\t\t\t[0x%x] %u => %lu \n", dword, i, BITS(dword, 7, 4));
+ }
+
+ printf("AUD_HDMIW_HDMIEDID HDMI ELD:\n\t");
+ dword = INREG(AUD_CNTL_ST);
+ dword &= ~BITMASK(8, 5);
+ OUTREG(AUD_CNTL_ST, dword);
+ for (i = 0; i < BITS(dword, 14, 10) / 4; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_HDMIEDID)));
+ printf("\n");
+
+ printf("AUD_HDMIW_INFOFR HDMI audio Infoframe:\n\t");
+ dword = INREG(AUD_CNTL_ST);
+ dword &= ~BITMASK(20, 18);
+ dword &= ~BITMASK(3, 0);
+ OUTREG(AUD_CNTL_ST, dword);
+ for (i = 0; i < 8; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_INFOFR)));
+ printf("\n");
+}
+
+#undef AUD_RID
+#undef AUD_VID_DID
+#undef AUD_PWRST
+#undef AUD_OUT_CH_STR
+#undef AUD_HDMIW_STATUS
+
+/*
+ * IronLake registers
+ */
+#define AUD_CONFIG_A 0xE2000
+#define AUD_CONFIG_B 0xE2100
+#define AUD_CTS_ENABLE_A 0xE2028
+#define AUD_CTS_ENABLE_B 0xE2128
+#define AUD_MISC_CTRL_A 0xE2010
+#define AUD_MISC_CTRL_B 0xE2110
+#define AUD_VID_DID 0xE2020
+#define AUD_RID 0xE2024
+#define AUD_PWRST 0xE204C
+#define AUD_PORT_EN_HD_CFG 0xE207C
+#define AUD_OUT_DIG_CNVT_A 0xE2080
+#define AUD_OUT_DIG_CNVT_B 0xE2180
+#define AUD_OUT_CH_STR 0xE2088
+#define AUD_OUT_STR_DESC_A 0xE2084
+#define AUD_OUT_STR_DESC_B 0xE2184
+#define AUD_PINW_CONNLNG_LIST 0xE20A8
+#define AUD_PINW_CONNLNG_SEL 0xE20AC
+#define AUD_CNTL_ST_A 0xE20B4
+#define AUD_CNTL_ST_B 0xE21B4
+#define AUD_CNTL_ST2 0xE20C0
+#define AUD_HDMIW_STATUS 0xE20D4
+#define AUD_HDMIW_HDMIEDID_A 0xE2050
+#define AUD_HDMIW_HDMIEDID_B 0xE2150
+#define AUD_HDMIW_INFOFR_A 0xE2054
+#define AUD_HDMIW_INFOFR_B 0xE2154
+
+static void dump_ironlake(void)
+{
+ uint32_t dword;
+ int i;
+
+ dump_reg(HDMIB, "sDVO/HDMI Port B Control");
+ dump_reg(HDMIC, "HDMI Port C Control");
+ dump_reg(HDMID, "HDMI Port D Control");
+ dump_reg(PCH_DP_B, "DisplayPort B Control Register");
+ dump_reg(PCH_DP_C, "DisplayPort C Control Register");
+ dump_reg(PCH_DP_D, "DisplayPort D Control Register");
+ dump_reg(AUD_CONFIG_A, "Audio Configuration - Transcoder A");
+ dump_reg(AUD_CONFIG_B, "Audio Configuration - Transcoder B");
+ dump_reg(AUD_CTS_ENABLE_A, "Audio CTS Programming Enable - Transcoder A");
+ dump_reg(AUD_CTS_ENABLE_B, "Audio CTS Programming Enable - Transcoder B");
+ dump_reg(AUD_MISC_CTRL_A, "Audio MISC Control for Transcoder A");
+ dump_reg(AUD_MISC_CTRL_B, "Audio MISC Control for Transcoder B");
+ dump_reg(AUD_VID_DID, "Audio Vendor ID / Device ID");
+ dump_reg(AUD_RID, "Audio Revision ID");
+ dump_reg(AUD_PWRST, "Audio Power State (Function Group, Convertor, Pin Widget)");
+ dump_reg(AUD_PORT_EN_HD_CFG, "Audio Port Enable HDAudio Config");
+ dump_reg(AUD_OUT_DIG_CNVT_A, "Audio Digital Converter - Conv A");
+ dump_reg(AUD_OUT_DIG_CNVT_B, "Audio Digital Converter - Conv B");
+ dump_reg(AUD_OUT_CH_STR, "Audio Channel ID and Stream ID");
+ dump_reg(AUD_OUT_STR_DESC_A, "Audio Stream Descriptor Format - Conv A");
+ dump_reg(AUD_OUT_STR_DESC_B, "Audio Stream Descriptor Format - Conv B");
+ dump_reg(AUD_PINW_CONNLNG_LIST, "Audio Connection List");
+ dump_reg(AUD_PINW_CONNLNG_SEL, "Audio Connection Select");
+ dump_reg(AUD_CNTL_ST_A, "Audio Control State Register - Transcoder A");
+ dump_reg(AUD_CNTL_ST_B, "Audio Control State Register - Transcoder B");
+ dump_reg(AUD_CNTL_ST2, "Audio Control State 2");
+ dump_reg(AUD_HDMIW_STATUS, "Audio HDMI Status");
+ dump_reg(AUD_HDMIW_HDMIEDID_A, "HDMI Data EDID Block - Transcoder A");
+ dump_reg(AUD_HDMIW_HDMIEDID_B, "HDMI Data EDID Block - Transcoder B");
+ dump_reg(AUD_HDMIW_INFOFR_A, "Audio Widget Data Island Packet - Transcoder A");
+ dump_reg(AUD_HDMIW_INFOFR_B, "Audio Widget Data Island Packet - Transcoder B");
+
+ printf("\nDetails:\n\n");
+
+ dword = INREG(AUD_VID_DID);
+ printf("AUD_VID_DID vendor id\t\t\t\t\t0x%x\n", dword >> 16);
+ printf("AUD_VID_DID device id\t\t\t\t\t0x%x\n", dword & 0xffff);
+
+ dword = INREG(AUD_RID);
+ printf("AUD_RID Major_Revision\t\t\t\t\t0x%lx\n", BITS(dword, 23, 20));
+ printf("AUD_RID Minor_Revision\t\t\t\t\t0x%lx\n", BITS(dword, 19, 16));
+ printf("AUD_RID Revision_Id\t\t\t\t\t0x%lx\n", BITS(dword, 15, 8));
+ printf("AUD_RID Stepping_Id\t\t\t\t\t0x%lx\n", BITS(dword, 7, 0));
+
+ dword = INREG(HDMIB);
+ printf("HDMIB HDMIB_Enable\t\t\t\t\t%u\n", !!(dword & SDVO_ENABLE));
+ printf("HDMIB Transcoder_Select\t\t\t\t\t%s\n", BIT(dword, 30) ? "Transcoder B" : "Transcoder A");
+ printf("HDMIB HDCP_Port_Select\t\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("HDMIB SDVOB Hot Plug Interrupt Detect Enable\t\t%lu\n", BIT(dword, 23));
+ printf("HDMIB Digital_Port_B_Detected\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("HDMIB Encoding\t\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 11, 10), sdvo_hdmi_encoding[BITS(dword, 11, 10)]);
+ printf("HDMIB Null_packets_enabled_during_Vsync\t\t\t%u\n", !!(dword & SDVO_NULL_PACKETS_DURING_VSYNC));
+ printf("HDMIB Audio_Output_Enable\t\t\t\t%u\n", !!(dword & SDVO_AUDIO_ENABLE));
+
+ dword = INREG(HDMIC);
+ printf("HDMIC HDMIC_Enable\t\t\t\t\t%u\n", !!(dword & SDVO_ENABLE));
+ printf("HDMIC Transcoder_Select\t\t\t\t\t%s\n", BIT(dword, 30) ? "Transcoder B" : "Transcoder A");
+ printf("HDMIC HDCP_Port_Select\t\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("HDMIC Digital_Port_C_Detected\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("HDMIC Encoding\t\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 11, 10), sdvo_hdmi_encoding[BITS(dword, 11, 10)]);
+ printf("HDMIC Null_packets_enabled_during_Vsync\t\t\t%u\n", !!(dword & SDVO_NULL_PACKETS_DURING_VSYNC));
+ printf("HDMIC Audio_Output_Enable\t\t\t\t%u\n", !!(dword & SDVO_AUDIO_ENABLE));
+
+ dword = INREG(HDMID);
+ printf("HDMID HDMID_Enable\t\t\t\t\t%u\n", !!(dword & SDVO_ENABLE));
+ printf("HDMID Transcoder_Select\t\t\t\t\t%s\n", BIT(dword, 30) ? "Transcoder B" : "Transcoder A");
+ printf("HDMID HDCP_Port_Select\t\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("HDMID Digital_Port_D_Detected\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("HDMID Encoding\t\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 11, 10), sdvo_hdmi_encoding[BITS(dword, 11, 10)]);
+ printf("HDMID Null_packets_enabled_during_Vsync\t\t\t%u\n", !!(dword & SDVO_NULL_PACKETS_DURING_VSYNC));
+ printf("HDMID Audio_Output_Enable\t\t\t\t%u\n", !!(dword & SDVO_AUDIO_ENABLE));
+
+ dword = INREG(PCH_DP_B);
+ printf("PCH_DP_B DisplayPort_Enable\t\t\t\t%lu\n", BIT(dword, 31));
+ printf("PCH_DP_B Transcoder_Select\t\t\t\t%s\n", BIT(dword, 30) ? "Transcoder B" : "Transcoder A");
+ printf("PCH_DP_B Port_Width_Selection\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 21, 19), dp_port_width[BITS(dword, 21, 19)]);
+ printf("PCH_DP_B Port_Detected\t\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("PCH_DP_B HDCP_Port_Select\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("PCH_DP_B Audio_Output_Enable\t\t\t\t%lu\n", BIT(dword, 6));
+
+ dword = INREG(PCH_DP_C);
+ printf("PCH_DP_C DisplayPort_Enable\t\t\t\t%lu\n", BIT(dword, 31));
+ printf("PCH_DP_C Transcoder_Select\t\t\t\t%s\n", BIT(dword, 30) ? "Transcoder B" : "Transcoder A");
+ printf("PCH_DP_C Port_Width_Selection\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 21, 19), dp_port_width[BITS(dword, 21, 19)]);
+ printf("PCH_DP_C Port_Detected\t\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("PCH_DP_C HDCP_Port_Select\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("PCH_DP_C Audio_Output_Enable\t\t\t\t%lu\n", BIT(dword, 6));
+
+ dword = INREG(PCH_DP_D);
+ printf("PCH_DP_D DisplayPort_Enable\t\t\t\t%lu\n", BIT(dword, 31));
+ printf("PCH_DP_D Transcoder_Select\t\t\t\t%s\n", BIT(dword, 30) ? "Transcoder B" : "Transcoder A");
+ printf("PCH_DP_D Port_Width_Selection\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 21, 19), dp_port_width[BITS(dword, 21, 19)]);
+ printf("PCH_DP_D Port_Detected\t\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("PCH_DP_D HDCP_Port_Select\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("PCH_DP_D Audio_Output_Enable\t\t\t\t%lu\n", BIT(dword, 6));
+
+ dword = INREG(AUD_CONFIG_A);
+ printf("AUD_CONFIG_A N_index_value\t\t\t\t[0x%lx] %s\n", BIT(dword, 29),
+ n_index_value[BIT(dword, 29)]);
+ printf("AUD_CONFIG_A N_programming_enable\t\t\t%lu\n", BIT(dword, 28));
+ printf("AUD_CONFIG_A Upper_N_value\t\t\t\t0x%02lx\n", BITS(dword, 27, 20));
+ printf("AUD_CONFIG_A Lower_N_value\t\t\t\t0x%03lx\n", BITS(dword, 15, 4));
+ printf("AUD_CONFIG_A Pixel_Clock\t\t\t\t[0x%lx] %s\n", BITS(dword, 19, 16),
+ OPNAME(pixel_clock, BITS(dword, 19, 16)));
+ printf("AUD_CONFIG_A Disable_NCTS\t\t\t\t%lu\n", BIT(dword, 3));
+ dword = INREG(AUD_CONFIG_B);
+ printf("AUD_CONFIG_B N_index_value\t\t\t\t[0x%lx] %s\n", BIT(dword, 29),
+ n_index_value[BIT(dword, 29)]);
+ printf("AUD_CONFIG_B N_programming_enable\t\t\t%lu\n", BIT(dword, 28));
+ printf("AUD_CONFIG_B Upper_N_value\t\t\t\t0x%02lx\n", BITS(dword, 27, 20));
+ printf("AUD_CONFIG_B Lower_N_value\t\t\t\t0x%03lx\n", BITS(dword, 15, 4));
+ printf("AUD_CONFIG_B Pixel_Clock\t\t\t\t[0x%lx] %s\n", BITS(dword, 19, 16),
+ OPNAME(pixel_clock, BITS(dword, 19, 16)));
+ printf("AUD_CONFIG_B Disable_NCTS\t\t\t\t%lu\n", BIT(dword, 3));
+
+ dword = INREG(AUD_CTS_ENABLE_A);
+ printf("AUD_CTS_ENABLE_A Enable_CTS_or_M_programming\t\t%lu\n", BIT(dword, 20));
+ printf("AUD_CTS_ENABLE_A CTS/M value Index\t\t\t%s\n", BIT(dword, 21) ? "CTS" : "M");
+ printf("AUD_CTS_ENABLE_A CTS_programming\t\t\t%#lx\n", BITS(dword, 19, 0));
+ dword = INREG(AUD_CTS_ENABLE_B);
+ printf("AUD_CTS_ENABLE_B Enable_CTS_or_M_programming\t\t%lu\n", BIT(dword, 20));
+ printf("AUD_CTS_ENABLE_B CTS/M value Index\t\t\t%s\n", BIT(dword, 21) ? "CTS" : "M");
+ printf("AUD_CTS_ENABLE_B CTS_programming\t\t\t%#lx\n", BITS(dword, 19, 0));
+
+ dword = INREG(AUD_MISC_CTRL_A);
+ printf("AUD_MISC_CTRL_A Sample_Fabrication_EN_bit\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_MISC_CTRL_A Sample_present_Disable\t\t\t%lu\n", BIT(dword, 8));
+ printf("AUD_MISC_CTRL_A Output_Delay\t\t\t\t%lu\n", BITS(dword, 7, 4));
+ printf("AUD_MISC_CTRL_A Pro_Allowed\t\t\t\t%lu\n", BIT(dword, 1));
+ dword = INREG(AUD_MISC_CTRL_B);
+ printf("AUD_MISC_CTRL_B Sample_Fabrication_EN_bit\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_MISC_CTRL_B Sample_present_Disable\t\t\t%lu\n", BIT(dword, 8));
+ printf("AUD_MISC_CTRL_B Output_Delay\t\t\t\t%lu\n", BITS(dword, 7, 4));
+ printf("AUD_MISC_CTRL_B Pro_Allowed\t\t\t\t%lu\n", BIT(dword, 1));
+
+ dword = INREG(AUD_PWRST);
+ printf("AUD_PWRST Function_Group_Device_Power_State_Current\t%s\n", power_state[BITS(dword, 23, 22)]);
+ printf("AUD_PWRST Function_Group_Device_Power_State_Set \t%s\n", power_state[BITS(dword, 21, 20)]);
+ printf("AUD_PWRST ConvertorB_Widget_Power_State_Current \t%s\n", power_state[BITS(dword, 19, 18)]);
+ printf("AUD_PWRST ConvertorB_Widget_Power_State_Requested \t%s\n", power_state[BITS(dword, 17, 16)]);
+ printf("AUD_PWRST ConvertorA_Widget_Power_State_Current \t%s\n", power_state[BITS(dword, 15, 14)]);
+ printf("AUD_PWRST ConvertorA_Widget_Power_State_Requsted \t%s\n", power_state[BITS(dword, 13, 12)]);
+ printf("AUD_PWRST PinD_Widget_Power_State_Current \t%s\n", power_state[BITS(dword, 11, 10)]);
+ printf("AUD_PWRST PinD_Widget_Power_State_Set \t%s\n", power_state[BITS(dword, 9, 8)]);
+ printf("AUD_PWRST PinC_Widget_Power_State_Current \t%s\n", power_state[BITS(dword, 7, 6)]);
+ printf("AUD_PWRST PinC_Widget_Power_State_Set \t%s\n", power_state[BITS(dword, 5, 4)]);
+ printf("AUD_PWRST PinB_Widget_Power_State_Current \t%s\n", power_state[BITS(dword, 3, 2)]);
+ printf("AUD_PWRST PinB_Widget_Power_State_Set \t%s\n", power_state[BITS(dword, 1, 0)]);
+
+ dword = INREG(AUD_PORT_EN_HD_CFG);
+ printf("AUD_PORT_EN_HD_CFG Convertor_A_Digen\t\t\t%lu\n", BIT(dword, 0));
+ printf("AUD_PORT_EN_HD_CFG Convertor_B_Digen\t\t\t%lu\n", BIT(dword, 1));
+ printf("AUD_PORT_EN_HD_CFG ConvertorA_Stream_ID\t\t%lu\n", BITS(dword, 7, 4));
+ printf("AUD_PORT_EN_HD_CFG ConvertorB_Stream_ID\t\t%lu\n", BITS(dword, 11, 8));
+ printf("AUD_PORT_EN_HD_CFG Port_B_Out_Enable\t\t\t%lu\n", BIT(dword, 12));
+ printf("AUD_PORT_EN_HD_CFG Port_C_Out_Enable\t\t\t%lu\n", BIT(dword, 13));
+ printf("AUD_PORT_EN_HD_CFG Port_D_Out_Enable\t\t\t%lu\n", BIT(dword, 14));
+ printf("AUD_PORT_EN_HD_CFG Port_B_Amp_Mute_Status\t\t%lu\n", BIT(dword, 16));
+ printf("AUD_PORT_EN_HD_CFG Port_C_Amp_Mute_Status\t\t%lu\n", BIT(dword, 17));
+ printf("AUD_PORT_EN_HD_CFG Port_D_Amp_Mute_Status\t\t%lu\n", BIT(dword, 18));
+
+ dword = INREG(AUD_OUT_DIG_CNVT_A);
+ printf("AUD_OUT_DIG_CNVT_A V\t\t\t\t\t%lu\n", BIT(dword, 1));
+ printf("AUD_OUT_DIG_CNVT_A VCFG\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_OUT_DIG_CNVT_A PRE\t\t\t\t\t%lu\n", BIT(dword, 3));
+ printf("AUD_OUT_DIG_CNVT_A Copy\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_OUT_DIG_CNVT_A NonAudio\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("AUD_OUT_DIG_CNVT_A PRO\t\t\t\t\t%lu\n", BIT(dword, 6));
+ printf("AUD_OUT_DIG_CNVT_A Level\t\t\t\t%lu\n", BIT(dword, 7));
+ printf("AUD_OUT_DIG_CNVT_A Category_Code\t\t\t%lu\n", BITS(dword, 14, 8));
+ printf("AUD_OUT_DIG_CNVT_A Lowest_Channel_Number\t\t%lu\n",BITS(dword, 19, 16));
+ printf("AUD_OUT_DIG_CNVT_A Stream_ID\t\t\t\t%lu\n", BITS(dword, 23, 20));
+
+ dword = INREG(AUD_OUT_DIG_CNVT_B);
+ printf("AUD_OUT_DIG_CNVT_B V\t\t\t\t\t%lu\n", BIT(dword, 1));
+ printf("AUD_OUT_DIG_CNVT_B VCFG\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_OUT_DIG_CNVT_B PRE\t\t\t\t\t%lu\n", BIT(dword, 3));
+ printf("AUD_OUT_DIG_CNVT_B Copy\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_OUT_DIG_CNVT_B NonAudio\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("AUD_OUT_DIG_CNVT_B PRO\t\t\t\t\t%lu\n", BIT(dword, 6));
+ printf("AUD_OUT_DIG_CNVT_B Level\t\t\t\t%lu\n", BIT(dword, 7));
+ printf("AUD_OUT_DIG_CNVT_B Category_Code\t\t\t%lu\n", BITS(dword, 14, 8));
+ printf("AUD_OUT_DIG_CNVT_B Lowest_Channel_Number\t\t%lu\n",BITS(dword, 19, 16));
+ printf("AUD_OUT_DIG_CNVT_B Stream_ID\t\t\t\t%lu\n", BITS(dword, 23, 20));
+
+ printf("AUD_OUT_CH_STR Converter_Channel_MAP PORTB PORTC PORTD\n");
+ for (i = 0; i < 8; i++) {
+ OUTREG(AUD_OUT_CH_STR, i | (i << 8) | (i << 16));
+ dword = INREG(AUD_OUT_CH_STR);
+ printf("\t\t\t\t%lu\t%lu\t%lu\t%lu\n",
+ 1 + BITS(dword, 3, 0),
+ 1 + BITS(dword, 7, 4),
+ 1 + BITS(dword, 15, 12),
+ 1 + BITS(dword, 23, 20));
+ }
+
+ dword = INREG(AUD_OUT_STR_DESC_A);
+ printf("AUD_OUT_STR_DESC_A HBR_enable\t\t\t\t%lu\n", BITS(dword, 28, 27));
+ printf("AUD_OUT_STR_DESC_A Convertor_Channel_Count\t\t%lu\n", BITS(dword, 20, 16) + 1);
+ printf("AUD_OUT_STR_DESC_A Bits_per_Sample\t\t\t[%#lx] %s\n",
+ BITS(dword, 6, 4), OPNAME(bits_per_sample, BITS(dword, 6, 4)));
+ printf("AUD_OUT_STR_DESC_A Number_of_Channels_in_a_Stream\t%lu\n", 1 + BITS(dword, 3, 0));
+
+ dword = INREG(AUD_OUT_STR_DESC_B);
+ printf("AUD_OUT_STR_DESC_B HBR_enable\t\t\t\t%lu\n", BITS(dword, 28, 27));
+ printf("AUD_OUT_STR_DESC_B Convertor_Channel_Count\t\t%lu\n", BITS(dword, 20, 16) + 1);
+ printf("AUD_OUT_STR_DESC_B Bits_per_Sample\t\t\t[%#lx] %s\n",
+ BITS(dword, 6, 4), OPNAME(bits_per_sample, BITS(dword, 6, 4)));
+ printf("AUD_OUT_STR_DESC_B Number_of_Channels_in_a_Stream\t%lu\n", 1 + BITS(dword, 3, 0));
+
+ dword = INREG(AUD_PINW_CONNLNG_SEL);
+ printf("AUD_PINW_CONNLNG_SEL Connection_select_Control_B\t%lu\n", BITS(dword, 7, 0));
+ printf("AUD_PINW_CONNLNG_SEL Connection_select_Control_C\t%lu\n", BITS(dword, 15, 8));
+ printf("AUD_PINW_CONNLNG_SEL Connection_select_Control_D\t%lu\n", BITS(dword, 23, 16));
+
+ dword = INREG(AUD_CNTL_ST_A);
+ printf("AUD_CNTL_ST_A DIP_Port_Select\t\t\t\t[%#lx] %s\n",
+ BITS(dword, 30, 29), dip_port[BITS(dword, 30, 29)]);
+ printf("AUD_CNTL_ST_A DIP_type_enable_status Audio DIP\t\t%lu\n", BIT(dword, 21));
+ printf("AUD_CNTL_ST_A DIP_type_enable_status ACP DIP\t\t%lu\n", BIT(dword, 22));
+ printf("AUD_CNTL_ST_A DIP_type_enable_status Generic 2 DIP\t%lu\n", BIT(dword, 23));
+ printf("AUD_CNTL_ST_A DIP_transmission_frequency\t\t[0x%lx] %s\n",
+ BITS(dword, 17, 16), dip_trans[BITS(dword, 17, 16)]);
+ printf("AUD_CNTL_ST_A ELD_ACK\t\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_CNTL_ST_A ELD_buffer_size\t\t\t\t%lu\n", BITS(dword, 14, 10));
+ printf("AUD_CNTL_ST_A ELD_access_address\t\t\t%lu\n", BITS(dword, 9, 5));
+
+ dword = INREG(AUD_CNTL_ST_B);
+ printf("AUD_CNTL_ST_B DIP_Port_Select\t\t\t\t[%#lx] %s\n",
+ BITS(dword, 30, 29), dip_port[BITS(dword, 30, 29)]);
+ printf("AUD_CNTL_ST_B DIP_type_enable_status Audio DIP\t\t%lu\n", BIT(dword, 21));
+ printf("AUD_CNTL_ST_B DIP_type_enable_status ACP DIP\t\t%lu\n", BIT(dword, 22));
+ printf("AUD_CNTL_ST_B DIP_type_enable_status Generic 2 DIP\t%lu\n", BIT(dword, 23));
+ printf("AUD_CNTL_ST_B DIP_transmission_frequency\t\t[0x%lx] %s\n",
+ BITS(dword, 17, 16), dip_trans[BITS(dword, 17, 16)]);
+ printf("AUD_CNTL_ST_B ELD_ACK\t\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_CNTL_ST_B ELD_buffer_size\t\t\t\t%lu\n", BITS(dword, 14, 10));
+ printf("AUD_CNTL_ST_B ELD_access_address\t\t\t%lu\n", BITS(dword, 9, 5));
+
+ dword = INREG(AUD_CNTL_ST2);
+ printf("AUD_CNTL_ST2 CP_ReadyB\t\t\t\t\t%lu\n", BIT(dword, 1));
+ printf("AUD_CNTL_ST2 ELD_validB\t\t\t\t%lu\n", BIT(dword, 0));
+ printf("AUD_CNTL_ST2 CP_ReadyC\t\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("AUD_CNTL_ST2 ELD_validC\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_CNTL_ST2 CP_ReadyD\t\t\t\t\t%lu\n", BIT(dword, 9));
+ printf("AUD_CNTL_ST2 ELD_validD\t\t\t\t%lu\n", BIT(dword, 8));
+
+ dword = INREG(AUD_HDMIW_STATUS);
+ printf("AUD_HDMIW_STATUS Conv_B_CDCLK/DOTCLK_FIFO_Underrun\t%lu\n", BIT(dword, 31));
+ printf("AUD_HDMIW_STATUS Conv_B_CDCLK/DOTCLK_FIFO_Overrun\t%lu\n", BIT(dword, 30));
+ printf("AUD_HDMIW_STATUS Conv_A_CDCLK/DOTCLK_FIFO_Underrun\t%lu\n", BIT(dword, 29));
+ printf("AUD_HDMIW_STATUS Conv_A_CDCLK/DOTCLK_FIFO_Overrun\t%lu\n", BIT(dword, 28));
+ printf("AUD_HDMIW_STATUS BCLK/CDCLK_FIFO_Overrun\t\t%lu\n", BIT(dword, 25));
+ printf("AUD_HDMIW_STATUS Function_Reset\t\t\t%lu\n", BIT(dword, 29));
+
+ printf("AUD_HDMIW_HDMIEDID_A HDMI ELD:\n\t");
+ dword = INREG(AUD_CNTL_ST_A);
+ dword &= ~BITMASK(9, 5);
+ OUTREG(AUD_CNTL_ST_A, dword);
+ for (i = 0; i < BITS(dword, 14, 10) / 4; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_HDMIEDID_A)));
+ printf("\n");
+
+ printf("AUD_HDMIW_HDMIEDID_B HDMI ELD:\n\t");
+ dword = INREG(AUD_CNTL_ST_B);
+ dword &= ~BITMASK(9, 5);
+ OUTREG(AUD_CNTL_ST_B, dword);
+ for (i = 0; i < BITS(dword, 14, 10) / 4; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_HDMIEDID_B)));
+ printf("\n");
+
+ printf("AUD_HDMIW_INFOFR_A HDMI audio Infoframe:\n\t");
+ dword = INREG(AUD_CNTL_ST_A);
+ dword &= ~BITMASK(20, 18);
+ dword &= ~BITMASK(3, 0);
+ OUTREG(AUD_CNTL_ST_A, dword);
+ for (i = 0; i < 8; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_INFOFR_A)));
+ printf("\n");
+
+ printf("AUD_HDMIW_INFOFR_B HDMI audio Infoframe:\n\t");
+ dword = INREG(AUD_CNTL_ST_B);
+ dword &= ~BITMASK(20, 18);
+ dword &= ~BITMASK(3, 0);
+ OUTREG(AUD_CNTL_ST_B, dword);
+ for (i = 0; i < 8; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_INFOFR_B)));
+ printf("\n");
+
+}
+
+
+#undef AUD_CONFIG_A
+#undef AUD_MISC_CTRL_A
+#undef AUD_VID_DID
+#undef AUD_RID
+#undef AUD_CTS_ENABLE_A
+#undef AUD_PWRST
+#undef AUD_HDMIW_HDMIEDID_A
+#undef AUD_HDMIW_INFOFR_A
+#undef AUD_PORT_EN_HD_CFG
+#undef AUD_OUT_DIG_CNVT_A
+#undef AUD_OUT_STR_DESC_A
+#undef AUD_OUT_CH_STR
+#undef AUD_PINW_CONNLNG_LIST
+#undef AUD_CNTL_ST_A
+#undef AUD_HDMIW_STATUS
+#undef AUD_CONFIG_B
+#undef AUD_MISC_CTRL_B
+#undef AUD_CTS_ENABLE_B
+#undef AUD_HDMIW_HDMIEDID_B
+#undef AUD_HDMIW_INFOFR_B
+#undef AUD_OUT_DIG_CNVT_B
+#undef AUD_OUT_STR_DESC_B
+#undef AUD_CNTL_ST_B
+
+/*
+ * CougarPoint registers
+ */
+#define DP_CTL_B 0xE4100
+#define DP_CTL_C 0xE4200
+#define DP_AUX_CTL_C 0xE4210
+#define DP_AUX_TST_C 0xE4228
+#define SPORT_DDI_CRC_C 0xE4250
+#define SPORT_DDI_CRC_R 0xE4264
+#define DP_CTL_D 0xE4300
+#define DP_AUX_CTL_D 0xE4310
+#define DP_AUX_TST_D 0xE4328
+#define SPORT_DDI_CRC_CTL_D 0xE4350
+#define AUD_CONFIG_A 0xE5000
+#define AUD_MISC_CTRL_A 0xE5010
+#define AUD_VID_DID 0xE5020
+#define AUD_RID 0xE5024
+#define AUD_CTS_ENABLE_A 0xE5028
+#define AUD_PWRST 0xE504C
+#define AUD_HDMIW_HDMIEDID_A 0xE5050
+#define AUD_HDMIW_INFOFR_A 0xE5054
+#define AUD_PORT_EN_HD_CFG 0xE507C
+#define AUD_OUT_DIG_CNVT_A 0xE5080
+#define AUD_OUT_STR_DESC_A 0xE5084
+#define AUD_OUT_CH_STR 0xE5088
+#define AUD_PINW_CONNLNG_LIST 0xE50A8
+#define AUD_PINW_CONNLNG_SELA 0xE50AC
+#define AUD_CNTL_ST_A 0xE50B4
+#define AUD_CNTRL_ST2 0xE50C0
+#define AUD_CNTRL_ST3 0xE50C4
+#define AUD_HDMIW_STATUS 0xE50D4
+#define AUD_CONFIG_B 0xE5100
+#define AUD_MISC_CTRL_B 0xE5110
+#define AUD_CTS_ENABLE_B 0xE5128
+#define AUD_HDMIW_HDMIEDID_B 0xE5150
+#define AUD_HDMIW_INFOFR_B 0xE5154
+#define AUD_OUT_DIG_CNVT_B 0xE5180
+#define AUD_OUT_STR_DESC_B 0xE5184
+#define AUD_CNTL_ST_B 0xE51B4
+#define AUD_CONFIG_C 0xE5200
+#define AUD_MISC_CTRL_C 0xE5210
+#define AUD_CTS_ENABLE_C 0xE5228
+#define AUD_HDMIW_HDMIEDID_C 0xE5250
+#define AUD_HDMIW_INFOFR_C 0xE5254
+#define AUD_OUT_DIG_CNVT_C 0xE5280
+#define AUD_OUT_STR_DESC_C 0xE5284
+#define AUD_CNTL_ST_C 0xE52B4
+#define AUD_CONFIG_D 0xE5300
+#define AUD_MISC_CTRL_D 0xE5310
+#define AUD_CTS_ENABLE_D 0xE5328
+#define AUD_HDMIW_HDMIEDID_D 0xE5350
+#define AUD_HDMIW_INFOFR_D 0xE5354
+#define AUD_OUT_DIG_CNVT_D 0xE5380
+#define AUD_OUT_STR_DESC_D 0xE5384
+#define AUD_CNTL_ST_D 0xE53B4
+
+#define VIDEO_DIP_CTL_A 0xE0200
+#define VIDEO_DIP_CTL_B 0xE1200
+#define VIDEO_DIP_CTL_C 0xE2200
+#define VIDEO_DIP_CTL_D 0xE3200
+
+
+static void dump_cpt(void)
+{
+ uint32_t dword;
+ int i;
+
+ dump_reg(HDMIB, "sDVO/HDMI Port B Control");
+ dump_reg(HDMIC, "HDMI Port C Control");
+ dump_reg(HDMID, "HDMI Port D Control");
+ dump_reg(DP_CTL_B, "DisplayPort B Control");
+ dump_reg(DP_CTL_C, "DisplayPort C Control");
+ dump_reg(DP_CTL_D, "DisplayPort D Control");
+ dump_reg(TRANS_DP_CTL_A, "Transcoder A DisplayPort Control");
+ dump_reg(TRANS_DP_CTL_B, "Transcoder B DisplayPort Control");
+ dump_reg(TRANS_DP_CTL_C, "Transcoder C DisplayPort Control");
+ dump_reg(AUD_CONFIG_A, "Audio Configuration - Transcoder A");
+ dump_reg(AUD_CONFIG_B, "Audio Configuration - Transcoder B");
+ dump_reg(AUD_CONFIG_C, "Audio Configuration - Transcoder C");
+ dump_reg(AUD_CTS_ENABLE_A, "Audio CTS Programming Enable - Transcoder A");
+ dump_reg(AUD_CTS_ENABLE_B, "Audio CTS Programming Enable - Transcoder B");
+ dump_reg(AUD_CTS_ENABLE_C, "Audio CTS Programming Enable - Transcoder C");
+ dump_reg(AUD_MISC_CTRL_A, "Audio MISC Control for Transcoder A");
+ dump_reg(AUD_MISC_CTRL_B, "Audio MISC Control for Transcoder B");
+ dump_reg(AUD_MISC_CTRL_C, "Audio MISC Control for Transcoder C");
+ dump_reg(AUD_VID_DID, "Audio Vendor ID / Device ID");
+ dump_reg(AUD_RID, "Audio Revision ID");
+ dump_reg(AUD_PWRST, "Audio Power State (Function Group, Convertor, Pin Widget)");
+ dump_reg(AUD_PORT_EN_HD_CFG, "Audio Port Enable HDAudio Config");
+ dump_reg(AUD_OUT_DIG_CNVT_A, "Audio Digital Converter - Conv A");
+ dump_reg(AUD_OUT_DIG_CNVT_B, "Audio Digital Converter - Conv B");
+ dump_reg(AUD_OUT_DIG_CNVT_C, "Audio Digital Converter - Conv C");
+ dump_reg(AUD_OUT_CH_STR, "Audio Channel ID and Stream ID");
+ dump_reg(AUD_OUT_STR_DESC_A, "Audio Stream Descriptor Format - Conv A");
+ dump_reg(AUD_OUT_STR_DESC_B, "Audio Stream Descriptor Format - Conv B");
+ dump_reg(AUD_OUT_STR_DESC_C, "Audio Stream Descriptor Format - Conv C");
+ dump_reg(AUD_PINW_CONNLNG_LIST, "Audio Connection List");
+ dump_reg(AUD_PINW_CONNLNG_SEL, "Audio Connection Select");
+ dump_reg(AUD_CNTL_ST_A, "Audio Control State Register - Transcoder A");
+ dump_reg(AUD_CNTL_ST_B, "Audio Control State Register - Transcoder B");
+ dump_reg(AUD_CNTL_ST_C, "Audio Control State Register - Transcoder C");
+ dump_reg(AUD_CNTRL_ST2, "Audio Control State 2");
+ dump_reg(AUD_CNTRL_ST3, "Audio Control State 3");
+ dump_reg(AUD_HDMIW_STATUS, "Audio HDMI Status");
+ dump_reg(AUD_HDMIW_HDMIEDID_A, "HDMI Data EDID Block - Transcoder A");
+ dump_reg(AUD_HDMIW_HDMIEDID_B, "HDMI Data EDID Block - Transcoder B");
+ dump_reg(AUD_HDMIW_HDMIEDID_C, "HDMI Data EDID Block - Transcoder C");
+ dump_reg(AUD_HDMIW_INFOFR_A, "Audio Widget Data Island Packet - Transcoder A");
+ dump_reg(AUD_HDMIW_INFOFR_B, "Audio Widget Data Island Packet - Transcoder B");
+ dump_reg(AUD_HDMIW_INFOFR_C, "Audio Widget Data Island Packet - Transcoder C");
+
+ printf("\nDetails:\n\n");
+
+ dword = INREG(VIDEO_DIP_CTL_A);
+ printf("VIDEO_DIP_CTL_A Enable_Graphics_DIP\t\t\t%ld\n", BIT(dword, 31)),
+ printf("VIDEO_DIP_CTL_A GCP_DIP_enable\t\t\t\t%ld\n", BIT(dword, 25)),
+ printf("VIDEO_DIP_CTL_A Video_DIP_type_enable AVI\t\t%lu\n", BIT(dword, 21));
+ printf("VIDEO_DIP_CTL_A Video_DIP_type_enable Vendor\t\t%lu\n", BIT(dword, 22));
+ printf("VIDEO_DIP_CTL_A Video_DIP_type_enable Gamut\t\t%lu\n", BIT(dword, 23));
+ printf("VIDEO_DIP_CTL_A Video_DIP_type_enable Source \t\t%lu\n", BIT(dword, 24));
+ printf("VIDEO_DIP_CTL_A Video_DIP_buffer_index\t\t\t[0x%lx] %s\n",
+ BITS(dword, 20, 19), video_dip_index[BITS(dword, 20, 19)]);
+ printf("VIDEO_DIP_CTL_A Video_DIP_frequency\t\t\t[0x%lx] %s\n",
+ BITS(dword, 17, 16), video_dip_trans[BITS(dword, 17, 16)]);
+ printf("VIDEO_DIP_CTL_A Video_DIP_buffer_size\t\t\t%lu\n", BITS(dword, 11, 8));
+ printf("VIDEO_DIP_CTL_A Video_DIP_access_address\t\t%lu\n", BITS(dword, 3, 0));
+
+ dword = INREG(VIDEO_DIP_CTL_B);
+ printf("VIDEO_DIP_CTL_B Enable_Graphics_DIP\t\t\t%ld\n", BIT(dword, 31)),
+ printf("VIDEO_DIP_CTL_B GCP_DIP_enable\t\t\t\t%ld\n", BIT(dword, 25)),
+ printf("VIDEO_DIP_CTL_B Video_DIP_type_enable AVI\t\t%lu\n", BIT(dword, 21));
+ printf("VIDEO_DIP_CTL_B Video_DIP_type_enable Vendor\t\t%lu\n", BIT(dword, 22));
+ printf("VIDEO_DIP_CTL_B Video_DIP_type_enable Gamut\t\t%lu\n", BIT(dword, 23));
+ printf("VIDEO_DIP_CTL_B Video_DIP_type_enable Source \t\t%lu\n", BIT(dword, 24));
+ printf("VIDEO_DIP_CTL_B Video_DIP_buffer_index\t\t\t[0x%lx] %s\n",
+ BITS(dword, 20, 19), video_dip_index[BITS(dword, 20, 19)]);
+ printf("VIDEO_DIP_CTL_B Video_DIP_frequency\t\t\t[0x%lx] %s\n",
+ BITS(dword, 17, 16), video_dip_trans[BITS(dword, 17, 16)]);
+ printf("VIDEO_DIP_CTL_B Video_DIP_buffer_size\t\t\t%lu\n", BITS(dword, 11, 8));
+ printf("VIDEO_DIP_CTL_B Video_DIP_access_address\t\t%lu\n", BITS(dword, 3, 0));
+
+ dword = INREG(VIDEO_DIP_CTL_C);
+ printf("VIDEO_DIP_CTL_C Enable_Graphics_DIP\t\t\t%ld\n", BIT(dword, 31)),
+ printf("VIDEO_DIP_CTL_C GCP_DIP_enable\t\t\t\t%ld\n", BIT(dword, 25)),
+ printf("VIDEO_DIP_CTL_C Video_DIP_type_enable AVI\t\t%lu\n", BIT(dword, 21));
+ printf("VIDEO_DIP_CTL_C Video_DIP_type_enable Vendor\t\t%lu\n", BIT(dword, 22));
+ printf("VIDEO_DIP_CTL_C Video_DIP_type_enable Gamut\t\t%lu\n", BIT(dword, 23));
+ printf("VIDEO_DIP_CTL_C Video_DIP_type_enable Source \t\t%lu\n", BIT(dword, 24));
+ printf("VIDEO_DIP_CTL_C Video_DIP_buffer_index\t\t\t[0x%lx] %s\n",
+ BITS(dword, 20, 19), video_dip_index[BITS(dword, 20, 19)]);
+ printf("VIDEO_DIP_CTL_C Video_DIP_frequency\t\t\t[0x%lx] %s\n",
+ BITS(dword, 17, 16), video_dip_trans[BITS(dword, 17, 16)]);
+ printf("VIDEO_DIP_CTL_C Video_DIP_buffer_size\t\t\t%lu\n", BITS(dword, 11, 8));
+ printf("VIDEO_DIP_CTL_C Video_DIP_access_address\t\t%lu\n", BITS(dword, 3, 0));
+
+ dword = INREG(AUD_VID_DID);
+ printf("AUD_VID_DID vendor id\t\t\t\t\t0x%x\n", dword >> 16);
+ printf("AUD_VID_DID device id\t\t\t\t\t0x%x\n", dword & 0xffff);
+
+ dword = INREG(AUD_RID);
+ printf("AUD_RID Major_Revision\t\t\t\t\t0x%lx\n", BITS(dword, 23, 20));
+ printf("AUD_RID Minor_Revision\t\t\t\t\t0x%lx\n", BITS(dword, 19, 16));
+ printf("AUD_RID Revision_Id\t\t\t\t\t0x%lx\n", BITS(dword, 15, 8));
+ printf("AUD_RID Stepping_Id\t\t\t\t\t0x%lx\n", BITS(dword, 7, 0));
+
+ dword = INREG(HDMIB);
+ printf("HDMIB Port_Enable\t\t\t\t\t%u\n", !!(dword & SDVO_ENABLE));
+ printf("HDMIB Transcoder_Select\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 30, 29), transcoder_select[BITS(dword, 30, 29)]);
+ printf("HDMIB sDVO_Border_Enable\t\t\t\t%lu\n", BIT(dword, 7));
+ printf("HDMIB HDCP_Port_Select\t\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("HDMIB SDVO_HPD_Interrupt_Enable\t\t\t\t%lu\n", BIT(dword, 23));
+ printf("HDMIB Port_Detected\t\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("HDMIB Encoding\t\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 11, 10), sdvo_hdmi_encoding[BITS(dword, 11, 10)]);
+ printf("HDMIB HDMI_or_DVI_Select\t\t\t\t%s\n", BIT(dword, 9) ? "HDMI" : "DVI");
+ printf("HDMIB Audio_Output_Enable\t\t\t\t%u\n", !!(dword & SDVO_AUDIO_ENABLE));
+
+ dword = INREG(HDMIC);
+ printf("HDMIC Port_Enable\t\t\t\t\t%u\n", !!(dword & SDVO_ENABLE));
+ printf("HDMIC Transcoder_Select\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 30, 29), transcoder_select[BITS(dword, 30, 29)]);
+ printf("HDMIC sDVO_Border_Enable\t\t\t\t%lu\n", BIT(dword, 7));
+ printf("HDMIC HDCP_Port_Select\t\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("HDMIC SDVO_HPD_Interrupt_Enable\t\t\t\t%lu\n", BIT(dword, 23));
+ printf("HDMIC Port_Detected\t\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("HDMIC Encoding\t\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 11, 10), sdvo_hdmi_encoding[BITS(dword, 11, 10)]);
+ printf("HDMIC HDMI_or_DVI_Select\t\t\t\t%s\n", BIT(dword, 9) ? "HDMI" : "DVI");
+ printf("HDMIC Audio_Output_Enable\t\t\t\t%u\n", !!(dword & SDVO_AUDIO_ENABLE));
+
+ dword = INREG(HDMID);
+ printf("HDMID Port_Enable\t\t\t\t\t%u\n", !!(dword & SDVO_ENABLE));
+ printf("HDMID Transcoder_Select\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 30, 29), transcoder_select[BITS(dword, 30, 29)]);
+ printf("HDMID sDVO_Border_Enable\t\t\t\t%lu\n", BIT(dword, 7));
+ printf("HDMID HDCP_Port_Select\t\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("HDMID SDVO_HPD_Interrupt_Enable\t\t\t\t%lu\n", BIT(dword, 23));
+ printf("HDMID Port_Detected\t\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("HDMID Encoding\t\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 11, 10), sdvo_hdmi_encoding[BITS(dword, 11, 10)]);
+ printf("HDMID HDMI_or_DVI_Select\t\t\t\t%s\n", BIT(dword, 9) ? "HDMI" : "DVI");
+ printf("HDMID Audio_Output_Enable\t\t\t\t%u\n", !!(dword & SDVO_AUDIO_ENABLE));
+
+ dword = INREG(DP_CTL_B);
+ printf("DP_CTL_B DisplayPort_Enable\t\t\t\t%lu\n", BIT(dword, 31));
+ printf("DP_CTL_B Port_Width_Selection\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 21, 19), dp_port_width[BITS(dword, 21, 19)]);
+ printf("DP_CTL_B Port_Detected\t\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("DP_CTL_B HDCP_Port_Select\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("DP_CTL_B Audio_Output_Enable\t\t\t\t%lu\n", BIT(dword, 6));
+
+ dword = INREG(DP_CTL_C);
+ printf("DP_CTL_C DisplayPort_Enable\t\t\t\t%lu\n", BIT(dword, 31));
+ printf("DP_CTL_C Port_Width_Selection\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 21, 19), dp_port_width[BITS(dword, 21, 19)]);
+ printf("DP_CTL_C Port_Detected\t\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("DP_CTL_C HDCP_Port_Select\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("DP_CTL_C Audio_Output_Enable\t\t\t\t%lu\n", BIT(dword, 6));
+
+ dword = INREG(DP_CTL_D);
+ printf("DP_CTL_D DisplayPort_Enable\t\t\t\t%lu\n", BIT(dword, 31));
+ printf("DP_CTL_D Port_Width_Selection\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 21, 19), dp_port_width[BITS(dword, 21, 19)]);
+ printf("DP_CTL_D Port_Detected\t\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("DP_CTL_D HDCP_Port_Select\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("DP_CTL_D Audio_Output_Enable\t\t\t\t%lu\n", BIT(dword, 6));
+
+ dword = INREG(AUD_CONFIG_A);
+ printf("AUD_CONFIG_A N_index_value\t\t\t\t[0x%lx] %s\n", BIT(dword, 29),
+ n_index_value[BIT(dword, 29)]);
+ printf("AUD_CONFIG_A N_programming_enable\t\t\t%lu\n", BIT(dword, 28));
+ printf("AUD_CONFIG_A Upper_N_value\t\t\t\t0x%02lx\n", BITS(dword, 27, 20));
+ printf("AUD_CONFIG_A Lower_N_value\t\t\t\t0x%03lx\n", BITS(dword, 15, 4));
+ printf("AUD_CONFIG_A Pixel_Clock_HDMI\t\t\t\t[0x%lx] %s\n", BITS(dword, 19, 16),
+ OPNAME(pixel_clock, BITS(dword, 19, 16)));
+ printf("AUD_CONFIG_A Disable_NCTS\t\t\t\t%lu\n", BIT(dword, 3));
+ dword = INREG(AUD_CONFIG_B);
+ printf("AUD_CONFIG_B N_index_value\t\t\t\t[0x%lx] %s\n", BIT(dword, 29),
+ n_index_value[BIT(dword, 29)]);
+ printf("AUD_CONFIG_B N_programming_enable\t\t\t%lu\n", BIT(dword, 28));
+ printf("AUD_CONFIG_B Upper_N_value\t\t\t\t0x%02lx\n", BITS(dword, 27, 20));
+ printf("AUD_CONFIG_B Lower_N_value\t\t\t\t0x%03lx\n", BITS(dword, 15, 4));
+ printf("AUD_CONFIG_B Pixel_Clock_HDMI\t\t\t\t[0x%lx] %s\n", BITS(dword, 19, 16),
+ OPNAME(pixel_clock, BITS(dword, 19, 16)));
+ printf("AUD_CONFIG_B Disable_NCTS\t\t\t\t%lu\n", BIT(dword, 3));
+ dword = INREG(AUD_CONFIG_C);
+ printf("AUD_CONFIG_C N_index_value\t\t\t\t[0x%lx] %s\n", BIT(dword, 29),
+ n_index_value[BIT(dword, 29)]);
+ printf("AUD_CONFIG_C N_programming_enable\t\t\t%lu\n", BIT(dword, 28));
+ printf("AUD_CONFIG_C Upper_N_value\t\t\t\t0x%02lx\n", BITS(dword, 27, 20));
+ printf("AUD_CONFIG_C Lower_N_value\t\t\t\t0x%03lx\n", BITS(dword, 15, 4));
+ printf("AUD_CONFIG_C Pixel_Clock_HDMI\t\t\t\t[0x%lx] %s\n", BITS(dword, 19, 16),
+ OPNAME(pixel_clock, BITS(dword, 19, 16)));
+ printf("AUD_CONFIG_C Disable_NCTS\t\t\t\t%lu\n", BIT(dword, 3));
+
+ dword = INREG(AUD_CTS_ENABLE_A);
+ printf("AUD_CTS_ENABLE_A Enable_CTS_or_M_programming\t\t%lu\n", BIT(dword, 20));
+ printf("AUD_CTS_ENABLE_A CTS_M value Index\t\t\t%s\n", BIT(dword, 21) ? "CTS" : "M");
+ printf("AUD_CTS_ENABLE_A CTS_programming\t\t\t%#lx\n", BITS(dword, 19, 0));
+ dword = INREG(AUD_CTS_ENABLE_B);
+ printf("AUD_CTS_ENABLE_B Enable_CTS_or_M_programming\t\t%lu\n", BIT(dword, 20));
+ printf("AUD_CTS_ENABLE_B CTS_M value Index\t\t\t%s\n", BIT(dword, 21) ? "CTS" : "M");
+ printf("AUD_CTS_ENABLE_B CTS_programming\t\t\t%#lx\n", BITS(dword, 19, 0));
+ dword = INREG(AUD_CTS_ENABLE_C);
+ printf("AUD_CTS_ENABLE_C Enable_CTS_or_M_programming\t\t%lu\n", BIT(dword, 20));
+ printf("AUD_CTS_ENABLE_C CTS_M value Index\t\t\t%s\n", BIT(dword, 21) ? "CTS" : "M");
+ printf("AUD_CTS_ENABLE_C CTS_programming\t\t\t%#lx\n", BITS(dword, 19, 0));
+
+ dword = INREG(AUD_MISC_CTRL_A);
+ printf("AUD_MISC_CTRL_A Sample_Fabrication_EN_bit\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_MISC_CTRL_A Sample_present_Disable\t\t\t%lu\n", BIT(dword, 8));
+ printf("AUD_MISC_CTRL_A Output_Delay\t\t\t\t%lu\n", BITS(dword, 7, 4));
+ printf("AUD_MISC_CTRL_A Pro_Allowed\t\t\t\t%lu\n", BIT(dword, 1));
+ dword = INREG(AUD_MISC_CTRL_B);
+ printf("AUD_MISC_CTRL_B Sample_Fabrication_EN_bit\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_MISC_CTRL_B Sample_present_Disable\t\t\t%lu\n", BIT(dword, 8));
+ printf("AUD_MISC_CTRL_B Output_Delay\t\t\t\t%lu\n", BITS(dword, 7, 4));
+ printf("AUD_MISC_CTRL_B Pro_Allowed\t\t\t\t%lu\n", BIT(dword, 1));
+ dword = INREG(AUD_MISC_CTRL_C);
+ printf("AUD_MISC_CTRL_C Sample_Fabrication_EN_bit\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_MISC_CTRL_C Sample_present_Disable\t\t\t%lu\n", BIT(dword, 8));
+ printf("AUD_MISC_CTRL_C Output_Delay\t\t\t\t%lu\n", BITS(dword, 7, 4));
+ printf("AUD_MISC_CTRL_C Pro_Allowed\t\t\t\t%lu\n", BIT(dword, 1));
+
+ dword = INREG(AUD_PWRST);
+ printf("AUD_PWRST Func_Grp_Dev_PwrSt_Curr \t%s\n", power_state[BITS(dword, 27, 26)]);
+ printf("AUD_PWRST Func_Grp_Dev_PwrSt_Set \t%s\n", power_state[BITS(dword, 25, 24)]);
+ printf("AUD_PWRST ConvertorA_Widget_Power_State_Current \t%s\n", power_state[BITS(dword, 15, 14)]);
+ printf("AUD_PWRST ConvertorA_Widget_Power_State_Requsted \t%s\n", power_state[BITS(dword, 13, 12)]);
+ printf("AUD_PWRST ConvertorB_Widget_Power_State_Current \t%s\n", power_state[BITS(dword, 19, 18)]);
+ printf("AUD_PWRST ConvertorB_Widget_Power_State_Requested \t%s\n", power_state[BITS(dword, 17, 16)]);
+ printf("AUD_PWRST ConvC_Widget_PwrSt_Curr \t%s\n", power_state[BITS(dword, 23, 22)]);
+ printf("AUD_PWRST ConvC_Widget_PwrSt_Req \t%s\n", power_state[BITS(dword, 21, 20)]);
+ printf("AUD_PWRST PinB_Widget_Power_State_Current \t%s\n", power_state[BITS(dword, 3, 2)]);
+ printf("AUD_PWRST PinB_Widget_Power_State_Set \t%s\n", power_state[BITS(dword, 1, 0)]);
+ printf("AUD_PWRST PinC_Widget_Power_State_Current \t%s\n", power_state[BITS(dword, 7, 6)]);
+ printf("AUD_PWRST PinC_Widget_Power_State_Set \t%s\n", power_state[BITS(dword, 5, 4)]);
+ printf("AUD_PWRST PinD_Widget_Power_State_Current \t%s\n", power_state[BITS(dword, 11, 10)]);
+ printf("AUD_PWRST PinD_Widget_Power_State_Set \t%s\n", power_state[BITS(dword, 9, 8)]);
+
+ dword = INREG(AUD_PORT_EN_HD_CFG);
+ printf("AUD_PORT_EN_HD_CFG Convertor_A_Digen\t\t\t%lu\n", BIT(dword, 0));
+ printf("AUD_PORT_EN_HD_CFG Convertor_B_Digen\t\t\t%lu\n", BIT(dword, 1));
+ printf("AUD_PORT_EN_HD_CFG Convertor_C_Digen\t\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_PORT_EN_HD_CFG ConvertorA_Stream_ID\t\t%lu\n", BITS(dword, 7, 4));
+ printf("AUD_PORT_EN_HD_CFG ConvertorB_Stream_ID\t\t%lu\n", BITS(dword, 11, 8));
+ printf("AUD_PORT_EN_HD_CFG ConvertorC_Stream_ID\t\t%lu\n", BITS(dword, 15, 12));
+ printf("AUD_PORT_EN_HD_CFG Port_B_Out_Enable\t\t\t%lu\n", BIT(dword, 16));
+ printf("AUD_PORT_EN_HD_CFG Port_C_Out_Enable\t\t\t%lu\n", BIT(dword, 17));
+ printf("AUD_PORT_EN_HD_CFG Port_D_Out_Enable\t\t\t%lu\n", BIT(dword, 18));
+ printf("AUD_PORT_EN_HD_CFG Port_B_Amp_Mute_Status\t\t%lu\n", BIT(dword, 20));
+ printf("AUD_PORT_EN_HD_CFG Port_C_Amp_Mute_Status\t\t%lu\n", BIT(dword, 21));
+ printf("AUD_PORT_EN_HD_CFG Port_D_Amp_Mute_Status\t\t%lu\n", BIT(dword, 22));
+
+ dword = INREG(AUD_OUT_DIG_CNVT_A);
+ printf("AUD_OUT_DIG_CNVT_A V\t\t\t\t\t%lu\n", BIT(dword, 1));
+ printf("AUD_OUT_DIG_CNVT_A VCFG\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_OUT_DIG_CNVT_A PRE\t\t\t\t\t%lu\n", BIT(dword, 3));
+ printf("AUD_OUT_DIG_CNVT_A Copy\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_OUT_DIG_CNVT_A NonAudio\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("AUD_OUT_DIG_CNVT_A PRO\t\t\t\t\t%lu\n", BIT(dword, 6));
+ printf("AUD_OUT_DIG_CNVT_A Level\t\t\t\t%lu\n", BIT(dword, 7));
+ printf("AUD_OUT_DIG_CNVT_A Category_Code\t\t\t%lu\n", BITS(dword, 14, 8));
+ printf("AUD_OUT_DIG_CNVT_A Lowest_Channel_Number\t\t%lu\n",BITS(dword, 19, 16));
+ printf("AUD_OUT_DIG_CNVT_A Stream_ID\t\t\t\t%lu\n", BITS(dword, 23, 20));
+
+ dword = INREG(AUD_OUT_DIG_CNVT_B);
+ printf("AUD_OUT_DIG_CNVT_B V\t\t\t\t\t%lu\n", BIT(dword, 1));
+ printf("AUD_OUT_DIG_CNVT_B VCFG\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_OUT_DIG_CNVT_B PRE\t\t\t\t\t%lu\n", BIT(dword, 3));
+ printf("AUD_OUT_DIG_CNVT_B Copy\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_OUT_DIG_CNVT_B NonAudio\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("AUD_OUT_DIG_CNVT_B PRO\t\t\t\t\t%lu\n", BIT(dword, 6));
+ printf("AUD_OUT_DIG_CNVT_B Level\t\t\t\t%lu\n", BIT(dword, 7));
+ printf("AUD_OUT_DIG_CNVT_B Category_Code\t\t\t%lu\n", BITS(dword, 14, 8));
+ printf("AUD_OUT_DIG_CNVT_B Lowest_Channel_Number\t\t%lu\n",BITS(dword, 19, 16));
+ printf("AUD_OUT_DIG_CNVT_B Stream_ID\t\t\t\t%lu\n", BITS(dword, 23, 20));
+
+ dword = INREG(AUD_OUT_DIG_CNVT_C);
+ printf("AUD_OUT_DIG_CNVT_C V\t\t\t\t\t%lu\n", BIT(dword, 1));
+ printf("AUD_OUT_DIG_CNVT_C VCFG\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_OUT_DIG_CNVT_C PRE\t\t\t\t\t%lu\n", BIT(dword, 3));
+ printf("AUD_OUT_DIG_CNVT_C Copy\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_OUT_DIG_CNVT_C NonAudio\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("AUD_OUT_DIG_CNVT_C PRO\t\t\t\t\t%lu\n", BIT(dword, 6));
+ printf("AUD_OUT_DIG_CNVT_C Level\t\t\t\t%lu\n", BIT(dword, 7));
+ printf("AUD_OUT_DIG_CNVT_C Category_Code\t\t\t%lu\n", BITS(dword, 14, 8));
+ printf("AUD_OUT_DIG_CNVT_C Lowest_Channel_Number\t\t%lu\n",BITS(dword, 19, 16));
+ printf("AUD_OUT_DIG_CNVT_C Stream_ID\t\t\t\t%lu\n", BITS(dword, 23, 20));
+
+ printf("AUD_OUT_CH_STR Converter_Channel_MAP PORTB PORTC PORTD\n");
+ for (i = 0; i < 8; i++) {
+ OUTREG(AUD_OUT_CH_STR, i | (i << 8) | (i << 16));
+ dword = INREG(AUD_OUT_CH_STR);
+ printf("\t\t\t\t%lu\t%lu\t%lu\t%lu\n",
+ 1 + BITS(dword, 3, 0),
+ 1 + BITS(dword, 7, 4),
+ 1 + BITS(dword, 15, 12),
+ 1 + BITS(dword, 23, 20));
+ }
+
+ dword = INREG(AUD_OUT_STR_DESC_A);
+ printf("AUD_OUT_STR_DESC_A HBR_enable\t\t\t\t%lu\n", BITS(dword, 28, 27));
+ printf("AUD_OUT_STR_DESC_A Convertor_Channel_Count\t\t%lu\n", BITS(dword, 20, 16) + 1);
+ printf("AUD_OUT_STR_DESC_A Bits_per_Sample\t\t\t[%#lx] %s\n",
+ BITS(dword, 6, 4), OPNAME(bits_per_sample, BITS(dword, 6, 4)));
+ printf("AUD_OUT_STR_DESC_A Number_of_Channels_in_a_Stream\t%lu\n", 1 + BITS(dword, 3, 0));
+
+ dword = INREG(AUD_OUT_STR_DESC_B);
+ printf("AUD_OUT_STR_DESC_B HBR_enable\t\t\t\t%lu\n", BITS(dword, 28, 27));
+ printf("AUD_OUT_STR_DESC_B Convertor_Channel_Count\t\t%lu\n", BITS(dword, 20, 16) + 1);
+ printf("AUD_OUT_STR_DESC_B Bits_per_Sample\t\t\t[%#lx] %s\n",
+ BITS(dword, 6, 4), OPNAME(bits_per_sample, BITS(dword, 6, 4)));
+ printf("AUD_OUT_STR_DESC_B Number_of_Channels_in_a_Stream\t%lu\n", 1 + BITS(dword, 3, 0));
+
+ dword = INREG(AUD_OUT_STR_DESC_C);
+ printf("AUD_OUT_STR_DESC_C HBR_enable\t\t\t\t%lu\n", BITS(dword, 28, 27));
+ printf("AUD_OUT_STR_DESC_C Convertor_Channel_Count\t\t%lu\n", BITS(dword, 20, 16) + 1);
+ printf("AUD_OUT_STR_DESC_C Bits_per_Sample\t\t\t[%#lx] %s\n",
+ BITS(dword, 6, 4), OPNAME(bits_per_sample, BITS(dword, 6, 4)));
+ printf("AUD_OUT_STR_DESC_C Number_of_Channels_in_a_Stream\t%lu\n", 1 + BITS(dword, 3, 0));
+
+ dword = INREG(AUD_PINW_CONNLNG_SEL);
+ printf("AUD_PINW_CONNLNG_SEL Connection_select_Control_B\t%#lx\n", BITS(dword, 7, 0));
+ printf("AUD_PINW_CONNLNG_SEL Connection_select_Control_C\t%#lx\n", BITS(dword, 15, 8));
+ printf("AUD_PINW_CONNLNG_SEL Connection_select_Control_D\t%#lx\n", BITS(dword, 23, 16));
+
+ dword = INREG(AUD_CNTL_ST_A);
+ printf("AUD_CNTL_ST_A DIP_Port_Select\t\t\t\t[%#lx] %s\n",
+ BITS(dword, 30, 29), dip_port[BITS(dword, 30, 29)]);
+ printf("AUD_CNTL_ST_A DIP_type_enable_status Audio DIP\t\t%lu\n", BIT(dword, 21));
+ printf("AUD_CNTL_ST_A DIP_type_enable_status ACP DIP\t\t%lu\n", BIT(dword, 22));
+ printf("AUD_CNTL_ST_A DIP_type_enable_status Generic 2 DIP\t%lu\n", BIT(dword, 23));
+ printf("AUD_CNTL_ST_A DIP_transmission_frequency\t\t[0x%lx] %s\n",
+ BITS(dword, 17, 16), dip_trans[BITS(dword, 17, 16)]);
+ printf("AUD_CNTL_ST_A ELD_ACK\t\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_CNTL_ST_A ELD_buffer_size\t\t\t\t%lu\n", BITS(dword, 14, 10));
+
+ dword = INREG(AUD_CNTL_ST_B);
+ printf("AUD_CNTL_ST_B DIP_Port_Select\t\t\t\t[%#lx] %s\n",
+ BITS(dword, 30, 29), dip_port[BITS(dword, 30, 29)]);
+ printf("AUD_CNTL_ST_B DIP_type_enable_status Audio DIP\t\t%lu\n", BIT(dword, 21));
+ printf("AUD_CNTL_ST_B DIP_type_enable_status ACP DIP\t\t%lu\n", BIT(dword, 22));
+ printf("AUD_CNTL_ST_B DIP_type_enable_status Generic 2 DIP\t%lu\n", BIT(dword, 23));
+ printf("AUD_CNTL_ST_B DIP_transmission_frequency\t\t[0x%lx] %s\n",
+ BITS(dword, 17, 16), dip_trans[BITS(dword, 17, 16)]);
+ printf("AUD_CNTL_ST_B ELD_ACK\t\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_CNTL_ST_B ELD_buffer_size\t\t\t\t%lu\n", BITS(dword, 14, 10));
+
+ dword = INREG(AUD_CNTL_ST_C);
+ printf("AUD_CNTL_ST_C DIP_Port_Select\t\t\t\t[%#lx] %s\n",
+ BITS(dword, 30, 29), dip_port[BITS(dword, 30, 29)]);
+ printf("AUD_CNTL_ST_C DIP_type_enable_status Audio DIP\t\t%lu\n", BIT(dword, 21));
+ printf("AUD_CNTL_ST_C DIP_type_enable_status ACP DIP\t\t%lu\n", BIT(dword, 22));
+ printf("AUD_CNTL_ST_C DIP_type_enable_status Generic 2 DIP\t%lu\n", BIT(dword, 23));
+ printf("AUD_CNTL_ST_C DIP_transmission_frequency\t\t[0x%lx] %s\n",
+ BITS(dword, 17, 16), dip_trans[BITS(dword, 17, 16)]);
+ printf("AUD_CNTL_ST_C ELD_ACK\t\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_CNTL_ST_C ELD_buffer_size\t\t\t\t%lu\n", BITS(dword, 14, 10));
+
+ dword = INREG(AUD_CNTRL_ST2);
+ printf("AUD_CNTRL_ST2 CP_ReadyB\t\t\t\t%lu\n", BIT(dword, 1));
+ printf("AUD_CNTRL_ST2 ELD_validB\t\t\t\t%lu\n", BIT(dword, 0));
+ printf("AUD_CNTRL_ST2 CP_ReadyC\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("AUD_CNTRL_ST2 ELD_validC\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_CNTRL_ST2 CP_ReadyD\t\t\t\t%lu\n", BIT(dword, 9));
+ printf("AUD_CNTRL_ST2 ELD_validD\t\t\t\t%lu\n", BIT(dword, 8));
+
+ dword = INREG(AUD_CNTRL_ST3);
+ printf("AUD_CNTRL_ST3 TransA_DPT_Audio_Output_En\t\t%lu\n", BIT(dword, 3));
+ printf("AUD_CNTRL_ST3 TransA_to_Port_Sel\t\t\t[%#lx] %s\n",
+ BITS(dword, 2, 0), trans_to_port_sel[BITS(dword, 2, 0)]);
+ printf("AUD_CNTRL_ST3 TransB_DPT_Audio_Output_En\t\t%lu\n", BIT(dword, 7));
+ printf("AUD_CNTRL_ST3 TransB_to_Port_Sel\t\t\t[%#lx] %s\n",
+ BITS(dword, 6, 4), trans_to_port_sel[BITS(dword, 6, 4)]);
+ printf("AUD_CNTRL_ST3 TransC_DPT_Audio_Output_En\t\t%lu\n", BIT(dword, 11));
+ printf("AUD_CNTRL_ST3 TransC_to_Port_Sel\t\t\t[%#lx] %s\n",
+ BITS(dword, 10, 8), trans_to_port_sel[BITS(dword, 10, 8)]);
+
+ dword = INREG(AUD_HDMIW_STATUS);
+ printf("AUD_HDMIW_STATUS Conv_A_CDCLK/DOTCLK_FIFO_Underrun\t%lu\n", BIT(dword, 27));
+ printf("AUD_HDMIW_STATUS Conv_A_CDCLK/DOTCLK_FIFO_Overrun\t%lu\n", BIT(dword, 26));
+ printf("AUD_HDMIW_STATUS Conv_B_CDCLK/DOTCLK_FIFO_Underrun\t%lu\n", BIT(dword, 29));
+ printf("AUD_HDMIW_STATUS Conv_B_CDCLK/DOTCLK_FIFO_Overrun\t%lu\n", BIT(dword, 28));
+ printf("AUD_HDMIW_STATUS Conv_C_CDCLK/DOTCLK_FIFO_Underrun\t%lu\n", BIT(dword, 31));
+ printf("AUD_HDMIW_STATUS Conv_C_CDCLK/DOTCLK_FIFO_Overrun\t%lu\n", BIT(dword, 30));
+ printf("AUD_HDMIW_STATUS BCLK/CDCLK_FIFO_Overrun\t\t%lu\n", BIT(dword, 25));
+ printf("AUD_HDMIW_STATUS Function_Reset\t\t\t%lu\n", BIT(dword, 24));
+
+ printf("AUD_HDMIW_HDMIEDID_A HDMI ELD:\n\t");
+ dword = INREG(AUD_CNTL_ST_A);
+ dword &= ~BITMASK(9, 5);
+ OUTREG(AUD_CNTL_ST_A, dword);
+ for (i = 0; i < BITS(dword, 14, 10) / 4; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_HDMIEDID_A)));
+ printf("\n");
+
+ printf("AUD_HDMIW_HDMIEDID_B HDMI ELD:\n\t");
+ dword = INREG(AUD_CNTL_ST_B);
+ dword &= ~BITMASK(9, 5);
+ OUTREG(AUD_CNTL_ST_B, dword);
+ for (i = 0; i < BITS(dword, 14, 10) / 4; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_HDMIEDID_B)));
+ printf("\n");
+
+ printf("AUD_HDMIW_HDMIEDID_C HDMI ELD:\n\t");
+ dword = INREG(AUD_CNTL_ST_C);
+ dword &= ~BITMASK(9, 5);
+ OUTREG(AUD_CNTL_ST_C, dword);
+ for (i = 0; i < BITS(dword, 14, 10) / 4; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_HDMIEDID_C)));
+ printf("\n");
+
+ printf("AUD_HDMIW_INFOFR_A HDMI audio Infoframe:\n\t");
+ dword = INREG(AUD_CNTL_ST_A);
+ dword &= ~BITMASK(20, 18);
+ dword &= ~BITMASK(3, 0);
+ OUTREG(AUD_CNTL_ST_A, dword);
+ for (i = 0; i < 8; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_INFOFR_A)));
+ printf("\n");
+
+ printf("AUD_HDMIW_INFOFR_B HDMI audio Infoframe:\n\t");
+ dword = INREG(AUD_CNTL_ST_B);
+ dword &= ~BITMASK(20, 18);
+ dword &= ~BITMASK(3, 0);
+ OUTREG(AUD_CNTL_ST_B, dword);
+ for (i = 0; i < 8; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_INFOFR_B)));
+ printf("\n");
+
+ printf("AUD_HDMIW_INFOFR_C HDMI audio Infoframe:\n\t");
+ dword = INREG(AUD_CNTL_ST_C);
+ dword &= ~BITMASK(20, 18);
+ dword &= ~BITMASK(3, 0);
+ OUTREG(AUD_CNTL_ST_C, dword);
+ for (i = 0; i < 8; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_INFOFR_C)));
+ printf("\n");
+
+}
+
+#undef AUD_CONFIG_A
+#undef AUD_MISC_CTRL_A
+#undef AUD_VID_DID
+#undef AUD_RID
+#undef AUD_CTS_ENABLE_A
+#undef AUD_PWRST
+#undef AUD_HDMIW_HDMIEDID_A
+#undef AUD_HDMIW_INFOFR_A
+#undef AUD_PORT_EN_HD_CFG
+#undef AUD_OUT_DIG_CNVT_A
+#undef AUD_OUT_STR_DESC_A
+#undef AUD_OUT_CH_STR
+#undef AUD_PINW_CONNLNG_LIST
+#undef AUD_CNTL_ST_A
+#undef AUD_HDMIW_STATUS
+#undef AUD_CONFIG_B
+#undef AUD_MISC_CTRL_B
+#undef AUD_CTS_ENABLE_B
+#undef AUD_HDMIW_HDMIEDID_B
+#undef AUD_HDMIW_INFOFR_B
+#undef AUD_OUT_DIG_CNVT_B
+#undef AUD_OUT_STR_DESC_B
+#undef AUD_CNTL_ST_B
+#undef AUD_CONFIG_C
+#undef AUD_MISC_CTRL_C
+#undef AUD_CTS_ENABLE_C
+#undef AUD_HDMIW_HDMIEDID_C
+#undef AUD_HDMIW_INFOFR_C
+#undef AUD_OUT_DIG_CNVT_C
+#undef AUD_OUT_STR_DESC_C
+
+#undef VIDEO_DIP_CTL_A
+#undef VIDEO_DIP_CTL_B
+#undef VIDEO_DIP_CTL_C
+#undef VIDEO_DIP_CTL_D
+#undef VIDEO_DIP_DATA
+
+/*
+ * Haswell registers
+ */
+
+/* DisplayPort Transport Control */
+#define DP_TP_CTL_A 0x64040
+#define DP_TP_CTL_B 0x64140
+#define DP_TP_CTL_C 0x64240
+#define DP_TP_CTL_D 0x64340
+#define DP_TP_CTL_E 0x64440
+
+/* DisplayPort Transport Status */
+#define DP_TP_ST_A 0x64044
+#define DP_TP_ST_B 0x64144
+#define DP_TP_ST_C 0x64244
+#define DP_TP_ST_D 0x64344
+#define DP_TP_ST_E 0x64444
+
+/* Transcoder configuration */
+#define TRANS_CONF_A 0xF0008
+#define TRANS_CONF_B 0xF1008
+#define TRANS_CONF_C 0xF2008
+
+/* DDI Buffer Control */
+#define DDI_BUF_CTL_A 0x64000
+#define DDI_BUF_CTL_B 0x64100
+#define DDI_BUF_CTL_C 0x64200
+#define DDI_BUF_CTL_D 0x64300
+#define DDI_BUF_CTL_E 0x64400
+
+/* DDI Buffer Translation */
+#define DDI_BUF_TRANS_A 0x64e00
+#define DDI_BUF_TRANS_B 0x64e60
+#define DDI_BUF_TRANS_C 0x64ec0
+#define DDI_BUF_TRANS_D 0x64f20
+#define DDI_BUF_TRANS_E 0x64f80
+
+/* DDI Aux Channel */
+#define DDI_AUX_CHANNEL_CTRL 0x64010
+#define DDI_AUX_DATA 0x64014
+#define DDI_AUX_TST 0x64028
+
+/* DDI CRC Control */
+#define DDI_CRC_CTL_A 0x64050
+#define DDI_CRC_CTL_B 0x64150
+#define DDI_CRC_CTL_C 0x64250
+#define DDI_CRC_CTL_D 0x64350
+#define DDI_CRC_CTL_E 0x64450
+
+/* Pipe DDI Function Control */
+#define PIPE_DDI_FUNC_CTL_A 0x60400
+#define PIPE_DDI_FUNC_CTL_B 0x61400
+#define PIPE_DDI_FUNC_CTL_C 0x62400
+#define PIPE_DDI_FUNC_CTL_EDP 0x6F400
+
+/* Pipe Configuration */
+#define PIPE_CONF_A 0x70008
+#define PIPE_CONF_B 0x71008
+#define PIPE_CONF_C 0x72008
+#define PIPE_CONF_EDP 0x7F008
+
+/* Audio registers */
+#define AUD_CONFIG_A 0x65000
+#define AUD_MISC_CTRL_A 0x65010
+#define AUD_VID_DID 0x65020
+#define AUD_RID 0x65024
+#define AUD_CTS_ENABLE_A 0x65028
+#define AUD_PWRST 0x6504C
+#define AUD_HDMIW_HDMIEDID_A 0x65050
+#define AUD_HDMIW_INFOFR_A 0x65054
+#define AUD_PORT_EN_HD_CFG 0x6507C
+#define AUD_OUT_DIG_CNVT_A 0x65080
+#define AUD_OUT_STR_DESC_A 0x65084
+#define AUD_OUT_CHAN_MAP 0x65088
+#define AUD_PINW_CONNLNG_LIST_A 0x650A8
+#define AUD_PINW_CONNLNG_LIST_B 0x651A8
+#define AUD_PINW_CONNLNG_LIST_C 0x652A8
+#define AUD_PIPE_CONN_SEL_CTRL 0x650AC
+#define AUD_PIN_ELD_CP_VLD 0x650C0
+#define AUD_HDMIW_STATUS 0x650D4
+#define AUD_CONFIG_B 0x65100
+#define AUD_MISC_CTRL_B 0x65110
+#define AUD_CTS_ENABLE_B 0x65128
+#define AUD_HDMIW_HDMIEDID_B 0x65150
+#define AUD_HDMIW_INFOFR_B 0x65154
+#define AUD_OUT_DIG_CNVT_B 0x65180
+#define AUD_OUT_STR_DESC_B 0x65184
+#define AUD_CONFIG_C 0x65200
+#define AUD_MISC_CTRL_C 0x65210
+#define AUD_CTS_ENABLE_C 0x65228
+#define AUD_HDMIW_HDMIEDID_C 0x65250
+#define AUD_HDMIW_INFOFR_C 0x65254
+#define AUD_OUT_DIG_CNVT_C 0x65280
+#define AUD_OUT_STR_DESC_C 0x65284
+#define AUD_DIP_ELD_CTRL_ST_A 0x650b4
+#define AUD_DIP_ELD_CTRL_ST_B 0x651b4
+#define AUD_DIP_ELD_CTRL_ST_C 0x652b4
+
+/* Video DIP Control */
+#define VIDEO_DIP_CTL_A 0x60200
+#define VIDEO_DIP_CTL_B 0x61200
+#define VIDEO_DIP_CTL_C 0x62200
+#define VIDEO_DIP_CTL_D 0x63200
+
+#define VIDEO_DIP_DATA 0x60220
+#define VIDEO_DIP_ECC 0x60240
+
+#define AUD_DP_DIP_STATUS 0x65f20
+
+
+static void dump_hsw(void)
+{
+ uint32_t dword;
+ int i;
+
+ /* HSW DDI Buffer */
+ dump_reg(DDI_BUF_CTL_A, "DDI Buffer Controler A");
+ dump_reg(DDI_BUF_CTL_B, "DDI Buffer Controler B");
+ dump_reg(DDI_BUF_CTL_C, "DDI Buffer Controler C");
+ dump_reg(DDI_BUF_CTL_D, "DDI Buffer Controler D");
+ dump_reg(DDI_BUF_CTL_E, "DDI Buffer Controler E");
+
+ /* HSW Pipe Function */
+ dump_reg(PIPE_CONF_A, "PIPE Configuration A");
+ dump_reg(PIPE_CONF_B, "PIPE Configuration B");
+ dump_reg(PIPE_CONF_C, "PIPE Configuration C");
+ dump_reg(PIPE_CONF_EDP, "PIPE Configuration EDP");
+
+ dump_reg(PIPE_DDI_FUNC_CTL_A, "PIPE DDI Function Control A");
+ dump_reg(PIPE_DDI_FUNC_CTL_B, "PIPE DDI Function Control B");
+ dump_reg(PIPE_DDI_FUNC_CTL_C, "PIPE DDI Function Control C");
+ dump_reg(PIPE_DDI_FUNC_CTL_EDP, "PIPE DDI Function Control EDP");
+
+ /* HSW Display port */
+ dump_reg(DP_TP_CTL_A, "DisplayPort Transport A Control");
+ dump_reg(DP_TP_CTL_B, "DisplayPort Transport B Control");
+ dump_reg(DP_TP_CTL_C, "DisplayPort Transport C Control");
+ dump_reg(DP_TP_CTL_D, "DisplayPort Transport D Control");
+ dump_reg(DP_TP_CTL_E, "DisplayPort Transport E Control");
+
+ dump_reg(DP_TP_ST_A, "DisplayPort Transport A Status");
+ dump_reg(DP_TP_ST_B, "DisplayPort Transport B Status");
+ dump_reg(DP_TP_ST_C, "DisplayPort Transport C Status");
+ dump_reg(DP_TP_ST_D, "DisplayPort Transport D Status");
+ dump_reg(DP_TP_ST_E, "DisplayPort Transport E Status");
+
+ /* HSW Transcoder A configuration */
+ dump_reg(TRANS_CONF_A, "Transcoder A Configuration");
+ dump_reg(TRANS_CONF_B, "Transcoder B Configuration");
+ dump_reg(TRANS_CONF_C, "Transcoder C Configuration");
+
+ /* HSW North Display Audio */
+ dump_reg(AUD_CONFIG_A, "Audio Configuration - Transcoder A");
+ dump_reg(AUD_CONFIG_B, "Audio Configuration - Transcoder B");
+ dump_reg(AUD_CONFIG_C, "Audio Configuration - Transcoder C");
+ dump_reg(AUD_MISC_CTRL_A, "Audio MISC Control for Transcoder A");
+ dump_reg(AUD_MISC_CTRL_B, "Audio MISC Control for Transcoder B");
+ dump_reg(AUD_MISC_CTRL_C, "Audio MISC Control for Transcoder C");
+ dump_reg(AUD_VID_DID, "Audio Vendor ID / Device ID");
+ dump_reg(AUD_RID, "Audio Revision ID");
+ dump_reg(AUD_CTS_ENABLE_A, "Audio CTS Programming Enable - Transcoder A");
+ dump_reg(AUD_CTS_ENABLE_B, "Audio CTS Programming Enable - Transcoder B");
+ dump_reg(AUD_CTS_ENABLE_C, "Audio CTS Programming Enable - Transcoder C");
+ dump_reg(AUD_PWRST, "Audio Power State (Function Group, Convertor, Pin Widget)");
+ dump_reg(AUD_HDMIW_HDMIEDID_A, "HDMI Data EDID Block - Transcoder A");
+ dump_reg(AUD_HDMIW_HDMIEDID_B, "HDMI Data EDID Block - Transcoder B");
+ dump_reg(AUD_HDMIW_HDMIEDID_C, "HDMI Data EDID Block - Transcoder C");
+ dump_reg(AUD_HDMIW_INFOFR_A, "Audio Widget Data Island Packet - Transcoder A");
+ dump_reg(AUD_HDMIW_INFOFR_B, "Audio Widget Data Island Packet - Transcoder B");
+ dump_reg(AUD_HDMIW_INFOFR_C, "Audio Widget Data Island Packet - Transcoder C");
+
+ dump_reg(AUD_PORT_EN_HD_CFG, "Audio Pipe and Convert Configs");
+ dump_reg(AUD_OUT_DIG_CNVT_A, "Audio Digital Converter - Conv A");
+ dump_reg(AUD_OUT_DIG_CNVT_B, "Audio Digital Converter - Conv B");
+ dump_reg(AUD_OUT_DIG_CNVT_C, "Audio Digital Converter - Conv C");
+ dump_reg(AUD_OUT_CHAN_MAP, "Audio Output Channel Mapping");
+ dump_reg(AUD_OUT_STR_DESC_A, "Audio Stream Descriptor Format - Conv A");
+ dump_reg(AUD_OUT_STR_DESC_B, "Audio Stream Descriptor Format - Conv B");
+ dump_reg(AUD_OUT_STR_DESC_C, "Audio Stream Descriptor Format - Conv C");
+ dump_reg(AUD_PINW_CONNLNG_LIST_A, "Audio Connection List entry and Length - Transcoder A");
+ dump_reg(AUD_PINW_CONNLNG_LIST_B, "Audio Connection List entry and Length - Transcoder B");
+ dump_reg(AUD_PINW_CONNLNG_LIST_C, "Audio Connection List entry and Length - Transcoder C");
+ dump_reg(AUD_PIPE_CONN_SEL_CTRL, "Audio Pipe Connection Select Control");
+ dump_reg(AUD_DIP_ELD_CTRL_ST_A, "Audio DIP and ELD control state - Transcoder A");
+ dump_reg(AUD_DIP_ELD_CTRL_ST_B, "Audio DIP and ELD control state - Transcoder B");
+ dump_reg(AUD_DIP_ELD_CTRL_ST_C, "Audio DIP and ELD control state - Transcoder C");
+ dump_reg(AUD_PIN_ELD_CP_VLD, "audio pin eld valid status");
+ dump_reg(AUD_HDMIW_STATUS, "Audio HDMI FIFO Status");
+
+ printf("\nDetails:\n\n");
+
+ dword = INREG(AUD_VID_DID);
+ printf("AUD_VID_DID vendor id\t\t\t\t\t0x%x\n", dword >> 16);
+ printf("AUD_VID_DID device id\t\t\t\t\t0x%x\n", dword & 0xffff);
+
+ dword = INREG(AUD_RID);
+ printf("AUD_RID Major_Revision\t\t\t\t\t0x%lx\n", BITS(dword, 23, 20));
+ printf("AUD_RID Minor_Revision\t\t\t\t\t0x%lx\n", BITS(dword, 19, 16));
+ printf("AUD_RID Revision_Id\t\t\t\t\t0x%lx\n", BITS(dword, 15, 8));
+ printf("AUD_RID Stepping_Id\t\t\t\t\t0x%lx\n", BITS(dword, 7, 0));
+
+ dword = INREG(AUD_DIP_ELD_CTRL_ST_A);
+ printf("Audio DIP and ELD control state for TranscoderA\n");
+ printf("Audio DIP port select\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 30, 29), dip_port[BITS(dword, 30, 29)]);
+
+ printf("Audio DIP type enable status\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 24, 21), dip_type[BIT(dword, 21)]);
+
+ printf("DIP Buffer Index \t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 20, 18), dip_index[BITS(dword, 20, 18)]);
+ printf("DIP_transmission_frequency\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 17, 16), dip_trans[BITS(dword, 17, 16)]);
+ printf("ELD_ACK\t\t\t\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("ELD_buffer_size\t\t\t\t\t\t%lu\n", BITS(dword, 14, 10));
+
+ dword = INREG(AUD_DIP_ELD_CTRL_ST_B);
+ printf("Audio DIP and ELD control state for TranscoderB\n");
+ printf("Audio DIP port select\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 30, 29), dip_port[BITS(dword, 30, 29)]);
+
+ printf("Audio DIP type enable status\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 24, 21), dip_type[BIT(dword, 21)]);
+
+ printf("DIP Buffer Index \t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 20, 18), dip_index[BITS(dword, 20, 18)]);
+ printf("DIP_transmission_frequency\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 17, 16), dip_trans[BITS(dword, 17, 16)]);
+ printf("ELD_ACK\t\t\t\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("ELD_buffer_size\t\t\t\t\t\t%lu\n", BITS(dword, 14, 10));
+
+ dword = INREG(AUD_DIP_ELD_CTRL_ST_C);
+ printf("Audio DIP and ELD control state for TranscoderC\n");
+ printf("Audio DIP port select\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 30, 29), dip_port[BITS(dword, 30, 29)]);
+
+ printf("Audio DIP type enable status\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 24, 21), dip_type[BIT(dword, 21)]);
+
+ printf("DIP Buffer Index \t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 20, 18), dip_index[BITS(dword, 20, 18)]);
+ printf("DIP_transmission_frequency\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 17, 16), dip_trans[BITS(dword, 17, 16)]);
+ printf("ELD_ACK\t\t\t\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("ELD_buffer_size\t\t\t\t\t\t%lu\n", BITS(dword, 14, 10));
+
+ dword = INREG(DDI_BUF_CTL_A);
+ printf("DDI A Buffer control\n");
+ printf("DDI Buffer Enable\t\t\t\t\t%ld\n", BIT(dword, 31));
+ printf("DP port width\t\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 3, 1), dp_port_width[BITS(dword, 3, 1)]);
+ dword = INREG(DDI_BUF_CTL_B);
+ printf("DDI B Buffer control\n");
+ printf("DDI Buffer Enable\t\t\t\t\t%ld\n", BIT(dword, 31));
+ printf("DP port width\t\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 3, 1), dp_port_width[BITS(dword, 3, 1)]);
+ dword = INREG(DDI_BUF_CTL_C);
+ printf("DDI C Buffer control\n");
+ printf("DDI Buffer Enable\t\t\t\t\t%ld\n", BIT(dword, 31));
+ printf("DP port width\t\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 3, 1), dp_port_width[BITS(dword, 3, 1)]);
+ dword = INREG(DDI_BUF_CTL_D);
+ printf("DDI D Buffer control\n");
+ printf("DDI Buffer Enable\t\t\t\t\t%ld\n", BIT(dword, 31));
+ printf("DP port width\t\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 3, 1), dp_port_width[BITS(dword, 3, 1)]);
+ dword = INREG(DDI_BUF_CTL_E);
+ printf("DDI E Buffer control\n");
+ printf("DDI Buffer Enable\t\t\t\t\t%ld\n", BIT(dword, 31));
+ printf("DP port width\t\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 3, 1), dp_port_width[BITS(dword, 3, 1)]);
+
+ dword = INREG(PIPE_DDI_FUNC_CTL_A);
+ printf("Pipe A DDI Function Control\n");
+ printf("PIPE DDI Function Enable\t\t\t\t[0x%lx]\n", BIT(dword, 31));
+ printf("PIPE DDI selection\t\t\t\t\t[0x%lx] %s\n", BITS(dword, 30, 28),
+ trans_to_port_sel[BITS(dword, 30, 28)]);
+ printf("PIPE DDI Mode\t\t\t\t\t\t[0x%lx] %s\n", BITS(dword, 26, 24), ddi_mode[BITS(dword, 26, 24)]);
+ printf("BITS per color\t\t\t\t\t\t[0x%lx]\n", BITS(dword, 22, 20));
+
+ dword = INREG(PIPE_DDI_FUNC_CTL_B);
+ printf("Pipe B DDI Function Control\n");
+ printf("PIPE DDI Function Enable\t\t\t\t[0x%lx]\n", BIT(dword, 31));
+ printf("PIPE DDI selection\t\t\t\t\t[0x%lx] %s\n", BITS(dword, 30, 28),
+ trans_to_port_sel[BITS(dword, 30, 28)]);
+ printf("PIPE DDI Mode \t\t\t\t\t\t[0x%lx] %s\n", BITS(dword, 26, 24), ddi_mode[BITS(dword, 26, 24)]);
+ printf("BITS per color\t\t\t\t\t\t[0x%lx]\n", BITS(dword, 22, 20));
+
+ dword = INREG(PIPE_DDI_FUNC_CTL_C);
+ printf("Pipe C DDI Function Control\n");
+ printf("PIPE DDI Function Enable\t\t\t\t[0x%lx]\n", BIT(dword, 31));
+ printf("PIPE DDI selection\t\t\t\t\t[0x%lx] %s\n", BITS(dword, 30, 28),
+ trans_to_port_sel[BITS(dword, 30, 28)]);
+ printf("PIPE DDI Mode \t\t\t\t\t\t[0x%lx] %s\n", BITS(dword, 26, 24), ddi_mode[BITS(dword, 26, 24)]);
+ printf("BITS per color\t\t\t\t\t\t[0x%lx]\n", BITS(dword, 22, 20));
+
+ dword = INREG(AUD_CONFIG_A);
+ printf("AUD_CONFIG_A N_index_value\t\t\t\t[0x%lx] %s\n", BIT(dword, 29),
+ n_index_value[BIT(dword, 29)]);
+ printf("AUD_CONFIG_A N_programming_enable\t\t\t%lu\n", BIT(dword, 28));
+ printf("AUD_CONFIG_A Upper_N_value\t\t\t\t0x%02lx\n", BITS(dword, 27, 20));
+ printf("AUD_CONFIG_A Lower_N_value\t\t\t\t0x%03lx\n", BITS(dword, 15, 4));
+ printf("AUD_CONFIG_A Pixel_Clock_HDMI\t\t\t\t[0x%lx] %s\n", BITS(dword, 19, 16),
+ OPNAME(pixel_clock, BITS(dword, 19, 16)));
+ printf("AUD_CONFIG_A Disable_NCTS\t\t\t\t%lu\n", BIT(dword, 3));
+ dword = INREG(AUD_CONFIG_B);
+ printf("AUD_CONFIG_B N_index_value\t\t\t\t[0x%lx] %s\n", BIT(dword, 29),
+ n_index_value[BIT(dword, 29)]);
+ printf("AUD_CONFIG_B N_programming_enable\t\t\t%lu\n", BIT(dword, 28));
+ printf("AUD_CONFIG_B Upper_N_value\t\t\t\t0x%02lx\n", BITS(dword, 27, 20));
+ printf("AUD_CONFIG_B Lower_N_value\t\t\t\t0x%03lx\n", BITS(dword, 15, 4));
+ printf("AUD_CONFIG_B Pixel_Clock_HDMI\t\t\t\t[0x%lx] %s\n", BITS(dword, 19, 16),
+ OPNAME(pixel_clock, BITS(dword, 19, 16)));
+ printf("AUD_CONFIG_B Disable_NCTS\t\t\t\t%lu\n", BIT(dword, 3));
+ dword = INREG(AUD_CONFIG_C);
+ printf("AUD_CONFIG_C N_index_value\t\t\t\t[0x%lx] %s\n", BIT(dword, 29),
+ n_index_value[BIT(dword, 29)]);
+ printf("AUD_CONFIG_C N_programming_enable\t\t\t%lu\n", BIT(dword, 28));
+ printf("AUD_CONFIG_C Upper_N_value\t\t\t\t0x%02lx\n", BITS(dword, 27, 20));
+ printf("AUD_CONFIG_C Lower_N_value\t\t\t\t0x%03lx\n", BITS(dword, 15, 4));
+ printf("AUD_CONFIG_C Pixel_Clock_HDMI\t\t\t\t[0x%lx] %s\n", BITS(dword, 19, 16),
+ OPNAME(pixel_clock, BITS(dword, 19, 16)));
+ printf("AUD_CONFIG_C Disable_NCTS\t\t\t\t%lu\n", BIT(dword, 3));
+
+ dword = INREG(AUD_CTS_ENABLE_A);
+ printf("AUD_CTS_ENABLE_A Enable_CTS_or_M_programming\t\t%lu\n", BIT(dword, 20));
+ printf("AUD_CTS_ENABLE_A CTS_M value Index\t\t\t%s\n", BIT(dword, 21) ? "CTS" : "M");
+ printf("AUD_CTS_ENABLE_A CTS_programming\t\t\t%#lx\n", BITS(dword, 19, 0));
+ dword = INREG(AUD_CTS_ENABLE_B);
+ printf("AUD_CTS_ENABLE_B Enable_CTS_or_M_programming\t\t%lu\n", BIT(dword, 20));
+ printf("AUD_CTS_ENABLE_B CTS_M value Index\t\t\t%s\n", BIT(dword, 21) ? "CTS" : "M");
+ printf("AUD_CTS_ENABLE_B CTS_programming\t\t\t%#lx\n", BITS(dword, 19, 0));
+ dword = INREG(AUD_CTS_ENABLE_C);
+ printf("AUD_CTS_ENABLE_C Enable_CTS_or_M_programming\t\t%lu\n", BIT(dword, 20));
+ printf("AUD_CTS_ENABLE_C CTS_M value Index\t\t\t%s\n", BIT(dword, 21) ? "CTS" : "M");
+ printf("AUD_CTS_ENABLE_C CTS_programming\t\t\t%#lx\n", BITS(dword, 19, 0));
+
+ dword = INREG(AUD_MISC_CTRL_A);
+ printf("AUD_MISC_CTRL_A Sample_Fabrication_EN_bit\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_MISC_CTRL_A Sample_present_Disable\t\t\t%lu\n", BIT(dword, 8));
+ printf("AUD_MISC_CTRL_A Output_Delay\t\t\t\t%lu\n", BITS(dword, 7, 4));
+ printf("AUD_MISC_CTRL_A Pro_Allowed\t\t\t\t%lu\n", BIT(dword, 1));
+ dword = INREG(AUD_MISC_CTRL_B);
+ printf("AUD_MISC_CTRL_B Sample_Fabrication_EN_bit\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_MISC_CTRL_B Sample_present_Disable\t\t\t%lu\n", BIT(dword, 8));
+ printf("AUD_MISC_CTRL_B Output_Delay\t\t\t\t%lu\n", BITS(dword, 7, 4));
+ printf("AUD_MISC_CTRL_B Pro_Allowed\t\t\t\t%lu\n", BIT(dword, 1));
+ dword = INREG(AUD_MISC_CTRL_C);
+ printf("AUD_MISC_CTRL_C Sample_Fabrication_EN_bit\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_MISC_CTRL_C Sample_present_Disable\t\t\t%lu\n", BIT(dword, 8));
+ printf("AUD_MISC_CTRL_C Output_Delay\t\t\t\t%lu\n", BITS(dword, 7, 4));
+ printf("AUD_MISC_CTRL_C Pro_Allowed\t\t\t\t%lu\n", BIT(dword, 1));
+
+ dword = INREG(AUD_PWRST);
+ printf("AUD_PWRST Func_Grp_Dev_PwrSt_Curr \t%s\n", power_state[BITS(dword, 27, 26)]);
+ printf("AUD_PWRST Func_Grp_Dev_PwrSt_Set \t%s\n", power_state[BITS(dword, 25, 24)]);
+ printf("AUD_PWRST ConvertorA_Widget_Power_State_Current \t%s\n", power_state[BITS(dword, 15, 14)]);
+ printf("AUD_PWRST ConvertorA_Widget_Power_State_Requsted \t%s\n", power_state[BITS(dword, 13, 12)]);
+ printf("AUD_PWRST ConvertorB_Widget_Power_State_Current \t%s\n", power_state[BITS(dword, 19, 18)]);
+ printf("AUD_PWRST ConvertorB_Widget_Power_State_Requested \t%s\n", power_state[BITS(dword, 17, 16)]);
+ printf("AUD_PWRST ConvC_Widget_PwrSt_Curr \t%s\n", power_state[BITS(dword, 23, 22)]);
+ printf("AUD_PWRST ConvC_Widget_PwrSt_Req \t%s\n", power_state[BITS(dword, 21, 20)]);
+ printf("AUD_PWRST PinB_Widget_Power_State_Current \t%s\n", power_state[BITS(dword, 3, 2)]);
+ printf("AUD_PWRST PinB_Widget_Power_State_Set \t%s\n", power_state[BITS(dword, 1, 0)]);
+ printf("AUD_PWRST PinC_Widget_Power_State_Current \t%s\n", power_state[BITS(dword, 7, 6)]);
+ printf("AUD_PWRST PinC_Widget_Power_State_Set \t%s\n", power_state[BITS(dword, 5, 4)]);
+ printf("AUD_PWRST PinD_Widget_Power_State_Current \t%s\n", power_state[BITS(dword, 11, 10)]);
+ printf("AUD_PWRST PinD_Widget_Power_State_Set \t%s\n", power_state[BITS(dword, 9, 8)]);
+
+ dword = INREG(AUD_PORT_EN_HD_CFG);
+ printf("AUD_PORT_EN_HD_CFG Convertor_A_Digen\t\t\t%lu\n", BIT(dword, 0));
+ printf("AUD_PORT_EN_HD_CFG Convertor_B_Digen\t\t\t%lu\n", BIT(dword, 1));
+ printf("AUD_PORT_EN_HD_CFG Convertor_C_Digen\t\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_PORT_EN_HD_CFG ConvertorA_Stream_ID\t\t%lu\n", BITS(dword, 7, 4));
+ printf("AUD_PORT_EN_HD_CFG ConvertorB_Stream_ID\t\t%lu\n", BITS(dword, 11, 8));
+ printf("AUD_PORT_EN_HD_CFG ConvertorC_Stream_ID\t\t%lu\n", BITS(dword, 15, 12));
+ printf("AUD_PORT_EN_HD_CFG Port_B_Out_Enable\t\t\t%lu\n", BIT(dword, 16));
+ printf("AUD_PORT_EN_HD_CFG Port_C_Out_Enable\t\t\t%lu\n", BIT(dword, 17));
+ printf("AUD_PORT_EN_HD_CFG Port_D_Out_Enable\t\t\t%lu\n", BIT(dword, 18));
+ printf("AUD_PORT_EN_HD_CFG Port_B_Amp_Mute_Status\t\t%lu\n", BIT(dword, 20));
+ printf("AUD_PORT_EN_HD_CFG Port_C_Amp_Mute_Status\t\t%lu\n", BIT(dword, 21));
+ printf("AUD_PORT_EN_HD_CFG Port_D_Amp_Mute_Status\t\t%lu\n", BIT(dword, 22));
+
+ dword = INREG(AUD_OUT_DIG_CNVT_A);
+ printf("AUD_OUT_DIG_CNVT_A V\t\t\t\t\t%lu\n", BIT(dword, 1));
+ printf("AUD_OUT_DIG_CNVT_A VCFG\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_OUT_DIG_CNVT_A PRE\t\t\t\t\t%lu\n", BIT(dword, 3));
+ printf("AUD_OUT_DIG_CNVT_A Copy\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_OUT_DIG_CNVT_A NonAudio\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("AUD_OUT_DIG_CNVT_A PRO\t\t\t\t\t%lu\n", BIT(dword, 6));
+ printf("AUD_OUT_DIG_CNVT_A Level\t\t\t\t%lu\n", BIT(dword, 7));
+ printf("AUD_OUT_DIG_CNVT_A Category_Code\t\t\t%lu\n", BITS(dword, 14, 8));
+ printf("AUD_OUT_DIG_CNVT_A Lowest_Channel_Number\t\t%lu\n",BITS(dword, 19, 16));
+ printf("AUD_OUT_DIG_CNVT_A Stream_ID\t\t\t\t%lu\n", BITS(dword, 23, 20));
+
+ dword = INREG(AUD_OUT_DIG_CNVT_B);
+ printf("AUD_OUT_DIG_CNVT_B V\t\t\t\t\t%lu\n", BIT(dword, 1));
+ printf("AUD_OUT_DIG_CNVT_B VCFG\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_OUT_DIG_CNVT_B PRE\t\t\t\t\t%lu\n", BIT(dword, 3));
+ printf("AUD_OUT_DIG_CNVT_B Copy\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_OUT_DIG_CNVT_B NonAudio\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("AUD_OUT_DIG_CNVT_B PRO\t\t\t\t\t%lu\n", BIT(dword, 6));
+ printf("AUD_OUT_DIG_CNVT_B Level\t\t\t\t%lu\n", BIT(dword, 7));
+ printf("AUD_OUT_DIG_CNVT_B Category_Code\t\t\t%lu\n", BITS(dword, 14, 8));
+ printf("AUD_OUT_DIG_CNVT_B Lowest_Channel_Number\t\t%lu\n",BITS(dword, 19, 16));
+ printf("AUD_OUT_DIG_CNVT_B Stream_ID\t\t\t\t%lu\n", BITS(dword, 23, 20));
+
+ dword = INREG(AUD_OUT_DIG_CNVT_C);
+ printf("AUD_OUT_DIG_CNVT_C V\t\t\t\t\t%lu\n", BIT(dword, 1));
+ printf("AUD_OUT_DIG_CNVT_C VCFG\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_OUT_DIG_CNVT_C PRE\t\t\t\t\t%lu\n", BIT(dword, 3));
+ printf("AUD_OUT_DIG_CNVT_C Copy\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_OUT_DIG_CNVT_C NonAudio\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("AUD_OUT_DIG_CNVT_C PRO\t\t\t\t\t%lu\n", BIT(dword, 6));
+ printf("AUD_OUT_DIG_CNVT_C Level\t\t\t\t%lu\n", BIT(dword, 7));
+ printf("AUD_OUT_DIG_CNVT_C Category_Code\t\t\t%lu\n", BITS(dword, 14, 8));
+ printf("AUD_OUT_DIG_CNVT_C Lowest_Channel_Number\t\t%lu\n",BITS(dword, 19, 16));
+ printf("AUD_OUT_DIG_CNVT_C Stream_ID\t\t\t\t%lu\n", BITS(dword, 23, 20));
+
+ printf("AUD_OUT_CHAN_MAP Converter_Channel_MAP PORTB PORTC PORTD\n");
+ for (i = 0; i < 8; i++) {
+ OUTREG(AUD_OUT_CHAN_MAP, i | (i << 8) | (i << 16));
+ dword = INREG(AUD_OUT_CHAN_MAP);
+ printf("\t\t\t\t%lu\t%lu\t%lu\t%lu\n",
+ 1 + BITS(dword, 3, 0),
+ 1 + BITS(dword, 7, 4),
+ 1 + BITS(dword, 15, 12),
+ 1 + BITS(dword, 23, 20));
+ }
+
+ dword = INREG(AUD_OUT_STR_DESC_A);
+ printf("AUD_OUT_STR_DESC_A Convertor_Channel_Count\t\t%lu\n", BITS(dword, 20, 16) + 1);
+ printf("AUD_OUT_STR_DESC_A Bits_per_Sample\t\t\t[%#lx] %s\n",
+ BITS(dword, 6, 4), OPNAME(bits_per_sample, BITS(dword, 6, 4)));
+ printf("AUD_OUT_STR_DESC_A Number_of_Channels_in_a_Stream\t%lu\n", 1 + BITS(dword, 3, 0));
+
+ dword = INREG(AUD_OUT_STR_DESC_B);
+ printf("AUD_OUT_STR_DESC_B Convertor_Channel_Count\t\t%lu\n", BITS(dword, 20, 16) + 1);
+ printf("AUD_OUT_STR_DESC_B Bits_per_Sample\t\t\t[%#lx] %s\n",
+ BITS(dword, 6, 4), OPNAME(bits_per_sample, BITS(dword, 6, 4)));
+ printf("AUD_OUT_STR_DESC_B Number_of_Channels_in_a_Stream\t%lu\n", 1 + BITS(dword, 3, 0));
+
+ dword = INREG(AUD_OUT_STR_DESC_C);
+ printf("AUD_OUT_STR_DESC_C Convertor_Channel_Count\t\t%lu\n", BITS(dword, 20, 16) + 1);
+ printf("AUD_OUT_STR_DESC_C Bits_per_Sample\t\t\t[%#lx] %s\n",
+ BITS(dword, 6, 4), OPNAME(bits_per_sample, BITS(dword, 6, 4)));
+ printf("AUD_OUT_STR_DESC_C Number_of_Channels_in_a_Stream\t%lu\n", 1 + BITS(dword, 3, 0));
+
+ dword = INREG(AUD_PINW_CONNLNG_SEL);
+ printf("AUD_PINW_CONNLNG_SEL Connection_select_Control_B\t%#lx\n", BITS(dword, 7, 0));
+ printf("AUD_PINW_CONNLNG_SEL Connection_select_Control_C\t%#lx\n", BITS(dword, 15, 8));
+ printf("AUD_PINW_CONNLNG_SEL Connection_select_Control_D\t%#lx\n", BITS(dword, 23, 16));
+
+ dword = INREG(AUD_PIN_ELD_CP_VLD);
+ printf("AUD_CNTRL_ST2 CP_ReadyB\t\t\t\t%lu\n", BIT(dword, 1));
+ printf("AUD_CNTRL_ST2 ELD_validB\t\t\t\t%lu\n", BIT(dword, 0));
+ printf("AUD_CNTRL_ST2 OUT_enableB\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_CNTRL_ST2 CP_ReadyC\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("AUD_CNTRL_ST2 ELD_validC\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_CNTRL_ST2 OUT_enableC\t\t\t\t%lu\n", BIT(dword, 6));
+ printf("AUD_CNTRL_ST2 CP_ReadyD\t\t\t\t%lu\n", BIT(dword, 9));
+ printf("AUD_CNTRL_ST2 ELD_validD\t\t\t\t%lu\n", BIT(dword, 8));
+ printf("AUD_CNTRL_ST2 OUT_enableD\t\t\t\t%lu\n", BIT(dword, 10));
+
+ dword = INREG(AUD_HDMIW_STATUS);
+ printf("AUD_HDMIW_STATUS Conv_A_CDCLK/DOTCLK_FIFO_Underrun\t%lu\n", BIT(dword, 27));
+ printf("AUD_HDMIW_STATUS Conv_A_CDCLK/DOTCLK_FIFO_Overrun\t%lu\n", BIT(dword, 26));
+ printf("AUD_HDMIW_STATUS Conv_B_CDCLK/DOTCLK_FIFO_Underrun\t%lu\n", BIT(dword, 29));
+ printf("AUD_HDMIW_STATUS Conv_B_CDCLK/DOTCLK_FIFO_Overrun\t%lu\n", BIT(dword, 28));
+ printf("AUD_HDMIW_STATUS Conv_C_CDCLK/DOTCLK_FIFO_Underrun\t%lu\n", BIT(dword, 31));
+ printf("AUD_HDMIW_STATUS Conv_C_CDCLK/DOTCLK_FIFO_Overrun\t%lu\n", BIT(dword, 30));
+ printf("AUD_HDMIW_STATUS BCLK/CDCLK_FIFO_Overrun\t\t%lu\n", BIT(dword, 25));
+ printf("AUD_HDMIW_STATUS Function_Reset\t\t\t%lu\n", BIT(dword, 24));
+
+ printf("AUD_HDMIW_HDMIEDID_A HDMI ELD:\n\t");
+ dword = INREG(AUD_DIP_ELD_CTRL_ST_A);
+ dword &= ~BITMASK(9, 5);
+ OUTREG(AUD_DIP_ELD_CTRL_ST_A, dword);
+ for (i = 0; i < BITS(dword, 14, 10) / 4; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_HDMIEDID_A)));
+ printf("\n");
+
+ printf("AUD_HDMIW_HDMIEDID_B HDMI ELD:\n\t");
+ dword = INREG(AUD_DIP_ELD_CTRL_ST_B);
+ dword &= ~BITMASK(9, 5);
+ OUTREG(AUD_DIP_ELD_CTRL_ST_B, dword);
+ for (i = 0; i < BITS(dword, 14, 10) / 4; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_HDMIEDID_B)));
+ printf("\n");
+
+ printf("AUD_HDMIW_HDMIEDID_C HDMI ELD:\n\t");
+ dword = INREG(AUD_DIP_ELD_CTRL_ST_C);
+ dword &= ~BITMASK(9, 5);
+ OUTREG(AUD_DIP_ELD_CTRL_ST_C, dword);
+ for (i = 0; i < BITS(dword, 14, 10) / 4; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_HDMIEDID_C)));
+ printf("\n");
+
+ printf("AUD_HDMIW_INFOFR_A HDMI audio Infoframe:\n\t");
+ dword = INREG(AUD_DIP_ELD_CTRL_ST_A);
+ dword &= ~BITMASK(20, 18);
+ dword &= ~BITMASK(3, 0);
+ OUTREG(AUD_DIP_ELD_CTRL_ST_A, dword);
+ for (i = 0; i < 8; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_INFOFR_A)));
+ printf("\n");
+
+ printf("AUD_HDMIW_INFOFR_B HDMI audio Infoframe:\n\t");
+ dword = INREG(AUD_DIP_ELD_CTRL_ST_B);
+ dword &= ~BITMASK(20, 18);
+ dword &= ~BITMASK(3, 0);
+ OUTREG(AUD_DIP_ELD_CTRL_ST_B, dword);
+ for (i = 0; i < 8; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_INFOFR_B)));
+ printf("\n");
+
+ printf("AUD_HDMIW_INFOFR_C HDMI audio Infoframe:\n\t");
+ dword = INREG(AUD_DIP_ELD_CTRL_ST_C);
+ dword &= ~BITMASK(20, 18);
+ dword &= ~BITMASK(3, 0);
+ OUTREG(AUD_DIP_ELD_CTRL_ST_C, dword);
+ for (i = 0; i < 8; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_INFOFR_C)));
+ printf("\n");
+}
+
+int main(int argc, char **argv)
+{
+ struct pci_device *pci_dev;
+
+ pci_dev = intel_get_pci_device();
+ devid = pci_dev->device_id; /* XXX not true when mapping! */
+
+ do_self_tests();
+
+ if (argc == 2)
+ intel_map_file(argv[1]);
+ else
+ intel_get_mmio(pci_dev);
+
+ if (IS_GEN6(devid) || IS_GEN7(devid) || getenv("HAS_PCH_SPLIT")) {
+ if (IS_HASWELL(devid)) {
+ printf("Haswell audio registers:\n\n");
+ dump_hsw();
+ return 0;
+ }
+ printf("%s audio registers:\n\n",
+ IS_GEN6(devid) ? "SandyBridge" : "IvyBridge");
+ intel_check_pch();
+ dump_cpt();
+ } else if (IS_GEN5(devid)) {
+ printf("Ironlake audio registers:\n\n");
+ dump_ironlake();
+ } else if (IS_G4X(devid)) {
+ printf("G45 audio registers:\n\n");
+ dump_eaglelake();
+ }
+
+ return 0;
+}
diff --git a/tools/intel_backlight.c b/tools/intel_backlight.c
new file mode 100644
index 00000000..bd7c813b
--- /dev/null
+++ b/tools/intel_backlight.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright © 2011 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:
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "intel_gpu_tools.h"
+
+/* XXX PCH only today */
+
+static uint32_t reg_read(uint32_t reg)
+{
+ return *(volatile uint32_t *)((volatile char*)mmio + reg);
+}
+
+static void reg_write(uint32_t reg, uint32_t val)
+{
+ *(volatile uint32_t *)((volatile char*)mmio + reg) = val;
+}
+
+int main(int argc, char** argv)
+{
+ uint32_t current, max;
+
+ intel_get_mmio(intel_get_pci_device());
+
+ current = reg_read(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
+ max = reg_read(BLC_PWM_PCH_CTL2) >> 16;
+
+ printf ("current backlight value: %d%%\n", current * 100 / max);
+
+ if (argc > 1) {
+ uint32_t v = atoi (argv[1]) * max / 100;
+ if (v > max)
+ v = max;
+ reg_write(BLC_PWM_CPU_CTL,
+ (reg_read(BLC_PWM_CPU_CTL) &~ BACKLIGHT_DUTY_CYCLE_MASK) | v);
+ (void) reg_read(BLC_PWM_CPU_CTL);
+ printf ("set backlight to %d%%\n", v * 100 / max);
+ }
+
+ return 0;
+}
diff --git a/tools/intel_bios.h b/tools/intel_bios.h
new file mode 100644
index 00000000..12850203
--- /dev/null
+++ b/tools/intel_bios.h
@@ -0,0 +1,731 @@
+/*
+ * Copyright 2006 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:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#ifndef _INTEL_BIOS_H_
+#define _INTEL_BIOS_H_
+
+#include <stdint.h>
+
+struct vbt_header {
+ char signature[20]; /**< Always starts with 'VBT$' */
+ uint16_t version; /**< decimal */
+ uint16_t header_size; /**< in bytes */
+ uint16_t vbt_size; /**< in bytes */
+ uint8_t vbt_checksum;
+ uint8_t reserved0;
+ uint32_t bdb_offset; /**< from beginning of VBT */
+ uint32_t aim_offset[4]; /**< from beginning of VBT */
+} __attribute__ ((packed));
+
+struct bdb_header {
+ char signature[16]; /**< Always 'BIOS_DATA_BLOCK' */
+ uint16_t version; /**< decimal */
+ uint16_t header_size; /**< in bytes */
+ uint16_t bdb_size; /**< in bytes */
+} __attribute__ ((packed));
+
+/*
+ * There are several types of BIOS data blocks (BDBs), each block has
+ * an ID and size in the first 3 bytes (ID in first, size in next 2).
+ * Known types are listed below.
+ */
+#define BDB_GENERAL_FEATURES 1
+#define BDB_GENERAL_DEFINITIONS 2
+#define BDB_OLD_TOGGLE_LIST 3
+#define BDB_MODE_SUPPORT_LIST 4
+#define BDB_GENERIC_MODE_TABLE 5
+#define BDB_EXT_MMIO_REGS 6
+#define BDB_SWF_IO 7
+#define BDB_SWF_MMIO 8
+#define BDB_DOT_CLOCK_TABLE 9
+#define BDB_MODE_REMOVAL_TABLE 10
+#define BDB_CHILD_DEVICE_TABLE 11
+#define BDB_DRIVER_FEATURES 12
+#define BDB_DRIVER_PERSISTENCE 13
+#define BDB_EXT_TABLE_PTRS 14
+#define BDB_DOT_CLOCK_OVERRIDE 15
+#define BDB_DISPLAY_SELECT 16
+/* 17 rsvd */
+#define BDB_DRIVER_ROTATION 18
+#define BDB_DISPLAY_REMOVE 19
+#define BDB_OEM_CUSTOM 20
+#define BDB_EFP_LIST 21 /* workarounds for VGA hsync/vsync */
+#define BDB_SDVO_LVDS_OPTIONS 22
+#define BDB_SDVO_PANEL_DTDS 23
+#define BDB_SDVO_LVDS_PNP_IDS 24
+#define BDB_SDVO_LVDS_POWER_SEQ 25
+#define BDB_TV_OPTIONS 26
+#define BDB_EDP 27
+#define BDB_LVDS_OPTIONS 40
+#define BDB_LVDS_LFP_DATA_PTRS 41
+#define BDB_LVDS_LFP_DATA 42
+#define BDB_LVDS_BACKLIGHT 43
+#define BDB_LVDS_POWER 44
+#define BDB_SKIP 254 /* VBIOS private block, ignore */
+
+struct bdb_general_features {
+ /* bits 1 */
+ unsigned char panel_fitting:2;
+ unsigned char flexaim:1;
+ unsigned char msg_enable:1;
+ unsigned char clear_screen:3;
+ unsigned char color_flip:1;
+
+ /* bits 2 */
+ unsigned char download_ext_vbt:1;
+ unsigned char enable_ssc:1;
+ unsigned char ssc_freq:1;
+ unsigned char enable_lfp_on_override:1;
+ unsigned char disable_ssc_ddt:1;
+ unsigned char rsvd8:3; /* finish byte */
+
+ /* bits 3 */
+ unsigned char disable_smooth_vision:1;
+ unsigned char single_dvi:1;
+ unsigned char rsvd9:6; /* finish byte */
+
+ /* bits 4 */
+ unsigned char legacy_monitor_detect;
+
+ /* bits 5 */
+ unsigned char int_crt_support:1;
+ unsigned char int_tv_support:1;
+ unsigned char rsvd11:6; /* finish byte */
+} __attribute__ ((packed));
+
+#define GPIO_PIN_NONE 0x00 /* "N/A" */
+#define GPIO_PIN_I2C 0x01 /* "I2C GPIO pins" */
+#define GPIO_PIN_CRT_DDC 0x02 /* "Analog CRT DDC GPIO pins" */
+/* 915+ */
+#define GPIO_PIN_LVDS 0x03 /* "Integrated LVDS DDC GPIO pins" */
+#define GPIO_PIN_SDVO_I2C 0x05 /* "sDVO I2C GPIO pins" */
+#define GPIO_PIN_SDVO_DDC1 0x1D /* "SDVO DDC1 GPIO pins" */
+#define GPIO_PIN_SDVO_DDC2 0x2D /* "SDVO DDC2 GPIO pins" */
+/* pre-915 */
+#define GPIO_PIN_DVI_LVDS 0x03 /* "DVI/LVDS DDC GPIO pins" */
+#define GPIO_PIN_ADD_I2C 0x05 /* "ADDCARD I2C GPIO pins" */
+#define GPIO_PIN_ADD_DDC 0x04 /* "ADDCARD DDC GPIO pins" */
+#define GPIO_PIN_ADD_DDC_I2C 0x06 /* "ADDCARD DDC/I2C GPIO pins" */
+
+/* Pre 915 */
+#define DEVICE_TYPE_NONE 0x00
+#define DEVICE_TYPE_CRT 0x01
+#define DEVICE_TYPE_TV 0x09
+#define DEVICE_TYPE_EFP 0x12
+#define DEVICE_TYPE_LFP 0x22
+/* On 915+ */
+#define DEVICE_TYPE_CRT_DPMS 0x6001
+#define DEVICE_TYPE_CRT_DPMS_HOTPLUG 0x4001
+#define DEVICE_TYPE_TV_COMPOSITE 0x0209
+#define DEVICE_TYPE_TV_MACROVISION 0x0289
+#define DEVICE_TYPE_TV_RF_COMPOSITE 0x020c
+#define DEVICE_TYPE_TV_SVIDEO_COMPOSITE 0x0609
+#define DEVICE_TYPE_TV_SCART 0x0209
+#define DEVICE_TYPE_TV_CODEC_HOTPLUG_PWR 0x6009
+#define DEVICE_TYPE_EFP_HOTPLUG_PWR 0x6012
+#define DEVICE_TYPE_EFP_DVI_HOTPLUG_PWR 0x6052
+#define DEVICE_TYPE_EFP_DVI_I 0x6053
+#define DEVICE_TYPE_EFP_DVI_D_DUAL 0x6152
+#define DEVICE_TYPE_EFP_DVI_D_HDCP 0x60d2
+#define DEVICE_TYPE_OPENLDI_HOTPLUG_PWR 0x6062
+#define DEVICE_TYPE_OPENLDI_DUALPIX 0x6162
+#define DEVICE_TYPE_LFP_PANELLINK 0x5012
+#define DEVICE_TYPE_LFP_CMOS_PWR 0x5042
+#define DEVICE_TYPE_LFP_LVDS_PWR 0x5062
+#define DEVICE_TYPE_LFP_LVDS_DUAL 0x5162
+#define DEVICE_TYPE_LFP_LVDS_DUAL_HDCP 0x51e2
+#define DEVICE_TYPE_INT_HDMI 0xf0D2
+
+#define DEVICE_TYPE_INT_LFP 0x1022
+#define DEVICE_TYPE_INT_TV 0x1009
+#define DEVICE_TYPE_DP 0x68C6
+#define DEVICE_TYPE_DP_HDMI_DVI 0x60d6
+#define DEVICE_TYPE_DP_DVI 0x68d6
+#define DEVICE_TYPE_HDMI_DVI 0x60d2
+#define DEVICE_TYPE_DVI 0x68d2
+#define DEVICE_TYPE_eDP 0x78C6
+
+#define DEVICE_CFG_NONE 0x00
+#define DEVICE_CFG_12BIT_DVOB 0x01
+#define DEVICE_CFG_12BIT_DVOC 0x02
+#define DEVICE_CFG_24BIT_DVOBC 0x09
+#define DEVICE_CFG_24BIT_DVOCB 0x0a
+#define DEVICE_CFG_DUAL_DVOB 0x11
+#define DEVICE_CFG_DUAL_DVOC 0x12
+#define DEVICE_CFG_DUAL_DVOBC 0x13
+#define DEVICE_CFG_DUAL_LINK_DVOBC 0x19
+#define DEVICE_CFG_DUAL_LINK_DVOCB 0x1a
+
+#define DEVICE_WIRE_NONE 0x00
+#define DEVICE_WIRE_DVOB 0x01
+#define DEVICE_WIRE_DVOC 0x02
+#define DEVICE_WIRE_DVOBC 0x03
+#define DEVICE_WIRE_DVOBB 0x05
+#define DEVICE_WIRE_DVOCC 0x06
+#define DEVICE_WIRE_DVOB_MASTER 0x0d
+#define DEVICE_WIRE_DVOC_MASTER 0x0e
+
+#define DEVICE_PORT_DVOA 0x00 /* none on 845+ */
+#define DEVICE_PORT_DVOB 0x01
+#define DEVICE_PORT_DVOC 0x02
+
+#define DEVICE_PORT_NONE 0
+#define DEVICE_PORT_HDMIB 1
+#define DEVICE_PORT_HDMIC 2
+#define DEVICE_PORT_HDMID 3
+#define DEVICE_PORT_DPB 7
+#define DEVICE_PORT_DPC 8
+#define DEVICE_PORT_DPD 9
+
+#define DEVICE_INFO_NONE 0
+#define DEVICE_INFO_HDMI_CERT 1
+#define DEVICE_INFO_DP 2
+#define DEVICE_INFO_DVI 3
+
+struct child_device_config {
+ uint16_t handle;
+ uint16_t device_type; /* See DEVICE_TYPE_* above */
+ uint8_t device_id[10];
+ uint16_t addin_offset;
+ uint8_t dvo_port; /* See DEVICE_PORT_* above */
+ uint8_t i2c_pin;
+ uint8_t slave_addr;
+ uint8_t ddc_pin;
+ uint16_t edid_ptr;
+ uint8_t dvo_cfg; /* See DEVICE_CFG_* above */
+ uint8_t dvo2_port;
+ uint8_t i2c2_pin;
+ uint8_t slave2_addr;
+ uint8_t ddc2_pin;
+ uint8_t capabilities;
+ uint8_t dvo_wiring; /* See DEVICE_WIRE_* above */
+ uint8_t dvo2_wiring;
+ uint16_t extended_type;
+ uint8_t dvo_function;
+} __attribute__ ((packed));
+
+struct efp_child_device_config {
+ uint16_t handle;
+ uint16_t device_type;
+ uint8_t skip1[12];
+ uint8_t port;
+ uint8_t skip2[2];
+ uint8_t ddc_pin;
+ uint8_t skip3[3];
+ uint8_t docked_port;
+ uint8_t hdmi_compat:1;
+ uint8_t conn_info:3;
+ uint8_t skip4:4;
+ uint8_t aux_chan;
+ uint8_t dongle_detect;
+ uint8_t skip5[6];
+} __attribute__ ((packed));
+
+struct bdb_general_definitions {
+ unsigned char crt_ddc_gmbus_pin; /* see GPIO_PIN_* above */
+
+ /* DPMS bits */
+ unsigned char dpms_acpi:1;
+ unsigned char skip_boot_crt_detect:1;
+ unsigned char dpms_aim:1;
+ unsigned char rsvd1:5; /* finish byte */
+
+ /* boot device bits */
+ unsigned char boot_display[2];
+ unsigned char child_dev_size;
+
+ /*
+ * Device info:
+ * If TV is present, it'll be at devices[0]
+ * LVDS will be next, either devices[0] or [1], if present
+ * Max total will be 6, but could be as few as 4 if both
+ * TV and LVDS are missing, so be careful when interpreting
+ * [4] and [5].
+ */
+ struct child_device_config devices[0];
+ /* may be another device block here on some platforms */
+} __attribute__ ((packed));
+
+#define DEVICE_CHILD_SIZE 7
+
+struct bdb_child_devices {
+ uint8_t child_structure_size;
+ struct child_device_config children[DEVICE_CHILD_SIZE];
+} __attribute__ ((packed));
+
+struct bdb_lvds_options {
+ uint8_t panel_type;
+ uint8_t rsvd1;
+ /* LVDS capabilities, stored in a dword */
+ uint8_t pfit_mode:2;
+ uint8_t pfit_text_mode_enhanced:1;
+ uint8_t pfit_gfx_mode_enhanced:1;
+ uint8_t pfit_ratio_auto:1;
+ uint8_t pixel_dither:1;
+ uint8_t lvds_edid:1;
+ uint8_t rsvd2:1;
+ uint8_t rsvd4;
+} __attribute__ ((packed));
+
+/* 915+ only */
+struct bdb_tv_features {
+ /* need to verify bit ordering */
+ uint16_t under_over_scan_via_yprpb:2;
+ uint16_t rsvd1:10;
+ uint16_t under_over_scan_via_dvi:2;
+ uint16_t add_overscan_mode:1;
+ uint16_t rsvd2:1;
+} __attribute__ ((packed));
+
+struct lvds_fp_timing {
+ uint16_t x_res;
+ uint16_t y_res;
+ uint32_t lvds_reg;
+ uint32_t lvds_reg_val;
+ uint32_t pp_on_reg;
+ uint32_t pp_on_reg_val;
+ uint32_t pp_off_reg;
+ uint32_t pp_off_reg_val;
+ uint32_t pp_cycle_reg;
+ uint32_t pp_cycle_reg_val;
+ uint32_t pfit_reg;
+ uint32_t pfit_reg_val;
+ uint16_t terminator;
+} __attribute__ ((packed));
+
+struct lvds_dvo_timing {
+ uint16_t dclk; /**< In 10khz */
+ uint8_t hactive;
+ uint8_t hblank;
+ uint8_t high_h; /**< 7:4 = hactive 11:8, 3:0 = hblank 11:8 */
+ uint8_t vactive;
+ uint8_t vblank;
+ uint8_t high_v; /**< 7:4 = vactive 11:8, 3:0 = vblank 11:8 */
+ uint8_t hsync_off;
+ uint8_t hsync_pulse_width;
+ uint8_t vsync_off;
+ uint8_t high_hsync_off; /**< 7:6 = hsync off 9:8 */
+ uint8_t h_image;
+ uint8_t v_image;
+ uint8_t max_hv;
+ uint8_t h_border;
+ uint8_t v_border;
+ uint8_t flags;
+} __attribute__ ((packed));
+struct lvds_dvo_timing2 {
+ uint16_t clock; /**< In 10khz */
+ uint8_t hactive_lo;
+ uint8_t hblank_lo;
+ uint8_t hblank_hi:4;
+ uint8_t hactive_hi:4;
+ uint8_t vactive_lo;
+ uint8_t vblank_lo;
+ uint8_t vblank_hi:4;
+ uint8_t vactive_hi:4;
+ uint8_t hsync_off_lo;
+ uint8_t hsync_pulse_width;
+ uint8_t vsync_pulse_width:4;
+ uint8_t vsync_off:4;
+ uint8_t rsvd0:6;
+ uint8_t hsync_off_hi:2;
+ uint8_t h_image;
+ uint8_t v_image;
+ uint8_t max_hv;
+ uint8_t h_border;
+ uint8_t v_border;
+ uint8_t rsvd1:3;
+ uint8_t digital:2;
+ uint8_t vsync_positive:1;
+ uint8_t hsync_positive:1;
+ uint8_t rsvd2:1;
+} __attribute__((packed));
+
+struct lvds_pnp_id {
+ uint16_t mfg_name;
+ uint16_t product_code;
+ uint32_t serial;
+ uint8_t mfg_week;
+ uint8_t mfg_year;
+} __attribute__ ((packed));;
+
+/* LFP pointer table contains entries to the struct below */
+struct bdb_lvds_lfp_data_ptr {
+ uint16_t fp_timing_offset; /* offsets are from start of bdb */
+ uint8_t fp_table_size;
+ uint16_t dvo_timing_offset;
+ uint8_t dvo_table_size;
+ uint16_t panel_pnp_id_offset;
+ uint8_t pnp_table_size;
+} __attribute__ ((packed));
+
+struct bdb_lvds_lfp_data_ptrs {
+ uint8_t lvds_entries;
+ struct bdb_lvds_lfp_data_ptr ptr[16];
+} __attribute__ ((packed));
+
+struct bdb_lvds_lfp_data_entry {
+ struct lvds_fp_timing fp_timing;
+ struct lvds_dvo_timing dvo_timing;
+ struct lvds_pnp_id pnp_id;
+} __attribute__ ((packed));
+
+struct bdb_lvds_lfp_data {
+ struct bdb_lvds_lfp_data_entry data[16];
+} __attribute__ ((packed));
+
+#define BACKLIGHT_TYPE_NONE 0
+#define BACKLIGHT_TYPE_I2C 1
+#define BACKLIGHT_TYPE_PWM 2
+
+#define BACKLIGHT_GMBUS_100KHZ 0
+#define BACKLIGHT_GMBUS_50KHZ 1
+#define BACKLIGHT_GMBUS_400KHZ 2
+#define BACKLIGHT_GMBUS_1MHZ 3
+
+struct backlight_info {
+ uint8_t inverter_type:2; /* see BACKLIGHT_TYPE_* above */
+ uint8_t inverter_polarity:1; /* 1 means 0 is max, 255 is min */
+ uint8_t gpio_pins:3; /* see GPIO_PIN_* above */
+ uint8_t gmbus_speed:2;
+ uint16_t pwm_frequency; /* in Hz */
+ uint8_t min_brightness;
+ /* Next two are only for 915+ systems */
+ uint8_t i2c_addr;
+ uint8_t i2c_cmd;
+} __attribute((packed));
+
+struct bdb_backlight_control {
+ uint8_t row_size;
+ struct backlight_info lfps[16];
+} __attribute__ ((packed));
+
+struct bdb_bia {
+ uint8_t bia_enable:1;
+ uint8_t bia_level:3;
+ uint8_t rsvd1:3;
+ uint8_t als_enable:1;
+ uint8_t als_response_data[20];
+} __attribute((packed));
+
+struct aimdb_header {
+ char signature[16];
+ char oem_device[20];
+ uint16_t aimdb_version;
+ uint16_t aimdb_header_size;
+ uint16_t aimdb_size;
+} __attribute__ ((packed));
+
+struct aimdb_block {
+ uint8_t aimdb_id;
+ uint16_t aimdb_size;
+} __attribute__ ((packed));
+
+struct vch_panel_data {
+ uint16_t fp_timing_offset;
+ uint8_t fp_timing_size;
+ uint16_t dvo_timing_offset;
+ uint8_t dvo_timing_size;
+ uint16_t text_fitting_offset;
+ uint8_t text_fitting_size;
+ uint16_t graphics_fitting_offset;
+ uint8_t graphics_fitting_size;
+} __attribute__ ((packed));
+
+struct vch_bdb_22 {
+ struct aimdb_block aimdb_block;
+ struct vch_panel_data panels[16];
+} __attribute__ ((packed));
+
+#define BLC_INVERTER_TYPE_NONE 0
+#define BLC_INVERTER_TYPE_I2C 1
+#define BLC_INVERTER_TYPE_PWM 2
+
+#define BLC_GPIO_NONE 0
+#define BLC_GPIO_I2C 1
+#define BLC_GPIO_CRT_DDC 2
+#define BLC_GPIO_DVI_DDC 3
+#define BLC_GPIO_SDVO_I2C 5
+
+struct blc_struct {
+ uint8_t inverter_type:2;
+ uint8_t inverter_polarity:1; /* 1 means inverted (0 = max brightness) */
+ uint8_t gpio_pins:3;
+ uint8_t gmbus_speed:2;
+ uint16_t pwm_freq; /* in Hz */
+ uint8_t min_brightness; /* (0-255) */
+ uint8_t i2c_slave_addr;
+ uint8_t i2c_cmd;
+} __attribute__ ((packed));
+
+struct bdb_lvds_backlight {
+ uint8_t blcstruct_size;
+ struct blc_struct panels[16];
+} __attribute__ ((packed));
+
+struct bdb_lvds_power {
+ uint8_t dpst_enabled:1;
+ uint8_t pwr_prefs:3;
+ uint8_t rsvd1:3;
+ uint8_t als_enabled:1;
+ uint16_t als_backlight1;
+ uint16_t als_backlight2;
+ uint16_t als_backlight3;
+ uint16_t als_backlight4;
+ uint16_t als_backlight5;
+} __attribute__ ((packed));
+
+#define BDB_DRIVER_NO_LVDS 0
+#define BDB_DRIVER_INT_LVDS 1
+#define BDB_DRIVER_SDVO_LVDS 2
+#define BDB_DRIVER_EDP 3
+
+struct bdb_driver_feature {
+ uint8_t boot_dev_algorithm:1;
+ uint8_t block_display_switch:1;
+ uint8_t allow_display_switch:1;
+ uint8_t hotplug_dvo:1;
+ uint8_t dual_view_zoom:1;
+ uint8_t int15h_hook:1;
+ uint8_t sprite_in_clone:1;
+ uint8_t primary_lfp_id:1;
+
+ uint16_t boot_mode_x;
+ uint16_t boot_mode_y;
+ uint8_t boot_mode_bpp;
+ uint8_t boot_mode_refresh;
+
+ uint16_t enable_lfp_primary:1;
+ uint16_t selective_mode_pruning:1;
+ uint16_t dual_frequency:1;
+ uint16_t render_clock_freq:1; /* 0: high freq; 1: low freq */
+ uint16_t nt_clone_support:1;
+ uint16_t power_scheme_ui:1; /* 0: CUI; 1: 3rd party */
+ uint16_t sprite_display_assign:1; /* 0: secondary; 1: primary */
+ uint16_t cui_aspect_scaling:1;
+ uint16_t preserve_aspect_ratio:1;
+ uint16_t sdvo_device_power_down:1;
+ uint16_t crt_hotplug:1;
+ uint16_t lvds_config:2;
+ uint16_t reserved:3;
+
+ uint8_t static_display:1;
+ uint8_t reserved2:7;
+ uint16_t legacy_crt_max_x;
+ uint16_t legacy_crt_max_y;
+ uint8_t legacy_crt_max_refresh;
+} __attribute__ ((packed));
+
+struct bdb_sdvo_lvds_options {
+ uint8_t panel_backlight;
+ uint8_t h40_set_panel_type;
+ uint8_t panel_type;
+ uint8_t ssc_clk_freq;
+ uint16_t als_low_trip;
+ uint16_t als_high_trip;
+ uint8_t sclalarcoeff_tab_row_num;
+ uint8_t sclalarcoeff_tab_row_size;
+ uint8_t coefficient[8];
+ uint8_t panel_misc_bits_1;
+ uint8_t panel_misc_bits_2;
+ uint8_t panel_misc_bits_3;
+ uint8_t panel_misc_bits_4;
+} __attribute__ ((packed));
+
+#define EDP_18BPP 0
+#define EDP_24BPP 1
+#define EDP_30BPP 2
+#define EDP_RATE_1_62 0
+#define EDP_RATE_2_7 1
+#define EDP_LANE_1 0
+#define EDP_LANE_2 1
+#define EDP_LANE_4 3
+#define EDP_PREEMPHASIS_NONE 0
+#define EDP_PREEMPHASIS_3_5dB 1
+#define EDP_PREEMPHASIS_6dB 2
+#define EDP_PREEMPHASIS_9_5dB 3
+#define EDP_VSWING_0_4V 0
+#define EDP_VSWING_0_6V 1
+#define EDP_VSWING_0_8V 2
+#define EDP_VSWING_1_2V 3
+
+struct edp_power_seq {
+ uint16_t t3;
+ uint16_t t7;
+ uint16_t t9;
+ uint16_t t10;
+ uint16_t t12;
+} __attribute__ ((packed));
+
+struct edp_link_params {
+ uint8_t rate:4;
+ uint8_t lanes:4;
+ uint8_t preemphasis:4;
+ uint8_t vswing:4;
+} __attribute__ ((packed));
+
+struct bdb_edp {
+ struct edp_power_seq power_seqs[16];
+ uint32_t color_depth;
+ uint32_t sdrrs_msa_timing_delay;
+ struct edp_link_params link_params[16];
+} __attribute__ ((packed));
+
+/*
+ * Driver<->VBIOS interaction occurs through scratch bits in
+ * GR18 & SWF*.
+ *
+ * The VBIOS/firmware will signal to the gfx driver through the ASLE interrupt
+ * (visible in the interupt regs at bit 0) when it wants something done.
+ *
+ * Pre-965:
+ * The gfx driver can make calls to the VBIOS/firmware through an SMI request,
+ * generated by writing to offset 0xe0 of the device's config space (see the
+ * publically available 915 PRM for details).
+ *
+ * 965 and above:
+ * IGD OpRegion requests to the VBIOS/firmware are made using SWSCI, which can
+ * be triggered by writing to offset 0xe4 (see the publically available
+ * 965 graphics PRM for details).
+ */
+
+/* GR18 bits are set on display switch and hotkey events */
+#define GR18_DRIVER_SWITCH_EN (1<<7) /* 0: VBIOS control, 1: driver control */
+#define GR18_HOTKEY_MASK 0x78 /* See also SWF4 15:0 */
+#define GR18_HK_NONE (0x0<<3)
+#define GR18_HK_LFP_STRETCH (0x1<<3)
+#define GR18_HK_TOGGLE_DISP (0x2<<3)
+#define GR18_HK_DISP_SWITCH (0x4<<3) /* see SWF14 15:0 for what to enable */
+#define GR18_HK_POPUP_DISABLED (0x6<<3)
+#define GR18_HK_POPUP_ENABLED (0x7<<3)
+#define GR18_HK_PFIT (0x8<<3)
+#define GR18_HK_APM_CHANGE (0xa<<3)
+#define GR18_HK_MULTIPLE (0xc<<3)
+#define GR18_USER_INT_EN (1<<2)
+#define GR18_A0000_FLUSH_EN (1<<1)
+#define GR18_SMM_EN (1<<0)
+
+/* Set by driver, cleared by VBIOS */
+#define SWF00_YRES_SHIFT 16
+#define SWF00_XRES_SHIFT 0
+#define SWF00_RES_MASK 0xffff
+
+/* Set by VBIOS at boot time and driver at runtime */
+#define SWF01_TV2_FORMAT_SHIFT 8
+#define SWF01_TV1_FORMAT_SHIFT 0
+#define SWF01_TV_FORMAT_MASK 0xffff
+
+#define SWF10_VBIOS_BLC_I2C_EN (1<<29)
+#define SWF10_GTT_OVERRIDE_EN (1<<28)
+#define SWF10_LFP_DPMS_OVR (1<<27) /* override DPMS on display switch */
+#define SWF10_ACTIVE_TOGGLE_LIST_MASK (7<<24)
+#define SWF10_OLD_TOGGLE 0x0
+#define SWF10_TOGGLE_LIST_1 0x1
+#define SWF10_TOGGLE_LIST_2 0x2
+#define SWF10_TOGGLE_LIST_3 0x3
+#define SWF10_TOGGLE_LIST_4 0x4
+#define SWF10_PANNING_EN (1<<23)
+#define SWF10_DRIVER_LOADED (1<<22)
+#define SWF10_EXTENDED_DESKTOP (1<<21)
+#define SWF10_EXCLUSIVE_MODE (1<<20)
+#define SWF10_OVERLAY_EN (1<<19)
+#define SWF10_PLANEB_HOLDOFF (1<<18)
+#define SWF10_PLANEA_HOLDOFF (1<<17)
+#define SWF10_VGA_HOLDOFF (1<<16)
+#define SWF10_ACTIVE_DISP_MASK 0xffff
+#define SWF10_PIPEB_LFP2 (1<<15)
+#define SWF10_PIPEB_EFP2 (1<<14)
+#define SWF10_PIPEB_TV2 (1<<13)
+#define SWF10_PIPEB_CRT2 (1<<12)
+#define SWF10_PIPEB_LFP (1<<11)
+#define SWF10_PIPEB_EFP (1<<10)
+#define SWF10_PIPEB_TV (1<<9)
+#define SWF10_PIPEB_CRT (1<<8)
+#define SWF10_PIPEA_LFP2 (1<<7)
+#define SWF10_PIPEA_EFP2 (1<<6)
+#define SWF10_PIPEA_TV2 (1<<5)
+#define SWF10_PIPEA_CRT2 (1<<4)
+#define SWF10_PIPEA_LFP (1<<3)
+#define SWF10_PIPEA_EFP (1<<2)
+#define SWF10_PIPEA_TV (1<<1)
+#define SWF10_PIPEA_CRT (1<<0)
+
+#define SWF11_MEMORY_SIZE_SHIFT 16
+#define SWF11_SV_TEST_EN (1<<15)
+#define SWF11_IS_AGP (1<<14)
+#define SWF11_DISPLAY_HOLDOFF (1<<13)
+#define SWF11_DPMS_REDUCED (1<<12)
+#define SWF11_IS_VBE_MODE (1<<11)
+#define SWF11_PIPEB_ACCESS (1<<10) /* 0 here means pipe a */
+#define SWF11_DPMS_MASK 0x07
+#define SWF11_DPMS_OFF (1<<2)
+#define SWF11_DPMS_SUSPEND (1<<1)
+#define SWF11_DPMS_STANDBY (1<<0)
+#define SWF11_DPMS_ON 0
+
+#define SWF14_GFX_PFIT_EN (1<<31)
+#define SWF14_TEXT_PFIT_EN (1<<30)
+#define SWF14_LID_SWITCH_EN (1<<29)
+#define SWF14_POPUP_EN (1<<28)
+#define SWF14_DISPLAY_HOLDOFF (1<<27)
+#define SWF14_DISP_DETECT_EN (1<<26)
+#define SWF14_DOCKING_STATUS_DOCKED (1<<25) /* 0 here means undocked */
+#define SWF14_DRIVER_STATUS (1<<24)
+#define SWF14_OS_TYPE_WIN9X (1<<23)
+#define SWF14_OS_TYPE_WINNT (1<<22)
+/* 21:19 rsvd */
+#define SWF14_PM_TYPE_MASK 0x00070000
+#define SWF14_PM_ACPI_VIDEO (0x4 << 16)
+#define SWF14_PM_ACPI (0x3 << 16)
+#define SWF14_PM_APM_12 (0x2 << 16)
+#define SWF14_PM_APM_11 (0x1 << 16)
+#define SWF14_HK_REQUEST_MASK 0x0000ffff /* see GR18 6:3 for event type */
+ /* if GR18 indicates a display switch */
+#define SWF14_DS_PIPEB_LFP2_EN (1<<15)
+#define SWF14_DS_PIPEB_EFP2_EN (1<<14)
+#define SWF14_DS_PIPEB_TV2_EN (1<<13)
+#define SWF14_DS_PIPEB_CRT2_EN (1<<12)
+#define SWF14_DS_PIPEB_LFP_EN (1<<11)
+#define SWF14_DS_PIPEB_EFP_EN (1<<10)
+#define SWF14_DS_PIPEB_TV_EN (1<<9)
+#define SWF14_DS_PIPEB_CRT_EN (1<<8)
+#define SWF14_DS_PIPEA_LFP2_EN (1<<7)
+#define SWF14_DS_PIPEA_EFP2_EN (1<<6)
+#define SWF14_DS_PIPEA_TV2_EN (1<<5)
+#define SWF14_DS_PIPEA_CRT2_EN (1<<4)
+#define SWF14_DS_PIPEA_LFP_EN (1<<3)
+#define SWF14_DS_PIPEA_EFP_EN (1<<2)
+#define SWF14_DS_PIPEA_TV_EN (1<<1)
+#define SWF14_DS_PIPEA_CRT_EN (1<<0)
+ /* if GR18 indicates a panel fitting request */
+#define SWF14_PFIT_EN (1<<0) /* 0 means disable */
+ /* if GR18 indicates an APM change request */
+#define SWF14_APM_HIBERNATE 0x4
+#define SWF14_APM_SUSPEND 0x3
+#define SWF14_APM_STANDBY 0x1
+#define SWF14_APM_RESTORE 0x0
+
+#endif /* _INTEL_BIOS_H_ */
diff --git a/tools/intel_bios_dumper.c b/tools/intel_bios_dumper.c
new file mode 100644
index 00000000..6455689f
--- /dev/null
+++ b/tools/intel_bios_dumper.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright © 2007 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:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pciaccess.h>
+#include <err.h>
+
+#ifndef DEFFILEMODE
+#define DEFFILEMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) /* 0666 */
+#endif
+
+static void usage(void)
+{
+ fprintf(stderr, "usage: bios_dumper <filename>\n");
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ struct pci_device *dev;
+ void *bios;
+ int error, fd;
+
+ if (argc != 2)
+ usage();
+
+ error = pci_system_init();
+ if (error != 0) {
+ fprintf(stderr, "Couldn't initialize PCI system: %s\n",
+ strerror(error));
+ exit(1);
+ }
+
+ /* Grab the graphics card */
+ dev = pci_device_find_by_slot(0, 0, 2, 0);
+ if (dev == NULL)
+ errx(1, "Couldn't find graphics card");
+
+ error = pci_device_probe(dev);
+ if (error != 0) {
+ fprintf(stderr, "Couldn't probe graphics card: %s\n",
+ strerror(error));
+ exit(1);
+ }
+
+ if (dev->vendor_id != 0x8086)
+ errx(1, "Graphics card is non-intel");
+
+ /* Some versions of libpciaccess correct this automatically, but some
+ * don't. */
+ if (dev->rom_size == 0)
+ dev->rom_size = 64 * 1024;
+
+ bios = malloc(dev->rom_size);
+ if (bios == NULL)
+ errx(1, "Couldn't allocate memory for BIOS data\n");
+
+ error = pci_device_read_rom(dev, bios);
+ if (error != 0) {
+ fprintf(stderr, "Couldn't read graphics card ROM: %s\n",
+ strerror(error));
+ exit(1);
+ }
+
+ fd = open(argv[1], O_RDWR | O_CREAT | O_TRUNC, DEFFILEMODE);
+ if (fd < 0) {
+ fprintf(stderr, "Couldn't open output: %s\n", strerror(errno));
+ exit(1);
+ }
+
+ if (write(fd, bios, dev->rom_size) < dev->rom_size) {
+ fprintf(stderr, "Couldn't write BIOS data: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+
+ close(fd);
+ pci_system_cleanup();
+
+ return 0;
+}
diff --git a/tools/intel_bios_reader.c b/tools/intel_bios_reader.c
new file mode 100644
index 00000000..493fb637
--- /dev/null
+++ b/tools/intel_bios_reader.c
@@ -0,0 +1,947 @@
+/*
+ * Copyright 2006 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:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "intel_bios.h"
+#include "intel_gpu_tools.h"
+
+static uint32_t devid = -1;
+
+/* no bother to include "edid.h" */
+#define _H_ACTIVE(x) (x[2] + ((x[4] & 0xF0) << 4))
+#define _H_SYNC_OFF(x) (x[8] + ((x[11] & 0xC0) << 2))
+#define _H_SYNC_WIDTH(x) (x[9] + ((x[11] & 0x30) << 4))
+#define _H_BLANK(x) (x[3] + ((x[4] & 0x0F) << 8))
+#define _V_ACTIVE(x) (x[5] + ((x[7] & 0xF0) << 4))
+#define _V_SYNC_OFF(x) ((x[10] >> 4) + ((x[11] & 0x0C) << 2))
+#define _V_SYNC_WIDTH(x) ((x[10] & 0x0F) + ((x[11] & 0x03) << 4))
+#define _V_BLANK(x) (x[6] + ((x[7] & 0x0F) << 8))
+#define _PIXEL_CLOCK(x) (x[0] + (x[1] << 8)) * 10000
+
+uint8_t *VBIOS;
+
+#define INTEL_BIOS_8(_addr) (VBIOS[_addr])
+#define INTEL_BIOS_16(_addr) (VBIOS[_addr] | \
+ (VBIOS[_addr + 1] << 8))
+#define INTEL_BIOS_32(_addr) (VBIOS[_addr] | \
+ (VBIOS[_addr + 1] << 8) | \
+ (VBIOS[_addr + 2] << 16) | \
+ (VBIOS[_addr + 3] << 24))
+
+#define YESNO(val) ((val) ? "yes" : "no")
+
+struct bdb_block {
+ uint8_t id;
+ uint16_t size;
+ void *data;
+};
+
+struct bdb_header *bdb;
+static int tv_present;
+static int lvds_present;
+static int panel_type;
+
+static struct bdb_block *find_section(int section_id, int length)
+{
+ struct bdb_block *block;
+ unsigned char *base = (unsigned char *)bdb;
+ int idx = 0;
+ uint16_t total, current_size;
+ unsigned char current_id;
+
+ /* skip to first section */
+ idx += bdb->header_size;
+ total = bdb->bdb_size;
+ if (total > length)
+ total = length;
+
+ block = malloc(sizeof(*block));
+ if (!block) {
+ fprintf(stderr, "out of memory\n");
+ exit(-1);
+ }
+
+ /* walk the sections looking for section_id */
+ while (idx + 3 < total) {
+ current_id = *(base + idx);
+ current_size = *(uint16_t *)(base + idx + 1);
+ if (idx + current_size > total)
+ return NULL;
+
+ if (current_id == section_id) {
+ block->id = current_id;
+ block->size = current_size;
+ block->data = base + idx + 3;
+ return block;
+ }
+
+ idx += current_size + 3;
+ }
+
+ free(block);
+ return NULL;
+}
+
+static void dump_general_features(int length)
+{
+ struct bdb_general_features *features;
+ struct bdb_block *block;
+
+ block = find_section(BDB_GENERAL_FEATURES, length);
+
+ if (!block)
+ return;
+
+ features = block->data;
+
+ printf("General features block:\n");
+
+ printf("\tPanel fitting: ");
+ switch (features->panel_fitting) {
+ case 0:
+ printf("disabled\n");
+ break;
+ case 1:
+ printf("text only\n");
+ break;
+ case 2:
+ printf("graphics only\n");
+ break;
+ case 3:
+ printf("text & graphics\n");
+ break;
+ }
+ printf("\tFlexaim: %s\n", YESNO(features->flexaim));
+ printf("\tMessage: %s\n", YESNO(features->msg_enable));
+ printf("\tClear screen: %d\n", features->clear_screen);
+ printf("\tDVO color flip required: %s\n", YESNO(features->color_flip));
+ printf("\tExternal VBT: %s\n", YESNO(features->download_ext_vbt));
+ printf("\tEnable SSC: %s\n", YESNO(features->enable_ssc));
+ if (features->enable_ssc) {
+ if (HAS_PCH_SPLIT(devid))
+ printf("\tSSC frequency: %s\n", features->ssc_freq ?
+ "100 MHz" : "120 MHz");
+ else
+ printf("\tSSC frequency: %s\n", features->ssc_freq ?
+ "100 MHz (66 MHz on 855)" : "96 MHz (48 MHz on 855)");
+ }
+ printf("\tLFP on override: %s\n",
+ YESNO(features->enable_lfp_on_override));
+ printf("\tDisable SSC on clone: %s\n",
+ YESNO(features->disable_ssc_ddt));
+ printf("\tDisable smooth vision: %s\n",
+ YESNO(features->disable_smooth_vision));
+ printf("\tSingle DVI for CRT/DVI: %s\n", YESNO(features->single_dvi));
+ printf("\tLegacy monitor detect: %s\n",
+ YESNO(features->legacy_monitor_detect));
+ printf("\tIntegrated CRT: %s\n", YESNO(features->int_crt_support));
+ printf("\tIntegrated TV: %s\n", YESNO(features->int_tv_support));
+
+ tv_present = 1; /* should be based on whether TV DAC exists */
+ lvds_present = 1; /* should be based on IS_MOBILE() */
+
+ free(block);
+}
+
+static void dump_backlight_info(int length)
+{
+ struct bdb_block *block;
+ struct bdb_lvds_backlight *backlight;
+ struct blc_struct *blc;
+
+ block = find_section(BDB_LVDS_BACKLIGHT, length);
+
+ if (!block)
+ return;
+
+ backlight = block->data;
+
+ printf("Backlight info block (len %d):\n", block->size);
+
+ if (sizeof(struct blc_struct) != backlight->blcstruct_size) {
+ printf("\tBacklight struct sizes don't match (expected %zu, got %u), skipping\n",
+ sizeof(struct blc_struct), backlight->blcstruct_size);
+ return;
+ }
+
+ blc = &backlight->panels[panel_type];
+
+ printf("\tInverter type: %d\n", blc->inverter_type);
+ printf("\t polarity: %d\n", blc->inverter_polarity);
+ printf("\t GPIO pins: %d\n", blc->gpio_pins);
+ printf("\t GMBUS speed: %d\n", blc->gmbus_speed);
+ printf("\t PWM freq: %d\n", blc->pwm_freq);
+ printf("\tMinimum brightness: %d\n", blc->min_brightness);
+ printf("\tI2C slave addr: 0x%02x\n", blc->i2c_slave_addr);
+ printf("\tI2C command: 0x%02x\n", blc->i2c_cmd);
+}
+
+static const struct {
+ unsigned short type;
+ const char *name;
+} child_device_types[] = {
+ { DEVICE_TYPE_NONE, "none" },
+ { DEVICE_TYPE_CRT, "CRT" },
+ { DEVICE_TYPE_TV, "TV" },
+ { DEVICE_TYPE_EFP, "EFP" },
+ { DEVICE_TYPE_LFP, "LFP" },
+ { DEVICE_TYPE_CRT_DPMS, "CRT" },
+ { DEVICE_TYPE_CRT_DPMS_HOTPLUG, "CRT" },
+ { DEVICE_TYPE_TV_COMPOSITE, "TV composite" },
+ { DEVICE_TYPE_TV_MACROVISION, "TV" },
+ { DEVICE_TYPE_TV_RF_COMPOSITE, "TV" },
+ { DEVICE_TYPE_TV_SVIDEO_COMPOSITE, "TV S-Video" },
+ { DEVICE_TYPE_TV_SCART, "TV SCART" },
+ { DEVICE_TYPE_TV_CODEC_HOTPLUG_PWR, "TV" },
+ { DEVICE_TYPE_EFP_HOTPLUG_PWR, "EFP" },
+ { DEVICE_TYPE_EFP_DVI_HOTPLUG_PWR, "DVI" },
+ { DEVICE_TYPE_EFP_DVI_I, "DVI-I" },
+ { DEVICE_TYPE_EFP_DVI_D_DUAL, "DL-DVI-D" },
+ { DEVICE_TYPE_EFP_DVI_D_HDCP, "DVI-D" },
+ { DEVICE_TYPE_OPENLDI_HOTPLUG_PWR, "OpenLDI" },
+ { DEVICE_TYPE_OPENLDI_DUALPIX, "OpenLDI" },
+ { DEVICE_TYPE_LFP_PANELLINK, "PanelLink" },
+ { DEVICE_TYPE_LFP_CMOS_PWR, "CMOS LFP" },
+ { DEVICE_TYPE_LFP_LVDS_PWR, "LVDS" },
+ { DEVICE_TYPE_LFP_LVDS_DUAL, "LVDS" },
+ { DEVICE_TYPE_LFP_LVDS_DUAL_HDCP, "LVDS" },
+ { DEVICE_TYPE_INT_LFP, "LFP" },
+ { DEVICE_TYPE_INT_TV, "TV" },
+ { DEVICE_TYPE_DP, "DisplayPort" },
+ { DEVICE_TYPE_DP_HDMI_DVI, "DisplayPort/HDMI/DVI" },
+ { DEVICE_TYPE_DP_DVI, "DisplayPort/DVI" },
+ { DEVICE_TYPE_HDMI_DVI, "HDMI/DVI" },
+ { DEVICE_TYPE_DVI, "DVI" },
+ { DEVICE_TYPE_eDP, "eDP" },
+};
+static const int num_child_device_types =
+ sizeof(child_device_types) / sizeof(child_device_types[0]);
+
+static const char *child_device_type(unsigned short type)
+{
+ int i;
+
+ for (i = 0; i < num_child_device_types; i++)
+ if (child_device_types[i].type == type)
+ return child_device_types[i].name;
+
+ return "unknown";
+}
+
+static const struct {
+ unsigned short type;
+ const char *name;
+} efp_ports[] = {
+ { DEVICE_PORT_NONE, "N/A" },
+ { DEVICE_PORT_HDMIB, "HDMI-B" },
+ { DEVICE_PORT_HDMIC, "HDMI-C" },
+ { DEVICE_PORT_HDMID, "HDMI-D" },
+ { DEVICE_PORT_DPB, "DP-B" },
+ { DEVICE_PORT_DPC, "DP-C" },
+ { DEVICE_PORT_DPD, "DP-D" },
+};
+static const int num_efp_ports = sizeof(efp_ports) / sizeof(efp_ports[0]);
+
+static const char *efp_port(uint8_t type)
+{
+ int i;
+
+ for (i = 0; i < num_efp_ports; i++)
+ if (efp_ports[i].type == type)
+ return efp_ports[i].name;
+
+ return "unknown";
+}
+
+static const struct {
+ unsigned short type;
+ const char *name;
+} efp_conn_info[] = {
+ { DEVICE_INFO_NONE, "N/A" },
+ { DEVICE_INFO_HDMI_CERT, "HDMI certified" },
+ { DEVICE_INFO_DP, "DisplayPort" },
+ { DEVICE_INFO_DVI, "DVI" },
+};
+static const int num_efp_conn_info = sizeof(efp_conn_info) / sizeof(efp_conn_info[0]);
+
+static const char *efp_conn(uint8_t type)
+{
+ int i;
+
+ for (i = 0; i < num_efp_conn_info; i++)
+ if (efp_conn_info[i].type == type)
+ return efp_conn_info[i].name;
+
+ return "unknown";
+}
+
+
+
+static void dump_child_device(struct child_device_config *child)
+{
+ char child_id[11];
+
+ if (!child->device_type)
+ return;
+
+ if (bdb->version < 152) {
+ strncpy(child_id, (char *)child->device_id, 10);
+ child_id[10] = 0;
+
+ printf("\tChild device info:\n");
+ printf("\t\tDevice type: %04x (%s)\n", child->device_type,
+ child_device_type(child->device_type));
+ printf("\t\tSignature: %s\n", child_id);
+ printf("\t\tAIM offset: %d\n", child->addin_offset);
+ printf("\t\tDVO port: 0x%02x\n", child->dvo_port);
+ } else { /* 152+ have EFP blocks here */
+ struct efp_child_device_config *efp =
+ (struct efp_child_device_config *)child;
+ printf("\tEFP device info:\n");
+ printf("\t\tDevice type: 0x%04x (%s)\n", efp->device_type,
+ child_device_type(efp->device_type));
+ printf("\t\tPort: 0x%02x (%s)\n", efp->port,
+ efp_port(efp->port));
+ printf("\t\tDDC pin: 0x%02x\n", efp->ddc_pin);
+ printf("\t\tDock port: 0x%02x (%s)\n", efp->docked_port,
+ efp_port(efp->docked_port));
+ printf("\t\tHDMI compatible? %s\n", efp->hdmi_compat ? "Yes" : "No");
+ printf("\t\tInfo: %s\n", efp_conn(efp->conn_info));
+ printf("\t\tAux channel: 0x%02x\n", efp->aux_chan);
+ printf("\t\tDongle detect: 0x%02x\n", efp->dongle_detect);
+ }
+}
+
+static void dump_general_definitions(int length)
+{
+ struct bdb_block *block;
+ struct bdb_general_definitions *defs;
+ struct child_device_config *child;
+ int i;
+ int child_device_num;
+
+ block = find_section(BDB_GENERAL_DEFINITIONS, length);
+
+ if (!block)
+ return;
+
+ defs = block->data;
+
+ printf("General definitions block:\n");
+
+ printf("\tCRT DDC GMBUS addr: 0x%02x\n", defs->crt_ddc_gmbus_pin);
+ printf("\tUse ACPI DPMS CRT power states: %s\n",
+ YESNO(defs->dpms_acpi));
+ printf("\tSkip CRT detect at boot: %s\n",
+ YESNO(defs->skip_boot_crt_detect));
+ printf("\tUse DPMS on AIM devices: %s\n", YESNO(defs->dpms_aim));
+ printf("\tBoot display type: 0x%02x%02x\n", defs->boot_display[1],
+ defs->boot_display[0]);
+ printf("\tTV data block present: %s\n", YESNO(tv_present));
+ child_device_num = (block->size - sizeof(*defs)) / sizeof(*child);
+ for (i = 0; i < child_device_num; i++)
+ dump_child_device(&defs->devices[i]);
+ free(block);
+}
+
+static void dump_child_devices(int length)
+{
+ struct bdb_block *block;
+ struct bdb_child_devices *child_devs;
+ struct child_device_config *child;
+ int i;
+
+ block = find_section(BDB_CHILD_DEVICE_TABLE, length);
+ if (!block) {
+ printf("No child device table found\n");
+ return;
+ }
+
+ child_devs = block->data;
+
+ printf("Child devices block:\n");
+ for (i = 0; i < DEVICE_CHILD_SIZE; i++) {
+ child = &child_devs->children[i];
+ /* Skip nonexistent children */
+ if (!child->device_type)
+ continue;
+ printf("\tChild device %d\n", i);
+ printf("\t\tType: 0x%04x (%s)\n", child->device_type,
+ child_device_type(child->device_type));
+ printf("\t\tDVO port: 0x%02x\n", child->dvo_port);
+ printf("\t\tI2C pin: 0x%02x\n", child->i2c_pin);
+ printf("\t\tSlave addr: 0x%02x\n", child->slave_addr);
+ printf("\t\tDDC pin: 0x%02x\n", child->ddc_pin);
+ printf("\t\tDVO config: 0x%02x\n", child->dvo_cfg);
+ printf("\t\tDVO wiring: 0x%02x\n", child->dvo_wiring);
+ }
+
+ free(block);
+}
+
+static void dump_lvds_options(int length)
+{
+ struct bdb_block *block;
+ struct bdb_lvds_options *options;
+
+ block = find_section(BDB_LVDS_OPTIONS, length);
+ if (!block) {
+ printf("No LVDS options block\n");
+ return;
+ }
+
+ options = block->data;
+
+ printf("LVDS options block:\n");
+
+ panel_type = options->panel_type;
+ printf("\tPanel type: %d\n", panel_type);
+ printf("\tLVDS EDID available: %s\n", YESNO(options->lvds_edid));
+ printf("\tPixel dither: %s\n", YESNO(options->pixel_dither));
+ printf("\tPFIT auto ratio: %s\n", YESNO(options->pfit_ratio_auto));
+ printf("\tPFIT enhanced graphics mode: %s\n",
+ YESNO(options->pfit_gfx_mode_enhanced));
+ printf("\tPFIT enhanced text mode: %s\n",
+ YESNO(options->pfit_text_mode_enhanced));
+ printf("\tPFIT mode: %d\n", options->pfit_mode);
+
+ free(block);
+}
+
+static void dump_lvds_ptr_data(int length)
+{
+ struct bdb_block *block;
+ struct bdb_lvds_lfp_data *lvds_data;
+ struct bdb_lvds_lfp_data_ptrs *ptrs;
+ struct lvds_fp_timing *fp_timing;
+ struct bdb_lvds_lfp_data_entry *entry;
+ int lfp_data_size;
+
+ block = find_section(BDB_LVDS_LFP_DATA_PTRS, length);
+ if (!block) {
+ printf("No LFP data pointers block\n");
+ return;
+ }
+ ptrs = block->data;
+
+ block = find_section(BDB_LVDS_LFP_DATA, length);
+ if (!block) {
+ printf("No LVDS data block\n");
+ return;
+ }
+ lvds_data = block->data;
+
+ lfp_data_size =
+ ptrs->ptr[1].fp_timing_offset - ptrs->ptr[0].fp_timing_offset;
+ entry =
+ (struct bdb_lvds_lfp_data_entry *)((uint8_t *) lvds_data->data +
+ (lfp_data_size * panel_type));
+ fp_timing = &entry->fp_timing;
+
+ printf("LVDS timing pointer data:\n");
+ printf(" Number of entries: %d\n", ptrs->lvds_entries);
+
+ printf("\tpanel type %02i: %dx%d\n", panel_type, fp_timing->x_res,
+ fp_timing->y_res);
+
+ free(block);
+}
+
+static void dump_lvds_data(int length)
+{
+ struct bdb_block *block;
+ struct bdb_lvds_lfp_data *lvds_data;
+ struct bdb_lvds_lfp_data_ptrs *ptrs;
+ int num_entries;
+ int i;
+ int hdisplay, hsyncstart, hsyncend, htotal;
+ int vdisplay, vsyncstart, vsyncend, vtotal;
+ float clock;
+ int lfp_data_size, dvo_offset;
+
+ block = find_section(BDB_LVDS_LFP_DATA_PTRS, length);
+ if (!block) {
+ printf("No LVDS ptr block\n");
+ return;
+ }
+ ptrs = block->data;
+ lfp_data_size =
+ ptrs->ptr[1].fp_timing_offset - ptrs->ptr[0].fp_timing_offset;
+ dvo_offset =
+ ptrs->ptr[0].dvo_timing_offset - ptrs->ptr[0].fp_timing_offset;
+ free(block);
+
+ block = find_section(BDB_LVDS_LFP_DATA, length);
+ if (!block) {
+ printf("No LVDS data block\n");
+ return;
+ }
+
+ lvds_data = block->data;
+ num_entries = block->size / lfp_data_size;
+
+ printf("LVDS panel data block (preferred block marked with '*'):\n");
+ printf(" Number of entries: %d\n", num_entries);
+
+ for (i = 0; i < num_entries; i++) {
+ uint8_t *lfp_data_ptr =
+ (uint8_t *) lvds_data->data + lfp_data_size * i;
+ uint8_t *timing_data = lfp_data_ptr + dvo_offset;
+ struct bdb_lvds_lfp_data_entry *lfp_data =
+ (struct bdb_lvds_lfp_data_entry *)lfp_data_ptr;
+ char marker;
+
+ if (i == panel_type)
+ marker = '*';
+ else
+ marker = ' ';
+
+ hdisplay = _H_ACTIVE(timing_data);
+ hsyncstart = hdisplay + _H_SYNC_OFF(timing_data);
+ hsyncend = hsyncstart + _H_SYNC_WIDTH(timing_data);
+ htotal = hdisplay + _H_BLANK(timing_data);
+
+ vdisplay = _V_ACTIVE(timing_data);
+ vsyncstart = vdisplay + _V_SYNC_OFF(timing_data);
+ vsyncend = vsyncstart + _V_SYNC_WIDTH(timing_data);
+ vtotal = vdisplay + _V_BLANK(timing_data);
+ clock = _PIXEL_CLOCK(timing_data) / 1000;
+
+ printf("%c\tpanel type %02i: %dx%d clock %d\n", marker,
+ i, lfp_data->fp_timing.x_res, lfp_data->fp_timing.y_res,
+ _PIXEL_CLOCK(timing_data));
+ printf("\t\tinfo:\n");
+ printf("\t\t LVDS: 0x%08lx\n",
+ (unsigned long)lfp_data->fp_timing.lvds_reg_val);
+ printf("\t\t PP_ON_DELAYS: 0x%08lx\n",
+ (unsigned long)lfp_data->fp_timing.pp_on_reg_val);
+ printf("\t\t PP_OFF_DELAYS: 0x%08lx\n",
+ (unsigned long)lfp_data->fp_timing.pp_off_reg_val);
+ printf("\t\t PP_DIVISOR: 0x%08lx\n",
+ (unsigned long)lfp_data->fp_timing.pp_cycle_reg_val);
+ printf("\t\t PFIT: 0x%08lx\n",
+ (unsigned long)lfp_data->fp_timing.pfit_reg_val);
+ printf("\t\ttimings: %d %d %d %d %d %d %d %d %.2f (%s)\n",
+ hdisplay, hsyncstart, hsyncend, htotal,
+ vdisplay, vsyncstart, vsyncend, vtotal, clock,
+ (hsyncend > htotal || vsyncend > vtotal) ?
+ "BAD!" : "good");
+ }
+ free(block);
+}
+
+static void dump_driver_feature(int length)
+{
+ struct bdb_block *block;
+ struct bdb_driver_feature *feature;
+
+ block = find_section(BDB_DRIVER_FEATURES, length);
+ if (!block) {
+ printf("No Driver feature data block\n");
+ return;
+ }
+ feature = block->data;
+
+ printf("Driver feature Data Block:\n");
+ printf("\tBoot Device Algorithm: %s\n", feature->boot_dev_algorithm ?
+ "driver default" : "os default");
+ printf("\tBlock display switching when DVD active: %s\n",
+ YESNO(feature->block_display_switch));
+ printf("\tAllow display switching when in Full Screen DOS: %s\n",
+ YESNO(feature->allow_display_switch));
+ printf("\tHot Plug DVO: %s\n", YESNO(feature->hotplug_dvo));
+ printf("\tDual View Zoom: %s\n", YESNO(feature->dual_view_zoom));
+ printf("\tDriver INT 15h hook: %s\n", YESNO(feature->int15h_hook));
+ printf("\tEnable Sprite in Clone Mode: %s\n",
+ YESNO(feature->sprite_in_clone));
+ printf("\tUse 00000110h ID for Primary LFP: %s\n",
+ YESNO(feature->primary_lfp_id));
+ printf("\tBoot Mode X: %u\n", feature->boot_mode_x);
+ printf("\tBoot Mode Y: %u\n", feature->boot_mode_y);
+ printf("\tBoot Mode Bpp: %u\n", feature->boot_mode_bpp);
+ printf("\tBoot Mode Refresh: %u\n", feature->boot_mode_refresh);
+ printf("\tEnable LFP as primary: %s\n",
+ YESNO(feature->enable_lfp_primary));
+ printf("\tSelective Mode Pruning: %s\n",
+ YESNO(feature->selective_mode_pruning));
+ printf("\tDual-Frequency Graphics Technology: %s\n",
+ YESNO(feature->dual_frequency));
+ printf("\tDefault Render Clock Frequency: %s\n",
+ feature->render_clock_freq ? "low" : "high");
+ printf("\tNT 4.0 Dual Display Clone Support: %s\n",
+ YESNO(feature->nt_clone_support));
+ printf("\tDefault Power Scheme user interface: %s\n",
+ feature->power_scheme_ui ? "3rd party" : "CUI");
+ printf
+ ("\tSprite Display Assignment when Overlay is Active in Clone Mode: %s\n",
+ feature->sprite_display_assign ? "primary" : "secondary");
+ printf("\tDisplay Maintain Aspect Scaling via CUI: %s\n",
+ YESNO(feature->cui_aspect_scaling));
+ printf("\tPreserve Aspect Ratio: %s\n",
+ YESNO(feature->preserve_aspect_ratio));
+ printf("\tEnable SDVO device power down: %s\n",
+ YESNO(feature->sdvo_device_power_down));
+ printf("\tCRT hotplug: %s\n", YESNO(feature->crt_hotplug));
+ printf("\tLVDS config: ");
+ switch (feature->lvds_config) {
+ case BDB_DRIVER_NO_LVDS:
+ printf("No LVDS\n");
+ break;
+ case BDB_DRIVER_INT_LVDS:
+ printf("Integrated LVDS\n");
+ break;
+ case BDB_DRIVER_SDVO_LVDS:
+ printf("SDVO LVDS\n");
+ break;
+ case BDB_DRIVER_EDP:
+ printf("Embedded DisplayPort\n");
+ break;
+ }
+ printf("\tDefine Display statically: %s\n",
+ YESNO(feature->static_display));
+ printf("\tLegacy CRT max X: %d\n", feature->legacy_crt_max_x);
+ printf("\tLegacy CRT max Y: %d\n", feature->legacy_crt_max_y);
+ printf("\tLegacy CRT max refresh: %d\n",
+ feature->legacy_crt_max_refresh);
+ free(block);
+}
+
+static void dump_edp(int length)
+{
+ struct bdb_block *block;
+ struct bdb_edp *edp;
+ int bpp;
+
+ block = find_section(BDB_EDP, length);
+ if (!block) {
+ printf("No EDP data block\n");
+ return;
+ }
+ edp = block->data;
+
+ printf("eDP block: type %d\n", panel_type);
+ printf("\tPower Sequence: T3 %d T7 %d T9 %d T10 %d T12 %d\n",
+ edp->power_seqs[panel_type].t3,
+ edp->power_seqs[panel_type].t7,
+ edp->power_seqs[panel_type].t9,
+ edp->power_seqs[panel_type].t10,
+ edp->power_seqs[panel_type].t12);
+
+ bpp = (edp->color_depth >> (panel_type * 2)) & 3;
+
+ printf("\tPanel color depth: ");
+ switch (bpp) {
+ case EDP_18BPP:
+ printf("18bpp\n");
+ break;
+ case EDP_24BPP:
+ printf("24bpp\n");
+ break;
+ case EDP_30BPP:
+ printf("30bpp\n");
+ break;
+ }
+ printf("\teDP sDRRs MSA timing delay: %d\n", edp->sdrrs_msa_timing_delay);
+ printf("\tLink params:\n");
+ printf("\t\trate: ");
+ if (edp->link_params[panel_type].rate == EDP_RATE_1_62)
+ printf("1.62G\n");
+ else if (edp->link_params[panel_type].rate == EDP_RATE_2_7)
+ printf("2.7G\n");
+ printf("\t\tlanes: ");
+ switch (edp->link_params[panel_type].lanes) {
+ case EDP_LANE_1:
+ printf("x1 mode\n");
+ break;
+ case EDP_LANE_2:
+ printf("x2 mode\n");
+ break;
+ case EDP_LANE_4:
+ printf("x4 mode\n");
+ break;
+ }
+ printf("\t\tpre-emphasis: ");
+ switch (edp->link_params[panel_type].preemphasis) {
+ case EDP_PREEMPHASIS_NONE:
+ printf("none\n");
+ break;
+ case EDP_PREEMPHASIS_3_5dB:
+ printf("3.5dB\n");
+ break;
+ case EDP_PREEMPHASIS_6dB:
+ printf("6dB\n");
+ break;
+ case EDP_PREEMPHASIS_9_5dB:
+ printf("9.5dB\n");
+ break;
+ }
+ printf("\t\tvswing: ");
+ switch (edp->link_params[panel_type].vswing) {
+ case EDP_VSWING_0_4V:
+ printf("0.4V\n");
+ break;
+ case EDP_VSWING_0_6V:
+ printf("0.6V\n");
+ break;
+ case EDP_VSWING_0_8V:
+ printf("0.8V\n");
+ break;
+ case EDP_VSWING_1_2V:
+ printf("1.2V\n");
+ break;
+ }
+ free(block);
+}
+
+static void
+print_detail_timing_data(struct lvds_dvo_timing2 *dvo_timing)
+{
+ int display, sync_start, sync_end, total;
+
+ display = (dvo_timing->hactive_hi << 8) | dvo_timing->hactive_lo;
+ sync_start = display +
+ ((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo);
+ sync_end = sync_start + dvo_timing->hsync_pulse_width;
+ total = display +
+ ((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo);
+ printf("\thdisplay: %d\n", display);
+ printf("\thsync [%d, %d] %s\n", sync_start, sync_end,
+ dvo_timing->hsync_positive ? "+sync" : "-sync");
+ printf("\thtotal: %d\n", total);
+
+ display = (dvo_timing->vactive_hi << 8) | dvo_timing->vactive_lo;
+ sync_start = display + dvo_timing->vsync_off;
+ sync_end = sync_start + dvo_timing->vsync_pulse_width;
+ total = display +
+ ((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo);
+ printf("\tvdisplay: %d\n", display);
+ printf("\tvsync [%d, %d] %s\n", sync_start, sync_end,
+ dvo_timing->vsync_positive ? "+sync" : "-sync");
+ printf("\tvtotal: %d\n", total);
+
+ printf("\tclock: %d\n", dvo_timing->clock * 10);
+}
+
+static void dump_sdvo_panel_dtds(int length)
+{
+ struct bdb_block *block;
+ struct lvds_dvo_timing2 *dvo_timing;
+ int n, count;
+
+ block = find_section(BDB_SDVO_PANEL_DTDS, length);
+ if (!block) {
+ printf("No SDVO panel dtds block\n");
+ return;
+ }
+
+ printf("SDVO panel dtds:\n");
+ count = block->size / sizeof(struct lvds_dvo_timing2);
+ dvo_timing = block->data;
+ for (n = 0; n < count; n++) {
+ printf("%d:\n", n);
+ print_detail_timing_data(dvo_timing++);
+ }
+
+ free(block);
+}
+
+static void dump_sdvo_lvds_options(int length)
+{
+ struct bdb_block *block;
+ struct bdb_sdvo_lvds_options *options;
+
+ block = find_section(BDB_SDVO_LVDS_OPTIONS, length);
+ if (!block) {
+ printf("No SDVO LVDS options block\n");
+ return;
+ }
+
+ options = block->data;
+
+ printf("SDVO LVDS options block:\n");
+ printf("\tbacklight: %d\n", options->panel_backlight);
+ printf("\th40 type: %d\n", options->h40_set_panel_type);
+ printf("\ttype: %d\n", options->panel_type);
+ printf("\tssc_clk_freq: %d\n", options->ssc_clk_freq);
+ printf("\tals_low_trip: %d\n", options->als_low_trip);
+ printf("\tals_high_trip: %d\n", options->als_high_trip);
+ /*
+ u8 sclalarcoeff_tab_row_num;
+ u8 sclalarcoeff_tab_row_size;
+ u8 coefficient[8];
+ */
+ printf("\tmisc[0]: %x\n", options->panel_misc_bits_1);
+ printf("\tmisc[1]: %x\n", options->panel_misc_bits_2);
+ printf("\tmisc[2]: %x\n", options->panel_misc_bits_3);
+ printf("\tmisc[3]: %x\n", options->panel_misc_bits_4);
+
+ free(block);
+}
+
+static int
+get_device_id(unsigned char *bios)
+{
+ int device;
+ int offset = (bios[0x19] << 8) + bios[0x18];
+
+ if (bios[offset] != 'P' ||
+ bios[offset+1] != 'C' ||
+ bios[offset+2] != 'I' ||
+ bios[offset+3] != 'R')
+ return -1;
+
+ device = (bios[offset+7] << 8) + bios[offset+6];
+
+ return device;
+}
+
+int main(int argc, char **argv)
+{
+ int fd;
+ struct vbt_header *vbt = NULL;
+ int vbt_off, bdb_off, i;
+ const char *filename = "bios";
+ struct stat finfo;
+ struct bdb_block *block;
+ char signature[17];
+ char *devid_string;
+
+ if (argc != 2) {
+ printf("usage: %s <rom file>\n", argv[0]);
+ return 1;
+ }
+
+ if ((devid_string = getenv("DEVICE")))
+ devid = strtoul(devid_string, NULL, 0);
+
+ filename = argv[1];
+
+ fd = open(filename, O_RDONLY);
+ if (fd == -1) {
+ printf("Couldn't open \"%s\": %s\n", filename, strerror(errno));
+ return 1;
+ }
+
+ if (stat(filename, &finfo)) {
+ printf("failed to stat \"%s\": %s\n", filename,
+ strerror(errno));
+ return 1;
+ }
+
+ if (finfo.st_size == 0) {
+ int len = 0, ret;
+ finfo.st_size = 8192;
+ VBIOS = malloc (finfo.st_size);
+ while ((ret = read(fd, VBIOS + len, finfo.st_size - len))) {
+ if (ret < 0) {
+ printf("failed to read \"%s\": %s\n", filename,
+ strerror(errno));
+ return 1;
+ }
+
+ len += ret;
+ if (len == finfo.st_size) {
+ finfo.st_size *= 2;
+ VBIOS = realloc(VBIOS, finfo.st_size);
+ }
+ }
+ } else {
+ VBIOS = mmap(NULL, finfo.st_size, PROT_READ, MAP_SHARED, fd, 0);
+ if (VBIOS == MAP_FAILED) {
+ printf("failed to map \"%s\": %s\n", filename, strerror(errno));
+ return 1;
+ }
+ }
+
+ /* Scour memory looking for the VBT signature */
+ for (i = 0; i + 4 < finfo.st_size; i++) {
+ if (!memcmp(VBIOS + i, "$VBT", 4)) {
+ vbt_off = i;
+ vbt = (struct vbt_header *)(VBIOS + i);
+ break;
+ }
+ }
+
+ if (!vbt) {
+ printf("VBT signature missing\n");
+ return 1;
+ }
+
+ printf("VBT vers: %d.%d\n", vbt->version / 100, vbt->version % 100);
+
+ bdb_off = vbt_off + vbt->bdb_offset;
+ if (bdb_off >= finfo.st_size - sizeof(struct bdb_header)) {
+ printf("Invalid VBT found, BDB points beyond end of data block\n");
+ return 1;
+ }
+
+ bdb = (struct bdb_header *)(VBIOS + bdb_off);
+ strncpy(signature, (char *)bdb->signature, 16);
+ signature[16] = 0;
+ printf("BDB sig: %s\n", signature);
+ printf("BDB vers: %d\n", bdb->version);
+
+ printf("Available sections: ");
+ for (i = 0; i < 256; i++) {
+ block = find_section(i, finfo.st_size);
+ if (!block)
+ continue;
+ printf("%d ", i);
+ free(block);
+ }
+ printf("\n");
+
+ if (devid == -1)
+ devid = get_device_id(VBIOS);
+ if (devid == -1)
+ printf("Warning: could not find PCI device ID!\n");
+
+ dump_general_features(finfo.st_size);
+ dump_general_definitions(finfo.st_size);
+ dump_child_devices(finfo.st_size);
+ dump_lvds_options(finfo.st_size);
+ dump_lvds_data(finfo.st_size);
+ dump_lvds_ptr_data(finfo.st_size);
+ dump_backlight_info(finfo.st_size);
+
+ dump_sdvo_lvds_options(finfo.st_size);
+ dump_sdvo_panel_dtds(finfo.st_size);
+
+ dump_driver_feature(finfo.st_size);
+ dump_edp(finfo.st_size);
+
+ return 0;
+}
diff --git a/tools/intel_disable_clock_gating.c b/tools/intel_disable_clock_gating.c
new file mode 100644
index 00000000..8dde3e18
--- /dev/null
+++ b/tools/intel_disable_clock_gating.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright © 2010 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:
+ * Zhenyu Wang <zhenyuw@linux.intel.com>
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+#include <string.h>
+#include "intel_gpu_tools.h"
+
+int main(int argc, char** argv)
+{
+ struct pci_device *pci_dev;
+
+ pci_dev = intel_get_pci_device();
+ intel_get_mmio(pci_dev);
+
+ if (IS_GEN5(pci_dev->device_id)) {
+ printf("Restore method:\n");
+
+ printf("intel_reg_write 0x%x 0x%08x\n",
+ PCH_3DCGDIS0, INREG(PCH_3DCGDIS0));
+ OUTREG(PCH_3DCGDIS0, 0xffffffff);
+
+ printf("intel_reg_write 0x%x 0x%08x\n",
+ PCH_3DCGDIS1, INREG(PCH_3DCGDIS1));
+ OUTREG(PCH_3DCGDIS1, 0xffffffff);
+
+ printf("intel_reg_write 0x%x 0x%08x\n",
+ PCH_3DRAMCGDIS0, INREG(PCH_3DRAMCGDIS0));
+ OUTREG(PCH_3DRAMCGDIS0, 0xffffffff);
+
+ printf("intel_reg_write 0x%x 0x%08x\n",
+ PCH_DSPCLK_GATE_D, INREG(PCH_DSPCLK_GATE_D));
+ OUTREG(PCH_DSPCLK_GATE_D, 0xffffffff);
+
+ printf("intel_reg_write 0x%x 0x%08x\n",
+ PCH_DSPRAMCLK_GATE_D, INREG(PCH_DSPRAMCLK_GATE_D));
+ OUTREG(PCH_DSPRAMCLK_GATE_D, 0xffffffff);
+ } else {
+ fprintf(stderr, "unsupported chipset\n");
+ }
+
+
+ return 0;
+}
+
diff --git a/tools/intel_dpio_read.c b/tools/intel_dpio_read.c
new file mode 100644
index 00000000..c0c904a6
--- /dev/null
+++ b/tools/intel_dpio_read.c
@@ -0,0 +1,68 @@
+/*
+ * 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:
+ * Vijay Purushothaman <vijay.a.purushothaman@intel.com>
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+#include <string.h>
+#include "intel_gpu_tools.h"
+
+static void usage(char *cmdname)
+{
+ printf("Warning : This program will work only on Valleyview\n");
+ printf("Usage: %s [addr]\n", cmdname);
+ printf("\t addr : in 0xXXXX format\n");
+}
+
+int main(int argc, char** argv)
+{
+ int ret = 0;
+ uint32_t reg, val;
+ char *cmdname = strdup(argv[0]);
+ struct pci_device *dev = intel_get_pci_device();
+
+ if (argc != 2 || !IS_VALLEYVIEW(dev->device_id)) {
+ usage(cmdname);
+ ret = 1;
+ goto out;
+ }
+
+ sscanf(argv[1], "0x%x", &reg);
+
+ intel_register_access_init(dev, 0);
+
+ val = intel_dpio_reg_read(reg);
+
+ printf("Read DPIO register: 0x%x - Value : 0x%x\n", reg, val);
+
+ intel_register_access_fini();
+
+out:
+ free(cmdname);
+ return ret;
+}
diff --git a/tools/intel_dpio_write.c b/tools/intel_dpio_write.c
new file mode 100644
index 00000000..f8429990
--- /dev/null
+++ b/tools/intel_dpio_write.c
@@ -0,0 +1,67 @@
+/*
+ * 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:
+ * Vijay Purushothaman <vijay.a.purushothaman@intel.com>
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+#include <string.h>
+#include "intel_gpu_tools.h"
+
+static void usage(char *cmdname)
+{
+ printf("Warning : This program will work only on Valleyview\n");
+ printf("Usage: %s [addr] [val]\n", cmdname);
+ printf("\t addr : in 0xXXXX format\n");
+}
+
+int main(int argc, char** argv)
+{
+ int ret = 0;
+ uint32_t reg, val;
+ char *cmdname = strdup(argv[0]);
+ struct pci_device *dev = intel_get_pci_device();
+
+ if (argc != 3 || !IS_VALLEYVIEW(dev->device_id)) {
+ usage(cmdname);
+ ret = 1;
+ goto out;
+ }
+
+ sscanf(argv[1], "0x%x", &reg);
+ sscanf(argv[2], "0x%x", &val);
+
+ intel_register_access_init(dev, 0);
+
+ intel_dpio_reg_write(reg, val);
+
+ intel_register_access_fini();
+
+out:
+ free(cmdname);
+ return ret;
+}
diff --git a/tools/intel_dump_decode.c b/tools/intel_dump_decode.c
new file mode 100644
index 00000000..a3cd2e59
--- /dev/null
+++ b/tools/intel_dump_decode.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright © 2010 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:
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ */
+
+#define _GNU_SOURCE
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <getopt.h>
+
+#include <intel_bufmgr.h>
+
+struct drm_intel_decode *ctx;
+
+static void
+read_bin_file(const char * filename)
+{
+ uint32_t buf[16384];
+ int fd, offset, ret;
+
+ if (!strcmp(filename, "-"))
+ fd = fileno(stdin);
+ else
+ fd = open (filename, O_RDONLY);
+ if (fd < 0) {
+ fprintf (stderr, "Failed to open %s: %s\n",
+ filename, strerror (errno));
+ exit (1);
+ }
+
+ drm_intel_decode_set_dump_past_end(ctx, 1);
+
+ offset = 0;
+ while ((ret = read (fd, buf, sizeof(buf))) > 0) {
+ drm_intel_decode_set_batch_pointer(ctx, buf, offset, ret/4);
+ drm_intel_decode(ctx);
+ offset += ret;
+ }
+ close (fd);
+}
+
+static void
+read_data_file(const char * filename)
+{
+ FILE *file;
+ uint32_t *data = NULL;
+ int data_size = 0, count = 0, line_number = 0, matched;
+ char *line = NULL;
+ size_t line_size;
+ uint32_t offset, value;
+ uint32_t gtt_offset = 0;
+
+ if (!strcmp(filename, "-"))
+ file = stdin;
+ else
+ file = fopen (filename, "r");
+
+ if (file == NULL) {
+ fprintf (stderr, "Failed to open %s: %s\n",
+ filename, strerror (errno));
+ exit (1);
+ }
+
+ while (getline (&line, &line_size, file) > 0) {
+ line_number++;
+
+ matched = sscanf (line, "%08x : %08x", &offset, &value);
+ if (matched != 2) {
+ printf("ignoring line %s", line);
+
+ continue;
+ }
+
+ count++;
+
+ if (count > data_size) {
+ data_size = data_size ? data_size * 2 : 1024;
+ data = realloc (data, data_size * sizeof (uint32_t));
+ if (data == NULL) {
+ fprintf (stderr, "Out of memory.\n");
+ exit (1);
+ }
+ }
+
+ data[count-1] = value;
+ }
+
+ if (count) {
+ drm_intel_decode_set_batch_pointer(ctx, data, gtt_offset, count);
+ drm_intel_decode(ctx);
+ }
+
+ free (data);
+ free (line);
+
+ fclose (file);
+}
+
+static void
+read_autodetect_file(const char * filename)
+{
+ int binary = 0, c;
+ FILE *file;
+
+ file = fopen (filename, "r");
+ if (file == NULL) {
+ fprintf (stderr, "Failed to open %s: %s\n",
+ filename, strerror (errno));
+ exit (1);
+ }
+
+ while ((c = fgetc(file)) != EOF) {
+ /* totally lazy binary detector */
+ if (c < 10) {
+ binary = 1;
+ break;
+ }
+ }
+
+ fclose(file);
+
+ if (binary == 1)
+ read_bin_file(filename);
+ else
+ read_data_file(filename);
+
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ uint32_t devid = 0xa011;
+ int i, c;
+ int option_index = 0;
+ int binary = -1;
+
+ static struct option long_options[] = {
+ {"devid", 1, 0, 'd'},
+ {"ascii", 0, 0, 'a'},
+ {"binary", 0, 0, 'b'}
+ };
+
+ while((c = getopt_long(argc, argv, "ab",
+ long_options, &option_index)) != -1) {
+ switch(c) {
+ case 'd':
+ devid = strtoul(optarg, NULL, 0);
+ break;
+ case 'b':
+ binary = 1;
+ break;
+ case 'a':
+ binary = 0;
+ break;
+ default:
+ printf("unkown command options\n");
+ break;
+ }
+ }
+
+ ctx = drm_intel_decode_context_alloc(devid);
+
+ if (optind == argc) {
+ fprintf(stderr, "no input file given\n");
+ exit(-1);
+ }
+
+ for (i = optind; i < argc; i++) {
+ /* For stdin input, let's read as data file */
+ if (!strcmp(argv[i], "-")) {
+ read_data_file(argv[i]);
+ continue;
+ }
+ if (binary == 1)
+ read_bin_file(argv[i]);
+ else if (binary == 0)
+ read_data_file(argv[i]);
+ else
+ read_autodetect_file(argv[i]);
+ }
+
+ return 0;
+}
diff --git a/tools/intel_error_decode.c b/tools/intel_error_decode.c
new file mode 100644
index 00000000..e0ec8f60
--- /dev/null
+++ b/tools/intel_error_decode.c
@@ -0,0 +1,515 @@
+/* -*- c-basic-offset: 4 -*- */
+/*
+ * Copyright © 2007 Intel Corporation
+ * Copyright © 2009 Intel Corporation
+ * Copyright © 2010 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:
+ * Eric Anholt <eric@anholt.net>
+ * Carl Worth <cworth@cworth.org>
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ */
+
+/** @file intel_decode.c
+ * This file contains code to print out batchbuffer contents in a
+ * human-readable format.
+ *
+ * The current version only supports i915 packets, and only pretty-prints a
+ * subset of them. The intention is for it to make just a best attempt to
+ * decode, but never crash in the process.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <err.h>
+#include <intel_bufmgr.h>
+
+#include "intel_chipset.h"
+#include "intel_gpu_tools.h"
+#include "instdone.h"
+
+static void
+print_instdone (uint32_t devid, unsigned int instdone, unsigned int instdone1)
+{
+ int i;
+ static int once;
+
+ if (!once) {
+ init_instdone_definitions(devid);
+ once = 1;
+ }
+
+ for (i = 0; i < num_instdone_bits; i++) {
+ int busy = 0;
+
+ if (instdone_bits[i].reg == INST_DONE_1) {
+ if (!(instdone1 & instdone_bits[i].bit))
+ busy = 1;
+ } else {
+ if (!(instdone & instdone_bits[i].bit))
+ busy = 1;
+ }
+
+ if (busy)
+ printf(" busy: %s\n", instdone_bits[i].name);
+ }
+}
+
+static void
+print_i830_pgtbl_err(unsigned int reg)
+{
+ const char *str;
+
+ switch((reg >> 3) & 0xf) {
+ case 0x1: str = "Overlay TLB"; break;
+ case 0x2: str = "Display A TLB"; break;
+ case 0x3: str = "Host TLB"; break;
+ case 0x4: str = "Render TLB"; break;
+ case 0x5: str = "Display C TLB"; break;
+ case 0x6: str = "Mapping TLB"; break;
+ case 0x7: str = "Command Stream TLB"; break;
+ case 0x8: str = "Vertex Buffer TLB"; break;
+ case 0x9: str = "Display B TLB"; break;
+ case 0xa: str = "Reserved System Memory"; break;
+ case 0xb: str = "Compressor TLB"; break;
+ case 0xc: str = "Binner TLB"; break;
+ default: str = "unknown"; break;
+ }
+
+ if (str)
+ printf (" source = %s\n", str);
+
+ switch(reg & 0x7) {
+ case 0x0: str = "Invalid GTT"; break;
+ case 0x1: str = "Invalid GTT PTE"; break;
+ case 0x2: str = "Invalid Memory"; break;
+ case 0x3: str = "Invalid TLB miss"; break;
+ case 0x4: str = "Invalid PTE data"; break;
+ case 0x5: str = "Invalid LocalMemory not present"; break;
+ case 0x6: str = "Invalid Tiling"; break;
+ case 0x7: str = "Host to CAM"; break;
+ }
+ printf (" error = %s\n", str);
+}
+
+static void
+print_i915_pgtbl_err(unsigned int reg)
+{
+ if (reg & (1 << 29))
+ printf (" Cursor A: Invalid GTT PTE\n");
+ if (reg & (1 << 28))
+ printf (" Cursor B: Invalid GTT PTE\n");
+ if (reg & (1 << 27))
+ printf (" MT: Invalid tiling\n");
+ if (reg & (1 << 26))
+ printf (" MT: Invalid GTT PTE\n");
+ if (reg & (1 << 25))
+ printf (" LC: Invalid tiling\n");
+ if (reg & (1 << 24))
+ printf (" LC: Invalid GTT PTE\n");
+ if (reg & (1 << 23))
+ printf (" BIN VertexData: Invalid GTT PTE\n");
+ if (reg & (1 << 22))
+ printf (" BIN Instruction: Invalid GTT PTE\n");
+ if (reg & (1 << 21))
+ printf (" CS VertexData: Invalid GTT PTE\n");
+ if (reg & (1 << 20))
+ printf (" CS Instruction: Invalid GTT PTE\n");
+ if (reg & (1 << 19))
+ printf (" CS: Invalid GTT\n");
+ if (reg & (1 << 18))
+ printf (" Overlay: Invalid tiling\n");
+ if (reg & (1 << 16))
+ printf (" Overlay: Invalid GTT PTE\n");
+ if (reg & (1 << 14))
+ printf (" Display C: Invalid tiling\n");
+ if (reg & (1 << 12))
+ printf (" Display C: Invalid GTT PTE\n");
+ if (reg & (1 << 10))
+ printf (" Display B: Invalid tiling\n");
+ if (reg & (1 << 8))
+ printf (" Display B: Invalid GTT PTE\n");
+ if (reg & (1 << 6))
+ printf (" Display A: Invalid tiling\n");
+ if (reg & (1 << 4))
+ printf (" Display A: Invalid GTT PTE\n");
+ if (reg & (1 << 1))
+ printf (" Host Invalid PTE data\n");
+ if (reg & (1 << 0))
+ printf (" Host Invalid GTT PTE\n");
+}
+
+static void
+print_i965_pgtbl_err(unsigned int reg)
+{
+ if (reg & (1 << 26))
+ printf (" Invalid Sampler Cache GTT entry\n");
+ if (reg & (1 << 24))
+ printf (" Invalid Render Cache GTT entry\n");
+ if (reg & (1 << 23))
+ printf (" Invalid Instruction/State Cache GTT entry\n");
+ if (reg & (1 << 22))
+ printf (" There is no ROC, this cannot occur!\n");
+ if (reg & (1 << 21))
+ printf (" Invalid GTT entry during Vertex Fetch\n");
+ if (reg & (1 << 20))
+ printf (" Invalid GTT entry during Command Fetch\n");
+ if (reg & (1 << 19))
+ printf (" Invalid GTT entry during CS\n");
+ if (reg & (1 << 18))
+ printf (" Invalid GTT entry during Cursor Fetch\n");
+ if (reg & (1 << 17))
+ printf (" Invalid GTT entry during Overlay Fetch\n");
+ if (reg & (1 << 8))
+ printf (" Invalid GTT entry during Display B Fetch\n");
+ if (reg & (1 << 4))
+ printf (" Invalid GTT entry during Display A Fetch\n");
+ if (reg & (1 << 1))
+ printf (" Valid PTE references illegal memory\n");
+ if (reg & (1 << 0))
+ printf (" Invalid GTT entry during fetch for host\n");
+}
+
+static void
+print_pgtbl_err(unsigned int reg, unsigned int devid)
+{
+ if (IS_965(devid)) {
+ return print_i965_pgtbl_err(reg);
+ } else if (IS_GEN3(devid)) {
+ return print_i915_pgtbl_err(reg);
+ } else {
+ return print_i830_pgtbl_err(reg);
+ }
+}
+
+static void
+print_snb_fence(unsigned int devid, uint64_t fence)
+{
+ printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %u\n",
+ fence & 1 ? "" : "in",
+ fence & (1<<1) ? 'y' : 'x',
+ (int)(((fence>>32)&0xfff)+1)*128,
+ (uint32_t)fence & 0xfffff000,
+ (uint32_t)(((fence>>32)&0xfffff000) - (fence&0xfffff000) + 4096));
+}
+
+static void
+print_i965_fence(unsigned int devid, uint64_t fence)
+{
+ printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %u\n",
+ fence & 1 ? "" : "in",
+ fence & (1<<1) ? 'y' : 'x',
+ (int)(((fence>>2)&0x1ff)+1)*128,
+ (uint32_t)fence & 0xfffff000,
+ (uint32_t)(((fence>>32)&0xfffff000) - (fence&0xfffff000) + 4096));
+}
+
+static void
+print_i915_fence(unsigned int devid, uint64_t fence)
+{
+ unsigned tile_width;
+ if ((fence & 12) && !IS_915(devid))
+ tile_width = 128;
+ else
+ tile_width = 512;
+
+ printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %i\n",
+ fence & 1 ? "" : "in",
+ fence & 12 ? 'y' : 'x',
+ (1<<((fence>>4)&0xf))*tile_width,
+ (uint32_t)fence & 0xff00000,
+ 1<<(20 + ((fence>>8)&0xf)));
+}
+
+static void
+print_i830_fence(unsigned int devid, uint64_t fence)
+{
+ printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %i\n",
+ fence & 1 ? "" : "in",
+ fence & 12 ? 'y' : 'x',
+ (1<<((fence>>4)&0xf))*128,
+ (uint32_t)fence & 0x7f80000,
+ 1<<(19 + ((fence>>8)&0xf)));
+}
+
+static void
+print_fence(unsigned int devid, uint64_t fence)
+{
+ if (IS_GEN6(devid) || IS_GEN7(devid)) {
+ return print_snb_fence(devid, fence);
+ } else if (IS_GEN4(devid) || IS_GEN5(devid)) {
+ return print_i965_fence(devid, fence);
+ } else if (IS_GEN3(devid)) {
+ return print_i915_fence(devid, fence);
+ } else {
+ return print_i830_fence(devid, fence);
+ }
+}
+
+static void
+read_data_file (FILE *file)
+{
+ struct drm_intel_decode *decode_ctx = NULL;
+ uint32_t devid = PCI_CHIP_I855_GM;
+ uint32_t *data = NULL;
+ long long unsigned fence;
+ int data_size = 0, count = 0, line_number = 0, matched;
+ char *line = NULL;
+ size_t line_size;
+ uint32_t offset, value;
+ uint32_t gtt_offset = 0, new_gtt_offset;
+ const char *buffer_type[2] = { "ringbuffer", "batchbuffer" };
+ char *ring_name = NULL;
+ int is_batch = 1;
+
+ while (getline (&line, &line_size, file) > 0) {
+ char *dashes;
+ line_number++;
+
+ dashes = strstr(line, "---");
+ if (dashes) {
+ char *new_ring_name = malloc(dashes - line);
+ strncpy(new_ring_name, line, dashes - line);
+ new_ring_name[dashes - line - 1] = '\0';
+
+ matched = sscanf (dashes, "--- gtt_offset = 0x%08x\n",
+ &new_gtt_offset);
+ if (matched == 1) {
+ if (count) {
+ printf("%s (%s) at 0x%08x:\n",
+ buffer_type[is_batch],
+ ring_name,
+ gtt_offset);
+ drm_intel_decode_set_batch_pointer(decode_ctx,
+ data, gtt_offset,
+ count);
+ drm_intel_decode(decode_ctx);
+ count = 0;
+ }
+ gtt_offset = new_gtt_offset;
+ is_batch = 1;
+ free(ring_name);
+ ring_name = new_ring_name;
+ continue;
+ }
+
+ matched = sscanf (dashes, "--- ringbuffer = 0x%08x\n",
+ &new_gtt_offset);
+ if (matched == 1) {
+ if (count) {
+ printf("%s (%s) at 0x%08x:\n",
+ buffer_type[is_batch],
+ ring_name,
+ gtt_offset);
+ drm_intel_decode_set_batch_pointer(decode_ctx,
+ data, gtt_offset,
+ count);
+ drm_intel_decode(decode_ctx);
+ count = 0;
+ }
+ gtt_offset = new_gtt_offset;
+ is_batch = 0;
+ free(ring_name);
+ ring_name = new_ring_name;
+ continue;
+ }
+ }
+
+ matched = sscanf (line, "%08x : %08x", &offset, &value);
+ if (matched != 2) {
+ unsigned int reg;
+
+ /* display reg section is after the ringbuffers, don't mix them */
+ if (count) {
+ printf("%s (%s) at 0x%08x:\n",
+ buffer_type[is_batch],
+ ring_name,
+ gtt_offset);
+ drm_intel_decode_set_batch_pointer(decode_ctx,
+ data, gtt_offset,
+ count);
+ drm_intel_decode(decode_ctx);
+ count = 0;
+ }
+
+ printf("%s", line);
+
+ matched = sscanf (line, "PCI ID: 0x%04x\n", &reg);
+ if (matched == 0)
+ matched = sscanf (line, " PCI ID: 0x%04x\n", &reg);
+ if (matched == 1) {
+ devid = reg;
+ printf("Detected GEN%i chipset\n",
+ intel_gen(devid));
+
+ decode_ctx = drm_intel_decode_context_alloc(devid);
+ }
+
+ matched = sscanf (line, " ACTHD: 0x%08x\n", &reg);
+ if (matched == 1)
+ drm_intel_decode_set_head_tail(decode_ctx, reg, 0xffffffff);
+
+ matched = sscanf (line, " PGTBL_ER: 0x%08x\n", &reg);
+ if (matched == 1 && reg)
+ print_pgtbl_err(reg, devid);
+
+ matched = sscanf (line, " INSTDONE: 0x%08x\n", &reg);
+ if (matched == 1)
+ print_instdone (devid, reg, -1);
+
+ matched = sscanf (line, " INSTDONE1: 0x%08x\n", &reg);
+ if (matched == 1)
+ print_instdone (devid, -1, reg);
+
+ matched = sscanf (line, " fence[%i] = %Lx\n", &reg, &fence);
+ if (matched == 2)
+ print_fence (devid, fence);
+
+ continue;
+ }
+
+ count++;
+
+ if (count > data_size) {
+ data_size = data_size ? data_size * 2 : 1024;
+ data = realloc (data, data_size * sizeof (uint32_t));
+ if (data == NULL) {
+ fprintf (stderr, "Out of memory.\n");
+ exit (1);
+ }
+ }
+
+ data[count-1] = value;
+ }
+
+ if (count) {
+ printf("%s (%s) at 0x%08x:\n",
+ buffer_type[is_batch],
+ ring_name,
+ gtt_offset);
+ drm_intel_decode_set_batch_pointer(decode_ctx,
+ data, gtt_offset,
+ count);
+ drm_intel_decode(decode_ctx);
+ }
+
+ free (data);
+ free (line);
+ free (ring_name);
+}
+
+int
+main (int argc, char *argv[])
+{
+ FILE *file;
+ const char *path;
+ char *filename = NULL;
+ struct stat st;
+ int error;
+
+ if (argc > 2) {
+ fprintf (stderr,
+ "intel_gpu_decode: Parse an Intel GPU i915_error_state\n"
+ "Usage:\n"
+ "\t%s [<file>]\n"
+ "\n"
+ "With no arguments, debugfs-dri-directory is probed for in "
+ "/debug and \n"
+ "/sys/kernel/debug. Otherwise, it may be "
+ "specified. If a file is given,\n"
+ "it is parsed as an GPU dump in the format of "
+ "/debug/dri/0/i915_error_state.\n",
+ argv[0]);
+ return 1;
+ }
+
+ if (argc == 1) {
+ if (isatty(0)) {
+ path = "/debug/dri";
+ error = stat (path, &st);
+ if (error != 0) {
+ path = "/sys/kernel/debug/dri";
+ error = stat (path, &st);
+ if (error != 0) {
+ errx(1,
+ "Couldn't find i915 debugfs directory.\n\n"
+ "Is debugfs mounted? You might try mounting it with a command such as:\n\n"
+ "\tsudo mount -t debugfs debugfs /sys/kernel/debug\n");
+ }
+ }
+ } else {
+ read_data_file(stdin);
+ exit(0);
+ }
+ } else {
+ path = argv[1];
+ error = stat (path, &st);
+ if (error != 0) {
+ fprintf (stderr, "Error opening %s: %s\n",
+ path, strerror (errno));
+ exit (1);
+ }
+ }
+
+ if (S_ISDIR (st.st_mode)) {
+ asprintf (&filename, "%s/i915_error_state", path);
+ file = fopen(filename, "r");
+ if (!file) {
+ int minor;
+ for (minor = 0; minor < 64; minor++) {
+ free(filename);
+ asprintf(&filename, "%s/%d/i915_error_state", path, minor);
+ file = fopen(filename, "r");
+ if (file)
+ break;
+ }
+ }
+ if (!file) {
+ fprintf (stderr, "Failed to find i915_error_state beneath %s\n",
+ path);
+ exit (1);
+ }
+ } else {
+ file = fopen(path, "r");
+ if (!file) {
+ fprintf (stderr, "Failed to open %s: %s\n",
+ path, strerror (errno));
+ exit (1);
+ }
+ }
+
+ read_data_file (file);
+ fclose (file);
+
+ if (filename != path)
+ free (filename);
+
+ return 0;
+}
diff --git a/tools/intel_forcewaked.c b/tools/intel_forcewaked.c
new file mode 100644
index 00000000..3ab2d6f8
--- /dev/null
+++ b/tools/intel_forcewaked.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright © 2011 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:
+ * Ben Widawsky <ben@bwidawsk.net>
+ *
+ */
+
+#include <assert.h>
+#include <err.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <unistd.h>
+#include "intel_gpu_tools.h"
+
+bool daemonized;
+
+#define INFO_PRINT(...) \
+ do { \
+ if (daemonized) \
+ syslog(LOG_INFO, ##__VA_ARGS__); \
+ else \
+ fprintf(stdout, ##__VA_ARGS__); \
+ } while(0)
+
+static void
+help(char *prog) {
+ printf("%s Prevents the GT from sleeping.\n\n", prog);
+ printf("usage: %s [options] \n\n", prog);
+ printf("Options: \n");
+ printf(" -b Run in background/daemon mode\n");
+}
+
+static int
+is_alive(void) {
+ /* Read the timestamp, which should *almost* always be !0 */
+ return (intel_register_read(0x2358) != 0);
+}
+
+int main(int argc, char *argv[])
+{
+ int ret;
+
+ if (argc > 2 || (argc == 2 && !strncmp(argv[1], "-h", 2))) {
+ help(argv[1]);
+ exit(0);
+ }
+
+ if (argc == 2 && (!strncmp(argv[1], "-b", 2)))
+ daemonized = true;
+
+ if (daemonized) {
+ assert(daemon(0, 0) == 0);
+ openlog(argv[0], LOG_CONS | LOG_PID, LOG_USER);
+ INFO_PRINT("started daemon");
+ }
+
+ ret = intel_register_access_init(intel_get_pci_device(), 1);
+ if (ret) {
+ INFO_PRINT("Couldn't init register access\n");
+ exit(1);
+ } else {
+ INFO_PRINT("Forcewake locked\n");
+ }
+ while(1) {
+ if (!is_alive()) {
+ INFO_PRINT("gpu reset? restarting daemon\n");
+ intel_register_access_fini();
+ ret = intel_register_access_init(intel_get_pci_device(),
+ 1);
+ }
+ sleep(1);
+ }
+ intel_register_access_fini();
+ INFO_PRINT("Forcewake unlock\n");
+
+ if (daemonized) {
+ INFO_PRINT("finished\n");
+ closelog();
+ }
+
+ return 0;
+}
diff --git a/tools/intel_gpu_abrt b/tools/intel_gpu_abrt
new file mode 100755
index 00000000..141a5246
--- /dev/null
+++ b/tools/intel_gpu_abrt
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+if [ -d /debug/dri ] ; then
+ debugfs_path=/debug_dri
+fi
+
+if [ -d /sys/kernel/debug/dri ] ; then
+ debugfs_path=/sys/kernel/debug/dri
+fi
+
+i915_debugfs=x
+for dir in `ls $debugfs_path` ; do
+ if [ -f $debugfs_path/$dir/i915_error_state ] ; then
+ i915_debugfs=$debugfs_path/$dir
+ break
+ fi
+done
+
+if [ $i915_debugfs = "x" ] ; then
+ echo i915 debugfs path not found.
+ exit 1
+fi
+
+tmpdir=`mktemp -d`
+tardir=$tmpdir/intel_gpu_abrt
+mkdir $tardir
+
+mkdir $tardir/debugfs
+cp $i915_debugfs/* $tardir/debugfs
+
+mkdir $tardir/mod_opts
+cp /sys/module/i915/parameters/* $tardir/mod_opts
+
+mkdir $tardir/X
+cp /var/log/Xorg.*.log $tardir/X
+cp /etc/X11/xorg.conf $tardir/X
+
+dmesg > $tardir/dmesg
+lspci -nn > $tardir/lspci
+
+(cd $tmpdir; tar -c intel_gpu_abrt ) > intel_gpu_abrt.tar
+
+rm $tmpdir -Rf
+
+exit 0
diff --git a/tools/intel_gpu_time.c b/tools/intel_gpu_time.c
new file mode 100644
index 00000000..c30b84d2
--- /dev/null
+++ b/tools/intel_gpu_time.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright © 2007,2009 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:
+ * Eric Anholt <eric@anholt.net>
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ */
+
+#include <unistd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+
+#include "intel_gpu_tools.h"
+
+#define SAMPLES_PER_SEC 10000
+
+static volatile int goddo;
+
+static pid_t spawn(char **argv)
+{
+ pid_t pid;
+
+ pid = fork();
+ if (pid != 0)
+ return pid;
+
+ execvp(argv[0], argv);
+ exit(1);
+}
+
+static void sighandler(int sig)
+{
+ goddo = sig;
+}
+
+int main(int argc, char **argv)
+{
+ pid_t child;
+ uint64_t ring_idle = 0, ring_time = 0;
+ struct timeval start, end;
+ static struct rusage rusage;
+ int status;
+
+ intel_get_mmio(intel_get_pci_device());
+
+ if (argc == 1) {
+ fprintf(stderr, "usage: %s cmd [args...]\n", argv[0]);
+ return 1;
+ }
+
+ signal(SIGCHLD, sighandler);
+ signal(SIGINT, SIG_IGN);
+ signal(SIGQUIT, SIG_IGN);
+
+ gettimeofday(&start, NULL);
+ child = spawn(argv+1);
+ if (child < 0)
+ return 127;
+
+ while (!goddo) {
+ uint32_t ring_head, ring_tail;
+
+ ring_head = INREG(LP_RING + RING_HEAD) & HEAD_ADDR;
+ ring_tail = INREG(LP_RING + RING_TAIL) & TAIL_ADDR;
+
+ if (ring_tail == ring_head)
+ ring_idle++;
+ ring_time++;
+
+ usleep(1000000 / SAMPLES_PER_SEC);
+ }
+ gettimeofday(&end, NULL);
+ timersub(&end, &start, &end);
+
+ waitpid(child, &status, 0);
+
+ getrusage(RUSAGE_CHILDREN, &rusage);
+ printf("user: %ld.%06lds, sys: %ld.%06lds, elapsed: %ld.%06lds, CPU: %.1f%%, GPU: %.1f%%\n",
+ rusage.ru_utime.tv_sec, rusage.ru_utime.tv_usec,
+ rusage.ru_stime.tv_sec, rusage.ru_stime.tv_usec,
+ end.tv_sec, end.tv_usec,
+ 100*(rusage.ru_utime.tv_sec + 1e-6*rusage.ru_utime.tv_usec + rusage.ru_stime.tv_sec + 1e-6*rusage.ru_stime.tv_usec) / (end.tv_sec + 1e-6*end.tv_usec),
+ 100 - ring_idle * 100. / ring_time);
+
+ return WEXITSTATUS(status);
+}
diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
new file mode 100644
index 00000000..e561865c
--- /dev/null
+++ b/tools/intel_gpu_top.c
@@ -0,0 +1,716 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ * Copyright © 2011 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:
+ * Eric Anholt <eric@anholt.net>
+ * Eugeni Dodonov <eugeni.dodonov@intel.com>
+ *
+ */
+
+#include "config.h"
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <string.h>
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif
+#include "intel_gpu_tools.h"
+#include "instdone.h"
+
+#define FORCEWAKE 0xA18C
+#define FORCEWAKE_ACK 0x130090
+
+#define SAMPLES_PER_SEC 10000
+#define SAMPLES_TO_PERCENT_RATIO (SAMPLES_PER_SEC / 100)
+
+#define MAX_NUM_TOP_BITS 100
+
+#define HAS_STATS_REGS(devid) IS_965(devid)
+
+struct top_bit {
+ struct instdone_bit *bit;
+ int count;
+} top_bits[MAX_NUM_TOP_BITS];
+struct top_bit *top_bits_sorted[MAX_NUM_TOP_BITS];
+
+static uint32_t instdone, instdone1;
+
+static const char *bars[] = {
+ " ",
+ "▏",
+ "▎",
+ "▍",
+ "▌",
+ "▋",
+ "▊",
+ "▉",
+ "█"
+};
+
+enum stats_counts {
+ IA_VERTICES,
+ IA_PRIMITIVES,
+ VS_INVOCATION,
+ GS_INVOCATION,
+ GS_PRIMITIVES,
+ CL_INVOCATION,
+ CL_PRIMITIVES,
+ PS_INVOCATION,
+ PS_DEPTH,
+ STATS_COUNT
+};
+
+const uint32_t stats_regs[STATS_COUNT] = {
+ IA_VERTICES_COUNT_QW,
+ IA_PRIMITIVES_COUNT_QW,
+ VS_INVOCATION_COUNT_QW,
+ GS_INVOCATION_COUNT_QW,
+ GS_PRIMITIVES_COUNT_QW,
+ CL_INVOCATION_COUNT_QW,
+ CL_PRIMITIVES_COUNT_QW,
+ PS_INVOCATION_COUNT_QW,
+ PS_DEPTH_COUNT_QW,
+};
+
+const char *stats_reg_names[STATS_COUNT] = {
+ "vert fetch",
+ "prim fetch",
+ "VS invocations",
+ "GS invocations",
+ "GS prims",
+ "CL invocations",
+ "CL prims",
+ "PS invocations",
+ "PS depth pass",
+};
+
+uint64_t stats[STATS_COUNT];
+uint64_t last_stats[STATS_COUNT];
+
+static unsigned long
+gettime(void)
+{
+ struct timeval t;
+ gettimeofday(&t, NULL);
+ return (t.tv_usec + (t.tv_sec * 1000000));
+}
+
+static int
+top_bits_sort(const void *a, const void *b)
+{
+ struct top_bit * const *bit_a = a;
+ struct top_bit * const *bit_b = b;
+ int a_count = (*bit_a)->count;
+ int b_count = (*bit_b)->count;
+
+ if (a_count < b_count)
+ return 1;
+ else if (a_count == b_count)
+ return 0;
+ else
+ return -1;
+}
+
+static void
+update_idle_bit(struct top_bit *top_bit)
+{
+ uint32_t reg_val;
+
+ if (top_bit->bit->reg == INST_DONE_1)
+ reg_val = instdone1;
+ else
+ reg_val = instdone;
+
+ if ((reg_val & top_bit->bit->bit) == 0)
+ top_bit->count++;
+}
+
+static void
+print_clock(const char *name, int clock) {
+ if (clock == -1)
+ printf("%s clock: unknown", name);
+ else
+ printf("%s clock: %d Mhz", name, clock);
+}
+
+static int
+print_clock_info(struct pci_device *pci_dev)
+{
+ uint32_t devid = pci_dev->device_id;
+ uint16_t gcfgc;
+
+ if (IS_GM45(devid)) {
+ int core_clock = -1;
+
+ pci_device_cfg_read_u16(pci_dev, &gcfgc, I915_GCFGC);
+
+ switch (gcfgc & 0xf) {
+ case 8:
+ core_clock = 266;
+ break;
+ case 9:
+ core_clock = 320;
+ break;
+ case 11:
+ core_clock = 400;
+ break;
+ case 13:
+ core_clock = 533;
+ break;
+ }
+ print_clock("core", core_clock);
+ } else if (IS_965(devid) && IS_MOBILE(devid)) {
+ int render_clock = -1, sampler_clock = -1;
+
+ pci_device_cfg_read_u16(pci_dev, &gcfgc, I915_GCFGC);
+
+ switch (gcfgc & 0xf) {
+ case 2:
+ render_clock = 250; sampler_clock = 267;
+ break;
+ case 3:
+ render_clock = 320; sampler_clock = 333;
+ break;
+ case 4:
+ render_clock = 400; sampler_clock = 444;
+ break;
+ case 5:
+ render_clock = 500; sampler_clock = 533;
+ break;
+ }
+
+ print_clock("render", render_clock);
+ printf(" ");
+ print_clock("sampler", sampler_clock);
+ } else if (IS_945(devid) && IS_MOBILE(devid)) {
+ int render_clock = -1, display_clock = -1;
+
+ pci_device_cfg_read_u16(pci_dev, &gcfgc, I915_GCFGC);
+
+ switch (gcfgc & 0x7) {
+ case 0:
+ render_clock = 166;
+ break;
+ case 1:
+ render_clock = 200;
+ break;
+ case 3:
+ render_clock = 250;
+ break;
+ case 5:
+ render_clock = 400;
+ break;
+ }
+
+ switch (gcfgc & 0x70) {
+ case 0:
+ display_clock = 200;
+ break;
+ case 4:
+ display_clock = 320;
+ break;
+ }
+ if (gcfgc & (1 << 7))
+ display_clock = 133;
+
+ print_clock("render", render_clock);
+ printf(" ");
+ print_clock("display", display_clock);
+ } else if (IS_915(devid) && IS_MOBILE(devid)) {
+ int render_clock = -1, display_clock = -1;
+
+ pci_device_cfg_read_u16(pci_dev, &gcfgc, I915_GCFGC);
+
+ switch (gcfgc & 0x7) {
+ case 0:
+ render_clock = 160;
+ break;
+ case 1:
+ render_clock = 190;
+ break;
+ case 4:
+ render_clock = 333;
+ break;
+ }
+ if (gcfgc & (1 << 13))
+ render_clock = 133;
+
+ switch (gcfgc & 0x70) {
+ case 0:
+ display_clock = 190;
+ break;
+ case 4:
+ display_clock = 333;
+ break;
+ }
+ if (gcfgc & (1 << 7))
+ display_clock = 133;
+
+ print_clock("render", render_clock);
+ printf(" ");
+ print_clock("display", display_clock);
+ }
+
+
+ printf("\n");
+ return -1;
+}
+
+#define STATS_LEN (20)
+#define PERCENTAGE_BAR_END (79 - STATS_LEN)
+
+static void
+print_percentage_bar(float percent, int cur_line_len)
+{
+ int bar_avail_len = (PERCENTAGE_BAR_END - cur_line_len - 1) * 8;
+ int bar_len = bar_avail_len * (percent + .5) / 100.0;
+ int i;
+
+ for (i = bar_len; i >= 8; i -= 8) {
+ printf("%s", bars[8]);
+ cur_line_len++;
+ }
+ if (i) {
+ printf("%s", bars[i]);
+ cur_line_len++;
+ }
+
+ /* NB: We can't use a field width with utf8 so we manually
+ * guarantee a field with of 45 chars for any bar. */
+ printf("%*s", PERCENTAGE_BAR_END - cur_line_len, "");
+}
+
+struct ring {
+ const char *name;
+ uint32_t mmio;
+ int head, tail, size;
+ uint64_t full;
+ int idle;
+};
+
+static uint32_t ring_read(struct ring *ring, uint32_t reg)
+{
+ return INREG(ring->mmio + reg);
+}
+
+static void ring_init(struct ring *ring)
+{
+ ring->size = (((ring_read(ring, RING_LEN) & RING_NR_PAGES) >> 12) + 1) * 4096;
+}
+
+static void ring_reset(struct ring *ring)
+{
+ ring->idle = ring->full = 0;
+}
+
+static void ring_sample(struct ring *ring)
+{
+ int full;
+
+ if (!ring->size)
+ return;
+
+ ring->head = ring_read(ring, RING_HEAD) & HEAD_ADDR;
+ ring->tail = ring_read(ring, RING_TAIL) & TAIL_ADDR;
+
+ if (ring->tail == ring->head)
+ ring->idle++;
+
+ full = ring->tail - ring->head;
+ if (full < 0)
+ full += ring->size;
+ ring->full += full;
+}
+
+static void ring_print_header(FILE *out, struct ring *ring)
+{
+ fprintf(out, "%.6s%%\tops\t",
+ ring->name
+ );
+}
+
+static void ring_print(struct ring *ring, unsigned long samples_per_sec)
+{
+ int percent_busy, len;
+
+ if (!ring->size)
+ return;
+
+ percent_busy = 100 - 100 * ring->idle / samples_per_sec;
+
+ len = printf("%25s busy: %3d%%: ", ring->name, percent_busy);
+ print_percentage_bar (percent_busy, len);
+ printf("%24s space: %d/%d\n",
+ ring->name,
+ (int)(ring->full / samples_per_sec),
+ ring->size);
+}
+
+static void ring_log(struct ring *ring, unsigned long samples_per_sec,
+ FILE *output)
+{
+ if (ring->size)
+ fprintf(output, "%3d\t%d\t",
+ (int)(100 - 100 * ring->idle / samples_per_sec),
+ (int)(ring->full / samples_per_sec));
+ else
+ fprintf(output, "-1\t-1\t");
+}
+
+static void
+usage(const char *appname)
+{
+ printf("intel_gpu_top - Display a top-like summary of Intel GPU usage\n"
+ "\n"
+ "usage: %s [parameters]\n"
+ "\n"
+ "The following parameters apply:\n"
+ "[-s <samples>] samples per seconds (default %d)\n"
+ "[-e <command>] command to profile\n"
+ "[-o <file>] output statistics to file. If file is '-',"
+ " run in batch mode and output statistics to stdio only \n"
+ "[-h] show this help screen\n"
+ "\n",
+ appname,
+ SAMPLES_PER_SEC
+ );
+ return;
+}
+
+int main(int argc, char **argv)
+{
+ uint32_t devid;
+ struct pci_device *pci_dev;
+ struct ring render_ring = {
+ .name = "render",
+ .mmio = 0x2030,
+ }, bsd_ring = {
+ .name = "bitstream",
+ .mmio = 0x4030,
+ }, bsd6_ring = {
+ .name = "bitstream",
+ .mmio = 0x12030,
+ }, blt_ring = {
+ .name = "blitter",
+ .mmio = 0x22030,
+ };
+ int i, ch;
+ int samples_per_sec = SAMPLES_PER_SEC;
+ FILE *output = NULL;
+ double elapsed_time=0;
+ int print_headers=1;
+ pid_t child_pid=-1;
+ int child_stat;
+ char *cmd=NULL;
+ int interactive=1;
+
+ /* Parse options? */
+ while ((ch = getopt(argc, argv, "s:o:e:h")) != -1) {
+ switch (ch) {
+ case 'e': cmd = strdup(optarg);
+ break;
+ case 's': samples_per_sec = atoi(optarg);
+ if (samples_per_sec < 100) {
+ fprintf(stderr, "Error: samples per second must be >= 100\n");
+ exit(1);
+ }
+ break;
+ case 'o':
+ if (!strcmp(optarg, "-")) {
+ /* Running in non-interactive mode */
+ interactive = 0;
+ output = stdout;
+ }
+ else
+ output = fopen(optarg, "w");
+ if (!output)
+ {
+ perror("fopen");
+ exit(1);
+ }
+ break;
+ case 'h':
+ usage(argv[0]);
+ exit(0);
+ break;
+ default:
+ fprintf(stderr, "Invalid flag %c!\n", (char)optopt);
+ usage(argv[0]);
+ exit(1);
+ break;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ pci_dev = intel_get_pci_device();
+ devid = pci_dev->device_id;
+ intel_get_mmio(pci_dev);
+ init_instdone_definitions(devid);
+
+ /* Do we have a command to run? */
+ if (cmd != NULL) {
+ if (output) {
+ fprintf(output, "# Profiling: %s\n", cmd);
+ fflush(output);
+ }
+ child_pid = fork();
+ if (child_pid < 0) {
+ perror("fork");
+ exit(1);
+ }
+ else if (child_pid == 0) {
+ int res;
+ res = system(cmd);
+ if (res < 0)
+ perror("running command");
+ if (output) {
+ fflush(output);
+ fprintf(output, "# %s exited with status %d\n", cmd, res);
+ fflush(output);
+ }
+ free(cmd);
+ exit(0);
+ } else {
+ free(cmd);
+ }
+ }
+
+ for (i = 0; i < num_instdone_bits; i++) {
+ top_bits[i].bit = &instdone_bits[i];
+ top_bits[i].count = 0;
+ top_bits_sorted[i] = &top_bits[i];
+ }
+
+ /* Grab access to the registers */
+ intel_register_access_init(pci_dev, 0);
+
+ ring_init(&render_ring);
+ if (IS_GEN4(devid) || IS_GEN5(devid))
+ ring_init(&bsd_ring);
+ if (IS_GEN6(devid) || IS_GEN7(devid)) {
+ ring_init(&bsd6_ring);
+ ring_init(&blt_ring);
+ }
+
+ /* Initialize GPU stats */
+ if (HAS_STATS_REGS(devid)) {
+ for (i = 0; i < STATS_COUNT; i++) {
+ uint32_t stats_high, stats_low, stats_high_2;
+
+ do {
+ stats_high = INREG(stats_regs[i] + 4);
+ stats_low = INREG(stats_regs[i]);
+ stats_high_2 = INREG(stats_regs[i] + 4);
+ } while (stats_high != stats_high_2);
+
+ last_stats[i] = (uint64_t)stats_high << 32 |
+ stats_low;
+ }
+ }
+
+ for (;;) {
+ int j;
+ unsigned long long t1, ti, tf, t2;
+ unsigned long long def_sleep = 1000000 / samples_per_sec;
+ unsigned long long last_samples_per_sec = samples_per_sec;
+ unsigned short int max_lines;
+ struct winsize ws;
+ char clear_screen[] = {0x1b, '[', 'H',
+ 0x1b, '[', 'J',
+ 0x0};
+ int percent;
+ int len;
+
+ t1 = gettime();
+
+ ring_reset(&render_ring);
+ ring_reset(&bsd_ring);
+ ring_reset(&bsd6_ring);
+ ring_reset(&blt_ring);
+
+ for (i = 0; i < samples_per_sec; i++) {
+ long long interval;
+ ti = gettime();
+ if (IS_965(devid)) {
+ instdone = INREG(INST_DONE_I965);
+ instdone1 = INREG(INST_DONE_1);
+ } else
+ instdone = INREG(INST_DONE);
+
+ for (j = 0; j < num_instdone_bits; j++)
+ update_idle_bit(&top_bits[j]);
+
+ ring_sample(&render_ring);
+ ring_sample(&bsd_ring);
+ ring_sample(&bsd6_ring);
+ ring_sample(&blt_ring);
+
+ tf = gettime();
+ if (tf - t1 >= 1000000) {
+ /* We are out of sync, bail out */
+ last_samples_per_sec = i+1;
+ break;
+ }
+ interval = def_sleep - (tf - ti);
+ if (interval > 0)
+ usleep(interval);
+ }
+
+ if (HAS_STATS_REGS(devid)) {
+ for (i = 0; i < STATS_COUNT; i++) {
+ uint32_t stats_high, stats_low, stats_high_2;
+
+ do {
+ stats_high = INREG(stats_regs[i] + 4);
+ stats_low = INREG(stats_regs[i]);
+ stats_high_2 = INREG(stats_regs[i] + 4);
+ } while (stats_high != stats_high_2);
+
+ stats[i] = (uint64_t)stats_high << 32 |
+ stats_low;
+ }
+ }
+
+ qsort(top_bits_sorted, num_instdone_bits,
+ sizeof(struct top_bit *), top_bits_sort);
+
+ /* Limit the number of lines printed to the terminal height so the
+ * most important info (at the top) will stay on screen. */
+ max_lines = -1;
+ if (ioctl(0, TIOCGWINSZ, &ws) != -1)
+ max_lines = ws.ws_row - 6; /* exclude header lines */
+ if (max_lines >= num_instdone_bits)
+ max_lines = num_instdone_bits;
+
+ t2 = gettime();
+ elapsed_time += (t2 - t1) / 1000000.0;
+
+ if (interactive) {
+ printf("%s", clear_screen);
+ print_clock_info(pci_dev);
+
+ ring_print(&render_ring, last_samples_per_sec);
+ ring_print(&bsd_ring, last_samples_per_sec);
+ ring_print(&bsd6_ring, last_samples_per_sec);
+ ring_print(&blt_ring, last_samples_per_sec);
+
+ printf("\n%30s %s\n", "task", "percent busy");
+ for (i = 0; i < max_lines; i++) {
+ if (top_bits_sorted[i]->count > 0) {
+ percent = (top_bits_sorted[i]->count * 100) /
+ last_samples_per_sec;
+ len = printf("%30s: %3d%%: ",
+ top_bits_sorted[i]->bit->name,
+ percent);
+ print_percentage_bar (percent, len);
+ } else {
+ printf("%*s", PERCENTAGE_BAR_END, "");
+ }
+
+ if (i < STATS_COUNT && HAS_STATS_REGS(devid)) {
+ printf("%13s: %llu (%lld/sec)",
+ stats_reg_names[i],
+ (long long)stats[i],
+ (long long)(stats[i] - last_stats[i]));
+ last_stats[i] = stats[i];
+ } else {
+ if (!top_bits_sorted[i]->count)
+ break;
+ }
+ printf("\n");
+ }
+ }
+ if (output) {
+ /* Print headers for columns at first run */
+ if (print_headers) {
+ fprintf(output, "# time\t");
+ ring_print_header(output, &render_ring);
+ ring_print_header(output, &bsd_ring);
+ ring_print_header(output, &bsd6_ring);
+ ring_print_header(output, &blt_ring);
+ for (i = 0; i < MAX_NUM_TOP_BITS; i++) {
+ if (i < STATS_COUNT && HAS_STATS_REGS(devid)) {
+ fprintf(output, "%.6s\t",
+ stats_reg_names[i]
+ );
+ }
+ if (!top_bits[i].count)
+ continue;
+ }
+ fprintf(output, "\n");
+ print_headers = 0;
+ }
+
+ /* Print statistics */
+ fprintf(output, "%.2f\t", elapsed_time);
+ ring_log(&render_ring, last_samples_per_sec, output);
+ ring_log(&bsd_ring, last_samples_per_sec, output);
+ ring_log(&bsd6_ring, last_samples_per_sec, output);
+ ring_log(&blt_ring, last_samples_per_sec, output);
+
+ for (i = 0; i < MAX_NUM_TOP_BITS; i++) {
+ if (i < STATS_COUNT && HAS_STATS_REGS(devid)) {
+ fprintf(output, "%lu\t",
+ stats[i] - last_stats[i]);
+ last_stats[i] = stats[i];
+ }
+ if (!top_bits[i].count)
+ continue;
+ }
+ fprintf(output, "\n");
+ fflush(output);
+ }
+
+ for (i = 0; i < num_instdone_bits; i++) {
+ top_bits_sorted[i]->count = 0;
+
+ if (i < STATS_COUNT)
+ last_stats[i] = stats[i];
+ }
+
+ /* Check if child has gone */
+ if (child_pid > 0) {
+ int res;
+ if ((res = waitpid(child_pid, &child_stat, WNOHANG)) == -1) {
+ perror("waitpid");
+ exit(1);
+ }
+ if (res == 0)
+ continue;
+ if (WIFEXITED(child_stat))
+ break;
+ }
+ }
+
+ fclose(output);
+
+ intel_register_access_fini();
+ return 0;
+}
diff --git a/tools/intel_gtt.c b/tools/intel_gtt.c
new file mode 100644
index 00000000..05d36d71
--- /dev/null
+++ b/tools/intel_gtt.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright © 2008 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:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <pciaccess.h>
+#include <unistd.h>
+
+#include "intel_gpu_tools.h"
+
+#define INGTT(offset) (*(volatile uint32_t *)(gtt + (offset) / (KB(4) / 4)))
+
+#define KB(x) ((x) * 1024)
+#define MB(x) ((x) * 1024 * 1024)
+
+int main(int argc, char **argv)
+{
+ struct pci_device *pci_dev;
+ int start, aper_size;
+ unsigned char *gtt;
+ uint32_t devid;
+ int flag[] = {
+ PCI_DEV_MAP_FLAG_WRITE_COMBINE,
+ PCI_DEV_MAP_FLAG_WRITABLE,
+ 0
+ }, f;
+
+ pci_dev = intel_get_pci_device();
+ devid = pci_dev->device_id;
+
+ if (IS_GEN2(devid)) {
+ printf("Unsupported chipset for gtt dumper\n");
+ exit(1);
+ }
+
+ for (f = 0; flag[f] != 0; f++) {
+ if (IS_GEN3(devid)) {
+ /* 915/945 chips has GTT range in bar 3 */
+ if (pci_device_map_range(pci_dev,
+ pci_dev->regions[3].base_addr,
+ pci_dev->regions[3].size,
+ flag[f],
+ (void **)&gtt) == 0)
+ break;
+ } else {
+ int offset;
+ if (IS_G4X(devid) || IS_GEN5(devid))
+ offset = MB(2);
+ else
+ offset = KB(512);
+ if (pci_device_map_range(pci_dev,
+ pci_dev->regions[0].base_addr + offset,
+ offset,
+ flag[f],
+ (void **)&gtt) == 0)
+ break;
+ }
+ }
+ if (flag[f] == 0) {
+ printf("Failed to map gtt\n");
+ exit(1);
+ }
+
+ aper_size = pci_dev->regions[2].size;
+
+ for (start = 0; start < aper_size; start += KB(4)) {
+ uint32_t start_pte = INGTT(start);
+ uint32_t end;
+ int constant_length = 0;
+ int linear_length = 0;
+
+ /* Check if it's a linear sequence */
+ for (end = start + KB(4); end < aper_size; end += KB(4)) {
+ uint32_t end_pte = INGTT(end);
+ if (end_pte == start_pte + (end - start))
+ linear_length++;
+ else
+ break;
+ }
+ if (linear_length > 0) {
+ printf("0x%08x - 0x%08x: linear from "
+ "0x%08x to 0x%08x\n",
+ start, end - KB(4),
+ start_pte, start_pte + (end - start) - KB(4));
+ start = end - KB(4);
+ continue;
+ }
+
+ /* Check if it's a constant sequence */
+ for (end = start + KB(4); end < aper_size; end += KB(4)) {
+ uint32_t end_pte = INGTT(end);
+ if (end_pte == start_pte)
+ constant_length++;
+ else
+ break;
+ }
+ if (constant_length > 0) {
+ printf("0x%08x - 0x%08x: constant 0x%08x\n",
+ start, end - KB(4), start_pte);
+ start = end - KB(4);
+ continue;
+ }
+
+ printf("0x%08x: 0x%08x\n", start, start_pte);
+ }
+
+ return 0;
+}
diff --git a/tools/intel_infoframes.c b/tools/intel_infoframes.c
new file mode 100644
index 00000000..f5a40067
--- /dev/null
+++ b/tools/intel_infoframes.c
@@ -0,0 +1,1142 @@
+/*
+ * 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_gpu_tools.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_PCH = 0xe1140,
+ REG_HDMIC_PCH = 0xe1150,
+ REG_HDMID_PCH = 0xe1160,
+ REG_DIP_CTL_GEN4 = 0x61170,
+ REG_DIP_CTL_A = 0xe0200,
+ REG_DIP_CTL_B = 0xe1200,
+ REG_DIP_CTL_C = 0xe2200,
+ REG_DIP_DATA_GEN4 = 0x61178,
+ 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
+
+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 body[27];
+ } generic;
+ uint8_t data8[128];
+ uint32_t data32[16];
+} DipInfoFrame;
+
+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)"
+};
+
+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 (gen == 4)
+ return REG_DIP_CTL_GEN4;
+ else
+ return pch_dip_ctl_regs[transcoder];
+}
+
+static Register get_dip_data_reg(Transcoder transcoder)
+{
+ 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 (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)
+ transcoder = (val & HDMI_PORT_TRANSCODER_GEN4) >> 30;
+ else if (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 = INREG(reg);
+ 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: %x, 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 void dump_vendor_info(Transcoder transcoder)
+{
+ Register reg = get_dip_ctl_reg(transcoder);
+ uint32_t val = INREG(reg);
+ 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);
+
+ 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 = INREG(reg);
+ 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 = INREG(reg);
+ 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 (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 = INREG(reg);
+ 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 = &current[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,
+ &current))
+ frame.avi.S = option_val;
+ else if (parse_infoframe_option_u("B", option, 0, 3,
+ &option_val, &current))
+ frame.avi.B = option_val;
+ else if (parse_infoframe_option_u("A", option, 0, 1,
+ &option_val, &current))
+ frame.avi.A = option_val;
+ else if (parse_infoframe_option_u("Y", option, 0, 2,
+ &option_val, &current))
+ frame.avi.Y = option_val;
+ else if (parse_infoframe_option_u("R", option, 0, 15,
+ &option_val, &current))
+ frame.avi.R = option_val;
+ else if (parse_infoframe_option_u("M", option, 0, 2,
+ &option_val, &current))
+ frame.avi.M = option_val;
+ else if (parse_infoframe_option_u("C", option, 0, 3,
+ &option_val, &current))
+ frame.avi.C = option_val;
+ else if (parse_infoframe_option_u("SC", option, 0, 3,
+ &option_val, &current))
+ frame.avi.SC = option_val;
+ else if (parse_infoframe_option_u("Q", option, 0, 2,
+ &option_val, &current))
+ frame.avi.Q = option_val;
+ else if (parse_infoframe_option_u("EC", option, 0, 1,
+ &option_val,&current))
+ frame.avi.EC = option_val;
+ else if (parse_infoframe_option_u("ITC", option, 0, 1,
+ &option_val, &current))
+ frame.avi.ITC = option_val;
+ else if (parse_infoframe_option_u("VIC", option, 0, 127,
+ &option_val, &current))
+ frame.avi.VIC = option_val;
+ else if (parse_infoframe_option_u("PR", option, 0, 15,
+ &option_val, &current))
+ frame.avi.PR = option_val;
+ else if (parse_infoframe_option_u("top", option, 0, 65535,
+ &option_val, &current))
+ frame.avi.top = option_val;
+ else if (parse_infoframe_option_u("bottom", option, 0, 65535,
+ &option_val, &current))
+ frame.avi.bottom = option_val;
+ else if (parse_infoframe_option_u("left", option, 0, 65535,
+ &option_val, &current))
+ frame.avi.left = option_val;
+ else if (parse_infoframe_option_u("right", option, 0, 65535,
+ &option_val, &current))
+ 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 = INREG(reg);
+ 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, "%31s%n", option, &read);
+ current = &current[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, &current))
+ memcpy(frame.spd.vendor, option_val_s, 8);
+ else if (parse_infoframe_option_s("description", option, 0, 16,
+ option_val_s, &current))
+ memcpy(frame.spd.description, option_val_s, 16);
+ else if (parse_infoframe_option_u("source", option, 0, 0x0c,
+ &option_val_i, &current))
+ 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;
+ struct pci_device *pci_dev;
+ 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' },
+ };
+
+ 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);
+ 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 (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;
+}
diff --git a/tools/intel_l3_parity.c b/tools/intel_l3_parity.c
new file mode 100644
index 00000000..260c3d0c
--- /dev/null
+++ b/tools/intel_l3_parity.c
@@ -0,0 +1,159 @@
+/*
+ * 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:
+ * Ben Widawsky <ben@bwidawsk.net>
+ *
+ */
+
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "intel_chipset.h"
+#include "intel_gpu_tools.h"
+#include "drmtest.h"
+
+#define NUM_BANKS 4
+#define NUM_SUBBANKS 8
+#define NUM_REGS (NUM_BANKS * NUM_SUBBANKS)
+
+struct __attribute__ ((__packed__)) l3_log_register {
+ uint32_t row0_enable : 1;
+ uint32_t rsvd2 : 4;
+ uint32_t row0 : 11;
+ uint32_t row1_enable : 1;
+ uint32_t rsvd1 : 4;
+ uint32_t row1 : 11;
+} l3log[NUM_BANKS][NUM_SUBBANKS];
+
+static void dumpit(void)
+{
+ int i, j;
+
+ for (i = 0; i < NUM_BANKS; i++) {
+ for (j = 0; j < NUM_SUBBANKS; j++) {
+ struct l3_log_register *reg = &l3log[i][j];
+
+ if (reg->row0_enable)
+ printf("Row %d, Bank %d, Subbank %d is disabled\n",
+ reg->row0, i, j);
+ if (reg->row1_enable)
+ printf("Row %d, Bank %d, Subbank %d is disabled\n",
+ reg->row1, i, j);
+ }
+ }
+}
+
+static int disable_rbs(int row, int bank, int sbank)
+{
+ struct l3_log_register *reg = &l3log[bank][sbank];
+
+ // can't map more than 2 rows
+ if (reg->row0_enable && reg->row1_enable)
+ return -1;
+
+ // can't remap the same row twice
+ if ((reg->row0_enable && reg->row0 == row) ||
+ (reg->row1_enable && reg->row1 == row)) {
+ return -1;
+ }
+
+ if (reg->row0_enable) {
+ reg->row1 = row;
+ reg->row1_enable = 1;
+ } else {
+ reg->row0 = row;
+ reg->row0_enable = 1;
+ }
+
+ return 0;
+}
+
+static int do_parse(int argc, char *argv[])
+{
+ int row, bank, sbank, i, ret;
+
+ for (i = 1; i < argc; i++) {
+ ret = sscanf(argv[i], "%d,%d,%d", &row, &bank, &sbank);
+ if (ret != 3)
+ return i;
+ assert(disable_rbs(row, bank, sbank) == 0);
+ }
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ const int device = drm_get_card(0);
+ char *path;
+ unsigned int devid;
+ int drm_fd, fd, ret;
+
+ drm_fd = drm_open_any();
+ devid = intel_get_drm_devid(drm_fd);
+
+ ret = asprintf(&path, "/sys/class/drm/card%d/l3_parity", device);
+ assert(ret != -1);
+
+ fd = open(path, O_RDWR);
+ if (fd == -1 && IS_IVYBRIDGE(devid)) {
+ perror("Opening sysfs");
+ exit(EXIT_FAILURE);
+ } else if (fd == -1)
+ exit(EXIT_SUCCESS);
+
+ ret = read(fd, l3log, NUM_REGS * sizeof(uint32_t));
+ if (ret == -1) {
+ perror("Reading sysfs");
+ exit(EXIT_FAILURE);
+ }
+
+ assert(lseek(fd, 0, SEEK_SET) == 0);
+
+ if (argc == 1) {
+ dumpit();
+ exit(EXIT_SUCCESS);
+ } else if (!strncmp("-c", argv[1], 2)) {
+ memset(l3log, 0, sizeof(l3log));
+ } else {
+ ret = do_parse(argc, argv);
+ if (ret != 0) {
+ fprintf(stderr, "Malformed command line at %s\n", argv[ret]);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ ret = write(fd, l3log, NUM_REGS * sizeof(uint32_t));
+ if (ret == -1) {
+ perror("Writing sysfs");
+ exit(EXIT_FAILURE);
+ }
+
+ close(fd);
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/tools/intel_lid.c b/tools/intel_lid.c
new file mode 100644
index 00000000..908224ee
--- /dev/null
+++ b/tools/intel_lid.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright © 2009 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:
+ * Zhenyu Wang <zhenyu.z.wang@intel.com>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <pciaccess.h>
+#include <err.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "intel_gpu_tools.h"
+#include "intel_reg.h"
+#include "intel_bios.h"
+
+enum lid_status {
+ LID_UNKNOWN = -1,
+ LID_OPEN,
+ LID_CLOSE,
+};
+
+#define ACPI_BUTTON "/proc/acpi/button/"
+#define ACPI_LID "/proc/acpi/button/lid/"
+
+static int i830_lvds_acpi_lid_state(void)
+{
+ int fd;
+ DIR *button_dir;
+ DIR *lid_dir;
+ struct dirent *lid_dent;
+ char *state_name;
+ char state[64];
+ enum lid_status ret = LID_UNKNOWN;
+
+ button_dir = opendir(ACPI_BUTTON);
+ /* If acpi button driver is not loaded, bypass ACPI check method */
+ if (button_dir == NULL)
+ goto out;
+ closedir(button_dir);
+
+ lid_dir = opendir(ACPI_LID);
+
+ /* no acpi lid object found */
+ if (lid_dir == NULL)
+ goto out;
+
+ while (1) {
+ lid_dent = readdir(lid_dir);
+ if (lid_dent == NULL) {
+ /* no LID object */
+ closedir(lid_dir);
+ goto out;
+ }
+ if (strcmp(lid_dent->d_name, ".") &&
+ strcmp(lid_dent->d_name, "..")) {
+ break;
+ }
+ }
+ state_name = malloc(strlen(ACPI_LID) + strlen(lid_dent->d_name) + 7);
+ memset(state_name, 0, sizeof(state_name));
+ strcat(state_name, ACPI_LID);
+ strcat(state_name, lid_dent->d_name);
+ strcat(state_name, "/state");
+
+ closedir(lid_dir);
+
+ if ((fd = open(state_name, O_RDONLY)) == -1) {
+ free(state_name);
+ goto out;
+ }
+ free(state_name);
+ if (read(fd, state, 64) == -1) {
+ close(fd);
+ goto out;
+ }
+ close(fd);
+ if (strstr(state, "open"))
+ ret = LID_OPEN;
+ else if (strstr(state, "closed"))
+ ret = LID_CLOSE;
+ else /* "unsupported" */
+ ret = LID_UNKNOWN;
+
+out:
+ return ret;
+}
+
+int main(int argc, char **argv)
+{
+ int swf14, acpi_lid;
+
+ intel_get_mmio(intel_get_pci_device());
+
+ while (1) {
+ swf14 = INREG(SWF14);
+
+ printf("Intel LVDS Lid status:\n");
+ printf("\tSWF14(0x%x) : %s\n", swf14,
+ swf14 & SWF14_LID_SWITCH_EN ? "close" : "open");
+
+ acpi_lid = i830_lvds_acpi_lid_state();
+ switch (acpi_lid) {
+ case LID_UNKNOWN:
+ printf("\tACPI Lid state : unknown\n");
+ break;
+ case LID_OPEN:
+ printf("\tACPI Lid state : open\n");
+ break;
+ case LID_CLOSE:
+ printf("\tACPI Lid state : close\n");
+ break;
+ }
+ sleep(2);
+ }
+ return 0;
+}
diff --git a/tools/intel_panel_fitter.c b/tools/intel_panel_fitter.c
new file mode 100644
index 00000000..f6723d17
--- /dev/null
+++ b/tools/intel_panel_fitter.c
@@ -0,0 +1,344 @@
+/*
+ * 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 <stdbool.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include "intel_gpu_tools.h"
+
+int gen;
+
+uint32_t HTOTAL[] = { 0x60000, 0x61000, 0x62000 };
+uint32_t VTOTAL[] = { 0x6000C, 0x6100C, 0x6200C };
+uint32_t PIPECONF[] = { 0x70008, 0x71008, 0x72008 };
+uint32_t PIPESRC[] = { 0x6001C, 0x6101C, 0x6201C };
+uint32_t PF_CTRL1[] = { 0x68080, 0x68880, 0x69080 };
+uint32_t PF_WIN_POS[] = { 0x68070, 0x68870, 0x69070 };
+uint32_t PF_WIN_SZ[] = { 0x68074, 0x68874, 0x69074 };
+
+#define PIPECONF_ENABLE (1 << 31)
+#define PIPECONF_INTERLACE_MASK (7 << 21)
+#define PIPECONF_PF_PD (0 << 21)
+#define PIPECONF_PF_ID (1 << 21)
+#define PIPECONF_IF_ID (3 << 21)
+
+#define HTOTAL_ACTIVE_MASK (0xFFF << 0)
+#define VTOTAL_ACTIVE_MASK (0xFFF << 0)
+
+#define PIPESRC_HORIZ_MASK (0xFFF << 16)
+#define PIPESRC_VERT_MASK (0xFFF << 0)
+
+/*#define PF_ENABLE (1 << 31)*/
+#define PF_PIPE_MASK (3 << 29)
+#define PF_FILTER_MASK (3 << 23)
+#define PF_FILTER_MED (1 << 23)
+#define PF_PIPE_A (0 << 29)
+#define PF_PIPE_B (1 << 29)
+#define PF_PIPE_C (2 << 29)
+
+#define PF_WIN_SZ_X_MASK (0x1FFF << 16)
+#define PF_WIN_SZ_Y_MASK (0xFFF << 0)
+
+struct pipe_info {
+ bool enabled;
+ bool pf_enabled;
+ uint32_t interlace_mode;
+ uint32_t tot_width; /* htotal */
+ uint32_t tot_height; /* vtotal */
+ uint32_t src_width; /* pipesrc.x */
+ uint32_t src_height; /* pipesrc.y */
+ uint32_t dst_width; /* pf_win_sz.x */
+ uint32_t dst_height; /* pf_win_sz.y */
+};
+
+static void read_pipe_info(int intel_pipe, struct pipe_info *info)
+{
+ uint32_t conf, vtotal, htotal, src, ctrl1, win_sz;
+
+ conf = INREG(PIPECONF[intel_pipe]);
+ htotal = INREG(HTOTAL[intel_pipe]);
+ vtotal = INREG(VTOTAL[intel_pipe]);
+ src = INREG(PIPESRC[intel_pipe]);
+ ctrl1 = INREG(PF_CTRL1[intel_pipe]);
+ win_sz = INREG(PF_WIN_SZ[intel_pipe]);
+
+ info->enabled = (conf & PIPECONF_ENABLE) ? true : false;
+ info->tot_width = (htotal & HTOTAL_ACTIVE_MASK) + 1;
+ info->tot_height = (vtotal & VTOTAL_ACTIVE_MASK) + 1;
+ info->src_width = ((src & PIPESRC_HORIZ_MASK) >> 16) + 1;
+ info->src_height = (src & PIPESRC_VERT_MASK) + 1;
+ info->interlace_mode = conf & PIPECONF_INTERLACE_MASK;
+ info->pf_enabled = ctrl1 & PF_ENABLE;
+ info->dst_width = (win_sz & PF_WIN_SZ_X_MASK) >> 16;
+ info->dst_height = win_sz & PF_WIN_SZ_Y_MASK;
+}
+
+static void dump_pipe(int intel_pipe)
+{
+ struct pipe_info info;
+
+ read_pipe_info(intel_pipe, &info);
+
+ printf("\nPipe %c:\n", intel_pipe + 'A');
+
+ printf("- %s\n", info.enabled ? "enabled" : "disabled");
+ if (!info.enabled)
+ return;
+
+ switch (info.interlace_mode) {
+ case PIPECONF_PF_PD:
+ printf("- progressive\n");
+ break;
+ case PIPECONF_PF_ID:
+ printf("- interlaced (progressive fetch)\n");
+ break;
+ case PIPECONF_IF_ID:
+ printf("- interlaced (interlaced fetch)\n");
+ break;
+ default:
+ assert(0);
+ }
+
+ printf("- pf %s\n", info.pf_enabled ? "enabled" : "disabled");
+ if (!info.pf_enabled)
+ return;
+
+ printf("- tot %dx%d\n", info.tot_width, info.tot_height);
+ printf("- src %dx%d\n", info.src_width, info.src_height);
+ printf("- dst %dx%d\n", info.dst_width, info.dst_height);
+}
+
+static void dump_info(void)
+{
+ int i;
+ int pipes;
+
+ if (gen < 7)
+ pipes = 2;
+ else
+ pipes = 3;
+
+ for (i = 0; i < pipes; i++) {
+ dump_pipe(i);
+ }
+}
+
+static int change_screen_size(int intel_pipe, int x, int y)
+{
+ struct pipe_info info;
+ uint32_t dst_width, dst_height, pos_x, pos_y;
+ uint32_t ctrl1_val;
+ uint32_t win_pos_val;
+ uint32_t win_sz_val;
+
+ read_pipe_info(intel_pipe, &info);
+
+ if (x == 0) {
+ if (info.dst_width != 0)
+ dst_width = info.dst_width;
+ else
+ dst_width = info.src_width;
+ } else {
+ dst_width = x;
+ }
+
+ if (y == 0) {
+ if (info.dst_height != 0)
+ dst_height = info.dst_height;
+ else
+ dst_height = info.src_height;
+ } else {
+ dst_height = y;
+ }
+
+ pos_x = abs((info.tot_width - dst_width)) / 2;
+ pos_y = abs((info.tot_height - dst_height)) / 2;
+
+ if (pos_x == 1)
+ pos_x = 0;
+
+ if (info.src_width / (double) dst_width > 1.125) {
+ printf("X is too small\n");
+ return 1;
+ } else if (info.tot_width < dst_width) {
+ printf("X is too big\n");
+ return 1;
+ } else if (dst_width & 1) {
+ printf("X must be even\n");
+ return 1;
+ } else if (info.src_height / (double) dst_height > 1.125) {
+ printf("Y is too small\n");
+ return 1;
+ } else if (info.tot_height < dst_height) {
+ printf("Y is too big\n");
+ return 1;
+ } else if (dst_height & 1) {
+ printf("Y must be even\n");
+ return 1;
+ }
+
+ printf("Changing size for pipe %c:\n"
+ "- width: %d -> %d\n"
+ "- height: %d -> %d\n"
+ "- pos: %dx%d\n",
+ intel_pipe + 'A', info.src_width, dst_width, info.src_height,
+ dst_height, pos_x, pos_y);
+
+ ctrl1_val = PF_ENABLE | PF_FILTER_MED;
+
+ /* This can break stuff if the panel fitter is already enabled for
+ * another pipe */
+ if (gen >= 7) {
+ switch (intel_pipe) {
+ case 0:
+ ctrl1_val |= PF_PIPE_A;
+ break;
+ case 1:
+ ctrl1_val |= PF_PIPE_B;
+ break;
+ case 2:
+ ctrl1_val |= PF_PIPE_C;
+ break;
+ default:
+ assert(0);
+ }
+ }
+ OUTREG(PF_CTRL1[intel_pipe], ctrl1_val);
+
+ win_pos_val = pos_x << 16;
+ win_pos_val |= pos_y;
+ OUTREG(PF_WIN_POS[intel_pipe], win_pos_val);
+
+ win_sz_val = dst_width << 16;
+ win_sz_val |= dst_height;
+ OUTREG(PF_WIN_SZ[intel_pipe], win_sz_val);
+
+ return 0;
+}
+
+static int disable_panel_fitter(int intel_pipe)
+{
+ OUTREG(PF_CTRL1[intel_pipe], 0);
+ OUTREG(PF_WIN_POS[intel_pipe], 0);
+ OUTREG(PF_WIN_SZ[intel_pipe], 0);
+ return 0;
+}
+
+static void print_usage(void)
+{
+ printf("Options:\n"
+" -p pipe: pipe to be used (A, B or C)\n"
+" -x value: final screen width size in pixels\n"
+" -y value: final screen height size in pixels\n"
+" -d: disable panel fitter\n"
+" -l: list the current state of each pipe\n"
+" -h: prints this message\n");
+}
+
+int main (int argc, char *argv[])
+{
+ int opt;
+ int ret = 0;
+ char intel_pipe = '\0';
+ int x = 0, y = 0;
+ bool do_disable = false, do_dump = false, do_usage = false;
+ struct pci_device *pci_dev;
+ uint32_t devid;
+
+ printf("WARNING:\n"
+ "This tool is a workaround for people that don't have a Kernel "
+ "with overscan compensation properties: it is just a temporary "
+ "solution that may or may not work. Use it at your own risk.\n");
+
+ pci_dev = intel_get_pci_device();
+ intel_register_access_init(pci_dev, 0);
+ devid = pci_dev->device_id;
+
+ if (!HAS_PCH_SPLIT(devid)) {
+ printf("This tool was only tested on Ironlake and newer\n");
+ ret = 1;
+ goto out;
+ }
+ if (IS_GEN5(devid))
+ gen = 5;
+ else if (IS_GEN6(devid))
+ gen = 6;
+ else
+ gen = 7;
+
+ while ((opt = getopt(argc, argv, "p:x:y:dlh")) != -1) {
+ switch (opt) {
+ case 'p':
+ intel_pipe = optarg[0];
+ if (intel_pipe != 'A' && intel_pipe != 'B' &&
+ (gen <= 6 || intel_pipe != 'C')) {
+ printf("Invalid pipe\n");
+ ret = 1;
+ goto out;
+ }
+ break;
+ case 'x':
+ x = atoi(optarg);
+ break;
+ case 'y':
+ y = atoi(optarg);
+ break;
+ case 'd':
+ do_disable = true;
+ break;
+ case 'l':
+ do_dump = true;
+ break;
+ case 'h':
+ do_usage = true;
+ break;
+ default:
+ do_usage = true;
+ ret = 1;
+ }
+ }
+
+ if (do_usage) {
+ print_usage();
+ } else if (do_dump) {
+ dump_info();
+ } else if (intel_pipe) {
+ if (do_disable)
+ ret = disable_panel_fitter(intel_pipe - 'A');
+ else
+ ret = change_screen_size(intel_pipe - 'A', x, y);
+ } else {
+ print_usage();
+ ret = 1;
+ }
+
+out:
+ intel_register_access_fini();
+ return ret;
+}
diff --git a/tools/intel_reg_checker.c b/tools/intel_reg_checker.c
new file mode 100644
index 00000000..daa8d0fb
--- /dev/null
+++ b/tools/intel_reg_checker.c
@@ -0,0 +1,399 @@
+/* Copyright © 2011 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.
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+#include <string.h>
+#include <stdbool.h>
+#include "intel_gpu_tools.h"
+
+static uint32_t devid;
+static int gen;
+
+static inline uint32_t
+read_reg(uint32_t reg)
+{
+ return *(volatile uint32_t *)((volatile char *)mmio + reg);
+}
+
+static uint32_t
+read_and_print_reg(const char *name, uint32_t reg)
+{
+ uint32_t val = read_reg(reg);
+
+ printf("%s (0x%x): 0x%08x\n", name, reg, val);
+
+ return val;
+}
+
+static void
+check_chicken_unset(const char *name, uint32_t reg)
+{
+ uint32_t val = read_and_print_reg(name, reg);
+
+
+ if (val != 0) {
+ fprintf(stderr, " WARN: chicken bits set\n");
+ } else {
+ printf(" OK: chicken bits unset\n");
+ }
+}
+
+static void
+check_bit(uint32_t val, int bit, const char *bitname, bool set)
+{
+ if (!!(val & (1 << bit)) != set) {
+ fprintf(stderr, " (bit %2d) FAIL: %s must be %s\n",
+ bit, bitname, set ? "set" : "unset");
+ } else {
+ printf(" (bit %2d) OK: %s\n", bit, bitname);
+ }
+}
+
+static void
+check_perf_bit(uint32_t val, int bit, const char *bitname, bool set)
+{
+ if (!!(val & (1 << bit)) != set) {
+ printf(" (bit %2d) PERF: %s should be %s\n",
+ bit, bitname, set ? "set" : "unset");
+ } else {
+ printf(" (bit %2d) OK: %s\n", bit, bitname);
+ }
+}
+
+static void
+check_mi_mode(void)
+{
+ /* Described in page 14-16 of the IHD_OS_Vol1_Part3.pdf
+ * specification.
+ */
+
+ uint32_t mi_mode = read_and_print_reg("MI_MODE", 0x209c);
+
+ /* From page 14:
+ *
+ * Async Flip Performance mode
+ * Project: All
+ * Default Value: 0h
+ * Format: U1
+ * [DevSNB] This bit must be set to ‘1’
+ */
+ if (gen == 6)
+ check_bit(mi_mode, 14, "Async Flip Performance mode", true);
+ else
+ check_perf_bit(mi_mode, 14, "Async Flip Performance mode",
+ false);
+
+ check_perf_bit(mi_mode, 13, "Flush Performance Mode", false);
+
+ /* Our driver relies on MI_FLUSH, unfortunately. */
+ if (gen >= 6)
+ check_bit(mi_mode, 12, "MI_FLUSH enable", true);
+
+ /* From page 15:
+ *
+ * "1h: LRA mode of allocation. Used for validation purposes"
+ */
+ if (gen < 7)
+ check_bit(mi_mode, 7, "Vertex Shader Cache Mode", false);
+
+ /* From page 16:
+ *
+ * "To avoid deadlock conditions in hardware this bit
+ * needs to be set for normal operation.
+ */
+ check_bit(mi_mode, 6, "Vertex Shader Timer Dispatch Enable", true);
+}
+
+static void
+check_gfx_mode(void)
+{
+ /* Described in page 17-19 of the IHD_OS_Vol1_Part3.pdf
+ * specification.
+ */
+ uint32_t gfx_mode;
+
+ if (gen < 6)
+ return;
+
+ if (gen == 6)
+ gfx_mode = read_and_print_reg("GFX_MODE", 0x2520);
+ else
+ gfx_mode = read_and_print_reg("GFX_MODE", 0x229c);
+
+ /* Our driver only updates page tables at batchbuffer
+ * boundaries, so we don't need TLB flushes at other times.
+ */
+ check_perf_bit(gfx_mode, 13, "Flush TLB Invalidation Mode", true);
+}
+
+static void
+check_gt_mode(void)
+{
+ /* Described in page 20-22 of the IHD_OS_Vol1_Part3.pdf
+ * specification.
+ */
+ uint32_t gt_mode;
+
+ if (gen < 6)
+ return;
+
+ if (gen == 6)
+ gt_mode = read_and_print_reg("GT_MODE", 0x20d0);
+ else
+ gt_mode = read_and_print_reg("GT_MODE", 0x7008);
+
+ if (gen == 6)
+ check_perf_bit(gt_mode, 8, "Full Rate Sampler Disable", false);
+
+ /* For DevSmallGT, this bit must be set, which means disable
+ * hashing.
+ */
+ if (devid == PCI_CHIP_SANDYBRIDGE_GT1 ||
+ devid == PCI_CHIP_SANDYBRIDGE_M_GT1)
+ check_bit(gt_mode, 6, "WIZ Hashing disable", true);
+ else if (gen == 6)
+ check_perf_bit(gt_mode, 6, "WIZ Hashing disable", false);
+
+ if (gen == 6) {
+ check_perf_bit(gt_mode, 5, "TD Four Row Dispatch Disable",
+ false);
+ check_perf_bit(gt_mode, 4, "Full Size URB Disable", false);
+ check_perf_bit(gt_mode, 3, "Full Size SF FIFO Disable", false);
+ check_perf_bit(gt_mode, 1, "VS Quad Thread Dispatch Disable",
+ false);
+ }
+}
+
+static void
+check_cache_mode_0(void)
+{
+ /* Described in page 23-25 of the IHD_OS_Vol1_Part3.pdf
+ * specification.
+ */
+ uint32_t cache_mode_0;
+
+ if (gen >= 7)
+ cache_mode_0 = read_and_print_reg("CACHE_MODE_0", 0x7000);
+ else
+ cache_mode_0 = read_and_print_reg("CACHE_MODE_0", 0x2120);
+
+ check_perf_bit(cache_mode_0, 15, "Sampler L2 Disable", false);
+ check_perf_bit(cache_mode_0, 9, "Sampler L2 TLB Prefetch Enable", true);
+ check_perf_bit(cache_mode_0, 8,
+ "Depth Related Cache Pipelined Flush Disable", false);
+
+ /* From page 24:
+ *
+ * "If this bit is set, RCCunit will have LRA as
+ * replacement policy. The default value i.e. ( when this
+ * bit is reset ) indicates that non-LRA eviction
+ * policy. This bit must be reset. LRA replacement policy
+ * is not supported."
+ *
+ * And the same for STC Eviction Policy.
+ */
+ check_bit(cache_mode_0, 5, "STC LRA Eviction Policy", false);
+ if (gen >= 6)
+ check_bit(cache_mode_0, 4, "RCC LRA Eviction Policy", false);
+
+ check_perf_bit(cache_mode_0, 3, "Hierarchical Z Disable", false);
+
+ if (gen == 6) {
+ check_perf_bit(cache_mode_0, 2,
+ "Hierarchical Z RAW Stall Optimization "
+ "Disable", false);
+ }
+
+ /* From page 25:
+ *
+ * "This bit must be 0. Operational Flushes [DevSNB] are
+ * not supported in [DevSNB]. SW must flush the render
+ * target after front buffer rendering."
+ */
+ check_bit(cache_mode_0, 0, "Render Cache Operational Flush", false);
+}
+
+
+static void
+check_cache_mode_1(void)
+{
+ /* Described in page 23-25 of the IHD_OS_Vol1_Part3.pdf
+ * specification.
+ */
+ uint32_t cache_mode_1;
+
+ if (gen >= 7)
+ cache_mode_1 = read_and_print_reg("CACHE_MODE_1", 0x7004);
+ else
+ cache_mode_1 = read_and_print_reg("CACHE_MODE_1", 0x2124);
+
+ if (gen >= 7) {
+ check_perf_bit(cache_mode_1, 13,
+ "STC Address Lookup Optimization Disable",
+ false);
+ }
+
+ /* From page 24:
+ *
+ * "If this bit is set, Hizunit will have LRA as
+ * replacement policy. The default value i.e. (when this
+ * bit is reset) indicates the non-LRA eviction
+ * policy. For performance reasons, this bit must be
+ * reset."
+ */
+ check_bit(cache_mode_1, 12, "HIZ LRA Eviction Policy", false);
+
+ /* Page 26 describes these bits as reserved (debug only). */
+ check_bit(cache_mode_1, 11,
+ "DAP Instruction and State Cache Invalidate", false);
+ check_bit(cache_mode_1, 10,
+ "Instruction L1 Cache and In-Flight Queue Disable",
+ false);
+ check_bit(cache_mode_1, 9, "Instruction L2 Cache Fill Buffers Disable",
+ false);
+
+
+ if (gen >= 7) {
+ check_perf_bit(cache_mode_1, 6,
+ "Pixel Backend sub-span collection "
+ "Optimization Disable",
+ false);
+ check_perf_bit(cache_mode_1, 5, "MCS Cache Disable", false);
+ }
+ check_perf_bit(cache_mode_1, 4, "Data Disable", false);
+
+ if (gen == 6) {
+ /* In a later update of the documentation, it says:
+ *
+ * "[DevSNB:A0{WKA1}] [DevSNB]: This bit must be
+ * set for depth buffer format
+ * D24_UNORM_S8_UINT."
+ *
+ * XXX: Does that mean A0 only, or all DevSNB?
+ */
+ check_perf_bit(cache_mode_1, 3,
+ "Depth Read Hit Write-Only Optimization "
+ "Disable", false);
+
+ check_perf_bit(cache_mode_1, 2,
+ "Depth Cache LRA Hunt Feature Disable",
+ false);
+ }
+
+ check_bit(cache_mode_1, 1, "Instruction and State L2 Cache Disable",
+ false);
+ check_bit(cache_mode_1, 0, "Instruction and State L1 Cache Disable",
+ false);
+}
+
+
+static void
+check_3d_chicken4(void)
+{
+ /* Described in page 23-25 of the IHD_OS_Vol1_Part3.pdf
+ * specification.
+ */
+ uint32_t _3d_chicken4 = read_and_print_reg("3D_CHICKEN4", 0x20d4);
+
+ check_perf_bit(_3d_chicken4, 6, "3D Scoreboard Hashing Enable", true);
+
+ if (_3d_chicken4 & 0x0fbf) {
+ fprintf(stderr,
+ " WARN: other non-thread deps bits set\n");
+ } else {
+ printf(" OK: other non-thread deps bits unset\n");
+ }
+}
+
+static void
+check_dpfc_control_sa(void)
+{
+ uint32_t dpfc_control_sa;
+
+ if (gen != 6)
+ return;
+
+ dpfc_control_sa = read_and_print_reg("DPFC_CONTROL_SA", 0x100100);
+
+ /* This is needed for framebuffer compression for us to be
+ * able to access the framebuffer by the CPU through the GTT.
+ */
+ check_bit(dpfc_control_sa, 29, "CPU Fence Enable", true);
+}
+
+int main(int argc, char** argv)
+{
+ struct pci_device *dev;
+
+ dev = intel_get_pci_device();
+ devid = dev->device_id;
+ intel_get_mmio(dev);
+
+ if (IS_GEN7(devid))
+ gen = 7;
+ else if (IS_GEN6(devid))
+ gen = 6;
+ else if (IS_GEN5(devid))
+ gen = 5;
+ else
+ gen = 4;
+
+ check_mi_mode();
+ check_gfx_mode();
+ check_gt_mode();
+ check_cache_mode_0();
+ check_cache_mode_1();
+
+ if (gen < 7) {
+ check_chicken_unset("3D_CHICKEN", 0x2084);
+ check_chicken_unset("3D_CHICKEN2", 0x208c);
+ } else {
+ check_chicken_unset("FF_SLICE_CHICKEN", 0x2088);
+ }
+ if (gen >= 6)
+ check_chicken_unset("3D_CHICKEN3", 0x2090);
+ if (gen == 6)
+ check_3d_chicken4();
+
+ if (gen >= 7) {
+ check_chicken_unset("FF_SLICE_CS_CHICKEN1", 0x20e0);
+ check_chicken_unset("FF_SLICE_CS_CHICKEN2", 0x20e4);
+ check_chicken_unset("FF_SLICE_CS_CHICKEN3", 0x20e8);
+ check_chicken_unset("COMMON_SLICE_CHICKEN1", 0x7010);
+ check_chicken_unset("COMMON_SLICE_CHICKEN2", 0x7014);
+ check_chicken_unset("WM_CHICKEN", 0x5580);
+ check_chicken_unset("HALF_SLICE_CHICKEN", 0xe100);
+ check_chicken_unset("HALF_SLICE_CHICKEN2", 0xe180);
+ check_chicken_unset("ROW_CHICKEN", 0xe4f0);
+ check_chicken_unset("ROW_CHICKEN2", 0xe4f4);
+ }
+
+ check_chicken_unset("ECOSKPD", 0x21d0);
+
+ check_dpfc_control_sa();
+
+ return 0;
+}
+
diff --git a/tools/intel_reg_dumper.c b/tools/intel_reg_dumper.c
new file mode 100644
index 00000000..b49d967b
--- /dev/null
+++ b/tools/intel_reg_dumper.c
@@ -0,0 +1,2246 @@
+/*
+ * Copyright © 2006,2009 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:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <err.h>
+#include <unistd.h>
+#include "intel_gpu_tools.h"
+
+static uint32_t devid = 0;
+
+#define DEBUGSTRING(func) static void func(char *result, int len, int reg, uint32_t val)
+
+DEBUGSTRING(i830_16bit_func)
+{
+ snprintf(result, len, "0x%04x", (uint16_t) val);
+}
+
+DEBUGSTRING(i830_debug_dcc)
+{
+ const char *addressing = NULL;
+
+ if (!IS_MOBILE(devid))
+ return;
+
+ if (IS_965(devid)) {
+ if (val & (1 << 1))
+ addressing = "dual channel interleaved";
+ else
+ addressing = "single or dual channel asymmetric";
+ } else {
+ switch (val & 3) {
+ case 0:
+ addressing = "single channel";
+ break;
+ case 1:
+ addressing = "dual channel asymmetric";
+ break;
+ case 2:
+ addressing = "dual channel interleaved";
+ break;
+ case 3:
+ addressing = "unknown channel layout";
+ break;
+ }
+ }
+
+ snprintf(result, len, "%s, XOR randomization: %sabled, XOR bit: %d",
+ addressing,
+ (val & (1 << 10)) ? "dis" : "en",
+ (val & (1 << 9)) ? 17 : 11);
+}
+
+DEBUGSTRING(i830_debug_chdecmisc)
+{
+ const char *enhmodesel = NULL;
+
+ switch ((val >> 5) & 3) {
+ case 1:
+ enhmodesel = "XOR bank/rank";
+ break;
+ case 2:
+ enhmodesel = "swap bank";
+ break;
+ case 3:
+ enhmodesel = "XOR bank";
+ break;
+ case 0:
+ enhmodesel = "none";
+ break;
+ }
+
+ snprintf(result, len,
+ "%s, ch2 enh %sabled, ch1 enh %sabled, "
+ "ch0 enh %sabled, "
+ "flex %sabled, ep %spresent", enhmodesel,
+ (val & (1 << 4)) ? "en" : "dis",
+ (val & (1 << 3)) ? "en" : "dis",
+ (val & (1 << 2)) ? "en" : "dis",
+ (val & (1 << 1)) ? "en" : "dis",
+ (val & (1 << 0)) ? "" : "not ");
+}
+
+DEBUGSTRING(i830_debug_xyminus1)
+{
+ snprintf(result, len, "%d, %d", (val & 0xffff) + 1,
+ ((val & 0xffff0000) >> 16) + 1);
+}
+
+DEBUGSTRING(i830_debug_yxminus1)
+{
+ snprintf(result, len, "%d, %d", ((val & 0xffff0000) >> 16) + 1,
+ (val & 0xffff) + 1);
+}
+
+DEBUGSTRING(i830_debug_xy)
+{
+ snprintf(result, len, "%d, %d", (val & 0xffff), ((val & 0xffff0000) >> 16));
+}
+
+DEBUGSTRING(i830_debug_dspstride)
+{
+ snprintf(result, len, "%d bytes", val);
+}
+
+DEBUGSTRING(i830_debug_dspcntr)
+{
+ const char *enabled = val & DISPLAY_PLANE_ENABLE ? "enabled" : "disabled";
+ char plane = val & DISPPLANE_SEL_PIPE_B ? 'B' : 'A';
+ if (HAS_PCH_SPLIT(devid))
+ snprintf(result, len, "%s", enabled);
+ else
+ snprintf(result, len, "%s, pipe %c", enabled, plane);
+}
+
+DEBUGSTRING(i830_debug_pipeconf)
+{
+ const char *enabled = val & PIPEACONF_ENABLE ? "enabled" : "disabled";
+ const char *bit30, *interlace;
+
+ if (IS_965(devid))
+ bit30 = val & I965_PIPECONF_ACTIVE ? "active" : "inactive";
+ else
+ bit30 =
+ val & PIPEACONF_DOUBLE_WIDE ? "double-wide" : "single-wide";
+
+ if (HAS_PCH_SPLIT(devid)) {
+ const char *bpc, *rotation;
+
+ switch ((val >> 21) & 7) {
+ case 0:
+ interlace = "pf-pd";
+ break;
+ case 1:
+ interlace = "pf-id";
+ break;
+ case 3:
+ interlace = "if-id";
+ break;
+ case 4:
+ interlace = "if-id-dbl";
+ break;
+ case 5:
+ interlace = "pf-id-dbl";
+ break;
+ default:
+ interlace = "rsvd";
+ break;
+ }
+
+ switch ((val >> 14) & 3) {
+ case 0:
+ rotation = "rotate 0";
+ break;
+ case 1:
+ rotation = "rotate 90";
+ break;
+ case 2:
+ rotation = "rotate 180";
+ break;
+ case 3:
+ rotation = "rotate 270";
+ break;
+ }
+
+ switch (val & (7 << 5)) {
+ case PIPECONF_8BPP:
+ bpc = "8bpc";
+ break;
+ case PIPECONF_10BPP:
+ bpc = "10bpc";
+ break;
+ case PIPECONF_6BPP:
+ bpc = "6bpc";
+ break;
+ case PIPECONF_12BPP:
+ bpc = "12bpc";
+ break;
+ default:
+ bpc = "invalid bpc";
+ break;
+ }
+ snprintf(result, len, "%s, %s, %s, %s, %s", enabled, bit30,
+ interlace, rotation, bpc);
+ } else if (IS_GEN4(devid)) {
+ switch ((val >> 21) & 7) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ interlace = "progressive";
+ break;
+ case 4:
+ interlace = "interlaced embedded";
+ break;
+ case 5:
+ interlace = "interlaced";
+ break;
+ case 6:
+ interlace = "interlaced sdvo";
+ break;
+ case 7:
+ interlace = "interlaced legacy";
+ break;
+ }
+ snprintf(result, len, "%s, %s, %s", enabled, bit30, interlace);
+ } else
+ snprintf(result, len, "%s, %s", enabled, bit30);
+}
+
+DEBUGSTRING(i830_debug_pipestat)
+{
+ const char *_FIFO_UNDERRUN = val & FIFO_UNDERRUN ? " FIFO_UNDERRUN" : "";
+ const char *_CRC_ERROR_ENABLE =
+ val & CRC_ERROR_ENABLE ? " CRC_ERROR_ENABLE" : "";
+ const char *_CRC_DONE_ENABLE =
+ val & CRC_DONE_ENABLE ? " CRC_DONE_ENABLE" : "";
+ const char *_GMBUS_EVENT_ENABLE =
+ val & GMBUS_EVENT_ENABLE ? " GMBUS_EVENT_ENABLE" : "";
+ const char *_VSYNC_INT_ENABLE =
+ val & VSYNC_INT_ENABLE ? " VSYNC_INT_ENABLE" : "";
+ const char *_DLINE_COMPARE_ENABLE =
+ val & DLINE_COMPARE_ENABLE ? " DLINE_COMPARE_ENABLE" : "";
+ const char *_DPST_EVENT_ENABLE =
+ val & DPST_EVENT_ENABLE ? " DPST_EVENT_ENABLE" : "";
+ const char *_LBLC_EVENT_ENABLE =
+ val & LBLC_EVENT_ENABLE ? " LBLC_EVENT_ENABLE" : "";
+ const char *_OFIELD_INT_ENABLE =
+ val & OFIELD_INT_ENABLE ? " OFIELD_INT_ENABLE" : "";
+ const char *_EFIELD_INT_ENABLE =
+ val & EFIELD_INT_ENABLE ? " EFIELD_INT_ENABLE" : "";
+ const char *_SVBLANK_INT_ENABLE =
+ val & SVBLANK_INT_ENABLE ? " SVBLANK_INT_ENABLE" : "";
+ const char *_VBLANK_INT_ENABLE =
+ val & VBLANK_INT_ENABLE ? " VBLANK_INT_ENABLE" : "";
+ const char *_OREG_UPDATE_ENABLE =
+ val & OREG_UPDATE_ENABLE ? " OREG_UPDATE_ENABLE" : "";
+ const char *_CRC_ERROR_INT_STATUS =
+ val & CRC_ERROR_INT_STATUS ? " CRC_ERROR_INT_STATUS" : "";
+ const char *_CRC_DONE_INT_STATUS =
+ val & CRC_DONE_INT_STATUS ? " CRC_DONE_INT_STATUS" : "";
+ const char *_GMBUS_INT_STATUS =
+ val & GMBUS_INT_STATUS ? " GMBUS_INT_STATUS" : "";
+ const char *_VSYNC_INT_STATUS =
+ val & VSYNC_INT_STATUS ? " VSYNC_INT_STATUS" : "";
+ const char *_DLINE_COMPARE_STATUS =
+ val & DLINE_COMPARE_STATUS ? " DLINE_COMPARE_STATUS" : "";
+ const char *_DPST_EVENT_STATUS =
+ val & DPST_EVENT_STATUS ? " DPST_EVENT_STATUS" : "";
+ const char *_LBLC_EVENT_STATUS =
+ val & LBLC_EVENT_STATUS ? " LBLC_EVENT_STATUS" : "";
+ const char *_OFIELD_INT_STATUS =
+ val & OFIELD_INT_STATUS ? " OFIELD_INT_STATUS" : "";
+ const char *_EFIELD_INT_STATUS =
+ val & EFIELD_INT_STATUS ? " EFIELD_INT_STATUS" : "";
+ const char *_SVBLANK_INT_STATUS =
+ val & SVBLANK_INT_STATUS ? " SVBLANK_INT_STATUS" : "";
+ const char *_VBLANK_INT_STATUS =
+ val & VBLANK_INT_STATUS ? " VBLANK_INT_STATUS" : "";
+ const char *_OREG_UPDATE_STATUS =
+ val & OREG_UPDATE_STATUS ? " OREG_UPDATE_STATUS" : "";
+ snprintf(result, len,
+ "status:%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+ _FIFO_UNDERRUN,
+ _CRC_ERROR_ENABLE,
+ _CRC_DONE_ENABLE,
+ _GMBUS_EVENT_ENABLE,
+ _VSYNC_INT_ENABLE,
+ _DLINE_COMPARE_ENABLE,
+ _DPST_EVENT_ENABLE,
+ _LBLC_EVENT_ENABLE,
+ _OFIELD_INT_ENABLE,
+ _EFIELD_INT_ENABLE,
+ _SVBLANK_INT_ENABLE,
+ _VBLANK_INT_ENABLE,
+ _OREG_UPDATE_ENABLE,
+ _CRC_ERROR_INT_STATUS,
+ _CRC_DONE_INT_STATUS,
+ _GMBUS_INT_STATUS,
+ _VSYNC_INT_STATUS,
+ _DLINE_COMPARE_STATUS,
+ _DPST_EVENT_STATUS,
+ _LBLC_EVENT_STATUS,
+ _OFIELD_INT_STATUS,
+ _EFIELD_INT_STATUS,
+ _SVBLANK_INT_STATUS,
+ _VBLANK_INT_STATUS,
+ _OREG_UPDATE_STATUS);
+}
+
+DEBUGSTRING(ivb_debug_port)
+{
+ const char *drrs = NULL;
+ switch (val & (2 << 30)) {
+ case PORT_DBG_DRRS_HW_STATE_OFF:
+ drrs = "off";
+ break;
+ case PORT_DBG_DRRS_HW_STATE_LOW:
+ drrs = "low";
+ break;
+ case PORT_DBG_DRRS_HW_STATE_HIGH:
+ drrs = "high";
+ break;
+ }
+ snprintf(result, len, "HW DRRS %s",
+ drrs);
+}
+
+DEBUGSTRING(i830_debug_hvtotal)
+{
+ snprintf(result, len, "%d active, %d total",
+ (val & 0xffff) + 1,
+ ((val & 0xffff0000) >> 16) + 1);
+}
+
+DEBUGSTRING(i830_debug_hvsyncblank)
+{
+ snprintf(result, len, "%d start, %d end",
+ (val & 0xffff) + 1,
+ ((val & 0xffff0000) >> 16) + 1);
+}
+
+DEBUGSTRING(i830_debug_vgacntrl)
+{
+ snprintf(result, len, "%s",
+ val & VGA_DISP_DISABLE ? "disabled" : "enabled");
+}
+
+DEBUGSTRING(i830_debug_fp)
+{
+ if (IS_IGD(devid)) {
+ snprintf(result, len, "n = %d, m1 = %d, m2 = %d",
+ ffs((val & FP_N_IGD_DIV_MASK) >>
+ FP_N_DIV_SHIFT) - 1,
+ ((val & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT),
+ ((val & FP_M2_IGD_DIV_MASK) >>
+ FP_M2_DIV_SHIFT));
+ }
+ snprintf(result, len, "n = %d, m1 = %d, m2 = %d",
+ ((val & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT),
+ ((val & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT),
+ ((val & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT));
+}
+
+DEBUGSTRING(i830_debug_vga_pd)
+{
+ int vga0_p1, vga0_p2, vga1_p1, vga1_p2;
+
+ /* XXX: i9xx version */
+
+ if (val & VGA0_PD_P1_DIV_2)
+ vga0_p1 = 2;
+ else
+ vga0_p1 = ((val & VGA0_PD_P1_MASK) >> VGA0_PD_P1_SHIFT) + 2;
+ vga0_p2 = (val & VGA0_PD_P2_DIV_4) ? 4 : 2;
+
+ if (val & VGA1_PD_P1_DIV_2)
+ vga1_p1 = 2;
+ else
+ vga1_p1 = ((val & VGA1_PD_P1_MASK) >> VGA1_PD_P1_SHIFT) + 2;
+ vga1_p2 = (val & VGA1_PD_P2_DIV_4) ? 4 : 2;
+
+ snprintf(result, len, "vga0 p1 = %d, p2 = %d, vga1 p1 = %d, p2 = %d",
+ vga0_p1, vga0_p2, vga1_p1, vga1_p2);
+}
+
+DEBUGSTRING(i830_debug_pp_status)
+{
+ const char *status = val & PP_ON ? "on" : "off";
+ const char *ready = val & PP_READY ? "ready" : "not ready";
+ const char *seq = "unknown";
+
+ switch (val & PP_SEQUENCE_MASK) {
+ case PP_SEQUENCE_NONE:
+ seq = "idle";
+ break;
+ case PP_SEQUENCE_ON:
+ seq = "on";
+ break;
+ case PP_SEQUENCE_OFF:
+ seq = "off";
+ break;
+ }
+
+ snprintf(result, len, "%s, %s, sequencing %s", status, ready, seq);
+}
+
+DEBUGSTRING(i830_debug_pp_control)
+{
+ snprintf(result, len, "power target: %s",
+ val & POWER_TARGET_ON ? "on" : "off");
+}
+
+DEBUGSTRING(i830_debug_dpll)
+{
+ const char *enabled = val & DPLL_VCO_ENABLE ? "enabled" : "disabled";
+ const char *dvomode = val & DPLL_DVO_HIGH_SPEED ? "dvo" : "non-dvo";
+ const char *vgamode = val & DPLL_VGA_MODE_DIS ? "" : ", VGA";
+ const char *mode = "unknown";
+ const char *clock = "unknown";
+ const char *fpextra = val & DISPLAY_RATE_SELECT_FPA1 ? ", using FPx1!" : "";
+ char sdvoextra[20];
+ int p1, p2 = 0;
+
+ if (IS_GEN2(devid)) {
+ char is_lvds = (INREG(LVDS) & LVDS_PORT_EN) && (reg == DPLL_B);
+
+ if (is_lvds) {
+ mode = "LVDS";
+ p1 = ffs((val & DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS)
+ >> DPLL_FPA01_P1_POST_DIV_SHIFT);
+ if ((INREG(LVDS) & LVDS_CLKB_POWER_MASK) ==
+ LVDS_CLKB_POWER_UP)
+ p2 = 7;
+ else
+ p2 = 14;
+
+ } else {
+ mode = "DAC/serial";
+ if (val & PLL_P1_DIVIDE_BY_TWO) {
+ p1 = 2;
+ } else {
+ /* Map the number in the field to (3, 33) */
+ p1 = ((val & DPLL_FPA01_P1_POST_DIV_MASK_I830)
+ >> DPLL_FPA01_P1_POST_DIV_SHIFT) + 2;
+ }
+ if (val & PLL_P2_DIVIDE_BY_4)
+ p2 = 4;
+ else
+ p2 = 2;
+ }
+ } else {
+ if (IS_IGD(devid)) {
+ p1 = ffs((val & DPLL_FPA01_P1_POST_DIV_MASK_IGD) >>
+ DPLL_FPA01_P1_POST_DIV_SHIFT_IGD);
+ } else {
+ p1 = ffs((val & DPLL_FPA01_P1_POST_DIV_MASK) >>
+ DPLL_FPA01_P1_POST_DIV_SHIFT);
+ }
+ switch (val & DPLL_MODE_MASK) {
+ case DPLLB_MODE_DAC_SERIAL:
+ mode = "DAC/serial";
+ p2 = val & DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 ? 5 : 10;
+ break;
+ case DPLLB_MODE_LVDS:
+ mode = "LVDS";
+ p2 = val & DPLLB_LVDS_P2_CLOCK_DIV_7 ? 7 : 14;
+ break;
+ }
+ }
+
+ switch (val & PLL_REF_INPUT_MASK) {
+ case PLL_REF_INPUT_DREFCLK:
+ clock = "default";
+ break;
+ case PLL_REF_INPUT_TVCLKINA:
+ clock = "TV A";
+ break;
+ case PLL_REF_INPUT_TVCLKINBC:
+ clock = "TV B/C";
+ break;
+ case PLLB_REF_INPUT_SPREADSPECTRUMIN:
+ if (reg == DPLL_B)
+ clock = "spread spectrum";
+ break;
+ }
+
+ if (IS_945(devid)) {
+ sprintf(sdvoextra, ", SDVO mult %d",
+ (int)((val & SDVO_MULTIPLIER_MASK) >>
+ SDVO_MULTIPLIER_SHIFT_HIRES) + 1);
+ } else {
+ sdvoextra[0] = '\0';
+ }
+
+ snprintf(result, len, "%s, %s%s, %s clock, %s mode, p1 = %d, "
+ "p2 = %d%s%s",
+ enabled, dvomode, vgamode, clock, mode, p1, p2,
+ fpextra, sdvoextra);
+}
+
+DEBUGSTRING(i830_debug_dpll_test)
+{
+ const char *dpllandiv = val & DPLLA_TEST_N_BYPASS ? ", DPLLA N bypassed" : "";
+ const char *dpllamdiv = val & DPLLA_TEST_M_BYPASS ? ", DPLLA M bypassed" : "";
+ const char *dpllainput = val & DPLLA_INPUT_BUFFER_ENABLE ?
+ "" : ", DPLLA input buffer disabled";
+ const char *dpllbndiv = val & DPLLB_TEST_N_BYPASS ? ", DPLLB N bypassed" : "";
+ const char *dpllbmdiv = val & DPLLB_TEST_M_BYPASS ? ", DPLLB M bypassed" : "";
+ const char *dpllbinput = val & DPLLB_INPUT_BUFFER_ENABLE ?
+ "" : ", DPLLB input buffer disabled";
+
+ snprintf(result, len, "%s%s%s%s%s%s",
+ dpllandiv, dpllamdiv, dpllainput,
+ dpllbndiv, dpllbmdiv, dpllbinput);
+}
+
+DEBUGSTRING(i830_debug_adpa)
+{
+ char disp_pipe = (val & ADPA_PIPE_B_SELECT) ? 'B' : 'A';
+ const char *enable = (val & ADPA_DAC_ENABLE) ? "enabled" : "disabled";
+ char hsync = (val & ADPA_HSYNC_ACTIVE_HIGH) ? '+' : '-';
+ char vsync = (val & ADPA_VSYNC_ACTIVE_HIGH) ? '+' : '-';
+
+ if (HAS_CPT)
+ disp_pipe = val & (1<<29) ? 'B' : 'A';
+
+ if (HAS_PCH_SPLIT(devid))
+ snprintf(result, len, "%s, transcoder %c, %chsync, %cvsync",
+ enable, disp_pipe, hsync, vsync);
+ else
+ snprintf(result, len, "%s, pipe %c, %chsync, %cvsync",
+ enable, disp_pipe, hsync, vsync);
+}
+
+DEBUGSTRING(i830_debug_lvds)
+{
+ char disp_pipe = val & LVDS_PIPEB_SELECT ? 'B' : 'A';
+ const char *enable = val & LVDS_PORT_EN ? "enabled" : "disabled";
+ int depth;
+ const char *channels;
+
+ if ((val & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP)
+ depth = 24;
+ else
+ depth = 18;
+ if ((val & LVDS_B0B3_POWER_MASK) == LVDS_B0B3_POWER_UP)
+ channels = "2 channels";
+ else
+ channels = "1 channel";
+
+ if (HAS_CPT)
+ disp_pipe = val & (1<<29) ? 'B' : 'A';
+
+ snprintf(result, len, "%s, pipe %c, %d bit, %s",
+ enable, disp_pipe, depth, channels);
+}
+
+DEBUGSTRING(i830_debug_dvo)
+{
+ const char *enable = val & DVO_ENABLE ? "enabled" : "disabled";
+ char disp_pipe = val & DVO_PIPE_B_SELECT ? 'B' : 'A';
+ const char *stall;
+ char hsync = val & DVO_HSYNC_ACTIVE_HIGH ? '+' : '-';
+ char vsync = val & DVO_VSYNC_ACTIVE_HIGH ? '+' : '-';
+
+ switch (val & DVO_PIPE_STALL_MASK) {
+ case DVO_PIPE_STALL_UNUSED:
+ stall = "no stall";
+ break;
+ case DVO_PIPE_STALL:
+ stall = "stall";
+ break;
+ case DVO_PIPE_STALL_TV:
+ stall = "TV stall";
+ break;
+ default:
+ stall = "unknown stall";
+ break;
+ }
+
+ snprintf(result, len, "%s, pipe %c, %s, %chsync, %cvsync",
+ enable, disp_pipe, stall, hsync, vsync);
+}
+
+DEBUGSTRING(i830_debug_sdvo)
+{
+ const char *enable = val & SDVO_ENABLE ? "enabled" : "disabled";
+ char disp_pipe = val & SDVO_PIPE_B_SELECT ? 'B' : 'A';
+ const char *stall = val & SDVO_STALL_SELECT ? "enabled" : "disabled";
+ const char *detected = val & SDVO_DETECTED ? "" : "not ";
+ const char *gang = val & SDVOC_GANG_MODE ? ", gang mode" : "";
+ char sdvoextra[20];
+
+ if (IS_915(devid)) {
+ sprintf(sdvoextra, ", SDVO mult %d",
+ (int)((val & SDVO_PORT_MULTIPLY_MASK) >>
+ SDVO_PORT_MULTIPLY_SHIFT) + 1);
+ } else {
+ sdvoextra[0] = '\0';
+ }
+
+ snprintf(result, len, "%s, pipe %c, stall %s, %sdetected%s%s",
+ enable, disp_pipe, stall, detected, sdvoextra, gang);
+}
+
+DEBUGSTRING(i830_debug_dspclk_gate_d)
+{
+ const char *DPUNIT_B = val & DPUNIT_B_CLOCK_GATE_DISABLE ? " DPUNIT_B" : "";
+ const char *VSUNIT = val & VSUNIT_CLOCK_GATE_DISABLE ? " VSUNIT" : "";
+ const char *VRHUNIT = val & VRHUNIT_CLOCK_GATE_DISABLE ? " VRHUNIT" : "";
+ const char *VRDUNIT = val & VRDUNIT_CLOCK_GATE_DISABLE ? " VRDUNIT" : "";
+ const char *AUDUNIT = val & AUDUNIT_CLOCK_GATE_DISABLE ? " AUDUNIT" : "";
+ const char *DPUNIT_A = val & DPUNIT_A_CLOCK_GATE_DISABLE ? " DPUNIT_A" : "";
+ const char *DPCUNIT = val & DPCUNIT_CLOCK_GATE_DISABLE ? " DPCUNIT" : "";
+ const char *TVRUNIT = val & TVRUNIT_CLOCK_GATE_DISABLE ? " TVRUNIT" : "";
+ const char *TVCUNIT = val & TVCUNIT_CLOCK_GATE_DISABLE ? " TVCUNIT" : "";
+ const char *TVFUNIT = val & TVFUNIT_CLOCK_GATE_DISABLE ? " TVFUNIT" : "";
+ const char *TVEUNIT = val & TVEUNIT_CLOCK_GATE_DISABLE ? " TVEUNIT" : "";
+ const char *DVSUNIT = val & DVSUNIT_CLOCK_GATE_DISABLE ? " DVSUNIT" : "";
+ const char *DSSUNIT = val & DSSUNIT_CLOCK_GATE_DISABLE ? " DSSUNIT" : "";
+ const char *DDBUNIT = val & DDBUNIT_CLOCK_GATE_DISABLE ? " DDBUNIT" : "";
+ const char *DPRUNIT = val & DPRUNIT_CLOCK_GATE_DISABLE ? " DPRUNIT" : "";
+ const char *DPFUNIT = val & DPFUNIT_CLOCK_GATE_DISABLE ? " DPFUNIT" : "";
+ const char *DPBMUNIT = val & DPBMUNIT_CLOCK_GATE_DISABLE ? " DPBMUNIT" : "";
+ const char *DPLSUNIT = val & DPLSUNIT_CLOCK_GATE_DISABLE ? " DPLSUNIT" : "";
+ const char *DPLUNIT = val & DPLUNIT_CLOCK_GATE_DISABLE ? " DPLUNIT" : "";
+ const char *DPOUNIT = val & DPOUNIT_CLOCK_GATE_DISABLE ? " DPOUNIT" : "";
+ const char *DPBUNIT = val & DPBUNIT_CLOCK_GATE_DISABLE ? " DPBUNIT" : "";
+ const char *DCUNIT = val & DCUNIT_CLOCK_GATE_DISABLE ? " DCUNIT" : "";
+ const char *DPUNIT = val & DPUNIT_CLOCK_GATE_DISABLE ? " DPUNIT" : "";
+ const char *VRUNIT = val & VRUNIT_CLOCK_GATE_DISABLE ? " VRUNIT" : "";
+ const char *OVHUNIT = val & OVHUNIT_CLOCK_GATE_DISABLE ? " OVHUNIT" : "";
+ const char *DPIOUNIT = val & DPIOUNIT_CLOCK_GATE_DISABLE ? " DPIOUNIT" : "";
+ const char *OVFUNIT = val & OVFUNIT_CLOCK_GATE_DISABLE ? " OVFUNIT" : "";
+ const char *OVBUNIT = val & OVBUNIT_CLOCK_GATE_DISABLE ? " OVBUNIT" : "";
+ const char *OVRUNIT = val & OVRUNIT_CLOCK_GATE_DISABLE ? " OVRUNIT" : "";
+ const char *OVCUNIT = val & OVCUNIT_CLOCK_GATE_DISABLE ? " OVCUNIT" : "";
+ const char *OVUUNIT = val & OVUUNIT_CLOCK_GATE_DISABLE ? " OVUUNIT" : "";
+ const char *OVLUNIT = val & OVLUNIT_CLOCK_GATE_DISABLE ? " OVLUNIT" : "";
+
+ snprintf(result, len,
+ "clock gates disabled:%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+ DPUNIT_B, VSUNIT, VRHUNIT, VRDUNIT, AUDUNIT, DPUNIT_A, DPCUNIT,
+ TVRUNIT, TVCUNIT, TVFUNIT, TVEUNIT, DVSUNIT, DSSUNIT, DDBUNIT,
+ DPRUNIT, DPFUNIT, DPBMUNIT, DPLSUNIT, DPLUNIT, DPOUNIT, DPBUNIT,
+ DCUNIT, DPUNIT, VRUNIT, OVHUNIT, DPIOUNIT, OVFUNIT, OVBUNIT,
+ OVRUNIT, OVCUNIT, OVUUNIT, OVLUNIT);
+}
+
+DEBUGSTRING(i810_debug_915_fence)
+{
+ char format = (val & 1 << 12) ? 'Y' : 'X';
+ int pitch = 128 << ((val & 0x70) >> 4);
+ unsigned int offset = val & 0x0ff00000;
+ int size = (1024 * 1024) << ((val & 0x700) >> 8);
+
+ if (IS_965(devid) || (IS_915(devid) && reg >= FENCE_NEW))
+ return;
+
+ if (format == 'X')
+ pitch *= 4;
+ if (val & 1) {
+ snprintf(result, len, "enabled, %c tiled, %4d pitch, 0x%08x - 0x%08x (%dkb)",
+ format, pitch, offset, offset + size,
+ size / 1024);
+ } else {
+ snprintf(result, len, "disabled");
+ }
+}
+
+DEBUGSTRING(i810_debug_965_fence_start)
+{
+ const char *enable = (val & FENCE_VALID) ? " enabled" : "disabled";
+ char format = (val & I965_FENCE_Y_MAJOR) ? 'Y' : 'X';
+ int pitch = ((val & 0xffc) >> 2) * 128 + 128;
+ unsigned int offset = val & 0xfffff000;
+
+ if (!IS_965(devid))
+ return;
+
+ snprintf(result, len, "%s, %c tile walk, %4d pitch, 0x%08x start",
+ enable, format, pitch, offset);
+}
+
+DEBUGSTRING(i810_debug_965_fence_end)
+{
+ unsigned int end = val & 0xfffff000;
+
+ if (!IS_965(devid))
+ return;
+
+ snprintf(result, len, " 0x%08x end", end);
+}
+
+#define DEFINEREG(reg) \
+ { reg, #reg, NULL, 0 }
+#define DEFINEREG_16BIT(reg) \
+ { reg, #reg, i830_16bit_func, 0 }
+#define DEFINEREG2(reg, func) \
+ { reg, #reg, func, 0 }
+
+struct reg_debug {
+ int reg;
+ const char *name;
+ void (*debug_output) (char *result, int len, int reg, uint32_t val);
+ uint32_t val;
+};
+
+static struct reg_debug intel_debug_regs[] = {
+ DEFINEREG2(DCC, i830_debug_dcc),
+ DEFINEREG2(CHDECMISC, i830_debug_chdecmisc),
+ DEFINEREG_16BIT(C0DRB0),
+ DEFINEREG_16BIT(C0DRB1),
+ DEFINEREG_16BIT(C0DRB2),
+ DEFINEREG_16BIT(C0DRB3),
+ DEFINEREG_16BIT(C1DRB0),
+ DEFINEREG_16BIT(C1DRB1),
+ DEFINEREG_16BIT(C1DRB2),
+ DEFINEREG_16BIT(C1DRB3),
+ DEFINEREG_16BIT(C0DRA01),
+ DEFINEREG_16BIT(C0DRA23),
+ DEFINEREG_16BIT(C1DRA01),
+ DEFINEREG_16BIT(C1DRA23),
+
+ DEFINEREG(PGETBL_CTL),
+
+ DEFINEREG2(VCLK_DIVISOR_VGA0, i830_debug_fp),
+ DEFINEREG2(VCLK_DIVISOR_VGA1, i830_debug_fp),
+ DEFINEREG2(VCLK_POST_DIV, i830_debug_vga_pd),
+ DEFINEREG2(DPLL_TEST, i830_debug_dpll_test),
+ DEFINEREG(CACHE_MODE_0),
+ DEFINEREG(D_STATE),
+ DEFINEREG2(DSPCLK_GATE_D, i830_debug_dspclk_gate_d),
+ DEFINEREG(RENCLK_GATE_D1),
+ DEFINEREG(RENCLK_GATE_D2),
+/* DEFINEREG(RAMCLK_GATE_D), CRL only */
+ DEFINEREG2(SDVOB, i830_debug_sdvo),
+ DEFINEREG2(SDVOC, i830_debug_sdvo),
+/* DEFINEREG(UDIB_SVB_SHB_CODES), CRL only */
+/* DEFINEREG(UDIB_SHA_BLANK_CODES), CRL only */
+ DEFINEREG(SDVOUDI),
+ DEFINEREG(DSPARB),
+ DEFINEREG(DSPFW1),
+ DEFINEREG(DSPFW2),
+ DEFINEREG(DSPFW3),
+
+ DEFINEREG2(ADPA, i830_debug_adpa),
+ DEFINEREG2(LVDS, i830_debug_lvds),
+ DEFINEREG2(DVOA, i830_debug_dvo),
+ DEFINEREG2(DVOB, i830_debug_dvo),
+ DEFINEREG2(DVOC, i830_debug_dvo),
+ DEFINEREG(DVOA_SRCDIM),
+ DEFINEREG(DVOB_SRCDIM),
+ DEFINEREG(DVOC_SRCDIM),
+
+ DEFINEREG(BLC_PWM_CTL),
+ DEFINEREG(BLC_PWM_CTL2),
+
+ DEFINEREG2(PP_CONTROL, i830_debug_pp_control),
+ DEFINEREG2(PP_STATUS, i830_debug_pp_status),
+ DEFINEREG(PP_ON_DELAYS),
+ DEFINEREG(PP_OFF_DELAYS),
+ DEFINEREG(PP_DIVISOR),
+ DEFINEREG(PFIT_CONTROL),
+ DEFINEREG(PFIT_PGM_RATIOS),
+ DEFINEREG(PORT_HOTPLUG_EN),
+ DEFINEREG(PORT_HOTPLUG_STAT),
+
+ DEFINEREG2(DSPACNTR, i830_debug_dspcntr),
+ DEFINEREG2(DSPASTRIDE, i830_debug_dspstride),
+ DEFINEREG2(DSPAPOS, i830_debug_xy),
+ DEFINEREG2(DSPASIZE, i830_debug_xyminus1),
+ DEFINEREG(DSPABASE),
+ DEFINEREG(DSPASURF),
+ DEFINEREG(DSPATILEOFF),
+ DEFINEREG2(PIPEACONF, i830_debug_pipeconf),
+ DEFINEREG2(PIPEASRC, i830_debug_yxminus1),
+ DEFINEREG2(PIPEASTAT, i830_debug_pipestat),
+ DEFINEREG(PIPEA_GMCH_DATA_M),
+ DEFINEREG(PIPEA_GMCH_DATA_N),
+ DEFINEREG(PIPEA_DP_LINK_M),
+ DEFINEREG(PIPEA_DP_LINK_N),
+ DEFINEREG(CURSOR_A_BASE),
+ DEFINEREG(CURSOR_A_CONTROL),
+ DEFINEREG(CURSOR_A_POSITION),
+
+ DEFINEREG2(FPA0, i830_debug_fp),
+ DEFINEREG2(FPA1, i830_debug_fp),
+ DEFINEREG2(DPLL_A, i830_debug_dpll),
+ DEFINEREG(DPLL_A_MD),
+ DEFINEREG2(HTOTAL_A, i830_debug_hvtotal),
+ DEFINEREG2(HBLANK_A, i830_debug_hvsyncblank),
+ DEFINEREG2(HSYNC_A, i830_debug_hvsyncblank),
+ DEFINEREG2(VTOTAL_A, i830_debug_hvtotal),
+ DEFINEREG2(VBLANK_A, i830_debug_hvsyncblank),
+ DEFINEREG2(VSYNC_A, i830_debug_hvsyncblank),
+ DEFINEREG(BCLRPAT_A),
+ DEFINEREG(VSYNCSHIFT_A),
+
+ DEFINEREG2(DSPBCNTR, i830_debug_dspcntr),
+ DEFINEREG2(DSPBSTRIDE, i830_debug_dspstride),
+ DEFINEREG2(DSPBPOS, i830_debug_xy),
+ DEFINEREG2(DSPBSIZE, i830_debug_xyminus1),
+ DEFINEREG(DSPBBASE),
+ DEFINEREG(DSPBSURF),
+ DEFINEREG(DSPBTILEOFF),
+ DEFINEREG2(PIPEBCONF, i830_debug_pipeconf),
+ DEFINEREG2(PIPEBSRC, i830_debug_yxminus1),
+ DEFINEREG2(PIPEBSTAT, i830_debug_pipestat),
+ DEFINEREG(PIPEB_GMCH_DATA_M),
+ DEFINEREG(PIPEB_GMCH_DATA_N),
+ DEFINEREG(PIPEB_DP_LINK_M),
+ DEFINEREG(PIPEB_DP_LINK_N),
+ DEFINEREG(CURSOR_B_BASE),
+ DEFINEREG(CURSOR_B_CONTROL),
+ DEFINEREG(CURSOR_B_POSITION),
+
+ DEFINEREG2(FPB0, i830_debug_fp),
+ DEFINEREG2(FPB1, i830_debug_fp),
+ DEFINEREG2(DPLL_B, i830_debug_dpll),
+ DEFINEREG(DPLL_B_MD),
+ DEFINEREG2(HTOTAL_B, i830_debug_hvtotal),
+ DEFINEREG2(HBLANK_B, i830_debug_hvsyncblank),
+ DEFINEREG2(HSYNC_B, i830_debug_hvsyncblank),
+ DEFINEREG2(VTOTAL_B, i830_debug_hvtotal),
+ DEFINEREG2(VBLANK_B, i830_debug_hvsyncblank),
+ DEFINEREG2(VSYNC_B, i830_debug_hvsyncblank),
+ DEFINEREG(BCLRPAT_B),
+ DEFINEREG(VSYNCSHIFT_B),
+
+ DEFINEREG(VCLK_DIVISOR_VGA0),
+ DEFINEREG(VCLK_DIVISOR_VGA1),
+ DEFINEREG(VCLK_POST_DIV),
+ DEFINEREG2(VGACNTRL, i830_debug_vgacntrl),
+
+ DEFINEREG(TV_CTL),
+ DEFINEREG(TV_DAC),
+ DEFINEREG(TV_CSC_Y),
+ DEFINEREG(TV_CSC_Y2),
+ DEFINEREG(TV_CSC_U),
+ DEFINEREG(TV_CSC_U2),
+ DEFINEREG(TV_CSC_V),
+ DEFINEREG(TV_CSC_V2),
+ DEFINEREG(TV_CLR_KNOBS),
+ DEFINEREG(TV_CLR_LEVEL),
+ DEFINEREG(TV_H_CTL_1),
+ DEFINEREG(TV_H_CTL_2),
+ DEFINEREG(TV_H_CTL_3),
+ DEFINEREG(TV_V_CTL_1),
+ DEFINEREG(TV_V_CTL_2),
+ DEFINEREG(TV_V_CTL_3),
+ DEFINEREG(TV_V_CTL_4),
+ DEFINEREG(TV_V_CTL_5),
+ DEFINEREG(TV_V_CTL_6),
+ DEFINEREG(TV_V_CTL_7),
+ DEFINEREG(TV_SC_CTL_1),
+ DEFINEREG(TV_SC_CTL_2),
+ DEFINEREG(TV_SC_CTL_3),
+ DEFINEREG(TV_WIN_POS),
+ DEFINEREG(TV_WIN_SIZE),
+ DEFINEREG(TV_FILTER_CTL_1),
+ DEFINEREG(TV_FILTER_CTL_2),
+ DEFINEREG(TV_FILTER_CTL_3),
+ DEFINEREG(TV_CC_CONTROL),
+ DEFINEREG(TV_CC_DATA),
+ DEFINEREG(TV_H_LUMA_0),
+ DEFINEREG(TV_H_LUMA_59),
+ DEFINEREG(TV_H_CHROMA_0),
+ DEFINEREG(TV_H_CHROMA_59),
+
+ DEFINEREG(FBC_CFB_BASE),
+ DEFINEREG(FBC_LL_BASE),
+ DEFINEREG(FBC_CONTROL),
+ DEFINEREG(FBC_COMMAND),
+ DEFINEREG(FBC_STATUS),
+ DEFINEREG(FBC_CONTROL2),
+ DEFINEREG(FBC_FENCE_OFF),
+ DEFINEREG(FBC_MOD_NUM),
+
+ DEFINEREG(MI_MODE),
+ /* DEFINEREG(MI_DISPLAY_POWER_DOWN), CRL only */
+ DEFINEREG(MI_ARB_STATE),
+ DEFINEREG(MI_RDRET_STATE),
+ DEFINEREG(ECOSKPD),
+
+ DEFINEREG(DP_B),
+ DEFINEREG(DPB_AUX_CH_CTL),
+ DEFINEREG(DPB_AUX_CH_DATA1),
+ DEFINEREG(DPB_AUX_CH_DATA2),
+ DEFINEREG(DPB_AUX_CH_DATA3),
+ DEFINEREG(DPB_AUX_CH_DATA4),
+ DEFINEREG(DPB_AUX_CH_DATA5),
+
+ DEFINEREG(DP_C),
+ DEFINEREG(DPC_AUX_CH_CTL),
+ DEFINEREG(DPC_AUX_CH_DATA1),
+ DEFINEREG(DPC_AUX_CH_DATA2),
+ DEFINEREG(DPC_AUX_CH_DATA3),
+ DEFINEREG(DPC_AUX_CH_DATA4),
+ DEFINEREG(DPC_AUX_CH_DATA5),
+
+ DEFINEREG(DP_D),
+ DEFINEREG(DPD_AUX_CH_CTL),
+ DEFINEREG(DPD_AUX_CH_DATA1),
+ DEFINEREG(DPD_AUX_CH_DATA2),
+ DEFINEREG(DPD_AUX_CH_DATA3),
+ DEFINEREG(DPD_AUX_CH_DATA4),
+ DEFINEREG(DPD_AUX_CH_DATA5),
+
+ DEFINEREG(AUD_CONFIG),
+ DEFINEREG(AUD_HDMIW_STATUS),
+ DEFINEREG(AUD_CONV_CHCNT),
+ DEFINEREG(VIDEO_DIP_CTL),
+ DEFINEREG(AUD_PINW_CNTR),
+ DEFINEREG(AUD_CNTL_ST),
+ DEFINEREG(AUD_PIN_CAP),
+ DEFINEREG(AUD_PINW_CAP),
+ DEFINEREG(AUD_PINW_UNSOLRESP),
+ DEFINEREG(AUD_OUT_DIG_CNVT),
+ DEFINEREG(AUD_OUT_CWCAP),
+ DEFINEREG(AUD_GRP_CAP),
+
+#define DEFINEFENCE_915(i) \
+ { FENCE+i*4, "FENCE " #i, i810_debug_915_fence, 0 }
+#define DEFINEFENCE_945(i) \
+ { FENCE_NEW+(i - 8) * 4, "FENCE " #i, i810_debug_915_fence, 0 }
+
+ DEFINEFENCE_915(0),
+ DEFINEFENCE_915(1),
+ DEFINEFENCE_915(2),
+ DEFINEFENCE_915(3),
+ DEFINEFENCE_915(4),
+ DEFINEFENCE_915(5),
+ DEFINEFENCE_915(6),
+ DEFINEFENCE_915(7),
+ DEFINEFENCE_945(8),
+ DEFINEFENCE_945(9),
+ DEFINEFENCE_945(10),
+ DEFINEFENCE_945(11),
+ DEFINEFENCE_945(12),
+ DEFINEFENCE_945(13),
+ DEFINEFENCE_945(14),
+ DEFINEFENCE_945(15),
+
+#define DEFINEFENCE_965(i) \
+ { FENCE_NEW+i*8, "FENCE START " #i, i810_debug_965_fence_start, 0 }, \
+ { FENCE_NEW+i*8+4, "FENCE END " #i, i810_debug_965_fence_end, 0 }
+
+ DEFINEFENCE_965(0),
+ DEFINEFENCE_965(1),
+ DEFINEFENCE_965(2),
+ DEFINEFENCE_965(3),
+ DEFINEFENCE_965(4),
+ DEFINEFENCE_965(5),
+ DEFINEFENCE_965(6),
+ DEFINEFENCE_965(7),
+ DEFINEFENCE_965(8),
+ DEFINEFENCE_965(9),
+ DEFINEFENCE_965(10),
+ DEFINEFENCE_965(11),
+ DEFINEFENCE_965(12),
+ DEFINEFENCE_965(13),
+ DEFINEFENCE_965(14),
+ DEFINEFENCE_965(15),
+
+ DEFINEREG(INST_PM),
+};
+
+DEBUGSTRING(ironlake_debug_rr_hw_ctl)
+{
+ snprintf(result, len, "low %d, high %d", val & RR_HW_LOW_POWER_FRAMES_MASK,
+ (val & RR_HW_HIGH_POWER_FRAMES_MASK) >> 8);
+}
+
+DEBUGSTRING(ironlake_debug_m_tu)
+{
+ snprintf(result, len, "TU %d, val 0x%x %d", (val >> 25) + 1, val & 0xffffff,
+ val & 0xffffff);
+}
+
+DEBUGSTRING(ironlake_debug_n)
+{
+ snprintf(result, len, "val 0x%x %d", val & 0xffffff, val & 0xffffff);
+}
+
+DEBUGSTRING(ironlake_debug_fdi_tx_ctl)
+{
+ const char *train = NULL, *voltage = NULL, *pre_emphasis = NULL, *portw =
+ NULL;
+
+ switch (val & FDI_LINK_TRAIN_NONE) {
+ case FDI_LINK_TRAIN_PATTERN_1:
+ train = "pattern_1";
+ break;
+ case FDI_LINK_TRAIN_PATTERN_2:
+ train = "pattern_2";
+ break;
+ case FDI_LINK_TRAIN_PATTERN_IDLE:
+ train = "pattern_idle";
+ break;
+ case FDI_LINK_TRAIN_NONE:
+ train = "not train";
+ break;
+ }
+
+ if (HAS_CPT) {
+ /* SNB B0 */
+ switch (val & (0x3f << 22)) {
+ case FDI_LINK_TRAIN_400MV_0DB_SNB_B:
+ voltage = "0.4V";
+ pre_emphasis = "0dB";
+ break;
+ case FDI_LINK_TRAIN_400MV_6DB_SNB_B:
+ voltage = "0.4V";
+ pre_emphasis = "6dB";
+ break;
+ case FDI_LINK_TRAIN_600MV_3_5DB_SNB_B:
+ voltage = "0.6V";
+ pre_emphasis = "3.5dB";
+ break;
+ case FDI_LINK_TRAIN_800MV_0DB_SNB_B:
+ voltage = "0.8V";
+ pre_emphasis = "0dB";
+ break;
+ }
+
+ } else {
+
+ switch (val & (7 << 25)) {
+ case FDI_LINK_TRAIN_VOLTAGE_0_4V:
+ voltage = "0.4V";
+ break;
+ case FDI_LINK_TRAIN_VOLTAGE_0_6V:
+ voltage = "0.6V";
+ break;
+ case FDI_LINK_TRAIN_VOLTAGE_0_8V:
+ voltage = "0.8V";
+ break;
+ case FDI_LINK_TRAIN_VOLTAGE_1_2V:
+ voltage = "1.2V";
+ break;
+ default:
+ voltage = "reserved";
+ }
+
+ switch (val & (7 << 22)) {
+ case FDI_LINK_TRAIN_PRE_EMPHASIS_NONE:
+ pre_emphasis = "none";
+ break;
+ case FDI_LINK_TRAIN_PRE_EMPHASIS_1_5X:
+ pre_emphasis = "1.5x";
+ break;
+ case FDI_LINK_TRAIN_PRE_EMPHASIS_2X:
+ pre_emphasis = "2x";
+ break;
+ case FDI_LINK_TRAIN_PRE_EMPHASIS_3X:
+ pre_emphasis = "3x";
+ break;
+ default:
+ pre_emphasis = "reserved";
+ }
+
+ }
+
+ switch (val & (7 << 19)) {
+ case FDI_DP_PORT_WIDTH_X1:
+ portw = "X1";
+ break;
+ case FDI_DP_PORT_WIDTH_X2:
+ portw = "X2";
+ break;
+ case FDI_DP_PORT_WIDTH_X3:
+ portw = "X3";
+ break;
+ case FDI_DP_PORT_WIDTH_X4:
+ portw = "X4";
+ break;
+ }
+
+ snprintf(result, len, "%s, train pattern %s, voltage swing %s,"
+ "pre-emphasis %s, port width %s, enhanced framing %s, FDI PLL %s, scrambing %s, master mode %s",
+ val & FDI_TX_ENABLE ? "enable" : "disable",
+ train, voltage, pre_emphasis, portw,
+ val & FDI_TX_ENHANCE_FRAME_ENABLE ? "enable" :
+ "disable",
+ val & FDI_TX_PLL_ENABLE ? "enable" : "disable",
+ val & (1 << 7) ? "disable" : "enable",
+ val & (1 << 0) ? "enable" : "disable");
+}
+
+DEBUGSTRING(ironlake_debug_fdi_rx_ctl)
+{
+ const char *train = NULL, *portw = NULL, *bpc = NULL;
+
+ if (HAS_CPT) {
+ switch (val & FDI_LINK_TRAIN_PATTERN_MASK_CPT) {
+ case FDI_LINK_TRAIN_PATTERN_1_CPT:
+ train = "pattern_1";
+ break;
+ case FDI_LINK_TRAIN_PATTERN_2_CPT:
+ train = "pattern_2";
+ break;
+ case FDI_LINK_TRAIN_PATTERN_IDLE_CPT:
+ train = "pattern_idle";
+ break;
+ case FDI_LINK_TRAIN_NORMAL_CPT:
+ train = "not train";
+ break;
+ }
+ } else {
+ switch (val & FDI_LINK_TRAIN_NONE) {
+ case FDI_LINK_TRAIN_PATTERN_1:
+ train = "pattern_1";
+ break;
+ case FDI_LINK_TRAIN_PATTERN_2:
+ train = "pattern_2";
+ break;
+ case FDI_LINK_TRAIN_PATTERN_IDLE:
+ train = "pattern_idle";
+ break;
+ case FDI_LINK_TRAIN_NONE:
+ train = "not train";
+ break;
+ }
+ }
+
+ switch (val & (7 << 19)) {
+ case FDI_DP_PORT_WIDTH_X1:
+ portw = "X1";
+ break;
+ case FDI_DP_PORT_WIDTH_X2:
+ portw = "X2";
+ break;
+ case FDI_DP_PORT_WIDTH_X3:
+ portw = "X3";
+ break;
+ case FDI_DP_PORT_WIDTH_X4:
+ portw = "X4";
+ break;
+ }
+
+ switch (val & (7 << 16)) {
+ case FDI_8BPC:
+ bpc = "8bpc";
+ break;
+ case FDI_10BPC:
+ bpc = "10bpc";
+ break;
+ case FDI_6BPC:
+ bpc = "6bpc";
+ break;
+ case FDI_12BPC:
+ bpc = "12bpc";
+ break;
+ }
+
+ snprintf(result, len, "%s, train pattern %s, port width %s, %s,"
+ "link_reverse_strap_overwrite %s, dmi_link_reverse %s, FDI PLL %s,"
+ "FS ecc %s, FE ecc %s, FS err report %s, FE err report %s,"
+ "scrambing %s, enhanced framing %s, %s",
+ val & FDI_RX_ENABLE ? "enable" : "disable",
+ train, portw, bpc,
+ val & FDI_LINK_REVERSE_OVERWRITE ? "yes" : "no",
+ val & FDI_DMI_LINK_REVERSE_MASK ? "yes" : "no",
+ val & FDI_RX_PLL_ENABLE ? "enable" : "disable",
+ val & FDI_FS_ERR_CORRECT_ENABLE ? "enable" : "disable",
+ val & FDI_FE_ERR_CORRECT_ENABLE ? "enable" : "disable",
+ val & FDI_FS_ERR_REPORT_ENABLE ? "enable" : "disable",
+ val & FDI_FE_ERR_REPORT_ENABLE ? "enable" : "disable",
+ val & (1 << 7) ? "disable" : "enable",
+ val & FDI_RX_ENHANCE_FRAME_ENABLE ? "enable" :
+ "disable", val & FDI_SEL_PCDCLK ? "PCDClk" : "RawClk");
+}
+
+DEBUGSTRING(ironlake_debug_dspstride)
+{
+ snprintf(result, len, "%d", val >> 6);
+}
+
+DEBUGSTRING(ironlake_debug_pch_dpll)
+{
+ const char *enable = val & DPLL_VCO_ENABLE ? "enable" : "disable";
+ const char *highspeed = val & DPLL_DVO_HIGH_SPEED ? "yes" : "no";
+ const char *mode = NULL;
+ const char *p2 = NULL;
+ int fpa0_p1, fpa1_p1;
+ const char *refclk = NULL;
+ int sdvo_mul;
+
+ if ((val & DPLLB_MODE_LVDS) == DPLLB_MODE_LVDS) {
+ mode = "LVDS";
+ if (val & DPLLB_LVDS_P2_CLOCK_DIV_7)
+ p2 = "Div 7";
+ else
+ p2 = "Div 14";
+ } else if ((val & DPLLB_MODE_LVDS) == DPLLB_MODE_DAC_SERIAL) {
+ mode = "Non-LVDS";
+ if (val & DPLL_DAC_SERIAL_P2_CLOCK_DIV_5)
+ p2 = "Div 5";
+ else
+ p2 = "Div 10";
+ }
+ fpa0_p1 = ffs((val & DPLL_FPA01_P1_POST_DIV_MASK) >> 16);
+ fpa1_p1 = ffs((val & DPLL_FPA1_P1_POST_DIV_MASK));
+
+ switch (val & PLL_REF_INPUT_MASK) {
+ case PLL_REF_INPUT_DREFCLK:
+ refclk = "default 120Mhz";
+ break;
+ case PLL_REF_INPUT_SUPER_SSC:
+ refclk = "SuperSSC 120Mhz";
+ break;
+ case PLL_REF_INPUT_TVCLKINBC:
+ refclk = "SDVO TVClkIn";
+ break;
+ case PLLB_REF_INPUT_SPREADSPECTRUMIN:
+ refclk = "SSC";
+ break;
+ case PLL_REF_INPUT_DMICLK:
+ refclk = "DMI RefCLK";
+ break;
+ }
+
+ sdvo_mul = ((val & PLL_REF_SDVO_HDMI_MULTIPLIER_MASK) >> 9) + 1;
+
+ snprintf(result, len, "%s, sdvo high speed %s, mode %s, p2 %s, "
+ "FPA0 P1 %d, FPA1 P1 %d, refclk %s, sdvo/hdmi mul %d",
+ enable, highspeed, mode, p2, fpa0_p1, fpa1_p1, refclk,
+ sdvo_mul);
+}
+
+DEBUGSTRING(ironlake_debug_dref_ctl)
+{
+ const char *cpu_source;
+ const char *ssc_source = val & DREF_SSC_SOURCE_ENABLE ? "enable" : "disable";
+ const char *nonspread_source =
+ val & DREF_NONSPREAD_SOURCE_ENABLE ? "enable" : "disable";
+ const char *superspread_source =
+ val & DREF_SUPERSPREAD_SOURCE_ENABLE ? "enable" : "disable";
+ const char *ssc4_mode =
+ val & DREF_SSC4_CENTERSPREAD ? "centerspread" : "downspread";
+ const char *ssc1 = val & DREF_SSC1_ENABLE ? "enable" : "disable";
+ const char *ssc4 = val & DREF_SSC4_ENABLE ? "enable" : "disable";
+
+ switch (val & DREF_CPU_SOURCE_OUTPUT_NONSPREAD) {
+ case DREF_CPU_SOURCE_OUTPUT_DISABLE:
+ cpu_source = "disable";
+ break;
+ case DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD:
+ cpu_source = "downspread";
+ break;
+ case DREF_CPU_SOURCE_OUTPUT_NONSPREAD:
+ cpu_source = "nonspread";
+ break;
+ default:
+ cpu_source = "reserved";
+ }
+ snprintf(result, len, "cpu source %s, ssc_source %s, nonspread_source %s, "
+ "superspread_source %s, ssc4_mode %s, ssc1 %s, ssc4 %s",
+ cpu_source, ssc_source, nonspread_source,
+ superspread_source, ssc4_mode, ssc1, ssc4);
+}
+
+DEBUGSTRING(ironlake_debug_rawclk_freq)
+{
+ const char *tp1 = NULL, *tp2 = NULL;
+
+ switch (val & FDL_TP1_TIMER_MASK) {
+ case 0:
+ tp1 = "0.5us";
+ break;
+ case (1 << 12):
+ tp1 = "1.0us";
+ break;
+ case (2 << 12):
+ tp1 = "2.0us";
+ break;
+ case (3 << 12):
+ tp1 = "4.0us";
+ break;
+ }
+ switch (val & FDL_TP2_TIMER_MASK) {
+ case 0:
+ tp2 = "1.5us";
+ break;
+ case (1 << 10):
+ tp2 = "3.0us";
+ break;
+ case (2 << 10):
+ tp2 = "6.0us";
+ break;
+ case (3 << 10):
+ tp2 = "12.0us";
+ break;
+ }
+ snprintf(result, len, "FDL_TP1 timer %s, FDL_TP2 timer %s, freq %d",
+ tp1, tp2, val & RAWCLK_FREQ_MASK);
+
+}
+
+DEBUGSTRING(ironlake_debug_fdi_rx_misc)
+{
+ snprintf(result, len, "FDI Delay %d", val & ((1 << 13) - 1));
+}
+
+DEBUGSTRING(ironlake_debug_transconf)
+{
+ const char *enable = val & TRANS_ENABLE ? "enable" : "disable";
+ const char *state = val & TRANS_STATE_ENABLE ? "active" : "inactive";
+ const char *interlace;
+
+ switch ((val >> 21) & 7) {
+ case 0:
+ interlace = "progressive";
+ break;
+ case 2:
+ if (IS_GEN5(devid))
+ interlace = "interlaced sdvo";
+ else
+ interlace = "rsvd";
+ break;
+ case 3:
+ interlace = "interlaced";
+ break;
+ default:
+ interlace = "rsvd";
+ }
+
+ snprintf(result, len, "%s, %s, %s", enable, state, interlace);
+}
+
+DEBUGSTRING(ironlake_debug_panel_fitting)
+{
+ const char *vadapt = NULL, *filter_sel = NULL;
+
+ switch (val & (3 << 25)) {
+ case 0:
+ vadapt = "least";
+ break;
+ case (1 << 25):
+ vadapt = "moderate";
+ break;
+ case (2 << 25):
+ vadapt = "reserved";
+ break;
+ case (3 << 25):
+ vadapt = "most";
+ break;
+ }
+
+ switch (val & (3 << 23)) {
+ case 0:
+ filter_sel = "programmed";
+ break;
+ case (1 << 23):
+ filter_sel = "hardcoded";
+ break;
+ case (2 << 23):
+ filter_sel = "edge_enhance";
+ break;
+ case (3 << 23):
+ filter_sel = "edge_soften";
+ break;
+ }
+
+ snprintf(result, len,
+ "%s, auto_scale %s, auto_scale_cal %s, v_filter %s, vadapt %s, mode %s, filter_sel %s,"
+ "chroma pre-filter %s, vert3tap %s, v_inter_invert %s",
+ val & PF_ENABLE ? "enable" : "disable",
+ val & (1 << 30) ? "no" : "yes",
+ val & (1 << 29) ? "yes" : "no",
+ val & (1 << 28) ? "bypass" : "enable",
+ val & (1 << 27) ? "enable" : "disable",
+ vadapt,
+ filter_sel,
+ val & (1 << 22) ? "enable" : "disable",
+ val & (1 << 21) ? "force" : "auto",
+ val & (1 << 20) ? "field 0" : "field 1");
+}
+
+DEBUGSTRING(ironlake_debug_panel_fitting_2)
+{
+ snprintf(result, len,
+ "vscale %f",
+ val / (float) (1<<15));
+}
+
+DEBUGSTRING(ironlake_debug_panel_fitting_3)
+{
+ snprintf(result, len,
+ "vscale initial phase %f",
+ val / (float) (1<<15));
+}
+
+DEBUGSTRING(ironlake_debug_panel_fitting_4)
+{
+ snprintf(result, len,
+ "hscale %f",
+ val / (float) (1<<15));
+}
+
+DEBUGSTRING(ironlake_debug_pf_win)
+{
+ int a, b;
+
+ a = (val >> 16) & 0x1fff;
+ b = val & 0xfff;
+
+ snprintf(result, len, "%d, %d", a, b);
+}
+
+DEBUGSTRING(ironlake_debug_hdmi)
+{
+ int disp_pipe;
+ const char *enable, *bpc = NULL, *encoding;
+ const char *mode, *audio, *vsync, *hsync, *detect;
+
+ if (val & PORT_ENABLE)
+ enable = "enabled";
+ else
+ enable = "disabled";
+
+ if (HAS_CPT)
+ disp_pipe = (val & (3<<29)) >> 29;
+ else
+ disp_pipe = (val & TRANSCODER_B) >> 29;
+
+ switch (val & (7 << 26)) {
+ case COLOR_FORMAT_8bpc:
+ bpc = "8bpc";
+ break;
+ case COLOR_FORMAT_12bpc:
+ bpc = "12bpc";
+ break;
+ }
+
+ if ((val & (3 << 10)) == TMDS_ENCODING)
+ encoding = "TMDS";
+ else
+ encoding = "SDVO";
+
+ if (val & (1 << 9))
+ mode = "HDMI";
+ else
+ mode = "DVI";
+
+ if (val & AUDIO_ENABLE)
+ audio = "enabled";
+ else
+ audio = "disabled";
+
+ if (val & VSYNC_ACTIVE_HIGH)
+ vsync = "+vsync";
+ else
+ vsync = "-vsync";
+
+ if (val & HSYNC_ACTIVE_HIGH)
+ hsync = "+hsync";
+ else
+ hsync = "-hsync";
+
+ if (val & PORT_DETECTED)
+ detect = "detected";
+ else
+ detect = "non-detected";
+
+ snprintf(result, len, "%s pipe %c %s %s %s audio %s %s %s %s",
+ enable, disp_pipe + 'A', bpc, encoding, mode, audio, vsync, hsync, detect);
+}
+
+DEBUGSTRING(snb_debug_dpll_sel)
+{
+ const char *transa, *transb;
+ const char *dplla = NULL, *dpllb = NULL;
+
+ if (!HAS_CPT)
+ return;
+
+ if (val & TRANSA_DPLL_ENABLE) {
+ transa = "enable";
+ if (val & TRANSA_DPLLB_SEL)
+ dplla = "B";
+ else
+ dplla = "A";
+ } else
+ transa = "disable";
+
+ if (val & TRANSB_DPLL_ENABLE) {
+ transb = "enable";
+ if (val & TRANSB_DPLLB_SEL)
+ dpllb = "B";
+ else
+ dpllb = "A";
+ } else
+ transb = "disable";
+
+ snprintf(result, len, "TransA DPLL %s (DPLL %s), TransB DPLL %s (DPLL %s)",
+ transa, dplla, transb, dpllb);
+}
+
+DEBUGSTRING(snb_debug_trans_dp_ctl)
+{
+ const char *enable, *port = NULL, *bpc = NULL, *vsync, *hsync;
+
+ if (!HAS_CPT)
+ return;
+
+ if (val & TRANS_DP_OUTPUT_ENABLE)
+ enable = "enable";
+ else
+ enable = "disable";
+
+ switch (val & TRANS_DP_PORT_SEL_MASK) {
+ case TRANS_DP_PORT_SEL_B:
+ port = "B";
+ break;
+ case TRANS_DP_PORT_SEL_C:
+ port = "C";
+ break;
+ case TRANS_DP_PORT_SEL_D:
+ port = "D";
+ break;
+ default:
+ port = "none";
+ break;
+ }
+
+ switch (val & (7<<9)) {
+ case TRANS_DP_8BPC:
+ bpc = "8bpc";
+ break;
+ case TRANS_DP_10BPC:
+ bpc = "10bpc";
+ break;
+ case TRANS_DP_6BPC:
+ bpc = "6bpc";
+ break;
+ case TRANS_DP_12BPC:
+ bpc = "12bpc";
+ break;
+ }
+
+ if (val & TRANS_DP_VSYNC_ACTIVE_HIGH)
+ vsync = "+vsync";
+ else
+ vsync = "-vsync";
+
+ if (val & TRANS_DP_HSYNC_ACTIVE_HIGH)
+ hsync = "+hsync";
+ else
+ hsync = "-hsync";
+
+ snprintf(result, len, "%s port %s %s %s %s",
+ enable, port, bpc, vsync, hsync);
+}
+
+DEBUGSTRING(ilk_debug_pp_control)
+{
+ snprintf(result, len, "blacklight %s, %spower down on reset, panel %s",
+ (val & (1 << 2)) ? "enabled" : "disabled",
+ (val & (1 << 1)) ? "" : "do not ",
+ (val & (1 << 0)) ? "on" : "off");
+}
+
+static struct reg_debug ironlake_debug_regs[] = {
+ DEFINEREG(PGETBL_CTL),
+ DEFINEREG(GEN6_INSTDONE_1),
+ DEFINEREG(GEN6_INSTDONE_2),
+ DEFINEREG2(CPU_VGACNTRL, i830_debug_vgacntrl),
+ DEFINEREG(DIGITAL_PORT_HOTPLUG_CNTRL),
+
+ DEFINEREG2(RR_HW_CTL, ironlake_debug_rr_hw_ctl),
+
+ DEFINEREG(FDI_PLL_BIOS_0),
+ DEFINEREG(FDI_PLL_BIOS_1),
+ DEFINEREG(FDI_PLL_BIOS_2),
+
+ DEFINEREG(DISPLAY_PORT_PLL_BIOS_0),
+ DEFINEREG(DISPLAY_PORT_PLL_BIOS_1),
+ DEFINEREG(DISPLAY_PORT_PLL_BIOS_2),
+
+ DEFINEREG(FDI_PLL_FREQ_CTL),
+
+ /* pipe B */
+
+ DEFINEREG2(PIPEACONF, i830_debug_pipeconf),
+
+ DEFINEREG2(HTOTAL_A, i830_debug_hvtotal),
+ DEFINEREG2(HBLANK_A, i830_debug_hvsyncblank),
+ DEFINEREG2(HSYNC_A, i830_debug_hvsyncblank),
+ DEFINEREG2(VTOTAL_A, i830_debug_hvtotal),
+ DEFINEREG2(VBLANK_A, i830_debug_hvsyncblank),
+ DEFINEREG2(VSYNC_A, i830_debug_hvsyncblank),
+ DEFINEREG(VSYNCSHIFT_A),
+ DEFINEREG2(PIPEASRC, i830_debug_yxminus1),
+
+ DEFINEREG2(PIPEA_DATA_M1, ironlake_debug_m_tu),
+ DEFINEREG2(PIPEA_DATA_N1, ironlake_debug_n),
+ DEFINEREG2(PIPEA_DATA_M2, ironlake_debug_m_tu),
+ DEFINEREG2(PIPEA_DATA_N2, ironlake_debug_n),
+
+ DEFINEREG2(PIPEA_LINK_M1, ironlake_debug_n),
+ DEFINEREG2(PIPEA_LINK_N1, ironlake_debug_n),
+ DEFINEREG2(PIPEA_LINK_M2, ironlake_debug_n),
+ DEFINEREG2(PIPEA_LINK_N2, ironlake_debug_n),
+
+ DEFINEREG2(DSPACNTR, i830_debug_dspcntr),
+ DEFINEREG(DSPABASE),
+ DEFINEREG2(DSPASTRIDE, ironlake_debug_dspstride),
+ DEFINEREG(DSPASURF),
+ DEFINEREG2(DSPATILEOFF, i830_debug_xy),
+
+ /* pipe B */
+
+ DEFINEREG2(PIPEBCONF, i830_debug_pipeconf),
+
+ DEFINEREG2(HTOTAL_B, i830_debug_hvtotal),
+ DEFINEREG2(HBLANK_B, i830_debug_hvsyncblank),
+ DEFINEREG2(HSYNC_B, i830_debug_hvsyncblank),
+ DEFINEREG2(VTOTAL_B, i830_debug_hvtotal),
+ DEFINEREG2(VBLANK_B, i830_debug_hvsyncblank),
+ DEFINEREG2(VSYNC_B, i830_debug_hvsyncblank),
+ DEFINEREG(VSYNCSHIFT_B),
+ DEFINEREG2(PIPEBSRC, i830_debug_yxminus1),
+
+ DEFINEREG2(PIPEB_DATA_M1, ironlake_debug_m_tu),
+ DEFINEREG2(PIPEB_DATA_N1, ironlake_debug_n),
+ DEFINEREG2(PIPEB_DATA_M2, ironlake_debug_m_tu),
+ DEFINEREG2(PIPEB_DATA_N2, ironlake_debug_n),
+
+ DEFINEREG2(PIPEB_LINK_M1, ironlake_debug_n),
+ DEFINEREG2(PIPEB_LINK_N1, ironlake_debug_n),
+ DEFINEREG2(PIPEB_LINK_M2, ironlake_debug_n),
+ DEFINEREG2(PIPEB_LINK_N2, ironlake_debug_n),
+
+ DEFINEREG2(DSPBCNTR, i830_debug_dspcntr),
+ DEFINEREG(DSPBBASE),
+ DEFINEREG2(DSPBSTRIDE, ironlake_debug_dspstride),
+ DEFINEREG(DSPBSURF),
+ DEFINEREG2(DSPBTILEOFF, i830_debug_xy),
+
+ /* pipe C */
+
+ DEFINEREG2(PIPECCONF, i830_debug_pipeconf),
+
+ DEFINEREG2(HTOTAL_C, i830_debug_hvtotal),
+ DEFINEREG2(HBLANK_C, i830_debug_hvsyncblank),
+ DEFINEREG2(HSYNC_C, i830_debug_hvsyncblank),
+ DEFINEREG2(VTOTAL_C, i830_debug_hvtotal),
+ DEFINEREG2(VBLANK_C, i830_debug_hvsyncblank),
+ DEFINEREG2(VSYNC_C, i830_debug_hvsyncblank),
+ DEFINEREG(VSYNCSHIFT_C),
+ DEFINEREG2(PIPECSRC, i830_debug_yxminus1),
+
+ DEFINEREG2(PIPEC_DATA_M1, ironlake_debug_m_tu),
+ DEFINEREG2(PIPEC_DATA_N1, ironlake_debug_n),
+ DEFINEREG2(PIPEC_DATA_M2, ironlake_debug_m_tu),
+ DEFINEREG2(PIPEC_DATA_N2, ironlake_debug_n),
+
+ DEFINEREG2(PIPEC_LINK_M1, ironlake_debug_n),
+ DEFINEREG2(PIPEC_LINK_N1, ironlake_debug_n),
+ DEFINEREG2(PIPEC_LINK_M2, ironlake_debug_n),
+ DEFINEREG2(PIPEC_LINK_N2, ironlake_debug_n),
+
+ DEFINEREG2(DSPCCNTR, i830_debug_dspcntr),
+ DEFINEREG(DSPCBASE),
+ DEFINEREG2(DSPCSTRIDE, ironlake_debug_dspstride),
+ DEFINEREG(DSPCSURF),
+ DEFINEREG2(DSPCTILEOFF, i830_debug_xy),
+
+ /* Panel fitter */
+
+ DEFINEREG2(PFA_CTL_1, ironlake_debug_panel_fitting),
+ DEFINEREG2(PFA_CTL_2, ironlake_debug_panel_fitting_2),
+ DEFINEREG2(PFA_CTL_3, ironlake_debug_panel_fitting_3),
+ DEFINEREG2(PFA_CTL_4, ironlake_debug_panel_fitting_4),
+ DEFINEREG2(PFA_WIN_POS, ironlake_debug_pf_win),
+ DEFINEREG2(PFA_WIN_SIZE, ironlake_debug_pf_win),
+ DEFINEREG2(PFB_CTL_1, ironlake_debug_panel_fitting),
+ DEFINEREG2(PFB_CTL_2, ironlake_debug_panel_fitting_2),
+ DEFINEREG2(PFB_CTL_3, ironlake_debug_panel_fitting_3),
+ DEFINEREG2(PFB_CTL_4, ironlake_debug_panel_fitting_4),
+ DEFINEREG2(PFB_WIN_POS, ironlake_debug_pf_win),
+ DEFINEREG2(PFB_WIN_SIZE, ironlake_debug_pf_win),
+ DEFINEREG2(PFC_CTL_1, ironlake_debug_panel_fitting),
+ DEFINEREG2(PFC_CTL_2, ironlake_debug_panel_fitting_2),
+ DEFINEREG2(PFC_CTL_3, ironlake_debug_panel_fitting_3),
+ DEFINEREG2(PFC_CTL_4, ironlake_debug_panel_fitting_4),
+ DEFINEREG2(PFC_WIN_POS, ironlake_debug_pf_win),
+ DEFINEREG2(PFC_WIN_SIZE, ironlake_debug_pf_win),
+
+ /* PCH */
+
+ DEFINEREG2(PCH_DREF_CONTROL, ironlake_debug_dref_ctl),
+ DEFINEREG2(PCH_RAWCLK_FREQ, ironlake_debug_rawclk_freq),
+ DEFINEREG(PCH_DPLL_TMR_CFG),
+ DEFINEREG(PCH_SSC4_PARMS),
+ DEFINEREG(PCH_SSC4_AUX_PARMS),
+ DEFINEREG2(PCH_DPLL_SEL, snb_debug_dpll_sel),
+ DEFINEREG(PCH_DPLL_ANALOG_CTL),
+
+ DEFINEREG2(PCH_DPLL_A, ironlake_debug_pch_dpll),
+ DEFINEREG2(PCH_DPLL_B, ironlake_debug_pch_dpll),
+ DEFINEREG2(PCH_FPA0, i830_debug_fp),
+ DEFINEREG2(PCH_FPA1, i830_debug_fp),
+ DEFINEREG2(PCH_FPB0, i830_debug_fp),
+ DEFINEREG2(PCH_FPB1, i830_debug_fp),
+
+ DEFINEREG2(TRANS_HTOTAL_A, i830_debug_hvtotal),
+ DEFINEREG2(TRANS_HBLANK_A, i830_debug_hvsyncblank),
+ DEFINEREG2(TRANS_HSYNC_A, i830_debug_hvsyncblank),
+ DEFINEREG2(TRANS_VTOTAL_A, i830_debug_hvtotal),
+ DEFINEREG2(TRANS_VBLANK_A, i830_debug_hvsyncblank),
+ DEFINEREG2(TRANS_VSYNC_A, i830_debug_hvsyncblank),
+ DEFINEREG(TRANS_VSYNCSHIFT_A),
+
+ DEFINEREG2(TRANSA_DATA_M1, ironlake_debug_m_tu),
+ DEFINEREG2(TRANSA_DATA_N1, ironlake_debug_n),
+ DEFINEREG2(TRANSA_DATA_M2, ironlake_debug_m_tu),
+ DEFINEREG2(TRANSA_DATA_N2, ironlake_debug_n),
+ DEFINEREG2(TRANSA_DP_LINK_M1, ironlake_debug_n),
+ DEFINEREG2(TRANSA_DP_LINK_N1, ironlake_debug_n),
+ DEFINEREG2(TRANSA_DP_LINK_M2, ironlake_debug_n),
+ DEFINEREG2(TRANSA_DP_LINK_N2, ironlake_debug_n),
+
+ DEFINEREG2(TRANS_HTOTAL_B, i830_debug_hvtotal),
+ DEFINEREG2(TRANS_HBLANK_B, i830_debug_hvsyncblank),
+ DEFINEREG2(TRANS_HSYNC_B, i830_debug_hvsyncblank),
+ DEFINEREG2(TRANS_VTOTAL_B, i830_debug_hvtotal),
+ DEFINEREG2(TRANS_VBLANK_B, i830_debug_hvsyncblank),
+ DEFINEREG2(TRANS_VSYNC_B, i830_debug_hvsyncblank),
+ DEFINEREG(TRANS_VSYNCSHIFT_B),
+
+ DEFINEREG2(TRANSB_DATA_M1, ironlake_debug_m_tu),
+ DEFINEREG2(TRANSB_DATA_N1, ironlake_debug_n),
+ DEFINEREG2(TRANSB_DATA_M2, ironlake_debug_m_tu),
+ DEFINEREG2(TRANSB_DATA_N2, ironlake_debug_n),
+ DEFINEREG2(TRANSB_DP_LINK_M1, ironlake_debug_n),
+ DEFINEREG2(TRANSB_DP_LINK_N1, ironlake_debug_n),
+ DEFINEREG2(TRANSB_DP_LINK_M2, ironlake_debug_n),
+ DEFINEREG2(TRANSB_DP_LINK_N2, ironlake_debug_n),
+
+ DEFINEREG2(TRANS_HTOTAL_C, i830_debug_hvtotal),
+ DEFINEREG2(TRANS_HBLANK_C, i830_debug_hvsyncblank),
+ DEFINEREG2(TRANS_HSYNC_C, i830_debug_hvsyncblank),
+ DEFINEREG2(TRANS_VTOTAL_C, i830_debug_hvtotal),
+ DEFINEREG2(TRANS_VBLANK_C, i830_debug_hvsyncblank),
+ DEFINEREG2(TRANS_VSYNC_C, i830_debug_hvsyncblank),
+ DEFINEREG(TRANS_VSYNCSHIFT_C),
+
+ DEFINEREG2(TRANSC_DATA_M1, ironlake_debug_m_tu),
+ DEFINEREG2(TRANSC_DATA_N1, ironlake_debug_n),
+ DEFINEREG2(TRANSC_DATA_M2, ironlake_debug_m_tu),
+ DEFINEREG2(TRANSC_DATA_N2, ironlake_debug_n),
+ DEFINEREG2(TRANSC_DP_LINK_M1, ironlake_debug_n),
+ DEFINEREG2(TRANSC_DP_LINK_N1, ironlake_debug_n),
+ DEFINEREG2(TRANSC_DP_LINK_M2, ironlake_debug_n),
+ DEFINEREG2(TRANSC_DP_LINK_N2, ironlake_debug_n),
+
+ DEFINEREG2(TRANSACONF, ironlake_debug_transconf),
+ DEFINEREG2(TRANSBCONF, ironlake_debug_transconf),
+ DEFINEREG2(TRANSCCONF, ironlake_debug_transconf),
+
+ DEFINEREG2(FDI_TXA_CTL, ironlake_debug_fdi_tx_ctl),
+ DEFINEREG2(FDI_TXB_CTL, ironlake_debug_fdi_tx_ctl),
+ DEFINEREG2(FDI_TXC_CTL, ironlake_debug_fdi_tx_ctl),
+ DEFINEREG2(FDI_RXA_CTL, ironlake_debug_fdi_rx_ctl),
+ DEFINEREG2(FDI_RXB_CTL, ironlake_debug_fdi_rx_ctl),
+ DEFINEREG2(FDI_RXC_CTL, ironlake_debug_fdi_rx_ctl),
+
+ DEFINEREG2(FDI_RXA_MISC, ironlake_debug_fdi_rx_misc),
+ DEFINEREG2(FDI_RXB_MISC, ironlake_debug_fdi_rx_misc),
+ DEFINEREG2(FDI_RXC_MISC, ironlake_debug_fdi_rx_misc),
+ DEFINEREG(FDI_RXA_TUSIZE1),
+ DEFINEREG(FDI_RXA_TUSIZE2),
+ DEFINEREG(FDI_RXB_TUSIZE1),
+ DEFINEREG(FDI_RXB_TUSIZE2),
+ DEFINEREG(FDI_RXC_TUSIZE1),
+ DEFINEREG(FDI_RXC_TUSIZE2),
+
+ DEFINEREG(FDI_PLL_CTL_1),
+ DEFINEREG(FDI_PLL_CTL_2),
+
+ DEFINEREG(FDI_RXA_IIR),
+ DEFINEREG(FDI_RXA_IMR),
+ DEFINEREG(FDI_RXB_IIR),
+ DEFINEREG(FDI_RXB_IMR),
+
+ DEFINEREG2(PCH_ADPA, i830_debug_adpa),
+ DEFINEREG2(HDMIB, ironlake_debug_hdmi),
+ DEFINEREG2(HDMIC, ironlake_debug_hdmi),
+ DEFINEREG2(HDMID, ironlake_debug_hdmi),
+ DEFINEREG2(PCH_LVDS, i830_debug_lvds),
+ DEFINEREG(CPU_eDP_A),
+ DEFINEREG(PCH_DP_B),
+ DEFINEREG(PCH_DP_C),
+ DEFINEREG(PCH_DP_D),
+ DEFINEREG2(TRANS_DP_CTL_A, snb_debug_trans_dp_ctl),
+ DEFINEREG2(TRANS_DP_CTL_B, snb_debug_trans_dp_ctl),
+ DEFINEREG2(TRANS_DP_CTL_C, snb_debug_trans_dp_ctl),
+
+ DEFINEREG(BLC_PWM_CPU_CTL2),
+ DEFINEREG(BLC_PWM_CPU_CTL),
+ DEFINEREG(BLC_PWM_PCH_CTL1),
+ DEFINEREG(BLC_PWM_PCH_CTL2),
+
+ DEFINEREG2(PCH_PP_STATUS, i830_debug_pp_status),
+ DEFINEREG2(PCH_PP_CONTROL, ilk_debug_pp_control),
+ DEFINEREG(PCH_PP_ON_DELAYS),
+ DEFINEREG(PCH_PP_OFF_DELAYS),
+ DEFINEREG(PCH_PP_DIVISOR),
+
+ DEFINEREG2(PORT_DBG, ivb_debug_port),
+
+ DEFINEREG(RC6_RESIDENCY_TIME),
+ DEFINEREG(RC6p_RESIDENCY_TIME),
+ DEFINEREG(RC6pp_RESIDENCY_TIME),
+};
+
+static struct reg_debug haswell_debug_regs[] = {
+ /* Power wells */
+ DEFINEREG(HSW_PWR_WELL_CTL1),
+ DEFINEREG(HSW_PWR_WELL_CTL2),
+ DEFINEREG(HSW_PWR_WELL_CTL3),
+ DEFINEREG(HSW_PWR_WELL_CTL4),
+ DEFINEREG(HSW_PWR_WELL_CTL5),
+ DEFINEREG(HSW_PWR_WELL_CTL6),
+
+ /* DDI pipe function */
+ DEFINEREG(PIPE_DDI_FUNC_CTL_A),
+ DEFINEREG(PIPE_DDI_FUNC_CTL_B),
+ DEFINEREG(PIPE_DDI_FUNC_CTL_C),
+ DEFINEREG(PIPE_DDI_FUNC_CTL_EDP),
+
+ /* DP transport control */
+ DEFINEREG(DP_TP_CTL_A),
+ DEFINEREG(DP_TP_CTL_B),
+ DEFINEREG(DP_TP_CTL_C),
+ DEFINEREG(DP_TP_CTL_D),
+ DEFINEREG(DP_TP_CTL_E),
+
+ /* DP status */
+ DEFINEREG(DP_TP_STATUS_A),
+ DEFINEREG(DP_TP_STATUS_B),
+ DEFINEREG(DP_TP_STATUS_C),
+ DEFINEREG(DP_TP_STATUS_D),
+ DEFINEREG(DP_TP_STATUS_E),
+
+ /* DDI buffer control */
+ DEFINEREG(DDI_BUF_CTL_A),
+ DEFINEREG(DDI_BUF_CTL_B),
+ DEFINEREG(DDI_BUF_CTL_C),
+ DEFINEREG(DDI_BUF_CTL_D),
+ DEFINEREG(DDI_BUF_CTL_E),
+
+ /* Clocks */
+ DEFINEREG(PIXCLK_GATE),
+ DEFINEREG(SPLL_CTL),
+ DEFINEREG(LCPLL_CTL),
+ DEFINEREG(WRPLL_CTL1),
+ DEFINEREG(WRPLL_CTL2),
+
+ /* DDI port clock control */
+ DEFINEREG(PORT_CLK_SEL_A),
+ DEFINEREG(PORT_CLK_SEL_B),
+ DEFINEREG(PORT_CLK_SEL_C),
+ DEFINEREG(PORT_CLK_SEL_D),
+ DEFINEREG(PORT_CLK_SEL_E),
+
+ /* Pipe clock control */
+ DEFINEREG(PIPE_CLK_SEL_A),
+ DEFINEREG(PIPE_CLK_SEL_B),
+ DEFINEREG(PIPE_CLK_SEL_C),
+
+ /* Pipe line time */
+ DEFINEREG(PIPE_WM_LINETIME_A),
+ DEFINEREG(PIPE_WM_LINETIME_B),
+ DEFINEREG(PIPE_WM_LINETIME_C),
+
+ /* Fuses */
+ DEFINEREG(SFUSE_STRAP),
+
+};
+
+static struct reg_debug i945gm_mi_regs[] = {
+ DEFINEREG(PGETBL_CTL),
+ DEFINEREG(PGTBL_ER),
+ DEFINEREG(EXCC),
+ DEFINEREG(HWS_PGA),
+ DEFINEREG(IPEIR),
+ DEFINEREG(IPEHR),
+ DEFINEREG(INST_DONE),
+ DEFINEREG(NOP_ID),
+ DEFINEREG(HWSTAM),
+ DEFINEREG(SCPD0),
+ DEFINEREG(IER),
+ DEFINEREG(IIR),
+ DEFINEREG(IMR),
+ DEFINEREG(ISR),
+ DEFINEREG(EIR),
+ DEFINEREG(EMR),
+ DEFINEREG(ESR),
+ DEFINEREG(INST_PM),
+ DEFINEREG(ECOSKPD),
+};
+
+#define intel_dump_regs(regs) _intel_dump_regs(regs, ARRAY_SIZE(regs))
+
+static void
+_intel_dump_regs(struct reg_debug *regs, int count)
+{
+ char debug[1024];
+ int i;
+
+ for (i = 0; i < count; i++) {
+ uint32_t val = INREG(regs[i].reg);
+
+ if (regs[i].debug_output != NULL) {
+ regs[i].debug_output(debug, sizeof(debug), regs[i].reg, val);
+ printf("%30.30s: 0x%08x (%s)\n",
+ regs[i].name,
+ (unsigned int)val, debug);
+ } else {
+ printf("%30.30s: 0x%08x\n", regs[i].name,
+ (unsigned int)val);
+ }
+ }
+}
+
+DEBUGSTRING(gen6_rp_control)
+{
+ snprintf(result, len, "%s",
+ (val & (1 << 7)) ? "enabled" : "disabled");
+}
+
+static struct reg_debug gen6_rp_debug_regs[] = {
+ DEFINEREG2(GEN6_RP_CONTROL, gen6_rp_control),
+ DEFINEREG(GEN6_RPNSWREQ),
+ DEFINEREG(GEN6_RP_DOWN_TIMEOUT),
+ DEFINEREG(GEN6_RP_INTERRUPT_LIMITS),
+ DEFINEREG(GEN6_RP_UP_THRESHOLD),
+ DEFINEREG(GEN6_RP_UP_EI),
+ DEFINEREG(GEN6_RP_DOWN_EI),
+ DEFINEREG(GEN6_RP_IDLE_HYSTERSIS),
+ DEFINEREG(GEN6_RC_STATE),
+ DEFINEREG(GEN6_RC_CONTROL),
+ DEFINEREG(GEN6_RC1_WAKE_RATE_LIMIT),
+ DEFINEREG(GEN6_RC6_WAKE_RATE_LIMIT),
+ DEFINEREG(GEN6_RC_EVALUATION_INTERVAL),
+ DEFINEREG(GEN6_RC_IDLE_HYSTERSIS),
+ DEFINEREG(GEN6_RC_SLEEP),
+ DEFINEREG(GEN6_RC1e_THRESHOLD),
+ DEFINEREG(GEN6_RC6_THRESHOLD),
+ DEFINEREG(GEN6_RC_VIDEO_FREQ),
+ DEFINEREG(GEN6_PMIER),
+ DEFINEREG(GEN6_PMIMR),
+ DEFINEREG(GEN6_PMINTRMSK),
+};
+
+static void
+intel_dump_other_regs(void)
+{
+ int i;
+ int fp, dpll;
+ int disp_pipe;
+ int n, m1, m2, m, p1, p2;
+ int ref;
+ int dot;
+ int phase;
+#if 0
+ int msr;
+ int crt;
+#endif
+
+#if 0
+ i830DumpIndexed(pScrn, "SR", 0x3c4, 0x3c5, 0, 7);
+ msr = INREG8(0x3cc);
+ printf("%20.20s: 0x%02x\n",
+ "MSR", (unsigned int)msr);
+
+ i830DumpAR(pScrn);
+ if (msr & 1)
+ crt = 0x3d0;
+ else
+ crt = 0x3b0;
+ i830DumpIndexed(pScrn, "CR", crt + 4, crt + 5, 0, 0x24);
+#endif
+ for (disp_pipe = 0; disp_pipe <= 1; disp_pipe++) {
+ fp = INREG(disp_pipe == 0 ? FPA0 : FPB0);
+ dpll = INREG(disp_pipe == 0 ? DPLL_A : DPLL_B);
+ if (IS_GEN2(devid)) {
+ uint32_t lvds = INREG(LVDS);
+ if (devid == PCI_CHIP_I855_GM &&
+ (lvds & LVDS_PORT_EN) &&
+ (lvds & LVDS_PIPEB_SELECT) == (disp_pipe << 30)) {
+ if ((lvds & LVDS_CLKB_POWER_MASK) ==
+ LVDS_CLKB_POWER_UP)
+ p2 = 7;
+ else
+ p2 = 14;
+ switch ((dpll >> 16) & 0x3f) {
+ case 0x01:
+ p1 = 1;
+ break;
+ case 0x02:
+ p1 = 2;
+ break;
+ case 0x04:
+ p1 = 3;
+ break;
+ case 0x08:
+ p1 = 4;
+ break;
+ case 0x10:
+ p1 = 5;
+ break;
+ case 0x20:
+ p1 = 6;
+ break;
+ default:
+ p1 = 1;
+ printf("LVDS P1 0x%x invalid encoding\n",
+ (dpll >> 16) & 0x3f);
+ break;
+ }
+ } else {
+ if (dpll & (1 << 23))
+ p2 = 4;
+ else
+ p2 = 2;
+ if (dpll & PLL_P1_DIVIDE_BY_TWO)
+ p1 = 2;
+ else
+ p1 = ((dpll >> 16) & 0x3f) + 2;
+ }
+
+ switch ((dpll >> 13) & 0x3) {
+ case 0:
+ ref = 48000;
+ break;
+ case 3:
+ ref = 66000;
+ break;
+ default:
+ ref = 0;
+ printf("ref out of range\n");
+ break;
+ }
+ } else {
+ uint32_t lvds = INREG(LVDS);
+ if ((lvds & LVDS_PORT_EN) &&
+ (lvds & LVDS_PIPEB_SELECT) == (disp_pipe << 30)) {
+ if ((lvds & LVDS_CLKB_POWER_MASK) ==
+ LVDS_CLKB_POWER_UP)
+ p2 = 7;
+ else
+ p2 = 14;
+ } else {
+ switch ((dpll >> 24) & 0x3) {
+ case 0:
+ p2 = 10;
+ break;
+ case 1:
+ p2 = 5;
+ break;
+ default:
+ p2 = 1;
+ printf("p2 out of range\n");
+ break;
+ }
+ }
+ if (IS_IGD(devid))
+ i = (dpll >> DPLL_FPA01_P1_POST_DIV_SHIFT_IGD) &
+ 0x1ff;
+ else
+ i = (dpll >> DPLL_FPA01_P1_POST_DIV_SHIFT) &
+ 0xff;
+ switch (i) {
+ case 1:
+ p1 = 1;
+ break;
+ case 2:
+ p1 = 2;
+ break;
+ case 4:
+ p1 = 3;
+ break;
+ case 8:
+ p1 = 4;
+ break;
+ case 16:
+ p1 = 5;
+ break;
+ case 32:
+ p1 = 6;
+ break;
+ case 64:
+ p1 = 7;
+ break;
+ case 128:
+ p1 = 8;
+ break;
+ case 256:
+ if (IS_IGD(devid)) {
+ p1 = 9;
+ break;
+ } /* fallback */
+ default:
+ p1 = 1;
+ printf("p1 out of range\n");
+ break;
+ }
+
+ switch ((dpll >> 13) & 0x3) {
+ case 0:
+ ref = 96000;
+ break;
+ case 3:
+ ref = 100000;
+ break;
+ default:
+ ref = 0;
+ printf("ref out of range\n");
+ break;
+ }
+ }
+ if (IS_965(devid)) {
+ phase = (dpll >> 9) & 0xf;
+ switch (phase) {
+ case 6:
+ break;
+ default:
+ printf("SDVO phase shift %d out of range -- probobly not "
+ "an issue.\n", phase);
+ break;
+ }
+ }
+ switch ((dpll >> 8) & 1) {
+ case 0:
+ break;
+ default:
+ printf("fp select out of range\n");
+ break;
+ }
+ m1 = ((fp >> 8) & 0x3f);
+ if (IS_IGD(devid)) {
+ n = ffs((fp & FP_N_IGD_DIV_MASK) >> FP_N_DIV_SHIFT) - 1;
+ m2 = (fp & FP_M2_IGD_DIV_MASK) >> FP_M2_DIV_SHIFT;
+ m = m2 + 2;
+ dot = (ref * m) / n / (p1 * p2);
+ } else {
+ n = ((fp >> 16) & 0x3f);
+ m2 = ((fp >> 0) & 0x3f);
+ m = 5 * (m1 + 2) + (m2 + 2);
+ dot =
+ (ref * (5 * (m1 + 2) + (m2 + 2)) / (n + 2)) / (p1 *
+ p2);
+ }
+
+ printf("pipe %s dot %d n %d m1 %d m2 %d p1 %d p2 %d\n",
+ disp_pipe == 0 ? "A" : "B", dot, n, m1, m2, p1, p2);
+ }
+}
+
+static void print_usage(void)
+{
+ printf("Usage: intel_reg_dumper [options] [file]\n"
+ "Options:\n"
+ " -d id when a dump file is used, use 'id' as device id (in "
+ "hex)\n"
+ " -h prints this help\n");
+}
+
+int main(int argc, char** argv)
+{
+ struct pci_device *pci_dev;
+ int opt;
+ char *file = NULL;
+
+ while ((opt = getopt(argc, argv, "d:h")) != -1) {
+ switch (opt) {
+ case 'd':
+ devid = strtol(optarg, NULL, 16);
+ break;
+ case 'h':
+ print_usage();
+ return 0;
+ default:
+ print_usage();
+ return 1;
+ }
+ }
+ if (optind < argc)
+ file = argv[optind];
+
+ if (file) {
+ intel_map_file(file);
+ if (devid) {
+ if (IS_GEN5(devid))
+ pch = PCH_IBX;
+ else
+ pch = PCH_CPT;
+ } else {
+ printf("Dumping from file without -d argument. "
+ "Assuming Ironlake machine.\n");
+ devid = 0x0042;
+ pch = PCH_IBX;
+ }
+ } else {
+ pci_dev = intel_get_pci_device();
+ devid = pci_dev->device_id;
+
+ intel_register_access_init(pci_dev, 1);
+
+ if (HAS_PCH_SPLIT(devid))
+ intel_check_pch();
+ }
+
+ if (HAS_PCH_SPLIT(devid)) {
+ intel_dump_regs(ironlake_debug_regs);
+ } else if (IS_945GM(devid)) {
+ intel_dump_regs(i945gm_mi_regs);
+ intel_dump_regs(intel_debug_regs);
+ intel_dump_other_regs();
+ } else {
+ intel_dump_regs(intel_debug_regs);
+ intel_dump_other_regs();
+ }
+
+ if (IS_GEN6(devid) || IS_GEN7(devid))
+ intel_dump_regs(gen6_rp_debug_regs);
+
+ if (IS_HASWELL(devid))
+ intel_dump_regs(haswell_debug_regs);
+
+
+ intel_register_access_fini();
+ return 0;
+}
diff --git a/tools/intel_reg_read.c b/tools/intel_reg_read.c
new file mode 100644
index 00000000..ae631be0
--- /dev/null
+++ b/tools/intel_reg_read.c
@@ -0,0 +1,142 @@
+/*
+ * Copyright © 2010 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:
+ * Zhenyu Wang <zhenyuw@linux.intel.com>
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+#include <string.h>
+#include "intel_gpu_tools.h"
+
+static void bit_decode(uint32_t reg)
+{
+ int i;
+
+ for (i=31; i >= 0; i--)
+ printf(" %2d", i);
+ printf("\n");
+
+ for (i=31; i >= 0; i--)
+ printf(" %2d", (reg & (1 << i)) && 1);
+ printf("\n");
+}
+
+static void dump_range(uint32_t start, uint32_t end)
+{
+ int i;
+
+ for (i = start; i < end; i += 4)
+ printf("0x%X : 0x%X\n", i,
+ *(volatile uint32_t *)((volatile char*)mmio + i));
+}
+
+static void usage(char *cmdname)
+{
+ printf("Usage: %s [-f|-d] [addr1] [addr2] .. [addrN]\n", cmdname);
+ printf("\t -f : read back full range of registers.\n");
+ printf("\t WARNING! This option may result in a machine hang!\n");
+ printf("\t -d : decode register bits.\n");
+ printf("\t -c : number of dwords to dump (can't be used with -f/-d).\n");
+ printf("\t addr : in 0xXXXX format\n");
+}
+
+int main(int argc, char** argv)
+{
+ int ret = 0;
+ uint32_t reg;
+ int i, ch;
+ char *cmdname = strdup(argv[0]);
+ int full_dump = 0;
+ int decode_bits = 0;
+ int dwords = 1;
+
+ while ((ch = getopt(argc, argv, "dfhc:")) != -1) {
+ switch(ch) {
+ case 'd':
+ decode_bits = 1;
+ break;
+ case 'f':
+ full_dump = 1;
+ break;
+ case 'h':
+ usage(cmdname);
+ ret = 1;
+ goto out;
+ case 'c':
+ dwords = strtol(optarg, NULL, 0);
+ break;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1) {
+ usage(cmdname);
+ ret = 1;
+ goto out;
+ }
+
+ if ((dwords > 1) && (argc != 1 || full_dump || decode_bits)) {
+ usage(cmdname);
+ ret = 1;
+ goto out;
+ }
+
+ intel_register_access_init(intel_get_pci_device(), 0);
+
+ if (full_dump) {
+ dump_range(0x00000, 0x00fff); /* VGA registers */
+ dump_range(0x02000, 0x02fff); /* instruction, memory, interrupt control registers */
+ dump_range(0x03000, 0x031ff); /* FENCE and PPGTT control registers */
+ dump_range(0x03200, 0x03fff); /* frame buffer compression registers */
+ dump_range(0x05000, 0x05fff); /* I/O control registers */
+ dump_range(0x06000, 0x06fff); /* clock control registers */
+ dump_range(0x07000, 0x07fff); /* 3D internal debug registers */
+ dump_range(0x07400, 0x088ff); /* GPE debug registers */
+ dump_range(0x0a000, 0x0afff); /* display palette registers */
+ dump_range(0x10000, 0x13fff); /* MMIO MCHBAR */
+ dump_range(0x30000, 0x3ffff); /* overlay registers */
+ dump_range(0x60000, 0x6ffff); /* display engine pipeline registers */
+ dump_range(0x70000, 0x72fff); /* display and cursor registers */
+ dump_range(0x73000, 0x73fff); /* performance counters */
+ } else {
+ for (i=0; i < argc; i++) {
+ sscanf(argv[i], "0x%x", &reg);
+ dump_range(reg, reg + (dwords * 4));
+
+ if (decode_bits)
+ bit_decode(*(volatile uint32_t *)((volatile char*)mmio + reg));
+ }
+ }
+
+ intel_register_access_fini();
+
+out:
+ free(cmdname);
+ return ret;
+}
+
diff --git a/tools/intel_reg_snapshot.c b/tools/intel_reg_snapshot.c
new file mode 100644
index 00000000..83e76e5c
--- /dev/null
+++ b/tools/intel_reg_snapshot.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright © 2010 Red Hat, Inc.
+ *
+ * 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:
+ * Adam Jackson <ajax@redhat.com>
+ */
+
+#include <unistd.h>
+#include "intel_gpu_tools.h"
+
+int main(int argc, char** argv)
+{
+ struct pci_device *pci_dev;
+ uint32_t devid;
+ int mmio_bar;
+
+ pci_dev = intel_get_pci_device();
+ devid = pci_dev->device_id;
+ intel_get_mmio(pci_dev);
+
+ if (IS_GEN2(devid))
+ mmio_bar = 1;
+ else
+ mmio_bar = 0;
+
+ write(1, mmio, pci_dev->regions[mmio_bar].size);
+
+ return 0;
+}
diff --git a/tools/intel_reg_write.c b/tools/intel_reg_write.c
new file mode 100644
index 00000000..dd636f65
--- /dev/null
+++ b/tools/intel_reg_write.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright © 2007 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:
+ * Ben Gamari <bgamari.foss@gmail.com>
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+#include "intel_gpu_tools.h"
+
+int main(int argc, char** argv)
+{
+ uint32_t reg, value;
+ volatile uint32_t *ptr;
+
+ if (argc < 3) {
+ printf("Usage: %s addr value\n", argv[0]);
+ printf(" WARNING: This is dangerous to you and your system's health.\n");
+ printf(" Only for use in debugging.\n");
+ exit(1);
+ }
+
+ intel_register_access_init(intel_get_pci_device(), 0);
+ sscanf(argv[1], "0x%x", &reg);
+ sscanf(argv[2], "0x%x", &value);
+ ptr = (volatile uint32_t *)((volatile char *)mmio + reg);
+
+ printf("Value before: 0x%X\n", *ptr);
+ *ptr = value;
+ printf("Value after: 0x%X\n", *ptr);
+
+ intel_register_access_fini();
+ return 0;
+}
+
diff --git a/tools/intel_stepping.c b/tools/intel_stepping.c
new file mode 100644
index 00000000..f6f15d1a
--- /dev/null
+++ b/tools/intel_stepping.c
@@ -0,0 +1,294 @@
+/*
+ * Copyright © 2007 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:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <pciaccess.h>
+#include <err.h>
+#include "intel_chipset.h"
+#include "intel_gpu_tools.h"
+
+static void
+print_clock(const char *name, int clock) {
+ if (clock == -1)
+ printf("%s clock: unknown", name);
+ else
+ printf("%s clock: %d Mhz", name, clock);
+}
+
+static int
+print_clock_info(struct pci_device *pci_dev)
+{
+ uint32_t devid = pci_dev->device_id;
+ uint16_t gcfgc;
+
+ if (IS_GM45(devid)) {
+ int core_clock = -1;
+
+ pci_device_cfg_read_u16(pci_dev, &gcfgc, I915_GCFGC);
+
+ switch (gcfgc & 0xf) {
+ case 8:
+ core_clock = 266;
+ break;
+ case 9:
+ core_clock = 320;
+ break;
+ case 11:
+ core_clock = 400;
+ break;
+ case 13:
+ core_clock = 533;
+ break;
+ }
+ print_clock("core", core_clock);
+ } else if (IS_965(devid) && IS_MOBILE(devid)) {
+ int render_clock = -1, sampler_clock = -1;
+
+ pci_device_cfg_read_u16(pci_dev, &gcfgc, I915_GCFGC);
+
+ switch (gcfgc & 0xf) {
+ case 2:
+ render_clock = 250; sampler_clock = 267;
+ break;
+ case 3:
+ render_clock = 320; sampler_clock = 333;
+ break;
+ case 4:
+ render_clock = 400; sampler_clock = 444;
+ break;
+ case 5:
+ render_clock = 500; sampler_clock = 533;
+ break;
+ }
+
+ print_clock("render", render_clock);
+ printf(" ");
+ print_clock("sampler", sampler_clock);
+ } else if (IS_945(devid) && IS_MOBILE(devid)) {
+ int render_clock = -1, display_clock = -1;
+
+ pci_device_cfg_read_u16(pci_dev, &gcfgc, I915_GCFGC);
+
+ switch (gcfgc & 0x7) {
+ case 0:
+ render_clock = 166;
+ break;
+ case 1:
+ render_clock = 200;
+ break;
+ case 3:
+ render_clock = 250;
+ break;
+ case 5:
+ render_clock = 400;
+ break;
+ }
+
+ switch (gcfgc & 0x70) {
+ case 0:
+ display_clock = 200;
+ break;
+ case 4:
+ display_clock = 320;
+ break;
+ }
+ if (gcfgc & (1 << 7))
+ display_clock = 133;
+
+ print_clock("render", render_clock);
+ printf(" ");
+ print_clock("display", display_clock);
+ } else if (IS_915(devid) && IS_MOBILE(devid)) {
+ int render_clock = -1, display_clock = -1;
+
+ pci_device_cfg_read_u16(pci_dev, &gcfgc, I915_GCFGC);
+
+ switch (gcfgc & 0x7) {
+ case 0:
+ render_clock = 160;
+ break;
+ case 1:
+ render_clock = 190;
+ break;
+ case 4:
+ render_clock = 333;
+ break;
+ }
+ if (gcfgc & (1 << 13))
+ render_clock = 133;
+
+ switch (gcfgc & 0x70) {
+ case 0:
+ display_clock = 190;
+ break;
+ case 4:
+ display_clock = 333;
+ break;
+ }
+ if (gcfgc & (1 << 7))
+ display_clock = 133;
+
+ print_clock("render", render_clock);
+ printf(" ");
+ print_clock("display", display_clock);
+ }
+
+ printf("\n");
+ return -1;
+}
+
+int main(int argc, char **argv)
+{
+ struct pci_device *dev, *bridge;
+ int error;
+ uint8_t stepping;
+ const char *step_desc = "??";
+
+ error = pci_system_init();
+ if (error != 0) {
+ fprintf(stderr, "Couldn't initialize PCI system: %s\n",
+ strerror(error));
+ exit(1);
+ }
+
+ /* Grab the graphics card */
+ dev = pci_device_find_by_slot(0, 0, 2, 0);
+ if (dev == NULL)
+ errx(1, "Couldn't find graphics card");
+
+ error = pci_device_probe(dev);
+ if (error != 0) {
+ fprintf(stderr, "Couldn't probe graphics card: %s\n",
+ strerror(error));
+ exit(1);
+ }
+
+ if (dev->vendor_id != 0x8086)
+ errx(1, "Graphics card is non-intel");
+
+ bridge = pci_device_find_by_slot(0, 0, 0, 0);
+ if (dev == NULL)
+ errx(1, "Couldn't bridge");
+
+ error = pci_device_cfg_read_u8(bridge, &stepping, 8);
+ if (error != 0) {
+ fprintf(stderr, "Couldn't read revision ID: %s\n",
+ strerror(error));
+ exit(1);
+ }
+
+ switch (dev->device_id) {
+ case PCI_CHIP_I915_G:
+ if (stepping < 0x04)
+ step_desc = "<B1";
+ else if (stepping == 0x04)
+ step_desc = "B1";
+ else if (stepping == 0x0e)
+ step_desc = "C2";
+ else if (stepping > 0x0e)
+ step_desc = ">C2";
+ else
+ step_desc = ">B1 <C2";
+ break;
+ case PCI_CHIP_I915_GM:
+ if (stepping < 0x03)
+ step_desc = "<B1";
+ else if (stepping == 0x03)
+ step_desc = "B1/C0";
+ else if (stepping == 0x04)
+ step_desc = "C1/C2";
+ else
+ step_desc = ">C2";
+ break;
+ case PCI_CHIP_I945_GM:
+ if (stepping < 0x03)
+ step_desc = "<A3";
+ else if (stepping == 0x03)
+ step_desc = "A3";
+ else
+ step_desc = ">A3";
+ break;
+ case PCI_CHIP_I965_G:
+ case PCI_CHIP_I965_Q:
+ if (stepping < 0x02)
+ step_desc = "<C1";
+ else if (stepping == 0x02)
+ step_desc = "C1/C2";
+ else
+ step_desc = ">C2";
+ break;
+ case PCI_CHIP_I965_GM:
+ if (stepping < 0x03)
+ step_desc = "<C0";
+ else if (stepping == 0x03)
+ step_desc = "C0";
+ else
+ step_desc = ">C0";
+ break;
+ case PCI_CHIP_I965_G_1:
+ if (stepping < 0x03)
+ step_desc = "<E0";
+ else if (stepping == 0x03)
+ step_desc = "E0";
+ else
+ step_desc = ">E0";
+ break;
+ case PCI_CHIP_GM45_GM:
+ if (stepping < 0x07)
+ step_desc = "<B3";
+ else if (stepping == 0x03)
+ step_desc = "B3";
+ else
+ step_desc = ">B3";
+ break;
+ case PCI_CHIP_G45_G:
+ case PCI_CHIP_Q45_G:
+ case PCI_CHIP_G41_G:
+ if (stepping < 0x02)
+ step_desc = "<A2";
+ else if (stepping == 0x02)
+ step_desc = "A2";
+ else if (stepping == 0x03)
+ step_desc = "A3";
+ else
+ step_desc = ">A3";
+ break;
+ }
+
+ printf("Vendor: 0x%04x, Device: 0x%04x, Revision: 0x%02x (%s)\n",
+ dev->vendor_id,
+ dev->device_id,
+ stepping,
+ step_desc);
+
+ print_clock_info(dev);
+
+ return 0;
+}