From e8861698f019eb218be451e444898a1cb5577d21 Mon Sep 17 00:00:00 2001 From: aszlig Date: Tue, 1 Mar 2016 07:14:38 +0100 Subject: 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 --- modules/hardware/t100ha/backlight.patch | 225 +++++++ modules/hardware/t100ha/default.nix | 32 +- modules/hardware/t100ha/drm-fixes.patch | 1019 ------------------------------- modules/hardware/t100ha/meta-keys.patch | 44 ++ 4 files changed, 292 insertions(+), 1028 deletions(-) create mode 100644 modules/hardware/t100ha/backlight.patch delete mode 100644 modules/hardware/t100ha/drm-fixes.patch create mode 100644 modules/hardware/t100ha/meta-keys.patch 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 + #include ++#include + #include + #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 + -- cgit 1.4.1