Merge tag 'drm-fixes-for-v4.9-rc4' of git://people.freedesktop.org/~airlied/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 4 Nov 2016 20:30:13 +0000 (13:30 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 4 Nov 2016 20:30:13 +0000 (13:30 -0700)
Pull drm fixes from Dave Airlie:
 "Fixes for amdgpu, radeon, intel, imx and virtio-gpu.

  This is a bit larger than I'd like, but I had some stuff I meant to
  send for -rc3 but was waiting for the PAT regression fix to land. So
  this is really fixes for rc3 and rc4 in one go.

  There are a set of fixes for an oops we've been seeing around MST
  display unplug, along with more suspend/resume and shutdown fixes for
  amdgpu, one power management follow on fix for nouveau, and set of imx
  fixes, and a single virtio-gpu regression fix"

* tag 'drm-fixes-for-v4.9-rc4' of git://people.freedesktop.org/~airlied/linux: (54 commits)
  virtio-gpu: fix vblank events
  drm/nouveau/acpi: fix check for power resources support
  drm/i915: Fix SKL+ 90/270 degree rotated plane coordinate computation
  drm/i915: Remove two invalid warns
  drm/i915: Rotated view does not need a fence
  drm/i915/fbc: fix CFB size calculation for gen8+
  drm: i915: Wait for fences on new fb, not old
  drm/i915: Clean up DDI DDC/AUX CH sanitation
  drm/i915: Respect alternate_aux_channel for all DDI ports
  drm/i915/gen9: fix watermarks when using the pipe scaler
  drm/i915: Fix mismatched INIT power domain disabling during suspend
  drm/i915: fix a read size argument
  drm/i915: Use fence_write() from rpm resume
  drm/i915/gen9: fix DDB partitioning for multi-screen cases
  drm/i915: workaround sparse warning on variable length arrays
  drm/i915: keep declarations in i915_drv.h
  drm/amd/powerplay: fix bug get wrong evv voltage of Polaris.
  drm/amdgpu/si_dpm: workaround for SI kickers
  drm/radeon/si_dpm: workaround for SI kickers
  drm/amdgpu: fix s3 resume back, uvd dpm randomly can't disable.
  ...

52 files changed:
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
drivers/gpu/drm/amd/amdgpu/ci_dpm.c
drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
drivers/gpu/drm/amd/amdgpu/kv_dpm.c
drivers/gpu/drm/amd/amdgpu/si_dpm.c
drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
drivers/gpu/drm/amd/amdgpu/vi.c
drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c
drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c
drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
drivers/gpu/drm/amd/scheduler/sched_fence.c
drivers/gpu/drm/drm_atomic.c
drivers/gpu/drm/drm_atomic_helper.c
drivers/gpu/drm/drm_dp_mst_topology.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/exynos/exynos_drm_drv.c
drivers/gpu/drm/exynos/exynos_drm_drv.h
drivers/gpu/drm/exynos/exynos_drm_fb.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_fence.c
drivers/gpu/drm/i915/i915_pci.c
drivers/gpu/drm/i915/intel_bios.c
drivers/gpu/drm/i915/intel_device_info.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_fbc.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/imx/imx-drm-core.c
drivers/gpu/drm/imx/ipuv3-plane.c
drivers/gpu/drm/nouveau/nouveau_acpi.c
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/radeon_dp_auxch.c
drivers/gpu/drm/radeon/si_dpm.c
drivers/gpu/drm/rcar-du/rcar_du_kms.c
drivers/gpu/drm/sti/sti_drv.c
drivers/gpu/drm/virtio/virtgpu_display.c
drivers/gpu/ipu-v3/ipu-image-convert.c
include/drm/drm_plane.h

index b0f6e69..82dc8d2 100644 (file)
@@ -519,7 +519,8 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
                r = ttm_eu_reserve_buffers(&p->ticket, &p->validated, true,
                                           &duplicates);
                if (unlikely(r != 0)) {
-                       DRM_ERROR("ttm_eu_reserve_buffers failed.\n");
+                       if (r != -ERESTARTSYS)
+                               DRM_ERROR("ttm_eu_reserve_buffers failed.\n");
                        goto error_free_pages;
                }
 
index b4f4a92..7ca07e7 100644 (file)
@@ -1959,6 +1959,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon)
        /* evict remaining vram memory */
        amdgpu_bo_evict_vram(adev);
 
+       amdgpu_atombios_scratch_regs_save(adev);
        pci_save_state(dev->pdev);
        if (suspend) {
                /* Shut down the device */
@@ -2010,6 +2011,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)
                        return r;
                }
        }
+       amdgpu_atombios_scratch_regs_restore(adev);
 
        /* post card */
        if (!amdgpu_card_posted(adev) || !resume) {
@@ -2268,8 +2270,6 @@ int amdgpu_gpu_reset(struct amdgpu_device *adev)
        }
 
        if (need_full_reset) {
-               /* save scratch */
-               amdgpu_atombios_scratch_regs_save(adev);
                r = amdgpu_suspend(adev);
 
 retry:
@@ -2279,8 +2279,9 @@ retry:
                        amdgpu_display_stop_mc_access(adev, &save);
                        amdgpu_wait_for_idle(adev, AMD_IP_BLOCK_TYPE_GMC);
                }
-
+               amdgpu_atombios_scratch_regs_save(adev);
                r = amdgpu_asic_reset(adev);
+               amdgpu_atombios_scratch_regs_restore(adev);
                /* post card */
                amdgpu_atom_asic_init(adev->mode_info.atom_context);
 
@@ -2288,8 +2289,6 @@ retry:
                        dev_info(adev->dev, "GPU reset succeeded, trying to resume\n");
                        r = amdgpu_resume(adev);
                }
-               /* restore scratch */
-               amdgpu_atombios_scratch_regs_restore(adev);
        }
        if (!r) {
                amdgpu_irq_gpu_reset_resume_helper(adev);
index 3a2e42f..77b34ec 100644 (file)
@@ -68,6 +68,7 @@ int amdgpu_fence_slab_init(void)
 
 void amdgpu_fence_slab_fini(void)
 {
+       rcu_barrier();
        kmem_cache_destroy(amdgpu_fence_slab);
 }
 /*
index 278708f..9fa8098 100644 (file)
@@ -239,6 +239,7 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
        if (r) {
                adev->irq.installed = false;
                flush_work(&adev->hotplug_work);
+               cancel_work_sync(&adev->reset_work);
                return r;
        }
 
@@ -264,6 +265,7 @@ void amdgpu_irq_fini(struct amdgpu_device *adev)
                if (adev->irq.msi_enabled)
                        pci_disable_msi(adev->pdev);
                flush_work(&adev->hotplug_work);
+               cancel_work_sync(&adev->reset_work);
        }
 
        for (i = 0; i < AMDGPU_MAX_IRQ_SRC_ID; ++i) {
index c2c7fb1..203d98b 100644 (file)
@@ -459,10 +459,8 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
                /* return all clocks in KHz */
                dev_info.gpu_counter_freq = amdgpu_asic_get_xclk(adev) * 10;
                if (adev->pm.dpm_enabled) {
-                       dev_info.max_engine_clock =
-                               adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.sclk * 10;
-                       dev_info.max_memory_clock =
-                               adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.mclk * 10;
+                       dev_info.max_engine_clock = amdgpu_dpm_get_sclk(adev, false) * 10;
+                       dev_info.max_memory_clock = amdgpu_dpm_get_mclk(adev, false) * 10;
                } else {
                        dev_info.max_engine_clock = adev->pm.default_sclk * 10;
                        dev_info.max_memory_clock = adev->pm.default_mclk * 10;
index 06f2432..968c426 100644 (file)
@@ -1758,5 +1758,6 @@ void amdgpu_vm_manager_fini(struct amdgpu_device *adev)
                fence_put(adev->vm_manager.ids[i].first);
                amdgpu_sync_free(&adev->vm_manager.ids[i].active);
                fence_put(id->flushed_updates);
+               fence_put(id->last_flush);
        }
 }
index 1d8c375..5be788b 100644 (file)
@@ -4075,7 +4075,7 @@ static int ci_enable_uvd_dpm(struct amdgpu_device *adev, bool enable)
                                                          pi->dpm_level_enable_mask.mclk_dpm_enable_mask);
                }
        } else {
-               if (pi->last_mclk_dpm_enable_mask & 0x1) {
+               if (pi->uvd_enabled) {
                        pi->uvd_enabled = false;
                        pi->dpm_level_enable_mask.mclk_dpm_enable_mask |= 1;
                        amdgpu_ci_send_msg_to_smc_with_parameter(adev,
@@ -6236,6 +6236,8 @@ static int ci_dpm_sw_fini(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+       flush_work(&adev->pm.dpm.thermal.work);
+
        mutex_lock(&adev->pm.mutex);
        amdgpu_pm_sysfs_fini(adev);
        ci_dpm_fini(adev);
index 4108c68..9260cae 100644 (file)
@@ -3151,10 +3151,6 @@ static int dce_v10_0_hw_fini(void *handle)
 
 static int dce_v10_0_suspend(void *handle)
 {
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-       amdgpu_atombios_scratch_regs_save(adev);
-
        return dce_v10_0_hw_fini(handle);
 }
 
@@ -3165,8 +3161,6 @@ static int dce_v10_0_resume(void *handle)
 
        ret = dce_v10_0_hw_init(handle);
 
-       amdgpu_atombios_scratch_regs_restore(adev);
-
        /* turn on the BL */
        if (adev->mode_info.bl_encoder) {
                u8 bl_level = amdgpu_display_backlight_get_level(adev,
index f264b8f..367739b 100644 (file)
@@ -3215,10 +3215,6 @@ static int dce_v11_0_hw_fini(void *handle)
 
 static int dce_v11_0_suspend(void *handle)
 {
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-       amdgpu_atombios_scratch_regs_save(adev);
-
        return dce_v11_0_hw_fini(handle);
 }
 
@@ -3229,8 +3225,6 @@ static int dce_v11_0_resume(void *handle)
 
        ret = dce_v11_0_hw_init(handle);
 
-       amdgpu_atombios_scratch_regs_restore(adev);
-
        /* turn on the BL */
        if (adev->mode_info.bl_encoder) {
                u8 bl_level = amdgpu_display_backlight_get_level(adev,
index b948d6c..15f9fc0 100644 (file)
@@ -2482,10 +2482,6 @@ static int dce_v6_0_hw_fini(void *handle)
 
 static int dce_v6_0_suspend(void *handle)
 {
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-       amdgpu_atombios_scratch_regs_save(adev);
-
        return dce_v6_0_hw_fini(handle);
 }
 
@@ -2496,8 +2492,6 @@ static int dce_v6_0_resume(void *handle)
 
        ret = dce_v6_0_hw_init(handle);
 
-       amdgpu_atombios_scratch_regs_restore(adev);
-
        /* turn on the BL */
        if (adev->mode_info.bl_encoder) {
                u8 bl_level = amdgpu_display_backlight_get_level(adev,
index 5966166..8c4d808 100644 (file)
@@ -3033,10 +3033,6 @@ static int dce_v8_0_hw_fini(void *handle)
 
 static int dce_v8_0_suspend(void *handle)
 {
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-       amdgpu_atombios_scratch_regs_save(adev);
-
        return dce_v8_0_hw_fini(handle);
 }
 
@@ -3047,8 +3043,6 @@ static int dce_v8_0_resume(void *handle)
 
        ret = dce_v8_0_hw_init(handle);
 
-       amdgpu_atombios_scratch_regs_restore(adev);
-
        /* turn on the BL */
        if (adev->mode_info.bl_encoder) {
                u8 bl_level = amdgpu_display_backlight_get_level(adev,
index ee6a48a..bb97182 100644 (file)
@@ -640,7 +640,6 @@ static const u32 stoney_mgcg_cgcg_init[] =
        mmCP_MEM_SLP_CNTL, 0xffffffff, 0x00020201,
        mmRLC_MEM_SLP_CNTL, 0xffffffff, 0x00020201,
        mmCGTS_SM_CTRL_REG, 0xffffffff, 0x96940200,
-       mmATC_MISC_CG, 0xffffffff, 0x000c0200,
 };
 
 static void gfx_v8_0_set_ring_funcs(struct amdgpu_device *adev);
index c22ef14..a16b220 100644 (file)
@@ -100,6 +100,7 @@ static const u32 cz_mgcg_cgcg_init[] =
 
 static const u32 stoney_mgcg_cgcg_init[] =
 {
+       mmATC_MISC_CG, 0xffffffff, 0x000c0200,
        mmMC_MEM_POWER_LS, 0xffffffff, 0x00000104
 };
 
index f8618a3..71d2856 100644 (file)
@@ -3063,6 +3063,8 @@ static int kv_dpm_sw_fini(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+       flush_work(&adev->pm.dpm.thermal.work);
+
        mutex_lock(&adev->pm.mutex);
        amdgpu_pm_sysfs_fini(adev);
        kv_dpm_fini(adev);
index 3de7bca..d6f85b1 100644 (file)
@@ -3477,6 +3477,49 @@ static void si_apply_state_adjust_rules(struct amdgpu_device *adev,
        int i;
        struct si_dpm_quirk *p = si_dpm_quirk_list;
 
+       /* limit all SI kickers */
+       if (adev->asic_type == CHIP_PITCAIRN) {
+               if ((adev->pdev->revision == 0x81) ||
+                   (adev->pdev->device == 0x6810) ||
+                   (adev->pdev->device == 0x6811) ||
+                   (adev->pdev->device == 0x6816) ||
+                   (adev->pdev->device == 0x6817) ||
+                   (adev->pdev->device == 0x6806))
+                       max_mclk = 120000;
+       } else if (adev->asic_type == CHIP_VERDE) {
+               if ((adev->pdev->revision == 0x81) ||
+                   (adev->pdev->revision == 0x83) ||
+                   (adev->pdev->revision == 0x87) ||
+                   (adev->pdev->device == 0x6820) ||
+                   (adev->pdev->device == 0x6821) ||
+                   (adev->pdev->device == 0x6822) ||
+                   (adev->pdev->device == 0x6823) ||
+                   (adev->pdev->device == 0x682A) ||
+                   (adev->pdev->device == 0x682B)) {
+                       max_sclk = 75000;
+                       max_mclk = 80000;
+               }
+       } else if (adev->asic_type == CHIP_OLAND) {
+               if ((adev->pdev->revision == 0xC7) ||
+                   (adev->pdev->revision == 0x80) ||
+                   (adev->pdev->revision == 0x81) ||
+                   (adev->pdev->revision == 0x83) ||
+                   (adev->pdev->device == 0x6604) ||
+                   (adev->pdev->device == 0x6605)) {
+                       max_sclk = 75000;
+                       max_mclk = 80000;
+               }
+       } else if (adev->asic_type == CHIP_HAINAN) {
+               if ((adev->pdev->revision == 0x81) ||
+                   (adev->pdev->revision == 0x83) ||
+                   (adev->pdev->revision == 0xC3) ||
+                   (adev->pdev->device == 0x6664) ||
+                   (adev->pdev->device == 0x6665) ||
+                   (adev->pdev->device == 0x6667)) {
+                       max_sclk = 75000;
+                       max_mclk = 80000;
+               }
+       }
        /* Apply dpm quirks */
        while (p && p->chip_device != 0) {
                if (adev->pdev->vendor == p->chip_vendor &&
@@ -3489,22 +3532,6 @@ static void si_apply_state_adjust_rules(struct amdgpu_device *adev,
                }
                ++p;
        }
-       /* limit mclk on all R7 370 parts for stability */
-       if (adev->pdev->device == 0x6811 &&
-           adev->pdev->revision == 0x81)
-               max_mclk = 120000;
-       /* limit sclk/mclk on Jet parts for stability */
-       if (adev->pdev->device == 0x6665 &&
-           adev->pdev->revision == 0xc3) {
-               max_sclk = 75000;
-               max_mclk = 80000;
-       }
-       /* Limit clocks for some HD8600 parts */
-       if (adev->pdev->device == 0x6660 &&
-           adev->pdev->revision == 0x83) {
-               max_sclk = 75000;
-               max_mclk = 80000;
-       }
 
        if (rps->vce_active) {
                rps->evclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].evclk;
@@ -7777,6 +7804,8 @@ static int si_dpm_sw_fini(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+       flush_work(&adev->pm.dpm.thermal.work);
+
        mutex_lock(&adev->pm.mutex);
        amdgpu_pm_sysfs_fini(adev);
        si_dpm_fini(adev);
index 8533269..6feed72 100644 (file)
@@ -52,6 +52,8 @@
 #define VCE_V3_0_STACK_SIZE    (64 * 1024)
 #define VCE_V3_0_DATA_SIZE     ((16 * 1024 * AMDGPU_MAX_VCE_HANDLES) + (52 * 1024))
 
+#define FW_52_8_3      ((52 << 24) | (8 << 16) | (3 << 8))
+
 static void vce_v3_0_mc_resume(struct amdgpu_device *adev, int idx);
 static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev);
 static void vce_v3_0_set_irq_funcs(struct amdgpu_device *adev);
@@ -382,6 +384,10 @@ static int vce_v3_0_sw_init(void *handle)
        if (r)
                return r;
 
+       /* 52.8.3 required for 3 ring support */
+       if (adev->vce.fw_version < FW_52_8_3)
+               adev->vce.num_rings = 2;
+
        r = amdgpu_vce_resume(adev);
        if (r)
                return r;
index c0d9aad..7c13090 100644 (file)
@@ -1651,7 +1651,7 @@ static int vi_common_early_init(void *handle)
                        AMD_CG_SUPPORT_SDMA_MGCG |
                        AMD_CG_SUPPORT_SDMA_LS |
                        AMD_CG_SUPPORT_VCE_MGCG;
-               adev->pg_flags |= AMD_PG_SUPPORT_GFX_PG |
+               adev->pg_flags = AMD_PG_SUPPORT_GFX_PG |
                        AMD_PG_SUPPORT_GFX_SMG |
                        AMD_PG_SUPPORT_GFX_PIPELINE |
                        AMD_PG_SUPPORT_UVD |
index 1167205..2ba7937 100644 (file)
@@ -716,7 +716,7 @@ int phm_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type,
                        *voltage = 1150;
        } else {
                ret = atomctrl_get_voltage_evv_on_sclk_ai(hwmgr, voltage_type, sclk, id, &vol);
-               *voltage = (uint16_t)vol/100;
+               *voltage = (uint16_t)(vol/100);
        }
        return ret;
 }
index 1126bd4..0894527 100644 (file)
@@ -1320,7 +1320,8 @@ int atomctrl_get_voltage_evv_on_sclk_ai(struct pp_hwmgr *hwmgr, uint8_t voltage_
        if (0 != result)
                return result;
 
-       *voltage = le32_to_cpu(((GET_EVV_VOLTAGE_INFO_OUTPUT_PARAMETER_V1_3 *)(&get_voltage_info_param_space))->ulVoltageLevel);
+       *voltage = le32_to_cpu(((GET_EVV_VOLTAGE_INFO_OUTPUT_PARAMETER_V1_3 *)
+                               (&get_voltage_info_param_space))->ulVoltageLevel);
 
        return result;
 }
index 7de701d..4477c55 100644 (file)
@@ -1201,12 +1201,15 @@ static uint32_t make_classification_flags(struct pp_hwmgr *hwmgr,
 static int ppt_get_num_of_vce_state_table_entries_v1_0(struct pp_hwmgr *hwmgr)
 {
        const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr);
-       const ATOM_Tonga_VCE_State_Table *vce_state_table =
-                               (ATOM_Tonga_VCE_State_Table *)(((unsigned long)pp_table) + le16_to_cpu(pp_table->usVCEStateTableOffset));
+       const ATOM_Tonga_VCE_State_Table *vce_state_table;
 
-       if (vce_state_table == NULL)
+
+       if (pp_table == NULL)
                return 0;
 
+       vce_state_table = (void *)pp_table +
+                       le16_to_cpu(pp_table->usVCEStateTableOffset);
+
        return vce_state_table->ucNumEntries;
 }
 
index 609996c..7585402 100644 (file)
@@ -1168,8 +1168,8 @@ int smu7_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
 
        tmp_result = (!smum_is_dpm_running(hwmgr)) ? 0 : -1;
        PP_ASSERT_WITH_CODE(tmp_result == 0,
-                       "DPM is already running right now, no need to enable DPM!",
-                       return 0);
+                       "DPM is already running",
+                       );
 
        if (smu7_voltage_control(hwmgr)) {
                tmp_result = smu7_enable_voltage_control(hwmgr);
@@ -2127,15 +2127,18 @@ static int smu7_patch_acp_vddc(struct pp_hwmgr *hwmgr,
 }
 
 static int smu7_patch_limits_vddc(struct pp_hwmgr *hwmgr,
-                                    struct phm_clock_and_voltage_limits *tab)
+                                 struct phm_clock_and_voltage_limits *tab)
 {
+       uint32_t vddc, vddci;
        struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
 
        if (tab) {
-               smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, (uint32_t *)&tab->vddc,
-                                                       &data->vddc_leakage);
-               smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, (uint32_t *)&tab->vddci,
-                                                       &data->vddci_leakage);
+               smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &vddc,
+                                                  &data->vddc_leakage);
+               tab->vddc = vddc;
+               smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &vddci,
+                                                  &data->vddci_leakage);
+               tab->vddci = vddci;
        }
 
        return 0;
index 963a24d..910b8d5 100644 (file)
@@ -645,6 +645,7 @@ void amd_sched_fini(struct amd_gpu_scheduler *sched)
 {
        if (sched->thread)
                kthread_stop(sched->thread);
+       rcu_barrier();
        if (atomic_dec_and_test(&sched_fence_slab_ref))
                kmem_cache_destroy(sched_fence_slab);
 }
index 6b63bea..3653b5a 100644 (file)
@@ -103,7 +103,7 @@ static void amd_sched_fence_free(struct rcu_head *rcu)
 }
 
 /**
- * amd_sched_fence_release - callback that fence can be freed
+ * amd_sched_fence_release_scheduled - callback that fence can be freed
  *
  * @fence: fence
  *
@@ -118,7 +118,7 @@ static void amd_sched_fence_release_scheduled(struct fence *f)
 }
 
 /**
- * amd_sched_fence_release_scheduled - drop extra reference
+ * amd_sched_fence_release_finished - drop extra reference
  *
  * @f: fence
  *
index 2373960..e6862a7 100644 (file)
@@ -420,18 +420,21 @@ drm_atomic_replace_property_blob_from_id(struct drm_crtc *crtc,
                                         ssize_t expected_size,
                                         bool *replaced)
 {
-       struct drm_device *dev = crtc->dev;
        struct drm_property_blob *new_blob = NULL;
 
        if (blob_id != 0) {
-               new_blob = drm_property_lookup_blob(dev, blob_id);
+               new_blob = drm_property_lookup_blob(crtc->dev, blob_id);
                if (new_blob == NULL)
                        return -EINVAL;
-               if (expected_size > 0 && expected_size != new_blob->length)
+
+               if (expected_size > 0 && expected_size != new_blob->length) {
+                       drm_property_unreference_blob(new_blob);
                        return -EINVAL;
+               }
        }
 
        drm_atomic_replace_property_blob(blob, new_blob, replaced);
+       drm_property_unreference_blob(new_blob);
 
        return 0;
 }
index c3f8347..21f9926 100644 (file)
@@ -594,10 +594,6 @@ drm_atomic_helper_check_planes(struct drm_device *dev,
        struct drm_plane_state *plane_state;
        int i, ret = 0;
 
-       ret = drm_atomic_normalize_zpos(dev, state);
-       if (ret)
-               return ret;
-
        for_each_plane_in_state(state, plane, plane_state, i) {
                const struct drm_plane_helper_funcs *funcs;
 
index 04e4571..aa64448 100644 (file)
@@ -914,6 +914,7 @@ static void drm_dp_destroy_port(struct kref *kref)
                /* no need to clean up vcpi
                 * as if we have no connector we never setup a vcpi */
                drm_dp_port_teardown_pdt(port, port->pdt);
+               port->pdt = DP_PEER_DEVICE_NONE;
        }
        kfree(port);
 }
@@ -1159,7 +1160,9 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
                        drm_dp_put_port(port);
                        goto out;
                }
-               if (port->port_num >= DP_MST_LOGICAL_PORT_0) {
+               if ((port->pdt == DP_PEER_DEVICE_DP_LEGACY_CONV ||
+                    port->pdt == DP_PEER_DEVICE_SST_SINK) &&
+                   port->port_num >= DP_MST_LOGICAL_PORT_0) {
                        port->cached_edid = drm_get_edid(port->connector, &port->aux.ddc);
                        drm_mode_connector_set_tile_property(port->connector);
                }
@@ -2919,6 +2922,7 @@ static void drm_dp_destroy_connector_work(struct work_struct *work)
                mgr->cbs->destroy_connector(mgr, port->connector);
 
                drm_dp_port_teardown_pdt(port, port->pdt);
+               port->pdt = DP_PEER_DEVICE_NONE;
 
                if (!port->input && port->vcpi.vcpi > 0) {
                        drm_dp_mst_reset_vcpi_slots(mgr, port);
index 03414bd..6c75e62 100644 (file)
@@ -131,7 +131,12 @@ int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
        return 0;
 fail:
        for (i = 0; i < fb_helper->connector_count; i++) {
-               kfree(fb_helper->connector_info[i]);
+               struct drm_fb_helper_connector *fb_helper_connector =
+                       fb_helper->connector_info[i];
+
+               drm_connector_unreference(fb_helper_connector->connector);
+
+               kfree(fb_helper_connector);
                fb_helper->connector_info[i] = NULL;
        }
        fb_helper->connector_count = 0;
@@ -603,6 +608,24 @@ int drm_fb_helper_blank(int blank, struct fb_info *info)
 }
 EXPORT_SYMBOL(drm_fb_helper_blank);
 
+static void drm_fb_helper_modeset_release(struct drm_fb_helper *helper,
+                                         struct drm_mode_set *modeset)
+{
+       int i;
+
+       for (i = 0; i < modeset->num_connectors; i++) {
+               drm_connector_unreference(modeset->connectors[i]);
+               modeset->connectors[i] = NULL;
+       }
+       modeset->num_connectors = 0;
+
+       drm_mode_destroy(helper->dev, modeset->mode);
+       modeset->mode = NULL;
+
+       /* FIXME should hold a ref? */
+       modeset->fb = NULL;
+}
+
 static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)
 {
        int i;
@@ -612,10 +635,12 @@ static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)
                kfree(helper->connector_info[i]);
        }
        kfree(helper->connector_info);
+
        for (i = 0; i < helper->crtc_count; i++) {
-               kfree(helper->crtc_info[i].mode_set.connectors);
-               if (helper->crtc_info[i].mode_set.mode)
-                       drm_mode_destroy(helper->dev, helper->crtc_info[i].mode_set.mode);
+               struct drm_mode_set *modeset = &helper->crtc_info[i].mode_set;
+
+               drm_fb_helper_modeset_release(helper, modeset);
+               kfree(modeset->connectors);
        }
        kfree(helper->crtc_info);
 }
@@ -644,7 +669,9 @@ static void drm_fb_helper_dirty_work(struct work_struct *work)
        clip->x2 = clip->y2 = 0;
        spin_unlock_irqrestore(&helper->dirty_lock, flags);
 
-       helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, &clip_copy, 1);
+       /* call dirty callback only when it has been really touched */
+       if (clip_copy.x1 < clip_copy.x2 && clip_copy.y1 < clip_copy.y2)
+               helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, &clip_copy, 1);
 }
 
 /**
@@ -2088,7 +2115,6 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
        struct drm_fb_helper_crtc **crtcs;
        struct drm_display_mode **modes;
        struct drm_fb_offset *offsets;
-       struct drm_mode_set *modeset;
        bool *enabled;
        int width, height;
        int i;
@@ -2136,45 +2162,35 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
 
        /* need to set the modesets up here for use later */
        /* fill out the connector<->crtc mappings into the modesets */
-       for (i = 0; i < fb_helper->crtc_count; i++) {
-               modeset = &fb_helper->crtc_info[i].mode_set;
-               modeset->num_connectors = 0;
-               modeset->fb = NULL;
-       }
+       for (i = 0; i < fb_helper->crtc_count; i++)
+               drm_fb_helper_modeset_release(fb_helper,
+                                             &fb_helper->crtc_info[i].mode_set);
 
        for (i = 0; i < fb_helper->connector_count; i++) {
                struct drm_display_mode *mode = modes[i];
                struct drm_fb_helper_crtc *fb_crtc = crtcs[i];
                struct drm_fb_offset *offset = &offsets[i];
-               modeset = &fb_crtc->mode_set;
+               struct drm_mode_set *modeset = &fb_crtc->mode_set;
 
                if (mode && fb_crtc) {
+                       struct drm_connector *connector =
+                               fb_helper->connector_info[i]->connector;
+
                        DRM_DEBUG_KMS("desired mode %s set on crtc %d (%d,%d)\n",
                                      mode->name, fb_crtc->mode_set.crtc->base.id, offset->x, offset->y);
+
                        fb_crtc->desired_mode = mode;
                        fb_crtc->x = offset->x;
                        fb_crtc->y = offset->y;
-                       if (modeset->mode)
-                               drm_mode_destroy(dev, modeset->mode);
                        modeset->mode = drm_mode_duplicate(dev,
                                                           fb_crtc->desired_mode);
-                       modeset->connectors[modeset->num_connectors++] = fb_helper->connector_info[i]->connector;
+                       drm_connector_reference(connector);
+                       modeset->connectors[modeset->num_connectors++] = connector;
                        modeset->fb = fb_helper->fb;
                        modeset->x = offset->x;
                        modeset->y = offset->y;
                }
        }
-
-       /* Clear out any old modes if there are no more connected outputs. */
-       for (i = 0; i < fb_helper->crtc_count; i++) {
-               modeset = &fb_helper->crtc_info[i].mode_set;
-               if (modeset->num_connectors == 0) {
-                       BUG_ON(modeset->fb);
-                       if (modeset->mode)
-                               drm_mode_destroy(dev, modeset->mode);
-                       modeset->mode = NULL;
-               }
-       }
 out:
        kfree(crtcs);
        kfree(modes);
index def78c8..f86e7c8 100644 (file)
@@ -262,6 +262,26 @@ int exynos_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state,
        return 0;
 }
 
+int exynos_atomic_check(struct drm_device *dev,
+                       struct drm_atomic_state *state)
+{
+       int ret;
+
+       ret = drm_atomic_helper_check_modeset(dev, state);
+       if (ret)
+               return ret;
+
+       ret = drm_atomic_normalize_zpos(dev, state);
+       if (ret)
+               return ret;
+
+       ret = drm_atomic_helper_check_planes(dev, state);
+       if (ret)
+               return ret;
+
+       return ret;
+}
+
 static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
 {
        struct drm_exynos_file_private *file_priv;
index d215149..80c4d5b 100644 (file)
@@ -301,6 +301,7 @@ static inline int exynos_dpi_bind(struct drm_device *dev,
 
 int exynos_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state,
                         bool nonblock);
+int exynos_atomic_check(struct drm_device *dev, struct drm_atomic_state *state);
 
 
 extern struct platform_driver fimd_driver;
index 40ce841..23cce0a 100644 (file)
@@ -190,7 +190,7 @@ dma_addr_t exynos_drm_fb_dma_addr(struct drm_framebuffer *fb, int index)
 static const struct drm_mode_config_funcs exynos_drm_mode_config_funcs = {
        .fb_create = exynos_user_fb_create,
        .output_poll_changed = exynos_drm_output_poll_changed,
-       .atomic_check = drm_atomic_helper_check,
+       .atomic_check = exynos_atomic_check,
        .atomic_commit = exynos_atomic_commit,
 };
 
index bfb2efd..18dfdd5 100644 (file)
@@ -1447,8 +1447,6 @@ static int i915_drm_suspend(struct drm_device *dev)
 
        dev_priv->suspend_count++;
 
-       intel_display_set_init_power(dev_priv, false);
-
        intel_csr_ucode_suspend(dev_priv);
 
 out:
@@ -1466,6 +1464,8 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
 
        disable_rpm_wakeref_asserts(dev_priv);
 
+       intel_display_set_init_power(dev_priv, false);
+
        fw_csr = !IS_BROXTON(dev_priv) &&
                suspend_to_idle(dev_priv) && dev_priv->csr.dmc_payload;
        /*
index 8b9ee4e..685e9e0 100644 (file)
@@ -2883,6 +2883,11 @@ __i915_printk(struct drm_i915_private *dev_priv, const char *level,
 extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
                              unsigned long arg);
 #endif
+extern const struct dev_pm_ops i915_pm_ops;
+
+extern int i915_driver_load(struct pci_dev *pdev,
+                           const struct pci_device_id *ent);
+extern void i915_driver_unload(struct drm_device *dev);
 extern int intel_gpu_reset(struct drm_i915_private *dev_priv, u32 engine_mask);
 extern bool intel_has_gpu_reset(struct drm_i915_private *dev_priv);
 extern void i915_reset(struct drm_i915_private *dev_priv);
index 947e82c..23960de 100644 (file)
@@ -3550,8 +3550,6 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
 
        vma->display_alignment = max_t(u64, vma->display_alignment, alignment);
 
-       WARN_ON(obj->pin_display > i915_vma_pin_count(vma));
-
        i915_gem_object_flush_cpu_write_domain(obj);
 
        old_write_domain = obj->base.write_domain;
@@ -3588,7 +3586,6 @@ i915_gem_object_unpin_from_display_plane(struct i915_vma *vma)
                list_move_tail(&vma->vm_link, &vma->vm->inactive_list);
 
        i915_vma_unpin(vma);
-       WARN_ON(vma->obj->pin_display > i915_vma_pin_count(vma));
 }
 
 /**
@@ -3745,7 +3742,12 @@ void __i915_vma_set_map_and_fenceable(struct i915_vma *vma)
        mappable = (vma->node.start + fence_size <=
                    dev_priv->ggtt.mappable_end);
 
-       if (mappable && fenceable)
+       /*
+        * Explicitly disable for rotated VMA since the display does not
+        * need the fence and the VMA is not accessible to other users.
+        */
+       if (mappable && fenceable &&
+           vma->ggtt_view.type != I915_GGTT_VIEW_ROTATED)
                vma->flags |= I915_VMA_CAN_FENCE;
        else
                vma->flags &= ~I915_VMA_CAN_FENCE;
index 8df1fa7..2c7ba0e 100644 (file)
@@ -290,6 +290,8 @@ i915_vma_put_fence(struct i915_vma *vma)
 {
        struct drm_i915_fence_reg *fence = vma->fence;
 
+       assert_rpm_wakelock_held(to_i915(vma->vm->dev));
+
        if (!fence)
                return 0;
 
@@ -341,6 +343,8 @@ i915_vma_get_fence(struct i915_vma *vma)
        struct drm_i915_fence_reg *fence;
        struct i915_vma *set = i915_gem_object_is_tiled(vma->obj) ? vma : NULL;
 
+       assert_rpm_wakelock_held(to_i915(vma->vm->dev));
+
        /* Just update our place in the LRU if our fence is getting reused. */
        if (vma->fence) {
                fence = vma->fence;
@@ -371,6 +375,12 @@ void i915_gem_restore_fences(struct drm_device *dev)
        struct drm_i915_private *dev_priv = to_i915(dev);
        int i;
 
+       /* Note that this may be called outside of struct_mutex, by
+        * runtime suspend/resume. The barrier we require is enforced by
+        * rpm itself - all access to fences/GTT are only within an rpm
+        * wakeref, and to acquire that wakeref you must pass through here.
+        */
+
        for (i = 0; i < dev_priv->num_fence_regs; i++) {
                struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i];
                struct i915_vma *vma = reg->vma;
@@ -379,10 +389,17 @@ void i915_gem_restore_fences(struct drm_device *dev)
                 * Commit delayed tiling changes if we have an object still
                 * attached to the fence, otherwise just clear the fence.
                 */
-               if (vma && !i915_gem_object_is_tiled(vma->obj))
+               if (vma && !i915_gem_object_is_tiled(vma->obj)) {
+                       GEM_BUG_ON(!reg->dirty);
+                       GEM_BUG_ON(vma->obj->fault_mappable);
+
+                       list_move(&reg->link, &dev_priv->mm.fence_list);
+                       vma->fence = NULL;
                        vma = NULL;
+               }
 
-               fence_update(reg, vma);
+               fence_write(reg, vma);
+               reg->vma = vma;
        }
 }
 
index 687c768..31e6edd 100644 (file)
@@ -431,9 +431,6 @@ static const struct pci_device_id pciidlist[] = {
 };
 MODULE_DEVICE_TABLE(pci, pciidlist);
 
-extern int i915_driver_load(struct pci_dev *pdev,
-                           const struct pci_device_id *ent);
-
 static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct intel_device_info *intel_info =
@@ -463,8 +460,6 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        return i915_driver_load(pdev, ent);
 }
 
-extern void i915_driver_unload(struct drm_device *dev);
-
 static void i915_pci_remove(struct pci_dev *pdev)
 {
        struct drm_device *dev = pci_get_drvdata(pdev);
@@ -473,8 +468,6 @@ static void i915_pci_remove(struct pci_dev *pdev)
        drm_dev_unref(dev);
 }
 
-extern const struct dev_pm_ops i915_pm_ops;
-
 static struct pci_driver i915_pci_driver = {
        .name = DRIVER_NAME,
        .id_table = pciidlist,
index c6e69e4..1f8af87 100644 (file)
@@ -1031,6 +1031,77 @@ static u8 translate_iboost(u8 val)
        return mapping[val];
 }
 
+static void sanitize_ddc_pin(struct drm_i915_private *dev_priv,
+                            enum port port)
+{
+       const struct ddi_vbt_port_info *info =
+               &dev_priv->vbt.ddi_port_info[port];
+       enum port p;
+
+       if (!info->alternate_ddc_pin)
+               return;
+
+       for_each_port_masked(p, (1 << port) - 1) {
+               struct ddi_vbt_port_info *i = &dev_priv->vbt.ddi_port_info[p];
+
+               if (info->alternate_ddc_pin != i->alternate_ddc_pin)
+                       continue;
+
+               DRM_DEBUG_KMS("port %c trying to use the same DDC pin (0x%x) as port %c, "
+                             "disabling port %c DVI/HDMI support\n",
+                             port_name(p), i->alternate_ddc_pin,
+                             port_name(port), port_name(p));
+
+               /*
+                * If we have multiple ports supposedly sharing the
+                * pin, then dvi/hdmi couldn't exist on the shared
+                * port. Otherwise they share the same ddc bin and
+                * system couldn't communicate with them separately.
+                *
+                * Due to parsing the ports in alphabetical order,
+                * a higher port will always clobber a lower one.
+                */
+               i->supports_dvi = false;
+               i->supports_hdmi = false;
+               i->alternate_ddc_pin = 0;
+       }
+}
+
+static void sanitize_aux_ch(struct drm_i915_private *dev_priv,
+                           enum port port)
+{
+       const struct ddi_vbt_port_info *info =
+               &dev_priv->vbt.ddi_port_info[port];
+       enum port p;
+
+       if (!info->alternate_aux_channel)
+               return;
+
+       for_each_port_masked(p, (1 << port) - 1) {
+               struct ddi_vbt_port_info *i = &dev_priv->vbt.ddi_port_info[p];
+
+               if (info->alternate_aux_channel != i->alternate_aux_channel)
+                       continue;
+
+               DRM_DEBUG_KMS("port %c trying to use the same AUX CH (0x%x) as port %c, "
+                             "disabling port %c DP support\n",
+                             port_name(p), i->alternate_aux_channel,
+                             port_name(port), port_name(p));
+
+               /*
+                * If we have multiple ports supposedlt sharing the
+                * aux channel, then DP couldn't exist on the shared
+                * port. Otherwise they share the same aux channel
+                * and system couldn't communicate with them separately.
+                *
+                * Due to parsing the ports in alphabetical order,
+                * a higher port will always clobber a lower one.
+                */
+               i->supports_dp = false;
+               i->alternate_aux_channel = 0;
+       }
+}
+
 static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
                           const struct bdb_header *bdb)
 {
@@ -1105,54 +1176,15 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
                DRM_DEBUG_KMS("Port %c is internal DP\n", port_name(port));
 
        if (is_dvi) {
-               if (port == PORT_E) {
-                       info->alternate_ddc_pin = ddc_pin;
-                       /* if DDIE share ddc pin with other port, then
-                        * dvi/hdmi couldn't exist on the shared port.
-                        * Otherwise they share the same ddc bin and system
-                        * couldn't communicate with them seperately. */
-                       if (ddc_pin == DDC_PIN_B) {
-                               dev_priv->vbt.ddi_port_info[PORT_B].supports_dvi = 0;
-                               dev_priv->vbt.ddi_port_info[PORT_B].supports_hdmi = 0;
-                       } else if (ddc_pin == DDC_PIN_C) {
-                               dev_priv->vbt.ddi_port_info[PORT_C].supports_dvi = 0;
-                               dev_priv->vbt.ddi_port_info[PORT_C].supports_hdmi = 0;
-                       } else if (ddc_pin == DDC_PIN_D) {
-                               dev_priv->vbt.ddi_port_info[PORT_D].supports_dvi = 0;
-                               dev_priv->vbt.ddi_port_info[PORT_D].supports_hdmi = 0;
-                       }
-               } else if (ddc_pin == DDC_PIN_B && port != PORT_B)
-                       DRM_DEBUG_KMS("Unexpected DDC pin for port B\n");
-               else if (ddc_pin == DDC_PIN_C && port != PORT_C)
-                       DRM_DEBUG_KMS("Unexpected DDC pin for port C\n");
-               else if (ddc_pin == DDC_PIN_D && port != PORT_D)
-                       DRM_DEBUG_KMS("Unexpected DDC pin for port D\n");
+               info->alternate_ddc_pin = ddc_pin;
+
+               sanitize_ddc_pin(dev_priv, port);
        }
 
        if (is_dp) {
-               if (port == PORT_E) {
-                       info->alternate_aux_channel = aux_channel;
-                       /* if DDIE share aux channel with other port, then
-                        * DP couldn't exist on the shared port. Otherwise
-                        * they share the same aux channel and system
-                        * couldn't communicate with them seperately. */
-                       if (aux_channel == DP_AUX_A)
-                               dev_priv->vbt.ddi_port_info[PORT_A].supports_dp = 0;
-                       else if (aux_channel == DP_AUX_B)
-                               dev_priv->vbt.ddi_port_info[PORT_B].supports_dp = 0;
-                       else if (aux_channel == DP_AUX_C)
-                               dev_priv->vbt.ddi_port_info[PORT_C].supports_dp = 0;
-                       else if (aux_channel == DP_AUX_D)
-                               dev_priv->vbt.ddi_port_info[PORT_D].supports_dp = 0;
-               }
-               else if (aux_channel == DP_AUX_A && port != PORT_A)
-                       DRM_DEBUG_KMS("Unexpected AUX channel for port A\n");
-               else if (aux_channel == DP_AUX_B && port != PORT_B)
-                       DRM_DEBUG_KMS("Unexpected AUX channel for port B\n");
-               else if (aux_channel == DP_AUX_C && port != PORT_C)
-                       DRM_DEBUG_KMS("Unexpected AUX channel for port C\n");
-               else if (aux_channel == DP_AUX_D && port != PORT_D)
-                       DRM_DEBUG_KMS("Unexpected AUX channel for port D\n");
+               info->alternate_aux_channel = aux_channel;
+
+               sanitize_aux_ch(dev_priv, port);
        }
 
        if (bdb->version >= 158) {
index 73b6858..1b20e16 100644 (file)
@@ -192,7 +192,7 @@ static void broadwell_sseu_info_init(struct drm_i915_private *dev_priv)
        struct sseu_dev_info *sseu = &mkwrite_device_info(dev_priv)->sseu;
        const int s_max = 3, ss_max = 3, eu_max = 8;
        int s, ss;
-       u32 fuse2, eu_disable[s_max];
+       u32 fuse2, eu_disable[3]; /* s_max */
 
        fuse2 = I915_READ(GEN8_FUSE2);
        sseu->slice_mask = (fuse2 & GEN8_F2_S_ENA_MASK) >> GEN8_F2_S_ENA_SHIFT;
index fbcfed6..0ad1879 100644 (file)
@@ -2978,7 +2978,8 @@ int skl_check_plane_surface(struct intel_plane_state *plane_state)
        /* Rotate src coordinates to match rotated GTT view */
        if (intel_rotation_90_or_270(rotation))
                drm_rect_rotate(&plane_state->base.src,
-                               fb->width, fb->height, DRM_ROTATE_270);
+                               fb->width << 16, fb->height << 16,
+                               DRM_ROTATE_270);
 
        /*
         * Handle the AUX surface first since
@@ -14310,7 +14311,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
 
        for_each_plane_in_state(state, plane, plane_state, i) {
                struct intel_plane_state *intel_plane_state =
-                       to_intel_plane_state(plane_state);
+                       to_intel_plane_state(plane->state);
 
                if (!intel_plane_state->wait_req)
                        continue;
index 14a3cf0..3581b5a 100644 (file)
@@ -1108,6 +1108,44 @@ intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
        return ret;
 }
 
+static enum port intel_aux_port(struct drm_i915_private *dev_priv,
+                               enum port port)
+{
+       const struct ddi_vbt_port_info *info =
+               &dev_priv->vbt.ddi_port_info[port];
+       enum port aux_port;
+
+       if (!info->alternate_aux_channel) {
+               DRM_DEBUG_KMS("using AUX %c for port %c (platform default)\n",
+                             port_name(port), port_name(port));
+               return port;
+       }
+
+       switch (info->alternate_aux_channel) {
+       case DP_AUX_A:
+               aux_port = PORT_A;
+               break;
+       case DP_AUX_B:
+               aux_port = PORT_B;
+               break;
+       case DP_AUX_C:
+               aux_port = PORT_C;
+               break;
+       case DP_AUX_D:
+               aux_port = PORT_D;
+               break;
+       default:
+               MISSING_CASE(info->alternate_aux_channel);
+               aux_port = PORT_A;
+               break;
+       }
+
+       DRM_DEBUG_KMS("using AUX %c for port %c (VBT)\n",
+                     port_name(aux_port), port_name(port));
+
+       return aux_port;
+}
+
 static i915_reg_t g4x_aux_ctl_reg(struct drm_i915_private *dev_priv,
                                       enum port port)
 {
@@ -1168,36 +1206,9 @@ static i915_reg_t ilk_aux_data_reg(struct drm_i915_private *dev_priv,
        }
 }
 
-/*
- * On SKL we don't have Aux for port E so we rely
- * on VBT to set a proper alternate aux channel.
- */
-static enum port skl_porte_aux_port(struct drm_i915_private *dev_priv)
-{
-       const struct ddi_vbt_port_info *info =
-               &dev_priv->vbt.ddi_port_info[PORT_E];
-
-       switch (info->alternate_aux_channel) {
-       case DP_AUX_A:
-               return PORT_A;
-       case DP_AUX_B:
-               return PORT_B;
-       case DP_AUX_C:
-               return PORT_C;
-       case DP_AUX_D:
-               return PORT_D;
-       default:
-               MISSING_CASE(info->alternate_aux_channel);
-               return PORT_A;
-       }
-}
-
 static i915_reg_t skl_aux_ctl_reg(struct drm_i915_private *dev_priv,
                                       enum port port)
 {
-       if (port == PORT_E)
-               port = skl_porte_aux_port(dev_priv);
-
        switch (port) {
        case PORT_A:
        case PORT_B:
@@ -1213,9 +1224,6 @@ static i915_reg_t skl_aux_ctl_reg(struct drm_i915_private *dev_priv,
 static i915_reg_t skl_aux_data_reg(struct drm_i915_private *dev_priv,
                                        enum port port, int index)
 {
-       if (port == PORT_E)
-               port = skl_porte_aux_port(dev_priv);
-
        switch (port) {
        case PORT_A:
        case PORT_B:
@@ -1253,7 +1261,8 @@ static i915_reg_t intel_aux_data_reg(struct drm_i915_private *dev_priv,
 static void intel_aux_reg_init(struct intel_dp *intel_dp)
 {
        struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp));
-       enum port port = dp_to_dig_port(intel_dp)->port;
+       enum port port = intel_aux_port(dev_priv,
+                                       dp_to_dig_port(intel_dp)->port);
        int i;
 
        intel_dp->aux_ch_ctl_reg = intel_aux_ctl_reg(dev_priv, port);
@@ -3551,8 +3560,8 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp)
        /* Read the eDP Display control capabilities registers */
        if ((intel_dp->dpcd[DP_EDP_CONFIGURATION_CAP] & DP_DPCD_DISPLAY_CONTROL_CAPABLE) &&
            drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_DPCD_REV,
-                            intel_dp->edp_dpcd, sizeof(intel_dp->edp_dpcd) ==
-                            sizeof(intel_dp->edp_dpcd)))
+                            intel_dp->edp_dpcd, sizeof(intel_dp->edp_dpcd)) ==
+                            sizeof(intel_dp->edp_dpcd))
                DRM_DEBUG_KMS("EDP DPCD : %*ph\n", (int) sizeof(intel_dp->edp_dpcd),
                              intel_dp->edp_dpcd);
 
index faa6762..c43dd9a 100644 (file)
@@ -104,8 +104,10 @@ static int intel_fbc_calculate_cfb_size(struct drm_i915_private *dev_priv,
        int lines;
 
        intel_fbc_get_plane_source_size(cache, NULL, &lines);
-       if (INTEL_INFO(dev_priv)->gen >= 7)
+       if (INTEL_GEN(dev_priv) == 7)
                lines = min(lines, 2048);
+       else if (INTEL_GEN(dev_priv) >= 8)
+               lines = min(lines, 2560);
 
        /* Hardware needs the full buffer stride, not just the active area. */
        return lines * cache->fb.stride;
index a2f751c..db24f89 100644 (file)
@@ -3362,13 +3362,15 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
        int num_active;
        int id, i;
 
+       /* Clear the partitioning for disabled planes. */
+       memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe]));
+       memset(ddb->y_plane[pipe], 0, sizeof(ddb->y_plane[pipe]));
+
        if (WARN_ON(!state))
                return 0;
 
        if (!cstate->base.active) {
                ddb->pipe[pipe].start = ddb->pipe[pipe].end = 0;
-               memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe]));
-               memset(ddb->y_plane[pipe], 0, sizeof(ddb->y_plane[pipe]));
                return 0;
        }
 
@@ -3468,12 +3470,6 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
        return 0;
 }
 
-static uint32_t skl_pipe_pixel_rate(const struct intel_crtc_state *config)
-{
-       /* TODO: Take into account the scalers once we support them */
-       return config->base.adjusted_mode.crtc_clock;
-}
-
 /*
  * The max latency should be 257 (max the punit can code is 255 and we add 2us
  * for the read latency) and cpp should always be <= 8, so that
@@ -3524,7 +3520,7 @@ static uint32_t skl_adjusted_plane_pixel_rate(const struct intel_crtc_state *cst
         * Adjusted plane pixel rate is just the pipe's adjusted pixel rate
         * with additional adjustments for plane-specific scaling.
         */
-       adjusted_pixel_rate = skl_pipe_pixel_rate(cstate);
+       adjusted_pixel_rate = ilk_pipe_pixel_rate(cstate);
        downscale_amount = skl_plane_downscale_amount(pstate);
 
        pixel_rate = adjusted_pixel_rate * downscale_amount >> 16;
@@ -3736,11 +3732,11 @@ skl_compute_linetime_wm(struct intel_crtc_state *cstate)
        if (!cstate->base.active)
                return 0;
 
-       if (WARN_ON(skl_pipe_pixel_rate(cstate) == 0))
+       if (WARN_ON(ilk_pipe_pixel_rate(cstate) == 0))
                return 0;
 
        return DIV_ROUND_UP(8 * cstate->base.adjusted_mode.crtc_htotal * 1000,
-                           skl_pipe_pixel_rate(cstate));
+                           ilk_pipe_pixel_rate(cstate));
 }
 
 static void skl_compute_transition_wm(struct intel_crtc_state *cstate,
@@ -4050,6 +4046,12 @@ skl_compute_ddb(struct drm_atomic_state *state)
                intel_state->wm_results.dirty_pipes = ~0;
        }
 
+       /*
+        * We're not recomputing for the pipes not included in the commit, so
+        * make sure we start with the current state.
+        */
+       memcpy(ddb, &dev_priv->wm.skl_hw.ddb, sizeof(*ddb));
+
        for_each_intel_crtc_mask(dev, intel_crtc, realloc_pipes) {
                struct intel_crtc_state *cstate;
 
index 98df09c..9672b57 100644 (file)
@@ -357,8 +357,8 @@ static int imx_drm_bind(struct device *dev)
        int ret;
 
        drm = drm_dev_alloc(&imx_drm_driver, dev);
-       if (!drm)
-               return -ENOMEM;
+       if (IS_ERR(drm))
+               return PTR_ERR(drm);
 
        imxdrm = devm_kzalloc(dev, sizeof(*imxdrm), GFP_KERNEL);
        if (!imxdrm) {
@@ -436,9 +436,11 @@ static int imx_drm_bind(struct device *dev)
 
 err_fbhelper:
        drm_kms_helper_poll_fini(drm);
+#if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION)
        if (imxdrm->fbhelper)
                drm_fbdev_cma_fini(imxdrm->fbhelper);
 err_unbind:
+#endif
        component_unbind_all(drm->dev, drm);
 err_vblank:
        drm_vblank_cleanup(drm);
index ce22d0a..d5864ed 100644 (file)
@@ -103,11 +103,11 @@ drm_plane_state_to_vbo(struct drm_plane_state *state)
               (state->src_x >> 16) / 2 - eba;
 }
 
-static void ipu_plane_atomic_set_base(struct ipu_plane *ipu_plane,
-                                     struct drm_plane_state *old_state)
+static void ipu_plane_atomic_set_base(struct ipu_plane *ipu_plane)
 {
        struct drm_plane *plane = &ipu_plane->base;
        struct drm_plane_state *state = plane->state;
+       struct drm_crtc_state *crtc_state = state->crtc->state;
        struct drm_framebuffer *fb = state->fb;
        unsigned long eba, ubo, vbo;
        int active;
@@ -117,7 +117,7 @@ static void ipu_plane_atomic_set_base(struct ipu_plane *ipu_plane,
        switch (fb->pixel_format) {
        case DRM_FORMAT_YUV420:
        case DRM_FORMAT_YVU420:
-               if (old_state->fb)
+               if (!drm_atomic_crtc_needs_modeset(crtc_state))
                        break;
 
                /*
@@ -149,7 +149,7 @@ static void ipu_plane_atomic_set_base(struct ipu_plane *ipu_plane,
                break;
        }
 
-       if (old_state->fb) {
+       if (!drm_atomic_crtc_needs_modeset(crtc_state)) {
                active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch);
                ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba);
                ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active);
@@ -259,6 +259,7 @@ static int ipu_plane_atomic_check(struct drm_plane *plane,
        struct drm_framebuffer *fb = state->fb;
        struct drm_framebuffer *old_fb = old_state->fb;
        unsigned long eba, ubo, vbo, old_ubo, old_vbo;
+       int hsub, vsub;
 
        /* Ok to disable */
        if (!fb)
@@ -355,7 +356,9 @@ static int ipu_plane_atomic_check(struct drm_plane *plane,
                if ((ubo > 0xfffff8) || (vbo > 0xfffff8))
                        return -EINVAL;
 
-               if (old_fb) {
+               if (old_fb &&
+                   (old_fb->pixel_format == DRM_FORMAT_YUV420 ||
+                    old_fb->pixel_format == DRM_FORMAT_YVU420)) {
                        old_ubo = drm_plane_state_to_ubo(old_state);
                        old_vbo = drm_plane_state_to_vbo(old_state);
                        if (ubo != old_ubo || vbo != old_vbo)
@@ -370,6 +373,16 @@ static int ipu_plane_atomic_check(struct drm_plane *plane,
 
                if (old_fb && old_fb->pitches[1] != fb->pitches[1])
                        crtc_state->mode_changed = true;
+
+               /*
+                * The x/y offsets must be even in case of horizontal/vertical
+                * chroma subsampling.
+                */
+               hsub = drm_format_horz_chroma_subsampling(fb->pixel_format);
+               vsub = drm_format_vert_chroma_subsampling(fb->pixel_format);
+               if (((state->src_x >> 16) & (hsub - 1)) ||
+                   ((state->src_y >> 16) & (vsub - 1)))
+                       return -EINVAL;
        }
 
        return 0;
@@ -392,7 +405,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,
                struct drm_crtc_state *crtc_state = state->crtc->state;
 
                if (!drm_atomic_crtc_needs_modeset(crtc_state)) {
-                       ipu_plane_atomic_set_base(ipu_plane, old_state);
+                       ipu_plane_atomic_set_base(ipu_plane);
                        return;
                }
        }
@@ -424,6 +437,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,
                        ipu_dp_set_global_alpha(ipu_plane->dp, false, 0, false);
                        break;
                default:
+                       ipu_dp_set_global_alpha(ipu_plane->dp, true, 0, true);
                        break;
                }
        }
@@ -437,7 +451,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,
        ipu_cpmem_set_high_priority(ipu_plane->ipu_ch);
        ipu_idmac_set_double_buffer(ipu_plane->ipu_ch, 1);
        ipu_cpmem_set_stride(ipu_plane->ipu_ch, state->fb->pitches[0]);
-       ipu_plane_atomic_set_base(ipu_plane, old_state);
+       ipu_plane_atomic_set_base(ipu_plane);
        ipu_plane_enable(ipu_plane);
 }
 
index dc57b62..193573d 100644 (file)
@@ -240,7 +240,8 @@ static bool nouveau_pr3_present(struct pci_dev *pdev)
        if (!parent_adev)
                return false;
 
-       return acpi_has_method(parent_adev->handle, "_PR3");
+       return parent_adev->power.flags.power_resources &&
+               acpi_has_method(parent_adev->handle, "_PR3");
 }
 
 static void nouveau_dsm_pci_probe(struct pci_dev *pdev, acpi_handle *dhandle_out,
index 103fc86..a0d4a05 100644 (file)
@@ -1396,9 +1396,7 @@ static void cayman_pcie_gart_fini(struct radeon_device *rdev)
 void cayman_cp_int_cntl_setup(struct radeon_device *rdev,
                              int ring, u32 cp_int_cntl)
 {
-       u32 srbm_gfx_cntl = RREG32(SRBM_GFX_CNTL) & ~3;
-
-       WREG32(SRBM_GFX_CNTL, srbm_gfx_cntl | (ring & 3));
+       WREG32(SRBM_GFX_CNTL, RINGID(ring));
        WREG32(CP_INT_CNTL, cp_int_cntl);
 }
 
index 2d46564..474a8a1 100644 (file)
@@ -105,7 +105,7 @@ radeon_dp_aux_transfer_native(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg
 
        tmp &= AUX_HPD_SEL(0x7);
        tmp |= AUX_HPD_SEL(chan->rec.hpd);
-       tmp |= AUX_EN | AUX_LS_READ_EN | AUX_HPD_DISCON(0x1);
+       tmp |= AUX_EN | AUX_LS_READ_EN;
 
        WREG32(AUX_CONTROL + aux_offset[instance], tmp);
 
index 89bdf20..c499345 100644 (file)
@@ -2999,6 +2999,49 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
        int i;
        struct si_dpm_quirk *p = si_dpm_quirk_list;
 
+       /* limit all SI kickers */
+       if (rdev->family == CHIP_PITCAIRN) {
+               if ((rdev->pdev->revision == 0x81) ||
+                   (rdev->pdev->device == 0x6810) ||
+                   (rdev->pdev->device == 0x6811) ||
+                   (rdev->pdev->device == 0x6816) ||
+                   (rdev->pdev->device == 0x6817) ||
+                   (rdev->pdev->device == 0x6806))
+                       max_mclk = 120000;
+       } else if (rdev->family == CHIP_VERDE) {
+               if ((rdev->pdev->revision == 0x81) ||
+                   (rdev->pdev->revision == 0x83) ||
+                   (rdev->pdev->revision == 0x87) ||
+                   (rdev->pdev->device == 0x6820) ||
+                   (rdev->pdev->device == 0x6821) ||
+                   (rdev->pdev->device == 0x6822) ||
+                   (rdev->pdev->device == 0x6823) ||
+                   (rdev->pdev->device == 0x682A) ||
+                   (rdev->pdev->device == 0x682B)) {
+                       max_sclk = 75000;
+                       max_mclk = 80000;
+               }
+       } else if (rdev->family == CHIP_OLAND) {
+               if ((rdev->pdev->revision == 0xC7) ||
+                   (rdev->pdev->revision == 0x80) ||
+                   (rdev->pdev->revision == 0x81) ||
+                   (rdev->pdev->revision == 0x83) ||
+                   (rdev->pdev->device == 0x6604) ||
+                   (rdev->pdev->device == 0x6605)) {
+                       max_sclk = 75000;
+                       max_mclk = 80000;
+               }
+       } else if (rdev->family == CHIP_HAINAN) {
+               if ((rdev->pdev->revision == 0x81) ||
+                   (rdev->pdev->revision == 0x83) ||
+                   (rdev->pdev->revision == 0xC3) ||
+                   (rdev->pdev->device == 0x6664) ||
+                   (rdev->pdev->device == 0x6665) ||
+                   (rdev->pdev->device == 0x6667)) {
+                       max_sclk = 75000;
+                       max_mclk = 80000;
+               }
+       }
        /* Apply dpm quirks */
        while (p && p->chip_device != 0) {
                if (rdev->pdev->vendor == p->chip_vendor &&
@@ -3011,16 +3054,6 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
                }
                ++p;
        }
-       /* limit mclk on all R7 370 parts for stability */
-       if (rdev->pdev->device == 0x6811 &&
-           rdev->pdev->revision == 0x81)
-               max_mclk = 120000;
-       /* limit sclk/mclk on Jet parts for stability */
-       if (rdev->pdev->device == 0x6665 &&
-           rdev->pdev->revision == 0xc3) {
-               max_sclk = 75000;
-               max_mclk = 80000;
-       }
 
        if (rps->vce_active) {
                rps->evclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].evclk;
index bd9c3bb..392c7e6 100644 (file)
@@ -231,8 +231,16 @@ static int rcar_du_atomic_check(struct drm_device *dev,
        struct rcar_du_device *rcdu = dev->dev_private;
        int ret;
 
-       ret = drm_atomic_helper_check(dev, state);
-       if (ret < 0)
+       ret = drm_atomic_helper_check_modeset(dev, state);
+       if (ret)
+               return ret;
+
+       ret = drm_atomic_normalize_zpos(dev, state);
+       if (ret)
+               return ret;
+
+       ret = drm_atomic_helper_check_planes(dev, state);
+       if (ret)
                return ret;
 
        if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE))
index 2784919..9df3085 100644 (file)
@@ -195,6 +195,26 @@ static void sti_atomic_work(struct work_struct *work)
        sti_atomic_complete(private, private->commit.state);
 }
 
+static int sti_atomic_check(struct drm_device *dev,
+                           struct drm_atomic_state *state)
+{
+       int ret;
+
+       ret = drm_atomic_helper_check_modeset(dev, state);
+       if (ret)
+               return ret;
+
+       ret = drm_atomic_normalize_zpos(dev, state);
+       if (ret)
+               return ret;
+
+       ret = drm_atomic_helper_check_planes(dev, state);
+       if (ret)
+               return ret;
+
+       return ret;
+}
+
 static int sti_atomic_commit(struct drm_device *drm,
                             struct drm_atomic_state *state, bool nonblock)
 {
@@ -248,7 +268,7 @@ static void sti_output_poll_changed(struct drm_device *ddev)
 static const struct drm_mode_config_funcs sti_mode_config_funcs = {
        .fb_create = drm_fb_cma_create,
        .output_poll_changed = sti_output_poll_changed,
-       .atomic_check = drm_atomic_helper_check,
+       .atomic_check = sti_atomic_check,
        .atomic_commit = sti_atomic_commit,
 };
 
index 7cf3678..5804870 100644 (file)
@@ -338,8 +338,7 @@ static void vgdev_atomic_commit_tail(struct drm_atomic_state *state)
 
        drm_atomic_helper_commit_modeset_disables(dev, state);
        drm_atomic_helper_commit_modeset_enables(dev, state);
-       drm_atomic_helper_commit_planes(dev, state,
-                                       DRM_PLANE_COMMIT_ACTIVE_ONLY);
+       drm_atomic_helper_commit_planes(dev, state, 0);
 
        drm_atomic_helper_commit_hw_done(state);
 
index 2ba7d43..805b6fa 100644 (file)
@@ -1617,7 +1617,7 @@ ipu_image_convert(struct ipu_soc *ipu, enum ipu_ic_task ic_task,
        ctx = ipu_image_convert_prepare(ipu, ic_task, in, out, rot_mode,
                                        complete, complete_context);
        if (IS_ERR(ctx))
-               return ERR_PTR(PTR_ERR(ctx));
+               return ERR_CAST(ctx);
 
        run = kzalloc(sizeof(*run), GFP_KERNEL);
        if (!run) {
index 43cf193..8b4dc62 100644 (file)
@@ -47,8 +47,14 @@ struct drm_crtc;
  * @src_h: height of visible portion of plane (in 16.16)
  * @rotation: rotation of the plane
  * @zpos: priority of the given plane on crtc (optional)
+ *     Note that multiple active planes on the same crtc can have an identical
+ *     zpos value. The rule to solving the conflict is to compare the plane
+ *     object IDs; the plane with a higher ID must be stacked on top of a
+ *     plane with a lower ID.
  * @normalized_zpos: normalized value of zpos: unique, range from 0 to N-1
- *     where N is the number of active planes for given crtc
+ *     where N is the number of active planes for given crtc. Note that
+ *     the driver must call drm_atomic_normalize_zpos() to update this before
+ *     it can be trusted.
  * @src: clipped source coordinates of the plane (in 16.16)
  * @dst: clipped destination coordinates of the plane
  * @visible: visibility of the plane