about summary refs log tree commit diff
path: root/modules/hardware
diff options
context:
space:
mode:
authoraszlig <aszlig@redmoonstudios.org>2016-03-01 07:14:38 +0100
committeraszlig <aszlig@redmoonstudios.org>2016-03-01 08:20:13 +0100
commite8861698f019eb218be451e444898a1cb5577d21 (patch)
tree4c558dc7a63d814647ddc96d432aef6a72f87bb8 /modules/hardware
parent8809e075a37035ee4daa61ba6e4d51268725de98 (diff)
hardware/t100ha: Switch to linux-next with patches
Both of these patches are from the following Google Drive:

https://drive.google.com/folderview?id=0B4DiU2o72FbuejQ1S2VZZW5xV2c

The meta-keys-asus.patch (which is called just meta-keys.patch in this
repository) is used verbatim.

However, the baytrail-backlight.4.4.patch (here just backlight.patch) is
a rebased version of the patch from the Google Drive with a few
modifications by me, which boils down to:

 * Remove the module parameter force_backlight_pmic, because this module
   is hardware-specific so we don't actually need to do that (and *if*
   we want to do that we'd compile it in directly).
 * Add an unused pipe function argument to vlv_pmic_setup_backlight().

As the backlight patch introduces the functions intel_soc_pmic_readb()
and intel_soc_pmic_writeb() which are not available at module link time,
I have also added DRM_I915 to be compiled into the kernel.

In addition I needed to disable VIDEO_EM28XX and RAPIDIO, because they
do not compile with linux-next-20160226 and I didn't bother to provide
fixes because it's for hardware that is not existing on the T100HA.

Note that I'm using linux-next-20160226 here instead of 20160229 because
the latter has some networking I/O issues right now.

This makes the backlight, battery status and charging usable on the
T100HA and the fixes from the drm-intel-fixes branch are no longer
needed because they're already in linux-next-20160229.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
Diffstat (limited to 'modules/hardware')
-rw-r--r--modules/hardware/t100ha/backlight.patch225
-rw-r--r--modules/hardware/t100ha/default.nix32
-rw-r--r--modules/hardware/t100ha/drm-fixes.patch1019
-rw-r--r--modules/hardware/t100ha/meta-keys.patch44
4 files changed, 292 insertions, 1028 deletions
diff --git a/modules/hardware/t100ha/backlight.patch b/modules/hardware/t100ha/backlight.patch
new file mode 100644
index 00000000..8791ab56
--- /dev/null
+++ b/modules/hardware/t100ha/backlight.patch
@@ -0,0 +1,225 @@
+diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
+index 01b8e9f..ef74047 100644
+--- a/drivers/gpu/drm/i915/intel_dsi.c
++++ b/drivers/gpu/drm/i915/intel_dsi.c
+@@ -551,6 +551,8 @@ static void intel_dsi_disable(struct intel_encoder *encoder)
+ 	struct drm_device *dev = encoder->base.dev;
+ 	struct drm_i915_private *dev_priv = dev->dev_private;
+ 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
++	struct intel_connector *intel_connector =
++		intel_dsi->attached_connector;
+ 	enum port port;
+ 	u32 temp;
+ 
+@@ -564,6 +566,8 @@ static void intel_dsi_disable(struct intel_encoder *encoder)
+ 		msleep(2);
+ 	}
+ 
++	intel_panel_disable_backlight(intel_connector);
++
+ 	for_each_dsi_port(port, intel_dsi->ports) {
+ 		/* Panel commands can be sent when clock is in LP11 */
+ 		I915_WRITE(MIPI_DEVICE_READY(port), 0x0);
+@@ -1065,6 +1069,7 @@ static void intel_dsi_connector_destroy(struct drm_connector *connector)
+ 
+ 	DRM_DEBUG_KMS("\n");
+ 	intel_panel_fini(&intel_connector->panel);
++	intel_panel_destroy_backlight(connector);
+ 	drm_connector_cleanup(connector);
+ 	kfree(connector);
+ }
+diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
+index 21ee647..ddd5743 100644
+--- a/drivers/gpu/drm/i915/intel_panel.c
++++ b/drivers/gpu/drm/i915/intel_panel.c
+@@ -32,6 +32,7 @@
+ 
+ #include <linux/kernel.h>
+ #include <linux/moduleparam.h>
++#include <linux/mfd/intel_soc_pmic.h>
+ #include <linux/pwm.h>
+ #include "intel_drv.h"
+ 
+@@ -544,6 +545,11 @@ static u32 pwm_get_backlight(struct intel_connector *connector)
+ 	return DIV_ROUND_UP(duty_ns * 100, CRC_PMIC_PWM_PERIOD_NS);
+ }
+ 
++static u32 vlv_pmic_get_backlight(struct intel_connector *connector)
++{
++	return intel_soc_pmic_readb(0x4E);
++}
++
+ static u32 intel_panel_get_backlight(struct intel_connector *connector)
+ {
+ 	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+@@ -635,6 +641,11 @@ static void pwm_set_backlight(struct intel_connector *connector, u32 level)
+ 	pwm_config(panel->backlight.pwm, duty_ns, CRC_PMIC_PWM_PERIOD_NS);
+ }
+ 
++static void vlv_pmic_set_backlight(struct intel_connector *connector, u32 level)
++{
++	intel_soc_pmic_writeb(0x4E, level);
++}
++
+ static void
+ intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level)
+ {
+@@ -808,6 +819,14 @@ static void pwm_disable_backlight(struct intel_connector *connector)
+ 	pwm_disable(panel->backlight.pwm);
+ }
+ 
++static void vlv_pmic_disable_backlight(struct intel_connector *connector)
++{
++	intel_panel_actually_set_backlight(connector, 0);
++
++	intel_soc_pmic_writeb(0x51, 0x00);
++	intel_soc_pmic_writeb(0x4B, 0x7F);
++}
++
+ void intel_panel_disable_backlight(struct intel_connector *connector)
+ {
+ 	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+@@ -1073,6 +1092,17 @@ static void pwm_enable_backlight(struct intel_connector *connector)
+ 	intel_panel_actually_set_backlight(connector, panel->backlight.level);
+ }
+ 
++static void vlv_pmic_enable_backlight(struct intel_connector *connector)
++{
++	struct intel_panel *panel = &connector->panel;
++
++	intel_soc_pmic_writeb(0x4B, 0xFF);
++	intel_soc_pmic_writeb(0x4E, 0xFF);
++	intel_soc_pmic_writeb(0x51, 0x01);
++
++	intel_panel_actually_set_backlight(connector, panel->backlight.level);
++}
++
+ void intel_panel_enable_backlight(struct intel_connector *connector)
+ {
+ 	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+@@ -1659,6 +1689,21 @@ static int pwm_setup_backlight(struct intel_connector *connector,
+ 	return 0;
+ }
+ 
++static int vlv_pmic_setup_backlight(struct intel_connector *connector,
++		enum pipe unused)
++{
++	struct intel_panel *panel = &connector->panel;
++
++	printk("vlv_pmic_setup_backlight\n");
++	panel->backlight.present = 1;
++	panel->backlight.min = 0x00;
++	panel->backlight.max = 0xFF;
++	panel->backlight.level = 0x5A;
++	panel->backlight.enabled = 1;
++
++	return 0;
++}
++
+ int intel_panel_setup_backlight(struct drm_connector *connector, enum pipe pipe)
+ {
+ 	struct drm_i915_private *dev_priv = to_i915(connector->dev);
+@@ -1666,6 +1711,8 @@ int intel_panel_setup_backlight(struct drm_connector *connector, enum pipe pipe)
+ 	struct intel_panel *panel = &intel_connector->panel;
+ 	int ret;
+ 
++	intel_backlight_device_register(intel_connector);
++
+ 	if (!dev_priv->vbt.backlight.present) {
+ 		if (dev_priv->quirks & QUIRK_BACKLIGHT_PRESENT) {
+ 			DRM_DEBUG_KMS("no backlight present per VBT, but present per quirk\n");
+@@ -1746,18 +1793,17 @@ intel_panel_init_backlight_funcs(struct intel_panel *panel)
+ 		panel->backlight.hz_to_pwm = pch_hz_to_pwm;
+ 	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
+ 		if (dev_priv->vbt.has_mipi) {
+-			panel->backlight.setup = pwm_setup_backlight;
+-			panel->backlight.enable = pwm_enable_backlight;
+-			panel->backlight.disable = pwm_disable_backlight;
+-			panel->backlight.set = pwm_set_backlight;
+-			panel->backlight.get = pwm_get_backlight;
++			panel->backlight.setup = vlv_pmic_setup_backlight;
++			panel->backlight.enable = vlv_pmic_enable_backlight;
++			panel->backlight.disable = vlv_pmic_disable_backlight;
++			panel->backlight.set = vlv_pmic_set_backlight;
++			panel->backlight.get = vlv_pmic_get_backlight;
+ 		} else {
+ 			panel->backlight.setup = vlv_setup_backlight;
+ 			panel->backlight.enable = vlv_enable_backlight;
+ 			panel->backlight.disable = vlv_disable_backlight;
+ 			panel->backlight.set = vlv_set_backlight;
+ 			panel->backlight.get = vlv_get_backlight;
+-			panel->backlight.hz_to_pwm = vlv_hz_to_pwm;
+ 		}
+ 	} else if (IS_GEN4(dev_priv)) {
+ 		panel->backlight.setup = i965_setup_backlight;
+diff --git a/drivers/mfd/intel_soc_pmic_core.c b/drivers/mfd/intel_soc_pmic_core.c
+index d9e15cf..8af5afd 100644
+--- a/drivers/mfd/intel_soc_pmic_core.c
++++ b/drivers/mfd/intel_soc_pmic_core.c
+@@ -43,6 +43,8 @@ static struct pwm_lookup crc_pwm_lookup[] = {
+ 	PWM_LOOKUP("crystal_cove_pwm", 0, "0000:00:02.0", "pwm_backlight", 0, PWM_POLARITY_NORMAL),
+ };
+ 
++static struct intel_soc_pmic *pmic_hack = NULL;
++
+ static int intel_soc_pmic_find_gpio_irq(struct device *dev)
+ {
+ 	struct gpio_desc *desc;
+@@ -76,6 +78,7 @@ static int intel_soc_pmic_i2c_probe(struct i2c_client *i2c,
+ 	config = (struct intel_soc_pmic_config *)id->driver_data;
+ 
+ 	pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL);
++	pmic_hack = pmic;
+ 	if (!pmic)
+ 		return -ENOMEM;
+ 
+@@ -167,6 +170,37 @@ static int intel_soc_pmic_resume(struct device *dev)
+ }
+ #endif
+ 
++int intel_soc_pmic_readb(int reg)
++{
++	int ret;
++	unsigned int val;
++
++	if (!pmic_hack) {
++		ret = -EIO;
++	} else {
++		ret = regmap_read(pmic_hack->regmap, reg, &val);
++		if (!ret) {
++			ret = val;
++		}
++	}
++
++	return ret;
++}
++EXPORT_SYMBOL(intel_soc_pmic_readb);
++
++int intel_soc_pmic_writeb(int reg, u8 val)
++{
++	int ret;
++
++	if (!pmic_hack) {
++		ret = -EIO;
++	} else {
++		ret = regmap_write(pmic_hack->regmap, reg, val);
++	}
++	return ret;
++}
++EXPORT_SYMBOL(intel_soc_pmic_writeb);
++
+ static SIMPLE_DEV_PM_OPS(intel_soc_pmic_pm_ops, intel_soc_pmic_suspend,
+ 			 intel_soc_pmic_resume);
+ 
+diff --git a/include/linux/mfd/intel_soc_pmic.h b/include/linux/mfd/intel_soc_pmic.h
+index cf619db..52ad034 100644
+--- a/include/linux/mfd/intel_soc_pmic.h
++++ b/include/linux/mfd/intel_soc_pmic.h
+@@ -29,4 +29,7 @@ struct intel_soc_pmic {
+ 	struct device *dev;
+ };
+ 
++int intel_soc_pmic_readb(int reg);
++int intel_soc_pmic_writeb(int reg, u8 val);
++
+ #endif	/* __INTEL_SOC_PMIC_H__ */
diff --git a/modules/hardware/t100ha/default.nix b/modules/hardware/t100ha/default.nix
index 29645636..054680e8 100644
--- a/modules/hardware/t100ha/default.nix
+++ b/modules/hardware/t100ha/default.nix
@@ -12,22 +12,28 @@ in {
     # few additional patches:
     boot.kernelPackages = let
       nixpkgs = import ../../../nixpkgs-path.nix;
+      linuxNextVersion = "20160226";
       mkKernel = import "${nixpkgs}/pkgs/os-specific/linux/kernel/generic.nix";
       t100haKernel = mkKernel rec {
         version = "4.5-rc5";
-        modDirVersion = "4.5.0-rc5";
+        modDirVersion = "4.5.0-rc5-next-${linuxNextVersion}";
         extraMeta.branch = "4.5";
 
-        src = pkgs.fetchurl {
-          url = "mirror://kernel/linux/kernel/v4.x/testing/"
-              + "linux-${version}.tar.xz";
-          sha256 = "06qlypnrlkckxhf3clq6l2d3kps7rwfw811sxapjbnhzjd75fcx8";
+        src = pkgs.fetchgit {
+          url = "git://git.kernel.org/pub/scm/linux/kernel/git/next/"
+              + "linux-next.git";
+          rev = "refs/tags/next-${linuxNextVersion}";
+          sha256 = "0q39mnjyi8jany03b4ral34hicdrgjpab53hg712jzhbcngj5kh3";
         };
 
-        kernelPatches = lib.singleton {
-          name = "drm-fixes.patch";
-          patch = ./drm-fixes.patch;
-        };
+        kernelPatches = [
+          { name = "backlight";
+            patch = ./backlight.patch;
+          }
+          { name = "meta-keys";
+            patch = ./meta-keys.patch;
+          }
+        ];
 
         extraConfig = ''
           MMC y
@@ -36,6 +42,14 @@ in {
           MMC_SDHCI_ACPI y
           PINCTRL_CHERRYVIEW y
           INTEL_SOC_PMIC y
+
+          AGP n
+          DRM y
+          DRM_I915 y
+
+          # These do not compile as of 4.5.0-rc5-next-20160226:
+          VIDEO_EM28XX n
+          RAPIDIO n
         '';
 
         features.iwlwifi = true;
diff --git a/modules/hardware/t100ha/drm-fixes.patch b/modules/hardware/t100ha/drm-fixes.patch
deleted file mode 100644
index 2aceb0dc..00000000
--- a/modules/hardware/t100ha/drm-fixes.patch
+++ /dev/null
@@ -1,1019 +0,0 @@
-diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
-index 0fc38bb..cf39ed3 100644
---- a/drivers/gpu/drm/i915/i915_debugfs.c
-+++ b/drivers/gpu/drm/i915/i915_debugfs.c
-@@ -825,8 +825,11 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
- 		}
- 
- 		for_each_pipe(dev_priv, pipe) {
--			if (!intel_display_power_is_enabled(dev_priv,
--						POWER_DOMAIN_PIPE(pipe))) {
-+			enum intel_display_power_domain power_domain;
-+
-+			power_domain = POWER_DOMAIN_PIPE(pipe);
-+			if (!intel_display_power_get_if_enabled(dev_priv,
-+								power_domain)) {
- 				seq_printf(m, "Pipe %c power disabled\n",
- 					   pipe_name(pipe));
- 				continue;
-@@ -840,6 +843,8 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
- 			seq_printf(m, "Pipe %c IER:\t%08x\n",
- 				   pipe_name(pipe),
- 				   I915_READ(GEN8_DE_PIPE_IER(pipe)));
-+
-+			intel_display_power_put(dev_priv, power_domain);
- 		}
- 
- 		seq_printf(m, "Display Engine port interrupt mask:\t%08x\n",
-@@ -3985,6 +3990,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
- 	struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe];
- 	struct intel_crtc *crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev,
- 									pipe));
-+	enum intel_display_power_domain power_domain;
- 	u32 val = 0; /* shut up gcc */
- 	int ret;
- 
-@@ -3995,7 +4001,8 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
- 	if (pipe_crc->source && source)
- 		return -EINVAL;
- 
--	if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PIPE(pipe))) {
-+	power_domain = POWER_DOMAIN_PIPE(pipe);
-+	if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) {
- 		DRM_DEBUG_KMS("Trying to capture CRC while pipe is off\n");
- 		return -EIO;
- 	}
-@@ -4012,7 +4019,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
- 		ret = ivb_pipe_crc_ctl_reg(dev, pipe, &source, &val);
- 
- 	if (ret != 0)
--		return ret;
-+		goto out;
- 
- 	/* none -> real source transition */
- 	if (source) {
-@@ -4024,8 +4031,10 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
- 		entries = kcalloc(INTEL_PIPE_CRC_ENTRIES_NR,
- 				  sizeof(pipe_crc->entries[0]),
- 				  GFP_KERNEL);
--		if (!entries)
--			return -ENOMEM;
-+		if (!entries) {
-+			ret = -ENOMEM;
-+			goto out;
-+		}
- 
- 		/*
- 		 * When IPS gets enabled, the pipe CRC changes. Since IPS gets
-@@ -4081,7 +4090,12 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
- 		hsw_enable_ips(crtc);
- 	}
- 
--	return 0;
-+	ret = 0;
-+
-+out:
-+	intel_display_power_put(dev_priv, power_domain);
-+
-+	return ret;
- }
- 
- /*
-diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
-index e7cd311..b0847b9 100644
---- a/drivers/gpu/drm/i915/i915_drv.h
-+++ b/drivers/gpu/drm/i915/i915_drv.h
-@@ -751,6 +751,7 @@ struct intel_csr {
- 	uint32_t mmio_count;
- 	i915_reg_t mmioaddr[8];
- 	uint32_t mmiodata[8];
-+	uint32_t dc_state;
- };
- 
- #define DEV_INFO_FOR_EACH_FLAG(func, sep) \
-diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
-index 9c89df1..a7b4a524 100644
---- a/drivers/gpu/drm/i915/intel_crt.c
-+++ b/drivers/gpu/drm/i915/intel_crt.c
-@@ -71,22 +71,29 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder,
- 	struct intel_crt *crt = intel_encoder_to_crt(encoder);
- 	enum intel_display_power_domain power_domain;
- 	u32 tmp;
-+	bool ret;
- 
- 	power_domain = intel_display_port_power_domain(encoder);
--	if (!intel_display_power_is_enabled(dev_priv, power_domain))
-+	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
- 		return false;
- 
-+	ret = false;
-+
- 	tmp = I915_READ(crt->adpa_reg);
- 
- 	if (!(tmp & ADPA_DAC_ENABLE))
--		return false;
-+		goto out;
- 
- 	if (HAS_PCH_CPT(dev))
- 		*pipe = PORT_TO_PIPE_CPT(tmp);
- 	else
- 		*pipe = PORT_TO_PIPE(tmp);
- 
--	return true;
-+	ret = true;
-+out:
-+	intel_display_power_put(dev_priv, power_domain);
-+
-+	return ret;
- }
- 
- static unsigned int intel_crt_get_flags(struct intel_encoder *encoder)
-diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c
-index 9bb63a8..647d85e 100644
---- a/drivers/gpu/drm/i915/intel_csr.c
-+++ b/drivers/gpu/drm/i915/intel_csr.c
-@@ -240,6 +240,8 @@ void intel_csr_load_program(struct drm_i915_private *dev_priv)
- 		I915_WRITE(dev_priv->csr.mmioaddr[i],
- 			   dev_priv->csr.mmiodata[i]);
- 	}
-+
-+	dev_priv->csr.dc_state = 0;
- }
- 
- static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv,
-diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
-index 54a165b..0f3df2c 100644
---- a/drivers/gpu/drm/i915/intel_ddi.c
-+++ b/drivers/gpu/drm/i915/intel_ddi.c
-@@ -1969,13 +1969,16 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
- 	enum transcoder cpu_transcoder;
- 	enum intel_display_power_domain power_domain;
- 	uint32_t tmp;
-+	bool ret;
- 
- 	power_domain = intel_display_port_power_domain(intel_encoder);
--	if (!intel_display_power_is_enabled(dev_priv, power_domain))
-+	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
- 		return false;
- 
--	if (!intel_encoder->get_hw_state(intel_encoder, &pipe))
--		return false;
-+	if (!intel_encoder->get_hw_state(intel_encoder, &pipe)) {
-+		ret = false;
-+		goto out;
-+	}
- 
- 	if (port == PORT_A)
- 		cpu_transcoder = TRANSCODER_EDP;
-@@ -1987,23 +1990,33 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
- 	switch (tmp & TRANS_DDI_MODE_SELECT_MASK) {
- 	case TRANS_DDI_MODE_SELECT_HDMI:
- 	case TRANS_DDI_MODE_SELECT_DVI:
--		return (type == DRM_MODE_CONNECTOR_HDMIA);
-+		ret = type == DRM_MODE_CONNECTOR_HDMIA;
-+		break;
- 
- 	case TRANS_DDI_MODE_SELECT_DP_SST:
--		if (type == DRM_MODE_CONNECTOR_eDP)
--			return true;
--		return (type == DRM_MODE_CONNECTOR_DisplayPort);
-+		ret = type == DRM_MODE_CONNECTOR_eDP ||
-+		      type == DRM_MODE_CONNECTOR_DisplayPort;
-+		break;
-+
- 	case TRANS_DDI_MODE_SELECT_DP_MST:
- 		/* if the transcoder is in MST state then
- 		 * connector isn't connected */
--		return false;
-+		ret = false;
-+		break;
- 
- 	case TRANS_DDI_MODE_SELECT_FDI:
--		return (type == DRM_MODE_CONNECTOR_VGA);
-+		ret = type == DRM_MODE_CONNECTOR_VGA;
-+		break;
- 
- 	default:
--		return false;
-+		ret = false;
-+		break;
- 	}
-+
-+out:
-+	intel_display_power_put(dev_priv, power_domain);
-+
-+	return ret;
- }
- 
- bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
-@@ -2015,15 +2028,18 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
- 	enum intel_display_power_domain power_domain;
- 	u32 tmp;
- 	int i;
-+	bool ret;
- 
- 	power_domain = intel_display_port_power_domain(encoder);
--	if (!intel_display_power_is_enabled(dev_priv, power_domain))
-+	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
- 		return false;
- 
-+	ret = false;
-+
- 	tmp = I915_READ(DDI_BUF_CTL(port));
- 
- 	if (!(tmp & DDI_BUF_CTL_ENABLE))
--		return false;
-+		goto out;
- 
- 	if (port == PORT_A) {
- 		tmp = I915_READ(TRANS_DDI_FUNC_CTL(TRANSCODER_EDP));
-@@ -2041,25 +2057,32 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
- 			break;
- 		}
- 
--		return true;
--	} else {
--		for (i = TRANSCODER_A; i <= TRANSCODER_C; i++) {
--			tmp = I915_READ(TRANS_DDI_FUNC_CTL(i));
-+		ret = true;
- 
--			if ((tmp & TRANS_DDI_PORT_MASK)
--			    == TRANS_DDI_SELECT_PORT(port)) {
--				if ((tmp & TRANS_DDI_MODE_SELECT_MASK) == TRANS_DDI_MODE_SELECT_DP_MST)
--					return false;
-+		goto out;
-+	}
- 
--				*pipe = i;
--				return true;
--			}
-+	for (i = TRANSCODER_A; i <= TRANSCODER_C; i++) {
-+		tmp = I915_READ(TRANS_DDI_FUNC_CTL(i));
-+
-+		if ((tmp & TRANS_DDI_PORT_MASK) == TRANS_DDI_SELECT_PORT(port)) {
-+			if ((tmp & TRANS_DDI_MODE_SELECT_MASK) ==
-+			    TRANS_DDI_MODE_SELECT_DP_MST)
-+				goto out;
-+
-+			*pipe = i;
-+			ret = true;
-+
-+			goto out;
- 		}
- 	}
- 
- 	DRM_DEBUG_KMS("No pipe for ddi port %c found\n", port_name(port));
- 
--	return false;
-+out:
-+	intel_display_power_put(dev_priv, power_domain);
-+
-+	return ret;
- }
- 
- void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc)
-@@ -2508,12 +2531,14 @@ static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv,
- {
- 	uint32_t val;
- 
--	if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS))
-+	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
- 		return false;
- 
- 	val = I915_READ(WRPLL_CTL(pll->id));
- 	hw_state->wrpll = val;
- 
-+	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
-+
- 	return val & WRPLL_PLL_ENABLE;
- }
- 
-@@ -2523,12 +2548,14 @@ static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv,
- {
- 	uint32_t val;
- 
--	if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS))
-+	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
- 		return false;
- 
- 	val = I915_READ(SPLL_CTL);
- 	hw_state->spll = val;
- 
-+	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
-+
- 	return val & SPLL_PLL_ENABLE;
- }
- 
-@@ -2645,16 +2672,19 @@ static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
- 	uint32_t val;
- 	unsigned int dpll;
- 	const struct skl_dpll_regs *regs = skl_dpll_regs;
-+	bool ret;
- 
--	if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS))
-+	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
- 		return false;
- 
-+	ret = false;
-+
- 	/* DPLL0 is not part of the shared DPLLs, so pll->id is 0 for DPLL1 */
- 	dpll = pll->id + 1;
- 
- 	val = I915_READ(regs[pll->id].ctl);
- 	if (!(val & LCPLL_PLL_ENABLE))
--		return false;
-+		goto out;
- 
- 	val = I915_READ(DPLL_CTRL1);
- 	hw_state->ctrl1 = (val >> (dpll * 6)) & 0x3f;
-@@ -2664,8 +2694,12 @@ static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
- 		hw_state->cfgcr1 = I915_READ(regs[pll->id].cfgcr1);
- 		hw_state->cfgcr2 = I915_READ(regs[pll->id].cfgcr2);
- 	}
-+	ret = true;
- 
--	return true;
-+out:
-+	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
-+
-+	return ret;
- }
- 
- static void skl_shared_dplls_init(struct drm_i915_private *dev_priv)
-@@ -2932,13 +2966,16 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
- {
- 	enum port port = (enum port)pll->id;	/* 1:1 port->PLL mapping */
- 	uint32_t val;
-+	bool ret;
- 
--	if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS))
-+	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
- 		return false;
- 
-+	ret = false;
-+
- 	val = I915_READ(BXT_PORT_PLL_ENABLE(port));
- 	if (!(val & PORT_PLL_ENABLE))
--		return false;
-+		goto out;
- 
- 	hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(port));
- 	hw_state->ebb0 &= PORT_PLL_P1_MASK | PORT_PLL_P2_MASK;
-@@ -2985,7 +3022,12 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
- 				 I915_READ(BXT_PORT_PCS_DW12_LN23(port)));
- 	hw_state->pcsdw12 &= LANE_STAGGER_MASK | LANESTAGGER_STRAP_OVRD;
- 
--	return true;
-+	ret = true;
-+
-+out:
-+	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
-+
-+	return ret;
- }
- 
- static void bxt_shared_dplls_init(struct drm_i915_private *dev_priv)
-@@ -3120,11 +3162,15 @@ bool intel_ddi_is_audio_enabled(struct drm_i915_private *dev_priv,
- {
- 	u32 temp;
- 
--	if (intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_AUDIO)) {
-+	if (intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_AUDIO)) {
- 		temp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
-+
-+		intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO);
-+
- 		if (temp & AUDIO_OUTPUT_ENABLE(intel_crtc->pipe))
- 			return true;
- 	}
-+
- 	return false;
- }
- 
-diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
-index 5feb657..46947ff 100644
---- a/drivers/gpu/drm/i915/intel_display.c
-+++ b/drivers/gpu/drm/i915/intel_display.c
-@@ -1351,18 +1351,21 @@ void assert_pipe(struct drm_i915_private *dev_priv,
- 	bool cur_state;
- 	enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
- 								      pipe);
-+	enum intel_display_power_domain power_domain;
- 
- 	/* if we need the pipe quirk it must be always on */
- 	if ((pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) ||
- 	    (pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE))
- 		state = true;
- 
--	if (!intel_display_power_is_enabled(dev_priv,
--				POWER_DOMAIN_TRANSCODER(cpu_transcoder))) {
--		cur_state = false;
--	} else {
-+	power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder);
-+	if (intel_display_power_get_if_enabled(dev_priv, power_domain)) {
- 		u32 val = I915_READ(PIPECONF(cpu_transcoder));
- 		cur_state = !!(val & PIPECONF_ENABLE);
-+
-+		intel_display_power_put(dev_priv, power_domain);
-+	} else {
-+		cur_state = false;
- 	}
- 
- 	I915_STATE_WARN(cur_state != state,
-@@ -8171,18 +8174,22 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
- {
- 	struct drm_device *dev = crtc->base.dev;
- 	struct drm_i915_private *dev_priv = dev->dev_private;
-+	enum intel_display_power_domain power_domain;
- 	uint32_t tmp;
-+	bool ret;
- 
--	if (!intel_display_power_is_enabled(dev_priv,
--					    POWER_DOMAIN_PIPE(crtc->pipe)))
-+	power_domain = POWER_DOMAIN_PIPE(crtc->pipe);
-+	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
- 		return false;
- 
- 	pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
- 	pipe_config->shared_dpll = DPLL_ID_PRIVATE;
- 
-+	ret = false;
-+
- 	tmp = I915_READ(PIPECONF(crtc->pipe));
- 	if (!(tmp & PIPECONF_ENABLE))
--		return false;
-+		goto out;
- 
- 	if (IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
- 		switch (tmp & PIPECONF_BPC_MASK) {
-@@ -8262,7 +8269,12 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
- 	pipe_config->base.adjusted_mode.crtc_clock =
- 		pipe_config->port_clock / pipe_config->pixel_multiplier;
- 
--	return true;
-+	ret = true;
-+
-+out:
-+	intel_display_power_put(dev_priv, power_domain);
-+
-+	return ret;
- }
- 
- static void ironlake_init_pch_refclk(struct drm_device *dev)
-@@ -9366,18 +9378,21 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
- {
- 	struct drm_device *dev = crtc->base.dev;
- 	struct drm_i915_private *dev_priv = dev->dev_private;
-+	enum intel_display_power_domain power_domain;
- 	uint32_t tmp;
-+	bool ret;
- 
--	if (!intel_display_power_is_enabled(dev_priv,
--					    POWER_DOMAIN_PIPE(crtc->pipe)))
-+	power_domain = POWER_DOMAIN_PIPE(crtc->pipe);
-+	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
- 		return false;
- 
- 	pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
- 	pipe_config->shared_dpll = DPLL_ID_PRIVATE;
- 
-+	ret = false;
- 	tmp = I915_READ(PIPECONF(crtc->pipe));
- 	if (!(tmp & PIPECONF_ENABLE))
--		return false;
-+		goto out;
- 
- 	switch (tmp & PIPECONF_BPC_MASK) {
- 	case PIPECONF_6BPC:
-@@ -9440,7 +9455,12 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
- 
- 	ironlake_get_pfit_config(crtc, pipe_config);
- 
--	return true;
-+	ret = true;
-+
-+out:
-+	intel_display_power_put(dev_priv, power_domain);
-+
-+	return ret;
- }
- 
- static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
-@@ -9950,12 +9970,17 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
- {
- 	struct drm_device *dev = crtc->base.dev;
- 	struct drm_i915_private *dev_priv = dev->dev_private;
--	enum intel_display_power_domain pfit_domain;
-+	enum intel_display_power_domain power_domain;
-+	unsigned long power_domain_mask;
- 	uint32_t tmp;
-+	bool ret;
- 
--	if (!intel_display_power_is_enabled(dev_priv,
--					 POWER_DOMAIN_PIPE(crtc->pipe)))
-+	power_domain = POWER_DOMAIN_PIPE(crtc->pipe);
-+	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
- 		return false;
-+	power_domain_mask = BIT(power_domain);
-+
-+	ret = false;
- 
- 	pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
- 	pipe_config->shared_dpll = DPLL_ID_PRIVATE;
-@@ -9982,13 +10007,14 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
- 			pipe_config->cpu_transcoder = TRANSCODER_EDP;
- 	}
- 
--	if (!intel_display_power_is_enabled(dev_priv,
--			POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder)))
--		return false;
-+	power_domain = POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder);
-+	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
-+		goto out;
-+	power_domain_mask |= BIT(power_domain);
- 
- 	tmp = I915_READ(PIPECONF(pipe_config->cpu_transcoder));
- 	if (!(tmp & PIPECONF_ENABLE))
--		return false;
-+		goto out;
- 
- 	haswell_get_ddi_port_state(crtc, pipe_config);
- 
-@@ -9998,14 +10024,14 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
- 		skl_init_scalers(dev, crtc, pipe_config);
- 	}
- 
--	pfit_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe);
--
- 	if (INTEL_INFO(dev)->gen >= 9) {
- 		pipe_config->scaler_state.scaler_id = -1;
- 		pipe_config->scaler_state.scaler_users &= ~(1 << SKL_CRTC_INDEX);
- 	}
- 
--	if (intel_display_power_is_enabled(dev_priv, pfit_domain)) {
-+	power_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe);
-+	if (intel_display_power_get_if_enabled(dev_priv, power_domain)) {
-+		power_domain_mask |= BIT(power_domain);
- 		if (INTEL_INFO(dev)->gen >= 9)
- 			skylake_get_pfit_config(crtc, pipe_config);
- 		else
-@@ -10023,7 +10049,13 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
- 		pipe_config->pixel_multiplier = 1;
- 	}
- 
--	return true;
-+	ret = true;
-+
-+out:
-+	for_each_power_domain(power_domain, power_domain_mask)
-+		intel_display_power_put(dev_priv, power_domain);
-+
-+	return ret;
- }
- 
- static void i845_update_cursor(struct drm_crtc *crtc, u32 base, bool on)
-@@ -13630,7 +13662,7 @@ static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
- {
- 	uint32_t val;
- 
--	if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS))
-+	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
- 		return false;
- 
- 	val = I915_READ(PCH_DPLL(pll->id));
-@@ -13638,6 +13670,8 @@ static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
- 	hw_state->fp0 = I915_READ(PCH_FP0(pll->id));
- 	hw_state->fp1 = I915_READ(PCH_FP1(pll->id));
- 
-+	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
-+
- 	return val & DPLL_VCO_ENABLE;
- }
- 
-@@ -15568,10 +15602,12 @@ void i915_redisable_vga(struct drm_device *dev)
- 	 * level, just check if the power well is enabled instead of trying to
- 	 * follow the "don't touch the power well if we don't need it" policy
- 	 * the rest of the driver uses. */
--	if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_VGA))
-+	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_VGA))
- 		return;
- 
- 	i915_redisable_vga_power_on(dev);
-+
-+	intel_display_power_put(dev_priv, POWER_DOMAIN_VGA);
- }
- 
- static bool primary_get_hw_state(struct intel_plane *plane)
-diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
-index 1bbd67b..1d8de43 100644
---- a/drivers/gpu/drm/i915/intel_dp.c
-+++ b/drivers/gpu/drm/i915/intel_dp.c
-@@ -2362,15 +2362,18 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder,
- 	struct drm_i915_private *dev_priv = dev->dev_private;
- 	enum intel_display_power_domain power_domain;
- 	u32 tmp;
-+	bool ret;
- 
- 	power_domain = intel_display_port_power_domain(encoder);
--	if (!intel_display_power_is_enabled(dev_priv, power_domain))
-+	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
- 		return false;
- 
-+	ret = false;
-+
- 	tmp = I915_READ(intel_dp->output_reg);
- 
- 	if (!(tmp & DP_PORT_EN))
--		return false;
-+		goto out;
- 
- 	if (IS_GEN7(dev) && port == PORT_A) {
- 		*pipe = PORT_TO_PIPE_CPT(tmp);
-@@ -2381,7 +2384,9 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder,
- 			u32 trans_dp = I915_READ(TRANS_DP_CTL(p));
- 			if (TRANS_DP_PIPE_TO_PORT(trans_dp) == port) {
- 				*pipe = p;
--				return true;
-+				ret = true;
-+
-+				goto out;
- 			}
- 		}
- 
-@@ -2393,7 +2398,12 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder,
- 		*pipe = PORT_TO_PIPE(tmp);
- 	}
- 
--	return true;
-+	ret = true;
-+
-+out:
-+	intel_display_power_put(dev_priv, power_domain);
-+
-+	return ret;
- }
- 
- static void intel_dp_get_config(struct intel_encoder *encoder,
-diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
-index ea54158..df7f3cb 100644
---- a/drivers/gpu/drm/i915/intel_drv.h
-+++ b/drivers/gpu/drm/i915/intel_drv.h
-@@ -1428,6 +1428,8 @@ bool __intel_display_power_is_enabled(struct drm_i915_private *dev_priv,
- 				      enum intel_display_power_domain domain);
- void intel_display_power_get(struct drm_i915_private *dev_priv,
- 			     enum intel_display_power_domain domain);
-+bool intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
-+					enum intel_display_power_domain domain);
- void intel_display_power_put(struct drm_i915_private *dev_priv,
- 			     enum intel_display_power_domain domain);
- 
-@@ -1514,6 +1516,7 @@ enable_rpm_wakeref_asserts(struct drm_i915_private *dev_priv)
- 	enable_rpm_wakeref_asserts(dev_priv)
- 
- void intel_runtime_pm_get(struct drm_i915_private *dev_priv);
-+bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv);
- void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv);
- void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
- 
-diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
-index 44742fa..0193c62a 100644
---- a/drivers/gpu/drm/i915/intel_dsi.c
-+++ b/drivers/gpu/drm/i915/intel_dsi.c
-@@ -664,13 +664,16 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
- 	struct drm_device *dev = encoder->base.dev;
- 	enum intel_display_power_domain power_domain;
- 	enum port port;
-+	bool ret;
- 
- 	DRM_DEBUG_KMS("\n");
- 
- 	power_domain = intel_display_port_power_domain(encoder);
--	if (!intel_display_power_is_enabled(dev_priv, power_domain))
-+	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
- 		return false;
- 
-+	ret = false;
-+
- 	/* XXX: this only works for one DSI output */
- 	for_each_dsi_port(port, intel_dsi->ports) {
- 		i915_reg_t ctrl_reg = IS_BROXTON(dev) ?
-@@ -691,12 +694,16 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
- 		if (dpi_enabled || (func & CMD_MODE_DATA_WIDTH_MASK)) {
- 			if (I915_READ(MIPI_DEVICE_READY(port)) & DEVICE_READY) {
- 				*pipe = port == PORT_A ? PIPE_A : PIPE_B;
--				return true;
-+				ret = true;
-+
-+				goto out;
- 			}
- 		}
- 	}
-+out:
-+	intel_display_power_put(dev_priv, power_domain);
- 
--	return false;
-+	return ret;
- }
- 
- static void intel_dsi_get_config(struct intel_encoder *encoder,
-diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
-index 4a77639..cb5d1b1 100644
---- a/drivers/gpu/drm/i915/intel_hdmi.c
-+++ b/drivers/gpu/drm/i915/intel_hdmi.c
-@@ -880,15 +880,18 @@ static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder,
- 	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
- 	enum intel_display_power_domain power_domain;
- 	u32 tmp;
-+	bool ret;
- 
- 	power_domain = intel_display_port_power_domain(encoder);
--	if (!intel_display_power_is_enabled(dev_priv, power_domain))
-+	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
- 		return false;
- 
-+	ret = false;
-+
- 	tmp = I915_READ(intel_hdmi->hdmi_reg);
- 
- 	if (!(tmp & SDVO_ENABLE))
--		return false;
-+		goto out;
- 
- 	if (HAS_PCH_CPT(dev))
- 		*pipe = PORT_TO_PIPE_CPT(tmp);
-@@ -897,7 +900,12 @@ static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder,
- 	else
- 		*pipe = PORT_TO_PIPE(tmp);
- 
--	return true;
-+	ret = true;
-+
-+out:
-+	intel_display_power_put(dev_priv, power_domain);
-+
-+	return ret;
- }
- 
- static void intel_hdmi_get_config(struct intel_encoder *encoder,
-diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
-index 0da0240..bc04d8d 100644
---- a/drivers/gpu/drm/i915/intel_lvds.c
-+++ b/drivers/gpu/drm/i915/intel_lvds.c
-@@ -75,22 +75,30 @@ static bool intel_lvds_get_hw_state(struct intel_encoder *encoder,
- 	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
- 	enum intel_display_power_domain power_domain;
- 	u32 tmp;
-+	bool ret;
- 
- 	power_domain = intel_display_port_power_domain(encoder);
--	if (!intel_display_power_is_enabled(dev_priv, power_domain))
-+	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
- 		return false;
- 
-+	ret = false;
-+
- 	tmp = I915_READ(lvds_encoder->reg);
- 
- 	if (!(tmp & LVDS_PORT_EN))
--		return false;
-+		goto out;
- 
- 	if (HAS_PCH_CPT(dev))
- 		*pipe = PORT_TO_PIPE_CPT(tmp);
- 	else
- 		*pipe = PORT_TO_PIPE(tmp);
- 
--	return true;
-+	ret = true;
-+
-+out:
-+	intel_display_power_put(dev_priv, power_domain);
-+
-+	return ret;
- }
- 
- static void intel_lvds_get_config(struct intel_encoder *encoder,
-diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
-index a234687..b28c29f 100644
---- a/drivers/gpu/drm/i915/intel_pm.c
-+++ b/drivers/gpu/drm/i915/intel_pm.c
-@@ -2829,7 +2829,10 @@ void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
- 	memset(ddb, 0, sizeof(*ddb));
- 
- 	for_each_pipe(dev_priv, pipe) {
--		if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PIPE(pipe)))
-+		enum intel_display_power_domain power_domain;
-+
-+		power_domain = POWER_DOMAIN_PIPE(pipe);
-+		if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
- 			continue;
- 
- 		for_each_plane(dev_priv, pipe, plane) {
-@@ -2841,6 +2844,8 @@ void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
- 		val = I915_READ(CUR_BUF_CFG(pipe));
- 		skl_ddb_entry_init_from_hw(&ddb->plane[pipe][PLANE_CURSOR],
- 					   val);
-+
-+		intel_display_power_put(dev_priv, power_domain);
- 	}
- }
- 
-diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
-index ddbdbff..678ed34 100644
---- a/drivers/gpu/drm/i915/intel_runtime_pm.c
-+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
-@@ -470,6 +470,43 @@ static void gen9_set_dc_state_debugmask_memory_up(
- 	}
- }
- 
-+static void gen9_write_dc_state(struct drm_i915_private *dev_priv,
-+				u32 state)
-+{
-+	int rewrites = 0;
-+	int rereads = 0;
-+	u32 v;
-+
-+	I915_WRITE(DC_STATE_EN, state);
-+
-+	/* It has been observed that disabling the dc6 state sometimes
-+	 * doesn't stick and dmc keeps returning old value. Make sure
-+	 * the write really sticks enough times and also force rewrite until
-+	 * we are confident that state is exactly what we want.
-+	 */
-+	do  {
-+		v = I915_READ(DC_STATE_EN);
-+
-+		if (v != state) {
-+			I915_WRITE(DC_STATE_EN, state);
-+			rewrites++;
-+			rereads = 0;
-+		} else if (rereads++ > 5) {
-+			break;
-+		}
-+
-+	} while (rewrites < 100);
-+
-+	if (v != state)
-+		DRM_ERROR("Writing dc state to 0x%x failed, now 0x%x\n",
-+			  state, v);
-+
-+	/* Most of the times we need one retry, avoid spam */
-+	if (rewrites > 1)
-+		DRM_DEBUG_KMS("Rewrote dc state to 0x%x %d times\n",
-+			      state, rewrites);
-+}
-+
- static void gen9_set_dc_state(struct drm_i915_private *dev_priv, uint32_t state)
- {
- 	uint32_t val;
-@@ -494,10 +531,18 @@ static void gen9_set_dc_state(struct drm_i915_private *dev_priv, uint32_t state)
- 	val = I915_READ(DC_STATE_EN);
- 	DRM_DEBUG_KMS("Setting DC state from %02x to %02x\n",
- 		      val & mask, state);
-+
-+	/* Check if DMC is ignoring our DC state requests */
-+	if ((val & mask) != dev_priv->csr.dc_state)
-+		DRM_ERROR("DC state mismatch (0x%x -> 0x%x)\n",
-+			  dev_priv->csr.dc_state, val & mask);
-+
- 	val &= ~mask;
- 	val |= state;
--	I915_WRITE(DC_STATE_EN, val);
--	POSTING_READ(DC_STATE_EN);
-+
-+	gen9_write_dc_state(dev_priv, val);
-+
-+	dev_priv->csr.dc_state = val & mask;
- }
- 
- void bxt_enable_dc9(struct drm_i915_private *dev_priv)
-@@ -1442,6 +1487,22 @@ static void chv_pipe_power_well_disable(struct drm_i915_private *dev_priv,
- 	chv_set_pipe_power_well(dev_priv, power_well, false);
- }
- 
-+static void
-+__intel_display_power_get_domain(struct drm_i915_private *dev_priv,
-+				 enum intel_display_power_domain domain)
-+{
-+	struct i915_power_domains *power_domains = &dev_priv->power_domains;
-+	struct i915_power_well *power_well;
-+	int i;
-+
-+	for_each_power_well(i, power_well, BIT(domain), power_domains) {
-+		if (!power_well->count++)
-+			intel_power_well_enable(dev_priv, power_well);
-+	}
-+
-+	power_domains->domain_use_count[domain]++;
-+}
-+
- /**
-  * intel_display_power_get - grab a power domain reference
-  * @dev_priv: i915 device instance
-@@ -1457,24 +1518,53 @@ static void chv_pipe_power_well_disable(struct drm_i915_private *dev_priv,
- void intel_display_power_get(struct drm_i915_private *dev_priv,
- 			     enum intel_display_power_domain domain)
- {
--	struct i915_power_domains *power_domains;
--	struct i915_power_well *power_well;
--	int i;
-+	struct i915_power_domains *power_domains = &dev_priv->power_domains;
- 
- 	intel_runtime_pm_get(dev_priv);
- 
--	power_domains = &dev_priv->power_domains;
-+	mutex_lock(&power_domains->lock);
-+
-+	__intel_display_power_get_domain(dev_priv, domain);
-+
-+	mutex_unlock(&power_domains->lock);
-+}
-+
-+/**
-+ * intel_display_power_get_if_enabled - grab a reference for an enabled display power domain
-+ * @dev_priv: i915 device instance
-+ * @domain: power domain to reference
-+ *
-+ * This function grabs a power domain reference for @domain and ensures that the
-+ * power domain and all its parents are powered up. Therefore users should only
-+ * grab a reference to the innermost power domain they need.
-+ *
-+ * Any power domain reference obtained by this function must have a symmetric
-+ * call to intel_display_power_put() to release the reference again.
-+ */
-+bool intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
-+					enum intel_display_power_domain domain)
-+{
-+	struct i915_power_domains *power_domains = &dev_priv->power_domains;
-+	bool is_enabled;
-+
-+	if (!intel_runtime_pm_get_if_in_use(dev_priv))
-+		return false;
- 
- 	mutex_lock(&power_domains->lock);
- 
--	for_each_power_well(i, power_well, BIT(domain), power_domains) {
--		if (!power_well->count++)
--			intel_power_well_enable(dev_priv, power_well);
-+	if (__intel_display_power_is_enabled(dev_priv, domain)) {
-+		__intel_display_power_get_domain(dev_priv, domain);
-+		is_enabled = true;
-+	} else {
-+		is_enabled = false;
- 	}
- 
--	power_domains->domain_use_count[domain]++;
--
- 	mutex_unlock(&power_domains->lock);
-+
-+	if (!is_enabled)
-+		intel_runtime_pm_put(dev_priv);
-+
-+	return is_enabled;
- }
- 
- /**
-@@ -2246,6 +2336,43 @@ void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
- }
- 
- /**
-+ * intel_runtime_pm_get_if_in_use - grab a runtime pm reference if device in use
-+ * @dev_priv: i915 device instance
-+ *
-+ * This function grabs a device-level runtime pm reference if the device is
-+ * already in use and ensures that it is powered up.
-+ *
-+ * Any runtime pm reference obtained by this function must have a symmetric
-+ * call to intel_runtime_pm_put() to release the reference again.
-+ */
-+bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv)
-+{
-+	struct drm_device *dev = dev_priv->dev;
-+	struct device *device = &dev->pdev->dev;
-+	int ret;
-+
-+	if (!IS_ENABLED(CONFIG_PM))
-+		return true;
-+
-+	ret = pm_runtime_get_if_in_use(device);
-+
-+	/*
-+	 * In cases runtime PM is disabled by the RPM core and we get an
-+	 * -EINVAL return value we are not supposed to call this function,
-+	 * since the power state is undefined. This applies atm to the
-+	 * late/early system suspend/resume handlers.
-+	 */
-+	WARN_ON_ONCE(ret < 0);
-+	if (ret <= 0)
-+		return false;
-+
-+	atomic_inc(&dev_priv->pm.wakeref_count);
-+	assert_rpm_wakelock_held(dev_priv);
-+
-+	return true;
-+}
-+
-+/**
-  * intel_runtime_pm_get_noresume - grab a runtime pm reference
-  * @dev_priv: i915 device instance
-  *
diff --git a/modules/hardware/t100ha/meta-keys.patch b/modules/hardware/t100ha/meta-keys.patch
new file mode 100644
index 00000000..26fd4fda
--- /dev/null
+++ b/modules/hardware/t100ha/meta-keys.patch
@@ -0,0 +1,44 @@
+diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
+index bcfaf32..c54cb28 100644
+--- a/drivers/hid/hid-input.c
++++ b/drivers/hid/hid-input.c
+@@ -502,7 +502,8 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
+ 
+ 	field->hidinput = hidinput;
+ 
+-	if (field->flags & HID_MAIN_ITEM_CONSTANT)
++	if ((field->flags & HID_MAIN_ITEM_CONSTANT) &&
++		(usage->hid & HID_USAGE_PAGE) != HID_UP_ASUSVENDOR)
+ 		goto ignore;
+ 
+ 	/* Ignore if report count is out of bounds. */
+@@ -980,6 +981,17 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
+ 		}
+ 		break;
+ 
++	case HID_UP_ASUSVENDOR:
++		switch (usage->hid & HID_USAGE) {
++			case 0x06C: map_key_clear(KEY_SLEEP);           break; /* Fn+F1: Sleep */
++			case 0x088: map_key_clear(KEY_WLAN);            break; /* Fn+F2: Wifi & BT */
++			case 0x010: map_key_clear(KEY_BRIGHTNESSDOWN);  break; /* Fn+F5: Brightness down */
++			case 0x020: map_key_clear(KEY_BRIGHTNESSUP);    break; /* Fn+F6: Brightness up */
++			case 0x06B: map_key_clear(KEY_F24);             break; /* Fn+F9: Touchpad */
++			default: goto ignore;
++		}
++		break;
++
+ 	default:
+ 	unknown:
+ 		if (field->report_size == 1) {
+diff --git a/include/linux/hid.h b/include/linux/hid.h
+index 75b66ec..16a64fd 100644
+--- a/include/linux/hid.h
++++ b/include/linux/hid.h
+@@ -172,6 +172,7 @@ struct hid_item {
+ #define HID_UP_LOGIVENDOR3   0xff430000
+ #define HID_UP_LNVENDOR		0xffa00000
+ #define HID_UP_SENSOR		0x00200000
++#define HID_UP_ASUSVENDOR	0xff310000
+ 
+ #define HID_USAGE		0x0000ffff
+