HWSEQ_REG_SET_N(reg, 1, FD(reg##__##field), val)
 
 /* TODO should be moved to OTG */
-static void lock_otg_master_update(
-       struct dc_context *ctx,
-       uint8_t inst)
-{
-       uint32_t inst_offset = reg_offsets[inst].otg;
-
-       HWSEQ_REG_UPDATE(OTG0_OTG_GLOBAL_CONTROL0,
-                       OTG_MASTER_UPDATE_LOCK_SEL, inst);
-
-       HWSEQ_REG_UPDATE(OTG0_OTG_MASTER_UPDATE_LOCK,
-                       OTG_MASTER_UPDATE_LOCK, 1);
-}
 
 static bool unlock_master_tg_and_wait(
        struct dc_context *ctx,
        return true;
 }
 
-/* TODO: should be  moved to OTG ? */
-static void unlock_otg_master(
-       struct dc_context *ctx,
-       uint8_t inst)
-{
-       uint32_t inst_offset = reg_offsets[inst].otg;
-
-       /* unlock master locker */
-       HWSEQ_REG_UPDATE(OTG0_OTG_MASTER_UPDATE_LOCK,
-                       OTG_MASTER_UPDATE_LOCK, 0);
-}
-
-
 static void wait_no_outstanding_request(
        struct dc_context *ctx,
        uint8_t plane_id)
 
 static void power_on_plane(
        struct dc_context *ctx,
-       uint8_t plane_id,
-       uint8_t inst)
+       int plane_id)
 {
        uint32_t inst_offset = 0;
 
        hubp_pg_control(ctx, plane_id, true);
        HWSEQ_REG_SET(DC_IP_REQUEST_CNTL,
                        IP_REQUEST_EN, 0);
+       dm_logger_write(ctx->logger, LOG_DC,
+                       "Un-gated front end for pipe %d\n", plane_id);
 }
 
 /* fully check bios enabledisplaypowergating table. dal only need dce init
                                dc->res_pool->mpcc[i];
                struct mpcc_cfg mpcc_cfg;
 
-               lock_otg_master_update(dc->ctx, tg->inst);
+               tg->funcs->lock(tg);
                mpcc_cfg.opp_id = 0xf;
                mpcc_cfg.top_dpp_id = 0xf;
                mpcc_cfg.bot_mpcc_id = 0xf;
                mpcc_cfg.top_of_tree = true;
                mpcc->funcs->set(mpcc, &mpcc_cfg);
-               unlock_otg_master(dc->ctx, tg->inst);
+               tg->funcs->unlock(tg);
 
                tg->funcs->disable_vga(tg);
                /* Blank controller using driver code instead of
                return;
 
        pipe_ctx->stream = NULL;
+       dm_logger_write(dc->ctx->logger, LOG_DC,
+                                       "Reset back end for pipe %d, tg:%d\n",
+                                       pipe_ctx->pipe_idx, pipe_ctx->tg->inst);
 }
 
-static void reset_front_end_for_pipe(
+static void reset_front_end(
                struct core_dc *dc,
-               struct pipe_ctx *pipe_ctx,
-               struct validate_context *context)
+               int fe_idx)
 {
        struct mpcc_cfg mpcc_cfg;
+       struct mem_input *mi = dc->res_pool->mis[fe_idx];
+       struct transform *xfm = dc->res_pool->transforms[fe_idx];
+       struct mpcc *mpcc = dc->res_pool->mpcc[fe_idx];
+       struct timing_generator *tg = dc->res_pool->timing_generators[mpcc->opp_id];
 
-       if (!pipe_ctx->surface)
+       /*Already reset*/
+       if (mpcc->opp_id == 0xf)
                return;
 
-       pipe_ctx->mi->funcs->dcc_control(pipe_ctx->mi, false, false);
-
-       lock_otg_master_update(dc->ctx, pipe_ctx->tg->inst);
+       mi->funcs->dcc_control(mi, false, false);
+       tg->funcs->lock(tg);
 
        mpcc_cfg.opp_id = 0xf;
        mpcc_cfg.top_dpp_id = 0xf;
        mpcc_cfg.bot_mpcc_id = 0xf;
-       mpcc_cfg.top_of_tree = !pipe_ctx->top_pipe;
-       pipe_ctx->mpcc->funcs->set(pipe_ctx->mpcc, &mpcc_cfg);
-
-       pipe_ctx->top_pipe = NULL;
-       pipe_ctx->bottom_pipe = NULL;
+       mpcc_cfg.top_of_tree = tg->inst == mpcc->inst;
+       mpcc->funcs->set(mpcc, &mpcc_cfg);
 
-       unlock_master_tg_and_wait(dc->ctx, pipe_ctx->tg->inst);
+       unlock_master_tg_and_wait(dc->ctx, tg->inst);
+       mpcc->funcs->wait_for_idle(mpcc);
+       mi->funcs->set_blank(mi, true);
+       wait_no_outstanding_request(dc->ctx, fe_idx);
+       disable_clocks(dc->ctx, fe_idx);
 
-       pipe_ctx->mi->funcs->set_blank(pipe_ctx->mi, true);
+       xfm->funcs->transform_reset(xfm);
 
-       wait_no_outstanding_request(dc->ctx, pipe_ctx->pipe_idx);
+       dm_logger_write(dc->ctx->logger, LOG_DC,
+                                       "Reset front end %d\n",
+                                       fe_idx);
+}
 
-       disable_clocks(dc->ctx, pipe_ctx->pipe_idx);
+static void dcn10_power_down_fe(struct core_dc *dc, int fe_idx)
+{
+       struct dc_context *ctx = dc->ctx;
+       uint32_t inst_offset = 0;
 
-       pipe_ctx->xfm->funcs->transform_reset(pipe_ctx->xfm);
+       reset_front_end(dc, fe_idx);
 
+       HWSEQ_REG_SET(DC_IP_REQUEST_CNTL,
+                       IP_REQUEST_EN, 1);
+       dpp_pg_control(ctx, fe_idx, false);
+       hubp_pg_control(ctx, fe_idx, false);
+       HWSEQ_REG_SET(DC_IP_REQUEST_CNTL,
+                       IP_REQUEST_EN, 0);
        dm_logger_write(dc->ctx->logger, LOG_DC,
-                                       "Reset front end for pipe %d\n",
-                                       pipe_ctx->pipe_idx);
-
-       pipe_ctx->surface = NULL;
+                       "Power gated front end %d\n", fe_idx);
 }
 
-static void reset_hw_ctx(struct core_dc *dc,
-               struct validate_context *context,
-               void (*reset)(struct core_dc *dc,
-                               struct pipe_ctx *pipe_ctx,
-                               struct validate_context *context))
+static void reset_hw_ctx_wrap(
+               struct core_dc *dc,
+               struct validate_context *context)
 {
        int i;
 
+       /* Reset Front End*/
+       for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) {
+               struct pipe_ctx *pipe_ctx_old =
+                       &dc->current_context->res_ctx.pipe_ctx[i];
+               struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+
+               /*if (!pipe_ctx_old->stream)
+                       continue;*/
+
+               if (!pipe_ctx->stream || !pipe_ctx->surface)
+                       dcn10_power_down_fe(dc, i);
+               else if (pipe_need_reprogram(pipe_ctx_old, pipe_ctx))
+                       reset_front_end(dc, i);
+       }
+       /* Reset Back End*/
        for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) {
                struct pipe_ctx *pipe_ctx_old =
                        &dc->current_context->res_ctx.pipe_ctx[i];
 
                if (!pipe_ctx->stream ||
                                pipe_need_reprogram(pipe_ctx_old, pipe_ctx))
-                       reset(dc, pipe_ctx_old, dc->current_context);
+                       reset_back_end_for_pipe(dc, pipe_ctx_old, dc->current_context);
        }
 }
 
-static void reset_hw_ctx_wrap(
-               struct core_dc *dc,
-               struct validate_context *context)
-{
-       /* Reset Front End*/
-       reset_hw_ctx(dc, context, reset_front_end_for_pipe);
-       /* Reset Back End*/
-       reset_hw_ctx(dc, context, reset_back_end_for_pipe);
-}
-
 
-static bool patch_address_for_sbs_tb_stereo(struct pipe_ctx *pipe_ctx,
-                                                                                       PHYSICAL_ADDRESS_LOC *addr)
+static bool patch_address_for_sbs_tb_stereo(
+               struct pipe_ctx *pipe_ctx, PHYSICAL_ADDRESS_LOC *addr)
 {
        struct core_surface *surface = pipe_ctx->surface;
        bool sec_split = pipe_ctx->top_pipe &&
 }
 
 static bool dcn10_set_input_transfer_func(
-       struct pipe_ctx *pipe_ctx,
-       const struct core_surface *surface)
+       struct pipe_ctx *pipe_ctx, const struct core_surface *surface)
 {
        struct input_pixel_processor *ipp = pipe_ctx->ipp;
        const struct core_transfer_func *tf = NULL;
                tf = DC_TRANSFER_FUNC_TO_CORE(surface->public.in_transfer_func);
 
        if (surface->public.gamma_correction && dce_use_lut(surface))
-           ipp->funcs->ipp_program_input_lut(ipp,
-                           surface->public.gamma_correction);
+               ipp->funcs->ipp_program_input_lut(ipp,
+                               surface->public.gamma_correction);
 
        if (tf == NULL)
                ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS);
        struct pipe_ctx *pipe,
        bool lock)
 {
-       struct dce_hwseq *hws = hws = dc->hwseq;
-
        /* use TG master update lock to lock everything on the TG
         * therefore only top pipe need to lock
         */
                return;
 
        if (lock)
-               dcn10_lock(pipe->tg);
+               pipe->tg->funcs->lock(pipe->tg);
        else
-               dcn10_unlock(pipe->tg);
+               pipe->tg->funcs->unlock(pipe->tg);
 }
 
 static bool wait_for_reset_trigger_to_occur(
        struct dc_surface *dc_surface = &pipe_ctx->surface->public;
 
        power_on_plane(dc->ctx,
-               pipe_ctx->pipe_idx, pipe_ctx->tg->inst);
+               pipe_ctx->pipe_idx);
 
        /* enable DCFCLK current DCHUB */
        enable_dcfclk(dc->ctx,
        struct default_adjustment ocsc = {0};
        struct tg_color black_color = {0};
        struct mpcc_cfg mpcc_cfg;
-       struct pipe_ctx *top_pipe;
        bool per_pixel_alpha = surface->public.per_pixel_alpha && pipe_ctx->bottom_pipe;
 
        /* TODO: proper fix once fpga works */
                        IPP_OUTPUT_FORMAT_12_BIT_FIX);
 
        pipe_ctx->scl_data.lb_params.alpha_en = per_pixel_alpha;
-       for (top_pipe = pipe_ctx; top_pipe != NULL; top_pipe = top_pipe->top_pipe)
-               mpcc_cfg.opp_id = top_pipe->opp->inst;
        mpcc_cfg.top_dpp_id = pipe_ctx->pipe_idx;
        if (pipe_ctx->bottom_pipe)
                mpcc_cfg.bot_mpcc_id = pipe_ctx->bottom_pipe->mpcc->inst;
        else
                mpcc_cfg.bot_mpcc_id = 0xf;
-       mpcc_cfg.top_of_tree = !pipe_ctx->top_pipe;
+       mpcc_cfg.opp_id = pipe_ctx->tg->inst;
+       mpcc_cfg.top_of_tree = pipe_ctx->pipe_idx == pipe_ctx->tg->inst;
        mpcc_cfg.per_pixel_alpha = per_pixel_alpha;
        /* DCN1.0 has output CM before MPC which seems to screw with
         * pre-multiplied alpha.
        mpcc_cfg.pre_multiplied_alpha = is_rgb_cspace(
                        pipe_ctx->stream->public.output_color_space)
                                        && per_pixel_alpha;
-       if (!dc->current_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx].surface)
-               pipe_ctx->mpcc->funcs->wait_for_idle(pipe_ctx->mpcc);
        pipe_ctx->mpcc->funcs->set(pipe_ctx->mpcc, &mpcc_cfg);
 
        color_space_to_black_color(
                /* watermark is for all pipes */
                pipe_ctx->mi->funcs->program_watermarks(
                                pipe_ctx->mi, &context->bw.dcn.watermarks, ref_clk_mhz);
-               lock_otg_master_update(dc->ctx, pipe_ctx->tg->inst);
+               pipe_ctx->tg->funcs->lock(pipe_ctx->tg);
 
                pipe_ctx->tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset;
                pipe_ctx->tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start;
 {
        int i;
 
+       /* reset unused mpcc */
+       /*for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+               struct pipe_ctx *old_pipe_ctx =
+                               &dc->current_context->res_ctx.pipe_ctx[i];
+
+               if ((!pipe_ctx->surface && old_pipe_ctx->surface)
+                               || (!pipe_ctx->stream && old_pipe_ctx->stream)) {
+                       struct mpcc_cfg mpcc_cfg;
+
+                       mpcc_cfg.opp_id = 0xf;
+                       mpcc_cfg.top_dpp_id = 0xf;
+                       mpcc_cfg.bot_mpcc_id = 0xf;
+                       mpcc_cfg.top_of_tree = !old_pipe_ctx->top_pipe;
+                       old_pipe_ctx->mpcc->funcs->set(old_pipe_ctx->mpcc, &mpcc_cfg);
+
+                       old_pipe_ctx->top_pipe = NULL;
+                       old_pipe_ctx->bottom_pipe = NULL;
+                       old_pipe_ctx->surface = NULL;
+
+                       dm_logger_write(dc->ctx->logger, LOG_DC,
+                                       "Reset mpcc for pipe %d\n",
+                                       old_pipe_ctx->pipe_idx);
+               }
+       }*/
+
+       if (!surface)
+               return;
+
        for (i = 0; i < dc->res_pool->pipe_count; i++) {
                struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
 
-               if (!pipe_ctx->surface || pipe_ctx->surface != surface)
+               if (pipe_ctx->surface != surface)
                        continue;
 
-
                /* looking for top pipe to program */
                if (!pipe_ctx->top_pipe)
                        program_all_pipe_in_tree(dc, pipe_ctx, context);
                        context->bw.dcn.watermarks.d.cstate_pstate.pstate_change_ns,
                        context->bw.dcn.watermarks.d.pte_meta_urgent_ns
                        );
-
-       for (i = 0; i < dc->res_pool->pipe_count; i++) {
-               struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
-
-               if (!pipe_ctx->surface || pipe_ctx->top_pipe)
-                       continue;
-
-               /* unlock master update lock */
-               unlock_otg_master(dc->ctx, pipe_ctx->tg->inst);
-       }
-
-       /* reset unused pipe */
-       for (i = 0; i < dc->res_pool->pipe_count; i++) {
-               struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
-               struct pipe_ctx *old_pipe_ctx =
-                               &dc->current_context->res_ctx.pipe_ctx[i];
-
-               if ((!pipe_ctx->surface && old_pipe_ctx->surface)
-                               || (!pipe_ctx->stream && old_pipe_ctx->stream))
-                       reset_front_end_for_pipe(dc, old_pipe_ctx, dc->current_context);
-       }
 }
 
 static void dcn10_set_bandwidth(
        dcn10_pplib_apply_display_requirements(dc, context);
 }
 
-static void dcn10_power_down_fe(struct core_dc *dc, struct pipe_ctx *pipe)
-{
-       struct dc_context *ctx = dc->ctx;
-       uint32_t inst_offset = 0;
-
-       HWSEQ_REG_SET(DC_IP_REQUEST_CNTL,
-                       IP_REQUEST_EN, 1);
-       dpp_pg_control(ctx, pipe->pipe_idx, false);
-       hubp_pg_control(ctx, pipe->pipe_idx, false);
-       HWSEQ_REG_SET(DC_IP_REQUEST_CNTL,
-                       IP_REQUEST_EN, 0);
-
-       if (pipe->xfm)
-               pipe->xfm->funcs->transform_reset(pipe->xfm);
-       memset(&pipe->scl_data, 0, sizeof(pipe->scl_data));
-}
-
 static void set_drr(struct pipe_ctx **pipe_ctx,
                int num_pipes, int vmin, int vmax)
 {