drm/amd/display: move wm ranges reporting to end of init hw
[linux-2.6-microblaze.git] / drivers / gpu / drm / amd / display / dc / dcn10 / dcn10_hw_sequencer.c
index e50a696..eb91432 100644 (file)
@@ -438,7 +438,7 @@ bool dcn10_did_underflow_occur(struct dc *dc, struct pipe_ctx *pipe_ctx)
        return false;
 }
 
-static void enable_power_gating_plane(
+static void dcn10_enable_power_gating_plane(
        struct dce_hwseq *hws,
        bool enable)
 {
@@ -460,7 +460,7 @@ static void enable_power_gating_plane(
        REG_UPDATE(DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, force_on);
 }
 
-static void disable_vga(
+static void dcn10_disable_vga(
        struct dce_hwseq *hws)
 {
        unsigned int in_vga1_mode = 0;
@@ -493,7 +493,7 @@ static void disable_vga(
        REG_UPDATE(VGA_TEST_CONTROL, VGA_TEST_RENDER_START, 1);
 }
 
-static void dpp_pg_control(
+static void dcn10_dpp_pg_control(
                struct dce_hwseq *hws,
                unsigned int dpp_inst,
                bool power_on)
@@ -545,7 +545,7 @@ static void dpp_pg_control(
        }
 }
 
-static void hubp_pg_control(
+static void dcn10_hubp_pg_control(
                struct dce_hwseq *hws,
                unsigned int hubp_inst,
                bool power_on)
@@ -605,8 +605,8 @@ static void power_on_plane(
        if (REG(DC_IP_REQUEST_CNTL)) {
                REG_SET(DC_IP_REQUEST_CNTL, 0,
                                IP_REQUEST_EN, 1);
-               dpp_pg_control(hws, plane_id, true);
-               hubp_pg_control(hws, plane_id, true);
+               hws->ctx->dc->hwss.dpp_pg_control(hws, plane_id, true);
+               hws->ctx->dc->hwss.hubp_pg_control(hws, plane_id, true);
                REG_SET(DC_IP_REQUEST_CNTL, 0,
                                IP_REQUEST_EN, 0);
                DC_LOG_DEBUG(
@@ -627,7 +627,7 @@ static void undo_DEGVIDCN10_253_wa(struct dc *dc)
        REG_SET(DC_IP_REQUEST_CNTL, 0,
                        IP_REQUEST_EN, 1);
 
-       hubp_pg_control(hws, 0, false);
+       dc->hwss.hubp_pg_control(hws, 0, false);
        REG_SET(DC_IP_REQUEST_CNTL, 0,
                        IP_REQUEST_EN, 0);
 
@@ -656,7 +656,7 @@ static void apply_DEGVIDCN10_253_wa(struct dc *dc)
        REG_SET(DC_IP_REQUEST_CNTL, 0,
                        IP_REQUEST_EN, 1);
 
-       hubp_pg_control(hws, 0, true);
+       dc->hwss.hubp_pg_control(hws, 0, true);
        REG_SET(DC_IP_REQUEST_CNTL, 0,
                        IP_REQUEST_EN, 0);
 
@@ -664,10 +664,27 @@ static void apply_DEGVIDCN10_253_wa(struct dc *dc)
        hws->wa_state.DEGVIDCN10_253_applied = true;
 }
 
-static void bios_golden_init(struct dc *dc)
+static void dcn10_bios_golden_init(struct dc *dc)
 {
        struct dc_bios *bp = dc->ctx->dc_bios;
        int i;
+       bool allow_self_fresh_force_enable = true;
+
+#if defined(CONFIG_DRM_AMD_DC_DCN2_1)
+       if (dc->hwss.s0i3_golden_init_wa && dc->hwss.s0i3_golden_init_wa(dc))
+               return;
+#endif
+       if (dc->res_pool->hubbub->funcs->is_allow_self_refresh_enabled)
+               allow_self_fresh_force_enable =
+                               dc->res_pool->hubbub->funcs->is_allow_self_refresh_enabled(dc->res_pool->hubbub);
+
+
+       /* WA for making DF sleep when idle after resume from S0i3.
+        * DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE is set to 1 by
+        * command table, if DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE = 0
+        * before calling command table and it changed to 1 after,
+        * it should be set back to 0.
+        */
 
        /* initialize dcn global */
        bp->funcs->enable_disp_power_gating(bp,
@@ -678,6 +695,12 @@ static void bios_golden_init(struct dc *dc)
                bp->funcs->enable_disp_power_gating(bp,
                                CONTROLLER_ID_D0 + i, ASIC_PIPE_DISABLE);
        }
+
+       if (dc->res_pool->hubbub->funcs->allow_self_refresh_control)
+               if (allow_self_fresh_force_enable == false &&
+                               dc->res_pool->hubbub->funcs->is_allow_self_refresh_enabled(dc->res_pool->hubbub))
+                       dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub, true);
+
 }
 
 static void false_optc_underflow_wa(
@@ -702,7 +725,8 @@ static void false_optc_underflow_wa(
                dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, old_pipe_ctx);
        }
 
-       tg->funcs->set_blank_data_double_buffer(tg, true);
+       if (tg->funcs->set_blank_data_double_buffer)
+               tg->funcs->set_blank_data_double_buffer(tg, true);
 
        if (tg->funcs->is_optc_underflow_occurred(tg) && !underflow)
                tg->funcs->clear_optc_underflow(tg);
@@ -808,11 +832,23 @@ static void dcn10_reset_back_end_for_pipe(
        if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
                /* DPMS may already disable */
                if (!pipe_ctx->stream->dpms_off)
-                       core_link_disable_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE);
-               else if (pipe_ctx->stream_res.audio) {
-                       dc->hwss.disable_audio_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE);
+                       core_link_disable_stream(pipe_ctx);
+               else if (pipe_ctx->stream_res.audio)
+                       dc->hwss.disable_audio_stream(pipe_ctx);
+
+               if (pipe_ctx->stream_res.audio) {
+                       /*disable az_endpoint*/
+                       pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
+
+                       /*free audio*/
+                       if (dc->caps.dynamic_audio == true) {
+                               /*we have to dynamic arbitrate the audio endpoints*/
+                               /*we free the resource, need reset is_audio_acquired*/
+                               update_audio_usage(&dc->current_state->res_ctx, dc->res_pool,
+                                               pipe_ctx->stream_res.audio, false);
+                               pipe_ctx->stream_res.audio = NULL;
+                       }
                }
-
        }
 
        /* by upper caller loop, parent pipe: pipe0, will be reset last.
@@ -823,6 +859,9 @@ static void dcn10_reset_back_end_for_pipe(
                pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg);
 
                pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, false);
+               if (pipe_ctx->stream_res.tg->funcs->set_drr)
+                       pipe_ctx->stream_res.tg->funcs->set_drr(
+                                       pipe_ctx->stream_res.tg, NULL);
        }
 
        for (i = 0; i < dc->res_pool->pipe_count; i++)
@@ -968,7 +1007,7 @@ void hwss1_plane_atomic_disconnect(struct dc *dc, struct pipe_ctx *pipe_ctx)
                dcn10_verify_allow_pstate_change_high(dc);
 }
 
-static void plane_atomic_power_down(struct dc *dc,
+static void dcn10_plane_atomic_power_down(struct dc *dc,
                struct dpp *dpp,
                struct hubp *hubp)
 {
@@ -978,8 +1017,8 @@ static void plane_atomic_power_down(struct dc *dc,
        if (REG(DC_IP_REQUEST_CNTL)) {
                REG_SET(DC_IP_REQUEST_CNTL, 0,
                                IP_REQUEST_EN, 1);
-               dpp_pg_control(hws, dpp->inst, false);
-               hubp_pg_control(hws, hubp->inst, false);
+               dc->hwss.dpp_pg_control(hws, dpp->inst, false);
+               dc->hwss.hubp_pg_control(hws, hubp->inst, false);
                dpp->funcs->dpp_reset(dpp);
                REG_SET(DC_IP_REQUEST_CNTL, 0,
                                IP_REQUEST_EN, 0);
@@ -991,7 +1030,7 @@ static void plane_atomic_power_down(struct dc *dc,
 /* disable HW used by plane.
  * note:  cannot disable until disconnect is complete
  */
-static void plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
+static void dcn10_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
 {
        struct hubp *hubp = pipe_ctx->plane_res.hubp;
        struct dpp *dpp = pipe_ctx->plane_res.dpp;
@@ -1011,7 +1050,7 @@ static void plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
        hubp->power_gated = true;
        dc->optimized_required = false; /* We're powering off, no need to optimize */
 
-       plane_atomic_power_down(dc,
+       dc->hwss.plane_atomic_power_down(dc,
                        pipe_ctx->plane_res.dpp,
                        pipe_ctx->plane_res.hubp);
 
@@ -1030,7 +1069,7 @@ static void dcn10_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx)
        if (!pipe_ctx->plane_res.hubp || pipe_ctx->plane_res.hubp->power_gated)
                return;
 
-       plane_atomic_disable(dc, pipe_ctx);
+       dc->hwss.plane_atomic_disable(dc, pipe_ctx);
 
        apply_DEGVIDCN10_253_wa(dc);
 
@@ -1065,15 +1104,27 @@ static void dcn10_init_pipes(struct dc *dc, struct dc_state *context)
                 * command table.
                 */
                if (tg->funcs->is_tg_enabled(tg)) {
-                       tg->funcs->lock(tg);
-                       tg->funcs->set_blank(tg, true);
-                       hwss_wait_for_blank_complete(tg);
+                       if (dc->hwss.init_blank != NULL) {
+                               dc->hwss.init_blank(dc, tg);
+                               tg->funcs->lock(tg);
+                       } else {
+                               tg->funcs->lock(tg);
+                               tg->funcs->set_blank(tg, true);
+                               hwss_wait_for_blank_complete(tg);
+                       }
                }
        }
 
-       /* Cannot reset the MPC mux if seamless boot */
-       if (!can_apply_seamless_boot)
-               dc->res_pool->mpc->funcs->mpc_init(dc->res_pool->mpc);
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+
+               /* Cannot reset the MPC mux if seamless boot */
+               if (pipe_ctx->stream != NULL && can_apply_seamless_boot)
+                       continue;
+
+               dc->res_pool->mpc->funcs->mpc_init_single_inst(
+                               dc->res_pool->mpc, i);
+       }
 
        for (i = 0; i < dc->res_pool->pipe_count; i++) {
                struct timing_generator *tg = dc->res_pool->timing_generators[i];
@@ -1111,12 +1162,12 @@ static void dcn10_init_pipes(struct dc *dc, struct dc_state *context)
                dc->res_pool->opps[i]->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true;
                pipe_ctx->stream_res.opp = dc->res_pool->opps[i];
 
-               hwss1_plane_atomic_disconnect(dc, pipe_ctx);
+               dc->hwss.plane_atomic_disconnect(dc, pipe_ctx);
 
                if (tg->funcs->is_tg_enabled(tg))
                        tg->funcs->unlock(tg);
 
-               dcn10_disable_plane(dc, pipe_ctx);
+               dc->hwss.disable_plane(dc, pipe_ctx);
 
                pipe_ctx->stream_res.tg = NULL;
                pipe_ctx->plane_res.hubp = NULL;
@@ -1132,8 +1183,17 @@ static void dcn10_init_hw(struct dc *dc)
        struct dmcu *dmcu = dc->res_pool->dmcu;
        struct dce_hwseq *hws = dc->hwseq;
        struct dc_bios *dcb = dc->ctx->dc_bios;
+       struct resource_pool *res_pool = dc->res_pool;
+
+       if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
+               dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
+
+       // Initialize the dccg
+       if (dc->res_pool->dccg && dc->res_pool->dccg->funcs->dccg_init)
+               dc->res_pool->dccg->funcs->dccg_init(res_pool->dccg);
 
        if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
+
                REG_WRITE(REFCLK_CNTL, 0);
                REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
                REG_WRITE(DIO_MEM_PWR_CTRL, 0);
@@ -1147,31 +1207,40 @@ static void dcn10_init_hw(struct dc *dc)
                        REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
                }
 
-               enable_power_gating_plane(dc->hwseq, true);
+               //Enable ability to power gate / don't force power on permanently
+               dc->hwss.enable_power_gating_plane(hws, true);
 
-               /* end of FPGA. Below if real ASIC */
                return;
        }
 
-       if (!dcb->funcs->is_accelerated_mode(dcb)) {
-               bool allow_self_fresh_force_enable =
-                       hububu1_is_allow_self_refresh_enabled(
-                                               dc->res_pool->hubbub);
+       if (!dcb->funcs->is_accelerated_mode(dcb))
+               dc->hwss.disable_vga(dc->hwseq);
 
-               bios_golden_init(dc);
+       dc->hwss.bios_golden_init(dc);
+       if (dc->ctx->dc_bios->fw_info_valid) {
+               res_pool->ref_clocks.xtalin_clock_inKhz =
+                               dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
 
-               /* WA for making DF sleep when idle after resume from S0i3.
-                * DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE is set to 1 by
-                * command table, if DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE = 0
-                * before calling command table and it changed to 1 after,
-                * it should be set back to 0.
-                */
-               if (allow_self_fresh_force_enable == false &&
-                               hububu1_is_allow_self_refresh_enabled(dc->res_pool->hubbub))
-                       hubbub1_allow_self_refresh_control(dc->res_pool->hubbub, true);
+               if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
+                       if (res_pool->dccg && res_pool->hubbub) {
 
-               disable_vga(dc->hwseq);
-       }
+                               (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
+                                               dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
+                                               &res_pool->ref_clocks.dccg_ref_clock_inKhz);
+
+                               (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub,
+                                               res_pool->ref_clocks.dccg_ref_clock_inKhz,
+                                               &res_pool->ref_clocks.dchub_ref_clock_inKhz);
+                       } else {
+                               // Not all ASICs have DCCG sw component
+                               res_pool->ref_clocks.dccg_ref_clock_inKhz =
+                                               res_pool->ref_clocks.xtalin_clock_inKhz;
+                               res_pool->ref_clocks.dchub_ref_clock_inKhz =
+                                               res_pool->ref_clocks.xtalin_clock_inKhz;
+                       }
+               }
+       } else
+               ASSERT_CRITICAL(false);
 
        for (i = 0; i < dc->link_count; i++) {
                /* Power up AND update implementation according to the
@@ -1188,6 +1257,13 @@ static void dcn10_init_hw(struct dc *dc)
                        link->link_status.link_active = true;
        }
 
+       /* Power gate DSCs */
+#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
+       for (i = 0; i < res_pool->res_cap->num_dsc; i++)
+               if (dc->hwss.dsc_pg_control != NULL)
+                       dc->hwss.dsc_pg_control(hws, res_pool->dscs[i]->inst, false);
+#endif
+
        /* If taking control over from VBIOS, we may want to optimize our first
         * mode set, so we need to skip powering down pipes until we know which
         * pipes we want to use.
@@ -1195,20 +1271,11 @@ static void dcn10_init_hw(struct dc *dc)
         * everything down.
         */
        if (dcb->funcs->is_accelerated_mode(dcb) || dc->config.power_down_display_on_boot) {
-               for (i = 0; i < dc->res_pool->pipe_count; i++) {
-                       struct hubp *hubp = dc->res_pool->hubps[i];
-                       struct dpp *dpp = dc->res_pool->dpps[i];
-
-                       hubp->funcs->hubp_init(hubp);
-                       dc->res_pool->opps[i]->mpc_tree_params.opp_id = dc->res_pool->opps[i]->inst;
-                       plane_atomic_power_down(dc, dpp, hubp);
-               }
-
-               apply_DEGVIDCN10_253_wa(dc);
+               dc->hwss.init_pipes(dc, dc->current_state);
        }
 
-       for (i = 0; i < dc->res_pool->audio_count; i++) {
-               struct audio *audio = dc->res_pool->audios[i];
+       for (i = 0; i < res_pool->audio_count; i++) {
+               struct audio *audio = res_pool->audios[i];
 
                audio->funcs->hw_init(audio);
        }
@@ -1236,9 +1303,11 @@ static void dcn10_init_hw(struct dc *dc)
                REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
        }
 
-       enable_power_gating_plane(dc->hwseq, true);
+       dc->hwss.enable_power_gating_plane(dc->hwseq, true);
+
+       if (dc->clk_mgr->funcs->notify_wm_ranges)
+               dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr);
 
-       memset(&dc->clk_mgr->clks, 0, sizeof(dc->clk_mgr->clks));
 }
 
 static void dcn10_reset_hw_ctx_wrap(
@@ -1375,9 +1444,33 @@ static bool dcn10_set_input_transfer_func(struct pipe_ctx *pipe_ctx,
        return result;
 }
 
+#define MAX_NUM_HW_POINTS 0x200
+
+static void log_tf(struct dc_context *ctx,
+                               struct dc_transfer_func *tf, uint32_t hw_points_num)
+{
+       // DC_LOG_GAMMA is default logging of all hw points
+       // DC_LOG_ALL_GAMMA logs all points, not only hw points
+       // DC_LOG_ALL_TF_POINTS logs all channels of the tf
+       int i = 0;
 
+       DC_LOGGER_INIT(ctx->logger);
+       DC_LOG_GAMMA("Gamma Correction TF");
+       DC_LOG_ALL_GAMMA("Logging all tf points...");
+       DC_LOG_ALL_TF_CHANNELS("Logging all channels...");
 
+       for (i = 0; i < hw_points_num; i++) {
+               DC_LOG_GAMMA("R\t%d\t%llu", i, tf->tf_pts.red[i].value);
+               DC_LOG_ALL_TF_CHANNELS("G\t%d\t%llu", i, tf->tf_pts.green[i].value);
+               DC_LOG_ALL_TF_CHANNELS("B\t%d\t%llu", i, tf->tf_pts.blue[i].value);
+       }
 
+       for (i = hw_points_num; i < MAX_NUM_HW_POINTS; i++) {
+               DC_LOG_ALL_GAMMA("R\t%d\t%llu", i, tf->tf_pts.red[i].value);
+               DC_LOG_ALL_TF_CHANNELS("G\t%d\t%llu", i, tf->tf_pts.green[i].value);
+               DC_LOG_ALL_TF_CHANNELS("B\t%d\t%llu", i, tf->tf_pts.blue[i].value);
+       }
+}
 
 static bool
 dcn10_set_output_transfer_func(struct pipe_ctx *pipe_ctx,
@@ -1407,6 +1500,13 @@ dcn10_set_output_transfer_func(struct pipe_ctx *pipe_ctx,
        } else
                dpp->funcs->dpp_program_regamma_pwl(dpp, NULL, OPP_REGAMMA_BYPASS);
 
+       if (stream != NULL && stream->ctx != NULL &&
+                       stream->out_transfer_func != NULL) {
+               log_tf(stream->ctx,
+                               stream->out_transfer_func,
+                               dpp->regamma_params.hw_points_num);
+       }
+
        return true;
 }
 
@@ -1799,7 +1899,7 @@ static void dcn10_enable_plane(
        }
 }
 
-static void program_gamut_remap(struct pipe_ctx *pipe_ctx)
+static void dcn10_program_gamut_remap(struct pipe_ctx *pipe_ctx)
 {
        int i = 0;
        struct dpp_grph_csc_adjustment adjust;
@@ -1817,6 +1917,36 @@ static void program_gamut_remap(struct pipe_ctx *pipe_ctx)
        pipe_ctx->plane_res.dpp->funcs->dpp_set_gamut_remap(pipe_ctx->plane_res.dpp, &adjust);
 }
 
+
+static bool dcn10_is_rear_mpo_fix_required(struct pipe_ctx *pipe_ctx, enum dc_color_space colorspace)
+{
+       if (pipe_ctx->plane_state && pipe_ctx->plane_state->layer_index > 0 && is_rgb_cspace(colorspace)) {
+               if (pipe_ctx->top_pipe) {
+                       struct pipe_ctx *top = pipe_ctx->top_pipe;
+
+                       while (top->top_pipe)
+                               top = top->top_pipe; // Traverse to top pipe_ctx
+                       if (top->plane_state && top->plane_state->layer_index == 0)
+                               return true; // Front MPO plane not hidden
+               }
+       }
+       return false;
+}
+
+static void dcn10_set_csc_adjustment_rgb_mpo_fix(struct pipe_ctx *pipe_ctx, uint16_t *matrix)
+{
+       // Override rear plane RGB bias to fix MPO brightness
+       uint16_t rgb_bias = matrix[3];
+
+       matrix[3] = 0;
+       matrix[7] = 0;
+       matrix[11] = 0;
+       pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment(pipe_ctx->plane_res.dpp, matrix);
+       matrix[3] = rgb_bias;
+       matrix[7] = rgb_bias;
+       matrix[11] = rgb_bias;
+}
+
 static void dcn10_program_output_csc(struct dc *dc,
                struct pipe_ctx *pipe_ctx,
                enum dc_color_space colorspace,
@@ -1824,8 +1954,25 @@ static void dcn10_program_output_csc(struct dc *dc,
                int opp_id)
 {
        if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) {
-               if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment != NULL)
-                       pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment(pipe_ctx->plane_res.dpp, matrix);
+               if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment != NULL) {
+
+                       /* MPO is broken with RGB colorspaces when OCSC matrix
+                        * brightness offset >= 0 on DCN1 due to OCSC before MPC
+                        * Blending adds offsets from front + rear to rear plane
+                        *
+                        * Fix is to set RGB bias to 0 on rear plane, top plane
+                        * black value pixels add offset instead of rear + front
+                        */
+
+                       int16_t rgb_bias = matrix[3];
+                       // matrix[3/7/11] are all the same offset value
+
+                       if (rgb_bias > 0 && dcn10_is_rear_mpo_fix_required(pipe_ctx, colorspace)) {
+                               dcn10_set_csc_adjustment_rgb_mpo_fix(pipe_ctx, matrix);
+                       } else {
+                               pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment(pipe_ctx->plane_res.dpp, matrix);
+                       }
+               }
        } else {
                if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_default != NULL)
                        pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_default(pipe_ctx->plane_res.dpp, colorspace);
@@ -2145,7 +2292,7 @@ void update_dchubp_dpp(
        struct hubp *hubp = pipe_ctx->plane_res.hubp;
        struct dpp *dpp = pipe_ctx->plane_res.dpp;
        struct dc_plane_state *plane_state = pipe_ctx->plane_state;
-       union plane_size size = plane_state->plane_size;
+       struct plane_size size = plane_state->plane_size;
        unsigned int compat_level = 0;
 
        /* depends on DML calculation, DPP clock value may change dynamically */
@@ -2191,7 +2338,7 @@ void update_dchubp_dpp(
                        &pipe_ctx->ttu_regs);
        }
 
-       size.grph.surface_size = pipe_ctx->plane_res.scl_data.viewport;
+       size.surface_size = pipe_ctx->plane_res.scl_data.viewport;
 
        if (plane_state->update_flags.bits.full_update ||
                plane_state->update_flags.bits.bpp_change)
@@ -2229,7 +2376,7 @@ void update_dchubp_dpp(
 
        if (plane_state->update_flags.bits.full_update) {
                /*gamut remap*/
-               program_gamut_remap(pipe_ctx);
+               dc->hwss.program_gamut_remap(pipe_ctx);
 
                dc->hwss.program_output_csc(dc,
                                pipe_ctx,
@@ -2372,8 +2519,10 @@ static void program_all_pipe_in_tree(
                pipe_ctx->stream_res.tg->funcs->set_vtg_params(
                                pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
 
-               dc->hwss.blank_pixel_data(dc, pipe_ctx, blank);
+               if (dc->hwss.setup_vupdate_interrupt)
+                       dc->hwss.setup_vupdate_interrupt(pipe_ctx);
 
+               dc->hwss.blank_pixel_data(dc, pipe_ctx, blank);
        }
 
        if (pipe_ctx->plane_state != NULL)
@@ -2401,7 +2550,7 @@ struct pipe_ctx *find_top_pipe_for_stream(
                if (pipe_ctx->stream != stream)
                        continue;
 
-               if (!pipe_ctx->top_pipe)
+               if (!pipe_ctx->top_pipe && !pipe_ctx->prev_odm_pipe)
                        return pipe_ctx;
        }
        return NULL;
@@ -2466,7 +2615,7 @@ static void dcn10_apply_ctx_for_surface(
                        if (old_pipe_ctx->stream_res.tg == tg &&
                            old_pipe_ctx->plane_res.hubp &&
                            old_pipe_ctx->plane_res.hubp->opp_id != OPP_ID_INVALID)
-                               dcn10_disable_plane(dc, old_pipe_ctx);
+                               dc->hwss.disable_plane(dc, old_pipe_ctx);
                }
 
                if ((!pipe_ctx->plane_state ||
@@ -2514,7 +2663,13 @@ static void dcn10_apply_ctx_for_surface(
 
        for (i = 0; i < dc->res_pool->pipe_count; i++)
                if (removed_pipe[i])
-                       dcn10_disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]);
+                       dc->hwss.disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]);
+
+       for (i = 0; i < dc->res_pool->pipe_count; i++)
+               if (removed_pipe[i]) {
+                       dc->hwss.optimize_bandwidth(dc, context);
+                       break;
+               }
 
        if (dc->hwseq->wa.DEGVIDCN10_254)
                hubbub1_wm_change_req_wa(dc->res_pool->hubbub);
@@ -2600,8 +2755,9 @@ static void dcn10_optimize_bandwidth(
                dcn10_verify_allow_pstate_change_high(dc);
 }
 
-static void set_drr(struct pipe_ctx **pipe_ctx,
-               int num_pipes, int vmin, int vmax)
+static void dcn10_set_drr(struct pipe_ctx **pipe_ctx,
+               int num_pipes, unsigned int vmin, unsigned int vmax,
+               unsigned int vmid, unsigned int vmid_frame_number)
 {
        int i = 0;
        struct drr_params params = {0};
@@ -2610,6 +2766,8 @@ static void set_drr(struct pipe_ctx **pipe_ctx,
 
        params.vertical_total_max = vmax;
        params.vertical_total_min = vmin;
+       params.vertical_total_mid = vmid;
+       params.vertical_total_mid_frame_num = vmid_frame_number;
 
        /* TODO: If multiple pipes are to be supported, you need
         * some GSL stuff. Static screen triggers may be programmed differently
@@ -2625,7 +2783,7 @@ static void set_drr(struct pipe_ctx **pipe_ctx,
        }
 }
 
-static void get_position(struct pipe_ctx **pipe_ctx,
+static void dcn10_get_position(struct pipe_ctx **pipe_ctx,
                int num_pipes,
                struct crtc_position *position)
 {
@@ -2637,7 +2795,7 @@ static void get_position(struct pipe_ctx **pipe_ctx,
                pipe_ctx[i]->stream_res.tg->funcs->get_position(pipe_ctx[i]->stream_res.tg, position);
 }
 
-static void set_static_screen_control(struct pipe_ctx **pipe_ctx,
+static void dcn10_set_static_screen_control(struct pipe_ctx **pipe_ctx,
                int num_pipes, const struct dc_static_screen_events *events)
 {
        unsigned int i;
@@ -2699,6 +2857,13 @@ static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct dc *dc)
 
        dcn10_config_stereo_parameters(stream, &flags);
 
+       if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_SIDEBAND_FA) {
+               if (!dc_set_generic_gpio_for_stereo(true, dc->ctx->gpio_service))
+                       dc_set_generic_gpio_for_stereo(false, dc->ctx->gpio_service);
+       } else {
+               dc_set_generic_gpio_for_stereo(false, dc->ctx->gpio_service);
+       }
+
        pipe_ctx->stream_res.opp->funcs->opp_program_stereo(
                pipe_ctx->stream_res.opp,
                flags.PROGRAM_STEREO == 1 ? true:false,
@@ -2789,14 +2954,10 @@ static void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx)
 
 static void dcn10_update_dchub(struct dce_hwseq *hws, struct dchub_init_data *dh_data)
 {
-       if (hws->ctx->dc->res_pool->hubbub != NULL) {
-               struct hubp *hubp = hws->ctx->dc->res_pool->hubps[0];
+       struct hubbub *hubbub = hws->ctx->dc->res_pool->hubbub;
 
-               if (hubp->funcs->hubp_update_dchub)
-                       hubp->funcs->hubp_update_dchub(hubp, dh_data);
-               else
-                       hubbub1_update_dchub(hws->ctx->dc->res_pool->hubbub, dh_data);
-       }
+       /* In DCN, this programming sequence is owned by the hubbub */
+       hubbub->funcs->update_dchub(hubbub, dh_data);
 }
 
 static void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx)
@@ -2827,6 +2988,40 @@ static void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx)
                        == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE)
                pos_cpy.enable = false;
 
+       // Swap axis and mirror horizontally
+       if (param.rotation == ROTATION_ANGLE_90) {
+               uint32_t temp_x = pos_cpy.x;
+               pos_cpy.x = pipe_ctx->plane_res.scl_data.viewport.width -
+                               (pos_cpy.y - pipe_ctx->plane_res.scl_data.viewport.x) + pipe_ctx->plane_res.scl_data.viewport.x;
+               pos_cpy.y = temp_x;
+       }
+       // Swap axis and mirror vertically
+       else if (param.rotation == ROTATION_ANGLE_270) {
+               uint32_t temp_y = pos_cpy.y;
+               if (pos_cpy.x >  pipe_ctx->plane_res.scl_data.viewport.height) {
+                       pos_cpy.x = pos_cpy.x - pipe_ctx->plane_res.scl_data.viewport.height;
+                       pos_cpy.y = pipe_ctx->plane_res.scl_data.viewport.height - pos_cpy.x;
+               } else {
+                       pos_cpy.y = 2 * pipe_ctx->plane_res.scl_data.viewport.height - pos_cpy.x;
+               }
+               pos_cpy.x = temp_y;
+       }
+       // Mirror horizontally and vertically
+       else if (param.rotation == ROTATION_ANGLE_180) {
+               if (pos_cpy.x >= pipe_ctx->plane_res.scl_data.viewport.width + pipe_ctx->plane_res.scl_data.viewport.x) {
+                       pos_cpy.x = 2 * pipe_ctx->plane_res.scl_data.viewport.width
+                                       - pos_cpy.x + 2 * pipe_ctx->plane_res.scl_data.viewport.x;
+               } else {
+                       uint32_t temp_x = pos_cpy.x;
+                       pos_cpy.x = 2 * pipe_ctx->plane_res.scl_data.viewport.x - pos_cpy.x;
+                       if (temp_x >= pipe_ctx->plane_res.scl_data.viewport.x + (int)hubp->curs_attr.width
+                                       || pos_cpy.x <= (int)hubp->curs_attr.width + pipe_ctx->plane_state->src_rect.x) {
+                               pos_cpy.x = temp_x + pipe_ctx->plane_res.scl_data.viewport.width;
+                       }
+               }
+               pos_cpy.y = pipe_ctx->plane_res.scl_data.viewport.height - pos_cpy.y;
+       }
+
        hubp->funcs->set_cursor_position(hubp, &pos_cpy, &param);
        dpp->funcs->set_cursor_position(dpp, &pos_cpy, &param, hubp->curs_attr.width, hubp->curs_attr.height);
 }
@@ -2838,7 +3033,7 @@ static void dcn10_set_cursor_attribute(struct pipe_ctx *pipe_ctx)
        pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes(
                        pipe_ctx->plane_res.hubp, attributes);
        pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes(
-               pipe_ctx->plane_res.dpp, attributes->color_format);
+               pipe_ctx->plane_res.dpp, attributes);
 }
 
 static void dcn10_set_cursor_sdr_white_level(struct pipe_ctx *pipe_ctx)
@@ -3069,9 +3264,59 @@ static void dcn10_send_immediate_sdp_message(struct pipe_ctx *pipe_ctx,
                                sdp_message_size);
        }
 }
+static enum dc_status dcn10_set_clock(struct dc *dc,
+                       enum dc_clock_type clock_type,
+                       uint32_t clk_khz,
+                       uint32_t stepping)
+{
+       struct dc_state *context = dc->current_state;
+       struct dc_clock_config clock_cfg = {0};
+       struct dc_clocks *current_clocks = &context->bw_ctx.bw.dcn.clk;
+
+       if (dc->clk_mgr && dc->clk_mgr->funcs->get_clock)
+                               dc->clk_mgr->funcs->get_clock(dc->clk_mgr,
+                                               context, clock_type, &clock_cfg);
+
+       if (!dc->clk_mgr->funcs->get_clock)
+               return DC_FAIL_UNSUPPORTED_1;
+
+       if (clk_khz > clock_cfg.max_clock_khz)
+               return DC_FAIL_CLK_EXCEED_MAX;
+
+       if (clk_khz < clock_cfg.min_clock_khz)
+               return DC_FAIL_CLK_BELOW_MIN;
+
+       if (clk_khz < clock_cfg.bw_requirequired_clock_khz)
+               return DC_FAIL_CLK_BELOW_CFG_REQUIRED;
+
+       /*update internal request clock for update clock use*/
+       if (clock_type == DC_CLOCK_TYPE_DISPCLK)
+               current_clocks->dispclk_khz = clk_khz;
+       else if (clock_type == DC_CLOCK_TYPE_DPPCLK)
+               current_clocks->dppclk_khz = clk_khz;
+       else
+               return DC_ERROR_UNEXPECTED;
+
+       if (dc->clk_mgr && dc->clk_mgr->funcs->update_clocks)
+                               dc->clk_mgr->funcs->update_clocks(dc->clk_mgr,
+                               context, true);
+       return DC_OK;
+
+}
+
+static void dcn10_get_clock(struct dc *dc,
+                       enum dc_clock_type clock_type,
+                       struct dc_clock_config *clock_cfg)
+{
+       struct dc_state *context = dc->current_state;
+
+       if (dc->clk_mgr && dc->clk_mgr->funcs->get_clock)
+                               dc->clk_mgr->funcs->get_clock(dc->clk_mgr, context, clock_type, clock_cfg);
+
+}
 
 static const struct hw_sequencer_funcs dcn10_funcs = {
-       .program_gamut_remap = program_gamut_remap,
+       .program_gamut_remap = dcn10_program_gamut_remap,
        .init_hw = dcn10_init_hw,
        .init_pipes = dcn10_init_pipes,
        .apply_ctx_to_hw = dce110_apply_ctx_to_hw,
@@ -3104,18 +3349,18 @@ static const struct hw_sequencer_funcs dcn10_funcs = {
        .optimize_bandwidth = dcn10_optimize_bandwidth,
        .reset_hw_ctx_wrap = dcn10_reset_hw_ctx_wrap,
        .enable_stream_timing = dcn10_enable_stream_timing,
-       .set_drr = set_drr,
-       .get_position = get_position,
-       .set_static_screen_control = set_static_screen_control,
+       .set_drr = dcn10_set_drr,
+       .get_position = dcn10_get_position,
+       .set_static_screen_control = dcn10_set_static_screen_control,
        .setup_stereo = dcn10_setup_stereo,
        .set_avmute = dce110_set_avmute,
        .log_hw_state = dcn10_log_hw_state,
        .get_hw_state = dcn10_get_hw_state,
        .clear_status_bits = dcn10_clear_status_bits,
        .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect,
-       .edp_backlight_control = hwss_edp_backlight_control,
-       .edp_power_control = hwss_edp_power_control,
-       .edp_wait_for_hpd_ready = hwss_edp_wait_for_hpd_ready,
+       .edp_backlight_control = dce110_edp_backlight_control,
+       .edp_power_control = dce110_edp_power_control,
+       .edp_wait_for_hpd_ready = dce110_edp_wait_for_hpd_ready,
        .set_cursor_position = dcn10_set_cursor_position,
        .set_cursor_attribute = dcn10_set_cursor_attribute,
        .set_cursor_sdr_white_level = dcn10_set_cursor_sdr_white_level,
@@ -3123,7 +3368,18 @@ static const struct hw_sequencer_funcs dcn10_funcs = {
        .enable_stream_gating = NULL,
        .setup_periodic_interrupt = dcn10_setup_periodic_interrupt,
        .setup_vupdate_interrupt = dcn10_setup_vupdate_interrupt,
-       .did_underflow_occur = dcn10_did_underflow_occur
+       .set_clock = dcn10_set_clock,
+       .get_clock = dcn10_get_clock,
+       .did_underflow_occur = dcn10_did_underflow_occur,
+       .init_blank = NULL,
+       .disable_vga = dcn10_disable_vga,
+       .bios_golden_init = dcn10_bios_golden_init,
+       .plane_atomic_disable = dcn10_plane_atomic_disable,
+       .plane_atomic_power_down = dcn10_plane_atomic_power_down,
+       .enable_power_gating_plane = dcn10_enable_power_gating_plane,
+       .dpp_pg_control = dcn10_dpp_pg_control,
+       .hubp_pg_control = dcn10_hubp_pg_control,
+       .dsc_pg_control = NULL,
 };