]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/amd/display: Add DMUB IPS command support for IPS residency tools
authorOvidiu Bunea <Ovidiu.Bunea@amd.com>
Fri, 6 Jun 2025 19:49:22 +0000 (15:49 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 24 Jun 2025 13:58:22 +0000 (09:58 -0400)
[why & how]
Add DMUB IPS CMD interface for driver and
DMU to communicate for IPS residency tools.

Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Signed-off-by: Ovidiu Bunea <Ovidiu.Bunea@amd.com>
Signed-off-by: Fangzhi Zuo <jerry.zuo@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/dc_dmub_srv.c
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
drivers/gpu/drm/amd/display/dmub/dmub_srv.h
drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h

index 1f685fc5c55ab115c886cdf9f47f27696bb8de65..0a47d1a3515b634790d541be4e41e7867ce419ba 100644 (file)
@@ -1904,85 +1904,53 @@ void dc_dmub_srv_fams2_passthrough_flip(
        }
 }
 
-bool dc_dmub_srv_ips_residency_cntl(struct dc_dmub_srv *dc_dmub_srv, bool start_measurement)
+
+bool dc_dmub_srv_ips_residency_cntl(const struct dc_context *ctx, uint8_t panel_inst, bool start_measurement)
 {
-       bool result;
+       union dmub_rb_cmd cmd;
 
-       if (!dc_dmub_srv || !dc_dmub_srv->dmub)
-               return false;
+       memset(&cmd, 0, sizeof(cmd));
 
-       result = dc_wake_and_execute_gpint(dc_dmub_srv->ctx, DMUB_GPINT__IPS_RESIDENCY,
-                                          start_measurement, NULL, DM_DMUB_WAIT_TYPE_WAIT);
+       cmd.ips_residency_cntl.header.type = DMUB_CMD__IPS;
+       cmd.ips_residency_cntl.header.sub_type = DMUB_CMD__IPS_RESIDENCY_CNTL;
+       cmd.ips_residency_cntl.header.payload_bytes = sizeof(struct dmub_cmd_ips_residency_cntl_data);
 
-       return result;
+       // only panel_inst=0 is supported at the moment
+       cmd.ips_residency_cntl.cntl_data.panel_inst = panel_inst;
+       cmd.ips_residency_cntl.cntl_data.start_measurement = start_measurement;
+
+       if (!dc_wake_and_execute_dmub_cmd(ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY))
+               return false;
+
+       return true;
 }
 
-void dc_dmub_srv_ips_query_residency_info(struct dc_dmub_srv *dc_dmub_srv, struct ips_residency_info *output)
+bool dc_dmub_srv_ips_query_residency_info(const struct dc_context *ctx, uint8_t panel_inst, struct dmub_ips_residency_info *driver_info,
+                                         enum ips_residency_mode ips_mode)
 {
-       uint32_t i;
-       enum dmub_gpint_command command_code;
+       union dmub_rb_cmd cmd;
+       uint32_t bytes = sizeof(struct dmub_ips_residency_info);
 
-       if (!dc_dmub_srv || !dc_dmub_srv->dmub)
-               return;
+       dmub_flush_buffer_mem(&ctx->dmub_srv->dmub->scratch_mem_fb);
+       memset(&cmd, 0, sizeof(cmd));
 
-       switch (output->ips_mode) {
-       case DMUB_IPS_MODE_IPS1_MAX:
-               command_code = DMUB_GPINT__GET_IPS1_HISTOGRAM_COUNTER;
-               break;
-       case DMUB_IPS_MODE_IPS2:
-               command_code = DMUB_GPINT__GET_IPS2_HISTOGRAM_COUNTER;
-               break;
-       case DMUB_IPS_MODE_IPS1_RCG:
-               command_code = DMUB_GPINT__GET_IPS1_RCG_HISTOGRAM_COUNTER;
-               break;
-       case DMUB_IPS_MODE_IPS1_ONO2_ON:
-               command_code = DMUB_GPINT__GET_IPS1_ONO2_ON_HISTOGRAM_COUNTER;
-               break;
-       default:
-               command_code = DMUB_GPINT__INVALID_COMMAND;
-               break;
-       }
+       cmd.ips_query_residency_info.header.type = DMUB_CMD__IPS;
+       cmd.ips_query_residency_info.header.sub_type = DMUB_CMD__IPS_QUERY_RESIDENCY_INFO;
+       cmd.ips_query_residency_info.header.payload_bytes = sizeof(struct dmub_cmd_ips_query_residency_info_data);
 
-       if (command_code == DMUB_GPINT__INVALID_COMMAND)
-               return;
+       cmd.ips_query_residency_info.info_data.dest.quad_part = ctx->dmub_srv->dmub->scratch_mem_fb.gpu_addr;
+       cmd.ips_query_residency_info.info_data.size = bytes;
+       cmd.ips_query_residency_info.info_data.panel_inst = panel_inst;
+       cmd.ips_query_residency_info.info_data.ips_mode = (uint32_t)ips_mode;
 
-       for (i = 0; i < GPINT_RETRY_NUM; i++) {
-               // false could mean GPINT timeout, in which case we should retry
-               if (dc_wake_and_execute_gpint(dc_dmub_srv->ctx, DMUB_GPINT__GET_IPS_RESIDENCY_PERCENT,
-                                             (uint16_t)(output->ips_mode), &output->residency_percent,
-                                             DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY))
-                       break;
-               udelay(100);
-       }
+       if (!dc_wake_and_execute_dmub_cmd(ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY) ||
+                                         cmd.ips_query_residency_info.header.ret_status == 0)
+               return false;
 
-       if (!dc_wake_and_execute_gpint(dc_dmub_srv->ctx, DMUB_GPINT__GET_IPS_RESIDENCY_ENTRY_COUNTER,
-                                     (uint16_t)(output->ips_mode),
-                                      &output->entry_counter, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY))
-               output->entry_counter = 0;
-
-       if (!dc_wake_and_execute_gpint(dc_dmub_srv->ctx, DMUB_GPINT__GET_IPS_RESIDENCY_DURATION_US_LO,
-                                     (uint16_t)(output->ips_mode),
-                                      &output->total_active_time_us[0], DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY))
-               output->total_active_time_us[0] = 0;
-       if (!dc_wake_and_execute_gpint(dc_dmub_srv->ctx, DMUB_GPINT__GET_IPS_RESIDENCY_DURATION_US_HI,
-                                     (uint16_t)(output->ips_mode),
-                                      &output->total_active_time_us[1], DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY))
-               output->total_active_time_us[1] = 0;
-
-       if (!dc_wake_and_execute_gpint(dc_dmub_srv->ctx, DMUB_GPINT__GET_IPS_INACTIVE_RESIDENCY_DURATION_US_LO,
-                                     (uint16_t)(output->ips_mode),
-                                      &output->total_inactive_time_us[0], DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY))
-               output->total_inactive_time_us[0] = 0;
-       if (!dc_wake_and_execute_gpint(dc_dmub_srv->ctx, DMUB_GPINT__GET_IPS_INACTIVE_RESIDENCY_DURATION_US_HI,
-                                     (uint16_t)(output->ips_mode),
-                                      &output->total_inactive_time_us[1], DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY))
-               output->total_inactive_time_us[1] = 0;
-
-       // NUM_IPS_HISTOGRAM_BUCKETS = 16
-       for (i = 0; i < 16; i++)
-               if (!dc_wake_and_execute_gpint(dc_dmub_srv->ctx, command_code, i, &output->histogram[i],
-                                              DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY))
-                       output->histogram[i] = 0;
+       // copy the result to the output since ret_status != 0 means the command returned data
+       memcpy(driver_info, ctx->dmub_srv->dmub->scratch_mem_fb.cpu_addr, bytes);
+
+       return true;
 }
 
 bool dmub_lsdma_init(struct dc_dmub_srv *dc_dmub_srv)
index 178a71e3b7dc41120551d556c3ab8dd9e9506f6e..1f1c155be30e938af72b90e28d3f88598982d3e7 100644 (file)
@@ -210,45 +210,6 @@ void dc_dmub_srv_fams2_passthrough_flip(
                struct dc_surface_update *srf_updates,
                int surface_count);
 
-/**
- * struct ips_residency_info - struct containing info from dmub_ips_residency_stats
- *
- * @ips_mode: The mode of IPS that the follow stats appertain to
- * @residency_percent: The percentage of time spent in given IPS mode in millipercent
- * @entry_counter: The number of entries made in to this IPS state
- * @total_active_time_us: uint32_t array of length 2 representing time in the given IPS mode
- *                        in microseconds. Index 0 is lower 32 bits, index 1 is upper 32 bits.
- * @total_inactive_time_us: uint32_t array of length 2 representing time outside the given IPS mode
- *                          in microseconds. Index 0 is lower 32 bits, index 1 is upper 32 bits.
- * @histogram: Histogram of given IPS state durations - bucket definitions in dmub_ips.c
- */
-struct ips_residency_info {
-       enum dmub_ips_mode ips_mode;
-       unsigned int residency_percent;
-       unsigned int entry_counter;
-       unsigned int total_active_time_us[2];
-       unsigned int total_inactive_time_us[2];
-       unsigned int histogram[16];
-};
-
-/**
- * bool dc_dmub_srv_ips_residency_cntl() - Controls IPS residency measurement status
- *
- * @dc_dmub_srv: The DC DMUB service pointer
- * @start_measurement: Describes whether to start or stop measurement
- *
- * Return: true if GPINT was sent successfully, false otherwise
- */
-bool dc_dmub_srv_ips_residency_cntl(struct dc_dmub_srv *dc_dmub_srv, bool start_measurement);
-
-/**
- * bool dc_dmub_srv_ips_query_residency_info() - Queries DMCUB for residency info
- *
- * @dc_dmub_srv: The DC DMUB service pointer
- * @output: Output struct to copy the the residency info to
- */
-void dc_dmub_srv_ips_query_residency_info(struct dc_dmub_srv *dc_dmub_srv, struct ips_residency_info *output);
-
 bool dmub_lsdma_init(struct dc_dmub_srv *dc_dmub_srv);
 bool dmub_lsdma_send_linear_copy_packet(
        struct dc_dmub_srv *dc_dmub_srv,
@@ -303,4 +264,31 @@ bool dmub_lsdma_send_tiled_to_tiled_copy_command(
        struct lsdma_send_tiled_to_tiled_copy_command_params params);
 bool dmub_lsdma_send_poll_reg_write_command(struct dc_dmub_srv *dc_dmub_srv, uint32_t reg_addr, uint32_t reg_data);
 
+/**
+ * struct ips_residency_info - struct containing info from dmub_ips_residency_stats
+ *
+ * @ips_mode: The mode of IPS that the follow stats appertain to
+ * @residency_percent: The percentage of time spent in given IPS mode in millipercent
+ * @entry_counter: The number of entries made in to this IPS state
+ * @total_active_time_us: uint32_t array of length 2 representing time in the given IPS mode
+ *                        in microseconds. Index 0 is lower 32 bits, index 1 is upper 32 bits.
+ * @total_inactive_time_us: uint32_t array of length 2 representing time outside the given IPS mode
+ *                          in microseconds. Index 0 is lower 32 bits, index 1 is upper 32 bits.
+ * @histogram: Histogram of given IPS state durations - bucket definitions in dmub_ips.c
+ */
+struct ips_residency_info {
+       enum ips_residency_mode ips_mode;
+       unsigned int residency_percent;
+       unsigned int entry_counter;
+       unsigned int total_active_time_us[2];
+       unsigned int total_inactive_time_us[2];
+       unsigned int histogram[16];
+};
+
+bool dc_dmub_srv_ips_residency_cntl(const struct dc_context *ctx, uint8_t panel_inst, bool start_measurement);
+
+bool dc_dmub_srv_ips_query_residency_info(const struct dc_context *ctx, uint8_t panel_inst,
+                                         struct dmub_ips_residency_info *driver_info,
+                                         enum ips_residency_mode ips_mode);
+
 #endif /* _DMUB_DC_SRV_H_ */
index c627093bb849c7b9a3523c330c98ed62cd8110a0..0bafb6710761841d99c3d176366a33e4fca8a29e 100644 (file)
@@ -607,14 +607,6 @@ struct dmub_notification {
        };
 };
 
-/* enum dmub_ips_mode - IPS mode identifier */
-enum dmub_ips_mode {
-       DMUB_IPS_MODE_IPS1_MAX          = 0,
-       DMUB_IPS_MODE_IPS2,
-       DMUB_IPS_MODE_IPS1_RCG,
-       DMUB_IPS_MODE_IPS1_ONO2_ON
-};
-
 /**
  * DMUB firmware version helper macro - useful for checking if the version
  * of a firmware to know if feature or functionality is supported or present.
index 569644bea641d6fa3cf6f0396975d65f0ff18d04..e6730e59d987f79eeda1928f7f502a7b9b739d75 100644 (file)
@@ -795,6 +795,17 @@ enum dmub_ips_rcg_disable_type {
 #define DMUB_IPS1_COMMIT_MASK 0x00000004
 #define DMUB_IPS2_COMMIT_MASK 0x00000008
 
+enum dmub_ips_comand_type {
+       /**
+        * Start/stop IPS residency measurements for a given IPS mode
+        */
+       DMUB_CMD__IPS_RESIDENCY_CNTL = 0,
+       /**
+        * Query IPS residency information for a given IPS mode
+        */
+       DMUB_CMD__IPS_QUERY_RESIDENCY_INFO = 1,
+};
+
 /**
  * union dmub_fw_boot_options - Boot option definitions for SCRATCH14
  */
@@ -1546,6 +1557,11 @@ enum dmub_cmd_type {
         */
        DMUB_CMD__LSDMA = 90,
 
+       /**
+        * Command type use for all IPS commands.
+        */
+       DMUB_CMD__IPS = 91,
+
        DMUB_CMD__VBIOS = 128,
 };
 
@@ -5856,6 +5872,56 @@ struct dmub_rb_cmd_assr_enable {
        uint32_t reserved[3];
 };
 
+/**
+ * Current definition of "ips_mode" from driver
+ */
+enum ips_residency_mode {
+       IPS_RESIDENCY__IPS1_MAX,
+       IPS_RESIDENCY__IPS2,
+       IPS_RESIDENCY__IPS1_RCG,
+       IPS_RESIDENCY__IPS1_ONO2_ON,
+};
+
+#define NUM_IPS_HISTOGRAM_BUCKETS 16
+
+/**
+ * IPS residency statistics to be sent to driver - subset of struct dmub_ips_residency_stats
+ */
+struct dmub_ips_residency_info {
+       uint32_t residency_millipercent;
+       uint32_t entry_counter;
+       uint32_t histogram[NUM_IPS_HISTOGRAM_BUCKETS];
+       uint64_t total_time_us;
+       uint64_t total_inactive_time_us;
+};
+
+/**
+ * Data passed from driver to FW in a DMUB_CMD__IPS_RESIDENCY_CNTL command.
+ */
+struct dmub_cmd_ips_residency_cntl_data {
+       uint8_t panel_inst;
+       uint8_t start_measurement;
+       uint8_t padding[2]; // align to 4-byte boundary
+};
+
+struct dmub_rb_cmd_ips_residency_cntl {
+       struct dmub_cmd_header header;
+       struct dmub_cmd_ips_residency_cntl_data cntl_data;
+};
+
+struct dmub_cmd_ips_query_residency_info_data {
+       union dmub_addr dest;
+       uint32_t size;
+       uint32_t ips_mode;
+       uint8_t panel_inst;
+       uint8_t padding[3]; // align to 4-byte boundary
+};
+
+struct dmub_rb_cmd_ips_query_residency_info {
+       struct dmub_cmd_header header;
+       struct dmub_cmd_ips_query_residency_info_data info_data;
+};
+
 /**
  * union dmub_rb_cmd - DMUB inbox command.
  */
@@ -6177,6 +6243,10 @@ union dmub_rb_cmd {
         * Definition of a DMUB_CMD__LSDMA command.
         */
        struct dmub_rb_cmd_lsdma lsdma;
+
+       struct dmub_rb_cmd_ips_residency_cntl ips_residency_cntl;
+
+       struct dmub_rb_cmd_ips_query_residency_info ips_query_residency_info;
 };
 
 /**