[PATCH] amd/include: Move register declarations from display to include/asic_reg

2018-05-31 Thread David Francis
A few register addresses were declared in
amd/display/dc/dce*/dce*_resource.c.

They have been consolidated with the appropriate
master list of registers in
amd/include/asic_reg/dce/...

This will make them accessible to external tools that
need direct asic register access

Signed-off-by: David Francis 
---
 .../amd/display/dc/dce100/dce100_resource.c   | 35 ---
 .../amd/display/dc/dce110/dce110_resource.c   | 35 ---
 .../amd/display/dc/dce112/dce112_resource.c   | 35 ---
 .../drm/amd/display/dc/dce80/dce80_resource.c | 34 --
 .../drm/amd/include/asic_reg/dce/dce_10_0_d.h | 18 ++
 .../drm/amd/include/asic_reg/dce/dce_11_0_d.h | 10 ++
 .../drm/amd/include/asic_reg/dce/dce_11_2_d.h | 10 ++
 .../drm/amd/include/asic_reg/dce/dce_8_0_d.h  | 15 
 8 files changed, 53 insertions(+), 139 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c 
b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c
index 38ec0d609297..7615668a78e9 100644
--- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c
@@ -59,46 +59,11 @@
 #include "gmc/gmc_8_2_sh_mask.h"
 #endif
 
-#ifndef mmDP_DPHY_INTERNAL_CTRL
-   #define mmDP_DPHY_INTERNAL_CTRL 0x4aa7
-   #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x4aa7
-   #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x4ba7
-   #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x4ca7
-   #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x4da7
-   #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x4ea7
-   #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4fa7
-   #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x54a7
-   #define mmDP7_DP_DPHY_INTERNAL_CTRL 0x56a7
-   #define mmDP8_DP_DPHY_INTERNAL_CTRL 0x57a7
-#endif
-
 #ifndef mmBIOS_SCRATCH_2
#define mmBIOS_SCRATCH_2 0x05CB
#define mmBIOS_SCRATCH_6 0x05CF
 #endif
 
-#ifndef mmDP_DPHY_BS_SR_SWAP_CNTL
-   #define mmDP_DPHY_BS_SR_SWAP_CNTL   0x4ADC
-   #define mmDP0_DP_DPHY_BS_SR_SWAP_CNTL   0x4ADC
-   #define mmDP1_DP_DPHY_BS_SR_SWAP_CNTL   0x4BDC
-   #define mmDP2_DP_DPHY_BS_SR_SWAP_CNTL   0x4CDC
-   #define mmDP3_DP_DPHY_BS_SR_SWAP_CNTL   0x4DDC
-   #define mmDP4_DP_DPHY_BS_SR_SWAP_CNTL   0x4EDC
-   #define mmDP5_DP_DPHY_BS_SR_SWAP_CNTL   0x4FDC
-   #define mmDP6_DP_DPHY_BS_SR_SWAP_CNTL   0x54DC
-#endif
-
-#ifndef mmDP_DPHY_FAST_TRAINING
-   #define mmDP_DPHY_FAST_TRAINING 0x4ABC
-   #define mmDP0_DP_DPHY_FAST_TRAINING 0x4ABC
-   #define mmDP1_DP_DPHY_FAST_TRAINING 0x4BBC
-   #define mmDP2_DP_DPHY_FAST_TRAINING 0x4CBC
-   #define mmDP3_DP_DPHY_FAST_TRAINING 0x4DBC
-   #define mmDP4_DP_DPHY_FAST_TRAINING 0x4EBC
-   #define mmDP5_DP_DPHY_FAST_TRAINING 0x4FBC
-   #define mmDP6_DP_DPHY_FAST_TRAINING 0x54BC
-#endif
-
 static const struct dce110_timing_generator_offsets dce100_tg_offsets[] = {
{
.crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC_CONTROL),
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c 
b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c
index ee33786bdef6..648187a28671 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c
@@ -68,46 +68,11 @@
 #include "gmc/gmc_8_2_sh_mask.h"
 #endif
 
-#ifndef mmDP_DPHY_INTERNAL_CTRL
-   #define mmDP_DPHY_INTERNAL_CTRL 0x4aa7
-   #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x4aa7
-   #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x4ba7
-   #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x4ca7
-   #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x4da7
-   #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x4ea7
-   #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4fa7
-   #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x54a7
-   #define mmDP7_DP_DPHY_INTERNAL_CTRL 0x56a7
-   #define mmDP8_DP_DPHY_INTERNAL_CTRL 0x57a7
-#endif
-
 #ifndef mmBIOS_SCRATCH_2
#define mmBIOS_SCRATCH_2 0x05CB
#define mmBIOS_SCRATCH_6 0x05CF
 #endif
 
-#ifndef mmDP_DPHY_BS_SR_SWAP_CNTL
-   #define mmDP_DPHY_BS_SR_SWAP_CNTL   0x4ADC
-   #define mmDP0_DP_DPHY_BS_SR_SWAP_CNTL   0x4ADC
-   #define mmDP1_DP_DPHY_BS_SR_SWAP_CNTL   0x4BDC
-   #define mmDP2_DP_DPHY_BS_SR_SWAP_CNTL   0x4CDC
-   #define mmDP3_DP_DPHY_BS_SR_SWAP_CNTL   0x4DDC
-   #define mmDP4_DP_DPHY_BS_SR_SWAP_CNTL   0x4EDC
-   #define mmDP5_DP_DPHY_BS_SR_SWAP_CNTL   0x4FDC
-   #define mmDP6_DP_DPHY_BS_SR_SWAP_CNTL   0x54DC
-#endif
-
-#ifndef mmDP_DPHY_FAST_TRAINING
-   #define mmD

[PATCH] drm/amd: Add DMCU firmware loading on raven

2018-09-07 Thread David Francis
[Why]
DMCU (Display MicroController Unit) is an on-GPU microcontroller
in AMD graphics cards that is used in features for
embedded displays such as Panel Self-Refresh

DMCU is part of the DM IP block

[How]
DMCU is added as an option in the enum AMDGPU_UCODE_ID

DMCU needs two pieces of firmware - the initial eram and the
interrupt vectors.  These are treated as seperate pieces of
firmware and loaded by PSP

The loading occurs in the sw_init hook of DM

If the firmware is not found, the sw_init hook returns without error.
DMCU is not a requirement for DM to run.

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h |  2 +
 drivers/gpu/drm/amd/amdgpu/psp_v10_0.c|  6 ++
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 98 +++
 3 files changed, 106 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
index b358e7519987..38d3af317aa2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
@@ -196,6 +196,8 @@ enum AMDGPU_UCODE_ID {
AMDGPU_UCODE_ID_UVD1,
AMDGPU_UCODE_ID_VCE,
AMDGPU_UCODE_ID_VCN,
+   AMDGPU_UCODE_ID_DMCU_ERAM,
+   AMDGPU_UCODE_ID_DMCU_INTV,
AMDGPU_UCODE_ID_MAXIMUM,
 };
 
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c 
b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
index 02be34e72ed9..240dc8c85867 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
@@ -91,6 +91,12 @@ psp_v10_0_get_fw_type(struct amdgpu_firmware_info *ucode, 
enum psp_gfx_fw_type *
case AMDGPU_UCODE_ID_VCN:
*type = GFX_FW_TYPE_VCN;
break;
+   case AMDGPU_UCODE_ID_DMCU_ERAM:
+   *type = GFX_FW_TYPE_DMCU_ERAM;
+   break;
+   case AMDGPU_UCODE_ID_DMCU_INTV:
+   *type = GFX_FW_TYPE_DMCU_ISR;
+   break;
case AMDGPU_UCODE_ID_MAXIMUM:
default:
return -EINVAL;
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 5103eba75cb3..8ad0ee359ef8 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -30,6 +30,7 @@
 #include "vid.h"
 #include "amdgpu.h"
 #include "amdgpu_display.h"
+#include "amdgpu_ucode.h"
 #include "atom.h"
 #include "amdgpu_dm.h"
 #include "amdgpu_pm.h"
@@ -50,6 +51,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -71,6 +73,12 @@
 
 #include "modules/inc/mod_freesync.h"
 
+#define FIRMWARE_RAVEN_DMCU_ERAM   "amdgpu/raven_dmcu_eram.bin"
+MODULE_FIRMWARE(FIRMWARE_RAVEN_DMCU_ERAM);
+
+#define FIRMWARE_RAVEN_DMCU_INTV   "amdgpu/raven_dmcu_intv.bin"
+MODULE_FIRMWARE(FIRMWARE_RAVEN_DMCU_INTV);
+
 /* basic init/fini API */
 static int amdgpu_dm_init(struct amdgpu_device *adev);
 static void amdgpu_dm_fini(struct amdgpu_device *adev);
@@ -516,6 +524,96 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
 
 static int dm_sw_init(void *handle)
 {
+   const struct firmware *fw;
+   const char *fw_name_dmcu_eram;
+   const char *fw_name_dmcu_intv;
+   struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+   int r;
+
+   switch(adev->asic_type) {
+   case CHIP_BONAIRE:
+   case CHIP_HAWAII:
+   case CHIP_KAVERI:
+   case CHIP_KABINI:
+   case CHIP_MULLINS:
+   case CHIP_TONGA:
+   case CHIP_FIJI:
+   case CHIP_CARRIZO:
+   case CHIP_STONEY:
+   case CHIP_POLARIS11:
+   case CHIP_POLARIS10:
+   case CHIP_POLARIS12:
+   case CHIP_VEGAM:
+   case CHIP_VEGA10:
+   case CHIP_VEGA12:
+   case CHIP_VEGA20:
+   return 0;
+   case CHIP_RAVEN:
+   fw_name_dmcu_eram = FIRMWARE_RAVEN_DMCU_ERAM;
+   fw_name_dmcu_intv = FIRMWARE_RAVEN_DMCU_INTV;
+   break;
+   default:
+   DRM_ERROR("Unsupported ASIC type: 0x%X\n", adev->asic_type);
+   return -1;
+   }
+
+   r = request_firmware(, fw_name_dmcu_eram, adev->dev);
+   if (r == -ENOENT)
+   {
+   /* DMCU firmware is not necessary, so don't raise a fuss if 
it's missing */
+   return 0;
+   }
+   if (r) {
+   dev_err(adev->dev, "amdgpu_dm: Can't load firmware \"%s\"\n",
+   fw_name_dmcu_eram);
+   return r;
+   }
+
+   r = amdgpu_ucode_validate(fw);
+   if (r) {
+   dev_err(adev->dev, "amdgpu_dm: Can't validate firmware 
\"%s\"\n",
+   fw_name_dmcu_eram);
+   release_firmware(fw);
+   fw = NULL;
+   return r;
+   }
+
+   if (adev->fir

[PATCH] drm/amd: Add DMCU firmware loading on raven

2018-09-07 Thread David Francis
[Why]
DMCU (Display MicroController Unit) is an on-GPU microcontroller
in AMD graphics cards that is used in features for
embedded displays such as Panel Self-Refresh

DMCU is part of the DM IP block

[How]
DMCU is added as an option in the enum AMDGPU_UCODE_ID

DMCU needs two pieces of firmware - the initial eram and the
interrupt vectors.  These are treated as seperate pieces of
firmware and loaded by PSP

The loading occurs in the sw_init hook of DM

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h |  2 +
 drivers/gpu/drm/amd/amdgpu/psp_v10_0.c|  6 ++
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 93 +++
 3 files changed, 101 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
index b358e7519987..38d3af317aa2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
@@ -196,6 +196,8 @@ enum AMDGPU_UCODE_ID {
AMDGPU_UCODE_ID_UVD1,
AMDGPU_UCODE_ID_VCE,
AMDGPU_UCODE_ID_VCN,
+   AMDGPU_UCODE_ID_DMCU_ERAM,
+   AMDGPU_UCODE_ID_DMCU_INTV,
AMDGPU_UCODE_ID_MAXIMUM,
 };
 
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c 
b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
index 02be34e72ed9..240dc8c85867 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
@@ -91,6 +91,12 @@ psp_v10_0_get_fw_type(struct amdgpu_firmware_info *ucode, 
enum psp_gfx_fw_type *
case AMDGPU_UCODE_ID_VCN:
*type = GFX_FW_TYPE_VCN;
break;
+   case AMDGPU_UCODE_ID_DMCU_ERAM:
+   *type = GFX_FW_TYPE_DMCU_ERAM;
+   break;
+   case AMDGPU_UCODE_ID_DMCU_INTV:
+   *type = GFX_FW_TYPE_DMCU_ISR;
+   break;
case AMDGPU_UCODE_ID_MAXIMUM:
default:
return -EINVAL;
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 5103eba75cb3..4619f624f346 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -30,6 +30,7 @@
 #include "vid.h"
 #include "amdgpu.h"
 #include "amdgpu_display.h"
+#include "amdgpu_ucode.h"
 #include "atom.h"
 #include "amdgpu_dm.h"
 #include "amdgpu_pm.h"
@@ -50,6 +51,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -71,6 +73,12 @@
 
 #include "modules/inc/mod_freesync.h"
 
+#define FIRMWARE_RAVEN_DMCU_ERAM   "amdgpu/raven_dmcu_eram.bin"
+MODULE_FIRMWARE(FIRMWARE_RAVEN_DMCU_ERAM);
+
+#define FIRMWARE_RAVEN_DMCU_INTV   "amdgpu/raven_dmcu_intv.bin"
+MODULE_FIRMWARE(FIRMWARE_RAVEN_DMCU_INTV);
+
 /* basic init/fini API */
 static int amdgpu_dm_init(struct amdgpu_device *adev);
 static void amdgpu_dm_fini(struct amdgpu_device *adev);
@@ -516,6 +524,91 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
 
 static int dm_sw_init(void *handle)
 {
+   const struct firmware *fw;
+   const char *fw_name_dmcu_eram;
+   const char *fw_name_dmcu_intv;
+   struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+   int r;
+
+   switch(adev->asic_type) {
+   case CHIP_BONAIRE:
+   case CHIP_HAWAII:
+   case CHIP_KAVERI:
+   case CHIP_KABINI:
+   case CHIP_MULLINS:
+   case CHIP_TONGA:
+   case CHIP_FIJI:
+   case CHIP_CARRIZO:
+   case CHIP_STONEY:
+   case CHIP_POLARIS11:
+   case CHIP_POLARIS10:
+   case CHIP_POLARIS12:
+   case CHIP_VEGAM:
+   case CHIP_VEGA10:
+   case CHIP_VEGA12:
+   case CHIP_VEGA20:
+   return 0;
+   case CHIP_RAVEN:
+   fw_name_dmcu_eram = FIRMWARE_RAVEN_DMCU_ERAM;
+   fw_name_dmcu_intv = FIRMWARE_RAVEN_DMCU_INTV;
+   break;
+   default:
+   DRM_ERROR("Unsupported ASIC type: 0x%X\n", adev->asic_type);
+   return -1;
+   }
+
+   r = request_firmware(, fw_name_dmcu_eram, adev->dev);
+   if (r) {
+   dev_err(adev->dev, "amdgpu_dm: Can't load firmware \"%s\"\n",
+   fw_name_dmcu_eram);
+   return r;
+   }
+
+   r = amdgpu_ucode_validate(fw);
+   if (r) {
+   dev_err(adev->dev, "amdgpu_dm: Can't validate firmware 
\"%s\"\n",
+   fw_name_dmcu_eram);
+   release_firmware(fw);
+   fw = NULL;
+   return r;
+   }
+
+   if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
+   const struct common_firmware_header *hdr;
+   hdr = (const struct common_firmware_header *)fw->data;
+   adev->firmware.ucode[AMDGPU_UCODE_ID_DMCU_ERAM].ucode_id = 
AMDGPU_UCODE_

[PATCH v2] drm/amd: Add DMCU firmware loading on raven

2018-09-07 Thread David Francis
[Why]
DMCU (Display MicroController Unit) is an on-GPU microcontroller
in AMD graphics cards that is used in features for
embedded displays such as Panel Self-Refresh

DMCU is part of the DM IP block

[How]
DMCU is added as an option in the enum AMDGPU_UCODE_ID

DMCU needs two pieces of firmware - the initial eram and the
interrupt vectors.  These are treated as seperate pieces of
firmware and loaded by PSP

The loading occurs in the sw_init hook of DM

If the firmware is not found, the sw_init hook returns without error.
DMCU is not a requirement for DM to run.

v2: Move dmcu firmware loading into its own function, properly
release firmware, add debug messages

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h |   2 +
 drivers/gpu/drm/amd/amdgpu/psp_v10_0.c|   6 +
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 114 +-
 3 files changed, 121 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
index b358e7519987..38d3af317aa2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
@@ -196,6 +196,8 @@ enum AMDGPU_UCODE_ID {
AMDGPU_UCODE_ID_UVD1,
AMDGPU_UCODE_ID_VCE,
AMDGPU_UCODE_ID_VCN,
+   AMDGPU_UCODE_ID_DMCU_ERAM,
+   AMDGPU_UCODE_ID_DMCU_INTV,
AMDGPU_UCODE_ID_MAXIMUM,
 };
 
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c 
b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
index 02be34e72ed9..240dc8c85867 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
@@ -91,6 +91,12 @@ psp_v10_0_get_fw_type(struct amdgpu_firmware_info *ucode, 
enum psp_gfx_fw_type *
case AMDGPU_UCODE_ID_VCN:
*type = GFX_FW_TYPE_VCN;
break;
+   case AMDGPU_UCODE_ID_DMCU_ERAM:
+   *type = GFX_FW_TYPE_DMCU_ERAM;
+   break;
+   case AMDGPU_UCODE_ID_DMCU_INTV:
+   *type = GFX_FW_TYPE_DMCU_ISR;
+   break;
case AMDGPU_UCODE_ID_MAXIMUM:
default:
return -EINVAL;
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 5103eba75cb3..016da243dde8 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -30,6 +30,7 @@
 #include "vid.h"
 #include "amdgpu.h"
 #include "amdgpu_display.h"
+#include "amdgpu_ucode.h"
 #include "atom.h"
 #include "amdgpu_dm.h"
 #include "amdgpu_pm.h"
@@ -50,6 +51,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -71,6 +73,12 @@
 
 #include "modules/inc/mod_freesync.h"
 
+#define FIRMWARE_RAVEN_DMCU_ERAM   "amdgpu/raven_dmcu_eram.bin"
+MODULE_FIRMWARE(FIRMWARE_RAVEN_DMCU_ERAM);
+
+#define FIRMWARE_RAVEN_DMCU_INTV   "amdgpu/raven_dmcu_intv.bin"
+MODULE_FIRMWARE(FIRMWARE_RAVEN_DMCU_INTV);
+
 /* basic init/fini API */
 static int amdgpu_dm_init(struct amdgpu_device *adev);
 static void amdgpu_dm_fini(struct amdgpu_device *adev);
@@ -514,11 +522,115 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
return;
 }
 
-static int dm_sw_init(void *handle)
+static int load_dmcu_fw(struct amdgpu_device *adev)
 {
+   const struct firmware *fw;
+   const char *fw_name_dmcu_eram;
+   const char *fw_name_dmcu_intv;
+   int r;
+   const struct common_firmware_header *hdr;
+
+   switch(adev->asic_type) {
+   case CHIP_BONAIRE:
+   case CHIP_HAWAII:
+   case CHIP_KAVERI:
+   case CHIP_KABINI:
+   case CHIP_MULLINS:
+   case CHIP_TONGA:
+   case CHIP_FIJI:
+   case CHIP_CARRIZO:
+   case CHIP_STONEY:
+   case CHIP_POLARIS11:
+   case CHIP_POLARIS10:
+   case CHIP_POLARIS12:
+   case CHIP_VEGAM:
+   case CHIP_VEGA10:
+   case CHIP_VEGA12:
+   case CHIP_VEGA20:
+   return 0;
+   case CHIP_RAVEN:
+   fw_name_dmcu_eram = FIRMWARE_RAVEN_DMCU_ERAM;
+   fw_name_dmcu_intv = FIRMWARE_RAVEN_DMCU_INTV;
+   break;
+   default:
+   DRM_ERROR("Unsupported ASIC type: 0x%X\n", adev->asic_type);
+   return -1;
+   }
+
+   if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
+   {
+   DRM_DEBUG_KMS("dm: DMCU firmware not supported on direct or SMU 
loading\n");
+   return 0;
+   }
+
+   r = request_firmware(, fw_name_dmcu_eram, adev->dev);
+   if (r == -ENOENT)
+   {
+   /* DMCU firmware is not necessary, so don't raise a fuss if 
it's missing */
+   DRM_DEBUG_KMS("dm: DMCU firmware not found\n");
+   return 0;
+   }
+   if (r) {
+   dev_err(adev->dev, "amdgpu_dm:

[PATCH] amd/dc/dce100: On dce100, set clocks to 0 on suspend

2018-07-12 Thread David Francis
[Why]
When a dce100 asic was suspended, the clocks were not set to 0.
Upon resume, the new clock was compared to the existing clock,
they were found to be the same, and so the clock was not set.
This resulted in a pernicious blackscreen.

[How]
In atomic commit, check to see if there are any active pipes.
If no, set clocks to 0

Signed-off-by: David Francis 
---
 .../amd/display/dc/dce100/dce100_resource.c   | 19 ---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c 
b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c
index 8ed8eace42be..ad8ad4e1437c 100644
--- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c
@@ -678,9 +678,22 @@ bool dce100_validate_bandwidth(
struct dc  *dc,
struct dc_state *context)
 {
-   /* TODO implement when needed but for now hardcode max value*/
-   context->bw.dce.dispclk_khz = 681000;
-   context->bw.dce.yclk_khz = 25 * MEMORY_TYPE_MULTIPLIER;
+   int i;
+   bool at_least_one_pipe = false;
+
+   for (i = 0; i < dc->res_pool->pipe_count; i++) {
+   if (context->res_ctx.pipe_ctx[i].stream)
+   at_least_one_pipe = true;
+   }
+
+   if (at_least_one_pipe) {
+   /* TODO implement when needed but for now hardcode max value*/
+   context->bw.dce.dispclk_khz = 681000;
+   context->bw.dce.yclk_khz = 25 * MEMORY_TYPE_MULTIPLIER;
+   } else {
+   context->bw.dce.dispclk_khz = 0;
+   context->bw.dce.yclk_khz = 0;
+   }
 
return true;
 }
-- 
2.17.1

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


[PATCH v3] drm/amd: Add DMCU firmware loading on raven

2018-09-11 Thread David Francis
[Why]
DMCU (Display MicroController Unit) is an on-GPU microcontroller
in AMD graphics cards that is used in features for
embedded displays such as Panel Self-Refresh

DMCU is part of the DM IP block

[How]
DMCU is added as an option in the enum AMDGPU_UCODE_ID

DMCU needs two pieces of firmware - the initial eram and the
interrupt vectors.  These are treated as seperate pieces of
firmware and loaded by PSP

The loading occurs in the sw_init hook of DM

If the firmware is not found, the sw_init hook returns without error.
DMCU is not a requirement for DM to run.

v2: Move dmcu firmware loading into its own function, properly
release firmware, add debug messages

v3: Use one binary file which contains both firmware pieces

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 21 -
 drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h | 10 ++
 drivers/gpu/drm/amd/amdgpu/psp_v10_0.c|  6 ++
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 94 ++-
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  2 +
 5 files changed, 130 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
index a942fd28dae8..3b1af1cecf14 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
@@ -322,6 +322,7 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_device 
*adev,
 {
const struct common_firmware_header *header = NULL;
const struct gfx_firmware_header_v1_0 *cp_hdr = NULL;
+   const struct dmcu_firmware_header_v1_0 *dmcu_hdr = NULL;
 
if (NULL == ucode->fw)
return 0;
@@ -333,8 +334,8 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_device 
*adev,
return 0;
 
header = (const struct common_firmware_header *)ucode->fw->data;
-
cp_hdr = (const struct gfx_firmware_header_v1_0 *)ucode->fw->data;
+   dmcu_hdr = (const struct dmcu_firmware_header_v1_0 *)ucode->fw->data;
 
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP ||
(ucode->ucode_id != AMDGPU_UCODE_ID_CP_MEC1 &&
@@ -343,7 +344,9 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_device 
*adev,
 ucode->ucode_id != AMDGPU_UCODE_ID_CP_MEC2_JT &&
 ucode->ucode_id != AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL &&
 ucode->ucode_id != AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM &&
-ucode->ucode_id != AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM)) {
+ucode->ucode_id != AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM &&
+ucode->ucode_id != AMDGPU_UCODE_ID_DMCU_ERAM &&
+ucode->ucode_id != AMDGPU_UCODE_ID_DMCU_INTV)) {
ucode->ucode_size = le32_to_cpu(header->ucode_size_bytes);
 
memcpy(ucode->kaddr, (void *)((uint8_t *)ucode->fw->data +
@@ -365,6 +368,20 @@ static int amdgpu_ucode_init_single_fw(struct 
amdgpu_device *adev,
  
le32_to_cpu(header->ucode_array_offset_bytes) +
  le32_to_cpu(cp_hdr->jt_offset) * 
4),
   ucode->ucode_size);
+   } else if (ucode->ucode_id == AMDGPU_UCODE_ID_DMCU_ERAM) {
+   ucode->ucode_size = le32_to_cpu(header->ucode_size_bytes) -
+   le32_to_cpu(dmcu_hdr->intv_size) * 4;
+
+   memcpy(ucode->kaddr, (void *)((uint8_t *)ucode->fw->data +
+ 
le32_to_cpu(header->ucode_array_offset_bytes)),
+  ucode->ucode_size);
+   } else if (ucode->ucode_id == AMDGPU_UCODE_ID_DMCU_INTV) {
+   ucode->ucode_size = le32_to_cpu(dmcu_hdr->intv_size) * 4;
+
+   memcpy(ucode->kaddr, (void *)((uint8_t *)ucode->fw->data +
+ 
le32_to_cpu(header->ucode_array_offset_bytes) +
+ 
le32_to_cpu(dmcu_hdr->intv_offset) * 4),
+  ucode->ucode_size);
} else if (ucode->ucode_id == AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL) {
ucode->ucode_size = 
adev->gfx.rlc.save_restore_list_cntl_size_bytes;
memcpy(ucode->kaddr, adev->gfx.rlc.save_restore_list_cntl,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
index b358e7519987..13bd540709b6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
@@ -157,6 +157,13 @@ struct gpu_info_firmware_header_v1_0 {
uint16_t version_minor; /* version */
 };
 
+/* version_major=1, version_minor=0 */
+struct dmcu_firmware_header_v1_0 {
+   struct common_firmware_header header;
+   uint3

[PATCH 1/2] drm/amdgpu: Stop dividing watermarks by 1000 in powerplay

2018-10-30 Thread David Francis
Watermarks were being multiplied by 1000 in amdgpu_dm
and divided by 1000 in powerplay.  Change watermarks
to units of mhz to stop doing that.

Signed-off-by: David Francis 
---
 .../amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c  | 24 +-
 .../drm/amd/display/dc/dm_services_types.h| 16 +-
 .../gpu/drm/amd/powerplay/hwmgr/smu_helper.c  | 32 +--
 3 files changed, 24 insertions(+), 48 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
index 9d2d6986b983..d9daa038fdb2 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
@@ -517,14 +517,10 @@ void pp_rv_set_wm_ranges(struct pp_smu *pp,
else
wm_dce_clocks[i].wm_set_id =
ranges->reader_wm_sets[i].wm_inst;
-   wm_dce_clocks[i].wm_max_dcfclk_clk_in_khz =
-   ranges->reader_wm_sets[i].max_drain_clk_mhz * 
1000;
-   wm_dce_clocks[i].wm_min_dcfclk_clk_in_khz =
-   ranges->reader_wm_sets[i].min_drain_clk_mhz * 
1000;
-   wm_dce_clocks[i].wm_max_mem_clk_in_khz =
-   ranges->reader_wm_sets[i].max_fill_clk_mhz * 
1000;
-   wm_dce_clocks[i].wm_min_mem_clk_in_khz =
-   ranges->reader_wm_sets[i].min_fill_clk_mhz * 
1000;
+   wm_dce_clocks[i].wm_max_dcfclk_clk_in_mhz = 
ranges->reader_wm_sets[i].max_drain_clk_mhz;
+   wm_dce_clocks[i].wm_min_dcfclk_clk_in_mhz = 
ranges->reader_wm_sets[i].min_drain_clk_mhz;
+   wm_dce_clocks[i].wm_max_mem_clk_in_mhz = 
ranges->reader_wm_sets[i].max_fill_clk_mhz;
+   wm_dce_clocks[i].wm_min_mem_clk_in_mhz = 
ranges->reader_wm_sets[i].min_fill_clk_mhz;
}
 
for (i = 0; i < wm_with_clock_ranges.num_wm_mcif_sets; i++) {
@@ -533,14 +529,10 @@ void pp_rv_set_wm_ranges(struct pp_smu *pp,
else
wm_soc_clocks[i].wm_set_id =
ranges->writer_wm_sets[i].wm_inst;
-   wm_soc_clocks[i].wm_max_socclk_clk_in_khz =
-   ranges->writer_wm_sets[i].max_fill_clk_mhz * 
1000;
-   wm_soc_clocks[i].wm_min_socclk_clk_in_khz =
-   ranges->writer_wm_sets[i].min_fill_clk_mhz * 
1000;
-   wm_soc_clocks[i].wm_max_mem_clk_in_khz =
-   ranges->writer_wm_sets[i].max_drain_clk_mhz * 
1000;
-   wm_soc_clocks[i].wm_min_mem_clk_in_khz =
-   ranges->writer_wm_sets[i].min_drain_clk_mhz * 
1000;
+   wm_soc_clocks[i].wm_max_socclk_clk_in_mhz = 
ranges->writer_wm_sets[i].max_fill_clk_mhz;
+   wm_soc_clocks[i].wm_min_socclk_clk_in_mhz = 
ranges->writer_wm_sets[i].min_fill_clk_mhz;
+   wm_soc_clocks[i].wm_max_mem_clk_in_mhz = 
ranges->writer_wm_sets[i].max_drain_clk_mhz;
+   wm_soc_clocks[i].wm_min_mem_clk_in_mhz = 
ranges->writer_wm_sets[i].min_drain_clk_mhz;
}
 
pp_funcs->set_watermarks_for_clocks_ranges(pp_handle, 
_with_clock_ranges);
diff --git a/drivers/gpu/drm/amd/display/dc/dm_services_types.h 
b/drivers/gpu/drm/amd/display/dc/dm_services_types.h
index 1af8c777b3ac..ce6fedd97df9 100644
--- a/drivers/gpu/drm/amd/display/dc/dm_services_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dm_services_types.h
@@ -148,18 +148,18 @@ struct dm_pp_wm_sets_with_clock_ranges {
 
 struct dm_pp_clock_range_for_dmif_wm_set_soc15 {
enum dm_pp_wm_set_id wm_set_id;
-   uint32_t wm_min_dcfclk_clk_in_khz;
-   uint32_t wm_max_dcfclk_clk_in_khz;
-   uint32_t wm_min_mem_clk_in_khz;
-   uint32_t wm_max_mem_clk_in_khz;
+   uint32_t wm_min_dcfclk_clk_in_mhz;
+   uint32_t wm_max_dcfclk_clk_in_mhz;
+   uint32_t wm_min_mem_clk_in_mhz;
+   uint32_t wm_max_mem_clk_in_mhz;
 };
 
 struct dm_pp_clock_range_for_mcif_wm_set_soc15 {
enum dm_pp_wm_set_id wm_set_id;
-   uint32_t wm_min_socclk_clk_in_khz;
-   uint32_t wm_max_socclk_clk_in_khz;
-   uint32_t wm_min_mem_clk_in_khz;
-   uint32_t wm_max_mem_clk_in_khz;
+   uint32_t wm_min_socclk_clk_in_mhz;
+   uint32_t wm_max_socclk_clk_in_mhz;
+   uint32_t wm_min_mem_clk_in_mhz;
+   uint32_t wm_max_mem_clk_in_mhz;
 };
 
 struct dm_pp_wm_sets_with_clock_ranges_soc15 {
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c 
b/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c
index 99a33c33a32c..0fae388220fe 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c
@@ -712,42 +712,26 @@ int smu_set_watermarks_for_clocks_ranges(void *wt_table,
 
for (i = 0; i < wm_wi

[PATCH 2/2] drm/amdgpu: Change pp clock requests to mHz

2018-10-30 Thread David Francis
We were multiplying clock requests by 1000 in amdgpu_dm
and then dividing them by 1000 in powerplay.

Also, the vega12 code was dividing by 10 when it should have been
multiplying (to convert units of 10kHz to units of kHz).

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c | 6 +++---
 drivers/gpu/drm/amd/include/dm_pp_interface.h| 2 +-
 drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c| 4 ++--
 drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c   | 4 ++--
 drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c   | 4 ++--
 drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c   | 4 ++--
 6 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
index d9daa038fdb2..cfa9b7f545b8 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
@@ -436,7 +436,7 @@ bool dm_pp_apply_clock_for_voltage_request(
int ret = 0;
 
pp_clock_request.clock_type = 
dc_to_pp_clock_type(clock_for_voltage_req->clk_type);
-   pp_clock_request.clock_freq_in_khz = 
clock_for_voltage_req->clocks_in_khz;
+   pp_clock_request.clock_freq_in_mhz = 
clock_for_voltage_req->clocks_in_khz / 1000;
 
if (!pp_clock_request.clock_type)
return false;
@@ -485,11 +485,11 @@ void pp_rv_set_display_requirement(struct pp_smu *pp,
return;
 
clock.clock_type = amd_pp_dcf_clock;
-   clock.clock_freq_in_khz = req->hard_min_dcefclk_mhz * 1000;
+   clock.clock_freq_in_mhz = req->hard_min_dcefclk_mhz;
pp_funcs->display_clock_voltage_request(pp_handle, );
 
clock.clock_type = amd_pp_f_clock;
-   clock.clock_freq_in_khz = req->hard_min_fclk_mhz * 1000;
+   clock.clock_freq_in_mhz = req->hard_min_fclk_mhz;
pp_funcs->display_clock_voltage_request(pp_handle, );
 }
 
diff --git a/drivers/gpu/drm/amd/include/dm_pp_interface.h 
b/drivers/gpu/drm/amd/include/dm_pp_interface.h
index 1d93a0c574c9..114ddd03e238 100644
--- a/drivers/gpu/drm/amd/include/dm_pp_interface.h
+++ b/drivers/gpu/drm/amd/include/dm_pp_interface.h
@@ -188,7 +188,7 @@ struct pp_clock_levels_with_voltage {
 
 struct pp_display_clock_request {
enum amd_pp_clock_type clock_type;
-   uint32_t clock_freq_in_khz;
+   uint32_t clock_freq_in_mhz;
 };
 
 #endif /* _DM_PP_INTERFACE_ */
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c 
b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
index dd18cb710391..d6a6a4f4ac9d 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
@@ -57,7 +57,7 @@ static int smu10_display_clock_voltage_request(struct 
pp_hwmgr *hwmgr,
 {
struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
enum amd_pp_clock_type clk_type = clock_req->clock_type;
-   uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000;
+   uint32_t clk_freq = clock_req->clock_freq_in_mhz;
PPSMC_Msgmsg;
 
switch (clk_type) {
@@ -203,7 +203,7 @@ static int smu10_set_clock_limit(struct pp_hwmgr *hwmgr, 
const void *input)
 
clocks.dcefClock = hwmgr->display_config->min_dcef_set_clk;
clock_req.clock_type = amd_pp_dcf_clock;
-   clock_req.clock_freq_in_khz = clocks.dcefClock * 10;
+   clock_req.clock_freq_in_mhz = clocks.dcefClock / 100;
 
PP_ASSERT_WITH_CODE(!smu10_display_clock_voltage_request(hwmgr, 
_req),
"Attempt to set DCF Clock Failed!", return 
-EINVAL);
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c 
b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
index 419a1d77d661..f926a46bf256 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
@@ -3740,7 +3740,7 @@ int vega10_display_clock_voltage_request(struct pp_hwmgr 
*hwmgr,
 {
int result = 0;
enum amd_pp_clock_type clk_type = clock_req->clock_type;
-   uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000;
+   uint32_t clk_freq = clock_req->clock_freq_in_mhz;
DSPCLK_e clk_select = 0;
uint32_t clk_request = 0;
 
@@ -3825,7 +3825,7 @@ static int 
vega10_notify_smc_display_config_after_ps_adjustment(
 
if (i < dpm_table->count) {
clock_req.clock_type = amd_pp_dcef_clock;
-   clock_req.clock_freq_in_khz = dpm_table->dpm_levels[i].value * 
10;
+   clock_req.clock_freq_in_mhz = dpm_table->dpm_levels[i].value / 
100;
if (!vega10_display_clock_voltage_request(hwmgr, _req)) {
smum_send_msg_to_smc_with_parameter(
hwmgr, PPSMC_MSG_SetMinDeepSleepDcefclk

[PATCH v2 2/3] drm/amdgpu: Fix a bad unit conversion in vega12 powerplay

2018-11-01 Thread David Francis
The default unit in powerplay is 10kHz

To convert from 10kHz to kHz, multiply by 10

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c 
b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c
index 74bc37308dc0..b6baf817b4db 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c
@@ -1405,7 +1405,7 @@ static int 
vega12_notify_smc_display_config_after_ps_adjustment(
 
if (data->smu_features[GNLD_DPM_DCEFCLK].supported) {
clock_req.clock_type = amd_pp_dcef_clock;
-   clock_req.clock_freq_in_khz = min_clocks.dcefClock/10;
+   clock_req.clock_freq_in_khz = min_clocks.dcefClock * 10;
if (!vega12_display_clock_voltage_request(hwmgr, _req)) {
if (data->smu_features[GNLD_DS_DCEFCLK].supported)
PP_ASSERT_WITH_CODE(
-- 
2.17.1

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


[PATCH v2 3/3] drm/amdgpu: Change powerplay clock requests to mHz

2018-11-01 Thread David Francis
This will clean up powerplay code, as we are no longer
multiplying the clocks by 1000 in DM and then dividing them
by 1000 in powerplay

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c | 6 +++---
 drivers/gpu/drm/amd/include/dm_pp_interface.h| 2 +-
 drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c| 4 ++--
 drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c   | 4 ++--
 drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c   | 4 ++--
 drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c   | 4 ++--
 6 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
index d9daa038fdb2..cfa9b7f545b8 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
@@ -436,7 +436,7 @@ bool dm_pp_apply_clock_for_voltage_request(
int ret = 0;
 
pp_clock_request.clock_type = 
dc_to_pp_clock_type(clock_for_voltage_req->clk_type);
-   pp_clock_request.clock_freq_in_khz = 
clock_for_voltage_req->clocks_in_khz;
+   pp_clock_request.clock_freq_in_mhz = 
clock_for_voltage_req->clocks_in_khz / 1000;
 
if (!pp_clock_request.clock_type)
return false;
@@ -485,11 +485,11 @@ void pp_rv_set_display_requirement(struct pp_smu *pp,
return;
 
clock.clock_type = amd_pp_dcf_clock;
-   clock.clock_freq_in_khz = req->hard_min_dcefclk_mhz * 1000;
+   clock.clock_freq_in_mhz = req->hard_min_dcefclk_mhz;
pp_funcs->display_clock_voltage_request(pp_handle, );
 
clock.clock_type = amd_pp_f_clock;
-   clock.clock_freq_in_khz = req->hard_min_fclk_mhz * 1000;
+   clock.clock_freq_in_mhz = req->hard_min_fclk_mhz;
pp_funcs->display_clock_voltage_request(pp_handle, );
 }
 
diff --git a/drivers/gpu/drm/amd/include/dm_pp_interface.h 
b/drivers/gpu/drm/amd/include/dm_pp_interface.h
index 1d93a0c574c9..114ddd03e238 100644
--- a/drivers/gpu/drm/amd/include/dm_pp_interface.h
+++ b/drivers/gpu/drm/amd/include/dm_pp_interface.h
@@ -188,7 +188,7 @@ struct pp_clock_levels_with_voltage {
 
 struct pp_display_clock_request {
enum amd_pp_clock_type clock_type;
-   uint32_t clock_freq_in_khz;
+   uint32_t clock_freq_in_mhz;
 };
 
 #endif /* _DM_PP_INTERFACE_ */
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c 
b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
index dd18cb710391..d6a6a4f4ac9d 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
@@ -57,7 +57,7 @@ static int smu10_display_clock_voltage_request(struct 
pp_hwmgr *hwmgr,
 {
struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
enum amd_pp_clock_type clk_type = clock_req->clock_type;
-   uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000;
+   uint32_t clk_freq = clock_req->clock_freq_in_mhz;
PPSMC_Msgmsg;
 
switch (clk_type) {
@@ -203,7 +203,7 @@ static int smu10_set_clock_limit(struct pp_hwmgr *hwmgr, 
const void *input)
 
clocks.dcefClock = hwmgr->display_config->min_dcef_set_clk;
clock_req.clock_type = amd_pp_dcf_clock;
-   clock_req.clock_freq_in_khz = clocks.dcefClock * 10;
+   clock_req.clock_freq_in_mhz = clocks.dcefClock / 100;
 
PP_ASSERT_WITH_CODE(!smu10_display_clock_voltage_request(hwmgr, 
_req),
"Attempt to set DCF Clock Failed!", return 
-EINVAL);
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c 
b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
index 419a1d77d661..f926a46bf256 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
@@ -3740,7 +3740,7 @@ int vega10_display_clock_voltage_request(struct pp_hwmgr 
*hwmgr,
 {
int result = 0;
enum amd_pp_clock_type clk_type = clock_req->clock_type;
-   uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000;
+   uint32_t clk_freq = clock_req->clock_freq_in_mhz;
DSPCLK_e clk_select = 0;
uint32_t clk_request = 0;
 
@@ -3825,7 +3825,7 @@ static int 
vega10_notify_smc_display_config_after_ps_adjustment(
 
if (i < dpm_table->count) {
clock_req.clock_type = amd_pp_dcef_clock;
-   clock_req.clock_freq_in_khz = dpm_table->dpm_levels[i].value * 
10;
+   clock_req.clock_freq_in_mhz = dpm_table->dpm_levels[i].value / 
100;
if (!vega10_display_clock_voltage_request(hwmgr, _req)) {
smum_send_msg_to_smc_with_parameter(
hwmgr, PPSMC_MSG_SetMinDeepSleepDcefclk,
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c 
b/drivers/gpu/dr

[PATCH v2 1/3] drm/amdgpu: Stop dividing watermarks by 1000 in powerplay

2018-11-01 Thread David Francis
Watermarks were being multiplied by 1000 in amdgpu_dm
and divided by 1000 in powerplay.  Change watermarks
to units of mhz to stop doing that.

Signed-off-by: David Francis 
---
 .../amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c  | 24 +-
 .../drm/amd/display/dc/dm_services_types.h| 16 +-
 .../gpu/drm/amd/powerplay/hwmgr/smu_helper.c  | 32 +--
 3 files changed, 24 insertions(+), 48 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
index 9d2d6986b983..d9daa038fdb2 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
@@ -517,14 +517,10 @@ void pp_rv_set_wm_ranges(struct pp_smu *pp,
else
wm_dce_clocks[i].wm_set_id =
ranges->reader_wm_sets[i].wm_inst;
-   wm_dce_clocks[i].wm_max_dcfclk_clk_in_khz =
-   ranges->reader_wm_sets[i].max_drain_clk_mhz * 
1000;
-   wm_dce_clocks[i].wm_min_dcfclk_clk_in_khz =
-   ranges->reader_wm_sets[i].min_drain_clk_mhz * 
1000;
-   wm_dce_clocks[i].wm_max_mem_clk_in_khz =
-   ranges->reader_wm_sets[i].max_fill_clk_mhz * 
1000;
-   wm_dce_clocks[i].wm_min_mem_clk_in_khz =
-   ranges->reader_wm_sets[i].min_fill_clk_mhz * 
1000;
+   wm_dce_clocks[i].wm_max_dcfclk_clk_in_mhz = 
ranges->reader_wm_sets[i].max_drain_clk_mhz;
+   wm_dce_clocks[i].wm_min_dcfclk_clk_in_mhz = 
ranges->reader_wm_sets[i].min_drain_clk_mhz;
+   wm_dce_clocks[i].wm_max_mem_clk_in_mhz = 
ranges->reader_wm_sets[i].max_fill_clk_mhz;
+   wm_dce_clocks[i].wm_min_mem_clk_in_mhz = 
ranges->reader_wm_sets[i].min_fill_clk_mhz;
}
 
for (i = 0; i < wm_with_clock_ranges.num_wm_mcif_sets; i++) {
@@ -533,14 +529,10 @@ void pp_rv_set_wm_ranges(struct pp_smu *pp,
else
wm_soc_clocks[i].wm_set_id =
ranges->writer_wm_sets[i].wm_inst;
-   wm_soc_clocks[i].wm_max_socclk_clk_in_khz =
-   ranges->writer_wm_sets[i].max_fill_clk_mhz * 
1000;
-   wm_soc_clocks[i].wm_min_socclk_clk_in_khz =
-   ranges->writer_wm_sets[i].min_fill_clk_mhz * 
1000;
-   wm_soc_clocks[i].wm_max_mem_clk_in_khz =
-   ranges->writer_wm_sets[i].max_drain_clk_mhz * 
1000;
-   wm_soc_clocks[i].wm_min_mem_clk_in_khz =
-   ranges->writer_wm_sets[i].min_drain_clk_mhz * 
1000;
+   wm_soc_clocks[i].wm_max_socclk_clk_in_mhz = 
ranges->writer_wm_sets[i].max_fill_clk_mhz;
+   wm_soc_clocks[i].wm_min_socclk_clk_in_mhz = 
ranges->writer_wm_sets[i].min_fill_clk_mhz;
+   wm_soc_clocks[i].wm_max_mem_clk_in_mhz = 
ranges->writer_wm_sets[i].max_drain_clk_mhz;
+   wm_soc_clocks[i].wm_min_mem_clk_in_mhz = 
ranges->writer_wm_sets[i].min_drain_clk_mhz;
}
 
pp_funcs->set_watermarks_for_clocks_ranges(pp_handle, 
_with_clock_ranges);
diff --git a/drivers/gpu/drm/amd/display/dc/dm_services_types.h 
b/drivers/gpu/drm/amd/display/dc/dm_services_types.h
index 2b83f922ac02..59a6e0ab811a 100644
--- a/drivers/gpu/drm/amd/display/dc/dm_services_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dm_services_types.h
@@ -148,18 +148,18 @@ struct dm_pp_wm_sets_with_clock_ranges {
 
 struct dm_pp_clock_range_for_dmif_wm_set_soc15 {
enum dm_pp_wm_set_id wm_set_id;
-   uint32_t wm_min_dcfclk_clk_in_khz;
-   uint32_t wm_max_dcfclk_clk_in_khz;
-   uint32_t wm_min_mem_clk_in_khz;
-   uint32_t wm_max_mem_clk_in_khz;
+   uint32_t wm_min_dcfclk_clk_in_mhz;
+   uint32_t wm_max_dcfclk_clk_in_mhz;
+   uint32_t wm_min_mem_clk_in_mhz;
+   uint32_t wm_max_mem_clk_in_mhz;
 };
 
 struct dm_pp_clock_range_for_mcif_wm_set_soc15 {
enum dm_pp_wm_set_id wm_set_id;
-   uint32_t wm_min_socclk_clk_in_khz;
-   uint32_t wm_max_socclk_clk_in_khz;
-   uint32_t wm_min_mem_clk_in_khz;
-   uint32_t wm_max_mem_clk_in_khz;
+   uint32_t wm_min_socclk_clk_in_mhz;
+   uint32_t wm_max_socclk_clk_in_mhz;
+   uint32_t wm_min_mem_clk_in_mhz;
+   uint32_t wm_max_mem_clk_in_mhz;
 };
 
 struct dm_pp_wm_sets_with_clock_ranges_soc15 {
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c 
b/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c
index 99a33c33a32c..0fae388220fe 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c
@@ -712,42 +712,26 @@ int smu_set_watermarks_for_clocks_ranges(void *wt_table,
 
for (i = 0; i < wm_wi

[PATCH v3 2/3] drm/amdgpu: Fix a bad unit conversion in vega12 powerplay

2018-11-02 Thread David Francis
The default unit in powerplay is 10kHz

To convert from 10kHz to kHz, multiply by 10

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c 
b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c
index 74bc37308dc0..b6baf817b4db 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c
@@ -1405,7 +1405,7 @@ static int 
vega12_notify_smc_display_config_after_ps_adjustment(
 
if (data->smu_features[GNLD_DPM_DCEFCLK].supported) {
clock_req.clock_type = amd_pp_dcef_clock;
-   clock_req.clock_freq_in_khz = min_clocks.dcefClock/10;
+   clock_req.clock_freq_in_khz = min_clocks.dcefClock * 10;
if (!vega12_display_clock_voltage_request(hwmgr, _req)) {
if (data->smu_features[GNLD_DS_DCEFCLK].supported)
PP_ASSERT_WITH_CODE(
-- 
2.17.1

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


[PATCH v3 3/3] drm/amdgpu: Change powerplay clock requests to MHz

2018-11-02 Thread David Francis
This will clean up powerplay code, as we are no longer
multiplying the clocks by 1000 in DM and then dividing them
by 1000 in powerplay

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c | 6 +++---
 drivers/gpu/drm/amd/include/dm_pp_interface.h| 2 +-
 drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c| 4 ++--
 drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c   | 4 ++--
 drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c   | 4 ++--
 drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c   | 4 ++--
 6 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
index d9daa038fdb2..cfa9b7f545b8 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
@@ -436,7 +436,7 @@ bool dm_pp_apply_clock_for_voltage_request(
int ret = 0;
 
pp_clock_request.clock_type = 
dc_to_pp_clock_type(clock_for_voltage_req->clk_type);
-   pp_clock_request.clock_freq_in_khz = 
clock_for_voltage_req->clocks_in_khz;
+   pp_clock_request.clock_freq_in_mhz = 
clock_for_voltage_req->clocks_in_khz / 1000;
 
if (!pp_clock_request.clock_type)
return false;
@@ -485,11 +485,11 @@ void pp_rv_set_display_requirement(struct pp_smu *pp,
return;
 
clock.clock_type = amd_pp_dcf_clock;
-   clock.clock_freq_in_khz = req->hard_min_dcefclk_mhz * 1000;
+   clock.clock_freq_in_mhz = req->hard_min_dcefclk_mhz;
pp_funcs->display_clock_voltage_request(pp_handle, );
 
clock.clock_type = amd_pp_f_clock;
-   clock.clock_freq_in_khz = req->hard_min_fclk_mhz * 1000;
+   clock.clock_freq_in_mhz = req->hard_min_fclk_mhz;
pp_funcs->display_clock_voltage_request(pp_handle, );
 }
 
diff --git a/drivers/gpu/drm/amd/include/dm_pp_interface.h 
b/drivers/gpu/drm/amd/include/dm_pp_interface.h
index 1d93a0c574c9..114ddd03e238 100644
--- a/drivers/gpu/drm/amd/include/dm_pp_interface.h
+++ b/drivers/gpu/drm/amd/include/dm_pp_interface.h
@@ -188,7 +188,7 @@ struct pp_clock_levels_with_voltage {
 
 struct pp_display_clock_request {
enum amd_pp_clock_type clock_type;
-   uint32_t clock_freq_in_khz;
+   uint32_t clock_freq_in_mhz;
 };
 
 #endif /* _DM_PP_INTERFACE_ */
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c 
b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
index dd18cb710391..d6a6a4f4ac9d 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
@@ -57,7 +57,7 @@ static int smu10_display_clock_voltage_request(struct 
pp_hwmgr *hwmgr,
 {
struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
enum amd_pp_clock_type clk_type = clock_req->clock_type;
-   uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000;
+   uint32_t clk_freq = clock_req->clock_freq_in_mhz;
PPSMC_Msgmsg;
 
switch (clk_type) {
@@ -203,7 +203,7 @@ static int smu10_set_clock_limit(struct pp_hwmgr *hwmgr, 
const void *input)
 
clocks.dcefClock = hwmgr->display_config->min_dcef_set_clk;
clock_req.clock_type = amd_pp_dcf_clock;
-   clock_req.clock_freq_in_khz = clocks.dcefClock * 10;
+   clock_req.clock_freq_in_mhz = clocks.dcefClock / 100;
 
PP_ASSERT_WITH_CODE(!smu10_display_clock_voltage_request(hwmgr, 
_req),
"Attempt to set DCF Clock Failed!", return 
-EINVAL);
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c 
b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
index 8c4db86bb4b7..b1ea1e074373 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
@@ -3770,7 +3770,7 @@ int vega10_display_clock_voltage_request(struct pp_hwmgr 
*hwmgr,
 {
int result = 0;
enum amd_pp_clock_type clk_type = clock_req->clock_type;
-   uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000;
+   uint32_t clk_freq = clock_req->clock_freq_in_mhz;
DSPCLK_e clk_select = 0;
uint32_t clk_request = 0;
 
@@ -3855,7 +3855,7 @@ static int 
vega10_notify_smc_display_config_after_ps_adjustment(
 
if (i < dpm_table->count) {
clock_req.clock_type = amd_pp_dcef_clock;
-   clock_req.clock_freq_in_khz = dpm_table->dpm_levels[i].value * 
10;
+   clock_req.clock_freq_in_mhz = dpm_table->dpm_levels[i].value / 
100;
if (!vega10_display_clock_voltage_request(hwmgr, _req)) {
smum_send_msg_to_smc_with_parameter(
hwmgr, PPSMC_MSG_SetMinDeepSleepDcefclk,
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c 
b/drivers/gpu/dr

[PATCH v3 1/3] drm/amdgpu: Stop dividing watermarks by 1000 in powerplay

2018-11-02 Thread David Francis
Watermarks were being multiplied by 1000 in amdgpu_dm
and divided by 1000 in powerplay.  Change watermarks
to units of MHz to stop doing that.

Signed-off-by: David Francis 
---
 .../amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c  | 24 +-
 .../drm/amd/display/dc/dm_services_types.h| 16 +-
 .../gpu/drm/amd/powerplay/hwmgr/smu_helper.c  | 32 +--
 3 files changed, 24 insertions(+), 48 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
index 9d2d6986b983..d9daa038fdb2 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
@@ -517,14 +517,10 @@ void pp_rv_set_wm_ranges(struct pp_smu *pp,
else
wm_dce_clocks[i].wm_set_id =
ranges->reader_wm_sets[i].wm_inst;
-   wm_dce_clocks[i].wm_max_dcfclk_clk_in_khz =
-   ranges->reader_wm_sets[i].max_drain_clk_mhz * 
1000;
-   wm_dce_clocks[i].wm_min_dcfclk_clk_in_khz =
-   ranges->reader_wm_sets[i].min_drain_clk_mhz * 
1000;
-   wm_dce_clocks[i].wm_max_mem_clk_in_khz =
-   ranges->reader_wm_sets[i].max_fill_clk_mhz * 
1000;
-   wm_dce_clocks[i].wm_min_mem_clk_in_khz =
-   ranges->reader_wm_sets[i].min_fill_clk_mhz * 
1000;
+   wm_dce_clocks[i].wm_max_dcfclk_clk_in_mhz = 
ranges->reader_wm_sets[i].max_drain_clk_mhz;
+   wm_dce_clocks[i].wm_min_dcfclk_clk_in_mhz = 
ranges->reader_wm_sets[i].min_drain_clk_mhz;
+   wm_dce_clocks[i].wm_max_mem_clk_in_mhz = 
ranges->reader_wm_sets[i].max_fill_clk_mhz;
+   wm_dce_clocks[i].wm_min_mem_clk_in_mhz = 
ranges->reader_wm_sets[i].min_fill_clk_mhz;
}
 
for (i = 0; i < wm_with_clock_ranges.num_wm_mcif_sets; i++) {
@@ -533,14 +529,10 @@ void pp_rv_set_wm_ranges(struct pp_smu *pp,
else
wm_soc_clocks[i].wm_set_id =
ranges->writer_wm_sets[i].wm_inst;
-   wm_soc_clocks[i].wm_max_socclk_clk_in_khz =
-   ranges->writer_wm_sets[i].max_fill_clk_mhz * 
1000;
-   wm_soc_clocks[i].wm_min_socclk_clk_in_khz =
-   ranges->writer_wm_sets[i].min_fill_clk_mhz * 
1000;
-   wm_soc_clocks[i].wm_max_mem_clk_in_khz =
-   ranges->writer_wm_sets[i].max_drain_clk_mhz * 
1000;
-   wm_soc_clocks[i].wm_min_mem_clk_in_khz =
-   ranges->writer_wm_sets[i].min_drain_clk_mhz * 
1000;
+   wm_soc_clocks[i].wm_max_socclk_clk_in_mhz = 
ranges->writer_wm_sets[i].max_fill_clk_mhz;
+   wm_soc_clocks[i].wm_min_socclk_clk_in_mhz = 
ranges->writer_wm_sets[i].min_fill_clk_mhz;
+   wm_soc_clocks[i].wm_max_mem_clk_in_mhz = 
ranges->writer_wm_sets[i].max_drain_clk_mhz;
+   wm_soc_clocks[i].wm_min_mem_clk_in_mhz = 
ranges->writer_wm_sets[i].min_drain_clk_mhz;
}
 
pp_funcs->set_watermarks_for_clocks_ranges(pp_handle, 
_with_clock_ranges);
diff --git a/drivers/gpu/drm/amd/display/dc/dm_services_types.h 
b/drivers/gpu/drm/amd/display/dc/dm_services_types.h
index 1af8c777b3ac..ce6fedd97df9 100644
--- a/drivers/gpu/drm/amd/display/dc/dm_services_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dm_services_types.h
@@ -148,18 +148,18 @@ struct dm_pp_wm_sets_with_clock_ranges {
 
 struct dm_pp_clock_range_for_dmif_wm_set_soc15 {
enum dm_pp_wm_set_id wm_set_id;
-   uint32_t wm_min_dcfclk_clk_in_khz;
-   uint32_t wm_max_dcfclk_clk_in_khz;
-   uint32_t wm_min_mem_clk_in_khz;
-   uint32_t wm_max_mem_clk_in_khz;
+   uint32_t wm_min_dcfclk_clk_in_mhz;
+   uint32_t wm_max_dcfclk_clk_in_mhz;
+   uint32_t wm_min_mem_clk_in_mhz;
+   uint32_t wm_max_mem_clk_in_mhz;
 };
 
 struct dm_pp_clock_range_for_mcif_wm_set_soc15 {
enum dm_pp_wm_set_id wm_set_id;
-   uint32_t wm_min_socclk_clk_in_khz;
-   uint32_t wm_max_socclk_clk_in_khz;
-   uint32_t wm_min_mem_clk_in_khz;
-   uint32_t wm_max_mem_clk_in_khz;
+   uint32_t wm_min_socclk_clk_in_mhz;
+   uint32_t wm_max_socclk_clk_in_mhz;
+   uint32_t wm_min_mem_clk_in_mhz;
+   uint32_t wm_max_mem_clk_in_mhz;
 };
 
 struct dm_pp_wm_sets_with_clock_ranges_soc15 {
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c 
b/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c
index 99a33c33a32c..0fae388220fe 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c
@@ -712,42 +712,26 @@ int smu_set_watermarks_for_clocks_ranges(void *wt_table,
 
for (i = 0; i < wm_wi

[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   

[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 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 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] drm/amd: Don't fail on backlight = 0

2018-11-06 Thread David Francis
Amgpu's backlight update status function was
returning 1 (an error value) when the backlight
property was 0.  This breaks users that assume
0 is a valid backlight value (which is a
correct assumption)

If the user passes in a backlight value of 0,
tell them everything is fine, then write a value of
1 to hardware.

Signed-off-by: David Francis 
Bugzilla: https://bugs.freedesktop.org/108668
Fixes: 416615ea9578 ("drm/amd/display: set backlight level limit to 1")
Cc: suresh.gutt...@amd.com
Cc: harry.wentl...@amd.com
Cc: samant...@posteo.net
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c  | 18 ++
 1 file changed, 10 insertions(+), 8 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 f8ec8a146663..131e6483d442 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -1567,21 +1567,23 @@ static int amdgpu_dm_backlight_update_status(struct 
backlight_device *bd)
 {
struct amdgpu_display_manager *dm = bl_get_data(bd);
 
+   /* backlight_pwm_u16_16 parameter is in unsigned 32 bit, 16 bit integer
+* and 16 bit fractional, where 1.0 is max backlight value.
+* bd->props.brightness is 8 bit format and needs to be converted by
+* scaling via copy lower byte to upper byte of 16 bit value.
+*/
+   uint32_t brightness = bd->props.brightness * 0x101;
+
/*
 * PWM interperts 0 as 100% rather than 0% because of HW
-* limitation for level 0.So limiting minimum brightness level
+* limitation for level 0.  So limiting minimum brightness level
 * to 1.
 */
if (bd->props.brightness < 1)
-   return 1;
+   brightness = 0x101;
 
-   /* backlight_pwm_u16_16 parameter is in unsigned 32 bit, 16 bit integer
-* and 16 bit fractional, where 1.0 is max backlight value.
-* bd->props.brightness is 8 bit format and needs to be converted by
-* scaling via copy lower byte to upper byte of 16 bit value.
-*/
if (dc_link_set_backlight_level(dm->backlight_link,
-   (bd->props.brightness * 0x101), 0, 0))
+   brightness, 0, 0))
return 0;
else
return 1;
-- 
2.17.1

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


[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] 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] 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 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 1/2] drm/amd/display: Add DMCU firmware version

2018-09-13 Thread David Francis
Read the version number from the common firmware header and store
it in the dm struct

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 ++
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 1 +
 2 files changed, 3 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 f0ae11802e9a..d21d738c8356 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -589,6 +589,8 @@ static int load_dmcu_fw(struct amdgpu_device *adev)
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(hdr->intv_size_bytes), PAGE_SIZE);
 
+   adev->dm.dmcu_fw_version = le32_to_cpu(hdr->header.ucode_version);
+
DRM_DEBUG_KMS("PSP loading DMCU firmware\n");
 
return 0;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
index 9a57c654943a..b6fe9adf4b93 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -131,6 +131,7 @@ struct amdgpu_display_manager {
struct dm_comressor_info compressor;
 
const struct firmware *fw_dmcu;
+   uint32_t dmcu_fw_version;
 };
 
 struct amdgpu_dm_connector {
-- 
2.17.1

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


[PATCH 2/2] drm/amdgpu: Add DMCU to firmware query interface

2018-09-13 Thread David Francis
DMCU firmware version can be read using the AMDGPU_INFO ioctl
or the amdgpu_firmware_info debugfs entry

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 12 
 include/uapi/drm/amdgpu_drm.h   |  2 ++
 2 files changed, 14 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index 29ac3873eeb0..f5caf873f008 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -257,6 +257,10 @@ static int amdgpu_firmware_info(struct 
drm_amdgpu_info_firmware *fw_info,
fw_info->ver = adev->psp.asd_fw_version;
fw_info->feature = adev->psp.asd_feature_version;
break;
+   case AMDGPU_INFO_FW_DMCU:
+   fw_info->ver = adev->dm.dmcu_fw_version;
+   fw_info->feature = 0;
+   break;
default:
return -EINVAL;
}
@@ -1296,6 +1300,14 @@ static int amdgpu_debugfs_firmware_info(struct seq_file 
*m, void *data)
seq_printf(m, "VCN feature version: %u, firmware version: 0x%08x\n",
   fw_info.feature, fw_info.ver);
 
+   /* DMCU */
+   query_fw.fw_type = AMDGPU_INFO_FW_DMCU;
+   ret = amdgpu_firmware_info(_info, _fw, adev);
+   if (ret)
+   return ret;
+   seq_printf(m, "DMCU feature version: %u, firmware version: 0x%08x\n",
+  fw_info.feature, fw_info.ver);
+
 
seq_printf(m, "VBIOS version: %s\n", ctx->vbios_version);
 
diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h
index 9eeba55b..6a0d77dcfc47 100644
--- a/include/uapi/drm/amdgpu_drm.h
+++ b/include/uapi/drm/amdgpu_drm.h
@@ -668,6 +668,8 @@ struct drm_amdgpu_cs_chunk_data {
#define AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_GPM_MEM 0x10
/* Subquery id: Query GFX RLC SRLS firmware version */
#define AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_SRM_MEM 0x11
+   /* Subquery id: Query DMCU firmware version */
+   #define AMDGPU_INFO_FW_DMCU 0x12
 /* number of bytes moved for TTM migration */
 #define AMDGPU_INFO_NUM_BYTES_MOVED0x0f
 /* the used VRAM size */
-- 
2.17.1

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


[PATCH 0/2] DMCU firmware version storing and access

2018-09-13 Thread David Francis
David Francis (2):
  drm/amd/display: Add DMCU firmware version
  drm/amdgpu: Add DMCU to firmware query interface

 drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c   | 12 
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  2 ++
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  1 +
 include/uapi/drm/amdgpu_drm.h |  2 ++
 4 files changed, 17 insertions(+)

-- 
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/amd: Add ucode DMCU support

2018-09-12 Thread David Francis
DMCU (Display Microcontroller Unit) is a GPU chip involved in
eDP features like Adaptive Backlight Modulation and Panel Self
Refresh.

DMCU has two pieces of firmware: the ERAM and the interrupt
vectors, which must be loaded seperately.

To this end, the DMCU firmware has a custom header and parsing
logic similar to MEC, to extract the two ucodes from a single
struct firmware.

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 21 +++--
 drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h | 10 ++
 2 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
index a942fd28dae8..1fa8bc337859 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
@@ -322,6 +322,7 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_device 
*adev,
 {
const struct common_firmware_header *header = NULL;
const struct gfx_firmware_header_v1_0 *cp_hdr = NULL;
+   const struct dmcu_firmware_header_v1_0 *dmcu_hdr = NULL;
 
if (NULL == ucode->fw)
return 0;
@@ -333,8 +334,8 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_device 
*adev,
return 0;
 
header = (const struct common_firmware_header *)ucode->fw->data;
-
cp_hdr = (const struct gfx_firmware_header_v1_0 *)ucode->fw->data;
+   dmcu_hdr = (const struct dmcu_firmware_header_v1_0 *)ucode->fw->data;
 
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP ||
(ucode->ucode_id != AMDGPU_UCODE_ID_CP_MEC1 &&
@@ -343,7 +344,9 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_device 
*adev,
 ucode->ucode_id != AMDGPU_UCODE_ID_CP_MEC2_JT &&
 ucode->ucode_id != AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL &&
 ucode->ucode_id != AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM &&
-ucode->ucode_id != AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM)) {
+ucode->ucode_id != AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM &&
+ucode->ucode_id != AMDGPU_UCODE_ID_DMCU_ERAM &&
+ucode->ucode_id != AMDGPU_UCODE_ID_DMCU_INTV)) {
ucode->ucode_size = le32_to_cpu(header->ucode_size_bytes);
 
memcpy(ucode->kaddr, (void *)((uint8_t *)ucode->fw->data +
@@ -365,6 +368,20 @@ static int amdgpu_ucode_init_single_fw(struct 
amdgpu_device *adev,
  
le32_to_cpu(header->ucode_array_offset_bytes) +
  le32_to_cpu(cp_hdr->jt_offset) * 
4),
   ucode->ucode_size);
+   } else if (ucode->ucode_id == AMDGPU_UCODE_ID_DMCU_ERAM) {
+   ucode->ucode_size = le32_to_cpu(header->ucode_size_bytes) -
+   le32_to_cpu(dmcu_hdr->intv_size_bytes);
+
+   memcpy(ucode->kaddr, (void *)((uint8_t *)ucode->fw->data +
+ 
le32_to_cpu(header->ucode_array_offset_bytes)),
+  ucode->ucode_size);
+   } else if (ucode->ucode_id == AMDGPU_UCODE_ID_DMCU_INTV) {
+   ucode->ucode_size = le32_to_cpu(dmcu_hdr->intv_size_bytes);
+
+   memcpy(ucode->kaddr, (void *)((uint8_t *)ucode->fw->data +
+ 
le32_to_cpu(header->ucode_array_offset_bytes) +
+ 
le32_to_cpu(dmcu_hdr->intv_offset_bytes)),
+  ucode->ucode_size);
} else if (ucode->ucode_id == AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL) {
ucode->ucode_size = 
adev->gfx.rlc.save_restore_list_cntl_size_bytes;
memcpy(ucode->kaddr, adev->gfx.rlc.save_restore_list_cntl,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
index b358e7519987..8f3f1117728c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
@@ -157,6 +157,13 @@ struct gpu_info_firmware_header_v1_0 {
uint16_t version_minor; /* version */
 };
 
+/* version_major=1, version_minor=0 */
+struct dmcu_firmware_header_v1_0 {
+   struct common_firmware_header header;
+   uint32_t intv_offset_bytes; /* interrupt vectors offset from end of 
header, in bytes */
+   uint32_t intv_size_bytes;  /* size of interrupt vectors, in bytes */
+};
+
 /* header is fixed size */
 union amdgpu_firmware_header {
struct common_firmware_header common;
@@ -170,6 +177,7 @@ union amdgpu_firmware_header {
struct sdma_firmware_header_v1_0 sdma;
struct sdma_firmware_header_v1_1 sdma_v1_1;
struct gpu_info_firmware_header_v1_0 gpu_info;
+   struct dmcu_f

[PATCH v2 0/3] Add DMCU fw loading on raven

2018-09-12 Thread David Francis
v2: measure intv offset in bytes instead of words

David Francis (3):
  drm/amd: Add ucode DMCU support
  drm/amd: Add PSP DMCU support
  drm/amd: Add DM DMCU support

 drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 21 -
 drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h | 10 ++
 drivers/gpu/drm/amd/amdgpu/psp_v10_0.c|  6 ++
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 91 ++-
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  2 +
 5 files changed, 127 insertions(+), 3 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/amd: Add PSP DMCU support

2018-09-12 Thread David Francis
DMCU (Display Microcontroller Unit) is a GPU chip involved in
eDP features like Adaptive Backlight Modulation and Panel Self
Refresh.

PSP is already equipped to handle DMCU firmware loading, all
that is needed is to translate between the new DMCU ucode ID and
the equivalent psp_gfx_fw_type.

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

diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c 
b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
index 02be34e72ed9..240dc8c85867 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
@@ -91,6 +91,12 @@ psp_v10_0_get_fw_type(struct amdgpu_firmware_info *ucode, 
enum psp_gfx_fw_type *
case AMDGPU_UCODE_ID_VCN:
*type = GFX_FW_TYPE_VCN;
break;
+   case AMDGPU_UCODE_ID_DMCU_ERAM:
+   *type = GFX_FW_TYPE_DMCU_ERAM;
+   break;
+   case AMDGPU_UCODE_ID_DMCU_INTV:
+   *type = GFX_FW_TYPE_DMCU_ISR;
+   break;
case AMDGPU_UCODE_ID_MAXIMUM:
default:
return -EINVAL;
-- 
2.17.1

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


[PATCH v2 3/3] drm/amd: Add DM DMCU support

2018-09-12 Thread David Francis
DMCU (Display Microcontroller Unit) is a GPU chip involved in
eDP features like Adaptive Backlight Modulation and Panel Self
Refresh.

DC is already fully equipped to initialize DMCU as long as the
firmware is loaded.

At the moment only the raven firmware is available.

A single .bin file is loaded by the kernel's loading mechanism
and split into two ucodes according to the header.

DMCU is optional, so if the firmware is not found, no error or
warning is raised.

Signed-off-by: David Francis 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 91 ++-
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  2 +
 2 files changed, 92 insertions(+), 1 deletion(-)

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 5103eba75cb3..7cb753e1d026 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -30,6 +30,7 @@
 #include "vid.h"
 #include "amdgpu.h"
 #include "amdgpu_display.h"
+#include "amdgpu_ucode.h"
 #include "atom.h"
 #include "amdgpu_dm.h"
 #include "amdgpu_pm.h"
@@ -50,6 +51,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -71,6 +73,9 @@
 
 #include "modules/inc/mod_freesync.h"
 
+#define FIRMWARE_RAVEN_DMCU"amdgpu/raven_dmcue.bin"
+MODULE_FIRMWARE(FIRMWARE_RAVEN_DMCU);
+
 /* basic init/fini API */
 static int amdgpu_dm_init(struct amdgpu_device *adev);
 static void amdgpu_dm_fini(struct amdgpu_device *adev);
@@ -514,13 +519,97 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
return;
 }
 
-static int dm_sw_init(void *handle)
+static int load_dmcu_fw(struct amdgpu_device *adev)
 {
+   const char *fw_name_dmcu;
+   int r;
+   const struct dmcu_firmware_header_v1_0 *hdr;
+
+   switch(adev->asic_type) {
+   case CHIP_BONAIRE:
+   case CHIP_HAWAII:
+   case CHIP_KAVERI:
+   case CHIP_KABINI:
+   case CHIP_MULLINS:
+   case CHIP_TONGA:
+   case CHIP_FIJI:
+   case CHIP_CARRIZO:
+   case CHIP_STONEY:
+   case CHIP_POLARIS11:
+   case CHIP_POLARIS10:
+   case CHIP_POLARIS12:
+   case CHIP_VEGAM:
+   case CHIP_VEGA10:
+   case CHIP_VEGA12:
+   case CHIP_VEGA20:
+   return 0;
+   case CHIP_RAVEN:
+   fw_name_dmcu = FIRMWARE_RAVEN_DMCU;
+   break;
+   default:
+   DRM_ERROR("Unsupported ASIC type: 0x%X\n", adev->asic_type);
+   return -1;
+   }
+
+   if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
+   DRM_DEBUG_KMS("dm: DMCU firmware not supported on direct or SMU 
loading\n");
+   return 0;
+   }
+
+   r = request_firmware_direct(>dm.fw_dmcu, fw_name_dmcu, adev->dev);
+   if (r == -ENOENT) {
+   /* DMCU firmware is not necessary, so don't raise a fuss if 
it's missing */
+   DRM_DEBUG_KMS("dm: DMCU firmware not found\n");
+   adev->dm.fw_dmcu = NULL;
+   return 0;
+   }
+   if (r) {
+   dev_err(adev->dev, "amdgpu_dm: Can't load firmware \"%s\"\n",
+   fw_name_dmcu);
+   return r;
+   }
+
+   r = amdgpu_ucode_validate(adev->dm.fw_dmcu);
+   if (r) {
+   dev_err(adev->dev, "amdgpu_dm: Can't validate firmware 
\"%s\"\n",
+   fw_name_dmcu);
+   release_firmware(adev->dm.fw_dmcu);
+   adev->dm.fw_dmcu = NULL;
+   return r;
+   }
+
+   hdr = (const struct dmcu_firmware_header_v1_0 *)adev->dm.fw_dmcu->data;
+   adev->firmware.ucode[AMDGPU_UCODE_ID_DMCU_ERAM].ucode_id = 
AMDGPU_UCODE_ID_DMCU_ERAM;
+   adev->firmware.ucode[AMDGPU_UCODE_ID_DMCU_ERAM].fw = adev->dm.fw_dmcu;
+   adev->firmware.fw_size +=
+   ALIGN(le32_to_cpu(hdr->header.ucode_size_bytes) - 
le32_to_cpu(hdr->intv_size_bytes), PAGE_SIZE);
+
+   adev->firmware.ucode[AMDGPU_UCODE_ID_DMCU_INTV].ucode_id = 
AMDGPU_UCODE_ID_DMCU_INTV;
+   adev->firmware.ucode[AMDGPU_UCODE_ID_DMCU_INTV].fw = adev->dm.fw_dmcu;
+   adev->firmware.fw_size +=
+   ALIGN(le32_to_cpu(hdr->intv_size_bytes), PAGE_SIZE);
+
+   DRM_DEBUG_KMS("PSP loading DMCU firmware\n");
+
return 0;
 }
 
+static int dm_sw_init(void *handle)
+{
+   struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+   return load_dmcu_fw(adev);
+}
+
 static int dm_sw_fini(void *handle)
 {
+   struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+   if(adev->dm.fw_dmcu) {
+   release_firmware(adev->dm.fw_dmcu);
+   adev->dm.fw_dmcu = NULL;
+   }
+
return 0;
 }
 
diff

[PATCH 2/3] drm/amd: Add PSP DMCU support

2018-09-11 Thread David Francis
DMCU (Display Microcontroller Unit) is a GPU chip involved in
eDP features like Adaptive Backlight Modulation and Panel Self
Refresh.

PSP is already equipped to handle DMCU firmware loading, all
that is needed is to translate between the new DMCU ucode ID and
the equivalent psp_gfx_fw_type.

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

diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c 
b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
index 02be34e72ed9..240dc8c85867 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
@@ -91,6 +91,12 @@ psp_v10_0_get_fw_type(struct amdgpu_firmware_info *ucode, 
enum psp_gfx_fw_type *
case AMDGPU_UCODE_ID_VCN:
*type = GFX_FW_TYPE_VCN;
break;
+   case AMDGPU_UCODE_ID_DMCU_ERAM:
+   *type = GFX_FW_TYPE_DMCU_ERAM;
+   break;
+   case AMDGPU_UCODE_ID_DMCU_INTV:
+   *type = GFX_FW_TYPE_DMCU_ISR;
+   break;
case AMDGPU_UCODE_ID_MAXIMUM:
default:
return -EINVAL;
-- 
2.17.1

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


[PATCH 3/3] drm/amd: Add DM DMCU support

2018-09-11 Thread David Francis
DMCU (Display Microcontroller Unit) is a GPU chip involved in
eDP features like Adaptive Backlight Modulation and Panel Self
Refresh.

DC is already fully equipped to initialize DMCU as long as the
firmware is loaded.

At the moment only the raven firmware is available.

A single .bin file is loaded by the kernel's loading mechanism
and split into two ucodes according to the header.

DMCU is optional, so if the firmware is not found, no error or
warning is raised.

Signed-off-by: David Francis 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 91 ++-
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  2 +
 2 files changed, 92 insertions(+), 1 deletion(-)

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 5103eba75cb3..7541c849a417 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -30,6 +30,7 @@
 #include "vid.h"
 #include "amdgpu.h"
 #include "amdgpu_display.h"
+#include "amdgpu_ucode.h"
 #include "atom.h"
 #include "amdgpu_dm.h"
 #include "amdgpu_pm.h"
@@ -50,6 +51,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -71,6 +73,9 @@
 
 #include "modules/inc/mod_freesync.h"
 
+#define FIRMWARE_RAVEN_DMCU"amdgpu/raven_dmcue.bin"
+MODULE_FIRMWARE(FIRMWARE_RAVEN_DMCU);
+
 /* basic init/fini API */
 static int amdgpu_dm_init(struct amdgpu_device *adev);
 static void amdgpu_dm_fini(struct amdgpu_device *adev);
@@ -514,13 +519,97 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
return;
 }
 
-static int dm_sw_init(void *handle)
+static int load_dmcu_fw(struct amdgpu_device *adev)
 {
+   const char *fw_name_dmcu;
+   int r;
+   const struct dmcu_firmware_header_v1_0 *hdr;
+
+   switch(adev->asic_type) {
+   case CHIP_BONAIRE:
+   case CHIP_HAWAII:
+   case CHIP_KAVERI:
+   case CHIP_KABINI:
+   case CHIP_MULLINS:
+   case CHIP_TONGA:
+   case CHIP_FIJI:
+   case CHIP_CARRIZO:
+   case CHIP_STONEY:
+   case CHIP_POLARIS11:
+   case CHIP_POLARIS10:
+   case CHIP_POLARIS12:
+   case CHIP_VEGAM:
+   case CHIP_VEGA10:
+   case CHIP_VEGA12:
+   case CHIP_VEGA20:
+   return 0;
+   case CHIP_RAVEN:
+   fw_name_dmcu = FIRMWARE_RAVEN_DMCU;
+   break;
+   default:
+   DRM_ERROR("Unsupported ASIC type: 0x%X\n", adev->asic_type);
+   return -1;
+   }
+
+   if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
+   DRM_DEBUG_KMS("dm: DMCU firmware not supported on direct or SMU 
loading\n");
+   return 0;
+   }
+
+   r = request_firmware_direct(>dm.fw_dmcu, fw_name_dmcu, adev->dev);
+   if (r == -ENOENT) {
+   /* DMCU firmware is not necessary, so don't raise a fuss if 
it's missing */
+   DRM_DEBUG_KMS("dm: DMCU firmware not found\n");
+   adev->dm.fw_dmcu = NULL;
+   return 0;
+   }
+   if (r) {
+   dev_err(adev->dev, "amdgpu_dm: Can't load firmware \"%s\"\n",
+   fw_name_dmcu);
+   return r;
+   }
+
+   r = amdgpu_ucode_validate(adev->dm.fw_dmcu);
+   if (r) {
+   dev_err(adev->dev, "amdgpu_dm: Can't validate firmware 
\"%s\"\n",
+   fw_name_dmcu);
+   release_firmware(adev->dm.fw_dmcu);
+   adev->dm.fw_dmcu = NULL;
+   return r;
+   }
+
+   hdr = (const struct dmcu_firmware_header_v1_0 *)adev->dm.fw_dmcu->data;
+   adev->firmware.ucode[AMDGPU_UCODE_ID_DMCU_ERAM].ucode_id = 
AMDGPU_UCODE_ID_DMCU_ERAM;
+   adev->firmware.ucode[AMDGPU_UCODE_ID_DMCU_ERAM].fw = adev->dm.fw_dmcu;
+   adev->firmware.fw_size +=
+   ALIGN(le32_to_cpu(hdr->header.ucode_size_bytes) - 
le32_to_cpu(hdr->intv_size) * 4, PAGE_SIZE);
+
+   adev->firmware.ucode[AMDGPU_UCODE_ID_DMCU_INTV].ucode_id = 
AMDGPU_UCODE_ID_DMCU_INTV;
+   adev->firmware.ucode[AMDGPU_UCODE_ID_DMCU_INTV].fw = adev->dm.fw_dmcu;
+   adev->firmware.fw_size +=
+   ALIGN(le32_to_cpu(hdr->intv_size) * 4, PAGE_SIZE);
+
+   DRM_DEBUG_KMS("PSP loading DMCU firmware\n");
+
return 0;
 }
 
+static int dm_sw_init(void *handle)
+{
+   struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+   return load_dmcu_fw(adev);
+}
+
 static int dm_sw_fini(void *handle)
 {
+   struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+   if(adev->dm.fw_dmcu) {
+   release_firmware(adev->dm.fw_dmcu);
+   adev->dm.fw_dmcu = NULL;
+   }
+
return 0;
 }
 
diff

[PATCH 1/3] drm/amd: Add ucode DMCU support

2018-09-11 Thread David Francis
DMCU (Display Microcontroller Unit) is a GPU chip involved in
eDP features like Adaptive Backlight Modulation and Panel Self
Refresh.

DMCU has two pieces of firmware: the ERAM and the interrupt
vectors, which must be loaded seperately.

To this end, the DMCU firmware has a custom header and parsing
logic similar to MEC, to extract the two ucodes from a single
struct firmware.

Signed-off-by: David Francis 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 21 +++--
 drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h | 10 ++
 2 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
index a942fd28dae8..3b1af1cecf14 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
@@ -322,6 +322,7 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_device 
*adev,
 {
const struct common_firmware_header *header = NULL;
const struct gfx_firmware_header_v1_0 *cp_hdr = NULL;
+   const struct dmcu_firmware_header_v1_0 *dmcu_hdr = NULL;
 
if (NULL == ucode->fw)
return 0;
@@ -333,8 +334,8 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_device 
*adev,
return 0;
 
header = (const struct common_firmware_header *)ucode->fw->data;
-
cp_hdr = (const struct gfx_firmware_header_v1_0 *)ucode->fw->data;
+   dmcu_hdr = (const struct dmcu_firmware_header_v1_0 *)ucode->fw->data;
 
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP ||
(ucode->ucode_id != AMDGPU_UCODE_ID_CP_MEC1 &&
@@ -343,7 +344,9 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_device 
*adev,
 ucode->ucode_id != AMDGPU_UCODE_ID_CP_MEC2_JT &&
 ucode->ucode_id != AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL &&
 ucode->ucode_id != AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM &&
-ucode->ucode_id != AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM)) {
+ucode->ucode_id != AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM &&
+ucode->ucode_id != AMDGPU_UCODE_ID_DMCU_ERAM &&
+ucode->ucode_id != AMDGPU_UCODE_ID_DMCU_INTV)) {
ucode->ucode_size = le32_to_cpu(header->ucode_size_bytes);
 
memcpy(ucode->kaddr, (void *)((uint8_t *)ucode->fw->data +
@@ -365,6 +368,20 @@ static int amdgpu_ucode_init_single_fw(struct 
amdgpu_device *adev,
  
le32_to_cpu(header->ucode_array_offset_bytes) +
  le32_to_cpu(cp_hdr->jt_offset) * 
4),
   ucode->ucode_size);
+   } else if (ucode->ucode_id == AMDGPU_UCODE_ID_DMCU_ERAM) {
+   ucode->ucode_size = le32_to_cpu(header->ucode_size_bytes) -
+   le32_to_cpu(dmcu_hdr->intv_size) * 4;
+
+   memcpy(ucode->kaddr, (void *)((uint8_t *)ucode->fw->data +
+ 
le32_to_cpu(header->ucode_array_offset_bytes)),
+  ucode->ucode_size);
+   } else if (ucode->ucode_id == AMDGPU_UCODE_ID_DMCU_INTV) {
+   ucode->ucode_size = le32_to_cpu(dmcu_hdr->intv_size) * 4;
+
+   memcpy(ucode->kaddr, (void *)((uint8_t *)ucode->fw->data +
+ 
le32_to_cpu(header->ucode_array_offset_bytes) +
+ 
le32_to_cpu(dmcu_hdr->intv_offset) * 4),
+  ucode->ucode_size);
} else if (ucode->ucode_id == AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL) {
ucode->ucode_size = 
adev->gfx.rlc.save_restore_list_cntl_size_bytes;
memcpy(ucode->kaddr, adev->gfx.rlc.save_restore_list_cntl,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
index b358e7519987..13bd540709b6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
@@ -157,6 +157,13 @@ struct gpu_info_firmware_header_v1_0 {
uint16_t version_minor; /* version */
 };
 
+/* version_major=1, version_minor=0 */
+struct dmcu_firmware_header_v1_0 {
+   struct common_firmware_header header;
+   uint32_t intv_offset; /* interrupt vectors offset from end of header, 
in words */
+   uint32_t intv_size;  /* size of interrupt vectors, in words */
+};
+
 /* header is fixed size */
 union amdgpu_firmware_header {
struct common_firmware_header common;
@@ -170,6 +177,7 @@ union amdgpu_firmware_header {
struct sdma_firmware_header_v1_0 sdma;
struct sdma_firmware_header_v1_1 sdma_v1_1;
struct gpu_info_firmware_header_v1_0 gpu_info;
+   struct dmcu_firmware_header_v1_0 dmcu;
u

[PATCH 0/3] Add DMCU fw loading on raven

2018-09-11 Thread David Francis
David Francis (3):
  drm/amd: Add ucode DMCU support
  drm/amd: Add PSP DMCU support
  drm/amd: Add DM DMCU support

 drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 21 -
 drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h | 10 ++
 drivers/gpu/drm/amd/amdgpu/psp_v10_0.c|  6 ++
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 91 ++-
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  2 +
 5 files changed, 127 insertions(+), 3 deletions(-)

-- 
2.17.1

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


[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 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 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 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 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 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 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 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 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] 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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

  1   2   >