Merge tag 'topic/drm-fixes-2015-09-09' of git://anongit.freedesktop.org/drm-intel...
authorDave Airlie <airlied@redhat.com>
Fri, 11 Sep 2015 00:52:37 +0000 (10:52 +1000)
committerDave Airlie <airlied@redhat.com>
Fri, 11 Sep 2015 00:52:37 +0000 (10:52 +1000)
bunch of drm fixes.

* tag 'topic/drm-fixes-2015-09-09' of git://anongit.freedesktop.org/drm-intel:
  drm/dp: Add dp_aux_i2c_speed_khz module param to set the assume i2c bus speed
  drm/dp: Adjust i2c-over-aux retry count based on message size and i2c bus speed
  drm/dp: Define AUX_RETRY_INTERVAL as 500 us
  drm/atomic: Fix bookkeeping with TEST_ONLY, v3.

73 files changed:
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c
drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
drivers/gpu/drm/amd/amdgpu/atombios_dp.c
drivers/gpu/drm/amd/amdgpu/cik_sdma.c
drivers/gpu/drm/amd/amdgpu/cikd.h
drivers/gpu/drm/amd/amdgpu/cz_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/fiji_smc.c
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
drivers/gpu/drm/amd/amdgpu/iceland_sdma_pkt_open.h
drivers/gpu/drm/amd/amdgpu/iceland_smc.c
drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
drivers/gpu/drm/amd/amdgpu/tonga_sdma_pkt_open.h
drivers/gpu/drm/amd/amdgpu/tonga_smc.c
drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c
drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c
drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
drivers/gpu/drm/amd/amdgpu/vce_v2_0.c
drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
drivers/gpu/drm/exynos/exynos_drm_fb.c
drivers/gpu/drm/exynos/exynos_drm_fb.h
drivers/gpu/drm/exynos/exynos_drm_fbdev.c
drivers/gpu/drm/exynos/exynos_drm_g2d.c
drivers/gpu/drm/exynos/exynos_drm_plane.c
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem_execbuffer.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/intel_bios.c
drivers/gpu/drm/i915/intel_bios.h
drivers/gpu/drm/i915/intel_csr.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_dp_mst.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_dsi.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_runtime_pm.c
drivers/gpu/drm/qxl/qxl_display.c
drivers/gpu/drm/qxl/qxl_drv.h
drivers/gpu/drm/radeon/atombios_dp.c
drivers/gpu/drm/radeon/radeon_audio.c
drivers/gpu/drm/radeon/radeon_combios.c
drivers/gpu/drm/radeon/radeon_dp_auxch.c
drivers/gpu/drm/rockchip/rockchip_drm_vop.c
drivers/gpu/drm/rockchip/rockchip_drm_vop.h
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
include/uapi/drm/i915_drm.h

index aa2dcf5..668939a 100644 (file)
@@ -98,6 +98,9 @@ extern int amdgpu_sched_hw_submission;
 #define AMDGPU_MAX_COMPUTE_RINGS               8
 #define AMDGPU_MAX_VCE_RINGS                   2
 
+/* max number of IP instances */
+#define AMDGPU_MAX_SDMA_INSTANCES              2
+
 /* number of hw syncs before falling back on blocking */
 #define AMDGPU_NUM_SYNCS                       4
 
@@ -262,7 +265,7 @@ struct amdgpu_buffer_funcs {
        unsigned        fill_num_dw;
 
        /* used for buffer clearing */
-       void (*emit_fill_buffer)(struct amdgpu_ring *ring,
+       void (*emit_fill_buffer)(struct amdgpu_ib *ib,
                                 /* value to write to memory */
                                 uint32_t src_data,
                                 /* dst addr in bytes */
@@ -340,6 +343,8 @@ struct amdgpu_ring_funcs {
        int (*test_ring)(struct amdgpu_ring *ring);
        int (*test_ib)(struct amdgpu_ring *ring);
        bool (*is_lockup)(struct amdgpu_ring *ring);
+       /* insert NOP packets */
+       void (*insert_nop)(struct amdgpu_ring *ring, uint32_t count);
 };
 
 /*
@@ -440,12 +445,11 @@ int amdgpu_fence_wait_next(struct amdgpu_ring *ring);
 int amdgpu_fence_wait_empty(struct amdgpu_ring *ring);
 unsigned amdgpu_fence_count_emitted(struct amdgpu_ring *ring);
 
-signed long amdgpu_fence_wait_multiple(struct amdgpu_device *adev,
-                                      struct fence **array,
-                                      uint32_t count,
-                                      bool wait_all,
-                                      bool intr,
-                                      signed long t);
+signed long amdgpu_fence_wait_any(struct amdgpu_device *adev,
+                                 struct fence **array,
+                                 uint32_t count,
+                                 bool intr,
+                                 signed long t);
 struct amdgpu_fence *amdgpu_fence_ref(struct amdgpu_fence *fence);
 void amdgpu_fence_unref(struct amdgpu_fence **fence);
 
@@ -717,6 +721,7 @@ int amdgpu_sync_resv(struct amdgpu_device *adev,
                     void *owner);
 int amdgpu_sync_rings(struct amdgpu_sync *sync,
                      struct amdgpu_ring *ring);
+struct fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync);
 int amdgpu_sync_wait(struct amdgpu_sync *sync);
 void amdgpu_sync_free(struct amdgpu_device *adev, struct amdgpu_sync *sync,
                      struct fence *fence);
@@ -1214,6 +1219,7 @@ int amdgpu_ib_ring_tests(struct amdgpu_device *adev);
 void amdgpu_ring_free_size(struct amdgpu_ring *ring);
 int amdgpu_ring_alloc(struct amdgpu_ring *ring, unsigned ndw);
 int amdgpu_ring_lock(struct amdgpu_ring *ring, unsigned ndw);
+void amdgpu_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count);
 void amdgpu_ring_commit(struct amdgpu_ring *ring);
 void amdgpu_ring_unlock_commit(struct amdgpu_ring *ring);
 void amdgpu_ring_undo(struct amdgpu_ring *ring);
@@ -1665,7 +1671,6 @@ struct amdgpu_uvd {
        struct amdgpu_bo        *vcpu_bo;
        void                    *cpu_addr;
        uint64_t                gpu_addr;
-       void                    *saved_bo;
        atomic_t                handles[AMDGPU_MAX_UVD_HANDLES];
        struct drm_file         *filp[AMDGPU_MAX_UVD_HANDLES];
        struct delayed_work     idle_work;
@@ -1709,6 +1714,7 @@ struct amdgpu_sdma {
        uint32_t                feature_version;
 
        struct amdgpu_ring      ring;
+       bool                    burst_nop;
 };
 
 /*
@@ -2057,7 +2063,7 @@ struct amdgpu_device {
        struct amdgpu_gfx               gfx;
 
        /* sdma */
-       struct amdgpu_sdma              sdma[2];
+       struct amdgpu_sdma              sdma[AMDGPU_MAX_SDMA_INSTANCES];
        struct amdgpu_irq_src           sdma_trap_irq;
        struct amdgpu_irq_src           sdma_illegal_inst_irq;
 
@@ -2196,6 +2202,21 @@ static inline void amdgpu_ring_write(struct amdgpu_ring *ring, uint32_t v)
        ring->ring_free_dw--;
 }
 
+static inline struct amdgpu_sdma * amdgpu_get_sdma_instance(struct amdgpu_ring *ring)
+{
+       struct amdgpu_device *adev = ring->adev;
+       int i;
+
+       for (i = 0; i < AMDGPU_MAX_SDMA_INSTANCES; i++)
+               if (&adev->sdma[i].ring == ring)
+                       break;
+
+       if (i < AMDGPU_MAX_SDMA_INSTANCES)
+               return &adev->sdma[i];
+       else
+               return NULL;
+}
+
 /*
  * ASICs macro.
  */
@@ -2248,7 +2269,7 @@ static inline void amdgpu_ring_write(struct amdgpu_ring *ring, uint32_t v)
 #define amdgpu_display_stop_mc_access(adev, s) (adev)->mode_info.funcs->stop_mc_access((adev), (s))
 #define amdgpu_display_resume_mc_access(adev, s) (adev)->mode_info.funcs->resume_mc_access((adev), (s))
 #define amdgpu_emit_copy_buffer(adev, ib, s, d, b) (adev)->mman.buffer_funcs->emit_copy_buffer((ib),  (s), (d), (b))
-#define amdgpu_emit_fill_buffer(adev, r, s, d, b) (adev)->mman.buffer_funcs->emit_fill_buffer((r), (s), (d), (b))
+#define amdgpu_emit_fill_buffer(adev, ib, s, d, b) (adev)->mman.buffer_funcs->emit_fill_buffer((ib), (s), (d), (b))
 #define amdgpu_dpm_get_temperature(adev) (adev)->pm.funcs->get_temperature((adev))
 #define amdgpu_dpm_pre_set_power_state(adev) (adev)->pm.funcs->pre_set_power_state((adev))
 #define amdgpu_dpm_set_power_state(adev) (adev)->pm.funcs->set_power_state((adev))
index 6a206f1..3b355ae 100644 (file)
@@ -354,7 +354,7 @@ int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p)
                         * into account. We don't want to disallow buffer moves
                         * completely.
                         */
-                       if (current_domain != AMDGPU_GEM_DOMAIN_CPU &&
+                       if ((lobj->allowed_domains & current_domain) != 0 &&
                            (domain & current_domain) == 0 && /* will be moved */
                            bytes_moved > bytes_moved_threshold) {
                                /* don't move it */
index 42d1a22..6ff6ae9 100644 (file)
@@ -244,7 +244,8 @@ static int amdgpu_vram_scratch_init(struct amdgpu_device *adev)
 
        if (adev->vram_scratch.robj == NULL) {
                r = amdgpu_bo_create(adev, AMDGPU_GPU_PAGE_SIZE,
-                                    PAGE_SIZE, true, AMDGPU_GEM_DOMAIN_VRAM, 0,
+                                    PAGE_SIZE, true, AMDGPU_GEM_DOMAIN_VRAM,
+                                    AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
                                     NULL, &adev->vram_scratch.robj);
                if (r) {
                        return r;
index 81b8212..8a122b1 100644 (file)
@@ -126,8 +126,8 @@ static int amdgpufb_create_pinned_object(struct amdgpu_fbdev *rfbdev,
        aligned_size = ALIGN(size, PAGE_SIZE);
        ret = amdgpu_gem_object_create(adev, aligned_size, 0,
                                       AMDGPU_GEM_DOMAIN_VRAM,
-                                      0, true,
-                                      &gobj);
+                                      AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+                                      true, &gobj);
        if (ret) {
                printk(KERN_ERR "failed to allocate framebuffer (%d)\n",
                       aligned_size);
index f446bf2..1be2bd6 100644 (file)
@@ -851,22 +851,6 @@ static bool amdgpu_test_signaled_any(struct fence **fences, uint32_t count)
        return false;
 }
 
-static bool amdgpu_test_signaled_all(struct fence **fences, uint32_t count)
-{
-       int idx;
-       struct fence *fence;
-
-       for (idx = 0; idx < count; ++idx) {
-               fence = fences[idx];
-               if (fence) {
-                       if (!test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags))
-                               return false;
-               }
-       }
-
-       return true;
-}
-
 struct amdgpu_wait_cb {
        struct fence_cb base;
        struct task_struct *task;
@@ -885,7 +869,7 @@ static signed long amdgpu_fence_default_wait(struct fence *f, bool intr,
        struct amdgpu_fence *fence = to_amdgpu_fence(f);
        struct amdgpu_device *adev = fence->ring->adev;
 
-       return amdgpu_fence_wait_multiple(adev, &f, 1, false, intr, t);
+       return amdgpu_fence_wait_any(adev, &f, 1, intr, t);
 }
 
 /**
@@ -894,23 +878,18 @@ static signed long amdgpu_fence_default_wait(struct fence *f, bool intr,
  * @adev:     amdgpu device
  * @array:    the fence array with amdgpu fence pointer
  * @count:    the number of the fence array
- * @wait_all: the flag of wait all(true) or wait any(false)
  * @intr:     when sleep, set the current task interruptable or not
  * @t:        timeout to wait
  *
- * If wait_all is true, it will return when all fences are signaled or timeout.
- * If wait_all is false, it will return when any fence is signaled or timeout.
+ * It will return when any fence is signaled or timeout.
  */
-signed long amdgpu_fence_wait_multiple(struct amdgpu_device *adev,
-                                      struct fence **array,
-                                      uint32_t count,
-                                      bool wait_all,
-                                      bool intr,
-                                      signed long t)
-{
-       long idx = 0;
+signed long amdgpu_fence_wait_any(struct amdgpu_device *adev,
+                                 struct fence **array, uint32_t count,
+                                 bool intr, signed long t)
+{
        struct amdgpu_wait_cb *cb;
        struct fence *fence;
+       unsigned idx;
 
        BUG_ON(!array);
 
@@ -927,10 +906,7 @@ signed long amdgpu_fence_wait_multiple(struct amdgpu_device *adev,
                        if (fence_add_callback(fence,
                                        &cb[idx].base, amdgpu_fence_wait_cb)) {
                                /* The fence is already signaled */
-                               if (wait_all)
-                                       continue;
-                               else
-                                       goto fence_rm_cb;
+                               goto fence_rm_cb;
                        }
                }
        }
@@ -945,9 +921,7 @@ signed long amdgpu_fence_wait_multiple(struct amdgpu_device *adev,
                 * amdgpu_test_signaled_any must be called after
                 * set_current_state to prevent a race with wake_up_process
                 */
-               if (!wait_all && amdgpu_test_signaled_any(array, count))
-                       break;
-               if (wait_all && amdgpu_test_signaled_all(array, count))
+               if (amdgpu_test_signaled_any(array, count))
                        break;
 
                if (adev->needs_reset) {
index e02db0b..cbd3a48 100644 (file)
@@ -125,7 +125,8 @@ int amdgpu_gart_table_vram_alloc(struct amdgpu_device *adev)
 
        if (adev->gart.robj == NULL) {
                r = amdgpu_bo_create(adev, adev->gart.table_size,
-                                    PAGE_SIZE, true, AMDGPU_GEM_DOMAIN_VRAM, 0,
+                                    PAGE_SIZE, true, AMDGPU_GEM_DOMAIN_VRAM,
+                                    AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
                                     NULL, &adev->gart.robj);
                if (r) {
                        return r;
index 4afc507..5839fab 100644 (file)
@@ -615,6 +615,7 @@ int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data,
                info.alignment = robj->tbo.mem.page_alignment << PAGE_SHIFT;
                info.domains = robj->initial_domain;
                info.domain_flags = robj->flags;
+               amdgpu_bo_unreserve(robj);
                if (copy_to_user(out, &info, sizeof(info)))
                        r = -EFAULT;
                break;
@@ -622,17 +623,19 @@ int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data,
        case AMDGPU_GEM_OP_SET_PLACEMENT:
                if (amdgpu_ttm_tt_has_userptr(robj->tbo.ttm)) {
                        r = -EPERM;
+                       amdgpu_bo_unreserve(robj);
                        break;
                }
                robj->initial_domain = args->value & (AMDGPU_GEM_DOMAIN_VRAM |
                                                      AMDGPU_GEM_DOMAIN_GTT |
                                                      AMDGPU_GEM_DOMAIN_CPU);
+               amdgpu_bo_unreserve(robj);
                break;
        default:
+               amdgpu_bo_unreserve(robj);
                r = -EINVAL;
        }
 
-       amdgpu_bo_unreserve(robj);
 out:
        drm_gem_object_unreference_unlocked(gobj);
        return r;
@@ -653,7 +656,8 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv,
 
        r = amdgpu_gem_object_create(adev, args->size, 0,
                                     AMDGPU_GEM_DOMAIN_VRAM,
-                                    0, ttm_bo_type_device,
+                                    AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+                                    ttm_bo_type_device,
                                     &gobj);
        if (r)
                return -ENOMEM;
index 57adcad..08b09d5 100644 (file)
@@ -127,7 +127,7 @@ static void amdgpu_ttm_placement_init(struct amdgpu_device *adev,
                        placements[c].fpfn =
                                adev->mc.visible_vram_size >> PAGE_SHIFT;
                        placements[c++].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED |
-                               TTM_PL_FLAG_VRAM;
+                               TTM_PL_FLAG_VRAM | TTM_PL_FLAG_TOPDOWN;
                }
                placements[c].fpfn = 0;
                placements[c++].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED |
index 7d442c5..9bec914 100644 (file)
@@ -131,6 +131,21 @@ int amdgpu_ring_lock(struct amdgpu_ring *ring, unsigned ndw)
        return 0;
 }
 
+/** amdgpu_ring_insert_nop - insert NOP packets
+ *
+ * @ring: amdgpu_ring structure holding ring information
+ * @count: the number of NOP packets to insert
+ *
+ * This is the generic insert_nop function for rings except SDMA
+ */
+void amdgpu_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
+{
+       int i;
+
+       for (i = 0; i < count; i++)
+               amdgpu_ring_write(ring, ring->nop);
+}
+
 /**
  * amdgpu_ring_commit - tell the GPU to execute the new
  * commands on the ring buffer
@@ -143,10 +158,13 @@ int amdgpu_ring_lock(struct amdgpu_ring *ring, unsigned ndw)
  */
 void amdgpu_ring_commit(struct amdgpu_ring *ring)
 {
+       uint32_t count;
+
        /* We pad to match fetch size */
-       while (ring->wptr & ring->align_mask) {
-               amdgpu_ring_write(ring, ring->nop);
-       }
+       count = ring->align_mask + 1 - (ring->wptr & ring->align_mask);
+       count %= ring->align_mask + 1;
+       ring->funcs->insert_nop(ring, count);
+
        mb();
        amdgpu_ring_set_wptr(ring);
 }
index b925253..74dad27 100644 (file)
@@ -367,8 +367,8 @@ int amdgpu_sa_bo_new(struct amdgpu_device *adev,
                } while (amdgpu_sa_bo_next_hole(sa_manager, fences, tries));
 
                spin_unlock(&sa_manager->wq.lock);
-               t = amdgpu_fence_wait_multiple(adev, fences, AMDGPU_MAX_RINGS, false, false,
-                                               MAX_SCHEDULE_TIMEOUT);
+               t = amdgpu_fence_wait_any(adev, fences, AMDGPU_MAX_RINGS,
+                                         false, MAX_SCHEDULE_TIMEOUT);
                r = (t > 0) ? 0 : t;
                spin_lock(&sa_manager->wq.lock);
                /* if we have nothing to wait for block */
index f93fb35..de98fbd 100644 (file)
 #include <drm/drmP.h>
 #include "amdgpu.h"
 
+static struct fence *amdgpu_sched_dependency(struct amd_sched_job *job)
+{
+       struct amdgpu_job *sched_job = (struct amdgpu_job *)job;
+       return amdgpu_sync_get_fence(&sched_job->ibs->sync);
+}
+
 static struct fence *amdgpu_sched_run_job(struct amd_sched_job *job)
 {
        struct amdgpu_job *sched_job;
@@ -75,6 +81,7 @@ static void amdgpu_sched_process_job(struct amd_sched_job *job)
 }
 
 struct amd_sched_backend_ops amdgpu_sched_ops = {
+       .dependency = amdgpu_sched_dependency,
        .run_job = amdgpu_sched_run_job,
        .process_job = amdgpu_sched_process_job
 };
index 4fffb25..068aeaf 100644 (file)
@@ -142,6 +142,18 @@ int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync,
        return 0;
 }
 
+static void *amdgpu_sync_get_owner(struct fence *f)
+{
+       struct amdgpu_fence *a_fence = to_amdgpu_fence(f);
+       struct amd_sched_fence *s_fence = to_amd_sched_fence(f);
+
+       if (s_fence)
+               return s_fence->owner;
+       else if (a_fence)
+               return a_fence->owner;
+       return AMDGPU_FENCE_OWNER_UNDEFINED;
+}
+
 /**
  * amdgpu_sync_resv - use the semaphores to sync to a reservation object
  *
@@ -158,7 +170,7 @@ int amdgpu_sync_resv(struct amdgpu_device *adev,
 {
        struct reservation_object_list *flist;
        struct fence *f;
-       struct amdgpu_fence *fence;
+       void *fence_owner;
        unsigned i;
        int r = 0;
 
@@ -176,22 +188,22 @@ int amdgpu_sync_resv(struct amdgpu_device *adev,
        for (i = 0; i < flist->shared_count; ++i) {
                f = rcu_dereference_protected(flist->shared[i],
                                              reservation_object_held(resv));
-               fence = f ? to_amdgpu_fence(f) : NULL;
-               if (fence && fence->ring->adev == adev) {
+               if (amdgpu_sync_same_dev(adev, f)) {
                        /* VM updates are only interesting
                         * for other VM updates and moves.
                         */
+                       fence_owner = amdgpu_sync_get_owner(f);
                        if ((owner != AMDGPU_FENCE_OWNER_MOVE) &&
-                           (fence->owner != AMDGPU_FENCE_OWNER_MOVE) &&
+                           (fence_owner != AMDGPU_FENCE_OWNER_MOVE) &&
                            ((owner == AMDGPU_FENCE_OWNER_VM) !=
-                            (fence->owner == AMDGPU_FENCE_OWNER_VM)))
+                            (fence_owner == AMDGPU_FENCE_OWNER_VM)))
                                continue;
 
                        /* Ignore fence from the same owner as
                         * long as it isn't undefined.
                         */
                        if (owner != AMDGPU_FENCE_OWNER_UNDEFINED &&
-                           fence->owner == owner)
+                           fence_owner == owner)
                                continue;
                }
 
@@ -202,6 +214,28 @@ int amdgpu_sync_resv(struct amdgpu_device *adev,
        return r;
 }
 
+struct fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync)
+{
+       struct amdgpu_sync_entry *e;
+       struct hlist_node *tmp;
+       struct fence *f;
+       int i;
+
+       hash_for_each_safe(sync->fences, i, tmp, e, node) {
+
+               f = e->fence;
+
+               hash_del(&e->node);
+               kfree(e);
+
+               if (!fence_is_signaled(f))
+                       return f;
+
+               fence_put(f);
+       }
+       return NULL;
+}
+
 int amdgpu_sync_wait(struct amdgpu_sync *sync)
 {
        struct amdgpu_sync_entry *e;
index 3991435..b5abd5c 100644 (file)
@@ -859,7 +859,8 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
        amdgpu_ttm_set_active_vram_size(adev, adev->mc.visible_vram_size);
 
        r = amdgpu_bo_create(adev, 256 * 1024, PAGE_SIZE, true,
-                            AMDGPU_GEM_DOMAIN_VRAM, 0,
+                            AMDGPU_GEM_DOMAIN_VRAM,
+                            AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
                             NULL, &adev->stollen_vga_memory);
        if (r) {
                return r;
index b87355c..2cf6c6b 100644 (file)
@@ -154,7 +154,9 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
        bo_size = AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8)
                 +  AMDGPU_UVD_STACK_SIZE + AMDGPU_UVD_HEAP_SIZE;
        r = amdgpu_bo_create(adev, bo_size, PAGE_SIZE, true,
-                            AMDGPU_GEM_DOMAIN_VRAM, 0, NULL, &adev->uvd.vcpu_bo);
+                            AMDGPU_GEM_DOMAIN_VRAM,
+                            AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+                            NULL, &adev->uvd.vcpu_bo);
        if (r) {
                dev_err(adev->dev, "(%d) failed to allocate UVD bo\n", r);
                return r;
@@ -221,31 +223,32 @@ int amdgpu_uvd_sw_fini(struct amdgpu_device *adev)
 
 int amdgpu_uvd_suspend(struct amdgpu_device *adev)
 {
-       unsigned size;
-       void *ptr;
-       const struct common_firmware_header *hdr;
-       int i;
+       struct amdgpu_ring *ring = &adev->uvd.ring;
+       int i, r;
 
        if (adev->uvd.vcpu_bo == NULL)
                return 0;
 
-       for (i = 0; i < AMDGPU_MAX_UVD_HANDLES; ++i)
-               if (atomic_read(&adev->uvd.handles[i]))
-                       break;
-
-       if (i == AMDGPU_MAX_UVD_HANDLES)
-               return 0;
+       for (i = 0; i < AMDGPU_MAX_UVD_HANDLES; ++i) {
+               uint32_t handle = atomic_read(&adev->uvd.handles[i]);
+               if (handle != 0) {
+                       struct fence *fence;
 
-       hdr = (const struct common_firmware_header *)adev->uvd.fw->data;
+                       amdgpu_uvd_note_usage(adev);
 
-       size = amdgpu_bo_size(adev->uvd.vcpu_bo);
-       size -= le32_to_cpu(hdr->ucode_size_bytes);
+                       r = amdgpu_uvd_get_destroy_msg(ring, handle, &fence);
+                       if (r) {
+                               DRM_ERROR("Error destroying UVD (%d)!\n", r);
+                               continue;
+                       }
 
-       ptr = adev->uvd.cpu_addr;
-       ptr += le32_to_cpu(hdr->ucode_size_bytes);
+                       fence_wait(fence, false);
+                       fence_put(fence);
 
-       adev->uvd.saved_bo = kmalloc(size, GFP_KERNEL);
-       memcpy(adev->uvd.saved_bo, ptr, size);
+                       adev->uvd.filp[i] = NULL;
+                       atomic_set(&adev->uvd.handles[i], 0);
+               }
+       }
 
        return 0;
 }
@@ -270,12 +273,7 @@ int amdgpu_uvd_resume(struct amdgpu_device *adev)
        ptr = adev->uvd.cpu_addr;
        ptr += le32_to_cpu(hdr->ucode_size_bytes);
 
-       if (adev->uvd.saved_bo != NULL) {
-               memcpy(ptr, adev->uvd.saved_bo, size);
-               kfree(adev->uvd.saved_bo);
-               adev->uvd.saved_bo = NULL;
-       } else
-               memset(ptr, 0, size);
+       memset(ptr, 0, size);
 
        return 0;
 }
@@ -905,7 +903,9 @@ int amdgpu_uvd_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
        int r, i;
 
        r = amdgpu_bo_create(adev, 1024, PAGE_SIZE, true,
-                            AMDGPU_GEM_DOMAIN_VRAM, 0, NULL, &bo);
+                            AMDGPU_GEM_DOMAIN_VRAM,
+                            AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+                            NULL, &bo);
        if (r)
                return r;
 
@@ -952,7 +952,9 @@ int amdgpu_uvd_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
        int r, i;
 
        r = amdgpu_bo_create(adev, 1024, PAGE_SIZE, true,
-                            AMDGPU_GEM_DOMAIN_VRAM, 0, NULL, &bo);
+                            AMDGPU_GEM_DOMAIN_VRAM,
+                            AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+                            NULL, &bo);
        if (r)
                return r;
 
index 1a984c9..3cab96c 100644 (file)
@@ -141,7 +141,9 @@ int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size)
        /* allocate firmware, stack and heap BO */
 
        r = amdgpu_bo_create(adev, size, PAGE_SIZE, true,
-                            AMDGPU_GEM_DOMAIN_VRAM, 0, NULL, &adev->vce.vcpu_bo);
+                            AMDGPU_GEM_DOMAIN_VRAM,
+                            AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+                            NULL, &adev->vce.vcpu_bo);
        if (r) {
                dev_err(adev->dev, "(%d) failed to allocate VCE bo\n", r);
                return r;
@@ -836,6 +838,10 @@ int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring)
        struct fence *fence = NULL;
        int r;
 
+       /* skip vce ring1 ib test for now, since it's not reliable */
+       if (ring == &ring->adev->vce.ring[1])
+               return 0;
+
        r = amdgpu_vce_get_create_msg(ring, 1, NULL);
        if (r) {
                DRM_ERROR("amdgpu: failed to get create msg (%d).\n", r);
index 83b7ce6..f68b7cd 100644 (file)
@@ -627,9 +627,14 @@ static int amdgpu_vm_update_ptes(struct amdgpu_device *adev,
 {
        uint64_t mask = AMDGPU_VM_PTE_COUNT - 1;
        uint64_t last_pte = ~0, last_dst = ~0;
+       void *owner = AMDGPU_FENCE_OWNER_VM;
        unsigned count = 0;
        uint64_t addr;
 
+       /* sync to everything on unmapping */
+       if (!(flags & AMDGPU_PTE_VALID))
+               owner = AMDGPU_FENCE_OWNER_UNDEFINED;
+
        /* walk over the address space and update the page tables */
        for (addr = start; addr < end; ) {
                uint64_t pt_idx = addr >> amdgpu_vm_block_size;
@@ -638,8 +643,7 @@ static int amdgpu_vm_update_ptes(struct amdgpu_device *adev,
                uint64_t pte;
                int r;
 
-               amdgpu_sync_resv(adev, &ib->sync, pt->tbo.resv,
-                                AMDGPU_FENCE_OWNER_VM);
+               amdgpu_sync_resv(adev, &ib->sync, pt->tbo.resv, owner);
                r = reservation_object_reserve_shared(pt->tbo.resv);
                if (r)
                        return r;
@@ -790,17 +794,6 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev,
 
        ib->length_dw = 0;
 
-       if (!(flags & AMDGPU_PTE_VALID)) {
-               unsigned i;
-
-               for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
-                       struct amdgpu_fence *f = vm->ids[i].last_id_use;
-                       r = amdgpu_sync_fence(adev, &ib->sync, &f->base);
-                       if (r)
-                               return r;
-               }
-       }
-
        r = amdgpu_vm_update_ptes(adev, vm, ib, mapping->it.start,
                                  mapping->it.last + 1, addr + mapping->offset,
                                  flags, gtt_flags);
@@ -1106,7 +1099,9 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
 
                r = amdgpu_bo_create(adev, AMDGPU_VM_PTE_COUNT * 8,
                                     AMDGPU_GPU_PAGE_SIZE, true,
-                                    AMDGPU_GEM_DOMAIN_VRAM, 0, NULL, &pt);
+                                    AMDGPU_GEM_DOMAIN_VRAM,
+                                    AMDGPU_GEM_CREATE_NO_CPU_ACCESS,
+                                    NULL, &pt);
                if (r)
                        goto error_free;
 
@@ -1306,7 +1301,8 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)
        vm->page_directory_fence = NULL;
 
        r = amdgpu_bo_create(adev, pd_size, align, true,
-                            AMDGPU_GEM_DOMAIN_VRAM, 0,
+                            AMDGPU_GEM_DOMAIN_VRAM,
+                            AMDGPU_GEM_CREATE_NO_CPU_ACCESS,
                             NULL, &vm->page_directory);
        if (r)
                return r;
index 9ba0a7d..92b6aca 100644 (file)
@@ -139,7 +139,8 @@ amdgpu_atombios_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *m
 
        tx_buf[0] = msg->address & 0xff;
        tx_buf[1] = msg->address >> 8;
-       tx_buf[2] = msg->request << 4;
+       tx_buf[2] = (msg->request << 4) |
+               ((msg->address >> 16) & 0xf);
        tx_buf[3] = msg->size ? (msg->size - 1) : 0;
 
        switch (msg->request & ~DP_AUX_I2C_MOT) {
index 3920c1e..9ea9de4 100644 (file)
@@ -188,6 +188,19 @@ static void cik_sdma_ring_set_wptr(struct amdgpu_ring *ring)
        WREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[me], (ring->wptr << 2) & 0x3fffc);
 }
 
+static void cik_sdma_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
+{
+       struct amdgpu_sdma *sdma = amdgpu_get_sdma_instance(ring);
+       int i;
+
+       for (i = 0; i < count; i++)
+               if (sdma && sdma->burst_nop && (i == 0))
+                       amdgpu_ring_write(ring, ring->nop |
+                                         SDMA_NOP_COUNT(count - 1));
+               else
+                       amdgpu_ring_write(ring, ring->nop);
+}
+
 /**
  * cik_sdma_ring_emit_ib - Schedule an IB on the DMA engine
  *
@@ -213,8 +226,8 @@ static void cik_sdma_ring_emit_ib(struct amdgpu_ring *ring,
        amdgpu_ring_write(ring, next_rptr);
 
        /* IB packet must end on a 8 DW boundary */
-       while ((ring->wptr & 7) != 4)
-               amdgpu_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_NOP, 0, 0));
+       cik_sdma_ring_insert_nop(ring, (12 - (ring->wptr & 7)) % 8);
+
        amdgpu_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_INDIRECT_BUFFER, 0, extra_bits));
        amdgpu_ring_write(ring, ib->gpu_addr & 0xffffffe0); /* base must be 32 byte aligned */
        amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xffffffff);
@@ -501,6 +514,8 @@ static int cik_sdma_load_microcode(struct amdgpu_device *adev)
                fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
                adev->sdma[i].fw_version = le32_to_cpu(hdr->header.ucode_version);
                adev->sdma[i].feature_version = le32_to_cpu(hdr->ucode_feature_version);
+               if (adev->sdma[i].feature_version >= 20)
+                       adev->sdma[i].burst_nop = true;
                fw_data = (const __le32 *)
                        (adev->sdma[i].fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
                WREG32(mmSDMA0_UCODE_ADDR + sdma_offsets[i], 0);
@@ -815,8 +830,19 @@ static void cik_sdma_vm_set_pte_pde(struct amdgpu_ib *ib,
  */
 static void cik_sdma_vm_pad_ib(struct amdgpu_ib *ib)
 {
-       while (ib->length_dw & 0x7)
-               ib->ptr[ib->length_dw++] = SDMA_PACKET(SDMA_OPCODE_NOP, 0, 0);
+       struct amdgpu_sdma *sdma = amdgpu_get_sdma_instance(ib->ring);
+       u32 pad_count;
+       int i;
+
+       pad_count = (8 - (ib->length_dw & 0x7)) % 8;
+       for (i = 0; i < pad_count; i++)
+               if (sdma && sdma->burst_nop && (i == 0))
+                       ib->ptr[ib->length_dw++] =
+                                       SDMA_PACKET(SDMA_OPCODE_NOP, 0, 0) |
+                                       SDMA_NOP_COUNT(pad_count - 1);
+               else
+                       ib->ptr[ib->length_dw++] =
+                                       SDMA_PACKET(SDMA_OPCODE_NOP, 0, 0);
 }
 
 /**
@@ -1303,6 +1329,7 @@ static const struct amdgpu_ring_funcs cik_sdma_ring_funcs = {
        .test_ring = cik_sdma_ring_test_ring,
        .test_ib = cik_sdma_ring_test_ib,
        .is_lockup = cik_sdma_ring_is_lockup,
+       .insert_nop = cik_sdma_ring_insert_nop,
 };
 
 static void cik_sdma_set_ring_funcs(struct amdgpu_device *adev)
@@ -1363,16 +1390,16 @@ static void cik_sdma_emit_copy_buffer(struct amdgpu_ib *ib,
  *
  * Fill GPU buffers using the DMA engine (CIK).
  */
-static void cik_sdma_emit_fill_buffer(struct amdgpu_ring *ring,
+static void cik_sdma_emit_fill_buffer(struct amdgpu_ib *ib,
                                      uint32_t src_data,
                                      uint64_t dst_offset,
                                      uint32_t byte_count)
 {
-       amdgpu_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_CONSTANT_FILL, 0, 0));
-       amdgpu_ring_write(ring, lower_32_bits(dst_offset));
-       amdgpu_ring_write(ring, upper_32_bits(dst_offset));
-       amdgpu_ring_write(ring, src_data);
-       amdgpu_ring_write(ring, byte_count);
+       ib->ptr[ib->length_dw++] = SDMA_PACKET(SDMA_OPCODE_CONSTANT_FILL, 0, 0);
+       ib->ptr[ib->length_dw++] = lower_32_bits(dst_offset);
+       ib->ptr[ib->length_dw++] = upper_32_bits(dst_offset);
+       ib->ptr[ib->length_dw++] = src_data;
+       ib->ptr[ib->length_dw++] = byte_count;
 }
 
 static const struct amdgpu_buffer_funcs cik_sdma_buffer_funcs = {
index a3e3dfa..7f6d457 100644 (file)
                                         (((op) & 0xFF) << 0))
 /* sDMA opcodes */
 #define        SDMA_OPCODE_NOP                                   0
+#      define SDMA_NOP_COUNT(x)                          (((x) & 0x3FFF) << 16)
 #define        SDMA_OPCODE_COPY                                  1
 #       define SDMA_COPY_SUB_OPCODE_LINEAR                0
 #       define SDMA_COPY_SUB_OPCODE_TILED                 1
index ace870a..44fa96a 100644 (file)
@@ -1596,9 +1596,9 @@ static int cz_dpm_update_low_memory_pstate(struct amdgpu_device *adev)
 
        if (pi->sys_info.nb_dpm_enable) {
                if (ps->force_high)
-                       cz_dpm_nbdpm_lm_pstate_enable(adev, true);
-               else
                        cz_dpm_nbdpm_lm_pstate_enable(adev, false);
+               else
+                       cz_dpm_nbdpm_lm_pstate_enable(adev, true);
        }
 
        return ret;
index 4b255ac..e4d101b 100644 (file)
@@ -1353,7 +1353,7 @@ static void dce_v10_0_program_watermarks(struct amdgpu_device *adev,
        tmp = REG_SET_FIELD(wm_mask, DPG_WATERMARK_MASK_CONTROL, URGENCY_WATERMARK_MASK, 2);
        WREG32(mmDPG_WATERMARK_MASK_CONTROL + amdgpu_crtc->crtc_offset, tmp);
        tmp = RREG32(mmDPG_PIPE_URGENCY_CONTROL + amdgpu_crtc->crtc_offset);
-       tmp = REG_SET_FIELD(tmp, DPG_PIPE_URGENCY_CONTROL, URGENCY_LOW_WATERMARK, latency_watermark_a);
+       tmp = REG_SET_FIELD(tmp, DPG_PIPE_URGENCY_CONTROL, URGENCY_LOW_WATERMARK, latency_watermark_b);
        tmp = REG_SET_FIELD(tmp, DPG_PIPE_URGENCY_CONTROL, URGENCY_HIGH_WATERMARK, line_time);
        WREG32(mmDPG_PIPE_URGENCY_CONTROL + amdgpu_crtc->crtc_offset, tmp);
        /* restore original selection */
index 70eee80..6411e82 100644 (file)
@@ -1329,7 +1329,7 @@ static void dce_v11_0_program_watermarks(struct amdgpu_device *adev,
        tmp = REG_SET_FIELD(wm_mask, DPG_WATERMARK_MASK_CONTROL, URGENCY_WATERMARK_MASK, 2);
        WREG32(mmDPG_WATERMARK_MASK_CONTROL + amdgpu_crtc->crtc_offset, tmp);
        tmp = RREG32(mmDPG_PIPE_URGENCY_CONTROL + amdgpu_crtc->crtc_offset);
-       tmp = REG_SET_FIELD(tmp, DPG_PIPE_URGENCY_CONTROL, URGENCY_LOW_WATERMARK, latency_watermark_a);
+       tmp = REG_SET_FIELD(tmp, DPG_PIPE_URGENCY_CONTROL, URGENCY_LOW_WATERMARK, latency_watermark_b);
        tmp = REG_SET_FIELD(tmp, DPG_PIPE_URGENCY_CONTROL, URGENCY_HIGH_WATERMARK, line_time);
        WREG32(mmDPG_PIPE_URGENCY_CONTROL + amdgpu_crtc->crtc_offset, tmp);
        /* restore original selection */
index 493c8c9..322edea 100644 (file)
@@ -762,7 +762,9 @@ int fiji_smu_init(struct amdgpu_device *adev)
 
        /* Allocate FW image data structure and header buffer */
        ret = amdgpu_bo_create(adev, image_size, PAGE_SIZE,
-                               true, AMDGPU_GEM_DOMAIN_VRAM, 0, NULL, toc_buf);
+                              true, AMDGPU_GEM_DOMAIN_VRAM,
+                              AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+                              NULL, toc_buf);
        if (ret) {
                DRM_ERROR("Failed to allocate memory for TOC buffer\n");
                return -ENOMEM;
@@ -770,7 +772,9 @@ int fiji_smu_init(struct amdgpu_device *adev)
 
        /* Allocate buffer for SMU internal buffer */
        ret = amdgpu_bo_create(adev, smu_internal_buffer_size, PAGE_SIZE,
-                               true, AMDGPU_GEM_DOMAIN_VRAM, 0, NULL, smu_buf);
+                              true, AMDGPU_GEM_DOMAIN_VRAM,
+                              AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+                              NULL, smu_buf);
        if (ret) {
                DRM_ERROR("Failed to allocate memory for SMU internal buffer\n");
                return -ENOMEM;
index fab7b23..4bd1e5c 100644 (file)
@@ -3786,7 +3786,9 @@ static int gfx_v7_0_rlc_init(struct amdgpu_device *adev)
                /* save restore block */
                if (adev->gfx.rlc.save_restore_obj == NULL) {
                        r = amdgpu_bo_create(adev, dws * 4, PAGE_SIZE, true,
-                                            AMDGPU_GEM_DOMAIN_VRAM, 0, NULL, &adev->gfx.rlc.save_restore_obj);
+                                            AMDGPU_GEM_DOMAIN_VRAM,
+                                            AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+                                            NULL, &adev->gfx.rlc.save_restore_obj);
                        if (r) {
                                dev_warn(adev->dev, "(%d) create RLC sr bo failed\n", r);
                                return r;
@@ -3827,7 +3829,9 @@ static int gfx_v7_0_rlc_init(struct amdgpu_device *adev)
 
                if (adev->gfx.rlc.clear_state_obj == NULL) {
                        r = amdgpu_bo_create(adev, dws * 4, PAGE_SIZE, true,
-                                            AMDGPU_GEM_DOMAIN_VRAM, 0, NULL, &adev->gfx.rlc.clear_state_obj);
+                                            AMDGPU_GEM_DOMAIN_VRAM,
+                                            AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+                                            NULL, &adev->gfx.rlc.clear_state_obj);
                        if (r) {
                                dev_warn(adev->dev, "(%d) create RLC c bo failed\n", r);
                                gfx_v7_0_rlc_fini(adev);
@@ -3864,7 +3868,9 @@ static int gfx_v7_0_rlc_init(struct amdgpu_device *adev)
        if (adev->gfx.rlc.cp_table_size) {
                if (adev->gfx.rlc.cp_table_obj == NULL) {
                        r = amdgpu_bo_create(adev, adev->gfx.rlc.cp_table_size, PAGE_SIZE, true,
-                                            AMDGPU_GEM_DOMAIN_VRAM, 0, NULL, &adev->gfx.rlc.cp_table_obj);
+                                            AMDGPU_GEM_DOMAIN_VRAM,
+                                            AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+                                            NULL, &adev->gfx.rlc.cp_table_obj);
                        if (r) {
                                dev_warn(adev->dev, "(%d) create RLC cp table bo failed\n", r);
                                gfx_v7_0_rlc_fini(adev);
@@ -5598,6 +5604,7 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_gfx = {
        .test_ring = gfx_v7_0_ring_test_ring,
        .test_ib = gfx_v7_0_ring_test_ib,
        .is_lockup = gfx_v7_0_ring_is_lockup,
+       .insert_nop = amdgpu_ring_insert_nop,
 };
 
 static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_compute = {
@@ -5614,6 +5621,7 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_compute = {
        .test_ring = gfx_v7_0_ring_test_ring,
        .test_ib = gfx_v7_0_ring_test_ib,
        .is_lockup = gfx_v7_0_ring_is_lockup,
+       .insert_nop = amdgpu_ring_insert_nop,
 };
 
 static void gfx_v7_0_set_ring_funcs(struct amdgpu_device *adev)
index 818edb3..53f0743 100644 (file)
@@ -2005,7 +2005,7 @@ static void gfx_v8_0_setup_rb(struct amdgpu_device *adev,
 }
 
 /**
- * gmc_v8_0_init_compute_vmid - gart enable
+ * gfx_v8_0_init_compute_vmid - gart enable
  *
  * @rdev: amdgpu_device pointer
  *
@@ -2015,7 +2015,7 @@ static void gfx_v8_0_setup_rb(struct amdgpu_device *adev,
 #define DEFAULT_SH_MEM_BASES   (0x6000)
 #define FIRST_COMPUTE_VMID     (8)
 #define LAST_COMPUTE_VMID      (16)
-static void gmc_v8_0_init_compute_vmid(struct amdgpu_device *adev)
+static void gfx_v8_0_init_compute_vmid(struct amdgpu_device *adev)
 {
        int i;
        uint32_t sh_mem_config;
@@ -2282,7 +2282,7 @@ static void gfx_v8_0_gpu_init(struct amdgpu_device *adev)
        vi_srbm_select(adev, 0, 0, 0, 0);
        mutex_unlock(&adev->srbm_mutex);
 
-       gmc_v8_0_init_compute_vmid(adev);
+       gfx_v8_0_init_compute_vmid(adev);
 
        mutex_lock(&adev->grbm_idx_mutex);
        /*
@@ -3240,7 +3240,8 @@ static int gfx_v8_0_cp_compute_resume(struct amdgpu_device *adev)
 
                /* enable the doorbell if requested */
                if (use_doorbell) {
-                       if (adev->asic_type == CHIP_CARRIZO) {
+                       if ((adev->asic_type == CHIP_CARRIZO) ||
+                           (adev->asic_type == CHIP_FIJI)) {
                                WREG32(mmCP_MEC_DOORBELL_RANGE_LOWER,
                                       AMDGPU_DOORBELL_KIQ << 2);
                                WREG32(mmCP_MEC_DOORBELL_RANGE_UPPER,
@@ -4378,6 +4379,7 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = {
        .test_ring = gfx_v8_0_ring_test_ring,
        .test_ib = gfx_v8_0_ring_test_ib,
        .is_lockup = gfx_v8_0_ring_is_lockup,
+       .insert_nop = amdgpu_ring_insert_nop,
 };
 
 static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_compute = {
@@ -4394,6 +4396,7 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_compute = {
        .test_ring = gfx_v8_0_ring_test_ring,
        .test_ib = gfx_v8_0_ring_test_ib,
        .is_lockup = gfx_v8_0_ring_is_lockup,
+       .insert_nop = amdgpu_ring_insert_nop,
 };
 
 static void gfx_v8_0_set_ring_funcs(struct amdgpu_device *adev)
index 1021882..774528a 100644 (file)
@@ -523,17 +523,11 @@ static int gmc_v7_0_gart_enable(struct amdgpu_device *adev)
        tmp = RREG32(mmVM_CONTEXT1_CNTL);
        tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, ENABLE_CONTEXT, 1);
        tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, PAGE_TABLE_DEPTH, 1);
-       tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT, 1);
        tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
-       tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT, 1);
        tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
-       tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT, 1);
        tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, PDE0_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
-       tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, VALID_PROTECTION_FAULT_ENABLE_INTERRUPT, 1);
        tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, VALID_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
-       tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, READ_PROTECTION_FAULT_ENABLE_INTERRUPT, 1);
        tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, READ_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
-       tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT, 1);
        tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
        tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, PAGE_TABLE_BLOCK_SIZE,
                            amdgpu_vm_block_size - 9);
@@ -852,6 +846,13 @@ static int gmc_v7_0_early_init(void *handle)
        return 0;
 }
 
+static int gmc_v7_0_late_init(void *handle)
+{
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+       return amdgpu_irq_get(adev, &adev->mc.vm_fault, 0);
+}
+
 static int gmc_v7_0_sw_init(void *handle)
 {
        int r;
@@ -976,6 +977,7 @@ static int gmc_v7_0_hw_fini(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+       amdgpu_irq_put(adev, &adev->mc.vm_fault, 0);
        gmc_v7_0_gart_disable(adev);
 
        return 0;
@@ -1301,7 +1303,7 @@ static int gmc_v7_0_set_powergating_state(void *handle,
 
 const struct amd_ip_funcs gmc_v7_0_ip_funcs = {
        .early_init = gmc_v7_0_early_init,
-       .late_init = NULL,
+       .late_init = gmc_v7_0_late_init,
        .sw_init = gmc_v7_0_sw_init,
        .sw_fini = gmc_v7_0_sw_fini,
        .hw_init = gmc_v7_0_hw_init,
index 78109b7..9a07742 100644 (file)
@@ -653,19 +653,12 @@ static int gmc_v8_0_gart_enable(struct amdgpu_device *adev)
        tmp = RREG32(mmVM_CONTEXT1_CNTL);
        tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, ENABLE_CONTEXT, 1);
        tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, PAGE_TABLE_DEPTH, 1);
-       tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT, 1);
        tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
-       tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT, 1);
        tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
-       tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT, 1);
        tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, PDE0_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
-       tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, VALID_PROTECTION_FAULT_ENABLE_INTERRUPT, 1);
        tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, VALID_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
-       tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, READ_PROTECTION_FAULT_ENABLE_INTERRUPT, 1);
        tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, READ_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
-       tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT, 1);
        tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
-       tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, EXECUTE_PROTECTION_FAULT_ENABLE_INTERRUPT, 1);
        tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
        tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, PAGE_TABLE_BLOCK_SIZE,
                            amdgpu_vm_block_size - 9);
@@ -852,6 +845,13 @@ static int gmc_v8_0_early_init(void *handle)
        return 0;
 }
 
+static int gmc_v8_0_late_init(void *handle)
+{
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+       return amdgpu_irq_get(adev, &adev->mc.vm_fault, 0);
+}
+
 static int gmc_v8_0_sw_init(void *handle)
 {
        int r;
@@ -978,6 +978,7 @@ static int gmc_v8_0_hw_fini(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+       amdgpu_irq_put(adev, &adev->mc.vm_fault, 0);
        gmc_v8_0_gart_disable(adev);
 
        return 0;
@@ -1288,7 +1289,7 @@ static int gmc_v8_0_set_powergating_state(void *handle,
 
 const struct amd_ip_funcs gmc_v8_0_ip_funcs = {
        .early_init = gmc_v8_0_early_init,
-       .late_init = NULL,
+       .late_init = gmc_v8_0_late_init,
        .sw_init = gmc_v8_0_sw_init,
        .sw_fini = gmc_v8_0_sw_fini,
        .hw_init = gmc_v8_0_hw_init,
index c723602..ee6a041 100644 (file)
 #define SDMA_PKT_NOP_HEADER_sub_op_shift  8
 #define SDMA_PKT_NOP_HEADER_SUB_OP(x) (((x) & SDMA_PKT_NOP_HEADER_sub_op_mask) << SDMA_PKT_NOP_HEADER_sub_op_shift)
 
+/*define for count field*/
+#define SDMA_PKT_NOP_HEADER_count_offset 0
+#define SDMA_PKT_NOP_HEADER_count_mask   0x00003FFF
+#define SDMA_PKT_NOP_HEADER_count_shift  16
+#define SDMA_PKT_NOP_HEADER_COUNT(x) (((x) & SDMA_PKT_NOP_HEADER_count_mask) << SDMA_PKT_NOP_HEADER_count_shift)
 
 #endif /* __ICELAND_SDMA_PKT_OPEN_H_ */
index c6f1e2f..c900aa9 100644 (file)
@@ -623,7 +623,9 @@ int iceland_smu_init(struct amdgpu_device *adev)
 
        /* Allocate FW image data structure and header buffer */
        ret = amdgpu_bo_create(adev, image_size, PAGE_SIZE,
-                              true, AMDGPU_GEM_DOMAIN_VRAM, 0, NULL, toc_buf);
+                              true, AMDGPU_GEM_DOMAIN_VRAM,
+                              AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+                              NULL, toc_buf);
        if (ret) {
                DRM_ERROR("Failed to allocate memory for TOC buffer\n");
                return -ENOMEM;
index 715e02d..14e8723 100644 (file)
@@ -146,6 +146,8 @@ static int sdma_v2_4_init_microcode(struct amdgpu_device *adev)
                hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma[i].fw->data;
                adev->sdma[i].fw_version = le32_to_cpu(hdr->header.ucode_version);
                adev->sdma[i].feature_version = le32_to_cpu(hdr->ucode_feature_version);
+               if (adev->sdma[i].feature_version >= 20)
+                       adev->sdma[i].burst_nop = true;
 
                if (adev->firmware.smu_load) {
                        info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SDMA0 + i];
@@ -218,6 +220,19 @@ static void sdma_v2_4_ring_set_wptr(struct amdgpu_ring *ring)
        WREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[me], ring->wptr << 2);
 }
 
+static void sdma_v2_4_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
+{
+       struct amdgpu_sdma *sdma = amdgpu_get_sdma_instance(ring);
+       int i;
+
+       for (i = 0; i < count; i++)
+               if (sdma && sdma->burst_nop && (i == 0))
+                       amdgpu_ring_write(ring, ring->nop |
+                               SDMA_PKT_NOP_HEADER_COUNT(count - 1));
+               else
+                       amdgpu_ring_write(ring, ring->nop);
+}
+
 /**
  * sdma_v2_4_ring_emit_ib - Schedule an IB on the DMA engine
  *
@@ -245,8 +260,8 @@ static void sdma_v2_4_ring_emit_ib(struct amdgpu_ring *ring,
        amdgpu_ring_write(ring, next_rptr);
 
        /* IB packet must end on a 8 DW boundary */
-       while ((ring->wptr & 7) != 2)
-               amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_NOP));
+       sdma_v2_4_ring_insert_nop(ring, (10 - (ring->wptr & 7)) % 8);
+
        amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_INDIRECT) |
                          SDMA_PKT_INDIRECT_HEADER_VMID(vmid));
        /* base must be 32 byte aligned */
@@ -879,8 +894,19 @@ static void sdma_v2_4_vm_set_pte_pde(struct amdgpu_ib *ib,
  */
 static void sdma_v2_4_vm_pad_ib(struct amdgpu_ib *ib)
 {
-       while (ib->length_dw & 0x7)
-               ib->ptr[ib->length_dw++] = SDMA_PKT_HEADER_OP(SDMA_OP_NOP);
+       struct amdgpu_sdma *sdma = amdgpu_get_sdma_instance(ib->ring);
+       u32 pad_count;
+       int i;
+
+       pad_count = (8 - (ib->length_dw & 0x7)) % 8;
+       for (i = 0; i < pad_count; i++)
+               if (sdma && sdma->burst_nop && (i == 0))
+                       ib->ptr[ib->length_dw++] =
+                               SDMA_PKT_HEADER_OP(SDMA_OP_NOP) |
+                               SDMA_PKT_NOP_HEADER_COUNT(pad_count - 1);
+               else
+                       ib->ptr[ib->length_dw++] =
+                               SDMA_PKT_HEADER_OP(SDMA_OP_NOP);
 }
 
 /**
@@ -1314,6 +1340,7 @@ static const struct amdgpu_ring_funcs sdma_v2_4_ring_funcs = {
        .test_ring = sdma_v2_4_ring_test_ring,
        .test_ib = sdma_v2_4_ring_test_ib,
        .is_lockup = sdma_v2_4_ring_is_lockup,
+       .insert_nop = sdma_v2_4_ring_insert_nop,
 };
 
 static void sdma_v2_4_set_ring_funcs(struct amdgpu_device *adev)
@@ -1375,16 +1402,16 @@ static void sdma_v2_4_emit_copy_buffer(struct amdgpu_ib *ib,
  *
  * Fill GPU buffers using the DMA engine (VI).
  */
-static void sdma_v2_4_emit_fill_buffer(struct amdgpu_ring *ring,
+static void sdma_v2_4_emit_fill_buffer(struct amdgpu_ib *ib,
                                       uint32_t src_data,
                                       uint64_t dst_offset,
                                       uint32_t byte_count)
 {
-       amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_CONST_FILL));
-       amdgpu_ring_write(ring, lower_32_bits(dst_offset));
-       amdgpu_ring_write(ring, upper_32_bits(dst_offset));
-       amdgpu_ring_write(ring, src_data);
-       amdgpu_ring_write(ring, byte_count);
+       ib->ptr[ib->length_dw++] = SDMA_PKT_HEADER_OP(SDMA_OP_CONST_FILL);
+       ib->ptr[ib->length_dw++] = lower_32_bits(dst_offset);
+       ib->ptr[ib->length_dw++] = upper_32_bits(dst_offset);
+       ib->ptr[ib->length_dw++] = src_data;
+       ib->ptr[ib->length_dw++] = byte_count;
 }
 
 static const struct amdgpu_buffer_funcs sdma_v2_4_buffer_funcs = {
index 67128c8..9bfe92d 100644 (file)
@@ -218,6 +218,8 @@ static int sdma_v3_0_init_microcode(struct amdgpu_device *adev)
                hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma[i].fw->data;
                adev->sdma[i].fw_version = le32_to_cpu(hdr->header.ucode_version);
                adev->sdma[i].feature_version = le32_to_cpu(hdr->ucode_feature_version);
+               if (adev->sdma[i].feature_version >= 20)
+                       adev->sdma[i].burst_nop = true;
 
                if (adev->firmware.smu_load) {
                        info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SDMA0 + i];
@@ -304,6 +306,19 @@ static void sdma_v3_0_ring_set_wptr(struct amdgpu_ring *ring)
        }
 }
 
+static void sdma_v3_0_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
+{
+       struct amdgpu_sdma *sdma = amdgpu_get_sdma_instance(ring);
+       int i;
+
+       for (i = 0; i < count; i++)
+               if (sdma && sdma->burst_nop && (i == 0))
+                       amdgpu_ring_write(ring, ring->nop |
+                               SDMA_PKT_NOP_HEADER_COUNT(count - 1));
+               else
+                       amdgpu_ring_write(ring, ring->nop);
+}
+
 /**
  * sdma_v3_0_ring_emit_ib - Schedule an IB on the DMA engine
  *
@@ -330,8 +345,7 @@ static void sdma_v3_0_ring_emit_ib(struct amdgpu_ring *ring,
        amdgpu_ring_write(ring, next_rptr);
 
        /* IB packet must end on a 8 DW boundary */
-       while ((ring->wptr & 7) != 2)
-               amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_NOP));
+       sdma_v3_0_ring_insert_nop(ring, (10 - (ring->wptr & 7)) % 8);
 
        amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_INDIRECT) |
                          SDMA_PKT_INDIRECT_HEADER_VMID(vmid));
@@ -999,8 +1013,19 @@ static void sdma_v3_0_vm_set_pte_pde(struct amdgpu_ib *ib,
  */
 static void sdma_v3_0_vm_pad_ib(struct amdgpu_ib *ib)
 {
-       while (ib->length_dw & 0x7)
-               ib->ptr[ib->length_dw++] = SDMA_PKT_HEADER_OP(SDMA_OP_NOP);
+       struct amdgpu_sdma *sdma = amdgpu_get_sdma_instance(ib->ring);
+       u32 pad_count;
+       int i;
+
+       pad_count = (8 - (ib->length_dw & 0x7)) % 8;
+       for (i = 0; i < pad_count; i++)
+               if (sdma && sdma->burst_nop && (i == 0))
+                       ib->ptr[ib->length_dw++] =
+                               SDMA_PKT_HEADER_OP(SDMA_OP_NOP) |
+                               SDMA_PKT_NOP_HEADER_COUNT(pad_count - 1);
+               else
+                       ib->ptr[ib->length_dw++] =
+                               SDMA_PKT_HEADER_OP(SDMA_OP_NOP);
 }
 
 /**
@@ -1438,6 +1463,7 @@ static const struct amdgpu_ring_funcs sdma_v3_0_ring_funcs = {
        .test_ring = sdma_v3_0_ring_test_ring,
        .test_ib = sdma_v3_0_ring_test_ib,
        .is_lockup = sdma_v3_0_ring_is_lockup,
+       .insert_nop = sdma_v3_0_ring_insert_nop,
 };
 
 static void sdma_v3_0_set_ring_funcs(struct amdgpu_device *adev)
@@ -1499,16 +1525,16 @@ static void sdma_v3_0_emit_copy_buffer(struct amdgpu_ib *ib,
  *
  * Fill GPU buffers using the DMA engine (VI).
  */
-static void sdma_v3_0_emit_fill_buffer(struct amdgpu_ring *ring,
+static void sdma_v3_0_emit_fill_buffer(struct amdgpu_ib *ib,
                                       uint32_t src_data,
                                       uint64_t dst_offset,
                                       uint32_t byte_count)
 {
-       amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_CONST_FILL));
-       amdgpu_ring_write(ring, lower_32_bits(dst_offset));
-       amdgpu_ring_write(ring, upper_32_bits(dst_offset));
-       amdgpu_ring_write(ring, src_data);
-       amdgpu_ring_write(ring, byte_count);
+       ib->ptr[ib->length_dw++] = SDMA_PKT_HEADER_OP(SDMA_OP_CONST_FILL);
+       ib->ptr[ib->length_dw++] = lower_32_bits(dst_offset);
+       ib->ptr[ib->length_dw++] = upper_32_bits(dst_offset);
+       ib->ptr[ib->length_dw++] = src_data;
+       ib->ptr[ib->length_dw++] = byte_count;
 }
 
 static const struct amdgpu_buffer_funcs sdma_v3_0_buffer_funcs = {
index 099b7b5..e5ebd08 100644 (file)
 #define SDMA_PKT_NOP_HEADER_sub_op_shift  8
 #define SDMA_PKT_NOP_HEADER_SUB_OP(x) (((x) & SDMA_PKT_NOP_HEADER_sub_op_mask) << SDMA_PKT_NOP_HEADER_sub_op_shift)
 
+/*define for count field*/
+#define SDMA_PKT_NOP_HEADER_count_offset 0
+#define SDMA_PKT_NOP_HEADER_count_mask   0x00003FFF
+#define SDMA_PKT_NOP_HEADER_count_shift  16
+#define SDMA_PKT_NOP_HEADER_COUNT(x) (((x) & SDMA_PKT_NOP_HEADER_count_mask) << SDMA_PKT_NOP_HEADER_count_shift)
 
 #endif /* __TONGA_SDMA_PKT_OPEN_H_ */
index 5fc53a4..1f5ac94 100644 (file)
@@ -761,7 +761,9 @@ int tonga_smu_init(struct amdgpu_device *adev)
 
        /* Allocate FW image data structure and header buffer */
        ret = amdgpu_bo_create(adev, image_size, PAGE_SIZE,
-                               true, AMDGPU_GEM_DOMAIN_VRAM, 0, NULL, toc_buf);
+                              true, AMDGPU_GEM_DOMAIN_VRAM,
+                              AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+                              NULL, toc_buf);
        if (ret) {
                DRM_ERROR("Failed to allocate memory for TOC buffer\n");
                return -ENOMEM;
@@ -769,7 +771,9 @@ int tonga_smu_init(struct amdgpu_device *adev)
 
        /* Allocate buffer for SMU internal buffer */
        ret = amdgpu_bo_create(adev, smu_internal_buffer_size, PAGE_SIZE,
-                               true, AMDGPU_GEM_DOMAIN_VRAM, 0, NULL, smu_buf);
+                              true, AMDGPU_GEM_DOMAIN_VRAM,
+                              AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+                              NULL, smu_buf);
        if (ret) {
                DRM_ERROR("Failed to allocate memory for SMU internal buffer\n");
                return -ENOMEM;
index 9ac383b..5fac5da 100644 (file)
@@ -886,6 +886,7 @@ static const struct amdgpu_ring_funcs uvd_v4_2_ring_funcs = {
        .test_ring = uvd_v4_2_ring_test_ring,
        .test_ib = uvd_v4_2_ring_test_ib,
        .is_lockup = amdgpu_ring_test_lockup,
+       .insert_nop = amdgpu_ring_insert_nop,
 };
 
 static void uvd_v4_2_set_ring_funcs(struct amdgpu_device *adev)
index de4b3f5..2d5c59c 100644 (file)
@@ -825,6 +825,7 @@ static const struct amdgpu_ring_funcs uvd_v5_0_ring_funcs = {
        .test_ring = uvd_v5_0_ring_test_ring,
        .test_ib = uvd_v5_0_ring_test_ib,
        .is_lockup = amdgpu_ring_test_lockup,
+       .insert_nop = amdgpu_ring_insert_nop,
 };
 
 static void uvd_v5_0_set_ring_funcs(struct amdgpu_device *adev)
index 66c9758..d9f553f 100644 (file)
@@ -805,6 +805,7 @@ static const struct amdgpu_ring_funcs uvd_v6_0_ring_funcs = {
        .test_ring = uvd_v6_0_ring_test_ring,
        .test_ib = uvd_v6_0_ring_test_ib,
        .is_lockup = amdgpu_ring_test_lockup,
+       .insert_nop = amdgpu_ring_insert_nop,
 };
 
 static void uvd_v6_0_set_ring_funcs(struct amdgpu_device *adev)
index 303d961..cd16df5 100644 (file)
@@ -643,6 +643,7 @@ static const struct amdgpu_ring_funcs vce_v2_0_ring_funcs = {
        .test_ring = amdgpu_vce_ring_test_ring,
        .test_ib = amdgpu_vce_ring_test_ib,
        .is_lockup = amdgpu_ring_test_lockup,
+       .insert_nop = amdgpu_ring_insert_nop,
 };
 
 static void vce_v2_0_set_ring_funcs(struct amdgpu_device *adev)
index 4349658..f0656df 100644 (file)
@@ -32,8 +32,8 @@
 #include "vid.h"
 #include "vce/vce_3_0_d.h"
 #include "vce/vce_3_0_sh_mask.h"
-#include "oss/oss_2_0_d.h"
-#include "oss/oss_2_0_sh_mask.h"
+#include "oss/oss_3_0_d.h"
+#include "oss/oss_3_0_sh_mask.h"
 #include "gca/gfx_8_0_d.h"
 #include "smu/smu_7_1_2_d.h"
 #include "smu/smu_7_1_2_sh_mask.h"
@@ -426,17 +426,41 @@ static void vce_v3_0_mc_resume(struct amdgpu_device *adev, int idx)
 static bool vce_v3_0_is_idle(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+       u32 mask = 0;
+       int idx;
 
-       return !(RREG32(mmSRBM_STATUS2) & SRBM_STATUS2__VCE_BUSY_MASK);
+       for (idx = 0; idx < 2; ++idx) {
+               if (adev->vce.harvest_config & (1 << idx))
+                       continue;
+
+               if (idx == 0)
+                       mask |= SRBM_STATUS2__VCE0_BUSY_MASK;
+               else
+                       mask |= SRBM_STATUS2__VCE1_BUSY_MASK;
+       }
+
+       return !(RREG32(mmSRBM_STATUS2) & mask);
 }
 
 static int vce_v3_0_wait_for_idle(void *handle)
 {
        unsigned i;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+       u32 mask = 0;
+       int idx;
+
+       for (idx = 0; idx < 2; ++idx) {
+               if (adev->vce.harvest_config & (1 << idx))
+                       continue;
+
+               if (idx == 0)
+                       mask |= SRBM_STATUS2__VCE0_BUSY_MASK;
+               else
+                       mask |= SRBM_STATUS2__VCE1_BUSY_MASK;
+       }
 
        for (i = 0; i < adev->usec_timeout; i++) {
-               if (!(RREG32(mmSRBM_STATUS2) & SRBM_STATUS2__VCE_BUSY_MASK))
+               if (!(RREG32(mmSRBM_STATUS2) & mask))
                        return 0;
        }
        return -ETIMEDOUT;
@@ -445,9 +469,21 @@ static int vce_v3_0_wait_for_idle(void *handle)
 static int vce_v3_0_soft_reset(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+       u32 mask = 0;
+       int idx;
+
+       for (idx = 0; idx < 2; ++idx) {
+               if (adev->vce.harvest_config & (1 << idx))
+                       continue;
 
-       WREG32_P(mmSRBM_SOFT_RESET, SRBM_SOFT_RESET__SOFT_RESET_VCE_MASK,
-                       ~SRBM_SOFT_RESET__SOFT_RESET_VCE_MASK);
+               if (idx == 0)
+                       mask |= SRBM_SOFT_RESET__SOFT_RESET_VCE0_MASK;
+               else
+                       mask |= SRBM_SOFT_RESET__SOFT_RESET_VCE1_MASK;
+       }
+       WREG32_P(mmSRBM_SOFT_RESET, mask,
+                ~(SRBM_SOFT_RESET__SOFT_RESET_VCE0_MASK |
+                  SRBM_SOFT_RESET__SOFT_RESET_VCE1_MASK));
        mdelay(5);
 
        return vce_v3_0_start(adev);
@@ -608,6 +644,7 @@ static const struct amdgpu_ring_funcs vce_v3_0_ring_funcs = {
        .test_ring = amdgpu_vce_ring_test_ring,
        .test_ib = amdgpu_vce_ring_test_ib,
        .is_lockup = amdgpu_ring_test_lockup,
+       .insert_nop = amdgpu_ring_insert_nop,
 };
 
 static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev)
index d99fe90..9259f1b 100644 (file)
@@ -27,6 +27,8 @@
 #include <drm/drmP.h>
 #include "gpu_scheduler.h"
 
+static struct amd_sched_job *
+amd_sched_entity_pop_job(struct amd_sched_entity *entity);
 static void amd_sched_wakeup(struct amd_gpu_scheduler *sched);
 
 /* Initialize a given run queue struct */
@@ -56,34 +58,36 @@ static void amd_sched_rq_remove_entity(struct amd_sched_rq *rq,
 }
 
 /**
- * Select next entity from a specified run queue with round robin policy.
- * It could return the same entity as current one if current is the only
- * available one in the queue. Return NULL if nothing available.
+ * Select next job from a specified run queue with round robin policy.
+ * Return NULL if nothing available.
  */
-static struct amd_sched_entity *
-amd_sched_rq_select_entity(struct amd_sched_rq *rq)
+static struct amd_sched_job *
+amd_sched_rq_select_job(struct amd_sched_rq *rq)
 {
        struct amd_sched_entity *entity;
+       struct amd_sched_job *job;
 
        spin_lock(&rq->lock);
 
        entity = rq->current_entity;
        if (entity) {
                list_for_each_entry_continue(entity, &rq->entities, list) {
-                       if (!kfifo_is_empty(&entity->job_queue)) {
+                       job = amd_sched_entity_pop_job(entity);
+                       if (job) {
                                rq->current_entity = entity;
                                spin_unlock(&rq->lock);
-                               return rq->current_entity;
+                               return job;
                        }
                }
        }
 
        list_for_each_entry(entity, &rq->entities, list) {
 
-               if (!kfifo_is_empty(&entity->job_queue)) {
+               job = amd_sched_entity_pop_job(entity);
+               if (job) {
                        rq->current_entity = entity;
                        spin_unlock(&rq->lock);
-                       return rq->current_entity;
+                       return job;
                }
 
                if (entity == rq->current_entity)
@@ -188,6 +192,39 @@ void amd_sched_entity_fini(struct amd_gpu_scheduler *sched,
        kfifo_free(&entity->job_queue);
 }
 
+static void amd_sched_entity_wakeup(struct fence *f, struct fence_cb *cb)
+{
+       struct amd_sched_entity *entity =
+               container_of(cb, struct amd_sched_entity, cb);
+       entity->dependency = NULL;
+       fence_put(f);
+       amd_sched_wakeup(entity->scheduler);
+}
+
+static struct amd_sched_job *
+amd_sched_entity_pop_job(struct amd_sched_entity *entity)
+{
+       struct amd_gpu_scheduler *sched = entity->scheduler;
+       struct amd_sched_job *job;
+
+       if (ACCESS_ONCE(entity->dependency))
+               return NULL;
+
+       if (!kfifo_out_peek(&entity->job_queue, &job, sizeof(job)))
+               return NULL;
+
+       while ((entity->dependency = sched->ops->dependency(job))) {
+
+               if (fence_add_callback(entity->dependency, &entity->cb,
+                                      amd_sched_entity_wakeup))
+                       fence_put(entity->dependency);
+               else
+                       return NULL;
+       }
+
+       return job;
+}
+
 /**
  * Helper to submit a job to the job queue
  *
@@ -227,7 +264,6 @@ int amd_sched_entity_push_job(struct amd_sched_job *sched_job)
        struct amd_sched_entity *entity = sched_job->s_entity;
        struct amd_sched_fence *fence = amd_sched_fence_create(
                entity, sched_job->owner);
-       int r;
 
        if (!fence)
                return -ENOMEM;
@@ -235,10 +271,10 @@ int amd_sched_entity_push_job(struct amd_sched_job *sched_job)
        fence_get(&fence->base);
        sched_job->s_fence = fence;
 
-       r = wait_event_interruptible(entity->scheduler->job_scheduled,
-                                    amd_sched_entity_in(sched_job));
+       wait_event(entity->scheduler->job_scheduled,
+                  amd_sched_entity_in(sched_job));
 
-       return r;
+       return 0;
 }
 
 /**
@@ -260,22 +296,22 @@ static void amd_sched_wakeup(struct amd_gpu_scheduler *sched)
 }
 
 /**
- * Select next entity containing real IB submissions
+ * Select next to run
 */
-static struct amd_sched_entity *
-amd_sched_select_context(struct amd_gpu_scheduler *sched)
+static struct amd_sched_job *
+amd_sched_select_job(struct amd_gpu_scheduler *sched)
 {
-       struct amd_sched_entity *tmp;
+       struct amd_sched_job *job;
 
        if (!amd_sched_ready(sched))
                return NULL;
 
        /* Kernel run queue has higher priority than normal run queue*/
-       tmp = amd_sched_rq_select_entity(&sched->kernel_rq);
-       if (tmp == NULL)
-               tmp = amd_sched_rq_select_entity(&sched->sched_rq);
+       job = amd_sched_rq_select_job(&sched->kernel_rq);
+       if (job == NULL)
+               job = amd_sched_rq_select_job(&sched->sched_rq);
 
-       return tmp;
+       return job;
 }
 
 static void amd_sched_process_job(struct fence *f, struct fence_cb *cb)
@@ -296,27 +332,24 @@ static int amd_sched_main(void *param)
 {
        struct sched_param sparam = {.sched_priority = 1};
        struct amd_gpu_scheduler *sched = (struct amd_gpu_scheduler *)param;
-       int r;
+       int r, count;
 
        sched_setscheduler(current, SCHED_FIFO, &sparam);
 
        while (!kthread_should_stop()) {
-               struct amd_sched_entity *c_entity = NULL;
+               struct amd_sched_entity *entity;
                struct amd_sched_job *job;
                struct fence *fence;
 
                wait_event_interruptible(sched->wake_up_worker,
                        kthread_should_stop() ||
-                       (c_entity = amd_sched_select_context(sched)));
+                       (job = amd_sched_select_job(sched)));
 
-               if (!c_entity)
+               if (!job)
                        continue;
 
-               r = kfifo_out(&c_entity->job_queue, &job, sizeof(void *));
-               if (r != sizeof(void *))
-                       continue;
+               entity = job->s_entity;
                atomic_inc(&sched->hw_rq_count);
-
                fence = sched->ops->run_job(job);
                if (fence) {
                        r = fence_add_callback(fence, &job->cb,
@@ -328,6 +361,8 @@ static int amd_sched_main(void *param)
                        fence_put(fence);
                }
 
+               count = kfifo_out(&entity->job_queue, &job, sizeof(job));
+               WARN_ON(count != sizeof(job));
                wake_up(&sched->job_scheduled);
        }
        return 0;
index e797796..2af0e4d 100644 (file)
@@ -45,6 +45,8 @@ struct amd_sched_entity {
        spinlock_t                      queue_lock;
        struct amd_gpu_scheduler        *scheduler;
        uint64_t                        fence_context;
+       struct fence                    *dependency;
+       struct fence_cb                 cb;
 };
 
 /**
@@ -89,6 +91,7 @@ static inline struct amd_sched_fence *to_amd_sched_fence(struct fence *f)
  * these functions should be implemented in driver side
 */
 struct amd_sched_backend_ops {
+       struct fence *(*dependency)(struct amd_sched_job *job);
        struct fence *(*run_job)(struct amd_sched_job *job);
        void (*process_job)(struct amd_sched_job *job);
 };
index 59ebbe5..0842808 100644 (file)
@@ -23,7 +23,6 @@
 #include "exynos_drm_drv.h"
 #include "exynos_drm_fb.h"
 #include "exynos_drm_fbdev.h"
-#include "exynos_drm_gem.h"
 #include "exynos_drm_iommu.h"
 #include "exynos_drm_crtc.h"
 
  * exynos specific framebuffer structure.
  *
  * @fb: drm framebuffer obejct.
- * @buf_cnt: a buffer count to drm framebuffer.
  * @exynos_gem_obj: array of exynos specific gem object containing a gem object.
  */
 struct exynos_drm_fb {
        struct drm_framebuffer          fb;
-       unsigned int                    buf_cnt;
        struct exynos_drm_gem_obj       *exynos_gem_obj[MAX_FB_BUFFER];
 };
 
@@ -98,10 +95,6 @@ static int exynos_drm_fb_create_handle(struct drm_framebuffer *fb,
 {
        struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
 
-       /* This fb should have only one gem object. */
-       if (WARN_ON(exynos_fb->buf_cnt != 1))
-               return -EINVAL;
-
        return drm_gem_handle_create(file_priv,
                        &exynos_fb->exynos_gem_obj[0]->base, handle);
 }
@@ -122,119 +115,77 @@ static struct drm_framebuffer_funcs exynos_drm_fb_funcs = {
        .dirty          = exynos_drm_fb_dirty,
 };
 
-void exynos_drm_fb_set_buf_cnt(struct drm_framebuffer *fb,
-                                               unsigned int cnt)
-{
-       struct exynos_drm_fb *exynos_fb;
-
-       exynos_fb = to_exynos_fb(fb);
-
-       exynos_fb->buf_cnt = cnt;
-}
-
-unsigned int exynos_drm_fb_get_buf_cnt(struct drm_framebuffer *fb)
-{
-       struct exynos_drm_fb *exynos_fb;
-
-       exynos_fb = to_exynos_fb(fb);
-
-       return exynos_fb->buf_cnt;
-}
-
 struct drm_framebuffer *
 exynos_drm_framebuffer_init(struct drm_device *dev,
                            struct drm_mode_fb_cmd2 *mode_cmd,
-                           struct drm_gem_object *obj)
+                           struct exynos_drm_gem_obj **gem_obj,
+                           int count)
 {
        struct exynos_drm_fb *exynos_fb;
-       struct exynos_drm_gem_obj *exynos_gem_obj;
+       int i;
        int ret;
 
-       exynos_gem_obj = to_exynos_gem_obj(obj);
-
-       ret = check_fb_gem_memory_type(dev, exynos_gem_obj);
-       if (ret < 0)
-               return ERR_PTR(ret);
-
        exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL);
        if (!exynos_fb)
                return ERR_PTR(-ENOMEM);
 
+       for (i = 0; i < count; i++) {
+               ret = check_fb_gem_memory_type(dev, gem_obj[i]);
+               if (ret < 0)
+                       goto err;
+
+               exynos_fb->exynos_gem_obj[i] = gem_obj[i];
+       }
+
        drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd);
-       exynos_fb->exynos_gem_obj[0] = exynos_gem_obj;
 
        ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs);
-       if (ret) {
-               kfree(exynos_fb);
+       if (ret < 0) {
                DRM_ERROR("failed to initialize framebuffer\n");
-               return ERR_PTR(ret);
+               goto err;
        }
 
        return &exynos_fb->fb;
+
+err:
+       kfree(exynos_fb);
+       return ERR_PTR(ret);
 }
 
 static struct drm_framebuffer *
 exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
                      struct drm_mode_fb_cmd2 *mode_cmd)
 {
+       struct exynos_drm_gem_obj *gem_objs[MAX_FB_BUFFER];
        struct drm_gem_object *obj;
-       struct exynos_drm_gem_obj *exynos_gem_obj;
-       struct exynos_drm_fb *exynos_fb;
-       int i, ret;
-
-       exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL);
-       if (!exynos_fb)
-               return ERR_PTR(-ENOMEM);
-
-       obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
-       if (!obj) {
-               DRM_ERROR("failed to lookup gem object\n");
-               ret = -ENOENT;
-               goto err_free;
-       }
-
-       drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd);
-       exynos_fb->exynos_gem_obj[0] = to_exynos_gem_obj(obj);
-       exynos_fb->buf_cnt = drm_format_num_planes(mode_cmd->pixel_format);
-
-       DRM_DEBUG_KMS("buf_cnt = %d\n", exynos_fb->buf_cnt);
+       struct drm_framebuffer *fb;
+       int i;
+       int ret;
 
-       for (i = 1; i < exynos_fb->buf_cnt; i++) {
+       for (i = 0; i < drm_format_num_planes(mode_cmd->pixel_format); i++) {
                obj = drm_gem_object_lookup(dev, file_priv,
-                               mode_cmd->handles[i]);
+                                           mode_cmd->handles[i]);
                if (!obj) {
                        DRM_ERROR("failed to lookup gem object\n");
                        ret = -ENOENT;
-                       exynos_fb->buf_cnt = i;
-                       goto err_unreference;
+                       goto err;
                }
 
-               exynos_gem_obj = to_exynos_gem_obj(obj);
-               exynos_fb->exynos_gem_obj[i] = exynos_gem_obj;
-
-               ret = check_fb_gem_memory_type(dev, exynos_gem_obj);
-               if (ret < 0)
-                       goto err_unreference;
+               gem_objs[i] = to_exynos_gem_obj(obj);
        }
 
-       ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs);
-       if (ret) {
-               DRM_ERROR("failed to init framebuffer.\n");
-               goto err_unreference;
+       fb = exynos_drm_framebuffer_init(dev, mode_cmd, gem_objs, i);
+       if (IS_ERR(fb)) {
+               ret = PTR_ERR(fb);
+               goto err;
        }
 
-       return &exynos_fb->fb;
+       return fb;
 
-err_unreference:
-       for (i = 0; i < exynos_fb->buf_cnt; i++) {
-               struct drm_gem_object *obj;
+err:
+       while (i--)
+               drm_gem_object_unreference_unlocked(&gem_objs[i]->base);
 
-               obj = &exynos_fb->exynos_gem_obj[i]->base;
-               if (obj)
-                       drm_gem_object_unreference_unlocked(obj);
-       }
-err_free:
-       kfree(exynos_fb);
        return ERR_PTR(ret);
 }
 
index 1c9e27c..85e4445 100644 (file)
 #ifndef _EXYNOS_DRM_FB_H_
 #define _EXYNOS_DRM_FB_H
 
+#include "exynos_drm_gem.h"
+
 struct drm_framebuffer *
 exynos_drm_framebuffer_init(struct drm_device *dev,
                            struct drm_mode_fb_cmd2 *mode_cmd,
-                           struct drm_gem_object *obj);
+                           struct exynos_drm_gem_obj **gem_obj,
+                           int count);
 
 /* get gem object of a drm framebuffer */
 struct exynos_drm_gem_obj *exynos_drm_fb_gem_obj(struct drm_framebuffer *fb,
@@ -25,11 +28,4 @@ struct exynos_drm_gem_obj *exynos_drm_fb_gem_obj(struct drm_framebuffer *fb,
 
 void exynos_drm_mode_config_init(struct drm_device *dev);
 
-/* set a buffer count to drm framebuffer. */
-void exynos_drm_fb_set_buf_cnt(struct drm_framebuffer *fb,
-                                               unsigned int cnt);
-
-/* get a buffer count to drm framebuffer. */
-unsigned int exynos_drm_fb_get_buf_cnt(struct drm_framebuffer *fb);
-
 #endif
index 624595a..a221f75 100644 (file)
@@ -21,7 +21,6 @@
 #include "exynos_drm_drv.h"
 #include "exynos_drm_fb.h"
 #include "exynos_drm_fbdev.h"
-#include "exynos_drm_gem.h"
 #include "exynos_drm_iommu.h"
 
 #define MAX_CONNECTOR          4
@@ -32,7 +31,7 @@
 
 struct exynos_drm_fbdev {
        struct drm_fb_helper            drm_fb_helper;
-       struct exynos_drm_gem_obj       *exynos_gem_obj;
+       struct exynos_drm_gem_obj       *obj;
 };
 
 static int exynos_drm_fb_mmap(struct fb_info *info,
@@ -40,7 +39,7 @@ static int exynos_drm_fb_mmap(struct fb_info *info,
 {
        struct drm_fb_helper *helper = info->par;
        struct exynos_drm_fbdev *exynos_fbd = to_exynos_fbdev(helper);
-       struct exynos_drm_gem_obj *obj = exynos_fbd->exynos_gem_obj;
+       struct exynos_drm_gem_obj *obj = exynos_fbd->obj;
        unsigned long vm_size;
        int ret;
 
@@ -75,37 +74,38 @@ static struct fb_ops exynos_drm_fb_ops = {
 };
 
 static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
-                                    struct drm_fb_helper_surface_size *sizes,
-                                    struct drm_framebuffer *fb)
+                                  struct drm_fb_helper_surface_size *sizes,
+                                  struct exynos_drm_gem_obj *obj)
 {
-       struct fb_info *fbi = helper->fbdev;
-       struct exynos_drm_gem_obj *obj;
+       struct fb_info *fbi;
+       struct drm_framebuffer *fb = helper->fb;
        unsigned int size = fb->width * fb->height * (fb->bits_per_pixel >> 3);
        unsigned int nr_pages;
        unsigned long offset;
 
+       fbi = drm_fb_helper_alloc_fbi(helper);
+       if (IS_ERR(fbi)) {
+               DRM_ERROR("failed to allocate fb info.\n");
+               return PTR_ERR(fbi);
+       }
+
+       fbi->par = helper;
+       fbi->flags = FBINFO_FLAG_DEFAULT;
+       fbi->fbops = &exynos_drm_fb_ops;
+
        drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
        drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height);
 
-       /* RGB formats use only one buffer */
-       obj = exynos_drm_fb_gem_obj(fb, 0);
-       if (!obj) {
-               DRM_DEBUG_KMS("gem object is null.\n");
-               return -EFAULT;
-       }
-
        nr_pages = obj->size >> PAGE_SHIFT;
 
        obj->kvaddr = (void __iomem *) vmap(obj->pages, nr_pages, VM_MAP,
                        pgprot_writecombine(PAGE_KERNEL));
        if (!obj->kvaddr) {
                DRM_ERROR("failed to map pages to kernel space.\n");
+               drm_fb_helper_release_fbi(helper);
                return -EIO;
        }
 
-       /* buffer count to framebuffer always is 1 at booting time. */
-       exynos_drm_fb_set_buf_cnt(fb, 1);
-
        offset = fbi->var.xoffset * (fb->bits_per_pixel >> 3);
        offset += fbi->var.yoffset * fb->pitches[0];
 
@@ -120,9 +120,8 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
                                    struct drm_fb_helper_surface_size *sizes)
 {
        struct exynos_drm_fbdev *exynos_fbdev = to_exynos_fbdev(helper);
-       struct exynos_drm_gem_obj *exynos_gem_obj;
+       struct exynos_drm_gem_obj *obj;
        struct drm_device *dev = helper->dev;
-       struct fb_info *fbi;
        struct drm_mode_fb_cmd2 mode_cmd = { 0 };
        struct platform_device *pdev = dev->platformdev;
        unsigned long size;
@@ -140,47 +139,34 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
 
        mutex_lock(&dev->struct_mutex);
 
-       fbi = drm_fb_helper_alloc_fbi(helper);
-       if (IS_ERR(fbi)) {
-               DRM_ERROR("failed to allocate fb info.\n");
-               ret = PTR_ERR(fbi);
-               goto out;
-       }
-
        size = mode_cmd.pitches[0] * mode_cmd.height;
 
-       exynos_gem_obj = exynos_drm_gem_create(dev, EXYNOS_BO_CONTIG, size);
+       obj = exynos_drm_gem_create(dev, EXYNOS_BO_CONTIG, size);
        /*
         * If physically contiguous memory allocation fails and if IOMMU is
         * supported then try to get buffer from non physically contiguous
         * memory area.
         */
-       if (IS_ERR(exynos_gem_obj) && is_drm_iommu_supported(dev)) {
+       if (IS_ERR(obj) && is_drm_iommu_supported(dev)) {
                dev_warn(&pdev->dev, "contiguous FB allocation failed, falling back to non-contiguous\n");
-               exynos_gem_obj = exynos_drm_gem_create(dev, EXYNOS_BO_NONCONTIG,
-                                                       size);
+               obj = exynos_drm_gem_create(dev, EXYNOS_BO_NONCONTIG, size);
        }
 
-       if (IS_ERR(exynos_gem_obj)) {
-               ret = PTR_ERR(exynos_gem_obj);
-               goto err_release_fbi;
+       if (IS_ERR(obj)) {
+               ret = PTR_ERR(obj);
+               goto out;
        }
 
-       exynos_fbdev->exynos_gem_obj = exynos_gem_obj;
+       exynos_fbdev->obj = obj;
 
-       helper->fb = exynos_drm_framebuffer_init(dev, &mode_cmd,
-                       &exynos_gem_obj->base);
+       helper->fb = exynos_drm_framebuffer_init(dev, &mode_cmd, &obj, 1);
        if (IS_ERR(helper->fb)) {
                DRM_ERROR("failed to create drm framebuffer.\n");
                ret = PTR_ERR(helper->fb);
                goto err_destroy_gem;
        }
 
-       fbi->par = helper;
-       fbi->flags = FBINFO_FLAG_DEFAULT;
-       fbi->fbops = &exynos_drm_fb_ops;
-
-       ret = exynos_drm_fbdev_update(helper, sizes, helper->fb);
+       ret = exynos_drm_fbdev_update(helper, sizes, obj);
        if (ret < 0)
                goto err_destroy_framebuffer;
 
@@ -190,9 +176,7 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
 err_destroy_framebuffer:
        drm_framebuffer_cleanup(helper->fb);
 err_destroy_gem:
-       exynos_drm_gem_destroy(exynos_gem_obj);
-err_release_fbi:
-       drm_fb_helper_release_fbi(helper);
+       exynos_drm_gem_destroy(obj);
 
 /*
  * if failed, all resources allocated above would be released by
@@ -285,11 +269,11 @@ static void exynos_drm_fbdev_destroy(struct drm_device *dev,
                                      struct drm_fb_helper *fb_helper)
 {
        struct exynos_drm_fbdev *exynos_fbd = to_exynos_fbdev(fb_helper);
-       struct exynos_drm_gem_obj *exynos_gem_obj = exynos_fbd->exynos_gem_obj;
+       struct exynos_drm_gem_obj *obj = exynos_fbd->obj;
        struct drm_framebuffer *fb;
 
-       if (exynos_gem_obj->kvaddr)
-               vunmap(exynos_gem_obj->kvaddr);
+       if (obj->kvaddr)
+               vunmap(obj->kvaddr);
 
        /* release drm framebuffer and real buffer */
        if (fb_helper->fb && fb_helper->fb->funcs) {
index ba00839..535b4ad 100644 (file)
 
 /* registers for base address */
 #define G2D_SRC_BASE_ADDR              0x0304
+#define G2D_SRC_STRIDE_REG             0x0308
 #define G2D_SRC_COLOR_MODE             0x030C
 #define G2D_SRC_LEFT_TOP               0x0310
 #define G2D_SRC_RIGHT_BOTTOM           0x0314
 #define G2D_SRC_PLANE2_BASE_ADDR       0x0318
 #define G2D_DST_BASE_ADDR              0x0404
+#define G2D_DST_STRIDE_REG             0x0408
 #define G2D_DST_COLOR_MODE             0x040C
 #define G2D_DST_LEFT_TOP               0x0410
 #define G2D_DST_RIGHT_BOTTOM           0x0414
@@ -148,6 +150,7 @@ struct g2d_cmdlist {
  * A structure of buffer description
  *
  * @format: color format
+ * @stride: buffer stride/pitch in bytes
  * @left_x: the x coordinates of left top corner
  * @top_y: the y coordinates of left top corner
  * @right_x: the x coordinates of right bottom corner
@@ -156,6 +159,7 @@ struct g2d_cmdlist {
  */
 struct g2d_buf_desc {
        unsigned int    format;
+       unsigned int    stride;
        unsigned int    left_x;
        unsigned int    top_y;
        unsigned int    right_x;
@@ -589,6 +593,7 @@ static enum g2d_reg_type g2d_get_reg_type(int reg_offset)
 
        switch (reg_offset) {
        case G2D_SRC_BASE_ADDR:
+       case G2D_SRC_STRIDE_REG:
        case G2D_SRC_COLOR_MODE:
        case G2D_SRC_LEFT_TOP:
        case G2D_SRC_RIGHT_BOTTOM:
@@ -598,6 +603,7 @@ static enum g2d_reg_type g2d_get_reg_type(int reg_offset)
                reg_type = REG_TYPE_SRC_PLANE2;
                break;
        case G2D_DST_BASE_ADDR:
+       case G2D_DST_STRIDE_REG:
        case G2D_DST_COLOR_MODE:
        case G2D_DST_LEFT_TOP:
        case G2D_DST_RIGHT_BOTTOM:
@@ -652,8 +658,8 @@ static bool g2d_check_buf_desc_is_valid(struct g2d_buf_desc *buf_desc,
                                                enum g2d_reg_type reg_type,
                                                unsigned long size)
 {
-       unsigned int width, height;
-       unsigned long area;
+       int width, height;
+       unsigned long bpp, last_pos;
 
        /*
         * check source and destination buffers only.
@@ -662,22 +668,37 @@ static bool g2d_check_buf_desc_is_valid(struct g2d_buf_desc *buf_desc,
        if (reg_type != REG_TYPE_SRC && reg_type != REG_TYPE_DST)
                return true;
 
-       width = buf_desc->right_x - buf_desc->left_x;
+       /* This check also makes sure that right_x > left_x. */
+       width = (int)buf_desc->right_x - (int)buf_desc->left_x;
        if (width < G2D_LEN_MIN || width > G2D_LEN_MAX) {
-               DRM_ERROR("width[%u] is out of range!\n", width);
+               DRM_ERROR("width[%d] is out of range!\n", width);
                return false;
        }
 
-       height = buf_desc->bottom_y - buf_desc->top_y;
+       /* This check also makes sure that bottom_y > top_y. */
+       height = (int)buf_desc->bottom_y - (int)buf_desc->top_y;
        if (height < G2D_LEN_MIN || height > G2D_LEN_MAX) {
-               DRM_ERROR("height[%u] is out of range!\n", height);
+               DRM_ERROR("height[%d] is out of range!\n", height);
                return false;
        }
 
-       area = (unsigned long)width * (unsigned long)height *
-                                       g2d_get_buf_bpp(buf_desc->format);
-       if (area > size) {
-               DRM_ERROR("area[%lu] is out of range[%lu]!\n", area, size);
+       bpp = g2d_get_buf_bpp(buf_desc->format);
+
+       /* Compute the position of the last byte that the engine accesses. */
+       last_pos = ((unsigned long)buf_desc->bottom_y - 1) *
+               (unsigned long)buf_desc->stride +
+               (unsigned long)buf_desc->right_x * bpp - 1;
+
+       /*
+        * Since right_x > left_x and bottom_y > top_y we already know
+        * that the first_pos < last_pos (first_pos being the position
+        * of the first byte the engine accesses), it just remains to
+        * check if last_pos is smaller then the buffer size.
+        */
+
+       if (last_pos >= size) {
+               DRM_ERROR("last engine access position [%lu] "
+                       "is out of range [%lu]!\n", last_pos, size);
                return false;
        }
 
@@ -973,8 +994,6 @@ static int g2d_check_reg_offset(struct device *dev,
                                goto err;
 
                        reg_type = g2d_get_reg_type(reg_offset);
-                       if (reg_type == REG_TYPE_NONE)
-                               goto err;
 
                        /* check userptr buffer type. */
                        if ((cmdlist->data[index] & ~0x7fffffff) >> 31) {
@@ -983,14 +1002,22 @@ static int g2d_check_reg_offset(struct device *dev,
                        } else
                                buf_info->types[reg_type] = BUF_TYPE_GEM;
                        break;
+               case G2D_SRC_STRIDE_REG:
+               case G2D_DST_STRIDE_REG:
+                       if (for_addr)
+                               goto err;
+
+                       reg_type = g2d_get_reg_type(reg_offset);
+
+                       buf_desc = &buf_info->descs[reg_type];
+                       buf_desc->stride = cmdlist->data[index + 1];
+                       break;
                case G2D_SRC_COLOR_MODE:
                case G2D_DST_COLOR_MODE:
                        if (for_addr)
                                goto err;
 
                        reg_type = g2d_get_reg_type(reg_offset);
-                       if (reg_type == REG_TYPE_NONE)
-                               goto err;
 
                        buf_desc = &buf_info->descs[reg_type];
                        value = cmdlist->data[index + 1];
@@ -1003,8 +1030,6 @@ static int g2d_check_reg_offset(struct device *dev,
                                goto err;
 
                        reg_type = g2d_get_reg_type(reg_offset);
-                       if (reg_type == REG_TYPE_NONE)
-                               goto err;
 
                        buf_desc = &buf_info->descs[reg_type];
                        value = cmdlist->data[index + 1];
@@ -1018,8 +1043,6 @@ static int g2d_check_reg_offset(struct device *dev,
                                goto err;
 
                        reg_type = g2d_get_reg_type(reg_offset);
-                       if (reg_type == REG_TYPE_NONE)
-                               goto err;
 
                        buf_desc = &buf_info->descs[reg_type];
                        value = cmdlist->data[index + 1];
index 865d6eb..7148224 100644 (file)
@@ -126,7 +126,7 @@ static int exynos_plane_atomic_check(struct drm_plane *plane,
        if (!state->fb)
                return 0;
 
-       nr = exynos_drm_fb_get_buf_cnt(state->fb);
+       nr = drm_format_num_planes(state->fb->pixel_format);
        for (i = 0; i < nr; i++) {
                struct exynos_drm_gem_obj *obj =
                                        exynos_drm_fb_gem_obj(state->fb, i);
index 33aabc7..e3ec904 100644 (file)
@@ -2562,6 +2562,8 @@ static const char *power_domain_str(enum intel_display_power_domain domain)
                return "PORT_DDI_D_2_LANES";
        case POWER_DOMAIN_PORT_DDI_D_4_LANES:
                return "PORT_DDI_D_4_LANES";
+       case POWER_DOMAIN_PORT_DDI_E_2_LANES:
+               return "PORT_DDI_E_2_LANES";
        case POWER_DOMAIN_PORT_DSI:
                return "PORT_DSI";
        case POWER_DOMAIN_PORT_CRT:
index 1d88745..8edcec8 100644 (file)
@@ -662,15 +662,18 @@ static int i915_drm_suspend_late(struct drm_device *drm_dev, bool hibernation)
 
        pci_disable_device(drm_dev->pdev);
        /*
-        * During hibernation on some GEN4 platforms the BIOS may try to access
+        * During hibernation on some platforms the BIOS may try to access
         * the device even though it's already in D3 and hang the machine. So
         * leave the device in D0 on those platforms and hope the BIOS will
-        * power down the device properly. Platforms where this was seen:
-        * Lenovo Thinkpad X301, X61s
+        * power down the device properly. The issue was seen on multiple old
+        * GENs with different BIOS vendors, so having an explicit blacklist
+        * is inpractical; apply the workaround on everything pre GEN6. The
+        * platforms where the issue was seen:
+        * Lenovo Thinkpad X301, X61s, X60, T60, X41
+        * Fujitsu FSC S7110
+        * Acer Aspire 1830T
         */
-       if (!(hibernation &&
-             drm_dev->pdev->subsystem_vendor == PCI_VENDOR_ID_LENOVO &&
-             INTEL_INFO(dev_priv)->gen == 4))
+       if (!(hibernation && INTEL_INFO(dev_priv)->gen < 6))
                pci_set_power_state(drm_dev->pdev, PCI_D3hot);
 
        return 0;
index 089459b..b06e030 100644 (file)
@@ -182,6 +182,7 @@ enum intel_display_power_domain {
        POWER_DOMAIN_PORT_DDI_C_4_LANES,
        POWER_DOMAIN_PORT_DDI_D_2_LANES,
        POWER_DOMAIN_PORT_DDI_D_4_LANES,
+       POWER_DOMAIN_PORT_DDI_E_2_LANES,
        POWER_DOMAIN_PORT_DSI,
        POWER_DOMAIN_PORT_CRT,
        POWER_DOMAIN_PORT_OTHER,
@@ -1416,6 +1417,10 @@ enum modeset_restore {
 #define DP_AUX_C 0x20
 #define DP_AUX_D 0x30
 
+#define DDC_PIN_B  0x05
+#define DDC_PIN_C  0x04
+#define DDC_PIN_D  0x06
+
 struct ddi_vbt_port_info {
        /*
         * This is an index in the HDMI/DVI DDI buffer translation table.
@@ -1430,6 +1435,7 @@ struct ddi_vbt_port_info {
        uint8_t supports_dp:1;
 
        uint8_t alternate_aux_channel;
+       uint8_t alternate_ddc_pin;
 
        uint8_t dp_boost_level;
        uint8_t hdmi_boost_level;
@@ -1922,6 +1928,8 @@ struct drm_i915_private {
                        struct skl_wm_values skl_hw;
                        struct vlv_wm_values vlv;
                };
+
+               uint8_t max_level;
        } wm;
 
        struct i915_runtime_pm pm;
@@ -3377,13 +3385,13 @@ int intel_freq_opcode(struct drm_i915_private *dev_priv, int val);
 #define I915_READ64(reg)       dev_priv->uncore.funcs.mmio_readq(dev_priv, (reg), true)
 
 #define I915_READ64_2x32(lower_reg, upper_reg) ({                      \
-       u32 upper, lower, tmp;                                          \
-       tmp = I915_READ(upper_reg);                                     \
+       u32 upper, lower, old_upper, loop = 0;                          \
+       upper = I915_READ(upper_reg);                                   \
        do {                                                            \
-               upper = tmp;                                            \
+               old_upper = upper;                                      \
                lower = I915_READ(lower_reg);                           \
-               tmp = I915_READ(upper_reg);                             \
-       } while (upper != tmp);                                         \
+               upper = I915_READ(upper_reg);                           \
+       } while (upper != old_upper && loop++ < 2);                     \
        (u64)upper << 32 | lower; })
 
 #define POSTING_READ(reg)      (void)I915_READ_NOTRACE(reg)
index 923a3c4..a953d49 100644 (file)
@@ -1032,6 +1032,7 @@ i915_gem_execbuffer_move_to_active(struct list_head *vmas,
                u32 old_read = obj->base.read_domains;
                u32 old_write = obj->base.write_domain;
 
+               obj->dirty = 1; /* be paranoid  */
                obj->base.write_domain = obj->base.pending_write_domain;
                if (obj->base.write_domain == 0)
                        obj->base.pending_read_domains |= obj->base.read_domains;
@@ -1039,7 +1040,6 @@ i915_gem_execbuffer_move_to_active(struct list_head *vmas,
 
                i915_vma_move_to_active(vma, req);
                if (obj->base.write_domain) {
-                       obj->dirty = 1;
                        i915_gem_request_assign(&obj->last_write_req, req);
 
                        intel_fb_obj_invalidate(obj, ORIGIN_CS);
index d94c92d..a2bceb7 100644 (file)
@@ -1558,7 +1558,7 @@ static void i9xx_hpd_irq_handler(struct drm_device *dev)
                u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915;
 
                intel_get_hpd_pins(&pin_mask, &long_mask, hotplug_trigger,
-                                  hotplug_trigger, hpd_status_g4x,
+                                  hotplug_trigger, hpd_status_i915,
                                   i9xx_port_hotplug_long_detect);
                intel_hpd_irq_handler(dev, pin_mask, long_mask);
        }
index be83b77..b3e437b 100644 (file)
@@ -905,23 +905,23 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
        uint8_t hdmi_level_shift;
        int i, j;
        bool is_dvi, is_hdmi, is_dp, is_edp, is_crt;
-       uint8_t aux_channel;
+       uint8_t aux_channel, ddc_pin;
        /* Each DDI port can have more than one value on the "DVO Port" field,
         * so look for all the possible values for each port and abort if more
         * than one is found. */
-       int dvo_ports[][2] = {
-               {DVO_PORT_HDMIA, DVO_PORT_DPA},
-               {DVO_PORT_HDMIB, DVO_PORT_DPB},
-               {DVO_PORT_HDMIC, DVO_PORT_DPC},
-               {DVO_PORT_HDMID, DVO_PORT_DPD},
-               {DVO_PORT_CRT, -1 /* Port E can only be DVO_PORT_CRT */ },
+       int dvo_ports[][3] = {
+               {DVO_PORT_HDMIA, DVO_PORT_DPA, -1},
+               {DVO_PORT_HDMIB, DVO_PORT_DPB, -1},
+               {DVO_PORT_HDMIC, DVO_PORT_DPC, -1},
+               {DVO_PORT_HDMID, DVO_PORT_DPD, -1},
+               {DVO_PORT_CRT, DVO_PORT_HDMIE, DVO_PORT_DPE},
        };
 
        /* Find the child device to use, abort if more than one found. */
        for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
                it = dev_priv->vbt.child_dev + i;
 
-               for (j = 0; j < 2; j++) {
+               for (j = 0; j < 3; j++) {
                        if (dvo_ports[port][j] == -1)
                                break;
 
@@ -939,6 +939,7 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
                return;
 
        aux_channel = child->raw[25];
+       ddc_pin = child->common.ddc_pin;
 
        is_dvi = child->common.device_type & DEVICE_TYPE_TMDS_DVI_SIGNALING;
        is_dp = child->common.device_type & DEVICE_TYPE_DISPLAYPORT_OUTPUT;
@@ -970,11 +971,27 @@ 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 (child->common.ddc_pin == 0x05 && port != PORT_B)
+               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");
-               if (child->common.ddc_pin == 0x04 && port != PORT_C)
+               else if (ddc_pin == DDC_PIN_C && port != PORT_C)
                        DRM_DEBUG_KMS("Unexpected DDC pin for port C\n");
-               if (child->common.ddc_pin == 0x06 && port != PORT_D)
+               else if (ddc_pin == DDC_PIN_D && port != PORT_D)
                        DRM_DEBUG_KMS("Unexpected DDC pin for port D\n");
        }
 
index 06d0dbd..46cd5c7 100644 (file)
@@ -758,11 +758,6 @@ int intel_parse_bios(struct drm_device *dev);
 #define                DVO_C           2
 #define                DVO_D           3
 
-/* define the PORT for DP output type */
-#define                PORT_IDPB       7
-#define                PORT_IDPC       8
-#define                PORT_IDPD       9
-
 /* Possible values for the "DVO Port" field for versions >= 155: */
 #define DVO_PORT_HDMIA 0
 #define DVO_PORT_HDMIB 1
@@ -775,6 +770,8 @@ int intel_parse_bios(struct drm_device *dev);
 #define DVO_PORT_DPC   8
 #define DVO_PORT_DPD   9
 #define DVO_PORT_DPA   10
+#define DVO_PORT_DPE   11
+#define DVO_PORT_HDMIE 12
 #define DVO_PORT_MIPIA 21
 #define DVO_PORT_MIPIB 22
 #define DVO_PORT_MIPIC 23
index ba1ae03..d0f1b8d 100644 (file)
@@ -350,7 +350,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
        }
        csr->mmio_count = dmc_header->mmio_count;
        for (i = 0; i < dmc_header->mmio_count; i++) {
-               if (dmc_header->mmioaddr[i] < CSR_MMIO_START_RANGE &&
+               if (dmc_header->mmioaddr[i] < CSR_MMIO_START_RANGE ||
                        dmc_header->mmioaddr[i] > CSR_MMIO_END_RANGE) {
                        DRM_ERROR(" Firmware has wrong mmio address 0x%x\n",
                                                dmc_header->mmioaddr[i]);
index 1900455..61575f6 100644 (file)
@@ -1554,17 +1554,14 @@ skl_ddi_pll_select(struct intel_crtc *intel_crtc,
                         DPLL_CFGCR2_PDIV(wrpll_params.pdiv) |
                         wrpll_params.central_freq;
        } else if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT) {
-               struct drm_encoder *encoder = &intel_encoder->base;
-               struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-
-               switch (intel_dp->link_bw) {
-               case DP_LINK_BW_1_62:
+               switch (crtc_state->port_clock / 2) {
+               case 81000:
                        ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, 0);
                        break;
-               case DP_LINK_BW_2_7:
+               case 135000:
                        ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, 0);
                        break;
-               case DP_LINK_BW_5_4:
+               case 270000:
                        ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, 0);
                        break;
                }
index 53f5476..8cc9264 100644 (file)
@@ -5150,7 +5150,6 @@ static enum intel_display_power_domain port_to_power_domain(enum port port)
 {
        switch (port) {
        case PORT_A:
-       case PORT_E:
                return POWER_DOMAIN_PORT_DDI_A_4_LANES;
        case PORT_B:
                return POWER_DOMAIN_PORT_DDI_B_4_LANES;
@@ -5158,6 +5157,8 @@ static enum intel_display_power_domain port_to_power_domain(enum port port)
                return POWER_DOMAIN_PORT_DDI_C_4_LANES;
        case PORT_D:
                return POWER_DOMAIN_PORT_DDI_D_4_LANES;
+       case PORT_E:
+               return POWER_DOMAIN_PORT_DDI_E_2_LANES;
        default:
                WARN_ON_ONCE(1);
                return POWER_DOMAIN_PORT_OTHER;
@@ -5712,16 +5713,13 @@ void skl_init_cdclk(struct drm_i915_private *dev_priv)
        /* enable PG1 and Misc I/O */
        intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS);
 
-       /* DPLL0 already enabed !? */
-       if (I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE) {
-               DRM_DEBUG_DRIVER("DPLL0 already running\n");
-               return;
+       /* DPLL0 not enabled (happens on early BIOS versions) */
+       if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE)) {
+               /* enable DPLL0 */
+               required_vco = skl_cdclk_get_vco(dev_priv->skl_boot_cdclk);
+               skl_dpll0_enable(dev_priv, required_vco);
        }
 
-       /* enable DPLL0 */
-       required_vco = skl_cdclk_get_vco(dev_priv->skl_boot_cdclk);
-       skl_dpll0_enable(dev_priv, required_vco);
-
        /* set CDCLK to the frequency the BIOS chose */
        skl_set_cdclk(dev_priv, dev_priv->skl_boot_cdclk);
 
@@ -6307,7 +6305,7 @@ static void intel_connector_check_state(struct intel_connector *connector)
                      connector->base.name);
 
        if (connector->get_hw_state(connector)) {
-               struct drm_encoder *encoder = &connector->encoder->base;
+               struct intel_encoder *encoder = connector->encoder;
                struct drm_connector_state *conn_state = connector->base.state;
 
                I915_STATE_WARN(!crtc,
@@ -6319,13 +6317,13 @@ static void intel_connector_check_state(struct intel_connector *connector)
                I915_STATE_WARN(!crtc->state->active,
                      "connector is active, but attached crtc isn't\n");
 
-               if (!encoder)
+               if (!encoder || encoder->type == INTEL_OUTPUT_DP_MST)
                        return;
 
-               I915_STATE_WARN(conn_state->best_encoder != encoder,
+               I915_STATE_WARN(conn_state->best_encoder != &encoder->base,
                        "atomic encoder doesn't match attached encoder\n");
 
-               I915_STATE_WARN(conn_state->crtc != encoder->crtc,
+               I915_STATE_WARN(conn_state->crtc != encoder->base.crtc,
                        "attached encoder crtc differs from connector crtc\n");
        } else {
                I915_STATE_WARN(crtc && crtc->state->active,
@@ -13963,6 +13961,15 @@ static void intel_setup_outputs(struct drm_device *dev)
                        intel_ddi_init(dev, PORT_C);
                if (found & SFUSE_STRAP_DDID_DETECTED)
                        intel_ddi_init(dev, PORT_D);
+               /*
+                * On SKL we don't have a way to detect DDI-E so we rely on VBT.
+                */
+               if (IS_SKYLAKE(dev) &&
+                   (dev_priv->vbt.ddi_port_info[PORT_E].supports_dp ||
+                    dev_priv->vbt.ddi_port_info[PORT_E].supports_dvi ||
+                    dev_priv->vbt.ddi_port_info[PORT_E].supports_hdmi))
+                       intel_ddi_init(dev, PORT_E);
+
        } else if (HAS_PCH_SPLIT(dev)) {
                int found;
                dpd_is_edp = intel_dp_is_edp(dev, PORT_D);
@@ -14733,6 +14740,24 @@ void intel_modeset_init(struct drm_device *dev)
        if (INTEL_INFO(dev)->num_pipes == 0)
                return;
 
+       /*
+        * There may be no VBT; and if the BIOS enabled SSC we can
+        * just keep using it to avoid unnecessary flicker.  Whereas if the
+        * BIOS isn't using it, don't assume it will work even if the VBT
+        * indicates as much.
+        */
+       if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
+               bool bios_lvds_use_ssc = !!(I915_READ(PCH_DREF_CONTROL) &
+                                           DREF_SSC1_ENABLE);
+
+               if (dev_priv->vbt.lvds_use_ssc != bios_lvds_use_ssc) {
+                       DRM_DEBUG_KMS("SSC %sabled by BIOS, overriding VBT which says %sabled\n",
+                                    bios_lvds_use_ssc ? "en" : "dis",
+                                    dev_priv->vbt.lvds_use_ssc ? "en" : "dis");
+                       dev_priv->vbt.lvds_use_ssc = bios_lvds_use_ssc;
+               }
+       }
+
        intel_init_display(dev);
        intel_init_audio(dev);
 
@@ -15292,7 +15317,6 @@ err:
 
 void intel_modeset_gem_init(struct drm_device *dev)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_crtc *c;
        struct drm_i915_gem_object *obj;
        int ret;
@@ -15301,16 +15325,6 @@ void intel_modeset_gem_init(struct drm_device *dev)
        intel_init_gt_powersave(dev);
        mutex_unlock(&dev->struct_mutex);
 
-       /*
-        * There may be no VBT; and if the BIOS enabled SSC we can
-        * just keep using it to avoid unnecessary flicker.  Whereas if the
-        * BIOS isn't using it, don't assume it will work even if the VBT
-        * indicates as much.
-        */
-       if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
-               dev_priv->vbt.lvds_use_ssc = !!(I915_READ(PCH_DREF_CONTROL) &
-                                               DREF_SSC1_ENABLE);
-
        intel_modeset_init_hw(dev);
 
        intel_setup_overlay(dev);
index 3781cd3..0a2e33f 100644 (file)
 #define INTEL_DP_RESOLUTION_FAILSAFE   (3 << INTEL_DP_RESOLUTION_SHIFT_MASK)
 
 struct dp_link_dpll {
-       int link_bw;
+       int clock;
        struct dpll dpll;
 };
 
 static const struct dp_link_dpll gen4_dpll[] = {
-       { DP_LINK_BW_1_62,
+       { 162000,
                { .p1 = 2, .p2 = 10, .n = 2, .m1 = 23, .m2 = 8 } },
-       { DP_LINK_BW_2_7,
+       { 270000,
                { .p1 = 1, .p2 = 10, .n = 1, .m1 = 14, .m2 = 2 } }
 };
 
 static const struct dp_link_dpll pch_dpll[] = {
-       { DP_LINK_BW_1_62,
+       { 162000,
                { .p1 = 2, .p2 = 10, .n = 1, .m1 = 12, .m2 = 9 } },
-       { DP_LINK_BW_2_7,
+       { 270000,
                { .p1 = 1, .p2 = 10, .n = 2, .m1 = 14, .m2 = 8 } }
 };
 
 static const struct dp_link_dpll vlv_dpll[] = {
-       { DP_LINK_BW_1_62,
+       { 162000,
                { .p1 = 3, .p2 = 2, .n = 5, .m1 = 3, .m2 = 81 } },
-       { DP_LINK_BW_2_7,
+       { 270000,
                { .p1 = 2, .p2 = 2, .n = 1, .m1 = 2, .m2 = 27 } }
 };
 
@@ -83,11 +83,11 @@ static const struct dp_link_dpll chv_dpll[] = {
         * m2 is stored in fixed point format using formula below
         * (m2_int << 22) | m2_fraction
         */
-       { DP_LINK_BW_1_62,      /* m2_int = 32, m2_fraction = 1677722 */
+       { 162000,       /* m2_int = 32, m2_fraction = 1677722 */
                { .p1 = 4, .p2 = 2, .n = 1, .m1 = 2, .m2 = 0x819999a } },
-       { DP_LINK_BW_2_7,       /* m2_int = 27, m2_fraction = 0 */
+       { 270000,       /* m2_int = 27, m2_fraction = 0 */
                { .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 } },
-       { DP_LINK_BW_5_4,       /* m2_int = 27, m2_fraction = 0 */
+       { 540000,       /* m2_int = 27, m2_fraction = 0 */
                { .p1 = 2, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 } }
 };
 
@@ -1130,7 +1130,7 @@ intel_dp_connector_unregister(struct intel_connector *intel_connector)
 }
 
 static void
-skl_edp_set_pll_config(struct intel_crtc_state *pipe_config, int link_clock)
+skl_edp_set_pll_config(struct intel_crtc_state *pipe_config)
 {
        u32 ctrl1;
 
@@ -1142,7 +1142,7 @@ skl_edp_set_pll_config(struct intel_crtc_state *pipe_config, int link_clock)
        pipe_config->dpll_hw_state.cfgcr2 = 0;
 
        ctrl1 = DPLL_CTRL1_OVERRIDE(SKL_DPLL0);
-       switch (link_clock / 2) {
+       switch (pipe_config->port_clock / 2) {
        case 81000:
                ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810,
                                              SKL_DPLL0);
@@ -1175,20 +1175,20 @@ skl_edp_set_pll_config(struct intel_crtc_state *pipe_config, int link_clock)
        pipe_config->dpll_hw_state.ctrl1 = ctrl1;
 }
 
-static void
-hsw_dp_set_ddi_pll_sel(struct intel_crtc_state *pipe_config, int link_bw)
+void
+hsw_dp_set_ddi_pll_sel(struct intel_crtc_state *pipe_config)
 {
        memset(&pipe_config->dpll_hw_state, 0,
               sizeof(pipe_config->dpll_hw_state));
 
-       switch (link_bw) {
-       case DP_LINK_BW_1_62:
+       switch (pipe_config->port_clock / 2) {
+       case 81000:
                pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_810;
                break;
-       case DP_LINK_BW_2_7:
+       case 135000:
                pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_1350;
                break;
-       case DP_LINK_BW_5_4:
+       case 270000:
                pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_2700;
                break;
        }
@@ -1245,7 +1245,7 @@ intel_dp_source_rates(struct drm_device *dev, const int **source_rates)
 
 static void
 intel_dp_set_clock(struct intel_encoder *encoder,
-                  struct intel_crtc_state *pipe_config, int link_bw)
+                  struct intel_crtc_state *pipe_config)
 {
        struct drm_device *dev = encoder->base.dev;
        const struct dp_link_dpll *divisor = NULL;
@@ -1267,7 +1267,7 @@ intel_dp_set_clock(struct intel_encoder *encoder,
 
        if (divisor && count) {
                for (i = 0; i < count; i++) {
-                       if (link_bw == divisor[i].link_bw) {
+                       if (pipe_config->port_clock == divisor[i].clock) {
                                pipe_config->dpll = divisor[i].dpll;
                                pipe_config->clock_set = true;
                                break;
@@ -1544,13 +1544,13 @@ found:
        }
 
        if (IS_SKYLAKE(dev) && is_edp(intel_dp))
-               skl_edp_set_pll_config(pipe_config, common_rates[clock]);
+               skl_edp_set_pll_config(pipe_config);
        else if (IS_BROXTON(dev))
                /* handled in ddi */;
        else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
-               hsw_dp_set_ddi_pll_sel(pipe_config, intel_dp->link_bw);
+               hsw_dp_set_ddi_pll_sel(pipe_config);
        else
-               intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw);
+               intel_dp_set_clock(encoder, pipe_config);
 
        return true;
 }
@@ -4961,9 +4961,12 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
 
                intel_dp_probe_oui(intel_dp);
 
-               if (!intel_dp_probe_mst(intel_dp))
+               if (!intel_dp_probe_mst(intel_dp)) {
+                       drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+                       intel_dp_check_link_status(intel_dp);
+                       drm_modeset_unlock(&dev->mode_config.connection_mutex);
                        goto mst_fail;
-
+               }
        } else {
                if (intel_dp->is_mst) {
                        if (intel_dp_check_mst_status(intel_dp) == -EINVAL)
@@ -4971,10 +4974,6 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
                }
 
                if (!intel_dp->is_mst) {
-                       /*
-                        * we'll check the link status via the normal hot plug path later -
-                        * but for short hpds we should check it now
-                        */
                        drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
                        intel_dp_check_link_status(intel_dp);
                        drm_modeset_unlock(&dev->mode_config.connection_mutex);
@@ -5016,16 +5015,17 @@ intel_trans_dp_port_sel(struct drm_crtc *crtc)
        return -1;
 }
 
-/* check the VBT to see whether the eDP is on DP-D port */
+/* check the VBT to see whether the eDP is on another port */
 bool intel_dp_is_edp(struct drm_device *dev, enum port port)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        union child_device_config *p_child;
        int i;
        static const short port_mapping[] = {
-               [PORT_B] = PORT_IDPB,
-               [PORT_C] = PORT_IDPC,
-               [PORT_D] = PORT_IDPD,
+               [PORT_B] = DVO_PORT_DPB,
+               [PORT_C] = DVO_PORT_DPC,
+               [PORT_D] = DVO_PORT_DPD,
+               [PORT_E] = DVO_PORT_DPE,
        };
 
        if (port == PORT_A)
index 369f8b6..3e4be5a 100644 (file)
@@ -33,6 +33,7 @@
 static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
                                        struct intel_crtc_state *pipe_config)
 {
+       struct drm_device *dev = encoder->base.dev;
        struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
        struct intel_digital_port *intel_dig_port = intel_mst->primary;
        struct intel_dp *intel_dp = &intel_dig_port->dp;
@@ -97,6 +98,10 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
                               &pipe_config->dp_m_n);
 
        pipe_config->dp_m_n.tu = slots;
+
+       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+               hsw_dp_set_ddi_pll_sel(pipe_config);
+
        return true;
 
 }
@@ -168,6 +173,11 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder)
                return;
        }
 
+       /* MST encoders are bound to a crtc, not to a connector,
+        * force the mapping here for get_hw_state.
+        */
+       found->encoder = encoder;
+
        DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
        intel_mst->port = found->port;
 
@@ -395,7 +405,7 @@ static const struct drm_encoder_funcs intel_dp_mst_enc_funcs = {
 
 static bool intel_dp_mst_get_hw_state(struct intel_connector *connector)
 {
-       if (connector->encoder) {
+       if (connector->encoder && connector->base.state->crtc) {
                enum pipe pipe;
                if (!connector->encoder->get_hw_state(connector->encoder, &pipe))
                        return false;
index 93008fb..2b9e6f9 100644 (file)
@@ -1185,6 +1185,7 @@ void intel_edp_drrs_disable(struct intel_dp *intel_dp);
 void intel_edp_drrs_invalidate(struct drm_device *dev,
                unsigned frontbuffer_bits);
 void intel_edp_drrs_flush(struct drm_device *dev, unsigned frontbuffer_bits);
+void hsw_dp_set_ddi_pll_sel(struct intel_crtc_state *pipe_config);
 
 /* intel_dp_mst.c */
 int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id);
index 4a601cf..32a6c71 100644 (file)
@@ -1048,11 +1048,7 @@ void intel_dsi_init(struct drm_device *dev)
        intel_connector->unregister = intel_connector_unregister;
 
        /* Pipe A maps to MIPI DSI port A, pipe B maps to MIPI DSI port C */
-       if (dev_priv->vbt.dsi.config->dual_link) {
-               /* XXX: does dual link work on either pipe? */
-               intel_encoder->crtc_mask = (1 << PIPE_A);
-               intel_dsi->ports = ((1 << PORT_A) | (1 << PORT_C));
-       } else if (dev_priv->vbt.dsi.port == DVO_PORT_MIPIA) {
+       if (dev_priv->vbt.dsi.port == DVO_PORT_MIPIA) {
                intel_encoder->crtc_mask = (1 << PIPE_A);
                intel_dsi->ports = (1 << PORT_A);
        } else if (dev_priv->vbt.dsi.port == DVO_PORT_MIPIC) {
@@ -1060,6 +1056,9 @@ void intel_dsi_init(struct drm_device *dev)
                intel_dsi->ports = (1 << PORT_C);
        }
 
+       if (dev_priv->vbt.dsi.config->dual_link)
+               intel_dsi->ports = ((1 << PORT_A) | (1 << PORT_C));
+
        /* Create a DSI host (and a device) for each port. */
        for_each_dsi_port(port, intel_dsi->ports) {
                struct intel_dsi_host *host;
index 51cbea8..dcd336b 100644 (file)
@@ -1958,6 +1958,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
        struct drm_device *dev = intel_encoder->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        enum port port = intel_dig_port->port;
+       uint8_t alternate_ddc_pin;
 
        drm_connector_init(dev, connector, &intel_hdmi_connector_funcs,
                           DRM_MODE_CONNECTOR_HDMIA);
@@ -1991,6 +1992,26 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
                        intel_hdmi->ddc_bus = GMBUS_PIN_DPD;
                intel_encoder->hpd_pin = HPD_PORT_D;
                break;
+       case PORT_E:
+               /* On SKL PORT E doesn't have seperate GMBUS pin
+                *  We rely on VBT to set a proper alternate GMBUS pin. */
+               alternate_ddc_pin =
+                       dev_priv->vbt.ddi_port_info[PORT_E].alternate_ddc_pin;
+               switch (alternate_ddc_pin) {
+               case DDC_PIN_B:
+                       intel_hdmi->ddc_bus = GMBUS_PIN_DPB;
+                       break;
+               case DDC_PIN_C:
+                       intel_hdmi->ddc_bus = GMBUS_PIN_DPC;
+                       break;
+               case DDC_PIN_D:
+                       intel_hdmi->ddc_bus = GMBUS_PIN_DPD;
+                       break;
+               default:
+                       MISSING_CASE(alternate_ddc_pin);
+               }
+               intel_encoder->hpd_pin = HPD_PORT_E;
+               break;
        case PORT_A:
                intel_encoder->hpd_pin = HPD_PORT_A;
                /* Internal port only for eDP. */
index fff0c22..ddbb7ed 100644 (file)
@@ -955,8 +955,6 @@ enum vlv_wm_level {
        VLV_WM_LEVEL_PM2,
        VLV_WM_LEVEL_PM5,
        VLV_WM_LEVEL_DDR_DVFS,
-       CHV_WM_NUM_LEVELS,
-       VLV_WM_NUM_LEVELS = 1,
 };
 
 /* latency must be in 0.1us units. */
@@ -982,9 +980,13 @@ static void vlv_setup_wm_latency(struct drm_device *dev)
        /* all latencies in usec */
        dev_priv->wm.pri_latency[VLV_WM_LEVEL_PM2] = 3;
 
+       dev_priv->wm.max_level = VLV_WM_LEVEL_PM2;
+
        if (IS_CHERRYVIEW(dev_priv)) {
                dev_priv->wm.pri_latency[VLV_WM_LEVEL_PM5] = 12;
                dev_priv->wm.pri_latency[VLV_WM_LEVEL_DDR_DVFS] = 33;
+
+               dev_priv->wm.max_level = VLV_WM_LEVEL_DDR_DVFS;
        }
 }
 
@@ -1137,10 +1139,7 @@ static void vlv_compute_wm(struct intel_crtc *crtc)
        memset(wm_state, 0, sizeof(*wm_state));
 
        wm_state->cxsr = crtc->pipe != PIPE_C && crtc->wm.cxsr_allowed;
-       if (IS_CHERRYVIEW(dev))
-               wm_state->num_levels = CHV_WM_NUM_LEVELS;
-       else
-               wm_state->num_levels = VLV_WM_NUM_LEVELS;
+       wm_state->num_levels = to_i915(dev)->wm.max_level + 1;
 
        wm_state->num_active_planes = 0;
 
@@ -1220,7 +1219,7 @@ static void vlv_compute_wm(struct intel_crtc *crtc)
        }
 
        /* clear any (partially) filled invalid levels */
-       for (level = wm_state->num_levels; level < CHV_WM_NUM_LEVELS; level++) {
+       for (level = wm_state->num_levels; level < to_i915(dev)->wm.max_level + 1; level++) {
                memset(&wm_state->wm[level], 0, sizeof(wm_state->wm[level]));
                memset(&wm_state->sr[level], 0, sizeof(wm_state->sr[level]));
        }
@@ -1324,10 +1323,7 @@ static void vlv_merge_wm(struct drm_device *dev,
        struct intel_crtc *crtc;
        int num_active_crtcs = 0;
 
-       if (IS_CHERRYVIEW(dev))
-               wm->level = VLV_WM_LEVEL_DDR_DVFS;
-       else
-               wm->level = VLV_WM_LEVEL_PM2;
+       wm->level = to_i915(dev)->wm.max_level;
        wm->cxsr = true;
 
        for_each_intel_crtc(dev, crtc) {
@@ -4083,9 +4079,29 @@ void vlv_wm_get_hw_state(struct drm_device *dev)
                if (val & DSP_MAXFIFO_PM5_ENABLE)
                        wm->level = VLV_WM_LEVEL_PM5;
 
+               /*
+                * If DDR DVFS is disabled in the BIOS, Punit
+                * will never ack the request. So if that happens
+                * assume we don't have to enable/disable DDR DVFS
+                * dynamically. To test that just set the REQ_ACK
+                * bit to poke the Punit, but don't change the
+                * HIGH/LOW bits so that we don't actually change
+                * the current state.
+                */
                val = vlv_punit_read(dev_priv, PUNIT_REG_DDR_SETUP2);
-               if ((val & FORCE_DDR_HIGH_FREQ) == 0)
-                       wm->level = VLV_WM_LEVEL_DDR_DVFS;
+               val |= FORCE_DDR_FREQ_REQ_ACK;
+               vlv_punit_write(dev_priv, PUNIT_REG_DDR_SETUP2, val);
+
+               if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DDR_SETUP2) &
+                             FORCE_DDR_FREQ_REQ_ACK) == 0, 3)) {
+                       DRM_DEBUG_KMS("Punit not acking DDR DVFS request, "
+                                     "assuming DDR DVFS is disabled\n");
+                       dev_priv->wm.max_level = VLV_WM_LEVEL_PM5;
+               } else {
+                       val = vlv_punit_read(dev_priv, PUNIT_REG_DDR_SETUP2);
+                       if ((val & FORCE_DDR_HIGH_FREQ) == 0)
+                               wm->level = VLV_WM_LEVEL_DDR_DVFS;
+               }
 
                mutex_unlock(&dev_priv->rps.hw_lock);
        }
index 821644d..af7fdb3 100644 (file)
@@ -297,6 +297,7 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv,
        BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) |          \
        BIT(POWER_DOMAIN_PORT_DDI_D_2_LANES) |          \
        BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) |          \
+       BIT(POWER_DOMAIN_PORT_DDI_E_2_LANES) |          \
        BIT(POWER_DOMAIN_AUX_B) |                       \
        BIT(POWER_DOMAIN_AUX_C) |                       \
        BIT(POWER_DOMAIN_AUX_D) |                       \
@@ -316,6 +317,7 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv,
 #define SKL_DISPLAY_DDI_A_E_POWER_DOMAINS (            \
        BIT(POWER_DOMAIN_PORT_DDI_A_2_LANES) |          \
        BIT(POWER_DOMAIN_PORT_DDI_A_4_LANES) |          \
+       BIT(POWER_DOMAIN_PORT_DDI_E_2_LANES) |          \
        BIT(POWER_DOMAIN_INIT))
 #define SKL_DISPLAY_DDI_B_POWER_DOMAINS (              \
        BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) |          \
index a8dbb3e..7c6225c 100644 (file)
@@ -160,9 +160,35 @@ static int qxl_add_monitors_config_modes(struct drm_connector *connector,
        *pwidth = head->width;
        *pheight = head->height;
        drm_mode_probed_add(connector, mode);
+       /* remember the last custom size for mode validation */
+       qdev->monitors_config_width = mode->hdisplay;
+       qdev->monitors_config_height = mode->vdisplay;
        return 1;
 }
 
+static struct mode_size {
+       int w;
+       int h;
+} common_modes[] = {
+       { 640,  480},
+       { 720,  480},
+       { 800,  600},
+       { 848,  480},
+       {1024,  768},
+       {1152,  768},
+       {1280,  720},
+       {1280,  800},
+       {1280,  854},
+       {1280,  960},
+       {1280, 1024},
+       {1440,  900},
+       {1400, 1050},
+       {1680, 1050},
+       {1600, 1200},
+       {1920, 1080},
+       {1920, 1200}
+};
+
 static int qxl_add_common_modes(struct drm_connector *connector,
                                 unsigned pwidth,
                                 unsigned pheight)
@@ -170,29 +196,6 @@ static int qxl_add_common_modes(struct drm_connector *connector,
        struct drm_device *dev = connector->dev;
        struct drm_display_mode *mode = NULL;
        int i;
-       struct mode_size {
-               int w;
-               int h;
-       } common_modes[] = {
-               { 640,  480},
-               { 720,  480},
-               { 800,  600},
-               { 848,  480},
-               {1024,  768},
-               {1152,  768},
-               {1280,  720},
-               {1280,  800},
-               {1280,  854},
-               {1280,  960},
-               {1280, 1024},
-               {1440,  900},
-               {1400, 1050},
-               {1680, 1050},
-               {1600, 1200},
-               {1920, 1080},
-               {1920, 1200}
-       };
-
        for (i = 0; i < ARRAY_SIZE(common_modes); i++) {
                mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h,
                                    60, false, false, false);
@@ -823,11 +826,22 @@ static int qxl_conn_get_modes(struct drm_connector *connector)
 static int qxl_conn_mode_valid(struct drm_connector *connector,
                               struct drm_display_mode *mode)
 {
+       struct drm_device *ddev = connector->dev;
+       struct qxl_device *qdev = ddev->dev_private;
+       int i;
+
        /* TODO: is this called for user defined modes? (xrandr --add-mode)
         * TODO: check that the mode fits in the framebuffer */
-       DRM_DEBUG("%s: %dx%d status=%d\n", mode->name, mode->hdisplay,
-                 mode->vdisplay, mode->status);
-       return MODE_OK;
+
+       if(qdev->monitors_config_width == mode->hdisplay &&
+          qdev->monitors_config_height == mode->vdisplay)
+               return MODE_OK;
+
+       for (i = 0; i < ARRAY_SIZE(common_modes); i++) {
+               if (common_modes[i].w == mode->hdisplay && common_modes[i].h == mode->vdisplay)
+                       return MODE_OK;
+       }
+       return MODE_BAD;
 }
 
 static struct drm_encoder *qxl_best_encoder(struct drm_connector *connector)
index d854969..01a8694 100644 (file)
@@ -325,6 +325,8 @@ struct qxl_device {
        struct work_struct fb_work;
 
        struct drm_property *hotplug_mode_update_property;
+       int monitors_config_width;
+       int monitors_config_height;
 };
 
 /* forward declaration for QXL_INFO_IO */
index f81e0d7..9cd49c5 100644 (file)
@@ -171,8 +171,9 @@ radeon_dp_aux_transfer_atom(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
                return -E2BIG;
 
        tx_buf[0] = msg->address & 0xff;
-       tx_buf[1] = msg->address >> 8;
-       tx_buf[2] = msg->request << 4;
+       tx_buf[1] = (msg->address >> 8) & 0xff;
+       tx_buf[2] = (msg->request << 4) |
+               ((msg->address >> 16) & 0xf);
        tx_buf[3] = msg->size ? (msg->size - 1) : 0;
 
        switch (msg->request & ~DP_AUX_I2C_MOT) {
index fbc8d88..2c02e99 100644 (file)
@@ -522,13 +522,15 @@ static int radeon_audio_set_avi_packet(struct drm_encoder *encoder,
                return err;
        }
 
-       if (drm_rgb_quant_range_selectable(radeon_connector_edid(connector))) {
-               if (radeon_encoder->output_csc == RADEON_OUTPUT_CSC_TVRGB)
-                       frame.quantization_range = HDMI_QUANTIZATION_RANGE_LIMITED;
-               else
-                       frame.quantization_range = HDMI_QUANTIZATION_RANGE_FULL;
-       } else {
-               frame.quantization_range = HDMI_QUANTIZATION_RANGE_DEFAULT;
+       if (radeon_encoder->output_csc != RADEON_OUTPUT_CSC_BYPASS) {
+               if (drm_rgb_quant_range_selectable(radeon_connector_edid(connector))) {
+                       if (radeon_encoder->output_csc == RADEON_OUTPUT_CSC_TVRGB)
+                               frame.quantization_range = HDMI_QUANTIZATION_RANGE_LIMITED;
+                       else
+                               frame.quantization_range = HDMI_QUANTIZATION_RANGE_FULL;
+               } else {
+                       frame.quantization_range = HDMI_QUANTIZATION_RANGE_DEFAULT;
+               }
        }
 
        err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
index c097d3a..a9b01bc 100644 (file)
@@ -3387,6 +3387,14 @@ void radeon_combios_asic_init(struct drm_device *dev)
            rdev->pdev->subsystem_device == 0x30ae)
                return;
 
+       /* quirk for rs4xx HP Compaq dc5750 Small Form Factor to make it resume
+        * - it hangs on resume inside the dynclk 1 table.
+        */
+       if (rdev->family == CHIP_RS480 &&
+           rdev->pdev->subsystem_vendor == 0x103c &&
+           rdev->pdev->subsystem_device == 0x280a)
+               return;
+
        /* DYN CLK 1 */
        table = combios_get_table_offset(dev, COMBIOS_DYN_CLK_1_TABLE);
        if (table)
index fcbd60b..3b0c229 100644 (file)
@@ -116,8 +116,8 @@ radeon_dp_aux_transfer_native(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg
               AUX_SW_WR_BYTES(bytes));
 
        /* write the data header into the registers */
-       /* request, addres, msg size */
-       byte = (msg->request << 4);
+       /* request, address, msg size */
+       byte = (msg->request << 4) | ((msg->address >> 16) & 0xf);
        WREG32(AUX_SW_DATA + aux_offset[instance],
               AUX_SW_DATA_MASK(byte) | AUX_SW_AUTOINCREMENT_DISABLE);
 
index 34b78e7..5d8ae5e 100644 (file)
@@ -50,6 +50,8 @@
 
 #define VOP_WIN_SET(x, win, name, v) \
                REG_SET(x, win->base, win->phy->name, v, RELAXED)
+#define VOP_SCL_SET(x, win, name, v) \
+               REG_SET(x, win->base, win->phy->scl->name, v, RELAXED)
 #define VOP_CTRL_SET(x, name, v) \
                REG_SET(x, 0, (x)->data->ctrl->name, v, NORMAL)
 
@@ -164,7 +166,37 @@ struct vop_ctrl {
        struct vop_reg vpost_st_end;
 };
 
+struct vop_scl_regs {
+       struct vop_reg cbcr_vsd_mode;
+       struct vop_reg cbcr_vsu_mode;
+       struct vop_reg cbcr_hsd_mode;
+       struct vop_reg cbcr_ver_scl_mode;
+       struct vop_reg cbcr_hor_scl_mode;
+       struct vop_reg yrgb_vsd_mode;
+       struct vop_reg yrgb_vsu_mode;
+       struct vop_reg yrgb_hsd_mode;
+       struct vop_reg yrgb_ver_scl_mode;
+       struct vop_reg yrgb_hor_scl_mode;
+       struct vop_reg line_load_mode;
+       struct vop_reg cbcr_axi_gather_num;
+       struct vop_reg yrgb_axi_gather_num;
+       struct vop_reg vsd_cbcr_gt2;
+       struct vop_reg vsd_cbcr_gt4;
+       struct vop_reg vsd_yrgb_gt2;
+       struct vop_reg vsd_yrgb_gt4;
+       struct vop_reg bic_coe_sel;
+       struct vop_reg cbcr_axi_gather_en;
+       struct vop_reg yrgb_axi_gather_en;
+
+       struct vop_reg lb_mode;
+       struct vop_reg scale_yrgb_x;
+       struct vop_reg scale_yrgb_y;
+       struct vop_reg scale_cbcr_x;
+       struct vop_reg scale_cbcr_y;
+};
+
 struct vop_win_phy {
+       const struct vop_scl_regs *scl;
        const uint32_t *data_formats;
        uint32_t nformats;
 
@@ -222,7 +254,36 @@ static const uint32_t formats_234[] = {
        DRM_FORMAT_BGR565,
 };
 
+static const struct vop_scl_regs win_full_scl = {
+       .cbcr_vsd_mode = VOP_REG(WIN0_CTRL1, 0x1, 31),
+       .cbcr_vsu_mode = VOP_REG(WIN0_CTRL1, 0x1, 30),
+       .cbcr_hsd_mode = VOP_REG(WIN0_CTRL1, 0x3, 28),
+       .cbcr_ver_scl_mode = VOP_REG(WIN0_CTRL1, 0x3, 26),
+       .cbcr_hor_scl_mode = VOP_REG(WIN0_CTRL1, 0x3, 24),
+       .yrgb_vsd_mode = VOP_REG(WIN0_CTRL1, 0x1, 23),
+       .yrgb_vsu_mode = VOP_REG(WIN0_CTRL1, 0x1, 22),
+       .yrgb_hsd_mode = VOP_REG(WIN0_CTRL1, 0x3, 20),
+       .yrgb_ver_scl_mode = VOP_REG(WIN0_CTRL1, 0x3, 18),
+       .yrgb_hor_scl_mode = VOP_REG(WIN0_CTRL1, 0x3, 16),
+       .line_load_mode = VOP_REG(WIN0_CTRL1, 0x1, 15),
+       .cbcr_axi_gather_num = VOP_REG(WIN0_CTRL1, 0x7, 12),
+       .yrgb_axi_gather_num = VOP_REG(WIN0_CTRL1, 0xf, 8),
+       .vsd_cbcr_gt2 = VOP_REG(WIN0_CTRL1, 0x1, 7),
+       .vsd_cbcr_gt4 = VOP_REG(WIN0_CTRL1, 0x1, 6),
+       .vsd_yrgb_gt2 = VOP_REG(WIN0_CTRL1, 0x1, 5),
+       .vsd_yrgb_gt4 = VOP_REG(WIN0_CTRL1, 0x1, 4),
+       .bic_coe_sel = VOP_REG(WIN0_CTRL1, 0x3, 2),
+       .cbcr_axi_gather_en = VOP_REG(WIN0_CTRL1, 0x1, 1),
+       .yrgb_axi_gather_en = VOP_REG(WIN0_CTRL1, 0x1, 0),
+       .lb_mode = VOP_REG(WIN0_CTRL0, 0x7, 5),
+       .scale_yrgb_x = VOP_REG(WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
+       .scale_yrgb_y = VOP_REG(WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
+       .scale_cbcr_x = VOP_REG(WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
+       .scale_cbcr_y = VOP_REG(WIN0_SCL_FACTOR_CBR, 0xffff, 16),
+};
+
 static const struct vop_win_phy win01_data = {
+       .scl = &win_full_scl,
        .data_formats = formats_01,
        .nformats = ARRAY_SIZE(formats_01),
        .enable = VOP_REG(WIN0_CTRL0, 0x1, 0),
@@ -279,6 +340,12 @@ static const struct vop_reg_data vop_init_reg_table[] = {
        {DSP_CTRL0, 0x00000000},
        {WIN0_CTRL0, 0x00000080},
        {WIN1_CTRL0, 0x00000080},
+       /* TODO: Win2/3 support multiple area function, but we haven't found
+        * a suitable way to use it yet, so let's just use them as other windows
+        * with only area 0 enabled.
+        */
+       {WIN2_CTRL0, 0x00000010},
+       {WIN3_CTRL0, 0x00000010},
 };
 
 /*
@@ -393,6 +460,18 @@ static enum vop_data_format vop_convert_format(uint32_t format)
        }
 }
 
+static bool is_yuv_support(uint32_t format)
+{
+       switch (format) {
+       case DRM_FORMAT_NV12:
+       case DRM_FORMAT_NV16:
+       case DRM_FORMAT_NV24:
+               return true;
+       default:
+               return false;
+       }
+}
+
 static bool is_alpha_support(uint32_t format)
 {
        switch (format) {
@@ -404,6 +483,126 @@ static bool is_alpha_support(uint32_t format)
        }
 }
 
+static uint16_t scl_vop_cal_scale(enum scale_mode mode, uint32_t src,
+                                 uint32_t dst, bool is_horizontal,
+                                 int vsu_mode, int *vskiplines)
+{
+       uint16_t val = 1 << SCL_FT_DEFAULT_FIXPOINT_SHIFT;
+
+       if (is_horizontal) {
+               if (mode == SCALE_UP)
+                       val = GET_SCL_FT_BIC(src, dst);
+               else if (mode == SCALE_DOWN)
+                       val = GET_SCL_FT_BILI_DN(src, dst);
+       } else {
+               if (mode == SCALE_UP) {
+                       if (vsu_mode == SCALE_UP_BIL)
+                               val = GET_SCL_FT_BILI_UP(src, dst);
+                       else
+                               val = GET_SCL_FT_BIC(src, dst);
+               } else if (mode == SCALE_DOWN) {
+                       if (vskiplines) {
+                               *vskiplines = scl_get_vskiplines(src, dst);
+                               val = scl_get_bili_dn_vskip(src, dst,
+                                                           *vskiplines);
+                       } else {
+                               val = GET_SCL_FT_BILI_DN(src, dst);
+                       }
+               }
+       }
+
+       return val;
+}
+
+static void scl_vop_cal_scl_fac(struct vop *vop, const struct vop_win_data *win,
+                            uint32_t src_w, uint32_t src_h, uint32_t dst_w,
+                            uint32_t dst_h, uint32_t pixel_format)
+{
+       uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode;
+       uint16_t cbcr_hor_scl_mode = SCALE_NONE;
+       uint16_t cbcr_ver_scl_mode = SCALE_NONE;
+       int hsub = drm_format_horz_chroma_subsampling(pixel_format);
+       int vsub = drm_format_vert_chroma_subsampling(pixel_format);
+       bool is_yuv = is_yuv_support(pixel_format);
+       uint16_t cbcr_src_w = src_w / hsub;
+       uint16_t cbcr_src_h = src_h / vsub;
+       uint16_t vsu_mode;
+       uint16_t lb_mode;
+       uint32_t val;
+       int vskiplines;
+
+       if (dst_w > 3840) {
+               DRM_ERROR("Maximum destination width (3840) exceeded\n");
+               return;
+       }
+
+       yrgb_hor_scl_mode = scl_get_scl_mode(src_w, dst_w);
+       yrgb_ver_scl_mode = scl_get_scl_mode(src_h, dst_h);
+
+       if (is_yuv) {
+               cbcr_hor_scl_mode = scl_get_scl_mode(cbcr_src_w, dst_w);
+               cbcr_ver_scl_mode = scl_get_scl_mode(cbcr_src_h, dst_h);
+               if (cbcr_hor_scl_mode == SCALE_DOWN)
+                       lb_mode = scl_vop_cal_lb_mode(dst_w, true);
+               else
+                       lb_mode = scl_vop_cal_lb_mode(cbcr_src_w, true);
+       } else {
+               if (yrgb_hor_scl_mode == SCALE_DOWN)
+                       lb_mode = scl_vop_cal_lb_mode(dst_w, false);
+               else
+                       lb_mode = scl_vop_cal_lb_mode(src_w, false);
+       }
+
+       VOP_SCL_SET(vop, win, lb_mode, lb_mode);
+       if (lb_mode == LB_RGB_3840X2) {
+               if (yrgb_ver_scl_mode != SCALE_NONE) {
+                       DRM_ERROR("ERROR : not allow yrgb ver scale\n");
+                       return;
+               }
+               if (cbcr_ver_scl_mode != SCALE_NONE) {
+                       DRM_ERROR("ERROR : not allow cbcr ver scale\n");
+                       return;
+               }
+               vsu_mode = SCALE_UP_BIL;
+       } else if (lb_mode == LB_RGB_2560X4) {
+               vsu_mode = SCALE_UP_BIL;
+       } else {
+               vsu_mode = SCALE_UP_BIC;
+       }
+
+       val = scl_vop_cal_scale(yrgb_hor_scl_mode, src_w, dst_w,
+                               true, 0, NULL);
+       VOP_SCL_SET(vop, win, scale_yrgb_x, val);
+       val = scl_vop_cal_scale(yrgb_ver_scl_mode, src_h, dst_h,
+                               false, vsu_mode, &vskiplines);
+       VOP_SCL_SET(vop, win, scale_yrgb_y, val);
+
+       VOP_SCL_SET(vop, win, vsd_yrgb_gt4, vskiplines == 4);
+       VOP_SCL_SET(vop, win, vsd_yrgb_gt2, vskiplines == 2);
+
+       VOP_SCL_SET(vop, win, yrgb_hor_scl_mode, yrgb_hor_scl_mode);
+       VOP_SCL_SET(vop, win, yrgb_ver_scl_mode, yrgb_ver_scl_mode);
+       VOP_SCL_SET(vop, win, yrgb_hsd_mode, SCALE_DOWN_BIL);
+       VOP_SCL_SET(vop, win, yrgb_vsd_mode, SCALE_DOWN_BIL);
+       VOP_SCL_SET(vop, win, yrgb_vsu_mode, vsu_mode);
+       if (is_yuv) {
+               val = scl_vop_cal_scale(cbcr_hor_scl_mode, cbcr_src_w,
+                                       dst_w, true, 0, NULL);
+               VOP_SCL_SET(vop, win, scale_cbcr_x, val);
+               val = scl_vop_cal_scale(cbcr_ver_scl_mode, cbcr_src_h,
+                                       dst_h, false, vsu_mode, &vskiplines);
+               VOP_SCL_SET(vop, win, scale_cbcr_y, val);
+
+               VOP_SCL_SET(vop, win, vsd_cbcr_gt4, vskiplines == 4);
+               VOP_SCL_SET(vop, win, vsd_cbcr_gt2, vskiplines == 2);
+               VOP_SCL_SET(vop, win, cbcr_hor_scl_mode, cbcr_hor_scl_mode);
+               VOP_SCL_SET(vop, win, cbcr_ver_scl_mode, cbcr_ver_scl_mode);
+               VOP_SCL_SET(vop, win, cbcr_hsd_mode, SCALE_DOWN_BIL);
+               VOP_SCL_SET(vop, win, cbcr_vsd_mode, SCALE_DOWN_BIL);
+               VOP_SCL_SET(vop, win, cbcr_vsu_mode, vsu_mode);
+       }
+}
+
 static void vop_dsp_hold_valid_irq_enable(struct vop *vop)
 {
        unsigned long flags;
@@ -478,6 +677,7 @@ static void vop_enable(struct drm_crtc *crtc)
                goto err_disable_aclk;
        }
 
+       memcpy(vop->regs, vop->regsbak, vop->len);
        /*
         * At here, vop clock & iommu is enable, R/W vop regs would be safe.
         */
@@ -598,17 +798,22 @@ static int vop_update_plane_event(struct drm_plane *plane,
        struct vop *vop = to_vop(crtc);
        struct drm_gem_object *obj;
        struct rockchip_gem_object *rk_obj;
+       struct drm_gem_object *uv_obj;
+       struct rockchip_gem_object *rk_uv_obj;
        unsigned long offset;
        unsigned int actual_w;
        unsigned int actual_h;
        unsigned int dsp_stx;
        unsigned int dsp_sty;
        unsigned int y_vir_stride;
+       unsigned int uv_vir_stride = 0;
        dma_addr_t yrgb_mst;
+       dma_addr_t uv_mst = 0;
        enum vop_data_format format;
        uint32_t val;
        bool is_alpha;
        bool rb_swap;
+       bool is_yuv;
        bool visible;
        int ret;
        struct drm_rect dest = {
@@ -629,11 +834,15 @@ static int vop_update_plane_event(struct drm_plane *plane,
                .y2 = crtc->mode.vdisplay,
        };
        bool can_position = plane->type != DRM_PLANE_TYPE_PRIMARY;
+       int min_scale = win->phy->scl ? FRAC_16_16(1, 8) :
+                                       DRM_PLANE_HELPER_NO_SCALING;
+       int max_scale = win->phy->scl ? FRAC_16_16(8, 1) :
+                                       DRM_PLANE_HELPER_NO_SCALING;
 
        ret = drm_plane_helper_check_update(plane, crtc, fb,
                                            &src, &dest, &clip,
-                                           DRM_PLANE_HELPER_NO_SCALING,
-                                           DRM_PLANE_HELPER_NO_SCALING,
+                                           min_scale,
+                                           max_scale,
                                            can_position, false, &visible);
        if (ret)
                return ret;
@@ -643,6 +852,8 @@ static int vop_update_plane_event(struct drm_plane *plane,
 
        is_alpha = is_alpha_support(fb->pixel_format);
        rb_swap = has_rb_swapped(fb->pixel_format);
+       is_yuv = is_yuv_support(fb->pixel_format);
+
        format = vop_convert_format(fb->pixel_format);
        if (format < 0)
                return format;
@@ -655,19 +866,46 @@ static int vop_update_plane_event(struct drm_plane *plane,
 
        rk_obj = to_rockchip_obj(obj);
 
+       if (is_yuv) {
+               /*
+                * Src.x1 can be odd when do clip, but yuv plane start point
+                * need align with 2 pixel.
+                */
+               val = (src.x1 >> 16) % 2;
+               src.x1 += val << 16;
+               src.x2 += val << 16;
+       }
+
        actual_w = (src.x2 - src.x1) >> 16;
        actual_h = (src.y2 - src.y1) >> 16;
-       crtc_x = max(0, crtc_x);
-       crtc_y = max(0, crtc_y);
 
-       dsp_stx = crtc_x + crtc->mode.htotal - crtc->mode.hsync_start;
-       dsp_sty = crtc_y + crtc->mode.vtotal - crtc->mode.vsync_start;
+       dsp_stx = dest.x1 + crtc->mode.htotal - crtc->mode.hsync_start;
+       dsp_sty = dest.y1 + crtc->mode.vtotal - crtc->mode.vsync_start;
 
-       offset = (src.x1 >> 16) * (fb->bits_per_pixel >> 3);
+       offset = (src.x1 >> 16) * drm_format_plane_cpp(fb->pixel_format, 0);
        offset += (src.y1 >> 16) * fb->pitches[0];
-       yrgb_mst = rk_obj->dma_addr + offset;
 
-       y_vir_stride = fb->pitches[0] / (fb->bits_per_pixel >> 3);
+       yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0];
+       y_vir_stride = fb->pitches[0] >> 2;
+
+       if (is_yuv) {
+               int hsub = drm_format_horz_chroma_subsampling(fb->pixel_format);
+               int vsub = drm_format_vert_chroma_subsampling(fb->pixel_format);
+               int bpp = drm_format_plane_cpp(fb->pixel_format, 1);
+
+               uv_obj = rockchip_fb_get_gem_obj(fb, 1);
+               if (!uv_obj) {
+                       DRM_ERROR("fail to get uv object from framebuffer\n");
+                       return -EINVAL;
+               }
+               rk_uv_obj = to_rockchip_obj(uv_obj);
+               uv_vir_stride = fb->pitches[1] >> 2;
+
+               offset = (src.x1 >> 16) * bpp / hsub;
+               offset += (src.y1 >> 16) * fb->pitches[1] / vsub;
+
+               uv_mst = rk_uv_obj->dma_addr + offset + fb->offsets[1];
+       }
 
        /*
         * If this plane update changes the plane's framebuffer, (or more
@@ -704,9 +942,22 @@ static int vop_update_plane_event(struct drm_plane *plane,
        VOP_WIN_SET(vop, win, format, format);
        VOP_WIN_SET(vop, win, yrgb_vir, y_vir_stride);
        VOP_WIN_SET(vop, win, yrgb_mst, yrgb_mst);
+       if (is_yuv) {
+               VOP_WIN_SET(vop, win, uv_vir, uv_vir_stride);
+               VOP_WIN_SET(vop, win, uv_mst, uv_mst);
+       }
+
+       if (win->phy->scl)
+               scl_vop_cal_scl_fac(vop, win, actual_w, actual_h,
+                                   dest.x2 - dest.x1, dest.y2 - dest.y1,
+                                   fb->pixel_format);
+
        val = (actual_h - 1) << 16;
        val |= (actual_w - 1) & 0xffff;
        VOP_WIN_SET(vop, win, act_info, val);
+
+       val = (dest.y2 - dest.y1 - 1) << 16;
+       val |= (dest.x2 - dest.x1 - 1) & 0xffff;
        VOP_WIN_SET(vop, win, dsp_info, val);
        val = (dsp_sty - 1) << 16;
        val |= (dsp_stx - 1) & 0xffff;
index 63e9b3a..a2d4ddb 100644 (file)
@@ -198,4 +198,92 @@ enum factor_mode {
        ALPHA_SRC_GLOBAL,
 };
 
+enum scale_mode {
+       SCALE_NONE = 0x0,
+       SCALE_UP   = 0x1,
+       SCALE_DOWN = 0x2
+};
+
+enum lb_mode {
+       LB_YUV_3840X5 = 0x0,
+       LB_YUV_2560X8 = 0x1,
+       LB_RGB_3840X2 = 0x2,
+       LB_RGB_2560X4 = 0x3,
+       LB_RGB_1920X5 = 0x4,
+       LB_RGB_1280X8 = 0x5
+};
+
+enum sacle_up_mode {
+       SCALE_UP_BIL = 0x0,
+       SCALE_UP_BIC = 0x1
+};
+
+enum scale_down_mode {
+       SCALE_DOWN_BIL = 0x0,
+       SCALE_DOWN_AVG = 0x1
+};
+
+#define FRAC_16_16(mult, div)    (((mult) << 16) / (div))
+#define SCL_FT_DEFAULT_FIXPOINT_SHIFT  12
+#define SCL_MAX_VSKIPLINES             4
+#define MIN_SCL_FT_AFTER_VSKIP         1
+
+static inline uint16_t scl_cal_scale(int src, int dst, int shift)
+{
+       return ((src * 2 - 3) << (shift - 1)) / (dst - 1);
+}
+
+#define GET_SCL_FT_BILI_DN(src, dst)   scl_cal_scale(src, dst, 12)
+#define GET_SCL_FT_BILI_UP(src, dst)   scl_cal_scale(src, dst, 16)
+#define GET_SCL_FT_BIC(src, dst)       scl_cal_scale(src, dst, 16)
+
+static inline uint16_t scl_get_bili_dn_vskip(int src_h, int dst_h,
+                                            int vskiplines)
+{
+       int act_height;
+
+       act_height = (src_h + vskiplines - 1) / vskiplines;
+
+       return GET_SCL_FT_BILI_DN(act_height, dst_h);
+}
+
+static inline enum scale_mode scl_get_scl_mode(int src, int dst)
+{
+       if (src < dst)
+               return SCALE_UP;
+       else if (src > dst)
+               return SCALE_DOWN;
+
+       return SCALE_NONE;
+}
+
+static inline int scl_get_vskiplines(uint32_t srch, uint32_t dsth)
+{
+       uint32_t vskiplines;
+
+       for (vskiplines = SCL_MAX_VSKIPLINES; vskiplines > 1; vskiplines /= 2)
+               if (srch >= vskiplines * dsth * MIN_SCL_FT_AFTER_VSKIP)
+                       break;
+
+       return vskiplines;
+}
+
+static inline int scl_vop_cal_lb_mode(int width, bool is_yuv)
+{
+       int lb_mode;
+
+       if (width > 2560)
+               lb_mode = LB_RGB_3840X2;
+       else if (width > 1920)
+               lb_mode = LB_RGB_2560X4;
+       else if (!is_yuv)
+               lb_mode = LB_RGB_1920X5;
+       else if (width > 1280)
+               lb_mode = LB_YUV_3840X5;
+       else
+               lb_mode = LB_YUV_2560X8;
+
+       return lb_mode;
+}
+
 #endif /* _ROCKCHIP_DRM_VOP_H */
index 03854d6..e13b20b 100644 (file)
@@ -1052,10 +1052,15 @@ static struct vmw_master *vmw_master_check(struct drm_device *dev,
        }
 
        /*
-        * Check if we were previously master, but now dropped.
+        * Check if we were previously master, but now dropped. In that
+        * case, allow at least render node functionality.
         */
        if (vmw_fp->locked_master) {
                mutex_unlock(&dev->master_mutex);
+
+               if (flags & DRM_RENDER_ALLOW)
+                       return NULL;
+
                DRM_ERROR("Dropped master trying to access ioctl that "
                          "requires authentication.\n");
                return ERR_PTR(-EACCES);
index 5b8595b..3361769 100644 (file)
@@ -911,6 +911,12 @@ vmw_surface_handle_reference(struct vmw_private *dev_priv,
                                  "surface reference.\n");
                        return -EACCES;
                }
+               if (ACCESS_ONCE(vmw_fpriv(file_priv)->locked_master)) {
+                       DRM_ERROR("Locked master refused legacy "
+                                 "surface reference.\n");
+                       return -EACCES;
+               }
+
                handle = u_handle;
        }
 
index dbd16a2..fd5aa47 100644 (file)
@@ -358,7 +358,7 @@ typedef struct drm_i915_irq_wait {
 #define I915_PARAM_HAS_RESOURCE_STREAMER 36
 
 typedef struct drm_i915_getparam {
-       s32 param;
+       __s32 param;
        /*
         * WARNING: Using pointers instead of fixed-size u64 means we need to write
         * compat32 code. Don't repeat this mistake.