OSDN Git Service

drm/amd/display: disable stream if pixel clock changed with link active
authorChiawen Huang <chiawen.huang@amd.com>
Fri, 25 Sep 2020 14:54:50 +0000 (10:54 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 29 Sep 2020 20:08:44 +0000 (16:08 -0400)
[Why]
Vbios uses preferred timing to turn on edp but OS could use other
timing. If change pixel clock when link active, there is unexpected
garbage on monitor.

[How]
Once pixel clock changed, the driver needs to disable stream.

Signed-off-by: Chiawen Huang <chiawen.huang@amd.com>
Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c

index 7e74ddc..9fabe26 100644 (file)
@@ -842,6 +842,61 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
        dc_release_state(current_ctx);
 }
 
+static void disable_vbios_mode_if_required(
+               struct dc *dc,
+               struct dc_state *context)
+{
+       unsigned int i;
+
+       /* check if timing_changed, disable stream*/
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               struct dc_stream_state *stream = NULL;
+               struct dc_link *link = NULL;
+               struct pipe_ctx *pipe = NULL;
+
+               pipe = &context->res_ctx.pipe_ctx[i];
+               stream = pipe->stream;
+               if (stream == NULL)
+                       continue;
+
+               if (stream->link->local_sink &&
+                       stream->link->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
+                       link = stream->link;
+                       break;
+               }
+
+               if (link != NULL) {
+                       unsigned int enc_inst, tg_inst = 0;
+                       unsigned int pix_clk_100hz;
+
+                       enc_inst = link->link_enc->funcs->get_dig_frontend(link->link_enc);
+                       if (enc_inst != ENGINE_ID_UNKNOWN) {
+                               for (i = 0; i < dc->res_pool->stream_enc_count; i++) {
+                                       if (dc->res_pool->stream_enc[i]->id == enc_inst) {
+                                               tg_inst = dc->res_pool->stream_enc[i]->funcs->dig_source_otg(
+                                                       dc->res_pool->stream_enc[i]);
+                                               break;
+                                       }
+                               }
+
+                               dc->res_pool->dp_clock_source->funcs->get_pixel_clk_frequency_100hz(
+                                       dc->res_pool->dp_clock_source,
+                                       tg_inst, &pix_clk_100hz);
+
+                               if (link->link_status.link_active) {
+                                       uint32_t requested_pix_clk_100hz =
+                                               pipe->stream_res.pix_clk_params.requested_pix_clk_100hz;
+
+                                       if (pix_clk_100hz != requested_pix_clk_100hz) {
+                                               core_link_disable_stream(pipe);
+                                               pipe->stream->dpms_off = false;
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
 static void wait_for_no_pipes_pending(struct dc *dc, struct dc_state *context)
 {
        int i;
@@ -1278,13 +1333,14 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
        for (i = 0; i < context->stream_count; i++)
                dc_streams[i] =  context->streams[i];
 
-       if (!dcb->funcs->is_accelerated_mode(dcb))
+       if (!dcb->funcs->is_accelerated_mode(dcb)) {
+               disable_vbios_mode_if_required(dc, context);
                dc->hwss.enable_accelerated_mode(dc, context);
+       }
 
-       for (i = 0; i < context->stream_count; i++) {
+       for (i = 0; i < context->stream_count; i++)
                if (context->streams[i]->apply_seamless_boot_optimization)
                        dc->optimize_seamless_boot_streams++;
-       }
 
        if (context->stream_count > dc->optimize_seamless_boot_streams ||
                context->stream_count == 0)
index 27a1262..c73768e 100644 (file)
@@ -1654,7 +1654,7 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context)
                // enable fastboot if backend is enabled on eDP
                if (edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc)) {
                        /* Set optimization flag on eDP stream*/
-                       if (edp_stream) {
+                       if (edp_stream && edp_link->link_status.link_active) {
                                edp_stream->apply_edp_fast_boot_optimization = true;
                                can_apply_edp_fast_boot = true;
                        }