Upgrade igt-gpu-tools to 1a5b48671e0863cb723e3d0239e54c828360dc99

Exempt-From-Owner-Approval: upgrade library
Test: None
Change-Id: I4c73c898f2f1fe0a23160333a81ca99506d6a08a
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 893dc98..7ed538a 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,14 +1,14 @@
 image: $CI_REGISTRY/$CI_PROJECT_PATH/igt-fedora:latest
 variables:
   MESON_OPTIONS: >
-    -Dwith_libdrm=intel,nouveau,amdgpu
-    -Dbuild_overlay=enabled
-    -Dbuild_chamelium=enabled
-    -Dwith_valgrind=enabled
-    -Dbuild_man=enabled
-    -Dbuild_tests=enabled
-    -Dbuild_runner=enabled
-    -Dwith_libunwind=enabled
+    -Dlibdrm_drivers=intel,nouveau,amdgpu
+    -Doverlay=enabled
+    -Dchamelium=enabled
+    -Dvalgrind=enabled
+    -Dman=enabled
+    -Dtests=enabled
+    -Drunner=enabled
+    -Dlibunwind=enabled
   LANG: "C.UTF-8"
 
 stages:
@@ -33,7 +33,7 @@
   stage: build
   script:
     - dnf remove -y libunwind-devel
-    - meson -Dlibunwind=false build
+    - meson -Dlibunwind=disabled build
     - ninja -C build
 
 # documentation building is different with meson<0.47
@@ -72,7 +72,7 @@
   image: $CI_REGISTRY/$CI_PROJECT_PATH/igt-debian-minimal:latest
   stage: build
   script:
-    - meson -Dbuild_tests=disabled -Dwith_libdrm="" build
+    - meson -Dtests=disabled -Dlibdrm_drivers="" build
     - ninja -C build
   artifacts:
     paths:
@@ -100,6 +100,17 @@
     paths:
       - build
 
+build:tests-debian-meson-mips:
+  image: $CI_REGISTRY/$CI_PROJECT_PATH/igt-debian-mips:latest
+  stage: build
+  script:
+    - export PKG_CONFIG_PATH=/usr/lib/mips-linux-gnu/pkgconfig/
+    - meson --cross-file meson-cross-mips.txt build
+    - ninja -C build
+  artifacts:
+    paths:
+      - build
+
 build:tests-debian-autotools:
   image: $CI_REGISTRY/$CI_PROJECT_PATH/igt-debian:latest
   stage: build
@@ -162,6 +173,20 @@
       - build
     when: on_failure
 
+test:ninja-test-mips:
+  image: $CI_REGISTRY/$CI_PROJECT_PATH/igt-debian-mips:latest
+  dependencies:
+    - build:tests-debian-meson-mips
+  stage: test
+  script:
+    - export PKG_CONFIG_PATH=/usr/lib/mips-linux-gnu/pkgconfig/
+    - env > build/envdump.txt
+    - ninja -C build test
+  artifacts:
+    paths:
+      - build
+    when: on_failure
+
 test:test-list-diff:
   dependencies:
     - build:tests-debian-autotools
@@ -241,6 +266,23 @@
     - docker build -t $CI_REGISTRY/$CI_PROJECT_PATH/igt-debian-arm64 -f Dockerfile.debian-arm64 .
     - docker push $CI_REGISTRY/$CI_PROJECT_PATH/igt-debian-arm64
 
+containers:igt-debian-mips:
+  stage: containers
+  image: docker:stable
+  only:
+    changes:
+      - Dockerfile.debian-mips
+      - .gitlab-ci.yml
+  services:
+    - docker:dind
+  variables:
+    DOCKER_HOST: tcp://docker:2375
+    DOCKER_DRIVER: overlay2
+  script:
+    - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
+    - docker build -t $CI_REGISTRY/$CI_PROJECT_PATH/igt-debian-mips -f Dockerfile.debian-mips .
+    - docker push $CI_REGISTRY/$CI_PROJECT_PATH/igt-debian-mips
+
 containers:igt-fedora:
   stage: containers
   image: docker:stable
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index d3a3d09..6d1294a 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,9 +1,43 @@
+CONTRIBUTING
+============
+
 Patches to igt-gpu-tools are very much welcome, we really want this to be the
 universal set of low-level tools and testcases for kernel graphics drivers
 on Linux and similar platforms. So please bring on porting patches, bugfixes,
 improvements for documentation and new tools and testcases.
 
-A short list of contribution guidelines:
+
+The Code
+--------
+
+- The code should follow kernel coding style:
+  https://www.kernel.org/doc/html/latest/process/coding-style.html
+
+- Testcases (subtests) have to use minus signs (-) as a word separator.
+  The generated documentation contains glossary of commonly used terms.
+
+- All new test have to be described using `igt_describe()` family of
+  functions. The description should contain the spirit of the test (what is
+  the general idea behind the test) and *not* the letter (C to English
+  translation of the test). Refer to [`igt_describe()`
+  documentation][igt-describe] for more details.
+
+- The generated documentation contains explanation of magic control blocks like
+  `igt_subtest` and `igt_fixture`. Please make sure that you understand their
+  roles and limitation before using/altering them.
+
+- Also please make full use of all the helpers and convenience macros
+  provided by the igt library. The semantic patch lib/igt.cocci can help with
+  more automatic conversions.
+
+[igt-describe]: https://drm.pages.freedesktop.org/igt-gpu-tools/igt-gpu-tools-Core.html#igt-describe
+
+
+Sending Patches
+---------------
+
+- igt-gpu-tools is MIT licensed and we require contributions to follow the
+  developer's certificate of origin: http://developercertificate.org/
 
 - Please submit patches formatted with git send-email/git format-patch or
   equivalent to:
@@ -23,14 +57,6 @@
 
   on its first invocation.
 
-- igt-gpu-tools is MIT licensed and we require contributions to follow the
-  developer's certificate of origin: http://developercertificate.org/
-
-- When submitting new testcases please follow the naming conventions documented
-  in the generated documentation. Also please make full use of all the helpers
-  and convenience macros provided by the igt library. The semantic patch
-  lib/igt.cocci can help with the more automatic conversions.
-
 - Patches need to be reviewed on the mailing list. Exceptions only apply for
   testcases and tooling for drivers with just a single contributor (e.g. vc4).
   In this case patches must still be submitted to the mailing list first.
@@ -46,7 +72,8 @@
 - Changes to the testcases are automatically tested. Take the results into
   account before merging.
 
-Commit rights
+
+Commit Rights
 -------------
 
 Commit rights will be granted to anyone who requests them and fulfills the
@@ -80,6 +107,7 @@
 Maintainers and committers should encourage contributors to request commit
 rights, especially junior contributors tend to underestimate their skills.
 
+
 Code of Conduct
 ---------------
 
diff --git a/Dockerfile.debian-arm64 b/Dockerfile.debian-arm64
index 7b3a3c7..c9fb28c 100644
--- a/Dockerfile.debian-arm64
+++ b/Dockerfile.debian-arm64
@@ -14,6 +14,7 @@
 RUN apt-get update
 RUN apt-get install -y \
 			gcc-aarch64-linux-gnu \
+			libatomic1:arm64 \
 			libpciaccess-dev:arm64 \
 			libkmod-dev:arm64 \
 			libprocps-dev:arm64 \
diff --git a/Dockerfile.debian-armhf b/Dockerfile.debian-armhf
index c67a1e2..3a133d8 100644
--- a/Dockerfile.debian-armhf
+++ b/Dockerfile.debian-armhf
@@ -14,6 +14,7 @@
 RUN apt-get update
 RUN apt-get install -y \
 			gcc-arm-linux-gnueabihf \
+			libatomic1:armhf \
 			libpciaccess-dev:armhf \
 			libkmod-dev:armhf \
 			libprocps-dev:armhf \
diff --git a/Dockerfile.debian-minimal b/Dockerfile.debian-minimal
index bbe70be..6384469 100644
--- a/Dockerfile.debian-minimal
+++ b/Dockerfile.debian-minimal
@@ -6,6 +6,7 @@
 			flex \
 			bison \
 			pkg-config \
+			libatomic1 \
 			libpciaccess-dev \
 			libkmod-dev \
 			libprocps-dev \
diff --git a/Dockerfile.debian-mips b/Dockerfile.debian-mips
new file mode 100644
index 0000000..ee29f5f
--- /dev/null
+++ b/Dockerfile.debian-mips
@@ -0,0 +1,39 @@
+FROM debian:stretch-backports
+
+RUN apt-get update
+RUN apt-get install -y \
+			flex \
+			bison \
+			pkg-config \
+			x11proto-dri2-dev \
+			python-docutils \
+			valgrind \
+			peg
+
+RUN dpkg --add-architecture mips
+RUN apt-get update
+RUN apt-get install -y \
+			gcc-mips-linux-gnu \
+			libatomic1:mips \
+			libpciaccess-dev:mips \
+			libkmod-dev:mips \
+			libprocps-dev:mips \
+			libunwind-dev:mips \
+			libdw-dev:mips \
+			zlib1g-dev:mips \
+			liblzma-dev:mips \
+			libcairo-dev:mips \
+			libpixman-1-dev:mips \
+			libudev-dev:mips \
+			libgsl-dev:mips \
+			libasound2-dev:mips \
+			libjson-c-dev:mips \
+			libcurl4-openssl-dev:mips \
+			libxrandr-dev:mips \
+			libxv-dev:mips
+
+RUN apt-get install -t stretch-backports -y \
+			meson \
+			libdrm-dev:mips \
+			qemu-user \
+			qemu-user-static
diff --git a/Dockerfile.fedora b/Dockerfile.fedora
index 6686e58..fa27a62 100644
--- a/Dockerfile.fedora
+++ b/Dockerfile.fedora
@@ -1,7 +1,7 @@
 FROM fedora:30
 
 RUN dnf install -y \
-	gcc flex bison meson ninja-build xdotool \
+	gcc flex bison libatomic meson ninja-build xdotool \
 	'pkgconfig(libdrm)' \
 	'pkgconfig(pciaccess)' \
 	'pkgconfig(libkmod)' \
@@ -28,7 +28,8 @@
 RUN dnf install -y make
 RUN mkdir /tmp/peg
 WORKDIR /tmp/peg
-RUN curl -O http://piumarta.com/software/peg/peg-0.1.18.tar.gz
+# originaly from http://piumarta.com/software/peg/
+RUN curl -O https://intel-gfx-ci.01.org/mirror/peg/peg-0.1.18.tar.gz
 RUN tar xf peg-0.1.18.tar.gz
 RUN cd peg-0.1.18 && make PREFIX=/usr install
 RUN rm -fr /tmp/peg
diff --git a/METADATA b/METADATA
index 69d80ce..aa97f6f 100644
--- a/METADATA
+++ b/METADATA
@@ -5,11 +5,11 @@
     type: GIT
     value: "https://gitlab.freedesktop.org/drm/igt-gpu-tools"
   }
-  version: "22850c1906550fb97b405c019275dcfb34be8cf7"
+  version: "1a5b48671e0863cb723e3d0239e54c828360dc99"
   license_type: NOTICE
   last_upgrade_date {
     year: 2019
-    month: 6
-    day: 20
+    month: 7
+    day: 22
   }
 }
diff --git a/NEWS b/NEWS
index d94374f..d4e381e 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,10 @@
+Unreleased
+----------
+
+Meson build options have been renamed. Please check the news options in
+meson_options.txt and make sure you don't get any warnings when configuring the
+project.
+
 Release 1.24 (2019-06-20)
 -------------------------
 
diff --git a/docs/reference/igt-gpu-tools/generate_description_xml.py b/docs/reference/igt-gpu-tools/generate_description_xml.py
new file mode 100755
index 0000000..8bb0989
--- /dev/null
+++ b/docs/reference/igt-gpu-tools/generate_description_xml.py
@@ -0,0 +1,114 @@
+#!/usr/bin/env python3
+
+import re
+import sys
+import os.path
+import subprocess
+import xml.etree.cElementTree as ET
+
+from collections import namedtuple
+
+Subtest = namedtuple("Subtest", "name description")
+KEYWORDS=re.compile(r'\b(invalid|hang|swap|thrash|crc|tiled|tiling|rte|ctx|render|blt|bsd|vebox|exec|rpm)\b')
+
+
+def get_testlist(path):
+    "read binaries' names from test-list.txt"
+    with open(path, 'r') as f:
+        assert(f.readline() == "TESTLIST\n")
+        tests = f.readline().strip().split(" ")
+        assert(f.readline() == "END TESTLIST\n")
+
+    return tests
+
+
+def keywordize(root, text, keywords):
+    "set text for root element and wrap KEYWORDS in a <acronym>"
+    matches = list(keywords.finditer(text))
+
+    if not matches:
+        root.text = text
+        return
+
+    pos = 0
+    last_element = None
+    root.text = ""
+
+    for match in matches:
+        if match.start() > pos:
+            to_append = text[pos:match.start()]
+
+            if last_element == None:
+                root.text += to_append
+            else:
+                last_element.tail += to_append
+
+        last_element = ET.SubElement(root, "acronym")
+        last_element.tail = ""
+        last_element.text=match.group()
+        pos = match.end()
+
+    last_element.tail = text[pos:]
+
+
+def get_subtests(testdir, test):
+    "execute test and get subtests with their descriptions via --describe"
+    output = []
+    full_test_path = os.path.join(testdir, test)
+    proc = subprocess.run([full_test_path, "--describe"], stdout=subprocess.PIPE)
+    description = ""
+    current_subtest = None
+
+    for line in proc.stdout.decode().splitlines():
+        if line.startswith("SUB "):
+            output += [Subtest(current_subtest, description)]
+            description = ""
+            current_subtest = line.split(' ')[1]
+        else:
+            description += line
+
+    output += [Subtest(current_subtest, description)]
+
+    return output
+
+def main():
+    output_file   = sys.argv[1]
+    test_filter   = re.compile(sys.argv[2])
+    testlist_file = sys.argv[3]
+    testdir       = os.path.abspath(os.path.dirname(testlist_file))
+
+    root = ET.Element("refsect1")
+    ET.SubElement(root, "title").text = "Description"
+
+    tests = get_testlist(testlist_file)
+
+    for test in tests:
+        if not test_filter.match(test):
+            continue
+
+        test_section = ET.SubElement(root, "refsect2", id=test)
+        test_title = ET.SubElement(test_section, "title")
+        keywordize(test_title, test, KEYWORDS)
+
+        subtests = get_subtests(testdir, test)
+
+        # we have description with no subtest name, add it at the top level
+        if subtests and not subtests[0].name:
+            ET.SubElement(test_section, "para").text = subtests[0].description
+
+        if len(subtests) > 100:
+            ET.SubElement(test_section, "para").text = "More than 100 subtests, skipping listing"
+            continue
+
+        for name, description in subtests:
+            if not name:
+                continue
+
+            subtest_section = ET.SubElement(test_section, "refsect3", id="{}@{}".format(test, name))
+            subtest_title = ET.SubElement(subtest_section, "title")
+            keywordize(subtest_title, name, KEYWORDS)
+            ET.SubElement(subtest_section, "para").text = description
+
+    ET.ElementTree(root).write(output_file)
+
+main()
diff --git a/docs/reference/igt-gpu-tools/generate_description_xml.sh b/docs/reference/igt-gpu-tools/generate_description_xml.sh
deleted file mode 100644
index 705a7bf..0000000
--- a/docs/reference/igt-gpu-tools/generate_description_xml.sh
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/bin/sh
-
-output=$1
-filter=$2
-testlist=$3
-testdir=$(dirname $testlist)
-
-KEYWORDS="(invalid|hang|swap|thrash|crc|tiled|tiling|rte|ctx|render|blt|bsd|vebox|exec|rpm)"
-
-echo "<?xml version=\"1.0\"?>" > $output
-echo "<!DOCTYPE refsect1 PUBLIC \"-//OASIS//DTD DocBook XML V4.3//EN\"" >> $output
-echo "               \"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd\"" >> $output
-echo "[" >> $output
-echo "  <!ENTITY % local.common.attrib \"xmlns:xi  CDATA  #FIXED 'http://www.w3.org/2003/XInclude'\">" >> $output
-echo "  <!ENTITY version SYSTEM \"version.xml\">" >> $output
-echo "]>" >> $output
-echo "<refsect1>" >> $output
-echo "<title>Description</title>" >> $output
-for test in `cat $testlist | tr ' ' '\n' | grep "^$filter" | sort`; do
-	echo "<refsect2 id=\"$test\"><title>" >> $output;
-	echo "$test" | perl -pe "s/(?<=_)$KEYWORDS(?=(_|\\W))/<acronym>\\1<\\/acronym>/g" >> $output;
-	echo "</title><para><![CDATA[" >> $output;
-	testprog=$testdir/$test;
-	 ./$testprog --help-description >> $output;
-	echo "]]></para>" >> $output;
-	if ./$testprog --list-subtests > /dev/null ; then
-		echo "<refsect3><title>Subtests</title>" >> $output;
-		subtest_list=`./$testprog --list-subtests`;
-		subtest_count=`echo $subtest_list | wc -w`;
-		if [ $subtest_count -gt 100 ]; then
-			echo "<para>This test has over 100 subtests. " >> $output;
-			echo "Run <command>$test</command> <option>--list-subtests</option> to list them.</para>" >> $output;
-		else
-			echo "<simplelist>" >> $output;
-			for subtest in $subtest_list; do
-				echo "<member>" >> $output;
-				echo "$subtest" | perl -pe "s/\\b$KEYWORDS\\b/<acronym>\\1<\\/acronym>/g" >> $output;
-				echo "</member>" >> $output;
-			done;
-			echo "</simplelist>" >> $output;
-		fi;
-		echo "</refsect3>" >> $output;
-	fi;
-	echo "</refsect2>" >> $output;
-done;
-echo "</refsect1>" >> $output
diff --git a/docs/reference/igt-gpu-tools/meson.build b/docs/reference/igt-gpu-tools/meson.build
index 4d177e4..e2bdc49 100644
--- a/docs/reference/igt-gpu-tools/meson.build
+++ b/docs/reference/igt-gpu-tools/meson.build
@@ -45,7 +45,7 @@
 	'vgem',
 ]
 
-gen_description = find_program('generate_description_xml.sh')
+gen_description = find_program('generate_description_xml.py')
 gen_programs = find_program('generate_programs_xml.sh')
 
 generated_docs = []
diff --git a/lib/drmtest.c b/lib/drmtest.c
index 25f2035..c379a7b 100644
--- a/lib/drmtest.c
+++ b/lib/drmtest.c
@@ -187,12 +187,6 @@
 	return igt_kmod_load(driver, "");
 }
 
-/* virtio's driver name is virtio_gpu but the module is virtio-gpu.ko */
-static void modprobe_virtio(const char *name)
-{
-	igt_kmod_load("virtio-gpu", "");
-}
-
 static void modprobe_i915(const char *name)
 {
 	/* When loading i915, we also want to load snd-hda et al */
@@ -210,7 +204,6 @@
 	{ DRIVER_V3D, "v3d" },
 	{ DRIVER_VC4, "vc4" },
 	{ DRIVER_VGEM, "vgem" },
-	{ DRIVER_VIRTIO, "virtio_gpu", modprobe_virtio },
 	{}
 };
 
@@ -363,8 +356,6 @@
 		return "vc4";
 	case DRIVER_VGEM:
 		return "vgem";
-	case DRIVER_VIRTIO:
-		return "virtio";
 	case DRIVER_AMDGPU:
 		return "amdgpu";
 	case DRIVER_PANFROST:
diff --git a/lib/drmtest.h b/lib/drmtest.h
index 6c4c389..614f57e 100644
--- a/lib/drmtest.h
+++ b/lib/drmtest.h
@@ -38,13 +38,18 @@
 
 #include "igt_core.h"
 
+/*
+ * NOTE: Theser are _only_ for testcases exercising driver specific rendering
+ * ioctls and uapi (and a bunch of historical reasons). And KMS testcase should
+ * be build on top of DRIVER_ANY. Do _NOT_ add your driver here for enabling KMS
+ * tests.
+ */
 #define DRIVER_INTEL	(1 << 0)
 #define DRIVER_VC4	(1 << 1)
 #define DRIVER_VGEM	(1 << 2)
-#define DRIVER_VIRTIO	(1 << 3)
-#define DRIVER_AMDGPU	(1 << 4)
-#define DRIVER_V3D	(1 << 5)
-#define DRIVER_PANFROST	(1 << 6)
+#define DRIVER_AMDGPU	(1 << 3)
+#define DRIVER_V3D	(1 << 4)
+#define DRIVER_PANFROST	(1 << 5)
 /*
  * Exclude DRVER_VGEM from DRIVER_ANY since if you run on a system
  * with vgem as well as a supported driver, you can end up with a
diff --git a/lib/i915/gem_engine_topology.c b/lib/i915/gem_engine_topology.c
index fdd1b95..790d455 100644
--- a/lib/i915/gem_engine_topology.c
+++ b/lib/i915/gem_engine_topology.c
@@ -289,3 +289,51 @@
 
 	return !__gem_context_get_param(fd, &param);
 }
+
+struct intel_execution_engine2 gem_eb_flags_to_engine(unsigned int flags)
+{
+	const unsigned int ring = flags & (I915_EXEC_RING_MASK | 3 << 13);
+	struct intel_execution_engine2 e2__ = {
+		.class = -1,
+		.instance = -1,
+		.flags = -1,
+		.name = "invalid"
+	};
+
+	if (ring == I915_EXEC_DEFAULT) {
+		e2__.flags = I915_EXEC_DEFAULT;
+		e2__.name = "default";
+	} else {
+		const struct intel_execution_engine2 *e2;
+
+		__for_each_static_engine(e2) {
+			if (e2->flags == ring)
+				return *e2;
+		}
+	}
+
+	return e2__;
+}
+
+bool gem_context_has_engine_map(int fd, uint32_t ctx)
+{
+	struct drm_i915_gem_context_param param = {
+		.param = I915_CONTEXT_PARAM_ENGINES,
+		.ctx_id = ctx
+	};
+
+	/*
+	 * If the kernel is too old to support PARAM_ENGINES,
+	 * then naturally the context has no engine map.
+	 */
+	if (__gem_context_get_param(fd, &param))
+		return false;
+
+	return param.size;
+}
+
+bool gem_engine_is_equal(const struct intel_execution_engine2 *e1,
+			 const struct intel_execution_engine2 *e2)
+{
+	return e1->class == e2->class && e1->instance == e2->instance;
+}
diff --git a/lib/i915/gem_engine_topology.h b/lib/i915/gem_engine_topology.h
index 2415fd1..d98773e 100644
--- a/lib/i915/gem_engine_topology.h
+++ b/lib/i915/gem_engine_topology.h
@@ -53,6 +53,13 @@
 
 void gem_context_set_all_engines(int fd, uint32_t ctx);
 
+bool gem_context_has_engine_map(int fd, uint32_t ctx);
+
+bool gem_engine_is_equal(const struct intel_execution_engine2 *e1,
+			 const struct intel_execution_engine2 *e2);
+
+struct intel_execution_engine2 gem_eb_flags_to_engine(unsigned int flags);
+
 #define __for_each_static_engine(e__) \
 	for ((e__) = intel_execution_engines2; (e__)->name; (e__)++)
 
diff --git a/lib/i915/gem_submission.c b/lib/i915/gem_submission.c
index 2fd460d..a8bb45c 100644
--- a/lib/i915/gem_submission.c
+++ b/lib/i915/gem_submission.c
@@ -28,6 +28,8 @@
 
 #include <i915_drm.h>
 
+#include "i915/gem_engine_topology.h"
+
 #include "igt_core.h"
 #include "igt_gt.h"
 #include "igt_sysfs.h"
@@ -215,8 +217,10 @@
 	gem_write(i915, obj.handle, 0, &bbe, sizeof(bbe));
 
 	if (engine == ALL_ENGINES) {
-		for_each_physical_engine(i915, engine) {
-			execbuf.flags = engine;
+		const struct intel_execution_engine2 *e2;
+
+		__for_each_physical_engine(i915, e2) {
+			execbuf.flags = e2->flags;
 			gem_execbuf(i915, &execbuf);
 		}
 	} else {
diff --git a/lib/i915_pciids.h b/lib/i915_pciids.h
index c7cdbfc..a70c982 100644
--- a/lib/i915_pciids.h
+++ b/lib/i915_pciids.h
@@ -108,8 +108,10 @@
 	INTEL_VGA_DEVICE(0x2e42, info), /* B43_G */ \
 	INTEL_VGA_DEVICE(0x2e92, info)	/* B43_G.1 */
 
-#define INTEL_PINEVIEW_IDS(info)			\
-	INTEL_VGA_DEVICE(0xa001, info),			\
+#define INTEL_PINEVIEW_G_IDS(info) \
+	INTEL_VGA_DEVICE(0xa001, info)
+
+#define INTEL_PINEVIEW_M_IDS(info) \
 	INTEL_VGA_DEVICE(0xa011, info)
 
 #define INTEL_IRONLAKE_D_IDS(info) \
@@ -166,7 +168,18 @@
 #define INTEL_IVB_Q_IDS(info) \
 	INTEL_QUANTA_VGA_DEVICE(info) /* Quanta transcode */
 
+#define INTEL_HSW_ULT_GT1_IDS(info) \
+	INTEL_VGA_DEVICE(0x0A02, info), /* ULT GT1 desktop */ \
+	INTEL_VGA_DEVICE(0x0A0A, info), /* ULT GT1 server */ \
+	INTEL_VGA_DEVICE(0x0A0B, info), /* ULT GT1 reserved */ \
+	INTEL_VGA_DEVICE(0x0A06, info)  /* ULT GT1 mobile */
+
+#define INTEL_HSW_ULX_GT1_IDS(info) \
+	INTEL_VGA_DEVICE(0x0A0E, info) /* ULX GT1 mobile */
+
 #define INTEL_HSW_GT1_IDS(info) \
+	INTEL_HSW_ULT_GT1_IDS(info), \
+	INTEL_HSW_ULX_GT1_IDS(info), \
 	INTEL_VGA_DEVICE(0x0402, info), /* GT1 desktop */ \
 	INTEL_VGA_DEVICE(0x040a, info), /* GT1 server */ \
 	INTEL_VGA_DEVICE(0x040B, info), /* GT1 reserved */ \
@@ -175,20 +188,26 @@
 	INTEL_VGA_DEVICE(0x0C0A, info), /* SDV GT1 server */ \
 	INTEL_VGA_DEVICE(0x0C0B, info), /* SDV GT1 reserved */ \
 	INTEL_VGA_DEVICE(0x0C0E, info), /* SDV GT1 reserved */ \
-	INTEL_VGA_DEVICE(0x0A02, info), /* ULT GT1 desktop */ \
-	INTEL_VGA_DEVICE(0x0A0A, info), /* ULT GT1 server */ \
-	INTEL_VGA_DEVICE(0x0A0B, info), /* ULT GT1 reserved */ \
 	INTEL_VGA_DEVICE(0x0D02, info), /* CRW GT1 desktop */ \
 	INTEL_VGA_DEVICE(0x0D0A, info), /* CRW GT1 server */ \
 	INTEL_VGA_DEVICE(0x0D0B, info), /* CRW GT1 reserved */ \
 	INTEL_VGA_DEVICE(0x0D0E, info), /* CRW GT1 reserved */ \
 	INTEL_VGA_DEVICE(0x0406, info), /* GT1 mobile */ \
 	INTEL_VGA_DEVICE(0x0C06, info), /* SDV GT1 mobile */ \
-	INTEL_VGA_DEVICE(0x0A06, info), /* ULT GT1 mobile */ \
-	INTEL_VGA_DEVICE(0x0A0E, info), /* ULX GT1 mobile */ \
 	INTEL_VGA_DEVICE(0x0D06, info)  /* CRW GT1 mobile */
 
+#define INTEL_HSW_ULT_GT2_IDS(info) \
+	INTEL_VGA_DEVICE(0x0A12, info), /* ULT GT2 desktop */ \
+	INTEL_VGA_DEVICE(0x0A1A, info), /* ULT GT2 server */ \
+	INTEL_VGA_DEVICE(0x0A1B, info), /* ULT GT2 reserved */ \
+	INTEL_VGA_DEVICE(0x0A16, info)  /* ULT GT2 mobile */
+
+#define INTEL_HSW_ULX_GT2_IDS(info) \
+	INTEL_VGA_DEVICE(0x0A1E, info) /* ULX GT2 mobile */ \
+
 #define INTEL_HSW_GT2_IDS(info) \
+	INTEL_HSW_ULT_GT2_IDS(info), \
+	INTEL_HSW_ULX_GT2_IDS(info), \
 	INTEL_VGA_DEVICE(0x0412, info), /* GT2 desktop */ \
 	INTEL_VGA_DEVICE(0x041a, info), /* GT2 server */ \
 	INTEL_VGA_DEVICE(0x041B, info), /* GT2 reserved */ \
@@ -197,9 +216,6 @@
 	INTEL_VGA_DEVICE(0x0C1A, info), /* SDV GT2 server */ \
 	INTEL_VGA_DEVICE(0x0C1B, info), /* SDV GT2 reserved */ \
 	INTEL_VGA_DEVICE(0x0C1E, info), /* SDV GT2 reserved */ \
-	INTEL_VGA_DEVICE(0x0A12, info), /* ULT GT2 desktop */ \
-	INTEL_VGA_DEVICE(0x0A1A, info), /* ULT GT2 server */ \
-	INTEL_VGA_DEVICE(0x0A1B, info), /* ULT GT2 reserved */ \
 	INTEL_VGA_DEVICE(0x0D12, info), /* CRW GT2 desktop */ \
 	INTEL_VGA_DEVICE(0x0D1A, info), /* CRW GT2 server */ \
 	INTEL_VGA_DEVICE(0x0D1B, info), /* CRW GT2 reserved */ \
@@ -207,11 +223,17 @@
 	INTEL_VGA_DEVICE(0x0416, info), /* GT2 mobile */ \
 	INTEL_VGA_DEVICE(0x0426, info), /* GT2 mobile */ \
 	INTEL_VGA_DEVICE(0x0C16, info), /* SDV GT2 mobile */ \
-	INTEL_VGA_DEVICE(0x0A16, info), /* ULT GT2 mobile */ \
-	INTEL_VGA_DEVICE(0x0A1E, info), /* ULX GT2 mobile */ \
 	INTEL_VGA_DEVICE(0x0D16, info)  /* CRW GT2 mobile */
 
+#define INTEL_HSW_ULT_GT3_IDS(info) \
+	INTEL_VGA_DEVICE(0x0A22, info), /* ULT GT3 desktop */ \
+	INTEL_VGA_DEVICE(0x0A2A, info), /* ULT GT3 server */ \
+	INTEL_VGA_DEVICE(0x0A2B, info), /* ULT GT3 reserved */ \
+	INTEL_VGA_DEVICE(0x0A26, info), /* ULT GT3 mobile */ \
+	INTEL_VGA_DEVICE(0x0A2E, info)  /* ULT GT3 reserved */
+
 #define INTEL_HSW_GT3_IDS(info) \
+	INTEL_HSW_ULT_GT3_IDS(info), \
 	INTEL_VGA_DEVICE(0x0422, info), /* GT3 desktop */ \
 	INTEL_VGA_DEVICE(0x042a, info), /* GT3 server */ \
 	INTEL_VGA_DEVICE(0x042B, info), /* GT3 reserved */ \
@@ -220,16 +242,11 @@
 	INTEL_VGA_DEVICE(0x0C2A, info), /* SDV GT3 server */ \
 	INTEL_VGA_DEVICE(0x0C2B, info), /* SDV GT3 reserved */ \
 	INTEL_VGA_DEVICE(0x0C2E, info), /* SDV GT3 reserved */ \
-	INTEL_VGA_DEVICE(0x0A22, info), /* ULT GT3 desktop */ \
-	INTEL_VGA_DEVICE(0x0A2A, info), /* ULT GT3 server */ \
-	INTEL_VGA_DEVICE(0x0A2B, info), /* ULT GT3 reserved */ \
 	INTEL_VGA_DEVICE(0x0D22, info), /* CRW GT3 desktop */ \
 	INTEL_VGA_DEVICE(0x0D2A, info), /* CRW GT3 server */ \
 	INTEL_VGA_DEVICE(0x0D2B, info), /* CRW GT3 reserved */ \
 	INTEL_VGA_DEVICE(0x0D2E, info), /* CRW GT3 reserved */ \
 	INTEL_VGA_DEVICE(0x0C26, info), /* SDV GT3 mobile */ \
-	INTEL_VGA_DEVICE(0x0A26, info), /* ULT GT3 mobile */ \
-	INTEL_VGA_DEVICE(0x0A2E, info), /* ULT GT3 reserved */ \
 	INTEL_VGA_DEVICE(0x0D26, info)  /* CRW GT3 mobile */
 
 #define INTEL_HSW_IDS(info) \
@@ -245,35 +262,59 @@
 	INTEL_VGA_DEVICE(0x0157, info), \
 	INTEL_VGA_DEVICE(0x0155, info)
 
-#define INTEL_BDW_GT1_IDS(info)  \
-	INTEL_VGA_DEVICE(0x1602, info), /* GT1 ULT */ \
+#define INTEL_BDW_ULT_GT1_IDS(info) \
 	INTEL_VGA_DEVICE(0x1606, info), /* GT1 ULT */ \
-	INTEL_VGA_DEVICE(0x160B, info), /* GT1 Iris */ \
-	INTEL_VGA_DEVICE(0x160E, info), /* GT1 ULX */ \
+	INTEL_VGA_DEVICE(0x160B, info)  /* GT1 Iris */
+
+#define INTEL_BDW_ULX_GT1_IDS(info) \
+	INTEL_VGA_DEVICE(0x160E, info) /* GT1 ULX */
+
+#define INTEL_BDW_GT1_IDS(info) \
+	INTEL_BDW_ULT_GT1_IDS(info), \
+	INTEL_BDW_ULX_GT1_IDS(info), \
+	INTEL_VGA_DEVICE(0x1602, info), /* GT1 ULT */ \
 	INTEL_VGA_DEVICE(0x160A, info), /* GT1 Server */ \
 	INTEL_VGA_DEVICE(0x160D, info)  /* GT1 Workstation */
 
-#define INTEL_BDW_GT2_IDS(info)  \
-	INTEL_VGA_DEVICE(0x1612, info), /* GT2 Halo */	\
+#define INTEL_BDW_ULT_GT2_IDS(info) \
 	INTEL_VGA_DEVICE(0x1616, info), /* GT2 ULT */ \
-	INTEL_VGA_DEVICE(0x161B, info), /* GT2 ULT */ \
-	INTEL_VGA_DEVICE(0x161E, info), /* GT2 ULX */ \
+	INTEL_VGA_DEVICE(0x161B, info)  /* GT2 ULT */
+
+#define INTEL_BDW_ULX_GT2_IDS(info) \
+	INTEL_VGA_DEVICE(0x161E, info) /* GT2 ULX */
+
+#define INTEL_BDW_GT2_IDS(info) \
+	INTEL_BDW_ULT_GT2_IDS(info), \
+	INTEL_BDW_ULX_GT2_IDS(info), \
+	INTEL_VGA_DEVICE(0x1612, info), /* GT2 Halo */	\
 	INTEL_VGA_DEVICE(0x161A, info), /* GT2 Server */ \
 	INTEL_VGA_DEVICE(0x161D, info)  /* GT2 Workstation */
 
-#define INTEL_BDW_GT3_IDS(info) \
-	INTEL_VGA_DEVICE(0x1622, info), /* ULT */ \
+#define INTEL_BDW_ULT_GT3_IDS(info) \
 	INTEL_VGA_DEVICE(0x1626, info), /* ULT */ \
-	INTEL_VGA_DEVICE(0x162B, info), /* Iris */ \
-	INTEL_VGA_DEVICE(0x162E, info),  /* ULX */\
+	INTEL_VGA_DEVICE(0x162B, info)  /* Iris */ \
+
+#define INTEL_BDW_ULX_GT3_IDS(info) \
+	INTEL_VGA_DEVICE(0x162E, info)  /* ULX */
+
+#define INTEL_BDW_GT3_IDS(info) \
+	INTEL_BDW_ULT_GT3_IDS(info), \
+	INTEL_BDW_ULX_GT3_IDS(info), \
+	INTEL_VGA_DEVICE(0x1622, info), /* ULT */ \
 	INTEL_VGA_DEVICE(0x162A, info), /* Server */ \
 	INTEL_VGA_DEVICE(0x162D, info)  /* Workstation */
 
-#define INTEL_BDW_RSVD_IDS(info) \
-	INTEL_VGA_DEVICE(0x1632, info), /* ULT */ \
+#define INTEL_BDW_ULT_RSVD_IDS(info) \
 	INTEL_VGA_DEVICE(0x1636, info), /* ULT */ \
-	INTEL_VGA_DEVICE(0x163B, info), /* Iris */ \
-	INTEL_VGA_DEVICE(0x163E, info), /* ULX */ \
+	INTEL_VGA_DEVICE(0x163B, info)  /* Iris */
+
+#define INTEL_BDW_ULX_RSVD_IDS(info) \
+	INTEL_VGA_DEVICE(0x163E, info) /* ULX */
+
+#define INTEL_BDW_RSVD_IDS(info) \
+	INTEL_BDW_ULT_RSVD_IDS(info), \
+	INTEL_BDW_ULX_RSVD_IDS(info), \
+	INTEL_VGA_DEVICE(0x1632, info), /* ULT */ \
 	INTEL_VGA_DEVICE(0x163A, info), /* Server */ \
 	INTEL_VGA_DEVICE(0x163D, info)  /* Workstation */
 
@@ -289,25 +330,40 @@
 	INTEL_VGA_DEVICE(0x22b2, info), \
 	INTEL_VGA_DEVICE(0x22b3, info)
 
+#define INTEL_SKL_ULT_GT1_IDS(info) \
+	INTEL_VGA_DEVICE(0x1906, info) /* ULT GT1 */
+
+#define INTEL_SKL_ULX_GT1_IDS(info) \
+	INTEL_VGA_DEVICE(0x190E, info) /* ULX GT1 */
+
 #define INTEL_SKL_GT1_IDS(info)	\
-	INTEL_VGA_DEVICE(0x1906, info), /* ULT GT1 */ \
-	INTEL_VGA_DEVICE(0x190E, info), /* ULX GT1 */ \
+	INTEL_SKL_ULT_GT1_IDS(info), \
+	INTEL_SKL_ULX_GT1_IDS(info), \
 	INTEL_VGA_DEVICE(0x1902, info), /* DT  GT1 */ \
 	INTEL_VGA_DEVICE(0x190B, info), /* Halo GT1 */ \
 	INTEL_VGA_DEVICE(0x190A, info) /* SRV GT1 */
 
-#define INTEL_SKL_GT2_IDS(info)	\
+#define INTEL_SKL_ULT_GT2_IDS(info) \
 	INTEL_VGA_DEVICE(0x1916, info), /* ULT GT2 */ \
-	INTEL_VGA_DEVICE(0x1921, info), /* ULT GT2F */ \
-	INTEL_VGA_DEVICE(0x191E, info), /* ULX GT2 */ \
+	INTEL_VGA_DEVICE(0x1921, info)  /* ULT GT2F */
+
+#define INTEL_SKL_ULX_GT2_IDS(info) \
+	INTEL_VGA_DEVICE(0x191E, info) /* ULX GT2 */
+
+#define INTEL_SKL_GT2_IDS(info)	\
+	INTEL_SKL_ULT_GT2_IDS(info), \
+	INTEL_SKL_ULX_GT2_IDS(info), \
 	INTEL_VGA_DEVICE(0x1912, info), /* DT  GT2 */ \
 	INTEL_VGA_DEVICE(0x191B, info), /* Halo GT2 */ \
 	INTEL_VGA_DEVICE(0x191A, info), /* SRV GT2 */ \
 	INTEL_VGA_DEVICE(0x191D, info)  /* WKS GT2 */
 
+#define INTEL_SKL_ULT_GT3_IDS(info) \
+	INTEL_VGA_DEVICE(0x1926, info) /* ULT GT3 */
+
 #define INTEL_SKL_GT3_IDS(info) \
+	INTEL_SKL_ULT_GT3_IDS(info), \
 	INTEL_VGA_DEVICE(0x1923, info), /* ULT GT3 */ \
-	INTEL_VGA_DEVICE(0x1926, info), /* ULT GT3 */ \
 	INTEL_VGA_DEVICE(0x1927, info), /* ULT GT3 */ \
 	INTEL_VGA_DEVICE(0x192B, info), /* Halo GT3 */ \
 	INTEL_VGA_DEVICE(0x192D, info)  /* SRV GT3 */
@@ -336,29 +392,44 @@
 	INTEL_VGA_DEVICE(0x3184, info), \
 	INTEL_VGA_DEVICE(0x3185, info)
 
-#define INTEL_KBL_GT1_IDS(info)	\
-	INTEL_VGA_DEVICE(0x5913, info), /* ULT GT1.5 */ \
-	INTEL_VGA_DEVICE(0x5915, info), /* ULX GT1.5 */ \
+#define INTEL_KBL_ULT_GT1_IDS(info) \
 	INTEL_VGA_DEVICE(0x5906, info), /* ULT GT1 */ \
+	INTEL_VGA_DEVICE(0x5913, info)  /* ULT GT1.5 */
+
+#define INTEL_KBL_ULX_GT1_IDS(info) \
 	INTEL_VGA_DEVICE(0x590E, info), /* ULX GT1 */ \
+	INTEL_VGA_DEVICE(0x5915, info)  /* ULX GT1.5 */
+
+#define INTEL_KBL_GT1_IDS(info)	\
+	INTEL_KBL_ULT_GT1_IDS(info), \
+	INTEL_KBL_ULX_GT1_IDS(info), \
 	INTEL_VGA_DEVICE(0x5902, info), /* DT  GT1 */ \
 	INTEL_VGA_DEVICE(0x5908, info), /* Halo GT1 */ \
 	INTEL_VGA_DEVICE(0x590B, info), /* Halo GT1 */ \
 	INTEL_VGA_DEVICE(0x590A, info) /* SRV GT1 */
 
-#define INTEL_KBL_GT2_IDS(info)	\
+#define INTEL_KBL_ULT_GT2_IDS(info) \
 	INTEL_VGA_DEVICE(0x5916, info), /* ULT GT2 */ \
+	INTEL_VGA_DEVICE(0x5921, info)  /* ULT GT2F */
+
+#define INTEL_KBL_ULX_GT2_IDS(info) \
+	INTEL_VGA_DEVICE(0x591E, info)  /* ULX GT2 */
+
+#define INTEL_KBL_GT2_IDS(info)	\
+	INTEL_KBL_ULT_GT2_IDS(info), \
+	INTEL_KBL_ULX_GT2_IDS(info), \
 	INTEL_VGA_DEVICE(0x5917, info), /* Mobile GT2 */ \
-	INTEL_VGA_DEVICE(0x5921, info), /* ULT GT2F */ \
-	INTEL_VGA_DEVICE(0x591E, info), /* ULX GT2 */ \
 	INTEL_VGA_DEVICE(0x5912, info), /* DT  GT2 */ \
 	INTEL_VGA_DEVICE(0x591B, info), /* Halo GT2 */ \
 	INTEL_VGA_DEVICE(0x591A, info), /* SRV GT2 */ \
 	INTEL_VGA_DEVICE(0x591D, info) /* WKS GT2 */
 
+#define INTEL_KBL_ULT_GT3_IDS(info) \
+	INTEL_VGA_DEVICE(0x5926, info) /* ULT GT3 */
+
 #define INTEL_KBL_GT3_IDS(info) \
+	INTEL_KBL_ULT_GT3_IDS(info), \
 	INTEL_VGA_DEVICE(0x5923, info), /* ULT GT3 */ \
-	INTEL_VGA_DEVICE(0x5926, info), /* ULT GT3 */ \
 	INTEL_VGA_DEVICE(0x5927, info) /* ULT GT3 */
 
 #define INTEL_KBL_GT4_IDS(info) \
@@ -465,7 +536,14 @@
 	INTEL_CML_GT2_IDS(info)
 
 /* CNL */
+#define INTEL_CNL_PORT_F_IDS(info) \
+	INTEL_VGA_DEVICE(0x5A54, info), \
+	INTEL_VGA_DEVICE(0x5A5C, info), \
+	INTEL_VGA_DEVICE(0x5A44, info), \
+	INTEL_VGA_DEVICE(0x5A4C, info)
+
 #define INTEL_CNL_IDS(info) \
+	INTEL_CNL_PORT_F_IDS(info), \
 	INTEL_VGA_DEVICE(0x5A51, info), \
 	INTEL_VGA_DEVICE(0x5A59, info), \
 	INTEL_VGA_DEVICE(0x5A41, info), \
@@ -475,18 +553,12 @@
 	INTEL_VGA_DEVICE(0x5A42, info), \
 	INTEL_VGA_DEVICE(0x5A4A, info), \
 	INTEL_VGA_DEVICE(0x5A50, info), \
-	INTEL_VGA_DEVICE(0x5A40, info), \
-	INTEL_VGA_DEVICE(0x5A54, info), \
-	INTEL_VGA_DEVICE(0x5A5C, info), \
-	INTEL_VGA_DEVICE(0x5A44, info), \
-	INTEL_VGA_DEVICE(0x5A4C, info)
+	INTEL_VGA_DEVICE(0x5A40, info)
 
 /* ICL */
-#define INTEL_ICL_11_IDS(info) \
+#define INTEL_ICL_PORT_F_IDS(info) \
 	INTEL_VGA_DEVICE(0x8A50, info), \
-	INTEL_VGA_DEVICE(0x8A51, info), \
 	INTEL_VGA_DEVICE(0x8A5C, info), \
-	INTEL_VGA_DEVICE(0x8A5D, info), \
 	INTEL_VGA_DEVICE(0x8A59, info),	\
 	INTEL_VGA_DEVICE(0x8A58, info),	\
 	INTEL_VGA_DEVICE(0x8A52, info), \
@@ -496,7 +568,13 @@
 	INTEL_VGA_DEVICE(0x8A56, info), \
 	INTEL_VGA_DEVICE(0x8A71, info), \
 	INTEL_VGA_DEVICE(0x8A70, info), \
-	INTEL_VGA_DEVICE(0x8A53, info)
+	INTEL_VGA_DEVICE(0x8A53, info), \
+	INTEL_VGA_DEVICE(0x8A54, info)
+
+#define INTEL_ICL_11_IDS(info) \
+	INTEL_ICL_PORT_F_IDS(info), \
+	INTEL_VGA_DEVICE(0x8A51, info), \
+	INTEL_VGA_DEVICE(0x8A5D, info)
 
 /* EHL */
 #define INTEL_EHL_IDS(info) \
@@ -505,4 +583,14 @@
 	INTEL_VGA_DEVICE(0x4551, info), \
 	INTEL_VGA_DEVICE(0x4541, info)
 
+/* TGL */
+#define INTEL_TGL_12_IDS(info) \
+	INTEL_VGA_DEVICE(0x9A49, info), \
+	INTEL_VGA_DEVICE(0x9A40, info), \
+	INTEL_VGA_DEVICE(0x9A59, info), \
+	INTEL_VGA_DEVICE(0x9A60, info), \
+	INTEL_VGA_DEVICE(0x9A68, info), \
+	INTEL_VGA_DEVICE(0x9A70, info), \
+	INTEL_VGA_DEVICE(0x9A78, info)
+
 #endif /* _I915_PCIIDS_H */
diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c
index b83ff39..301e9d2 100644
--- a/lib/igt_chamelium.c
+++ b/lib/igt_chamelium.c
@@ -28,6 +28,7 @@
 
 #include <string.h>
 #include <errno.h>
+#include <math.h>
 #include <xmlrpc-c/base.h>
 #include <xmlrpc-c/client.h>
 #include <pthread.h>
@@ -82,7 +83,10 @@
  */
 
 struct chamelium_edid {
-	int id;
+	struct chamelium *chamelium;
+	struct edid *base;
+	struct edid *raw[CHAMELIUM_MAX_PORTS];
+	int ids[CHAMELIUM_MAX_PORTS];
 	struct igt_list link;
 };
 
@@ -119,7 +123,7 @@
 	int drm_fd;
 
 	struct igt_list edids;
-	struct chamelium_port *ports;
+	struct chamelium_port ports[CHAMELIUM_MAX_PORTS];
 	int port_count;
 };
 
@@ -357,7 +361,7 @@
  */
 void chamelium_plug(struct chamelium *chamelium, struct chamelium_port *port)
 {
-	igt_debug("Plugging %s\n", port->name);
+	igt_debug("Plugging %s (Chamelium port ID %d)\n", port->name, port->id);
 	xmlrpc_DECREF(chamelium_rpc(chamelium, NULL, "Plug", "(i)", port->id));
 }
 
@@ -522,38 +526,18 @@
 				    "(iii)", port->id, delay_ms, rising_edge));
 }
 
-/**
- * chamelium_new_edid:
- * @chamelium: The Chamelium instance to use
- * @edid: The edid blob to upload to the chamelium
- *
- * Uploads and registers a new EDID with the chamelium. The EDID will be
- * destroyed automatically when #chamelium_deinit is called.
- *
- * Returns: An opaque pointer to the Chamelium EDID
- */
-struct chamelium_edid *chamelium_new_edid(struct chamelium *chamelium,
-					  const unsigned char *raw_edid)
+static int chamelium_upload_edid(struct chamelium *chamelium,
+				 const struct edid *edid)
 {
 	xmlrpc_value *res;
-	struct chamelium_edid *chamelium_edid;
 	int edid_id;
-	struct edid *edid = (struct edid *) raw_edid;
-	size_t edid_size = sizeof(struct edid) +
-			   edid->extensions_len * sizeof(struct edid_ext);
 
 	res = chamelium_rpc(chamelium, NULL, "CreateEdid", "(6)",
-			    raw_edid, edid_size);
-
+			    edid, edid_get_size(edid));
 	xmlrpc_read_int(&chamelium->env, res, &edid_id);
 	xmlrpc_DECREF(res);
 
-	chamelium_edid = calloc(1, sizeof(struct chamelium_edid));
-	chamelium_edid->id = edid_id;
-
-	igt_list_add(&chamelium_edid->link, &chamelium->edids);
-
-	return chamelium_edid;
+	return edid_id;
 }
 
 static void chamelium_destroy_edid(struct chamelium *chamelium, int edid_id)
@@ -563,24 +547,118 @@
 }
 
 /**
+ * chamelium_new_edid:
+ * @chamelium: The Chamelium instance to use
+ * @edid: The edid blob to upload to the chamelium
+ *
+ * Uploads and registers a new EDID with the chamelium. The EDID will be
+ * destroyed automatically when #chamelium_deinit is called.
+ *
+ * Callers shouldn't assume that the raw EDID they provide is uploaded as-is to
+ * the Chamelium. The EDID may be mutated (e.g. a serial number can be appended
+ * to be able to uniquely identify the EDID). To retrieve the exact EDID that
+ * will be applied to a particular port, use #chamelium_edid_get_raw.
+ *
+ * Returns: An opaque pointer to the Chamelium EDID
+ */
+struct chamelium_edid *chamelium_new_edid(struct chamelium *chamelium,
+					  const unsigned char *raw_edid)
+{
+	struct chamelium_edid *chamelium_edid;
+	const struct edid *edid = (struct edid *) raw_edid;
+	size_t edid_size = edid_get_size(edid);
+
+	chamelium_edid = calloc(1, sizeof(struct chamelium_edid));
+	chamelium_edid->chamelium = chamelium;
+	chamelium_edid->base = malloc(edid_size);
+	memcpy(chamelium_edid->base, edid, edid_size);
+	igt_list_add(&chamelium_edid->link, &chamelium->edids);
+
+	return chamelium_edid;
+}
+
+/**
+ * chamelium_port_tag_edid: tag the EDID with the provided Chamelium port.
+ */
+static void chamelium_port_tag_edid(struct chamelium_port *port,
+				    struct edid *edid)
+{
+	uint32_t *serial;
+
+	/* Product code: Chamelium */
+	edid->prod_code[0] = 'C';
+	edid->prod_code[1] = 'H';
+
+	/* Serial: Chamelium port ID */
+	serial = (uint32_t *) &edid->serial;
+	*serial = port->id;
+
+	edid_update_checksum(edid);
+}
+
+/**
+ * chamelium_edid_get_raw: get the raw EDID
+ * @edid: the Chamelium EDID
+ * @port: the Chamelium port
+ *
+ * The EDID provided to #chamelium_new_edid may be mutated for identification
+ * purposes. This function allows to retrieve the exact EDID that will be set
+ * for a given port.
+ *
+ * The returned raw EDID is only valid until the next call to this function.
+ */
+const struct edid *chamelium_edid_get_raw(struct chamelium_edid *edid,
+					  struct chamelium_port *port)
+{
+	size_t port_index = port - edid->chamelium->ports;
+	size_t edid_size;
+
+	if (!edid->raw[port_index]) {
+		edid_size = edid_get_size(edid->base);
+		edid->raw[port_index] = malloc(edid_size);
+		memcpy(edid->raw[port_index], edid->base, edid_size);
+		chamelium_port_tag_edid(port, edid->raw[port_index]);
+	}
+
+	return edid->raw[port_index];
+}
+
+/**
  * chamelium_port_set_edid:
  * @chamelium: The Chamelium instance to use
  * @port: The port on the Chamelium to set the EDID on
- * @edid: The Chamelium EDID to set
- * #chamelium_new_edid, or 0 to disable the EDID on the port
+ * @edid: The Chamelium EDID to set or NULL to use the default Chamelium EDID
  *
  * Sets a port on the chamelium to use the specified EDID. This does not fire a
  * hotplug pulse on it's own, and merely changes what EDID the chamelium port
  * will report to us the next time we probe it. Users will need to reprobe the
  * connectors themselves if they want to see the EDID reported by the port
  * change.
+ *
+ * To create an EDID, see #chamelium_new_edid.
  */
 void chamelium_port_set_edid(struct chamelium *chamelium,
 			     struct chamelium_port *port,
 			     struct chamelium_edid *edid)
 {
+	int edid_id;
+	size_t port_index;
+	const struct edid *raw_edid;
+
+	if (edid) {
+		port_index = port - chamelium->ports;
+		edid_id = edid->ids[port_index];
+		if (edid_id == 0) {
+			raw_edid = chamelium_edid_get_raw(edid, port);
+			edid_id = chamelium_upload_edid(chamelium, raw_edid);
+			edid->ids[port_index] = edid_id;
+		}
+	} else {
+		edid_id = 0;
+	}
+
 	xmlrpc_DECREF(chamelium_rpc(chamelium, NULL, "ApplyEdid", "(ii)",
-				    port->id, edid->id));
+				    port->id, edid_id));
 }
 
 /**
@@ -659,6 +737,90 @@
 	xmlrpc_DECREF(res);
 }
 
+/** chamelium_supports_method: checks if the Chamelium board supports a method.
+ *
+ * Note: this actually tries to call the method.
+ *
+ * See https://crbug.com/977995 for a discussion about a better solution.
+ */
+static bool chamelium_supports_method(struct chamelium *chamelium,
+				      const char *name)
+{
+	xmlrpc_value *res;
+
+	res = __chamelium_rpc(chamelium, NULL, name, "()");
+	if (res)
+		xmlrpc_DECREF(res);
+
+	/* XML-RPC has a special code for unsupported methods
+	 * (XMLRPC_NO_SUCH_METHOD_ERROR) however the Chamelium implementation
+	 * doesn't return it. */
+	return (!chamelium->env.fault_occurred ||
+		strstr(chamelium->env.fault_string, "not supported") == NULL);
+}
+
+bool chamelium_supports_get_video_params(struct chamelium *chamelium)
+{
+	return chamelium_supports_method(chamelium, "GetVideoParams");
+}
+
+static void read_int_from_xml_struct(struct chamelium *chamelium,
+				     xmlrpc_value *struct_val, const char *key,
+				     int *dst)
+{
+	xmlrpc_value *val = NULL;
+
+	xmlrpc_struct_find_value(&chamelium->env, struct_val, key, &val);
+	if (val) {
+		xmlrpc_read_int(&chamelium->env, val, dst);
+		xmlrpc_DECREF(val);
+	} else
+		*dst = -1;
+}
+
+static void video_params_from_xml(struct chamelium *chamelium,
+				  xmlrpc_value *res,
+				  struct chamelium_video_params *params)
+{
+	xmlrpc_value *val = NULL;
+
+	xmlrpc_struct_find_value(&chamelium->env, res, "clock", &val);
+	if (val) {
+		xmlrpc_read_double(&chamelium->env, val, &params->clock);
+		xmlrpc_DECREF(val);
+	} else
+		params->clock = NAN;
+
+	read_int_from_xml_struct(chamelium, res, "htotal", &params->htotal);
+	read_int_from_xml_struct(chamelium, res, "hactive", &params->hactive);
+	read_int_from_xml_struct(chamelium, res, "hsync_offset",
+				 &params->hsync_offset);
+	read_int_from_xml_struct(chamelium, res, "hsync_width",
+				 &params->hsync_width);
+	read_int_from_xml_struct(chamelium, res, "hsync_polarity",
+				 &params->hsync_polarity);
+	read_int_from_xml_struct(chamelium, res, "vtotal", &params->vtotal);
+	read_int_from_xml_struct(chamelium, res, "vactive", &params->vactive);
+	read_int_from_xml_struct(chamelium, res, "vsync_offset",
+				 &params->vsync_offset);
+	read_int_from_xml_struct(chamelium, res, "vsync_width",
+				 &params->vsync_width);
+	read_int_from_xml_struct(chamelium, res, "vsync_polarity",
+				 &params->vsync_polarity);
+}
+
+void chamelium_port_get_video_params(struct chamelium *chamelium,
+				     struct chamelium_port *port,
+				     struct chamelium_video_params *params)
+{
+	xmlrpc_value *res;
+
+	res = chamelium_rpc(chamelium, NULL, "GetVideoParams", "(i)", port->id);
+	video_params_from_xml(chamelium, res, params);
+
+	xmlrpc_DECREF(res);
+}
+
 static void chamelium_get_captured_resolution(struct chamelium *chamelium,
 					      int *w, int *h)
 {
@@ -962,32 +1124,13 @@
 	return ret;
 }
 
-/**
- * chamelium_supports_get_audio_format: check the Chamelium device supports
- * retrieving the capture audio format.
- */
-static bool chamelium_supports_get_audio_format(struct chamelium *chamelium)
-{
-	xmlrpc_value *res;
-
-	res = __chamelium_rpc(chamelium, NULL, "GetAudioFormat", "(i)", 3);
-	if (res)
-		xmlrpc_DECREF(res);
-
-	/* XML-RPC has a special code for unsupported methods
-	 * (XMLRPC_NO_SUCH_METHOD_ERROR) however the Chamelium implementation
-	 * doesn't return it. */
-	return (!chamelium->env.fault_occurred ||
-		strstr(chamelium->env.fault_string, "not supported") == NULL);
-}
-
 bool chamelium_has_audio_support(struct chamelium *chamelium,
 				 struct chamelium_port *port)
 {
 	xmlrpc_value *res;
 	xmlrpc_bool has_support;
 
-	if (!chamelium_supports_get_audio_format(chamelium)) {
+	if (!chamelium_supports_method(chamelium, "GetAudioFormat")) {
 		igt_debug("The Chamelium device doesn't support GetAudioFormat\n");
 		return false;
 	}
@@ -1682,6 +1825,50 @@
 	return port_type;
 }
 
+static bool chamelium_has_video_support(struct chamelium *chamelium,
+					int port_id)
+{
+	xmlrpc_value *res;
+	int has_video_support;
+
+	res = chamelium_rpc(chamelium, NULL, "HasVideoSupport", "(i)", port_id);
+	xmlrpc_read_bool(&chamelium->env, res, &has_video_support);
+	xmlrpc_DECREF(res);
+
+	return has_video_support;
+}
+
+/**
+ * chamelium_get_video_ports: retrieve a list of video port IDs
+ *
+ * Returns: the number of video port IDs
+ */
+static size_t chamelium_get_video_ports(struct chamelium *chamelium,
+					int port_ids[static CHAMELIUM_MAX_PORTS])
+{
+	xmlrpc_value *res, *res_port;
+	int res_len, i, port_id;
+	size_t port_ids_len = 0;
+
+	res = chamelium_rpc(chamelium, NULL, "GetSupportedInputs", "()");
+	res_len = xmlrpc_array_size(&chamelium->env, res);
+	for (i = 0; i < res_len; i++) {
+		xmlrpc_array_read_item(&chamelium->env, res, i, &res_port);
+		xmlrpc_read_int(&chamelium->env, res_port, &port_id);
+		xmlrpc_DECREF(res_port);
+
+		if (!chamelium_has_video_support(chamelium, port_id))
+			continue;
+
+		igt_assert(port_ids_len < CHAMELIUM_MAX_PORTS);
+		port_ids[port_ids_len] = port_id;
+		port_ids_len++;
+	}
+	xmlrpc_DECREF(res);
+
+	return port_ids_len;
+}
+
 static bool chamelium_read_port_mappings(struct chamelium *chamelium,
 					 int drm_fd)
 {
@@ -1705,11 +1892,9 @@
 		if (strstr(group_list[i], "Chamelium:"))
 			chamelium->port_count++;
 	}
+	igt_assert(chamelium->port_count <= CHAMELIUM_MAX_PORTS);
 
-	chamelium->ports = calloc(sizeof(struct chamelium_port),
-				  chamelium->port_count);
 	port_i = 0;
-
 	for (i = 0; group_list[i] != NULL; i++) {
 		group = group_list[i];
 
@@ -1775,6 +1960,212 @@
 	return ret;
 }
 
+static int port_id_from_edid(int drm_fd, drmModeConnector *connector)
+{
+	int port_id = -1;
+	bool ok;
+	uint64_t edid_blob_id;
+	drmModePropertyBlobRes *edid_blob;
+	const struct edid *edid;
+	char mfg[3];
+
+	if (connector->connection != DRM_MODE_CONNECTED) {
+		igt_debug("Skipping auto-discovery for connector %s-%d: "
+			  "connector status is not connected\n",
+			  kmstest_connector_type_str(connector->connector_type),
+			  connector->connector_type_id);
+		return -1;
+	}
+
+	ok = kmstest_get_property(drm_fd, connector->connector_id,
+				  DRM_MODE_OBJECT_CONNECTOR, "EDID",
+				  NULL, &edid_blob_id, NULL);
+	if (!ok || !edid_blob_id) {
+		igt_debug("Skipping auto-discovery for connector %s-%d: "
+			  "missing the EDID property\n",
+			  kmstest_connector_type_str(connector->connector_type),
+			  connector->connector_type_id);
+		return -1;
+	}
+
+	edid_blob = drmModeGetPropertyBlob(drm_fd, edid_blob_id);
+	igt_assert(edid_blob);
+
+	edid = (const struct edid *) edid_blob->data;
+
+	edid_get_mfg(edid, mfg);
+	if (memcmp(mfg, "IGT", 3) != 0) {
+		igt_debug("Skipping connector %s-%d for auto-discovery: "
+			  "manufacturer is %.3s, not IGT\n",
+			  kmstest_connector_type_str(connector->connector_type),
+			  connector->connector_type_id, mfg);
+		goto out;
+	}
+
+	if (edid->prod_code[0] != 'C' || edid->prod_code[1] != 'H') {
+		igt_warn("Invalid EDID for IGT connector %s-%d: "
+			  "invalid product code\n",
+			  kmstest_connector_type_str(connector->connector_type),
+			  connector->connector_type_id);
+		goto out;
+	}
+
+	port_id = *(uint32_t *) &edid->serial;
+	igt_debug("Auto-discovery mapped connector %s-%d to Chamelium "
+		  "port ID %d\n",
+		  kmstest_connector_type_str(connector->connector_type),
+		  connector->connector_type_id, port_id);
+
+out:
+	drmModeFreePropertyBlob(edid_blob);
+	return port_id;
+}
+
+/**
+ * chamelium_autodiscover: automagically discover the Chamelium port mapping
+ *
+ * The Chamelium API uses port IDs wheras the Device Under Test uses DRM
+ * connectors. We need to know which Chamelium port is plugged to a given DRM
+ * connector. This has typically been done via a configuration file in the
+ * past (see #chamelium_read_port_mappings), but this function provides an
+ * automatic way to do it.
+ *
+ * We will plug all Chamelium ports with a different EDID on each. Then we'll
+ * read the EDID on each DRM connector and infer the Chamelium port ID.
+ */
+static bool chamelium_autodiscover(struct chamelium *chamelium, int drm_fd)
+{
+	int candidate_ports[CHAMELIUM_MAX_PORTS];
+	size_t candidate_ports_len;
+	drmModeRes *res;
+	drmModeConnector *connector;
+	struct chamelium_port *port;
+	size_t i, j, port_count;
+	int port_id;
+	uint32_t conn_id;
+	struct chamelium_edid *edid;
+	bool found;
+	uint32_t discovered_conns[CHAMELIUM_MAX_PORTS] = {0};
+	char conn_name[64];
+	struct timespec start;
+	uint64_t elapsed_ns;
+
+	candidate_ports_len = chamelium_get_video_ports(chamelium,
+							candidate_ports);
+
+	igt_debug("Starting Chamelium port auto-discovery on %zu ports\n",
+		  candidate_ports_len);
+	igt_gettime(&start);
+
+	edid = chamelium_new_edid(chamelium, igt_kms_get_base_edid());
+
+	/* Set EDID and plug ports we want to auto-discover */
+	port_count = chamelium->port_count;
+	for (i = 0; i < candidate_ports_len; i++) {
+		port_id = candidate_ports[i];
+
+		/* Get or add a chamelium_port slot */
+		port = NULL;
+		for (j = 0; j < chamelium->port_count; j++) {
+			if (chamelium->ports[j].id == port_id) {
+				port = &chamelium->ports[j];
+				break;
+			}
+		}
+		if (!port) {
+			igt_assert(port_count < CHAMELIUM_MAX_PORTS);
+			port = &chamelium->ports[port_count];
+			port_count++;
+
+			port->id = port_id;
+		}
+
+		chamelium_port_set_edid(chamelium, port, edid);
+		chamelium_plug(chamelium, port);
+	}
+
+	/* Reprobe connectors and build the mapping */
+	res = drmModeGetResources(drm_fd);
+	if (!res)
+		return false;
+
+	for (i = 0; i < res->count_connectors; i++) {
+		conn_id = res->connectors[i];
+
+		/* Read the EDID and parse the Chamelium port ID we stored
+		 * there. */
+		connector = drmModeGetConnector(drm_fd, res->connectors[i]);
+		port_id = port_id_from_edid(drm_fd, connector);
+		drmModeFreeConnector(connector);
+		if (port_id < 0)
+			continue;
+
+		/* If we already have a mapping from the config file, check
+		 * that it's consistent. */
+		found = false;
+		for (j = 0; j < chamelium->port_count; j++) {
+			port = &chamelium->ports[j];
+			if (port->connector_id == conn_id) {
+				found = true;
+				igt_assert_f(port->id == port_id,
+					     "Inconsistency detected in .igtrc: "
+					     "connector %s is configured with "
+					     "Chamelium port %d, but is "
+					     "connected to port %d\n",
+					     port->name, port->id, port_id);
+				break;
+			}
+		}
+		if (found)
+			continue;
+
+		/* We got a new mapping */
+		found = false;
+		for (j = 0; j < candidate_ports_len; j++) {
+			if (port_id == candidate_ports[j]) {
+				found = true;
+				discovered_conns[j] = conn_id;
+				break;
+			}
+		}
+		igt_assert_f(found, "Auto-discovered a port (%d) we haven't "
+			     "setup\n", port_id);
+	}
+
+	drmModeFreeResources(res);
+
+	/* We now have a Chamelium port ID ↔ DRM connector ID mapping:
+	 * candidate_ports contains the Chamelium port IDs and
+	 * discovered_conns contains the DRM connector IDs. */
+	for (i = 0; i < candidate_ports_len; i++) {
+		port_id = candidate_ports[i];
+		conn_id = discovered_conns[i];
+		if (!conn_id) {
+			continue;
+		}
+
+		port = &chamelium->ports[chamelium->port_count];
+		chamelium->port_count++;
+
+		port->id = port_id;
+		port->type = chamelium_get_port_type(chamelium, port);
+		port->connector_id = conn_id;
+
+		connector = drmModeGetConnectorCurrent(drm_fd, conn_id);
+		snprintf(conn_name, sizeof(conn_name), "%s-%u",
+			 kmstest_connector_type_str(connector->connector_type),
+			 connector->connector_type_id);
+		drmModeFreeConnector(connector);
+		port->name = strdup(conn_name);
+	}
+
+	elapsed_ns = igt_nsec_elapsed(&start);
+	igt_debug("Auto-discovery took %fms\n",
+		  (float) elapsed_ns / (1000 * 1000));
+
+	return true;
+}
+
 static bool chamelium_read_config(struct chamelium *chamelium, int drm_fd)
 {
 	GError *error = NULL;
@@ -1792,7 +2183,10 @@
 		return false;
 	}
 
-	return chamelium_read_port_mappings(chamelium, drm_fd);
+	if (!chamelium_read_port_mappings(chamelium, drm_fd)) {
+		return false;
+	}
+	return chamelium_autodiscover(chamelium, drm_fd);
 }
 
 /**
@@ -1898,7 +2292,12 @@
 
 	/* Destroy any EDIDs we created to make sure we don't leak them */
 	igt_list_for_each_safe(pos, tmp, &chamelium->edids, link) {
-		chamelium_destroy_edid(chamelium, pos->id);
+		for (i = 0; i < CHAMELIUM_MAX_PORTS; i++) {
+			if (pos->ids[i])
+				chamelium_destroy_edid(chamelium, pos->ids[i]);
+			free(pos->raw[i]);
+		}
+		free(pos->base);
 		free(pos);
 	}
 
@@ -1908,7 +2307,6 @@
 	for (i = 0; i < chamelium->port_count; i++)
 		free(chamelium->ports[i].name);
 
-	free(chamelium->ports);
 	free(chamelium);
 }
 
diff --git a/lib/igt_chamelium.h b/lib/igt_chamelium.h
index ce9e9ce..b6b7eb4 100644
--- a/lib/igt_chamelium.h
+++ b/lib/igt_chamelium.h
@@ -53,6 +53,12 @@
 	CHAMELIUM_CHECK_CRC,
 };
 
+struct chamelium_video_params {
+	double clock;
+	int htotal, hactive, hsync_offset, hsync_width, hsync_polarity;
+	int vtotal, vactive, vsync_offset, vsync_width, vsync_polarity;
+};
+
 struct chamelium_audio_file {
 	char *path;
 	int rate; /* Hz */
@@ -62,6 +68,13 @@
 struct chamelium_edid;
 
 /**
+ * CHAMELIUM_MAX_PORTS: the maximum number of ports supported by igt_chamelium.
+ *
+ * For now, we have 1 VGA, 1 HDMI and 2 DisplayPort ports.
+ */
+#define CHAMELIUM_MAX_PORTS 4
+
+/**
  * CHAMELIUM_DEFAULT_EDID: provide this ID to #chamelium_port_set_edid to use
  * the default EDID.
  */
@@ -102,6 +115,8 @@
 				   bool rising_edge);
 struct chamelium_edid *chamelium_new_edid(struct chamelium *chamelium,
 					  const unsigned char *edid);
+const struct edid *chamelium_edid_get_raw(struct chamelium_edid *edid,
+					  struct chamelium_port *port);
 void chamelium_port_set_edid(struct chamelium *chamelium,
 			     struct chamelium_port *port,
 			     struct chamelium_edid *edid);
@@ -113,6 +128,10 @@
 void chamelium_port_get_resolution(struct chamelium *chamelium,
 				   struct chamelium_port *port,
 				   int *x, int *y);
+bool chamelium_supports_get_video_params(struct chamelium *chamelium);
+void chamelium_port_get_video_params(struct chamelium *chamelium,
+				     struct chamelium_port *port,
+				     struct chamelium_video_params *params);
 igt_crc_t *chamelium_get_crc_for_area(struct chamelium *chamelium,
 				      struct chamelium_port *port,
 				      int x, int y, int w, int h);
diff --git a/lib/igt_core.c b/lib/igt_core.c
index 6b9f042..1cbb09f 100644
--- a/lib/igt_core.c
+++ b/lib/igt_core.c
@@ -70,6 +70,7 @@
 #include "igt_sysfs.h"
 #include "igt_sysrq.h"
 #include "igt_rc.h"
+#include "igt_list.h"
 
 #define UNW_LOCAL_ONLY
 #include <libunwind.h>
@@ -256,9 +257,11 @@
 
 static unsigned int exit_handler_count;
 const char *igt_interactive_debug;
+bool igt_skip_crc_compare;
 
 /* subtests helpers */
 static bool list_subtests = false;
+static bool describe_subtests = false;
 static char *run_single_subtest = NULL;
 static bool run_single_subtest_found = false;
 static const char *in_subtest = NULL;
@@ -271,6 +274,16 @@
 	CONT = 0, SKIP, FAIL
 } skip_subtests_henceforth = CONT;
 
+static char __current_description[512];
+
+struct description_node {
+	char desc[sizeof(__current_description)];
+	struct igt_list link;
+};
+
+static struct igt_list subgroup_descriptions;
+
+
 bool __igt_plain_output = false;
 
 /* fork support state */
@@ -285,10 +298,12 @@
 	 * conflict with core ones
 	 */
 	OPT_LIST_SUBTESTS = 500,
+	OPT_DESCRIBE_SUBTESTS,
 	OPT_RUN_SUBTEST,
 	OPT_DESCRIPTION,
 	OPT_DEBUG,
 	OPT_INTERACTIVE_DEBUG,
+	OPT_SKIP_CRC,
 	OPT_HELP = 'h'
 };
 
@@ -528,10 +543,59 @@
 	assert(sig != 0 || igt_exit_called);
 }
 
+static void print_line_wrapping(const char *indent, const char *text)
+{
+	char *copy, *curr, *next_space;
+	int current_line_length = 0;
+	bool done = false;
+
+	const int total_line_length = 80;
+	const int line_length = total_line_length - strlen(indent);
+
+	copy = malloc(strlen(text) + 1);
+	memcpy(copy, text, strlen(text) + 1);
+
+	curr = copy;
+
+	printf("%s", indent);
+
+	while (!done) {
+		next_space = strchr(curr, ' ');
+
+		if (!next_space) { /* no more spaces, print everything that is left */
+			done = true;
+			next_space = strchr(curr, '\0');
+		}
+
+		*next_space = '\0';
+
+		if ((next_space - curr) + current_line_length > line_length && curr != copy) {
+			printf("\n%s", indent);
+			current_line_length = 0;
+		}
+
+		if (current_line_length == 0)
+			printf("%s", curr); /* first word in a line, don't space out */
+		else
+			printf(" %s", curr);
+
+		current_line_length += next_space - curr;
+		curr = next_space + 1;
+	}
+
+	printf("\n");
+
+	free(copy);
+}
+
+
 static void print_test_description(void)
 {
-	if (&__igt_test_description)
-		printf("%s\n", __igt_test_description);
+	if (&__igt_test_description) {
+		print_line_wrapping("", __igt_test_description);
+		if (describe_subtests)
+			printf("\n");
+	}
 }
 
 static void print_version(void)
@@ -557,7 +621,9 @@
 		   "  --run-subtest <pattern>\n"
 		   "  --debug[=log-domain]\n"
 		   "  --interactive-debug[=domain]\n"
+		   "  --skip-crc-compare\n"
 		   "  --help-description\n"
+		   "  --describe\n"
 		   "  --help|-h\n");
 	if (help_str)
 		fprintf(f, "%s\n", help_str);
@@ -671,10 +737,12 @@
 	int c, option_index = 0, i, x;
 	static struct option long_options[] = {
 		{"list-subtests",     no_argument,       NULL, OPT_LIST_SUBTESTS},
+		{"describe",          optional_argument, NULL, OPT_DESCRIBE_SUBTESTS},
 		{"run-subtest",       required_argument, NULL, OPT_RUN_SUBTEST},
 		{"help-description",  no_argument,       NULL, OPT_DESCRIPTION},
 		{"debug",             optional_argument, NULL, OPT_DEBUG},
 		{"interactive-debug", optional_argument, NULL, OPT_INTERACTIVE_DEBUG},
+		{"skip-crc-compare",  no_argument,       NULL, OPT_SKIP_CRC},
 		{"help",              no_argument,       NULL, OPT_HELP},
 		{0, 0, 0, 0}
 	};
@@ -687,6 +755,7 @@
 	int ret = 0;
 
 	common_init_env();
+	igt_list_init(&subgroup_descriptions);
 
 	command_str = argv[0];
 	if (strrchr(command_str, '/'))
@@ -777,6 +846,13 @@
 			if (!run_single_subtest)
 				list_subtests = true;
 			break;
+		case OPT_DESCRIBE_SUBTESTS:
+			if (optarg)
+				run_single_subtest = strdup(optarg);
+			list_subtests = true;
+			describe_subtests = true;
+			print_test_description();
+			break;
 		case OPT_RUN_SUBTEST:
 			assert(optarg);
 			if (!list_subtests)
@@ -786,6 +862,9 @@
 			print_test_description();
 			ret = -1;
 			goto out;
+		case OPT_SKIP_CRC:
+			igt_skip_crc_compare = true;
+			goto out;
 		case OPT_HELP:
 			print_usage(help_str, false);
 			ret = -1;
@@ -934,12 +1013,41 @@
 		    extra_opt_handler, handler_data);
 }
 
+static void _clear_current_description(void) {
+	__current_description[0] = '\0';
+}
+
+static void __igt_print_description(const char *subtest_name, const char *file, int line)
+{
+	struct description_node *desc;
+	const char indent[] = "  ";
+	bool has_doc = false;
+
+
+	printf("SUB %s %s:%d:\n", subtest_name, file, line);
+
+	igt_list_for_each(desc, &subgroup_descriptions, link) {
+		print_line_wrapping(indent, desc->desc);
+		printf("\n");
+		has_doc = true;
+	}
+
+	if (__current_description[0] != '\0') {
+		print_line_wrapping(indent, __current_description);
+		printf("\n");
+		has_doc = true;
+	}
+
+	if (!has_doc)
+		printf("%sNO DOCUMENTATION!\n\n", indent);
+}
+
 /*
  * Note: Testcases which use these helpers MUST NOT output anything to stdout
  * outside of places protected by igt_run_subtest checks - the piglit
  * runner adds every line to the subtest list.
  */
-bool __igt_run_subtest(const char *subtest_name)
+bool __igt_run_subtest(const char *subtest_name, const char *file, const int line)
 {
 	int i;
 
@@ -954,17 +1062,24 @@
 			igt_exit();
 		}
 
-	if (list_subtests) {
+	if (run_single_subtest) {
+		if (uwildmat(subtest_name, run_single_subtest) == 0) {
+			_clear_current_description();
+			return false;
+		} else {
+			run_single_subtest_found = true;
+		}
+	}
+
+	if (describe_subtests) {
+		__igt_print_description(subtest_name, file, line);
+		_clear_current_description();
+		return false;
+	} else if (list_subtests) {
 		printf("%s\n", subtest_name);
 		return false;
 	}
 
-	if (run_single_subtest) {
-		if (uwildmat(subtest_name, run_single_subtest) == 0)
-			return false;
-		else
-			run_single_subtest_found = true;
-	}
 
 	if (skip_subtests_henceforth) {
 		printf("%sSubtest %s: %s%s\n",
@@ -1014,15 +1129,32 @@
 	return list_subtests;
 }
 
-void __igt_subtest_group_save(int *save)
+
+
+void __igt_subtest_group_save(int *save, int *desc)
 {
 	assert(test_with_subtests);
 
+	if (__current_description[0] != '\0') {
+		struct description_node *new = calloc(1, sizeof(*new));
+		memcpy(new->desc, __current_description, sizeof(__current_description));
+		igt_list_add_tail(&new->link, &subgroup_descriptions);
+		_clear_current_description();
+		*desc = true;
+	}
+
 	*save = skip_subtests_henceforth;
 }
 
-void __igt_subtest_group_restore(int save)
+void __igt_subtest_group_restore(int save, int desc)
 {
+	if (desc) {
+		struct description_node *last =
+			igt_list_last_entry(&subgroup_descriptions, last, link);
+		igt_list_del(&last->link);
+		free(last);
+	}
+
 	skip_subtests_henceforth = save;
 }
 
@@ -1229,6 +1361,34 @@
 	return !test_with_subtests || in_fixture || in_subtest;
 }
 
+/**
+ * igt_describe_f:
+ * @fmt: format string containing description
+ * @...: argument used by the format string
+ *
+ * Attach a description to the following #igt_subtest or #igt_subtest_group
+ * block.
+ *
+ * Check #igt_describe for more details.
+ *
+ */
+void igt_describe_f(const char *fmt, ...)
+{
+	int ret;
+	va_list args;
+
+	if (!describe_subtests)
+		return;
+
+	va_start(args, fmt);
+
+	ret = vsnprintf(__current_description, sizeof(__current_description), fmt, args);
+
+	va_end(args);
+
+	assert(ret < sizeof(__current_description));
+}
+
 static bool running_under_gdb(void)
 {
 	char pathname[30], buf[1024];
@@ -1540,7 +1700,7 @@
 		g_key_file_free(igt_key_file);
 
 	if (run_single_subtest && !run_single_subtest_found) {
-		igt_warn("Unknown subtest: %s\n", run_single_subtest);
+		igt_critical("Unknown subtest: %s\n", run_single_subtest);
 		exit(IGT_EXIT_INVALID);
 	}
 
diff --git a/lib/igt_core.h b/lib/igt_core.h
index 88a95ec..177d243 100644
--- a/lib/igt_core.h
+++ b/lib/igt_core.h
@@ -174,7 +174,7 @@
 #define igt_subtest_init(argc, argv) \
 	igt_subtest_init_parse_opts(&argc, argv, NULL, NULL, NULL, NULL, NULL);
 
-bool __igt_run_subtest(const char *subtest_name);
+bool __igt_run_subtest(const char *subtest_name, const char *file, const int line);
 #define __igt_tokencat2(x, y) x ## y
 
 /**
@@ -198,14 +198,14 @@
  *
  * This is a simpler version of igt_subtest_f()
  */
-#define igt_subtest(name) for (; __igt_run_subtest((name)) && \
+#define igt_subtest(name) for (; __igt_run_subtest((name), __FILE__, __LINE__) && \
 				   (sigsetjmp(igt_subtest_jmpbuf, 1) == 0); \
 				   igt_success())
 #define __igt_subtest_f(tmp, format...) \
 	for (char tmp [256]; \
 	     snprintf( tmp , sizeof( tmp ), \
 		      format), \
-	     __igt_run_subtest( tmp ) && \
+	     __igt_run_subtest(tmp, __FILE__, __LINE__) && \
 	     (sigsetjmp(igt_subtest_jmpbuf, 1) == 0); \
 	     igt_success())
 
@@ -227,8 +227,8 @@
 const char *igt_subtest_name(void);
 bool igt_only_list_subtests(void);
 
-void __igt_subtest_group_save(int *);
-void __igt_subtest_group_restore(int);
+void __igt_subtest_group_save(int *, int *);
+void __igt_subtest_group_restore(int, int);
 /**
  * igt_subtest_group:
  *
@@ -245,11 +245,14 @@
  * group will fail or skip. Subtest groups can be arbitrarily nested.
  */
 #define igt_subtest_group for (int igt_tokencat(__tmpint,__LINE__) = 0, \
-			       igt_tokencat(__save,__LINE__) = 0; \
+			       igt_tokencat(__save,__LINE__) = 0, \
+			       igt_tokencat(__desc,__LINE__) = 0; \
 			       igt_tokencat(__tmpint,__LINE__) < 1 && \
-			       (__igt_subtest_group_save(& igt_tokencat(__save,__LINE__) ), true); \
+			       (__igt_subtest_group_save(& igt_tokencat(__save,__LINE__), \
+							 & igt_tokencat(__desc,__LINE__) ), true); \
 			       igt_tokencat(__tmpint,__LINE__) ++, \
-			       __igt_subtest_group_restore(igt_tokencat(__save,__LINE__) ))
+			       __igt_subtest_group_restore(igt_tokencat(__save,__LINE__), \
+							   igt_tokencat(__desc,__LINE__)))
 
 /**
  * igt_main_args:
@@ -385,6 +388,124 @@
 {
 }
 
+__attribute__((format(printf, 1, 2)))
+void igt_describe_f(const char *fmt, ...);
+
+/**
+ * igt_describe:
+ * @dsc: string containing description
+ *
+ * Attach a description to the following #igt_subtest or #igt_subtest_group
+ * block.
+ *
+ * The description should complement the test/subtest name and provide more
+ * context on what is being tested. It should explain the idea of the test and
+ * do not mention implementation details, so that it never goes out of date.
+ *
+ * DO:
+ *  * focus on the userspace's perspective
+ *  * try to capture the reason for the test's existence
+ *  * be brief
+ *
+ * DON'T:
+ *  * try to translate the code into English
+ *  * explain all the checks the test does
+ *  * delve on the implementation
+ *
+ * Good examples:
+ *  * "make sure that legacy cursor updates do not stall atomic commits"
+ *  * "check that atomic updates of many planes are indeed atomic and take
+ *     effect immediately after the commit"
+ *  * "make sure that the meta-data exposed by the kernel to the userspace
+ *     is correct and matches the used EDID"
+ *
+ * Bad examples:
+ *  * "spawn 10 threads, each pinning cpu core with a busy loop..."
+ *  * "randomly generate holes in a primary plane then try to cover each hole
+ *    with a plane and make sure that CRC matches, do 25 gazillion rounds of
+ *    that..."
+ *
+ *
+ * Resulting #igt_subtest documentation is a concatenation of its own
+ * description and all the parenting #igt_subtest_group descriptions, starting
+ * from the outermost one. Example:
+ *
+ * |[<!-- language="C" -->
+ * #include "igt.h"
+ *
+ * IGT_TEST_DESCRIPTION("Global description of the whole binary");
+ * igt_main
+ * {
+ * 	igt_describe("Desc of the subgroup with A and B");
+ * 	igt_subtest_group {
+ * 		igt_describe("Desc of the subtest A");
+ * 		igt_subtest("subtest-a") {
+ * 			...
+ * 		}
+ *
+ * 		igt_describe("Desc of the subtest B");
+ * 		igt_subtest("subtest-b") {
+ * 			...
+ * 		}
+ * 	}
+ *
+ * 	igt_describe("Desc of the subtest C");
+ * 	igt_subtest("subtest-c") {
+ * 		...
+ * 	}
+ * }
+ * ]|
+ *
+ * It's will accessible via --describe command line switch:
+ *
+ * |[
+ * $ test --describe
+ * Global description of the whole binary
+ *
+ * SUB subtest-a test.c:5:
+ *   Desc of the subgroup with A and B
+ *
+ *   Desc of the subtest A
+ *
+ * SUB subtest-b test.c:10:
+ *   Desc of the subgroup with A and B
+ *
+ *   Desc of the subtest B
+ *
+ * SUB subtest-c test.c:15:
+ *   Desc of the subtest C
+ * ]|
+ *
+ * Every single #igt_subtest does not have to be preceded with a #igt_describe
+ * as long as it has good-enough explanation provided on the #igt_subtest_group
+ * level.
+ *
+ * Example:
+ *
+ * |[<!-- language="C" -->
+ * #include "igt.h"
+ *
+ * igt_main
+ * {
+ * 	igt_describe("check xyz with different tilings");
+ * 	igt_subtest_group {
+ * 		// no need for extra description, group is enough and tiling is
+ * 		// obvious from the test name
+ * 		igt_subtest("foo-tiling-x") {
+ * 			...
+ * 		}
+ *
+ * 		igt_subtest("foo-tiling-y") {
+ * 			...
+ * 		}
+ * 	}
+ * }
+ * ]|
+ *
+ */
+#define igt_describe(dsc) \
+	igt_describe_f("%s", dsc)
+
 /**
  * igt_assert:
  * @expr: condition to test
@@ -877,6 +998,7 @@
 void igt_skip_on_simulation(void);
 
 extern const char *igt_interactive_debug;
+extern bool igt_skip_crc_compare;
 
 /**
  * igt_log_level:
diff --git a/lib/igt_debugfs.c b/lib/igt_debugfs.c
index 82ce183..676884c 100644
--- a/lib/igt_debugfs.c
+++ b/lib/igt_debugfs.c
@@ -405,6 +405,12 @@
  * assert that CRCs match, never that they are different. Otherwise there might
  * be random testcase failures when different screen contents end up with the
  * same CRC by chance.
+ *
+ * Passing --skip-crc-compare on the command line will force this function
+ * to always pass, which can be useful in interactive debugging where you
+ * might know the test will fail, but still want the test to keep going as if
+ * it had succeeded so that you can see the on-screen behavior.
+ *
  */
 void igt_assert_crc_equal(const igt_crc_t *a, const igt_crc_t *b)
 {
@@ -413,10 +419,11 @@
 
 	mismatch = igt_find_crc_mismatch(a, b, &index);
 	if (mismatch)
-		igt_debug("CRC mismatch at index %d: 0x%x != 0x%x\n", index,
-			  a->crc[index], b->crc[index]);
+		igt_debug("CRC mismatch%s at index %d: 0x%x != 0x%x\n",
+			  igt_skip_crc_compare ? " (ignored)" : "",
+			  index, a->crc[index], b->crc[index]);
 
-	igt_assert(!mismatch);
+	igt_assert(!mismatch || igt_skip_crc_compare);
 }
 
 /**
diff --git a/lib/igt_debugfs.h b/lib/igt_debugfs.h
index 52520b3..36b6381 100644
--- a/lib/igt_debugfs.h
+++ b/lib/igt_debugfs.h
@@ -83,6 +83,7 @@
 } igt_crc_t;
 
 #define INTEL_PIPE_CRC_SOURCE_AUTO "auto"
+#define AMDGPU_PIPE_CRC_SOURCE_DPRX "dprx"
 
 void igt_assert_crc_equal(const igt_crc_t *a, const igt_crc_t *b);
 bool igt_check_crc_equal(const igt_crc_t *a, const igt_crc_t *b);
diff --git a/lib/igt_edid.c b/lib/igt_edid.c
index e71136f..1ad8897 100644
--- a/lib/igt_edid.c
+++ b/lib/igt_edid.c
@@ -34,6 +34,21 @@
 #include "igt_core.h"
 #include "igt_edid.h"
 
+/**
+ * SECTION:igt_edid
+ * @short_description: EDID generation library
+ * @title: EDID
+ * @include: igt_edid.h
+ *
+ * This library contains helpers to generate custom EDIDs.
+
+ * The E-EDID specification is available at:
+ * https://glenwing.github.io/docs/VESA-EEDID-A2.pdf
+ *
+ * The EDID CEA extension is defined in CEA-861-D section 7. The HDMI VSDB is
+ * defined in the HDMI spec.
+ */
+
 static const char edid_header[] = {
 	0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00
 };
@@ -42,6 +57,8 @@
 	0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
 };
 
+const uint8_t hdmi_ieee_oui[3] = {0x03, 0x0C, 0x00};
+
 /* vfreq is in Hz */
 static void std_timing_set(struct std_timing *st, int hsize, int vfreq,
 			   enum std_timing_aspect aspect)
@@ -172,6 +189,19 @@
 		ds->str[len] = '\n';
 }
 
+/**
+ * edid_get_mfg: reads the 3-letter manufacturer identifier
+ *
+ * The string is *not* NULL-terminated.
+ */
+void edid_get_mfg(const struct edid *edid, char out[static 3])
+{
+	out[0] = ((edid->mfg_id[0] & 0x7C) >> 2) + '@';
+	out[1] = (((edid->mfg_id[0] & 0x03) << 3) |
+		 ((edid->mfg_id[1] & 0xE0) >> 5)) + '@';
+	out[2] = (edid->mfg_id[1] & 0x1F) + '@';
+}
+
 static void edid_set_mfg(struct edid *edid, const char mfg[static 3])
 {
 	edid->mfg_id[0] = (mfg[0] - '@') << 2 | (mfg[1] - '@') >> 3;
@@ -275,6 +305,16 @@
 }
 
 /**
+ * edid_get_size: return the size of the EDID block in bytes including EDID
+ * extensions, if any.
+ */
+size_t edid_get_size(const struct edid *edid)
+{
+	return sizeof(struct edid) +
+	       edid->extensions_len * sizeof(struct edid_ext);
+}
+
+/**
  * cea_sad_init_pcm:
  * @channels: the number of supported channels (max. 8)
  * @sampling_rates: bitfield of enum cea_sad_sampling_rate
@@ -292,29 +332,31 @@
 }
 
 /**
- * cea_vsd_get_hdmi_default:
+ * cea_vsdb_get_hdmi_default:
  *
  * Returns the default Vendor Specific Data block for HDMI.
  */
-const struct cea_vsd *cea_vsd_get_hdmi_default(size_t *size)
+const struct cea_vsdb *cea_vsdb_get_hdmi_default(size_t *size)
 {
-	static char raw[sizeof(struct cea_vsd) + 4] = {0};
-	struct cea_vsd *vsd;
+	/* We'll generate a VSDB with 2 extension fields. */
+	static char raw[CEA_VSDB_HDMI_MIN_SIZE + 2] = {0};
+	struct cea_vsdb *vsdb;
+	struct hdmi_vsdb *hdmi;
 
 	*size = sizeof(raw);
 
 	/* Magic incantation. Works better if you orient your screen in the
 	 * direction of the VESA headquarters. */
-	vsd = (struct cea_vsd *) raw;
-	vsd->ieee_oui[0] = 0x03;
-	vsd->ieee_oui[1] = 0x0C;
-	vsd->ieee_oui[2] = 0x00;
-	vsd->data[0] = 0x10;
-	vsd->data[1] = 0x00;
-	vsd->data[2] = 0x38;
-	vsd->data[3] = 0x2D;
+	vsdb = (struct cea_vsdb *) raw;
+	memcpy(vsdb->ieee_oui, hdmi_ieee_oui, sizeof(hdmi_ieee_oui));
+	hdmi = &vsdb->data.hdmi;
+	hdmi->src_phy_addr[0] = 0x10;
+	hdmi->src_phy_addr[1] = 0x00;
+	/* 2 VSDB extension fields */
+	hdmi->flags1 = 0x38;
+	hdmi->max_tdms_clock = 0x2D;
 
-	return vsd;
+	return vsdb;
 }
 
 static void edid_cea_data_block_init(struct edid_cea_data_block *block,
@@ -324,6 +366,10 @@
 	block->type_len = type << 5 | size;
 }
 
+/**
+ * edid_cea_data_block_set_sad: initialize a CEA data block to contain Short
+ * Audio Descriptors
+ */
 size_t edid_cea_data_block_set_sad(struct edid_cea_data_block *block,
 				   const struct cea_sad *sads, size_t sads_len)
 {
@@ -337,17 +383,57 @@
 	return sizeof(struct edid_cea_data_block) + sads_size;
 }
 
-size_t edid_cea_data_block_set_vsd(struct edid_cea_data_block *block,
-				   const struct cea_vsd *vsd, size_t vsd_size)
+/**
+ * edid_cea_data_block_set_svd: initialize a CEA data block to contain Short
+ * Video Descriptors
+ */
+size_t edid_cea_data_block_set_svd(struct edid_cea_data_block *block,
+				   const uint8_t *svds, size_t svds_len)
 {
-	edid_cea_data_block_init(block, EDID_CEA_DATA_VENDOR_SPECIFIC,
-				 vsd_size);
-
-	memcpy(block->data.vsds, vsd, vsd_size);
-
-	return sizeof(struct edid_cea_data_block) + vsd_size;
+	edid_cea_data_block_init(block, EDID_CEA_DATA_VIDEO, svds_len);
+	memcpy(block->data.svds, svds, svds_len);
+	return sizeof(struct edid_cea_data_block) + svds_len;
 }
 
+/**
+ * edid_cea_data_block_set_vsdb: initialize a CEA data block to contain a
+ * Vendor Specific Data Block
+ */
+size_t edid_cea_data_block_set_vsdb(struct edid_cea_data_block *block,
+				    const struct cea_vsdb *vsdb, size_t vsdb_size)
+{
+	edid_cea_data_block_init(block, EDID_CEA_DATA_VENDOR_SPECIFIC,
+				 vsdb_size);
+
+	memcpy(block->data.vsdbs, vsdb, vsdb_size);
+
+	return sizeof(struct edid_cea_data_block) + vsdb_size;
+}
+
+/**
+ * edid_cea_data_block_set_hdmi_vsdb: initialize a CEA data block to contain an
+ * HDMI VSDB
+ */
+size_t edid_cea_data_block_set_hdmi_vsdb(struct edid_cea_data_block *block,
+					 const struct hdmi_vsdb *hdmi,
+					 size_t hdmi_size)
+{
+	char raw_vsdb[CEA_VSDB_HDMI_MAX_SIZE] = {0};
+	struct cea_vsdb *vsdb = (struct cea_vsdb *) raw_vsdb;
+
+	assert(hdmi_size >= HDMI_VSDB_MIN_SIZE &&
+	       hdmi_size <= HDMI_VSDB_MAX_SIZE);
+	memcpy(vsdb->ieee_oui, hdmi_ieee_oui, sizeof(hdmi_ieee_oui));
+	memcpy(&vsdb->data.hdmi, hdmi, hdmi_size);
+
+	return edid_cea_data_block_set_vsdb(block, vsdb,
+					    CEA_VSDB_HEADER_SIZE + hdmi_size);
+}
+
+/**
+ * edid_cea_data_block_set_speaker_alloc: initialize a CEA data block to
+ * contain a Speaker Allocation Data block
+ */
 size_t edid_cea_data_block_set_speaker_alloc(struct edid_cea_data_block *block,
 					     const struct cea_speaker_alloc *speakers)
 {
@@ -360,16 +446,24 @@
 	return sizeof(struct edid_cea_data_block) + size;
 }
 
+/**
+ * edid_ext_set_cea: initialize an EDID extension block to contain a CEA
+ * extension. CEA extensions contain a Data Block Collection (with multiple
+ * CEA data blocks) followed by multiple Detailed Timing Descriptors.
+ */
 void edid_ext_set_cea(struct edid_ext *ext, size_t data_blocks_size,
-		      uint8_t flags)
+		      uint8_t num_native_dtds, uint8_t flags)
 {
 	struct edid_cea *cea = &ext->data.cea;
 
 	ext->tag = EDID_EXT_CEA;
 
+	assert(num_native_dtds <= 0x0F);
+	assert((flags & 0x0F) == 0);
+	assert(data_blocks_size <= sizeof(cea->data));
 	cea->revision = 3;
 	cea->dtd_start = 4 + data_blocks_size;
-	cea->misc = flags; /* just flags, no DTD */
+	cea->misc = flags | num_native_dtds;
 }
 
 void edid_ext_update_cea_checksum(struct edid_ext *ext)
diff --git a/lib/igt_edid.h b/lib/igt_edid.h
index 00596ef..606541a 100644
--- a/lib/igt_edid.h
+++ b/lib/igt_edid.h
@@ -32,6 +32,9 @@
 
 #include <xf86drmMode.h>
 
+/**
+ * est_timings: set of established timings
+ */
 struct est_timings {
 	uint8_t t1;
 	uint8_t t2;
@@ -47,6 +50,9 @@
 	STD_TIMING_16_9 = 0b11,
 };
 
+/**
+ * std_timing: a standard timing
+ */
 struct std_timing {
 	uint8_t hsize;
 	uint8_t vfreq_aspect;
@@ -191,12 +197,62 @@
 	uint8_t bitrate;
 } __attribute__((packed));
 
-/* Vendor Specific Data */
-struct cea_vsd {
-	uint8_t ieee_oui[3];
-	char data[];
+/* Indicates that a Short Video Descriptor is native */
+#define CEA_SVD_NATIVE (1 << 7)
+
+enum hdmi_vsdb_flags1 {
+	HDMI_VSDB_DVI_DUAL = 1 << 0,
+	HDMI_VSDB_DC_Y444 = 1 << 3, /* supports YCbCr 4:4:4 */
+	HDMI_VSDB_DC_30BIT = 1 << 4, /* 30 bits per pixel */
+	HDMI_VSDB_DC_36BIT = 1 << 5, /* 36 bits per pixel */
+	HDMI_VSDB_DC_48BIT = 1 << 6, /* 48 bits per pixel */
+	HDMI_VSDB_SUPPORTS_AI = 1 << 7, /* supports ACP, ISRC1 or ISRC2 packets */
 };
 
+enum hdmi_vsdb_flags2 {
+	HDMI_VSDB_CNC_GRAPHICS = 1 << 0,
+	HDMI_VSDB_CNC_PHOTO = 1 << 1,
+	HDMI_VSDB_CNC_CINEMA = 1 << 2,
+	HDMI_VSDB_CNC_GAME = 1 << 3,
+	HDMI_VSDB_VIDEO_PRESENT = 1 << 5,
+	HDMI_VSDB_INTERLACED_LATENCY_PRESENT = 1 << 6,
+	HDMI_VSDB_LATENCY_PRESENT = 1 << 7,
+};
+
+enum hdmi_vsdb_video_flags {
+	HDMI_VSDB_VIDEO_3D_STRUCT_PRESENT = 0b01 << 5,
+	HDMI_VSDB_VIDEO_3D_STRUCT_MASK_PRESENT = 0b10 << 5,
+	HDMI_VSDB_VIDEO_3D_PRESENT = 1 << 7,
+};
+
+/* HDMI's IEEE Registration Identifier */
+extern const uint8_t hdmi_ieee_oui[3];
+
+/* HDMI Vendor-Specific Data Block (defined in the HDMI spec) */
+struct hdmi_vsdb {
+	uint8_t src_phy_addr[2]; /* source physical address */
+
+	/* Extension fields */
+	uint8_t flags1; /* enum hdmi_vsdb_flags1 */
+	uint8_t max_tdms_clock; /* multiply by 5MHz */
+	uint8_t flags2; /* enum hdmi_vsdb_flags2 */
+	char data[]; /* latency, misc, VIC, 3D */
+} __attribute__((packed));
+
+#define HDMI_VSDB_MIN_SIZE 2 /* just the source physical address */
+#define HDMI_VSDB_MAX_SIZE 28
+#define CEA_VSDB_HEADER_SIZE 3 /* IEEE OUI */
+#define CEA_VSDB_HDMI_MIN_SIZE (CEA_VSDB_HEADER_SIZE + HDMI_VSDB_MIN_SIZE)
+#define CEA_VSDB_HDMI_MAX_SIZE (CEA_VSDB_HEADER_SIZE + HDMI_VSDB_MAX_SIZE)
+
+/* Vendor-Specific Data Block */
+struct cea_vsdb {
+	uint8_t ieee_oui[3]; /* 24-bit IEEE Registration Identifier, LSB */
+	union {
+		struct hdmi_vsdb hdmi;
+	} data;
+} __attribute__((packed));
+
 enum cea_speaker_alloc_item {
 	CEA_SPEAKER_FRONT_LEFT_RIGHT = 1 << 0,
 	CEA_SPEAKER_LFE = 1 << 1,
@@ -223,7 +279,8 @@
 	uint8_t type_len; /* type is from enum edid_cea_data_type */
 	union {
 		struct cea_sad sads[0];
-		struct cea_vsd vsds[0];
+		uint8_t svds[0]; /* Short Video Descriptors */
+		struct cea_vsdb vsdbs[0];
 		struct cea_speaker_alloc speakers[0];
 	} data;
 } __attribute__((packed));
@@ -297,6 +354,8 @@
 void edid_init(struct edid *edid);
 void edid_init_with_mode(struct edid *edid, drmModeModeInfo *mode);
 void edid_update_checksum(struct edid *edid);
+size_t edid_get_size(const struct edid *edid);
+void edid_get_mfg(const struct edid *edid, char out[static 3]);
 void detailed_timing_set_mode(struct detailed_timing *dt, drmModeModeInfo *mode,
 			      int width_mm, int height_mm);
 void detailed_timing_set_monitor_range_mode(struct detailed_timing *dt,
@@ -308,14 +367,19 @@
 void cea_sad_init_pcm(struct cea_sad *sad, int channels,
 		      uint8_t sampling_rates, uint8_t sample_sizes);
 void edid_ext_update_cea_checksum(struct edid_ext *ext);
-const struct cea_vsd *cea_vsd_get_hdmi_default(size_t *size);
+const struct cea_vsdb *cea_vsdb_get_hdmi_default(size_t *size);
 size_t edid_cea_data_block_set_sad(struct edid_cea_data_block *block,
 				   const struct cea_sad *sads, size_t sads_len);
-size_t edid_cea_data_block_set_vsd(struct edid_cea_data_block *block,
-				   const struct cea_vsd *vsd, size_t vsd_size);
+size_t edid_cea_data_block_set_svd(struct edid_cea_data_block *block,
+				   const uint8_t *svds, size_t svds_len);
+size_t edid_cea_data_block_set_vsdb(struct edid_cea_data_block *block,
+				   const struct cea_vsdb *vsdb, size_t vsdb_size);
+size_t edid_cea_data_block_set_hdmi_vsdb(struct edid_cea_data_block *block,
+					 const struct hdmi_vsdb *hdmi,
+					 size_t hdmi_size);
 size_t edid_cea_data_block_set_speaker_alloc(struct edid_cea_data_block *block,
 					     const struct cea_speaker_alloc *speakers);
 void edid_ext_set_cea(struct edid_ext *ext, size_t data_blocks_size,
-		      uint8_t flags);
+		      uint8_t num_native_dtds, uint8_t flags);
 
 #endif
diff --git a/lib/igt_eld.c b/lib/igt_eld.c
index 3d7fd4d..16c4ac0 100644
--- a/lib/igt_eld.c
+++ b/lib/igt_eld.c
@@ -207,10 +207,11 @@
 {
 	DIR *dir;
 	struct dirent *dirent;
-	int i;
+	int i, n_elds;
 	char card[64];
 	char path[PATH_MAX];
 
+	n_elds = 0;
 	for (i = 0; i < 8; i++) {
 		snprintf(card, sizeof(card), "/proc/asound/card%d", i);
 		dir = opendir(card);
@@ -222,6 +223,8 @@
 				    strlen(ELD_PREFIX)) != 0)
 				continue;
 
+			n_elds++;
+
 			snprintf(path, sizeof(path), "%s/%s", card,
 				 dirent->d_name);
 			if (!eld_parse_entry(path, eld)) {
@@ -246,6 +249,9 @@
 		closedir(dir);
 	}
 
+	if (n_elds == 0)
+		igt_debug("Found zero ELDs\n");
+
 	return false;
 }
 
diff --git a/lib/igt_fb.c b/lib/igt_fb.c
index 9d4f905..5dc74a0 100644
--- a/lib/igt_fb.c
+++ b/lib/igt_fb.c
@@ -903,6 +903,200 @@
 	return fb.gem_handle;
 }
 
+#define get_u16_bit(x, n) 	((x & (1 << n)) >> n )
+#define set_u16_bit(x, n, val)	((x & ~(1 << n)) | (val << n))
+/*
+ * update_crc16_dp:
+ * @crc_old: old 16-bit CRC value to be updated
+ * @d: input 16-bit data on which to calculate 16-bit CRC
+ *
+ * CRC algorithm implementation described in DP 1.4 spec Appendix J
+ * the 16-bit CRC IBM is applied, with the following polynomial:
+ *
+ *       f(x) = x ^ 16 + x ^ 15 + x ^ 2 + 1
+ *
+ * the MSB is shifted in first, for any color format that is less than 16 bits
+ * per component, the LSB is zero-padded.
+ *
+ * The following implementation is based on the hardware parallel 16-bit CRC
+ * generation and ported to C code.
+ *
+ * Reference: VESA DisplayPort Standard v1.4, appendix J
+ *
+ * Returns:
+ * updated 16-bit CRC value.
+ */
+static uint16_t update_crc16_dp(uint16_t crc_old, uint16_t d)
+{
+	uint16_t crc_new = 0;	/* 16-bit CRC output */
+
+	/* internal use */
+	uint16_t b = crc_old;
+	uint8_t val;
+
+	/* b[15] */
+	val = get_u16_bit(b, 0) ^ get_u16_bit(b, 1) ^ get_u16_bit(b, 2) ^
+	      get_u16_bit(b, 3) ^ get_u16_bit(b, 4) ^ get_u16_bit(b, 5) ^
+	      get_u16_bit(b, 6) ^ get_u16_bit(b, 7) ^ get_u16_bit(b, 8) ^
+	      get_u16_bit(b, 9) ^ get_u16_bit(b, 10) ^ get_u16_bit(b, 11) ^
+	      get_u16_bit(b, 12) ^ get_u16_bit(b, 14) ^ get_u16_bit(b, 15) ^
+	      get_u16_bit(d, 0) ^ get_u16_bit(d, 1) ^ get_u16_bit(d, 2) ^
+	      get_u16_bit(d, 3) ^ get_u16_bit(d, 4) ^ get_u16_bit(d, 5) ^
+	      get_u16_bit(d, 6) ^ get_u16_bit(d, 7) ^ get_u16_bit(d, 8) ^
+	      get_u16_bit(d, 9) ^ get_u16_bit(d, 10) ^ get_u16_bit(d, 11) ^
+	      get_u16_bit(d, 12) ^ get_u16_bit(d, 14) ^ get_u16_bit(d, 15);
+	crc_new = set_u16_bit(crc_new, 15, val);
+
+	/* b[14] */
+	val = get_u16_bit(b, 12) ^ get_u16_bit(b, 13) ^
+	      get_u16_bit(d, 12) ^ get_u16_bit(d, 13);
+	crc_new = set_u16_bit(crc_new, 14, val);
+
+	/* b[13] */
+	val = get_u16_bit(b, 11) ^ get_u16_bit(b, 12) ^
+	      get_u16_bit(d, 11) ^ get_u16_bit(d, 12);
+	crc_new = set_u16_bit(crc_new, 13, val);
+
+	/* b[12] */
+	val = get_u16_bit(b, 10) ^ get_u16_bit(b, 11) ^
+	      get_u16_bit(d, 10) ^ get_u16_bit(d, 11);
+	crc_new = set_u16_bit(crc_new, 12, val);
+
+	/* b[11] */
+	val = get_u16_bit(b, 9) ^ get_u16_bit(b, 10) ^
+	      get_u16_bit(d, 9) ^ get_u16_bit(d, 10);
+	crc_new = set_u16_bit(crc_new, 11, val);
+
+	/* b[10] */
+	val = get_u16_bit(b, 8) ^ get_u16_bit(b, 9) ^
+	      get_u16_bit(d, 8) ^ get_u16_bit(d, 9);
+	crc_new = set_u16_bit(crc_new, 10, val);
+
+	/* b[9] */
+	val = get_u16_bit(b, 7) ^ get_u16_bit(b, 8) ^
+	      get_u16_bit(d, 7) ^ get_u16_bit(d, 8);
+	crc_new = set_u16_bit(crc_new, 9, val);
+
+	/* b[8] */
+	val = get_u16_bit(b, 6) ^ get_u16_bit(b, 7) ^
+	      get_u16_bit(d, 6) ^ get_u16_bit(d, 7);
+	crc_new = set_u16_bit(crc_new, 8, val);
+
+	/* b[7] */
+	val = get_u16_bit(b, 5) ^ get_u16_bit(b, 6) ^
+	      get_u16_bit(d, 5) ^ get_u16_bit(d, 6);
+	crc_new = set_u16_bit(crc_new, 7, val);
+
+	/* b[6] */
+	val = get_u16_bit(b, 4) ^ get_u16_bit(b, 5) ^
+	      get_u16_bit(d, 4) ^ get_u16_bit(d, 5);
+	crc_new = set_u16_bit(crc_new, 6, val);
+
+	/* b[5] */
+	val = get_u16_bit(b, 3) ^ get_u16_bit(b, 4) ^
+	      get_u16_bit(d, 3) ^ get_u16_bit(d, 4);
+	crc_new = set_u16_bit(crc_new, 5, val);
+
+	/* b[4] */
+	val = get_u16_bit(b, 2) ^ get_u16_bit(b, 3) ^
+	      get_u16_bit(d, 2) ^ get_u16_bit(d, 3);
+	crc_new = set_u16_bit(crc_new, 4, val);
+
+	/* b[3] */
+	val = get_u16_bit(b, 1) ^ get_u16_bit(b, 2) ^ get_u16_bit(b, 15) ^
+	      get_u16_bit(d, 1) ^ get_u16_bit(d, 2) ^ get_u16_bit(d, 15);
+	crc_new = set_u16_bit(crc_new, 3, val);
+
+	/* b[2] */
+	val = get_u16_bit(b, 0) ^ get_u16_bit(b, 1) ^ get_u16_bit(b, 14) ^
+	      get_u16_bit(d, 0) ^ get_u16_bit(d, 1) ^ get_u16_bit(d, 14);
+	crc_new = set_u16_bit(crc_new, 2, val);
+
+	/* b[1] */
+	val = get_u16_bit(b, 1) ^ get_u16_bit(b, 2) ^ get_u16_bit(b, 3) ^
+	      get_u16_bit(b, 4) ^ get_u16_bit(b, 5) ^ get_u16_bit(b, 6) ^
+	      get_u16_bit(b, 7) ^ get_u16_bit(b, 8) ^ get_u16_bit(b, 9) ^
+	      get_u16_bit(b, 10) ^ get_u16_bit(b, 11) ^ get_u16_bit(b, 12) ^
+	      get_u16_bit(b, 13) ^ get_u16_bit(b, 14) ^
+	      get_u16_bit(d, 1) ^ get_u16_bit(d, 2) ^ get_u16_bit(d, 3) ^
+	      get_u16_bit(d, 4) ^ get_u16_bit(d, 5) ^ get_u16_bit(d, 6) ^
+	      get_u16_bit(d, 7) ^ get_u16_bit(d, 8) ^ get_u16_bit(d, 9) ^
+	      get_u16_bit(d, 10) ^ get_u16_bit(d, 11) ^ get_u16_bit(d, 12) ^
+	      get_u16_bit(d, 13) ^ get_u16_bit(d, 14);
+	crc_new = set_u16_bit(crc_new, 1, val);
+
+	/* b[0] */
+	val = get_u16_bit(b, 0) ^ get_u16_bit(b, 1) ^ get_u16_bit(b, 2) ^
+	      get_u16_bit(b, 3) ^ get_u16_bit(b, 4) ^ get_u16_bit(b, 5) ^
+	      get_u16_bit(b, 6) ^ get_u16_bit(b, 7) ^ get_u16_bit(b, 8) ^
+	      get_u16_bit(b, 9) ^ get_u16_bit(b, 10) ^ get_u16_bit(b, 11) ^
+	      get_u16_bit(b, 12) ^ get_u16_bit(b, 13) ^ get_u16_bit(b, 15) ^
+	      get_u16_bit(d, 0) ^ get_u16_bit(d, 1) ^ get_u16_bit(d, 2) ^
+	      get_u16_bit(d, 3) ^ get_u16_bit(d, 4) ^ get_u16_bit(d, 5) ^
+	      get_u16_bit(d, 6) ^ get_u16_bit(d, 7) ^ get_u16_bit(d, 8) ^
+	      get_u16_bit(d, 9) ^ get_u16_bit(d, 10) ^ get_u16_bit(d, 11) ^
+	      get_u16_bit(d, 12) ^ get_u16_bit(d, 13) ^ get_u16_bit(d, 15);
+	crc_new = set_u16_bit(crc_new, 0, val);
+
+	return crc_new;
+}
+
+/**
+ * igt_fb_calc_crc:
+ * @fb: pointer to an #igt_fb structure
+ * @crc: pointer to an #igt_crc_t structure
+ *
+ * This function calculate the 16-bit frame CRC of RGB components over all
+ * the active pixels.
+ */
+void igt_fb_calc_crc(struct igt_fb *fb, igt_crc_t *crc)
+{
+	int x, y, i;
+	void *ptr;
+	uint8_t *data;
+	uint16_t din;
+
+	igt_assert(fb && crc);
+
+	ptr = igt_fb_map_buffer(fb->fd, fb);
+	igt_assert(ptr);
+
+	/* set for later CRC comparison */
+	crc->has_valid_frame = true;
+	crc->frame = 0;
+	crc->n_words = 3;
+	crc->crc[0] = 0;	/* R */
+	crc->crc[1] = 0;	/* G */
+	crc->crc[2] = 0;	/* B */
+
+	data = ptr + fb->offsets[0];
+	for (y = 0; y < fb->height; ++y) {
+		for (x = 0; x < fb->width; ++x) {
+			switch (fb->drm_format) {
+			case DRM_FORMAT_XRGB8888:
+				i = x * 4 + y * fb->strides[0];
+
+				din = data[i + 2] << 8; /* padding-zeros */
+				crc->crc[0] = update_crc16_dp(crc->crc[0], din);
+
+				/* Green-component */
+				din = data[i + 1] << 8;
+				crc->crc[1] = update_crc16_dp(crc->crc[1], din);
+
+				/* Blue-component */
+				din = data[i] << 8;
+				crc->crc[2] = update_crc16_dp(crc->crc[2], din);
+				break;
+			default:
+				igt_assert_f(0, "DRM Format Invalid");
+				break;
+			}
+		}
+	}
+
+	igt_fb_unmap_buffer(fb, ptr);
+}
+
 /**
  * igt_paint_color:
  * @cr: cairo drawing context
@@ -1221,6 +1415,8 @@
  * @height: height of the framebuffer in pixel
  * @format: drm fourcc pixel format code
  * @modifier: tiling layout of the framebuffer (as framebuffer modifier)
+ * @color_encoding: color encoding for YCbCr formats (ignored otherwise)
+ * @color_range: color range for YCbCr formats (ignored otherwise)
  * @fb: pointer to an #igt_fb structure
  * @bo_size: size of the backing bo (0 for automatic size)
  * @bo_stride: stride of the backing bo (0 for automatic stride)
@@ -1238,12 +1434,11 @@
 unsigned int
 igt_create_fb_with_bo_size(int fd, int width, int height,
 			   uint32_t format, uint64_t modifier,
+			   enum igt_color_encoding color_encoding,
+			   enum igt_color_range color_range,
 			   struct igt_fb *fb, uint64_t bo_size,
 			   unsigned bo_stride)
 {
-	/* FIXME allow the caller to pass these in */
-	enum igt_color_encoding color_encoding = IGT_COLOR_YCBCR_BT709;
-	enum igt_color_range color_range = IGT_COLOR_YCBCR_LIMITED_RANGE;
 	uint32_t flags = 0;
 
 	fb_init(fb, fd, width, height, format, modifier,
@@ -1299,8 +1494,10 @@
 unsigned int igt_create_fb(int fd, int width, int height, uint32_t format,
 			   uint64_t modifier, struct igt_fb *fb)
 {
-	return igt_create_fb_with_bo_size(fd, width, height, format, modifier, fb,
-					  0, 0);
+	return igt_create_fb_with_bo_size(fd, width, height, format, modifier,
+					  IGT_COLOR_YCBCR_BT709,
+					  IGT_COLOR_YCBCR_LIMITED_RANGE,
+					  fb, 0, 0);
 }
 
 /**
@@ -3135,7 +3332,10 @@
 
 	fb_id = igt_create_fb_with_bo_size(src->fd, src->width,
 					   src->height, dst_fourcc,
-					   dst_modifier, dst, 0,
+					   dst_modifier,
+					   IGT_COLOR_YCBCR_BT709,
+					   IGT_COLOR_YCBCR_LIMITED_RANGE,
+					   dst, 0,
 					   dst_stride);
 	igt_assert(fb_id > 0);
 
diff --git a/lib/igt_fb.h b/lib/igt_fb.h
index adefebe..e19cc5d 100644
--- a/lib/igt_fb.h
+++ b/lib/igt_fb.h
@@ -37,6 +37,7 @@
 #include <i915_drm.h>
 
 #include "igt_color_encoding.h"
+#include "igt_debugfs.h"
 
 /*
  * Internal format to denote a buffer compatible with pixman's
@@ -119,6 +120,8 @@
 unsigned int
 igt_create_fb_with_bo_size(int fd, int width, int height,
 			   uint32_t format, uint64_t modifier,
+			   enum igt_color_encoding color_encoding,
+			   enum igt_color_range color_range,
 			   struct igt_fb *fb, uint64_t bo_size,
 			   unsigned bo_stride);
 unsigned int igt_create_fb(int fd, int width, int height, uint32_t format,
@@ -158,6 +161,7 @@
 				  uint64_t modifier, unsigned stride,
 				  uint64_t *size_ret, unsigned *stride_ret,
 				  bool *is_dumb);
+void igt_fb_calc_crc(struct igt_fb *fb, igt_crc_t *crc);
 
 uint64_t igt_fb_mod_to_tiling(uint64_t modifier);
 uint64_t igt_fb_tiling_to_mod(uint64_t tiling);
diff --git a/lib/igt_kms.c b/lib/igt_kms.c
index da188a3..175e71c 100644
--- a/lib/igt_kms.c
+++ b/lib/igt_kms.c
@@ -87,24 +87,6 @@
 static char *forced_connectors[MAX_CONNECTORS + 1];
 static int forced_connectors_device[MAX_CONNECTORS + 1];
 
-static void update_edid_csum(unsigned char *edid, int cea_pos)
-{
-	int i, sum = 0;
-	struct tm *tm;
-	time_t t;
-
-	/* year of manufacture */
-	t = time(NULL);
-	tm = localtime(&t);
-	edid[17] = tm->tm_year - 90;
-
-	/* calculate checksum */
-	for (i = 0; i < 127; i++) {
-		sum = sum + edid[cea_pos + i];
-	}
-	edid[cea_pos + 127] = 256 - sum;
-}
-
 /**
  * igt_kms_get_base_edid:
  *
@@ -116,9 +98,6 @@
  *  - 800x600 60Hz
  *  - 640x480 60Hz
  *
- * This can be extended with further features using functions such as
- * #kmstest_edid_add_3d.
- *
  * Returns: a basic edid block
  */
 const unsigned char *igt_kms_get_base_edid(void)
@@ -155,9 +134,6 @@
  *  - 800x600 60Hz
  *  - 640x480 60Hz
  *
- * This can be extended with further features using functions such as
- * #kmstest_edid_add_3d.
- *
  * Returns: an alternate edid block
  */
 const unsigned char *igt_kms_get_alt_edid(void)
@@ -182,9 +158,11 @@
 	return (unsigned char *) &edid;
 }
 
+#define AUDIO_EDID_LENGTH (2 * EDID_LENGTH)
+
 static void
 generate_audio_edid(unsigned char raw_edid[static AUDIO_EDID_LENGTH],
-		    bool with_vsd, struct cea_sad *sad,
+		    bool with_vsdb, struct cea_sad *sad,
 		    struct cea_speaker_alloc *speaker_alloc)
 {
 	struct edid *edid;
@@ -192,8 +170,8 @@
 	struct edid_cea *edid_cea;
 	char *cea_data;
 	struct edid_cea_data_block *block;
-	const struct cea_vsd *vsd;
-	size_t cea_data_size, vsd_size;
+	const struct cea_vsdb *vsdb;
+	size_t cea_data_size, vsdb_size;
 
 	/* Create a new EDID from the base IGT EDID, and add an
 	 * extension that advertises audio support. */
@@ -210,11 +188,11 @@
 	cea_data_size += edid_cea_data_block_set_sad(block, sad, 1);
 
 	/* A Vendor Specific Data block is needed for HDMI audio */
-	if (with_vsd) {
+	if (with_vsdb) {
 		block = (struct edid_cea_data_block *) &cea_data[cea_data_size];
-		vsd = cea_vsd_get_hdmi_default(&vsd_size);
-		cea_data_size += edid_cea_data_block_set_vsd(block, vsd,
-							     vsd_size);
+		vsdb = cea_vsdb_get_hdmi_default(&vsdb_size);
+		cea_data_size += edid_cea_data_block_set_vsdb(block, vsdb,
+							      vsdb_size);
 	}
 
 	/* Speaker Allocation Data block */
@@ -224,8 +202,7 @@
 
 	assert(cea_data_size <= sizeof(edid_cea->data));
 
-	edid_ext_set_cea(edid_ext, cea_data_size,
-			 EDID_CEA_BASIC_AUDIO);
+	edid_ext_set_cea(edid_ext, cea_data_size, 0, EDID_CEA_BASIC_AUDIO);
 
 	edid_update_checksum(edid);
 	edid_ext_update_cea_checksum(edid_ext);
@@ -283,6 +260,117 @@
 	return raw_edid;
 }
 
+static const uint8_t edid_4k_svds[] = {
+	32 | CEA_SVD_NATIVE, /* 1080p @ 24Hz (native) */
+	5,                   /* 1080i @ 60Hz */
+	20,                  /* 1080i @ 50Hz */
+	4,                   /* 720p @ 60Hz */
+	19,                  /* 720p @ 50Hz */
+};
+
+const unsigned char *igt_kms_get_4k_edid(void)
+{
+	static unsigned char raw_edid[256] = {0};
+	struct edid *edid;
+	struct edid_ext *edid_ext;
+	struct edid_cea *edid_cea;
+	char *cea_data;
+	struct edid_cea_data_block *block;
+	/* We'll add 6 extension fields to the HDMI VSDB. */
+	char raw_hdmi[HDMI_VSDB_MIN_SIZE + 6] = {0};
+	struct hdmi_vsdb *hdmi;
+	size_t cea_data_size = 0;
+
+	/* Create a new EDID from the base IGT EDID, and add an
+	 * extension that advertises 4K support. */
+	edid = (struct edid *) raw_edid;
+	memcpy(edid, igt_kms_get_base_edid(), sizeof(struct edid));
+	edid->extensions_len = 1;
+	edid_ext = &edid->extensions[0];
+	edid_cea = &edid_ext->data.cea;
+	cea_data = edid_cea->data;
+
+	/* Short Video Descriptor */
+	block = (struct edid_cea_data_block *) &cea_data[cea_data_size];
+	cea_data_size += edid_cea_data_block_set_svd(block, edid_4k_svds,
+						     sizeof(edid_4k_svds));
+
+	/* Vendor-Specific Data Block */
+	hdmi = (struct hdmi_vsdb *) raw_hdmi;
+	hdmi->src_phy_addr[0] = 0x10;
+	hdmi->src_phy_addr[1] = 0x00;
+	/* 6 extension fields */
+	hdmi->flags1 = 0;
+	hdmi->max_tdms_clock = 0;
+	hdmi->flags2 = HDMI_VSDB_VIDEO_PRESENT;
+	hdmi->data[0] = 0x00; /* HDMI video flags */
+	hdmi->data[1] = 1 << 5; /* 1 VIC entry, 0 3D entries */
+	hdmi->data[2] = 0x01; /* 2160p, specified as short descriptor */
+
+	block = (struct edid_cea_data_block *) &cea_data[cea_data_size];
+	cea_data_size += edid_cea_data_block_set_hdmi_vsdb(block, hdmi,
+							   sizeof(raw_hdmi));
+
+	assert(cea_data_size <= sizeof(edid_cea->data));
+
+	edid_ext_set_cea(edid_ext, cea_data_size, 0, 0);
+
+	edid_update_checksum(edid);
+	edid_ext_update_cea_checksum(edid_ext);
+	return raw_edid;
+}
+
+const unsigned char *igt_kms_get_3d_edid(void)
+{
+	static unsigned char raw_edid[256] = {0};
+	struct edid *edid;
+	struct edid_ext *edid_ext;
+	struct edid_cea *edid_cea;
+	char *cea_data;
+	struct edid_cea_data_block *block;
+	/* We'll add 5 extension fields to the HDMI VSDB. */
+	char raw_hdmi[HDMI_VSDB_MIN_SIZE + 5] = {0};
+	struct hdmi_vsdb *hdmi;
+	size_t cea_data_size = 0;
+
+	/* Create a new EDID from the base IGT EDID, and add an
+	 * extension that advertises 3D support. */
+	edid = (struct edid *) raw_edid;
+	memcpy(edid, igt_kms_get_base_edid(), sizeof(struct edid));
+	edid->extensions_len = 1;
+	edid_ext = &edid->extensions[0];
+	edid_cea = &edid_ext->data.cea;
+	cea_data = edid_cea->data;
+
+	/* Short Video Descriptor */
+	block = (struct edid_cea_data_block *) &cea_data[cea_data_size];
+	cea_data_size += edid_cea_data_block_set_svd(block, edid_4k_svds,
+						     sizeof(edid_4k_svds));
+
+	/* Vendor-Specific Data Block */
+	hdmi = (struct hdmi_vsdb *) raw_hdmi;
+	hdmi->src_phy_addr[0] = 0x10;
+	hdmi->src_phy_addr[1] = 0x00;
+	/* 5 extension fields */
+	hdmi->flags1 = 0;
+	hdmi->max_tdms_clock = 0;
+	hdmi->flags2 = HDMI_VSDB_VIDEO_PRESENT;
+	hdmi->data[0] = HDMI_VSDB_VIDEO_3D_PRESENT; /* HDMI video flags */
+	hdmi->data[1] = 0; /* 0 VIC entries, 0 3D entries */
+
+	block = (struct edid_cea_data_block *) &cea_data[cea_data_size];
+	cea_data_size += edid_cea_data_block_set_hdmi_vsdb(block, hdmi,
+							   sizeof(raw_hdmi));
+
+	assert(cea_data_size <= sizeof(edid_cea->data));
+
+	edid_ext_set_cea(edid_ext, cea_data_size, 0, 0);
+
+	edid_update_checksum(edid);
+	edid_ext_update_cea_checksum(edid_ext);
+	return raw_edid;
+}
+
 const char * const igt_plane_prop_names[IGT_NUM_PLANE_PROPS] = {
 	[IGT_PLANE_SRC_X] = "SRC_X",
 	[IGT_PLANE_SRC_Y] = "SRC_Y",
@@ -595,6 +683,24 @@
 	}
 }
 
+static const char *mode_picture_aspect_name(const drmModeModeInfo *mode)
+{
+	switch (mode->flags & DRM_MODE_FLAG_PIC_AR_MASK) {
+	case DRM_MODE_FLAG_PIC_AR_NONE:
+		return NULL;
+	case DRM_MODE_FLAG_PIC_AR_4_3:
+		return "4:3";
+	case DRM_MODE_FLAG_PIC_AR_16_9:
+		return "16:9";
+	case DRM_MODE_FLAG_PIC_AR_64_27:
+		return "64:27";
+	case DRM_MODE_FLAG_PIC_AR_256_135:
+		return "256:135";
+	default:
+		return "invalid";
+	}
+}
+
 /**
  * kmstest_dump_mode:
  * @mode: libdrm mode structure
@@ -604,8 +710,9 @@
 void kmstest_dump_mode(drmModeModeInfo *mode)
 {
 	const char *stereo = mode_stereo_name(mode);
+	const char *aspect = mode_picture_aspect_name(mode);
 
-	igt_info("  %s %d %d %d %d %d %d %d %d %d 0x%x 0x%x %d%s%s%s\n",
+	igt_info("  %s %d %d %d %d %d %d %d %d %d 0x%x 0x%x %d%s%s%s%s%s%s\n",
 		 mode->name, mode->vrefresh,
 		 mode->hdisplay, mode->hsync_start,
 		 mode->hsync_end, mode->htotal,
@@ -613,7 +720,9 @@
 		 mode->vsync_end, mode->vtotal,
 		 mode->flags, mode->type, mode->clock,
 		 stereo ? " (3D:" : "",
-		 stereo ? stereo : "", stereo ? ")" : "");
+		 stereo ? stereo : "", stereo ? ")" : "",
+		 aspect ? " (PAR:" : "",
+		 aspect ? aspect : "", aspect ? ")" : "");
 }
 
 /**
@@ -969,15 +1078,13 @@
  * @drm_fd: drm file descriptor
  * @connector: connector to set @edid on
  * @edid: An EDID data block
- * @length: length of the EDID data. #EDID_LENGTH defines the standard EDID
- * length
  *
  * Set the EDID data on @connector to @edid. See also #igt_kms_get_base_edid.
  *
- * If @length is zero, the forced EDID will be removed.
+ * If @edid is NULL, the forced EDID will be removed.
  */
 void kmstest_force_edid(int drm_fd, drmModeConnector *connector,
-			const unsigned char *edid, size_t length)
+			const unsigned char *edid)
 {
 	char *path;
 	int debugfs_fd, ret;
@@ -990,10 +1097,11 @@
 
 	igt_require(debugfs_fd != -1);
 
-	if (length == 0)
+	if (edid == NULL)
 		ret = write(debugfs_fd, "reset", 5);
 	else
-		ret = write(debugfs_fd, edid, length);
+		ret = write(debugfs_fd, edid,
+			    edid_get_size((struct edid *) edid));
 	close(debugfs_fd);
 
 	/* To allow callers to always use GetConnectorCurrent we need to force a
@@ -1320,145 +1428,6 @@
 	return found;
 }
 
-struct edid_block {
-    int pos;
-    unsigned char *data;
-};
-
-#define DTD_SUPPORTS_AUDIO 1<<6
-
-static struct edid_block
-init_cea_block(const unsigned char *edid, size_t length,
-	       unsigned char *new_edid_ptr[], size_t *new_length,
-	       char extra_extensions_length,
-	       uint32_t dtd_support)
-{
-	struct edid_block new_edid;
-	int n_extensions;
-	int pos;
-	static const char cea_header_len = 4, video_block_len = 6;
-
-	igt_assert(new_edid_ptr != NULL && new_length != NULL);
-
-	*new_length = length + 128;
-
-	new_edid.data = calloc(*new_length, sizeof(*new_edid.data));
-	igt_assert_f(new_edid.data, "Failed to allocate %zu bytes for edid\n", sizeof(new_length));
-	memcpy(new_edid.data, edid, length);
-	*new_edid_ptr = new_edid.data;
-
-	n_extensions = new_edid.data[126];
-	n_extensions++;
-	new_edid.data[126] = n_extensions;
-
-	update_edid_csum(new_edid.data, 0);
-
-	/* add a cea-861 extension block */
-	pos = length;
-	new_edid.data[pos++] = 0x2;
-	new_edid.data[pos++] = 0x3;
-	new_edid.data[pos++] = cea_header_len + video_block_len +
-		extra_extensions_length;
-	new_edid.data[pos++] = dtd_support;
-
-	/* video block (id | length) */
-	new_edid.data[pos++] = 2 << 5 | (video_block_len - 1);
-	new_edid.data[pos++] = 32 | 0x80; /* 1080p @ 24Hz | (native)*/
-	new_edid.data[pos++] = 5;         /* 1080i @ 60Hz */
-	new_edid.data[pos++] = 20;        /* 1080i @ 50Hz */
-	new_edid.data[pos++] = 4;         /* 720p @ 60Hz*/
-	new_edid.data[pos++] = 19;        /* 720p @ 50Hz*/
-	new_edid.pos = pos;
-
-	return new_edid;
-}
-
-/**
- * kmstest_edid_add_3d:
- * @edid: an existing valid edid block
- * @length: length of @edid
- * @new_edid_ptr: pointer to where the new edid will be placed
- * @new_length: pointer to the size of the new edid
- *
- * Makes a copy of an existing edid block and adds an extension indicating
- * stereo 3D capabilities.
- */
-void kmstest_edid_add_3d(const unsigned char *edid, size_t length,
-			 unsigned char *new_edid_ptr[], size_t *new_length)
-{
-	char vsdb_block_len = 11;
-	struct edid_block new_edid = init_cea_block(edid, length, new_edid_ptr,
-						    new_length, vsdb_block_len,
-						    0);
-	int pos = new_edid.pos;
-
-	/* vsdb block ( id | length ) */
-	new_edid.data[pos++] = 3 << 5 | (vsdb_block_len - 1);
-	/* registration id */
-	new_edid.data[pos++] = 0x3;
-	new_edid.data[pos++] = 0xc;
-	new_edid.data[pos++] = 0x0;
-	/* source physical address */
-	new_edid.data[pos++] = 0x10;
-	new_edid.data[pos++] = 0x00;
-	/* Supports_AI ... etc */
-	new_edid.data[pos++] = 0x00;
-	/* Max TMDS Clock */
-	new_edid.data[pos++] = 0x00;
-	/* Latency present, HDMI Video Present */
-	new_edid.data[pos++] = 0x20;
-	/* HDMI Video */
-	new_edid.data[pos++] = 0x80;
-	new_edid.data[pos++] = 0x00;
-
-	update_edid_csum(new_edid.data, length);
-}
-
-/**
- * kmstest_edid_add_4k:
- * @edid: an existing valid edid block
- * @length: length of @edid
- * @new_edid_ptr: pointer to where the new edid will be placed
- * @new_length: pointer to the size of the new edid
- *
- * Makes a copy of an existing edid block and adds an extension indicating
- * a HDMI 4K mode in vsdb.
- */
-void kmstest_edid_add_4k(const unsigned char *edid, size_t length,
-			 unsigned char *new_edid_ptr[], size_t *new_length)
-{
-	char vsdb_block_len = 12;
-	struct edid_block new_edid = init_cea_block(edid, length, new_edid_ptr,
-						    new_length, vsdb_block_len,
-						    0);
-	int pos = new_edid.pos;
-
-	/* vsdb block ( id | length ) */
-	new_edid.data[pos++] = 3 << 5 | (vsdb_block_len - 1);
-	/* registration id */
-	new_edid.data[pos++] = 0x3;
-	new_edid.data[pos++] = 0xc;
-	new_edid.data[pos++] = 0x0;
-	/* source physical address */
-	new_edid.data[pos++] = 0x10;
-	new_edid.data[pos++] = 0x00;
-	/* Supports_AI ... etc */
-	new_edid.data[pos++] = 0x00;
-	/* Max TMDS Clock */
-	new_edid.data[pos++] = 0x00;
-	/* Latency present, HDMI Video Present */
-	new_edid.data[pos++] = 0x20;
-	/* HDMI Video */
-	new_edid.data[pos++] = 0x00; /* 3D present */
-
-	/* HDMI MODE LEN -- how many entries */
-	new_edid.data[pos++] = 0x20;
-	/* 2160p, specified as short descriptor */
-	new_edid.data[pos++] = 0x01;
-
-	update_edid_csum(new_edid.data, length);
-}
-
 /**
  * kmstest_unset_all_crtcs:
  * @drm_fd: the DRM fd
diff --git a/lib/igt_kms.h b/lib/igt_kms.h
index a448a00..0486737 100644
--- a/lib/igt_kms.h
+++ b/lib/igt_kms.h
@@ -194,10 +194,8 @@
 
 bool kmstest_force_connector(int fd, drmModeConnector *connector,
 			     enum kmstest_force_connector_state state);
-void kmstest_edid_add_3d(const unsigned char *edid, size_t length, unsigned char *new_edid_ptr[], size_t *new_length);
-void kmstest_edid_add_4k(const unsigned char *edid, size_t length, unsigned char *new_edid_ptr[], size_t *new_length);
 void kmstest_force_edid(int drm_fd, drmModeConnector *connector,
-			const unsigned char *edid, size_t length);
+			const unsigned char *edid);
 
 bool kmstest_get_connector_default_mode(int drm_fd, drmModeConnector *connector,
 					drmModeModeInfo *mode);
@@ -759,11 +757,12 @@
 struct cea_speaker_alloc;
 
 #define EDID_LENGTH 128
-#define AUDIO_EDID_LENGTH (2 * EDID_LENGTH)
 const unsigned char *igt_kms_get_base_edid(void);
 const unsigned char *igt_kms_get_alt_edid(void);
 const unsigned char *igt_kms_get_hdmi_audio_edid(void);
 const unsigned char *igt_kms_get_dp_audio_edid(void);
+const unsigned char *igt_kms_get_4k_edid(void);
+const unsigned char *igt_kms_get_3d_edid(void);
 
 struct udev_monitor *igt_watch_hotplug(void);
 bool igt_hotplug_detected(struct udev_monitor *mon,
diff --git a/lib/intel_chipset.h b/lib/intel_chipset.h
index 7fc9bd7..781486d 100644
--- a/lib/intel_chipset.h
+++ b/lib/intel_chipset.h
@@ -31,6 +31,8 @@
 #include <pciaccess.h>
 #include <stdbool.h>
 
+#define BIT(x) (1ul <<(x))
+
 struct pci_device *intel_get_pci_device(void);
 uint32_t intel_get_drm_devid(int fd);
 
@@ -69,6 +71,7 @@
 	bool is_cometlake : 1;
 	bool is_cannonlake : 1;
 	bool is_icelake : 1;
+	bool is_tigerlake : 1;
 	const char *codename;
 };
 
@@ -166,6 +169,7 @@
 #define IS_COFFEELAKE(devid)	(intel_get_device_info(devid)->is_coffeelake)
 #define IS_CANNONLAKE(devid)	(intel_get_device_info(devid)->is_cannonlake)
 #define IS_ICELAKE(devid)	(intel_get_device_info(devid)->is_icelake)
+#define IS_TIGERLAKE(devid)	(intel_get_device_info(devid)->is_tigerlake)
 
 #define IS_GEN(devid, x)	(intel_get_device_info(devid)->gen & (1u << ((x)-1)))
 #define AT_LEAST_GEN(devid, x)	(intel_get_device_info(devid)->gen & -(1u << ((x)-1)))
@@ -180,6 +184,7 @@
 #define IS_GEN9(devid)		IS_GEN(devid, 9)
 #define IS_GEN10(devid)		IS_GEN(devid, 10)
 #define IS_GEN11(devid)		IS_GEN(devid, 11)
+#define IS_GEN12(devid)		IS_GEN(devid, 12)
 
 #define IS_MOBILE(devid)	(intel_get_device_info(devid)->is_mobile)
 #define IS_965(devid)		AT_LEAST_GEN(devid, 4)
diff --git a/lib/intel_device_info.c b/lib/intel_device_info.c
index 88be291..4f96577 100644
--- a/lib/intel_device_info.c
+++ b/lib/intel_device_info.c
@@ -3,8 +3,6 @@
 
 #include <strings.h> /* ffs() */
 
-#define BIT(x) (1<<(x))
-
 static const struct intel_device_info intel_generic_info = {
 	.gen = 0,
 };
@@ -71,7 +69,14 @@
 	.is_bearlake = true,
 	.codename = "bearlake"
 };
-static const struct intel_device_info intel_pineview_info = {
+
+static const struct intel_device_info intel_pineview_g_info = {
+	.gen = BIT(2),
+	.is_pineview = true,
+	.codename = "pineview"
+};
+
+static const struct intel_device_info intel_pineview_m_info = {
 	.gen = BIT(2),
 	.is_mobile = true,
 	.is_pineview = true,
@@ -304,6 +309,12 @@
 	.codename = "icelake"
 };
 
+static const struct intel_device_info intel_tigerlake_info = {
+	.gen = BIT(11),
+	.is_tigerlake = true,
+	.codename = "tigerlake"
+};
+
 static const struct pci_id_match intel_device_match[] = {
 	INTEL_I810_IDS(&intel_i810_info),
 	INTEL_I815_IDS(&intel_i815_info),
@@ -319,7 +330,8 @@
 	INTEL_I945GM_IDS(&intel_i945m_info),
 
 	INTEL_G33_IDS(&intel_g33_info),
-	INTEL_PINEVIEW_IDS(&intel_pineview_info),
+	INTEL_PINEVIEW_G_IDS(&intel_pineview_g_info),
+	INTEL_PINEVIEW_M_IDS(&intel_pineview_m_info),
 
 	INTEL_I965G_IDS(&intel_i965_info),
 	INTEL_I965GM_IDS(&intel_i965m_info),
@@ -384,6 +396,8 @@
 
 	INTEL_EHL_IDS(&intel_icelake_info),
 
+	INTEL_TGL_12_IDS(&intel_tigerlake_info),
+
 	INTEL_VGA_DEVICE(PCI_MATCH_ANY, &intel_generic_info),
 };
 
diff --git a/lib/tests/igt_describe.c b/lib/tests/igt_describe.c
new file mode 100644
index 0000000..2ea47e9
--- /dev/null
+++ b/lib/tests/igt_describe.c
@@ -0,0 +1,282 @@
+/*
+ * Copyright © 2019 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 <sys/wait.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "drmtest.h"
+#include "igt_tests_common.h"
+
+IGT_TEST_DESCRIPTION("the top level description");
+static void fake_main(int argc, char **argv) {
+	igt_subtest_init(argc, argv);
+
+	igt_describe("Basic A");
+	igt_subtest("A")
+		;
+
+	igt_fixture
+		printf("should not be executed!\n");
+
+	igt_describe("Group with B, C & D");
+	igt_subtest_group {
+		igt_describe("Basic B");
+		igt_subtest("B")
+			;
+
+		if (!igt_only_list_subtests())
+			printf("should not be executed!\n");
+
+		igt_describe("Group with C & D");
+		igt_subtest_group {
+			igt_describe("Basic C");
+			igt_subtest("C")
+				printf("should not be executed!\n");
+
+			// NO DOC
+			igt_subtest("D")
+				;
+		}
+	}
+
+	// NO DOC
+	igt_subtest_group {
+		// NO DOC
+		igt_subtest("E")
+			;
+	}
+
+	// NO DOC
+	igt_subtest("F")
+		;
+
+	igt_describe("this description should be so long that it wraps itself nicely in the terminal "
+		     "this description should be so long that it wraps itself nicely in the terminal "
+		     "this description should be so long that it wraps itself nicely in the terminal "
+		     "this description should be so long that it wraps itself nicely in the terminal "
+		     "this description should be so long that it wraps itself nicely in the terminal "
+		     "this description should be so long that it wraps itself nicely in the terminal");
+	igt_subtest("G")
+		;
+
+	igt_describe("verylongwordthatshoudlbeprintedeventhoughitspastthewrppinglimit"
+		     "verylongwordthatshoudlbeprintedeventhoughitspastthewrappinglimit "
+		     "verylongwordthatshoudlbeprintedeventhoughitspastthewrappinglimit"
+		     "verylongwordthatshoudlbeprintedeventhoughitspastthewrappinglimit");
+	igt_subtest("F")
+		;
+
+	igt_exit();
+}
+
+static const char DESCRIBE_ALL_OUTPUT[] = \
+	"the top level description\n"
+	"\n"
+	"SUB A ../lib/tests/igt_describe.c:36:\n"
+	"  Basic A\n"
+	"\n"
+	"SUB B ../lib/tests/igt_describe.c:45:\n"
+	"  Group with B, C & D\n"
+	"\n"
+	"  Basic B\n"
+	"\n"
+	"SUB C ../lib/tests/igt_describe.c:54:\n"
+	"  Group with B, C & D\n"
+	"\n"
+	"  Group with C & D\n"
+	"\n"
+	"  Basic C\n"
+	"\n"
+	"SUB D ../lib/tests/igt_describe.c:58:\n"
+	"  Group with B, C & D\n"
+	"\n"
+	"  Group with C & D\n"
+	"\n"
+	"SUB E ../lib/tests/igt_describe.c:66:\n"
+	"  NO DOCUMENTATION!\n"
+	"\n"
+	"SUB F ../lib/tests/igt_describe.c:71:\n"
+	"  NO DOCUMENTATION!\n"
+	"\n"
+	"SUB G ../lib/tests/igt_describe.c:80:\n"
+	"  this description should be so long that it wraps itself nicely in the terminal this\n"
+	"  description should be so long that it wraps itself nicely in the terminal this description\n"
+	"  should be so long that it wraps itself nicely in the terminal this description should be so\n"
+	"  long that it wraps itself nicely in the terminal this description should be so long that it\n"
+	"  wraps itself nicely in the terminal this description should be so long that it wraps itself\n"
+	"  nicely in the terminal\n"
+	"\n"
+	"SUB F ../lib/tests/igt_describe.c:87:\n"
+	"  verylongwordthatshoudlbeprintedeventhoughitspastthewrppinglimitverylongwordthatshoudlbeprintedeventhoughitspastthewrappinglimit\n"
+	"  verylongwordthatshoudlbeprintedeventhoughitspastthewrappinglimitverylongwordthatshoudlbeprintedeventhoughitspastthewrappinglimit\n\n";
+
+static const char JUST_C_OUTPUT[] = \
+	"the top level description\n"
+	"\n"
+	"SUB C ../lib/tests/igt_describe.c:54:\n"
+	"  Group with B, C & D\n"
+	"\n"
+	"  Group with C & D\n"
+	"\n"
+	"  Basic C\n"
+	"\n";
+
+static void assert_pipe_empty(int fd)
+{
+	char buf[5];
+	internal_assert(0 == read(fd, buf, sizeof(buf)));
+}
+
+static void read_whole_pipe(int fd, char *buf, size_t buflen)
+{
+	ssize_t readlen;
+	off_t offset;
+
+	offset = 0;
+	while ((readlen = read(fd, buf+offset, buflen-offset))) {
+		if (readlen == -1) {
+			if (errno == EINTR) {
+				continue;
+			} else {
+				printf("read failed with %s\n", strerror(errno));
+				exit(1);
+			}
+		}
+		internal_assert(readlen != -1);
+		offset += readlen;
+	}
+}
+
+static pid_t do_fork(int argc, char **argv, int *out, int *err)
+{
+	int outfd[2], errfd[2];
+	pid_t pid;
+
+	internal_assert(pipe(outfd) != -1);
+	internal_assert(pipe(errfd) != -1);
+
+	pid = fork();
+	internal_assert(pid != -1);
+
+	if (pid == 0) {
+		while (dup2(outfd[1], STDOUT_FILENO) == -1 && errno == EINTR) {}
+		while (dup2(errfd[1], STDERR_FILENO) == -1 && errno == EINTR) {}
+
+		close(outfd[0]);
+		close(outfd[1]);
+		close(errfd[0]);
+		close(errfd[1]);
+
+		fake_main(argc, argv);
+
+		exit(-1);
+	} else {
+		/* close the writing ends */
+		close(outfd[1]);
+		close(errfd[1]);
+
+		*out = outfd[0];
+		*err = errfd[0];
+
+		return pid;
+	}
+}
+
+static int _wait(pid_t pid, int *status) {
+	int ret;
+
+	do {
+		ret = waitpid(pid, status, 0);
+	} while (ret == -1 && errno == EINTR);
+
+	return ret;
+}
+
+int main(int argc, char **argv)
+{
+	char prog[] = "igt_describe";
+	int status;
+	int outfd, errfd;
+
+	/* describe all subtest */ {
+		static char out[4096];
+		char arg[] = "--describe";
+		char *fake_argv[] = {prog, arg};
+		int fake_argc = ARRAY_SIZE(fake_argv);
+
+		pid_t pid = do_fork(fake_argc, fake_argv, &outfd, &errfd);
+
+		read_whole_pipe(outfd, out, sizeof(out));
+		assert_pipe_empty(errfd);
+
+		internal_assert(_wait(pid, &status) != -1);
+		internal_assert(WIFEXITED(status));
+		internal_assert(WEXITSTATUS(status) == IGT_EXIT_SUCCESS);
+		internal_assert(0 == strcmp(DESCRIBE_ALL_OUTPUT, out));
+
+		close(outfd);
+		close(errfd);
+	}
+
+	/* describe C using a pattern */ {
+		static char out[4096];
+		char arg[] = "--describe=C";
+		char *fake_argv[] = {prog, arg};
+		int fake_argc = ARRAY_SIZE(fake_argv);
+
+		pid_t pid = do_fork(fake_argc, fake_argv, &outfd, &errfd);
+
+		read_whole_pipe(outfd, out, sizeof(out));
+		assert_pipe_empty(errfd);
+
+		internal_assert(_wait(pid, &status) != -1);
+		internal_assert(WIFEXITED(status));
+		internal_assert(WEXITSTATUS(status) == IGT_EXIT_SUCCESS);
+		internal_assert(0 == strcmp(JUST_C_OUTPUT, out));
+
+		close(outfd);
+		close(errfd);
+	}
+
+	/* fail describing with a bad pattern */ {
+		static char err[4096];
+		char arg[] = "--describe=Z";
+		char *fake_argv[] = {prog, arg};
+		int fake_argc = ARRAY_SIZE(fake_argv);
+
+		pid_t pid = do_fork(fake_argc, fake_argv, &outfd, &errfd);
+
+		read_whole_pipe(errfd, err, sizeof(err));
+
+		internal_assert(_wait(pid, &status) != -1);
+		internal_assert(WIFEXITED(status));
+		internal_assert(WEXITSTATUS(status) == IGT_EXIT_INVALID);
+		internal_assert(strstr(err, "Unknown subtest: Z"));
+
+		close(outfd);
+		close(errfd);
+	}
+
+	return 0;
+}
diff --git a/lib/tests/igt_edid.c b/lib/tests/igt_edid.c
index a847df2..fc98f1b 100644
--- a/lib/tests/igt_edid.c
+++ b/lib/tests/igt_edid.c
@@ -76,6 +76,8 @@
 		{ "base", igt_kms_get_base_edid, 0 },
 		{ "alt", igt_kms_get_alt_edid, 0 },
 		{ "hdmi_audio", igt_kms_get_hdmi_audio_edid, 1 },
+		{ "4k", igt_kms_get_4k_edid, 1 },
+		{ "3d", igt_kms_get_3d_edid, 1 },
 		{0},
 	}, *f;
 	const unsigned char *edid;
@@ -90,6 +92,9 @@
 		igt_assert_f(edid_block_checksum(edid),
 			     "checksum failed on %s EDID", f->desc);
 		/* check extension blocks, if any */
+		igt_assert_f(edid[126] == f->exts,
+			     "unexpected number of extensions on %s EDID",
+			     f->desc);
 		for (i = 0; i < f->exts; i++)
 			igt_assert_f(edid_block_checksum(edid + (i + 1) * EDID_LENGTH),
 				     "CEA block checksum failed on %s EDID", f->desc);
diff --git a/lib/tests/igt_hdmi_inject.c b/lib/tests/igt_hdmi_inject.c
deleted file mode 100644
index 2534b1a..0000000
--- a/lib/tests/igt_hdmi_inject.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright © 2017 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 "igt.h"
-
-static const unsigned char edid_header[] = {
-	0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00
-};
-
-/**
- * Sanity check the header of the base EDID block.
- *
- * Return: 8 if the header is perfect, down to 0 if it's totally wrong.
- */
-static int edid_header_is_valid(const unsigned char *raw_edid)
-{
-	int i, score = 0;
-
-	for (i = 0; i < sizeof(edid_header); i++)
-		if (raw_edid[i] == edid_header[i])
-			score++;
-
-	return score;
-}
-
-/**
- * Sanity check the checksum of the EDID block.
- *
- * Return: 0 if the block is perfect.
- * See byte 127 of spec
- * https://en.wikipedia.org/wiki/Extended_Display_Identification_Data#EDID_1.3_data_format
- */
-static int edid_block_checksum(const unsigned char *raw_edid)
-{
-	int i;
-	unsigned char csum = 0;
-	for (i = 0; i < EDID_LENGTH; i++) {
-		csum += raw_edid[i];
-	}
-
-	return csum;
-}
-
-typedef void (*hdmi_inject_func)(const unsigned char *edid, size_t length,
-				 unsigned char *new_edid_ptr[], size_t *new_length);
-
-igt_simple_main
-{
-	const struct {
-		const char *desc;
-		hdmi_inject_func inject;
-	} funcs[] = {
-		{ "3D", kmstest_edid_add_3d },
-		{ "4k", kmstest_edid_add_4k },
-		{ NULL, NULL },
-	}, *f;
-
-	for (f = funcs; f->inject; f++) {
-		unsigned char *edid;
-		size_t length;
-
-		f->inject(igt_kms_get_base_edid(), EDID_LENGTH, &edid,
-			  &length);
-
-		igt_assert_f(edid_header_is_valid(edid) == 8,
-			     "invalid header on HDMI %s", f->desc);
-		/* check base edid block */
-		igt_assert_f(edid_block_checksum(edid) == 0,
-			     "checksum failed on HDMI %s", f->desc);
-		/* check extension block */
-		igt_assert_f(edid_block_checksum(edid + EDID_LENGTH) == 0,
-			     "CEA block checksum failed on HDMI %s", f->desc);
-	}
-}
diff --git a/lib/tests/meson.build b/lib/tests/meson.build
index b930ee6..0c35da3 100644
--- a/lib/tests/meson.build
+++ b/lib/tests/meson.build
@@ -3,11 +3,11 @@
 	'igt_can_fail',
 	'igt_can_fail_simple',
 	'igt_conflicting_args',
+	'igt_describe',
 	'igt_edid',
 	'igt_exit_handler',
 	'igt_fork',
 	'igt_fork_helper',
-	'igt_hdmi_inject',
 	'igt_list_only',
 	'igt_invalid_subtest_name',
 	'igt_no_exit',
diff --git a/man/meson.build b/man/meson.build
index 2c1396a..2187e8c 100644
--- a/man/meson.build
+++ b/man/meson.build
@@ -1,4 +1,4 @@
-build_man = get_option('build_man')
+build_man = get_option('man')
 
 manpages = [
 	'intel_aubdump',
diff --git a/meson-cross-mips.txt b/meson-cross-mips.txt
new file mode 100644
index 0000000..6350d67
--- /dev/null
+++ b/meson-cross-mips.txt
@@ -0,0 +1,12 @@
+[binaries]
+c = '/usr/bin/mips-linux-gnu-gcc'
+ar = '/usr/bin/mips-linux-gnu-gcc-ar'
+strip = '/usr/bin/mips-linux-gnu-strip'
+pkgconfig = 'pkg-config'
+exe_wrapper = 'qemu-mips'
+
+[host_machine]
+system = 'linux'
+cpu_family = 'mips'
+cpu = 'mips'
+endian = 'big'
diff --git a/meson.build b/meson.build
index b1028ee..478869e 100644
--- a/meson.build
+++ b/meson.build
@@ -77,10 +77,10 @@
   endif
 endforeach
 
-build_chamelium = get_option('build_chamelium')
-build_docs = get_option('build_docs')
-build_tests = not get_option('build_tests').disabled()
-with_libdrm = get_option('with_libdrm')
+build_chamelium = get_option('chamelium')
+build_docs = get_option('docs')
+build_tests = not get_option('tests').disabled()
+with_libdrm = get_option('libdrm_drivers')
 
 build_info = ['Build type: ' + get_option('buildtype')]
 
@@ -118,13 +118,13 @@
 libkmod = dependency('libkmod')
 libprocps = dependency('libprocps', required : true)
 
-libunwind = dependency('libunwind', required : get_option('with_libunwind'))
+libunwind = dependency('libunwind', required : get_option('libunwind'))
 build_info += 'With libunwind: @0@'.format(libunwind.found())
 
 libdw = dependency('libdw', required : true)
 pixman = dependency('pixman-1', required : true)
 
-valgrind = dependency('valgrind', required : get_option('with_valgrind'))
+valgrind = dependency('valgrind', required : get_option('valgrind'))
 if valgrind.found()
 	config.set('HAVE_VALGRIND', 1)
 endif
@@ -180,6 +180,20 @@
 dlsym = cc.find_library('dl')
 zlib = cc.find_library('z')
 
+if cc.links('''
+#include <stdint.h>
+int main(void) {
+  uint32_t x32 = 0;
+  uint64_t x64 = 0;
+  __atomic_load_n(&x32, __ATOMIC_SEQ_CST);
+  __atomic_load_n(&x64, __ATOMIC_SEQ_CST);
+  return 0;
+}''', name : 'built-in atomics')
+	libatomic = null_dep
+else
+	libatomic = cc.find_library('atomic')
+endif
+
 if cc.has_header('linux/kd.h')
 	config.set('HAVE_LINUX_KD_H', 1)
 endif
@@ -289,7 +303,8 @@
 subdir('man')
 
 gtk_doc = dependency('gtk-doc', required : build_docs)
-if build_tests and gtk_doc.found()
+python3 = find_program('python3', required : build_docs)
+if build_tests and gtk_doc.found() and python3.found()
 	subdir('docs')
 elif build_docs.enabled()
 	error('Documentation requires building tests')
diff --git a/meson_options.txt b/meson_options.txt
index 9cca0c4..8e2e1cf 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -1,6 +1,6 @@
-option('build_overlay',
+option('overlay',
        type : 'feature',
-       description : 'Build overlay')
+       description : 'Build overlay tool')
 
 option('overlay_backends',
        type : 'array',
@@ -8,37 +8,37 @@
        choices : [ 'auto', 'x', 'xv' ],
        description : 'Overlay backends to enable')
 
-option('build_chamelium',
+option('chamelium',
        type : 'feature',
-       description : 'Build chamelium test')
+       description : 'Build Chamelium test')
 
-option('with_valgrind',
+option('valgrind',
        type : 'feature',
        description : 'Build with support for valgrind annotations')
 
-option('build_man',
+option('man',
        type : 'feature',
        description : 'Build man pages')
 
-option('build_docs',
+option('docs',
        type : 'feature',
        description : 'Build documentation')
 
-option('build_tests',
+option('tests',
        type : 'feature',
        description : 'Build tests')
 
-option('with_libdrm',
+option('libdrm_drivers',
        type : 'array',
        value : ['auto'],
        choices : ['', 'auto', 'intel', 'nouveau', 'amdgpu'],
        description : 'libdrm libraries to be used')
 
-option('with_libunwind',
+option('libunwind',
        type : 'feature',
        description : 'Use libunwind')
 
-option('build_runner',
+option('runner',
        type : 'feature',
        description : 'Build test runner')
 
diff --git a/overlay/Makefile.am b/overlay/Makefile.am
index 51643e4..eeeddbb 100644
--- a/overlay/Makefile.am
+++ b/overlay/Makefile.am
@@ -31,8 +31,6 @@
 	gpu-perf.c \
 	gpu-freq.h \
 	gpu-freq.c \
-	igfx.h \
-	igfx.c \
 	overlay.h \
 	overlay.c \
 	power.h \
diff --git a/overlay/gpu-top.c b/overlay/gpu-top.c
index 61b8f62..6cec2e9 100644
--- a/overlay/gpu-top.c
+++ b/overlay/gpu-top.c
@@ -33,7 +33,6 @@
 
 #include "igt_perf.h"
 
-#include "igfx.h"
 #include "gpu-top.h"
 
 #define RING_TAIL      0x00
@@ -99,176 +98,12 @@
 	return 0;
 }
 
-struct mmio_ring {
-	int id;
-	uint32_t base;
-	void *mmio;
-	int idle, wait, sema;
-};
-
-static uint32_t mmio_ring_read(struct mmio_ring *ring, uint32_t reg)
-{
-	return igfx_read(ring->mmio, ring->base + reg);
-}
-
-static int has_execlists(void)
-{
-	int detected = 0;
-	FILE *file;
-
-	file = fopen("/sys/module/i915/parameters/enable_execlists", "r");
-	if (file) {
-		int value;
-		if (fscanf(file, "%d", &value) == 1)
-			detected = value != 0;
-		fclose(file);
-	}
-
-	return detected;
-
-}
-
-static void mmio_ring_init(struct mmio_ring *ring, void *mmio)
-{
-	uint32_t ctl;
-
-	ring->mmio = mmio;
-
-	ctl = mmio_ring_read(ring, RING_CTL);
-	if ((ctl & 1) == 0 && !has_execlists())
-		ring->id = -1;
-}
-
-static void mmio_ring_reset(struct mmio_ring *ring)
-{
-	ring->idle = 0;
-	ring->wait = 0;
-	ring->sema = 0;
-}
-
-static void mmio_ring_sample(struct mmio_ring *ring)
-{
-	uint32_t head, tail, ctl;
-
-	if (ring->id == -1)
-		return;
-
-	head = mmio_ring_read(ring, RING_HEAD) & ADDR_MASK;
-	tail = mmio_ring_read(ring, RING_TAIL) & ADDR_MASK;
-	ring->idle += head == tail;
-
-	ctl = mmio_ring_read(ring, RING_CTL);
-	ring->wait += !!(ctl & RING_WAIT);
-	ring->sema += !!(ctl & RING_WAIT_SEMAPHORE);
-}
-
-static void mmio_ring_emit(struct mmio_ring *ring, int samples, union gpu_top_payload *payload)
-{
-	if (ring->id == -1)
-		return;
-
-	payload[ring->id].u.busy = 100 - 100 * ring->idle / samples;
-	payload[ring->id].u.wait = 100 * ring->wait / samples;
-	payload[ring->id].u.sema = 100 * ring->sema / samples;
-}
-
-static void mmio_init(struct gpu_top *gt)
-{
-	struct mmio_ring render_ring = {
-		.base = 0x2030,
-		.id = 0,
-	}, bsd_ring = {
-		.base = 0x4030,
-		.id = 1,
-	}, bsd6_ring = {
-		.base = 0x12030,
-		.id = 1,
-	}, blt_ring = {
-		.base = 0x22030,
-		.id = 2,
-	};
-	const struct igfx_info *info;
-	struct pci_device *igfx;
-	void *mmio;
-	int fd[2], i;
-
-	igfx = igfx_get();
-	if (!igfx)
-		return;
-
-	if (pipe(fd) < 0)
-		return;
-
-	info = igfx_get_info(igfx);
-
-	switch (fork()) {
-	case -1: return;
-	default:
-		 fcntl(fd[0], F_SETFL, fcntl(fd[0], F_GETFL) | O_NONBLOCK);
-		 gt->fd = fd[0];
-		 gt->type = MMIO;
-		 gt->ring[0].name = "render";
-		 gt->num_rings = 1;
-		 if (info->gen >= 040) {
-			 gt->ring[1].name = "bitstream";
-			 gt->num_rings++;
-		 }
-		 if (info->gen >= 060) {
-			 gt->ring[2].name = "blt";
-			 gt->num_rings++;
-		 }
-		 close(fd[1]);
-		 return;
-	case 0:
-		 close(fd[0]);
-		 break;
-	}
-
-	mmio = igfx_get_mmio(igfx);
-	if (mmio == NULL)
-		exit(127);
-
-	mmio_ring_init(&render_ring, mmio);
-	if (info->gen >= 060) {
-		bsd_ring = bsd6_ring;
-		mmio_ring_init(&blt_ring, mmio);
-	}
-	if (info->gen >= 040) {
-		mmio_ring_init(&bsd_ring, mmio);
-	}
-
-	for (;;) {
-		union gpu_top_payload payload[MAX_RINGS];
-
-		mmio_ring_reset(&render_ring);
-		mmio_ring_reset(&bsd_ring);
-		mmio_ring_reset(&blt_ring);
-
-		for (i = 0; i < 1000; i++) {
-			mmio_ring_sample(&render_ring);
-			mmio_ring_sample(&bsd_ring);
-			mmio_ring_sample(&blt_ring);
-			usleep(1000);
-		}
-
-		memset(payload, 0, sizeof(payload));
-		mmio_ring_emit(&render_ring, 1000, payload);
-		mmio_ring_emit(&bsd_ring, 1000, payload);
-		mmio_ring_emit(&blt_ring, 1000, payload);
-		assert(write(fd[1], payload, sizeof(payload))
-		       == sizeof(payload));
-	}
-}
-
 void gpu_top_init(struct gpu_top *gt)
 {
 	memset(gt, 0, sizeof(*gt));
 	gt->fd = -1;
 
-	if (perf_init(gt) == 0)
-		return;
-
-	mmio_init(gt);
+	perf_init(gt);
 }
 
 int gpu_top_update(struct gpu_top *gt)
diff --git a/overlay/igfx.c b/overlay/igfx.c
deleted file mode 100644
index 6d82bc8..0000000
--- a/overlay/igfx.c
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * Copyright © 2013 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 <pciaccess.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdio.h>
-
-#include "igfx.h"
-#include "../lib/i915_pciids.h"
-
-static const struct igfx_info generic_info = {
-	.gen = -1,
-};
-
-#if 0
-static const struct igfx_info i81x_info = {
-	.gen = 010,
-};
-#endif
-
-static const struct igfx_info i830_info = {
-	.gen = 020,
-};
-static const struct igfx_info i845_info = {
-	.gen = 020,
-};
-static const struct igfx_info i855_info = {
-	.gen = 021,
-};
-static const struct igfx_info i865_info = {
-	.gen = 022,
-};
-
-static const struct igfx_info i915_info = {
-	.gen = 030,
-};
-static const struct igfx_info i945_info = {
-	.gen = 031,
-};
-
-static const struct igfx_info g33_info = {
-	.gen = 033,
-};
-
-static const struct igfx_info i965_info = {
-	.gen = 040,
-};
-
-static const struct igfx_info g4x_info = {
-	.gen = 045,
-};
-
-static const struct igfx_info ironlake_info = {
-	.gen = 050,
-};
-
-static const struct igfx_info sandybridge_info = {
-	.gen = 060,
-};
-
-static const struct igfx_info ivybridge_info = {
-	.gen = 070,
-};
-
-static const struct igfx_info valleyview_info = {
-	.gen = 071,
-};
-
-static const struct igfx_info haswell_info = {
-	.gen = 075,
-};
-
-static const struct igfx_info broadwell_info = {
-	.gen = 0100,
-};
-
-static const struct igfx_info cherryview_info = {
-	.gen = 0101,
-};
-
-static const struct igfx_info skylake_info = {
-	.gen = 0110,
-};
-
-static const struct igfx_info broxton_info = {
-	.gen = 0111,
-};
-
-static const struct pci_id_match match[] = {
-#if 0
-	INTEL_VGA_DEVICE(PCI_CHIP_I810, &i81x_info),
-	INTEL_VGA_DEVICE(PCI_CHIP_I810_DC100, &i81x_info),
-	INTEL_VGA_DEVICE(PCI_CHIP_I810_E, &i81x_info),
-	INTEL_VGA_DEVICE(PCI_CHIP_I815, &i81x_info),
-#endif
-
-	INTEL_I830_IDS(&i830_info),
-	INTEL_I845G_IDS(&i845_info),
-	INTEL_I85X_IDS(&i855_info),
-	INTEL_I865G_IDS(&i865_info),
-
-	INTEL_I915G_IDS(&i915_info),
-	INTEL_I915GM_IDS(&i915_info),
-	INTEL_I945G_IDS(&i945_info),
-	INTEL_I945GM_IDS(&i945_info),
-
-	INTEL_G33_IDS(&g33_info),
-	INTEL_PINEVIEW_IDS(&g33_info),
-
-	INTEL_I965G_IDS(&i965_info),
-	INTEL_I965GM_IDS(&i965_info),
-
-	INTEL_G45_IDS(&g4x_info),
-	INTEL_GM45_IDS(&g4x_info),
-
-	INTEL_IRONLAKE_D_IDS(&ironlake_info),
-	INTEL_IRONLAKE_M_IDS(&ironlake_info),
-
-	INTEL_SNB_D_IDS(&sandybridge_info),
-	INTEL_SNB_M_IDS(&sandybridge_info),
-
-	INTEL_IVB_D_IDS(&ivybridge_info),
-	INTEL_IVB_M_IDS(&ivybridge_info),
-
-	INTEL_HSW_IDS(&haswell_info),
-
-	INTEL_VLV_IDS(&valleyview_info),
-
-	INTEL_BDW_IDS(&broadwell_info),
-
-	INTEL_CHV_IDS(&cherryview_info),
-
-	INTEL_SKL_IDS(&skylake_info),
-	INTEL_BXT_IDS(&broxton_info),
-
-	INTEL_VGA_DEVICE(PCI_MATCH_ANY, &generic_info),
-
-	{ 0, 0, 0 },
-};
-
-struct pci_device *igfx_get(void)
-{
-	struct pci_device *dev;
-
-	if (pci_system_init())
-		return 0;
-
-	dev = pci_device_find_by_slot(0, 0, 2, 0);
-	if (dev == NULL || dev->vendor_id != 0x8086) {
-		struct pci_device_iterator *iter;
-
-		iter = pci_id_match_iterator_create(match);
-		if (!iter)
-			return 0;
-
-		dev = pci_device_next(iter);
-		pci_iterator_destroy(iter);
-	}
-
-	return dev;
-}
-
-const struct igfx_info *igfx_get_info(struct pci_device *dev)
-{
-	int i;
-
-	if (!dev)
-		return 0;
-
-	for (i = 0; match[i].device_id != PCI_MATCH_ANY; i++)
-		if (dev->device_id == match[i].device_id)
-			return (const struct igfx_info *)match[i].match_data;
-
-	return &generic_info;
-}
-
-static int forcewake = -1;
-
-static void
-igfx_forcewake(void)
-{
-	char buf[1024];
-	const char *path[] = {
-		"/sys/kernel/debug/dri/",
-		"/debug/dri/",
-		0,
-	};
-	int i, j;
-
-	for (j = 0; path[j]; j++) {
-		struct stat st;
-
-		if (stat(path[j], &st))
-			continue;
-
-		for (i = 0; i < 16; i++) {
-			snprintf(buf, sizeof(buf),
-				 "%s/%i/i915_forcewake_user",
-				 path[j], i);
-			forcewake = open(buf, 0);
-			if (forcewake != -1)
-				return;
-		}
-	}
-}
-
-void *igfx_get_mmio(struct pci_device *dev)
-{
-	const struct igfx_info *info;
-	int mmio_bar, mmio_size;
-	void *mmio;
-
-	info = igfx_get_info(dev);
-	if (info->gen >> 3 == 2)
-		mmio_bar = 1;
-	else
-		mmio_bar = 0;
-
-	if (info->gen < 030)
-		mmio_size = 512*1024;
-	else if (info->gen < 050)
-		mmio_size = 512*1024;
-	else
-		mmio_size = 2*1024*1024;
-
-	if (pci_device_probe(dev))
-		return 0;
-
-	if (pci_device_map_range(dev,
-				 dev->regions[mmio_bar].base_addr,
-				 mmio_size,
-				 PCI_DEV_MAP_FLAG_WRITABLE,
-				 &mmio))
-		return 0;
-
-	if (info->gen >= 060)
-		igfx_forcewake();
-
-	return mmio;
-}
-
diff --git a/overlay/igfx.h b/overlay/igfx.h
deleted file mode 100644
index c99af18..0000000
--- a/overlay/igfx.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright © 2013 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.
- *
- */
-
-#ifndef IGFX_H
-#define IGFX_H
-
-struct igfx_info {
-	int gen;
-};
-
-struct pci_device;
-
-struct pci_device *igfx_get(void);
-const struct igfx_info *igfx_get_info(struct pci_device *pci_dev);
-void *igfx_get_mmio(struct pci_device *pci_dev);
-
-static inline uint32_t
-igfx_read(void *mmio, uint32_t reg)
-{
-	return *(volatile uint32_t *)((volatile char *)mmio + reg);
-}
-
-#endif /* IGFX_H */
diff --git a/overlay/meson.build b/overlay/meson.build
index d133b6b..0a99076 100644
--- a/overlay/meson.build
+++ b/overlay/meson.build
@@ -1,4 +1,4 @@
-build_overlay = get_option('build_overlay')
+build_overlay = get_option('overlay')
 overlay_backends = get_option('overlay_backends')
 
 gpu_overlay_src = [
@@ -11,7 +11,6 @@
 	'gpu-top.c',
 	'gpu-perf.c',
 	'gpu-freq.c',
-	'igfx.c',
 	'overlay.c',
 	'power.c',
 	'rc6.c',
diff --git a/runner/executor.c b/runner/executor.c
index 7e5fbe8..52fee7d 100644
--- a/runner/executor.c
+++ b/runner/executor.c
@@ -7,6 +7,7 @@
 #include <string.h>
 #include <sys/ioctl.h>
 #include <sys/select.h>
+#include <sys/poll.h>
 #include <sys/signalfd.h>
 #include <sys/stat.h>
 #include <sys/time.h>
@@ -25,6 +26,17 @@
 	size_t num_dogs;
 } watchdogs;
 
+static void __close_watchdog(int fd)
+{
+	ssize_t ret = write(fd, "V", 1);
+
+	if (ret == -1)
+		fprintf(stderr, "Failed to stop a watchdog: %s\n",
+			strerror(errno));
+
+	close(fd);
+}
+
 static void close_watchdogs(struct settings *settings)
 {
 	size_t i;
@@ -32,10 +44,16 @@
 	if (settings && settings->log_level >= LOG_LEVEL_VERBOSE)
 		printf("Closing watchdogs\n");
 
+	if (settings == NULL && watchdogs.num_dogs != 0)
+		fprintf(stderr, "Closing watchdogs from exit handler!\n");
+
 	for (i = 0; i < watchdogs.num_dogs; i++) {
-		write(watchdogs.fds[i], "V", 1);
-		close(watchdogs.fds[i]);
+		__close_watchdog(watchdogs.fds[i]);
 	}
+
+	free(watchdogs.fds);
+	watchdogs.num_dogs = 0;
+	watchdogs.fds = NULL;
 }
 
 static void close_watchdogs_atexit(void)
@@ -81,8 +99,7 @@
 
 	for (i = 0; i < watchdogs.num_dogs; i++) {
 		if (ioctl(watchdogs.fds[i], WDIOC_SETTIMEOUT, &timeout)) {
-			write(watchdogs.fds[i], "V", 1);
-			close(watchdogs.fds[i]);
+			__close_watchdog(watchdogs.fds[i]);
 			watchdogs.fds[i] = -1;
 			continue;
 		}
@@ -102,9 +119,14 @@
 static void ping_watchdogs(void)
 {
 	size_t i;
+	int ret;
 
 	for (i = 0; i < watchdogs.num_dogs; i++) {
-		ioctl(watchdogs.fds[i], WDIOC_KEEPALIVE, 0);
+		ret = ioctl(watchdogs.fds[i], WDIOC_KEEPALIVE, NULL);
+
+		if (ret == -1)
+			fprintf(stderr, "Failed to ping a watchdog: %s\n",
+				strerror(errno));
 	}
 }
 
@@ -493,7 +515,6 @@
 			if (wd_timeout - wd_extra < 0)
 				wd_extra = wd_timeout / 2;
 			timeout_intervals = timeout / (wd_timeout - wd_extra);
-			intervals_left = timeout_intervals;
 			timeout /= timeout_intervals;
 
 			if (settings->log_level >= LOG_LEVEL_VERBOSE) {
@@ -504,6 +525,8 @@
 		}
 	}
 
+	intervals_left = timeout_intervals;
+
 	while (outfd >= 0 || errfd >= 0 || sigfd >= 0) {
 		struct timeval tv = { .tv_sec = timeout };
 
@@ -582,7 +605,6 @@
 				close(outfd);
 				close(errfd);
 				close(kmsgfd);
-				close(sigfd);
 				return -1;
 			}
 
@@ -724,7 +746,8 @@
 			} else {
 				/* We're dying, so we're taking them with us */
 				if (settings->log_level >= LOG_LEVEL_NORMAL)
-					printf("Abort requested, terminating children\n");
+					printf("Abort requested via %s, terminating children\n",
+					       strsignal(siginfo.ssi_signo));
 
 				aborting = true;
 				timeout = 2;
@@ -753,9 +776,8 @@
 					*time_spent = time;
 			}
 
-			close(sigfd);
-			sigfd = -1;
 			child = 0;
+			sigfd = -1; /* we are dying, no signal handling for now */
 		}
 	}
 
@@ -767,7 +789,6 @@
 	close(outfd);
 	close(errfd);
 	close(kmsgfd);
-	close(sigfd);
 
 	if (aborting)
 		return -1;
@@ -885,13 +906,12 @@
 			      double *time_spent,
 			      struct settings *settings,
 			      struct job_list_entry *entry,
-			      int testdirfd, int resdirfd)
+			      int testdirfd, int resdirfd,
+			      int sigfd, sigset_t *sigmask)
 {
 	int dirfd;
 	int outputs[_F_LAST];
 	int kmsgfd;
-	int sigfd;
-	sigset_t mask;
 	int outpipe[2] = { -1, -1 };
 	int errpipe[2] = { -1, -1 };
 	int outfd, errfd;
@@ -931,20 +951,6 @@
 		lseek(kmsgfd, 0, SEEK_END);
 	}
 
-	sigemptyset(&mask);
-	sigaddset(&mask, SIGCHLD);
-	sigaddset(&mask, SIGINT);
-	sigaddset(&mask, SIGTERM);
-	sigaddset(&mask, SIGQUIT);
-	sigprocmask(SIG_BLOCK, &mask, NULL);
-	sigfd = signalfd(-1, &mask, O_CLOEXEC);
-
-	if (sigfd < 0) {
-		/* TODO: Handle better */
-		fprintf(stderr, "Cannot monitor child process with signalfd\n");
-		result = -1;
-		goto out_kmsgfd;
-	}
 
 	if (settings->log_level >= LOG_LEVEL_NORMAL) {
 		char *displayname;
@@ -978,7 +984,7 @@
 		close(outpipe[0]);
 		close(errpipe[0]);
 
-		sigprocmask(SIG_UNBLOCK, &mask, NULL);
+		sigprocmask(SIG_UNBLOCK, sigmask, NULL);
 
 		setenv("IGT_SENTINEL_ON_STDERR", "1", 1);
 
@@ -1237,12 +1243,48 @@
 	close(fd);
 }
 
+static bool should_die_because_signal(int sigfd)
+{
+	struct signalfd_siginfo siginfo;
+	int ret;
+	struct pollfd sigpoll = { .fd = sigfd, .events = POLLIN | POLLRDBAND };
+
+	ret = poll(&sigpoll, 1, 0);
+
+	if (ret != 0) {
+		if (ret == -1) {
+			fprintf(stderr, "Poll on signalfd failed with %s\n", strerror(errno));
+			return true; /* something is wrong, let's die */
+		}
+
+		ret = read(sigfd, &siginfo, sizeof(siginfo));
+
+		if (ret == -1) {
+			fprintf(stderr, "Error reading from signalfd: %s\n", strerror(errno));
+			return false; /* we may want to retry later */
+		}
+
+		if (siginfo.ssi_signo == SIGCHLD) {
+			fprintf(stderr, "Runner got stray SIGCHLD while not executing any tests.\n");
+		} else {
+			fprintf(stderr, "Runner is being killed by %s\n",
+				strsignal(siginfo.ssi_signo));
+			return true;
+		}
+
+	}
+
+	return false;
+}
+
 bool execute(struct execute_state *state,
 	     struct settings *settings,
 	     struct job_list *job_list)
 {
 	struct utsname unamebuf;
 	int resdirfd, testdirfd, unamefd, timefd;
+	sigset_t sigmask;
+	int sigfd;
 	double time_spent = 0.0;
 	bool status = true;
 
@@ -1286,6 +1328,22 @@
 
 	oom_immortal();
 
+	sigemptyset(&sigmask);
+	sigaddset(&sigmask, SIGCHLD);
+	sigaddset(&sigmask, SIGINT);
+	sigaddset(&sigmask, SIGTERM);
+	sigaddset(&sigmask, SIGQUIT);
+	sigaddset(&sigmask, SIGHUP);
+	sigfd = signalfd(-1, &sigmask, O_CLOEXEC);
+	sigprocmask(SIG_BLOCK, &sigmask, NULL);
+
+	if (sigfd < 0) {
+		/* TODO: Handle better */
+		fprintf(stderr, "Cannot mask signals\n");
+		status = false;
+		goto end;
+	}
+
 	init_watchdogs(settings);
 
 	if (!uname(&unamebuf)) {
@@ -1321,12 +1379,18 @@
 		char *reason;
 		int result;
 
+		if (should_die_because_signal(sigfd)) {
+			status = false;
+			goto end;
+		}
+
 		result = execute_next_entry(state,
 					    job_list->size,
 					    &time_spent,
 					    settings,
 					    &job_list->entries[state->next],
-					    testdirfd, resdirfd);
+					    testdirfd, resdirfd,
+					    sigfd, &sigmask);
 
 		if (result < 0) {
 			status = false;
@@ -1359,8 +1423,15 @@
 		if (result > 0) {
 			double time_left = state->time_left;
 
-			close(testdirfd);
 			close_watchdogs(settings);
+			sigprocmask(SIG_UNBLOCK, &sigmask, NULL);
+			/* make sure that we do not leave any signals unhandled */
+			if (should_die_because_signal(sigfd)) {
+				status = false;
+				goto end_post_signal_restore;
+			}
+			close(sigfd);
+			close(testdirfd);
 			initialize_execute_state_from_resume(resdirfd, state, settings, job_list);
 			state->time_left = time_left;
 			return execute(state, settings, job_list);
@@ -1373,8 +1444,14 @@
 	}
 
  end:
+	close_watchdogs(settings);
+	sigprocmask(SIG_UNBLOCK, &sigmask, NULL);
+	/* make sure that we do not leave any signals unhandled */
+	if (should_die_because_signal(sigfd))
+		status = false;
+ end_post_signal_restore:
+	close(sigfd);
 	close(testdirfd);
 	close(resdirfd);
-	close_watchdogs(settings);
 	return status;
 }
diff --git a/runner/meson.build b/runner/meson.build
index 4eff193..86521f9 100644
--- a/runner/meson.build
+++ b/runner/meson.build
@@ -1,4 +1,4 @@
-build_runner = get_option('build_runner')
+build_runner = get_option('runner')
 
 runnerlib_sources = [ 'settings.c',
 		      'job_list.c',
diff --git a/runner/resultgen.c b/runner/resultgen.c
index 7b4cd51..58b9522 100644
--- a/runner/resultgen.c
+++ b/runner/resultgen.c
@@ -866,7 +866,7 @@
 
 static void override_result_single(struct json_object *obj)
 {
-	const char *errtext = NULL, *result = NULL;
+	const char *errtext = "", *result = "";
 	struct json_object *textobj;
 	bool dmesgwarns = false;
 
diff --git a/runner/settings.c b/runner/settings.c
index 9920e1a..8b39c06 100644
--- a/runner/settings.c
+++ b/runner/settings.c
@@ -227,7 +227,7 @@
 	FILE *f;
 	char *line = NULL;
 	size_t line_len = 0;
-	bool status;
+	bool status = false;
 
 	if ((f = fopen(blacklist_filename, "r")) == NULL) {
 		fprintf(stderr, "Cannot open blacklist file %s\n", blacklist_filename);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 5a428b8..7d71df8 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -90,7 +90,7 @@
 drm_import_export_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS)
 drm_import_export_LDADD = $(LDADD) -lpthread
 gem_create_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS)
-gem_create_LDADD = $(LDADD) -lpthread
+gem_create_LDADD = $(LDADD) -lpthread -latomic
 gem_close_race_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS)
 gem_close_race_LDADD = $(LDADD) -lpthread
 gem_ctx_thrash_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS)
@@ -122,6 +122,7 @@
 gem_userptr_blits_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS)
 gem_userptr_blits_LDADD = $(LDADD) -lpthread
 perf_pmu_LDADD = $(LDADD) $(top_builddir)/lib/libigt_perf.la
+sw_sync_LDADD = $(LDADD) -latomic
 
 kms_flip_LDADD = $(LDADD) -lpthread
 
diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index 027ed82..250dbd3 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -6,6 +6,7 @@
 
 AMDGPU_TESTS = \
 	amdgpu/amd_basic \
+	amdgpu/amd_bypass \
 	amdgpu/amd_color \
 	amdgpu/amd_cs_nop \
 	amdgpu/amd_prime \
diff --git a/tests/amdgpu/amd_bypass.c b/tests/amdgpu/amd_bypass.c
new file mode 100644
index 0000000..8231c76
--- /dev/null
+++ b/tests/amdgpu/amd_bypass.c
@@ -0,0 +1,378 @@
+/*
+ * Copyright 2019 Advanced Micro Devices, 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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 "igt.h"
+
+/*
+ * internal use
+ * Common test data
+ * */
+typedef struct {
+	int drm_fd;
+	int width;
+	int height;
+	enum pipe pipe_id;
+	igt_display_t display;
+	igt_plane_t *primary;
+	igt_output_t *output;
+	igt_pipe_t *pipe;
+	igt_pipe_crc_t *pipe_crc;
+	igt_crc_t crc_fb;
+	igt_crc_t crc_dprx;
+	drmModeModeInfo *mode;
+} data_t;
+
+enum pattern {
+	TEST_PATTERN_DP_COLOR_RAMP,
+	TEST_PATTERN_DP_BLACK_WHITE_VERT_LINES,
+	TEST_PATTERN_DP_BLACK_WHITE_HORZ_LINES,
+	TEST_PATTERN_DP_COLOR_SQUARES_VESA,
+	/* please don't add pattern after the below line */
+	TEST_PATTERN_MAX,
+};
+
+const char *ptnstr[TEST_PATTERN_MAX] = {
+	"DP Color Ramp",
+	"DP Vertical Lines",
+	"DP Horizontal Lines",
+	"DP Color Squares VESA"
+};
+
+/* Common test setup. */
+static void test_init(data_t *data)
+{
+	igt_display_t *display = &data->display;
+
+	/* It doesn't matter which pipe we choose on amdpgu. */
+	data->pipe_id = PIPE_A;
+	data->pipe = &data->display.pipes[data->pipe_id];
+
+	igt_display_reset(display);
+
+	data->output = igt_get_single_output_for_pipe(display, data->pipe_id);
+	igt_assert(data->output);
+
+	data->mode = igt_output_get_mode(data->output);
+	igt_assert(data->mode);
+
+	data->primary =
+		igt_pipe_get_plane_type(data->pipe, DRM_PLANE_TYPE_PRIMARY);
+
+	data->pipe_crc = igt_pipe_crc_new(data->drm_fd, data->pipe_id,
+					  AMDGPU_PIPE_CRC_SOURCE_DPRX);
+
+	igt_output_set_pipe(data->output, data->pipe_id);
+
+	data->width = data->mode->hdisplay;
+	data->height = data->mode->vdisplay;
+}
+
+/* Common test cleanup. */
+static void test_fini(data_t *data)
+{
+	igt_pipe_crc_free(data->pipe_crc);
+	igt_display_reset(&data->display);
+}
+
+/*
+ * draw the DP color ramp test pattern
+ * Reference: DP Link CTS 1.2 Core r1.1, sec. 3.1.5.1
+ */
+static void draw_dp_test_pattern_color_ramp(igt_fb_t *fb)
+{
+	const int h = 64;  /* test pattern rectangle height */
+	const int block_h = h * 4; /* block height of R-G-B-White rectangles */
+	void *ptr_fb;
+	uint8_t *data;
+	int x,y;
+	int i;
+	uint8_t val;
+
+	/*
+	 * 64-by-256 pixels per rectangle
+	 * R-G-B-White rectangle in order in vertical
+	 * duplicate in horizontal
+	 */
+	ptr_fb = igt_fb_map_buffer(fb->fd, fb);
+	igt_assert(ptr_fb);
+	data = ptr_fb + fb->offsets[0];
+
+	switch (fb->drm_format) {
+	case DRM_FORMAT_XRGB8888:
+		for (y = 0; y < fb->height; ++y) {
+			for (x = 0, val = 0; x < fb->width; ++x, ++val) {
+				i = x * 4 + y * fb->strides[0];
+
+				/* vertical R-G-B-White rect */
+				if ((y % block_h) < h) {	    /* Red */
+					data[i + 2] = val;
+					data[i + 1] = 0;
+					data[i + 0] = 0;
+				} else if ((y % block_h) < 2 * h) { /* Green */
+					data[i + 2] = 0;
+					data[i + 1] = val;
+					data[i + 0] = 0;
+				} else if ((y % block_h) < 3 * h) { /* Blue */
+					data[i + 2] = 0;
+					data[i + 1] = 0;
+					data[i + 0] = val;
+				} else {			    /* White */
+					data[i + 2] = val;
+					data[i + 1] = val;
+					data[i + 0] = val;
+				}
+			}
+		}
+		break;
+	default:
+		igt_assert_f(0, "DRM Format Invalid");
+		break;
+	}
+
+	igt_fb_unmap_buffer(fb, ptr_fb);
+}
+
+/*
+ * draw the DP vertical lines test pattern
+ * Reference: DP Link CTS 1.2 Core r1.1, sec. 3.1.5.2
+ */
+static void draw_dp_test_pattern_vert_lines(igt_fb_t *fb)
+{
+	void *ptr_fb;
+	uint8_t *data;
+	int x, y;
+	int i;
+
+	/* alternating black and white lines, 1 pixel wide */
+	ptr_fb = igt_fb_map_buffer(fb->fd, fb);
+	igt_assert(ptr_fb);
+	data = ptr_fb + fb->offsets[0];
+
+	switch (fb->drm_format) {
+	case DRM_FORMAT_XRGB8888:
+		for (y = 0; y < fb->height; ++y) {
+			for (x = 0; x < fb->width; ++x) {
+				i = x * 4 + y * fb->strides[0];
+
+				if ((x & 1) == 0) {
+					data[i + 2] = 0xff; /* R */
+					data[i + 1] = 0xff; /* G */
+					data[i + 0] = 0xff; /* B */
+				} else {
+					data[i + 2] = 0;
+					data[i + 1] = 0;
+					data[i + 0] = 0;
+				}
+			}
+		}
+		break;
+	default:
+		igt_assert_f(0, "DRM Format Invalid");
+		break;
+	}
+
+	igt_fb_unmap_buffer(fb, ptr_fb);
+}
+
+/* draw the DP horizontal lines test pattern */
+static void draw_dp_test_pattern_horz_lines(igt_fb_t *fb)
+{
+	void *ptr_fb;
+	uint8_t *data;
+	int x, y;
+	int i;
+
+	/* alternating black and white horizontal lines, 1 pixel high */
+	ptr_fb = igt_fb_map_buffer(fb->fd, fb);
+	igt_assert(ptr_fb);
+	data = ptr_fb + fb->offsets[0];
+
+	switch (fb->drm_format) {
+	case DRM_FORMAT_XRGB8888:
+		for (y = 0; y < fb->height; ++y) {
+			for (x = 0; x < fb->width; ++x) {
+
+				i = x * 4 + y * fb->strides[0];
+
+				if ((y & 1) == 0) {
+					data[i + 2] = 0xff; /* R */
+					data[i + 1] = 0xff; /* G */
+					data[i + 0] = 0xff; /* B */
+				} else {
+					data[i + 2] = 0;
+					data[i + 1] = 0;
+					data[i + 0] = 0;
+				}
+			}
+		}
+		break;
+	default:
+		igt_assert_f(0, "DRM Format Invalid");
+		break;
+	}
+
+	igt_fb_unmap_buffer(fb, ptr_fb);
+}
+
+/*
+ * draw the DP color squares VESA test pattern
+ * Reference: DP Link CTS 1.2 Core r1.1, sec. 3.1.5.3
+ */
+static void draw_dp_test_pattern_color_squares_vesa(igt_fb_t *fb)
+{
+	const int h = 64; /* test pattern square height/width */
+	const int block_h = h * 2; /* block height of the repetition pattern */
+	const int block_w = h * 8; /* block width of the repetition pattern */
+	const uint8_t rgb[3][2][8] = {
+		{/* Red table of the pattern squares */
+			{255, 255, 0, 0, 255, 255, 0, 0},
+			{0, 255, 255, 0, 0, 255, 255, 0},
+		},
+		{/* Green table */
+			{255, 255, 255, 255, 0, 0, 0, 0},
+			{0, 0, 0, 255, 255, 255, 255, 0},
+		},
+		{/* Blue table */
+			{255, 0, 255, 0, 255, 0, 255, 0},
+			{255, 0, 255, 0, 255, 0, 255, 0},
+		},
+	};
+
+	void *ptr_fb;
+	uint8_t *data;
+	int x, y;
+	int i, j, k;
+
+	ptr_fb = igt_fb_map_buffer(fb->fd, fb);
+	igt_assert(ptr_fb);
+	data = ptr_fb + fb->offsets[0];
+
+	switch (fb->drm_format) {
+	case DRM_FORMAT_XRGB8888:
+		for (y = 0; y < fb->height; ++y) {
+			for (x = 0; x < fb->width; ++x) {
+
+				i = x * 4 + y * fb->strides[0];
+				j = (y % block_h) / h;
+				k = (x % block_w) / h;
+
+				data[i + 2] = rgb[0][j][k]; /* R */
+				data[i + 1] = rgb[1][j][k]; /* G */
+				data[i + 0] = rgb[2][j][k]; /* B */
+			}
+		}
+		break;
+
+	default:
+		igt_assert_f(0, "DRM Format Invalid");
+		break;
+	}
+
+
+	igt_fb_unmap_buffer(fb, ptr_fb);
+}
+
+/* generate test pattern and fills a FB */
+static void generate_test_pattern(igt_fb_t *fb, data_t *data, enum pattern ptn)
+{
+	igt_assert(fb->fd && (ptn < TEST_PATTERN_MAX));
+
+	if (ptn == TEST_PATTERN_DP_COLOR_RAMP) {
+		draw_dp_test_pattern_color_ramp(fb);
+	} else if (ptn == TEST_PATTERN_DP_BLACK_WHITE_VERT_LINES) {
+		draw_dp_test_pattern_vert_lines(fb);
+	} else if (ptn == TEST_PATTERN_DP_BLACK_WHITE_HORZ_LINES) {
+		draw_dp_test_pattern_horz_lines(fb);
+	} else if (ptn == TEST_PATTERN_DP_COLOR_SQUARES_VESA) {
+		draw_dp_test_pattern_color_squares_vesa(fb);
+	}
+}
+
+static void bypass_8bpc_test(data_t *data)
+{
+	igt_display_t *display = &data->display;
+	igt_fb_t fb;
+	enum pattern ptn;
+
+	test_init(data);
+
+	igt_create_fb(data->drm_fd, data->width, data->height,
+		      DRM_FORMAT_XRGB8888, LOCAL_DRM_FORMAT_MOD_NONE, &fb);
+
+	/*
+	 * Settings:
+	 *   no degamma
+	 *   no regamma
+	 *   no CTM
+	 */
+	igt_pipe_obj_replace_prop_blob(data->pipe, IGT_CRTC_DEGAMMA_LUT, NULL, 0);
+	igt_pipe_obj_replace_prop_blob(data->pipe, IGT_CRTC_GAMMA_LUT, NULL, 0);
+	igt_pipe_obj_replace_prop_blob(data->pipe, IGT_CRTC_CTM, NULL, 0);
+
+	igt_plane_set_fb(data->primary, &fb);
+	igt_display_commit_atomic(display, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
+
+	/* traverse all the test pattern to validate 8bpc bypass mode */
+	for (ptn = TEST_PATTERN_DP_COLOR_RAMP; ptn < TEST_PATTERN_MAX; ++ptn) {
+		igt_info("Test Pattern: %s\n", ptnstr[ptn]);
+
+		generate_test_pattern(&fb, data, ptn);
+
+		/* Grab FB and DPRX CRCs and compare */
+		igt_fb_calc_crc(&fb, &data->crc_fb);
+		igt_pipe_crc_collect_crc(data->pipe_crc, &data->crc_dprx);
+
+		igt_assert_crc_equal(&data->crc_fb, &data->crc_dprx);
+	}
+
+	igt_plane_set_fb(data->primary, NULL);
+	test_fini(data);
+	igt_remove_fb(data->drm_fd, &fb);
+}
+
+igt_main
+{
+	data_t data;
+	memset(&data, 0, sizeof(data));
+
+	igt_skip_on_simulation();
+
+	igt_fixture {
+		data.drm_fd = drm_open_driver_master(DRIVER_AMDGPU);
+		if (data.drm_fd == -1)
+			igt_skip("Not an amdgpu driver.\n");
+		igt_require_pipe_crc(data.drm_fd);
+
+		kmstest_set_vt_graphics_mode();
+
+		igt_display_require(&data.display, data.drm_fd);
+		igt_require(data.display.is_atomic);
+		igt_display_require_output(&data.display);
+	}
+
+	igt_subtest("8bpc-bypass-mode")
+		bypass_8bpc_test(&data);
+
+	igt_fixture {
+		igt_display_fini(&data.display);
+	}
+}
diff --git a/tests/amdgpu/meson.build b/tests/amdgpu/meson.build
index 4208637..b798229 100644
--- a/tests/amdgpu/meson.build
+++ b/tests/amdgpu/meson.build
@@ -4,6 +4,7 @@
 if libdrm_amdgpu.found()
 	amdgpu_progs += [ 'amd_abm',
 			  'amd_basic',
+			  'amd_bypass',
 			  'amd_color',
 			  'amd_cs_nop',
 			  'amd_prime',
diff --git a/tests/i915/gem_create.c b/tests/i915/gem_create.c
index 43cbf45..aed7d1c 100644
--- a/tests/i915/gem_create.c
+++ b/tests/i915/gem_create.c
@@ -45,6 +45,7 @@
 #include <sys/time.h>
 #include <getopt.h>
 #include <pthread.h>
+#include <stdatomic.h>
 
 #include <drm.h>
 
@@ -156,7 +157,14 @@
 	gem_close(fd, create.handle);
 }
 
-static uint64_t get_npages(uint64_t *global, uint64_t npages)
+static uint64_t atomic_compare_swap_u64(_Atomic(uint64_t) *ptr,
+					uint64_t oldval, uint64_t newval)
+{
+	atomic_compare_exchange_strong(ptr, &oldval, newval);
+	return oldval;
+}
+
+static uint64_t get_npages(_Atomic(uint64_t) *global, uint64_t npages)
 {
 	uint64_t try, old, max;
 
@@ -165,13 +173,13 @@
 		old = max;
 		try = 1 + npages % (max / 2);
 		max -= try;
-	} while ((max = __sync_val_compare_and_swap(global, old, max)) != old);
+	} while ((max = atomic_compare_swap_u64(global, old, max)) != old);
 
 	return try;
 }
 
 struct thread_clear {
-	uint64_t max;
+	_Atomic(uint64_t) max;
 	int timeout;
 	int i915;
 };
@@ -179,6 +187,7 @@
 static void *thread_clear(void *data)
 {
 	struct thread_clear *arg = data;
+	unsigned long checked = 0;
 	int i915 = arg->i915;
 
 	igt_until_timeout(arg->timeout) {
@@ -201,11 +210,12 @@
 			igt_assert_eq_u64(x, 0);
 		}
 		gem_close(i915, create.handle);
+		checked += npages;
 
-		__sync_add_and_fetch(&arg->max, npages);
+		atomic_fetch_add(&arg->max, npages);
 	}
 
-	return NULL;
+	return (void *)(uintptr_t)checked;
 }
 
 static void always_clear(int i915, int timeout)
@@ -216,12 +226,19 @@
 		.max = intel_get_avail_ram_mb() << (20 - 12), /* in pages */
 	};
 	const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+	unsigned long checked;
 	pthread_t thread[ncpus];
+	void *result;
 
 	for (int i = 0; i < ncpus; i++)
 		pthread_create(&thread[i], NULL, thread_clear, &arg);
-	for (int i = 0; i < ncpus; i++)
-		pthread_join(thread[i], NULL);
+
+	checked = 0;
+	for (int i = 0; i < ncpus; i++) {
+		pthread_join(thread[i], &result);
+		checked += (uintptr_t)result;
+	}
+	igt_info("Checked %'lu page allocations\n", checked);
 }
 
 static void size_update(int fd)
diff --git a/tests/i915/gem_ctx_isolation.c b/tests/i915/gem_ctx_isolation.c
index 5b054c8..c430239 100644
--- a/tests/i915/gem_ctx_isolation.c
+++ b/tests/i915/gem_ctx_isolation.c
@@ -33,7 +33,6 @@
 #define DIRTY2 0x2
 #define RESET 0x4
 
-#define BIT(x) (1ul << (x))
 #define ENGINE(x, y) BIT(4*(x) + (y))
 
 enum {
diff --git a/tests/i915/gem_ctx_param.c b/tests/i915/gem_ctx_param.c
index fa0ab52..bd1ee39 100644
--- a/tests/i915/gem_ctx_param.c
+++ b/tests/i915/gem_ctx_param.c
@@ -32,8 +32,6 @@
 
 IGT_TEST_DESCRIPTION("Basic test for context set/get param input validation.");
 
-#define BIT(x) (1ul << (x))
-
 #define NEW_CTX	BIT(0)
 #define USER BIT(1)
 
diff --git a/tests/i915/gem_ctx_switch.c b/tests/i915/gem_ctx_switch.c
index 647911d..c071def 100644
--- a/tests/i915/gem_ctx_switch.c
+++ b/tests/i915/gem_ctx_switch.c
@@ -55,7 +55,7 @@
 
 static int measure_qlen(int fd,
 			struct drm_i915_gem_execbuffer2 *execbuf,
-			unsigned int *engine, unsigned int nengine,
+			const struct intel_engine_data *engines,
 			int timeout)
 {
 	const struct drm_i915_gem_exec_object2 * const obj =
@@ -63,15 +63,17 @@
 	uint32_t ctx[64];
 	int min = INT_MAX, max = 0;
 
-	for (int i = 0; i < ARRAY_SIZE(ctx); i++)
+	for (int i = 0; i < ARRAY_SIZE(ctx); i++) {
 		ctx[i] = gem_context_create(fd);
+		gem_context_set_all_engines(fd, ctx[i]);
+	}
 
-	for (unsigned int n = 0; n < nengine; n++) {
+	for (unsigned int n = 0; n < engines->nengines; n++) {
 		uint64_t saved = execbuf->flags;
 		struct timespec tv = {};
 		int q;
 
-		execbuf->flags |= engine[n];
+		execbuf->flags |= engines->engines[n].flags;
 
 		for (int i = 0; i < ARRAY_SIZE(ctx); i++) {
 			execbuf->rsvd1 = ctx[i];
@@ -90,7 +92,8 @@
 		 * Be conservative and aim not to overshoot timeout, so scale
 		 * down by 8 for hopefully a max of 12.5% error.
 		 */
-		q = ARRAY_SIZE(ctx) * timeout * 1e9 / igt_nsec_elapsed(&tv) / 8 + 1;
+		q = ARRAY_SIZE(ctx) * timeout * 1e9 / igt_nsec_elapsed(&tv) /
+		    8 + 1;
 		if (q < min)
 			min = q;
 		if (q > max)
@@ -107,7 +110,7 @@
 }
 
 static void single(int fd, uint32_t handle,
-		   const struct intel_execution_engine *e,
+		   const struct intel_execution_engine2 *e2,
 		   unsigned flags,
 		   const int ncpus,
 		   int timeout)
@@ -125,13 +128,14 @@
 	shared = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
 	igt_assert(shared != MAP_FAILED);
 
-	gem_require_ring(fd, e->exec_id | e->flags);
-
 	for (n = 0; n < 64; n++) {
 		if (flags & QUEUE)
 			contexts[n] = gem_queue_create(fd);
 		else
 			contexts[n] = gem_context_create(fd);
+
+		if (gem_context_has_engine_map(fd, 0))
+			gem_context_set_all_engines(fd, contexts[n]);
 	}
 
 	memset(&obj, 0, sizeof(obj));
@@ -152,12 +156,12 @@
 	execbuf.buffers_ptr = to_user_pointer(&obj);
 	execbuf.buffer_count = 1;
 	execbuf.rsvd1 = contexts[0];
-	execbuf.flags = e->exec_id | e->flags;
+	execbuf.flags = e2->flags;
 	execbuf.flags |= LOCAL_I915_EXEC_HANDLE_LUT;
 	execbuf.flags |= LOCAL_I915_EXEC_NO_RELOC;
 	igt_require(__gem_execbuf(fd, &execbuf) == 0);
 	if (__gem_execbuf(fd, &execbuf)) {
-		execbuf.flags = e->exec_id | e->flags;
+		execbuf.flags = e2->flags;
 		reloc.target_handle = obj.handle;
 		gem_execbuf(fd, &execbuf);
 	}
@@ -190,7 +194,8 @@
 		clock_gettime(CLOCK_MONOTONIC, &now);
 
 		igt_info("[%d] %s: %'u cycles: %.3fus%s\n",
-			 child, e->name, count, elapsed(&start, &now)*1e6 / count,
+			 child, e2->name, count,
+			 elapsed(&start, &now) * 1e6 / count,
 			 flags & INTERRUPTIBLE ? " (interruptible)" : "");
 
 		shared[child].elapsed = elapsed(&start, &now);
@@ -209,7 +214,7 @@
 		}
 
 		igt_info("Total %s: %'lu cycles: %.3fus%s\n",
-			 e->name, total, max*1e6 / total,
+			 e2->name, total, max*1e6 / total,
 			 flags & INTERRUPTIBLE ? " (interruptible)" : "");
 	}
 
@@ -223,25 +228,20 @@
 {
 	struct drm_i915_gem_execbuffer2 execbuf;
 	struct drm_i915_gem_exec_object2 obj[2];
-	unsigned int engine[16], e;
-	const char *name[16];
+	struct intel_engine_data engines = { };
 	uint32_t contexts[65];
-	unsigned int nengine;
 	int n, qlen;
 
-	nengine = 0;
-	for_each_physical_engine(fd, e) {
-		engine[nengine] = e;
-		name[nengine] = e__->name;
-		nengine++;
-	}
-	igt_require(nengine);
+	engines = intel_init_engine_list(fd, 0);
+	igt_require(engines.nengines);
 
 	for (n = 0; n < ARRAY_SIZE(contexts); n++) {
 		if (flags & QUEUE)
 			contexts[n] = gem_queue_create(fd);
 		else
 			contexts[n] = gem_context_create(fd);
+
+		gem_context_set_all_engines(fd, contexts[n]);
 	}
 
 	memset(obj, 0, sizeof(obj));
@@ -256,7 +256,7 @@
 	igt_require(__gem_execbuf(fd, &execbuf) == 0);
 	gem_sync(fd, handle);
 
-	qlen = measure_qlen(fd, &execbuf, engine, nengine, timeout);
+	qlen = measure_qlen(fd, &execbuf, &engines, timeout);
 	igt_info("Using timing depth of %d batches\n", qlen);
 
 	execbuf.buffers_ptr = to_user_pointer(obj);
@@ -264,13 +264,15 @@
 
 	for (int pot = 2; pot <= 64; pot *= 2) {
 		for (int nctx = pot - 1; nctx <= pot + 1; nctx++) {
-			igt_fork(child, nengine) {
+			igt_fork(child, engines.nengines) {
 				struct timespec start, now;
 				unsigned int count = 0;
 
 				obj[0].handle = gem_create(fd, 4096);
-				execbuf.flags |= engine[child];
-				for (int loop = 0; loop < ARRAY_SIZE(contexts); loop++) {
+				execbuf.flags |= engines.engines[child].flags;
+				for (int loop = 0;
+				     loop < ARRAY_SIZE(contexts);
+				     loop++) {
 					execbuf.rsvd1 = contexts[loop];
 					gem_execbuf(fd, &execbuf);
 				}
@@ -279,7 +281,8 @@
 				clock_gettime(CLOCK_MONOTONIC, &start);
 				do {
 					for (int loop = 0; loop < qlen; loop++) {
-						execbuf.rsvd1 = contexts[loop % nctx];
+						execbuf.rsvd1 =
+							contexts[loop % nctx];
 						gem_execbuf(fd, &execbuf);
 					}
 					count += qlen;
@@ -291,8 +294,11 @@
 				gem_close(fd, obj[0].handle);
 
 				igt_info("[%d:%d] %s: %'u cycles: %.3fus%s (elapsed: %.3fs)\n",
-					 nctx, child, name[child], count, elapsed(&start, &now)*1e6 / count,
-					 flags & INTERRUPTIBLE ? " (interruptible)" : "",
+					 nctx, child,
+					 engines.engines[child].name, count,
+					 elapsed(&start, &now) * 1e6 / count,
+					 flags & INTERRUPTIBLE ?
+					 " (interruptible)" : "",
 					 elapsed(&start, &now));
 			}
 			igt_waitchildren();
@@ -306,6 +312,7 @@
 igt_main
 {
 	const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+	const struct intel_execution_engine2 *e2;
 	const struct intel_execution_engine *e;
 	static const struct {
 		const char *name;
@@ -338,7 +345,46 @@
 		igt_fork_hang_detector(fd);
 	}
 
+	/* Legacy testing must be first. */
 	for (e = intel_execution_engines; e->name; e++) {
+		struct intel_execution_engine2 e2__;
+
+		e2__ = gem_eb_flags_to_engine(e->exec_id | e->flags);
+		if (e2__.flags == -1)
+			continue; /* I915_EXEC_BSD with no ring selectors */
+
+		e2 = &e2__;
+
+		for (typeof(*phases) *p = phases; p->name; p++) {
+			igt_subtest_group {
+				igt_fixture {
+					gem_require_ring(fd, e2->flags);
+					if (p->require)
+						igt_require(p->require(fd));
+				}
+
+				igt_subtest_f("legacy-%s%s", e->name, p->name)
+					single(fd, light, e2, p->flags, 1, 5);
+
+				igt_skip_on_simulation();
+
+				igt_subtest_f("legacy-%s-heavy%s",
+					      e->name, p->name)
+					single(fd, heavy, e2, p->flags, 1, 5);
+				igt_subtest_f("legacy-%s-forked%s",
+					      e->name, p->name)
+					single(fd, light, e2, p->flags, ncpus,
+					       150);
+				igt_subtest_f("legacy-%s-forked-heavy%s",
+					      e->name, p->name)
+					single(fd, heavy, e2, p->flags, ncpus,
+					       150);
+			}
+		}
+	}
+
+	/* Must come after legacy subtests. */
+	__for_each_physical_engine(fd, e2) {
 		for (typeof(*phases) *p = phases; p->name; p++) {
 			igt_subtest_group {
 				igt_fixture {
@@ -346,33 +392,36 @@
 						igt_require(p->require(fd));
 				}
 
-				igt_subtest_f("%s%s%s", e->exec_id == 0 ? "basic-" : "", e->name, p->name)
-					single(fd, light, e, p->flags, 1, 5);
+				igt_subtest_f("%s%s", e2->name, p->name)
+					single(fd, light, e2, p->flags, 1, 5);
 
 				igt_skip_on_simulation();
 
-				igt_subtest_f("%s%s-heavy%s", e->exec_id == 0 ? "basic-" : "", e->name, p->name)
-					single(fd, heavy, e, p->flags, 1, 5);
-				igt_subtest_f("forked-%s%s", e->name, p->name)
-					single(fd, light, e, p->flags, ncpus, 150);
-				igt_subtest_f("forked-%s-heavy%s", e->name, p->name)
-					single(fd, heavy, e, p->flags, ncpus, 150);
+				igt_subtest_f("%s-heavy%s", e2->name, p->name)
+					single(fd, heavy, e2, p->flags, 1, 5);
+				igt_subtest_f("%s-forked%s", e2->name, p->name)
+					single(fd, light, e2, p->flags, ncpus,
+					       150);
+				igt_subtest_f("%s-forked-heavy%s",
+					      e2->name, p->name)
+					single(fd, heavy, e2, p->flags, ncpus,
+					       150);
 			}
 		}
 	}
 
-	igt_subtest("basic-all-light")
+	igt_subtest("all-light")
 		all(fd, light, 0, 5);
-	igt_subtest("basic-all-heavy")
+	igt_subtest("all-heavy")
 		all(fd, heavy, 0, 5);
 
 	igt_subtest_group {
 		igt_fixture {
 			igt_require(gem_has_queues(fd));
 		}
-		igt_subtest("basic-queue-light")
+		igt_subtest("queue-light")
 			all(fd, light, QUEUE, 5);
-		igt_subtest("basic-queue-heavy")
+		igt_subtest("queue-heavy")
 			all(fd, heavy, QUEUE, 5);
 	}
 
diff --git a/tests/i915/gem_eio.c b/tests/i915/gem_eio.c
index 5396a04..4d7362d 100644
--- a/tests/i915/gem_eio.c
+++ b/tests/i915/gem_eio.c
@@ -71,10 +71,11 @@
 
 	igt_nsec_elapsed(&ts);
 
+	igt_kmsg(KMSG_DEBUG "Forcing GPU reset\n");
 	igt_force_gpu_reset(fd);
 
 	/* And just check the gpu is indeed running again */
-	igt_debug("Checking that the GPU recovered\n");
+	igt_kmsg(KMSG_DEBUG "Checking that the GPU recovered\n");
 	gem_test_engine(fd, ALL_ENGINES);
 	igt_drop_caches_set(fd, DROP_ACTIVE);
 
@@ -175,7 +176,7 @@
 	struct igt_spin_factory opts = {
 		.ctx = ctx,
 		.engine = flags,
-		.flags = IGT_SPIN_FAST,
+		.flags = IGT_SPIN_FAST | IGT_SPIN_FENCE_OUT,
 	};
 
 	if (gem_can_store_dword(fd, opts.engine))
@@ -270,12 +271,12 @@
 		igt_stats_push(st, igt_nsec_elapsed(&ts));
 }
 
-static void check_wait_elapsed(int fd, igt_stats_t *st)
+static void check_wait_elapsed(const char *prefix, int fd, igt_stats_t *st)
 {
 	double med, max, limit;
 
-	igt_info("Completed %d resets, wakeups took %.3f+-%.3fms (min:%.3fms, median:%.3fms, max:%.3fms)\n",
-		 st->n_values,
+	igt_info("%s: completed %d resets, wakeups took %.3f+-%.3fms (min:%.3fms, median:%.3fms, max:%.3fms)\n",
+		 prefix, st->n_values,
 		 igt_stats_get_mean(st)*1e-6,
 		 igt_stats_get_std_deviation(st)*1e-6,
 		 igt_stats_get_min(st)*1e-6,
@@ -715,8 +716,8 @@
 	close(fd);
 }
 
-static void reset_stress(int fd,
-			 uint32_t ctx0, unsigned int engine,
+static void reset_stress(int fd, uint32_t ctx0,
+			 const char *name, unsigned int engine,
 			 unsigned int flags)
 {
 	const uint32_t bbe = MI_BATCH_BUFFER_END;
@@ -759,6 +760,7 @@
 
 		/* Wedge after a small delay. */
 		check_wait(fd, obj.handle, 100e3, &stats);
+		igt_assert_eq(sync_fence_status(hang->out_fence), -EIO);
 
 		/* Unwedge by forcing a reset. */
 		igt_assert(i915_reset_control(true));
@@ -782,7 +784,7 @@
 		igt_spin_free(fd, hang);
 		gem_context_destroy(fd, ctx);
 	}
-	check_wait_elapsed(fd, &stats);
+	check_wait_elapsed(name, fd, &stats);
 	igt_stats_fini(&stats);
 
 	gem_close(fd, obj.handle);
@@ -797,7 +799,7 @@
 	unsigned int engine;
 
 	for_each_engine(fd, engine)
-		reset_stress(fd, ctx0, engine, flags);
+		reset_stress(fd, ctx0, e__->name, engine, flags);
 
 	gem_context_destroy(fd, ctx0);
 }
diff --git a/tests/i915/gem_mmap_wc.c b/tests/i915/gem_mmap_wc.c
index c9e5bf2..375a9b5 100644
--- a/tests/i915/gem_mmap_wc.c
+++ b/tests/i915/gem_mmap_wc.c
@@ -300,8 +300,8 @@
 
 	memset(ptr, 0xcc, OBJECT_SIZE);
 	gem_close(fd, handle);
-	for (i = 0; i < 4096; i++)
-		igt_assert(ptr[i*4096+i] == 0xcc);
+	for (i = 0; i < OBJECT_SIZE / 4096; i++)
+		igt_assert(ptr[i * 4096 + i] == 0xcc);
 
 	munmap(ptr, OBJECT_SIZE);
 }
diff --git a/tests/i915/gem_pread.c b/tests/i915/gem_pread.c
index c647876..0d3e10b 100644
--- a/tests/i915/gem_pread.c
+++ b/tests/i915/gem_pread.c
@@ -159,7 +159,7 @@
 		dst_user = malloc(object_size);
 	}
 
-	igt_subtest("basic") {
+	igt_subtest("bench") {
 		for (count = 1; count <= 1<<17; count <<= 1) {
 			struct timeval start, end;
 
diff --git a/tests/i915/gem_pwrite.c b/tests/i915/gem_pwrite.c
index 97703a2..37e9787 100644
--- a/tests/i915/gem_pwrite.c
+++ b/tests/i915/gem_pwrite.c
@@ -286,7 +286,7 @@
 		src_user = malloc(object_size);
 	}
 
-	igt_subtest("basic") {
+	igt_subtest("bench") {
 		for (count = 1; count <= 1<<17; count <<= 1) {
 			struct timeval start, end;
 
diff --git a/tests/i915/gem_spin_batch.c b/tests/i915/gem_spin_batch.c
index 3b4f907..e0623f4 100644
--- a/tests/i915/gem_spin_batch.c
+++ b/tests/i915/gem_spin_batch.c
@@ -32,7 +32,8 @@
 		     "'%s' != '%s' (%lld not within %d%% tolerance of %lld)\n",\
 		     #x, #ref, (long long)x, tolerance, (long long)ref)
 
-static void spin(int fd, unsigned int engine, unsigned int timeout_sec)
+static void spin(int fd, const struct intel_execution_engine2 *e2,
+		 unsigned int timeout_sec)
 {
 	const uint64_t timeout_100ms = 100000000LL;
 	unsigned long loops = 0;
@@ -41,9 +42,9 @@
 	struct timespec itv = { };
 	uint64_t elapsed;
 
-	spin = __igt_spin_new(fd, .engine = engine);
+	spin = __igt_spin_new(fd, .engine = e2->flags);
 	while ((elapsed = igt_nsec_elapsed(&tv)) >> 30 < timeout_sec) {
-		igt_spin_t *next = __igt_spin_new(fd, .engine = engine);
+		igt_spin_t *next = __igt_spin_new(fd, .engine = e2->flags);
 
 		igt_spin_set_timeout(spin,
 				     timeout_100ms - igt_nsec_elapsed(&itv));
@@ -69,13 +70,14 @@
 #define RESUBMIT_NEW_CTX     (1 << 0)
 #define RESUBMIT_ALL_ENGINES (1 << 1)
 
-static void spin_resubmit(int fd, unsigned int engine, unsigned int flags)
+static void spin_resubmit(int fd, const struct intel_execution_engine2 *e2,
+			  unsigned int flags)
 {
 	const uint32_t ctx0 = gem_context_create(fd);
 	const uint32_t ctx1 = (flags & RESUBMIT_NEW_CTX) ?
 		gem_context_create(fd) : ctx0;
-	igt_spin_t *spin = __igt_spin_new(fd, .ctx = ctx0, .engine = engine);
-	unsigned int other;
+	igt_spin_t *spin = __igt_spin_new(fd, .ctx = ctx0, .engine = e2->flags);
+	const struct intel_execution_engine2 *other;
 
 	struct drm_i915_gem_execbuffer2 eb = {
 		.buffer_count = 1,
@@ -83,16 +85,23 @@
 		.rsvd1 = ctx1,
 	};
 
+	igt_assert(gem_context_has_engine_map(fd, 0) ||
+		   !(flags & RESUBMIT_ALL_ENGINES));
+
 	if (flags & RESUBMIT_ALL_ENGINES) {
-		for_each_physical_engine(fd, other) {
-			if  (other == engine)
+		gem_context_set_all_engines(fd, ctx0);
+		if (ctx0 != ctx1)
+			gem_context_set_all_engines(fd, ctx1);
+
+		for_each_context_engine(fd, ctx1, other) {
+			if (gem_engine_is_equal(other, e2))
 				continue;
 
-			eb.flags = other;
+			eb.flags = other->flags;
 			gem_execbuf(fd, &eb);
 		}
 	} else {
-		eb.flags = engine;
+		eb.flags = e2->flags;
 		gem_execbuf(fd, &eb);
 	}
 
@@ -115,12 +124,12 @@
 
 static void spin_on_all_engines(int fd, unsigned int timeout_sec)
 {
-	unsigned engine;
+	const struct intel_execution_engine2 *e2;
 
-	for_each_physical_engine(fd, engine) {
+	__for_each_physical_engine(fd, e2) {
 		igt_fork(child, 1) {
 			igt_install_exit_handler(spin_exit_handler);
-			spin(fd, engine, timeout_sec);
+			spin(fd, e2, timeout_sec);
 		}
 	}
 
@@ -129,7 +138,9 @@
 
 igt_main
 {
+	const struct intel_execution_engine2 *e2;
 	const struct intel_execution_engine *e;
+	struct intel_execution_engine2 e2__;
 	int fd = -1;
 
 	igt_skip_on_simulation();
@@ -141,20 +152,36 @@
 	}
 
 	for (e = intel_execution_engines; e->name; e++) {
-		igt_subtest_f("basic-%s", e->name)
-			spin(fd, e->exec_id, 3);
+		e2__ = gem_eb_flags_to_engine(e->exec_id | e->flags);
+		if (e2__.flags == -1)
+			continue;
+		e2 = &e2__;
 
-		igt_subtest_f("resubmit-%s", e->name)
-			spin_resubmit(fd, e->exec_id, 0);
+		igt_subtest_f("legacy-%s", e->name)
+			spin(fd, e2, 3);
 
-		igt_subtest_f("resubmit-new-%s", e->name)
-			spin_resubmit(fd, e->exec_id, RESUBMIT_NEW_CTX);
+		igt_subtest_f("legacy-resubmit-%s", e->name)
+			spin_resubmit(fd, e2, 0);
 
-		igt_subtest_f("resubmit-all-%s", e->name)
-			spin_resubmit(fd, e->exec_id, RESUBMIT_ALL_ENGINES);
+		igt_subtest_f("legacy-resubmit-new-%s", e->name)
+			spin_resubmit(fd, e2, RESUBMIT_NEW_CTX);
+	}
 
-		igt_subtest_f("resubmit-new-all-%s", e->name)
-			spin_resubmit(fd, e->exec_id,
+	__for_each_physical_engine(fd, e2) {
+		igt_subtest_f("%s", e2->name)
+			spin(fd, e2, 3);
+
+		igt_subtest_f("resubmit-%s", e2->name)
+			spin_resubmit(fd, e2, 0);
+
+		igt_subtest_f("resubmit-new-%s", e2->name)
+			spin_resubmit(fd, e2, RESUBMIT_NEW_CTX);
+
+		igt_subtest_f("resubmit-all-%s", e2->name)
+			spin_resubmit(fd, e2, RESUBMIT_ALL_ENGINES);
+
+		igt_subtest_f("resubmit-new-all-%s", e2->name)
+			spin_resubmit(fd, e2,
 				      RESUBMIT_NEW_CTX |
 				      RESUBMIT_ALL_ENGINES);
 	}
diff --git a/tests/i915/gem_workarounds.c b/tests/i915/gem_workarounds.c
index 403863c..81c356f 100644
--- a/tests/i915/gem_workarounds.c
+++ b/tests/i915/gem_workarounds.c
@@ -249,6 +249,7 @@
 	igt_fixture {
 		FILE *file;
 		char *line = NULL;
+		char *str;
 		size_t line_size;
 		int i, fd;
 
@@ -261,9 +262,13 @@
 
 		fd = igt_debugfs_open(device, "i915_wa_registers", O_RDONLY);
 		file = fdopen(fd, "r");
-		igt_assert(getline(&line, &line_size, file) > 0);
+		igt_require(getline(&line, &line_size, file) > 0);
 		igt_debug("i915_wa_registers: %s", line);
-		sscanf(line, "Workarounds applied: %d", &num_wa_regs);
+
+		/* We assume that the first batch is for rcs */
+		str = strstr(line, "Workarounds applied:");
+		igt_assert(str);
+		sscanf(str, "Workarounds applied: %d", &num_wa_regs);
 		igt_require(num_wa_regs > 0);
 
 		wa_regs = malloc(num_wa_regs * sizeof(*wa_regs));
@@ -271,6 +276,9 @@
 
 		i = 0;
 		while (getline(&line, &line_size, file) > 0) {
+			if (strstr(line, "Workarounds applied:"))
+				break;
+
 			igt_debug("%s", line);
 			if (sscanf(line, "0x%X: 0x%08X, mask: 0x%08X",
 				   &wa_regs[i].addr,
diff --git a/tests/intel-ci/blacklist.txt b/tests/intel-ci/blacklist.txt
index 2a5893c..8e3dafa 100644
--- a/tests/intel-ci/blacklist.txt
+++ b/tests/intel-ci/blacklist.txt
@@ -25,7 +25,7 @@
 igt@gem_ctx_create@(?!.*basic).*
 igt@gem_ctx_exec@(?!.*basic).*
 igt@gem_ctx_shared@*exhaust*
-igt@gem_ctx_switch@(?!.*basic).*
+igt@gem_ctx_switch@.*(forked|interruptible).*
 igt@gem_ctx_thrash(@.*)?
 igt@gem_evict_alignment(@.*)?
 igt@gem_evict_everything(@.*)?
diff --git a/tests/intel-ci/fast-feedback.testlist b/tests/intel-ci/fast-feedback.testlist
index 58e6b5c..29d09a6 100644
--- a/tests/intel-ci/fast-feedback.testlist
+++ b/tests/intel-ci/fast-feedback.testlist
@@ -14,7 +14,8 @@
 igt@gem_ctx_exec@basic
 igt@gem_ctx_param@basic
 igt@gem_ctx_param@basic-default
-igt@gem_ctx_switch@basic-default
+igt@gem_ctx_switch@legacy-render
+igt@gem_ctx_switch@rcs0
 igt@gem_exec_basic@basic-all
 igt@gem_exec_create@basic
 igt@gem_exec_fence@basic-busy-default
@@ -85,8 +86,6 @@
 igt@gem_mmap_gtt@basic-write-no-prefault
 igt@gem_mmap_gtt@basic-write-read
 igt@gem_mmap_gtt@basic-write-read-distinct
-igt@gem_pread@basic
-igt@gem_pwrite@basic
 igt@gem_render_linear_blits@basic
 igt@gem_render_tiled_blits@basic
 igt@gem_ringfill@basic-default
diff --git a/tests/kms_3d.c b/tests/kms_3d.c
index df8185a..8ade6d3 100644
--- a/tests/kms_3d.c
+++ b/tests/kms_3d.c
@@ -31,8 +31,7 @@
 	int drm_fd;
 	drmModeRes *res;
 	drmModeConnector *connector;
-	unsigned char *edid;
-	size_t length;
+	const unsigned char *edid;
 	int mode_count, connector_id;
 
 	drm_fd = drm_open_driver_master(DRIVER_INTEL);
@@ -57,10 +56,9 @@
 	}
 	igt_require(connector);
 
-	kmstest_edid_add_3d(igt_kms_get_base_edid(), EDID_LENGTH, &edid,
-			    &length);
+	edid = igt_kms_get_3d_edid();
 
-	kmstest_force_edid(drm_fd, connector, edid, length);
+	kmstest_force_edid(drm_fd, connector, edid);
 	if (!kmstest_force_connector(drm_fd, connector, FORCE_CONNECTOR_ON))
 		igt_skip("Could not force connector on\n");
 
@@ -113,8 +111,7 @@
 	}
 
 	kmstest_force_connector(drm_fd, connector, FORCE_CONNECTOR_UNSPECIFIED);
-	kmstest_force_edid(drm_fd, connector, NULL, 0);
+	kmstest_force_edid(drm_fd, connector, NULL);
 
 	drmModeFreeConnector(connector);
-	free(edid);
 }
diff --git a/tests/kms_addfb_basic.c b/tests/kms_addfb_basic.c
index d5dc3ef..20dfd4f 100644
--- a/tests/kms_addfb_basic.c
+++ b/tests/kms_addfb_basic.c
@@ -527,7 +527,7 @@
 		gem_close(fd, gem_bo);
 }
 
-static int addfb_expected_ret(int fd)
+static int addfb_expected_ret(int fd, uint64_t modifier)
 {
 	int gen;
 
@@ -535,6 +535,9 @@
 		return 0;
 
 	gen = intel_gen(intel_get_drm_devid(fd));
+
+	if (modifier == LOCAL_I915_FORMAT_MOD_Yf_TILED)
+		return gen >= 9 && gen < 12 ? 0 : -1;
 	return gen >= 9 ? 0 : -1;
 }
 
@@ -568,8 +571,8 @@
 
 		f.modifier[0] = LOCAL_I915_FORMAT_MOD_Y_TILED;
 		igt_assert(drmIoctl(fd, LOCAL_DRM_IOCTL_MODE_ADDFB2, &f) ==
-			   addfb_expected_ret(fd));
-		if (!addfb_expected_ret(fd))
+			   addfb_expected_ret(fd, f.modifier[0]));
+		if (!addfb_expected_ret(fd, f.modifier[0]))
 			igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &f.fb_id) == 0);
 		f.fb_id = 0;
 	}
@@ -579,8 +582,8 @@
 
 		f.modifier[0] = LOCAL_I915_FORMAT_MOD_Yf_TILED;
 		igt_assert(drmIoctl(fd, LOCAL_DRM_IOCTL_MODE_ADDFB2, &f) ==
-			   addfb_expected_ret(fd));
-		if (!addfb_expected_ret(fd))
+			   addfb_expected_ret(fd, f.modifier[0]));
+		if (!addfb_expected_ret(fd, f.modifier[0]))
 			igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &f.fb_id) == 0);
 		f.fb_id = 0;
 	}
diff --git a/tests/kms_chamelium.c b/tests/kms_chamelium.c
index 378024d..b7d30a2 100644
--- a/tests/kms_chamelium.c
+++ b/tests/kms_chamelium.c
@@ -184,7 +184,7 @@
 	drmModeConnector *connector = chamelium_port_get_connector(
 	    data->chamelium, port, false);
 	uint64_t edid_blob_id;
-	unsigned char *edid;
+	const struct edid *edid;
 	char edid_vendor[3];
 
 	if (chamelium_port_get_type(port) != DRM_MODE_CONNECTOR_VGA) {
@@ -198,12 +198,8 @@
 	igt_assert(edid_blob = drmModeGetPropertyBlob(data->drm_fd,
 						      edid_blob_id));
 
-	edid = (unsigned char *) edid_blob->data;
-
-	edid_vendor[0] = ((edid[8] & 0x7c) >> 2) + '@';
-	edid_vendor[1] = (((edid[8] & 0x03) << 3) |
-			  ((edid[9] & 0xe0) >> 5)) + '@';
-	edid_vendor[2] = (edid[9] & 0x1f) + '@';
+	edid = (const struct edid *) edid_blob->data;
+	edid_get_mfg(edid, edid_vendor);
 
 	drmModeFreePropertyBlob(edid_blob);
 	drmModeFreeConnector(connector);
@@ -276,9 +272,10 @@
 test_edid_read(data_t *data, struct chamelium_port *port, enum test_edid edid)
 {
 	drmModePropertyBlobPtr edid_blob = NULL;
-	const unsigned char *raw_edid = get_edid(edid);
 	drmModeConnector *connector = chamelium_port_get_connector(
 	    data->chamelium, port, false);
+	size_t raw_edid_size;
+	const struct edid *raw_edid;
 	uint64_t edid_blob_id;
 
 	reset_state(data, port);
@@ -295,7 +292,9 @@
 	igt_assert(edid_blob = drmModeGetPropertyBlob(data->drm_fd,
 						      edid_blob_id));
 
-	igt_assert(memcmp(raw_edid, edid_blob->data, EDID_LENGTH) == 0);
+	raw_edid = chamelium_edid_get_raw(data->edids[edid], port);
+	raw_edid_size = edid_get_size(raw_edid);
+	igt_assert(memcmp(raw_edid, edid_blob->data, raw_edid_size) == 0);
 
 	drmModeFreePropertyBlob(edid_blob);
 	drmModeFreeConnector(connector);
@@ -468,14 +467,11 @@
 {
 	igt_display_t *display = &data->display;
 	igt_output_t *output;
-	drmModeRes *res;
 	drmModeConnector *connector =
 		chamelium_port_get_connector(data->chamelium, port, false);
 	enum pipe pipe;
 	bool found = false;
 
-	igt_require(res = drmModeGetResources(data->drm_fd));
-
 	/* The chamelium's default EDID has a lot of resolutions, way more then
 	 * we need to test. Additionally the default EDID doesn't support HDMI
 	 * audio.
@@ -505,7 +501,6 @@
 	igt_output_set_pipe(output, pipe);
 
 	drmModeFreeConnector(connector);
-	drmModeFreeResources(res);
 
 	return output;
 }
@@ -762,6 +757,110 @@
 	drmModeFreeConnector(connector);
 }
 
+#define MODE_CLOCK_ACCURACY 0.05 /* 5% */
+
+static void check_mode(struct chamelium *chamelium, struct chamelium_port *port,
+		       drmModeModeInfo *mode)
+{
+	struct chamelium_video_params video_params = {0};
+	double mode_clock;
+	int mode_hsync_offset, mode_vsync_offset;
+	int mode_hsync_width, mode_vsync_width;
+	int mode_hsync_polarity, mode_vsync_polarity;
+
+	chamelium_port_get_video_params(chamelium, port, &video_params);
+
+	mode_clock = (double) mode->clock / 1000;
+	mode_hsync_offset = mode->hsync_start - mode->hdisplay;
+	mode_vsync_offset = mode->vsync_start - mode->vdisplay;
+	mode_hsync_width = mode->hsync_end - mode->hsync_start;
+	mode_vsync_width = mode->vsync_end - mode->vsync_start;
+	mode_hsync_polarity = !!(mode->flags & DRM_MODE_FLAG_PHSYNC);
+	mode_vsync_polarity = !!(mode->flags & DRM_MODE_FLAG_PVSYNC);
+
+	igt_debug("Checking video mode:\n");
+	igt_debug("clock: got %f, expected %f ± %f%%\n",
+		  video_params.clock, mode_clock, MODE_CLOCK_ACCURACY * 100);
+	igt_debug("hactive: got %d, expected %d\n",
+		  video_params.hactive, mode->hdisplay);
+	igt_debug("vactive: got %d, expected %d\n",
+		  video_params.vactive, mode->vdisplay);
+	igt_debug("hsync_offset: got %d, expected %d\n",
+		  video_params.hsync_offset, mode_hsync_offset);
+	igt_debug("vsync_offset: got %d, expected %d\n",
+		  video_params.vsync_offset, mode_vsync_offset);
+	igt_debug("htotal: got %d, expected %d\n",
+		  video_params.htotal, mode->htotal);
+	igt_debug("vtotal: got %d, expected %d\n",
+		  video_params.vtotal, mode->vtotal);
+	igt_debug("hsync_width: got %d, expected %d\n",
+		  video_params.hsync_width, mode_hsync_width);
+	igt_debug("vsync_width: got %d, expected %d\n",
+		  video_params.vsync_width, mode_vsync_width);
+	igt_debug("hsync_polarity: got %d, expected %d\n",
+		  video_params.hsync_polarity, mode_hsync_polarity);
+	igt_debug("vsync_polarity: got %d, expected %d\n",
+		  video_params.vsync_polarity, mode_vsync_polarity);
+
+	if (!isnan(video_params.clock)) {
+		igt_assert(video_params.clock >
+			   mode_clock * (1 - MODE_CLOCK_ACCURACY));
+		igt_assert(video_params.clock <
+			   mode_clock * (1 + MODE_CLOCK_ACCURACY));
+	}
+	igt_assert(video_params.hactive == mode->hdisplay);
+	igt_assert(video_params.vactive == mode->vdisplay);
+	igt_assert(video_params.hsync_offset == mode_hsync_offset);
+	igt_assert(video_params.vsync_offset == mode_vsync_offset);
+	igt_assert(video_params.htotal == mode->htotal);
+	igt_assert(video_params.vtotal == mode->vtotal);
+	igt_assert(video_params.hsync_width == mode_hsync_width);
+	igt_assert(video_params.vsync_width == mode_vsync_width);
+	igt_assert(video_params.hsync_polarity == mode_hsync_polarity);
+	igt_assert(video_params.vsync_polarity == mode_vsync_polarity);
+}
+
+static void test_mode_timings(data_t *data, struct chamelium_port *port)
+{
+	igt_output_t *output;
+	igt_plane_t *primary;
+	drmModeConnector *connector;
+	int fb_id, i;
+	struct igt_fb fb;
+
+	igt_require(chamelium_supports_get_video_params(data->chamelium));
+
+	reset_state(data, port);
+
+	output = prepare_output(data, port, TEST_EDID_BASE);
+	connector = chamelium_port_get_connector(data->chamelium, port, false);
+	primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
+	igt_assert(primary);
+
+	igt_assert(connector->count_modes > 0);
+	for (i = 0; i < connector->count_modes; i++) {
+		drmModeModeInfo *mode = &connector->modes[i];
+
+		fb_id = igt_create_color_pattern_fb(data->drm_fd,
+						    mode->hdisplay, mode->vdisplay,
+						    DRM_FORMAT_XRGB8888,
+						    LOCAL_DRM_FORMAT_MOD_NONE,
+						    0, 0, 0, &fb);
+		igt_assert(fb_id > 0);
+
+		enable_output(data, port, output, mode, &fb);
+
+		/* Trigger the FSM */
+		chamelium_capture(data->chamelium, port, 0, 0, 0, 0, 0);
+
+		check_mode(data->chamelium, port, mode);
+
+		igt_remove_fb(data->drm_fd, &fb);
+	}
+
+	drmModeFreeConnector(connector);
+}
+
 
 /* Playback parameters control the audio signal we synthesize and send */
 #define PLAYBACK_CHANNELS 2
@@ -2164,8 +2263,9 @@
 		connector_subtest("dp-frame-dump", DisplayPort)
 			test_display_frame_dump(&data, port);
 
-		/* The EDID we generate advertises HDMI audio, not DP audio.
-		 * Use the Chamelium's default EDID for DP audio. */
+		connector_subtest("dp-mode-timings", DisplayPort)
+			test_mode_timings(&data, port);
+
 		connector_subtest("dp-audio", DisplayPort)
 			test_display_audio(&data, port, "HDMI",
 					   TEST_EDID_DP_AUDIO);
@@ -2321,6 +2421,9 @@
 		connector_subtest("hdmi-frame-dump", HDMIA)
 			test_display_frame_dump(&data, port);
 
+		connector_subtest("hdmi-mode-timings", HDMIA)
+			test_mode_timings(&data, port);
+
 		connector_subtest("hdmi-audio", HDMIA)
 			test_display_audio(&data, port, "HDMI",
 					   TEST_EDID_HDMI_AUDIO);
diff --git a/tests/kms_flip.c b/tests/kms_flip.c
index 2a158d9..ef2521f 100755
--- a/tests/kms_flip.c
+++ b/tests/kms_flip.c
@@ -686,14 +686,16 @@
 	    !(o->pending_events & EVENT_VBLANK) && o->flip_state.count > 0) {
 		struct vblank_reply reply;
 		unsigned int exp_seq;
-		unsigned long start;
+		unsigned long start, end;
 
 		exp_seq = o->flip_state.current_seq;
 		start = gettime_us();
 		do_or_die(__wait_for_vblank(TEST_VBLANK_ABSOLUTE |
 					    TEST_VBLANK_BLOCK, o->pipe, exp_seq,
 					    0, &reply));
-		igt_assert(gettime_us() - start < 500);
+		end = gettime_us();
+		igt_debug("Vblank took %luus\n", end - start);
+		igt_assert(end - start < 500);
 		igt_assert_eq(reply.sequence, exp_seq);
 		igt_assert(timercmp(&reply.ts, &o->flip_state.last_ts, ==));
 	}
@@ -1245,8 +1247,10 @@
 					 igt_bpp_depth_to_drm_format(o->bpp, o->depth),
 					 tiling, &o->fb_info[0]);
 	o->fb_ids[1] = igt_create_fb_with_bo_size(drm_fd, o->fb_width, o->fb_height,
-					 igt_bpp_depth_to_drm_format(o->bpp, o->depth),
-					 tiling, &o->fb_info[1], bo_size, 0);
+						  igt_bpp_depth_to_drm_format(o->bpp, o->depth),
+						  tiling, IGT_COLOR_YCBCR_BT709,
+						  IGT_COLOR_YCBCR_LIMITED_RANGE,
+						  &o->fb_info[1], bo_size, 0);
 
 	igt_assert(o->fb_ids[0]);
 	igt_assert(o->fb_ids[1]);
diff --git a/tests/kms_force_connector_basic.c b/tests/kms_force_connector_basic.c
index 20812d5..f1533e5 100644
--- a/tests/kms_force_connector_basic.c
+++ b/tests/kms_force_connector_basic.c
@@ -48,7 +48,7 @@
 		kmstest_force_connector(drm_fd, connector,
 					FORCE_CONNECTOR_UNSPECIFIED);
 
-		kmstest_force_edid(drm_fd, connector, NULL, 0);
+		kmstest_force_edid(drm_fd, connector, NULL);
 
 		drmModeFreeConnector(connector);
 	}
@@ -247,7 +247,7 @@
 
 		/* test edid forcing */
 		kmstest_force_edid(drm_fd, vga_connector,
-				   igt_kms_get_base_edid(), EDID_LENGTH);
+				   igt_kms_get_base_edid());
 		temp = drmModeGetConnectorCurrent(drm_fd,
 						  vga_connector->connector_id);
 
@@ -260,7 +260,7 @@
 		drmModeFreeConnector(temp);
 
 		/* remove edid */
-		kmstest_force_edid(drm_fd, vga_connector, NULL, 0);
+		kmstest_force_edid(drm_fd, vga_connector, NULL);
 		kmstest_force_connector(drm_fd, vga_connector,
 					FORCE_CONNECTOR_UNSPECIFIED);
 		temp = drmModeGetConnectorCurrent(drm_fd,
@@ -280,7 +280,7 @@
 
 		/* test pruning of stale modes */
 		kmstest_force_edid(drm_fd, vga_connector,
-				   igt_kms_get_alt_edid(), EDID_LENGTH);
+				   igt_kms_get_alt_edid());
 		temp = drmModeGetConnectorCurrent(drm_fd,
 						  vga_connector->connector_id);
 
@@ -294,7 +294,7 @@
 		drmModeFreeConnector(temp);
 
 		kmstest_force_edid(drm_fd, vga_connector,
-				   igt_kms_get_base_edid(), EDID_LENGTH);
+				   igt_kms_get_base_edid());
 		temp = drmModeGetConnectorCurrent(drm_fd,
 						  vga_connector->connector_id);
 
@@ -307,7 +307,7 @@
 
 		drmModeFreeConnector(temp);
 
-		kmstest_force_edid(drm_fd, vga_connector, NULL, 0);
+		kmstest_force_edid(drm_fd, vga_connector, NULL);
 		kmstest_force_connector(drm_fd, vga_connector,
 					FORCE_CONNECTOR_UNSPECIFIED);
 	}
diff --git a/tests/kms_frontbuffer_tracking.c b/tests/kms_frontbuffer_tracking.c
index 1037faf..c788b59 100644
--- a/tests/kms_frontbuffer_tracking.c
+++ b/tests/kms_frontbuffer_tracking.c
@@ -491,8 +491,10 @@
 	igt_calc_fb_size(drm.fd, width, height, format, tiling_for_size, &size,
 			 &stride);
 
-	igt_create_fb_with_bo_size(drm.fd, width, height, format, tiling, fb,
-				   size, stride);
+	igt_create_fb_with_bo_size(drm.fd, width, height, format, tiling,
+				   IGT_COLOR_YCBCR_BT709,
+				   IGT_COLOR_YCBCR_LIMITED_RANGE,
+				   fb, size, stride);
 }
 
 static uint32_t pick_color(struct igt_fb *fb, enum color ecolor)
diff --git a/tests/kms_hdmi_inject.c b/tests/kms_hdmi_inject.c
index 8c0d133..7868424 100644
--- a/tests/kms_hdmi_inject.c
+++ b/tests/kms_hdmi_inject.c
@@ -33,7 +33,10 @@
 #define HDISPLAY_4K	3840
 #define VDISPLAY_4K	2160
 
-IGT_TEST_DESCRIPTION("Tests 4K and audio HDMI injection.");
+IGT_TEST_DESCRIPTION("Test that in-kernel EDID parsing is producing "
+		     "expected results by forcing a disconnected HDMI "
+		     "connector with a known EDID and checking that the "
+		     "metadata exposed to user space matches.");
 
 /**
  * This collection of tests performs EDID and status injection tests. Injection
@@ -76,8 +79,7 @@
 static void
 hdmi_inject_4k(int drm_fd, drmModeConnector *connector)
 {
-	unsigned char *edid;
-	size_t length;
+	const unsigned char *edid;
 	struct kmstest_connector_config config;
 	int ret, cid, i, crtc_mask = -1;
 	int fb_id;
@@ -90,10 +92,8 @@
 	/* 4K requires at least HSW */
 	igt_require(IS_HASWELL(devid) || intel_gen(devid) >= 8);
 
-	kmstest_edid_add_4k(igt_kms_get_base_edid(), EDID_LENGTH, &edid,
-			    &length);
-
-	kmstest_force_edid(drm_fd, connector, edid, length);
+	edid = igt_kms_get_4k_edid();
+	kmstest_force_edid(drm_fd, connector, edid);
 
 	if (!kmstest_force_connector(drm_fd, connector, FORCE_CONNECTOR_ON))
 		igt_skip("Could not force connector on\n");
@@ -134,24 +134,19 @@
 	igt_remove_fb(drm_fd, &fb);
 
 	kmstest_force_connector(drm_fd, connector, FORCE_CONNECTOR_UNSPECIFIED);
-	kmstest_force_edid(drm_fd, connector, NULL, 0);
-
-	free(edid);
+	kmstest_force_edid(drm_fd, connector, NULL);
 }
 
 static void
 hdmi_inject_audio(int drm_fd, drmModeConnector *connector)
 {
 	const unsigned char *edid;
-	size_t length;
 	int fb_id, cid, ret, crtc_mask = -1;
 	struct igt_fb fb;
 	struct kmstest_connector_config config;
 
 	edid = igt_kms_get_hdmi_audio_edid();
-	length = AUDIO_EDID_LENGTH;
-
-	kmstest_force_edid(drm_fd, connector, edid, length);
+	kmstest_force_edid(drm_fd, connector, edid);
 
 	if (!kmstest_force_connector(drm_fd, connector, FORCE_CONNECTOR_ON))
 		igt_skip("Could not force connector on\n");
@@ -191,7 +186,7 @@
 	kmstest_dump_mode(&connector->modes[0]);
 
 	kmstest_force_connector(drm_fd, connector, FORCE_CONNECTOR_UNSPECIFIED);
-	kmstest_force_edid(drm_fd, connector, NULL, 0);
+	kmstest_force_edid(drm_fd, connector, NULL);
 }
 
 igt_main
@@ -210,9 +205,13 @@
 		igt_require(connector);
 	}
 
+	igt_describe("Make sure that 4K modes exposed by DRM match the "
+                     "forced EDID and modesetting using it succeed.");
 	igt_subtest("inject-4k")
 		hdmi_inject_4k(drm_fd, connector);
 
+	igt_describe("Make sure that audio information exposed by ALSA "
+		     "match the forced EDID.");
 	igt_subtest("inject-audio")
 		hdmi_inject_audio(drm_fd, connector);
 
diff --git a/tests/kms_plane.c b/tests/kms_plane.c
index 59d5f1e..5f1a73f 100644
--- a/tests/kms_plane.c
+++ b/tests/kms_plane.c
@@ -30,6 +30,13 @@
 #include <stdio.h>
 #include <string.h>
 
+/*
+ * Throw away enough lsbs in pixel formats tests
+ * to get a match despite some differences between
+ * the software and hardware YCbCr<->RGB conversion
+ * routines.
+ */
+#define LUT_MASK 0xf800
 
 typedef struct {
 	float red;
@@ -427,27 +434,36 @@
 				    igt_plane_t *plane,
 				    uint32_t format, uint64_t modifier,
 				    int width, int height,
+				    enum igt_color_encoding color_encoding,
+				    enum igt_color_range color_range,
 				    int color, igt_crc_t *crc, struct igt_fb *fb)
 {
 	const color_t *c = &colors[color];
 	struct igt_fb old_fb = *fb;
+	cairo_t *cr;
 
 	if (data->crop == 0 || format == DRM_FORMAT_XRGB8888) {
-		igt_create_color_fb(data->drm_fd, width, height,
-				    format, modifier,
-				    c->red, c->green, c->blue, fb);
+		igt_create_fb_with_bo_size(data->drm_fd, width, height,
+					   format, modifier, color_encoding,
+					   color_range, fb, 0, 0);
+
+		cr = igt_get_cairo_ctx(data->drm_fd, fb);
+
+		igt_paint_color(cr, 0, 0, width, height,
+				c->red, c->green, c->blue);
+
+		igt_put_cairo_ctx(data->drm_fd, fb, cr);
 	} else {
+		igt_create_fb_with_bo_size(data->drm_fd,
+					   width + data->crop * 2,
+					   height + data->crop * 2,
+					   format, modifier, color_encoding,
+					   color_range, fb, 0, 0);
+
 		/*
 		 * paint border in inverted color, then visible area in middle
 		 * with correct color for clamping test
 		 */
-		cairo_t *cr;
-
-		igt_create_fb(data->drm_fd,
-			      width + data->crop * 2,
-			      height + data->crop * 2,
-			      format, modifier, fb);
-
 		cr = igt_get_cairo_ctx(data->drm_fd, fb);
 
 		igt_paint_color(cr, 0, 0,
@@ -500,6 +516,104 @@
 	return num_unique_crc;
 }
 
+static bool test_format_plane_colors(data_t *data, enum pipe pipe,
+				     igt_plane_t *plane,
+				     uint32_t format, uint64_t modifier,
+				     int width, int height,
+				     enum igt_color_encoding encoding,
+				     enum igt_color_range range,
+				     igt_crc_t ref_crc[ARRAY_SIZE(colors)],
+				     struct igt_fb *fb)
+{
+	int crc_mismatch_count = 0;
+	unsigned int crc_mismatch_mask = 0;
+	bool result = true;
+
+	for (int i = 0; i < ARRAY_SIZE(colors); i++) {
+		igt_crc_t crc;
+
+		test_format_plane_color(data, pipe, plane,
+					format, modifier,
+					width, height,
+					encoding, range,
+					i, &crc, fb);
+
+		if (!igt_check_crc_equal(&crc, &ref_crc[i])) {
+			crc_mismatch_count++;
+			crc_mismatch_mask |= (1 << i);
+			result = false;
+		}
+	}
+
+	if (crc_mismatch_count)
+		igt_warn("CRC mismatches with format " IGT_FORMAT_FMT " on %s.%u with %d/%d solid colors tested (0x%X)\n",
+			 IGT_FORMAT_ARGS(format), kmstest_pipe_name(pipe),
+			 plane->index, crc_mismatch_count, (int)ARRAY_SIZE(colors), crc_mismatch_mask);
+
+	return result;
+}
+
+static bool test_format_plane_rgb(data_t *data, enum pipe pipe,
+				  igt_plane_t *plane,
+				  uint32_t format, uint64_t modifier,
+				  int width, int height,
+				  igt_crc_t ref_crc[ARRAY_SIZE(colors)],
+				  struct igt_fb *fb)
+{
+	igt_info("Testing format " IGT_FORMAT_FMT " / modifier 0x%" PRIx64 " on %s.%u\n",
+		 IGT_FORMAT_ARGS(format), modifier,
+		 kmstest_pipe_name(pipe), plane->index);
+
+	return test_format_plane_colors(data, pipe, plane,
+					format, modifier,
+					width, height,
+					IGT_COLOR_YCBCR_BT601,
+					IGT_COLOR_YCBCR_LIMITED_RANGE,
+					ref_crc, fb);
+}
+
+static bool test_format_plane_yuv(data_t *data, enum pipe pipe,
+				  igt_plane_t *plane,
+				  uint32_t format, uint64_t modifier,
+				  int width, int height,
+				  igt_crc_t ref_crc[ARRAY_SIZE(colors)],
+				  struct igt_fb *fb)
+{
+	bool result = true;
+
+	if (!igt_plane_has_prop(plane, IGT_PLANE_COLOR_ENCODING))
+		return true;
+	if (!igt_plane_has_prop(plane, IGT_PLANE_COLOR_RANGE))
+		return true;
+
+	for (enum igt_color_encoding e = 0; e < IGT_NUM_COLOR_ENCODINGS; e++) {
+		if (!igt_plane_try_prop_enum(plane,
+					     IGT_PLANE_COLOR_ENCODING,
+					     igt_color_encoding_to_str(e)))
+			continue;
+
+		for (enum igt_color_range r = 0; r < IGT_NUM_COLOR_RANGES; r++) {
+			if (!igt_plane_try_prop_enum(plane,
+						     IGT_PLANE_COLOR_RANGE,
+						     igt_color_range_to_str(r)))
+				continue;
+
+			igt_info("Testing format " IGT_FORMAT_FMT " / modifier 0x%" PRIx64 " (%s, %s) on %s.%u\n",
+				 IGT_FORMAT_ARGS(format), modifier,
+				 igt_color_encoding_to_str(e),
+				 igt_color_range_to_str(r),
+				 kmstest_pipe_name(pipe), plane->index);
+
+			result &= test_format_plane_colors(data, pipe, plane,
+							   format, modifier,
+							   width, height,
+							   e, r, ref_crc, fb);
+		}
+	}
+
+	return result;
+}
+
 static bool test_format_plane(data_t *data, enum pipe pipe,
 			      igt_output_t *output, igt_plane_t *plane)
 {
@@ -569,6 +683,8 @@
 		test_format_plane_color(data, pipe, plane,
 					format, modifier,
 					width, height,
+					IGT_COLOR_YCBCR_BT709,
+					IGT_COLOR_YCBCR_LIMITED_RANGE,
 					i, &ref_crc[i], &fb);
 	}
 
@@ -580,10 +696,6 @@
 	igt_require(num_unique_crcs(ref_crc, ARRAY_SIZE(colors)) > 1);
 
 	for (int i = 0; i < plane->format_mod_count; i++) {
-		int crc_mismatch_count = 0;
-		int crc_mismatch_mask = 0;
-		igt_crc_t crc;
-
 		format = plane->formats[i];
 		modifier = plane->modifiers[i];
 
@@ -592,37 +704,26 @@
 			continue;
 
 		if (format == DRM_FORMAT_C8) {
-			if (!set_c8_legacy_lut(data, pipe, 0xfc00))
+			if (!set_c8_legacy_lut(data, pipe, LUT_MASK))
 				continue;
 		} else {
 			if (!igt_fb_supported_format(format))
 				continue;
 		}
 
-		igt_info("Testing format " IGT_FORMAT_FMT " / modifier 0x%" PRIx64 " on %s.%u\n",
-			 IGT_FORMAT_ARGS(format), modifier,
-			 kmstest_pipe_name(pipe), plane->index);
-
-		for (int j = 0; j < ARRAY_SIZE(colors); j++) {
-			test_format_plane_color(data, pipe, plane,
-						format, modifier,
-						width, height,
-						j, &crc, &fb);
-
-			if (!igt_check_crc_equal(&crc, &ref_crc[j])) {
-				crc_mismatch_count++;
-				crc_mismatch_mask |= (1 << j);
-				result = false;
-			}
-		}
+		if (igt_format_is_yuv(format))
+			result &= test_format_plane_yuv(data, pipe, plane,
+							format, modifier,
+							width, height,
+							ref_crc, &fb);
+		else
+			result &= test_format_plane_rgb(data, pipe, plane,
+							format, modifier,
+							width, height,
+							ref_crc, &fb);
 
 		if (format == DRM_FORMAT_C8)
-			set_legacy_lut(data, pipe, 0xfc00);
-
-		if (crc_mismatch_count)
-			igt_warn("CRC mismatches with format " IGT_FORMAT_FMT " on %s.%u with %d/%d solid colors tested (0x%X)\n",
-				 IGT_FORMAT_ARGS(format), kmstest_pipe_name(pipe),
-				 plane->index, crc_mismatch_count, (int)ARRAY_SIZE(colors), crc_mismatch_mask);
+			set_legacy_lut(data, pipe, LUT_MASK);
 	}
 
 	igt_pipe_crc_stop(data->pipe_crc);
@@ -657,7 +758,7 @@
 
 	igt_display_commit2(&data->display, data->display.is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
 
-	set_legacy_lut(data, pipe, 0xfc00);
+	set_legacy_lut(data, pipe, LUT_MASK);
 
 	test_init(data, pipe);
 
diff --git a/tests/kms_plane_multiple.c b/tests/kms_plane_multiple.c
index 0d3ba4f..81ed45d 100644
--- a/tests/kms_plane_multiple.c
+++ b/tests/kms_plane_multiple.c
@@ -30,7 +30,7 @@
 #include <string.h>
 #include <time.h>
 
-IGT_TEST_DESCRIPTION("Test atomic mode setting with multiple planes ");
+IGT_TEST_DESCRIPTION("Test atomic mode setting with multiple planes.");
 
 #define SIZE_PLANE      256
 #define SIZE_CURSOR     128
@@ -96,7 +96,7 @@
 }
 
 static void
-test_grab_crc(data_t *data, igt_output_t *output, enum pipe pipe,
+get_reference_crc(data_t *data, igt_output_t *output, enum pipe pipe,
 	      color_t *color, uint64_t tiling)
 {
 	drmModeModeInfo *mode;
@@ -125,17 +125,6 @@
 	igt_pipe_crc_get_single(data->pipe_crc, &data->ref_crc);
 }
 
-/*
- * Multiple plane position test.
- *   - We start by grabbing a reference CRC of a full blue fb being scanned
- *     out on the primary plane
- *   - Then we scannout number of planes:
- *      * the primary plane uses a blue fb with a black rectangle hole
- *      * planes, on top of the primary plane, with a blue fb that is set-up
- *        to cover the black rectangles of the primary plane fb
- *     The resulting CRC should be identical to the reference CRC
- */
-
 static void
 create_fb_for_mode_position(data_t *data, igt_output_t *output, drmModeModeInfo *mode,
 			    color_t *color, int *rect_x, int *rect_y,
@@ -281,6 +270,17 @@
 	free((void*)suffle);
 }
 
+/*
+ * Multiple plane position test.
+ *   - We start by grabbing a reference CRC of a full blue fb being scanned
+ *     out on the primary plane
+ *   - Then we scannout number of planes:
+ *      * the primary plane uses a blue fb with a black rectangle holes
+ *      * planes, on top of the primary plane, with a blue fb that is set-up
+ *        to cover the black rectangles of the primary plane
+ *     The resulting CRC should be identical to the reference CRC
+ */
+
 static void
 test_plane_position_with_output(data_t *data, enum pipe pipe,
 				igt_output_t *output, int n_planes,
@@ -306,11 +306,9 @@
 
 	test_init(data, pipe, n_planes);
 
-	test_grab_crc(data, output, pipe, &blue, tiling);
+	get_reference_crc(data, output, pipe, &blue, tiling);
 
-	/*
-	 * Find out how many planes are allowed simultaneously
-	 */
+	/* Find out how many planes are allowed simultaneously */
 	do {
 		c++;
 		prepare_planes(data, pipe, &blue, tiling, c, output);
@@ -323,7 +321,7 @@
 			igt_remove_fb(data->drm_fd, &data->fb[x]);
 	} while (!err && c < n_planes);
 
-	if(err)
+	if (err)
 		c--;
 
 	igt_info("Testing connector %s using pipe %s with %d planes %s with seed %d\n",
@@ -332,6 +330,7 @@
 
 	i = 0;
 	while (i < iterations || loop_forever) {
+		/* randomize planes and set up the holes */
 		prepare_planes(data, pipe, &blue, tiling, c, output);
 
 		igt_display_commit2(&data->display, COMMIT_ATOMIC);
@@ -441,6 +440,10 @@
 	}
 
 	for_each_pipe_static(pipe) {
+		igt_describe("Check that the kernel handles atomic updates of "
+			     "multiple planes correctly by changing their "
+			     "geometry and making sure the changes are "
+			     "reflected immediately after each commit.");
 		igt_subtest_group
 			run_tests_for_pipe(&data, pipe);
 	}
diff --git a/tests/meson.build b/tests/meson.build
index f168fbb..34a7402 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -76,7 +76,6 @@
 	'prime_self_import',
 	'prime_udl',
 	'prime_vgem',
-	'sw_sync',
 	'syncobj_basic',
 	'syncobj_wait',
 	'template',
@@ -110,7 +109,6 @@
 	'gem_close_race',
 	'gem_concurrent_blit',
 	'gem_cpu_reloc',
-	'gem_create',
 	'gem_cs_prefetch',
 	'gem_cs_tlb',
 	'gem_ctx_bad_destroy',
@@ -277,6 +275,14 @@
 	test_list += prog
 endforeach
 
+test_executables += executable('gem_create',
+	   join_paths('i915', 'gem_create.c'),
+	   dependencies : test_deps + [ libatomic ],
+	   install_dir : libexecdir,
+	   install_rpath : libexecdir_rpathdir,
+	   install : true)
+test_list += 'gem_create'
+
 test_executables += executable('gem_ctx_sseu',
 	   join_paths('i915', 'gem_ctx_sseu.c'),
 	   dependencies : test_deps + [ lib_igt_perf ],
@@ -322,6 +328,13 @@
 	   install : true)
 test_list += 'testdisplay'
 
+test_executables += executable('sw_sync', 'sw_sync.c',
+	   dependencies : test_deps + [ libatomic ],
+	   install_dir : libexecdir,
+	   install_rpath : libexecdir_rpathdir,
+	   install : true)
+test_list += 'sw_sync'
+
 subdir('amdgpu')
 
 gen_testlist = find_program('generate_testlist.sh')
diff --git a/tests/prime_vgem.c b/tests/prime_vgem.c
index 69ae8c9..bebf9ed 100644
--- a/tests/prime_vgem.c
+++ b/tests/prime_vgem.c
@@ -82,6 +82,8 @@
 	close(dmabuf);
 
 	igt_fork(child, 1) {
+		close(master[0]);
+		close(slave[1]);
 		for (i = 0; i < 1024; i++) {
 			uint32_t tmp;
 			gem_read(i915, handle, 4096*i, &tmp, sizeof(tmp));
@@ -97,6 +99,8 @@
 		gem_close(i915, handle);
 	}
 
+	close(master[1]);
+	close(slave[0]);
 	read(master[0], &i, sizeof(i));
 	fence = vgem_fence_attach(vgem, &scratch, VGEM_FENCE_WRITE);
 	write(slave[1], &i, sizeof(i));
@@ -110,8 +114,6 @@
 
 	igt_waitchildren();
 	close(master[0]);
-	close(master[1]);
-	close(slave[0]);
 	close(slave[1]);
 }
 
@@ -137,6 +139,8 @@
 	close(dmabuf);
 
 	igt_fork(child, 1) {
+		close(master[0]);
+		close(slave[1]);
 		ptr = gem_mmap__gtt(i915, handle, 4096*1024, PROT_READ);
 
 		gem_set_domain(i915, handle, I915_GEM_DOMAIN_GTT, 0);
@@ -153,6 +157,8 @@
 		gem_close(i915, handle);
 	}
 
+	close(master[1]);
+	close(slave[0]);
 	read(master[0], &i, sizeof(i));
 	fence = vgem_fence_attach(vgem, &scratch, VGEM_FENCE_WRITE);
 	write(slave[1], &i, sizeof(i));
@@ -166,8 +172,6 @@
 
 	igt_waitchildren();
 	close(master[0]);
-	close(master[1]);
-	close(slave[0]);
 	close(slave[1]);
 }
 
diff --git a/tests/sw_sync.c b/tests/sw_sync.c
index 950b8b6..62d1d17 100644
--- a/tests/sw_sync.c
+++ b/tests/sw_sync.c
@@ -26,6 +26,7 @@
 
 #include <pthread.h>
 #include <semaphore.h>
+#include <stdatomic.h>
 #include <stdint.h>
 #include <sys/socket.h>
 #include <sys/types.h>
@@ -43,7 +44,7 @@
 typedef struct {
 	int timeline;
 	uint32_t thread_id;
-	uint32_t *counter;
+	_Atomic(uint32_t) *counter;
 	sem_t *sem;
 } data_t;
 
@@ -489,7 +490,7 @@
 	pthread_t thread_arr[MULTI_CONSUMER_THREADS];
 	sem_t sem;
 	int timeline;
-	uint32_t counter = 0;
+	_Atomic(uint32_t) counter = 0;
 	uintptr_t thread_ret = 0;
 	data_t data;
 	int i, ret;
@@ -517,7 +518,7 @@
 	{
 		sem_wait(&sem);
 
-		__sync_fetch_and_add(&counter, 1);
+		atomic_fetch_add(&counter, 1);
 		sw_sync_timeline_inc(timeline, 1);
 	}
 
@@ -554,7 +555,7 @@
 		if (sync_fence_wait(fence, 1000) < 0)
 			return (void *) 1;
 
-		if (__sync_fetch_and_add(data->counter, 1) != next_point)
+		if (atomic_fetch_add(data->counter, 1) != next_point)
 			return (void *) 1;
 
 		/* Kick off the next thread. */
@@ -570,7 +571,7 @@
 	data_t data_arr[MULTI_CONSUMER_PRODUCER_THREADS];
 	pthread_t thread_arr[MULTI_CONSUMER_PRODUCER_THREADS];
 	int timeline;
-	uint32_t counter = 0;
+	_Atomic(uint32_t) counter = 0;
 	uintptr_t thread_ret = 0;
 	data_t data;
 	int i, ret;
@@ -900,4 +901,3 @@
 	igt_subtest("sync_random_merge")
 		test_sync_random_merge();
 }
-
diff --git a/tests/testdisplay.c b/tests/testdisplay.c
index 3259054..2fdc023 100644
--- a/tests/testdisplay.c
+++ b/tests/testdisplay.c
@@ -80,7 +80,7 @@
 drmModeRes *resources;
 int drm_fd, modes;
 int test_all_modes = 0, test_preferred_mode = 0, force_mode = 0, test_plane,
-    test_stereo_modes;
+    test_stereo_modes, test_aspect_ratio;
 uint64_t tiling = LOCAL_DRM_FORMAT_MOD_NONE;
 int sleep_between_modes = 0;
 int do_dpms = 0; /* This aliases to DPMS_ON */
@@ -248,6 +248,24 @@
 	igt_paint_image(cr, file, img_x, img_y, img_h, img_w);
 }
 
+static const char *picture_aspect_ratio_str(uint32_t flags)
+{
+	switch (flags & DRM_MODE_FLAG_PIC_AR_MASK) {
+	case DRM_MODE_FLAG_PIC_AR_NONE:
+		return "";
+	case DRM_MODE_FLAG_PIC_AR_4_3:
+		return "(4:3) ";
+	case DRM_MODE_FLAG_PIC_AR_16_9:
+		return "(16:9) ";
+	case DRM_MODE_FLAG_PIC_AR_64_27:
+		return "(64:27) ";
+	case DRM_MODE_FLAG_PIC_AR_256_135:
+		return "(256:135) ";
+	default:
+		return "(invalid) ";
+	}
+}
+
 static void paint_output_info(struct connector *c, struct igt_fb *fb)
 {
 	cairo_t *cr = igt_get_cairo_ctx(drm_fd, fb);
@@ -288,8 +306,10 @@
 			cairo_move_to(cr, x, top_y);
 		}
 		str_width = igt_cairo_printf_line(cr, align_right, 10,
-			"%s @ %dHz", c->connector->modes[i].name,
-			 c->connector->modes[i].vrefresh);
+						  "%s%s @ %dHz",
+						  picture_aspect_ratio_str(c->connector->modes[i].flags),
+						  c->connector->modes[i].name,
+						  c->connector->modes[i].vrefresh);
 		if (str_width > max_width)
 			max_width = str_width;
 	}
@@ -573,7 +593,7 @@
 	tcsetattr(tio_fd, TCSANOW, &tio);
 }
 
-static char optstr[] = "3iaf:s:d:p:mrto:j:y";
+static char optstr[] = "3Aiaf:s:d:p:mrto:j:y";
 static struct option long_opts[] = {
 	{"yb", 0, 0, OPT_YB},
 	{"yf", 0, 0, OPT_YF},
@@ -588,6 +608,7 @@
 	"  -p\t<planew,h>,<crtcx,y>,<crtcw,h> test overlay plane\n"
 	"  -m\ttest the preferred mode\n"
 	"  -3\ttest all 3D modes\n"
+	"  -A\ttest all aspect ratios\n"
 	"  -t\tuse an X-tiled framebuffer\n"
 	"  -y, --yb\n"
 	"  \tuse a Y-tiled framebuffer\n"
@@ -609,6 +630,9 @@
 	case '3':
 		test_stereo_modes = 1;
 		break;
+	case 'A':
+		test_aspect_ratio = 1;
+		break;
 	case 'i':
 		opt_dump_info = true;
 		break;
@@ -697,6 +721,12 @@
 		goto out_close;
 	}
 
+	if (test_aspect_ratio &&
+	    drmSetClientCap(drm_fd, DRM_CLIENT_CAP_ASPECT_RATIO, 1) < 0) {
+		igt_warn("DRM_CLIENT_CAP_ASPECT_RATIO failed\n");
+		goto out_close;
+	}
+
 	if (opt_dump_info) {
 		dump_info();
 		goto out_close;
diff --git a/tools/intel_audio_dump.c b/tools/intel_audio_dump.c
index 90260a2..726bb4b 100644
--- a/tools/intel_audio_dump.c
+++ b/tools/intel_audio_dump.c
@@ -46,8 +46,8 @@
 
 #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 REG_BITS(reg, high, low)	(((reg) & (BITMASK(high, low))) >> (low))
+#define REG_BIT(reg, n)		REG_BITS(reg, n, n)
 
 #define min_t(type, x, y) ({                    \
 		type __min1 = (x);                      \
@@ -430,11 +430,11 @@
 
 static void do_self_tests(void)
 {
-	if (BIT(1, 0) != 1)
+	if (REG_BIT(1, 0) != 1)
 		exit(1);
-	if (BIT(0x80000000, 31) != 1)
+	if (REG_BIT(0x80000000, 31) != 1)
 		exit(2);
-	if (BITS(0xc0000000, 31, 30) != 3)
+	if (REG_BITS(0xc0000000, 31, 30) != 3)
 		exit(3);
 }
 
@@ -537,10 +537,10 @@
 	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));
+	printf("AUD_RID major revision\t\t\t0x%lx\n", REG_BITS(dword, 23, 20));
+	printf("AUD_RID minor revision\t\t\t0x%lx\n", REG_BITS(dword, 19, 16));
+	printf("AUD_RID revision id\t\t\t0x%lx\n",    REG_BITS(dword, 15, 8));
+	printf("AUD_RID stepping id\t\t\t0x%lx\n",    REG_BITS(dword, 7, 0));
 
 	dword = INREG(SDVOB);
 	printf("SDVOB enable\t\t\t\t%u\n",      !!(dword & SDVO_ENABLE));
@@ -557,180 +557,180 @@
 	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)),
+	printf("PORT_HOTPLUG_EN DisplayPort/HDMI port B\t%ld\n", REG_BIT(dword, 29)),
+	printf("PORT_HOTPLUG_EN DisplayPort/HDMI port C\t%ld\n", REG_BIT(dword, 28)),
+	printf("PORT_HOTPLUG_EN DisplayPort port D\t%ld\n",      REG_BIT(dword, 27)),
+	printf("PORT_HOTPLUG_EN SDVOB\t\t\t%ld\n", REG_BIT(dword, 26)),
+	printf("PORT_HOTPLUG_EN SDVOC\t\t\t%ld\n", REG_BIT(dword, 25)),
+	printf("PORT_HOTPLUG_EN audio\t\t\t%ld\n", REG_BIT(dword, 24)),
+	printf("PORT_HOTPLUG_EN TV\t\t\t%ld\n",    REG_BIT(dword, 23)),
+	printf("PORT_HOTPLUG_EN CRT\t\t\t%ld\n",   REG_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 enable graphics DIP\t%ld\n",     REG_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));
+				REG_BITS(dword, 30, 29), dip_port[REG_BITS(dword, 30, 29)]);
+	printf("VIDEO_DIP_CTL DIP buffer trans active\t%lu\n", REG_BIT(dword, 28));
+	printf("VIDEO_DIP_CTL AVI DIP enabled\t\t%lu\n",       REG_BIT(dword, 21));
+	printf("VIDEO_DIP_CTL vendor DIP enabled\t%lu\n",      REG_BIT(dword, 22));
+	printf("VIDEO_DIP_CTL SPD DIP enabled\t\t%lu\n",       REG_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)]);
+			REG_BITS(dword, 20, 19), video_dip_index[REG_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));
+			REG_BITS(dword, 17, 16), video_dip_trans[REG_BITS(dword, 17, 16)]);
+	printf("VIDEO_DIP_CTL DIP buffer size\t\t%lu\n", REG_BITS(dword, 11, 8));
+	printf("VIDEO_DIP_CTL DIP address\t\t%lu\n", REG_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));
+	printf("AUD_CONFIG pixel clock\t\t\t[0x%lx] %s\n", REG_BITS(dword, 19, 16),
+			OPNAME(pixel_clock, REG_BITS(dword, 19, 16)));
+	printf("AUD_CONFIG fabrication enabled\t\t%lu\n", REG_BITS(dword, 2, 2));
+	printf("AUD_CONFIG professional use allowed\t%lu\n", REG_BIT(dword, 1));
+	printf("AUD_CONFIG fuse enabled\t\t\t%lu\n", REG_BIT(dword, 0));
 
 	dword = INREG(AUD_DEBUG);
-	printf("AUD_DEBUG function reset\t\t%lu\n", BIT(dword, 0));
+	printf("AUD_DEBUG function reset\t\t%lu\n", REG_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));
+	printf("AUD_SUBN_CNT starting node number\t0x%lx\n",  REG_BITS(dword, 23, 16));
+	printf("AUD_SUBN_CNT total number of nodes\t0x%lx\n", REG_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));
+	printf("AUD_SUBN_CNT2 starting node number\t0x%lx\n",  REG_BITS(dword, 24, 16));
+	printf("AUD_SUBN_CNT2 total number of nodes\t0x%lx\n", REG_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));
+	printf("AUD_FUNC_GRP unsol capable\t\t%lu\n", REG_BIT(dword, 8));
+	printf("AUD_FUNC_GRP node type\t\t\t0x%lx\n", REG_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));
+	printf("AUD_GRP_CAP beep 0\t\t\t%lu\n",       REG_BIT(dword, 16));
+	printf("AUD_GRP_CAP input delay\t\t\t%lu\n",  REG_BITS(dword, 11, 8));
+	printf("AUD_GRP_CAP output delay\t\t%lu\n",   REG_BITS(dword, 3, 0));
 
 	dword = INREG(AUD_PWRST);
 	printf("AUD_PWRST device power state\t\t%s\n",
-			power_state[BITS(dword, 5, 4)]);
+			power_state[REG_BITS(dword, 5, 4)]);
 	printf("AUD_PWRST device power state setting\t%s\n",
-			power_state[BITS(dword, 1, 0)]);
+			power_state[REG_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));
+	printf("AUD_SUPPWR support D0\t\t\t%lu\n", REG_BIT(dword, 0));
+	printf("AUD_SUPPWR support D1\t\t\t%lu\n", REG_BIT(dword, 1));
+	printf("AUD_SUPPWR support D2\t\t\t%lu\n", REG_BIT(dword, 2));
+	printf("AUD_SUPPWR support D3\t\t\t%lu\n", REG_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 widget type\t\t0x%lx\n",  REG_BITS(dword, 23, 20));
+	printf("AUD_OUT_CWCAP sample delay\t\t0x%lx\n", REG_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));
+			REG_BITS(dword, 15, 13) * 2 + REG_BIT(dword, 0) + 1);
+	printf("AUD_OUT_CWCAP L-R swap\t\t\t%lu\n",       REG_BIT(dword, 11));
+	printf("AUD_OUT_CWCAP power control\t\t%lu\n",    REG_BIT(dword, 10));
+	printf("AUD_OUT_CWCAP digital\t\t\t%lu\n",        REG_BIT(dword, 9));
+	printf("AUD_OUT_CWCAP conn list\t\t\t%lu\n",      REG_BIT(dword, 8));
+	printf("AUD_OUT_CWCAP unsol\t\t\t%lu\n",          REG_BIT(dword, 7));
+	printf("AUD_OUT_CWCAP mute\t\t\t%lu\n",           REG_BIT(dword, 5));
+	printf("AUD_OUT_CWCAP format override\t\t%lu\n",  REG_BIT(dword, 4));
+	printf("AUD_OUT_CWCAP amp param override\t%lu\n", REG_BIT(dword, 3));
+	printf("AUD_OUT_CWCAP out amp present\t\t%lu\n",  REG_BIT(dword, 2));
+	printf("AUD_OUT_CWCAP in amp present\t\t%lu\n",   REG_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));
+	printf("AUD_OUT_DIG_CNVT SPDIF category\t\t0x%lx\n", REG_BITS(dword, 14, 8));
+	printf("AUD_OUT_DIG_CNVT SPDIF level\t\t%lu\n",      REG_BIT(dword, 7));
+	printf("AUD_OUT_DIG_CNVT professional\t\t%lu\n",     REG_BIT(dword, 6));
+	printf("AUD_OUT_DIG_CNVT non PCM\t\t%lu\n",          REG_BIT(dword, 5));
+	printf("AUD_OUT_DIG_CNVT copyright asserted\t%lu\n", REG_BIT(dword, 4));
+	printf("AUD_OUT_DIG_CNVT filter preemphasis\t%lu\n", REG_BIT(dword, 3));
+	printf("AUD_OUT_DIG_CNVT validity config\t%lu\n",    REG_BIT(dword, 2));
+	printf("AUD_OUT_DIG_CNVT validity flag\t\t%lu\n",    REG_BIT(dword, 1));
+	printf("AUD_OUT_DIG_CNVT digital enable\t\t%lu\n",   REG_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));
+	printf("AUD_OUT_CH_STR stream id\t\t0x%lx\n",        REG_BITS(dword, 7, 4));
+	printf("AUD_OUT_CH_STR lowest channel\t\t%lu\n",     REG_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 stream channels\t%lu\n",    REG_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)));
+			REG_BITS(dword, 6, 4), OPNAME(bits_per_sample, REG_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 widget type\t\t0x%lx\n",        REG_BITS(dword, 23, 20));
+	printf("AUD_PINW_CAP sample delay\t\t0x%lx\n",       REG_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));
+			REG_BITS(dword, 15, 13) * 2 + REG_BIT(dword, 0) + 1);
+	printf("AUD_PINW_CAP HDCP\t\t\t%lu\n",               REG_BIT(dword, 12));
+	printf("AUD_PINW_CAP L-R swap\t\t\t%lu\n",           REG_BIT(dword, 11));
+	printf("AUD_PINW_CAP power control\t\t%lu\n",        REG_BIT(dword, 10));
+	printf("AUD_PINW_CAP digital\t\t\t%lu\n",            REG_BIT(dword, 9));
+	printf("AUD_PINW_CAP conn list\t\t\t%lu\n",          REG_BIT(dword, 8));
+	printf("AUD_PINW_CAP unsol\t\t\t%lu\n",              REG_BIT(dword, 7));
+	printf("AUD_PINW_CAP mute\t\t\t%lu\n",               REG_BIT(dword, 5));
+	printf("AUD_PINW_CAP format override\t\t%lu\n",      REG_BIT(dword, 4));
+	printf("AUD_PINW_CAP amp param override\t\t%lu\n",   REG_BIT(dword, 3));
+	printf("AUD_PINW_CAP out amp present\t\t%lu\n",      REG_BIT(dword, 2));
+	printf("AUD_PINW_CAP in amp present\t\t%lu\n",       REG_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));
+	printf("AUD_PIN_CAP EAPD\t\t\t%lu\n",          REG_BIT(dword, 16));
+	printf("AUD_PIN_CAP HDMI\t\t\t%lu\n",          REG_BIT(dword, 7));
+	printf("AUD_PIN_CAP output\t\t\t%lu\n",        REG_BIT(dword, 4));
+	printf("AUD_PIN_CAP presence detect\t\t%lu\n", REG_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 mute status\t\t%lu\n",     REG_BIT(dword, 8));
+	printf("AUD_PINW_CNTR out enable\t\t%lu\n",      REG_BIT(dword, 6));
+	printf("AUD_PINW_CNTR amp mute status\t\t%lu\n", REG_BIT(dword, 8));
+	printf("AUD_PINW_CNTR amp mute status\t\t%lu\n", REG_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)));
+			REG_BITS(dword, 2, 0),
+			OPNAME(stream_type, REG_BITS(dword, 2, 0)));
 
 	dword = INREG(AUD_PINW_UNSOLRESP);
-	printf("AUD_PINW_UNSOLRESP enable unsol resp\t%lu\n", BIT(dword, 31));
+	printf("AUD_PINW_UNSOLRESP enable unsol resp\t%lu\n", REG_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 audio enabled\t\t%lu\n", REG_BIT(dword, 21));
+	printf("AUD_CNTL_ST DIP ACP enabled\t\t%lu\n",   REG_BIT(dword, 22));
+	printf("AUD_CNTL_ST DIP ISRCx enabled\t\t%lu\n", REG_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)]);
+			REG_BITS(dword, 30, 29), dip_port[REG_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)));
+			REG_BITS(dword, 20, 18), OPNAME(dip_index, REG_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));
+			REG_BITS(dword, 17, 16), dip_trans[REG_BITS(dword, 17, 16)]);
+	printf("AUD_CNTL_ST DIP address\t\t\t%lu\n", REG_BITS(dword, 3, 0));
+	printf("AUD_CNTL_ST CP ready\t\t\t%lu\n",    REG_BIT(dword, 15));
+	printf("AUD_CNTL_ST ELD valid\t\t\t%lu\n",   REG_BIT(dword, 14));
+	printf("AUD_CNTL_ST ELD ack\t\t\t%lu\n",     REG_BIT(dword, 4));
+	printf("AUD_CNTL_ST ELD bufsize\t\t\t%lu\n", REG_BITS(dword, 13, 9));
+	printf("AUD_CNTL_ST ELD address\t\t\t%lu\n", REG_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));
+	printf("AUD_HDMIW_STATUS CDCLK/DOTCLK underrun\t%lu\n", REG_BIT(dword, 31));
+	printf("AUD_HDMIW_STATUS CDCLK/DOTCLK overrun\t%lu\n",  REG_BIT(dword, 30));
+	printf("AUD_HDMIW_STATUS BCLK/CDCLK underrun\t%lu\n",   REG_BIT(dword, 29));
+	printf("AUD_HDMIW_STATUS BCLK/CDCLK overrun\t%lu\n",    REG_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 HBR enabled\t\t%lu\n", REG_BITS(dword, 15, 14));
+	printf("AUD_CONV_CHCNT HDMI channel count\t%lu\n", REG_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("\t\t\t\t\t[0x%x] %u => %lu\n", dword, i, REG_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++)
+	for (i = 0; i < REG_BITS(dword, 14, 10) / 4; i++)
 		printf("%08x ", htonl(INREG(AUD_HDMIW_HDMIEDID)));
 	printf("\n");
 
@@ -864,347 +864,347 @@
 	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 Enable_Graphics_DIP\t\t\t%ld\n",     REG_BIT(dword, 31)),
+	printf("VIDEO_DIP_CTL_A GCP_DIP_enable\t\t\t\t%ld\n",     REG_BIT(dword, 25)),
+	printf("VIDEO_DIP_CTL_A Video_DIP_type_enable AVI\t\t%lu\n",       REG_BIT(dword, 21));
+	printf("VIDEO_DIP_CTL_A Video_DIP_type_enable Vendor\t\t%lu\n",      REG_BIT(dword, 22));
+	printf("VIDEO_DIP_CTL_A Video_DIP_type_enable Gamut\t\t%lu\n",       REG_BIT(dword, 23));
+	printf("VIDEO_DIP_CTL_A Video_DIP_type_enable Source \t\t%lu\n",       REG_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)]);
+			REG_BITS(dword, 20, 19), video_dip_index[REG_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));
+			REG_BITS(dword, 17, 16), video_dip_trans[REG_BITS(dword, 17, 16)]);
+	printf("VIDEO_DIP_CTL_A Video_DIP_buffer_size\t\t\t%lu\n", REG_BITS(dword, 11, 8));
+	printf("VIDEO_DIP_CTL_A Video_DIP_access_address\t\t%lu\n", REG_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 Enable_Graphics_DIP\t\t\t%ld\n",     REG_BIT(dword, 31)),
+	printf("VIDEO_DIP_CTL_B GCP_DIP_enable\t\t\t\t%ld\n",     REG_BIT(dword, 25)),
+	printf("VIDEO_DIP_CTL_B Video_DIP_type_enable AVI\t\t%lu\n",       REG_BIT(dword, 21));
+	printf("VIDEO_DIP_CTL_B Video_DIP_type_enable Vendor\t\t%lu\n",      REG_BIT(dword, 22));
+	printf("VIDEO_DIP_CTL_B Video_DIP_type_enable Gamut\t\t%lu\n",       REG_BIT(dword, 23));
+	printf("VIDEO_DIP_CTL_B Video_DIP_type_enable Source \t\t%lu\n",       REG_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)]);
+			REG_BITS(dword, 20, 19), video_dip_index[REG_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));
+			REG_BITS(dword, 17, 16), video_dip_trans[REG_BITS(dword, 17, 16)]);
+	printf("VIDEO_DIP_CTL_B Video_DIP_buffer_size\t\t\t%lu\n", REG_BITS(dword, 11, 8));
+	printf("VIDEO_DIP_CTL_B Video_DIP_access_address\t\t%lu\n", REG_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 Enable_Graphics_DIP\t\t\t%ld\n",     REG_BIT(dword, 31)),
+	printf("VIDEO_DIP_CTL_C GCP_DIP_enable\t\t\t\t%ld\n",     REG_BIT(dword, 25)),
+	printf("VIDEO_DIP_CTL_C Video_DIP_type_enable AVI\t\t%lu\n",       REG_BIT(dword, 21));
+	printf("VIDEO_DIP_CTL_C Video_DIP_type_enable Vendor\t\t%lu\n",      REG_BIT(dword, 22));
+	printf("VIDEO_DIP_CTL_C Video_DIP_type_enable Gamut\t\t%lu\n",       REG_BIT(dword, 23));
+	printf("VIDEO_DIP_CTL_C Video_DIP_type_enable Source \t\t%lu\n",       REG_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)]);
+			REG_BITS(dword, 20, 19), video_dip_index[REG_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));
+			REG_BITS(dword, 17, 16), video_dip_trans[REG_BITS(dword, 17, 16)]);
+	printf("VIDEO_DIP_CTL_C Video_DIP_buffer_size\t\t\t%lu\n", REG_BITS(dword, 11, 8));
+	printf("VIDEO_DIP_CTL_C Video_DIP_access_address\t\t%lu\n", REG_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));
+	printf("AUD_RID Major_Revision\t\t\t\t\t0x%lx\n", REG_BITS(dword, 23, 20));
+	printf("AUD_RID Minor_Revision\t\t\t\t\t0x%lx\n", REG_BITS(dword, 19, 16));
+	printf("AUD_RID Revision_Id\t\t\t\t\t0x%lx\n",    REG_BITS(dword, 15, 8));
+	printf("AUD_RID Stepping_Id\t\t\t\t\t0x%lx\n",    REG_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));
+			REG_BITS(dword, 30, 29), transcoder_select[REG_BITS(dword, 30, 29)]);
+	printf("HDMIB sDVO_Border_Enable\t\t\t\t%lu\n", REG_BIT(dword, 7));
+	printf("HDMIB HDCP_Port_Select\t\t\t\t\t%lu\n", REG_BIT(dword, 5));
+	printf("HDMIB SDVO_HPD_Interrupt_Enable\t\t\t\t%lu\n", REG_BIT(dword, 23));
+	printf("HDMIB Port_Detected\t\t\t\t\t%lu\n", REG_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");
+			REG_BITS(dword, 11, 10), sdvo_hdmi_encoding[REG_BITS(dword, 11, 10)]);
+	printf("HDMIB HDMI_or_DVI_Select\t\t\t\t%s\n", REG_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));
+			REG_BITS(dword, 30, 29), transcoder_select[REG_BITS(dword, 30, 29)]);
+	printf("HDMIC sDVO_Border_Enable\t\t\t\t%lu\n", REG_BIT(dword, 7));
+	printf("HDMIC HDCP_Port_Select\t\t\t\t\t%lu\n", REG_BIT(dword, 5));
+	printf("HDMIC SDVO_HPD_Interrupt_Enable\t\t\t\t%lu\n", REG_BIT(dword, 23));
+	printf("HDMIC Port_Detected\t\t\t\t\t%lu\n", REG_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");
+			REG_BITS(dword, 11, 10), sdvo_hdmi_encoding[REG_BITS(dword, 11, 10)]);
+	printf("HDMIC HDMI_or_DVI_Select\t\t\t\t%s\n", REG_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));
+			REG_BITS(dword, 30, 29), transcoder_select[REG_BITS(dword, 30, 29)]);
+	printf("HDMID sDVO_Border_Enable\t\t\t\t%lu\n", REG_BIT(dword, 7));
+	printf("HDMID HDCP_Port_Select\t\t\t\t\t%lu\n", REG_BIT(dword, 5));
+	printf("HDMID SDVO_HPD_Interrupt_Enable\t\t\t\t%lu\n", REG_BIT(dword, 23));
+	printf("HDMID Port_Detected\t\t\t\t\t%lu\n", REG_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");
+			REG_BITS(dword, 11, 10), sdvo_hdmi_encoding[REG_BITS(dword, 11, 10)]);
+	printf("HDMID HDMI_or_DVI_Select\t\t\t\t%s\n", REG_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 DisplayPort_Enable\t\t\t\t%lu\n", REG_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));
+			REG_BITS(dword, 21, 19), dp_port_width[REG_BITS(dword, 21, 19)]);
+	printf("DP_CTL_B Port_Detected\t\t\t\t\t%lu\n", REG_BIT(dword, 2));
+	printf("DP_CTL_B HDCP_Port_Select\t\t\t\t%lu\n", REG_BIT(dword, 5));
+	printf("DP_CTL_B Audio_Output_Enable\t\t\t\t%lu\n", REG_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 DisplayPort_Enable\t\t\t\t%lu\n", REG_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));
+			REG_BITS(dword, 21, 19), dp_port_width[REG_BITS(dword, 21, 19)]);
+	printf("DP_CTL_C Port_Detected\t\t\t\t\t%lu\n", REG_BIT(dword, 2));
+	printf("DP_CTL_C HDCP_Port_Select\t\t\t\t%lu\n", REG_BIT(dword, 5));
+	printf("DP_CTL_C Audio_Output_Enable\t\t\t\t%lu\n", REG_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 DisplayPort_Enable\t\t\t\t%lu\n", REG_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));
+			REG_BITS(dword, 21, 19), dp_port_width[REG_BITS(dword, 21, 19)]);
+	printf("DP_CTL_D Port_Detected\t\t\t\t\t%lu\n", REG_BIT(dword, 2));
+	printf("DP_CTL_D HDCP_Port_Select\t\t\t\t%lu\n", REG_BIT(dword, 5));
+	printf("DP_CTL_D Audio_Output_Enable\t\t\t\t%lu\n", REG_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));
+	printf("AUD_CONFIG_A  N_index_value\t\t\t\t[0x%lx] %s\n", REG_BIT(dword, 29),
+			n_index_value[REG_BIT(dword, 29)]);
+	printf("AUD_CONFIG_A  N_programming_enable\t\t\t%lu\n", REG_BIT(dword, 28));
+	printf("AUD_CONFIG_A  Upper_N_value\t\t\t\t0x%02lx\n", REG_BITS(dword, 27, 20));
+	printf("AUD_CONFIG_A  Lower_N_value\t\t\t\t0x%03lx\n", REG_BITS(dword, 15, 4));
+	printf("AUD_CONFIG_A  Pixel_Clock_HDMI\t\t\t\t[0x%lx] %s\n", REG_BITS(dword, 19, 16),
+			OPNAME(pixel_clock, REG_BITS(dword, 19, 16)));
+	printf("AUD_CONFIG_A  Disable_NCTS\t\t\t\t%lu\n", REG_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));
+	printf("AUD_CONFIG_B  N_index_value\t\t\t\t[0x%lx] %s\n", REG_BIT(dword, 29),
+			n_index_value[REG_BIT(dword, 29)]);
+	printf("AUD_CONFIG_B  N_programming_enable\t\t\t%lu\n", REG_BIT(dword, 28));
+	printf("AUD_CONFIG_B  Upper_N_value\t\t\t\t0x%02lx\n", REG_BITS(dword, 27, 20));
+	printf("AUD_CONFIG_B  Lower_N_value\t\t\t\t0x%03lx\n", REG_BITS(dword, 15, 4));
+	printf("AUD_CONFIG_B  Pixel_Clock_HDMI\t\t\t\t[0x%lx] %s\n", REG_BITS(dword, 19, 16),
+			OPNAME(pixel_clock, REG_BITS(dword, 19, 16)));
+	printf("AUD_CONFIG_B  Disable_NCTS\t\t\t\t%lu\n", REG_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));
+	printf("AUD_CONFIG_C  N_index_value\t\t\t\t[0x%lx] %s\n", REG_BIT(dword, 29),
+			n_index_value[REG_BIT(dword, 29)]);
+	printf("AUD_CONFIG_C  N_programming_enable\t\t\t%lu\n", REG_BIT(dword, 28));
+	printf("AUD_CONFIG_C  Upper_N_value\t\t\t\t0x%02lx\n", REG_BITS(dword, 27, 20));
+	printf("AUD_CONFIG_C  Lower_N_value\t\t\t\t0x%03lx\n", REG_BITS(dword, 15, 4));
+	printf("AUD_CONFIG_C  Pixel_Clock_HDMI\t\t\t\t[0x%lx] %s\n", REG_BITS(dword, 19, 16),
+			OPNAME(pixel_clock, REG_BITS(dword, 19, 16)));
+	printf("AUD_CONFIG_C  Disable_NCTS\t\t\t\t%lu\n", REG_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));
+	printf("AUD_CTS_ENABLE_A  Enable_CTS_or_M_programming\t\t%lu\n", REG_BIT(dword, 20));
+	printf("AUD_CTS_ENABLE_A  CTS_M value Index\t\t\t%s\n", REG_BIT(dword, 21) ? "CTS" : "M");
+	printf("AUD_CTS_ENABLE_A  CTS_programming\t\t\t%#lx\n", REG_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));
+	printf("AUD_CTS_ENABLE_B  Enable_CTS_or_M_programming\t\t%lu\n", REG_BIT(dword, 20));
+	printf("AUD_CTS_ENABLE_B  CTS_M value Index\t\t\t%s\n", REG_BIT(dword, 21) ? "CTS" : "M");
+	printf("AUD_CTS_ENABLE_B  CTS_programming\t\t\t%#lx\n", REG_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));
+	printf("AUD_CTS_ENABLE_C  Enable_CTS_or_M_programming\t\t%lu\n", REG_BIT(dword, 20));
+	printf("AUD_CTS_ENABLE_C  CTS_M value Index\t\t\t%s\n", REG_BIT(dword, 21) ? "CTS" : "M");
+	printf("AUD_CTS_ENABLE_C  CTS_programming\t\t\t%#lx\n", REG_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));
+	printf("AUD_MISC_CTRL_A  Sample_Fabrication_EN_bit\t\t%lu\n",	REG_BIT(dword, 2));
+	printf("AUD_MISC_CTRL_A  Sample_present_Disable\t\t\t%lu\n",	REG_BIT(dword, 8));
+	printf("AUD_MISC_CTRL_A  Output_Delay\t\t\t\t%lu\n",		REG_BITS(dword, 7, 4));
+	printf("AUD_MISC_CTRL_A  Pro_Allowed\t\t\t\t%lu\n",			REG_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));
+	printf("AUD_MISC_CTRL_B  Sample_Fabrication_EN_bit\t\t%lu\n",	REG_BIT(dword, 2));
+	printf("AUD_MISC_CTRL_B  Sample_present_Disable\t\t\t%lu\n",	REG_BIT(dword, 8));
+	printf("AUD_MISC_CTRL_B  Output_Delay\t\t\t\t%lu\n",		REG_BITS(dword, 7, 4));
+	printf("AUD_MISC_CTRL_B  Pro_Allowed\t\t\t\t%lu\n",			REG_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));
+	printf("AUD_MISC_CTRL_C  Sample_Fabrication_EN_bit\t\t%lu\n",	REG_BIT(dword, 2));
+	printf("AUD_MISC_CTRL_C  Sample_present_Disable\t\t\t%lu\n",	REG_BIT(dword, 8));
+	printf("AUD_MISC_CTRL_C  Output_Delay\t\t\t\t%lu\n",		REG_BITS(dword, 7, 4));
+	printf("AUD_MISC_CTRL_C  Pro_Allowed\t\t\t\t%lu\n",			REG_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)]);
+	printf("AUD_PWRST  Func_Grp_Dev_PwrSt_Curr                  \t%s\n", power_state[REG_BITS(dword, 27, 26)]);
+	printf("AUD_PWRST  Func_Grp_Dev_PwrSt_Set                   \t%s\n", power_state[REG_BITS(dword, 25, 24)]);
+	printf("AUD_PWRST  ConvertorA_Widget_Power_State_Current    \t%s\n", power_state[REG_BITS(dword, 15, 14)]);
+	printf("AUD_PWRST  ConvertorA_Widget_Power_State_Requsted   \t%s\n", power_state[REG_BITS(dword, 13, 12)]);
+	printf("AUD_PWRST  ConvertorB_Widget_Power_State_Current    \t%s\n", power_state[REG_BITS(dword, 19, 18)]);
+	printf("AUD_PWRST  ConvertorB_Widget_Power_State_Requested  \t%s\n", power_state[REG_BITS(dword, 17, 16)]);
+	printf("AUD_PWRST  ConvC_Widget_PwrSt_Curr                  \t%s\n", power_state[REG_BITS(dword, 23, 22)]);
+	printf("AUD_PWRST  ConvC_Widget_PwrSt_Req                   \t%s\n", power_state[REG_BITS(dword, 21, 20)]);
+	printf("AUD_PWRST  PinB_Widget_Power_State_Current          \t%s\n", power_state[REG_BITS(dword,  3,  2)]);
+	printf("AUD_PWRST  PinB_Widget_Power_State_Set              \t%s\n", power_state[REG_BITS(dword,  1,  0)]);
+	printf("AUD_PWRST  PinC_Widget_Power_State_Current          \t%s\n", power_state[REG_BITS(dword,  7,  6)]);
+	printf("AUD_PWRST  PinC_Widget_Power_State_Set              \t%s\n", power_state[REG_BITS(dword,  5,  4)]);
+	printf("AUD_PWRST  PinD_Widget_Power_State_Current          \t%s\n", power_state[REG_BITS(dword, 11, 10)]);
+	printf("AUD_PWRST  PinD_Widget_Power_State_Set              \t%s\n", power_state[REG_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));
+	printf("AUD_PORT_EN_HD_CFG  Convertor_A_Digen\t\t\t%lu\n",	REG_BIT(dword, 0));
+	printf("AUD_PORT_EN_HD_CFG  Convertor_B_Digen\t\t\t%lu\n",	REG_BIT(dword, 1));
+	printf("AUD_PORT_EN_HD_CFG  Convertor_C_Digen\t\t\t%lu\n",	REG_BIT(dword, 2));
+	printf("AUD_PORT_EN_HD_CFG  ConvertorA_Stream_ID\t\t%lu\n",	REG_BITS(dword,  7, 4));
+	printf("AUD_PORT_EN_HD_CFG  ConvertorB_Stream_ID\t\t%lu\n",	REG_BITS(dword, 11, 8));
+	printf("AUD_PORT_EN_HD_CFG  ConvertorC_Stream_ID\t\t%lu\n",	REG_BITS(dword, 15, 12));
+	printf("AUD_PORT_EN_HD_CFG  Port_B_Out_Enable\t\t\t%lu\n",	REG_BIT(dword, 16));
+	printf("AUD_PORT_EN_HD_CFG  Port_C_Out_Enable\t\t\t%lu\n",	REG_BIT(dword, 17));
+	printf("AUD_PORT_EN_HD_CFG  Port_D_Out_Enable\t\t\t%lu\n",	REG_BIT(dword, 18));
+	printf("AUD_PORT_EN_HD_CFG  Port_B_Amp_Mute_Status\t\t%lu\n", REG_BIT(dword, 20));
+	printf("AUD_PORT_EN_HD_CFG  Port_C_Amp_Mute_Status\t\t%lu\n", REG_BIT(dword, 21));
+	printf("AUD_PORT_EN_HD_CFG  Port_D_Amp_Mute_Status\t\t%lu\n", REG_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));
+	printf("AUD_OUT_DIG_CNVT_A  V\t\t\t\t\t%lu\n",		REG_BIT(dword, 1));
+	printf("AUD_OUT_DIG_CNVT_A  VCFG\t\t\t\t%lu\n",		REG_BIT(dword, 2));
+	printf("AUD_OUT_DIG_CNVT_A  PRE\t\t\t\t\t%lu\n",		REG_BIT(dword, 3));
+	printf("AUD_OUT_DIG_CNVT_A  Copy\t\t\t\t%lu\n",		REG_BIT(dword, 4));
+	printf("AUD_OUT_DIG_CNVT_A  NonAudio\t\t\t\t%lu\n",		REG_BIT(dword, 5));
+	printf("AUD_OUT_DIG_CNVT_A  PRO\t\t\t\t\t%lu\n",		REG_BIT(dword, 6));
+	printf("AUD_OUT_DIG_CNVT_A  Level\t\t\t\t%lu\n",		REG_BIT(dword, 7));
+	printf("AUD_OUT_DIG_CNVT_A  Category_Code\t\t\t%lu\n",	REG_BITS(dword, 14, 8));
+	printf("AUD_OUT_DIG_CNVT_A  Lowest_Channel_Number\t\t%lu\n", REG_BITS(dword, 19, 16));
+	printf("AUD_OUT_DIG_CNVT_A  Stream_ID\t\t\t\t%lu\n",	REG_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_DIG_CNVT_B  V\t\t\t\t\t%lu\n",		REG_BIT(dword, 1));
+	printf("AUD_OUT_DIG_CNVT_B  VCFG\t\t\t\t%lu\n",		REG_BIT(dword, 2));
+	printf("AUD_OUT_DIG_CNVT_B  PRE\t\t\t\t\t%lu\n",		REG_BIT(dword, 3));
+	printf("AUD_OUT_DIG_CNVT_B  Copy\t\t\t\t%lu\n",		REG_BIT(dword, 4));
+	printf("AUD_OUT_DIG_CNVT_B  NonAudio\t\t\t\t%lu\n",		REG_BIT(dword, 5));
+	printf("AUD_OUT_DIG_CNVT_B  PRO\t\t\t\t\t%lu\n",		REG_BIT(dword, 6));
+	printf("AUD_OUT_DIG_CNVT_B  Level\t\t\t\t%lu\n",		REG_BIT(dword, 7));
+	printf("AUD_OUT_DIG_CNVT_B  Category_Code\t\t\t%lu\n",	REG_BITS(dword, 14, 8));
+	printf("AUD_OUT_DIG_CNVT_B  Lowest_Channel_Number\t\t%lu\n", REG_BITS(dword, 19, 16));
+	printf("AUD_OUT_DIG_CNVT_B  Stream_ID\t\t\t\t%lu\n",	REG_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_DIG_CNVT_C  V\t\t\t\t\t%lu\n",		REG_BIT(dword, 1));
+	printf("AUD_OUT_DIG_CNVT_C  VCFG\t\t\t\t%lu\n",		REG_BIT(dword, 2));
+	printf("AUD_OUT_DIG_CNVT_C  PRE\t\t\t\t\t%lu\n",		REG_BIT(dword, 3));
+	printf("AUD_OUT_DIG_CNVT_C  Copy\t\t\t\t%lu\n",		REG_BIT(dword, 4));
+	printf("AUD_OUT_DIG_CNVT_C  NonAudio\t\t\t\t%lu\n",		REG_BIT(dword, 5));
+	printf("AUD_OUT_DIG_CNVT_C  PRO\t\t\t\t\t%lu\n",		REG_BIT(dword, 6));
+	printf("AUD_OUT_DIG_CNVT_C  Level\t\t\t\t%lu\n",		REG_BIT(dword, 7));
+	printf("AUD_OUT_DIG_CNVT_C  Category_Code\t\t\t%lu\n",	REG_BITS(dword, 14, 8));
+	printf("AUD_OUT_DIG_CNVT_C  Lowest_Channel_Number\t\t%lu\n", REG_BITS(dword, 19, 16));
+	printf("AUD_OUT_DIG_CNVT_C  Stream_ID\t\t\t\t%lu\n",	REG_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));
+				1 + REG_BITS(dword,  3,  0),
+				1 + REG_BITS(dword,  7,  4),
+				1 + REG_BITS(dword, 15, 12),
+				1 + REG_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  HBR_enable\t\t\t\t%lu\n",	 REG_BITS(dword, 28, 27));
+	printf("AUD_OUT_STR_DESC_A  Convertor_Channel_Count\t\t%lu\n", REG_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));
+			REG_BITS(dword, 6, 4), OPNAME(bits_per_sample, REG_BITS(dword, 6, 4)));
+	printf("AUD_OUT_STR_DESC_A  Number_of_Channels_in_a_Stream\t%lu\n", 1 + REG_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  HBR_enable\t\t\t\t%lu\n",	 REG_BITS(dword, 28, 27));
+	printf("AUD_OUT_STR_DESC_B  Convertor_Channel_Count\t\t%lu\n", REG_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));
+			REG_BITS(dword, 6, 4), OPNAME(bits_per_sample, REG_BITS(dword, 6, 4)));
+	printf("AUD_OUT_STR_DESC_B  Number_of_Channels_in_a_Stream\t%lu\n", 1 + REG_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  HBR_enable\t\t\t\t%lu\n",	 REG_BITS(dword, 28, 27));
+	printf("AUD_OUT_STR_DESC_C  Convertor_Channel_Count\t\t%lu\n", REG_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));
+			REG_BITS(dword, 6, 4), OPNAME(bits_per_sample, REG_BITS(dword, 6, 4)));
+	printf("AUD_OUT_STR_DESC_C  Number_of_Channels_in_a_Stream\t%lu\n", 1 + REG_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));
+	printf("AUD_PINW_CONNLNG_SEL  Connection_select_Control_B\t%#lx\n", REG_BITS(dword,  7,  0));
+	printf("AUD_PINW_CONNLNG_SEL  Connection_select_Control_C\t%#lx\n", REG_BITS(dword, 15,  8));
+	printf("AUD_PINW_CONNLNG_SEL  Connection_select_Control_D\t%#lx\n", REG_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));
+			REG_BITS(dword, 30, 29), dip_port[REG_BITS(dword, 30, 29)]);
+	printf("AUD_CNTL_ST_A  DIP_type_enable_status Audio DIP\t\t%lu\n", REG_BIT(dword, 21));
+	printf("AUD_CNTL_ST_A  DIP_type_enable_status ACP DIP\t\t%lu\n", REG_BIT(dword, 22));
+	printf("AUD_CNTL_ST_A  DIP_type_enable_status Generic 2 DIP\t%lu\n", REG_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));
+			REG_BITS(dword, 17, 16), dip_trans[REG_BITS(dword, 17, 16)]);
+	printf("AUD_CNTL_ST_A  ELD_ACK\t\t\t\t\t%lu\n", REG_BIT(dword, 4));
+	printf("AUD_CNTL_ST_A  ELD_buffer_size\t\t\t\t%lu\n", REG_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));
+			REG_BITS(dword, 30, 29), dip_port[REG_BITS(dword, 30, 29)]);
+	printf("AUD_CNTL_ST_B  DIP_type_enable_status Audio DIP\t\t%lu\n", REG_BIT(dword, 21));
+	printf("AUD_CNTL_ST_B  DIP_type_enable_status ACP DIP\t\t%lu\n", REG_BIT(dword, 22));
+	printf("AUD_CNTL_ST_B  DIP_type_enable_status Generic 2 DIP\t%lu\n", REG_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));
+			REG_BITS(dword, 17, 16), dip_trans[REG_BITS(dword, 17, 16)]);
+	printf("AUD_CNTL_ST_B  ELD_ACK\t\t\t\t\t%lu\n", REG_BIT(dword, 4));
+	printf("AUD_CNTL_ST_B  ELD_buffer_size\t\t\t\t%lu\n", REG_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));
+			REG_BITS(dword, 30, 29), dip_port[REG_BITS(dword, 30, 29)]);
+	printf("AUD_CNTL_ST_C  DIP_type_enable_status Audio DIP\t\t%lu\n", REG_BIT(dword, 21));
+	printf("AUD_CNTL_ST_C  DIP_type_enable_status ACP DIP\t\t%lu\n", REG_BIT(dword, 22));
+	printf("AUD_CNTL_ST_C  DIP_type_enable_status Generic 2 DIP\t%lu\n", REG_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));
+			REG_BITS(dword, 17, 16), dip_trans[REG_BITS(dword, 17, 16)]);
+	printf("AUD_CNTL_ST_C  ELD_ACK\t\t\t\t\t%lu\n", REG_BIT(dword, 4));
+	printf("AUD_CNTL_ST_C  ELD_buffer_size\t\t\t\t%lu\n", REG_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));
+	printf("AUD_CNTRL_ST2  CP_ReadyB\t\t\t\t%lu\n",	REG_BIT(dword, 1));
+	printf("AUD_CNTRL_ST2  ELD_validB\t\t\t\t%lu\n",	REG_BIT(dword, 0));
+	printf("AUD_CNTRL_ST2  CP_ReadyC\t\t\t\t%lu\n",	REG_BIT(dword, 5));
+	printf("AUD_CNTRL_ST2  ELD_validC\t\t\t\t%lu\n",	REG_BIT(dword, 4));
+	printf("AUD_CNTRL_ST2  CP_ReadyD\t\t\t\t%lu\n",	REG_BIT(dword, 9));
+	printf("AUD_CNTRL_ST2  ELD_validD\t\t\t\t%lu\n",	REG_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_DPT_Audio_Output_En\t\t%lu\n",	REG_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));
+			REG_BITS(dword, 2, 0), trans_to_port_sel[REG_BITS(dword, 2, 0)]);
+	printf("AUD_CNTRL_ST3  TransB_DPT_Audio_Output_En\t\t%lu\n",	REG_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));
+			REG_BITS(dword, 6, 4), trans_to_port_sel[REG_BITS(dword, 6, 4)]);
+	printf("AUD_CNTRL_ST3  TransC_DPT_Audio_Output_En\t\t%lu\n",	REG_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)]);
+			REG_BITS(dword, 10, 8), trans_to_port_sel[REG_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_STATUS  Conv_A_CDCLK/DOTCLK_FIFO_Underrun\t%lu\n", REG_BIT(dword, 27));
+	printf("AUD_HDMIW_STATUS  Conv_A_CDCLK/DOTCLK_FIFO_Overrun\t%lu\n",  REG_BIT(dword, 26));
+	printf("AUD_HDMIW_STATUS  Conv_B_CDCLK/DOTCLK_FIFO_Underrun\t%lu\n", REG_BIT(dword, 29));
+	printf("AUD_HDMIW_STATUS  Conv_B_CDCLK/DOTCLK_FIFO_Overrun\t%lu\n",  REG_BIT(dword, 28));
+	printf("AUD_HDMIW_STATUS  Conv_C_CDCLK/DOTCLK_FIFO_Underrun\t%lu\n", REG_BIT(dword, 31));
+	printf("AUD_HDMIW_STATUS  Conv_C_CDCLK/DOTCLK_FIFO_Overrun\t%lu\n",  REG_BIT(dword, 30));
+	printf("AUD_HDMIW_STATUS  BCLK/CDCLK_FIFO_Overrun\t\t%lu\n",	 REG_BIT(dword, 25));
+	printf("AUD_HDMIW_STATUS  Function_Reset\t\t\t%lu\n",		 REG_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++)
+	for (i = 0; i < REG_BITS(dword, 14, 10) / 4; i++)
 		printf("%08x ", htonl(INREG(AUD_HDMIW_HDMIEDID_A)));
 	printf("\n");
 
@@ -1212,7 +1212,7 @@
 	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++)
+	for (i = 0; i < REG_BITS(dword, 14, 10) / 4; i++)
 		printf("%08x ", htonl(INREG(AUD_HDMIW_HDMIEDID_B)));
 	printf("\n");
 
@@ -1220,7 +1220,7 @@
 	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++)
+	for (i = 0; i < REG_BITS(dword, 14, 10) / 4; i++)
 		printf("%08x ", htonl(INREG(AUD_HDMIW_HDMIEDID_C)));
 	printf("\n");
 
@@ -1381,14 +1381,14 @@
 		sprintf(prefix, "AUD_TC%c_CONFIG", 'A' + index - TRANSCODER_A);
 	}
 
-	printf("%s  Disable_NCTS\t\t\t\t%lu\n",          prefix, BIT(dword, 3));
-	printf("%s  Lower_N_value\t\t\t\t0x%03lx\n",     prefix, BITS(dword, 15, 4));
-	printf("%s  Pixel_Clock_HDMI\t\t\t[0x%lx] %s\n", prefix, BITS(dword, 19, 16),
-		OPNAME(pixel_clock, BITS(dword, 19, 16)));
-	printf("%s  Upper_N_value\t\t\t\t0x%02lx\n",     prefix, BITS(dword, 27, 20));
-	printf("%s  N_programming_enable\t\t\t%lu\n",    prefix, BIT(dword, 28));
-	printf("%s  N_index_value\t\t\t\t[0x%lx] %s\n",  prefix, BIT(dword, 29),
-		OPNAME(n_index_value, BIT(dword, 29)));
+	printf("%s  Disable_NCTS\t\t\t\t%lu\n",          prefix, REG_BIT(dword, 3));
+	printf("%s  Lower_N_value\t\t\t\t0x%03lx\n",     prefix, REG_BITS(dword, 15, 4));
+	printf("%s  Pixel_Clock_HDMI\t\t\t[0x%lx] %s\n", prefix, REG_BITS(dword, 19, 16),
+		OPNAME(pixel_clock, REG_BITS(dword, 19, 16)));
+	printf("%s  Upper_N_value\t\t\t\t0x%02lx\n",     prefix, REG_BITS(dword, 27, 20));
+	printf("%s  N_programming_enable\t\t\t%lu\n",    prefix, REG_BIT(dword, 28));
+	printf("%s  N_index_value\t\t\t\t[0x%lx] %s\n",  prefix, REG_BIT(dword, 29),
+		OPNAME(n_index_value, REG_BIT(dword, 29)));
 }
 
 static void dump_aud_misc_control(int index)
@@ -1404,10 +1404,10 @@
 		sprintf(prefix, "AUD_C%c_MISC_CTRL", '1' + index - CONVERTER_1);
 	}
 
-	printf("%s   Pro_Allowed\t\t\t\t%lu\n",           prefix, BIT(dword, 1));
-	printf("%s   Sample_Fabrication_EN_bit\t\t%lu\n", prefix, BIT(dword, 2));
-	printf("%s   Output_Delay\t\t\t\t%lu\n",          prefix, BITS(dword, 7, 4));
-	printf("%s   Sample_present_Disable\t\t%lu\n",    prefix, BIT(dword, 8));
+	printf("%s   Pro_Allowed\t\t\t\t%lu\n",           prefix, REG_BIT(dword, 1));
+	printf("%s   Sample_Fabrication_EN_bit\t\t%lu\n", prefix, REG_BIT(dword, 2));
+	printf("%s   Output_Delay\t\t\t\t%lu\n",          prefix, REG_BITS(dword, 7, 4));
+	printf("%s   Sample_present_Disable\t\t%lu\n",    prefix, REG_BIT(dword, 8));
 }
 
 static void dump_aud_vendor_device_id(void)
@@ -1415,8 +1415,8 @@
 	uint32_t dword;
 
 	dword = INREG(aud_reg_base + AUD_VID_DID);
-	printf("AUD_VID_DID device id\t\t\t\t\t0x%lx\n", BITS(dword, 15, 0));
-	printf("AUD_VID_DID vendor id\t\t\t\t\t0x%lx\n", BITS(dword, 31, 16));
+	printf("AUD_VID_DID device id\t\t\t\t\t0x%lx\n", REG_BITS(dword, 15, 0));
+	printf("AUD_VID_DID vendor id\t\t\t\t\t0x%lx\n", REG_BITS(dword, 31, 16));
 }
 
 static void dump_aud_revision_id(void)
@@ -1424,10 +1424,10 @@
 	uint32_t dword;
 
 	dword = INREG(aud_reg_base + AUD_RID);
-	printf("AUD_RID Stepping_Id\t\t\t\t\t0x%lx\n",    BITS(dword, 7, 0));
-	printf("AUD_RID Revision_Id\t\t\t\t\t0x%lx\n",    BITS(dword, 15, 8));
-	printf("AUD_RID Minor_Revision\t\t\t\t\t0x%lx\n", BITS(dword, 19, 16));
-	printf("AUD_RID Major_Revision\t\t\t\t\t0x%lx\n", BITS(dword, 23, 20));
+	printf("AUD_RID Stepping_Id\t\t\t\t\t0x%lx\n",    REG_BITS(dword, 7, 0));
+	printf("AUD_RID Revision_Id\t\t\t\t\t0x%lx\n",    REG_BITS(dword, 15, 8));
+	printf("AUD_RID Minor_Revision\t\t\t\t\t0x%lx\n", REG_BITS(dword, 19, 16));
+	printf("AUD_RID Major_Revision\t\t\t\t\t0x%lx\n", REG_BITS(dword, 23, 20));
 }
 
 static void dump_aud_m_cts_enable(int index)
@@ -1443,10 +1443,10 @@
 		sprintf(prefix, "AUD_TC%c_M_CTS_ENABLE", 'A' + index - TRANSCODER_A);
 	}
 
-	printf("%s  CTS_programming\t\t\t%#lx\n",        prefix, BITS(dword, 19, 0));
-	printf("%s  Enable_CTS_or_M_programming\t%lu\n", prefix, BIT(dword, 20));
-	printf("%s  CTS_M value Index\t\t\t[0x%lx] %s\n",prefix, BIT(dword, 21),
-		OPNAME(cts_m_value_index, BIT(dword, 21)));
+	printf("%s  CTS_programming\t\t\t%#lx\n",        prefix, REG_BITS(dword, 19, 0));
+	printf("%s  Enable_CTS_or_M_programming\t%lu\n", prefix, REG_BIT(dword, 20));
+	printf("%s  CTS_M value Index\t\t\t[0x%lx] %s\n",prefix, REG_BIT(dword, 21),
+		OPNAME(cts_m_value_index, REG_BIT(dword, 21)));
 }
 
 static void dump_aud_power_state(void)
@@ -1455,39 +1455,39 @@
 	int num_pipes;
 
 	dword = INREG(aud_reg_base + AUD_PWRST);
-	printf("AUD_PWRST  PinB_Widget_Power_State_Set              \t%s\n",         power_state[BITS(dword,  1,  0)]);
-	printf("AUD_PWRST  PinB_Widget_Power_State_Current          \t%s\n",         power_state[BITS(dword,  3,  2)]);
-	printf("AUD_PWRST  PinC_Widget_Power_State_Set              \t%s\n",         power_state[BITS(dword,  5,  4)]);
-	printf("AUD_PWRST  PinC_Widget_Power_State_Current          \t%s\n",         power_state[BITS(dword,  7,  6)]);
-	printf("AUD_PWRST  PinD_Widget_Power_State_Set              \t%s\n",         power_state[BITS(dword,  9,  8)]);
-	printf("AUD_PWRST  PinD_Widget_Power_State_Current          \t%s\n",         power_state[BITS(dword, 11, 10)]);
+	printf("AUD_PWRST  PinB_Widget_Power_State_Set              \t%s\n",         power_state[REG_BITS(dword,  1,  0)]);
+	printf("AUD_PWRST  PinB_Widget_Power_State_Current          \t%s\n",         power_state[REG_BITS(dword,  3,  2)]);
+	printf("AUD_PWRST  PinC_Widget_Power_State_Set              \t%s\n",         power_state[REG_BITS(dword,  5,  4)]);
+	printf("AUD_PWRST  PinC_Widget_Power_State_Current          \t%s\n",         power_state[REG_BITS(dword,  7,  6)]);
+	printf("AUD_PWRST  PinD_Widget_Power_State_Set              \t%s\n",         power_state[REG_BITS(dword,  9,  8)]);
+	printf("AUD_PWRST  PinD_Widget_Power_State_Current          \t%s\n",         power_state[REG_BITS(dword, 11, 10)]);
 
 	if (!IS_HASWELL_PLUS(devid)) {
-		printf("AUD_PWRST  ConvertorA_Widget_Power_State_Requsted   \t%s\n", power_state[BITS(dword, 13, 12)]);
-		printf("AUD_PWRST  ConvertorA_Widget_Power_State_Current    \t%s\n", power_state[BITS(dword, 15, 14)]);
-		printf("AUD_PWRST  ConvertorB_Widget_Power_State_Requested  \t%s\n", power_state[BITS(dword, 17, 16)]);
-		printf("AUD_PWRST  ConvertorB_Widget_Power_State_Current    \t%s\n", power_state[BITS(dword, 19, 18)]);
+		printf("AUD_PWRST  ConvertorA_Widget_Power_State_Requsted   \t%s\n", power_state[REG_BITS(dword, 13, 12)]);
+		printf("AUD_PWRST  ConvertorA_Widget_Power_State_Current    \t%s\n", power_state[REG_BITS(dword, 15, 14)]);
+		printf("AUD_PWRST  ConvertorB_Widget_Power_State_Requested  \t%s\n", power_state[REG_BITS(dword, 17, 16)]);
+		printf("AUD_PWRST  ConvertorB_Widget_Power_State_Current    \t%s\n", power_state[REG_BITS(dword, 19, 18)]);
 	} else {
-		printf("AUD_PWRST  Convertor1_Widget_Power_State_Requsted   \t%s\n", power_state[BITS(dword, 13, 12)]);
-		printf("AUD_PWRST  Convertor1_Widget_Power_State_Current    \t%s\n", power_state[BITS(dword, 15, 14)]);
-		printf("AUD_PWRST  Convertor2_Widget_Power_State_Requested  \t%s\n", power_state[BITS(dword, 17, 16)]);
-		printf("AUD_PWRST  Convertor2_Widget_Power_State_Current    \t%s\n", power_state[BITS(dword, 19, 18)]);
+		printf("AUD_PWRST  Convertor1_Widget_Power_State_Requsted   \t%s\n", power_state[REG_BITS(dword, 13, 12)]);
+		printf("AUD_PWRST  Convertor1_Widget_Power_State_Current    \t%s\n", power_state[REG_BITS(dword, 15, 14)]);
+		printf("AUD_PWRST  Convertor2_Widget_Power_State_Requested  \t%s\n", power_state[REG_BITS(dword, 17, 16)]);
+		printf("AUD_PWRST  Convertor2_Widget_Power_State_Current    \t%s\n", power_state[REG_BITS(dword, 19, 18)]);
 	}
 
 	num_pipes = get_num_pipes();
 	if (num_pipes == 2) {
-		printf("AUD_PWRST  Func_Grp_Dev_PwrSt_Set                   \t%s\n", power_state[BITS(dword, 21, 20)]);
-		printf("AUD_PWRST  Func_Grp_Dev_PwrSt_Curr                  \t%s\n", power_state[BITS(dword, 23, 22)]);
+		printf("AUD_PWRST  Func_Grp_Dev_PwrSt_Set                   \t%s\n", power_state[REG_BITS(dword, 21, 20)]);
+		printf("AUD_PWRST  Func_Grp_Dev_PwrSt_Curr                  \t%s\n", power_state[REG_BITS(dword, 23, 22)]);
 	} else {	/* 3 pipes */
 		if (!IS_HASWELL_PLUS(devid)) {
-			printf("AUD_PWRST  ConvertorC_Widget_Power_State_Requested  \t%s\n", power_state[BITS(dword, 21, 20)]);
-			printf("AUD_PWRST  ConvertorC_Widget_Power_State_Current    \t%s\n", power_state[BITS(dword, 23, 22)]);
+			printf("AUD_PWRST  ConvertorC_Widget_Power_State_Requested  \t%s\n", power_state[REG_BITS(dword, 21, 20)]);
+			printf("AUD_PWRST  ConvertorC_Widget_Power_State_Current    \t%s\n", power_state[REG_BITS(dword, 23, 22)]);
 		} else {
-			printf("AUD_PWRST  Convertor3_Widget_Power_State_Requested  \t%s\n", power_state[BITS(dword, 21, 20)]);
-			printf("AUD_PWRST  Convertor3_Widget_Power_State_Current    \t%s\n", power_state[BITS(dword, 23, 22)]);
+			printf("AUD_PWRST  Convertor3_Widget_Power_State_Requested  \t%s\n", power_state[REG_BITS(dword, 21, 20)]);
+			printf("AUD_PWRST  Convertor3_Widget_Power_State_Current    \t%s\n", power_state[REG_BITS(dword, 23, 22)]);
 		}
-		printf("AUD_PWRST  Func_Grp_Dev_PwrSt_Set                   \t%s\n", power_state[BITS(dword, 25, 24)]);
-		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[REG_BITS(dword, 25, 24)]);
+		printf("AUD_PWRST  Func_Grp_Dev_PwrSt_Curr                  \t%s\n", power_state[REG_BITS(dword, 27, 26)]);
 	}
 }
 
@@ -1513,7 +1513,7 @@
 	dword = INREG(aud_ctrl_st);
 	dword &= ~BITMASK(9, 5);
 	OUTREG(aud_ctrl_st, dword);
-	for (i = 0; i < BITS(dword, 14, 10) / 4; i++)
+	for (i = 0; i < REG_BITS(dword, 14, 10) / 4; i++)
 		printf("%08x ", htonl(INREG(edid_data)));
 	printf("\n");
 }
@@ -1553,31 +1553,31 @@
 
 	dword = INREG(aud_reg_base + AUD_PORT_EN_HD_CFG);
 	if (num_pipes == 2) {
-		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_A_Stream_ID\t\t%lu\n",  BITS(dword,  7, 4));
-		printf("AUD_PORT_EN_HD_CFG  Convertor_B_Stream_ID\t\t%lu\n",  BITS(dword, 11, 8));
+		printf("AUD_PORT_EN_HD_CFG  Convertor_A_Digen\t\t\t%lu\n",    REG_BIT(dword, 0));
+		printf("AUD_PORT_EN_HD_CFG  Convertor_B_Digen\t\t\t%lu\n",    REG_BIT(dword, 1));
+		printf("AUD_PORT_EN_HD_CFG  Convertor_A_Stream_ID\t\t%lu\n",  REG_BITS(dword,  7, 4));
+		printf("AUD_PORT_EN_HD_CFG  Convertor_B_Stream_ID\t\t%lu\n",  REG_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));
+		printf("AUD_PORT_EN_HD_CFG  Port_B_Out_Enable\t\t\t%lu\n",    REG_BIT(dword, 12));
+		printf("AUD_PORT_EN_HD_CFG  Port_C_Out_Enable\t\t\t%lu\n",    REG_BIT(dword, 13));
+		printf("AUD_PORT_EN_HD_CFG  Port_D_Out_Enable\t\t\t%lu\n",    REG_BIT(dword, 14));
+		printf("AUD_PORT_EN_HD_CFG  Port_B_Amp_Mute_Status\t\t%lu\n", REG_BIT(dword, 16));
+		printf("AUD_PORT_EN_HD_CFG  Port_C_Amp_Mute_Status\t\t%lu\n", REG_BIT(dword, 17));
+		printf("AUD_PORT_EN_HD_CFG  Port_D_Amp_Mute_Status\t\t%lu\n", REG_BIT(dword, 18));
 	} else { /* three pipes */
-		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  Convertor_A_Stream_ID\t\t%lu\n",  BITS(dword,  7, 4));
-		printf("AUD_PORT_EN_HD_CFG  Convertor_B_Stream_ID\t\t%lu\n",  BITS(dword, 11, 8));
-		printf("AUD_PORT_EN_HD_CFG  Convertor_C_Stream_ID\t\t%lu\n",  BITS(dword, 15, 12));
+		printf("AUD_PORT_EN_HD_CFG  Convertor_A_Digen\t\t\t%lu\n",    REG_BIT(dword, 0));
+		printf("AUD_PORT_EN_HD_CFG  Convertor_B_Digen\t\t\t%lu\n",    REG_BIT(dword, 1));
+		printf("AUD_PORT_EN_HD_CFG  Convertor_C_Digen\t\t\t%lu\n",    REG_BIT(dword, 2));
+		printf("AUD_PORT_EN_HD_CFG  Convertor_A_Stream_ID\t\t%lu\n",  REG_BITS(dword,  7, 4));
+		printf("AUD_PORT_EN_HD_CFG  Convertor_B_Stream_ID\t\t%lu\n",  REG_BITS(dword, 11, 8));
+		printf("AUD_PORT_EN_HD_CFG  Convertor_C_Stream_ID\t\t%lu\n",  REG_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));
+		printf("AUD_PORT_EN_HD_CFG  Port_B_Out_Enable\t\t\t%lu\n",    REG_BIT(dword, 16));
+		printf("AUD_PORT_EN_HD_CFG  Port_C_Out_Enable\t\t\t%lu\n",    REG_BIT(dword, 17));
+		printf("AUD_PORT_EN_HD_CFG  Port_D_Out_Enable\t\t\t%lu\n",    REG_BIT(dword, 18));
+		printf("AUD_PORT_EN_HD_CFG  Port_B_Amp_Mute_Status\t\t%lu\n", REG_BIT(dword, 20));
+		printf("AUD_PORT_EN_HD_CFG  Port_C_Amp_Mute_Status\t\t%lu\n", REG_BIT(dword, 21));
+		printf("AUD_PORT_EN_HD_CFG  Port_D_Amp_Mute_Status\t\t%lu\n", REG_BIT(dword, 22));
 	}
 }
 
@@ -1586,19 +1586,19 @@
 	uint32_t dword;
 
 	dword = INREG(aud_reg_base + AUD_PIPE_CONV_CFG);
-	printf("AUD_PIPE_CONV_CFG  Convertor_1_Digen\t\t\t%lu\n",    BIT(dword, 0));
-	printf("AUD_PIPE_CONV_CFG  Convertor_2_Digen\t\t\t%lu\n",    BIT(dword, 1));
-	printf("AUD_PIPE_CONV_CFG  Convertor_3_Digen\t\t\t%lu\n",    BIT(dword, 2));
-	printf("AUD_PIPE_CONV_CFG  Convertor_1_Stream_ID\t\t%lu\n",  BITS(dword,  7, 4));
-	printf("AUD_PIPE_CONV_CFG  Convertor_2_Stream_ID\t\t%lu\n",  BITS(dword, 11, 8));
-	printf("AUD_PIPE_CONV_CFG  Convertor_3_Stream_ID\t\t%lu\n",  BITS(dword, 15, 12));
+	printf("AUD_PIPE_CONV_CFG  Convertor_1_Digen\t\t\t%lu\n",    REG_BIT(dword, 0));
+	printf("AUD_PIPE_CONV_CFG  Convertor_2_Digen\t\t\t%lu\n",    REG_BIT(dword, 1));
+	printf("AUD_PIPE_CONV_CFG  Convertor_3_Digen\t\t\t%lu\n",    REG_BIT(dword, 2));
+	printf("AUD_PIPE_CONV_CFG  Convertor_1_Stream_ID\t\t%lu\n",  REG_BITS(dword,  7, 4));
+	printf("AUD_PIPE_CONV_CFG  Convertor_2_Stream_ID\t\t%lu\n",  REG_BITS(dword, 11, 8));
+	printf("AUD_PIPE_CONV_CFG  Convertor_3_Stream_ID\t\t%lu\n",  REG_BITS(dword, 15, 12));
 
-	printf("AUD_PIPE_CONV_CFG  Port_B_Out_Enable\t\t\t%lu\n",    BIT(dword, 16));
-	printf("AUD_PIPE_CONV_CFG  Port_C_Out_Enable\t\t\t%lu\n",    BIT(dword, 17));
-	printf("AUD_PIPE_CONV_CFG  Port_D_Out_Enable\t\t\t%lu\n",    BIT(dword, 18));
-	printf("AUD_PIPE_CONV_CFG  Port_B_Amp_Mute_Status\t\t%lu\n", BIT(dword, 20));
-	printf("AUD_PIPE_CONV_CFG  Port_C_Amp_Mute_Status\t\t%lu\n", BIT(dword, 21));
-	printf("AUD_PIPE_CONV_CFG  Port_D_Amp_Mute_Status\t\t%lu\n", BIT(dword, 22));
+	printf("AUD_PIPE_CONV_CFG  Port_B_Out_Enable\t\t\t%lu\n",    REG_BIT(dword, 16));
+	printf("AUD_PIPE_CONV_CFG  Port_C_Out_Enable\t\t\t%lu\n",    REG_BIT(dword, 17));
+	printf("AUD_PIPE_CONV_CFG  Port_D_Out_Enable\t\t\t%lu\n",    REG_BIT(dword, 18));
+	printf("AUD_PIPE_CONV_CFG  Port_B_Amp_Mute_Status\t\t%lu\n", REG_BIT(dword, 20));
+	printf("AUD_PIPE_CONV_CFG  Port_C_Amp_Mute_Status\t\t%lu\n", REG_BIT(dword, 21));
+	printf("AUD_PIPE_CONV_CFG  Port_D_Amp_Mute_Status\t\t%lu\n", REG_BIT(dword, 22));
 }
 
 static void dump_aud_dig_cnvt(int index)
@@ -1614,16 +1614,16 @@
 		sprintf(prefix, "AUD_C%c_DIG_CNVT   ", '1' + index - CONVERTER_1);
 	}
 
-	printf("%s  V\t\t\t\t\t%lu\n",               prefix, BIT(dword, 1));
-	printf("%s  VCFG\t\t\t\t%lu\n",              prefix, BIT(dword, 2));
-	printf("%s  PRE\t\t\t\t\t%lu\n",             prefix, BIT(dword, 3));
-	printf("%s  Copy\t\t\t\t%lu\n",              prefix, BIT(dword, 4));
-	printf("%s  NonAudio\t\t\t\t%lu\n",          prefix, BIT(dword, 5));
-	printf("%s  PRO\t\t\t\t\t%lu\n",             prefix, BIT(dword, 6));
-	printf("%s  Level\t\t\t\t%lu\n",             prefix, BIT(dword, 7));
-	printf("%s  Category_Code\t\t\t%lu\n",       prefix, BITS(dword, 14, 8));
-	printf("%s  Lowest_Channel_Number\t\t%lu\n", prefix, BITS(dword, 19, 16));
-	printf("%s  Stream_ID\t\t\t\t%lu\n",         prefix, BITS(dword, 23, 20));
+	printf("%s  V\t\t\t\t\t%lu\n",               prefix, REG_BIT(dword, 1));
+	printf("%s  VCFG\t\t\t\t%lu\n",              prefix, REG_BIT(dword, 2));
+	printf("%s  PRE\t\t\t\t\t%lu\n",             prefix, REG_BIT(dword, 3));
+	printf("%s  Copy\t\t\t\t%lu\n",              prefix, REG_BIT(dword, 4));
+	printf("%s  NonAudio\t\t\t\t%lu\n",          prefix, REG_BIT(dword, 5));
+	printf("%s  PRO\t\t\t\t\t%lu\n",             prefix, REG_BIT(dword, 6));
+	printf("%s  Level\t\t\t\t%lu\n",             prefix, REG_BIT(dword, 7));
+	printf("%s  Category_Code\t\t\t%lu\n",       prefix, REG_BITS(dword, 14, 8));
+	printf("%s  Lowest_Channel_Number\t\t%lu\n", prefix, REG_BITS(dword, 19, 16));
+	printf("%s  Stream_ID\t\t\t\t%lu\n",         prefix, REG_BITS(dword, 23, 20));
 }
 
 static void dump_aud_str_desc(int index)
@@ -1640,24 +1640,24 @@
 		sprintf(prefix, "AUD_C%c_STR_DESC  ", '1' + index - CONVERTER_1);
 	}
 
-	printf("%s  Number_of_Channels_in_a_Stream\t%lu\n",   prefix, BITS(dword, 3, 0) + 1);
-	printf("%s  Bits_per_Sample\t\t\t[%#lx] %s\n",        prefix, BITS(dword, 6, 4),
-		OPNAME(bits_per_sample, BITS(dword, 6, 4)));
+	printf("%s  Number_of_Channels_in_a_Stream\t%lu\n",   prefix, REG_BITS(dword, 3, 0) + 1);
+	printf("%s  Bits_per_Sample\t\t\t[%#lx] %s\n",        prefix, REG_BITS(dword, 6, 4),
+		OPNAME(bits_per_sample, REG_BITS(dword, 6, 4)));
 
-	printf("%s  Sample_Base_Rate_Divisor\t\t[%#lx] %s\n", prefix, BITS(dword, 10, 8),
-		OPNAME(sample_base_rate_divisor, BITS(dword, 10, 8)));
-	printf("%s  Sample_Base_Rate_Mult\t\t[%#lx] %s\n",    prefix, BITS(dword, 13, 11),
-		OPNAME(sample_base_rate_mult, BITS(dword, 13, 11)));
-	printf("%s  Sample_Base_Rate\t\t\t[%#lx] %s\t",       prefix, BIT(dword, 14),
-		OPNAME(sample_base_rate, BIT(dword, 14)));
-	rate = (BIT(dword, 14) ? 44100 : 48000) * (BITS(dword, 13, 11) + 1)
-		/(BITS(dword, 10, 8) + 1);
+	printf("%s  Sample_Base_Rate_Divisor\t\t[%#lx] %s\n", prefix, REG_BITS(dword, 10, 8),
+		OPNAME(sample_base_rate_divisor, REG_BITS(dword, 10, 8)));
+	printf("%s  Sample_Base_Rate_Mult\t\t[%#lx] %s\n",    prefix, REG_BITS(dword, 13, 11),
+		OPNAME(sample_base_rate_mult, REG_BITS(dword, 13, 11)));
+	printf("%s  Sample_Base_Rate\t\t\t[%#lx] %s\t",       prefix, REG_BIT(dword, 14),
+		OPNAME(sample_base_rate, REG_BIT(dword, 14)));
+	rate = (REG_BIT(dword, 14) ? 44100 : 48000) * (REG_BITS(dword, 13, 11) + 1)
+		/(REG_BITS(dword, 10, 8) + 1);
 	printf("=> Sample Rate %d Hz\n", rate);
 
-	printf("%s  Convertor_Channel_Count\t\t%lu\n",        prefix, BITS(dword, 20, 16) + 1);
+	printf("%s  Convertor_Channel_Count\t\t%lu\n",        prefix, REG_BITS(dword, 20, 16) + 1);
 
 	if (!IS_HASWELL_PLUS(devid))
-		printf("%s  HBR_enable\t\t\t\t%lu\n",         prefix, BITS(dword, 28, 27));
+		printf("%s  HBR_enable\t\t\t\t%lu\n",         prefix, REG_BITS(dword, 28, 27));
 }
 
 #define dump_aud_out_ch_str		dump_aud_out_chan_map
@@ -1671,10 +1671,10 @@
 		OUTREG(aud_reg_base + AUD_OUT_CHAN_MAP, i | (i << 8) | (i << 16));
 		dword = INREG(aud_reg_base + 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));
+				1 + REG_BITS(dword,  3,  0),
+				1 + REG_BITS(dword,  7,  4),
+				1 + REG_BITS(dword, 15, 12),
+				1 + REG_BITS(dword, 23, 20));
 	}
 }
 
@@ -1686,10 +1686,10 @@
 	dword = INREG(aud_reg_base + AUD_PINW_CONNLNG_LIST);
 	sprintf(prefix, "AUD_PINW_CONNLNG_LIST");
 
-	printf("%s  Connect_List_Length\t\t%lu\n",     prefix, BITS(dword, 6, 0));
-	printf("%s  Form \t\t\t\t[%#lx] %s\n",         prefix, BIT(dword, 7),
-		OPNAME(connect_list_form, BIT(dword, 7)));
-	printf("%s  Connect_List_Entry\t\t%lu, %lu\n", prefix, BITS(dword, 15, 8), BITS(dword, 23, 16));
+	printf("%s  Connect_List_Length\t\t%lu\n",     prefix, REG_BITS(dword, 6, 0));
+	printf("%s  Form \t\t\t\t[%#lx] %s\n",         prefix, REG_BIT(dword, 7),
+		OPNAME(connect_list_form, REG_BIT(dword, 7)));
+	printf("%s  Connect_List_Entry\t\t%lu, %lu\n", prefix, REG_BITS(dword, 15, 8), REG_BITS(dword, 23, 16));
 }
 
 static void dump_aud_connect_select(void)
@@ -1706,9 +1706,9 @@
 		sprintf(prefix, "AUD_PINW_CONNLNG_SEL  ");
 	}
 
-	printf("%s  Connection_select_Port_B\t%#lx\n", prefix, BITS(dword,  7,  0));
-	printf("%s  Connection_select_Port_C\t%#lx\n", prefix, BITS(dword, 15,  8));
-	printf("%s  Connection_select_Port_D\t%#lx\n", prefix, BITS(dword, 23, 16));
+	printf("%s  Connection_select_Port_B\t%#lx\n", prefix, REG_BITS(dword,  7,  0));
+	printf("%s  Connection_select_Port_C\t%#lx\n", prefix, REG_BITS(dword, 15,  8));
+	printf("%s  Connection_select_Port_D\t%#lx\n", prefix, REG_BITS(dword, 23, 16));
 }
 
 static void dump_aud_ctrl_state(int index)
@@ -1726,16 +1726,16 @@
 		printf("Audio control state - Pipe %c\n",  'A' + index - PIPE_A);
 	}
 
-	printf("\tELD_ACK\t\t\t\t\t\t%lu\n",                                 BIT(dword, 4));
-	printf("\tELD_buffer_size\t\t\t\t\t%lu\n",                           BITS(dword, 14, 10));
-	printf("\tDIP_transmission_frequency\t\t\t[0x%lx] %s\n",             BITS(dword, 17, 16),
-		dip_trans[BITS(dword, 17, 16)]);
-	printf("\tDIP Buffer Index \t\t\t\t[0x%lx] %s\n",                    BITS(dword, 20, 18),
-		dip_index[BITS(dword, 20, 18)]);
-	printf("\tAudio DIP type enable status\t\t\t[0x%04lx] %s, %s, %s\n", BITS(dword, 24, 21),
-		dip_type[BIT(dword, 21)], dip_gen1_state[BIT(dword, 22)],  dip_gen2_state[BIT(dword, 23)]);
-	printf("\tAudio DIP port select\t\t\t\t[0x%lx] %s\n",                BITS(dword, 30, 29),
-		dip_port[BITS(dword, 30, 29)]);
+	printf("\tELD_ACK\t\t\t\t\t\t%lu\n",                                 REG_BIT(dword, 4));
+	printf("\tELD_buffer_size\t\t\t\t\t%lu\n",                           REG_BITS(dword, 14, 10));
+	printf("\tDIP_transmission_frequency\t\t\t[0x%lx] %s\n",             REG_BITS(dword, 17, 16),
+		dip_trans[REG_BITS(dword, 17, 16)]);
+	printf("\tDIP Buffer Index \t\t\t\t[0x%lx] %s\n",                    REG_BITS(dword, 20, 18),
+		dip_index[REG_BITS(dword, 20, 18)]);
+	printf("\tAudio DIP type enable status\t\t\t[0x%04lx] %s, %s, %s\n", REG_BITS(dword, 24, 21),
+		dip_type[REG_BIT(dword, 21)], dip_gen1_state[REG_BIT(dword, 22)],  dip_gen2_state[REG_BIT(dword, 23)]);
+	printf("\tAudio DIP port select\t\t\t\t[0x%lx] %s\n",                REG_BITS(dword, 30, 29),
+		dip_port[REG_BITS(dword, 30, 29)]);
 	printf("\n");
 }
 
@@ -1744,12 +1744,12 @@
 	uint32_t dword;
 
 	dword = INREG(aud_reg_base + AUD_CNTL_ST2);
-	printf("AUD_CNTL_ST2  ELD_validB\t\t\t\t%lu\n",  BIT(dword, 0));
-	printf("AUD_CNTL_ST2  CP_ReadyB\t\t\t\t\t%lu\n", BIT(dword, 1));
-	printf("AUD_CNTL_ST2  ELD_validC\t\t\t\t%lu\n",  BIT(dword, 4));
-	printf("AUD_CNTL_ST2  CP_ReadyC\t\t\t\t\t%lu\n", BIT(dword, 5));
-	printf("AUD_CNTL_ST2  ELD_validD\t\t\t\t%lu\n",  BIT(dword, 8));
-	printf("AUD_CNTL_ST2  CP_ReadyD\t\t\t\t\t%lu\n", BIT(dword, 9));
+	printf("AUD_CNTL_ST2  ELD_validB\t\t\t\t%lu\n",  REG_BIT(dword, 0));
+	printf("AUD_CNTL_ST2  CP_ReadyB\t\t\t\t\t%lu\n", REG_BIT(dword, 1));
+	printf("AUD_CNTL_ST2  ELD_validC\t\t\t\t%lu\n",  REG_BIT(dword, 4));
+	printf("AUD_CNTL_ST2  CP_ReadyC\t\t\t\t\t%lu\n", REG_BIT(dword, 5));
+	printf("AUD_CNTL_ST2  ELD_validD\t\t\t\t%lu\n",  REG_BIT(dword, 8));
+	printf("AUD_CNTL_ST2  CP_ReadyD\t\t\t\t\t%lu\n", REG_BIT(dword, 9));
 }
 
 /* for hsw+ */
@@ -1758,18 +1758,18 @@
 	uint32_t dword;
 
 	dword = INREG(aud_reg_base + AUD_PIN_ELD_CP_VLD);
-	printf("AUD_PIN_ELD_CP_VLD  Transcoder_A ELD_valid\t\t%lu\n",	BIT(dword, 0));
-	printf("AUD_PIN_ELD_CP_VLD  Transcoder_A CP_Ready \t\t%lu\n",	BIT(dword, 1));
-	printf("AUD_PIN_ELD_CP_VLD  Transcoder_A Out_enable\t\t%lu\n",	BIT(dword, 2));
-	printf("AUD_PIN_ELD_CP_VLD  Transcoder_A Inactive\t\t%lu\n",	BIT(dword, 3));
-	printf("AUD_PIN_ELD_CP_VLD  Transcoder_B ELD_valid\t\t%lu\n",	BIT(dword, 4));
-	printf("AUD_PIN_ELD_CP_VLD  Transcoder_B CP_Ready\t\t%lu\n",	BIT(dword, 5));
-	printf("AUD_PIN_ELD_CP_VLD  Transcoder_B OUT_enable\t\t%lu\n",	BIT(dword, 6));
-	printf("AUD_PIN_ELD_CP_VLD  Transcoder_B Inactive\t\t%lu\n",    BIT(dword, 7));
-	printf("AUD_PIN_ELD_CP_VLD  Transcoder_C ELD_valid\t\t%lu\n",	BIT(dword, 8));
-	printf("AUD_PIN_ELD_CP_VLD  Transcoder_C CP_Ready\t\t%lu\n",	BIT(dword, 9));
-	printf("AUD_PIN_ELD_CP_VLD  Transcoder_C OUT_enable\t\t%lu\n",	BIT(dword, 10));
-	printf("AUD_PIN_ELD_CP_VLD  Transcoder_C Inactive\t\t%lu\n",    BIT(dword, 11));
+	printf("AUD_PIN_ELD_CP_VLD  Transcoder_A ELD_valid\t\t%lu\n",	REG_BIT(dword, 0));
+	printf("AUD_PIN_ELD_CP_VLD  Transcoder_A CP_Ready \t\t%lu\n",	REG_BIT(dword, 1));
+	printf("AUD_PIN_ELD_CP_VLD  Transcoder_A Out_enable\t\t%lu\n",	REG_BIT(dword, 2));
+	printf("AUD_PIN_ELD_CP_VLD  Transcoder_A Inactive\t\t%lu\n",	REG_BIT(dword, 3));
+	printf("AUD_PIN_ELD_CP_VLD  Transcoder_B ELD_valid\t\t%lu\n",	REG_BIT(dword, 4));
+	printf("AUD_PIN_ELD_CP_VLD  Transcoder_B CP_Ready\t\t%lu\n",	REG_BIT(dword, 5));
+	printf("AUD_PIN_ELD_CP_VLD  Transcoder_B OUT_enable\t\t%lu\n",	REG_BIT(dword, 6));
+	printf("AUD_PIN_ELD_CP_VLD  Transcoder_B Inactive\t\t%lu\n",    REG_BIT(dword, 7));
+	printf("AUD_PIN_ELD_CP_VLD  Transcoder_C ELD_valid\t\t%lu\n",	REG_BIT(dword, 8));
+	printf("AUD_PIN_ELD_CP_VLD  Transcoder_C CP_Ready\t\t%lu\n",	REG_BIT(dword, 9));
+	printf("AUD_PIN_ELD_CP_VLD  Transcoder_C OUT_enable\t\t%lu\n",	REG_BIT(dword, 10));
+	printf("AUD_PIN_ELD_CP_VLD  Transcoder_C Inactive\t\t%lu\n",    REG_BIT(dword, 11));
 }
 
 static void dump_aud_hdmi_status(void)
@@ -1777,12 +1777,12 @@
 	uint32_t dword;
 
 	dword = INREG(aud_reg_base + AUD_HDMIW_STATUS);
-	printf("AUD_HDMIW_STATUS  Function_Reset\t\t\t%lu\n",                BIT(dword, 24));
-	printf("AUD_HDMIW_STATUS  BCLK/CDCLK_FIFO_Overrun\t\t%lu\n",	     BIT(dword, 25));
-	printf("AUD_HDMIW_STATUS  Conv_A_CDCLK/DOTCLK_FIFO_Overrun\t%lu\n",  BIT(dword, 28));
-	printf("AUD_HDMIW_STATUS  Conv_A_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, 30));
-	printf("AUD_HDMIW_STATUS  Conv_B_CDCLK/DOTCLK_FIFO_Underrun\t%lu\n", BIT(dword, 31));
+	printf("AUD_HDMIW_STATUS  Function_Reset\t\t\t%lu\n",                REG_BIT(dword, 24));
+	printf("AUD_HDMIW_STATUS  BCLK/CDCLK_FIFO_Overrun\t\t%lu\n",	     REG_BIT(dword, 25));
+	printf("AUD_HDMIW_STATUS  Conv_A_CDCLK/DOTCLK_FIFO_Overrun\t%lu\n",  REG_BIT(dword, 28));
+	printf("AUD_HDMIW_STATUS  Conv_A_CDCLK/DOTCLK_FIFO_Underrun\t%lu\n", REG_BIT(dword, 29));
+	printf("AUD_HDMIW_STATUS  Conv_B_CDCLK/DOTCLK_FIFO_Overrun\t%lu\n",  REG_BIT(dword, 30));
+	printf("AUD_HDMIW_STATUS  Conv_B_CDCLK/DOTCLK_FIFO_Underrun\t%lu\n", REG_BIT(dword, 31));
 }
 
 /*
@@ -1818,13 +1818,13 @@
 
 	port_ctrl = disp_reg_base + DP_CTL_B + (port - PORT_B) * 0x100;
 	dword = INREG(port_ctrl);
-	printf("%s DisplayPort_Enable\t\t\t\t\t%lu\n",        prefix, BIT(dword, 31));
-	printf("%s Transcoder_Select\t\t\t\t\t%s\n",          prefix, BIT(dword, 30) ? "Transcoder B" : "Transcoder A");
-	printf("%s Port_Width_Selection\t\t\t\t[0x%lx] %s\n", prefix, BITS(dword, 21, 19),
-		dp_port_width[BITS(dword, 21, 19)]);
-	printf("%s Port_Detected\t\t\t\t\t%lu\n",             prefix, BIT(dword, 2));
-	printf("%s HDCP_Port_Select\t\t\t\t\t%lu\n",          prefix, BIT(dword, 5));
-	printf("%s Audio_Output_Enable\t\t\t\t%lu\n",         prefix, BIT(dword, 6));
+	printf("%s DisplayPort_Enable\t\t\t\t\t%lu\n",        prefix, REG_BIT(dword, 31));
+	printf("%s Transcoder_Select\t\t\t\t\t%s\n",          prefix, REG_BIT(dword, 30) ? "Transcoder B" : "Transcoder A");
+	printf("%s Port_Width_Selection\t\t\t\t[0x%lx] %s\n", prefix, REG_BITS(dword, 21, 19),
+		dp_port_width[REG_BITS(dword, 21, 19)]);
+	printf("%s Port_Detected\t\t\t\t\t%lu\n",             prefix, REG_BIT(dword, 2));
+	printf("%s HDCP_Port_Select\t\t\t\t\t%lu\n",          prefix, REG_BIT(dword, 5));
+	printf("%s Audio_Output_Enable\t\t\t\t%lu\n",         prefix, REG_BIT(dword, 6));
 }
 
 static void dump_hdmi_port_ctrl(int port)
@@ -1843,13 +1843,13 @@
 
 	dword = INREG(port_ctrl);
 	printf("%s HDMI_Enable\t\t\t\t\t%u\n",                 prefix, !!(dword & SDVO_ENABLE));
-	printf("%s Transcoder_Select\t\t\t\t%s\n",             prefix, BIT(dword, 30) ? "Transcoder B" : "Transcoder A");
-	printf("%s HDCP_Port_Select\t\t\t\t%lu\n",             prefix, BIT(dword, 5));
+	printf("%s Transcoder_Select\t\t\t\t%s\n",             prefix, REG_BIT(dword, 30) ? "Transcoder B" : "Transcoder A");
+	printf("%s HDCP_Port_Select\t\t\t\t%lu\n",             prefix, REG_BIT(dword, 5));
 	if (port == PORT_B) /* TODO: check spec, not found in Ibx b-spec, and only for port B? */
-		printf("%s SDVO Hot Plug Interrupt Detect Enable\t%lu\n", prefix, BIT(dword, 23));
-	printf("%s Digital_Port_Detected\t\t\t%lu\n",          prefix, BIT(dword, 2));
-	printf("%s Encoding\t\t\t\t\t[0x%lx] %s\n",            prefix, BITS(dword, 11, 10),
-		sdvo_hdmi_encoding[BITS(dword, 11, 10)]);
+		printf("%s SDVO Hot Plug Interrupt Detect Enable\t%lu\n", prefix, REG_BIT(dword, 23));
+	printf("%s Digital_Port_Detected\t\t\t%lu\n",          prefix, REG_BIT(dword, 2));
+	printf("%s Encoding\t\t\t\t\t[0x%lx] %s\n",            prefix, REG_BITS(dword, 11, 10),
+		sdvo_hdmi_encoding[REG_BITS(dword, 11, 10)]);
 	printf("%s Null_packets_enabled_during_Vsync\t\t%u\n", prefix, !!(dword & SDVO_NULL_PACKETS_DURING_VSYNC));
 	printf("%s Audio_Output_Enable\t\t\t\t%u\n",           prefix, !!(dword & SDVO_AUDIO_ENABLE));
 }
@@ -2032,9 +2032,9 @@
 	dword = INREG(DDI_BUF_CTL_A + (port - PORT_A) * 0x100);
 	printf("DDI %c Buffer control\n", 'A' + port - PORT_A);
 
-	printf("\tDP port width\t\t\t\t\t[0x%lx] %s\n", BITS(dword, 3, 1),
-		OPNAME(dp_port_width, BITS(dword, 3, 1)));
-	printf("\tDDI Buffer Enable\t\t\t\t%ld\n",      BIT(dword, 31));
+	printf("\tDP port width\t\t\t\t\t[0x%lx] %s\n", REG_BITS(dword, 3, 1),
+		OPNAME(dp_port_width, REG_BITS(dword, 3, 1)));
+	printf("\tDDI Buffer Enable\t\t\t\t%ld\n",      REG_BIT(dword, 31));
 }
 
 static void dump_ddi_func_ctl(int pipe)
@@ -2044,13 +2044,13 @@
 	dword = INREG(PIPE_DDI_FUNC_CTL_A + (pipe - PIPE_A) * 0x1000);
 	printf("Pipe %c DDI Function Control\n", 'A' + pipe - PIPE_A);
 
-	printf("\tBITS per color\t\t\t\t\t[0x%lx] %s\n",    BITS(dword, 22, 20),
-		OPNAME(bits_per_color, BITS(dword, 22, 20)));
-	printf("\tPIPE DDI Mode\t\t\t\t\t[0x%lx] %s\n",     BITS(dword, 26, 24),
-		OPNAME(ddi_mode, BITS(dword, 26, 24)));
-	printf("\tPIPE DDI selection\t\t\t\t[0x%lx] %s\n",  BITS(dword, 30, 28),
-		OPNAME(trans_to_port_sel, BITS(dword, 30, 28)));
-	printf("\tPIPE DDI Function Enable\t\t\t[0x%lx]\n", BIT(dword, 31));
+	printf("\tREG_BITS per color\t\t\t\t\t[0x%lx] %s\n", REG_BITS(dword, 22, 20),
+		OPNAME(bits_per_color, REG_BITS(dword, 22, 20)));
+	printf("\tPIPE DDI Mode\t\t\t\t\t[0x%lx] %s\n",     REG_BITS(dword, 26, 24),
+		OPNAME(ddi_mode, REG_BITS(dword, 26, 24)));
+	printf("\tPIPE DDI selection\t\t\t\t[0x%lx] %s\n",  REG_BITS(dword, 30, 28),
+		OPNAME(trans_to_port_sel, REG_BITS(dword, 30, 28)));
+	printf("\tPIPE DDI Function Enable\t\t\t[0x%lx]\n", REG_BIT(dword, 31));
 }
 
 static void dump_aud_connect_list_entry_length(int transcoder)
@@ -2061,10 +2061,10 @@
 	dword = INREG(aud_reg_base + AUD_TCA_PIN_PIPE_CONN_ENTRY_LNGTH + (transcoder - TRANSCODER_A) * 0x100);
 	sprintf(prefix, "AUD_TC%c_PIN_PIPE_CONN_ENTRY_LNGTH", 'A' + transcoder - TRANSCODER_A);
 
-	printf("%s  Connect_List_Length\t%lu\n", prefix, BITS(dword, 6, 0));
-	printf("%s  Form \t\t[%#lx] %s\n",       prefix, BIT(dword, 7),
-		OPNAME(connect_list_form, BIT(dword, 7)));
-	printf("%s  Connect_List_Entry\t%lu\n",  prefix, BITS(dword, 15, 8));
+	printf("%s  Connect_List_Length\t%lu\n", prefix, REG_BITS(dword, 6, 0));
+	printf("%s  Form \t\t[%#lx] %s\n",       prefix, REG_BIT(dword, 7),
+		OPNAME(connect_list_form, REG_BIT(dword, 7)));
+	printf("%s  Connect_List_Entry\t%lu\n",  prefix, REG_BITS(dword, 15, 8));
 }
 
 static void dump_aud_connect_select_ctrl(void)
@@ -2072,9 +2072,9 @@
 	uint32_t dword;
 
 	dword = INREG(aud_reg_base + AUD_PIPE_CONN_SEL_CTRL);
-	printf("AUD_PIPE_CONN_SEL_CTRL  Connection_select_Port_B\t%#lx\n", BITS(dword,  7,  0));
-	printf("AUD_PIPE_CONN_SEL_CTRL  Connection_select_Port_C\t%#lx\n", BITS(dword, 15,  8));
-	printf("AUD_PIPE_CONN_SEL_CTRL  Connection_select_Port_D\t%#lx\n", BITS(dword, 23, 16));
+	printf("AUD_PIPE_CONN_SEL_CTRL  Connection_select_Port_B\t%#lx\n", REG_BITS(dword,  7,  0));
+	printf("AUD_PIPE_CONN_SEL_CTRL  Connection_select_Port_C\t%#lx\n", REG_BITS(dword, 15,  8));
+	printf("AUD_PIPE_CONN_SEL_CTRL  Connection_select_Port_D\t%#lx\n", REG_BITS(dword, 23, 16));
 }
 
 static void dump_aud_dip_eld_ctrl_st(int transcoder)
@@ -2085,16 +2085,16 @@
 	dword = INREG(aud_reg_base + AUD_TCA_DIP_ELD_CTRL_ST + offset);
 	printf("Audio DIP and ELD control state for Transcoder %c\n",  'A' + transcoder - TRANSCODER_A);
 
-	printf("\tELD_ACK\t\t\t\t\t\t%lu\n",                                 BIT(dword, 4));
-	printf("\tELD_buffer_size\t\t\t\t\t%lu\n",                           BITS(dword, 14, 10));
-	printf("\tDIP_transmission_frequency\t\t\t[0x%lx] %s\n",             BITS(dword, 17, 16),
-		dip_trans[BITS(dword, 17, 16)]);
-	printf("\tDIP Buffer Index \t\t\t\t[0x%lx] %s\n",                    BITS(dword, 20, 18),
-		dip_index[BITS(dword, 20, 18)]);
-	printf("\tAudio DIP type enable status\t\t\t[0x%04lx] %s, %s, %s\n", BITS(dword, 24, 21),
-		dip_type[BIT(dword, 21)], dip_gen1_state[BIT(dword, 22)],  dip_gen2_state[BIT(dword, 23)]);
-	printf("\tAudio DIP port select\t\t\t\t[0x%lx] %s\n",                BITS(dword, 30, 29),
-		dip_port[BITS(dword, 30, 29)]);
+	printf("\tELD_ACK\t\t\t\t\t\t%lu\n",                                 REG_BIT(dword, 4));
+	printf("\tELD_buffer_size\t\t\t\t\t%lu\n",                           REG_BITS(dword, 14, 10));
+	printf("\tDIP_transmission_frequency\t\t\t[0x%lx] %s\n",             REG_BITS(dword, 17, 16),
+		dip_trans[REG_BITS(dword, 17, 16)]);
+	printf("\tDIP Buffer Index \t\t\t\t[0x%lx] %s\n",                    REG_BITS(dword, 20, 18),
+		dip_index[REG_BITS(dword, 20, 18)]);
+	printf("\tAudio DIP type enable status\t\t\t[0x%04lx] %s, %s, %s\n", REG_BITS(dword, 24, 21),
+		dip_type[REG_BIT(dword, 21)], dip_gen1_state[REG_BIT(dword, 22)],  dip_gen2_state[REG_BIT(dword, 23)]);
+	printf("\tAudio DIP port select\t\t\t\t[0x%lx] %s\n",                REG_BITS(dword, 30, 29),
+		dip_port[REG_BITS(dword, 30, 29)]);
 	printf("\n");
 }
 
@@ -2103,39 +2103,39 @@
 	uint32_t dword;
 
 	dword = INREG(aud_reg_base + AUD_HDMI_FIFO_STATUS);
-	printf("AUD_HDMI_FIFO_STATUS  Function_Reset\t\t\t%lu\n",                BIT(dword, 24));
-	printf("AUD_HDMI_FIFO_STATUS  Conv_1_CDCLK/DOTCLK_FIFO_Overrun\t%lu\n",  BIT(dword, 26));
-	printf("AUD_HDMI_FIFO_STATUS  Conv_1_CDCLK/DOTCLK_FIFO_Underrun\t%lu\n", BIT(dword, 27));
-	printf("AUD_HDMI_FIFO_STATUS  Conv_2_CDCLK/DOTCLK_FIFO_Overrun\t%lu\n",  BIT(dword, 28));
-	printf("AUD_HDMI_FIFO_STATUS  Conv_2_CDCLK/DOTCLK_FIFO_Underrun\t%lu\n", BIT(dword, 29));
-	printf("AUD_HDMI_FIFO_STATUS  Conv_3_CDCLK/DOTCLK_FIFO_Overrun\t%lu\n",  BIT(dword, 30));
-	printf("AUD_HDMI_FIFO_STATUS  Conv_3_CDCLK/DOTCLK_FIFO_Underrun\t%lu\n", BIT(dword, 31));
+	printf("AUD_HDMI_FIFO_STATUS  Function_Reset\t\t\t%lu\n",                REG_BIT(dword, 24));
+	printf("AUD_HDMI_FIFO_STATUS  Conv_1_CDCLK/DOTCLK_FIFO_Overrun\t%lu\n",  REG_BIT(dword, 26));
+	printf("AUD_HDMI_FIFO_STATUS  Conv_1_CDCLK/DOTCLK_FIFO_Underrun\t%lu\n", REG_BIT(dword, 27));
+	printf("AUD_HDMI_FIFO_STATUS  Conv_2_CDCLK/DOTCLK_FIFO_Overrun\t%lu\n",  REG_BIT(dword, 28));
+	printf("AUD_HDMI_FIFO_STATUS  Conv_2_CDCLK/DOTCLK_FIFO_Underrun\t%lu\n", REG_BIT(dword, 29));
+	printf("AUD_HDMI_FIFO_STATUS  Conv_3_CDCLK/DOTCLK_FIFO_Overrun\t%lu\n",  REG_BIT(dword, 30));
+	printf("AUD_HDMI_FIFO_STATUS  Conv_3_CDCLK/DOTCLK_FIFO_Underrun\t%lu\n", REG_BIT(dword, 31));
 }
 
 static void parse_bdw_audio_chicken_bit_reg(uint32_t dword)
 {
 	printf("\t");
-	printf("%s\n\t", OPNAME(vanilla_dp12_en,           BIT(dword, 31)));
-	printf("%s\n\t", OPNAME(vanilla_3_widgets_en,      BIT(dword, 30)));
-	printf("%s\n\t", OPNAME(block_audio,               BIT(dword, 10)));
-	printf("%s\n\t", OPNAME(dis_eld_valid_pulse_trans, BIT(dword, 9)));
-	printf("%s\n\t", OPNAME(dis_pd_pulse_trans,        BIT(dword, 8)));
-	printf("%s\n\t", OPNAME(dis_ts_delta_err,          BIT(dword, 7)));
-	printf("%s\n\t", OPNAME(dis_ts_fix_dp_hbr,         BIT(dword, 6)));
-	printf("%s\n\t", OPNAME(pattern_gen_8_ch_en,       BIT(dword, 5)));
-	printf("%s\n\t", OPNAME(pattern_gen_2_ch_en,       BIT(dword, 4)));
-	printf("%s\n\t", OPNAME(fabric_32_44_dis,          BIT(dword, 3)));
-	printf("%s\n\t", OPNAME(epss_dis,                  BIT(dword, 2)));
-	printf("%s\n\t", OPNAME(ts_test_mode,              BIT(dword, 1)));
-	printf("%s\n",   OPNAME(en_mmio_program,           BIT(dword, 0)));
+	printf("%s\n\t", OPNAME(vanilla_dp12_en,           REG_BIT(dword, 31)));
+	printf("%s\n\t", OPNAME(vanilla_3_widgets_en,      REG_BIT(dword, 30)));
+	printf("%s\n\t", OPNAME(block_audio,               REG_BIT(dword, 10)));
+	printf("%s\n\t", OPNAME(dis_eld_valid_pulse_trans, REG_BIT(dword, 9)));
+	printf("%s\n\t", OPNAME(dis_pd_pulse_trans,        REG_BIT(dword, 8)));
+	printf("%s\n\t", OPNAME(dis_ts_delta_err,          REG_BIT(dword, 7)));
+	printf("%s\n\t", OPNAME(dis_ts_fix_dp_hbr,         REG_BIT(dword, 6)));
+	printf("%s\n\t", OPNAME(pattern_gen_8_ch_en,       REG_BIT(dword, 5)));
+	printf("%s\n\t", OPNAME(pattern_gen_2_ch_en,       REG_BIT(dword, 4)));
+	printf("%s\n\t", OPNAME(fabric_32_44_dis,          REG_BIT(dword, 3)));
+	printf("%s\n\t", OPNAME(epss_dis,                  REG_BIT(dword, 2)));
+	printf("%s\n\t", OPNAME(ts_test_mode,              REG_BIT(dword, 1)));
+	printf("%s\n",   OPNAME(en_mmio_program,           REG_BIT(dword, 0)));
 }
 
 static void parse_skl_audio_freq_cntrl_reg(uint32_t dword)
 {
 	printf("\t");
-	printf("%s\n\t", OPNAME(sdi_operate_mode,          BIT(dword, 15)));
-	printf("%s\n\t", OPNAME(bclk_96mhz,                BIT(dword, 4)));
-	printf("%s\n",   OPNAME(bclk_48mhz,                BIT(dword, 3)));
+	printf("%s\n\t", OPNAME(sdi_operate_mode,          REG_BIT(dword, 15)));
+	printf("%s\n\t", OPNAME(bclk_96mhz,                REG_BIT(dword, 4)));
+	printf("%s\n",   OPNAME(bclk_48mhz,                REG_BIT(dword, 3)));
 }
 
 /* Dump audio registers for Haswell and its successors (eg. Broadwell).
@@ -2311,10 +2311,10 @@
 	dump_aud_hdmi_fifo_status();
 
 	dword = read_aud_reg(AUD_ICS);
-	printf("IRV [%1lx] %s\t", BIT(dword, 1),
-		OPNAME(immed_result_valid, BIT(dword, 1)));
-	printf("ICB [%1lx] %s\n", BIT(dword, 1),
-		OPNAME(immed_cmd_busy, BIT(dword, 0)));
+	printf("IRV [%1lx] %s\t", REG_BIT(dword, 1),
+		OPNAME(immed_result_valid, REG_BIT(dword, 1)));
+	printf("ICB [%1lx] %s\n", REG_BIT(dword, 1),
+		OPNAME(immed_cmd_busy, REG_BIT(dword, 0)));
 
 	dword = read_aud_reg(AUD_CHICKENBIT_REG);
 	printf("AUD_CHICKENBIT_REG Audio Chicken Bits: %08x\n", dword);
@@ -2324,7 +2324,7 @@
 	dword = read_aud_reg(AUD_DP_DIP_STATUS);
 	printf("AUD_DP_DIP_STATUS Audio DP & DIP FIFO Status: %08x\n\t", dword);
 	for (i = 31; i >= 0; i--)
-		if (BIT(dword, i))
+		if (REG_BIT(dword, i))
 			printf("%s\n\t", audio_dp_dip_status[i]);
 	printf("\n");
 
diff --git a/tools/intel_l3_parity.c b/tools/intel_l3_parity.c
index d8c997a..4179c5a 100644
--- a/tools/intel_l3_parity.c
+++ b/tools/intel_l3_parity.c
@@ -195,6 +195,12 @@
 
 	for_each_slice(i) {
 		fd[i] = openat(dir, path[i], O_RDWR);
+		if (fd[i] < 0) {
+			if (i == 0) /* at least one slice must be supported */
+				exit(77);
+			continue;
+		}
+
 		if (read(fd[i], l3logs[i], NUM_REGS * sizeof(uint32_t)) < 0) {
 			perror(path[i]);
 			exit(77);
@@ -333,6 +339,9 @@
 
 	/* Per slice operations */
 	for_each_slice(i) {
+		if (fd[i] < 0)
+			continue;
+
 		switch (action) {
 			case 'l':
 				dumpit(i);
@@ -374,6 +383,9 @@
 		exit(EXIT_SUCCESS);
 
 	for_each_slice(i) {
+		if (fd[i] < 0)
+			continue;
+
 		ret = write(fd[i], l3logs[i], NUM_REGS * sizeof(uint32_t));
 		if (ret == -1) {
 			perror("Writing sysfs");
diff --git a/tools/intel_vbt_decode.c b/tools/intel_vbt_decode.c
index 38eccc4..3b9006f 100644
--- a/tools/intel_vbt_decode.c
+++ b/tools/intel_vbt_decode.c
@@ -944,11 +944,13 @@
 {
 	const struct bdb_psr *psr_block = block->data;
 	int i;
+	uint32_t psr2_tp_time;
 
 	/* The same block ID was used for something else before? */
 	if (context->bdb->version < 165)
 		return;
 
+	psr2_tp_time = psr_block->psr2_tp2_tp3_wakeup_time;
 	for (i = 0; i < 16; i++) {
 		const struct psr_table *psr = &psr_block->psr_table[i];
 
@@ -987,6 +989,15 @@
 		printf("\t\tTP2/TP3 wakeup time: %d usec (0x%x)\n",
 		       psr->tp2_tp3_wakeup_time * 100,
 		       psr->tp2_tp3_wakeup_time);
+
+		if (context->bdb->version >= 226) {
+			int index;
+			static const uint16_t psr2_tp_times[] = {500, 100, 2500, 5};
+
+			index = (psr2_tp_time >> (i * 2)) & 0x3;
+			printf("\t\tPSR2 TP2/TP3 wakeup time: %d usec (0x%x)\n",
+			       psr2_tp_times[index], index);
+		}
 	}
 }
 
diff --git a/tools/intel_vbt_defs.h b/tools/intel_vbt_defs.h
index 89ef14c..c903cda 100644
--- a/tools/intel_vbt_defs.h
+++ b/tools/intel_vbt_defs.h
@@ -475,13 +475,13 @@
 	/* TP wake up time in multiple of 100 */
 	u16 tp1_wakeup_time;
 	u16 tp2_tp3_wakeup_time;
-
-	/* PSR2 TP2/TP3 wakeup time for 16 panels */
-	u32 psr2_tp2_tp3_wakeup_time;
 } __packed;
 
 struct bdb_psr {
 	struct psr_table psr_table[16];
+
+	/* PSR2 TP2/TP3 wakeup time for 16 panels */
+	u32 psr2_tp2_tp3_wakeup_time;
 } __packed;
 
 /*