state->abm_level = cur->abm_level;
        state->vrr_supported = cur->vrr_supported;
        state->freesync_config = cur->freesync_config;
-       state->crc_enabled = cur->crc_enabled;
+       state->crc_src = cur->crc_src;
        state->cm_has_degamma = cur->cm_has_degamma;
        state->cm_is_degamma_srgb = cur->cm_is_degamma_srgb;
 
        struct drm_crtc *crtc;
        struct drm_crtc_state *old_crtc_state, *new_crtc_state;
        int i;
+       enum amdgpu_dm_pipe_crc_source source;
 
        for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state,
                                      new_crtc_state, i) {
 
 #ifdef CONFIG_DEBUG_FS
                /* The stream has changed so CRC capture needs to re-enabled. */
-               if (dm_new_crtc_state->crc_enabled) {
-                       dm_new_crtc_state->crc_enabled = false;
-                       amdgpu_dm_crtc_set_crc_source(crtc, "auto");
+               source = dm_new_crtc_state->crc_src;
+               if (amdgpu_dm_is_valid_crc_source(source)) {
+                       dm_new_crtc_state->crc_src = AMDGPU_DM_PIPE_CRC_SOURCE_NONE;
+                       if (source == AMDGPU_DM_PIPE_CRC_SOURCE_CRTC)
+                               amdgpu_dm_crtc_set_crc_source(crtc, "crtc");
+                       else if (source == AMDGPU_DM_PIPE_CRC_SOURCE_DPRX)
+                               amdgpu_dm_crtc_set_crc_source(crtc, "dprx");
                }
 #endif
        }
                         * Drop the extra vblank reference added by CRC
                         * capture if applicable.
                         */
-                       if (dm_new_crtc_state->crc_enabled)
+                       if (amdgpu_dm_is_valid_crc_source(dm_new_crtc_state->crc_src))
                                drm_crtc_vblank_put(crtc);
 
                        /*
                         * still a stream for the CRTC.
                         */
                        if (!dm_new_crtc_state->stream)
-                               dm_new_crtc_state->crc_enabled = false;
+                               dm_new_crtc_state->crc_src = AMDGPU_DM_PIPE_CRC_SOURCE_NONE;
 
                        manage_dm_interrupts(adev, acrtc, false);
                }
 
 
 #include "irq_types.h"
 #include "signal_types.h"
+#include "amdgpu_dm_crc.h"
 
 /* Forward declarations */
 struct amdgpu_device;
        bool interrupts_enabled;
 
        int crc_skip_count;
-       bool crc_enabled;
+       enum amdgpu_dm_pipe_crc_source crc_src;
 
        bool freesync_timing_changed;
        bool freesync_vrr_info_changed;
 void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
                                        struct edid *edid);
 
-/* amdgpu_dm_crc.c */
-#ifdef CONFIG_DEBUG_FS
-int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name);
-int amdgpu_dm_crtc_verify_crc_source(struct drm_crtc *crtc,
-                                    const char *src_name,
-                                    size_t *values_cnt);
-void amdgpu_dm_crtc_handle_crc_irq(struct drm_crtc *crtc);
-#else
-#define amdgpu_dm_crtc_set_crc_source NULL
-#define amdgpu_dm_crtc_verify_crc_source NULL
-#define amdgpu_dm_crtc_handle_crc_irq(x)
-#endif
-
 #define MAX_COLOR_LUT_ENTRIES 4096
 /* Legacy gamm LUT users such as X doesn't like large LUT sizes */
 #define MAX_COLOR_LEGACY_LUT_ENTRIES 256
 
 #include "amdgpu_dm.h"
 #include "dc.h"
 
-enum amdgpu_dm_pipe_crc_source {
-       AMDGPU_DM_PIPE_CRC_SOURCE_NONE = 0,
-       AMDGPU_DM_PIPE_CRC_SOURCE_AUTO,
-       AMDGPU_DM_PIPE_CRC_SOURCE_MAX,
-       AMDGPU_DM_PIPE_CRC_SOURCE_INVALID = -1,
-};
-
 static enum amdgpu_dm_pipe_crc_source dm_parse_crc_source(const char *source)
 {
        if (!source || !strcmp(source, "none"))
                return AMDGPU_DM_PIPE_CRC_SOURCE_NONE;
-       if (!strcmp(source, "auto"))
-               return AMDGPU_DM_PIPE_CRC_SOURCE_AUTO;
+       if (!strcmp(source, "auto") || !strcmp(source, "crtc"))
+               return AMDGPU_DM_PIPE_CRC_SOURCE_CRTC;
+       if (!strcmp(source, "dprx"))
+               return AMDGPU_DM_PIPE_CRC_SOURCE_DPRX;
 
        return AMDGPU_DM_PIPE_CRC_SOURCE_INVALID;
 }
        struct amdgpu_device *adev = crtc->dev->dev_private;
        struct dm_crtc_state *crtc_state = to_dm_crtc_state(crtc->state);
        struct dc_stream_state *stream_state = crtc_state->stream;
-       bool enable;
+       struct amdgpu_dm_connector *aconn;
+       struct drm_dp_aux *aux = NULL;
+       bool enable = false;
+       bool enabled = false;
 
        enum amdgpu_dm_pipe_crc_source source = dm_parse_crc_source(src_name);
 
                return -EINVAL;
        }
 
-       enable = (source == AMDGPU_DM_PIPE_CRC_SOURCE_AUTO);
+       enable = amdgpu_dm_is_valid_crc_source(source);
 
        mutex_lock(&adev->dm.dc_lock);
-       if (!dc_stream_configure_crc(stream_state->ctx->dc, stream_state,
-                                    enable, enable)) {
-               mutex_unlock(&adev->dm.dc_lock);
-               return -EINVAL;
+       /*
+        * USER REQ SRC | CURRENT SRC | BEHAVIOR
+        * -----------------------------
+        * None         | None        | Do nothing
+        * None         | CRTC        | Disable CRTC CRC
+        * None         | DPRX        | Disable DPRX CRC, need 'aux'
+        * CRTC         | XXXX        | Enable CRTC CRC, configure DC strm
+        * DPRX         | XXXX        | Enable DPRX CRC, need 'aux'
+        */
+       if (source == AMDGPU_DM_PIPE_CRC_SOURCE_DPRX ||
+               (source == AMDGPU_DM_PIPE_CRC_SOURCE_NONE &&
+                crtc_state->crc_src == AMDGPU_DM_PIPE_CRC_SOURCE_DPRX)) {
+               aconn = stream_state->link->priv;
+
+               if (!aconn) {
+                       DRM_DEBUG_DRIVER("No amd connector matching CRTC-%d\n", crtc->index);
+                       mutex_unlock(&adev->dm.dc_lock);
+                       return -EINVAL;
+               }
+
+               aux = &aconn->dm_dp_aux.aux;
+
+               if (!aux) {
+                       DRM_DEBUG_DRIVER("No dp aux for amd connector\n");
+                       mutex_unlock(&adev->dm.dc_lock);
+                       return -EINVAL;
+               }
+       } else if (source == AMDGPU_DM_PIPE_CRC_SOURCE_CRTC) {
+               if (!dc_stream_configure_crc(stream_state->ctx->dc, stream_state,
+                                            enable, enable)) {
+                       mutex_unlock(&adev->dm.dc_lock);
+                       return -EINVAL;
+               }
        }
 
        /* When enabling CRC, we should also disable dithering. */
         * Reading the CRC requires the vblank interrupt handler to be
         * enabled. Keep a reference until CRC capture stops.
         */
-       if (!crtc_state->crc_enabled && enable)
+       enabled = amdgpu_dm_is_valid_crc_source(crtc_state->crc_src);
+       if (!enabled && enable) {
                drm_crtc_vblank_get(crtc);
-       else if (crtc_state->crc_enabled && !enable)
+               if (source == AMDGPU_DM_PIPE_CRC_SOURCE_DPRX) {
+                       if (drm_dp_start_crc(aux, crtc)) {
+                               DRM_DEBUG_DRIVER("dp start crc failed\n");
+                               return -EINVAL;
+                       }
+               }
+       } else if (enabled && !enable) {
                drm_crtc_vblank_put(crtc);
+               if (crtc_state->crc_src == AMDGPU_DM_PIPE_CRC_SOURCE_DPRX) {
+                       if (drm_dp_stop_crc(aux)) {
+                               DRM_DEBUG_DRIVER("dp stop crc failed\n");
+                               return -EINVAL;
+                       }
+               }
+       }
 
-       crtc_state->crc_enabled = enable;
+       crtc_state->crc_src = source;
 
        /* Reset crc_skipped on dm state */
        crtc_state->crc_skip_count = 0;
        stream_state = crtc_state->stream;
 
        /* Early return if CRC capture is not enabled. */
-       if (!crtc_state->crc_enabled)
+       if (!amdgpu_dm_is_valid_crc_source(crtc_state->crc_src))
                return;
 
        /*
                return;
        }
 
-       if (!dc_stream_get_crc(stream_state->ctx->dc, stream_state,
-                              &crcs[0], &crcs[1], &crcs[2]))
-               return;
+       if (crtc_state->crc_src == AMDGPU_DM_PIPE_CRC_SOURCE_CRTC) {
+               if (!dc_stream_get_crc(stream_state->ctx->dc, stream_state,
+                                      &crcs[0], &crcs[1], &crcs[2]))
+                       return;
 
-       drm_crtc_add_crc_entry(crtc, true,
-                              drm_crtc_accurate_vblank_count(crtc), crcs);
+               drm_crtc_add_crc_entry(crtc, true,
+                                      drm_crtc_accurate_vblank_count(crtc), crcs);
+       }
 }
 
--- /dev/null
+/*
+ * Copyright 2019 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef AMD_DAL_DEV_AMDGPU_DM_AMDGPU_DM_CRC_H_
+#define AMD_DAL_DEV_AMDGPU_DM_AMDGPU_DM_CRC_H_
+
+enum amdgpu_dm_pipe_crc_source {
+       AMDGPU_DM_PIPE_CRC_SOURCE_NONE = 0,
+       AMDGPU_DM_PIPE_CRC_SOURCE_CRTC,
+       AMDGPU_DM_PIPE_CRC_SOURCE_DPRX,
+       AMDGPU_DM_PIPE_CRC_SOURCE_MAX,
+       AMDGPU_DM_PIPE_CRC_SOURCE_INVALID = -1,
+};
+
+static inline bool amdgpu_dm_is_valid_crc_source(enum amdgpu_dm_pipe_crc_source source)
+{
+       return (source == AMDGPU_DM_PIPE_CRC_SOURCE_CRTC) ||
+                  (source == AMDGPU_DM_PIPE_CRC_SOURCE_DPRX);
+}
+
+/* amdgpu_dm_crc.c */
+#ifdef CONFIG_DEBUG_FS
+int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name);
+int amdgpu_dm_crtc_verify_crc_source(struct drm_crtc *crtc,
+                                    const char *src_name,
+                                    size_t *values_cnt);
+void amdgpu_dm_crtc_handle_crc_irq(struct drm_crtc *crtc);
+#else
+#define amdgpu_dm_crtc_set_crc_source NULL
+#define amdgpu_dm_crtc_verify_crc_source NULL
+#define amdgpu_dm_crtc_handle_crc_irq(x)
+#endif
+
+#endif /* AMD_DAL_DEV_AMDGPU_DM_AMDGPU_DM_CRC_H_ */