drm/amd/display: Refactor edp power control
authorIan Chen <ian.chen@amd.com>
Tue, 4 Jul 2023 07:31:43 +0000 (15:31 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 8 Dec 2023 07:52:24 +0000 (08:52 +0100)
[ Upstream commit 45f98fccb1f6895f527bd5f811f23478c2f920f5 ]

[Why & How]
To organize the edp power control a bit:

1. add flag in dc_link to indicate dc to skip all implicit eDP power control.
2. add edp_set_panel_power link service for DM to call.

Reviewed-by: Aric Cyr <aric.cyr@amd.com>
Reviewed-by: Jun Lei <jun.lei@amd.com>
Acked-by: Wayne Lin <wayne.lin@amd.com>
Signed-off-by: Ian Chen <ian.chen@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Stable-dep-of: b0399e22ada0 ("drm/amd/display: Remove power sequencing check")
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/dc.h
drivers/gpu/drm/amd/display/dc/dc_stream.h
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c
drivers/gpu/drm/amd/display/dc/inc/link.h
drivers/gpu/drm/amd/display/dc/link/link_dpms.c
drivers/gpu/drm/amd/display/dc/link/link_factory.c
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.c
drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h

index 186936a..a1be93f 100644 (file)
@@ -5254,3 +5254,24 @@ void dc_query_current_properties(struct dc *dc, struct dc_current_properties *pr
        properties->cursor_size_limit = subvp_in_use ? 64 : dc->caps.max_cursor_size;
 }
 
+/**
+ *****************************************************************************
+ * dc_set_edp_power() - DM controls eDP power to be ON/OFF
+ *
+ * Called when DM wants to power on/off eDP.
+ *     Only work on links with flag skip_implict_edp_power_control is set.
+ *
+ *****************************************************************************
+ */
+void dc_set_edp_power(const struct dc *dc, struct dc_link *edp_link,
+                                bool powerOn)
+{
+       if (edp_link->connector_signal != SIGNAL_TYPE_EDP)
+               return;
+
+       if (edp_link->skip_implict_edp_power_control == false)
+               return;
+
+       edp_link->dc->link_srv->edp_set_panel_power(edp_link, powerOn);
+}
+
index c05e91b..dd7bf31 100644 (file)
@@ -1578,6 +1578,7 @@ struct dc_link {
        struct phy_state phy_state;
        // BW ALLOCATON USB4 ONLY
        struct dc_dpia_bw_alloc dpia_bw_alloc_config;
+       bool skip_implict_edp_power_control;
 };
 
 /* Return an enumerated dc_link.
@@ -1597,6 +1598,9 @@ void dc_get_edp_links(const struct dc *dc,
                struct dc_link **edp_links,
                int *edp_num);
 
+void dc_set_edp_power(const struct dc *dc, struct dc_link *edp_link,
+                                bool powerOn);
+
 /* The function initiates detection handshake over the given link. It first
  * determines if there are display connections over the link. If so it initiates
  * detection protocols supported by the connected receiver device. The function
index 3697ea1..d5b3e3a 100644 (file)
@@ -302,7 +302,6 @@ struct dc_stream_state {
        bool vblank_synchronized;
        bool fpo_in_use;
        struct mall_stream_config mall_stream_config;
-       bool skip_edp_power_down;
 };
 
 #define ABM_LEVEL_IMMEDIATE_DISABLE 255
index 2a61575..9c78e42 100644 (file)
@@ -1226,7 +1226,7 @@ void dce110_blank_stream(struct pipe_ctx *pipe_ctx)
        struct dce_hwseq *hws = link->dc->hwseq;
 
        if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
-               if (!stream->skip_edp_power_down)
+               if (!link->skip_implict_edp_power_control)
                        hws->funcs.edp_backlight_control(link, false);
                link->dc->hwss.set_abm_immediate_disable(pipe_ctx);
        }
index 4d2820f..33a8626 100644 (file)
@@ -476,7 +476,8 @@ void dcn314_disable_link_output(struct dc_link *link,
        struct dmcu *dmcu = dc->res_pool->dmcu;
 
        if (signal == SIGNAL_TYPE_EDP &&
-                       link->dc->hwss.edp_backlight_control)
+                       link->dc->hwss.edp_backlight_control &&
+                       !link->skip_implict_edp_power_control)
                link->dc->hwss.edp_backlight_control(link, false);
        else if (dmcu != NULL && dmcu->funcs->lock_phy)
                dmcu->funcs->lock_phy(dmcu);
index e3e8c76..d768536 100644 (file)
@@ -295,6 +295,7 @@ struct link_service {
        bool (*edp_receiver_ready_T9)(struct dc_link *link);
        bool (*edp_receiver_ready_T7)(struct dc_link *link);
        bool (*edp_power_alpm_dpcd_enable)(struct dc_link *link, bool enable);
+       void (*edp_set_panel_power)(struct dc_link *link, bool powerOn);
 
 
        /*************************** DP CTS ************************************/
index 79aef20..28cb1f5 100644 (file)
@@ -1930,7 +1930,8 @@ static void disable_link_dp(struct dc_link *link,
        dp_disable_link_phy(link, link_res, signal);
 
        if (link->connector_signal == SIGNAL_TYPE_EDP) {
-               if (!link->dc->config.edp_no_power_sequencing)
+               if (!link->dc->config.edp_no_power_sequencing &&
+                       !link->skip_implict_edp_power_control)
                        link->dc->hwss.edp_power_control(link, false);
        }
 
@@ -2219,7 +2220,7 @@ static enum dc_status enable_link(
         * link settings. Need to call disable first before enabling at
         * new link settings.
         */
-       if (link->link_status.link_active && !stream->skip_edp_power_down)
+       if (link->link_status.link_active)
                disable_link(link, &pipe_ctx->link_res, pipe_ctx->stream->signal);
 
        switch (pipe_ctx->stream->signal) {
@@ -2338,9 +2339,7 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx)
                dc->hwss.disable_stream(pipe_ctx);
        } else {
                dc->hwss.disable_stream(pipe_ctx);
-               if (!pipe_ctx->stream->skip_edp_power_down) {
-                       disable_link(pipe_ctx->stream->link, &pipe_ctx->link_res, pipe_ctx->stream->signal);
-               }
+               disable_link(pipe_ctx->stream->link, &pipe_ctx->link_res, pipe_ctx->stream->signal);
        }
 
        if (pipe_ctx->stream->timing.flags.DSC) {
index 0895742..e406561 100644 (file)
@@ -223,6 +223,7 @@ static void construct_link_service_edp_panel_control(struct link_service *link_s
        link_srv->edp_receiver_ready_T9 = edp_receiver_ready_T9;
        link_srv->edp_receiver_ready_T7 = edp_receiver_ready_T7;
        link_srv->edp_power_alpm_dpcd_enable = edp_power_alpm_dpcd_enable;
+       link_srv->edp_set_panel_power = edp_set_panel_power;
 }
 
 /* link dp cts implements dp compliance test automation protocols and manual
index b7abba5..0050e0a 100644 (file)
@@ -73,7 +73,8 @@ void dp_disable_link_phy(struct dc_link *link,
 {
        struct dc  *dc = link->ctx->dc;
 
-       if (!link->wa_flags.dp_keep_receiver_powered)
+       if (!link->wa_flags.dp_keep_receiver_powered &&
+               !link->skip_implict_edp_power_control)
                dpcd_write_rx_power_ctrl(link, false);
 
        dc->hwss.disable_link_output(link, link_res, signal);
index 98e715a..24b47fa 100644 (file)
@@ -33,6 +33,7 @@
 #include "link_dp_capability.h"
 #include "dm_helpers.h"
 #include "dal_asic_id.h"
+#include "link_dp_phy.h"
 #include "dce/dmub_psr.h"
 #include "dc/dc_dmub_srv.h"
 #include "dce/dmub_replay.h"
@@ -362,6 +363,34 @@ void edp_panel_backlight_power_on(struct dc_link *link, bool wait_for_hpd)
                link->dc->hwss.edp_backlight_control(link, true);
 }
 
+void edp_set_panel_power(struct dc_link *link, bool powerOn)
+{
+       if (powerOn) {
+               // 1. panel VDD on
+               if (!link->dc->config.edp_no_power_sequencing)
+                       link->dc->hwss.edp_power_control(link, true);
+               link->dc->hwss.edp_wait_for_hpd_ready(link, true);
+
+               // 2. panel BL on
+               if (link->dc->hwss.edp_backlight_control)
+                       link->dc->hwss.edp_backlight_control(link, true);
+
+               // 3. Rx power on
+               dpcd_write_rx_power_ctrl(link, true);
+       } else {
+               // 3. Rx power off
+               dpcd_write_rx_power_ctrl(link, false);
+
+               // 2. panel BL off
+               if (link->dc->hwss.edp_backlight_control)
+                       link->dc->hwss.edp_backlight_control(link, false);
+
+               // 1. panel VDD off
+               if (!link->dc->config.edp_no_power_sequencing)
+                       link->dc->hwss.edp_power_control(link, false);
+       }
+}
+
 bool edp_wait_for_t12(struct dc_link *link)
 {
        if (link->connector_signal == SIGNAL_TYPE_EDP && link->dc->hwss.edp_wait_for_T12) {
index 0a5bbda..20f91de 100644 (file)
@@ -69,4 +69,5 @@ void edp_add_delay_for_T9(struct dc_link *link);
 bool edp_receiver_ready_T9(struct dc_link *link);
 bool edp_receiver_ready_T7(struct dc_link *link);
 bool edp_power_alpm_dpcd_enable(struct dc_link *link, bool enable);
+void edp_set_panel_power(struct dc_link *link, bool powerOn);
 #endif /* __DC_LINK_EDP_POWER_CONTROL_H__ */