]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 15 Apr 2016 21:59:28 +0000 (14:59 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 15 Apr 2016 21:59:28 +0000 (14:59 -0700)
Pull drm fixes from Dave Airlie:
 "This contains fixes for exynos, amdgpu, radeon, i915 and qxl.

  It also contains some fixes to the core drm edid parser.

  qxl:
   - fix for a cursor hotspot issue

  radeon:
   - some MST fixes that I've been running locally and make my monitor a
     bit happier

  exynos:
   - fix some regressions and build fixes

  amdgpu:
   - a couple of small fixes

  i915:
   - two DP MST fixes and a couple of other regression fixes

  Nothing too out of the ordinary or surprising at this point"

* 'drm-fixes' of git://people.freedesktop.org/~airlied/linux:
  drm/exynos: Use VIDEO_SAMSUNG_S5P_G2D=n as G2D Kconfig dependency
  drm/exynos: fix a warning message
  drm/exynos: mic: fix an error code
  drm/exynos: fimd: fix broken dp_clock control
  drm/exynos: build fbdev code conditionally
  drm/exynos: fix adjusted_mode pointer in exynos_plane_mode_set
  drm/exynos: fix error handling in exynos_drm_subdrv_open
  drm/amd/amdgpu: fix irq domain remove for tonga ih
  drm/i915: fix deadlock on lid open
  drm/radeon: use helper for mst connector dpms.
  drm/radeon/mst: port some MST setup code from DAL.
  drm/amdgpu: add invisible pin size statistic
  drm/edid: Fix DMT 1024x768@43Hz (interlaced) timings
  drm/i915: Exit cherryview_irq_handler() after one pass
  drm/i915: Call intel_dp_mst_resume() before resuming displays
  drm/i915: Fix race condition in intel_dp_destroy_mst_connector()
  drm/edid: Fix parsing of EDID 1.4 Established Timings III descriptor
  drm/edid: Fix EDID Established Timings I and II
  drm/qxl: fix cursor position with non-zero hotspot

22 files changed:
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
drivers/gpu/drm/amd/amdgpu/tonga_ih.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/exynos/Kconfig
drivers/gpu/drm/exynos/Makefile
drivers/gpu/drm/exynos/exynos_drm_core.c
drivers/gpu/drm/exynos/exynos_drm_fb.c
drivers/gpu/drm/exynos/exynos_drm_fbdev.c
drivers/gpu/drm/exynos/exynos_drm_fbdev.h
drivers/gpu/drm/exynos/exynos_drm_fimd.c
drivers/gpu/drm/exynos/exynos_drm_mic.c
drivers/gpu/drm/exynos/exynos_drm_plane.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/intel_dp_mst.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/qxl/qxl_display.c
drivers/gpu/drm/qxl/qxl_drv.h
drivers/gpu/drm/radeon/ni_reg.h
drivers/gpu/drm/radeon/radeon_dp_mst.c

index 62a778012fe06cc572964b463f873c987ca34755..b77489dec6e8ce86cc8c283191fee6a49069f781 100644 (file)
@@ -2034,6 +2034,7 @@ struct amdgpu_device {
 
        /* tracking pinned memory */
        u64 vram_pin_size;
+       u64 invisible_pin_size;
        u64 gart_pin_size;
 
        /* amdkfd interface */
index 598eb0cd5aab6a1b437ad04d0c58dce24adc8d9d..aef70db168329fc7c5db57a1c730fc48c35f1b6e 100644 (file)
@@ -384,7 +384,7 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
                vram_gtt.vram_size = adev->mc.real_vram_size;
                vram_gtt.vram_size -= adev->vram_pin_size;
                vram_gtt.vram_cpu_accessible_size = adev->mc.visible_vram_size;
-               vram_gtt.vram_cpu_accessible_size -= adev->vram_pin_size;
+               vram_gtt.vram_cpu_accessible_size -= (adev->vram_pin_size - adev->invisible_pin_size);
                vram_gtt.gtt_size  = adev->mc.gtt_size;
                vram_gtt.gtt_size -= adev->gart_pin_size;
                return copy_to_user(out, &vram_gtt,
index 5b6639faa731e83b1b14c07bf673aa30deff52c8..e557fc1f17c8becfb3ddae209942326d05d5a884 100644 (file)
@@ -424,9 +424,11 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
                bo->pin_count = 1;
                if (gpu_addr != NULL)
                        *gpu_addr = amdgpu_bo_gpu_offset(bo);
-               if (domain == AMDGPU_GEM_DOMAIN_VRAM)
+               if (domain == AMDGPU_GEM_DOMAIN_VRAM) {
                        bo->adev->vram_pin_size += amdgpu_bo_size(bo);
-               else
+                       if (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)
+                               bo->adev->invisible_pin_size += amdgpu_bo_size(bo);
+               } else
                        bo->adev->gart_pin_size += amdgpu_bo_size(bo);
        } else {
                dev_err(bo->adev->dev, "%p pin failed\n", bo);
@@ -456,9 +458,11 @@ int amdgpu_bo_unpin(struct amdgpu_bo *bo)
        }
        r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
        if (likely(r == 0)) {
-               if (bo->tbo.mem.mem_type == TTM_PL_VRAM)
+               if (bo->tbo.mem.mem_type == TTM_PL_VRAM) {
                        bo->adev->vram_pin_size -= amdgpu_bo_size(bo);
-               else
+                       if (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)
+                               bo->adev->invisible_pin_size -= amdgpu_bo_size(bo);
+               } else
                        bo->adev->gart_pin_size -= amdgpu_bo_size(bo);
        } else {
                dev_err(bo->adev->dev, "%p validate failed for unpin\n", bo);
index b6f7d7bff92989737511e8cc20452b6eecf89f05..0f14199cf716e157aa5638b7adebc041958225ac 100644 (file)
@@ -307,7 +307,7 @@ static int tonga_ih_sw_fini(void *handle)
 
        amdgpu_irq_fini(adev);
        amdgpu_ih_ring_fini(adev);
-       amdgpu_irq_add_domain(adev);
+       amdgpu_irq_remove_domain(adev);
 
        return 0;
 }
index 414d7f61aa05cbacb78542b1e3154ea700f6e3bd..558ef9fc39e6c2104b90725950fb7a562e9eefa4 100644 (file)
@@ -205,7 +205,7 @@ static const struct drm_display_mode drm_dmt_modes[] = {
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
        /* 0x0f - 1024x768@43Hz, interlace */
        { DRM_MODE("1024x768i", DRM_MODE_TYPE_DRIVER, 44900, 1024, 1032,
-                  1208, 1264, 0, 768, 768, 772, 817, 0,
+                  1208, 1264, 0, 768, 768, 776, 817, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
                   DRM_MODE_FLAG_INTERLACE) },
        /* 0x10 - 1024x768@60Hz */
@@ -522,12 +522,12 @@ static const struct drm_display_mode edid_est_modes[] = {
                   720, 840, 0, 480, 481, 484, 500, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@75Hz */
        { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 664,
-                  704,  832, 0, 480, 489, 491, 520, 0,
+                  704,  832, 0, 480, 489, 492, 520, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@72Hz */
        { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 30240, 640, 704,
                   768,  864, 0, 480, 483, 486, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@67Hz */
-       { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25200, 640, 656,
+       { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
                   752, 800, 0, 480, 490, 492, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@60Hz */
        { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 35500, 720, 738,
@@ -539,7 +539,7 @@ static const struct drm_display_mode edid_est_modes[] = {
        { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 135000, 1280, 1296,
                   1440, 1688, 0, 1024, 1025, 1028, 1066, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1280x1024@75Hz */
-       { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 78800, 1024, 1040,
+       { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 78750, 1024, 1040,
                   1136, 1312, 0,  768, 769, 772, 800, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1024x768@75Hz */
        { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 75000, 1024, 1048,
@@ -2241,7 +2241,7 @@ drm_est3_modes(struct drm_connector *connector, struct detailed_timing *timing)
 {
        int i, j, m, modes = 0;
        struct drm_display_mode *mode;
-       u8 *est = ((u8 *)timing) + 5;
+       u8 *est = ((u8 *)timing) + 6;
 
        for (i = 0; i < 6; i++) {
                for (j = 7; j >= 0; j--) {
index f17d3927959604301e9e53c7614fcb1e4982e80c..baddf33fb475863379bcffcd7befb4da085e37f2 100644 (file)
@@ -94,7 +94,7 @@ comment "Sub-drivers"
 
 config DRM_EXYNOS_G2D
        bool "G2D"
-       depends on !VIDEO_SAMSUNG_S5P_G2D
+       depends on VIDEO_SAMSUNG_S5P_G2D=n
        select FRAME_VECTOR
        help
          Choose this option if you want to use Exynos G2D for DRM.
index 968b31c522b2ddaa9cc8ed7fc4f675f8e39964d8..23d2f958739b187b7bd28ae4e0f7f7ec7522da6f 100644 (file)
@@ -2,10 +2,10 @@
 # Makefile for the drm device driver.  This driver provides support for the
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
-exynosdrm-y := exynos_drm_drv.o exynos_drm_crtc.o exynos_drm_fbdev.o \
-               exynos_drm_fb.o exynos_drm_gem.o exynos_drm_core.o \
-               exynos_drm_plane.o
+exynosdrm-y := exynos_drm_drv.o exynos_drm_crtc.o exynos_drm_fb.o \
+               exynos_drm_gem.o exynos_drm_core.o exynos_drm_plane.o
 
+exynosdrm-$(CONFIG_DRM_FBDEV_EMULATION) += exynos_drm_fbdev.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_IOMMU) += exynos_drm_iommu.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD)    += exynos_drm_fimd.o
 exynosdrm-$(CONFIG_DRM_EXYNOS5433_DECON)       += exynos5433_drm_decon.o
index 7f55ba6771c6b94e5f45bee6bdec078c27c74f5b..011211e4167d41dce17d56e8baee0b168b37e7b6 100644 (file)
@@ -101,7 +101,7 @@ int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file)
        return 0;
 
 err:
-       list_for_each_entry_reverse(subdrv, &subdrv->list, list) {
+       list_for_each_entry_continue_reverse(subdrv, &exynos_drm_subdrv_list, list) {
                if (subdrv->close)
                        subdrv->close(dev, subdrv->dev, file);
        }
index d614194644c814211ee069054a492fa1032c8fb0..81cc5537cf2577899bd5c1d011beb404584e08a6 100644 (file)
@@ -199,17 +199,6 @@ dma_addr_t exynos_drm_fb_dma_addr(struct drm_framebuffer *fb, int index)
        return exynos_fb->dma_addr[index];
 }
 
-static void exynos_drm_output_poll_changed(struct drm_device *dev)
-{
-       struct exynos_drm_private *private = dev->dev_private;
-       struct drm_fb_helper *fb_helper = private->fb_helper;
-
-       if (fb_helper)
-               drm_fb_helper_hotplug_event(fb_helper);
-       else
-               exynos_drm_fbdev_init(dev);
-}
-
 static const struct drm_mode_config_funcs exynos_drm_mode_config_funcs = {
        .fb_create = exynos_user_fb_create,
        .output_poll_changed = exynos_drm_output_poll_changed,
index 4ae860c44f1d8e052c1ce3a721e1c7348d14adf0..72d7c0b7c216531c7f3d7af2d1136ee5a3ecb01b 100644 (file)
@@ -317,3 +317,14 @@ void exynos_drm_fbdev_restore_mode(struct drm_device *dev)
 
        drm_fb_helper_restore_fbdev_mode_unlocked(private->fb_helper);
 }
+
+void exynos_drm_output_poll_changed(struct drm_device *dev)
+{
+       struct exynos_drm_private *private = dev->dev_private;
+       struct drm_fb_helper *fb_helper = private->fb_helper;
+
+       if (fb_helper)
+               drm_fb_helper_hotplug_event(fb_helper);
+       else
+               exynos_drm_fbdev_init(dev);
+}
index e16d7f0ae1920eb944364747b3f009e7976654f4..330eef87f7180b1b726ff41933874a6568b0474d 100644 (file)
 #ifndef _EXYNOS_DRM_FBDEV_H_
 #define _EXYNOS_DRM_FBDEV_H_
 
+#ifdef CONFIG_DRM_FBDEV_EMULATION
+
 int exynos_drm_fbdev_init(struct drm_device *dev);
-int exynos_drm_fbdev_reinit(struct drm_device *dev);
 void exynos_drm_fbdev_fini(struct drm_device *dev);
 void exynos_drm_fbdev_restore_mode(struct drm_device *dev);
+void exynos_drm_output_poll_changed(struct drm_device *dev);
+
+#else
+
+static inline int exynos_drm_fbdev_init(struct drm_device *dev)
+{
+       return 0;
+}
+
+static inline void exynos_drm_fbdev_fini(struct drm_device *dev)
+{
+}
+
+static inline void exynos_drm_fbdev_restore_mode(struct drm_device *dev)
+{
+}
+
+#define exynos_drm_output_poll_changed (NULL)
+
+#endif
 
 #endif
index 51d484ae9f498c17a07ba43a0891ef8ebe0dd3a4..018449f8d55750d0546ac0891e78662a67a65ab3 100644 (file)
@@ -888,7 +888,7 @@ static void fimd_dp_clock_enable(struct exynos_drm_crtc *crtc, bool enable)
         * clock. On these SoCs the bootloader may enable it but any
         * power domain off/on will reset it to disable state.
         */
-       if (ctx->driver_data != &exynos5_fimd_driver_data ||
+       if (ctx->driver_data != &exynos5_fimd_driver_data &&
            ctx->driver_data != &exynos5420_fimd_driver_data)
                return;
 
index 9869d70e9e54af32abb775dc0e17f0c1da83999b..a0def0be6d650de02fad25fc3cf3248d89b8fce0 100644 (file)
@@ -129,7 +129,7 @@ static void mic_set_path(struct exynos_mic *mic, bool enable)
        } else
                val &= ~(MIC0_RGB_MUX | MIC0_I80_MUX | MIC0_ON_MUX);
 
-       regmap_write(mic->sysreg, DSD_CFG_MUX, val);
+       ret = regmap_write(mic->sysreg, DSD_CFG_MUX, val);
        if (ret)
                DRM_ERROR("mic: Failed to read system register\n");
 }
@@ -457,6 +457,7 @@ static int exynos_mic_probe(struct platform_device *pdev)
                                                        "samsung,disp-syscon");
        if (IS_ERR(mic->sysreg)) {
                DRM_ERROR("mic: Failed to get system register.\n");
+               ret = PTR_ERR(mic->sysreg);
                goto err;
        }
 
index d86227236f5519f93099565622956f00530b7e24..50185ac347b24352202b7d38b314222438ca9b20 100644 (file)
 
 #include <drm/drmP.h>
 
-#include <drm/exynos_drm.h>
-#include <drm/drm_plane_helper.h>
+#include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/exynos_drm.h>
 #include "exynos_drm_drv.h"
 #include "exynos_drm_crtc.h"
 #include "exynos_drm_fb.h"
@@ -57,11 +58,12 @@ static int exynos_plane_get_size(int start, unsigned length, unsigned last)
 }
 
 static void exynos_plane_mode_set(struct exynos_drm_plane_state *exynos_state)
-
 {
        struct drm_plane_state *state = &exynos_state->base;
-       struct drm_crtc *crtc = exynos_state->base.crtc;
-       struct drm_display_mode *mode = &crtc->state->adjusted_mode;
+       struct drm_crtc *crtc = state->crtc;
+       struct drm_crtc_state *crtc_state =
+                       drm_atomic_get_existing_crtc_state(state->state, crtc);
+       struct drm_display_mode *mode = &crtc_state->adjusted_mode;
        int crtc_x, crtc_y;
        unsigned int crtc_w, crtc_h;
        unsigned int src_x, src_y;
index 20e82008b8b6c683b9189d25699dc33a054b874a..30798cbc6fc08938cc2adc62089148d545c118a6 100644 (file)
@@ -758,10 +758,10 @@ static int i915_drm_resume(struct drm_device *dev)
                dev_priv->display.hpd_irq_setup(dev);
        spin_unlock_irq(&dev_priv->irq_lock);
 
-       intel_display_resume(dev);
-
        intel_dp_mst_resume(dev);
 
+       intel_display_resume(dev);
+
        /*
         * ... but also need to make sure that hotplug processing
         * doesn't cause havoc. Like in the driver load code we don't
index d1a46ef5ab3f4b051b42599805266cd5fbd2bc7e..1c212205d0e7fd856e3298a10f6c039210bb570f 100644 (file)
@@ -1829,7 +1829,7 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg)
        /* IRQs are synced during runtime_suspend, we don't require a wakeref */
        disable_rpm_wakeref_asserts(dev_priv);
 
-       for (;;) {
+       do {
                master_ctl = I915_READ(GEN8_MASTER_IRQ) & ~GEN8_MASTER_IRQ_CONTROL;
                iir = I915_READ(VLV_IIR);
 
@@ -1857,7 +1857,7 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg)
 
                I915_WRITE(GEN8_MASTER_IRQ, DE_MASTER_IRQ_CONTROL);
                POSTING_READ(GEN8_MASTER_IRQ);
-       }
+       } while (0);
 
        enable_rpm_wakeref_asserts(dev_priv);
 
index a2bd698fe2f78f801813c99b097d7576e2f0c869..937e77228466eb22e66ac765d001078a418badfd 100644 (file)
@@ -506,6 +506,8 @@ static void intel_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
        struct intel_connector *intel_connector = to_intel_connector(connector);
        struct drm_device *dev = connector->dev;
 
+       intel_connector->unregister(intel_connector);
+
        /* need to nuke the connector */
        drm_modeset_lock_all(dev);
        if (connector->state->crtc) {
@@ -519,11 +521,7 @@ static void intel_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
 
                WARN(ret, "Disabling mst crtc failed with %i\n", ret);
        }
-       drm_modeset_unlock_all(dev);
 
-       intel_connector->unregister(intel_connector);
-
-       drm_modeset_lock_all(dev);
        intel_connector_remove_from_fbdev(intel_connector);
        drm_connector_cleanup(connector);
        drm_modeset_unlock_all(dev);
index 30a8403a8f4fbaa25e8f55ca3655596bc298768e..cd9fe609aefbc2487ce94ab01e0d495dd12d8167 100644 (file)
@@ -478,11 +478,8 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
         * and as part of the cleanup in the hw state restore we also redisable
         * the vga plane.
         */
-       if (!HAS_PCH_SPLIT(dev)) {
-               drm_modeset_lock_all(dev);
+       if (!HAS_PCH_SPLIT(dev))
                intel_display_resume(dev);
-               drm_modeset_unlock_all(dev);
-       }
 
        dev_priv->modeset_restore = MODESET_DONE;
 
index 43e5f503d1c5c4dd9662a7b20aec4db5c061817d..030409a3ee4e014ab512b5141d4b4e0ededbfe5d 100644 (file)
@@ -375,10 +375,15 @@ static int qxl_crtc_cursor_set2(struct drm_crtc *crtc,
 
        qxl_bo_kunmap(user_bo);
 
+       qcrtc->cur_x += qcrtc->hot_spot_x - hot_x;
+       qcrtc->cur_y += qcrtc->hot_spot_y - hot_y;
+       qcrtc->hot_spot_x = hot_x;
+       qcrtc->hot_spot_y = hot_y;
+
        cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release);
        cmd->type = QXL_CURSOR_SET;
-       cmd->u.set.position.x = qcrtc->cur_x;
-       cmd->u.set.position.y = qcrtc->cur_y;
+       cmd->u.set.position.x = qcrtc->cur_x + qcrtc->hot_spot_x;
+       cmd->u.set.position.y = qcrtc->cur_y + qcrtc->hot_spot_y;
 
        cmd->u.set.shape = qxl_bo_physical_address(qdev, cursor_bo, 0);
 
@@ -441,8 +446,8 @@ static int qxl_crtc_cursor_move(struct drm_crtc *crtc,
 
        cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release);
        cmd->type = QXL_CURSOR_MOVE;
-       cmd->u.position.x = qcrtc->cur_x;
-       cmd->u.position.y = qcrtc->cur_y;
+       cmd->u.position.x = qcrtc->cur_x + qcrtc->hot_spot_x;
+       cmd->u.position.y = qcrtc->cur_y + qcrtc->hot_spot_y;
        qxl_release_unmap(qdev, release, &cmd->release_info);
 
        qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
index 6e6b9b1519b8edd376fbed8341dbe99374dba8cf..3f3897eb458ce326f39a32d6b324c4361d70747d 100644 (file)
@@ -135,6 +135,8 @@ struct qxl_crtc {
        int index;
        int cur_x;
        int cur_y;
+       int hot_spot_x;
+       int hot_spot_y;
 };
 
 struct qxl_output {
index da310a70c0f01b880f8bac9bf7bb2abe6da5d7a1..827ccc87cbc340bf4132a792f6436005f11111d6 100644 (file)
 #define NI_DP_MSE_SAT2                                 0x7398
 
 #define NI_DP_MSE_SAT_UPDATE                           0x739c
+#       define NI_DP_MSE_SAT_UPDATE_MASK               0x3
+#       define NI_DP_MSE_16_MTP_KEEPOUT                0x100
 
 #define NI_DIG_BE_CNTL                                 0x7140
 #       define NI_DIG_FE_SOURCE_SELECT(x)              (((x) & 0x7f) << 8)
index 43cffb526b0c604adbab9722f9e63501f51412db..de504ea29c06d355758e79c6ca18345f42e55f88 100644 (file)
@@ -89,8 +89,16 @@ static int radeon_dp_mst_set_stream_attrib(struct radeon_encoder *primary,
        WREG32(NI_DP_MSE_SAT_UPDATE + primary->offset, 1);
 
        do {
+               unsigned value1, value2;
+               udelay(10);
                temp = RREG32(NI_DP_MSE_SAT_UPDATE + primary->offset);
-       } while ((temp & 0x1) && retries++ < 10000);
+
+               value1 = temp & NI_DP_MSE_SAT_UPDATE_MASK;
+               value2 = temp & NI_DP_MSE_16_MTP_KEEPOUT;
+
+               if (!value1 && !value2)
+                       break;
+       } while (retries++ < 50);
 
        if (retries == 10000)
                DRM_ERROR("timed out waitin for SAT update %d\n", primary->offset);
@@ -150,7 +158,7 @@ static int radeon_dp_mst_update_stream_attribs(struct radeon_connector *mst_conn
        return 0;
 }
 
-static int radeon_dp_mst_set_vcp_size(struct radeon_encoder *mst, uint32_t x, uint32_t y)
+static int radeon_dp_mst_set_vcp_size(struct radeon_encoder *mst, s64 avg_time_slots_per_mtp)
 {
        struct drm_device *dev = mst->base.dev;
        struct radeon_device *rdev = dev->dev_private;
@@ -158,6 +166,8 @@ static int radeon_dp_mst_set_vcp_size(struct radeon_encoder *mst, uint32_t x, ui
        uint32_t val, temp;
        uint32_t offset = radeon_atom_set_enc_offset(mst_enc->fe);
        int retries = 0;
+       uint32_t x = drm_fixp2int(avg_time_slots_per_mtp);
+       uint32_t y = drm_fixp2int_ceil((avg_time_slots_per_mtp - x) << 26);
 
        val = NI_DP_MSE_RATE_X(x) | NI_DP_MSE_RATE_Y(y);
 
@@ -165,6 +175,7 @@ static int radeon_dp_mst_set_vcp_size(struct radeon_encoder *mst, uint32_t x, ui
 
        do {
                temp = RREG32(NI_DP_MSE_RATE_UPDATE + offset);
+               udelay(10);
        } while ((temp & 0x1) && (retries++ < 10000));
 
        if (retries >= 10000)
@@ -246,14 +257,8 @@ radeon_dp_mst_connector_destroy(struct drm_connector *connector)
        kfree(radeon_connector);
 }
 
-static int radeon_connector_dpms(struct drm_connector *connector, int mode)
-{
-       DRM_DEBUG_KMS("\n");
-       return 0;
-}
-
 static const struct drm_connector_funcs radeon_dp_mst_connector_funcs = {
-       .dpms = radeon_connector_dpms,
+       .dpms = drm_helper_connector_dpms,
        .detect = radeon_dp_mst_detect,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .destroy = radeon_dp_mst_connector_destroy,
@@ -394,7 +399,7 @@ radeon_mst_encoder_dpms(struct drm_encoder *encoder, int mode)
        struct drm_crtc *crtc;
        struct radeon_crtc *radeon_crtc;
        int ret, slots;
-
+       s64 fixed_pbn, fixed_pbn_per_slot, avg_time_slots_per_mtp;
        if (!ASIC_IS_DCE5(rdev)) {
                DRM_ERROR("got mst dpms on non-DCE5\n");
                return;
@@ -456,7 +461,11 @@ radeon_mst_encoder_dpms(struct drm_encoder *encoder, int mode)
 
                mst_enc->enc_active = true;
                radeon_dp_mst_update_stream_attribs(radeon_connector->mst_port, primary);
-               radeon_dp_mst_set_vcp_size(radeon_encoder, slots, 0);
+
+               fixed_pbn = drm_int2fixp(mst_enc->pbn);
+               fixed_pbn_per_slot = drm_int2fixp(radeon_connector->mst_port->mst_mgr.pbn_div);
+               avg_time_slots_per_mtp = drm_fixp_div(fixed_pbn, fixed_pbn_per_slot);
+               radeon_dp_mst_set_vcp_size(radeon_encoder, avg_time_slots_per_mtp);
 
                atombios_dig_encoder_setup2(&primary->base, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0,
                                            mst_enc->fe);