drm/amd/display: add shared helpers to update psr config fields to power module
authorDavid Zhang <dingchen.zhang@amd.com>
Mon, 25 Apr 2022 22:08:13 +0000 (18:08 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 6 Jun 2022 18:42:33 +0000 (14:42 -0400)
[why]
Currently the amdgpu DM psr configuration parameters are hardcoded
before feeding into the DC helper to setup PSR. We would define a
helper which is to calculate parts of the psr config fields to
avoid hard-coding.

[how]
To make helper shareable, declare and define the helper in the
module_helper, to set/update below fields:
- psr remote buffer setup time
- sdp tx line number deadline
- line time in us
- su_y_granularity
- su_granularity_required
- psr_frame_capture_indication_req
- psr_exit_link_training_required

add another helper to check given the stream context, if there is
only one stream and the output is eDP panel connected.

changes in v2:
------------------
- add detailed comment for how psr setup time is calculated as per
  eDP 1.5 spec

Cc: Chandan Vurdigerenataraj <chandan.vurdigerenataraj@amd.com>
Signed-off-by: David Zhang <dingchen.zhang@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/modules/power/power_helpers.c
drivers/gpu/drm/amd/display/modules/power/power_helpers.h

index 97928d4c3b9ab4806c1c06b52e48b7f3ebc79172..bc239d38c3c7e565e9ae9086ced7aa9e87042535 100644 (file)
@@ -822,3 +822,87 @@ bool is_psr_su_specific_panel(struct dc_link *link)
 
        return false;
 }
+
+/**
+ * mod_power_calc_psr_configs() - calculate/update generic psr configuration fields.
+ * @psr_config: [output], psr configuration structure to be updated
+ * @link: [input] dc link pointer
+ * @stream: [input] dc stream state pointer
+ *
+ * calculate and update the psr configuration fields that are not DM specific, i.e. such
+ * fields which are based on DPCD caps or timing information. To setup PSR in DMUB FW,
+ * this helper is assumed to be called before the call of the DC helper dc_link_setup_psr().
+ *
+ * PSR config fields to be updated within the helper:
+ * - psr_rfb_setup_time
+ * - psr_sdp_transmit_line_num_deadline
+ * - line_time_in_us
+ * - su_y_granularity
+ * - su_granularity_required
+ * - psr_frame_capture_indication_req
+ * - psr_exit_link_training_required
+ *
+ * PSR config fields that are DM specific and NOT updated within the helper:
+ * - allow_smu_optimizations
+ * - allow_multi_disp_optimizations
+ */
+void mod_power_calc_psr_configs(struct psr_config *psr_config,
+               struct dc_link *link,
+               const struct dc_stream_state *stream)
+{
+       unsigned int num_vblank_lines = 0;
+       unsigned int vblank_time_in_us = 0;
+       unsigned int sdp_tx_deadline_in_us = 0;
+       unsigned int line_time_in_us = 0;
+       struct dpcd_caps *dpcd_caps = &link->dpcd_caps;
+       const int psr_setup_time_step_in_us = 55;       /* refer to eDP spec DPCD 0x071h */
+
+       /* timing parameters */
+       num_vblank_lines = stream->timing.v_total -
+                        stream->timing.v_addressable -
+                        stream->timing.v_border_top -
+                        stream->timing.v_border_bottom;
+
+       vblank_time_in_us = (stream->timing.h_total * num_vblank_lines * 1000) / (stream->timing.pix_clk_100hz / 10);
+
+       line_time_in_us = ((stream->timing.h_total * 1000) / (stream->timing.pix_clk_100hz / 10)) + 1;
+
+       /**
+        * psr configuration fields
+        *
+        * as per eDP 1.5 pg. 377 of 459, DPCD 0x071h bits [3:1], psr setup time bits interpreted as below
+        * 000b <--> 330 us (default)
+        * 001b <--> 275 us
+        * 010b <--> 220 us
+        * 011b <--> 165 us
+        * 100b <--> 110 us
+        * 101b <--> 055 us
+        * 110b <--> 000 us
+        */
+       psr_config->psr_rfb_setup_time =
+               (6 - dpcd_caps->psr_info.psr_dpcd_caps.bits.PSR_SETUP_TIME) * psr_setup_time_step_in_us;
+
+       if (psr_config->psr_rfb_setup_time > vblank_time_in_us) {
+               link->psr_settings.psr_frame_capture_indication_req = true;
+               link->psr_settings.psr_sdp_transmit_line_num_deadline = num_vblank_lines;
+       } else {
+               sdp_tx_deadline_in_us = vblank_time_in_us - psr_config->psr_rfb_setup_time;
+
+               /* Set the last possible line SDP may be transmitted without violating the RFB setup time */
+               link->psr_settings.psr_frame_capture_indication_req = false;
+               link->psr_settings.psr_sdp_transmit_line_num_deadline = sdp_tx_deadline_in_us / line_time_in_us;
+       }
+
+       psr_config->psr_sdp_transmit_line_num_deadline = link->psr_settings.psr_sdp_transmit_line_num_deadline;
+       psr_config->line_time_in_us = line_time_in_us;
+       psr_config->su_y_granularity = dpcd_caps->psr_info.psr2_su_y_granularity_cap;
+       psr_config->su_granularity_required = dpcd_caps->psr_info.psr_dpcd_caps.bits.SU_GRANULARITY_REQUIRED;
+       psr_config->psr_frame_capture_indication_req = link->psr_settings.psr_frame_capture_indication_req;
+       psr_config->psr_exit_link_training_required =
+               !link->dpcd_caps.psr_info.psr_dpcd_caps.bits.LINK_TRAINING_ON_EXIT_NOT_REQUIRED;
+}
+
+bool mod_power_only_edp(const struct dc_state *context, const struct dc_stream_state *stream)
+{
+       return context && context->stream_count == 1 && dc_is_embedded_signal(stream->signal);
+}
index 1a634d8c78c58662f10031220b8924df29c54576..316452e9dbc91d74cbcf2f729084f29efa5405c6 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "dc/inc/hw/dmcu.h"
 #include "dc/inc/hw/abm.h"
+#include "dc/inc/core_types.h"
 
 struct resource_pool;
 
@@ -53,4 +54,9 @@ bool dmub_init_abm_config(struct resource_pool *res_pool,
                unsigned int inst);
 
 bool is_psr_su_specific_panel(struct dc_link *link);
+void mod_power_calc_psr_configs(struct psr_config *psr_config,
+               struct dc_link *link,
+               const struct dc_stream_state *stream);
+bool mod_power_only_edp(const struct dc_state *context,
+               const struct dc_stream_state *stream);
 #endif /* MODULES_POWER_POWER_HELPERS_H_ */