bool az_endpoint_mute_only;
        bool always_use_regamma;
        bool p010_mpo_support;
+       bool recovery_enabled;
+
 };
 struct dc_state;
 struct resource_pool;
 
                        DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, watermark_change_req);
 }
 
+void hubbub1_soft_reset(struct hubbub *hubbub, bool reset)
+{
+       uint32_t reset_en = reset ? 1 : 0;
+
+       REG_UPDATE(DCHUBBUB_SOFT_RESET,
+                       DCHUBBUB_GLOBAL_SOFT_RESET, reset_en);
+}
+
 static bool hubbub1_dcc_support_swizzle(
                enum swizzle_mode_values swizzle,
                unsigned int bytes_per_element,
 
        SR(DCHUBBUB_ARB_DF_REQ_OUTSTAND),\
        SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \
        SR(DCHUBBUB_TEST_DEBUG_INDEX), \
-       SR(DCHUBBUB_TEST_DEBUG_DATA)
+       SR(DCHUBBUB_TEST_DEBUG_DATA),\
+       SR(DCHUBBUB_SOFT_RESET)
 
 #define HUBBUB_SR_WATERMARK_REG_LIST()\
        SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A),\
        uint32_t DCHUBBUB_SDPIF_AGP_BOT;
        uint32_t DCHUBBUB_SDPIF_AGP_TOP;
        uint32_t DCHUBBUB_CRC_CTRL;
+       uint32_t DCHUBBUB_SOFT_RESET;
 };
 
 /* set field name */
 
 #define HUBBUB_MASK_SH_LIST_DCN(mask_sh)\
                HUBBUB_SF(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, mask_sh), \
+               HUBBUB_SF(DCHUBBUB_SOFT_RESET, DCHUBBUB_GLOBAL_SOFT_RESET, mask_sh), \
                HUBBUB_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, mask_sh), \
                HUBBUB_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, mask_sh), \
                HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, mask_sh), \
                type DCHUBBUB_ARB_SAT_LEVEL;\
                type DCHUBBUB_ARB_MIN_REQ_OUTSTAND;\
                type DCHUBBUB_GLOBAL_TIMER_REFDIV;\
+               type DCHUBBUB_GLOBAL_SOFT_RESET; \
                type SDPIF_FB_TOP;\
                type SDPIF_FB_BASE;\
                type SDPIF_FB_OFFSET;\
 void hubbub1_wm_read_state(struct hubbub *hubbub,
                struct dcn_hubbub_wm *wm);
 
+void hubbub1_soft_reset(struct hubbub *hubbub, bool reset);
 void hubbub1_construct(struct hubbub *hubbub,
        struct dc_context *ctx,
        const struct dcn_hubbub_registers *hubbub_regs,
 
                        CURSOR_ENABLE, 0);
 }
 
+static void hubp1_disable_control(struct hubp *hubp, bool disable_hubp)
+{
+       struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp);
+       uint32_t disable = disable_hubp ? 1 : 0;
+
+       REG_UPDATE(DCHUBP_CNTL,
+                       HUBP_DISABLE, disable);
+}
+
+static unsigned int hubp1_get_underflow_status(struct hubp *hubp)
+{
+       uint32_t hubp_underflow = 0;
+       struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp);
+
+       REG_GET(DCHUBP_CNTL,
+               HUBP_UNDERFLOW_STATUS,
+               &hubp_underflow);
+
+       return hubp_underflow;
+}
+
 static void hubp1_set_hubp_blank_en(struct hubp *hubp, bool blank)
 {
        struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp);
        .hubp_clk_cntl = hubp1_clk_cntl,
        .hubp_vtg_sel = hubp1_vtg_sel,
        .hubp_read_state = hubp1_read_state,
+       .hubp_disable_control =  hubp1_disable_control,
+       .hubp_get_underflow_status = hubp1_get_underflow_status,
+
 };
 
 /*****************************************/
 
        HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_UNDERFLOW_STATUS, mask_sh),\
        HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, mask_sh),\
        HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_VTG_SEL, mask_sh),\
+       HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_DISABLE, mask_sh),\
        HUBP_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_PIPES, mask_sh),\
        HUBP_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_BANKS, mask_sh),\
        HUBP_SF(HUBP0_DCSURF_ADDR_CONFIG, PIPE_INTERLEAVE, mask_sh),\
 
 #define DCN_HUBP_REG_FIELD_LIST(type) \
        type HUBP_BLANK_EN;\
+       type HUBP_DISABLE;\
        type HUBP_TTU_DISABLE;\
        type HUBP_NO_OUTSTANDING_REQ;\
        type HUBP_VTG_SEL;\
 
 enum cursor_pitch hubp1_get_cursor_pitch(unsigned int pitch);
 
+
 #endif
 
                                        pipe_ctx->pipe_idx, pipe_ctx->stream_res.tg->inst);
 }
 
+static bool dcn10_hw_wa_force_recovery(struct dc *dc)
+{
+       struct hubp *hubp ;
+       unsigned int i;
+       bool need_recover = true;
+
+       if (!dc->debug.recovery_enabled)
+               return false;
+
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               struct pipe_ctx *pipe_ctx =
+                       &dc->current_state->res_ctx.pipe_ctx[i];
+               if (pipe_ctx != NULL) {
+                       hubp = pipe_ctx->plane_res.hubp;
+                       if (hubp != NULL) {
+                               if (hubp->funcs->hubp_get_underflow_status(hubp) != 0) {
+                                       /* one pipe underflow, we will reset all the pipes*/
+                                       need_recover = true;
+                               }
+                       }
+               }
+       }
+       if (!need_recover)
+               return false;
+       /*
+       DCHUBP_CNTL:HUBP_BLANK_EN=1
+       DCHUBBUB_SOFT_RESET:DCHUBBUB_GLOBAL_SOFT_RESET=1
+       DCHUBP_CNTL:HUBP_DISABLE=1
+       DCHUBP_CNTL:HUBP_DISABLE=0
+       DCHUBBUB_SOFT_RESET:DCHUBBUB_GLOBAL_SOFT_RESET=0
+       DCSURF_PRIMARY_SURFACE_ADDRESS
+       DCHUBP_CNTL:HUBP_BLANK_EN=0
+       */
+
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               struct pipe_ctx *pipe_ctx =
+                       &dc->current_state->res_ctx.pipe_ctx[i];
+               if (pipe_ctx != NULL) {
+                       hubp = pipe_ctx->plane_res.hubp;
+                       /*DCHUBP_CNTL:HUBP_BLANK_EN=1*/
+                       if (hubp != NULL)
+                               hubp->funcs->set_hubp_blank_en(hubp, true);
+               }
+       }
+       /*DCHUBBUB_SOFT_RESET:DCHUBBUB_GLOBAL_SOFT_RESET=1*/
+       hubbub1_soft_reset(dc->res_pool->hubbub, true);
+
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               struct pipe_ctx *pipe_ctx =
+                       &dc->current_state->res_ctx.pipe_ctx[i];
+               if (pipe_ctx != NULL) {
+                       hubp = pipe_ctx->plane_res.hubp;
+                       /*DCHUBP_CNTL:HUBP_DISABLE=1*/
+                       if (hubp != NULL)
+                               hubp->funcs->hubp_disable_control(hubp, true);
+               }
+       }
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               struct pipe_ctx *pipe_ctx =
+                       &dc->current_state->res_ctx.pipe_ctx[i];
+               if (pipe_ctx != NULL) {
+                       hubp = pipe_ctx->plane_res.hubp;
+                       /*DCHUBP_CNTL:HUBP_DISABLE=0*/
+                       if (hubp != NULL)
+                               hubp->funcs->hubp_disable_control(hubp, true);
+               }
+       }
+       /*DCHUBBUB_SOFT_RESET:DCHUBBUB_GLOBAL_SOFT_RESET=0*/
+       hubbub1_soft_reset(dc->res_pool->hubbub, false);
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               struct pipe_ctx *pipe_ctx =
+                       &dc->current_state->res_ctx.pipe_ctx[i];
+               if (pipe_ctx != NULL) {
+                       hubp = pipe_ctx->plane_res.hubp;
+                       /*DCHUBP_CNTL:HUBP_BLANK_EN=0*/
+                       if (hubp != NULL)
+                               hubp->funcs->set_hubp_blank_en(hubp, true);
+               }
+       }
+       return true;
+
+}
+
+
 static void dcn10_verify_allow_pstate_change_high(struct dc *dc)
 {
        static bool should_log_hw_state; /* prevent hw state log by default */
                if (should_log_hw_state) {
                        dcn10_log_hw_state(dc);
                }
-
                BREAK_TO_DEBUGGER();
+               if (dcn10_hw_wa_force_recovery(dc)) {
+               /*check again*/
+                       if (!hubbub1_verify_allow_pstate_change_high(dc->res_pool->hubbub))
+                               BREAK_TO_DEBUGGER();
+               }
        }
 }
 
 
                .vsr_support = true,
                .performance_trace = false,
                .az_endpoint_mute_only = true,
+               .recovery_enabled = false, /*enable this by default after testing.*/
 };
 
 static const struct dc_debug debug_defaults_diags = {
 
        void (*hubp_clk_cntl)(struct hubp *hubp, bool enable);
        void (*hubp_vtg_sel)(struct hubp *hubp, uint32_t otg_inst);
        void (*hubp_read_state)(struct hubp *hubp);
+       void (*hubp_disable_control)(struct hubp *hubp, bool disable_hubp);
+       unsigned int (*hubp_get_underflow_status)(struct hubp *hubp);
 
 };