drm/amd/display: add vsync notify to dmub for abm pause
authorEric Yang <Eric.Yang2@amd.com>
Fri, 10 Sep 2021 17:43:49 +0000 (13:43 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 28 Sep 2021 13:30:09 +0000 (09:30 -0400)
[Why]
To prevent unnecessary wake up of DMCUB when ABM is enabled without PSR
enabled, driver will notify DMCUB to stop ABM's vertical interrupts
if vsync is disabled and steady state is reached.

[How]
Send inbox message to notify ABM pause based on vsync on/off

Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com>
Acked-by: Anson Jacob <Anson.Jacob@amd.com>
Signed-off-by: Eric Yang <Eric.Yang2@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@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/dc.h
drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c
drivers/gpu/drm/amd/display/dc/inc/hw/abm.h
drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h

index 331a7517176b5ae06b5d308096561e06f9363584..644005846433a08957715bcf368d81266e2c9f93 100644 (file)
@@ -3536,3 +3536,57 @@ void dc_disable_accelerated_mode(struct dc *dc)
 {
        bios_set_scratch_acc_mode_change(dc->ctx->dc_bios, 0);
 }
+
+
+/**
+ *****************************************************************************
+ *  dc_notify_vsync_int_state() - notifies vsync enable/disable state
+ *  @dc: dc structure
+ *     @stream: stream where vsync int state changed
+ *     @enable: whether vsync is enabled or disabled
+ *
+ *  Called when vsync is enabled/disabled
+ *     Will notify DMUB to start/stop ABM interrupts after steady state is reached
+ *
+ *****************************************************************************
+ */
+void dc_notify_vsync_int_state(struct dc *dc, struct dc_stream_state *stream, bool enable)
+{
+       int i;
+       int edp_num;
+       struct pipe_ctx *pipe = NULL;
+       struct dc_link *link = stream->sink->link;
+       struct dc_link *edp_links[MAX_NUM_EDP];
+
+
+       if (link->psr_settings.psr_feature_enabled)
+               return;
+
+       /*find primary pipe associated with stream*/
+       for (i = 0; i < MAX_PIPES; i++) {
+               pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+
+               if (pipe->stream == stream && pipe->stream_res.tg)
+                       break;
+       }
+
+       if (i == MAX_PIPES) {
+               ASSERT(0);
+               return;
+       }
+
+       get_edp_links(dc, edp_links, &edp_num);
+
+       /* Determine panel inst */
+       for (i = 0; i < edp_num; i++) {
+               if (edp_links[i] == link)
+                       break;
+       }
+
+       if (i == edp_num) {
+               return;
+       }
+
+       if (pipe->stream_res.abm && pipe->stream_res.abm->funcs->set_abm_pause)
+               pipe->stream_res.abm->funcs->set_abm_pause(pipe->stream_res.abm, !enable, i, pipe->stream_res.tg->inst);
+}
index e5dcbee6e6723fef06f6c0a13e11ea9495a70ce9..b194a2727bd80196fcff90853a657234e1bad0a7 100644 (file)
@@ -1313,6 +1313,8 @@ void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src);
 enum dc_irq_source dc_get_hpd_irq_source_at_index(
                struct dc *dc, uint32_t link_index);
 
+void dc_notify_vsync_int_state(struct dc *dc, struct dc_stream_state *stream, bool enable);
+
 /*******************************************************************************
  * Power Interfaces
  ******************************************************************************/
index 54a1408c8015c8bc5005b3c6131aaf06258b3e86..fb0dec4ed3a6ca6fb42414b46d298c58fced8739 100644 (file)
@@ -203,12 +203,33 @@ static bool dmub_abm_init_config(struct abm *abm,
        return true;
 }
 
+static bool dmub_abm_set_pause(struct abm *abm, bool pause, unsigned int panel_inst, unsigned int stream_inst)
+{
+       union dmub_rb_cmd cmd;
+       struct dc_context *dc = abm->ctx;
+       uint8_t panel_mask = 0x01 << panel_inst;
+
+       memset(&cmd, 0, sizeof(cmd));
+       cmd.abm_pause.header.type = DMUB_CMD__ABM;
+       cmd.abm_pause.header.sub_type = DMUB_CMD__ABM_PAUSE;
+       cmd.abm_pause.abm_pause_data.enable = pause;
+       cmd.abm_pause.abm_pause_data.panel_mask = panel_mask;
+       cmd.abm_set_level.header.payload_bytes = sizeof(struct dmub_cmd_abm_pause_data);
+
+       dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
+       dc_dmub_srv_cmd_execute(dc->dmub_srv);
+       dc_dmub_srv_wait_idle(dc->dmub_srv);
+
+       return true;
+}
+
 static const struct abm_funcs abm_funcs = {
        .abm_init = dmub_abm_init,
        .set_abm_level = dmub_abm_set_level,
        .get_current_backlight = dmub_abm_get_current_backlight,
        .get_target_backlight = dmub_abm_get_target_backlight,
        .init_abm_config = dmub_abm_init_config,
+       .set_abm_pause = dmub_abm_set_pause,
 };
 
 static void dmub_abm_construct(
index 142753644377a6314ed7a4f48b17592f25609dad..ecb4191b6e64f45cceb2af602c59a5d9f2ad85b9 100644 (file)
@@ -54,6 +54,7 @@ struct abm_funcs {
                        const char *src,
                        unsigned int bytes,
                        unsigned int inst);
+       bool (*set_abm_pause)(struct abm *abm, bool pause, unsigned int panel_inst, unsigned int otg_inst);
 };
 
 #endif
index 4647129c66fda13a983f07fd82fbbe5139a19ff4..70e6d6905fda1d2386e1e24bd1a87e995392a98c 100644 (file)
@@ -1731,6 +1731,11 @@ enum dmub_cmd_abm_type {
         * Enable/disable fractional duty cycle for backlight PWM.
         */
        DMUB_CMD__ABM_SET_PWM_FRAC      = 5,
+
+       /**
+        * unregister vertical interrupt after steady state is reached
+        */
+       DMUB_CMD__ABM_PAUSE     = 6,
 };
 
 /**
@@ -2086,6 +2091,50 @@ struct dmub_rb_cmd_abm_init_config {
        struct dmub_cmd_abm_init_config_data abm_init_config_data;
 };
 
+/**
+ * Data passed from driver to FW in a DMUB_CMD__ABM_PAUSE command.
+ */
+
+struct dmub_cmd_abm_pause_data {
+
+       /**
+        * Panel Control HW instance mask.
+        * Bit 0 is Panel Control HW instance 0.
+        * Bit 1 is Panel Control HW instance 1.
+        */
+       uint8_t panel_mask;
+
+       /**
+        * OTG hw instance
+        */
+       uint8_t otg_inst;
+
+       /**
+        * Enable or disable ABM pause
+        */
+       uint8_t enable;
+
+       /**
+        * Explicit padding to 4 byte boundary.
+        */
+       uint8_t pad[1];
+};
+
+/**
+ * Definition of a DMUB_CMD__ABM_PAUSE command.
+ */
+struct dmub_rb_cmd_abm_pause {
+       /**
+        * Command header.
+        */
+       struct dmub_cmd_header header;
+
+       /**
+        * Data passed from driver to FW in a DMUB_CMD__ABM_PAUSE command.
+        */
+       struct dmub_cmd_abm_pause_data abm_pause_data;
+};
+
 /**
  * Data passed from driver to FW in a DMUB_CMD__QUERY_FEATURE_CAPS command.
  */
@@ -2364,6 +2413,11 @@ union dmub_rb_cmd {
         */
        struct dmub_rb_cmd_abm_init_config abm_init_config;
 
+       /**
+        * Definition of a DMUB_CMD__ABM_PAUSE command.
+        */
+       struct dmub_rb_cmd_abm_pause abm_pause;
+
        /**
         * Definition of a DMUB_CMD__DP_AUX_ACCESS command.
         */