]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
drm/amd/display: Restore rptr/wptr for DMCUB as workaround
authorJinZe.Xu <JinZe.Xu@amd.com>
Mon, 10 Apr 2023 15:23:37 +0000 (23:23 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 8 Dec 2023 07:51:19 +0000 (08:51 +0100)
[ Upstream commit 8f3589bb6fcea397775398cba4fbcc46829a60ed ]

[Why]
States may be desync after resume.

[How]
Sync sw state with hw state.

Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: JinZe.Xu <JinZe.Xu@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Stable-dep-of: 1ffa8602e39b ("drm/amd/display: Guard against invalid RPTR/WPTR being set")
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/gpu/drm/amd/display/dmub/dmub_srv.h
drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h
drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h
drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c
drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.h
drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c

index a21fe7b037d1fe675dbbb5471bbd87314f614031..aaabaab49809d1b1b811343117c091080e95bdd6 100644 (file)
@@ -332,6 +332,8 @@ struct dmub_srv_hw_funcs {
        void (*setup_mailbox)(struct dmub_srv *dmub,
                              const struct dmub_region *inbox1);
 
+       uint32_t (*get_inbox1_wptr)(struct dmub_srv *dmub);
+
        uint32_t (*get_inbox1_rptr)(struct dmub_srv *dmub);
 
        void (*set_inbox1_wptr)(struct dmub_srv *dmub, uint32_t wptr_offset);
@@ -590,6 +592,18 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub,
  */
 enum dmub_status dmub_srv_hw_reset(struct dmub_srv *dmub);
 
+/**
+ * dmub_srv_sync_inbox1() - sync sw state with hw state
+ * @dmub: the dmub service
+ *
+ * Sync sw state with hw state when resume from S0i3
+ *
+ * Return:
+ *   DMUB_STATUS_OK - success
+ *   DMUB_STATUS_INVALID - unspecified error
+ */
+enum dmub_status dmub_srv_sync_inbox1(struct dmub_srv *dmub);
+
 /**
  * dmub_srv_cmd_queue() - queues a command to the DMUB
  * @dmub: the dmub service
index a6540e27044d289c67d93eb4389282c8828b27b5..98dad0d47e72cfd87f012b34e61067ee64df9936 100644 (file)
@@ -282,6 +282,11 @@ void dmub_dcn20_setup_mailbox(struct dmub_srv *dmub,
        REG_WRITE(DMCUB_INBOX1_SIZE, inbox1->top - inbox1->base);
 }
 
+uint32_t dmub_dcn20_get_inbox1_wptr(struct dmub_srv *dmub)
+{
+       return REG_READ(DMCUB_INBOX1_WPTR);
+}
+
 uint32_t dmub_dcn20_get_inbox1_rptr(struct dmub_srv *dmub)
 {
        return REG_READ(DMCUB_INBOX1_RPTR);
index c2e5831ac52cc017454587b4c23d423d40ef591c..1df128e57ed3bc4c610242bb91dcdfc9755a612e 100644 (file)
@@ -202,6 +202,8 @@ void dmub_dcn20_setup_windows(struct dmub_srv *dmub,
 void dmub_dcn20_setup_mailbox(struct dmub_srv *dmub,
                              const struct dmub_region *inbox1);
 
+uint32_t dmub_dcn20_get_inbox1_wptr(struct dmub_srv *dmub);
+
 uint32_t dmub_dcn20_get_inbox1_rptr(struct dmub_srv *dmub);
 
 void dmub_dcn20_set_inbox1_wptr(struct dmub_srv *dmub, uint32_t wptr_offset);
index 89d24fb7024e2be0cac7839f9ec660dd3dfb2dc4..5e952541e72d5160edb6bd3eeae7356aebf8618e 100644 (file)
@@ -242,6 +242,11 @@ void dmub_dcn31_setup_mailbox(struct dmub_srv *dmub,
        REG_WRITE(DMCUB_INBOX1_SIZE, inbox1->top - inbox1->base);
 }
 
+uint32_t dmub_dcn31_get_inbox1_wptr(struct dmub_srv *dmub)
+{
+       return REG_READ(DMCUB_INBOX1_WPTR);
+}
+
 uint32_t dmub_dcn31_get_inbox1_rptr(struct dmub_srv *dmub)
 {
        return REG_READ(DMCUB_INBOX1_RPTR);
index eb62410941473ab5ae6a256bfd233883bd7e8942..89c5a948b67d5c1228c4d73c7cd029902e5575c6 100644 (file)
@@ -204,6 +204,8 @@ void dmub_dcn31_setup_windows(struct dmub_srv *dmub,
 void dmub_dcn31_setup_mailbox(struct dmub_srv *dmub,
                              const struct dmub_region *inbox1);
 
+uint32_t dmub_dcn31_get_inbox1_wptr(struct dmub_srv *dmub);
+
 uint32_t dmub_dcn31_get_inbox1_rptr(struct dmub_srv *dmub);
 
 void dmub_dcn31_set_inbox1_wptr(struct dmub_srv *dmub, uint32_t wptr_offset);
index 9c20516be066ccd6b1e620b7b61fc78d41ce544f..d2f03f797279f41d14265eb7edfac5bec72eb087 100644 (file)
@@ -266,6 +266,11 @@ void dmub_dcn32_setup_mailbox(struct dmub_srv *dmub,
        REG_WRITE(DMCUB_INBOX1_SIZE, inbox1->top - inbox1->base);
 }
 
+uint32_t dmub_dcn32_get_inbox1_wptr(struct dmub_srv *dmub)
+{
+       return REG_READ(DMCUB_INBOX1_WPTR);
+}
+
 uint32_t dmub_dcn32_get_inbox1_rptr(struct dmub_srv *dmub)
 {
        return REG_READ(DMCUB_INBOX1_RPTR);
index 7d1a6eb4d6657869b2307641531d1b8ac48f36fe..f15336b6e22beea07375b520982e1336061c3e45 100644 (file)
@@ -206,6 +206,8 @@ void dmub_dcn32_setup_windows(struct dmub_srv *dmub,
 void dmub_dcn32_setup_mailbox(struct dmub_srv *dmub,
                              const struct dmub_region *inbox1);
 
+uint32_t dmub_dcn32_get_inbox1_wptr(struct dmub_srv *dmub);
+
 uint32_t dmub_dcn32_get_inbox1_rptr(struct dmub_srv *dmub);
 
 void dmub_dcn32_set_inbox1_wptr(struct dmub_srv *dmub, uint32_t wptr_offset);
index f58803de37cb07f658c47a72279a18f0918d4512..6b8bd556c872f3757e180df8b8588f69e1c06bff 100644 (file)
@@ -167,6 +167,7 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic)
                funcs->backdoor_load = dmub_dcn20_backdoor_load;
                funcs->setup_windows = dmub_dcn20_setup_windows;
                funcs->setup_mailbox = dmub_dcn20_setup_mailbox;
+               funcs->get_inbox1_wptr = dmub_dcn20_get_inbox1_wptr;
                funcs->get_inbox1_rptr = dmub_dcn20_get_inbox1_rptr;
                funcs->set_inbox1_wptr = dmub_dcn20_set_inbox1_wptr;
                funcs->is_supported = dmub_dcn20_is_supported;
@@ -243,6 +244,7 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic)
                funcs->backdoor_load = dmub_dcn31_backdoor_load;
                funcs->setup_windows = dmub_dcn31_setup_windows;
                funcs->setup_mailbox = dmub_dcn31_setup_mailbox;
+               funcs->get_inbox1_wptr = dmub_dcn31_get_inbox1_wptr;
                funcs->get_inbox1_rptr = dmub_dcn31_get_inbox1_rptr;
                funcs->set_inbox1_wptr = dmub_dcn31_set_inbox1_wptr;
                funcs->setup_out_mailbox = dmub_dcn31_setup_out_mailbox;
@@ -281,6 +283,7 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic)
                funcs->backdoor_load_zfb_mode = dmub_dcn32_backdoor_load_zfb_mode;
                funcs->setup_windows = dmub_dcn32_setup_windows;
                funcs->setup_mailbox = dmub_dcn32_setup_mailbox;
+               funcs->get_inbox1_wptr = dmub_dcn32_get_inbox1_wptr;
                funcs->get_inbox1_rptr = dmub_dcn32_get_inbox1_rptr;
                funcs->set_inbox1_wptr = dmub_dcn32_set_inbox1_wptr;
                funcs->setup_out_mailbox = dmub_dcn32_setup_out_mailbox;
@@ -666,6 +669,20 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub,
        return DMUB_STATUS_OK;
 }
 
+enum dmub_status dmub_srv_sync_inbox1(struct dmub_srv *dmub)
+{
+       if (!dmub->sw_init)
+               return DMUB_STATUS_INVALID;
+
+       if (dmub->hw_funcs.get_inbox1_rptr && dmub->hw_funcs.get_inbox1_wptr) {
+               dmub->inbox1_rb.rptr = dmub->hw_funcs.get_inbox1_rptr(dmub);
+               dmub->inbox1_rb.wrpt = dmub->hw_funcs.get_inbox1_wptr(dmub);
+               dmub->inbox1_last_wptr = dmub->inbox1_rb.wrpt;
+       }
+
+       return DMUB_STATUS_OK;
+}
+
 enum dmub_status dmub_srv_hw_reset(struct dmub_srv *dmub)
 {
        if (!dmub->sw_init)