[PATCH v2] drm/amdkfd: Refactor kfd CRIU into its own file

2024-05-07 Thread David Francis
The kfd CRIU code takes up about a thousand lines
in the kfd_chardev file; move it to its own file.

No functional change intended.

Signed-off-by: David Francis 
Reviewed-by: Felix Kuehling 
---
 drivers/gpu/drm/amd/amdkfd/Makefile  |   1 +
 drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 974 +-
 drivers/gpu/drm/amd/amdkfd/kfd_criu.c| 989 +++
 drivers/gpu/drm/amd/amdkfd/kfd_criu.h|  50 ++
 4 files changed, 1046 insertions(+), 968 deletions(-)
 create mode 100644 drivers/gpu/drm/amd/amdkfd/kfd_criu.c
 create mode 100644 drivers/gpu/drm/amd/amdkfd/kfd_criu.h

diff --git a/drivers/gpu/drm/amd/amdkfd/Makefile 
b/drivers/gpu/drm/amd/amdkfd/Makefile
index 0d3d8972240d..e06af4073ac5 100644
--- a/drivers/gpu/drm/amd/amdkfd/Makefile
+++ b/drivers/gpu/drm/amd/amdkfd/Makefile
@@ -32,6 +32,7 @@ AMDKFD_FILES  := $(AMDKFD_PATH)/kfd_module.o \
$(AMDKFD_PATH)/kfd_flat_memory.o \
$(AMDKFD_PATH)/kfd_process.o \
$(AMDKFD_PATH)/kfd_queue.o \
+   $(AMDKFD_PATH)/kfd_criu.o \
$(AMDKFD_PATH)/kfd_mqd_manager.o \
$(AMDKFD_PATH)/kfd_mqd_manager_cik.o \
$(AMDKFD_PATH)/kfd_mqd_manager_vi.o \
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
index 6b713fb0b818..d9587364130a 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
@@ -36,15 +36,14 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include "kfd_priv.h"
 #include "kfd_device_queue_manager.h"
 #include "kfd_svm.h"
 #include "amdgpu_amdkfd.h"
 #include "kfd_smi_events.h"
-#include "amdgpu_dma_buf.h"
 #include "kfd_debug.h"
+#include "kfd_criu.h"
 
 static long kfd_ioctl(struct file *, unsigned int, unsigned long);
 static int kfd_open(struct inode *, struct file *);
@@ -1751,967 +1750,6 @@ static int kfd_ioctl_svm(struct file *filep, struct 
kfd_process *p, void *data)
 }
 #endif
 
-static int criu_checkpoint_process(struct kfd_process *p,
-uint8_t __user *user_priv_data,
-uint64_t *priv_offset)
-{
-   struct kfd_criu_process_priv_data process_priv;
-   int ret;
-
-   memset(_priv, 0, sizeof(process_priv));
-
-   process_priv.version = KFD_CRIU_PRIV_VERSION;
-   /* For CR, we don't consider negative xnack mode which is used for
-* querying without changing it, here 0 simply means disabled and 1
-* means enabled so retry for finding a valid PTE.
-*/
-   process_priv.xnack_mode = p->xnack_enabled ? 1 : 0;
-
-   ret = copy_to_user(user_priv_data + *priv_offset,
-   _priv, sizeof(process_priv));
-
-   if (ret) {
-   pr_err("Failed to copy process information to user\n");
-   ret = -EFAULT;
-   }
-
-   *priv_offset += sizeof(process_priv);
-   return ret;
-}
-
-static int criu_checkpoint_devices(struct kfd_process *p,
-uint32_t num_devices,
-uint8_t __user *user_addr,
-uint8_t __user *user_priv_data,
-uint64_t *priv_offset)
-{
-   struct kfd_criu_device_priv_data *device_priv = NULL;
-   struct kfd_criu_device_bucket *device_buckets = NULL;
-   int ret = 0, i;
-
-   device_buckets = kvzalloc(num_devices * sizeof(*device_buckets), 
GFP_KERNEL);
-   if (!device_buckets) {
-   ret = -ENOMEM;
-   goto exit;
-   }
-
-   device_priv = kvzalloc(num_devices * sizeof(*device_priv), GFP_KERNEL);
-   if (!device_priv) {
-   ret = -ENOMEM;
-   goto exit;
-   }
-
-   for (i = 0; i < num_devices; i++) {
-   struct kfd_process_device *pdd = p->pdds[i];
-
-   device_buckets[i].user_gpu_id = pdd->user_gpu_id;
-   device_buckets[i].actual_gpu_id = pdd->dev->id;
-
-   /*
-* priv_data does not contain useful information for now and is 
reserved for
-* future use, so we do not set its contents.
-*/
-   }
-
-   ret = copy_to_user(user_addr, device_buckets, num_devices * 
sizeof(*device_buckets));
-   if (ret) {
-   pr_err("Failed to copy device information to user\n");
-   ret = -EFAULT;
-   goto exit;
-   }
-
-   ret = copy_to_user(user_priv_data + *priv_offset,
-  device_priv,
-  num_devices * sizeof(*device_priv));
-   if (ret) {
-   pr_err("Failed to copy device information to user\n");
-   ret = -EFAULT;
-   }
-   *priv_offset += num_devices * sizeof(*device_priv);
-
-exit:
-   kvfree(device_buckets);
-

[PATCH] drm/amdkfd: Refactor kfd CRIU into its own file

2024-05-06 Thread David Francis
The kfd CRIU code takes up about a thousand lines
in the kfd_chardev file; move it to its own file.

No functional change intended.

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdkfd/Makefile  |   1 +
 drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 972 +-
 drivers/gpu/drm/amd/amdkfd/kfd_criu.c| 989 +++
 drivers/gpu/drm/amd/amdkfd/kfd_criu.h|  50 ++
 4 files changed, 1046 insertions(+), 966 deletions(-)
 create mode 100644 drivers/gpu/drm/amd/amdkfd/kfd_criu.c
 create mode 100644 drivers/gpu/drm/amd/amdkfd/kfd_criu.h

diff --git a/drivers/gpu/drm/amd/amdkfd/Makefile 
b/drivers/gpu/drm/amd/amdkfd/Makefile
index 0d3d8972240d..e06af4073ac5 100644
--- a/drivers/gpu/drm/amd/amdkfd/Makefile
+++ b/drivers/gpu/drm/amd/amdkfd/Makefile
@@ -32,6 +32,7 @@ AMDKFD_FILES  := $(AMDKFD_PATH)/kfd_module.o \
$(AMDKFD_PATH)/kfd_flat_memory.o \
$(AMDKFD_PATH)/kfd_process.o \
$(AMDKFD_PATH)/kfd_queue.o \
+   $(AMDKFD_PATH)/kfd_criu.o \
$(AMDKFD_PATH)/kfd_mqd_manager.o \
$(AMDKFD_PATH)/kfd_mqd_manager_cik.o \
$(AMDKFD_PATH)/kfd_mqd_manager_vi.o \
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
index 6b713fb0b818..e6e44a199a93 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
@@ -45,6 +45,7 @@
 #include "kfd_smi_events.h"
 #include "amdgpu_dma_buf.h"
 #include "kfd_debug.h"
+#include "kfd_criu.h"
 
 static long kfd_ioctl(struct file *, unsigned int, unsigned long);
 static int kfd_open(struct inode *, struct file *);
@@ -1751,967 +1752,6 @@ static int kfd_ioctl_svm(struct file *filep, struct 
kfd_process *p, void *data)
 }
 #endif
 
-static int criu_checkpoint_process(struct kfd_process *p,
-uint8_t __user *user_priv_data,
-uint64_t *priv_offset)
-{
-   struct kfd_criu_process_priv_data process_priv;
-   int ret;
-
-   memset(_priv, 0, sizeof(process_priv));
-
-   process_priv.version = KFD_CRIU_PRIV_VERSION;
-   /* For CR, we don't consider negative xnack mode which is used for
-* querying without changing it, here 0 simply means disabled and 1
-* means enabled so retry for finding a valid PTE.
-*/
-   process_priv.xnack_mode = p->xnack_enabled ? 1 : 0;
-
-   ret = copy_to_user(user_priv_data + *priv_offset,
-   _priv, sizeof(process_priv));
-
-   if (ret) {
-   pr_err("Failed to copy process information to user\n");
-   ret = -EFAULT;
-   }
-
-   *priv_offset += sizeof(process_priv);
-   return ret;
-}
-
-static int criu_checkpoint_devices(struct kfd_process *p,
-uint32_t num_devices,
-uint8_t __user *user_addr,
-uint8_t __user *user_priv_data,
-uint64_t *priv_offset)
-{
-   struct kfd_criu_device_priv_data *device_priv = NULL;
-   struct kfd_criu_device_bucket *device_buckets = NULL;
-   int ret = 0, i;
-
-   device_buckets = kvzalloc(num_devices * sizeof(*device_buckets), 
GFP_KERNEL);
-   if (!device_buckets) {
-   ret = -ENOMEM;
-   goto exit;
-   }
-
-   device_priv = kvzalloc(num_devices * sizeof(*device_priv), GFP_KERNEL);
-   if (!device_priv) {
-   ret = -ENOMEM;
-   goto exit;
-   }
-
-   for (i = 0; i < num_devices; i++) {
-   struct kfd_process_device *pdd = p->pdds[i];
-
-   device_buckets[i].user_gpu_id = pdd->user_gpu_id;
-   device_buckets[i].actual_gpu_id = pdd->dev->id;
-
-   /*
-* priv_data does not contain useful information for now and is 
reserved for
-* future use, so we do not set its contents.
-*/
-   }
-
-   ret = copy_to_user(user_addr, device_buckets, num_devices * 
sizeof(*device_buckets));
-   if (ret) {
-   pr_err("Failed to copy device information to user\n");
-   ret = -EFAULT;
-   goto exit;
-   }
-
-   ret = copy_to_user(user_priv_data + *priv_offset,
-  device_priv,
-  num_devices * sizeof(*device_priv));
-   if (ret) {
-   pr_err("Failed to copy device information to user\n");
-   ret = -EFAULT;
-   }
-   *priv_offset += num_devices * sizeof(*device_priv);
-
-exit:
-   kvfree(device_buckets);
-   kvfree(device_priv);
-   return ret;
-}
-
-static uint32_t get_process_num_bos(struct kfd_process *p)
-{
-   uint32_t num_of_bos = 0;
-   int i;
-
-   /* Run over all PDDs of the process */
-   for (i = 0; i < p->n_

[PATCH] drm/amdgpu: Allow secure submission on SDMAv4.4.2 rings

2024-02-13 Thread David Francis
This flag was accidentally left off of SDMAv4.4.2 when it was
added. SDMAv4.4.2, like all other SDMA engines, does support
secure submission.

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c 
b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
index fec5a3d1c4bc..bd29b13bc3d5 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
@@ -1839,6 +1839,7 @@ static const struct amdgpu_ring_funcs 
sdma_v4_4_2_ring_funcs = {
.align_mask = 0xff,
.nop = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP),
.support_64bit_ptrs = true,
+   .secure_submission_supported = true,
.get_rptr = sdma_v4_4_2_ring_get_rptr,
.get_wptr = sdma_v4_4_2_ring_get_wptr,
.set_wptr = sdma_v4_4_2_ring_set_wptr,
@@ -1870,6 +1871,7 @@ static const struct amdgpu_ring_funcs 
sdma_v4_4_2_page_ring_funcs = {
.align_mask = 0xff,
.nop = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP),
.support_64bit_ptrs = true,
+   .secure_submission_supported = true,
.get_rptr = sdma_v4_4_2_ring_get_rptr,
.get_wptr = sdma_v4_4_2_page_ring_get_wptr,
.set_wptr = sdma_v4_4_2_page_ring_set_wptr,
-- 
2.25.1



[PATCH v3 2/2] drm/amdgpu: Permit PCIe transfer over links with XGMI

2023-10-24 Thread David Francis
When the CPU is XGMI connected, the PCIe links should
not be enumerated for topology purposes. However, PCIe
transfer should still be a valid option for remote
doorbells and MMIO mappings.

Move the XGMI connection check out of the shared helper
function amdgpu_device_is_peer_accessible and into the
topology path.

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 4 +---
 drivers/gpu/drm/amd/amdkfd/kfd_topology.c  | 6 --
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 7ec32b44df05..a5c054f8a427 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -5783,9 +5783,7 @@ bool amdgpu_device_is_peer_accessible(struct 
amdgpu_device *adev,
~*peer_adev->dev->dma_mask : ~((1ULL << 32) - 1);
resource_size_t aper_limit =
adev->gmc.aper_base + adev->gmc.aper_size - 1;
-   bool p2p_access =
-   !adev->gmc.xgmi.connected_to_cpu &&
-   !(pci_p2pdma_distance(adev->pdev, peer_adev->dev, false) < 0);
+   bool p2p_access = !(pci_p2pdma_distance(adev->pdev, peer_adev->dev, 
false) < 0);
 
return pcie_p2p && p2p_access && (adev->gmc.visible_vram_size &&
adev->gmc.real_vram_size == adev->gmc.visible_vram_size &&
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
index 4e530791507e..cb64c19482f3 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
@@ -1514,11 +1514,13 @@ static int kfd_dev_create_p2p_links(void)
goto next;
 
/* check if node(s) is/are peer accessible in one direction or 
bi-direction */
-   ret = kfd_add_peer_prop(new_dev, dev, i, k);
+   if (!new_dev->gpu->adev->gmc.xgmi.connected_to_cpu)
+   ret = kfd_add_peer_prop(new_dev, dev, i, k);
if (ret < 0)
goto out;
 
-   ret = kfd_add_peer_prop(dev, new_dev, k, i);
+   if (!dev->gpu->adev->gmc.xgmi.connected_to_cpu)
+   ret = kfd_add_peer_prop(dev, new_dev, k, i);
if (ret < 0)
goto out;
 next:
-- 
2.34.1



[PATCH v3 1/2] drm/amdgpu: Acquire ttm locks for dmaunmap

2023-10-24 Thread David Francis
dmaunmap can call ttm_bo_validate, which expects the
ttm dma_resv to be held.

Acquire the locks in amdgpu_amdkfd_gpuvm_dmaunmap_mem.

Because the dmaunmap step can now fail, two new numbers
need to be tracked. n_dmaunmap_success tracks the number
of devices that have completed dmaunmap. If a device fails
to dmaunmap due to a signal interrupt, n_dmaunmap_bos tracks
the number of bos on that device that were successfully
dmaunmapped.

Track those values in struct kgd_mem.

This failure can also cause the sync_memory step of the ioctl
to be repeated; it is idempotent, so this should not cause any issues.

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h|  6 -
 .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c  | 23 +++
 drivers/gpu/drm/amd/amdkfd/kfd_chardev.c  | 19 ++-
 3 files changed, 37 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
index 3ad8dc523b42..c60564ec4312 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
@@ -86,6 +86,10 @@ struct kgd_mem {
 
bool aql_queue;
bool is_imported;
+
+   /* Used to track successful dmaunmap across retries in unmap ioctl */
+   uint32_t n_dmaunmap_success;
+   uint32_t n_dmaunmap_bos;
 };
 
 /* KFD Memory Eviction */
@@ -302,7 +306,7 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(struct 
amdgpu_device *adev,
  struct kgd_mem *mem, void *drm_priv);
 int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
struct amdgpu_device *adev, struct kgd_mem *mem, void 
*drm_priv);
-void amdgpu_amdkfd_gpuvm_dmaunmap_mem(struct kgd_mem *mem, void *drm_priv);
+int amdgpu_amdkfd_gpuvm_dmaunmap_mem(struct kgd_mem *mem, void *drm_priv);
 int amdgpu_amdkfd_gpuvm_sync_memory(
struct amdgpu_device *adev, struct kgd_mem *mem, bool intr);
 int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct kgd_mem *mem,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index 54f31a420229..c431132d7cc1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -2102,21 +2102,36 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
return ret;
 }
 
-void amdgpu_amdkfd_gpuvm_dmaunmap_mem(struct kgd_mem *mem, void *drm_priv)
+int amdgpu_amdkfd_gpuvm_dmaunmap_mem(struct kgd_mem *mem, void *drm_priv)
 {
struct kfd_mem_attachment *entry;
struct amdgpu_vm *vm;
+   int ret;
+   int i = 0;
 
vm = drm_priv_to_vm(drm_priv);
 
mutex_lock(>lock);
 
list_for_each_entry(entry, >attachments, list) {
-   if (entry->bo_va->base.vm == vm)
-   kfd_mem_dmaunmap_attachment(mem, entry);
-   }
+   if (i >= mem->n_dmaunmap_bos) {
+   ret = amdgpu_bo_reserve(entry->bo_va->base.bo, false);
+   if (ret) {
+   mem->n_dmaunmap_bos = i;
+   goto out;
+   }
+
+   if (entry->bo_va->base.vm == vm)
+   kfd_mem_dmaunmap_attachment(mem, entry);
 
+   amdgpu_bo_unreserve(entry->bo_va->base.bo);
+   }
+   i++;
+   }
+   mem->n_dmaunmap_bos = 0;
+out:
mutex_unlock(>lock);
+   return ret;
 }
 
 int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
index 06988cf1db51..66dee67ad859 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
@@ -1366,7 +1366,7 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file 
*filep,
 {
struct kfd_ioctl_unmap_memory_from_gpu_args *args = data;
struct kfd_process_device *pdd, *peer_pdd;
-   void *mem;
+   struct kgd_mem *mem;
long err = 0;
uint32_t *devices_arr = NULL, i;
bool flush_tlb;
@@ -1400,7 +1400,7 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file 
*filep,
goto bind_process_to_device_failed;
}
 
-   mem = kfd_process_device_translate_handle(pdd,
+   mem = (struct kgd_mem *)kfd_process_device_translate_handle(pdd,
GET_IDR_HANDLE(args->handle));
if (!mem) {
err = -ENOMEM;
@@ -1414,7 +1414,7 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file 
*filep,
goto get_mem_obj_from_handle_failed;
}
err = amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
-   peer_pdd->dev->adev, (struct kgd_mem *)mem, 
peer_pdd->drm_priv);
+   peer_pdd->

[PATCH v3] drm/amdgpu: Add EXT_COHERENT support for APU and NUMA systems

2023-10-24 Thread David Francis
On gfx943 APU, EXT_COHERENT should give MTYPE_CC for local and
MTYPE_UC for nonlocal memory.

On NUMA systems, local memory gets the local mtype, set by an
override callback. If EXT_COHERENT is set, memory will be set as
MTYPE_UC by default, with local memory MTYPE_CC.

Add an option in the override function for this case, and
add a check to ensure it is not used on UNCACHED memory.

V2: Combined APU and NUMA code into one patch
V3: Fixed a potential nullptr in amdgpu_vm_bo_update

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c| 17 +++-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h|  8 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c |  2 +-
 drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 33 +++
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c  |  8 +++---
 5 files changed, 45 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index d72daf15662f..155c04589753 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -761,6 +761,7 @@ static void amdgpu_vm_tlb_seq_cb(struct dma_fence *fence,
  * @immediate: immediate submission in a page fault
  * @unlocked: unlocked invalidation during MM callback
  * @flush_tlb: trigger tlb invalidation after update completed
+ * @allow_override: change MTYPE for local NUMA nodes
  * @resv: fences we need to sync to
  * @start: start of mapped range
  * @last: last mapped entry
@@ -777,7 +778,7 @@ static void amdgpu_vm_tlb_seq_cb(struct dma_fence *fence,
  * 0 for success, negative erro code for failure.
  */
 int amdgpu_vm_update_range(struct amdgpu_device *adev, struct amdgpu_vm *vm,
-  bool immediate, bool unlocked, bool flush_tlb,
+  bool immediate, bool unlocked, bool flush_tlb, bool 
allow_override,
   struct dma_resv *resv, uint64_t start, uint64_t last,
   uint64_t flags, uint64_t offset, uint64_t vram_base,
   struct ttm_resource *res, dma_addr_t *pages_addr,
@@ -815,6 +816,7 @@ int amdgpu_vm_update_range(struct amdgpu_device *adev, 
struct amdgpu_vm *vm,
params.immediate = immediate;
params.pages_addr = pages_addr;
params.unlocked = unlocked;
+   params.allow_override = allow_override;
 
/* Implicitly sync to command submissions in the same VM before
 * unmapping. Sync to moving fences before mapping.
@@ -990,6 +992,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct 
amdgpu_bo_va *bo_va,
struct ttm_resource *mem;
struct dma_fence **last_update;
bool flush_tlb = clear;
+   bool uncached;
struct dma_resv *resv;
uint64_t vram_base;
uint64_t flags;
@@ -1027,9 +1030,11 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, 
struct amdgpu_bo_va *bo_va,
 
bo_adev = amdgpu_ttm_adev(bo->tbo.bdev);
vram_base = bo_adev->vm_manager.vram_base_offset;
+   uncached = (bo->flags & AMDGPU_GEM_CREATE_UNCACHED) != 0;
} else {
flags = 0x0;
vram_base = 0;
+   uncached = false;
}
 
if (clear || (bo && bo->tbo.base.resv ==
@@ -1063,7 +1068,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, 
struct amdgpu_bo_va *bo_va,
trace_amdgpu_vm_bo_update(mapping);
 
r = amdgpu_vm_update_range(adev, vm, false, false, flush_tlb,
-  resv, mapping->start, mapping->last,
+  !uncached, resv, mapping->start, 
mapping->last,
   update_flags, mapping->offset,
   vram_base, mem, pages_addr,
   last_update);
@@ -1258,8 +1263,8 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
mapping->start < AMDGPU_GMC_HOLE_START)
init_pte_value = AMDGPU_PTE_DEFAULT_ATC;
 
-   r = amdgpu_vm_update_range(adev, vm, false, false, true, resv,
-  mapping->start, mapping->last,
+   r = amdgpu_vm_update_range(adev, vm, false, false, true, false,
+  resv, mapping->start, mapping->last,
   init_pte_value, 0, 0, NULL, NULL,
   );
amdgpu_vm_free_mapping(adev, vm, mapping, f);
@@ -2547,8 +2552,8 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, 
u32 pasid,
goto error_unlock;
}
 
-   r = amdgpu_vm_update_range(adev, vm, true, false, false, NULL, addr,
-  addr, flags, value, 0, NULL, NULL, NULL);
+   r = a

[PATCH v2] drm/amdgpu: Add EXT_COHERENT support for APU and NUMA systems

2023-10-19 Thread David Francis
On gfx943 APU, EXT_COHERENT should give MTYPE_CC for local and
MTYPE_UC for nonlocal memory.

On NUMA systems, local memory gets the local mtype, set by an
override callback. If EXT_COHERENT is set, memory will be set as
MTYPE_UC by default, with local memory MTYPE_CC.

Add an option in the override function for this case, and
add a check to ensure it is not used on UNCACHED memory.

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c| 13 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h|  8 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c |  2 +-
 drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 33 +++
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c  |  8 +++---
 5 files changed, 42 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 46d27c87..189341944bf1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -761,6 +761,7 @@ static void amdgpu_vm_tlb_seq_cb(struct dma_fence *fence,
  * @immediate: immediate submission in a page fault
  * @unlocked: unlocked invalidation during MM callback
  * @flush_tlb: trigger tlb invalidation after update completed
+ * @allow_override: change MTYPE for local NUMA nodes
  * @resv: fences we need to sync to
  * @start: start of mapped range
  * @last: last mapped entry
@@ -777,7 +778,7 @@ static void amdgpu_vm_tlb_seq_cb(struct dma_fence *fence,
  * 0 for success, negative erro code for failure.
  */
 int amdgpu_vm_update_range(struct amdgpu_device *adev, struct amdgpu_vm *vm,
-  bool immediate, bool unlocked, bool flush_tlb,
+  bool immediate, bool unlocked, bool flush_tlb, bool 
allow_override,
   struct dma_resv *resv, uint64_t start, uint64_t last,
   uint64_t flags, uint64_t offset, uint64_t vram_base,
   struct ttm_resource *res, dma_addr_t *pages_addr,
@@ -815,6 +816,7 @@ int amdgpu_vm_update_range(struct amdgpu_device *adev, 
struct amdgpu_vm *vm,
params.immediate = immediate;
params.pages_addr = pages_addr;
params.unlocked = unlocked;
+   params.allow_override = allow_override;
 
/* Implicitly sync to command submissions in the same VM before
 * unmapping. Sync to moving fences before mapping.
@@ -1062,6 +1064,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, 
struct amdgpu_bo_va *bo_va,
trace_amdgpu_vm_bo_update(mapping);
 
r = amdgpu_vm_update_range(adev, vm, false, false, flush_tlb,
+  !(bo->flags & 
AMDGPU_GEM_CREATE_UNCACHED),
   resv, mapping->start, mapping->last,
   update_flags, mapping->offset,
   vram_base, mem, pages_addr,
@@ -1257,8 +1260,8 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
mapping->start < AMDGPU_GMC_HOLE_START)
init_pte_value = AMDGPU_PTE_DEFAULT_ATC;
 
-   r = amdgpu_vm_update_range(adev, vm, false, false, true, resv,
-  mapping->start, mapping->last,
+   r = amdgpu_vm_update_range(adev, vm, false, false, true, false,
+  resv, mapping->start, mapping->last,
   init_pte_value, 0, 0, NULL, NULL,
   );
amdgpu_vm_free_mapping(adev, vm, mapping, f);
@@ -2546,8 +2549,8 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, 
u32 pasid,
goto error_unlock;
}
 
-   r = amdgpu_vm_update_range(adev, vm, true, false, false, NULL, addr,
-  addr, flags, value, 0, NULL, NULL, NULL);
+   r = amdgpu_vm_update_range(adev, vm, true, false, false, false,
+  NULL, addr, addr, flags, value, 0, NULL, 
NULL, NULL);
if (r)
goto error_unlock;
 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
index 6e71978db13f..9ea8b5b644e3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
@@ -244,6 +244,12 @@ struct amdgpu_vm_update_params {
 * @table_freed: return true if page table is freed when updating
 */
bool table_freed;
+
+   /**
+* @allow_override: true for memory that is not uncached: allows MTYPE
+* to be overridden for NUMA local memory.
+*/
+   bool allow_override;
 };
 
 struct amdgpu_vm_update_funcs {
@@ -436,7 +442,7 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev,
 void amdgpu_vm_bo_base_init(struct amdgpu_vm_bo_base *base,
struct amdgpu_v

[PATCH V2 2/2] drm/amdgpu: Permit PCIe transfer over links with XGMI

2023-10-16 Thread David Francis
When the CPU is XGMI connected, the PCIe links should
not be enumerated for topology purposes. However, PCIe
transfer should still be a valid option for remote
doorbells and MMIO mappings.

Move the XGMI connection check out of the shared helper
function amdgpu_device_is_peer_accessible and into the
topology path.

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 4 +---
 drivers/gpu/drm/amd/amdkfd/kfd_topology.c  | 6 --
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index bad2b5577e96..b47cb7f8cfbd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -5753,9 +5753,7 @@ bool amdgpu_device_is_peer_accessible(struct 
amdgpu_device *adev,
~*peer_adev->dev->dma_mask : ~((1ULL << 32) - 1);
resource_size_t aper_limit =
adev->gmc.aper_base + adev->gmc.aper_size - 1;
-   bool p2p_access =
-   !adev->gmc.xgmi.connected_to_cpu &&
-   !(pci_p2pdma_distance(adev->pdev, peer_adev->dev, false) < 0);
+   bool p2p_access = !(pci_p2pdma_distance(adev->pdev, peer_adev->dev, 
false) < 0);
 
return pcie_p2p && p2p_access && (adev->gmc.visible_vram_size &&
adev->gmc.real_vram_size == adev->gmc.visible_vram_size &&
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
index 4e530791507e..cb64c19482f3 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
@@ -1514,11 +1514,13 @@ static int kfd_dev_create_p2p_links(void)
goto next;
 
/* check if node(s) is/are peer accessible in one direction or 
bi-direction */
-   ret = kfd_add_peer_prop(new_dev, dev, i, k);
+   if (!new_dev->gpu->adev->gmc.xgmi.connected_to_cpu)
+   ret = kfd_add_peer_prop(new_dev, dev, i, k);
if (ret < 0)
goto out;
 
-   ret = kfd_add_peer_prop(dev, new_dev, k, i);
+   if (!dev->gpu->adev->gmc.xgmi.connected_to_cpu)
+   ret = kfd_add_peer_prop(dev, new_dev, k, i);
if (ret < 0)
goto out;
 next:
-- 
2.34.1



[PATCH V2 1/2] drm/amdgpu: Acquire ttm locks for dmaunmap

2023-10-16 Thread David Francis
dmaunmap can call ttm_bo_validate, which expects the
ttm dma_resv to be held.

Acquire the locks in amdgpu_amdkfd_gpuvm_dmaunmap_mem.

Because the dmaunmap step can now fail, the unmap ioctl UAPI
needs two new arguments. n_dmaunmap_success tracks the number
of devices that have completed dmaunmap. If a device fails
to dmaunmap due to a signal interrupt, n_dmaunmap_bos tracks
the number of bos on that device that were successfully
dmaunmapped.

This failure can also cause the sync_memory step of the ioctl
to be repeated; it is idempotent, so this should not cause any issues.

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h|  2 +-
 .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c  | 23 +++
 drivers/gpu/drm/amd/amdkfd/kfd_chardev.c  | 14 +--
 include/uapi/linux/kfd_ioctl.h|  2 ++
 4 files changed, 34 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
index 3ad8dc523b42..781642871900 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
@@ -302,7 +302,7 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(struct 
amdgpu_device *adev,
  struct kgd_mem *mem, void *drm_priv);
 int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
struct amdgpu_device *adev, struct kgd_mem *mem, void 
*drm_priv);
-void amdgpu_amdkfd_gpuvm_dmaunmap_mem(struct kgd_mem *mem, void *drm_priv);
+int amdgpu_amdkfd_gpuvm_dmaunmap_mem(struct kgd_mem *mem, void *drm_priv, 
uint32_t *num_bos);
 int amdgpu_amdkfd_gpuvm_sync_memory(
struct amdgpu_device *adev, struct kgd_mem *mem, bool intr);
 int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct kgd_mem *mem,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index a15e59abe70a..cbd6032f3d39 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -2094,21 +2094,36 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
return ret;
 }
 
-void amdgpu_amdkfd_gpuvm_dmaunmap_mem(struct kgd_mem *mem, void *drm_priv)
+int amdgpu_amdkfd_gpuvm_dmaunmap_mem(struct kgd_mem *mem, void *drm_priv, 
uint32_t *num_bos)
 {
struct kfd_mem_attachment *entry;
struct amdgpu_vm *vm;
+   int ret;
+   int i = 0;
 
vm = drm_priv_to_vm(drm_priv);
 
mutex_lock(>lock);
 
list_for_each_entry(entry, >attachments, list) {
-   if (entry->bo_va->base.vm == vm)
-   kfd_mem_dmaunmap_attachment(mem, entry);
-   }
+   if (i >= *num_bos) {
+   ret = amdgpu_bo_reserve(entry->bo_va->base.bo, false);
+   if (ret) {
+   *num_bos = i;
+   goto out;
+   }
+
+   if (entry->bo_va->base.vm == vm)
+   kfd_mem_dmaunmap_attachment(mem, entry);
 
+   amdgpu_bo_unreserve(entry->bo_va->base.bo);
+   }
+   i++;
+   }
+   *num_bos = 0;
+out:
mutex_unlock(>lock);
+   return ret;
 }
 
 int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
index 06988cf1db51..a944e255de4a 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
@@ -1379,6 +1379,10 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file 
*filep,
pr_debug("n_success exceeds n_devices\n");
return -EINVAL;
}
+   if (args->n_dmaunmap_success > args->n_devices) {
+   pr_debug("n_dmaunmap_success exceeds n_devices\n");
+   return -EINVAL;
+   }
 
devices_arr = kmalloc_array(args->n_devices, sizeof(*devices_arr),
GFP_KERNEL);
@@ -1434,7 +1438,7 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file 
*filep,
}
 
/* Flush TLBs after waiting for the page table updates to complete */
-   for (i = 0; i < args->n_devices; i++) {
+   for (i = args->n_dmaunmap_success; i < args->n_devices; i++) {
peer_pdd = kfd_process_device_data_by_id(p, devices_arr[i]);
if (WARN_ON_ONCE(!peer_pdd))
continue;
@@ -1442,7 +1446,12 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file 
*filep,
kfd_flush_tlb(peer_pdd, TLB_FLUSH_HEAVYWEIGHT);
 
/* Remove dma mapping after tlb flush to avoid IO_PAGE_FAULT */
-   amdgpu_amdkfd_gpuvm_dmaunmap_mem(mem, peer_pdd->drm_priv);
+   err = amdgpu_amdkfd_gpuvm_dmaunmap_mem(mem, peer_pdd->drm_

[PATCH] drm/amdgpu: Add EXT_COHERENT override for NUMA local nodes

2023-10-12 Thread David Francis
On NUMA systems, local memory gets the local mtype, set by an
override callback. If EXT_COHERENT is set, memory will be set as
MTYPE_UC by default, with local memory MTYPE_CC.

Add an option in the override function for this case, and
add a check to ensure it is not used on UNCACHED memory.

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c| 13 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h|  8 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c |  2 +-
 drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 33 +++
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c  |  6 ++---
 5 files changed, 41 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 46d27c87..189341944bf1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -761,6 +761,7 @@ static void amdgpu_vm_tlb_seq_cb(struct dma_fence *fence,
  * @immediate: immediate submission in a page fault
  * @unlocked: unlocked invalidation during MM callback
  * @flush_tlb: trigger tlb invalidation after update completed
+ * @allow_override: change MTYPE for local NUMA nodes
  * @resv: fences we need to sync to
  * @start: start of mapped range
  * @last: last mapped entry
@@ -777,7 +778,7 @@ static void amdgpu_vm_tlb_seq_cb(struct dma_fence *fence,
  * 0 for success, negative erro code for failure.
  */
 int amdgpu_vm_update_range(struct amdgpu_device *adev, struct amdgpu_vm *vm,
-  bool immediate, bool unlocked, bool flush_tlb,
+  bool immediate, bool unlocked, bool flush_tlb, bool 
allow_override,
   struct dma_resv *resv, uint64_t start, uint64_t last,
   uint64_t flags, uint64_t offset, uint64_t vram_base,
   struct ttm_resource *res, dma_addr_t *pages_addr,
@@ -815,6 +816,7 @@ int amdgpu_vm_update_range(struct amdgpu_device *adev, 
struct amdgpu_vm *vm,
params.immediate = immediate;
params.pages_addr = pages_addr;
params.unlocked = unlocked;
+   params.allow_override = allow_override;
 
/* Implicitly sync to command submissions in the same VM before
 * unmapping. Sync to moving fences before mapping.
@@ -1062,6 +1064,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, 
struct amdgpu_bo_va *bo_va,
trace_amdgpu_vm_bo_update(mapping);
 
r = amdgpu_vm_update_range(adev, vm, false, false, flush_tlb,
+  !(bo->flags & 
AMDGPU_GEM_CREATE_UNCACHED),
   resv, mapping->start, mapping->last,
   update_flags, mapping->offset,
   vram_base, mem, pages_addr,
@@ -1257,8 +1260,8 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
mapping->start < AMDGPU_GMC_HOLE_START)
init_pte_value = AMDGPU_PTE_DEFAULT_ATC;
 
-   r = amdgpu_vm_update_range(adev, vm, false, false, true, resv,
-  mapping->start, mapping->last,
+   r = amdgpu_vm_update_range(adev, vm, false, false, true, false,
+  resv, mapping->start, mapping->last,
   init_pte_value, 0, 0, NULL, NULL,
   );
amdgpu_vm_free_mapping(adev, vm, mapping, f);
@@ -2546,8 +2549,8 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, 
u32 pasid,
goto error_unlock;
}
 
-   r = amdgpu_vm_update_range(adev, vm, true, false, false, NULL, addr,
-  addr, flags, value, 0, NULL, NULL, NULL);
+   r = amdgpu_vm_update_range(adev, vm, true, false, false, false,
+  NULL, addr, addr, flags, value, 0, NULL, 
NULL, NULL);
if (r)
goto error_unlock;
 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
index 6e71978db13f..9ea8b5b644e3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
@@ -244,6 +244,12 @@ struct amdgpu_vm_update_params {
 * @table_freed: return true if page table is freed when updating
 */
bool table_freed;
+
+   /**
+* @allow_override: true for memory that is not uncached: allows MTYPE
+* to be overridden for NUMA local memory.
+*/
+   bool allow_override;
 };
 
 struct amdgpu_vm_update_funcs {
@@ -436,7 +442,7 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev,
 void amdgpu_vm_bo_base_init(struct amdgpu_vm_bo_base *base,
struct amdgpu_vm *vm, struct amdgpu_bo *bo);
 int amdgpu_vm_update_range(struct amdgpu_

[PATCH 2/2] drm/amdgpu: Permit PCIe transfer over links with XGMI

2023-10-11 Thread David Francis
When the CPU is XGMI connected, the PCIe links should
not be enumerated for topology purposes. However, PCIe
transfer should still be a valid option for memory attachment
that requires it.

Move the XGMI connection check out of the shared helper
function amdgpu_device_is_peer_accessible and into the
topology path.

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 4 +---
 drivers/gpu/drm/amd/amdkfd/kfd_topology.c  | 3 +++
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index bad2b5577e96..b47cb7f8cfbd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -5753,9 +5753,7 @@ bool amdgpu_device_is_peer_accessible(struct 
amdgpu_device *adev,
~*peer_adev->dev->dma_mask : ~((1ULL << 32) - 1);
resource_size_t aper_limit =
adev->gmc.aper_base + adev->gmc.aper_size - 1;
-   bool p2p_access =
-   !adev->gmc.xgmi.connected_to_cpu &&
-   !(pci_p2pdma_distance(adev->pdev, peer_adev->dev, false) < 0);
+   bool p2p_access = !(pci_p2pdma_distance(adev->pdev, peer_adev->dev, 
false) < 0);
 
return pcie_p2p && p2p_access && (adev->gmc.visible_vram_size &&
adev->gmc.real_vram_size == adev->gmc.visible_vram_size &&
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
index 4e530791507e..f0cff5072736 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
@@ -1423,6 +1423,9 @@ static int kfd_add_peer_prop(struct kfd_topology_device 
*kdev,
peer->gpu->adev))
return ret;
 
+   if (kdev->gpu->adev->gmc.xgmi.connected_to_cpu)
+   return ret;
+
iolink1 = list_first_entry(>io_link_props,
struct 
kfd_iolink_properties, list);
if (!iolink1)
-- 
2.34.1



[PATCH 1/2] drm/amdgpu: Acquire ttm locks for dmaunmap

2023-10-11 Thread David Francis
dmaunmap can call ttm_bo_validate, which expects the
ttm dma_resv to be held.

Acquire the locks in amdgpu_amdkfd_gpuvm_dmaunmap_mem.

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h   |  2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 12 +++-
 drivers/gpu/drm/amd/amdkfd/kfd_chardev.c |  7 ++-
 3 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
index 3ad8dc523b42..dba4f6b7a2f9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
@@ -302,7 +302,7 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(struct 
amdgpu_device *adev,
  struct kgd_mem *mem, void *drm_priv);
 int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
struct amdgpu_device *adev, struct kgd_mem *mem, void 
*drm_priv);
-void amdgpu_amdkfd_gpuvm_dmaunmap_mem(struct kgd_mem *mem, void *drm_priv);
+int amdgpu_amdkfd_gpuvm_dmaunmap_mem(struct kgd_mem *mem, void *drm_priv);
 int amdgpu_amdkfd_gpuvm_sync_memory(
struct amdgpu_device *adev, struct kgd_mem *mem, bool intr);
 int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct kgd_mem *mem,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index a15e59abe70a..808deec8aa58 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -2094,21 +2094,31 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
return ret;
 }
 
-void amdgpu_amdkfd_gpuvm_dmaunmap_mem(struct kgd_mem *mem, void *drm_priv)
+int amdgpu_amdkfd_gpuvm_dmaunmap_mem(struct kgd_mem *mem, void *drm_priv)
 {
struct kfd_mem_attachment *entry;
struct amdgpu_vm *vm;
+   struct bo_vm_reservation_context ctx;
+   int ret;
 
vm = drm_priv_to_vm(drm_priv);
 
mutex_lock(>lock);
 
+   ret = reserve_bo_and_cond_vms(mem, vm, BO_VM_MAPPED, );
+   if (ret)
+   goto out;
+
list_for_each_entry(entry, >attachments, list) {
if (entry->bo_va->base.vm == vm)
kfd_mem_dmaunmap_attachment(mem, entry);
}
 
+   unreserve_bo_and_vms(, false, false);
+
+out:
mutex_unlock(>lock);
+   return ret;
 }
 
 int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
index 06988cf1db51..21d4e7d46238 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
@@ -1442,7 +1442,11 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file 
*filep,
kfd_flush_tlb(peer_pdd, TLB_FLUSH_HEAVYWEIGHT);
 
/* Remove dma mapping after tlb flush to avoid IO_PAGE_FAULT */
-   amdgpu_amdkfd_gpuvm_dmaunmap_mem(mem, peer_pdd->drm_priv);
+   err = amdgpu_amdkfd_gpuvm_dmaunmap_mem(mem, peer_pdd->drm_priv);
+   if (err) {
+   pr_debug("DMA unmapping failed\n");
+   goto dmaunmap_failed;
+   }
}
 
mutex_unlock(>mutex);
@@ -1455,6 +1459,7 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file 
*filep,
 get_mem_obj_from_handle_failed:
 unmap_memory_from_gpu_failed:
 sync_memory_failed:
+dmaunmap_failed:
mutex_unlock(>mutex);
 copy_from_user_failed:
kfree(devices_arr);
-- 
2.34.1



[PATCH v4] drm/amdgpu: Add EXT_COHERENT memory allocation flags

2023-09-14 Thread David Francis
These flags (for GEM and SVM allocations) allocate
memory that allows for system-scope atomic semantics.

On GFX943 these flags cause caches to be avoided on
non-local memory.

On all other ASICs they are identical in functionality to the
equivalent COHERENT flags.

Corresponding Thunk patch is at
https://github.com/RadeonOpenCompute/ROCT-Thunk-Interface/pull/88

v3: changed name of flag
v4: added checks for invalid flag combinations

Reviewed-by: David Yat Sin w
Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c |  7 +++
 drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c  |  1 +
 drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c   |  1 +
 drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c   |  1 +
 drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c|  5 -
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 10 +-
 include/uapi/drm/amdgpu_drm.h| 10 +-
 include/uapi/linux/kfd_ioctl.h   |  3 +++
 8 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index b5b940485059..ec9e9e95e5f4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -1738,9 +1738,16 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
 
if (flags & KFD_IOC_ALLOC_MEM_FLAGS_COHERENT)
alloc_flags |= AMDGPU_GEM_CREATE_COHERENT;
+   if (flags & KFD_IOC_ALLOC_MEM_FLAGS_EXT_COHERENT)
+   alloc_flags |= AMDGPU_GEM_CREATE_EXT_COHERENT;
if (flags & KFD_IOC_ALLOC_MEM_FLAGS_UNCACHED)
alloc_flags |= AMDGPU_GEM_CREATE_UNCACHED;
 
+   if (((flags & KFD_IOC_ALLOC_MEM_FLAGS_COHERENT) && (flags & 
KFD_IOC_ALLOC_MEM_FLAGS_EXT_COHERENT)) ||
+   ((flags & KFD_IOC_ALLOC_MEM_FLAGS_UNCACHED) && (flags & 
KFD_IOC_ALLOC_MEM_FLAGS_EXT_COHERENT)) ||
+   ((flags & KFD_IOC_ALLOC_MEM_FLAGS_COHERENT) && (flags & 
KFD_IOC_ALLOC_MEM_FLAGS_UNCACHED)))
+   return -EINVAL; 
+
*mem = kzalloc(sizeof(struct kgd_mem), GFP_KERNEL);
if (!*mem) {
ret = -ENOMEM;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
index 12210598e5b8..76b618735dc0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -331,6 +331,7 @@ amdgpu_dma_buf_create_obj(struct drm_device *dev, struct 
dma_buf *dma_buf)
 
flags |= other->flags & (AMDGPU_GEM_CREATE_CPU_GTT_USWC |
 AMDGPU_GEM_CREATE_COHERENT |
+AMDGPU_GEM_CREATE_EXT_COHERENT |
 AMDGPU_GEM_CREATE_UNCACHED);
}
 
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c 
b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
index fa87a85e1017..c45fde9f1887 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
@@ -634,6 +634,7 @@ static void gmc_v10_0_get_vm_pte(struct amdgpu_device *adev,
}
 
if (bo && bo->flags & (AMDGPU_GEM_CREATE_COHERENT |
+  AMDGPU_GEM_CREATE_EXT_COHERENT |
   AMDGPU_GEM_CREATE_UNCACHED))
*flags = (*flags & ~AMDGPU_PTE_MTYPE_NV10_MASK) |
 AMDGPU_PTE_MTYPE_NV10(MTYPE_UC);
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c 
b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
index 671e288c7575..dd135d8b25f7 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
@@ -543,6 +543,7 @@ static void gmc_v11_0_get_vm_pte(struct amdgpu_device *adev,
}
 
if (bo && bo->flags & (AMDGPU_GEM_CREATE_COHERENT |
+  AMDGPU_GEM_CREATE_EXT_COHERENT |
   AMDGPU_GEM_CREATE_UNCACHED))
*flags = (*flags & ~AMDGPU_PTE_MTYPE_NV10_MASK) |
 AMDGPU_PTE_MTYPE_NV10(MTYPE_UC);
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c 
b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
index 3d13d0bba7b1..e63d9c39fc35 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
@@ -1185,7 +1185,8 @@ static void gmc_v9_0_get_coherence_flags(struct 
amdgpu_device *adev,
 {
struct amdgpu_device *bo_adev = amdgpu_ttm_adev(bo->tbo.bdev);
bool is_vram = bo->tbo.resource->mem_type == TTM_PL_VRAM;
-   bool coherent = bo->flags & AMDGPU_GEM_CREATE_COHERENT;
+   bool coherent = bo->flags & (AMDGPU_GEM_CREATE_COHERENT | 
AMDGPU_GEM_CREATE_EXT_COHERENT);
+   bool ext_coherent = bo->flags & AMDGPU_GEM_CREATE_EXT_COHERENT;
bool uncached = bo->flags & AMDGPU_GEM_CREAT

[PATCH v2] drm/amdgpu: Handle null atom context in VBIOS info ioctl

2023-09-11 Thread David Francis
On some APU systems, there is no atom context and so the
atom_context struct is null.

Add a check to the VBIOS_INFO branch of amdgpu_info_ioctl
to handle this case, returning all zeroes.

v2: Maintain current use of {} initialization.

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 17 +++--
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index d462b36adf4b..a74ea53899f6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -951,12 +951,17 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, 
struct drm_file *filp)
struct atom_context *atom_context;
 
atom_context = adev->mode_info.atom_context;
-   memcpy(vbios_info.name, atom_context->name, 
sizeof(atom_context->name));
-   memcpy(vbios_info.vbios_pn, atom_context->vbios_pn, 
sizeof(atom_context->vbios_pn));
-   vbios_info.version = atom_context->version;
-   memcpy(vbios_info.vbios_ver_str, 
atom_context->vbios_ver_str,
-   
sizeof(atom_context->vbios_ver_str));
-   memcpy(vbios_info.date, atom_context->date, 
sizeof(atom_context->date));
+   if (atom_context) {
+   memcpy(vbios_info.name, atom_context->name,
+  sizeof(atom_context->name));
+   memcpy(vbios_info.vbios_pn, 
atom_context->vbios_pn,
+  sizeof(atom_context->vbios_pn));
+   vbios_info.version = atom_context->version;
+   memcpy(vbios_info.vbios_ver_str, 
atom_context->vbios_ver_str,
+  sizeof(atom_context->vbios_ver_str));
+   memcpy(vbios_info.date, atom_context->date,
+  sizeof(atom_context->date));
+   }
 
return copy_to_user(out, _info,
min((size_t)size, 
sizeof(vbios_info))) ? -EFAULT : 0;
-- 
2.34.1



[PATCH] drm/amdgpu: Handle null atom context in VBIOS info ioctl

2023-09-05 Thread David Francis
On some APU systems, there is no atom context and so the
atom_context struct is null.

Add a check to the VBIOS_INFO branch of amdgpu_info_ioctl
to handle this case, returning all zeroes.

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 19 ---
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index 3a48bec10aea..86748290ead7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -947,16 +947,21 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, 
struct drm_file *filp)
? -EFAULT : 0;
}
case AMDGPU_INFO_VBIOS_INFO: {
-   struct drm_amdgpu_info_vbios vbios_info = {};
+   struct drm_amdgpu_info_vbios vbios_info = {0};
struct atom_context *atom_context;
 
atom_context = adev->mode_info.atom_context;
-   memcpy(vbios_info.name, atom_context->name, 
sizeof(atom_context->name));
-   memcpy(vbios_info.vbios_pn, atom_context->vbios_pn, 
sizeof(atom_context->vbios_pn));
-   vbios_info.version = atom_context->version;
-   memcpy(vbios_info.vbios_ver_str, 
atom_context->vbios_ver_str,
-   
sizeof(atom_context->vbios_ver_str));
-   memcpy(vbios_info.date, atom_context->date, 
sizeof(atom_context->date));
+   if (atom_context) {
+   memcpy(vbios_info.name, atom_context->name,
+  sizeof(atom_context->name));
+   memcpy(vbios_info.vbios_pn, 
atom_context->vbios_pn,
+  sizeof(atom_context->vbios_pn));
+   vbios_info.version = atom_context->version;
+   memcpy(vbios_info.vbios_ver_str, 
atom_context->vbios_ver_str,
+  sizeof(atom_context->vbios_ver_str));
+   memcpy(vbios_info.date, atom_context->date,
+  sizeof(atom_context->date));
+   }
 
return copy_to_user(out, _info,
min((size_t)size, 
sizeof(vbios_info))) ? -EFAULT : 0;
-- 
2.34.1



[PATCH] drm/amdkfd: Checkpoint and restore queues on GFX11

2023-08-25 Thread David Francis
The code in kfd_mqd_manager_v11.c to support criu dump and
restore of queue state was missing.

Added it; should be equivalent to kfd_mqd_manager_v10.c.

CC: Felix Kuehling 
Signed-off-by: David Francis 
---
 .../gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c  | 41 +++
 1 file changed, 41 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c
index 2319467d2d95..2a79d37da95d 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c
@@ -321,6 +321,43 @@ static int get_wave_state(struct mqd_manager *mm, void 
*mqd,
return 0;
 }
 
+static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst, 
void *ctl_stack_dst)
+{
+   struct v11_compute_mqd *m;
+
+   m = get_mqd(mqd);
+
+   memcpy(mqd_dst, m, sizeof(struct v11_compute_mqd));
+}
+
+static void restore_mqd(struct mqd_manager *mm, void **mqd,
+   struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr,
+   struct queue_properties *qp,
+   const void *mqd_src,
+   const void *ctl_stack_src, const u32 ctl_stack_size)
+{
+   uint64_t addr;
+   struct v11_compute_mqd *m;
+
+   m = (struct v11_compute_mqd *) mqd_mem_obj->cpu_ptr;
+   addr = mqd_mem_obj->gpu_addr;
+
+   memcpy(m, mqd_src, sizeof(*m));
+
+   *mqd = m;
+   if (gart_addr)
+   *gart_addr = addr;
+
+   m->cp_hqd_pq_doorbell_control =
+   qp->doorbell_off <<
+   CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_OFFSET__SHIFT;
+   pr_debug("cp_hqd_pq_doorbell_control 0x%x\n",
+   m->cp_hqd_pq_doorbell_control);
+
+   qp->is_active = 0;
+}
+
+
 static void init_mqd_hiq(struct mqd_manager *mm, void **mqd,
struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr,
struct queue_properties *q)
@@ -457,6 +494,8 @@ struct mqd_manager *mqd_manager_init_v11(enum KFD_MQD_TYPE 
type,
mqd->is_occupied = kfd_is_occupied_cp;
mqd->mqd_size = sizeof(struct v11_compute_mqd);
mqd->get_wave_state = get_wave_state;
+   mqd->checkpoint_mqd = checkpoint_mqd;
+   mqd->restore_mqd = restore_mqd;
 #if defined(CONFIG_DEBUG_FS)
mqd->debugfs_show_mqd = debugfs_show_mqd;
 #endif
@@ -500,6 +539,8 @@ struct mqd_manager *mqd_manager_init_v11(enum KFD_MQD_TYPE 
type,
mqd->update_mqd = update_mqd_sdma;
mqd->destroy_mqd = kfd_destroy_mqd_sdma;
mqd->is_occupied = kfd_is_occupied_sdma;
+   mqd->checkpoint_mqd = checkpoint_mqd;
+   mqd->restore_mqd = restore_mqd;
mqd->mqd_size = sizeof(struct v11_sdma_mqd);
 #if defined(CONFIG_DEBUG_FS)
mqd->debugfs_show_mqd = debugfs_show_mqd_sdma;
-- 
2.34.1



[PATCH v3] drm/amdgpu: Add EXT_COHERENT memory allocation flags

2023-07-28 Thread David Francis
These flags (for GEM and SVM allocations) allocate
memory that allows for system-scope atomic semantics.

On GFX943 these flags cause caches to be avoided on
non-local memory.

On all other ASICs they are identical in functionality to the
equivalent COHERENT flags.

Corresponding Thunk patch is at
https://github.com/RadeonOpenCompute/ROCT-Thunk-Interface/pull/88

v3: changed name of flag

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c |  2 ++
 drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c  |  1 +
 drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c   |  1 +
 drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c   |  1 +
 drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c|  5 -
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 10 +-
 include/uapi/drm/amdgpu_drm.h| 10 +-
 include/uapi/linux/kfd_ioctl.h   |  3 +++
 8 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index d34c3ef8f3ed..a1ce261f2d06 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -1738,6 +1738,8 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
 
if (flags & KFD_IOC_ALLOC_MEM_FLAGS_COHERENT)
alloc_flags |= AMDGPU_GEM_CREATE_COHERENT;
+   if (flags & KFD_IOC_ALLOC_MEM_FLAGS_EXT_COHERENT)
+   alloc_flags |= AMDGPU_GEM_CREATE_EXT_COHERENT;
if (flags & KFD_IOC_ALLOC_MEM_FLAGS_UNCACHED)
alloc_flags |= AMDGPU_GEM_CREATE_UNCACHED;
 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
index 12210598e5b8..76b618735dc0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -331,6 +331,7 @@ amdgpu_dma_buf_create_obj(struct drm_device *dev, struct 
dma_buf *dma_buf)
 
flags |= other->flags & (AMDGPU_GEM_CREATE_CPU_GTT_USWC |
 AMDGPU_GEM_CREATE_COHERENT |
+AMDGPU_GEM_CREATE_EXT_COHERENT |
 AMDGPU_GEM_CREATE_UNCACHED);
}
 
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c 
b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
index 6b430e10d38e..301ffe30824f 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
@@ -632,6 +632,7 @@ static void gmc_v10_0_get_vm_pte(struct amdgpu_device *adev,
}
 
if (bo && bo->flags & (AMDGPU_GEM_CREATE_COHERENT |
+  AMDGPU_GEM_CREATE_EXT_COHERENT |
   AMDGPU_GEM_CREATE_UNCACHED))
*flags = (*flags & ~AMDGPU_PTE_MTYPE_NV10_MASK) |
 AMDGPU_PTE_MTYPE_NV10(MTYPE_UC);
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c 
b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
index a6ee0220db56..846894e212e7 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
@@ -540,6 +540,7 @@ static void gmc_v11_0_get_vm_pte(struct amdgpu_device *adev,
}
 
if (bo && bo->flags & (AMDGPU_GEM_CREATE_COHERENT |
+  AMDGPU_GEM_CREATE_EXT_COHERENT |
   AMDGPU_GEM_CREATE_UNCACHED))
*flags = (*flags & ~AMDGPU_PTE_MTYPE_NV10_MASK) |
 AMDGPU_PTE_MTYPE_NV10(MTYPE_UC);
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c 
b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
index 880460cd3239..92a623e130d9 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
@@ -1183,7 +1183,8 @@ static void gmc_v9_0_get_coherence_flags(struct 
amdgpu_device *adev,
 {
struct amdgpu_device *bo_adev = amdgpu_ttm_adev(bo->tbo.bdev);
bool is_vram = bo->tbo.resource->mem_type == TTM_PL_VRAM;
-   bool coherent = bo->flags & AMDGPU_GEM_CREATE_COHERENT;
+   bool coherent = bo->flags & (AMDGPU_GEM_CREATE_COHERENT | 
AMDGPU_GEM_CREATE_EXT_COHERENT);
+   bool ext_coherent = bo->flags & AMDGPU_GEM_CREATE_EXT_COHERENT;
bool uncached = bo->flags & AMDGPU_GEM_CREATE_UNCACHED;
struct amdgpu_vm *vm = mapping->bo_va->base.vm;
unsigned int mtype_local, mtype;
@@ -1251,6 +1252,8 @@ static void gmc_v9_0_get_coherence_flags(struct 
amdgpu_device *adev,
snoop = true;
if (uncached) {
mtype = MTYPE_UC;
+   } else if (ext_coherent) {
+   mtype = is_local ? MTYPE_CC : MTYPE_UC;
} else if (adev->flags & AMD_IS_APU) {
mtype = is_local ? mtype_local : MTYPE_NC;
} else {
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
b/dr

[PATCH v3] drm/amdgpu: Add EXT_COHERENCE memory allocation flags

2023-07-26 Thread David Francis
These flags (for GEM and SVM allocations) allocate
memory that allows for system-scope atomic semantics.

On GFX943 these flags cause caches to be avoided on
non-local memory.

On all other ASICs they are identical in functionality to the
equivalent COHERENT flags.

Corresponding Thunk patch is at
https://github.com/RadeonOpenCompute/ROCT-Thunk-Interface/pull/88

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c |  2 ++
 drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c   |  1 +
 drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c   |  1 +
 drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c|  5 -
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 10 +-
 include/uapi/drm/amdgpu_drm.h|  7 +++
 include/uapi/linux/kfd_ioctl.h   |  3 +++
 7 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index d34c3ef8f3ed..7f23bc0ee592 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -1738,6 +1738,8 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
 
if (flags & KFD_IOC_ALLOC_MEM_FLAGS_COHERENT)
alloc_flags |= AMDGPU_GEM_CREATE_COHERENT;
+   if (flags & KFD_IOC_ALLOC_MEM_FLAGS_EXT_COHERENCE)
+   alloc_flags |= AMDGPU_GEM_CREATE_EXT_COHERENCE;
if (flags & KFD_IOC_ALLOC_MEM_FLAGS_UNCACHED)
alloc_flags |= AMDGPU_GEM_CREATE_UNCACHED;
 
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c 
b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
index 6b430e10d38e..8e951688668b 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
@@ -632,6 +632,7 @@ static void gmc_v10_0_get_vm_pte(struct amdgpu_device *adev,
}
 
if (bo && bo->flags & (AMDGPU_GEM_CREATE_COHERENT |
+  AMDGPU_GEM_CREATE_EXT_COHERENCE |
   AMDGPU_GEM_CREATE_UNCACHED))
*flags = (*flags & ~AMDGPU_PTE_MTYPE_NV10_MASK) |
 AMDGPU_PTE_MTYPE_NV10(MTYPE_UC);
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c 
b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
index a6ee0220db56..ff330c7c0232 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
@@ -540,6 +540,7 @@ static void gmc_v11_0_get_vm_pte(struct amdgpu_device *adev,
}
 
if (bo && bo->flags & (AMDGPU_GEM_CREATE_COHERENT |
+  AMDGPU_GEM_CREATE_EXT_COHERENCE |
   AMDGPU_GEM_CREATE_UNCACHED))
*flags = (*flags & ~AMDGPU_PTE_MTYPE_NV10_MASK) |
 AMDGPU_PTE_MTYPE_NV10(MTYPE_UC);
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c 
b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
index 880460cd3239..e40fcfc1a3f3 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
@@ -1183,7 +1183,8 @@ static void gmc_v9_0_get_coherence_flags(struct 
amdgpu_device *adev,
 {
struct amdgpu_device *bo_adev = amdgpu_ttm_adev(bo->tbo.bdev);
bool is_vram = bo->tbo.resource->mem_type == TTM_PL_VRAM;
-   bool coherent = bo->flags & AMDGPU_GEM_CREATE_COHERENT;
+   bool coherent = bo->flags & (AMDGPU_GEM_CREATE_COHERENT | 
AMDGPU_GEM_CREATE_EXT_COHERENCE);
+   bool ext_coherence = bo->flags & AMDGPU_GEM_CREATE_EXT_COHERENCE;
bool uncached = bo->flags & AMDGPU_GEM_CREATE_UNCACHED;
struct amdgpu_vm *vm = mapping->bo_va->base.vm;
unsigned int mtype_local, mtype;
@@ -1251,6 +1252,8 @@ static void gmc_v9_0_get_coherence_flags(struct 
amdgpu_device *adev,
snoop = true;
if (uncached) {
mtype = MTYPE_UC;
+   } else if (ext_coherence) {
+   mtype = is_local ? MTYPE_CC : MTYPE_UC;
} else if (adev->flags & AMD_IS_APU) {
mtype = is_local ? mtype_local : MTYPE_NC;
} else {
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index 1b50eae051a4..28304b93a990 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -1155,7 +1155,8 @@ svm_range_get_pte_flags(struct kfd_node *node,
uint32_t mapping_flags = 0;
uint64_t pte_flags;
bool snoop = (domain != SVM_RANGE_VRAM_DOMAIN);
-   bool coherent = flags & KFD_IOCTL_SVM_FLAG_COHERENT;
+   bool coherent = flags & (KFD_IOCTL_SVM_FLAG_COHERENT | 
KFD_IOCTL_SVM_FLAG_EXT_COHERENCE);
+   bool ext_coherence = flags & KFD_IOCTL_SVM_FLAG_EXT_COHERENCE;
bool uncached = false; /*flags & KFD_IOCTL_SVM_FLAG_UNCACHED;*/
unsigned int mtype_local;
 
@@ -1203,6 +

[PATCH v2] drm/amdgpu: Add EXT_COHERENCE memory allocation flags

2023-07-26 Thread David Francis
These flags (for GEM and SVM allocations) allocate
memory that allows for system-scope atomic semantics.

On GFX943 these flags cause caches to be avoided on
non-local memory.

On all other ASICs they are identical in functionality to the
equivalent COHERENT flags.

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c |  2 ++
 drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c   |  1 +
 drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c   |  1 +
 drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c|  5 -
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 10 +-
 include/uapi/drm/amdgpu_drm.h|  7 +++
 include/uapi/linux/kfd_ioctl.h   |  3 +++
 7 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index d34c3ef8f3ed..7f23bc0ee592 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -1738,6 +1738,8 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
 
if (flags & KFD_IOC_ALLOC_MEM_FLAGS_COHERENT)
alloc_flags |= AMDGPU_GEM_CREATE_COHERENT;
+   if (flags & KFD_IOC_ALLOC_MEM_FLAGS_EXT_COHERENCE)
+   alloc_flags |= AMDGPU_GEM_CREATE_EXT_COHERENCE;
if (flags & KFD_IOC_ALLOC_MEM_FLAGS_UNCACHED)
alloc_flags |= AMDGPU_GEM_CREATE_UNCACHED;
 
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c 
b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
index 6b430e10d38e..8e951688668b 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
@@ -632,6 +632,7 @@ static void gmc_v10_0_get_vm_pte(struct amdgpu_device *adev,
}
 
if (bo && bo->flags & (AMDGPU_GEM_CREATE_COHERENT |
+  AMDGPU_GEM_CREATE_EXT_COHERENCE |
   AMDGPU_GEM_CREATE_UNCACHED))
*flags = (*flags & ~AMDGPU_PTE_MTYPE_NV10_MASK) |
 AMDGPU_PTE_MTYPE_NV10(MTYPE_UC);
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c 
b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
index a6ee0220db56..ff330c7c0232 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
@@ -540,6 +540,7 @@ static void gmc_v11_0_get_vm_pte(struct amdgpu_device *adev,
}
 
if (bo && bo->flags & (AMDGPU_GEM_CREATE_COHERENT |
+  AMDGPU_GEM_CREATE_EXT_COHERENCE |
   AMDGPU_GEM_CREATE_UNCACHED))
*flags = (*flags & ~AMDGPU_PTE_MTYPE_NV10_MASK) |
 AMDGPU_PTE_MTYPE_NV10(MTYPE_UC);
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c 
b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
index 880460cd3239..e40fcfc1a3f3 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
@@ -1183,7 +1183,8 @@ static void gmc_v9_0_get_coherence_flags(struct 
amdgpu_device *adev,
 {
struct amdgpu_device *bo_adev = amdgpu_ttm_adev(bo->tbo.bdev);
bool is_vram = bo->tbo.resource->mem_type == TTM_PL_VRAM;
-   bool coherent = bo->flags & AMDGPU_GEM_CREATE_COHERENT;
+   bool coherent = bo->flags & (AMDGPU_GEM_CREATE_COHERENT | 
AMDGPU_GEM_CREATE_EXT_COHERENCE);
+   bool ext_coherence = bo->flags & AMDGPU_GEM_CREATE_EXT_COHERENCE;
bool uncached = bo->flags & AMDGPU_GEM_CREATE_UNCACHED;
struct amdgpu_vm *vm = mapping->bo_va->base.vm;
unsigned int mtype_local, mtype;
@@ -1251,6 +1252,8 @@ static void gmc_v9_0_get_coherence_flags(struct 
amdgpu_device *adev,
snoop = true;
if (uncached) {
mtype = MTYPE_UC;
+   } else if (ext_coherence) {
+   mtype = is_local ? MTYPE_CC : MTYPE_UC;
} else if (adev->flags & AMD_IS_APU) {
mtype = is_local ? mtype_local : MTYPE_NC;
} else {
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index 1b50eae051a4..28304b93a990 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -1155,7 +1155,8 @@ svm_range_get_pte_flags(struct kfd_node *node,
uint32_t mapping_flags = 0;
uint64_t pte_flags;
bool snoop = (domain != SVM_RANGE_VRAM_DOMAIN);
-   bool coherent = flags & KFD_IOCTL_SVM_FLAG_COHERENT;
+   bool coherent = flags & (KFD_IOCTL_SVM_FLAG_COHERENT | 
KFD_IOCTL_SVM_FLAG_EXT_COHERENCE);
+   bool ext_coherence = flags & KFD_IOCTL_SVM_FLAG_EXT_COHERENCE;
bool uncached = false; /*flags & KFD_IOCTL_SVM_FLAG_UNCACHED;*/
unsigned int mtype_local;
 
@@ -1203,6 +1204,13 @@ svm_range_get_pte_flags(struct kfd_node *node,
snoop = true;
i

Re: [PATCH] drm/amdgpu: Add EXT_COHERENCE memory allocation flags

2023-07-24 Thread David Francis

Cover letter got lost, here it is:

This is in support of a RCCL change that requires specific
coherence behaviour.

Corresponding Thunk patch is at
https://github.com/RadeonOpenCompute/ROCT-Thunk-Interface/pull/88


These flags (for GEM and SVM allocations) allocate
memory that allows for system-scope atomic semantics.

On GFX943 these flags cause caches to be avoided on
non-local memory.

On all other ASICs they are identical in functionality to the
equivalent COHERENT flags.

Signed-off-by: David Francis
---
  drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c |  2 ++
  drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c   |  1 +
  drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c   |  1 +
  drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c|  5 -
  drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 10 +-
  include/uapi/drm/amdgpu_drm.h|  7 +++
  include/uapi/linux/kfd_ioctl.h   |  3 +++
  7 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index 9e18fe5eb190..67634e9f6466 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -1790,6 +1790,8 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
  
  	if (flags & KFD_IOC_ALLOC_MEM_FLAGS_COHERENT)

alloc_flags |= AMDGPU_GEM_CREATE_COHERENT;
+   if (flags & KFD_IOC_ALLOC_MEM_FLAGS_EXT_COHERENCE)
+   alloc_flags |= AMDGPU_GEM_CREATE_EXT_COHERENCE;
if (flags & KFD_IOC_ALLOC_MEM_FLAGS_UNCACHED)
alloc_flags |= AMDGPU_GEM_CREATE_UNCACHED;
  
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c

index 1c07459e2bd2..6a6f6068bea0 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
@@ -631,6 +631,7 @@ static void gmc_v10_0_get_vm_pte(struct amdgpu_device *adev,
}
  
  	if (bo && bo->flags & (AMDGPU_GEM_CREATE_COHERENT |

+  AMDGPU_GEM_CREATE_EXT_COHERENCE |
   AMDGPU_GEM_CREATE_UNCACHED))
*flags = (*flags & ~AMDGPU_PTE_MTYPE_NV10_MASK) |
 AMDGPU_PTE_MTYPE_NV10(MTYPE_UC);
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c 
b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
index a6ee0220db56..ff330c7c0232 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
@@ -540,6 +540,7 @@ static void gmc_v11_0_get_vm_pte(struct amdgpu_device *adev,
}
  
  	if (bo && bo->flags & (AMDGPU_GEM_CREATE_COHERENT |

+  AMDGPU_GEM_CREATE_EXT_COHERENCE |
   AMDGPU_GEM_CREATE_UNCACHED))
*flags = (*flags & ~AMDGPU_PTE_MTYPE_NV10_MASK) |
 AMDGPU_PTE_MTYPE_NV10(MTYPE_UC);
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c 
b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
index 8447fcada8bb..17cf19c868e1 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
@@ -1180,7 +1180,8 @@ static void gmc_v9_0_get_coherence_flags(struct 
amdgpu_device *adev,
  {
struct amdgpu_device *bo_adev = amdgpu_ttm_adev(bo->tbo.bdev);
bool is_vram = bo->tbo.resource->mem_type == TTM_PL_VRAM;
-   bool coherent = bo->flags & AMDGPU_GEM_CREATE_COHERENT;
+   bool coherent = bo->flags & (AMDGPU_GEM_CREATE_COHERENT | 
AMDGPU_GEM_CREATE_EXT_COHERENCE);
+   bool ext_coherence = bo->flags & AMDGPU_GEM_CREATE_EXT_COHERENCE;
bool uncached = bo->flags & AMDGPU_GEM_CREATE_UNCACHED;
struct amdgpu_vm *vm = mapping->bo_va->base.vm;
unsigned int mtype_local, mtype;
@@ -1248,6 +1249,8 @@ static void gmc_v9_0_get_coherence_flags(struct 
amdgpu_device *adev,
snoop = true;
if (uncached) {
mtype = MTYPE_UC;
+   } else if (ext_coherence) {
+   mtype = is_local ? MTYPE_CC : MTYPE_UC;
} else if (adev->flags & AMD_IS_APU) {
mtype = is_local ? mtype_local : MTYPE_NC;
} else {
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index 909f1ef8927d..acb87b2fe8df 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -1157,7 +1157,8 @@ svm_range_get_pte_flags(struct kfd_node *node,
uint32_t mapping_flags = 0;
uint64_t pte_flags;
bool snoop = (domain != SVM_RANGE_VRAM_DOMAIN);
-   bool coherent = flags & KFD_IOCTL_SVM_FLAG_COHERENT;
+   bool coherent = flags & (KFD_IOCTL_SVM_FLAG_COHERENT | 
KFD_IOCTL_SVM_FLAG_EXT_COHERENCE);
+   bool ext_coherence = flags & KFD_IOCTL_SVM_FLAG_EXT_COHERENCE;
bool unc

[PATCH] drm/amdgpu: Add EXT_COHERENCE memory allocation flags

2023-07-24 Thread David Francis
These flags (for GEM and SVM allocations) allocate
memory that allows for system-scope atomic semantics.

On GFX943 these flags cause caches to be avoided on
non-local memory.

On all other ASICs they are identical in functionality to the
equivalent COHERENT flags.

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c |  2 ++
 drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c   |  1 +
 drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c   |  1 +
 drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c|  5 -
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 10 +-
 include/uapi/drm/amdgpu_drm.h|  7 +++
 include/uapi/linux/kfd_ioctl.h   |  3 +++
 7 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index 9e18fe5eb190..67634e9f6466 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -1790,6 +1790,8 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
 
if (flags & KFD_IOC_ALLOC_MEM_FLAGS_COHERENT)
alloc_flags |= AMDGPU_GEM_CREATE_COHERENT;
+   if (flags & KFD_IOC_ALLOC_MEM_FLAGS_EXT_COHERENCE)
+   alloc_flags |= AMDGPU_GEM_CREATE_EXT_COHERENCE;
if (flags & KFD_IOC_ALLOC_MEM_FLAGS_UNCACHED)
alloc_flags |= AMDGPU_GEM_CREATE_UNCACHED;
 
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c 
b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
index 1c07459e2bd2..6a6f6068bea0 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
@@ -631,6 +631,7 @@ static void gmc_v10_0_get_vm_pte(struct amdgpu_device *adev,
}
 
if (bo && bo->flags & (AMDGPU_GEM_CREATE_COHERENT |
+  AMDGPU_GEM_CREATE_EXT_COHERENCE |
   AMDGPU_GEM_CREATE_UNCACHED))
*flags = (*flags & ~AMDGPU_PTE_MTYPE_NV10_MASK) |
 AMDGPU_PTE_MTYPE_NV10(MTYPE_UC);
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c 
b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
index a6ee0220db56..ff330c7c0232 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
@@ -540,6 +540,7 @@ static void gmc_v11_0_get_vm_pte(struct amdgpu_device *adev,
}
 
if (bo && bo->flags & (AMDGPU_GEM_CREATE_COHERENT |
+  AMDGPU_GEM_CREATE_EXT_COHERENCE |
   AMDGPU_GEM_CREATE_UNCACHED))
*flags = (*flags & ~AMDGPU_PTE_MTYPE_NV10_MASK) |
 AMDGPU_PTE_MTYPE_NV10(MTYPE_UC);
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c 
b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
index 8447fcada8bb..17cf19c868e1 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
@@ -1180,7 +1180,8 @@ static void gmc_v9_0_get_coherence_flags(struct 
amdgpu_device *adev,
 {
struct amdgpu_device *bo_adev = amdgpu_ttm_adev(bo->tbo.bdev);
bool is_vram = bo->tbo.resource->mem_type == TTM_PL_VRAM;
-   bool coherent = bo->flags & AMDGPU_GEM_CREATE_COHERENT;
+   bool coherent = bo->flags & (AMDGPU_GEM_CREATE_COHERENT | 
AMDGPU_GEM_CREATE_EXT_COHERENCE);
+   bool ext_coherence = bo->flags & AMDGPU_GEM_CREATE_EXT_COHERENCE;
bool uncached = bo->flags & AMDGPU_GEM_CREATE_UNCACHED;
struct amdgpu_vm *vm = mapping->bo_va->base.vm;
unsigned int mtype_local, mtype;
@@ -1248,6 +1249,8 @@ static void gmc_v9_0_get_coherence_flags(struct 
amdgpu_device *adev,
snoop = true;
if (uncached) {
mtype = MTYPE_UC;
+   } else if (ext_coherence) {
+   mtype = is_local ? MTYPE_CC : MTYPE_UC;
} else if (adev->flags & AMD_IS_APU) {
mtype = is_local ? mtype_local : MTYPE_NC;
} else {
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index 909f1ef8927d..acb87b2fe8df 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -1157,7 +1157,8 @@ svm_range_get_pte_flags(struct kfd_node *node,
uint32_t mapping_flags = 0;
uint64_t pte_flags;
bool snoop = (domain != SVM_RANGE_VRAM_DOMAIN);
-   bool coherent = flags & KFD_IOCTL_SVM_FLAG_COHERENT;
+   bool coherent = flags & (KFD_IOCTL_SVM_FLAG_COHERENT | 
KFD_IOCTL_SVM_FLAG_EXT_COHERENCE);
+   bool ext_coherence = flags & KFD_IOCTL_SVM_FLAG_EXT_COHERENCE;
bool uncached = false; /*flags & KFD_IOCTL_SVM_FLAG_UNCACHED;*/
unsigned int mtype_local;
 
@@ -1205,6 +1206,13 @@ svm_range_get_pte_flags(struct kfd_node *node,
snoop = true;
i

[no subject]

2023-07-24 Thread David Francis
This is in support of a RCCL change that requires specific
coherence behaviour.

Corresponding Thunk patch is at
https://github.com/RadeonOpenCompute/ROCT-Thunk-Interface/pull/88




Re: [patch V2] drm/amdkfd: Access gpuvm_export_dmabuf() api

2023-06-29 Thread David Francis




Does this read well.

drm/amdkfd: Access gpuvm_export_dmabuf() API to get Dmabuf

Directly invoking the function amdgpu_gem_prime_export() from within

KFD is not correct. By utilizing the KFD API to obtain Dmabuf, the

implementation can prevent the creation of multiple instances of

struct dma_buf.

Regards,

Ramesh


Looks good.

With the new commit message, patch is

Reviewed-by: David Francis


On 2023-06-22 17:10, Ramesh Errabolu wrote:

Call KFD api to get Dmabuf instead of calling GEM Prime API

Would appreciate a more detailed commit message to explain why the
KFD API is preferred over the GEM API.
With or without that change, this is
Reviewed-by: David Francis  
<mailto:david.fran...@amd.com>

Signed-off-by: Ramesh Errabolu  
<mailto:ramesh.errab...@amd.com>

---

  drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 11 +--

  1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c

index cf1db0ab3471..40ac093b5035 100644

--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c

+++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c

@@ -1852,15 +1852,14 @@ static uint32_t get_process_num_bos(struct 
kfd_process *p)

     return num_of_bos;

  }

-static int criu_get_prime_handle(struct drm_gem_object *gobj, int flags,

+static int criu_get_prime_handle(struct kgd_mem *mem, int flags,

   u32 *shared_fd)

  {

     struct dma_buf *dmabuf;

     int ret;

-   dmabuf = amdgpu_gem_prime_export(gobj, flags);

-   if (IS_ERR(dmabuf)) {

-   ret = PTR_ERR(dmabuf);

+   ret = amdgpu_amdkfd_gpuvm_export_dmabuf(mem, );

+   if (ret) {

     pr_err("dmabuf export failed for the BO\n");

     return ret;

     }

@@ -1940,7 +1939,7 @@ static int criu_checkpoint_bos(struct kfd_process *p,

     }

     if (bo_bucket->alloc_flags

     & (KFD_IOC_ALLOC_MEM_FLAGS_VRAM | 
KFD_IOC_ALLOC_MEM_FLAGS_GTT)) {

-   ret = 
criu_get_prime_handle(_bo->tbo.base,

+   ret = criu_get_prime_handle(kgd_mem,

     bo_bucket->alloc_flags &

     
KFD_IOC_ALLOC_MEM_FLAGS_WRITABLE ? DRM_RDWR : 0,

     _bucket->dmabuf_fd);

@@ -2402,7 +2401,7 @@ static int criu_restore_bo(struct kfd_process *p,

     /* create the dmabuf object and export the bo */

     if (bo_bucket->alloc_flags

     & (KFD_IOC_ALLOC_MEM_FLAGS_VRAM | 
KFD_IOC_ALLOC_MEM_FLAGS_GTT)) {

-   ret = criu_get_prime_handle(_mem->bo->tbo.base, 
DRM_RDWR,

+   ret = criu_get_prime_handle(kgd_mem, DRM_RDWR,

     _bucket->dmabuf_fd);

     if (ret)

     return ret;

--

2.25.1


Re: [patch V2] drm/amdkfd: Access gpuvm_export_dmabuf() api

2023-06-28 Thread David Francis

On 2023-06-22 17:10, Ramesh Errabolu wrote:


Call KFD api to get Dmabuf instead of calling GEM Prime API


Would appreciate a more detailed commit message to explain why the
KFD API is preferred over the GEM API.

With or without that change, this is

Reviewed-by: David Francis



Signed-off-by: Ramesh Errabolu
---
  drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 11 +--
  1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
index cf1db0ab3471..40ac093b5035 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
@@ -1852,15 +1852,14 @@ static uint32_t get_process_num_bos(struct kfd_process 
*p)
 return num_of_bos;
  }

-static int criu_get_prime_handle(struct drm_gem_object *gobj, int flags,
+static int criu_get_prime_handle(struct kgd_mem *mem, int flags,
   u32 *shared_fd)
  {
 struct dma_buf *dmabuf;
 int ret;

-   dmabuf = amdgpu_gem_prime_export(gobj, flags);
-   if (IS_ERR(dmabuf)) {
-   ret = PTR_ERR(dmabuf);
+   ret = amdgpu_amdkfd_gpuvm_export_dmabuf(mem, );
+   if (ret) {
 pr_err("dmabuf export failed for the BO\n");
 return ret;
 }
@@ -1940,7 +1939,7 @@ static int criu_checkpoint_bos(struct kfd_process *p,
 }
 if (bo_bucket->alloc_flags
 & (KFD_IOC_ALLOC_MEM_FLAGS_VRAM | 
KFD_IOC_ALLOC_MEM_FLAGS_GTT)) {
-   ret = 
criu_get_prime_handle(_bo->tbo.base,
+   ret = criu_get_prime_handle(kgd_mem,
 bo_bucket->alloc_flags &
 
KFD_IOC_ALLOC_MEM_FLAGS_WRITABLE ? DRM_RDWR : 0,
 _bucket->dmabuf_fd);
@@ -2402,7 +2401,7 @@ static int criu_restore_bo(struct kfd_process *p,
 /* create the dmabuf object and export the bo */
 if (bo_bucket->alloc_flags
 & (KFD_IOC_ALLOC_MEM_FLAGS_VRAM | KFD_IOC_ALLOC_MEM_FLAGS_GTT)) {
-   ret = criu_get_prime_handle(_mem->bo->tbo.base, DRM_RDWR,
+   ret = criu_get_prime_handle(kgd_mem, DRM_RDWR,
 _bucket->dmabuf_fd);
 if (ret)
 return ret;
--
2.25.1


[v2] drm/amd: Add IMU fw version to fw version queries

2022-09-19 Thread David Francis
IMU is a new firmware for GFX11.

There are four means by which firmware version can be queried
from the driver: device attributes, vf2pf, debugfs,
and the AMDGPU_INFO_FW_VERSION option in the amdgpu info ioctl.

Add IMU as an option for those four methods.

V2: Added debugfs

CC: Likun Gao 

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 13 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c   |  4 +++-
 drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c|  1 +
 drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h |  1 +
 include/uapi/drm/amdgpu_drm.h   |  2 ++
 5 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index 1369c25448dc..56753c3574b1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -328,6 +328,10 @@ static int amdgpu_firmware_info(struct 
drm_amdgpu_info_firmware *fw_info,
fw_info->ver = adev->psp.cap_fw_version;
fw_info->feature = adev->psp.cap_feature_version;
break;
+   case AMDGPU_INFO_FW_IMU:
+   fw_info->ver = adev->gfx.imu_fw_version;
+   fw_info->feature = 0;
+   break;
default:
return -EINVAL;
}
@@ -1488,6 +1492,15 @@ static int amdgpu_debugfs_firmware_info_show(struct 
seq_file *m, void *unused)
   fw_info.feature, fw_info.ver);
}
 
+   /* IMU */
+   query_fw.fw_type = AMDGPU_INFO_FW_IMU;
+   query_fw.index = 0;
+   ret = amdgpu_firmware_info(_info, _fw, adev);
+   if (ret)
+   return ret;
+   seq_printf(m, "IMU feature version: %u, firmware version: 0x%08x\n",
+  fw_info.feature, fw_info.ver);
+
/* PSP SOS */
query_fw.fw_type = AMDGPU_INFO_FW_SOS;
ret = amdgpu_firmware_info(_info, _fw, adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
index 939c8614f0e3..a576a50fad25 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
@@ -630,6 +630,7 @@ FW_VERSION_ATTR(rlc_srlg_fw_version, 0444, 
gfx.rlc_srlg_fw_version);
 FW_VERSION_ATTR(rlc_srls_fw_version, 0444, gfx.rlc_srls_fw_version);
 FW_VERSION_ATTR(mec_fw_version, 0444, gfx.mec_fw_version);
 FW_VERSION_ATTR(mec2_fw_version, 0444, gfx.mec2_fw_version);
+FW_VERSION_ATTR(imu_fw_version, 0444, gfx.imu_fw_version);
 FW_VERSION_ATTR(sos_fw_version, 0444, psp.sos.fw_version);
 FW_VERSION_ATTR(asd_fw_version, 0444, psp.asd_context.bin_desc.fw_version);
 FW_VERSION_ATTR(ta_ras_fw_version, 0444, 
psp.ras_context.context.bin_desc.fw_version);
@@ -651,7 +652,8 @@ static struct attribute *fw_attrs[] = {
_attr_ta_ras_fw_version.attr, _attr_ta_xgmi_fw_version.attr,
_attr_smc_fw_version.attr, _attr_sdma_fw_version.attr,
_attr_sdma2_fw_version.attr, _attr_vcn_fw_version.attr,
-   _attr_dmcu_fw_version.attr, NULL
+   _attr_dmcu_fw_version.attr, _attr_imu_fw_version.attr,
+   NULL
 };
 
 static const struct attribute_group fw_attr_group = {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
index e4af40b9a8aa..38c46f09d784 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
@@ -547,6 +547,7 @@ static void amdgpu_virt_populate_vf2pf_ucode_info(struct 
amdgpu_device *adev)
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_RLC_SRLS, 
adev->gfx.rlc_srls_fw_version);
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_MEC,  
adev->gfx.mec_fw_version);
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_MEC2, 
adev->gfx.mec2_fw_version);
+   POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_IMU,  
adev->gfx.imu_fw_version);
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SOS,  
adev->psp.sos.fw_version);
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_ASD,
adev->psp.asd_context.bin_desc.fw_version);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h 
b/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h
index e78e4c27b62a..6c97148ca0ed 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h
@@ -70,6 +70,7 @@ enum amd_sriov_ucode_engine_id {
AMD_SRIOV_UCODE_ID_RLC_SRLS,
AMD_SRIOV_UCODE_ID_MEC,
AMD_SRIOV_UCODE_ID_MEC2,
+   AMD_SRIOV_UCODE_ID_IMU,
AMD_SRIOV_UCODE_ID_SOS,
AMD_SRIOV_UCODE_ID_ASD,
AMD_SRIOV_UCODE_ID_TA_RAS,
diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h
index c2c9c674a223..3e00cec47f52 100644
--- a/include/uapi/drm/amdgpu_drm.h
+++ b/include/uapi/drm/amdgpu_drm.h
@@ -755,6 +755,8 @@ struct drm_amdgpu_cs_chunk_data {
#define AMDGPU_INF

[PATCH v9 1/6] drm/dp_mst: Add PBN calculation for DSC modes

2019-08-27 Thread David Francis
With DSC, bpp can be fractional in multiples of 1/16.

Change drm_dp_calc_pbn_mode to reflect this, adding a new
parameter bool dsc. When this parameter is true, treat the
bpp parameter as having units not of bits per pixel, but
1/16 of a bit per pixel

v2: Don't add separate function for this

Cc: amd-gfx@lists.freedesktop.org
Cc: nouv...@lists.freedesktop.org
Cc: intel-...@lists.freedesktop.org
Reviewed-by: Manasi Navare 
Reviewed-by: Lyude Paul 
Reviewed-by: Harry Wentland 
Signed-off-by: David Francis 
---
 .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c|  2 +-
 drivers/gpu/drm/drm_dp_mst_topology.c| 16 
 drivers/gpu/drm/i915/display/intel_dp_mst.c  |  2 +-
 drivers/gpu/drm/nouveau/dispnv50/disp.c  |  2 +-
 drivers/gpu/drm/radeon/radeon_dp_mst.c   |  2 +-
 include/drm/drm_dp_mst_helper.h  |  3 +--
 6 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index a0ed0154a9f0..abafb5221b44 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -235,7 +235,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
 
/* TODO need to know link rate */
 
-   pbn = drm_dp_calc_pbn_mode(clock, bpp);
+   pbn = drm_dp_calc_pbn_mode(clock, bpp, false);
 
slots = drm_dp_find_vcpi_slots(mst_mgr, pbn);
ret = drm_dp_mst_allocate_vcpi(mst_mgr, mst_port, pbn, slots);
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c 
b/drivers/gpu/drm/drm_dp_mst_topology.c
index 82add736e17d..3e7b7553cf4d 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -3534,10 +3534,11 @@ EXPORT_SYMBOL(drm_dp_check_act_status);
  * drm_dp_calc_pbn_mode() - Calculate the PBN for a mode.
  * @clock: dot clock for the mode
  * @bpp: bpp for the mode.
+ * @dsc: DSC mode. If true, bpp has units of 1/16 of a bit per pixel
  *
  * This uses the formula in the spec to calculate the PBN value for a mode.
  */
-int drm_dp_calc_pbn_mode(int clock, int bpp)
+int drm_dp_calc_pbn_mode(int clock, int bpp, bool dsc)
 {
u64 kbps;
s64 peak_kbps;
@@ -3555,11 +3556,18 @@ int drm_dp_calc_pbn_mode(int clock, int bpp)
 * peak_kbps *= (1006/1000)
 * peak_kbps *= (64/54)
 * peak_kbps *= 8convert to bytes
+*
+* If the bpp is in units of 1/16, further divide by 16. Put this
+* factor in the numerator rather than the denominator to avoid
+* integer overflow
 */
 
numerator = 64 * 1006;
denominator = 54 * 8 * 1000 * 1000;
 
+   if (dsc)
+   numerator /= 16;
+
kbps *= numerator;
peak_kbps = drm_fixp_from_fraction(kbps, denominator);
 
@@ -3570,19 +3578,19 @@ EXPORT_SYMBOL(drm_dp_calc_pbn_mode);
 static int test_calc_pbn_mode(void)
 {
int ret;
-   ret = drm_dp_calc_pbn_mode(154000, 30);
+   ret = drm_dp_calc_pbn_mode(154000, 30, false);
if (ret != 689) {
DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, 
expected PBN %d, actual PBN %d.\n",
154000, 30, 689, ret);
return -EINVAL;
}
-   ret = drm_dp_calc_pbn_mode(234000, 30);
+   ret = drm_dp_calc_pbn_mode(234000, 30, false);
if (ret != 1047) {
DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, 
expected PBN %d, actual PBN %d.\n",
234000, 30, 1047, ret);
return -EINVAL;
}
-   ret = drm_dp_calc_pbn_mode(297000, 24);
+   ret = drm_dp_calc_pbn_mode(297000, 24, false);
if (ret != 1063) {
DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, 
expected PBN %d, actual PBN %d.\n",
297000, 24, 1063, ret);
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c 
b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 2c5ac3dd647f..4f17f61f4453 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -61,7 +61,7 @@ static int intel_dp_mst_compute_link_config(struct 
intel_encoder *encoder,
crtc_state->pipe_bpp = bpp;
 
crtc_state->pbn = 
drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock,
-  crtc_state->pipe_bpp);
+  crtc_state->pipe_bpp, 
false);
 
slots = drm_dp_atomic_find_vcpi_slots(state, _dp->mst_mgr,
  port, crtc_state->pbn);
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 5c36c75232e6..c68783c1f3fa 1

[PATCH v8 1/6] drm/dp_mst: Add PBN calculation for DSC modes

2019-08-26 Thread David Francis
With DSC, bpp can be fractional in multiples of 1/16.

Change drm_dp_calc_pbn_mode to reflect this, adding a new
parameter bool dsc. When this parameter is true, treat the
bpp parameter as having units not of bits per pixel, but
1/16 of a bit per pixel

v2: Don't add separate function for this

Cc: amd-gfx@lists.freedesktop.org
Cc: nouv...@lists.freedesktop.org
Cc: intel-...@lists.freedesktop.org
Reviewed-by: Manasi Navare 
Reviewed-by: Lyude Paul 
Signed-off-by: David Francis 
---
 .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c|  2 +-
 drivers/gpu/drm/drm_dp_mst_topology.c| 16 
 drivers/gpu/drm/i915/display/intel_dp_mst.c  |  2 +-
 drivers/gpu/drm/nouveau/dispnv50/disp.c  |  2 +-
 drivers/gpu/drm/radeon/radeon_dp_mst.c   |  2 +-
 include/drm/drm_dp_mst_helper.h  |  3 +--
 6 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index a0ed0154a9f0..abafb5221b44 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -235,7 +235,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
 
/* TODO need to know link rate */
 
-   pbn = drm_dp_calc_pbn_mode(clock, bpp);
+   pbn = drm_dp_calc_pbn_mode(clock, bpp, false);
 
slots = drm_dp_find_vcpi_slots(mst_mgr, pbn);
ret = drm_dp_mst_allocate_vcpi(mst_mgr, mst_port, pbn, slots);
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c 
b/drivers/gpu/drm/drm_dp_mst_topology.c
index 82add736e17d..3e7b7553cf4d 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -3534,10 +3534,11 @@ EXPORT_SYMBOL(drm_dp_check_act_status);
  * drm_dp_calc_pbn_mode() - Calculate the PBN for a mode.
  * @clock: dot clock for the mode
  * @bpp: bpp for the mode.
+ * @dsc: DSC mode. If true, bpp has units of 1/16 of a bit per pixel
  *
  * This uses the formula in the spec to calculate the PBN value for a mode.
  */
-int drm_dp_calc_pbn_mode(int clock, int bpp)
+int drm_dp_calc_pbn_mode(int clock, int bpp, bool dsc)
 {
u64 kbps;
s64 peak_kbps;
@@ -3555,11 +3556,18 @@ int drm_dp_calc_pbn_mode(int clock, int bpp)
 * peak_kbps *= (1006/1000)
 * peak_kbps *= (64/54)
 * peak_kbps *= 8convert to bytes
+*
+* If the bpp is in units of 1/16, further divide by 16. Put this
+* factor in the numerator rather than the denominator to avoid
+* integer overflow
 */
 
numerator = 64 * 1006;
denominator = 54 * 8 * 1000 * 1000;
 
+   if (dsc)
+   numerator /= 16;
+
kbps *= numerator;
peak_kbps = drm_fixp_from_fraction(kbps, denominator);
 
@@ -3570,19 +3578,19 @@ EXPORT_SYMBOL(drm_dp_calc_pbn_mode);
 static int test_calc_pbn_mode(void)
 {
int ret;
-   ret = drm_dp_calc_pbn_mode(154000, 30);
+   ret = drm_dp_calc_pbn_mode(154000, 30, false);
if (ret != 689) {
DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, 
expected PBN %d, actual PBN %d.\n",
154000, 30, 689, ret);
return -EINVAL;
}
-   ret = drm_dp_calc_pbn_mode(234000, 30);
+   ret = drm_dp_calc_pbn_mode(234000, 30, false);
if (ret != 1047) {
DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, 
expected PBN %d, actual PBN %d.\n",
234000, 30, 1047, ret);
return -EINVAL;
}
-   ret = drm_dp_calc_pbn_mode(297000, 24);
+   ret = drm_dp_calc_pbn_mode(297000, 24, false);
if (ret != 1063) {
DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, 
expected PBN %d, actual PBN %d.\n",
297000, 24, 1063, ret);
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c 
b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 2c5ac3dd647f..4f17f61f4453 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -61,7 +61,7 @@ static int intel_dp_mst_compute_link_config(struct 
intel_encoder *encoder,
crtc_state->pipe_bpp = bpp;
 
crtc_state->pbn = 
drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock,
-  crtc_state->pipe_bpp);
+  crtc_state->pipe_bpp, 
false);
 
slots = drm_dp_atomic_find_vcpi_slots(state, _dp->mst_mgr,
  port, crtc_state->pbn);
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 5c36c75232e6..c68783c1f3fa 100644
--- a/drivers/gpu/drm/no

[PATCH v7 1/6] drm/dp_mst: Add PBN calculation for DSC modes

2019-08-26 Thread David Francis
With DSC, bpp can be fractional in multiples of 1/16.

Change drm_dp_calc_pbn_mode to reflect this, adding a new
parameter bool dsc. When this parameter is true, treat the
bpp parameter as having units not of bits per pixel, but
1/16 of a bit per pixel

v2: Don't add separate function for this

Cc: amd-gfx@lists.freedesktop.org
Cc: nouv...@lists.freedesktop.org
Cc: intel-...@lists.freedesktop.org
Reviewed-by: Manasi Navare 
Reviewed-by: Lyude Paul 
Signed-off-by: David Francis 
---
 .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c|  2 +-
 drivers/gpu/drm/drm_dp_mst_topology.c| 16 
 drivers/gpu/drm/i915/display/intel_dp_mst.c  |  2 +-
 drivers/gpu/drm/nouveau/dispnv50/disp.c  |  2 +-
 drivers/gpu/drm/radeon/radeon_dp_mst.c   |  2 +-
 include/drm/drm_dp_mst_helper.h  |  3 +--
 6 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index a0ed0154a9f0..abafb5221b44 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -235,7 +235,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
 
/* TODO need to know link rate */
 
-   pbn = drm_dp_calc_pbn_mode(clock, bpp);
+   pbn = drm_dp_calc_pbn_mode(clock, bpp, false);
 
slots = drm_dp_find_vcpi_slots(mst_mgr, pbn);
ret = drm_dp_mst_allocate_vcpi(mst_mgr, mst_port, pbn, slots);
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c 
b/drivers/gpu/drm/drm_dp_mst_topology.c
index 82add736e17d..3e7b7553cf4d 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -3534,10 +3534,11 @@ EXPORT_SYMBOL(drm_dp_check_act_status);
  * drm_dp_calc_pbn_mode() - Calculate the PBN for a mode.
  * @clock: dot clock for the mode
  * @bpp: bpp for the mode.
+ * @dsc: DSC mode. If true, bpp has units of 1/16 of a bit per pixel
  *
  * This uses the formula in the spec to calculate the PBN value for a mode.
  */
-int drm_dp_calc_pbn_mode(int clock, int bpp)
+int drm_dp_calc_pbn_mode(int clock, int bpp, bool dsc)
 {
u64 kbps;
s64 peak_kbps;
@@ -3555,11 +3556,18 @@ int drm_dp_calc_pbn_mode(int clock, int bpp)
 * peak_kbps *= (1006/1000)
 * peak_kbps *= (64/54)
 * peak_kbps *= 8convert to bytes
+*
+* If the bpp is in units of 1/16, further divide by 16. Put this
+* factor in the numerator rather than the denominator to avoid
+* integer overflow
 */
 
numerator = 64 * 1006;
denominator = 54 * 8 * 1000 * 1000;
 
+   if (dsc)
+   numerator /= 16;
+
kbps *= numerator;
peak_kbps = drm_fixp_from_fraction(kbps, denominator);
 
@@ -3570,19 +3578,19 @@ EXPORT_SYMBOL(drm_dp_calc_pbn_mode);
 static int test_calc_pbn_mode(void)
 {
int ret;
-   ret = drm_dp_calc_pbn_mode(154000, 30);
+   ret = drm_dp_calc_pbn_mode(154000, 30, false);
if (ret != 689) {
DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, 
expected PBN %d, actual PBN %d.\n",
154000, 30, 689, ret);
return -EINVAL;
}
-   ret = drm_dp_calc_pbn_mode(234000, 30);
+   ret = drm_dp_calc_pbn_mode(234000, 30, false);
if (ret != 1047) {
DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, 
expected PBN %d, actual PBN %d.\n",
234000, 30, 1047, ret);
return -EINVAL;
}
-   ret = drm_dp_calc_pbn_mode(297000, 24);
+   ret = drm_dp_calc_pbn_mode(297000, 24, false);
if (ret != 1063) {
DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, 
expected PBN %d, actual PBN %d.\n",
297000, 24, 1063, ret);
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c 
b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 2c5ac3dd647f..4f17f61f4453 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -61,7 +61,7 @@ static int intel_dp_mst_compute_link_config(struct 
intel_encoder *encoder,
crtc_state->pipe_bpp = bpp;
 
crtc_state->pbn = 
drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock,
-  crtc_state->pipe_bpp);
+  crtc_state->pipe_bpp, 
false);
 
slots = drm_dp_atomic_find_vcpi_slots(state, _dp->mst_mgr,
  port, crtc_state->pbn);
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 5c36c75232e6..c68783c1f3fa 100644
--- a/drivers/gpu/drm/no

[PATCH v6 1/6] drm/dp_mst: Add PBN calculation for DSC modes

2019-08-26 Thread David Francis
With DSC, bpp can be fractional in multiples of 1/16.

Change drm_dp_calc_pbn_mode to reflect this, adding a new
parameter bool dsc. When this parameter is true, treat the
bpp parameter as having units not of bits per pixel, but
1/16 of a bit per pixel

v2: Don't add separate function for this

Cc: amd-gfx@lists.freedesktop.org
Cc: nouv...@lists.freedesktop.org
Cc: intel-...@lists.freedesktop.org
Reviewed-by: Manasi Navare 
Reviewed-by: Lyude Paul 
Signed-off-by: David Francis 
---
 .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c|  2 +-
 drivers/gpu/drm/drm_dp_mst_topology.c| 16 
 drivers/gpu/drm/i915/display/intel_dp_mst.c  |  2 +-
 drivers/gpu/drm/nouveau/dispnv50/disp.c  |  2 +-
 drivers/gpu/drm/radeon/radeon_dp_mst.c   |  2 +-
 include/drm/drm_dp_mst_helper.h  |  3 +--
 6 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index a0ed0154a9f0..abafb5221b44 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -235,7 +235,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
 
/* TODO need to know link rate */
 
-   pbn = drm_dp_calc_pbn_mode(clock, bpp);
+   pbn = drm_dp_calc_pbn_mode(clock, bpp, false);
 
slots = drm_dp_find_vcpi_slots(mst_mgr, pbn);
ret = drm_dp_mst_allocate_vcpi(mst_mgr, mst_port, pbn, slots);
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c 
b/drivers/gpu/drm/drm_dp_mst_topology.c
index 82add736e17d..3e7b7553cf4d 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -3534,10 +3534,11 @@ EXPORT_SYMBOL(drm_dp_check_act_status);
  * drm_dp_calc_pbn_mode() - Calculate the PBN for a mode.
  * @clock: dot clock for the mode
  * @bpp: bpp for the mode.
+ * @dsc: DSC mode. If true, bpp has units of 1/16 of a bit per pixel
  *
  * This uses the formula in the spec to calculate the PBN value for a mode.
  */
-int drm_dp_calc_pbn_mode(int clock, int bpp)
+int drm_dp_calc_pbn_mode(int clock, int bpp, bool dsc)
 {
u64 kbps;
s64 peak_kbps;
@@ -3555,11 +3556,18 @@ int drm_dp_calc_pbn_mode(int clock, int bpp)
 * peak_kbps *= (1006/1000)
 * peak_kbps *= (64/54)
 * peak_kbps *= 8convert to bytes
+*
+* If the bpp is in units of 1/16, further divide by 16. Put this
+* factor in the numerator rather than the denominator to avoid
+* integer overflow
 */
 
numerator = 64 * 1006;
denominator = 54 * 8 * 1000 * 1000;
 
+   if (dsc)
+   numerator /= 16;
+
kbps *= numerator;
peak_kbps = drm_fixp_from_fraction(kbps, denominator);
 
@@ -3570,19 +3578,19 @@ EXPORT_SYMBOL(drm_dp_calc_pbn_mode);
 static int test_calc_pbn_mode(void)
 {
int ret;
-   ret = drm_dp_calc_pbn_mode(154000, 30);
+   ret = drm_dp_calc_pbn_mode(154000, 30, false);
if (ret != 689) {
DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, 
expected PBN %d, actual PBN %d.\n",
154000, 30, 689, ret);
return -EINVAL;
}
-   ret = drm_dp_calc_pbn_mode(234000, 30);
+   ret = drm_dp_calc_pbn_mode(234000, 30, false);
if (ret != 1047) {
DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, 
expected PBN %d, actual PBN %d.\n",
234000, 30, 1047, ret);
return -EINVAL;
}
-   ret = drm_dp_calc_pbn_mode(297000, 24);
+   ret = drm_dp_calc_pbn_mode(297000, 24, false);
if (ret != 1063) {
DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, 
expected PBN %d, actual PBN %d.\n",
297000, 24, 1063, ret);
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c 
b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 2c5ac3dd647f..4f17f61f4453 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -61,7 +61,7 @@ static int intel_dp_mst_compute_link_config(struct 
intel_encoder *encoder,
crtc_state->pipe_bpp = bpp;
 
crtc_state->pbn = 
drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock,
-  crtc_state->pipe_bpp);
+  crtc_state->pipe_bpp, 
false);
 
slots = drm_dp_atomic_find_vcpi_slots(state, _dp->mst_mgr,
  port, crtc_state->pbn);
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 5c36c75232e6..c68783c1f3fa 100644
--- a/drivers/gpu/drm/no

[PATCH v3 16/16] drm/amd/display: Trigger modesets on MST DSC connectors

2019-08-21 Thread David Francis
Whenever a connector on an MST network is attached, detached, or
undergoes a modeset, the DSC configs for each stream on that
topology will be recalculated. This can change their required
bandwidth, requiring a full reprogramming, as though a modeset
was performed, even if that stream did not change timing.

Therefore, whenever a crtc has drm_atomic_crtc_needs_modeset,
for each crtc that shares a MST topology with that stream and
supports DSC, add that crtc (and all affected connectors and
planes) to the atomic state and set mode_changed on its state

v2: Do this check only on Navi and before adding connectors
and planes on modesetting crtcs

Cc: Leo Li 
Cc: Nicholas Kazlauskas 
Cc: Lyude Paul 
Signed-off-by: David Francis 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 77 +++
 1 file changed, 77 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 145fd73025dc..702fb0e29053 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -6475,7 +6475,73 @@ static int do_aquire_global_lock(struct drm_device *dev,
 
return ret < 0 ? ret : 0;
 }
+#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
+/*
+ * TODO: This logic should at some point be moved into DRM
+ */
+static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct 
drm_crtc *crtc)
+{
+   struct drm_connector *connector;
+   struct drm_connector_state *conn_state;
+   struct drm_connector_list_iter conn_iter;
+   struct drm_crtc_state *new_crtc_state;
+   struct amdgpu_dm_connector *aconnector = NULL, *aconnector_to_add;
+   int i, j;
+   struct drm_crtc *crtcs_affected[AMDGPU_MAX_CRTCS] = { 0 };
+
+   for_each_new_connector_in_state(state, connector, conn_state, i) {
+   if (conn_state->crtc != crtc)
+   continue;
+
+   aconnector = to_amdgpu_dm_connector(connector);
+   if (!aconnector->port)
+   aconnector = NULL;
+   else
+   break;
+   }
+
+   if (!aconnector)
+   return 0;
+
+   i = 0;
+   drm_connector_list_iter_begin(state->dev, _iter);
+   drm_for_each_connector_iter(connector, _iter) {
+   if (!connector->state || !connector->state->crtc)
+   continue;
+
+   aconnector_to_add = to_amdgpu_dm_connector(connector);
+   if (!aconnector_to_add->port)
+   continue;
+
+   if (aconnector_to_add->port->mgr != aconnector->port->mgr)
+   continue;
+
+   if (!aconnector_to_add->dc_sink)
+   continue;
+
+   if 
(!aconnector_to_add->dc_sink->sink_dsc_caps.dsc_dec_caps.is_dsc_supported)
+   continue;
+
+   if (i >= AMDGPU_MAX_CRTCS)
+   continue;
+
+   crtcs_affected[i] = connector->state->crtc;
+   i++;
+   }
+   drm_connector_list_iter_end(_iter);
+
+   for (j = 0; j < i; j++) {
+   new_crtc_state = drm_atomic_get_crtc_state(state, 
crtcs_affected[j]);
+   if (IS_ERR(new_crtc_state))
+   return PTR_ERR(new_crtc_state);
 
+   new_crtc_state->mode_changed = true;
+   }
+
+   return 0;
+
+}
+#endif
 static void get_freesync_config_for_crtc(
struct dm_crtc_state *new_crtc_state,
struct dm_connector_state *new_con_state)
@@ -7160,6 +7226,17 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
if (ret)
goto fail;
 
+#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
+   if (adev->asic_type >= CHIP_NAVI10) {
+   for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, 
new_crtc_state, i) {
+   if (drm_atomic_crtc_needs_modeset(new_crtc_state)) {
+   ret = add_affected_mst_dsc_crtcs(state, crtc);
+   if (ret)
+   goto fail;
+   }
+   }
+   }
+#endif
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, 
new_crtc_state, i) {
if (!drm_atomic_crtc_needs_modeset(new_crtc_state) &&
!new_crtc_state->color_mgmt_changed &&
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH v3 15/16] drm/amd/display: MST DSC compute fair share

2019-08-21 Thread David Francis
If there is limited link bandwidth on a MST network,
it must be divided fairly between the streams on that network

Implement an algorithm to determine the correct DSC config
for each stream

The algorithm:
This
 [   ]  ( )
represents the range of bandwidths possible for a given stream.
The [] area represents the range of DSC configs, and the ()
represents no DSC. The bandwidth used increases from left to right.

First, try disabling DSC on all streams
 [  ]  (|)
 [ ](|)
Check this against the bandwidth limits of the link and each branch
(including each endpoint). If it passes, the job is done

Second, try maximum DSC compression on all streams
that support DSC
 [| ]( )
 [|] ( )
If this does not pass, then enabling this combination of streams
is impossible

Otherwise, divide the remaining bandwidth evenly amongst the streams
 [|  ] ( )
 [|  ]( )

If one or more of the streams reach minimum compression, evenly
divide the reamining bandwidth amongst the remaining streams
 [|] ( )
 [   |]   ( )
 [ |   ]   ( )
 [ |  ]  ( )

If all streams can reach minimum compression, disable compression
greedily
 [  |]  ( )
 [|]( )
 [ ](|)

Perform this algorithm on each full update, on each MST link
with at least one DSC stream on it

After the configs are computed, call
dcn20_add_dsc_to_stream_resource on each stream with DSC enabled.
It is only after all streams are created that we can know which
of them will need DSC.

Do all of this at the end of amdgpu atomic check.  If it fails,
fail check; This combination of timings cannot be supported.

Cc: Wenjing Liu 
Cc: Nikola Cornij 
Signed-off-by: David Francis 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |   4 +
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 375 ++
 .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |   4 +
 .../drm/amd/display/dc/dcn20/dcn20_resource.c |   7 +-
 .../drm/amd/display/dc/dcn20/dcn20_resource.h |   1 +
 5 files changed, 389 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 84249057e181..145fd73025dc 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -7331,6 +7331,10 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
if (ret)
goto fail;
 
+#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
+   if (!compute_mst_dsc_configs_for_state(dm_state->context))
+   goto fail;
+#endif
if (dc_validate_global_state(dc, dm_state->context, false) != 
DC_OK) {
ret = -EINVAL;
goto fail;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 9978c1a01eb7..57b5a711c336 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -38,6 +38,8 @@
 
 #include "i2caux_interface.h"
 
+#include "dc/dcn20/dcn20_resource.h"
+
 /* #define TRACE_DPCD */
 
 #ifdef TRACE_DPCD
@@ -452,3 +454,376 @@ void amdgpu_dm_initialize_dp_connector(struct 
amdgpu_display_manager *dm,
aconnector->connector_id);
 }
 
+#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
+struct dsc_mst_fairness_params {
+   struct dc_crtc_timing *timing;
+   struct dc_sink *sink;
+   struct dc_dsc_bw_range bw_range;
+   bool compression_possible;
+   struct drm_dp_mst_port *port;
+};
+
+struct dsc_mst_fairness_vars {
+   int pbn;
+   bool dsc_enabled;
+   int bpp_x16;
+};
+
+static bool port_downstream_of_branch(struct drm_dp_mst_port *port,
+   struct drm_dp_mst_branch *branch)
+{
+   while (port->parent) {
+   if (port->parent == branch)
+   return true;
+
+   if (port->parent->port_parent)
+   port = port->parent->port_parent;
+   else
+   break;
+   }
+   return false;
+}
+
+static bool check_pbn_limit_on_branch(struct drm_dp_mst_branch *branch,
+   struct dsc_mst_fairness_params *params,
+   struct dsc_mst_fairness_vars *vars, int count)
+{
+   struct drm_dp_mst_port *port;
+   int i;
+   int pbn_limit = 0;
+   int pbn_used = 0;
+
+   list_for_each_entry(port, >ports, next) {
+   if (port->mstb)
+   if (!check_pbn_limit_on_branch(port->mstb, params, 
vars, count))
+  

[PATCH v3 10/16] drm/dp-mst: Add MST support to DP DPCD R/W functions

2019-08-21 Thread David Francis
Instead of having drm_dp_dpcd_read/write and
drm_dp_mst_dpcd_read/write as entry points into the
aux code, have drm_dp_dpcd_read/write handle both.

This means that DRM drivers can make MST DPCD read/writes.

Cc: Leo Li 
Cc: Lyude Paul 
Signed-off-by: David Francis 
---
 drivers/gpu/drm/drm_dp_aux_dev.c | 12 ++--
 drivers/gpu/drm/drm_dp_helper.c  | 10 --
 2 files changed, 10 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_aux_dev.c b/drivers/gpu/drm/drm_dp_aux_dev.c
index 00610bd8d6c1..0780fc358389 100644
--- a/drivers/gpu/drm/drm_dp_aux_dev.c
+++ b/drivers/gpu/drm/drm_dp_aux_dev.c
@@ -162,11 +162,7 @@ static ssize_t auxdev_read_iter(struct kiocb *iocb, struct 
iov_iter *to)
break;
}
 
-   if (aux_dev->aux->is_remote)
-   res = drm_dp_mst_dpcd_read(aux_dev->aux, pos, buf,
-  todo);
-   else
-   res = drm_dp_dpcd_read(aux_dev->aux, pos, buf, todo);
+   res = drm_dp_dpcd_read(aux_dev->aux, pos, buf, todo);
 
if (res <= 0)
break;
@@ -214,11 +210,7 @@ static ssize_t auxdev_write_iter(struct kiocb *iocb, 
struct iov_iter *from)
break;
}
 
-   if (aux_dev->aux->is_remote)
-   res = drm_dp_mst_dpcd_write(aux_dev->aux, pos, buf,
-   todo);
-   else
-   res = drm_dp_dpcd_write(aux_dev->aux, pos, buf, todo);
+   res = drm_dp_mst_dpcd_write(aux_dev->aux, pos, buf, todo);
 
if (res <= 0)
break;
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 54a6414c5d96..9f976b90c53a 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -29,6 +29,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "drm_crtc_helper_internal.h"
@@ -272,7 +273,7 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 
request,
 
 /**
  * drm_dp_dpcd_read() - read a series of bytes from the DPCD
- * @aux: DisplayPort AUX channel
+ * @aux: DisplayPort AUX channel (SST or MST)
  * @offset: address of the (first) register to read
  * @buffer: buffer to store the register values
  * @size: number of bytes in @buffer
@@ -289,6 +290,8 @@ ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned 
int offset,
 {
int ret;
 
+if (aux->is_remote)
+return drm_dp_mst_dpcd_read(aux, offset, buffer, size);
/*
 * HP ZR24w corrupts the first DPCD access after entering power save
 * mode. Eg. on a read, the entire buffer will be filled with the same
@@ -317,7 +320,7 @@ EXPORT_SYMBOL(drm_dp_dpcd_read);
 
 /**
  * drm_dp_dpcd_write() - write a series of bytes to the DPCD
- * @aux: DisplayPort AUX channel
+ * @aux: DisplayPort AUX channel (SST or MST)
  * @offset: address of the (first) register to write
  * @buffer: buffer containing the values to write
  * @size: number of bytes in @buffer
@@ -334,6 +337,9 @@ ssize_t drm_dp_dpcd_write(struct drm_dp_aux *aux, unsigned 
int offset,
 {
int ret;
 
+if (aux->is_remote)
+return drm_dp_mst_dpcd_write(aux, offset, buffer, size);
+
ret = drm_dp_dpcd_access(aux, DP_AUX_NATIVE_WRITE, offset, buffer,
 size);
drm_dp_dump_access(aux, DP_AUX_NATIVE_WRITE, offset, buffer, ret);
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH v3 12/16] drm/dp-mst: Add helpers for querying and enabling MST DSC

2019-08-21 Thread David Francis
Add drm_dp_mst_dsc_caps_for_port and drm_dp_mst_dsc_enable,
two helper functions for MST DSC

The former, given a port, returns the raw DPCD DSC caps off
that port.

The latter, given a port, enables or disables DSC on that port.

In both cases, the port given as input should be a leaf of
the MST tree with an attached display.

The logic for this is somewhat complicated, as DSC can be
enabled in 4 different ways.

Case 1: DP-to-DP peer device
if the branch immediately upstream has
 - PDT = DP_PEER_DEVICE_DP_MST_BRANCHING (2)
 - DPCD rev. >= DP 1.4
 - Exactly one input and one output
 - The output has PDT = DP_PEER_DEVICE_SST_SINK (3)

In this case, DSC could be possible either on the endpoint
or the peer device. Prefer the endpoint, which is possible if
 - The endpoint has DP_DSC_DECOMPRESSION_IS_SUPPORTED bit set
 - The endpoint has DP_FEC_CAPABLE bit set
 - The peer device has DSC_PASSTHROUGH_CAPABILITY bit set (from DP v2.0)

Otherwise, use the peer device

Case 2: DP-to-HDMI peer device
If the output port has
 - PDT = DP_PEER_DEVICE_DP_LEGACY_CONV (4)
 - DPCD rev. >= DP 1.4
 - LDPS = true
 - MCS = false

In this case, DSC can only be attempted on the peer device
(the output port)

Case 3: Virtual DP Sink (Internal Display Panel)
If the output port has
 - DPCD rev. >= DP 1.4
 - port_num >= 8

In this case, DSC can only be attempted on the peer device
(the output port)

Case 4: Synaptix Workaround
If the output has
 - link DPCD rev. >= DP 1.4
 - link branch_dev_id = 0x90CC24 (Synaptix)
 - There is exactly one branch device between the link and output

In this case, DSC can be attempted, but only using the *link*
aux device's caps. This is a quirk.

Cc: Lyude Paul 
Cc: Wenjing Liu 
Cc: Nikola Cornij 
Signed-off-by: David Francis 
---
 drivers/gpu/drm/drm_dp_mst_topology.c | 192 ++
 include/drm/drm_dp_mst_helper.h   |   3 +
 2 files changed, 195 insertions(+)

diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c 
b/drivers/gpu/drm/drm_dp_mst_topology.c
index 7decb5bef062..94742538551e 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -4183,3 +4183,195 @@ static void drm_dp_mst_unregister_i2c_bus(struct 
drm_dp_aux *aux)
 {
i2c_del_adapter(>ddc);
 }
+
+/**
+ * drm_dp_mst_is_virtual_dpcd() - Is the given port a virtual DPCD device?
+ * @port: The port to check
+ *
+ * Returns:
+ * true if the port is a virtual DPCD peer device, false otherwise
+ */
+static bool drm_dp_mst_is_virtual_dpcd(struct drm_dp_mst_port *port)
+{
+   struct drm_dp_mst_port *downstream_port;
+
+   if (!port)
+   return false;
+
+   /* Virtual DP Sink (Internal Display Panel) */
+   if (port->port_num >= 8 && port->dpcd_rev >= DP_DPCD_REV_14)
+   return true;
+
+   /* DP-to-HDMI Protocol Converter */
+   if (port->pdt == DP_PEER_DEVICE_DP_LEGACY_CONV &&
+   !port->mcs &&
+   port->ldps &&
+   port->dpcd_rev >= DP_DPCD_REV_14)
+   return true;
+
+   /* DP-to-DP */
+   if (port->pdt == DP_PEER_DEVICE_MST_BRANCHING &&
+   port->mstb &&
+   port->dpcd_rev >= DP_DPCD_REV_14 &&
+   port->mstb->num_ports == 2) {
+   list_for_each_entry(downstream_port, >mstb->ports, next) {
+   if (!downstream_port->input &&
+   downstream_port->pdt == DP_PEER_DEVICE_SST_SINK)
+   return true;
+   }
+   }
+
+   return false;
+}
+
+/**
+ * drm_dp_mst_is_virtual_dpcd() - Does this port require Synaptix DSC 
workaround?
+ * @port: The port to check
+ *
+ * Some Synaptix MST hubs support DSC even though they do not support virtual
+ * DPCD. This is a quirk.
+ *
+ * Returns:
+ * true if the Synaptix workaround is required, false otherwise
+ */
+static bool drm_dp_mst_dsc_synaptix_workaround(struct drm_dp_mst_port *port)
+{
+   u8 data[3] = { 0 };
+   u32 dev_id;
+   struct drm_dp_aux *phys_aux;
+
+   /* The hub must be directly connected to the connector */
+   if (port->mgr->mst_primary != port->parent)
+   return false;
+
+   phys_aux = port->mgr->aux;
+   if (drm_dp_dpcd_read(phys_aux, DP_BRANCH_OUI, data, 3) < 0)
+   return false;
+   dev_id = (data[0] << 16) & (data[1] << 8) & data[3];
+   /* Synaptix device ID */
+   if (dev_id != 0x90CC24)
+   return false;
+
+   if (drm_dp_dpcd_read(phys_aux, DP_DPCD_REV, data, 1) < 0)
+   return false;
+   /* Must be DPCD rev. 1.4 or later */
+   if (data[0] < DP_DPCD_REV_14)
+   return false;
+
+   if (drm_dp_dpcd_read(>aux, DP_DOWNSTRE

[PATCH v3 14/16] drm/amd/display: Write DSC enable to MST DPCD

2019-08-21 Thread David Francis
Rework the dm_helpers_write_dsc_enable callback to
handle the MST case.

Use the drm_dp_mst_dsc_enable helper.

Cc: Wenjing Liu 
Cc: Nikola Cornij 
Signed-off-by: David Francis 
---
 .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c| 16 +++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index 716d6577cdbd..6ef680fa2875 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -38,6 +38,7 @@
 #include "dc.h"
 #include "amdgpu_dm.h"
 #include "amdgpu_dm_irq.h"
+#include "amdgpu_dm_mst_types.h"
 
 #include "dm_helpers.h"
 
@@ -557,8 +558,21 @@ bool dm_helpers_dp_write_dsc_enable(
 )
 {
uint8_t enable_dsc = enable ? 1 : 0;
+   struct amdgpu_dm_connector *aconnector;
+
+   if (!stream)
+   return false;
+
+   if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
+   aconnector = (struct amdgpu_dm_connector 
*)stream->dm_stream_context;
+
+   return (drm_dp_mst_dsc_enable(aconnector->port, enable) >= 0);
+   }
+
+   if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT)
+   return dm_helpers_dp_write_dpcd(ctx, stream->link, 
DP_DSC_ENABLE, _dsc, 1);
 
-   return dm_helpers_dp_write_dpcd(ctx, stream->sink->link, DP_DSC_ENABLE, 
_dsc, 1);
+   return false;
 }
 #endif
 
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH v3 09/16] drm/dp-mst: Parse FEC capability on MST ports

2019-08-21 Thread David Francis
As of DP1.4, ENUM_PATH_RESOURCES returns a bit indicating
if FEC can be supported up to that point in the MST network.

The bit is the first byte of the ENUM_PATH_RESOURCES ack reply,
bottom-most bit (refer to section 2.11.9.4 of DP standard,
v1.4)

That value is needed for FEC and DSC support

Store it on drm_dp_mst_port

Signed-off-by: David Francis 
Reviewed-by: Lyude Paul 
---
 drivers/gpu/drm/drm_dp_mst_topology.c | 2 ++
 include/drm/drm_dp_mst_helper.h   | 3 +++
 2 files changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c 
b/drivers/gpu/drm/drm_dp_mst_topology.c
index 34a5bdfc598b..ad5ccc08c40a 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -552,6 +552,7 @@ static bool 
drm_dp_sideband_parse_enum_path_resources_ack(struct drm_dp_sideband
 {
int idx = 1;
repmsg->u.path_resources.port_number = (raw->msg[idx] >> 4) & 0xf;
+   repmsg->u.path_resources.fec_capable = raw->msg[idx] & 0x1;
idx++;
if (idx > raw->curlen)
goto fail_len;
@@ -2180,6 +2181,7 @@ static int drm_dp_send_enum_path_resources(struct 
drm_dp_mst_topology_mgr *mgr,
DRM_DEBUG_KMS("enum path resources %d: %d %d\n", 
txmsg->reply.u.path_resources.port_number, 
txmsg->reply.u.path_resources.full_payload_bw_number,
   
txmsg->reply.u.path_resources.avail_payload_bw_number);
port->available_pbn = 
txmsg->reply.u.path_resources.avail_payload_bw_number;
+   port->fec_capable = 
txmsg->reply.u.path_resources.fec_capable;
}
}
 
diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h
index ddb518f2157a..fa973773a4a7 100644
--- a/include/drm/drm_dp_mst_helper.h
+++ b/include/drm/drm_dp_mst_helper.h
@@ -108,6 +108,8 @@ struct drm_dp_mst_port {
 * audio-capable.
 */
bool has_audio;
+
+   bool fec_capable;
 };
 
 /**
@@ -312,6 +314,7 @@ struct drm_dp_port_number_req {
 
 struct drm_dp_enum_path_resources_ack_reply {
u8 port_number;
+   bool fec_capable;
u16 full_payload_bw_number;
u16 avail_payload_bw_number;
 };
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH v3 13/16] drm/amd/display: Validate DSC caps on MST endpoints

2019-08-21 Thread David Francis
During MST mode enumeration, if a new dc_sink is created,
populate it with dsc caps as appropriate.

Use drm_dp_mst_dsc_caps_for_port to get the raw caps,
then parse them onto dc_sink with dc_dsc_parse_dsc_dpcd.

Cc: Wenjing Liu 
Cc: Nikola Cornij 
Signed-off-by: David Francis 
---
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 27 ++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 16218a202b59..9978c1a01eb7 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -25,6 +25,7 @@
 
 #include 
 #include 
+#include 
 #include "dm_services.h"
 #include "amdgpu.h"
 #include "amdgpu_dm.h"
@@ -189,6 +190,24 @@ static const struct drm_connector_funcs 
dm_dp_mst_connector_funcs = {
.early_unregister = amdgpu_dm_mst_connector_early_unregister,
 };
 
+#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
+static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector 
*aconnector)
+{
+   struct dc_sink *dc_sink = aconnector->dc_sink;
+   struct drm_dp_mst_port *port = aconnector->port;
+   u8 dsc_caps[16] = { 0 };
+
+   if (drm_dp_mst_dsc_caps_for_port(port, dsc_caps) < 0)
+   return false;
+
+   printk("Validated DSC caps 0x%x", dsc_caps[0]);
+   if (!dc_dsc_parse_dsc_dpcd(dsc_caps, NULL, 
_sink->sink_dsc_caps.dsc_dec_caps))
+   return false;
+
+   return true;
+}
+#endif
+
 static int dm_dp_mst_get_modes(struct drm_connector *connector)
 {
struct amdgpu_dm_connector *aconnector = 
to_amdgpu_dm_connector(connector);
@@ -231,10 +250,16 @@ static int dm_dp_mst_get_modes(struct drm_connector 
*connector)
/* dc_link_add_remote_sink returns a new reference */
aconnector->dc_sink = dc_sink;
 
-   if (aconnector->dc_sink)
+   if (aconnector->dc_sink) {
amdgpu_dm_update_freesync_caps(
connector, aconnector->edid);
 
+#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
+   if (!validate_dsc_caps_on_connector(aconnector))
+   memset(>dc_sink->sink_dsc_caps,
+  0, 
sizeof(aconnector->dc_sink->sink_dsc_caps));
+#endif
+   }
}
 
drm_connector_update_edid_property(
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH v3 11/16] drm/dp-mst: Fill branch->num_ports

2019-08-21 Thread David Francis
This field on drm_dp_mst_branch was never filled

Initialize it to zero when the list of ports is created.
When a port is added to the list, increment num_ports,
and when a port is removed from the list, decrement num_ports.

v2: remember to decrement on port removal

Signed-off-by: David Francis 
Reviewed-by: Lyude Paul 
---
 drivers/gpu/drm/drm_dp_mst_topology.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c 
b/drivers/gpu/drm/drm_dp_mst_topology.c
index ad5ccc08c40a..7decb5bef062 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -918,6 +918,7 @@ static struct drm_dp_mst_branch 
*drm_dp_add_mst_branch_device(u8 lct, u8 *rad)
INIT_LIST_HEAD(>ports);
kref_init(>topology_kref);
kref_init(>malloc_kref);
+   mstb->num_ports = 0;
return mstb;
 }
 
@@ -1670,6 +1671,7 @@ static void drm_dp_add_port(struct drm_dp_mst_branch 
*mstb,
mutex_lock(>mgr->lock);
drm_dp_mst_topology_get_port(port);
list_add(>next, >ports);
+   mstb->num_ports++;
mutex_unlock(>mgr->lock);
}
 
@@ -1704,6 +1706,7 @@ static void drm_dp_add_port(struct drm_dp_mst_branch 
*mstb,
/* remove it from the port list */
mutex_lock(>mgr->lock);
list_del(>next);
+   mstb->num_ports--;
mutex_unlock(>mgr->lock);
/* drop port list reference */
drm_dp_mst_topology_put_port(port);
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH v3 03/16] Revert "drm/amd/display: add global master update lock for DCN2"

2019-08-21 Thread David Francis
This reverts commit 55a6f5bbcf00a49565946c0a9b8c716313dc6c05.

This commit was accidentally promoted twice

Signed-off-by: David Francis 
Reviewed-by: Roman Li 
Reviewed-by: Harry Wentland 
Reviewed-by: Nicholas Kazlauskas 
---
 .../drm/amd/display/dc/dcn20/dcn20_hwseq.c|  4 --
 .../gpu/drm/amd/display/dc/dcn20/dcn20_optc.c | 63 +--
 .../gpu/drm/amd/display/dc/dcn20/dcn20_optc.h |  3 -
 .../amd/display/dc/inc/hw/timing_generator.h  |  2 -
 4 files changed, 1 insertion(+), 71 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
index fa8a73f6c8e3..e146d1d8d45e 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
@@ -575,10 +575,6 @@ enum dc_status dcn20_enable_stream_timing(
pipe_ctx->stream->signal,
true);
 
-   if (pipe_ctx->stream_res.tg->funcs->setup_global_lock)
-   pipe_ctx->stream_res.tg->funcs->setup_global_lock(
-   pipe_ctx->stream_res.tg);
-
if (odm_pipe)
odm_pipe->stream_res.opp->funcs->opp_pipe_clock_control(
odm_pipe->stream_res.opp,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
index 99070e93020b..2137e2be2140 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
@@ -333,65 +333,6 @@ void optc2_triplebuffer_unlock(struct timing_generator 
*optc)
 
 }
 
-
-void optc2_setup_global_lock(struct timing_generator *optc)
-{
-   struct optc *optc1 = DCN10TG_FROM_TG(optc);
-   uint32_t v_blank_start = 0;
-   uint32_t h_blank_start = 0, h_total = 0;
-
-   REG_SET(OTG_GLOBAL_CONTROL1, 0, MASTER_UPDATE_LOCK_DB_EN, 1);
-
-   REG_SET(OTG_GLOBAL_CONTROL2, 0, DIG_UPDATE_LOCATION, 20);
-
-   REG_GET(OTG_V_BLANK_START_END, OTG_V_BLANK_START, _blank_start);
-
-   REG_GET(OTG_H_BLANK_START_END, OTG_H_BLANK_START, _blank_start);
-
-   REG_GET(OTG_H_TOTAL, OTG_H_TOTAL, _total);
-   REG_UPDATE_2(OTG_GLOBAL_CONTROL1,
-   MASTER_UPDATE_LOCK_DB_X,
-   h_blank_start - 200 - 1,
-   MASTER_UPDATE_LOCK_DB_Y,
-   v_blank_start - 1);
-}
-
-void optc2_lock_global(struct timing_generator *optc)
-{
-   struct optc *optc1 = DCN10TG_FROM_TG(optc);
-
-   REG_UPDATE(OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, 1);
-
-   REG_SET(OTG_GLOBAL_CONTROL0, 0,
-   OTG_MASTER_UPDATE_LOCK_SEL, optc->inst);
-   REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
-   OTG_MASTER_UPDATE_LOCK, 1);
-
-   /* Should be fast, status does not update on maximus */
-   if (optc->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS)
-   REG_WAIT(OTG_MASTER_UPDATE_LOCK,
-   UPDATE_LOCK_STATUS, 1,
-   1, 10);
-}
-
-void optc2_lock(struct timing_generator *optc)
-{
-   struct optc *optc1 = DCN10TG_FROM_TG(optc);
-
-   REG_UPDATE(OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, 0);
-
-   REG_SET(OTG_GLOBAL_CONTROL0, 0,
-   OTG_MASTER_UPDATE_LOCK_SEL, optc->inst);
-   REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
-   OTG_MASTER_UPDATE_LOCK, 1);
-
-   /* Should be fast, status does not update on maximus */
-   if (optc->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS)
-   REG_WAIT(OTG_MASTER_UPDATE_LOCK,
-   UPDATE_LOCK_STATUS, 1,
-   1, 10);
-}
-
 void optc2_lock_doublebuffer_enable(struct timing_generator *optc)
 {
struct optc *optc1 = DCN10TG_FROM_TG(optc);
@@ -486,10 +427,8 @@ static struct timing_generator_funcs dcn20_tg_funcs = {
.triplebuffer_lock = optc2_triplebuffer_lock,
.triplebuffer_unlock = optc2_triplebuffer_unlock,
.disable_reset_trigger = optc1_disable_reset_trigger,
-   .lock = optc2_lock,
+   .lock = optc1_lock,
.unlock = optc1_unlock,
-   .lock_global = optc2_lock_global,
-   .setup_global_lock = optc2_setup_global_lock,
.lock_doublebuffer_enable = optc2_lock_doublebuffer_enable,
.lock_doublebuffer_disable = optc2_lock_doublebuffer_disable,
.enable_optc_clock = optc1_enable_optc_clock,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h
index 47cb4de1564c..32a58431fd09 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h
@@ -106,9 +106,6 @@ void optc2_get_optc_source(struct timing_generator *optc,
 
 void optc

[PATCH v3 00/16] Display Stream Compression (DSC) for AMD Navi

2019-08-21 Thread David Francis
This patchset enables Display Stream Compression (DSC) on DP
connectors on Navi ASICs, both SST and DSC.

8k60 and 4k144 support requires ODM combine, an AMD internal
feature that may be a bit buggy right now.

Patches 1 through 5 enable DSC for SST. Most of the work was
already done in the Navi promotion patches; this just hooks
it up to the atomic interface. The first two reverts are of temporary
changes to block off DSC. The third is of a commit that was
accidentally promoted twice. The fourth and last revert fixes a
potential issue with ODM combine.

Patches 6, 7 and 8 are fixes for bugs that would be exposed by
MST DSC. Patches 6 and 7 add and use a new DRM helper for MST
calculations. Patch 8 fixes a silly use-uninitialized

Patches 9, 10, and 11 are small DRM changes required for DSC MST:
FEC, a new bit in the standard; MST DPCD from drivers; and
a previously uninitialized variable.

Patches 12 through 16 are the DSC MST policy itself. Patch 12
adds DSC aux access helpers to DRM, and patches 13 and 14 make
use of those helpers. Patch 15 deals with dividing bandwidth
fairly between multiple streams, and patch 16 ensures
that MST CRTC that may change DSC config are reprogrammed

v2: Updating patches 6 and 14 in respoinse to Nick's feedback
v3: Add return value to patch 6 and split it (now patches 6 & 7)
New patch 10 adding MST DPCD read/write support
Minor fix (num_ports--) to patch 11
Add DRM helpers (patch 12)

David Francis (16):
  Revert "drm/amd/display: skip dsc config for navi10 bring up"
  Revert "drm/amd/display: navi10 bring up skip dsc encoder config"
  Revert "drm/amd/display: add global master update lock for DCN2"
  Revert "drm/amd/display: Fix underscan not using proper scaling"
  drm/amd/display: Enable SST DSC in DM
  drm/dp-mst: Add PBN calculation for DSC modes
  drm/amd/display: Use correct helpers to compute timeslots
  drm/amd/display: Initialize DSC PPS variables to 0
  drm/dp-mst: Parse FEC capability on MST ports
  drm/dp-mst: Add MST support to DP DPCD R/W functions
  drm/dp-mst: Fill branch->num_ports
  drm/dp-mst: Add helpers for querying and enabling MST DSC
  drm/amd/display: Validate DSC caps on MST endpoints
  drm/amd/display: Write DSC enable to MST DPCD
  drm/amd/display: MST DSC compute fair share
  drm/amd/display: Trigger modesets on MST DSC connectors

 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 113 -
 .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  33 +-
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 402 +-
 .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |   4 +
 drivers/gpu/drm/amd/display/dc/core/dc.c  |  12 +-
 .../drm/amd/display/dc/core/dc_link_hwss.c|   3 +
 .../gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c  |   3 +
 .../drm/amd/display/dc/dcn20/dcn20_hwseq.c|   4 -
 .../gpu/drm/amd/display/dc/dcn20/dcn20_optc.c |  72 +---
 .../gpu/drm/amd/display/dc/dcn20/dcn20_optc.h |   3 -
 .../drm/amd/display/dc/dcn20/dcn20_resource.c |   7 +-
 .../drm/amd/display/dc/dcn20/dcn20_resource.h |   1 +
 .../display/dc/dcn20/dcn20_stream_encoder.c   |   8 -
 .../amd/display/dc/inc/hw/timing_generator.h  |   2 -
 drivers/gpu/drm/drm_dp_aux_dev.c  |  12 +-
 drivers/gpu/drm/drm_dp_helper.c   |  10 +-
 drivers/gpu/drm/drm_dp_mst_topology.c | 240 +++
 include/drm/drm_dp_mst_helper.h   |   8 +-
 18 files changed, 806 insertions(+), 131 deletions(-)

-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH v3 05/16] drm/amd/display: Enable SST DSC in DM

2019-08-21 Thread David Francis
In create_stream_for_sink, check for SST DP connectors

Parse DSC caps to DC format, then, if DSC is supported,
compute the config

DSC hardware will be programmed by dc_commit_state

Tested-by: Mikita Lipski 
Signed-off-by: David Francis 
Reviewed-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 32 ---
 .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  4 ++-
 2 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 911fe78b47c1..84249057e181 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3576,6 +3576,10 @@ create_stream_for_sink(struct amdgpu_dm_connector 
*aconnector,
bool scale = dm_state ? (dm_state->scaling != RMX_OFF) : false;
int mode_refresh;
int preferred_refresh = 0;
+#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
+   struct dsc_dec_dpcd_caps dsc_caps;
+   uint32_t link_bandwidth_kbps;
+#endif
 
struct dc_sink *sink = NULL;
if (aconnector == NULL) {
@@ -3648,17 +3652,23 @@ create_stream_for_sink(struct amdgpu_dm_connector 
*aconnector,
, >base, con_state, old_stream);
 
 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
-   /* stream->timing.flags.DSC = 0; */
-/*  */
-   /* if (aconnector->dc_link && */
-   /*  aconnector->dc_link->connector_signal == 
SIGNAL_TYPE_DISPLAY_PORT #<{(|&& */
-   /*  
aconnector->dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.is_dsc_supported|)}>#) */
-   /*  if (dc_dsc_compute_config(aconnector->dc_link->ctx->dc, */
-   /*  >dc_link->dpcd_caps.dsc_caps, */
-   /*  dc_link_bandwidth_kbps(aconnector->dc_link, 
dc_link_get_link_cap(aconnector->dc_link)), */
-   /*  >timing, */
-   /*  >timing.dsc_cfg)) */
-   /*  stream->timing.flags.DSC = 1; */
+   stream->timing.flags.DSC = 0;
+
+   if (aconnector->dc_link && sink->sink_signal == 
SIGNAL_TYPE_DISPLAY_PORT) {
+   
dc_dsc_parse_dsc_dpcd(aconnector->dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.raw,
+ 
aconnector->dc_link->dpcd_caps.dsc_caps.dsc_ext_caps.raw,
+ _caps);
+   link_bandwidth_kbps = 
dc_link_bandwidth_kbps(aconnector->dc_link,
+
dc_link_get_link_cap(aconnector->dc_link));
+
+   if (dsc_caps.is_dsc_supported)
+   if (dc_dsc_compute_config(aconnector->dc_link->ctx->dc,
+ _caps,
+ link_bandwidth_kbps,
+ >timing,
+ >timing.dsc_cfg))
+   stream->timing.flags.DSC = 1;
+   }
 #endif
 
update_stream_scaling_settings(, dm_state, stream);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index 7cf0573ab25f..5f2c315b18ba 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -549,7 +549,9 @@ bool dm_helpers_dp_write_dsc_enable(
bool enable
 )
 {
-   return false;
+   uint8_t enable_dsc = enable ? 1 : 0;
+
+   return dm_helpers_dp_write_dpcd(ctx, stream->sink->link, DP_DSC_ENABLE, 
_dsc, 1);
 }
 #endif
 
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH v3 06/16] drm/dp-mst: Add PBN calculation for DSC modes

2019-08-21 Thread David Francis
With DSC, bpp can be a multiple of 1/16, so
drm_dp_calc_pbn_mode is insufficient.

Add drm_dp_calc_pbn_mode_dsc, a function which is
the same as drm_dp_calc_pbn_mode, but the bpp is
in units of 1/16.

Cc: Lyude Paul 
Cc: Nicholas Kazlauskas 
Signed-off-by: David Francis 
---
 drivers/gpu/drm/drm_dp_mst_topology.c | 43 +++
 include/drm/drm_dp_mst_helper.h   |  2 +-
 2 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c 
b/drivers/gpu/drm/drm_dp_mst_topology.c
index 398e7314ea8b..34a5bdfc598b 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -3588,6 +3588,49 @@ static int test_calc_pbn_mode(void)
return 0;
 }
 
+/**
+ * drm_dp_calc_pbn_mode_dsc() - Calculate the PBN for a mode with DSC enabled.
+ * @clock: dot clock for the mode
+ * @dsc_bpp: dsc bits per pixel x16 (e.g. dsc_bpp = 136 is 8.5 bpp)
+ *
+ * This uses the formula in the spec to calculate the PBN value for a mode,
+ * given that the mode is using DSC
+ * Returns:
+ * PBN required for this mode
+ */
+int drm_dp_calc_pbn_mode_dsc(int clock, int dsc_bpp)
+{
+   u64 kbps;
+   s64 peak_kbps;
+   u32 numerator;
+   u32 denominator;
+
+   kbps = clock * dsc_bpp;
+
+   /*
+* margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006
+* The unit of 54/64Mbytes/sec is an arbitrary unit chosen based on
+* common multiplier to render an integer PBN for all link rate/lane
+* counts combinations
+* calculate
+* peak_kbps *= (1/16) bppx16 to bpp
+* peak_kbps *= (1006/1000)
+* peak_kbps *= (64/54)
+* peak_kbps *= 8convert to bytes
+*
+* Divide numerator and denominator by 16 to avoid overflow
+*/
+
+   numerator = 64 * 1006 / 16;
+   denominator = 54 * 8 * 1000 * 1000;
+
+   kbps *= numerator;
+   peak_kbps = drm_fixp_from_fraction(kbps, denominator);
+
+   return drm_fixp2int_ceil(peak_kbps);
+}
+EXPORT_SYMBOL(drm_dp_calc_pbn_mode_dsc);
+
 /* we want to kick the TX after we've ack the up/down IRQs. */
 static void drm_dp_mst_kick_tx(struct drm_dp_mst_topology_mgr *mgr)
 {
diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h
index 2ba6253ea6d3..ddb518f2157a 100644
--- a/include/drm/drm_dp_mst_helper.h
+++ b/include/drm/drm_dp_mst_helper.h
@@ -611,7 +611,7 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector 
*connector, struct drm_dp_
 
 
 int drm_dp_calc_pbn_mode(int clock, int bpp);
-
+int drm_dp_calc_pbn_mode_dsc(int clock, int dsc_bpp);
 
 bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr,
  struct drm_dp_mst_port *port, int pbn, int slots);
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH v3 01/16] Revert "drm/amd/display: skip dsc config for navi10 bring up"

2019-08-21 Thread David Francis
This reverts commit 55ad81f3510ec1a1c19e6a4d8a6319812d07d256.

optc dsc config was causing warnings due to missing register
definitions. With the registers restored, the function can
be re-enabled

The reverted commit also disabled sanity checks and dsc
power gating. The sanity check warnings are not associated
with dsc, and power gating on dsc still has an issue on
non-dsc monitors where the dsc hardware block is never init
and so cannot respond to power gating requests. Therefore,
those are left as is

Signed-off-by: David Francis 
Reviewed-by: Roman Li 
Reviewed-by: Harry Wentland 
Reviewed-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c | 9 -
 1 file changed, 9 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
index aedf9de1c947..99070e93020b 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
@@ -191,15 +191,6 @@ void optc2_set_dsc_config(struct timing_generator *optc,
uint32_t dsc_slice_width)
 {
struct optc *optc1 = DCN10TG_FROM_TG(optc);
-   uint32_t data_format = 0;
-   /* skip if dsc mode is not changed */
-   data_format = dm_read_reg(CTX, REG(OPTC_DATA_FORMAT_CONTROL));
-
-   data_format = data_format & 0x30; /* bit5:4 */
-   data_format = data_format >> 4;
-
-   if (data_format == dsc_mode)
-   return;
 
REG_UPDATE(OPTC_DATA_FORMAT_CONTROL,
OPTC_DSC_MODE, dsc_mode);
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH v3 08/16] drm/amd/display: Initialize DSC PPS variables to 0

2019-08-21 Thread David Francis
For DSC MST, sometimes monitors would break out
in full-screen static. The issue traced back to the
PPS generation code, where these variables were being used
uninitialized and were picking up garbage.

memset to 0 to avoid this

Signed-off-by: David Francis 
Reviewed-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 3 +++
 drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c   | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c 
b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
index 35c5467e60e8..619ac48edd05 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
@@ -491,6 +491,9 @@ bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool 
enable)
struct dsc_config dsc_cfg;
uint8_t dsc_packed_pps[128];
 
+   memset(_cfg, 0, sizeof(dsc_cfg));
+   memset(dsc_packed_pps, 0, 128);
+
/* Enable DSC hw block */
dsc_cfg.pic_width = stream->timing.h_addressable + 
stream->timing.h_border_left + stream->timing.h_border_right;
dsc_cfg.pic_height = stream->timing.v_addressable + 
stream->timing.v_border_top + stream->timing.v_border_bottom;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c
index 379c9e4ac63b..16debe6d89f2 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c
@@ -207,6 +207,9 @@ static bool dsc2_get_packed_pps(struct 
display_stream_compressor *dsc, const str
struct dsc_reg_values dsc_reg_vals;
struct dsc_optc_config dsc_optc_cfg;
 
+   memset(_reg_vals, 0, sizeof(dsc_reg_vals));
+   memset(_optc_cfg, 0, sizeof(dsc_optc_cfg));
+
DC_LOG_DSC("Getting packed DSC PPS for DSC Config:");
dsc_config_log(dsc, dsc_cfg);
DC_LOG_DSC("DSC Picture Parameter Set (PPS):");
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH v3 04/16] Revert "drm/amd/display: Fix underscan not using proper scaling"

2019-08-21 Thread David Francis
This reverts commit 80e80ec817f161560b4159608fb41bd289abede3.

This commit fixed an issue with underscan commits not updating all
needed timing values, but through various refactors it is no longer
necessary. It causes corruption on odm combine by
overwriting the halved h_active in the stream timing

Signed-off-by: David Francis 
Reviewed-by: Roman Li 
Reviewed-by: Harry Wentland 
Reviewed-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/dc/core/dc.c | 12 +---
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c 
b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 77ac7f707ec5..1189e320062b 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -2127,7 +2127,7 @@ void dc_commit_updates_for_stream(struct dc *dc,
enum surface_update_type update_type;
struct dc_state *context;
struct dc_context *dc_ctx = dc->ctx;
-   int i, j;
+   int i;
 
stream_status = dc_stream_get_status(stream);
context = dc->current_state;
@@ -2165,16 +2165,6 @@ void dc_commit_updates_for_stream(struct dc *dc,
 
copy_surface_update_to_plane(surface, _updates[i]);
 
-   if (update_type >= UPDATE_TYPE_MED) {
-   for (j = 0; j < dc->res_pool->pipe_count; j++) {
-   struct pipe_ctx *pipe_ctx = 
>res_ctx.pipe_ctx[j];
-
-   if (pipe_ctx->plane_state != surface)
-   continue;
-
-   resource_build_scaling_params(pipe_ctx);
-   }
-   }
}
 
copy_stream_update_to_stream(dc, context, stream, stream_update);
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH v3 07/16] drm/amd/display: Use correct helpers to compute timeslots

2019-08-21 Thread David Francis
We were using drm helpers to convert a timing into its
bandwidth, its bandwidth into pbn, and its pbn into timeslots

These helpers
-Did not take DSC timings into account
-Used the link rate and lane count of the link's aux device,
which are not the same as the link's current cap
-Did not take FEC into account (FEC reduces the PBN per timeslot)

For converting timing into PBN, use the new function
drm_dp_calc_pbn_mode_dsc that handles the DSC case

For converting PBN into time slots, amdgpu doesn't use the
'correct' atomic method (drm_dp_atomic_find_vcpi_slots), so
don't add a new helper to cover our approach. Use the same
means of calculating pbn per time slot as the DSC code.

Cc: Jerry Zuo 
Cc: Nicholas Kazlauskas 
Signed-off-by: David Francis 
---
 .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c   | 17 -
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index 5f2c315b18ba..716d6577cdbd 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -189,8 +189,8 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
int slots = 0;
bool ret;
int clock;
-   int bpp = 0;
int pbn = 0;
+   int pbn_per_timeslot, bpp = 0;
 
aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
 
@@ -234,11 +234,18 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
 
bpp = bpp * 3;
 
-   /* TODO need to know link rate */
-
-   pbn = drm_dp_calc_pbn_mode(clock, bpp);
+#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
+   if (stream->timing.flags.DSC)
+   pbn = drm_dp_calc_pbn_mode_dsc(clock,
+   stream->timing.dsc_cfg.bits_per_pixel);
+   else
+#endif
+   pbn = drm_dp_calc_pbn_mode(clock, bpp);
 
-   slots = drm_dp_find_vcpi_slots(mst_mgr, pbn);
+   /* Convert kilobits per second / 64 (for 64 timeslots) to pbn 
(54/64 megabytes per second) */
+   pbn_per_timeslot = dc_link_bandwidth_kbps(
+   stream->link, 
dc_link_get_link_cap(stream->link)) / (8 * 1000 * 54);
+   slots = DIV_ROUND_UP(pbn, pbn_per_timeslot);
ret = drm_dp_mst_allocate_vcpi(mst_mgr, mst_port, pbn, slots);
 
if (!ret)
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH v3 02/16] Revert "drm/amd/display: navi10 bring up skip dsc encoder config"

2019-08-21 Thread David Francis
This reverts commit 5f2fd347eeff7d4ce271920efd47baaa18fe968c.

Re-enable enc2_dp_set_dsc_config. This function caused warnings
due to missing register definitions. With the registers added,
this now works

Signed-off-by: David Francis 
Reviewed-by: Roman Li 
Reviewed-by: Harry Wentland 
Reviewed-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c   | 8 
 1 file changed, 8 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c
index 6d54942ab98b..a4e67286cdad 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c
@@ -277,14 +277,6 @@ static void enc2_dp_set_dsc_config(struct stream_encoder 
*enc,
uint32_t dsc_slice_width)
 {
struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
-   uint32_t dsc_value = 0;
-
-   dsc_value = REG_READ(DP_DSC_CNTL);
-
-   /* dsc disable skip */
-   if ((dsc_value & 0x3) == 0x0)
-   return;
-
 
REG_UPDATE_2(DP_DSC_CNTL,
DP_DSC_MODE, dsc_mode,
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH v2 01/14] Revert "drm/amd/display: skip dsc config for navi10 bring up"

2019-08-20 Thread David Francis
This reverts commit 55ad81f3510ec1a1c19e6a4d8a6319812d07d256.

optc dsc config was causing warnings due to missing register
definitions. With the registers restored, the function can
be re-enabled

The reverted commit also disabled sanity checks and dsc
power gating. The sanity check warnings are not associated
with dsc, and power gating on dsc still has an issue on
non-dsc monitors where the dsc hardware block is never init
and so cannot respond to power gating requests. Therefore,
those are left as is

Signed-off-by: David Francis 
Reviewed-by: Roman Li 
Reviewed-by: Harry Wentland 
Reviewed-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c | 9 -
 1 file changed, 9 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
index aedf9de1c947..99070e93020b 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
@@ -191,15 +191,6 @@ void optc2_set_dsc_config(struct timing_generator *optc,
uint32_t dsc_slice_width)
 {
struct optc *optc1 = DCN10TG_FROM_TG(optc);
-   uint32_t data_format = 0;
-   /* skip if dsc mode is not changed */
-   data_format = dm_read_reg(CTX, REG(OPTC_DATA_FORMAT_CONTROL));
-
-   data_format = data_format & 0x30; /* bit5:4 */
-   data_format = data_format >> 4;
-
-   if (data_format == dsc_mode)
-   return;
 
REG_UPDATE(OPTC_DATA_FORMAT_CONTROL,
OPTC_DSC_MODE, dsc_mode);
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH v2 12/14] drm/amd/display: Write DSC enable to MST DPCD

2019-08-20 Thread David Francis
Rework the dm_helpers_write_dsc_enable callback to
handle the MST case

Depending on how DSC is done, the DP_DSC_ENABLE bit
needs to be set on a different point

For SST, use the link aux

For endpoint DSC over DP-to-DP peer devices,
use the output port

For peer device DSC over DP-to-DP peer devices,
use the upstream (peer) device

For DP-to-HDMI or virtual DP peer devices,
use the output port

For the Synaptix workaround, use the link aux

Cc: Wenjing Liu 
Cc: Nikola Cornij 
Signed-off-by: David Francis 
---
 .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 30 ++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index dfa99e0d6e64..62731c2bf2bf 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -38,6 +38,7 @@
 #include "dc.h"
 #include "amdgpu_dm.h"
 #include "amdgpu_dm_irq.h"
+#include "amdgpu_dm_mst_types.h"
 
 #include "dm_helpers.h"
 
@@ -556,8 +557,35 @@ bool dm_helpers_dp_write_dsc_enable(
 )
 {
uint8_t enable_dsc = enable ? 1 : 0;
+   struct amdgpu_dm_connector *aconnector;
+
+   if (!stream)
+   return false;
+
+   if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
+   aconnector = (struct amdgpu_dm_connector 
*)stream->dm_stream_context;
+
+   if (!aconnector || !aconnector->dc_sink)
+   return false;
+
+   if (!aconnector->dc_sink->sink_dsc_caps.is_virtual_dpcd_dsc)
+   return drm_dp_mst_dpcd_write(>port->aux,
+   DP_DSC_ENABLE, _dsc, 
1) >= 0;
+   else if (is_virtual_dpcd(aconnector->port->parent->port_parent))
+   return 
drm_dp_mst_dpcd_write(>port->parent->port_parent->aux,
+   DP_DSC_ENABLE, _dsc, 
1) >= 0;
+   else if (is_virtual_dpcd(aconnector->port))
+   return drm_dp_mst_dpcd_write(>port->aux,
+   DP_DSC_ENABLE, _dsc, 
1) >= 0;
+   else if (synaptix_workaround(aconnector))
+   return dm_helpers_dp_write_dpcd(ctx, stream->link,
+   DP_DSC_ENABLE, _dsc, 1);
+   }
+
+   if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT)
+   return dm_helpers_dp_write_dpcd(ctx, stream->link, 
DP_DSC_ENABLE, _dsc, 1);
 
-   return dm_helpers_dp_write_dpcd(ctx, stream->sink->link, DP_DSC_ENABLE, 
_dsc, 1);
+   return false;
 }
 #endif
 
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH v2 14/14] drm/amd/display: Trigger modesets on MST DSC connectors

2019-08-20 Thread David Francis
Whenever a connector on an MST network is attached, detached, or
undergoes a modeset, the DSC configs for each stream on that
topology will be recalculated. This can change their required
bandwidth, requiring a full reprogramming, as though a modeset
was performed, even if that stream did not change timing.

Therefore, whenever a crtc has drm_atomic_crtc_needs_modeset,
for each crtc that shares a MST topology with that stream and
supports DSC, add that crtc (and all affected connectors and
planes) to the atomic state and set mode_changed on its state

v2: Do this check only on Navi and before adding connectors
and planes on modesetting crtcs

Cc: Leo Li 
Cc: Nicholas Kazlauskas 
Signed-off-by: David Francis 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 74 +++
 1 file changed, 74 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 145fd73025dc..e64f2a6eb71a 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -6475,7 +6475,70 @@ static int do_aquire_global_lock(struct drm_device *dev,
 
return ret < 0 ? ret : 0;
 }
+#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
+static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct 
drm_crtc *crtc)
+{
+   struct drm_connector *connector;
+   struct drm_connector_state *conn_state;
+   struct drm_connector_list_iter conn_iter;
+   struct drm_crtc_state *new_crtc_state;
+   struct amdgpu_dm_connector *aconnector = NULL, *aconnector_to_add;
+   int i, j;
+   struct drm_crtc *crtcs_affected[AMDGPU_MAX_CRTCS] = { 0 };
+
+   for_each_new_connector_in_state(state, connector, conn_state, i) {
+   if (conn_state->crtc != crtc)
+   continue;
+
+   aconnector = to_amdgpu_dm_connector(connector);
+   if (!aconnector->port)
+   aconnector = NULL;
+   else
+   break;
+   }
+
+   if (!aconnector)
+   return 0;
+
+   i = 0;
+   drm_connector_list_iter_begin(state->dev, _iter);
+   drm_for_each_connector_iter(connector, _iter) {
+   if (!connector->state || !connector->state->crtc)
+   continue;
+
+   aconnector_to_add = to_amdgpu_dm_connector(connector);
+   if (!aconnector_to_add->port)
+   continue;
+
+   if (aconnector_to_add->port->mgr != aconnector->port->mgr)
+   continue;
 
+   if (!aconnector_to_add->dc_sink)
+   continue;
+
+   if 
(!aconnector_to_add->dc_sink->sink_dsc_caps.dsc_dec_caps.is_dsc_supported)
+   continue;
+
+   if (i >= AMDGPU_MAX_CRTCS)
+   continue;
+
+   crtcs_affected[i] = connector->state->crtc;
+   i++;
+   }
+   drm_connector_list_iter_end(_iter);
+
+   for (j = 0; j < i; j++) {
+   new_crtc_state = drm_atomic_get_crtc_state(state, 
crtcs_affected[j]);
+   if (IS_ERR(new_crtc_state))
+   return PTR_ERR(new_crtc_state);
+
+   new_crtc_state->mode_changed = true;
+   }
+
+   return 0;
+
+}
+#endif
 static void get_freesync_config_for_crtc(
struct dm_crtc_state *new_crtc_state,
struct dm_connector_state *new_con_state)
@@ -7160,6 +7223,17 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
if (ret)
goto fail;
 
+#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
+   if (adev->asic_type >= CHIP_NAVI10) {
+   for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, 
new_crtc_state, i) {
+   if (drm_atomic_crtc_needs_modeset(new_crtc_state)) {
+   ret = add_affected_mst_dsc_crtcs(state, crtc);
+   if (ret)
+   goto fail;
+   }
+   }
+   }
+#endif
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, 
new_crtc_state, i) {
if (!drm_atomic_crtc_needs_modeset(new_crtc_state) &&
!new_crtc_state->color_mgmt_changed &&
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH v2 10/14] drm/dp-mst: Fill branch->num_ports

2019-08-20 Thread David Francis
This field on drm_dp_mst_branch was never filled

Initialize it to zero when the list of ports is created.
When a port is added to the list, increment num_ports

Signed-off-by: David Francis 
---
 drivers/gpu/drm/drm_dp_mst_topology.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c 
b/drivers/gpu/drm/drm_dp_mst_topology.c
index 5d5bd42da17c..0c580d5279c1 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -918,6 +918,7 @@ static struct drm_dp_mst_branch 
*drm_dp_add_mst_branch_device(u8 lct, u8 *rad)
INIT_LIST_HEAD(>ports);
kref_init(>topology_kref);
kref_init(>malloc_kref);
+   mstb->num_ports = 0;
return mstb;
 }
 
@@ -1672,6 +1673,7 @@ static void drm_dp_add_port(struct drm_dp_mst_branch 
*mstb,
mutex_lock(>mgr->lock);
drm_dp_mst_topology_get_port(port);
list_add(>next, >ports);
+   mstb->num_ports++;
mutex_unlock(>mgr->lock);
}
 
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH v2 09/14] drm/dp-mst: Export symbols for dpcd read/write

2019-08-20 Thread David Francis
To use these functions in drm driver directories, they must be
exported

Signed-off-by: David Francis 
---
 drivers/gpu/drm/drm_dp_mst_topology.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c 
b/drivers/gpu/drm/drm_dp_mst_topology.c
index b40d975aec76..5d5bd42da17c 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -1512,6 +1512,7 @@ ssize_t drm_dp_mst_dpcd_read(struct drm_dp_aux *aux,
return drm_dp_send_dpcd_read(port->mgr, port,
 offset, size, buffer);
 }
+EXPORT_SYMBOL(drm_dp_mst_dpcd_read);
 
 /**
  * drm_dp_mst_dpcd_write() - write a series of bytes to the DPCD via sideband
@@ -1535,6 +1536,7 @@ ssize_t drm_dp_mst_dpcd_write(struct drm_dp_aux *aux,
return drm_dp_send_dpcd_write(port->mgr, port,
  offset, size, buffer);
 }
+EXPORT_SYMBOL(drm_dp_mst_dpcd_write);
 
 static void drm_dp_check_mstb_guid(struct drm_dp_mst_branch *mstb, u8 *guid)
 {
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH v2 08/14] drm/dp-mst: Parse FEC capability on MST ports

2019-08-20 Thread David Francis
As of DP1.4, ENUM_PATH_RESOURCES returns a bit indicating
if FEC can be supported up to that point in the MST network.

The bit is the first byte of the ENUM_PATH_RESOURCES ack reply,
bottom-most bit (refer to section 2.11.9.4 of DP standard,
v1.4)

That value is needed for FEC and DSC support

Store it on drm_dp_mst_port

Signed-off-by: David Francis 
---
 drivers/gpu/drm/drm_dp_mst_topology.c | 2 ++
 include/drm/drm_dp_mst_helper.h   | 3 +++
 2 files changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c 
b/drivers/gpu/drm/drm_dp_mst_topology.c
index d789b7af7dbf..b40d975aec76 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -552,6 +552,7 @@ static bool 
drm_dp_sideband_parse_enum_path_resources_ack(struct drm_dp_sideband
 {
int idx = 1;
repmsg->u.path_resources.port_number = (raw->msg[idx] >> 4) & 0xf;
+   repmsg->u.path_resources.fec_capable = raw->msg[idx] & 0x1;
idx++;
if (idx > raw->curlen)
goto fail_len;
@@ -2180,6 +2181,7 @@ static int drm_dp_send_enum_path_resources(struct 
drm_dp_mst_topology_mgr *mgr,
DRM_DEBUG_KMS("enum path resources %d: %d %d\n", 
txmsg->reply.u.path_resources.port_number, 
txmsg->reply.u.path_resources.full_payload_bw_number,
   
txmsg->reply.u.path_resources.avail_payload_bw_number);
port->available_pbn = 
txmsg->reply.u.path_resources.avail_payload_bw_number;
+   port->fec_capable = 
txmsg->reply.u.path_resources.fec_capable;
}
}
 
diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h
index ddb518f2157a..fa973773a4a7 100644
--- a/include/drm/drm_dp_mst_helper.h
+++ b/include/drm/drm_dp_mst_helper.h
@@ -108,6 +108,8 @@ struct drm_dp_mst_port {
 * audio-capable.
 */
bool has_audio;
+
+   bool fec_capable;
 };
 
 /**
@@ -312,6 +314,7 @@ struct drm_dp_port_number_req {
 
 struct drm_dp_enum_path_resources_ack_reply {
u8 port_number;
+   bool fec_capable;
u16 full_payload_bw_number;
u16 avail_payload_bw_number;
 };
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH v2 03/14] Revert "drm/amd/display: add global master update lock for DCN2"

2019-08-20 Thread David Francis
This reverts commit 55a6f5bbcf00a49565946c0a9b8c716313dc6c05.

This commit was accidentally promoted twice

Signed-off-by: David Francis 
Reviewed-by: Roman Li 
Reviewed-by: Harry Wentland 
Reviewed-by: Nicholas Kazlauskas 
---
 .../drm/amd/display/dc/dcn20/dcn20_hwseq.c|  4 --
 .../gpu/drm/amd/display/dc/dcn20/dcn20_optc.c | 63 +--
 .../gpu/drm/amd/display/dc/dcn20/dcn20_optc.h |  3 -
 .../amd/display/dc/inc/hw/timing_generator.h  |  2 -
 4 files changed, 1 insertion(+), 71 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
index fa8a73f6c8e3..e146d1d8d45e 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
@@ -575,10 +575,6 @@ enum dc_status dcn20_enable_stream_timing(
pipe_ctx->stream->signal,
true);
 
-   if (pipe_ctx->stream_res.tg->funcs->setup_global_lock)
-   pipe_ctx->stream_res.tg->funcs->setup_global_lock(
-   pipe_ctx->stream_res.tg);
-
if (odm_pipe)
odm_pipe->stream_res.opp->funcs->opp_pipe_clock_control(
odm_pipe->stream_res.opp,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
index 99070e93020b..2137e2be2140 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
@@ -333,65 +333,6 @@ void optc2_triplebuffer_unlock(struct timing_generator 
*optc)
 
 }
 
-
-void optc2_setup_global_lock(struct timing_generator *optc)
-{
-   struct optc *optc1 = DCN10TG_FROM_TG(optc);
-   uint32_t v_blank_start = 0;
-   uint32_t h_blank_start = 0, h_total = 0;
-
-   REG_SET(OTG_GLOBAL_CONTROL1, 0, MASTER_UPDATE_LOCK_DB_EN, 1);
-
-   REG_SET(OTG_GLOBAL_CONTROL2, 0, DIG_UPDATE_LOCATION, 20);
-
-   REG_GET(OTG_V_BLANK_START_END, OTG_V_BLANK_START, _blank_start);
-
-   REG_GET(OTG_H_BLANK_START_END, OTG_H_BLANK_START, _blank_start);
-
-   REG_GET(OTG_H_TOTAL, OTG_H_TOTAL, _total);
-   REG_UPDATE_2(OTG_GLOBAL_CONTROL1,
-   MASTER_UPDATE_LOCK_DB_X,
-   h_blank_start - 200 - 1,
-   MASTER_UPDATE_LOCK_DB_Y,
-   v_blank_start - 1);
-}
-
-void optc2_lock_global(struct timing_generator *optc)
-{
-   struct optc *optc1 = DCN10TG_FROM_TG(optc);
-
-   REG_UPDATE(OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, 1);
-
-   REG_SET(OTG_GLOBAL_CONTROL0, 0,
-   OTG_MASTER_UPDATE_LOCK_SEL, optc->inst);
-   REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
-   OTG_MASTER_UPDATE_LOCK, 1);
-
-   /* Should be fast, status does not update on maximus */
-   if (optc->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS)
-   REG_WAIT(OTG_MASTER_UPDATE_LOCK,
-   UPDATE_LOCK_STATUS, 1,
-   1, 10);
-}
-
-void optc2_lock(struct timing_generator *optc)
-{
-   struct optc *optc1 = DCN10TG_FROM_TG(optc);
-
-   REG_UPDATE(OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, 0);
-
-   REG_SET(OTG_GLOBAL_CONTROL0, 0,
-   OTG_MASTER_UPDATE_LOCK_SEL, optc->inst);
-   REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
-   OTG_MASTER_UPDATE_LOCK, 1);
-
-   /* Should be fast, status does not update on maximus */
-   if (optc->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS)
-   REG_WAIT(OTG_MASTER_UPDATE_LOCK,
-   UPDATE_LOCK_STATUS, 1,
-   1, 10);
-}
-
 void optc2_lock_doublebuffer_enable(struct timing_generator *optc)
 {
struct optc *optc1 = DCN10TG_FROM_TG(optc);
@@ -486,10 +427,8 @@ static struct timing_generator_funcs dcn20_tg_funcs = {
.triplebuffer_lock = optc2_triplebuffer_lock,
.triplebuffer_unlock = optc2_triplebuffer_unlock,
.disable_reset_trigger = optc1_disable_reset_trigger,
-   .lock = optc2_lock,
+   .lock = optc1_lock,
.unlock = optc1_unlock,
-   .lock_global = optc2_lock_global,
-   .setup_global_lock = optc2_setup_global_lock,
.lock_doublebuffer_enable = optc2_lock_doublebuffer_enable,
.lock_doublebuffer_disable = optc2_lock_doublebuffer_disable,
.enable_optc_clock = optc1_enable_optc_clock,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h
index 47cb4de1564c..32a58431fd09 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h
@@ -106,9 +106,6 @@ void optc2_get_optc_source(struct timing_generator *optc,
 
 void optc

[PATCH v2 13/14] drm/amd/display: MST DSC compute fair share

2019-08-20 Thread David Francis
If there is limited link bandwidth on a MST network,
it must be divided fairly between the streams on that network

Implement an algorithm to determine the correct DSC config
for each stream

The algorithm:
This
 [   ]  ( )
represents the range of bandwidths possible for a given stream.
The [] area represents the range of DSC configs, and the ()
represents no DSC. The bandwidth used increases from left to right.

First, try disabling DSC on all streams
 [  ]  (|)
 [ ](|)
Check this against the bandwidth limits of the link and each branch
(including each endpoint). If it passes, the job is done

Second, try maximum DSC compression on all streams
that support DSC
 [| ]( )
 [|] ( )
If this does not pass, then enabling this combination of streams
is impossible

Otherwise, divide the remaining bandwidth evenly amongst the streams
 [|  ] ( )
 [|  ]( )

If one or more of the streams reach minimum compression, evenly
divide the reamining bandwidth amongst the remaining streams
 [|] ( )
 [   |]   ( )
 [ |   ]   ( )
 [ |  ]  ( )

If all streams can reach minimum compression, disable compression
greedily
 [  |]  ( )
 [|]( )
 [ ](|)

Perform this algorithm on each full update, on each MST link
with at least one DSC stream on it

After the configs are computed, call
dcn20_add_dsc_to_stream_resource on each stream with DSC enabled.
It is only after all streams are created that we can know which
of them will need DSC.

Do all of this at the end of amdgpu atomic check.  If it fails,
fail check; This combination of timings cannot be supported.

Cc: Wenjing Liu 
Cc: Nikola Cornij 
Signed-off-by: David Francis 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |   4 +
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 375 ++
 .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |   4 +-
 .../drm/amd/display/dc/dcn20/dcn20_resource.c |   7 +-
 .../drm/amd/display/dc/dcn20/dcn20_resource.h |   1 +
 5 files changed, 388 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 84249057e181..145fd73025dc 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -7331,6 +7331,10 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
if (ret)
goto fail;
 
+#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
+   if (!compute_mst_dsc_configs_for_state(dm_state->context))
+   goto fail;
+#endif
if (dc_validate_global_state(dc, dm_state->context, false) != 
DC_OK) {
ret = -EINVAL;
goto fail;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 58571844f6d5..0b6bfa093e83 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -38,6 +38,8 @@
 
 #include "i2caux_interface.h"
 
+#include "dc/dcn20/dcn20_resource.h"
+
 /* #define TRACE_DPCD */
 
 #ifdef TRACE_DPCD
@@ -548,3 +550,376 @@ void amdgpu_dm_initialize_dp_connector(struct 
amdgpu_display_manager *dm,
aconnector->connector_id);
 }
 
+#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
+struct dsc_mst_fairness_params {
+   struct dc_crtc_timing *timing;
+   struct dc_sink *sink;
+   struct dc_dsc_bw_range bw_range;
+   bool compression_possible;
+   struct drm_dp_mst_port *port;
+};
+
+struct dsc_mst_fairness_vars {
+   int pbn;
+   bool dsc_enabled;
+   int bpp_x16;
+};
+
+static bool port_downstream_of_branch(struct drm_dp_mst_port *port,
+   struct drm_dp_mst_branch *branch)
+{
+   while (port->parent) {
+   if (port->parent == branch)
+   return true;
+
+   if (port->parent->port_parent)
+   port = port->parent->port_parent;
+   else
+   break;
+   }
+   return false;
+}
+
+static bool check_pbn_limit_on_branch(struct drm_dp_mst_branch *branch,
+   struct dsc_mst_fairness_params *params,
+   struct dsc_mst_fairness_vars *vars, int count)
+{
+   struct drm_dp_mst_port *port;
+   int i;
+   int pbn_limit = 0;
+   int pbn_used = 0;
+
+   list_for_each_entry(port, >ports, next) {
+   if (port->mstb)
+   if (!check_pbn_limit_on_branch(port->mstb, params, 
vars, count))
+  

[PATCH v2 07/14] drm/amd/display: Initialize DSC PPS variables to 0

2019-08-20 Thread David Francis
For DSC MST, sometimes monitors would break out
in full-screen static. The issue traced back to the
PPS generation code, where these variables were being used
uninitialized and were picking up garbage.

memset to 0 to avoid this

Signed-off-by: David Francis 
Reviewed-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 3 +++
 drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c   | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c 
b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
index 35c5467e60e8..619ac48edd05 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
@@ -491,6 +491,9 @@ bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool 
enable)
struct dsc_config dsc_cfg;
uint8_t dsc_packed_pps[128];
 
+   memset(_cfg, 0, sizeof(dsc_cfg));
+   memset(dsc_packed_pps, 0, 128);
+
/* Enable DSC hw block */
dsc_cfg.pic_width = stream->timing.h_addressable + 
stream->timing.h_border_left + stream->timing.h_border_right;
dsc_cfg.pic_height = stream->timing.v_addressable + 
stream->timing.v_border_top + stream->timing.v_border_bottom;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c
index 379c9e4ac63b..16debe6d89f2 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c
@@ -207,6 +207,9 @@ static bool dsc2_get_packed_pps(struct 
display_stream_compressor *dsc, const str
struct dsc_reg_values dsc_reg_vals;
struct dsc_optc_config dsc_optc_cfg;
 
+   memset(_reg_vals, 0, sizeof(dsc_reg_vals));
+   memset(_optc_cfg, 0, sizeof(dsc_optc_cfg));
+
DC_LOG_DSC("Getting packed DSC PPS for DSC Config:");
dsc_config_log(dsc, dsc_cfg);
DC_LOG_DSC("DSC Picture Parameter Set (PPS):");
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH v2 06/14] drm/dp-mst: Use dc and drm helpers to compute timeslots

2019-08-20 Thread David Francis
We were using drm helpers to convert a timing into its
bandwidth, its bandwidth into pbn, and its pbn into timeslots

These helpers
-Did not take DSC timings into account
-Used the link rate and lane count of the link's aux device,
 which are not the same as the link's current cap
-Did not take FEC into account (FEC reduces the PBN per timeslot)

For converting timing into PBN, add a new function
drm_dp_calc_pbn_mode_dsc that handles the DSC case

For converting PBN into time slots, amdgpu doesn't use the
'correct' atomic method (drm_dp_atomic_find_vcpi_slots), so
don't add a new helper to cover our approach. Use the same
means of calculating pbn per time slot as the DSC code.

v2: Add drm helper for clock to pbn conversion

Cc: Jerry Zuo 
Cc: Nicholas Kazlauskas 
Signed-off-by: David Francis 
---
 .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 18 +---
 drivers/gpu/drm/drm_dp_mst_topology.c | 41 +++
 include/drm/drm_dp_mst_helper.h   |  2 +-
 3 files changed, 54 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index 5f2c315b18ba..dfa99e0d6e64 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -189,8 +189,8 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
int slots = 0;
bool ret;
int clock;
-   int bpp = 0;
int pbn = 0;
+   int pbn_per_timeslot, bpp = 0;
 
aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
 
@@ -208,7 +208,6 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
clock = stream->timing.pix_clk_100hz / 10;
 
switch (stream->timing.display_color_depth) {
-
case COLOR_DEPTH_666:
bpp = 6;
break;
@@ -234,11 +233,18 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
 
bpp = bpp * 3;
 
-   /* TODO need to know link rate */
-
-   pbn = drm_dp_calc_pbn_mode(clock, bpp);
+#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
+   if (stream->timing.flags.DSC)
+   pbn = drm_dp_calc_pbn_mode_dsc(clock,
+   stream->timing.dsc_cfg.bits_per_pixel);
+   else
+#endif
+   pbn = drm_dp_calc_pbn_mode(clock, bpp);
 
-   slots = drm_dp_find_vcpi_slots(mst_mgr, pbn);
+   /* Convert kilobits per second / 64 (for 64 timeslots) to pbn 
(54/64 megabytes per second) */
+   pbn_per_timeslot = dc_link_bandwidth_kbps(
+   stream->link, 
dc_link_get_link_cap(stream->link)) / (8 * 1000 * 54);
+   slots = DIV_ROUND_UP(pbn, pbn_per_timeslot);
ret = drm_dp_mst_allocate_vcpi(mst_mgr, mst_port, pbn, slots);
 
if (!ret)
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c 
b/drivers/gpu/drm/drm_dp_mst_topology.c
index 398e7314ea8b..d789b7af7dbf 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -3588,6 +3588,47 @@ static int test_calc_pbn_mode(void)
return 0;
 }
 
+/**
+ * drm_dp_calc_pbn_mode_dsc() - Calculate the PBN for a mode with DSC enabled.
+ * @clock: dot clock for the mode
+ * @dsc_bpp: dsc bits per pixel x16 (e.g. dsc_bpp = 136 is 8.5 bpp)
+ *
+ * This uses the formula in the spec to calculate the PBN value for a mode,
+ * given that the mode is using DSC
+ */
+int drm_dp_calc_pbn_mode_dsc(int clock, int dsc_bpp)
+{
+   u64 kbps;
+   s64 peak_kbps;
+   u32 numerator;
+   u32 denominator;
+
+   kbps = clock * dsc_bpp;
+
+   /*
+* margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006
+* The unit of 54/64Mbytes/sec is an arbitrary unit chosen based on
+* common multiplier to render an integer PBN for all link rate/lane
+* counts combinations
+* calculate
+* peak_kbps *= (1/16) bppx16 to bpp
+* peak_kbps *= (1006/1000)
+* peak_kbps *= (64/54)
+* peak_kbps *= 8convert to bytes
+*
+* Divide numerator and denominator by 16 to avoid overflow
+*/
+
+   numerator = 64 * 1006 / 16;
+   denominator = 54 * 8 * 1000 * 1000;
+
+   kbps *= numerator;
+   peak_kbps = drm_fixp_from_fraction(kbps, denominator);
+
+   return drm_fixp2int_ceil(peak_kbps);
+}
+EXPORT_SYMBOL(drm_dp_calc_pbn_mode_dsc);
+
 /* we want to kick the TX after we've ack the up/down IRQs. */
 static void drm_dp_mst_kick_tx(struct drm_dp_mst_topology_mgr *mgr)
 {
diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h
index 2ba6253ea6d3..ddb518f2157a 100644
--- a/include/drm/drm_dp_mst_helper.h
+++ b/include/drm/drm_dp_mst_helper.h
@@ -611,7 +611,7 @@ struct edid *drm_dp_mst_get_edid

[PATCH v2 02/14] Revert "drm/amd/display: navi10 bring up skip dsc encoder config"

2019-08-20 Thread David Francis
This reverts commit 5f2fd347eeff7d4ce271920efd47baaa18fe968c.

Re-enable enc2_dp_set_dsc_config. This function caused warnings
due to missing register definitions. With the registers added,
this now works

Signed-off-by: David Francis 
Reviewed-by: Roman Li 
Reviewed-by: Harry Wentland 
Reviewed-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c   | 8 
 1 file changed, 8 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c
index 6d54942ab98b..a4e67286cdad 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c
@@ -277,14 +277,6 @@ static void enc2_dp_set_dsc_config(struct stream_encoder 
*enc,
uint32_t dsc_slice_width)
 {
struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
-   uint32_t dsc_value = 0;
-
-   dsc_value = REG_READ(DP_DSC_CNTL);
-
-   /* dsc disable skip */
-   if ((dsc_value & 0x3) == 0x0)
-   return;
-
 
REG_UPDATE_2(DP_DSC_CNTL,
DP_DSC_MODE, dsc_mode,
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH v2 11/14] drm/amd/display: Validate DSC caps on MST endpoints

2019-08-20 Thread David Francis
The first step in MST DSC is checking MST endpoints
to see how DSC can be enabled

Case 1: DP-to-DP peer device
if the branch immediately upstream has
 - PDT = DP_PEER_DEVICE_DP_MST_BRANCHING (2)
 - DPCD rev. >= DP 1.4
 - Exactly one input and one output
 - The output has PDT = DP_PEER_DEVICE_SST_SINK (3)

In this case, DSC could be possible either on the endpoint
or the peer device. Prefer the endpoint, which is possible if
 - The endpoint has DP_DSC_DECOMPRESSION_IS_SUPPORTED bit set
 - The endpoint has DP_FEC_CAPABLE bit set
 - The peer device has DSC_PASSTHROUGH_CAPABILITY bit set (from DP v2.0)

Otherwise, use the peer device

Case 2: DP-to-HDMI peer device
If the output port has
 - PDT = DP_PEER_DEVICE_DP_LEGACY_CONV (4)
 - DPCD rev. >= DP 1.4
 - LDPS = true
 - MCS = false

In this case, DSC can only be attempted on the peer device
(the output port)

Case 3: Virtual DP Sink (Internal Display Panel)
If the output port has
 - DPCD rev. >= DP 1.4
 - port_num >= 8

In this case, DSC can only be attempted on the peer device
(the output port)

Case 4: Synaptix Workaround
If the output has
 - link DPCD rev. >= DP 1.4
 - link branch_dev_id = 0x90CC24 (Synaptix)
 - There is exactly one branch device between the link and output

In this case, DSC can be attempted, but only using the *link*
aux device's caps. This is a quirk.

Test for these cases as modes are enumerated for an MST endpoint.
We cannot do this during link attach because the dc_sink object
will not have been created yet

If no DSC is attempted, zero the DSC caps

Cc: Wenjing Liu 
Cc: Nikola Cornij 
Signed-off-by: David Francis 
---
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 123 +-
 .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |   3 +
 2 files changed, 125 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 16218a202b59..58571844f6d5 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -25,6 +25,7 @@
 
 #include 
 #include 
+#include 
 #include "dm_services.h"
 #include "amdgpu.h"
 #include "amdgpu_dm.h"
@@ -189,6 +190,120 @@ static const struct drm_connector_funcs 
dm_dp_mst_connector_funcs = {
.early_unregister = amdgpu_dm_mst_connector_early_unregister,
 };
 
+bool is_virtual_dpcd(struct drm_dp_mst_port *port)
+{
+   struct drm_dp_mst_port *downstream_port;
+
+   if (!port)
+   return false;
+
+   if (port->port_num >= 8 &&
+   port->dpcd_rev >= DP_DPCD_REV_14) {
+   /* Virtual DP Sink (Internal Display Panel) */
+   return true;
+   } else if (port->pdt == DP_PEER_DEVICE_DP_LEGACY_CONV &&
+   !port->mcs &&
+   port->ldps &&
+   port->dpcd_rev >= DP_DPCD_REV_14) {
+   /* DP-to-HDMI Protocol Converter */
+   return true;
+   } else if (port->pdt == DP_PEER_DEVICE_MST_BRANCHING &&
+   port->mstb &&
+   port->dpcd_rev >= DP_DPCD_REV_14) {
+   /* DP-to-DP */
+   if (port->mstb->num_ports == 2) {
+   list_for_each_entry(downstream_port, 
>mstb->ports, next) {
+   if (!downstream_port->input &&
+   downstream_port->pdt == 
DP_PEER_DEVICE_SST_SINK)
+   return true;
+   }
+   }
+   }
+   return false;
+}
+
+bool synaptix_workaround(struct amdgpu_dm_connector *aconnector)
+{
+   struct drm_dp_mst_port *port = aconnector->port;
+   struct dc_link *link = aconnector->dc_sink->link;
+   u8 down_stream_port_data;
+
+   if (port->mgr->mst_primary == port->parent &&
+   link->dpcd_caps.branch_dev_id == 0x90CC24 &&
+   link->dpcd_caps.dpcd_rev.raw >= DP_DPCD_REV_14) {
+   drm_dp_mst_dpcd_read(>aux, DP_DOWNSTREAMPORT_PRESENT, 
_stream_port_data, 1);
+   if ((down_stream_port_data & 7) != 3)
+   return true;
+   }
+   return false;
+}
+
+#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
+static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector 
*aconnector)
+{
+   u8 upstream_dsc_caps[16] = { 0 };
+   u8 endpoint_dsc_caps[16] = { 0 };
+   u8 endpoint_fec_caps = 0;
+   struct dc_sink *dc_sink = aconnector->dc_sink;
+   struct drm_dp_mst_port *output_port = aconnector->port;
+   struct drm_dp_mst_port *immediate_upstream_port;
+   struct drm_dp_mst_port *fec_port;
+
+   if (aconnector->por

[PATCH v2 05/14] drm/amd/display: Enable SST DSC in DM

2019-08-20 Thread David Francis
In create_stream_for_sink, check for SST DP connectors

Parse DSC caps to DC format, then, if DSC is supported,
compute the config

DSC hardware will be programmed by dc_commit_state

Tested-by: Mikita Lipski 
Signed-off-by: David Francis 
Reviewed-by: Nicholas Kazlauskas 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 32 ---
 .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  4 ++-
 2 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 911fe78b47c1..84249057e181 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3576,6 +3576,10 @@ create_stream_for_sink(struct amdgpu_dm_connector 
*aconnector,
bool scale = dm_state ? (dm_state->scaling != RMX_OFF) : false;
int mode_refresh;
int preferred_refresh = 0;
+#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
+   struct dsc_dec_dpcd_caps dsc_caps;
+   uint32_t link_bandwidth_kbps;
+#endif
 
struct dc_sink *sink = NULL;
if (aconnector == NULL) {
@@ -3648,17 +3652,23 @@ create_stream_for_sink(struct amdgpu_dm_connector 
*aconnector,
, >base, con_state, old_stream);
 
 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
-   /* stream->timing.flags.DSC = 0; */
-/*  */
-   /* if (aconnector->dc_link && */
-   /*  aconnector->dc_link->connector_signal == 
SIGNAL_TYPE_DISPLAY_PORT #<{(|&& */
-   /*  
aconnector->dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.is_dsc_supported|)}>#) */
-   /*  if (dc_dsc_compute_config(aconnector->dc_link->ctx->dc, */
-   /*  >dc_link->dpcd_caps.dsc_caps, */
-   /*  dc_link_bandwidth_kbps(aconnector->dc_link, 
dc_link_get_link_cap(aconnector->dc_link)), */
-   /*  >timing, */
-   /*  >timing.dsc_cfg)) */
-   /*  stream->timing.flags.DSC = 1; */
+   stream->timing.flags.DSC = 0;
+
+   if (aconnector->dc_link && sink->sink_signal == 
SIGNAL_TYPE_DISPLAY_PORT) {
+   
dc_dsc_parse_dsc_dpcd(aconnector->dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.raw,
+ 
aconnector->dc_link->dpcd_caps.dsc_caps.dsc_ext_caps.raw,
+ _caps);
+   link_bandwidth_kbps = 
dc_link_bandwidth_kbps(aconnector->dc_link,
+
dc_link_get_link_cap(aconnector->dc_link));
+
+   if (dsc_caps.is_dsc_supported)
+   if (dc_dsc_compute_config(aconnector->dc_link->ctx->dc,
+ _caps,
+ link_bandwidth_kbps,
+ >timing,
+ >timing.dsc_cfg))
+   stream->timing.flags.DSC = 1;
+   }
 #endif
 
update_stream_scaling_settings(, dm_state, stream);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index 7cf0573ab25f..5f2c315b18ba 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -549,7 +549,9 @@ bool dm_helpers_dp_write_dsc_enable(
bool enable
 )
 {
-   return false;
+   uint8_t enable_dsc = enable ? 1 : 0;
+
+   return dm_helpers_dp_write_dpcd(ctx, stream->sink->link, DP_DSC_ENABLE, 
_dsc, 1);
 }
 #endif
 
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH v2 04/14] Revert "drm/amd/display: Fix underscan not using proper scaling"

2019-08-20 Thread David Francis
This reverts commit 80e80ec817f161560b4159608fb41bd289abede3.

This commit fixed an issue with underscan commits not updating all
needed timing values, but through various refactors it is no longer
necessary. It causes corruption on odm combine by
overwriting the halved h_active in the stream timing

Signed-off-by: David Francis 
Reviewed-by: Roman Li 
Reviewed-by: Harry Wentland 
Reviewed-by: Nicholas Kazlauskas 
---
 drivers/gpu/drm/amd/display/dc/core/dc.c | 12 +---
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c 
b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 77ac7f707ec5..1189e320062b 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -2127,7 +2127,7 @@ void dc_commit_updates_for_stream(struct dc *dc,
enum surface_update_type update_type;
struct dc_state *context;
struct dc_context *dc_ctx = dc->ctx;
-   int i, j;
+   int i;
 
stream_status = dc_stream_get_status(stream);
context = dc->current_state;
@@ -2165,16 +2165,6 @@ void dc_commit_updates_for_stream(struct dc *dc,
 
copy_surface_update_to_plane(surface, _updates[i]);
 
-   if (update_type >= UPDATE_TYPE_MED) {
-   for (j = 0; j < dc->res_pool->pipe_count; j++) {
-   struct pipe_ctx *pipe_ctx = 
>res_ctx.pipe_ctx[j];
-
-   if (pipe_ctx->plane_state != surface)
-   continue;
-
-   resource_build_scaling_params(pipe_ctx);
-   }
-   }
}
 
copy_stream_update_to_stream(dc, context, stream, stream_update);
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH v2 00/14] Display Stream Compression (DSC) for AMD Navi

2019-08-20 Thread David Francis
This patchset enables Display Stream Compression (DSC) on DP
connectors on Navi ASICs, both SST and DSC.

8k60 and 4k144 support requires ODM combine, an AMD internal
feature that may be a bit buggy right now.

Patches 1 through 5 enable DSC for SST. Most of the work was
already done in the Navi promotion patches; this just hooks
it up to the atomic interface. The first two reverts are of temporary
changes to block off DSC. The third is of a commit that was
accidentally promoted twice. The fourth and last revert fixes a
potential issue with ODM combine.

Patches 6 and 7 are fixes for bugs that would be exposed by
MST DSC. One fix is with the MST code and the other in the DSC code.

Patches 8, 9, and 10 are small DRM changes required for DSC MST:
FEC, a new bit in the standard; some export definitions; and
a previously uninitialized variable.

Patches 11 through 14 are the DSC MST policy itself. This includes
the code for detecting and validating DSC capabilities, enabling
DSC over a link, computing the fair DSC configurations for
multiple DSC displays, and adding to atomic state crtcs that might
need reprogramming due to DSC.

v2: Updating patches 6 and 14 in respoinse to Nick's feedback

David Francis (14):
  Revert "drm/amd/display: skip dsc config for navi10 bring up"
  Revert "drm/amd/display: navi10 bring up skip dsc encoder config"
  Revert "drm/amd/display: add global master update lock for DCN2"
  Revert "drm/amd/display: Fix underscan not using proper scaling"
  drm/amd/display: Enable SST DSC in DM
  drm/dp-mst: Use dc and drm helpers to compute timeslots
  drm/amd/display: Initialize DSC PPS variables to 0
  drm/dp-mst: Parse FEC capability on MST ports
  drm/dp-mst: Export symbols for dpcd read/write
  drm/dp-mst: Fill branch->num_ports
  drm/amd/display: Validate DSC caps on MST endpoints
  drm/amd/display: Write DSC enable to MST DPCD
  drm/amd/display: MST DSC compute fair share
  drm/amd/display: Trigger modesets on MST DSC connectors

 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 110 +++-
 .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  48 +-
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 498 +-
 .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |   5 +
 drivers/gpu/drm/amd/display/dc/core/dc.c  |  12 +-
 .../drm/amd/display/dc/core/dc_link_hwss.c|   3 +
 .../gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c  |   3 +
 .../drm/amd/display/dc/dcn20/dcn20_hwseq.c|   4 -
 .../gpu/drm/amd/display/dc/dcn20/dcn20_optc.c |  72 +--
 .../gpu/drm/amd/display/dc/dcn20/dcn20_optc.h |   3 -
 .../drm/amd/display/dc/dcn20/dcn20_resource.c |   7 +-
 .../drm/amd/display/dc/dcn20/dcn20_resource.h |   1 +
 .../display/dc/dcn20/dcn20_stream_encoder.c   |   8 -
 .../amd/display/dc/inc/hw/timing_generator.h  |   2 -
 drivers/gpu/drm/drm_dp_mst_topology.c |  47 ++
 include/drm/drm_dp_mst_helper.h   |   5 +-
 16 files changed, 708 insertions(+), 120 deletions(-)

-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 13/14] drm/amd/display: MST DSC compute fair share

2019-08-19 Thread David Francis
If there is limited link bandwidth on a MST network,
it must be divided fairly between the streams on that network

Implement an algorithm to determine the correct DSC config
for each stream

The algorithm:
This
 [   ]  ( )
represents the range of bandwidths possible for a given stream.
The [] area represents the range of DSC configs, and the ()
represents no DSC. The bandwidth used increases from left to right.

First, try disabling DSC on all streams
 [  ]  (|)
 [ ](|)
Check this against the bandwidth limits of the link and each branch
(including each endpoint). If it passes, the job is done

Second, try maximum DSC compression on all streams
that support DSC
 [| ]( )
 [|] ( )
If this does not pass, then enabling this combination of streams
is impossible

Otherwise, divide the remaining bandwidth evenly amongst the streams
 [|  ] ( )
 [|  ]( )

If one or more of the streams reach minimum compression, evenly
divide the reamining bandwidth amongst the remaining streams
 [|] ( )
 [   |]   ( )
 [ |   ]   ( )
 [ |  ]  ( )

If all streams can reach minimum compression, disable compression
greedily
 [  |]  ( )
 [|]( )
 [ ](|)

Perform this algorithm on each full update, on each MST link
with at least one DSC stream on it

After the configs are computed, call
dcn20_add_dsc_to_stream_resource on each stream with DSC enabled.
It is only after all streams are created that we can know which
of them will need DSC.

Do all of this at the end of amdgpu atomic check.  If it fails,
fail check; This combination of timings cannot be supported.

Cc: Wenjing Liu 
Cc: Nikola Cornij 
Signed-off-by: David Francis 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |   4 +
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 375 ++
 .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |   4 +-
 .../drm/amd/display/dc/dcn20/dcn20_resource.c |   7 +-
 .../drm/amd/display/dc/dcn20/dcn20_resource.h |   1 +
 5 files changed, 388 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 84249057e181..145fd73025dc 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -7331,6 +7331,10 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
if (ret)
goto fail;
 
+#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
+   if (!compute_mst_dsc_configs_for_state(dm_state->context))
+   goto fail;
+#endif
if (dc_validate_global_state(dc, dm_state->context, false) != 
DC_OK) {
ret = -EINVAL;
goto fail;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 58571844f6d5..0b6bfa093e83 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -38,6 +38,8 @@
 
 #include "i2caux_interface.h"
 
+#include "dc/dcn20/dcn20_resource.h"
+
 /* #define TRACE_DPCD */
 
 #ifdef TRACE_DPCD
@@ -548,3 +550,376 @@ void amdgpu_dm_initialize_dp_connector(struct 
amdgpu_display_manager *dm,
aconnector->connector_id);
 }
 
+#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
+struct dsc_mst_fairness_params {
+   struct dc_crtc_timing *timing;
+   struct dc_sink *sink;
+   struct dc_dsc_bw_range bw_range;
+   bool compression_possible;
+   struct drm_dp_mst_port *port;
+};
+
+struct dsc_mst_fairness_vars {
+   int pbn;
+   bool dsc_enabled;
+   int bpp_x16;
+};
+
+static bool port_downstream_of_branch(struct drm_dp_mst_port *port,
+   struct drm_dp_mst_branch *branch)
+{
+   while (port->parent) {
+   if (port->parent == branch)
+   return true;
+
+   if (port->parent->port_parent)
+   port = port->parent->port_parent;
+   else
+   break;
+   }
+   return false;
+}
+
+static bool check_pbn_limit_on_branch(struct drm_dp_mst_branch *branch,
+   struct dsc_mst_fairness_params *params,
+   struct dsc_mst_fairness_vars *vars, int count)
+{
+   struct drm_dp_mst_port *port;
+   int i;
+   int pbn_limit = 0;
+   int pbn_used = 0;
+
+   list_for_each_entry(port, >ports, next) {
+   if (port->mstb)
+   if (!check_pbn_limit_on_branch(port->mstb, params, 
vars, count))
+  

[PATCH 14/14] drm/amd/display: Trigger modesets on MST DSC connectors

2019-08-19 Thread David Francis
Whenever a connector on an MST network is attached, detached, or
undergoes a modeset, the DSC configs for each stream on that
topology will be recalculated. This can change their required
bandwidth, requiring a full reprogramming, as though a modeset
was performed, even if that stream did not change timing.

Therefore, whenever a crtc has drm_atomic_crtc_needs_modeset,
for each crtc that shares a MST topology with that stream and
supports DSC, add that crtc (and all affected connectors and
planes) to the atomic state and set mode_changed on its state

Cc: Leo Li 
Cc: Nicholas Kazlauskas 
Signed-off-by: David Francis 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 80 +++
 1 file changed, 80 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 145fd73025dc..8d5357aec5e8 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -6475,7 +6475,78 @@ static int do_aquire_global_lock(struct drm_device *dev,
 
return ret < 0 ? ret : 0;
 }
+#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
+static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct 
drm_crtc *crtc)
+{
+   struct drm_connector *connector;
+   struct drm_connector_state *conn_state;
+   struct drm_connector_list_iter conn_iter;
+   struct drm_crtc_state *new_crtc_state;
+   struct amdgpu_dm_connector *aconnector = NULL, *aconnector_to_add;
+   int i, j, ret;
+   struct drm_crtc *crtcs_affected[MAX_PIPES] = { 0 };
+
+   for_each_new_connector_in_state(state, connector, conn_state, i) {
+   if (conn_state->crtc != crtc)
+   continue;
+
+   aconnector = to_amdgpu_dm_connector(connector);
+   if (!aconnector->port)
+   aconnector = NULL;
+   else
+   break;
+   }
+
+   if (!aconnector)
+   return 0;
+
+   i = 0;
+   drm_connector_list_iter_begin(state->dev, _iter);
+   drm_for_each_connector_iter(connector, _iter) {
+   if (!connector->state || !connector->state->crtc)
+   continue;
+
+   aconnector_to_add = to_amdgpu_dm_connector(connector);
+   if (!aconnector_to_add->port)
+   continue;
+
+   if (aconnector_to_add->port->mgr != aconnector->port->mgr)
+   continue;
+
+   if (!aconnector_to_add->dc_sink)
+   continue;
+
+   if 
(!aconnector_to_add->dc_sink->sink_dsc_caps.dsc_dec_caps.is_dsc_supported)
+   continue;
 
+   if (i >= MAX_PIPES)
+   continue;
+
+   crtcs_affected[i] = connector->state->crtc;
+   i++;
+   }
+   drm_connector_list_iter_end(_iter);
+
+   for (j = 0; j < i; j++) {
+   new_crtc_state = drm_atomic_get_crtc_state(state, 
crtcs_affected[j]);
+   if (IS_ERR(new_crtc_state))
+   return PTR_ERR(new_crtc_state);
+
+   new_crtc_state->mode_changed = true;
+
+   ret = drm_atomic_add_affected_connectors(state, 
crtcs_affected[j]);
+   if (ret)
+   return ret;
+
+   ret = drm_atomic_add_affected_planes(state, crtcs_affected[j]);
+   if (ret)
+   return ret;
+   }
+
+   return 0;
+
+}
+#endif
 static void get_freesync_config_for_crtc(
struct dm_crtc_state *new_crtc_state,
struct dm_connector_state *new_con_state)
@@ -7178,6 +7249,15 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
goto fail;
}
 
+#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
+   for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, 
new_crtc_state, i) {
+   if (drm_atomic_crtc_needs_modeset(new_crtc_state)) {
+   ret = add_affected_mst_dsc_crtcs(state, crtc);
+   if (ret)
+   goto fail;
+   }
+   }
+#endif
/*
 * Add all primary and overlay planes on the CRTC to the state
 * whenever a plane is enabled to maintain correct z-ordering
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 12/14] drm/amd/display: Write DSC enable to MST DPCD

2019-08-19 Thread David Francis
Rework the dm_helpers_write_dsc_enable callback to
handle the MST case

Depending on how DSC is done, the DP_DSC_ENABLE bit
needs to be set on a different point

For SST, use the link aux

For endpoint DSC over DP-to-DP peer devices,
use the output port

For peer device DSC over DP-to-DP peer devices,
use the upstream (peer) device

For DP-to-HDMI or virtual DP peer devices,
use the output port

For the Synaptix workaround, use the link aux

Cc: Wenjing Liu 
Cc: Nikola Cornij 
Signed-off-by: David Francis 
---
 .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 30 ++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index b32c0790399a..3d5deeed8367 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -38,6 +38,7 @@
 #include "dc.h"
 #include "amdgpu_dm.h"
 #include "amdgpu_dm_irq.h"
+#include "amdgpu_dm_mst_types.h"
 
 #include "dm_helpers.h"
 
@@ -525,8 +526,35 @@ bool dm_helpers_dp_write_dsc_enable(
 )
 {
uint8_t enable_dsc = enable ? 1 : 0;
+   struct amdgpu_dm_connector *aconnector;
+
+   if (!stream)
+   return false;
+
+   if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
+   aconnector = (struct amdgpu_dm_connector 
*)stream->dm_stream_context;
+
+   if (!aconnector || !aconnector->dc_sink)
+   return false;
+
+   if (!aconnector->dc_sink->sink_dsc_caps.is_virtual_dpcd_dsc)
+   return drm_dp_mst_dpcd_write(>port->aux,
+   DP_DSC_ENABLE, _dsc, 
1) >= 0;
+   else if (is_virtual_dpcd(aconnector->port->parent->port_parent))
+   return 
drm_dp_mst_dpcd_write(>port->parent->port_parent->aux,
+   DP_DSC_ENABLE, _dsc, 
1) >= 0;
+   else if (is_virtual_dpcd(aconnector->port))
+   return drm_dp_mst_dpcd_write(>port->aux,
+   DP_DSC_ENABLE, _dsc, 
1) >= 0;
+   else if (synaptix_workaround(aconnector))
+   return dm_helpers_dp_write_dpcd(ctx, stream->link,
+   DP_DSC_ENABLE, _dsc, 1);
+   }
+
+   if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT)
+   return dm_helpers_dp_write_dpcd(ctx, stream->link, 
DP_DSC_ENABLE, _dsc, 1);
 
-   return dm_helpers_dp_write_dpcd(ctx, stream->sink->link, DP_DSC_ENABLE, 
_dsc, 1);
+   return false;
 }
 #endif
 
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 00/14] Display Stream Compression (DSC) for AMD Navi

2019-08-19 Thread David Francis
This patchset enables Display Stream Compression (DSC) on DP 
connectors on Navi ASICs, both SST and DSC.

8k60 and 4k144 support requires ODM combine, an AMD internal
feature that may be a bit buggy right now.

Patches 1 through 5 enable DSC for SST. Most of the work was
already done in the Navi promotion patches; this just hooks
it up to the atomic interface. The first two reverts are of temporary
changes to block off DSC. The third is of a commit that was
accidentally promoted twice. The fourth and last revert fixes a 
potential issue with ODM combine.

Patches 6 and 7 are fixes for bugs that would be exposed by 
MST DSC. One fix is with the MST code and the other in the DSC code.

Patches 8, 9, and 10 are small DRM changes required for DSC MST:
FEC, a new bit in the standard; some export definitions; and
a previously uninitialized variable.

Patches 11 through 14 are the DSC MST policy itself. This includes
the code for detecting and validating DSC capabilities, enabling
DSC over a link, computing the fair DSC configurations for
multiple DSC displays, and adding to atomic state crtcs that might 
need reprogramming due to DSC.

David Francis (14):
  Revert "drm/amd/display: skip dsc config for navi10 bring up"
  Revert "drm/amd/display: navi10 bring up skip dsc encoder config"
  Revert "drm/amd/display: add global master update lock for DCN2"
  Revert "drm/amd/display: Fix underscan not using proper scaling"
  drm/amd/display: Enable SST DSC in DM
  drm/amd/display: Use dc helpers to compute timeslot distribution
  drm/amd/display: Initialize DSC PPS variables to 0
  drm/dp-mst: Parse FEC capability on MST ports
  drm/dp-mst: Export symbols for dpcd read/write
  drm/dp-mst: Fill branch->num_ports
  drm/amd/display: Validate DSC caps on MST endpoints
  drm/amd/display: Write DSC enable to MST DPCD
  drm/amd/display: MST DSC compute fair share
  drm/amd/display: Trigger modesets on MST DSC connectors

 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 116 +++-
 .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  71 +--
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 498 +-
 .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |   5 +
 drivers/gpu/drm/amd/display/dc/core/dc.c  |  12 +-
 .../drm/amd/display/dc/core/dc_link_hwss.c|   3 +
 .../gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c  |   3 +
 .../drm/amd/display/dc/dcn20/dcn20_hwseq.c|   4 -
 .../gpu/drm/amd/display/dc/dcn20/dcn20_optc.c |  72 +--
 .../gpu/drm/amd/display/dc/dcn20/dcn20_optc.h |   3 -
 .../drm/amd/display/dc/dcn20/dcn20_resource.c |   7 +-
 .../drm/amd/display/dc/dcn20/dcn20_resource.h |   1 +
 .../display/dc/dcn20/dcn20_stream_encoder.c   |   8 -
 .../amd/display/dc/inc/hw/timing_generator.h  |   2 -
 drivers/gpu/drm/drm_dp_mst_topology.c |   6 +
 include/drm/drm_dp_mst_helper.h   |   3 +
 16 files changed, 668 insertions(+), 146 deletions(-)

-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 10/14] drm/dp-mst: Fill branch->num_ports

2019-08-19 Thread David Francis
This field on drm_dp_mst_branch was never filled

Initialize it to zero when the list of ports is created.
When a port is added to the list, increment num_ports

Signed-off-by: David Francis 
---
 drivers/gpu/drm/drm_dp_mst_topology.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c 
b/drivers/gpu/drm/drm_dp_mst_topology.c
index 5a072571cb44..31b7213b6036 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -918,6 +918,7 @@ static struct drm_dp_mst_branch 
*drm_dp_add_mst_branch_device(u8 lct, u8 *rad)
INIT_LIST_HEAD(>ports);
kref_init(>topology_kref);
kref_init(>malloc_kref);
+   mstb->num_ports = 0;
return mstb;
 }
 
@@ -1672,6 +1673,7 @@ static void drm_dp_add_port(struct drm_dp_mst_branch 
*mstb,
mutex_lock(>mgr->lock);
drm_dp_mst_topology_get_port(port);
list_add(>next, >ports);
+   mstb->num_ports++;
mutex_unlock(>mgr->lock);
}
 
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 11/14] drm/amd/display: Validate DSC caps on MST endpoints

2019-08-19 Thread David Francis
The first step in MST DSC is checking MST endpoints
to see how DSC can be enabled

Case 1: DP-to-DP peer device
if the branch immediately upstream has
 - PDT = DP_PEER_DEVICE_DP_MST_BRANCHING (2)
 - DPCD rev. >= DP 1.4
 - Exactly one input and one output
 - The output has PDT = DP_PEER_DEVICE_SST_SINK (3)

In this case, DSC could be possible either on the endpoint
or the peer device. Prefer the endpoint, which is possible if
 - The endpoint has DP_DSC_DECOMPRESSION_IS_SUPPORTED bit set
 - The endpoint has DP_FEC_CAPABLE bit set
 - The peer device has DSC_PASSTHROUGH_CAPABILITY bit set (from DP v2.0)

Otherwise, use the peer device

Case 2: DP-to-HDMI peer device
If the output port has
 - PDT = DP_PEER_DEVICE_DP_LEGACY_CONV (4)
 - DPCD rev. >= DP 1.4
 - LDPS = true
 - MCS = false

In this case, DSC can only be attempted on the peer device
(the output port)

Case 3: Virtual DP Sink (Internal Display Panel)
If the output port has
 - DPCD rev. >= DP 1.4
 - port_num >= 8

In this case, DSC can only be attempted on the peer device
(the output port)

Case 4: Synaptix Workaround
If the output has
 - link DPCD rev. >= DP 1.4
 - link branch_dev_id = 0x90CC24 (Synaptix)
 - There is exactly one branch device between the link and output

In this case, DSC can be attempted, but only using the *link*
aux device's caps. This is a quirk.

Test for these cases as modes are enumerated for an MST endpoint.
We cannot do this during link attach because the dc_sink object
will not have been created yet

If no DSC is attempted, zero the DSC caps

Cc: Wenjing Liu 
Cc: Nikola Cornij 
Signed-off-by: David Francis 
---
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 123 +-
 .../display/amdgpu_dm/amdgpu_dm_mst_types.h   |   3 +
 2 files changed, 125 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 16218a202b59..58571844f6d5 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -25,6 +25,7 @@
 
 #include 
 #include 
+#include 
 #include "dm_services.h"
 #include "amdgpu.h"
 #include "amdgpu_dm.h"
@@ -189,6 +190,120 @@ static const struct drm_connector_funcs 
dm_dp_mst_connector_funcs = {
.early_unregister = amdgpu_dm_mst_connector_early_unregister,
 };
 
+bool is_virtual_dpcd(struct drm_dp_mst_port *port)
+{
+   struct drm_dp_mst_port *downstream_port;
+
+   if (!port)
+   return false;
+
+   if (port->port_num >= 8 &&
+   port->dpcd_rev >= DP_DPCD_REV_14) {
+   /* Virtual DP Sink (Internal Display Panel) */
+   return true;
+   } else if (port->pdt == DP_PEER_DEVICE_DP_LEGACY_CONV &&
+   !port->mcs &&
+   port->ldps &&
+   port->dpcd_rev >= DP_DPCD_REV_14) {
+   /* DP-to-HDMI Protocol Converter */
+   return true;
+   } else if (port->pdt == DP_PEER_DEVICE_MST_BRANCHING &&
+   port->mstb &&
+   port->dpcd_rev >= DP_DPCD_REV_14) {
+   /* DP-to-DP */
+   if (port->mstb->num_ports == 2) {
+   list_for_each_entry(downstream_port, 
>mstb->ports, next) {
+   if (!downstream_port->input &&
+   downstream_port->pdt == 
DP_PEER_DEVICE_SST_SINK)
+   return true;
+   }
+   }
+   }
+   return false;
+}
+
+bool synaptix_workaround(struct amdgpu_dm_connector *aconnector)
+{
+   struct drm_dp_mst_port *port = aconnector->port;
+   struct dc_link *link = aconnector->dc_sink->link;
+   u8 down_stream_port_data;
+
+   if (port->mgr->mst_primary == port->parent &&
+   link->dpcd_caps.branch_dev_id == 0x90CC24 &&
+   link->dpcd_caps.dpcd_rev.raw >= DP_DPCD_REV_14) {
+   drm_dp_mst_dpcd_read(>aux, DP_DOWNSTREAMPORT_PRESENT, 
_stream_port_data, 1);
+   if ((down_stream_port_data & 7) != 3)
+   return true;
+   }
+   return false;
+}
+
+#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
+static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector 
*aconnector)
+{
+   u8 upstream_dsc_caps[16] = { 0 };
+   u8 endpoint_dsc_caps[16] = { 0 };
+   u8 endpoint_fec_caps = 0;
+   struct dc_sink *dc_sink = aconnector->dc_sink;
+   struct drm_dp_mst_port *output_port = aconnector->port;
+   struct drm_dp_mst_port *immediate_upstream_port;
+   struct drm_dp_mst_port *fec_port;
+
+   if (aconnector->por

[PATCH 02/14] Revert "drm/amd/display: navi10 bring up skip dsc encoder config"

2019-08-19 Thread David Francis
This reverts commit 5f2fd347eeff7d4ce271920efd47baaa18fe968c.

Re-enable enc2_dp_set_dsc_config. This function caused warnings
due to missing register definitions. With the registers added,
this now works

Signed-off-by: David Francis 
Reviewed-by: Roman Li 
Reviewed-by: Harry Wentland 
---
 .../gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c   | 8 
 1 file changed, 8 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c
index 6d54942ab98b..a4e67286cdad 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c
@@ -277,14 +277,6 @@ static void enc2_dp_set_dsc_config(struct stream_encoder 
*enc,
uint32_t dsc_slice_width)
 {
struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
-   uint32_t dsc_value = 0;
-
-   dsc_value = REG_READ(DP_DSC_CNTL);
-
-   /* dsc disable skip */
-   if ((dsc_value & 0x3) == 0x0)
-   return;
-
 
REG_UPDATE_2(DP_DSC_CNTL,
DP_DSC_MODE, dsc_mode,
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 06/14] drm/amd/display: Use dc helpers to compute timeslot distribution

2019-08-19 Thread David Francis
We were using drm helpers to convert a timing into its
bandwidth, its bandwidth into pbn, and its pbn into timeslots

These helpers
-Did not take DSC timings into account
-Used the link rate and lane count of the link's aux device,
 which are not the same as the link's current cap
-Did not take FEC into account (FEC reduces the PBN per timeslot)

Use the DC helpers (dc_bandwidth_in_kbps_from_timing,
dc_link_bandwidth_kbps) instead

Cc: Jerry Zuo 
Signed-off-by: David Francis 
---
 .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 41 ---
 1 file changed, 8 insertions(+), 33 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index 5f2c315b18ba..b32c0790399a 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -189,8 +189,8 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
int slots = 0;
bool ret;
int clock;
-   int bpp = 0;
int pbn = 0;
+   int pbn_per_timeslot;
 
aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
 
@@ -205,40 +205,15 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
mst_port = aconnector->port;
 
if (enable) {
-   clock = stream->timing.pix_clk_100hz / 10;
-
-   switch (stream->timing.display_color_depth) {
-
-   case COLOR_DEPTH_666:
-   bpp = 6;
-   break;
-   case COLOR_DEPTH_888:
-   bpp = 8;
-   break;
-   case COLOR_DEPTH_101010:
-   bpp = 10;
-   break;
-   case COLOR_DEPTH_121212:
-   bpp = 12;
-   break;
-   case COLOR_DEPTH_141414:
-   bpp = 14;
-   break;
-   case COLOR_DEPTH_161616:
-   bpp = 16;
-   break;
-   default:
-   ASSERT(bpp != 0);
-   break;
-   }
-
-   bpp = bpp * 3;
-
-   /* TODO need to know link rate */
+   clock = dc_bandwidth_in_kbps_from_timing(>timing);
 
-   pbn = drm_dp_calc_pbn_mode(clock, bpp);
+   /* dc_bandwidth_in_kbps_from_timing already takes bpp into 
account */
+   pbn = drm_dp_calc_pbn_mode(clock, 1);
 
-   slots = drm_dp_find_vcpi_slots(mst_mgr, pbn);
+   /* Convert kilobits per second / 64 (for 64 timeslots) to pbn 
(54/64 megabytes per second) */
+   pbn_per_timeslot = dc_link_bandwidth_kbps(
+   stream->link, 
dc_link_get_link_cap(stream->link)) / (8 * 1000 * 54);
+   slots = DIV_ROUND_UP(pbn, pbn_per_timeslot);
ret = drm_dp_mst_allocate_vcpi(mst_mgr, mst_port, pbn, slots);
 
if (!ret)
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 09/14] drm/dp-mst: Export symbols for dpcd read/write

2019-08-19 Thread David Francis
To use these functions in drm driver directories, they must be
exported

Signed-off-by: David Francis 
---
 drivers/gpu/drm/drm_dp_mst_topology.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c 
b/drivers/gpu/drm/drm_dp_mst_topology.c
index 53a0ad16e37b..5a072571cb44 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -1512,6 +1512,7 @@ ssize_t drm_dp_mst_dpcd_read(struct drm_dp_aux *aux,
return drm_dp_send_dpcd_read(port->mgr, port,
 offset, size, buffer);
 }
+EXPORT_SYMBOL(drm_dp_mst_dpcd_read);
 
 /**
  * drm_dp_mst_dpcd_write() - write a series of bytes to the DPCD via sideband
@@ -1535,6 +1536,7 @@ ssize_t drm_dp_mst_dpcd_write(struct drm_dp_aux *aux,
return drm_dp_send_dpcd_write(port->mgr, port,
  offset, size, buffer);
 }
+EXPORT_SYMBOL(drm_dp_mst_dpcd_write);
 
 static void drm_dp_check_mstb_guid(struct drm_dp_mst_branch *mstb, u8 *guid)
 {
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 08/14] drm/dp-mst: Parse FEC capability on MST ports

2019-08-19 Thread David Francis
As of DP1.4, ENUM_PATH_RESOURCES returns a bit indicating
if FEC can be supported up to that point in the MST network.

The bit is the first byte of the ENUM_PATH_RESOURCES ack reply,
bottom-most bit (refer to section 2.11.9.4 of DP standard,
v1.4)

That value is needed for FEC and DSC support

Store it on drm_dp_mst_port

Signed-off-by: David Francis 
---
 drivers/gpu/drm/drm_dp_mst_topology.c | 2 ++
 include/drm/drm_dp_mst_helper.h   | 3 +++
 2 files changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c 
b/drivers/gpu/drm/drm_dp_mst_topology.c
index 398e7314ea8b..53a0ad16e37b 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -552,6 +552,7 @@ static bool 
drm_dp_sideband_parse_enum_path_resources_ack(struct drm_dp_sideband
 {
int idx = 1;
repmsg->u.path_resources.port_number = (raw->msg[idx] >> 4) & 0xf;
+   repmsg->u.path_resources.fec_capable = raw->msg[idx] & 0x1;
idx++;
if (idx > raw->curlen)
goto fail_len;
@@ -2180,6 +2181,7 @@ static int drm_dp_send_enum_path_resources(struct 
drm_dp_mst_topology_mgr *mgr,
DRM_DEBUG_KMS("enum path resources %d: %d %d\n", 
txmsg->reply.u.path_resources.port_number, 
txmsg->reply.u.path_resources.full_payload_bw_number,
   
txmsg->reply.u.path_resources.avail_payload_bw_number);
port->available_pbn = 
txmsg->reply.u.path_resources.avail_payload_bw_number;
+   port->fec_capable = 
txmsg->reply.u.path_resources.fec_capable;
}
}
 
diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h
index 2ba6253ea6d3..e1801781fff5 100644
--- a/include/drm/drm_dp_mst_helper.h
+++ b/include/drm/drm_dp_mst_helper.h
@@ -108,6 +108,8 @@ struct drm_dp_mst_port {
 * audio-capable.
 */
bool has_audio;
+
+   bool fec_capable;
 };
 
 /**
@@ -312,6 +314,7 @@ struct drm_dp_port_number_req {
 
 struct drm_dp_enum_path_resources_ack_reply {
u8 port_number;
+   bool fec_capable;
u16 full_payload_bw_number;
u16 avail_payload_bw_number;
 };
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 05/14] drm/amd/display: Enable SST DSC in DM

2019-08-19 Thread David Francis
In create_stream_for_sink, check for SST DP connectors

Parse DSC caps to DC format, then, if DSC is supported,
compute the config

DSC hardware will be programmed by dc_commit_state

Cc: Mikita Lipski 
Signed-off-by: David Francis 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 32 ---
 .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  4 ++-
 2 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 911fe78b47c1..84249057e181 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3576,6 +3576,10 @@ create_stream_for_sink(struct amdgpu_dm_connector 
*aconnector,
bool scale = dm_state ? (dm_state->scaling != RMX_OFF) : false;
int mode_refresh;
int preferred_refresh = 0;
+#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
+   struct dsc_dec_dpcd_caps dsc_caps;
+   uint32_t link_bandwidth_kbps;
+#endif
 
struct dc_sink *sink = NULL;
if (aconnector == NULL) {
@@ -3648,17 +3652,23 @@ create_stream_for_sink(struct amdgpu_dm_connector 
*aconnector,
, >base, con_state, old_stream);
 
 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
-   /* stream->timing.flags.DSC = 0; */
-/*  */
-   /* if (aconnector->dc_link && */
-   /*  aconnector->dc_link->connector_signal == 
SIGNAL_TYPE_DISPLAY_PORT #<{(|&& */
-   /*  
aconnector->dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.is_dsc_supported|)}>#) */
-   /*  if (dc_dsc_compute_config(aconnector->dc_link->ctx->dc, */
-   /*  >dc_link->dpcd_caps.dsc_caps, */
-   /*  dc_link_bandwidth_kbps(aconnector->dc_link, 
dc_link_get_link_cap(aconnector->dc_link)), */
-   /*  >timing, */
-   /*  >timing.dsc_cfg)) */
-   /*  stream->timing.flags.DSC = 1; */
+   stream->timing.flags.DSC = 0;
+
+   if (aconnector->dc_link && sink->sink_signal == 
SIGNAL_TYPE_DISPLAY_PORT) {
+   
dc_dsc_parse_dsc_dpcd(aconnector->dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.raw,
+ 
aconnector->dc_link->dpcd_caps.dsc_caps.dsc_ext_caps.raw,
+ _caps);
+   link_bandwidth_kbps = 
dc_link_bandwidth_kbps(aconnector->dc_link,
+
dc_link_get_link_cap(aconnector->dc_link));
+
+   if (dsc_caps.is_dsc_supported)
+   if (dc_dsc_compute_config(aconnector->dc_link->ctx->dc,
+ _caps,
+ link_bandwidth_kbps,
+ >timing,
+ >timing.dsc_cfg))
+   stream->timing.flags.DSC = 1;
+   }
 #endif
 
update_stream_scaling_settings(, dm_state, stream);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index 7cf0573ab25f..5f2c315b18ba 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -549,7 +549,9 @@ bool dm_helpers_dp_write_dsc_enable(
bool enable
 )
 {
-   return false;
+   uint8_t enable_dsc = enable ? 1 : 0;
+
+   return dm_helpers_dp_write_dpcd(ctx, stream->sink->link, DP_DSC_ENABLE, 
_dsc, 1);
 }
 #endif
 
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 04/14] Revert "drm/amd/display: Fix underscan not using proper scaling"

2019-08-19 Thread David Francis
This reverts commit 80e80ec817f161560b4159608fb41bd289abede3.

This commit fixed an issue with underscan commits not updating all
needed timing values, but through various refactors it is no longer
necessary. It causes corruption on odm combine by
overwriting the halved h_active in the stream timing

Signed-off-by: David Francis 
Reviewed-by: Roman Li 
Reviewed-by: Harry Wentland 
---
 drivers/gpu/drm/amd/display/dc/core/dc.c | 12 +---
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c 
b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 77ac7f707ec5..1189e320062b 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -2127,7 +2127,7 @@ void dc_commit_updates_for_stream(struct dc *dc,
enum surface_update_type update_type;
struct dc_state *context;
struct dc_context *dc_ctx = dc->ctx;
-   int i, j;
+   int i;
 
stream_status = dc_stream_get_status(stream);
context = dc->current_state;
@@ -2165,16 +2165,6 @@ void dc_commit_updates_for_stream(struct dc *dc,
 
copy_surface_update_to_plane(surface, _updates[i]);
 
-   if (update_type >= UPDATE_TYPE_MED) {
-   for (j = 0; j < dc->res_pool->pipe_count; j++) {
-   struct pipe_ctx *pipe_ctx = 
>res_ctx.pipe_ctx[j];
-
-   if (pipe_ctx->plane_state != surface)
-   continue;
-
-   resource_build_scaling_params(pipe_ctx);
-   }
-   }
}
 
copy_stream_update_to_stream(dc, context, stream, stream_update);
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 07/14] drm/amd/display: Initialize DSC PPS variables to 0

2019-08-19 Thread David Francis
For DSC MST, sometimes monitors would break out
in full-screen static. The issue traced back to the
PPS generation code, where these variables were being used
uninitialized and were picking up garbage.

memset to 0 to avoid this

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 3 +++
 drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c   | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c 
b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
index 35c5467e60e8..619ac48edd05 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
@@ -491,6 +491,9 @@ bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool 
enable)
struct dsc_config dsc_cfg;
uint8_t dsc_packed_pps[128];
 
+   memset(_cfg, 0, sizeof(dsc_cfg));
+   memset(dsc_packed_pps, 0, 128);
+
/* Enable DSC hw block */
dsc_cfg.pic_width = stream->timing.h_addressable + 
stream->timing.h_border_left + stream->timing.h_border_right;
dsc_cfg.pic_height = stream->timing.v_addressable + 
stream->timing.v_border_top + stream->timing.v_border_bottom;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c
index 379c9e4ac63b..16debe6d89f2 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c
@@ -207,6 +207,9 @@ static bool dsc2_get_packed_pps(struct 
display_stream_compressor *dsc, const str
struct dsc_reg_values dsc_reg_vals;
struct dsc_optc_config dsc_optc_cfg;
 
+   memset(_reg_vals, 0, sizeof(dsc_reg_vals));
+   memset(_optc_cfg, 0, sizeof(dsc_optc_cfg));
+
DC_LOG_DSC("Getting packed DSC PPS for DSC Config:");
dsc_config_log(dsc, dsc_cfg);
DC_LOG_DSC("DSC Picture Parameter Set (PPS):");
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 03/14] Revert "drm/amd/display: add global master update lock for DCN2"

2019-08-19 Thread David Francis
This reverts commit 55a6f5bbcf00a49565946c0a9b8c716313dc6c05.

This commit was accidentally promoted twice

Signed-off-by: David Francis 
Reviewed-by: Roman Li 
Reviewed-by: Harry Wentland 
---
 .../drm/amd/display/dc/dcn20/dcn20_hwseq.c|  4 --
 .../gpu/drm/amd/display/dc/dcn20/dcn20_optc.c | 63 +--
 .../gpu/drm/amd/display/dc/dcn20/dcn20_optc.h |  3 -
 .../amd/display/dc/inc/hw/timing_generator.h  |  2 -
 4 files changed, 1 insertion(+), 71 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
index fa8a73f6c8e3..e146d1d8d45e 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
@@ -575,10 +575,6 @@ enum dc_status dcn20_enable_stream_timing(
pipe_ctx->stream->signal,
true);
 
-   if (pipe_ctx->stream_res.tg->funcs->setup_global_lock)
-   pipe_ctx->stream_res.tg->funcs->setup_global_lock(
-   pipe_ctx->stream_res.tg);
-
if (odm_pipe)
odm_pipe->stream_res.opp->funcs->opp_pipe_clock_control(
odm_pipe->stream_res.opp,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
index 99070e93020b..2137e2be2140 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
@@ -333,65 +333,6 @@ void optc2_triplebuffer_unlock(struct timing_generator 
*optc)
 
 }
 
-
-void optc2_setup_global_lock(struct timing_generator *optc)
-{
-   struct optc *optc1 = DCN10TG_FROM_TG(optc);
-   uint32_t v_blank_start = 0;
-   uint32_t h_blank_start = 0, h_total = 0;
-
-   REG_SET(OTG_GLOBAL_CONTROL1, 0, MASTER_UPDATE_LOCK_DB_EN, 1);
-
-   REG_SET(OTG_GLOBAL_CONTROL2, 0, DIG_UPDATE_LOCATION, 20);
-
-   REG_GET(OTG_V_BLANK_START_END, OTG_V_BLANK_START, _blank_start);
-
-   REG_GET(OTG_H_BLANK_START_END, OTG_H_BLANK_START, _blank_start);
-
-   REG_GET(OTG_H_TOTAL, OTG_H_TOTAL, _total);
-   REG_UPDATE_2(OTG_GLOBAL_CONTROL1,
-   MASTER_UPDATE_LOCK_DB_X,
-   h_blank_start - 200 - 1,
-   MASTER_UPDATE_LOCK_DB_Y,
-   v_blank_start - 1);
-}
-
-void optc2_lock_global(struct timing_generator *optc)
-{
-   struct optc *optc1 = DCN10TG_FROM_TG(optc);
-
-   REG_UPDATE(OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, 1);
-
-   REG_SET(OTG_GLOBAL_CONTROL0, 0,
-   OTG_MASTER_UPDATE_LOCK_SEL, optc->inst);
-   REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
-   OTG_MASTER_UPDATE_LOCK, 1);
-
-   /* Should be fast, status does not update on maximus */
-   if (optc->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS)
-   REG_WAIT(OTG_MASTER_UPDATE_LOCK,
-   UPDATE_LOCK_STATUS, 1,
-   1, 10);
-}
-
-void optc2_lock(struct timing_generator *optc)
-{
-   struct optc *optc1 = DCN10TG_FROM_TG(optc);
-
-   REG_UPDATE(OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, 0);
-
-   REG_SET(OTG_GLOBAL_CONTROL0, 0,
-   OTG_MASTER_UPDATE_LOCK_SEL, optc->inst);
-   REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
-   OTG_MASTER_UPDATE_LOCK, 1);
-
-   /* Should be fast, status does not update on maximus */
-   if (optc->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS)
-   REG_WAIT(OTG_MASTER_UPDATE_LOCK,
-   UPDATE_LOCK_STATUS, 1,
-   1, 10);
-}
-
 void optc2_lock_doublebuffer_enable(struct timing_generator *optc)
 {
struct optc *optc1 = DCN10TG_FROM_TG(optc);
@@ -486,10 +427,8 @@ static struct timing_generator_funcs dcn20_tg_funcs = {
.triplebuffer_lock = optc2_triplebuffer_lock,
.triplebuffer_unlock = optc2_triplebuffer_unlock,
.disable_reset_trigger = optc1_disable_reset_trigger,
-   .lock = optc2_lock,
+   .lock = optc1_lock,
.unlock = optc1_unlock,
-   .lock_global = optc2_lock_global,
-   .setup_global_lock = optc2_setup_global_lock,
.lock_doublebuffer_enable = optc2_lock_doublebuffer_enable,
.lock_doublebuffer_disable = optc2_lock_doublebuffer_disable,
.enable_optc_clock = optc1_enable_optc_clock,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h
index 47cb4de1564c..32a58431fd09 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h
@@ -106,9 +106,6 @@ void optc2_get_optc_source(struct timing_generator *optc,
 
 void optc2_triplebuffer_lock(struct timing

[PATCH 01/14] Revert "drm/amd/display: skip dsc config for navi10 bring up"

2019-08-19 Thread David Francis
This reverts commit 55ad81f3510ec1a1c19e6a4d8a6319812d07d256.

optc dsc config was causing warnings due to missing register
definitions. With the registers restored, the function can
be re-enabled

The reverted commit also disabled sanity checks and dsc
power gating. The sanity check warnings are not associated
with dsc, and power gating on dsc still has an issue on
non-dsc monitors where the dsc hardware block is never init
and so cannot respond to power gating requests. Therefore,
those are left as is

Signed-off-by: David Francis 
Reviewed-by: Roman Li 
Reviewed-by: Harry Wentland 
---
 drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c | 9 -
 1 file changed, 9 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
index aedf9de1c947..99070e93020b 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
@@ -191,15 +191,6 @@ void optc2_set_dsc_config(struct timing_generator *optc,
uint32_t dsc_slice_width)
 {
struct optc *optc1 = DCN10TG_FROM_TG(optc);
-   uint32_t data_format = 0;
-   /* skip if dsc mode is not changed */
-   data_format = dm_read_reg(CTX, REG(OPTC_DATA_FORMAT_CONTROL));
-
-   data_format = data_format & 0x30; /* bit5:4 */
-   data_format = data_format >> 4;
-
-   if (data_format == dsc_mode)
-   return;
 
REG_UPDATE(OPTC_DATA_FORMAT_CONTROL,
OPTC_DSC_MODE, dsc_mode);
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH] drm/amd/display: Remove drm_dsc_dc.c

2019-08-07 Thread David Francis
This file was accidentally added to the driver during
Navi promotion

Nothing includes it. No makefile attempts to compile it, and
it would fail compilation if they tried

Remove it

Signed-off-by: David Francis 
---
 .../gpu/drm/amd/display/dc/dsc/drm_dsc_dc.c   | 453 --
 1 file changed, 453 deletions(-)
 delete mode 100644 drivers/gpu/drm/amd/display/dc/dsc/drm_dsc_dc.c

diff --git a/drivers/gpu/drm/amd/display/dc/dsc/drm_dsc_dc.c 
b/drivers/gpu/drm/amd/display/dc/dsc/drm_dsc_dc.c
deleted file mode 100644
index fd1fb1653479..
--- a/drivers/gpu/drm/amd/display/dc/dsc/drm_dsc_dc.c
+++ /dev/null
@@ -1,453 +0,0 @@
-// SPDX-License-Identifier: MIT
-/*
- * Copyright © 2018 Intel Corp
- *
- * Author:
- * Manasi Navare 
- */
-
-/* DC versions of linux includes */
-#include 
-
-#define EXPORT_SYMBOL(symbol)  /* nothing */
-#define BUILD_BUG_ON(cond) /* nothing */
-#define DIV_ROUND_UP(a, b) (((b) + (a) - 1) / (b))
-#define ERANGE -1
-#define DRM_DEBUG_KMS(msg) /* nothing */
-#define cpu_to_be16(__x) little_to_big(__x)
-#define MAX(x, y)  ((x) > (y) ? (x) : (y))
-
-static unsigned short little_to_big(int data)
-{
-   /* Swap lower and upper byte. DMCU uses big endian format. */
-   return (0xff & (data >> 8)) + ((data & 0xff) << 8);
-}
-
-/*
- * Everything below this comment was copied directly from drm_dsc.c.
- * Only the functions needed in DC are included.
- * Please keep this file synced with upstream.
- */
-
-/**
- * DOC: dsc helpers
- *
- * These functions contain some common logic and helpers to deal with VESA
- * Display Stream Compression standard required for DSC on Display Port/eDP or
- * MIPI display interfaces.
- */
-
-/**
- * drm_dsc_pps_payload_pack() - Populates the DSC PPS
- *
- * @pps_payload:
- * Bitwise struct for DSC Picture Parameter Set. This is defined
- * by  drm_dsc_picture_parameter_set
- * @dsc_cfg:
- * DSC Configuration data filled by driver as defined by
- *  drm_dsc_config
- *
- * DSC source device sends a picture parameter set (PPS) containing the
- * information required by the sink to decode the compressed frame. Driver
- * populates the DSC PPS struct using the DSC configuration parameters in
- * the order expected by the DSC Display Sink device. For the DSC, the sink
- * device expects the PPS payload in big endian format for fields
- * that span more than 1 byte.
- */
-void drm_dsc_pps_payload_pack(struct drm_dsc_picture_parameter_set 
*pps_payload,
-   const struct drm_dsc_config *dsc_cfg)
-{
-   int i;
-
-   /* Protect against someone accidently changing struct size */
-   BUILD_BUG_ON(sizeof(*pps_payload) !=
-DP_SDP_PPS_HEADER_PAYLOAD_BYTES_MINUS_1 + 1);
-
-   memset(pps_payload, 0, sizeof(*pps_payload));
-
-   /* PPS 0 */
-   pps_payload->dsc_version =
-   dsc_cfg->dsc_version_minor |
-   dsc_cfg->dsc_version_major << DSC_PPS_VERSION_MAJOR_SHIFT;
-
-   /* PPS 1, 2 is 0 */
-
-   /* PPS 3 */
-   pps_payload->pps_3 =
-   dsc_cfg->line_buf_depth |
-   dsc_cfg->bits_per_component << DSC_PPS_BPC_SHIFT;
-
-   /* PPS 4 */
-   pps_payload->pps_4 =
-   ((dsc_cfg->bits_per_pixel & DSC_PPS_BPP_HIGH_MASK) >>
-DSC_PPS_MSB_SHIFT) |
-   dsc_cfg->vbr_enable << DSC_PPS_VBR_EN_SHIFT |
-   dsc_cfg->simple_422 << DSC_PPS_SIMPLE422_SHIFT |
-   dsc_cfg->convert_rgb << DSC_PPS_CONVERT_RGB_SHIFT |
-   dsc_cfg->block_pred_enable << DSC_PPS_BLOCK_PRED_EN_SHIFT;
-
-   /* PPS 5 */
-   pps_payload->bits_per_pixel_low =
-   (dsc_cfg->bits_per_pixel & DSC_PPS_LSB_MASK);
-
-   /*
-* The DSC panel expects the PPS packet to have big endian format
-* for data spanning 2 bytes. Use a macro cpu_to_be16() to convert
-* to big endian format. If format is little endian, it will swap
-* bytes to convert to Big endian else keep it unchanged.
-*/
-
-   /* PPS 6, 7 */
-   pps_payload->pic_height = cpu_to_be16(dsc_cfg->pic_height);
-
-   /* PPS 8, 9 */
-   pps_payload->pic_width = cpu_to_be16(dsc_cfg->pic_width);
-
-   /* PPS 10, 11 */
-   pps_payload->slice_height = cpu_to_be16(dsc_cfg->slice_height);
-
-   /* PPS 12, 13 */
-   pps_payload->slice_width = cpu_to_be16(dsc_cfg->slice_width);
-
-   /* PPS 14, 15 */
-   pps_payload->chunk_size = cpu_to_be16(dsc_cfg->slice_chunk_size);
-
-   /* PPS 16 */
-   pps_payload->initial_xmit_delay_high =
-   ((dsc_cfg->initial_xmit_delay &
- DSC_PPS_INIT_XMIT_DELAY_HIGH_MASK) >>
-DSC_PPS_MSB_SHIFT);
-
-   /* PPS 17 */
-   pps_payload->initial_xmit_delay_low =
-

[PATCH v2 3/3] drm/dsc: Split DSC PPS and SDP header initialisations

2019-02-21 Thread David Francis
The DP 1.4 spec defines the SDP header and SDP contents for
a Picture Parameter Set (PPS) that must be sent in advance
of DSC transmission to define the encoding characteristics.

This was done in one struct, drm_dsc_pps_infoframe, which
conatined the SDP header and PPS.  Because the PPS is
a property of DSC over any connector, not just DP, and because
drm drivers may have their own SDP structs they wish to use,
make the functions that initialise SDP and PPS headers take
the components they operate on, not drm_dsc_pps_infoframe,

Signed-off-by: David Francis 
---
 drivers/gpu/drm/drm_dsc.c | 117 +++---
 drivers/gpu/drm/i915/intel_vdsc.c |   4 +-
 include/drm/drm_dsc.h |   4 +-
 3 files changed, 62 insertions(+), 63 deletions(-)

diff --git a/drivers/gpu/drm/drm_dsc.c b/drivers/gpu/drm/drm_dsc.c
index d77570bf6ac4..77f4e5ae4197 100644
--- a/drivers/gpu/drm/drm_dsc.c
+++ b/drivers/gpu/drm/drm_dsc.c
@@ -32,66 +32,65 @@
 /**
  * drm_dsc_dp_pps_header_init() - Initializes the PPS Header
  * for DisplayPort as per the DP 1.4 spec.
- * @pps_sdp: Secondary data packet for DSC Picture Parameter Set
- *   as defined in  drm_dsc_pps_infoframe
+ * @pps_header: Secondary data packet header for DSC Picture
+ *  Parameter Set as defined in  dp_sdp_header
  *
  * DP 1.4 spec defines the secondary data packet for sending the
  * picture parameter infoframes from the source to the sink.
- * This function populates the pps header defined in
- *  drm_dsc_pps_infoframe as per the header bytes defined
- * in  dp_sdp_header.
+ * This function populates the SDP header defined in
+ *  dp_sdp_header.
  */
-void drm_dsc_dp_pps_header_init(struct drm_dsc_pps_infoframe *pps_sdp)
+void drm_dsc_dp_pps_header_init(struct dp_sdp_header *pps_header)
 {
-   memset(_sdp->pps_header, 0, sizeof(pps_sdp->pps_header));
+   memset(pps_header, 0, sizeof(*pps_header));
 
-   pps_sdp->pps_header.HB1 = DP_SDP_PPS;
-   pps_sdp->pps_header.HB2 = DP_SDP_PPS_HEADER_PAYLOAD_BYTES_MINUS_1;
+   pps_header->HB1 = DP_SDP_PPS;
+   pps_header->HB2 = DP_SDP_PPS_HEADER_PAYLOAD_BYTES_MINUS_1;
 }
 EXPORT_SYMBOL(drm_dsc_dp_pps_header_init);
 
 /**
- * drm_dsc_pps_infoframe_pack() - Populates the DSC PPS infoframe
+ * drm_dsc_pps_payload_pack() - Populates the DSC PPS
  *
- * @pps_sdp:
- * Secondary data packet for DSC Picture Parameter Set. This is defined
- * by  drm_dsc_pps_infoframe
+ * @pps_payload:
+ * Bitwise struct for DSC Picture Parameter Set. This is defined
+ * by  drm_dsc_picture_parameter_set
  * @dsc_cfg:
  * DSC Configuration data filled by driver as defined by
  *  drm_dsc_config
  *
- * DSC source device sends a secondary data packet filled with all the
- * picture parameter set (PPS) information required by the sink to decode
- * the compressed frame. Driver populates the dsC PPS infoframe using the DSC
- * configuration parameters in the order expected by the DSC Display Sink
- * device. For the DSC, the sink device expects the PPS payload in the big
- * endian format for the fields that span more than 1 byte.
+ * DSC source device sends a picture parameter set (PPS) containing the
+ * information required by the sink to decode the compressed frame. Driver
+ * populates the DSC PPS struct using the DSC configuration parameters in
+ * the order expected by the DSC Display Sink device. For the DSC, the sink
+ * device expects the PPS payload in big endian format for fields
+ * that span more than 1 byte.
  */
-void drm_dsc_pps_infoframe_pack(struct drm_dsc_pps_infoframe *pps_sdp,
+void drm_dsc_pps_payload_pack(struct drm_dsc_picture_parameter_set 
*pps_payload,
const struct drm_dsc_config *dsc_cfg)
 {
int i;
 
/* Protect against someone accidently changing struct size */
-   BUILD_BUG_ON(sizeof(pps_sdp->pps_payload) !=
+   BUILD_BUG_ON(sizeof(*pps_payload) !=
 DP_SDP_PPS_HEADER_PAYLOAD_BYTES_MINUS_1 + 1);
 
-   memset(_sdp->pps_payload, 0, sizeof(pps_sdp->pps_payload));
+   memset(pps_payload, 0, sizeof(*pps_payload));
 
/* PPS 0 */
-   pps_sdp->pps_payload.dsc_version =
+   pps_payload->dsc_version =
dsc_cfg->dsc_version_minor |
dsc_cfg->dsc_version_major << DSC_PPS_VERSION_MAJOR_SHIFT;
 
/* PPS 1, 2 is 0 */
 
/* PPS 3 */
-   pps_sdp->pps_payload.pps_3 =
+   pps_payload->pps_3 =
dsc_cfg->line_buf_depth |
dsc_cfg->bits_per_component << DSC_PPS_BPC_SHIFT;
 
/* PPS 4 */
-   pps_sdp->pps_payload.pps_4 =
+   pps_payload->pps_4 =
((dsc_cfg->bits_per_pixel & DSC_PPS_BPP_HIGH_MASK) >>
 DSC_PPS_MSB_SHIFT) |
dsc_cfg->vbr_enable << DSC_PPS_VBR_EN_SHIFT |
@@ -100,7 +99,7 @@ void drm_dsc_pps_infoframe_pack(struct drm_dsc_pps_inf

[PATCH v2 0/3] Make DRM DSC helpers more generally usable

2019-02-21 Thread David Francis
drm_dsc could use some work so that drm drivers other than
i915 can make use of it their own DSC implementations

Move rc compute, a function that forms part of the DSC spec,
into drm. Update it to DSC 1.2. Also split the PPS packing and
SDP header init functions, to allow for drivers with
their own SDP struct headers

Re-sending due to Mail Delivery System errors

v2:
Rebase onto drm-next
Refactor drm_dsc_dp_pps_header_init
Clean up documentation on new drm function

David Francis (3):
  drm/i915: Move dsc rate params compute into drm
  drm/dsc: Add native 420 and 422 support to compute_rc_params
  drm/dsc: Split DSC PPS and SDP header initialisations

 drivers/gpu/drm/drm_dsc.c | 269 +++---
 drivers/gpu/drm/i915/intel_vdsc.c | 133 +--
 include/drm/drm_dsc.h |   9 +-
 3 files changed, 219 insertions(+), 192 deletions(-)

-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH v2 1/3] drm/i915: Move dsc rate params compute into drm

2019-02-21 Thread David Francis
The function intel_compute_rc_parameters is part of the dsc spec
and is not driver-specific. Other drm drivers might like to use
it.  The function is not changed; just moved and renamed.

Reviewed-by: Harry Wentland 
Signed-off-by: David Francis 
---
 drivers/gpu/drm/drm_dsc.c | 135 ++
 drivers/gpu/drm/i915/intel_vdsc.c | 125 +--
 include/drm/drm_dsc.h |   1 +
 3 files changed, 137 insertions(+), 124 deletions(-)

diff --git a/drivers/gpu/drm/drm_dsc.c b/drivers/gpu/drm/drm_dsc.c
index bce99f95c1a3..b7f1903508a4 100644
--- a/drivers/gpu/drm/drm_dsc.c
+++ b/drivers/gpu/drm/drm_dsc.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -244,3 +245,137 @@ void drm_dsc_pps_infoframe_pack(struct 
drm_dsc_pps_infoframe *pps_sdp,
/* PPS 94 - 127 are O */
 }
 EXPORT_SYMBOL(drm_dsc_pps_infoframe_pack);
+
+/**
+ * drm_dsc_compute_rc_parameters() - Write rate control
+ * parameters to the dsc configuration defined in
+ *  drm_dsc_config in accordance with the DSC 1.1
+ * specification. Some configuration fields must be present
+ * beforehand.
+ *
+ * @vdsc_cfg:
+ * DSC Configuration data partially filled by driver
+ */
+int drm_dsc_compute_rc_parameters(struct drm_dsc_config *vdsc_cfg)
+{
+   unsigned long groups_per_line = 0;
+   unsigned long groups_total = 0;
+   unsigned long num_extra_mux_bits = 0;
+   unsigned long slice_bits = 0;
+   unsigned long hrd_delay = 0;
+   unsigned long final_scale = 0;
+   unsigned long rbs_min = 0;
+
+   /* Number of groups used to code each line of a slice */
+   groups_per_line = DIV_ROUND_UP(vdsc_cfg->slice_width,
+  DSC_RC_PIXELS_PER_GROUP);
+
+   /* chunksize in Bytes */
+   vdsc_cfg->slice_chunk_size = DIV_ROUND_UP(vdsc_cfg->slice_width *
+ vdsc_cfg->bits_per_pixel,
+ (8 * 16));
+
+   if (vdsc_cfg->convert_rgb)
+   num_extra_mux_bits = 3 * (vdsc_cfg->mux_word_size +
+ (4 * vdsc_cfg->bits_per_component + 4)
+ - 2);
+   else
+   num_extra_mux_bits = 3 * vdsc_cfg->mux_word_size +
+   (4 * vdsc_cfg->bits_per_component + 4) +
+   2 * (4 * vdsc_cfg->bits_per_component) - 2;
+   /* Number of bits in one Slice */
+   slice_bits = 8 * vdsc_cfg->slice_chunk_size * vdsc_cfg->slice_height;
+
+   while ((num_extra_mux_bits > 0) &&
+  ((slice_bits - num_extra_mux_bits) % vdsc_cfg->mux_word_size))
+   num_extra_mux_bits--;
+
+   if (groups_per_line < vdsc_cfg->initial_scale_value - 8)
+   vdsc_cfg->initial_scale_value = groups_per_line + 8;
+
+   /* scale_decrement_interval calculation according to DSC spec 1.11 */
+   if (vdsc_cfg->initial_scale_value > 8)
+   vdsc_cfg->scale_decrement_interval = groups_per_line /
+   (vdsc_cfg->initial_scale_value - 8);
+   else
+   vdsc_cfg->scale_decrement_interval = 
DSC_SCALE_DECREMENT_INTERVAL_MAX;
+
+   vdsc_cfg->final_offset = vdsc_cfg->rc_model_size -
+   (vdsc_cfg->initial_xmit_delay *
+vdsc_cfg->bits_per_pixel + 8) / 16 + num_extra_mux_bits;
+
+   if (vdsc_cfg->final_offset >= vdsc_cfg->rc_model_size) {
+   DRM_DEBUG_KMS("FinalOfs < RcModelSze for this 
InitialXmitDelay\n");
+   return -ERANGE;
+   }
+
+   final_scale = (vdsc_cfg->rc_model_size * 8) /
+   (vdsc_cfg->rc_model_size - vdsc_cfg->final_offset);
+   if (vdsc_cfg->slice_height > 1)
+   /*
+* NflBpgOffset is 16 bit value with 11 fractional bits
+* hence we multiply by 2^11 for preserving the
+* fractional part
+*/
+   vdsc_cfg->nfl_bpg_offset = 
DIV_ROUND_UP((vdsc_cfg->first_line_bpg_offset << 11),
+   (vdsc_cfg->slice_height 
- 1));
+   else
+   vdsc_cfg->nfl_bpg_offset = 0;
+
+   /* 2^16 - 1 */
+   if (vdsc_cfg->nfl_bpg_offset > 65535) {
+   DRM_DEBUG_KMS("NflBpgOffset is too large for this slice 
height\n");
+   return -ERANGE;
+   }
+
+   /* Number of groups used to code the entire slice */
+   groups_total = groups_per_line * vdsc_cfg->slice_height;
+
+   /* slice_bpg_offset is 16 bit value with 11 fractional bits */
+   vdsc_cfg->slice_bpg_offset = DIV_ROUND_UP(((vdsc_cfg->rc_model_size -
+   vdsc_cfg->initial_offset +
+

[PATCH v2 2/3] drm/dsc: Add native 420 and 422 support to compute_rc_params

2019-02-21 Thread David Francis
Native 420 and 422 transfer modes are new in DSC1.2

In these modes, each two pixels of a slice are treated as one
pixel, so the slice width is half as large (round down) for
the purposes of calucating the groups per line and chunk size
in bytes

In native 422 mode, each pixel has four components, so the
mux component of a group is larger by one additional mux word
and one additional component

Now that there is native 422 support, the configuration option
previously called enable422 is renamed to simple_422 to avoid
confusion

Acked-by: Jani Nikula 
Reviewed-by: Manasi Navare 
Reviewed-by: Harry Wentland 
Signed-off-by: David Francis 
---
 drivers/gpu/drm/drm_dsc.c | 33 ++-
 drivers/gpu/drm/i915/intel_vdsc.c |  4 ++--
 include/drm/drm_dsc.h |  4 ++--
 3 files changed, 28 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/drm_dsc.c b/drivers/gpu/drm/drm_dsc.c
index b7f1903508a4..d77570bf6ac4 100644
--- a/drivers/gpu/drm/drm_dsc.c
+++ b/drivers/gpu/drm/drm_dsc.c
@@ -95,7 +95,7 @@ void drm_dsc_pps_infoframe_pack(struct drm_dsc_pps_infoframe 
*pps_sdp,
((dsc_cfg->bits_per_pixel & DSC_PPS_BPP_HIGH_MASK) >>
 DSC_PPS_MSB_SHIFT) |
dsc_cfg->vbr_enable << DSC_PPS_VBR_EN_SHIFT |
-   dsc_cfg->enable422 << DSC_PPS_SIMPLE422_SHIFT |
+   dsc_cfg->simple_422 << DSC_PPS_SIMPLE422_SHIFT |
dsc_cfg->convert_rgb << DSC_PPS_CONVERT_RGB_SHIFT |
dsc_cfg->block_pred_enable << DSC_PPS_BLOCK_PRED_EN_SHIFT;
 
@@ -249,7 +249,7 @@ EXPORT_SYMBOL(drm_dsc_pps_infoframe_pack);
 /**
  * drm_dsc_compute_rc_parameters() - Write rate control
  * parameters to the dsc configuration defined in
- *  drm_dsc_config in accordance with the DSC 1.1
+ *  drm_dsc_config in accordance with the DSC 1.2
  * specification. Some configuration fields must be present
  * beforehand.
  *
@@ -266,19 +266,34 @@ int drm_dsc_compute_rc_parameters(struct drm_dsc_config 
*vdsc_cfg)
unsigned long final_scale = 0;
unsigned long rbs_min = 0;
 
-   /* Number of groups used to code each line of a slice */
-   groups_per_line = DIV_ROUND_UP(vdsc_cfg->slice_width,
-  DSC_RC_PIXELS_PER_GROUP);
+   if (vdsc_cfg->native_420 || vdsc_cfg->native_422) {
+   /* Number of groups used to code each line of a slice */
+   groups_per_line = DIV_ROUND_UP(vdsc_cfg->slice_width / 2,
+  DSC_RC_PIXELS_PER_GROUP);
 
-   /* chunksize in Bytes */
-   vdsc_cfg->slice_chunk_size = DIV_ROUND_UP(vdsc_cfg->slice_width *
- vdsc_cfg->bits_per_pixel,
- (8 * 16));
+   /* chunksize in Bytes */
+   vdsc_cfg->slice_chunk_size = DIV_ROUND_UP(vdsc_cfg->slice_width 
/ 2 *
+ 
vdsc_cfg->bits_per_pixel,
+ (8 * 16));
+   } else {
+   /* Number of groups used to code each line of a slice */
+   groups_per_line = DIV_ROUND_UP(vdsc_cfg->slice_width,
+  DSC_RC_PIXELS_PER_GROUP);
+
+   /* chunksize in Bytes */
+   vdsc_cfg->slice_chunk_size = DIV_ROUND_UP(vdsc_cfg->slice_width 
*
+ 
vdsc_cfg->bits_per_pixel,
+ (8 * 16));
+   }
 
if (vdsc_cfg->convert_rgb)
num_extra_mux_bits = 3 * (vdsc_cfg->mux_word_size +
  (4 * vdsc_cfg->bits_per_component + 4)
  - 2);
+   else if (vdsc_cfg->native_422)
+   num_extra_mux_bits = 4 * vdsc_cfg->mux_word_size +
+   (4 * vdsc_cfg->bits_per_component + 4) +
+   3 * (4 * vdsc_cfg->bits_per_component) - 2;
else
num_extra_mux_bits = 3 * vdsc_cfg->mux_word_size +
(4 * vdsc_cfg->bits_per_component + 4) +
diff --git a/drivers/gpu/drm/i915/intel_vdsc.c 
b/drivers/gpu/drm/i915/intel_vdsc.c
index 2d059ebc9bd0..8c8d96157333 100644
--- a/drivers/gpu/drm/i915/intel_vdsc.c
+++ b/drivers/gpu/drm/i915/intel_vdsc.c
@@ -368,7 +368,7 @@ int intel_dp_compute_dsc_params(struct intel_dp *intel_dp,
DSC_1_1_MAX_LINEBUF_DEPTH_BITS : line_buf_depth;
 
/* Gen 11 does not support YCbCr */
-   vdsc_cfg->enable422 = false;
+   vdsc_cfg->simple_422 = false;
/* Gen 11 does not support VBR */
vdsc_cfg->vbr_enable = false;
vdsc_cfg->block_pred_enable =
@@ -495,7 +495,7 @@ static voi

[PATCH v2 0/3] Make DRM DSC helpers more generally usable

2019-02-15 Thread David Francis
drm_dsc could use some work so that drm drivers other than
i915 can make use of it their own DSC implementations

Move rc compute, a function that forms part of the DSC spec,
into drm. Update it to DSC 1.2. Also split the PPS packing and
SDP header init functions, to allow for drivers with
their own SDP struct headers

v2:
Rebase onto drm-next
Refactor drm_dsc_dp_pps_header_init
Clean up documentation on new drm function

David Francis (3):
  drm/i915: Move dsc rate params compute into drm
  drm/dsc: Add native 420 and 422 support to compute_rc_params
  drm/dsc: Split DSC PPS and SDP header initialisations

 drivers/gpu/drm/drm_dsc.c | 269 +++---
 drivers/gpu/drm/i915/intel_vdsc.c | 133 +--
 include/drm/drm_dsc.h |   9 +-
 3 files changed, 219 insertions(+), 192 deletions(-)

-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH v2 2/3] drm/dsc: Add native 420 and 422 support to compute_rc_params

2019-02-15 Thread David Francis
Native 420 and 422 transfer modes are new in DSC1.2

In these modes, each two pixels of a slice are treated as one
pixel, so the slice width is half as large (round down) for
the purposes of calucating the groups per line and chunk size
in bytes

In native 422 mode, each pixel has four components, so the
mux component of a group is larger by one additional mux word
and one additional component

Now that there is native 422 support, the configuration option
previously called enable422 is renamed to simple_422 to avoid
confusion

Acked-by: Jani Nikula 
Reviewed-by: Manasi Navare 
Reviewed-by: Harry Wentland 
Signed-off-by: David Francis 
---
 drivers/gpu/drm/drm_dsc.c | 33 ++-
 drivers/gpu/drm/i915/intel_vdsc.c |  4 ++--
 include/drm/drm_dsc.h |  4 ++--
 3 files changed, 28 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/drm_dsc.c b/drivers/gpu/drm/drm_dsc.c
index b7f1903508a4..d77570bf6ac4 100644
--- a/drivers/gpu/drm/drm_dsc.c
+++ b/drivers/gpu/drm/drm_dsc.c
@@ -95,7 +95,7 @@ void drm_dsc_pps_infoframe_pack(struct drm_dsc_pps_infoframe 
*pps_sdp,
((dsc_cfg->bits_per_pixel & DSC_PPS_BPP_HIGH_MASK) >>
 DSC_PPS_MSB_SHIFT) |
dsc_cfg->vbr_enable << DSC_PPS_VBR_EN_SHIFT |
-   dsc_cfg->enable422 << DSC_PPS_SIMPLE422_SHIFT |
+   dsc_cfg->simple_422 << DSC_PPS_SIMPLE422_SHIFT |
dsc_cfg->convert_rgb << DSC_PPS_CONVERT_RGB_SHIFT |
dsc_cfg->block_pred_enable << DSC_PPS_BLOCK_PRED_EN_SHIFT;
 
@@ -249,7 +249,7 @@ EXPORT_SYMBOL(drm_dsc_pps_infoframe_pack);
 /**
  * drm_dsc_compute_rc_parameters() - Write rate control
  * parameters to the dsc configuration defined in
- *  drm_dsc_config in accordance with the DSC 1.1
+ *  drm_dsc_config in accordance with the DSC 1.2
  * specification. Some configuration fields must be present
  * beforehand.
  *
@@ -266,19 +266,34 @@ int drm_dsc_compute_rc_parameters(struct drm_dsc_config 
*vdsc_cfg)
unsigned long final_scale = 0;
unsigned long rbs_min = 0;
 
-   /* Number of groups used to code each line of a slice */
-   groups_per_line = DIV_ROUND_UP(vdsc_cfg->slice_width,
-  DSC_RC_PIXELS_PER_GROUP);
+   if (vdsc_cfg->native_420 || vdsc_cfg->native_422) {
+   /* Number of groups used to code each line of a slice */
+   groups_per_line = DIV_ROUND_UP(vdsc_cfg->slice_width / 2,
+  DSC_RC_PIXELS_PER_GROUP);
 
-   /* chunksize in Bytes */
-   vdsc_cfg->slice_chunk_size = DIV_ROUND_UP(vdsc_cfg->slice_width *
- vdsc_cfg->bits_per_pixel,
- (8 * 16));
+   /* chunksize in Bytes */
+   vdsc_cfg->slice_chunk_size = DIV_ROUND_UP(vdsc_cfg->slice_width 
/ 2 *
+ 
vdsc_cfg->bits_per_pixel,
+ (8 * 16));
+   } else {
+   /* Number of groups used to code each line of a slice */
+   groups_per_line = DIV_ROUND_UP(vdsc_cfg->slice_width,
+  DSC_RC_PIXELS_PER_GROUP);
+
+   /* chunksize in Bytes */
+   vdsc_cfg->slice_chunk_size = DIV_ROUND_UP(vdsc_cfg->slice_width 
*
+ 
vdsc_cfg->bits_per_pixel,
+ (8 * 16));
+   }
 
if (vdsc_cfg->convert_rgb)
num_extra_mux_bits = 3 * (vdsc_cfg->mux_word_size +
  (4 * vdsc_cfg->bits_per_component + 4)
  - 2);
+   else if (vdsc_cfg->native_422)
+   num_extra_mux_bits = 4 * vdsc_cfg->mux_word_size +
+   (4 * vdsc_cfg->bits_per_component + 4) +
+   3 * (4 * vdsc_cfg->bits_per_component) - 2;
else
num_extra_mux_bits = 3 * vdsc_cfg->mux_word_size +
(4 * vdsc_cfg->bits_per_component + 4) +
diff --git a/drivers/gpu/drm/i915/intel_vdsc.c 
b/drivers/gpu/drm/i915/intel_vdsc.c
index 2d059ebc9bd0..8c8d96157333 100644
--- a/drivers/gpu/drm/i915/intel_vdsc.c
+++ b/drivers/gpu/drm/i915/intel_vdsc.c
@@ -368,7 +368,7 @@ int intel_dp_compute_dsc_params(struct intel_dp *intel_dp,
DSC_1_1_MAX_LINEBUF_DEPTH_BITS : line_buf_depth;
 
/* Gen 11 does not support YCbCr */
-   vdsc_cfg->enable422 = false;
+   vdsc_cfg->simple_422 = false;
/* Gen 11 does not support VBR */
vdsc_cfg->vbr_enable = false;
vdsc_cfg->block_pred_enable =
@@ -495,7 +495,7 @@ static voi

[PATCH v2 1/3] drm/i915: Move dsc rate params compute into drm

2019-02-15 Thread David Francis
The function intel_compute_rc_parameters is part of the dsc spec
and is not driver-specific. Other drm drivers might like to use
it.  The function is not changed; just moved and renamed.

Reviewed-by: Harry Wentland 
Signed-off-by: David Francis 
---
 drivers/gpu/drm/drm_dsc.c | 135 ++
 drivers/gpu/drm/i915/intel_vdsc.c | 125 +--
 include/drm/drm_dsc.h |   1 +
 3 files changed, 137 insertions(+), 124 deletions(-)

diff --git a/drivers/gpu/drm/drm_dsc.c b/drivers/gpu/drm/drm_dsc.c
index bce99f95c1a3..b7f1903508a4 100644
--- a/drivers/gpu/drm/drm_dsc.c
+++ b/drivers/gpu/drm/drm_dsc.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -244,3 +245,137 @@ void drm_dsc_pps_infoframe_pack(struct 
drm_dsc_pps_infoframe *pps_sdp,
/* PPS 94 - 127 are O */
 }
 EXPORT_SYMBOL(drm_dsc_pps_infoframe_pack);
+
+/**
+ * drm_dsc_compute_rc_parameters() - Write rate control
+ * parameters to the dsc configuration defined in
+ *  drm_dsc_config in accordance with the DSC 1.1
+ * specification. Some configuration fields must be present
+ * beforehand.
+ *
+ * @vdsc_cfg:
+ * DSC Configuration data partially filled by driver
+ */
+int drm_dsc_compute_rc_parameters(struct drm_dsc_config *vdsc_cfg)
+{
+   unsigned long groups_per_line = 0;
+   unsigned long groups_total = 0;
+   unsigned long num_extra_mux_bits = 0;
+   unsigned long slice_bits = 0;
+   unsigned long hrd_delay = 0;
+   unsigned long final_scale = 0;
+   unsigned long rbs_min = 0;
+
+   /* Number of groups used to code each line of a slice */
+   groups_per_line = DIV_ROUND_UP(vdsc_cfg->slice_width,
+  DSC_RC_PIXELS_PER_GROUP);
+
+   /* chunksize in Bytes */
+   vdsc_cfg->slice_chunk_size = DIV_ROUND_UP(vdsc_cfg->slice_width *
+ vdsc_cfg->bits_per_pixel,
+ (8 * 16));
+
+   if (vdsc_cfg->convert_rgb)
+   num_extra_mux_bits = 3 * (vdsc_cfg->mux_word_size +
+ (4 * vdsc_cfg->bits_per_component + 4)
+ - 2);
+   else
+   num_extra_mux_bits = 3 * vdsc_cfg->mux_word_size +
+   (4 * vdsc_cfg->bits_per_component + 4) +
+   2 * (4 * vdsc_cfg->bits_per_component) - 2;
+   /* Number of bits in one Slice */
+   slice_bits = 8 * vdsc_cfg->slice_chunk_size * vdsc_cfg->slice_height;
+
+   while ((num_extra_mux_bits > 0) &&
+  ((slice_bits - num_extra_mux_bits) % vdsc_cfg->mux_word_size))
+   num_extra_mux_bits--;
+
+   if (groups_per_line < vdsc_cfg->initial_scale_value - 8)
+   vdsc_cfg->initial_scale_value = groups_per_line + 8;
+
+   /* scale_decrement_interval calculation according to DSC spec 1.11 */
+   if (vdsc_cfg->initial_scale_value > 8)
+   vdsc_cfg->scale_decrement_interval = groups_per_line /
+   (vdsc_cfg->initial_scale_value - 8);
+   else
+   vdsc_cfg->scale_decrement_interval = 
DSC_SCALE_DECREMENT_INTERVAL_MAX;
+
+   vdsc_cfg->final_offset = vdsc_cfg->rc_model_size -
+   (vdsc_cfg->initial_xmit_delay *
+vdsc_cfg->bits_per_pixel + 8) / 16 + num_extra_mux_bits;
+
+   if (vdsc_cfg->final_offset >= vdsc_cfg->rc_model_size) {
+   DRM_DEBUG_KMS("FinalOfs < RcModelSze for this 
InitialXmitDelay\n");
+   return -ERANGE;
+   }
+
+   final_scale = (vdsc_cfg->rc_model_size * 8) /
+   (vdsc_cfg->rc_model_size - vdsc_cfg->final_offset);
+   if (vdsc_cfg->slice_height > 1)
+   /*
+* NflBpgOffset is 16 bit value with 11 fractional bits
+* hence we multiply by 2^11 for preserving the
+* fractional part
+*/
+   vdsc_cfg->nfl_bpg_offset = 
DIV_ROUND_UP((vdsc_cfg->first_line_bpg_offset << 11),
+   (vdsc_cfg->slice_height 
- 1));
+   else
+   vdsc_cfg->nfl_bpg_offset = 0;
+
+   /* 2^16 - 1 */
+   if (vdsc_cfg->nfl_bpg_offset > 65535) {
+   DRM_DEBUG_KMS("NflBpgOffset is too large for this slice 
height\n");
+   return -ERANGE;
+   }
+
+   /* Number of groups used to code the entire slice */
+   groups_total = groups_per_line * vdsc_cfg->slice_height;
+
+   /* slice_bpg_offset is 16 bit value with 11 fractional bits */
+   vdsc_cfg->slice_bpg_offset = DIV_ROUND_UP(((vdsc_cfg->rc_model_size -
+   vdsc_cfg->initial_offset +
+

[PATCH 3/3] drm/dsc: Change infoframe_pack to payload_pack

2019-02-13 Thread David Francis
The function drm_dsc_pps_infoframe_pack only
packed the payload portion of the infoframe.
Change the input struct to the PPS payload
to clarify the function's purpose and allow
for drivers with their own handling of sdp.
(e.g. drivers with their own struct for
all SDP transactions)

Signed-off-by: David Francis 
---
 drivers/gpu/drm/drm_dsc.c | 86 +++
 drivers/gpu/drm/i915/intel_vdsc.c |  2 +-
 include/drm/drm_dsc.h |  2 +-
 3 files changed, 45 insertions(+), 45 deletions(-)

diff --git a/drivers/gpu/drm/drm_dsc.c b/drivers/gpu/drm/drm_dsc.c
index 9e675dd39a44..4ada4d4f59ac 100644
--- a/drivers/gpu/drm/drm_dsc.c
+++ b/drivers/gpu/drm/drm_dsc.c
@@ -38,42 +38,42 @@ void drm_dsc_dp_pps_header_init(struct 
drm_dsc_pps_infoframe *pps_sdp)
 EXPORT_SYMBOL(drm_dsc_dp_pps_header_init);
 
 /**
- * drm_dsc_pps_infoframe_pack() - Populates the DSC PPS infoframe
+ * drm_dsc_pps_payload_pack() - Populates the DSC PPS payload
  * using the DSC configuration parameters in the order expected
  * by the DSC Display Sink device. For the DSC, the sink device
  * expects the PPS payload in the big endian format for the fields
  * that span more than 1 byte.
  *
- * @pps_sdp:
- * Secondary data packet for DSC Picture Parameter Set
+ * @pps_payload:
+ * DSC Picture Parameter Set
  * @dsc_cfg:
  * DSC Configuration data filled by driver
  */
-void drm_dsc_pps_infoframe_pack(struct drm_dsc_pps_infoframe *pps_sdp,
+void drm_dsc_pps_payload_pack(struct drm_dsc_picture_parameter_set 
*pps_payload,
const struct drm_dsc_config *dsc_cfg)
 {
int i;
 
/* Protect against someone accidently changing struct size */
-   BUILD_BUG_ON(sizeof(pps_sdp->pps_payload) !=
+   BUILD_BUG_ON(sizeof(*pps_payload) !=
 DP_SDP_PPS_HEADER_PAYLOAD_BYTES_MINUS_1 + 1);
 
-   memset(_sdp->pps_payload, 0, sizeof(pps_sdp->pps_payload));
+   memset(pps_payload, 0, sizeof(*pps_payload));
 
/* PPS 0 */
-   pps_sdp->pps_payload.dsc_version =
+   pps_payload->dsc_version =
dsc_cfg->dsc_version_minor |
dsc_cfg->dsc_version_major << DSC_PPS_VERSION_MAJOR_SHIFT;
 
/* PPS 1, 2 is 0 */
 
/* PPS 3 */
-   pps_sdp->pps_payload.pps_3 =
+   pps_payload->pps_3 =
dsc_cfg->line_buf_depth |
dsc_cfg->bits_per_component << DSC_PPS_BPC_SHIFT;
 
/* PPS 4 */
-   pps_sdp->pps_payload.pps_4 =
+   pps_payload->pps_4 =
((dsc_cfg->bits_per_pixel & DSC_PPS_BPP_HIGH_MASK) >>
 DSC_PPS_MSB_SHIFT) |
dsc_cfg->vbr_enable << DSC_PPS_VBR_EN_SHIFT |
@@ -82,7 +82,7 @@ void drm_dsc_pps_infoframe_pack(struct drm_dsc_pps_infoframe 
*pps_sdp,
dsc_cfg->block_pred_enable << DSC_PPS_BLOCK_PRED_EN_SHIFT;
 
/* PPS 5 */
-   pps_sdp->pps_payload.bits_per_pixel_low =
+   pps_payload->bits_per_pixel_low =
(dsc_cfg->bits_per_pixel & DSC_PPS_LSB_MASK);
 
/*
@@ -93,103 +93,103 @@ void drm_dsc_pps_infoframe_pack(struct 
drm_dsc_pps_infoframe *pps_sdp,
 */
 
/* PPS 6, 7 */
-   pps_sdp->pps_payload.pic_height = cpu_to_be16(dsc_cfg->pic_height);
+   pps_payload->pic_height = cpu_to_be16(dsc_cfg->pic_height);
 
/* PPS 8, 9 */
-   pps_sdp->pps_payload.pic_width = cpu_to_be16(dsc_cfg->pic_width);
+   pps_payload->pic_width = cpu_to_be16(dsc_cfg->pic_width);
 
/* PPS 10, 11 */
-   pps_sdp->pps_payload.slice_height = cpu_to_be16(dsc_cfg->slice_height);
+   pps_payload->slice_height = cpu_to_be16(dsc_cfg->slice_height);
 
/* PPS 12, 13 */
-   pps_sdp->pps_payload.slice_width = cpu_to_be16(dsc_cfg->slice_width);
+   pps_payload->slice_width = cpu_to_be16(dsc_cfg->slice_width);
 
/* PPS 14, 15 */
-   pps_sdp->pps_payload.chunk_size = 
cpu_to_be16(dsc_cfg->slice_chunk_size);
+   pps_payload->chunk_size = cpu_to_be16(dsc_cfg->slice_chunk_size);
 
/* PPS 16 */
-   pps_sdp->pps_payload.initial_xmit_delay_high =
+   pps_payload->initial_xmit_delay_high =
((dsc_cfg->initial_xmit_delay &
  DSC_PPS_INIT_XMIT_DELAY_HIGH_MASK) >>
 DSC_PPS_MSB_SHIFT);
 
/* PPS 17 */
-   pps_sdp->pps_payload.initial_xmit_delay_low =
+   pps_payload->initial_xmit_delay_low =
(dsc_cfg->initial_xmit_delay & DSC_PPS_LSB_MASK);
 
/* PPS 18, 19 */
-   pps_sdp->pps_payload.initial_dec_delay =
+   pps_payload->initial_dec_delay =
cpu_to_be16(dsc_cfg->initial_dec_delay);
 
/* PPS 20 is 0 */
 
/* PPS 21 */
-   pps_sdp->pps_payload.initial_scale_value =
+   pps_payloa

[PATCH 0/3] Make DRM DSC helpers more generally usable

2019-02-13 Thread David Francis
drm_dsc could use some work so that drm drivers other than
i915 can make use of it their own DSC implementations

Move rc compute, a function that forms part of the DSC spec,
into drm. Update it to DSC 1.2. Also change the packing function
to operate only on the packing struct, to allow for drivers with
their own SDP struct headers

David Francis (3):
  drm/i915: Move dsc rate params compute into drm
  drm/dsc: Add native 420 and 422 support to compute_rc_params
  drm/dsc: Change infoframe_pack to payload_pack

 drivers/gpu/drm/drm_dsc.c | 236 --
 drivers/gpu/drm/i915/intel_vdsc.c | 131 +
 include/drm/drm_dsc.h |   7 +-
 3 files changed, 200 insertions(+), 174 deletions(-)

-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

[PATCH 2/3] drm/dsc: Add native 420 and 422 support to compute_rc_params

2019-02-13 Thread David Francis
Native 420 and 422 transfer modes are new in DSC1.2

In these modes, each two pixels of a slice are treated as one
pixel, so the slice width is half as large (round down) for
the purposes of calucating the groups per line and chunk size
in bytes

In native 422 mode, each pixel has four components, so the
mux component of a group is larger by one additional mux word
and one additional component

Now that there is native 422 support, the configuration option
previously called enable422 is renamed to simple_422 to avoid
confusion

Signed-off-by: David Francis 
---
 drivers/gpu/drm/drm_dsc.c | 31 +++
 drivers/gpu/drm/i915/intel_vdsc.c |  4 ++--
 include/drm/drm_dsc.h |  4 ++--
 3 files changed, 27 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/drm_dsc.c b/drivers/gpu/drm/drm_dsc.c
index 4b0e3c9c3ff8..9e675dd39a44 100644
--- a/drivers/gpu/drm/drm_dsc.c
+++ b/drivers/gpu/drm/drm_dsc.c
@@ -77,7 +77,7 @@ void drm_dsc_pps_infoframe_pack(struct drm_dsc_pps_infoframe 
*pps_sdp,
((dsc_cfg->bits_per_pixel & DSC_PPS_BPP_HIGH_MASK) >>
 DSC_PPS_MSB_SHIFT) |
dsc_cfg->vbr_enable << DSC_PPS_VBR_EN_SHIFT |
-   dsc_cfg->enable422 << DSC_PPS_SIMPLE422_SHIFT |
+   dsc_cfg->simple_422 << DSC_PPS_SIMPLE422_SHIFT |
dsc_cfg->convert_rgb << DSC_PPS_CONVERT_RGB_SHIFT |
dsc_cfg->block_pred_enable << DSC_PPS_BLOCK_PRED_EN_SHIFT;
 
@@ -246,19 +246,34 @@ int drm_dsc_compute_rc_parameters(struct drm_dsc_config 
*vdsc_cfg)
unsigned long final_scale = 0;
unsigned long rbs_min = 0;
 
-   /* Number of groups used to code each line of a slice */
-   groups_per_line = DIV_ROUND_UP(vdsc_cfg->slice_width,
-  DSC_RC_PIXELS_PER_GROUP);
+   if (vdsc_cfg->native_420 || vdsc_cfg->native_422) {
+   /* Number of groups used to code each line of a slice */
+   groups_per_line = DIV_ROUND_UP(vdsc_cfg->slice_width / 2,
+  DSC_RC_PIXELS_PER_GROUP);
 
-   /* chunksize in Bytes */
-   vdsc_cfg->slice_chunk_size = DIV_ROUND_UP(vdsc_cfg->slice_width *
- vdsc_cfg->bits_per_pixel,
- (8 * 16));
+   /* chunksize in Bytes */
+   vdsc_cfg->slice_chunk_size = DIV_ROUND_UP(vdsc_cfg->slice_width 
/ 2 *
+ 
vdsc_cfg->bits_per_pixel,
+ (8 * 16));
+   } else {
+   /* Number of groups used to code each line of a slice */
+   groups_per_line = DIV_ROUND_UP(vdsc_cfg->slice_width,
+  DSC_RC_PIXELS_PER_GROUP);
+
+   /* chunksize in Bytes */
+   vdsc_cfg->slice_chunk_size = DIV_ROUND_UP(vdsc_cfg->slice_width 
*
+ 
vdsc_cfg->bits_per_pixel,
+ (8 * 16));
+   }
 
if (vdsc_cfg->convert_rgb)
num_extra_mux_bits = 3 * (vdsc_cfg->mux_word_size +
  (4 * vdsc_cfg->bits_per_component + 4)
  - 2);
+   else if (vdsc_cfg->native_422)
+   num_extra_mux_bits = 4 * vdsc_cfg->mux_word_size +
+   (4 * vdsc_cfg->bits_per_component + 4) +
+   3 * (4 * vdsc_cfg->bits_per_component) - 2;
else
num_extra_mux_bits = 3 * vdsc_cfg->mux_word_size +
(4 * vdsc_cfg->bits_per_component + 4) +
diff --git a/drivers/gpu/drm/i915/intel_vdsc.c 
b/drivers/gpu/drm/i915/intel_vdsc.c
index c76cec8bfb74..7702c5c8b3f2 100644
--- a/drivers/gpu/drm/i915/intel_vdsc.c
+++ b/drivers/gpu/drm/i915/intel_vdsc.c
@@ -369,7 +369,7 @@ int intel_dp_compute_dsc_params(struct intel_dp *intel_dp,
DSC_1_1_MAX_LINEBUF_DEPTH_BITS : line_buf_depth;
 
/* Gen 11 does not support YCbCr */
-   vdsc_cfg->enable422 = false;
+   vdsc_cfg->simple_422 = false;
/* Gen 11 does not support VBR */
vdsc_cfg->vbr_enable = false;
vdsc_cfg->block_pred_enable =
@@ -496,7 +496,7 @@ static void intel_configure_pps_for_dsc_encoder(struct 
intel_encoder *encoder,
pps_val |= DSC_BLOCK_PREDICTION;
if (vdsc_cfg->convert_rgb)
pps_val |= DSC_COLOR_SPACE_CONVERSION;
-   if (vdsc_cfg->enable422)
+   if (vdsc_cfg->simple_422)
pps_val |= DSC_422_ENABLE;
if (vdsc_cfg->vbr_enable)
pps_val |= DSC_VBR_ENABLE;
diff --git a/include/drm/drm_d

[PATCH 1/3] drm/i915: Move dsc rate params compute into drm

2019-02-13 Thread David Francis
The function intel_compute_rc_parameters is part of the dsc spec
and is not driver-specific. Other drm drivers might like to use
it.  The function is not changed; just moved and renamed.

Signed-off-by: David Francis 
---
 drivers/gpu/drm/drm_dsc.c | 133 ++
 drivers/gpu/drm/i915/intel_vdsc.c | 125 +---
 include/drm/drm_dsc.h |   1 +
 3 files changed, 135 insertions(+), 124 deletions(-)

diff --git a/drivers/gpu/drm/drm_dsc.c b/drivers/gpu/drm/drm_dsc.c
index bc2b23adb072..4b0e3c9c3ff8 100644
--- a/drivers/gpu/drm/drm_dsc.c
+++ b/drivers/gpu/drm/drm_dsc.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -226,3 +227,135 @@ void drm_dsc_pps_infoframe_pack(struct 
drm_dsc_pps_infoframe *pps_sdp,
/* PPS 94 - 127 are O */
 }
 EXPORT_SYMBOL(drm_dsc_pps_infoframe_pack);
+
+/**
+ * drm_dsc_compute_rc_parameters() - Write rate control
+ * parameters to the dsc configuration. Some configuration
+ * fields must be present beforehand.
+ *
+ * @dsc_cfg:
+ * DSC Configuration data partially filled by driver
+ */
+int drm_dsc_compute_rc_parameters(struct drm_dsc_config *vdsc_cfg)
+{
+   unsigned long groups_per_line = 0;
+   unsigned long groups_total = 0;
+   unsigned long num_extra_mux_bits = 0;
+   unsigned long slice_bits = 0;
+   unsigned long hrd_delay = 0;
+   unsigned long final_scale = 0;
+   unsigned long rbs_min = 0;
+
+   /* Number of groups used to code each line of a slice */
+   groups_per_line = DIV_ROUND_UP(vdsc_cfg->slice_width,
+  DSC_RC_PIXELS_PER_GROUP);
+
+   /* chunksize in Bytes */
+   vdsc_cfg->slice_chunk_size = DIV_ROUND_UP(vdsc_cfg->slice_width *
+ vdsc_cfg->bits_per_pixel,
+ (8 * 16));
+
+   if (vdsc_cfg->convert_rgb)
+   num_extra_mux_bits = 3 * (vdsc_cfg->mux_word_size +
+ (4 * vdsc_cfg->bits_per_component + 4)
+ - 2);
+   else
+   num_extra_mux_bits = 3 * vdsc_cfg->mux_word_size +
+   (4 * vdsc_cfg->bits_per_component + 4) +
+   2 * (4 * vdsc_cfg->bits_per_component) - 2;
+   /* Number of bits in one Slice */
+   slice_bits = 8 * vdsc_cfg->slice_chunk_size * vdsc_cfg->slice_height;
+
+   while ((num_extra_mux_bits > 0) &&
+  ((slice_bits - num_extra_mux_bits) % vdsc_cfg->mux_word_size))
+   num_extra_mux_bits--;
+
+   if (groups_per_line < vdsc_cfg->initial_scale_value - 8)
+   vdsc_cfg->initial_scale_value = groups_per_line + 8;
+
+   /* scale_decrement_interval calculation according to DSC spec 1.11 */
+   if (vdsc_cfg->initial_scale_value > 8)
+   vdsc_cfg->scale_decrement_interval = groups_per_line /
+   (vdsc_cfg->initial_scale_value - 8);
+   else
+   vdsc_cfg->scale_decrement_interval = 
DSC_SCALE_DECREMENT_INTERVAL_MAX;
+
+   vdsc_cfg->final_offset = vdsc_cfg->rc_model_size -
+   (vdsc_cfg->initial_xmit_delay *
+vdsc_cfg->bits_per_pixel + 8) / 16 + num_extra_mux_bits;
+
+   if (vdsc_cfg->final_offset >= vdsc_cfg->rc_model_size) {
+   DRM_DEBUG_KMS("FinalOfs < RcModelSze for this 
InitialXmitDelay\n");
+   return -ERANGE;
+   }
+
+   final_scale = (vdsc_cfg->rc_model_size * 8) /
+   (vdsc_cfg->rc_model_size - vdsc_cfg->final_offset);
+   if (vdsc_cfg->slice_height > 1)
+   /*
+* NflBpgOffset is 16 bit value with 11 fractional bits
+* hence we multiply by 2^11 for preserving the
+* fractional part
+*/
+   vdsc_cfg->nfl_bpg_offset = 
DIV_ROUND_UP((vdsc_cfg->first_line_bpg_offset << 11),
+   (vdsc_cfg->slice_height 
- 1));
+   else
+   vdsc_cfg->nfl_bpg_offset = 0;
+
+   /* 2^16 - 1 */
+   if (vdsc_cfg->nfl_bpg_offset > 65535) {
+   DRM_DEBUG_KMS("NflBpgOffset is too large for this slice 
height\n");
+   return -ERANGE;
+   }
+
+   /* Number of groups used to code the entire slice */
+   groups_total = groups_per_line * vdsc_cfg->slice_height;
+
+   /* slice_bpg_offset is 16 bit value with 11 fractional bits */
+   vdsc_cfg->slice_bpg_offset = DIV_ROUND_UP(((vdsc_cfg->rc_model_size -
+   vdsc_cfg->initial_offset +
+   num_extra_mux_bits) << 11),
+  

[PATCH] drm/amd/display: Clean up coding style violations

2019-01-29 Thread David Francis
Some of the grandfathered amd display code does not follow
Linux coding style and emits warnings or errors on checkpatch

No functional changes here - just cleanup

Signed-off-by: David Francis 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 96 +--
 1 file changed, 47 insertions(+), 49 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index cdda68aba70e..973517d35d5c 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -176,56 +176,56 @@ static const enum drm_plane_type 
dm_plane_type_stoney[AMDGPU_MAX_PLANES] = {
  */
 static u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc)
 {
+   struct amdgpu_crtc *acrtc;
+   struct dm_crtc_state *acrtc_state;
+
if (crtc >= adev->mode_info.num_crtc)
return 0;
-   else {
-   struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc];
-   struct dm_crtc_state *acrtc_state = to_dm_crtc_state(
-   acrtc->base.state);
 
+   acrtc = adev->mode_info.crtcs[crtc];
+   acrtc_state = to_dm_crtc_state(acrtc->base.state);
 
-   if (acrtc_state->stream == NULL) {
-   DRM_ERROR("dc_stream_state is NULL for crtc '%d'!\n",
- crtc);
-   return 0;
-   }
-
-   return dc_stream_get_vblank_counter(acrtc_state->stream);
+   if (acrtc_state->stream == NULL) {
+   DRM_ERROR("dc_stream_state is NULL for crtc '%d'!\n",
+ crtc);
+   return 0;
}
+
+   return dc_stream_get_vblank_counter(acrtc_state->stream);
 }
 
 static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
  u32 *vbl, u32 *position)
 {
uint32_t v_blank_start, v_blank_end, h_position, v_position;
+   struct amdgpu_crtc *acrtc;
+   struct dm_crtc_state *acrtc_state;
 
if ((crtc < 0) || (crtc >= adev->mode_info.num_crtc))
return -EINVAL;
-   else {
-   struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc];
-   struct dm_crtc_state *acrtc_state = to_dm_crtc_state(
-   acrtc->base.state);
-
-   if (acrtc_state->stream ==  NULL) {
-   DRM_ERROR("dc_stream_state is NULL for crtc '%d'!\n",
- crtc);
-   return 0;
-   }
 
-   /*
-* TODO rework base driver to use values directly.
-* for now parse it back into reg-format
-*/
-   dc_stream_get_scanoutpos(acrtc_state->stream,
-_blank_start,
-_blank_end,
-_position,
-_position);
+   acrtc = adev->mode_info.crtcs[crtc];
+   acrtc_state = to_dm_crtc_state(acrtc->base.state);
 
-   *position = v_position | (h_position << 16);
-   *vbl = v_blank_start | (v_blank_end << 16);
+   if (acrtc_state->stream ==  NULL) {
+   DRM_ERROR("dc_stream_state is NULL for crtc '%d'!\n",
+ crtc);
+   return 0;
}
 
+   /*
+* TODO rework base driver to use values directly.
+* for now parse it back into reg-format
+*/
+   dc_stream_get_scanoutpos(acrtc_state->stream,
+_blank_start,
+_blank_end,
+_position,
+_position);
+
+   *position = v_position | (h_position << 16);
+   *vbl = v_blank_start | (v_blank_end << 16);
+
return 0;
 }
 
@@ -293,8 +293,8 @@ static void dm_pflip_high_irq(void *interrupt_params)
 
spin_lock_irqsave(>ddev->event_lock, flags);
 
-   if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED){
-   DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d 
!=AMDGPU_FLIP_SUBMITTED(%d) on crtc:%d[%p] \n",
+   if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED) {
+   DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d 
!=AMDGPU_FLIP_SUBMITTED(%d) on crtc:%d[%p]\n",
 amdgpu_crtc->pflip_status,
 AMDGPU_FLIP_SUBMITTED,
 amdgpu_crtc->crtc_id,
@@ -370,7 +370,7 @@ static int dm_set_powergating_state(void *handle,
 }
 
 /* Prototypes of private functions */
-static int dm_early_ini

[PATCH 04/16 v2] drm/amd/display: Add tracing to dc

2018-11-30 Thread David Francis
[Why]
Tracing is a useful and cheap debug functionality

[How]
This creates a new trace system amdgpu_dm, currently with
three trace events

amdgpu_dc_rreg and amdgpu_dc_wreg report the address and value
of any dc register reads and writes

amdgpu_dc_performance requires at least one of those two to be
enabled.  It counts the register reads and writes since the
last entry

v2: Don't check for NULL before kfree

Signed-off-by: David Francis 
Reviewed-by: Harry Wentland 
Acked-by: Leo Li 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |   3 +
 .../amd/display/amdgpu_dm/amdgpu_dm_trace.h   | 104 ++
 drivers/gpu/drm/amd/display/dc/core/dc.c  |  19 
 drivers/gpu/drm/amd/display/dc/dc_types.h |   8 ++
 .../amd/display/dc/dcn10/dcn10_cm_common.c|   4 +-
 drivers/gpu/drm/amd/display/dc/dm_services.h  |  12 +-
 6 files changed, 146 insertions(+), 4 deletions(-)
 create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 76b1aebdca0c..376927c8bcc6 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -23,6 +23,9 @@
  *
  */
 
+/* The caprices of the preprocessor require that this be declared right here */
+#define CREATE_TRACE_POINTS
+
 #include "dm_services_types.h"
 #include "dc.h"
 #include "dc/inc/core_types.h"
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
new file mode 100644
index ..d898981684d5
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2018 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM amdgpu_dm
+
+#if !defined(_AMDGPU_DM_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _AMDGPU_DM_TRACE_H_
+
+#include 
+
+TRACE_EVENT(amdgpu_dc_rreg,
+   TP_PROTO(unsigned long *read_count, uint32_t reg, uint32_t value),
+   TP_ARGS(read_count, reg, value),
+   TP_STRUCT__entry(
+   __field(uint32_t, reg)
+   __field(uint32_t, value)
+   ),
+   TP_fast_assign(
+   __entry->reg = reg;
+   __entry->value = value;
+   *read_count = *read_count + 1;
+   ),
+   TP_printk("reg=0x%08lx, value=0x%08lx",
+   (unsigned long)__entry->reg,
+   (unsigned long)__entry->value)
+);
+
+TRACE_EVENT(amdgpu_dc_wreg,
+   TP_PROTO(unsigned long *write_count, uint32_t reg, uint32_t value),
+   TP_ARGS(write_count, reg, value),
+   TP_STRUCT__entry(
+   __field(uint32_t, reg)
+   __field(uint32_t, value)
+   ),
+   TP_fast_assign(
+   __entry->reg = reg;
+   __entry->value = value;
+   *write_count = *write_count + 1;
+   ),
+   TP_printk("reg=0x%08lx, value=0x%08lx",
+   (unsigned long)__entry->reg,
+   (unsigned long)__entry->value)
+);
+
+
+TRACE_EVENT(amdgpu_dc_performance,
+   TP_PROTO(unsigned long read_count, unsigned long write_count,
+   unsigned long *last_read, unsigned long *last_write,
+   const char *func, unsigned int line),
+   TP_ARGS(read_count, write_count, last_read, last_write, func, line),
+   TP_STRUCT__entry(
+   __field(uint32_t, reads)
+   __field(uint32_t, writes)
+   __field(uint32_t, read_delta)
+   __field(uint3

[PATCH] drm/amd/display: Fix compile error with ACPI disabled

2018-11-27 Thread David Francis
The fallback code for getting default backlight caps was using
the wrong variable name.  Fix it.

Fixes: 
https://lists.freedesktop.org/archives/dri-devel/2018-November/197752.html
Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 27df3ae945be..aa3f8200fa69 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -1615,8 +1615,8 @@ static void amdgpu_dm_update_backlight_caps(struct 
amdgpu_display_manager *dm)
AMDGPU_DM_DEFAULT_MAX_BACKLIGHT;
}
 #else
-   dm->backlight_min_input_signal = AMDGPU_DM_DEFAULT_MIN_BACKLIGHT;
-   dm->backlight_max_input_signal = AMDGPU_DM_DEFAULT_MAX_BACKLIGHT;
+   dm->backlight_caps.min_input_signal = AMDGPU_DM_DEFAULT_MIN_BACKLIGHT;
+   dm->backlight_caps.max_input_signal = AMDGPU_DM_DEFAULT_MAX_BACKLIGHT;
 #endif
 }
 
-- 
2.17.1

___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[PATCH v4 2/2] drm/amd: Add abm level drm property

2018-11-20 Thread David Francis
Adaptive Backlight Management (ABM) is a feature
that reduces backlight level to save power, while
increasing pixel contrast and pixel luminance
to maintain readability and image quality.

ABM will adjust in response to the
pixel luminance of the displayed content.

ABM is made available as a drm property on eDP
monitors called "abm level", which ranges from 0 to 4.
When this property is set to 0, ABM is off.  Levels 1
to 4 represent different ranges of backlight reduction.
At higher levels both the backlight reduction and pixel
adjustment will be greater.

ABM requires DMCU firmware, which is currently available for
Raven ASICs only.  If the feature does not work, please
ensure your firmware is up to date.

v2:
Fix commit message, only attach property if DMCU loaded
v3:
Store ABM level in crtc state to accommodate dc
v4:
Fix ABM saving on dpms cycle

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_display.c   |  5 +++
 drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h  |  2 ++
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 36 ---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  3 ++
 drivers/gpu/drm/amd/display/dc/core/dc.c  | 11 +-
 drivers/gpu/drm/amd/display/dc/dc.h   |  1 +
 6 files changed, 53 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index 7d6a36bca9dd..ced8cefa223b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -637,6 +637,11 @@ int amdgpu_display_modeset_create_props(struct 
amdgpu_device *adev)
 "freesync_capable");
if (!adev->mode_info.freesync_capable_property)
return -ENOMEM;
+   adev->mode_info.abm_level_property =
+   drm_property_create_range(adev->ddev, 0,
+   "abm level", 0, 4);
+   if (!adev->mode_info.abm_level_property)
+   return -ENOMEM;
}
 
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index 1627dd3413c7..2938635c0fc1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -342,6 +342,8 @@ struct amdgpu_mode_info {
struct drm_property *freesync_property;
/* it is used to know about display capability of freesync mode */
struct drm_property *freesync_capable_property;
+   /* Adaptive Backlight Modulation (power feature) */
+   struct drm_property *abm_level_property;
/* hardcoded DFP edid from BIOS */
struct edid *bios_hardcoded_edid;
int bios_hardcoded_edid_size;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index f71febb4210d..95b1106e0662 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -2920,6 +2920,7 @@ dm_crtc_duplicate_state(struct drm_crtc *crtc)
state->adjust = cur->adjust;
state->vrr_infopacket = cur->vrr_infopacket;
state->freesync_enabled = cur->freesync_enabled;
+   state->abm_level = cur->abm_level;
 
/* TODO Duplicate dc_stream after objects are stream object is 
flattened */
 
@@ -3038,6 +3039,9 @@ int amdgpu_dm_connector_atomic_set_property(struct 
drm_connector *connector,
} else if (property == adev->mode_info.freesync_capable_property) {
dm_new_state->freesync_capable = val;
ret = 0;
+   } else if (property == adev->mode_info.abm_level_property) {
+   dm_new_state->abm_level = val;
+   ret = 0;
}
 
return ret;
@@ -3086,7 +3090,11 @@ int amdgpu_dm_connector_atomic_get_property(struct 
drm_connector *connector,
} else if (property == adev->mode_info.freesync_capable_property) {
*val = dm_state->freesync_capable;
ret = 0;
+   } else if (property == adev->mode_info.abm_level_property) {
+   *val = dm_state->abm_level;
+   ret = 0;
}
+
return ret;
 }
 
@@ -3151,6 +3159,7 @@ amdgpu_dm_connector_atomic_duplicate_state(struct 
drm_connector *connector)
 
new_state->freesync_capable = state->freesync_capable;
new_state->freesync_enable = state->freesync_enable;
+   new_state->abm_level = state->abm_level;
 
return _state->base;
 }
@@ -3904,6 +3913,12 @@ void amdgpu_dm_connector_init_helper(struct 
amdgpu_display_manager *dm,
drm_object_attach_property(>base.base,
adev->mode_info.freesync_capable_property, 0);
}
+
+   if (connector_type == DRM_MODE_CONN

[PATCH v4 1/2] drm/amd: Load DMCU IRAM

2018-11-20 Thread David Francis
DMCU IRAM must be loaded by the driver before DMCU
can function.

Move the IRAM code out of the shadows and into a new file
modules/power/power_helpers.c

The IRAM table contains the backlight curve and ABM parameters

Add this new file to the Makefiles

Call dmcu_load_iram in late init of DM

Move struct dmcu_version from dc.h to dmcu.h to allow
dmcu to be included on its own

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/display/Makefile  |   3 +-
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  21 ++
 drivers/gpu/drm/amd/display/dc/dc.h   |   8 +-
 drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h  |   7 +
 .../drm/amd/display/modules/power/Makefile|  31 ++
 .../amd/display/modules/power/power_helpers.c | 326 ++
 .../amd/display/modules/power/power_helpers.h |  47 +++
 7 files changed, 435 insertions(+), 8 deletions(-)
 create mode 100644 drivers/gpu/drm/amd/display/modules/power/Makefile
 create mode 100644 drivers/gpu/drm/amd/display/modules/power/power_helpers.c
 create mode 100644 drivers/gpu/drm/amd/display/modules/power/power_helpers.h

diff --git a/drivers/gpu/drm/amd/display/Makefile 
b/drivers/gpu/drm/amd/display/Makefile
index c97dc9613325..cfde1568c79a 100644
--- a/drivers/gpu/drm/amd/display/Makefile
+++ b/drivers/gpu/drm/amd/display/Makefile
@@ -32,11 +32,12 @@ subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/inc
 subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/freesync
 subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/color
 subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/info_packet
+subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/power
 
 #TODO: remove when Timing Sync feature is complete
 subdir-ccflags-y += -DBUILD_FEATURE_TIMING_SYNC=0
 
-DAL_LIBS = amdgpu_dm dcmodules/freesync modules/color 
modules/info_packet
+DAL_LIBS = amdgpu_dm dcmodules/freesync modules/color 
modules/info_packet modules/power
 
 AMD_DAL = $(addsuffix /Makefile, $(addprefix 
$(FULL_AMD_DISPLAY_PATH)/,$(DAL_LIBS)))
 
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 0c1a533eb531..f71febb4210d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -72,6 +72,7 @@
 #endif
 
 #include "modules/inc/mod_freesync.h"
+#include "modules/power/power_helpers.h"
 
 #define FIRMWARE_RAVEN_DMCU"amdgpu/raven_dmcu.bin"
 MODULE_FIRMWARE(FIRMWARE_RAVEN_DMCU);
@@ -643,6 +644,26 @@ static int dm_late_init(void *handle)
 {
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+   struct dmcu_iram_parameters params;
+   unsigned int linear_lut[16];
+   int i;
+   struct dmcu *dmcu = adev->dm.dc->res_pool->dmcu;
+   bool ret;
+
+   for (i = 0; i < 16; i++)
+   linear_lut[i] = 0x * i / 15;
+
+   params.set = 0;
+   params.backlight_ramping_start = 0x;
+   params.backlight_ramping_reduction = 0x;
+   params.backlight_lut_array_size = 16;
+   params.backlight_lut_array = linear_lut;
+
+   ret = dmcu_load_iram(dmcu, params);
+
+   if (!ret)
+   return -EINVAL;
+
return detect_mst_link_for_all_connectors(adev->ddev);
 }
 
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h 
b/drivers/gpu/drm/amd/display/dc/dc.h
index 18865a76ea55..6b0988310138 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -36,6 +36,7 @@
 
 #include "inc/hw_sequencer.h"
 #include "inc/compressor.h"
+#include "inc/hw/dmcu.h"
 #include "dml/display_mode_lib.h"
 
 #define DC_VER "3.2.06"
@@ -47,13 +48,6 @@
 
/***
  * Display Core Interfaces
  
**/
-struct dmcu_version {
-   unsigned int date;
-   unsigned int month;
-   unsigned int year;
-   unsigned int interface_version;
-};
-
 struct dc_versions {
const char *dc_ver;
struct dmcu_version dmcu_version;
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h 
b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h
index 4550747fb61c..cb85eaa9857f 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h
@@ -32,6 +32,13 @@ enum dmcu_state {
DMCU_RUNNING = 1
 };
 
+struct dmcu_version {
+   unsigned int date;
+   unsigned int month;
+   unsigned int year;
+   unsigned int interface_version;
+};
+
 struct dmcu {
struct dc_context *ctx;
const struct dmcu_funcs *funcs;
diff --git a/drivers/gpu/drm/amd/display/modules/power/Makefile 
b/drivers/gpu/drm/amd/display/modules/power/Makefile
new file mode 100644
index ..87851f892a52
--- /dev/null
+++ b/drivers/gpu/drm/amd/d

[PATCH] drm/amd: Query and use ACPI backlight caps

2018-11-20 Thread David Francis
ACPI ATIF has a function called query
backlight transfer characteristics.  Among the
information returned by this function is
the minimum and maximum input signals for the
backlight

Call that function on ACPI init.  When DM
backlight device is updated, copy over the
backlight caps into DM, but only once.  Use
the backlight caps in the backlight-to-dc
calculation.

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu.h   |  3 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c  | 83 +++
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 59 ++---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 13 +++
 drivers/gpu/drm/amd/include/amd_acpi.h| 24 ++
 5 files changed, 170 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 2c80453ca350..adbad0e2d4ea 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -1255,6 +1255,9 @@ bool 
amdgpu_acpi_is_pcie_performance_request_supported(struct amdgpu_device *ade
 int amdgpu_acpi_pcie_performance_request(struct amdgpu_device *adev,
u8 perf_req, bool advertise);
 int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev);
+
+void amdgpu_acpi_get_backlight_caps(struct amdgpu_device *adev,
+   struct amdgpu_dm_backlight_caps *caps);
 #else
 static inline int amdgpu_acpi_init(struct amdgpu_device *adev) { return 0; }
 static inline void amdgpu_acpi_fini(struct amdgpu_device *adev) { }
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
index 471266901d1b..47db65926d71 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
@@ -65,6 +65,7 @@ struct amdgpu_atif {
struct amdgpu_atif_functions functions;
struct amdgpu_atif_notification_cfg notification_cfg;
struct amdgpu_encoder *encoder_for_bl;
+   struct amdgpu_dm_backlight_caps backlight_caps;
 };
 
 /* Call the ATIF method
@@ -297,6 +298,65 @@ static int amdgpu_atif_get_notification_params(struct 
amdgpu_atif *atif)
return err;
 }
 
+/**
+ * amdgpu_atif_query_backlight_caps - get min and max backlight input signal
+ *
+ * @handle: acpi handle
+ *
+ * Execute the QUERY_BRIGHTNESS_TRANSFER_CHARACTERISTICS ATIF function
+ * to determine the acceptable range of backlight values
+ *
+ * Backlight_caps.caps_valid will be set to true if the query is successful
+ *
+ * The input signals are in range 0-255
+ *
+ * This function assumes the display with backlight is the first LCD
+ *
+ * Returns 0 on success, error on failure.
+ */
+static int amdgpu_atif_query_backlight_caps(struct amdgpu_atif *atif)
+{
+   union acpi_object *info;
+   struct atif_qbtc_output characteristics;
+   struct atif_qbtc_arguments arguments;
+   struct acpi_buffer params;
+   size_t size;
+   int err = 0;
+
+   arguments.size = sizeof(arguments);
+   arguments.requested_display = ATIF_QBTC_REQUEST_LCD1;
+
+   params.length = sizeof(arguments);
+   params.pointer = (void *)
+
+   info = amdgpu_atif_call(atif,
+   ATIF_FUNCTION_QUERY_BRIGHTNESS_TRANSFER_CHARACTERISTICS,
+   );
+   if (!info) {
+   err = -EIO;
+   goto out;
+   }
+
+   size = *(u16 *) info->buffer.pointer;
+   if (size < 10) {
+   err = -EINVAL;
+   goto out;
+   }
+
+   memset(, 0, sizeof(characteristics));
+   size = min(sizeof(characteristics), size);
+   memcpy(, info->buffer.pointer, size);
+
+   atif->backlight_caps.caps_valid = true;
+   atif->backlight_caps.min_input_signal =
+   characteristics.min_input_signal;
+   atif->backlight_caps.max_input_signal =
+   characteristics.max_input_signal;
+out:
+   kfree(info);
+   return err;
+}
+
 /**
  * amdgpu_atif_get_sbios_requests - get requested sbios event
  *
@@ -786,6 +846,17 @@ int amdgpu_acpi_init(struct amdgpu_device *adev)
}
}
 
+   if (atif->functions.query_backlight_transfer_characteristics) {
+   ret = amdgpu_atif_query_backlight_caps(atif);
+   if (ret) {
+   DRM_DEBUG_DRIVER("Call to 
QUERY_BACKLIGHT_TRANSFER_CHARACTERISTICS failed: %d\n",
+   ret);
+   atif->backlight_caps.caps_valid = false;
+   }
+   } else {
+   atif->backlight_caps.caps_valid = false;
+   }
+
 out:
adev->acpi_nb.notifier_call = amdgpu_acpi_event;
register_acpi_notifier(>acpi_nb);
@@ -793,6 +864,18 @@ int amdgpu_acpi_init(struct amdgpu_device *adev)
return ret;
 }
 
+void amdgpu_acpi_get_backlight_caps(struct amdgpu_device *adev,
+   struct amdgpu_dm_backl

[PATCH v3 2/2] drm/amd: Add abm level drm property

2018-11-15 Thread David Francis
Adaptive Backlight Management (ABM) is a feature
that reduces backlight level to save power, while
increasing pixel contrast and pixel luminance
to maintain readability and image quality.

ABM will adjust in response to the
pixel luminance of the displayed content.

ABM is made available as a drm property on eDP
monitors called "abm level", which ranges from 0 to 4.
When this property is set to 0, ABM is off.  Levels 1
to 4 represent different ranges of backlight reduction.
At higher levels both the backlight reduction and pixel
adjustment will be greater.

ABM requires DMCU firmware, which is currently available for
Raven ASICs only.  If the feature does not work, please
ensure your firmware is up to date.

v2:
Fix commit message, only attach property if DMCU loaded
v3:
Storre ABM level in crtc state to accommodate dc

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_display.c   |  5 +++
 drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h  |  2 ++
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 35 ---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  3 ++
 drivers/gpu/drm/amd/display/dc/core/dc.c  | 11 +-
 drivers/gpu/drm/amd/display/dc/dc.h   |  1 +
 6 files changed, 52 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index 7d6a36bca9dd..ced8cefa223b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -637,6 +637,11 @@ int amdgpu_display_modeset_create_props(struct 
amdgpu_device *adev)
 "freesync_capable");
if (!adev->mode_info.freesync_capable_property)
return -ENOMEM;
+   adev->mode_info.abm_level_property =
+   drm_property_create_range(adev->ddev, 0,
+   "abm level", 0, 4);
+   if (!adev->mode_info.abm_level_property)
+   return -ENOMEM;
}
 
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index 1627dd3413c7..2938635c0fc1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -342,6 +342,8 @@ struct amdgpu_mode_info {
struct drm_property *freesync_property;
/* it is used to know about display capability of freesync mode */
struct drm_property *freesync_capable_property;
+   /* Adaptive Backlight Modulation (power feature) */
+   struct drm_property *abm_level_property;
/* hardcoded DFP edid from BIOS */
struct edid *bios_hardcoded_edid;
int bios_hardcoded_edid_size;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index f71febb4210d..090a602f3014 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -2920,6 +2920,7 @@ dm_crtc_duplicate_state(struct drm_crtc *crtc)
state->adjust = cur->adjust;
state->vrr_infopacket = cur->vrr_infopacket;
state->freesync_enabled = cur->freesync_enabled;
+   state->abm_level = cur->abm_level;
 
/* TODO Duplicate dc_stream after objects are stream object is 
flattened */
 
@@ -3038,6 +3039,9 @@ int amdgpu_dm_connector_atomic_set_property(struct 
drm_connector *connector,
} else if (property == adev->mode_info.freesync_capable_property) {
dm_new_state->freesync_capable = val;
ret = 0;
+   } else if (property == adev->mode_info.abm_level_property) {
+   dm_new_state->abm_level = val;
+   ret = 0;
}
 
return ret;
@@ -3086,7 +3090,11 @@ int amdgpu_dm_connector_atomic_get_property(struct 
drm_connector *connector,
} else if (property == adev->mode_info.freesync_capable_property) {
*val = dm_state->freesync_capable;
ret = 0;
+   } else if (property == adev->mode_info.abm_level_property) {
+   *val = dm_state->abm_level;
+   ret = 0;
}
+
return ret;
 }
 
@@ -3151,6 +3159,7 @@ amdgpu_dm_connector_atomic_duplicate_state(struct 
drm_connector *connector)
 
new_state->freesync_capable = state->freesync_capable;
new_state->freesync_enable = state->freesync_enable;
+   new_state->abm_level = state->abm_level;
 
return _state->base;
 }
@@ -3904,6 +3913,12 @@ void amdgpu_dm_connector_init_helper(struct 
amdgpu_display_manager *dm,
drm_object_attach_property(>base.base,
adev->mode_info.freesync_capable_property, 0);
}
+
+   if (connector_type == DRM_MODE_CONN

[PATCH v3 1/2] drm/amd: Load DMCU IRAM

2018-11-15 Thread David Francis
DMCU IRAM must be loaded by the driver before DMCU
can function.

Move the IRAM code out of the shadows and into a new file
modules/power/power_helpers.c

The IRAM table contains the backlight curve and ABM parameters

Add this new file to the Makefiles

Call dmcu_load_iram in late init of DM

Move struct dmcu_version from dc.h to dmcu.h to allow
dmcu to be included on its own

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/display/Makefile  |   3 +-
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  21 ++
 drivers/gpu/drm/amd/display/dc/dc.h   |   8 +-
 drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h  |   7 +
 .../drm/amd/display/modules/power/Makefile|  31 ++
 .../amd/display/modules/power/power_helpers.c | 326 ++
 .../amd/display/modules/power/power_helpers.h |  47 +++
 7 files changed, 435 insertions(+), 8 deletions(-)
 create mode 100644 drivers/gpu/drm/amd/display/modules/power/Makefile
 create mode 100644 drivers/gpu/drm/amd/display/modules/power/power_helpers.c
 create mode 100644 drivers/gpu/drm/amd/display/modules/power/power_helpers.h

diff --git a/drivers/gpu/drm/amd/display/Makefile 
b/drivers/gpu/drm/amd/display/Makefile
index c97dc9613325..cfde1568c79a 100644
--- a/drivers/gpu/drm/amd/display/Makefile
+++ b/drivers/gpu/drm/amd/display/Makefile
@@ -32,11 +32,12 @@ subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/inc
 subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/freesync
 subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/color
 subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/info_packet
+subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/power
 
 #TODO: remove when Timing Sync feature is complete
 subdir-ccflags-y += -DBUILD_FEATURE_TIMING_SYNC=0
 
-DAL_LIBS = amdgpu_dm dcmodules/freesync modules/color 
modules/info_packet
+DAL_LIBS = amdgpu_dm dcmodules/freesync modules/color 
modules/info_packet modules/power
 
 AMD_DAL = $(addsuffix /Makefile, $(addprefix 
$(FULL_AMD_DISPLAY_PATH)/,$(DAL_LIBS)))
 
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 0c1a533eb531..f71febb4210d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -72,6 +72,7 @@
 #endif
 
 #include "modules/inc/mod_freesync.h"
+#include "modules/power/power_helpers.h"
 
 #define FIRMWARE_RAVEN_DMCU"amdgpu/raven_dmcu.bin"
 MODULE_FIRMWARE(FIRMWARE_RAVEN_DMCU);
@@ -643,6 +644,26 @@ static int dm_late_init(void *handle)
 {
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+   struct dmcu_iram_parameters params;
+   unsigned int linear_lut[16];
+   int i;
+   struct dmcu *dmcu = adev->dm.dc->res_pool->dmcu;
+   bool ret;
+
+   for (i = 0; i < 16; i++)
+   linear_lut[i] = 0x * i / 15;
+
+   params.set = 0;
+   params.backlight_ramping_start = 0x;
+   params.backlight_ramping_reduction = 0x;
+   params.backlight_lut_array_size = 16;
+   params.backlight_lut_array = linear_lut;
+
+   ret = dmcu_load_iram(dmcu, params);
+
+   if (!ret)
+   return -EINVAL;
+
return detect_mst_link_for_all_connectors(adev->ddev);
 }
 
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h 
b/drivers/gpu/drm/amd/display/dc/dc.h
index 18865a76ea55..6b0988310138 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -36,6 +36,7 @@
 
 #include "inc/hw_sequencer.h"
 #include "inc/compressor.h"
+#include "inc/hw/dmcu.h"
 #include "dml/display_mode_lib.h"
 
 #define DC_VER "3.2.06"
@@ -47,13 +48,6 @@
 
/***
  * Display Core Interfaces
  
**/
-struct dmcu_version {
-   unsigned int date;
-   unsigned int month;
-   unsigned int year;
-   unsigned int interface_version;
-};
-
 struct dc_versions {
const char *dc_ver;
struct dmcu_version dmcu_version;
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h 
b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h
index 4550747fb61c..cb85eaa9857f 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h
@@ -32,6 +32,13 @@ enum dmcu_state {
DMCU_RUNNING = 1
 };
 
+struct dmcu_version {
+   unsigned int date;
+   unsigned int month;
+   unsigned int year;
+   unsigned int interface_version;
+};
+
 struct dmcu {
struct dc_context *ctx;
const struct dmcu_funcs *funcs;
diff --git a/drivers/gpu/drm/amd/display/modules/power/Makefile 
b/drivers/gpu/drm/amd/display/modules/power/Makefile
new file mode 100644
index ..87851f892a52
--- /dev/null
+++ b/drivers/gpu/drm/amd/d

[PATCH v2 2/2] drm/amd: Add abm level drm property

2018-11-13 Thread David Francis
Adaptive Backlight Management (ABM) is a feature
that reduces backlight level to save power, while
increasing pixel contrast and pixel luminance
to maintain readability and image quality.

ABM will adjust in response to the
pixel luminance of the displayed content.

ABM is made available as a drm property on eDP
monitors called "abm level", which ranges from 0 to 4.
When this property is set to 0, ABM is off.  Levels 1
to 4 represent different ranges of backlight reduction.
At higher levels both the backlight reduction and pixel
adjustment will be greater.

ABM requires DMCU firmware, which is currently available for
Raven ASICs only.  If the feature does not work, please
ensure your firmware is up to date.

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_display.c   |  5 +++
 drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h  |  2 +
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 38 ---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  1 +
 drivers/gpu/drm/amd/display/dc/core/dc.c  | 11 +-
 drivers/gpu/drm/amd/display/dc/dc.h   |  1 +
 6 files changed, 52 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index 7d6a36bca9dd..ced8cefa223b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -637,6 +637,11 @@ int amdgpu_display_modeset_create_props(struct 
amdgpu_device *adev)
 "freesync_capable");
if (!adev->mode_info.freesync_capable_property)
return -ENOMEM;
+   adev->mode_info.abm_level_property =
+   drm_property_create_range(adev->ddev, 0,
+   "abm level", 0, 4);
+   if (!adev->mode_info.abm_level_property)
+   return -ENOMEM;
}
 
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index 1627dd3413c7..2938635c0fc1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -342,6 +342,8 @@ struct amdgpu_mode_info {
struct drm_property *freesync_property;
/* it is used to know about display capability of freesync mode */
struct drm_property *freesync_capable_property;
+   /* Adaptive Backlight Modulation (power feature) */
+   struct drm_property *abm_level_property;
/* hardcoded DFP edid from BIOS */
struct edid *bios_hardcoded_edid;
int bios_hardcoded_edid_size;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index f71febb4210d..ca1c5e073545 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3038,6 +3038,9 @@ int amdgpu_dm_connector_atomic_set_property(struct 
drm_connector *connector,
} else if (property == adev->mode_info.freesync_capable_property) {
dm_new_state->freesync_capable = val;
ret = 0;
+   } else if (property == adev->mode_info.abm_level_property) {
+   dm_new_state->abm_level = val;
+   ret = 0;
}
 
return ret;
@@ -3086,7 +3089,11 @@ int amdgpu_dm_connector_atomic_get_property(struct 
drm_connector *connector,
} else if (property == adev->mode_info.freesync_capable_property) {
*val = dm_state->freesync_capable;
ret = 0;
+   } else if (property == adev->mode_info.abm_level_property) {
+   *val = dm_state->abm_level;
+   ret = 0;
}
+
return ret;
 }
 
@@ -3151,6 +3158,7 @@ amdgpu_dm_connector_atomic_duplicate_state(struct 
drm_connector *connector)
 
new_state->freesync_capable = state->freesync_capable;
new_state->freesync_enable = state->freesync_enable;
+   new_state->abm_level = state->abm_level;
 
return _state->base;
 }
@@ -3904,6 +3912,12 @@ void amdgpu_dm_connector_init_helper(struct 
amdgpu_display_manager *dm,
drm_object_attach_property(>base.base,
adev->mode_info.freesync_capable_property, 0);
}
+
+   if (connector_type == DRM_MODE_CONNECTOR_eDP &&
+   dc_is_dmcu_initialized(adev->dm.dc)) {
+   drm_object_attach_property(>base.base,
+   adev->mode_info.abm_level_property, 0);
+   }
 }
 
 static int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap,
@@ -4399,7 +4413,8 @@ static bool commit_planes_to_stream(
uint8_t new_plane_count,
struct dm_crtc_state *dm_new_crtc_state,
struct dm_crtc_state *dm_old_crtc_state,
-   

[PATCH 1/2] drm/amd: Load DMCU IRAM

2018-11-13 Thread David Francis
DMCU IRAM must be loaded by the driver before DMCU
can function.

Move the IRAM code out of the shadows and into a new file
modules/power/power_helpers.c

The IRAM table contains the backlight curve and ABM parameters

Add this new file to the Makefiles

Call dmcu_load_iram in late init of DM

Move struct dmcu_version from dc.h to dmcu.h to allow
dmcu to be included on its own

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/display/Makefile  |   3 +-
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  21 ++
 drivers/gpu/drm/amd/display/dc/dc.h   |   8 +-
 drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h  |   7 +
 .../drm/amd/display/modules/power/Makefile|  31 ++
 .../amd/display/modules/power/power_helpers.c | 326 ++
 .../amd/display/modules/power/power_helpers.h |  47 +++
 7 files changed, 435 insertions(+), 8 deletions(-)
 create mode 100644 drivers/gpu/drm/amd/display/modules/power/Makefile
 create mode 100644 drivers/gpu/drm/amd/display/modules/power/power_helpers.c
 create mode 100644 drivers/gpu/drm/amd/display/modules/power/power_helpers.h

diff --git a/drivers/gpu/drm/amd/display/Makefile 
b/drivers/gpu/drm/amd/display/Makefile
index c97dc9613325..cfde1568c79a 100644
--- a/drivers/gpu/drm/amd/display/Makefile
+++ b/drivers/gpu/drm/amd/display/Makefile
@@ -32,11 +32,12 @@ subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/inc
 subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/freesync
 subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/color
 subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/info_packet
+subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/power
 
 #TODO: remove when Timing Sync feature is complete
 subdir-ccflags-y += -DBUILD_FEATURE_TIMING_SYNC=0
 
-DAL_LIBS = amdgpu_dm dcmodules/freesync modules/color 
modules/info_packet
+DAL_LIBS = amdgpu_dm dcmodules/freesync modules/color 
modules/info_packet modules/power
 
 AMD_DAL = $(addsuffix /Makefile, $(addprefix 
$(FULL_AMD_DISPLAY_PATH)/,$(DAL_LIBS)))
 
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 0c1a533eb531..f71febb4210d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -72,6 +72,7 @@
 #endif
 
 #include "modules/inc/mod_freesync.h"
+#include "modules/power/power_helpers.h"
 
 #define FIRMWARE_RAVEN_DMCU"amdgpu/raven_dmcu.bin"
 MODULE_FIRMWARE(FIRMWARE_RAVEN_DMCU);
@@ -643,6 +644,26 @@ static int dm_late_init(void *handle)
 {
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+   struct dmcu_iram_parameters params;
+   unsigned int linear_lut[16];
+   int i;
+   struct dmcu *dmcu = adev->dm.dc->res_pool->dmcu;
+   bool ret;
+
+   for (i = 0; i < 16; i++)
+   linear_lut[i] = 0x * i / 15;
+
+   params.set = 0;
+   params.backlight_ramping_start = 0x;
+   params.backlight_ramping_reduction = 0x;
+   params.backlight_lut_array_size = 16;
+   params.backlight_lut_array = linear_lut;
+
+   ret = dmcu_load_iram(dmcu, params);
+
+   if (!ret)
+   return -EINVAL;
+
return detect_mst_link_for_all_connectors(adev->ddev);
 }
 
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h 
b/drivers/gpu/drm/amd/display/dc/dc.h
index 18865a76ea55..6b0988310138 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -36,6 +36,7 @@
 
 #include "inc/hw_sequencer.h"
 #include "inc/compressor.h"
+#include "inc/hw/dmcu.h"
 #include "dml/display_mode_lib.h"
 
 #define DC_VER "3.2.06"
@@ -47,13 +48,6 @@
 
/***
  * Display Core Interfaces
  
**/
-struct dmcu_version {
-   unsigned int date;
-   unsigned int month;
-   unsigned int year;
-   unsigned int interface_version;
-};
-
 struct dc_versions {
const char *dc_ver;
struct dmcu_version dmcu_version;
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h 
b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h
index 4550747fb61c..cb85eaa9857f 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h
@@ -32,6 +32,13 @@ enum dmcu_state {
DMCU_RUNNING = 1
 };
 
+struct dmcu_version {
+   unsigned int date;
+   unsigned int month;
+   unsigned int year;
+   unsigned int interface_version;
+};
+
 struct dmcu {
struct dc_context *ctx;
const struct dmcu_funcs *funcs;
diff --git a/drivers/gpu/drm/amd/display/modules/power/Makefile 
b/drivers/gpu/drm/amd/display/modules/power/Makefile
new file mode 100644
index ..87851f892a52
--- /dev/null
+++ b/drivers/gpu/drm/amd/d

[PATCH 2/2] drm/amd: Add abm level drm property

2018-11-13 Thread David Francis
Adaptive Backlight Management (ABM) is a feature
that reduces backlight level to save power, while
increasing pixel contrast and pixel luminance
to maintain readability and image quality.

ABM will adjust in response to the
pixel luminance of the displayed content.

ABM is made available as a drm property on eDP
monitors called "abm level", which ranges from 0 to 4.
When this property is set to 0, ABM is off.  Levels 1
to 4 represent different ranges of backlight reduction.
At higher levels both the backlight reduction and pixel
adjustment will be greater.

ABM requires DMCU firmware, which is currently available for
Raven ASICs only.  If the feature does not work, please
ensure your firmware is up to date.drm/amd: Add abm drm property

Adaptive Backlight Management (ABM) is a feature that reduces backlight
and increases contrast to save power.  It is available only on Raven
series ASICs and only on eDP monitors.

This is a new property on amdgpu connectors, with a range of
0 (off) to 4 (severe backlight reduction).

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_display.c   |  5 +++
 drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h  |  2 +
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 37 ---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  1 +
 4 files changed, 40 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index 7d6a36bca9dd..ced8cefa223b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -637,6 +637,11 @@ int amdgpu_display_modeset_create_props(struct 
amdgpu_device *adev)
 "freesync_capable");
if (!adev->mode_info.freesync_capable_property)
return -ENOMEM;
+   adev->mode_info.abm_level_property =
+   drm_property_create_range(adev->ddev, 0,
+   "abm level", 0, 4);
+   if (!adev->mode_info.abm_level_property)
+   return -ENOMEM;
}
 
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index 1627dd3413c7..2938635c0fc1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -342,6 +342,8 @@ struct amdgpu_mode_info {
struct drm_property *freesync_property;
/* it is used to know about display capability of freesync mode */
struct drm_property *freesync_capable_property;
+   /* Adaptive Backlight Modulation (power feature) */
+   struct drm_property *abm_level_property;
/* hardcoded DFP edid from BIOS */
struct edid *bios_hardcoded_edid;
int bios_hardcoded_edid_size;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index f71febb4210d..96d60e735e71 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3038,6 +3038,9 @@ int amdgpu_dm_connector_atomic_set_property(struct 
drm_connector *connector,
} else if (property == adev->mode_info.freesync_capable_property) {
dm_new_state->freesync_capable = val;
ret = 0;
+   } else if (property == adev->mode_info.abm_level_property) {
+   dm_new_state->abm_level = val;
+   ret = 0;
}
 
return ret;
@@ -3086,7 +3089,11 @@ int amdgpu_dm_connector_atomic_get_property(struct 
drm_connector *connector,
} else if (property == adev->mode_info.freesync_capable_property) {
*val = dm_state->freesync_capable;
ret = 0;
+   } else if (property == adev->mode_info.abm_level_property) {
+   *val = dm_state->abm_level;
+   ret = 0;
}
+
return ret;
 }
 
@@ -3151,6 +3158,7 @@ amdgpu_dm_connector_atomic_duplicate_state(struct 
drm_connector *connector)
 
new_state->freesync_capable = state->freesync_capable;
new_state->freesync_enable = state->freesync_enable;
+   new_state->abm_level = state->abm_level;
 
return _state->base;
 }
@@ -3904,6 +3912,11 @@ void amdgpu_dm_connector_init_helper(struct 
amdgpu_display_manager *dm,
drm_object_attach_property(>base.base,
adev->mode_info.freesync_capable_property, 0);
}
+
+   if (connector_type == DRM_MODE_CONNECTOR_eDP) {
+   drm_object_attach_property(>base.base,
+   adev->mode_info.abm_level_property, 0);
+   }
 }
 
 static int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap,
@@ -4399,7 +4412,8 @@ static bool commit_planes_to_stream(
uint8_t new_plane_c

[PATCH] drm/amd: update ATIF functions in AMD ACPI header

2018-11-08 Thread David Francis
The ACPI interface in AMD was a few years out of date
and contained some unused and deprecated functions

Remove functions: Select Active Displays, Get Lid State,
Get TV Standard, Set TV Standard, Get Panel Expansion Mode,
Set Panel Expansion Mode, Get Graphics Device Types

Add functions: Query Backlight Transfer Characteristics,
Ready To Undock Notification

Changed functions: Get System Parameters,
Get System BIOS Requests

All changes are right from the standard
ATI ACPI Control Methods V0.44

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c |  31 ++---
 drivers/gpu/drm/amd/include/amd_acpi.h   | 151 +++
 2 files changed, 56 insertions(+), 126 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
index 7f0afc526419..471266901d1b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
@@ -41,28 +41,21 @@ struct amdgpu_atif_notification_cfg {
 };
 
 struct amdgpu_atif_notifications {
-   bool display_switch;
-   bool expansion_mode_change;
bool thermal_state;
bool forced_power_state;
bool system_power_state;
-   bool display_conf_change;
-   bool px_gfx_switch;
bool brightness_change;
bool dgpu_display_event;
+   bool gpu_package_power_limit;
 };
 
 struct amdgpu_atif_functions {
bool system_params;
bool sbios_requests;
-   bool select_active_disp;
-   bool lid_state;
-   bool get_tv_standard;
-   bool set_tv_standard;
-   bool get_panel_expansion_mode;
-   bool set_panel_expansion_mode;
bool temperature_change;
-   bool graphics_device_types;
+   bool query_backlight_transfer_characteristics;
+   bool ready_to_undock;
+   bool external_gpu_information;
 };
 
 struct amdgpu_atif {
@@ -137,15 +130,12 @@ static union acpi_object *amdgpu_atif_call(struct 
amdgpu_atif *atif,
  */
 static void amdgpu_atif_parse_notification(struct amdgpu_atif_notifications 
*n, u32 mask)
 {
-   n->display_switch = mask & ATIF_DISPLAY_SWITCH_REQUEST_SUPPORTED;
-   n->expansion_mode_change = mask & 
ATIF_EXPANSION_MODE_CHANGE_REQUEST_SUPPORTED;
n->thermal_state = mask & ATIF_THERMAL_STATE_CHANGE_REQUEST_SUPPORTED;
n->forced_power_state = mask & 
ATIF_FORCED_POWER_STATE_CHANGE_REQUEST_SUPPORTED;
n->system_power_state = mask & 
ATIF_SYSTEM_POWER_SOURCE_CHANGE_REQUEST_SUPPORTED;
-   n->display_conf_change = mask & 
ATIF_DISPLAY_CONF_CHANGE_REQUEST_SUPPORTED;
-   n->px_gfx_switch = mask & ATIF_PX_GFX_SWITCH_REQUEST_SUPPORTED;
n->brightness_change = mask & 
ATIF_PANEL_BRIGHTNESS_CHANGE_REQUEST_SUPPORTED;
n->dgpu_display_event = mask & ATIF_DGPU_DISPLAY_EVENT_SUPPORTED;
+   n->gpu_package_power_limit = mask & 
ATIF_GPU_PACKAGE_POWER_LIMIT_REQUEST_SUPPORTED;
 }
 
 /**
@@ -162,14 +152,11 @@ static void amdgpu_atif_parse_functions(struct 
amdgpu_atif_functions *f, u32 mas
 {
f->system_params = mask & ATIF_GET_SYSTEM_PARAMETERS_SUPPORTED;
f->sbios_requests = mask & ATIF_GET_SYSTEM_BIOS_REQUESTS_SUPPORTED;
-   f->select_active_disp = mask & ATIF_SELECT_ACTIVE_DISPLAYS_SUPPORTED;
-   f->lid_state = mask & ATIF_GET_LID_STATE_SUPPORTED;
-   f->get_tv_standard = mask & ATIF_GET_TV_STANDARD_FROM_CMOS_SUPPORTED;
-   f->set_tv_standard = mask & ATIF_SET_TV_STANDARD_IN_CMOS_SUPPORTED;
-   f->get_panel_expansion_mode = mask & 
ATIF_GET_PANEL_EXPANSION_MODE_FROM_CMOS_SUPPORTED;
-   f->set_panel_expansion_mode = mask & 
ATIF_SET_PANEL_EXPANSION_MODE_IN_CMOS_SUPPORTED;
f->temperature_change = mask & 
ATIF_TEMPERATURE_CHANGE_NOTIFICATION_SUPPORTED;
-   f->graphics_device_types = mask & 
ATIF_GET_GRAPHICS_DEVICE_TYPES_SUPPORTED;
+   f->query_backlight_transfer_characteristics =
+   mask & ATIF_QUERY_BACKLIGHT_TRANSFER_CHARACTERISTICS_SUPPORTED;
+   f->ready_to_undock = mask & ATIF_READY_TO_UNDOCK_NOTIFICATION_SUPPORTED;
+   f->external_gpu_information = mask & 
ATIF_GET_EXTERNAL_GPU_INFORMATION_SUPPORTED;
 }
 
 /**
diff --git a/drivers/gpu/drm/amd/include/amd_acpi.h 
b/drivers/gpu/drm/amd/include/amd_acpi.h
index 9b9699fc433f..8980edfe5fa9 100644
--- a/drivers/gpu/drm/amd/include/amd_acpi.h
+++ b/drivers/gpu/drm/amd/include/amd_acpi.h
@@ -126,26 +126,18 @@ struct atcs_pref_req_output {
  * DWORD - supported functions bit vector
  */
 /* Notifications mask */
-#   define ATIF_DISPLAY_SWITCH_REQUEST_SUPPORTED   (1 << 0)
-#   define ATIF_EXPANSION_MODE_CHANGE_REQUEST_SUPPORTED(1 << 1)
 #   define ATIF_THERMAL_STATE_CHANGE_REQUEST_SUPPORTED (1 << 2)
 #   define ATIF_FORCED_POWER_STATE_CHANGE_REQUEST_SUPPORTED   

  1   2   >