Merge tag 'drm-intel-next-2015-03-27-merge' of git://anongit.freedesktop.org/drm-intel into drm-next

This backmerges 4.0-rc6 due to the recent fixes in rc5/6

- DP link rate refactoring from Ville
- byt/bsw rps tuning from Chris
- kerneldoc for the shrinker code
- more dynamic ppgtt pte work (Michel, Ben, ...)
- vlv dpll code refactoring to prep fro bxt (Imre)
- refactoring the sprite colorkey code (Ville)
- rotated ggtt view support from Tvrtko
- roll out struct drm_atomic_state to prep for atomic update (Ander)

* tag 'drm-intel-next-2015-03-27-merge' of git://anongit.freedesktop.org/drm-intel: (473 commits)
  Linux 4.0-rc6
  arm64: juno: Fix misleading name of UART reference clock
  drm/i915: Update DRIVER_DATE to 20150327
  drm/i915: Skip allocating shadow batch for 0-length batches
  drm/i915: Handle error to get connector state when staging config
  drm/i915: Compare GGTT view structs instead of types
  drm/i915: fix simple_return.cocci warnings
  drm/i915: Add module param to test the load detect code
  drm/i915: Remove usage of encoder->new_crtc from clock computations
  drm/i915: Don't look at staged config crtc when changing DRRS state
  drm/i915: Convert intel_pipe_will_have_type() to using atomic state
  drm/i915: Pass an atomic state to modeset_global_resources() functions
  drm/i915: Add dynamic page trace events
  drm/i915: Finish gen6/7 dynamic page table allocation
  drm/i915: Remove unnecessary gen6_ppgtt_unmap_pages
  drm/i915: Fix i915_dma_map_single positive error code
  drm/i915: Prevent out of range pt in gen6_for_each_pde
  drm/i915: fix definition of the DRM_IOCTL_I915_GET_SPRITE_COLORKEY ioctl
  drm/i915: Rip out GET_SPRITE_COLORKEY ioctl
  watchdog: imgpdc: Fix default heartbeat
  ...
diff --git a/MAINTAINERS b/MAINTAINERS
index 1de6afa..36cf100 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3397,7 +3397,6 @@
 S:	Supported
 F:	drivers/gpu/drm/rcar-du/
 F:	drivers/gpu/drm/shmobile/
-F:	include/linux/platform_data/rcar-du.h
 F:	include/linux/platform_data/shmob_drm.h
 
 DSBR100 USB FM RADIO DRIVER
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
index 5c50aa8..19a4fba 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
@@ -435,21 +435,22 @@
 {
 	struct kfd_ioctl_get_clock_counters_args *args = data;
 	struct kfd_dev *dev;
-	struct timespec time;
+	struct timespec64 time;
 
 	dev = kfd_device_by_id(args->gpu_id);
 	if (dev == NULL)
 		return -EINVAL;
 
 	/* Reading GPU clock counter from KGD */
-	args->gpu_clock_counter = kfd2kgd->get_gpu_clock_counter(dev->kgd);
+	args->gpu_clock_counter =
+		dev->kfd2kgd->get_gpu_clock_counter(dev->kgd);
 
 	/* No access to rdtsc. Using raw monotonic time */
-	getrawmonotonic(&time);
-	args->cpu_clock_counter = (uint64_t)timespec_to_ns(&time);
+	getrawmonotonic64(&time);
+	args->cpu_clock_counter = (uint64_t)timespec64_to_ns(&time);
 
-	get_monotonic_boottime(&time);
-	args->system_clock_counter = (uint64_t)timespec_to_ns(&time);
+	get_monotonic_boottime64(&time);
+	args->system_clock_counter = (uint64_t)timespec64_to_ns(&time);
 
 	/* Since the counter is in nano-seconds we use 1GHz frequency */
 	args->system_clock_freq = 1000000000;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
index 5bc32c2..ca7f2d3 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
@@ -94,7 +94,8 @@
 	return NULL;
 }
 
-struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd, struct pci_dev *pdev)
+struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd,
+	struct pci_dev *pdev, const struct kfd2kgd_calls *f2g)
 {
 	struct kfd_dev *kfd;
 
@@ -112,6 +113,11 @@
 	kfd->device_info = device_info;
 	kfd->pdev = pdev;
 	kfd->init_complete = false;
+	kfd->kfd2kgd = f2g;
+
+	mutex_init(&kfd->doorbell_mutex);
+	memset(&kfd->doorbell_available_index, 0,
+		sizeof(kfd->doorbell_available_index));
 
 	return kfd;
 }
@@ -200,8 +206,9 @@
 	/* add another 512KB for all other allocations on gart (HPD, fences) */
 	size += 512 * 1024;
 
-	if (kfd2kgd->init_gtt_mem_allocation(kfd->kgd, size, &kfd->gtt_mem,
-			&kfd->gtt_start_gpu_addr, &kfd->gtt_start_cpu_ptr)) {
+	if (kfd->kfd2kgd->init_gtt_mem_allocation(
+			kfd->kgd, size, &kfd->gtt_mem,
+			&kfd->gtt_start_gpu_addr, &kfd->gtt_start_cpu_ptr)){
 		dev_err(kfd_device,
 			"Could not allocate %d bytes for device (%x:%x)\n",
 			size, kfd->pdev->vendor, kfd->pdev->device);
@@ -270,7 +277,7 @@
 kfd_topology_add_device_error:
 	kfd_gtt_sa_fini(kfd);
 kfd_gtt_sa_init_error:
-	kfd2kgd->free_gtt_mem(kfd->kgd, kfd->gtt_mem);
+	kfd->kfd2kgd->free_gtt_mem(kfd->kgd, kfd->gtt_mem);
 	dev_err(kfd_device,
 		"device (%x:%x) NOT added due to errors\n",
 		kfd->pdev->vendor, kfd->pdev->device);
@@ -285,7 +292,7 @@
 		amd_iommu_free_device(kfd->pdev);
 		kfd_topology_remove_device(kfd);
 		kfd_gtt_sa_fini(kfd);
-		kfd2kgd->free_gtt_mem(kfd->kgd, kfd->gtt_mem);
+		kfd->kfd2kgd->free_gtt_mem(kfd->kgd, kfd->gtt_mem);
 	}
 
 	kfree(kfd);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
index d8135ad..69af73f 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
@@ -82,7 +82,8 @@
 void program_sh_mem_settings(struct device_queue_manager *dqm,
 					struct qcm_process_device *qpd)
 {
-	return kfd2kgd->program_sh_mem_settings(dqm->dev->kgd, qpd->vmid,
+	return dqm->dev->kfd2kgd->program_sh_mem_settings(
+						dqm->dev->kgd, qpd->vmid,
 						qpd->sh_mem_config,
 						qpd->sh_mem_ape1_base,
 						qpd->sh_mem_ape1_limit,
@@ -457,9 +458,12 @@
 {
 	uint32_t pasid_mapping;
 
-	pasid_mapping = (pasid == 0) ? 0 : (uint32_t)pasid |
-						ATC_VMID_PASID_MAPPING_VALID;
-	return kfd2kgd->set_pasid_vmid_mapping(dqm->dev->kgd, pasid_mapping,
+	pasid_mapping = (pasid == 0) ? 0 :
+		(uint32_t)pasid |
+		ATC_VMID_PASID_MAPPING_VALID;
+
+	return dqm->dev->kfd2kgd->set_pasid_vmid_mapping(
+						dqm->dev->kgd, pasid_mapping,
 						vmid);
 }
 
@@ -511,7 +515,7 @@
 		pipe_hpd_addr = dqm->pipelines_addr + i * CIK_HPD_EOP_BYTES;
 		pr_debug("kfd: pipeline address %llX\n", pipe_hpd_addr);
 		/* = log2(bytes/4)-1 */
-		kfd2kgd->init_pipeline(dqm->dev->kgd, inx,
+		dqm->dev->kfd2kgd->init_pipeline(dqm->dev->kgd, inx,
 				CIK_HPD_EOP_BYTES_LOG2 - 3, pipe_hpd_addr);
 	}
 
@@ -905,7 +909,7 @@
 	return retval;
 }
 
-static int fence_wait_timeout(unsigned int *fence_addr,
+static int amdkfd_fence_wait_timeout(unsigned int *fence_addr,
 				unsigned int fence_value,
 				unsigned long timeout)
 {
@@ -961,7 +965,7 @@
 	pm_send_query_status(&dqm->packets, dqm->fence_gpu_addr,
 				KFD_FENCE_COMPLETED);
 	/* should be timed out */
-	fence_wait_timeout(dqm->fence_addr, KFD_FENCE_COMPLETED,
+	amdkfd_fence_wait_timeout(dqm->fence_addr, KFD_FENCE_COMPLETED,
 				QUEUE_PREEMPT_DEFAULT_TIMEOUT_MS);
 	pm_release_ib(&dqm->packets);
 	dqm->active_runlist = false;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c b/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c
index 1a9b355..17e56dc 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c
@@ -32,9 +32,6 @@
  * and that's assures that any user process won't get access to the
  * kernel doorbells page
  */
-static DEFINE_MUTEX(doorbell_mutex);
-static unsigned long doorbell_available_index[
-	DIV_ROUND_UP(KFD_MAX_NUM_OF_QUEUES_PER_PROCESS, BITS_PER_LONG)] = { 0 };
 
 #define KERNEL_DOORBELL_PASID 1
 #define KFD_SIZE_OF_DOORBELL_IN_BYTES 4
@@ -170,12 +167,12 @@
 
 	BUG_ON(!kfd || !doorbell_off);
 
-	mutex_lock(&doorbell_mutex);
-	inx = find_first_zero_bit(doorbell_available_index,
+	mutex_lock(&kfd->doorbell_mutex);
+	inx = find_first_zero_bit(kfd->doorbell_available_index,
 					KFD_MAX_NUM_OF_QUEUES_PER_PROCESS);
 
-	__set_bit(inx, doorbell_available_index);
-	mutex_unlock(&doorbell_mutex);
+	__set_bit(inx, kfd->doorbell_available_index);
+	mutex_unlock(&kfd->doorbell_mutex);
 
 	if (inx >= KFD_MAX_NUM_OF_QUEUES_PER_PROCESS)
 		return NULL;
@@ -203,9 +200,9 @@
 
 	inx = (unsigned int)(db_addr - kfd->doorbell_kernel_ptr);
 
-	mutex_lock(&doorbell_mutex);
-	__clear_bit(inx, doorbell_available_index);
-	mutex_unlock(&doorbell_mutex);
+	mutex_lock(&kfd->doorbell_mutex);
+	__clear_bit(inx, kfd->doorbell_available_index);
+	mutex_unlock(&kfd->doorbell_mutex);
 }
 
 inline void write_kernel_doorbell(u32 __iomem *db, u32 value)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_module.c b/drivers/gpu/drm/amd/amdkfd/kfd_module.c
index 3f34ae1..4e0a68f 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_module.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_module.c
@@ -34,7 +34,6 @@
 #define KFD_DRIVER_MINOR	7
 #define KFD_DRIVER_PATCHLEVEL	1
 
-const struct kfd2kgd_calls *kfd2kgd;
 static const struct kgd2kfd_calls kgd2kfd = {
 	.exit		= kgd2kfd_exit,
 	.probe		= kgd2kfd_probe,
@@ -55,9 +54,7 @@
 MODULE_PARM_DESC(max_num_of_queues_per_device,
 	"Maximum number of supported queues per device (1 = Minimum, 4096 = default)");
 
-bool kgd2kfd_init(unsigned interface_version,
-		  const struct kfd2kgd_calls *f2g,
-		  const struct kgd2kfd_calls **g2f)
+bool kgd2kfd_init(unsigned interface_version, const struct kgd2kfd_calls **g2f)
 {
 	/*
 	 * Only one interface version is supported,
@@ -66,11 +63,6 @@
 	if (interface_version != KFD_INTERFACE_VERSION)
 		return false;
 
-	/* Protection against multiple amd kgd loads */
-	if (kfd2kgd)
-		return true;
-
-	kfd2kgd = f2g;
 	*g2f = &kgd2kfd;
 
 	return true;
@@ -85,8 +77,6 @@
 {
 	int err;
 
-	kfd2kgd = NULL;
-
 	/* Verify module parameters */
 	if ((sched_policy < KFD_SCHED_POLICY_HWS) ||
 		(sched_policy > KFD_SCHED_POLICY_NO_HWS)) {
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c
index a09e18a..4349794 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c
@@ -151,14 +151,15 @@
 static int load_mqd(struct mqd_manager *mm, void *mqd, uint32_t pipe_id,
 			uint32_t queue_id, uint32_t __user *wptr)
 {
-	return kfd2kgd->hqd_load(mm->dev->kgd, mqd, pipe_id, queue_id, wptr);
+	return mm->dev->kfd2kgd->hqd_load
+		(mm->dev->kgd, mqd, pipe_id, queue_id, wptr);
 }
 
 static int load_mqd_sdma(struct mqd_manager *mm, void *mqd,
 			uint32_t pipe_id, uint32_t queue_id,
 			uint32_t __user *wptr)
 {
-	return kfd2kgd->hqd_sdma_load(mm->dev->kgd, mqd);
+	return mm->dev->kfd2kgd->hqd_sdma_load(mm->dev->kgd, mqd);
 }
 
 static int update_mqd(struct mqd_manager *mm, void *mqd,
@@ -245,7 +246,7 @@
 			unsigned int timeout, uint32_t pipe_id,
 			uint32_t queue_id)
 {
-	return kfd2kgd->hqd_destroy(mm->dev->kgd, type, timeout,
+	return mm->dev->kfd2kgd->hqd_destroy(mm->dev->kgd, type, timeout,
 					pipe_id, queue_id);
 }
 
@@ -258,7 +259,7 @@
 				unsigned int timeout, uint32_t pipe_id,
 				uint32_t queue_id)
 {
-	return kfd2kgd->hqd_sdma_destroy(mm->dev->kgd, mqd, timeout);
+	return mm->dev->kfd2kgd->hqd_sdma_destroy(mm->dev->kgd, mqd, timeout);
 }
 
 static bool is_occupied(struct mqd_manager *mm, void *mqd,
@@ -266,7 +267,7 @@
 			uint32_t queue_id)
 {
 
-	return kfd2kgd->hqd_is_occupied(mm->dev->kgd, queue_address,
+	return mm->dev->kfd2kgd->hqd_is_occupied(mm->dev->kgd, queue_address,
 					pipe_id, queue_id);
 
 }
@@ -275,7 +276,7 @@
 			uint64_t queue_address,	uint32_t pipe_id,
 			uint32_t queue_id)
 {
-	return kfd2kgd->hqd_sdma_is_occupied(mm->dev->kgd, mqd);
+	return mm->dev->kfd2kgd->hqd_sdma_is_occupied(mm->dev->kgd, mqd);
 }
 
 /*
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
index 5a44f2f..f21fcce 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
@@ -148,6 +148,11 @@
 
 	struct kgd2kfd_shared_resources shared_resources;
 
+	const struct kfd2kgd_calls *kfd2kgd;
+	struct mutex doorbell_mutex;
+	unsigned long doorbell_available_index[DIV_ROUND_UP(
+		KFD_MAX_NUM_OF_QUEUES_PER_PROCESS, BITS_PER_LONG)];
+
 	void *gtt_mem;
 	uint64_t gtt_start_gpu_addr;
 	void *gtt_start_cpu_ptr;
@@ -164,13 +169,12 @@
 
 /* KGD2KFD callbacks */
 void kgd2kfd_exit(void);
-struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd, struct pci_dev *pdev);
+struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd,
+			struct pci_dev *pdev, const struct kfd2kgd_calls *f2g);
 bool kgd2kfd_device_init(struct kfd_dev *kfd,
-			 const struct kgd2kfd_shared_resources *gpu_resources);
+			const struct kgd2kfd_shared_resources *gpu_resources);
 void kgd2kfd_device_exit(struct kfd_dev *kfd);
 
-extern const struct kfd2kgd_calls *kfd2kgd;
-
 enum kfd_mempool {
 	KFD_MEMPOOL_SYSTEM_CACHEABLE = 1,
 	KFD_MEMPOOL_SYSTEM_WRITECOMBINE = 2,
@@ -378,8 +382,6 @@
 	/* The Device Queue Manager that owns this data */
 	struct device_queue_manager *dqm;
 	struct process_queue_manager *pqm;
-	/* Device Queue Manager lock */
-	struct mutex *lock;
 	/* Queues list */
 	struct list_head queues_list;
 	struct list_head priv_queue_list;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
index a369c14..945d622 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -162,10 +162,16 @@
 
 	p = my_work->p;
 
+	pr_debug("Releasing process (pasid %d) in workqueue\n",
+			p->pasid);
+
 	mutex_lock(&p->mutex);
 
 	list_for_each_entry_safe(pdd, temp, &p->per_device_data,
 							per_device_list) {
+		pr_debug("Releasing pdd (topology id %d) for process (pasid %d) in workqueue\n",
+				pdd->dev->id, p->pasid);
+
 		amd_iommu_unbind_pasid(pdd->dev->pdev, p->pasid);
 		list_del(&pdd->per_device_list);
 
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
index 4983993..661c660 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
@@ -726,13 +726,14 @@
 		}
 
 		sysfs_show_32bit_prop(buffer, "max_engine_clk_fcompute",
-				kfd2kgd->get_max_engine_clock_in_mhz(
+			dev->gpu->kfd2kgd->get_max_engine_clock_in_mhz(
 					dev->gpu->kgd));
 		sysfs_show_64bit_prop(buffer, "local_mem_size",
-				kfd2kgd->get_vmem_size(dev->gpu->kgd));
+			dev->gpu->kfd2kgd->get_vmem_size(
+					dev->gpu->kgd));
 
 		sysfs_show_32bit_prop(buffer, "fw_version",
-				kfd2kgd->get_fw_version(
+			dev->gpu->kfd2kgd->get_fw_version(
 						dev->gpu->kgd,
 						KGD_ENGINE_MEC1));
 	}
@@ -1099,8 +1100,9 @@
 	buf[2] = gpu->pdev->subsystem_device;
 	buf[3] = gpu->pdev->device;
 	buf[4] = gpu->pdev->bus->number;
-	buf[5] = (uint32_t)(kfd2kgd->get_vmem_size(gpu->kgd) & 0xffffffff);
-	buf[6] = (uint32_t)(kfd2kgd->get_vmem_size(gpu->kgd) >> 32);
+	buf[5] = (uint32_t)(gpu->kfd2kgd->get_vmem_size(gpu->kgd)
+			& 0xffffffff);
+	buf[6] = (uint32_t)(gpu->kfd2kgd->get_vmem_size(gpu->kgd) >> 32);
 
 	for (i = 0, hashout = 0; i < 7; i++)
 		hashout ^= hash_32(buf[i], KFD_GPU_ID_HASH_WIDTH);
diff --git a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h
index 239bc16..dabd944 100644
--- a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h
+++ b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h
@@ -77,37 +77,6 @@
 };
 
 /**
- * struct kgd2kfd_calls
- *
- * @exit: Notifies amdkfd that kgd module is unloaded
- *
- * @probe: Notifies amdkfd about a probe done on a device in the kgd driver.
- *
- * @device_init: Initialize the newly probed device (if it is a device that
- * amdkfd supports)
- *
- * @device_exit: Notifies amdkfd about a removal of a kgd device
- *
- * @suspend: Notifies amdkfd about a suspend action done to a kgd device
- *
- * @resume: Notifies amdkfd about a resume action done to a kgd device
- *
- * This structure contains function callback pointers so the kgd driver
- * will notify to the amdkfd about certain status changes.
- *
- */
-struct kgd2kfd_calls {
-	void (*exit)(void);
-	struct kfd_dev* (*probe)(struct kgd_dev *kgd, struct pci_dev *pdev);
-	bool (*device_init)(struct kfd_dev *kfd,
-			const struct kgd2kfd_shared_resources *gpu_resources);
-	void (*device_exit)(struct kfd_dev *kfd);
-	void (*interrupt)(struct kfd_dev *kfd, const void *ih_ring_entry);
-	void (*suspend)(struct kfd_dev *kfd);
-	int (*resume)(struct kfd_dev *kfd);
-};
-
-/**
  * struct kfd2kgd_calls
  *
  * @init_gtt_mem_allocation: Allocate a buffer on the gart aperture.
@@ -196,8 +165,39 @@
 				enum kgd_engine_type type);
 };
 
+/**
+ * struct kgd2kfd_calls
+ *
+ * @exit: Notifies amdkfd that kgd module is unloaded
+ *
+ * @probe: Notifies amdkfd about a probe done on a device in the kgd driver.
+ *
+ * @device_init: Initialize the newly probed device (if it is a device that
+ * amdkfd supports)
+ *
+ * @device_exit: Notifies amdkfd about a removal of a kgd device
+ *
+ * @suspend: Notifies amdkfd about a suspend action done to a kgd device
+ *
+ * @resume: Notifies amdkfd about a resume action done to a kgd device
+ *
+ * This structure contains function callback pointers so the kgd driver
+ * will notify to the amdkfd about certain status changes.
+ *
+ */
+struct kgd2kfd_calls {
+	void (*exit)(void);
+	struct kfd_dev* (*probe)(struct kgd_dev *kgd, struct pci_dev *pdev,
+		const struct kfd2kgd_calls *f2g);
+	bool (*device_init)(struct kfd_dev *kfd,
+			const struct kgd2kfd_shared_resources *gpu_resources);
+	void (*device_exit)(struct kfd_dev *kfd);
+	void (*interrupt)(struct kfd_dev *kfd, const void *ih_ring_entry);
+	void (*suspend)(struct kfd_dev *kfd);
+	int (*resume)(struct kfd_dev *kfd);
+};
+
 bool kgd2kfd_init(unsigned interface_version,
-		const struct kfd2kgd_calls *f2g,
 		const struct kgd2kfd_calls **g2f);
 
 #endif	/* KGD_KFD_INTERFACE_H_INCLUDED */
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
index d55c0c2..f69b925 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
@@ -207,6 +207,27 @@
 	crtc->enabled = true;
 }
 
+void atmel_hlcdc_crtc_suspend(struct drm_crtc *c)
+{
+	struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
+
+	if (crtc->enabled) {
+		atmel_hlcdc_crtc_disable(c);
+		/* save enable state for resume */
+		crtc->enabled = true;
+	}
+}
+
+void atmel_hlcdc_crtc_resume(struct drm_crtc *c)
+{
+	struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
+
+	if (crtc->enabled) {
+		crtc->enabled = false;
+		atmel_hlcdc_crtc_enable(c);
+	}
+}
+
 static int atmel_hlcdc_crtc_atomic_check(struct drm_crtc *c,
 					 struct drm_crtc_state *s)
 {
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
index c4bb1f9..60b0c13 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
@@ -569,14 +569,8 @@
 		return 0;
 
 	drm_modeset_lock_all(drm_dev);
-	list_for_each_entry(crtc, &drm_dev->mode_config.crtc_list, head) {
-		struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
-		if (crtc->enabled) {
-			crtc_funcs->disable(crtc);
-			/* save enable state for resume */
-			crtc->enabled = true;
-		}
-	}
+	list_for_each_entry(crtc, &drm_dev->mode_config.crtc_list, head)
+		atmel_hlcdc_crtc_suspend(crtc);
 	drm_modeset_unlock_all(drm_dev);
 	return 0;
 }
@@ -590,13 +584,8 @@
 		return 0;
 
 	drm_modeset_lock_all(drm_dev);
-	list_for_each_entry(crtc, &drm_dev->mode_config.crtc_list, head) {
-		struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
-		if (crtc->enabled) {
-			crtc->enabled = false;
-			crtc_funcs->enable(crtc);
-		}
-	}
+	list_for_each_entry(crtc, &drm_dev->mode_config.crtc_list, head)
+		atmel_hlcdc_crtc_resume(crtc);
 	drm_modeset_unlock_all(drm_dev);
 	return 0;
 }
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
index 1ea9c2c..cf6b375 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
@@ -155,6 +155,9 @@
 void atmel_hlcdc_crtc_cancel_page_flip(struct drm_crtc *crtc,
 				       struct drm_file *file);
 
+void atmel_hlcdc_crtc_suspend(struct drm_crtc *crtc);
+void atmel_hlcdc_crtc_resume(struct drm_crtc *crtc);
+
 int atmel_hlcdc_crtc_create(struct drm_device *dev);
 
 int atmel_hlcdc_create_outputs(struct drm_device *dev);
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index a745881..d9ed9a5 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -151,7 +151,7 @@
 static int
 update_connector_routing(struct drm_atomic_state *state, int conn_idx)
 {
-	struct drm_connector_helper_funcs *funcs;
+	const struct drm_connector_helper_funcs *funcs;
 	struct drm_encoder *new_encoder;
 	struct drm_crtc *encoder_crtc;
 	struct drm_connector *connector;
@@ -264,7 +264,7 @@
 	}
 
 	for (i = 0; i < state->num_connector; i++) {
-		struct drm_encoder_helper_funcs *funcs;
+		const struct drm_encoder_helper_funcs *funcs;
 		struct drm_encoder *encoder;
 
 		conn_state = state->connector_states[i];
@@ -317,7 +317,7 @@
 	}
 
 	for (i = 0; i < ncrtcs; i++) {
-		struct drm_crtc_helper_funcs *funcs;
+		const struct drm_crtc_helper_funcs *funcs;
 		struct drm_crtc *crtc;
 
 		crtc_state = state->crtc_states[i];
@@ -346,7 +346,7 @@
 }
 
 /**
- * drm_atomic_helper_check - validate state object for modeset changes
+ * drm_atomic_helper_check_modeset - validate state object for modeset changes
  * @dev: DRM device
  * @state: the driver state object
  *
@@ -461,7 +461,7 @@
 EXPORT_SYMBOL(drm_atomic_helper_check_modeset);
 
 /**
- * drm_atomic_helper_check - validate state object for modeset changes
+ * drm_atomic_helper_check_planes - validate state object for planes changes
  * @dev: DRM device
  * @state: the driver state object
  *
@@ -481,7 +481,7 @@
 	int i, ret = 0;
 
 	for (i = 0; i < nplanes; i++) {
-		struct drm_plane_helper_funcs *funcs;
+		const struct drm_plane_helper_funcs *funcs;
 		struct drm_plane *plane = state->planes[i];
 		struct drm_plane_state *plane_state = state->plane_states[i];
 
@@ -504,7 +504,7 @@
 	}
 
 	for (i = 0; i < ncrtcs; i++) {
-		struct drm_crtc_helper_funcs *funcs;
+		const struct drm_crtc_helper_funcs *funcs;
 		struct drm_crtc *crtc = state->crtcs[i];
 
 		if (!crtc)
@@ -571,9 +571,9 @@
 	int i;
 
 	for (i = 0; i < old_state->num_connector; i++) {
+		const struct drm_encoder_helper_funcs *funcs;
 		struct drm_connector_state *old_conn_state;
 		struct drm_connector *connector;
-		struct drm_encoder_helper_funcs *funcs;
 		struct drm_encoder *encoder;
 		struct drm_crtc_state *old_crtc_state;
 
@@ -605,7 +605,7 @@
 
 		/*
 		 * Each encoder has at most one connector (since we always steal
-		 * it away), so we won't call call disable hooks twice.
+		 * it away), so we won't call disable hooks twice.
 		 */
 		if (encoder->bridge)
 			encoder->bridge->funcs->disable(encoder->bridge);
@@ -623,7 +623,7 @@
 	}
 
 	for (i = 0; i < ncrtcs; i++) {
-		struct drm_crtc_helper_funcs *funcs;
+		const struct drm_crtc_helper_funcs *funcs;
 		struct drm_crtc *crtc;
 		struct drm_crtc_state *old_crtc_state;
 
@@ -713,7 +713,7 @@
 	int i;
 
 	for (i = 0; i < ncrtcs; i++) {
-		struct drm_crtc_helper_funcs *funcs;
+		const struct drm_crtc_helper_funcs *funcs;
 		struct drm_crtc *crtc;
 
 		crtc = old_state->crtcs[i];
@@ -732,9 +732,9 @@
 	}
 
 	for (i = 0; i < old_state->num_connector; i++) {
+		const struct drm_encoder_helper_funcs *funcs;
 		struct drm_connector *connector;
 		struct drm_crtc_state *new_crtc_state;
-		struct drm_encoder_helper_funcs *funcs;
 		struct drm_encoder *encoder;
 		struct drm_display_mode *mode, *adjusted_mode;
 
@@ -757,7 +757,7 @@
 
 		/*
 		 * Each encoder has at most one connector (since we always steal
-		 * it away), so we won't call call mode_set hooks twice.
+		 * it away), so we won't call mode_set hooks twice.
 		 */
 		if (funcs->mode_set)
 			funcs->mode_set(encoder, mode, adjusted_mode);
@@ -812,7 +812,7 @@
 	int i;
 
 	for (i = 0; i < ncrtcs; i++) {
-		struct drm_crtc_helper_funcs *funcs;
+		const struct drm_crtc_helper_funcs *funcs;
 		struct drm_crtc *crtc;
 
 		crtc = old_state->crtcs[i];
@@ -838,8 +838,8 @@
 	}
 
 	for (i = 0; i < old_state->num_connector; i++) {
+		const struct drm_encoder_helper_funcs *funcs;
 		struct drm_connector *connector;
-		struct drm_encoder_helper_funcs *funcs;
 		struct drm_encoder *encoder;
 
 		connector = old_state->connectors[i];
@@ -858,7 +858,7 @@
 
 		/*
 		 * Each encoder has at most one connector (since we always steal
-		 * it away), so we won't call call enable hooks twice.
+		 * it away), so we won't call enable hooks twice.
 		 */
 		if (encoder->bridge)
 			encoder->bridge->funcs->pre_enable(encoder->bridge);
@@ -1025,7 +1025,7 @@
 
 	/*
 	 * Everything below can be run asynchronously without the need to grab
-	 * any modeset locks at all under one conditions: It must be guaranteed
+	 * any modeset locks at all under one condition: It must be guaranteed
 	 * that the asynchronous work has either been cancelled (if the driver
 	 * supports it, which at least requires that the framebuffers get
 	 * cleaned up with drm_atomic_helper_cleanup_planes()) or completed
@@ -1114,7 +1114,7 @@
 	int ret, i;
 
 	for (i = 0; i < nplanes; i++) {
-		struct drm_plane_helper_funcs *funcs;
+		const struct drm_plane_helper_funcs *funcs;
 		struct drm_plane *plane = state->planes[i];
 		struct drm_plane_state *plane_state = state->plane_states[i];
 		struct drm_framebuffer *fb;
@@ -1137,7 +1137,7 @@
 
 fail:
 	for (i--; i >= 0; i--) {
-		struct drm_plane_helper_funcs *funcs;
+		const struct drm_plane_helper_funcs *funcs;
 		struct drm_plane *plane = state->planes[i];
 		struct drm_plane_state *plane_state = state->plane_states[i];
 		struct drm_framebuffer *fb;
@@ -1179,7 +1179,7 @@
 	int i;
 
 	for (i = 0; i < ncrtcs; i++) {
-		struct drm_crtc_helper_funcs *funcs;
+		const struct drm_crtc_helper_funcs *funcs;
 		struct drm_crtc *crtc = old_state->crtcs[i];
 
 		if (!crtc)
@@ -1194,7 +1194,7 @@
 	}
 
 	for (i = 0; i < nplanes; i++) {
-		struct drm_plane_helper_funcs *funcs;
+		const struct drm_plane_helper_funcs *funcs;
 		struct drm_plane *plane = old_state->planes[i];
 		struct drm_plane_state *old_plane_state;
 
@@ -1219,7 +1219,7 @@
 	}
 
 	for (i = 0; i < ncrtcs; i++) {
-		struct drm_crtc_helper_funcs *funcs;
+		const struct drm_crtc_helper_funcs *funcs;
 		struct drm_crtc *crtc = old_state->crtcs[i];
 
 		if (!crtc)
@@ -1254,7 +1254,7 @@
 	int i;
 
 	for (i = 0; i < nplanes; i++) {
-		struct drm_plane_helper_funcs *funcs;
+		const struct drm_plane_helper_funcs *funcs;
 		struct drm_plane *plane = old_state->planes[i];
 		struct drm_plane_state *plane_state = old_state->plane_states[i];
 		struct drm_framebuffer *old_fb;
@@ -2001,10 +2001,10 @@
 	WARN_ON(!drm_modeset_is_locked(&config->connection_mutex));
 
 	list_for_each_entry(tmp_connector, &config->connector_list, head) {
-		if (connector->state->crtc != crtc)
+		if (tmp_connector->state->crtc != crtc)
 			continue;
 
-		if (connector->dpms == DRM_MODE_DPMS_ON) {
+		if (tmp_connector->dpms == DRM_MODE_DPMS_ON) {
 			active = true;
 			break;
 		}
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index d1187e5..eaa5790 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -49,7 +49,7 @@
 }
 EXPORT_SYMBOL(drm_bridge_remove);
 
-extern int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge)
+int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge)
 {
 	if (!dev || !bridge)
 		return -EINVAL;
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 9f970c2..d576a4d 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -660,6 +660,9 @@
 	struct drm_mode_config *config = &dev->mode_config;
 	int ret;
 
+	WARN_ON(primary && primary->type != DRM_PLANE_TYPE_PRIMARY);
+	WARN_ON(cursor && cursor->type != DRM_PLANE_TYPE_CURSOR);
+
 	crtc->dev = dev;
 	crtc->funcs = funcs;
 	crtc->invert_dimensions = false;
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index f128387..d5368ea 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -427,11 +427,13 @@
  * retrying the transaction as appropriate.  It is assumed that the
  * aux->transfer function does not modify anything in the msg other than the
  * reply field.
+ *
+ * Returns bytes transferred on success, or a negative error code on failure.
  */
 static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
 {
 	unsigned int retry;
-	int err;
+	int ret;
 
 	/*
 	 * DP1.2 sections 2.7.7.1.5.6.1 and 2.7.7.1.6.6.1: A DP Source device
@@ -440,14 +442,14 @@
 	 */
 	for (retry = 0; retry < 7; retry++) {
 		mutex_lock(&aux->hw_mutex);
-		err = aux->transfer(aux, msg);
+		ret = aux->transfer(aux, msg);
 		mutex_unlock(&aux->hw_mutex);
-		if (err < 0) {
-			if (err == -EBUSY)
+		if (ret < 0) {
+			if (ret == -EBUSY)
 				continue;
 
-			DRM_DEBUG_KMS("transaction failed: %d\n", err);
-			return err;
+			DRM_DEBUG_KMS("transaction failed: %d\n", ret);
+			return ret;
 		}
 
 
@@ -488,9 +490,7 @@
 			 * Both native ACK and I2C ACK replies received. We
 			 * can assume the transfer was successful.
 			 */
-			if (err < msg->size)
-				return -EPROTO;
-			return 0;
+			return ret;
 
 		case DP_AUX_I2C_REPLY_NACK:
 			DRM_DEBUG_KMS("I2C nack\n");
@@ -513,14 +513,55 @@
 	return -EREMOTEIO;
 }
 
+/*
+ * Keep retrying drm_dp_i2c_do_msg until all data has been transferred.
+ *
+ * Returns an error code on failure, or a recommended transfer size on success.
+ */
+static int drm_dp_i2c_drain_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *orig_msg)
+{
+	int err, ret = orig_msg->size;
+	struct drm_dp_aux_msg msg = *orig_msg;
+
+	while (msg.size > 0) {
+		err = drm_dp_i2c_do_msg(aux, &msg);
+		if (err <= 0)
+			return err == 0 ? -EPROTO : err;
+
+		if (err < msg.size && err < ret) {
+			DRM_DEBUG_KMS("Partial I2C reply: requested %zu bytes got %d bytes\n",
+				      msg.size, err);
+			ret = err;
+		}
+
+		msg.size -= err;
+		msg.buffer += err;
+	}
+
+	return ret;
+}
+
+/*
+ * Bizlink designed DP->DVI-D Dual Link adapters require the I2C over AUX
+ * packets to be as large as possible. If not, the I2C transactions never
+ * succeed. Hence the default is maximum.
+ */
+static int dp_aux_i2c_transfer_size __read_mostly = DP_AUX_MAX_PAYLOAD_BYTES;
+module_param_unsafe(dp_aux_i2c_transfer_size, int, 0644);
+MODULE_PARM_DESC(dp_aux_i2c_transfer_size,
+		 "Number of bytes to transfer in a single I2C over DP AUX CH message, (1-16, default 16)");
+
 static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
 			   int num)
 {
 	struct drm_dp_aux *aux = adapter->algo_data;
 	unsigned int i, j;
+	unsigned transfer_size;
 	struct drm_dp_aux_msg msg;
 	int err = 0;
 
+	dp_aux_i2c_transfer_size = clamp(dp_aux_i2c_transfer_size, 1, DP_AUX_MAX_PAYLOAD_BYTES);
+
 	memset(&msg, 0, sizeof(msg));
 
 	for (i = 0; i < num; i++) {
@@ -538,20 +579,19 @@
 		err = drm_dp_i2c_do_msg(aux, &msg);
 		if (err < 0)
 			break;
-		/*
-		 * Many hardware implementations support FIFOs larger than a
-		 * single byte, but it has been empirically determined that
-		 * transferring data in larger chunks can actually lead to
-		 * decreased performance. Therefore each message is simply
-		 * transferred byte-by-byte.
+		/* We want each transaction to be as large as possible, but
+		 * we'll go to smaller sizes if the hardware gives us a
+		 * short reply.
 		 */
-		for (j = 0; j < msgs[i].len; j++) {
+		transfer_size = dp_aux_i2c_transfer_size;
+		for (j = 0; j < msgs[i].len; j += msg.size) {
 			msg.buffer = msgs[i].buf + j;
-			msg.size = 1;
+			msg.size = min(transfer_size, msgs[i].len - j);
 
-			err = drm_dp_i2c_do_msg(aux, &msg);
+			err = drm_dp_i2c_drain_msg(aux, &msg);
 			if (err < 0)
 				break;
+			transfer_size = err;
 		}
 		if (err < 0)
 			break;
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
index 379ab45..132581c 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -2324,6 +2324,19 @@
 }
 EXPORT_SYMBOL(drm_dp_mst_allocate_vcpi);
 
+int drm_dp_mst_get_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
+{
+	int slots = 0;
+	port = drm_dp_get_validated_port_ref(mgr, port);
+	if (!port)
+		return slots;
+
+	slots = port->vcpi.num_slots;
+	drm_dp_put_port(port);
+	return slots;
+}
+EXPORT_SYMBOL(drm_dp_mst_get_vcpi_slots);
+
 /**
  * drm_dp_mst_reset_vcpi_slots() - Reset number of slots to 0 for VCPI
  * @mgr: manager for this port
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index d512134..48f7359 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -70,7 +70,7 @@
 	vaf.fmt = format;
 	vaf.va = &args;
 
-	printk(KERN_ERR "[" DRM_NAME ":%pf] *ERROR* %pV",
+	printk(KERN_ERR "[" DRM_NAME ":%ps] *ERROR* %pV",
 	       __builtin_return_address(0), &vaf);
 
 	va_end(args);
diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c
index cc0ae04..5c1aca4 100644
--- a/drivers/gpu/drm/drm_fb_cma_helper.c
+++ b/drivers/gpu/drm/drm_fb_cma_helper.c
@@ -304,7 +304,7 @@
 	}
 
 	drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
-	drm_fb_helper_fill_var(fbi, helper, fb->width, fb->height);
+	drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height);
 
 	offset = fbi->var.xoffset * bytes_per_pixel;
 	offset += fbi->var.yoffset * fb->pitches[0];
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 1e6a0c7..1a20db7 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -1034,23 +1034,45 @@
 	crtc_count = 0;
 	for (i = 0; i < fb_helper->crtc_count; i++) {
 		struct drm_display_mode *desired_mode;
-		int x, y;
+		struct drm_mode_set *mode_set;
+		int x, y, j;
+		/* in case of tile group, are we the last tile vert or horiz?
+		 * If no tile group you are always the last one both vertically
+		 * and horizontally
+		 */
+		bool lastv = true, lasth = true;
+
 		desired_mode = fb_helper->crtc_info[i].desired_mode;
+		mode_set = &fb_helper->crtc_info[i].mode_set;
+
+		if (!desired_mode)
+			continue;
+
+		crtc_count++;
+
 		x = fb_helper->crtc_info[i].x;
 		y = fb_helper->crtc_info[i].y;
-		if (desired_mode) {
-			if (gamma_size == 0)
-				gamma_size = fb_helper->crtc_info[i].mode_set.crtc->gamma_size;
-			if (desired_mode->hdisplay + x < sizes.fb_width)
-				sizes.fb_width = desired_mode->hdisplay + x;
-			if (desired_mode->vdisplay + y < sizes.fb_height)
-				sizes.fb_height = desired_mode->vdisplay + y;
-			if (desired_mode->hdisplay + x > sizes.surface_width)
-				sizes.surface_width = desired_mode->hdisplay + x;
-			if (desired_mode->vdisplay + y > sizes.surface_height)
-				sizes.surface_height = desired_mode->vdisplay + y;
-			crtc_count++;
+
+		if (gamma_size == 0)
+			gamma_size = fb_helper->crtc_info[i].mode_set.crtc->gamma_size;
+
+		sizes.surface_width  = max_t(u32, desired_mode->hdisplay + x, sizes.surface_width);
+		sizes.surface_height = max_t(u32, desired_mode->vdisplay + y, sizes.surface_height);
+
+		for (j = 0; j < mode_set->num_connectors; j++) {
+			struct drm_connector *connector = mode_set->connectors[j];
+			if (connector->has_tile) {
+				lasth = (connector->tile_h_loc == (connector->num_h_tile - 1));
+				lastv = (connector->tile_v_loc == (connector->num_v_tile - 1));
+				/* cloning to multiple tiles is just crazy-talk, so: */
+				break;
+			}
 		}
+
+		if (lasth)
+			sizes.fb_width  = min_t(u32, desired_mode->hdisplay + x, sizes.fb_width);
+		if (lastv)
+			sizes.fb_height = min_t(u32, desired_mode->vdisplay + y, sizes.fb_height);
 	}
 
 	if (crtc_count == 0 || sizes.fb_width == -1 || sizes.fb_height == -1) {
diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c
index f1b32f9..cbb4fc0 100644
--- a/drivers/gpu/drm/drm_info.c
+++ b/drivers/gpu/drm/drm_info.c
@@ -37,6 +37,7 @@
 #include <drm/drmP.h>
 #include <drm/drm_gem.h>
 
+#include "drm_internal.h"
 #include "drm_legacy.h"
 
 /**
diff --git a/drivers/gpu/drm/drm_ioc32.c b/drivers/gpu/drm/drm_ioc32.c
index 2f4c4343..aa8bbb4 100644
--- a/drivers/gpu/drm/drm_ioc32.c
+++ b/drivers/gpu/drm/drm_ioc32.c
@@ -1016,7 +1016,7 @@
 	return 0;
 }
 
-drm_ioctl_compat_t *drm_compat_ioctls[] = {
+static drm_ioctl_compat_t *drm_compat_ioctls[] = {
 	[DRM_IOCTL_NR(DRM_IOCTL_VERSION32)] = compat_drm_version,
 	[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE32)] = compat_drm_getunique,
 	[DRM_IOCTL_NR(DRM_IOCTL_GET_MAP32)] = compat_drm_getmap,
diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c
index fd29f03..1b1bd42 100644
--- a/drivers/gpu/drm/drm_pci.c
+++ b/drivers/gpu/drm/drm_pci.c
@@ -27,6 +27,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/export.h>
 #include <drm/drmP.h>
+#include "drm_internal.h"
 #include "drm_legacy.h"
 
 /**
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
index b62b036..33807e0 100644
--- a/drivers/gpu/drm/drm_plane_helper.c
+++ b/drivers/gpu/drm/drm_plane_helper.c
@@ -353,13 +353,14 @@
 	if (primary == NULL) {
 		DRM_DEBUG_KMS("Failed to allocate primary plane\n");
 		return NULL;
-		/*
-		 * Remove the format_default field from drm_plane when dropping
-		 * this helper.
-		 */
-		primary->format_default = true;
 	}
 
+	/*
+	 * Remove the format_default field from drm_plane when dropping
+	 * this helper.
+	 */
+	primary->format_default = true;
+
 	/* possible_crtc's will be filled in later by crtc_init */
 	ret = drm_universal_plane_init(dev, primary, 0,
 				       &drm_primary_helper_funcs,
diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c
index 4a2c328..aab49ee 100644
--- a/drivers/gpu/drm/drm_vm.c
+++ b/drivers/gpu/drm/drm_vm.c
@@ -41,6 +41,7 @@
 #include <linux/slab.h>
 #endif
 #include <asm/pgtable.h>
+#include "drm_internal.h"
 #include "drm_legacy.h"
 
 struct drm_vma_entry {
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
index 84f8dfe..e71e331 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
@@ -76,6 +76,7 @@
 };
 
 static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
+				     struct drm_fb_helper_surface_size *sizes,
 				     struct drm_framebuffer *fb)
 {
 	struct fb_info *fbi = helper->fbdev;
@@ -85,7 +86,7 @@
 	unsigned long offset;
 
 	drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
-	drm_fb_helper_fill_var(fbi, helper, fb->width, fb->height);
+	drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height);
 
 	/* RGB formats use only one buffer */
 	buffer = exynos_drm_fb_buffer(fb, 0);
@@ -189,7 +190,7 @@
 		goto err_destroy_framebuffer;
 	}
 
-	ret = exynos_drm_fbdev_update(helper, helper->fb);
+	ret = exynos_drm_fbdev_update(helper, sizes, helper->fb);
 	if (ret < 0)
 		goto err_dealloc_cmap;
 
diff --git a/drivers/gpu/drm/i2c/adv7511.c b/drivers/gpu/drm/i2c/adv7511.c
index 61aa824..b728523 100644
--- a/drivers/gpu/drm/i2c/adv7511.c
+++ b/drivers/gpu/drm/i2c/adv7511.c
@@ -27,12 +27,13 @@
 	struct regmap *regmap;
 	struct regmap *packet_memory_regmap;
 	enum drm_connector_status status;
-	int dpms_mode;
+	bool powered;
 
 	unsigned int f_tmds;
 
 	unsigned int current_edid_segment;
 	uint8_t edid_buf[256];
+	bool edid_read;
 
 	wait_queue_head_t wq;
 	struct drm_encoder *encoder;
@@ -357,6 +358,48 @@
 	adv7511->rgb = config->input_colorspace == HDMI_COLORSPACE_RGB;
 }
 
+static void adv7511_power_on(struct adv7511 *adv7511)
+{
+	adv7511->current_edid_segment = -1;
+
+	regmap_write(adv7511->regmap, ADV7511_REG_INT(0),
+		     ADV7511_INT0_EDID_READY);
+	regmap_write(adv7511->regmap, ADV7511_REG_INT(1),
+		     ADV7511_INT1_DDC_ERROR);
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER,
+			   ADV7511_POWER_POWER_DOWN, 0);
+
+	/*
+	 * Per spec it is allowed to pulse the HDP signal to indicate that the
+	 * EDID information has changed. Some monitors do this when they wakeup
+	 * from standby or are enabled. When the HDP goes low the adv7511 is
+	 * reset and the outputs are disabled which might cause the monitor to
+	 * go to standby again. To avoid this we ignore the HDP pin for the
+	 * first few seconds after enabling the output.
+	 */
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,
+			   ADV7511_REG_POWER2_HDP_SRC_MASK,
+			   ADV7511_REG_POWER2_HDP_SRC_NONE);
+
+	/*
+	 * Most of the registers are reset during power down or when HPD is low.
+	 */
+	regcache_sync(adv7511->regmap);
+
+	adv7511->powered = true;
+}
+
+static void adv7511_power_off(struct adv7511 *adv7511)
+{
+	/* TODO: setup additional power down modes */
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER,
+			   ADV7511_POWER_POWER_DOWN,
+			   ADV7511_POWER_POWER_DOWN);
+	regcache_mark_dirty(adv7511->regmap);
+
+	adv7511->powered = false;
+}
+
 /* -----------------------------------------------------------------------------
  * Interrupt and hotplug detection
  */
@@ -379,69 +422,71 @@
 	return false;
 }
 
-static irqreturn_t adv7511_irq_handler(int irq, void *devid)
-{
-	struct adv7511 *adv7511 = devid;
-
-	if (adv7511_hpd(adv7511))
-		drm_helper_hpd_irq_event(adv7511->encoder->dev);
-
-	wake_up_all(&adv7511->wq);
-
-	return IRQ_HANDLED;
-}
-
-static unsigned int adv7511_is_interrupt_pending(struct adv7511 *adv7511,
-						 unsigned int irq)
+static int adv7511_irq_process(struct adv7511 *adv7511)
 {
 	unsigned int irq0, irq1;
-	unsigned int pending;
 	int ret;
 
 	ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(0), &irq0);
 	if (ret < 0)
-		return 0;
+		return ret;
+
 	ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(1), &irq1);
 	if (ret < 0)
-		return 0;
+		return ret;
 
-	pending = (irq1 << 8) | irq0;
+	regmap_write(adv7511->regmap, ADV7511_REG_INT(0), irq0);
+	regmap_write(adv7511->regmap, ADV7511_REG_INT(1), irq1);
 
-	return pending & irq;
-}
+	if (irq0 & ADV7511_INT0_HDP)
+		drm_helper_hpd_irq_event(adv7511->encoder->dev);
 
-static int adv7511_wait_for_interrupt(struct adv7511 *adv7511, int irq,
-				      int timeout)
-{
-	unsigned int pending;
-	int ret;
+	if (irq0 & ADV7511_INT0_EDID_READY || irq1 & ADV7511_INT1_DDC_ERROR) {
+		adv7511->edid_read = true;
 
-	if (adv7511->i2c_main->irq) {
-		ret = wait_event_interruptible_timeout(adv7511->wq,
-				adv7511_is_interrupt_pending(adv7511, irq),
-				msecs_to_jiffies(timeout));
-		if (ret <= 0)
-			return 0;
-		pending = adv7511_is_interrupt_pending(adv7511, irq);
-	} else {
-		if (timeout < 25)
-			timeout = 25;
-		do {
-			pending = adv7511_is_interrupt_pending(adv7511, irq);
-			if (pending)
-				break;
-			msleep(25);
-			timeout -= 25;
-		} while (timeout >= 25);
+		if (adv7511->i2c_main->irq)
+			wake_up_all(&adv7511->wq);
 	}
 
-	return pending;
+	return 0;
+}
+
+static irqreturn_t adv7511_irq_handler(int irq, void *devid)
+{
+	struct adv7511 *adv7511 = devid;
+	int ret;
+
+	ret = adv7511_irq_process(adv7511);
+	return ret < 0 ? IRQ_NONE : IRQ_HANDLED;
 }
 
 /* -----------------------------------------------------------------------------
  * EDID retrieval
  */
 
+static int adv7511_wait_for_edid(struct adv7511 *adv7511, int timeout)
+{
+	int ret;
+
+	if (adv7511->i2c_main->irq) {
+		ret = wait_event_interruptible_timeout(adv7511->wq,
+				adv7511->edid_read, msecs_to_jiffies(timeout));
+	} else {
+		for (; timeout > 0; timeout -= 25) {
+			ret = adv7511_irq_process(adv7511);
+			if (ret < 0)
+				break;
+
+			if (adv7511->edid_read)
+				break;
+
+			msleep(25);
+		}
+	}
+
+	return adv7511->edid_read ? 0 : -EIO;
+}
+
 static int adv7511_get_edid_block(void *data, u8 *buf, unsigned int block,
 				  size_t len)
 {
@@ -463,19 +508,14 @@
 			return ret;
 
 		if (status != 2) {
+			adv7511->edid_read = false;
 			regmap_write(adv7511->regmap, ADV7511_REG_EDID_SEGMENT,
 				     block);
-			ret = adv7511_wait_for_interrupt(adv7511,
-					ADV7511_INT0_EDID_READY |
-					ADV7511_INT1_DDC_ERROR, 200);
-
-			if (!(ret & ADV7511_INT0_EDID_READY))
-				return -EIO;
+			ret = adv7511_wait_for_edid(adv7511, 200);
+			if (ret < 0)
+				return ret;
 		}
 
-		regmap_write(adv7511->regmap, ADV7511_REG_INT(0),
-			     ADV7511_INT0_EDID_READY | ADV7511_INT1_DDC_ERROR);
-
 		/* Break this apart, hopefully more I2C controllers will
 		 * support 64 byte transfers than 256 byte transfers
 		 */
@@ -526,9 +566,11 @@
 	unsigned int count;
 
 	/* Reading the EDID only works if the device is powered */
-	if (adv7511->dpms_mode != DRM_MODE_DPMS_ON) {
+	if (!adv7511->powered) {
 		regmap_write(adv7511->regmap, ADV7511_REG_INT(0),
-			     ADV7511_INT0_EDID_READY | ADV7511_INT1_DDC_ERROR);
+			     ADV7511_INT0_EDID_READY);
+		regmap_write(adv7511->regmap, ADV7511_REG_INT(1),
+			     ADV7511_INT1_DDC_ERROR);
 		regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER,
 				   ADV7511_POWER_POWER_DOWN, 0);
 		adv7511->current_edid_segment = -1;
@@ -536,7 +578,7 @@
 
 	edid = drm_do_get_edid(connector, adv7511_get_edid_block, adv7511);
 
-	if (adv7511->dpms_mode != DRM_MODE_DPMS_ON)
+	if (!adv7511->powered)
 		regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER,
 				   ADV7511_POWER_POWER_DOWN,
 				   ADV7511_POWER_POWER_DOWN);
@@ -558,41 +600,10 @@
 {
 	struct adv7511 *adv7511 = encoder_to_adv7511(encoder);
 
-	switch (mode) {
-	case DRM_MODE_DPMS_ON:
-		adv7511->current_edid_segment = -1;
-
-		regmap_write(adv7511->regmap, ADV7511_REG_INT(0),
-			     ADV7511_INT0_EDID_READY | ADV7511_INT1_DDC_ERROR);
-		regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER,
-				   ADV7511_POWER_POWER_DOWN, 0);
-		/*
-		 * Per spec it is allowed to pulse the HDP signal to indicate
-		 * that the EDID information has changed. Some monitors do this
-		 * when they wakeup from standby or are enabled. When the HDP
-		 * goes low the adv7511 is reset and the outputs are disabled
-		 * which might cause the monitor to go to standby again. To
-		 * avoid this we ignore the HDP pin for the first few seconds
-		 * after enabling the output.
-		 */
-		regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,
-				   ADV7511_REG_POWER2_HDP_SRC_MASK,
-				   ADV7511_REG_POWER2_HDP_SRC_NONE);
-		/* Most of the registers are reset during power down or
-		 * when HPD is low
-		 */
-		regcache_sync(adv7511->regmap);
-		break;
-	default:
-		/* TODO: setup additional power down modes */
-		regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER,
-				   ADV7511_POWER_POWER_DOWN,
-				   ADV7511_POWER_POWER_DOWN);
-		regcache_mark_dirty(adv7511->regmap);
-		break;
-	}
-
-	adv7511->dpms_mode = mode;
+	if (mode == DRM_MODE_DPMS_ON)
+		adv7511_power_on(adv7511);
+	else
+		adv7511_power_off(adv7511);
 }
 
 static enum drm_connector_status
@@ -620,10 +631,9 @@
 	 * there is a pending HPD interrupt and the cable is connected there was
 	 * at least one transition from disconnected to connected and the chip
 	 * has to be reinitialized. */
-	if (status == connector_status_connected && hpd &&
-	    adv7511->dpms_mode == DRM_MODE_DPMS_ON) {
+	if (status == connector_status_connected && hpd && adv7511->powered) {
 		regcache_mark_dirty(adv7511->regmap);
-		adv7511_encoder_dpms(encoder, adv7511->dpms_mode);
+		adv7511_power_on(adv7511);
 		adv7511_get_modes(encoder, connector);
 		if (adv7511->status == connector_status_connected)
 			status = connector_status_disconnected;
@@ -858,7 +868,7 @@
 	if (!adv7511)
 		return -ENOMEM;
 
-	adv7511->dpms_mode = DRM_MODE_DPMS_OFF;
+	adv7511->powered = false;
 	adv7511->status = connector_status_disconnected;
 
 	ret = adv7511_parse_dt(dev->of_node, &link_config);
@@ -918,10 +928,7 @@
 	regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL,
 		     ADV7511_CEC_CTRL_POWER_DOWN);
 
-	regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER,
-			   ADV7511_POWER_POWER_DOWN, ADV7511_POWER_POWER_DOWN);
-
-	adv7511->current_edid_segment = -1;
+	adv7511_power_off(adv7511);
 
 	i2c_set_clientdata(i2c, adv7511);
 
diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile
index 4605633..dea53e3 100644
--- a/drivers/gpu/drm/radeon/Makefile
+++ b/drivers/gpu/drm/radeon/Makefile
@@ -81,7 +81,7 @@
 	rv770_smc.o cypress_dpm.o btc_dpm.o sumo_dpm.o sumo_smc.o trinity_dpm.o \
 	trinity_smc.o ni_dpm.o si_smc.o si_dpm.o kv_smc.o kv_dpm.o ci_smc.o \
 	ci_dpm.o dce6_afmt.o radeon_vm.o radeon_ucode.o radeon_ib.o \
-	radeon_sync.o radeon_audio.o
+	radeon_sync.o radeon_audio.o radeon_dp_auxch.o radeon_dp_mst.o
 
 radeon-$(CONFIG_MMU_NOTIFIER) += radeon_mn.o
 
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index 86807ee..dac78ad 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -330,8 +330,10 @@
 		misc |= ATOM_COMPOSITESYNC;
 	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
 		misc |= ATOM_INTERLACE;
-	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
 		misc |= ATOM_DOUBLE_CLOCK_MODE;
+	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+		misc |= ATOM_H_REPLICATIONBY2 | ATOM_V_REPLICATIONBY2;
 
 	args.susModeMiscInfo.usAccess = cpu_to_le16(misc);
 	args.ucCRTC = radeon_crtc->crtc_id;
@@ -374,8 +376,10 @@
 		misc |= ATOM_COMPOSITESYNC;
 	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
 		misc |= ATOM_INTERLACE;
-	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
 		misc |= ATOM_DOUBLE_CLOCK_MODE;
+	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+		misc |= ATOM_H_REPLICATIONBY2 | ATOM_V_REPLICATIONBY2;
 
 	args.susModeMiscInfo.usAccess = cpu_to_le16(misc);
 	args.ucCRTC = radeon_crtc->crtc_id;
@@ -606,6 +610,13 @@
 		}
 	}
 
+	if (radeon_encoder->is_mst_encoder) {
+		struct radeon_encoder_mst *mst_enc = radeon_encoder->enc_priv;
+		struct radeon_connector_atom_dig *dig_connector = mst_enc->connector->con_priv;
+
+		dp_clock = dig_connector->dp_clock;
+	}
+
 	/* use recommended ref_div for ss */
 	if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
 		if (radeon_crtc->ss_enabled) {
@@ -952,7 +963,9 @@
 	radeon_crtc->bpc = 8;
 	radeon_crtc->ss_enabled = false;
 
-	if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) ||
+	if (radeon_encoder->is_mst_encoder) {
+		radeon_dp_mst_prepare_pll(crtc, mode);
+	} else if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) ||
 	    (radeon_encoder_get_dp_bridge_encoder_id(radeon_crtc->encoder) != ENCODER_OBJECT_ID_NONE)) {
 		struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
 		struct drm_connector *connector =
@@ -2069,6 +2082,12 @@
 		radeon_crtc->connector = NULL;
 		return false;
 	}
+	if (radeon_crtc->encoder) {
+		struct radeon_encoder *radeon_encoder =
+			to_radeon_encoder(radeon_crtc->encoder);
+
+		radeon_crtc->output_csc = radeon_encoder->output_csc;
+	}
 	if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
 		return false;
 	if (!atombios_crtc_prepare_pll(crtc, adjusted_mode))
diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c
index 8d74de8..3e3290c 100644
--- a/drivers/gpu/drm/radeon/atombios_dp.c
+++ b/drivers/gpu/drm/radeon/atombios_dp.c
@@ -158,7 +158,7 @@
 #define HEADER_SIZE (BARE_ADDRESS_SIZE + 1)
 
 static ssize_t
-radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
+radeon_dp_aux_transfer_atom(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
 {
 	struct radeon_i2c_chan *chan =
 		container_of(aux, struct radeon_i2c_chan, aux);
@@ -226,11 +226,20 @@
 
 void radeon_dp_aux_init(struct radeon_connector *radeon_connector)
 {
+	struct drm_device *dev = radeon_connector->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
 	int ret;
 
 	radeon_connector->ddc_bus->rec.hpd = radeon_connector->hpd.hpd;
 	radeon_connector->ddc_bus->aux.dev = radeon_connector->base.kdev;
-	radeon_connector->ddc_bus->aux.transfer = radeon_dp_aux_transfer;
+	if (ASIC_IS_DCE5(rdev)) {
+		if (radeon_auxch)
+			radeon_connector->ddc_bus->aux.transfer = radeon_dp_aux_transfer_native;
+		else
+			radeon_connector->ddc_bus->aux.transfer = radeon_dp_aux_transfer_atom;
+	} else {
+		radeon_connector->ddc_bus->aux.transfer = radeon_dp_aux_transfer_atom;
+	}
 
 	ret = drm_dp_aux_register(&radeon_connector->ddc_bus->aux);
 	if (!ret)
@@ -301,8 +310,8 @@
 
 /***** radeon specific DP functions *****/
 
-static int radeon_dp_get_max_link_rate(struct drm_connector *connector,
-				       u8 dpcd[DP_DPCD_SIZE])
+int radeon_dp_get_max_link_rate(struct drm_connector *connector,
+				u8 dpcd[DP_DPCD_SIZE])
 {
 	int max_link_rate;
 
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c
index c39c1d0..f57c1ab 100644
--- a/drivers/gpu/drm/radeon/atombios_encoders.c
+++ b/drivers/gpu/drm/radeon/atombios_encoders.c
@@ -671,7 +671,15 @@
 	struct drm_connector *connector;
 	struct radeon_connector *radeon_connector;
 	struct radeon_connector_atom_dig *dig_connector;
+	struct radeon_encoder_atom_dig *dig_enc;
 
+	if (radeon_encoder_is_digital(encoder)) {
+		dig_enc = radeon_encoder->enc_priv;
+		if (dig_enc->active_mst_links)
+			return ATOM_ENCODER_MODE_DP_MST;
+	}
+	if (radeon_encoder->is_mst_encoder || radeon_encoder->offset)
+		return ATOM_ENCODER_MODE_DP_MST;
 	/* dp bridges are always DP */
 	if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)
 		return ATOM_ENCODER_MODE_DP;
@@ -823,7 +831,7 @@
 };
 
 void
-atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode)
+atombios_dig_encoder_setup2(struct drm_encoder *encoder, int action, int panel_mode, int enc_override)
 {
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
@@ -920,7 +928,10 @@
 
 			if (ENCODER_MODE_IS_DP(args.v3.ucEncoderMode) && (dp_clock == 270000))
 				args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
-			args.v3.acConfig.ucDigSel = dig->dig_encoder;
+			if (enc_override != -1)
+				args.v3.acConfig.ucDigSel = enc_override;
+			else
+				args.v3.acConfig.ucDigSel = dig->dig_encoder;
 			args.v3.ucBitPerColor = radeon_atom_get_bpc(encoder);
 			break;
 		case 4:
@@ -948,7 +959,11 @@
 				else
 					args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_1_62GHZ;
 			}
-			args.v4.acConfig.ucDigSel = dig->dig_encoder;
+
+			if (enc_override != -1)
+				args.v4.acConfig.ucDigSel = enc_override;
+			else
+				args.v4.acConfig.ucDigSel = dig->dig_encoder;
 			args.v4.ucBitPerColor = radeon_atom_get_bpc(encoder);
 			if (hpd_id == RADEON_HPD_NONE)
 				args.v4.ucHPD_ID = 0;
@@ -969,6 +984,12 @@
 
 }
 
+void
+atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode)
+{
+	atombios_dig_encoder_setup2(encoder, action, panel_mode, -1);
+}
+
 union dig_transmitter_control {
 	DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1;
 	DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2;
@@ -978,7 +999,7 @@
 };
 
 void
-atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set)
+atombios_dig_transmitter_setup2(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set, int fe)
 {
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
@@ -1328,7 +1349,7 @@
 				args.v5.asConfig.ucHPDSel = 0;
 			else
 				args.v5.asConfig.ucHPDSel = hpd_id + 1;
-			args.v5.ucDigEncoderSel = 1 << dig_encoder;
+			args.v5.ucDigEncoderSel = (fe != -1) ? (1 << fe) : (1 << dig_encoder);
 			args.v5.ucDPLaneSet = lane_set;
 			break;
 		default:
@@ -1344,6 +1365,12 @@
 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
+void
+atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set)
+{
+	atombios_dig_transmitter_setup2(encoder, action, lane_num, lane_set, -1);
+}
+
 bool
 atombios_set_edp_panel_power(struct drm_connector *connector, int action)
 {
@@ -1687,6 +1714,11 @@
 	case DRM_MODE_DPMS_STANDBY:
 	case DRM_MODE_DPMS_SUSPEND:
 	case DRM_MODE_DPMS_OFF:
+
+		/* don't power off encoders with active MST links */
+		if (dig->active_mst_links)
+			return;
+
 		if (ASIC_IS_DCE4(rdev)) {
 			if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector)
 				atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
@@ -1955,6 +1987,53 @@
 	radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
 }
 
+void
+atombios_set_mst_encoder_crtc_source(struct drm_encoder *encoder, int fe)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
+	int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
+	uint8_t frev, crev;
+	union crtc_source_param args;
+
+	memset(&args, 0, sizeof(args));
+
+	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+		return;
+
+	if (frev != 1 && crev != 2)
+		DRM_ERROR("Unknown table for MST %d, %d\n", frev, crev);
+
+	args.v2.ucCRTC = radeon_crtc->crtc_id;
+	args.v2.ucEncodeMode = ATOM_ENCODER_MODE_DP_MST;
+
+	switch (fe) {
+	case 0:
+		args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
+		break;
+	case 1:
+		args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
+		break;
+	case 2:
+		args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID;
+		break;
+	case 3:
+		args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID;
+		break;
+	case 4:
+		args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID;
+		break;
+	case 5:
+		args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID;
+		break;
+	case 6:
+		args.v2.ucEncoderID = ASIC_INT_DIG7_ENCODER_ID;
+		break;
+	}
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+}
+
 static void
 atombios_apply_encoder_quirks(struct drm_encoder *encoder,
 			      struct drm_display_mode *mode)
@@ -2003,7 +2082,14 @@
 	}
 }
 
-static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder)
+void radeon_atom_release_dig_encoder(struct radeon_device *rdev, int enc_idx)
+{
+	if (enc_idx < 0)
+		return;
+	rdev->mode_info.active_encoders &= ~(1 << enc_idx);
+}
+
+int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder, int fe_idx)
 {
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
@@ -2012,71 +2098,79 @@
 	struct drm_encoder *test_encoder;
 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
 	uint32_t dig_enc_in_use = 0;
+	int enc_idx = -1;
 
+	if (fe_idx >= 0) {
+		enc_idx = fe_idx;
+		goto assigned;
+	}
 	if (ASIC_IS_DCE6(rdev)) {
 		/* DCE6 */
 		switch (radeon_encoder->encoder_id) {
 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
 			if (dig->linkb)
-				return 1;
+				enc_idx = 1;
 			else
-				return 0;
+				enc_idx = 0;
 			break;
 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
 			if (dig->linkb)
-				return 3;
+				enc_idx = 3;
 			else
-				return 2;
+				enc_idx = 2;
 			break;
 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
 			if (dig->linkb)
-				return 5;
+				enc_idx = 5;
 			else
-				return 4;
+				enc_idx = 4;
 			break;
 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
-			return 6;
+			enc_idx = 6;
 			break;
 		}
+		goto assigned;
 	} else if (ASIC_IS_DCE4(rdev)) {
 		/* DCE4/5 */
 		if (ASIC_IS_DCE41(rdev) && !ASIC_IS_DCE61(rdev)) {
 			/* ontario follows DCE4 */
 			if (rdev->family == CHIP_PALM) {
 				if (dig->linkb)
-					return 1;
+					enc_idx = 1;
 				else
-					return 0;
+					enc_idx = 0;
 			} else
 				/* llano follows DCE3.2 */
-				return radeon_crtc->crtc_id;
+				enc_idx = radeon_crtc->crtc_id;
 		} else {
 			switch (radeon_encoder->encoder_id) {
 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
 				if (dig->linkb)
-					return 1;
+					enc_idx = 1;
 				else
-					return 0;
+					enc_idx = 0;
 				break;
 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
 				if (dig->linkb)
-					return 3;
+					enc_idx = 3;
 				else
-					return 2;
+					enc_idx = 2;
 				break;
 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
 				if (dig->linkb)
-					return 5;
+					enc_idx = 5;
 				else
-					return 4;
+					enc_idx = 4;
 				break;
 			}
 		}
+		goto assigned;
 	}
 
 	/* on DCE32 and encoder can driver any block so just crtc id */
 	if (ASIC_IS_DCE32(rdev)) {
-		return radeon_crtc->crtc_id;
+		enc_idx = radeon_crtc->crtc_id;
+		goto assigned;
 	}
 
 	/* on DCE3 - LVTMA can only be driven by DIGB */
@@ -2104,6 +2198,17 @@
 	if (!(dig_enc_in_use & 1))
 		return 0;
 	return 1;
+
+assigned:
+	if (enc_idx == -1) {
+		DRM_ERROR("Got encoder index incorrect - returning 0\n");
+		return 0;
+	}
+	if (rdev->mode_info.active_encoders & (1 << enc_idx)) {
+		DRM_ERROR("chosen encoder in use %d\n", enc_idx);
+	}
+	rdev->mode_info.active_encoders |= (1 << enc_idx);
+	return enc_idx;
 }
 
 /* This only needs to be called once at startup */
@@ -2362,7 +2467,9 @@
 	     ENCODER_OBJECT_ID_NONE)) {
 		struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
 		if (dig) {
-			dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder);
+			if (dig->dig_encoder >= 0)
+				radeon_atom_release_dig_encoder(rdev, dig->dig_encoder);
+			dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder, -1);
 			if (radeon_encoder->active_device & ATOM_DEVICE_DFP_SUPPORT) {
 				if (rdev->family >= CHIP_R600)
 					dig->afmt = rdev->mode_info.afmt[dig->dig_encoder];
@@ -2464,10 +2571,18 @@
 
 disable_done:
 	if (radeon_encoder_is_digital(encoder)) {
-		dig = radeon_encoder->enc_priv;
-		dig->dig_encoder = -1;
-	}
-	radeon_encoder->active_device = 0;
+		if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) {
+			if (rdev->asic->display.hdmi_enable)
+				radeon_hdmi_enable(rdev, encoder, false);
+		}
+		if (atombios_get_encoder_mode(encoder) != ATOM_ENCODER_MODE_DP_MST) {
+			dig = radeon_encoder->enc_priv;
+			radeon_atom_release_dig_encoder(rdev, dig->dig_encoder);
+			dig->dig_encoder = -1;
+			radeon_encoder->active_device = 0;
+		}
+	} else
+		radeon_encoder->active_device = 0;
 }
 
 /* these are handled by the primary encoders */
diff --git a/drivers/gpu/drm/radeon/btc_dpm.c b/drivers/gpu/drm/radeon/btc_dpm.c
index db08f17..69556f5 100644
--- a/drivers/gpu/drm/radeon/btc_dpm.c
+++ b/drivers/gpu/drm/radeon/btc_dpm.c
@@ -2751,13 +2751,54 @@
 		else /* current_index == 2 */
 			pl = &ps->high;
 		seq_printf(m, "uvd    vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
-		if (rdev->family >= CHIP_CEDAR) {
-			seq_printf(m, "power level %d    sclk: %u mclk: %u vddc: %u vddci: %u\n",
-				   current_index, pl->sclk, pl->mclk, pl->vddc, pl->vddci);
-		} else {
-			seq_printf(m, "power level %d    sclk: %u mclk: %u vddc: %u\n",
-				   current_index, pl->sclk, pl->mclk, pl->vddc);
-		}
+		seq_printf(m, "power level %d    sclk: %u mclk: %u vddc: %u vddci: %u\n",
+			   current_index, pl->sclk, pl->mclk, pl->vddc, pl->vddci);
+	}
+}
+
+u32 btc_dpm_get_current_sclk(struct radeon_device *rdev)
+{
+	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+	struct radeon_ps *rps = &eg_pi->current_rps;
+	struct rv7xx_ps *ps = rv770_get_ps(rps);
+	struct rv7xx_pl *pl;
+	u32 current_index =
+		(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_PROFILE_INDEX_MASK) >>
+		CURRENT_PROFILE_INDEX_SHIFT;
+
+	if (current_index > 2) {
+		return 0;
+	} else {
+		if (current_index == 0)
+			pl = &ps->low;
+		else if (current_index == 1)
+			pl = &ps->medium;
+		else /* current_index == 2 */
+			pl = &ps->high;
+		return pl->sclk;
+	}
+}
+
+u32 btc_dpm_get_current_mclk(struct radeon_device *rdev)
+{
+	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+	struct radeon_ps *rps = &eg_pi->current_rps;
+	struct rv7xx_ps *ps = rv770_get_ps(rps);
+	struct rv7xx_pl *pl;
+	u32 current_index =
+		(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_PROFILE_INDEX_MASK) >>
+		CURRENT_PROFILE_INDEX_SHIFT;
+
+	if (current_index > 2) {
+		return 0;
+	} else {
+		if (current_index == 0)
+			pl = &ps->low;
+		else if (current_index == 1)
+			pl = &ps->medium;
+		else /* current_index == 2 */
+			pl = &ps->high;
+		return pl->mclk;
 	}
 }
 
diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c
index bcd2f1f..8730562 100644
--- a/drivers/gpu/drm/radeon/ci_dpm.c
+++ b/drivers/gpu/drm/radeon/ci_dpm.c
@@ -5922,6 +5922,20 @@
 	r600_dpm_print_ps_status(rdev, rps);
 }
 
+u32 ci_dpm_get_current_sclk(struct radeon_device *rdev)
+{
+	u32 sclk = ci_get_average_sclk_freq(rdev);
+
+	return sclk;
+}
+
+u32 ci_dpm_get_current_mclk(struct radeon_device *rdev)
+{
+	u32 mclk = ci_get_average_mclk_freq(rdev);
+
+	return mclk;
+}
+
 u32 ci_dpm_get_sclk(struct radeon_device *rdev, bool low)
 {
 	struct ci_power_info *pi = ci_get_pi(rdev);
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index 3e670d3..28faea9 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -141,6 +141,39 @@
 static void cik_enable_gui_idle_interrupt(struct radeon_device *rdev,
 					  bool enable);
 
+/**
+ * cik_get_allowed_info_register - fetch the register for the info ioctl
+ *
+ * @rdev: radeon_device pointer
+ * @reg: register offset in bytes
+ * @val: register value
+ *
+ * Returns 0 for success or -EINVAL for an invalid register
+ *
+ */
+int cik_get_allowed_info_register(struct radeon_device *rdev,
+				  u32 reg, u32 *val)
+{
+	switch (reg) {
+	case GRBM_STATUS:
+	case GRBM_STATUS2:
+	case GRBM_STATUS_SE0:
+	case GRBM_STATUS_SE1:
+	case GRBM_STATUS_SE2:
+	case GRBM_STATUS_SE3:
+	case SRBM_STATUS:
+	case SRBM_STATUS2:
+	case (SDMA0_STATUS_REG + SDMA0_REGISTER_OFFSET):
+	case (SDMA0_STATUS_REG + SDMA1_REGISTER_OFFSET):
+	case UVD_STATUS:
+	/* TODO VCE */
+		*val = RREG32(reg);
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
 /* get temperature in millidegrees */
 int ci_get_temp(struct radeon_device *rdev)
 {
@@ -7394,12 +7427,12 @@
 		(CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
 	cp_int_cntl |= PRIV_INSTR_INT_ENABLE | PRIV_REG_INT_ENABLE;
 
-	hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN;
-	hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN;
-	hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~DC_HPDx_INT_EN;
-	hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~DC_HPDx_INT_EN;
-	hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN;
-	hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN;
+	hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
+	hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
+	hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
+	hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
+	hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
+	hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
 
 	dma_cntl = RREG32(SDMA0_CNTL + SDMA0_REGISTER_OFFSET) & ~TRAP_ENABLE;
 	dma_cntl1 = RREG32(SDMA0_CNTL + SDMA1_REGISTER_OFFSET) & ~TRAP_ENABLE;
@@ -7486,27 +7519,27 @@
 	}
 	if (rdev->irq.hpd[0]) {
 		DRM_DEBUG("cik_irq_set: hpd 1\n");
-		hpd1 |= DC_HPDx_INT_EN;
+		hpd1 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
 	}
 	if (rdev->irq.hpd[1]) {
 		DRM_DEBUG("cik_irq_set: hpd 2\n");
-		hpd2 |= DC_HPDx_INT_EN;
+		hpd2 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
 	}
 	if (rdev->irq.hpd[2]) {
 		DRM_DEBUG("cik_irq_set: hpd 3\n");
-		hpd3 |= DC_HPDx_INT_EN;
+		hpd3 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
 	}
 	if (rdev->irq.hpd[3]) {
 		DRM_DEBUG("cik_irq_set: hpd 4\n");
-		hpd4 |= DC_HPDx_INT_EN;
+		hpd4 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
 	}
 	if (rdev->irq.hpd[4]) {
 		DRM_DEBUG("cik_irq_set: hpd 5\n");
-		hpd5 |= DC_HPDx_INT_EN;
+		hpd5 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
 	}
 	if (rdev->irq.hpd[5]) {
 		DRM_DEBUG("cik_irq_set: hpd 6\n");
-		hpd6 |= DC_HPDx_INT_EN;
+		hpd6 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
 	}
 
 	WREG32(CP_INT_CNTL_RING0, cp_int_cntl);
@@ -7678,6 +7711,36 @@
 		tmp |= DC_HPDx_INT_ACK;
 		WREG32(DC_HPD6_INT_CONTROL, tmp);
 	}
+	if (rdev->irq.stat_regs.cik.disp_int & DC_HPD1_RX_INTERRUPT) {
+		tmp = RREG32(DC_HPD1_INT_CONTROL);
+		tmp |= DC_HPDx_RX_INT_ACK;
+		WREG32(DC_HPD1_INT_CONTROL, tmp);
+	}
+	if (rdev->irq.stat_regs.cik.disp_int_cont & DC_HPD2_RX_INTERRUPT) {
+		tmp = RREG32(DC_HPD2_INT_CONTROL);
+		tmp |= DC_HPDx_RX_INT_ACK;
+		WREG32(DC_HPD2_INT_CONTROL, tmp);
+	}
+	if (rdev->irq.stat_regs.cik.disp_int_cont2 & DC_HPD3_RX_INTERRUPT) {
+		tmp = RREG32(DC_HPD3_INT_CONTROL);
+		tmp |= DC_HPDx_RX_INT_ACK;
+		WREG32(DC_HPD3_INT_CONTROL, tmp);
+	}
+	if (rdev->irq.stat_regs.cik.disp_int_cont3 & DC_HPD4_RX_INTERRUPT) {
+		tmp = RREG32(DC_HPD4_INT_CONTROL);
+		tmp |= DC_HPDx_RX_INT_ACK;
+		WREG32(DC_HPD4_INT_CONTROL, tmp);
+	}
+	if (rdev->irq.stat_regs.cik.disp_int_cont4 & DC_HPD5_RX_INTERRUPT) {
+		tmp = RREG32(DC_HPD5_INT_CONTROL);
+		tmp |= DC_HPDx_RX_INT_ACK;
+		WREG32(DC_HPD5_INT_CONTROL, tmp);
+	}
+	if (rdev->irq.stat_regs.cik.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
+		tmp = RREG32(DC_HPD5_INT_CONTROL);
+		tmp |= DC_HPDx_RX_INT_ACK;
+		WREG32(DC_HPD6_INT_CONTROL, tmp);
+	}
 }
 
 /**
@@ -7803,6 +7866,7 @@
 	u8 me_id, pipe_id, queue_id;
 	u32 ring_index;
 	bool queue_hotplug = false;
+	bool queue_dp = false;
 	bool queue_reset = false;
 	u32 addr, status, mc_client;
 	bool queue_thermal = false;
@@ -8048,6 +8112,48 @@
 					DRM_DEBUG("IH: HPD6\n");
 				}
 				break;
+			case 6:
+				if (rdev->irq.stat_regs.cik.disp_int & DC_HPD1_RX_INTERRUPT) {
+					rdev->irq.stat_regs.cik.disp_int &= ~DC_HPD1_RX_INTERRUPT;
+					queue_dp = true;
+					DRM_DEBUG("IH: HPD_RX 1\n");
+				}
+				break;
+			case 7:
+				if (rdev->irq.stat_regs.cik.disp_int_cont & DC_HPD2_RX_INTERRUPT) {
+					rdev->irq.stat_regs.cik.disp_int_cont &= ~DC_HPD2_RX_INTERRUPT;
+					queue_dp = true;
+					DRM_DEBUG("IH: HPD_RX 2\n");
+				}
+				break;
+			case 8:
+				if (rdev->irq.stat_regs.cik.disp_int_cont2 & DC_HPD3_RX_INTERRUPT) {
+					rdev->irq.stat_regs.cik.disp_int_cont2 &= ~DC_HPD3_RX_INTERRUPT;
+					queue_dp = true;
+					DRM_DEBUG("IH: HPD_RX 3\n");
+				}
+				break;
+			case 9:
+				if (rdev->irq.stat_regs.cik.disp_int_cont3 & DC_HPD4_RX_INTERRUPT) {
+					rdev->irq.stat_regs.cik.disp_int_cont3 &= ~DC_HPD4_RX_INTERRUPT;
+					queue_dp = true;
+					DRM_DEBUG("IH: HPD_RX 4\n");
+				}
+				break;
+			case 10:
+				if (rdev->irq.stat_regs.cik.disp_int_cont4 & DC_HPD5_RX_INTERRUPT) {
+					rdev->irq.stat_regs.cik.disp_int_cont4 &= ~DC_HPD5_RX_INTERRUPT;
+					queue_dp = true;
+					DRM_DEBUG("IH: HPD_RX 5\n");
+				}
+				break;
+			case 11:
+				if (rdev->irq.stat_regs.cik.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
+					rdev->irq.stat_regs.cik.disp_int_cont5 &= ~DC_HPD6_RX_INTERRUPT;
+					queue_dp = true;
+					DRM_DEBUG("IH: HPD_RX 6\n");
+				}
+				break;
 			default:
 				DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data);
 				break;
@@ -8256,6 +8362,8 @@
 		rptr &= rdev->ih.ptr_mask;
 		WREG32(IH_RB_RPTR, rptr);
 	}
+	if (queue_dp)
+		schedule_work(&rdev->dp_work);
 	if (queue_hotplug)
 		schedule_work(&rdev->hotplug_work);
 	if (queue_reset) {
diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h
index c648e19..4870df8 100644
--- a/drivers/gpu/drm/radeon/cikd.h
+++ b/drivers/gpu/drm/radeon/cikd.h
@@ -2088,6 +2088,8 @@
 #	define CLK_OD(x)				((x) << 6)
 #	define CLK_OD_MASK				(0x1f << 6)
 
+#define UVD_STATUS					0xf6bc
+
 /* UVD clocks */
 
 #define CG_DCLK_CNTL			0xC050009C
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 973df06..f848acf 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -1006,6 +1006,34 @@
 	}
 }
 
+/**
+ * evergreen_get_allowed_info_register - fetch the register for the info ioctl
+ *
+ * @rdev: radeon_device pointer
+ * @reg: register offset in bytes
+ * @val: register value
+ *
+ * Returns 0 for success or -EINVAL for an invalid register
+ *
+ */
+int evergreen_get_allowed_info_register(struct radeon_device *rdev,
+					u32 reg, u32 *val)
+{
+	switch (reg) {
+	case GRBM_STATUS:
+	case GRBM_STATUS_SE0:
+	case GRBM_STATUS_SE1:
+	case SRBM_STATUS:
+	case SRBM_STATUS2:
+	case DMA_STATUS_REG:
+	case UVD_STATUS:
+		*val = RREG32(reg);
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
 void evergreen_tiling_fields(unsigned tiling_flags, unsigned *bankw,
 			     unsigned *bankh, unsigned *mtaspect,
 			     unsigned *tile_split)
@@ -4392,12 +4420,12 @@
 		return 0;
 	}
 
-	hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN;
-	hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN;
-	hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~DC_HPDx_INT_EN;
-	hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~DC_HPDx_INT_EN;
-	hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN;
-	hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN;
+	hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
+	hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
+	hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
+	hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
+	hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
+	hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
 	if (rdev->family == CHIP_ARUBA)
 		thermal_int = RREG32(TN_CG_THERMAL_INT_CTRL) &
 			~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW);
@@ -4486,27 +4514,27 @@
 	}
 	if (rdev->irq.hpd[0]) {
 		DRM_DEBUG("evergreen_irq_set: hpd 1\n");
-		hpd1 |= DC_HPDx_INT_EN;
+		hpd1 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
 	}
 	if (rdev->irq.hpd[1]) {
 		DRM_DEBUG("evergreen_irq_set: hpd 2\n");
-		hpd2 |= DC_HPDx_INT_EN;
+		hpd2 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
 	}
 	if (rdev->irq.hpd[2]) {
 		DRM_DEBUG("evergreen_irq_set: hpd 3\n");
-		hpd3 |= DC_HPDx_INT_EN;
+		hpd3 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
 	}
 	if (rdev->irq.hpd[3]) {
 		DRM_DEBUG("evergreen_irq_set: hpd 4\n");
-		hpd4 |= DC_HPDx_INT_EN;
+		hpd4 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
 	}
 	if (rdev->irq.hpd[4]) {
 		DRM_DEBUG("evergreen_irq_set: hpd 5\n");
-		hpd5 |= DC_HPDx_INT_EN;
+		hpd5 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
 	}
 	if (rdev->irq.hpd[5]) {
 		DRM_DEBUG("evergreen_irq_set: hpd 6\n");
-		hpd6 |= DC_HPDx_INT_EN;
+		hpd6 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
 	}
 	if (rdev->irq.afmt[0]) {
 		DRM_DEBUG("evergreen_irq_set: hdmi 0\n");
@@ -4700,6 +4728,38 @@
 		tmp |= DC_HPDx_INT_ACK;
 		WREG32(DC_HPD6_INT_CONTROL, tmp);
 	}
+
+	if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_RX_INTERRUPT) {
+		tmp = RREG32(DC_HPD1_INT_CONTROL);
+		tmp |= DC_HPDx_RX_INT_ACK;
+		WREG32(DC_HPD1_INT_CONTROL, tmp);
+	}
+	if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_RX_INTERRUPT) {
+		tmp = RREG32(DC_HPD2_INT_CONTROL);
+		tmp |= DC_HPDx_RX_INT_ACK;
+		WREG32(DC_HPD2_INT_CONTROL, tmp);
+	}
+	if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_RX_INTERRUPT) {
+		tmp = RREG32(DC_HPD3_INT_CONTROL);
+		tmp |= DC_HPDx_RX_INT_ACK;
+		WREG32(DC_HPD3_INT_CONTROL, tmp);
+	}
+	if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_RX_INTERRUPT) {
+		tmp = RREG32(DC_HPD4_INT_CONTROL);
+		tmp |= DC_HPDx_RX_INT_ACK;
+		WREG32(DC_HPD4_INT_CONTROL, tmp);
+	}
+	if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_RX_INTERRUPT) {
+		tmp = RREG32(DC_HPD5_INT_CONTROL);
+		tmp |= DC_HPDx_RX_INT_ACK;
+		WREG32(DC_HPD5_INT_CONTROL, tmp);
+	}
+	if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
+		tmp = RREG32(DC_HPD5_INT_CONTROL);
+		tmp |= DC_HPDx_RX_INT_ACK;
+		WREG32(DC_HPD6_INT_CONTROL, tmp);
+	}
+
 	if (rdev->irq.stat_regs.evergreen.afmt_status1 & AFMT_AZ_FORMAT_WTRIG) {
 		tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET);
 		tmp |= AFMT_AZ_FORMAT_WTRIG_ACK;
@@ -4780,6 +4840,7 @@
 	u32 ring_index;
 	bool queue_hotplug = false;
 	bool queue_hdmi = false;
+	bool queue_dp = false;
 	bool queue_thermal = false;
 	u32 status, addr;
 
@@ -5019,6 +5080,48 @@
 					DRM_DEBUG("IH: HPD6\n");
 				}
 				break;
+			case 6:
+				if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_RX_INTERRUPT) {
+					rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_RX_INTERRUPT;
+					queue_dp = true;
+					DRM_DEBUG("IH: HPD_RX 1\n");
+				}
+				break;
+			case 7:
+				if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_RX_INTERRUPT) {
+					rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_RX_INTERRUPT;
+					queue_dp = true;
+					DRM_DEBUG("IH: HPD_RX 2\n");
+				}
+				break;
+			case 8:
+				if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_RX_INTERRUPT) {
+					rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_RX_INTERRUPT;
+					queue_dp = true;
+					DRM_DEBUG("IH: HPD_RX 3\n");
+				}
+				break;
+			case 9:
+				if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_RX_INTERRUPT) {
+					rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_RX_INTERRUPT;
+					queue_dp = true;
+					DRM_DEBUG("IH: HPD_RX 4\n");
+				}
+				break;
+			case 10:
+				if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_RX_INTERRUPT) {
+					rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_RX_INTERRUPT;
+					queue_dp = true;
+					DRM_DEBUG("IH: HPD_RX 5\n");
+				}
+				break;
+			case 11:
+				if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
+					rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_RX_INTERRUPT;
+					queue_dp = true;
+					DRM_DEBUG("IH: HPD_RX 6\n");
+				}
+				break;
 			default:
 				DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data);
 				break;
@@ -5151,6 +5254,8 @@
 		rptr &= rdev->ih.ptr_mask;
 		WREG32(IH_RB_RPTR, rptr);
 	}
+	if (queue_dp)
+		schedule_work(&rdev->dp_work);
 	if (queue_hotplug)
 		schedule_work(&rdev->hotplug_work);
 	if (queue_hdmi)
diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h
index a8d1d52..4aa5f75 100644
--- a/drivers/gpu/drm/radeon/evergreend.h
+++ b/drivers/gpu/drm/radeon/evergreend.h
@@ -1520,6 +1520,7 @@
 #define UVD_UDEC_DBW_ADDR_CONFIG			0xef54
 #define UVD_RBC_RB_RPTR					0xf690
 #define UVD_RBC_RB_WPTR					0xf694
+#define UVD_STATUS					0xf6bc
 
 /*
  * PM4
diff --git a/drivers/gpu/drm/radeon/kv_dpm.c b/drivers/gpu/drm/radeon/kv_dpm.c
index 0e236d0..2d71da4 100644
--- a/drivers/gpu/drm/radeon/kv_dpm.c
+++ b/drivers/gpu/drm/radeon/kv_dpm.c
@@ -2820,6 +2820,29 @@
 	}
 }
 
+u32 kv_dpm_get_current_sclk(struct radeon_device *rdev)
+{
+	struct kv_power_info *pi = kv_get_pi(rdev);
+	u32 current_index =
+		(RREG32_SMC(TARGET_AND_CURRENT_PROFILE_INDEX) & CURR_SCLK_INDEX_MASK) >>
+		CURR_SCLK_INDEX_SHIFT;
+	u32 sclk;
+
+	if (current_index >= SMU__NUM_SCLK_DPM_STATE) {
+		return 0;
+	} else {
+		sclk = be32_to_cpu(pi->graphics_level[current_index].SclkFrequency);
+		return sclk;
+	}
+}
+
+u32 kv_dpm_get_current_mclk(struct radeon_device *rdev)
+{
+	struct kv_power_info *pi = kv_get_pi(rdev);
+
+	return pi->sys_info.bootup_uma_clk;
+}
+
 void kv_dpm_print_power_state(struct radeon_device *rdev,
 			      struct radeon_ps *rps)
 {
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index dab0081..e8a496f 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -828,6 +828,35 @@
 	return err;
 }
 
+/**
+ * cayman_get_allowed_info_register - fetch the register for the info ioctl
+ *
+ * @rdev: radeon_device pointer
+ * @reg: register offset in bytes
+ * @val: register value
+ *
+ * Returns 0 for success or -EINVAL for an invalid register
+ *
+ */
+int cayman_get_allowed_info_register(struct radeon_device *rdev,
+				     u32 reg, u32 *val)
+{
+	switch (reg) {
+	case GRBM_STATUS:
+	case GRBM_STATUS_SE0:
+	case GRBM_STATUS_SE1:
+	case SRBM_STATUS:
+	case SRBM_STATUS2:
+	case (DMA_STATUS_REG + DMA0_REGISTER_OFFSET):
+	case (DMA_STATUS_REG + DMA1_REGISTER_OFFSET):
+	case UVD_STATUS:
+		*val = RREG32(reg);
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
 int tn_get_temp(struct radeon_device *rdev)
 {
 	u32 temp = RREG32_SMC(TN_CURRENT_GNB_TEMP) & 0x7ff;
diff --git a/drivers/gpu/drm/radeon/ni_dpm.c b/drivers/gpu/drm/radeon/ni_dpm.c
index 7bc9f8d..c3d531a 100644
--- a/drivers/gpu/drm/radeon/ni_dpm.c
+++ b/drivers/gpu/drm/radeon/ni_dpm.c
@@ -4319,6 +4319,42 @@
 	}
 }
 
+u32 ni_dpm_get_current_sclk(struct radeon_device *rdev)
+{
+	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+	struct radeon_ps *rps = &eg_pi->current_rps;
+	struct ni_ps *ps = ni_get_ps(rps);
+	struct rv7xx_pl *pl;
+	u32 current_index =
+		(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_INDEX_MASK) >>
+		CURRENT_STATE_INDEX_SHIFT;
+
+	if (current_index >= ps->performance_level_count) {
+		return 0;
+	} else {
+		pl = &ps->performance_levels[current_index];
+		return pl->sclk;
+	}
+}
+
+u32 ni_dpm_get_current_mclk(struct radeon_device *rdev)
+{
+	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+	struct radeon_ps *rps = &eg_pi->current_rps;
+	struct ni_ps *ps = ni_get_ps(rps);
+	struct rv7xx_pl *pl;
+	u32 current_index =
+		(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_INDEX_MASK) >>
+		CURRENT_STATE_INDEX_SHIFT;
+
+	if (current_index >= ps->performance_level_count) {
+		return 0;
+	} else {
+		pl = &ps->performance_levels[current_index];
+		return pl->mclk;
+	}
+}
+
 u32 ni_dpm_get_sclk(struct radeon_device *rdev, bool low)
 {
 	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
diff --git a/drivers/gpu/drm/radeon/ni_reg.h b/drivers/gpu/drm/radeon/ni_reg.h
index 5db7b7d..da310a70 100644
--- a/drivers/gpu/drm/radeon/ni_reg.h
+++ b/drivers/gpu/drm/radeon/ni_reg.h
@@ -83,4 +83,48 @@
 #       define NI_REGAMMA_PROG_B                       4
 #       define NI_OVL_REGAMMA_MODE(x)                  (((x) & 0x7) << 4)
 
+#define NI_DP_MSE_LINK_TIMING                          0x73a0
+#	define NI_DP_MSE_LINK_FRAME			(((x) & 0x3ff) << 0)
+#	define NI_DP_MSE_LINK_LINE                      (((x) & 0x3) << 16)
+
+#define NI_DP_MSE_MISC_CNTL                            0x736c
+#       define NI_DP_MSE_BLANK_CODE                    (((x) & 0x1) << 0)
+#       define NI_DP_MSE_TIMESTAMP_MODE                (((x) & 0x1) << 4)
+#       define NI_DP_MSE_ZERO_ENCODER                  (((x) & 0x1) << 8)
+
+#define NI_DP_MSE_RATE_CNTL                            0x7384
+#       define NI_DP_MSE_RATE_Y(x)                   (((x) & 0x3ffffff) << 0)
+#       define NI_DP_MSE_RATE_X(x)                   (((x) & 0x3f) << 26)
+
+#define NI_DP_MSE_RATE_UPDATE                          0x738c
+
+#define NI_DP_MSE_SAT0                                 0x7390
+#       define NI_DP_MSE_SAT_SRC0(x)                   (((x) & 0x7) << 0)
+#       define NI_DP_MSE_SAT_SLOT_COUNT0(x)            (((x) & 0x3f) << 8)
+#       define NI_DP_MSE_SAT_SRC1(x)                   (((x) & 0x7) << 16)
+#       define NI_DP_MSE_SAT_SLOT_COUNT1(x)            (((x) & 0x3f) << 24)
+
+#define NI_DP_MSE_SAT1                                 0x7394
+
+#define NI_DP_MSE_SAT2                                 0x7398
+
+#define NI_DP_MSE_SAT_UPDATE                           0x739c
+
+#define NI_DIG_BE_CNTL                                 0x7140
+#       define NI_DIG_FE_SOURCE_SELECT(x)              (((x) & 0x7f) << 8)
+#       define NI_DIG_FE_DIG_MODE(x)                   (((x) & 0x7) << 16)
+#       define NI_DIG_MODE_DP_SST                      0
+#       define NI_DIG_MODE_LVDS                        1
+#       define NI_DIG_MODE_TMDS_DVI                    2
+#       define NI_DIG_MODE_TMDS_HDMI                   3
+#       define NI_DIG_MODE_DP_MST                      5
+#       define NI_DIG_HPD_SELECT(x)                    (((x) & 0x7) << 28)
+
+#define NI_DIG_FE_CNTL                                 0x7000
+#       define NI_DIG_SOURCE_SELECT(x)                 (((x) & 0x3) << 0)
+#       define NI_DIG_STEREOSYNC_SELECT(x)             (((x) & 0x3) << 4)
+#       define NI_DIG_STEREOSYNC_GATE_EN(x)            (((x) & 0x1) << 8)
+#       define NI_DIG_DUAL_LINK_ENABLE(x)              (((x) & 0x1) << 16)
+#       define NI_DIG_SWAP(x)                          (((x) & 0x1) << 18)
+#       define NI_DIG_SYMCLK_FE_ON                     (0x1 << 24)
 #endif
diff --git a/drivers/gpu/drm/radeon/nid.h b/drivers/gpu/drm/radeon/nid.h
index 6b44580..3b29083 100644
--- a/drivers/gpu/drm/radeon/nid.h
+++ b/drivers/gpu/drm/radeon/nid.h
@@ -816,6 +816,52 @@
 #define MC_PMG_CMD_MRS2                                 0x2b5c
 #define MC_SEQ_PMG_CMD_MRS2_LP                          0x2b60
 
+#define AUX_CONTROL					0x6200
+#define 	AUX_EN					(1 << 0)
+#define 	AUX_LS_READ_EN				(1 << 8)
+#define 	AUX_LS_UPDATE_DISABLE(x)		(((x) & 0x1) << 12)
+#define 	AUX_HPD_DISCON(x)			(((x) & 0x1) << 16)
+#define 	AUX_DET_EN				(1 << 18)
+#define 	AUX_HPD_SEL(x)				(((x) & 0x7) << 20)
+#define 	AUX_IMPCAL_REQ_EN			(1 << 24)
+#define 	AUX_TEST_MODE				(1 << 28)
+#define 	AUX_DEGLITCH_EN				(1 << 29)
+#define AUX_SW_CONTROL					0x6204
+#define 	AUX_SW_GO				(1 << 0)
+#define 	AUX_LS_READ_TRIG			(1 << 2)
+#define 	AUX_SW_START_DELAY(x)			(((x) & 0xf) << 4)
+#define 	AUX_SW_WR_BYTES(x)			(((x) & 0x1f) << 16)
+
+#define AUX_SW_INTERRUPT_CONTROL			0x620c
+#define 	AUX_SW_DONE_INT				(1 << 0)
+#define 	AUX_SW_DONE_ACK				(1 << 1)
+#define 	AUX_SW_DONE_MASK			(1 << 2)
+#define 	AUX_SW_LS_DONE_INT			(1 << 4)
+#define 	AUX_SW_LS_DONE_MASK			(1 << 6)
+#define AUX_SW_STATUS					0x6210
+#define 	AUX_SW_DONE				(1 << 0)
+#define 	AUX_SW_REQ				(1 << 1)
+#define 	AUX_SW_RX_TIMEOUT_STATE(x)		(((x) & 0x7) << 4)
+#define 	AUX_SW_RX_TIMEOUT			(1 << 7)
+#define 	AUX_SW_RX_OVERFLOW			(1 << 8)
+#define 	AUX_SW_RX_HPD_DISCON			(1 << 9)
+#define 	AUX_SW_RX_PARTIAL_BYTE			(1 << 10)
+#define 	AUX_SW_NON_AUX_MODE			(1 << 11)
+#define 	AUX_SW_RX_MIN_COUNT_VIOL		(1 << 12)
+#define 	AUX_SW_RX_INVALID_STOP			(1 << 14)
+#define 	AUX_SW_RX_SYNC_INVALID_L		(1 << 17)
+#define 	AUX_SW_RX_SYNC_INVALID_H		(1 << 18)
+#define 	AUX_SW_RX_INVALID_START			(1 << 19)
+#define 	AUX_SW_RX_RECV_NO_DET			(1 << 20)
+#define 	AUX_SW_RX_RECV_INVALID_H		(1 << 22)
+#define 	AUX_SW_RX_RECV_INVALID_V		(1 << 23)
+
+#define AUX_SW_DATA					0x6218
+#define AUX_SW_DATA_RW					(1 << 0)
+#define AUX_SW_DATA_MASK(x)				(((x) & 0xff) << 8)
+#define AUX_SW_DATA_INDEX(x)				(((x) & 0x1f) << 16)
+#define AUX_SW_AUTOINCREMENT_DISABLE			(1 << 31)
+
 #define	LB_SYNC_RESET_SEL				0x6b28
 #define		LB_SYNC_RESET_SEL_MASK			(3 << 0)
 #define		LB_SYNC_RESET_SEL_SHIFT			0
@@ -1086,6 +1132,7 @@
 #define UVD_UDEC_DBW_ADDR_CONFIG			0xEF54
 #define UVD_RBC_RB_RPTR					0xF690
 #define UVD_RBC_RB_WPTR					0xF694
+#define UVD_STATUS					0xf6bc
 
 /*
  * PM4
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index 2fcad34..8f6d862 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -109,6 +109,32 @@
 extern void rv770_set_clk_bypass_mode(struct radeon_device *rdev);
 
 /**
+ * r600_get_allowed_info_register - fetch the register for the info ioctl
+ *
+ * @rdev: radeon_device pointer
+ * @reg: register offset in bytes
+ * @val: register value
+ *
+ * Returns 0 for success or -EINVAL for an invalid register
+ *
+ */
+int r600_get_allowed_info_register(struct radeon_device *rdev,
+				   u32 reg, u32 *val)
+{
+	switch (reg) {
+	case GRBM_STATUS:
+	case GRBM_STATUS2:
+	case R_000E50_SRBM_STATUS:
+	case DMA_STATUS_REG:
+	case UVD_STATUS:
+		*val = RREG32(reg);
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+/**
  * r600_get_xclk - get the xclk
  *
  * @rdev: radeon_device pointer
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 5587603..35ab65d 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -111,6 +111,8 @@
 extern int radeon_use_pflipirq;
 extern int radeon_bapm;
 extern int radeon_backlight;
+extern int radeon_auxch;
+extern int radeon_mst;
 
 /*
  * Copy from radeon_drv.h so we don't have to include both and have conflicting
@@ -1856,6 +1858,8 @@
 	u32 (*get_xclk)(struct radeon_device *rdev);
 	/* get the gpu clock counter */
 	uint64_t (*get_gpu_clock_counter)(struct radeon_device *rdev);
+	/* get register for info ioctl */
+	int (*get_allowed_info_register)(struct radeon_device *rdev, u32 reg, u32 *val);
 	/* gart */
 	struct {
 		void (*tlb_flush)(struct radeon_device *rdev);
@@ -1984,6 +1988,8 @@
 		u32 (*fan_ctrl_get_mode)(struct radeon_device *rdev);
 		int (*set_fan_speed_percent)(struct radeon_device *rdev, u32 speed);
 		int (*get_fan_speed_percent)(struct radeon_device *rdev, u32 *speed);
+		u32 (*get_current_sclk)(struct radeon_device *rdev);
+		u32 (*get_current_mclk)(struct radeon_device *rdev);
 	} dpm;
 	/* pageflipping */
 	struct {
@@ -2407,6 +2413,7 @@
 	struct radeon_rlc rlc;
 	struct radeon_mec mec;
 	struct work_struct hotplug_work;
+	struct work_struct dp_work;
 	struct work_struct audio_work;
 	int num_crtc; /* number of crtcs */
 	struct mutex dc_hw_i2c_mutex; /* display controller hw i2c mutex */
@@ -2931,6 +2938,7 @@
 #define radeon_mc_wait_for_idle(rdev) (rdev)->asic->mc_wait_for_idle((rdev))
 #define radeon_get_xclk(rdev) (rdev)->asic->get_xclk((rdev))
 #define radeon_get_gpu_clock_counter(rdev) (rdev)->asic->get_gpu_clock_counter((rdev))
+#define radeon_get_allowed_info_register(rdev, r, v) (rdev)->asic->get_allowed_info_register((rdev), (r), (v))
 #define radeon_dpm_init(rdev) rdev->asic->dpm.init((rdev))
 #define radeon_dpm_setup_asic(rdev) rdev->asic->dpm.setup_asic((rdev))
 #define radeon_dpm_enable(rdev) rdev->asic->dpm.enable((rdev))
@@ -2949,6 +2957,8 @@
 #define radeon_dpm_vblank_too_short(rdev) rdev->asic->dpm.vblank_too_short((rdev))
 #define radeon_dpm_powergate_uvd(rdev, g) rdev->asic->dpm.powergate_uvd((rdev), (g))
 #define radeon_dpm_enable_bapm(rdev, e) rdev->asic->dpm.enable_bapm((rdev), (e))
+#define radeon_dpm_get_current_sclk(rdev) rdev->asic->dpm.get_current_sclk((rdev))
+#define radeon_dpm_get_current_mclk(rdev) rdev->asic->dpm.get_current_mclk((rdev))
 
 /* Common functions */
 /* AGP */
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
index c0ecd12..fafd8ce 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -136,6 +136,11 @@
 	}
 }
 
+static int radeon_invalid_get_allowed_info_register(struct radeon_device *rdev,
+						    u32 reg, u32 *val)
+{
+	return -EINVAL;
+}
 
 /* helper to disable agp */
 /**
@@ -199,6 +204,7 @@
 	.mmio_hdp_flush = NULL,
 	.gui_idle = &r100_gui_idle,
 	.mc_wait_for_idle = &r100_mc_wait_for_idle,
+	.get_allowed_info_register = radeon_invalid_get_allowed_info_register,
 	.gart = {
 		.tlb_flush = &r100_pci_gart_tlb_flush,
 		.get_page_entry = &r100_pci_gart_get_page_entry,
@@ -266,6 +272,7 @@
 	.mmio_hdp_flush = NULL,
 	.gui_idle = &r100_gui_idle,
 	.mc_wait_for_idle = &r100_mc_wait_for_idle,
+	.get_allowed_info_register = radeon_invalid_get_allowed_info_register,
 	.gart = {
 		.tlb_flush = &r100_pci_gart_tlb_flush,
 		.get_page_entry = &r100_pci_gart_get_page_entry,
@@ -361,6 +368,7 @@
 	.mmio_hdp_flush = NULL,
 	.gui_idle = &r100_gui_idle,
 	.mc_wait_for_idle = &r300_mc_wait_for_idle,
+	.get_allowed_info_register = radeon_invalid_get_allowed_info_register,
 	.gart = {
 		.tlb_flush = &r100_pci_gart_tlb_flush,
 		.get_page_entry = &r100_pci_gart_get_page_entry,
@@ -428,6 +436,7 @@
 	.mmio_hdp_flush = NULL,
 	.gui_idle = &r100_gui_idle,
 	.mc_wait_for_idle = &r300_mc_wait_for_idle,
+	.get_allowed_info_register = radeon_invalid_get_allowed_info_register,
 	.gart = {
 		.tlb_flush = &rv370_pcie_gart_tlb_flush,
 		.get_page_entry = &rv370_pcie_gart_get_page_entry,
@@ -495,6 +504,7 @@
 	.mmio_hdp_flush = NULL,
 	.gui_idle = &r100_gui_idle,
 	.mc_wait_for_idle = &r300_mc_wait_for_idle,
+	.get_allowed_info_register = radeon_invalid_get_allowed_info_register,
 	.gart = {
 		.tlb_flush = &rv370_pcie_gart_tlb_flush,
 		.get_page_entry = &rv370_pcie_gart_get_page_entry,
@@ -562,6 +572,7 @@
 	.mmio_hdp_flush = NULL,
 	.gui_idle = &r100_gui_idle,
 	.mc_wait_for_idle = &rs400_mc_wait_for_idle,
+	.get_allowed_info_register = radeon_invalid_get_allowed_info_register,
 	.gart = {
 		.tlb_flush = &rs400_gart_tlb_flush,
 		.get_page_entry = &rs400_gart_get_page_entry,
@@ -629,6 +640,7 @@
 	.mmio_hdp_flush = NULL,
 	.gui_idle = &r100_gui_idle,
 	.mc_wait_for_idle = &rs600_mc_wait_for_idle,
+	.get_allowed_info_register = radeon_invalid_get_allowed_info_register,
 	.gart = {
 		.tlb_flush = &rs600_gart_tlb_flush,
 		.get_page_entry = &rs600_gart_get_page_entry,
@@ -696,6 +708,7 @@
 	.mmio_hdp_flush = NULL,
 	.gui_idle = &r100_gui_idle,
 	.mc_wait_for_idle = &rs690_mc_wait_for_idle,
+	.get_allowed_info_register = radeon_invalid_get_allowed_info_register,
 	.gart = {
 		.tlb_flush = &rs400_gart_tlb_flush,
 		.get_page_entry = &rs400_gart_get_page_entry,
@@ -763,6 +776,7 @@
 	.mmio_hdp_flush = NULL,
 	.gui_idle = &r100_gui_idle,
 	.mc_wait_for_idle = &rv515_mc_wait_for_idle,
+	.get_allowed_info_register = radeon_invalid_get_allowed_info_register,
 	.gart = {
 		.tlb_flush = &rv370_pcie_gart_tlb_flush,
 		.get_page_entry = &rv370_pcie_gart_get_page_entry,
@@ -830,6 +844,7 @@
 	.mmio_hdp_flush = NULL,
 	.gui_idle = &r100_gui_idle,
 	.mc_wait_for_idle = &r520_mc_wait_for_idle,
+	.get_allowed_info_register = radeon_invalid_get_allowed_info_register,
 	.gart = {
 		.tlb_flush = &rv370_pcie_gart_tlb_flush,
 		.get_page_entry = &rv370_pcie_gart_get_page_entry,
@@ -925,6 +940,7 @@
 	.mc_wait_for_idle = &r600_mc_wait_for_idle,
 	.get_xclk = &r600_get_xclk,
 	.get_gpu_clock_counter = &r600_get_gpu_clock_counter,
+	.get_allowed_info_register = r600_get_allowed_info_register,
 	.gart = {
 		.tlb_flush = &r600_pcie_gart_tlb_flush,
 		.get_page_entry = &rs600_gart_get_page_entry,
@@ -1009,6 +1025,7 @@
 	.mc_wait_for_idle = &r600_mc_wait_for_idle,
 	.get_xclk = &r600_get_xclk,
 	.get_gpu_clock_counter = &r600_get_gpu_clock_counter,
+	.get_allowed_info_register = r600_get_allowed_info_register,
 	.gart = {
 		.tlb_flush = &r600_pcie_gart_tlb_flush,
 		.get_page_entry = &rs600_gart_get_page_entry,
@@ -1080,6 +1097,8 @@
 		.print_power_state = &rv6xx_dpm_print_power_state,
 		.debugfs_print_current_performance_level = &rv6xx_dpm_debugfs_print_current_performance_level,
 		.force_performance_level = &rv6xx_dpm_force_performance_level,
+		.get_current_sclk = &rv6xx_dpm_get_current_sclk,
+		.get_current_mclk = &rv6xx_dpm_get_current_mclk,
 	},
 	.pflip = {
 		.page_flip = &rs600_page_flip,
@@ -1099,6 +1118,7 @@
 	.mc_wait_for_idle = &r600_mc_wait_for_idle,
 	.get_xclk = &r600_get_xclk,
 	.get_gpu_clock_counter = &r600_get_gpu_clock_counter,
+	.get_allowed_info_register = r600_get_allowed_info_register,
 	.gart = {
 		.tlb_flush = &r600_pcie_gart_tlb_flush,
 		.get_page_entry = &rs600_gart_get_page_entry,
@@ -1170,6 +1190,8 @@
 		.print_power_state = &rs780_dpm_print_power_state,
 		.debugfs_print_current_performance_level = &rs780_dpm_debugfs_print_current_performance_level,
 		.force_performance_level = &rs780_dpm_force_performance_level,
+		.get_current_sclk = &rs780_dpm_get_current_sclk,
+		.get_current_mclk = &rs780_dpm_get_current_mclk,
 	},
 	.pflip = {
 		.page_flip = &rs600_page_flip,
@@ -1202,6 +1224,7 @@
 	.mc_wait_for_idle = &r600_mc_wait_for_idle,
 	.get_xclk = &rv770_get_xclk,
 	.get_gpu_clock_counter = &r600_get_gpu_clock_counter,
+	.get_allowed_info_register = r600_get_allowed_info_register,
 	.gart = {
 		.tlb_flush = &r600_pcie_gart_tlb_flush,
 		.get_page_entry = &rs600_gart_get_page_entry,
@@ -1274,6 +1297,8 @@
 		.debugfs_print_current_performance_level = &rv770_dpm_debugfs_print_current_performance_level,
 		.force_performance_level = &rv770_dpm_force_performance_level,
 		.vblank_too_short = &rv770_dpm_vblank_too_short,
+		.get_current_sclk = &rv770_dpm_get_current_sclk,
+		.get_current_mclk = &rv770_dpm_get_current_mclk,
 	},
 	.pflip = {
 		.page_flip = &rv770_page_flip,
@@ -1319,6 +1344,7 @@
 	.mc_wait_for_idle = &evergreen_mc_wait_for_idle,
 	.get_xclk = &rv770_get_xclk,
 	.get_gpu_clock_counter = &r600_get_gpu_clock_counter,
+	.get_allowed_info_register = evergreen_get_allowed_info_register,
 	.gart = {
 		.tlb_flush = &evergreen_pcie_gart_tlb_flush,
 		.get_page_entry = &rs600_gart_get_page_entry,
@@ -1391,6 +1417,8 @@
 		.debugfs_print_current_performance_level = &rv770_dpm_debugfs_print_current_performance_level,
 		.force_performance_level = &rv770_dpm_force_performance_level,
 		.vblank_too_short = &cypress_dpm_vblank_too_short,
+		.get_current_sclk = &rv770_dpm_get_current_sclk,
+		.get_current_mclk = &rv770_dpm_get_current_mclk,
 	},
 	.pflip = {
 		.page_flip = &evergreen_page_flip,
@@ -1410,6 +1438,7 @@
 	.mc_wait_for_idle = &evergreen_mc_wait_for_idle,
 	.get_xclk = &r600_get_xclk,
 	.get_gpu_clock_counter = &r600_get_gpu_clock_counter,
+	.get_allowed_info_register = evergreen_get_allowed_info_register,
 	.gart = {
 		.tlb_flush = &evergreen_pcie_gart_tlb_flush,
 		.get_page_entry = &rs600_gart_get_page_entry,
@@ -1481,6 +1510,8 @@
 		.print_power_state = &sumo_dpm_print_power_state,
 		.debugfs_print_current_performance_level = &sumo_dpm_debugfs_print_current_performance_level,
 		.force_performance_level = &sumo_dpm_force_performance_level,
+		.get_current_sclk = &sumo_dpm_get_current_sclk,
+		.get_current_mclk = &sumo_dpm_get_current_mclk,
 	},
 	.pflip = {
 		.page_flip = &evergreen_page_flip,
@@ -1500,6 +1531,7 @@
 	.mc_wait_for_idle = &evergreen_mc_wait_for_idle,
 	.get_xclk = &rv770_get_xclk,
 	.get_gpu_clock_counter = &r600_get_gpu_clock_counter,
+	.get_allowed_info_register = evergreen_get_allowed_info_register,
 	.gart = {
 		.tlb_flush = &evergreen_pcie_gart_tlb_flush,
 		.get_page_entry = &rs600_gart_get_page_entry,
@@ -1572,6 +1604,8 @@
 		.debugfs_print_current_performance_level = &btc_dpm_debugfs_print_current_performance_level,
 		.force_performance_level = &rv770_dpm_force_performance_level,
 		.vblank_too_short = &btc_dpm_vblank_too_short,
+		.get_current_sclk = &btc_dpm_get_current_sclk,
+		.get_current_mclk = &btc_dpm_get_current_mclk,
 	},
 	.pflip = {
 		.page_flip = &evergreen_page_flip,
@@ -1634,6 +1668,7 @@
 	.mc_wait_for_idle = &evergreen_mc_wait_for_idle,
 	.get_xclk = &rv770_get_xclk,
 	.get_gpu_clock_counter = &r600_get_gpu_clock_counter,
+	.get_allowed_info_register = cayman_get_allowed_info_register,
 	.gart = {
 		.tlb_flush = &cayman_pcie_gart_tlb_flush,
 		.get_page_entry = &rs600_gart_get_page_entry,
@@ -1717,6 +1752,8 @@
 		.debugfs_print_current_performance_level = &ni_dpm_debugfs_print_current_performance_level,
 		.force_performance_level = &ni_dpm_force_performance_level,
 		.vblank_too_short = &ni_dpm_vblank_too_short,
+		.get_current_sclk = &ni_dpm_get_current_sclk,
+		.get_current_mclk = &ni_dpm_get_current_mclk,
 	},
 	.pflip = {
 		.page_flip = &evergreen_page_flip,
@@ -1736,6 +1773,7 @@
 	.mc_wait_for_idle = &evergreen_mc_wait_for_idle,
 	.get_xclk = &r600_get_xclk,
 	.get_gpu_clock_counter = &r600_get_gpu_clock_counter,
+	.get_allowed_info_register = cayman_get_allowed_info_register,
 	.gart = {
 		.tlb_flush = &cayman_pcie_gart_tlb_flush,
 		.get_page_entry = &rs600_gart_get_page_entry,
@@ -1819,6 +1857,8 @@
 		.debugfs_print_current_performance_level = &trinity_dpm_debugfs_print_current_performance_level,
 		.force_performance_level = &trinity_dpm_force_performance_level,
 		.enable_bapm = &trinity_dpm_enable_bapm,
+		.get_current_sclk = &trinity_dpm_get_current_sclk,
+		.get_current_mclk = &trinity_dpm_get_current_mclk,
 	},
 	.pflip = {
 		.page_flip = &evergreen_page_flip,
@@ -1868,6 +1908,7 @@
 	.mc_wait_for_idle = &evergreen_mc_wait_for_idle,
 	.get_xclk = &si_get_xclk,
 	.get_gpu_clock_counter = &si_get_gpu_clock_counter,
+	.get_allowed_info_register = si_get_allowed_info_register,
 	.gart = {
 		.tlb_flush = &si_pcie_gart_tlb_flush,
 		.get_page_entry = &rs600_gart_get_page_entry,
@@ -1955,6 +1996,8 @@
 		.fan_ctrl_get_mode = &si_fan_ctrl_get_mode,
 		.get_fan_speed_percent = &si_fan_ctrl_get_fan_speed_percent,
 		.set_fan_speed_percent = &si_fan_ctrl_set_fan_speed_percent,
+		.get_current_sclk = &si_dpm_get_current_sclk,
+		.get_current_mclk = &si_dpm_get_current_mclk,
 	},
 	.pflip = {
 		.page_flip = &evergreen_page_flip,
@@ -2032,6 +2075,7 @@
 	.mc_wait_for_idle = &evergreen_mc_wait_for_idle,
 	.get_xclk = &cik_get_xclk,
 	.get_gpu_clock_counter = &cik_get_gpu_clock_counter,
+	.get_allowed_info_register = cik_get_allowed_info_register,
 	.gart = {
 		.tlb_flush = &cik_pcie_gart_tlb_flush,
 		.get_page_entry = &rs600_gart_get_page_entry,
@@ -2123,6 +2167,8 @@
 		.fan_ctrl_get_mode = &ci_fan_ctrl_get_mode,
 		.get_fan_speed_percent = &ci_fan_ctrl_get_fan_speed_percent,
 		.set_fan_speed_percent = &ci_fan_ctrl_set_fan_speed_percent,
+		.get_current_sclk = &ci_dpm_get_current_sclk,
+		.get_current_mclk = &ci_dpm_get_current_mclk,
 	},
 	.pflip = {
 		.page_flip = &evergreen_page_flip,
@@ -2142,6 +2188,7 @@
 	.mc_wait_for_idle = &evergreen_mc_wait_for_idle,
 	.get_xclk = &cik_get_xclk,
 	.get_gpu_clock_counter = &cik_get_gpu_clock_counter,
+	.get_allowed_info_register = cik_get_allowed_info_register,
 	.gart = {
 		.tlb_flush = &cik_pcie_gart_tlb_flush,
 		.get_page_entry = &rs600_gart_get_page_entry,
@@ -2229,6 +2276,8 @@
 		.force_performance_level = &kv_dpm_force_performance_level,
 		.powergate_uvd = &kv_dpm_powergate_uvd,
 		.enable_bapm = &kv_dpm_enable_bapm,
+		.get_current_sclk = &kv_dpm_get_current_sclk,
+		.get_current_mclk = &kv_dpm_get_current_mclk,
 	},
 	.pflip = {
 		.page_flip = &evergreen_page_flip,
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
index 72bdd3b..cf0a90b 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -384,6 +384,8 @@
 		      struct radeon_ring *ring);
 void r600_gfx_set_wptr(struct radeon_device *rdev,
 		       struct radeon_ring *ring);
+int r600_get_allowed_info_register(struct radeon_device *rdev,
+				   u32 reg, u32 *val);
 /* r600 irq */
 int r600_irq_process(struct radeon_device *rdev);
 int r600_irq_init(struct radeon_device *rdev);
@@ -433,6 +435,8 @@
 						       struct seq_file *m);
 int rv6xx_dpm_force_performance_level(struct radeon_device *rdev,
 				      enum radeon_dpm_forced_level level);
+u32 rv6xx_dpm_get_current_sclk(struct radeon_device *rdev);
+u32 rv6xx_dpm_get_current_mclk(struct radeon_device *rdev);
 /* rs780 dpm */
 int rs780_dpm_init(struct radeon_device *rdev);
 int rs780_dpm_enable(struct radeon_device *rdev);
@@ -449,6 +453,8 @@
 						       struct seq_file *m);
 int rs780_dpm_force_performance_level(struct radeon_device *rdev,
 				      enum radeon_dpm_forced_level level);
+u32 rs780_dpm_get_current_sclk(struct radeon_device *rdev);
+u32 rs780_dpm_get_current_mclk(struct radeon_device *rdev);
 
 /*
  * rv770,rv730,rv710,rv740
@@ -488,6 +494,8 @@
 int rv770_dpm_force_performance_level(struct radeon_device *rdev,
 				      enum radeon_dpm_forced_level level);
 bool rv770_dpm_vblank_too_short(struct radeon_device *rdev);
+u32 rv770_dpm_get_current_sclk(struct radeon_device *rdev);
+u32 rv770_dpm_get_current_mclk(struct radeon_device *rdev);
 
 /*
  * evergreen
@@ -540,6 +548,8 @@
 					unsigned num_gpu_pages,
 					struct reservation_object *resv);
 int evergreen_get_temp(struct radeon_device *rdev);
+int evergreen_get_allowed_info_register(struct radeon_device *rdev,
+					u32 reg, u32 *val);
 int sumo_get_temp(struct radeon_device *rdev);
 int tn_get_temp(struct radeon_device *rdev);
 int cypress_dpm_init(struct radeon_device *rdev);
@@ -563,6 +573,8 @@
 bool btc_dpm_vblank_too_short(struct radeon_device *rdev);
 void btc_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
 						     struct seq_file *m);
+u32 btc_dpm_get_current_sclk(struct radeon_device *rdev);
+u32 btc_dpm_get_current_mclk(struct radeon_device *rdev);
 int sumo_dpm_init(struct radeon_device *rdev);
 int sumo_dpm_enable(struct radeon_device *rdev);
 int sumo_dpm_late_enable(struct radeon_device *rdev);
@@ -581,6 +593,8 @@
 						      struct seq_file *m);
 int sumo_dpm_force_performance_level(struct radeon_device *rdev,
 				     enum radeon_dpm_forced_level level);
+u32 sumo_dpm_get_current_sclk(struct radeon_device *rdev);
+u32 sumo_dpm_get_current_mclk(struct radeon_device *rdev);
 
 /*
  * cayman
@@ -637,6 +651,8 @@
 			     struct radeon_ring *ring);
 void cayman_dma_set_wptr(struct radeon_device *rdev,
 			 struct radeon_ring *ring);
+int cayman_get_allowed_info_register(struct radeon_device *rdev,
+				     u32 reg, u32 *val);
 
 int ni_dpm_init(struct radeon_device *rdev);
 void ni_dpm_setup_asic(struct radeon_device *rdev);
@@ -655,6 +671,8 @@
 int ni_dpm_force_performance_level(struct radeon_device *rdev,
 				   enum radeon_dpm_forced_level level);
 bool ni_dpm_vblank_too_short(struct radeon_device *rdev);
+u32 ni_dpm_get_current_sclk(struct radeon_device *rdev);
+u32 ni_dpm_get_current_mclk(struct radeon_device *rdev);
 int trinity_dpm_init(struct radeon_device *rdev);
 int trinity_dpm_enable(struct radeon_device *rdev);
 int trinity_dpm_late_enable(struct radeon_device *rdev);
@@ -674,6 +692,8 @@
 int trinity_dpm_force_performance_level(struct radeon_device *rdev,
 					enum radeon_dpm_forced_level level);
 void trinity_dpm_enable_bapm(struct radeon_device *rdev, bool enable);
+u32 trinity_dpm_get_current_sclk(struct radeon_device *rdev);
+u32 trinity_dpm_get_current_mclk(struct radeon_device *rdev);
 
 /* DCE6 - SI */
 void dce6_bandwidth_update(struct radeon_device *rdev);
@@ -726,6 +746,8 @@
 uint64_t si_get_gpu_clock_counter(struct radeon_device *rdev);
 int si_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
 int si_get_temp(struct radeon_device *rdev);
+int si_get_allowed_info_register(struct radeon_device *rdev,
+				 u32 reg, u32 *val);
 int si_dpm_init(struct radeon_device *rdev);
 void si_dpm_setup_asic(struct radeon_device *rdev);
 int si_dpm_enable(struct radeon_device *rdev);
@@ -746,6 +768,8 @@
 						 u32 speed);
 u32 si_fan_ctrl_get_mode(struct radeon_device *rdev);
 void si_fan_ctrl_set_mode(struct radeon_device *rdev, u32 mode);
+u32 si_dpm_get_current_sclk(struct radeon_device *rdev);
+u32 si_dpm_get_current_mclk(struct radeon_device *rdev);
 
 /* DCE8 - CIK */
 void dce8_bandwidth_update(struct radeon_device *rdev);
@@ -841,6 +865,8 @@
 		       struct radeon_ring *ring);
 int ci_get_temp(struct radeon_device *rdev);
 int kv_get_temp(struct radeon_device *rdev);
+int cik_get_allowed_info_register(struct radeon_device *rdev,
+				  u32 reg, u32 *val);
 
 int ci_dpm_init(struct radeon_device *rdev);
 int ci_dpm_enable(struct radeon_device *rdev);
@@ -862,6 +888,8 @@
 				   enum radeon_dpm_forced_level level);
 bool ci_dpm_vblank_too_short(struct radeon_device *rdev);
 void ci_dpm_powergate_uvd(struct radeon_device *rdev, bool gate);
+u32 ci_dpm_get_current_sclk(struct radeon_device *rdev);
+u32 ci_dpm_get_current_mclk(struct radeon_device *rdev);
 
 int ci_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev,
 						 u32 *speed);
@@ -890,6 +918,8 @@
 				   enum radeon_dpm_forced_level level);
 void kv_dpm_powergate_uvd(struct radeon_device *rdev, bool gate);
 void kv_dpm_enable_bapm(struct radeon_device *rdev, bool enable);
+u32 kv_dpm_get_current_sclk(struct radeon_device *rdev);
+u32 kv_dpm_get_current_mclk(struct radeon_device *rdev);
 
 /* uvd v1.0 */
 uint32_t uvd_v1_0_get_rptr(struct radeon_device *rdev,
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index fc1b3f3..8f28524 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -845,6 +845,7 @@
 
 	radeon_link_encoder_connector(dev);
 
+	radeon_setup_mst_connector(dev);
 	return true;
 }
 
diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c
index b21ef69..48d49e6 100644
--- a/drivers/gpu/drm/radeon/radeon_audio.c
+++ b/drivers/gpu/drm/radeon/radeon_audio.c
@@ -520,16 +520,40 @@
 	struct radeon_device *rdev = encoder->dev->dev_private;
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+	struct drm_connector *connector;
+	struct radeon_connector *radeon_connector = NULL;
 	u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
 	struct hdmi_avi_infoframe frame;
 	int err;
 
+	list_for_each_entry(connector,
+		&encoder->dev->mode_config.connector_list, head) {
+		if (connector->encoder == encoder) {
+			radeon_connector = to_radeon_connector(connector);
+			break;
+		}
+	}
+
+	if (!radeon_connector) {
+		DRM_ERROR("Couldn't find encoder's connector\n");
+		return -ENOENT;
+	}
+
 	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
 	if (err < 0) {
 		DRM_ERROR("failed to setup AVI infoframe: %d\n", err);
 		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;
+	}
+
 	err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
 	if (err < 0) {
 		DRM_ERROR("failed to pack AVI infoframe: %d\n", err);
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index 27def67..7ffa7d5 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -27,6 +27,7 @@
 #include <drm/drm_edid.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_fb_helper.h>
+#include <drm/drm_dp_mst_helper.h>
 #include <drm/radeon_drm.h>
 #include "radeon.h"
 #include "radeon_audio.h"
@@ -34,12 +35,33 @@
 
 #include <linux/pm_runtime.h>
 
+static int radeon_dp_handle_hpd(struct drm_connector *connector)
+{
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+	int ret;
+
+	ret = radeon_dp_mst_check_status(radeon_connector);
+	if (ret == -EINVAL)
+		return 1;
+	return 0;
+}
 void radeon_connector_hotplug(struct drm_connector *connector)
 {
 	struct drm_device *dev = connector->dev;
 	struct radeon_device *rdev = dev->dev_private;
 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 
+	if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
+		struct radeon_connector_atom_dig *dig_connector =
+			radeon_connector->con_priv;
+
+		if (radeon_connector->is_mst_connector)
+			return;
+		if (dig_connector->is_mst) {
+			radeon_dp_handle_hpd(connector);
+			return;
+		}
+	}
 	/* bail if the connector does not have hpd pin, e.g.,
 	 * VGA, TV, etc.
 	 */
@@ -725,6 +747,30 @@
 		radeon_property_change_mode(&radeon_encoder->base);
 	}
 
+	if (property == rdev->mode_info.output_csc_property) {
+		if (connector->encoder)
+			radeon_encoder = to_radeon_encoder(connector->encoder);
+		else {
+			struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
+			radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector));
+		}
+
+		if (radeon_encoder->output_csc == val)
+			return 0;
+
+		radeon_encoder->output_csc = val;
+
+		if (connector->encoder->crtc) {
+			struct drm_crtc *crtc  = connector->encoder->crtc;
+			struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+			struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+
+			radeon_crtc->output_csc = radeon_encoder->output_csc;
+
+			(*crtc_funcs->load_lut)(crtc);
+		}
+	}
+
 	return 0;
 }
 
@@ -1585,6 +1631,9 @@
 	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
 	int r;
 
+	if (radeon_dig_connector->is_mst)
+		return connector_status_disconnected;
+
 	r = pm_runtime_get_sync(connector->dev->dev);
 	if (r < 0)
 		return connector_status_disconnected;
@@ -1643,12 +1692,21 @@
 		radeon_dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector);
 		if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) {
 			ret = connector_status_connected;
-			if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT)
+			if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) {
 				radeon_dp_getdpcd(radeon_connector);
+				r = radeon_dp_mst_probe(radeon_connector);
+				if (r == 1)
+					ret = connector_status_disconnected;
+			}
 		} else {
 			if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) {
-				if (radeon_dp_getdpcd(radeon_connector))
-					ret = connector_status_connected;
+				if (radeon_dp_getdpcd(radeon_connector)) {
+					r = radeon_dp_mst_probe(radeon_connector);
+					if (r == 1)
+						ret = connector_status_disconnected;
+					else
+						ret = connector_status_connected;
+				}
 			} else {
 				/* try non-aux ddc (DP to DVI/HDMI/etc. adapter) */
 				if (radeon_ddc_probe(radeon_connector, false))
@@ -1872,6 +1930,10 @@
 			drm_object_attach_property(&radeon_connector->base.base,
 						   dev->mode_config.scaling_mode_property,
 						   DRM_MODE_SCALE_NONE);
+			if (ASIC_IS_DCE5(rdev))
+				drm_object_attach_property(&radeon_connector->base.base,
+							   rdev->mode_info.output_csc_property,
+							   RADEON_OUTPUT_CSC_BYPASS);
 			break;
 		case DRM_MODE_CONNECTOR_DVII:
 		case DRM_MODE_CONNECTOR_DVID:
@@ -1904,6 +1966,10 @@
 				drm_object_attach_property(&radeon_connector->base.base,
 							   rdev->mode_info.audio_property,
 							   RADEON_AUDIO_AUTO);
+			if (ASIC_IS_DCE5(rdev))
+				drm_object_attach_property(&radeon_connector->base.base,
+							   rdev->mode_info.output_csc_property,
+							   RADEON_OUTPUT_CSC_BYPASS);
 
 			subpixel_order = SubPixelHorizontalRGB;
 			connector->interlace_allowed = true;
@@ -1950,6 +2016,10 @@
 				drm_object_attach_property(&radeon_connector->base.base,
 							   dev->mode_config.scaling_mode_property,
 							   DRM_MODE_SCALE_NONE);
+			if (ASIC_IS_DCE5(rdev))
+				drm_object_attach_property(&radeon_connector->base.base,
+							   rdev->mode_info.output_csc_property,
+							   RADEON_OUTPUT_CSC_BYPASS);
 			/* no HPD on analog connectors */
 			radeon_connector->hpd.hpd = RADEON_HPD_NONE;
 			connector->polled = DRM_CONNECTOR_POLL_CONNECT;
@@ -1972,6 +2042,10 @@
 				drm_object_attach_property(&radeon_connector->base.base,
 							   dev->mode_config.scaling_mode_property,
 							   DRM_MODE_SCALE_NONE);
+			if (ASIC_IS_DCE5(rdev))
+				drm_object_attach_property(&radeon_connector->base.base,
+							   rdev->mode_info.output_csc_property,
+							   RADEON_OUTPUT_CSC_BYPASS);
 			/* no HPD on analog connectors */
 			radeon_connector->hpd.hpd = RADEON_HPD_NONE;
 			connector->interlace_allowed = true;
@@ -2023,6 +2097,10 @@
 							      rdev->mode_info.load_detect_property,
 							      1);
 			}
+			if (ASIC_IS_DCE5(rdev))
+				drm_object_attach_property(&radeon_connector->base.base,
+							   rdev->mode_info.output_csc_property,
+							   RADEON_OUTPUT_CSC_BYPASS);
 			connector->interlace_allowed = true;
 			if (connector_type == DRM_MODE_CONNECTOR_DVII)
 				connector->doublescan_allowed = true;
@@ -2068,6 +2146,10 @@
 							   rdev->mode_info.audio_property,
 							   RADEON_AUDIO_AUTO);
 			}
+			if (ASIC_IS_DCE5(rdev))
+				drm_object_attach_property(&radeon_connector->base.base,
+							   rdev->mode_info.output_csc_property,
+							   RADEON_OUTPUT_CSC_BYPASS);
 			subpixel_order = SubPixelHorizontalRGB;
 			connector->interlace_allowed = true;
 			if (connector_type == DRM_MODE_CONNECTOR_HDMIB)
@@ -2116,6 +2198,10 @@
 							   rdev->mode_info.audio_property,
 							   RADEON_AUDIO_AUTO);
 			}
+			if (ASIC_IS_DCE5(rdev))
+				drm_object_attach_property(&radeon_connector->base.base,
+							   rdev->mode_info.output_csc_property,
+							   RADEON_OUTPUT_CSC_BYPASS);
 			connector->interlace_allowed = true;
 			/* in theory with a DP to VGA converter... */
 			connector->doublescan_allowed = false;
@@ -2352,3 +2438,27 @@
 	connector->display_info.subpixel_order = subpixel_order;
 	drm_connector_register(connector);
 }
+
+void radeon_setup_mst_connector(struct drm_device *dev)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	struct drm_connector *connector;
+	struct radeon_connector *radeon_connector;
+
+	if (!ASIC_IS_DCE5(rdev))
+		return;
+
+	if (radeon_mst == 0)
+		return;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		int ret;
+
+		radeon_connector = to_radeon_connector(connector);
+
+		if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort)
+			continue;
+
+		ret = radeon_dp_mst_init(radeon_connector);
+	}
+}
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index bd7519f..b7ca4c5 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -1442,6 +1442,11 @@
 		DRM_ERROR("registering gem debugfs failed (%d).\n", r);
 	}
 
+	r = radeon_mst_debugfs_init(rdev);
+	if (r) {
+		DRM_ERROR("registering mst debugfs failed (%d).\n", r);
+	}
+
 	if (rdev->flags & RADEON_IS_AGP && !rdev->accel_working) {
 		/* Acceleration not working on AGP card try again
 		 * with fallback to PCI or PCIE GART
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 913fafa..d2e9e9e 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -154,7 +154,7 @@
 	       (NI_GRPH_REGAMMA_MODE(NI_REGAMMA_BYPASS) |
 		NI_OVL_REGAMMA_MODE(NI_REGAMMA_BYPASS)));
 	WREG32(NI_OUTPUT_CSC_CONTROL + radeon_crtc->crtc_offset,
-	       (NI_OUTPUT_CSC_GRPH_MODE(NI_OUTPUT_CSC_BYPASS) |
+	       (NI_OUTPUT_CSC_GRPH_MODE(radeon_crtc->output_csc) |
 		NI_OUTPUT_CSC_OVL_MODE(NI_OUTPUT_CSC_BYPASS)));
 	/* XXX match this to the depth of the crtc fmt block, move to modeset? */
 	WREG32(0x6940 + radeon_crtc->crtc_offset, 0);
@@ -1382,6 +1382,13 @@
 	{ RADEON_FMT_DITHER_ENABLE, "on" },
 };
 
+static struct drm_prop_enum_list radeon_output_csc_enum_list[] =
+{	{ RADEON_OUTPUT_CSC_BYPASS, "bypass" },
+	{ RADEON_OUTPUT_CSC_TVRGB, "tvrgb" },
+	{ RADEON_OUTPUT_CSC_YCBCR601, "ycbcr601" },
+	{ RADEON_OUTPUT_CSC_YCBCR709, "ycbcr709" },
+};
+
 static int radeon_modeset_create_props(struct radeon_device *rdev)
 {
 	int sz;
@@ -1444,6 +1451,12 @@
 					 "dither",
 					 radeon_dither_enum_list, sz);
 
+	sz = ARRAY_SIZE(radeon_output_csc_enum_list);
+	rdev->mode_info.output_csc_property =
+		drm_property_create_enum(rdev->ddev, 0,
+					 "output_csc",
+					 radeon_output_csc_enum_list, sz);
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/radeon/radeon_dp_auxch.c b/drivers/gpu/drm/radeon/radeon_dp_auxch.c
new file mode 100644
index 0000000..bf1fecc
--- /dev/null
+++ b/drivers/gpu/drm/radeon/radeon_dp_auxch.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2015 Red Hat 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: Dave Airlie
+ */
+#include <drm/drmP.h>
+#include <drm/radeon_drm.h>
+#include "radeon.h"
+#include "nid.h"
+
+#define AUX_RX_ERROR_FLAGS (AUX_SW_RX_OVERFLOW |	     \
+			    AUX_SW_RX_HPD_DISCON |	     \
+			    AUX_SW_RX_PARTIAL_BYTE |	     \
+			    AUX_SW_NON_AUX_MODE |	     \
+			    AUX_SW_RX_MIN_COUNT_VIOL |	     \
+			    AUX_SW_RX_INVALID_STOP |	     \
+			    AUX_SW_RX_SYNC_INVALID_L |	     \
+			    AUX_SW_RX_SYNC_INVALID_H |	     \
+			    AUX_SW_RX_INVALID_START |	     \
+			    AUX_SW_RX_RECV_NO_DET |	     \
+			    AUX_SW_RX_RECV_INVALID_H |	     \
+			    AUX_SW_RX_RECV_INVALID_V)
+
+#define AUX_SW_REPLY_GET_BYTE_COUNT(x) (((x) >> 24) & 0x1f)
+
+#define BARE_ADDRESS_SIZE 3
+
+static const u32 aux_offset[] =
+{
+	0x6200 - 0x6200,
+	0x6250 - 0x6200,
+	0x62a0 - 0x6200,
+	0x6300 - 0x6200,
+	0x6350 - 0x6200,
+	0x63a0 - 0x6200,
+};
+
+ssize_t
+radeon_dp_aux_transfer_native(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
+{
+	struct radeon_i2c_chan *chan =
+		container_of(aux, struct radeon_i2c_chan, aux);
+	struct drm_device *dev = chan->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	int ret = 0, i;
+	uint32_t tmp, ack = 0;
+	int instance = chan->rec.i2c_id & 0xf;
+	u8 byte;
+	u8 *buf = msg->buffer;
+	int retry_count = 0;
+	int bytes;
+	int msize;
+	bool is_write = false;
+
+	if (WARN_ON(msg->size > 16))
+		return -E2BIG;
+
+	switch (msg->request & ~DP_AUX_I2C_MOT) {
+	case DP_AUX_NATIVE_WRITE:
+	case DP_AUX_I2C_WRITE:
+		is_write = true;
+		break;
+	case DP_AUX_NATIVE_READ:
+	case DP_AUX_I2C_READ:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* work out two sizes required */
+	msize = 0;
+	bytes = BARE_ADDRESS_SIZE;
+	if (msg->size) {
+		msize = msg->size - 1;
+		bytes++;
+		if (is_write)
+			bytes += msg->size;
+	}
+
+	mutex_lock(&chan->mutex);
+
+	/* switch the pad to aux mode */
+	tmp = RREG32(chan->rec.mask_clk_reg);
+	tmp |= (1 << 16);
+	WREG32(chan->rec.mask_clk_reg, tmp);
+
+	/* setup AUX control register with correct HPD pin */
+	tmp = RREG32(AUX_CONTROL + aux_offset[instance]);
+
+	tmp &= AUX_HPD_SEL(0x7);
+	tmp |= AUX_HPD_SEL(chan->rec.hpd);
+	tmp |= AUX_EN | AUX_LS_READ_EN;
+
+	WREG32(AUX_CONTROL + aux_offset[instance], tmp);
+
+	/* atombios appears to write this twice lets copy it */
+	WREG32(AUX_SW_CONTROL + aux_offset[instance],
+	       AUX_SW_WR_BYTES(bytes));
+	WREG32(AUX_SW_CONTROL + aux_offset[instance],
+	       AUX_SW_WR_BYTES(bytes));
+
+	/* write the data header into the registers */
+	/* request, addres, msg size */
+	byte = (msg->request << 4);
+	WREG32(AUX_SW_DATA + aux_offset[instance],
+	       AUX_SW_DATA_MASK(byte) | AUX_SW_AUTOINCREMENT_DISABLE);
+
+	byte = (msg->address >> 8) & 0xff;
+	WREG32(AUX_SW_DATA + aux_offset[instance],
+	       AUX_SW_DATA_MASK(byte));
+
+	byte = msg->address & 0xff;
+	WREG32(AUX_SW_DATA + aux_offset[instance],
+	       AUX_SW_DATA_MASK(byte));
+
+	byte = msize;
+	WREG32(AUX_SW_DATA + aux_offset[instance],
+	       AUX_SW_DATA_MASK(byte));
+
+	/* if we are writing - write the msg buffer */
+	if (is_write) {
+		for (i = 0; i < msg->size; i++) {
+			WREG32(AUX_SW_DATA + aux_offset[instance],
+			       AUX_SW_DATA_MASK(buf[i]));
+		}
+	}
+
+	/* clear the ACK */
+	WREG32(AUX_SW_INTERRUPT_CONTROL + aux_offset[instance], AUX_SW_DONE_ACK);
+
+	/* write the size and GO bits */
+	WREG32(AUX_SW_CONTROL + aux_offset[instance],
+	       AUX_SW_WR_BYTES(bytes) | AUX_SW_GO);
+
+	/* poll the status registers - TODO irq support */
+	do {
+		tmp = RREG32(AUX_SW_STATUS + aux_offset[instance]);
+		if (tmp & AUX_SW_DONE) {
+			break;
+		}
+		usleep_range(100, 200);
+	} while (retry_count++ < 1000);
+
+	if (retry_count >= 1000) {
+		DRM_ERROR("auxch hw never signalled completion, error %08x\n", tmp);
+		ret = -EIO;
+		goto done;
+	}
+
+	if (tmp & AUX_SW_RX_TIMEOUT) {
+		DRM_DEBUG_KMS("dp_aux_ch timed out\n");
+		ret = -ETIMEDOUT;
+		goto done;
+	}
+	if (tmp & AUX_RX_ERROR_FLAGS) {
+		DRM_DEBUG_KMS("dp_aux_ch flags not zero: %08x\n", tmp);
+		ret = -EIO;
+		goto done;
+	}
+
+	bytes = AUX_SW_REPLY_GET_BYTE_COUNT(tmp);
+	if (bytes) {
+		WREG32(AUX_SW_DATA + aux_offset[instance],
+		       AUX_SW_DATA_RW | AUX_SW_AUTOINCREMENT_DISABLE);
+
+		tmp = RREG32(AUX_SW_DATA + aux_offset[instance]);
+		ack = (tmp >> 8) & 0xff;
+
+		for (i = 0; i < bytes - 1; i++) {
+			tmp = RREG32(AUX_SW_DATA + aux_offset[instance]);
+			if (buf)
+				buf[i] = (tmp >> 8) & 0xff;
+		}
+		if (buf)
+			ret = bytes - 1;
+	}
+
+	WREG32(AUX_SW_INTERRUPT_CONTROL + aux_offset[instance], AUX_SW_DONE_ACK);
+
+	if (is_write)
+		ret = msg->size;
+done:
+	mutex_unlock(&chan->mutex);
+
+	if (ret >= 0)
+		msg->reply = ack >> 4;
+	return ret;
+}
diff --git a/drivers/gpu/drm/radeon/radeon_dp_mst.c b/drivers/gpu/drm/radeon/radeon_dp_mst.c
new file mode 100644
index 0000000..5952ff2
--- /dev/null
+++ b/drivers/gpu/drm/radeon/radeon_dp_mst.c
@@ -0,0 +1,782 @@
+
+#include <drm/drmP.h>
+#include <drm/drm_dp_mst_helper.h>
+#include <drm/drm_fb_helper.h>
+
+#include "radeon.h"
+#include "atom.h"
+#include "ni_reg.h"
+
+static struct radeon_encoder *radeon_dp_create_fake_mst_encoder(struct radeon_connector *connector);
+
+static int radeon_atom_set_enc_offset(int id)
+{
+	static const int offsets[] = { EVERGREEN_CRTC0_REGISTER_OFFSET,
+				       EVERGREEN_CRTC1_REGISTER_OFFSET,
+				       EVERGREEN_CRTC2_REGISTER_OFFSET,
+				       EVERGREEN_CRTC3_REGISTER_OFFSET,
+				       EVERGREEN_CRTC4_REGISTER_OFFSET,
+				       EVERGREEN_CRTC5_REGISTER_OFFSET,
+				       0x13830 - 0x7030 };
+
+	return offsets[id];
+}
+
+static int radeon_dp_mst_set_be_cntl(struct radeon_encoder *primary,
+				     struct radeon_encoder_mst *mst_enc,
+				     enum radeon_hpd_id hpd, bool enable)
+{
+	struct drm_device *dev = primary->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t reg;
+	int retries = 0;
+	uint32_t temp;
+
+	reg = RREG32(NI_DIG_BE_CNTL + primary->offset);
+
+	/* set MST mode */
+	reg &= ~NI_DIG_FE_DIG_MODE(7);
+	reg |= NI_DIG_FE_DIG_MODE(NI_DIG_MODE_DP_MST);
+
+	if (enable)
+		reg |= NI_DIG_FE_SOURCE_SELECT(1 << mst_enc->fe);
+	else
+		reg &= ~NI_DIG_FE_SOURCE_SELECT(1 << mst_enc->fe);
+
+	reg |= NI_DIG_HPD_SELECT(hpd);
+	DRM_DEBUG_KMS("writing 0x%08x 0x%08x\n", NI_DIG_BE_CNTL + primary->offset, reg);
+	WREG32(NI_DIG_BE_CNTL + primary->offset, reg);
+
+	if (enable) {
+		uint32_t offset = radeon_atom_set_enc_offset(mst_enc->fe);
+
+		do {
+			temp = RREG32(NI_DIG_FE_CNTL + offset);
+		} while ((temp & NI_DIG_SYMCLK_FE_ON) && retries++ < 10000);
+		if (retries == 10000)
+			DRM_ERROR("timed out waiting for FE %d %d\n", primary->offset, mst_enc->fe);
+	}
+	return 0;
+}
+
+static int radeon_dp_mst_set_stream_attrib(struct radeon_encoder *primary,
+					   int stream_number,
+					   int fe,
+					   int slots)
+{
+	struct drm_device *dev = primary->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	u32 temp, val;
+	int retries  = 0;
+	int satreg, satidx;
+
+	satreg = stream_number >> 1;
+	satidx = stream_number & 1;
+
+	temp = RREG32(NI_DP_MSE_SAT0 + satreg + primary->offset);
+
+	val = NI_DP_MSE_SAT_SLOT_COUNT0(slots) | NI_DP_MSE_SAT_SRC0(fe);
+
+	val <<= (16 * satidx);
+
+	temp &= ~(0xffff << (16 * satidx));
+
+	temp |= val;
+
+	DRM_DEBUG_KMS("writing 0x%08x 0x%08x\n", NI_DP_MSE_SAT0 + satreg + primary->offset, temp);
+	WREG32(NI_DP_MSE_SAT0 + satreg + primary->offset, temp);
+
+	WREG32(NI_DP_MSE_SAT_UPDATE + primary->offset, 1);
+
+	do {
+		temp = RREG32(NI_DP_MSE_SAT_UPDATE + primary->offset);
+	} while ((temp & 0x1) && retries++ < 10000);
+
+	if (retries == 10000)
+		DRM_ERROR("timed out waitin for SAT update %d\n", primary->offset);
+
+	/* MTP 16 ? */
+	return 0;
+}
+
+static int radeon_dp_mst_update_stream_attribs(struct radeon_connector *mst_conn,
+					       struct radeon_encoder *primary)
+{
+	struct drm_device *dev = mst_conn->base.dev;
+	struct stream_attribs new_attribs[6];
+	int i;
+	int idx = 0;
+	struct radeon_connector *radeon_connector;
+	struct drm_connector *connector;
+
+	memset(new_attribs, 0, sizeof(new_attribs));
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		struct radeon_encoder *subenc;
+		struct radeon_encoder_mst *mst_enc;
+
+		radeon_connector = to_radeon_connector(connector);
+		if (!radeon_connector->is_mst_connector)
+			continue;
+
+		if (radeon_connector->mst_port != mst_conn)
+			continue;
+
+		subenc = radeon_connector->mst_encoder;
+		mst_enc = subenc->enc_priv;
+
+		if (!mst_enc->enc_active)
+			continue;
+
+		new_attribs[idx].fe = mst_enc->fe;
+		new_attribs[idx].slots = drm_dp_mst_get_vcpi_slots(&mst_conn->mst_mgr, mst_enc->port);
+		idx++;
+	}
+
+	for (i = 0; i < idx; i++) {
+		if (new_attribs[i].fe != mst_conn->cur_stream_attribs[i].fe ||
+		    new_attribs[i].slots != mst_conn->cur_stream_attribs[i].slots) {
+			radeon_dp_mst_set_stream_attrib(primary, i, new_attribs[i].fe, new_attribs[i].slots);
+			mst_conn->cur_stream_attribs[i].fe = new_attribs[i].fe;
+			mst_conn->cur_stream_attribs[i].slots = new_attribs[i].slots;
+		}
+	}
+
+	for (i = idx; i < mst_conn->enabled_attribs; i++) {
+		radeon_dp_mst_set_stream_attrib(primary, i, 0, 0);
+		mst_conn->cur_stream_attribs[i].fe = 0;
+		mst_conn->cur_stream_attribs[i].slots = 0;
+	}
+	mst_conn->enabled_attribs = idx;
+	return 0;
+}
+
+static int radeon_dp_mst_set_vcp_size(struct radeon_encoder *mst, uint32_t x, uint32_t y)
+{
+	struct drm_device *dev = mst->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder_mst *mst_enc = mst->enc_priv;
+	uint32_t val, temp;
+	uint32_t offset = radeon_atom_set_enc_offset(mst_enc->fe);
+	int retries = 0;
+
+	val = NI_DP_MSE_RATE_X(x) | NI_DP_MSE_RATE_Y(y);
+
+	WREG32(NI_DP_MSE_RATE_CNTL + offset, val);
+
+	do {
+		temp = RREG32(NI_DP_MSE_RATE_UPDATE + offset);
+	} while ((temp & 0x1) && (retries++ < 10000));
+
+	if (retries >= 10000)
+		DRM_ERROR("timed out wait for rate cntl %d\n", mst_enc->fe);
+	return 0;
+}
+
+static int radeon_dp_mst_get_ddc_modes(struct drm_connector *connector)
+{
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+	struct radeon_connector *master = radeon_connector->mst_port;
+	struct edid *edid;
+	int ret = 0;
+
+	edid = drm_dp_mst_get_edid(connector, &master->mst_mgr, radeon_connector->port);
+	radeon_connector->edid = edid;
+	DRM_DEBUG_KMS("edid retrieved %p\n", edid);
+	if (radeon_connector->edid) {
+		drm_mode_connector_update_edid_property(&radeon_connector->base, radeon_connector->edid);
+		ret = drm_add_edid_modes(&radeon_connector->base, radeon_connector->edid);
+		drm_edid_to_eld(&radeon_connector->base, radeon_connector->edid);
+		return ret;
+	}
+	drm_mode_connector_update_edid_property(&radeon_connector->base, NULL);
+
+	return ret;
+}
+
+static int radeon_dp_mst_get_modes(struct drm_connector *connector)
+{
+	return radeon_dp_mst_get_ddc_modes(connector);
+}
+
+static enum drm_mode_status
+radeon_dp_mst_mode_valid(struct drm_connector *connector,
+			struct drm_display_mode *mode)
+{
+	/* TODO - validate mode against available PBN for link */
+	if (mode->clock < 10000)
+		return MODE_CLOCK_LOW;
+
+	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
+		return MODE_H_ILLEGAL;
+
+	return MODE_OK;
+}
+
+struct drm_encoder *radeon_mst_best_encoder(struct drm_connector *connector)
+{
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+
+	return &radeon_connector->mst_encoder->base;
+}
+
+static const struct drm_connector_helper_funcs radeon_dp_mst_connector_helper_funcs = {
+	.get_modes = radeon_dp_mst_get_modes,
+	.mode_valid = radeon_dp_mst_mode_valid,
+	.best_encoder = radeon_mst_best_encoder,
+};
+
+static enum drm_connector_status
+radeon_dp_mst_detect(struct drm_connector *connector, bool force)
+{
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+	struct radeon_connector *master = radeon_connector->mst_port;
+
+	return drm_dp_mst_detect_port(connector, &master->mst_mgr, radeon_connector->port);
+}
+
+static void
+radeon_dp_mst_connector_destroy(struct drm_connector *connector)
+{
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+	struct radeon_encoder *radeon_encoder = radeon_connector->mst_encoder;
+
+	drm_encoder_cleanup(&radeon_encoder->base);
+	kfree(radeon_encoder);
+	drm_connector_cleanup(connector);
+	kfree(radeon_connector);
+}
+
+static void radeon_connector_dpms(struct drm_connector *connector, int mode)
+{
+	DRM_DEBUG_KMS("\n");
+}
+
+static const struct drm_connector_funcs radeon_dp_mst_connector_funcs = {
+	.dpms = radeon_connector_dpms,
+	.detect = radeon_dp_mst_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = radeon_dp_mst_connector_destroy,
+};
+
+static struct drm_connector *radeon_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
+							 struct drm_dp_mst_port *port,
+							 const char *pathprop)
+{
+	struct radeon_connector *master = container_of(mgr, struct radeon_connector, mst_mgr);
+	struct drm_device *dev = master->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_connector *radeon_connector;
+	struct drm_connector *connector;
+
+	radeon_connector = kzalloc(sizeof(*radeon_connector), GFP_KERNEL);
+	if (!radeon_connector)
+		return NULL;
+
+	radeon_connector->is_mst_connector = true;
+	connector = &radeon_connector->base;
+	radeon_connector->port = port;
+	radeon_connector->mst_port = master;
+	DRM_DEBUG_KMS("\n");
+
+	drm_connector_init(dev, connector, &radeon_dp_mst_connector_funcs, DRM_MODE_CONNECTOR_DisplayPort);
+	drm_connector_helper_add(connector, &radeon_dp_mst_connector_helper_funcs);
+	radeon_connector->mst_encoder = radeon_dp_create_fake_mst_encoder(master);
+
+	drm_object_attach_property(&connector->base, dev->mode_config.path_property, 0);
+	drm_mode_connector_set_path_property(connector, pathprop);
+	drm_reinit_primary_mode_group(dev);
+
+	mutex_lock(&dev->mode_config.mutex);
+	radeon_fb_add_connector(rdev, connector);
+	mutex_unlock(&dev->mode_config.mutex);
+
+	drm_connector_register(connector);
+	return connector;
+}
+
+static void radeon_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
+					    struct drm_connector *connector)
+{
+	struct radeon_connector *master = container_of(mgr, struct radeon_connector, mst_mgr);
+	struct drm_device *dev = master->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+
+	drm_connector_unregister(connector);
+	/* need to nuke the connector */
+	mutex_lock(&dev->mode_config.mutex);
+	/* dpms off */
+	radeon_fb_remove_connector(rdev, connector);
+
+	drm_connector_cleanup(connector);
+	mutex_unlock(&dev->mode_config.mutex);
+	drm_reinit_primary_mode_group(dev);
+
+
+	kfree(connector);
+	DRM_DEBUG_KMS("\n");
+}
+
+static void radeon_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr)
+{
+	struct radeon_connector *master = container_of(mgr, struct radeon_connector, mst_mgr);
+	struct drm_device *dev = master->base.dev;
+
+	drm_kms_helper_hotplug_event(dev);
+}
+
+struct drm_dp_mst_topology_cbs mst_cbs = {
+	.add_connector = radeon_dp_add_mst_connector,
+	.destroy_connector = radeon_dp_destroy_mst_connector,
+	.hotplug = radeon_dp_mst_hotplug,
+};
+
+struct radeon_connector *radeon_mst_find_connector(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct drm_connector *connector;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+		if (!connector->encoder)
+			continue;
+		if (!radeon_connector->is_mst_connector)
+			continue;
+
+		DRM_DEBUG_KMS("checking %p vs %p\n", connector->encoder, encoder);
+		if (connector->encoder == encoder)
+			return radeon_connector;
+	}
+	return NULL;
+}
+
+void radeon_dp_mst_prepare_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
+{
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(radeon_crtc->encoder);
+	struct radeon_encoder_mst *mst_enc = radeon_encoder->enc_priv;
+	struct radeon_connector *radeon_connector = radeon_mst_find_connector(&radeon_encoder->base);
+	int dp_clock;
+	struct radeon_connector_atom_dig *dig_connector = mst_enc->connector->con_priv;
+
+	if (radeon_connector) {
+		radeon_connector->pixelclock_for_modeset = mode->clock;
+		if (radeon_connector->base.display_info.bpc)
+			radeon_crtc->bpc = radeon_connector->base.display_info.bpc;
+		else
+			radeon_crtc->bpc = 8;
+	}
+
+	DRM_DEBUG_KMS("dp_clock %p %d\n", dig_connector, dig_connector->dp_clock);
+	dp_clock = dig_connector->dp_clock;
+	radeon_crtc->ss_enabled =
+		radeon_atombios_get_asic_ss_info(rdev, &radeon_crtc->ss,
+						 ASIC_INTERNAL_SS_ON_DP,
+						 dp_clock);
+}
+
+static void
+radeon_mst_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder, *primary;
+	struct radeon_encoder_mst *mst_enc;
+	struct radeon_encoder_atom_dig *dig_enc;
+	struct radeon_connector *radeon_connector;
+	struct drm_crtc *crtc;
+	struct radeon_crtc *radeon_crtc;
+	int ret, slots;
+
+	if (!ASIC_IS_DCE5(rdev)) {
+		DRM_ERROR("got mst dpms on non-DCE5\n");
+		return;
+	}
+
+	radeon_connector = radeon_mst_find_connector(encoder);
+	if (!radeon_connector)
+		return;
+
+	radeon_encoder = to_radeon_encoder(encoder);
+
+	mst_enc = radeon_encoder->enc_priv;
+
+	primary = mst_enc->primary;
+
+	dig_enc = primary->enc_priv;
+
+	crtc = encoder->crtc;
+	DRM_DEBUG_KMS("got connector %d\n", dig_enc->active_mst_links);
+
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+		dig_enc->active_mst_links++;
+
+		radeon_crtc = to_radeon_crtc(crtc);
+
+		if (dig_enc->active_mst_links == 1) {
+			mst_enc->fe = dig_enc->dig_encoder;
+			mst_enc->fe_from_be = true;
+			atombios_set_mst_encoder_crtc_source(encoder, mst_enc->fe);
+
+			atombios_dig_encoder_setup(&primary->base, ATOM_ENCODER_CMD_SETUP, 0);
+			atombios_dig_transmitter_setup2(&primary->base, ATOM_TRANSMITTER_ACTION_ENABLE,
+							0, 0, dig_enc->dig_encoder);
+
+			if (radeon_dp_needs_link_train(mst_enc->connector) ||
+			    dig_enc->active_mst_links == 1) {
+				radeon_dp_link_train(&primary->base, &mst_enc->connector->base);
+			}
+
+		} else {
+			mst_enc->fe = radeon_atom_pick_dig_encoder(encoder, radeon_crtc->crtc_id);
+			if (mst_enc->fe == -1)
+				DRM_ERROR("failed to get frontend for dig encoder\n");
+			mst_enc->fe_from_be = false;
+			atombios_set_mst_encoder_crtc_source(encoder, mst_enc->fe);
+		}
+
+		DRM_DEBUG_KMS("dig encoder is %d %d %d\n", dig_enc->dig_encoder,
+			      dig_enc->linkb, radeon_crtc->crtc_id);
+
+		ret = drm_dp_mst_allocate_vcpi(&radeon_connector->mst_port->mst_mgr,
+					       radeon_connector->port,
+					       mst_enc->pbn, &slots);
+		ret = drm_dp_update_payload_part1(&radeon_connector->mst_port->mst_mgr);
+
+		radeon_dp_mst_set_be_cntl(primary, mst_enc,
+					  radeon_connector->mst_port->hpd.hpd, true);
+
+		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);
+
+		atombios_dig_encoder_setup2(&primary->base, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0,
+					    mst_enc->fe);
+		ret = drm_dp_check_act_status(&radeon_connector->mst_port->mst_mgr);
+
+		ret = drm_dp_update_payload_part2(&radeon_connector->mst_port->mst_mgr);
+
+		break;
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+	case DRM_MODE_DPMS_OFF:
+		DRM_ERROR("DPMS OFF %d\n", dig_enc->active_mst_links);
+
+		if (!mst_enc->enc_active)
+			return;
+
+		drm_dp_mst_reset_vcpi_slots(&radeon_connector->mst_port->mst_mgr, mst_enc->port);
+		ret = drm_dp_update_payload_part1(&radeon_connector->mst_port->mst_mgr);
+
+		drm_dp_check_act_status(&radeon_connector->mst_port->mst_mgr);
+		/* and this can also fail */
+		drm_dp_update_payload_part2(&radeon_connector->mst_port->mst_mgr);
+
+		drm_dp_mst_deallocate_vcpi(&radeon_connector->mst_port->mst_mgr, mst_enc->port);
+
+		mst_enc->enc_active = false;
+		radeon_dp_mst_update_stream_attribs(radeon_connector->mst_port, primary);
+
+		radeon_dp_mst_set_be_cntl(primary, mst_enc,
+					  radeon_connector->mst_port->hpd.hpd, false);
+		atombios_dig_encoder_setup2(&primary->base, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0,
+					    mst_enc->fe);
+
+		if (!mst_enc->fe_from_be)
+			radeon_atom_release_dig_encoder(rdev, mst_enc->fe);
+
+		mst_enc->fe_from_be = false;
+		dig_enc->active_mst_links--;
+		if (dig_enc->active_mst_links == 0) {
+			/* drop link */
+		}
+
+		break;
+	}
+
+}
+
+static bool radeon_mst_mode_fixup(struct drm_encoder *encoder,
+				   const struct drm_display_mode *mode,
+				   struct drm_display_mode *adjusted_mode)
+{
+	struct radeon_encoder_mst *mst_enc;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	int bpp = 24;
+
+	mst_enc = radeon_encoder->enc_priv;
+
+	mst_enc->pbn = drm_dp_calc_pbn_mode(adjusted_mode->clock, bpp);
+
+	mst_enc->primary->active_device = mst_enc->primary->devices & mst_enc->connector->devices;
+	DRM_DEBUG_KMS("setting active device to %08x from %08x %08x for encoder %d\n",
+		      mst_enc->primary->active_device, mst_enc->primary->devices,
+		      mst_enc->connector->devices, mst_enc->primary->base.encoder_type);
+
+
+	drm_mode_set_crtcinfo(adjusted_mode, 0);
+	{
+	  struct radeon_connector_atom_dig *dig_connector;
+
+	  dig_connector = mst_enc->connector->con_priv;
+	  dig_connector->dp_lane_count = drm_dp_max_lane_count(dig_connector->dpcd);
+	  dig_connector->dp_clock = radeon_dp_get_max_link_rate(&mst_enc->connector->base,
+								dig_connector->dpcd);
+	  DRM_DEBUG_KMS("dig clock %p %d %d\n", dig_connector,
+			dig_connector->dp_lane_count, dig_connector->dp_clock);
+	}
+	return true;
+}
+
+static void radeon_mst_encoder_prepare(struct drm_encoder *encoder)
+{
+	struct radeon_connector *radeon_connector;
+	struct radeon_encoder *radeon_encoder, *primary;
+	struct radeon_encoder_mst *mst_enc;
+	struct radeon_encoder_atom_dig *dig_enc;
+
+	radeon_connector = radeon_mst_find_connector(encoder);
+	if (!radeon_connector) {
+		DRM_DEBUG_KMS("failed to find connector %p\n", encoder);
+		return;
+	}
+	radeon_encoder = to_radeon_encoder(encoder);
+
+	radeon_mst_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
+
+	mst_enc = radeon_encoder->enc_priv;
+
+	primary = mst_enc->primary;
+
+	dig_enc = primary->enc_priv;
+
+	mst_enc->port = radeon_connector->port;
+
+	if (dig_enc->dig_encoder == -1) {
+		dig_enc->dig_encoder = radeon_atom_pick_dig_encoder(&primary->base, -1);
+		primary->offset = radeon_atom_set_enc_offset(dig_enc->dig_encoder);
+		atombios_set_mst_encoder_crtc_source(encoder, dig_enc->dig_encoder);
+
+
+	}
+	DRM_DEBUG_KMS("%d %d\n", dig_enc->dig_encoder, primary->offset);
+}
+
+static void
+radeon_mst_encoder_mode_set(struct drm_encoder *encoder,
+			     struct drm_display_mode *mode,
+			     struct drm_display_mode *adjusted_mode)
+{
+	DRM_DEBUG_KMS("\n");
+}
+
+static void radeon_mst_encoder_commit(struct drm_encoder *encoder)
+{
+	radeon_mst_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
+	DRM_DEBUG_KMS("\n");
+}
+
+static const struct drm_encoder_helper_funcs radeon_mst_helper_funcs = {
+	.dpms = radeon_mst_encoder_dpms,
+	.mode_fixup = radeon_mst_mode_fixup,
+	.prepare = radeon_mst_encoder_prepare,
+	.mode_set = radeon_mst_encoder_mode_set,
+	.commit = radeon_mst_encoder_commit,
+};
+
+void radeon_dp_mst_encoder_destroy(struct drm_encoder *encoder)
+{
+	drm_encoder_cleanup(encoder);
+	kfree(encoder);
+}
+
+static const struct drm_encoder_funcs radeon_dp_mst_enc_funcs = {
+	.destroy = radeon_dp_mst_encoder_destroy,
+};
+
+static struct radeon_encoder *
+radeon_dp_create_fake_mst_encoder(struct radeon_connector *connector)
+{
+	struct drm_device *dev = connector->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder;
+	struct radeon_encoder_mst *mst_enc;
+	struct drm_encoder *encoder;
+	struct drm_connector_helper_funcs *connector_funcs = connector->base.helper_private;
+	struct drm_encoder *enc_master = connector_funcs->best_encoder(&connector->base);
+
+	DRM_DEBUG_KMS("enc master is %p\n", enc_master);
+	radeon_encoder = kzalloc(sizeof(*radeon_encoder), GFP_KERNEL);
+	if (!radeon_encoder)
+		return NULL;
+
+	radeon_encoder->enc_priv = kzalloc(sizeof(*mst_enc), GFP_KERNEL);
+	if (!radeon_encoder->enc_priv) {
+		kfree(radeon_encoder);
+		return NULL;
+	}
+	encoder = &radeon_encoder->base;
+	switch (rdev->num_crtc) {
+	case 1:
+		encoder->possible_crtcs = 0x1;
+		break;
+	case 2:
+	default:
+		encoder->possible_crtcs = 0x3;
+		break;
+	case 4:
+		encoder->possible_crtcs = 0xf;
+		break;
+	case 6:
+		encoder->possible_crtcs = 0x3f;
+		break;
+	}
+
+	drm_encoder_init(dev, &radeon_encoder->base, &radeon_dp_mst_enc_funcs,
+			 DRM_MODE_ENCODER_DPMST);
+	drm_encoder_helper_add(encoder, &radeon_mst_helper_funcs);
+
+	mst_enc = radeon_encoder->enc_priv;
+	mst_enc->connector = connector;
+	mst_enc->primary = to_radeon_encoder(enc_master);
+	radeon_encoder->is_mst_encoder = true;
+	return radeon_encoder;
+}
+
+int
+radeon_dp_mst_init(struct radeon_connector *radeon_connector)
+{
+	struct drm_device *dev = radeon_connector->base.dev;
+
+	if (!radeon_connector->ddc_bus->has_aux)
+		return 0;
+
+	radeon_connector->mst_mgr.cbs = &mst_cbs;
+	return drm_dp_mst_topology_mgr_init(&radeon_connector->mst_mgr, dev->dev,
+					    &radeon_connector->ddc_bus->aux, 16, 6,
+					    radeon_connector->base.base.id);
+}
+
+int
+radeon_dp_mst_probe(struct radeon_connector *radeon_connector)
+{
+	struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
+	int ret;
+	u8 msg[1];
+
+	if (dig_connector->dpcd[DP_DPCD_REV] < 0x12)
+		return 0;
+
+	ret = drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_MSTM_CAP, msg,
+			       1);
+	if (ret) {
+		if (msg[0] & DP_MST_CAP) {
+			DRM_DEBUG_KMS("Sink is MST capable\n");
+			dig_connector->is_mst = true;
+		} else {
+			DRM_DEBUG_KMS("Sink is not MST capable\n");
+			dig_connector->is_mst = false;
+		}
+
+	}
+	drm_dp_mst_topology_mgr_set_mst(&radeon_connector->mst_mgr,
+					dig_connector->is_mst);
+	return dig_connector->is_mst;
+}
+
+int
+radeon_dp_mst_check_status(struct radeon_connector *radeon_connector)
+{
+	struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
+	int retry;
+
+	if (dig_connector->is_mst) {
+		u8 esi[16] = { 0 };
+		int dret;
+		int ret = 0;
+		bool handled;
+
+		dret = drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux,
+				       DP_SINK_COUNT_ESI, esi, 8);
+go_again:
+		if (dret == 8) {
+			DRM_DEBUG_KMS("got esi %02x %02x %02x\n", esi[0], esi[1], esi[2]);
+			ret = drm_dp_mst_hpd_irq(&radeon_connector->mst_mgr, esi, &handled);
+
+			if (handled) {
+				for (retry = 0; retry < 3; retry++) {
+					int wret;
+					wret = drm_dp_dpcd_write(&radeon_connector->ddc_bus->aux,
+								 DP_SINK_COUNT_ESI + 1, &esi[1], 3);
+					if (wret == 3)
+						break;
+				}
+
+				dret = drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux,
+							DP_SINK_COUNT_ESI, esi, 8);
+				if (dret == 8) {
+					DRM_DEBUG_KMS("got esi2 %02x %02x %02x\n", esi[0], esi[1], esi[2]);
+					goto go_again;
+				}
+			} else
+				ret = 0;
+
+			return ret;
+		} else {
+			DRM_DEBUG_KMS("failed to get ESI - device may have failed %d\n", ret);
+			dig_connector->is_mst = false;
+			drm_dp_mst_topology_mgr_set_mst(&radeon_connector->mst_mgr,
+							dig_connector->is_mst);
+			/* send a hotplug event */
+		}
+	}
+	return -EINVAL;
+}
+
+#if defined(CONFIG_DEBUG_FS)
+
+static int radeon_debugfs_mst_info(struct seq_file *m, void *data)
+{
+	struct drm_info_node *node = (struct drm_info_node *)m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct drm_connector *connector;
+	struct radeon_connector *radeon_connector;
+	struct radeon_connector_atom_dig *dig_connector;
+	int i;
+
+	drm_modeset_lock_all(dev);
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort)
+			continue;
+
+		radeon_connector = to_radeon_connector(connector);
+		dig_connector = radeon_connector->con_priv;
+		if (radeon_connector->is_mst_connector)
+			continue;
+		if (!dig_connector->is_mst)
+			continue;
+		drm_dp_mst_dump_topology(m, &radeon_connector->mst_mgr);
+
+		for (i = 0; i < radeon_connector->enabled_attribs; i++)
+			seq_printf(m, "attrib %d: %d %d\n", i,
+				   radeon_connector->cur_stream_attribs[i].fe,
+				   radeon_connector->cur_stream_attribs[i].slots);
+	}
+	drm_modeset_unlock_all(dev);
+	return 0;
+}
+
+static struct drm_info_list radeon_debugfs_mst_list[] = {
+	{"radeon_mst_info", &radeon_debugfs_mst_info, 0, NULL},
+};
+#endif
+
+int radeon_mst_debugfs_init(struct radeon_device *rdev)
+{
+#if defined(CONFIG_DEBUG_FS)
+	return radeon_debugfs_add_files(rdev, radeon_debugfs_mst_list, 1);
+#endif
+	return 0;
+}
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 5d684be..d688f6c 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -190,6 +190,8 @@
 int radeon_use_pflipirq = 2;
 int radeon_bapm = -1;
 int radeon_backlight = -1;
+int radeon_auxch = -1;
+int radeon_mst = 0;
 
 MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
 module_param_named(no_wb, radeon_no_wb, int, 0444);
@@ -239,7 +241,7 @@
 MODULE_PARM_DESC(msi, "MSI support (1 = enable, 0 = disable, -1 = auto)");
 module_param_named(msi, radeon_msi, int, 0444);
 
-MODULE_PARM_DESC(lockup_timeout, "GPU lockup timeout in ms (defaul 10000 = 10 seconds, 0 = disable)");
+MODULE_PARM_DESC(lockup_timeout, "GPU lockup timeout in ms (default 10000 = 10 seconds, 0 = disable)");
 module_param_named(lockup_timeout, radeon_lockup_timeout, int, 0444);
 
 MODULE_PARM_DESC(fastfb, "Direct FB access for IGP chips (0 = disable, 1 = enable)");
@@ -275,6 +277,12 @@
 MODULE_PARM_DESC(backlight, "backlight support (1 = enable, 0 = disable, -1 = auto)");
 module_param_named(backlight, radeon_backlight, int, 0444);
 
+MODULE_PARM_DESC(auxch, "Use native auxch experimental support (1 = enable, 0 = disable, -1 = auto)");
+module_param_named(auxch, radeon_auxch, int, 0444);
+
+MODULE_PARM_DESC(mst, "DisplayPort MST experimental support (1 = enable, 0 = disable)");
+module_param_named(mst, radeon_mst, int, 0444);
+
 static struct pci_device_id pciidlist[] = {
 	radeon_PCI_IDS
 };
diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c
index 3a29703..ef99917 100644
--- a/drivers/gpu/drm/radeon/radeon_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_encoders.c
@@ -247,7 +247,16 @@
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 		radeon_connector = to_radeon_connector(connector);
-		if (radeon_encoder->active_device & radeon_connector->devices)
+		if (radeon_encoder->is_mst_encoder) {
+			struct radeon_encoder_mst *mst_enc;
+
+			if (!radeon_connector->is_mst_connector)
+				continue;
+
+			mst_enc = radeon_encoder->enc_priv;
+			if (mst_enc->connector == radeon_connector->mst_port)
+				return connector;
+		} else if (radeon_encoder->active_device & radeon_connector->devices)
 			return connector;
 	}
 	return NULL;
@@ -393,6 +402,9 @@
 	case DRM_MODE_CONNECTOR_DVID:
 	case DRM_MODE_CONNECTOR_HDMIA:
 	case DRM_MODE_CONNECTOR_DisplayPort:
+		if (radeon_connector->is_mst_connector)
+			return false;
+
 		dig_connector = radeon_connector->con_priv;
 		if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
 		    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index ea276ff..aeb6767 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -257,6 +257,7 @@
 	}
 
 	info->par = rfbdev;
+	info->skip_vt_switch = true;
 
 	ret = radeon_framebuffer_init(rdev->ddev, &rfbdev->rfb, &mode_cmd, gobj);
 	if (ret) {
@@ -434,3 +435,13 @@
 		return true;
 	return false;
 }
+
+void radeon_fb_add_connector(struct radeon_device *rdev, struct drm_connector *connector)
+{
+	drm_fb_helper_add_one_connector(&rdev->mode_info.rfbdev->helper, connector);
+}
+
+void radeon_fb_remove_connector(struct radeon_device *rdev, struct drm_connector *connector)
+{
+	drm_fb_helper_remove_one_connector(&rdev->mode_info.rfbdev->helper, connector);
+}
diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c
index 00fc597..7162c93 100644
--- a/drivers/gpu/drm/radeon/radeon_irq_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c
@@ -87,6 +87,20 @@
 	drm_helper_hpd_irq_event(dev);
 }
 
+static void radeon_dp_work_func(struct work_struct *work)
+{
+	struct radeon_device *rdev = container_of(work, struct radeon_device,
+						  dp_work);
+	struct drm_device *dev = rdev->ddev;
+	struct drm_mode_config *mode_config = &dev->mode_config;
+	struct drm_connector *connector;
+
+	/* this should take a mutex */
+	if (mode_config->num_connector) {
+		list_for_each_entry(connector, &mode_config->connector_list, head)
+			radeon_connector_hotplug(connector);
+	}
+}
 /**
  * radeon_driver_irq_preinstall_kms - drm irq preinstall callback
  *
@@ -276,6 +290,7 @@
 	}
 
 	INIT_WORK(&rdev->hotplug_work, radeon_hotplug_work_func);
+	INIT_WORK(&rdev->dp_work, radeon_dp_work_func);
 	INIT_WORK(&rdev->audio_work, r600_audio_update_hdmi);
 
 	rdev->irq.installed = true;
diff --git a/drivers/gpu/drm/radeon/radeon_kfd.c b/drivers/gpu/drm/radeon/radeon_kfd.c
index 122eb56..3db2300 100644
--- a/drivers/gpu/drm/radeon/radeon_kfd.c
+++ b/drivers/gpu/drm/radeon/radeon_kfd.c
@@ -103,15 +103,14 @@
 bool radeon_kfd_init(void)
 {
 #if defined(CONFIG_HSA_AMD_MODULE)
-	bool (*kgd2kfd_init_p)(unsigned, const struct kfd2kgd_calls*,
-				const struct kgd2kfd_calls**);
+	bool (*kgd2kfd_init_p)(unsigned, const struct kgd2kfd_calls**);
 
 	kgd2kfd_init_p = symbol_request(kgd2kfd_init);
 
 	if (kgd2kfd_init_p == NULL)
 		return false;
 
-	if (!kgd2kfd_init_p(KFD_INTERFACE_VERSION, &kfd2kgd, &kgd2kfd)) {
+	if (!kgd2kfd_init_p(KFD_INTERFACE_VERSION, &kgd2kfd)) {
 		symbol_put(kgd2kfd_init);
 		kgd2kfd = NULL;
 
@@ -120,7 +119,7 @@
 
 	return true;
 #elif defined(CONFIG_HSA_AMD)
-	if (!kgd2kfd_init(KFD_INTERFACE_VERSION, &kfd2kgd, &kgd2kfd)) {
+	if (!kgd2kfd_init(KFD_INTERFACE_VERSION, &kgd2kfd)) {
 		kgd2kfd = NULL;
 
 		return false;
@@ -143,7 +142,8 @@
 void radeon_kfd_device_probe(struct radeon_device *rdev)
 {
 	if (kgd2kfd)
-		rdev->kfd = kgd2kfd->probe((struct kgd_dev *)rdev, rdev->pdev);
+		rdev->kfd = kgd2kfd->probe((struct kgd_dev *)rdev,
+			rdev->pdev, &kfd2kgd);
 }
 
 void radeon_kfd_device_init(struct radeon_device *rdev)
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index 686411e..7b2a733 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -547,6 +547,35 @@
 		else
 			*value = 1;
 		break;
+	case RADEON_INFO_CURRENT_GPU_TEMP:
+		/* get temperature in millidegrees C */
+		if (rdev->asic->pm.get_temperature)
+			*value = radeon_get_temperature(rdev);
+		else
+			*value = 0;
+		break;
+	case RADEON_INFO_CURRENT_GPU_SCLK:
+		/* get sclk in Mhz */
+		if (rdev->pm.dpm_enabled)
+			*value = radeon_dpm_get_current_sclk(rdev) / 100;
+		else
+			*value = rdev->pm.current_sclk / 100;
+		break;
+	case RADEON_INFO_CURRENT_GPU_MCLK:
+		/* get mclk in Mhz */
+		if (rdev->pm.dpm_enabled)
+			*value = radeon_dpm_get_current_mclk(rdev) / 100;
+		else
+			*value = rdev->pm.current_mclk / 100;
+		break;
+	case RADEON_INFO_READ_REG:
+		if (copy_from_user(value, value_ptr, sizeof(uint32_t))) {
+			DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
+			return -EFAULT;
+		}
+		if (radeon_get_allowed_info_register(rdev, *value, value))
+			return -EINVAL;
+		break;
 	default:
 		DRM_DEBUG_KMS("Invalid request %d\n", info->request);
 		return -EINVAL;
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 920a8be..fa91a17 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -33,6 +33,7 @@
 #include <drm/drm_crtc.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_dp_helper.h>
+#include <drm/drm_dp_mst_helper.h>
 #include <drm/drm_fixed.h>
 #include <drm/drm_crtc_helper.h>
 #include <linux/i2c.h>
@@ -85,6 +86,13 @@
 	RADEON_HPD_NONE = 0xff,
 };
 
+enum radeon_output_csc {
+	RADEON_OUTPUT_CSC_BYPASS = 0,
+	RADEON_OUTPUT_CSC_TVRGB = 1,
+	RADEON_OUTPUT_CSC_YCBCR601 = 2,
+	RADEON_OUTPUT_CSC_YCBCR709 = 3,
+};
+
 #define RADEON_MAX_I2C_BUS 16
 
 /* radeon gpio-based i2c
@@ -255,6 +263,8 @@
 	struct drm_property *audio_property;
 	/* FMT dithering */
 	struct drm_property *dither_property;
+	/* Output CSC */
+	struct drm_property *output_csc_property;
 	/* hardcoded DFP edid from BIOS */
 	struct edid *bios_hardcoded_edid;
 	int bios_hardcoded_edid_size;
@@ -265,6 +275,9 @@
 	u16 firmware_flags;
 	/* pointer to backlight encoder */
 	struct radeon_encoder *bl_encoder;
+
+	/* bitmask for active encoder frontends */
+	uint32_t active_encoders;
 };
 
 #define RADEON_MAX_BL_LEVEL 0xFF
@@ -357,6 +370,7 @@
 	u32 wm_low;
 	u32 wm_high;
 	struct drm_display_mode hw_mode;
+	enum radeon_output_csc output_csc;
 };
 
 struct radeon_encoder_primary_dac {
@@ -426,12 +440,24 @@
 	uint8_t backlight_level;
 	int panel_mode;
 	struct radeon_afmt *afmt;
+	int active_mst_links;
 };
 
 struct radeon_encoder_atom_dac {
 	enum radeon_tv_std tv_std;
 };
 
+struct radeon_encoder_mst {
+	int crtc;
+	struct radeon_encoder *primary;
+	struct radeon_connector *connector;
+	struct drm_dp_mst_port *port;
+	int pbn;
+	int fe;
+	bool fe_from_be;
+	bool enc_active;
+};
+
 struct radeon_encoder {
 	struct drm_encoder base;
 	uint32_t encoder_enum;
@@ -450,6 +476,11 @@
 	bool is_ext_encoder;
 	u16 caps;
 	struct radeon_audio_funcs *audio;
+	enum radeon_output_csc output_csc;
+	bool can_mst;
+	uint32_t offset;
+	bool is_mst_encoder;
+	/* front end for this mst encoder */
 };
 
 struct radeon_connector_atom_dig {
@@ -460,6 +491,7 @@
 	int dp_clock;
 	int dp_lane_count;
 	bool edp_on;
+	bool is_mst;
 };
 
 struct radeon_gpio_rec {
@@ -503,6 +535,11 @@
 	RADEON_FMT_DITHER_ENABLE = 1,
 };
 
+struct stream_attribs {
+	uint16_t fe;
+	uint16_t slots;
+};
+
 struct radeon_connector {
 	struct drm_connector base;
 	uint32_t connector_id;
@@ -524,6 +561,14 @@
 	enum radeon_connector_audio audio;
 	enum radeon_connector_dither dither;
 	int pixelclock_for_modeset;
+	bool is_mst_connector;
+	struct radeon_connector *mst_port;
+	struct drm_dp_mst_port *port;
+	struct drm_dp_mst_topology_mgr mst_mgr;
+
+	struct radeon_encoder *mst_encoder;
+	struct stream_attribs cur_stream_attribs[6];
+	int enabled_attribs;
 };
 
 struct radeon_framebuffer {
@@ -708,15 +753,26 @@
 extern bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector);
 extern int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
 				    struct drm_connector *connector);
+int radeon_dp_get_max_link_rate(struct drm_connector *connector,
+				u8 *dpcd);
 extern void radeon_dp_set_rx_power_state(struct drm_connector *connector,
 					 u8 power_state);
 extern void radeon_dp_aux_init(struct radeon_connector *radeon_connector);
+extern ssize_t
+radeon_dp_aux_transfer_native(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg);
+
 extern void atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode);
+extern void atombios_dig_encoder_setup2(struct drm_encoder *encoder, int action, int panel_mode, int enc_override);
 extern void radeon_atom_encoder_init(struct radeon_device *rdev);
 extern void radeon_atom_disp_eng_pll_init(struct radeon_device *rdev);
 extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder,
 					   int action, uint8_t lane_num,
 					   uint8_t lane_set);
+extern void atombios_dig_transmitter_setup2(struct drm_encoder *encoder,
+					    int action, uint8_t lane_num,
+					    uint8_t lane_set, int fe);
+extern void atombios_set_mst_encoder_crtc_source(struct drm_encoder *encoder,
+						 int fe);
 extern void radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder);
 extern struct drm_encoder *radeon_get_external_encoder(struct drm_encoder *encoder);
 void radeon_atom_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le);
@@ -929,7 +985,23 @@
 void radeon_fb_output_poll_changed(struct radeon_device *rdev);
 
 void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id);
+
+void radeon_fb_add_connector(struct radeon_device *rdev, struct drm_connector *connector);
+void radeon_fb_remove_connector(struct radeon_device *rdev, struct drm_connector *connector);
+
 void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id);
 
 int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled);
+
+/* mst */
+int radeon_dp_mst_init(struct radeon_connector *radeon_connector);
+int radeon_dp_mst_probe(struct radeon_connector *radeon_connector);
+int radeon_dp_mst_check_status(struct radeon_connector *radeon_connector);
+int radeon_mst_debugfs_init(struct radeon_device *rdev);
+void radeon_dp_mst_prepare_pll(struct drm_crtc *crtc, struct drm_display_mode *mode);
+
+void radeon_setup_mst_connector(struct drm_device *dev);
+
+int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder, int fe_idx);
+void radeon_atom_release_dig_encoder(struct radeon_device *rdev, int enc_idx);
 #endif
diff --git a/drivers/gpu/drm/radeon/rs780_dpm.c b/drivers/gpu/drm/radeon/rs780_dpm.c
index 9031f4b..cb0afe7 100644
--- a/drivers/gpu/drm/radeon/rs780_dpm.c
+++ b/drivers/gpu/drm/radeon/rs780_dpm.c
@@ -1001,6 +1001,28 @@
 			   ps->sclk_high, ps->max_voltage);
 }
 
+/* get the current sclk in 10 khz units */
+u32 rs780_dpm_get_current_sclk(struct radeon_device *rdev)
+{
+	u32 current_fb_div = RREG32(FVTHROT_STATUS_REG0) & CURRENT_FEEDBACK_DIV_MASK;
+	u32 func_cntl = RREG32(CG_SPLL_FUNC_CNTL);
+	u32 ref_div = ((func_cntl & SPLL_REF_DIV_MASK) >> SPLL_REF_DIV_SHIFT) + 1;
+	u32 post_div = ((func_cntl & SPLL_SW_HILEN_MASK) >> SPLL_SW_HILEN_SHIFT) + 1 +
+		((func_cntl & SPLL_SW_LOLEN_MASK) >> SPLL_SW_LOLEN_SHIFT) + 1;
+	u32 sclk = (rdev->clock.spll.reference_freq * current_fb_div) /
+		(post_div * ref_div);
+
+	return sclk;
+}
+
+/* get the current mclk in 10 khz units */
+u32 rs780_dpm_get_current_mclk(struct radeon_device *rdev)
+{
+	struct igp_power_info *pi = rs780_get_pi(rdev);
+
+	return pi->bootup_uma_clk;
+}
+
 int rs780_dpm_force_performance_level(struct radeon_device *rdev,
 				      enum radeon_dpm_forced_level level)
 {
diff --git a/drivers/gpu/drm/radeon/rv6xx_dpm.c b/drivers/gpu/drm/radeon/rv6xx_dpm.c
index 6a5c233..97e5a6f 100644
--- a/drivers/gpu/drm/radeon/rv6xx_dpm.c
+++ b/drivers/gpu/drm/radeon/rv6xx_dpm.c
@@ -2050,6 +2050,52 @@
 	}
 }
 
+/* get the current sclk in 10 khz units */
+u32 rv6xx_dpm_get_current_sclk(struct radeon_device *rdev)
+{
+	struct radeon_ps *rps = rdev->pm.dpm.current_ps;
+	struct rv6xx_ps *ps = rv6xx_get_ps(rps);
+	struct rv6xx_pl *pl;
+	u32 current_index =
+		(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_PROFILE_INDEX_MASK) >>
+		CURRENT_PROFILE_INDEX_SHIFT;
+
+	if (current_index > 2) {
+		return 0;
+	} else {
+		if (current_index == 0)
+			pl = &ps->low;
+		else if (current_index == 1)
+			pl = &ps->medium;
+		else /* current_index == 2 */
+			pl = &ps->high;
+		return pl->sclk;
+	}
+}
+
+/* get the current mclk in 10 khz units */
+u32 rv6xx_dpm_get_current_mclk(struct radeon_device *rdev)
+{
+	struct radeon_ps *rps = rdev->pm.dpm.current_ps;
+	struct rv6xx_ps *ps = rv6xx_get_ps(rps);
+	struct rv6xx_pl *pl;
+	u32 current_index =
+		(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_PROFILE_INDEX_MASK) >>
+		CURRENT_PROFILE_INDEX_SHIFT;
+
+	if (current_index > 2) {
+		return 0;
+	} else {
+		if (current_index == 0)
+			pl = &ps->low;
+		else if (current_index == 1)
+			pl = &ps->medium;
+		else /* current_index == 2 */
+			pl = &ps->high;
+		return pl->mclk;
+	}
+}
+
 void rv6xx_dpm_fini(struct radeon_device *rdev)
 {
 	int i;
diff --git a/drivers/gpu/drm/radeon/rv770_dpm.c b/drivers/gpu/drm/radeon/rv770_dpm.c
index 3067326..b9c7707 100644
--- a/drivers/gpu/drm/radeon/rv770_dpm.c
+++ b/drivers/gpu/drm/radeon/rv770_dpm.c
@@ -2492,6 +2492,50 @@
 	}
 }
 
+u32 rv770_dpm_get_current_sclk(struct radeon_device *rdev)
+{
+	struct radeon_ps *rps = rdev->pm.dpm.current_ps;
+	struct rv7xx_ps *ps = rv770_get_ps(rps);
+	struct rv7xx_pl *pl;
+	u32 current_index =
+		(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_PROFILE_INDEX_MASK) >>
+		CURRENT_PROFILE_INDEX_SHIFT;
+
+	if (current_index > 2) {
+		return 0;
+	} else {
+		if (current_index == 0)
+			pl = &ps->low;
+		else if (current_index == 1)
+			pl = &ps->medium;
+		else /* current_index == 2 */
+			pl = &ps->high;
+		return  pl->sclk;
+	}
+}
+
+u32 rv770_dpm_get_current_mclk(struct radeon_device *rdev)
+{
+	struct radeon_ps *rps = rdev->pm.dpm.current_ps;
+	struct rv7xx_ps *ps = rv770_get_ps(rps);
+	struct rv7xx_pl *pl;
+	u32 current_index =
+		(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_PROFILE_INDEX_MASK) >>
+		CURRENT_PROFILE_INDEX_SHIFT;
+
+	if (current_index > 2) {
+		return 0;
+	} else {
+		if (current_index == 0)
+			pl = &ps->low;
+		else if (current_index == 1)
+			pl = &ps->medium;
+		else /* current_index == 2 */
+			pl = &ps->high;
+		return  pl->mclk;
+	}
+}
+
 void rv770_dpm_fini(struct radeon_device *rdev)
 {
 	int i;
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index a7fb273..b1d74bc 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -1264,6 +1264,36 @@
 	}
 }
 
+/**
+ * si_get_allowed_info_register - fetch the register for the info ioctl
+ *
+ * @rdev: radeon_device pointer
+ * @reg: register offset in bytes
+ * @val: register value
+ *
+ * Returns 0 for success or -EINVAL for an invalid register
+ *
+ */
+int si_get_allowed_info_register(struct radeon_device *rdev,
+				 u32 reg, u32 *val)
+{
+	switch (reg) {
+	case GRBM_STATUS:
+	case GRBM_STATUS2:
+	case GRBM_STATUS_SE0:
+	case GRBM_STATUS_SE1:
+	case SRBM_STATUS:
+	case SRBM_STATUS2:
+	case (DMA_STATUS_REG + DMA0_REGISTER_OFFSET):
+	case (DMA_STATUS_REG + DMA1_REGISTER_OFFSET):
+	case UVD_STATUS:
+		*val = RREG32(reg);
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
 #define PCIE_BUS_CLK                10000
 #define TCLK                        (PCIE_BUS_CLK / 10)
 
@@ -6055,12 +6085,12 @@
 		(CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
 
 	if (!ASIC_IS_NODCE(rdev)) {
-		hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN;
-		hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN;
-		hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~DC_HPDx_INT_EN;
-		hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~DC_HPDx_INT_EN;
-		hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN;
-		hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN;
+		hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
+		hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
+		hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
+		hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
+		hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
+		hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
 	}
 
 	dma_cntl = RREG32(DMA_CNTL + DMA0_REGISTER_OFFSET) & ~TRAP_ENABLE;
@@ -6123,27 +6153,27 @@
 	}
 	if (rdev->irq.hpd[0]) {
 		DRM_DEBUG("si_irq_set: hpd 1\n");
-		hpd1 |= DC_HPDx_INT_EN;
+		hpd1 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
 	}
 	if (rdev->irq.hpd[1]) {
 		DRM_DEBUG("si_irq_set: hpd 2\n");
-		hpd2 |= DC_HPDx_INT_EN;
+		hpd2 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
 	}
 	if (rdev->irq.hpd[2]) {
 		DRM_DEBUG("si_irq_set: hpd 3\n");
-		hpd3 |= DC_HPDx_INT_EN;
+		hpd3 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
 	}
 	if (rdev->irq.hpd[3]) {
 		DRM_DEBUG("si_irq_set: hpd 4\n");
-		hpd4 |= DC_HPDx_INT_EN;
+		hpd4 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
 	}
 	if (rdev->irq.hpd[4]) {
 		DRM_DEBUG("si_irq_set: hpd 5\n");
-		hpd5 |= DC_HPDx_INT_EN;
+		hpd5 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
 	}
 	if (rdev->irq.hpd[5]) {
 		DRM_DEBUG("si_irq_set: hpd 6\n");
-		hpd6 |= DC_HPDx_INT_EN;
+		hpd6 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
 	}
 
 	WREG32(CP_INT_CNTL_RING0, cp_int_cntl);
@@ -6306,6 +6336,37 @@
 		tmp |= DC_HPDx_INT_ACK;
 		WREG32(DC_HPD6_INT_CONTROL, tmp);
 	}
+
+	if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_RX_INTERRUPT) {
+		tmp = RREG32(DC_HPD1_INT_CONTROL);
+		tmp |= DC_HPDx_RX_INT_ACK;
+		WREG32(DC_HPD1_INT_CONTROL, tmp);
+	}
+	if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_RX_INTERRUPT) {
+		tmp = RREG32(DC_HPD2_INT_CONTROL);
+		tmp |= DC_HPDx_RX_INT_ACK;
+		WREG32(DC_HPD2_INT_CONTROL, tmp);
+	}
+	if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_RX_INTERRUPT) {
+		tmp = RREG32(DC_HPD3_INT_CONTROL);
+		tmp |= DC_HPDx_RX_INT_ACK;
+		WREG32(DC_HPD3_INT_CONTROL, tmp);
+	}
+	if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_RX_INTERRUPT) {
+		tmp = RREG32(DC_HPD4_INT_CONTROL);
+		tmp |= DC_HPDx_RX_INT_ACK;
+		WREG32(DC_HPD4_INT_CONTROL, tmp);
+	}
+	if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_RX_INTERRUPT) {
+		tmp = RREG32(DC_HPD5_INT_CONTROL);
+		tmp |= DC_HPDx_RX_INT_ACK;
+		WREG32(DC_HPD5_INT_CONTROL, tmp);
+	}
+	if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
+		tmp = RREG32(DC_HPD5_INT_CONTROL);
+		tmp |= DC_HPDx_RX_INT_ACK;
+		WREG32(DC_HPD6_INT_CONTROL, tmp);
+	}
 }
 
 static void si_irq_disable(struct radeon_device *rdev)
@@ -6371,6 +6432,7 @@
 	u32 src_id, src_data, ring_id;
 	u32 ring_index;
 	bool queue_hotplug = false;
+	bool queue_dp = false;
 	bool queue_thermal = false;
 	u32 status, addr;
 
@@ -6611,6 +6673,48 @@
 					DRM_DEBUG("IH: HPD6\n");
 				}
 				break;
+			case 6:
+				if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_RX_INTERRUPT) {
+					rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_RX_INTERRUPT;
+					queue_dp = true;
+					DRM_DEBUG("IH: HPD_RX 1\n");
+				}
+				break;
+			case 7:
+				if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_RX_INTERRUPT) {
+					rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_RX_INTERRUPT;
+					queue_dp = true;
+					DRM_DEBUG("IH: HPD_RX 2\n");
+				}
+				break;
+			case 8:
+				if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_RX_INTERRUPT) {
+					rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_RX_INTERRUPT;
+					queue_dp = true;
+					DRM_DEBUG("IH: HPD_RX 3\n");
+				}
+				break;
+			case 9:
+				if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_RX_INTERRUPT) {
+					rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_RX_INTERRUPT;
+					queue_dp = true;
+					DRM_DEBUG("IH: HPD_RX 4\n");
+				}
+				break;
+			case 10:
+				if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_RX_INTERRUPT) {
+					rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_RX_INTERRUPT;
+					queue_dp = true;
+					DRM_DEBUG("IH: HPD_RX 5\n");
+				}
+				break;
+			case 11:
+				if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
+					rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_RX_INTERRUPT;
+					queue_dp = true;
+					DRM_DEBUG("IH: HPD_RX 6\n");
+				}
+				break;
 			default:
 				DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data);
 				break;
@@ -6693,6 +6797,8 @@
 		rptr &= rdev->ih.ptr_mask;
 		WREG32(IH_RB_RPTR, rptr);
 	}
+	if (queue_dp)
+		schedule_work(&rdev->dp_work);
 	if (queue_hotplug)
 		schedule_work(&rdev->hotplug_work);
 	if (queue_thermal && rdev->pm.dpm_enabled)
diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c
index 7be1165..b35bccf 100644
--- a/drivers/gpu/drm/radeon/si_dpm.c
+++ b/drivers/gpu/drm/radeon/si_dpm.c
@@ -6993,3 +6993,39 @@
 			   current_index, pl->sclk, pl->mclk, pl->vddc, pl->vddci, pl->pcie_gen + 1);
 	}
 }
+
+u32 si_dpm_get_current_sclk(struct radeon_device *rdev)
+{
+	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+	struct radeon_ps *rps = &eg_pi->current_rps;
+	struct ni_ps *ps = ni_get_ps(rps);
+	struct rv7xx_pl *pl;
+	u32 current_index =
+		(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_INDEX_MASK) >>
+		CURRENT_STATE_INDEX_SHIFT;
+
+	if (current_index >= ps->performance_level_count) {
+		return 0;
+	} else {
+		pl = &ps->performance_levels[current_index];
+		return pl->sclk;
+	}
+}
+
+u32 si_dpm_get_current_mclk(struct radeon_device *rdev)
+{
+	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+	struct radeon_ps *rps = &eg_pi->current_rps;
+	struct ni_ps *ps = ni_get_ps(rps);
+	struct rv7xx_pl *pl;
+	u32 current_index =
+		(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_INDEX_MASK) >>
+		CURRENT_STATE_INDEX_SHIFT;
+
+	if (current_index >= ps->performance_level_count) {
+		return 0;
+	} else {
+		pl = &ps->performance_levels[current_index];
+		return pl->mclk;
+	}
+}
diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h
index 99a9835..3afac30 100644
--- a/drivers/gpu/drm/radeon/sid.h
+++ b/drivers/gpu/drm/radeon/sid.h
@@ -1556,6 +1556,7 @@
 #define UVD_UDEC_DBW_ADDR_CONFIG			0xEF54
 #define UVD_RBC_RB_RPTR					0xF690
 #define UVD_RBC_RB_WPTR					0xF694
+#define UVD_STATUS					0xf6bc
 
 #define	UVD_CGC_CTRL					0xF4B0
 #	define DCM					(1 << 0)
diff --git a/drivers/gpu/drm/radeon/sumo_dpm.c b/drivers/gpu/drm/radeon/sumo_dpm.c
index 25fd4ce..cd08628 100644
--- a/drivers/gpu/drm/radeon/sumo_dpm.c
+++ b/drivers/gpu/drm/radeon/sumo_dpm.c
@@ -1837,6 +1837,34 @@
 	}
 }
 
+u32 sumo_dpm_get_current_sclk(struct radeon_device *rdev)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+	struct radeon_ps *rps = &pi->current_rps;
+	struct sumo_ps *ps = sumo_get_ps(rps);
+	struct sumo_pl *pl;
+	u32 current_index =
+		(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURR_INDEX_MASK) >>
+		CURR_INDEX_SHIFT;
+
+	if (current_index == BOOST_DPM_LEVEL) {
+		pl = &pi->boost_pl;
+		return pl->sclk;
+	} else if (current_index >= ps->num_levels) {
+		return 0;
+	} else {
+		pl = &ps->levels[current_index];
+		return pl->sclk;
+	}
+}
+
+u32 sumo_dpm_get_current_mclk(struct radeon_device *rdev)
+{
+	struct sumo_power_info *pi = sumo_get_pi(rdev);
+
+	return pi->sys_info.bootup_uma_clk;
+}
+
 void sumo_dpm_fini(struct radeon_device *rdev)
 {
 	int i;
diff --git a/drivers/gpu/drm/radeon/trinity_dpm.c b/drivers/gpu/drm/radeon/trinity_dpm.c
index 38dacb7..a5b02c5 100644
--- a/drivers/gpu/drm/radeon/trinity_dpm.c
+++ b/drivers/gpu/drm/radeon/trinity_dpm.c
@@ -1964,6 +1964,31 @@
 	}
 }
 
+u32 trinity_dpm_get_current_sclk(struct radeon_device *rdev)
+{
+	struct trinity_power_info *pi = trinity_get_pi(rdev);
+	struct radeon_ps *rps = &pi->current_rps;
+	struct trinity_ps *ps = trinity_get_ps(rps);
+	struct trinity_pl *pl;
+	u32 current_index =
+		(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) >>
+		CURRENT_STATE_SHIFT;
+
+	if (current_index >= ps->num_levels) {
+		return 0;
+	} else {
+		pl = &ps->levels[current_index];
+		return pl->sclk;
+	}
+}
+
+u32 trinity_dpm_get_current_mclk(struct radeon_device *rdev)
+{
+	struct trinity_power_info *pi = trinity_get_pi(rdev);
+
+	return pi->sys_info.bootup_uma_clk;
+}
+
 void trinity_dpm_fini(struct radeon_device *rdev)
 {
 	int i;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 9e72133..7d0b8ef 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -486,8 +486,6 @@
 	unsigned long flags;
 
 	if (event) {
-		event->pipe = rcrtc->index;
-
 		WARN_ON(drm_crtc_vblank_get(crtc) != 0);
 
 		spin_lock_irqsave(&dev->event_lock, flags);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index 1d9e4f8..da1216a 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -252,7 +252,8 @@
 };
 
 static struct drm_driver rcar_du_driver = {
-	.driver_features	= DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME,
+	.driver_features	= DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME
+				| DRIVER_ATOMIC,
 	.load			= rcar_du_load,
 	.unload			= rcar_du_unload,
 	.preclose		= rcar_du_preclose,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index 35a2f04..210e5c3 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -316,6 +316,9 @@
 static void rcar_du_plane_atomic_destroy_state(struct drm_plane *plane,
 					       struct drm_plane_state *state)
 {
+	if (state->fb)
+		drm_framebuffer_unreference(state->fb);
+
 	kfree(to_rcar_du_plane_state(state));
 }
 
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c b/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c
index a5d889a..d5c1248 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c
@@ -71,7 +71,7 @@
 
 	size = mode_cmd.pitches[0] * mode_cmd.height;
 
-	rk_obj = rockchip_gem_create_object(dev, size);
+	rk_obj = rockchip_gem_create_object(dev, size, true);
 	if (IS_ERR(rk_obj))
 		return -ENOMEM;
 
@@ -106,7 +106,7 @@
 
 	fb = helper->fb;
 	drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
-	drm_fb_helper_fill_var(fbi, helper, fb->width, fb->height);
+	drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height);
 
 	offset = fbi->var.xoffset * bytes_per_pixel;
 	offset += fbi->var.yoffset * fb->pitches[0];
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
index 7ca8799e..eb2282c 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
@@ -22,7 +22,8 @@
 #include "rockchip_drm_drv.h"
 #include "rockchip_drm_gem.h"
 
-static int rockchip_gem_alloc_buf(struct rockchip_gem_object *rk_obj)
+static int rockchip_gem_alloc_buf(struct rockchip_gem_object *rk_obj,
+				  bool alloc_kmap)
 {
 	struct drm_gem_object *obj = &rk_obj->base;
 	struct drm_device *drm = obj->dev;
@@ -30,7 +31,9 @@
 	init_dma_attrs(&rk_obj->dma_attrs);
 	dma_set_attr(DMA_ATTR_WRITE_COMBINE, &rk_obj->dma_attrs);
 
-	/* TODO(djkurtz): Use DMA_ATTR_NO_KERNEL_MAPPING except for fbdev */
+	if (!alloc_kmap)
+		dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &rk_obj->dma_attrs);
+
 	rk_obj->kvaddr = dma_alloc_attrs(drm->dev, obj->size,
 					 &rk_obj->dma_addr, GFP_KERNEL,
 					 &rk_obj->dma_attrs);
@@ -103,7 +106,8 @@
 }
 
 struct rockchip_gem_object *
-	rockchip_gem_create_object(struct drm_device *drm, unsigned int size)
+	rockchip_gem_create_object(struct drm_device *drm, unsigned int size,
+				   bool alloc_kmap)
 {
 	struct rockchip_gem_object *rk_obj;
 	struct drm_gem_object *obj;
@@ -119,7 +123,7 @@
 
 	drm_gem_private_object_init(drm, obj, size);
 
-	ret = rockchip_gem_alloc_buf(rk_obj);
+	ret = rockchip_gem_alloc_buf(rk_obj, alloc_kmap);
 	if (ret)
 		goto err_free_rk_obj;
 
@@ -163,7 +167,7 @@
 	struct drm_gem_object *obj;
 	int ret;
 
-	rk_obj = rockchip_gem_create_object(drm, size);
+	rk_obj = rockchip_gem_create_object(drm, size, false);
 	if (IS_ERR(rk_obj))
 		return ERR_CAST(rk_obj);
 
@@ -282,6 +286,9 @@
 {
 	struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj);
 
+	if (dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, &rk_obj->dma_attrs))
+		return NULL;
+
 	return rk_obj->kvaddr;
 }
 
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.h b/drivers/gpu/drm/rockchip/rockchip_drm_gem.h
index 67bcebe..ad22618 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.h
@@ -41,7 +41,8 @@
 			  struct vm_area_struct *vma);
 
 struct rockchip_gem_object *
-	rockchip_gem_create_object(struct drm_device *drm, unsigned int size);
+	rockchip_gem_create_object(struct drm_device *drm, unsigned int size,
+				   bool alloc_kmap);
 
 void rockchip_gem_free_object(struct drm_gem_object *obj);
 
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 9a5c571..d041921 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -81,7 +81,7 @@
 	struct drm_crtc crtc;
 	struct device *dev;
 	struct drm_device *drm_dev;
-	unsigned int dpms;
+	bool is_enabled;
 
 	int connector_type;
 	int connector_out_mode;
@@ -89,6 +89,7 @@
 	/* mutex vsync_ work */
 	struct mutex vsync_mutex;
 	bool vsync_work_pending;
+	struct completion dsp_hold_completion;
 
 	const struct vop_data *data;
 
@@ -382,11 +383,44 @@
 	}
 }
 
+static void vop_dsp_hold_valid_irq_enable(struct vop *vop)
+{
+	unsigned long flags;
+
+	if (WARN_ON(!vop->is_enabled))
+		return;
+
+	spin_lock_irqsave(&vop->irq_lock, flags);
+
+	vop_mask_write(vop, INTR_CTRL0, DSP_HOLD_VALID_INTR_MASK,
+		       DSP_HOLD_VALID_INTR_EN(1));
+
+	spin_unlock_irqrestore(&vop->irq_lock, flags);
+}
+
+static void vop_dsp_hold_valid_irq_disable(struct vop *vop)
+{
+	unsigned long flags;
+
+	if (WARN_ON(!vop->is_enabled))
+		return;
+
+	spin_lock_irqsave(&vop->irq_lock, flags);
+
+	vop_mask_write(vop, INTR_CTRL0, DSP_HOLD_VALID_INTR_MASK,
+		       DSP_HOLD_VALID_INTR_EN(0));
+
+	spin_unlock_irqrestore(&vop->irq_lock, flags);
+}
+
 static void vop_enable(struct drm_crtc *crtc)
 {
 	struct vop *vop = to_vop(crtc);
 	int ret;
 
+	if (vop->is_enabled)
+		return;
+
 	ret = clk_enable(vop->hclk);
 	if (ret < 0) {
 		dev_err(vop->dev, "failed to enable hclk - %d\n", ret);
@@ -417,6 +451,11 @@
 		goto err_disable_aclk;
 	}
 
+	/*
+	 * At here, vop clock & iommu is enable, R/W vop regs would be safe.
+	 */
+	vop->is_enabled = true;
+
 	spin_lock(&vop->reg_lock);
 
 	VOP_CTRL_SET(vop, standby, 0);
@@ -441,26 +480,41 @@
 {
 	struct vop *vop = to_vop(crtc);
 
+	if (!vop->is_enabled)
+		return;
+
 	drm_vblank_off(crtc->dev, vop->pipe);
 
-	disable_irq(vop->irq);
-
 	/*
-	 * TODO: Since standby doesn't take effect until the next vblank,
-	 * when we turn off dclk below, the vop is probably still active.
+	 * Vop standby will take effect at end of current frame,
+	 * if dsp hold valid irq happen, it means standby complete.
+	 *
+	 * we must wait standby complete when we want to disable aclk,
+	 * if not, memory bus maybe dead.
 	 */
+	reinit_completion(&vop->dsp_hold_completion);
+	vop_dsp_hold_valid_irq_enable(vop);
+
 	spin_lock(&vop->reg_lock);
 
 	VOP_CTRL_SET(vop, standby, 1);
 
 	spin_unlock(&vop->reg_lock);
-	/*
-	 * disable dclk to stop frame scan, so we can safely detach iommu,
-	 */
-	clk_disable(vop->dclk);
 
+	wait_for_completion(&vop->dsp_hold_completion);
+
+	vop_dsp_hold_valid_irq_disable(vop);
+
+	disable_irq(vop->irq);
+
+	vop->is_enabled = false;
+
+	/*
+	 * vop standby complete, so iommu detach is safe.
+	 */
 	rockchip_drm_dma_detach_device(vop->drm_dev, vop->dev);
 
+	clk_disable(vop->dclk);
 	clk_disable(vop->aclk);
 	clk_disable(vop->hclk);
 }
@@ -742,7 +796,7 @@
 	struct vop *vop = to_vop(crtc);
 	unsigned long flags;
 
-	if (vop->dpms != DRM_MODE_DPMS_ON)
+	if (!vop->is_enabled)
 		return -EPERM;
 
 	spin_lock_irqsave(&vop->irq_lock, flags);
@@ -759,8 +813,9 @@
 	struct vop *vop = to_vop(crtc);
 	unsigned long flags;
 
-	if (vop->dpms != DRM_MODE_DPMS_ON)
+	if (!vop->is_enabled)
 		return;
+
 	spin_lock_irqsave(&vop->irq_lock, flags);
 	vop_mask_write(vop, INTR_CTRL0, FS_INTR_MASK, FS_INTR_EN(0));
 	spin_unlock_irqrestore(&vop->irq_lock, flags);
@@ -773,15 +828,8 @@
 
 static void vop_crtc_dpms(struct drm_crtc *crtc, int mode)
 {
-	struct vop *vop = to_vop(crtc);
-
 	DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode);
 
-	if (vop->dpms == mode) {
-		DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n");
-		return;
-	}
-
 	switch (mode) {
 	case DRM_MODE_DPMS_ON:
 		vop_enable(crtc);
@@ -795,8 +843,6 @@
 		DRM_DEBUG_KMS("unspecified mode %d\n", mode);
 		break;
 	}
-
-	vop->dpms = mode;
 }
 
 static void vop_crtc_prepare(struct drm_crtc *crtc)
@@ -874,8 +920,8 @@
 	VOP_CTRL_SET(vop, out_mode, vop->connector_out_mode);
 
 	val = 0x8;
-	val |= (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0;
-	val |= (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) ? (1 << 1) : 0;
+	val |= (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : 1;
+	val |= (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : (1 << 1);
 	VOP_CTRL_SET(vop, pin_pol, val);
 
 	VOP_CTRL_SET(vop, htotal_pw, (htotal << 16) | hsync_len);
@@ -934,9 +980,9 @@
 	struct drm_framebuffer *old_fb = crtc->primary->fb;
 	int ret;
 
-	/* when the page flip is requested, crtc's dpms should be on */
-	if (vop->dpms > DRM_MODE_DPMS_ON) {
-		DRM_DEBUG("failed page flip request at dpms[%d].\n", vop->dpms);
+	/* when the page flip is requested, crtc should be on */
+	if (!vop->is_enabled) {
+		DRM_DEBUG("page flip request rejected because crtc is off.\n");
 		return 0;
 	}
 
@@ -1081,6 +1127,7 @@
 	struct vop *vop = data;
 	uint32_t intr0_reg, active_irqs;
 	unsigned long flags;
+	int ret = IRQ_NONE;
 
 	/*
 	 * INTR_CTRL0 register has interrupt status, enable and clear bits, we
@@ -1099,15 +1146,23 @@
 	if (!active_irqs)
 		return IRQ_NONE;
 
-	/* Only Frame Start Interrupt is enabled; other irqs are spurious. */
-	if (!(active_irqs & FS_INTR)) {
-		DRM_ERROR("Unknown VOP IRQs: %#02x\n", active_irqs);
-		return IRQ_NONE;
+	if (active_irqs & DSP_HOLD_VALID_INTR) {
+		complete(&vop->dsp_hold_completion);
+		active_irqs &= ~DSP_HOLD_VALID_INTR;
+		ret = IRQ_HANDLED;
 	}
 
-	drm_handle_vblank(vop->drm_dev, vop->pipe);
+	if (active_irqs & FS_INTR) {
+		drm_handle_vblank(vop->drm_dev, vop->pipe);
+		active_irqs &= ~FS_INTR;
+		ret = (vop->vsync_work_pending) ? IRQ_WAKE_THREAD : IRQ_HANDLED;
+	}
 
-	return (vop->vsync_work_pending) ? IRQ_WAKE_THREAD : IRQ_HANDLED;
+	/* Unhandled irqs are spurious. */
+	if (active_irqs)
+		DRM_ERROR("Unknown VOP IRQs: %#02x\n", active_irqs);
+
+	return ret;
 }
 
 static int vop_create_crtc(struct vop *vop)
@@ -1189,6 +1244,7 @@
 		goto err_cleanup_crtc;
 	}
 
+	init_completion(&vop->dsp_hold_completion);
 	crtc->port = port;
 	vop->pipe = drm_crtc_index(crtc);
 	rockchip_register_crtc_funcs(drm_dev, &private_crtc_funcs, vop->pipe);
@@ -1302,7 +1358,7 @@
 
 	clk_disable(vop->hclk);
 
-	vop->dpms = DRM_MODE_DPMS_OFF;
+	vop->is_enabled = false;
 
 	return 0;
 
diff --git a/drivers/gpu/drm/sti/sti_drm_crtc.c b/drivers/gpu/drm/sti/sti_drm_crtc.c
index e6f6ef7..6b641c5 100644
--- a/drivers/gpu/drm/sti/sti_drm_crtc.c
+++ b/drivers/gpu/drm/sti/sti_drm_crtc.c
@@ -9,6 +9,8 @@
 #include <linux/clk.h>
 
 #include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_plane_helper.h>
 
@@ -77,22 +79,18 @@
 }
 
 static int
-sti_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
-		      struct drm_display_mode *adjusted_mode, int x, int y,
-		      struct drm_framebuffer *old_fb)
+sti_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode)
 {
 	struct sti_mixer *mixer = to_sti_mixer(crtc);
 	struct device *dev = mixer->dev;
 	struct sti_compositor *compo = dev_get_drvdata(dev);
-	struct sti_layer *layer;
 	struct clk *clk;
 	int rate = mode->clock * 1000;
 	int res;
-	unsigned int w, h;
 
-	DRM_DEBUG_KMS("CRTC:%d (%s) fb:%d mode:%d (%s)\n",
+	DRM_DEBUG_KMS("CRTC:%d (%s) mode:%d (%s)\n",
 		      crtc->base.id, sti_mixer_to_str(mixer),
-		      crtc->primary->fb->base.id, mode->base.id, mode->name);
+		      mode->base.id, mode->name);
 
 	DRM_DEBUG_KMS("%d %d %d %d %d %d %d %d %d %d 0x%x 0x%x\n",
 		      mode->vrefresh, mode->clock,
@@ -122,72 +120,13 @@
 	sti_vtg_set_config(mixer->id == STI_MIXER_MAIN ?
 			compo->vtg_main : compo->vtg_aux, &crtc->mode);
 
-	/* a GDP is reserved to the CRTC FB */
-	layer = to_sti_layer(crtc->primary);
-	if (!layer) {
-		DRM_ERROR("Can not find GDP0)\n");
-		return -EINVAL;
-	}
-
-	/* copy the mode data adjusted by mode_fixup() into crtc->mode
-	 * so that hardware can be set to proper mode
-	 */
-	memcpy(&crtc->mode, adjusted_mode, sizeof(*adjusted_mode));
-
-	res = sti_mixer_set_layer_depth(mixer, layer);
-	if (res) {
-		DRM_ERROR("Can not set layer depth\n");
-		return -EINVAL;
-	}
 	res = sti_mixer_active_video_area(mixer, &crtc->mode);
 	if (res) {
 		DRM_ERROR("Can not set active video area\n");
 		return -EINVAL;
 	}
 
-	w = crtc->primary->fb->width - x;
-	h = crtc->primary->fb->height - y;
-
-	return sti_layer_prepare(layer, crtc,
-			crtc->primary->fb, &crtc->mode,
-			mixer->id, 0, 0, w, h, x, y, w, h);
-}
-
-static int sti_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
-				      struct drm_framebuffer *old_fb)
-{
-	struct sti_mixer *mixer = to_sti_mixer(crtc);
-	struct sti_layer *layer;
-	unsigned int w, h;
-	int ret;
-
-	DRM_DEBUG_KMS("CRTC:%d (%s) fb:%d (%d,%d)\n",
-		      crtc->base.id, sti_mixer_to_str(mixer),
-		      crtc->primary->fb->base.id, x, y);
-
-	/* GDP is reserved to the CRTC FB */
-	layer = to_sti_layer(crtc->primary);
-	if (!layer) {
-		DRM_ERROR("Can not find GDP0)\n");
-		ret = -EINVAL;
-		goto out;
-	}
-
-	w = crtc->primary->fb->width - crtc->x;
-	h = crtc->primary->fb->height - crtc->y;
-
-	ret = sti_layer_prepare(layer, crtc,
-				crtc->primary->fb, &crtc->mode,
-				mixer->id, 0, 0, w, h,
-				crtc->x, crtc->y, w, h);
-	if (ret) {
-		DRM_ERROR("Can not prepare layer\n");
-		goto out;
-	}
-
-	sti_drm_crtc_commit(crtc);
-out:
-	return ret;
+	return res;
 }
 
 static void sti_drm_crtc_disable(struct drm_crtc *crtc)
@@ -195,7 +134,6 @@
 	struct sti_mixer *mixer = to_sti_mixer(crtc);
 	struct device *dev = mixer->dev;
 	struct sti_compositor *compo = dev_get_drvdata(dev);
-	struct sti_layer *layer;
 
 	if (!mixer->enabled)
 		return;
@@ -205,24 +143,6 @@
 	/* Disable Background */
 	sti_mixer_set_background_status(mixer, false);
 
-	/* Disable GDP */
-	layer = to_sti_layer(crtc->primary);
-	if (!layer) {
-		DRM_ERROR("Cannot find GDP0\n");
-		return;
-	}
-
-	/* Disable layer at mixer level */
-	if (sti_mixer_set_layer_status(mixer, layer, false))
-		DRM_ERROR("Can not disable %s layer at mixer\n",
-				sti_layer_to_str(layer));
-
-	/* Wait a while to be sure that a Vsync event is received */
-	msleep(WAIT_NEXT_VSYNC_MS);
-
-	/* Then disable layer itself */
-	sti_layer_disable(layer);
-
 	drm_crtc_vblank_off(crtc);
 
 	/* Disable pixel clock and compo IP clocks */
@@ -237,64 +157,44 @@
 	mixer->enabled = false;
 }
 
+static void
+sti_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+	sti_drm_crtc_prepare(crtc);
+	sti_drm_crtc_mode_set(crtc, &crtc->state->adjusted_mode);
+}
+
+static void sti_drm_atomic_begin(struct drm_crtc *crtc)
+{
+	struct sti_mixer *mixer = to_sti_mixer(crtc);
+
+	if (crtc->state->event) {
+		crtc->state->event->pipe = drm_crtc_index(crtc);
+
+		WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
+		mixer->pending_event = crtc->state->event;
+		crtc->state->event = NULL;
+	}
+}
+
+static void sti_drm_atomic_flush(struct drm_crtc *crtc)
+{
+}
+
 static struct drm_crtc_helper_funcs sti_crtc_helper_funcs = {
 	.dpms = sti_drm_crtc_dpms,
 	.prepare = sti_drm_crtc_prepare,
 	.commit = sti_drm_crtc_commit,
 	.mode_fixup = sti_drm_crtc_mode_fixup,
-	.mode_set = sti_drm_crtc_mode_set,
-	.mode_set_base = sti_drm_crtc_mode_set_base,
+	.mode_set = drm_helper_crtc_mode_set,
+	.mode_set_nofb = sti_drm_crtc_mode_set_nofb,
+	.mode_set_base = drm_helper_crtc_mode_set_base,
 	.disable = sti_drm_crtc_disable,
+	.atomic_begin = sti_drm_atomic_begin,
+	.atomic_flush = sti_drm_atomic_flush,
 };
 
-static int sti_drm_crtc_page_flip(struct drm_crtc *crtc,
-				  struct drm_framebuffer *fb,
-				  struct drm_pending_vblank_event *event,
-				  uint32_t page_flip_flags)
-{
-	struct drm_device *drm_dev = crtc->dev;
-	struct drm_framebuffer *old_fb;
-	struct sti_mixer *mixer = to_sti_mixer(crtc);
-	unsigned long flags;
-	int ret;
-
-	DRM_DEBUG_KMS("fb %d --> fb %d\n",
-			crtc->primary->fb->base.id, fb->base.id);
-
-	mutex_lock(&drm_dev->struct_mutex);
-
-	old_fb = crtc->primary->fb;
-	crtc->primary->fb = fb;
-	ret = sti_drm_crtc_mode_set_base(crtc, crtc->x, crtc->y, old_fb);
-	if (ret) {
-		DRM_ERROR("failed\n");
-		crtc->primary->fb = old_fb;
-		goto out;
-	}
-
-	if (event) {
-		event->pipe = mixer->id;
-
-		ret = drm_vblank_get(drm_dev, event->pipe);
-		if (ret) {
-			DRM_ERROR("Cannot get vblank\n");
-			goto out;
-		}
-
-		spin_lock_irqsave(&drm_dev->event_lock, flags);
-		if (mixer->pending_event) {
-			drm_vblank_put(drm_dev, event->pipe);
-			ret = -EBUSY;
-		} else {
-			mixer->pending_event = event;
-		}
-		spin_unlock_irqrestore(&drm_dev->event_lock, flags);
-	}
-out:
-	mutex_unlock(&drm_dev->struct_mutex);
-	return ret;
-}
-
 static void sti_drm_crtc_destroy(struct drm_crtc *crtc)
 {
 	DRM_DEBUG_KMS("\n");
@@ -380,10 +280,13 @@
 EXPORT_SYMBOL(sti_drm_crtc_disable_vblank);
 
 static struct drm_crtc_funcs sti_crtc_funcs = {
-	.set_config = drm_crtc_helper_set_config,
-	.page_flip = sti_drm_crtc_page_flip,
+	.set_config = drm_atomic_helper_set_config,
+	.page_flip = drm_atomic_helper_page_flip,
 	.destroy = sti_drm_crtc_destroy,
 	.set_property = sti_drm_crtc_set_property,
+	.reset = drm_atomic_helper_crtc_reset,
+	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
 };
 
 bool sti_drm_crtc_is_main(struct drm_crtc *crtc)
diff --git a/drivers/gpu/drm/sti/sti_drm_drv.c b/drivers/gpu/drm/sti/sti_drm_drv.c
index 5239fa1..59d558b 100644
--- a/drivers/gpu/drm/sti/sti_drm_drv.c
+++ b/drivers/gpu/drm/sti/sti_drm_drv.c
@@ -12,6 +12,8 @@
 #include <linux/module.h>
 #include <linux/of_platform.h>
 
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_fb_cma_helper.h>
@@ -28,8 +30,87 @@
 #define STI_MAX_FB_HEIGHT	4096
 #define STI_MAX_FB_WIDTH	4096
 
+static void sti_drm_atomic_schedule(struct sti_drm_private *private,
+				  struct drm_atomic_state *state)
+{
+	private->commit.state = state;
+	schedule_work(&private->commit.work);
+}
+
+static void sti_drm_atomic_complete(struct sti_drm_private *private,
+				  struct drm_atomic_state *state)
+{
+	struct drm_device *drm = private->drm_dev;
+
+	/*
+	 * Everything below can be run asynchronously without the need to grab
+	 * any modeset locks at all under one condition: It must be guaranteed
+	 * that the asynchronous work has either been cancelled (if the driver
+	 * supports it, which at least requires that the framebuffers get
+	 * cleaned up with drm_atomic_helper_cleanup_planes()) or completed
+	 * before the new state gets committed on the software side with
+	 * drm_atomic_helper_swap_state().
+	 *
+	 * This scheme allows new atomic state updates to be prepared and
+	 * checked in parallel to the asynchronous completion of the previous
+	 * update. Which is important since compositors need to figure out the
+	 * composition of the next frame right after having submitted the
+	 * current layout.
+	 */
+
+	drm_atomic_helper_commit_modeset_disables(drm, state);
+	drm_atomic_helper_commit_planes(drm, state);
+	drm_atomic_helper_commit_modeset_enables(drm, state);
+
+	drm_atomic_helper_wait_for_vblanks(drm, state);
+
+	drm_atomic_helper_cleanup_planes(drm, state);
+	drm_atomic_state_free(state);
+}
+
+static void sti_drm_atomic_work(struct work_struct *work)
+{
+	struct sti_drm_private *private = container_of(work,
+			struct sti_drm_private, commit.work);
+
+	sti_drm_atomic_complete(private, private->commit.state);
+}
+
+static int sti_drm_atomic_commit(struct drm_device *drm,
+			       struct drm_atomic_state *state, bool async)
+{
+	struct sti_drm_private *private = drm->dev_private;
+	int err;
+
+	err = drm_atomic_helper_prepare_planes(drm, state);
+	if (err)
+		return err;
+
+	/* serialize outstanding asynchronous commits */
+	mutex_lock(&private->commit.lock);
+	flush_work(&private->commit.work);
+
+	/*
+	 * This is the point of no return - everything below never fails except
+	 * when the hw goes bonghits. Which means we can commit the new state on
+	 * the software side now.
+	 */
+
+	drm_atomic_helper_swap_state(drm, state);
+
+	if (async)
+		sti_drm_atomic_schedule(private, state);
+	else
+		sti_drm_atomic_complete(private, state);
+
+	mutex_unlock(&private->commit.lock);
+	return 0;
+}
+
 static struct drm_mode_config_funcs sti_drm_mode_config_funcs = {
 	.fb_create = drm_fb_cma_create,
+	.atomic_check = drm_atomic_helper_check,
+	.atomic_commit = sti_drm_atomic_commit,
 };
 
 static void sti_drm_mode_config_init(struct drm_device *dev)
@@ -61,6 +142,9 @@
 	dev->dev_private = (void *)private;
 	private->drm_dev = dev;
 
+	mutex_init(&private->commit.lock);
+	INIT_WORK(&private->commit.work, sti_drm_atomic_work);
+
 	drm_mode_config_init(dev);
 	drm_kms_helper_poll_init(dev);
 
@@ -74,7 +158,7 @@
 		return ret;
 	}
 
-	drm_helper_disable_unused_functions(dev);
+	drm_mode_config_reset(dev);
 
 #ifdef CONFIG_DRM_STI_FBDEV
 	drm_fbdev_cma_init(dev, 32,
diff --git a/drivers/gpu/drm/sti/sti_drm_drv.h b/drivers/gpu/drm/sti/sti_drm_drv.h
index ec5e2eb..c413aa3 100644
--- a/drivers/gpu/drm/sti/sti_drm_drv.h
+++ b/drivers/gpu/drm/sti/sti_drm_drv.h
@@ -24,6 +24,12 @@
 	struct sti_compositor *compo;
 	struct drm_property *plane_zorder_property;
 	struct drm_device *drm_dev;
+
+	struct {
+		struct drm_atomic_state *state;
+		struct work_struct work;
+		struct mutex lock;
+	} commit;
 };
 
 #endif
diff --git a/drivers/gpu/drm/sti/sti_drm_plane.c b/drivers/gpu/drm/sti/sti_drm_plane.c
index bb6a293..64d4ed4 100644
--- a/drivers/gpu/drm/sti/sti_drm_plane.c
+++ b/drivers/gpu/drm/sti/sti_drm_plane.c
@@ -6,6 +6,10 @@
  * License terms:  GNU General Public License (GPL), version 2
  */
 
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_plane_helper.h>
+
 #include "sti_compositor.h"
 #include "sti_drm_drv.h"
 #include "sti_drm_plane.h"
@@ -33,9 +37,9 @@
 	struct sti_mixer *mixer = to_sti_mixer(crtc);
 	int res;
 
-	DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s) drm fb:%d\n",
+	DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s)\n",
 		      crtc->base.id, sti_mixer_to_str(mixer),
-		      plane->base.id, sti_layer_to_str(layer), fb->base.id);
+		      plane->base.id, sti_layer_to_str(layer));
 	DRM_DEBUG_KMS("(%dx%d)@(%d,%d)\n", crtc_w, crtc_h, crtc_x, crtc_y);
 
 	res = sti_mixer_set_layer_depth(mixer, layer);
@@ -110,7 +114,7 @@
 {
 	DRM_DEBUG_DRIVER("\n");
 
-	sti_drm_disable_plane(plane);
+	drm_plane_helper_disable(plane);
 	drm_plane_cleanup(plane);
 }
 
@@ -133,10 +137,58 @@
 }
 
 static struct drm_plane_funcs sti_drm_plane_funcs = {
-	.update_plane = sti_drm_update_plane,
-	.disable_plane = sti_drm_disable_plane,
+	.update_plane = drm_atomic_helper_update_plane,
+	.disable_plane = drm_atomic_helper_disable_plane,
 	.destroy = sti_drm_plane_destroy,
 	.set_property = sti_drm_plane_set_property,
+	.reset = drm_atomic_helper_plane_reset,
+	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+};
+
+static int sti_drm_plane_prepare_fb(struct drm_plane *plane,
+				  struct drm_framebuffer *fb,
+				  const struct drm_plane_state *new_state)
+{
+	return 0;
+}
+
+static void sti_drm_plane_cleanup_fb(struct drm_plane *plane,
+				   struct drm_framebuffer *fb,
+				   const struct drm_plane_state *old_fb)
+{
+}
+
+static int sti_drm_plane_atomic_check(struct drm_plane *plane,
+				      struct drm_plane_state *state)
+{
+	return 0;
+}
+
+static void sti_drm_plane_atomic_update(struct drm_plane *plane,
+					struct drm_plane_state *oldstate)
+{
+	struct drm_plane_state *state = plane->state;
+
+	sti_drm_update_plane(plane, state->crtc, state->fb,
+			    state->crtc_x, state->crtc_y,
+			    state->crtc_w, state->crtc_h,
+			    state->src_x, state->src_y,
+			    state->src_w, state->src_h);
+}
+
+static void sti_drm_plane_atomic_disable(struct drm_plane *plane,
+					 struct drm_plane_state *oldstate)
+{
+	sti_drm_disable_plane(plane);
+}
+
+static const struct drm_plane_helper_funcs sti_drm_plane_helpers_funcs = {
+	.prepare_fb = sti_drm_plane_prepare_fb,
+	.cleanup_fb = sti_drm_plane_cleanup_fb,
+	.atomic_check = sti_drm_plane_atomic_check,
+	.atomic_update = sti_drm_plane_atomic_update,
+	.atomic_disable = sti_drm_plane_atomic_disable,
 };
 
 static void sti_drm_plane_attach_zorder_property(struct drm_plane *plane,
@@ -178,11 +230,13 @@
 		return NULL;
 	}
 
+	drm_plane_helper_add(&layer->plane, &sti_drm_plane_helpers_funcs);
+
 	for (i = 0; i < ARRAY_SIZE(sti_layer_default_zorder); i++)
 		if (sti_layer_default_zorder[i] == layer->desc)
 			break;
 
-	default_zorder = i;
+	default_zorder = i + 1;
 
 	if (type == DRM_PLANE_TYPE_OVERLAY)
 		sti_drm_plane_attach_zorder_property(&layer->plane,
diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
index aeb5070..a9b678a 100644
--- a/drivers/gpu/drm/sti/sti_dvo.c
+++ b/drivers/gpu/drm/sti/sti_dvo.c
@@ -11,6 +11,7 @@
 #include <linux/platform_device.h>
 
 #include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_panel.h>
 
@@ -364,10 +365,13 @@
 }
 
 static struct drm_connector_funcs sti_dvo_connector_funcs = {
-	.dpms = drm_helper_connector_dpms,
+	.dpms = drm_atomic_helper_connector_dpms,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.detect = sti_dvo_connector_detect,
 	.destroy = sti_dvo_connector_destroy,
+	.reset = drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
 static struct drm_encoder *sti_dvo_find_encoder(struct drm_device *dev)
diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c
index a9bbb08..598cd78 100644
--- a/drivers/gpu/drm/sti/sti_hda.c
+++ b/drivers/gpu/drm/sti/sti_hda.c
@@ -10,6 +10,7 @@
 #include <linux/platform_device.h>
 
 #include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
 
 /* HDformatter registers */
@@ -611,10 +612,13 @@
 }
 
 static struct drm_connector_funcs sti_hda_connector_funcs = {
-	.dpms = drm_helper_connector_dpms,
+	.dpms = drm_atomic_helper_connector_dpms,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.detect = sti_hda_connector_detect,
 	.destroy = sti_hda_connector_destroy,
+	.reset = drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
 static struct drm_encoder *sti_hda_find_encoder(struct drm_device *dev)
diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
index 1485ade..ae5424b 100644
--- a/drivers/gpu/drm/sti/sti_hdmi.c
+++ b/drivers/gpu/drm/sti/sti_hdmi.c
@@ -13,6 +13,7 @@
 #include <linux/reset.h>
 
 #include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_edid.h>
 
@@ -663,10 +664,13 @@
 }
 
 static struct drm_connector_funcs sti_hdmi_connector_funcs = {
-	.dpms = drm_helper_connector_dpms,
+	.dpms = drm_atomic_helper_connector_dpms,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.detect = sti_hdmi_connector_detect,
 	.destroy = sti_hdmi_connector_destroy,
+	.reset = drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
 static struct drm_encoder *sti_hdmi_find_encoder(struct drm_device *dev)
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index adc9ea5..7b5c661 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -915,7 +915,7 @@
 };
 
 /**
- * struct struct drm_atomic_state - the global state object for atomic updates
+ * struct drm_atomic_state - the global state object for atomic updates
  * @dev: parent DRM device
  * @allow_modeset: allow full modeset
  * @legacy_cursor_update: hint to enforce legacy cursor ioctl semantics
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index c5fdc2d..523f04c 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -42,6 +42,8 @@
  * 1.2 formally includes both eDP and DPI definitions.
  */
 
+#define DP_AUX_MAX_PAYLOAD_BYTES	16
+
 #define DP_AUX_I2C_WRITE		0x0
 #define DP_AUX_I2C_READ			0x1
 #define DP_AUX_I2C_STATUS		0x2
@@ -680,6 +682,9 @@
  * transactions. The drm_dp_aux_register_i2c_bus() function registers an
  * I2C adapter that can be passed to drm_probe_ddc(). Upon removal, drivers
  * should call drm_dp_aux_unregister_i2c_bus() to remove the I2C adapter.
+ * The I2C adapter uses long transfers by default; if a partial response is
+ * received, the adapter will drop down to the size given by the partial
+ * response for this transaction only.
  *
  * Note that the aux helper code assumes that the .transfer() function
  * only modifies the reply field of the drm_dp_aux_msg structure.  The
diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h
index 00c1da9..a250781 100644
--- a/include/drm/drm_dp_mst_helper.h
+++ b/include/drm/drm_dp_mst_helper.h
@@ -486,6 +486,8 @@
 
 bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, int pbn, int *slots);
 
+int drm_dp_mst_get_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port);
+
 
 void drm_dp_mst_reset_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port);
 
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index 21b944c..0dfd94def 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -44,6 +44,25 @@
 	int x, y;
 };
 
+/**
+ * struct drm_fb_helper_surface_size - describes fbdev size and scanout surface size
+ * @fb_width: fbdev width
+ * @fb_height: fbdev height
+ * @surface_width: scanout buffer width
+ * @surface_height: scanout buffer height
+ * @surface_bpp: scanout buffer bpp
+ * @surface_depth: scanout buffer depth
+ *
+ * Note that the scanout surface width/height may be larger than the fbdev
+ * width/height.  In case of multiple displays, the scanout surface is sized
+ * according to the largest width/height (so it is large enough for all CRTCs
+ * to scanout).  But the fbdev width/height is sized to the minimum width/
+ * height of all the displays.  This ensures that fbcon fits on the smallest
+ * of the attached displays.
+ *
+ * So what is passed to drm_fb_helper_fill_var() should be fb_width/fb_height,
+ * rather than the surface size.
+ */
 struct drm_fb_helper_surface_size {
 	u32 fb_width;
 	u32 fb_height;
diff --git a/include/uapi/drm/radeon_drm.h b/include/uapi/drm/radeon_drm.h
index 50d0fb4..871e73f 100644
--- a/include/uapi/drm/radeon_drm.h
+++ b/include/uapi/drm/radeon_drm.h
@@ -1034,6 +1034,10 @@
 #define RADEON_INFO_VRAM_USAGE		0x1e
 #define RADEON_INFO_GTT_USAGE		0x1f
 #define RADEON_INFO_ACTIVE_CU_COUNT	0x20
+#define RADEON_INFO_CURRENT_GPU_TEMP	0x21
+#define RADEON_INFO_CURRENT_GPU_SCLK	0x22
+#define RADEON_INFO_CURRENT_GPU_MCLK	0x23
+#define RADEON_INFO_READ_REG		0x24
 
 struct drm_radeon_info {
 	uint32_t		request;