drm/amd/display: redesign dce/dcn clock voltage update request
authorDmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
Wed, 23 May 2018 20:21:54 +0000 (16:21 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 5 Jul 2018 21:38:28 +0000 (16:38 -0500)
The goal of this change is to move clock programming and voltage
requests to a single function. As of this change only dce is affected.

Signed-off-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
Acked-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c
drivers/gpu/drm/amd/display/dc/core/dc_link.c
drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c
drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h
drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h

index d8a31650e8562cebfda7ac93b42052a0a009572e..2b70ac67e6c2864f7e041e6825fb27d45507cb70 100644 (file)
@@ -1145,10 +1145,10 @@ static unsigned int dcn_find_normalized_clock_vdd_Level(
 
        switch (clocks_type) {
        case DM_PP_CLOCK_TYPE_DISPLAY_CLK:
-               /*if (clocks_in_khz > dc->dcn_soc->max_dispclk_vmax0p9*1000) {
+               if (clocks_in_khz > dc->dcn_soc->max_dispclk_vmax0p9*1000) {
                        vdd_level = dcn_bw_v_max0p91;
-                       //BREAK_TO_DEBUGGER();
-               } else*/ if (clocks_in_khz > dc->dcn_soc->max_dispclk_vnom0p8*1000) {
+                       BREAK_TO_DEBUGGER();
+               } else if (clocks_in_khz > dc->dcn_soc->max_dispclk_vnom0p8*1000) {
                        vdd_level = dcn_bw_v_max0p9;
                } else if (clocks_in_khz > dc->dcn_soc->max_dispclk_vmid0p72*1000) {
                        vdd_level = dcn_bw_v_nom0p8;
@@ -1158,10 +1158,10 @@ static unsigned int dcn_find_normalized_clock_vdd_Level(
                        vdd_level = dcn_bw_v_min0p65;
                break;
        case DM_PP_CLOCK_TYPE_DISPLAYPHYCLK:
-               /*if (clocks_in_khz > dc->dcn_soc->phyclkv_max0p9*1000) {
+               if (clocks_in_khz > dc->dcn_soc->phyclkv_max0p9*1000) {
                        vdd_level = dcn_bw_v_max0p91;
                        BREAK_TO_DEBUGGER();
-               } else*/ if (clocks_in_khz > dc->dcn_soc->phyclkv_nom0p8*1000) {
+               } else if (clocks_in_khz > dc->dcn_soc->phyclkv_nom0p8*1000) {
                        vdd_level = dcn_bw_v_max0p9;
                } else if (clocks_in_khz > dc->dcn_soc->phyclkv_mid0p72*1000) {
                        vdd_level = dcn_bw_v_nom0p8;
@@ -1172,10 +1172,10 @@ static unsigned int dcn_find_normalized_clock_vdd_Level(
                break;
 
        case DM_PP_CLOCK_TYPE_DPPCLK:
-               /*if (clocks_in_khz > dc->dcn_soc->max_dppclk_vmax0p9*1000) {
+               if (clocks_in_khz > dc->dcn_soc->max_dppclk_vmax0p9*1000) {
                        vdd_level = dcn_bw_v_max0p91;
                        BREAK_TO_DEBUGGER();
-               } else*/ if (clocks_in_khz > dc->dcn_soc->max_dppclk_vnom0p8*1000) {
+               } else if (clocks_in_khz > dc->dcn_soc->max_dppclk_vnom0p8*1000) {
                        vdd_level = dcn_bw_v_max0p9;
                } else if (clocks_in_khz > dc->dcn_soc->max_dppclk_vmid0p72*1000) {
                        vdd_level = dcn_bw_v_nom0p8;
@@ -1189,10 +1189,10 @@ static unsigned int dcn_find_normalized_clock_vdd_Level(
                {
                        unsigned factor = (ddr4_dram_factor_single_Channel * dc->dcn_soc->number_of_channels);
 
-                       /*if (clocks_in_khz > dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9*1000000/factor) {
+                       if (clocks_in_khz > dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9*1000000/factor) {
                                vdd_level = dcn_bw_v_max0p91;
                                BREAK_TO_DEBUGGER();
-                       } else */if (clocks_in_khz > dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8*1000000/factor) {
+                       } else if (clocks_in_khz > dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8*1000000/factor) {
                                vdd_level = dcn_bw_v_max0p9;
                        } else if (clocks_in_khz > dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72*1000000/factor) {
                                vdd_level = dcn_bw_v_nom0p8;
@@ -1204,10 +1204,10 @@ static unsigned int dcn_find_normalized_clock_vdd_Level(
                break;
 
        case DM_PP_CLOCK_TYPE_DCFCLK:
-               /*if (clocks_in_khz > dc->dcn_soc->dcfclkv_max0p9*1000) {
+               if (clocks_in_khz > dc->dcn_soc->dcfclkv_max0p9*1000) {
                        vdd_level = dcn_bw_v_max0p91;
                        BREAK_TO_DEBUGGER();
-               } else */if (clocks_in_khz > dc->dcn_soc->dcfclkv_nom0p8*1000) {
+               } else if (clocks_in_khz > dc->dcn_soc->dcfclkv_nom0p8*1000) {
                        vdd_level = dcn_bw_v_max0p9;
                } else if (clocks_in_khz > dc->dcn_soc->dcfclkv_mid0p72*1000) {
                        vdd_level = dcn_bw_v_nom0p8;
index 6155a5c7bd3684ab70cbe1277d6df592a0eb064e..779d1926a756c915270acfc49248e30777e2258e 100644 (file)
@@ -1284,27 +1284,15 @@ static enum dc_status enable_link_dp(
                max_link_rate = LINK_RATE_HIGH3;
 
        if (link_settings.link_rate == max_link_rate) {
-               if (state->dis_clk->funcs->set_min_clocks_state) {
-                       if (state->dis_clk->cur_min_clks_state < DM_PP_CLOCKS_STATE_NOMINAL)
-                               state->dis_clk->funcs->set_min_clocks_state(
-                                       state->dis_clk, DM_PP_CLOCKS_STATE_NOMINAL);
-               } else {
-                       uint32_t dp_phyclk_in_khz;
-                       const struct dc_clocks clocks_value =
-                                       state->dis_clk->clks;
-
-                       /* 27mhz = 27000000hz= 27000khz */
-                       dp_phyclk_in_khz = link_settings.link_rate * 27000;
-
-                       if (dp_phyclk_in_khz > clocks_value.phyclk_khz) {
-                               state->dis_clk->funcs->apply_clock_voltage_request(
-                                               state->dis_clk,
-                                               DM_PP_CLOCK_TYPE_DISPLAYPHYCLK,
-                                               dp_phyclk_in_khz,
-                                               false,
-                                               true);
-                       }
-               }
+               struct dc_clocks clocks = state->bw.dcn.calc_clk;
+
+               /* dce/dcn compat, do not update dispclk */
+               clocks.dispclk_khz = 0;
+               /* 27mhz = 27000000hz= 27000khz */
+               clocks.phyclk_khz = link_settings.link_rate * 27000;
+
+               state->dis_clk->funcs->update_clocks(
+                               state->dis_clk, &clocks, false);
        }
 
        dp_enable_link_phy(
index b749a20a0c3de3cf42aed6e64cb8a7193519efba..d3bbac85dff1863c49f93bdffa6cc0bf9e36a0cf 100644 (file)
@@ -275,7 +275,7 @@ static int dce_clocks_get_dp_ref_freq_wrkaround(struct display_clock *clk)
 }
 static enum dm_pp_clocks_state dce_get_required_clocks_state(
        struct display_clock *clk,
-       struct state_dependent_clocks *req_clocks)
+       struct dc_clocks *req_clocks)
 {
        struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk);
        int i;
@@ -286,48 +286,25 @@ static enum dm_pp_clocks_state dce_get_required_clocks_state(
         * all required clocks
         */
        for (i = clk->max_clks_state; i >= DM_PP_CLOCKS_STATE_ULTRA_LOW; i--)
-               if (req_clocks->display_clk_khz >
+               if (req_clocks->dispclk_khz >
                                clk_dce->max_clks_by_state[i].display_clk_khz
-                       || req_clocks->pixel_clk_khz >
+                       || req_clocks->phyclk_khz >
                                clk_dce->max_clks_by_state[i].pixel_clk_khz)
                        break;
 
        low_req_clk = i + 1;
        if (low_req_clk > clk->max_clks_state) {
-               DC_LOG_WARNING("%s: clocks unsupported disp_clk %d pix_clk %d",
-                               __func__,
-                               req_clocks->display_clk_khz,
-                               req_clocks->pixel_clk_khz);
-               low_req_clk = DM_PP_CLOCKS_STATE_INVALID;
+               /* set max clock state for high phyclock, invalid on exceeding display clock */
+               if (clk_dce->max_clks_by_state[clk->max_clks_state].display_clk_khz
+                               < req_clocks->dispclk_khz)
+                       low_req_clk = DM_PP_CLOCKS_STATE_INVALID;
+               else
+                       low_req_clk = clk->max_clks_state;
        }
 
        return low_req_clk;
 }
 
-static bool dce_clock_set_min_clocks_state(
-       struct display_clock *clk,
-       enum dm_pp_clocks_state clocks_state)
-{
-       struct dm_pp_power_level_change_request level_change_req = {
-                       clocks_state };
-
-       if (clocks_state > clk->max_clks_state) {
-               /*Requested state exceeds max supported state.*/
-               DC_LOG_WARNING("Requested state exceeds max supported state");
-               return false;
-       } else if (clocks_state == clk->cur_min_clks_state) {
-               /*if we're trying to set the same state, we can just return
-                * since nothing needs to be done*/
-               return true;
-       }
-
-       /* get max clock state from PPLIB */
-       if (dm_pp_apply_power_level_change_request(clk->ctx, &level_change_req))
-               clk->cur_min_clks_state = clocks_state;
-
-       return true;
-}
-
 static int dce_set_clock(
        struct display_clock *clk,
        int requested_clk_khz)
@@ -488,8 +465,6 @@ static void dce_clock_read_integrated_info(struct dce_disp_clk *clk_dce)
        if (!debug->disable_dfs_bypass && bp->integrated_info)
                if (bp->integrated_info->gpu_cap_info & DFS_BYPASS_ENABLE)
                        clk_dce->dfs_bypass_enabled = true;
-
-       clk_dce->use_max_disp_clk = debug->max_disp_clk;
 }
 
 static void dce_clock_read_ss_info(struct dce_disp_clk *clk_dce)
@@ -548,117 +523,160 @@ static void dce_clock_read_ss_info(struct dce_disp_clk *clk_dce)
        }
 }
 
-static bool dce_apply_clock_voltage_request(
-       struct display_clock *clk,
-       enum dm_pp_clock_type clocks_type,
-       int clocks_in_khz,
-       bool pre_mode_set,
-       bool update_dp_phyclk)
+static void dce12_update_clocks(struct display_clock *dccg,
+                       struct dc_clocks *new_clocks,
+                       bool safe_to_lower)
 {
-       bool send_request = false;
        struct dm_pp_clock_for_voltage_req clock_voltage_req = {0};
 
-       switch (clocks_type) {
-       case DM_PP_CLOCK_TYPE_DISPLAY_CLK:
-       case DM_PP_CLOCK_TYPE_DISPLAYPHYCLK:
-               break;
-       default:
-               return false;
+       if ((new_clocks->dispclk_khz < dccg->clks.dispclk_khz && safe_to_lower)
+                       || new_clocks->dispclk_khz > dccg->clks.dispclk_khz) {
+               clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DISPLAY_CLK;
+               clock_voltage_req.clocks_in_khz = new_clocks->dispclk_khz;
+               dccg->funcs->set_dispclk(dccg, new_clocks->dispclk_khz);
+               dccg->clks.dispclk_khz = new_clocks->dispclk_khz;
+
+               dm_pp_apply_clock_for_voltage_request(dccg->ctx, &clock_voltage_req);
        }
 
-       clock_voltage_req.clk_type = clocks_type;
-       clock_voltage_req.clocks_in_khz = clocks_in_khz;
-
-       /* to pplib */
-       if (pre_mode_set) {
-               switch (clocks_type) {
-               case DM_PP_CLOCK_TYPE_DISPLAY_CLK:
-                       if (clocks_in_khz > clk->clks.dispclk_khz) {
-                               clk->dispclk_notify_pplib_done = true;
-                               send_request = true;
-                       } else
-                               clk->dispclk_notify_pplib_done = false;
-                       /* no matter incrase or decrase clock, update current clock value */
-                       clk->clks.dispclk_khz = clocks_in_khz;
-                       break;
-               case DM_PP_CLOCK_TYPE_DISPLAYPHYCLK:
-                       if (clocks_in_khz > clk->clks.phyclk_khz) {
-                               clk->phyclk_notify_pplib_done = true;
-                               send_request = true;
-                       } else
-                               clk->phyclk_notify_pplib_done = false;
-                       /* no matter incrase or decrase clock, update current clock value */
-                       clk->clks.phyclk_khz = clocks_in_khz;
-                       break;
-               default:
-                       ASSERT(0);
-                       break;
-               }
+       if ((new_clocks->phyclk_khz < dccg->clks.phyclk_khz && safe_to_lower)
+                       || new_clocks->phyclk_khz > dccg->clks.phyclk_khz) {
+               clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DISPLAYPHYCLK;
+               clock_voltage_req.clocks_in_khz = new_clocks->phyclk_khz;
+               dccg->clks.phyclk_khz = new_clocks->phyclk_khz;
 
-       } else {
-               switch (clocks_type) {
-               case DM_PP_CLOCK_TYPE_DISPLAY_CLK:
-                       if (!clk->dispclk_notify_pplib_done)
-                               send_request = true;
-                       clk->dispclk_notify_pplib_done = true;
-                       break;
-               case DM_PP_CLOCK_TYPE_DISPLAYPHYCLK:
-                       if (!clk->phyclk_notify_pplib_done)
-                               send_request = true;
-                       clk->phyclk_notify_pplib_done = true;
-                       break;
-               default:
-                       ASSERT(0);
-                       break;
-               }
+               dm_pp_apply_clock_for_voltage_request(dccg->ctx, &clock_voltage_req);
        }
-       if (send_request) {
-#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
-               if (clk->ctx->dce_version >= DCN_VERSION_1_0
+}
+
+static void dcn_update_clocks(struct display_clock *dccg,
+                       struct dc_clocks *new_clocks,
+                       bool safe_to_lower)
+{
+       struct dm_pp_clock_for_voltage_req clock_voltage_req = {0};
+       bool send_request_to_increase = false;
+       bool send_request_to_lower = false;
+
+       if (new_clocks->dispclk_khz > dccg->clks.dispclk_khz
+                       || new_clocks->phyclk_khz > dccg->clks.phyclk_khz
+                       || new_clocks->fclk_khz > dccg->clks.fclk_khz
+                       || new_clocks->dcfclk_khz > dccg->clks.dcfclk_khz)
+               send_request_to_increase = true;
+
+#ifdef CONFIG_DRM_AMD_DC_DCN1_0
+       if (send_request_to_increase
                ) {
-                       struct dc *core_dc = clk->ctx->dc;
-                       /*use dcfclk request voltage*/
-                       clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DCFCLK;
-                       clock_voltage_req.clocks_in_khz =
-                               dcn_find_dcfclk_suits_all(core_dc, &clk->clks);
-               }
+               struct dc *core_dc = dccg->ctx->dc;
+
+               /*use dcfclk to request voltage*/
+               clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DCFCLK;
+               clock_voltage_req.clocks_in_khz = dcn_find_dcfclk_suits_all(core_dc, new_clocks);
+               dm_pp_apply_clock_for_voltage_request(dccg->ctx, &clock_voltage_req);
+       }
 #endif
-               dm_pp_apply_clock_for_voltage_request(
-                       clk->ctx, &clock_voltage_req);
+
+       if ((new_clocks->dispclk_khz < dccg->clks.dispclk_khz && safe_to_lower)
+                       || new_clocks->dispclk_khz > dccg->clks.dispclk_khz) {
+               clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DISPLAY_CLK;
+               clock_voltage_req.clocks_in_khz = new_clocks->dispclk_khz;
+               /* TODO: ramp up - dccg->funcs->set_dispclk(dccg, new_clocks->dispclk_khz);*/
+               dccg->clks.dispclk_khz = new_clocks->dispclk_khz;
+
+               dm_pp_apply_clock_for_voltage_request(dccg->ctx, &clock_voltage_req);
+               send_request_to_lower = true;
        }
-       if (update_dp_phyclk && (clocks_in_khz >
-       clk->clks.phyclk_khz))
-               clk->clks.phyclk_khz = clocks_in_khz;
 
-       return true;
+       if ((new_clocks->phyclk_khz < dccg->clks.phyclk_khz && safe_to_lower)
+                       || new_clocks->phyclk_khz > dccg->clks.phyclk_khz) {
+               dccg->clks.phyclk_khz = new_clocks->phyclk_khz;
+               clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DISPLAYPHYCLK;
+               clock_voltage_req.clocks_in_khz = new_clocks->phyclk_khz;
+
+               dm_pp_apply_clock_for_voltage_request(dccg->ctx, &clock_voltage_req);
+               send_request_to_lower = true;
+       }
+
+       if ((new_clocks->fclk_khz < dccg->clks.fclk_khz && safe_to_lower)
+                       || new_clocks->fclk_khz > dccg->clks.fclk_khz) {
+               dccg->clks.phyclk_khz = new_clocks->fclk_khz;
+               clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_FCLK;
+               clock_voltage_req.clocks_in_khz = new_clocks->fclk_khz;
+
+               dm_pp_apply_clock_for_voltage_request(dccg->ctx, &clock_voltage_req);
+               send_request_to_lower = true;
+       }
+
+       if ((new_clocks->dcfclk_khz < dccg->clks.dcfclk_khz && safe_to_lower)
+                       || new_clocks->dcfclk_khz > dccg->clks.dcfclk_khz) {
+               dccg->clks.phyclk_khz = new_clocks->dcfclk_khz;
+               clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DCFCLK;
+               clock_voltage_req.clocks_in_khz = new_clocks->dcfclk_khz;
+
+               send_request_to_lower = true;
+       }
+
+#ifdef CONFIG_DRM_AMD_DC_DCN1_0
+       if (!send_request_to_increase && send_request_to_lower
+               ) {
+               struct dc *core_dc = dccg->ctx->dc;
+
+               /*use dcfclk to request voltage*/
+               clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DCFCLK;
+               clock_voltage_req.clocks_in_khz = dcn_find_dcfclk_suits_all(core_dc, new_clocks);
+               dm_pp_apply_clock_for_voltage_request(dccg->ctx, &clock_voltage_req);
+       }
+#endif
+}
+
+static void dce_update_clocks(struct display_clock *dccg,
+                       struct dc_clocks *new_clocks,
+                       bool safe_to_lower)
+{
+       struct dm_pp_power_level_change_request level_change_req;
+
+       level_change_req.power_level = dce_get_required_clocks_state(dccg, new_clocks);
+       /* get max clock state from PPLIB */
+       if ((level_change_req.power_level < dccg->cur_min_clks_state && safe_to_lower)
+                       || level_change_req.power_level > dccg->cur_min_clks_state) {
+               if (dm_pp_apply_power_level_change_request(dccg->ctx, &level_change_req))
+                       dccg->cur_min_clks_state = level_change_req.power_level;
+       }
+
+       if ((new_clocks->dispclk_khz < dccg->clks.dispclk_khz && safe_to_lower)
+                       || new_clocks->dispclk_khz > dccg->clks.dispclk_khz) {
+               dccg->funcs->set_dispclk(dccg, new_clocks->dispclk_khz);
+               dccg->clks.dispclk_khz = new_clocks->dispclk_khz;
+       }
 }
 
+static const struct display_clock_funcs dcn_funcs = {
+       .get_dp_ref_clk_frequency = dce_clocks_get_dp_ref_freq_wrkaround,
+       .set_dispclk = dce112_set_clock,
+       .update_clocks = dcn_update_clocks
+};
 
 static const struct display_clock_funcs dce120_funcs = {
        .get_dp_ref_clk_frequency = dce_clocks_get_dp_ref_freq_wrkaround,
-       .apply_clock_voltage_request = dce_apply_clock_voltage_request,
-       .set_clock = dce112_set_clock
+       .set_dispclk = dce112_set_clock,
+       .update_clocks = dce12_update_clocks
 };
 
 static const struct display_clock_funcs dce112_funcs = {
        .get_dp_ref_clk_frequency = dce_clocks_get_dp_ref_freq,
-       .get_required_clocks_state = dce_get_required_clocks_state,
-       .set_min_clocks_state = dce_clock_set_min_clocks_state,
-       .set_clock = dce112_set_clock
+       .set_dispclk = dce112_set_clock,
+       .update_clocks = dce_update_clocks
 };
 
 static const struct display_clock_funcs dce110_funcs = {
        .get_dp_ref_clk_frequency = dce_clocks_get_dp_ref_freq,
-       .get_required_clocks_state = dce_get_required_clocks_state,
-       .set_min_clocks_state = dce_clock_set_min_clocks_state,
-       .set_clock = dce_psr_set_clock
+       .set_dispclk = dce_psr_set_clock,
+       .update_clocks = dce_update_clocks
 };
 
 static const struct display_clock_funcs dce_funcs = {
        .get_dp_ref_clk_frequency = dce_clocks_get_dp_ref_freq,
-       .get_required_clocks_state = dce_get_required_clocks_state,
-       .set_min_clocks_state = dce_clock_set_min_clocks_state,
-       .set_clock = dce_set_clock
+       .set_dispclk = dce_set_clock,
+       .update_clocks = dce_update_clocks
 };
 
 static void dce_disp_clk_construct(
@@ -785,7 +803,6 @@ struct display_clock *dce112_disp_clk_create(
 struct display_clock *dce120_disp_clk_create(struct dc_context *ctx)
 {
        struct dce_disp_clk *clk_dce = kzalloc(sizeof(*clk_dce), GFP_KERNEL);
-       struct dm_pp_clock_levels_with_voltage clk_level_info = {0};
 
        if (clk_dce == NULL) {
                BREAK_TO_DEBUGGER();
@@ -801,15 +818,23 @@ struct display_clock *dce120_disp_clk_create(struct dc_context *ctx)
 
        clk_dce->base.funcs = &dce120_funcs;
 
-       /* new in dce120 */
-       if (!ctx->dc->debug.disable_pplib_clock_request  &&
-                       dm_pp_get_clock_levels_by_type_with_voltage(
-                       ctx, DM_PP_CLOCK_TYPE_DISPLAY_CLK, &clk_level_info)
-                                               && clk_level_info.num_levels)
-               clk_dce->max_displ_clk_in_khz =
-                       clk_level_info.data[clk_level_info.num_levels - 1].clocks_in_khz;
-       else
-               clk_dce->max_displ_clk_in_khz = 1133000;
+       return &clk_dce->base;
+}
+
+struct display_clock *dcn_disp_clk_create(struct dc_context *ctx)
+{
+       struct dce_disp_clk *clk_dce = kzalloc(sizeof(*clk_dce), GFP_KERNEL);
+
+       if (clk_dce == NULL) {
+               BREAK_TO_DEBUGGER();
+               return NULL;
+       }
+
+       /* TODO strip out useful stuff out of dce constructor */
+       dce_disp_clk_construct(
+               clk_dce, ctx, NULL, NULL, NULL);
+
+       clk_dce->base.funcs = &dcn_funcs;
 
        return &clk_dce->base;
 }
index 0e717e0dc8f021322a652cc9316c8681012a6103..f9b002015255d124d0cb9ef5734cb740cd8c537b 100644 (file)
@@ -91,7 +91,6 @@ struct dce_disp_clk {
        struct state_dependent_clocks max_clks_by_state[DM_PP_CLOCKS_MAX_STATES];
        struct dce_divider_range divider_ranges[DIVIDER_RANGE_MAX];
 
-       bool use_max_disp_clk;
        int dentist_vco_freq_khz;
 
        /* Cache the status of DFS-bypass feature*/
@@ -106,9 +105,6 @@ struct dce_disp_clk {
        int dprefclk_ss_percentage;
        /* DPREFCLK SS percentage Divider (100 or 1000) */
        int dprefclk_ss_divider;
-
-       /* max disp_clk from PPLIB for max validation display clock*/
-       int max_displ_clk_in_khz;
 };
 
 
@@ -132,6 +128,8 @@ struct display_clock *dce112_disp_clk_create(
 
 struct display_clock *dce120_disp_clk_create(struct dc_context *ctx);
 
+struct display_clock *dcn_disp_clk_create(struct dc_context *ctx);
+
 void dce_disp_clk_destroy(struct display_clock **disp_clk);
 
 #endif /* _DCE_CLOCKS_H_ */
index 41f83ecd7469b0a03e922196273b1ea19c7bdf4b..aabf7ca9b241057e726b8bbc912c97564451febf 100644 (file)
@@ -125,17 +125,54 @@ static void dce100_pplib_apply_display_requirements(
        dc->prev_display_config = *pp_display_cfg;
 }
 
+/* unit: in_khz before mode set, get pixel clock from context. ASIC register
+ * may not be programmed yet
+ */
+static uint32_t get_max_pixel_clock_for_all_paths(
+       struct dc *dc,
+       struct dc_state *context)
+{
+       uint32_t max_pix_clk = 0;
+       int i;
+
+       for (i = 0; i < MAX_PIPES; i++) {
+               struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+
+               if (pipe_ctx->stream == NULL)
+                       continue;
+
+               /* do not check under lay */
+               if (pipe_ctx->top_pipe)
+                       continue;
+
+               if (pipe_ctx->stream_res.pix_clk_params.requested_pix_clk > max_pix_clk)
+                       max_pix_clk =
+                               pipe_ctx->stream_res.pix_clk_params.requested_pix_clk;
+       }
+
+       if (max_pix_clk == 0)
+               ASSERT(0);
+
+       return max_pix_clk;
+}
+
 void dce100_set_bandwidth(
                struct dc *dc,
                struct dc_state *context,
                bool decrease_allowed)
 {
-       if (decrease_allowed || context->bw.dce.dispclk_khz > dc->current_state->bw.dce.dispclk_khz) {
-               dc->res_pool->display_clock->funcs->set_clock(
-                               dc->res_pool->display_clock,
-                               context->bw.dce.dispclk_khz * 115 / 100);
-               dc->current_state->bw.dce.dispclk_khz = context->bw.dce.dispclk_khz;
-       }
+       struct dc_clocks req_clks;
+
+       req_clks.dispclk_khz = context->bw.dce.dispclk_khz * 115 / 100;
+       req_clks.phyclk_khz = get_max_pixel_clock_for_all_paths(dc, context);
+
+       dce110_set_safe_displaymarks(&context->res_ctx, dc->res_pool);
+
+       dc->res_pool->display_clock->funcs->update_clocks(
+                       dc->res_pool->display_clock,
+                       &req_clks,
+                       decrease_allowed);
+
        dce100_pplib_apply_display_requirements(dc, context);
 }
 
index ddc8ffda906781c94f2dcc8ccb485f761b5e0aed..02aa0a2ec87506964d82ba4ab0d98e81ac530e11 100644 (file)
@@ -1663,7 +1663,7 @@ static void dce110_set_displaymarks(
        }
 }
 
-static void set_safe_displaymarks(
+void dce110_set_safe_displaymarks(
                struct resource_context *res_ctx,
                const struct resource_pool *pool)
 {
@@ -1755,23 +1755,15 @@ static void set_static_screen_control(struct pipe_ctx **pipe_ctx,
 }
 
 /* unit: in_khz before mode set, get pixel clock from context. ASIC register
- * may not be programmed yet.
- * TODO: after mode set, pre_mode_set = false,
- * may read PLL register to get pixel clock
+ * may not be programmed yet
  */
 static uint32_t get_max_pixel_clock_for_all_paths(
        struct dc *dc,
-       struct dc_state *context,
-       bool pre_mode_set)
+       struct dc_state *context)
 {
        uint32_t max_pix_clk = 0;
        int i;
 
-       if (!pre_mode_set) {
-               /* TODO: read ASIC register to get pixel clock */
-               ASSERT(0);
-       }
-
        for (i = 0; i < MAX_PIPES; i++) {
                struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
 
@@ -1793,74 +1785,6 @@ static uint32_t get_max_pixel_clock_for_all_paths(
        return max_pix_clk;
 }
 
-/*
- * Find clock state based on clock requested. if clock value is 0, simply
- * set clock state as requested without finding clock state by clock value
- */
-
-static void apply_min_clocks(
-       struct dc *dc,
-       struct dc_state *context,
-       enum dm_pp_clocks_state *clocks_state,
-       bool pre_mode_set)
-{
-       struct state_dependent_clocks req_clocks = {0};
-
-       if (!pre_mode_set) {
-               /* set clock_state without verification */
-               if (context->dis_clk->funcs->set_min_clocks_state) {
-                       context->dis_clk->funcs->set_min_clocks_state(
-                                               context->dis_clk, *clocks_state);
-                       return;
-               }
-
-               /* TODO: This is incorrect. Figure out how to fix. */
-               context->dis_clk->funcs->apply_clock_voltage_request(
-                               context->dis_clk,
-                               DM_PP_CLOCK_TYPE_DISPLAY_CLK,
-                               context->dis_clk->clks.dispclk_khz,
-                               pre_mode_set,
-                               false);
-
-               context->dis_clk->funcs->apply_clock_voltage_request(
-                               context->dis_clk,
-                               DM_PP_CLOCK_TYPE_DISPLAYPHYCLK,
-                               context->dis_clk->clks.phyclk_khz,
-                               pre_mode_set,
-                               false);
-               return;
-       }
-
-       /* get the required state based on state dependent clocks:
-        * display clock and pixel clock
-        */
-       req_clocks.display_clk_khz = context->bw.dce.dispclk_khz;
-
-       req_clocks.pixel_clk_khz = get_max_pixel_clock_for_all_paths(
-                       dc, context, true);
-
-       if (context->dis_clk->funcs->get_required_clocks_state) {
-               *clocks_state = context->dis_clk->funcs->get_required_clocks_state(
-                               context->dis_clk, &req_clocks);
-               context->dis_clk->funcs->set_min_clocks_state(
-                       context->dis_clk, *clocks_state);
-       } else {
-               context->dis_clk->funcs->apply_clock_voltage_request(
-                               context->dis_clk,
-                               DM_PP_CLOCK_TYPE_DISPLAY_CLK,
-                               req_clocks.display_clk_khz,
-                               pre_mode_set,
-                               false);
-
-               context->dis_clk->funcs->apply_clock_voltage_request(
-                               context->dis_clk,
-                               DM_PP_CLOCK_TYPE_DISPLAYPHYCLK,
-                               req_clocks.pixel_clk_khz,
-                               pre_mode_set,
-                               false);
-       }
-}
-
 /*
  *  Check if FBC can be enabled
  */
@@ -2079,7 +2003,6 @@ enum dc_status dce110_apply_ctx_to_hw(
        struct dc_bios *dcb = dc->ctx->dc_bios;
        enum dc_status status;
        int i;
-       enum dm_pp_clocks_state clocks_state = DM_PP_CLOCKS_STATE_INVALID;
 
        /* Reset old context */
        /* look up the targets that have been removed since last commit */
@@ -2113,54 +2036,10 @@ enum dc_status dce110_apply_ctx_to_hw(
                                PIPE_GATING_CONTROL_DISABLE);
        }
 
-       set_safe_displaymarks(&context->res_ctx, dc->res_pool);
-
        if (dc->fbc_compressor)
                dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor);
 
-       /*TODO: when pplib works*/
-       apply_min_clocks(dc, context, &clocks_state, true);
-
-#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
-       if (dc->ctx->dce_version >= DCN_VERSION_1_0) {
-               if (context->bw.dcn.calc_clk.fclk_khz
-                               > dc->current_state->bw.dcn.cur_clk.fclk_khz) {
-                       struct dm_pp_clock_for_voltage_req clock;
-
-                       clock.clk_type = DM_PP_CLOCK_TYPE_FCLK;
-                       clock.clocks_in_khz = context->bw.dcn.calc_clk.fclk_khz;
-                       dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock);
-                       dc->current_state->bw.dcn.cur_clk.fclk_khz = clock.clocks_in_khz;
-                       context->bw.dcn.cur_clk.fclk_khz = clock.clocks_in_khz;
-               }
-               if (context->bw.dcn.calc_clk.dcfclk_khz
-                               > dc->current_state->bw.dcn.cur_clk.dcfclk_khz) {
-                       struct dm_pp_clock_for_voltage_req clock;
-
-                       clock.clk_type = DM_PP_CLOCK_TYPE_DCFCLK;
-                       clock.clocks_in_khz = context->bw.dcn.calc_clk.dcfclk_khz;
-                       dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock);
-                       dc->current_state->bw.dcn.cur_clk.dcfclk_khz = clock.clocks_in_khz;
-                       context->bw.dcn.cur_clk.dcfclk_khz = clock.clocks_in_khz;
-               }
-               if (context->bw.dcn.calc_clk.dispclk_khz
-                               > dc->current_state->bw.dcn.cur_clk.dispclk_khz) {
-                       dc->res_pool->display_clock->funcs->set_clock(
-                                       dc->res_pool->display_clock,
-                                       context->bw.dcn.calc_clk.dispclk_khz);
-                       dc->current_state->bw.dcn.cur_clk.dispclk_khz =
-                                       context->bw.dcn.calc_clk.dispclk_khz;
-                       context->bw.dcn.cur_clk.dispclk_khz =
-                                       context->bw.dcn.calc_clk.dispclk_khz;
-               }
-       } else
-#endif
-       if (context->bw.dce.dispclk_khz
-                       > dc->current_state->bw.dce.dispclk_khz) {
-               dc->res_pool->display_clock->funcs->set_clock(
-                               dc->res_pool->display_clock,
-                               context->bw.dce.dispclk_khz * 115 / 100);
-       }
+       dc->hwss.set_bandwidth(dc, context, false);
 
        dce110_setup_audio_dto(dc, context);
 
@@ -2191,7 +2070,7 @@ enum dc_status dce110_apply_ctx_to_hw(
        }
 
        /* to save power */
-       apply_min_clocks(dc, context, &clocks_state, false);
+       dc->hwss.set_bandwidth(dc, context, true);
 
        dcb->funcs->set_scratch_critical_state(dcb, false);
 
@@ -2680,15 +2559,20 @@ static void dce110_set_bandwidth(
                struct dc_state *context,
                bool decrease_allowed)
 {
-       dce110_set_displaymarks(dc, context);
+       struct dc_clocks req_clks;
 
-       if (decrease_allowed || context->bw.dce.dispclk_khz > dc->current_state->bw.dce.dispclk_khz) {
-               dc->res_pool->display_clock->funcs->set_clock(
-                               dc->res_pool->display_clock,
-                               context->bw.dce.dispclk_khz * 115 / 100);
-               dc->current_state->bw.dce.dispclk_khz = context->bw.dce.dispclk_khz;
-       }
+       req_clks.dispclk_khz = context->bw.dce.dispclk_khz * 115 / 100;
+       req_clks.phyclk_khz = get_max_pixel_clock_for_all_paths(dc, context);
+
+       if (decrease_allowed)
+               dce110_set_displaymarks(dc, context);
+       else
+               dce110_set_safe_displaymarks(&context->res_ctx, dc->res_pool);
 
+       dc->res_pool->display_clock->funcs->update_clocks(
+                       dc->res_pool->display_clock,
+                       &req_clks,
+                       decrease_allowed);
        pplib_apply_display_requirements(dc, context);
 }
 
index f48d5a68d2386ea30d93123691dbaca25b7ba7af..d6db3dbd90153ba4a3f9511eb494552b143b4255 100644 (file)
@@ -60,6 +60,10 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context);
 
 void dce110_power_down(struct dc *dc);
 
+void dce110_set_safe_displaymarks(
+               struct resource_context *res_ctx,
+               const struct resource_pool *pool);
+
 void dce110_fill_display_configs(
        const struct dc_state *context,
        struct dm_pp_display_configuration *pp_display_cfg);
index 03eb736a312ff8207f6c085ffce6eced2687021c..7f1a7ec9ff5f631808ced3dda10915284ab4b45b 100644 (file)
@@ -2424,7 +2424,7 @@ static void ramp_up_dispclk_with_dpp(struct dc *dc, struct dc_state *context)
        int dispclk_to_dpp_threshold = determine_dppclk_threshold(dc, context);
 
        /* set disp clk to dpp clk threshold */
-       dc->res_pool->display_clock->funcs->set_clock(
+       dc->res_pool->display_clock->funcs->set_dispclk(
                        dc->res_pool->display_clock,
                        dispclk_to_dpp_threshold);
 
@@ -2443,7 +2443,7 @@ static void ramp_up_dispclk_with_dpp(struct dc *dc, struct dc_state *context)
 
        /* If target clk not same as dppclk threshold, set to target clock */
        if (dispclk_to_dpp_threshold != context->bw.dcn.calc_clk.dispclk_khz) {
-               dc->res_pool->display_clock->funcs->set_clock(
+               dc->res_pool->display_clock->funcs->set_dispclk(
                                dc->res_pool->display_clock,
                                context->bw.dcn.calc_clk.dispclk_khz);
        }
@@ -2473,6 +2473,11 @@ static void dcn10_set_bandwidth(
        if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
                return;
 
+       dc->res_pool->display_clock->funcs->update_clocks(
+                       dc->res_pool->display_clock,
+                       &context->bw.dcn.calc_clk,
+                       decrease_allowed);
+
        if (should_set_clock(
                        decrease_allowed,
                        context->bw.dcn.calc_clk.dcfclk_khz,
index 2da325ce781bca529d4df4f8d2cc9c1bd2bb4c2a..870eb0aabcc9e321488dba86b86497f106343c15 100644 (file)
@@ -1072,7 +1072,7 @@ static bool construct(
                }
        }
 
-       pool->base.display_clock = dce120_disp_clk_create(ctx);
+       pool->base.display_clock = dcn_disp_clk_create(ctx);
        if (pool->base.display_clock == NULL) {
                dm_error("DC: failed to create display clock!\n");
                BREAK_TO_DEBUGGER();
index 6b9ca5562de994b99a74c3f2d2025ce3a105275f..8ce106f156476d7b5d05bab3c9f048a011a41404 100644 (file)
@@ -40,32 +40,19 @@ struct display_clock {
        struct dc_context *ctx;
        const struct display_clock_funcs *funcs;
 
-       bool dispclk_notify_pplib_done;
-       bool phyclk_notify_pplib_done;
        enum dm_pp_clocks_state max_clks_state;
        enum dm_pp_clocks_state cur_min_clks_state;
        struct dc_clocks clks;
 };
 
 struct display_clock_funcs {
-       int (*set_clock)(struct display_clock *disp_clk,
+       void (*update_clocks)(struct display_clock *dccg,
+                       struct dc_clocks *new_clocks,
+                       bool safe_to_lower);
+       int (*set_dispclk)(struct display_clock *disp_clk,
                int requested_clock_khz);
 
-       enum dm_pp_clocks_state (*get_required_clocks_state)(
-               struct display_clock *disp_clk,
-               struct state_dependent_clocks *req_clocks);
-
-       bool (*set_min_clocks_state)(struct display_clock *disp_clk,
-               enum dm_pp_clocks_state dm_pp_clocks_state);
-
        int (*get_dp_ref_clk_frequency)(struct display_clock *disp_clk);
-
-       bool (*apply_clock_voltage_request)(
-               struct display_clock *disp_clk,
-               enum dm_pp_clock_type clocks_type,
-               int clocks_in_khz,
-               bool pre_mode_set,
-               bool update_dp_phyclk);
 };
 
 #endif /* __DISPLAY_CLOCK_H__ */