drm/amd/display: Process crc window at DMCU
authorWayne Lin <Wayne.Lin@amd.com>
Tue, 19 Jan 2021 09:19:17 +0000 (17:19 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 5 Mar 2021 20:11:54 +0000 (15:11 -0500)
[Why & How]
Add additional MCP_SCP commands for starting/stopping updaing crc
window at DMCU

Signed-off-by: Wayne Lin <Wayne.Lin@amd.com>
Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com>
Acked-by: Eryk Brol <eryk.brol@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/dc_stream.h
drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h

index 87b8315..86de6ee 100644 (file)
@@ -347,6 +347,88 @@ bool dc_stream_get_crtc_position(struct dc *dc,
        return ret;
 }
 
+#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
+bool dc_stream_forward_dmcu_crc_window(struct dc *dc, struct dc_stream_state *stream,
+                            struct crc_params *crc_window)
+{
+       int i;
+       struct dmcu *dmcu = dc->res_pool->dmcu;
+       struct pipe_ctx *pipe;
+       struct crc_region tmp_win, *crc_win;
+       struct otg_phy_mux mapping_tmp, *mux_mapping;
+
+       /*crc window can't be null*/
+       if (!crc_window)
+               return false;
+
+       if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu))) {
+               crc_win = &tmp_win;
+               mux_mapping = &mapping_tmp;
+               /*set crc window*/
+               tmp_win.x_start = crc_window->windowa_x_start;
+               tmp_win.y_start = crc_window->windowa_y_start;
+               tmp_win.x_end = crc_window->windowa_x_end;
+               tmp_win.y_end = crc_window->windowa_y_end;
+
+               for (i = 0; i < MAX_PIPES; i++) {
+                       pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+                       if (pipe->stream == stream && !pipe->top_pipe && !pipe->prev_odm_pipe)
+                               break;
+               }
+
+               /* Stream not found */
+               if (i == MAX_PIPES)
+                       return false;
+
+
+               /*set mux routing info*/
+               mapping_tmp.phy_output_num = stream->link->link_enc_hw_inst;
+               mapping_tmp.otg_output_num = pipe->stream_res.tg->inst;
+
+               dmcu->funcs->forward_crc_window(dmcu, crc_win, mux_mapping);
+       } else {
+               DC_LOG_DC("dmcu is not initialized");
+               return false;
+       }
+
+       return true;
+}
+
+bool dc_stream_stop_dmcu_crc_win_update(struct dc *dc, struct dc_stream_state *stream)
+{
+       int i;
+       struct dmcu *dmcu = dc->res_pool->dmcu;
+       struct pipe_ctx *pipe;
+       struct otg_phy_mux mapping_tmp, *mux_mapping;
+
+       if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu))) {
+               mux_mapping = &mapping_tmp;
+
+               for (i = 0; i < MAX_PIPES; i++) {
+                       pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+                       if (pipe->stream == stream && !pipe->top_pipe && !pipe->prev_odm_pipe)
+                               break;
+               }
+
+               /* Stream not found */
+               if (i == MAX_PIPES)
+                       return false;
+
+
+               /*set mux routing info*/
+               mapping_tmp.phy_output_num = stream->link->link_enc_hw_inst;
+               mapping_tmp.otg_output_num = pipe->stream_res.tg->inst;
+
+               dmcu->funcs->stop_crc_win_update(dmcu, mux_mapping);
+       } else {
+               DC_LOG_DC("dmcu is not initialized");
+               return false;
+       }
+
+       return true;
+}
+#endif
+
 /**
  * dc_stream_configure_crc() - Configure CRC capture for the given stream.
  * @dc: DC Object
index a597eca..e747370 100644 (file)
@@ -453,6 +453,13 @@ bool dc_stream_get_crtc_position(struct dc *dc,
                                 unsigned int *v_pos,
                                 unsigned int *nom_v_pos);
 
+#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
+bool dc_stream_forward_dmcu_crc_window(struct dc *dc, struct dc_stream_state *stream,
+                            struct crc_params *crc_window);
+bool dc_stream_stop_dmcu_crc_win_update(struct dc *dc,
+                                struct dc_stream_state *stream);
+#endif
+
 bool dc_stream_configure_crc(struct dc *dc,
                             struct dc_stream_state *stream,
                             struct crc_params *crc_window,
index ddc789d..4f86450 100644 (file)
@@ -57,6 +57,8 @@
 #define MCP_SYNC_PHY_LOCK 0x90
 #define MCP_SYNC_PHY_UNLOCK 0x91
 #define MCP_BL_SET_PWM_FRAC 0x6A  /* Enable or disable Fractional PWM */
+#define CRC_WIN_NOTIFY 0x92
+#define CRC_STOP_UPDATE 0x93
 #define MCP_SEND_EDID_CEA 0xA0
 #define EDID_CEA_CMD_ACK 1
 #define EDID_CEA_CMD_NACK 2
@@ -930,6 +932,84 @@ static bool dcn10_recv_edid_cea_ack(struct dmcu *dmcu, int *offset)
 
 #endif //(CONFIG_DRM_AMD_DC_DCN)
 
+#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
+static void dcn10_forward_crc_window(struct dmcu *dmcu,
+                                       struct crc_region *crc_win,
+                                       struct otg_phy_mux *mux_mapping)
+{
+       struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu);
+       unsigned int dmcu_max_retry_on_wait_reg_ready = 801;
+       unsigned int dmcu_wait_reg_ready_interval = 100;
+       unsigned int crc_start = 0, crc_end = 0, otg_phy_mux = 0;
+
+       /* If microcontroller is not running, do nothing */
+       if (dmcu->dmcu_state != DMCU_RUNNING)
+               return;
+
+       if (!crc_win)
+               return;
+
+       /* waitDMCUReadyForCmd */
+       REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0,
+                               dmcu_wait_reg_ready_interval,
+                               dmcu_max_retry_on_wait_reg_ready);
+
+       /* build up nitification data */
+       crc_start = (((unsigned int) crc_win->x_start) << 16) | crc_win->y_start;
+       crc_end = (((unsigned int) crc_win->x_end) << 16) | crc_win->y_end;
+       otg_phy_mux =
+               (((unsigned int) mux_mapping->otg_output_num) << 16) | mux_mapping->phy_output_num;
+
+       dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG1),
+                                       crc_start);
+
+       dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG2),
+                       crc_end);
+
+       dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG3),
+                       otg_phy_mux);
+
+       /* setDMCUParam_Cmd */
+       REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0,
+                               CRC_WIN_NOTIFY);
+
+       /* notifyDMCUMsg */
+       REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
+}
+
+static void dcn10_stop_crc_win_update(struct dmcu *dmcu,
+                                       struct otg_phy_mux *mux_mapping)
+{
+       struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu);
+       unsigned int dmcu_max_retry_on_wait_reg_ready = 801;
+       unsigned int dmcu_wait_reg_ready_interval = 100;
+       unsigned int otg_phy_mux = 0;
+
+       /* If microcontroller is not running, do nothing */
+       if (dmcu->dmcu_state != DMCU_RUNNING)
+               return;
+
+       /* waitDMCUReadyForCmd */
+       REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0,
+                               dmcu_wait_reg_ready_interval,
+                               dmcu_max_retry_on_wait_reg_ready);
+
+       /* build up nitification data */
+       otg_phy_mux =
+               (((unsigned int) mux_mapping->otg_output_num) << 16) | mux_mapping->phy_output_num;
+
+       dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG1),
+                                       otg_phy_mux);
+
+       /* setDMCUParam_Cmd */
+       REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0,
+                               CRC_STOP_UPDATE);
+
+       /* notifyDMCUMsg */
+       REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
+}
+#endif
+
 static const struct dmcu_funcs dce_funcs = {
        .dmcu_init = dce_dmcu_init,
        .load_iram = dce_dmcu_load_iram,
@@ -953,6 +1033,10 @@ static const struct dmcu_funcs dcn10_funcs = {
        .send_edid_cea = dcn10_send_edid_cea,
        .recv_amd_vsdb = dcn10_recv_amd_vsdb,
        .recv_edid_cea_ack = dcn10_recv_edid_cea_ack,
+#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
+       .forward_crc_window = dcn10_forward_crc_window,
+       .stop_crc_win_update = dcn10_stop_crc_win_update,
+#endif
        .is_dmcu_initialized = dcn10_is_dmcu_initialized
 };
 
index cd1c0dc..8df2765 100644 (file)
@@ -56,6 +56,20 @@ struct dmcu {
        bool auto_load_dmcu;
 };
 
+#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
+struct crc_region {
+       uint16_t x_start;
+       uint16_t y_start;
+       uint16_t x_end;
+       uint16_t y_end;
+};
+
+struct otg_phy_mux {
+       uint8_t phy_output_num;
+       uint8_t otg_output_num;
+};
+#endif
+
 struct dmcu_funcs {
        bool (*dmcu_init)(struct dmcu *dmcu);
        bool (*load_iram)(struct dmcu *dmcu,
@@ -84,6 +98,13 @@ struct dmcu_funcs {
                        int *min_frame_rate,
                        int *max_frame_rate);
        bool (*recv_edid_cea_ack)(struct dmcu *dmcu, int *offset);
+#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
+       void (*forward_crc_window)(struct dmcu *dmcu,
+                       struct crc_region *crc_win,
+                       struct otg_phy_mux *mux_mapping);
+       void (*stop_crc_win_update)(struct dmcu *dmcu,
+                       struct otg_phy_mux *mux_mapping);
+#endif
 };
 
 #endif