LCOV - code coverage report
Current view: top level - drivers/gpu/drm/amd/display/dc - dc_dmub_srv.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 37 358 10.3 %
Date: 2022-12-09 01:23:36 Functions: 1 26 3.8 %

          Line data    Source code
       1             : /*
       2             :  * Copyright 2019 Advanced Micro Devices, Inc.
       3             :  *
       4             :  * Permission is hereby granted, free of charge, to any person obtaining a
       5             :  * copy of this software and associated documentation files (the "Software"),
       6             :  * to deal in the Software without restriction, including without limitation
       7             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
       8             :  * and/or sell copies of the Software, and to permit persons to whom the
       9             :  * Software is furnished to do so, subject to the following conditions:
      10             :  *
      11             :  * The above copyright notice and this permission notice shall be included in
      12             :  * all copies or substantial portions of the Software.
      13             :  *
      14             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      15             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      16             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      17             :  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
      18             :  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
      19             :  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
      20             :  * OTHER DEALINGS IN THE SOFTWARE.
      21             :  *
      22             :  * Authors: AMD
      23             :  *
      24             :  */
      25             : 
      26             : #include "dc.h"
      27             : #include "dc_dmub_srv.h"
      28             : #include "../dmub/dmub_srv.h"
      29             : #include "dm_helpers.h"
      30             : #include "dc_hw_types.h"
      31             : #include "core_types.h"
      32             : #include "../basics/conversion.h"
      33             : 
      34             : #define CTX dc_dmub_srv->ctx
      35             : #define DC_LOGGER CTX->logger
      36             : 
      37             : static void dc_dmub_srv_construct(struct dc_dmub_srv *dc_srv, struct dc *dc,
      38             :                                   struct dmub_srv *dmub)
      39             : {
      40           0 :         dc_srv->dmub = dmub;
      41           0 :         dc_srv->ctx = dc->ctx;
      42             : }
      43             : 
      44           0 : struct dc_dmub_srv *dc_dmub_srv_create(struct dc *dc, struct dmub_srv *dmub)
      45             : {
      46           0 :         struct dc_dmub_srv *dc_srv =
      47             :                 kzalloc(sizeof(struct dc_dmub_srv), GFP_KERNEL);
      48             : 
      49           0 :         if (dc_srv == NULL) {
      50           0 :                 BREAK_TO_DEBUGGER();
      51           0 :                 return NULL;
      52             :         }
      53             : 
      54           0 :         dc_dmub_srv_construct(dc_srv, dc, dmub);
      55             : 
      56           0 :         return dc_srv;
      57             : }
      58             : 
      59           0 : void dc_dmub_srv_destroy(struct dc_dmub_srv **dmub_srv)
      60             : {
      61           0 :         if (*dmub_srv) {
      62           0 :                 kfree(*dmub_srv);
      63           0 :                 *dmub_srv = NULL;
      64             :         }
      65           0 : }
      66             : 
      67           0 : void dc_dmub_srv_cmd_queue(struct dc_dmub_srv *dc_dmub_srv,
      68             :                            union dmub_rb_cmd *cmd)
      69             : {
      70           0 :         struct dmub_srv *dmub = dc_dmub_srv->dmub;
      71           0 :         struct dc_context *dc_ctx = dc_dmub_srv->ctx;
      72             :         enum dmub_status status;
      73             : 
      74           0 :         status = dmub_srv_cmd_queue(dmub, cmd);
      75           0 :         if (status == DMUB_STATUS_OK)
      76             :                 return;
      77             : 
      78           0 :         if (status != DMUB_STATUS_QUEUE_FULL)
      79             :                 goto error;
      80             : 
      81             :         /* Execute and wait for queue to become empty again. */
      82           0 :         dc_dmub_srv_cmd_execute(dc_dmub_srv);
      83           0 :         dc_dmub_srv_wait_idle(dc_dmub_srv);
      84             : 
      85             :         /* Requeue the command. */
      86           0 :         status = dmub_srv_cmd_queue(dmub, cmd);
      87           0 :         if (status == DMUB_STATUS_OK)
      88             :                 return;
      89             : 
      90             : error:
      91           0 :         DC_ERROR("Error queuing DMUB command: status=%d\n", status);
      92           0 :         dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
      93             : }
      94             : 
      95           0 : void dc_dmub_srv_cmd_execute(struct dc_dmub_srv *dc_dmub_srv)
      96             : {
      97           0 :         struct dmub_srv *dmub = dc_dmub_srv->dmub;
      98           0 :         struct dc_context *dc_ctx = dc_dmub_srv->ctx;
      99             :         enum dmub_status status;
     100             : 
     101           0 :         status = dmub_srv_cmd_execute(dmub);
     102           0 :         if (status != DMUB_STATUS_OK) {
     103           0 :                 DC_ERROR("Error starting DMUB execution: status=%d\n", status);
     104           0 :                 dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
     105             :         }
     106           0 : }
     107             : 
     108           0 : void dc_dmub_srv_wait_idle(struct dc_dmub_srv *dc_dmub_srv)
     109             : {
     110           0 :         struct dmub_srv *dmub = dc_dmub_srv->dmub;
     111           0 :         struct dc_context *dc_ctx = dc_dmub_srv->ctx;
     112             :         enum dmub_status status;
     113             : 
     114           0 :         status = dmub_srv_wait_for_idle(dmub, 100000);
     115           0 :         if (status != DMUB_STATUS_OK) {
     116           0 :                 DC_ERROR("Error waiting for DMUB idle: status=%d\n", status);
     117           0 :                 dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
     118             :         }
     119           0 : }
     120             : 
     121           0 : void dc_dmub_srv_clear_inbox0_ack(struct dc_dmub_srv *dmub_srv)
     122             : {
     123           0 :         struct dmub_srv *dmub = dmub_srv->dmub;
     124           0 :         struct dc_context *dc_ctx = dmub_srv->ctx;
     125           0 :         enum dmub_status status = DMUB_STATUS_OK;
     126             : 
     127           0 :         status = dmub_srv_clear_inbox0_ack(dmub);
     128           0 :         if (status != DMUB_STATUS_OK) {
     129           0 :                 DC_ERROR("Error clearing INBOX0 ack: status=%d\n", status);
     130           0 :                 dc_dmub_srv_log_diagnostic_data(dmub_srv);
     131             :         }
     132           0 : }
     133             : 
     134           0 : void dc_dmub_srv_wait_for_inbox0_ack(struct dc_dmub_srv *dmub_srv)
     135             : {
     136           0 :         struct dmub_srv *dmub = dmub_srv->dmub;
     137           0 :         struct dc_context *dc_ctx = dmub_srv->ctx;
     138           0 :         enum dmub_status status = DMUB_STATUS_OK;
     139             : 
     140           0 :         status = dmub_srv_wait_for_inbox0_ack(dmub, 100000);
     141           0 :         if (status != DMUB_STATUS_OK) {
     142           0 :                 DC_ERROR("Error waiting for INBOX0 HW Lock Ack\n");
     143           0 :                 dc_dmub_srv_log_diagnostic_data(dmub_srv);
     144             :         }
     145           0 : }
     146             : 
     147           0 : void dc_dmub_srv_send_inbox0_cmd(struct dc_dmub_srv *dmub_srv,
     148             :                 union dmub_inbox0_data_register data)
     149             : {
     150           0 :         struct dmub_srv *dmub = dmub_srv->dmub;
     151           0 :         struct dc_context *dc_ctx = dmub_srv->ctx;
     152           0 :         enum dmub_status status = DMUB_STATUS_OK;
     153             : 
     154           0 :         status = dmub_srv_send_inbox0_cmd(dmub, data);
     155           0 :         if (status != DMUB_STATUS_OK) {
     156           0 :                 DC_ERROR("Error sending INBOX0 cmd\n");
     157           0 :                 dc_dmub_srv_log_diagnostic_data(dmub_srv);
     158             :         }
     159           0 : }
     160             : 
     161           0 : bool dc_dmub_srv_cmd_with_reply_data(struct dc_dmub_srv *dc_dmub_srv, union dmub_rb_cmd *cmd)
     162             : {
     163             :         struct dmub_srv *dmub;
     164             :         enum dmub_status status;
     165             : 
     166           0 :         if (!dc_dmub_srv || !dc_dmub_srv->dmub)
     167             :                 return false;
     168             : 
     169           0 :         dmub = dc_dmub_srv->dmub;
     170             : 
     171           0 :         status = dmub_srv_cmd_with_reply_data(dmub, cmd);
     172           0 :         if (status != DMUB_STATUS_OK) {
     173           0 :                 DC_LOG_DEBUG("No reply for DMUB command: status=%d\n", status);
     174           0 :                 return false;
     175             :         }
     176             : 
     177             :         return true;
     178             : }
     179             : 
     180           0 : void dc_dmub_srv_wait_phy_init(struct dc_dmub_srv *dc_dmub_srv)
     181             : {
     182           0 :         struct dmub_srv *dmub = dc_dmub_srv->dmub;
     183           0 :         struct dc_context *dc_ctx = dc_dmub_srv->ctx;
     184             :         enum dmub_status status;
     185             : 
     186             :         for (;;) {
     187             :                 /* Wait up to a second for PHY init. */
     188           0 :                 status = dmub_srv_wait_for_phy_init(dmub, 1000000);
     189           0 :                 if (status == DMUB_STATUS_OK)
     190             :                         /* Initialization OK */
     191             :                         break;
     192             : 
     193           0 :                 DC_ERROR("DMCUB PHY init failed: status=%d\n", status);
     194           0 :                 ASSERT(0);
     195             : 
     196           0 :                 if (status != DMUB_STATUS_TIMEOUT)
     197             :                         /*
     198             :                          * Server likely initialized or we don't have
     199             :                          * DMCUB HW support - this won't end.
     200             :                          */
     201             :                         break;
     202             : 
     203             :                 /* Continue spinning so we don't hang the ASIC. */
     204             :         }
     205           0 : }
     206             : 
     207           0 : bool dc_dmub_srv_notify_stream_mask(struct dc_dmub_srv *dc_dmub_srv,
     208             :                                     unsigned int stream_mask)
     209             : {
     210             :         struct dmub_srv *dmub;
     211           0 :         const uint32_t timeout = 30;
     212             : 
     213           0 :         if (!dc_dmub_srv || !dc_dmub_srv->dmub)
     214             :                 return false;
     215             : 
     216           0 :         dmub = dc_dmub_srv->dmub;
     217             : 
     218           0 :         return dmub_srv_send_gpint_command(
     219             :                        dmub, DMUB_GPINT__IDLE_OPT_NOTIFY_STREAM_MASK,
     220           0 :                        stream_mask, timeout) == DMUB_STATUS_OK;
     221             : }
     222             : 
     223           0 : bool dc_dmub_srv_is_restore_required(struct dc_dmub_srv *dc_dmub_srv)
     224             : {
     225             :         struct dmub_srv *dmub;
     226             :         struct dc_context *dc_ctx;
     227             :         union dmub_fw_boot_status boot_status;
     228             :         enum dmub_status status;
     229             : 
     230           0 :         if (!dc_dmub_srv || !dc_dmub_srv->dmub)
     231             :                 return false;
     232             : 
     233           0 :         dmub = dc_dmub_srv->dmub;
     234           0 :         dc_ctx = dc_dmub_srv->ctx;
     235             : 
     236           0 :         status = dmub_srv_get_fw_boot_status(dmub, &boot_status);
     237           0 :         if (status != DMUB_STATUS_OK) {
     238           0 :                 DC_ERROR("Error querying DMUB boot status: error=%d\n", status);
     239           0 :                 return false;
     240             :         }
     241             : 
     242           0 :         return boot_status.bits.restore_required;
     243             : }
     244             : 
     245           0 : bool dc_dmub_srv_get_dmub_outbox0_msg(const struct dc *dc, struct dmcub_trace_buf_entry *entry)
     246             : {
     247           0 :         struct dmub_srv *dmub = dc->ctx->dmub_srv->dmub;
     248           0 :         return dmub_srv_get_outbox0_msg(dmub, entry);
     249             : }
     250             : 
     251           0 : void dc_dmub_trace_event_control(struct dc *dc, bool enable)
     252             : {
     253           0 :         dm_helpers_dmub_outbox_interrupt_control(dc->ctx, enable);
     254           0 : }
     255             : 
     256           0 : void dc_dmub_srv_drr_update_cmd(struct dc *dc, uint32_t tg_inst, uint32_t vtotal_min, uint32_t vtotal_max)
     257             : {
     258           0 :         union dmub_rb_cmd cmd = { 0 };
     259             : 
     260           0 :         cmd.drr_update.header.type = DMUB_CMD__FW_ASSISTED_MCLK_SWITCH;
     261           0 :         cmd.drr_update.header.sub_type = DMUB_CMD__FAMS_DRR_UPDATE;
     262           0 :         cmd.drr_update.dmub_optc_state_req.v_total_max = vtotal_max;
     263           0 :         cmd.drr_update.dmub_optc_state_req.v_total_min = vtotal_min;
     264           0 :         cmd.drr_update.dmub_optc_state_req.tg_inst = tg_inst;
     265             : 
     266           0 :         cmd.drr_update.header.payload_bytes = sizeof(cmd.drr_update) - sizeof(cmd.drr_update.header);
     267             : 
     268             :         // Send the command to the DMCUB.
     269           0 :         dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
     270           0 :         dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
     271           0 :         dc_dmub_srv_wait_idle(dc->ctx->dmub_srv);
     272           0 : }
     273             : 
     274           0 : void dc_dmub_srv_set_drr_manual_trigger_cmd(struct dc *dc, uint32_t tg_inst)
     275             : {
     276           0 :         union dmub_rb_cmd cmd = { 0 };
     277             : 
     278           0 :         cmd.drr_update.header.type = DMUB_CMD__FW_ASSISTED_MCLK_SWITCH;
     279           0 :         cmd.drr_update.header.sub_type = DMUB_CMD__FAMS_SET_MANUAL_TRIGGER;
     280           0 :         cmd.drr_update.dmub_optc_state_req.tg_inst = tg_inst;
     281             : 
     282           0 :         cmd.drr_update.header.payload_bytes = sizeof(cmd.drr_update) - sizeof(cmd.drr_update.header);
     283             : 
     284             :         // Send the command to the DMCUB.
     285           0 :         dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
     286           0 :         dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
     287           0 :         dc_dmub_srv_wait_idle(dc->ctx->dmub_srv);
     288           0 : }
     289             : 
     290             : static uint8_t dc_dmub_srv_get_pipes_for_stream(struct dc *dc, struct dc_stream_state *stream)
     291             : {
     292             :         uint8_t pipes = 0;
     293             :         int i = 0;
     294             : 
     295           0 :         for (i = 0; i < MAX_PIPES; i++) {
     296           0 :                 struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
     297             : 
     298           0 :                 if (pipe->stream == stream && pipe->stream_res.tg)
     299           0 :                         pipes = i;
     300             :         }
     301             :         return pipes;
     302             : }
     303             : 
     304             : static int dc_dmub_srv_get_timing_generator_offset(struct dc *dc, struct dc_stream_state *stream)
     305             : {
     306             :         int  tg_inst = 0;
     307             :         int i = 0;
     308             : 
     309           0 :         for (i = 0; i < MAX_PIPES; i++) {
     310           0 :                 struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
     311             : 
     312           0 :                 if (pipe->stream == stream && pipe->stream_res.tg) {
     313           0 :                         tg_inst = pipe->stream_res.tg->inst;
     314             :                         break;
     315             :                 }
     316             :         }
     317             :         return tg_inst;
     318             : }
     319             : 
     320           0 : bool dc_dmub_srv_p_state_delegate(struct dc *dc, bool should_manage_pstate, struct dc_state *context)
     321             : {
     322           0 :         union dmub_rb_cmd cmd = { 0 };
     323           0 :         struct dmub_cmd_fw_assisted_mclk_switch_config *config_data = &cmd.fw_assisted_mclk_switch.config_data;
     324           0 :         int i = 0;
     325           0 :         int ramp_up_num_steps = 1; // TODO: Ramp is currently disabled. Reenable it.
     326             :         uint8_t visual_confirm_enabled;
     327             : 
     328           0 :         if (dc == NULL)
     329             :                 return false;
     330             : 
     331           0 :         visual_confirm_enabled = dc->debug.visual_confirm == VISUAL_CONFIRM_FAMS;
     332             : 
     333             :         // Format command.
     334           0 :         cmd.fw_assisted_mclk_switch.header.type = DMUB_CMD__FW_ASSISTED_MCLK_SWITCH;
     335             :         cmd.fw_assisted_mclk_switch.header.sub_type = DMUB_CMD__FAMS_SETUP_FW_CTRL;
     336           0 :         cmd.fw_assisted_mclk_switch.config_data.fams_enabled = should_manage_pstate;
     337           0 :         cmd.fw_assisted_mclk_switch.config_data.visual_confirm_enabled = visual_confirm_enabled;
     338             : 
     339           0 :         for (i = 0; context && i < context->stream_count; i++) {
     340           0 :                 struct dc_stream_state *stream = context->streams[i];
     341           0 :                 uint8_t min_refresh_in_hz = (stream->timing.min_refresh_in_uhz + 999999) / 1000000;
     342           0 :                 int  tg_inst = dc_dmub_srv_get_timing_generator_offset(dc, stream);
     343             : 
     344           0 :                 config_data->pipe_data[tg_inst].pix_clk_100hz = stream->timing.pix_clk_100hz;
     345           0 :                 config_data->pipe_data[tg_inst].min_refresh_in_hz = min_refresh_in_hz;
     346           0 :                 config_data->pipe_data[tg_inst].max_ramp_step = ramp_up_num_steps;
     347           0 :                 config_data->pipe_data[tg_inst].pipes = dc_dmub_srv_get_pipes_for_stream(dc, stream);
     348             :         }
     349             : 
     350           0 :         cmd.fw_assisted_mclk_switch.header.payload_bytes =
     351             :                 sizeof(cmd.fw_assisted_mclk_switch) - sizeof(cmd.fw_assisted_mclk_switch.header);
     352             : 
     353             :         // Send the command to the DMCUB.
     354           0 :         dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
     355           0 :         dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
     356           0 :         dc_dmub_srv_wait_idle(dc->ctx->dmub_srv);
     357             : 
     358           0 :         return true;
     359             : }
     360             : 
     361           0 : void dc_dmub_srv_query_caps_cmd(struct dmub_srv *dmub)
     362             : {
     363           0 :         union dmub_rb_cmd cmd = { 0 };
     364             :         enum dmub_status status;
     365             : 
     366           0 :         if (!dmub) {
     367           0 :                 return;
     368             :         }
     369             : 
     370           0 :         memset(&cmd, 0, sizeof(cmd));
     371             : 
     372             :         /* Prepare fw command */
     373           0 :         cmd.query_feature_caps.header.type = DMUB_CMD__QUERY_FEATURE_CAPS;
     374           0 :         cmd.query_feature_caps.header.sub_type = 0;
     375           0 :         cmd.query_feature_caps.header.ret_status = 1;
     376           0 :         cmd.query_feature_caps.header.payload_bytes = sizeof(struct dmub_cmd_query_feature_caps_data);
     377             : 
     378             :         /* Send command to fw */
     379           0 :         status = dmub_srv_cmd_with_reply_data(dmub, &cmd);
     380             : 
     381           0 :         ASSERT(status == DMUB_STATUS_OK);
     382             : 
     383             :         /* If command was processed, copy feature caps to dmub srv */
     384           0 :         if (status == DMUB_STATUS_OK &&
     385           0 :             cmd.query_feature_caps.header.ret_status == 0) {
     386           0 :                 memcpy(&dmub->feature_caps,
     387             :                        &cmd.query_feature_caps.query_feature_caps_data,
     388             :                        sizeof(struct dmub_feature_caps));
     389             :         }
     390             : }
     391             : 
     392           0 : void dc_dmub_srv_get_visual_confirm_color_cmd(struct dc *dc, struct pipe_ctx *pipe_ctx)
     393             : {
     394           0 :         union dmub_rb_cmd cmd = { 0 };
     395             :         enum dmub_status status;
     396           0 :         unsigned int panel_inst = 0;
     397             : 
     398           0 :         dc_get_edp_link_panel_inst(dc, pipe_ctx->stream->link, &panel_inst);
     399             : 
     400           0 :         memset(&cmd, 0, sizeof(cmd));
     401             : 
     402             :         // Prepare fw command
     403           0 :         cmd.visual_confirm_color.header.type = DMUB_CMD__GET_VISUAL_CONFIRM_COLOR;
     404           0 :         cmd.visual_confirm_color.header.sub_type = 0;
     405           0 :         cmd.visual_confirm_color.header.ret_status = 1;
     406           0 :         cmd.visual_confirm_color.header.payload_bytes = sizeof(struct dmub_cmd_visual_confirm_color_data);
     407           0 :         cmd.visual_confirm_color.visual_confirm_color_data.visual_confirm_color.panel_inst = panel_inst;
     408             : 
     409             :         // Send command to fw
     410           0 :         status = dmub_srv_cmd_with_reply_data(dc->ctx->dmub_srv->dmub, &cmd);
     411             : 
     412           0 :         ASSERT(status == DMUB_STATUS_OK);
     413             : 
     414             :         // If command was processed, copy feature caps to dmub srv
     415           0 :         if (status == DMUB_STATUS_OK &&
     416           0 :                 cmd.visual_confirm_color.header.ret_status == 0) {
     417           0 :                 memcpy(&dc->ctx->dmub_srv->dmub->visual_confirm_color,
     418             :                         &cmd.visual_confirm_color.visual_confirm_color_data,
     419             :                         sizeof(struct dmub_visual_confirm_color));
     420             :         }
     421           0 : }
     422             : 
     423             : #ifdef CONFIG_DRM_AMD_DC_DCN
     424             : /**
     425             :  * ***********************************************************************************************
     426             :  * populate_subvp_cmd_drr_info: Helper to populate DRR pipe info for the DMCUB subvp command
     427             :  *
     428             :  * Populate the DMCUB SubVP command with DRR pipe info. All the information required for calculating
     429             :  * the SubVP + DRR microschedule is populated here.
     430             :  *
     431             :  * High level algorithm:
     432             :  * 1. Get timing for SubVP pipe, phantom pipe, and DRR pipe
     433             :  * 2. Calculate the min and max vtotal which supports SubVP + DRR microschedule
     434             :  * 3. Populate the drr_info with the min and max supported vtotal values
     435             :  *
     436             :  * @param [in] dc: current dc state
     437             :  * @param [in] subvp_pipe: pipe_ctx for the SubVP pipe
     438             :  * @param [in] vblank_pipe: pipe_ctx for the DRR pipe
     439             :  * @param [in] pipe_data: Pipe data which stores the VBLANK/DRR info
     440             :  *
     441             :  * @return: void
     442             :  *
     443             :  * ***********************************************************************************************
     444             :  */
     445           5 : static void populate_subvp_cmd_drr_info(struct dc *dc,
     446             :                 struct pipe_ctx *subvp_pipe,
     447             :                 struct pipe_ctx *vblank_pipe,
     448             :                 struct dmub_cmd_fw_assisted_mclk_switch_pipe_data_v2 *pipe_data)
     449             : {
     450           5 :         struct dc_crtc_timing *main_timing = &subvp_pipe->stream->timing;
     451           5 :         struct dc_crtc_timing *phantom_timing = &subvp_pipe->stream->mall_stream_config.paired_stream->timing;
     452           5 :         struct dc_crtc_timing *drr_timing = &vblank_pipe->stream->timing;
     453           5 :         int16_t drr_frame_us = 0;
     454           5 :         int16_t min_drr_supported_us = 0;
     455           5 :         int16_t max_drr_supported_us = 0;
     456           5 :         int16_t max_drr_vblank_us = 0;
     457           5 :         int16_t max_drr_mallregion_us = 0;
     458           5 :         int16_t mall_region_us = 0;
     459           5 :         int16_t prefetch_us = 0;
     460           5 :         int16_t subvp_active_us = 0;
     461           5 :         int16_t drr_active_us = 0;
     462           5 :         int16_t min_vtotal_supported = 0;
     463           5 :         int16_t max_vtotal_supported = 0;
     464             : 
     465           5 :         pipe_data->pipe_config.vblank_data.drr_info.drr_in_use = true;
     466           5 :         pipe_data->pipe_config.vblank_data.drr_info.use_ramping = false; // for now don't use ramping
     467           5 :         pipe_data->pipe_config.vblank_data.drr_info.drr_window_size_ms = 4; // hardcode 4ms DRR window for now
     468             : 
     469          10 :         drr_frame_us = div64_s64(drr_timing->v_total * drr_timing->h_total,
     470           5 :                                  (int64_t)(drr_timing->pix_clk_100hz * 100) * 1000000);
     471             :         // P-State allow width and FW delays already included phantom_timing->v_addressable
     472          10 :         mall_region_us = div64_s64(phantom_timing->v_addressable * phantom_timing->h_total,
     473           5 :                                    (int64_t)(phantom_timing->pix_clk_100hz * 100) * 1000000);
     474           5 :         min_drr_supported_us = drr_frame_us + mall_region_us + SUBVP_DRR_MARGIN_US;
     475          15 :         min_vtotal_supported = div64_s64(drr_timing->pix_clk_100hz * 100 *
     476          10 :                                          (div64_s64((int64_t)min_drr_supported_us, 1000000)),
     477             :                                          (int64_t)drr_timing->h_total);
     478             : 
     479          10 :         prefetch_us = div64_s64((phantom_timing->v_total - phantom_timing->v_front_porch) * phantom_timing->h_total,
     480             :                                 (int64_t)(phantom_timing->pix_clk_100hz * 100) * 1000000 +
     481           5 :                                 dc->caps.subvp_prefetch_end_to_mall_start_us);
     482          10 :         subvp_active_us = div64_s64(main_timing->v_addressable * main_timing->h_total,
     483           5 :                                     (int64_t)(main_timing->pix_clk_100hz * 100) * 1000000);
     484          10 :         drr_active_us = div64_s64(drr_timing->v_addressable * drr_timing->h_total,
     485             :                                   (int64_t)(drr_timing->pix_clk_100hz * 100) * 1000000);
     486          10 :         max_drr_vblank_us = div64_s64((int64_t)(subvp_active_us - prefetch_us - drr_active_us), 2) + drr_active_us;
     487           5 :         max_drr_mallregion_us = subvp_active_us - prefetch_us - mall_region_us;
     488           5 :         max_drr_supported_us = max_drr_vblank_us > max_drr_mallregion_us ? max_drr_vblank_us : max_drr_mallregion_us;
     489          15 :         max_vtotal_supported = div64_s64(drr_timing->pix_clk_100hz * 100 * (div64_s64((int64_t)max_drr_supported_us, 1000000)),
     490             :                                          (int64_t)drr_timing->h_total);
     491             : 
     492           5 :         pipe_data->pipe_config.vblank_data.drr_info.min_vtotal_supported = min_vtotal_supported;
     493           5 :         pipe_data->pipe_config.vblank_data.drr_info.max_vtotal_supported = max_vtotal_supported;
     494           5 : }
     495             : 
     496             : /**
     497             :  * ***********************************************************************************************
     498             :  * populate_subvp_cmd_vblank_pipe_info: Helper to populate VBLANK pipe info for the DMUB subvp command
     499             :  *
     500             :  * Populate the DMCUB SubVP command with VBLANK pipe info. All the information required to calculate
     501             :  * the microschedule for SubVP + VBLANK case is stored in the pipe_data (subvp_data and vblank_data).
     502             :  * Also check if the VBLANK pipe is a DRR display -- if it is make a call to populate drr_info.
     503             :  *
     504             :  * @param [in] dc: current dc state
     505             :  * @param [in] context: new dc state
     506             :  * @param [in] cmd: DMUB cmd to be populated with SubVP info
     507             :  * @param [in] vblank_pipe: pipe_ctx for the VBLANK pipe
     508             :  * @param [in] cmd_pipe_index: index for the pipe array in DMCUB SubVP cmd
     509             :  *
     510             :  * @return: void
     511             :  *
     512             :  * ***********************************************************************************************
     513             :  */
     514           0 : static void populate_subvp_cmd_vblank_pipe_info(struct dc *dc,
     515             :                 struct dc_state *context,
     516             :                 union dmub_rb_cmd *cmd,
     517             :                 struct pipe_ctx *vblank_pipe,
     518             :                 uint8_t cmd_pipe_index)
     519             : {
     520             :         uint32_t i;
     521           0 :         struct pipe_ctx *pipe = NULL;
     522           0 :         struct dmub_cmd_fw_assisted_mclk_switch_pipe_data_v2 *pipe_data =
     523           0 :                         &cmd->fw_assisted_mclk_switch_v2.config_data.pipe_data[cmd_pipe_index];
     524             : 
     525             :         // Find the SubVP pipe
     526           0 :         for (i = 0; i < dc->res_pool->pipe_count; i++) {
     527           0 :                 pipe = &context->res_ctx.pipe_ctx[i];
     528             : 
     529             :                 // We check for master pipe, but it shouldn't matter since we only need
     530             :                 // the pipe for timing info (stream should be same for any pipe splits)
     531           0 :                 if (!pipe->stream || !pipe->plane_state || pipe->top_pipe || pipe->prev_odm_pipe)
     532           0 :                         continue;
     533             : 
     534             :                 // Find the SubVP pipe
     535           0 :                 if (pipe->stream->mall_stream_config.type == SUBVP_MAIN)
     536             :                         break;
     537             :         }
     538             : 
     539           0 :         pipe_data->mode = VBLANK;
     540           0 :         pipe_data->pipe_config.vblank_data.pix_clk_100hz = vblank_pipe->stream->timing.pix_clk_100hz;
     541           0 :         pipe_data->pipe_config.vblank_data.vblank_start = vblank_pipe->stream->timing.v_total -
     542           0 :                                                         vblank_pipe->stream->timing.v_front_porch;
     543           0 :         pipe_data->pipe_config.vblank_data.vtotal = vblank_pipe->stream->timing.v_total;
     544           0 :         pipe_data->pipe_config.vblank_data.htotal = vblank_pipe->stream->timing.h_total;
     545           0 :         pipe_data->pipe_config.vblank_data.vblank_pipe_index = vblank_pipe->pipe_idx;
     546           0 :         pipe_data->pipe_config.vblank_data.vstartup_start = vblank_pipe->pipe_dlg_param.vstartup_start;
     547           0 :         pipe_data->pipe_config.vblank_data.vblank_end =
     548           0 :                         vblank_pipe->stream->timing.v_total - vblank_pipe->stream->timing.v_front_porch - vblank_pipe->stream->timing.v_addressable;
     549             : 
     550           0 :         if (vblank_pipe->stream->ignore_msa_timing_param)
     551           0 :                 populate_subvp_cmd_drr_info(dc, pipe, vblank_pipe, pipe_data);
     552           0 : }
     553             : 
     554             : /**
     555             :  * ***********************************************************************************************
     556             :  * update_subvp_prefetch_end_to_mall_start: Helper for SubVP + SubVP case
     557             :  *
     558             :  * For SubVP + SubVP, we use a single vertical interrupt to start the microschedule for both
     559             :  * SubVP pipes. In order for this to work correctly, the MALL REGION of both SubVP pipes must
     560             :  * start at the same time. This function lengthens the prefetch end to mall start delay of the
     561             :  * SubVP pipe that has the shorter prefetch so that both MALL REGION's will start at the same time.
     562             :  *
     563             :  * @param [in] dc: current dc state
     564             :  * @param [in] context: new dc state
     565             :  * @param [in] cmd: DMUB cmd to be populated with SubVP info
     566             :  * @param [in] subvp_pipes: Array of SubVP pipes (should always be length 2)
     567             :  *
     568             :  * @return: void
     569             :  *
     570             :  * ***********************************************************************************************
     571             :  */
     572           0 : static void update_subvp_prefetch_end_to_mall_start(struct dc *dc,
     573             :                 struct dc_state *context,
     574             :                 union dmub_rb_cmd *cmd,
     575             :                 struct pipe_ctx *subvp_pipes[])
     576             : {
     577           0 :         uint32_t subvp0_prefetch_us = 0;
     578           0 :         uint32_t subvp1_prefetch_us = 0;
     579           0 :         uint32_t prefetch_delta_us = 0;
     580           0 :         struct dc_crtc_timing *phantom_timing0 = &subvp_pipes[0]->stream->mall_stream_config.paired_stream->timing;
     581           0 :         struct dc_crtc_timing *phantom_timing1 = &subvp_pipes[1]->stream->mall_stream_config.paired_stream->timing;
     582           0 :         struct dmub_cmd_fw_assisted_mclk_switch_pipe_data_v2 *pipe_data = NULL;
     583             : 
     584           0 :         subvp0_prefetch_us = div64_s64((phantom_timing0->v_total - phantom_timing0->v_front_porch) * phantom_timing0->h_total,
     585           0 :                                        (int64_t)(phantom_timing0->pix_clk_100hz * 100) * 1000000 + dc->caps.subvp_prefetch_end_to_mall_start_us);
     586           0 :         subvp1_prefetch_us = div64_s64((phantom_timing1->v_total - phantom_timing1->v_front_porch) * phantom_timing1->h_total,
     587           0 :                                        (int64_t)(phantom_timing1->pix_clk_100hz * 100) * 1000000 + dc->caps.subvp_prefetch_end_to_mall_start_us);
     588             : 
     589             :         // Whichever SubVP PIPE has the smaller prefetch (including the prefetch end to mall start time)
     590             :         // should increase it's prefetch time to match the other
     591           0 :         if (subvp0_prefetch_us > subvp1_prefetch_us) {
     592           0 :                 pipe_data = &cmd->fw_assisted_mclk_switch_v2.config_data.pipe_data[1];
     593           0 :                 prefetch_delta_us = subvp0_prefetch_us - subvp1_prefetch_us;
     594           0 :                 pipe_data->pipe_config.subvp_data.prefetch_to_mall_start_lines =
     595           0 :                         div64_s64(((div64_s64((int64_t)(dc->caps.subvp_prefetch_end_to_mall_start_us + prefetch_delta_us), 1000000)) *
     596           0 :                                    (phantom_timing1->pix_clk_100hz * 100) + phantom_timing1->h_total - 1),
     597             :                                   (int64_t)phantom_timing1->h_total);
     598           0 :         } else if (subvp1_prefetch_us >  subvp0_prefetch_us) {
     599           0 :                 pipe_data = &cmd->fw_assisted_mclk_switch_v2.config_data.pipe_data[0];
     600           0 :                 prefetch_delta_us = subvp1_prefetch_us - subvp0_prefetch_us;
     601           0 :                 pipe_data->pipe_config.subvp_data.prefetch_to_mall_start_lines =
     602           0 :                         div64_s64(((div64_s64((int64_t)(dc->caps.subvp_prefetch_end_to_mall_start_us + prefetch_delta_us), 1000000)) *
     603           0 :                                    (phantom_timing0->pix_clk_100hz * 100) + phantom_timing0->h_total - 1),
     604             :                                   (int64_t)phantom_timing0->h_total);
     605             :         }
     606           0 : }
     607             : 
     608             : /**
     609             :  * ***************************************************************************************
     610             :  * setup_subvp_dmub_command: Helper to populate the SubVP pipe info for the DMUB subvp command
     611             :  *
     612             :  * Populate the DMCUB SubVP command with SubVP pipe info. All the information required to
     613             :  * calculate the microschedule for the SubVP pipe is stored in the pipe_data of the DMCUB
     614             :  * SubVP command.
     615             :  *
     616             :  * @param [in] dc: current dc state
     617             :  * @param [in] context: new dc state
     618             :  * @param [in] cmd: DMUB cmd to be populated with SubVP info
     619             :  * @param [in] subvp_pipe: pipe_ctx for the SubVP pipe
     620             :  * @param [in] cmd_pipe_index: index for the pipe array in DMCUB SubVP cmd
     621             :  *
     622             :  * @return: void
     623             :  *
     624             :  * ***************************************************************************************
     625             :  */
     626           0 : static void populate_subvp_cmd_pipe_info(struct dc *dc,
     627             :                 struct dc_state *context,
     628             :                 union dmub_rb_cmd *cmd,
     629             :                 struct pipe_ctx *subvp_pipe,
     630             :                 uint8_t cmd_pipe_index)
     631             : {
     632             :         uint32_t j;
     633           0 :         struct dmub_cmd_fw_assisted_mclk_switch_pipe_data_v2 *pipe_data =
     634           0 :                         &cmd->fw_assisted_mclk_switch_v2.config_data.pipe_data[cmd_pipe_index];
     635           0 :         struct dc_crtc_timing *main_timing = &subvp_pipe->stream->timing;
     636           0 :         struct dc_crtc_timing *phantom_timing = &subvp_pipe->stream->mall_stream_config.paired_stream->timing;
     637             :         uint32_t out_num_stream, out_den_stream, out_num_plane, out_den_plane, out_num, out_den;
     638             : 
     639           0 :         pipe_data->mode = SUBVP;
     640           0 :         pipe_data->pipe_config.subvp_data.pix_clk_100hz = subvp_pipe->stream->timing.pix_clk_100hz;
     641           0 :         pipe_data->pipe_config.subvp_data.htotal = subvp_pipe->stream->timing.h_total;
     642           0 :         pipe_data->pipe_config.subvp_data.vtotal = subvp_pipe->stream->timing.v_total;
     643           0 :         pipe_data->pipe_config.subvp_data.main_vblank_start =
     644           0 :                         main_timing->v_total - main_timing->v_front_porch;
     645           0 :         pipe_data->pipe_config.subvp_data.main_vblank_end =
     646           0 :                         main_timing->v_total - main_timing->v_front_porch - main_timing->v_addressable;
     647           0 :         pipe_data->pipe_config.subvp_data.mall_region_lines = phantom_timing->v_addressable;
     648           0 :         pipe_data->pipe_config.subvp_data.main_pipe_index = subvp_pipe->pipe_idx;
     649           0 :         pipe_data->pipe_config.subvp_data.is_drr = subvp_pipe->stream->ignore_msa_timing_param;
     650             : 
     651             :         /* Calculate the scaling factor from the src and dst height.
     652             :          * e.g. If 3840x2160 being downscaled to 1920x1080, the scaling factor is 1/2.
     653             :          * Reduce the fraction 1080/2160 = 1/2 for the "scaling factor"
     654             :          *
     655             :          * Make sure to combine stream and plane scaling together.
     656             :          */
     657           0 :         reduce_fraction(subvp_pipe->stream->src.height, subvp_pipe->stream->dst.height,
     658             :                         &out_num_stream, &out_den_stream);
     659           0 :         reduce_fraction(subvp_pipe->plane_state->src_rect.height, subvp_pipe->plane_state->dst_rect.height,
     660             :                         &out_num_plane, &out_den_plane);
     661           0 :         reduce_fraction(out_num_stream * out_num_plane, out_den_stream * out_den_plane, &out_num, &out_den);
     662           0 :         pipe_data->pipe_config.subvp_data.scale_factor_numerator = out_num;
     663           0 :         pipe_data->pipe_config.subvp_data.scale_factor_denominator = out_den;
     664             : 
     665             :         // Prefetch lines is equal to VACTIVE + BP + VSYNC
     666           0 :         pipe_data->pipe_config.subvp_data.prefetch_lines =
     667           0 :                         phantom_timing->v_total - phantom_timing->v_front_porch;
     668             : 
     669             :         // Round up
     670           0 :         pipe_data->pipe_config.subvp_data.prefetch_to_mall_start_lines =
     671           0 :                 div64_s64(((div64_s64((int64_t)dc->caps.subvp_prefetch_end_to_mall_start_us, 1000000)) *
     672           0 :                            (phantom_timing->pix_clk_100hz * 100) + phantom_timing->h_total - 1),
     673           0 :                           (int64_t)phantom_timing->h_total);
     674           0 :         pipe_data->pipe_config.subvp_data.processing_delay_lines =
     675           0 :                 div64_s64(((div64_s64((int64_t)dc->caps.subvp_fw_processing_delay_us, 1000000)) *
     676           0 :                            (phantom_timing->pix_clk_100hz * 100) + phantom_timing->h_total - 1),
     677           0 :                           (int64_t)phantom_timing->h_total);
     678             :         // Find phantom pipe index based on phantom stream
     679           0 :         for (j = 0; j < dc->res_pool->pipe_count; j++) {
     680           0 :                 struct pipe_ctx *phantom_pipe = &context->res_ctx.pipe_ctx[j];
     681             : 
     682           0 :                 if (phantom_pipe->stream == subvp_pipe->stream->mall_stream_config.paired_stream) {
     683           0 :                         pipe_data->pipe_config.subvp_data.phantom_pipe_index = phantom_pipe->pipe_idx;
     684           0 :                         break;
     685             :                 }
     686             :         }
     687           0 : }
     688             : 
     689             : /**
     690             :  * ***************************************************************************************
     691             :  * dc_dmub_setup_subvp_dmub_command: Populate the DMCUB SubVP command
     692             :  *
     693             :  * This function loops through each pipe and populates the DMUB
     694             :  * SubVP CMD info based on the pipe (e.g. SubVP, VBLANK).
     695             :  *
     696             :  * @param [in] dc: current dc state
     697             :  * @param [in] context: new dc state
     698             :  * @param [in] cmd: DMUB cmd to be populated with SubVP info
     699             :  *
     700             :  * @return: void
     701             :  *
     702             :  * ***************************************************************************************
     703             :  */
     704           0 : void dc_dmub_setup_subvp_dmub_command(struct dc *dc,
     705             :                 struct dc_state *context,
     706             :                 bool enable)
     707             : {
     708           0 :         uint8_t cmd_pipe_index = 0;
     709             :         uint32_t i, pipe_idx;
     710           0 :         uint8_t subvp_count = 0;
     711             :         union dmub_rb_cmd cmd;
     712             :         struct pipe_ctx *subvp_pipes[2];
     713           0 :         uint32_t wm_val_refclk = 0;
     714             : 
     715           0 :         memset(&cmd, 0, sizeof(cmd));
     716             :         // FW command for SUBVP
     717           0 :         cmd.fw_assisted_mclk_switch_v2.header.type = DMUB_CMD__FW_ASSISTED_MCLK_SWITCH;
     718           0 :         cmd.fw_assisted_mclk_switch_v2.header.sub_type = DMUB_CMD__HANDLE_SUBVP_CMD;
     719           0 :         cmd.fw_assisted_mclk_switch_v2.header.payload_bytes =
     720             :                         sizeof(cmd.fw_assisted_mclk_switch_v2) - sizeof(cmd.fw_assisted_mclk_switch_v2.header);
     721             : 
     722           0 :         for (i = 0; i < dc->res_pool->pipe_count; i++) {
     723           0 :                 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
     724             : 
     725           0 :                 if (!pipe->stream)
     726           0 :                         continue;
     727             : 
     728           0 :                 if (pipe->plane_state && !pipe->top_pipe &&
     729           0 :                                 pipe->stream->mall_stream_config.type == SUBVP_MAIN)
     730           0 :                         subvp_pipes[subvp_count++] = pipe;
     731             :         }
     732             : 
     733           0 :         if (enable) {
     734             :                 // For each pipe that is a "main" SUBVP pipe, fill in pipe data for DMUB SUBVP cmd
     735           0 :                 for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
     736           0 :                         struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
     737             : 
     738           0 :                         if (!pipe->stream)
     739           0 :                                 continue;
     740             : 
     741           0 :                         if (pipe->plane_state && pipe->stream->mall_stream_config.paired_stream &&
     742           0 :                                         pipe->stream->mall_stream_config.type == SUBVP_MAIN) {
     743           0 :                                 populate_subvp_cmd_pipe_info(dc, context, &cmd, pipe, cmd_pipe_index++);
     744           0 :                         } else if (pipe->plane_state && pipe->stream->mall_stream_config.type == SUBVP_NONE) {
     745             :                                 // Don't need to check for ActiveDRAMClockChangeMargin < 0, not valid in cases where
     746             :                                 // we run through DML without calculating "natural" P-state support
     747           0 :                                 populate_subvp_cmd_vblank_pipe_info(dc, context, &cmd, pipe, cmd_pipe_index++);
     748             : 
     749             :                         }
     750           0 :                         pipe_idx++;
     751             :                 }
     752           0 :                 if (subvp_count == 2) {
     753           0 :                         update_subvp_prefetch_end_to_mall_start(dc, context, &cmd, subvp_pipes);
     754             :                 }
     755           0 :                 cmd.fw_assisted_mclk_switch_v2.config_data.pstate_allow_width_us = dc->caps.subvp_pstate_allow_width_us;
     756           0 :                 cmd.fw_assisted_mclk_switch_v2.config_data.vertical_int_margin_us = dc->caps.subvp_vertical_int_margin_us;
     757             : 
     758             :                 // Store the original watermark value for this SubVP config so we can lower it when the
     759             :                 // MCLK switch starts
     760           0 :                 wm_val_refclk = context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns *
     761           0 :                                 dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000 / 1000;
     762             : 
     763           0 :                 cmd.fw_assisted_mclk_switch_v2.config_data.watermark_a_cache = wm_val_refclk < 0xFFFF ? wm_val_refclk : 0xFFFF;
     764             :         }
     765           0 :         dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
     766           0 :         dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
     767           0 :         dc_dmub_srv_wait_idle(dc->ctx->dmub_srv);
     768           0 : }
     769             : #endif
     770             : 
     771           0 : bool dc_dmub_srv_get_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv, struct dmub_diagnostic_data *diag_data)
     772             : {
     773           0 :         if (!dc_dmub_srv || !dc_dmub_srv->dmub || !diag_data)
     774             :                 return false;
     775           0 :         return dmub_srv_get_diagnostic_data(dc_dmub_srv->dmub, diag_data);
     776             : }
     777             : 
     778           0 : void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv)
     779             : {
     780           0 :         struct dmub_diagnostic_data diag_data = {0};
     781             : 
     782           0 :         if (!dc_dmub_srv || !dc_dmub_srv->dmub) {
     783           0 :                 DC_LOG_ERROR("%s: invalid parameters.", __func__);
     784           0 :                 return;
     785             :         }
     786             : 
     787           0 :         if (!dc_dmub_srv_get_diagnostic_data(dc_dmub_srv, &diag_data)) {
     788           0 :                 DC_LOG_ERROR("%s: dc_dmub_srv_get_diagnostic_data failed.", __func__);
     789           0 :                 return;
     790             :         }
     791             : 
     792           0 :         DC_LOG_DEBUG(
     793             :                 "DMCUB STATE\n"
     794             :                 "    dmcub_version      : %08x\n"
     795             :                 "    scratch  [0]       : %08x\n"
     796             :                 "    scratch  [1]       : %08x\n"
     797             :                 "    scratch  [2]       : %08x\n"
     798             :                 "    scratch  [3]       : %08x\n"
     799             :                 "    scratch  [4]       : %08x\n"
     800             :                 "    scratch  [5]       : %08x\n"
     801             :                 "    scratch  [6]       : %08x\n"
     802             :                 "    scratch  [7]       : %08x\n"
     803             :                 "    scratch  [8]       : %08x\n"
     804             :                 "    scratch  [9]       : %08x\n"
     805             :                 "    scratch [10]       : %08x\n"
     806             :                 "    scratch [11]       : %08x\n"
     807             :                 "    scratch [12]       : %08x\n"
     808             :                 "    scratch [13]       : %08x\n"
     809             :                 "    scratch [14]       : %08x\n"
     810             :                 "    scratch [15]       : %08x\n"
     811             :                 "    pc                 : %08x\n"
     812             :                 "    unk_fault_addr     : %08x\n"
     813             :                 "    inst_fault_addr    : %08x\n"
     814             :                 "    data_fault_addr    : %08x\n"
     815             :                 "    inbox1_rptr        : %08x\n"
     816             :                 "    inbox1_wptr        : %08x\n"
     817             :                 "    inbox1_size        : %08x\n"
     818             :                 "    inbox0_rptr        : %08x\n"
     819             :                 "    inbox0_wptr        : %08x\n"
     820             :                 "    inbox0_size        : %08x\n"
     821             :                 "    is_enabled         : %d\n"
     822             :                 "    is_soft_reset      : %d\n"
     823             :                 "    is_secure_reset    : %d\n"
     824             :                 "    is_traceport_en    : %d\n"
     825             :                 "    is_cw0_en          : %d\n"
     826             :                 "    is_cw6_en          : %d\n",
     827             :                 diag_data.dmcub_version,
     828             :                 diag_data.scratch[0],
     829             :                 diag_data.scratch[1],
     830             :                 diag_data.scratch[2],
     831             :                 diag_data.scratch[3],
     832             :                 diag_data.scratch[4],
     833             :                 diag_data.scratch[5],
     834             :                 diag_data.scratch[6],
     835             :                 diag_data.scratch[7],
     836             :                 diag_data.scratch[8],
     837             :                 diag_data.scratch[9],
     838             :                 diag_data.scratch[10],
     839             :                 diag_data.scratch[11],
     840             :                 diag_data.scratch[12],
     841             :                 diag_data.scratch[13],
     842             :                 diag_data.scratch[14],
     843             :                 diag_data.scratch[15],
     844             :                 diag_data.pc,
     845             :                 diag_data.undefined_address_fault_addr,
     846             :                 diag_data.inst_fetch_fault_addr,
     847             :                 diag_data.data_write_fault_addr,
     848             :                 diag_data.inbox1_rptr,
     849             :                 diag_data.inbox1_wptr,
     850             :                 diag_data.inbox1_size,
     851             :                 diag_data.inbox0_rptr,
     852             :                 diag_data.inbox0_wptr,
     853             :                 diag_data.inbox0_size,
     854             :                 diag_data.is_dmcub_enabled,
     855             :                 diag_data.is_dmcub_soft_reset,
     856             :                 diag_data.is_dmcub_secure_reset,
     857             :                 diag_data.is_traceport_en,
     858             :                 diag_data.is_cw0_enabled,
     859             :                 diag_data.is_cw6_enabled);
     860             : }
     861             : 
     862             : #if IS_ENABLED(CONFIG_AMD_DC_KUNIT_TEST)
     863             : #include "../tests/dc/dc_dmub_srv_test.c"
     864             : #endif

Generated by: LCOV version 1.14