]> Git Repo - linux.git/commitdiff
BackMerge v5.1-rc5 into drm-next
authorDave Airlie <[email protected]>
Mon, 15 Apr 2019 05:51:49 +0000 (15:51 +1000)
committerDave Airlie <[email protected]>
Mon, 15 Apr 2019 05:51:49 +0000 (15:51 +1000)
Need rc5 for udl fix to add udl cleanups on top.

Signed-off-by: Dave Airlie <[email protected]>
29 files changed:
1  2 
MAINTAINERS
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
drivers/gpu/drm/amd/amdkfd/kfd_device.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/dc/core/dc_link.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.h
drivers/gpu/drm/drm_atomic_helper.c
drivers/gpu/drm/drm_drv.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/i915/gvt/cmd_parser.c
drivers/gpu/drm/i915/gvt/dmabuf.c
drivers/gpu/drm/i915/gvt/scheduler.c
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/icl_dsi.c
drivers/gpu/drm/i915/intel_ddi.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/vlv_dsi.c
drivers/gpu/drm/meson/meson_drv.c
drivers/gpu/drm/meson/meson_dw_hdmi.c
drivers/gpu/drm/rockchip/rockchip_drm_vop.c
drivers/gpu/drm/udl/udl_drv.c
drivers/staging/Kconfig
drivers/staging/Makefile
include/drm/drm_modeset_helper_vtables.h
sound/hda/hdac_component.c

diff --combined MAINTAINERS
index 8825dffebb4c5aef35ad8d7dc23277a324ee1caa,3671fdea5010e351ff5cedabde6dee83a8db9d7c..bbb95d66a2202eebebac18fdc699d75eb839969c
@@@ -1167,7 -1167,7 +1167,7 @@@ S:      Supporte
  T:    git git://linux-arm.org/linux-ld.git for-upstream/mali-dp
  F:    drivers/gpu/drm/arm/display/include/
  F:    drivers/gpu/drm/arm/display/komeda/
 -F:    Documentation/devicetree/bindings/display/arm/arm,komeda.txt
 +F:    Documentation/devicetree/bindings/display/arm,komeda.txt
  F:    Documentation/gpu/komeda-kms.rst
  
  ARM MALI-DP DRM DRIVER
@@@ -1893,14 -1893,15 +1893,15 @@@ T:   git git://git.kernel.org/pub/scm/lin
  ARM/NUVOTON NPCM ARCHITECTURE
  M:    Avi Fishman <[email protected]>
  M:    Tomer Maimon <[email protected]>
+ M:    Tali Perry <[email protected]>
  R:    Patrick Venture <[email protected]>
  R:    Nancy Yuen <[email protected]>
- R:    Brendan Higgins <brendanhiggins@google.com>
+ R:    Benjamin Fair <benjaminfair@google.com>
  L:    [email protected] (moderated for non-subscribers)
  S:    Supported
  F:    arch/arm/mach-npcm/
  F:    arch/arm/boot/dts/nuvoton-npcm*
- F:    include/dt-bindings/clock/nuvoton,npcm7xx-clks.h
+ F:    include/dt-bindings/clock/nuvoton,npcm7xx-clock.h
  F:    drivers/*/*npcm*
  F:    Documentation/devicetree/bindings/*/*npcm*
  F:    Documentation/devicetree/bindings/*/*/*npcm*
@@@ -2356,7 -2357,7 +2357,7 @@@ F:      arch/arm/mm/cache-uniphier.
  F:    arch/arm64/boot/dts/socionext/uniphier*
  F:    drivers/bus/uniphier-system-bus.c
  F:    drivers/clk/uniphier/
- F:    drivers/dmaengine/uniphier-mdmac.c
+ F:    drivers/dma/uniphier-mdmac.c
  F:    drivers/gpio/gpio-uniphier.c
  F:    drivers/i2c/busses/i2c-uniphier*
  F:    drivers/irqchip/irq-uniphier-aidet.c
@@@ -4129,7 -4130,7 +4130,7 @@@ F:      drivers/cpuidle/
  F:    include/linux/cpuidle.h
  
  CRAMFS FILESYSTEM
- M:    Nicolas Pitre <nico@linaro.org>
+ M:    Nicolas Pitre <nico@fluxnic.net>
  S:    Maintained
  F:    Documentation/filesystems/cramfs.txt
  F:    fs/cramfs/
@@@ -4894,14 -4895,6 +4895,14 @@@ M:    Dave Airlie <[email protected]
  S:    Odd Fixes
  F:    drivers/gpu/drm/ast/
  
 +DRM DRIVER FOR ASPEED BMC GFX
 +M:    Joel Stanley <[email protected]>
 +L:    [email protected]
 +T:    git git://anongit.freedesktop.org/drm/drm-misc
 +S:    Supported
 +F:    drivers/gpu/drm/aspeed/
 +F:    Documentation/devicetree/bindings/gpu/aspeed-gfx.txt
 +
  DRM DRIVER FOR BOCHS VIRTUAL GPU
  M:    Gerd Hoffmann <[email protected]>
  L:    [email protected]
@@@ -4915,12 -4908,6 +4916,12 @@@ T:    git git://anongit.freedesktop.org/dr
  S:    Maintained
  F:    drivers/gpu/drm/tve200/
  
 +DRM DRIVER FOR FEIYANG FY07024DI26A30-D MIPI-DSI LCD PANELS
 +M:    Jagan Teki <[email protected]>
 +S:    Maintained
 +F:    drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c
 +F:    Documentation/devicetree/bindings/display/panel/feiyang,fy07024di26a30d.txt
 +
  DRM DRIVER FOR ILITEK ILI9225 PANELS
  M:    David Lechner <[email protected]>
  S:    Maintained
@@@ -5012,12 -4999,6 +5013,12 @@@ S:    Orphan / Obsolet
  F:    drivers/gpu/drm/r128/
  F:    include/uapi/drm/r128_drm.h
  
 +DRM DRIVER FOR ROCKTECH JH057N00900 PANELS
 +M:    Guido Günther <[email protected]>
 +S:    Maintained
 +F:    drivers/gpu/drm/panel/panel-rocktech-jh057n00900.c
 +F:    Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.txt
 +
  DRM DRIVER FOR SAVAGE VIDEO CARDS
  S:    Orphan / Obsolete
  F:    drivers/gpu/drm/savage/
@@@ -5065,13 -5046,6 +5066,13 @@@ S:    Odd Fixe
  F:    drivers/gpu/drm/udl/
  T:    git git://anongit.freedesktop.org/drm/drm-misc
  
 +DRM DRIVER FOR VIRTUALBOX VIRTUAL GPU
 +M:    Hans de Goede <[email protected]>
 +L:    [email protected]
 +S:    Maintained
 +F:    drivers/gpu/drm/vboxvideo/
 +T:    git git://anongit.freedesktop.org/drm/drm-misc
 +
  DRM DRIVER FOR VIRTUAL KERNEL MODESETTING (VKMS)
  M:    Rodrigo Siqueira <[email protected]>
  R:    Haneen Mohammed <[email protected]>
@@@ -5206,15 -5180,6 +5207,15 @@@ S:    Maintaine
  F:    drivers/gpu/drm/hisilicon/
  F:    Documentation/devicetree/bindings/display/hisilicon/
  
 +DRM DRIVERS FOR LIMA
 +M:    Qiang Yu <[email protected]>
 +L:    [email protected]
 +L:    [email protected] (moderated for non-subscribers)
 +S:    Maintained
 +F:    drivers/gpu/drm/lima/
 +F:    include/uapi/drm/lima_drm.h
 +T:    git git://anongit.freedesktop.org/drm/drm-misc
 +
  DRM DRIVERS FOR MEDIATEK
  M:    CK Hu <[email protected]>
  M:    Philipp Zabel <[email protected]>
@@@ -5869,7 -5834,7 +5870,7 @@@ L:      [email protected]
  S:    Maintained
  F:    Documentation/ABI/testing/sysfs-bus-mdio
  F:    Documentation/devicetree/bindings/net/mdio*
- F:    Documentation/networking/phy.txt
+ F:    Documentation/networking/phy.rst
  F:    drivers/net/phy/
  F:    drivers/of/of_mdio.c
  F:    drivers/of/of_net.c
@@@ -6444,7 -6409,6 +6445,6 @@@ L:      [email protected]
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git locking/core
  S:    Maintained
  F:    kernel/futex.c
- F:    kernel/futex_compat.c
  F:    include/asm-generic/futex.h
  F:    include/linux/futex.h
  F:    include/uapi/linux/futex.h
@@@ -7552,7 -7516,7 +7552,7 @@@ F:      include/net/mac802154.
  F:    include/net/af_ieee802154.h
  F:    include/net/cfg802154.h
  F:    include/net/ieee802154_netdev.h
- F:    Documentation/networking/ieee802154.txt
+ F:    Documentation/networking/ieee802154.rst
  
  IFE PROTOCOL
  M:    Yotam Gigi <[email protected]>
@@@ -14018,7 -13982,7 +14018,7 @@@ F:   drivers/media/rc/serial_ir.
  SFC NETWORK DRIVER
  M:    Solarflare linux maintainers <[email protected]>
  M:    Edward Cree <[email protected]>
- M:    Bert Kenward <bkenward@solarflare.com>
+ M:    Martin Habets <mhabets@solarflare.com>
  L:    [email protected]
  S:    Supported
  F:    drivers/net/ethernet/sfc/
@@@ -16545,7 -16509,7 +16545,7 @@@ F:   drivers/char/virtio_console.
  F:    include/linux/virtio_console.h
  F:    include/uapi/linux/virtio_console.h
  
- VIRTIO CORE, NET AND BLOCK DRIVERS
+ VIRTIO CORE AND NET DRIVERS
  M:    "Michael S. Tsirkin" <[email protected]>
  M:    Jason Wang <[email protected]>
  L:    [email protected]
@@@ -16560,6 -16524,19 +16560,19 @@@ F: include/uapi/linux/virtio_*.
  F:    drivers/crypto/virtio/
  F:    mm/balloon_compaction.c
  
+ VIRTIO BLOCK AND SCSI DRIVERS
+ M:    "Michael S. Tsirkin" <[email protected]>
+ M:    Jason Wang <[email protected]>
+ R:    Paolo Bonzini <[email protected]>
+ R:    Stefan Hajnoczi <[email protected]>
+ L:    [email protected]
+ S:    Maintained
+ F:    drivers/block/virtio_blk.c
+ F:    drivers/scsi/virtio_scsi.c
+ F:    include/uapi/linux/virtio_blk.h
+ F:    include/uapi/linux/virtio_scsi.h
+ F:    drivers/vhost/scsi.c
  VIRTIO CRYPTO DRIVER
  M:    Gonglei <[email protected]>
  L:    [email protected]
index 3f08be7a913efdc97fd4f06ddf7f63f864c2bec5,5d8b30fd4534582bbf0203343df180927f5bdbc1..d47354997e3c12f4d8f841d72d6c2aa3667625e3
@@@ -60,7 -60,6 +60,7 @@@
  #include "amdgpu_pm.h"
  
  #include "amdgpu_xgmi.h"
 +#include "amdgpu_ras.h"
  
  MODULE_FIRMWARE("amdgpu/vega10_gpu_info.bin");
  MODULE_FIRMWARE("amdgpu/vega12_gpu_info.bin");
@@@ -1507,9 -1506,7 +1507,9 @@@ static int amdgpu_device_ip_early_init(
                        return -EAGAIN;
        }
  
 -      adev->powerplay.pp_feature = amdgpu_pp_feature_mask;
 +      adev->pm.pp_feature = amdgpu_pp_feature_mask;
 +      if (amdgpu_sriov_vf(adev))
 +              adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
  
        for (i = 0; i < adev->num_ip_blocks; i++) {
                if ((amdgpu_ip_block_mask & (1 << i)) == 0) {
@@@ -1641,10 -1638,6 +1641,10 @@@ static int amdgpu_device_ip_init(struc
  {
        int i, r;
  
 +      r = amdgpu_ras_init(adev);
 +      if (r)
 +              return r;
 +
        for (i = 0; i < adev->num_ip_blocks; i++) {
                if (!adev->ip_blocks[i].status.valid)
                        continue;
                }
        }
  
 +      r = amdgpu_ib_pool_init(adev);
 +      if (r) {
 +              dev_err(adev->dev, "IB initialization failed (%d).\n", r);
 +              amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_IB_INIT_FAIL, 0, r);
 +              goto init_failed;
 +      }
 +
        r = amdgpu_ucode_create_bo(adev); /* create ucode bo when sw_init complete*/
        if (r)
                goto init_failed;
@@@ -1883,8 -1869,6 +1883,8 @@@ static int amdgpu_device_ip_fini(struc
  {
        int i, r;
  
 +      amdgpu_ras_pre_fini(adev);
 +
        if (adev->gmc.xgmi.num_physical_nodes > 1)
                amdgpu_xgmi_remove_device(adev);
  
                        amdgpu_free_static_csa(&adev->virt.csa_obj);
                        amdgpu_device_wb_fini(adev);
                        amdgpu_device_vram_scratch_fini(adev);
 +                      amdgpu_ib_pool_fini(adev);
                }
  
                r = adev->ip_blocks[i].version->funcs->sw_fini((void *)adev);
                adev->ip_blocks[i].status.late_initialized = false;
        }
  
 +      amdgpu_ras_fini(adev);
 +
        if (amdgpu_sriov_vf(adev))
                if (amdgpu_virt_release_full_gpu(adev, false))
                        DRM_ERROR("failed to release exclusive mode on fini\n");
@@@ -2018,10 -1999,6 +2018,10 @@@ static void amdgpu_device_ip_late_init_
        r = amdgpu_device_enable_mgpu_fan_boost();
        if (r)
                DRM_ERROR("enable mgpu fan boost failed (%d).\n", r);
 +
 +      /*set to low pstate by default */
 +      amdgpu_xgmi_set_pstate(adev, 0);
 +
  }
  
  static void amdgpu_device_delay_enable_gfx_off(struct work_struct *work)
@@@ -2392,7 -2369,7 +2392,7 @@@ static void amdgpu_device_xgmi_reset_fu
  
        adev->asic_reset_res =  amdgpu_asic_reset(adev);
        if (adev->asic_reset_res)
 -              DRM_WARN("ASIC reset failed with err r, %d for drm dev, %s",
 +              DRM_WARN("ASIC reset failed with error, %d for drm dev, %s",
                         adev->asic_reset_res, adev->ddev->unique);
  }
  
@@@ -2471,7 -2448,6 +2471,7 @@@ int amdgpu_device_init(struct amdgpu_de
        mutex_init(&adev->virt.vf_errors.lock);
        hash_init(adev->mn_hash);
        mutex_init(&adev->lock_reset);
 +      mutex_init(&adev->virt.dpm_mutex);
  
        amdgpu_device_check_arguments(adev);
  
@@@ -2666,6 -2642,13 +2666,6 @@@ fence_driver_init
        /* Get a log2 for easy divisions. */
        adev->mm_stats.log2_max_MBps = ilog2(max(1u, max_MBps));
  
 -      r = amdgpu_ib_pool_init(adev);
 -      if (r) {
 -              dev_err(adev->dev, "IB initialization failed (%d).\n", r);
 -              amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_IB_INIT_FAIL, 0, r);
 -              goto failed;
 -      }
 -
        amdgpu_fbdev_init(adev);
  
        r = amdgpu_pm_sysfs_init(adev);
                goto failed;
        }
  
 +      /* must succeed. */
 +      amdgpu_ras_post_init(adev);
 +
        return 0;
  
  failed:
@@@ -2746,6 -2726,7 +2746,6 @@@ void amdgpu_device_fini(struct amdgpu_d
                else
                        drm_atomic_helper_shutdown(adev->ddev);
        }
 -      amdgpu_ib_pool_fini(adev);
        amdgpu_fence_driver_fini(adev);
        amdgpu_pm_sysfs_fini(adev);
        amdgpu_fbdev_fini(adev);
@@@ -3192,11 -3173,16 +3192,16 @@@ static int amdgpu_device_recover_vram(s
                        break;
  
                if (fence) {
-                       r = dma_fence_wait_timeout(fence, false, tmo);
+                       tmo = dma_fence_wait_timeout(fence, false, tmo);
                        dma_fence_put(fence);
                        fence = next;
-                       if (r <= 0)
+                       if (tmo == 0) {
+                               r = -ETIMEDOUT;
                                break;
+                       } else if (tmo < 0) {
+                               r = tmo;
+                               break;
+                       }
                } else {
                        fence = next;
                }
                tmo = dma_fence_wait_timeout(fence, false, tmo);
        dma_fence_put(fence);
  
-       if (r <= 0 || tmo <= 0) {
-               DRM_ERROR("recover vram bo from shadow failed\n");
+       if (r < 0 || tmo <= 0) {
+               DRM_ERROR("recover vram bo from shadow failed, r is %ld, tmo is %ld\n", r, tmo);
                return -EIO;
        }
  
@@@ -3238,8 -3224,6 +3243,8 @@@ static int amdgpu_device_reset_sriov(st
        if (r)
                return r;
  
 +      amdgpu_amdkfd_pre_reset(adev);
 +
        /* Resume IP prior to SMC */
        r = amdgpu_device_ip_reinit_early_sriov(adev);
        if (r)
  
        amdgpu_irq_gpu_reset_resume_helper(adev);
        r = amdgpu_ib_ring_tests(adev);
 +      amdgpu_amdkfd_post_reset(adev);
  
  error:
        amdgpu_virt_init_data_exchange(adev);
@@@ -3392,7 -3375,7 +3397,7 @@@ static int amdgpu_do_asic_reset(struct 
                                r = amdgpu_asic_reset(tmp_adev);
  
                        if (r) {
 -                              DRM_ERROR("ASIC reset failed with err r, %d for drm dev, %s",
 +                              DRM_ERROR("ASIC reset failed with error, %d for drm dev, %s",
                                         r, tmp_adev->ddev->unique);
                                break;
                        }
                                                break;
                                }
                        }
 +
 +                      list_for_each_entry(tmp_adev, device_list_handle,
 +                                      gmc.xgmi.head) {
 +                              amdgpu_ras_reserve_bad_pages(tmp_adev);
 +                      }
                }
        }
  
@@@ -3652,6 -3630,7 +3657,7 @@@ static void amdgpu_device_get_min_pci_s
        struct pci_dev *pdev = adev->pdev;
        enum pci_bus_speed cur_speed;
        enum pcie_link_width cur_width;
+       u32 ret = 1;
  
        *speed = PCI_SPEED_UNKNOWN;
        *width = PCIE_LNK_WIDTH_UNKNOWN;
        while (pdev) {
                cur_speed = pcie_get_speed_cap(pdev);
                cur_width = pcie_get_width_cap(pdev);
+               ret = pcie_bandwidth_available(adev->pdev, NULL,
+                                                      NULL, &cur_width);
+               if (!ret)
+                       cur_width = PCIE_LNK_WIDTH_RESRV;
  
                if (cur_speed != PCI_SPEED_UNKNOWN) {
                        if (*speed == PCI_SPEED_UNKNOWN)
index 107756dd1b256a34ed4266c1847638fb879adbc8,a11db2b1a63f41e16acd4df34a24b2f3e6db9140..ba67d10232643cb9963c2b58954fd00cbaaa67ae
@@@ -40,8 -40,6 +40,8 @@@
  
  #include "ivsrcid/gfx/irqsrcs_gfx_9_0.h"
  
 +#include "amdgpu_ras.h"
 +
  #define GFX9_NUM_GFX_RINGS     1
  #define GFX9_MEC_HPD_SIZE 4096
  #define RLCG_UCODE_LOADING_START_ADDRESS 0x00002000L
@@@ -578,27 -576,6 +578,27 @@@ static void gfx_v9_0_check_fw_write_wai
        }
  }
  
 +static void gfx_v9_0_check_if_need_gfxoff(struct amdgpu_device *adev)
 +{
 +      switch (adev->asic_type) {
 +      case CHIP_VEGA10:
 +      case CHIP_VEGA12:
 +      case CHIP_VEGA20:
 +              break;
 +      case CHIP_RAVEN:
 +              if (adev->rev_id >= 0x8 || adev->pdev->device == 0x15d8)
 +                      break;
 +              if ((adev->gfx.rlc_fw_version < 531) ||
 +                  (adev->gfx.rlc_fw_version == 53815) ||
 +                  (adev->gfx.rlc_feature_version < 1) ||
 +                  !adev->gfx.rlc.is_rlc_v2_1)
 +                      adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
 +              break;
 +      default:
 +              break;
 +      }
 +}
 +
  static int gfx_v9_0_init_microcode(struct amdgpu_device *adev)
  {
        const char *chip_name;
        }
  
  out:
 +      gfx_v9_0_check_if_need_gfxoff(adev);
        gfx_v9_0_check_fw_write_wait(adev);
        if (err) {
                dev_err(adev->dev,
@@@ -1663,18 -1639,6 +1663,18 @@@ static int gfx_v9_0_sw_init(void *handl
        if (r)
                return r;
  
 +      /* ECC error */
 +      r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_GRBM_CP, GFX_9_0__SRCID__CP_ECC_ERROR,
 +                            &adev->gfx.cp_ecc_error_irq);
 +      if (r)
 +              return r;
 +
 +      /* FUE error */
 +      r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_GRBM_CP, GFX_9_0__SRCID__CP_FUE_ERROR,
 +                            &adev->gfx.cp_ecc_error_irq);
 +      if (r)
 +              return r;
 +
        adev->gfx.gfx_current_status = AMDGPU_GFX_NORMAL_MODE;
  
        gfx_v9_0_scratch_init(adev);
@@@ -1767,20 -1731,6 +1767,20 @@@ static int gfx_v9_0_sw_fini(void *handl
        int i;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
  
 +      if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__GFX) &&
 +                      adev->gfx.ras_if) {
 +              struct ras_common_if *ras_if = adev->gfx.ras_if;
 +              struct ras_ih_if ih_info = {
 +                      .head = *ras_if,
 +              };
 +
 +              amdgpu_ras_debugfs_remove(adev, ras_if);
 +              amdgpu_ras_sysfs_remove(adev, ras_if);
 +              amdgpu_ras_interrupt_remove_handler(adev,  &ih_info);
 +              amdgpu_ras_feature_enable(adev, ras_if, 0);
 +              kfree(ras_if);
 +      }
 +
        amdgpu_bo_free_kernel(&adev->gds.oa_gfx_bo, NULL, NULL);
        amdgpu_bo_free_kernel(&adev->gds.gws_gfx_bo, NULL, NULL);
        amdgpu_bo_free_kernel(&adev->gds.gds_gfx_bo, NULL, NULL);
@@@ -2455,8 -2405,6 +2455,6 @@@ static int gfx_v9_0_rlc_resume(struct a
        /* disable CG */
        WREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL, 0);
  
-       adev->gfx.rlc.funcs->reset(adev);
        gfx_v9_0_init_pg(adev);
  
        if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
@@@ -3355,7 -3303,6 +3353,7 @@@ static int gfx_v9_0_hw_fini(void *handl
  {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
  
 +      amdgpu_irq_put(adev, &adev->gfx.cp_ecc_error_irq, 0);
        amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0);
        amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0);
  
@@@ -3545,80 -3492,6 +3543,80 @@@ static int gfx_v9_0_early_init(void *ha
        return 0;
  }
  
 +static int gfx_v9_0_process_ras_data_cb(struct amdgpu_device *adev,
 +              struct amdgpu_iv_entry *entry);
 +
 +static int gfx_v9_0_ecc_late_init(void *handle)
 +{
 +      struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 +      struct ras_common_if **ras_if = &adev->gfx.ras_if;
 +      struct ras_ih_if ih_info = {
 +              .cb = gfx_v9_0_process_ras_data_cb,
 +      };
 +      struct ras_fs_if fs_info = {
 +              .sysfs_name = "gfx_err_count",
 +              .debugfs_name = "gfx_err_inject",
 +      };
 +      struct ras_common_if ras_block = {
 +              .block = AMDGPU_RAS_BLOCK__GFX,
 +              .type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE,
 +              .sub_block_index = 0,
 +              .name = "gfx",
 +      };
 +      int r;
 +
 +      if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__GFX)) {
 +              amdgpu_ras_feature_enable_on_boot(adev, &ras_block, 0);
 +              return 0;
 +      }
 +
 +      if (*ras_if)
 +              goto resume;
 +
 +      *ras_if = kmalloc(sizeof(**ras_if), GFP_KERNEL);
 +      if (!*ras_if)
 +              return -ENOMEM;
 +
 +      **ras_if = ras_block;
 +
 +      r = amdgpu_ras_feature_enable_on_boot(adev, *ras_if, 1);
 +      if (r)
 +              goto feature;
 +
 +      ih_info.head = **ras_if;
 +      fs_info.head = **ras_if;
 +
 +      r = amdgpu_ras_interrupt_add_handler(adev, &ih_info);
 +      if (r)
 +              goto interrupt;
 +
 +      r = amdgpu_ras_debugfs_create(adev, &fs_info);
 +      if (r)
 +              goto debugfs;
 +
 +      r = amdgpu_ras_sysfs_create(adev, &fs_info);
 +      if (r)
 +              goto sysfs;
 +resume:
 +      r = amdgpu_irq_get(adev, &adev->gfx.cp_ecc_error_irq, 0);
 +      if (r)
 +              goto irq;
 +
 +      return 0;
 +irq:
 +      amdgpu_ras_sysfs_remove(adev, *ras_if);
 +sysfs:
 +      amdgpu_ras_debugfs_remove(adev, *ras_if);
 +debugfs:
 +      amdgpu_ras_interrupt_remove_handler(adev, &ih_info);
 +interrupt:
 +      amdgpu_ras_feature_enable(adev, *ras_if, 0);
 +feature:
 +      kfree(*ras_if);
 +      *ras_if = NULL;
 +      return -EINVAL;
 +}
 +
  static int gfx_v9_0_late_init(void *handle)
  {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        if (r)
                return r;
  
 +      r = gfx_v9_0_ecc_late_init(handle);
 +      if (r)
 +              return r;
 +
        return 0;
  }
  
@@@ -4672,45 -4541,6 +4670,45 @@@ static int gfx_v9_0_set_priv_inst_fault
        return 0;
  }
  
 +#define ENABLE_ECC_ON_ME_PIPE(me, pipe)                               \
 +      WREG32_FIELD15(GC, 0, CP_ME##me##_PIPE##pipe##_INT_CNTL,\
 +                      CP_ECC_ERROR_INT_ENABLE, 1)
 +
 +#define DISABLE_ECC_ON_ME_PIPE(me, pipe)                      \
 +      WREG32_FIELD15(GC, 0, CP_ME##me##_PIPE##pipe##_INT_CNTL,\
 +                      CP_ECC_ERROR_INT_ENABLE, 0)
 +
 +static int gfx_v9_0_set_cp_ecc_error_state(struct amdgpu_device *adev,
 +                                            struct amdgpu_irq_src *source,
 +                                            unsigned type,
 +                                            enum amdgpu_interrupt_state state)
 +{
 +      switch (state) {
 +      case AMDGPU_IRQ_STATE_DISABLE:
 +              WREG32_FIELD15(GC, 0, CP_INT_CNTL_RING0,
 +                              CP_ECC_ERROR_INT_ENABLE, 0);
 +              DISABLE_ECC_ON_ME_PIPE(1, 0);
 +              DISABLE_ECC_ON_ME_PIPE(1, 1);
 +              DISABLE_ECC_ON_ME_PIPE(1, 2);
 +              DISABLE_ECC_ON_ME_PIPE(1, 3);
 +              break;
 +
 +      case AMDGPU_IRQ_STATE_ENABLE:
 +              WREG32_FIELD15(GC, 0, CP_INT_CNTL_RING0,
 +                              CP_ECC_ERROR_INT_ENABLE, 1);
 +              ENABLE_ECC_ON_ME_PIPE(1, 0);
 +              ENABLE_ECC_ON_ME_PIPE(1, 1);
 +              ENABLE_ECC_ON_ME_PIPE(1, 2);
 +              ENABLE_ECC_ON_ME_PIPE(1, 3);
 +              break;
 +      default:
 +              break;
 +      }
 +
 +      return 0;
 +}
 +
 +
  static int gfx_v9_0_set_eop_interrupt_state(struct amdgpu_device *adev,
                                            struct amdgpu_irq_src *src,
                                            unsigned type,
@@@ -4827,34 -4657,6 +4825,34 @@@ static int gfx_v9_0_priv_inst_irq(struc
        return 0;
  }
  
 +static int gfx_v9_0_process_ras_data_cb(struct amdgpu_device *adev,
 +              struct amdgpu_iv_entry *entry)
 +{
 +      /* TODO ue will trigger an interrupt. */
 +      kgd2kfd_set_sram_ecc_flag(adev->kfd.dev);
 +      amdgpu_ras_reset_gpu(adev, 0);
 +      return AMDGPU_RAS_UE;
 +}
 +
 +static int gfx_v9_0_cp_ecc_error_irq(struct amdgpu_device *adev,
 +                                struct amdgpu_irq_src *source,
 +                                struct amdgpu_iv_entry *entry)
 +{
 +      struct ras_common_if *ras_if = adev->gfx.ras_if;
 +      struct ras_dispatch_if ih_data = {
 +              .entry = entry,
 +      };
 +
 +      if (!ras_if)
 +              return 0;
 +
 +      ih_data.head = *ras_if;
 +
 +      DRM_ERROR("CP ECC ERROR IRQ\n");
 +      amdgpu_ras_interrupt_dispatch(adev, &ih_data);
 +      return 0;
 +}
 +
  static const struct amd_ip_funcs gfx_v9_0_ip_funcs = {
        .name = "gfx_v9_0",
        .early_init = gfx_v9_0_early_init,
@@@ -5016,12 -4818,6 +5014,12 @@@ static const struct amdgpu_irq_src_func
        .process = gfx_v9_0_priv_inst_irq,
  };
  
 +static const struct amdgpu_irq_src_funcs gfx_v9_0_cp_ecc_error_irq_funcs = {
 +      .set = gfx_v9_0_set_cp_ecc_error_state,
 +      .process = gfx_v9_0_cp_ecc_error_irq,
 +};
 +
 +
  static void gfx_v9_0_set_irq_funcs(struct amdgpu_device *adev)
  {
        adev->gfx.eop_irq.num_types = AMDGPU_CP_IRQ_LAST;
  
        adev->gfx.priv_inst_irq.num_types = 1;
        adev->gfx.priv_inst_irq.funcs = &gfx_v9_0_priv_inst_irq_funcs;
 +
 +      adev->gfx.cp_ecc_error_irq.num_types = 2; /*C5 ECC error and C9 FUE error*/
 +      adev->gfx.cp_ecc_error_irq.funcs = &gfx_v9_0_cp_ecc_error_irq_funcs;
  }
  
  static void gfx_v9_0_set_rlc_funcs(struct amdgpu_device *adev)
index b3cdbf79f47b3d7ea3ebfa66a14aa0ee252210d4,cf9a49f49d3a41a99bb96dc75c38f24e72579367..2fee3063a0d6ba6cb6140c5679fca896923d13fd
@@@ -320,6 -320,7 +320,7 @@@ static const struct kfd_deviceid suppor
        { 0x9876, &carrizo_device_info },       /* Carrizo */
        { 0x9877, &carrizo_device_info },       /* Carrizo */
        { 0x15DD, &raven_device_info },         /* Raven */
+       { 0x15D8, &raven_device_info },         /* Raven */
  #endif
        { 0x67A0, &hawaii_device_info },        /* Hawaii */
        { 0x67A1, &hawaii_device_info },        /* Hawaii */
@@@ -466,8 -467,6 +467,8 @@@ struct kfd_dev *kgd2kfd_probe(struct kg
        memset(&kfd->doorbell_available_index, 0,
                sizeof(kfd->doorbell_available_index));
  
 +      atomic_set(&kfd->sram_ecc_flag, 0);
 +
        return kfd;
  }
  
@@@ -663,9 -662,6 +664,9 @@@ int kgd2kfd_post_reset(struct kfd_dev *
                return ret;
        count = atomic_dec_return(&kfd_locked);
        WARN_ONCE(count != 0, "KFD reset ref. error");
 +
 +      atomic_set(&kfd->sram_ecc_flag, 0);
 +
        return 0;
  }
  
@@@ -1029,12 -1025,6 +1030,12 @@@ int kfd_gtt_sa_free(struct kfd_dev *kfd
        return 0;
  }
  
 +void kgd2kfd_set_sram_ecc_flag(struct kfd_dev *kfd)
 +{
 +      if (kfd)
 +              atomic_inc(&kfd->sram_ecc_flag);
 +}
 +
  #if defined(CONFIG_DEBUG_FS)
  
  /* This function will send a package to HIQ to hang the HWS
index fd5646c11bb25991fda8ea2b7c49f78ef05cc692,3082b55b1e774fd31b4293c402c41174df28e9a9..9f7d399b73d4f281027598de3744e4c6e50dff54
@@@ -111,8 -111,7 +111,8 @@@ amdgpu_dm_update_connector_after_detect
  
  static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
                                struct drm_plane *plane,
 -                              unsigned long possible_crtcs);
 +                              unsigned long possible_crtcs,
 +                              const struct dc_plane_cap *plane_cap);
  static int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
                               struct drm_plane *plane,
                               uint32_t link_index);
@@@ -138,6 -137,30 +138,6 @@@ static int amdgpu_dm_atomic_check(struc
  static void handle_cursor_update(struct drm_plane *plane,
                                 struct drm_plane_state *old_plane_state);
  
 -
 -
 -static const enum drm_plane_type dm_plane_type_default[AMDGPU_MAX_PLANES] = {
 -      DRM_PLANE_TYPE_PRIMARY,
 -      DRM_PLANE_TYPE_PRIMARY,
 -      DRM_PLANE_TYPE_PRIMARY,
 -      DRM_PLANE_TYPE_PRIMARY,
 -      DRM_PLANE_TYPE_PRIMARY,
 -      DRM_PLANE_TYPE_PRIMARY,
 -};
 -
 -static const enum drm_plane_type dm_plane_type_carizzo[AMDGPU_MAX_PLANES] = {
 -      DRM_PLANE_TYPE_PRIMARY,
 -      DRM_PLANE_TYPE_PRIMARY,
 -      DRM_PLANE_TYPE_PRIMARY,
 -      DRM_PLANE_TYPE_OVERLAY,/* YUV Capable Underlay */
 -};
 -
 -static const enum drm_plane_type dm_plane_type_stoney[AMDGPU_MAX_PLANES] = {
 -      DRM_PLANE_TYPE_PRIMARY,
 -      DRM_PLANE_TYPE_PRIMARY,
 -      DRM_PLANE_TYPE_OVERLAY, /* YUV Capable Underlay */
 -};
 -
  /*
   * dm_vblank_get_counter
   *
@@@ -252,22 -275,12 +252,22 @@@ get_crtc_by_otg_inst(struct amdgpu_devi
        return NULL;
  }
  
 +static inline bool amdgpu_dm_vrr_active(struct dm_crtc_state *dm_state)
 +{
 +      return dm_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE ||
 +             dm_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED;
 +}
 +
  static void dm_pflip_high_irq(void *interrupt_params)
  {
        struct amdgpu_crtc *amdgpu_crtc;
        struct common_irq_params *irq_params = interrupt_params;
        struct amdgpu_device *adev = irq_params->adev;
        unsigned long flags;
 +      struct drm_pending_vblank_event *e;
 +      struct dm_crtc_state *acrtc_state;
 +      uint32_t vpos, hpos, v_blank_start, v_blank_end;
 +      bool vrr_active;
  
        amdgpu_crtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_PFLIP);
  
                return;
        }
  
 -      /* Update to correct count(s) if racing with vblank irq */
 -      amdgpu_crtc->last_flip_vblank = drm_crtc_accurate_vblank_count(&amdgpu_crtc->base);
 +      /* page flip completed. */
 +      e = amdgpu_crtc->event;
 +      amdgpu_crtc->event = NULL;
  
 -      /* wake up userspace */
 -      if (amdgpu_crtc->event) {
 -              drm_crtc_send_vblank_event(&amdgpu_crtc->base, amdgpu_crtc->event);
 +      if (!e)
 +              WARN_ON(1);
  
 -              /* page flip completed. clean up */
 -              amdgpu_crtc->event = NULL;
 +      acrtc_state = to_dm_crtc_state(amdgpu_crtc->base.state);
 +      vrr_active = amdgpu_dm_vrr_active(acrtc_state);
 +
 +      /* Fixed refresh rate, or VRR scanout position outside front-porch? */
 +      if (!vrr_active ||
 +          !dc_stream_get_scanoutpos(acrtc_state->stream, &v_blank_start,
 +                                    &v_blank_end, &hpos, &vpos) ||
 +          (vpos < v_blank_start)) {
 +              /* Update to correct count and vblank timestamp if racing with
 +               * vblank irq. This also updates to the correct vblank timestamp
 +               * even in VRR mode, as scanout is past the front-porch atm.
 +               */
 +              drm_crtc_accurate_vblank_count(&amdgpu_crtc->base);
  
 -      } else
 -              WARN_ON(1);
 +              /* Wake up userspace by sending the pageflip event with proper
 +               * count and timestamp of vblank of flip completion.
 +               */
 +              if (e) {
 +                      drm_crtc_send_vblank_event(&amdgpu_crtc->base, e);
 +
 +                      /* Event sent, so done with vblank for this flip */
 +                      drm_crtc_vblank_put(&amdgpu_crtc->base);
 +              }
 +      } else if (e) {
 +              /* VRR active and inside front-porch: vblank count and
 +               * timestamp for pageflip event will only be up to date after
 +               * drm_crtc_handle_vblank() has been executed from late vblank
 +               * irq handler after start of back-porch (vline 0). We queue the
 +               * pageflip event for send-out by drm_crtc_handle_vblank() with
 +               * updated timestamp and count, once it runs after us.
 +               *
 +               * We need to open-code this instead of using the helper
 +               * drm_crtc_arm_vblank_event(), as that helper would
 +               * call drm_crtc_accurate_vblank_count(), which we must
 +               * not call in VRR mode while we are in front-porch!
 +               */
 +
 +              /* sequence will be replaced by real count during send-out. */
 +              e->sequence = drm_crtc_vblank_count(&amdgpu_crtc->base);
 +              e->pipe = amdgpu_crtc->crtc_id;
 +
 +              list_add_tail(&e->base.link, &adev->ddev->vblank_event_list);
 +              e = NULL;
 +      }
 +
 +      /* Keep track of vblank of this flip for flip throttling. We use the
 +       * cooked hw counter, as that one incremented at start of this vblank
 +       * of pageflip completion, so last_flip_vblank is the forbidden count
 +       * for queueing new pageflips if vsync + VRR is enabled.
 +       */
 +      amdgpu_crtc->last_flip_vblank = amdgpu_get_vblank_counter_kms(adev->ddev,
 +                                                      amdgpu_crtc->crtc_id);
  
        amdgpu_crtc->pflip_status = AMDGPU_FLIP_NONE;
        spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
  
 -      DRM_DEBUG_DRIVER("%s - crtc :%d[%p], pflip_stat:AMDGPU_FLIP_NONE\n",
 -                                      __func__, amdgpu_crtc->crtc_id, amdgpu_crtc);
 +      DRM_DEBUG_DRIVER("crtc:%d[%p], pflip_stat:AMDGPU_FLIP_NONE, vrr[%d]-fp %d\n",
 +                       amdgpu_crtc->crtc_id, amdgpu_crtc,
 +                       vrr_active, (int) !e);
 +}
 +
 +static void dm_vupdate_high_irq(void *interrupt_params)
 +{
 +      struct common_irq_params *irq_params = interrupt_params;
 +      struct amdgpu_device *adev = irq_params->adev;
 +      struct amdgpu_crtc *acrtc;
 +      struct dm_crtc_state *acrtc_state;
 +
 +      acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VUPDATE);
 +
 +      if (acrtc) {
 +              acrtc_state = to_dm_crtc_state(acrtc->base.state);
 +
 +              DRM_DEBUG_DRIVER("crtc:%d, vupdate-vrr:%d\n", acrtc->crtc_id,
 +                               amdgpu_dm_vrr_active(acrtc_state));
  
 -      drm_crtc_vblank_put(&amdgpu_crtc->base);
 +              /* Core vblank handling is done here after end of front-porch in
 +               * vrr mode, as vblank timestamping will give valid results
 +               * while now done after front-porch. This will also deliver
 +               * page-flip completion events that have been queued to us
 +               * if a pageflip happened inside front-porch.
 +               */
 +              if (amdgpu_dm_vrr_active(acrtc_state))
 +                      drm_crtc_handle_vblank(&acrtc->base);
 +      }
  }
  
  static void dm_crtc_high_irq(void *interrupt_params)
        acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VBLANK);
  
        if (acrtc) {
 -              drm_crtc_handle_vblank(&acrtc->base);
 -              amdgpu_dm_crtc_handle_crc_irq(&acrtc->base);
 -
                acrtc_state = to_dm_crtc_state(acrtc->base.state);
  
 +              DRM_DEBUG_DRIVER("crtc:%d, vupdate-vrr:%d\n", acrtc->crtc_id,
 +                               amdgpu_dm_vrr_active(acrtc_state));
 +
 +              /* Core vblank handling at start of front-porch is only possible
 +               * in non-vrr mode, as only there vblank timestamping will give
 +               * valid results while done in front-porch. Otherwise defer it
 +               * to dm_vupdate_high_irq after end of front-porch.
 +               */
 +              if (!amdgpu_dm_vrr_active(acrtc_state))
 +                      drm_crtc_handle_vblank(&acrtc->base);
 +
 +              /* Following stuff must happen at start of vblank, for crc
 +               * computation and below-the-range btr support in vrr mode.
 +               */
 +              amdgpu_dm_crtc_handle_crc_irq(&acrtc->base);
 +
                if (acrtc_state->stream &&
                    acrtc_state->vrr_params.supported &&
                    acrtc_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE) {
@@@ -984,16 -912,9 +984,16 @@@ static int dm_resume(void *handle
        struct drm_plane *plane;
        struct drm_plane_state *new_plane_state;
        struct dm_plane_state *dm_new_plane_state;
 +      struct dm_atomic_state *dm_state = to_dm_atomic_state(dm->atomic_obj.state);
        enum dc_connection_type new_connection_type = dc_connection_none;
        int i;
  
 +      /* Recreate dc_state - DC invalidates it when setting power state to S3. */
 +      dc_release_state(dm_state->context);
 +      dm_state->context = dc_create_state(dm->dc);
 +      /* TODO: Remove dc_state->dccg, use dc->dccg directly. */
 +      dc_resource_state_construct(dm->dc, dm_state->context);
 +
        /* power on hardware */
        dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D0);
  
@@@ -1536,27 -1457,6 +1536,27 @@@ static int dce110_register_irq_handlers
                                dm_crtc_high_irq, c_irq_params);
        }
  
 +      /* Use VUPDATE interrupt */
 +      for (i = VISLANDS30_IV_SRCID_D1_V_UPDATE_INT; i <= VISLANDS30_IV_SRCID_D6_V_UPDATE_INT; i += 2) {
 +              r = amdgpu_irq_add_id(adev, client_id, i, &adev->vupdate_irq);
 +              if (r) {
 +                      DRM_ERROR("Failed to add vupdate irq id!\n");
 +                      return r;
 +              }
 +
 +              int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
 +              int_params.irq_source =
 +                      dc_interrupt_to_irq_source(dc, i, 0);
 +
 +              c_irq_params = &adev->dm.vupdate_params[int_params.irq_source - DC_IRQ_SOURCE_VUPDATE1];
 +
 +              c_irq_params->adev = adev;
 +              c_irq_params->irq_src = int_params.irq_source;
 +
 +              amdgpu_dm_irq_register_interrupt(adev, &int_params,
 +                              dm_vupdate_high_irq, c_irq_params);
 +      }
 +
        /* Use GRPH_PFLIP interrupt */
        for (i = VISLANDS30_IV_SRCID_D1_GRPH_PFLIP;
                        i <= VISLANDS30_IV_SRCID_D6_GRPH_PFLIP; i += 2) {
@@@ -1642,34 -1542,6 +1642,34 @@@ static int dcn10_register_irq_handlers(
                                dm_crtc_high_irq, c_irq_params);
        }
  
 +      /* Use VUPDATE_NO_LOCK interrupt on DCN, which seems to correspond to
 +       * the regular VUPDATE interrupt on DCE. We want DC_IRQ_SOURCE_VUPDATEx
 +       * to trigger at end of each vblank, regardless of state of the lock,
 +       * matching DCE behaviour.
 +       */
 +      for (i = DCN_1_0__SRCID__OTG0_IHC_V_UPDATE_NO_LOCK_INTERRUPT;
 +           i <= DCN_1_0__SRCID__OTG0_IHC_V_UPDATE_NO_LOCK_INTERRUPT + adev->mode_info.num_crtc - 1;
 +           i++) {
 +              r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_DCE, i, &adev->vupdate_irq);
 +
 +              if (r) {
 +                      DRM_ERROR("Failed to add vupdate irq id!\n");
 +                      return r;
 +              }
 +
 +              int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
 +              int_params.irq_source =
 +                      dc_interrupt_to_irq_source(dc, i, 0);
 +
 +              c_irq_params = &adev->dm.vupdate_params[int_params.irq_source - DC_IRQ_SOURCE_VUPDATE1];
 +
 +              c_irq_params->adev = adev;
 +              c_irq_params->irq_src = int_params.irq_source;
 +
 +              amdgpu_dm_irq_register_interrupt(adev, &int_params,
 +                              dm_vupdate_high_irq, c_irq_params);
 +      }
 +
        /* Use GRPH_PFLIP interrupt */
        for (i = DCN_1_0__SRCID__HUBP0_FLIP_INTERRUPT;
                        i <= DCN_1_0__SRCID__HUBP0_FLIP_INTERRUPT + adev->mode_info.num_crtc - 1;
@@@ -1721,10 -1593,15 +1721,10 @@@ static int dm_atomic_get_state(struct d
        struct amdgpu_device *adev = dev->dev_private;
        struct amdgpu_display_manager *dm = &adev->dm;
        struct drm_private_state *priv_state;
 -      int ret;
  
        if (*dm_state)
                return 0;
  
 -      ret = drm_modeset_lock(&dm->atomic_obj_lock, state->acquire_ctx);
 -      if (ret)
 -              return ret;
 -
        priv_state = drm_atomic_get_private_obj_state(state, &dm->atomic_obj);
        if (IS_ERR(priv_state))
                return PTR_ERR(priv_state);
@@@ -1781,16 -1658,17 +1781,16 @@@ dm_atomic_duplicate_state(struct drm_pr
  
        __drm_atomic_helper_private_obj_duplicate_state(obj, &new_state->base);
  
 -      new_state->context = dc_create_state();
 +      old_state = to_dm_atomic_state(obj->state);
 +
 +      if (old_state && old_state->context)
 +              new_state->context = dc_copy_state(old_state->context);
 +
        if (!new_state->context) {
                kfree(new_state);
                return NULL;
        }
  
 -      old_state = to_dm_atomic_state(obj->state);
 -      if (old_state && old_state->context)
 -              dc_resource_state_copy_construct(old_state->context,
 -                                               new_state->context);
 -
        return &new_state->base;
  }
  
@@@ -1830,11 -1708,13 +1830,11 @@@ static int amdgpu_dm_mode_config_init(s
  
        adev->ddev->mode_config.fb_base = adev->gmc.aper_base;
  
 -      drm_modeset_lock_init(&adev->dm.atomic_obj_lock);
 -
        state = kzalloc(sizeof(*state), GFP_KERNEL);
        if (!state)
                return -ENOMEM;
  
 -      state->context = dc_create_state();
 +      state->context = dc_create_state(adev->dm.dc);
        if (!state->context) {
                kfree(state);
                return -ENOMEM;
@@@ -1961,42 -1841,39 +1961,42 @@@ amdgpu_dm_register_backlight_device(str
  #endif
  
  static int initialize_plane(struct amdgpu_display_manager *dm,
 -                           struct amdgpu_mode_info *mode_info,
 -                           int plane_id)
 +                          struct amdgpu_mode_info *mode_info, int plane_id,
 +                          enum drm_plane_type plane_type,
 +                          const struct dc_plane_cap *plane_cap)
  {
        struct drm_plane *plane;
        unsigned long possible_crtcs;
        int ret = 0;
  
        plane = kzalloc(sizeof(struct drm_plane), GFP_KERNEL);
 -      mode_info->planes[plane_id] = plane;
 -
        if (!plane) {
                DRM_ERROR("KMS: Failed to allocate plane\n");
                return -ENOMEM;
        }
 -      plane->type = mode_info->plane_type[plane_id];
 +      plane->type = plane_type;
  
        /*
 -       * HACK: IGT tests expect that each plane can only have
 -       * one possible CRTC. For now, set one CRTC for each
 -       * plane that is not an underlay, but still allow multiple
 -       * CRTCs for underlay planes.
 +       * HACK: IGT tests expect that the primary plane for a CRTC
 +       * can only have one possible CRTC. Only expose support for
 +       * any CRTC if they're not going to be used as a primary plane
 +       * for a CRTC - like overlay or underlay planes.
         */
        possible_crtcs = 1 << plane_id;
        if (plane_id >= dm->dc->caps.max_streams)
                possible_crtcs = 0xff;
  
 -      ret = amdgpu_dm_plane_init(dm, mode_info->planes[plane_id], possible_crtcs);
 +      ret = amdgpu_dm_plane_init(dm, plane, possible_crtcs, plane_cap);
  
        if (ret) {
                DRM_ERROR("KMS: Failed to initialize plane\n");
 +              kfree(plane);
                return ret;
        }
  
 +      if (mode_info)
 +              mode_info->planes[plane_id] = plane;
 +
        return ret;
  }
  
@@@ -2039,9 -1916,8 +2039,9 @@@ static int amdgpu_dm_initialize_drm_dev
        struct amdgpu_encoder *aencoder = NULL;
        struct amdgpu_mode_info *mode_info = &adev->mode_info;
        uint32_t link_cnt;
 -      int32_t total_overlay_planes, total_primary_planes;
 +      int32_t primary_planes;
        enum dc_connection_type new_connection_type = dc_connection_none;
 +      const struct dc_plane_cap *plane;
  
        link_cnt = dm->dc->caps.max_links;
        if (amdgpu_dm_mode_config_init(dm->adev)) {
                return -EINVAL;
        }
  
 -      /* Identify the number of planes to be initialized */
 -      total_overlay_planes = dm->dc->caps.max_slave_planes;
 -      total_primary_planes = dm->dc->caps.max_planes - dm->dc->caps.max_slave_planes;
 +      /* There is one primary plane per CRTC */
 +      primary_planes = dm->dc->caps.max_streams;
 +      ASSERT(primary_planes <= AMDGPU_MAX_PLANES);
  
 -      /* First initialize overlay planes, index starting after primary planes */
 -      for (i = (total_overlay_planes - 1); i >= 0; i--) {
 -              if (initialize_plane(dm, mode_info, (total_primary_planes + i))) {
 -                      DRM_ERROR("KMS: Failed to initialize overlay plane\n");
 +      /*
 +       * Initialize primary planes, implicit planes for legacy IOCTLS.
 +       * Order is reversed to match iteration order in atomic check.
 +       */
 +      for (i = (primary_planes - 1); i >= 0; i--) {
 +              plane = &dm->dc->caps.planes[i];
 +
 +              if (initialize_plane(dm, mode_info, i,
 +                                   DRM_PLANE_TYPE_PRIMARY, plane)) {
 +                      DRM_ERROR("KMS: Failed to initialize primary plane\n");
                        goto fail;
                }
        }
  
 -      /* Initialize primary planes */
 -      for (i = (total_primary_planes - 1); i >= 0; i--) {
 -              if (initialize_plane(dm, mode_info, i)) {
 -                      DRM_ERROR("KMS: Failed to initialize primary plane\n");
 +      /*
 +       * Initialize overlay planes, index starting after primary planes.
 +       * These planes have a higher DRM index than the primary planes since
 +       * they should be considered as having a higher z-order.
 +       * Order is reversed to match iteration order in atomic check.
 +       *
 +       * Only support DCN for now, and only expose one so we don't encourage
 +       * userspace to use up all the pipes.
 +       */
 +      for (i = 0; i < dm->dc->caps.max_planes; ++i) {
 +              struct dc_plane_cap *plane = &dm->dc->caps.planes[i];
 +
 +              if (plane->type != DC_PLANE_TYPE_DCN_UNIVERSAL)
 +                      continue;
 +
 +              if (!plane->blends_with_above || !plane->blends_with_below)
 +                      continue;
 +
 +              if (!plane->supports_argb8888)
 +                      continue;
 +
 +              if (initialize_plane(dm, NULL, primary_planes + i,
 +                                   DRM_PLANE_TYPE_OVERLAY, plane)) {
 +                      DRM_ERROR("KMS: Failed to initialize overlay plane\n");
                        goto fail;
                }
 +
 +              /* Only create one overlay plane. */
 +              break;
        }
  
        for (i = 0; i < dm->dc->caps.max_streams; i++)
  fail:
        kfree(aencoder);
        kfree(aconnector);
 -      for (i = 0; i < dm->dc->caps.max_planes; i++)
 -              kfree(mode_info->planes[i]);
 +
        return -EINVAL;
  }
  
@@@ -2276,45 -2124,53 +2276,45 @@@ static int dm_early_init(void *handle
                adev->mode_info.num_crtc = 6;
                adev->mode_info.num_hpd = 6;
                adev->mode_info.num_dig = 6;
 -              adev->mode_info.plane_type = dm_plane_type_default;
                break;
        case CHIP_KAVERI:
                adev->mode_info.num_crtc = 4;
                adev->mode_info.num_hpd = 6;
                adev->mode_info.num_dig = 7;
 -              adev->mode_info.plane_type = dm_plane_type_default;
                break;
        case CHIP_KABINI:
        case CHIP_MULLINS:
                adev->mode_info.num_crtc = 2;
                adev->mode_info.num_hpd = 6;
                adev->mode_info.num_dig = 6;
 -              adev->mode_info.plane_type = dm_plane_type_default;
                break;
        case CHIP_FIJI:
        case CHIP_TONGA:
                adev->mode_info.num_crtc = 6;
                adev->mode_info.num_hpd = 6;
                adev->mode_info.num_dig = 7;
 -              adev->mode_info.plane_type = dm_plane_type_default;
                break;
        case CHIP_CARRIZO:
                adev->mode_info.num_crtc = 3;
                adev->mode_info.num_hpd = 6;
                adev->mode_info.num_dig = 9;
 -              adev->mode_info.plane_type = dm_plane_type_carizzo;
                break;
        case CHIP_STONEY:
                adev->mode_info.num_crtc = 2;
                adev->mode_info.num_hpd = 6;
                adev->mode_info.num_dig = 9;
 -              adev->mode_info.plane_type = dm_plane_type_stoney;
                break;
        case CHIP_POLARIS11:
        case CHIP_POLARIS12:
                adev->mode_info.num_crtc = 5;
                adev->mode_info.num_hpd = 5;
                adev->mode_info.num_dig = 5;
 -              adev->mode_info.plane_type = dm_plane_type_default;
                break;
        case CHIP_POLARIS10:
        case CHIP_VEGAM:
                adev->mode_info.num_crtc = 6;
                adev->mode_info.num_hpd = 6;
                adev->mode_info.num_dig = 6;
 -              adev->mode_info.plane_type = dm_plane_type_default;
                break;
        case CHIP_VEGA10:
        case CHIP_VEGA12:
                adev->mode_info.num_crtc = 6;
                adev->mode_info.num_hpd = 6;
                adev->mode_info.num_dig = 6;
 -              adev->mode_info.plane_type = dm_plane_type_default;
                break;
  #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
        case CHIP_RAVEN:
                adev->mode_info.num_crtc = 4;
                adev->mode_info.num_hpd = 4;
                adev->mode_info.num_dig = 4;
 -              adev->mode_info.plane_type = dm_plane_type_default;
                break;
  #endif
        default:
@@@ -2463,11 -2321,9 +2463,11 @@@ static inline uint64_t get_dcc_address(
        return offset ? (address + offset * 256) : 0;
  }
  
 -static bool fill_plane_dcc_attributes(struct amdgpu_device *adev,
 +static int fill_plane_dcc_attributes(struct amdgpu_device *adev,
                                      const struct amdgpu_framebuffer *afb,
 -                                    struct dc_plane_state *plane_state,
 +                                    const struct dc_plane_state *plane_state,
 +                                    struct dc_plane_dcc_param *dcc,
 +                                    struct dc_plane_address *address,
                                      uint64_t info)
  {
        struct dc *dc = adev->dm.dc;
        memset(&output, 0, sizeof(output));
  
        if (!offset)
 -              return false;
 +              return 0;
 +
 +      if (plane_state->address.type != PLN_ADDR_TYPE_GRAPHICS)
 +              return 0;
  
        if (!dc->cap_funcs.get_dcc_compression_cap)
 -              return false;
 +              return -EINVAL;
  
        input.format = plane_state->format;
        input.surface_size.width =
                input.scan = SCAN_DIRECTION_VERTICAL;
  
        if (!dc->cap_funcs.get_dcc_compression_cap(dc, &input, &output))
 -              return false;
 +              return -EINVAL;
  
        if (!output.capable)
 -              return false;
 +              return -EINVAL;
  
        if (i64b == 0 && output.grph.rgb.independent_64b_blks != 0)
 -              return false;
 +              return -EINVAL;
  
 -      plane_state->dcc.enable = 1;
 -      plane_state->dcc.grph.meta_pitch =
 +      dcc->enable = 1;
 +      dcc->grph.meta_pitch =
                AMDGPU_TILING_GET(info, DCC_PITCH_MAX) + 1;
 -      plane_state->dcc.grph.independent_64b_blks = i64b;
 +      dcc->grph.independent_64b_blks = i64b;
  
        dcc_address = get_dcc_address(afb->address, info);
 -      plane_state->address.grph.meta_addr.low_part =
 -              lower_32_bits(dcc_address);
 -      plane_state->address.grph.meta_addr.high_part =
 -              upper_32_bits(dcc_address);
 +      address->grph.meta_addr.low_part = lower_32_bits(dcc_address);
 +      address->grph.meta_addr.high_part = upper_32_bits(dcc_address);
  
 -      return true;
 +      return 0;
 +}
 +
 +static int
 +fill_plane_tiling_attributes(struct amdgpu_device *adev,
 +                           const struct amdgpu_framebuffer *afb,
 +                           const struct dc_plane_state *plane_state,
 +                           union dc_tiling_info *tiling_info,
 +                           struct dc_plane_dcc_param *dcc,
 +                           struct dc_plane_address *address,
 +                           uint64_t tiling_flags)
 +{
 +      int ret;
 +
 +      memset(tiling_info, 0, sizeof(*tiling_info));
 +      memset(dcc, 0, sizeof(*dcc));
 +      memset(address, 0, sizeof(*address));
 +
 +      if (plane_state->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) {
 +              address->type = PLN_ADDR_TYPE_GRAPHICS;
 +              address->grph.addr.low_part = lower_32_bits(afb->address);
 +              address->grph.addr.high_part = upper_32_bits(afb->address);
 +      } else {
 +              const struct drm_framebuffer *fb = &afb->base;
 +              uint64_t chroma_addr = afb->address + fb->offsets[1];
 +
 +              address->type = PLN_ADDR_TYPE_VIDEO_PROGRESSIVE;
 +              address->video_progressive.luma_addr.low_part =
 +                      lower_32_bits(afb->address);
 +              address->video_progressive.luma_addr.high_part =
 +                      upper_32_bits(afb->address);
 +              address->video_progressive.chroma_addr.low_part =
 +                      lower_32_bits(chroma_addr);
 +              address->video_progressive.chroma_addr.high_part =
 +                      upper_32_bits(chroma_addr);
 +      }
 +
 +      /* Fill GFX8 params */
 +      if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == DC_ARRAY_2D_TILED_THIN1) {
 +              unsigned int bankw, bankh, mtaspect, tile_split, num_banks;
 +
 +              bankw = AMDGPU_TILING_GET(tiling_flags, BANK_WIDTH);
 +              bankh = AMDGPU_TILING_GET(tiling_flags, BANK_HEIGHT);
 +              mtaspect = AMDGPU_TILING_GET(tiling_flags, MACRO_TILE_ASPECT);
 +              tile_split = AMDGPU_TILING_GET(tiling_flags, TILE_SPLIT);
 +              num_banks = AMDGPU_TILING_GET(tiling_flags, NUM_BANKS);
 +
 +              /* XXX fix me for VI */
 +              tiling_info->gfx8.num_banks = num_banks;
 +              tiling_info->gfx8.array_mode =
 +                              DC_ARRAY_2D_TILED_THIN1;
 +              tiling_info->gfx8.tile_split = tile_split;
 +              tiling_info->gfx8.bank_width = bankw;
 +              tiling_info->gfx8.bank_height = bankh;
 +              tiling_info->gfx8.tile_aspect = mtaspect;
 +              tiling_info->gfx8.tile_mode =
 +                              DC_ADDR_SURF_MICRO_TILING_DISPLAY;
 +      } else if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE)
 +                      == DC_ARRAY_1D_TILED_THIN1) {
 +              tiling_info->gfx8.array_mode = DC_ARRAY_1D_TILED_THIN1;
 +      }
 +
 +      tiling_info->gfx8.pipe_config =
 +                      AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG);
 +
 +      if (adev->asic_type == CHIP_VEGA10 ||
 +          adev->asic_type == CHIP_VEGA12 ||
 +          adev->asic_type == CHIP_VEGA20 ||
 +          adev->asic_type == CHIP_RAVEN) {
 +              /* Fill GFX9 params */
 +              tiling_info->gfx9.num_pipes =
 +                      adev->gfx.config.gb_addr_config_fields.num_pipes;
 +              tiling_info->gfx9.num_banks =
 +                      adev->gfx.config.gb_addr_config_fields.num_banks;
 +              tiling_info->gfx9.pipe_interleave =
 +                      adev->gfx.config.gb_addr_config_fields.pipe_interleave_size;
 +              tiling_info->gfx9.num_shader_engines =
 +                      adev->gfx.config.gb_addr_config_fields.num_se;
 +              tiling_info->gfx9.max_compressed_frags =
 +                      adev->gfx.config.gb_addr_config_fields.max_compress_frags;
 +              tiling_info->gfx9.num_rb_per_se =
 +                      adev->gfx.config.gb_addr_config_fields.num_rb_per_se;
 +              tiling_info->gfx9.swizzle =
 +                      AMDGPU_TILING_GET(tiling_flags, SWIZZLE_MODE);
 +              tiling_info->gfx9.shaderEnable = 1;
 +
 +              ret = fill_plane_dcc_attributes(adev, afb, plane_state, dcc,
 +                                              address, tiling_flags);
 +              if (ret)
 +                      return ret;
 +      }
 +
 +      return 0;
  }
  
  static int fill_plane_attributes_from_fb(struct amdgpu_device *adev,
                                         const struct amdgpu_framebuffer *amdgpu_fb)
  {
        uint64_t tiling_flags;
 -      unsigned int awidth;
        const struct drm_framebuffer *fb = &amdgpu_fb->base;
        int ret = 0;
        struct drm_format_name_buf format_name;
        }
  
        memset(&plane_state->address, 0, sizeof(plane_state->address));
 -      memset(&plane_state->tiling_info, 0, sizeof(plane_state->tiling_info));
 -      memset(&plane_state->dcc, 0, sizeof(plane_state->dcc));
  
        if (plane_state->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) {
 -              plane_state->address.type = PLN_ADDR_TYPE_GRAPHICS;
                plane_state->plane_size.grph.surface_size.x = 0;
                plane_state->plane_size.grph.surface_size.y = 0;
                plane_state->plane_size.grph.surface_size.width = fb->width;
                plane_state->color_space = COLOR_SPACE_SRGB;
  
        } else {
 -              awidth = ALIGN(fb->width, 64);
 -              plane_state->address.type = PLN_ADDR_TYPE_VIDEO_PROGRESSIVE;
                plane_state->plane_size.video.luma_size.x = 0;
                plane_state->plane_size.video.luma_size.y = 0;
 -              plane_state->plane_size.video.luma_size.width = awidth;
 +              plane_state->plane_size.video.luma_size.width = fb->width;
                plane_state->plane_size.video.luma_size.height = fb->height;
 -              /* TODO: unhardcode */
 -              plane_state->plane_size.video.luma_pitch = awidth;
 +              plane_state->plane_size.video.luma_pitch =
 +                      fb->pitches[0] / fb->format->cpp[0];
  
                plane_state->plane_size.video.chroma_size.x = 0;
                plane_state->plane_size.video.chroma_size.y = 0;
 -              plane_state->plane_size.video.chroma_size.width = awidth;
 -              plane_state->plane_size.video.chroma_size.height = fb->height;
 -              plane_state->plane_size.video.chroma_pitch = awidth / 2;
 +              /* TODO: set these based on surface format */
 +              plane_state->plane_size.video.chroma_size.width = fb->width / 2;
 +              plane_state->plane_size.video.chroma_size.height = fb->height / 2;
 +
 +              plane_state->plane_size.video.chroma_pitch =
 +                      fb->pitches[1] / fb->format->cpp[1];
  
                /* TODO: unhardcode */
                plane_state->color_space = COLOR_SPACE_YCBCR709;
        }
  
 -      /* Fill GFX8 params */
 -      if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == DC_ARRAY_2D_TILED_THIN1) {
 -              unsigned int bankw, bankh, mtaspect, tile_split, num_banks;
 -
 -              bankw = AMDGPU_TILING_GET(tiling_flags, BANK_WIDTH);
 -              bankh = AMDGPU_TILING_GET(tiling_flags, BANK_HEIGHT);
 -              mtaspect = AMDGPU_TILING_GET(tiling_flags, MACRO_TILE_ASPECT);
 -              tile_split = AMDGPU_TILING_GET(tiling_flags, TILE_SPLIT);
 -              num_banks = AMDGPU_TILING_GET(tiling_flags, NUM_BANKS);
 -
 -              /* XXX fix me for VI */
 -              plane_state->tiling_info.gfx8.num_banks = num_banks;
 -              plane_state->tiling_info.gfx8.array_mode =
 -                              DC_ARRAY_2D_TILED_THIN1;
 -              plane_state->tiling_info.gfx8.tile_split = tile_split;
 -              plane_state->tiling_info.gfx8.bank_width = bankw;
 -              plane_state->tiling_info.gfx8.bank_height = bankh;
 -              plane_state->tiling_info.gfx8.tile_aspect = mtaspect;
 -              plane_state->tiling_info.gfx8.tile_mode =
 -                              DC_ADDR_SURF_MICRO_TILING_DISPLAY;
 -      } else if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE)
 -                      == DC_ARRAY_1D_TILED_THIN1) {
 -              plane_state->tiling_info.gfx8.array_mode = DC_ARRAY_1D_TILED_THIN1;
 -      }
 -
 -      plane_state->tiling_info.gfx8.pipe_config =
 -                      AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG);
 -
 -      if (adev->asic_type == CHIP_VEGA10 ||
 -          adev->asic_type == CHIP_VEGA12 ||
 -          adev->asic_type == CHIP_VEGA20 ||
 -          adev->asic_type == CHIP_RAVEN) {
 -              /* Fill GFX9 params */
 -              plane_state->tiling_info.gfx9.num_pipes =
 -                      adev->gfx.config.gb_addr_config_fields.num_pipes;
 -              plane_state->tiling_info.gfx9.num_banks =
 -                      adev->gfx.config.gb_addr_config_fields.num_banks;
 -              plane_state->tiling_info.gfx9.pipe_interleave =
 -                      adev->gfx.config.gb_addr_config_fields.pipe_interleave_size;
 -              plane_state->tiling_info.gfx9.num_shader_engines =
 -                      adev->gfx.config.gb_addr_config_fields.num_se;
 -              plane_state->tiling_info.gfx9.max_compressed_frags =
 -                      adev->gfx.config.gb_addr_config_fields.max_compress_frags;
 -              plane_state->tiling_info.gfx9.num_rb_per_se =
 -                      adev->gfx.config.gb_addr_config_fields.num_rb_per_se;
 -              plane_state->tiling_info.gfx9.swizzle =
 -                      AMDGPU_TILING_GET(tiling_flags, SWIZZLE_MODE);
 -              plane_state->tiling_info.gfx9.shaderEnable = 1;
 -
 -              fill_plane_dcc_attributes(adev, amdgpu_fb, plane_state,
 -                                        tiling_flags);
 -      }
 +      fill_plane_tiling_attributes(adev, amdgpu_fb, plane_state,
 +                                   &plane_state->tiling_info,
 +                                   &plane_state->dcc,
 +                                   &plane_state->address,
 +                                   tiling_flags);
  
        plane_state->visible = true;
        plane_state->scaling_quality.h_taps_c = 0;
  
  }
  
 +static void
 +fill_blending_from_plane_state(struct drm_plane_state *plane_state,
 +                             const struct dc_plane_state *dc_plane_state,
 +                             bool *per_pixel_alpha, bool *global_alpha,
 +                             int *global_alpha_value)
 +{
 +      *per_pixel_alpha = false;
 +      *global_alpha = false;
 +      *global_alpha_value = 0xff;
 +
 +      if (plane_state->plane->type != DRM_PLANE_TYPE_OVERLAY)
 +              return;
 +
 +      if (plane_state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI) {
 +              static const uint32_t alpha_formats[] = {
 +                      DRM_FORMAT_ARGB8888,
 +                      DRM_FORMAT_RGBA8888,
 +                      DRM_FORMAT_ABGR8888,
 +              };
 +              uint32_t format = plane_state->fb->format->format;
 +              unsigned int i;
 +
 +              for (i = 0; i < ARRAY_SIZE(alpha_formats); ++i) {
 +                      if (format == alpha_formats[i]) {
 +                              *per_pixel_alpha = true;
 +                              break;
 +                      }
 +              }
 +      }
 +
 +      if (plane_state->alpha < 0xffff) {
 +              *global_alpha = true;
 +              *global_alpha_value = plane_state->alpha >> 8;
 +      }
 +}
 +
 +static int
 +fill_plane_color_attributes(const struct drm_plane_state *plane_state,
 +                          const struct dc_plane_state *dc_plane_state,
 +                          enum dc_color_space *color_space)
 +{
 +      bool full_range;
 +
 +      *color_space = COLOR_SPACE_SRGB;
 +
 +      /* DRM color properties only affect non-RGB formats. */
 +      if (dc_plane_state->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
 +              return 0;
 +
 +      full_range = (plane_state->color_range == DRM_COLOR_YCBCR_FULL_RANGE);
 +
 +      switch (plane_state->color_encoding) {
 +      case DRM_COLOR_YCBCR_BT601:
 +              if (full_range)
 +                      *color_space = COLOR_SPACE_YCBCR601;
 +              else
 +                      *color_space = COLOR_SPACE_YCBCR601_LIMITED;
 +              break;
 +
 +      case DRM_COLOR_YCBCR_BT709:
 +              if (full_range)
 +                      *color_space = COLOR_SPACE_YCBCR709;
 +              else
 +                      *color_space = COLOR_SPACE_YCBCR709_LIMITED;
 +              break;
 +
 +      case DRM_COLOR_YCBCR_BT2020:
 +              if (full_range)
 +                      *color_space = COLOR_SPACE_2020_YCBCR;
 +              else
 +                      return -EINVAL;
 +              break;
 +
 +      default:
 +              return -EINVAL;
 +      }
 +
 +      return 0;
 +}
 +
  static int fill_plane_attributes(struct amdgpu_device *adev,
                                 struct dc_plane_state *dc_plane_state,
                                 struct drm_plane_state *plane_state,
        if (ret)
                return ret;
  
 +      ret = fill_plane_color_attributes(plane_state, dc_plane_state,
 +                                        &dc_plane_state->color_space);
 +      if (ret)
 +              return ret;
 +
        /*
         * Always set input transfer function, since plane state is refreshed
         * every time.
                dc_plane_state->in_transfer_func = NULL;
        }
  
 +      fill_blending_from_plane_state(plane_state, dc_plane_state,
 +                                     &dc_plane_state->per_pixel_alpha,
 +                                     &dc_plane_state->global_alpha,
 +                                     &dc_plane_state->global_alpha_value);
 +
        return ret;
  }
  
@@@ -3413,41 -3136,12 +3413,41 @@@ dm_crtc_duplicate_state(struct drm_crt
        return &state->base;
  }
  
 +static inline int dm_set_vupdate_irq(struct drm_crtc *crtc, bool enable)
 +{
 +      enum dc_irq_source irq_source;
 +      struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
 +      struct amdgpu_device *adev = crtc->dev->dev_private;
 +      int rc;
 +
 +      irq_source = IRQ_TYPE_VUPDATE + acrtc->otg_inst;
 +
 +      rc = dc_interrupt_set(adev->dm.dc, irq_source, enable) ? 0 : -EBUSY;
 +
 +      DRM_DEBUG_DRIVER("crtc %d - vupdate irq %sabling: r=%d\n",
 +                       acrtc->crtc_id, enable ? "en" : "dis", rc);
 +      return rc;
 +}
  
  static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable)
  {
        enum dc_irq_source irq_source;
        struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
        struct amdgpu_device *adev = crtc->dev->dev_private;
 +      struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state);
 +      int rc = 0;
 +
 +      if (enable) {
 +              /* vblank irq on -> Only need vupdate irq in vrr mode */
 +              if (amdgpu_dm_vrr_active(acrtc_state))
 +                      rc = dm_set_vupdate_irq(crtc, true);
 +      } else {
 +              /* vblank irq off -> vupdate irq off */
 +              rc = dm_set_vupdate_irq(crtc, false);
 +      }
 +
 +      if (rc)
 +              return rc;
  
        irq_source = IRQ_TYPE_VBLANK + acrtc->otg_inst;
        return dc_interrupt_set(adev->dm.dc, irq_source, enable) ? 0 : -EBUSY;
@@@ -3889,8 -3583,11 +3889,8 @@@ static void dm_drm_plane_reset(struct d
        amdgpu_state = kzalloc(sizeof(*amdgpu_state), GFP_KERNEL);
        WARN_ON(amdgpu_state == NULL);
  
 -      if (amdgpu_state) {
 -              plane->state = &amdgpu_state->base;
 -              plane->state->plane = plane;
 -              plane->state->rotation = DRM_MODE_ROTATE_0;
 -      }
 +      if (amdgpu_state)
 +              __drm_atomic_helper_plane_reset(plane, &amdgpu_state->base);
  }
  
  static struct drm_plane_state *
@@@ -3940,8 -3637,10 +3940,8 @@@ static int dm_plane_helper_prepare_fb(s
        struct drm_gem_object *obj;
        struct amdgpu_device *adev;
        struct amdgpu_bo *rbo;
 -      uint64_t chroma_addr = 0;
        struct dm_plane_state *dm_plane_state_new, *dm_plane_state_old;
 -      uint64_t tiling_flags, dcc_address;
 -      unsigned int awidth;
 +      uint64_t tiling_flags;
        uint32_t domain;
        int r;
  
                        dm_plane_state_old->dc_state != dm_plane_state_new->dc_state) {
                struct dc_plane_state *plane_state = dm_plane_state_new->dc_state;
  
 -              if (plane_state->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) {
 -                      plane_state->address.grph.addr.low_part = lower_32_bits(afb->address);
 -                      plane_state->address.grph.addr.high_part = upper_32_bits(afb->address);
 -
 -                      dcc_address =
 -                              get_dcc_address(afb->address, tiling_flags);
 -                      plane_state->address.grph.meta_addr.low_part =
 -                              lower_32_bits(dcc_address);
 -                      plane_state->address.grph.meta_addr.high_part =
 -                              upper_32_bits(dcc_address);
 -              } else {
 -                      awidth = ALIGN(new_state->fb->width, 64);
 -                      plane_state->address.type = PLN_ADDR_TYPE_VIDEO_PROGRESSIVE;
 -                      plane_state->address.video_progressive.luma_addr.low_part
 -                                                      = lower_32_bits(afb->address);
 -                      plane_state->address.video_progressive.luma_addr.high_part
 -                                                      = upper_32_bits(afb->address);
 -                      chroma_addr = afb->address + (u64)awidth * new_state->fb->height;
 -                      plane_state->address.video_progressive.chroma_addr.low_part
 -                                                      = lower_32_bits(chroma_addr);
 -                      plane_state->address.video_progressive.chroma_addr.high_part
 -                                                      = upper_32_bits(chroma_addr);
 -              }
 +              fill_plane_tiling_attributes(
 +                      adev, afb, plane_state, &plane_state->tiling_info,
 +                      &plane_state->dcc, &plane_state->address, tiling_flags);
        }
  
        return 0;
@@@ -4109,12 -3828,9 +4109,12 @@@ static const uint32_t rgb_formats[] = 
        DRM_FORMAT_ABGR8888,
  };
  
 -static const uint32_t yuv_formats[] = {
 -      DRM_FORMAT_NV12,
 -      DRM_FORMAT_NV21,
 +static const uint32_t overlay_formats[] = {
 +      DRM_FORMAT_XRGB8888,
 +      DRM_FORMAT_ARGB8888,
 +      DRM_FORMAT_RGBA8888,
 +      DRM_FORMAT_XBGR8888,
 +      DRM_FORMAT_ABGR8888,
  };
  
  static const u32 cursor_formats[] = {
  
  static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
                                struct drm_plane *plane,
 -                              unsigned long possible_crtcs)
 +                              unsigned long possible_crtcs,
 +                              const struct dc_plane_cap *plane_cap)
  {
        int res = -EPERM;
  
                                plane,
                                possible_crtcs,
                                &dm_plane_funcs,
 -                              yuv_formats,
 -                              ARRAY_SIZE(yuv_formats),
 +                              overlay_formats,
 +                              ARRAY_SIZE(overlay_formats),
                                NULL, plane->type, NULL);
                break;
        case DRM_PLANE_TYPE_CURSOR:
                break;
        }
  
 +      if (plane->type == DRM_PLANE_TYPE_OVERLAY &&
 +          plane_cap && plane_cap->per_pixel_alpha) {
 +              unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) |
 +                                        BIT(DRM_MODE_BLEND_PREMULTI);
 +
 +              drm_plane_create_alpha_property(plane);
 +              drm_plane_create_blend_mode_property(plane, blend_caps);
 +      }
 +
        drm_plane_helper_add(plane, &dm_plane_helper_funcs);
  
        /* Create (reset) the plane state */
@@@ -4194,7 -3900,7 +4194,7 @@@ static int amdgpu_dm_crtc_init(struct a
                goto fail;
  
        cursor_plane->type = DRM_PLANE_TYPE_CURSOR;
 -      res = amdgpu_dm_plane_init(dm, cursor_plane, 0);
 +      res = amdgpu_dm_plane_init(dm, cursor_plane, 0, NULL);
  
        acrtc = kzalloc(sizeof(struct amdgpu_crtc), GFP_KERNEL);
        if (!acrtc)
@@@ -4628,8 -4334,6 +4628,8 @@@ static int amdgpu_dm_connector_init(str
                DRM_ERROR("Failed to create debugfs for connector");
                goto out_free;
        }
 +      aconnector->debugfs_dpcd_address = 0;
 +      aconnector->debugfs_dpcd_size = 0;
  #endif
  
        if (connector_type == DRM_MODE_CONNECTOR_DisplayPort
@@@ -4829,6 -4533,7 +4829,7 @@@ static void handle_cursor_update(struc
        amdgpu_crtc->cursor_width = plane->state->crtc_w;
        amdgpu_crtc->cursor_height = plane->state->crtc_h;
  
+       memset(&attributes, 0, sizeof(attributes));
        attributes.address.high_part = upper_32_bits(address);
        attributes.address.low_part  = lower_32_bits(address);
        attributes.width             = plane->state->crtc_w;
@@@ -4879,6 -4584,7 +4880,6 @@@ static void update_freesync_state_on_st
  {
        struct mod_vrr_params vrr_params = new_crtc_state->vrr_params;
        struct dc_info_packet vrr_infopacket = {0};
 -      struct mod_freesync_config config = new_crtc_state->freesync_config;
  
        if (!new_stream)
                return;
        if (!new_stream->timing.h_total || !new_stream->timing.v_total)
                return;
  
 -      if (new_crtc_state->vrr_supported &&
 -          config.min_refresh_in_uhz &&
 -          config.max_refresh_in_uhz) {
 -              config.state = new_crtc_state->base.vrr_enabled ?
 -                      VRR_STATE_ACTIVE_VARIABLE :
 -                      VRR_STATE_INACTIVE;
 -      } else {
 -              config.state = VRR_STATE_UNSUPPORTED;
 -      }
 -
 -      mod_freesync_build_vrr_params(dm->freesync_module,
 -                                    new_stream,
 -                                    &config, &vrr_params);
 -
        if (surface) {
                mod_freesync_handle_preflip(
                        dm->freesync_module,
                              (int)vrr_params.state);
  }
  
 +static void pre_update_freesync_state_on_stream(
 +      struct amdgpu_display_manager *dm,
 +      struct dm_crtc_state *new_crtc_state)
 +{
 +      struct dc_stream_state *new_stream = new_crtc_state->stream;
 +      struct mod_vrr_params vrr_params = new_crtc_state->vrr_params;
 +      struct mod_freesync_config config = new_crtc_state->freesync_config;
 +
 +      if (!new_stream)
 +              return;
 +
 +      /*
 +       * TODO: Determine why min/max totals and vrefresh can be 0 here.
 +       * For now it's sufficient to just guard against these conditions.
 +       */
 +      if (!new_stream->timing.h_total || !new_stream->timing.v_total)
 +              return;
 +
 +      if (new_crtc_state->vrr_supported &&
 +          config.min_refresh_in_uhz &&
 +          config.max_refresh_in_uhz) {
 +              config.state = new_crtc_state->base.vrr_enabled ?
 +                      VRR_STATE_ACTIVE_VARIABLE :
 +                      VRR_STATE_INACTIVE;
 +      } else {
 +              config.state = VRR_STATE_UNSUPPORTED;
 +      }
 +
 +      mod_freesync_build_vrr_params(dm->freesync_module,
 +                                    new_stream,
 +                                    &config, &vrr_params);
 +
 +      new_crtc_state->freesync_timing_changed |=
 +              (memcmp(&new_crtc_state->vrr_params.adjust,
 +                      &vrr_params.adjust,
 +                      sizeof(vrr_params.adjust)) != 0);
 +
 +      new_crtc_state->vrr_params = vrr_params;
 +}
 +
 +static void amdgpu_dm_handle_vrr_transition(struct dm_crtc_state *old_state,
 +                                          struct dm_crtc_state *new_state)
 +{
 +      bool old_vrr_active = amdgpu_dm_vrr_active(old_state);
 +      bool new_vrr_active = amdgpu_dm_vrr_active(new_state);
 +
 +      if (!old_vrr_active && new_vrr_active) {
 +              /* Transition VRR inactive -> active:
 +               * While VRR is active, we must not disable vblank irq, as a
 +               * reenable after disable would compute bogus vblank/pflip
 +               * timestamps if it likely happened inside display front-porch.
 +               *
 +               * We also need vupdate irq for the actual core vblank handling
 +               * at end of vblank.
 +               */
 +              dm_set_vupdate_irq(new_state->base.crtc, true);
 +              drm_crtc_vblank_get(new_state->base.crtc);
 +              DRM_DEBUG_DRIVER("%s: crtc=%u VRR off->on: Get vblank ref\n",
 +                               __func__, new_state->base.crtc->base.id);
 +      } else if (old_vrr_active && !new_vrr_active) {
 +              /* Transition VRR active -> inactive:
 +               * Allow vblank irq disable again for fixed refresh rate.
 +               */
 +              dm_set_vupdate_irq(new_state->base.crtc, false);
 +              drm_crtc_vblank_put(new_state->base.crtc);
 +              DRM_DEBUG_DRIVER("%s: crtc=%u VRR on->off: Drop vblank ref\n",
 +                               __func__, new_state->base.crtc->base.id);
 +      }
 +}
 +
  static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
                                    struct dc_state *dc_state,
                                    struct drm_device *dev,
                                    struct amdgpu_display_manager *dm,
                                    struct drm_crtc *pcrtc,
 -                                  bool *wait_for_vblank)
 +                                  bool wait_for_vblank)
  {
        uint32_t i, r;
        uint64_t timestamp_ns;
        struct dm_crtc_state *acrtc_state = to_dm_crtc_state(new_pcrtc_state);
        struct dm_crtc_state *dm_old_crtc_state =
                        to_dm_crtc_state(drm_atomic_get_old_crtc_state(state, pcrtc));
 -      int flip_count = 0, planes_count = 0, vpos, hpos;
 +      int planes_count = 0, vpos, hpos;
        unsigned long flags;
        struct amdgpu_bo *abo;
 -      uint64_t tiling_flags, dcc_address;
 -      uint32_t target, target_vblank;
 -      uint64_t last_flip_vblank;
 -      bool vrr_active = acrtc_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE;
 -
 -      struct {
 -              struct dc_surface_update surface_updates[MAX_SURFACES];
 -              struct dc_flip_addrs flip_addrs[MAX_SURFACES];
 -              struct dc_stream_update stream_update;
 -      } *flip;
 -
 +      uint64_t tiling_flags;
 +      uint32_t target_vblank, last_flip_vblank;
 +      bool vrr_active = amdgpu_dm_vrr_active(acrtc_state);
 +      bool pflip_present = false;
        struct {
                struct dc_surface_update surface_updates[MAX_SURFACES];
                struct dc_plane_info plane_infos[MAX_SURFACES];
                struct dc_scaling_info scaling_infos[MAX_SURFACES];
 +              struct dc_flip_addrs flip_addrs[MAX_SURFACES];
                struct dc_stream_update stream_update;
 -      } *full;
 +      } *bundle;
  
 -      flip = kzalloc(sizeof(*flip), GFP_KERNEL);
 -      full = kzalloc(sizeof(*full), GFP_KERNEL);
 +      bundle = kzalloc(sizeof(*bundle), GFP_KERNEL);
  
 -      if (!flip || !full) {
 -              dm_error("Failed to allocate update bundles\n");
 +      if (!bundle) {
 +              dm_error("Failed to allocate update bundle\n");
                goto cleanup;
        }
  
                struct drm_crtc_state *new_crtc_state;
                struct drm_framebuffer *fb = new_plane_state->fb;
                struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(fb);
 -              bool pflip_needed;
 +              bool plane_needs_flip;
                struct dc_plane_state *dc_plane;
                struct dm_plane_state *dm_new_plane_state = to_dm_plane_state(new_plane_state);
  
                if (!new_crtc_state->active)
                        continue;
  
 -              pflip_needed = old_plane_state->fb &&
 -                      old_plane_state->fb != new_plane_state->fb;
 -
                dc_plane = dm_new_plane_state->dc_state;
  
 -              if (pflip_needed) {
 -                      /*
 -                       * Assume even ONE crtc with immediate flip means
 -                       * entire can't wait for VBLANK
 -                       * TODO Check if it's correct
 -                       */
 -                      if (new_pcrtc_state->pageflip_flags & DRM_MODE_PAGE_FLIP_ASYNC)
 -                              *wait_for_vblank = false;
 +              bundle->surface_updates[planes_count].surface = dc_plane;
 +              if (new_pcrtc_state->color_mgmt_changed) {
 +                      bundle->surface_updates[planes_count].gamma = dc_plane->gamma_correction;
 +                      bundle->surface_updates[planes_count].in_transfer_func = dc_plane->in_transfer_func;
 +              }
  
 -                      /*
 -                       * TODO This might fail and hence better not used, wait
 -                       * explicitly on fences instead
 -                       * and in general should be called for
 -                       * blocking commit to as per framework helpers
 -                       */
 -                      abo = gem_to_amdgpu_bo(fb->obj[0]);
 -                      r = amdgpu_bo_reserve(abo, true);
 -                      if (unlikely(r != 0))
 -                              DRM_ERROR("failed to reserve buffer before flip\n");
  
 -                      /*
 -                       * Wait for all fences on this FB. Do limited wait to avoid
 -                       * deadlock during GPU reset when this fence will not signal
 -                       * but we hold reservation lock for the BO.
 -                       */
 -                      r = reservation_object_wait_timeout_rcu(abo->tbo.resv,
 -                                                              true, false,
 -                                                              msecs_to_jiffies(5000));
 -                      if (unlikely(r == 0))
 -                              DRM_ERROR("Waiting for fences timed out.");
 +              bundle->scaling_infos[planes_count].scaling_quality = dc_plane->scaling_quality;
 +              bundle->scaling_infos[planes_count].src_rect = dc_plane->src_rect;
 +              bundle->scaling_infos[planes_count].dst_rect = dc_plane->dst_rect;
 +              bundle->scaling_infos[planes_count].clip_rect = dc_plane->clip_rect;
 +              bundle->surface_updates[planes_count].scaling_info = &bundle->scaling_infos[planes_count];
  
 +              fill_plane_color_attributes(
 +                      new_plane_state, dc_plane,
 +                      &bundle->plane_infos[planes_count].color_space);
  
 +              bundle->plane_infos[planes_count].format = dc_plane->format;
 +              bundle->plane_infos[planes_count].plane_size = dc_plane->plane_size;
 +              bundle->plane_infos[planes_count].rotation = dc_plane->rotation;
 +              bundle->plane_infos[planes_count].horizontal_mirror = dc_plane->horizontal_mirror;
 +              bundle->plane_infos[planes_count].stereo_format = dc_plane->stereo_format;
 +              bundle->plane_infos[planes_count].tiling_info = dc_plane->tiling_info;
 +              bundle->plane_infos[planes_count].visible = dc_plane->visible;
 +              bundle->plane_infos[planes_count].global_alpha = dc_plane->global_alpha;
 +              bundle->plane_infos[planes_count].global_alpha_value = dc_plane->global_alpha_value;
 +              bundle->plane_infos[planes_count].per_pixel_alpha = dc_plane->per_pixel_alpha;
 +              bundle->plane_infos[planes_count].dcc = dc_plane->dcc;
 +              bundle->surface_updates[planes_count].plane_info = &bundle->plane_infos[planes_count];
  
 -                      amdgpu_bo_get_tiling_flags(abo, &tiling_flags);
 +              plane_needs_flip = old_plane_state->fb && new_plane_state->fb;
  
 -                      amdgpu_bo_unreserve(abo);
 +              pflip_present = pflip_present || plane_needs_flip;
  
 -                      flip->flip_addrs[flip_count].address.grph.addr.low_part = lower_32_bits(afb->address);
 -                      flip->flip_addrs[flip_count].address.grph.addr.high_part = upper_32_bits(afb->address);
 +              if (!plane_needs_flip) {
 +                      planes_count += 1;
 +                      continue;
 +              }
  
 -                      dcc_address = get_dcc_address(afb->address, tiling_flags);
 -                      flip->flip_addrs[flip_count].address.grph.meta_addr.low_part = lower_32_bits(dcc_address);
 -                      flip->flip_addrs[flip_count].address.grph.meta_addr.high_part = upper_32_bits(dcc_address);
 +              /*
 +               * TODO This might fail and hence better not used, wait
 +               * explicitly on fences instead
 +               * and in general should be called for
 +               * blocking commit to as per framework helpers
 +               */
 +              abo = gem_to_amdgpu_bo(fb->obj[0]);
 +              r = amdgpu_bo_reserve(abo, true);
 +              if (unlikely(r != 0)) {
 +                      DRM_ERROR("failed to reserve buffer before flip\n");
 +                      WARN_ON(1);
 +              }
  
 -                      flip->flip_addrs[flip_count].flip_immediate =
 -                                      (crtc->state->pageflip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0;
 +              /* Wait for all fences on this FB */
 +              WARN_ON(reservation_object_wait_timeout_rcu(abo->tbo.resv, true, false,
 +                                                                          MAX_SCHEDULE_TIMEOUT) < 0);
  
 -                      timestamp_ns = ktime_get_ns();
 -                      flip->flip_addrs[flip_count].flip_timestamp_in_us = div_u64(timestamp_ns, 1000);
 -                      flip->surface_updates[flip_count].flip_addr = &flip->flip_addrs[flip_count];
 -                      flip->surface_updates[flip_count].surface = dc_plane;
 +              amdgpu_bo_get_tiling_flags(abo, &tiling_flags);
  
 -                      if (!flip->surface_updates[flip_count].surface) {
 -                              DRM_ERROR("No surface for CRTC: id=%d\n",
 -                                              acrtc_attach->crtc_id);
 -                              continue;
 -                      }
 +              amdgpu_bo_unreserve(abo);
  
 -                      if (plane == pcrtc->primary)
 -                              update_freesync_state_on_stream(
 -                                      dm,
 -                                      acrtc_state,
 -                                      acrtc_state->stream,
 -                                      dc_plane,
 -                                      flip->flip_addrs[flip_count].flip_timestamp_in_us);
 +              fill_plane_tiling_attributes(dm->adev, afb, dc_plane,
 +                      &bundle->plane_infos[planes_count].tiling_info,
 +                      &bundle->plane_infos[planes_count].dcc,
 +                      &bundle->flip_addrs[planes_count].address,
 +                      tiling_flags);
  
 -                      DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x\n",
 -                                       __func__,
 -                                       flip->flip_addrs[flip_count].address.grph.addr.high_part,
 -                                       flip->flip_addrs[flip_count].address.grph.addr.low_part);
 +              bundle->flip_addrs[planes_count].flip_immediate =
 +                              (crtc->state->pageflip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0;
  
 -                      flip_count += 1;
 -              }
 +              timestamp_ns = ktime_get_ns();
 +              bundle->flip_addrs[planes_count].flip_timestamp_in_us = div_u64(timestamp_ns, 1000);
 +              bundle->surface_updates[planes_count].flip_addr = &bundle->flip_addrs[planes_count];
 +              bundle->surface_updates[planes_count].surface = dc_plane;
  
 -              full->surface_updates[planes_count].surface = dc_plane;
 -              if (new_pcrtc_state->color_mgmt_changed) {
 -                      full->surface_updates[planes_count].gamma = dc_plane->gamma_correction;
 -                      full->surface_updates[planes_count].in_transfer_func = dc_plane->in_transfer_func;
 +              if (!bundle->surface_updates[planes_count].surface) {
 +                      DRM_ERROR("No surface for CRTC: id=%d\n",
 +                                      acrtc_attach->crtc_id);
 +                      continue;
                }
  
 +              if (plane == pcrtc->primary)
 +                      update_freesync_state_on_stream(
 +                              dm,
 +                              acrtc_state,
 +                              acrtc_state->stream,
 +                              dc_plane,
 +                              bundle->flip_addrs[planes_count].flip_timestamp_in_us);
  
 -              full->scaling_infos[planes_count].scaling_quality = dc_plane->scaling_quality;
 -              full->scaling_infos[planes_count].src_rect = dc_plane->src_rect;
 -              full->scaling_infos[planes_count].dst_rect = dc_plane->dst_rect;
 -              full->scaling_infos[planes_count].clip_rect = dc_plane->clip_rect;
 -              full->surface_updates[planes_count].scaling_info = &full->scaling_infos[planes_count];
 -
 -
 -              full->plane_infos[planes_count].color_space = dc_plane->color_space;
 -              full->plane_infos[planes_count].format = dc_plane->format;
 -              full->plane_infos[planes_count].plane_size = dc_plane->plane_size;
 -              full->plane_infos[planes_count].rotation = dc_plane->rotation;
 -              full->plane_infos[planes_count].horizontal_mirror = dc_plane->horizontal_mirror;
 -              full->plane_infos[planes_count].stereo_format = dc_plane->stereo_format;
 -              full->plane_infos[planes_count].tiling_info = dc_plane->tiling_info;
 -              full->plane_infos[planes_count].visible = dc_plane->visible;
 -              full->plane_infos[planes_count].per_pixel_alpha = dc_plane->per_pixel_alpha;
 -              full->plane_infos[planes_count].dcc = dc_plane->dcc;
 -              full->surface_updates[planes_count].plane_info = &full->plane_infos[planes_count];
 +              DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x\n",
 +                               __func__,
 +                               bundle->flip_addrs[planes_count].address.grph.addr.high_part,
 +                               bundle->flip_addrs[planes_count].address.grph.addr.low_part);
  
                planes_count += 1;
  
        }
  
 -      /*
 -       * TODO: For proper atomic behaviour, we should be calling into DC once with
 -       * all the changes.  However, DC refuses to do pageflips and non-pageflip
 -       * changes in the same call.  Change DC to respect atomic behaviour,
 -       * hopefully eliminating dc_*_update structs in their entirety.
 -       */
 -      if (flip_count) {
 +      if (pflip_present) {
                if (!vrr_active) {
                        /* Use old throttling in non-vrr fixed refresh rate mode
                         * to keep flip scheduling based on target vblank counts
                         * clients using the GLX_OML_sync_control extension or
                         * DRI3/Present extension with defined target_msc.
                         */
 -                      last_flip_vblank = drm_crtc_vblank_count(pcrtc);
 +                      last_flip_vblank = amdgpu_get_vblank_counter_kms(dm->ddev, acrtc_attach->crtc_id);
                }
                else {
                        /* For variable refresh rate mode only:
                        spin_unlock_irqrestore(&pcrtc->dev->event_lock, flags);
                }
  
 -              target = (uint32_t)last_flip_vblank + *wait_for_vblank;
 -
 -              /* Prepare wait for target vblank early - before the fence-waits */
 -              target_vblank = target - (uint32_t)drm_crtc_vblank_count(pcrtc) +
 -                              amdgpu_get_vblank_counter_kms(pcrtc->dev, acrtc_attach->crtc_id);
 +              target_vblank = last_flip_vblank + wait_for_vblank;
  
                /*
                 * Wait until we're out of the vertical blank period before the one
                if (acrtc_state->stream) {
  
                        if (acrtc_state->freesync_timing_changed)
 -                              flip->stream_update.adjust =
 +                              bundle->stream_update.adjust =
                                        &acrtc_state->stream->adjust;
  
                        if (acrtc_state->freesync_vrr_info_changed)
 -                              flip->stream_update.vrr_infopacket =
 +                              bundle->stream_update.vrr_infopacket =
                                        &acrtc_state->stream->vrr_infopacket;
                }
 -
 -              mutex_lock(&dm->dc_lock);
 -              dc_commit_updates_for_stream(dm->dc,
 -                                                   flip->surface_updates,
 -                                                   flip_count,
 -                                                   acrtc_state->stream,
 -                                                   &flip->stream_update,
 -                                                   dc_state);
 -              mutex_unlock(&dm->dc_lock);
        }
  
        if (planes_count) {
                if (new_pcrtc_state->mode_changed) {
 -                      full->stream_update.src = acrtc_state->stream->src;
 -                      full->stream_update.dst = acrtc_state->stream->dst;
 +                      bundle->stream_update.src = acrtc_state->stream->src;
 +                      bundle->stream_update.dst = acrtc_state->stream->dst;
                }
  
                if (new_pcrtc_state->color_mgmt_changed)
 -                      full->stream_update.out_transfer_func = acrtc_state->stream->out_transfer_func;
 +                      bundle->stream_update.out_transfer_func = acrtc_state->stream->out_transfer_func;
  
                acrtc_state->stream->abm_level = acrtc_state->abm_level;
                if (acrtc_state->abm_level != dm_old_crtc_state->abm_level)
 -                      full->stream_update.abm_level = &acrtc_state->abm_level;
 +                      bundle->stream_update.abm_level = &acrtc_state->abm_level;
  
                mutex_lock(&dm->dc_lock);
                dc_commit_updates_for_stream(dm->dc,
 -                                                   full->surface_updates,
 +                                                   bundle->surface_updates,
                                                     planes_count,
                                                     acrtc_state->stream,
 -                                                   &full->stream_update,
 +                                                   &bundle->stream_update,
                                                     dc_state);
                mutex_unlock(&dm->dc_lock);
        }
                        handle_cursor_update(plane, old_plane_state);
  
  cleanup:
 -      kfree(flip);
 -      kfree(full);
 +      kfree(bundle);
  }
  
  /*
  static void amdgpu_dm_crtc_copy_transient_flags(struct drm_crtc_state *crtc_state,
                                                struct dc_stream_state *stream_state)
  {
 -      stream_state->mode_changed =
 -              crtc_state->mode_changed || crtc_state->active_changed;
 +      stream_state->mode_changed = drm_atomic_crtc_needs_modeset(crtc_state);
  }
  
  static int amdgpu_dm_atomic_commit(struct drm_device *dev,
@@@ -5349,7 -5037,7 +5350,7 @@@ static void amdgpu_dm_atomic_commit_tai
                dc_state = dm_state->context;
        } else {
                /* No state changes, retain current state. */
 -              dc_state_temp = dc_create_state();
 +              dc_state_temp = dc_create_state(dm->dc);
                ASSERT(dc_state_temp);
                dc_state = dc_state_temp;
                dc_resource_state_copy_construct_current(dm->dc, dc_state);
                mutex_unlock(&dm->dc_lock);
        }
  
 +      /* Update freesync state before amdgpu_dm_handle_vrr_transition(). */
 +      for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
 +              dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
 +              pre_update_freesync_state_on_stream(dm, dm_new_crtc_state);
 +      }
 +
        for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state,
                        new_crtc_state, i) {
                /*
  
                dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
                dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
 +
 +              /* Handle vrr on->off / off->on transitions */
 +              amdgpu_dm_handle_vrr_transition(dm_old_crtc_state,
 +                                              dm_new_crtc_state);
 +
                modeset_needed = modeset_required(
                                new_crtc_state,
                                dm_new_crtc_state->stream,
  #endif
        }
  
 +      for_each_new_crtc_in_state(state, crtc, new_crtc_state, j)
 +              if (new_crtc_state->pageflip_flags & DRM_MODE_PAGE_FLIP_ASYNC)
 +                      wait_for_vblank = false;
 +
        /* update planes when needed per crtc*/
        for_each_new_crtc_in_state(state, crtc, new_crtc_state, j) {
                dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
  
                if (dm_new_crtc_state->stream)
                        amdgpu_dm_commit_planes(state, dc_state, dev,
 -                                              dm, crtc, &wait_for_vblank);
 +                                              dm, crtc, wait_for_vblank);
        }
  
  
@@@ -5757,9 -5430,11 +5758,11 @@@ static void get_freesync_config_for_crt
        struct amdgpu_dm_connector *aconnector =
                        to_amdgpu_dm_connector(new_con_state->base.connector);
        struct drm_display_mode *mode = &new_crtc_state->base.mode;
+       int vrefresh = drm_mode_vrefresh(mode);
  
        new_crtc_state->vrr_supported = new_con_state->freesync_capable &&
-               aconnector->min_vfreq <= drm_mode_vrefresh(mode);
+                                       vrefresh >= aconnector->min_vfreq &&
+                                       vrefresh <= aconnector->max_vfreq;
  
        if (new_crtc_state->vrr_supported) {
                new_crtc_state->stream->ignore_msa_timing_param = true;
@@@ -5986,9 -5661,6 +5989,9 @@@ skip_modeset
                update_stream_scaling_settings(
                        &new_crtc_state->mode, dm_new_conn_state, dm_new_crtc_state->stream);
  
 +      /* ABM settings */
 +      dm_new_crtc_state->abm_level = dm_new_conn_state->abm_level;
 +
        /*
         * Color management settings. We also update color properties
         * when a modeset is needed, to ensure it gets reprogrammed.
@@@ -6186,9 -5858,7 +6189,9 @@@ dm_determine_update_type_for_commit(str
        }
  
        for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
 -              struct dc_stream_update stream_update = { 0 };
 +              struct dc_stream_update stream_update;
 +
 +              memset(&stream_update, 0, sizeof(stream_update));
  
                new_dm_crtc_state = to_dm_crtc_state(new_crtc_state);
                old_dm_crtc_state = to_dm_crtc_state(old_crtc_state);
index 3b1e38e110eecbb3b5ec09673c1721adf518d846,ea18e9c2d8cea5c65582274a297d67b1d0fbb82d..3ef68a249f4d7d454ee6e9b508511a5362ae113e
@@@ -58,6 -58,7 +58,6 @@@
   ******************************************************************************/
  
  enum {
 -      LINK_RATE_REF_FREQ_IN_MHZ = 27,
        PEAK_FACTOR_X1000 = 1006,
        /*
        * Some receivers fail to train on first try and are good
@@@ -639,8 -640,7 +639,8 @@@ bool dc_link_detect(struct dc_link *lin
        bool same_dpcd = true;
        enum dc_connection_type new_connection_type = dc_connection_none;
        DC_LOGGER_INIT(link->ctx->logger);
 -      if (link->connector_signal == SIGNAL_TYPE_VIRTUAL)
 +
 +      if (dc_is_virtual_signal(link->connector_signal))
                return false;
  
        if (false == dc_link_detect_sink(link, &new_connection_type)) {
                                        same_dpcd = false;
                        }
                        /* Active dongle plug in without display or downstream unplug*/
 -                      if (link->type == dc_connection_active_dongle
 -                                      && link->dpcd_caps.sink_count.
 -                                      bits.SINK_COUNT == 0) {
 +                      if (link->type == dc_connection_active_dongle &&
 +                              link->dpcd_caps.sink_count.bits.SINK_COUNT == 0) {
                                if (prev_sink != NULL) {
                                        /* Downstream unplug */
                                        dc_sink_release(prev_sink);
@@@ -1171,6 -1172,8 +1171,6 @@@ static bool construct
                goto create_fail;
        }
  
 -
 -
        /* TODO: #DAL3 Implement id to str function.*/
        LINK_INFO("Connector[%d] description:"
                        "signal %d\n",
        link->link_enc = link->dc->res_pool->funcs->link_enc_create(
                                                                &enc_init_data);
  
 -      iflink->link_enc == NULL) {
 +      if (link->link_enc == NULL) {
                DC_ERROR("Failed to create link encoder!\n");
                goto link_enc_create_fail;
        }
@@@ -1396,18 -1399,9 +1396,18 @@@ static enum dc_status enable_link_dp
        /* get link settings for video mode timing */
        decide_link_settings(stream, &link_settings);
  
 +      /* If link settings are different than current and link already enabled
 +       * then need to disable before programming to new rate.
 +       */
 +      if (link->link_status.link_active &&
 +              (link->cur_link_settings.lane_count != link_settings.lane_count ||
 +               link->cur_link_settings.link_rate != link_settings.link_rate)) {
 +              dp_disable_link_phy(link, pipe_ctx->stream->signal);
 +      }
 +
        pipe_ctx->stream_res.pix_clk_params.requested_sym_clk =
                        link_settings.link_rate * LINK_RATE_REF_FREQ_IN_KHZ;
 -      state->dccg->funcs->update_clocks(state->dccg, state, false);
 +      state->clk_mgr->funcs->update_clocks(state->clk_mgr, state, false);
  
        dp_enable_link_phy(
                link,
@@@ -1472,14 -1466,14 +1472,14 @@@ static enum dc_status enable_link_dp_ms
        if (link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN)
                return DC_OK;
  
 +      /* clear payload table */
 +      dm_helpers_dp_mst_clear_payload_allocation_table(link->ctx, link);
 +
        /* to make sure the pending down rep can be processed
 -       * before clear payload table
 +       * before enabling the link
         */
        dm_helpers_dp_mst_poll_pending_down_reply(link->ctx, link);
  
 -      /* clear payload table */
 -      dm_helpers_dp_mst_clear_payload_allocation_table(link->ctx, link);
 -
        /* set the sink to MST mode before enabling the link */
        dp_enable_mst_on_sink(link, true);
  
@@@ -1988,7 -1982,7 +1988,7 @@@ static void enable_link_hdmi(struct pip
                        pipe_ctx->stream->signal,
                        stream->phy_pix_clk);
  
 -      if (pipe_ctx->stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
 +      if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
                dal_ddc_service_read_scdc_data(link->ddc);
  }
  
@@@ -2080,28 -2074,11 +2080,28 @@@ static void disable_link(struct dc_lin
        }
  }
  
 +static uint32_t get_timing_pixel_clock_100hz(const struct dc_crtc_timing *timing)
 +{
 +
 +      uint32_t pxl_clk = timing->pix_clk_100hz;
 +
 +      if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
 +              pxl_clk /= 2;
 +      else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422)
 +              pxl_clk = pxl_clk * 2 / 3;
 +
 +      if (timing->display_color_depth == COLOR_DEPTH_101010)
 +              pxl_clk = pxl_clk * 10 / 8;
 +      else if (timing->display_color_depth == COLOR_DEPTH_121212)
 +              pxl_clk = pxl_clk * 12 / 8;
 +
 +      return pxl_clk;
 +}
 +
  static bool dp_active_dongle_validate_timing(
                const struct dc_crtc_timing *timing,
                const struct dpcd_caps *dpcd_caps)
  {
 -      unsigned int required_pix_clk_100hz = timing->pix_clk_100hz;
        const struct dc_dongle_caps *dongle_caps = &dpcd_caps->dongle_caps;
  
        switch (dpcd_caps->dongle_type) {
                return false;
        }
  
 -
 -      /* Check Color Depth and Pixel Clock */
 -      if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
 -              required_pix_clk_100hz /= 2;
 -      else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422)
 -              required_pix_clk_100hz = required_pix_clk_100hz * 2 / 3;
 -
        switch (timing->display_color_depth) {
        case COLOR_DEPTH_666:
        case COLOR_DEPTH_888:
        case COLOR_DEPTH_101010:
                if (dongle_caps->dp_hdmi_max_bpc < 10)
                        return false;
 -              required_pix_clk_100hz = required_pix_clk_100hz * 10 / 8;
                break;
        case COLOR_DEPTH_121212:
                if (dongle_caps->dp_hdmi_max_bpc < 12)
                        return false;
 -              required_pix_clk_100hz = required_pix_clk_100hz * 12 / 8;
                break;
 -
        case COLOR_DEPTH_141414:
        case COLOR_DEPTH_161616:
        default:
                return false;
        }
  
 -      if (required_pix_clk_100hz > (dongle_caps->dp_hdmi_max_pixel_clk * 10))
 +      if (get_timing_pixel_clock_100hz(timing) > (dongle_caps->dp_hdmi_max_pixel_clk_in_khz * 10))
                return false;
  
        return true;
@@@ -2179,7 -2166,7 +2179,7 @@@ enum dc_status dc_link_validate_mode_ti
                return DC_OK;
  
        /* Passive Dongle */
 -      if (0 != max_pix_clk && timing->pix_clk_100hz > max_pix_clk)
 +      if (max_pix_clk != 0 && get_timing_pixel_clock_100hz(timing) > max_pix_clk)
                return DC_EXCEED_DONGLE_CAP;
  
        /* Active Dongle*/
@@@ -2297,13 -2284,14 +2297,13 @@@ void core_link_resume(struct dc_link *l
  
  static struct fixed31_32 get_pbn_per_slot(struct dc_stream_state *stream)
  {
 -      struct dc_link_settings *link_settings =
 -                      &stream->link->cur_link_settings;
 -      uint32_t link_rate_in_mbps =
 -                      link_settings->link_rate * LINK_RATE_REF_FREQ_IN_MHZ;
 -      struct fixed31_32 mbps = dc_fixpt_from_int(
 -                      link_rate_in_mbps * link_settings->lane_count);
 -
 -      return dc_fixpt_div_int(mbps, 54);
 +      struct fixed31_32 mbytes_per_sec;
 +      uint32_t link_rate_in_mbytes_per_sec = dc_link_bandwidth_kbps(stream->link, &stream->link->cur_link_settings);
 +      link_rate_in_mbytes_per_sec /= 8000; /* Kbits to MBytes */
 +
 +      mbytes_per_sec = dc_fixpt_from_int(link_rate_in_mbytes_per_sec);
 +
 +      return dc_fixpt_div_int(mbytes_per_sec, 54);
  }
  
  static int get_color_depth(enum dc_color_depth color_depth)
@@@ -2328,7 -2316,7 +2328,7 @@@ static struct fixed31_32 get_pbn_from_t
        uint32_t denominator;
  
        bpc = get_color_depth(pipe_ctx->stream_res.pix_clk_params.color_depth);
 -      kbps = pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz / 10 * bpc * 3;
 +      kbps = dc_bandwidth_in_kbps_from_timing(&pipe_ctx->stream->timing);
  
        /*
         * margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006
@@@ -2563,12 -2551,12 +2563,12 @@@ void core_link_enable_stream
                struct dc_state *state,
                struct pipe_ctx *pipe_ctx)
  {
 -      struct dc  *core_dc = pipe_ctx->stream->ctx->dc;
 +      struct dc *core_dc = pipe_ctx->stream->ctx->dc;
        struct dc_stream_state *stream = pipe_ctx->stream;
        enum dc_status status;
        DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
  
 -      if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL) {
 +      if (!dc_is_virtual_signal(pipe_ctx->stream->signal)) {
                stream->link->link_enc->funcs->setup(
                        stream->link->link_enc,
                        pipe_ctx->stream->signal);
                pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute(
                        pipe_ctx->stream_res.stream_enc,
                        &stream->timing,
 -                      stream->output_color_space);
 +                      stream->output_color_space,
 +                      stream->link->dpcd_caps.dprx_feature.bits.SST_SPLIT_SDP_CAP);
  
 -      if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
 +      if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal))
                pipe_ctx->stream_res.stream_enc->funcs->hdmi_set_stream_attribute(
                        pipe_ctx->stream_res.stream_enc,
                        &stream->timing,
  void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option)
  {
        struct dc  *core_dc = pipe_ctx->stream->ctx->dc;
+       struct dc_stream_state *stream = pipe_ctx->stream;
  
        core_dc->hwss.blank_stream(pipe_ctx);
  
        if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
                deallocate_mst_payload(pipe_ctx);
  
+       if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
+               dal_ddc_service_write_scdc_data(
+                       stream->link->ddc, 0,
+                       stream->timing.flags.LTE_340MCSC_SCRAMBLE);
        core_dc->hwss.disable_stream(pipe_ctx, option);
  
        disable_link(pipe_ctx->stream->link, pipe_ctx->stream->signal);
@@@ -2743,49 -2736,3 +2749,49 @@@ void dc_link_enable_hpd_filter(struct d
        }
  }
  
 +uint32_t dc_bandwidth_in_kbps_from_timing(
 +      const struct dc_crtc_timing *timing)
 +{
 +      uint32_t bits_per_channel = 0;
 +      uint32_t kbps;
 +
 +      switch (timing->display_color_depth) {
 +      case COLOR_DEPTH_666:
 +              bits_per_channel = 6;
 +              break;
 +      case COLOR_DEPTH_888:
 +              bits_per_channel = 8;
 +              break;
 +      case COLOR_DEPTH_101010:
 +              bits_per_channel = 10;
 +              break;
 +      case COLOR_DEPTH_121212:
 +              bits_per_channel = 12;
 +              break;
 +      case COLOR_DEPTH_141414:
 +              bits_per_channel = 14;
 +              break;
 +      case COLOR_DEPTH_161616:
 +              bits_per_channel = 16;
 +              break;
 +      default:
 +              break;
 +      }
 +
 +      ASSERT(bits_per_channel != 0);
 +
 +      kbps = timing->pix_clk_100hz / 10;
 +      kbps *= bits_per_channel;
 +
 +      if (timing->flags.Y_ONLY != 1) {
 +              /*Only YOnly make reduce bandwidth by 1/3 compares to RGB*/
 +              kbps *= 3;
 +              if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
 +                      kbps /= 2;
 +              else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422)
 +                      kbps = kbps * 2 / 3;
 +      }
 +
 +      return kbps;
 +
 +}
index 34f3782ff018dead05c1d84d2ceaf86438ddcf37,23b5b94a4939ac809c40448f1aa33e5d1500f93e..39a547084e90188fd06ad5aa8e6036884f0cccc5
@@@ -91,6 -91,12 +91,12 @@@ static void vega20_set_default_registry
         *   MP0CLK DS
         */
        data->registry_data.disallowed_features = 0xE0041C00;
+       /* ECC feature should be disabled on old SMUs */
+       smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetSmuVersion);
+       hwmgr->smu_version = smum_get_argument(hwmgr);
+       if (hwmgr->smu_version < 0x282100)
+               data->registry_data.disallowed_features |= FEATURE_ECC_MASK;
        data->registry_data.od_state_in_dc_support = 0;
        data->registry_data.thermal_support = 1;
        data->registry_data.skip_baco_hardware = 0;
@@@ -357,6 -363,7 +363,7 @@@ static void vega20_init_dpm_defaults(st
        data->smu_features[GNLD_DS_MP1CLK].smu_feature_id = FEATURE_DS_MP1CLK_BIT;
        data->smu_features[GNLD_DS_MP0CLK].smu_feature_id = FEATURE_DS_MP0CLK_BIT;
        data->smu_features[GNLD_XGMI].smu_feature_id = FEATURE_XGMI_BIT;
+       data->smu_features[GNLD_ECC].smu_feature_id = FEATURE_ECC_BIT;
  
        for (i = 0; i < GNLD_FEATURES_MAX; i++) {
                data->smu_features[i].smu_feature_bitmap =
@@@ -427,7 -434,6 +434,7 @@@ static int vega20_hwmgr_backend_init(st
        hwmgr->platform_descriptor.clockStep.memoryClock = 500;
  
        data->total_active_cus = adev->gfx.cu_info.number;
 +      data->is_custom_profile_set = false;
  
        return 0;
  }
@@@ -444,7 -450,6 +451,7 @@@ static int vega20_init_sclk_threshold(s
  
  static int vega20_setup_asic_task(struct pp_hwmgr *hwmgr)
  {
 +      struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
        int ret = 0;
  
        ret = vega20_init_sclk_threshold(hwmgr);
                        "Failed to init sclk threshold!",
                        return ret);
  
 -      return 0;
 +      if (adev->in_baco_reset) {
 +              adev->in_baco_reset = 0;
 +
 +              ret = vega20_baco_apply_vdci_flush_workaround(hwmgr);
 +              if (ret)
 +                      pr_err("Failed to apply vega20 baco workaround!\n");
 +      }
 +
 +      return ret;
  }
  
  /*
@@@ -3030,7 -3027,8 +3037,8 @@@ static int vega20_get_ppfeature_status(
                                "FCLK_DS",
                                "MP1CLK_DS",
                                "MP0CLK_DS",
-                               "XGMI"};
+                               "XGMI",
+                               "ECC"};
        static const char *output_title[] = {
                                "FEATURES",
                                "BITMASK",
@@@ -3472,6 -3470,7 +3480,7 @@@ static int vega20_apply_clocks_adjust_r
        struct vega20_single_dpm_table *dpm_table;
        bool vblank_too_short = false;
        bool disable_mclk_switching;
+       bool disable_fclk_switching;
        uint32_t i, latency;
  
        disable_mclk_switching = ((1 < hwmgr->display_config->num_display) &&
        if (hwmgr->display_config->nb_pstate_switch_disable)
                dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
  
+       if ((disable_mclk_switching &&
+           (dpm_table->dpm_state.hard_min_level == dpm_table->dpm_levels[dpm_table->count - 1].value)) ||
+            hwmgr->display_config->min_mem_set_clock / 100 >= dpm_table->dpm_levels[dpm_table->count - 1].value)
+               disable_fclk_switching = true;
+       else
+               disable_fclk_switching = false;
        /* fclk */
        dpm_table = &(data->dpm_table.fclk_table);
        dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
        dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT;
        dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
        dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT;
-       if (hwmgr->display_config->nb_pstate_switch_disable)
+       if (hwmgr->display_config->nb_pstate_switch_disable || disable_fclk_switching)
                dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
  
        /* vclk */
@@@ -3820,19 -3826,16 +3836,19 @@@ static int vega20_set_power_profile_mod
  {
        DpmActivityMonitorCoeffInt_t activity_monitor;
        int workload_type, result = 0;
 +      uint32_t power_profile_mode = input[size];
  
 -      hwmgr->power_profile_mode = input[size];
 -
 -      if (hwmgr->power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
 -              pr_err("Invalid power profile mode %d\n", hwmgr->power_profile_mode);
 +      if (power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
 +              pr_err("Invalid power profile mode %d\n", power_profile_mode);
                return -EINVAL;
        }
  
 -      if (hwmgr->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
 -              if (size < 10)
 +      if (power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
 +              struct vega20_hwmgr *data =
 +                      (struct vega20_hwmgr *)(hwmgr->backend);
 +              if (size == 0 && !data->is_custom_profile_set)
 +                      return -EINVAL;
 +              if (size < 10 && size != 0)
                        return -EINVAL;
  
                result = vega20_get_activity_monitor_coeff(hwmgr,
                                "[SetPowerProfile] Failed to get activity monitor!",
                                return result);
  
 +              /* If size==0, then we want to apply the already-configured
 +               * CUSTOM profile again. Just apply it, since we checked its
 +               * validity above
 +               */
 +              if (size == 0)
 +                      goto out;
 +
                switch (input[0]) {
                case 0: /* Gfxclk */
                        activity_monitor.Gfx_FPS = input[1];
                result = vega20_set_activity_monitor_coeff(hwmgr,
                                (uint8_t *)(&activity_monitor),
                                WORKLOAD_PPLIB_CUSTOM_BIT);
 +              data->is_custom_profile_set = true;
                PP_ASSERT_WITH_CODE(!result,
                                "[SetPowerProfile] Failed to set activity monitor!",
                                return result);
        }
  
 +out:
        /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
        workload_type =
 -              conv_power_profile_to_pplib_workload(hwmgr->power_profile_mode);
 +              conv_power_profile_to_pplib_workload(power_profile_mode);
        smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetWorkloadMask,
                                                1 << workload_type);
  
 +      hwmgr->power_profile_mode = power_profile_mode;
 +
        return 0;
  }
  
index f37a28afd574c7d225f667ba27297afc904b24f6,ac2a3118a0ae779224be91fd750dda2319027a64..2c3125f82b24acf2f6e6c7698694e88f3ee8a640
@@@ -80,6 -80,7 +80,7 @@@ enum 
        GNLD_DS_MP1CLK,
        GNLD_DS_MP0CLK,
        GNLD_XGMI,
+       GNLD_ECC,
  
        GNLD_FEATURES_MAX
  };
@@@ -530,8 -531,6 +531,8 @@@ struct vega20_hwmgr 
        bool                           pcie_parameters_override;
        uint32_t                       pcie_gen_level1;
        uint32_t                       pcie_width_level1;
 +
 +      bool                           is_custom_profile_set;
  };
  
  #define VEGA20_DPM2_NEAR_TDP_DEC                      10
index 86efd2da37f9cc50d890444c2519df9414019d4d,fbb76332cc9f149c0cc037a6d35a5ed9c63d1baa..2e0cb4246cbda6c3a7a1e12506c55061449aea75
@@@ -495,7 -495,7 +495,7 @@@ mode_fixup(struct drm_atomic_state *sta
  static enum drm_mode_status mode_valid_path(struct drm_connector *connector,
                                            struct drm_encoder *encoder,
                                            struct drm_crtc *crtc,
 -                                          struct drm_display_mode *mode)
 +                                          const struct drm_display_mode *mode)
  {
        enum drm_mode_status ret;
  
@@@ -534,7 -534,7 +534,7 @@@ mode_valid(struct drm_atomic_state *sta
                struct drm_crtc *crtc = conn_state->crtc;
                struct drm_crtc_state *crtc_state;
                enum drm_mode_status mode_status;
 -              struct drm_display_mode *mode;
 +              const struct drm_display_mode *mode;
  
                if (!crtc || !encoder)
                        continue;
@@@ -1034,7 -1034,7 +1034,7 @@@ disable_outputs(struct drm_device *dev
                        funcs->atomic_disable(crtc, old_crtc_state);
                else if (funcs->disable)
                        funcs->disable(crtc);
-               else
+               else if (funcs->dpms)
                        funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
  
                if (!(dev->irq_enabled && dev->num_crtcs))
@@@ -1277,10 -1277,9 +1277,9 @@@ void drm_atomic_helper_commit_modeset_e
                if (new_crtc_state->enable) {
                        DRM_DEBUG_ATOMIC("enabling [CRTC:%d:%s]\n",
                                         crtc->base.id, crtc->name);
                        if (funcs->atomic_enable)
                                funcs->atomic_enable(crtc, old_crtc_state);
-                       else
+                       else if (funcs->commit)
                                funcs->commit(crtc);
                }
        }
@@@ -1752,7 -1751,7 +1751,7 @@@ int drm_atomic_helper_commit(struct drm
         *
         * NOTE: Commit work has multiple phases, first hardware commit, then
         * cleanup. We want them to overlap, hence need system_unbound_wq to
 -       * make sure work items don't artifically stall on each another.
 +       * make sure work items don't artificially stall on each another.
         */
  
        drm_atomic_state_get(state);
@@@ -1786,7 -1785,7 +1785,7 @@@ EXPORT_SYMBOL(drm_atomic_helper_commit)
   *
   * Asynchronous workers need to have sufficient parallelism to be able to run
   * different atomic commits on different CRTCs in parallel. The simplest way to
 - * achive this is by running them on the &system_unbound_wq work queue. Note
 + * achieve this is by running them on the &system_unbound_wq work queue. Note
   * that drivers are not required to split up atomic commits and run an
   * individual commit in parallel - userspace is supposed to do that if it cares.
   * But it might be beneficial to do that for modesets, since those necessarily
@@@ -2261,21 -2260,10 +2260,21 @@@ EXPORT_SYMBOL(drm_atomic_helper_commit_
  int drm_atomic_helper_prepare_planes(struct drm_device *dev,
                                     struct drm_atomic_state *state)
  {
 +      struct drm_connector *connector;
 +      struct drm_connector_state *new_conn_state;
        struct drm_plane *plane;
        struct drm_plane_state *new_plane_state;
        int ret, i, j;
  
 +      for_each_new_connector_in_state(state, connector, new_conn_state, i) {
 +              if (!new_conn_state->writeback_job)
 +                      continue;
 +
 +              ret = drm_writeback_prepare_job(new_conn_state->writeback_job);
 +              if (ret < 0)
 +                      return ret;
 +      }
 +
        for_each_new_plane_in_state(state, plane, new_plane_state, i) {
                const struct drm_plane_helper_funcs *funcs;
  
index 50d849d1bc6ef15708de599144b071ddbe5fd7c8,05bbc2b622fc1094a2a8f85ce060d0805eae0f7e..e87799e3e7ffb497c7725c77bff89ea43d9b3f7e
@@@ -286,138 -286,6 +286,138 @@@ void drm_minor_release(struct drm_mino
   * Note that the lifetime rules for &drm_device instance has still a lot of
   * historical baggage. Hence use the reference counting provided by
   * drm_dev_get() and drm_dev_put() only carefully.
 + *
 + * Display driver example
 + * ~~~~~~~~~~~~~~~~~~~~~~
 + *
 + * The following example shows a typical structure of a DRM display driver.
 + * The example focus on the probe() function and the other functions that is
 + * almost always present and serves as a demonstration of devm_drm_dev_init()
 + * usage with its accompanying drm_driver->release callback.
 + *
 + * .. code-block:: c
 + *
 + *    struct driver_device {
 + *            struct drm_device drm;
 + *            void *userspace_facing;
 + *            struct clk *pclk;
 + *    };
 + *
 + *    static void driver_drm_release(struct drm_device *drm)
 + *    {
 + *            struct driver_device *priv = container_of(...);
 + *
 + *            drm_mode_config_cleanup(drm);
 + *            drm_dev_fini(drm);
 + *            kfree(priv->userspace_facing);
 + *            kfree(priv);
 + *    }
 + *
 + *    static struct drm_driver driver_drm_driver = {
 + *            [...]
 + *            .release = driver_drm_release,
 + *    };
 + *
 + *    static int driver_probe(struct platform_device *pdev)
 + *    {
 + *            struct driver_device *priv;
 + *            struct drm_device *drm;
 + *            int ret;
 + *
 + *            [
 + *              devm_kzalloc() can't be used here because the drm_device
 + *              lifetime can exceed the device lifetime if driver unbind
 + *              happens when userspace still has open file descriptors.
 + *            ]
 + *            priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 + *            if (!priv)
 + *                    return -ENOMEM;
 + *
 + *            drm = &priv->drm;
 + *
 + *            ret = devm_drm_dev_init(&pdev->dev, drm, &driver_drm_driver);
 + *            if (ret) {
 + *                    kfree(drm);
 + *                    return ret;
 + *            }
 + *
 + *            drm_mode_config_init(drm);
 + *
 + *            priv->userspace_facing = kzalloc(..., GFP_KERNEL);
 + *            if (!priv->userspace_facing)
 + *                    return -ENOMEM;
 + *
 + *            priv->pclk = devm_clk_get(dev, "PCLK");
 + *            if (IS_ERR(priv->pclk))
 + *                    return PTR_ERR(priv->pclk);
 + *
 + *            [ Further setup, display pipeline etc ]
 + *
 + *            platform_set_drvdata(pdev, drm);
 + *
 + *            drm_mode_config_reset(drm);
 + *
 + *            ret = drm_dev_register(drm);
 + *            if (ret)
 + *                    return ret;
 + *
 + *            drm_fbdev_generic_setup(drm, 32);
 + *
 + *            return 0;
 + *    }
 + *
 + *    [ This function is called before the devm_ resources are released ]
 + *    static int driver_remove(struct platform_device *pdev)
 + *    {
 + *            struct drm_device *drm = platform_get_drvdata(pdev);
 + *
 + *            drm_dev_unregister(drm);
 + *            drm_atomic_helper_shutdown(drm)
 + *
 + *            return 0;
 + *    }
 + *
 + *    [ This function is called on kernel restart and shutdown ]
 + *    static void driver_shutdown(struct platform_device *pdev)
 + *    {
 + *            drm_atomic_helper_shutdown(platform_get_drvdata(pdev));
 + *    }
 + *
 + *    static int __maybe_unused driver_pm_suspend(struct device *dev)
 + *    {
 + *            return drm_mode_config_helper_suspend(dev_get_drvdata(dev));
 + *    }
 + *
 + *    static int __maybe_unused driver_pm_resume(struct device *dev)
 + *    {
 + *            drm_mode_config_helper_resume(dev_get_drvdata(dev));
 + *
 + *            return 0;
 + *    }
 + *
 + *    static const struct dev_pm_ops driver_pm_ops = {
 + *            SET_SYSTEM_SLEEP_PM_OPS(driver_pm_suspend, driver_pm_resume)
 + *    };
 + *
 + *    static struct platform_driver driver_driver = {
 + *            .driver = {
 + *                    [...]
 + *                    .pm = &driver_pm_ops,
 + *            },
 + *            .probe = driver_probe,
 + *            .remove = driver_remove,
 + *            .shutdown = driver_shutdown,
 + *    };
 + *    module_platform_driver(driver_driver);
 + *
 + * Drivers that want to support device unplugging (USB, DT overlay unload) should
 + * use drm_dev_unplug() instead of drm_dev_unregister(). The driver must protect
 + * regions that is accessing device resources to prevent use after they're
 + * released. This is done using drm_dev_enter() and drm_dev_exit(). There is one
 + * shortcoming however, drm_dev_unplug() marks the drm_device as unplugged before
 + * drm_atomic_helper_shutdown() is called. This means that if the disable code
 + * paths are protected, they will not run on regular driver module unload,
 + * possibily leaving the hardware enabled.
   */
  
  /**
@@@ -508,6 -376,7 +508,7 @@@ void drm_dev_unplug(struct drm_device *
        synchronize_srcu(&drm_unplug_srcu);
  
        drm_dev_unregister(dev);
+       drm_dev_put(dev);
  }
  EXPORT_SYMBOL(drm_dev_unplug);
  
@@@ -583,31 -452,6 +584,31 @@@ static void drm_fs_inode_free(struct in
        }
  }
  
 +/**
 + * DOC: component helper usage recommendations
 + *
 + * DRM drivers that drive hardware where a logical device consists of a pile of
 + * independent hardware blocks are recommended to use the :ref:`component helper
 + * library<component>`. For consistency and better options for code reuse the
 + * following guidelines apply:
 + *
 + *  - The entire device initialization procedure should be run from the
 + *    &component_master_ops.master_bind callback, starting with drm_dev_init(),
 + *    then binding all components with component_bind_all() and finishing with
 + *    drm_dev_register().
 + *
 + *  - The opaque pointer passed to all components through component_bind_all()
 + *    should point at &struct drm_device of the device instance, not some driver
 + *    specific private structure.
 + *
 + *  - The component helper fills the niche where further standardization of
 + *    interfaces is not practical. When there already is, or will be, a
 + *    standardized interface like &drm_bridge or &drm_panel, providing its own
 + *    functions to find such components at driver load time, like
 + *    drm_of_find_panel_or_bridge(), then the component helper should not be
 + *    used.
 + */
 +
  /**
   * drm_dev_init - Initialise new DRM device
   * @dev: DRM device
@@@ -653,7 -497,7 +654,7 @@@ int drm_dev_init(struct drm_device *dev
        BUG_ON(!parent);
  
        kref_init(&dev->ref);
 -      dev->dev = parent;
 +      dev->dev = get_device(parent);
        dev->driver = driver;
  
        /* no per-device feature limits by default */
@@@ -723,7 -567,6 +724,7 @@@ err_minors
        drm_minor_free(dev, DRM_MINOR_RENDER);
        drm_fs_inode_free(dev->anon_inode);
  err_free:
 +      put_device(dev->dev);
        mutex_destroy(&dev->master_mutex);
        mutex_destroy(&dev->ctxlist_mutex);
        mutex_destroy(&dev->clientlist_mutex);
  }
  EXPORT_SYMBOL(drm_dev_init);
  
 +static void devm_drm_dev_init_release(void *data)
 +{
 +      drm_dev_put(data);
 +}
 +
 +/**
 + * devm_drm_dev_init - Resource managed drm_dev_init()
 + * @parent: Parent device object
 + * @dev: DRM device
 + * @driver: DRM driver
 + *
 + * Managed drm_dev_init(). The DRM device initialized with this function is
 + * automatically put on driver detach using drm_dev_put(). You must supply a
 + * &drm_driver.release callback to control the finalization explicitly.
 + *
 + * RETURNS:
 + * 0 on success, or error code on failure.
 + */
 +int devm_drm_dev_init(struct device *parent,
 +                    struct drm_device *dev,
 +                    struct drm_driver *driver)
 +{
 +      int ret;
 +
 +      if (WARN_ON(!parent || !driver->release))
 +              return -EINVAL;
 +
 +      ret = drm_dev_init(dev, driver, parent);
 +      if (ret)
 +              return ret;
 +
 +      ret = devm_add_action(parent, devm_drm_dev_init_release, dev);
 +      if (ret)
 +              devm_drm_dev_init_release(dev);
 +
 +      return ret;
 +}
 +EXPORT_SYMBOL(devm_drm_dev_init);
 +
  /**
   * drm_dev_fini - Finalize a dead DRM device
   * @dev: DRM device
@@@ -798,8 -602,6 +799,8 @@@ void drm_dev_fini(struct drm_device *de
        drm_minor_free(dev, DRM_MINOR_PRIMARY);
        drm_minor_free(dev, DRM_MINOR_RENDER);
  
 +      put_device(dev->dev);
 +
        mutex_destroy(&dev->master_mutex);
        mutex_destroy(&dev->ctxlist_mutex);
        mutex_destroy(&dev->clientlist_mutex);
index 84791dd4a90d3838801388043687001d5bb86abc,af2ab640cadbb05105325a0de2b31ae5f5c70ccf..d1ce7bd04cad293af8e7ace401345d4cd9da2e89
@@@ -639,19 -639,20 +639,19 @@@ static struct sysrq_key_op sysrq_drm_fb
  static void dpms_legacy(struct drm_fb_helper *fb_helper, int dpms_mode)
  {
        struct drm_device *dev = fb_helper->dev;
 -      struct drm_crtc *crtc;
        struct drm_connector *connector;
 +      struct drm_mode_set *modeset;
        int i, j;
  
        drm_modeset_lock_all(dev);
        for (i = 0; i < fb_helper->crtc_count; i++) {
 -              crtc = fb_helper->crtc_info[i].mode_set.crtc;
 +              modeset = &fb_helper->crtc_info[i].mode_set;
  
 -              if (!crtc->enabled)
 +              if (!modeset->crtc->enabled)
                        continue;
  
 -              /* Walk the connectors & encoders on this fb turning them on/off */
 -              drm_fb_helper_for_each_connector(fb_helper, j) {
 -                      connector = fb_helper->connector_info[j]->connector;
 +              for (j = 0; j < modeset->num_connectors; j++) {
 +                      connector = modeset->connectors[j];
                        connector->funcs->dpms(connector, dpms_mode);
                        drm_object_property_set_value(&connector->base,
                                dev->mode_config.dpms_property, dpms_mode);
@@@ -933,7 -934,6 +933,7 @@@ struct fb_info *drm_fb_helper_alloc_fbi
        }
  
        fb_helper->fbdev = info;
 +      info->skip_vt_switch = true;
  
        return info;
  
@@@ -1873,6 -1873,7 +1873,6 @@@ static int drm_fb_helper_single_fb_prob
        int crtc_count = 0;
        int i;
        struct drm_fb_helper_surface_size sizes;
 -      int gamma_size = 0;
        int best_depth = 0;
  
        memset(&sizes, 0, sizeof(struct drm_fb_helper_surface_size));
        if (preferred_bpp != sizes.surface_bpp)
                sizes.surface_depth = sizes.surface_bpp = preferred_bpp;
  
 -      /* first up get a count of crtcs now in use and new min/maxes width/heights */
        drm_fb_helper_for_each_connector(fb_helper, i) {
                struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i];
                struct drm_cmdline_mode *cmdline_mode;
                                best_depth = fmt->depth;
                }
        }
-       if (sizes.surface_depth != best_depth) {
+       if (sizes.surface_depth != best_depth && best_depth) {
                DRM_INFO("requested bpp %d, scaled depth down to %d",
                         sizes.surface_bpp, best_depth);
                sizes.surface_depth = best_depth;
        }
  
 +      /* first up get a count of crtcs now in use and new min/maxes width/heights */
        crtc_count = 0;
        for (i = 0; i < fb_helper->crtc_count; i++) {
                struct drm_display_mode *desired_mode;
                x = fb_helper->crtc_info[i].x;
                y = fb_helper->crtc_info[i].y;
  
 -              if (gamma_size == 0)
 -                      gamma_size = fb_helper->crtc_info[i].mode_set.crtc->gamma_size;
 -
                sizes.surface_width  = max_t(u32, desired_mode->hdisplay + x, sizes.surface_width);
                sizes.surface_height = max_t(u32, desired_mode->vdisplay + y, sizes.surface_height);
  
        return 0;
  }
  
 -/**
 - * drm_fb_helper_fill_fix - initializes fixed fbdev information
 - * @info: fbdev registered by the helper
 - * @pitch: desired pitch
 - * @depth: desired depth
 - *
 - * Helper to fill in the fixed fbdev information useful for a non-accelerated
 - * fbdev emulations. Drivers which support acceleration methods which impose
 - * additional constraints need to set up their own limits.
 - *
 - * Drivers should call this (or their equivalent setup code) from their
 - * &drm_fb_helper_funcs.fb_probe callback.
 - */
 -void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
 -                          uint32_t depth)
 +static void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
 +                                 uint32_t depth)
  {
        info->fix.type = FB_TYPE_PACKED_PIXELS;
        info->fix.visual = depth == 8 ? FB_VISUAL_PSEUDOCOLOR :
  
        info->fix.line_length = pitch;
  }
 -EXPORT_SYMBOL(drm_fb_helper_fill_fix);
  
 -/**
 - * drm_fb_helper_fill_var - initalizes variable fbdev information
 - * @info: fbdev instance to set up
 - * @fb_helper: fb helper instance to use as template
 - * @fb_width: desired fb width
 - * @fb_height: desired fb height
 - *
 - * Sets up the variable fbdev metainformation from the given fb helper instance
 - * and the drm framebuffer allocated in &drm_fb_helper.fb.
 - *
 - * Drivers should call this (or their equivalent setup code) from their
 - * &drm_fb_helper_funcs.fb_probe callback after having allocated the fbdev
 - * backing storage framebuffer.
 - */
 -void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper,
 -                          uint32_t fb_width, uint32_t fb_height)
 +static void drm_fb_helper_fill_var(struct fb_info *info,
 +                                 struct drm_fb_helper *fb_helper,
 +                                 uint32_t fb_width, uint32_t fb_height)
  {
        struct drm_framebuffer *fb = fb_helper->fb;
  
        info->var.xres = fb_width;
        info->var.yres = fb_height;
  }
 -EXPORT_SYMBOL(drm_fb_helper_fill_var);
 +
 +/**
 + * drm_fb_helper_fill_info - initializes fbdev information
 + * @info: fbdev instance to set up
 + * @fb_helper: fb helper instance to use as template
 + * @sizes: describes fbdev size and scanout surface size
 + *
 + * Sets up the variable and fixed fbdev metainformation from the given fb helper
 + * instance and the drm framebuffer allocated in &drm_fb_helper.fb.
 + *
 + * Drivers should call this (or their equivalent setup code) from their
 + * &drm_fb_helper_funcs.fb_probe callback after having allocated the fbdev
 + * backing storage framebuffer.
 + */
 +void drm_fb_helper_fill_info(struct fb_info *info,
 +                           struct drm_fb_helper *fb_helper,
 +                           struct drm_fb_helper_surface_size *sizes)
 +{
 +      struct drm_framebuffer *fb = fb_helper->fb;
 +
 +      drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth);
 +      drm_fb_helper_fill_var(info, fb_helper,
 +                             sizes->fb_width, sizes->fb_height);
 +
 +      info->par = fb_helper;
 +      snprintf(info->fix.id, sizeof(info->fix.id), "%sdrmfb",
 +               fb_helper->dev->driver->name);
 +
 +}
 +EXPORT_SYMBOL(drm_fb_helper_fill_info);
  
  static int drm_fb_helper_probe_connector_modes(struct drm_fb_helper *fb_helper,
                                                uint32_t maxX,
@@@ -2778,8 -2780,9 +2778,8 @@@ __drm_fb_helper_initial_config_and_unlo
   *
   * This function will call down into the &drm_fb_helper_funcs.fb_probe callback
   * to let the driver allocate and initialize the fbdev info structure and the
 - * drm framebuffer used to back the fbdev. drm_fb_helper_fill_var() and
 - * drm_fb_helper_fill_fix() are provided as helpers to setup simple default
 - * values for the fbdev info structure.
 + * drm framebuffer used to back the fbdev. drm_fb_helper_fill_info() is provided
 + * as a helper to setup simple default values for the fbdev info structure.
   *
   * HANG DEBUGGING:
   *
@@@ -3021,8 -3024,7 +3021,8 @@@ static int drm_fbdev_fb_open(struct fb_
  {
        struct drm_fb_helper *fb_helper = info->par;
  
 -      if (!try_module_get(fb_helper->dev->driver->fops->owner))
 +      /* No need to take a ref for fbcon because it unbinds on unregister */
 +      if (user && !try_module_get(fb_helper->dev->driver->fops->owner))
                return -ENODEV;
  
        return 0;
@@@ -3032,8 -3034,7 +3032,8 @@@ static int drm_fbdev_fb_release(struct 
  {
        struct drm_fb_helper *fb_helper = info->par;
  
 -      module_put(fb_helper->dev->driver->fops->owner);
 +      if (user)
 +              module_put(fb_helper->dev->driver->fops->owner);
  
        return 0;
  }
@@@ -3148,6 -3149,7 +3148,6 @@@ int drm_fb_helper_generic_probe(struct 
        if (IS_ERR(fbi))
                return PTR_ERR(fbi);
  
 -      fbi->par = fb_helper;
        fbi->fbops = &drm_fbdev_fb_ops;
        fbi->screen_size = fb->height * fb->pitches[0];
        fbi->fix.smem_len = fbi->screen_size;
                fbi->fix.smem_start =
                        page_to_phys(virt_to_page(fbi->screen_buffer));
  #endif
 -      strcpy(fbi->fix.id, "DRM emulated");
 -
 -      drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->format->depth);
 -      drm_fb_helper_fill_var(fbi, fb_helper, sizes->fb_width, sizes->fb_height);
 +      drm_fb_helper_fill_info(fbi, fb_helper, sizes);
  
        if (fb->funcs->dirty) {
                struct fb_ops *fbops;
@@@ -3312,6 -3317,8 +3312,6 @@@ int drm_fbdev_generic_setup(struct drm_
                return ret;
        }
  
 -      drm_client_add(&fb_helper->client);
 -
        if (!preferred_bpp)
                preferred_bpp = dev->mode_config.preferred_depth;
        if (!preferred_bpp)
        if (ret)
                DRM_DEV_DEBUG(dev->dev, "client hotplug ret=%d\n", ret);
  
 +      drm_client_add(&fb_helper->client);
 +
        return 0;
  }
  EXPORT_SYMBOL(drm_fbdev_generic_setup);
index cf4a1ecf6853659f6c231b07e1d5149c5f480555,3592d04c33b283cac0abd2f432ce313194d2b606..d8d59695619eb4d954b47715035a659fcea95f31
@@@ -391,12 -391,12 +391,12 @@@ struct cmd_info 
  #define F_POST_HANDLE (1<<2)
        u32 flag;
  
 -#define R_RCS (1 << RCS)
 -#define R_VCS1  (1 << VCS)
 -#define R_VCS2  (1 << VCS2)
 +#define R_RCS BIT(RCS0)
 +#define R_VCS1  BIT(VCS0)
 +#define R_VCS2  BIT(VCS1)
  #define R_VCS (R_VCS1 | R_VCS2)
 -#define R_BCS (1 << BCS)
 -#define R_VECS        (1 << VECS)
 +#define R_BCS BIT(BCS0)
 +#define R_VECS        BIT(VECS0)
  #define R_ALL (R_RCS | R_VCS | R_BCS | R_VECS)
        /* rings that support this cmd: BLT/RCS/VCS/VECS */
        u16 rings;
@@@ -558,7 -558,7 +558,7 @@@ static const struct decode_info decode_
  };
  
  static const struct decode_info *ring_decode_info[I915_NUM_ENGINES][8] = {
 -      [RCS] = {
 +      [RCS0] = {
                &decode_info_mi,
                NULL,
                NULL,
                NULL,
        },
  
 -      [VCS] = {
 +      [VCS0] = {
                &decode_info_mi,
                NULL,
                NULL,
                NULL,
        },
  
 -      [BCS] = {
 +      [BCS0] = {
                &decode_info_mi,
                NULL,
                &decode_info_2d,
                NULL,
        },
  
 -      [VECS] = {
 +      [VECS0] = {
                &decode_info_mi,
                NULL,
                NULL,
                NULL,
        },
  
 -      [VCS2] = {
 +      [VCS1] = {
                &decode_info_mi,
                NULL,
                NULL,
@@@ -631,7 -631,8 +631,7 @@@ static inline const struct cmd_info *fi
        struct cmd_entry *e;
  
        hash_for_each_possible(gvt->cmd_table, e, hlist, opcode) {
 -              if ((opcode == e->info->opcode) &&
 -                              (e->info->rings & (1 << ring_id)))
 +              if (opcode == e->info->opcode && e->info->rings & BIT(ring_id))
                        return e->info;
        }
        return NULL;
@@@ -942,12 -943,15 +942,12 @@@ static int cmd_handler_lri(struct parse
        struct intel_gvt *gvt = s->vgpu->gvt;
  
        for (i = 1; i < cmd_len; i += 2) {
 -              if (IS_BROADWELL(gvt->dev_priv) &&
 -                              (s->ring_id != RCS)) {
 -                      if (s->ring_id == BCS &&
 -                                      cmd_reg(s, i) ==
 -                                      i915_mmio_reg_offset(DERRMR))
 +              if (IS_BROADWELL(gvt->dev_priv) && s->ring_id != RCS0) {
 +                      if (s->ring_id == BCS0 &&
 +                          cmd_reg(s, i) == i915_mmio_reg_offset(DERRMR))
                                ret |= 0;
                        else
 -                              ret |= (cmd_reg_inhibit(s, i)) ?
 -                                      -EBADRQC : 0;
 +                              ret |= cmd_reg_inhibit(s, i) ? -EBADRQC : 0;
                }
                if (ret)
                        break;
@@@ -1043,27 -1047,27 +1043,27 @@@ struct cmd_interrupt_event 
  };
  
  static struct cmd_interrupt_event cmd_interrupt_events[] = {
 -      [RCS] = {
 +      [RCS0] = {
                .pipe_control_notify = RCS_PIPE_CONTROL,
                .mi_flush_dw = INTEL_GVT_EVENT_RESERVED,
                .mi_user_interrupt = RCS_MI_USER_INTERRUPT,
        },
 -      [BCS] = {
 +      [BCS0] = {
                .pipe_control_notify = INTEL_GVT_EVENT_RESERVED,
                .mi_flush_dw = BCS_MI_FLUSH_DW,
                .mi_user_interrupt = BCS_MI_USER_INTERRUPT,
        },
 -      [VCS] = {
 +      [VCS0] = {
                .pipe_control_notify = INTEL_GVT_EVENT_RESERVED,
                .mi_flush_dw = VCS_MI_FLUSH_DW,
                .mi_user_interrupt = VCS_MI_USER_INTERRUPT,
        },
 -      [VCS2] = {
 +      [VCS1] = {
                .pipe_control_notify = INTEL_GVT_EVENT_RESERVED,
                .mi_flush_dw = VCS2_MI_FLUSH_DW,
                .mi_user_interrupt = VCS2_MI_USER_INTERRUPT,
        },
 -      [VECS] = {
 +      [VECS0] = {
                .pipe_control_notify = INTEL_GVT_EVENT_RESERVED,
                .mi_flush_dw = VECS_MI_FLUSH_DW,
                .mi_user_interrupt = VECS_MI_USER_INTERRUPT,
@@@ -1437,7 -1441,7 +1437,7 @@@ static inline int cmd_address_audit(str
        }
  
        if (index_mode) {
-               if (guest_gma >= I915_GTT_PAGE_SIZE / sizeof(u64)) {
+               if (guest_gma >= I915_GTT_PAGE_SIZE) {
                        ret = -EFAULT;
                        goto err;
                }
index f27edf17b4ab6ce089db97fa28ec44894f5ed7bc,69a9a1b2ea4ac44ba7d8f6530f99f59a9958076f..4e1e425189ba971e58098f95dada623cd0997a85
@@@ -153,7 -153,7 +153,7 @@@ static struct drm_i915_gem_object *vgpu
        struct drm_i915_private *dev_priv = to_i915(dev);
        struct drm_i915_gem_object *obj;
  
 -      obj = i915_gem_object_alloc(dev_priv);
 +      obj = i915_gem_object_alloc();
        if (obj == NULL)
                return NULL;
  
@@@ -209,7 -209,7 +209,7 @@@ static int vgpu_get_plane_info(struct d
        struct drm_i915_private *dev_priv = to_i915(dev);
        struct intel_vgpu_primary_plane_format p;
        struct intel_vgpu_cursor_plane_format c;
-       int ret;
+       int ret, tile_height = 1;
  
        if (plane_id == DRM_PLANE_TYPE_PRIMARY) {
                ret = intel_vgpu_decode_primary_plane(vgpu, &p);
                        break;
                case PLANE_CTL_TILED_X:
                        info->drm_format_mod = I915_FORMAT_MOD_X_TILED;
+                       tile_height = 8;
                        break;
                case PLANE_CTL_TILED_Y:
                        info->drm_format_mod = I915_FORMAT_MOD_Y_TILED;
+                       tile_height = 32;
                        break;
                case PLANE_CTL_TILED_YF:
                        info->drm_format_mod = I915_FORMAT_MOD_Yf_TILED;
+                       tile_height = 32;
                        break;
                default:
                        gvt_vgpu_err("invalid tiling mode: %x\n", p.tiled);
                }
-               info->size = (((p.stride * p.height * p.bpp) / 8) +
-                             (PAGE_SIZE - 1)) >> PAGE_SHIFT;
        } else if (plane_id == DRM_PLANE_TYPE_CURSOR) {
                ret = intel_vgpu_decode_cursor_plane(vgpu, &c);
                if (ret)
                        info->x_hot = UINT_MAX;
                        info->y_hot = UINT_MAX;
                }
-               info->size = (((info->stride * c.height * c.bpp) / 8)
-                               + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
        } else {
                gvt_vgpu_err("invalid plane id:%d\n", plane_id);
                return -EINVAL;
        }
  
+       info->size = (info->stride * roundup(info->height, tile_height)
+                     + PAGE_SIZE - 1) >> PAGE_SHIFT;
        if (info->size == 0) {
                gvt_vgpu_err("fb size is zero\n");
                return -EINVAL;
index 3faf2438b9bcf6ad9f05849ffb4f8bd9e316f96e,05b953793316b28ac1fb19c902474e468ba828b0..2f91281ac0002c0f25a603d5c061e4e8b061ea0b
@@@ -93,7 -93,7 +93,7 @@@ static void sr_oa_regs(struct intel_vgp
                i915_mmio_reg_offset(EU_PERF_CNTL6),
        };
  
 -      if (workload->ring_id != RCS)
 +      if (workload->ring_id != RCS0)
                return;
  
        if (save) {
@@@ -149,7 -149,7 +149,7 @@@ static int populate_shadow_context(stru
        COPY_REG_MASKED(ctx_ctrl);
        COPY_REG(ctx_timestamp);
  
 -      if (ring_id == RCS) {
 +      if (ring_id == RCS0) {
                COPY_REG(bb_per_ctx_ptr);
                COPY_REG(rcs_indirect_ctx);
                COPY_REG(rcs_indirect_ctx_offset);
  
        context_page_num = context_page_num >> PAGE_SHIFT;
  
 -      if (IS_BROADWELL(gvt->dev_priv) && ring_id == RCS)
 +      if (IS_BROADWELL(gvt->dev_priv) && ring_id == RCS0)
                context_page_num = 19;
  
        i = 2;
@@@ -346,7 -346,7 +346,7 @@@ static int set_context_ppgtt_from_shado
        int i = 0;
  
        if (mm->type != INTEL_GVT_MM_PPGTT || !mm->ppgtt_mm.shadowed)
-               return -1;
+               return -EINVAL;
  
        if (mm->ppgtt_mm.root_entry_type == GTT_TYPE_PPGTT_ROOT_L4_ENTRY) {
                px_dma(&ppgtt->pml4) = mm->ppgtt_mm.shadow_pdps[0];
@@@ -410,12 -410,6 +410,6 @@@ int intel_gvt_scan_and_shadow_workload(
        if (workload->shadow)
                return 0;
  
-       ret = set_context_ppgtt_from_shadow(workload, shadow_ctx);
-       if (ret < 0) {
-               gvt_vgpu_err("workload shadow ppgtt isn't ready\n");
-               return ret;
-       }
        /* pin shadow context by gvt even the shadow context will be pinned
         * when i915 alloc request. That is because gvt will update the guest
         * context from shadow context when workload is completed, and at that
        if (ret)
                goto err_unpin;
  
 -      if ((workload->ring_id == RCS) &&
 -          (workload->wa_ctx.indirect_ctx.size != 0)) {
 +      if (workload->ring_id == RCS0 && workload->wa_ctx.indirect_ctx.size) {
                ret = intel_gvt_scan_and_shadow_wa_ctx(&workload->wa_ctx);
                if (ret)
                        goto err_shadow;
@@@ -677,6 -672,9 +671,9 @@@ static int dispatch_workload(struct int
  {
        struct intel_vgpu *vgpu = workload->vgpu;
        struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+       struct intel_vgpu_submission *s = &vgpu->submission;
+       struct i915_gem_context *shadow_ctx = s->shadow_ctx;
+       struct i915_request *rq;
        int ring_id = workload->ring_id;
        int ret;
  
        mutex_lock(&vgpu->vgpu_lock);
        mutex_lock(&dev_priv->drm.struct_mutex);
  
+       ret = set_context_ppgtt_from_shadow(workload, shadow_ctx);
+       if (ret < 0) {
+               gvt_vgpu_err("workload shadow ppgtt isn't ready\n");
+               goto err_req;
+       }
        ret = intel_gvt_workload_req_alloc(workload);
        if (ret)
                goto err_req;
  
        ret = prepare_workload(workload);
  out:
+       if (ret) {
+               /* We might still need to add request with
+                * clean ctx to retire it properly..
+                */
+               rq = fetch_and_zero(&workload->req);
+               i915_request_put(rq);
+       }
        if (!IS_ERR_OR_NULL(workload->req)) {
                gvt_dbg_sched("ring id %d submit workload to i915 %p\n",
                                ring_id, workload->req);
@@@ -738,7 -750,8 +749,8 @@@ static struct intel_vgpu_workload *pick
                goto out;
        }
  
-       if (list_empty(workload_q_head(scheduler->current_vgpu, ring_id)))
+       if (!scheduler->current_vgpu->active ||
+           list_empty(workload_q_head(scheduler->current_vgpu, ring_id)))
                goto out;
  
        /*
@@@ -790,7 -803,7 +802,7 @@@ static void update_guest_context(struc
        context_page_num = rq->engine->context_size;
        context_page_num = context_page_num >> PAGE_SHIFT;
  
 -      if (IS_BROADWELL(gvt->dev_priv) && rq->engine->id == RCS)
 +      if (IS_BROADWELL(gvt->dev_priv) && rq->engine->id == RCS0)
                context_page_num = 19;
  
        i = 2;
@@@ -890,8 -903,8 +902,8 @@@ static void complete_current_workload(s
                                workload->status = 0;
                }
  
 -              if (!workload->status && !(vgpu->resetting_eng &
 -                                         ENGINE_MASK(ring_id))) {
 +              if (!workload->status &&
 +                  !(vgpu->resetting_eng & BIT(ring_id))) {
                        update_guest_context(workload);
  
                        for_each_set_bit(event, workload->pending_events,
  
        list_del_init(&workload->list);
  
 -      if (workload->status || (vgpu->resetting_eng & ENGINE_MASK(ring_id))) {
 +      if (workload->status || vgpu->resetting_eng & BIT(ring_id)) {
                /* if workload->status is not successful means HW GPU
                 * has occurred GPU hang or something wrong with i915/GVT,
                 * and GVT won't inject context switch interrupt to guest.
                 * cleaned up during the resetting process later, so doing
                 * the workload clean up here doesn't have any impact.
                 **/
 -              intel_vgpu_clean_workloads(vgpu, ENGINE_MASK(ring_id));
 +              intel_vgpu_clean_workloads(vgpu, BIT(ring_id));
        }
  
        workload->complete(workload);
@@@ -988,7 -1001,7 +1000,7 @@@ static int workload_thread(void *priv
                                workload->ring_id, workload);
  
                if (need_force_wake)
 -                      intel_uncore_forcewake_get(gvt->dev_priv,
 +                      intel_uncore_forcewake_get(&gvt->dev_priv->uncore,
                                        FORCEWAKE_ALL);
  
                ret = dispatch_workload(workload);
@@@ -1010,7 -1023,7 +1022,7 @@@ complete
                complete_current_workload(gvt, ring_id);
  
                if (need_force_wake)
 -                      intel_uncore_forcewake_put(gvt->dev_priv,
 +                      intel_uncore_forcewake_put(&gvt->dev_priv->uncore,
                                        FORCEWAKE_ALL);
  
                intel_runtime_pm_put_unchecked(gvt->dev_priv);
@@@ -1101,9 -1114,9 +1113,9 @@@ i915_context_ppgtt_root_restore(struct 
        struct i915_hw_ppgtt *i915_ppgtt = s->shadow_ctx->ppgtt;
        int i;
  
 -      if (i915_vm_is_48bit(&i915_ppgtt->vm))
 +      if (i915_vm_is_4lvl(&i915_ppgtt->vm)) {
                px_dma(&i915_ppgtt->pml4) = s->i915_context_pml4;
 -      else {
 +      else {
                for (i = 0; i < GEN8_3LVL_PDPES; i++)
                        px_dma(i915_ppgtt->pdp.page_directory[i]) =
                                                s->i915_context_pdps[i];
@@@ -1154,7 -1167,7 +1166,7 @@@ i915_context_ppgtt_root_save(struct int
        struct i915_hw_ppgtt *i915_ppgtt = s->shadow_ctx->ppgtt;
        int i;
  
 -      if (i915_vm_is_48bit(&i915_ppgtt->vm))
 +      if (i915_vm_is_4lvl(&i915_ppgtt->vm))
                s->i915_context_pml4 = px_dma(&i915_ppgtt->pml4);
        else {
                for (i = 0; i < GEN8_3LVL_PDPES; i++)
@@@ -1437,7 -1450,7 +1449,7 @@@ intel_vgpu_create_workload(struct intel
        workload->rb_start = start;
        workload->rb_ctl = ctl;
  
 -      if (ring_id == RCS) {
 +      if (ring_id == RCS0) {
                intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa +
                        RING_CTX_OFF(bb_per_ctx_ptr.val), &per_ctx, 4);
                intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa +
                intel_runtime_pm_put_unchecked(dev_priv);
        }
  
-       if (ret && (vgpu_is_vm_unhealthy(ret))) {
-               enter_failsafe_mode(vgpu, GVT_FAILSAFE_GUEST_ERR);
+       if (ret) {
+               if (vgpu_is_vm_unhealthy(ret))
+                       enter_failsafe_mode(vgpu, GVT_FAILSAFE_GUEST_ERR);
                intel_vgpu_destroy_workload(workload);
                return ERR_PTR(ret);
        }
index 652f65d2e13152247ade2c49e941513c71873876,f6f6e5b78e9784c0ffee5f7132a8ddd2a9339954..b8cfe5e45e27755042864e4e14a0e7cde3096b57
@@@ -388,9 -388,12 +388,9 @@@ static void print_context_stats(struct 
        struct i915_gem_context *ctx;
  
        list_for_each_entry(ctx, &i915->contexts.list, link) {
 -              struct intel_engine_cs *engine;
 -              enum intel_engine_id id;
 -
 -              for_each_engine(engine, i915, id) {
 -                      struct intel_context *ce = to_intel_context(ctx, engine);
 +              struct intel_context *ce;
  
 +              list_for_each_entry(ce, &ctx->active_engines, active_link) {
                        if (ce->state)
                                per_file_stats(0, ce->state->obj, &kstats);
                        if (ce->ring)
  
                        rcu_read_lock();
                        task = pid_task(ctx->pid ?: file->pid, PIDTYPE_PID);
 -                      snprintf(name, sizeof(name), "%s/%d",
 -                               task ? task->comm : "<unknown>",
 -                               ctx->user_handle);
 +                      snprintf(name, sizeof(name), "%s",
 +                               task ? task->comm : "<unknown>");
                        rcu_read_unlock();
  
                        print_file_stats(m, name, stats);
@@@ -880,7 -884,7 +880,7 @@@ static int i915_interrupt_info(struct s
                for_each_engine(engine, dev_priv, id) {
                        seq_printf(m,
                                   "Graphics Interrupt mask (%s):       %08x\n",
 -                                 engine->name, I915_READ_IMR(engine));
 +                                 engine->name, ENGINE_READ(engine, RING_IMR));
                }
        }
  
@@@ -1093,7 -1097,7 +1093,7 @@@ static int i915_frequency_info(struct s
                }
  
                /* RPSTAT1 is in the GT power well */
 -              intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
 +              intel_uncore_forcewake_get(&dev_priv->uncore, FORCEWAKE_ALL);
  
                reqf = I915_READ(GEN6_RPNSWREQ);
                if (INTEL_GEN(dev_priv) >= 9)
                cagf = intel_gpu_freq(dev_priv,
                                      intel_get_cagf(dev_priv, rpstat));
  
 -              intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
 +              intel_uncore_forcewake_put(&dev_priv->uncore, FORCEWAKE_ALL);
  
                if (INTEL_GEN(dev_priv) >= 11) {
                        pm_ier = I915_READ(GEN11_GPM_WGBOXPERF_INTR_ENABLE);
@@@ -1277,11 -1281,14 +1277,11 @@@ static int i915_hangcheck_info(struct s
        intel_wakeref_t wakeref;
        enum intel_engine_id id;
  
 +      seq_printf(m, "Reset flags: %lx\n", dev_priv->gpu_error.flags);
        if (test_bit(I915_WEDGED, &dev_priv->gpu_error.flags))
 -              seq_puts(m, "Wedged\n");
 +              seq_puts(m, "\tWedged\n");
        if (test_bit(I915_RESET_BACKOFF, &dev_priv->gpu_error.flags))
 -              seq_puts(m, "Reset in progress: struct_mutex backoff\n");
 -      if (waitqueue_active(&dev_priv->gpu_error.wait_queue))
 -              seq_puts(m, "Waiter holding struct mutex\n");
 -      if (waitqueue_active(&dev_priv->gpu_error.reset_queue))
 -              seq_puts(m, "struct_mutex blocked for reset\n");
 +              seq_puts(m, "\tDevice (global) reset in progress\n");
  
        if (!i915_modparams.enable_hangcheck) {
                seq_puts(m, "Hangcheck disabled\n");
        with_intel_runtime_pm(dev_priv, wakeref) {
                for_each_engine(engine, dev_priv, id) {
                        acthd[id] = intel_engine_get_active_head(engine);
 -                      seqno[id] = intel_engine_get_seqno(engine);
 +                      seqno[id] = intel_engine_get_hangcheck_seqno(engine);
                }
  
 -              intel_engine_get_instdone(dev_priv->engine[RCS], &instdone);
 +              intel_engine_get_instdone(dev_priv->engine[RCS0], &instdone);
        }
  
        if (timer_pending(&dev_priv->gpu_error.hangcheck_work.timer))
        for_each_engine(engine, dev_priv, id) {
                seq_printf(m, "%s:\n", engine->name);
                seq_printf(m, "\tseqno = %x [current %x, last %x], %dms ago\n",
 -                         engine->hangcheck.seqno, seqno[id],
 -                         intel_engine_last_submit(engine),
 +                         engine->hangcheck.last_seqno,
 +                         seqno[id],
 +                         engine->hangcheck.next_seqno,
                           jiffies_to_msecs(jiffies -
                                            engine->hangcheck.action_timestamp));
  
                           (long long)engine->hangcheck.acthd,
                           (long long)acthd[id]);
  
 -              if (engine->id == RCS) {
 +              if (engine->id == RCS0) {
                        seq_puts(m, "\tinstdone read =\n");
  
                        i915_instdone_info(dev_priv, m, &instdone);
@@@ -1413,14 -1419,13 +1413,14 @@@ static int ironlake_drpc_info(struct se
  static int i915_forcewake_domains(struct seq_file *m, void *data)
  {
        struct drm_i915_private *i915 = node_to_i915(m->private);
 +      struct intel_uncore *uncore = &i915->uncore;
        struct intel_uncore_forcewake_domain *fw_domain;
        unsigned int tmp;
  
        seq_printf(m, "user.bypass_count = %u\n",
 -                 i915->uncore.user_forcewake.count);
 +                 uncore->user_forcewake.count);
  
 -      for_each_fw_domain(fw_domain, i915, tmp)
 +      for_each_fw_domain(fw_domain, uncore, tmp)
                seq_printf(m, "%s.wake_count = %u\n",
                           intel_uncore_forcewake_domain_to_str(fw_domain->id),
                           READ_ONCE(fw_domain->wake_count));
@@@ -1877,7 -1882,9 +1877,7 @@@ static int i915_context_status(struct s
  {
        struct drm_i915_private *dev_priv = node_to_i915(m->private);
        struct drm_device *dev = &dev_priv->drm;
 -      struct intel_engine_cs *engine;
        struct i915_gem_context *ctx;
 -      enum intel_engine_id id;
        int ret;
  
        ret = mutex_lock_interruptible(&dev->struct_mutex);
                return ret;
  
        list_for_each_entry(ctx, &dev_priv->contexts.list, link) {
 +              struct intel_context *ce;
 +
                seq_puts(m, "HW context ");
                if (!list_empty(&ctx->hw_id_link))
                        seq_printf(m, "%x [pin %u]", ctx->hw_id,
                seq_putc(m, ctx->remap_slice ? 'R' : 'r');
                seq_putc(m, '\n');
  
 -              for_each_engine(engine, dev_priv, id) {
 -                      struct intel_context *ce =
 -                              to_intel_context(ctx, engine);
 -
 -                      seq_printf(m, "%s: ", engine->name);
 +              list_for_each_entry(ce, &ctx->active_engines, active_link) {
 +                      seq_printf(m, "%s: ", ce->engine->name);
                        if (ce->state)
                                describe_obj(m, ce->state->obj);
                        if (ce->ring)
@@@ -2015,9 -2023,11 +2015,9 @@@ static const char *rps_power_to_str(uns
  static int i915_rps_boost_info(struct seq_file *m, void *data)
  {
        struct drm_i915_private *dev_priv = node_to_i915(m->private);
 -      struct drm_device *dev = &dev_priv->drm;
        struct intel_rps *rps = &dev_priv->gt_pm.rps;
        u32 act_freq = rps->cur_freq;
        intel_wakeref_t wakeref;
 -      struct drm_file *file;
  
        with_intel_runtime_pm_if_in_use(dev_priv, wakeref) {
                if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
                   intel_gpu_freq(dev_priv, rps->efficient_freq),
                   intel_gpu_freq(dev_priv, rps->boost_freq));
  
 -      mutex_lock(&dev->filelist_mutex);
 -      list_for_each_entry_reverse(file, &dev->filelist, lhead) {
 -              struct drm_i915_file_private *file_priv = file->driver_priv;
 -              struct task_struct *task;
 -
 -              rcu_read_lock();
 -              task = pid_task(file->pid, PIDTYPE_PID);
 -              seq_printf(m, "%s [%d]: %d boosts\n",
 -                         task ? task->comm : "<unknown>",
 -                         task ? task->pid : -1,
 -                         atomic_read(&file_priv->rps_client.boosts));
 -              rcu_read_unlock();
 -      }
 -      seq_printf(m, "Kernel (anonymous) boosts: %d\n",
 -                 atomic_read(&rps->boosts));
 -      mutex_unlock(&dev->filelist_mutex);
 +      seq_printf(m, "Wait boosts: %d\n", atomic_read(&rps->boosts));
  
        if (INTEL_GEN(dev_priv) >= 6 &&
            rps->enabled &&
                u32 rpup, rpupei;
                u32 rpdown, rpdownei;
  
 -              intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
 +              intel_uncore_forcewake_get(&dev_priv->uncore, FORCEWAKE_ALL);
                rpup = I915_READ_FW(GEN6_RP_CUR_UP) & GEN6_RP_EI_MASK;
                rpupei = I915_READ_FW(GEN6_RP_CUR_UP_EI) & GEN6_RP_EI_MASK;
                rpdown = I915_READ_FW(GEN6_RP_CUR_DOWN) & GEN6_RP_EI_MASK;
                rpdownei = I915_READ_FW(GEN6_RP_CUR_DOWN_EI) & GEN6_RP_EI_MASK;
 -              intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
 +              intel_uncore_forcewake_put(&dev_priv->uncore, FORCEWAKE_ALL);
  
                seq_printf(m, "\nRPS Autotuning (current \"%s\" window):\n",
                           rps_power_to_str(rps->power.mode));
@@@ -2582,6 -2607,7 +2582,6 @@@ static in
  i915_edp_psr_debug_set(void *data, u64 val)
  {
        struct drm_i915_private *dev_priv = data;
 -      struct drm_modeset_acquire_ctx ctx;
        intel_wakeref_t wakeref;
        int ret;
  
  
        wakeref = intel_runtime_pm_get(dev_priv);
  
 -      drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
 -
 -retry:
 -      ret = intel_psr_set_debugfs_mode(dev_priv, &ctx, val);
 -      if (ret == -EDEADLK) {
 -              ret = drm_modeset_backoff(&ctx);
 -              if (!ret)
 -                      goto retry;
 -      }
 -
 -      drm_modeset_drop_locks(&ctx);
 -      drm_modeset_acquire_fini(&ctx);
 +      ret = intel_psr_debug_set(dev_priv, val);
  
        intel_runtime_pm_put(dev_priv, wakeref);
  
@@@ -2649,7 -2686,8 +2649,7 @@@ static int i915_runtime_pm_status(struc
        seq_printf(m, "Runtime power status: %s\n",
                   enableddisabled(!dev_priv->power_domains.wakeref));
  
 -      seq_printf(m, "GPU idle: %s (epoch %u)\n",
 -                 yesno(!dev_priv->gt.awake), dev_priv->gt.epoch);
 +      seq_printf(m, "GPU idle: %s\n", yesno(!dev_priv->gt.awake));
        seq_printf(m, "IRQs disabled: %s\n",
                   yesno(!intel_irqs_enabled(dev_priv)));
  #ifdef CONFIG_PM
@@@ -2866,6 -2904,7 +2866,6 @@@ static void intel_connector_info(struc
        if (connector->status == connector_status_disconnected)
                return;
  
 -      seq_printf(m, "\tname: %s\n", connector->display_info.name);
        seq_printf(m, "\tphysical dimensions: %dx%dmm\n",
                   connector->display_info.width_mm,
                   connector->display_info.height_mm);
@@@ -3084,7 -3123,8 +3084,7 @@@ static int i915_engine_info(struct seq_
  
        wakeref = intel_runtime_pm_get(dev_priv);
  
 -      seq_printf(m, "GT awake? %s (epoch %u)\n",
 -                 yesno(dev_priv->gt.awake), dev_priv->gt.epoch);
 +      seq_printf(m, "GT awake? %s\n", yesno(dev_priv->gt.awake));
        seq_printf(m, "Global active requests: %d\n",
                   dev_priv->gt.active_requests);
        seq_printf(m, "CS timestamp frequency: %u kHz\n",
@@@ -3171,7 -3211,7 +3171,7 @@@ static int i915_shared_dplls_info(struc
  static int i915_wa_registers(struct seq_file *m, void *unused)
  {
        struct drm_i915_private *i915 = node_to_i915(m->private);
 -      const struct i915_wa_list *wal = &i915->engine[RCS]->ctx_wa_list;
 +      const struct i915_wa_list *wal = &i915->engine[RCS0]->ctx_wa_list;
        struct i915_wa *wa;
        unsigned int i;
  
@@@ -3825,18 -3865,11 +3825,18 @@@ static const struct file_operations i91
  static int
  i915_wedged_get(void *data, u64 *val)
  {
 -      struct drm_i915_private *dev_priv = data;
 -
 -      *val = i915_terminally_wedged(&dev_priv->gpu_error);
 +      int ret = i915_terminally_wedged(data);
  
 -      return 0;
 +      switch (ret) {
 +      case -EIO:
 +              *val = 1;
 +              return 0;
 +      case 0:
 +              *val = 0;
 +              return 0;
 +      default:
 +              return ret;
 +      }
  }
  
  static int
@@@ -3844,9 -3877,16 +3844,9 @@@ i915_wedged_set(void *data, u64 val
  {
        struct drm_i915_private *i915 = data;
  
 -      /*
 -       * There is no safeguard against this debugfs entry colliding
 -       * with the hangcheck calling same i915_handle_error() in
 -       * parallel, causing an explosion. For now we assume that the
 -       * test harness is responsible enough not to inject gpu hangs
 -       * while it is writing to 'i915_wedged'
 -       */
 -
 -      if (i915_reset_backoff(&i915->gpu_error))
 -              return -EAGAIN;
 +      /* Flush any previous reset before applying for a new one */
 +      wait_event(i915->gpu_error.reset_queue,
 +                 !test_bit(I915_RESET_BACKOFF, &i915->gpu_error.flags));
  
        i915_handle_error(i915, val, I915_ERROR_CAPTURE,
                          "Manually set wedged engine mask = %llx", val);
@@@ -3887,9 -3927,12 +3887,9 @@@ static in
  i915_drop_caches_set(void *data, u64 val)
  {
        struct drm_i915_private *i915 = data;
 -      intel_wakeref_t wakeref;
 -      int ret = 0;
  
        DRM_DEBUG("Dropping caches: 0x%08llx [0x%08llx]\n",
                  val, val & DROP_ALL);
 -      wakeref = intel_runtime_pm_get(i915);
  
        if (val & DROP_RESET_ACTIVE &&
            wait_for(intel_engines_are_idle(i915), I915_IDLE_ENGINES_TIMEOUT))
        /* No need to check and wait for gpu resets, only libdrm auto-restarts
         * on ioctls on -EAGAIN. */
        if (val & (DROP_ACTIVE | DROP_RETIRE | DROP_RESET_SEQNO)) {
 +              int ret;
 +
                ret = mutex_lock_interruptible(&i915->drm.struct_mutex);
                if (ret)
 -                      goto out;
 +                      return ret;
  
                if (val & DROP_ACTIVE)
                        ret = i915_gem_wait_for_idle(i915,
                mutex_unlock(&i915->drm.struct_mutex);
        }
  
 -      if (val & DROP_RESET_ACTIVE && i915_terminally_wedged(&i915->gpu_error))
 +      if (val & DROP_RESET_ACTIVE && i915_terminally_wedged(i915))
                i915_handle_error(i915, ALL_ENGINES, 0, NULL);
  
        fs_reclaim_acquire(GFP_KERNEL);
        if (val & DROP_FREED)
                i915_gem_drain_freed_objects(i915);
  
 -out:
 -      intel_runtime_pm_put(i915, wakeref);
 -
 -      return ret;
 +      return 0;
  }
  
  DEFINE_SIMPLE_ATTRIBUTE(i915_drop_caches_fops,
@@@ -4249,7 -4293,7 +4249,7 @@@ static int i915_forcewake_open(struct i
                return 0;
  
        file->private_data = (void *)(uintptr_t)intel_runtime_pm_get(i915);
 -      intel_uncore_forcewake_user_get(i915);
 +      intel_uncore_forcewake_user_get(&i915->uncore);
  
        return 0;
  }
@@@ -4261,7 -4305,7 +4261,7 @@@ static int i915_forcewake_release(struc
        if (INTEL_GEN(i915) < 6)
                return 0;
  
 -      intel_uncore_forcewake_user_put(i915);
 +      intel_uncore_forcewake_user_put(&i915->uncore);
        intel_runtime_pm_put(i915,
                             (intel_wakeref_t)(uintptr_t)file->private_data);
  
@@@ -4786,7 -4830,10 +4786,10 @@@ static int i915_dsc_fec_support_show(st
                ret = drm_modeset_lock(&dev->mode_config.connection_mutex,
                                       &ctx);
                if (ret) {
-                       ret = -EINTR;
+                       if (ret == -EDEADLK && !drm_modeset_backoff(&ctx)) {
+                               try_again = true;
+                               continue;
+                       }
                        break;
                }
                crtc = connector->state->crtc;
index b67ffaa283dc45f1072312d3140c08bd22368148,641e0778fa9c4123204f75091df3c53b5162a961..994e53848af7823dac4a82574bb10695cb2ae901
@@@ -246,13 -246,13 +246,13 @@@ static void dsi_program_swing_and_deemp
  
                for (lane = 0; lane <= 3; lane++) {
                        /* Bspec: must not use GRP register for write */
 -                      tmp = I915_READ(ICL_PORT_TX_DW4_LN(port, lane));
 +                      tmp = I915_READ(ICL_PORT_TX_DW4_LN(lane, port));
                        tmp &= ~(POST_CURSOR_1_MASK | POST_CURSOR_2_MASK |
                                 CURSOR_COEFF_MASK);
                        tmp |= POST_CURSOR_1(0x0);
                        tmp |= POST_CURSOR_2(0x0);
                        tmp |= CURSOR_COEFF(0x3f);
 -                      I915_WRITE(ICL_PORT_TX_DW4_LN(port, lane), tmp);
 +                      I915_WRITE(ICL_PORT_TX_DW4_LN(lane, port), tmp);
                }
        }
  }
@@@ -323,6 -323,21 +323,21 @@@ static void gen11_dsi_program_esc_clk_d
        }
  }
  
+ static void get_dsi_io_power_domains(struct drm_i915_private *dev_priv,
+                                    struct intel_dsi *intel_dsi)
+ {
+       enum port port;
+       for_each_dsi_port(port, intel_dsi->ports) {
+               WARN_ON(intel_dsi->io_wakeref[port]);
+               intel_dsi->io_wakeref[port] =
+                       intel_display_power_get(dev_priv,
+                                               port == PORT_A ?
+                                               POWER_DOMAIN_PORT_DDI_A_IO :
+                                               POWER_DOMAIN_PORT_DDI_B_IO);
+       }
+ }
  static void gen11_dsi_enable_io_power(struct intel_encoder *encoder)
  {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
                I915_WRITE(ICL_DSI_IO_MODECTL(port), tmp);
        }
  
-       for_each_dsi_port(port, intel_dsi->ports) {
-               intel_dsi->io_wakeref[port] =
-                       intel_display_power_get(dev_priv,
-                                               port == PORT_A ?
-                                               POWER_DOMAIN_PORT_DDI_A_IO :
-                                               POWER_DOMAIN_PORT_DDI_B_IO);
-       }
+       get_dsi_io_power_domains(dev_priv, intel_dsi);
  }
  
  static void gen11_dsi_power_up_lanes(struct intel_encoder *encoder)
@@@ -390,11 -399,11 +399,11 @@@ static void gen11_dsi_config_phy_lanes_
                tmp &= ~LOADGEN_SELECT;
                I915_WRITE(ICL_PORT_TX_DW4_AUX(port), tmp);
                for (lane = 0; lane <= 3; lane++) {
 -                      tmp = I915_READ(ICL_PORT_TX_DW4_LN(port, lane));
 +                      tmp = I915_READ(ICL_PORT_TX_DW4_LN(lane, port));
                        tmp &= ~LOADGEN_SELECT;
                        if (lane != 2)
                                tmp |= LOADGEN_SELECT;
 -                      I915_WRITE(ICL_PORT_TX_DW4_LN(port, lane), tmp);
 +                      I915_WRITE(ICL_PORT_TX_DW4_LN(lane, port), tmp);
                }
        }
  
@@@ -589,6 -598,12 +598,12 @@@ static void gen11_dsi_map_pll(struct in
                val |= DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, port);
        }
        I915_WRITE(DPCLKA_CFGCR0_ICL, val);
+       for_each_dsi_port(port, intel_dsi->ports) {
+               val &= ~DPCLKA_CFGCR0_DDI_CLK_OFF(port);
+       }
+       I915_WRITE(DPCLKA_CFGCR0_ICL, val);
        POSTING_READ(DPCLKA_CFGCR0_ICL);
  
        mutex_unlock(&dev_priv->dpll_lock);
@@@ -861,8 -876,7 +876,8 @@@ static void gen11_dsi_enable_transcoder
                I915_WRITE(PIPECONF(dsi_trans), tmp);
  
                /* wait for transcoder to be enabled */
 -              if (intel_wait_for_register(dev_priv, PIPECONF(dsi_trans),
 +              if (intel_wait_for_register(&dev_priv->uncore,
 +                                          PIPECONF(dsi_trans),
                                            I965_PIPECONF_ACTIVE,
                                            I965_PIPECONF_ACTIVE, 10))
                        DRM_ERROR("DSI transcoder not enabled\n");
@@@ -1040,8 -1054,7 +1055,8 @@@ static void gen11_dsi_disable_transcode
                I915_WRITE(PIPECONF(dsi_trans), tmp);
  
                /* wait for transcoder to be disabled */
 -              if (intel_wait_for_register(dev_priv, PIPECONF(dsi_trans),
 +              if (intel_wait_for_register(&dev_priv->uncore,
 +                                          PIPECONF(dsi_trans),
                                            I965_PIPECONF_ACTIVE, 0, 50))
                        DRM_ERROR("DSI trancoder not disabled\n");
        }
@@@ -1119,7 -1132,7 +1134,7 @@@ static void gen11_dsi_disable_port(stru
                        DRM_ERROR("DDI port:%c buffer not idle\n",
                                  port_name(port));
        }
-       gen11_dsi_ungate_clocks(encoder);
+       gen11_dsi_gate_clocks(encoder);
  }
  
  static void gen11_dsi_disable_io_power(struct intel_encoder *encoder)
@@@ -1181,10 -1194,11 +1196,10 @@@ static void gen11_dsi_get_config(struc
  {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
 -      u32 pll_id;
  
        /* FIXME: adapt icl_ddi_clock_get() for DSI and use that? */
 -      pll_id = intel_get_shared_dpll_id(dev_priv, pipe_config->shared_dpll);
 -      pipe_config->port_clock = cnl_calc_wrpll_link(dev_priv, pll_id);
 +      pipe_config->port_clock =
 +              cnl_calc_wrpll_link(dev_priv, &pipe_config->dpll_hw_state);
        pipe_config->base.adjusted_mode.crtc_clock = intel_dsi->pclk;
        pipe_config->output_types |= BIT(INTEL_OUTPUT_DSI);
  }
@@@ -1219,20 -1233,11 +1234,11 @@@ static int gen11_dsi_compute_config(str
        return 0;
  }
  
- static u64 gen11_dsi_get_power_domains(struct intel_encoder *encoder,
-                                      struct intel_crtc_state *crtc_state)
+ static void gen11_dsi_get_power_domains(struct intel_encoder *encoder,
+                                       struct intel_crtc_state *crtc_state)
  {
-       struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
-       u64 domains = 0;
-       enum port port;
-       for_each_dsi_port(port, intel_dsi->ports)
-               if (port == PORT_A)
-                       domains |= BIT_ULL(POWER_DOMAIN_PORT_DDI_A_IO);
-               else
-                       domains |= BIT_ULL(POWER_DOMAIN_PORT_DDI_B_IO);
-       return domains;
+       get_dsi_io_power_domains(to_i915(encoder->base.dev),
+                                enc_to_intel_dsi(&encoder->base));
  }
  
  static bool gen11_dsi_get_hw_state(struct intel_encoder *encoder,
@@@ -1362,7 -1367,7 +1368,7 @@@ void icl_dsi_init(struct drm_i915_priva
        struct intel_encoder *encoder;
        struct intel_connector *intel_connector;
        struct drm_connector *connector;
 -      struct drm_display_mode *scan, *fixed_mode = NULL;
 +      struct drm_display_mode *fixed_mode;
        enum port port;
  
        if (!intel_bios_is_dsi_present(dev_priv, &port))
        /* attach connector to encoder */
        intel_connector_attach_encoder(intel_connector, encoder);
  
 -      /* fill mode info from VBT */
        mutex_lock(&dev->mode_config.mutex);
 -      intel_dsi_vbt_get_modes(intel_dsi);
 -      list_for_each_entry(scan, &connector->probed_modes, head) {
 -              if (scan->type & DRM_MODE_TYPE_PREFERRED) {
 -                      fixed_mode = drm_mode_duplicate(dev, scan);
 -                      break;
 -              }
 -      }
 +      fixed_mode = intel_panel_vbt_fixed_mode(intel_connector);
        mutex_unlock(&dev->mode_config.mutex);
  
        if (!fixed_mode) {
                goto err;
        }
  
 -      connector->display_info.width_mm = fixed_mode->width_mm;
 -      connector->display_info.height_mm = fixed_mode->height_mm;
        intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
        intel_panel_setup_backlight(connector, INVALID_PIPE);
  
 -
        if (dev_priv->vbt.dsi.config->dual_link)
                intel_dsi->ports = BIT(PORT_A) | BIT(PORT_B);
        else
index 3f1e491bd0c0a05b5d98358f336edd96eed4bfbc,ab4e60dfd6a3460001cbcae4691f1ede8ebb230e..6fc602485c177c9892e885ba50c836ed15a937ce
@@@ -851,7 -851,7 +851,7 @@@ static int intel_ddi_hdmi_level(struct 
  
        level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift;
  
 -      if (IS_ICELAKE(dev_priv)) {
 +      if (INTEL_GEN(dev_priv) >= 11) {
                if (intel_port_is_combophy(dev_priv, port))
                        icl_get_combo_buf_trans(dev_priv, port, INTEL_OUTPUT_HDMI,
                                                0, &n_entries);
@@@ -1240,15 -1240,24 +1240,15 @@@ static int hsw_ddi_calc_wrpll_link(stru
        return (refclk * n * 100) / (p * r);
  }
  
 -static int skl_calc_wrpll_link(struct drm_i915_private *dev_priv,
 -                             enum intel_dpll_id pll_id)
 +static int skl_calc_wrpll_link(const struct intel_dpll_hw_state *pll_state)
  {
 -      i915_reg_t cfgcr1_reg, cfgcr2_reg;
 -      u32 cfgcr1_val, cfgcr2_val;
        u32 p0, p1, p2, dco_freq;
  
 -      cfgcr1_reg = DPLL_CFGCR1(pll_id);
 -      cfgcr2_reg = DPLL_CFGCR2(pll_id);
 -
 -      cfgcr1_val = I915_READ(cfgcr1_reg);
 -      cfgcr2_val = I915_READ(cfgcr2_reg);
 -
 -      p0 = cfgcr2_val & DPLL_CFGCR2_PDIV_MASK;
 -      p2 = cfgcr2_val & DPLL_CFGCR2_KDIV_MASK;
 +      p0 = pll_state->cfgcr2 & DPLL_CFGCR2_PDIV_MASK;
 +      p2 = pll_state->cfgcr2 & DPLL_CFGCR2_KDIV_MASK;
  
 -      if (cfgcr2_val &  DPLL_CFGCR2_QDIV_MODE(1))
 -              p1 = (cfgcr2_val & DPLL_CFGCR2_QDIV_RATIO_MASK) >> 8;
 +      if (pll_state->cfgcr2 &  DPLL_CFGCR2_QDIV_MODE(1))
 +              p1 = (pll_state->cfgcr2 & DPLL_CFGCR2_QDIV_RATIO_MASK) >> 8;
        else
                p1 = 1;
  
                break;
        }
  
 -      dco_freq = (cfgcr1_val & DPLL_CFGCR1_DCO_INTEGER_MASK) * 24 * 1000;
 +      dco_freq = (pll_state->cfgcr1 & DPLL_CFGCR1_DCO_INTEGER_MASK)
 +              * 24 * 1000;
  
 -      dco_freq += (((cfgcr1_val & DPLL_CFGCR1_DCO_FRACTION_MASK) >> 9) * 24 *
 -              1000) / 0x8000;
 +      dco_freq += (((pll_state->cfgcr1 & DPLL_CFGCR1_DCO_FRACTION_MASK) >> 9)
 +                   * 24 * 1000) / 0x8000;
  
        if (WARN_ON(p0 == 0 || p1 == 0 || p2 == 0))
                return 0;
  }
  
  int cnl_calc_wrpll_link(struct drm_i915_private *dev_priv,
 -                      enum intel_dpll_id pll_id)
 +                      struct intel_dpll_hw_state *pll_state)
  {
 -      u32 cfgcr0, cfgcr1;
        u32 p0, p1, p2, dco_freq, ref_clock;
  
 -      if (INTEL_GEN(dev_priv) >= 11) {
 -              cfgcr0 = I915_READ(ICL_DPLL_CFGCR0(pll_id));
 -              cfgcr1 = I915_READ(ICL_DPLL_CFGCR1(pll_id));
 -      } else {
 -              cfgcr0 = I915_READ(CNL_DPLL_CFGCR0(pll_id));
 -              cfgcr1 = I915_READ(CNL_DPLL_CFGCR1(pll_id));
 -      }
 -
 -      p0 = cfgcr1 & DPLL_CFGCR1_PDIV_MASK;
 -      p2 = cfgcr1 & DPLL_CFGCR1_KDIV_MASK;
 +      p0 = pll_state->cfgcr1 & DPLL_CFGCR1_PDIV_MASK;
 +      p2 = pll_state->cfgcr1 & DPLL_CFGCR1_KDIV_MASK;
  
 -      if (cfgcr1 & DPLL_CFGCR1_QDIV_MODE(1))
 -              p1 = (cfgcr1 & DPLL_CFGCR1_QDIV_RATIO_MASK) >>
 +      if (pll_state->cfgcr1 & DPLL_CFGCR1_QDIV_MODE(1))
 +              p1 = (pll_state->cfgcr1 & DPLL_CFGCR1_QDIV_RATIO_MASK) >>
                        DPLL_CFGCR1_QDIV_RATIO_SHIFT;
        else
                p1 = 1;
        case DPLL_CFGCR1_KDIV_2:
                p2 = 2;
                break;
 -      case DPLL_CFGCR1_KDIV_4:
 -              p2 = 4;
 +      case DPLL_CFGCR1_KDIV_3:
 +              p2 = 3;
                break;
        }
  
        ref_clock = cnl_hdmi_pll_ref_clock(dev_priv);
  
 -      dco_freq = (cfgcr0 & DPLL_CFGCR0_DCO_INTEGER_MASK) * ref_clock;
 +      dco_freq = (pll_state->cfgcr0 & DPLL_CFGCR0_DCO_INTEGER_MASK)
 +              * ref_clock;
  
 -      dco_freq += (((cfgcr0 & DPLL_CFGCR0_DCO_FRACTION_MASK) >>
 +      dco_freq += (((pll_state->cfgcr0 & DPLL_CFGCR0_DCO_FRACTION_MASK) >>
                      DPLL_CFGCR0_DCO_FRACTION_SHIFT) * ref_clock) / 0x8000;
  
        if (WARN_ON(p0 == 0 || p1 == 0 || p2 == 0))
@@@ -1374,21 -1390,25 +1374,21 @@@ static int icl_calc_tbt_pll_link(struc
  }
  
  static int icl_calc_mg_pll_link(struct drm_i915_private *dev_priv,
 -                              enum port port)
 +                              const struct intel_dpll_hw_state *pll_state)
  {
 -      enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
 -      u32 mg_pll_div0, mg_clktop_hsclkctl;
 -      u32 m1, m2_int, m2_frac, div1, div2, refclk;
 +      u32 m1, m2_int, m2_frac, div1, div2, ref_clock;
        u64 tmp;
  
 -      refclk = dev_priv->cdclk.hw.ref;
 +      ref_clock = dev_priv->cdclk.hw.ref;
  
 -      mg_pll_div0 = I915_READ(MG_PLL_DIV0(tc_port));
 -      mg_clktop_hsclkctl = I915_READ(MG_CLKTOP2_HSCLKCTL(tc_port));
 +      m1 = pll_state->mg_pll_div1 & MG_PLL_DIV1_FBPREDIV_MASK;
 +      m2_int = pll_state->mg_pll_div0 & MG_PLL_DIV0_FBDIV_INT_MASK;
 +      m2_frac = (pll_state->mg_pll_div0 & MG_PLL_DIV0_FRACNEN_H) ?
 +              (pll_state->mg_pll_div0 & MG_PLL_DIV0_FBDIV_FRAC_MASK) >>
 +              MG_PLL_DIV0_FBDIV_FRAC_SHIFT : 0;
  
 -      m1 = I915_READ(MG_PLL_DIV1(tc_port)) & MG_PLL_DIV1_FBPREDIV_MASK;
 -      m2_int = mg_pll_div0 & MG_PLL_DIV0_FBDIV_INT_MASK;
 -      m2_frac = (mg_pll_div0 & MG_PLL_DIV0_FRACNEN_H) ?
 -                (mg_pll_div0 & MG_PLL_DIV0_FBDIV_FRAC_MASK) >>
 -                MG_PLL_DIV0_FBDIV_FRAC_SHIFT : 0;
 -
 -      switch (mg_clktop_hsclkctl & MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_MASK) {
 +      switch (pll_state->mg_clktop2_hsclkctl &
 +              MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_MASK) {
        case MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_2:
                div1 = 2;
                break;
                div1 = 7;
                break;
        default:
 -              MISSING_CASE(mg_clktop_hsclkctl);
 +              MISSING_CASE(pll_state->mg_clktop2_hsclkctl);
                return 0;
        }
  
 -      div2 = (mg_clktop_hsclkctl & MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO_MASK) >>
 +      div2 = (pll_state->mg_clktop2_hsclkctl &
 +              MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO_MASK) >>
                MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO_SHIFT;
 +
        /* div2 value of 0 is same as 1 means no div */
        if (div2 == 0)
                div2 = 1;
         * Adjust the original formula to delay the division by 2^22 in order to
         * minimize possible rounding errors.
         */
 -      tmp = (u64)m1 * m2_int * refclk +
 -            (((u64)m1 * m2_frac * refclk) >> 22);
 +      tmp = (u64)m1 * m2_int * ref_clock +
 +            (((u64)m1 * m2_frac * ref_clock) >> 22);
        tmp = div_u64(tmp, 5 * div1 * div2);
  
        return tmp;
@@@ -1453,24 -1471,25 +1453,24 @@@ static void icl_ddi_clock_get(struct in
                              struct intel_crtc_state *pipe_config)
  {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 +      struct intel_dpll_hw_state *pll_state = &pipe_config->dpll_hw_state;
        enum port port = encoder->port;
 -      int link_clock = 0;
 -      u32 pll_id;
 +      int link_clock;
  
 -      pll_id = intel_get_shared_dpll_id(dev_priv, pipe_config->shared_dpll);
        if (intel_port_is_combophy(dev_priv, port)) {
 -              if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_HDMI))
 -                      link_clock = cnl_calc_wrpll_link(dev_priv, pll_id);
 -              else
 -                      link_clock = icl_calc_dp_combo_pll_link(dev_priv,
 -                                                              pll_id);
 +              link_clock = cnl_calc_wrpll_link(dev_priv, pll_state);
        } else {
 +              enum intel_dpll_id pll_id = intel_get_shared_dpll_id(dev_priv,
 +                                              pipe_config->shared_dpll);
 +
                if (pll_id == DPLL_ID_ICL_TBTPLL)
                        link_clock = icl_calc_tbt_pll_link(dev_priv, port);
                else
 -                      link_clock = icl_calc_mg_pll_link(dev_priv, port);
 +                      link_clock = icl_calc_mg_pll_link(dev_priv, pll_state);
        }
  
        pipe_config->port_clock = link_clock;
 +
        ddi_dotclock_get(pipe_config);
  }
  
@@@ -1478,13 -1497,18 +1478,13 @@@ static void cnl_ddi_clock_get(struct in
                              struct intel_crtc_state *pipe_config)
  {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 -      int link_clock = 0;
 -      u32 cfgcr0;
 -      enum intel_dpll_id pll_id;
 -
 -      pll_id = intel_get_shared_dpll_id(dev_priv, pipe_config->shared_dpll);
 -
 -      cfgcr0 = I915_READ(CNL_DPLL_CFGCR0(pll_id));
 +      struct intel_dpll_hw_state *pll_state = &pipe_config->dpll_hw_state;
 +      int link_clock;
  
 -      if (cfgcr0 & DPLL_CFGCR0_HDMI_MODE) {
 -              link_clock = cnl_calc_wrpll_link(dev_priv, pll_id);
 +      if (pll_state->cfgcr0 & DPLL_CFGCR0_HDMI_MODE) {
 +              link_clock = cnl_calc_wrpll_link(dev_priv, pll_state);
        } else {
 -              link_clock = cfgcr0 & DPLL_CFGCR0_LINK_RATE_MASK;
 +              link_clock = pll_state->cfgcr0 & DPLL_CFGCR0_LINK_RATE_MASK;
  
                switch (link_clock) {
                case DPLL_CFGCR0_LINK_RATE_810:
  }
  
  static void skl_ddi_clock_get(struct intel_encoder *encoder,
 -                              struct intel_crtc_state *pipe_config)
 +                            struct intel_crtc_state *pipe_config)
  {
 -      struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 -      int link_clock = 0;
 -      u32 dpll_ctl1;
 -      enum intel_dpll_id pll_id;
 -
 -      pll_id = intel_get_shared_dpll_id(dev_priv, pipe_config->shared_dpll);
 -
 -      dpll_ctl1 = I915_READ(DPLL_CTRL1);
 +      struct intel_dpll_hw_state *pll_state = &pipe_config->dpll_hw_state;
 +      int link_clock;
  
 -      if (dpll_ctl1 & DPLL_CTRL1_HDMI_MODE(pll_id)) {
 -              link_clock = skl_calc_wrpll_link(dev_priv, pll_id);
 +      /*
 +       * ctrl1 register is already shifted for each pll, just use 0 to get
 +       * the internal shift for each field
 +       */
 +      if (pll_state->ctrl1 & DPLL_CTRL1_HDMI_MODE(0)) {
 +              link_clock = skl_calc_wrpll_link(pll_state);
        } else {
 -              link_clock = dpll_ctl1 & DPLL_CTRL1_LINK_RATE_MASK(pll_id);
 -              link_clock >>= DPLL_CTRL1_LINK_RATE_SHIFT(pll_id);
 +              link_clock = pll_state->ctrl1 & DPLL_CTRL1_LINK_RATE_MASK(0);
 +              link_clock >>= DPLL_CTRL1_LINK_RATE_SHIFT(0);
  
                switch (link_clock) {
                case DPLL_CTRL1_LINK_RATE_810:
@@@ -1617,17 -1643,24 +1617,17 @@@ static void hsw_ddi_clock_get(struct in
        ddi_dotclock_get(pipe_config);
  }
  
 -static int bxt_calc_pll_link(struct intel_crtc_state *crtc_state)
 +static int bxt_calc_pll_link(const struct intel_dpll_hw_state *pll_state)
  {
 -      struct intel_dpll_hw_state *state;
        struct dpll clock;
  
 -      /* For DDI ports we always use a shared PLL. */
 -      if (WARN_ON(!crtc_state->shared_dpll))
 -              return 0;
 -
 -      state = &crtc_state->dpll_hw_state;
 -
        clock.m1 = 2;
 -      clock.m2 = (state->pll0 & PORT_PLL_M2_MASK) << 22;
 -      if (state->pll3 & PORT_PLL_M2_FRAC_ENABLE)
 -              clock.m2 |= state->pll2 & PORT_PLL_M2_FRAC_MASK;
 -      clock.n = (state->pll1 & PORT_PLL_N_MASK) >> PORT_PLL_N_SHIFT;
 -      clock.p1 = (state->ebb0 & PORT_PLL_P1_MASK) >> PORT_PLL_P1_SHIFT;
 -      clock.p2 = (state->ebb0 & PORT_PLL_P2_MASK) >> PORT_PLL_P2_SHIFT;
 +      clock.m2 = (pll_state->pll0 & PORT_PLL_M2_MASK) << 22;
 +      if (pll_state->pll3 & PORT_PLL_M2_FRAC_ENABLE)
 +              clock.m2 |= pll_state->pll2 & PORT_PLL_M2_FRAC_MASK;
 +      clock.n = (pll_state->pll1 & PORT_PLL_N_MASK) >> PORT_PLL_N_SHIFT;
 +      clock.p1 = (pll_state->ebb0 & PORT_PLL_P1_MASK) >> PORT_PLL_P1_SHIFT;
 +      clock.p2 = (pll_state->ebb0 & PORT_PLL_P2_MASK) >> PORT_PLL_P2_SHIFT;
  
        return chv_calc_dpll_params(100000, &clock);
  }
  static void bxt_ddi_clock_get(struct intel_encoder *encoder,
                              struct intel_crtc_state *pipe_config)
  {
 -      pipe_config->port_clock = bxt_calc_pll_link(pipe_config);
 +      pipe_config->port_clock =
 +              bxt_calc_pll_link(&pipe_config->dpll_hw_state);
  
        ddi_dotclock_get(pipe_config);
  }
@@@ -1646,7 -1678,7 +1646,7 @@@ static void intel_ddi_clock_get(struct 
  {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
  
 -      if (IS_ICELAKE(dev_priv))
 +      if (INTEL_GEN(dev_priv) >= 11)
                icl_ddi_clock_get(encoder, pipe_config);
        else if (IS_CANNONLAKE(dev_priv))
                cnl_ddi_clock_get(encoder, pipe_config);
@@@ -1879,7 -1911,7 +1879,7 @@@ bool intel_ddi_connector_get_hw_state(s
                goto out;
        }
  
 -      if (port == PORT_A)
 +      if (HAS_TRANSCODER_EDP(dev_priv) && port == PORT_A)
                cpu_transcoder = TRANSCODER_EDP;
        else
                cpu_transcoder = (enum transcoder) pipe;
@@@ -1941,7 -1973,7 +1941,7 @@@ static void intel_ddi_get_encoder_pipes
        if (!(tmp & DDI_BUF_CTL_ENABLE))
                goto out;
  
 -      if (port == PORT_A) {
 +      if (HAS_TRANSCODER_EDP(dev_priv) && port == PORT_A) {
                tmp = I915_READ(TRANS_DDI_FUNC_CTL(TRANSCODER_EDP));
  
                switch (tmp & TRANS_DDI_EDP_INPUT_MASK) {
@@@ -2043,12 -2075,11 +2043,11 @@@ intel_ddi_main_link_aux_domain(struct i
                                              intel_aux_power_domain(dig_port);
  }
  
- static u64 intel_ddi_get_power_domains(struct intel_encoder *encoder,
-                                      struct intel_crtc_state *crtc_state)
+ static void intel_ddi_get_power_domains(struct intel_encoder *encoder,
+                                       struct intel_crtc_state *crtc_state)
  {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        struct intel_digital_port *dig_port;
-       u64 domains;
  
        /*
         * TODO: Add support for MST encoders. Atm, the following should never
         * hook.
         */
        if (WARN_ON(intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)))
-               return 0;
+               return;
  
        dig_port = enc_to_dig_port(&encoder->base);
-       domains = BIT_ULL(dig_port->ddi_io_power_domain);
+       intel_display_power_get(dev_priv, dig_port->ddi_io_power_domain);
  
        /*
         * AUX power is only needed for (e)DP mode, and for HDMI mode on TC
         */
        if (intel_crtc_has_dp_encoder(crtc_state) ||
            intel_port_is_tc(dev_priv, encoder->port))
-               domains |= BIT_ULL(intel_ddi_main_link_aux_domain(dig_port));
+               intel_display_power_get(dev_priv,
+                                       intel_ddi_main_link_aux_domain(dig_port));
  
        /*
         * VDSC power is needed when DSC is enabled
         */
        if (crtc_state->dsc_params.compression_enable)
-               domains |= BIT_ULL(intel_dsc_power_domain(crtc_state));
-       return domains;
+               intel_display_power_get(dev_priv,
+                                       intel_dsc_power_domain(crtc_state));
  }
  
  void intel_ddi_enable_pipe_clock(const struct intel_crtc_state *crtc_state)
@@@ -2193,7 -2224,7 +2192,7 @@@ u8 intel_ddi_dp_voltage_max(struct inte
        enum port port = encoder->port;
        int n_entries;
  
 -      if (IS_ICELAKE(dev_priv)) {
 +      if (INTEL_GEN(dev_priv) >= 11) {
                if (intel_port_is_combophy(dev_priv, port))
                        icl_get_combo_buf_trans(dev_priv, port, encoder->type,
                                                intel_dp->link_rate, &n_entries);
@@@ -2285,13 -2316,13 +2284,13 @@@ static void cnl_ddi_vswing_program(stru
        /* Program PORT_TX_DW4 */
        /* We cannot write to GRP. It would overrite individual loadgen */
        for (ln = 0; ln < 4; ln++) {
 -              val = I915_READ(CNL_PORT_TX_DW4_LN(port, ln));
 +              val = I915_READ(CNL_PORT_TX_DW4_LN(ln, port));
                val &= ~(POST_CURSOR_1_MASK | POST_CURSOR_2_MASK |
                         CURSOR_COEFF_MASK);
                val |= POST_CURSOR_1(ddi_translations[level].dw4_post_cursor_1);
                val |= POST_CURSOR_2(ddi_translations[level].dw4_post_cursor_2);
                val |= CURSOR_COEFF(ddi_translations[level].dw4_cursor_coeff);
 -              I915_WRITE(CNL_PORT_TX_DW4_LN(port, ln), val);
 +              I915_WRITE(CNL_PORT_TX_DW4_LN(ln, port), val);
        }
  
        /* Program PORT_TX_DW5 */
@@@ -2347,14 -2378,14 +2346,14 @@@ static void cnl_ddi_vswing_sequence(str
         * > 6 GHz (LN0=0, LN1=0, LN2=0, LN3=0)
         */
        for (ln = 0; ln <= 3; ln++) {
 -              val = I915_READ(CNL_PORT_TX_DW4_LN(port, ln));
 +              val = I915_READ(CNL_PORT_TX_DW4_LN(ln, port));
                val &= ~LOADGEN_SELECT;
  
                if ((rate <= 600000 && width == 4 && ln >= 1)  ||
                    (rate <= 600000 && width < 4 && (ln == 1 || ln == 2))) {
                        val |= LOADGEN_SELECT;
                }
 -              I915_WRITE(CNL_PORT_TX_DW4_LN(port, ln), val);
 +              I915_WRITE(CNL_PORT_TX_DW4_LN(ln, port), val);
        }
  
        /* 3. Set PORT_CL_DW5 SUS Clock Config to 11b */
@@@ -2416,13 -2447,13 +2415,13 @@@ static void icl_ddi_combo_vswing_progra
        /* Program PORT_TX_DW4 */
        /* We cannot write to GRP. It would overwrite individual loadgen. */
        for (ln = 0; ln <= 3; ln++) {
 -              val = I915_READ(ICL_PORT_TX_DW4_LN(port, ln));
 +              val = I915_READ(ICL_PORT_TX_DW4_LN(ln, port));
                val &= ~(POST_CURSOR_1_MASK | POST_CURSOR_2_MASK |
                         CURSOR_COEFF_MASK);
                val |= POST_CURSOR_1(ddi_translations[level].dw4_post_cursor_1);
                val |= POST_CURSOR_2(ddi_translations[level].dw4_post_cursor_2);
                val |= CURSOR_COEFF(ddi_translations[level].dw4_cursor_coeff);
 -              I915_WRITE(ICL_PORT_TX_DW4_LN(port, ln), val);
 +              I915_WRITE(ICL_PORT_TX_DW4_LN(ln, port), val);
        }
  
        /* Program PORT_TX_DW7 */
@@@ -2473,14 -2504,14 +2472,14 @@@ static void icl_combo_phy_ddi_vswing_se
         * > 6 GHz (LN0=0, LN1=0, LN2=0, LN3=0)
         */
        for (ln = 0; ln <= 3; ln++) {
 -              val = I915_READ(ICL_PORT_TX_DW4_LN(port, ln));
 +              val = I915_READ(ICL_PORT_TX_DW4_LN(ln, port));
                val &= ~LOADGEN_SELECT;
  
                if ((rate <= 600000 && width == 4 && ln >= 1) ||
                    (rate <= 600000 && width < 4 && (ln == 1 || ln == 2))) {
                        val |= LOADGEN_SELECT;
                }
 -              I915_WRITE(ICL_PORT_TX_DW4_LN(port, ln), val);
 +              I915_WRITE(ICL_PORT_TX_DW4_LN(ln, port), val);
        }
  
        /* 3. Set PORT_CL_DW5 SUS Clock Config to 11b */
@@@ -2523,33 -2554,33 +2522,33 @@@ static void icl_mg_phy_ddi_vswing_seque
  
        /* Set MG_TX_LINK_PARAMS cri_use_fs32 to 0. */
        for (ln = 0; ln < 2; ln++) {
 -              val = I915_READ(MG_TX1_LINK_PARAMS(port, ln));
 +              val = I915_READ(MG_TX1_LINK_PARAMS(ln, port));
                val &= ~CRI_USE_FS32;
 -              I915_WRITE(MG_TX1_LINK_PARAMS(port, ln), val);
 +              I915_WRITE(MG_TX1_LINK_PARAMS(ln, port), val);
  
 -              val = I915_READ(MG_TX2_LINK_PARAMS(port, ln));
 +              val = I915_READ(MG_TX2_LINK_PARAMS(ln, port));
                val &= ~CRI_USE_FS32;
 -              I915_WRITE(MG_TX2_LINK_PARAMS(port, ln), val);
 +              I915_WRITE(MG_TX2_LINK_PARAMS(ln, port), val);
        }
  
        /* Program MG_TX_SWINGCTRL with values from vswing table */
        for (ln = 0; ln < 2; ln++) {
 -              val = I915_READ(MG_TX1_SWINGCTRL(port, ln));
 +              val = I915_READ(MG_TX1_SWINGCTRL(ln, port));
                val &= ~CRI_TXDEEMPH_OVERRIDE_17_12_MASK;
                val |= CRI_TXDEEMPH_OVERRIDE_17_12(
                        ddi_translations[level].cri_txdeemph_override_17_12);
 -              I915_WRITE(MG_TX1_SWINGCTRL(port, ln), val);
 +              I915_WRITE(MG_TX1_SWINGCTRL(ln, port), val);
  
 -              val = I915_READ(MG_TX2_SWINGCTRL(port, ln));
 +              val = I915_READ(MG_TX2_SWINGCTRL(ln, port));
                val &= ~CRI_TXDEEMPH_OVERRIDE_17_12_MASK;
                val |= CRI_TXDEEMPH_OVERRIDE_17_12(
                        ddi_translations[level].cri_txdeemph_override_17_12);
 -              I915_WRITE(MG_TX2_SWINGCTRL(port, ln), val);
 +              I915_WRITE(MG_TX2_SWINGCTRL(ln, port), val);
        }
  
        /* Program MG_TX_DRVCTRL with values from vswing table */
        for (ln = 0; ln < 2; ln++) {
 -              val = I915_READ(MG_TX1_DRVCTRL(port, ln));
 +              val = I915_READ(MG_TX1_DRVCTRL(ln, port));
                val &= ~(CRI_TXDEEMPH_OVERRIDE_11_6_MASK |
                         CRI_TXDEEMPH_OVERRIDE_5_0_MASK);
                val |= CRI_TXDEEMPH_OVERRIDE_5_0(
                        CRI_TXDEEMPH_OVERRIDE_11_6(
                                ddi_translations[level].cri_txdeemph_override_11_6) |
                        CRI_TXDEEMPH_OVERRIDE_EN;
 -              I915_WRITE(MG_TX1_DRVCTRL(port, ln), val);
 +              I915_WRITE(MG_TX1_DRVCTRL(ln, port), val);
  
 -              val = I915_READ(MG_TX2_DRVCTRL(port, ln));
 +              val = I915_READ(MG_TX2_DRVCTRL(ln, port));
                val &= ~(CRI_TXDEEMPH_OVERRIDE_11_6_MASK |
                         CRI_TXDEEMPH_OVERRIDE_5_0_MASK);
                val |= CRI_TXDEEMPH_OVERRIDE_5_0(
                        CRI_TXDEEMPH_OVERRIDE_11_6(
                                ddi_translations[level].cri_txdeemph_override_11_6) |
                        CRI_TXDEEMPH_OVERRIDE_EN;
 -              I915_WRITE(MG_TX2_DRVCTRL(port, ln), val);
 +              I915_WRITE(MG_TX2_DRVCTRL(ln, port), val);
  
                /* FIXME: Program CRI_LOADGEN_SEL after the spec is updated */
        }
         * values from table for which TX1 and TX2 enabled.
         */
        for (ln = 0; ln < 2; ln++) {
 -              val = I915_READ(MG_CLKHUB(port, ln));
 +              val = I915_READ(MG_CLKHUB(ln, port));
                if (link_clock < 300000)
                        val |= CFG_LOW_RATE_LKREN_EN;
                else
                        val &= ~CFG_LOW_RATE_LKREN_EN;
 -              I915_WRITE(MG_CLKHUB(port, ln), val);
 +              I915_WRITE(MG_CLKHUB(ln, port), val);
        }
  
        /* Program the MG_TX_DCC<LN, port being used> based on the link frequency */
        for (ln = 0; ln < 2; ln++) {
 -              val = I915_READ(MG_TX1_DCC(port, ln));
 +              val = I915_READ(MG_TX1_DCC(ln, port));
                val &= ~CFG_AMI_CK_DIV_OVERRIDE_VAL_MASK;
                if (link_clock <= 500000) {
                        val &= ~CFG_AMI_CK_DIV_OVERRIDE_EN;
                        val |= CFG_AMI_CK_DIV_OVERRIDE_EN |
                                CFG_AMI_CK_DIV_OVERRIDE_VAL(1);
                }
 -              I915_WRITE(MG_TX1_DCC(port, ln), val);
 +              I915_WRITE(MG_TX1_DCC(ln, port), val);
  
 -              val = I915_READ(MG_TX2_DCC(port, ln));
 +              val = I915_READ(MG_TX2_DCC(ln, port));
                val &= ~CFG_AMI_CK_DIV_OVERRIDE_VAL_MASK;
                if (link_clock <= 500000) {
                        val &= ~CFG_AMI_CK_DIV_OVERRIDE_EN;
                        val |= CFG_AMI_CK_DIV_OVERRIDE_EN |
                                CFG_AMI_CK_DIV_OVERRIDE_VAL(1);
                }
 -              I915_WRITE(MG_TX2_DCC(port, ln), val);
 +              I915_WRITE(MG_TX2_DCC(ln, port), val);
        }
  
        /* Program MG_TX_PISO_READLOAD with values from vswing table */
        for (ln = 0; ln < 2; ln++) {
 -              val = I915_READ(MG_TX1_PISO_READLOAD(port, ln));
 +              val = I915_READ(MG_TX1_PISO_READLOAD(ln, port));
                val |= CRI_CALCINIT;
 -              I915_WRITE(MG_TX1_PISO_READLOAD(port, ln), val);
 +              I915_WRITE(MG_TX1_PISO_READLOAD(ln, port), val);
  
 -              val = I915_READ(MG_TX2_PISO_READLOAD(port, ln));
 +              val = I915_READ(MG_TX2_PISO_READLOAD(ln, port));
                val |= CRI_CALCINIT;
 -              I915_WRITE(MG_TX2_PISO_READLOAD(port, ln), val);
 +              I915_WRITE(MG_TX2_PISO_READLOAD(ln, port), val);
        }
  }
  
@@@ -2666,7 -2697,7 +2665,7 @@@ u32 bxt_signal_levels(struct intel_dp *
        struct intel_encoder *encoder = &dport->base;
        int level = intel_ddi_dp_level(intel_dp);
  
 -      if (IS_ICELAKE(dev_priv))
 +      if (INTEL_GEN(dev_priv) >= 11)
                icl_ddi_vswing_sequence(encoder, intel_dp->link_rate,
                                        level, encoder->type);
        else if (IS_CANNONLAKE(dev_priv))
@@@ -2793,10 -2824,10 +2792,10 @@@ void icl_sanitize_encoder_pll_mapping(s
                                return;
                }
                /*
-                * DSI ports should have their DDI clock ungated when disabled
-                * and gated when enabled.
+                * For DSI we keep the ddi clocks gated
+                * except during enable/disable sequence.
                 */
-               ddi_clk_needed = !encoder->base.crtc;
+               ddi_clk_needed = false;
        }
  
        val = I915_READ(DPCLKA_CFGCR0_ICL);
@@@ -2835,7 -2866,7 +2834,7 @@@ static void intel_ddi_clk_select(struc
  
        mutex_lock(&dev_priv->dpll_lock);
  
 -      if (IS_ICELAKE(dev_priv)) {
 +      if (INTEL_GEN(dev_priv) >= 11) {
                if (!intel_port_is_combophy(dev_priv, port))
                        I915_WRITE(DDI_CLK_SEL(port),
                                   icl_pll_to_ddi_clk_sel(encoder, crtc_state));
@@@ -2877,7 -2908,7 +2876,7 @@@ static void intel_ddi_clk_disable(struc
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        enum port port = encoder->port;
  
 -      if (IS_ICELAKE(dev_priv)) {
 +      if (INTEL_GEN(dev_priv) >= 11) {
                if (!intel_port_is_combophy(dev_priv, port))
                        I915_WRITE(DDI_CLK_SEL(port), DDI_CLK_SEL_NONE);
        } else if (IS_CANNONLAKE(dev_priv)) {
@@@ -2896,7 -2927,7 +2895,7 @@@ static void icl_enable_phy_clock_gating
        struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
        enum port port = dig_port->base.port;
        enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
 -      i915_reg_t mg_regs[2] = { MG_DP_MODE(port, 0), MG_DP_MODE(port, 1) };
 +      i915_reg_t mg_regs[2] = { MG_DP_MODE(0, port), MG_DP_MODE(1, port) };
        u32 val;
        int i;
  
@@@ -2967,8 -2998,8 +2966,8 @@@ static void icl_program_mg_dp_mode(stru
        if (tc_port == PORT_TC_NONE || intel_dig_port->tc_type == TC_PORT_TBT)
                return;
  
 -      ln0 = I915_READ(MG_DP_MODE(port, 0));
 -      ln1 = I915_READ(MG_DP_MODE(port, 1));
 +      ln0 = I915_READ(MG_DP_MODE(0, port));
 +      ln1 = I915_READ(MG_DP_MODE(1, port));
  
        switch (intel_dig_port->tc_type) {
        case TC_PORT_TYPEC:
                return;
        }
  
 -      I915_WRITE(MG_DP_MODE(port, 0), ln0);
 -      I915_WRITE(MG_DP_MODE(port, 1), ln1);
 +      I915_WRITE(MG_DP_MODE(0, port), ln0);
 +      I915_WRITE(MG_DP_MODE(1, port), ln1);
  }
  
  static void intel_dp_sink_set_fec_ready(struct intel_dp *intel_dp,
@@@ -3046,7 -3077,7 +3045,7 @@@ static void intel_ddi_enable_fec(struc
        val |= DP_TP_CTL_FEC_ENABLE;
        I915_WRITE(DP_TP_CTL(port), val);
  
 -      if (intel_wait_for_register(dev_priv, DP_TP_STATUS(port),
 +      if (intel_wait_for_register(&dev_priv->uncore, DP_TP_STATUS(port),
                                    DP_TP_STATUS_FEC_ENABLE_LIVE,
                                    DP_TP_STATUS_FEC_ENABLE_LIVE,
                                    1))
@@@ -3094,7 -3125,7 +3093,7 @@@ static void intel_ddi_pre_enable_dp(str
        icl_program_mg_dp_mode(dig_port);
        icl_disable_phy_clock_gating(dig_port);
  
 -      if (IS_ICELAKE(dev_priv))
 +      if (INTEL_GEN(dev_priv) >= 11)
                icl_ddi_vswing_sequence(encoder, crtc_state->port_clock,
                                        level, encoder->type);
        else if (IS_CANNONLAKE(dev_priv))
@@@ -3143,7 -3174,7 +3142,7 @@@ static void intel_ddi_pre_enable_hdmi(s
        icl_program_mg_dp_mode(dig_port);
        icl_disable_phy_clock_gating(dig_port);
  
 -      if (IS_ICELAKE(dev_priv))
 +      if (INTEL_GEN(dev_priv) >= 11)
                icl_ddi_vswing_sequence(encoder, crtc_state->port_clock,
                                        level, INTEL_OUTPUT_HDMI);
        else if (IS_CANNONLAKE(dev_priv))
@@@ -3524,9 -3555,7 +3523,9 @@@ static void intel_ddi_update_pipe_dp(st
  {
        struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
  
 -      intel_psr_enable(intel_dp, crtc_state);
 +      intel_ddi_set_pipe_settings(crtc_state);
 +
 +      intel_psr_update(intel_dp, crtc_state);
        intel_edp_drrs_enable(intel_dp, crtc_state);
  
        intel_panel_update_backlight(encoder, crtc_state, conn_state);
@@@ -3681,7 -3710,7 +3680,7 @@@ static bool intel_ddi_is_audio_enabled(
  void intel_ddi_compute_min_voltage_level(struct drm_i915_private *dev_priv,
                                         struct intel_crtc_state *crtc_state)
  {
 -      if (IS_ICELAKE(dev_priv) && crtc_state->port_clock > 594000)
 +      if (INTEL_GEN(dev_priv) >= 11 && crtc_state->port_clock > 594000)
                crtc_state->min_voltage_level = 1;
        else if (IS_CANNONLAKE(dev_priv) && crtc_state->port_clock > 594000)
                crtc_state->min_voltage_level = 2;
@@@ -3734,10 -3763,7 +3733,10 @@@ void intel_ddi_get_config(struct intel_
                pipe_config->has_hdmi_sink = true;
                intel_dig_port = enc_to_dig_port(&encoder->base);
  
 -              if (intel_dig_port->infoframe_enabled(encoder, pipe_config))
 +              pipe_config->infoframes.enable |=
 +                      intel_hdmi_infoframes_enabled(encoder, pipe_config);
 +
 +              if (pipe_config->infoframes.enable)
                        pipe_config->has_infoframe = true;
  
                if (temp & TRANS_DDI_HDMI_SCRAMBLING)
                        bxt_ddi_phy_get_lane_lat_optim_mask(encoder);
  
        intel_ddi_compute_min_voltage_level(dev_priv, pipe_config);
 +
 +      intel_hdmi_read_gcp_infoframe(encoder, pipe_config);
 +
 +      intel_read_infoframe(encoder, pipe_config,
 +                           HDMI_INFOFRAME_TYPE_AVI,
 +                           &pipe_config->infoframes.avi);
 +      intel_read_infoframe(encoder, pipe_config,
 +                           HDMI_INFOFRAME_TYPE_SPD,
 +                           &pipe_config->infoframes.spd);
 +      intel_read_infoframe(encoder, pipe_config,
 +                           HDMI_INFOFRAME_TYPE_VENDOR,
 +                           &pipe_config->infoframes.hdmi);
  }
  
  static enum intel_output_type
@@@ -3841,7 -3855,7 +3840,7 @@@ static int intel_ddi_compute_config(str
        enum port port = encoder->port;
        int ret;
  
 -      if (port == PORT_A)
 +      if (HAS_TRANSCODER_EDP(dev_priv) && port == PORT_A)
                pipe_config->cpu_transcoder = TRANSCODER_EDP;
  
        if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_HDMI))
@@@ -3943,7 -3957,15 +3942,7 @@@ static int modeset_pipe(struct drm_crt
                goto out;
        }
  
 -      crtc_state->mode_changed = true;
 -
 -      ret = drm_atomic_add_affected_connectors(state, crtc);
 -      if (ret)
 -              goto out;
 -
 -      ret = drm_atomic_add_affected_planes(state, crtc);
 -      if (ret)
 -              goto out;
 +      crtc_state->connectors_changed = true;
  
        ret = drm_atomic_commit(state);
  out:
index 8576a7f799f2e0e91230bfc43cf9b3c457956c78,421aac80a83815b9c1cfa40a7142e171cfd8bcd5..c2c1b9ac6984c1a51b6ce190ceca8b401a1e9f9d
@@@ -595,7 -595,7 +595,7 @@@ i9xx_select_p2_div(const struct intel_l
                   const struct intel_crtc_state *crtc_state,
                   int target)
  {
 -      struct drm_device *dev = crtc_state->base.crtc->dev;
 +      struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
  
        if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) {
                /*
                 * We haven't figured out how to reliably set up different
                 * single/dual channel state, if we even can.
                 */
 -              if (intel_is_dual_link_lvds(dev))
 +              if (intel_is_dual_link_lvds(dev_priv))
                        return limit->p2.p2_fast;
                else
                        return limit->p2.p2_slow;
@@@ -951,15 -951,14 +951,15 @@@ chv_find_best_dpll(const struct intel_l
        return found;
  }
  
 -bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state, int target_clock,
 +bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state,
                        struct dpll *best_clock)
  {
        int refclk = 100000;
        const struct intel_limit *limit = &intel_limits_bxt;
  
        return chv_find_best_dpll(limit, crtc_state,
 -                                target_clock, refclk, NULL, best_clock);
 +                                crtc_state->port_clock, refclk,
 +                                NULL, best_clock);
  }
  
  bool intel_crtc_active(struct intel_crtc *crtc)
@@@ -1040,7 -1039,7 +1040,7 @@@ intel_wait_for_pipe_off(const struct in
                i915_reg_t reg = PIPECONF(cpu_transcoder);
  
                /* Wait for the Pipe State to go off */
 -              if (intel_wait_for_register(dev_priv,
 +              if (intel_wait_for_register(&dev_priv->uncore,
                                            reg, I965_PIPECONF_ACTIVE, 0,
                                            100))
                        WARN(1, "pipe_off wait timed out\n");
@@@ -1346,7 -1345,7 +1346,7 @@@ static void _vlv_enable_pll(struct inte
        POSTING_READ(DPLL(pipe));
        udelay(150);
  
 -      if (intel_wait_for_register(dev_priv,
 +      if (intel_wait_for_register(&dev_priv->uncore,
                                    DPLL(pipe),
                                    DPLL_LOCK_VLV,
                                    DPLL_LOCK_VLV,
@@@ -1399,7 -1398,7 +1399,7 @@@ static void _chv_enable_pll(struct inte
        I915_WRITE(DPLL(pipe), pipe_config->dpll_hw_state.dpll);
  
        /* Check PLL is locked */
 -      if (intel_wait_for_register(dev_priv,
 +      if (intel_wait_for_register(&dev_priv->uncore,
                                    DPLL(pipe), DPLL_LOCK_VLV, DPLL_LOCK_VLV,
                                    1))
                DRM_ERROR("PLL %d failed to lock\n", pipe);
@@@ -1442,12 -1441,17 +1442,12 @@@ static void chv_enable_pll(struct intel
        }
  }
  
 -static int intel_num_dvo_pipes(struct drm_i915_private *dev_priv)
 +static bool i9xx_has_pps(struct drm_i915_private *dev_priv)
  {
 -      struct intel_crtc *crtc;
 -      int count = 0;
 -
 -      for_each_intel_crtc(&dev_priv->drm, crtc) {
 -              count += crtc->base.state->active &&
 -                      intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DVO);
 -      }
 +      if (IS_I830(dev_priv))
 +              return false;
  
 -      return count;
 +      return IS_PINEVIEW(dev_priv) || IS_MOBILE(dev_priv);
  }
  
  static void i9xx_enable_pll(struct intel_crtc *crtc,
        assert_pipe_disabled(dev_priv, crtc->pipe);
  
        /* PLL is protected by panel, make sure we can write it */
 -      if (IS_MOBILE(dev_priv) && !IS_I830(dev_priv))
 +      if (i9xx_has_pps(dev_priv))
                assert_panel_unlocked(dev_priv, crtc->pipe);
  
 -      /* Enable DVO 2x clock on both PLLs if necessary */
 -      if (IS_I830(dev_priv) && intel_num_dvo_pipes(dev_priv) > 0) {
 -              /*
 -               * It appears to be important that we don't enable this
 -               * for the current pipe before otherwise configuring the
 -               * PLL. No idea how this should be handled if multiple
 -               * DVO outputs are enabled simultaneosly.
 -               */
 -              dpll |= DPLL_DVO_2X_MODE;
 -              I915_WRITE(DPLL(!crtc->pipe),
 -                         I915_READ(DPLL(!crtc->pipe)) | DPLL_DVO_2X_MODE);
 -      }
 -
        /*
         * Apparently we need to have VGA mode enabled prior to changing
         * the P1/P2 dividers. Otherwise the DPLL will keep using the old
         * dividers, even though the register value does change.
         */
 -      I915_WRITE(reg, 0);
 -
 +      I915_WRITE(reg, dpll & ~DPLL_VGA_MODE_DIS);
        I915_WRITE(reg, dpll);
  
        /* Wait for the clocks to stabilize. */
@@@ -1502,6 -1520,16 +1502,6 @@@ static void i9xx_disable_pll(const stru
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum pipe pipe = crtc->pipe;
  
 -      /* Disable DVO 2x clock on both PLLs if necessary */
 -      if (IS_I830(dev_priv) &&
 -          intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DVO) &&
 -          !intel_num_dvo_pipes(dev_priv)) {
 -              I915_WRITE(DPLL(PIPE_B),
 -                         I915_READ(DPLL(PIPE_B)) & ~DPLL_DVO_2X_MODE);
 -              I915_WRITE(DPLL(PIPE_A),
 -                         I915_READ(DPLL(PIPE_A)) & ~DPLL_DVO_2X_MODE);
 -      }
 -
        /* Don't disable pipe or pipe PLLs if needed */
        if (IS_I830(dev_priv))
                return;
@@@ -1580,7 -1608,7 +1580,7 @@@ void vlv_wait_port_ready(struct drm_i91
                BUG();
        }
  
 -      if (intel_wait_for_register(dev_priv,
 +      if (intel_wait_for_register(&dev_priv->uncore,
                                    dpll_reg, port_mask, expected_mask,
                                    1000))
                WARN(1, "timed out waiting for port %c ready: got 0x%x, expected 0x%x\n",
@@@ -1630,18 -1658,17 +1630,18 @@@ static void ironlake_enable_pch_transco
        }
  
        val &= ~TRANS_INTERLACE_MASK;
 -      if ((pipeconf_val & PIPECONF_INTERLACE_MASK) == PIPECONF_INTERLACED_ILK)
 +      if ((pipeconf_val & PIPECONF_INTERLACE_MASK) == PIPECONF_INTERLACED_ILK) {
                if (HAS_PCH_IBX(dev_priv) &&
                    intel_crtc_has_type(crtc_state, INTEL_OUTPUT_SDVO))
                        val |= TRANS_LEGACY_INTERLACED_ILK;
                else
                        val |= TRANS_INTERLACED;
 -      else
 +      } else {
                val |= TRANS_PROGRESSIVE;
 +      }
  
        I915_WRITE(reg, val | TRANS_ENABLE);
 -      if (intel_wait_for_register(dev_priv,
 +      if (intel_wait_for_register(&dev_priv->uncore,
                                    reg, TRANS_STATE_ENABLE, TRANS_STATE_ENABLE,
                                    100))
                DRM_ERROR("failed to enable transcoder %c\n", pipe_name(pipe));
@@@ -1671,7 -1698,7 +1671,7 @@@ static void lpt_enable_pch_transcoder(s
                val |= TRANS_PROGRESSIVE;
  
        I915_WRITE(LPT_TRANSCONF, val);
 -      if (intel_wait_for_register(dev_priv,
 +      if (intel_wait_for_register(&dev_priv->uncore,
                                    LPT_TRANSCONF,
                                    TRANS_STATE_ENABLE,
                                    TRANS_STATE_ENABLE,
@@@ -1697,7 -1724,7 +1697,7 @@@ static void ironlake_disable_pch_transc
        val &= ~TRANS_ENABLE;
        I915_WRITE(reg, val);
        /* wait for PCH transcoder off, transcoder state */
 -      if (intel_wait_for_register(dev_priv,
 +      if (intel_wait_for_register(&dev_priv->uncore,
                                    reg, TRANS_STATE_ENABLE, 0,
                                    50))
                DRM_ERROR("failed to disable transcoder %c\n", pipe_name(pipe));
@@@ -1719,7 -1746,7 +1719,7 @@@ void lpt_disable_pch_transcoder(struct 
        val &= ~TRANS_ENABLE;
        I915_WRITE(LPT_TRANSCONF, val);
        /* wait for PCH transcoder off, transcoder state */
 -      if (intel_wait_for_register(dev_priv,
 +      if (intel_wait_for_register(&dev_priv->uncore,
                                    LPT_TRANSCONF, TRANS_STATE_ENABLE, 0,
                                    50))
                DRM_ERROR("Failed to disable PCH transcoder\n");
@@@ -1803,8 -1830,6 +1803,8 @@@ static void intel_enable_pipe(const str
                /* FIXME: assert CPU port conditions for SNB+ */
        }
  
 +      trace_intel_pipe_enable(dev_priv, pipe);
 +
        reg = PIPECONF(cpu_transcoder);
        val = I915_READ(reg);
        if (val & PIPECONF_ENABLE) {
@@@ -1844,8 -1869,6 +1844,8 @@@ static void intel_disable_pipe(const st
         */
        assert_planes_disabled(crtc);
  
 +      trace_intel_pipe_disable(dev_priv, pipe);
 +
        reg = PIPECONF(cpu_transcoder);
        val = I915_READ(reg);
        if ((val & PIPECONF_ENABLE) == 0)
@@@ -2654,24 -2677,6 +2654,24 @@@ int skl_format_to_fourcc(int format, bo
                return DRM_FORMAT_RGB565;
        case PLANE_CTL_FORMAT_NV12:
                return DRM_FORMAT_NV12;
 +      case PLANE_CTL_FORMAT_P010:
 +              return DRM_FORMAT_P010;
 +      case PLANE_CTL_FORMAT_P012:
 +              return DRM_FORMAT_P012;
 +      case PLANE_CTL_FORMAT_P016:
 +              return DRM_FORMAT_P016;
 +      case PLANE_CTL_FORMAT_Y210:
 +              return DRM_FORMAT_Y210;
 +      case PLANE_CTL_FORMAT_Y212:
 +              return DRM_FORMAT_Y212;
 +      case PLANE_CTL_FORMAT_Y216:
 +              return DRM_FORMAT_Y216;
 +      case PLANE_CTL_FORMAT_Y410:
 +              return DRM_FORMAT_XVYU2101010;
 +      case PLANE_CTL_FORMAT_Y412:
 +              return DRM_FORMAT_XVYU12_16161616;
 +      case PLANE_CTL_FORMAT_Y416:
 +              return DRM_FORMAT_XVYU16161616;
        default:
        case PLANE_CTL_FORMAT_XRGB_8888:
                if (rgb_order) {
                        return DRM_FORMAT_XBGR2101010;
                else
                        return DRM_FORMAT_XRGB2101010;
 +      case PLANE_CTL_FORMAT_XRGB_16161616F:
 +              if (rgb_order) {
 +                      if (alpha)
 +                              return DRM_FORMAT_ABGR16161616F;
 +                      else
 +                              return DRM_FORMAT_XBGR16161616F;
 +              } else {
 +                      if (alpha)
 +                              return DRM_FORMAT_ARGB16161616F;
 +                      else
 +                              return DRM_FORMAT_XRGB16161616F;
 +              }
        }
  }
  
@@@ -2832,7 -2825,8 +2832,7 @@@ static void intel_plane_disable_noatomi
        if (plane->id == PLANE_PRIMARY)
                intel_pre_disable_primary_noatomic(&crtc->base);
  
 -      trace_intel_disable_plane(&plane->base, crtc);
 -      plane->disable_plane(plane, crtc_state);
 +      intel_disable_plane(plane, crtc_state);
  }
  
  static void
@@@ -3182,7 -3176,7 +3182,7 @@@ int skl_check_plane_surface(struct inte
         * Handle the AUX surface first since
         * the main surface setup depends on it.
         */
 -      if (fb->format->format == DRM_FORMAT_NV12) {
 +      if (is_planar_yuv_format(fb->format->format)) {
                ret = skl_check_nv12_aux_surface(plane_state);
                if (ret)
                        return ret;
@@@ -3236,10 -3230,9 +3236,10 @@@ static u32 i9xx_plane_ctl_crtc(const st
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        u32 dspcntr = 0;
  
 -      dspcntr |= DISPPLANE_GAMMA_ENABLE;
 +      if (crtc_state->gamma_enable)
 +              dspcntr |= DISPPLANE_GAMMA_ENABLE;
  
 -      if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
 +      if (crtc_state->csc_enable)
                dspcntr |= DISPPLANE_PIPE_CSC_ENABLE;
  
        if (INTEL_GEN(dev_priv) < 5)
@@@ -3466,7 -3459,7 +3466,7 @@@ static void i9xx_disable_plane(struct i
         *
         * On pre-g4x there is no way to gamma correct the
         * pipe bottom color but we'll keep on doing this
 -       * anyway.
 +       * anyway so that the crtc state readout works correctly.
         */
        dspcntr = i9xx_plane_ctl_crtc(crtc_state);
  
@@@ -3597,12 -3590,6 +3597,12 @@@ static u32 skl_plane_ctl_format(u32 pix
                return PLANE_CTL_FORMAT_XRGB_2101010;
        case DRM_FORMAT_XBGR2101010:
                return PLANE_CTL_ORDER_RGBX | PLANE_CTL_FORMAT_XRGB_2101010;
 +      case DRM_FORMAT_XBGR16161616F:
 +      case DRM_FORMAT_ABGR16161616F:
 +              return PLANE_CTL_FORMAT_XRGB_16161616F | PLANE_CTL_ORDER_RGBX;
 +      case DRM_FORMAT_XRGB16161616F:
 +      case DRM_FORMAT_ARGB16161616F:
 +              return PLANE_CTL_FORMAT_XRGB_16161616F;
        case DRM_FORMAT_YUYV:
                return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_YUYV;
        case DRM_FORMAT_YVYU:
                return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_VYUY;
        case DRM_FORMAT_NV12:
                return PLANE_CTL_FORMAT_NV12;
 +      case DRM_FORMAT_P010:
 +              return PLANE_CTL_FORMAT_P010;
 +      case DRM_FORMAT_P012:
 +              return PLANE_CTL_FORMAT_P012;
 +      case DRM_FORMAT_P016:
 +              return PLANE_CTL_FORMAT_P016;
 +      case DRM_FORMAT_Y210:
 +              return PLANE_CTL_FORMAT_Y210;
 +      case DRM_FORMAT_Y212:
 +              return PLANE_CTL_FORMAT_Y212;
 +      case DRM_FORMAT_Y216:
 +              return PLANE_CTL_FORMAT_Y216;
 +      case DRM_FORMAT_XVYU2101010:
 +              return PLANE_CTL_FORMAT_Y410;
 +      case DRM_FORMAT_XVYU12_16161616:
 +              return PLANE_CTL_FORMAT_Y412;
 +      case DRM_FORMAT_XVYU16161616:
 +              return PLANE_CTL_FORMAT_Y416;
        default:
                MISSING_CASE(pixel_format);
        }
@@@ -3741,11 -3710,8 +3741,11 @@@ u32 skl_plane_ctl_crtc(const struct int
        if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
                return plane_ctl;
  
 -      plane_ctl |= PLANE_CTL_PIPE_GAMMA_ENABLE;
 -      plane_ctl |= PLANE_CTL_PIPE_CSC_ENABLE;
 +      if (crtc_state->gamma_enable)
 +              plane_ctl |= PLANE_CTL_PIPE_GAMMA_ENABLE;
 +
 +      if (crtc_state->csc_enable)
 +              plane_ctl |= PLANE_CTL_PIPE_CSC_ENABLE;
  
        return plane_ctl;
  }
@@@ -3797,11 -3763,8 +3797,11 @@@ u32 glk_plane_color_ctl_crtc(const stru
        if (INTEL_GEN(dev_priv) >= 11)
                return plane_color_ctl;
  
 -      plane_color_ctl |= PLANE_COLOR_PIPE_GAMMA_ENABLE;
 -      plane_color_ctl |= PLANE_COLOR_PIPE_CSC_ENABLE;
 +      if (crtc_state->gamma_enable)
 +              plane_color_ctl |= PLANE_COLOR_PIPE_GAMMA_ENABLE;
 +
 +      if (crtc_state->csc_enable)
 +              plane_color_ctl |= PLANE_COLOR_PIPE_CSC_ENABLE;
  
        return plane_color_ctl;
  }
  u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state,
                        const struct intel_plane_state *plane_state)
  {
 +      struct drm_i915_private *dev_priv =
 +              to_i915(plane_state->base.plane->dev);
        const struct drm_framebuffer *fb = plane_state->base.fb;
        struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
        u32 plane_color_ctl = 0;
        plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE;
        plane_color_ctl |= glk_plane_color_ctl_alpha(plane_state);
  
 -      if (fb->format->is_yuv && !icl_is_hdr_plane(plane)) {
 +      if (fb->format->is_yuv && !icl_is_hdr_plane(dev_priv, plane->id)) {
                if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
                        plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709;
                else
@@@ -3960,6 -3921,9 +3960,6 @@@ void intel_finish_reset(struct drm_i915
                 * The display has been reset as well,
                 * so need a full re-initialization.
                 */
 -              intel_runtime_pm_disable_interrupts(dev_priv);
 -              intel_runtime_pm_enable_interrupts(dev_priv);
 -
                intel_pps_unlock_regs_wa(dev_priv);
                intel_modeset_init_hw(dev);
                intel_init_clock_gating(dev_priv);
@@@ -3999,13 -3963,13 +3999,13 @@@ static void icl_set_pipe_chicken(struc
         * and rounding for per-pixel values 00 and 0xff
         */
        tmp |= PER_PIXEL_ALPHA_BYPASS_EN;
 -
        /*
 -       * W/A for underruns with linear/X-tiled with
 -       * WM1+ disabled.
 +       * Display WA # 1605353570: icl
 +       * Set the pixel rounding bit to 1 for allowing
 +       * passthrough of Frame buffer pixels unmodified
 +       * across pipe
         */
 -      tmp |= PM_FILL_MAINTAIN_DBUF_FULLNESS;
 -
 +      tmp |= PIXEL_ROUNDING_TRUNC_FB_PASSTHRU;
        I915_WRITE(PIPE_CHICKEN(pipe), tmp);
  }
  
@@@ -4044,6 -4008,16 +4044,6 @@@ static void intel_update_pipe_config(co
                        ironlake_pfit_disable(old_crtc_state);
        }
  
 -      /*
 -       * We don't (yet) allow userspace to control the pipe background color,
 -       * so force it to black, but apply pipe gamma and CSC so that its
 -       * handling will match how we program our planes.
 -       */
 -      if (INTEL_GEN(dev_priv) >= 9)
 -              I915_WRITE(SKL_BOTTOM_COLOR(crtc->pipe),
 -                         SKL_BOTTOM_COLOR_GAMMA_ENABLE |
 -                         SKL_BOTTOM_COLOR_CSC_ENABLE);
 -
        if (INTEL_GEN(dev_priv) >= 11)
                icl_set_pipe_chicken(crtc);
  }
@@@ -5062,19 -5036,19 +5062,19 @@@ skl_update_scaler(struct intel_crtc_sta
                return 0;
        }
  
 -      if (format && format->format == DRM_FORMAT_NV12 &&
 +      if (format && is_planar_yuv_format(format->format) &&
            (src_h < SKL_MIN_YUV_420_SRC_H || src_w < SKL_MIN_YUV_420_SRC_W)) {
 -              DRM_DEBUG_KMS("NV12: src dimensions not met\n");
 +              DRM_DEBUG_KMS("Planar YUV: src dimensions not met\n");
                return -EINVAL;
        }
  
        /* range checks */
        if (src_w < SKL_MIN_SRC_W || src_h < SKL_MIN_SRC_H ||
            dst_w < SKL_MIN_DST_W || dst_h < SKL_MIN_DST_H ||
 -          (IS_GEN(dev_priv, 11) &&
 +          (INTEL_GEN(dev_priv) >= 11 &&
             (src_w > ICL_MAX_SRC_W || src_h > ICL_MAX_SRC_H ||
              dst_w > ICL_MAX_DST_W || dst_h > ICL_MAX_DST_H)) ||
 -          (!IS_GEN(dev_priv, 11) &&
 +          (INTEL_GEN(dev_priv) < 11 &&
             (src_w > SKL_MAX_SRC_W || src_h > SKL_MAX_SRC_H ||
              dst_w > SKL_MAX_DST_W || dst_h > SKL_MAX_DST_H))) {
                DRM_DEBUG_KMS("scaler_user index %u.%u: src %ux%u dst %ux%u "
@@@ -5131,15 -5105,14 +5131,15 @@@ static int skl_update_scaler_plane(stru
  {
        struct intel_plane *intel_plane =
                to_intel_plane(plane_state->base.plane);
 +      struct drm_i915_private *dev_priv = to_i915(intel_plane->base.dev);
        struct drm_framebuffer *fb = plane_state->base.fb;
        int ret;
        bool force_detach = !fb || !plane_state->base.visible;
        bool need_scaler = false;
  
        /* Pre-gen11 and SDR planes always need a scaler for planar formats. */
 -      if (!icl_is_hdr_plane(intel_plane) &&
 -          fb && fb->format->format == DRM_FORMAT_NV12)
 +      if (!icl_is_hdr_plane(dev_priv, intel_plane->id) &&
 +          fb && is_planar_yuv_format(fb->format->format))
                need_scaler = true;
  
        ret = skl_update_scaler(crtc_state, force_detach,
        case DRM_FORMAT_ARGB8888:
        case DRM_FORMAT_XRGB2101010:
        case DRM_FORMAT_XBGR2101010:
 +      case DRM_FORMAT_XBGR16161616F:
 +      case DRM_FORMAT_ABGR16161616F:
 +      case DRM_FORMAT_XRGB16161616F:
 +      case DRM_FORMAT_ARGB16161616F:
        case DRM_FORMAT_YUYV:
        case DRM_FORMAT_YVYU:
        case DRM_FORMAT_UYVY:
        case DRM_FORMAT_VYUY:
        case DRM_FORMAT_NV12:
 +      case DRM_FORMAT_P010:
 +      case DRM_FORMAT_P012:
 +      case DRM_FORMAT_P016:
 +      case DRM_FORMAT_Y210:
 +      case DRM_FORMAT_Y212:
 +      case DRM_FORMAT_Y216:
 +      case DRM_FORMAT_XVYU2101010:
 +      case DRM_FORMAT_XVYU12_16161616:
 +      case DRM_FORMAT_XVYU16161616:
                break;
        default:
                DRM_DEBUG_KMS("[PLANE:%d:%s] FB:%d unsupported scaling format 0x%x\n",
@@@ -5299,7 -5259,7 +5299,7 @@@ void hsw_enable_ips(const struct intel_
                 * and don't wait for vblanks until the end of crtc_enable, then
                 * the HW state readout code will complain that the expected
                 * IPS_CTL value is not the one we read. */
 -              if (intel_wait_for_register(dev_priv,
 +              if (intel_wait_for_register(&dev_priv->uncore,
                                            IPS_CTL, IPS_ENABLE, IPS_ENABLE,
                                            50))
                        DRM_ERROR("Timed out waiting for IPS enable\n");
@@@ -5324,7 -5284,7 +5324,7 @@@ void hsw_disable_ips(const struct intel
                 * 42ms timeout value leads to occasional timeouts so use 100ms
                 * instead.
                 */
 -              if (intel_wait_for_register(dev_priv,
 +              if (intel_wait_for_register(&dev_priv->uncore,
                                            IPS_CTL, IPS_ENABLE, 0,
                                            100))
                        DRM_ERROR("Timed out waiting for IPS disable\n");
@@@ -5643,7 -5603,7 +5643,7 @@@ static void intel_crtc_disable_planes(s
                    !(update_mask & BIT(plane->id)))
                        continue;
  
 -              plane->disable_plane(plane, new_crtc_state);
 +              intel_disable_plane(plane, new_crtc_state);
  
                if (old_plane_state->base.visible)
                        fb_bits |= plane->frontbuffer_bit;
@@@ -5794,14 -5754,6 +5794,14 @@@ static void intel_encoders_update_pipe(
        }
  }
  
 +static void intel_disable_primary_plane(const struct intel_crtc_state *crtc_state)
 +{
 +      struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
 +      struct intel_plane *plane = to_intel_plane(crtc->base.primary);
 +
 +      plane->disable_plane(plane, crtc_state);
 +}
 +
  static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config,
                                 struct drm_atomic_state *old_state)
  {
         */
        intel_color_load_luts(pipe_config);
        intel_color_commit(pipe_config);
 +      /* update DSPCNTR to configure gamma for pipe bottom color */
 +      intel_disable_primary_plane(pipe_config);
  
        if (dev_priv->display.initial_watermarks != NULL)
                dev_priv->display.initial_watermarks(old_intel_state, pipe_config);
@@@ -5997,9 -5947,6 +5997,9 @@@ static void haswell_crtc_enable(struct 
         */
        intel_color_load_luts(pipe_config);
        intel_color_commit(pipe_config);
 +      /* update DSPCNTR to configure gamma/csc for pipe bottom color */
 +      if (INTEL_GEN(dev_priv) < 9)
 +              intel_disable_primary_plane(pipe_config);
  
        if (INTEL_GEN(dev_priv) >= 11)
                icl_set_pipe_chicken(intel_crtc);
@@@ -6180,7 -6127,7 +6180,7 @@@ bool intel_port_is_combophy(struct drm_
        if (port == PORT_NONE)
                return false;
  
 -      if (IS_ICELAKE(dev_priv))
 +      if (INTEL_GEN(dev_priv) >= 11)
                return port <= PORT_B;
  
        return false;
  
  bool intel_port_is_tc(struct drm_i915_private *dev_priv, enum port port)
  {
 -      if (IS_ICELAKE(dev_priv))
 +      if (INTEL_GEN(dev_priv) >= 11)
                return port >= PORT_C && port <= PORT_F;
  
        return false;
@@@ -6357,8 -6304,6 +6357,8 @@@ static void valleyview_crtc_enable(stru
  
        intel_color_load_luts(pipe_config);
        intel_color_commit(pipe_config);
 +      /* update DSPCNTR to configure gamma for pipe bottom color */
 +      intel_disable_primary_plane(pipe_config);
  
        dev_priv->display.initial_watermarks(old_intel_state,
                                             pipe_config);
@@@ -6416,8 -6361,6 +6416,8 @@@ static void i9xx_crtc_enable(struct int
  
        intel_color_load_luts(pipe_config);
        intel_color_commit(pipe_config);
 +      /* update DSPCNTR to configure gamma for pipe bottom color */
 +      intel_disable_primary_plane(pipe_config);
  
        if (dev_priv->display.initial_watermarks != NULL)
                dev_priv->display.initial_watermarks(old_intel_state,
@@@ -6800,13 -6743,7 +6800,13 @@@ static bool hsw_compute_ips_config(stru
        if (!hsw_crtc_state_ips_capable(crtc_state))
                return false;
  
 -      if (crtc_state->ips_force_disable)
 +      /*
 +       * When IPS gets enabled, the pipe CRC changes. Since IPS gets
 +       * enabled and disabled dynamically based on package C states,
 +       * user space can't make reliable use of the CRCs, so let's just
 +       * completely disable it.
 +       */
 +      if (crtc_state->crc_enabled)
                return false;
  
        /* IPS should be fine as long as at least one plane is enabled. */
@@@ -6881,7 -6818,8 +6881,7 @@@ static void intel_crtc_compute_pixel_ra
  static int intel_crtc_compute_config(struct intel_crtc *crtc,
                                     struct intel_crtc_state *pipe_config)
  {
 -      struct drm_device *dev = crtc->base.dev;
 -      struct drm_i915_private *dev_priv = to_i915(dev);
 +      struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
        int clock_limit = dev_priv->max_dotclk_freq;
  
                }
  
                if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_LVDS) &&
 -                  intel_is_dual_link_lvds(dev)) {
 +                  intel_is_dual_link_lvds(dev_priv)) {
                        DRM_DEBUG_KMS("Odd pipe source width not supported with dual link LVDS\n");
                        return -EINVAL;
                }
@@@ -7548,19 -7486,7 +7548,19 @@@ static void i8xx_compute_dpll(struct in
                        dpll |= PLL_P2_DIVIDE_BY_4;
        }
  
 -      if (!IS_I830(dev_priv) &&
 +      /*
 +       * Bspec:
 +       * "[Almador Errata}: For the correct operation of the muxed DVO pins
 +       *  (GDEVSELB/I2Cdata, GIRDBY/I2CClk) and (GFRAMEB/DVI_Data,
 +       *  GTRDYB/DVI_Clk): Bit 31 (DPLL VCO Enable) and Bit 30 (2X Clock
 +       *  Enable) must be set to “1” in both the DPLL A Control Register
 +       *  (06014h-06017h) and DPLL B Control Register (06018h-0601Bh)."
 +       *
 +       * For simplicity We simply keep both bits always enabled in
 +       * both DPLLS. The spec says we should disable the DVO 2X clock
 +       * when not needed, but this seems to work fine in practice.
 +       */
 +      if (IS_I830(dev_priv) ||
            intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DVO))
                dpll |= DPLL_DVO_2X_MODE;
  
@@@ -7768,16 -7694,13 +7768,16 @@@ static void i9xx_set_pipeconf(const str
                        pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
                else
                        pipeconf |= PIPECONF_INTERLACE_W_SYNC_SHIFT;
 -      } else
 +      } else {
                pipeconf |= PIPECONF_PROGRESSIVE;
 +      }
  
        if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
             crtc_state->limited_color_range)
                pipeconf |= PIPECONF_COLOR_RANGE_SELECT;
  
 +      pipeconf |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode);
 +
        I915_WRITE(PIPECONF(crtc->pipe), pipeconf);
        POSTING_READ(PIPECONF(crtc->pipe));
  }
@@@ -7821,7 -7744,8 +7821,7 @@@ static int i8xx_crtc_compute_clock(stru
  static int g4x_crtc_compute_clock(struct intel_crtc *crtc,
                                  struct intel_crtc_state *crtc_state)
  {
 -      struct drm_device *dev = crtc->base.dev;
 -      struct drm_i915_private *dev_priv = to_i915(dev);
 +      struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        const struct intel_limit *limit;
        int refclk = 96000;
  
                        DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", refclk);
                }
  
 -              if (intel_is_dual_link_lvds(dev))
 +              if (intel_is_dual_link_lvds(dev_priv))
                        limit = &intel_limits_g4x_dual_channel_lvds;
                else
                        limit = &intel_limits_g4x_single_channel_lvds;
@@@ -7970,22 -7894,14 +7970,22 @@@ static int vlv_crtc_compute_clock(struc
        return 0;
  }
  
 +static bool i9xx_has_pfit(struct drm_i915_private *dev_priv)
 +{
 +      if (IS_I830(dev_priv))
 +              return false;
 +
 +      return INTEL_GEN(dev_priv) >= 4 ||
 +              IS_PINEVIEW(dev_priv) || IS_MOBILE(dev_priv);
 +}
 +
  static void i9xx_get_pfit_config(struct intel_crtc *crtc,
                                 struct intel_crtc_state *pipe_config)
  {
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        u32 tmp;
  
 -      if (INTEL_GEN(dev_priv) <= 3 &&
 -          (IS_I830(dev_priv) || !IS_MOBILE(dev_priv)))
 +      if (!i9xx_has_pfit(dev_priv))
                return;
  
        tmp = I915_READ(PFIT_CONTROL);
@@@ -8192,24 -8108,6 +8192,24 @@@ static void intel_get_crtc_ycbcr_config
        pipe_config->output_format = output;
  }
  
 +static void i9xx_get_pipe_color_config(struct intel_crtc_state *crtc_state)
 +{
 +      struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
 +      struct intel_plane *plane = to_intel_plane(crtc->base.primary);
 +      struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 +      enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
 +      u32 tmp;
 +
 +      tmp = I915_READ(DSPCNTR(i9xx_plane));
 +
 +      if (tmp & DISPPLANE_GAMMA_ENABLE)
 +              crtc_state->gamma_enable = true;
 +
 +      if (!HAS_GMCH(dev_priv) &&
 +          tmp & DISPPLANE_PIPE_CSC_ENABLE)
 +              crtc_state->csc_enable = true;
 +}
 +
  static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
                                 struct intel_crtc_state *pipe_config)
  {
            (tmp & PIPECONF_COLOR_RANGE_SELECT))
                pipe_config->limited_color_range = true;
  
 +      pipe_config->gamma_mode = (tmp & PIPECONF_GAMMA_MODE_MASK_I9XX) >>
 +              PIPECONF_GAMMA_MODE_SHIFT;
 +
 +      if (IS_CHERRYVIEW(dev_priv))
 +              pipe_config->cgm_mode = I915_READ(CGM_PIPE_MODE(crtc->pipe));
 +
 +      i9xx_get_pipe_color_config(pipe_config);
 +
        if (INTEL_GEN(dev_priv) < 4)
                pipe_config->double_wide = tmp & PIPECONF_DOUBLE_WIDE;
  
        }
        pipe_config->dpll_hw_state.dpll = I915_READ(DPLL(crtc->pipe));
        if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv)) {
 -              /*
 -               * DPLL_DVO_2X_MODE must be enabled for both DPLLs
 -               * on 830. Filter it out here so that we don't
 -               * report errors due to that.
 -               */
 -              if (IS_I830(dev_priv))
 -                      pipe_config->dpll_hw_state.dpll &= ~DPLL_DVO_2X_MODE;
 -
                pipe_config->dpll_hw_state.fp0 = I915_READ(FP0(crtc->pipe));
                pipe_config->dpll_hw_state.fp1 = I915_READ(FP1(crtc->pipe));
        } else {
@@@ -8794,8 -8692,6 +8794,8 @@@ static void ironlake_set_pipeconf(cons
        if (crtc_state->limited_color_range)
                val |= PIPECONF_COLOR_RANGE_SELECT;
  
 +      val |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode);
 +
        I915_WRITE(PIPECONF(pipe), val);
        POSTING_READ(PIPECONF(pipe));
  }
@@@ -8876,11 -8772,13 +8876,11 @@@ static bool ironlake_needs_fb_cb_tune(s
        return i9xx_dpll_compute_m(dpll) < factor * dpll->n;
  }
  
 -static void ironlake_compute_dpll(struct intel_crtc *intel_crtc,
 +static void ironlake_compute_dpll(struct intel_crtc *crtc,
                                  struct intel_crtc_state *crtc_state,
                                  struct dpll *reduced_clock)
  {
 -      struct drm_crtc *crtc = &intel_crtc->base;
 -      struct drm_device *dev = crtc->dev;
 -      struct drm_i915_private *dev_priv = to_i915(dev);
 +      struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        u32 dpll, fp, fp2;
        int factor;
  
        if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) {
                if ((intel_panel_use_ssc(dev_priv) &&
                     dev_priv->vbt.lvds_ssc_freq == 100000) ||
 -                  (HAS_PCH_IBX(dev_priv) && intel_is_dual_link_lvds(dev)))
 +                  (HAS_PCH_IBX(dev_priv) &&
 +                   intel_is_dual_link_lvds(dev_priv)))
                        factor = 25;
 -      } else if (crtc_state->sdvo_tv_clock)
 +      } else if (crtc_state->sdvo_tv_clock) {
                factor = 20;
 +      }
  
        fp = i9xx_dpll_compute_fp(&crtc_state->dpll);
  
  static int ironlake_crtc_compute_clock(struct intel_crtc *crtc,
                                       struct intel_crtc_state *crtc_state)
  {
 -      struct drm_device *dev = crtc->base.dev;
 -      struct drm_i915_private *dev_priv = to_i915(dev);
 +      struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        const struct intel_limit *limit;
        int refclk = 120000;
  
                        refclk = dev_priv->vbt.lvds_ssc_freq;
                }
  
 -              if (intel_is_dual_link_lvds(dev)) {
 +              if (intel_is_dual_link_lvds(dev_priv)) {
                        if (refclk == 100000)
                                limit = &intel_limits_ironlake_dual_lvds_100m;
                        else
  
        ironlake_compute_dpll(crtc, crtc_state, NULL);
  
 -      if (!intel_get_shared_dpll(crtc, crtc_state, NULL)) {
 +      if (!intel_get_shared_dpll(crtc_state, NULL)) {
                DRM_DEBUG_KMS("failed to find PLL for pipe %c\n",
                              pipe_name(crtc->pipe));
                return -EINVAL;
@@@ -9329,13 -9226,6 +9329,13 @@@ static bool ironlake_get_pipe_config(st
        if (tmp & PIPECONF_COLOR_RANGE_SELECT)
                pipe_config->limited_color_range = true;
  
 +      pipe_config->gamma_mode = (tmp & PIPECONF_GAMMA_MODE_MASK_ILK) >>
 +              PIPECONF_GAMMA_MODE_SHIFT;
 +
 +      pipe_config->csc_mode = I915_READ(PIPE_CSC_MODE(crtc->pipe));
 +
 +      i9xx_get_pipe_color_config(pipe_config);
 +
        if (I915_READ(PCH_TRANSCONF(crtc->pipe)) & TRANS_ENABLE) {
                struct intel_shared_dpll *pll;
                enum intel_dpll_id pll_id;
@@@ -9481,8 -9371,7 +9481,8 @@@ static void hsw_disable_lcpll(struct dr
        I915_WRITE(LCPLL_CTL, val);
        POSTING_READ(LCPLL_CTL);
  
 -      if (intel_wait_for_register(dev_priv, LCPLL_CTL, LCPLL_PLL_LOCK, 0, 1))
 +      if (intel_wait_for_register(&dev_priv->uncore,
 +                                  LCPLL_CTL, LCPLL_PLL_LOCK, 0, 1))
                DRM_ERROR("LCPLL still locked\n");
  
        val = hsw_read_dcomp(dev_priv);
@@@ -9520,7 -9409,7 +9520,7 @@@ static void hsw_restore_lcpll(struct dr
         * Make sure we're not on PC8 state before disabling PC8, otherwise
         * we'll hang the machine. To prevent PC8 state, just enable force_wake.
         */
 -      intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
 +      intel_uncore_forcewake_get(&dev_priv->uncore, FORCEWAKE_ALL);
  
        if (val & LCPLL_POWER_DOWN_ALLOW) {
                val &= ~LCPLL_POWER_DOWN_ALLOW;
        val &= ~LCPLL_PLL_DISABLE;
        I915_WRITE(LCPLL_CTL, val);
  
 -      if (intel_wait_for_register(dev_priv,
 +      if (intel_wait_for_register(&dev_priv->uncore,
                                    LCPLL_CTL, LCPLL_PLL_LOCK, LCPLL_PLL_LOCK,
                                    5))
                DRM_ERROR("LCPLL not locked yet\n");
                        DRM_ERROR("Switching back to LCPLL failed\n");
        }
  
 -      intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
 +      intel_uncore_forcewake_put(&dev_priv->uncore, FORCEWAKE_ALL);
  
        intel_update_cdclk(dev_priv);
        intel_dump_cdclk_state(&dev_priv->cdclk.hw, "Current CDCLK");
@@@ -9621,11 -9510,11 +9621,11 @@@ static int haswell_crtc_compute_clock(s
                to_intel_atomic_state(crtc_state->base.state);
  
        if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI) ||
 -          IS_ICELAKE(dev_priv)) {
 +          INTEL_GEN(dev_priv) >= 11) {
                struct intel_encoder *encoder =
                        intel_get_crtc_new_encoder(state, crtc_state);
  
 -              if (!intel_get_shared_dpll(crtc, crtc_state, encoder)) {
 +              if (!intel_get_shared_dpll(crtc_state, encoder)) {
                        DRM_DEBUG_KMS("failed to find PLL for pipe %c\n",
                                      pipe_name(crtc->pipe));
                        return -EINVAL;
@@@ -9663,6 -9552,9 +9663,6 @@@ static void icelake_get_ddi_pll(struct 
                temp = I915_READ(DPCLKA_CFGCR0_ICL) &
                       DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port);
                id = temp >> DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(port);
 -
 -              if (WARN_ON(!intel_dpll_is_combophy(id)))
 -                      return;
        } else if (intel_port_is_tc(dev_priv, port)) {
                id = icl_tc_port_to_pll_id(intel_port_to_tc(dev_priv, port));
        } else {
@@@ -9756,18 -9648,15 +9756,18 @@@ static bool hsw_get_transcoder_state(st
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
        enum intel_display_power_domain power_domain;
 -      unsigned long panel_transcoder_mask = BIT(TRANSCODER_EDP);
 +      unsigned long panel_transcoder_mask = 0;
        unsigned long enabled_panel_transcoders = 0;
        enum transcoder panel_transcoder;
        u32 tmp;
  
 -      if (IS_ICELAKE(dev_priv))
 +      if (INTEL_GEN(dev_priv) >= 11)
                panel_transcoder_mask |=
                        BIT(TRANSCODER_DSI_0) | BIT(TRANSCODER_DSI_1);
  
 +      if (HAS_TRANSCODER_EDP(dev_priv))
 +              panel_transcoder_mask |= BIT(TRANSCODER_EDP);
 +
        /*
         * The pipe->transcoder mapping is fixed with the exception of the eDP
         * and DSI transcoders handled below.
@@@ -9897,7 -9786,7 +9897,7 @@@ static void haswell_get_ddi_port_state(
  
        port = (tmp & TRANS_DDI_PORT_MASK) >> TRANS_DDI_PORT_SHIFT;
  
 -      if (IS_ICELAKE(dev_priv))
 +      if (INTEL_GEN(dev_priv) >= 11)
                icelake_get_ddi_pll(dev_priv, port, pipe_config);
        else if (IS_CANNONLAKE(dev_priv))
                cannonlake_get_ddi_pll(dev_priv, port, pipe_config);
@@@ -9960,7 -9849,7 +9960,7 @@@ static bool haswell_get_pipe_config(str
                goto out;
  
        if (!transcoder_is_dsi(pipe_config->cpu_transcoder) ||
 -          IS_ICELAKE(dev_priv)) {
 +          INTEL_GEN(dev_priv) >= 11) {
                haswell_get_ddi_port_state(crtc, pipe_config);
                intel_get_pipe_timings(crtc, pipe_config);
        }
        intel_get_pipe_src_size(crtc, pipe_config);
        intel_get_crtc_ycbcr_config(crtc, pipe_config);
  
 -      pipe_config->gamma_mode =
 -              I915_READ(GAMMA_MODE(crtc->pipe)) & GAMMA_MODE_MODE_MASK;
 +      pipe_config->gamma_mode = I915_READ(GAMMA_MODE(crtc->pipe));
 +
 +      pipe_config->csc_mode = I915_READ(PIPE_CSC_MODE(crtc->pipe));
 +
 +      if (INTEL_GEN(dev_priv) >= 9) {
 +              u32 tmp = I915_READ(SKL_BOTTOM_COLOR(crtc->pipe));
 +
 +              if (tmp & SKL_BOTTOM_COLOR_GAMMA_ENABLE)
 +                      pipe_config->gamma_enable = true;
 +
 +              if (tmp & SKL_BOTTOM_COLOR_CSC_ENABLE)
 +                      pipe_config->csc_enable = true;
 +      } else {
 +              i9xx_get_pipe_color_config(pipe_config);
 +      }
  
        power_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe);
        if (intel_display_power_get_if_enabled(dev_priv, power_domain)) {
@@@ -10154,12 -10030,7 +10154,12 @@@ i845_cursor_max_stride(struct intel_pla
  
  static u32 i845_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)
  {
 -      return CURSOR_GAMMA_ENABLE;
 +      u32 cntl = 0;
 +
 +      if (crtc_state->gamma_enable)
 +              cntl |= CURSOR_GAMMA_ENABLE;
 +
 +      return cntl;
  }
  
  static u32 i845_cursor_ctl(const struct intel_crtc_state *crtc_state,
@@@ -10313,10 -10184,9 +10313,10 @@@ static u32 i9xx_cursor_ctl_crtc(const s
        if (INTEL_GEN(dev_priv) >= 11)
                return cntl;
  
 -      cntl |= MCURSOR_GAMMA_ENABLE;
 +      if (crtc_state->gamma_enable)
 +              cntl = MCURSOR_GAMMA_ENABLE;
  
 -      if (HAS_DDI(dev_priv))
 +      if (crtc_state->csc_enable)
                cntl |= MCURSOR_PIPE_CSC_ENABLE;
  
        if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv))
@@@ -11264,7 -11134,7 +11264,7 @@@ static int icl_check_nv12_planes(struc
                }
  
                if (!linked_state) {
 -                      DRM_DEBUG_KMS("Need %d free Y planes for NV12\n",
 +                      DRM_DEBUG_KMS("Need %d free Y planes for planar YUV\n",
                                      hweight8(crtc_state->nv12_planes));
  
                        return -EINVAL;
@@@ -11305,11 -11175,16 +11305,11 @@@ static int intel_crtc_atomic_check(stru
                        return ret;
        }
  
 -      if (mode_changed || crtc_state->color_mgmt_changed) {
 +      if (mode_changed || pipe_config->update_pipe ||
 +          crtc_state->color_mgmt_changed) {
                ret = intel_color_check(pipe_config);
                if (ret)
                        return ret;
 -
 -              /*
 -               * Changing color management on Intel hardware is
 -               * handled as part of planes update.
 -               */
 -              crtc_state->planes_changed = true;
        }
  
        ret = 0;
@@@ -11480,16 -11355,6 +11480,16 @@@ intel_dump_m_n_config(struct intel_crtc
                      m_n->link_m, m_n->link_n, m_n->tu);
  }
  
 +static void
 +intel_dump_infoframe(struct drm_i915_private *dev_priv,
 +                   const union hdmi_infoframe *frame)
 +{
 +      if ((drm_debug & DRM_UT_KMS) == 0)
 +              return;
 +
 +      hdmi_infoframe_log(KERN_DEBUG, dev_priv->drm.dev, frame);
 +}
 +
  #define OUTPUT_TYPE(x) [INTEL_OUTPUT_ ## x] = #x
  
  static const char * const output_type_str[] = {
@@@ -11593,22 -11458,6 +11593,22 @@@ static void intel_dump_pipe_config(stru
        DRM_DEBUG_KMS("audio: %i, infoframes: %i\n",
                      pipe_config->has_audio, pipe_config->has_infoframe);
  
 +      DRM_DEBUG_KMS("infoframes enabled: 0x%x\n",
 +                    pipe_config->infoframes.enable);
 +
 +      if (pipe_config->infoframes.enable &
 +          intel_hdmi_infoframe_enable(HDMI_PACKET_TYPE_GENERAL_CONTROL))
 +              DRM_DEBUG_KMS("GCP: 0x%x\n", pipe_config->infoframes.gcp);
 +      if (pipe_config->infoframes.enable &
 +          intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_AVI))
 +              intel_dump_infoframe(dev_priv, &pipe_config->infoframes.avi);
 +      if (pipe_config->infoframes.enable &
 +          intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_SPD))
 +              intel_dump_infoframe(dev_priv, &pipe_config->infoframes.spd);
 +      if (pipe_config->infoframes.enable &
 +          intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_VENDOR))
 +              intel_dump_infoframe(dev_priv, &pipe_config->infoframes.hdmi);
 +
        DRM_DEBUG_KMS("requested mode:\n");
        drm_mode_debug_printmodeline(&pipe_config->base.mode);
        DRM_DEBUG_KMS("adjusted mode:\n");
@@@ -11757,7 -11606,7 +11757,7 @@@ clear_intel_crtc_state(struct intel_crt
        saved_state->shared_dpll = crtc_state->shared_dpll;
        saved_state->dpll_hw_state = crtc_state->dpll_hw_state;
        saved_state->pch_pfit.force_thru = crtc_state->pch_pfit.force_thru;
 -      saved_state->ips_force_disable = crtc_state->ips_force_disable;
 +      saved_state->crc_enabled = crtc_state->crc_enabled;
        if (IS_G4X(dev_priv) ||
            IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
                saved_state->wm = crtc_state->wm;
@@@ -11976,37 -11825,6 +11976,37 @@@ intel_compare_link_m_n(const struct int
        return false;
  }
  
 +static bool
 +intel_compare_infoframe(const union hdmi_infoframe *a,
 +                      const union hdmi_infoframe *b)
 +{
 +      return memcmp(a, b, sizeof(*a)) == 0;
 +}
 +
 +static void
 +pipe_config_infoframe_err(struct drm_i915_private *dev_priv,
 +                        bool adjust, const char *name,
 +                        const union hdmi_infoframe *a,
 +                        const union hdmi_infoframe *b)
 +{
 +      if (adjust) {
 +              if ((drm_debug & DRM_UT_KMS) == 0)
 +                      return;
 +
 +              drm_dbg(DRM_UT_KMS, "mismatch in %s infoframe", name);
 +              drm_dbg(DRM_UT_KMS, "expected:");
 +              hdmi_infoframe_log(KERN_DEBUG, dev_priv->drm.dev, a);
 +              drm_dbg(DRM_UT_KMS, "found");
 +              hdmi_infoframe_log(KERN_DEBUG, dev_priv->drm.dev, b);
 +      } else {
 +              drm_err("mismatch in %s infoframe", name);
 +              drm_err("expected:");
 +              hdmi_infoframe_log(KERN_ERR, dev_priv->drm.dev, a);
 +              drm_err("found");
 +              hdmi_infoframe_log(KERN_ERR, dev_priv->drm.dev, b);
 +      }
 +}
 +
  static void __printf(3, 4)
  pipe_config_err(bool adjust, const char *name, const char *format, ...)
  {
@@@ -12190,17 -12008,7 +12190,17 @@@ intel_pipe_config_compare(struct drm_i9
        } \
  } while (0)
  
 -#define PIPE_CONF_QUIRK(quirk)        \
 +#define PIPE_CONF_CHECK_INFOFRAME(name) do { \
 +      if (!intel_compare_infoframe(&current_config->infoframes.name, \
 +                                   &pipe_config->infoframes.name)) { \
 +              pipe_config_infoframe_err(dev_priv, adjust, __stringify(name), \
 +                                        &current_config->infoframes.name, \
 +                                        &pipe_config->infoframes.name); \
 +              ret = false; \
 +      } \
 +} while (0)
 +
 +#define PIPE_CONF_QUIRK(quirk) \
        ((current_config->quirks | pipe_config->quirks) & (quirk))
  
        PIPE_CONF_CHECK_I(cpu_transcoder);
  
                PIPE_CONF_CHECK_I(scaler_state.scaler_id);
                PIPE_CONF_CHECK_CLOCK_FUZZY(pixel_rate);
 +
 +              PIPE_CONF_CHECK_X(gamma_mode);
 +              if (IS_CHERRYVIEW(dev_priv))
 +                      PIPE_CONF_CHECK_X(cgm_mode);
 +              else
 +                      PIPE_CONF_CHECK_X(csc_mode);
 +              PIPE_CONF_CHECK_BOOL(gamma_enable);
 +              PIPE_CONF_CHECK_BOOL(csc_enable);
        }
  
        PIPE_CONF_CHECK_BOOL(double_wide);
  
        PIPE_CONF_CHECK_I(min_voltage_level);
  
 +      PIPE_CONF_CHECK_X(infoframes.enable);
 +      PIPE_CONF_CHECK_X(infoframes.gcp);
 +      PIPE_CONF_CHECK_INFOFRAME(avi);
 +      PIPE_CONF_CHECK_INFOFRAME(spd);
 +      PIPE_CONF_CHECK_INFOFRAME(hdmi);
 +
  #undef PIPE_CONF_CHECK_X
  #undef PIPE_CONF_CHECK_I
  #undef PIPE_CONF_CHECK_BOOL
@@@ -12377,15 -12171,12 +12377,15 @@@ static void verify_wm_state(struct drm_
                            struct drm_crtc_state *new_state)
  {
        struct drm_i915_private *dev_priv = to_i915(crtc->dev);
 -      struct skl_ddb_allocation hw_ddb, *sw_ddb;
 -      struct skl_pipe_wm hw_wm, *sw_wm;
 -      struct skl_plane_wm *hw_plane_wm, *sw_plane_wm;
 +      struct skl_hw_state {
 +              struct skl_ddb_entry ddb_y[I915_MAX_PLANES];
 +              struct skl_ddb_entry ddb_uv[I915_MAX_PLANES];
 +              struct skl_ddb_allocation ddb;
 +              struct skl_pipe_wm wm;
 +      } *hw;
 +      struct skl_ddb_allocation *sw_ddb;
 +      struct skl_pipe_wm *sw_wm;
        struct skl_ddb_entry *hw_ddb_entry, *sw_ddb_entry;
 -      struct skl_ddb_entry hw_ddb_y[I915_MAX_PLANES];
 -      struct skl_ddb_entry hw_ddb_uv[I915_MAX_PLANES];
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        const enum pipe pipe = intel_crtc->pipe;
        int plane, level, max_level = ilk_wm_max_level(dev_priv);
        if (INTEL_GEN(dev_priv) < 9 || !new_state->active)
                return;
  
 -      skl_pipe_wm_get_hw_state(intel_crtc, &hw_wm);
 +      hw = kzalloc(sizeof(*hw), GFP_KERNEL);
 +      if (!hw)
 +              return;
 +
 +      skl_pipe_wm_get_hw_state(intel_crtc, &hw->wm);
        sw_wm = &to_intel_crtc_state(new_state)->wm.skl.optimal;
  
 -      skl_pipe_ddb_get_hw_state(intel_crtc, hw_ddb_y, hw_ddb_uv);
 +      skl_pipe_ddb_get_hw_state(intel_crtc, hw->ddb_y, hw->ddb_uv);
  
 -      skl_ddb_get_hw_state(dev_priv, &hw_ddb);
 +      skl_ddb_get_hw_state(dev_priv, &hw->ddb);
        sw_ddb = &dev_priv->wm.skl_hw.ddb;
  
 -      if (INTEL_GEN(dev_priv) >= 11)
 -              if (hw_ddb.enabled_slices != sw_ddb->enabled_slices)
 -                      DRM_ERROR("mismatch in DBUF Slices (expected %u, got %u)\n",
 -                                sw_ddb->enabled_slices,
 -                                hw_ddb.enabled_slices);
 +      if (INTEL_GEN(dev_priv) >= 11 &&
 +          hw->ddb.enabled_slices != sw_ddb->enabled_slices)
 +              DRM_ERROR("mismatch in DBUF Slices (expected %u, got %u)\n",
 +                        sw_ddb->enabled_slices,
 +                        hw->ddb.enabled_slices);
 +
        /* planes */
        for_each_universal_plane(dev_priv, pipe, plane) {
 -              hw_plane_wm = &hw_wm.planes[plane];
 +              struct skl_plane_wm *hw_plane_wm, *sw_plane_wm;
 +
 +              hw_plane_wm = &hw->wm.planes[plane];
                sw_plane_wm = &sw_wm->planes[plane];
  
                /* Watermarks */
                }
  
                /* DDB */
 -              hw_ddb_entry = &hw_ddb_y[plane];
 +              hw_ddb_entry = &hw->ddb_y[plane];
                sw_ddb_entry = &to_intel_crtc_state(new_state)->wm.skl.plane_ddb_y[plane];
  
                if (!skl_ddb_entry_equal(hw_ddb_entry, sw_ddb_entry)) {
         * once the plane becomes visible, we can skip this check
         */
        if (1) {
 -              hw_plane_wm = &hw_wm.planes[PLANE_CURSOR];
 +              struct skl_plane_wm *hw_plane_wm, *sw_plane_wm;
 +
 +              hw_plane_wm = &hw->wm.planes[PLANE_CURSOR];
                sw_plane_wm = &sw_wm->planes[PLANE_CURSOR];
  
                /* Watermarks */
                }
  
                /* DDB */
 -              hw_ddb_entry = &hw_ddb_y[PLANE_CURSOR];
 +              hw_ddb_entry = &hw->ddb_y[PLANE_CURSOR];
                sw_ddb_entry = &to_intel_crtc_state(new_state)->wm.skl.plane_ddb_y[PLANE_CURSOR];
  
                if (!skl_ddb_entry_equal(hw_ddb_entry, sw_ddb_entry)) {
                                  hw_ddb_entry->start, hw_ddb_entry->end);
                }
        }
 +
 +      kfree(hw);
  }
  
  static void
@@@ -12667,8 -12447,7 +12667,8 @@@ intel_verify_planes(struct intel_atomic
  
        for_each_new_intel_plane_in_state(state, plane,
                                          plane_state, i)
 -              assert_plane(plane, plane_state->base.visible);
 +              assert_plane(plane, plane_state->slave ||
 +                           plane_state->base.visible);
  }
  
  static void
@@@ -13534,7 -13313,7 +13534,7 @@@ static void intel_atomic_commit_tail(st
                 * so enable debugging for the next modeset - and hope we catch
                 * the culprit.
                 */
 -              intel_uncore_arm_unclaimed_mmio_detection(dev_priv);
 +              intel_uncore_arm_unclaimed_mmio_detection(&dev_priv->uncore);
                intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET, wakeref);
        }
  
@@@ -13727,7 -13506,7 +13727,7 @@@ static int do_rps_boost(struct wait_que
         * vblank without our intervention, so leave RPS alone.
         */
        if (!i915_request_started(rq))
 -              gen6_rps_boost(rq, NULL);
 +              gen6_rps_boost(rq);
        i915_request_put(rq);
  
        drm_crtc_vblank_put(wait->crtc);
@@@ -13988,7 -13767,7 +13988,7 @@@ skl_max_scale(const struct intel_crtc_s
         *            or
         *    cdclk/crtc_clock
         */
 -      mult = pixel_format == DRM_FORMAT_NV12 ? 2 : 3;
 +      mult = is_planar_yuv_format(pixel_format) ? 2 : 3;
        tmpclk1 = (1 << 16) * mult - 1;
        tmpclk2 = (1 << 8) * ((max_dotclk << 8) / crtc_clock);
        max_scale = min(tmpclk1, tmpclk2);
@@@ -14260,11 -14039,14 +14260,11 @@@ intel_legacy_cursor_update(struct drm_p
         */
        crtc_state->active_planes = new_crtc_state->active_planes;
  
 -      if (plane->state->visible) {
 -              trace_intel_update_plane(plane, to_intel_crtc(crtc));
 -              intel_plane->update_plane(intel_plane, crtc_state,
 -                                        to_intel_plane_state(plane->state));
 -      } else {
 -              trace_intel_disable_plane(plane, to_intel_crtc(crtc));
 -              intel_plane->disable_plane(intel_plane, crtc_state);
 -      }
 +      if (plane->state->visible)
 +              intel_update_plane(intel_plane, crtc_state,
 +                                 to_intel_plane_state(plane->state));
 +      else
 +              intel_disable_plane(intel_plane, crtc_state);
  
        intel_plane_unpin_fb(to_intel_plane_state(old_plane_state));
  
@@@ -14714,12 -14496,7 +14714,12 @@@ static void intel_setup_outputs(struct 
        if (!HAS_DISPLAY(dev_priv))
                return;
  
 -      if (IS_ICELAKE(dev_priv)) {
 +      if (IS_ELKHARTLAKE(dev_priv)) {
 +              intel_ddi_init(dev_priv, PORT_A);
 +              intel_ddi_init(dev_priv, PORT_B);
 +              intel_ddi_init(dev_priv, PORT_C);
 +              icl_dsi_init(dev_priv);
 +      } else if (INTEL_GEN(dev_priv) >= 11) {
                intel_ddi_init(dev_priv, PORT_A);
                intel_ddi_init(dev_priv, PORT_B);
                intel_ddi_init(dev_priv, PORT_C);
@@@ -15620,8 -15397,6 +15620,8 @@@ int intel_modeset_init(struct drm_devic
        intel_update_czclk(dev_priv);
        intel_modeset_init_hw(dev);
  
 +      intel_hdcp_component_init(dev_priv);
 +
        if (dev_priv->max_cdclk_freq == 0)
                intel_update_max_cdclk(dev_priv);
  
@@@ -15697,7 -15472,7 +15697,7 @@@ void i830_enable_pipe(struct drm_i915_p
                      pipe_name(pipe), clock.vco, clock.dot);
  
        fp = i9xx_dpll_compute_fp(&clock);
 -      dpll = (I915_READ(DPLL(pipe)) & DPLL_DVO_2X_MODE) |
 +      dpll = DPLL_DVO_2X_MODE |
                DPLL_VGA_MODE_DIS |
                ((clock.p1 - 2) << DPLL_FPA01_P1_POST_DIV_SHIFT) |
                PLL_P2_DIVIDE_BY_4 |
@@@ -16211,8 -15986,6 +16211,6 @@@ get_encoder_power_domains(struct drm_i9
        struct intel_encoder *encoder;
  
        for_each_intel_encoder(&dev_priv->drm, encoder) {
-               u64 get_domains;
-               enum intel_display_power_domain domain;
                struct intel_crtc_state *crtc_state;
  
                if (!encoder->get_power_domains)
                        continue;
  
                crtc_state = to_intel_crtc_state(encoder->base.crtc->state);
-               get_domains = encoder->get_power_domains(encoder, crtc_state);
-               for_each_power_domain(domain, get_domains)
-                       intel_display_power_get(dev_priv, domain);
+               encoder->get_power_domains(encoder, crtc_state);
        }
  }
  
@@@ -16483,8 -16254,6 +16479,8 @@@ void intel_modeset_cleanup(struct drm_d
        /* flush any delayed tasks or pending work */
        flush_scheduled_work();
  
 +      intel_hdcp_component_fini(dev_priv);
 +
        drm_mode_config_cleanup(dev);
  
        intel_overlay_cleanup(dev_priv);
@@@ -16531,6 -16300,8 +16527,6 @@@ struct intel_display_error_state 
  
        u32 power_well_driver;
  
 -      int num_transcoders;
 -
        struct intel_cursor_error_state {
                u32 control;
                u32 position;
        } plane[I915_MAX_PIPES];
  
        struct intel_transcoder_error_state {
 +              bool available;
                bool power_domain_on;
                enum transcoder cpu_transcoder;
  
@@@ -16582,8 -16352,6 +16578,8 @@@ intel_display_capture_error_state(struc
        };
        int i;
  
 +      BUILD_BUG_ON(ARRAY_SIZE(transcoders) != ARRAY_SIZE(error->transcoder));
 +
        if (!HAS_DISPLAY(dev_priv))
                return NULL;
  
                        error->pipe[i].stat = I915_READ(PIPESTAT(i));
        }
  
 -      /* Note: this does not include DSI transcoders. */
 -      error->num_transcoders = INTEL_INFO(dev_priv)->num_pipes;
 -      if (HAS_DDI(dev_priv))
 -              error->num_transcoders++; /* Account for eDP. */
 -
 -      for (i = 0; i < error->num_transcoders; i++) {
 +      for (i = 0; i < ARRAY_SIZE(error->transcoder); i++) {
                enum transcoder cpu_transcoder = transcoders[i];
  
 +              if (!INTEL_INFO(dev_priv)->trans_offsets[cpu_transcoder])
 +                      continue;
 +
 +              error->transcoder[i].available = true;
                error->transcoder[i].power_domain_on =
                        __intel_display_power_is_enabled(dev_priv,
                                POWER_DOMAIN_TRANSCODER(cpu_transcoder));
@@@ -16694,10 -16463,7 +16690,10 @@@ intel_display_print_error_state(struct 
                err_printf(m, "  BASE: %08x\n", error->cursor[i].base);
        }
  
 -      for (i = 0; i < error->num_transcoders; i++) {
 +      for (i = 0; i < ARRAY_SIZE(error->transcoder); i++) {
 +              if (!error->transcoder[i].available)
 +                      continue;
 +
                err_printf(m, "CPU transcoder: %s\n",
                           transcoder_name(error->transcoder[i].cpu_transcoder));
                err_printf(m, "  Power: %s\n",
index 72c49070ed14c949a3b1a0eb7510e815eaaa116b,8891f29a8c7fffacad25f29e718376aa164261f7..dfa770da5c724365696ed7cfecf412ea368e61c3
@@@ -949,11 -949,8 +949,11 @@@ static void intel_pps_get_registers(str
        regs->pp_stat = PP_STATUS(pps_idx);
        regs->pp_on = PP_ON_DELAYS(pps_idx);
        regs->pp_off = PP_OFF_DELAYS(pps_idx);
 -      if (!IS_GEN9_LP(dev_priv) && !HAS_PCH_CNP(dev_priv) &&
 -          !HAS_PCH_ICP(dev_priv))
 +
 +      /* Cycle delay moved from PP_DIVISOR to PP_CONTROL */
 +      if (IS_GEN9_LP(dev_priv) || INTEL_PCH_TYPE(dev_priv) >= PCH_CNP)
 +              regs->pp_div = INVALID_MMIO_REG;
 +      else
                regs->pp_div = PP_DIVISOR(pps_idx);
  }
  
@@@ -1723,6 -1720,12 +1723,6 @@@ void intel_dp_compute_rate(struct intel
        }
  }
  
 -struct link_config_limits {
 -      int min_clock, max_clock;
 -      int min_lane_count, max_lane_count;
 -      int min_bpp, max_bpp;
 -};
 -
  static bool intel_dp_source_supports_fec(struct intel_dp *intel_dp,
                                         const struct intel_crtc_state *pipe_config)
  {
@@@ -1785,7 -1788,7 +1785,7 @@@ static int intel_dp_compute_bpp(struct 
  }
  
  /* Adjust link config limits based on compliance test requests. */
 -static void
 +void
  intel_dp_adjust_compliance_config(struct intel_dp *intel_dp,
                                  struct intel_crtc_state *pipe_config,
                                  struct link_config_limits *limits)
@@@ -1856,42 -1859,6 +1856,6 @@@ intel_dp_compute_link_config_wide(struc
        return -EINVAL;
  }
  
- /* Optimize link config in order: max bpp, min lanes, min clock */
- static int
- intel_dp_compute_link_config_fast(struct intel_dp *intel_dp,
-                                 struct intel_crtc_state *pipe_config,
-                                 const struct link_config_limits *limits)
- {
-       struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
-       int bpp, clock, lane_count;
-       int mode_rate, link_clock, link_avail;
-       for (bpp = limits->max_bpp; bpp >= limits->min_bpp; bpp -= 2 * 3) {
-               mode_rate = intel_dp_link_required(adjusted_mode->crtc_clock,
-                                                  bpp);
-               for (lane_count = limits->min_lane_count;
-                    lane_count <= limits->max_lane_count;
-                    lane_count <<= 1) {
-                       for (clock = limits->min_clock; clock <= limits->max_clock; clock++) {
-                               link_clock = intel_dp->common_rates[clock];
-                               link_avail = intel_dp_max_data_rate(link_clock,
-                                                                   lane_count);
-                               if (mode_rate <= link_avail) {
-                                       pipe_config->lane_count = lane_count;
-                                       pipe_config->pipe_bpp = bpp;
-                                       pipe_config->port_clock = link_clock;
-                                       return 0;
-                               }
-                       }
-               }
-       }
-       return -EINVAL;
- }
  static int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 dsc_max_bpc)
  {
        int i, num_bpc;
@@@ -2028,15 -1995,13 +1992,13 @@@ intel_dp_compute_link_config(struct int
        limits.min_bpp = 6 * 3;
        limits.max_bpp = intel_dp_compute_bpp(intel_dp, pipe_config);
  
-       if (intel_dp_is_edp(intel_dp) && intel_dp->edp_dpcd[0] < DP_EDP_14) {
+       if (intel_dp_is_edp(intel_dp)) {
                /*
                 * Use the maximum clock and number of lanes the eDP panel
-                * advertizes being capable of. The eDP 1.3 and earlier panels
-                * are generally designed to support only a single clock and
-                * lane configuration, and typically these values correspond to
-                * the native resolution of the panel. With eDP 1.4 rate select
-                * and DSC, this is decreasingly the case, and we need to be
-                * able to select less than maximum link config.
+                * advertizes being capable of. The panels are generally
+                * designed to support only a single clock and lane
+                * configuration, and typically these values correspond to the
+                * native resolution of the panel.
                 */
                limits.min_lane_count = limits.max_lane_count;
                limits.min_clock = limits.max_clock;
                      intel_dp->common_rates[limits.max_clock],
                      limits.max_bpp, adjusted_mode->crtc_clock);
  
-       if (intel_dp_is_edp(intel_dp))
-               /*
-                * Optimize for fast and narrow. eDP 1.3 section 3.3 and eDP 1.4
-                * section A.1: "It is recommended that the minimum number of
-                * lanes be used, using the minimum link rate allowed for that
-                * lane configuration."
-                *
-                * Note that we use the max clock and lane count for eDP 1.3 and
-                * earlier, and fast vs. wide is irrelevant.
-                */
-               ret = intel_dp_compute_link_config_fast(intel_dp, pipe_config,
-                                                       &limits);
-       else
-               /* Optimize for slow and wide. */
-               ret = intel_dp_compute_link_config_wide(intel_dp, pipe_config,
-                                                       &limits);
+       /*
+        * Optimize for slow and wide. This is the place to add alternative
+        * optimization policy.
+        */
+       ret = intel_dp_compute_link_config_wide(intel_dp, pipe_config, &limits);
  
        /* enable compression if the mode doesn't fit available BW */
        DRM_DEBUG_KMS("Force DSC en = %d\n", intel_dp->force_dsc_en);
        return 0;
  }
  
 +bool intel_dp_limited_color_range(const struct intel_crtc_state *crtc_state,
 +                                const struct drm_connector_state *conn_state)
 +{
 +      const struct intel_digital_connector_state *intel_conn_state =
 +              to_intel_digital_connector_state(conn_state);
 +      const struct drm_display_mode *adjusted_mode =
 +              &crtc_state->base.adjusted_mode;
 +
 +      if (intel_conn_state->broadcast_rgb == INTEL_BROADCAST_RGB_AUTO) {
 +              /*
 +               * See:
 +               * CEA-861-E - 5.1 Default Encoding Parameters
 +               * VESA DisplayPort Ver.1.2a - 5.1.1.1 Video Colorimetry
 +               */
 +              return crtc_state->pipe_bpp != 18 &&
 +                      drm_default_rgb_quant_range(adjusted_mode) ==
 +                      HDMI_QUANTIZATION_RANGE_LIMITED;
 +      } else {
 +              return intel_conn_state->broadcast_rgb ==
 +                      INTEL_BROADCAST_RGB_LIMITED;
 +      }
 +}
 +
  int
  intel_dp_compute_config(struct intel_encoder *encoder,
                        struct intel_crtc_state *pipe_config,
        if (ret < 0)
                return ret;
  
 -      if (intel_conn_state->broadcast_rgb == INTEL_BROADCAST_RGB_AUTO) {
 -              /*
 -               * See:
 -               * CEA-861-E - 5.1 Default Encoding Parameters
 -               * VESA DisplayPort Ver.1.2a - 5.1.1.1 Video Colorimetry
 -               */
 -              pipe_config->limited_color_range =
 -                      pipe_config->pipe_bpp != 18 &&
 -                      drm_default_rgb_quant_range(adjusted_mode) ==
 -                      HDMI_QUANTIZATION_RANGE_LIMITED;
 -      } else {
 -              pipe_config->limited_color_range =
 -                      intel_conn_state->broadcast_rgb == INTEL_BROADCAST_RGB_LIMITED;
 -      }
 +      pipe_config->limited_color_range =
 +              intel_dp_limited_color_range(pipe_config, conn_state);
  
        if (!pipe_config->dsc_params.compression_enable)
                intel_link_compute_m_n(pipe_config->pipe_bpp,
@@@ -2353,7 -2296,7 +2304,7 @@@ static void wait_panel_status(struct in
                        I915_READ(pp_stat_reg),
                        I915_READ(pp_ctrl_reg));
  
 -      if (intel_wait_for_register(dev_priv,
 +      if (intel_wait_for_register(&dev_priv->uncore,
                                    pp_stat_reg, mask, value,
                                    5000))
                DRM_ERROR("Panel status timeout: status %08x control %08x\n",
@@@ -3942,7 -3885,7 +3893,7 @@@ void intel_dp_set_idle_link_train(struc
        if (port == PORT_A)
                return;
  
 -      if (intel_wait_for_register(dev_priv,DP_TP_STATUS(port),
 +      if (intel_wait_for_register(&dev_priv->uncore, DP_TP_STATUS(port),
                                    DP_TP_STATUS_IDLE_DONE,
                                    DP_TP_STATUS_IDLE_DONE,
                                    1))
@@@ -4788,7 -4731,7 +4739,7 @@@ static void intel_dp_check_service_irq(
                intel_dp_handle_test_request(intel_dp);
  
        if (val & DP_CP_IRQ)
 -              intel_hdcp_check_link(intel_dp->attached_connector);
 +              intel_hdcp_handle_cp_irq(intel_dp->attached_connector);
  
        if (val & DP_SINK_SPECIFIC_IRQ)
                DRM_DEBUG_DRIVER("Sink specific irq unhandled\n");
@@@ -5631,18 -5574,6 +5582,18 @@@ void intel_dp_encoder_suspend(struct in
                edp_panel_vdd_off_sync(intel_dp);
  }
  
 +static void intel_dp_hdcp_wait_for_cp_irq(struct intel_hdcp *hdcp, int timeout)
 +{
 +      long ret;
 +
 +#define C (hdcp->cp_irq_count_cached != atomic_read(&hdcp->cp_irq_count))
 +      ret = wait_event_interruptible_timeout(hdcp->cp_irq_queue, C,
 +                                             msecs_to_jiffies(timeout));
 +
 +      if (!ret)
 +              DRM_DEBUG_KMS("Timedout at waiting for CP_IRQ\n");
 +}
 +
  static
  int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *intel_dig_port,
                                u8 *an)
@@@ -5867,336 -5798,6 +5818,336 @@@ int intel_dp_hdcp_capable(struct intel_
        return 0;
  }
  
 +struct hdcp2_dp_errata_stream_type {
 +      u8      msg_id;
 +      u8      stream_type;
 +} __packed;
 +
 +static struct hdcp2_dp_msg_data {
 +      u8 msg_id;
 +      u32 offset;
 +      bool msg_detectable;
 +      u32 timeout;
 +      u32 timeout2; /* Added for non_paired situation */
 +      } hdcp2_msg_data[] = {
 +              {HDCP_2_2_AKE_INIT, DP_HDCP_2_2_AKE_INIT_OFFSET, false, 0, 0},
 +              {HDCP_2_2_AKE_SEND_CERT, DP_HDCP_2_2_AKE_SEND_CERT_OFFSET,
 +                              false, HDCP_2_2_CERT_TIMEOUT_MS, 0},
 +              {HDCP_2_2_AKE_NO_STORED_KM, DP_HDCP_2_2_AKE_NO_STORED_KM_OFFSET,
 +                              false, 0, 0},
 +              {HDCP_2_2_AKE_STORED_KM, DP_HDCP_2_2_AKE_STORED_KM_OFFSET,
 +                              false, 0, 0},
 +              {HDCP_2_2_AKE_SEND_HPRIME, DP_HDCP_2_2_AKE_SEND_HPRIME_OFFSET,
 +                              true, HDCP_2_2_HPRIME_PAIRED_TIMEOUT_MS,
 +                              HDCP_2_2_HPRIME_NO_PAIRED_TIMEOUT_MS},
 +              {HDCP_2_2_AKE_SEND_PAIRING_INFO,
 +                              DP_HDCP_2_2_AKE_SEND_PAIRING_INFO_OFFSET, true,
 +                              HDCP_2_2_PAIRING_TIMEOUT_MS, 0},
 +              {HDCP_2_2_LC_INIT, DP_HDCP_2_2_LC_INIT_OFFSET, false, 0, 0},
 +              {HDCP_2_2_LC_SEND_LPRIME, DP_HDCP_2_2_LC_SEND_LPRIME_OFFSET,
 +                              false, HDCP_2_2_DP_LPRIME_TIMEOUT_MS, 0},
 +              {HDCP_2_2_SKE_SEND_EKS, DP_HDCP_2_2_SKE_SEND_EKS_OFFSET, false,
 +                              0, 0},
 +              {HDCP_2_2_REP_SEND_RECVID_LIST,
 +                              DP_HDCP_2_2_REP_SEND_RECVID_LIST_OFFSET, true,
 +                              HDCP_2_2_RECVID_LIST_TIMEOUT_MS, 0},
 +              {HDCP_2_2_REP_SEND_ACK, DP_HDCP_2_2_REP_SEND_ACK_OFFSET, false,
 +                              0, 0},
 +              {HDCP_2_2_REP_STREAM_MANAGE,
 +                              DP_HDCP_2_2_REP_STREAM_MANAGE_OFFSET, false,
 +                              0, 0},
 +              {HDCP_2_2_REP_STREAM_READY, DP_HDCP_2_2_REP_STREAM_READY_OFFSET,
 +                              false, HDCP_2_2_STREAM_READY_TIMEOUT_MS, 0},
 +/* local define to shovel this through the write_2_2 interface */
 +#define HDCP_2_2_ERRATA_DP_STREAM_TYPE        50
 +              {HDCP_2_2_ERRATA_DP_STREAM_TYPE,
 +                              DP_HDCP_2_2_REG_STREAM_TYPE_OFFSET, false,
 +                              0, 0},
 +              };
 +
 +static inline
 +int intel_dp_hdcp2_read_rx_status(struct intel_digital_port *intel_dig_port,
 +                                u8 *rx_status)
 +{
 +      ssize_t ret;
 +
 +      ret = drm_dp_dpcd_read(&intel_dig_port->dp.aux,
 +                             DP_HDCP_2_2_REG_RXSTATUS_OFFSET, rx_status,
 +                             HDCP_2_2_DP_RXSTATUS_LEN);
 +      if (ret != HDCP_2_2_DP_RXSTATUS_LEN) {
 +              DRM_DEBUG_KMS("Read bstatus from DP/AUX failed (%zd)\n", ret);
 +              return ret >= 0 ? -EIO : ret;
 +      }
 +
 +      return 0;
 +}
 +
 +static
 +int hdcp2_detect_msg_availability(struct intel_digital_port *intel_dig_port,
 +                                u8 msg_id, bool *msg_ready)
 +{
 +      u8 rx_status;
 +      int ret;
 +
 +      *msg_ready = false;
 +      ret = intel_dp_hdcp2_read_rx_status(intel_dig_port, &rx_status);
 +      if (ret < 0)
 +              return ret;
 +
 +      switch (msg_id) {
 +      case HDCP_2_2_AKE_SEND_HPRIME:
 +              if (HDCP_2_2_DP_RXSTATUS_H_PRIME(rx_status))
 +                      *msg_ready = true;
 +              break;
 +      case HDCP_2_2_AKE_SEND_PAIRING_INFO:
 +              if (HDCP_2_2_DP_RXSTATUS_PAIRING(rx_status))
 +                      *msg_ready = true;
 +              break;
 +      case HDCP_2_2_REP_SEND_RECVID_LIST:
 +              if (HDCP_2_2_DP_RXSTATUS_READY(rx_status))
 +                      *msg_ready = true;
 +              break;
 +      default:
 +              DRM_ERROR("Unidentified msg_id: %d\n", msg_id);
 +              return -EINVAL;
 +      }
 +
 +      return 0;
 +}
 +
 +static ssize_t
 +intel_dp_hdcp2_wait_for_msg(struct intel_digital_port *intel_dig_port,
 +                          struct hdcp2_dp_msg_data *hdcp2_msg_data)
 +{
 +      struct intel_dp *dp = &intel_dig_port->dp;
 +      struct intel_hdcp *hdcp = &dp->attached_connector->hdcp;
 +      u8 msg_id = hdcp2_msg_data->msg_id;
 +      int ret, timeout;
 +      bool msg_ready = false;
 +
 +      if (msg_id == HDCP_2_2_AKE_SEND_HPRIME && !hdcp->is_paired)
 +              timeout = hdcp2_msg_data->timeout2;
 +      else
 +              timeout = hdcp2_msg_data->timeout;
 +
 +      /*
 +       * There is no way to detect the CERT, LPRIME and STREAM_READY
 +       * availability. So Wait for timeout and read the msg.
 +       */
 +      if (!hdcp2_msg_data->msg_detectable) {
 +              mdelay(timeout);
 +              ret = 0;
 +      } else {
 +              /*
 +               * As we want to check the msg availability at timeout, Ignoring
 +               * the timeout at wait for CP_IRQ.
 +               */
 +              intel_dp_hdcp_wait_for_cp_irq(hdcp, timeout);
 +              ret = hdcp2_detect_msg_availability(intel_dig_port,
 +                                                  msg_id, &msg_ready);
 +              if (!msg_ready)
 +                      ret = -ETIMEDOUT;
 +      }
 +
 +      if (ret)
 +              DRM_DEBUG_KMS("msg_id %d, ret %d, timeout(mSec): %d\n",
 +                            hdcp2_msg_data->msg_id, ret, timeout);
 +
 +      return ret;
 +}
 +
 +static struct hdcp2_dp_msg_data *get_hdcp2_dp_msg_data(u8 msg_id)
 +{
 +      int i;
 +
 +      for (i = 0; i < ARRAY_SIZE(hdcp2_msg_data); i++)
 +              if (hdcp2_msg_data[i].msg_id == msg_id)
 +                      return &hdcp2_msg_data[i];
 +
 +      return NULL;
 +}
 +
 +static
 +int intel_dp_hdcp2_write_msg(struct intel_digital_port *intel_dig_port,
 +                           void *buf, size_t size)
 +{
 +      struct intel_dp *dp = &intel_dig_port->dp;
 +      struct intel_hdcp *hdcp = &dp->attached_connector->hdcp;
 +      unsigned int offset;
 +      u8 *byte = buf;
 +      ssize_t ret, bytes_to_write, len;
 +      struct hdcp2_dp_msg_data *hdcp2_msg_data;
 +
 +      hdcp2_msg_data = get_hdcp2_dp_msg_data(*byte);
 +      if (!hdcp2_msg_data)
 +              return -EINVAL;
 +
 +      offset = hdcp2_msg_data->offset;
 +
 +      /* No msg_id in DP HDCP2.2 msgs */
 +      bytes_to_write = size - 1;
 +      byte++;
 +
 +      hdcp->cp_irq_count_cached = atomic_read(&hdcp->cp_irq_count);
 +
 +      while (bytes_to_write) {
 +              len = bytes_to_write > DP_AUX_MAX_PAYLOAD_BYTES ?
 +                              DP_AUX_MAX_PAYLOAD_BYTES : bytes_to_write;
 +
 +              ret = drm_dp_dpcd_write(&intel_dig_port->dp.aux,
 +                                      offset, (void *)byte, len);
 +              if (ret < 0)
 +                      return ret;
 +
 +              bytes_to_write -= ret;
 +              byte += ret;
 +              offset += ret;
 +      }
 +
 +      return size;
 +}
 +
 +static
 +ssize_t get_receiver_id_list_size(struct intel_digital_port *intel_dig_port)
 +{
 +      u8 rx_info[HDCP_2_2_RXINFO_LEN];
 +      u32 dev_cnt;
 +      ssize_t ret;
 +
 +      ret = drm_dp_dpcd_read(&intel_dig_port->dp.aux,
 +                             DP_HDCP_2_2_REG_RXINFO_OFFSET,
 +                             (void *)rx_info, HDCP_2_2_RXINFO_LEN);
 +      if (ret != HDCP_2_2_RXINFO_LEN)
 +              return ret >= 0 ? -EIO : ret;
 +
 +      dev_cnt = (HDCP_2_2_DEV_COUNT_HI(rx_info[0]) << 4 |
 +                 HDCP_2_2_DEV_COUNT_LO(rx_info[1]));
 +
 +      if (dev_cnt > HDCP_2_2_MAX_DEVICE_COUNT)
 +              dev_cnt = HDCP_2_2_MAX_DEVICE_COUNT;
 +
 +      ret = sizeof(struct hdcp2_rep_send_receiverid_list) -
 +              HDCP_2_2_RECEIVER_IDS_MAX_LEN +
 +              (dev_cnt * HDCP_2_2_RECEIVER_ID_LEN);
 +
 +      return ret;
 +}
 +
 +static
 +int intel_dp_hdcp2_read_msg(struct intel_digital_port *intel_dig_port,
 +                          u8 msg_id, void *buf, size_t size)
 +{
 +      unsigned int offset;
 +      u8 *byte = buf;
 +      ssize_t ret, bytes_to_recv, len;
 +      struct hdcp2_dp_msg_data *hdcp2_msg_data;
 +
 +      hdcp2_msg_data = get_hdcp2_dp_msg_data(msg_id);
 +      if (!hdcp2_msg_data)
 +              return -EINVAL;
 +      offset = hdcp2_msg_data->offset;
 +
 +      ret = intel_dp_hdcp2_wait_for_msg(intel_dig_port, hdcp2_msg_data);
 +      if (ret < 0)
 +              return ret;
 +
 +      if (msg_id == HDCP_2_2_REP_SEND_RECVID_LIST) {
 +              ret = get_receiver_id_list_size(intel_dig_port);
 +              if (ret < 0)
 +                      return ret;
 +
 +              size = ret;
 +      }
 +      bytes_to_recv = size - 1;
 +
 +      /* DP adaptation msgs has no msg_id */
 +      byte++;
 +
 +      while (bytes_to_recv) {
 +              len = bytes_to_recv > DP_AUX_MAX_PAYLOAD_BYTES ?
 +                    DP_AUX_MAX_PAYLOAD_BYTES : bytes_to_recv;
 +
 +              ret = drm_dp_dpcd_read(&intel_dig_port->dp.aux, offset,
 +                                     (void *)byte, len);
 +              if (ret < 0) {
 +                      DRM_DEBUG_KMS("msg_id %d, ret %zd\n", msg_id, ret);
 +                      return ret;
 +              }
 +
 +              bytes_to_recv -= ret;
 +              byte += ret;
 +              offset += ret;
 +      }
 +      byte = buf;
 +      *byte = msg_id;
 +
 +      return size;
 +}
 +
 +static
 +int intel_dp_hdcp2_config_stream_type(struct intel_digital_port *intel_dig_port,
 +                                    bool is_repeater, u8 content_type)
 +{
 +      struct hdcp2_dp_errata_stream_type stream_type_msg;
 +
 +      if (is_repeater)
 +              return 0;
 +
 +      /*
 +       * Errata for DP: As Stream type is used for encryption, Receiver
 +       * should be communicated with stream type for the decryption of the
 +       * content.
 +       * Repeater will be communicated with stream type as a part of it's
 +       * auth later in time.
 +       */
 +      stream_type_msg.msg_id = HDCP_2_2_ERRATA_DP_STREAM_TYPE;
 +      stream_type_msg.stream_type = content_type;
 +
 +      return intel_dp_hdcp2_write_msg(intel_dig_port, &stream_type_msg,
 +                                      sizeof(stream_type_msg));
 +}
 +
 +static
 +int intel_dp_hdcp2_check_link(struct intel_digital_port *intel_dig_port)
 +{
 +      u8 rx_status;
 +      int ret;
 +
 +      ret = intel_dp_hdcp2_read_rx_status(intel_dig_port, &rx_status);
 +      if (ret)
 +              return ret;
 +
 +      if (HDCP_2_2_DP_RXSTATUS_REAUTH_REQ(rx_status))
 +              ret = HDCP_REAUTH_REQUEST;
 +      else if (HDCP_2_2_DP_RXSTATUS_LINK_FAILED(rx_status))
 +              ret = HDCP_LINK_INTEGRITY_FAILURE;
 +      else if (HDCP_2_2_DP_RXSTATUS_READY(rx_status))
 +              ret = HDCP_TOPOLOGY_CHANGE;
 +
 +      return ret;
 +}
 +
 +static
 +int intel_dp_hdcp2_capable(struct intel_digital_port *intel_dig_port,
 +                         bool *capable)
 +{
 +      u8 rx_caps[3];
 +      int ret;
 +
 +      *capable = false;
 +      ret = drm_dp_dpcd_read(&intel_dig_port->dp.aux,
 +                             DP_HDCP_2_2_REG_RX_CAPS_OFFSET,
 +                             rx_caps, HDCP_2_2_RXCAPS_LEN);
 +      if (ret != HDCP_2_2_RXCAPS_LEN)
 +              return ret >= 0 ? -EIO : ret;
 +
 +      if (rx_caps[0] == HDCP_2_2_RX_CAPS_VERSION_VAL &&
 +          HDCP_2_2_DP_HDCP_CAPABLE(rx_caps[2]))
 +              *capable = true;
 +
 +      return 0;
 +}
 +
  static const struct intel_hdcp_shim intel_dp_hdcp_shim = {
        .write_an_aksv = intel_dp_hdcp_write_an_aksv,
        .read_bksv = intel_dp_hdcp_read_bksv,
        .toggle_signalling = intel_dp_hdcp_toggle_signalling,
        .check_link = intel_dp_hdcp_check_link,
        .hdcp_capable = intel_dp_hdcp_capable,
 +      .write_2_2_msg = intel_dp_hdcp2_write_msg,
 +      .read_2_2_msg = intel_dp_hdcp2_read_msg,
 +      .config_stream_type = intel_dp_hdcp2_config_stream_type,
 +      .check_2_2_link = intel_dp_hdcp2_check_link,
 +      .hdcp_2_2_capable = intel_dp_hdcp2_capable,
 +      .protocol = HDCP_PROTOCOL_DP,
  };
  
  static void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp)
@@@ -6428,34 -6023,43 +6379,34 @@@ static voi
  intel_pps_readout_hw_state(struct intel_dp *intel_dp, struct edp_power_seq *seq)
  {
        struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 -      u32 pp_on, pp_off, pp_div = 0, pp_ctl = 0;
 +      u32 pp_on, pp_off, pp_ctl;
        struct pps_registers regs;
  
        intel_pps_get_registers(intel_dp, &regs);
  
 -      /* Workaround: Need to write PP_CONTROL with the unlock key as
 -       * the very first thing. */
        pp_ctl = ironlake_get_pp_control(intel_dp);
  
 +      /* Ensure PPS is unlocked */
 +      if (!HAS_DDI(dev_priv))
 +              I915_WRITE(regs.pp_ctrl, pp_ctl);
 +
        pp_on = I915_READ(regs.pp_on);
        pp_off = I915_READ(regs.pp_off);
 -      if (!IS_GEN9_LP(dev_priv) && !HAS_PCH_CNP(dev_priv) &&
 -          !HAS_PCH_ICP(dev_priv)) {
 -              I915_WRITE(regs.pp_ctrl, pp_ctl);
 -              pp_div = I915_READ(regs.pp_div);
 -      }
  
        /* Pull timing values out of registers */
 -      seq->t1_t3 = (pp_on & PANEL_POWER_UP_DELAY_MASK) >>
 -                   PANEL_POWER_UP_DELAY_SHIFT;
 +      seq->t1_t3 = REG_FIELD_GET(PANEL_POWER_UP_DELAY_MASK, pp_on);
 +      seq->t8 = REG_FIELD_GET(PANEL_LIGHT_ON_DELAY_MASK, pp_on);
 +      seq->t9 = REG_FIELD_GET(PANEL_LIGHT_OFF_DELAY_MASK, pp_off);
 +      seq->t10 = REG_FIELD_GET(PANEL_POWER_DOWN_DELAY_MASK, pp_off);
  
 -      seq->t8 = (pp_on & PANEL_LIGHT_ON_DELAY_MASK) >>
 -                PANEL_LIGHT_ON_DELAY_SHIFT;
 +      if (i915_mmio_reg_valid(regs.pp_div)) {
 +              u32 pp_div;
  
 -      seq->t9 = (pp_off & PANEL_LIGHT_OFF_DELAY_MASK) >>
 -                PANEL_LIGHT_OFF_DELAY_SHIFT;
 -
 -      seq->t10 = (pp_off & PANEL_POWER_DOWN_DELAY_MASK) >>
 -                 PANEL_POWER_DOWN_DELAY_SHIFT;
 +              pp_div = I915_READ(regs.pp_div);
  
 -      if (IS_GEN9_LP(dev_priv) || HAS_PCH_CNP(dev_priv) ||
 -          HAS_PCH_ICP(dev_priv)) {
 -              seq->t11_t12 = ((pp_ctl & BXT_POWER_CYCLE_DELAY_MASK) >>
 -                              BXT_POWER_CYCLE_DELAY_SHIFT) * 1000;
 +              seq->t11_t12 = REG_FIELD_GET(PANEL_POWER_CYCLE_DELAY_MASK, pp_div) * 1000;
        } else {
 -              seq->t11_t12 = ((pp_div & PANEL_POWER_CYCLE_DELAY_MASK) >>
 -                     PANEL_POWER_CYCLE_DELAY_SHIFT) * 1000;
 +              seq->t11_t12 = REG_FIELD_GET(BXT_POWER_CYCLE_DELAY_MASK, pp_ctl) * 1000;
        }
  }
  
@@@ -6580,7 -6184,7 +6531,7 @@@ intel_dp_init_panel_power_sequencer_reg
                                              bool force_disable_vdd)
  {
        struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 -      u32 pp_on, pp_off, pp_div, port_sel = 0;
 +      u32 pp_on, pp_off, port_sel = 0;
        int div = dev_priv->rawclk_freq / 1000;
        struct pps_registers regs;
        enum port port = dp_to_dig_port(intel_dp)->base.port;
                I915_WRITE(regs.pp_ctrl, pp);
        }
  
 -      pp_on = (seq->t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) |
 -              (seq->t8 << PANEL_LIGHT_ON_DELAY_SHIFT);
 -      pp_off = (seq->t9 << PANEL_LIGHT_OFF_DELAY_SHIFT) |
 -               (seq->t10 << PANEL_POWER_DOWN_DELAY_SHIFT);
 -      /* Compute the divisor for the pp clock, simply match the Bspec
 -       * formula. */
 -      if (IS_GEN9_LP(dev_priv) || HAS_PCH_CNP(dev_priv) ||
 -          HAS_PCH_ICP(dev_priv)) {
 -              pp_div = I915_READ(regs.pp_ctrl);
 -              pp_div &= ~BXT_POWER_CYCLE_DELAY_MASK;
 -              pp_div |= (DIV_ROUND_UP(seq->t11_t12, 1000)
 -                              << BXT_POWER_CYCLE_DELAY_SHIFT);
 -      } else {
 -              pp_div = ((100 * div)/2 - 1) << PP_REFERENCE_DIVIDER_SHIFT;
 -              pp_div |= (DIV_ROUND_UP(seq->t11_t12, 1000)
 -                              << PANEL_POWER_CYCLE_DELAY_SHIFT);
 -      }
 +      pp_on = REG_FIELD_PREP(PANEL_POWER_UP_DELAY_MASK, seq->t1_t3) |
 +              REG_FIELD_PREP(PANEL_LIGHT_ON_DELAY_MASK, seq->t8);
 +      pp_off = REG_FIELD_PREP(PANEL_LIGHT_OFF_DELAY_MASK, seq->t9) |
 +              REG_FIELD_PREP(PANEL_POWER_DOWN_DELAY_MASK, seq->t10);
  
        /* Haswell doesn't have any port selection bits for the panel
         * power sequencer any more. */
  
        I915_WRITE(regs.pp_on, pp_on);
        I915_WRITE(regs.pp_off, pp_off);
 -      if (IS_GEN9_LP(dev_priv) || HAS_PCH_CNP(dev_priv) ||
 -          HAS_PCH_ICP(dev_priv))
 -              I915_WRITE(regs.pp_ctrl, pp_div);
 -      else
 -              I915_WRITE(regs.pp_div, pp_div);
 +
 +      /*
 +       * Compute the divisor for the pp clock, simply match the Bspec formula.
 +       */
 +      if (i915_mmio_reg_valid(regs.pp_div)) {
 +              I915_WRITE(regs.pp_div,
 +                         REG_FIELD_PREP(PP_REFERENCE_DIVIDER_MASK, (100 * div) / 2 - 1) |
 +                         REG_FIELD_PREP(PANEL_POWER_CYCLE_DELAY_MASK, DIV_ROUND_UP(seq->t11_t12, 1000)));
 +      } else {
 +              u32 pp_ctl;
 +
 +              pp_ctl = I915_READ(regs.pp_ctrl);
 +              pp_ctl &= ~BXT_POWER_CYCLE_DELAY_MASK;
 +              pp_ctl |= REG_FIELD_PREP(BXT_POWER_CYCLE_DELAY_MASK, DIV_ROUND_UP(seq->t11_t12, 1000));
 +              I915_WRITE(regs.pp_ctrl, pp_ctl);
 +      }
  
        DRM_DEBUG_KMS("panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n",
                      I915_READ(regs.pp_on),
                      I915_READ(regs.pp_off),
 -                    (IS_GEN9_LP(dev_priv) || HAS_PCH_CNP(dev_priv)  ||
 -                     HAS_PCH_ICP(dev_priv)) ?
 -                    (I915_READ(regs.pp_ctrl) & BXT_POWER_CYCLE_DELAY_MASK) :
 -                    I915_READ(regs.pp_div));
 +                    i915_mmio_reg_valid(regs.pp_div) ?
 +                    I915_READ(regs.pp_div) :
 +                    (I915_READ(regs.pp_ctrl) & BXT_POWER_CYCLE_DELAY_MASK));
  }
  
  static void intel_dp_pps_init(struct intel_dp *intel_dp)
@@@ -7038,7 -6645,9 +6989,7 @@@ intel_dp_drrs_init(struct intel_connect
                return NULL;
        }
  
 -      downclock_mode = intel_find_panel_downclock(dev_priv, fixed_mode,
 -                                                  &connector->base);
 -
 +      downclock_mode = intel_panel_edid_downclock_mode(connector, fixed_mode);
        if (!downclock_mode) {
                DRM_DEBUG_KMS("Downclock mode is not found. DRRS not supported\n");
                return NULL;
@@@ -7060,6 -6669,7 +7011,6 @@@ static bool intel_edp_init_connector(st
        struct drm_display_mode *fixed_mode = NULL;
        struct drm_display_mode *downclock_mode = NULL;
        bool has_dpcd;
 -      struct drm_display_mode *scan;
        enum pipe pipe = INVALID_PIPE;
        intel_wakeref_t wakeref;
        struct edid *edid;
         * eDP and LVDS bail out early in this case to prevent interfering
         * with an already powered-on LVDS power sequencer.
         */
 -      if (intel_get_lvds_encoder(&dev_priv->drm)) {
 +      if (intel_get_lvds_encoder(dev_priv)) {
                WARN_ON(!(HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)));
                DRM_INFO("LVDS was detected, not registering eDP\n");
  
        }
        intel_connector->edid = edid;
  
 -      /* prefer fixed mode from EDID if available */
 -      list_for_each_entry(scan, &connector->probed_modes, head) {
 -              if ((scan->type & DRM_MODE_TYPE_PREFERRED)) {
 -                      fixed_mode = drm_mode_duplicate(dev, scan);
 -                      downclock_mode = intel_dp_drrs_init(
 -                                              intel_connector, fixed_mode);
 -                      break;
 -              }
 -      }
 +      fixed_mode = intel_panel_edid_fixed_mode(intel_connector);
 +      if (fixed_mode)
 +              downclock_mode = intel_dp_drrs_init(intel_connector, fixed_mode);
  
        /* fallback to VBT if available for eDP */
 -      if (!fixed_mode && dev_priv->vbt.lfp_lvds_vbt_mode) {
 -              fixed_mode = drm_mode_duplicate(dev,
 -                                      dev_priv->vbt.lfp_lvds_vbt_mode);
 -              if (fixed_mode) {
 -                      fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
 -                      connector->display_info.width_mm = fixed_mode->width_mm;
 -                      connector->display_info.height_mm = fixed_mode->height_mm;
 -              }
 -      }
 +      if (!fixed_mode)
 +              fixed_mode = intel_panel_vbt_fixed_mode(intel_connector);
        mutex_unlock(&dev->mode_config.mutex);
  
        if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
index f8c7b291fdc356a8b80eef5c28263de58901187c,d5660ac1b0d60999d8788710a0140ec2f8d38570..ea5e300b649c7022d5f052f4e619879db050f70d
@@@ -41,7 -41,6 +41,7 @@@
  #include <drm/drm_rect.h>
  #include <drm/drm_vblank.h>
  #include <drm/drm_atomic.h>
 +#include <drm/i915_mei_hdcp_interface.h>
  #include <media/cec-notifier.h>
  
  struct drm_printer;
@@@ -271,10 -270,12 +271,12 @@@ struct intel_encoder 
         * be set correctly before calling this function. */
        void (*get_config)(struct intel_encoder *,
                           struct intel_crtc_state *pipe_config);
-       /* Returns a mask of power domains that need to be referenced as part
-        * of the hardware state readout code. */
-       u64 (*get_power_domains)(struct intel_encoder *encoder,
-                                struct intel_crtc_state *crtc_state);
+       /*
+        * Acquires the power domains needed for an active encoder during
+        * hardware state readout.
+        */
+       void (*get_power_domains)(struct intel_encoder *encoder,
+                                 struct intel_crtc_state *crtc_state);
        /*
         * Called during system suspend after all pending requests for the
         * encoder are flushed (for example for DP AUX transactions) and
@@@ -324,13 -325,6 +326,13 @@@ struct intel_panel 
  
  struct intel_digital_port;
  
 +enum check_link_response {
 +      HDCP_LINK_PROTECTED     = 0,
 +      HDCP_TOPOLOGY_CHANGE,
 +      HDCP_LINK_INTEGRITY_FAILURE,
 +      HDCP_REAUTH_REQUEST
 +};
 +
  /*
   * This structure serves as a translation layer between the generic HDCP code
   * and the bus-specific code. What that means is that HDCP over HDMI differs
@@@ -403,32 -397,6 +405,32 @@@ struct intel_hdcp_shim 
        /* Detects panel's hdcp capability. This is optional for HDMI. */
        int (*hdcp_capable)(struct intel_digital_port *intel_dig_port,
                            bool *hdcp_capable);
 +
 +      /* HDCP adaptation(DP/HDMI) required on the port */
 +      enum hdcp_wired_protocol protocol;
 +
 +      /* Detects whether sink is HDCP2.2 capable */
 +      int (*hdcp_2_2_capable)(struct intel_digital_port *intel_dig_port,
 +                              bool *capable);
 +
 +      /* Write HDCP2.2 messages */
 +      int (*write_2_2_msg)(struct intel_digital_port *intel_dig_port,
 +                           void *buf, size_t size);
 +
 +      /* Read HDCP2.2 messages */
 +      int (*read_2_2_msg)(struct intel_digital_port *intel_dig_port,
 +                          u8 msg_id, void *buf, size_t size);
 +
 +      /*
 +       * Implementation of DP HDCP2.2 Errata for the communication of stream
 +       * type to Receivers. In DP HDCP2.2 Stream type is one of the input to
 +       * the HDCP2.2 Cipher for En/De-Cryption. Not applicable for HDMI.
 +       */
 +      int (*config_stream_type)(struct intel_digital_port *intel_dig_port,
 +                                bool is_repeater, u8 type);
 +
 +      /* HDCP2.2 Link Integrity Check */
 +      int (*check_2_2_link)(struct intel_digital_port *intel_dig_port);
  };
  
  struct intel_hdcp {
        u64 value;
        struct delayed_work check_work;
        struct work_struct prop_work;
 +
 +      /* HDCP1.4 Encryption status */
 +      bool hdcp_encrypted;
 +
 +      /* HDCP2.2 related definitions */
 +      /* Flag indicates whether this connector supports HDCP2.2 or not. */
 +      bool hdcp2_supported;
 +
 +      /* HDCP2.2 Encryption status */
 +      bool hdcp2_encrypted;
 +
 +      /*
 +       * Content Stream Type defined by content owner. TYPE0(0x0) content can
 +       * flow in the link protected by HDCP2.2 or HDCP1.4, where as TYPE1(0x1)
 +       * content can flow only through a link protected by HDCP2.2.
 +       */
 +      u8 content_type;
 +      struct hdcp_port_data port_data;
 +
 +      bool is_paired;
 +      bool is_repeater;
 +
 +      /*
 +       * Count of ReceiverID_List received. Initialized to 0 at AKE_INIT.
 +       * Incremented after processing the RepeaterAuth_Send_ReceiverID_List.
 +       * When it rolls over re-auth has to be triggered.
 +       */
 +      u32 seq_num_v;
 +
 +      /*
 +       * Count of RepeaterAuth_Stream_Manage msg propagated.
 +       * Initialized to 0 on AKE_INIT. Incremented after every successful
 +       * transmission of RepeaterAuth_Stream_Manage message. When it rolls
 +       * over re-Auth has to be triggered.
 +       */
 +      u32 seq_num_m;
 +
 +      /*
 +       * Work queue to signal the CP_IRQ. Used for the waiters to read the
 +       * available information from HDCP DP sink.
 +       */
 +      wait_queue_head_t cp_irq_queue;
 +      atomic_t cp_irq_count;
 +      int cp_irq_count_cached;
  };
  
  struct intel_connector {
@@@ -999,8 -923,7 +1001,8 @@@ struct intel_crtc_state 
        struct intel_link_m_n fdi_m_n;
  
        bool ips_enabled;
 -      bool ips_force_disable;
 +
 +      bool crc_enabled;
  
        bool enable_fbc;
  
        /* Gamma mode programmed on the pipe */
        u32 gamma_mode;
  
 +      union {
 +              /* CSC mode programmed on the pipe */
 +              u32 csc_mode;
 +
 +              /* CHV CGM mode */
 +              u32 cgm_mode;
 +      };
 +
        /* bitmask of visible planes (enum plane_id) */
        u8 active_planes;
        u8 nv12_planes;
 +      u8 c8_planes;
  
        /* bitmask of planes that will be updated during the commit */
        u8 update_planes;
  
 +      struct {
 +              u32 enable;
 +              u32 gcp;
 +              union hdmi_infoframe avi;
 +              union hdmi_infoframe spd;
 +              union hdmi_infoframe hdmi;
 +      } infoframes;
 +
        /* HDMI scrambling status */
        bool hdmi_scrambling;
  
        /* Output down scaling is done in LSPCON device */
        bool lspcon_downsampling;
  
 +      /* enable pipe gamma? */
 +      bool gamma_enable;
 +
 +      /* enable pipe csc? */
 +      bool csc_enable;
 +
        /* Display Stream compression state */
        struct {
                bool compression_enable;
@@@ -1091,6 -991,9 +1093,6 @@@ struct intel_crtc 
  
        struct intel_crtc_state *config;
  
 -      /* global reset count when the last flip was submitted */
 -      unsigned int reset_count;
 -
        /* Access to these should be protected by dev_priv->irq_lock. */
        bool cpu_fifo_underrun_disabled;
        bool pch_fifo_underrun_disabled;
@@@ -1359,15 -1262,11 +1361,15 @@@ struct intel_digital_port 
                                const struct intel_crtc_state *crtc_state,
                                unsigned int type,
                                const void *frame, ssize_t len);
 +      void (*read_infoframe)(struct intel_encoder *encoder,
 +                             const struct intel_crtc_state *crtc_state,
 +                             unsigned int type,
 +                             void *frame, ssize_t len);
        void (*set_infoframes)(struct intel_encoder *encoder,
                               bool enable,
                               const struct intel_crtc_state *crtc_state,
                               const struct drm_connector_state *conn_state);
 -      bool (*infoframe_enabled)(struct intel_encoder *encoder,
 +      u32 (*infoframes_enabled)(struct intel_encoder *encoder,
                                  const struct intel_crtc_state *pipe_config);
  };
  
@@@ -1659,7 -1558,7 +1661,7 @@@ int intel_ddi_toggle_hdcp_signalling(st
                                     bool enable);
  void icl_sanitize_encoder_pll_mapping(struct intel_encoder *encoder);
  int cnl_calc_wrpll_link(struct drm_i915_private *dev_priv,
 -                      enum intel_dpll_id pll_id);
 +                      struct intel_dpll_hw_state *state);
  
  unsigned int intel_fb_align_height(const struct drm_framebuffer *fb,
                                   int color_plane, unsigned int height);
@@@ -1841,7 -1740,7 +1843,7 @@@ void intel_dp_get_m_n(struct intel_crt
  void intel_dp_set_m_n(const struct intel_crtc_state *crtc_state,
                      enum link_m_n_set m_n);
  int intel_dotclock_calculate(int link_freq, const struct intel_link_m_n *m_n);
 -bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state, int target_clock,
 +bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state,
                        struct dpll *best_clock);
  int chv_calc_dpll_params(int refclk, struct dpll *pll_clock);
  
@@@ -1899,7 -1798,6 +1901,7 @@@ int intel_ddc_get_modes(struct drm_conn
  void intel_attach_force_audio_property(struct drm_connector *connector);
  void intel_attach_broadcast_rgb_property(struct drm_connector *connector);
  void intel_attach_aspect_ratio_property(struct drm_connector *connector);
 +void intel_attach_colorspace_property(struct drm_connector *connector);
  
  /* intel_csr.c */
  void intel_csr_ucode_init(struct drm_i915_private *);
@@@ -1909,16 -1807,6 +1911,16 @@@ void intel_csr_ucode_suspend(struct drm
  void intel_csr_ucode_resume(struct drm_i915_private *);
  
  /* intel_dp.c */
 +struct link_config_limits {
 +      int min_clock, max_clock;
 +      int min_lane_count, max_lane_count;
 +      int min_bpp, max_bpp;
 +};
 +void intel_dp_adjust_compliance_config(struct intel_dp *intel_dp,
 +                                     struct intel_crtc_state *pipe_config,
 +                                     struct link_config_limits *limits);
 +bool intel_dp_limited_color_range(const struct intel_crtc_state *crtc_state,
 +                                const struct drm_connector_state *conn_state);
  bool intel_dp_port_enabled(struct drm_i915_private *dev_priv,
                           i915_reg_t dp_reg, enum port port,
                           enum pipe *pipe);
@@@ -2113,22 -2001,13 +2115,22 @@@ bool intel_hdmi_handle_sink_scrambling(
                                       bool scrambling);
  void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable);
  void intel_infoframe_init(struct intel_digital_port *intel_dig_port);
 +u32 intel_hdmi_infoframes_enabled(struct intel_encoder *encoder,
 +                                const struct intel_crtc_state *crtc_state);
 +u32 intel_hdmi_infoframe_enable(unsigned int type);
 +void intel_hdmi_read_gcp_infoframe(struct intel_encoder *encoder,
 +                                 struct intel_crtc_state *crtc_state);
 +void intel_read_infoframe(struct intel_encoder *encoder,
 +                        const struct intel_crtc_state *crtc_state,
 +                        enum hdmi_infoframe_type type,
 +                        union hdmi_infoframe *frame);
  
  /* intel_lvds.c */
  bool intel_lvds_port_enabled(struct drm_i915_private *dev_priv,
                             i915_reg_t lvds_reg, enum pipe *pipe);
  void intel_lvds_init(struct drm_i915_private *dev_priv);
 -struct intel_encoder *intel_get_lvds_encoder(struct drm_device *dev);
 -bool intel_is_dual_link_lvds(struct drm_device *dev);
 +struct intel_encoder *intel_get_lvds_encoder(struct drm_i915_private *dev_priv);
 +bool intel_is_dual_link_lvds(struct drm_i915_private *dev_priv);
  
  /* intel_overlay.c */
  void intel_overlay_setup(struct drm_i915_private *dev_priv);
@@@ -2164,13 -2043,10 +2166,13 @@@ void intel_panel_update_backlight(struc
                                  const struct intel_crtc_state *crtc_state,
                                  const struct drm_connector_state *conn_state);
  void intel_panel_disable_backlight(const struct drm_connector_state *old_conn_state);
 -extern struct drm_display_mode *intel_find_panel_downclock(
 -                              struct drm_i915_private *dev_priv,
 -                              struct drm_display_mode *fixed_mode,
 -                              struct drm_connector *connector);
 +struct drm_display_mode *
 +intel_panel_edid_downclock_mode(struct intel_connector *connector,
 +                              const struct drm_display_mode *fixed_mode);
 +struct drm_display_mode *
 +intel_panel_edid_fixed_mode(struct intel_connector *connector);
 +struct drm_display_mode *
 +intel_panel_vbt_fixed_mode(struct intel_connector *connector);
  
  #if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE)
  int intel_backlight_device_register(struct intel_connector *connector);
@@@ -2193,12 -2069,9 +2195,12 @@@ int intel_hdcp_init(struct intel_connec
                    const struct intel_hdcp_shim *hdcp_shim);
  int intel_hdcp_enable(struct intel_connector *connector);
  int intel_hdcp_disable(struct intel_connector *connector);
 -int intel_hdcp_check_link(struct intel_connector *connector);
  bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port);
  bool intel_hdcp_capable(struct intel_connector *connector);
 +void intel_hdcp_component_init(struct drm_i915_private *dev_priv);
 +void intel_hdcp_component_fini(struct drm_i915_private *dev_priv);
 +void intel_hdcp_cleanup(struct intel_connector *connector);
 +void intel_hdcp_handle_cp_irq(struct intel_connector *connector);
  
  /* intel_psr.c */
  #define CAN_PSR(dev_priv) (HAS_PSR(dev_priv) && dev_priv->psr.sink_support)
@@@ -2207,9 -2080,9 +2209,9 @@@ void intel_psr_enable(struct intel_dp *
                      const struct intel_crtc_state *crtc_state);
  void intel_psr_disable(struct intel_dp *intel_dp,
                      const struct intel_crtc_state *old_crtc_state);
 -int intel_psr_set_debugfs_mode(struct drm_i915_private *dev_priv,
 -                             struct drm_modeset_acquire_ctx *ctx,
 -                             u64 value);
 +void intel_psr_update(struct intel_dp *intel_dp,
 +                    const struct intel_crtc_state *crtc_state);
 +int intel_psr_debug_set(struct drm_i915_private *dev_priv, u64 value);
  void intel_psr_invalidate(struct drm_i915_private *dev_priv,
                          unsigned frontbuffer_bits,
                          enum fb_op_origin origin);
@@@ -2280,26 -2153,20 +2282,26 @@@ void icl_dbuf_slices_update(struct drm_
                            u8 req_slices);
  
  static inline void
 -assert_rpm_device_not_suspended(struct drm_i915_private *i915)
 +assert_rpm_device_not_suspended(struct i915_runtime_pm *rpm)
  {
 -      WARN_ONCE(i915->runtime_pm.suspended,
 +      WARN_ONCE(rpm->suspended,
                  "Device suspended during HW access\n");
  }
  
  static inline void
 -assert_rpm_wakelock_held(struct drm_i915_private *i915)
 +__assert_rpm_wakelock_held(struct i915_runtime_pm *rpm)
  {
 -      assert_rpm_device_not_suspended(i915);
 -      WARN_ONCE(!atomic_read(&i915->runtime_pm.wakeref_count),
 +      assert_rpm_device_not_suspended(rpm);
 +      WARN_ONCE(!atomic_read(&rpm->wakeref_count),
                  "RPM wakelock ref not held during HW access");
  }
  
 +static inline void
 +assert_rpm_wakelock_held(struct drm_i915_private *i915)
 +{
 +      __assert_rpm_wakelock_held(&i915->runtime_pm);
 +}
 +
  /**
   * disable_rpm_wakeref_asserts - disable the RPM assert checks
   * @i915: i915 device instance
@@@ -2391,10 -2258,11 +2393,10 @@@ void intel_cleanup_gt_powersave(struct 
  void intel_sanitize_gt_powersave(struct drm_i915_private *dev_priv);
  void intel_enable_gt_powersave(struct drm_i915_private *dev_priv);
  void intel_disable_gt_powersave(struct drm_i915_private *dev_priv);
 -void intel_suspend_gt_powersave(struct drm_i915_private *dev_priv);
  void gen6_rps_busy(struct drm_i915_private *dev_priv);
  void gen6_rps_reset_ei(struct drm_i915_private *dev_priv);
  void gen6_rps_idle(struct drm_i915_private *dev_priv);
 -void gen6_rps_boost(struct i915_request *rq, struct intel_rps_client *rps);
 +void gen6_rps_boost(struct i915_request *rq);
  void g4x_wm_get_hw_state(struct drm_i915_private *dev_priv);
  void vlv_wm_get_hw_state(struct drm_i915_private *dev_priv);
  void ilk_wm_get_hw_state(struct drm_i915_private *dev_priv);
@@@ -2434,7 -2302,6 +2436,7 @@@ bool intel_sdvo_init(struct drm_i915_pr
  
  
  /* intel_sprite.c */
 +bool is_planar_yuv_format(u32 pixelformat);
  int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
                             int usecs);
  struct intel_plane *intel_sprite_plane_create(struct drm_i915_private *dev_priv,
@@@ -2459,13 -2326,12 +2461,13 @@@ static inline bool icl_is_nv12_y_plane(
        return false;
  }
  
 -static inline bool icl_is_hdr_plane(struct intel_plane *plane)
 +static inline bool icl_is_hdr_plane(struct drm_i915_private *dev_priv,
 +                                  enum plane_id plane_id)
  {
 -      if (INTEL_GEN(to_i915(plane->base.dev)) < 11)
 +      if (INTEL_GEN(dev_priv) < 11)
                return false;
  
 -      return plane->id < PLANE_SPRITE2;
 +      return plane_id < PLANE_SPRITE2;
  }
  
  /* intel_tv.c */
@@@ -2508,14 -2374,6 +2510,14 @@@ int intel_atomic_setup_scalers(struct d
                               struct intel_crtc_state *crtc_state);
  
  /* intel_atomic_plane.c */
 +void intel_update_plane(struct intel_plane *plane,
 +                      const struct intel_crtc_state *crtc_state,
 +                      const struct intel_plane_state *plane_state);
 +void intel_update_slave(struct intel_plane *plane,
 +                      const struct intel_crtc_state *crtc_state,
 +                      const struct intel_plane_state *plane_state);
 +void intel_disable_plane(struct intel_plane *plane,
 +                       const struct intel_crtc_state *crtc_state);
  struct intel_plane *intel_plane_alloc(void);
  void intel_plane_free(struct intel_plane *plane);
  struct drm_plane_state *intel_plane_duplicate_state(struct drm_plane *plane);
@@@ -2545,15 -2403,11 +2547,15 @@@ void lspcon_write_infoframe(struct inte
                            const struct intel_crtc_state *crtc_state,
                            unsigned int type,
                            const void *buf, ssize_t len);
 +void lspcon_read_infoframe(struct intel_encoder *encoder,
 +                         const struct intel_crtc_state *crtc_state,
 +                         unsigned int type,
 +                         void *frame, ssize_t len);
  void lspcon_set_infoframes(struct intel_encoder *encoder,
                           bool enable,
                           const struct intel_crtc_state *crtc_state,
                           const struct drm_connector_state *conn_state);
 -bool lspcon_infoframe_enabled(struct intel_encoder *encoder,
 +u32 lspcon_infoframes_enabled(struct intel_encoder *encoder,
                              const struct intel_crtc_state *pipe_config);
  void lspcon_ycbcr420_config(struct drm_connector *connector,
                            struct intel_crtc_state *crtc_state);
index 0a950c976bbb66df2e9946259b9fb9aed3e4d904,31c93c3ccd00ffa62c3158d159d7cc4afd8f9ae5..6898541403a2ac489d2bac676ca5a5d62d031835
@@@ -78,7 -78,7 +78,7 @@@ void vlv_dsi_wait_for_fifo_empty(struc
        mask = LP_CTRL_FIFO_EMPTY | HS_CTRL_FIFO_EMPTY |
                LP_DATA_FIFO_EMPTY | HS_DATA_FIFO_EMPTY;
  
 -      if (intel_wait_for_register(dev_priv,
 +      if (intel_wait_for_register(&dev_priv->uncore,
                                    MIPI_GEN_FIFO_STAT(port), mask, mask,
                                    100))
                DRM_ERROR("DPI FIFOs are not empty\n");
@@@ -148,7 -148,7 +148,7 @@@ static ssize_t intel_dsi_host_transfer(
  
        /* note: this is never true for reads */
        if (packet.payload_length) {
 -              if (intel_wait_for_register(dev_priv,
 +              if (intel_wait_for_register(&dev_priv->uncore,
                                            MIPI_GEN_FIFO_STAT(port),
                                            data_mask, 0,
                                            50))
                I915_WRITE(MIPI_INTR_STAT(port), GEN_READ_DATA_AVAIL);
        }
  
 -      if (intel_wait_for_register(dev_priv,
 +      if (intel_wait_for_register(&dev_priv->uncore,
                                    MIPI_GEN_FIFO_STAT(port),
                                    ctrl_mask, 0,
                                    50)) {
        /* ->rx_len is set only for reads */
        if (msg->rx_len) {
                data_mask = GEN_READ_DATA_AVAIL;
 -              if (intel_wait_for_register(dev_priv,
 +              if (intel_wait_for_register(&dev_priv->uncore,
                                            MIPI_INTR_STAT(port),
                                            data_mask, data_mask,
                                            50))
@@@ -234,7 -234,7 +234,7 @@@ static int dpi_send_cmd(struct intel_ds
        I915_WRITE(MIPI_DPI_CONTROL(port), cmd);
  
        mask = SPL_PKT_SENT_INTERRUPT;
 -      if (intel_wait_for_register(dev_priv,
 +      if (intel_wait_for_register(&dev_priv->uncore,
                                    MIPI_INTR_STAT(port), mask, mask,
                                    100))
                DRM_ERROR("Video mode command 0x%08x send failed.\n", cmd);
@@@ -256,6 -256,28 +256,28 @@@ static void band_gap_reset(struct drm_i
        mutex_unlock(&dev_priv->sb_lock);
  }
  
+ static int bdw_get_pipemisc_bpp(struct intel_crtc *crtc)
+ {
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       u32 tmp;
+       tmp = I915_READ(PIPEMISC(crtc->pipe));
+       switch (tmp & PIPEMISC_DITHER_BPC_MASK) {
+       case PIPEMISC_DITHER_6_BPC:
+               return 18;
+       case PIPEMISC_DITHER_8_BPC:
+               return 24;
+       case PIPEMISC_DITHER_10_BPC:
+               return 30;
+       case PIPEMISC_DITHER_12_BPC:
+               return 36;
+       default:
+               MISSING_CASE(tmp);
+               return 0;
+       }
+ }
  static int intel_dsi_compute_config(struct intel_encoder *encoder,
                                    struct intel_crtc_state *pipe_config,
                                    struct drm_connector_state *conn_state)
@@@ -353,18 -375,16 +375,18 @@@ static bool glk_dsi_enable_io(struct in
  
        /* Wait for Pwr ACK */
        for_each_dsi_port(port, intel_dsi->ports) {
 -              if (intel_wait_for_register(dev_priv,
 -                              MIPI_CTRL(port), GLK_MIPIIO_PORT_POWERED,
 -                              GLK_MIPIIO_PORT_POWERED, 20))
 +              if (intel_wait_for_register(&dev_priv->uncore,
 +                                          MIPI_CTRL(port),
 +                                          GLK_MIPIIO_PORT_POWERED,
 +                                          GLK_MIPIIO_PORT_POWERED,
 +                                          20))
                        DRM_ERROR("MIPIO port is powergated\n");
        }
  
        /* Check for cold boot scenario */
        for_each_dsi_port(port, intel_dsi->ports) {
 -              cold_boot |= !(I915_READ(MIPI_DEVICE_READY(port)) &
 -                                                      DEVICE_READY);
 +              cold_boot |=
 +                      !(I915_READ(MIPI_DEVICE_READY(port)) & DEVICE_READY);
        }
  
        return cold_boot;
@@@ -379,11 -399,9 +401,11 @@@ static void glk_dsi_device_ready(struc
  
        /* Wait for MIPI PHY status bit to set */
        for_each_dsi_port(port, intel_dsi->ports) {
 -              if (intel_wait_for_register(dev_priv,
 -                              MIPI_CTRL(port), GLK_PHY_STATUS_PORT_READY,
 -                              GLK_PHY_STATUS_PORT_READY, 20))
 +              if (intel_wait_for_register(&dev_priv->uncore,
 +                                          MIPI_CTRL(port),
 +                                          GLK_PHY_STATUS_PORT_READY,
 +                                          GLK_PHY_STATUS_PORT_READY,
 +                                          20))
                        DRM_ERROR("PHY is not ON\n");
        }
  
                        I915_WRITE(MIPI_DEVICE_READY(port), val);
  
                        /* Wait for ULPS active */
 -                      if (intel_wait_for_register(dev_priv,
 -                              MIPI_CTRL(port), GLK_ULPS_NOT_ACTIVE, 0, 20))
 +                      if (intel_wait_for_register(&dev_priv->uncore,
 +                                                  MIPI_CTRL(port),
 +                                                  GLK_ULPS_NOT_ACTIVE,
 +                                                  0,
 +                                                  20))
                                DRM_ERROR("ULPS not active\n");
  
                        /* Exit ULPS */
  
        /* Wait for Stop state */
        for_each_dsi_port(port, intel_dsi->ports) {
 -              if (intel_wait_for_register(dev_priv,
 -                              MIPI_CTRL(port), GLK_DATA_LANE_STOP_STATE,
 -                              GLK_DATA_LANE_STOP_STATE, 20))
 +              if (intel_wait_for_register(&dev_priv->uncore,
 +                                          MIPI_CTRL(port),
 +                                          GLK_DATA_LANE_STOP_STATE,
 +                                          GLK_DATA_LANE_STOP_STATE,
 +                                          20))
                        DRM_ERROR("Date lane not in STOP state\n");
        }
  
        /* Wait for AFE LATCH */
        for_each_dsi_port(port, intel_dsi->ports) {
 -              if (intel_wait_for_register(dev_priv,
 -                              BXT_MIPI_PORT_CTRL(port), AFE_LATCHOUT,
 -                              AFE_LATCHOUT, 20))
 +              if (intel_wait_for_register(&dev_priv->uncore,
 +                                          BXT_MIPI_PORT_CTRL(port),
 +                                          AFE_LATCHOUT,
 +                                          AFE_LATCHOUT,
 +                                          20))
                        DRM_ERROR("D-PHY not entering LP-11 state\n");
        }
  }
@@@ -548,7 -559,7 +570,7 @@@ static void glk_dsi_enter_low_power_mod
  
        /* Wait for MIPI PHY status bit to unset */
        for_each_dsi_port(port, intel_dsi->ports) {
 -              if (intel_wait_for_register(dev_priv,
 +              if (intel_wait_for_register(&dev_priv->uncore,
                                            MIPI_CTRL(port),
                                            GLK_PHY_STATUS_PORT_READY, 0, 20))
                        DRM_ERROR("PHY is not turning OFF\n");
  
        /* Wait for Pwr ACK bit to unset */
        for_each_dsi_port(port, intel_dsi->ports) {
 -              if (intel_wait_for_register(dev_priv,
 +              if (intel_wait_for_register(&dev_priv->uncore,
                                            MIPI_CTRL(port),
                                            GLK_MIPIIO_PORT_POWERED, 0, 20))
                        DRM_ERROR("MIPI IO Port is not powergated\n");
@@@ -577,7 -588,7 +599,7 @@@ static void glk_dsi_disable_mipi_io(str
  
        /* Wait for MIPI PHY status bit to unset */
        for_each_dsi_port(port, intel_dsi->ports) {
 -              if (intel_wait_for_register(dev_priv,
 +              if (intel_wait_for_register(&dev_priv->uncore,
                                            MIPI_CTRL(port),
                                            GLK_PHY_STATUS_PORT_READY, 0, 20))
                        DRM_ERROR("PHY is not turning OFF\n");
@@@ -627,7 -638,7 +649,7 @@@ static void vlv_dsi_clear_device_ready(
                 * Port A only. MIPI Port C has no similar bit for checking.
                 */
                if ((IS_GEN9_LP(dev_priv) || port == PORT_A) &&
 -                  intel_wait_for_register(dev_priv,
 +                  intel_wait_for_register(&dev_priv->uncore,
                                            port_ctrl, AFE_LATCHOUT, 0,
                                            30))
                        DRM_ERROR("DSI LP not going Low\n");
@@@ -1082,6 -1093,8 +1104,8 @@@ static void bxt_dsi_get_pipe_config(str
        bpp = mipi_dsi_pixel_format_to_bpp(
                        pixel_format_from_register_bits(fmt));
  
+       pipe_config->pipe_bpp = bdw_get_pipemisc_bpp(crtc);
        /* Enable Frame time stamo based scanline reporting */
        adjusted_mode->private_flags |=
                        I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP;
@@@ -1669,7 -1682,7 +1693,7 @@@ void vlv_dsi_init(struct drm_i915_priva
        struct drm_encoder *encoder;
        struct intel_connector *intel_connector;
        struct drm_connector *connector;
 -      struct drm_display_mode *scan, *fixed_mode = NULL;
 +      struct drm_display_mode *fixed_mode;
        enum port port;
  
        DRM_DEBUG_KMS("\n");
        intel_connector_attach_encoder(intel_connector, intel_encoder);
  
        mutex_lock(&dev->mode_config.mutex);
 -      intel_dsi_vbt_get_modes(intel_dsi);
 -      list_for_each_entry(scan, &connector->probed_modes, head) {
 -              if ((scan->type & DRM_MODE_TYPE_PREFERRED)) {
 -                      fixed_mode = drm_mode_duplicate(dev, scan);
 -                      break;
 -              }
 -      }
 +      fixed_mode = intel_panel_vbt_fixed_mode(intel_connector);
        mutex_unlock(&dev->mode_config.mutex);
  
        if (!fixed_mode) {
                goto err;
        }
  
 -      connector->display_info.width_mm = fixed_mode->width_mm;
 -      connector->display_info.height_mm = fixed_mode->height_mm;
 -
        intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
        intel_panel_setup_backlight(connector, INVALID_PIPE);
  
index 937cfabb95df122804f3bf35099dfa1d73ab1e12,8a4ebcb6405cee2427d0889ea49a0d871d2cc5ba..faf1b1b0357cdf13d7f307cc3469687adf48ff0f
@@@ -48,6 -48,7 +48,6 @@@
  #include "meson_vpp.h"
  #include "meson_viu.h"
  #include "meson_venc.h"
 -#include "meson_canvas.h"
  #include "meson_registers.h"
  
  #define DRIVER_NAME "meson"
@@@ -230,31 -231,50 +230,31 @@@ static int meson_drv_bind_master(struc
        }
  
        priv->canvas = meson_canvas_get(dev);
 -      if (!IS_ERR(priv->canvas)) {
 -              ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_osd1);
 -              if (ret)
 -                      goto free_drm;
 -              ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_vd1_0);
 -              if (ret) {
 -                      meson_canvas_free(priv->canvas, priv->canvas_id_osd1);
 -                      goto free_drm;
 -              }
 -              ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_vd1_1);
 -              if (ret) {
 -                      meson_canvas_free(priv->canvas, priv->canvas_id_osd1);
 -                      meson_canvas_free(priv->canvas, priv->canvas_id_vd1_0);
 -                      goto free_drm;
 -              }
 -              ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_vd1_2);
 -              if (ret) {
 -                      meson_canvas_free(priv->canvas, priv->canvas_id_osd1);
 -                      meson_canvas_free(priv->canvas, priv->canvas_id_vd1_0);
 -                      meson_canvas_free(priv->canvas, priv->canvas_id_vd1_1);
 -                      goto free_drm;
 -              }
 -      } else {
 -              priv->canvas = NULL;
 -
 -              res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dmc");
 -              if (!res) {
 -                      ret = -EINVAL;
 -                      goto free_drm;
 -              }
 -              /* Simply ioremap since it may be a shared register zone */
 -              regs = devm_ioremap(dev, res->start, resource_size(res));
 -              if (!regs) {
 -                      ret = -EADDRNOTAVAIL;
 -                      goto free_drm;
 -              }
 +      if (IS_ERR(priv->canvas)) {
 +              ret = PTR_ERR(priv->canvas);
 +              goto free_drm;
 +      }
  
 -              priv->dmc = devm_regmap_init_mmio(dev, regs,
 -                                                &meson_regmap_config);
 -              if (IS_ERR(priv->dmc)) {
 -                      dev_err(&pdev->dev, "Couldn't create the DMC regmap\n");
 -                      ret = PTR_ERR(priv->dmc);
 -                      goto free_drm;
 -              }
 +      ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_osd1);
 +      if (ret)
 +              goto free_drm;
 +      ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_vd1_0);
 +      if (ret) {
 +              meson_canvas_free(priv->canvas, priv->canvas_id_osd1);
 +              goto free_drm;
 +      }
 +      ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_vd1_1);
 +      if (ret) {
 +              meson_canvas_free(priv->canvas, priv->canvas_id_osd1);
 +              meson_canvas_free(priv->canvas, priv->canvas_id_vd1_0);
 +              goto free_drm;
 +      }
 +      ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_vd1_2);
 +      if (ret) {
 +              meson_canvas_free(priv->canvas, priv->canvas_id_osd1);
 +              meson_canvas_free(priv->canvas, priv->canvas_id_vd1_0);
 +              meson_canvas_free(priv->canvas, priv->canvas_id_vd1_1);
 +              goto free_drm;
        }
  
        priv->vsync_irq = platform_get_irq(pdev, 0);
  
        ret = drm_dev_register(drm, 0);
        if (ret)
-               goto free_drm;
+               goto uninstall_irq;
  
        drm_fbdev_generic_setup(drm, 32);
  
        return 0;
  
+ uninstall_irq:
+       drm_irq_uninstall(drm);
  free_drm:
        drm_dev_put(drm);
  
@@@ -336,8 -358,8 +338,8 @@@ static int meson_drv_bind(struct devic
  
  static void meson_drv_unbind(struct device *dev)
  {
-       struct drm_device *drm = dev_get_drvdata(dev);
-       struct meson_drm *priv = drm->dev_private;
+       struct meson_drm *priv = dev_get_drvdata(dev);
+       struct drm_device *drm = priv->drm;
  
        if (priv->canvas) {
                meson_canvas_free(priv->canvas, priv->canvas_id_osd1);
        }
  
        drm_dev_unregister(drm);
+       drm_irq_uninstall(drm);
        drm_kms_helper_poll_fini(drm);
        drm_mode_config_cleanup(drm);
        drm_dev_put(drm);
@@@ -444,7 -467,6 +447,7 @@@ static const struct of_device_id dt_mat
        { .compatible = "amlogic,meson-gxbb-vpu" },
        { .compatible = "amlogic,meson-gxl-vpu" },
        { .compatible = "amlogic,meson-gxm-vpu" },
 +      { .compatible = "amlogic,meson-g12a-vpu" },
        {}
  };
  MODULE_DEVICE_TABLE(of, dt_match);
index 2a860d158f4f9faba4b2674756e3064ff8436a84,563953ec6ad03fd904c2e5c38de8cbe1dc2edce0..779da21143b9b92785aa668277e8479663218774
@@@ -20,7 -20,6 +20,7 @@@
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/component.h>
 +#include <linux/of_device.h>
  #include <linux/of_graph.h>
  #include <linux/reset.h>
  #include <linux/clk.h>
  #define HDMITX_TOP_ADDR_REG   0x0
  #define HDMITX_TOP_DATA_REG   0x4
  #define HDMITX_TOP_CTRL_REG   0x8
 +#define HDMITX_TOP_G12A_OFFSET        0x8000
  
  /* Controller Communication Channel */
  #define HDMITX_DWC_ADDR_REG   0x10
  #define HHI_HDMI_PHY_CNTL1    0x3a4 /* 0xe9 */
  #define HHI_HDMI_PHY_CNTL2    0x3a8 /* 0xea */
  #define HHI_HDMI_PHY_CNTL3    0x3ac /* 0xeb */
 +#define HHI_HDMI_PHY_CNTL4    0x3b0 /* 0xec */
 +#define HHI_HDMI_PHY_CNTL5    0x3b4 /* 0xed */
  
  static DEFINE_SPINLOCK(reg_lock);
  
@@@ -131,26 -127,12 +131,26 @@@ enum meson_venc_source 
        MESON_VENC_SOURCE_ENCP = 2,
  };
  
 +struct meson_dw_hdmi;
 +
 +struct meson_dw_hdmi_data {
 +      unsigned int    (*top_read)(struct meson_dw_hdmi *dw_hdmi,
 +                                  unsigned int addr);
 +      void            (*top_write)(struct meson_dw_hdmi *dw_hdmi,
 +                                   unsigned int addr, unsigned int data);
 +      unsigned int    (*dwc_read)(struct meson_dw_hdmi *dw_hdmi,
 +                                  unsigned int addr);
 +      void            (*dwc_write)(struct meson_dw_hdmi *dw_hdmi,
 +                                   unsigned int addr, unsigned int data);
 +};
 +
  struct meson_dw_hdmi {
        struct drm_encoder encoder;
        struct dw_hdmi_plat_data dw_plat_data;
        struct meson_drm *priv;
        struct device *dev;
        void __iomem *hdmitx;
 +      const struct meson_dw_hdmi_data *data;
        struct reset_control *hdmitx_apb;
        struct reset_control *hdmitx_ctrl;
        struct reset_control *hdmitx_phy;
@@@ -192,12 -174,6 +192,12 @@@ static unsigned int dw_hdmi_top_read(st
        return data;
  }
  
 +static unsigned int dw_hdmi_g12a_top_read(struct meson_dw_hdmi *dw_hdmi,
 +                                        unsigned int addr)
 +{
 +      return readl(dw_hdmi->hdmitx + HDMITX_TOP_G12A_OFFSET + (addr << 2));
 +}
 +
  static inline void dw_hdmi_top_write(struct meson_dw_hdmi *dw_hdmi,
                                     unsigned int addr, unsigned int data)
  {
        spin_unlock_irqrestore(&reg_lock, flags);
  }
  
 +static inline void dw_hdmi_g12a_top_write(struct meson_dw_hdmi *dw_hdmi,
 +                                        unsigned int addr, unsigned int data)
 +{
 +      writel(data, dw_hdmi->hdmitx + HDMITX_TOP_G12A_OFFSET + (addr << 2));
 +}
 +
  /* Helper to change specific bits in PHY registers */
  static inline void dw_hdmi_top_write_bits(struct meson_dw_hdmi *dw_hdmi,
                                          unsigned int addr,
                                          unsigned int mask,
                                          unsigned int val)
  {
 -      unsigned int data = dw_hdmi_top_read(dw_hdmi, addr);
 +      unsigned int data = dw_hdmi->data->top_read(dw_hdmi, addr);
  
        data &= ~mask;
        data |= val;
  
 -      dw_hdmi_top_write(dw_hdmi, addr, data);
 +      dw_hdmi->data->top_write(dw_hdmi, addr, data);
  }
  
  static unsigned int dw_hdmi_dwc_read(struct meson_dw_hdmi *dw_hdmi,
        return data;
  }
  
 +static unsigned int dw_hdmi_g12a_dwc_read(struct meson_dw_hdmi *dw_hdmi,
 +                                        unsigned int addr)
 +{
 +      return readb(dw_hdmi->hdmitx + addr);
 +}
 +
  static inline void dw_hdmi_dwc_write(struct meson_dw_hdmi *dw_hdmi,
                                     unsigned int addr, unsigned int data)
  {
        spin_unlock_irqrestore(&reg_lock, flags);
  }
  
 +static inline void dw_hdmi_g12a_dwc_write(struct meson_dw_hdmi *dw_hdmi,
 +                                        unsigned int addr, unsigned int data)
 +{
 +      writeb(data, dw_hdmi->hdmitx + addr);
 +}
 +
  /* Helper to change specific bits in controller registers */
  static inline void dw_hdmi_dwc_write_bits(struct meson_dw_hdmi *dw_hdmi,
                                          unsigned int addr,
                                          unsigned int mask,
                                          unsigned int val)
  {
 -      unsigned int data = dw_hdmi_dwc_read(dw_hdmi, addr);
 +      unsigned int data = dw_hdmi->data->dwc_read(dw_hdmi, addr);
  
        data &= ~mask;
        data |= val;
  
 -      dw_hdmi_dwc_write(dw_hdmi, addr, data);
 +      dw_hdmi->data->dwc_write(dw_hdmi, addr, data);
  }
  
  /* Bridge */
@@@ -342,24 -300,6 +342,24 @@@ static void meson_hdmi_phy_setup_mode(s
                        regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33632122);
                        regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2000115b);
                }
 +      } else if (dw_hdmi_is_compatible(dw_hdmi,
 +                                       "amlogic,meson-g12a-dw-hdmi")) {
 +              if (pixel_clock >= 371250) {
 +                      /* 5.94Gbps, 3.7125Gbps */
 +                      regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x37eb65c4);
 +                      regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
 +                      regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL5, 0x0000080b);
 +              } else if (pixel_clock >= 297000) {
 +                      /* 2.97Gbps */
 +                      regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33eb6262);
 +                      regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
 +                      regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL5, 0x00000003);
 +              } else {
 +                      /* 1.485Gbps, and below */
 +                      regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33eb4242);
 +                      regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
 +                      regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL5, 0x00000003);
 +              }
        }
  }
  
@@@ -435,7 -375,7 +435,7 @@@ static int dw_hdmi_phy_init(struct dw_h
        regmap_update_bits(priv->hhi, HHI_MEM_PD_REG0, 0xff << 8, 0);
  
        /* Bring out of reset */
 -      dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_SW_RESET,  0);
 +      dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_SW_RESET,  0);
  
        /* Enable internal pixclk, tmds_clk, spdif_clk, i2s_clk, cecclk */
        dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_CLK_CNTL,
                               0x3 << 4, 0x3 << 4);
  
        /* Enable normal output to PHY */
 -      dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_BIST_CNTL, BIT(12));
 +      dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_BIST_CNTL, BIT(12));
  
        /* TMDS pattern setup (TOFIX Handle the YUV420 case) */
        if (mode->clock > 340000) {
 -              dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01, 0);
 -              dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23,
 +              dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01,
 +                                0);
 +              dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23,
                                  0x03ff03ff);
        } else {
 -              dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01,
 +              dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01,
                                  0x001f001f);
 -              dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23,
 +              dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23,
                                  0x001f001f);
        }
  
        /* Load TMDS pattern */
 -      dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x1);
 +      dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x1);
        msleep(20);
 -      dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x2);
 +      dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x2);
  
        /* Setup PHY parameters */
        meson_hdmi_phy_setup_mode(dw_hdmi, mode);
  
        /* BIT_INVERT */
        if (dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
 -          dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxm-dw-hdmi"))
 +          dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxm-dw-hdmi") ||
 +          dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-g12a-dw-hdmi"))
                regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1,
                                   BIT(17), 0);
        else
@@@ -542,7 -480,7 +542,7 @@@ static enum drm_connector_status dw_hdm
  {
        struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
  
 -      return !!dw_hdmi_top_read(dw_hdmi, HDMITX_TOP_STAT0) ?
 +      return !!dw_hdmi->data->top_read(dw_hdmi, HDMITX_TOP_STAT0) ?
                connector_status_connected : connector_status_disconnected;
  }
  
@@@ -552,11 -490,11 +552,11 @@@ static void dw_hdmi_setup_hpd(struct dw
        struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
  
        /* Setup HPD Filter */
 -      dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_HPD_FILTER,
 +      dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_HPD_FILTER,
                          (0xa << 12) | 0xa0);
  
        /* Clear interrupts */
 -      dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR,
 +      dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR,
                          HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL);
  
        /* Unmask interrupts */
@@@ -577,8 -515,8 +577,8 @@@ static irqreturn_t dw_hdmi_top_irq(int 
        struct meson_dw_hdmi *dw_hdmi = dev_id;
        u32 stat;
  
 -      stat = dw_hdmi_top_read(dw_hdmi, HDMITX_TOP_INTR_STAT);
 -      dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR, stat);
 +      stat = dw_hdmi->data->top_read(dw_hdmi, HDMITX_TOP_INTR_STAT);
 +      dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR, stat);
  
        /* HPD Events, handle in the threaded interrupt handler */
        if (stat & (HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL)) {
@@@ -631,7 -569,8 +631,8 @@@ dw_hdmi_mode_valid(struct drm_connecto
        DRM_DEBUG_DRIVER("Modeline " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
  
        /* If sink max TMDS clock, we reject the mode */
-       if (mode->clock > connector->display_info.max_tmds_clock)
+       if (connector->display_info.max_tmds_clock &&
+           mode->clock > connector->display_info.max_tmds_clock)
                return MODE_BAD;
  
        /* Check against non-VIC supported modes */
@@@ -747,9 -686,7 +748,9 @@@ static const struct drm_encoder_helper_
  static int meson_dw_hdmi_reg_read(void *context, unsigned int reg,
                                  unsigned int *result)
  {
 -      *result = dw_hdmi_dwc_read(context, reg);
 +      struct meson_dw_hdmi *dw_hdmi = context;
 +
 +      *result = dw_hdmi->data->dwc_read(dw_hdmi, reg);
  
        return 0;
  
  static int meson_dw_hdmi_reg_write(void *context, unsigned int reg,
                                   unsigned int val)
  {
 -      dw_hdmi_dwc_write(context, reg, val);
 +      struct meson_dw_hdmi *dw_hdmi = context;
 +
 +      dw_hdmi->data->dwc_write(dw_hdmi, reg, val);
  
        return 0;
  }
@@@ -774,20 -709,6 +775,20 @@@ static const struct regmap_config meson
        .fast_io = true,
  };
  
 +static const struct meson_dw_hdmi_data meson_dw_hdmi_gx_data = {
 +      .top_read = dw_hdmi_top_read,
 +      .top_write = dw_hdmi_top_write,
 +      .dwc_read = dw_hdmi_dwc_read,
 +      .dwc_write = dw_hdmi_dwc_write,
 +};
 +
 +static const struct meson_dw_hdmi_data meson_dw_hdmi_g12a_data = {
 +      .top_read = dw_hdmi_g12a_top_read,
 +      .top_write = dw_hdmi_g12a_top_write,
 +      .dwc_read = dw_hdmi_g12a_dwc_read,
 +      .dwc_write = dw_hdmi_g12a_dwc_write,
 +};
 +
  static bool meson_hdmi_connector_is_available(struct device *dev)
  {
        struct device_node *ep, *remote;
@@@ -814,7 -735,6 +815,7 @@@ static int meson_dw_hdmi_bind(struct de
                                void *data)
  {
        struct platform_device *pdev = to_platform_device(dev);
 +      const struct meson_dw_hdmi_data *match;
        struct meson_dw_hdmi *meson_dw_hdmi;
        struct drm_device *drm = data;
        struct meson_drm *priv = drm->dev_private;
                return -ENODEV;
        }
  
 +      match = of_device_get_match_data(&pdev->dev);
 +      if (!match) {
 +              dev_err(&pdev->dev, "failed to get match data\n");
 +              return -ENODEV;
 +      }
 +
        meson_dw_hdmi = devm_kzalloc(dev, sizeof(*meson_dw_hdmi),
                                     GFP_KERNEL);
        if (!meson_dw_hdmi)
  
        meson_dw_hdmi->priv = priv;
        meson_dw_hdmi->dev = dev;
 +      meson_dw_hdmi->data = match;
        dw_plat_data = &meson_dw_hdmi->dw_plat_data;
        encoder = &meson_dw_hdmi->encoder;
  
        reset_control_reset(meson_dw_hdmi->hdmitx_phy);
  
        /* Enable APB3 fail on error */
 -      writel_bits_relaxed(BIT(15), BIT(15),
 -                          meson_dw_hdmi->hdmitx + HDMITX_TOP_CTRL_REG);
 -      writel_bits_relaxed(BIT(15), BIT(15),
 -                          meson_dw_hdmi->hdmitx + HDMITX_DWC_CTRL_REG);
 +      if (!meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
 +              writel_bits_relaxed(BIT(15), BIT(15),
 +                                  meson_dw_hdmi->hdmitx + HDMITX_TOP_CTRL_REG);
 +              writel_bits_relaxed(BIT(15), BIT(15),
 +                                  meson_dw_hdmi->hdmitx + HDMITX_DWC_CTRL_REG);
 +      }
  
        /* Bring out of reset */
 -      dw_hdmi_top_write(meson_dw_hdmi, HDMITX_TOP_SW_RESET,  0);
 +      meson_dw_hdmi->data->top_write(meson_dw_hdmi,
 +                                     HDMITX_TOP_SW_RESET,  0);
  
        msleep(20);
  
 -      dw_hdmi_top_write(meson_dw_hdmi, HDMITX_TOP_CLK_CNTL, 0xff);
 +      meson_dw_hdmi->data->top_write(meson_dw_hdmi,
 +                                     HDMITX_TOP_CLK_CNTL, 0xff);
  
        /* Enable HDMI-TX Interrupt */
 -      dw_hdmi_top_write(meson_dw_hdmi, HDMITX_TOP_INTR_STAT_CLR,
 -                        HDMITX_TOP_INTR_CORE);
 +      meson_dw_hdmi->data->top_write(meson_dw_hdmi, HDMITX_TOP_INTR_STAT_CLR,
 +                                     HDMITX_TOP_INTR_CORE);
  
 -      dw_hdmi_top_write(meson_dw_hdmi, HDMITX_TOP_INTR_MASKN,
 -                        HDMITX_TOP_INTR_CORE);
 +      meson_dw_hdmi->data->top_write(meson_dw_hdmi, HDMITX_TOP_INTR_MASKN,
 +                                     HDMITX_TOP_INTR_CORE);
  
        /* Bridge / Connector */
  
@@@ -1015,14 -924,9 +1016,14 @@@ static int meson_dw_hdmi_remove(struct 
  }
  
  static const struct of_device_id meson_dw_hdmi_of_table[] = {
 -      { .compatible = "amlogic,meson-gxbb-dw-hdmi" },
 -      { .compatible = "amlogic,meson-gxl-dw-hdmi" },
 -      { .compatible = "amlogic,meson-gxm-dw-hdmi" },
 +      { .compatible = "amlogic,meson-gxbb-dw-hdmi",
 +        .data = &meson_dw_hdmi_gx_data },
 +      { .compatible = "amlogic,meson-gxl-dw-hdmi",
 +        .data = &meson_dw_hdmi_gx_data },
 +      { .compatible = "amlogic,meson-gxm-dw-hdmi",
 +        .data = &meson_dw_hdmi_gx_data },
 +      { .compatible = "amlogic,meson-g12a-dw-hdmi",
 +        .data = &meson_dw_hdmi_g12a_data },
        { }
  };
  MODULE_DEVICE_TABLE(of, meson_dw_hdmi_of_table);
index a7cbf6c9a1531722b79e044bed478d6bdc724a4f,0d4ade9d4722c340b706b82d7ea7bb587db5f293..20a9c296d0272d7ef8ad89cf6f66a81deace12c4
@@@ -541,6 -541,18 +541,18 @@@ static void vop_core_clks_disable(struc
        clk_disable(vop->hclk);
  }
  
+ static void vop_win_disable(struct vop *vop, const struct vop_win_data *win)
+ {
+       if (win->phy->scl && win->phy->scl->ext) {
+               VOP_SCL_SET_EXT(vop, win, yrgb_hor_scl_mode, SCALE_NONE);
+               VOP_SCL_SET_EXT(vop, win, yrgb_ver_scl_mode, SCALE_NONE);
+               VOP_SCL_SET_EXT(vop, win, cbcr_hor_scl_mode, SCALE_NONE);
+               VOP_SCL_SET_EXT(vop, win, cbcr_ver_scl_mode, SCALE_NONE);
+       }
+       VOP_WIN_SET(vop, win, enable, 0);
+ }
  static int vop_enable(struct drm_crtc *crtc)
  {
        struct vop *vop = to_vop(crtc);
                struct vop_win *vop_win = &vop->win[i];
                const struct vop_win_data *win = vop_win->data;
  
-               VOP_WIN_SET(vop, win, enable, 0);
+               vop_win_disable(vop, win);
        }
        spin_unlock(&vop->reg_lock);
  
@@@ -735,7 -747,7 +747,7 @@@ static void vop_plane_atomic_disable(st
  
        spin_lock(&vop->reg_lock);
  
-       VOP_WIN_SET(vop, win, enable, 0);
+       vop_win_disable(vop, win);
  
        spin_unlock(&vop->reg_lock);
  }
@@@ -1029,7 -1041,6 +1041,7 @@@ static void vop_crtc_atomic_enable(stru
        u16 vact_st = adjusted_mode->vtotal - adjusted_mode->vsync_start;
        u16 vact_end = vact_st + vdisplay;
        uint32_t pin_pol, val;
 +      int dither_bpc = s->output_bpc ? s->output_bpc : 10;
        int ret;
  
        mutex_lock(&vop->vop_lock);
            !(vop_data->feature & VOP_FEATURE_OUTPUT_RGB10))
                s->output_mode = ROCKCHIP_OUT_MODE_P888;
  
 -      if (s->output_mode == ROCKCHIP_OUT_MODE_AAAA && s->output_bpc == 8)
 +      if (s->output_mode == ROCKCHIP_OUT_MODE_AAAA && dither_bpc <= 8)
                VOP_REG_SET(vop, common, pre_dither_down, 1);
        else
                VOP_REG_SET(vop, common, pre_dither_down, 0);
  
 +      if (dither_bpc == 6) {
 +              VOP_REG_SET(vop, common, dither_down_sel, DITHER_DOWN_ALLEGRO);
 +              VOP_REG_SET(vop, common, dither_down_mode, RGB888_TO_RGB666);
 +              VOP_REG_SET(vop, common, dither_down_en, 1);
 +      } else {
 +              VOP_REG_SET(vop, common, dither_down_en, 0);
 +      }
 +
        VOP_REG_SET(vop, common, out_mode, s->output_mode);
  
        VOP_REG_SET(vop, modeset, htotal_pw, (htotal << 16) | hsync_len);
@@@ -1631,7 -1634,7 +1643,7 @@@ static int vop_initial(struct vop *vop
                int channel = i * 2 + 1;
  
                VOP_WIN_SET(vop, win, channel, (channel + 1) << 4 | channel);
-               VOP_WIN_SET(vop, win, enable, 0);
+               vop_win_disable(vop, win);
                VOP_WIN_SET(vop, win, gate, 1);
        }
  
index 53b7b8c04bc602916a0ccf097f2b76a8ba7a3c9e,ff47f890e6ad8d554fa7180aab449321a34ce5c1..b7d01b3664cb2714d3c984c3fff57bff5f5b158f
@@@ -52,6 -52,7 +52,7 @@@ static struct drm_driver driver = 
        .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME,
        .load = udl_driver_load,
        .unload = udl_driver_unload,
+       .release = udl_driver_release,
  
        /* gem hooks */
        .gem_free_object_unlocked = udl_gem_free_object,
@@@ -107,7 -108,6 +108,7 @@@ static void udl_usb_disconnect(struct u
        udl_fbdev_unplug(dev);
        udl_drop_usb(dev);
        drm_dev_unplug(dev);
 +      drm_dev_put(dev);
  }
  
  /*
diff --combined drivers/staging/Kconfig
index dee9e928d9dda9c10f679627eddf21a239c9f1cb,62951e836cbc879d1e4be6ba158a8230ebec2c52..e166969033a25d5b1ea65e3ff1cfd0b90c3da0c4
@@@ -96,6 -96,8 +96,6 @@@ source "drivers/staging/greybus/Kconfig
  
  source "drivers/staging/vc04_services/Kconfig"
  
 -source "drivers/staging/vboxvideo/Kconfig"
 -
  source "drivers/staging/pi433/Kconfig"
  
  source "drivers/staging/mt7621-pci/Kconfig"
@@@ -112,8 -114,6 +112,6 @@@ source "drivers/staging/ralink-gdma/Kco
  
  source "drivers/staging/mt7621-mmc/Kconfig"
  
- source "drivers/staging/mt7621-eth/Kconfig"
  source "drivers/staging/mt7621-dts/Kconfig"
  
  source "drivers/staging/gasket/Kconfig"
diff --combined drivers/staging/Makefile
index d344078c5458e70dfedefd2a5a13eca83ceefa89,d1b17ddcd354de10c68455bc64e802c101a59e7d..afa9dd4d3641a8be22b28f0be930ddfb8cc02fd8
@@@ -38,6 -38,7 +38,6 @@@ obj-$(CONFIG_MOST)            += most
  obj-$(CONFIG_KS7010)          += ks7010/
  obj-$(CONFIG_GREYBUS)         += greybus/
  obj-$(CONFIG_BCM2835_VCHIQ)   += vc04_services/
 -obj-$(CONFIG_DRM_VBOXVIDEO)   += vboxvideo/
  obj-$(CONFIG_PI433)           += pi433/
  obj-$(CONFIG_PCI_MT7621)      += mt7621-pci/
  obj-$(CONFIG_PCI_MT7621_PHY)  += mt7621-pci-phy/
@@@ -46,7 -47,6 +46,6 @@@ obj-$(CONFIG_SPI_MT7621)      += mt7621-spi
  obj-$(CONFIG_SOC_MT7621)      += mt7621-dma/
  obj-$(CONFIG_DMA_RALINK)      += ralink-gdma/
  obj-$(CONFIG_MTK_MMC)         += mt7621-mmc/
- obj-$(CONFIG_NET_MEDIATEK_SOC_STAGING)        += mt7621-eth/
  obj-$(CONFIG_SOC_MT7621)      += mt7621-dts/
  obj-$(CONFIG_STAGING_GASKET_FRAMEWORK)        += gasket/
  obj-$(CONFIG_XIL_AXIS_FIFO)   += axis-fifo/
index 8f3602811eb532eb255d57855f54400a6aeb218b,ce4de6b1e444a855d04cc9afe5c7ebca5833a1a6..f9c94c2a1364699a2c89dd535b52a2d204e4ef40
@@@ -49,8 -49,6 +49,8 @@@
   */
  
  enum mode_set_atomic;
 +struct drm_writeback_connector;
 +struct drm_writeback_job;
  
  /**
   * struct drm_crtc_helper_funcs - helper operations for CRTCs
@@@ -420,6 -418,8 +420,8 @@@ struct drm_crtc_helper_funcs 
         * Drivers can use the @old_crtc_state input parameter if the operations
         * needed to enable the CRTC don't depend solely on the new state but
         * also on the transition between the old state and the new state.
+        *
+        * This function is optional.
         */
        void (*atomic_enable)(struct drm_crtc *crtc,
                              struct drm_crtc_state *old_crtc_state);
         * parameter @old_crtc_state which could be used to access the old
         * state. Atomic drivers should consider to use this one instead
         * of @disable.
+        *
+        * This function is optional.
         */
        void (*atomic_disable)(struct drm_crtc *crtc,
                               struct drm_crtc_state *old_crtc_state);
@@@ -991,11 -993,6 +995,11 @@@ struct drm_connector_helper_funcs 
         */
        void (*atomic_commit)(struct drm_connector *connector,
                              struct drm_connector_state *state);
 +
 +      int (*prepare_writeback_job)(struct drm_writeback_connector *connector,
 +                                   struct drm_writeback_job *job);
 +      void (*cleanup_writeback_job)(struct drm_writeback_connector *connector,
 +                                    struct drm_writeback_job *job);
  };
  
  /**
index 13915fdc6a54c0335bc2ad6af283f6be97cb9f39,1ea51e3b942a034a1b487bb2ad7dc054893a4d39..dfe7e755f594df25ee4547ece4f6ee72d28f761a
@@@ -69,35 -69,33 +69,39 @@@ void snd_hdac_display_power(struct hdac
  
        dev_dbg(bus->dev, "display power %s\n",
                enable ? "enable" : "disable");
+       mutex_lock(&bus->lock);
        if (enable)
                set_bit(idx, &bus->display_power_status);
        else
                clear_bit(idx, &bus->display_power_status);
  
        if (!acomp || !acomp->ops)
-               return;
+               goto unlock;
  
        if (bus->display_power_status) {
                if (!bus->display_power_active) {
 +                      unsigned long cookie = -1;
 +
                        if (acomp->ops->get_power)
 -                              acomp->ops->get_power(acomp->dev);
 +                              cookie = acomp->ops->get_power(acomp->dev);
 +
                        snd_hdac_set_codec_wakeup(bus, true);
                        snd_hdac_set_codec_wakeup(bus, false);
 -                      bus->display_power_active = true;
 +                      bus->display_power_active = cookie;
                }
        } else {
                if (bus->display_power_active) {
 +                      unsigned long cookie = bus->display_power_active;
 +
                        if (acomp->ops->put_power)
 -                              acomp->ops->put_power(acomp->dev);
 -                      bus->display_power_active = false;
 +                              acomp->ops->put_power(acomp->dev, cookie);
 +
 +                      bus->display_power_active = 0;
                }
        }
+  unlock:
+       mutex_unlock(&bus->lock);
  }
  EXPORT_SYMBOL_GPL(snd_hdac_display_power);
  
@@@ -331,9 -329,9 +335,9 @@@ int snd_hdac_acomp_exit(struct hdac_bu
                return 0;
  
        if (WARN_ON(bus->display_power_active) && acomp->ops)
 -              acomp->ops->put_power(acomp->dev);
 +              acomp->ops->put_power(acomp->dev, bus->display_power_active);
  
 -      bus->display_power_active = false;
 +      bus->display_power_active = 0;
        bus->display_power_status = 0;
  
        component_master_del(dev, &hdac_component_master_ops);
This page took 0.482513 seconds and 4 git commands to generate.