<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<style type="text/css" style="display:none;"><!-- P {margin-top:0;margin-bottom:0;} --></style>
</head>
<body dir="ltr">
<div id="divtagdefaultwrapper" style="font-size:12pt;color:#000000;font-family:Calibri,Helvetica,sans-serif;" dir="ltr">
<p style="margin-top:0;margin-bottom:0">Ignore this thread - new, fixed patch is up</p>
</div>
<hr style="display:inline-block;width:98%" tabindex="-1">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> Francis, David<br>
<b>Sent:</b> September 7, 2018 10:26:59 AM<br>
<b>To:</b> amd-gfx@lists.freedesktop.org<br>
<b>Subject:</b> Re: [PATCH] drm/amd: Add DMCU firmware loading on raven</font>
<div> </div>
</div>
<meta content="text/html; charset=us-ascii">
<style type="text/css" style="display:none">
<!--
p
        {margin-top:0;
        margin-bottom:0}
-->
</style>
<div dir="ltr">
<div id="x_divtagdefaultwrapper" dir="ltr" style="font-size:12pt; color:#000000; font-family:Calibri,Helvetica,sans-serif">
<p style="margin-top:0; margin-bottom:0">This will cause amdgpu startup to fail if the firmware does not exist: this should either wait until the firmware is available or not return an error value if -<span>ENOENT is returned from request_firmware</span></p>
</div>
<hr tabindex="-1" style="display:inline-block; width:98%">
<div id="x_divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" color="#000000" style="font-size:11pt"><b>From:</b> David Francis <David.Francis@amd.com><br>
<b>Sent:</b> September 7, 2018 10:16:56 AM<br>
<b>To:</b> amd-gfx@lists.freedesktop.org<br>
<b>Cc:</b> Francis, David<br>
<b>Subject:</b> [PATCH] drm/amd: Add DMCU firmware loading on raven</font>
<div> </div>
</div>
<div class="x_BodyFragment"><font size="2"><span style="font-size:11pt">
<div class="x_PlainText">[Why]<br>
DMCU (Display MicroController Unit) is an on-GPU microcontroller<br>
in AMD graphics cards that is used in features for<br>
embedded displays such as Panel Self-Refresh<br>
<br>
DMCU is part of the DM IP block<br>
<br>
[How]<br>
DMCU is added as an option in the enum AMDGPU_UCODE_ID<br>
<br>
DMCU needs two pieces of firmware - the initial eram and the<br>
interrupt vectors.  These are treated as seperate pieces of<br>
firmware and loaded by PSP<br>
<br>
The loading occurs in the sw_init hook of DM<br>
<br>
Signed-off-by: David Francis <David.Francis@amd.com><br>
---<br>
 drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h     |  2 +<br>
 drivers/gpu/drm/amd/amdgpu/psp_v10_0.c        |  6 ++<br>
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 93 +++++++++++++++++++<br>
 3 files changed, 101 insertions(+)<br>
<br>
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h<br>
index b358e7519987..38d3af317aa2 100644<br>
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h<br>
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h<br>
@@ -196,6 +196,8 @@ enum AMDGPU_UCODE_ID {<br>
         AMDGPU_UCODE_ID_UVD1,<br>
         AMDGPU_UCODE_ID_VCE,<br>
         AMDGPU_UCODE_ID_VCN,<br>
+       AMDGPU_UCODE_ID_DMCU_ERAM,<br>
+       AMDGPU_UCODE_ID_DMCU_INTV,<br>
         AMDGPU_UCODE_ID_MAXIMUM,<br>
 };<br>
 <br>
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c<br>
index 02be34e72ed9..240dc8c85867 100644<br>
--- a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c<br>
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c<br>
@@ -91,6 +91,12 @@ psp_v10_0_get_fw_type(struct amdgpu_firmware_info *ucode, enum psp_gfx_fw_type *<br>
         case AMDGPU_UCODE_ID_VCN:<br>
                 *type = GFX_FW_TYPE_VCN;<br>
                 break;<br>
+       case AMDGPU_UCODE_ID_DMCU_ERAM:<br>
+               *type = GFX_FW_TYPE_DMCU_ERAM;<br>
+               break;<br>
+       case AMDGPU_UCODE_ID_DMCU_INTV:<br>
+               *type = GFX_FW_TYPE_DMCU_ISR;<br>
+               break;<br>
         case AMDGPU_UCODE_ID_MAXIMUM:<br>
         default:<br>
                 return -EINVAL;<br>
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c<br>
index 5103eba75cb3..4619f624f346 100644<br>
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c<br>
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c<br>
@@ -30,6 +30,7 @@<br>
 #include "vid.h"<br>
 #include "amdgpu.h"<br>
 #include "amdgpu_display.h"<br>
+#include "amdgpu_ucode.h"<br>
 #include "atom.h"<br>
 #include "amdgpu_dm.h"<br>
 #include "amdgpu_pm.h"<br>
@@ -50,6 +51,7 @@<br>
 #include <linux/version.h><br>
 #include <linux/types.h><br>
 #include <linux/pm_runtime.h><br>
+#include <linux/firmware.h><br>
 <br>
 #include <drm/drmP.h><br>
 #include <drm/drm_atomic.h><br>
@@ -71,6 +73,12 @@<br>
 <br>
 #include "modules/inc/mod_freesync.h"<br>
 <br>
+#define FIRMWARE_RAVEN_DMCU_ERAM               "amdgpu/raven_dmcu_eram.bin"<br>
+MODULE_FIRMWARE(FIRMWARE_RAVEN_DMCU_ERAM);<br>
+<br>
+#define FIRMWARE_RAVEN_DMCU_INTV               "amdgpu/raven_dmcu_intv.bin"<br>
+MODULE_FIRMWARE(FIRMWARE_RAVEN_DMCU_INTV);<br>
+<br>
 /* basic init/fini API */<br>
 static int amdgpu_dm_init(struct amdgpu_device *adev);<br>
 static void amdgpu_dm_fini(struct amdgpu_device *adev);<br>
@@ -516,6 +524,91 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)<br>
 <br>
 static int dm_sw_init(void *handle)<br>
 {<br>
+       const struct firmware *fw;<br>
+       const char *fw_name_dmcu_eram;<br>
+       const char *fw_name_dmcu_intv;<br>
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;<br>
+       int r;<br>
+<br>
+       switch(adev->asic_type) {<br>
+       case CHIP_BONAIRE:<br>
+       case CHIP_HAWAII:<br>
+       case CHIP_KAVERI:<br>
+       case CHIP_KABINI:<br>
+       case CHIP_MULLINS:<br>
+       case CHIP_TONGA:<br>
+       case CHIP_FIJI:<br>
+       case CHIP_CARRIZO:<br>
+       case CHIP_STONEY:<br>
+       case CHIP_POLARIS11:<br>
+       case CHIP_POLARIS10:<br>
+       case CHIP_POLARIS12:<br>
+       case CHIP_VEGAM:<br>
+       case CHIP_VEGA10:<br>
+       case CHIP_VEGA12:<br>
+       case CHIP_VEGA20:<br>
+               return 0;<br>
+       case CHIP_RAVEN:<br>
+               fw_name_dmcu_eram = FIRMWARE_RAVEN_DMCU_ERAM;<br>
+               fw_name_dmcu_intv = FIRMWARE_RAVEN_DMCU_INTV;<br>
+               break;<br>
+       default:<br>
+               DRM_ERROR("Unsupported ASIC type: 0x%X\n", adev->asic_type);<br>
+               return -1;<br>
+       }<br>
+<br>
+       r = request_firmware(&fw, fw_name_dmcu_eram, adev->dev);<br>
+       if (r) {<br>
+               dev_err(adev->dev, "amdgpu_dm: Can't load firmware \"%s\"\n",<br>
+                       fw_name_dmcu_eram);<br>
+               return r;<br>
+       }<br>
+<br>
+       r = amdgpu_ucode_validate(fw);<br>
+       if (r) {<br>
+               dev_err(adev->dev, "amdgpu_dm: Can't validate firmware \"%s\"\n",<br>
+                       fw_name_dmcu_eram);<br>
+               release_firmware(fw);<br>
+               fw = NULL;<br>
+               return r;<br>
+       }<br>
+<br>
+       if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {<br>
+               const struct common_firmware_header *hdr;<br>
+               hdr = (const struct common_firmware_header *)fw->data;<br>
+               adev->firmware.ucode[AMDGPU_UCODE_ID_DMCU_ERAM].ucode_id = AMDGPU_UCODE_ID_DMCU_ERAM;<br>
+               adev->firmware.ucode[AMDGPU_UCODE_ID_DMCU_ERAM].fw = fw;<br>
+               adev->firmware.fw_size +=<br>
+                       ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);<br>
+               DRM_INFO("PSP loading DMCU_ERAM firmware\n");<br>
+       }<br>
+<br>
+       r = request_firmware(&fw, fw_name_dmcu_intv, adev->dev);<br>
+       if (r) {<br>
+               dev_err(adev->dev, "amdgpu_dm: Can't load firmware \"%s\"\n",<br>
+                               fw_name_dmcu_intv);<br>
+               return r;<br>
+       }<br>
+<br>
+       r = amdgpu_ucode_validate(fw);<br>
+       if (r) {<br>
+               dev_err(adev->dev, "amdgpu_dm: Can't validate firmware \"%s\"\n",<br>
+                               fw_name_dmcu_intv);<br>
+               release_firmware(fw);<br>
+               fw = NULL;<br>
+               return r;<br>
+       }<br>
+<br>
+       if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {<br>
+               const struct common_firmware_header *hdr;<br>
+               hdr = (const struct common_firmware_header *)fw->data;<br>
+               adev->firmware.ucode[AMDGPU_UCODE_ID_DMCU_INTV].ucode_id = AMDGPU_UCODE_ID_DMCU_INTV;<br>
+               adev->firmware.ucode[AMDGPU_UCODE_ID_DMCU_INTV].fw = fw;<br>
+               adev->firmware.fw_size +=<br>
+                       ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);<br>
+               DRM_INFO("PSP loading DMCU_INTV firmware\n");<br>
+       }<br>
+<br>
         return 0;<br>
 }<br>
 <br>
-- <br>
2.17.1<br>
<br>
</div>
</span></font></div>
</div>
</body>
</html>