diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display')
135 files changed, 5344 insertions, 4498 deletions
diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig index 413d8c6d592f..6925e0280dbe 100644 --- a/drivers/gpu/drm/amd/display/Kconfig +++ b/drivers/gpu/drm/amd/display/Kconfig @@ -28,7 +28,6 @@ config DRM_AMD_DC_SI bool "AMD DC support for Southern Islands ASICs" depends on DRM_AMDGPU_SI depends on DRM_AMD_DC - default n help Choose this option to enable new AMD DC support for SI asics by default. This includes Tahiti, Pitcairn, Cape Verde, Oland. @@ -43,7 +42,6 @@ config DEBUG_KERNEL_DC config DRM_AMD_SECURE_DISPLAY bool "Enable secure display support" - default n depends on DEBUG_FS depends on DRM_AMD_DC_DCN help diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 1efe7fa5bc58..4c73727e0b7d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -88,6 +88,9 @@ #include <drm/drm_vblank.h> #include <drm/drm_audio_component.h> #include <drm/drm_gem_atomic_helper.h> +#include <drm/drm_plane_helper.h> + +#include <acpi/video.h> #include "ivsrcid/dcn/irqsrcs_dcn_1_0.h" @@ -97,8 +100,6 @@ #include "soc15_common.h" #include "vega10_ip_offset.h" -#include "soc15_common.h" - #include "gc/gc_11_0_0_offset.h" #include "gc/gc_11_0_0_sh_mask.h" @@ -1295,13 +1296,21 @@ static struct hpd_rx_irq_offload_work_queue *hpd_rx_irq_create_workqueue(struct if (hpd_rx_offload_wq[i].wq == NULL) { DRM_ERROR("create amdgpu_dm_hpd_rx_offload_wq fail!"); - return NULL; + goto out_err; } spin_lock_init(&hpd_rx_offload_wq[i].offload_lock); } return hpd_rx_offload_wq; + +out_err: + for (i = 0; i < max_caps; i++) { + if (hpd_rx_offload_wq[i].wq) + destroy_workqueue(hpd_rx_offload_wq[i].wq); + } + kfree(hpd_rx_offload_wq); + return NULL; } struct amdgpu_stutter_quirk { @@ -1529,7 +1538,6 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) if (amdgpu_dc_debug_mask & DC_DISABLE_DSC) { adev->dm.dc->debug.disable_dsc = true; - adev->dm.dc->debug.disable_dsc_edp = true; } if (amdgpu_dc_debug_mask & DC_DISABLE_CLOCK_GATING) @@ -2807,20 +2815,18 @@ static const struct drm_mode_config_funcs amdgpu_dm_mode_funcs = { }; static struct drm_mode_config_helper_funcs amdgpu_dm_mode_config_helperfuncs = { - .atomic_commit_tail = amdgpu_dm_atomic_commit_tail + .atomic_commit_tail = amdgpu_dm_atomic_commit_tail, + .atomic_commit_setup = drm_dp_mst_atomic_setup_commit, }; static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector) { - u32 max_avg, min_cll, max, min, q, r; struct amdgpu_dm_backlight_caps *caps; struct amdgpu_display_manager *dm; struct drm_connector *conn_base; struct amdgpu_device *adev; struct dc_link *link = NULL; - static const u8 pre_computed_values[] = { - 50, 51, 52, 53, 55, 56, 57, 58, 59, 61, 62, 63, 65, 66, 68, 69, - 71, 72, 74, 75, 77, 79, 81, 82, 84, 86, 88, 90, 92, 94, 96, 98}; + struct drm_luminance_range_info *luminance_range; int i; if (!aconnector || !aconnector->dc_link) @@ -2842,8 +2848,6 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector) caps = &dm->backlight_caps[i]; caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps; caps->aux_support = false; - max_avg = conn_base->hdr_sink_metadata.hdmi_type1.max_fall; - min_cll = conn_base->hdr_sink_metadata.hdmi_type1.min_cll; if (caps->ext_caps->bits.oled == 1 /*|| caps->ext_caps->bits.sdr_aux_backlight_control == 1 || @@ -2855,31 +2859,9 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector) else if (amdgpu_backlight == 1) caps->aux_support = true; - /* From the specification (CTA-861-G), for calculating the maximum - * luminance we need to use: - * Luminance = 50*2**(CV/32) - * Where CV is a one-byte value. - * For calculating this expression we may need float point precision; - * to avoid this complexity level, we take advantage that CV is divided - * by a constant. From the Euclids division algorithm, we know that CV - * can be written as: CV = 32*q + r. Next, we replace CV in the - * Luminance expression and get 50*(2**q)*(2**(r/32)), hence we just - * need to pre-compute the value of r/32. For pre-computing the values - * We just used the following Ruby line: - * (0...32).each {|cv| puts (50*2**(cv/32.0)).round} - * The results of the above expressions can be verified at - * pre_computed_values. - */ - q = max_avg >> 5; - r = max_avg % 32; - max = (1 << q) * pre_computed_values[r]; - - // min luminance: maxLum * (CV/255)^2 / 100 - q = DIV_ROUND_CLOSEST(min_cll, 255); - min = max * DIV_ROUND_CLOSEST((q * q), 100); - - caps->aux_max_input_signal = max; - caps->aux_min_input_signal = min; + luminance_range = &conn_base->display_info.luminance_range; + caps->aux_min_input_signal = luminance_range->min_luminance; + caps->aux_max_input_signal = luminance_range->max_luminance; } void amdgpu_dm_update_connector_after_detect( @@ -4058,6 +4040,13 @@ amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm) amdgpu_dm_update_backlight_caps(dm, dm->num_of_edps); dm->brightness[dm->num_of_edps] = AMDGPU_MAX_BL_LEVEL; + if (!acpi_video_backlight_use_native()) { + drm_info(adev_to_drm(dm->adev), "Skipping amdgpu DM backlight registration\n"); + /* Try registering an ACPI video backlight device instead. */ + acpi_video_register_backlight(); + return; + } + props.max_brightness = AMDGPU_MAX_BL_LEVEL; props.brightness = AMDGPU_MAX_BL_LEVEL; props.type = BACKLIGHT_RAW; @@ -5629,7 +5618,8 @@ static void apply_dsc_policy_for_stream(struct amdgpu_dm_connector *aconnector, dc_dsc_policy_set_enable_dsc_when_not_needed( aconnector->dsc_settings.dsc_force_enable == DSC_CLK_FORCE_ENABLE); - if (aconnector->dc_link && sink->sink_signal == SIGNAL_TYPE_EDP && !dc->debug.disable_dsc_edp && + if (aconnector->dc_link && sink->sink_signal == SIGNAL_TYPE_EDP && + !aconnector->dc_link->panel_config.dsc.disable_dsc_edp && dc->caps.edp_dsc_support && aconnector->dsc_settings.dsc_force_enable != DSC_CLK_FORCE_DISABLE) { apply_dsc_policy_for_edp(aconnector, sink, stream, dsc_caps, max_dsc_target_bpp_limit_override); @@ -6321,10 +6311,17 @@ amdgpu_dm_connector_atomic_check(struct drm_connector *conn, drm_atomic_get_old_connector_state(state, conn); struct drm_crtc *crtc = new_con_state->crtc; struct drm_crtc_state *new_crtc_state; + struct amdgpu_dm_connector *aconn = to_amdgpu_dm_connector(conn); int ret; trace_amdgpu_dm_connector_atomic_check(new_con_state); + if (conn->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { + ret = drm_dp_mst_root_conn_atomic_check(new_con_state, &aconn->mst_mgr); + if (ret < 0) + return ret; + } + if (!crtc) return 0; @@ -6408,6 +6405,7 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder, const struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode; struct drm_dp_mst_topology_mgr *mst_mgr; struct drm_dp_mst_port *mst_port; + struct drm_dp_mst_topology_state *mst_state; enum dc_color_depth color_depth; int clock, bpp = 0; bool is_y420 = false; @@ -6421,6 +6419,13 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder, if (!crtc_state->connectors_changed && !crtc_state->mode_changed) return 0; + mst_state = drm_atomic_get_mst_topology_state(state, mst_mgr); + if (IS_ERR(mst_state)) + return PTR_ERR(mst_state); + + if (!mst_state->pbn_div) + mst_state->pbn_div = dm_mst_get_pbn_divider(aconnector->mst_port->dc_link); + if (!state->duplicated) { int max_bpc = conn_state->max_requested_bpc; is_y420 = drm_mode_is_420_also(&connector->display_info, adjusted_mode) && @@ -6432,11 +6437,10 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder, clock = adjusted_mode->clock; dm_new_connector_state->pbn = drm_dp_calc_pbn_mode(clock, bpp, false); } - dm_new_connector_state->vcpi_slots = drm_dp_atomic_find_vcpi_slots(state, - mst_mgr, - mst_port, - dm_new_connector_state->pbn, - dm_mst_get_pbn_divider(aconnector->dc_link)); + + dm_new_connector_state->vcpi_slots = + drm_dp_atomic_find_time_slots(state, mst_mgr, mst_port, + dm_new_connector_state->pbn); if (dm_new_connector_state->vcpi_slots < 0) { DRM_DEBUG_ATOMIC("failed finding vcpi slots: %d\n", (int)dm_new_connector_state->vcpi_slots); return dm_new_connector_state->vcpi_slots; @@ -6506,18 +6510,12 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state, dm_conn_state->pbn = pbn; dm_conn_state->vcpi_slots = slot_num; - drm_dp_mst_atomic_enable_dsc(state, - aconnector->port, - dm_conn_state->pbn, - 0, + drm_dp_mst_atomic_enable_dsc(state, aconnector->port, dm_conn_state->pbn, false); continue; } - vcpi = drm_dp_mst_atomic_enable_dsc(state, - aconnector->port, - pbn, pbn_div, - true); + vcpi = drm_dp_mst_atomic_enable_dsc(state, aconnector->port, pbn, true); if (vcpi < 0) return vcpi; @@ -7387,11 +7385,6 @@ static void update_freesync_state_on_stream( &vrr_infopacket, pack_sdp_v1_3); - new_crtc_state->freesync_timing_changed |= - (memcmp(&acrtc->dm_irq_params.vrr_params.adjust, - &vrr_params.adjust, - sizeof(vrr_params.adjust)) != 0); - new_crtc_state->freesync_vrr_info_changed |= (memcmp(&new_crtc_state->vrr_infopacket, &vrr_infopacket, @@ -7400,7 +7393,6 @@ static void update_freesync_state_on_stream( acrtc->dm_irq_params.vrr_params = vrr_params; new_crtc_state->vrr_infopacket = vrr_infopacket; - new_stream->adjust = acrtc->dm_irq_params.vrr_params.adjust; new_stream->vrr_infopacket = vrr_infopacket; if (new_crtc_state->freesync_vrr_info_changed) @@ -7463,10 +7455,6 @@ static void update_stream_irq_parameters( new_stream, &config, &vrr_params); - new_crtc_state->freesync_timing_changed |= - (memcmp(&acrtc->dm_irq_params.vrr_params.adjust, - &vrr_params.adjust, sizeof(vrr_params.adjust)) != 0); - new_crtc_state->freesync_config = config; /* Copy state for access from DM IRQ handler */ acrtc->dm_irq_params.freesync_config = config; @@ -7992,6 +7980,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) DRM_ERROR("Waiting for fences timed out!"); drm_atomic_helper_update_legacy_modeset_state(dev, state); + drm_dp_mst_atomic_wait_for_dependencies(state); dm_state = dm_atomic_get_new_state(state); if (dm_state && dm_state->context) { @@ -8390,7 +8379,6 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) dc_release_state(dc_state_temp); } - static int dm_force_atomic_commit(struct drm_connector *connector) { int ret = 0; @@ -9321,6 +9309,7 @@ static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm /** * amdgpu_dm_atomic_check() - Atomic check implementation for AMDgpu DM. + * * @dev: The DRM device * @state: The atomic state to commit * @@ -9361,8 +9350,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state; #if defined(CONFIG_DRM_AMD_DC_DCN) struct dsc_mst_fairness_vars vars[MAX_PIPES]; - struct drm_dp_mst_topology_state *mst_state; - struct drm_dp_mst_topology_mgr *mgr; #endif trace_amdgpu_dm_atomic_check_begin(state); @@ -9379,9 +9366,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, struct dm_connector_state *dm_new_con_state = to_dm_connector_state(new_con_state); /* Skip connectors that are disabled or part of modeset already. */ - if (!old_con_state->crtc && !new_con_state->crtc) - continue; - if (!new_con_state->crtc) continue; @@ -9609,33 +9593,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, lock_and_validation_needed = true; } -#if defined(CONFIG_DRM_AMD_DC_DCN) - /* set the slot info for each mst_state based on the link encoding format */ - for_each_new_mst_mgr_in_state(state, mgr, mst_state, i) { - struct amdgpu_dm_connector *aconnector; - struct drm_connector *connector; - struct drm_connector_list_iter iter; - u8 link_coding_cap; - - if (!mgr->mst_state ) - continue; - - drm_connector_list_iter_begin(dev, &iter); - drm_for_each_connector_iter(connector, &iter) { - int id = connector->index; - - if (id == mst_state->mgr->conn_base_id) { - aconnector = to_amdgpu_dm_connector(connector); - link_coding_cap = dc_link_dp_mst_decide_link_encoding_format(aconnector->dc_link); - drm_dp_mst_update_slots(mst_state, link_coding_cap); - - break; - } - } - drm_connector_list_iter_end(&iter); - - } -#endif /** * Streams and planes are reset when there are changes that affect * bandwidth. Anything that affects bandwidth needs to go through @@ -9943,8 +9900,19 @@ static int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector, return valid_vsdb_found ? i : -ENODEV; } +/** + * amdgpu_dm_update_freesync_caps - Update Freesync capabilities + * + * @connector: Connector to query. + * @edid: EDID from monitor + * + * Amdgpu supports Freesync in DP and HDMI displays, and it is required to keep + * track of some of the display information in the internal data struct used by + * amdgpu_dm. This function checks which type of connector we need to set the + * FreeSync parameters. + */ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, - struct edid *edid) + struct edid *edid) { int i = 0; struct detailed_timing *timing; @@ -9957,8 +9925,8 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, struct drm_device *dev = connector->dev; struct amdgpu_device *adev = drm_to_adev(dev); - bool freesync_capable = false; struct amdgpu_hdmi_vsdb_info vsdb_info = {0}; + bool freesync_capable = false; if (!connector->state) { DRM_ERROR("%s - Connector has no state", __func__); @@ -9987,7 +9955,6 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, if (!adev->dm.freesync_module) goto update; - if (sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT || sink->sink_signal == SIGNAL_TYPE_EDP) { bool edid_check_required = false; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index 90b306a1dd68..b5ce15c43bcc 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -598,6 +598,10 @@ struct amdgpu_dm_connector { * The 'current' sink is in dc_link->sink. */ struct dc_sink *dc_sink; struct dc_link *dc_link; + + /** + * @dc_em_sink: Reference to the emulated (virtual) sink. + */ struct dc_sink *dc_em_sink; /* DM only */ @@ -610,7 +614,16 @@ struct amdgpu_dm_connector { struct amdgpu_i2c_adapter *i2c; /* Monitor range limits */ - int min_vfreq ; + /** + * @min_vfreq: Minimal frequency supported by the display in Hz. This + * value is set to zero when there is no FreeSync support. + */ + int min_vfreq; + + /** + * @max_vfreq: Maximum frequency supported by the display in Hz. This + * value is set to zero when there is no FreeSync support. + */ int max_vfreq ; int pixel_clock_mhz; @@ -668,7 +681,6 @@ struct dm_crtc_state { int crc_skip_count; - bool freesync_timing_changed; bool freesync_vrr_info_changed; bool dsc_force_changed; @@ -705,11 +717,34 @@ struct dm_connector_state { uint64_t pbn; }; +/** + * struct amdgpu_hdmi_vsdb_info - Keep track of the VSDB info + * + * AMDGPU supports FreeSync over HDMI by using the VSDB section, and this + * struct is useful to keep track of the display-specific information about + * FreeSync. + */ struct amdgpu_hdmi_vsdb_info { - unsigned int amd_vsdb_version; /* VSDB version, should be used to determine which VSIF to send */ - bool freesync_supported; /* FreeSync Supported */ - unsigned int min_refresh_rate_hz; /* FreeSync Minimum Refresh Rate in Hz */ - unsigned int max_refresh_rate_hz; /* FreeSync Maximum Refresh Rate in Hz */ + /** + * @amd_vsdb_version: Vendor Specific Data Block Version, should be + * used to determine which Vendor Specific InfoFrame (VSIF) to send. + */ + unsigned int amd_vsdb_version; + + /** + * @freesync_supported: FreeSync Supported. + */ + bool freesync_supported; + + /** + * @min_refresh_rate_hz: FreeSync Minimum Refresh Rate in Hz. + */ + unsigned int min_refresh_rate_hz; + + /** + * @max_refresh_rate_hz: FreeSync Maximum Refresh Rate in Hz + */ + unsigned int max_refresh_rate_hz; }; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c index a71177305bcd..a4cb23d059bd 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c @@ -29,7 +29,9 @@ #include "modules/color/color_gamma.h" #include "basics/conversion.h" -/* +/** + * DOC: overview + * * The DC interface to HW gives us the following color management blocks * per pipe (surface): * @@ -71,8 +73,8 @@ #define MAX_DRM_LUT_VALUE 0xFFFF -/* - * Initialize the color module. +/** + * amdgpu_dm_init_color_mod - Initialize the color module. * * We're not using the full color module, only certain components. * Only call setup functions for components that we need. @@ -82,7 +84,14 @@ void amdgpu_dm_init_color_mod(void) setup_x_points_distribution(); } -/* Extracts the DRM lut and lut size from a blob. */ +/** + * __extract_blob_lut - Extracts the DRM lut and lut size from a blob. + * @blob: DRM color mgmt property blob + * @size: lut size + * + * Returns: + * DRM LUT or NULL + */ static const struct drm_color_lut * __extract_blob_lut(const struct drm_property_blob *blob, uint32_t *size) { @@ -90,13 +99,18 @@ __extract_blob_lut(const struct drm_property_blob *blob, uint32_t *size) return blob ? (struct drm_color_lut *)blob->data : NULL; } -/* - * Return true if the given lut is a linear mapping of values, i.e. it acts - * like a bypass LUT. +/** + * __is_lut_linear - check if the given lut is a linear mapping of values + * @lut: given lut to check values + * @size: lut size * * It is considered linear if the lut represents: - * f(a) = (0xFF00/MAX_COLOR_LUT_ENTRIES-1)a; for integer a in - * [0, MAX_COLOR_LUT_ENTRIES) + * f(a) = (0xFF00/MAX_COLOR_LUT_ENTRIES-1)a; for integer a in [0, + * MAX_COLOR_LUT_ENTRIES) + * + * Returns: + * True if the given lut is a linear mapping of values, i.e. it acts like a + * bypass LUT. Otherwise, false. */ static bool __is_lut_linear(const struct drm_color_lut *lut, uint32_t size) { @@ -119,9 +133,13 @@ static bool __is_lut_linear(const struct drm_color_lut *lut, uint32_t size) return true; } -/* - * Convert the drm_color_lut to dc_gamma. The conversion depends on the size - * of the lut - whether or not it's legacy. +/** + * __drm_lut_to_dc_gamma - convert the drm_color_lut to dc_gamma. + * @lut: DRM lookup table for color conversion + * @gamma: DC gamma to set entries + * @is_legacy: legacy or atomic gamma + * + * The conversion depends on the size of the lut - whether or not it's legacy. */ static void __drm_lut_to_dc_gamma(const struct drm_color_lut *lut, struct dc_gamma *gamma, bool is_legacy) @@ -154,8 +172,11 @@ static void __drm_lut_to_dc_gamma(const struct drm_color_lut *lut, } } -/* - * Converts a DRM CTM to a DC CSC float matrix. +/** + * __drm_ctm_to_dc_matrix - converts a DRM CTM to a DC CSC float matrix + * @ctm: DRM color transformation matrix + * @matrix: DC CSC float matrix + * * The matrix needs to be a 3x4 (12 entry) matrix. */ static void __drm_ctm_to_dc_matrix(const struct drm_color_ctm *ctm, @@ -189,7 +210,18 @@ static void __drm_ctm_to_dc_matrix(const struct drm_color_ctm *ctm, } } -/* Calculates the legacy transfer function - only for sRGB input space. */ +/** + * __set_legacy_tf - Calculates the legacy transfer function + * @func: transfer function + * @lut: lookup table that defines the color space + * @lut_size: size of respective lut + * @has_rom: if ROM can be used for hardcoded curve + * + * Only for sRGB input space + * + * Returns: + * 0 in case of success, -ENOMEM if fails + */ static int __set_legacy_tf(struct dc_transfer_func *func, const struct drm_color_lut *lut, uint32_t lut_size, bool has_rom) @@ -218,7 +250,16 @@ static int __set_legacy_tf(struct dc_transfer_func *func, return res ? 0 : -ENOMEM; } -/* Calculates the output transfer function based on expected input space. */ +/** + * __set_output_tf - calculates the output transfer function based on expected input space. + * @func: transfer function + * @lut: lookup table that defines the color space + * @lut_size: size of respective lut + * @has_rom: if ROM can be used for hardcoded curve + * + * Returns: + * 0 in case of success. -ENOMEM if fails. + */ static int __set_output_tf(struct dc_transfer_func *func, const struct drm_color_lut *lut, uint32_t lut_size, bool has_rom) @@ -262,7 +303,16 @@ static int __set_output_tf(struct dc_transfer_func *func, return res ? 0 : -ENOMEM; } -/* Caculates the input transfer function based on expected input space. */ +/** + * __set_input_tf - calculates the input transfer function based on expected + * input space. + * @func: transfer function + * @lut: lookup table that defines the color space + * @lut_size: size of respective lut. + * + * Returns: + * 0 in case of success. -ENOMEM if fails. + */ static int __set_input_tf(struct dc_transfer_func *func, const struct drm_color_lut *lut, uint32_t lut_size) { @@ -285,13 +335,14 @@ static int __set_input_tf(struct dc_transfer_func *func, } /** - * amdgpu_dm_verify_lut_sizes + * amdgpu_dm_verify_lut_sizes - verifies if DRM luts match the hw supported sizes * @crtc_state: the DRM CRTC state * - * Verifies that the Degamma and Gamma LUTs attached to the |crtc_state| are of - * the expected size. + * Verifies that the Degamma and Gamma LUTs attached to the &crtc_state + * are of the expected size. * - * Returns 0 on success. + * Returns: + * 0 on success. -EINVAL if any lut sizes are invalid. */ int amdgpu_dm_verify_lut_sizes(const struct drm_crtc_state *crtc_state) { @@ -327,9 +378,9 @@ int amdgpu_dm_verify_lut_sizes(const struct drm_crtc_state *crtc_state) * of the HW blocks as long as the CRTC CTM always comes before the * CRTC RGM and after the CRTC DGM. * - * The CRTC RGM block will be placed in the RGM LUT block if it is non-linear. - * The CRTC DGM block will be placed in the DGM LUT block if it is non-linear. - * The CRTC CTM will be placed in the gamut remap block if it is non-linear. + * - The CRTC RGM block will be placed in the RGM LUT block if it is non-linear. + * - The CRTC DGM block will be placed in the DGM LUT block if it is non-linear. + * - The CRTC CTM will be placed in the gamut remap block if it is non-linear. * * The RGM block is typically more fully featured and accurate across * all ASICs - DCE can't support a custom non-linear CRTC DGM. @@ -338,7 +389,8 @@ int amdgpu_dm_verify_lut_sizes(const struct drm_crtc_state *crtc_state) * management at once we have to either restrict the usage of CRTC properties * or blend adjustments together. * - * Returns 0 on success. + * Returns: + * 0 on success. Error code if setup fails. */ int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc) { @@ -393,7 +445,7 @@ int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc) if (r) return r; } else if (has_regamma) { - /* CRTC RGM goes into RGM LUT. */ + /* If atomic regamma, CRTC RGM goes into RGM LUT. */ stream->out_transfer_func->type = TF_TYPE_DISTRIBUTED_POINTS; stream->out_transfer_func->tf = TRANSFER_FUNCTION_LINEAR; @@ -450,9 +502,10 @@ int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc) * * Update the underlying dc_stream_state's input transfer function (ITF) in * preparation for hardware commit. The transfer function used depends on - * the prepartion done on the stream for color management. + * the preparation done on the stream for color management. * - * Returns 0 on success. + * Returns: + * 0 on success. -ENOMEM if mem allocation fails. */ int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc, struct dc_plane_state *dc_plane_state) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index a0154a5f7183..f0b01c8dc4a6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -27,6 +27,7 @@ #include <linux/acpi.h> #include <linux/i2c.h> +#include <drm/drm_atomic.h> #include <drm/drm_probe_helper.h> #include <drm/amdgpu_drm.h> #include <drm/drm_edid.h> @@ -153,41 +154,28 @@ enum dc_edid_status dm_helpers_parse_edid_caps( return result; } -static void get_payload_table( - struct amdgpu_dm_connector *aconnector, - struct dp_mst_stream_allocation_table *proposed_table) +static void +fill_dc_mst_payload_table_from_drm(struct drm_dp_mst_topology_state *mst_state, + struct amdgpu_dm_connector *aconnector, + struct dc_dp_mst_stream_allocation_table *table) { - int i; - struct drm_dp_mst_topology_mgr *mst_mgr = - &aconnector->mst_port->mst_mgr; - - mutex_lock(&mst_mgr->payload_lock); - - proposed_table->stream_count = 0; - - /* number of active streams */ - for (i = 0; i < mst_mgr->max_payloads; i++) { - if (mst_mgr->payloads[i].num_slots == 0) - break; /* end of vcp_id table */ - - ASSERT(mst_mgr->payloads[i].payload_state != - DP_PAYLOAD_DELETE_LOCAL); - - if (mst_mgr->payloads[i].payload_state == DP_PAYLOAD_LOCAL || - mst_mgr->payloads[i].payload_state == - DP_PAYLOAD_REMOTE) { - - struct dp_mst_stream_allocation *sa = - &proposed_table->stream_allocations[ - proposed_table->stream_count]; - - sa->slot_count = mst_mgr->payloads[i].num_slots; - sa->vcp_id = mst_mgr->proposed_vcpis[i]->vcpi; - proposed_table->stream_count++; - } + struct dc_dp_mst_stream_allocation_table new_table = { 0 }; + struct dc_dp_mst_stream_allocation *sa; + struct drm_dp_mst_atomic_payload *payload; + + /* Fill payload info*/ + list_for_each_entry(payload, &mst_state->payloads, next) { + if (payload->delete) + continue; + + sa = &new_table.stream_allocations[new_table.stream_count]; + sa->slot_count = payload->time_slots; + sa->vcp_id = payload->vcpi; + new_table.stream_count++; } - mutex_unlock(&mst_mgr->payload_lock); + /* Overwrite the old table */ + *table = new_table; } void dm_helpers_dp_update_branch_info( @@ -201,15 +189,13 @@ void dm_helpers_dp_update_branch_info( bool dm_helpers_dp_mst_write_payload_allocation_table( struct dc_context *ctx, const struct dc_stream_state *stream, - struct dp_mst_stream_allocation_table *proposed_table, + struct dc_dp_mst_stream_allocation_table *proposed_table, bool enable) { struct amdgpu_dm_connector *aconnector; - struct dm_connector_state *dm_conn_state; + struct drm_dp_mst_topology_state *mst_state; + struct drm_dp_mst_atomic_payload *payload; struct drm_dp_mst_topology_mgr *mst_mgr; - struct drm_dp_mst_port *mst_port; - bool ret; - u8 link_coding_cap = DP_8b_10b_ENCODING; aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context; /* Accessing the connector state is required for vcpi_slots allocation @@ -220,40 +206,21 @@ bool dm_helpers_dp_mst_write_payload_allocation_table( if (!aconnector || !aconnector->mst_port) return false; - dm_conn_state = to_dm_connector_state(aconnector->base.state); - mst_mgr = &aconnector->mst_port->mst_mgr; - - if (!mst_mgr->mst_state) - return false; - - mst_port = aconnector->port; - -#if defined(CONFIG_DRM_AMD_DC_DCN) - link_coding_cap = dc_link_dp_mst_decide_link_encoding_format(aconnector->dc_link); -#endif - - if (enable) { - - ret = drm_dp_mst_allocate_vcpi(mst_mgr, mst_port, - dm_conn_state->pbn, - dm_conn_state->vcpi_slots); - if (!ret) - return false; - - } else { - drm_dp_mst_reset_vcpi_slots(mst_mgr, mst_port); - } + mst_state = to_drm_dp_mst_topology_state(mst_mgr->base.state); /* It's OK for this to fail */ - drm_dp_update_payload_part1(mst_mgr, (link_coding_cap == DP_CAP_ANSI_128B132B) ? 0:1); + payload = drm_atomic_get_mst_payload_state(mst_state, aconnector->port); + if (enable) + drm_dp_add_payload_part1(mst_mgr, mst_state, payload); + else + drm_dp_remove_payload(mst_mgr, mst_state, payload); /* mst_mgr->->payloads are VC payload notify MST branch using DPCD or * AUX message. The sequence is slot 1-63 allocated sequence for each * stream. AMD ASIC stream slot allocation should follow the same * sequence. copy DRM MST allocation to dc */ - - get_payload_table(aconnector, proposed_table); + fill_dc_mst_payload_table_from_drm(mst_state, aconnector, proposed_table); return true; } @@ -310,8 +277,9 @@ bool dm_helpers_dp_mst_send_payload_allocation( bool enable) { struct amdgpu_dm_connector *aconnector; + struct drm_dp_mst_topology_state *mst_state; struct drm_dp_mst_topology_mgr *mst_mgr; - struct drm_dp_mst_port *mst_port; + struct drm_dp_mst_atomic_payload *payload; enum mst_progress_status set_flag = MST_ALLOCATE_NEW_PAYLOAD; enum mst_progress_status clr_flag = MST_CLEAR_ALLOCATED_PAYLOAD; @@ -320,19 +288,16 @@ bool dm_helpers_dp_mst_send_payload_allocation( if (!aconnector || !aconnector->mst_port) return false; - mst_port = aconnector->port; - mst_mgr = &aconnector->mst_port->mst_mgr; + mst_state = to_drm_dp_mst_topology_state(mst_mgr->base.state); - if (!mst_mgr->mst_state) - return false; - + payload = drm_atomic_get_mst_payload_state(mst_state, aconnector->port); if (!enable) { set_flag = MST_CLEAR_ALLOCATED_PAYLOAD; clr_flag = MST_ALLOCATE_NEW_PAYLOAD; } - if (drm_dp_update_payload_part2(mst_mgr)) { + if (enable && drm_dp_add_payload_part2(mst_mgr, mst_state->base.state, payload)) { amdgpu_dm_set_mst_status(&aconnector->mst_status, set_flag, false); } else { @@ -342,9 +307,6 @@ bool dm_helpers_dp_mst_send_payload_allocation( clr_flag, false); } - if (!enable) - drm_dp_mst_deallocate_vcpi(mst_mgr, mst_port); - return true; } @@ -729,8 +691,14 @@ bool dm_helpers_dp_write_dsc_enable( const struct dc_stream_state *stream, bool enable) { - uint8_t enable_dsc = enable ? 1 : 0; + static const uint8_t DSC_DISABLE; + static const uint8_t DSC_DECODING = 0x01; + static const uint8_t DSC_PASSTHROUGH = 0x02; + struct amdgpu_dm_connector *aconnector; + struct drm_dp_mst_port *port; + uint8_t enable_dsc = enable ? DSC_DECODING : DSC_DISABLE; + uint8_t enable_passthrough = enable ? DSC_PASSTHROUGH : DSC_DISABLE; uint8_t ret = 0; if (!stream) @@ -750,8 +718,39 @@ bool dm_helpers_dp_write_dsc_enable( aconnector->dsc_aux, stream, enable_dsc); #endif - ret = drm_dp_dpcd_write(aconnector->dsc_aux, DP_DSC_ENABLE, &enable_dsc, 1); - DC_LOG_DC("Send DSC %s to MST RX\n", enable_dsc ? "enable" : "disable"); + port = aconnector->port; + + if (enable) { + if (port->passthrough_aux) { + ret = drm_dp_dpcd_write(port->passthrough_aux, + DP_DSC_ENABLE, + &enable_passthrough, 1); + DC_LOG_DC("Sent DSC pass-through enable to virtual dpcd port, ret = %u\n", + ret); + } + + ret = drm_dp_dpcd_write(aconnector->dsc_aux, + DP_DSC_ENABLE, &enable_dsc, 1); + DC_LOG_DC("Sent DSC decoding enable to %s port, ret = %u\n", + (port->passthrough_aux) ? "remote RX" : + "virtual dpcd", + ret); + } else { + ret = drm_dp_dpcd_write(aconnector->dsc_aux, + DP_DSC_ENABLE, &enable_dsc, 1); + DC_LOG_DC("Sent DSC decoding disable to %s port, ret = %u\n", + (port->passthrough_aux) ? "remote RX" : + "virtual dpcd", + ret); + + if (port->passthrough_aux) { + ret = drm_dp_dpcd_write(port->passthrough_aux, + DP_DSC_ENABLE, + &enable_passthrough, 1); + DC_LOG_DC("Sent DSC pass-through disable to virtual dpcd port, ret = %u\n", + ret); + } + } } if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT || stream->signal == SIGNAL_TYPE_EDP) { @@ -768,7 +767,7 @@ bool dm_helpers_dp_write_dsc_enable( #endif } - return (ret > 0); + return ret; } bool dm_helpers_is_dp_sink_present(struct dc_link *link) @@ -879,6 +878,34 @@ void dm_helpers_smu_timeout(struct dc_context *ctx, unsigned int msg_id, unsigne //amdgpu_device_gpu_recover(dc_context->driver-context, NULL); } +void dm_helpers_init_panel_settings( + struct dc_context *ctx, + struct dc_panel_config *panel_config, + struct dc_sink *sink) +{ + // Extra Panel Power Sequence + panel_config->pps.extra_t3_ms = sink->edid_caps.panel_patch.extra_t3_ms; + panel_config->pps.extra_t7_ms = sink->edid_caps.panel_patch.extra_t7_ms; + panel_config->pps.extra_delay_backlight_off = sink->edid_caps.panel_patch.extra_delay_backlight_off; + panel_config->pps.extra_post_t7_ms = 0; + panel_config->pps.extra_pre_t11_ms = 0; + panel_config->pps.extra_t12_ms = sink->edid_caps.panel_patch.extra_t12_ms; + panel_config->pps.extra_post_OUI_ms = 0; + // Feature DSC + panel_config->dsc.disable_dsc_edp = false; + panel_config->dsc.force_dsc_edp_policy = 0; +} + +void dm_helpers_override_panel_settings( + struct dc_context *ctx, + struct dc_panel_config *panel_config) +{ + // Feature DSC + if (amdgpu_dc_debug_mask & DC_DISABLE_DSC) { + panel_config->dsc.disable_dsc_edp = true; + } +} + void *dm_helpers_allocate_gpu_mem( struct dc_context *ctx, enum dc_gpu_mem_alloc_type type, diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 2e74ccf7df5b..6ff96b4bdda5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -36,6 +36,7 @@ #include "dm_helpers.h" #include "dc_link_ddc.h" +#include "dc_link_dp.h" #include "ddc_service_types.h" #include "dpcd_defs.h" @@ -447,34 +448,13 @@ dm_dp_mst_detect(struct drm_connector *connector, } static int dm_dp_mst_atomic_check(struct drm_connector *connector, - struct drm_atomic_state *state) + struct drm_atomic_state *state) { - struct drm_connector_state *new_conn_state = - drm_atomic_get_new_connector_state(state, connector); - struct drm_connector_state *old_conn_state = - drm_atomic_get_old_connector_state(state, connector); struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); - struct drm_crtc_state *new_crtc_state; - struct drm_dp_mst_topology_mgr *mst_mgr; - struct drm_dp_mst_port *mst_port; + struct drm_dp_mst_topology_mgr *mst_mgr = &aconnector->mst_port->mst_mgr; + struct drm_dp_mst_port *mst_port = aconnector->port; - mst_port = aconnector->port; - mst_mgr = &aconnector->mst_port->mst_mgr; - - if (!old_conn_state->crtc) - return 0; - - if (new_conn_state->crtc) { - new_crtc_state = drm_atomic_get_new_crtc_state(state, new_conn_state->crtc); - if (!new_crtc_state || - !drm_atomic_crtc_needs_modeset(new_crtc_state) || - new_crtc_state->enable) - return 0; - } - - return drm_dp_atomic_release_vcpi_slots(state, - mst_mgr, - mst_port); + return drm_dp_atomic_release_time_slots(state, mst_mgr, mst_port); } static const struct drm_connector_helper_funcs dm_dp_mst_connector_helper_funcs = { @@ -618,15 +598,8 @@ void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm, dc_link_dp_get_max_link_enc_cap(aconnector->dc_link, &max_link_enc_cap); aconnector->mst_mgr.cbs = &dm_mst_cbs; - drm_dp_mst_topology_mgr_init( - &aconnector->mst_mgr, - adev_to_drm(dm->adev), - &aconnector->dm_dp_aux.aux, - 16, - 4, - max_link_enc_cap.lane_count, - drm_dp_bw_code_to_link_rate(max_link_enc_cap.link_rate), - aconnector->connector_id); + drm_dp_mst_topology_mgr_init(&aconnector->mst_mgr, adev_to_drm(dm->adev), + &aconnector->dm_dp_aux.aux, 16, 4, aconnector->connector_id); drm_connector_attach_dp_subconnector_property(&aconnector->base); } @@ -731,6 +704,7 @@ static int bpp_x16_from_pbn(struct dsc_mst_fairness_params param, int pbn) } static bool increase_dsc_bpp(struct drm_atomic_state *state, + struct drm_dp_mst_topology_state *mst_state, struct dc_link *dc_link, struct dsc_mst_fairness_params *params, struct dsc_mst_fairness_vars *vars, @@ -743,12 +717,9 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state, int min_initial_slack; int next_index; int remaining_to_increase = 0; - int pbn_per_timeslot; int link_timeslots_used; int fair_pbn_alloc; - pbn_per_timeslot = dm_mst_get_pbn_divider(dc_link); - for (i = 0; i < count; i++) { if (vars[i + k].dsc_enabled) { initial_slack[i] = @@ -779,46 +750,43 @@ static bool increase_dsc_bpp(struct drm_atomic_state *state, link_timeslots_used = 0; for (i = 0; i < count; i++) - link_timeslots_used += DIV_ROUND_UP(vars[i + k].pbn, pbn_per_timeslot); + link_timeslots_used += DIV_ROUND_UP(vars[i + k].pbn, mst_state->pbn_div); - fair_pbn_alloc = (63 - link_timeslots_used) / remaining_to_increase * pbn_per_timeslot; + fair_pbn_alloc = + (63 - link_timeslots_used) / remaining_to_increase * mst_state->pbn_div; if (initial_slack[next_index] > fair_pbn_alloc) { vars[next_index].pbn += fair_pbn_alloc; - if (drm_dp_atomic_find_vcpi_slots(state, + if (drm_dp_atomic_find_time_slots(state, params[next_index].port->mgr, params[next_index].port, - vars[next_index].pbn, - pbn_per_timeslot) < 0) + vars[next_index].pbn) < 0) return false; if (!drm_dp_mst_atomic_check(state)) { vars[next_index].bpp_x16 = bpp_x16_from_pbn(params[next_index], vars[next_index].pbn); } else { vars[next_index].pbn -= fair_pbn_alloc; - if (drm_dp_atomic_find_vcpi_slots(state, + if (drm_dp_atomic_find_time_slots(state, params[next_index].port->mgr, params[next_index].port, - vars[next_index].pbn, - pbn_per_timeslot) < 0) + vars[next_index].pbn) < 0) return false; } } else { vars[next_index].pbn += initial_slack[next_index]; - if (drm_dp_atomic_find_vcpi_slots(state, + if (drm_dp_atomic_find_time_slots(state, params[next_index].port->mgr, params[next_index].port, - vars[next_index].pbn, - pbn_per_timeslot) < 0) + vars[next_index].pbn) < 0) return false; if (!drm_dp_mst_atomic_check(state)) { vars[next_index].bpp_x16 = params[next_index].bw_range.max_target_bpp_x16; } else { vars[next_index].pbn -= initial_slack[next_index]; - if (drm_dp_atomic_find_vcpi_slots(state, + if (drm_dp_atomic_find_time_slots(state, params[next_index].port->mgr, params[next_index].port, - vars[next_index].pbn, - pbn_per_timeslot) < 0) + vars[next_index].pbn) < 0) return false; } } @@ -872,11 +840,10 @@ static bool try_disable_dsc(struct drm_atomic_state *state, break; vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps); - if (drm_dp_atomic_find_vcpi_slots(state, + if (drm_dp_atomic_find_time_slots(state, params[next_index].port->mgr, params[next_index].port, - vars[next_index].pbn, - dm_mst_get_pbn_divider(dc_link)) < 0) + vars[next_index].pbn) < 0) return false; if (!drm_dp_mst_atomic_check(state)) { @@ -884,11 +851,10 @@ static bool try_disable_dsc(struct drm_atomic_state *state, vars[next_index].bpp_x16 = 0; } else { vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.max_kbps); - if (drm_dp_atomic_find_vcpi_slots(state, + if (drm_dp_atomic_find_time_slots(state, params[next_index].port->mgr, params[next_index].port, - vars[next_index].pbn, - dm_mst_get_pbn_divider(dc_link)) < 0) + vars[next_index].pbn) < 0) return false; } @@ -902,17 +868,27 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, struct dc_state *dc_state, struct dc_link *dc_link, struct dsc_mst_fairness_vars *vars, + struct drm_dp_mst_topology_mgr *mgr, int *link_vars_start_index) { - int i, k; struct dc_stream_state *stream; struct dsc_mst_fairness_params params[MAX_PIPES]; struct amdgpu_dm_connector *aconnector; + struct drm_dp_mst_topology_state *mst_state = drm_atomic_get_mst_topology_state(state, mgr); int count = 0; + int i, k; bool debugfs_overwrite = false; memset(params, 0, sizeof(params)); + if (IS_ERR(mst_state)) + return false; + + mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link); +#if defined(CONFIG_DRM_AMD_DC_DCN) + drm_dp_mst_update_slots(mst_state, dc_link_dp_mst_decide_link_encoding_format(dc_link)); +#endif + /* Set up params */ for (i = 0; i < dc_state->stream_count; i++) { struct dc_dsc_policy dsc_policy = {0}; @@ -971,11 +947,8 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps); vars[i + k].dsc_enabled = false; vars[i + k].bpp_x16 = 0; - if (drm_dp_atomic_find_vcpi_slots(state, - params[i].port->mgr, - params[i].port, - vars[i + k].pbn, - dm_mst_get_pbn_divider(dc_link)) < 0) + if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port, + vars[i + k].pbn) < 0) return false; } if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) { @@ -989,21 +962,15 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.min_kbps); vars[i + k].dsc_enabled = true; vars[i + k].bpp_x16 = params[i].bw_range.min_target_bpp_x16; - if (drm_dp_atomic_find_vcpi_slots(state, - params[i].port->mgr, - params[i].port, - vars[i + k].pbn, - dm_mst_get_pbn_divider(dc_link)) < 0) + if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr, + params[i].port, vars[i + k].pbn) < 0) return false; } else { vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps); vars[i + k].dsc_enabled = false; vars[i + k].bpp_x16 = 0; - if (drm_dp_atomic_find_vcpi_slots(state, - params[i].port->mgr, - params[i].port, - vars[i + k].pbn, - dm_mst_get_pbn_divider(dc_link)) < 0) + if (drm_dp_atomic_find_time_slots(state, params[i].port->mgr, + params[i].port, vars[i + k].pbn) < 0) return false; } } @@ -1011,7 +978,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, return false; /* Optimize degree of compression */ - if (!increase_dsc_bpp(state, dc_link, params, vars, count, k)) + if (!increase_dsc_bpp(state, mst_state, dc_link, params, vars, count, k)) return false; if (!try_disable_dsc(state, dc_link, params, vars, count, k)) @@ -1157,8 +1124,9 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state, continue; mutex_lock(&aconnector->mst_mgr.lock); - if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, - vars, &link_vars_start_index)) { + if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars, + &aconnector->mst_mgr, + &link_vars_start_index)) { mutex_unlock(&aconnector->mst_mgr.lock); return false; } @@ -1216,10 +1184,8 @@ static bool continue; mutex_lock(&aconnector->mst_mgr.lock); - if (!compute_mst_dsc_configs_for_link(state, - dc_state, - stream->link, - vars, + if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars, + &aconnector->mst_mgr, &link_vars_start_index)) { mutex_unlock(&aconnector->mst_mgr.lock); return false; @@ -1386,19 +1352,90 @@ clean_exit: return (ret == 0); } -#endif +static unsigned int kbps_from_pbn(unsigned int pbn) +{ + unsigned int kbps = pbn; + + kbps *= (1000000 / PEAK_FACTOR_X1000); + kbps *= 8; + kbps *= 54; + kbps /= 64; + + return kbps; +} + +static bool is_dsc_common_config_possible(struct dc_stream_state *stream, + struct dc_dsc_bw_range *bw_range) +{ + struct dc_dsc_policy dsc_policy = {0}; + + dc_dsc_get_policy_for_timing(&stream->timing, 0, &dsc_policy); + dc_dsc_compute_bandwidth_range(stream->sink->ctx->dc->res_pool->dscs[0], + stream->sink->ctx->dc->debug.dsc_min_slice_height_override, + dsc_policy.min_target_bpp * 16, + dsc_policy.max_target_bpp * 16, + &stream->sink->dsc_caps.dsc_dec_caps, + &stream->timing, bw_range); + + return bw_range->max_target_bpp_x16 && bw_range->min_target_bpp_x16; +} +#endif /* CONFIG_DRM_AMD_DC_DCN */ enum dc_status dm_dp_mst_is_port_support_mode( struct amdgpu_dm_connector *aconnector, struct dc_stream_state *stream) { int bpp, pbn, branch_max_throughput_mps = 0; +#if defined(CONFIG_DRM_AMD_DC_DCN) + struct dc_link_settings cur_link_settings; + unsigned int end_to_end_bw_in_kbps = 0; + unsigned int upper_link_bw_in_kbps = 0, down_link_bw_in_kbps = 0; + unsigned int max_compressed_bw_in_kbps = 0; + struct dc_dsc_bw_range bw_range = {0}; - /* check if mode could be supported within fUll_pbn */ - bpp = convert_dc_color_depth_into_bpc(stream->timing.display_color_depth) * 3; - pbn = drm_dp_calc_pbn_mode(stream->timing.pix_clk_100hz / 10, bpp, false); - if (pbn > aconnector->port->full_pbn) - return DC_FAIL_BANDWIDTH_VALIDATE; + /* + * check if the mode could be supported if DSC pass-through is supported + * AND check if there enough bandwidth available to support the mode + * with DSC enabled. + */ + if (is_dsc_common_config_possible(stream, &bw_range) && + aconnector->port->passthrough_aux) { + mutex_lock(&aconnector->mst_mgr.lock); + + cur_link_settings = stream->link->verified_link_cap; + + upper_link_bw_in_kbps = dc_link_bandwidth_kbps(aconnector->dc_link, + &cur_link_settings + ); + down_link_bw_in_kbps = kbps_from_pbn(aconnector->port->full_pbn); + + /* pick the bottleneck */ + end_to_end_bw_in_kbps = min(upper_link_bw_in_kbps, + down_link_bw_in_kbps); + + mutex_unlock(&aconnector->mst_mgr.lock); + + /* + * use the maximum dsc compression bandwidth as the required + * bandwidth for the mode + */ + max_compressed_bw_in_kbps = bw_range.min_kbps; + + if (end_to_end_bw_in_kbps < max_compressed_bw_in_kbps) { + DRM_DEBUG_DRIVER("Mode does not fit into DSC pass-through bandwidth validation\n"); + return DC_FAIL_BANDWIDTH_VALIDATE; + } + } else { +#endif + /* check if mode could be supported within full_pbn */ + bpp = convert_dc_color_depth_into_bpc(stream->timing.display_color_depth) * 3; + pbn = drm_dp_calc_pbn_mode(stream->timing.pix_clk_100hz / 10, bpp, false); + + if (pbn > aconnector->port->full_pbn) + return DC_FAIL_BANDWIDTH_VALIDATE; +#if defined(CONFIG_DRM_AMD_DC_DCN) + } +#endif /* check is mst dsc output bandwidth branch_overall_throughput_0_mps */ switch (stream->timing.pixel_encoding) { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c index 987bde4dca3d..dfd3be49eac8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c @@ -1563,7 +1563,7 @@ int dm_drm_plane_get_property(struct drm_plane *plane, static const struct drm_plane_funcs dm_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, - .destroy = drm_primary_helper_destroy, + .destroy = drm_plane_helper_destroy, .reset = dm_drm_plane_reset, .atomic_duplicate_state = dm_drm_plane_duplicate_state, .atomic_destroy_state = dm_drm_plane_destroy_state, diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c index c8da18e45b0e..8ca10ab3dfc1 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c @@ -170,7 +170,13 @@ bool amdgpu_dm_psr_enable(struct dc_stream_state *stream) &stream, 1, ¶ms); - power_opt |= psr_power_opt_z10_static_screen; + /* + * Only enable static-screen optimizations for PSR1. For PSR SU, this + * causes vstartup interrupt issues, used by amdgpu_dm to send vblank + * events. + */ + if (link->psr_settings.psr_version < DC_PSR_VERSION_SU_1) + power_opt |= psr_power_opt_z10_static_screen; return dc_link_set_psr_allow_active(link, &psr_enable, false, false, &power_opt); } diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 09fbb7ad5362..53b077b40d72 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -24,6 +24,7 @@ */ #include "dm_services.h" +#include "core_types.h" #include "ObjectID.h" #include "atomfirmware.h" @@ -44,25 +45,6 @@ #include "bios_parser_common.h" -/* Temporarily add in defines until ObjectID.h patch is updated in a few days */ -#ifndef GENERIC_OBJECT_ID_BRACKET_LAYOUT -#define GENERIC_OBJECT_ID_BRACKET_LAYOUT 0x05 -#endif /* GENERIC_OBJECT_ID_BRACKET_LAYOUT */ - -#ifndef GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID1 -#define GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_GENERIC << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - GENERIC_OBJECT_ID_BRACKET_LAYOUT << OBJECT_ID_SHIFT) -#endif /* GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID1 */ - -#ifndef GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID2 -#define GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID2 \ - (GRAPH_OBJECT_TYPE_GENERIC << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ - GENERIC_OBJECT_ID_BRACKET_LAYOUT << OBJECT_ID_SHIFT) -#endif /* GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID2 */ - #define DC_LOGGER \ bp->base.ctx->logger @@ -868,6 +850,8 @@ static enum bp_result get_ss_info_v4_1( disp_cntl_tbl->dvi_ss_rate_10hz * 10; if (disp_cntl_tbl->dvi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) ss_info->type.CENTER_MODE = true; + + DC_LOG_BIOS("AS_SIGNAL_TYPE_DVI ss_percentage: %d\n", ss_info->spread_spectrum_percentage); break; case AS_SIGNAL_TYPE_HDMI: ss_info->spread_spectrum_percentage = @@ -876,6 +860,8 @@ static enum bp_result get_ss_info_v4_1( disp_cntl_tbl->hdmi_ss_rate_10hz * 10; if (disp_cntl_tbl->hdmi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) ss_info->type.CENTER_MODE = true; + + DC_LOG_BIOS("AS_SIGNAL_TYPE_HDMI ss_percentage: %d\n", ss_info->spread_spectrum_percentage); break; /* TODO LVDS not support anymore? */ case AS_SIGNAL_TYPE_DISPLAY_PORT: @@ -885,6 +871,8 @@ static enum bp_result get_ss_info_v4_1( disp_cntl_tbl->dp_ss_rate_10hz * 10; if (disp_cntl_tbl->dp_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) ss_info->type.CENTER_MODE = true; + + DC_LOG_BIOS("AS_SIGNAL_TYPE_DISPLAY_PORT ss_percentage: %d\n", ss_info->spread_spectrum_percentage); break; case AS_SIGNAL_TYPE_GPU_PLL: /* atom_firmware: DAL only get data from dce_info table. @@ -898,13 +886,15 @@ static enum bp_result get_ss_info_v4_1( DATA_TABLES(smu_info)); if (!smu_info) return BP_RESULT_BADBIOSTABLE; - + DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info->gpuclk_ss_percentage); ss_info->spread_spectrum_percentage = smu_info->waflclk_ss_percentage; ss_info->spread_spectrum_range = smu_info->gpuclk_ss_rate_10hz * 10; if (smu_info->waflclk_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) ss_info->type.CENTER_MODE = true; + + DC_LOG_BIOS("AS_SIGNAL_TYPE_XGMI ss_percentage: %d\n", ss_info->spread_spectrum_percentage); break; default: result = BP_RESULT_UNSUPPORTED; @@ -941,6 +931,7 @@ static enum bp_result get_ss_info_v4_2( if (!smu_info) return BP_RESULT_BADBIOSTABLE; + DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info->gpuclk_ss_percentage); ss_info->type.STEP_AND_DELAY_INFO = false; ss_info->spread_percentage_divider = 1000; /* BIOS no longer uses target clock. Always enable for now */ @@ -954,6 +945,8 @@ static enum bp_result get_ss_info_v4_2( disp_cntl_tbl->dvi_ss_rate_10hz * 10; if (disp_cntl_tbl->dvi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) ss_info->type.CENTER_MODE = true; + + DC_LOG_BIOS("AS_SIGNAL_TYPE_DVI ss_percentage: %d\n", ss_info->spread_spectrum_percentage); break; case AS_SIGNAL_TYPE_HDMI: ss_info->spread_spectrum_percentage = @@ -962,6 +955,8 @@ static enum bp_result get_ss_info_v4_2( disp_cntl_tbl->hdmi_ss_rate_10hz * 10; if (disp_cntl_tbl->hdmi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) ss_info->type.CENTER_MODE = true; + + DC_LOG_BIOS("AS_SIGNAL_TYPE_HDMI ss_percentage: %d\n", ss_info->spread_spectrum_percentage); break; /* TODO LVDS not support anymore? */ case AS_SIGNAL_TYPE_DISPLAY_PORT: @@ -971,6 +966,8 @@ static enum bp_result get_ss_info_v4_2( smu_info->gpuclk_ss_rate_10hz * 10; if (smu_info->gpuclk_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) ss_info->type.CENTER_MODE = true; + + DC_LOG_BIOS("AS_SIGNAL_TYPE_DISPLAY_PORT ss_percentage: %d\n", ss_info->spread_spectrum_percentage); break; case AS_SIGNAL_TYPE_GPU_PLL: /* atom_firmware: DAL only get data from dce_info table. @@ -1019,6 +1016,8 @@ static enum bp_result get_ss_info_v4_5( disp_cntl_tbl->dvi_ss_rate_10hz * 10; if (disp_cntl_tbl->dvi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) ss_info->type.CENTER_MODE = true; + + DC_LOG_BIOS("AS_SIGNAL_TYPE_DVI ss_percentage: %d\n", ss_info->spread_spectrum_percentage); break; case AS_SIGNAL_TYPE_HDMI: ss_info->spread_spectrum_percentage = @@ -1027,6 +1026,8 @@ static enum bp_result get_ss_info_v4_5( disp_cntl_tbl->hdmi_ss_rate_10hz * 10; if (disp_cntl_tbl->hdmi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) ss_info->type.CENTER_MODE = true; + + DC_LOG_BIOS("AS_SIGNAL_TYPE_HDMI ss_percentage: %d\n", ss_info->spread_spectrum_percentage); break; case AS_SIGNAL_TYPE_DISPLAY_PORT: ss_info->spread_spectrum_percentage = @@ -1035,6 +1036,8 @@ static enum bp_result get_ss_info_v4_5( disp_cntl_tbl->dp_ss_rate_10hz * 10; if (disp_cntl_tbl->dp_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) ss_info->type.CENTER_MODE = true; + + DC_LOG_BIOS("AS_SIGNAL_TYPE_DISPLAY_PORT ss_percentage: %d\n", ss_info->spread_spectrum_percentage); break; case AS_SIGNAL_TYPE_GPU_PLL: /* atom_smu_info_v4_0 does not have fields for SS for SMU Display PLL anymore. @@ -1372,7 +1375,7 @@ static enum bp_result bios_parser_get_lttpr_interop( default: break; } - + DC_LOG_BIOS("DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE: %d tbl_revision.major = %d tbl_revision.minor = %d\n", *dce_caps, tbl_revision.major, tbl_revision.minor); return result; } @@ -1388,6 +1391,7 @@ static enum bp_result bios_parser_get_lttpr_caps( if (!DATA_TABLES(dce_info)) return BP_RESULT_UNSUPPORTED; + *dce_caps = 0; header = GET_IMAGE(struct atom_common_table_header, DATA_TABLES(dce_info)); get_atom_data_table_revision(header, &tbl_revision); @@ -1421,7 +1425,11 @@ static enum bp_result bios_parser_get_lttpr_caps( default: break; } - + DC_LOG_BIOS("DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE: %d tbl_revision.major = %d tbl_revision.minor = %d\n", *dce_caps, tbl_revision.major, tbl_revision.minor); + if (dcb->ctx->dc->config.force_bios_enable_lttpr && *dce_caps == 0) { + *dce_caps = 1; + DC_LOG_BIOS("DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE: forced enabled"); + } return result; } @@ -1859,7 +1867,7 @@ static enum bp_result get_firmware_info_v3_2( /* Vega12 */ smu_info_v3_2 = GET_IMAGE(struct atom_smu_info_v3_2, DATA_TABLES(smu_info)); - + DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info_v3_2->gpuclk_ss_percentage); if (!smu_info_v3_2) return BP_RESULT_BADBIOSTABLE; @@ -1868,7 +1876,7 @@ static enum bp_result get_firmware_info_v3_2( /* Vega20 */ smu_info_v3_3 = GET_IMAGE(struct atom_smu_info_v3_3, DATA_TABLES(smu_info)); - + DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info_v3_3->gpuclk_ss_percentage); if (!smu_info_v3_3) return BP_RESULT_BADBIOSTABLE; @@ -2010,7 +2018,7 @@ static enum bp_result get_firmware_info_v3_4( if (!smu_info_v3_5) return BP_RESULT_BADBIOSTABLE; - + DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info_v3_5->gpuclk_ss_percentage); info->default_engine_clk = smu_info_v3_5->bootup_dcefclk_10khz * 10; break; @@ -2416,6 +2424,7 @@ static enum bp_result get_integrated_info_v11( info_v11 = GET_IMAGE(struct atom_integrated_system_info_v1_11, DATA_TABLES(integratedsysteminfo)); + DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v11->gpuclk_ss_percentage); if (info_v11 == NULL) return BP_RESULT_BADBIOSTABLE; @@ -2630,6 +2639,7 @@ static enum bp_result get_integrated_info_v2_1( info_v2_1 = GET_IMAGE(struct atom_integrated_system_info_v2_1, DATA_TABLES(integratedsysteminfo)); + DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v2_1->gpuclk_ss_percentage); if (info_v2_1 == NULL) return BP_RESULT_BADBIOSTABLE; @@ -2791,6 +2801,8 @@ static enum bp_result get_integrated_info_v2_2( info_v2_2 = GET_IMAGE(struct atom_integrated_system_info_v2_2, DATA_TABLES(integratedsysteminfo)); + DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v2_2->gpuclk_ss_percentage); + if (info_v2_2 == NULL) return BP_RESULT_BADBIOSTABLE; @@ -2942,6 +2954,27 @@ static enum bp_result construct_integrated_info( default: return result; } + if (result == BP_RESULT_OK) { + + DC_LOG_BIOS("edp1:\n" + "\tedp_pwr_on_off_delay = %d\n" + "\tedp_pwr_on_vary_bl_to_blon = %d\n" + "\tedp_pwr_down_bloff_to_vary_bloff = %d\n" + "\tedp_bootup_bl_level = %d\n", + info->edp1_info.edp_pwr_on_off_delay, + info->edp1_info.edp_pwr_on_vary_bl_to_blon, + info->edp1_info.edp_pwr_down_bloff_to_vary_bloff, + info->edp1_info.edp_bootup_bl_level); + DC_LOG_BIOS("edp2:\n" + "\tedp_pwr_on_off_delayv = %d\n" + "\tedp_pwr_on_vary_bl_to_blon = %d\n" + "\tedp_pwr_down_bloff_to_vary_bloff = %d\n" + "\tedp_bootup_bl_level = %d\n", + info->edp2_info.edp_pwr_on_off_delay, + info->edp2_info.edp_pwr_on_vary_bl_to_blon, + info->edp2_info.edp_pwr_down_bloff_to_vary_bloff, + info->edp2_info.edp_bootup_bl_level); + } } if (result != BP_RESULT_OK) @@ -2967,13 +3000,22 @@ static enum bp_result construct_integrated_info( info->ext_disp_conn_info.path[i].ext_encoder_obj_id.id, info->ext_disp_conn_info.path[i].caps ); + if (info->ext_disp_conn_info.path[i].caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) + DC_LOG_BIOS("BIOS EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN on path %d\n", i); + else if (bp->base.ctx->dc->config.force_bios_fixed_vs) { + info->ext_disp_conn_info.path[i].caps |= EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN; + DC_LOG_BIOS("driver forced EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN on path %d\n", i); + } } - // Log the Checksum and Voltage Swing DC_LOG_BIOS("Integrated info table CHECKSUM: %d\n" "Integrated info table FIX_DP_VOLTAGE_SWING: %d\n", info->ext_disp_conn_info.checksum, info->ext_disp_conn_info.fixdpvoltageswing); + if (bp->base.ctx->dc->config.force_bios_fixed_vs && info->ext_disp_conn_info.fixdpvoltageswing == 0) { + info->ext_disp_conn_info.fixdpvoltageswing = bp->base.ctx->dc->config.force_bios_fixed_vs & 0xF; + DC_LOG_BIOS("driver forced fixdpvoltageswing = %d\n", info->ext_disp_conn_info.fixdpvoltageswing); + } } /* Sort voltage table from low to high*/ for (i = 1; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { @@ -3319,6 +3361,7 @@ static enum bp_result bios_get_board_layout_info( struct bios_parser *bp; static enum bp_result record_result; + unsigned int max_slots; const unsigned int slot_index_to_vbios_id[MAX_BOARD_SLOTS] = { GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID1, @@ -3335,8 +3378,14 @@ static enum bp_result bios_get_board_layout_info( } board_layout_info->num_of_slots = 0; + max_slots = MAX_BOARD_SLOTS; + + // Assume single slot on v1_5 + if (bp->object_info_tbl.revision.minor == 5) { + max_slots = 1; + } - for (i = 0; i < MAX_BOARD_SLOTS; ++i) { + for (i = 0; i < max_slots; ++i) { record_result = get_bracket_layout_record(dcb, slot_index_to_vbios_id[i], &board_layout_info->slots[i]); diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c index 23a299c929a1..c1eaf571407a 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c @@ -48,6 +48,11 @@ #include "dc_dmub_srv.h" +#include "logger_types.h" +#undef DC_LOGGER +#define DC_LOGGER \ + clk_mgr->base.base.ctx->logger + #include "yellow_carp_offset.h" #define regCLK1_CLK_PLL_REQ 0x0237 @@ -738,8 +743,49 @@ void dcn31_clk_mgr_construct( clk_mgr->base.base.bw_params = &dcn31_bw_params; if (clk_mgr->base.base.ctx->dc->debug.pstate_enabled) { + int i; + dcn31_get_dpm_table_from_smu(&clk_mgr->base, &smu_dpm_clks); + DC_LOG_SMU("NumDcfClkLevelsEnabled: %d\n" + "NumDispClkLevelsEnabled: %d\n" + "NumSocClkLevelsEnabled: %d\n" + "VcnClkLevelsEnabled: %d\n" + "NumDfPst atesEnabled: %d\n" + "MinGfxClk: %d\n" + "MaxGfxClk: %d\n", + smu_dpm_clks.dpm_clks->NumDcfClkLevelsEnabled, + smu_dpm_clks.dpm_clks->NumDispClkLevelsEnabled, + smu_dpm_clks.dpm_clks->NumSocClkLevelsEnabled, + smu_dpm_clks.dpm_clks->VcnClkLevelsEnabled, + smu_dpm_clks.dpm_clks->NumDfPstatesEnabled, + smu_dpm_clks.dpm_clks->MinGfxClk, + smu_dpm_clks.dpm_clks->MaxGfxClk); + for (i = 0; i < smu_dpm_clks.dpm_clks->NumDcfClkLevelsEnabled; i++) { + DC_LOG_SMU("smu_dpm_clks.dpm_clks->DcfClocks[%d] = %d\n", + i, + smu_dpm_clks.dpm_clks->DcfClocks[i]); + } + for (i = 0; i < smu_dpm_clks.dpm_clks->NumDispClkLevelsEnabled; i++) { + DC_LOG_SMU("smu_dpm_clks.dpm_clks->DispClocks[%d] = %d\n", + i, smu_dpm_clks.dpm_clks->DispClocks[i]); + } + for (i = 0; i < smu_dpm_clks.dpm_clks->NumSocClkLevelsEnabled; i++) { + DC_LOG_SMU("smu_dpm_clks.dpm_clks->SocClocks[%d] = %d\n", + i, smu_dpm_clks.dpm_clks->SocClocks[i]); + } + for (i = 0; i < NUM_SOC_VOLTAGE_LEVELS; i++) + DC_LOG_SMU("smu_dpm_clks.dpm_clks->SocVoltage[%d] = %d\n", + i, smu_dpm_clks.dpm_clks->SocVoltage[i]); + + for (i = 0; i < NUM_DF_PSTATE_LEVELS; i++) { + DC_LOG_SMU("smu_dpm_clks.dpm_clks.DfPstateTable[%d].FClk = %d\n" + "smu_dpm_clks.dpm_clks->DfPstateTable[%d].MemClk= %d\n" + "smu_dpm_clks.dpm_clks->DfPstateTable[%d].Voltage = %d\n", + i, smu_dpm_clks.dpm_clks->DfPstateTable[i].FClk, + i, smu_dpm_clks.dpm_clks->DfPstateTable[i].MemClk, + i, smu_dpm_clks.dpm_clks->DfPstateTable[i].Voltage); + } if (ctx->dc_bios && ctx->dc_bios->integrated_info) { dcn31_clk_mgr_helper_populate_bw_params( &clk_mgr->base, diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c index 8559dcd80af0..1131c6d73f6c 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c @@ -51,6 +51,13 @@ #include "dc_link_dp.h" #include "dcn314_smu.h" + +#include "logger_types.h" +#undef DC_LOGGER +#define DC_LOGGER \ + clk_mgr->base.base.ctx->logger + + #define MAX_INSTANCE 7 #define MAX_SEGMENT 8 @@ -130,11 +137,20 @@ static void dcn314_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state if (pipe->top_pipe || pipe->prev_odm_pipe) continue; if (pipe->stream && (pipe->stream->dpms_off || dc_is_virtual_signal(pipe->stream->signal))) { + struct stream_encoder *stream_enc = pipe->stream_res.stream_enc; + if (disable) { + if (stream_enc && stream_enc->funcs->disable_fifo) + pipe->stream_res.stream_enc->funcs->disable_fifo(stream_enc); + pipe->stream_res.tg->funcs->immediate_disable_crtc(pipe->stream_res.tg); reset_sync_context_for_pipe(dc, context, i); - } else + } else { pipe->stream_res.tg->funcs->enable_crtc(pipe->stream_res.tg); + + if (stream_enc && stream_enc->funcs->enable_fifo) + pipe->stream_res.stream_enc->funcs->enable_fifo(stream_enc); + } } } } @@ -614,7 +630,7 @@ static void dcn314_clk_mgr_helper_populate_bw_params(struct clk_mgr_internal *cl bw_params->clk_table.entries[i].dppclk_mhz = max_dppclk; bw_params->clk_table.entries[i].wck_ratio = convert_wck_ratio( clock_table->DfPstateTable[min_pstate].WckRatio); - }; + } /* Make sure to include at least one entry at highest pstate */ if (max_pstate != min_pstate || i == 0) { @@ -777,7 +793,48 @@ void dcn314_clk_mgr_construct( clk_mgr->base.base.bw_params = &dcn314_bw_params; if (clk_mgr->base.base.ctx->dc->debug.pstate_enabled) { + int i; + dcn314_get_dpm_table_from_smu(&clk_mgr->base, &smu_dpm_clks); + DC_LOG_SMU("NumDcfClkLevelsEnabled: %d\n" + "NumDispClkLevelsEnabled: %d\n" + "NumSocClkLevelsEnabled: %d\n" + "VcnClkLevelsEnabled: %d\n" + "NumDfPst atesEnabled: %d\n" + "MinGfxClk: %d\n" + "MaxGfxClk: %d\n", + smu_dpm_clks.dpm_clks->NumDcfClkLevelsEnabled, + smu_dpm_clks.dpm_clks->NumDispClkLevelsEnabled, + smu_dpm_clks.dpm_clks->NumSocClkLevelsEnabled, + smu_dpm_clks.dpm_clks->VcnClkLevelsEnabled, + smu_dpm_clks.dpm_clks->NumDfPstatesEnabled, + smu_dpm_clks.dpm_clks->MinGfxClk, + smu_dpm_clks.dpm_clks->MaxGfxClk); + for (i = 0; i < smu_dpm_clks.dpm_clks->NumDcfClkLevelsEnabled; i++) { + DC_LOG_SMU("smu_dpm_clks.dpm_clks->DcfClocks[%d] = %d\n", + i, + smu_dpm_clks.dpm_clks->DcfClocks[i]); + } + for (i = 0; i < smu_dpm_clks.dpm_clks->NumDispClkLevelsEnabled; i++) { + DC_LOG_SMU("smu_dpm_clks.dpm_clks->DispClocks[%d] = %d\n", + i, smu_dpm_clks.dpm_clks->DispClocks[i]); + } + for (i = 0; i < smu_dpm_clks.dpm_clks->NumSocClkLevelsEnabled; i++) { + DC_LOG_SMU("smu_dpm_clks.dpm_clks->SocClocks[%d] = %d\n", + i, smu_dpm_clks.dpm_clks->SocClocks[i]); + } + for (i = 0; i < NUM_SOC_VOLTAGE_LEVELS; i++) + DC_LOG_SMU("smu_dpm_clks.dpm_clks->SocVoltage[%d] = %d\n", + i, smu_dpm_clks.dpm_clks->SocVoltage[i]); + + for (i = 0; i < NUM_DF_PSTATE_LEVELS; i++) { + DC_LOG_SMU("smu_dpm_clks.dpm_clks.DfPstateTable[%d].FClk = %d\n" + "smu_dpm_clks.dpm_clks->DfPstateTable[%d].MemClk= %d\n" + "smu_dpm_clks.dpm_clks->DfPstateTable[%d].Voltage = %d\n", + i, smu_dpm_clks.dpm_clks->DfPstateTable[i].FClk, + i, smu_dpm_clks.dpm_clks->DfPstateTable[i].MemClk, + i, smu_dpm_clks.dpm_clks->DfPstateTable[i].Voltage); + } if (ctx->dc_bios && ctx->dc_bios->integrated_info && ctx->dc->config.use_default_clock_table == false) { dcn314_clk_mgr_helper_populate_bw_params( diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c index 98ad8e0fd2d8..893991a0eb97 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c @@ -41,6 +41,11 @@ #include "dc_dmub_srv.h" +#include "logger_types.h" +#undef DC_LOGGER +#define DC_LOGGER \ + clk_mgr->base.base.ctx->logger + #include "dc_link_dp.h" #define TO_CLK_MGR_DCN315(clk_mgr)\ @@ -514,7 +519,7 @@ static void dcn315_clk_mgr_helper_populate_bw_params( bw_params->clk_table.entries[i].dispclk_mhz = clock_table->DispClocks[i]; bw_params->clk_table.entries[i].dppclk_mhz = clock_table->DppClocks[i]; bw_params->clk_table.entries[i].wck_ratio = 1; - }; + } /* Make sure to include at least one entry and highest pstate */ if (max_pstate != min_pstate || i == 0) { @@ -672,7 +677,48 @@ void dcn315_clk_mgr_construct( clk_mgr->base.base.bw_params = &dcn315_bw_params; if (clk_mgr->base.base.ctx->dc->debug.pstate_enabled) { + int i; + dcn315_get_dpm_table_from_smu(&clk_mgr->base, &smu_dpm_clks); + DC_LOG_SMU("NumDcfClkLevelsEnabled: %d\n" + "NumDispClkLevelsEnabled: %d\n" + "NumSocClkLevelsEnabled: %d\n" + "VcnClkLevelsEnabled: %d\n" + "NumDfPst atesEnabled: %d\n" + "MinGfxClk: %d\n" + "MaxGfxClk: %d\n", + smu_dpm_clks.dpm_clks->NumDcfClkLevelsEnabled, + smu_dpm_clks.dpm_clks->NumDispClkLevelsEnabled, + smu_dpm_clks.dpm_clks->NumSocClkLevelsEnabled, + smu_dpm_clks.dpm_clks->VcnClkLevelsEnabled, + smu_dpm_clks.dpm_clks->NumDfPstatesEnabled, + smu_dpm_clks.dpm_clks->MinGfxClk, + smu_dpm_clks.dpm_clks->MaxGfxClk); + for (i = 0; i < smu_dpm_clks.dpm_clks->NumDcfClkLevelsEnabled; i++) { + DC_LOG_SMU("smu_dpm_clks.dpm_clks->DcfClocks[%d] = %d\n", + i, + smu_dpm_clks.dpm_clks->DcfClocks[i]); + } + for (i = 0; i < smu_dpm_clks.dpm_clks->NumDispClkLevelsEnabled; i++) { + DC_LOG_SMU("smu_dpm_clks.dpm_clks->DispClocks[%d] = %d\n", + i, smu_dpm_clks.dpm_clks->DispClocks[i]); + } + for (i = 0; i < smu_dpm_clks.dpm_clks->NumSocClkLevelsEnabled; i++) { + DC_LOG_SMU("smu_dpm_clks.dpm_clks->SocClocks[%d] = %d\n", + i, smu_dpm_clks.dpm_clks->SocClocks[i]); + } + for (i = 0; i < NUM_SOC_VOLTAGE_LEVELS; i++) + DC_LOG_SMU("smu_dpm_clks.dpm_clks->SocVoltage[%d] = %d\n", + i, smu_dpm_clks.dpm_clks->SocVoltage[i]); + + for (i = 0; i < NUM_DF_PSTATE_LEVELS; i++) { + DC_LOG_SMU("smu_dpm_clks.dpm_clks.DfPstateTable[%d].FClk = %d\n" + "smu_dpm_clks.dpm_clks->DfPstateTable[%d].MemClk= %d\n" + "smu_dpm_clks.dpm_clks->DfPstateTable[%d].Voltage = %d\n", + i, smu_dpm_clks.dpm_clks->DfPstateTable[i].FClk, + i, smu_dpm_clks.dpm_clks->DfPstateTable[i].MemClk, + i, smu_dpm_clks.dpm_clks->DfPstateTable[i].Voltage); + } if (ctx->dc_bios && ctx->dc_bios->integrated_info) { dcn315_clk_mgr_helper_populate_bw_params( diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c index c6785969eb1a..f0f3f66629cc 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c @@ -156,12 +156,14 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base) { struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); unsigned int num_levels; + unsigned int num_dcfclk_levels, num_dtbclk_levels, num_dispclk_levels; memset(&(clk_mgr_base->clks), 0, sizeof(struct dc_clocks)); clk_mgr_base->clks.p_state_change_support = true; clk_mgr_base->clks.prev_p_state_change_support = true; clk_mgr_base->clks.fclk_prev_p_state_change_support = true; clk_mgr->smu_present = false; + clk_mgr->dpm_present = false; if (!clk_mgr_base->bw_params) return; @@ -179,6 +181,7 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base) dcn32_init_single_clock(clk_mgr, PPCLK_DCFCLK, &clk_mgr_base->bw_params->clk_table.entries[0].dcfclk_mhz, &num_levels); + num_dcfclk_levels = num_levels; /* SOCCLK */ dcn32_init_single_clock(clk_mgr, PPCLK_SOCCLK, @@ -189,11 +192,16 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base) dcn32_init_single_clock(clk_mgr, PPCLK_DTBCLK, &clk_mgr_base->bw_params->clk_table.entries[0].dtbclk_mhz, &num_levels); + num_dtbclk_levels = num_levels; /* DISPCLK */ dcn32_init_single_clock(clk_mgr, PPCLK_DISPCLK, &clk_mgr_base->bw_params->clk_table.entries[0].dispclk_mhz, &num_levels); + num_dispclk_levels = num_levels; + + if (num_dcfclk_levels && num_dtbclk_levels && num_dispclk_levels) + clk_mgr->dpm_present = true; if (clk_mgr_base->ctx->dc->debug.min_disp_clk_khz) { unsigned int i; @@ -658,6 +666,12 @@ static void dcn32_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base) &num_levels); clk_mgr_base->bw_params->clk_table.num_entries = num_levels ? num_levels : 1; + if (clk_mgr->dpm_present && !num_levels) + clk_mgr->dpm_present = false; + + if (!clk_mgr->dpm_present) + dcn32_patch_dpm_table(clk_mgr_base->bw_params); + DC_FP_START(); /* Refresh bounding box */ clk_mgr_base->ctx->dc->res_pool->funcs->update_bw_bounding_box( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index fb22c3d70528..258ba5a872b1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -401,6 +401,9 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc, { int i; + if (memcmp(adjust, &stream->adjust, sizeof(struct dc_crtc_timing_adjust)) == 0) + return true; + stream->adjust.v_total_max = adjust->v_total_max; stream->adjust.v_total_mid = adjust->v_total_mid; stream->adjust.v_total_mid_frame_num = adjust->v_total_mid_frame_num; @@ -638,14 +641,17 @@ bool dc_stream_configure_crc(struct dc *dc, struct dc_stream_state *stream, /** * dc_stream_get_crc() - Get CRC values for the given stream. - * @dc: DC object + * + * @dc: DC object. * @stream: The DC stream state of the stream to get CRCs from. - * @r_cr: CRC value for the first of the 3 channels stored here. - * @g_y: CRC value for the second of the 3 channels stored here. - * @b_cb: CRC value for the third of the 3 channels stored here. + * @r_cr: CRC value for the red component. + * @g_y: CRC value for the green component. + * @b_cb: CRC value for the blue component. * * dc_stream_configure_crc needs to be called beforehand to enable CRCs. - * Return false if stream is not found, or if CRCs are not enabled. + * + * Return: + * false if stream is not found, or if CRCs are not enabled. */ bool dc_stream_get_crc(struct dc *dc, struct dc_stream_state *stream, uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb) @@ -1195,7 +1201,7 @@ static void wait_for_no_pipes_pending(struct dc *dc, struct dc_state *context) int count = 0; struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - if (!pipe->plane_state) + if (!pipe->plane_state || pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) continue; /* Timeout 100 ms */ @@ -1744,6 +1750,9 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c context->stream_count == 0) dc->hwss.prepare_bandwidth(dc, context); + if (dc->debug.enable_double_buffered_dsc_pg_support) + dc->hwss.update_dsc_pg(dc, context, false); + disable_dangling_plane(dc, context); /* re-program planes for existing stream, in case we need to * free up plane resource for later use @@ -1834,6 +1843,9 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c dc->hwss.optimize_bandwidth(dc, context); } + if (dc->debug.enable_double_buffered_dsc_pg_support) + dc->hwss.update_dsc_pg(dc, context, true); + if (dc->ctx->dce_version >= DCE_VERSION_MAX) TRACE_DCN_CLOCK_STATE(&context->bw_ctx.bw.dcn.clk); else @@ -1997,6 +2009,9 @@ void dc_post_update_surfaces_to_stream(struct dc *dc) dc->hwss.optimize_bandwidth(dc, context); + if (dc->debug.enable_double_buffered_dsc_pg_support) + dc->hwss.update_dsc_pg(dc, context, true); + dc->optimized_required = false; dc->wm_optimized_required = false; } @@ -2316,9 +2331,13 @@ static enum surface_update_type det_surface_update(const struct dc *dc, type = get_scaling_info_update_type(u); elevate_update_type(&overall_type, type); - if (u->flip_addr) + if (u->flip_addr) { update_flags->bits.addr_update = 1; - + if (u->flip_addr->address.tmz_surface != u->surface->address.tmz_surface) { + update_flags->bits.tmz_changed = 1; + elevate_update_type(&overall_type, UPDATE_TYPE_FULL); + } + } if (u->in_transfer_func) update_flags->bits.in_transfer_func_change = 1; @@ -2753,11 +2772,8 @@ static void copy_stream_update_to_stream(struct dc *dc, if (update->abm_level) stream->abm_level = *update->abm_level; - if (update->periodic_interrupt0) - stream->periodic_interrupt0 = *update->periodic_interrupt0; - - if (update->periodic_interrupt1) - stream->periodic_interrupt1 = *update->periodic_interrupt1; + if (update->periodic_interrupt) + stream->periodic_interrupt = *update->periodic_interrupt; if (update->gamut_remap) stream->gamut_remap_matrix = *update->gamut_remap; @@ -2842,16 +2858,6 @@ static void copy_stream_update_to_stream(struct dc *dc, } } -void dc_reset_state(struct dc *dc, struct dc_state *context) -{ - dc_resource_state_destruct(context); - - /* clear the structure, but don't reset the reference count */ - memset(context, 0, offsetof(struct dc_state, refcount)); - - init_state(dc, context); -} - static bool update_planes_and_stream_state(struct dc *dc, struct dc_surface_update *srf_updates, int surface_count, struct dc_stream_state *stream, @@ -2987,13 +2993,8 @@ static void commit_planes_do_stream_update(struct dc *dc, if (!pipe_ctx->top_pipe && !pipe_ctx->prev_odm_pipe && pipe_ctx->stream == stream) { - if (stream_update->periodic_interrupt0 && - dc->hwss.setup_periodic_interrupt) - dc->hwss.setup_periodic_interrupt(dc, pipe_ctx, VLINE0); - - if (stream_update->periodic_interrupt1 && - dc->hwss.setup_periodic_interrupt) - dc->hwss.setup_periodic_interrupt(dc, pipe_ctx, VLINE1); + if (stream_update->periodic_interrupt && dc->hwss.setup_periodic_interrupt) + dc->hwss.setup_periodic_interrupt(dc, pipe_ctx); if ((stream_update->hdr_static_metadata && !stream->use_dynamic_meta) || stream_update->vrr_infopacket || @@ -3071,7 +3072,6 @@ static void commit_planes_do_stream_update(struct dc *dc, } else { if (get_seamless_boot_stream_count(context) == 0) dc->hwss.prepare_bandwidth(dc, dc->current_state); - core_link_enable_stream(dc->current_state, pipe_ctx); } } @@ -3099,11 +3099,9 @@ static void commit_planes_do_stream_update(struct dc *dc, static bool dc_dmub_should_send_dirty_rect_cmd(struct dc *dc, struct dc_stream_state *stream) { - if (stream->link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) - return true; - - if (stream->link->psr_settings.psr_version == DC_PSR_VERSION_1 && - dc->debug.enable_sw_cntl_psr) + if ((stream->link->psr_settings.psr_version == DC_PSR_VERSION_SU_1 + || stream->link->psr_settings.psr_version == DC_PSR_VERSION_1) + && stream->ctx->dce_version >= DCN_VERSION_3_1) return true; return false; @@ -3205,6 +3203,9 @@ static void commit_planes_for_stream(struct dc *dc, if (get_seamless_boot_stream_count(context) == 0) dc->hwss.prepare_bandwidth(dc, context); + if (dc->debug.enable_double_buffered_dsc_pg_support) + dc->hwss.update_dsc_pg(dc, context, false); + context_clock_trace(dc, context); } @@ -3319,10 +3320,6 @@ static void commit_planes_for_stream(struct dc *dc, if (dc->hwss.program_front_end_for_ctx) dc->hwss.program_front_end_for_ctx(dc, context); - if (update_type != UPDATE_TYPE_FAST) - if (dc->hwss.commit_subvp_config) - dc->hwss.commit_subvp_config(dc, context); - if (should_lock_all_pipes && dc->hwss.interdependent_update_lock) { dc->hwss.interdependent_update_lock(dc, context, false); } else { @@ -3330,16 +3327,15 @@ static void commit_planes_for_stream(struct dc *dc, } dc->hwss.post_unlock_program_front_end(dc, context); + if (update_type != UPDATE_TYPE_FAST) + if (dc->hwss.commit_subvp_config) + dc->hwss.commit_subvp_config(dc, context); + /* Since phantom pipe programming is moved to post_unlock_program_front_end, * move the SubVP lock to after the phantom pipes have been setup */ - if (should_lock_all_pipes && dc->hwss.interdependent_update_lock) { - if (dc->hwss.subvp_pipe_control_lock) - dc->hwss.subvp_pipe_control_lock(dc, context, false, should_lock_all_pipes, NULL, subvp_prev_use); - } else { - if (dc->hwss.subvp_pipe_control_lock) - dc->hwss.subvp_pipe_control_lock(dc, context, false, should_lock_all_pipes, NULL, subvp_prev_use); - } + if (dc->hwss.subvp_pipe_control_lock) + dc->hwss.subvp_pipe_control_lock(dc, context, false, should_lock_all_pipes, NULL, subvp_prev_use); return; } @@ -3463,10 +3459,6 @@ static void commit_planes_for_stream(struct dc *dc, } - if (update_type != UPDATE_TYPE_FAST) - if (dc->hwss.commit_subvp_config) - dc->hwss.commit_subvp_config(dc, context); - if (should_lock_all_pipes && dc->hwss.interdependent_update_lock) { dc->hwss.interdependent_update_lock(dc, context, false); } else { @@ -3504,6 +3496,10 @@ static void commit_planes_for_stream(struct dc *dc, if (update_type != UPDATE_TYPE_FAST) dc->hwss.post_unlock_program_front_end(dc, context); + if (update_type != UPDATE_TYPE_FAST) + if (dc->hwss.commit_subvp_config) + dc->hwss.commit_subvp_config(dc, context); + /* Since phantom pipe programming is moved to post_unlock_program_front_end, * move the SubVP lock to after the phantom pipes have been setup */ @@ -3533,19 +3529,72 @@ static void commit_planes_for_stream(struct dc *dc, } } +/* Determines if the incoming context requires a applying transition state with unnecessary + * pipe splitting and ODM disabled, due to hardware limitations. In a case where + * the OPP associated with an MPCC might change due to plane additions, this function + * returns true. + */ +static bool could_mpcc_tree_change_for_active_pipes(struct dc *dc, + struct dc_stream_state *stream, + int surface_count, + bool *is_plane_addition) +{ + + struct dc_stream_status *cur_stream_status = stream_get_status(dc->current_state, stream); + bool force_minimal_pipe_splitting = false; + + *is_plane_addition = false; + + if (cur_stream_status && + dc->current_state->stream_count > 0 && + dc->debug.pipe_split_policy != MPC_SPLIT_AVOID) { + /* determine if minimal transition is required due to MPC*/ + if (surface_count > 0) { + if (cur_stream_status->plane_count > surface_count) { + force_minimal_pipe_splitting = true; + } else if (cur_stream_status->plane_count < surface_count) { + force_minimal_pipe_splitting = true; + *is_plane_addition = true; + } + } + } + + if (cur_stream_status && + dc->current_state->stream_count == 1 && + dc->debug.enable_single_display_2to1_odm_policy) { + /* determine if minimal transition is required due to dynamic ODM*/ + if (surface_count > 0) { + if (cur_stream_status->plane_count > 2 && cur_stream_status->plane_count > surface_count) { + force_minimal_pipe_splitting = true; + } else if (surface_count > 2 && cur_stream_status->plane_count < surface_count) { + force_minimal_pipe_splitting = true; + *is_plane_addition = true; + } + } + } + + return force_minimal_pipe_splitting; +} + static bool commit_minimal_transition_state(struct dc *dc, struct dc_state *transition_base_context) { struct dc_state *transition_context = dc_create_state(dc); - enum pipe_split_policy tmp_policy; + enum pipe_split_policy tmp_mpc_policy; + bool temp_dynamic_odm_policy; enum dc_status ret = DC_ERROR_UNEXPECTED; unsigned int i, j; if (!transition_context) return false; - tmp_policy = dc->debug.pipe_split_policy; - dc->debug.pipe_split_policy = MPC_SPLIT_AVOID; + if (!dc->config.is_vmin_only_asic) { + tmp_mpc_policy = dc->debug.pipe_split_policy; + dc->debug.pipe_split_policy = MPC_SPLIT_AVOID; + } + + temp_dynamic_odm_policy = dc->debug.enable_single_display_2to1_odm_policy; + dc->debug.enable_single_display_2to1_odm_policy = false; dc_resource_state_copy_construct(transition_base_context, transition_context); @@ -3567,19 +3616,22 @@ static bool commit_minimal_transition_state(struct dc *dc, ret = dc_commit_state_no_check(dc, transition_context); } - //always release as dc_commit_state_no_check retains in good case + /*always release as dc_commit_state_no_check retains in good case*/ dc_release_state(transition_context); - //restore previous pipe split policy - dc->debug.pipe_split_policy = tmp_policy; + /*restore previous pipe split and odm policy*/ + if (!dc->config.is_vmin_only_asic) + dc->debug.pipe_split_policy = tmp_mpc_policy; + + dc->debug.enable_single_display_2to1_odm_policy = temp_dynamic_odm_policy; if (ret != DC_OK) { - //this should never happen + /*this should never happen*/ BREAK_TO_DEBUGGER(); return false; } - //force full surface update + /*force full surface update*/ for (i = 0; i < dc->current_state->stream_count; i++) { for (j = 0; j < dc->current_state->stream_status[i].plane_count; j++) { dc->current_state->stream_status[i].plane_states[j]->update_flags.raw = 0xFFFFFFFF; @@ -3602,22 +3654,14 @@ bool dc_update_planes_and_stream(struct dc *dc, * cause underflow. Apply stream configuration with minimal pipe * split first to avoid unsupported transitions for active pipes. */ - bool force_minimal_pipe_splitting = false; - bool is_plane_addition = false; - - struct dc_stream_status *cur_stream_status = stream_get_status(dc->current_state, stream); + bool force_minimal_pipe_splitting; + bool is_plane_addition; - if (cur_stream_status && - dc->current_state->stream_count > 0 && - dc->debug.pipe_split_policy != MPC_SPLIT_AVOID) { - /* determine if minimal transition is required */ - if (cur_stream_status->plane_count > surface_count) { - force_minimal_pipe_splitting = true; - } else if (cur_stream_status->plane_count < surface_count) { - force_minimal_pipe_splitting = true; - is_plane_addition = true; - } - } + force_minimal_pipe_splitting = could_mpcc_tree_change_for_active_pipes( + dc, + stream, + surface_count, + &is_plane_addition); /* on plane addition, minimal state is the current one */ if (force_minimal_pipe_splitting && is_plane_addition && @@ -3634,7 +3678,7 @@ bool dc_update_planes_and_stream(struct dc *dc, &context)) return false; - /* on plane addition, minimal state is the new one */ + /* on plane removal, minimal state is the new one */ if (force_minimal_pipe_splitting && !is_plane_addition) { if (!commit_minimal_transition_state(dc, context)) { dc_release_state(context); @@ -4021,7 +4065,7 @@ struct dc_sink *dc_link_add_remote_sink( * Treat device as no EDID device if EDID * parsing fails */ - if (edid_status != EDID_OK) { + if (edid_status != EDID_OK && edid_status != EDID_PARTIAL_VALID) { dc_sink->dc_edid.length = 0; dm_error("Bad EDID, status%d!\n", edid_status); } @@ -4276,8 +4320,8 @@ void dc_mclk_switch_using_fw_based_vblank_stretch_shut_down(struct dc *dc) /* ***************************************************************************** * Function: dc_is_dmub_outbox_supported - - * - * @brief + * + * @brief * Checks whether DMUB FW supports outbox notifications, if supported * DM should register outbox interrupt prior to actually enabling interrupts * via dc_enable_dmub_outbox diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c index 2a8007928210..7c2e3b8dc26a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c @@ -402,6 +402,44 @@ void get_hdr_visual_confirm_color( } } +void get_subvp_visual_confirm_color( + struct dc *dc, + struct pipe_ctx *pipe_ctx, + struct tg_color *color) +{ + uint32_t color_value = MAX_TG_COLOR_VALUE; + bool enable_subvp = false; + int i; + + if (!dc->ctx || !dc->ctx->dmub_srv || !pipe_ctx) + return; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; + + if (pipe->stream && pipe->stream->mall_stream_config.paired_stream && + pipe->stream->mall_stream_config.type == SUBVP_MAIN) { + /* SubVP enable - red */ + color->color_r_cr = color_value; + enable_subvp = true; + + if (pipe_ctx->stream == pipe->stream) + return; + break; + } + } + + if (enable_subvp && pipe_ctx->stream->mall_stream_config.type == SUBVP_NONE) { + color->color_r_cr = 0; + if (pipe_ctx->stream->ignore_msa_timing_param == 1) + /* SubVP enable and DRR on - green */ + color->color_g_y = color_value; + else + /* SubVP enable and No DRR - blue */ + color->color_b_cb = color_value; + } +} + void get_surface_tile_visual_confirm_color( struct pipe_ctx *pipe_ctx, struct tg_color *color) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 66d2ae7aacf5..3d19fb92333b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -832,8 +832,9 @@ static bool discover_dp_mst_topology(struct dc_link *link, enum dc_detect_reason LINK_INFO("link=%d, mst branch is now Connected\n", link->link_index); - apply_dpia_mst_dsc_always_on_wa(link); link->type = dc_connection_mst_branch; + apply_dpia_mst_dsc_always_on_wa(link); + dm_helpers_dp_update_branch_info(link->ctx, link); if (dm_helpers_dp_mst_start_top_mgr(link->ctx, link, (reason == DETECT_REASON_BOOT || reason == DETECT_REASON_RESUMEFROMS3S4))) { @@ -847,20 +848,13 @@ static bool discover_dp_mst_topology(struct dc_link *link, enum dc_detect_reason bool reset_cur_dp_mst_topology(struct dc_link *link) { - bool result = false; DC_LOGGER_INIT(link->ctx->logger); LINK_INFO("link=%d, mst branch is now Disconnected\n", link->link_index); revert_dpia_mst_dsc_always_on_wa(link); - result = dm_helpers_dp_mst_stop_top_mgr(link->ctx, link); - - link->mst_stream_alloc_table.stream_count = 0; - memset(link->mst_stream_alloc_table.stream_allocations, - 0, - sizeof(link->mst_stream_alloc_table.stream_allocations)); - return result; + return dm_helpers_dp_mst_stop_top_mgr(link->ctx, link); } static bool should_prepare_phy_clocks_for_link_verification(const struct dc *dc, @@ -1311,6 +1305,14 @@ static bool detect_link_and_local_sink(struct dc_link *link, sink->edid_caps.audio_modes[i].sample_rate, sink->edid_caps.audio_modes[i].sample_size); } + + if (link->connector_signal == SIGNAL_TYPE_EDP) { + // Init dc_panel_config + dm_helpers_init_panel_settings(dc_ctx, &link->panel_config, sink); + // Override dc_panel_config if system has specific settings + dm_helpers_override_panel_settings(dc_ctx, &link->panel_config); + } + } else { /* From Connected-to-Disconnected. */ link->type = dc_connection_none; @@ -1975,7 +1977,7 @@ static enum dc_status enable_link_dp(struct dc_state *state, int i; bool apply_seamless_boot_optimization = false; uint32_t bl_oled_enable_delay = 50; // in ms - const uint32_t post_oui_delay = 30; // 30ms + uint32_t post_oui_delay = 30; // 30ms /* Reduce link bandwidth between failed link training attempts. */ bool do_fallback = false; @@ -2022,8 +2024,10 @@ static enum dc_status enable_link_dp(struct dc_state *state, // during mode switch we do DP_SET_POWER off then on, and OUI is lost dpcd_set_source_specific_data(link); - if (link->dpcd_sink_ext_caps.raw != 0) + if (link->dpcd_sink_ext_caps.raw != 0) { + post_oui_delay += link->panel_config.pps.extra_post_OUI_ms; msleep(post_oui_delay); + } // similarly, mode switch can cause loss of cable ID dpcd_write_cable_id_to_dprx(link); @@ -2069,11 +2073,7 @@ static enum dc_status enable_link_edp( struct dc_state *state, struct pipe_ctx *pipe_ctx) { - enum dc_status status; - - status = enable_link_dp(state, pipe_ctx); - - return status; + return enable_link_dp(state, pipe_ctx); } static enum dc_status enable_link_dp_mst( @@ -2639,9 +2639,8 @@ static void disable_link(struct dc_link *link, const struct link_resource *link_ dp_set_fec_ready(link, link_res, false); } } - } else { - if (signal != SIGNAL_TYPE_VIRTUAL) - link->link_enc->funcs->disable_output(link->link_enc, signal); + } else if (signal != SIGNAL_TYPE_VIRTUAL) { + link->dc->hwss.disable_link_output(link, link_res, signal); } if (signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { @@ -2663,6 +2662,7 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) bool is_over_340mhz = false; bool is_vga_mode = (stream->timing.h_addressable == 640) && (stream->timing.v_addressable == 480); + struct dc *dc = pipe_ctx->stream->ctx->dc; if (stream->phy_pix_clk == 0) stream->phy_pix_clk = stream->timing.pix_clk_100hz / 10; @@ -2702,11 +2702,12 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) display_color_depth = COLOR_DEPTH_888; - link->link_enc->funcs->enable_tmds_output( - link->link_enc, + dc->hwss.enable_tmds_link_output( + link, + &pipe_ctx->link_res, + pipe_ctx->stream->signal, pipe_ctx->clock_source->id, display_color_depth, - pipe_ctx->stream->signal, stream->phy_pix_clk); if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) @@ -2717,15 +2718,16 @@ static void enable_link_lvds(struct pipe_ctx *pipe_ctx) { struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->link; + struct dc *dc = stream->ctx->dc; if (stream->phy_pix_clk == 0) stream->phy_pix_clk = stream->timing.pix_clk_100hz / 10; memset(&stream->link->cur_link_settings, 0, sizeof(struct dc_link_settings)); - - link->link_enc->funcs->enable_lvds_output( - link->link_enc, + dc->hwss.enable_lvds_link_output( + link, + &pipe_ctx->link_res, pipe_ctx->clock_source->id, stream->phy_pix_clk); @@ -3516,7 +3518,7 @@ static void update_mst_stream_alloc_table( struct dc_link *link, struct stream_encoder *stream_enc, struct hpo_dp_stream_encoder *hpo_dp_stream_enc, // TODO: Rename stream_enc to dio_stream_enc? - const struct dp_mst_stream_allocation_table *proposed_table) + const struct dc_dp_mst_stream_allocation_table *proposed_table) { struct link_mst_stream_allocation work_table[MAX_CONTROLLER_NUM] = { 0 }; struct link_mst_stream_allocation *dc_alloc; @@ -3563,6 +3565,35 @@ static void update_mst_stream_alloc_table( work_table[i]; } +static void remove_stream_from_alloc_table( + struct dc_link *link, + struct stream_encoder *dio_stream_enc, + struct hpo_dp_stream_encoder *hpo_dp_stream_enc) +{ + int i = 0; + struct link_mst_stream_allocation_table *table = + &link->mst_stream_alloc_table; + + if (hpo_dp_stream_enc) { + for (; i < table->stream_count; i++) + if (hpo_dp_stream_enc == table->stream_allocations[i].hpo_dp_stream_enc) + break; + } else { + for (; i < table->stream_count; i++) + if (dio_stream_enc == table->stream_allocations[i].stream_enc) + break; + } + + if (i < table->stream_count) { + i++; + for (; i < table->stream_count; i++) + table->stream_allocations[i-1] = table->stream_allocations[i]; + memset(&table->stream_allocations[table->stream_count-1], 0, + sizeof(struct link_mst_stream_allocation)); + table->stream_count--; + } +} + static void dc_log_vcp_x_y(const struct dc_link *link, struct fixed31_32 avg_time_slots_per_mtp) { const uint32_t VCP_Y_PRECISION = 1000; @@ -3679,7 +3710,7 @@ enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx) { struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->link; - struct dp_mst_stream_allocation_table proposed_table = {0}; + struct dc_dp_mst_stream_allocation_table proposed_table = {0}; struct fixed31_32 avg_time_slots_per_mtp; struct fixed31_32 pbn; struct fixed31_32 pbn_per_slot; @@ -3784,7 +3815,7 @@ enum dc_status dc_link_reduce_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t bw struct fixed31_32 avg_time_slots_per_mtp; struct fixed31_32 pbn; struct fixed31_32 pbn_per_slot; - struct dp_mst_stream_allocation_table proposed_table = {0}; + struct dc_dp_mst_stream_allocation_table proposed_table = {0}; uint8_t i; const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res); DC_LOGGER_INIT(link->ctx->logger); @@ -3873,7 +3904,7 @@ enum dc_status dc_link_increase_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t struct fixed31_32 avg_time_slots_per_mtp; struct fixed31_32 pbn; struct fixed31_32 pbn_per_slot; - struct dp_mst_stream_allocation_table proposed_table = {0}; + struct dc_dp_mst_stream_allocation_table proposed_table = {0}; uint8_t i; enum act_return_status ret; const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res); @@ -3957,7 +3988,7 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) { struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->link; - struct dp_mst_stream_allocation_table proposed_table = {0}; + struct dc_dp_mst_stream_allocation_table proposed_table = {0}; struct fixed31_32 avg_time_slots_per_mtp = dc_fixpt_from_int(0); int i; bool mst_mode = (link->type == dc_connection_mst_branch); @@ -3980,26 +4011,32 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) &empty_link_settings, avg_time_slots_per_mtp); - /* TODO: which component is responsible for remove payload table? */ if (mst_mode) { + /* when link is in mst mode, reply on mst manager to remove + * payload + */ if (dm_helpers_dp_mst_write_payload_allocation_table( stream->ctx, stream, &proposed_table, - false)) { + false)) update_mst_stream_alloc_table( - link, - pipe_ctx->stream_res.stream_enc, - pipe_ctx->stream_res.hpo_dp_stream_enc, - &proposed_table); - } - else { - DC_LOG_WARNING("Failed to update" - "MST allocation table for" - "pipe idx:%d\n", - pipe_ctx->pipe_idx); - } + link, + pipe_ctx->stream_res.stream_enc, + pipe_ctx->stream_res.hpo_dp_stream_enc, + &proposed_table); + else + DC_LOG_WARNING("Failed to update" + "MST allocation table for" + "pipe idx:%d\n", + pipe_ctx->pipe_idx); + } else { + /* when link is no longer in mst mode (mst hub unplugged), + * remove payload with default dc logic + */ + remove_stream_from_alloc_table(link, pipe_ctx->stream_res.stream_enc, + pipe_ctx->stream_res.hpo_dp_stream_enc); } DC_LOG_MST("%s" @@ -4303,8 +4340,9 @@ void core_link_enable_stream( */ if (pipe_ctx->stream->timing.flags.DSC) { if (dc_is_dp_signal(pipe_ctx->stream->signal) || - dc_is_virtual_signal(pipe_ctx->stream->signal)) - dp_set_dsc_enable(pipe_ctx, true); + dc_is_virtual_signal(pipe_ctx->stream->signal)) + dp_set_dsc_enable(pipe_ctx, true); + } status = enable_link(state, pipe_ctx); @@ -4736,7 +4774,7 @@ bool dc_link_should_enable_fec(const struct dc_link *link) else if (link->connector_signal == SIGNAL_TYPE_EDP && (link->dpcd_caps.dsc_caps.dsc_basic_caps.fields. dsc_support.DSC_SUPPORT == false - || link->dc->debug.disable_dsc_edp + || link->panel_config.dsc.disable_dsc_edp || !link->dc->caps.edp_dsc_support)) force_disable = true; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c index d01d2eeed813..651231387043 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c @@ -35,6 +35,8 @@ #include "dc_link_ddc.h" #include "dce/dce_aux.h" #include "dmub/inc/dmub_cmd.h" +#include "link_dpcd.h" +#include "include/dal_asic_id.h" #define DC_LOGGER_INIT(logger) @@ -683,6 +685,21 @@ bool dc_link_aux_try_to_configure_timeout(struct ddc_service *ddc, bool result = false; struct ddc *ddc_pin = ddc->ddc_pin; + if ((ddc->link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) && + !ddc->link->dc->debug.disable_fixed_vs_aux_timeout_wa && + ASICREV_IS_YELLOW_CARP(ddc->ctx->asic_id.hw_internal_rev)) { + /* Fixed VS workaround for AUX timeout */ + const uint32_t fixed_vs_address = 0xF004F; + const uint8_t fixed_vs_data[4] = {0x1, 0x22, 0x63, 0xc}; + + core_link_write_dpcd(ddc->link, + fixed_vs_address, + fixed_vs_data, + sizeof(fixed_vs_data)); + + timeout = 3072; + } + /* Do not try to access nonexistent DDC pin. */ if (ddc->link->ep_type != DISPLAY_ENDPOINT_PHY) return true; @@ -691,6 +708,7 @@ bool dc_link_aux_try_to_configure_timeout(struct ddc_service *ddc, ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]->funcs->configure_timeout(ddc, timeout); result = true; } + return result; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 780f7f4c28b6..c57df45e83ff 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -526,9 +526,9 @@ uint8_t dc_dp_initialize_scrambling_data_symbols( return disable_scrabled_data_symbols; } -static inline bool is_repeater(struct dc_link *link, uint32_t offset) +static inline bool is_repeater(const struct link_training_settings *lt_settings, uint32_t offset) { - return (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && (offset != 0); + return (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && (offset != 0); } static void dpcd_set_lt_pattern_and_lane_settings( @@ -545,7 +545,7 @@ static void dpcd_set_lt_pattern_and_lane_settings( bool edp_workaround = false; /* TODO link_prop.INTERNAL */ dpcd_base_lt_offset = DP_TRAINING_PATTERN_SET; - if (is_repeater(link, offset)) + if (is_repeater(lt_settings, offset)) dpcd_base_lt_offset = DP_TRAINING_PATTERN_SET_PHY_REPEATER1 + ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1)); @@ -561,7 +561,7 @@ static void dpcd_set_lt_pattern_and_lane_settings( dpcd_lt_buffer[DP_TRAINING_PATTERN_SET - DP_TRAINING_PATTERN_SET] = dpcd_pattern.raw; - if (is_repeater(link, offset)) { + if (is_repeater(lt_settings, offset)) { DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Repeater ID: %d\n 0x%X pattern = %x\n", __func__, offset, @@ -584,7 +584,7 @@ static void dpcd_set_lt_pattern_and_lane_settings( lt_settings->dpcd_lane_settings, size_in_bytes); - if (is_repeater(link, offset)) { + if (is_repeater(lt_settings, offset)) { if (dp_get_link_encoding_format(<_settings->link_settings) == DP_128b_132b_ENCODING) DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n" @@ -873,7 +873,7 @@ enum dc_status dp_get_lane_status_and_lane_adjust( uint32_t lane; enum dc_status status; - if (is_repeater(link, offset)) { + if (is_repeater(link_training_setting, offset)) { lane01_status_address = DP_LANE0_1_STATUS_PHY_REPEATER1 + ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1)); @@ -906,7 +906,7 @@ enum dc_status dp_get_lane_status_and_lane_adjust( ln_align->raw = dpcd_buf[2]; - if (is_repeater(link, offset)) { + if (is_repeater(link_training_setting, offset)) { DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n" " 0x%X Lane01Status = %x\n 0x%X Lane23Status = %x\n ", __func__, @@ -954,7 +954,7 @@ enum dc_status dpcd_set_lane_settings( lane0_set_address = DP_TRAINING_LANE0_SET; - if (is_repeater(link, offset)) + if (is_repeater(link_training_setting, offset)) lane0_set_address = DP_TRAINING_LANE0_SET_PHY_REPEATER1 + ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1)); @@ -963,7 +963,7 @@ enum dc_status dpcd_set_lane_settings( (uint8_t *)(link_training_setting->dpcd_lane_settings), link_training_setting->link_settings.lane_count); - if (is_repeater(link, offset)) { + if (is_repeater(link_training_setting, offset)) { if (dp_get_link_encoding_format(&link_training_setting->link_settings) == DP_128b_132b_ENCODING) DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n" @@ -1172,7 +1172,7 @@ static enum link_training_result perform_channel_equalization_sequence( /* Note: also check that TPS4 is a supported feature*/ tr_pattern = lt_settings->pattern_for_eq; - if (is_repeater(link, offset) && dp_get_link_encoding_format(<_settings->link_settings) == DP_8b_10b_ENCODING) + if (is_repeater(lt_settings, offset) && dp_get_link_encoding_format(<_settings->link_settings) == DP_8b_10b_ENCODING) tr_pattern = DP_TRAINING_PATTERN_SEQUENCE_4; dp_set_hw_training_pattern(link, link_res, tr_pattern, offset); @@ -1198,7 +1198,7 @@ static enum link_training_result perform_channel_equalization_sequence( /* 3. wait for receiver to lock-on*/ wait_time_microsec = lt_settings->eq_pattern_time; - if (is_repeater(link, offset)) + if (is_repeater(lt_settings, offset)) wait_time_microsec = dp_translate_training_aux_read_interval( link->dpcd_caps.lttpr_caps.aux_rd_interval[offset - 1]); @@ -1469,7 +1469,6 @@ static inline void decide_8b_10b_training_settings( */ lt_settings->link_settings.link_spread = link->dp_ss_off ? LINK_SPREAD_DISABLED : LINK_SPREAD_05_DOWNSPREAD_30KHZ; - lt_settings->lttpr_mode = link->lttpr_mode; lt_settings->cr_pattern_time = get_cr_training_aux_rd_interval(link, link_setting); lt_settings->eq_pattern_time = get_eq_training_aux_rd_interval(link, link_setting); lt_settings->pattern_for_cr = decide_cr_training_pattern(link_setting); @@ -1478,6 +1477,7 @@ static inline void decide_8b_10b_training_settings( lt_settings->should_set_fec_ready = true; lt_settings->disallow_per_lane_settings = true; lt_settings->always_match_dpcd_with_hw_lane_settings = true; + lt_settings->lttpr_mode = dp_decide_8b_10b_lttpr_mode(link); dp_hw_to_dpcd_lane_settings(lt_settings, lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings); } @@ -1501,9 +1501,8 @@ static inline void decide_128b_132b_training_settings(struct dc_link *link, lt_settings->cds_pattern_time = 2500; lt_settings->cds_wait_time_limit = (dp_convert_to_count( link->dpcd_caps.lttpr_caps.phy_repeater_cnt) + 1) * 20000; - lt_settings->lttpr_mode = dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) ? - LTTPR_MODE_NON_TRANSPARENT : LTTPR_MODE_TRANSPARENT; lt_settings->disallow_per_lane_settings = true; + lt_settings->lttpr_mode = dp_decide_128b_132b_lttpr_mode(link); dp_hw_to_dpcd_lane_settings(lt_settings, lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings); } @@ -1543,7 +1542,7 @@ static void override_training_settings( lt_settings->ffe_preset = overrides->ffe_preset; /* Override HW lane settings with BIOS forced values if present */ if (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN && - link->lttpr_mode == LTTPR_MODE_TRANSPARENT) { + lt_settings->lttpr_mode == LTTPR_MODE_TRANSPARENT) { lt_settings->voltage_swing = &link->bios_forced_drive_settings.VOLTAGE_SWING; lt_settings->pre_emphasis = &link->bios_forced_drive_settings.PRE_EMPHASIS; lt_settings->always_match_dpcd_with_hw_lane_settings = false; @@ -1584,6 +1583,15 @@ static void override_training_settings( if (link->preferred_training_settings.fec_enable != NULL) lt_settings->should_set_fec_ready = *link->preferred_training_settings.fec_enable; + + #if defined(CONFIG_DRM_AMD_DC_DCN) + /* Check DP tunnel LTTPR mode debug option. */ + if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA && link->dc->debug.dpia_debug.bits.force_non_lttpr) + lt_settings->lttpr_mode = LTTPR_MODE_NON_LTTPR; + +#endif + dp_get_lttpr_mode_override(link, <_settings->lttpr_mode); + } uint8_t dp_convert_to_count(uint8_t lttpr_repeater_count) @@ -1649,7 +1657,7 @@ static enum dc_status configure_lttpr_mode_non_transparent( link->dpcd_caps.lttpr_caps.mode = repeater_mode; } - if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) { + if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) { DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Non Transparent Mode\n", __func__); @@ -2099,7 +2107,7 @@ static enum link_training_result dp_perform_8b_10b_link_training( /* 1. set link rate, lane count and spread. */ dpcd_set_link_settings(link, lt_settings); - if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) { + if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) { /* 2. perform link training (set link training done * to false is done as well) @@ -2216,7 +2224,7 @@ static enum link_training_result perform_fixed_vs_pe_nontransparent_training_seq link->vendor_specific_lttpr_link_rate_wa = target_rate; - if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) { + if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) { /* 2. perform link training (set link training done * to false is done as well) @@ -2288,7 +2296,7 @@ static enum link_training_result dp_perform_fixed_vs_pe_training_sequence( ASSERT(dp_get_link_encoding_format(<_settings->link_settings) == DP_8b_10b_ENCODING); - if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) { + if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) { status = perform_fixed_vs_pe_nontransparent_training_sequence(link, link_res, lt_settings); return status; } @@ -2635,6 +2643,7 @@ enum link_training_result dc_link_dp_perform_link_training( link, link_settings, <_settings); + override_training_settings( link, &link->preferred_training_settings, @@ -2652,7 +2661,7 @@ enum link_training_result dc_link_dp_perform_link_training( * Per DP specs starting from here, DPTX device shall not issue * Non-LT AUX transactions inside training mode. */ - if (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) + if (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN && encoding == DP_8b_10b_ENCODING) status = dp_perform_fixed_vs_pe_training_sequence(link, link_res, <_settings); else if (encoding == DP_8b_10b_ENCODING) status = dp_perform_8b_10b_link_training(link, link_res, <_settings); @@ -3086,7 +3095,7 @@ struct dc_link_settings dp_get_max_link_cap(struct dc_link *link) * account for lttpr repeaters cap * notes: repeaters do not snoop in the DPRX Capabilities addresses (3.6.3). */ - if (link->lttpr_mode != LTTPR_MODE_NON_LTTPR) { + if (dp_is_lttpr_present(link)) { if (link->dpcd_caps.lttpr_caps.max_lane_count < max_link_cap.lane_count) max_link_cap.lane_count = link->dpcd_caps.lttpr_caps.max_lane_count; lttpr_max_link_rate = get_lttpr_max_link_rate(link); @@ -3240,7 +3249,7 @@ static bool dp_verify_link_cap( cur_link_settings = max_link_settings; /* Grant extended timeout request */ - if ((link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && (link->dpcd_caps.lttpr_caps.max_ext_timeout > 0)) { + if (dp_is_lttpr_present(link) && link->dpcd_caps.lttpr_caps.max_ext_timeout > 0) { uint8_t grant = link->dpcd_caps.lttpr_caps.max_ext_timeout & 0x80; core_link_write_dpcd(link, DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT, &grant, sizeof(grant)); @@ -3749,7 +3758,7 @@ static bool decide_edp_link_settings_with_dsc(struct dc_link *link, unsigned int policy = 0; - policy = link->ctx->dc->debug.force_dsc_edp_policy; + policy = link->panel_config.dsc.force_dsc_edp_policy; if (max_link_rate == LINK_RATE_UNKNOWN) max_link_rate = link->verified_link_cap.link_rate; /* @@ -3915,7 +3924,7 @@ bool decide_link_settings(struct dc_stream_state *stream, if (stream->timing.flags.DSC) { enum dc_link_rate max_link_rate = LINK_RATE_UNKNOWN; - if (link->ctx->dc->debug.force_dsc_edp_policy) { + if (link->panel_config.dsc.force_dsc_edp_policy) { /* calculate link max link rate cap*/ struct dc_link_settings tmp_link_setting; struct dc_crtc_timing tmp_timing = stream->timing; @@ -4101,8 +4110,13 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) &dpcd_lane_adjustment[0].raw, sizeof(dpcd_lane_adjustment)); + /* prepare link training settings */ + link_training_settings.link_settings = link->cur_link_settings; + + link_training_settings.lttpr_mode = dp_decide_lttpr_mode(link, &link->cur_link_settings); + if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) && - link->lttpr_mode == LTTPR_MODE_TRANSPARENT) + link_training_settings.lttpr_mode == LTTPR_MODE_TRANSPARENT) dp_fixed_vs_pe_read_lane_adjust( link, link_training_settings.dpcd_lane_settings); @@ -4209,9 +4223,6 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) test_pattern_size); } - /* prepare link training settings */ - link_training_settings.link_settings = link->cur_link_settings; - for (lane = 0; lane < (unsigned int)(link->cur_link_settings.lane_count); lane++) { @@ -4524,17 +4535,15 @@ void dc_link_dp_handle_link_loss(struct dc_link *link) for (i = 0; i < MAX_PIPES; i++) { pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i]; if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off && - pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe) { + pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe) core_link_disable_stream(pipe_ctx); - } } for (i = 0; i < MAX_PIPES; i++) { pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i]; if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off && - pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe) { + pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe) core_link_enable_stream(link->dc->current_state, pipe_ctx); - } } } @@ -5023,129 +5032,136 @@ static bool dpcd_read_sink_ext_caps(struct dc_link *link) return true; } -/* Logic to determine LTTPR mode */ -static void determine_lttpr_mode(struct dc_link *link) +bool dp_retrieve_lttpr_cap(struct dc_link *link) { - bool allow_lttpr_non_transparent_mode = 0; - bool vbios_lttpr_enable = link->dc->caps.vbios_lttpr_enable; + uint8_t lttpr_dpcd_data[8]; + enum dc_status status = DC_ERROR_UNEXPECTED; + bool is_lttpr_present = false; + + /* Logic to determine LTTPR support*/ bool vbios_lttpr_interop = link->dc->caps.vbios_lttpr_aware; + if (!vbios_lttpr_interop || !link->dc->caps.extended_aux_timeout_support) + return false; - if ((link->dc->config.allow_lttpr_non_transparent_mode.bits.DP2_0 && - link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED)) { - allow_lttpr_non_transparent_mode = 1; - } else if (link->dc->config.allow_lttpr_non_transparent_mode.bits.DP1_4A && - !link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED) { - allow_lttpr_non_transparent_mode = 1; + /* By reading LTTPR capability, RX assumes that we will enable + * LTTPR extended aux timeout if LTTPR is present. + */ + status = core_link_read_dpcd(link, + DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV, + lttpr_dpcd_data, + sizeof(lttpr_dpcd_data)); + + link->dpcd_caps.lttpr_caps.revision.raw = + lttpr_dpcd_data[DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV - + DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; + + link->dpcd_caps.lttpr_caps.max_link_rate = + lttpr_dpcd_data[DP_MAX_LINK_RATE_PHY_REPEATER - + DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; + + link->dpcd_caps.lttpr_caps.phy_repeater_cnt = + lttpr_dpcd_data[DP_PHY_REPEATER_CNT - + DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; + + link->dpcd_caps.lttpr_caps.max_lane_count = + lttpr_dpcd_data[DP_MAX_LANE_COUNT_PHY_REPEATER - + DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; + + link->dpcd_caps.lttpr_caps.mode = + lttpr_dpcd_data[DP_PHY_REPEATER_MODE - + DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; + + link->dpcd_caps.lttpr_caps.max_ext_timeout = + lttpr_dpcd_data[DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT - + DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; + link->dpcd_caps.lttpr_caps.main_link_channel_coding.raw = + lttpr_dpcd_data[DP_MAIN_LINK_CHANNEL_CODING_PHY_REPEATER - + DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; + + link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.raw = + lttpr_dpcd_data[DP_PHY_REPEATER_128B132B_RATES - + DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; + + /* If this chip cap is set, at least one retimer must exist in the chain + * Override count to 1 if we receive a known bad count (0 or an invalid value) + */ + if (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN && + (dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) == 0)) { + ASSERT(0); + link->dpcd_caps.lttpr_caps.phy_repeater_cnt = 0x80; } - link->lttpr_mode = LTTPR_MODE_NON_LTTPR; - if (vbios_lttpr_enable && vbios_lttpr_interop) - link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT; - else if (!vbios_lttpr_enable && vbios_lttpr_interop) { - if (allow_lttpr_non_transparent_mode) - link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT; - else - link->lttpr_mode = LTTPR_MODE_TRANSPARENT; - } else if (!vbios_lttpr_enable && !vbios_lttpr_interop) { - if (!allow_lttpr_non_transparent_mode || !link->dc->caps.extended_aux_timeout_support) - link->lttpr_mode = LTTPR_MODE_NON_LTTPR; - else - link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT; - } + /* Attempt to train in LTTPR transparent mode if repeater count exceeds 8. */ + is_lttpr_present = dp_is_lttpr_present(link); -#if defined(CONFIG_DRM_AMD_DC_DCN) - /* Check DP tunnel LTTPR mode debug option. */ - if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA && - link->dc->debug.dpia_debug.bits.force_non_lttpr) - link->lttpr_mode = LTTPR_MODE_NON_LTTPR; -#endif + if (is_lttpr_present) + CONN_DATA_DETECT(link, lttpr_dpcd_data, sizeof(lttpr_dpcd_data), "LTTPR Caps: "); + + return is_lttpr_present; } -bool dp_retrieve_lttpr_cap(struct dc_link *link) +bool dp_is_lttpr_present(struct dc_link *link) { - uint8_t lttpr_dpcd_data[8]; - enum dc_status status = DC_ERROR_UNEXPECTED; - bool is_lttpr_present = false; + return (dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) != 0 && + link->dpcd_caps.lttpr_caps.max_lane_count > 0 && + link->dpcd_caps.lttpr_caps.max_lane_count <= 4 && + link->dpcd_caps.lttpr_caps.revision.raw >= 0x14); +} - memset(lttpr_dpcd_data, '\0', sizeof(lttpr_dpcd_data)); +enum lttpr_mode dp_decide_lttpr_mode(struct dc_link *link, struct dc_link_settings *link_setting) +{ + enum dp_link_encoding encoding = dp_get_link_encoding_format(link_setting); - /* Logic to determine LTTPR mode*/ - determine_lttpr_mode(link); + if (encoding == DP_8b_10b_ENCODING) + return dp_decide_8b_10b_lttpr_mode(link); + else if (encoding == DP_128b_132b_ENCODING) + return dp_decide_128b_132b_lttpr_mode(link); - if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT || link->lttpr_mode == LTTPR_MODE_TRANSPARENT) { - if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) && - !link->dc->debug.disable_fixed_vs_aux_timeout_wa) { - /* Fixed VS workaround for AUX timeout */ - const uint32_t fixed_vs_address = 0xF004F; - const uint8_t fixed_vs_data[4] = {0x1, 0x22, 0x63, 0xc}; + ASSERT(0); + return LTTPR_MODE_NON_LTTPR; +} - core_link_write_dpcd( - link, - fixed_vs_address, - fixed_vs_data, - sizeof(fixed_vs_data)); - } +void dp_get_lttpr_mode_override(struct dc_link *link, enum lttpr_mode *override) +{ + if (!dp_is_lttpr_present(link)) + return; - /* By reading LTTPR capability, RX assumes that we will enable - * LTTPR extended aux timeout if LTTPR is present. - */ - status = core_link_read_dpcd( - link, - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV, - lttpr_dpcd_data, - sizeof(lttpr_dpcd_data)); - - link->dpcd_caps.lttpr_caps.revision.raw = - lttpr_dpcd_data[DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV - - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; - - link->dpcd_caps.lttpr_caps.max_link_rate = - lttpr_dpcd_data[DP_MAX_LINK_RATE_PHY_REPEATER - - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; - - link->dpcd_caps.lttpr_caps.phy_repeater_cnt = - lttpr_dpcd_data[DP_PHY_REPEATER_CNT - - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; - - link->dpcd_caps.lttpr_caps.max_lane_count = - lttpr_dpcd_data[DP_MAX_LANE_COUNT_PHY_REPEATER - - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; - - link->dpcd_caps.lttpr_caps.mode = - lttpr_dpcd_data[DP_PHY_REPEATER_MODE - - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; - - link->dpcd_caps.lttpr_caps.max_ext_timeout = - lttpr_dpcd_data[DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT - - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; - link->dpcd_caps.lttpr_caps.main_link_channel_coding.raw = - lttpr_dpcd_data[DP_MAIN_LINK_CHANNEL_CODING_PHY_REPEATER - - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; - - link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.raw = - lttpr_dpcd_data[DP_PHY_REPEATER_128B132B_RATES - - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; - - /* If this chip cap is set, at least one retimer must exist in the chain - * Override count to 1 if we receive a known bad count (0 or an invalid value) */ - if (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN && - (dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) == 0)) { - ASSERT(0); - link->dpcd_caps.lttpr_caps.phy_repeater_cnt = 0x80; - } + if (link->dc->debug.lttpr_mode_override == LTTPR_MODE_TRANSPARENT) { + *override = LTTPR_MODE_TRANSPARENT; + } else if (link->dc->debug.lttpr_mode_override == LTTPR_MODE_NON_TRANSPARENT) { + *override = LTTPR_MODE_NON_TRANSPARENT; + } else if (link->dc->debug.lttpr_mode_override == LTTPR_MODE_NON_LTTPR) { + *override = LTTPR_MODE_NON_LTTPR; + } +} - /* Attempt to train in LTTPR transparent mode if repeater count exceeds 8. */ - is_lttpr_present = (link->dpcd_caps.lttpr_caps.max_lane_count > 0 && - link->dpcd_caps.lttpr_caps.max_lane_count <= 4 && - link->dpcd_caps.lttpr_caps.revision.raw >= 0x14); - if (is_lttpr_present) { - CONN_DATA_DETECT(link, lttpr_dpcd_data, sizeof(lttpr_dpcd_data), "LTTPR Caps: "); - configure_lttpr_mode_transparent(link); - } else - link->lttpr_mode = LTTPR_MODE_NON_LTTPR; +enum lttpr_mode dp_decide_8b_10b_lttpr_mode(struct dc_link *link) +{ + bool is_lttpr_present = dp_is_lttpr_present(link); + bool vbios_lttpr_force_non_transparent = link->dc->caps.vbios_lttpr_enable; + bool vbios_lttpr_aware = link->dc->caps.vbios_lttpr_aware; + + if (!is_lttpr_present) + return LTTPR_MODE_NON_LTTPR; + + if (vbios_lttpr_aware) { + if (vbios_lttpr_force_non_transparent) + return LTTPR_MODE_NON_TRANSPARENT; + else + return LTTPR_MODE_TRANSPARENT; } - return is_lttpr_present; + + if (link->dc->config.allow_lttpr_non_transparent_mode.bits.DP1_4A && + link->dc->caps.extended_aux_timeout_support) + return LTTPR_MODE_NON_TRANSPARENT; + + return LTTPR_MODE_NON_LTTPR; +} + +enum lttpr_mode dp_decide_128b_132b_lttpr_mode(struct dc_link *link) +{ + return dp_is_lttpr_present(link) ? LTTPR_MODE_NON_TRANSPARENT : LTTPR_MODE_NON_LTTPR; } static bool get_usbc_cable_id(struct dc_link *link, union dp_cable_id *cable_id) @@ -5207,13 +5223,16 @@ static enum dc_status wa_try_to_wake_dprx(struct dc_link *link, uint64_t timeout uint64_t current_ts = 0; uint64_t time_taken_ms = 0; enum dc_connection_type type = dc_connection_none; + bool lttpr_present; + bool vbios_lttpr_interop = link->dc->caps.vbios_lttpr_aware; - determine_lttpr_mode(link); + lttpr_present = dp_is_lttpr_present(link) || + (!vbios_lttpr_interop || !link->dc->caps.extended_aux_timeout_support); /* Issue an AUX read to test DPRX responsiveness. If LTTPR is supported the first read is expected to * be to determine LTTPR capabilities. Otherwise trying to read power state should be an innocuous AUX read. */ - if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT || link->lttpr_mode == LTTPR_MODE_TRANSPARENT) + if (lttpr_present) status = core_link_read_dpcd( link, DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV, @@ -5281,6 +5300,7 @@ static bool retrieve_link_cap(struct dc_link *link) union dp_downstream_port_present ds_port = { 0 }; enum dc_status status = DC_ERROR_UNEXPECTED; uint32_t read_dpcd_retry_cnt = 3; + uint32_t aux_channel_retry_cnt = 0; int i; struct dp_sink_hw_fw_revision dp_hw_fw_revision; const uint32_t post_oui_delay = 30; // 30ms @@ -5308,20 +5328,46 @@ static bool retrieve_link_cap(struct dc_link *link) status = wa_try_to_wake_dprx(link, timeout_ms); } + while (status != DC_OK && aux_channel_retry_cnt < 10) { + status = core_link_read_dpcd(link, DP_SET_POWER, + &dpcd_power_state, sizeof(dpcd_power_state)); + + /* Delay 1 ms if AUX CH is in power down state. Based on spec + * section 2.3.1.2, if AUX CH may be powered down due to + * write to DPCD 600h = 2. Sink AUX CH is monitoring differential + * signal and may need up to 1 ms before being able to reply. + */ + if (status != DC_OK || dpcd_power_state == DP_SET_POWER_D3) { + udelay(1000); + aux_channel_retry_cnt++; + } + } + + /* If aux channel is not active, return false and trigger another detect*/ + if (status != DC_OK) { + dpcd_power_state = DP_SET_POWER_D0; + status = core_link_write_dpcd( + link, + DP_SET_POWER, + &dpcd_power_state, + sizeof(dpcd_power_state)); + + dpcd_power_state = DP_SET_POWER_D3; + status = core_link_write_dpcd( + link, + DP_SET_POWER, + &dpcd_power_state, + sizeof(dpcd_power_state)); + return false; + } + is_lttpr_present = dp_retrieve_lttpr_cap(link); - /* Read DP tunneling information. */ - status = dpcd_get_tunneling_device_data(link); - status = core_link_read_dpcd(link, DP_SET_POWER, - &dpcd_power_state, sizeof(dpcd_power_state)); + if (is_lttpr_present) + configure_lttpr_mode_transparent(link); - /* Delay 1 ms if AUX CH is in power down state. Based on spec - * section 2.3.1.2, if AUX CH may be powered down due to - * write to DPCD 600h = 2. Sink AUX CH is monitoring differential - * signal and may need up to 1 ms before being able to reply. - */ - if (status != DC_OK || dpcd_power_state == DP_SET_POWER_D3) - udelay(1000); + /* Read DP tunneling information. */ + status = dpcd_get_tunneling_device_data(link); dpcd_set_source_specific_data(link); /* Sink may need to configure internals based on vendor, so allow some @@ -6071,7 +6117,7 @@ bool dc_link_dp_set_test_pattern( /* Set DPCD Lane Settings before running test pattern */ if (p_link_settings != NULL) { if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) && - link->lttpr_mode == LTTPR_MODE_TRANSPARENT) { + p_link_settings->lttpr_mode == LTTPR_MODE_TRANSPARENT) { dp_fixed_vs_pe_set_retimer_lane_settings( link, p_link_settings->dpcd_lane_settings, @@ -7048,68 +7094,16 @@ void dp_enable_link_phy( enum clock_source_id clock_source, const struct dc_link_settings *link_settings) { - struct dc *dc = link->ctx->dc; - struct dmcu *dmcu = dc->res_pool->dmcu; - struct pipe_ctx *pipes = - link->dc->current_state->res_ctx.pipe_ctx; - struct clock_source *dp_cs = - link->dc->res_pool->dp_clock_source; - const struct link_hwss *link_hwss = get_link_hwss(link, link_res); - unsigned int i; - - if (link->connector_signal == SIGNAL_TYPE_EDP) { - if (!link->dc->config.edp_no_power_sequencing) - link->dc->hwss.edp_power_control(link, true); - link->dc->hwss.edp_wait_for_hpd_ready(link, true); - } - - /* If the current pixel clock source is not DTO(happens after - * switching from HDMI passive dongle to DP on the same connector), - * switch the pixel clock source to DTO. - */ - for (i = 0; i < MAX_PIPES; i++) { - if (pipes[i].stream != NULL && - pipes[i].stream->link == link) { - if (pipes[i].clock_source != NULL && - pipes[i].clock_source->id != CLOCK_SOURCE_ID_DP_DTO) { - pipes[i].clock_source = dp_cs; - pipes[i].stream_res.pix_clk_params.requested_pix_clk_100hz = - pipes[i].stream->timing.pix_clk_100hz; - pipes[i].clock_source->funcs->program_pix_clk( - pipes[i].clock_source, - &pipes[i].stream_res.pix_clk_params, - dp_get_link_encoding_format(link_settings), - &pipes[i].pll_settings); - } - } - } - link->cur_link_settings = *link_settings; - - if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING) { - if (dc->clk_mgr->funcs->notify_link_rate_change) - dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link); - } - - if (dmcu != NULL && dmcu->funcs->lock_phy) - dmcu->funcs->lock_phy(dmcu); - - if (link_hwss->ext.enable_dp_link_output) - link_hwss->ext.enable_dp_link_output(link, link_res, signal, - clock_source, link_settings); - - if (dmcu != NULL && dmcu->funcs->unlock_phy) - dmcu->funcs->unlock_phy(dmcu); - - dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_LINK_PHY); + link->dc->hwss.enable_dp_link_output(link, link_res, signal, + clock_source, link_settings); dp_receiver_power_ctrl(link, true); } void edp_add_delay_for_T9(struct dc_link *link) { - if (link->local_sink && - link->local_sink->edid_caps.panel_patch.extra_delay_backlight_off > 0) - udelay(link->local_sink->edid_caps.panel_patch.extra_delay_backlight_off * 1000); + if (link && link->panel_config.pps.extra_delay_backlight_off > 0) + udelay(link->panel_config.pps.extra_delay_backlight_off * 1000); } bool edp_receiver_ready_T9(struct dc_link *link) @@ -7165,9 +7159,8 @@ bool edp_receiver_ready_T7(struct dc_link *link) } while (time_taken_in_ns < 50 * 1000000); //MAx T7 is 50ms } - if (link->local_sink && - link->local_sink->edid_caps.panel_patch.extra_t7_ms > 0) - udelay(link->local_sink->edid_caps.panel_patch.extra_t7_ms * 1000); + if (link && link->panel_config.pps.extra_t7_ms > 0) + udelay(link->panel_config.pps.extra_t7_ms * 1000); return result; } @@ -7176,29 +7169,11 @@ void dp_disable_link_phy(struct dc_link *link, const struct link_resource *link_ enum signal_type signal) { struct dc *dc = link->ctx->dc; - struct dmcu *dmcu = dc->res_pool->dmcu; - const struct link_hwss *link_hwss = get_link_hwss(link, link_res); if (!link->wa_flags.dp_keep_receiver_powered) dp_receiver_power_ctrl(link, false); - if (signal == SIGNAL_TYPE_EDP) { - if (link->dc->hwss.edp_backlight_control) - link->dc->hwss.edp_backlight_control(link, false); - if (link_hwss->ext.disable_dp_link_output) - link_hwss->ext.disable_dp_link_output(link, link_res, signal); - link->dc->hwss.edp_power_control(link, false); - } else { - if (dmcu != NULL && dmcu->funcs->lock_phy) - dmcu->funcs->lock_phy(dmcu); - if (link_hwss->ext.disable_dp_link_output) - link_hwss->ext.disable_dp_link_output(link, link_res, signal); - if (dmcu != NULL && dmcu->funcs->unlock_phy) - dmcu->funcs->unlock_phy(dmcu); - } - - dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY); - + dc->hwss.disable_link_output(link, link_res, signal); /* Clear current link setting.*/ memset(&link->cur_link_settings, 0, sizeof(link->cur_link_settings)); @@ -7264,7 +7239,7 @@ void dp_set_hw_lane_settings( { const struct link_hwss *link_hwss = get_link_hwss(link, link_res); - if ((link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && !is_immediate_downstream(link, offset)) + if ((link_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && !is_immediate_downstream(link, offset)) return; if (link_hwss->ext.set_dp_lane_settings) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dpia.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dpia.c index 468e39589ed8..74e36b34d3f7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dpia.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dpia.c @@ -115,12 +115,14 @@ static enum link_training_result dpia_configure_link( DC_LOG_HW_LINK_TRAINING("%s\n DPIA(%d) configuring\n - LTTPR mode(%d)\n", __func__, link->link_id.enum_id - ENUM_ID_1, - link->lttpr_mode); + lt_settings->lttpr_mode); dp_decide_training_settings(link, link_setting, lt_settings); + dp_get_lttpr_mode_override(link, <_settings->lttpr_mode); + status = dpcd_configure_channel_coding(link, lt_settings); if (status != DC_OK && link->is_hpd_pending) return LINK_TRAINING_ABORT; @@ -178,7 +180,7 @@ static uint8_t dpia_build_set_config_data(enum dpia_set_config_type type, switch (type) { case DPIA_SET_CFG_SET_LINK: - data.set_link.mode = link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT ? 1 : 0; + data.set_link.mode = lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT ? 1 : 0; break; case DPIA_SET_CFG_SET_PHY_TEST_MODE: break; @@ -553,7 +555,7 @@ static enum link_training_result dpia_training_cr_phase( { enum link_training_result result = LINK_TRAINING_CR_FAIL_LANE0; - if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) + if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) result = dpia_training_cr_non_transparent(link, link_res, lt_settings, hop); else result = dpia_training_cr_transparent(link, link_res, lt_settings); @@ -830,7 +832,7 @@ static enum link_training_result dpia_training_eq_phase( { enum link_training_result result; - if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) + if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) result = dpia_training_eq_non_transparent(link, link_res, lt_settings, hop); else result = dpia_training_eq_transparent(link, link_res, lt_settings); @@ -870,13 +872,14 @@ static enum dc_status dpcd_clear_lt_pattern(struct dc_link *link, uint32_t hop) * @param hop The Hop in display path. DPRX = 0. */ static enum link_training_result dpia_training_end(struct dc_link *link, + struct link_training_settings *lt_settings, uint32_t hop) { enum link_training_result result = LINK_TRAINING_SUCCESS; uint8_t repeater_cnt = 0; /* Number of hops/repeaters in display path. */ enum dc_status status; - if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) { + if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) { repeater_cnt = dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt); if (hop == repeater_cnt) { /* DPTX-to-DPIA */ @@ -916,7 +919,7 @@ static enum link_training_result dpia_training_end(struct dc_link *link, link->link_id.enum_id - ENUM_ID_1, hop, result, - link->lttpr_mode); + lt_settings->lttpr_mode); return result; } @@ -928,7 +931,9 @@ static enum link_training_result dpia_training_end(struct dc_link *link, * @param link DPIA link being trained. * @param hop The Hop in display path. DPRX = 0. */ -static void dpia_training_abort(struct dc_link *link, uint32_t hop) +static void dpia_training_abort(struct dc_link *link, + struct link_training_settings *lt_settings, + uint32_t hop) { uint8_t data = 0; uint32_t dpcd_tps_offset = DP_TRAINING_PATTERN_SET; @@ -936,7 +941,7 @@ static void dpia_training_abort(struct dc_link *link, uint32_t hop) DC_LOG_HW_LINK_TRAINING("%s\n DPIA(%d) aborting\n - LTTPR mode(%d)\n - HPD(%d)\n", __func__, link->link_id.enum_id - ENUM_ID_1, - link->lttpr_mode, + lt_settings->lttpr_mode, link->is_hpd_pending); /* Abandon clean-up if sink unplugged. */ @@ -964,12 +969,16 @@ enum link_training_result dc_link_dpia_perform_link_training( uint8_t repeater_cnt = 0; /* Number of hops/repeaters in display path. */ int8_t repeater_id; /* Current hop. */ + struct dc_link_settings link_settings = *link_setting; // non-const copy to pass in + + lt_settings.lttpr_mode = dp_decide_lttpr_mode(link, &link_settings); + /* Configure link as prescribed in link_setting and set LTTPR mode. */ result = dpia_configure_link(link, link_res, link_setting, <_settings); if (result != LINK_TRAINING_SUCCESS) return result; - if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) + if (lt_settings.lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) repeater_cnt = dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt); /* Train each hop in turn starting with the one closest to DPTX. @@ -987,7 +996,7 @@ enum link_training_result dc_link_dpia_perform_link_training( break; /* Stop training hop. */ - result = dpia_training_end(link, repeater_id); + result = dpia_training_end(link, <_settings, repeater_id); if (result != LINK_TRAINING_SUCCESS) break; } @@ -1001,9 +1010,9 @@ enum link_training_result dc_link_dpia_perform_link_training( msleep(5); result = dp_check_link_loss_status(link, <_settings); } else if (result == LINK_TRAINING_ABORT) { - dpia_training_abort(link, repeater_id); + dpia_training_abort(link, <_settings, repeater_id); } else { - dpia_training_end(link, repeater_id); + dpia_training_end(link, <_settings, repeater_id); } return result; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index ccf7bd3d90fe..8ee0d946bb2f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1904,9 +1904,6 @@ bool dc_is_stream_unchanged( if (memcmp(&old_stream->audio_info, &stream->audio_info, sizeof(stream->audio_info)) != 0) return false; - if (old_stream->odm_2to1_policy_applied != stream->odm_2to1_policy_applied) - return false; - return true; } @@ -3665,3 +3662,25 @@ const struct link_hwss *get_link_hwss(const struct dc_link *link, else return get_virtual_link_hwss(); } + +bool is_h_timing_divisible_by_2(struct dc_stream_state *stream) +{ + bool divisible = false; + uint16_t h_blank_start = 0; + uint16_t h_blank_end = 0; + + if (stream) { + h_blank_start = stream->timing.h_total - stream->timing.h_front_porch; + h_blank_end = h_blank_start - stream->timing.h_addressable; + + /* HTOTAL, Hblank start/end, and Hsync start/end all must be + * divisible by 2 in order for the horizontal timing params + * to be considered divisible by 2. Hsync start is always 0. + */ + divisible = (stream->timing.h_total % 2 == 0) && + (h_blank_start % 2 == 0) && + (h_blank_end % 2 == 0) && + (stream->timing.h_sync_width % 2 == 0); + } + return divisible; +}
\ No newline at end of file diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 0c85ab5933b4..ae13887756bf 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -30,6 +30,7 @@ #include "resource.h" #include "ipp.h" #include "timing_generator.h" +#include "dc_dmub_srv.h" #define DC_LOGGER dc->ctx->logger @@ -519,7 +520,7 @@ bool dc_stream_remove_writeback(struct dc *dc, } /* remove writeback info for disabled writeback pipes from stream */ - for (i = 0, j = 0; i < stream->num_wb_info; i++) { + for (i = 0, j = 0; i < stream->num_wb_info && j < MAX_DWB_PIPES; i++) { if (stream->writeback_info[i].wb_enabled) { if (i != j) /* trim the array */ diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index dbf8158b832e..2ecf36e6329b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -47,7 +47,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.198" +#define DC_VER "3.2.205" #define MAX_SURFACES 3 #define MAX_PLANES 6 @@ -118,7 +118,26 @@ struct dc_plane_cap { uint32_t min_height; }; -// Color management caps (DPP and MPC) +/** + * DOC: color-management-caps + * + * **Color management caps (DPP and MPC)** + * + * Modules/color calculates various color operations which are translated to + * abstracted HW. DCE 5-12 had almost no important changes, but starting with + * DCN1, every new generation comes with fairly major differences in color + * pipeline. Therefore, we abstract color pipe capabilities so modules/DM can + * decide mapping to HW block based on logical capabilities. + */ + +/** + * struct rom_curve_caps - predefined transfer function caps for degamma and regamma + * @srgb: RGB color space transfer func + * @bt2020: BT.2020 transfer func + * @gamma2_2: standard gamma + * @pq: perceptual quantizer transfer function + * @hlg: hybrid log–gamma transfer function + */ struct rom_curve_caps { uint16_t srgb : 1; uint16_t bt2020 : 1; @@ -127,36 +146,68 @@ struct rom_curve_caps { uint16_t hlg : 1; }; +/** + * struct dpp_color_caps - color pipeline capabilities for display pipe and + * plane blocks + * + * @dcn_arch: all DCE generations treated the same + * @input_lut_shared: shared with DGAM. Input LUT is different than most LUTs, + * just plain 256-entry lookup + * @icsc: input color space conversion + * @dgam_ram: programmable degamma LUT + * @post_csc: post color space conversion, before gamut remap + * @gamma_corr: degamma correction + * @hw_3d_lut: 3D LUT support. It implies a shaper LUT before. It may be shared + * with MPC by setting mpc:shared_3d_lut flag + * @ogam_ram: programmable out/blend gamma LUT + * @ocsc: output color space conversion + * @dgam_rom_for_yuv: pre-defined degamma LUT for YUV planes + * @dgam_rom_caps: pre-definied curve caps for degamma 1D LUT + * @ogam_rom_caps: pre-definied curve caps for regamma 1D LUT + * + * Note: hdr_mult and gamut remap (CTM) are always available in DPP (in that order) + */ struct dpp_color_caps { - uint16_t dcn_arch : 1; // all DCE generations treated the same - // input lut is different than most LUTs, just plain 256-entry lookup - uint16_t input_lut_shared : 1; // shared with DGAM + uint16_t dcn_arch : 1; + uint16_t input_lut_shared : 1; uint16_t icsc : 1; uint16_t dgam_ram : 1; - uint16_t post_csc : 1; // before gamut remap + uint16_t post_csc : 1; uint16_t gamma_corr : 1; - - // hdr_mult and gamut remap always available in DPP (in that order) - // 3d lut implies shaper LUT, - // it may be shared with MPC - check MPC:shared_3d_lut flag uint16_t hw_3d_lut : 1; - uint16_t ogam_ram : 1; // blnd gam + uint16_t ogam_ram : 1; uint16_t ocsc : 1; uint16_t dgam_rom_for_yuv : 1; struct rom_curve_caps dgam_rom_caps; struct rom_curve_caps ogam_rom_caps; }; +/** + * struct mpc_color_caps - color pipeline capabilities for multiple pipe and + * plane combined blocks + * + * @gamut_remap: color transformation matrix + * @ogam_ram: programmable out gamma LUT + * @ocsc: output color space conversion matrix + * @num_3dluts: MPC 3D LUT; always assumes a preceding shaper LUT + * @shared_3d_lut: shared 3D LUT flag. Can be either DPP or MPC, but single + * instance + * @ogam_rom_caps: pre-definied curve caps for regamma 1D LUT + */ struct mpc_color_caps { uint16_t gamut_remap : 1; uint16_t ogam_ram : 1; uint16_t ocsc : 1; - uint16_t num_3dluts : 3; //3d lut always assumes a preceding shaper LUT - uint16_t shared_3d_lut:1; //can be in either DPP or MPC, but single instance - + uint16_t num_3dluts : 3; + uint16_t shared_3d_lut:1; struct rom_curve_caps ogam_rom_caps; }; +/** + * struct dc_color_caps - color pipes capabilities for DPP and MPC hw blocks + * @dpp: color pipes caps for DPP + * @mpc: color pipes caps for MPC + */ struct dc_color_caps { struct dpp_color_caps dpp; struct mpc_color_caps mpc; @@ -350,10 +401,14 @@ struct dc_config { uint8_t vblank_alignment_max_frame_time_diff; bool is_asymmetric_memory; bool is_single_rank_dimm; + bool is_vmin_only_asic; bool use_pipe_ctx_sync_logic; bool ignore_dpref_ss; bool enable_mipi_converter_optimization; bool use_default_clock_table; + bool force_bios_enable_lttpr; + uint8_t force_bios_fixed_vs; + }; enum visual_confirm { @@ -365,6 +420,7 @@ enum visual_confirm { VISUAL_CONFIRM_SWAPCHAIN = 6, VISUAL_CONFIRM_FAMS = 7, VISUAL_CONFIRM_SWIZZLE = 9, + VISUAL_CONFIRM_SUBVP = 14, }; enum dc_psr_power_opts { @@ -386,9 +442,31 @@ enum dcc_option { DCC_HALF_REQ_DISALBE = 2, }; +/** + * enum pipe_split_policy - Pipe split strategy supported by DCN + * + * This enum is used to define the pipe split policy supported by DCN. By + * default, DC favors MPC_SPLIT_DYNAMIC. + */ enum pipe_split_policy { + /** + * @MPC_SPLIT_DYNAMIC: DC will automatically decide how to split the + * pipe in order to bring the best trade-off between performance and + * power consumption. This is the recommended option. + */ MPC_SPLIT_DYNAMIC = 0, + + /** + * @MPC_SPLIT_DYNAMIC: Avoid pipe split, which means that DC will not + * try any sort of split optimization. + */ MPC_SPLIT_AVOID = 1, + + /** + * @MPC_SPLIT_DYNAMIC: With this option, DC will only try to optimize + * the pipe utilization when using a single display; if the user + * connects to a second display, DC will avoid pipe split. + */ MPC_SPLIT_AVOID_MULT_DISP = 2, }; @@ -623,6 +701,14 @@ struct dc_state; struct resource_pool; struct dce_hwseq; +/** + * struct dc_debug_options - DC debug struct + * + * This struct provides a simple mechanism for developers to change some + * configurations, enable/disable features, and activate extra debug options. + * This can be very handy to narrow down whether some specific feature is + * causing an issue or not. + */ struct dc_debug_options { bool native422_support; bool disable_dsc; @@ -642,6 +728,11 @@ struct dc_debug_options { bool disable_stutter; bool use_max_lb; enum dcc_option disable_dcc; + + /** + * @pipe_split_policy: Define which pipe split policy is used by the + * display core. + */ enum pipe_split_policy pipe_split_policy; bool force_single_disp_pipe_split; bool voltage_align_fclk; @@ -715,8 +806,6 @@ struct dc_debug_options { bool validate_dml_output; bool enable_dmcub_surface_flip; bool usbc_combo_phy_reset_wa; - bool disable_dsc_edp; - unsigned int force_dsc_edp_policy; bool enable_dram_clock_change_one_display_vactive; /* TODO - remove once tested */ bool legacy_dp2_lt; @@ -740,12 +829,14 @@ struct dc_debug_options { int crb_alloc_policy_min_disp_count; bool disable_z10; bool enable_z9_disable_interface; - bool enable_sw_cntl_psr; union dpia_debug_options dpia_debug; bool disable_fixed_vs_aux_timeout_wa; bool force_disable_subvp; bool force_subvp_mclk_switch; bool allow_sw_cursor_fallback; + unsigned int force_subvp_num_ways; + unsigned int force_mall_ss_num_ways; + bool alloc_extra_way_for_cursor; bool force_usr_allow; /* uses value at boot and disables switch */ bool disable_dtb_ref_clk_switch; @@ -759,7 +850,9 @@ struct dc_debug_options { bool use_legacy_soc_bb_mechanism; bool exit_idle_opt_for_cursor_updates; bool enable_single_display_2to1_odm_policy; + bool enable_double_buffered_dsc_pg_support; bool enable_dp_dig_pixel_rate_div_policy; + enum lttpr_mode lttpr_mode_override; }; struct gpu_info_soc_bounding_box_v1_0; @@ -815,6 +908,17 @@ struct dc { uint32_t *dcn_reg_offsets; uint32_t *nbio_reg_offsets; + + /* Scratch memory */ + struct { + struct { + /* + * For matching clock_limits table in driver with table + * from PMFW. + */ + struct _vcs_dpi_voltage_scaling_st clock_limits[DC__VOLTAGE_STATES]; + } update_bw_bounding_box; + } scratch; }; enum frame_buffer_mode { @@ -1018,6 +1122,7 @@ union surface_update_flags { uint32_t clock_change:1; uint32_t stereo_format_change:1; uint32_t lut_3d:1; + uint32_t tmz_changed:1; uint32_t full_update:1; } bits; @@ -1086,6 +1191,7 @@ struct dc_plane_state { /* private to dc_surface.c */ enum dc_irq_source irq_source; struct kref refcount; + struct tg_color visual_confirm_color; }; struct dc_plane_info { diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c index 52a61b3e5a8b..89d7d3fd3321 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -323,11 +323,13 @@ bool dc_dmub_srv_p_state_delegate(struct dc *dc, bool should_manage_pstate, stru struct dmub_cmd_fw_assisted_mclk_switch_config *config_data = &cmd.fw_assisted_mclk_switch.config_data; int i = 0; int ramp_up_num_steps = 1; // TODO: Ramp is currently disabled. Reenable it. - uint8_t visual_confirm_enabled = dc->debug.visual_confirm == VISUAL_CONFIRM_FAMS; + uint8_t visual_confirm_enabled; if (dc == NULL) return false; + visual_confirm_enabled = dc->debug.visual_confirm == VISUAL_CONFIRM_FAMS; + // Format command. cmd.fw_assisted_mclk_switch.header.type = DMUB_CMD__FW_ASSISTED_MCLK_SWITCH; cmd.fw_assisted_mclk_switch.header.sub_type = DMUB_CMD__FAMS_SETUP_FW_CTRL; @@ -387,6 +389,37 @@ void dc_dmub_srv_query_caps_cmd(struct dmub_srv *dmub) } } +void dc_dmub_srv_get_visual_confirm_color_cmd(struct dc *dc, struct pipe_ctx *pipe_ctx) +{ + union dmub_rb_cmd cmd = { 0 }; + enum dmub_status status; + unsigned int panel_inst = 0; + + dc_get_edp_link_panel_inst(dc, pipe_ctx->stream->link, &panel_inst); + + memset(&cmd, 0, sizeof(cmd)); + + // Prepare fw command + cmd.visual_confirm_color.header.type = DMUB_CMD__GET_VISUAL_CONFIRM_COLOR; + cmd.visual_confirm_color.header.sub_type = 0; + cmd.visual_confirm_color.header.ret_status = 1; + cmd.visual_confirm_color.header.payload_bytes = sizeof(struct dmub_cmd_visual_confirm_color_data); + cmd.visual_confirm_color.visual_confirm_color_data.visual_confirm_color.panel_inst = panel_inst; + + // Send command to fw + status = dmub_srv_cmd_with_reply_data(dc->ctx->dmub_srv->dmub, &cmd); + + ASSERT(status == DMUB_STATUS_OK); + + // If command was processed, copy feature caps to dmub srv + if (status == DMUB_STATUS_OK && + cmd.visual_confirm_color.header.ret_status == 0) { + memcpy(&dc->ctx->dmub_srv->dmub->visual_confirm_color, + &cmd.visual_confirm_color.visual_confirm_color_data, + sizeof(struct dmub_visual_confirm_color)); + } +} + #ifdef CONFIG_DRM_AMD_DC_DCN /** * *********************************************************************************************** @@ -602,7 +635,7 @@ static void populate_subvp_cmd_pipe_info(struct dc *dc, &cmd->fw_assisted_mclk_switch_v2.config_data.pipe_data[cmd_pipe_index]; struct dc_crtc_timing *main_timing = &subvp_pipe->stream->timing; struct dc_crtc_timing *phantom_timing = &subvp_pipe->stream->mall_stream_config.paired_stream->timing; - uint32_t out_num, out_den; + uint32_t out_num_stream, out_den_stream, out_num_plane, out_den_plane, out_num, out_den; pipe_data->mode = SUBVP; pipe_data->pipe_config.subvp_data.pix_clk_100hz = subvp_pipe->stream->timing.pix_clk_100hz; @@ -619,11 +652,16 @@ static void populate_subvp_cmd_pipe_info(struct dc *dc, /* Calculate the scaling factor from the src and dst height. * e.g. If 3840x2160 being downscaled to 1920x1080, the scaling factor is 1/2. * Reduce the fraction 1080/2160 = 1/2 for the "scaling factor" + * + * Make sure to combine stream and plane scaling together. */ - reduce_fraction(subvp_pipe->stream->src.height, subvp_pipe->stream->dst.height, &out_num, &out_den); - // TODO: Uncomment below lines once DMCUB include headers are promoted - //pipe_data->pipe_config.subvp_data.scale_factor_numerator = out_num; - //pipe_data->pipe_config.subvp_data.scale_factor_denominator = out_den; + reduce_fraction(subvp_pipe->stream->src.height, subvp_pipe->stream->dst.height, + &out_num_stream, &out_den_stream); + reduce_fraction(subvp_pipe->plane_state->src_rect.height, subvp_pipe->plane_state->dst_rect.height, + &out_num_plane, &out_den_plane); + reduce_fraction(out_num_stream * out_num_plane, out_den_stream * out_den_plane, &out_num, &out_den); + pipe_data->pipe_config.subvp_data.scale_factor_numerator = out_num; + pipe_data->pipe_config.subvp_data.scale_factor_denominator = out_den; // Prefetch lines is equal to VACTIVE + BP + VSYNC pipe_data->pipe_config.subvp_data.prefetch_lines = @@ -636,12 +674,28 @@ static void populate_subvp_cmd_pipe_info(struct dc *dc, pipe_data->pipe_config.subvp_data.processing_delay_lines = div64_u64(((uint64_t)(dc->caps.subvp_fw_processing_delay_us) * ((uint64_t)phantom_timing->pix_clk_100hz * 100) + ((uint64_t)phantom_timing->h_total * 1000000 - 1)), ((uint64_t)phantom_timing->h_total * 1000000)); + + if (subvp_pipe->bottom_pipe) { + pipe_data->pipe_config.subvp_data.main_split_pipe_index = subvp_pipe->bottom_pipe->pipe_idx; + } else if (subvp_pipe->next_odm_pipe) { + pipe_data->pipe_config.subvp_data.main_split_pipe_index = subvp_pipe->next_odm_pipe->pipe_idx; + } else { + pipe_data->pipe_config.subvp_data.main_split_pipe_index = 0; + } + // Find phantom pipe index based on phantom stream for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *phantom_pipe = &context->res_ctx.pipe_ctx[j]; if (phantom_pipe->stream == subvp_pipe->stream->mall_stream_config.paired_stream) { pipe_data->pipe_config.subvp_data.phantom_pipe_index = phantom_pipe->pipe_idx; + if (phantom_pipe->bottom_pipe) { + pipe_data->pipe_config.subvp_data.phantom_split_pipe_index = phantom_pipe->bottom_pipe->pipe_idx; + } else if (phantom_pipe->next_odm_pipe) { + pipe_data->pipe_config.subvp_data.phantom_split_pipe_index = phantom_pipe->next_odm_pipe->pipe_idx; + } else { + pipe_data->pipe_config.subvp_data.phantom_split_pipe_index = 0; + } break; } } @@ -686,7 +740,9 @@ void dc_dmub_setup_subvp_dmub_command(struct dc *dc, if (!pipe->stream) continue; - if (pipe->plane_state && !pipe->top_pipe && + /* For SubVP pipe count, only count the top most (ODM / MPC) pipe + */ + if (pipe->plane_state && !pipe->top_pipe && !pipe->prev_odm_pipe && pipe->stream->mall_stream_config.type == SUBVP_MAIN) subvp_pipes[subvp_count++] = pipe; } @@ -699,7 +755,12 @@ void dc_dmub_setup_subvp_dmub_command(struct dc *dc, if (!pipe->stream) continue; + /* When populating subvp cmd info, only pass in the top most (ODM / MPC) pipe. + * Any ODM or MPC splits being used in SubVP will be handled internally in + * populate_subvp_cmd_pipe_info + */ if (pipe->plane_state && pipe->stream->mall_stream_config.paired_stream && + !pipe->top_pipe && !pipe->prev_odm_pipe && pipe->stream->mall_stream_config.type == SUBVP_MAIN) { populate_subvp_cmd_pipe_info(dc, context, &cmd, pipe, cmd_pipe_index++); } else if (pipe->plane_state && pipe->stream->mall_stream_config.type == SUBVP_NONE) { diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h index 159782cd6659..7e438345b1a8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h @@ -78,12 +78,14 @@ void dc_dmub_srv_set_drr_manual_trigger_cmd(struct dc *dc, uint32_t tg_inst); bool dc_dmub_srv_p_state_delegate(struct dc *dc, bool enable_pstate, struct dc_state *context); void dc_dmub_srv_query_caps_cmd(struct dmub_srv *dmub); +void dc_dmub_srv_get_visual_confirm_color_cmd(struct dc *dc, struct pipe_ctx *pipe_ctx); void dc_dmub_srv_clear_inbox0_ack(struct dc_dmub_srv *dmub_srv); void dc_dmub_srv_wait_for_inbox0_ack(struct dc_dmub_srv *dmub_srv); void dc_dmub_srv_send_inbox0_cmd(struct dc_dmub_srv *dmub_srv, union dmub_inbox0_data_register data); bool dc_dmub_srv_get_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv, struct dmub_diagnostic_data *dmub_oca); +void dc_dmub_setup_subvp_dmub_command(struct dc *dc, struct dc_state *context, bool enable); void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv); #endif /* _DMUB_DC_SRV_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 584aaf6967fd..848db8676adf 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -417,19 +417,43 @@ enum dc_scan_direction { SCAN_DIRECTION_VERTICAL = 2, /* 90, 270 rotation */ }; +/** + * struct dc_cursor_position: Hardware cursor data. + * + * This struct keeps the action information related to the cursor that will be + * sent and received from our DC core. + */ struct dc_cursor_position { + /** + * @x: It represents the top left abscissa coordinate of the cursor. + */ uint32_t x; + + /** + * @y: It is the top ordinate of the cursor coordinate. + */ uint32_t y; + /** + * @x_hotspot: Define the abscissa point where mouse click happens. + */ uint32_t x_hotspot; + + /** + * @y_hotspot: Define the ordinate point where mouse click happens. + */ uint32_t y_hotspot; - /* - * This parameter indicates whether HW cursor should be enabled + /** + * @enable: This parameter indicates whether hardware cursor should be + * enabled. */ bool enable; - /* Translate cursor x/y by the source rectangle for each plane. */ + /** + * @translate_by_source: Translate cursor x/y by the source rectangle + * for each plane. + */ bool translate_by_source; }; @@ -494,7 +518,9 @@ struct dc_gamma { /* Used by both ipp amd opp functions*/ /* TODO: to be consolidated with enum color_space */ -/* +/** + * enum dc_cursor_color_format - DC cursor programming mode + * * This enum is for programming CURSOR_MODE register field. What this register * should be programmed to depends on OS requested cursor shape flags and what * we stored in the cursor surface. @@ -530,17 +556,39 @@ union dc_cursor_attribute_flags { }; struct dc_cursor_attributes { + /** + * @address: This field represents the framebuffer address associated + * with the cursor. It is important to highlight that this address is + * divided into a high and low parts. + */ PHYSICAL_ADDRESS_LOC address; + + /** + * @pitch: Cursor line stride. + */ uint32_t pitch; - /* Width and height should correspond to cursor surface width x heigh */ + /** + * @width: Width should correspond to cursor surface width. + */ uint32_t width; + /** + * @heigh: Height should correspond to cursor surface heigh. + */ uint32_t height; + /** + * @color_format: DC cursor programming mode. + */ enum dc_cursor_color_format color_format; - uint32_t sdr_white_level; // for boosting (SDR) cursor in HDR mode + /** + * @sdr_white_level: Boosting (SDR) cursor in HDR mode. + */ + uint32_t sdr_white_level; - /* In case we support HW Cursor rotation in the future */ + /** + * @rotation_angle: In case we support HW Cursor rotation in the future + */ enum dc_rotation_angle rotation_angle; union dc_cursor_attribute_flags attribute_flags; @@ -764,22 +812,108 @@ struct dc_dsc_config { bool is_dp; /* indicate if DSC is applied based on DP's capability */ uint32_t mst_pbn; /* pbn of display on dsc mst hub */ }; + +/** + * struct dc_crtc_timing - Timing parameters used to configure DCN blocks + * + * DCN provides multiple signals and parameters that can be used to adjust + * timing parameters, this struct aggregate multiple of these values for easy + * access. In this struct, fields prefixed with h_* are related to horizontal + * timing, and v_* to vertical timing. Keep in mind that when we talk about + * vertical timings, the values, in general, are described in the number of + * lines; on the other hand, the horizontal values are in pixels. + */ struct dc_crtc_timing { + /** + * @h_total: The total number of pixels from the rising edge of HSync + * until the rising edge of the current HSync. + */ uint32_t h_total; + + /** + * @h_border_left: The black pixels related to the left border + */ uint32_t h_border_left; + + /** + * @h_addressable: It is the range of pixels displayed horizontally. + * For example, if the display resolution is 3840@2160, the horizontal + * addressable area is 3840. + */ uint32_t h_addressable; + + /** + * @h_border_right: The black pixels related to the right border + */ uint32_t h_border_right; + + /** + * @h_front_porch: Period (in pixels) between HBlank start and the + * rising edge of HSync. + */ uint32_t h_front_porch; + + /** + * @h_sync_width: HSync duration in pixels. + */ uint32_t h_sync_width; + /** + * @v_total: It is the total number of lines from the rising edge of + * the previous VSync until the rising edge of the current VSync. + * + * |--------------------------| + * +-+ V_TOTAL +-+ + * | | | | + * VSync ---+ +--------- // -----------+ +--- + */ uint32_t v_total; + + /** + * @v_border_top: The black border on the top. + */ uint32_t v_border_top; + + /** + * @v_addressable: It is the range of the scanout at which the + * framebuffer is displayed. For example, if the display resolution is + * 3840@2160, the addressable area is 2160 lines, or if the resolution + * is 1920x1080, the addressable area is 1080 lines. + */ uint32_t v_addressable; + + /** + * @v_border_bottom: The black border on the bottom. + */ uint32_t v_border_bottom; + + /** + * @v_front_porch: Period (in lines) between VBlank start and rising + * edge of VSync. + * +-+ + * VSync | | + * ----------+ +--------... + * +------------------... + * VBlank | + * --+ + * |-------| + * v_front_porch + */ uint32_t v_front_porch; + + /** + * @v_sync_width: VSync signal width in lines. + */ uint32_t v_sync_width; + /** + * @pix_clk_100hz: Pipe pixel precision + * + * This field is used to communicate pixel clocks with 100 Hz accuracy + * from dc_crtc_timing to BIOS command table. + */ uint32_t pix_clk_100hz; + uint32_t min_refresh_in_uhz; uint32_t vic; diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index 9544abf75e84..bf5f9e2773bc 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -113,6 +113,32 @@ struct psr_settings { unsigned int psr_power_opt; }; +/* To split out "global" and "per-panel" config settings. + * Add a struct dc_panel_config under dc_link + */ +struct dc_panel_config { + // extra panel power sequence parameters + struct pps { + unsigned int extra_t3_ms; + unsigned int extra_t7_ms; + unsigned int extra_delay_backlight_off; + unsigned int extra_post_t7_ms; + unsigned int extra_pre_t11_ms; + unsigned int extra_t12_ms; + unsigned int extra_post_OUI_ms; + } pps; + // ABM + struct varib { + unsigned int varibright_feature_enable; + unsigned int def_varibright_level; + unsigned int abm_config_setting; + } varib; + // edp DSC + struct dsc { + bool disable_dsc_edp; + unsigned int force_dsc_edp_policy; + } dsc; +}; /* * A link contains one or more sinks and their connected status. * The currently active signal type (HDMI, DP-SST, DP-MST) is also reported. @@ -131,7 +157,6 @@ struct dc_link { bool link_state_valid; bool aux_access_disabled; bool sync_lt_in_progress; - enum lttpr_mode lttpr_mode; bool is_internal_display; /* TODO: Rename. Flag an endpoint as having a programmable mapping to a @@ -224,6 +249,7 @@ struct dc_link { bool dpia_mst_dsc_always_on; /* Forced DPIA into TBT3 compatibility mode. */ bool dpia_forced_tbt3_mode; + bool dongle_mode_timing_override; } wa_flags; struct link_mst_stream_allocation_table mst_stream_alloc_table; @@ -232,6 +258,8 @@ struct dc_link { struct gpio *hpd_gpio; enum dc_link_fec_state fec_state; + struct dc_panel_config panel_config; + struct phy_state phy_state; }; const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link); diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index f87f852d4829..9e6025c98db9 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -212,8 +212,7 @@ struct dc_stream_state { /* DMCU info */ unsigned int abm_level; - struct periodic_interrupt_config periodic_interrupt0; - struct periodic_interrupt_config periodic_interrupt1; + struct periodic_interrupt_config periodic_interrupt; /* from core_stream struct */ struct dc_context *ctx; @@ -268,8 +267,6 @@ struct dc_stream_state { bool has_non_synchronizable_pclk; bool vblank_synchronized; struct mall_stream_config mall_stream_config; - - bool odm_2to1_policy_applied; }; #define ABM_LEVEL_IMMEDIATE_DISABLE 255 @@ -283,8 +280,7 @@ struct dc_stream_update { struct dc_info_packet *hdr_static_metadata; unsigned int *abm_level; - struct periodic_interrupt_config *periodic_interrupt0; - struct periodic_interrupt_config *periodic_interrupt1; + struct periodic_interrupt_config *periodic_interrupt; struct dc_info_packet *vrr_infopacket; struct dc_info_packet *vsc_infopacket; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c index bdb6bac8dd97..c94a966c6612 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c @@ -300,7 +300,7 @@ static void set_high_bit_rate_capable( AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR, value); } -/* set video latency in in ms/2+1 */ +/* set video latency in ms/2+1 */ static void set_video_latency( struct audio *audio, int latency_in_ms) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c index 919c2c2ba84b..32782ef9ef77 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c @@ -814,12 +814,6 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc, "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER"); retry_on_defer = true; - fallthrough; - case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK: - if (*payload->reply == AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK) - DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, - LOG_FLAG_I2cAux_DceAux, - "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK"); if (aux_defer_retries >= AUX_MIN_DEFER_RETRIES && defer_time_in_ms >= AUX_MAX_DEFER_TIMEOUT_MS) { @@ -848,7 +842,11 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc, } } break; - + case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK: + DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, + LOG_FLAG_I2cAux_DceAux, + "dce_aux_transfer_with_retries: FAILURE: AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK"); + goto fail; case AUX_TRANSACTION_REPLY_I2C_DEFER: DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, LOG_FLAG_I2cAux_DceAux, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c index 0df06740ec39..bec5e9f787fc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c @@ -393,17 +393,18 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub, if (copy_settings_data->dsc_enable_status && link->dpcd_caps.sink_dev_id == DP_DEVICE_ID_38EC11 && !memcmp(link->dpcd_caps.sink_dev_id_str, DP_SINK_DEVICE_STR_ID_1, - sizeof(link->dpcd_caps.sink_dev_id_str))) + sizeof(DP_SINK_DEVICE_STR_ID_1))) link->psr_settings.force_ffu_mode = 1; else link->psr_settings.force_ffu_mode = 0; copy_settings_data->force_ffu_mode = link->psr_settings.force_ffu_mode; if (link->fec_state == dc_link_fec_enabled && + link->dpcd_caps.sink_dev_id == DP_DEVICE_ID_38EC11 && (!memcmp(link->dpcd_caps.sink_dev_id_str, DP_SINK_DEVICE_STR_ID_1, - sizeof(link->dpcd_caps.sink_dev_id_str)) || + sizeof(DP_SINK_DEVICE_STR_ID_1)) || !memcmp(link->dpcd_caps.sink_dev_id_str, DP_SINK_DEVICE_STR_ID_2, - sizeof(link->dpcd_caps.sink_dev_id_str)))) + sizeof(DP_SINK_DEVICE_STR_ID_2)))) copy_settings_data->debug.bitfields.force_wakeup_by_tps3 = 1; else copy_settings_data->debug.bitfields.force_wakeup_by_tps3 = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index aea49334021c..d260eaa1509e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -722,7 +722,6 @@ void dce110_edp_wait_for_hpd_ready( struct dc_context *ctx = link->ctx; struct graphics_object_id connector = link->link_enc->connector; struct gpio *hpd; - struct dc_sink *sink = link->local_sink; bool edp_hpd_high = false; uint32_t time_elapsed = 0; uint32_t timeout = power_up ? @@ -755,9 +754,9 @@ void dce110_edp_wait_for_hpd_ready( return; } - if (sink != NULL) { - if (sink->edid_caps.panel_patch.extra_t3_ms > 0) { - int extra_t3_in_ms = sink->edid_caps.panel_patch.extra_t3_ms; + if (link != NULL) { + if (link->panel_config.pps.extra_t3_ms > 0) { + int extra_t3_in_ms = link->panel_config.pps.extra_t3_ms; msleep(extra_t3_in_ms); } @@ -842,7 +841,7 @@ void dce110_edp_power_control( /* add time defined by a patch, if any (usually patch extra_t12_ms is 0) */ if (link->local_sink != NULL) remaining_min_edp_poweroff_time_ms += - link->local_sink->edid_caps.panel_patch.extra_t12_ms; + link->panel_config.pps.extra_t12_ms; /* Adjust remaining_min_edp_poweroff_time_ms if this is not the first time. */ if (dp_trace_get_edp_poweroff_timestamp(link) != 0) { @@ -946,7 +945,7 @@ void dce110_edp_wait_for_T12( current_ts, dp_trace_get_edp_poweroff_timestamp(link)), 1000000); - t12_duration += link->local_sink->edid_caps.panel_patch.extra_t12_ms; // Add extra T12 + t12_duration += link->panel_config.pps.extra_t12_ms; // Add extra T12 if (time_since_edp_poweroff_ms < t12_duration) msleep(t12_duration - time_since_edp_poweroff_ms); @@ -965,6 +964,8 @@ void dce110_edp_backlight_control( struct dc_context *ctx = link->ctx; struct bp_transmitter_control cntl = { 0 }; uint8_t panel_instance; + unsigned int pre_T11_delay = OLED_PRE_T11_DELAY; + unsigned int post_T7_delay = OLED_POST_T7_DELAY; if (dal_graphics_object_id_get_connector_id(link->link_enc->connector) != CONNECTOR_ID_EDP) { @@ -1043,8 +1044,10 @@ void dce110_edp_backlight_control( link_transmitter_control(ctx->dc_bios, &cntl); - if (enable && link->dpcd_sink_ext_caps.bits.oled) - msleep(OLED_POST_T7_DELAY); + if (enable && link->dpcd_sink_ext_caps.bits.oled) { + post_T7_delay += link->panel_config.pps.extra_post_t7_ms; + msleep(post_T7_delay); + } if (link->dpcd_sink_ext_caps.bits.oled || link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 1 || @@ -1066,8 +1069,10 @@ void dce110_edp_backlight_control( DC_LOG_DC("edp_receiver_ready_T9 skipped\n"); } - if (!enable && link->dpcd_sink_ext_caps.bits.oled) - msleep(OLED_PRE_T11_DELAY); + if (!enable && link->dpcd_sink_ext_caps.bits.oled) { + pre_T11_delay += link->panel_config.pps.extra_pre_t11_ms; + msleep(pre_T11_delay); + } } void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx) @@ -1441,6 +1446,14 @@ static enum dc_status dce110_enable_stream_timing( return DC_ERROR_UNEXPECTED; } + if (dc_is_hdmi_tmds_signal(stream->signal)) { + stream->link->phy_state.symclk_ref_cnts.otg = 1; + if (stream->link->phy_state.symclk_state == SYMCLK_OFF_TX_OFF) + stream->link->phy_state.symclk_state = SYMCLK_ON_TX_OFF; + else + stream->link->phy_state.symclk_state = SYMCLK_ON_TX_ON; + } + pipe_ctx->stream_res.tg->funcs->program_timing( pipe_ctx->stream_res.tg, &stream->timing, @@ -2114,6 +2127,7 @@ static void dce110_reset_hw_ctx_wrap( BREAK_TO_DEBUGGER(); } pipe_ctx_old->stream_res.tg->funcs->disable_crtc(pipe_ctx_old->stream_res.tg); + pipe_ctx_old->stream->link->phy_state.symclk_ref_cnts.otg = 0; pipe_ctx_old->plane_res.mi->funcs->free_mem_input( pipe_ctx_old->plane_res.mi, dc->current_state->stream_count); @@ -2164,8 +2178,7 @@ static void dce110_setup_audio_dto( continue; if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_TYPE_A) continue; - if (pipe_ctx->stream_res.audio != NULL && - pipe_ctx->stream_res.audio->enabled == false) { + if (pipe_ctx->stream_res.audio != NULL) { struct audio_output audio_output; build_audio_output(context, pipe_ctx, &audio_output); @@ -2205,8 +2218,7 @@ static void dce110_setup_audio_dto( if (!dc_is_dp_signal(pipe_ctx->stream->signal)) continue; - if (pipe_ctx->stream_res.audio != NULL && - pipe_ctx->stream_res.audio->enabled == false) { + if (pipe_ctx->stream_res.audio != NULL) { struct audio_output audio_output; build_audio_output(context, pipe_ctx, &audio_output); @@ -2994,6 +3006,124 @@ void dce110_set_pipe(struct pipe_ctx *pipe_ctx) abm->funcs->set_pipe(abm, otg_inst, panel_cntl->inst); } +void dce110_enable_lvds_link_output(struct dc_link *link, + const struct link_resource *link_res, + enum clock_source_id clock_source, + uint32_t pixel_clock) +{ + link->link_enc->funcs->enable_lvds_output( + link->link_enc, + clock_source, + pixel_clock); + link->phy_state.symclk_state = SYMCLK_ON_TX_ON; +} + +void dce110_enable_tmds_link_output(struct dc_link *link, + const struct link_resource *link_res, + enum signal_type signal, + enum clock_source_id clock_source, + enum dc_color_depth color_depth, + uint32_t pixel_clock) +{ + link->link_enc->funcs->enable_tmds_output( + link->link_enc, + clock_source, + color_depth, + signal, + pixel_clock); + link->phy_state.symclk_state = SYMCLK_ON_TX_ON; +} + +void dce110_enable_dp_link_output( + struct dc_link *link, + const struct link_resource *link_res, + enum signal_type signal, + enum clock_source_id clock_source, + const struct dc_link_settings *link_settings) +{ + struct dc *dc = link->ctx->dc; + struct dmcu *dmcu = dc->res_pool->dmcu; + struct pipe_ctx *pipes = + link->dc->current_state->res_ctx.pipe_ctx; + struct clock_source *dp_cs = + link->dc->res_pool->dp_clock_source; + const struct link_hwss *link_hwss = get_link_hwss(link, link_res); + unsigned int i; + + + if (link->connector_signal == SIGNAL_TYPE_EDP) { + if (!link->dc->config.edp_no_power_sequencing) + link->dc->hwss.edp_power_control(link, true); + link->dc->hwss.edp_wait_for_hpd_ready(link, true); + } + + /* If the current pixel clock source is not DTO(happens after + * switching from HDMI passive dongle to DP on the same connector), + * switch the pixel clock source to DTO. + */ + + for (i = 0; i < MAX_PIPES; i++) { + if (pipes[i].stream != NULL && + pipes[i].stream->link == link) { + if (pipes[i].clock_source != NULL && + pipes[i].clock_source->id != CLOCK_SOURCE_ID_DP_DTO) { + pipes[i].clock_source = dp_cs; + pipes[i].stream_res.pix_clk_params.requested_pix_clk_100hz = + pipes[i].stream->timing.pix_clk_100hz; + pipes[i].clock_source->funcs->program_pix_clk( + pipes[i].clock_source, + &pipes[i].stream_res.pix_clk_params, + dp_get_link_encoding_format(link_settings), + &pipes[i].pll_settings); + } + } + } + + if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING) { + if (dc->clk_mgr->funcs->notify_link_rate_change) + dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link); + } + + if (dmcu != NULL && dmcu->funcs->lock_phy) + dmcu->funcs->lock_phy(dmcu); + + if (link_hwss->ext.enable_dp_link_output) + link_hwss->ext.enable_dp_link_output(link, link_res, signal, + clock_source, link_settings); + + link->phy_state.symclk_state = SYMCLK_ON_TX_ON; + + if (dmcu != NULL && dmcu->funcs->unlock_phy) + dmcu->funcs->unlock_phy(dmcu); + + dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_LINK_PHY); +} + +void dce110_disable_link_output(struct dc_link *link, + const struct link_resource *link_res, + enum signal_type signal) +{ + struct dc *dc = link->ctx->dc; + const struct link_hwss *link_hwss = get_link_hwss(link, link_res); + struct dmcu *dmcu = dc->res_pool->dmcu; + + if (signal == SIGNAL_TYPE_EDP && + link->dc->hwss.edp_backlight_control) + link->dc->hwss.edp_backlight_control(link, false); + else if (dmcu != NULL && dmcu->funcs->lock_phy) + dmcu->funcs->lock_phy(dmcu); + + link_hwss->disable_link_output(link, link_res, signal); + link->phy_state.symclk_state = SYMCLK_OFF_TX_OFF; + + if (signal == SIGNAL_TYPE_EDP && + link->dc->hwss.edp_backlight_control) + link->dc->hwss.edp_power_control(link, false); + else if (dmcu != NULL && dmcu->funcs->lock_phy) + dmcu->funcs->unlock_phy(dmcu); + dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY); +} + static const struct hw_sequencer_funcs dce110_funcs = { .program_gamut_remap = program_gamut_remap, .program_output_csc = program_output_csc, @@ -3033,6 +3163,10 @@ static const struct hw_sequencer_funcs dce110_funcs = { .set_backlight_level = dce110_set_backlight_level, .set_abm_immediate_disable = dce110_set_abm_immediate_disable, .set_pipe = dce110_set_pipe, + .enable_lvds_link_output = dce110_enable_lvds_link_output, + .enable_tmds_link_output = dce110_enable_tmds_link_output, + .enable_dp_link_output = dce110_enable_dp_link_output, + .disable_link_output = dce110_disable_link_output, }; static const struct hwseq_private_funcs dce110_private_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h index b6f3843d3d05..758f4b3b0087 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -90,6 +90,24 @@ bool dce110_set_backlight_level(struct pipe_ctx *pipe_ctx, uint32_t frame_ramp); void dce110_set_abm_immediate_disable(struct pipe_ctx *pipe_ctx); void dce110_set_pipe(struct pipe_ctx *pipe_ctx); - +void dce110_disable_link_output(struct dc_link *link, + const struct link_resource *link_res, + enum signal_type signal); +void dce110_enable_lvds_link_output(struct dc_link *link, + const struct link_resource *link_res, + enum clock_source_id clock_source, + uint32_t pixel_clock); +void dce110_enable_tmds_link_output(struct dc_link *link, + const struct link_resource *link_res, + enum signal_type signal, + enum clock_source_id clock_source, + enum dc_color_depth color_depth, + uint32_t pixel_clock); +void dce110_enable_dp_link_output( + struct dc_link *link, + const struct link_resource *link_res, + enum signal_type signal, + enum clock_source_id clock_source, + const struct dc_link_settings *link_settings); #endif /* __DC_HWSS_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index db7ca4b0cdb9..897f412f539e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -448,11 +448,12 @@ void dpp1_set_cursor_position( src_y_offset = pos->y - pos->x_hotspot - param->viewport.y; } } else if (param->rotation == ROTATION_ANGLE_180) { - src_x_offset = pos->x - param->viewport.x; + if (!param->mirror) + src_x_offset = pos->x - param->viewport.x; + src_y_offset = pos->y - param->viewport.y; } - if (src_x_offset >= (int)param->viewport.width) cur_en = 0; /* not visible beyond right edge*/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c index 564e061ccb58..52e201e9b091 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c @@ -1208,13 +1208,10 @@ void hubp1_cursor_set_position( src_y_offset = pos->y - pos->x_hotspot - param->viewport.y; } } else if (param->rotation == ROTATION_ANGLE_180) { - src_x_offset = pos->x - param->viewport.x; - src_y_offset = pos->y - param->viewport.y; - } + if (!param->mirror) + src_x_offset = pos->x - param->viewport.x; - if (param->mirror) { - x_hotspot = param->viewport.width - x_hotspot; - src_x_offset = param->viewport.x + param->viewport.width - src_x_offset; + src_y_offset = pos->y - param->viewport.y; } dst_x_offset = (src_x_offset >= 0) ? src_x_offset : 0; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 5b5d952b2b8c..72521749c01d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -899,6 +899,14 @@ enum dc_status dcn10_enable_stream_timing( return DC_ERROR_UNEXPECTED; } + if (dc_is_hdmi_tmds_signal(stream->signal)) { + stream->link->phy_state.symclk_ref_cnts.otg = 1; + if (stream->link->phy_state.symclk_state == SYMCLK_OFF_TX_OFF) + stream->link->phy_state.symclk_state = SYMCLK_ON_TX_OFF; + else + stream->link->phy_state.symclk_state = SYMCLK_ON_TX_ON; + } + pipe_ctx->stream_res.tg->funcs->program_timing( pipe_ctx->stream_res.tg, &stream->timing, @@ -1017,6 +1025,7 @@ static void dcn10_reset_back_end_for_pipe( if (pipe_ctx->stream_res.tg->funcs->set_drr) pipe_ctx->stream_res.tg->funcs->set_drr( pipe_ctx->stream_res.tg, NULL); + pipe_ctx->stream->link->phy_state.symclk_ref_cnts.otg = 0; } for (i = 0; i < dc->res_pool->pipe_count; i++) @@ -2151,8 +2160,8 @@ static int dcn10_align_pixel_clocks(struct dc *dc, int group_size, dc->res_pool->dp_clock_source->funcs->get_pixel_clk_frequency_100hz( dc->res_pool->dp_clock_source, grouped_pipes[i]->stream_res.tg->inst, &pclk); - grouped_pipes[i]->stream->timing.pix_clk_100hz = - pclk*get_clock_divider(grouped_pipes[i], false); + grouped_pipes[i]->stream->timing.pix_clk_100hz = + pclk*get_clock_divider(grouped_pipes[i], false); if (master == -1) master = i; } @@ -2199,14 +2208,14 @@ void dcn10_enable_vblanks_synchronization( if (master >= 0) { for (i = 0; i < group_size; i++) { if (i != master && !grouped_pipes[i]->stream->has_non_synchronizable_pclk) - grouped_pipes[i]->stream_res.tg->funcs->align_vblanks( - grouped_pipes[master]->stream_res.tg, - grouped_pipes[i]->stream_res.tg, - grouped_pipes[master]->stream->timing.pix_clk_100hz, - grouped_pipes[i]->stream->timing.pix_clk_100hz, - get_clock_divider(grouped_pipes[master], false), - get_clock_divider(grouped_pipes[i], false)); - grouped_pipes[i]->stream->vblank_synchronized = true; + grouped_pipes[i]->stream_res.tg->funcs->align_vblanks( + grouped_pipes[master]->stream_res.tg, + grouped_pipes[i]->stream_res.tg, + grouped_pipes[master]->stream->timing.pix_clk_100hz, + grouped_pipes[i]->stream->timing.pix_clk_100hz, + get_clock_divider(grouped_pipes[master], false), + get_clock_divider(grouped_pipes[i], false)); + grouped_pipes[i]->stream->vblank_synchronized = true; } grouped_pipes[master]->stream->vblank_synchronized = true; DC_SYNC_INFO("Sync complete\n"); @@ -2539,8 +2548,10 @@ void dcn10_update_visual_confirm_color(struct dc *dc, struct pipe_ctx *pipe_ctx, color_space_to_black_color( dc, pipe_ctx->stream->output_color_space, color); - if (mpc->funcs->set_bg_color) + if (mpc->funcs->set_bg_color) { + memcpy(&pipe_ctx->plane_state->visual_confirm_color, color, sizeof(struct tg_color)); mpc->funcs->set_bg_color(mpc, color, mpcc_id); + } } void dcn10_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx) @@ -3340,11 +3351,11 @@ static bool dcn10_dmub_should_update_cursor_data( if (pipe_ctx->plane_state->address.type == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE) return false; - if (pipe_ctx->stream->link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) - return true; + if (dcn10_can_pipe_disable_cursor(pipe_ctx)) + return false; - if (pipe_ctx->stream->link->psr_settings.psr_version == DC_PSR_VERSION_1 && - debug->enable_sw_cntl_psr) + if ((pipe_ctx->stream->link->psr_settings.psr_version == DC_PSR_VERSION_SU_1 || pipe_ctx->stream->link->psr_settings.psr_version == DC_PSR_VERSION_1) + && pipe_ctx->stream->ctx->dce_version >= DCN_VERSION_3_1) return true; return false; @@ -3468,8 +3479,7 @@ void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx) .rotation = pipe_ctx->plane_state->rotation, .mirror = pipe_ctx->plane_state->horizontal_mirror }; - bool pipe_split_on = (pipe_ctx->top_pipe != NULL) || - (pipe_ctx->bottom_pipe != NULL); + bool pipe_split_on = false; bool odm_combine_on = (pipe_ctx->next_odm_pipe != NULL) || (pipe_ctx->prev_odm_pipe != NULL); @@ -3478,6 +3488,13 @@ void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx) int x_pos = pos_cpy.x; int y_pos = pos_cpy.y; + if ((pipe_ctx->top_pipe != NULL) || (pipe_ctx->bottom_pipe != NULL)) { + if ((pipe_ctx->plane_state->src_rect.width != pipe_ctx->plane_res.scl_data.viewport.width) || + (pipe_ctx->plane_state->src_rect.height != pipe_ctx->plane_res.scl_data.viewport.height)) { + pipe_split_on = true; + } + } + /** * DC cursor is stream space, HW cursor is plane space and drawn * as part of the framebuffer. @@ -3549,8 +3566,36 @@ void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx) if (pos_cpy.enable && dcn10_can_pipe_disable_cursor(pipe_ctx)) pos_cpy.enable = false; + + if (param.rotation == ROTATION_ANGLE_0) { + int viewport_width = + pipe_ctx->plane_res.scl_data.viewport.width; + int viewport_x = + pipe_ctx->plane_res.scl_data.viewport.x; + + if (param.mirror) { + if (pipe_split_on || odm_combine_on) { + if (pos_cpy.x >= viewport_width + viewport_x) { + pos_cpy.x = 2 * viewport_width + - pos_cpy.x + 2 * viewport_x; + } else { + uint32_t temp_x = pos_cpy.x; + + pos_cpy.x = 2 * viewport_x - pos_cpy.x; + if (temp_x >= viewport_x + + (int)hubp->curs_attr.width || pos_cpy.x + <= (int)hubp->curs_attr.width + + pipe_ctx->plane_state->src_rect.x) { + pos_cpy.x = temp_x + viewport_width; + } + } + } else { + pos_cpy.x = viewport_width - pos_cpy.x + 2 * viewport_x; + } + } + } // Swap axis and mirror horizontally - if (param.rotation == ROTATION_ANGLE_90) { + else if (param.rotation == ROTATION_ANGLE_90) { uint32_t temp_x = pos_cpy.x; pos_cpy.x = pipe_ctx->plane_res.scl_data.viewport.width - @@ -3621,23 +3666,25 @@ void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx) int viewport_x = pipe_ctx->plane_res.scl_data.viewport.x; - if (pipe_split_on || odm_combine_on) { - if (pos_cpy.x >= viewport_width + viewport_x) { - pos_cpy.x = 2 * viewport_width - - pos_cpy.x + 2 * viewport_x; - } else { - uint32_t temp_x = pos_cpy.x; - - pos_cpy.x = 2 * viewport_x - pos_cpy.x; - if (temp_x >= viewport_x + - (int)hubp->curs_attr.width || pos_cpy.x - <= (int)hubp->curs_attr.width + - pipe_ctx->plane_state->src_rect.x) { - pos_cpy.x = temp_x + viewport_width; + if (!param.mirror) { + if (pipe_split_on || odm_combine_on) { + if (pos_cpy.x >= viewport_width + viewport_x) { + pos_cpy.x = 2 * viewport_width + - pos_cpy.x + 2 * viewport_x; + } else { + uint32_t temp_x = pos_cpy.x; + + pos_cpy.x = 2 * viewport_x - pos_cpy.x; + if (temp_x >= viewport_x + + (int)hubp->curs_attr.width || pos_cpy.x + <= (int)hubp->curs_attr.width + + pipe_ctx->plane_state->src_rect.x) { + pos_cpy.x = temp_x + viewport_width; + } } + } else { + pos_cpy.x = viewport_width - pos_cpy.x + 2 * viewport_x; } - } else { - pos_cpy.x = viewport_width - pos_cpy.x + 2 * viewport_x; } /** @@ -3738,7 +3785,6 @@ int dcn10_get_vupdate_offset_from_vsync(struct pipe_ctx *pipe_ctx) int vesa_sync_start; int asic_blank_end; int interlace_factor; - int vertical_line_start; patched_crtc_timing = *dc_crtc_timing; apply_front_porch_workaround(&patched_crtc_timing); @@ -3754,10 +3800,8 @@ int dcn10_get_vupdate_offset_from_vsync(struct pipe_ctx *pipe_ctx) patched_crtc_timing.v_border_top) * interlace_factor; - vertical_line_start = asic_blank_end - + return asic_blank_end - pipe_ctx->pipe_dlg_param.vstartup_start + 1; - - return vertical_line_start; } void dcn10_calc_vupdate_position( @@ -3768,7 +3812,7 @@ void dcn10_calc_vupdate_position( { const struct dc_crtc_timing *dc_crtc_timing = &pipe_ctx->stream->timing; int vline_int_offset_from_vupdate = - pipe_ctx->stream->periodic_interrupt0.lines_offset; + pipe_ctx->stream->periodic_interrupt.lines_offset; int vupdate_offset_from_vsync = dc->hwss.get_vupdate_offset_from_vsync(pipe_ctx); int start_position; @@ -3793,18 +3837,10 @@ void dcn10_calc_vupdate_position( static void dcn10_cal_vline_position( struct dc *dc, struct pipe_ctx *pipe_ctx, - enum vline_select vline, uint32_t *start_line, uint32_t *end_line) { - enum vertical_interrupt_ref_point ref_point = INVALID_POINT; - - if (vline == VLINE0) - ref_point = pipe_ctx->stream->periodic_interrupt0.ref_point; - else if (vline == VLINE1) - ref_point = pipe_ctx->stream->periodic_interrupt1.ref_point; - - switch (ref_point) { + switch (pipe_ctx->stream->periodic_interrupt.ref_point) { case START_V_UPDATE: dcn10_calc_vupdate_position( dc, @@ -3813,7 +3849,9 @@ static void dcn10_cal_vline_position( end_line); break; case START_V_SYNC: - // Suppose to do nothing because vsync is 0; + // vsync is line 0 so start_line is just the requested line offset + *start_line = pipe_ctx->stream->periodic_interrupt.lines_offset; + *end_line = *start_line + 2; break; default: ASSERT(0); @@ -3823,24 +3861,15 @@ static void dcn10_cal_vline_position( void dcn10_setup_periodic_interrupt( struct dc *dc, - struct pipe_ctx *pipe_ctx, - enum vline_select vline) + struct pipe_ctx *pipe_ctx) { struct timing_generator *tg = pipe_ctx->stream_res.tg; + uint32_t start_line = 0; + uint32_t end_line = 0; - if (vline == VLINE0) { - uint32_t start_line = 0; - uint32_t end_line = 0; - - dcn10_cal_vline_position(dc, pipe_ctx, vline, &start_line, &end_line); + dcn10_cal_vline_position(dc, pipe_ctx, &start_line, &end_line); - tg->funcs->setup_vertical_interrupt0(tg, start_line, end_line); - - } else if (vline == VLINE1) { - pipe_ctx->stream_res.tg->funcs->setup_vertical_interrupt1( - tg, - pipe_ctx->stream->periodic_interrupt1.lines_offset); - } + tg->funcs->setup_vertical_interrupt0(tg, start_line, end_line); } void dcn10_setup_vupdate_interrupt(struct dc *dc, struct pipe_ctx *pipe_ctx) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h index 9ae07c77fdc0..0ef7bf7ddb75 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h @@ -175,8 +175,7 @@ void dcn10_set_cursor_attribute(struct pipe_ctx *pipe_ctx); void dcn10_set_cursor_sdr_white_level(struct pipe_ctx *pipe_ctx); void dcn10_setup_periodic_interrupt( struct dc *dc, - struct pipe_ctx *pipe_ctx, - enum vline_select vline); + struct pipe_ctx *pipe_ctx); enum dc_status dcn10_set_clock(struct dc *dc, enum dc_clock_type clock_type, uint32_t clk_khz, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c index 10e613ec7d24..f2371c948822 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c @@ -82,6 +82,10 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .set_backlight_level = dce110_set_backlight_level, .set_abm_immediate_disable = dce110_set_abm_immediate_disable, .set_pipe = dce110_set_pipe, + .enable_lvds_link_output = dce110_enable_lvds_link_output, + .enable_tmds_link_output = dce110_enable_tmds_link_output, + .enable_dp_link_output = dce110_enable_dp_link_output, + .disable_link_output = dce110_disable_link_output, .get_dcc_en_bits = dcn10_get_dcc_en_bits, .update_visual_confirm_color = dcn10_update_visual_confirm_color, }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c index 3fc300cd1ce9..ea7739255119 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c @@ -312,6 +312,20 @@ void optc1_program_timing( } } +/** + * optc1_set_vtg_params - Set Vertical Timing Generator (VTG) parameters + * + * @optc: timing_generator struct used to extract the optc parameters + * @dc_crtc_timing: Timing parameters configured + * @program_fp2: Boolean value indicating if FP2 will be programmed or not + * + * OTG is responsible for generating the global sync signals, including + * vertical timing information for each HUBP in the dcfclk domain. Each VTG is + * associated with one OTG that provides HUBP with vertical timing information + * (i.e., there is 1:1 correspondence between OTG and VTG). This function is + * responsible for setting the OTG parameters to the VTG during the pipe + * programming. + */ void optc1_set_vtg_params(struct timing_generator *optc, const struct dc_crtc_timing *dc_crtc_timing, bool program_fp2) { @@ -1072,7 +1086,7 @@ static void optc1_set_test_pattern( src_color[index] >> (src_bpc - dst_bpc); /* CRTC_TEST_PATTERN_DATA has 16 bits, * lowest 6 are hardwired to ZERO - * color bits should be left aligned aligned to MSB + * color bits should be left aligned to MSB * XXXXXXXXXX000000 for 10 bit, * XXXXXXXX00000000 for 8 bit and XXXXXX0000000000 for 6 */ @@ -1379,6 +1393,12 @@ void optc1_read_otg_state(struct optc *optc1, REG_GET(OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_OCCURRED_STATUS, &s->underflow_occurred_status); + REG_GET(OTG_VERTICAL_INTERRUPT1_CONTROL, + OTG_VERTICAL_INTERRUPT1_INT_ENABLE, &s->vertical_interrupt1_en); + + REG_GET(OTG_VERTICAL_INTERRUPT1_POSITION, + OTG_VERTICAL_INTERRUPT1_LINE_START, &s->vertical_interrupt1_line); + REG_GET(OTG_VERTICAL_INTERRUPT2_CONTROL, OTG_VERTICAL_INTERRUPT2_INT_ENABLE, &s->vertical_interrupt2_en); @@ -1498,8 +1518,23 @@ bool optc1_configure_crc(struct timing_generator *optc, return true; } +/** + * optc1_get_crc - Capture CRC result per component + * + * @optc: timing_generator instance. + * @r_cr: 16-bit primary CRC signature for red data. + * @g_y: 16-bit primary CRC signature for green data. + * @b_cb: 16-bit primary CRC signature for blue data. + * + * This function reads the CRC signature from the OPTC registers. Notice that + * we have three registers to keep the CRC result per color component (RGB). + * + * Returns: + * If CRC is disabled, return false; otherwise, return true, and the CRC + * results in the parameters. + */ bool optc1_get_crc(struct timing_generator *optc, - uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb) + uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb) { uint32_t field = 0; struct optc *optc1 = DCN10TG_FROM_TG(optc); @@ -1510,12 +1545,14 @@ bool optc1_get_crc(struct timing_generator *optc, if (!field) return false; + /* OTG_CRC0_DATA_RG has the CRC16 results for the red and green component */ REG_GET_2(OTG_CRC0_DATA_RG, - CRC0_R_CR, r_cr, - CRC0_G_Y, g_y); + CRC0_R_CR, r_cr, + CRC0_G_Y, g_y); + /* OTG_CRC0_DATA_B has the CRC16 results for the blue component */ REG_GET(OTG_CRC0_DATA_B, - CRC0_B_CB, b_cb); + CRC0_B_CB, b_cb); return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h index 3fe5882ed018..6323ca6dc3b3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h @@ -583,6 +583,8 @@ struct dcn_otg_state { uint32_t underflow_occurred_status; uint32_t otg_enabled; uint32_t blank_enabled; + uint32_t vertical_interrupt1_en; + uint32_t vertical_interrupt1_line; uint32_t vertical_interrupt2_en; uint32_t vertical_interrupt2_line; }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 174eebbe8b4f..831080b9eb87 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1495,6 +1495,24 @@ static bool dcn10_resource_construct( /* Other architectures we build for build this with soft-float */ dcn10_resource_construct_fp(dc); + if (!dc->config.is_vmin_only_asic) + if (ASICREV_IS_RAVEN2(dc->ctx->asic_id.hw_internal_rev)) + switch (dc->ctx->asic_id.pci_revision_id) { + case PRID_DALI_DE: + case PRID_DALI_DF: + case PRID_DALI_E3: + case PRID_DALI_E4: + case PRID_POLLOCK_94: + case PRID_POLLOCK_95: + case PRID_POLLOCK_E9: + case PRID_POLLOCK_EA: + case PRID_POLLOCK_EB: + dc->config.is_vmin_only_asic = true; + break; + default: + break; + } + pool->base.pp_smu = dcn10_pp_smu_create(ctx); /* diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h index 2b9d3e63191b..915a20461c77 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h @@ -274,6 +274,7 @@ struct dccg_registers { uint32_t DSCCLK2_DTO_PARAM; uint32_t DPSTREAMCLK_ROOT_GATE_DISABLE; uint32_t DPSTREAMCLK_GATE_DISABLE; + uint32_t DCCG_GATE_DISABLE_CNTL; uint32_t DCCG_GATE_DISABLE_CNTL2; uint32_t DCCG_GATE_DISABLE_CNTL3; uint32_t HDMISTREAMCLK0_DTO_PARAM; diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c index 9570c2118ccc..b1ec0e6f7f58 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c @@ -987,13 +987,10 @@ void hubp2_cursor_set_position( src_y_offset = pos->y - pos->x_hotspot - param->viewport.y; } } else if (param->rotation == ROTATION_ANGLE_180) { - src_x_offset = pos->x - param->viewport.x; - src_y_offset = pos->y - param->viewport.y; - } + if (!param->mirror) + src_x_offset = pos->x - param->viewport.x; - if (param->mirror) { - x_hotspot = param->viewport.width - x_hotspot; - src_x_offset = param->viewport.x + param->viewport.width - src_x_offset; + src_y_offset = pos->y - param->viewport.y; } dst_x_offset = (src_x_offset >= 0) ? src_x_offset : 0; diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index 598ce872a8d7..e1d271fe9e64 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -706,6 +706,14 @@ enum dc_status dcn20_enable_stream_timing( return DC_ERROR_UNEXPECTED; } + if (dc_is_hdmi_tmds_signal(stream->signal)) { + stream->link->phy_state.symclk_ref_cnts.otg = 1; + if (stream->link->phy_state.symclk_state == SYMCLK_OFF_TX_OFF) + stream->link->phy_state.symclk_state = SYMCLK_ON_TX_OFF; + else + stream->link->phy_state.symclk_state = SYMCLK_ON_TX_ON; + } + if (dc->hwseq->funcs.PLAT_58856_wa && (!dc_is_dp_signal(stream->signal))) dc->hwseq->funcs.PLAT_58856_wa(context, pipe_ctx); @@ -1899,8 +1907,14 @@ void dcn20_post_unlock_program_front_end( * can underflow due to HUBP_VTG_SEL programming if done in the regular front end * programming sequence). */ - if (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) + while (pipe) { + if (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { + if (dc->hwss.update_phantom_vp_position) + dc->hwss.update_phantom_vp_position(dc, context, pipe); dcn20_program_pipe(dc, pipe, context); + } + pipe = pipe->bottom_pipe; + } } } @@ -2347,7 +2361,9 @@ static void dcn20_reset_back_end_for_pipe( struct dc_state *context) { int i; - struct dc_link *link; + struct dc_link *link = pipe_ctx->stream->link; + const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res); + DC_LOGGER_INIT(dc->ctx->logger); if (pipe_ctx->stream_res.stream_enc == NULL) { pipe_ctx->stream = NULL; @@ -2355,7 +2371,6 @@ static void dcn20_reset_back_end_for_pipe( } if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { - link = pipe_ctx->stream->link; /* DPMS may already disable or */ /* dpms_off status is incorrect due to fastboot * feature. When system resume from S4 with second @@ -2404,6 +2419,16 @@ static void dcn20_reset_back_end_for_pipe( if (pipe_ctx->stream_res.tg->funcs->set_drr) pipe_ctx->stream_res.tg->funcs->set_drr( pipe_ctx->stream_res.tg, NULL); + /* TODO - convert symclk_ref_cnts for otg to a bit map to solve + * the case where the same symclk is shared across multiple otg + * instances + */ + link->phy_state.symclk_ref_cnts.otg = 0; + if (link->phy_state.symclk_state == SYMCLK_ON_TX_OFF) { + link_hwss->disable_link_output(link, + &pipe_ctx->link_res, pipe_ctx->stream->signal); + link->phy_state.symclk_state = SYMCLK_OFF_TX_OFF; + } } for (i = 0; i < dc->res_pool->pipe_count; i++) @@ -2463,9 +2488,13 @@ void dcn20_update_visual_confirm_color(struct dc *dc, struct pipe_ctx *pipe_ctx, get_mpctree_visual_confirm_color(pipe_ctx, color); else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SWIZZLE) get_surface_tile_visual_confirm_color(pipe_ctx, color); + else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SUBVP) + get_subvp_visual_confirm_color(dc, pipe_ctx, color); - if (mpc->funcs->set_bg_color) + if (mpc->funcs->set_bg_color) { + memcpy(&pipe_ctx->plane_state->visual_confirm_color, color, sizeof(struct tg_color)); mpc->funcs->set_bg_color(mpc, color, mpcc_id); + } } void dcn20_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c index 91e4885b743e..7c5817c426fa 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c @@ -96,6 +96,10 @@ static const struct hw_sequencer_funcs dcn20_funcs = { #ifndef TRIM_FSFT .optimize_timing_for_fsft = dcn20_optimize_timing_for_fsft, #endif + .enable_lvds_link_output = dce110_enable_lvds_link_output, + .enable_tmds_link_output = dce110_enable_tmds_link_output, + .enable_dp_link_output = dce110_enable_dp_link_output, + .disable_link_output = dce110_disable_link_output, .set_disp_pattern_generator = dcn20_set_disp_pattern_generator, .get_dcc_en_bits = dcn10_get_dcc_en_bits, .update_visual_confirm_color = dcn20_update_visual_confirm_color diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mmhubbub.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mmhubbub.c index 694260c10a01..ccd91792991b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mmhubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mmhubbub.c @@ -215,7 +215,8 @@ void mmhubbub2_config_mcif_irq(struct mcif_wb *mcif_wb, REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_OVERRUN_INT_EN, params->sw_overrun_int_en); REG_UPDATE(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_INT_EN, params->vce_int_en); - REG_UPDATE(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_SLICE_INT_EN, params->vce_slice_int_en); + if (mcif_wb20->mcif_wb_mask->MCIF_WB_BUFMGR_VCE_SLICE_INT_EN) + REG_UPDATE(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_SLICE_INT_EN, params->vce_slice_int_en); } void mmhubbub2_enable_mcif(struct mcif_wb *mcif_wb) diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hwseq.c index 05b3fba9ccce..61bcfa03c4e7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hwseq.c @@ -82,7 +82,7 @@ static bool patch_address_for_sbs_tb_stereo( return false; } -static void gpu_addr_to_uma(struct dce_hwseq *hwseq, +static bool gpu_addr_to_uma(struct dce_hwseq *hwseq, PHYSICAL_ADDRESS_LOC *addr) { bool is_in_uma; @@ -98,6 +98,7 @@ static void gpu_addr_to_uma(struct dce_hwseq *hwseq, } else { is_in_uma = false; } + return is_in_uma; } static void plane_address_in_gpu_space_to_uma(struct dce_hwseq *hwseq, diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_init.c b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_init.c index 1826dd7f3da1..9c16633e473a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_init.c @@ -86,6 +86,10 @@ static const struct hw_sequencer_funcs dcn201_funcs = { .set_backlight_level = dce110_set_backlight_level, .set_abm_immediate_disable = dce110_set_abm_immediate_disable, .set_pipe = dce110_set_pipe, + .enable_lvds_link_output = dce110_enable_lvds_link_output, + .enable_tmds_link_output = dce110_enable_tmds_link_output, + .enable_dp_link_output = dce110_enable_dp_link_output, + .disable_link_output = dce110_disable_link_output, .set_disp_pattern_generator = dcn20_set_disp_pattern_generator, .update_visual_confirm_color = dcn20_update_visual_confirm_color, }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c index b270f0b194dc..fe1a8e2e08ef 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c @@ -99,6 +99,10 @@ static const struct hw_sequencer_funcs dcn21_funcs = { #ifndef TRIM_FSFT .optimize_timing_for_fsft = dcn20_optimize_timing_for_fsft, #endif + .enable_lvds_link_output = dce110_enable_lvds_link_output, + .enable_tmds_link_output = dce110_enable_tmds_link_output, + .enable_dp_link_output = dce110_enable_dp_link_output, + .disable_link_output = dce110_disable_link_output, .is_abm_supported = dcn21_is_abm_supported, .set_disp_pattern_generator = dcn20_set_disp_pattern_generator, .get_dcc_en_bits = dcn10_get_dcc_en_bits, diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c index fb59fed8f425..8c5045711264 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c @@ -939,13 +939,32 @@ bool dcn30_does_plane_fit_in_mall(struct dc *dc, struct dc_plane_state *plane, s void dcn30_hardware_release(struct dc *dc) { + bool subvp_in_use = false; + uint32_t i; + dc_dmub_srv_p_state_delegate(dc, false, NULL); + dc_dmub_setup_subvp_dmub_command(dc, dc->current_state, false); + + /* SubVP treated the same way as FPO. If driver disable and + * we are using a SubVP config, disable and force on DCN side + * to prevent P-State hang on driver enable. + */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; + if (!pipe->stream) + continue; + + if (pipe->stream->mall_stream_config.type == SUBVP_MAIN) { + subvp_in_use = true; + break; + } + } /* If pstate unsupported, or still supported * by firmware, force it supported by dcn */ if (dc->current_state) - if ((!dc->clk_mgr->clks.p_state_change_support || + if ((!dc->clk_mgr->clks.p_state_change_support || subvp_in_use || dc->current_state->bw_ctx.bw.dcn.clk.fw_based_mclk_switching) && dc->res_pool->hubbub->funcs->force_pstate_change_control) dc->res_pool->hubbub->funcs->force_pstate_change_control( diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c index 4c06e6e1ba4a..3216d10c58ba 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c @@ -100,6 +100,10 @@ static const struct hw_sequencer_funcs dcn30_funcs = { .set_abm_immediate_disable = dcn21_set_abm_immediate_disable, .hardware_release = dcn30_hardware_release, .set_pipe = dcn21_set_pipe, + .enable_lvds_link_output = dce110_enable_lvds_link_output, + .enable_tmds_link_output = dce110_enable_tmds_link_output, + .enable_dp_link_output = dce110_enable_dp_link_output, + .disable_link_output = dce110_disable_link_output, .set_disp_pattern_generator = dcn30_set_disp_pattern_generator, .get_dcc_en_bits = dcn10_get_dcc_en_bits, .update_visual_confirm_color = dcn20_update_visual_confirm_color, diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mmhubbub.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mmhubbub.h index f2580e65196c..7446e54bf5aa 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mmhubbub.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mmhubbub.h @@ -227,11 +227,7 @@ SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_C, MCIF_WB_BUF_3_ADDR_C, mask_sh),\ SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_Y, MCIF_WB_BUF_4_ADDR_Y, mask_sh),\ SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_C, MCIF_WB_BUF_4_ADDR_C, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_LOCK_IGNORE, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_INT_EN, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_INT_ACK, mask_sh),\ SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_SLICE_INT_EN, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_LOCK, mask_sh),\ SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_SLICE_SIZE, mask_sh),\ SF(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_REFRESH_WATERMARK, mask_sh),\ SF(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_WATERMARK_MASK, mask_sh),\ @@ -363,11 +359,7 @@ SF(MCIF_WB_BUF_3_ADDR_C, MCIF_WB_BUF_3_ADDR_C, mask_sh),\ SF(MCIF_WB_BUF_4_ADDR_Y, MCIF_WB_BUF_4_ADDR_Y, mask_sh),\ SF(MCIF_WB_BUF_4_ADDR_C, MCIF_WB_BUF_4_ADDR_C, mask_sh),\ - SF(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_LOCK_IGNORE, mask_sh),\ - SF(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_INT_EN, mask_sh),\ - SF(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_INT_ACK, mask_sh),\ SF(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_SLICE_INT_EN, mask_sh),\ - SF(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_LOCK, mask_sh),\ SF(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_SLICE_SIZE, mask_sh),\ SF(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_REFRESH_WATERMARK, mask_sh),\ SF(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_WATERMARK_MASK, mask_sh),\ diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index 64320e0ca446..3a3b2ac791c7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -724,7 +724,8 @@ static const struct dc_debug_options debug_defaults_drv = { .dwb_fi_phase = -1, // -1 = disable, .dmub_command_table = true, .disable_psr = false, - .use_max_lb = true + .use_max_lb = true, + .exit_idle_opt_for_cursor_updates = true }; static const struct dc_debug_options debug_defaults_diags = { @@ -1916,7 +1917,7 @@ static int get_refresh_rate(struct dc_state *context) */ #define V_SCALE (10000 / MAX_STRETCHED_V_BLANK) -int get_frame_rate_at_max_stretch_100hz(struct dc_state *context) +static int get_frame_rate_at_max_stretch_100hz(struct dc_state *context) { struct dc_crtc_timing *timing = NULL; uint32_t sec_per_100_lines; @@ -1946,7 +1947,7 @@ int get_frame_rate_at_max_stretch_100hz(struct dc_state *context) return scaled_refresh_rate; } -bool is_refresh_rate_support_mclk_switch_using_fw_based_vblank_stretch(struct dc_state *context) +static bool is_refresh_rate_support_mclk_switch_using_fw_based_vblank_stretch(struct dc_state *context) { int refresh_rate_max_stretch_100hz; int min_refresh_100hz; diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_init.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_init.c index 3d42a1a337ec..6192851c59ed 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_init.c @@ -99,6 +99,10 @@ static const struct hw_sequencer_funcs dcn301_funcs = { .set_backlight_level = dcn21_set_backlight_level, .set_abm_immediate_disable = dcn21_set_abm_immediate_disable, .set_pipe = dcn21_set_pipe, + .enable_lvds_link_output = dce110_enable_lvds_link_output, + .enable_tmds_link_output = dce110_enable_tmds_link_output, + .enable_dp_link_output = dce110_enable_dp_link_output, + .disable_link_output = dce110_disable_link_output, .set_disp_pattern_generator = dcn30_set_disp_pattern_generator, .get_dcc_en_bits = dcn10_get_dcc_en_bits, .optimize_pwr_state = dcn21_optimize_pwr_state, diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c index db172677d613..559e563d5bc1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c @@ -634,7 +634,7 @@ static const struct dcn20_vmid_mask vmid_masks = { DCN20_VMID_MASK_SH_LIST(_MASK) }; -static const struct resource_caps res_cap_dcn301 = { +static struct resource_caps res_cap_dcn301 = { .num_timing_generator = 4, .num_opp = 4, .num_video_plane = 4, @@ -700,6 +700,7 @@ static const struct dc_debug_options debug_defaults_drv = { .dwb_fi_phase = -1, // -1 = disable .dmub_command_table = true, .use_max_lb = false, + .exit_idle_opt_for_cursor_updates = true }; static const struct dc_debug_options debug_defaults_diags = { @@ -1429,6 +1430,8 @@ static bool dcn301_resource_construct( ctx->dc_bios->regs = &bios_regs; + if (dc->ctx->asic_id.chip_id == DEVICE_ID_VGH_1435) + res_cap_dcn301.num_pll = 2; pool->base.res_cap = &res_cap_dcn301; pool->base.funcs = &dcn301_res_pool_funcs; diff --git a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c index 4fab537e822f..b925b6ddde5a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c @@ -93,7 +93,8 @@ static const struct dc_debug_options debug_defaults_drv = { .underflow_assert_delay_us = 0xFFFFFFFF, .dwb_fi_phase = -1, // -1 = disable, .dmub_command_table = true, - .use_max_lb = true + .use_max_lb = true, + .exit_idle_opt_for_cursor_updates = true }; static const struct dc_debug_options debug_defaults_diags = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c index d97076648acb..527d5c902878 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c @@ -77,6 +77,7 @@ static const struct dc_debug_options debug_defaults_drv = { .underflow_assert_delay_us = 0xFFFFFFFF, .dwb_fi_phase = -1, // -1 = disable, .dmub_command_table = true, + .exit_idle_opt_for_cursor_updates = true, .disable_idle_power_optimizations = false, }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c index 23621ff08c90..52fb2bf3d578 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c @@ -150,9 +150,9 @@ static void dcn31_hpo_dp_stream_enc_dp_blank( * 10us*5000=50ms. This covers 41.7ms of minimum 24 Hz mode + * a little more because we may not trust delay accuracy. */ - //REG_WAIT(DP_SYM32_ENC_VID_STREAM_CONTROL, - // VID_STREAM_STATUS, 0, - // 10, 5000); + REG_WAIT(DP_SYM32_ENC_VID_STREAM_CONTROL, + VID_STREAM_STATUS, 0, + 10, 5000); /* Disable SDP tranmission */ REG_UPDATE(DP_SYM32_ENC_SDP_CONTROL, diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c index 51c5f3685470..6360dc9502e7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c @@ -876,7 +876,7 @@ static bool hubbub31_get_dcc_compression_cap(struct hubbub *hubbub, return true; } -static int hubbub31_init_dchub_sys_ctx(struct hubbub *hubbub, +int hubbub31_init_dchub_sys_ctx(struct hubbub *hubbub, struct dcn_hubbub_phys_addr_config *pa_config) { struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.h index e3a654bf04e8..70c60de448ac 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.h +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.h @@ -122,6 +122,8 @@ HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_PIPE, mask_sh), \ HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_INTERRUPT_STATUS, mask_sh) +int hubbub31_init_dchub_sys_ctx(struct hubbub *hubbub, + struct dcn_hubbub_phys_addr_config *pa_config); void hubbub31_construct(struct dcn20_hubbub *hubbub3, struct dc_context *ctx, diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c index 1ed1404e969d..bdf101547484 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c @@ -535,11 +535,11 @@ static void dcn31_reset_back_end_for_pipe( pipe_ctx->stream_res.tg, OPTC_DSC_DISABLED, 0, 0); pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg); - pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, false); if (pipe_ctx->stream_res.tg->funcs->set_odm_bypass) pipe_ctx->stream_res.tg->funcs->set_odm_bypass( pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing); + pipe_ctx->stream->link->phy_state.symclk_ref_cnts.otg = 0; if (pipe_ctx->stream_res.tg->funcs->set_drr) pipe_ctx->stream_res.tg->funcs->set_drr( diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c index e708f07fe75a..3a32810bbe38 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c @@ -100,6 +100,10 @@ static const struct hw_sequencer_funcs dcn31_funcs = { .set_backlight_level = dcn21_set_backlight_level, .set_abm_immediate_disable = dcn21_set_abm_immediate_disable, .set_pipe = dcn21_set_pipe, + .enable_lvds_link_output = dce110_enable_lvds_link_output, + .enable_tmds_link_output = dce110_enable_tmds_link_output, + .enable_dp_link_output = dce110_enable_dp_link_output, + .disable_link_output = dce110_disable_link_output, .z10_restore = dcn31_z10_restore, .z10_save_init = dcn31_z10_save_init, .set_disp_pattern_generator = dcn30_set_disp_pattern_generator, diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c index aedff18aff56..8c1a6fb36306 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c @@ -889,9 +889,8 @@ static const struct dc_debug_options debug_defaults_drv = { }, .disable_z10 = true, .optimize_edp_link_rate = true, - .enable_sw_cntl_psr = true, .enable_z9_disable_interface = true, /* Allow support for the PMFW interface for disable Z9*/ - .dml_hostvm_override = DML_HOSTVM_OVERRIDE_FALSE, + .dml_hostvm_override = DML_HOSTVM_NO_OVERRIDE, }; static const struct dc_debug_options debug_defaults_diags = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c index 232cc15979dd..1bd7e0f327d8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c @@ -45,6 +45,48 @@ #define DC_LOGGER \ dccg->ctx->logger +static void dccg314_get_pixel_rate_div( + struct dccg *dccg, + uint32_t otg_inst, + enum pixel_rate_div *k1, + enum pixel_rate_div *k2) +{ + struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); + uint32_t val_k1 = PIXEL_RATE_DIV_NA, val_k2 = PIXEL_RATE_DIV_NA; + + *k1 = PIXEL_RATE_DIV_NA; + *k2 = PIXEL_RATE_DIV_NA; + + switch (otg_inst) { + case 0: + REG_GET_2(OTG_PIXEL_RATE_DIV, + OTG0_PIXEL_RATE_DIVK1, &val_k1, + OTG0_PIXEL_RATE_DIVK2, &val_k2); + break; + case 1: + REG_GET_2(OTG_PIXEL_RATE_DIV, + OTG1_PIXEL_RATE_DIVK1, &val_k1, + OTG1_PIXEL_RATE_DIVK2, &val_k2); + break; + case 2: + REG_GET_2(OTG_PIXEL_RATE_DIV, + OTG2_PIXEL_RATE_DIVK1, &val_k1, + OTG2_PIXEL_RATE_DIVK2, &val_k2); + break; + case 3: + REG_GET_2(OTG_PIXEL_RATE_DIV, + OTG3_PIXEL_RATE_DIVK1, &val_k1, + OTG3_PIXEL_RATE_DIVK2, &val_k2); + break; + default: + BREAK_TO_DEBUGGER(); + return; + } + + *k1 = (enum pixel_rate_div)val_k1; + *k2 = (enum pixel_rate_div)val_k2; +} + static void dccg314_set_pixel_rate_div( struct dccg *dccg, uint32_t otg_inst, @@ -52,6 +94,11 @@ static void dccg314_set_pixel_rate_div( enum pixel_rate_div k2) { struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); + enum pixel_rate_div cur_k1 = PIXEL_RATE_DIV_NA, cur_k2 = PIXEL_RATE_DIV_NA; + + dccg314_get_pixel_rate_div(dccg, otg_inst, &cur_k1, &cur_k2); + if (k1 == PIXEL_RATE_DIV_NA || k2 == PIXEL_RATE_DIV_NA || (k1 == cur_k1 && k2 == cur_k2)) + return; switch (otg_inst) { case 0: @@ -137,7 +184,7 @@ static void dccg314_set_dtbclk_p_src( } /* Controls the generation of pixel valid for OTG in (OTG -> HPO case) */ -void dccg314_set_dtbclk_dto( +static void dccg314_set_dtbclk_dto( struct dccg *dccg, const struct dtbclk_dto_params *params) { @@ -181,7 +228,7 @@ void dccg314_set_dtbclk_dto( } } -void dccg314_set_dpstreamclk( +static void dccg314_set_dpstreamclk( struct dccg *dccg, enum streamclk_source src, int otg_inst, @@ -220,7 +267,7 @@ void dccg314_set_dpstreamclk( } } -void dccg314_set_valid_pixel_rate( +static void dccg314_set_valid_pixel_rate( struct dccg *dccg, int ref_dtbclk_khz, int otg_inst, diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.h b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.h index 9a4a9efc0203..6a35986307af 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.h +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.h @@ -63,34 +63,28 @@ DCCG_SRII(PHASE, DTBCLK_DTO, 3),\ SR(DCCG_AUDIO_DTBCLK_DTO_MODULO),\ SR(DCCG_AUDIO_DTBCLK_DTO_PHASE),\ + SR(DCCG_AUDIO_DTO_SOURCE),\ + SR(DENTIST_DISPCLK_CNTL),\ + SR(DSCCLK0_DTO_PARAM),\ + SR(DSCCLK1_DTO_PARAM),\ + SR(DSCCLK2_DTO_PARAM),\ + SR(DSCCLK_DTO_CTRL),\ + SR(DCCG_GATE_DISABLE_CNTL2),\ + SR(DCCG_GATE_DISABLE_CNTL3),\ + SR(HDMISTREAMCLK0_DTO_PARAM),\ SR(OTG_PIXEL_RATE_DIV),\ SR(DTBCLK_P_CNTL),\ SR(DCCG_AUDIO_DTO_SOURCE) - -#define DCCG_MASK_SH_LIST_DCN314(mask_sh) \ - DCCG_SFI(DPPCLK_DTO_CTRL, DTO_ENABLE, DPPCLK, 0, mask_sh),\ +#define DCCG_MASK_SH_LIST_DCN314_COMMON(mask_sh) \ DCCG_SFI(DPPCLK_DTO_CTRL, DTO_DB_EN, DPPCLK, 0, mask_sh),\ - DCCG_SFI(DPPCLK_DTO_CTRL, DTO_ENABLE, DPPCLK, 1, mask_sh),\ DCCG_SFI(DPPCLK_DTO_CTRL, DTO_DB_EN, DPPCLK, 1, mask_sh),\ - DCCG_SFI(DPPCLK_DTO_CTRL, DTO_ENABLE, DPPCLK, 2, mask_sh),\ DCCG_SFI(DPPCLK_DTO_CTRL, DTO_DB_EN, DPPCLK, 2, mask_sh),\ - DCCG_SFI(DPPCLK_DTO_CTRL, DTO_ENABLE, DPPCLK, 3, mask_sh),\ DCCG_SFI(DPPCLK_DTO_CTRL, DTO_DB_EN, DPPCLK, 3, mask_sh),\ DCCG_SF(DPPCLK0_DTO_PARAM, DPPCLK0_DTO_PHASE, mask_sh),\ DCCG_SF(DPPCLK0_DTO_PARAM, DPPCLK0_DTO_MODULO, mask_sh),\ DCCG_SF(HDMICHARCLK0_CLOCK_CNTL, HDMICHARCLK0_EN, mask_sh),\ DCCG_SF(HDMICHARCLK0_CLOCK_CNTL, HDMICHARCLK0_SRC_SEL, mask_sh),\ - DCCG_SF(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_FORCE_EN, mask_sh),\ - DCCG_SF(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_FORCE_SRC_SEL, mask_sh),\ - DCCG_SF(PHYBSYMCLK_CLOCK_CNTL, PHYBSYMCLK_FORCE_EN, mask_sh),\ - DCCG_SF(PHYBSYMCLK_CLOCK_CNTL, PHYBSYMCLK_FORCE_SRC_SEL, mask_sh),\ - DCCG_SF(PHYCSYMCLK_CLOCK_CNTL, PHYCSYMCLK_FORCE_EN, mask_sh),\ - DCCG_SF(PHYCSYMCLK_CLOCK_CNTL, PHYCSYMCLK_FORCE_SRC_SEL, mask_sh),\ - DCCG_SF(PHYDSYMCLK_CLOCK_CNTL, PHYDSYMCLK_FORCE_EN, mask_sh),\ - DCCG_SF(PHYDSYMCLK_CLOCK_CNTL, PHYDSYMCLK_FORCE_SRC_SEL, mask_sh),\ - DCCG_SF(PHYESYMCLK_CLOCK_CNTL, PHYESYMCLK_FORCE_EN, mask_sh),\ - DCCG_SF(PHYESYMCLK_CLOCK_CNTL, PHYESYMCLK_FORCE_SRC_SEL, mask_sh),\ DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK0_EN, mask_sh),\ DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK1_EN, mask_sh),\ DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK2_EN, mask_sh),\ @@ -100,7 +94,6 @@ DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK2_SRC_SEL, mask_sh),\ DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK3_SRC_SEL, mask_sh),\ DCCG_SF(HDMISTREAMCLK_CNTL, HDMISTREAMCLK0_EN, mask_sh),\ - DCCG_SF(HDMISTREAMCLK_CNTL, HDMISTREAMCLK0_DTO_FORCE_DIS, mask_sh),\ DCCG_SF(HDMISTREAMCLK_CNTL, HDMISTREAMCLK0_SRC_SEL, mask_sh),\ DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE0_SRC_SEL, mask_sh),\ DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE1_SRC_SEL, mask_sh),\ @@ -148,7 +141,48 @@ DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P3_SRC_SEL, mask_sh),\ DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P3_EN, mask_sh),\ DCCG_SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL, mask_sh),\ - DCCG_SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO_SEL, mask_sh) + DCCG_SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO_SEL, mask_sh),\ + DCCG_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_MODE, mask_sh),\ + DCCG_SF(DSCCLK0_DTO_PARAM, DSCCLK0_DTO_PHASE, mask_sh),\ + DCCG_SF(DSCCLK0_DTO_PARAM, DSCCLK0_DTO_MODULO, mask_sh),\ + DCCG_SF(DSCCLK1_DTO_PARAM, DSCCLK1_DTO_PHASE, mask_sh),\ + DCCG_SF(DSCCLK1_DTO_PARAM, DSCCLK1_DTO_MODULO, mask_sh),\ + DCCG_SF(DSCCLK2_DTO_PARAM, DSCCLK2_DTO_PHASE, mask_sh),\ + DCCG_SF(DSCCLK2_DTO_PARAM, DSCCLK2_DTO_MODULO, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE0_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE1_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE2_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE3_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_LE0_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_LE1_GATE_DISABLE, mask_sh),\ + DCCG_SF(HDMISTREAMCLK0_DTO_PARAM, HDMISTREAMCLK0_DTO_PHASE, mask_sh),\ + DCCG_SF(HDMISTREAMCLK0_DTO_PARAM, HDMISTREAMCLK0_DTO_MODULO, mask_sh) + +#define DCCG_MASK_SH_LIST_DCN314(mask_sh) \ + DCCG_MASK_SH_LIST_DCN314_COMMON(mask_sh),\ + DCCG_SFI(DPPCLK_DTO_CTRL, DTO_ENABLE, DPPCLK, 0, mask_sh),\ + DCCG_SFI(DPPCLK_DTO_CTRL, DTO_ENABLE, DPPCLK, 1, mask_sh),\ + DCCG_SFI(DPPCLK_DTO_CTRL, DTO_ENABLE, DPPCLK, 2, mask_sh),\ + DCCG_SFI(DPPCLK_DTO_CTRL, DTO_ENABLE, DPPCLK, 3, mask_sh),\ + DCCG_SF(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_FORCE_EN, mask_sh),\ + DCCG_SF(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_FORCE_SRC_SEL, mask_sh),\ + DCCG_SF(PHYBSYMCLK_CLOCK_CNTL, PHYBSYMCLK_FORCE_EN, mask_sh),\ + DCCG_SF(PHYBSYMCLK_CLOCK_CNTL, PHYBSYMCLK_FORCE_SRC_SEL, mask_sh),\ + DCCG_SF(PHYCSYMCLK_CLOCK_CNTL, PHYCSYMCLK_FORCE_EN, mask_sh),\ + DCCG_SF(PHYCSYMCLK_CLOCK_CNTL, PHYCSYMCLK_FORCE_SRC_SEL, mask_sh),\ + DCCG_SF(PHYDSYMCLK_CLOCK_CNTL, PHYDSYMCLK_FORCE_EN, mask_sh),\ + DCCG_SF(PHYDSYMCLK_CLOCK_CNTL, PHYDSYMCLK_FORCE_SRC_SEL, mask_sh),\ + DCCG_SF(PHYESYMCLK_CLOCK_CNTL, PHYESYMCLK_FORCE_EN, mask_sh),\ + DCCG_SF(PHYESYMCLK_CLOCK_CNTL, PHYESYMCLK_FORCE_SRC_SEL, mask_sh),\ + DCCG_SF(HDMISTREAMCLK_CNTL, HDMISTREAMCLK0_DTO_FORCE_DIS, mask_sh),\ + DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK0_DTO_ENABLE, mask_sh),\ + DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK1_DTO_ENABLE, mask_sh),\ + DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK2_DTO_ENABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYASYMCLK_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYBSYMCLK_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYCSYMCLK_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYDSYMCLK_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYESYMCLK_GATE_DISABLE, mask_sh) struct dccg *dccg314_create( struct dc_context *ctx, diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.c index 06d8638db696..0d2ffb692957 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.c @@ -56,7 +56,8 @@ static void enc314_enable_fifo(struct stream_encoder *enc) /* TODO: Confirm if we need to wait for DIG_SYMCLK_FE_ON */ REG_WAIT(DIG_FE_CNTL, DIG_SYMCLK_FE_ON, 1, 10, 5000); - REG_UPDATE_2(DIG_FIFO_CTRL0, DIG_FIFO_RESET, 1, DIG_FIFO_READ_START_LEVEL, 0x7); + REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_READ_START_LEVEL, 0x7); + REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_RESET, 1); REG_WAIT(DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, 1, 10, 5000); REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_RESET, 0); REG_WAIT(DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, 0, 10, 5000); @@ -80,7 +81,7 @@ static void enc314_dp_set_odm_combine( } /* setup stream encoder in dvi mode */ -void enc314_stream_encoder_dvi_set_stream_attribute( +static void enc314_stream_encoder_dvi_set_stream_attribute( struct stream_encoder *enc, struct dc_crtc_timing *crtc_timing, bool is_dual_link) @@ -261,6 +262,16 @@ static bool is_two_pixels_per_containter(const struct dc_crtc_timing *timing) return two_pix; } +void enc314_stream_encoder_dp_blank( + struct dc_link *link, + struct stream_encoder *enc) +{ + /* New to DCN314 - disable the FIFO before VID stream disable. */ + enc314_disable_fifo(enc); + + enc1_stream_encoder_dp_blank(link, enc); +} + static void enc314_stream_encoder_dp_unblank( struct dc_link *link, struct stream_encoder *enc, @@ -316,15 +327,11 @@ static void enc314_stream_encoder_dp_unblank( /* switch DP encoder to CRTC data, but reset it the fifo first. It may happen * that it overflows during mode transition, and sometimes doesn't recover. */ - REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_READ_START_LEVEL, 0x7); REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 1); udelay(10); REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 0); - /* DIG Resync FIFO now needs to be explicitly enabled. */ - enc314_enable_fifo(enc); - /* wait 100us for DIG/DP logic to prime * (i.e. a few video lines) */ @@ -340,6 +347,12 @@ static void enc314_stream_encoder_dp_unblank( REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, true); + /* + * DIG Resync FIFO now needs to be explicitly enabled. + * This should come after DP_VID_STREAM_ENABLE per HW docs. + */ + enc314_enable_fifo(enc); + dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_DP_VID_STREAM); } @@ -408,7 +421,7 @@ static const struct stream_encoder_funcs dcn314_str_enc_funcs = { .stop_dp_info_packets = enc1_stream_encoder_stop_dp_info_packets, .dp_blank = - enc1_stream_encoder_dp_blank, + enc314_stream_encoder_dp_blank, .dp_unblank = enc314_stream_encoder_dp_unblank, .audio_mute_control = enc3_audio_mute_control, diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c index f4d1b83979fe..588c1c71241f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c @@ -348,6 +348,9 @@ unsigned int dcn314_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsig two_pix_per_container = optc2_is_two_pixels_per_containter(&stream->timing); odm_combine_factor = get_odm_config(pipe_ctx, NULL); + if (pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) + return odm_combine_factor; + if (is_dp_128b_132b_signal(pipe_ctx)) { *k2_div = PIXEL_RATE_DIV_BY_1; } else if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal) || dc_is_dvi_signal(pipe_ctx->stream->signal)) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c index 72a563a4c3e8..5b6c2d94ec71 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c @@ -102,6 +102,10 @@ static const struct hw_sequencer_funcs dcn314_funcs = { .set_backlight_level = dcn21_set_backlight_level, .set_abm_immediate_disable = dcn21_set_abm_immediate_disable, .set_pipe = dcn21_set_pipe, + .enable_lvds_link_output = dce110_enable_lvds_link_output, + .enable_tmds_link_output = dce110_enable_tmds_link_output, + .enable_dp_link_output = dce110_enable_dp_link_output, + .disable_link_output = dce110_disable_link_output, .z10_restore = dcn31_z10_restore, .z10_save_init = dcn31_z10_save_init, .set_disp_pattern_generator = dcn30_set_disp_pattern_generator, diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_optc.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_optc.c index 38aa28ec6b13..47eb162f1a75 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_optc.c @@ -150,7 +150,7 @@ static bool optc314_disable_crtc(struct timing_generator *optc) return true; } -void optc314_phantom_crtc_post_enable(struct timing_generator *optc) +static void optc314_phantom_crtc_post_enable(struct timing_generator *optc) { struct optc *optc1 = DCN10TG_FROM_TG(optc); diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c index 44ac1c2aabf5..24ec71cbd3e3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c @@ -915,7 +915,6 @@ static const struct dc_debug_options debug_defaults_drv = { } }, .optimize_edp_link_rate = true, - .enable_sw_cntl_psr = true, .seamless_boot_odm_combine = true }; @@ -1647,6 +1646,7 @@ static struct clock_source *dcn31_clock_source_create( } BREAK_TO_DEBUGGER(); + kfree(clk_src); return NULL; } @@ -1719,6 +1719,7 @@ static struct clock_source *dcn30_clock_source_create( } BREAK_TO_DEBUGGER(); + kfree(clk_src); return NULL; } @@ -1818,8 +1819,6 @@ static bool dcn314_resource_construct( if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) dc->debug = debug_defaults_drv; - else if (dc->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS) - dc->debug = debug_defaults_diags; else dc->debug = debug_defaults_diags; // Init the vm_helper diff --git a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c index 7463b12ae4a3..eebb42c9ddd6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c @@ -886,7 +886,6 @@ static const struct dc_debug_options debug_defaults_drv = { } }, .optimize_edp_link_rate = true, - .enable_sw_cntl_psr = true, .psr_power_use_phy_fsm = 0, }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c index d56a212e065c..f4b52a35ad84 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c @@ -886,7 +886,6 @@ static const struct dc_debug_options debug_defaults_drv = { } }, .optimize_edp_link_rate = true, - .enable_sw_cntl_psr = true, }; static const struct dc_debug_options debug_defaults_diags = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c index 0d5e8a441512..e4daed44ef5f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c @@ -42,6 +42,48 @@ #define DC_LOGGER \ dccg->ctx->logger +static void dccg32_get_pixel_rate_div( + struct dccg *dccg, + uint32_t otg_inst, + enum pixel_rate_div *k1, + enum pixel_rate_div *k2) +{ + struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); + uint32_t val_k1 = PIXEL_RATE_DIV_NA, val_k2 = PIXEL_RATE_DIV_NA; + + *k1 = PIXEL_RATE_DIV_NA; + *k2 = PIXEL_RATE_DIV_NA; + + switch (otg_inst) { + case 0: + REG_GET_2(OTG_PIXEL_RATE_DIV, + OTG0_PIXEL_RATE_DIVK1, &val_k1, + OTG0_PIXEL_RATE_DIVK2, &val_k2); + break; + case 1: + REG_GET_2(OTG_PIXEL_RATE_DIV, + OTG1_PIXEL_RATE_DIVK1, &val_k1, + OTG1_PIXEL_RATE_DIVK2, &val_k2); + break; + case 2: + REG_GET_2(OTG_PIXEL_RATE_DIV, + OTG2_PIXEL_RATE_DIVK1, &val_k1, + OTG2_PIXEL_RATE_DIVK2, &val_k2); + break; + case 3: + REG_GET_2(OTG_PIXEL_RATE_DIV, + OTG3_PIXEL_RATE_DIVK1, &val_k1, + OTG3_PIXEL_RATE_DIVK2, &val_k2); + break; + default: + BREAK_TO_DEBUGGER(); + return; + } + + *k1 = (enum pixel_rate_div)val_k1; + *k2 = (enum pixel_rate_div)val_k2; +} + static void dccg32_set_pixel_rate_div( struct dccg *dccg, uint32_t otg_inst, @@ -50,6 +92,17 @@ static void dccg32_set_pixel_rate_div( { struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); + enum pixel_rate_div cur_k1 = PIXEL_RATE_DIV_NA, cur_k2 = PIXEL_RATE_DIV_NA; + + // Don't program 0xF into the register field. Not valid since + // K1 / K2 field is only 1 / 2 bits wide + if (k1 == PIXEL_RATE_DIV_NA || k2 == PIXEL_RATE_DIV_NA) + return; + + dccg32_get_pixel_rate_div(dccg, otg_inst, &cur_k1, &cur_k2); + if (k1 == cur_k1 && k2 == cur_k2) + return; + switch (otg_inst) { case 0: REG_UPDATE_2(OTG_PIXEL_RATE_DIV, @@ -133,7 +186,7 @@ static void dccg32_set_dtbclk_p_src( } /* Controls the generation of pixel valid for OTG in (OTG -> HPO case) */ -void dccg32_set_dtbclk_dto( +static void dccg32_set_dtbclk_dto( struct dccg *dccg, const struct dtbclk_dto_params *params) { @@ -208,7 +261,7 @@ static void dccg32_get_dccg_ref_freq(struct dccg *dccg, return; } -void dccg32_set_dpstreamclk( +static void dccg32_set_dpstreamclk( struct dccg *dccg, enum streamclk_source src, int otg_inst, @@ -245,7 +298,7 @@ void dccg32_set_dpstreamclk( } } -void dccg32_otg_add_pixel(struct dccg *dccg, +static void dccg32_otg_add_pixel(struct dccg *dccg, uint32_t otg_inst) { struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); @@ -254,7 +307,7 @@ void dccg32_otg_add_pixel(struct dccg *dccg, OTG_ADD_PIXEL[otg_inst], 1); } -void dccg32_otg_drop_pixel(struct dccg *dccg, +static void dccg32_otg_drop_pixel(struct dccg *dccg, uint32_t otg_inst) { struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c index d6855d4f749b..fdae6aa89908 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c @@ -118,7 +118,7 @@ void dcn32_link_encoder_enable_dp_output( } } -bool dcn32_link_encoder_is_in_alt_mode(struct link_encoder *enc) +static bool dcn32_link_encoder_is_in_alt_mode(struct link_encoder *enc) { struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); uint32_t dp_alt_mode_disable = 0; @@ -133,7 +133,7 @@ bool dcn32_link_encoder_is_in_alt_mode(struct link_encoder *enc) return is_usb_c_alt_mode; } -void dcn32_link_encoder_get_max_link_cap(struct link_encoder *enc, +static void dcn32_link_encoder_get_max_link_cap(struct link_encoder *enc, struct dc_link_settings *link_settings) { struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.c index 38a48983f663..0e9dce414641 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.c @@ -60,7 +60,7 @@ static void enc32_dp_set_odm_combine( } /* setup stream encoder in dvi mode */ -void enc32_stream_encoder_dvi_set_stream_attribute( +static void enc32_stream_encoder_dvi_set_stream_attribute( struct stream_encoder *enc, struct dc_crtc_timing *crtc_timing, bool is_dual_link) diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dpp.c index f349cbe2a0f0..dcf12a0b031c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dpp.c @@ -31,7 +31,7 @@ #include "dcn30/dcn30_cm_common.h" /* Compute the maximum number of lines that we can fit in the line buffer */ -void dscl32_calc_lb_num_partitions( +static void dscl32_calc_lb_num_partitions( const struct scaler_data *scl_data, enum lb_memory_config lb_config, int *num_part_y, diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c index 99eb239bbc7b..f6d3da475835 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c @@ -68,7 +68,7 @@ static void dcn32_init_crb(struct hubbub *hubbub) REG_UPDATE(DCHUBBUB_DEBUG_CTRL_0, DET_DEPTH, 0x47F); } -static void dcn32_program_det_size(struct hubbub *hubbub, int hubp_inst, unsigned int det_buffer_size_in_kbyte) +void dcn32_program_det_size(struct hubbub *hubbub, int hubp_inst, unsigned int det_buffer_size_in_kbyte) { struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); @@ -98,9 +98,13 @@ static void dcn32_program_det_size(struct hubbub *hubbub, int hubp_inst, unsigne default: break; } - /* Should never be hit, if it is we have an erroneous hw config*/ - ASSERT(hubbub2->det0_size + hubbub2->det1_size + hubbub2->det2_size - + hubbub2->det3_size + hubbub2->compbuf_size_segments <= hubbub2->crb_size_segs); + if (hubbub2->det0_size + hubbub2->det1_size + hubbub2->det2_size + + hubbub2->det3_size + hubbub2->compbuf_size_segments > hubbub2->crb_size_segs) { + /* This may happen during seamless transition from ODM 2:1 to ODM4:1 */ + DC_LOG_WARNING("CRB Config Warning: DET size (%d,%d,%d,%d) + Compbuf size (%d) > CRB segments (%d)\n", + hubbub2->det0_size, hubbub2->det1_size, hubbub2->det2_size, hubbub2->det3_size, + hubbub2->compbuf_size_segments, hubbub2->crb_size_segs); + } } static void dcn32_program_compbuf_size(struct hubbub *hubbub, unsigned int compbuf_size_kb, bool safe_to_increase) @@ -140,7 +144,7 @@ static uint32_t convert_and_clamp( return ret_val; } -static bool hubbub32_program_urgent_watermarks( +bool hubbub32_program_urgent_watermarks( struct hubbub *hubbub, struct dcn_watermark_set *watermarks, unsigned int refclk_mhz, @@ -330,7 +334,7 @@ static bool hubbub32_program_urgent_watermarks( return wm_pending; } -static bool hubbub32_program_stutter_watermarks( +bool hubbub32_program_stutter_watermarks( struct hubbub *hubbub, struct dcn_watermark_set *watermarks, unsigned int refclk_mhz, @@ -476,7 +480,7 @@ static bool hubbub32_program_stutter_watermarks( } -static bool hubbub32_program_pstate_watermarks( +bool hubbub32_program_pstate_watermarks( struct hubbub *hubbub, struct dcn_watermark_set *watermarks, unsigned int refclk_mhz, @@ -629,7 +633,7 @@ static bool hubbub32_program_pstate_watermarks( } -static bool hubbub32_program_usr_watermarks( +bool hubbub32_program_usr_watermarks( struct hubbub *hubbub, struct dcn_watermark_set *watermarks, unsigned int refclk_mhz, @@ -769,7 +773,7 @@ static bool hubbub32_program_watermarks( } /* Copy values from WM set A to all other sets */ -void hubbub32_init_watermarks(struct hubbub *hubbub) +static void hubbub32_init_watermarks(struct hubbub *hubbub) { struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); uint32_t reg; @@ -820,7 +824,7 @@ void hubbub32_init_watermarks(struct hubbub *hubbub) REG_WRITE(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, reg); } -void hubbub32_wm_read_state(struct hubbub *hubbub, +static void hubbub32_wm_read_state(struct hubbub *hubbub, struct dcn_hubbub_wm *wm) { struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.h index 3bae6e558971..cda94e0e31bf 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.h +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.h @@ -161,6 +161,35 @@ HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_PIPE, mask_sh), \ HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_INTERRUPT_STATUS, mask_sh) +bool hubbub32_program_urgent_watermarks( + struct hubbub *hubbub, + struct dcn_watermark_set *watermarks, + unsigned int refclk_mhz, + bool safe_to_lower); + +bool hubbub32_program_stutter_watermarks( + struct hubbub *hubbub, + struct dcn_watermark_set *watermarks, + unsigned int refclk_mhz, + bool safe_to_lower); + +bool hubbub32_program_pstate_watermarks( + struct hubbub *hubbub, + struct dcn_watermark_set *watermarks, + unsigned int refclk_mhz, + bool safe_to_lower); + +bool hubbub32_program_usr_watermarks( + struct hubbub *hubbub, + struct dcn_watermark_set *watermarks, + unsigned int refclk_mhz, + bool safe_to_lower); + +void hubbub32_force_usr_retraining_allow(struct hubbub *hubbub, bool allow); + +void hubbub32_force_wm_propagate_to_pipes(struct hubbub *hubbub); + +void dcn32_program_det_size(struct hubbub *hubbub, int hubp_inst, unsigned int det_buffer_size_in_kbyte); void hubbub32_construct(struct dcn20_hubbub *hubbub2, struct dc_context *ctx, diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c index 344fe7535df5..a750343ca521 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c @@ -49,6 +49,7 @@ #include "dcn20/dcn20_optc.h" #include "dmub_subvp_state.h" #include "dce/dmub_hw_lock_mgr.h" +#include "dcn32_resource.h" #include "dc_link_dp.h" #include "dmub/inc/dmub_subvp_state.h" @@ -198,42 +199,6 @@ static bool dcn32_check_no_memory_request_for_cab(struct dc *dc) return false; } -/* This function takes in the start address and surface size to be cached in CAB - * and calculates the total number of cache lines required to store the surface. - * The number of cache lines used for each surface is calculated independently of - * one another. For example, if there is a primary surface(1), meta surface(2), and - * cursor(3), this function should be called 3 times to calculate the number of cache - * lines used for each of those surfaces. - */ -static uint32_t dcn32_cache_lines_for_surface(struct dc *dc, uint32_t surface_size, uint64_t start_address) -{ - uint32_t lines_used = 1; - uint32_t num_cached_bytes = 0; - uint32_t remaining_size = 0; - uint32_t cache_line_size = dc->caps.cache_line_size; - uint32_t remainder = 0; - - /* 1. Calculate surface size minus the number of bytes stored - * in the first cache line (all bytes in first cache line might - * not be fully used). - */ - div_u64_rem(start_address, cache_line_size, &remainder); - num_cached_bytes = cache_line_size - remainder; - remaining_size = surface_size - num_cached_bytes; - - /* 2. Calculate number of cache lines that will be fully used with - * the remaining number of bytes to be stored. - */ - lines_used += (remaining_size / cache_line_size); - - /* 3. Check if we need an extra line due to the remaining size not being - * a multiple of CACHE_LINE_SIZE. - */ - if (remaining_size % cache_line_size > 0) - lines_used++; - - return lines_used; -} /* This function loops through every surface that needs to be cached in CAB for SS, * and calculates the total number of ways required to store all surfaces (primary, @@ -241,94 +206,116 @@ static uint32_t dcn32_cache_lines_for_surface(struct dc *dc, uint32_t surface_si */ static uint32_t dcn32_calculate_cab_allocation(struct dc *dc, struct dc_state *ctx) { - uint8_t i, j; + uint8_t i; + int j; struct dc_stream_state *stream = NULL; struct dc_plane_state *plane = NULL; - uint32_t surface_size = 0; uint32_t cursor_size = 0; - uint32_t cache_lines_used = 0; uint32_t total_lines = 0; uint32_t lines_per_way = 0; - uint32_t num_ways = 0; - uint32_t prev_addr_low = 0; + uint8_t num_ways = 0; + uint8_t bytes_per_pixel = 0; + uint8_t cursor_bpp = 0; + uint16_t mblk_width = 0; + uint16_t mblk_height = 0; + uint16_t mall_alloc_width_blk_aligned = 0; + uint16_t mall_alloc_height_blk_aligned = 0; + uint16_t num_mblks = 0; + uint32_t bytes_in_mall = 0; + uint32_t cache_lines_used = 0; + uint32_t cache_lines_per_plane = 0; - for (i = 0; i < ctx->stream_count; i++) { - stream = ctx->streams[i]; + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; - // Don't include PSR surface in the total surface size for CAB allocation - if (stream->link->psr_settings.psr_version != DC_PSR_VERSION_UNSUPPORTED) + if (!pipe->stream || !pipe->plane_state || + pipe->stream->link->psr_settings.psr_version != DC_PSR_VERSION_UNSUPPORTED || + pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) continue; - if (ctx->stream_status[i].plane_count == 0) - continue; + bytes_per_pixel = pipe->plane_state->format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616 ? 8 : 4; + mblk_width = DCN3_2_MBLK_WIDTH; + mblk_height = bytes_per_pixel == 4 ? DCN3_2_MBLK_HEIGHT_4BPE : DCN3_2_MBLK_HEIGHT_8BPE; - // For each stream, loop through each plane to calculate the number of cache - // lines required to store the surface in CAB - for (j = 0; j < ctx->stream_status[i].plane_count; j++) { - plane = ctx->stream_status[i].plane_states[j]; + /* full_vp_width_blk_aligned = FLOOR(vp_x_start + full_vp_width + blk_width - 1, blk_width) - + * FLOOR(vp_x_start, blk_width) + * + * mall_alloc_width_blk_aligned_l/c = full_vp_width_blk_aligned_l/c + */ + mall_alloc_width_blk_aligned = ((pipe->plane_res.scl_data.viewport.x + + pipe->plane_res.scl_data.viewport.width + mblk_width - 1) / mblk_width * mblk_width) - + (pipe->plane_res.scl_data.viewport.x / mblk_width * mblk_width); + + /* full_vp_height_blk_aligned = FLOOR(vp_y_start + full_vp_height + blk_height - 1, blk_height) - + * FLOOR(vp_y_start, blk_height) + * + * mall_alloc_height_blk_aligned_l/c = full_vp_height_blk_aligned_l/c + */ + mall_alloc_height_blk_aligned = ((pipe->plane_res.scl_data.viewport.y + + pipe->plane_res.scl_data.viewport.height + mblk_height - 1) / mblk_height * mblk_height) - + (pipe->plane_res.scl_data.viewport.y / mblk_height * mblk_height); - // Calculate total surface size - if (prev_addr_low != plane->address.grph.addr.u.low_part) { - /* if plane address are different from prev FB, then userspace allocated separate FBs*/ - surface_size += plane->plane_size.surface_pitch * - plane->plane_size.surface_size.height * - (plane->format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616 ? 8 : 4); + num_mblks = ((mall_alloc_width_blk_aligned + mblk_width - 1) / mblk_width) * + ((mall_alloc_height_blk_aligned + mblk_height - 1) / mblk_height); - prev_addr_low = plane->address.grph.addr.u.low_part; - } else { - /* We have the same fb for all the planes. - * Xorg always creates one giant fb that holds all surfaces, - * so allocating it once is sufficient. - * */ - continue; - } - // Convert surface size + starting address to number of cache lines required - // (alignment accounted for) - cache_lines_used += dcn32_cache_lines_for_surface(dc, surface_size, - plane->address.grph.addr.quad_part); - - if (plane->address.grph.meta_addr.quad_part) { - // Meta surface - cache_lines_used += dcn32_cache_lines_for_surface(dc, surface_size, - plane->address.grph.meta_addr.quad_part); - } - } + /* For DCC: + * meta_num_mblk = CEILING(full_mblk_width_ub_l*full_mblk_height_ub_l*Bpe/256/mblk_bytes, 1) + */ + if (pipe->plane_state->dcc.enable) + num_mblks += (mall_alloc_width_blk_aligned * mall_alloc_width_blk_aligned * bytes_per_pixel + + (256 * DCN3_2_MALL_MBLK_SIZE_BYTES) - 1) / (256 * DCN3_2_MALL_MBLK_SIZE_BYTES); - // Include cursor size for CAB allocation - for (j = 0; j < dc->res_pool->pipe_count; j++) { - struct pipe_ctx *pipe = &ctx->res_ctx.pipe_ctx[j]; - struct hubp *hubp = pipe->plane_res.hubp; + bytes_in_mall = num_mblks * DCN3_2_MALL_MBLK_SIZE_BYTES; - if (pipe->stream && pipe->plane_state && hubp) - /* Find the cursor plane and use the exact size instead of - * using the max for calculation - */ - if (hubp->curs_attr.width > 0) { - cursor_size = hubp->curs_attr.width * hubp->curs_attr.height; - break; - } - } + /* (cache lines used is total bytes / cache_line size. Add +2 for worst case alignment + * (MALL is 64-byte aligned) + */ + cache_lines_per_plane = bytes_in_mall / dc->caps.cache_line_size + 2; + cache_lines_used += cache_lines_per_plane; + } - switch (stream->cursor_attributes.color_format) { - case CURSOR_MODE_MONO: - cursor_size /= 2; - break; - case CURSOR_MODE_COLOR_1BIT_AND: - case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA: - case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA: - cursor_size *= 4; - break; + // Include cursor size for CAB allocation + for (j = 0; j < dc->res_pool->pipe_count; j++) { + struct pipe_ctx *pipe = &ctx->res_ctx.pipe_ctx[j]; + struct hubp *hubp = pipe->plane_res.hubp; - case CURSOR_MODE_COLOR_64BIT_FP_PRE_MULTIPLIED: - case CURSOR_MODE_COLOR_64BIT_FP_UN_PRE_MULTIPLIED: - cursor_size *= 8; - break; - } + if (pipe->stream && pipe->plane_state && hubp) + /* Find the cursor plane and use the exact size instead of + using the max for calculation */ - if (stream->cursor_position.enable && plane->address.grph.cursor_cache_addr.quad_part) { - cache_lines_used += dcn32_cache_lines_for_surface(dc, cursor_size, - plane->address.grph.cursor_cache_addr.quad_part); - } + if (hubp->curs_attr.width > 0) { + // Round cursor width to next multiple of 64 + cursor_size = (((hubp->curs_attr.width + 63) / 64) * 64) * hubp->curs_attr.height; + + switch (pipe->stream->cursor_attributes.color_format) { + case CURSOR_MODE_MONO: + cursor_size /= 2; + cursor_bpp = 4; + break; + case CURSOR_MODE_COLOR_1BIT_AND: + case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA: + case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA: + cursor_size *= 4; + cursor_bpp = 4; + break; + + case CURSOR_MODE_COLOR_64BIT_FP_PRE_MULTIPLIED: + case CURSOR_MODE_COLOR_64BIT_FP_UN_PRE_MULTIPLIED: + cursor_size *= 8; + cursor_bpp = 8; + break; + } + + if (pipe->stream->cursor_position.enable && !dc->debug.alloc_extra_way_for_cursor && + cursor_size > 16384) { + /* cursor_num_mblk = CEILING(num_cursors*cursor_width*cursor_width*cursor_Bpe/mblk_bytes, 1) + */ + cache_lines_used += (((hubp->curs_attr.width * hubp->curs_attr.height * cursor_bpp + + DCN3_2_MALL_MBLK_SIZE_BYTES - 1) / DCN3_2_MALL_MBLK_SIZE_BYTES) * + DCN3_2_MALL_MBLK_SIZE_BYTES) / dc->caps.cache_line_size + 2; + } + break; + } } // Convert number of cache lines required to number of ways @@ -345,8 +332,8 @@ static uint32_t dcn32_calculate_cab_allocation(struct dc *dc, struct dc_state *c plane = ctx->stream_status[i].plane_states[j]; if (stream->cursor_position.enable && plane && - !plane->address.grph.cursor_cache_addr.quad_part && - cursor_size > 16384) { + dc->debug.alloc_extra_way_for_cursor && + cursor_size > 16384) { /* Cursor caching is not supported since it won't be on the same line. * So we need an extra line to accommodate it. With large cursors and a single 4k monitor * this case triggers corruption. If we're at the edge, then dont trigger display refresh @@ -358,7 +345,9 @@ static uint32_t dcn32_calculate_cab_allocation(struct dc *dc, struct dc_state *c } } } - + if (dc->debug.force_mall_ss_num_ways > 0) { + num_ways = dc->debug.force_mall_ss_num_ways; + } return num_ways; } @@ -367,7 +356,7 @@ bool dcn32_apply_idle_power_optimizations(struct dc *dc, bool enable) union dmub_rb_cmd cmd; uint8_t ways, i; int j; - bool stereo_in_use = false; + bool mall_ss_unsupported = false; struct dc_plane_state *plane = NULL; if (!dc->ctx->dmub_srv) @@ -398,22 +387,23 @@ bool dcn32_apply_idle_power_optimizations(struct dc *dc, bool enable) */ ways = dcn32_calculate_cab_allocation(dc, dc->current_state); - /* MALL not supported with Stereo3D. If any plane is using stereo, - * don't try to enter MALL. + /* MALL not supported with Stereo3D or TMZ surface. If any plane is using stereo, + * or TMZ surface, don't try to enter MALL. */ for (i = 0; i < dc->current_state->stream_count; i++) { for (j = 0; j < dc->current_state->stream_status[i].plane_count; j++) { plane = dc->current_state->stream_status[i].plane_states[j]; - if (plane->address.type == PLN_ADDR_TYPE_GRPH_STEREO) { - stereo_in_use = true; + if (plane->address.type == PLN_ADDR_TYPE_GRPH_STEREO || + plane->address.tmz_surface) { + mall_ss_unsupported = true; break; } } - if (stereo_in_use) + if (mall_ss_unsupported) break; } - if (ways <= dc->caps.cache_num_ways && !stereo_in_use) { + if (ways <= dc->caps.cache_num_ways && !mall_ss_unsupported) { memset(&cmd, 0, sizeof(cmd)); cmd.cab.header.type = DMUB_CMD__CAB_FOR_SS; cmd.cab.header.sub_type = DMUB_CMD__CAB_DCN_SS_FIT_IN_CAB; @@ -451,7 +441,6 @@ bool dcn32_apply_idle_power_optimizations(struct dc *dc, bool enable) */ void dcn32_commit_subvp_config(struct dc *dc, struct dc_state *context) { -/* int i; bool enable_subvp = false; @@ -469,7 +458,6 @@ void dcn32_commit_subvp_config(struct dc *dc, struct dc_state *context) } } dc_dmub_setup_subvp_dmub_command(dc, context, enable_subvp); -*/ } /* Sub-Viewport DMUB lock needs to be acquired by driver whenever SubVP is active and: @@ -675,9 +663,9 @@ bool dcn32_set_output_transfer_func(struct dc *dc, stream->out_transfer_func, &mpc->blender_params, false)) params = &mpc->blender_params; - /* there are no ROM LUTs in OUTGAM */ - if (stream->out_transfer_func->type == TF_TYPE_PREDEFINED) - BREAK_TO_DEBUGGER(); + /* there are no ROM LUTs in OUTGAM */ + if (stream->out_transfer_func->type == TF_TYPE_PREDEFINED) + BREAK_TO_DEBUGGER(); } } @@ -773,7 +761,8 @@ void dcn32_update_mall_sel(struct dc *dc, struct dc_state *context) hubp->funcs->hubp_update_mall_sel(hubp, num_ways <= dc->caps.cache_num_ways && pipe->stream->link->psr_settings.psr_version == DC_PSR_VERSION_UNSUPPORTED && - pipe->plane_state->address.type != PLN_ADDR_TYPE_GRPH_STEREO ? 2 : 0, + pipe->plane_state->address.type != PLN_ADDR_TYPE_GRPH_STEREO && + !pipe->plane_state->address.tmz_surface ? 2 : 0, cache_cursor); } } @@ -883,6 +872,7 @@ void dcn32_init_hw(struct dc *dc) if (link->link_enc->funcs->is_dig_enabled && link->link_enc->funcs->is_dig_enabled(link->link_enc)) { link->link_status.link_active = true; + link->phy_state.symclk_state = SYMCLK_ON_TX_ON; if (link->link_enc->funcs->fec_is_active && link->link_enc->funcs->fec_is_active(link->link_enc)) link->fec_state = dc_link_fec_enabled; @@ -1181,6 +1171,9 @@ unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsign two_pix_per_container = optc2_is_two_pixels_per_containter(&stream->timing); odm_combine_factor = get_odm_config(pipe_ctx, NULL); + if (pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) + return odm_combine_factor; + if (is_dp_128b_132b_signal(pipe_ctx)) { *k2_div = PIXEL_RATE_DIV_BY_1; } else if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal) || dc_is_dvi_signal(pipe_ctx->stream->signal)) { @@ -1274,3 +1267,155 @@ bool dcn32_is_dp_dig_pixel_rate_div_policy(struct pipe_ctx *pipe_ctx) return true; return false; } + +static void apply_symclk_on_tx_off_wa(struct dc_link *link) +{ + /* There are use cases where SYMCLK is referenced by OTG. For instance + * for TMDS signal, OTG relies SYMCLK even if TX video output is off. + * However current link interface will power off PHY when disabling link + * output. This will turn off SYMCLK generated by PHY. The workaround is + * to identify such case where SYMCLK is still in use by OTG when we + * power off PHY. When this is detected, we will temporarily power PHY + * back on and move PHY's SYMCLK state to SYMCLK_ON_TX_OFF by calling + * program_pix_clk interface. When OTG is disabled, we will then power + * off PHY by calling disable link output again. + * + * In future dcn generations, we plan to rework transmitter control + * interface so that we could have an option to set SYMCLK ON TX OFF + * state in one step without this workaround + */ + + struct dc *dc = link->ctx->dc; + struct pipe_ctx *pipe_ctx = NULL; + uint8_t i; + + if (link->phy_state.symclk_ref_cnts.otg > 0) { + for (i = 0; i < MAX_PIPES; i++) { + pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; + if (pipe_ctx->stream && pipe_ctx->stream->link == link && pipe_ctx->top_pipe == NULL) { + pipe_ctx->clock_source->funcs->program_pix_clk( + pipe_ctx->clock_source, + &pipe_ctx->stream_res.pix_clk_params, + dp_get_link_encoding_format(&pipe_ctx->link_config.dp_link_settings), + &pipe_ctx->pll_settings); + link->phy_state.symclk_state = SYMCLK_ON_TX_OFF; + break; + } + } + } +} + +void dcn32_disable_link_output(struct dc_link *link, + const struct link_resource *link_res, + enum signal_type signal) +{ + struct dc *dc = link->ctx->dc; + const struct link_hwss *link_hwss = get_link_hwss(link, link_res); + struct dmcu *dmcu = dc->res_pool->dmcu; + + if (signal == SIGNAL_TYPE_EDP && + link->dc->hwss.edp_backlight_control) + link->dc->hwss.edp_backlight_control(link, false); + else if (dmcu != NULL && dmcu->funcs->lock_phy) + dmcu->funcs->lock_phy(dmcu); + + link_hwss->disable_link_output(link, link_res, signal); + link->phy_state.symclk_state = SYMCLK_OFF_TX_OFF; + + if (signal == SIGNAL_TYPE_EDP && + link->dc->hwss.edp_backlight_control) + link->dc->hwss.edp_power_control(link, false); + else if (dmcu != NULL && dmcu->funcs->lock_phy) + dmcu->funcs->unlock_phy(dmcu); + + dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY); + + apply_symclk_on_tx_off_wa(link); +} + +/* For SubVP the main pipe can have a viewport position change + * without a full update. In this case we must also update the + * viewport positions for the phantom pipe accordingly. + */ +void dcn32_update_phantom_vp_position(struct dc *dc, + struct dc_state *context, + struct pipe_ctx *phantom_pipe) +{ + uint32_t i; + struct dc_plane_state *phantom_plane = phantom_pipe->plane_state; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + + if (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_MAIN && + pipe->stream->mall_stream_config.paired_stream == phantom_pipe->stream) { + if (pipe->plane_state && pipe->plane_state->update_flags.bits.position_change) { + + phantom_plane->src_rect.x = pipe->plane_state->src_rect.x; + phantom_plane->src_rect.y = pipe->plane_state->src_rect.y; + phantom_plane->clip_rect.x = pipe->plane_state->clip_rect.x; + phantom_plane->dst_rect.x = pipe->plane_state->dst_rect.x; + phantom_plane->dst_rect.y = pipe->plane_state->dst_rect.y; + + phantom_pipe->plane_state->update_flags.bits.position_change = 1; + resource_build_scaling_params(phantom_pipe); + return; + } + } + } +} + +bool dcn32_dsc_pg_status( + struct dce_hwseq *hws, + unsigned int dsc_inst) +{ + uint32_t pwr_status = 0; + + switch (dsc_inst) { + case 0: /* DSC0 */ + REG_GET(DOMAIN16_PG_STATUS, + DOMAIN_PGFSM_PWR_STATUS, &pwr_status); + break; + case 1: /* DSC1 */ + + REG_GET(DOMAIN17_PG_STATUS, + DOMAIN_PGFSM_PWR_STATUS, &pwr_status); + break; + case 2: /* DSC2 */ + REG_GET(DOMAIN18_PG_STATUS, + DOMAIN_PGFSM_PWR_STATUS, &pwr_status); + break; + case 3: /* DSC3 */ + REG_GET(DOMAIN19_PG_STATUS, + DOMAIN_PGFSM_PWR_STATUS, &pwr_status); + break; + default: + BREAK_TO_DEBUGGER(); + break; + } + + return pwr_status == 0 ? true : false; +} + +void dcn32_update_dsc_pg(struct dc *dc, + struct dc_state *context, + bool safe_to_disable) +{ + struct dce_hwseq *hws = dc->hwseq; + int i; + + for (i = 0; i < dc->res_pool->res_cap->num_dsc; i++) { + struct display_stream_compressor *dsc = dc->res_pool->dscs[i]; + bool is_dsc_ungated = hws->funcs.dsc_pg_status(hws, dsc->inst); + + if (context->res_ctx.is_dsc_acquired[i]) { + if (!is_dsc_ungated) { + hws->funcs.dsc_pg_control(hws, dsc->inst, true); + } + } else if (safe_to_disable) { + if (is_dsc_ungated) { + hws->funcs.dsc_pg_control(hws, dsc->inst, false); + } + } + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.h index 083f3aeb54f0..ac3657a5b9ea 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.h @@ -84,4 +84,20 @@ void dcn32_unblank_stream(struct pipe_ctx *pipe_ctx, bool dcn32_is_dp_dig_pixel_rate_div_policy(struct pipe_ctx *pipe_ctx); +void dcn32_disable_link_output(struct dc_link *link, + const struct link_resource *link_res, + enum signal_type signal); + +void dcn32_update_phantom_vp_position(struct dc *dc, + struct dc_state *context, + struct pipe_ctx *phantom_pipe); + +bool dcn32_dsc_pg_status( + struct dce_hwseq *hws, + unsigned int dsc_inst); + +void dcn32_update_dsc_pg(struct dc *dc, + struct dc_state *context, + bool safe_to_disable); + #endif /* __DC_HWSS_DCN32_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c index c279a25ea293..45a949ba6f3f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c @@ -99,11 +99,17 @@ static const struct hw_sequencer_funcs dcn32_funcs = { .set_abm_immediate_disable = dcn21_set_abm_immediate_disable, .hardware_release = dcn30_hardware_release, .set_pipe = dcn21_set_pipe, + .enable_lvds_link_output = dce110_enable_lvds_link_output, + .enable_tmds_link_output = dce110_enable_tmds_link_output, + .enable_dp_link_output = dce110_enable_dp_link_output, + .disable_link_output = dcn32_disable_link_output, .set_disp_pattern_generator = dcn30_set_disp_pattern_generator, .get_dcc_en_bits = dcn10_get_dcc_en_bits, .commit_subvp_config = dcn32_commit_subvp_config, .subvp_pipe_control_lock = dcn32_subvp_pipe_control_lock, .update_visual_confirm_color = dcn20_update_visual_confirm_color, + .update_phantom_vp_position = dcn32_update_phantom_vp_position, + .update_dsc_pg = dcn32_update_dsc_pg, }; static const struct hwseq_private_funcs dcn32_private_funcs = { @@ -133,6 +139,7 @@ static const struct hwseq_private_funcs dcn32_private_funcs = { .program_all_writeback_pipes_in_tree = dcn30_program_all_writeback_pipes_in_tree, .update_odm = dcn32_update_odm, .dsc_pg_control = dcn32_dsc_pg_control, + .dsc_pg_status = dcn32_dsc_pg_status, .set_hdr_multiplier = dcn10_set_hdr_multiplier, .verify_allow_pstate_change_high = dcn10_verify_allow_pstate_change_high, .wait_for_blank_complete = dcn20_wait_for_blank_complete, diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.c index adf93cc8359c..41b0baf8e183 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.c @@ -100,7 +100,7 @@ static void mmhubbub32_warmup_mcif(struct mcif_wb *mcif_wb, REG_UPDATE(MMHUBBUB_WARMUP_CONTROL_STATUS, MMHUBBUB_WARMUP_EN, false); } -void mmhubbub32_config_mcif_buf(struct mcif_wb *mcif_wb, +static void mmhubbub32_config_mcif_buf(struct mcif_wb *mcif_wb, struct mcif_buf_params *params, unsigned int dest_height) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.h index 22355051f5f7..e460cf8d9041 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.h +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.h @@ -90,7 +90,6 @@ SF(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_OVERRUN_INT_EN, mask_sh),\ SF(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_LOCK, mask_sh),\ SF(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUF_ADDR_FENCE_EN, mask_sh),\ - SF(MCIF_WB_BUFMGR_STATUS, MCIF_WB_BUFMGR_VCE_INT_STATUS, mask_sh),\ SF(MCIF_WB_BUFMGR_STATUS, MCIF_WB_BUFMGR_SW_INT_STATUS, mask_sh),\ SF(MCIF_WB_BUFMGR_STATUS, MCIF_WB_BUFMGR_SW_OVERRUN_INT_STATUS, mask_sh),\ SF(MCIF_WB_BUFMGR_STATUS, MCIF_WB_BUFMGR_CUR_BUF, mask_sh),\ @@ -101,7 +100,6 @@ SF(MCIF_WB_BUF_PITCH, MCIF_WB_BUF_CHROMA_PITCH, mask_sh),\ SF(MCIF_WB_BUF_1_STATUS, MCIF_WB_BUF_1_ACTIVE, mask_sh),\ SF(MCIF_WB_BUF_1_STATUS, MCIF_WB_BUF_1_SW_LOCKED, mask_sh),\ - SF(MCIF_WB_BUF_1_STATUS, MCIF_WB_BUF_1_VCE_LOCKED, mask_sh),\ SF(MCIF_WB_BUF_1_STATUS, MCIF_WB_BUF_1_OVERFLOW, mask_sh),\ SF(MCIF_WB_BUF_1_STATUS, MCIF_WB_BUF_1_DISABLE, mask_sh),\ SF(MCIF_WB_BUF_1_STATUS, MCIF_WB_BUF_1_MODE, mask_sh),\ @@ -116,7 +114,6 @@ SF(MCIF_WB_BUF_1_STATUS2, MCIF_WB_BUF_1_C_OVERRUN, mask_sh),\ SF(MCIF_WB_BUF_2_STATUS, MCIF_WB_BUF_2_ACTIVE, mask_sh),\ SF(MCIF_WB_BUF_2_STATUS, MCIF_WB_BUF_2_SW_LOCKED, mask_sh),\ - SF(MCIF_WB_BUF_2_STATUS, MCIF_WB_BUF_2_VCE_LOCKED, mask_sh),\ SF(MCIF_WB_BUF_2_STATUS, MCIF_WB_BUF_2_OVERFLOW, mask_sh),\ SF(MCIF_WB_BUF_2_STATUS, MCIF_WB_BUF_2_DISABLE, mask_sh),\ SF(MCIF_WB_BUF_2_STATUS, MCIF_WB_BUF_2_MODE, mask_sh),\ @@ -131,7 +128,6 @@ SF(MCIF_WB_BUF_2_STATUS2, MCIF_WB_BUF_2_C_OVERRUN, mask_sh),\ SF(MCIF_WB_BUF_3_STATUS, MCIF_WB_BUF_3_ACTIVE, mask_sh),\ SF(MCIF_WB_BUF_3_STATUS, MCIF_WB_BUF_3_SW_LOCKED, mask_sh),\ - SF(MCIF_WB_BUF_3_STATUS, MCIF_WB_BUF_3_VCE_LOCKED, mask_sh),\ SF(MCIF_WB_BUF_3_STATUS, MCIF_WB_BUF_3_OVERFLOW, mask_sh),\ SF(MCIF_WB_BUF_3_STATUS, MCIF_WB_BUF_3_DISABLE, mask_sh),\ SF(MCIF_WB_BUF_3_STATUS, MCIF_WB_BUF_3_MODE, mask_sh),\ @@ -146,7 +142,6 @@ SF(MCIF_WB_BUF_3_STATUS2, MCIF_WB_BUF_3_C_OVERRUN, mask_sh),\ SF(MCIF_WB_BUF_4_STATUS, MCIF_WB_BUF_4_ACTIVE, mask_sh),\ SF(MCIF_WB_BUF_4_STATUS, MCIF_WB_BUF_4_SW_LOCKED, mask_sh),\ - SF(MCIF_WB_BUF_4_STATUS, MCIF_WB_BUF_4_VCE_LOCKED, mask_sh),\ SF(MCIF_WB_BUF_4_STATUS, MCIF_WB_BUF_4_OVERFLOW, mask_sh),\ SF(MCIF_WB_BUF_4_STATUS, MCIF_WB_BUF_4_DISABLE, mask_sh),\ SF(MCIF_WB_BUF_4_STATUS, MCIF_WB_BUF_4_MODE, mask_sh),\ @@ -172,11 +167,6 @@ SF(MCIF_WB_BUF_3_ADDR_C, MCIF_WB_BUF_3_ADDR_C, mask_sh),\ SF(MCIF_WB_BUF_4_ADDR_Y, MCIF_WB_BUF_4_ADDR_Y, mask_sh),\ SF(MCIF_WB_BUF_4_ADDR_C, MCIF_WB_BUF_4_ADDR_C, mask_sh),\ - SF(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_LOCK_IGNORE, mask_sh),\ - SF(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_INT_EN, mask_sh),\ - SF(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_INT_ACK, mask_sh),\ - SF(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_SLICE_INT_EN, mask_sh),\ - SF(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_LOCK, mask_sh),\ SF(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_SLICE_SIZE, mask_sh),\ SF(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_REFRESH_WATERMARK, mask_sh),\ SF(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_WATERMARK_MASK, mask_sh),\ diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c index 357bd2461bc9..4edd0655965b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c @@ -701,7 +701,7 @@ static void mpc32_power_on_shaper_3dlut( } -bool mpc32_program_shaper( +static bool mpc32_program_shaper( struct mpc *mpc, const struct pwl_params *params, uint32_t mpcc_id) @@ -726,7 +726,7 @@ bool mpc32_program_shaper( else next_mode = LUT_RAM_A; - mpc32_configure_shaper_lut(mpc, next_mode == LUT_RAM_A ? true:false, mpcc_id); + mpc32_configure_shaper_lut(mpc, next_mode == LUT_RAM_A, mpcc_id); if (next_mode == LUT_RAM_A) mpc32_program_shaper_luta_settings(mpc, params, mpcc_id); @@ -897,7 +897,7 @@ static void mpc32_set_3dlut_mode( } -bool mpc32_program_3dlut( +static bool mpc32_program_3dlut( struct mpc *mpc, const struct tetrahedral_params *params, int mpcc_id) diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c index 1fad7b48bd5b..ec3989d37086 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c @@ -156,7 +156,7 @@ static bool optc32_disable_crtc(struct timing_generator *optc) return true; } -void optc32_phantom_crtc_post_enable(struct timing_generator *optc) +static void optc32_phantom_crtc_post_enable(struct timing_generator *optc) { struct optc *optc1 = DCN10TG_FROM_TG(optc); @@ -190,7 +190,7 @@ static void optc32_set_odm_bypass(struct timing_generator *optc, optc1->opp_count = 1; } -void optc32_setup_manual_trigger(struct timing_generator *optc) +static void optc32_setup_manual_trigger(struct timing_generator *optc) { struct optc *optc1 = DCN10TG_FROM_TG(optc); struct dc *dc = optc->ctx->dc; @@ -215,7 +215,7 @@ void optc32_setup_manual_trigger(struct timing_generator *optc) } } -void optc32_set_drr( +static void optc32_set_drr( struct timing_generator *optc, const struct drr_params *params) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c index c3b783cea8a0..05de97ea855f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c @@ -90,29 +90,6 @@ #include "dcn20/dcn20_vmid.h" #include "dml/dcn32/dcn32_fpu.h" -#define DCN_BASE__INST0_SEG1 0x000000C0 -#define DCN_BASE__INST0_SEG2 0x000034C0 -#define DCN_BASE__INST0_SEG3 0x00009000 -#define NBIO_BASE__INST0_SEG1 0x00000014 - -#define MAX_INSTANCE 6 -#define MAX_SEGMENT 6 - -struct IP_BASE_INSTANCE { - unsigned int segment[MAX_SEGMENT]; -}; - -struct IP_BASE { - struct IP_BASE_INSTANCE instance[MAX_INSTANCE]; -}; - -static const struct IP_BASE DCN_BASE = { { { { 0x00000012, 0x000000C0, 0x000034C0, 0x00009000, 0x02403C00, 0 } }, - { { 0, 0, 0, 0, 0, 0 } }, - { { 0, 0, 0, 0, 0, 0 } }, - { { 0, 0, 0, 0, 0, 0 } }, - { { 0, 0, 0, 0, 0, 0 } }, - { { 0, 0, 0, 0, 0, 0 } } } }; - #define DC_LOGGER_INIT(logger) enum dcn32_clk_src_array_id { @@ -131,79 +108,103 @@ enum dcn32_clk_src_array_id { /* DCN */ /* TODO awful hack. fixup dcn20_dwb.h */ #undef BASE_INNER -#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg +#define BASE_INNER(seg) ctx->dcn_reg_offsets[seg] #define BASE(seg) BASE_INNER(seg) #define SR(reg_name)\ - .reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ + REG_STRUCT.reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ reg ## reg_name +#define SR_ARR(reg_name, id) \ + REG_STRUCT[id].reg_name = BASE(reg##reg_name##_BASE_IDX) + reg##reg_name + +#define SR_ARR_INIT(reg_name, id, value) \ + REG_STRUCT[id].reg_name = value #define SRI(reg_name, block, id)\ - .reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name + REG_STRUCT.reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRI_ARR(reg_name, block, id)\ + REG_STRUCT[id].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SR_ARR_I2C(reg_name, id) \ + REG_STRUCT[id-1].reg_name = BASE(reg##reg_name##_BASE_IDX) + reg##reg_name + +#define SRI_ARR_I2C(reg_name, block, id)\ + REG_STRUCT[id-1].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRI_ARR_ALPHABET(reg_name, block, index, id)\ + REG_STRUCT[index].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name #define SRI2(reg_name, block, id)\ - .reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ - reg ## reg_name + .reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ + reg ## reg_name +#define SRI2_ARR(reg_name, block, id)\ + REG_STRUCT[id].reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ + reg ## reg_name #define SRIR(var_name, reg_name, block, id)\ .var_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name + reg ## block ## id ## _ ## reg_name #define SRII(reg_name, block, id)\ - .reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + REG_STRUCT.reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ reg ## block ## id ## _ ## reg_name +#define SRII_ARR_2(reg_name, block, id, inst)\ + REG_STRUCT[inst].reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + #define SRII_MPC_RMU(reg_name, block, id)\ .RMU##_##reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name + reg ## block ## id ## _ ## reg_name #define SRII_DWB(reg_name, temp_name, block, id)\ - .reg_name[id] = BASE(reg ## block ## id ## _ ## temp_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## temp_name + REG_STRUCT.reg_name[id] = BASE(reg ## block ## id ## _ ## temp_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## temp_name #define DCCG_SRII(reg_name, block, id)\ - .block ## _ ## reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name + REG_STRUCT.block ## _ ## reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name #define VUPDATE_SRII(reg_name, block, id)\ - .reg_name[id] = BASE(reg ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ - reg ## reg_name ## _ ## block ## id + REG_STRUCT.reg_name[id] = BASE(reg ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ + reg ## reg_name ## _ ## block ## id /* NBIO */ -#define NBIO_BASE_INNER(seg) \ - NBIO_BASE__INST0_SEG ## seg +#define NBIO_BASE_INNER(seg) ctx->nbio_reg_offsets[seg] #define NBIO_BASE(seg) \ NBIO_BASE_INNER(seg) #define NBIO_SR(reg_name)\ - .reg_name = NBIO_BASE(regBIF_BX0_ ## reg_name ## _BASE_IDX) + \ - regBIF_BX0_ ## reg_name + REG_STRUCT.reg_name = NBIO_BASE(regBIF_BX0_ ## reg_name ## _BASE_IDX) + \ + regBIF_BX0_ ## reg_name +#define NBIO_SR_ARR(reg_name, id)\ + REG_STRUCT[id].reg_name = NBIO_BASE(regBIF_BX0_ ## reg_name ## _BASE_IDX) + \ + regBIF_BX0_ ## reg_name #undef CTX #define CTX ctx #define REG(reg_name) \ - (DCN_BASE.instance[0].segment[reg ## reg_name ## _BASE_IDX] + reg ## reg_name) + (ctx->dcn_reg_offsets[reg ## reg_name ## _BASE_IDX] + reg ## reg_name) -static const struct bios_registers bios_regs = { - NBIO_SR(BIOS_SCRATCH_3), - NBIO_SR(BIOS_SCRATCH_6) -}; +static struct bios_registers bios_regs; -#define clk_src_regs(index, pllid)\ -[index] = {\ - CS_COMMON_REG_LIST_DCN3_0(index, pllid),\ -} +#define bios_regs_init() \ + ( \ + NBIO_SR(BIOS_SCRATCH_3),\ + NBIO_SR(BIOS_SCRATCH_6)\ + ) -static const struct dce110_clk_src_regs clk_src_regs[] = { - clk_src_regs(0, A), - clk_src_regs(1, B), - clk_src_regs(2, C), - clk_src_regs(3, D), - clk_src_regs(4, E) -}; +#define clk_src_regs_init(index, pllid)\ + CS_COMMON_REG_LIST_DCN3_0_RI(index, pllid) + +static struct dce110_clk_src_regs clk_src_regs[5]; static const struct dce110_clk_src_shift cs_shift = { CS_COMMON_MASK_SH_LIST_DCN3_2(__SHIFT) @@ -213,17 +214,10 @@ static const struct dce110_clk_src_mask cs_mask = { CS_COMMON_MASK_SH_LIST_DCN3_2(_MASK) }; -#define abm_regs(id)\ -[id] = {\ - ABM_DCN32_REG_LIST(id)\ -} +#define abm_regs_init(id)\ + ABM_DCN32_REG_LIST_RI(id) -static const struct dce_abm_registers abm_regs[] = { - abm_regs(0), - abm_regs(1), - abm_regs(2), - abm_regs(3), -}; +static struct dce_abm_registers abm_regs[4]; static const struct dce_abm_shift abm_shift = { ABM_MASK_SH_LIST_DCN32(__SHIFT) @@ -233,18 +227,10 @@ static const struct dce_abm_mask abm_mask = { ABM_MASK_SH_LIST_DCN32(_MASK) }; -#define audio_regs(id)\ -[id] = {\ - AUD_COMMON_REG_LIST(id)\ -} +#define audio_regs_init(id)\ + AUD_COMMON_REG_LIST_RI(id) -static const struct dce_audio_registers audio_regs[] = { - audio_regs(0), - audio_regs(1), - audio_regs(2), - audio_regs(3), - audio_regs(4) -}; +static struct dce_audio_registers audio_regs[5]; #define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ @@ -259,23 +245,10 @@ static const struct dce_audio_mask audio_mask = { DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) }; -#define vpg_regs(id)\ -[id] = {\ - VPG_DCN3_REG_LIST(id)\ -} +#define vpg_regs_init(id)\ + VPG_DCN3_REG_LIST_RI(id) -static const struct dcn30_vpg_registers vpg_regs[] = { - vpg_regs(0), - vpg_regs(1), - vpg_regs(2), - vpg_regs(3), - vpg_regs(4), - vpg_regs(5), - vpg_regs(6), - vpg_regs(7), - vpg_regs(8), - vpg_regs(9), -}; +static struct dcn30_vpg_registers vpg_regs[10]; static const struct dcn30_vpg_shift vpg_shift = { DCN3_VPG_MASK_SH_LIST(__SHIFT) @@ -285,19 +258,10 @@ static const struct dcn30_vpg_mask vpg_mask = { DCN3_VPG_MASK_SH_LIST(_MASK) }; -#define afmt_regs(id)\ -[id] = {\ - AFMT_DCN3_REG_LIST(id)\ -} +#define afmt_regs_init(id)\ + AFMT_DCN3_REG_LIST_RI(id) -static const struct dcn30_afmt_registers afmt_regs[] = { - afmt_regs(0), - afmt_regs(1), - afmt_regs(2), - afmt_regs(3), - afmt_regs(4), - afmt_regs(5) -}; +static struct dcn30_afmt_registers afmt_regs[6]; static const struct dcn30_afmt_shift afmt_shift = { DCN3_AFMT_MASK_SH_LIST(__SHIFT) @@ -307,17 +271,10 @@ static const struct dcn30_afmt_mask afmt_mask = { DCN3_AFMT_MASK_SH_LIST(_MASK) }; -#define apg_regs(id)\ -[id] = {\ - APG_DCN31_REG_LIST(id)\ -} +#define apg_regs_init(id)\ + APG_DCN31_REG_LIST_RI(id) -static const struct dcn31_apg_registers apg_regs[] = { - apg_regs(0), - apg_regs(1), - apg_regs(2), - apg_regs(3) -}; +static struct dcn31_apg_registers apg_regs[4]; static const struct dcn31_apg_shift apg_shift = { DCN31_APG_MASK_SH_LIST(__SHIFT) @@ -327,18 +284,10 @@ static const struct dcn31_apg_mask apg_mask = { DCN31_APG_MASK_SH_LIST(_MASK) }; -#define stream_enc_regs(id)\ -[id] = {\ - SE_DCN32_REG_LIST(id)\ -} +#define stream_enc_regs_init(id)\ + SE_DCN32_REG_LIST_RI(id) -static const struct dcn10_stream_enc_registers stream_enc_regs[] = { - stream_enc_regs(0), - stream_enc_regs(1), - stream_enc_regs(2), - stream_enc_regs(3), - stream_enc_regs(4) -}; +static struct dcn10_stream_enc_registers stream_enc_regs[5]; static const struct dcn10_stream_encoder_shift se_shift = { SE_COMMON_MASK_SH_LIST_DCN32(__SHIFT) @@ -349,46 +298,24 @@ static const struct dcn10_stream_encoder_mask se_mask = { }; -#define aux_regs(id)\ -[id] = {\ - DCN2_AUX_REG_LIST(id)\ -} +#define aux_regs_init(id)\ + DCN2_AUX_REG_LIST_RI(id) -static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = { - aux_regs(0), - aux_regs(1), - aux_regs(2), - aux_regs(3), - aux_regs(4) -}; +static struct dcn10_link_enc_aux_registers link_enc_aux_regs[5]; -#define hpd_regs(id)\ -[id] = {\ - HPD_REG_LIST(id)\ -} +#define hpd_regs_init(id)\ + HPD_REG_LIST_RI(id) -static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { - hpd_regs(0), - hpd_regs(1), - hpd_regs(2), - hpd_regs(3), - hpd_regs(4) -}; +static struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[5]; -#define link_regs(id, phyid)\ -[id] = {\ - LE_DCN31_REG_LIST(id), \ - UNIPHY_DCN2_REG_LIST(phyid), \ +#define link_regs_init(id, phyid)\ + ( \ + LE_DCN31_REG_LIST_RI(id), \ + UNIPHY_DCN2_REG_LIST_RI(id, phyid)\ + ) /*DPCS_DCN31_REG_LIST(id),*/ \ -} -static const struct dcn10_link_enc_registers link_enc_regs[] = { - link_regs(0, A), - link_regs(1, B), - link_regs(2, C), - link_regs(3, D), - link_regs(4, E) -}; +static struct dcn10_link_enc_registers link_enc_regs[5]; static const struct dcn10_link_enc_shift le_shift = { LINK_ENCODER_MASK_SH_LIST_DCN31(__SHIFT), \ @@ -401,17 +328,10 @@ static const struct dcn10_link_enc_mask le_mask = { //DPCS_DCN31_MASK_SH_LIST(_MASK) }; -#define hpo_dp_stream_encoder_reg_list(id)\ -[id] = {\ - DCN3_1_HPO_DP_STREAM_ENC_REG_LIST(id)\ -} +#define hpo_dp_stream_encoder_reg_init(id)\ + DCN3_1_HPO_DP_STREAM_ENC_REG_LIST_RI(id) -static const struct dcn31_hpo_dp_stream_encoder_registers hpo_dp_stream_enc_regs[] = { - hpo_dp_stream_encoder_reg_list(0), - hpo_dp_stream_encoder_reg_list(1), - hpo_dp_stream_encoder_reg_list(2), - hpo_dp_stream_encoder_reg_list(3), -}; +static struct dcn31_hpo_dp_stream_encoder_registers hpo_dp_stream_enc_regs[4]; static const struct dcn31_hpo_dp_stream_encoder_shift hpo_dp_se_shift = { DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(__SHIFT) @@ -422,20 +342,14 @@ static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { }; -#define hpo_dp_link_encoder_reg_list(id)\ -[id] = {\ - DCN3_1_HPO_DP_LINK_ENC_REG_LIST(id),\ - /*DCN3_1_RDPCSTX_REG_LIST(0),*/\ - /*DCN3_1_RDPCSTX_REG_LIST(1),*/\ - /*DCN3_1_RDPCSTX_REG_LIST(2),*/\ - /*DCN3_1_RDPCSTX_REG_LIST(3),*/\ - /*DCN3_1_RDPCSTX_REG_LIST(4)*/\ -} +#define hpo_dp_link_encoder_reg_init(id)\ + DCN3_1_HPO_DP_LINK_ENC_REG_LIST_RI(id) + /*DCN3_1_RDPCSTX_REG_LIST(0),*/ + /*DCN3_1_RDPCSTX_REG_LIST(1),*/ + /*DCN3_1_RDPCSTX_REG_LIST(2),*/ + /*DCN3_1_RDPCSTX_REG_LIST(3),*/ -static const struct dcn31_hpo_dp_link_encoder_registers hpo_dp_link_enc_regs[] = { - hpo_dp_link_encoder_reg_list(0), - hpo_dp_link_encoder_reg_list(1), -}; +static struct dcn31_hpo_dp_link_encoder_registers hpo_dp_link_enc_regs[2]; static const struct dcn31_hpo_dp_link_encoder_shift hpo_dp_le_shift = { DCN3_2_HPO_DP_LINK_ENC_MASK_SH_LIST(__SHIFT) @@ -445,17 +359,10 @@ static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { DCN3_2_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK) }; -#define dpp_regs(id)\ -[id] = {\ - DPP_REG_LIST_DCN30_COMMON(id),\ -} +#define dpp_regs_init(id)\ + DPP_REG_LIST_DCN30_COMMON_RI(id) -static const struct dcn3_dpp_registers dpp_regs[] = { - dpp_regs(0), - dpp_regs(1), - dpp_regs(2), - dpp_regs(3) -}; +static struct dcn3_dpp_registers dpp_regs[4]; static const struct dcn3_dpp_shift tf_shift = { DPP_REG_LIST_SH_MASK_DCN30_COMMON(__SHIFT) @@ -466,17 +373,10 @@ static const struct dcn3_dpp_mask tf_mask = { }; -#define opp_regs(id)\ -[id] = {\ - OPP_REG_LIST_DCN30(id),\ -} +#define opp_regs_init(id)\ + OPP_REG_LIST_DCN30_RI(id) -static const struct dcn20_opp_registers opp_regs[] = { - opp_regs(0), - opp_regs(1), - opp_regs(2), - opp_regs(3) -}; +static struct dcn20_opp_registers opp_regs[4]; static const struct dcn20_opp_shift opp_shift = { OPP_MASK_SH_LIST_DCN20(__SHIFT) @@ -486,21 +386,16 @@ static const struct dcn20_opp_mask opp_mask = { OPP_MASK_SH_LIST_DCN20(_MASK) }; -#define aux_engine_regs(id)\ -[id] = {\ - AUX_COMMON_REG_LIST0(id), \ - .AUXN_IMPCAL = 0, \ - .AUXP_IMPCAL = 0, \ - .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK, \ -} +#define aux_engine_regs_init(id)\ + ( \ + AUX_COMMON_REG_LIST0_RI(id), \ + SR_ARR_INIT(AUXN_IMPCAL, id, 0), \ + SR_ARR_INIT(AUXP_IMPCAL, id, 0), \ + SR_ARR_INIT(AUX_RESET_MASK, id, DP_AUX0_AUX_CONTROL__AUX_RESET_MASK), \ + SR_ARR_INIT(AUX_RESET_MASK, id, DP_AUX0_AUX_CONTROL__AUX_RESET_MASK)\ + ) -static const struct dce110_aux_registers aux_engine_regs[] = { - aux_engine_regs(0), - aux_engine_regs(1), - aux_engine_regs(2), - aux_engine_regs(3), - aux_engine_regs(4) -}; +static struct dce110_aux_registers aux_engine_regs[5]; static const struct dce110_aux_registers_shift aux_shift = { DCN_AUX_MASK_SH_LIST(__SHIFT) @@ -510,15 +405,10 @@ static const struct dce110_aux_registers_mask aux_mask = { DCN_AUX_MASK_SH_LIST(_MASK) }; +#define dwbc_regs_dcn3_init(id)\ + DWBC_COMMON_REG_LIST_DCN30_RI(id) -#define dwbc_regs_dcn3(id)\ -[id] = {\ - DWBC_COMMON_REG_LIST_DCN30(id),\ -} - -static const struct dcn30_dwbc_registers dwbc30_regs[] = { - dwbc_regs_dcn3(0), -}; +static struct dcn30_dwbc_registers dwbc30_regs[1]; static const struct dcn30_dwbc_shift dwbc30_shift = { DWBC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) @@ -528,14 +418,10 @@ static const struct dcn30_dwbc_mask dwbc30_mask = { DWBC_COMMON_MASK_SH_LIST_DCN30(_MASK) }; -#define mcif_wb_regs_dcn3(id)\ -[id] = {\ - MCIF_WB_COMMON_REG_LIST_DCN32(id),\ -} +#define mcif_wb_regs_dcn3_init(id)\ + MCIF_WB_COMMON_REG_LIST_DCN32_RI(id) -static const struct dcn30_mmhubbub_registers mcif_wb30_regs[] = { - mcif_wb_regs_dcn3(0) -}; +static struct dcn30_mmhubbub_registers mcif_wb30_regs[1]; static const struct dcn30_mmhubbub_shift mcif_wb30_shift = { MCIF_WB_COMMON_MASK_SH_LIST_DCN32(__SHIFT) @@ -545,17 +431,10 @@ static const struct dcn30_mmhubbub_mask mcif_wb30_mask = { MCIF_WB_COMMON_MASK_SH_LIST_DCN32(_MASK) }; -#define dsc_regsDCN20(id)\ -[id] = {\ - DSC_REG_LIST_DCN20(id)\ -} +#define dsc_regsDCN20_init(id)\ + DSC_REG_LIST_DCN20_RI(id) -static const struct dcn20_dsc_registers dsc_regs[] = { - dsc_regsDCN20(0), - dsc_regsDCN20(1), - dsc_regsDCN20(2), - dsc_regsDCN20(3) -}; +static struct dcn20_dsc_registers dsc_regs[4]; static const struct dcn20_dsc_shift dsc_shift = { DSC_REG_LIST_SH_MASK_DCN20(__SHIFT) @@ -565,17 +444,18 @@ static const struct dcn20_dsc_mask dsc_mask = { DSC_REG_LIST_SH_MASK_DCN20(_MASK) }; -static const struct dcn30_mpc_registers mpc_regs = { - MPC_REG_LIST_DCN3_2(0), - MPC_REG_LIST_DCN3_2(1), - MPC_REG_LIST_DCN3_2(2), - MPC_REG_LIST_DCN3_2(3), - MPC_OUT_MUX_REG_LIST_DCN3_0(0), - MPC_OUT_MUX_REG_LIST_DCN3_0(1), - MPC_OUT_MUX_REG_LIST_DCN3_0(2), - MPC_OUT_MUX_REG_LIST_DCN3_0(3), - MPC_DWB_MUX_REG_LIST_DCN3_0(0), -}; +static struct dcn30_mpc_registers mpc_regs; + +#define dcn_mpc_regs_init() \ + MPC_REG_LIST_DCN3_2_RI(0),\ + MPC_REG_LIST_DCN3_2_RI(1),\ + MPC_REG_LIST_DCN3_2_RI(2),\ + MPC_REG_LIST_DCN3_2_RI(3),\ + MPC_OUT_MUX_REG_LIST_DCN3_0_RI(0),\ + MPC_OUT_MUX_REG_LIST_DCN3_0_RI(1),\ + MPC_OUT_MUX_REG_LIST_DCN3_0_RI(2),\ + MPC_OUT_MUX_REG_LIST_DCN3_0_RI(3),\ + MPC_DWB_MUX_REG_LIST_DCN3_0_RI(0) static const struct dcn30_mpc_shift mpc_shift = { MPC_COMMON_MASK_SH_LIST_DCN32(__SHIFT) @@ -585,19 +465,10 @@ static const struct dcn30_mpc_mask mpc_mask = { MPC_COMMON_MASK_SH_LIST_DCN32(_MASK) }; -#define optc_regs(id)\ -[id] = {OPTC_COMMON_REG_LIST_DCN3_2(id)} - -//#ifdef DIAGS_BUILD -//static struct dcn_optc_registers optc_regs[] = { -//#else -static const struct dcn_optc_registers optc_regs[] = { -//#endif - optc_regs(0), - optc_regs(1), - optc_regs(2), - optc_regs(3) -}; +#define optc_regs_init(id)\ + OPTC_COMMON_REG_LIST_DCN3_2_RI(id) + +static struct dcn_optc_registers optc_regs[4]; static const struct dcn_optc_shift optc_shift = { OPTC_COMMON_MASK_SH_LIST_DCN3_2(__SHIFT) @@ -607,17 +478,10 @@ static const struct dcn_optc_mask optc_mask = { OPTC_COMMON_MASK_SH_LIST_DCN3_2(_MASK) }; -#define hubp_regs(id)\ -[id] = {\ - HUBP_REG_LIST_DCN32(id)\ -} +#define hubp_regs_init(id)\ + HUBP_REG_LIST_DCN32_RI(id) -static const struct dcn_hubp2_registers hubp_regs[] = { - hubp_regs(0), - hubp_regs(1), - hubp_regs(2), - hubp_regs(3) -}; +static struct dcn_hubp2_registers hubp_regs[4]; static const struct dcn_hubp2_shift hubp_shift = { @@ -627,9 +491,10 @@ static const struct dcn_hubp2_shift hubp_shift = { static const struct dcn_hubp2_mask hubp_mask = { HUBP_MASK_SH_LIST_DCN32(_MASK) }; -static const struct dcn_hubbub_registers hubbub_reg = { - HUBBUB_REG_LIST_DCN32(0) -}; + +static struct dcn_hubbub_registers hubbub_reg; +#define hubbub_reg_init()\ + HUBBUB_REG_LIST_DCN32_RI(0) static const struct dcn_hubbub_shift hubbub_shift = { HUBBUB_MASK_SH_LIST_DCN32(__SHIFT) @@ -639,9 +504,10 @@ static const struct dcn_hubbub_mask hubbub_mask = { HUBBUB_MASK_SH_LIST_DCN32(_MASK) }; -static const struct dccg_registers dccg_regs = { - DCCG_REG_LIST_DCN32() -}; +static struct dccg_registers dccg_regs; + +#define dccg_regs_init()\ + DCCG_REG_LIST_DCN32_RI() static const struct dccg_shift dccg_shift = { DCCG_MASK_SH_LIST_DCN32(__SHIFT) @@ -714,9 +580,10 @@ static const struct dccg_mask dccg_mask = { SR(AZALIA_AUDIO_DTO), \ SR(AZALIA_CONTROLLER_CLOCK_GATING) -static const struct dce_hwseq_registers hwseq_reg = { - HWSEQ_DCN32_REG_LIST() -}; +static struct dce_hwseq_registers hwseq_reg; + +#define hwseq_reg_init()\ + HWSEQ_DCN32_REG_LIST() #define HWSEQ_DCN32_MASK_SH_LIST(mask_sh)\ HWSEQ_DCN_MASK_SH_LIST(mask_sh), \ @@ -759,29 +626,10 @@ static const struct dce_hwseq_shift hwseq_shift = { static const struct dce_hwseq_mask hwseq_mask = { HWSEQ_DCN32_MASK_SH_LIST(_MASK) }; -#define vmid_regs(id)\ -[id] = {\ - DCN20_VMID_REG_LIST(id)\ -} +#define vmid_regs_init(id)\ + DCN20_VMID_REG_LIST_RI(id) -static const struct dcn_vmid_registers vmid_regs[] = { - vmid_regs(0), - vmid_regs(1), - vmid_regs(2), - vmid_regs(3), - vmid_regs(4), - vmid_regs(5), - vmid_regs(6), - vmid_regs(7), - vmid_regs(8), - vmid_regs(9), - vmid_regs(10), - vmid_regs(11), - vmid_regs(12), - vmid_regs(13), - vmid_regs(14), - vmid_regs(15) -}; +static struct dcn_vmid_registers vmid_regs[16]; static const struct dcn20_vmid_shift vmid_shifts = { DCN20_VMID_MASK_SH_LIST(__SHIFT) @@ -870,8 +718,12 @@ static const struct dc_debug_options debug_defaults_drv = { .force_disable_subvp = false, .exit_idle_opt_for_cursor_updates = true, .enable_single_display_2to1_odm_policy = true, + + /* Must match enable_single_display_2to1_odm_policy to support dynamic ODM transitions*/ + .enable_double_buffered_dsc_pg_support = true, .enable_dp_dig_pixel_rate_div_policy = 1, .allow_sw_cursor_fallback = false, + .alloc_extra_way_for_cursor = true, }; static const struct dc_debug_options debug_defaults_diags = { @@ -904,6 +756,14 @@ static struct dce_aux *dcn32_aux_engine_create( if (!aux_engine) return NULL; +#undef REG_STRUCT +#define REG_STRUCT aux_engine_regs + aux_engine_regs_init(0), + aux_engine_regs_init(1), + aux_engine_regs_init(2), + aux_engine_regs_init(3), + aux_engine_regs_init(4); + dce110_aux_engine_construct(aux_engine, ctx, inst, SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, &aux_engine_regs[inst], @@ -913,15 +773,10 @@ static struct dce_aux *dcn32_aux_engine_create( return &aux_engine->base; } -#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST_DCN30(id) } - -static const struct dce_i2c_registers i2c_hw_regs[] = { - i2c_inst_regs(1), - i2c_inst_regs(2), - i2c_inst_regs(3), - i2c_inst_regs(4), - i2c_inst_regs(5), -}; +#define i2c_inst_regs_init(id)\ + I2C_HW_ENGINE_COMMON_REG_LIST_DCN30_RI(id) + +static struct dce_i2c_registers i2c_hw_regs[5]; static const struct dce_i2c_shift i2c_shifts = { I2C_COMMON_MASK_SH_LIST_DCN30(__SHIFT) @@ -941,6 +796,14 @@ static struct dce_i2c_hw *dcn32_i2c_hw_create( if (!dce_i2c_hw) return NULL; +#undef REG_STRUCT +#define REG_STRUCT i2c_hw_regs + i2c_inst_regs_init(1), + i2c_inst_regs_init(2), + i2c_inst_regs_init(3), + i2c_inst_regs_init(4), + i2c_inst_regs_init(5); + dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); @@ -980,6 +843,29 @@ static struct hubbub *dcn32_hubbub_create(struct dc_context *ctx) if (!hubbub2) return NULL; +#undef REG_STRUCT +#define REG_STRUCT hubbub_reg + hubbub_reg_init(); + +#undef REG_STRUCT +#define REG_STRUCT vmid_regs + vmid_regs_init(0), + vmid_regs_init(1), + vmid_regs_init(2), + vmid_regs_init(3), + vmid_regs_init(4), + vmid_regs_init(5), + vmid_regs_init(6), + vmid_regs_init(7), + vmid_regs_init(8), + vmid_regs_init(9), + vmid_regs_init(10), + vmid_regs_init(11), + vmid_regs_init(12), + vmid_regs_init(13), + vmid_regs_init(14), + vmid_regs_init(15); + hubbub32_construct(hubbub2, ctx, &hubbub_reg, &hubbub_shift, @@ -1012,6 +898,13 @@ static struct hubp *dcn32_hubp_create( if (!hubp2) return NULL; +#undef REG_STRUCT +#define REG_STRUCT hubp_regs + hubp_regs_init(0), + hubp_regs_init(1), + hubp_regs_init(2), + hubp_regs_init(3); + if (hubp32_construct(hubp2, ctx, inst, &hubp_regs[inst], &hubp_shift, &hubp_mask)) return &hubp2->base; @@ -1037,6 +930,13 @@ static struct dpp *dcn32_dpp_create( if (!dpp3) return NULL; +#undef REG_STRUCT +#define REG_STRUCT dpp_regs + dpp_regs_init(0), + dpp_regs_init(1), + dpp_regs_init(2), + dpp_regs_init(3); + if (dpp32_construct(dpp3, ctx, inst, &dpp_regs[inst], &tf_shift, &tf_mask)) return &dpp3->base; @@ -1057,6 +957,10 @@ static struct mpc *dcn32_mpc_create( if (!mpc30) return NULL; +#undef REG_STRUCT +#define REG_STRUCT mpc_regs + dcn_mpc_regs_init(); + dcn32_mpc_construct(mpc30, ctx, &mpc_regs, &mpc_shift, @@ -1078,6 +982,13 @@ static struct output_pixel_processor *dcn32_opp_create( return NULL; } +#undef REG_STRUCT +#define REG_STRUCT opp_regs + opp_regs_init(0), + opp_regs_init(1), + opp_regs_init(2), + opp_regs_init(3); + dcn20_opp_construct(opp2, ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); return &opp2->base; @@ -1094,6 +1005,13 @@ static struct timing_generator *dcn32_timing_generator_create( if (!tgn10) return NULL; +#undef REG_STRUCT +#define REG_STRUCT optc_regs + optc_regs_init(0), + optc_regs_init(1), + optc_regs_init(2), + optc_regs_init(3); + tgn10->base.inst = instance; tgn10->base.ctx = ctx; @@ -1128,6 +1046,30 @@ static struct link_encoder *dcn32_link_encoder_create( if (!enc20) return NULL; +#undef REG_STRUCT +#define REG_STRUCT link_enc_aux_regs + aux_regs_init(0), + aux_regs_init(1), + aux_regs_init(2), + aux_regs_init(3), + aux_regs_init(4); + +#undef REG_STRUCT +#define REG_STRUCT link_enc_hpd_regs + hpd_regs_init(0), + hpd_regs_init(1), + hpd_regs_init(2), + hpd_regs_init(3), + hpd_regs_init(4); + +#undef REG_STRUCT +#define REG_STRUCT link_enc_regs + link_regs_init(0, A), + link_regs_init(1, B), + link_regs_init(2, C), + link_regs_init(3, D), + link_regs_init(4, E); + dcn32_link_encoder_construct(enc20, enc_init_data, &link_enc_feature, @@ -1157,7 +1099,7 @@ static void read_dce_straps( struct dc_context *ctx, struct resource_straps *straps) { - generic_reg_get(ctx, regDC_PINSTRAPS + BASE(regDC_PINSTRAPS_BASE_IDX), + generic_reg_get(ctx, ctx->dcn_reg_offsets[regDC_PINSTRAPS_BASE_IDX] + regDC_PINSTRAPS, FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); } @@ -1165,6 +1107,15 @@ static void read_dce_straps( static struct audio *dcn32_create_audio( struct dc_context *ctx, unsigned int inst) { + +#undef REG_STRUCT +#define REG_STRUCT audio_regs + audio_regs_init(0), + audio_regs_init(1), + audio_regs_init(2), + audio_regs_init(3), + audio_regs_init(4); + return dce_audio_create(ctx, inst, &audio_regs[inst], &audio_shift, &audio_mask); } @@ -1178,6 +1129,19 @@ static struct vpg *dcn32_vpg_create( if (!vpg3) return NULL; +#undef REG_STRUCT +#define REG_STRUCT vpg_regs + vpg_regs_init(0), + vpg_regs_init(1), + vpg_regs_init(2), + vpg_regs_init(3), + vpg_regs_init(4), + vpg_regs_init(5), + vpg_regs_init(6), + vpg_regs_init(7), + vpg_regs_init(8), + vpg_regs_init(9); + vpg3_construct(vpg3, ctx, inst, &vpg_regs[inst], &vpg_shift, @@ -1195,6 +1159,15 @@ static struct afmt *dcn32_afmt_create( if (!afmt3) return NULL; +#undef REG_STRUCT +#define REG_STRUCT afmt_regs + afmt_regs_init(0), + afmt_regs_init(1), + afmt_regs_init(2), + afmt_regs_init(3), + afmt_regs_init(4), + afmt_regs_init(5); + afmt3_construct(afmt3, ctx, inst, &afmt_regs[inst], &afmt_shift, @@ -1212,6 +1185,13 @@ static struct apg *dcn31_apg_create( if (!apg31) return NULL; +#undef REG_STRUCT +#define REG_STRUCT apg_regs + apg_regs_init(0), + apg_regs_init(1), + apg_regs_init(2), + apg_regs_init(3); + apg31_construct(apg31, ctx, inst, &apg_regs[inst], &apg_shift, @@ -1248,6 +1228,14 @@ static struct stream_encoder *dcn32_stream_encoder_create( return NULL; } +#undef REG_STRUCT +#define REG_STRUCT stream_enc_regs + stream_enc_regs_init(0), + stream_enc_regs_init(1), + stream_enc_regs_init(2), + stream_enc_regs_init(3), + stream_enc_regs_init(4); + dcn32_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, eng_id, vpg, afmt, &stream_enc_regs[eng_id], @@ -1298,6 +1286,13 @@ static struct hpo_dp_stream_encoder *dcn32_hpo_dp_stream_encoder_create( return NULL; } +#undef REG_STRUCT +#define REG_STRUCT hpo_dp_stream_enc_regs + hpo_dp_stream_encoder_reg_init(0), + hpo_dp_stream_encoder_reg_init(1), + hpo_dp_stream_encoder_reg_init(2), + hpo_dp_stream_encoder_reg_init(3); + dcn31_hpo_dp_stream_encoder_construct(hpo_dp_enc31, ctx, ctx->dc_bios, hpo_dp_inst, eng_id, vpg, apg, &hpo_dp_stream_enc_regs[hpo_dp_inst], @@ -1315,6 +1310,11 @@ static struct hpo_dp_link_encoder *dcn32_hpo_dp_link_encoder_create( /* allocate HPO link encoder */ hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL); +#undef REG_STRUCT +#define REG_STRUCT hpo_dp_link_enc_regs + hpo_dp_link_encoder_reg_init(0), + hpo_dp_link_encoder_reg_init(1); + hpo_dp_link_encoder32_construct(hpo_dp_enc31, ctx, inst, &hpo_dp_link_enc_regs[inst], &hpo_dp_le_shift, &hpo_dp_le_mask); @@ -1327,6 +1327,10 @@ static struct dce_hwseq *dcn32_hwseq_create( { struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); +#undef REG_STRUCT +#define REG_STRUCT hwseq_reg + hwseq_reg_init(); + if (hws) { hws->ctx = ctx; hws->regs = &hwseq_reg; @@ -1518,6 +1522,10 @@ static bool dcn32_dwbc_create(struct dc_context *ctx, struct resource_pool *pool return false; } +#undef REG_STRUCT +#define REG_STRUCT dwbc30_regs + dwbc_regs_dcn3_init(0); + dcn30_dwbc_construct(dwbc30, ctx, &dwbc30_regs[i], &dwbc30_shift, @@ -1543,6 +1551,10 @@ static bool dcn32_mmhubbub_create(struct dc_context *ctx, struct resource_pool * return false; } +#undef REG_STRUCT +#define REG_STRUCT mcif_wb30_regs + mcif_wb_regs_dcn3_init(0); + dcn32_mmhubbub_construct(mcif_wb30, ctx, &mcif_wb30_regs[i], &mcif_wb30_shift, @@ -1565,6 +1577,13 @@ static struct display_stream_compressor *dcn32_dsc_create( return NULL; } +#undef REG_STRUCT +#define REG_STRUCT dsc_regs + dsc_regsDCN20_init(0), + dsc_regsDCN20_init(1), + dsc_regsDCN20_init(2), + dsc_regsDCN20_init(3); + dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask); dsc->max_image_width = 6016; @@ -1702,13 +1721,26 @@ bool dcn32_remove_phantom_pipes(struct dc *dc, struct dc_state *context) { int i; bool removed_pipe = false; + struct dc_plane_state *phantom_plane = NULL; + struct dc_stream_state *phantom_stream = NULL; for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; // build scaling params for phantom pipes if (pipe->plane_state && pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { + phantom_plane = pipe->plane_state; + phantom_stream = pipe->stream; + dc_rem_all_planes_for_stream(dc, pipe->stream, context); dc_remove_stream_from_ctx(dc, context, pipe->stream); + + /* Ref count is incremented on allocation and also when added to the context. + * Therefore we must call release for the the phantom plane and stream once + * they are removed from the ctx to finally decrement the refcount to 0 to free. + */ + dc_plane_state_release(phantom_plane); + dc_stream_release(phantom_stream); + removed_pipe = true; } @@ -1808,12 +1840,6 @@ validate_out: return out; } - -static bool is_dual_plane(enum surface_pixel_format format) -{ - return format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN || format == SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA; -} - int dcn32_populate_dml_pipes_from_context( struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, @@ -1822,12 +1848,37 @@ int dcn32_populate_dml_pipes_from_context( int i, pipe_cnt; struct resource_context *res_ctx = &context->res_ctx; struct pipe_ctx *pipe; - bool subvp_in_use = false, is_pipe_split_expected[MAX_PIPES]; - int plane_count = 0; + bool subvp_in_use = false; + uint8_t is_pipe_split_expected[MAX_PIPES] = {0}; struct dc_crtc_timing *timing; dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); + /* Determine whether we will apply ODM 2to1 policy: + * Applies to single display and where the number of planes is less than 3. + * For 3 plane case ( 2 MPO planes ), we will not set the policy for the MPO pipes. + * + * Apply pipe split policy first so we can predict the pipe split correctly + * (dcn32_predict_pipe_split). + */ + for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { + if (!res_ctx->pipe_ctx[i].stream) + continue; + pipe = &res_ctx->pipe_ctx[i]; + timing = &pipe->stream->timing; + + pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_dal; + if (context->stream_count == 1 && + context->stream_status[0].plane_count <= 1 && + !dc_is_hdmi_signal(res_ctx->pipe_ctx[i].stream->signal) && + is_h_timing_divisible_by_2(res_ctx->pipe_ctx[i].stream) && + pipe->stream->timing.pix_clk_100hz * 100 > DCN3_2_VMIN_DISPCLK_HZ && + dc->debug.enable_single_display_2to1_odm_policy) { + pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_2to1; + } + pipe_cnt++; + } + for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { if (!res_ctx->pipe_ctx[i].stream) @@ -1880,59 +1931,18 @@ int dcn32_populate_dml_pipes_from_context( } } - /* Calculate the number of planes we have so we can determine - * whether to apply ODM 2to1 policy or not - */ - if (pipe->stream && !pipe->prev_odm_pipe && - (!pipe->top_pipe || pipe->top_pipe->plane_state != pipe->plane_state)) - ++plane_count; - DC_FP_START(); - is_pipe_split_expected[i] = dcn32_predict_pipe_split(context, pipes[i].pipe, i); + is_pipe_split_expected[i] = dcn32_predict_pipe_split(context, &pipes[pipe_cnt]); DC_FP_END(); pipe_cnt++; } - /* Determine whether we will apply ODM 2to1 policy - * Applies to single display and where the number of planes is less than 3 - * For 3 plane case ( 2 MPO planes ), we will not set the policy for the MPO pipes - */ - for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { - if (!res_ctx->pipe_ctx[i].stream) - continue; - pipe = &res_ctx->pipe_ctx[i]; - timing = &pipe->stream->timing; - - pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_dal; - res_ctx->pipe_ctx[i].stream->odm_2to1_policy_applied = false; - if (context->stream_count == 1 && timing->dsc_cfg.num_slices_h != 1) { - if (dc->debug.enable_single_display_2to1_odm_policy) { - if (!((plane_count > 2) && pipe->top_pipe)) - pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_2to1; - } - res_ctx->pipe_ctx[i].stream->odm_2to1_policy_applied = true; - } - pipe_cnt++; - } - /* For DET allocation, we don't want to use DML policy (not optimal for utilizing all * the DET available for each pipe). Use the DET override input to maintain our driver * policy. */ - if (pipe_cnt == 1 && !is_pipe_split_expected[0]) { - pipes[0].pipe.src.det_size_override = DCN3_2_MAX_DET_SIZE; - if (pipe->plane_state && !dc->debug.disable_z9_mpc) { - if (!is_dual_plane(pipe->plane_state->format)) { - pipes[0].pipe.src.det_size_override = DCN3_2_DEFAULT_DET_SIZE; - pipes[0].pipe.src.unbounded_req_mode = true; - if (pipe->plane_state->src_rect.width >= 5120 && - pipe->plane_state->src_rect.height >= 2880) - pipes[0].pipe.src.det_size_override = 320; // 5K or higher - } - } - } else - dcn32_determine_det_override(context, pipes, is_pipe_split_expected, dc->res_pool->pipe_count); + dcn32_set_det_allocations(dc, context, pipes); // In general cases we want to keep the dram clock change requirement // (prefer configs that support MCLK switch). Only override to false @@ -2003,6 +2013,28 @@ static bool dcn32_resource_construct( uint32_t pipe_fuses = 0; uint32_t num_pipes = 4; + #undef REG_STRUCT + #define REG_STRUCT bios_regs + bios_regs_init(); + + #undef REG_STRUCT + #define REG_STRUCT clk_src_regs + clk_src_regs_init(0, A), + clk_src_regs_init(1, B), + clk_src_regs_init(2, C), + clk_src_regs_init(3, D), + clk_src_regs_init(4, E); + #undef REG_STRUCT + #define REG_STRUCT abm_regs + abm_regs_init(0), + abm_regs_init(1), + abm_regs_init(2), + abm_regs_init(3); + + #undef REG_STRUCT + #define REG_STRUCT dccg_regs + dccg_regs_init(); + DC_FP_START(); ctx->dc_bios->regs = &bios_regs; diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h index cf15d0e5e9b4..55945cca2260 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h @@ -28,11 +28,16 @@ #include "core_types.h" +#define DCN3_2_DEFAULT_DET_SIZE 256 +#define DCN3_2_MAX_DET_SIZE 1152 +#define DCN3_2_MIN_DET_SIZE 128 +#define DCN3_2_MIN_COMPBUF_SIZE_KB 128 #define DCN3_2_DET_SEG_SIZE 64 #define DCN3_2_MALL_MBLK_SIZE_BYTES 65536 // 64 * 1024 #define DCN3_2_MBLK_WIDTH 128 #define DCN3_2_MBLK_HEIGHT_4BPE 128 #define DCN3_2_MBLK_HEIGHT_8BPE 64 +#define DCN3_2_VMIN_DISPCLK_HZ 717000000 #define TO_DCN32_RES_POOL(pool)\ container_of(pool, struct dcn32_resource_pool, base) @@ -109,7 +114,1167 @@ struct pipe_ctx *dcn32_acquire_idle_pipe_for_head_pipe_in_layer( struct dc_stream_state *stream, struct pipe_ctx *head_pipe); -void dcn32_determine_det_override(struct dc_state *context, display_e2e_pipe_params_st *pipes, - bool *is_pipe_split_expected, int pipe_cnt); +void dcn32_determine_det_override(struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes); + +void dcn32_set_det_allocations(struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes); +/* definitions for run time init of reg offsets */ + +/* CLK SRC */ +#define CS_COMMON_REG_LIST_DCN3_0_RI(index, pllid) \ + ( \ + SRI_ARR_ALPHABET(PIXCLK_RESYNC_CNTL, PHYPLL, index, pllid), \ + SRII_ARR_2(PHASE, DP_DTO, 0, index), \ + SRII_ARR_2(PHASE, DP_DTO, 1, index), \ + SRII_ARR_2(PHASE, DP_DTO, 2, index), \ + SRII_ARR_2(PHASE, DP_DTO, 3, index), \ + SRII_ARR_2(MODULO, DP_DTO, 0, index), \ + SRII_ARR_2(MODULO, DP_DTO, 1, index), \ + SRII_ARR_2(MODULO, DP_DTO, 2, index), \ + SRII_ARR_2(MODULO, DP_DTO, 3, index), \ + SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 0, index), \ + SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 1, index), \ + SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 2, index), \ + SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 3, index) \ + ) + +/* ABM */ +#define ABM_DCN32_REG_LIST_RI(id) \ + ( \ + SRI_ARR(DC_ABM1_HG_SAMPLE_RATE, ABM, id), \ + SRI_ARR(DC_ABM1_LS_SAMPLE_RATE, ABM, id), \ + SRI_ARR(BL1_PWM_BL_UPDATE_SAMPLE_RATE, ABM, id), \ + SRI_ARR(DC_ABM1_HG_MISC_CTRL, ABM, id), \ + SRI_ARR(DC_ABM1_IPCSC_COEFF_SEL, ABM, id), \ + SRI_ARR(BL1_PWM_CURRENT_ABM_LEVEL, ABM, id), \ + SRI_ARR(BL1_PWM_TARGET_ABM_LEVEL, ABM, id), \ + SRI_ARR(BL1_PWM_USER_LEVEL, ABM, id), \ + SRI_ARR(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, ABM, id), \ + SRI_ARR(DC_ABM1_HGLS_REG_READ_PROGRESS, ABM, id), \ + SRI_ARR(DC_ABM1_ACE_OFFSET_SLOPE_0, ABM, id), \ + SRI_ARR(DC_ABM1_ACE_THRES_12, ABM, id), NBIO_SR_ARR(BIOS_SCRATCH_2, id) \ + ) + +/* Audio */ +#define AUD_COMMON_REG_LIST_RI(id) \ + ( \ + SRI_ARR(AZALIA_F0_CODEC_ENDPOINT_INDEX, AZF0ENDPOINT, id), \ + SRI_ARR(AZALIA_F0_CODEC_ENDPOINT_DATA, AZF0ENDPOINT, id), \ + SR_ARR(AZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS, id), \ + SR_ARR(AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES, id), \ + SR_ARR(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, id), \ + SR_ARR(DCCG_AUDIO_DTO_SOURCE, id), SR_ARR(DCCG_AUDIO_DTO0_MODULE, id), \ + SR_ARR(DCCG_AUDIO_DTO0_PHASE, id), SR_ARR(DCCG_AUDIO_DTO1_MODULE, id), \ + SR_ARR(DCCG_AUDIO_DTO1_PHASE, id) \ + ) + +/* VPG */ + +#define VPG_DCN3_REG_LIST_RI(id) \ + ( \ + SRI_ARR(VPG_GENERIC_STATUS, VPG, id), \ + SRI_ARR(VPG_GENERIC_PACKET_ACCESS_CTRL, VPG, id), \ + SRI_ARR(VPG_GENERIC_PACKET_DATA, VPG, id), \ + SRI_ARR(VPG_GSP_FRAME_UPDATE_CTRL, VPG, id), \ + SRI_ARR(VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG, id) \ + ) + +/* AFMT */ +#define AFMT_DCN3_REG_LIST_RI(id) \ + ( \ + SRI_ARR(AFMT_INFOFRAME_CONTROL0, AFMT, id), \ + SRI_ARR(AFMT_VBI_PACKET_CONTROL, AFMT, id), \ + SRI_ARR(AFMT_AUDIO_PACKET_CONTROL, AFMT, id), \ + SRI_ARR(AFMT_AUDIO_PACKET_CONTROL2, AFMT, id), \ + SRI_ARR(AFMT_AUDIO_SRC_CONTROL, AFMT, id), \ + SRI_ARR(AFMT_60958_0, AFMT, id), SRI_ARR(AFMT_60958_1, AFMT, id), \ + SRI_ARR(AFMT_60958_2, AFMT, id), SRI_ARR(AFMT_MEM_PWR, AFMT, id) \ + ) + +/* APG */ +#define APG_DCN31_REG_LIST_RI(id) \ + (\ + SRI_ARR(APG_CONTROL, APG, id), SRI_ARR(APG_CONTROL2, APG, id), \ + SRI_ARR(APG_MEM_PWR, APG, id), SRI_ARR(APG_DBG_GEN_CONTROL, APG, id) \ + ) + +/* Stream encoder */ +#define SE_DCN32_REG_LIST_RI(id) \ + ( \ + SRI_ARR(AFMT_CNTL, DIG, id), SRI_ARR(DIG_FE_CNTL, DIG, id), \ + SRI_ARR(HDMI_CONTROL, DIG, id), SRI_ARR(HDMI_DB_CONTROL, DIG, id), \ + SRI_ARR(HDMI_GC, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL0, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL1, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL2, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL3, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL4, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL5, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL6, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL7, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL8, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL9, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL10, DIG, id), \ + SRI_ARR(HDMI_INFOFRAME_CONTROL0, DIG, id), \ + SRI_ARR(HDMI_INFOFRAME_CONTROL1, DIG, id), \ + SRI_ARR(HDMI_VBI_PACKET_CONTROL, DIG, id), \ + SRI_ARR(HDMI_AUDIO_PACKET_CONTROL, DIG, id), \ + SRI_ARR(HDMI_ACR_PACKET_CONTROL, DIG, id), \ + SRI_ARR(HDMI_ACR_32_0, DIG, id), SRI_ARR(HDMI_ACR_32_1, DIG, id), \ + SRI_ARR(HDMI_ACR_44_0, DIG, id), SRI_ARR(HDMI_ACR_44_1, DIG, id), \ + SRI_ARR(HDMI_ACR_48_0, DIG, id), SRI_ARR(HDMI_ACR_48_1, DIG, id), \ + SRI_ARR(DP_DB_CNTL, DP, id), SRI_ARR(DP_MSA_MISC, DP, id), \ + SRI_ARR(DP_MSA_VBID_MISC, DP, id), SRI_ARR(DP_MSA_COLORIMETRY, DP, id), \ + SRI_ARR(DP_MSA_TIMING_PARAM1, DP, id), \ + SRI_ARR(DP_MSA_TIMING_PARAM2, DP, id), \ + SRI_ARR(DP_MSA_TIMING_PARAM3, DP, id), \ + SRI_ARR(DP_MSA_TIMING_PARAM4, DP, id), \ + SRI_ARR(DP_MSE_RATE_CNTL, DP, id), SRI_ARR(DP_MSE_RATE_UPDATE, DP, id), \ + SRI_ARR(DP_PIXEL_FORMAT, DP, id), SRI_ARR(DP_SEC_CNTL, DP, id), \ + SRI_ARR(DP_SEC_CNTL1, DP, id), SRI_ARR(DP_SEC_CNTL2, DP, id), \ + SRI_ARR(DP_SEC_CNTL5, DP, id), SRI_ARR(DP_SEC_CNTL6, DP, id), \ + SRI_ARR(DP_STEER_FIFO, DP, id), SRI_ARR(DP_VID_M, DP, id), \ + SRI_ARR(DP_VID_N, DP, id), SRI_ARR(DP_VID_STREAM_CNTL, DP, id), \ + SRI_ARR(DP_VID_TIMING, DP, id), SRI_ARR(DP_SEC_AUD_N, DP, id), \ + SRI_ARR(DP_SEC_TIMESTAMP, DP, id), SRI_ARR(DP_DSC_CNTL, DP, id), \ + SRI_ARR(DP_SEC_METADATA_TRANSMISSION, DP, id), \ + SRI_ARR(HDMI_METADATA_PACKET_CONTROL, DIG, id), \ + SRI_ARR(DP_SEC_FRAMING4, DP, id), SRI_ARR(DP_GSP11_CNTL, DP, id), \ + SRI_ARR(DME_CONTROL, DME, id), \ + SRI_ARR(DP_SEC_METADATA_TRANSMISSION, DP, id), \ + SRI_ARR(HDMI_METADATA_PACKET_CONTROL, DIG, id), \ + SRI_ARR(DIG_FE_CNTL, DIG, id), SRI_ARR(DIG_CLOCK_PATTERN, DIG, id), \ + SRI_ARR(DIG_FIFO_CTRL0, DIG, id) \ + ) + +/* Aux regs */ + +#define AUX_REG_LIST_RI(id) \ + ( \ + SRI_ARR(AUX_CONTROL, DP_AUX, id), SRI_ARR(AUX_DPHY_RX_CONTROL0, DP_AUX, id), \ + SRI_ARR(AUX_DPHY_RX_CONTROL1, DP_AUX, id) \ + ) + +#define DCN2_AUX_REG_LIST_RI(id) \ + ( \ + AUX_REG_LIST_RI(id), SRI_ARR(AUX_DPHY_TX_CONTROL, DP_AUX, id) \ + ) + +/* HDP */ +#define HPD_REG_LIST_RI(id) SRI_ARR(DC_HPD_CONTROL, HPD, id) + +/* Link encoder */ +#define LE_DCN3_REG_LIST_RI(id) \ + ( \ + SRI_ARR(DIG_BE_CNTL, DIG, id), SRI_ARR(DIG_BE_EN_CNTL, DIG, id), \ + SRI_ARR(TMDS_CTL_BITS, DIG, id), \ + SRI_ARR(TMDS_DCBALANCER_CONTROL, DIG, id), SRI_ARR(DP_CONFIG, DP, id), \ + SRI_ARR(DP_DPHY_CNTL, DP, id), SRI_ARR(DP_DPHY_PRBS_CNTL, DP, id), \ + SRI_ARR(DP_DPHY_SCRAM_CNTL, DP, id), SRI_ARR(DP_DPHY_SYM0, DP, id), \ + SRI_ARR(DP_DPHY_SYM1, DP, id), SRI_ARR(DP_DPHY_SYM2, DP, id), \ + SRI_ARR(DP_DPHY_TRAINING_PATTERN_SEL, DP, id), \ + SRI_ARR(DP_LINK_CNTL, DP, id), SRI_ARR(DP_LINK_FRAMING_CNTL, DP, id), \ + SRI_ARR(DP_MSE_SAT0, DP, id), SRI_ARR(DP_MSE_SAT1, DP, id), \ + SRI_ARR(DP_MSE_SAT2, DP, id), SRI_ARR(DP_MSE_SAT_UPDATE, DP, id), \ + SRI_ARR(DP_SEC_CNTL, DP, id), SRI_ARR(DP_VID_STREAM_CNTL, DP, id), \ + SRI_ARR(DP_DPHY_FAST_TRAINING, DP, id), SRI_ARR(DP_SEC_CNTL1, DP, id), \ + SRI_ARR(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ + SRI_ARR(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id) \ + ) + +#define LE_DCN31_REG_LIST_RI(id) \ + ( \ + LE_DCN3_REG_LIST_RI(id), SRI_ARR(DP_DPHY_INTERNAL_CTRL, DP, id), \ + SR_ARR(DIO_LINKA_CNTL, id), SR_ARR(DIO_LINKB_CNTL, id), \ + SR_ARR(DIO_LINKC_CNTL, id), SR_ARR(DIO_LINKD_CNTL, id), \ + SR_ARR(DIO_LINKE_CNTL, id), SR_ARR(DIO_LINKF_CNTL, id) \ + ) + +#define UNIPHY_DCN2_REG_LIST_RI(id, phyid) \ + ( \ + SRI_ARR_ALPHABET(CLOCK_ENABLE, SYMCLK, id, phyid), \ + SRI_ARR_ALPHABET(CHANNEL_XBAR_CNTL, UNIPHY, id, phyid) \ + ) + +/* HPO DP stream encoder */ +#define DCN3_1_HPO_DP_STREAM_ENC_REG_LIST_RI(id) \ + ( \ + SR_ARR(DP_STREAM_MAPPER_CONTROL0, id), \ + SR_ARR(DP_STREAM_MAPPER_CONTROL1, id), \ + SR_ARR(DP_STREAM_MAPPER_CONTROL2, id), \ + SR_ARR(DP_STREAM_MAPPER_CONTROL3, id), \ + SRI_ARR(DP_STREAM_ENC_CLOCK_CONTROL, DP_STREAM_ENC, id), \ + SRI_ARR(DP_STREAM_ENC_INPUT_MUX_CONTROL, DP_STREAM_ENC, id), \ + SRI_ARR(DP_STREAM_ENC_AUDIO_CONTROL, DP_STREAM_ENC, id), \ + SRI_ARR(DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, DP_STREAM_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_CONTROL, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_PIXEL_FORMAT, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_PIXEL_FORMAT_DOUBLE_BUFFER_CONTROL, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA0, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA1, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA2, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA3, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA4, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA5, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA6, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA7, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA8, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA_CONTROL, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA_DOUBLE_BUFFER_CONTROL, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_FIFO_CONTROL, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_STREAM_CONTROL, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_VBID_CONTROL, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_SDP_CONTROL, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_SDP_GSP_CONTROL0, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_SDP_GSP_CONTROL2, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_SDP_GSP_CONTROL3, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_SDP_GSP_CONTROL5, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_SDP_GSP_CONTROL11, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_SDP_METADATA_PACKET_CONTROL, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_SDP_AUDIO_CONTROL0, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_CRC_CONTROL, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_HBLANK_CONTROL, DP_SYM32_ENC, id) \ + ) + +/* HPO DP link encoder regs */ +#define DCN3_1_HPO_DP_LINK_ENC_REG_LIST_RI(id) \ + ( \ + SRI_ARR(DP_LINK_ENC_CLOCK_CONTROL, DP_LINK_ENC, id), \ + SRI_ARR(DP_DPHY_SYM32_CONTROL, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_STATUS, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CONFIG, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_PRBS_SEED0, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_PRBS_SEED1, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_PRBS_SEED2, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_PRBS_SEED3, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_SQ_PULSE, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM0, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM1, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM2, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM3, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM4, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM5, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM6, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM7, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM8, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM9, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM10, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_SAT_VC0, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_SAT_VC1, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_SAT_VC2, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_SAT_VC3, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_VC_RATE_CNTL0, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_VC_RATE_CNTL1, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_VC_RATE_CNTL2, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_VC_RATE_CNTL3, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_SAT_UPDATE, DP_DPHY_SYM32, id) \ + ) + +/* DPP */ +#define DPP_REG_LIST_DCN30_COMMON_RI(id) \ + ( \ + SRI_ARR(CM_DEALPHA, CM, id), SRI_ARR(CM_MEM_PWR_STATUS, CM, id), \ + SRI_ARR(CM_BIAS_CR_R, CM, id), SRI_ARR(CM_BIAS_Y_G_CB_B, CM, id), \ + SRI_ARR(PRE_DEGAM, CNVC_CFG, id), SRI_ARR(CM_GAMCOR_CONTROL, CM, id), \ + SRI_ARR(CM_GAMCOR_LUT_CONTROL, CM, id), \ + SRI_ARR(CM_GAMCOR_LUT_INDEX, CM, id), \ + SRI_ARR(CM_GAMCOR_LUT_INDEX, CM, id), \ + SRI_ARR(CM_GAMCOR_LUT_DATA, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_START_CNTL_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_START_CNTL_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_START_CNTL_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_START_SLOPE_CNTL_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_START_SLOPE_CNTL_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_START_SLOPE_CNTL_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_END_CNTL1_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_END_CNTL2_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_END_CNTL1_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_END_CNTL2_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_END_CNTL1_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_END_CNTL2_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_REGION_0_1, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_REGION_32_33, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_OFFSET_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_OFFSET_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_OFFSET_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_START_BASE_CNTL_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_START_BASE_CNTL_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_START_BASE_CNTL_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_START_CNTL_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_START_CNTL_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_START_CNTL_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_START_SLOPE_CNTL_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_START_SLOPE_CNTL_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_START_SLOPE_CNTL_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_END_CNTL1_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_END_CNTL2_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_END_CNTL1_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_END_CNTL2_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_END_CNTL1_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_END_CNTL2_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_REGION_0_1, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_REGION_32_33, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_OFFSET_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_OFFSET_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_OFFSET_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_START_BASE_CNTL_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_START_BASE_CNTL_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_START_BASE_CNTL_R, CM, id), \ + SRI_ARR(CM_GAMUT_REMAP_CONTROL, CM, id), \ + SRI_ARR(CM_GAMUT_REMAP_C11_C12, CM, id), \ + SRI_ARR(CM_GAMUT_REMAP_C13_C14, CM, id), \ + SRI_ARR(CM_GAMUT_REMAP_C21_C22, CM, id), \ + SRI_ARR(CM_GAMUT_REMAP_C23_C24, CM, id), \ + SRI_ARR(CM_GAMUT_REMAP_C31_C32, CM, id), \ + SRI_ARR(CM_GAMUT_REMAP_C33_C34, CM, id), \ + SRI_ARR(CM_GAMUT_REMAP_B_C11_C12, CM, id), \ + SRI_ARR(CM_GAMUT_REMAP_B_C13_C14, CM, id), \ + SRI_ARR(CM_GAMUT_REMAP_B_C21_C22, CM, id), \ + SRI_ARR(CM_GAMUT_REMAP_B_C23_C24, CM, id), \ + SRI_ARR(CM_GAMUT_REMAP_B_C31_C32, CM, id), \ + SRI_ARR(CM_GAMUT_REMAP_B_C33_C34, CM, id), \ + SRI_ARR(DSCL_EXT_OVERSCAN_LEFT_RIGHT, DSCL, id), \ + SRI_ARR(DSCL_EXT_OVERSCAN_TOP_BOTTOM, DSCL, id), \ + SRI_ARR(OTG_H_BLANK, DSCL, id), SRI_ARR(OTG_V_BLANK, DSCL, id), \ + SRI_ARR(SCL_MODE, DSCL, id), SRI_ARR(LB_DATA_FORMAT, DSCL, id), \ + SRI_ARR(LB_MEMORY_CTRL, DSCL, id), SRI_ARR(DSCL_AUTOCAL, DSCL, id), \ + SRI_ARR(SCL_TAP_CONTROL, DSCL, id), \ + SRI_ARR(SCL_COEF_RAM_TAP_SELECT, DSCL, id), \ + SRI_ARR(SCL_COEF_RAM_TAP_DATA, DSCL, id), \ + SRI_ARR(DSCL_2TAP_CONTROL, DSCL, id), SRI_ARR(MPC_SIZE, DSCL, id), \ + SRI_ARR(SCL_HORZ_FILTER_SCALE_RATIO, DSCL, id), \ + SRI_ARR(SCL_VERT_FILTER_SCALE_RATIO, DSCL, id), \ + SRI_ARR(SCL_HORZ_FILTER_SCALE_RATIO_C, DSCL, id), \ + SRI_ARR(SCL_VERT_FILTER_SCALE_RATIO_C, DSCL, id), \ + SRI_ARR(SCL_HORZ_FILTER_INIT, DSCL, id), \ + SRI_ARR(SCL_HORZ_FILTER_INIT_C, DSCL, id), \ + SRI_ARR(SCL_VERT_FILTER_INIT, DSCL, id), \ + SRI_ARR(SCL_VERT_FILTER_INIT_C, DSCL, id), \ + SRI_ARR(RECOUT_START, DSCL, id), SRI_ARR(RECOUT_SIZE, DSCL, id), \ + SRI_ARR(PRE_DEALPHA, CNVC_CFG, id), SRI_ARR(PRE_REALPHA, CNVC_CFG, id), \ + SRI_ARR(PRE_CSC_MODE, CNVC_CFG, id), \ + SRI_ARR(PRE_CSC_C11_C12, CNVC_CFG, id), \ + SRI_ARR(PRE_CSC_C33_C34, CNVC_CFG, id), \ + SRI_ARR(PRE_CSC_B_C11_C12, CNVC_CFG, id), \ + SRI_ARR(PRE_CSC_B_C33_C34, CNVC_CFG, id), \ + SRI_ARR(CM_POST_CSC_CONTROL, CM, id), \ + SRI_ARR(CM_POST_CSC_C11_C12, CM, id), \ + SRI_ARR(CM_POST_CSC_C33_C34, CM, id), \ + SRI_ARR(CM_POST_CSC_B_C11_C12, CM, id), \ + SRI_ARR(CM_POST_CSC_B_C33_C34, CM, id), \ + SRI_ARR(CM_MEM_PWR_CTRL, CM, id), SRI_ARR(CM_CONTROL, CM, id), \ + SRI_ARR(FORMAT_CONTROL, CNVC_CFG, id), \ + SRI_ARR(CNVC_SURFACE_PIXEL_FORMAT, CNVC_CFG, id), \ + SRI_ARR(CURSOR0_CONTROL, CNVC_CUR, id), \ + SRI_ARR(CURSOR0_COLOR0, CNVC_CUR, id), \ + SRI_ARR(CURSOR0_COLOR1, CNVC_CUR, id), \ + SRI_ARR(CURSOR0_FP_SCALE_BIAS, CNVC_CUR, id), \ + SRI_ARR(DPP_CONTROL, DPP_TOP, id), SRI_ARR(CM_HDR_MULT_COEF, CM, id), \ + SRI_ARR(CURSOR_CONTROL, CURSOR0_, id), \ + SRI_ARR(ALPHA_2BIT_LUT, CNVC_CFG, id), \ + SRI_ARR(FCNV_FP_BIAS_R, CNVC_CFG, id), \ + SRI_ARR(FCNV_FP_BIAS_G, CNVC_CFG, id), \ + SRI_ARR(FCNV_FP_BIAS_B, CNVC_CFG, id), \ + SRI_ARR(FCNV_FP_SCALE_R, CNVC_CFG, id), \ + SRI_ARR(FCNV_FP_SCALE_G, CNVC_CFG, id), \ + SRI_ARR(FCNV_FP_SCALE_B, CNVC_CFG, id), \ + SRI_ARR(COLOR_KEYER_CONTROL, CNVC_CFG, id), \ + SRI_ARR(COLOR_KEYER_ALPHA, CNVC_CFG, id), \ + SRI_ARR(COLOR_KEYER_RED, CNVC_CFG, id), \ + SRI_ARR(COLOR_KEYER_GREEN, CNVC_CFG, id), \ + SRI_ARR(COLOR_KEYER_BLUE, CNVC_CFG, id), \ + SRI_ARR(CURSOR_CONTROL, CURSOR0_, id), \ + SRI_ARR(OBUF_MEM_PWR_CTRL, DSCL, id), \ + SRI_ARR(DSCL_MEM_PWR_STATUS, DSCL, id), \ + SRI_ARR(DSCL_MEM_PWR_CTRL, DSCL, id) \ + ) + +/* OPP */ +#define OPP_REG_LIST_DCN_RI(id) \ + ( \ + SRI_ARR(FMT_BIT_DEPTH_CONTROL, FMT, id), SRI_ARR(FMT_CONTROL, FMT, id), \ + SRI_ARR(FMT_DITHER_RAND_R_SEED, FMT, id), \ + SRI_ARR(FMT_DITHER_RAND_G_SEED, FMT, id), \ + SRI_ARR(FMT_DITHER_RAND_B_SEED, FMT, id), \ + SRI_ARR(FMT_CLAMP_CNTL, FMT, id), \ + SRI_ARR(FMT_DYNAMIC_EXP_CNTL, FMT, id), \ + SRI_ARR(FMT_MAP420_MEMORY_CONTROL, FMT, id), \ + SRI_ARR(OPPBUF_CONTROL, OPPBUF, id), \ + SRI_ARR(OPPBUF_3D_PARAMETERS_0, OPPBUF, id), \ + SRI_ARR(OPPBUF_3D_PARAMETERS_1, OPPBUF, id), \ + SRI_ARR(OPP_PIPE_CONTROL, OPP_PIPE, id) \ + ) + +#define OPP_REG_LIST_DCN10_RI(id) OPP_REG_LIST_DCN_RI(id) + +#define OPP_DPG_REG_LIST_RI(id) \ + ( \ + SRI_ARR(DPG_CONTROL, DPG, id), SRI_ARR(DPG_DIMENSIONS, DPG, id), \ + SRI_ARR(DPG_OFFSET_SEGMENT, DPG, id), SRI_ARR(DPG_COLOUR_B_CB, DPG, id), \ + SRI_ARR(DPG_COLOUR_G_Y, DPG, id), SRI_ARR(DPG_COLOUR_R_CR, DPG, id), \ + SRI_ARR(DPG_RAMP_CONTROL, DPG, id), SRI_ARR(DPG_STATUS, DPG, id) \ + ) + +#define OPP_REG_LIST_DCN30_RI(id) \ + ( \ + OPP_REG_LIST_DCN10_RI(id), OPP_DPG_REG_LIST_RI(id), \ + SRI_ARR(FMT_422_CONTROL, FMT, id) \ + ) + +/* Aux engine regs */ +#define AUX_COMMON_REG_LIST0_RI(id) \ + ( \ + SRI_ARR(AUX_CONTROL, DP_AUX, id), SRI_ARR(AUX_ARB_CONTROL, DP_AUX, id), \ + SRI_ARR(AUX_SW_DATA, DP_AUX, id), SRI_ARR(AUX_SW_CONTROL, DP_AUX, id), \ + SRI_ARR(AUX_INTERRUPT_CONTROL, DP_AUX, id), \ + SRI_ARR(AUX_DPHY_RX_CONTROL1, DP_AUX, id), \ + SRI_ARR(AUX_SW_STATUS, DP_AUX, id) \ + ) + +/* DWBC */ +#define DWBC_COMMON_REG_LIST_DCN30_RI(id) \ + ( \ + SR_ARR(DWB_ENABLE_CLK_CTRL, id), SR_ARR(DWB_MEM_PWR_CTRL, id), \ + SR_ARR(FC_MODE_CTRL, id), SR_ARR(FC_FLOW_CTRL, id), \ + SR_ARR(FC_WINDOW_START, id), SR_ARR(FC_WINDOW_SIZE, id), \ + SR_ARR(FC_SOURCE_SIZE, id), SR_ARR(DWB_UPDATE_CTRL, id), \ + SR_ARR(DWB_CRC_CTRL, id), SR_ARR(DWB_CRC_MASK_R_G, id), \ + SR_ARR(DWB_CRC_MASK_B_A, id), SR_ARR(DWB_CRC_VAL_R_G, id), \ + SR_ARR(DWB_CRC_VAL_B_A, id), SR_ARR(DWB_OUT_CTRL, id), \ + SR_ARR(DWB_MMHUBBUB_BACKPRESSURE_CNT_EN, id), \ + SR_ARR(DWB_MMHUBBUB_BACKPRESSURE_CNT, id), \ + SR_ARR(DWB_HOST_READ_CONTROL, id), SR_ARR(DWB_SOFT_RESET, id), \ + SR_ARR(DWB_HDR_MULT_COEF, id), SR_ARR(DWB_GAMUT_REMAP_MODE, id), \ + SR_ARR(DWB_GAMUT_REMAP_COEF_FORMAT, id), \ + SR_ARR(DWB_GAMUT_REMAPA_C11_C12, id), \ + SR_ARR(DWB_GAMUT_REMAPA_C13_C14, id), \ + SR_ARR(DWB_GAMUT_REMAPA_C21_C22, id), \ + SR_ARR(DWB_GAMUT_REMAPA_C23_C24, id), \ + SR_ARR(DWB_GAMUT_REMAPA_C31_C32, id), \ + SR_ARR(DWB_GAMUT_REMAPA_C33_C34, id), \ + SR_ARR(DWB_GAMUT_REMAPB_C11_C12, id), \ + SR_ARR(DWB_GAMUT_REMAPB_C13_C14, id), \ + SR_ARR(DWB_GAMUT_REMAPB_C21_C22, id), \ + SR_ARR(DWB_GAMUT_REMAPB_C23_C24, id), \ + SR_ARR(DWB_GAMUT_REMAPB_C31_C32, id), \ + SR_ARR(DWB_GAMUT_REMAPB_C33_C34, id), SR_ARR(DWB_OGAM_CONTROL, id), \ + SR_ARR(DWB_OGAM_LUT_INDEX, id), SR_ARR(DWB_OGAM_LUT_DATA, id), \ + SR_ARR(DWB_OGAM_LUT_CONTROL, id), \ + SR_ARR(DWB_OGAM_RAMA_START_CNTL_B, id), \ + SR_ARR(DWB_OGAM_RAMA_START_CNTL_G, id), \ + SR_ARR(DWB_OGAM_RAMA_START_CNTL_R, id), \ + SR_ARR(DWB_OGAM_RAMA_START_BASE_CNTL_B, id), \ + SR_ARR(DWB_OGAM_RAMA_START_SLOPE_CNTL_B, id), \ + SR_ARR(DWB_OGAM_RAMA_START_BASE_CNTL_G, id), \ + SR_ARR(DWB_OGAM_RAMA_START_SLOPE_CNTL_G, id), \ + SR_ARR(DWB_OGAM_RAMA_START_BASE_CNTL_R, id), \ + SR_ARR(DWB_OGAM_RAMA_START_SLOPE_CNTL_R, id), \ + SR_ARR(DWB_OGAM_RAMA_END_CNTL1_B, id), \ + SR_ARR(DWB_OGAM_RAMA_END_CNTL2_B, id), \ + SR_ARR(DWB_OGAM_RAMA_END_CNTL1_G, id), \ + SR_ARR(DWB_OGAM_RAMA_END_CNTL2_G, id), \ + SR_ARR(DWB_OGAM_RAMA_END_CNTL1_R, id), \ + SR_ARR(DWB_OGAM_RAMA_END_CNTL2_R, id), \ + SR_ARR(DWB_OGAM_RAMA_OFFSET_B, id), SR_ARR(DWB_OGAM_RAMA_OFFSET_G, id), \ + SR_ARR(DWB_OGAM_RAMA_OFFSET_R, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_0_1, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_2_3, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_4_5, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_6_7, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_8_9, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_10_11, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_12_13, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_14_15, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_16_17, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_18_19, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_20_21, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_22_23, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_24_25, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_26_27, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_28_29, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_30_31, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_32_33, id), \ + SR_ARR(DWB_OGAM_RAMB_START_CNTL_B, id), \ + SR_ARR(DWB_OGAM_RAMB_START_CNTL_G, id), \ + SR_ARR(DWB_OGAM_RAMB_START_CNTL_R, id), \ + SR_ARR(DWB_OGAM_RAMB_START_BASE_CNTL_B, id), \ + SR_ARR(DWB_OGAM_RAMB_START_SLOPE_CNTL_B, id), \ + SR_ARR(DWB_OGAM_RAMB_START_BASE_CNTL_G, id), \ + SR_ARR(DWB_OGAM_RAMB_START_SLOPE_CNTL_G, id), \ + SR_ARR(DWB_OGAM_RAMB_START_BASE_CNTL_R, id), \ + SR_ARR(DWB_OGAM_RAMB_START_SLOPE_CNTL_R, id), \ + SR_ARR(DWB_OGAM_RAMB_END_CNTL1_B, id), \ + SR_ARR(DWB_OGAM_RAMB_END_CNTL2_B, id), \ + SR_ARR(DWB_OGAM_RAMB_END_CNTL1_G, id), \ + SR_ARR(DWB_OGAM_RAMB_END_CNTL2_G, id), \ + SR_ARR(DWB_OGAM_RAMB_END_CNTL1_R, id), \ + SR_ARR(DWB_OGAM_RAMB_END_CNTL2_R, id), \ + SR_ARR(DWB_OGAM_RAMB_OFFSET_B, id), SR_ARR(DWB_OGAM_RAMB_OFFSET_G, id), \ + SR_ARR(DWB_OGAM_RAMB_OFFSET_R, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_0_1, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_2_3, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_4_5, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_6_7, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_8_9, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_10_11, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_12_13, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_14_15, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_16_17, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_18_19, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_20_21, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_22_23, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_24_25, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_26_27, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_28_29, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_30_31, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_32_33, id) \ + ) + +/* MCIF */ + +#define MCIF_WB_COMMON_REG_LIST_DCN32_RI(inst) \ + ( \ + SRI2_ARR(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUFMGR_STATUS, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_PITCH, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_1_STATUS, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_1_STATUS2, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_2_STATUS, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_2_STATUS2, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_3_STATUS, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_3_STATUS2, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_4_STATUS, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_4_STATUS2, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_SCLK_CHANGE, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_TEST_DEBUG_INDEX, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_TEST_DEBUG_DATA, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_1_ADDR_Y, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_1_ADDR_C, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_2_ADDR_Y, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_2_ADDR_C, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_3_ADDR_Y, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_3_ADDR_C, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_4_ADDR_Y, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_4_ADDR_C, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, MMHUBBUB, inst), \ + SRI2_ARR(MCIF_WB_NB_PSTATE_CONTROL, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_WATERMARK, MMHUBBUB, inst), \ + SRI2_ARR(MCIF_WB_CLOCK_GATER_CONTROL, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_SELF_REFRESH_CONTROL, MCIF_WB, inst), \ + SRI2_ARR(MULTI_LEVEL_QOS_CTRL, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_SECURITY_LEVEL, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_LUMA_SIZE, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_CHROMA_SIZE, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_1_ADDR_Y_HIGH, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_1_ADDR_C_HIGH, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_2_ADDR_Y_HIGH, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_2_ADDR_C_HIGH, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_3_ADDR_Y_HIGH, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_3_ADDR_C_HIGH, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_4_ADDR_Y_HIGH, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_4_ADDR_C_HIGH, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_1_RESOLUTION, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_2_RESOLUTION, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_3_RESOLUTION, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_4_RESOLUTION, MCIF_WB, inst), \ + SRI2_ARR(MMHUBBUB_MEM_PWR_CNTL, MMHUBBUB, inst), \ + SRI2_ARR(MMHUBBUB_WARMUP_ADDR_REGION, MMHUBBUB, inst), \ + SRI2_ARR(MMHUBBUB_WARMUP_BASE_ADDR_HIGH, MMHUBBUB, inst), \ + SRI2_ARR(MMHUBBUB_WARMUP_BASE_ADDR_LOW, MMHUBBUB, inst), \ + SRI2_ARR(MMHUBBUB_WARMUP_CONTROL_STATUS, MMHUBBUB, inst) \ + ) + +/* DSC */ + +#define DSC_REG_LIST_DCN20_RI(id) \ + ( \ + SRI_ARR(DSC_TOP_CONTROL, DSC_TOP, id), \ + SRI_ARR(DSC_DEBUG_CONTROL, DSC_TOP, id), \ + SRI_ARR(DSCC_CONFIG0, DSCC, id), SRI_ARR(DSCC_CONFIG1, DSCC, id), \ + SRI_ARR(DSCC_STATUS, DSCC, id), \ + SRI_ARR(DSCC_INTERRUPT_CONTROL_STATUS, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG0, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG1, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG2, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG3, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG4, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG5, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG6, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG7, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG8, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG9, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG10, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG11, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG12, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG13, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG14, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG15, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG16, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG17, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG18, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG19, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG20, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG21, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG22, DSCC, id), \ + SRI_ARR(DSCC_MEM_POWER_CONTROL, DSCC, id), \ + SRI_ARR(DSCC_R_Y_SQUARED_ERROR_LOWER, DSCC, id), \ + SRI_ARR(DSCC_R_Y_SQUARED_ERROR_UPPER, DSCC, id), \ + SRI_ARR(DSCC_G_CB_SQUARED_ERROR_LOWER, DSCC, id), \ + SRI_ARR(DSCC_G_CB_SQUARED_ERROR_UPPER, DSCC, id), \ + SRI_ARR(DSCC_B_CR_SQUARED_ERROR_LOWER, DSCC, id), \ + SRI_ARR(DSCC_B_CR_SQUARED_ERROR_UPPER, DSCC, id), \ + SRI_ARR(DSCC_MAX_ABS_ERROR0, DSCC, id), \ + SRI_ARR(DSCC_MAX_ABS_ERROR1, DSCC, id), \ + SRI_ARR(DSCC_RATE_BUFFER0_MAX_FULLNESS_LEVEL, DSCC, id), \ + SRI_ARR(DSCC_RATE_BUFFER1_MAX_FULLNESS_LEVEL, DSCC, id), \ + SRI_ARR(DSCC_RATE_BUFFER2_MAX_FULLNESS_LEVEL, DSCC, id), \ + SRI_ARR(DSCC_RATE_BUFFER3_MAX_FULLNESS_LEVEL, DSCC, id), \ + SRI_ARR(DSCC_RATE_CONTROL_BUFFER0_MAX_FULLNESS_LEVEL, DSCC, id), \ + SRI_ARR(DSCC_RATE_CONTROL_BUFFER1_MAX_FULLNESS_LEVEL, DSCC, id), \ + SRI_ARR(DSCC_RATE_CONTROL_BUFFER2_MAX_FULLNESS_LEVEL, DSCC, id), \ + SRI_ARR(DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL, DSCC, id), \ + SRI_ARR(DSCCIF_CONFIG0, DSCCIF, id), \ + SRI_ARR(DSCCIF_CONFIG1, DSCCIF, id), \ + SRI_ARR(DSCRM_DSC_FORWARD_CONFIG, DSCRM, id) \ + ) + +/* MPC */ + +#define MPC_DWB_MUX_REG_LIST_DCN3_0_RI(inst) \ + SRII_DWB(DWB_MUX, MUX, MPC_DWB, inst) + +#define MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0_RI(inst) \ + ( \ + SRII(MUX, MPC_OUT, inst), VUPDATE_SRII(CUR, VUPDATE_LOCK_SET, inst) \ + ) + +#define MPC_OUT_MUX_REG_LIST_DCN3_0_RI(inst) \ + ( \ + MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0_RI(inst), SRII(CSC_MODE, MPC_OUT, inst), \ + SRII(CSC_C11_C12_A, MPC_OUT, inst), SRII(CSC_C33_C34_A, MPC_OUT, inst), \ + SRII(CSC_C11_C12_B, MPC_OUT, inst), SRII(CSC_C33_C34_B, MPC_OUT, inst), \ + SRII(DENORM_CONTROL, MPC_OUT, inst), \ + SRII(DENORM_CLAMP_G_Y, MPC_OUT, inst), \ + SRII(DENORM_CLAMP_B_CB, MPC_OUT, inst), SR(MPC_OUT_CSC_COEF_FORMAT) \ + ) + +#define MPC_COMMON_REG_LIST_DCN1_0_RI(inst) \ + ( \ + SRII(MPCC_TOP_SEL, MPCC, inst), SRII(MPCC_BOT_SEL, MPCC, inst), \ + SRII(MPCC_CONTROL, MPCC, inst), SRII(MPCC_STATUS, MPCC, inst), \ + SRII(MPCC_OPP_ID, MPCC, inst), SRII(MPCC_BG_G_Y, MPCC, inst), \ + SRII(MPCC_BG_R_CR, MPCC, inst), SRII(MPCC_BG_B_CB, MPCC, inst), \ + SRII(MPCC_SM_CONTROL, MPCC, inst), \ + SRII(MPCC_UPDATE_LOCK_SEL, MPCC, inst) \ + ) + +#define MPC_REG_LIST_DCN3_0_RI(inst) \ + ( \ + MPC_COMMON_REG_LIST_DCN1_0_RI(inst), SRII(MPCC_TOP_GAIN, MPCC, inst), \ + SRII(MPCC_BOT_GAIN_INSIDE, MPCC, inst), \ + SRII(MPCC_BOT_GAIN_OUTSIDE, MPCC, inst), \ + SRII(MPCC_MEM_PWR_CTRL, MPCC, inst), \ + SRII(MPCC_OGAM_LUT_INDEX, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_LUT_DATA, MPCC_OGAM, inst), \ + SRII(MPCC_GAMUT_REMAP_COEF_FORMAT, MPCC_OGAM, inst), \ + SRII(MPCC_GAMUT_REMAP_MODE, MPCC_OGAM, inst), \ + SRII(MPC_GAMUT_REMAP_C11_C12_A, MPCC_OGAM, inst), \ + SRII(MPC_GAMUT_REMAP_C33_C34_A, MPCC_OGAM, inst), \ + SRII(MPC_GAMUT_REMAP_C11_C12_B, MPCC_OGAM, inst), \ + SRII(MPC_GAMUT_REMAP_C33_C34_B, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_START_CNTL_B, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_START_CNTL_G, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_START_CNTL_R, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_START_SLOPE_CNTL_B, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_START_SLOPE_CNTL_G, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_START_SLOPE_CNTL_R, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_END_CNTL1_B, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_END_CNTL2_B, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_END_CNTL1_G, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_END_CNTL2_G, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_END_CNTL1_R, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_END_CNTL2_R, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_REGION_0_1, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_REGION_32_33, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_OFFSET_B, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_OFFSET_G, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_OFFSET_R, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_START_BASE_CNTL_B, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_START_BASE_CNTL_G, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_START_BASE_CNTL_R, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_START_CNTL_B, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_START_CNTL_G, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_START_CNTL_R, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_START_SLOPE_CNTL_B, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_START_SLOPE_CNTL_G, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_START_SLOPE_CNTL_R, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_END_CNTL1_B, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_END_CNTL2_B, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_END_CNTL1_G, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_END_CNTL2_G, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_END_CNTL1_R, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_END_CNTL2_R, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_REGION_0_1, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_REGION_32_33, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_OFFSET_B, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_OFFSET_G, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_OFFSET_R, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_START_BASE_CNTL_B, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_START_BASE_CNTL_G, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_START_BASE_CNTL_R, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_CONTROL, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_LUT_CONTROL, MPCC_OGAM, inst) \ + ) + +#define MPC_REG_LIST_DCN3_2_RI(inst) \ + MPC_REG_LIST_DCN3_0_RI(inst),\ + SRII(MPCC_MOVABLE_CM_LOCATION_CONTROL, MPCC, inst),\ + SRII(MPCC_MCM_SHAPER_CONTROL, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_OFFSET_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_OFFSET_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_OFFSET_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_SCALE_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_SCALE_G_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_LUT_INDEX, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_LUT_DATA, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_LUT_WRITE_EN_MASK, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_START_CNTL_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_START_CNTL_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_START_CNTL_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_END_CNTL_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_END_CNTL_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_END_CNTL_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_0_1, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_2_3, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_4_5, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_6_7, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_8_9, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_10_11, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_12_13, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_14_15, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_16_17, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_18_19, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_20_21, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_22_23, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_24_25, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_26_27, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_28_29, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_30_31, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_32_33, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_START_CNTL_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_START_CNTL_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_START_CNTL_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_END_CNTL_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_END_CNTL_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_END_CNTL_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_0_1, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_2_3, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_4_5, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_6_7, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_8_9, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_10_11, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_12_13, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_14_15, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_16_17, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_18_19, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_20_21, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_22_23, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_24_25, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_26_27, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_28_29, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_30_31, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_32_33, MPCC_MCM, inst),\ + SRII(MPCC_MCM_3DLUT_MODE, MPCC_MCM, inst), /*TODO: may need to add other 3DLUT regs*/\ + SRII(MPCC_MCM_3DLUT_INDEX, MPCC_MCM, inst),\ + SRII(MPCC_MCM_3DLUT_DATA, MPCC_MCM, inst),\ + SRII(MPCC_MCM_3DLUT_DATA_30BIT, MPCC_MCM, inst),\ + SRII(MPCC_MCM_3DLUT_READ_WRITE_CONTROL, MPCC_MCM, inst),\ + SRII(MPCC_MCM_3DLUT_OUT_NORM_FACTOR, MPCC_MCM, inst),\ + SRII(MPCC_MCM_3DLUT_OUT_OFFSET_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_3DLUT_OUT_OFFSET_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_3DLUT_OUT_OFFSET_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_CONTROL, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_LUT_INDEX, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_LUT_DATA, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_LUT_CONTROL, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_START_CNTL_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_START_CNTL_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_START_CNTL_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_START_SLOPE_CNTL_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_START_SLOPE_CNTL_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_START_SLOPE_CNTL_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_START_BASE_CNTL_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_START_BASE_CNTL_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_START_BASE_CNTL_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_END_CNTL1_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_END_CNTL2_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_END_CNTL1_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_END_CNTL2_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_END_CNTL1_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_END_CNTL2_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_OFFSET_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_OFFSET_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_OFFSET_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_0_1, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_2_3, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_4_5, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_6_7, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_8_9, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_10_11, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_12_13, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_14_15, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_16_17, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_18_19, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_20_21, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_22_23, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_24_25, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_26_27, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_28_29, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_30_31, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_32_33, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_START_CNTL_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_START_CNTL_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_START_CNTL_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_START_SLOPE_CNTL_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_START_SLOPE_CNTL_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_START_SLOPE_CNTL_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_START_BASE_CNTL_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_START_BASE_CNTL_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_START_BASE_CNTL_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_END_CNTL1_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_END_CNTL2_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_END_CNTL1_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_END_CNTL2_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_END_CNTL1_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_END_CNTL2_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_OFFSET_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_OFFSET_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_OFFSET_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_0_1, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_2_3, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_4_5, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_6_7, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_8_9, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_10_11, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_12_13, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_14_15, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_16_17, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_18_19, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_20_21, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_22_23, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_24_25, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_26_27, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_28_29, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_30_31, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_32_33, MPCC_MCM, inst),\ + SRII(MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM, inst) + +/* OPTC */ + +#define OPTC_COMMON_REG_LIST_DCN3_2_RI(inst) \ + ( \ + SRI_ARR(OTG_VSTARTUP_PARAM, OTG, inst), \ + SRI_ARR(OTG_VUPDATE_PARAM, OTG, inst), \ + SRI_ARR(OTG_VREADY_PARAM, OTG, inst), \ + SRI_ARR(OTG_MASTER_UPDATE_LOCK, OTG, inst), \ + SRI_ARR(OTG_GLOBAL_CONTROL0, OTG, inst), \ + SRI_ARR(OTG_GLOBAL_CONTROL1, OTG, inst), \ + SRI_ARR(OTG_GLOBAL_CONTROL2, OTG, inst), \ + SRI_ARR(OTG_GLOBAL_CONTROL4, OTG, inst), \ + SRI_ARR(OTG_DOUBLE_BUFFER_CONTROL, OTG, inst), \ + SRI_ARR(OTG_H_TOTAL, OTG, inst), \ + SRI_ARR(OTG_H_BLANK_START_END, OTG, inst), \ + SRI_ARR(OTG_H_SYNC_A, OTG, inst), SRI_ARR(OTG_H_SYNC_A_CNTL, OTG, inst), \ + SRI_ARR(OTG_H_TIMING_CNTL, OTG, inst), SRI_ARR(OTG_V_TOTAL, OTG, inst), \ + SRI_ARR(OTG_V_BLANK_START_END, OTG, inst), \ + SRI_ARR(OTG_V_SYNC_A, OTG, inst), SRI_ARR(OTG_V_SYNC_A_CNTL, OTG, inst), \ + SRI_ARR(OTG_CONTROL, OTG, inst), SRI_ARR(OTG_STEREO_CONTROL, OTG, inst), \ + SRI_ARR(OTG_3D_STRUCTURE_CONTROL, OTG, inst), \ + SRI_ARR(OTG_STEREO_STATUS, OTG, inst), \ + SRI_ARR(OTG_V_TOTAL_MAX, OTG, inst), \ + SRI_ARR(OTG_V_TOTAL_MIN, OTG, inst), \ + SRI_ARR(OTG_V_TOTAL_CONTROL, OTG, inst), \ + SRI_ARR(OTG_TRIGA_CNTL, OTG, inst), \ + SRI_ARR(OTG_FORCE_COUNT_NOW_CNTL, OTG, inst), \ + SRI_ARR(OTG_STATIC_SCREEN_CONTROL, OTG, inst), \ + SRI_ARR(OTG_STATUS_FRAME_COUNT, OTG, inst), \ + SRI_ARR(OTG_STATUS, OTG, inst), SRI_ARR(OTG_STATUS_POSITION, OTG, inst), \ + SRI_ARR(OTG_NOM_VERT_POSITION, OTG, inst), \ + SRI_ARR(OTG_M_CONST_DTO0, OTG, inst), \ + SRI_ARR(OTG_M_CONST_DTO1, OTG, inst), \ + SRI_ARR(OTG_CLOCK_CONTROL, OTG, inst), \ + SRI_ARR(OTG_VERTICAL_INTERRUPT0_CONTROL, OTG, inst), \ + SRI_ARR(OTG_VERTICAL_INTERRUPT0_POSITION, OTG, inst), \ + SRI_ARR(OTG_VERTICAL_INTERRUPT1_CONTROL, OTG, inst), \ + SRI_ARR(OTG_VERTICAL_INTERRUPT1_POSITION, OTG, inst), \ + SRI_ARR(OTG_VERTICAL_INTERRUPT2_CONTROL, OTG, inst), \ + SRI_ARR(OTG_VERTICAL_INTERRUPT2_POSITION, OTG, inst), \ + SRI_ARR(OPTC_INPUT_CLOCK_CONTROL, ODM, inst), \ + SRI_ARR(OPTC_DATA_SOURCE_SELECT, ODM, inst), \ + SRI_ARR(OPTC_INPUT_GLOBAL_CONTROL, ODM, inst), \ + SRI_ARR(CONTROL, VTG, inst), SRI_ARR(OTG_VERT_SYNC_CONTROL, OTG, inst), \ + SRI_ARR(OTG_GSL_CONTROL, OTG, inst), SRI_ARR(OTG_CRC_CNTL, OTG, inst), \ + SRI_ARR(OTG_CRC0_DATA_RG, OTG, inst), \ + SRI_ARR(OTG_CRC0_DATA_B, OTG, inst), \ + SRI_ARR(OTG_CRC0_WINDOWA_X_CONTROL, OTG, inst), \ + SRI_ARR(OTG_CRC0_WINDOWA_Y_CONTROL, OTG, inst), \ + SRI_ARR(OTG_CRC0_WINDOWB_X_CONTROL, OTG, inst), \ + SRI_ARR(OTG_CRC0_WINDOWB_Y_CONTROL, OTG, inst), \ + SR_ARR(GSL_SOURCE_SELECT, inst), \ + SRI_ARR(OTG_TRIGA_MANUAL_TRIG, OTG, inst), \ + SRI_ARR(OTG_GLOBAL_CONTROL1, OTG, inst), \ + SRI_ARR(OTG_GLOBAL_CONTROL2, OTG, inst), \ + SRI_ARR(OTG_GSL_WINDOW_X, OTG, inst), \ + SRI_ARR(OTG_GSL_WINDOW_Y, OTG, inst), \ + SRI_ARR(OTG_VUPDATE_KEEPOUT, OTG, inst), \ + SRI_ARR(OTG_DSC_START_POSITION, OTG, inst), \ + SRI_ARR(OTG_DRR_TRIGGER_WINDOW, OTG, inst), \ + SRI_ARR(OTG_DRR_V_TOTAL_CHANGE, OTG, inst), \ + SRI_ARR(OPTC_DATA_FORMAT_CONTROL, ODM, inst), \ + SRI_ARR(OPTC_BYTES_PER_PIXEL, ODM, inst), \ + SRI_ARR(OPTC_WIDTH_CONTROL, ODM, inst), \ + SRI_ARR(OPTC_MEMORY_CONFIG, ODM, inst), \ + SRI_ARR(OTG_DRR_CONTROL, OTG, inst) \ + ) + +/* HUBP */ + +#define HUBP_REG_LIST_DCN_VM_RI(id) \ + ( \ + SRI_ARR(NOM_PARAMETERS_0, HUBPREQ, id), \ + SRI_ARR(NOM_PARAMETERS_1, HUBPREQ, id), \ + SRI_ARR(NOM_PARAMETERS_2, HUBPREQ, id), \ + SRI_ARR(NOM_PARAMETERS_3, HUBPREQ, id), \ + SRI_ARR(DCN_VM_MX_L1_TLB_CNTL, HUBPREQ, id) \ + ) + +#define HUBP_REG_LIST_DCN_RI(id) \ + ( \ + SRI_ARR(DCHUBP_CNTL, HUBP, id), SRI_ARR(HUBPREQ_DEBUG_DB, HUBP, id), \ + SRI_ARR(HUBPREQ_DEBUG, HUBP, id), SRI_ARR(DCSURF_ADDR_CONFIG, HUBP, id), \ + SRI_ARR(DCSURF_TILING_CONFIG, HUBP, id), \ + SRI_ARR(DCSURF_SURFACE_PITCH, HUBPREQ, id), \ + SRI_ARR(DCSURF_SURFACE_PITCH_C, HUBPREQ, id), \ + SRI_ARR(DCSURF_SURFACE_CONFIG, HUBP, id), \ + SRI_ARR(DCSURF_FLIP_CONTROL, HUBPREQ, id), \ + SRI_ARR(DCSURF_PRI_VIEWPORT_DIMENSION, HUBP, id), \ + SRI_ARR(DCSURF_PRI_VIEWPORT_START, HUBP, id), \ + SRI_ARR(DCSURF_SEC_VIEWPORT_DIMENSION, HUBP, id), \ + SRI_ARR(DCSURF_SEC_VIEWPORT_START, HUBP, id), \ + SRI_ARR(DCSURF_PRI_VIEWPORT_DIMENSION_C, HUBP, id), \ + SRI_ARR(DCSURF_PRI_VIEWPORT_START_C, HUBP, id), \ + SRI_ARR(DCSURF_SEC_VIEWPORT_DIMENSION_C, HUBP, id), \ + SRI_ARR(DCSURF_SEC_VIEWPORT_START_C, HUBP, id), \ + SRI_ARR(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, HUBPREQ, id), \ + SRI_ARR(DCSURF_PRIMARY_SURFACE_ADDRESS, HUBPREQ, id), \ + SRI_ARR(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, HUBPREQ, id), \ + SRI_ARR(DCSURF_SECONDARY_SURFACE_ADDRESS, HUBPREQ, id), \ + SRI_ARR(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, HUBPREQ, id), \ + SRI_ARR(DCSURF_PRIMARY_META_SURFACE_ADDRESS, HUBPREQ, id), \ + SRI_ARR(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, HUBPREQ, id), \ + SRI_ARR(DCSURF_SECONDARY_META_SURFACE_ADDRESS, HUBPREQ, id), \ + SRI_ARR(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, HUBPREQ, id), \ + SRI_ARR(DCSURF_PRIMARY_SURFACE_ADDRESS_C, HUBPREQ, id), \ + SRI_ARR(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH_C, HUBPREQ, id), \ + SRI_ARR(DCSURF_SECONDARY_SURFACE_ADDRESS_C, HUBPREQ, id), \ + SRI_ARR(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, HUBPREQ, id), \ + SRI_ARR(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, HUBPREQ, id), \ + SRI_ARR(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH_C, HUBPREQ, id), \ + SRI_ARR(DCSURF_SECONDARY_META_SURFACE_ADDRESS_C, HUBPREQ, id), \ + SRI_ARR(DCSURF_SURFACE_INUSE, HUBPREQ, id), \ + SRI_ARR(DCSURF_SURFACE_INUSE_HIGH, HUBPREQ, id), \ + SRI_ARR(DCSURF_SURFACE_INUSE_C, HUBPREQ, id), \ + SRI_ARR(DCSURF_SURFACE_INUSE_HIGH_C, HUBPREQ, id), \ + SRI_ARR(DCSURF_SURFACE_EARLIEST_INUSE, HUBPREQ, id), \ + SRI_ARR(DCSURF_SURFACE_EARLIEST_INUSE_HIGH, HUBPREQ, id), \ + SRI_ARR(DCSURF_SURFACE_EARLIEST_INUSE_C, HUBPREQ, id), \ + SRI_ARR(DCSURF_SURFACE_EARLIEST_INUSE_HIGH_C, HUBPREQ, id), \ + SRI_ARR(DCSURF_SURFACE_CONTROL, HUBPREQ, id), \ + SRI_ARR(DCSURF_SURFACE_FLIP_INTERRUPT, HUBPREQ, id), \ + SRI_ARR(HUBPRET_CONTROL, HUBPRET, id), \ + SRI_ARR(HUBPRET_READ_LINE_STATUS, HUBPRET, id), \ + SRI_ARR(DCN_EXPANSION_MODE, HUBPREQ, id), \ + SRI_ARR(DCHUBP_REQ_SIZE_CONFIG, HUBP, id), \ + SRI_ARR(DCHUBP_REQ_SIZE_CONFIG_C, HUBP, id), \ + SRI_ARR(BLANK_OFFSET_0, HUBPREQ, id), \ + SRI_ARR(BLANK_OFFSET_1, HUBPREQ, id), \ + SRI_ARR(DST_DIMENSIONS, HUBPREQ, id), \ + SRI_ARR(DST_AFTER_SCALER, HUBPREQ, id), \ + SRI_ARR(VBLANK_PARAMETERS_0, HUBPREQ, id), \ + SRI_ARR(REF_FREQ_TO_PIX_FREQ, HUBPREQ, id), \ + SRI_ARR(VBLANK_PARAMETERS_1, HUBPREQ, id), \ + SRI_ARR(VBLANK_PARAMETERS_3, HUBPREQ, id), \ + SRI_ARR(NOM_PARAMETERS_4, HUBPREQ, id), \ + SRI_ARR(NOM_PARAMETERS_5, HUBPREQ, id), \ + SRI_ARR(PER_LINE_DELIVERY_PRE, HUBPREQ, id), \ + SRI_ARR(PER_LINE_DELIVERY, HUBPREQ, id), \ + SRI_ARR(VBLANK_PARAMETERS_2, HUBPREQ, id), \ + SRI_ARR(VBLANK_PARAMETERS_4, HUBPREQ, id), \ + SRI_ARR(NOM_PARAMETERS_6, HUBPREQ, id), \ + SRI_ARR(NOM_PARAMETERS_7, HUBPREQ, id), \ + SRI_ARR(DCN_TTU_QOS_WM, HUBPREQ, id), \ + SRI_ARR(DCN_GLOBAL_TTU_CNTL, HUBPREQ, id), \ + SRI_ARR(DCN_SURF0_TTU_CNTL0, HUBPREQ, id), \ + SRI_ARR(DCN_SURF0_TTU_CNTL1, HUBPREQ, id), \ + SRI_ARR(DCN_SURF1_TTU_CNTL0, HUBPREQ, id), \ + SRI_ARR(DCN_SURF1_TTU_CNTL1, HUBPREQ, id), \ + SRI_ARR(DCN_CUR0_TTU_CNTL0, HUBPREQ, id), \ + SRI_ARR(DCN_CUR0_TTU_CNTL1, HUBPREQ, id), \ + SRI_ARR(HUBP_CLK_CNTL, HUBP, id) \ + ) + +#define HUBP_REG_LIST_DCN2_COMMON_RI(id) \ + ( \ + HUBP_REG_LIST_DCN_RI(id), HUBP_REG_LIST_DCN_VM_RI(id), \ + SRI_ARR(PREFETCH_SETTINGS, HUBPREQ, id), \ + SRI_ARR(PREFETCH_SETTINGS_C, HUBPREQ, id), \ + SRI_ARR(DCN_VM_SYSTEM_APERTURE_LOW_ADDR, HUBPREQ, id), \ + SRI_ARR(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR, HUBPREQ, id), \ + SRI_ARR(CURSOR_SETTINGS, HUBPREQ, id), \ + SRI_ARR(CURSOR_SURFACE_ADDRESS_HIGH, CURSOR0_, id), \ + SRI_ARR(CURSOR_SURFACE_ADDRESS, CURSOR0_, id), \ + SRI_ARR(CURSOR_SIZE, CURSOR0_, id), \ + SRI_ARR(CURSOR_CONTROL, CURSOR0_, id), \ + SRI_ARR(CURSOR_POSITION, CURSOR0_, id), \ + SRI_ARR(CURSOR_HOT_SPOT, CURSOR0_, id), \ + SRI_ARR(CURSOR_DST_OFFSET, CURSOR0_, id), \ + SRI_ARR(DMDATA_ADDRESS_HIGH, CURSOR0_, id), \ + SRI_ARR(DMDATA_ADDRESS_LOW, CURSOR0_, id), \ + SRI_ARR(DMDATA_CNTL, CURSOR0_, id), \ + SRI_ARR(DMDATA_SW_CNTL, CURSOR0_, id), \ + SRI_ARR(DMDATA_QOS_CNTL, CURSOR0_, id), \ + SRI_ARR(DMDATA_SW_DATA, CURSOR0_, id), \ + SRI_ARR(DMDATA_STATUS, CURSOR0_, id), \ + SRI_ARR(FLIP_PARAMETERS_0, HUBPREQ, id), \ + SRI_ARR(FLIP_PARAMETERS_1, HUBPREQ, id), \ + SRI_ARR(FLIP_PARAMETERS_2, HUBPREQ, id), \ + SRI_ARR(DCN_CUR1_TTU_CNTL0, HUBPREQ, id), \ + SRI_ARR(DCN_CUR1_TTU_CNTL1, HUBPREQ, id), \ + SRI_ARR(DCSURF_FLIP_CONTROL2, HUBPREQ, id), \ + SRI_ARR(VMID_SETTINGS_0, HUBPREQ, id) \ + ) + +#define HUBP_REG_LIST_DCN21_RI(id) \ + ( \ + HUBP_REG_LIST_DCN2_COMMON_RI(id), SRI_ARR(FLIP_PARAMETERS_3, HUBPREQ, id), \ + SRI_ARR(FLIP_PARAMETERS_4, HUBPREQ, id), \ + SRI_ARR(FLIP_PARAMETERS_5, HUBPREQ, id), \ + SRI_ARR(FLIP_PARAMETERS_6, HUBPREQ, id), \ + SRI_ARR(VBLANK_PARAMETERS_5, HUBPREQ, id), \ + SRI_ARR(VBLANK_PARAMETERS_6, HUBPREQ, id) \ + ) + +#define HUBP_REG_LIST_DCN30_RI(id) \ + ( \ + HUBP_REG_LIST_DCN21_RI(id), SRI_ARR(DCN_DMDATA_VM_CNTL, HUBPREQ, id) \ + ) + +#define HUBP_REG_LIST_DCN32_RI(id) \ + ( \ + HUBP_REG_LIST_DCN30_RI(id), SRI_ARR(DCHUBP_MALL_CONFIG, HUBP, id), \ + SRI_ARR(DCHUBP_VMPG_CONFIG, HUBP, id), \ + SRI_ARR(UCLK_PSTATE_FORCE, HUBPREQ, id) \ + ) + +/* HUBBUB */ + +#define HUBBUB_REG_LIST_DCN32_RI(id) \ + ( \ + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A), \ + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B), \ + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C), \ + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D), \ + SR(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL), \ + SR(DCHUBBUB_ARB_DRAM_STATE_CNTL), SR(DCHUBBUB_ARB_SAT_LEVEL), \ + SR(DCHUBBUB_ARB_DF_REQ_OUTSTAND), SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ + SR(DCHUBBUB_SOFT_RESET), SR(DCHUBBUB_CRC_CTRL), \ + SR(DCN_VM_FB_LOCATION_BASE), SR(DCN_VM_FB_LOCATION_TOP), \ + SR(DCN_VM_FB_OFFSET), SR(DCN_VM_AGP_BOT), SR(DCN_VM_AGP_TOP), \ + SR(DCN_VM_AGP_BASE), HUBBUB_SR_WATERMARK_REG_LIST(), \ + SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A), SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B), \ + SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C), SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D), \ + SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A), \ + SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B), \ + SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C), \ + SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D), \ + SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A), \ + SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B), \ + SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C), \ + SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D), SR(DCHUBBUB_DET0_CTRL), \ + SR(DCHUBBUB_DET1_CTRL), SR(DCHUBBUB_DET2_CTRL), SR(DCHUBBUB_DET3_CTRL), \ + SR(DCHUBBUB_COMPBUF_CTRL), SR(COMPBUF_RESERVED_SPACE), \ + SR(DCHUBBUB_DEBUG_CTRL_0), \ + SR(DCHUBBUB_ARB_USR_RETRAINING_CNTL), \ + SR(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A), \ + SR(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B), \ + SR(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C), \ + SR(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D), \ + SR(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A), \ + SR(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B), \ + SR(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C), \ + SR(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D), \ + SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A), \ + SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B), \ + SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C), \ + SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D), \ + SR(DCN_VM_FAULT_ADDR_MSB), SR(DCN_VM_FAULT_ADDR_LSB), \ + SR(DCN_VM_FAULT_CNTL), SR(DCN_VM_FAULT_STATUS) \ + ) + +/* DCCG */ + +#define DCCG_REG_LIST_DCN32_RI() \ + ( \ + SR(DPPCLK_DTO_CTRL), DCCG_SRII(DTO_PARAM, DPPCLK, 0), \ + DCCG_SRII(DTO_PARAM, DPPCLK, 1), DCCG_SRII(DTO_PARAM, DPPCLK, 2), \ + DCCG_SRII(DTO_PARAM, DPPCLK, 3), DCCG_SRII(CLOCK_CNTL, HDMICHARCLK, 0), \ + SR(PHYASYMCLK_CLOCK_CNTL), SR(PHYBSYMCLK_CLOCK_CNTL), \ + SR(PHYCSYMCLK_CLOCK_CNTL), SR(PHYDSYMCLK_CLOCK_CNTL), \ + SR(PHYESYMCLK_CLOCK_CNTL), SR(DPSTREAMCLK_CNTL), SR(HDMISTREAMCLK_CNTL), \ + SR(SYMCLK32_SE_CNTL), SR(SYMCLK32_LE_CNTL), \ + DCCG_SRII(PIXEL_RATE_CNTL, OTG, 0), DCCG_SRII(PIXEL_RATE_CNTL, OTG, 1), \ + DCCG_SRII(PIXEL_RATE_CNTL, OTG, 2), DCCG_SRII(PIXEL_RATE_CNTL, OTG, 3), \ + DCCG_SRII(MODULO, DTBCLK_DTO, 0), DCCG_SRII(MODULO, DTBCLK_DTO, 1), \ + DCCG_SRII(MODULO, DTBCLK_DTO, 2), DCCG_SRII(MODULO, DTBCLK_DTO, 3), \ + DCCG_SRII(PHASE, DTBCLK_DTO, 0), DCCG_SRII(PHASE, DTBCLK_DTO, 1), \ + DCCG_SRII(PHASE, DTBCLK_DTO, 2), DCCG_SRII(PHASE, DTBCLK_DTO, 3), \ + SR(DCCG_AUDIO_DTBCLK_DTO_MODULO), SR(DCCG_AUDIO_DTBCLK_DTO_PHASE), \ + SR(OTG_PIXEL_RATE_DIV), SR(DTBCLK_P_CNTL), SR(DCCG_AUDIO_DTO_SOURCE) \ + ) + +/* VMID */ +#define DCN20_VMID_REG_LIST_RI(id) \ + ( \ + SRI_ARR(CNTL, DCN_VM_CONTEXT, id), \ + SRI_ARR(PAGE_TABLE_BASE_ADDR_HI32, DCN_VM_CONTEXT, id), \ + SRI_ARR(PAGE_TABLE_BASE_ADDR_LO32, DCN_VM_CONTEXT, id), \ + SRI_ARR(PAGE_TABLE_START_ADDR_HI32, DCN_VM_CONTEXT, id), \ + SRI_ARR(PAGE_TABLE_START_ADDR_LO32, DCN_VM_CONTEXT, id), \ + SRI_ARR(PAGE_TABLE_END_ADDR_HI32, DCN_VM_CONTEXT, id), \ + SRI_ARR(PAGE_TABLE_END_ADDR_LO32, DCN_VM_CONTEXT, id) \ + ) + +/* I2C HW */ + +#define I2C_HW_ENGINE_COMMON_REG_LIST_RI(id) \ + ( \ + SRI_ARR_I2C(SETUP, DC_I2C_DDC, id), SRI_ARR_I2C(SPEED, DC_I2C_DDC, id), \ + SRI_ARR_I2C(HW_STATUS, DC_I2C_DDC, id), \ + SR_ARR_I2C(DC_I2C_ARBITRATION, id), \ + SR_ARR_I2C(DC_I2C_CONTROL, id), SR_ARR_I2C(DC_I2C_SW_STATUS, id), \ + SR_ARR_I2C(DC_I2C_TRANSACTION0, id), SR_ARR_I2C(DC_I2C_TRANSACTION1, id),\ + SR_ARR_I2C(DC_I2C_TRANSACTION2, id), SR_ARR_I2C(DC_I2C_TRANSACTION3, id),\ + SR_ARR_I2C(DC_I2C_DATA, id), SR_ARR_I2C(MICROSECOND_TIME_BASE_DIV, id) \ + ) + +#define I2C_HW_ENGINE_COMMON_REG_LIST_DCN30_RI(id) \ + ( \ + I2C_HW_ENGINE_COMMON_REG_LIST_RI(id), SR_ARR_I2C(DIO_MEM_PWR_CTRL, id), \ + SR_ARR_I2C(DIO_MEM_PWR_STATUS, id) \ + ) #endif /* _DCN32_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c index 1f195c5b3377..a2a70a1572b7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c @@ -28,6 +28,11 @@ #include "dcn20/dcn20_resource.h" #include "dml/dcn32/display_mode_vba_util_32.h" +static bool is_dual_plane(enum surface_pixel_format format) +{ + return format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN || format == SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA; +} + /** * ******************************************************************************************** * dcn32_helper_calculate_num_ways_for_subvp: Calculate number of ways needed for SubVP @@ -54,22 +59,27 @@ uint32_t dcn32_helper_calculate_num_ways_for_subvp(struct dc *dc, struct dc_stat uint32_t num_mblks = 0; uint32_t cache_lines_per_plane = 0; uint32_t i = 0, j = 0; - uint32_t mblk_width = 0; - uint32_t mblk_height = 0; + uint16_t mblk_width = 0; + uint16_t mblk_height = 0; uint32_t full_vp_width_blk_aligned = 0; uint32_t full_vp_height_blk_aligned = 0; uint32_t mall_alloc_width_blk_aligned = 0; uint32_t mall_alloc_height_blk_aligned = 0; - uint32_t full_vp_height = 0; + uint16_t full_vp_height = 0; + bool subvp_in_use = false; for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - // Find the phantom pipes - if (pipe->stream && pipe->plane_state && !pipe->top_pipe && !pipe->prev_odm_pipe && + /* Find the phantom pipes. + * - For pipe split case we need to loop through the bottom and next ODM + * pipes or only half the viewport size is counted + */ + if (pipe->stream && pipe->plane_state && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { struct pipe_ctx *main_pipe = NULL; + subvp_in_use = true; /* Get full viewport height from main pipe (required for MBLK calculation) */ for (j = 0; j < dc->res_pool->pipe_count; j++) { main_pipe = &context->res_ctx.pipe_ctx[j]; @@ -116,9 +126,9 @@ uint32_t dcn32_helper_calculate_num_ways_for_subvp(struct dc *dc, struct dc_stat // (MALL is 64-byte aligned) cache_lines_per_plane = bytes_in_mall / dc->caps.cache_line_size + 2; - // For DCC we must cache the meat surface, so double cache lines required + /* For DCC divide by 256 */ if (pipe->plane_state->dcc.enable) - cache_lines_per_plane *= 2; + cache_lines_per_plane = cache_lines_per_plane + (cache_lines_per_plane / 256) + 1; cache_lines_used += cache_lines_per_plane; } } @@ -129,6 +139,9 @@ uint32_t dcn32_helper_calculate_num_ways_for_subvp(struct dc *dc, struct dc_stat if (cache_lines_used % lines_per_way > 0) num_ways++; + if (subvp_in_use && dc->debug.force_subvp_num_ways > 0) + num_ways = dc->debug.force_subvp_num_ways; + return num_ways; } @@ -220,36 +233,133 @@ bool dcn32_mpo_in_use(struct dc_state *context) return false; } -void dcn32_determine_det_override(struct dc_state *context, display_e2e_pipe_params_st *pipes, - bool *is_pipe_split_expected, int pipe_cnt) +/** + * ******************************************************************************************* + * dcn32_determine_det_override: Determine DET allocation for each pipe + * + * This function determines how much DET to allocate for each pipe. The total number of + * DET segments will be split equally among each of the streams, and after that the DET + * segments per stream will be split equally among the planes for the given stream. + * + * If there is a plane that's driven by more than 1 pipe (i.e. pipe split), then the + * number of DET for that given plane will be split among the pipes driving that plane. + * + * + * High level algorithm: + * 1. Split total DET among number of streams + * 2. For each stream, split DET among the planes + * 3. For each plane, check if there is a pipe split. If yes, split the DET allocation + * among those pipes. + * 4. Assign the DET override to the DML pipes. + * + * @param [in]: dc: Current DC state + * @param [in]: context: New DC state to be programmed + * @param [in]: pipes: Array of DML pipes + * + * @return: void + * + * ******************************************************************************************* + */ +void dcn32_determine_det_override(struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes) { - int i, j, count, stream_segments, pipe_segments[MAX_PIPES]; + uint32_t i, j, k; + uint8_t pipe_plane_count, stream_segments, plane_segments, pipe_segments[MAX_PIPES] = {0}; + uint8_t pipe_counted[MAX_PIPES] = {0}; + uint8_t pipe_cnt = 0; + struct dc_plane_state *current_plane = NULL; + uint8_t stream_count = 0; - if (context->stream_count > 0) { - stream_segments = 18 / context->stream_count; + for (i = 0; i < context->stream_count; i++) { + /* Don't count SubVP streams for DET allocation */ + if (context->streams[i]->mall_stream_config.type != SUBVP_PHANTOM) { + stream_count++; + } + } + + if (stream_count > 0) { + stream_segments = 18 / stream_count; for (i = 0; i < context->stream_count; i++) { - count = 0; - for (j = 0; j < pipe_cnt; j++) { - if (context->res_ctx.pipe_ctx[j].stream == context->streams[i]) { - count++; - if (is_pipe_split_expected[j]) - count++; + if (context->streams[i]->mall_stream_config.type == SUBVP_PHANTOM) + continue; + if (context->stream_status[i].plane_count > 0) + plane_segments = stream_segments / context->stream_status[i].plane_count; + else + plane_segments = stream_segments; + for (j = 0; j < dc->res_pool->pipe_count; j++) { + pipe_plane_count = 0; + if (context->res_ctx.pipe_ctx[j].stream == context->streams[i] && + pipe_counted[j] != 1) { + /* Note: pipe_plane_count indicates the number of pipes to be used for a + * given plane. e.g. pipe_plane_count = 1 means single pipe (i.e. not split), + * pipe_plane_count = 2 means 2:1 split, etc. + */ + pipe_plane_count++; + pipe_counted[j] = 1; + current_plane = context->res_ctx.pipe_ctx[j].plane_state; + for (k = 0; k < dc->res_pool->pipe_count; k++) { + if (k != j && context->res_ctx.pipe_ctx[k].stream == context->streams[i] && + context->res_ctx.pipe_ctx[k].plane_state == current_plane) { + pipe_plane_count++; + pipe_counted[k] = 1; + } + } + + pipe_segments[j] = plane_segments / pipe_plane_count; + for (k = 0; k < dc->res_pool->pipe_count; k++) { + if (k != j && context->res_ctx.pipe_ctx[k].stream == context->streams[i] && + context->res_ctx.pipe_ctx[k].plane_state == current_plane) { + pipe_segments[k] = plane_segments / pipe_plane_count; + } + } } } - pipe_segments[i] = stream_segments / count; } - for (i = 0; i < pipe_cnt; i++) { - pipes[i].pipe.src.det_size_override = 0; - for (j = 0; j < context->stream_count; j++) { - if (context->res_ctx.pipe_ctx[i].stream == context->streams[j]) { - pipes[i].pipe.src.det_size_override = pipe_segments[j] * DCN3_2_DET_SEG_SIZE; - break; - } - } + for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { + if (!context->res_ctx.pipe_ctx[i].stream) + continue; + pipes[pipe_cnt].pipe.src.det_size_override = pipe_segments[i] * DCN3_2_DET_SEG_SIZE; + pipe_cnt++; } } else { - for (i = 0; i < pipe_cnt; i++) + for (i = 0; i < dc->res_pool->pipe_count; i++) pipes[i].pipe.src.det_size_override = 4 * DCN3_2_DET_SEG_SIZE; //DCN3_2_DEFAULT_DET_SIZE } } + +void dcn32_set_det_allocations(struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes) +{ + int i, pipe_cnt; + struct resource_context *res_ctx = &context->res_ctx; + struct pipe_ctx *pipe; + + for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { + + if (!res_ctx->pipe_ctx[i].stream) + continue; + + pipe = &res_ctx->pipe_ctx[i]; + pipe_cnt++; + } + + /* For DET allocation, we don't want to use DML policy (not optimal for utilizing all + * the DET available for each pipe). Use the DET override input to maintain our driver + * policy. + */ + if (pipe_cnt == 1) { + pipes[0].pipe.src.det_size_override = DCN3_2_MAX_DET_SIZE; + if (pipe->plane_state && !dc->debug.disable_z9_mpc && pipe->plane_state->tiling_info.gfx9.swizzle != DC_SW_LINEAR) { + if (!is_dual_plane(pipe->plane_state->format)) { + pipes[0].pipe.src.det_size_override = DCN3_2_DEFAULT_DET_SIZE; + pipes[0].pipe.src.unbounded_req_mode = true; + if (pipe->plane_state->src_rect.width >= 5120 && + pipe->plane_state->src_rect.height >= 2880) + pipes[0].pipe.src.det_size_override = 320; // 5K or higher + } + } + } else + dcn32_determine_det_override(dc, context, pipes); +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c index 7309eed33a61..aed0f689cbbf 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c @@ -93,31 +93,6 @@ #include "vm_helper.h" #include "dcn20/dcn20_vmid.h" -#define DCN_BASE__INST0_SEG1 0x000000C0 -#define DCN_BASE__INST0_SEG2 0x000034C0 -#define DCN_BASE__INST0_SEG3 0x00009000 -#define NBIO_BASE__INST0_SEG1 0x00000014 - -#define MAX_INSTANCE 8 -#define MAX_SEGMENT 6 - -struct IP_BASE_INSTANCE { - unsigned int segment[MAX_SEGMENT]; -}; - -struct IP_BASE { - struct IP_BASE_INSTANCE instance[MAX_INSTANCE]; -}; - -static const struct IP_BASE DCN_BASE = { { { { 0x00000012, 0x000000C0, 0x000034C0, 0x00009000, 0x02403C00, 0 } }, - { { 0, 0, 0, 0, 0, 0 } }, - { { 0, 0, 0, 0, 0, 0 } }, - { { 0, 0, 0, 0, 0, 0 } }, - { { 0, 0, 0, 0, 0, 0 } }, - { { 0, 0, 0, 0, 0, 0 } }, - { { 0, 0, 0, 0, 0, 0 } }, - { { 0, 0, 0, 0, 0, 0 } } } }; - #define DC_LOGGER_INIT(logger) #define fixed16_to_double(x) (((double)x) / ((double) (1 << 16))) #define fixed16_to_double_to_cpu(x) fixed16_to_double(le32_to_cpu(x)) @@ -138,78 +113,102 @@ enum dcn321_clk_src_array_id { /* DCN */ /* TODO awful hack. fixup dcn20_dwb.h */ #undef BASE_INNER -#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg +#define BASE_INNER(seg) ctx->dcn_reg_offsets[seg] #define BASE(seg) BASE_INNER(seg) #define SR(reg_name)\ - .reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ - reg ## reg_name + REG_STRUCT.reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ + reg ## reg_name +#define SR_ARR(reg_name, id)\ + REG_STRUCT[id].reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ + reg ## reg_name +#define SR_ARR_INIT(reg_name, id, value)\ + REG_STRUCT[id].reg_name = value #define SRI(reg_name, block, id)\ - .reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name + REG_STRUCT.reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRI_ARR(reg_name, block, id)\ + REG_STRUCT[id].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SR_ARR_I2C(reg_name, id) \ + REG_STRUCT[id-1].reg_name = BASE(reg##reg_name##_BASE_IDX) + reg##reg_name + +#define SRI_ARR_I2C(reg_name, block, id)\ + REG_STRUCT[id-1].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRI_ARR_ALPHABET(reg_name, block, index, id)\ + REG_STRUCT[index].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name #define SRI2(reg_name, block, id)\ .reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ - reg ## reg_name + reg ## reg_name +#define SRI2_ARR(reg_name, block, id)\ + REG_STRUCT[id].reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ + reg ## reg_name #define SRIR(var_name, reg_name, block, id)\ .var_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name + reg ## block ## id ## _ ## reg_name #define SRII(reg_name, block, id)\ - .reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name + REG_STRUCT.reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRII_ARR_2(reg_name, block, id, inst)\ + REG_STRUCT[inst].reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name #define SRII_MPC_RMU(reg_name, block, id)\ .RMU##_##reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name + reg ## block ## id ## _ ## reg_name #define SRII_DWB(reg_name, temp_name, block, id)\ - .reg_name[id] = BASE(reg ## block ## id ## _ ## temp_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## temp_name + REG_STRUCT.reg_name[id] = BASE(reg ## block ## id ## _ ## temp_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## temp_name #define DCCG_SRII(reg_name, block, id)\ - .block ## _ ## reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name + REG_STRUCT.block ## _ ## reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name #define VUPDATE_SRII(reg_name, block, id)\ - .reg_name[id] = BASE(reg ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ - reg ## reg_name ## _ ## block ## id + REG_STRUCT.reg_name[id] = BASE(reg ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ + reg ## reg_name ## _ ## block ## id /* NBIO */ -#define NBIO_BASE_INNER(seg) \ - NBIO_BASE__INST0_SEG ## seg +#define NBIO_BASE_INNER(seg) ctx->nbio_reg_offsets[seg] #define NBIO_BASE(seg) \ NBIO_BASE_INNER(seg) #define NBIO_SR(reg_name)\ - .reg_name = NBIO_BASE(regBIF_BX0_ ## reg_name ## _BASE_IDX) + \ - regBIF_BX0_ ## reg_name + REG_STRUCT.reg_name = NBIO_BASE(regBIF_BX0_ ## reg_name ## _BASE_IDX) + \ + regBIF_BX0_ ## reg_name +#define NBIO_SR_ARR(reg_name, id)\ + REG_STRUCT[id].reg_name = NBIO_BASE(regBIF_BX0_ ## reg_name ## _BASE_IDX) + \ + regBIF_BX0_ ## reg_name #define CTX ctx #define REG(reg_name) \ - (DCN_BASE.instance[0].segment[reg ## reg_name ## _BASE_IDX] + reg ## reg_name) + (ctx->dcn_reg_offsets[reg ## reg_name ## _BASE_IDX] + reg ## reg_name) -static const struct bios_registers bios_regs = { - NBIO_SR(BIOS_SCRATCH_3), - NBIO_SR(BIOS_SCRATCH_6) -}; +static struct bios_registers bios_regs; -#define clk_src_regs(index, pllid)\ -[index] = {\ - CS_COMMON_REG_LIST_DCN3_0(index, pllid),\ -} +#define bios_regs_init() \ + ( \ + NBIO_SR(BIOS_SCRATCH_3),\ + NBIO_SR(BIOS_SCRATCH_6)\ + ) -static const struct dce110_clk_src_regs clk_src_regs[] = { - clk_src_regs(0, A), - clk_src_regs(1, B), - clk_src_regs(2, C), - clk_src_regs(3, D), - clk_src_regs(4, E) -}; +#define clk_src_regs_init(index, pllid)\ + CS_COMMON_REG_LIST_DCN3_0_RI(index, pllid) + +static struct dce110_clk_src_regs clk_src_regs[5]; static const struct dce110_clk_src_shift cs_shift = { CS_COMMON_MASK_SH_LIST_DCN3_2(__SHIFT) @@ -219,17 +218,10 @@ static const struct dce110_clk_src_mask cs_mask = { CS_COMMON_MASK_SH_LIST_DCN3_2(_MASK) }; -#define abm_regs(id)\ -[id] = {\ - ABM_DCN32_REG_LIST(id)\ -} +#define abm_regs_init(id)\ + ABM_DCN32_REG_LIST_RI(id) -static const struct dce_abm_registers abm_regs[] = { - abm_regs(0), - abm_regs(1), - abm_regs(2), - abm_regs(3), -}; +static struct dce_abm_registers abm_regs[4]; static const struct dce_abm_shift abm_shift = { ABM_MASK_SH_LIST_DCN32(__SHIFT) @@ -239,18 +231,10 @@ static const struct dce_abm_mask abm_mask = { ABM_MASK_SH_LIST_DCN32(_MASK) }; -#define audio_regs(id)\ -[id] = {\ - AUD_COMMON_REG_LIST(id)\ -} +#define audio_regs_init(id)\ + AUD_COMMON_REG_LIST_RI(id) -static const struct dce_audio_registers audio_regs[] = { - audio_regs(0), - audio_regs(1), - audio_regs(2), - audio_regs(3), - audio_regs(4) -}; +static struct dce_audio_registers audio_regs[5]; #define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ @@ -265,23 +249,10 @@ static const struct dce_audio_mask audio_mask = { DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) }; -#define vpg_regs(id)\ -[id] = {\ - VPG_DCN3_REG_LIST(id)\ -} +#define vpg_regs_init(id)\ + VPG_DCN3_REG_LIST_RI(id) -static const struct dcn30_vpg_registers vpg_regs[] = { - vpg_regs(0), - vpg_regs(1), - vpg_regs(2), - vpg_regs(3), - vpg_regs(4), - vpg_regs(5), - vpg_regs(6), - vpg_regs(7), - vpg_regs(8), - vpg_regs(9), -}; +static struct dcn30_vpg_registers vpg_regs[10]; static const struct dcn30_vpg_shift vpg_shift = { DCN3_VPG_MASK_SH_LIST(__SHIFT) @@ -291,19 +262,10 @@ static const struct dcn30_vpg_mask vpg_mask = { DCN3_VPG_MASK_SH_LIST(_MASK) }; -#define afmt_regs(id)\ -[id] = {\ - AFMT_DCN3_REG_LIST(id)\ -} +#define afmt_regs_init(id)\ + AFMT_DCN3_REG_LIST_RI(id) -static const struct dcn30_afmt_registers afmt_regs[] = { - afmt_regs(0), - afmt_regs(1), - afmt_regs(2), - afmt_regs(3), - afmt_regs(4), - afmt_regs(5) -}; +static struct dcn30_afmt_registers afmt_regs[6]; static const struct dcn30_afmt_shift afmt_shift = { DCN3_AFMT_MASK_SH_LIST(__SHIFT) @@ -313,17 +275,10 @@ static const struct dcn30_afmt_mask afmt_mask = { DCN3_AFMT_MASK_SH_LIST(_MASK) }; -#define apg_regs(id)\ -[id] = {\ - APG_DCN31_REG_LIST(id)\ -} +#define apg_regs_init(id)\ + APG_DCN31_REG_LIST_RI(id) -static const struct dcn31_apg_registers apg_regs[] = { - apg_regs(0), - apg_regs(1), - apg_regs(2), - apg_regs(3) -}; +static struct dcn31_apg_registers apg_regs[4]; static const struct dcn31_apg_shift apg_shift = { DCN31_APG_MASK_SH_LIST(__SHIFT) @@ -333,18 +288,10 @@ static const struct dcn31_apg_mask apg_mask = { DCN31_APG_MASK_SH_LIST(_MASK) }; -#define stream_enc_regs(id)\ -[id] = {\ - SE_DCN32_REG_LIST(id)\ -} +#define stream_enc_regs_init(id)\ + SE_DCN32_REG_LIST_RI(id) -static const struct dcn10_stream_enc_registers stream_enc_regs[] = { - stream_enc_regs(0), - stream_enc_regs(1), - stream_enc_regs(2), - stream_enc_regs(3), - stream_enc_regs(4) -}; +static struct dcn10_stream_enc_registers stream_enc_regs[5]; static const struct dcn10_stream_encoder_shift se_shift = { SE_COMMON_MASK_SH_LIST_DCN32(__SHIFT) @@ -355,46 +302,24 @@ static const struct dcn10_stream_encoder_mask se_mask = { }; -#define aux_regs(id)\ -[id] = {\ - DCN2_AUX_REG_LIST(id)\ -} +#define aux_regs_init(id)\ + DCN2_AUX_REG_LIST_RI(id) -static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = { - aux_regs(0), - aux_regs(1), - aux_regs(2), - aux_regs(3), - aux_regs(4) -}; +static struct dcn10_link_enc_aux_registers link_enc_aux_regs[5]; -#define hpd_regs(id)\ -[id] = {\ - HPD_REG_LIST(id)\ -} +#define hpd_regs_init(id)\ + HPD_REG_LIST_RI(id) -static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { - hpd_regs(0), - hpd_regs(1), - hpd_regs(2), - hpd_regs(3), - hpd_regs(4) -}; +static struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[5]; -#define link_regs(id, phyid)\ -[id] = {\ - LE_DCN31_REG_LIST(id), \ - UNIPHY_DCN2_REG_LIST(phyid), \ +#define link_regs_init(id, phyid)\ + ( \ + LE_DCN31_REG_LIST_RI(id), \ + UNIPHY_DCN2_REG_LIST_RI(id, phyid)\ + ) /*DPCS_DCN31_REG_LIST(id),*/ \ -} -static const struct dcn10_link_enc_registers link_enc_regs[] = { - link_regs(0, A), - link_regs(1, B), - link_regs(2, C), - link_regs(3, D), - link_regs(4, E) -}; +static struct dcn10_link_enc_registers link_enc_regs[5]; static const struct dcn10_link_enc_shift le_shift = { LINK_ENCODER_MASK_SH_LIST_DCN31(__SHIFT), \ @@ -406,17 +331,10 @@ static const struct dcn10_link_enc_mask le_mask = { // DPCS_DCN31_MASK_SH_LIST(_MASK) }; -#define hpo_dp_stream_encoder_reg_list(id)\ -[id] = {\ - DCN3_1_HPO_DP_STREAM_ENC_REG_LIST(id)\ -} +#define hpo_dp_stream_encoder_reg_init(id)\ + DCN3_1_HPO_DP_STREAM_ENC_REG_LIST_RI(id) -static const struct dcn31_hpo_dp_stream_encoder_registers hpo_dp_stream_enc_regs[] = { - hpo_dp_stream_encoder_reg_list(0), - hpo_dp_stream_encoder_reg_list(1), - hpo_dp_stream_encoder_reg_list(2), - hpo_dp_stream_encoder_reg_list(3), -}; +static struct dcn31_hpo_dp_stream_encoder_registers hpo_dp_stream_enc_regs[4]; static const struct dcn31_hpo_dp_stream_encoder_shift hpo_dp_se_shift = { DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(__SHIFT) @@ -427,20 +345,14 @@ static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { }; -#define hpo_dp_link_encoder_reg_list(id)\ -[id] = {\ - DCN3_1_HPO_DP_LINK_ENC_REG_LIST(id),\ - /*DCN3_1_RDPCSTX_REG_LIST(0),*/\ - /*DCN3_1_RDPCSTX_REG_LIST(1),*/\ - /*DCN3_1_RDPCSTX_REG_LIST(2),*/\ - /*DCN3_1_RDPCSTX_REG_LIST(3),*/\ - /*DCN3_1_RDPCSTX_REG_LIST(4)*/\ -} +#define hpo_dp_link_encoder_reg_init(id)\ + DCN3_1_HPO_DP_LINK_ENC_REG_LIST_RI(id) + /*DCN3_1_RDPCSTX_REG_LIST(0),*/ + /*DCN3_1_RDPCSTX_REG_LIST(1),*/ + /*DCN3_1_RDPCSTX_REG_LIST(2),*/ + /*DCN3_1_RDPCSTX_REG_LIST(3),*/ -static const struct dcn31_hpo_dp_link_encoder_registers hpo_dp_link_enc_regs[] = { - hpo_dp_link_encoder_reg_list(0), - hpo_dp_link_encoder_reg_list(1), -}; +static struct dcn31_hpo_dp_link_encoder_registers hpo_dp_link_enc_regs[2]; static const struct dcn31_hpo_dp_link_encoder_shift hpo_dp_le_shift = { DCN3_2_HPO_DP_LINK_ENC_MASK_SH_LIST(__SHIFT) @@ -450,17 +362,10 @@ static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { DCN3_2_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK) }; -#define dpp_regs(id)\ -[id] = {\ - DPP_REG_LIST_DCN30_COMMON(id),\ -} +#define dpp_regs_init(id)\ + DPP_REG_LIST_DCN30_COMMON_RI(id) -static const struct dcn3_dpp_registers dpp_regs[] = { - dpp_regs(0), - dpp_regs(1), - dpp_regs(2), - dpp_regs(3) -}; +static struct dcn3_dpp_registers dpp_regs[4]; static const struct dcn3_dpp_shift tf_shift = { DPP_REG_LIST_SH_MASK_DCN30_COMMON(__SHIFT) @@ -471,17 +376,10 @@ static const struct dcn3_dpp_mask tf_mask = { }; -#define opp_regs(id)\ -[id] = {\ - OPP_REG_LIST_DCN30(id),\ -} +#define opp_regs_init(id)\ + OPP_REG_LIST_DCN30_RI(id) -static const struct dcn20_opp_registers opp_regs[] = { - opp_regs(0), - opp_regs(1), - opp_regs(2), - opp_regs(3) -}; +static struct dcn20_opp_registers opp_regs[4]; static const struct dcn20_opp_shift opp_shift = { OPP_MASK_SH_LIST_DCN20(__SHIFT) @@ -491,21 +389,15 @@ static const struct dcn20_opp_mask opp_mask = { OPP_MASK_SH_LIST_DCN20(_MASK) }; -#define aux_engine_regs(id)\ -[id] = {\ - AUX_COMMON_REG_LIST0(id), \ - .AUXN_IMPCAL = 0, \ - .AUXP_IMPCAL = 0, \ - .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK, \ -} +#define aux_engine_regs_init(id) \ + ( \ + AUX_COMMON_REG_LIST0_RI(id), SR_ARR_INIT(AUXN_IMPCAL, id, 0), \ + SR_ARR_INIT(AUXP_IMPCAL, id, 0), \ + SR_ARR_INIT(AUX_RESET_MASK, id, DP_AUX0_AUX_CONTROL__AUX_RESET_MASK), \ + SR_ARR_INIT(AUX_RESET_MASK, id, DP_AUX0_AUX_CONTROL__AUX_RESET_MASK)\ + ) -static const struct dce110_aux_registers aux_engine_regs[] = { - aux_engine_regs(0), - aux_engine_regs(1), - aux_engine_regs(2), - aux_engine_regs(3), - aux_engine_regs(4) -}; +static struct dce110_aux_registers aux_engine_regs[5]; static const struct dce110_aux_registers_shift aux_shift = { DCN_AUX_MASK_SH_LIST(__SHIFT) @@ -515,15 +407,10 @@ static const struct dce110_aux_registers_mask aux_mask = { DCN_AUX_MASK_SH_LIST(_MASK) }; +#define dwbc_regs_dcn3_init(id)\ + DWBC_COMMON_REG_LIST_DCN30_RI(id) -#define dwbc_regs_dcn3(id)\ -[id] = {\ - DWBC_COMMON_REG_LIST_DCN30(id),\ -} - -static const struct dcn30_dwbc_registers dwbc30_regs[] = { - dwbc_regs_dcn3(0), -}; +static struct dcn30_dwbc_registers dwbc30_regs[1]; static const struct dcn30_dwbc_shift dwbc30_shift = { DWBC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) @@ -533,14 +420,10 @@ static const struct dcn30_dwbc_mask dwbc30_mask = { DWBC_COMMON_MASK_SH_LIST_DCN30(_MASK) }; -#define mcif_wb_regs_dcn3(id)\ -[id] = {\ - MCIF_WB_COMMON_REG_LIST_DCN32(id),\ -} +#define mcif_wb_regs_dcn3_init(id)\ + MCIF_WB_COMMON_REG_LIST_DCN32_RI(id) -static const struct dcn30_mmhubbub_registers mcif_wb30_regs[] = { - mcif_wb_regs_dcn3(0) -}; +static struct dcn30_mmhubbub_registers mcif_wb30_regs[1]; static const struct dcn30_mmhubbub_shift mcif_wb30_shift = { MCIF_WB_COMMON_MASK_SH_LIST_DCN32(__SHIFT) @@ -550,17 +433,10 @@ static const struct dcn30_mmhubbub_mask mcif_wb30_mask = { MCIF_WB_COMMON_MASK_SH_LIST_DCN32(_MASK) }; -#define dsc_regsDCN20(id)\ -[id] = {\ - DSC_REG_LIST_DCN20(id)\ -} +#define dsc_regsDCN20_init(id)\ + DSC_REG_LIST_DCN20_RI(id) -static const struct dcn20_dsc_registers dsc_regs[] = { - dsc_regsDCN20(0), - dsc_regsDCN20(1), - dsc_regsDCN20(2), - dsc_regsDCN20(3) -}; +static struct dcn20_dsc_registers dsc_regs[4]; static const struct dcn20_dsc_shift dsc_shift = { DSC_REG_LIST_SH_MASK_DCN20(__SHIFT) @@ -570,17 +446,17 @@ static const struct dcn20_dsc_mask dsc_mask = { DSC_REG_LIST_SH_MASK_DCN20(_MASK) }; -static const struct dcn30_mpc_registers mpc_regs = { - MPC_REG_LIST_DCN3_2(0), - MPC_REG_LIST_DCN3_2(1), - MPC_REG_LIST_DCN3_2(2), - MPC_REG_LIST_DCN3_2(3), - MPC_OUT_MUX_REG_LIST_DCN3_0(0), - MPC_OUT_MUX_REG_LIST_DCN3_0(1), - MPC_OUT_MUX_REG_LIST_DCN3_0(2), - MPC_OUT_MUX_REG_LIST_DCN3_0(3), - MPC_DWB_MUX_REG_LIST_DCN3_0(0), -}; +static struct dcn30_mpc_registers mpc_regs; +#define dcn_mpc_regs_init()\ + MPC_REG_LIST_DCN3_2_RI(0),\ + MPC_REG_LIST_DCN3_2_RI(1),\ + MPC_REG_LIST_DCN3_2_RI(2),\ + MPC_REG_LIST_DCN3_2_RI(3),\ + MPC_OUT_MUX_REG_LIST_DCN3_0_RI(0),\ + MPC_OUT_MUX_REG_LIST_DCN3_0_RI(1),\ + MPC_OUT_MUX_REG_LIST_DCN3_0_RI(2),\ + MPC_OUT_MUX_REG_LIST_DCN3_0_RI(3),\ + MPC_DWB_MUX_REG_LIST_DCN3_0_RI(0) static const struct dcn30_mpc_shift mpc_shift = { MPC_COMMON_MASK_SH_LIST_DCN32(__SHIFT) @@ -590,15 +466,10 @@ static const struct dcn30_mpc_mask mpc_mask = { MPC_COMMON_MASK_SH_LIST_DCN32(_MASK) }; -#define optc_regs(id)\ -[id] = {OPTC_COMMON_REG_LIST_DCN3_2(id)} +#define optc_regs_init(id)\ + OPTC_COMMON_REG_LIST_DCN3_2_RI(id) -static const struct dcn_optc_registers optc_regs[] = { - optc_regs(0), - optc_regs(1), - optc_regs(2), - optc_regs(3) -}; +static struct dcn_optc_registers optc_regs[4]; static const struct dcn_optc_shift optc_shift = { OPTC_COMMON_MASK_SH_LIST_DCN3_2(__SHIFT) @@ -608,18 +479,10 @@ static const struct dcn_optc_mask optc_mask = { OPTC_COMMON_MASK_SH_LIST_DCN3_2(_MASK) }; -#define hubp_regs(id)\ -[id] = {\ - HUBP_REG_LIST_DCN32(id)\ -} - -static const struct dcn_hubp2_registers hubp_regs[] = { - hubp_regs(0), - hubp_regs(1), - hubp_regs(2), - hubp_regs(3) -}; +#define hubp_regs_init(id) \ + HUBP_REG_LIST_DCN32_RI(id) +static struct dcn_hubp2_registers hubp_regs[4]; static const struct dcn_hubp2_shift hubp_shift = { HUBP_MASK_SH_LIST_DCN32(__SHIFT) @@ -628,9 +491,10 @@ static const struct dcn_hubp2_shift hubp_shift = { static const struct dcn_hubp2_mask hubp_mask = { HUBP_MASK_SH_LIST_DCN32(_MASK) }; -static const struct dcn_hubbub_registers hubbub_reg = { - HUBBUB_REG_LIST_DCN32(0) -}; + +static struct dcn_hubbub_registers hubbub_reg; +#define hubbub_reg_init()\ + HUBBUB_REG_LIST_DCN32_RI(0) static const struct dcn_hubbub_shift hubbub_shift = { HUBBUB_MASK_SH_LIST_DCN32(__SHIFT) @@ -640,9 +504,10 @@ static const struct dcn_hubbub_mask hubbub_mask = { HUBBUB_MASK_SH_LIST_DCN32(_MASK) }; -static const struct dccg_registers dccg_regs = { - DCCG_REG_LIST_DCN32() -}; +static struct dccg_registers dccg_regs; + +#define dccg_regs_init()\ + DCCG_REG_LIST_DCN32_RI() static const struct dccg_shift dccg_shift = { DCCG_MASK_SH_LIST_DCN32(__SHIFT) @@ -715,9 +580,10 @@ static const struct dccg_mask dccg_mask = { SR(AZALIA_AUDIO_DTO), \ SR(AZALIA_CONTROLLER_CLOCK_GATING) -static const struct dce_hwseq_registers hwseq_reg = { - HWSEQ_DCN32_REG_LIST() -}; +static struct dce_hwseq_registers hwseq_reg; + +#define hwseq_reg_init()\ + HWSEQ_DCN32_REG_LIST() #define HWSEQ_DCN32_MASK_SH_LIST(mask_sh)\ HWSEQ_DCN_MASK_SH_LIST(mask_sh), \ @@ -760,29 +626,10 @@ static const struct dce_hwseq_shift hwseq_shift = { static const struct dce_hwseq_mask hwseq_mask = { HWSEQ_DCN32_MASK_SH_LIST(_MASK) }; -#define vmid_regs(id)\ -[id] = {\ - DCN20_VMID_REG_LIST(id)\ -} +#define vmid_regs_init(id)\ + DCN20_VMID_REG_LIST_RI(id) -static const struct dcn_vmid_registers vmid_regs[] = { - vmid_regs(0), - vmid_regs(1), - vmid_regs(2), - vmid_regs(3), - vmid_regs(4), - vmid_regs(5), - vmid_regs(6), - vmid_regs(7), - vmid_regs(8), - vmid_regs(9), - vmid_regs(10), - vmid_regs(11), - vmid_regs(12), - vmid_regs(13), - vmid_regs(14), - vmid_regs(15) -}; +static struct dcn_vmid_registers vmid_regs[16]; static const struct dcn20_vmid_shift vmid_shifts = { DCN20_VMID_MASK_SH_LIST(__SHIFT) @@ -871,8 +718,12 @@ static const struct dc_debug_options debug_defaults_drv = { .force_disable_subvp = false, .exit_idle_opt_for_cursor_updates = true, .enable_single_display_2to1_odm_policy = true, + + /*must match enable_single_display_2to1_odm_policy to support dynamic ODM transitions*/ + .enable_double_buffered_dsc_pg_support = true, .enable_dp_dig_pixel_rate_div_policy = 1, .allow_sw_cursor_fallback = false, + .alloc_extra_way_for_cursor = true, }; static const struct dc_debug_options debug_defaults_diags = { @@ -906,6 +757,14 @@ static struct dce_aux *dcn321_aux_engine_create( if (!aux_engine) return NULL; +#undef REG_STRUCT +#define REG_STRUCT aux_engine_regs + aux_engine_regs_init(0), + aux_engine_regs_init(1), + aux_engine_regs_init(2), + aux_engine_regs_init(3), + aux_engine_regs_init(4); + dce110_aux_engine_construct(aux_engine, ctx, inst, SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, &aux_engine_regs[inst], @@ -915,15 +774,10 @@ static struct dce_aux *dcn321_aux_engine_create( return &aux_engine->base; } -#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST_DCN30(id) } - -static const struct dce_i2c_registers i2c_hw_regs[] = { - i2c_inst_regs(1), - i2c_inst_regs(2), - i2c_inst_regs(3), - i2c_inst_regs(4), - i2c_inst_regs(5), -}; +#define i2c_inst_regs_init(id)\ + I2C_HW_ENGINE_COMMON_REG_LIST_DCN30_RI(id) + +static struct dce_i2c_registers i2c_hw_regs[5]; static const struct dce_i2c_shift i2c_shifts = { I2C_COMMON_MASK_SH_LIST_DCN30(__SHIFT) @@ -943,6 +797,14 @@ static struct dce_i2c_hw *dcn321_i2c_hw_create( if (!dce_i2c_hw) return NULL; +#undef REG_STRUCT +#define REG_STRUCT i2c_hw_regs + i2c_inst_regs_init(1), + i2c_inst_regs_init(2), + i2c_inst_regs_init(3), + i2c_inst_regs_init(4), + i2c_inst_regs_init(5); + dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); @@ -982,6 +844,29 @@ static struct hubbub *dcn321_hubbub_create(struct dc_context *ctx) if (!hubbub2) return NULL; +#undef REG_STRUCT +#define REG_STRUCT hubbub_reg + hubbub_reg_init(); + +#undef REG_STRUCT +#define REG_STRUCT vmid_regs + vmid_regs_init(0), + vmid_regs_init(1), + vmid_regs_init(2), + vmid_regs_init(3), + vmid_regs_init(4), + vmid_regs_init(5), + vmid_regs_init(6), + vmid_regs_init(7), + vmid_regs_init(8), + vmid_regs_init(9), + vmid_regs_init(10), + vmid_regs_init(11), + vmid_regs_init(12), + vmid_regs_init(13), + vmid_regs_init(14), + vmid_regs_init(15); + hubbub32_construct(hubbub2, ctx, &hubbub_reg, &hubbub_shift, @@ -1014,6 +899,13 @@ static struct hubp *dcn321_hubp_create( if (!hubp2) return NULL; +#undef REG_STRUCT +#define REG_STRUCT hubp_regs + hubp_regs_init(0), + hubp_regs_init(1), + hubp_regs_init(2), + hubp_regs_init(3); + if (hubp32_construct(hubp2, ctx, inst, &hubp_regs[inst], &hubp_shift, &hubp_mask)) return &hubp2->base; @@ -1039,6 +931,13 @@ static struct dpp *dcn321_dpp_create( if (!dpp3) return NULL; +#undef REG_STRUCT +#define REG_STRUCT dpp_regs + dpp_regs_init(0), + dpp_regs_init(1), + dpp_regs_init(2), + dpp_regs_init(3); + if (dpp32_construct(dpp3, ctx, inst, &dpp_regs[inst], &tf_shift, &tf_mask)) return &dpp3->base; @@ -1059,6 +958,10 @@ static struct mpc *dcn321_mpc_create( if (!mpc30) return NULL; +#undef REG_STRUCT +#define REG_STRUCT mpc_regs + dcn_mpc_regs_init(); + dcn32_mpc_construct(mpc30, ctx, &mpc_regs, &mpc_shift, @@ -1080,6 +983,13 @@ static struct output_pixel_processor *dcn321_opp_create( return NULL; } +#undef REG_STRUCT +#define REG_STRUCT opp_regs + opp_regs_init(0), + opp_regs_init(1), + opp_regs_init(2), + opp_regs_init(3); + dcn20_opp_construct(opp2, ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); return &opp2->base; @@ -1096,6 +1006,13 @@ static struct timing_generator *dcn321_timing_generator_create( if (!tgn10) return NULL; +#undef REG_STRUCT +#define REG_STRUCT optc_regs + optc_regs_init(0), + optc_regs_init(1), + optc_regs_init(2), + optc_regs_init(3); + tgn10->base.inst = instance; tgn10->base.ctx = ctx; @@ -1130,6 +1047,30 @@ static struct link_encoder *dcn321_link_encoder_create( if (!enc20) return NULL; +#undef REG_STRUCT +#define REG_STRUCT link_enc_aux_regs + aux_regs_init(0), + aux_regs_init(1), + aux_regs_init(2), + aux_regs_init(3), + aux_regs_init(4); + +#undef REG_STRUCT +#define REG_STRUCT link_enc_hpd_regs + hpd_regs_init(0), + hpd_regs_init(1), + hpd_regs_init(2), + hpd_regs_init(3), + hpd_regs_init(4); + +#undef REG_STRUCT +#define REG_STRUCT link_enc_regs + link_regs_init(0, A), + link_regs_init(1, B), + link_regs_init(2, C), + link_regs_init(3, D), + link_regs_init(4, E); + dcn321_link_encoder_construct(enc20, enc_init_data, &link_enc_feature, @@ -1146,7 +1087,7 @@ static void read_dce_straps( struct dc_context *ctx, struct resource_straps *straps) { - generic_reg_get(ctx, regDC_PINSTRAPS + BASE(regDC_PINSTRAPS_BASE_IDX), + generic_reg_get(ctx, ctx->dcn_reg_offsets[regDC_PINSTRAPS_BASE_IDX] + regDC_PINSTRAPS, FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); } @@ -1154,6 +1095,15 @@ static void read_dce_straps( static struct audio *dcn321_create_audio( struct dc_context *ctx, unsigned int inst) { + +#undef REG_STRUCT +#define REG_STRUCT audio_regs + audio_regs_init(0), + audio_regs_init(1), + audio_regs_init(2), + audio_regs_init(3), + audio_regs_init(4); + return dce_audio_create(ctx, inst, &audio_regs[inst], &audio_shift, &audio_mask); } @@ -1167,6 +1117,19 @@ static struct vpg *dcn321_vpg_create( if (!vpg3) return NULL; +#undef REG_STRUCT +#define REG_STRUCT vpg_regs + vpg_regs_init(0), + vpg_regs_init(1), + vpg_regs_init(2), + vpg_regs_init(3), + vpg_regs_init(4), + vpg_regs_init(5), + vpg_regs_init(6), + vpg_regs_init(7), + vpg_regs_init(8), + vpg_regs_init(9); + vpg3_construct(vpg3, ctx, inst, &vpg_regs[inst], &vpg_shift, @@ -1184,6 +1147,15 @@ static struct afmt *dcn321_afmt_create( if (!afmt3) return NULL; +#undef REG_STRUCT +#define REG_STRUCT afmt_regs + afmt_regs_init(0), + afmt_regs_init(1), + afmt_regs_init(2), + afmt_regs_init(3), + afmt_regs_init(4), + afmt_regs_init(5); + afmt3_construct(afmt3, ctx, inst, &afmt_regs[inst], &afmt_shift, @@ -1201,6 +1173,13 @@ static struct apg *dcn321_apg_create( if (!apg31) return NULL; +#undef REG_STRUCT +#define REG_STRUCT apg_regs + apg_regs_init(0), + apg_regs_init(1), + apg_regs_init(2), + apg_regs_init(3); + apg31_construct(apg31, ctx, inst, &apg_regs[inst], &apg_shift, @@ -1237,6 +1216,14 @@ static struct stream_encoder *dcn321_stream_encoder_create( return NULL; } +#undef REG_STRUCT +#define REG_STRUCT stream_enc_regs + stream_enc_regs_init(0), + stream_enc_regs_init(1), + stream_enc_regs_init(2), + stream_enc_regs_init(3), + stream_enc_regs_init(4); + dcn32_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, eng_id, vpg, afmt, &stream_enc_regs[eng_id], @@ -1287,6 +1274,13 @@ static struct hpo_dp_stream_encoder *dcn321_hpo_dp_stream_encoder_create( return NULL; } +#undef REG_STRUCT +#define REG_STRUCT hpo_dp_stream_enc_regs + hpo_dp_stream_encoder_reg_init(0), + hpo_dp_stream_encoder_reg_init(1), + hpo_dp_stream_encoder_reg_init(2), + hpo_dp_stream_encoder_reg_init(3); + dcn31_hpo_dp_stream_encoder_construct(hpo_dp_enc31, ctx, ctx->dc_bios, hpo_dp_inst, eng_id, vpg, apg, &hpo_dp_stream_enc_regs[hpo_dp_inst], @@ -1304,6 +1298,11 @@ static struct hpo_dp_link_encoder *dcn321_hpo_dp_link_encoder_create( /* allocate HPO link encoder */ hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL); +#undef REG_STRUCT +#define REG_STRUCT hpo_dp_link_enc_regs + hpo_dp_link_encoder_reg_init(0), + hpo_dp_link_encoder_reg_init(1); + hpo_dp_link_encoder32_construct(hpo_dp_enc31, ctx, inst, &hpo_dp_link_enc_regs[inst], &hpo_dp_le_shift, &hpo_dp_le_mask); @@ -1316,6 +1315,10 @@ static struct dce_hwseq *dcn321_hwseq_create( { struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); +#undef REG_STRUCT +#define REG_STRUCT hwseq_reg + hwseq_reg_init(); + if (hws) { hws->ctx = ctx; hws->regs = &hwseq_reg; @@ -1506,6 +1509,10 @@ static bool dcn321_dwbc_create(struct dc_context *ctx, struct resource_pool *poo return false; } +#undef REG_STRUCT +#define REG_STRUCT dwbc30_regs + dwbc_regs_dcn3_init(0); + dcn30_dwbc_construct(dwbc30, ctx, &dwbc30_regs[i], &dwbc30_shift, @@ -1531,6 +1538,10 @@ static bool dcn321_mmhubbub_create(struct dc_context *ctx, struct resource_pool return false; } +#undef REG_STRUCT +#define REG_STRUCT mcif_wb30_regs + mcif_wb_regs_dcn3_init(0); + dcn32_mmhubbub_construct(mcif_wb30, ctx, &mcif_wb30_regs[i], &mcif_wb30_shift, @@ -1553,6 +1564,13 @@ static struct display_stream_compressor *dcn321_dsc_create( return NULL; } +#undef REG_STRUCT +#define REG_STRUCT dsc_regs + dsc_regsDCN20_init(0), + dsc_regsDCN20_init(1), + dsc_regsDCN20_init(2), + dsc_regsDCN20_init(3); + dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask); dsc->max_image_width = 6016; @@ -1617,6 +1635,30 @@ static bool dcn321_resource_construct( uint32_t pipe_fuses = 0; uint32_t num_pipes = 4; +#undef REG_STRUCT +#define REG_STRUCT bios_regs + bios_regs_init(); + +#undef REG_STRUCT +#define REG_STRUCT clk_src_regs + clk_src_regs_init(0, A), + clk_src_regs_init(1, B), + clk_src_regs_init(2, C), + clk_src_regs_init(3, D), + clk_src_regs_init(4, E); + +#undef REG_STRUCT +#define REG_STRUCT abm_regs + abm_regs_init(0), + abm_regs_init(1), + abm_regs_init(2), + abm_regs_init(3); + +#undef REG_STRUCT +#define REG_STRUCT dccg_regs + dccg_regs_init(); + + ctx->dc_bios->regs = &bios_regs; pool->base.res_cap = &res_cap_dcn321; diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h index fb6a2d7b6470..e3e5c39895a3 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h @@ -33,7 +33,7 @@ #include "dc_types.h" #include "dc.h" -struct dp_mst_stream_allocation_table; +struct dc_dp_mst_stream_allocation_table; struct aux_payload; enum aux_return_code_type; @@ -77,7 +77,7 @@ void dm_helpers_dp_update_branch_info( bool dm_helpers_dp_mst_write_payload_allocation_table( struct dc_context *ctx, const struct dc_stream_state *stream, - struct dp_mst_stream_allocation_table *proposed_table, + struct dc_dp_mst_stream_allocation_table *proposed_table, bool enable); /* @@ -171,7 +171,13 @@ void dm_helpers_smu_timeout(struct dc_context *ctx, unsigned int msg_id, unsigne // 0x1 = Result_OK, 0xFE = Result_UnkmownCmd, 0x0 = Status_Busy #define IS_SMU_TIMEOUT(result) \ (result == 0x0) - +void dm_helpers_init_panel_settings( + struct dc_context *ctx, + struct dc_panel_config *config, + struct dc_sink *sink); +void dm_helpers_override_panel_settings( + struct dc_context *ctx, + struct dc_panel_config *config); int dm_helper_dmub_aux_transfer_sync( struct dc_context *ctx, const struct dc_link *link, diff --git a/drivers/gpu/drm/amd/display/dc/dml/calcs/bw_fixed.c b/drivers/gpu/drm/amd/display/dc/dml/calcs/bw_fixed.c index 6ca288fb5fb9..3aa8dd0acd5e 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/calcs/bw_fixed.c +++ b/drivers/gpu/drm/amd/display/dc/dml/calcs/bw_fixed.c @@ -25,12 +25,11 @@ #include "dm_services.h" #include "bw_fixed.h" +#define MAX_I64 \ + ((int64_t)((1ULL << 63) - 1)) #define MIN_I64 \ - (int64_t)(-(1LL << 63)) - -#define MAX_I64 \ - (int64_t)((1ULL << 63) - 1) + (-MAX_I64 - 1) #define FRACTIONAL_PART_MASK \ ((1ULL << BW_FIXED_BITS_PER_FRACTIONAL_PART) - 1) @@ -49,6 +48,7 @@ static uint64_t abs_i64(int64_t arg) struct bw_fixed bw_int_to_fixed_nonconst(int64_t value) { struct bw_fixed res; + ASSERT(value < BW_FIXED_MAX_I32 && value > BW_FIXED_MIN_I32); res.value = value << BW_FIXED_BITS_PER_FRACTIONAL_PART; return res; @@ -78,14 +78,12 @@ struct bw_fixed bw_frc_to_fixed(int64_t numerator, int64_t denominator) { uint32_t i = BW_FIXED_BITS_PER_FRACTIONAL_PART; - do - { + do { remainder <<= 1; res_value <<= 1; - if (remainder >= arg2_value) - { + if (remainder >= arg2_value) { res_value |= 1; remainder -= arg2_value; } diff --git a/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calc_auto.c b/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calc_auto.c index 41284e263325..288d22a16cf2 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calc_auto.c +++ b/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calc_auto.c @@ -526,10 +526,10 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) } if (v->max_swath_height_c[k] > 0.0) { v->swath_width_granularity_c = 256.0 /dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / v->max_swath_height_c[k]; - } - v->rounded_up_max_swath_size_bytes_c = (dcn_bw_ceil2(v->swath_width_yper_state[i][j][k] / 2.0 - 1.0, v->swath_width_granularity_c) + v->swath_width_granularity_c) * v->byte_per_pixel_in_detc[k] * v->max_swath_height_c[k]; - if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_10) { - v->rounded_up_max_swath_size_bytes_c =dcn_bw_ceil2(v->rounded_up_max_swath_size_bytes_c, 256.0) + 256; + v->rounded_up_max_swath_size_bytes_c = (dcn_bw_ceil2(v->swath_width_yper_state[i][j][k] / 2.0 - 1.0, v->swath_width_granularity_c) + v->swath_width_granularity_c) * v->byte_per_pixel_in_detc[k] * v->max_swath_height_c[k]; + if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_10) { + v->rounded_up_max_swath_size_bytes_c = dcn_bw_ceil2(v->rounded_up_max_swath_size_bytes_c, 256.0) + 256; + } } if (v->rounded_up_max_swath_size_bytes_y + v->rounded_up_max_swath_size_bytes_c <= v->det_buffer_size_in_kbyte * 1024.0 / 2.0) { v->swath_height_yper_state[i][j][k] = v->max_swath_height_y[k]; @@ -552,14 +552,14 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) v->lines_in_det_chroma = v->det_buffer_size_in_kbyte * 1024.0 / 3.0 / v->byte_per_pixel_in_dety[k] / (v->swath_width_yper_state[i][j][k] / 2.0); } v->effective_lb_latency_hiding_source_lines_luma =dcn_bw_min2(v->max_line_buffer_lines,dcn_bw_floor2(v->line_buffer_size / v->lb_bit_per_pixel[k] / (v->swath_width_yper_state[i][j][k] /dcn_bw_max2(v->h_ratio[k], 1.0)), 1.0)) - (v->vtaps[k] - 1.0); - v->effective_lb_latency_hiding_source_lines_chroma =dcn_bw_min2(v->max_line_buffer_lines,dcn_bw_floor2(v->line_buffer_size / v->lb_bit_per_pixel[k] / (v->swath_width_yper_state[i][j][k] / 2.0 /dcn_bw_max2(v->h_ratio[k] / 2.0, 1.0)), 1.0)) - (v->vta_pschroma[k] - 1.0); v->effective_detlb_lines_luma =dcn_bw_floor2(v->lines_in_det_luma +dcn_bw_min2(v->lines_in_det_luma * v->required_dispclk[i][j] * v->byte_per_pixel_in_dety[k] * v->pscl_factor[k] / v->return_bw_per_state[i], v->effective_lb_latency_hiding_source_lines_luma), v->swath_height_yper_state[i][j][k]); - v->effective_detlb_lines_chroma =dcn_bw_floor2(v->lines_in_det_chroma +dcn_bw_min2(v->lines_in_det_chroma * v->required_dispclk[i][j] * v->byte_per_pixel_in_detc[k] * v->pscl_factor_chroma[k] / v->return_bw_per_state[i], v->effective_lb_latency_hiding_source_lines_chroma), v->swath_height_cper_state[i][j][k]); if (v->byte_per_pixel_in_detc[k] == 0.0) { v->urgent_latency_support_us_per_state[i][j][k] = v->effective_detlb_lines_luma * (v->htotal[k] / v->pixel_clock[k]) / v->v_ratio[k] - v->effective_detlb_lines_luma * v->swath_width_yper_state[i][j][k] *dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) / (v->return_bw_per_state[i] / v->no_of_dpp[i][j][k]); } else { - v->urgent_latency_support_us_per_state[i][j][k] =dcn_bw_min2(v->effective_detlb_lines_luma * (v->htotal[k] / v->pixel_clock[k]) / v->v_ratio[k] - v->effective_detlb_lines_luma * v->swath_width_yper_state[i][j][k] *dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) / (v->return_bw_per_state[i] / v->no_of_dpp[i][j][k]), v->effective_detlb_lines_chroma * (v->htotal[k] / v->pixel_clock[k]) / (v->v_ratio[k] / 2.0) - v->effective_detlb_lines_chroma * v->swath_width_yper_state[i][j][k] / 2.0 *dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / (v->return_bw_per_state[i] / v->no_of_dpp[i][j][k])); + v->effective_lb_latency_hiding_source_lines_chroma = dcn_bw_min2(v->max_line_buffer_lines, dcn_bw_floor2(v->line_buffer_size / v->lb_bit_per_pixel[k] / (v->swath_width_yper_state[i][j][k] / 2.0 / dcn_bw_max2(v->h_ratio[k] / 2.0, 1.0)), 1.0)) - (v->vta_pschroma[k] - 1.0); + v->effective_detlb_lines_chroma = dcn_bw_floor2(v->lines_in_det_chroma + dcn_bw_min2(v->lines_in_det_chroma * v->required_dispclk[i][j] * v->byte_per_pixel_in_detc[k] * v->pscl_factor_chroma[k] / v->return_bw_per_state[i], v->effective_lb_latency_hiding_source_lines_chroma), v->swath_height_cper_state[i][j][k]); + v->urgent_latency_support_us_per_state[i][j][k] = dcn_bw_min2(v->effective_detlb_lines_luma * (v->htotal[k] / v->pixel_clock[k]) / v->v_ratio[k] - v->effective_detlb_lines_luma * v->swath_width_yper_state[i][j][k] * dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) / (v->return_bw_per_state[i] / v->no_of_dpp[i][j][k]), v->effective_detlb_lines_chroma * (v->htotal[k] / v->pixel_clock[k]) / (v->v_ratio[k] / 2.0) - v->effective_detlb_lines_chroma * v->swath_width_yper_state[i][j][k] / 2.0 * dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / (v->return_bw_per_state[i] / v->no_of_dpp[i][j][k])); } } } @@ -1146,10 +1146,10 @@ void display_pipe_configuration(struct dcn_bw_internal_vars *v) } if (v->maximum_swath_height_c > 0.0) { v->swath_width_granularity_c = 256.0 /dcn_bw_ceil2(v->byte_per_pix_detc, 2.0) / v->maximum_swath_height_c; - } - v->rounded_up_max_swath_size_bytes_c = (dcn_bw_ceil2(v->swath_width / 2.0 - 1.0, v->swath_width_granularity_c) + v->swath_width_granularity_c) * v->byte_per_pix_detc * v->maximum_swath_height_c; - if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_10) { - v->rounded_up_max_swath_size_bytes_c =dcn_bw_ceil2(v->rounded_up_max_swath_size_bytes_c, 256.0) + 256; + v->rounded_up_max_swath_size_bytes_c = (dcn_bw_ceil2(v->swath_width / 2.0 - 1.0, v->swath_width_granularity_c) + v->swath_width_granularity_c) * v->byte_per_pix_detc * v->maximum_swath_height_c; + if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_10) { + v->rounded_up_max_swath_size_bytes_c = dcn_bw_ceil2(v->rounded_up_max_swath_size_bytes_c, 256.0) + 256; + } } if (v->rounded_up_max_swath_size_bytes_y + v->rounded_up_max_swath_size_bytes_c <= v->det_buffer_size_in_kbyte * 1024.0 / 2.0) { v->swath_height_y[k] = v->maximum_swath_height_y; diff --git a/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calc_math.c b/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calc_math.c index 07d18e78de49..cac72413a097 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calc_math.c +++ b/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calc_math.c @@ -23,6 +23,7 @@ * */ +#include "os_types.h" #include "dcn_calc_math.h" #define isNaN(number) ((number) != (number)) @@ -69,8 +70,8 @@ float dcn_bw_max2(const float arg1, const float arg2) float dcn_bw_floor2(const float arg, const float significance) { - if (significance == 0) - return 0; + ASSERT(significance != 0); + return ((int) (arg / significance)) * significance; } float dcn_bw_floor(const float arg) @@ -80,17 +81,14 @@ float dcn_bw_floor(const float arg) float dcn_bw_ceil(const float arg) { - float flr = dcn_bw_floor2(arg, 1); - - return flr + 0.00001 >= arg ? arg : flr + 1; + return (int) (arg + 0.99999); } float dcn_bw_ceil2(const float arg, const float significance) { - float flr = dcn_bw_floor2(arg, significance); - if (significance == 0) - return 0; - return flr + 0.00001 >= arg ? arg : flr + significance; + ASSERT(significance != 0); + + return ((int) (arg / significance + 0.99999)) * significance; } float dcn_bw_max3(float v1, float v2, float v3) diff --git a/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c index db3b16b77034..d46adc849d2a 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c @@ -736,30 +736,13 @@ static void hack_bounding_box(struct dcn_bw_internal_vars *v, hack_force_pipe_split(v, context->streams[0]->timing.pix_clk_100hz); } -static unsigned int get_highest_allowed_voltage_level(uint32_t chip_family, - uint32_t hw_internal_rev, - uint32_t pci_revision_id) +static unsigned int get_highest_allowed_voltage_level(bool is_vmin_only_asic) { /* for low power RV2 variants, the highest voltage level we want is 0 */ - if ((chip_family == FAMILY_RV) && - ASICREV_IS_RAVEN2(hw_internal_rev)) - switch (pci_revision_id) { - case PRID_DALI_DE: - case PRID_DALI_DF: - case PRID_DALI_E3: - case PRID_DALI_E4: - case PRID_POLLOCK_94: - case PRID_POLLOCK_95: - case PRID_POLLOCK_E9: - case PRID_POLLOCK_EA: - case PRID_POLLOCK_EB: - return 0; - default: - break; - } - - /* we are ok with all levels */ - return 4; + if (is_vmin_only_asic) + return 0; + else /* we are ok with all levels */ + return 4; } bool dcn_validate_bandwidth( @@ -1323,10 +1306,7 @@ bool dcn_validate_bandwidth( PERFORMANCE_TRACE_END(); BW_VAL_TRACE_FINISH(); - if (bw_limit_pass && v->voltage_level <= get_highest_allowed_voltage_level( - dc->ctx->asic_id.chip_family, - dc->ctx->asic_id.hw_internal_rev, - dc->ctx->asic_id.pci_revision_id)) + if (bw_limit_pass && v->voltage_level <= get_highest_allowed_voltage_level(dc->config.is_vmin_only_asic)) return true; else return false; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c index d34e0f1314d9..d680f1c5b69f 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c @@ -2234,6 +2234,7 @@ static struct _vcs_dpi_voltage_scaling_st construct_low_pstate_lvl(struct clk_li void dcn21_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) { + struct _vcs_dpi_voltage_scaling_st *s = dc->scratch.update_bw_bounding_box.clock_limits; struct dcn21_resource_pool *pool = TO_DCN21_RES_POOL(dc->res_pool); struct clk_limit_table *clk_table = &bw_params->clk_table; unsigned int i, closest_clk_lvl = 0, k = 0; @@ -2247,8 +2248,7 @@ void dcn21_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params ASSERT(clk_table->num_entries); /* Copy dcn2_1_soc.clock_limits to clock_limits to avoid copying over null states later */ - memcpy(&dcn2_1_soc._clock_tmp, &dcn2_1_soc.clock_limits, - sizeof(dcn2_1_soc.clock_limits)); + memcpy(s, dcn2_1_soc.clock_limits, sizeof(dcn2_1_soc.clock_limits)); for (i = 0; i < clk_table->num_entries; i++) { /* loop backwards*/ @@ -2263,25 +2263,25 @@ void dcn21_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params if (i == 1) k++; - dcn2_1_soc._clock_tmp[k].state = k; - dcn2_1_soc._clock_tmp[k].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz; - dcn2_1_soc._clock_tmp[k].fabricclk_mhz = clk_table->entries[i].fclk_mhz; - dcn2_1_soc._clock_tmp[k].socclk_mhz = clk_table->entries[i].socclk_mhz; - dcn2_1_soc._clock_tmp[k].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2; - - dcn2_1_soc._clock_tmp[k].dispclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dispclk_mhz; - dcn2_1_soc._clock_tmp[k].dppclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dppclk_mhz; - dcn2_1_soc._clock_tmp[k].dram_bw_per_chan_gbps = dcn2_1_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps; - dcn2_1_soc._clock_tmp[k].dscclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dscclk_mhz; - dcn2_1_soc._clock_tmp[k].dtbclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dtbclk_mhz; - dcn2_1_soc._clock_tmp[k].phyclk_d18_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz; - dcn2_1_soc._clock_tmp[k].phyclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].phyclk_mhz; + s[k].state = k; + s[k].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz; + s[k].fabricclk_mhz = clk_table->entries[i].fclk_mhz; + s[k].socclk_mhz = clk_table->entries[i].socclk_mhz; + s[k].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2; + + s[k].dispclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dispclk_mhz; + s[k].dppclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dppclk_mhz; + s[k].dram_bw_per_chan_gbps = + dcn2_1_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps; + s[k].dscclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dscclk_mhz; + s[k].dtbclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].dtbclk_mhz; + s[k].phyclk_d18_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz; + s[k].phyclk_mhz = dcn2_1_soc.clock_limits[closest_clk_lvl].phyclk_mhz; k++; } - memcpy(&dcn2_1_soc.clock_limits, &dcn2_1_soc._clock_tmp, - sizeof(dcn2_1_soc.clock_limits)); + memcpy(dcn2_1_soc.clock_limits, s, sizeof(dcn2_1_soc.clock_limits)); if (clk_table->num_entries) { dcn2_1_soc.num_states = clk_table->num_entries + 1; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c index 63bbdf8b8678..edd098c7eb92 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c @@ -4478,17 +4478,17 @@ void dml20v2_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode locals->EffectiveLBLatencyHidingSourceLinesLuma), locals->SwathHeightYPerState[i][j][k]); - locals->EffectiveDETLBLinesChroma = dml_floor(locals->LinesInDETChroma + dml_min( - locals->LinesInDETChroma * locals->RequiredDISPCLK[i][j] * locals->BytePerPixelInDETC[k] * - locals->PSCL_FACTOR_CHROMA[k] / locals->ReturnBWPerState[i][0], - locals->EffectiveLBLatencyHidingSourceLinesChroma), - locals->SwathHeightCPerState[i][j][k]); if (locals->BytePerPixelInDETC[k] == 0) { locals->UrgentLatencySupportUsPerState[i][j][k] = locals->EffectiveDETLBLinesLuma * (locals->HTotal[k] / locals->PixelClock[k]) / locals->VRatio[k] - locals->EffectiveDETLBLinesLuma * locals->SwathWidthYPerState[i][j][k] * dml_ceil(locals->BytePerPixelInDETY[k], 1) / (locals->ReturnBWPerState[i][0] / locals->NoOfDPP[i][j][k]); } else { + locals->EffectiveDETLBLinesChroma = dml_floor(locals->LinesInDETChroma + dml_min( + locals->LinesInDETChroma * locals->RequiredDISPCLK[i][j] * locals->BytePerPixelInDETC[k] * + locals->PSCL_FACTOR_CHROMA[k] / locals->ReturnBWPerState[i][0], + locals->EffectiveLBLatencyHidingSourceLinesChroma), + locals->SwathHeightCPerState[i][j][k]); locals->UrgentLatencySupportUsPerState[i][j][k] = dml_min( locals->EffectiveDETLBLinesLuma * (locals->HTotal[k] / locals->PixelClock[k]) / locals->VRatio[k] - locals->EffectiveDETLBLinesLuma * locals->SwathWidthYPerState[i][j][k] * diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c index 8a7485e21d53..1d84ae50311d 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c @@ -806,10 +806,12 @@ static bool CalculatePrefetchSchedule( if (myPipe->SourceScan == dm_horz) { *swath_width_luma_ub = dml_ceil(SwathWidthY - 1, myPipe->BlockWidth256BytesY) + myPipe->BlockWidth256BytesY; - *swath_width_chroma_ub = dml_ceil(SwathWidthY / 2 - 1, myPipe->BlockWidth256BytesC) + myPipe->BlockWidth256BytesC; + if (myPipe->BlockWidth256BytesC > 0) + *swath_width_chroma_ub = dml_ceil(SwathWidthY / 2 - 1, myPipe->BlockWidth256BytesC) + myPipe->BlockWidth256BytesC; } else { *swath_width_luma_ub = dml_ceil(SwathWidthY - 1, myPipe->BlockHeight256BytesY) + myPipe->BlockHeight256BytesY; - *swath_width_chroma_ub = dml_ceil(SwathWidthY / 2 - 1, myPipe->BlockHeight256BytesC) + myPipe->BlockHeight256BytesC; + if (myPipe->BlockWidth256BytesC > 0) + *swath_width_chroma_ub = dml_ceil(SwathWidthY / 2 - 1, myPipe->BlockHeight256BytesC) + myPipe->BlockHeight256BytesC; } prefetch_bw_oto = (PrefetchSourceLinesY * *swath_width_luma_ub * dml_ceil(BytePerPixelDETY, 1) + PrefetchSourceLinesC * *swath_width_chroma_ub * dml_ceil(BytePerPixelDETC, 2)) / Tsw_oto; @@ -2634,7 +2636,7 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman &mode_lib->vba.SrcActiveDrainRate, &mode_lib->vba.TInitXFill, &mode_lib->vba.TslvChk); - locals->XFCRemoteSurfaceFlipLatency[k] = + locals->XFCRemoteSurfaceFlipLatency[k] = dml_floor( mode_lib->vba.XFCRemoteSurfaceFlipDelay / (mode_lib->vba.HTotal[k] diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c index 1cb858dd6ea0..479e2c1a1301 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c @@ -396,64 +396,10 @@ static void CalculateUrgentBurstFactor( static void UseMinimumDCFCLK( struct display_mode_lib *mode_lib, - int MaxInterDCNTileRepeaters, + struct vba_vars_st *v, int MaxPrefetchMode, - double FinalDRAMClockChangeLatency, - double SREnterPlusExitTime, - int ReturnBusWidth, - int RoundTripPingLatencyCycles, - int ReorderingBytes, - int PixelChunkSizeInKByte, - int MetaChunkSize, - bool GPUVMEnable, - int GPUVMMaxPageTableLevels, - bool HostVMEnable, - int NumberOfActivePlanes, - double HostVMMinPageSize, - int HostVMMaxNonCachedPageTableLevels, - bool DynamicMetadataVMEnabled, - enum immediate_flip_requirement ImmediateFlipRequirement, - bool ProgressiveToInterlaceUnitInOPP, - double MaxAveragePercentOfIdealSDPPortBWDisplayCanUseInNormalSystemOperation, - double PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelMixedWithVMData, - double PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyVMDataOnly, - double PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelDataOnly, - int VTotal[], - int VActive[], - int DynamicMetadataTransmittedBytes[], - int DynamicMetadataLinesBeforeActiveRequired[], - bool Interlace[], - double RequiredDPPCLK[][2][DC__NUM_DPP__MAX], - double RequiredDISPCLK[][2], - double UrgLatency[], - unsigned int NoOfDPP[][2][DC__NUM_DPP__MAX], - double ProjectedDCFCLKDeepSleep[][2], - double MaximumVStartup[][2][DC__NUM_DPP__MAX], - double TotalVActivePixelBandwidth[][2], - double TotalVActiveCursorBandwidth[][2], - double TotalMetaRowBandwidth[][2], - double TotalDPTERowBandwidth[][2], - unsigned int TotalNumberOfActiveDPP[][2], - unsigned int TotalNumberOfDCCActiveDPP[][2], - int dpte_group_bytes[], - double PrefetchLinesY[][2][DC__NUM_DPP__MAX], - double PrefetchLinesC[][2][DC__NUM_DPP__MAX], - unsigned int swath_width_luma_ub_all_states[][2][DC__NUM_DPP__MAX], - unsigned int swath_width_chroma_ub_all_states[][2][DC__NUM_DPP__MAX], - int BytePerPixelY[], - int BytePerPixelC[], - int HTotal[], - double PixelClock[], - double PDEAndMetaPTEBytesPerFrame[][2][DC__NUM_DPP__MAX], - double DPTEBytesPerRow[][2][DC__NUM_DPP__MAX], - double MetaRowBytes[][2][DC__NUM_DPP__MAX], - bool DynamicMetadataEnable[], - double VActivePixelBandwidth[][2][DC__NUM_DPP__MAX], - double VActiveCursorBandwidth[][2][DC__NUM_DPP__MAX], - double ReadBandwidthLuma[], - double ReadBandwidthChroma[], - double DCFCLKPerState[], - double DCFCLKState[][2]); + int ReorderingBytes); + static void CalculatePixelDeliveryTimes( unsigned int NumberOfActivePlanes, double VRatio[], @@ -4692,66 +4638,7 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l } if (v->UseMinimumRequiredDCFCLK == true) { - UseMinimumDCFCLK( - mode_lib, - v->MaxInterDCNTileRepeaters, - MaxPrefetchMode, - v->FinalDRAMClockChangeLatency, - v->SREnterPlusExitTime, - v->ReturnBusWidth, - v->RoundTripPingLatencyCycles, - ReorderingBytes, - v->PixelChunkSizeInKByte, - v->MetaChunkSize, - v->GPUVMEnable, - v->GPUVMMaxPageTableLevels, - v->HostVMEnable, - v->NumberOfActivePlanes, - v->HostVMMinPageSize, - v->HostVMMaxNonCachedPageTableLevels, - v->DynamicMetadataVMEnabled, - v->ImmediateFlipRequirement[0], - v->ProgressiveToInterlaceUnitInOPP, - v->MaxAveragePercentOfIdealSDPPortBWDisplayCanUseInNormalSystemOperation, - v->PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelMixedWithVMData, - v->PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyVMDataOnly, - v->PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelDataOnly, - v->VTotal, - v->VActive, - v->DynamicMetadataTransmittedBytes, - v->DynamicMetadataLinesBeforeActiveRequired, - v->Interlace, - v->RequiredDPPCLK, - v->RequiredDISPCLK, - v->UrgLatency, - v->NoOfDPP, - v->ProjectedDCFCLKDeepSleep, - v->MaximumVStartup, - v->TotalVActivePixelBandwidth, - v->TotalVActiveCursorBandwidth, - v->TotalMetaRowBandwidth, - v->TotalDPTERowBandwidth, - v->TotalNumberOfActiveDPP, - v->TotalNumberOfDCCActiveDPP, - v->dpte_group_bytes, - v->PrefetchLinesY, - v->PrefetchLinesC, - v->swath_width_luma_ub_all_states, - v->swath_width_chroma_ub_all_states, - v->BytePerPixelY, - v->BytePerPixelC, - v->HTotal, - v->PixelClock, - v->PDEAndMetaPTEBytesPerFrame, - v->DPTEBytesPerRow, - v->MetaRowBytes, - v->DynamicMetadataEnable, - v->VActivePixelBandwidth, - v->VActiveCursorBandwidth, - v->ReadBandwidthLuma, - v->ReadBandwidthChroma, - v->DCFCLKPerState, - v->DCFCLKState); + UseMinimumDCFCLK(mode_lib, v, MaxPrefetchMode, ReorderingBytes); if (v->ClampMinDCFCLK) { /* Clamp calculated values to actual minimum */ @@ -6435,10 +6322,6 @@ static void CalculateSwathWidth( for (k = 0; k < NumberOfActivePlanes; ++k) { enum odm_combine_mode MainPlaneODMCombine = 0; - surface_width_ub_l = dml_ceil(SurfaceWidthY[k], Read256BytesBlockWidthY[k]); - surface_height_ub_l = dml_ceil(SurfaceHeightY[k], Read256BytesBlockHeightY[k]); - surface_width_ub_c = dml_ceil(SurfaceWidthC[k], Read256BytesBlockWidthC[k]); - surface_height_ub_c = dml_ceil(SurfaceHeightC[k], Read256BytesBlockHeightC[k]); if (SourceScan[k] != dm_vert) { SwathWidthSingleDPPY[k] = ViewportWidth[k]; @@ -6478,8 +6361,6 @@ static void CalculateSwathWidth( surface_width_ub_l = dml_ceil(SurfaceWidthY[k], Read256BytesBlockWidthY[k]); surface_height_ub_l = dml_ceil(SurfaceHeightY[k], Read256BytesBlockHeightY[k]); - surface_width_ub_c = dml_ceil(SurfaceWidthC[k], Read256BytesBlockWidthC[k]); - surface_height_ub_c = dml_ceil(SurfaceHeightC[k], Read256BytesBlockHeightC[k]); if (SourceScan[k] != dm_vert) { MaximumSwathHeightY[k] = Read256BytesBlockHeightY[k]; @@ -6487,6 +6368,7 @@ static void CalculateSwathWidth( swath_width_luma_ub[k] = dml_min(surface_width_ub_l, (long) dml_ceil(SwathWidthY[k] - 1, Read256BytesBlockWidthY[k]) + Read256BytesBlockWidthY[k]); if (BytePerPixC[k] > 0) { + surface_width_ub_c = dml_ceil(SurfaceWidthC[k], Read256BytesBlockWidthC[k]); swath_width_chroma_ub[k] = dml_min(surface_width_ub_c, (long) dml_ceil(SwathWidthC[k] - 1, Read256BytesBlockWidthC[k]) + Read256BytesBlockWidthC[k]); } else { @@ -6498,6 +6380,7 @@ static void CalculateSwathWidth( swath_width_luma_ub[k] = dml_min(surface_height_ub_l, (long) dml_ceil(SwathWidthY[k] - 1, Read256BytesBlockHeightY[k]) + Read256BytesBlockHeightY[k]); if (BytePerPixC[k] > 0) { + surface_height_ub_c = dml_ceil(SurfaceHeightC[k], Read256BytesBlockHeightC[k]); swath_width_chroma_ub[k] = dml_min(surface_height_ub_c, (long) dml_ceil(SwathWidthC[k] - 1, Read256BytesBlockHeightC[k]) + Read256BytesBlockHeightC[k]); } else { @@ -6612,74 +6495,19 @@ static double CalculateUrgentLatency( static noinline_for_stack void UseMinimumDCFCLK( struct display_mode_lib *mode_lib, - int MaxInterDCNTileRepeaters, + struct vba_vars_st *v, int MaxPrefetchMode, - double FinalDRAMClockChangeLatency, - double SREnterPlusExitTime, - int ReturnBusWidth, - int RoundTripPingLatencyCycles, - int ReorderingBytes, - int PixelChunkSizeInKByte, - int MetaChunkSize, - bool GPUVMEnable, - int GPUVMMaxPageTableLevels, - bool HostVMEnable, - int NumberOfActivePlanes, - double HostVMMinPageSize, - int HostVMMaxNonCachedPageTableLevels, - bool DynamicMetadataVMEnabled, - enum immediate_flip_requirement ImmediateFlipRequirement, - bool ProgressiveToInterlaceUnitInOPP, - double MaxAveragePercentOfIdealSDPPortBWDisplayCanUseInNormalSystemOperation, - double PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelMixedWithVMData, - double PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyVMDataOnly, - double PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelDataOnly, - int VTotal[], - int VActive[], - int DynamicMetadataTransmittedBytes[], - int DynamicMetadataLinesBeforeActiveRequired[], - bool Interlace[], - double RequiredDPPCLK[][2][DC__NUM_DPP__MAX], - double RequiredDISPCLK[][2], - double UrgLatency[], - unsigned int NoOfDPP[][2][DC__NUM_DPP__MAX], - double ProjectedDCFCLKDeepSleep[][2], - double MaximumVStartup[][2][DC__NUM_DPP__MAX], - double TotalVActivePixelBandwidth[][2], - double TotalVActiveCursorBandwidth[][2], - double TotalMetaRowBandwidth[][2], - double TotalDPTERowBandwidth[][2], - unsigned int TotalNumberOfActiveDPP[][2], - unsigned int TotalNumberOfDCCActiveDPP[][2], - int dpte_group_bytes[], - double PrefetchLinesY[][2][DC__NUM_DPP__MAX], - double PrefetchLinesC[][2][DC__NUM_DPP__MAX], - unsigned int swath_width_luma_ub_all_states[][2][DC__NUM_DPP__MAX], - unsigned int swath_width_chroma_ub_all_states[][2][DC__NUM_DPP__MAX], - int BytePerPixelY[], - int BytePerPixelC[], - int HTotal[], - double PixelClock[], - double PDEAndMetaPTEBytesPerFrame[][2][DC__NUM_DPP__MAX], - double DPTEBytesPerRow[][2][DC__NUM_DPP__MAX], - double MetaRowBytes[][2][DC__NUM_DPP__MAX], - bool DynamicMetadataEnable[], - double VActivePixelBandwidth[][2][DC__NUM_DPP__MAX], - double VActiveCursorBandwidth[][2][DC__NUM_DPP__MAX], - double ReadBandwidthLuma[], - double ReadBandwidthChroma[], - double DCFCLKPerState[], - double DCFCLKState[][2]) + int ReorderingBytes) { double NormalEfficiency = 0; double PTEEfficiency = 0; double TotalMaxPrefetchFlipDPTERowBandwidth[DC__VOLTAGE_STATES][2] = { { 0 } }; unsigned int i, j, k; - NormalEfficiency = (HostVMEnable == true ? PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelMixedWithVMData - : PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelDataOnly) / 100.0; - PTEEfficiency = (HostVMEnable == true ? PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyVMDataOnly - / PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelMixedWithVMData : 1.0); + NormalEfficiency = (v->HostVMEnable == true ? v->PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelMixedWithVMData + : v->PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelDataOnly) / 100.0; + PTEEfficiency = (v->HostVMEnable == true ? v->PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyVMDataOnly + / v->PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelMixedWithVMData : 1.0); for (i = 0; i < mode_lib->soc.num_states; ++i) { for (j = 0; j <= 1; ++j) { double PixelDCFCLKCyclesRequiredInPrefetch[DC__NUM_DPP__MAX] = { 0 }; @@ -6697,58 +6525,58 @@ static noinline_for_stack void UseMinimumDCFCLK( double MinimumTvmPlus2Tr0 = 0; TotalMaxPrefetchFlipDPTERowBandwidth[i][j] = 0; - for (k = 0; k < NumberOfActivePlanes; ++k) { + for (k = 0; k < v->NumberOfActivePlanes; ++k) { TotalMaxPrefetchFlipDPTERowBandwidth[i][j] = TotalMaxPrefetchFlipDPTERowBandwidth[i][j] - + NoOfDPP[i][j][k] * DPTEBytesPerRow[i][j][k] / (15.75 * HTotal[k] / PixelClock[k]); + + v->NoOfDPP[i][j][k] * v->DPTEBytesPerRow[i][j][k] / (15.75 * v->HTotal[k] / v->PixelClock[k]); } - for (k = 0; k <= NumberOfActivePlanes - 1; ++k) { - NoOfDPPState[k] = NoOfDPP[i][j][k]; + for (k = 0; k <= v->NumberOfActivePlanes - 1; ++k) { + NoOfDPPState[k] = v->NoOfDPP[i][j][k]; } - MinimumTWait = CalculateTWait(MaxPrefetchMode, FinalDRAMClockChangeLatency, UrgLatency[i], SREnterPlusExitTime); - NonDPTEBandwidth = TotalVActivePixelBandwidth[i][j] + TotalVActiveCursorBandwidth[i][j] + TotalMetaRowBandwidth[i][j]; - DPTEBandwidth = (HostVMEnable == true || ImmediateFlipRequirement == dm_immediate_flip_required) ? - TotalMaxPrefetchFlipDPTERowBandwidth[i][j] : TotalDPTERowBandwidth[i][j]; - DCFCLKRequiredForAverageBandwidth = dml_max3(ProjectedDCFCLKDeepSleep[i][j], - (NonDPTEBandwidth + TotalDPTERowBandwidth[i][j]) / ReturnBusWidth / (MaxAveragePercentOfIdealSDPPortBWDisplayCanUseInNormalSystemOperation / 100), - (NonDPTEBandwidth + DPTEBandwidth / PTEEfficiency) / NormalEfficiency / ReturnBusWidth); - - ExtraLatencyBytes = CalculateExtraLatencyBytes(ReorderingBytes, TotalNumberOfActiveDPP[i][j], PixelChunkSizeInKByte, TotalNumberOfDCCActiveDPP[i][j], - MetaChunkSize, GPUVMEnable, HostVMEnable, NumberOfActivePlanes, NoOfDPPState, dpte_group_bytes, - PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelMixedWithVMData, PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyVMDataOnly, - HostVMMinPageSize, HostVMMaxNonCachedPageTableLevels); - ExtraLatencyCycles = RoundTripPingLatencyCycles + 32 + ExtraLatencyBytes / NormalEfficiency / ReturnBusWidth; - for (k = 0; k < NumberOfActivePlanes; ++k) { + MinimumTWait = CalculateTWait(MaxPrefetchMode, v->FinalDRAMClockChangeLatency, v->UrgLatency[i], v->SREnterPlusExitTime); + NonDPTEBandwidth = v->TotalVActivePixelBandwidth[i][j] + v->TotalVActiveCursorBandwidth[i][j] + v->TotalMetaRowBandwidth[i][j]; + DPTEBandwidth = (v->HostVMEnable == true || v->ImmediateFlipRequirement[0] == dm_immediate_flip_required) ? + TotalMaxPrefetchFlipDPTERowBandwidth[i][j] : v->TotalDPTERowBandwidth[i][j]; + DCFCLKRequiredForAverageBandwidth = dml_max3(v->ProjectedDCFCLKDeepSleep[i][j], + (NonDPTEBandwidth + v->TotalDPTERowBandwidth[i][j]) / v->ReturnBusWidth / (v->MaxAveragePercentOfIdealSDPPortBWDisplayCanUseInNormalSystemOperation / 100), + (NonDPTEBandwidth + DPTEBandwidth / PTEEfficiency) / NormalEfficiency / v->ReturnBusWidth); + + ExtraLatencyBytes = CalculateExtraLatencyBytes(ReorderingBytes, v->TotalNumberOfActiveDPP[i][j], v->PixelChunkSizeInKByte, v->TotalNumberOfDCCActiveDPP[i][j], + v->MetaChunkSize, v->GPUVMEnable, v->HostVMEnable, v->NumberOfActivePlanes, NoOfDPPState, v->dpte_group_bytes, + v->PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelMixedWithVMData, v->PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyVMDataOnly, + v->HostVMMinPageSize, v->HostVMMaxNonCachedPageTableLevels); + ExtraLatencyCycles = v->RoundTripPingLatencyCycles + 32 + ExtraLatencyBytes / NormalEfficiency / v->ReturnBusWidth; + for (k = 0; k < v->NumberOfActivePlanes; ++k) { double DCFCLKCyclesRequiredInPrefetch = { 0 }; double ExpectedPrefetchBWAcceleration = { 0 }; double PrefetchTime = { 0 }; - PixelDCFCLKCyclesRequiredInPrefetch[k] = (PrefetchLinesY[i][j][k] * swath_width_luma_ub_all_states[i][j][k] * BytePerPixelY[k] - + PrefetchLinesC[i][j][k] * swath_width_chroma_ub_all_states[i][j][k] * BytePerPixelC[k]) / NormalEfficiency / ReturnBusWidth; - DCFCLKCyclesRequiredInPrefetch = 2 * ExtraLatencyCycles / NoOfDPPState[k] + PDEAndMetaPTEBytesPerFrame[i][j][k] / PTEEfficiency - / NormalEfficiency / ReturnBusWidth * (GPUVMMaxPageTableLevels > 2 ? 1 : 0) + 2 * DPTEBytesPerRow[i][j][k] / PTEEfficiency - / NormalEfficiency / ReturnBusWidth + 2 * MetaRowBytes[i][j][k] / NormalEfficiency / ReturnBusWidth + PixelDCFCLKCyclesRequiredInPrefetch[k]; - PrefetchPixelLinesTime[k] = dml_max(PrefetchLinesY[i][j][k], PrefetchLinesC[i][j][k]) * HTotal[k] / PixelClock[k]; - ExpectedPrefetchBWAcceleration = (VActivePixelBandwidth[i][j][k] + VActiveCursorBandwidth[i][j][k]) / (ReadBandwidthLuma[k] + ReadBandwidthChroma[k]); - DynamicMetadataVMExtraLatency[k] = (GPUVMEnable == true && DynamicMetadataEnable[k] == true && DynamicMetadataVMEnabled == true) ? - UrgLatency[i] * GPUVMMaxPageTableLevels * (HostVMEnable == true ? HostVMMaxNonCachedPageTableLevels + 1 : 1) : 0; - PrefetchTime = (MaximumVStartup[i][j][k] - 1) * HTotal[k] / PixelClock[k] - MinimumTWait - UrgLatency[i] * ((GPUVMMaxPageTableLevels <= 2 ? GPUVMMaxPageTableLevels - : GPUVMMaxPageTableLevels - 2) * (HostVMEnable == true ? HostVMMaxNonCachedPageTableLevels + 1 : 1) - 1) - DynamicMetadataVMExtraLatency[k]; + PixelDCFCLKCyclesRequiredInPrefetch[k] = (v->PrefetchLinesY[i][j][k] * v->swath_width_luma_ub_all_states[i][j][k] * v->BytePerPixelY[k] + + v->PrefetchLinesC[i][j][k] * v->swath_width_chroma_ub_all_states[i][j][k] * v->BytePerPixelC[k]) / NormalEfficiency / v->ReturnBusWidth; + DCFCLKCyclesRequiredInPrefetch = 2 * ExtraLatencyCycles / NoOfDPPState[k] + v->PDEAndMetaPTEBytesPerFrame[i][j][k] / PTEEfficiency + / NormalEfficiency / v->ReturnBusWidth * (v->GPUVMMaxPageTableLevels > 2 ? 1 : 0) + 2 * v->DPTEBytesPerRow[i][j][k] / PTEEfficiency + / NormalEfficiency / v->ReturnBusWidth + 2 * v->MetaRowBytes[i][j][k] / NormalEfficiency / v->ReturnBusWidth + PixelDCFCLKCyclesRequiredInPrefetch[k]; + PrefetchPixelLinesTime[k] = dml_max(v->PrefetchLinesY[i][j][k], v->PrefetchLinesC[i][j][k]) * v->HTotal[k] / v->PixelClock[k]; + ExpectedPrefetchBWAcceleration = (v->VActivePixelBandwidth[i][j][k] + v->VActiveCursorBandwidth[i][j][k]) / (v->ReadBandwidthLuma[k] + v->ReadBandwidthChroma[k]); + DynamicMetadataVMExtraLatency[k] = (v->GPUVMEnable == true && v->DynamicMetadataEnable[k] == true && v->DynamicMetadataVMEnabled == true) ? + v->UrgLatency[i] * v->GPUVMMaxPageTableLevels * (v->HostVMEnable == true ? v->HostVMMaxNonCachedPageTableLevels + 1 : 1) : 0; + PrefetchTime = (v->MaximumVStartup[i][j][k] - 1) * v->HTotal[k] / v->PixelClock[k] - MinimumTWait - v->UrgLatency[i] * ((v->GPUVMMaxPageTableLevels <= 2 ? v->GPUVMMaxPageTableLevels + : v->GPUVMMaxPageTableLevels - 2) * (v->HostVMEnable == true ? v->HostVMMaxNonCachedPageTableLevels + 1 : 1) - 1) - DynamicMetadataVMExtraLatency[k]; if (PrefetchTime > 0) { double ExpectedVRatioPrefetch = { 0 }; ExpectedVRatioPrefetch = PrefetchPixelLinesTime[k] / (PrefetchTime * PixelDCFCLKCyclesRequiredInPrefetch[k] / DCFCLKCyclesRequiredInPrefetch); DCFCLKRequiredForPeakBandwidthPerPlane[k] = NoOfDPPState[k] * PixelDCFCLKCyclesRequiredInPrefetch[k] / PrefetchPixelLinesTime[k] * dml_max(1.0, ExpectedVRatioPrefetch) * dml_max(1.0, ExpectedVRatioPrefetch / 4) * ExpectedPrefetchBWAcceleration; - if (HostVMEnable == true || ImmediateFlipRequirement == dm_immediate_flip_required) { + if (v->HostVMEnable == true || v->ImmediateFlipRequirement[0] == dm_immediate_flip_required) { DCFCLKRequiredForPeakBandwidthPerPlane[k] = DCFCLKRequiredForPeakBandwidthPerPlane[k] - + NoOfDPPState[k] * DPTEBandwidth / PTEEfficiency / NormalEfficiency / ReturnBusWidth; + + NoOfDPPState[k] * DPTEBandwidth / PTEEfficiency / NormalEfficiency / v->ReturnBusWidth; } } else { - DCFCLKRequiredForPeakBandwidthPerPlane[k] = DCFCLKPerState[i]; + DCFCLKRequiredForPeakBandwidthPerPlane[k] = v->DCFCLKPerState[i]; } - if (DynamicMetadataEnable[k] == true) { + if (v->DynamicMetadataEnable[k] == true) { double TsetupPipe = { 0 }; double TdmbfPipe = { 0 }; double TdmsksPipe = { 0 }; @@ -6756,49 +6584,49 @@ static noinline_for_stack void UseMinimumDCFCLK( double AllowedTimeForUrgentExtraLatency = { 0 }; CalculateDynamicMetadataParameters( - MaxInterDCNTileRepeaters, - RequiredDPPCLK[i][j][k], - RequiredDISPCLK[i][j], - ProjectedDCFCLKDeepSleep[i][j], - PixelClock[k], - HTotal[k], - VTotal[k] - VActive[k], - DynamicMetadataTransmittedBytes[k], - DynamicMetadataLinesBeforeActiveRequired[k], - Interlace[k], - ProgressiveToInterlaceUnitInOPP, + v->MaxInterDCNTileRepeaters, + v->RequiredDPPCLK[i][j][k], + v->RequiredDISPCLK[i][j], + v->ProjectedDCFCLKDeepSleep[i][j], + v->PixelClock[k], + v->HTotal[k], + v->VTotal[k] - v->VActive[k], + v->DynamicMetadataTransmittedBytes[k], + v->DynamicMetadataLinesBeforeActiveRequired[k], + v->Interlace[k], + v->ProgressiveToInterlaceUnitInOPP, &TsetupPipe, &TdmbfPipe, &TdmecPipe, &TdmsksPipe); - AllowedTimeForUrgentExtraLatency = MaximumVStartup[i][j][k] * HTotal[k] / PixelClock[k] - MinimumTWait - TsetupPipe + AllowedTimeForUrgentExtraLatency = v->MaximumVStartup[i][j][k] * v->HTotal[k] / v->PixelClock[k] - MinimumTWait - TsetupPipe - TdmbfPipe - TdmecPipe - TdmsksPipe - DynamicMetadataVMExtraLatency[k]; if (AllowedTimeForUrgentExtraLatency > 0) { DCFCLKRequiredForPeakBandwidthPerPlane[k] = dml_max(DCFCLKRequiredForPeakBandwidthPerPlane[k], ExtraLatencyCycles / AllowedTimeForUrgentExtraLatency); } else { - DCFCLKRequiredForPeakBandwidthPerPlane[k] = DCFCLKPerState[i]; + DCFCLKRequiredForPeakBandwidthPerPlane[k] = v->DCFCLKPerState[i]; } } } DCFCLKRequiredForPeakBandwidth = 0; - for (k = 0; k <= NumberOfActivePlanes - 1; ++k) { + for (k = 0; k <= v->NumberOfActivePlanes - 1; ++k) { DCFCLKRequiredForPeakBandwidth = DCFCLKRequiredForPeakBandwidth + DCFCLKRequiredForPeakBandwidthPerPlane[k]; } - MinimumTvmPlus2Tr0 = UrgLatency[i] * (GPUVMEnable == true ? (HostVMEnable == true ? - (GPUVMMaxPageTableLevels + 2) * (HostVMMaxNonCachedPageTableLevels + 1) - 1 : GPUVMMaxPageTableLevels + 1) : 0); - for (k = 0; k < NumberOfActivePlanes; ++k) { + MinimumTvmPlus2Tr0 = v->UrgLatency[i] * (v->GPUVMEnable == true ? (v->HostVMEnable == true ? + (v->GPUVMMaxPageTableLevels + 2) * (v->HostVMMaxNonCachedPageTableLevels + 1) - 1 : v->GPUVMMaxPageTableLevels + 1) : 0); + for (k = 0; k < v->NumberOfActivePlanes; ++k) { double MaximumTvmPlus2Tr0PlusTsw = { 0 }; - MaximumTvmPlus2Tr0PlusTsw = (MaximumVStartup[i][j][k] - 2) * HTotal[k] / PixelClock[k] - MinimumTWait - DynamicMetadataVMExtraLatency[k]; + MaximumTvmPlus2Tr0PlusTsw = (v->MaximumVStartup[i][j][k] - 2) * v->HTotal[k] / v->PixelClock[k] - MinimumTWait - DynamicMetadataVMExtraLatency[k]; if (MaximumTvmPlus2Tr0PlusTsw <= MinimumTvmPlus2Tr0 + PrefetchPixelLinesTime[k] / 4) { - DCFCLKRequiredForPeakBandwidth = DCFCLKPerState[i]; + DCFCLKRequiredForPeakBandwidth = v->DCFCLKPerState[i]; } else { DCFCLKRequiredForPeakBandwidth = dml_max3(DCFCLKRequiredForPeakBandwidth, 2 * ExtraLatencyCycles / (MaximumTvmPlus2Tr0PlusTsw - MinimumTvmPlus2Tr0 - PrefetchPixelLinesTime[k] / 4), (2 * ExtraLatencyCycles + PixelDCFCLKCyclesRequiredInPrefetch[k]) / (MaximumTvmPlus2Tr0PlusTsw - MinimumTvmPlus2Tr0)); } } - DCFCLKState[i][j] = dml_min(DCFCLKPerState[i], 1.05 * (1 + mode_lib->vba.PercentMarginOverMinimumRequiredDCFCLK / 100) + v->DCFCLKState[i][j] = dml_min(v->DCFCLKPerState[i], 1.05 * (1 + mode_lib->vba.PercentMarginOverMinimumRequiredDCFCLK / 100) * dml_max(DCFCLKRequiredForAverageBandwidth, DCFCLKRequiredForPeakBandwidth)); } } diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c index d211cf6d234c..422f17aefd4a 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c @@ -322,6 +322,7 @@ static void calculate_wm_set_for_vlevel(int vlevel, void dcn301_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) { + struct _vcs_dpi_voltage_scaling_st *s = dc->scratch.update_bw_bounding_box.clock_limits; struct dcn301_resource_pool *pool = TO_DCN301_RES_POOL(dc->res_pool); struct clk_limit_table *clk_table = &bw_params->clk_table; unsigned int i, closest_clk_lvl; @@ -329,8 +330,7 @@ void dcn301_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param dc_assert_fp_enabled(); - memcpy(&dcn3_01_soc._clock_tmp, &dcn3_01_soc.clock_limits, - sizeof(dcn3_01_soc.clock_limits)); + memcpy(s, dcn3_01_soc.clock_limits, sizeof(dcn3_01_soc.clock_limits)); /* Default clock levels are used for diags, which may lead to overclocking. */ if (!IS_DIAG_DC(dc->ctx->dce_environment)) { @@ -348,35 +348,42 @@ void dcn301_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param } } - dcn3_01_soc._clock_tmp[i].state = i; - dcn3_01_soc._clock_tmp[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz; - dcn3_01_soc._clock_tmp[i].fabricclk_mhz = clk_table->entries[i].fclk_mhz; - dcn3_01_soc._clock_tmp[i].socclk_mhz = clk_table->entries[i].socclk_mhz; - dcn3_01_soc._clock_tmp[i].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2; - - dcn3_01_soc._clock_tmp[i].dispclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dispclk_mhz; - dcn3_01_soc._clock_tmp[i].dppclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dppclk_mhz; - dcn3_01_soc._clock_tmp[i].dram_bw_per_chan_gbps = dcn3_01_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps; - dcn3_01_soc._clock_tmp[i].dscclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dscclk_mhz; - dcn3_01_soc._clock_tmp[i].dtbclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dtbclk_mhz; - dcn3_01_soc._clock_tmp[i].phyclk_d18_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz; - dcn3_01_soc._clock_tmp[i].phyclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].phyclk_mhz; + s[i].state = i; + s[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz; + s[i].fabricclk_mhz = clk_table->entries[i].fclk_mhz; + s[i].socclk_mhz = clk_table->entries[i].socclk_mhz; + s[i].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2; + + s[i].dispclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dispclk_mhz; + s[i].dppclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dppclk_mhz; + s[i].dram_bw_per_chan_gbps = + dcn3_01_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps; + s[i].dscclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dscclk_mhz; + s[i].dtbclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dtbclk_mhz; + s[i].phyclk_d18_mhz = + dcn3_01_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz; + s[i].phyclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].phyclk_mhz; } if (clk_table->num_entries) { dcn3_01_soc.num_states = clk_table->num_entries; /* duplicate last level */ - dcn3_01_soc._clock_tmp[dcn3_01_soc.num_states] = dcn3_01_soc.clock_limits[dcn3_01_soc.num_states - 1]; - dcn3_01_soc._clock_tmp[dcn3_01_soc.num_states].state = dcn3_01_soc.num_states; + s[dcn3_01_soc.num_states] = + dcn3_01_soc.clock_limits[dcn3_01_soc.num_states - 1]; + s[dcn3_01_soc.num_states].state = dcn3_01_soc.num_states; } } - memcpy(&dcn3_01_soc.clock_limits, &dcn3_01_soc._clock_tmp, - sizeof(dcn3_01_soc.clock_limits)); + memcpy(dcn3_01_soc.clock_limits, s, sizeof(dcn3_01_soc.clock_limits)); dcn3_01_soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; + if ((int)(dcn3_01_soc.dram_clock_change_latency_us * 1000) + != dc->debug.dram_clock_change_latency_ns + && dc->debug.dram_clock_change_latency_ns) { + dcn3_01_soc.dram_clock_change_latency_us = dc->debug.dram_clock_change_latency_ns / 1000.0; + } dml_init_instance(&dc->dml, &dcn3_01_soc, &dcn3_01_ip, DML_PROJECT_DCN30); } diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c index fa7b0291ce4d..b6e99eefe869 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c @@ -598,14 +598,14 @@ void dcn31_calculate_wm_and_dlg_fp( void dcn31_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) { + struct _vcs_dpi_voltage_scaling_st *s = dc->scratch.update_bw_bounding_box.clock_limits; struct clk_limit_table *clk_table = &bw_params->clk_table; unsigned int i, closest_clk_lvl; int j; dc_assert_fp_enabled(); - memcpy(&dcn3_1_soc._clock_tmp, &dcn3_1_soc.clock_limits, - sizeof(dcn3_1_soc.clock_limits)); + memcpy(s, dcn3_1_soc.clock_limits, sizeof(dcn3_1_soc.clock_limits)); // Default clock levels are used for diags, which may lead to overclocking. if (!IS_DIAG_DC(dc->ctx->dce_environment)) { @@ -634,38 +634,46 @@ void dcn31_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params } } - dcn3_1_soc._clock_tmp[i].state = i; + s[i].state = i; /* Clocks dependent on voltage level. */ - dcn3_1_soc._clock_tmp[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz; - dcn3_1_soc._clock_tmp[i].fabricclk_mhz = clk_table->entries[i].fclk_mhz; - dcn3_1_soc._clock_tmp[i].socclk_mhz = clk_table->entries[i].socclk_mhz; - dcn3_1_soc._clock_tmp[i].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2 * clk_table->entries[i].wck_ratio; + s[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz; + s[i].fabricclk_mhz = clk_table->entries[i].fclk_mhz; + s[i].socclk_mhz = clk_table->entries[i].socclk_mhz; + s[i].dram_speed_mts = clk_table->entries[i].memclk_mhz * + 2 * clk_table->entries[i].wck_ratio; /* Clocks independent of voltage level. */ - dcn3_1_soc._clock_tmp[i].dispclk_mhz = max_dispclk_mhz ? max_dispclk_mhz : + s[i].dispclk_mhz = max_dispclk_mhz ? max_dispclk_mhz : dcn3_1_soc.clock_limits[closest_clk_lvl].dispclk_mhz; - dcn3_1_soc._clock_tmp[i].dppclk_mhz = max_dppclk_mhz ? max_dppclk_mhz : + s[i].dppclk_mhz = max_dppclk_mhz ? max_dppclk_mhz : dcn3_1_soc.clock_limits[closest_clk_lvl].dppclk_mhz; - dcn3_1_soc._clock_tmp[i].dram_bw_per_chan_gbps = dcn3_1_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps; - dcn3_1_soc._clock_tmp[i].dscclk_mhz = dcn3_1_soc.clock_limits[closest_clk_lvl].dscclk_mhz; - dcn3_1_soc._clock_tmp[i].dtbclk_mhz = dcn3_1_soc.clock_limits[closest_clk_lvl].dtbclk_mhz; - dcn3_1_soc._clock_tmp[i].phyclk_d18_mhz = dcn3_1_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz; - dcn3_1_soc._clock_tmp[i].phyclk_mhz = dcn3_1_soc.clock_limits[closest_clk_lvl].phyclk_mhz; + s[i].dram_bw_per_chan_gbps = + dcn3_1_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps; + s[i].dscclk_mhz = dcn3_1_soc.clock_limits[closest_clk_lvl].dscclk_mhz; + s[i].dtbclk_mhz = dcn3_1_soc.clock_limits[closest_clk_lvl].dtbclk_mhz; + s[i].phyclk_d18_mhz = + dcn3_1_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz; + s[i].phyclk_mhz = dcn3_1_soc.clock_limits[closest_clk_lvl].phyclk_mhz; } if (clk_table->num_entries) { dcn3_1_soc.num_states = clk_table->num_entries; } } - memcpy(&dcn3_1_soc.clock_limits, &dcn3_1_soc._clock_tmp, - sizeof(dcn3_1_soc.clock_limits)); + memcpy(dcn3_1_soc.clock_limits, s, sizeof(dcn3_1_soc.clock_limits)); dcn3_1_soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; + if ((int)(dcn3_1_soc.dram_clock_change_latency_us * 1000) + != dc->debug.dram_clock_change_latency_ns + && dc->debug.dram_clock_change_latency_ns) { + dcn3_1_soc.dram_clock_change_latency_us = dc->debug.dram_clock_change_latency_ns / 1000; + } + if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) dml_init_instance(&dc->dml, &dcn3_1_soc, &dcn3_1_ip, DML_PROJECT_DCN31); else @@ -724,6 +732,12 @@ void dcn315_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param */ dcn3_15_soc.dispclk_dppclk_vco_speed_mhz = max_dispclk_mhz * 2; + if ((int)(dcn3_15_soc.dram_clock_change_latency_us * 1000) + != dc->debug.dram_clock_change_latency_ns + && dc->debug.dram_clock_change_latency_ns) { + dcn3_15_soc.dram_clock_change_latency_us = dc->debug.dram_clock_change_latency_ns / 1000; + } + if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) dml_init_instance(&dc->dml, &dcn3_15_soc, &dcn3_15_ip, DML_PROJECT_DCN31); else @@ -732,6 +746,7 @@ void dcn315_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param void dcn316_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) { + struct _vcs_dpi_voltage_scaling_st *s = dc->scratch.update_bw_bounding_box.clock_limits; struct clk_limit_table *clk_table = &bw_params->clk_table; unsigned int i, closest_clk_lvl; int max_dispclk_mhz = 0, max_dppclk_mhz = 0; @@ -739,8 +754,7 @@ void dcn316_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param dc_assert_fp_enabled(); - memcpy(&dcn3_16_soc._clock_tmp, &dcn3_16_soc.clock_limits, - sizeof(dcn3_16_soc.clock_limits)); + memcpy(s, dcn3_16_soc.clock_limits, sizeof(dcn3_16_soc.clock_limits)); // Default clock levels are used for diags, which may lead to overclocking. if (!IS_DIAG_DC(dc->ctx->dce_environment)) { @@ -762,7 +776,8 @@ void dcn316_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param for (i = 0; i < clk_table->num_entries; i++) { /* loop backwards*/ for (closest_clk_lvl = 0, j = dcn3_16_soc.num_states - 1; j >= 0; j--) { - if ((unsigned int) dcn3_16_soc.clock_limits[j].dcfclk_mhz <= clk_table->entries[i].dcfclk_mhz) { + if ((unsigned int) dcn3_16_soc.clock_limits[j].dcfclk_mhz <= + clk_table->entries[i].dcfclk_mhz) { closest_clk_lvl = j; break; } @@ -773,44 +788,53 @@ void dcn316_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param closest_clk_lvl = dcn3_16_soc.num_states - 1; } - dcn3_16_soc._clock_tmp[i].state = i; + s[i].state = i; /* Clocks dependent on voltage level. */ - dcn3_16_soc._clock_tmp[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz; + s[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz; if (clk_table->num_entries == 1 && - dcn3_16_soc._clock_tmp[i].dcfclk_mhz < dcn3_16_soc.clock_limits[closest_clk_lvl].dcfclk_mhz) { + s[i].dcfclk_mhz < + dcn3_16_soc.clock_limits[closest_clk_lvl].dcfclk_mhz) { /*SMU fix not released yet*/ - dcn3_16_soc._clock_tmp[i].dcfclk_mhz = dcn3_16_soc.clock_limits[closest_clk_lvl].dcfclk_mhz; + s[i].dcfclk_mhz = + dcn3_16_soc.clock_limits[closest_clk_lvl].dcfclk_mhz; } - dcn3_16_soc._clock_tmp[i].fabricclk_mhz = clk_table->entries[i].fclk_mhz; - dcn3_16_soc._clock_tmp[i].socclk_mhz = clk_table->entries[i].socclk_mhz; - dcn3_16_soc._clock_tmp[i].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2 * clk_table->entries[i].wck_ratio; + s[i].fabricclk_mhz = clk_table->entries[i].fclk_mhz; + s[i].socclk_mhz = clk_table->entries[i].socclk_mhz; + s[i].dram_speed_mts = clk_table->entries[i].memclk_mhz * + 2 * clk_table->entries[i].wck_ratio; /* Clocks independent of voltage level. */ - dcn3_16_soc._clock_tmp[i].dispclk_mhz = max_dispclk_mhz ? max_dispclk_mhz : + s[i].dispclk_mhz = max_dispclk_mhz ? max_dispclk_mhz : dcn3_16_soc.clock_limits[closest_clk_lvl].dispclk_mhz; - dcn3_16_soc._clock_tmp[i].dppclk_mhz = max_dppclk_mhz ? max_dppclk_mhz : + s[i].dppclk_mhz = max_dppclk_mhz ? max_dppclk_mhz : dcn3_16_soc.clock_limits[closest_clk_lvl].dppclk_mhz; - dcn3_16_soc._clock_tmp[i].dram_bw_per_chan_gbps = dcn3_16_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps; - dcn3_16_soc._clock_tmp[i].dscclk_mhz = dcn3_16_soc.clock_limits[closest_clk_lvl].dscclk_mhz; - dcn3_16_soc._clock_tmp[i].dtbclk_mhz = dcn3_16_soc.clock_limits[closest_clk_lvl].dtbclk_mhz; - dcn3_16_soc._clock_tmp[i].phyclk_d18_mhz = dcn3_16_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz; - dcn3_16_soc._clock_tmp[i].phyclk_mhz = dcn3_16_soc.clock_limits[closest_clk_lvl].phyclk_mhz; + s[i].dram_bw_per_chan_gbps = + dcn3_16_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps; + s[i].dscclk_mhz = dcn3_16_soc.clock_limits[closest_clk_lvl].dscclk_mhz; + s[i].dtbclk_mhz = dcn3_16_soc.clock_limits[closest_clk_lvl].dtbclk_mhz; + s[i].phyclk_d18_mhz = + dcn3_16_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz; + s[i].phyclk_mhz = dcn3_16_soc.clock_limits[closest_clk_lvl].phyclk_mhz; } if (clk_table->num_entries) { dcn3_16_soc.num_states = clk_table->num_entries; } } - memcpy(&dcn3_16_soc.clock_limits, &dcn3_16_soc._clock_tmp, - sizeof(dcn3_16_soc.clock_limits)); + memcpy(dcn3_16_soc.clock_limits, s, sizeof(dcn3_16_soc.clock_limits)); if (max_dispclk_mhz) { dcn3_16_soc.dispclk_dppclk_vco_speed_mhz = max_dispclk_mhz * 2; dc->dml.soc.dispclk_dppclk_vco_speed_mhz = max_dispclk_mhz * 2; } + if ((int)(dcn3_16_soc.dram_clock_change_latency_us * 1000) + != dc->debug.dram_clock_change_latency_ns + && dc->debug.dram_clock_change_latency_ns) { + dcn3_16_soc.dram_clock_change_latency_us = dc->debug.dram_clock_change_latency_ns / 1000; + } if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) dml_init_instance(&dc->dml, &dcn3_16_soc, &dcn3_16_ip, DML_PROJECT_DCN31); diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c index 8ca66f1644dc..8dfe639b6508 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c @@ -1051,10 +1051,10 @@ static bool CalculatePrefetchSchedule( bytes_pp = myPipe->BytePerPixelY + myPipe->BytePerPixelC; /*rev 99*/ prefetch_bw_pr = dml_min(1, bytes_pp * myPipe->PixelClock / (double) myPipe->DPPPerPlane); - max_Tsw = dml_max(PrefetchSourceLinesY, PrefetchSourceLinesC) * LineTime; + max_Tsw = dml_max(PrefetchSourceLinesY, PrefetchSourceLinesC) * LineTime; prefetch_sw_bytes = PrefetchSourceLinesY * swath_width_luma_ub * myPipe->BytePerPixelY + PrefetchSourceLinesC * swath_width_chroma_ub * myPipe->BytePerPixelC; prefetch_bw_oto = dml_max(bytes_pp * myPipe->PixelClock / myPipe->DPPPerPlane, prefetch_sw_bytes / (dml_max(PrefetchSourceLinesY, PrefetchSourceLinesC) * LineTime)); - prefetch_bw_oto = dml_max(prefetch_bw_pr, prefetch_sw_bytes / max_Tsw); + prefetch_bw_oto = dml_max(prefetch_bw_pr, prefetch_sw_bytes / max_Tsw); min_Lsw = dml_max(1, dml_max(PrefetchSourceLinesY, PrefetchSourceLinesC) / max_vratio_pre); Lsw_oto = dml_ceil(4 * dml_max(prefetch_sw_bytes / prefetch_bw_oto / LineTime, min_Lsw), 1) / 4; @@ -6711,8 +6711,6 @@ static void CalculateSwathWidth( { int surface_width_ub_l = dml_ceil(SurfaceWidthY[k], Read256BytesBlockWidthY[k]); int surface_height_ub_l = dml_ceil(SurfaceHeightY[k], Read256BytesBlockHeightY[k]); - int surface_width_ub_c = dml_ceil(SurfaceWidthC[k], Read256BytesBlockWidthC[k]); - int surface_height_ub_c = dml_ceil(SurfaceHeightC[k], Read256BytesBlockHeightC[k]); #ifdef __DML_VBA_DEBUG__ dml_print("DML::%s: k=%d surface_width_ub_l=%0d\n", __func__, k, surface_width_ub_l); @@ -6723,6 +6721,8 @@ static void CalculateSwathWidth( MaximumSwathHeightC[k] = Read256BytesBlockHeightC[k]; swath_width_luma_ub[k] = dml_min(surface_width_ub_l, (int) dml_ceil(SwathWidthY[k] - 1, Read256BytesBlockWidthY[k]) + Read256BytesBlockWidthY[k]); if (BytePerPixC[k] > 0) { + int surface_width_ub_c = dml_ceil(SurfaceWidthC[k], Read256BytesBlockWidthC[k]); + swath_width_chroma_ub[k] = dml_min( surface_width_ub_c, (int) dml_ceil(SwathWidthC[k] - 1, Read256BytesBlockWidthC[k]) + Read256BytesBlockWidthC[k]); @@ -6734,6 +6734,8 @@ static void CalculateSwathWidth( MaximumSwathHeightC[k] = Read256BytesBlockWidthC[k]; swath_width_luma_ub[k] = dml_min(surface_height_ub_l, (int) dml_ceil(SwathWidthY[k] - 1, Read256BytesBlockHeightY[k]) + Read256BytesBlockHeightY[k]); if (BytePerPixC[k] > 0) { + int surface_height_ub_c = dml_ceil(SurfaceHeightC[k], Read256BytesBlockHeightC[k]); + swath_width_chroma_ub[k] = dml_min( surface_height_ub_c, (int) dml_ceil(SwathWidthC[k] - 1, Read256BytesBlockHeightC[k]) + Read256BytesBlockHeightC[k]); diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c index 4bb3b31ea7e0..cf420ad2b8dc 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c @@ -264,6 +264,11 @@ void dcn314_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_p dc->dml.soc.dispclk_dppclk_vco_speed_mhz = max_dispclk_mhz * 2; } + if ((int)(dcn3_14_soc.dram_clock_change_latency_us * 1000) + != dc->debug.dram_clock_change_latency_ns + && dc->debug.dram_clock_change_latency_ns) { + dcn3_14_soc.dram_clock_change_latency_us = dc->debug.dram_clock_change_latency_ns / 1000; + } if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) dml_init_instance(&dc->dml, &dcn3_14_soc, &dcn3_14_ip, DML_PROJECT_DCN314); else @@ -318,6 +323,8 @@ int dcn314_populate_dml_pipes_from_context_fpu(struct dc *dc, struct dc_state *c pipes[pipe_cnt].pipe.src.dcc_fraction_of_zs_req_luma = 0; pipes[pipe_cnt].pipe.src.dcc_fraction_of_zs_req_chroma = 0; pipes[pipe_cnt].pipe.dest.vfront_porch = timing->v_front_porch; + pipes[pipe_cnt].pipe.dest.vblank_nom = + dcn3_14_ip.VBlankNomDefaultUS / (timing->h_total / (timing->pix_clk_100hz / 10000.0)); pipes[pipe_cnt].pipe.src.dcc_rate = 3; pipes[pipe_cnt].dout.dsc_input_bpc = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c index ee821c4fb5dd..0d12fd079cd6 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c @@ -1306,7 +1306,7 @@ static bool CalculatePrefetchSchedule( // - ((NumberOfCursors > 0 || GPUVMEnable || DCCEnable) ? - ((GPUVMEnable || myPipe->DCCEnable) ? (*DestinationLinesToRequestVMInVBlank + 2 * *DestinationLinesToRequestRowInVBlank) : 0.0); // TODO: Did someone else add this?? #else - LinesToRequestPrefetchPixelData = *DestinationLinesForPrefetch - *DestinationLinesToRequestVMInVBlank - 2 * *DestinationLinesToRequestRowInVBlank; + LinesToRequestPrefetchPixelData = *DestinationLinesForPrefetch - *DestinationLinesToRequestVMInVBlank - 2 * *DestinationLinesToRequestRowInVBlank; #endif #ifdef __DML_VBA_DEBUG__ @@ -6825,8 +6825,6 @@ static void CalculateSwathWidth( { int surface_width_ub_l = dml_ceil(SurfaceWidthY[k], Read256BytesBlockWidthY[k]); int surface_height_ub_l = dml_ceil(SurfaceHeightY[k], Read256BytesBlockHeightY[k]); - int surface_width_ub_c = dml_ceil(SurfaceWidthC[k], Read256BytesBlockWidthC[k]); - int surface_height_ub_c = dml_ceil(SurfaceHeightC[k], Read256BytesBlockHeightC[k]); #ifdef __DML_VBA_DEBUG__ dml_print("DML::%s: k=%d surface_width_ub_l=%0d\n", __func__, k, surface_width_ub_l); @@ -6837,6 +6835,8 @@ static void CalculateSwathWidth( MaximumSwathHeightC[k] = Read256BytesBlockHeightC[k]; swath_width_luma_ub[k] = dml_min(surface_width_ub_l, (int) dml_ceil(SwathWidthY[k] - 1, Read256BytesBlockWidthY[k]) + Read256BytesBlockWidthY[k]); if (BytePerPixC[k] > 0) { + int surface_width_ub_c = dml_ceil(SurfaceWidthC[k], Read256BytesBlockWidthC[k]); + swath_width_chroma_ub[k] = dml_min( surface_width_ub_c, (int) dml_ceil(SwathWidthC[k] - 1, Read256BytesBlockWidthC[k]) + Read256BytesBlockWidthC[k]); @@ -6848,6 +6848,8 @@ static void CalculateSwathWidth( MaximumSwathHeightC[k] = Read256BytesBlockWidthC[k]; swath_width_luma_ub[k] = dml_min(surface_height_ub_l, (int) dml_ceil(SwathWidthY[k] - 1, Read256BytesBlockHeightY[k]) + Read256BytesBlockHeightY[k]); if (BytePerPixC[k] > 0) { + int surface_height_ub_c = dml_ceil(SurfaceHeightC[k], Read256BytesBlockHeightC[k]); + swath_width_chroma_ub[k] = dml_min( surface_height_ub_c, (int) dml_ceil(SwathWidthC[k] - 1, Read256BytesBlockHeightC[k]) + Read256BytesBlockHeightC[k]); @@ -7183,7 +7185,7 @@ static unsigned int CalculateMaxVStartup( double line_time_us = HTotal / PixelClock; unsigned int vblank_actual = VTotal - VActive; unsigned int vblank_nom_default_in_line = dml_floor(VBlankNomDefaultUS / line_time_us, 1.0); - unsigned int vblank_nom_input = dml_min(VBlankNom, vblank_nom_default_in_line); + unsigned int vblank_nom_input = VBlankNom; //dml_min(VBlankNom, vblank_nom_default_in_line); unsigned int vblank_avail = vblank_nom_input == 0 ? vblank_nom_default_in_line : vblank_nom_input; vblank_size = (unsigned int) dml_min(vblank_actual, vblank_avail); diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c index f43686997917..0571700f53f9 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c @@ -121,8 +121,8 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_2_soc = { }, }, .num_states = 1, - .sr_exit_time_us = 20.16, - .sr_enter_plus_exit_time_us = 27.13, + .sr_exit_time_us = 42.97, + .sr_enter_plus_exit_time_us = 49.94, .sr_exit_z8_time_us = 285.0, .sr_enter_plus_exit_z8_time_us = 320, .writeback_latency_us = 12.0, @@ -330,41 +330,92 @@ void dcn32_helper_populate_phantom_dlg_params(struct dc *dc, } } -bool dcn32_predict_pipe_split(struct dc_state *context, display_pipe_params_st pipe, int index) +/** + * ******************************************************************************************* + * dcn32_predict_pipe_split: Predict if pipe split will occur for a given DML pipe + * + * This function takes in a DML pipe (pipe_e2e) and predicts if pipe split is required (both + * ODM and MPC). For pipe split, ODM combine is determined by the ODM mode, and MPC combine is + * determined by DPPClk requirements + * + * This function follows the same policy as DML: + * - Check for ODM combine requirements / policy first + * - MPC combine is only chosen if there is no ODM combine requirements / policy in place, and + * MPC is required + * + * @param [in]: context: New DC state to be programmed + * @param [in]: pipe_e2e: DML pipe end to end context + * + * @return: Number of splits expected (1 for 2:1 split, 3 for 4:1 split, 0 for no splits). + * + * ******************************************************************************************* + */ +uint8_t dcn32_predict_pipe_split(struct dc_state *context, + display_e2e_pipe_params_st *pipe_e2e) { double pscl_throughput; double pscl_throughput_chroma; double dpp_clk_single_dpp, clock; double clk_frequency = 0.0; double vco_speed = context->bw_ctx.dml.soc.dispclk_dppclk_vco_speed_mhz; + bool total_available_pipes_support = false; + uint32_t number_of_dpp = 0; + enum odm_combine_mode odm_mode = dm_odm_combine_mode_disabled; + double req_dispclk_per_surface = 0; + uint8_t num_splits = 0; dc_assert_fp_enabled(); - dml32_CalculateSinglePipeDPPCLKAndSCLThroughput(pipe.scale_ratio_depth.hscl_ratio, - pipe.scale_ratio_depth.hscl_ratio_c, - pipe.scale_ratio_depth.vscl_ratio, - pipe.scale_ratio_depth.vscl_ratio_c, - context->bw_ctx.dml.ip.max_dchub_pscl_bw_pix_per_clk, - context->bw_ctx.dml.ip.max_pscl_lb_bw_pix_per_clk, - pipe.dest.pixel_rate_mhz, - pipe.src.source_format, - pipe.scale_taps.htaps, - pipe.scale_taps.htaps_c, - pipe.scale_taps.vtaps, - pipe.scale_taps.vtaps_c, - /* Output */ - &pscl_throughput, &pscl_throughput_chroma, - &dpp_clk_single_dpp); + dml32_CalculateODMMode(context->bw_ctx.dml.ip.maximum_pixels_per_line_per_dsc_unit, + pipe_e2e->pipe.dest.hactive, + pipe_e2e->dout.output_format, + pipe_e2e->dout.output_type, + pipe_e2e->pipe.dest.odm_combine_policy, + context->bw_ctx.dml.soc.clock_limits[context->bw_ctx.dml.soc.num_states - 1].dispclk_mhz, + context->bw_ctx.dml.soc.clock_limits[context->bw_ctx.dml.soc.num_states - 1].dispclk_mhz, + pipe_e2e->dout.dsc_enable != 0, + 0, /* TotalNumberOfActiveDPP can be 0 since we're predicting pipe split requirement */ + context->bw_ctx.dml.ip.max_num_dpp, + pipe_e2e->pipe.dest.pixel_rate_mhz, + context->bw_ctx.dml.soc.dcn_downspread_percent, + context->bw_ctx.dml.ip.dispclk_ramp_margin_percent, + context->bw_ctx.dml.soc.dispclk_dppclk_vco_speed_mhz, + pipe_e2e->dout.dsc_slices, + /* Output */ + &total_available_pipes_support, + &number_of_dpp, + &odm_mode, + &req_dispclk_per_surface); + + dml32_CalculateSinglePipeDPPCLKAndSCLThroughput(pipe_e2e->pipe.scale_ratio_depth.hscl_ratio, + pipe_e2e->pipe.scale_ratio_depth.hscl_ratio_c, + pipe_e2e->pipe.scale_ratio_depth.vscl_ratio, + pipe_e2e->pipe.scale_ratio_depth.vscl_ratio_c, + context->bw_ctx.dml.ip.max_dchub_pscl_bw_pix_per_clk, + context->bw_ctx.dml.ip.max_pscl_lb_bw_pix_per_clk, + pipe_e2e->pipe.dest.pixel_rate_mhz, + pipe_e2e->pipe.src.source_format, + pipe_e2e->pipe.scale_taps.htaps, + pipe_e2e->pipe.scale_taps.htaps_c, + pipe_e2e->pipe.scale_taps.vtaps, + pipe_e2e->pipe.scale_taps.vtaps_c, + /* Output */ + &pscl_throughput, &pscl_throughput_chroma, + &dpp_clk_single_dpp); clock = dpp_clk_single_dpp * (1 + context->bw_ctx.dml.soc.dcn_downspread_percent / 100); if (clock > 0) - clk_frequency = vco_speed * 4.0 / ((int)(vco_speed * 4.0)); + clk_frequency = vco_speed * 4.0 / ((int)(vco_speed * 4.0) / clock); - if (clk_frequency > context->bw_ctx.dml.soc.clock_limits[index].dppclk_mhz) - return true; - else - return false; + if (odm_mode == dm_odm_combine_mode_2to1) + num_splits = 1; + else if (odm_mode == dm_odm_combine_mode_4to1) + num_splits = 3; + else if (clk_frequency > context->bw_ctx.dml.soc.clock_limits[context->bw_ctx.dml.soc.num_states - 1].dppclk_mhz) + num_splits = 1; + + return num_splits; } static float calculate_net_bw_in_kbytes_sec(struct _vcs_dpi_voltage_scaling_st *entry) @@ -604,6 +655,7 @@ static bool dcn32_assign_subvp_pipe(struct dc *dc, bool valid_assignment_found = false; unsigned int free_pipes = dcn32_get_num_free_pipes(dc, context); bool current_assignment_freesync = false; + struct vba_vars_st *vba = &context->bw_ctx.dml.vba; for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; @@ -617,8 +669,16 @@ static bool dcn32_assign_subvp_pipe(struct dc *dc, refresh_rate = (pipe->stream->timing.pix_clk_100hz * 100 + pipe->stream->timing.v_total * pipe->stream->timing.h_total - 1) / (double)(pipe->stream->timing.v_total * pipe->stream->timing.h_total); + /* SubVP pipe candidate requirements: + * - Refresh rate < 120hz + * - Not able to switch in vactive naturally (switching in active means the + * DET provides enough buffer to hide the P-State switch latency -- trying + * to combine this with SubVP can cause issues with the scheduling). + * - Not TMZ surface + */ if (pipe->plane_state && !pipe->top_pipe && - pipe->stream->mall_stream_config.type == SUBVP_NONE && refresh_rate < 120) { + pipe->stream->mall_stream_config.type == SUBVP_NONE && refresh_rate < 120 && !pipe->plane_state->address.tmz_surface && + vba->ActiveDRAMClockChangeLatencyMarginPerState[vba->VoltageLevel][vba->maxMpcComb][vba->pipe_plane[pipe_idx]] <= 0) { while (pipe) { num_pipes++; pipe = pipe->bottom_pipe; @@ -1042,8 +1102,10 @@ static void dcn32_full_validate_bw_helper(struct dc *dc, *vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, *pipe_cnt); /* This may adjust vlevel and maxMpcComb */ - if (*vlevel < context->bw_ctx.dml.soc.num_states) + if (*vlevel < context->bw_ctx.dml.soc.num_states) { *vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, *vlevel, split, merge); + vba->VoltageLevel = *vlevel; + } /* Conditions for setting up phantom pipes for SubVP: * 1. Not force disable SubVP @@ -1058,8 +1120,10 @@ static void dcn32_full_validate_bw_helper(struct dc *dc, dc->debug.force_subvp_mclk_switch)) { dcn32_merge_pipes_for_subvp(dc, context); - // to re-initialize viewport after the pipe merge - for (int i = 0; i < dc->res_pool->pipe_count; i++) { + memset(merge, 0, MAX_PIPES * sizeof(bool)); + + /* to re-initialize viewport after the pipe merge */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; if (!pipe_ctx->plane_state || !pipe_ctx->stream) @@ -1135,17 +1199,31 @@ static void dcn32_full_validate_bw_helper(struct dc *dc, dc->res_pool->funcs->remove_phantom_pipes(dc, context); vba->DRAMClockChangeSupport[*vlevel][vba->maxMpcComb] = dm_dram_clock_change_unsupported; *pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, false); - } else { - // only call dcn20_validate_apply_pipe_split_flags if we found a supported config - memset(split, 0, MAX_PIPES * sizeof(int)); - memset(merge, 0, MAX_PIPES * sizeof(bool)); - *vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, *vlevel, split, merge); + *vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, *pipe_cnt); + /* This may adjust vlevel and maxMpcComb */ + if (*vlevel < context->bw_ctx.dml.soc.num_states) { + *vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, *vlevel, split, merge); + vba->VoltageLevel = *vlevel; + } + } else { // Most populate phantom DLG params before programming hardware / timing for phantom pipe DC_FP_START(); dcn32_helper_populate_phantom_dlg_params(dc, context, pipes, *pipe_cnt); DC_FP_END(); + /* Call validate_apply_pipe_split flags after calling DML getters for + * phantom dlg params, or some of the VBA params indicating pipe split + * can be overwritten by the getters. + * + * When setting up SubVP config, all pipes are merged before attempting to + * add phantom pipes. If pipe split (ODM / MPC) is required, both the main + * and phantom pipes will be split in the regular pipe splitting sequence. + */ + memset(split, 0, MAX_PIPES * sizeof(int)); + memset(merge, 0, MAX_PIPES * sizeof(bool)); + *vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, *vlevel, split, merge); + vba->VoltageLevel = *vlevel; // Note: We can't apply the phantom pipes to hardware at this time. We have to wait // until driver has acquired the DMCUB lock to do it safely. } @@ -1469,6 +1547,8 @@ bool dcn32_internal_validate_bw(struct dc *dc, memset(split, 0, sizeof(split)); memset(merge, 0, sizeof(merge)); vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, vlevel, split, merge); + // dcn20_validate_apply_pipe_split_flags can modify voltage level outside of DML + vba->VoltageLevel = vlevel; } } @@ -1511,6 +1591,28 @@ bool dcn32_internal_validate_bw(struct dc *dc, if (pipe->next_odm_pipe) pipe->next_odm_pipe->prev_odm_pipe = pipe->prev_odm_pipe; + /*2:1ODM+MPC Split MPO to Single Pipe + MPC Split MPO*/ + if (pipe->bottom_pipe) { + if (pipe->bottom_pipe->prev_odm_pipe || pipe->bottom_pipe->next_odm_pipe) { + /*MPC split rules will handle this case*/ + pipe->bottom_pipe->top_pipe = NULL; + } else { + if (pipe->prev_odm_pipe->bottom_pipe) { + /* 3 plane MPO*/ + pipe->bottom_pipe->top_pipe = pipe->prev_odm_pipe->bottom_pipe; + pipe->prev_odm_pipe->bottom_pipe->bottom_pipe = pipe->bottom_pipe; + } else { + /* 2 plane MPO*/ + pipe->bottom_pipe->top_pipe = pipe->prev_odm_pipe; + pipe->prev_odm_pipe->bottom_pipe = pipe->bottom_pipe; + } + } + } + + if (pipe->top_pipe) { + pipe->top_pipe->bottom_pipe = NULL; + } + pipe->bottom_pipe = NULL; pipe->next_odm_pipe = NULL; pipe->plane_state = NULL; @@ -1643,8 +1745,20 @@ bool dcn32_internal_validate_bw(struct dc *dc, goto validate_fail; } - if (repopulate_pipes) + if (repopulate_pipes) { pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate); + + /* repopulate_pipes = 1 means the pipes were either split or merged. In this case + * we have to re-calculate the DET allocation and run through DML once more to + * ensure all the params are calculated correctly. We do not need to run the + * pipe split check again after this call (pipes are already split / merged). + * */ + if (!fast_validate) { + context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final = + dm_prefetch_support_uclk_fclk_and_stutter_if_possible; + vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt); + } + } *vlevel_out = vlevel; *pipe_cnt_out = pipe_cnt; @@ -1829,7 +1943,11 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context, context->bw_ctx.bw.dcn.watermarks.c.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; context->bw_ctx.bw.dcn.watermarks.c.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; context->bw_ctx.bw.dcn.watermarks.c.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.fclk_pstate_change_ns = get_fclk_watermark(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + /* On DCN32/321, PMFW will set PSTATE_CHANGE_TYPE = 1 (FCLK) for UCLK dummy p-state. + * In this case we must program FCLK WM Set C to use the UCLK dummy p-state WM + * value. + */ + context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.fclk_pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; context->bw_ctx.bw.dcn.watermarks.c.usr_retraining_ns = get_usr_retraining_watermark(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; if ((!pstate_en) && (dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].valid)) { @@ -1926,6 +2044,45 @@ static void remove_entry_from_table_at_index(struct _vcs_dpi_voltage_scaling_st memset(&table[--(*num_entries)], 0, sizeof(struct _vcs_dpi_voltage_scaling_st)); } +void dcn32_patch_dpm_table(struct clk_bw_params *bw_params) +{ + int i; + unsigned int max_dcfclk_mhz = 0, max_dispclk_mhz = 0, max_dppclk_mhz = 0, + max_phyclk_mhz = 0, max_dtbclk_mhz = 0, max_fclk_mhz = 0, max_uclk_mhz = 0; + + for (i = 0; i < MAX_NUM_DPM_LVL; i++) { + if (bw_params->clk_table.entries[i].dcfclk_mhz > max_dcfclk_mhz) + max_dcfclk_mhz = bw_params->clk_table.entries[i].dcfclk_mhz; + if (bw_params->clk_table.entries[i].fclk_mhz > max_fclk_mhz) + max_fclk_mhz = bw_params->clk_table.entries[i].fclk_mhz; + if (bw_params->clk_table.entries[i].memclk_mhz > max_uclk_mhz) + max_uclk_mhz = bw_params->clk_table.entries[i].memclk_mhz; + if (bw_params->clk_table.entries[i].dispclk_mhz > max_dispclk_mhz) + max_dispclk_mhz = bw_params->clk_table.entries[i].dispclk_mhz; + if (bw_params->clk_table.entries[i].dppclk_mhz > max_dppclk_mhz) + max_dppclk_mhz = bw_params->clk_table.entries[i].dppclk_mhz; + if (bw_params->clk_table.entries[i].phyclk_mhz > max_phyclk_mhz) + max_phyclk_mhz = bw_params->clk_table.entries[i].phyclk_mhz; + if (bw_params->clk_table.entries[i].dtbclk_mhz > max_dtbclk_mhz) + max_dtbclk_mhz = bw_params->clk_table.entries[i].dtbclk_mhz; + } + + /* Scan through clock values we currently have and if they are 0, + * then populate it with dcn3_2_soc.clock_limits[] value. + * + * Do it for DCFCLK, DISPCLK, DTBCLK and UCLK as any of those being + * 0, will cause it to skip building the clock table. + */ + if (max_dcfclk_mhz == 0) + bw_params->clk_table.entries[0].dcfclk_mhz = dcn3_2_soc.clock_limits[0].dcfclk_mhz; + if (max_dispclk_mhz == 0) + bw_params->clk_table.entries[0].dispclk_mhz = dcn3_2_soc.clock_limits[0].dispclk_mhz; + if (max_dtbclk_mhz == 0) + bw_params->clk_table.entries[0].dtbclk_mhz = dcn3_2_soc.clock_limits[0].dtbclk_mhz; + if (max_uclk_mhz == 0) + bw_params->clk_table.entries[0].memclk_mhz = dcn3_2_soc.clock_limits[0].dram_speed_mts / 16; +} + static int build_synthetic_soc_states(struct clk_bw_params *bw_params, struct _vcs_dpi_voltage_scaling_st *table, unsigned int *num_entries) { @@ -2160,6 +2317,7 @@ void dcn32_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_pa if ((int)(dcn3_2_soc.urgent_latency_us * 1000) != dc->bb_overrides.urgent_latency_ns && dc->bb_overrides.urgent_latency_ns) { dcn3_2_soc.urgent_latency_us = dc->bb_overrides.urgent_latency_ns / 1000.0; + dcn3_2_soc.urgent_latency_pixel_data_only_us = dc->bb_overrides.urgent_latency_ns / 1000.0; } if ((int)(dcn3_2_soc.dram_clock_change_latency_us * 1000) @@ -2189,13 +2347,16 @@ void dcn32_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_pa if (dc->ctx->dc_bios->funcs->get_soc_bb_info(dc->ctx->dc_bios, &bb_info) == BP_RESULT_OK) { if (bb_info.dram_clock_change_latency_100ns > 0) - dcn3_2_soc.dram_clock_change_latency_us = bb_info.dram_clock_change_latency_100ns * 10; + dcn3_2_soc.dram_clock_change_latency_us = + bb_info.dram_clock_change_latency_100ns * 10; - if (bb_info.dram_sr_enter_exit_latency_100ns > 0) - dcn3_2_soc.sr_enter_plus_exit_time_us = bb_info.dram_sr_enter_exit_latency_100ns * 10; + if (bb_info.dram_sr_enter_exit_latency_100ns > 0) + dcn3_2_soc.sr_enter_plus_exit_time_us = + bb_info.dram_sr_enter_exit_latency_100ns * 10; - if (bb_info.dram_sr_exit_latency_100ns > 0) - dcn3_2_soc.sr_exit_time_us = bb_info.dram_sr_exit_latency_100ns * 10; + if (bb_info.dram_sr_exit_latency_100ns > 0) + dcn3_2_soc.sr_exit_time_us = + bb_info.dram_sr_exit_latency_100ns * 10; } } diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h index 6ce221098979..3a3dc2ce4c73 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h @@ -29,11 +29,6 @@ #include "clk_mgr_internal.h" -#define DCN3_2_DEFAULT_DET_SIZE 256 -#define DCN3_2_MAX_DET_SIZE 1152 -#define DCN3_2_MIN_DET_SIZE 128 -#define DCN3_2_MIN_COMPBUF_SIZE_KB 128 - void dcn32_build_wm_range_table_fpu(struct clk_mgr_internal *clk_mgr); void dcn32_helper_populate_phantom_dlg_params(struct dc *dc, @@ -41,9 +36,8 @@ void dcn32_helper_populate_phantom_dlg_params(struct dc *dc, display_e2e_pipe_params_st *pipes, int pipe_cnt); -bool dcn32_predict_pipe_split(struct dc_state *context, - display_pipe_params_st pipe, - int index); +uint8_t dcn32_predict_pipe_split(struct dc_state *context, + display_e2e_pipe_params_st *pipe_e2e); void insert_entry_into_table_sorted(struct _vcs_dpi_voltage_scaling_st *table, unsigned int *num_entries, @@ -77,4 +71,6 @@ int dcn32_find_dummy_latency_index_for_fw_based_mclk_switch(struct dc *dc, int pipe_cnt, int vlevel); +void dcn32_patch_dpm_table(struct clk_bw_params *bw_params); + #endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c index 6980f698eb23..75be1e1ce543 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c @@ -677,9 +677,9 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman dml_ceil((double) v->WritebackDelay[mode_lib->vba.VoltageLevel][k] / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]), 1)); - // Clamp to max OTG vstartup register limit - if (v->MaxVStartupLines[k] > 1023) - v->MaxVStartupLines[k] = 1023; + // Clamp to max OTG vstartup register limit + if (v->MaxVStartupLines[k] > 1023) + v->MaxVStartupLines[k] = 1023; #ifdef __DML_VBA_DEBUG__ dml_print("DML::%s: k=%d MaxVStartupLines = %d\n", __func__, k, v->MaxVStartupLines[k]); @@ -2004,6 +2004,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading, mode_lib->vba.DISPCLKRampingMargin, mode_lib->vba.DISPCLKDPPCLKVCOSpeed, + mode_lib->vba.NumberOfDSCSlices[k], /* Output */ &v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.TotalAvailablePipesSupportNoDSC, @@ -2026,6 +2027,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading, mode_lib->vba.DISPCLKRampingMargin, mode_lib->vba.DISPCLKDPPCLKVCOSpeed, + mode_lib->vba.NumberOfDSCSlices[k], /* Output */ &v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.TotalAvailablePipesSupportDSC, @@ -3529,7 +3531,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l &v->FCLKChangeSupport[i][j], &v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.dummy_single2[1], // double *MinActiveFCLKChangeLatencySupported &mode_lib->vba.USRRetrainingSupport[i][j], - mode_lib->vba.ActiveDRAMClockChangeLatencyMargin); + mode_lib->vba.ActiveDRAMClockChangeLatencyMarginPerState[i][j]); } } } // End of Prefetch Check diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c index 365d290bba99..ad66e241f9ae 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c @@ -721,8 +721,8 @@ void dml32_CalculateSwathWidth( unsigned int surface_width_ub_l; unsigned int surface_height_ub_l; - unsigned int surface_width_ub_c; - unsigned int surface_height_ub_c; + unsigned int surface_width_ub_c = 0; + unsigned int surface_height_ub_c = 0; #ifdef __DML_VBA_DEBUG__ dml_print("DML::%s: ForceSingleDPP = %d\n", __func__, ForceSingleDPP); @@ -786,21 +786,6 @@ void dml32_CalculateSwathWidth( surface_width_ub_l = dml_ceil(SurfaceWidthY[k], Read256BytesBlockWidthY[k]); surface_height_ub_l = dml_ceil(SurfaceHeightY[k], Read256BytesBlockHeightY[k]); - surface_width_ub_c = dml_ceil(SurfaceWidthC[k], Read256BytesBlockWidthC[k]); - surface_height_ub_c = dml_ceil(SurfaceHeightC[k], Read256BytesBlockHeightC[k]); - -#ifdef __DML_VBA_DEBUG__ - dml_print("DML::%s: k=%d surface_width_ub_l=%0d\n", __func__, k, surface_width_ub_l); - dml_print("DML::%s: k=%d surface_height_ub_l=%0d\n", __func__, k, surface_height_ub_l); - dml_print("DML::%s: k=%d surface_width_ub_c=%0d\n", __func__, k, surface_width_ub_c); - dml_print("DML::%s: k=%d surface_height_ub_c=%0d\n", __func__, k, surface_height_ub_c); - dml_print("DML::%s: k=%d Read256BytesBlockWidthY=%0d\n", __func__, k, Read256BytesBlockWidthY[k]); - dml_print("DML::%s: k=%d Read256BytesBlockHeightY=%0d\n", __func__, k, Read256BytesBlockHeightY[k]); - dml_print("DML::%s: k=%d Read256BytesBlockWidthC=%0d\n", __func__, k, Read256BytesBlockWidthC[k]); - dml_print("DML::%s: k=%d Read256BytesBlockHeightC=%0d\n", __func__, k, Read256BytesBlockHeightC[k]); - dml_print("DML::%s: k=%d ViewportStationary=%0d\n", __func__, k, ViewportStationary[k]); - dml_print("DML::%s: k=%d DPPPerSurface=%0d\n", __func__, k, DPPPerSurface[k]); -#endif if (!IsVertical(SourceRotation[k])) { MaximumSwathHeightY[k] = Read256BytesBlockHeightY[k]; @@ -820,6 +805,7 @@ void dml32_CalculateSwathWidth( Read256BytesBlockWidthY[k]); } if (BytePerPixC[k] > 0) { + surface_width_ub_c = dml_ceil(SurfaceWidthC[k], Read256BytesBlockWidthC[k]); if (ViewportStationary[k] && DPPPerSurface[k] == 1) { swath_width_chroma_ub[k] = dml_min(surface_width_ub_c, dml_floor(ViewportXStartC[k] + SwathWidthC[k] + @@ -850,6 +836,7 @@ void dml32_CalculateSwathWidth( Read256BytesBlockHeightY[k]) + Read256BytesBlockHeightY[k]); } if (BytePerPixC[k] > 0) { + surface_height_ub_c = dml_ceil(SurfaceHeightC[k], Read256BytesBlockHeightC[k]); if (ViewportStationary[k] && DPPPerSurface[k] == 1) { swath_width_chroma_ub[k] = dml_min(surface_height_ub_c, dml_floor(ViewportYStartC[k] + SwathWidthC[k] + @@ -868,6 +855,16 @@ void dml32_CalculateSwathWidth( } #ifdef __DML_VBA_DEBUG__ + dml_print("DML::%s: k=%d surface_width_ub_l=%0d\n", __func__, k, surface_width_ub_l); + dml_print("DML::%s: k=%d surface_height_ub_l=%0d\n", __func__, k, surface_height_ub_l); + dml_print("DML::%s: k=%d surface_width_ub_c=%0d\n", __func__, k, surface_width_ub_c); + dml_print("DML::%s: k=%d surface_height_ub_c=%0d\n", __func__, k, surface_height_ub_c); + dml_print("DML::%s: k=%d Read256BytesBlockWidthY=%0d\n", __func__, k, Read256BytesBlockWidthY[k]); + dml_print("DML::%s: k=%d Read256BytesBlockHeightY=%0d\n", __func__, k, Read256BytesBlockHeightY[k]); + dml_print("DML::%s: k=%d Read256BytesBlockWidthC=%0d\n", __func__, k, Read256BytesBlockWidthC[k]); + dml_print("DML::%s: k=%d Read256BytesBlockHeightC=%0d\n", __func__, k, Read256BytesBlockHeightC[k]); + dml_print("DML::%s: k=%d ViewportStationary=%0d\n", __func__, k, ViewportStationary[k]); + dml_print("DML::%s: k=%d DPPPerSurface=%0d\n", __func__, k, DPPPerSurface[k]); dml_print("DML::%s: k=%d swath_width_luma_ub=%0d\n", __func__, k, swath_width_luma_ub[k]); dml_print("DML::%s: k=%d swath_width_chroma_ub=%0d\n", __func__, k, swath_width_chroma_ub[k]); dml_print("DML::%s: k=%d MaximumSwathHeightY=%0d\n", __func__, k, MaximumSwathHeightY[k]); @@ -1196,6 +1193,7 @@ void dml32_CalculateODMMode( double DISPCLKDPPCLKDSCCLKDownSpreading, double DISPCLKRampingMargin, double DISPCLKDPPCLKVCOSpeed, + unsigned int NumberOfDSCSlices, /* Output */ bool *TotalAvailablePipesSupport, @@ -1231,7 +1229,8 @@ void dml32_CalculateODMMode( if (!(Output == dm_hdmi || Output == dm_dp || Output == dm_edp) && (ODMUse == dm_odm_combine_policy_4to1 || ((SurfaceRequiredDISPCLKWithODMCombineTwoToOne > StateDispclk || - (DSCEnable && (HActive > 2 * MaximumPixelsPerLinePerDSCUnit)))))) { + (DSCEnable && (HActive > 2 * MaximumPixelsPerLinePerDSCUnit)) + || NumberOfDSCSlices > 8)))) { if (TotalNumberOfActiveDPP + 4 <= MaxNumDPP) { *ODMMode = dm_odm_combine_mode_4to1; *RequiredDISPCLKPerSurface = SurfaceRequiredDISPCLKWithODMCombineFourToOne; @@ -1242,7 +1241,8 @@ void dml32_CalculateODMMode( } else if (Output != dm_hdmi && (ODMUse == dm_odm_combine_policy_2to1 || (((SurfaceRequiredDISPCLKWithoutODMCombine > StateDispclk && SurfaceRequiredDISPCLKWithODMCombineTwoToOne <= StateDispclk) || - (DSCEnable && (HActive > MaximumPixelsPerLinePerDSCUnit)))))) { + (DSCEnable && (HActive > MaximumPixelsPerLinePerDSCUnit)) + || (NumberOfDSCSlices <= 8 && NumberOfDSCSlices > 4))))) { if (TotalNumberOfActiveDPP + 2 <= MaxNumDPP) { *ODMMode = dm_odm_combine_mode_2to1; *RequiredDISPCLKPerSurface = SurfaceRequiredDISPCLKWithODMCombineTwoToOne; @@ -1896,7 +1896,7 @@ void dml32_CalculateSurfaceSizeInMall( if (UseMALLForStaticScreen[k] == dm_use_mall_static_screen_enable) TotalSurfaceSizeInMALL = TotalSurfaceSizeInMALL + SurfaceSizeInMALL[k]; } - *ExceededMALLSize = (TotalSurfaceSizeInMALL <= MALLAllocatedForDCN * 1024 * 1024 ? false : true); + *ExceededMALLSize = (TotalSurfaceSizeInMALL > MALLAllocatedForDCN * 1024 * 1024); } // CalculateSurfaceSizeInMall void dml32_CalculateVMRowAndSwath( @@ -4260,7 +4260,7 @@ void dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport( double ActiveClockChangeLatencyHidingY; double ActiveClockChangeLatencyHidingC; double ActiveClockChangeLatencyHiding; - double EffectiveDETBufferSizeY; + double EffectiveDETBufferSizeY; double ActiveFCLKChangeLatencyMargin[DC__NUM_DPP__MAX]; double USRRetrainingLatencyMargin[DC__NUM_DPP__MAX]; double TotalPixelBW = 0.0; @@ -4643,10 +4643,6 @@ void dml32_CalculateMinAndMaxPrefetchMode( } else if (AllowForPStateChangeOrStutterInVBlankFinal == dm_prefetch_support_uclk_fclk_and_stutter) { *MinPrefetchMode = 0; *MaxPrefetchMode = 0; - } else if (AllowForPStateChangeOrStutterInVBlankFinal == - dm_prefetch_support_uclk_fclk_and_stutter_if_possible) { - *MinPrefetchMode = 0; - *MaxPrefetchMode = 3; } else { *MinPrefetchMode = 0; *MaxPrefetchMode = 3; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h index 0b427d89b3c5..55cead0d4237 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h @@ -228,6 +228,7 @@ void dml32_CalculateODMMode( double DISPCLKDPPCLKDSCCLKDownSpreading, double DISPCLKRampingMargin, double DISPCLKDPPCLKVCOSpeed, + unsigned int NumberOfDSCSlices, /* Output */ bool *TotalAvailablePipesSupport, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c index c87091683b5d..dd90f241e906 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c @@ -489,6 +489,7 @@ void dcn321_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_p if ((int)(dcn3_21_soc.urgent_latency_us * 1000) != dc->bb_overrides.urgent_latency_ns && dc->bb_overrides.urgent_latency_ns) { dcn3_21_soc.urgent_latency_us = dc->bb_overrides.urgent_latency_ns / 1000.0; + dcn3_21_soc.urgent_latency_pixel_data_only_us = dc->bb_overrides.urgent_latency_ns / 1000.0; } if ((int)(dcn3_21_soc.dram_clock_change_latency_us * 1000) @@ -518,13 +519,16 @@ void dcn321_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_p if (dc->ctx->dc_bios->funcs->get_soc_bb_info(dc->ctx->dc_bios, &bb_info) == BP_RESULT_OK) { if (bb_info.dram_clock_change_latency_100ns > 0) - dcn3_21_soc.dram_clock_change_latency_us = bb_info.dram_clock_change_latency_100ns * 10; + dcn3_21_soc.dram_clock_change_latency_us = + bb_info.dram_clock_change_latency_100ns * 10; - if (bb_info.dram_sr_enter_exit_latency_100ns > 0) - dcn3_21_soc.sr_enter_plus_exit_time_us = bb_info.dram_sr_enter_exit_latency_100ns * 10; + if (bb_info.dram_sr_enter_exit_latency_100ns > 0) + dcn3_21_soc.sr_enter_plus_exit_time_us = + bb_info.dram_sr_enter_exit_latency_100ns * 10; - if (bb_info.dram_sr_exit_latency_100ns > 0) - dcn3_21_soc.sr_exit_time_us = bb_info.dram_sr_exit_latency_100ns * 10; + if (bb_info.dram_sr_exit_latency_100ns > 0) + dcn3_21_soc.sr_exit_time_us = + bb_info.dram_sr_exit_latency_100ns * 10; } } diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h index e8b094006d95..f33a8879b05a 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h @@ -26,6 +26,16 @@ #include "dc_features.h" #include "display_mode_enums.h" +/** + * DOC: overview + * + * Most of the DML code is automatically generated and tested via hardware + * description language. Usually, we use the reference _vcs_dpi in the code + * where VCS means "Verilog Compiled Simulator" and DPI stands for "Direct + * Programmer Interface". In other words, those structs can be used to + * interface with Verilog with other languages such as C. + */ + #ifndef __DISPLAY_MODE_STRUCTS_H__ #define __DISPLAY_MODE_STRUCTS_H__ @@ -159,13 +169,20 @@ struct _vcs_dpi_voltage_scaling_st { double dtbclk_mhz; }; +/** + * _vcs_dpi_soc_bounding_box_st: SOC definitions + * + * This struct maintains the SOC Bounding Box information for the ASIC; it + * defines things such as clock, voltage, performance, etc. Usually, we load + * these values from VBIOS; if something goes wrong, we use some hard-coded + * values, which will enable the ASIC to light up with limitations. + */ struct _vcs_dpi_soc_bounding_box_st { struct _vcs_dpi_voltage_scaling_st clock_limits[DC__VOLTAGE_STATES]; - /* - * This is a temporary stash for updating @clock_limits with the PMFW - * clock table. Do not use outside of *update_bw_boudning_box functions. + /** + * @num_states: It represents the total of Display Power Management + * (DPM) supported by the specific ASIC. */ - struct _vcs_dpi_voltage_scaling_st _clock_tmp[DC__VOLTAGE_STATES]; unsigned int num_states; double sr_exit_time_us; double sr_enter_plus_exit_time_us; @@ -231,6 +248,14 @@ struct _vcs_dpi_soc_bounding_box_st { enum self_refresh_affinity allow_dram_self_refresh_or_dram_clock_change_in_vblank; }; +/** + * @_vcs_dpi_ip_params_st: IP configuraion for DCN blocks + * + * In this struct you can find the DCN configuration associated to the specific + * ASIC. For example, here we can save how many DPPs the ASIC is using and it + * is available. + * + */ struct _vcs_dpi_ip_params_st { bool use_min_dcfclk; bool clamp_min_dcfclk; @@ -283,6 +308,9 @@ struct _vcs_dpi_ip_params_st { unsigned int writeback_line_buffer_chroma_buffer_size; unsigned int max_page_table_levels; + /** + * @max_num_dpp: Maximum number of DPP supported in the target ASIC. + */ unsigned int max_num_dpp; unsigned int max_num_otg; unsigned int cursor_chunk_size; @@ -482,6 +510,7 @@ struct _vcs_dpi_display_pipe_dest_params_st { unsigned int htotal; unsigned int vtotal; unsigned int vfront_porch; + unsigned int vblank_nom; unsigned int vactive; unsigned int hactive; unsigned int vstartup_start; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index 503e7d984ff0..03924aed8d5c 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -597,6 +597,7 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) mode_lib->vba.HTotal[mode_lib->vba.NumberOfActivePlanes] = dst->htotal; mode_lib->vba.VTotal[mode_lib->vba.NumberOfActivePlanes] = dst->vtotal; mode_lib->vba.VFrontPorch[mode_lib->vba.NumberOfActivePlanes] = dst->vfront_porch; + mode_lib->vba.VBlankNom[mode_lib->vba.NumberOfActivePlanes] = dst->vblank_nom; mode_lib->vba.DCCFractionOfZeroSizeRequestsLuma[mode_lib->vba.NumberOfActivePlanes] = src->dcc_fraction_of_zs_req_luma; mode_lib->vba.DCCFractionOfZeroSizeRequestsChroma[mode_lib->vba.NumberOfActivePlanes] = src->dcc_fraction_of_zs_req_chroma; mode_lib->vba.DCCEnable[mode_lib->vba.NumberOfActivePlanes] = diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h index 2051ddaa641a..630f3395e90a 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h @@ -312,6 +312,7 @@ struct vba_vars_st { unsigned int ActiveDPPs; unsigned int LBLatencyHidingSourceLinesY; unsigned int LBLatencyHidingSourceLinesC; + double ActiveDRAMClockChangeLatencyMarginPerState[DC__VOLTAGE_STATES][2][DC__NUM_DPP__MAX];// DML doesn't save active margin per state double ActiveDRAMClockChangeLatencyMargin[DC__NUM_DPP__MAX]; double CachedActiveDRAMClockChangeLatencyMargin[DC__NUM_DPP__MAX]; // Cache in dml_get_voltage_level for debug purposes only double MinActiveDRAMClockChangeMargin; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h index 479d7d83220c..072bd0539605 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h @@ -76,14 +76,9 @@ static inline double dml_floor(double a, double granularity) static inline double dml_round(double a) { - double round_pt = 0.5; - double ceil = dml_ceil(a, 1); - double floor = dml_floor(a, 1); + const double round_pt = 0.5; - if (a - floor >= round_pt) - return ceil; - else - return floor; + return dml_floor(a + round_pt, 1); } /* float diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml/dml_wrapper.c deleted file mode 100644 index b4b51e51fc25..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_wrapper.c +++ /dev/null @@ -1,1884 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "resource.h" -#include "core_types.h" -#include "dsc.h" -#include "clk_mgr.h" - -#ifndef DC_LOGGER_INIT -#define DC_LOGGER_INIT -#undef DC_LOG_WARNING -#define DC_LOG_WARNING -#endif - -#define DML_WRAPPER_TRANSLATION_ -#include "dml_wrapper_translation.c" -#undef DML_WRAPPER_TRANSLATION_ - -static bool is_dual_plane(enum surface_pixel_format format) -{ - return format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN || format == SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA; -} - -static void build_clamping_params(struct dc_stream_state *stream) -{ - stream->clamping.clamping_level = CLAMPING_FULL_RANGE; - stream->clamping.c_depth = stream->timing.display_color_depth; - stream->clamping.pixel_encoding = stream->timing.pixel_encoding; -} - -static void get_pixel_clock_parameters( - const struct pipe_ctx *pipe_ctx, - struct pixel_clk_params *pixel_clk_params) -{ - const struct dc_stream_state *stream = pipe_ctx->stream; - - /*TODO: is this halved for YCbCr 420? in that case we might want to move - * the pixel clock normalization for hdmi up to here instead of doing it - * in pll_adjust_pix_clk - */ - pixel_clk_params->requested_pix_clk_100hz = stream->timing.pix_clk_100hz; - pixel_clk_params->encoder_object_id = stream->link->link_enc->id; - pixel_clk_params->signal_type = pipe_ctx->stream->signal; - pixel_clk_params->controller_id = pipe_ctx->stream_res.tg->inst + 1; - /* TODO: un-hardcode*/ - pixel_clk_params->requested_sym_clk = LINK_RATE_LOW * - LINK_RATE_REF_FREQ_IN_KHZ; - pixel_clk_params->flags.ENABLE_SS = 0; - pixel_clk_params->color_depth = - stream->timing.display_color_depth; - pixel_clk_params->flags.DISPLAY_BLANKED = 1; - pixel_clk_params->flags.SUPPORT_YCBCR420 = (stream->timing.pixel_encoding == - PIXEL_ENCODING_YCBCR420); - pixel_clk_params->pixel_encoding = stream->timing.pixel_encoding; - if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) { - pixel_clk_params->color_depth = COLOR_DEPTH_888; - } - if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) { - pixel_clk_params->requested_pix_clk_100hz = pixel_clk_params->requested_pix_clk_100hz / 2; - } - if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING) - pixel_clk_params->requested_pix_clk_100hz *= 2; - -} - -static void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream, - struct bit_depth_reduction_params *fmt_bit_depth) -{ - enum dc_dither_option option = stream->dither_option; - enum dc_pixel_encoding pixel_encoding = - stream->timing.pixel_encoding; - - memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth)); - - if (option == DITHER_OPTION_DEFAULT) { - switch (stream->timing.display_color_depth) { - case COLOR_DEPTH_666: - option = DITHER_OPTION_SPATIAL6; - break; - case COLOR_DEPTH_888: - option = DITHER_OPTION_SPATIAL8; - break; - case COLOR_DEPTH_101010: - option = DITHER_OPTION_SPATIAL10; - break; - default: - option = DITHER_OPTION_DISABLE; - } - } - - if (option == DITHER_OPTION_DISABLE) - return; - - if (option == DITHER_OPTION_TRUN6) { - fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; - fmt_bit_depth->flags.TRUNCATE_DEPTH = 0; - } else if (option == DITHER_OPTION_TRUN8 || - option == DITHER_OPTION_TRUN8_SPATIAL6 || - option == DITHER_OPTION_TRUN8_FM6) { - fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; - fmt_bit_depth->flags.TRUNCATE_DEPTH = 1; - } else if (option == DITHER_OPTION_TRUN10 || - option == DITHER_OPTION_TRUN10_SPATIAL6 || - option == DITHER_OPTION_TRUN10_SPATIAL8 || - option == DITHER_OPTION_TRUN10_FM8 || - option == DITHER_OPTION_TRUN10_FM6 || - option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { - fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; - fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; - } - - /* special case - Formatter can only reduce by 4 bits at most. - * When reducing from 12 to 6 bits, - * HW recommends we use trunc with round mode - * (if we did nothing, trunc to 10 bits would be used) - * note that any 12->10 bit reduction is ignored prior to DCE8, - * as the input was 10 bits. - */ - if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM || - option == DITHER_OPTION_SPATIAL6 || - option == DITHER_OPTION_FM6) { - fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; - fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; - fmt_bit_depth->flags.TRUNCATE_MODE = 1; - } - - /* spatial dither - * note that spatial modes 1-3 are never used - */ - if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM || - option == DITHER_OPTION_SPATIAL6 || - option == DITHER_OPTION_TRUN10_SPATIAL6 || - option == DITHER_OPTION_TRUN8_SPATIAL6) { - fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; - fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 0; - fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; - fmt_bit_depth->flags.RGB_RANDOM = - (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; - } else if (option == DITHER_OPTION_SPATIAL8_FRAME_RANDOM || - option == DITHER_OPTION_SPATIAL8 || - option == DITHER_OPTION_SPATIAL8_FM6 || - option == DITHER_OPTION_TRUN10_SPATIAL8 || - option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { - fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; - fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 1; - fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; - fmt_bit_depth->flags.RGB_RANDOM = - (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; - } else if (option == DITHER_OPTION_SPATIAL10_FRAME_RANDOM || - option == DITHER_OPTION_SPATIAL10 || - option == DITHER_OPTION_SPATIAL10_FM8 || - option == DITHER_OPTION_SPATIAL10_FM6) { - fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; - fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 2; - fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; - fmt_bit_depth->flags.RGB_RANDOM = - (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; - } - - if (option == DITHER_OPTION_SPATIAL6 || - option == DITHER_OPTION_SPATIAL8 || - option == DITHER_OPTION_SPATIAL10) { - fmt_bit_depth->flags.FRAME_RANDOM = 0; - } else { - fmt_bit_depth->flags.FRAME_RANDOM = 1; - } - - ////////////////////// - //// temporal dither - ////////////////////// - if (option == DITHER_OPTION_FM6 || - option == DITHER_OPTION_SPATIAL8_FM6 || - option == DITHER_OPTION_SPATIAL10_FM6 || - option == DITHER_OPTION_TRUN10_FM6 || - option == DITHER_OPTION_TRUN8_FM6 || - option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { - fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; - fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 0; - } else if (option == DITHER_OPTION_FM8 || - option == DITHER_OPTION_SPATIAL10_FM8 || - option == DITHER_OPTION_TRUN10_FM8) { - fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; - fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 1; - } else if (option == DITHER_OPTION_FM10) { - fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; - fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 2; - } - - fmt_bit_depth->pixel_encoding = pixel_encoding; -} - -/* Move this after the above function as VS complains about - * declaration issues for resource_build_bit_depth_reduction_params. - */ - -static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx) -{ - - get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->stream_res.pix_clk_params); - - if (pipe_ctx->clock_source) - pipe_ctx->clock_source->funcs->get_pix_clk_dividers( - pipe_ctx->clock_source, - &pipe_ctx->stream_res.pix_clk_params, - &pipe_ctx->pll_settings); - - pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->timing.pixel_encoding; - - resource_build_bit_depth_reduction_params(pipe_ctx->stream, - &pipe_ctx->stream->bit_depth_params); - build_clamping_params(pipe_ctx->stream); - - return DC_OK; -} - -bool dml_validate_dsc(struct dc *dc, struct dc_state *new_ctx) -{ - int i; - - /* Validate DSC config, dsc count validation is already done */ - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[i]; - struct dc_stream_state *stream = pipe_ctx->stream; - struct dsc_config dsc_cfg; - struct pipe_ctx *odm_pipe; - int opp_cnt = 1; - - for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) - opp_cnt++; - - /* Only need to validate top pipe */ - if (pipe_ctx->top_pipe || pipe_ctx->prev_odm_pipe || !stream || !stream->timing.flags.DSC) - continue; - - dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left - + stream->timing.h_border_right) / opp_cnt; - dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top - + stream->timing.v_border_bottom; - dsc_cfg.pixel_encoding = stream->timing.pixel_encoding; - dsc_cfg.color_depth = stream->timing.display_color_depth; - dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false; - dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg; - dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt; - - if (pipe_ctx->stream_res.dsc && !pipe_ctx->stream_res.dsc->funcs->dsc_validate_stream(pipe_ctx->stream_res.dsc, &dsc_cfg)) - return false; - } - return true; -} - -enum dc_status dml_build_mapped_resource(const struct dc *dc, struct dc_state *context, struct dc_stream_state *stream) -{ - enum dc_status status = DC_OK; - struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream(&context->res_ctx, stream); - - if (!pipe_ctx) - return DC_ERROR_UNEXPECTED; - - - status = build_pipe_hw_param(pipe_ctx); - - return status; -} - -void dml_acquire_dsc(const struct dc *dc, - struct resource_context *res_ctx, - struct display_stream_compressor **dsc, - int pipe_idx) -{ - int i; - const struct resource_pool *pool = dc->res_pool; - struct display_stream_compressor *dsc_old = dc->current_state->res_ctx.pipe_ctx[pipe_idx].stream_res.dsc; - - ASSERT(*dsc == NULL); /* If this ASSERT fails, dsc was not released properly */ - *dsc = NULL; - - /* Always do 1-to-1 mapping when number of DSCs is same as number of pipes */ - if (pool->res_cap->num_dsc == pool->res_cap->num_opp) { - *dsc = pool->dscs[pipe_idx]; - res_ctx->is_dsc_acquired[pipe_idx] = true; - return; - } - - /* Return old DSC to avoid the need for redo it */ - if (dsc_old && !res_ctx->is_dsc_acquired[dsc_old->inst]) { - *dsc = dsc_old; - res_ctx->is_dsc_acquired[dsc_old->inst] = true; - return ; - } - - /* Find first free DSC */ - for (i = 0; i < pool->res_cap->num_dsc; i++) - if (!res_ctx->is_dsc_acquired[i]) { - *dsc = pool->dscs[i]; - res_ctx->is_dsc_acquired[i] = true; - break; - } -} - -static bool dml_split_stream_for_mpc_or_odm( - const struct dc *dc, - struct resource_context *res_ctx, - struct pipe_ctx *pri_pipe, - struct pipe_ctx *sec_pipe, - bool odm) -{ - int pipe_idx = sec_pipe->pipe_idx; - const struct resource_pool *pool = dc->res_pool; - - *sec_pipe = *pri_pipe; - - sec_pipe->pipe_idx = pipe_idx; - sec_pipe->plane_res.mi = pool->mis[pipe_idx]; - sec_pipe->plane_res.hubp = pool->hubps[pipe_idx]; - sec_pipe->plane_res.ipp = pool->ipps[pipe_idx]; - sec_pipe->plane_res.xfm = pool->transforms[pipe_idx]; - sec_pipe->plane_res.dpp = pool->dpps[pipe_idx]; - sec_pipe->plane_res.mpcc_inst = pool->dpps[pipe_idx]->inst; - sec_pipe->stream_res.dsc = NULL; - if (odm) { - if (pri_pipe->next_odm_pipe) { - ASSERT(pri_pipe->next_odm_pipe != sec_pipe); - sec_pipe->next_odm_pipe = pri_pipe->next_odm_pipe; - sec_pipe->next_odm_pipe->prev_odm_pipe = sec_pipe; - } - if (pri_pipe->top_pipe && pri_pipe->top_pipe->next_odm_pipe) { - pri_pipe->top_pipe->next_odm_pipe->bottom_pipe = sec_pipe; - sec_pipe->top_pipe = pri_pipe->top_pipe->next_odm_pipe; - } - if (pri_pipe->bottom_pipe && pri_pipe->bottom_pipe->next_odm_pipe) { - pri_pipe->bottom_pipe->next_odm_pipe->top_pipe = sec_pipe; - sec_pipe->bottom_pipe = pri_pipe->bottom_pipe->next_odm_pipe; - } - pri_pipe->next_odm_pipe = sec_pipe; - sec_pipe->prev_odm_pipe = pri_pipe; - ASSERT(sec_pipe->top_pipe == NULL); - - if (!sec_pipe->top_pipe) - sec_pipe->stream_res.opp = pool->opps[pipe_idx]; - else - sec_pipe->stream_res.opp = sec_pipe->top_pipe->stream_res.opp; - if (sec_pipe->stream->timing.flags.DSC == 1) { - dml_acquire_dsc(dc, res_ctx, &sec_pipe->stream_res.dsc, pipe_idx); - ASSERT(sec_pipe->stream_res.dsc); - if (sec_pipe->stream_res.dsc == NULL) - return false; - } - } else { - if (pri_pipe->bottom_pipe) { - ASSERT(pri_pipe->bottom_pipe != sec_pipe); - sec_pipe->bottom_pipe = pri_pipe->bottom_pipe; - sec_pipe->bottom_pipe->top_pipe = sec_pipe; - } - pri_pipe->bottom_pipe = sec_pipe; - sec_pipe->top_pipe = pri_pipe; - - ASSERT(pri_pipe->plane_state); - } - - return true; -} - -static struct pipe_ctx *dml_find_split_pipe( - struct dc *dc, - struct dc_state *context, - int old_index) -{ - struct pipe_ctx *pipe = NULL; - int i; - - if (old_index >= 0 && context->res_ctx.pipe_ctx[old_index].stream == NULL) { - pipe = &context->res_ctx.pipe_ctx[old_index]; - pipe->pipe_idx = old_index; - } - - if (!pipe) - for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) { - if (dc->current_state->res_ctx.pipe_ctx[i].top_pipe == NULL - && dc->current_state->res_ctx.pipe_ctx[i].prev_odm_pipe == NULL) { - if (context->res_ctx.pipe_ctx[i].stream == NULL) { - pipe = &context->res_ctx.pipe_ctx[i]; - pipe->pipe_idx = i; - break; - } - } - } - - /* - * May need to fix pipes getting tossed from 1 opp to another on flip - * Add for debugging transient underflow during topology updates: - * ASSERT(pipe); - */ - if (!pipe) - for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) { - if (context->res_ctx.pipe_ctx[i].stream == NULL) { - pipe = &context->res_ctx.pipe_ctx[i]; - pipe->pipe_idx = i; - break; - } - } - - return pipe; -} - -static void dml_release_dsc(struct resource_context *res_ctx, - const struct resource_pool *pool, - struct display_stream_compressor **dsc) -{ - int i; - - for (i = 0; i < pool->res_cap->num_dsc; i++) - if (pool->dscs[i] == *dsc) { - res_ctx->is_dsc_acquired[i] = false; - *dsc = NULL; - break; - } -} - -static int dml_get_num_mpc_splits(struct pipe_ctx *pipe) -{ - int mpc_split_count = 0; - struct pipe_ctx *other_pipe = pipe->bottom_pipe; - - while (other_pipe && other_pipe->plane_state == pipe->plane_state) { - mpc_split_count++; - other_pipe = other_pipe->bottom_pipe; - } - other_pipe = pipe->top_pipe; - while (other_pipe && other_pipe->plane_state == pipe->plane_state) { - mpc_split_count++; - other_pipe = other_pipe->top_pipe; - } - - return mpc_split_count; -} - -static bool dml_enough_pipes_for_subvp(struct dc *dc, - struct dc_state *context) -{ - int i = 0; - int num_pipes = 0; - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - - if (pipe->stream && pipe->plane_state) - num_pipes++; - } - - // Sub-VP only possible if the number of "real" pipes is - // less than or equal to half the number of available pipes - if (num_pipes * 2 > dc->res_pool->pipe_count) - return false; - - return true; -} - -static int dml_validate_apply_pipe_split_flags( - struct dc *dc, - struct dc_state *context, - int vlevel, - int *split, - bool *merge) -{ - int i, pipe_idx, vlevel_split; - int plane_count = 0; - bool force_split = false; - bool avoid_split = dc->debug.pipe_split_policy == MPC_SPLIT_AVOID; - struct vba_vars_st *v = &context->bw_ctx.dml.vba; - int max_mpc_comb = v->maxMpcComb; - - if (context->stream_count > 1) { - if (dc->debug.pipe_split_policy == MPC_SPLIT_AVOID_MULT_DISP) - avoid_split = true; - } else if (dc->debug.force_single_disp_pipe_split) - force_split = true; - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - - /** - * Workaround for avoiding pipe-split in cases where we'd split - * planes that are too small, resulting in splits that aren't - * valid for the scaler. - */ - if (pipe->plane_state && - (pipe->plane_state->dst_rect.width <= 16 || - pipe->plane_state->dst_rect.height <= 16 || - pipe->plane_state->src_rect.width <= 16 || - pipe->plane_state->src_rect.height <= 16)) - avoid_split = true; - - /* TODO: fix dc bugs and remove this split threshold thing */ - if (pipe->stream && !pipe->prev_odm_pipe && - (!pipe->top_pipe || pipe->top_pipe->plane_state != pipe->plane_state)) - ++plane_count; - } - if (plane_count > dc->res_pool->pipe_count / 2) - avoid_split = true; - - /* W/A: Mode timing with borders may not work well with pipe split, avoid for this corner case */ - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - struct dc_crtc_timing timing; - - if (!pipe->stream) - continue; - else { - timing = pipe->stream->timing; - if (timing.h_border_left + timing.h_border_right - + timing.v_border_top + timing.v_border_bottom > 0) { - avoid_split = true; - break; - } - } - } - - /* Avoid split loop looks for lowest voltage level that allows most unsplit pipes possible */ - if (avoid_split) { - for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { - if (!context->res_ctx.pipe_ctx[i].stream) - continue; - - for (vlevel_split = vlevel; vlevel <= context->bw_ctx.dml.soc.num_states; vlevel++) - if (v->NoOfDPP[vlevel][0][pipe_idx] == 1 && - v->ModeSupport[vlevel][0]) - break; - /* Impossible to not split this pipe */ - if (vlevel > context->bw_ctx.dml.soc.num_states) - vlevel = vlevel_split; - else - max_mpc_comb = 0; - pipe_idx++; - } - v->maxMpcComb = max_mpc_comb; - } - - /* Split loop sets which pipe should be split based on dml outputs and dc flags */ - for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - int pipe_plane = v->pipe_plane[pipe_idx]; - bool split4mpc = context->stream_count == 1 && plane_count == 1 - && dc->config.enable_4to1MPC && dc->res_pool->pipe_count >= 4; - - if (!context->res_ctx.pipe_ctx[i].stream) - continue; - - if (split4mpc || v->NoOfDPP[vlevel][max_mpc_comb][pipe_plane] == 4) - split[i] = 4; - else if (force_split || v->NoOfDPP[vlevel][max_mpc_comb][pipe_plane] == 2) - split[i] = 2; - - if ((pipe->stream->view_format == - VIEW_3D_FORMAT_SIDE_BY_SIDE || - pipe->stream->view_format == - VIEW_3D_FORMAT_TOP_AND_BOTTOM) && - (pipe->stream->timing.timing_3d_format == - TIMING_3D_FORMAT_TOP_AND_BOTTOM || - pipe->stream->timing.timing_3d_format == - TIMING_3D_FORMAT_SIDE_BY_SIDE)) - split[i] = 2; - if (dc->debug.force_odm_combine & (1 << pipe->stream_res.tg->inst)) { - split[i] = 2; - v->ODMCombineEnablePerState[vlevel][pipe_plane] = dm_odm_combine_mode_2to1; - } - if (dc->debug.force_odm_combine_4to1 & (1 << pipe->stream_res.tg->inst)) { - split[i] = 4; - v->ODMCombineEnablePerState[vlevel][pipe_plane] = dm_odm_combine_mode_4to1; - } - /*420 format workaround*/ - if (pipe->stream->timing.h_addressable > 7680 && - pipe->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) { - split[i] = 4; - } - - v->ODMCombineEnabled[pipe_plane] = - v->ODMCombineEnablePerState[vlevel][pipe_plane]; - - if (v->ODMCombineEnabled[pipe_plane] == dm_odm_combine_mode_disabled) { - if (dml_get_num_mpc_splits(pipe) == 1) { - /*If need split for mpc but 2 way split already*/ - if (split[i] == 4) - split[i] = 2; /* 2 -> 4 MPC */ - else if (split[i] == 2) - split[i] = 0; /* 2 -> 2 MPC */ - else if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state) - merge[i] = true; /* 2 -> 1 MPC */ - } else if (dml_get_num_mpc_splits(pipe) == 3) { - /*If need split for mpc but 4 way split already*/ - if (split[i] == 2 && ((pipe->top_pipe && !pipe->top_pipe->top_pipe) - || !pipe->bottom_pipe)) { - merge[i] = true; /* 4 -> 2 MPC */ - } else if (split[i] == 0 && pipe->top_pipe && - pipe->top_pipe->plane_state == pipe->plane_state) - merge[i] = true; /* 4 -> 1 MPC */ - split[i] = 0; - } else if (dml_get_num_mpc_splits(pipe)) { - /* ODM -> MPC transition */ - if (pipe->prev_odm_pipe) { - split[i] = 0; - merge[i] = true; - } - } - } else { - if (dml_get_num_mpc_splits(pipe) == 1) { - /*If need split for odm but 2 way split already*/ - if (split[i] == 4) - split[i] = 2; /* 2 -> 4 ODM */ - else if (split[i] == 2) - split[i] = 0; /* 2 -> 2 ODM */ - else if (pipe->prev_odm_pipe) { - ASSERT(0); /* NOT expected yet */ - merge[i] = true; /* exit ODM */ - } - } else if (dml_get_num_mpc_splits(pipe) == 3) { - /*If need split for odm but 4 way split already*/ - if (split[i] == 2 && ((pipe->prev_odm_pipe && !pipe->prev_odm_pipe->prev_odm_pipe) - || !pipe->next_odm_pipe)) { - ASSERT(0); /* NOT expected yet */ - merge[i] = true; /* 4 -> 2 ODM */ - } else if (split[i] == 0 && pipe->prev_odm_pipe) { - ASSERT(0); /* NOT expected yet */ - merge[i] = true; /* exit ODM */ - } - split[i] = 0; - } else if (dml_get_num_mpc_splits(pipe)) { - /* MPC -> ODM transition */ - ASSERT(0); /* NOT expected yet */ - if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state) { - split[i] = 0; - merge[i] = true; - } - } - } - - /* Adjust dppclk when split is forced, do not bother with dispclk */ - if (split[i] != 0 && v->NoOfDPP[vlevel][max_mpc_comb][pipe_idx] == 1) - v->RequiredDPPCLK[vlevel][max_mpc_comb][pipe_idx] /= 2; - pipe_idx++; - } - - return vlevel; -} - -static void dml_set_phantom_stream_timing(struct dc *dc, - struct dc_state *context, - struct pipe_ctx *ref_pipe, - struct dc_stream_state *phantom_stream) -{ - // phantom_vactive = blackout (latency + margin) + fw_processing_delays + pstate allow width - uint32_t phantom_vactive_us = context->bw_ctx.dml.soc.dram_clock_change_latency_us + 60 + - dc->caps.subvp_fw_processing_delay_us + - dc->caps.subvp_pstate_allow_width_us; - uint32_t phantom_vactive = ((double)phantom_vactive_us/1000000) * - (ref_pipe->stream->timing.pix_clk_100hz * 100) / - (double)ref_pipe->stream->timing.h_total; - uint32_t phantom_bp = ref_pipe->pipe_dlg_param.vstartup_start; - - phantom_stream->dst.y = 0; - phantom_stream->dst.height = phantom_vactive; - phantom_stream->src.y = 0; - phantom_stream->src.height = phantom_vactive; - - phantom_stream->timing.v_addressable = phantom_vactive; - phantom_stream->timing.v_front_porch = 1; - phantom_stream->timing.v_total = phantom_stream->timing.v_addressable + - phantom_stream->timing.v_front_porch + - phantom_stream->timing.v_sync_width + - phantom_bp; -} - -static struct dc_stream_state *dml_enable_phantom_stream(struct dc *dc, - struct dc_state *context, - struct pipe_ctx *ref_pipe) -{ - struct dc_stream_state *phantom_stream = NULL; - - phantom_stream = dc_create_stream_for_sink(ref_pipe->stream->sink); - phantom_stream->signal = SIGNAL_TYPE_VIRTUAL; - phantom_stream->dpms_off = true; - phantom_stream->mall_stream_config.type = SUBVP_PHANTOM; - phantom_stream->mall_stream_config.paired_stream = ref_pipe->stream; - ref_pipe->stream->mall_stream_config.type = SUBVP_MAIN; - ref_pipe->stream->mall_stream_config.paired_stream = phantom_stream; - - /* stream has limited viewport and small timing */ - memcpy(&phantom_stream->timing, &ref_pipe->stream->timing, sizeof(phantom_stream->timing)); - memcpy(&phantom_stream->src, &ref_pipe->stream->src, sizeof(phantom_stream->src)); - memcpy(&phantom_stream->dst, &ref_pipe->stream->dst, sizeof(phantom_stream->dst)); - dml_set_phantom_stream_timing(dc, context, ref_pipe, phantom_stream); - - dc_add_stream_to_ctx(dc, context, phantom_stream); - dc->hwss.apply_ctx_to_hw(dc, context); - return phantom_stream; -} - -static void dml_enable_phantom_plane(struct dc *dc, - struct dc_state *context, - struct dc_stream_state *phantom_stream, - struct pipe_ctx *main_pipe) -{ - struct dc_plane_state *phantom_plane = NULL; - struct dc_plane_state *prev_phantom_plane = NULL; - struct pipe_ctx *curr_pipe = main_pipe; - - while (curr_pipe) { - if (curr_pipe->top_pipe && curr_pipe->top_pipe->plane_state == curr_pipe->plane_state) - phantom_plane = prev_phantom_plane; - else - phantom_plane = dc_create_plane_state(dc); - - memcpy(&phantom_plane->address, &curr_pipe->plane_state->address, sizeof(phantom_plane->address)); - memcpy(&phantom_plane->scaling_quality, &curr_pipe->plane_state->scaling_quality, - sizeof(phantom_plane->scaling_quality)); - memcpy(&phantom_plane->src_rect, &curr_pipe->plane_state->src_rect, sizeof(phantom_plane->src_rect)); - memcpy(&phantom_plane->dst_rect, &curr_pipe->plane_state->dst_rect, sizeof(phantom_plane->dst_rect)); - memcpy(&phantom_plane->clip_rect, &curr_pipe->plane_state->clip_rect, sizeof(phantom_plane->clip_rect)); - memcpy(&phantom_plane->plane_size, &curr_pipe->plane_state->plane_size, - sizeof(phantom_plane->plane_size)); - memcpy(&phantom_plane->tiling_info, &curr_pipe->plane_state->tiling_info, - sizeof(phantom_plane->tiling_info)); - memcpy(&phantom_plane->dcc, &curr_pipe->plane_state->dcc, sizeof(phantom_plane->dcc)); - /* Currently compat_level is undefined in dc_state - * phantom_plane->compat_level = curr_pipe->plane_state->compat_level; - */ - phantom_plane->format = curr_pipe->plane_state->format; - phantom_plane->rotation = curr_pipe->plane_state->rotation; - phantom_plane->visible = curr_pipe->plane_state->visible; - - /* Shadow pipe has small viewport. */ - phantom_plane->clip_rect.y = 0; - phantom_plane->clip_rect.height = phantom_stream->timing.v_addressable; - - dc_add_plane_to_context(dc, phantom_stream, phantom_plane, context); - - curr_pipe = curr_pipe->bottom_pipe; - prev_phantom_plane = phantom_plane; - } -} - -static void dml_add_phantom_pipes(struct dc *dc, struct dc_state *context) -{ - int i = 0; - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - struct dc_stream_state *ref_stream = pipe->stream; - // Only construct phantom stream for top pipes that have plane enabled - if (!pipe->top_pipe && pipe->plane_state && pipe->stream && - pipe->stream->mall_stream_config.type == SUBVP_NONE) { - struct dc_stream_state *phantom_stream = NULL; - - phantom_stream = dml_enable_phantom_stream(dc, context, pipe); - dml_enable_phantom_plane(dc, context, phantom_stream, pipe); - } - } - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - - if (pipe->plane_state && pipe->stream && - pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { - pipe->stream->use_dynamic_meta = false; - pipe->plane_state->flip_immediate = false; - if (!resource_build_scaling_params(pipe)) { - // Log / remove phantom pipes since failed to build scaling params - } - } - } -} - -static void dml_remove_phantom_pipes(struct dc *dc, struct dc_state *context) -{ - int i; - bool removed_pipe = false; - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - // build scaling params for phantom pipes - if (pipe->plane_state && pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { - dc_rem_all_planes_for_stream(dc, pipe->stream, context); - dc_remove_stream_from_ctx(dc, context, pipe->stream); - removed_pipe = true; - } - - // Clear all phantom stream info - if (pipe->stream) { - pipe->stream->mall_stream_config.type = SUBVP_NONE; - pipe->stream->mall_stream_config.paired_stream = NULL; - } - } - if (removed_pipe) - dc->hwss.apply_ctx_to_hw(dc, context); -} - -/* - * If the input state contains no upstream planes for a particular pipe (i.e. only timing) - * we need to populate some "conservative" plane information as DML cannot handle "no planes" - */ -static void populate_default_plane_from_timing(const struct dc_crtc_timing *timing, struct _vcs_dpi_display_pipe_params_st *pipe) -{ - pipe->src.is_hsplit = pipe->dest.odm_combine != dm_odm_combine_mode_disabled; - pipe->src.source_scan = dm_horz; - pipe->src.sw_mode = dm_sw_4kb_s; - pipe->src.macro_tile_size = dm_64k_tile; - pipe->src.viewport_width = timing->h_addressable; - if (pipe->src.viewport_width > 1920) - pipe->src.viewport_width = 1920; - pipe->src.viewport_height = timing->v_addressable; - if (pipe->src.viewport_height > 1080) - pipe->src.viewport_height = 1080; - pipe->src.surface_height_y = pipe->src.viewport_height; - pipe->src.surface_width_y = pipe->src.viewport_width; - pipe->src.surface_height_c = pipe->src.viewport_height; - pipe->src.surface_width_c = pipe->src.viewport_width; - pipe->src.data_pitch = ((pipe->src.viewport_width + 255) / 256) * 256; - pipe->src.source_format = dm_444_32; - pipe->dest.recout_width = pipe->src.viewport_width; - pipe->dest.recout_height = pipe->src.viewport_height; - pipe->dest.full_recout_width = pipe->dest.recout_width; - pipe->dest.full_recout_height = pipe->dest.recout_height; - pipe->scale_ratio_depth.lb_depth = dm_lb_16; - pipe->scale_ratio_depth.hscl_ratio = 1.0; - pipe->scale_ratio_depth.vscl_ratio = 1.0; - pipe->scale_ratio_depth.scl_enable = 0; - pipe->scale_taps.htaps = 1; - pipe->scale_taps.vtaps = 1; - pipe->dest.vtotal_min = timing->v_total; - pipe->dest.vtotal_max = timing->v_total; - - if (pipe->dest.odm_combine == dm_odm_combine_mode_2to1) { - pipe->src.viewport_width /= 2; - pipe->dest.recout_width /= 2; - } else if (pipe->dest.odm_combine == dm_odm_combine_mode_4to1) { - pipe->src.viewport_width /= 4; - pipe->dest.recout_width /= 4; - } - - pipe->src.dcc = false; - pipe->src.dcc_rate = 1; -} - -/* - * If the pipe is not blending (i.e. pipe_ctx->top pipe == null) then its - * hsplit group is equal to its own pipe ID - * Otherwise, all pipes part of the same blending tree have the same hsplit group - * ID as the top most pipe - * - * If the pipe ctx is ODM combined, then similar logic follows - */ -static void populate_hsplit_group_from_dc_pipe_ctx (const struct pipe_ctx *dc_pipe_ctx, struct _vcs_dpi_display_e2e_pipe_params_st *e2e_pipe) -{ - e2e_pipe->pipe.src.hsplit_grp = dc_pipe_ctx->pipe_idx; - - if (dc_pipe_ctx->top_pipe && dc_pipe_ctx->top_pipe->plane_state - == dc_pipe_ctx->plane_state) { - struct pipe_ctx *first_pipe = dc_pipe_ctx->top_pipe; - int split_idx = 0; - - while (first_pipe->top_pipe && first_pipe->top_pipe->plane_state - == dc_pipe_ctx->plane_state) { - first_pipe = first_pipe->top_pipe; - split_idx++; - } - - /* Treat 4to1 mpc combine as an mpo of 2 2-to-1 combines */ - if (split_idx == 0) - e2e_pipe->pipe.src.hsplit_grp = first_pipe->pipe_idx; - else if (split_idx == 1) - e2e_pipe->pipe.src.hsplit_grp = dc_pipe_ctx->pipe_idx; - else if (split_idx == 2) - e2e_pipe->pipe.src.hsplit_grp = dc_pipe_ctx->top_pipe->pipe_idx; - - } else if (dc_pipe_ctx->prev_odm_pipe) { - struct pipe_ctx *first_pipe = dc_pipe_ctx->prev_odm_pipe; - - while (first_pipe->prev_odm_pipe) - first_pipe = first_pipe->prev_odm_pipe; - e2e_pipe->pipe.src.hsplit_grp = first_pipe->pipe_idx; - } -} - -static void populate_dml_from_dc_pipe_ctx (const struct pipe_ctx *dc_pipe_ctx, struct _vcs_dpi_display_e2e_pipe_params_st *e2e_pipe, int always_scale) -{ - const struct dc_plane_state *pln = dc_pipe_ctx->plane_state; - const struct scaler_data *scl = &dc_pipe_ctx->plane_res.scl_data; - - e2e_pipe->pipe.src.immediate_flip = pln->flip_immediate; - e2e_pipe->pipe.src.is_hsplit = (dc_pipe_ctx->bottom_pipe && dc_pipe_ctx->bottom_pipe->plane_state == pln) - || (dc_pipe_ctx->top_pipe && dc_pipe_ctx->top_pipe->plane_state == pln) - || e2e_pipe->pipe.dest.odm_combine != dm_odm_combine_mode_disabled; - - /* stereo is not split */ - if (pln->stereo_format == PLANE_STEREO_FORMAT_SIDE_BY_SIDE || - pln->stereo_format == PLANE_STEREO_FORMAT_TOP_AND_BOTTOM) { - e2e_pipe->pipe.src.is_hsplit = false; - e2e_pipe->pipe.src.hsplit_grp = dc_pipe_ctx->pipe_idx; - } - - e2e_pipe->pipe.src.source_scan = pln->rotation == ROTATION_ANGLE_90 - || pln->rotation == ROTATION_ANGLE_270 ? dm_vert : dm_horz; - e2e_pipe->pipe.src.viewport_y_y = scl->viewport.y; - e2e_pipe->pipe.src.viewport_y_c = scl->viewport_c.y; - e2e_pipe->pipe.src.viewport_width = scl->viewport.width; - e2e_pipe->pipe.src.viewport_width_c = scl->viewport_c.width; - e2e_pipe->pipe.src.viewport_height = scl->viewport.height; - e2e_pipe->pipe.src.viewport_height_c = scl->viewport_c.height; - e2e_pipe->pipe.src.viewport_width_max = pln->src_rect.width; - e2e_pipe->pipe.src.viewport_height_max = pln->src_rect.height; - e2e_pipe->pipe.src.surface_width_y = pln->plane_size.surface_size.width; - e2e_pipe->pipe.src.surface_height_y = pln->plane_size.surface_size.height; - e2e_pipe->pipe.src.surface_width_c = pln->plane_size.chroma_size.width; - e2e_pipe->pipe.src.surface_height_c = pln->plane_size.chroma_size.height; - - if (pln->format == SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA - || pln->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { - e2e_pipe->pipe.src.data_pitch = pln->plane_size.surface_pitch; - e2e_pipe->pipe.src.data_pitch_c = pln->plane_size.chroma_pitch; - e2e_pipe->pipe.src.meta_pitch = pln->dcc.meta_pitch; - e2e_pipe->pipe.src.meta_pitch_c = pln->dcc.meta_pitch_c; - } else { - e2e_pipe->pipe.src.data_pitch = pln->plane_size.surface_pitch; - e2e_pipe->pipe.src.meta_pitch = pln->dcc.meta_pitch; - } - e2e_pipe->pipe.src.dcc = pln->dcc.enable; - e2e_pipe->pipe.src.dcc_rate = 1; - e2e_pipe->pipe.dest.recout_width = scl->recout.width; - e2e_pipe->pipe.dest.recout_height = scl->recout.height; - e2e_pipe->pipe.dest.full_recout_height = scl->recout.height; - e2e_pipe->pipe.dest.full_recout_width = scl->recout.width; - if (e2e_pipe->pipe.dest.odm_combine == dm_odm_combine_mode_2to1) - e2e_pipe->pipe.dest.full_recout_width *= 2; - else if (e2e_pipe->pipe.dest.odm_combine == dm_odm_combine_mode_4to1) - e2e_pipe->pipe.dest.full_recout_width *= 4; - else { - struct pipe_ctx *split_pipe = dc_pipe_ctx->bottom_pipe; - - while (split_pipe && split_pipe->plane_state == pln) { - e2e_pipe->pipe.dest.full_recout_width += split_pipe->plane_res.scl_data.recout.width; - split_pipe = split_pipe->bottom_pipe; - } - split_pipe = dc_pipe_ctx->top_pipe; - while (split_pipe && split_pipe->plane_state == pln) { - e2e_pipe->pipe.dest.full_recout_width += split_pipe->plane_res.scl_data.recout.width; - split_pipe = split_pipe->top_pipe; - } - } - - e2e_pipe->pipe.scale_ratio_depth.lb_depth = dm_lb_16; - e2e_pipe->pipe.scale_ratio_depth.hscl_ratio = (double) scl->ratios.horz.value / (1ULL<<32); - e2e_pipe->pipe.scale_ratio_depth.hscl_ratio_c = (double) scl->ratios.horz_c.value / (1ULL<<32); - e2e_pipe->pipe.scale_ratio_depth.vscl_ratio = (double) scl->ratios.vert.value / (1ULL<<32); - e2e_pipe->pipe.scale_ratio_depth.vscl_ratio_c = (double) scl->ratios.vert_c.value / (1ULL<<32); - e2e_pipe->pipe.scale_ratio_depth.scl_enable = - scl->ratios.vert.value != dc_fixpt_one.value - || scl->ratios.horz.value != dc_fixpt_one.value - || scl->ratios.vert_c.value != dc_fixpt_one.value - || scl->ratios.horz_c.value != dc_fixpt_one.value /*Lb only or Full scl*/ - || always_scale; /*support always scale*/ - e2e_pipe->pipe.scale_taps.htaps = scl->taps.h_taps; - e2e_pipe->pipe.scale_taps.htaps_c = scl->taps.h_taps_c; - e2e_pipe->pipe.scale_taps.vtaps = scl->taps.v_taps; - e2e_pipe->pipe.scale_taps.vtaps_c = scl->taps.v_taps_c; - - /* Currently compat_level is not defined. Commenting it until further resolution - * if (pln->compat_level == DC_LEGACY_TILING_ADDR_GEN_TWO) { - swizzle_to_dml_params(pln->tiling_info.gfx9.swizzle, - &e2e_pipe->pipe.src.sw_mode); - e2e_pipe->pipe.src.macro_tile_size = - swizzle_mode_to_macro_tile_size(pln->tiling_info.gfx9.swizzle); - } else { - gfx10array_mode_to_dml_params(pln->tiling_info.gfx10compatible.array_mode, - pln->compat_level, - &e2e_pipe->pipe.src.sw_mode); - e2e_pipe->pipe.src.macro_tile_size = dm_4k_tile; - }*/ - - e2e_pipe->pipe.src.source_format = dc_source_format_to_dml_source_format(pln->format); -} - -static void populate_dml_cursor_parameters_from_dc_pipe_ctx (const struct pipe_ctx *dc_pipe_ctx, struct _vcs_dpi_display_e2e_pipe_params_st *e2e_pipe) -{ - /* - * For graphic plane, cursor number is 1, nv12 is 0 - * bw calculations due to cursor on/off - */ - if (dc_pipe_ctx->plane_state && - (dc_pipe_ctx->plane_state->address.type == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE || - dc_pipe_ctx->stream->mall_stream_config.type == SUBVP_PHANTOM)) - e2e_pipe->pipe.src.num_cursors = 0; - else - e2e_pipe->pipe.src.num_cursors = 1; - - e2e_pipe->pipe.src.cur0_src_width = 256; - e2e_pipe->pipe.src.cur0_bpp = dm_cur_32bit; -} - -static int populate_dml_pipes_from_context_base( - struct dc *dc, - struct dc_state *context, - display_e2e_pipe_params_st *pipes, - bool fast_validate) -{ - int pipe_cnt, i; - bool synchronized_vblank = true; - struct resource_context *res_ctx = &context->res_ctx; - - for (i = 0, pipe_cnt = -1; i < dc->res_pool->pipe_count; i++) { - if (!res_ctx->pipe_ctx[i].stream) - continue; - - if (pipe_cnt < 0) { - pipe_cnt = i; - continue; - } - - if (res_ctx->pipe_ctx[pipe_cnt].stream == res_ctx->pipe_ctx[i].stream) - continue; - - if (dc->debug.disable_timing_sync || - (!resource_are_streams_timing_synchronizable( - res_ctx->pipe_ctx[pipe_cnt].stream, - res_ctx->pipe_ctx[i].stream) && - !resource_are_vblanks_synchronizable( - res_ctx->pipe_ctx[pipe_cnt].stream, - res_ctx->pipe_ctx[i].stream))) { - synchronized_vblank = false; - break; - } - } - - for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { - struct dc_crtc_timing *timing = &res_ctx->pipe_ctx[i].stream->timing; - - struct audio_check aud_check = {0}; - if (!res_ctx->pipe_ctx[i].stream) - continue; - - /* todo: - pipes[pipe_cnt].pipe.src.dynamic_metadata_enable = 0; - pipes[pipe_cnt].pipe.src.dcc = 0; - pipes[pipe_cnt].pipe.src.vm = 0;*/ - - pipes[pipe_cnt].clks_cfg.refclk_mhz = dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000.0; - - pipes[pipe_cnt].dout.dsc_enable = res_ctx->pipe_ctx[i].stream->timing.flags.DSC; - /* todo: rotation?*/ - pipes[pipe_cnt].dout.dsc_slices = res_ctx->pipe_ctx[i].stream->timing.dsc_cfg.num_slices_h; - if (res_ctx->pipe_ctx[i].stream->use_dynamic_meta) { - pipes[pipe_cnt].pipe.src.dynamic_metadata_enable = true; - /* 1/2 vblank */ - pipes[pipe_cnt].pipe.src.dynamic_metadata_lines_before_active = - (timing->v_total - timing->v_addressable - - timing->v_border_top - timing->v_border_bottom) / 2; - /* 36 bytes dp, 32 hdmi */ - pipes[pipe_cnt].pipe.src.dynamic_metadata_xmit_bytes = - dc_is_dp_signal(res_ctx->pipe_ctx[i].stream->signal) ? 36 : 32; - } - pipes[pipe_cnt].pipe.dest.synchronized_vblank_all_planes = synchronized_vblank; - - dc_timing_to_dml_timing(timing, &pipes[pipe_cnt].pipe.dest); - pipes[pipe_cnt].pipe.dest.vtotal_min = res_ctx->pipe_ctx[i].stream->adjust.v_total_min; - pipes[pipe_cnt].pipe.dest.vtotal_max = res_ctx->pipe_ctx[i].stream->adjust.v_total_max; - - pipes[pipe_cnt].pipe.dest.otg_inst = res_ctx->pipe_ctx[i].stream_res.tg->inst; - - pipes[pipe_cnt].pipe.dest.odm_combine = get_dml_odm_combine(&res_ctx->pipe_ctx[i]); - - populate_hsplit_group_from_dc_pipe_ctx(&res_ctx->pipe_ctx[i], &pipes[pipe_cnt]); - - pipes[pipe_cnt].dout.dp_lanes = 4; - pipes[pipe_cnt].dout.is_virtual = 0; - pipes[pipe_cnt].dout.output_type = get_dml_output_type(res_ctx->pipe_ctx[i].stream->signal); - if (pipes[pipe_cnt].dout.output_type < 0) { - pipes[pipe_cnt].dout.output_type = dm_dp; - pipes[pipe_cnt].dout.is_virtual = 1; - } - - populate_color_depth_and_encoding_from_timing(&res_ctx->pipe_ctx[i].stream->timing, &pipes[pipe_cnt].dout); - - if (res_ctx->pipe_ctx[i].stream->timing.flags.DSC) - pipes[pipe_cnt].dout.output_bpp = res_ctx->pipe_ctx[i].stream->timing.dsc_cfg.bits_per_pixel / 16.0; - - /* todo: default max for now, until there is logic reflecting this in dc*/ - pipes[pipe_cnt].dout.dsc_input_bpc = 12; - /*fill up the audio sample rate (unit in kHz)*/ - get_audio_check(&res_ctx->pipe_ctx[i].stream->audio_info, &aud_check); - pipes[pipe_cnt].dout.max_audio_sample_rate = aud_check.max_audiosample_rate / 1000; - - populate_dml_cursor_parameters_from_dc_pipe_ctx(&res_ctx->pipe_ctx[i], &pipes[pipe_cnt]); - - if (!res_ctx->pipe_ctx[i].plane_state) { - populate_default_plane_from_timing(timing, &pipes[pipe_cnt].pipe); - } else { - populate_dml_from_dc_pipe_ctx(&res_ctx->pipe_ctx[i], &pipes[pipe_cnt], dc->debug.always_scale); - } - - pipe_cnt++; - } - - /* populate writeback information */ - if (dc->res_pool) - dc->res_pool->funcs->populate_dml_writeback_from_context(dc, res_ctx, pipes); - - return pipe_cnt; -} - -static int dml_populate_dml_pipes_from_context( - struct dc *dc, struct dc_state *context, - display_e2e_pipe_params_st *pipes, - bool fast_validate) -{ - int i, pipe_cnt; - struct resource_context *res_ctx = &context->res_ctx; - struct pipe_ctx *pipe = NULL; // Fix potentially uninitialized error from VS - - populate_dml_pipes_from_context_base(dc, context, pipes, fast_validate); - - for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { - struct dc_crtc_timing *timing; - - if (!res_ctx->pipe_ctx[i].stream) - continue; - pipe = &res_ctx->pipe_ctx[i]; - timing = &pipe->stream->timing; - - pipes[pipe_cnt].pipe.src.gpuvm = true; - pipes[pipe_cnt].pipe.src.dcc_fraction_of_zs_req_luma = 0; - pipes[pipe_cnt].pipe.src.dcc_fraction_of_zs_req_chroma = 0; - pipes[pipe_cnt].pipe.dest.vfront_porch = timing->v_front_porch; - - pipes[pipe_cnt].dout.dsc_input_bpc = 0; - if (pipes[pipe_cnt].dout.dsc_enable) { - switch (timing->display_color_depth) { - case COLOR_DEPTH_888: - pipes[pipe_cnt].dout.dsc_input_bpc = 8; - break; - case COLOR_DEPTH_101010: - pipes[pipe_cnt].dout.dsc_input_bpc = 10; - break; - case COLOR_DEPTH_121212: - pipes[pipe_cnt].dout.dsc_input_bpc = 12; - break; - default: - ASSERT(0); - break; - } - } - pipe_cnt++; - } - dc->config.enable_4to1MPC = false; - if (pipe_cnt == 1 && pipe->plane_state && !dc->debug.disable_z9_mpc) { - if (is_dual_plane(pipe->plane_state->format) - && pipe->plane_state->src_rect.width <= 1920 && pipe->plane_state->src_rect.height <= 1080) { - dc->config.enable_4to1MPC = true; - } else if (!is_dual_plane(pipe->plane_state->format)) { - context->bw_ctx.dml.ip.det_buffer_size_kbytes = 192; - pipes[0].pipe.src.unbounded_req_mode = true; - } - } - - return pipe_cnt; -} - -static void dml_full_validate_bw_helper(struct dc *dc, - struct dc_state *context, - display_e2e_pipe_params_st *pipes, - int *vlevel, - int *split, - bool *merge, - int *pipe_cnt) -{ - struct vba_vars_st *vba = &context->bw_ctx.dml.vba; - - /* - * DML favors voltage over p-state, but we're more interested in - * supporting p-state over voltage. We can't support p-state in - * prefetch mode > 0 so try capping the prefetch mode to start. - */ - context->bw_ctx.dml.soc.allow_dram_self_refresh_or_dram_clock_change_in_vblank = - dm_allow_self_refresh_and_mclk_switch; - *vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, *pipe_cnt); - /* This may adjust vlevel and maxMpcComb */ - if (*vlevel < context->bw_ctx.dml.soc.num_states) - *vlevel = dml_validate_apply_pipe_split_flags(dc, context, *vlevel, split, merge); - - /* Conditions for setting up phantom pipes for SubVP: - * 1. Not force disable SubVP - * 2. Full update (i.e. !fast_validate) - * 3. Enough pipes are available to support SubVP (TODO: Which pipes will use VACTIVE / VBLANK / SUBVP?) - * 4. Display configuration passes validation - * 5. (Config doesn't support MCLK in VACTIVE/VBLANK || dc->debug.force_subvp_mclk_switch) - */ - if (!dc->debug.force_disable_subvp && - dml_enough_pipes_for_subvp(dc, context) && - *vlevel < context->bw_ctx.dml.soc.num_states && - (vba->DRAMClockChangeSupport[*vlevel][vba->maxMpcComb] == dm_dram_clock_change_unsupported || - dc->debug.force_subvp_mclk_switch)) { - - dml_add_phantom_pipes(dc, context); - - /* Create input to DML based on new context which includes phantom pipes - * TODO: Input to DML should mark which pipes are phantom - */ - *pipe_cnt = dml_populate_dml_pipes_from_context(dc, context, pipes, false); - *vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, *pipe_cnt); - if (*vlevel < context->bw_ctx.dml.soc.num_states) { - memset(split, 0, MAX_PIPES * sizeof(*split)); - memset(merge, 0, MAX_PIPES * sizeof(*merge)); - *vlevel = dml_validate_apply_pipe_split_flags(dc, context, *vlevel, split, merge); - } - - // If SubVP pipe config is unsupported (or cannot be used for UCLK switching) - // remove phantom pipes and repopulate dml pipes - if (*vlevel == context->bw_ctx.dml.soc.num_states || - vba->DRAMClockChangeSupport[*vlevel][vba->maxMpcComb] == dm_dram_clock_change_unsupported) { - dml_remove_phantom_pipes(dc, context); - *pipe_cnt = dml_populate_dml_pipes_from_context(dc, context, pipes, false); - } - } -} - -static void dcn20_adjust_adaptive_sync_v_startup( - const struct dc_crtc_timing *dc_crtc_timing, int *vstartup_start) -{ - struct dc_crtc_timing patched_crtc_timing; - uint32_t asic_blank_end = 0; - uint32_t asic_blank_start = 0; - uint32_t newVstartup = 0; - - patched_crtc_timing = *dc_crtc_timing; - - if (patched_crtc_timing.flags.INTERLACE == 1) { - if (patched_crtc_timing.v_front_porch < 2) - patched_crtc_timing.v_front_porch = 2; - } else { - if (patched_crtc_timing.v_front_porch < 1) - patched_crtc_timing.v_front_porch = 1; - } - - /* blank_start = frame end - front porch */ - asic_blank_start = patched_crtc_timing.v_total - - patched_crtc_timing.v_front_porch; - - /* blank_end = blank_start - active */ - asic_blank_end = asic_blank_start - - patched_crtc_timing.v_border_bottom - - patched_crtc_timing.v_addressable - - patched_crtc_timing.v_border_top; - - newVstartup = asic_blank_end + (patched_crtc_timing.v_total - asic_blank_start); - - *vstartup_start = ((newVstartup > *vstartup_start) ? newVstartup : *vstartup_start); -} - -static bool is_dp_128b_132b_signal(struct pipe_ctx *pipe_ctx) -{ - return (pipe_ctx->stream_res.hpo_dp_stream_enc && - pipe_ctx->link_res.hpo_dp_link_enc && - dc_is_dp_signal(pipe_ctx->stream->signal)); -} - -static bool is_dtbclk_required(struct dc *dc, struct dc_state *context) -{ - int i; - for (i = 0; i < dc->res_pool->pipe_count; i++) { - if (!context->res_ctx.pipe_ctx[i].stream) - continue; - if (is_dp_128b_132b_signal(&context->res_ctx.pipe_ctx[i])) - return true; - } - return false; -} - -static void dml_update_soc_for_wm_a(struct dc *dc, struct dc_state *context) -{ - if (dc->clk_mgr->bw_params->wm_table.nv_entries[WM_A].valid) { - context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.pstate_latency_us; - context->bw_ctx.dml.soc.sr_enter_plus_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.sr_enter_plus_exit_time_us; - context->bw_ctx.dml.soc.sr_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.sr_exit_time_us; - context->bw_ctx.dml.soc.fclk_change_latency_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.fclk_change_latency_us; - } -} - -static bool dml_internal_validate( - struct dc *dc, - struct dc_state *context, - display_e2e_pipe_params_st *pipes, - int *pipe_cnt_out, - int *vlevel_out, - bool fast_validate) -{ - bool out = false; - bool repopulate_pipes = false; - int split[MAX_PIPES] = { 0 }; - bool merge[MAX_PIPES] = { false }; - bool newly_split[MAX_PIPES] = { false }; - int pipe_cnt, i, pipe_idx, vlevel; - struct vba_vars_st *vba = &context->bw_ctx.dml.vba; - - ASSERT(pipes); - if (!pipes) - return false; - - // For each full update, remove all existing phantom pipes first - dml_remove_phantom_pipes(dc, context); - - dml_update_soc_for_wm_a(dc, context); - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - - if (pipe->plane_state) { - // On initial pass through DML, we intend to use MALL for SS on all - // (non-PSR) surfaces with none using MALL for P-State - // 'mall_plane_config': is not a member of 'dc_plane_state' - commenting it out till mall_plane_config gets supported in dc_plant_state - //if (pipe->stream && pipe->stream->link->psr_settings.psr_version == DC_PSR_VERSION_UNSUPPORTED) - // pipe->plane_state->mall_plane_config.use_mall_for_ss = true; - } - } - pipe_cnt = dml_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); - - if (!pipe_cnt) { - out = true; - goto validate_out; - } - - dml_log_pipe_params(&context->bw_ctx.dml, pipes, pipe_cnt); - - if (!fast_validate) { - dml_full_validate_bw_helper(dc, context, pipes, &vlevel, split, merge, &pipe_cnt); - } - - if (fast_validate || vlevel == context->bw_ctx.dml.soc.num_states || - vba->DRAMClockChangeSupport[vlevel][vba->maxMpcComb] == dm_dram_clock_change_unsupported) { - /* - * If mode is unsupported or there's still no p-state support then - * fall back to favoring voltage. - * - * We don't actually support prefetch mode 2, so require that we - * at least support prefetch mode 1. - */ - context->bw_ctx.dml.soc.allow_dram_self_refresh_or_dram_clock_change_in_vblank = - dm_allow_self_refresh; - - vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt); - if (vlevel < context->bw_ctx.dml.soc.num_states) { - memset(split, 0, sizeof(split)); - memset(merge, 0, sizeof(merge)); - vlevel = dml_validate_apply_pipe_split_flags(dc, context, vlevel, split, merge); - } - } - - dml_log_mode_support_params(&context->bw_ctx.dml); - - if (vlevel == context->bw_ctx.dml.soc.num_states) - goto validate_fail; - - for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - struct pipe_ctx *mpo_pipe = pipe->bottom_pipe; - - if (!pipe->stream) - continue; - - /* We only support full screen mpo with ODM */ - if (vba->ODMCombineEnabled[vba->pipe_plane[pipe_idx]] != dm_odm_combine_mode_disabled - && pipe->plane_state && mpo_pipe - && memcmp(&mpo_pipe->plane_res.scl_data.recout, - &pipe->plane_res.scl_data.recout, - sizeof(struct rect)) != 0) { - ASSERT(mpo_pipe->plane_state != pipe->plane_state); - goto validate_fail; - } - pipe_idx++; - } - - /* merge pipes if necessary */ - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - - /*skip pipes that don't need merging*/ - if (!merge[i]) - continue; - - /* if ODM merge we ignore mpc tree, mpo pipes will have their own flags */ - if (pipe->prev_odm_pipe) { - /*split off odm pipe*/ - pipe->prev_odm_pipe->next_odm_pipe = pipe->next_odm_pipe; - if (pipe->next_odm_pipe) - pipe->next_odm_pipe->prev_odm_pipe = pipe->prev_odm_pipe; - - pipe->bottom_pipe = NULL; - pipe->next_odm_pipe = NULL; - pipe->plane_state = NULL; - pipe->stream = NULL; - pipe->top_pipe = NULL; - pipe->prev_odm_pipe = NULL; - if (pipe->stream_res.dsc) - dml_release_dsc(&context->res_ctx, dc->res_pool, &pipe->stream_res.dsc); - memset(&pipe->plane_res, 0, sizeof(pipe->plane_res)); - memset(&pipe->stream_res, 0, sizeof(pipe->stream_res)); - repopulate_pipes = true; - } else if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state) { - struct pipe_ctx *top_pipe = pipe->top_pipe; - struct pipe_ctx *bottom_pipe = pipe->bottom_pipe; - - top_pipe->bottom_pipe = bottom_pipe; - if (bottom_pipe) - bottom_pipe->top_pipe = top_pipe; - - pipe->top_pipe = NULL; - pipe->bottom_pipe = NULL; - pipe->plane_state = NULL; - pipe->stream = NULL; - memset(&pipe->plane_res, 0, sizeof(pipe->plane_res)); - memset(&pipe->stream_res, 0, sizeof(pipe->stream_res)); - repopulate_pipes = true; - } else - ASSERT(0); /* Should never try to merge master pipe */ - - } - - for (i = 0, pipe_idx = -1; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i]; - struct pipe_ctx *hsplit_pipe = NULL; - bool odm; - int old_index = -1; - - if (!pipe->stream || newly_split[i]) - continue; - - pipe_idx++; - odm = vba->ODMCombineEnabled[vba->pipe_plane[pipe_idx]] != dm_odm_combine_mode_disabled; - - if (!pipe->plane_state && !odm) - continue; - - if (split[i]) { - if (odm) { - if (split[i] == 4 && old_pipe->next_odm_pipe && old_pipe->next_odm_pipe->next_odm_pipe) - old_index = old_pipe->next_odm_pipe->next_odm_pipe->pipe_idx; - else if (old_pipe->next_odm_pipe) - old_index = old_pipe->next_odm_pipe->pipe_idx; - } else { - if (split[i] == 4 && old_pipe->bottom_pipe && old_pipe->bottom_pipe->bottom_pipe && - old_pipe->bottom_pipe->bottom_pipe->plane_state == old_pipe->plane_state) - old_index = old_pipe->bottom_pipe->bottom_pipe->pipe_idx; - else if (old_pipe->bottom_pipe && - old_pipe->bottom_pipe->plane_state == old_pipe->plane_state) - old_index = old_pipe->bottom_pipe->pipe_idx; - } - hsplit_pipe = dml_find_split_pipe(dc, context, old_index); - ASSERT(hsplit_pipe); - if (!hsplit_pipe) - goto validate_fail; - - if (!dml_split_stream_for_mpc_or_odm( - dc, &context->res_ctx, - pipe, hsplit_pipe, odm)) - goto validate_fail; - - newly_split[hsplit_pipe->pipe_idx] = true; - repopulate_pipes = true; - } - if (split[i] == 4) { - struct pipe_ctx *pipe_4to1; - - if (odm && old_pipe->next_odm_pipe) - old_index = old_pipe->next_odm_pipe->pipe_idx; - else if (!odm && old_pipe->bottom_pipe && - old_pipe->bottom_pipe->plane_state == old_pipe->plane_state) - old_index = old_pipe->bottom_pipe->pipe_idx; - else - old_index = -1; - pipe_4to1 = dml_find_split_pipe(dc, context, old_index); - ASSERT(pipe_4to1); - if (!pipe_4to1) - goto validate_fail; - if (!dml_split_stream_for_mpc_or_odm( - dc, &context->res_ctx, - pipe, pipe_4to1, odm)) - goto validate_fail; - newly_split[pipe_4to1->pipe_idx] = true; - - if (odm && old_pipe->next_odm_pipe && old_pipe->next_odm_pipe->next_odm_pipe - && old_pipe->next_odm_pipe->next_odm_pipe->next_odm_pipe) - old_index = old_pipe->next_odm_pipe->next_odm_pipe->next_odm_pipe->pipe_idx; - else if (!odm && old_pipe->bottom_pipe && old_pipe->bottom_pipe->bottom_pipe && - old_pipe->bottom_pipe->bottom_pipe->bottom_pipe && - old_pipe->bottom_pipe->bottom_pipe->bottom_pipe->plane_state == old_pipe->plane_state) - old_index = old_pipe->bottom_pipe->bottom_pipe->bottom_pipe->pipe_idx; - else - old_index = -1; - pipe_4to1 = dml_find_split_pipe(dc, context, old_index); - ASSERT(pipe_4to1); - if (!pipe_4to1) - goto validate_fail; - if (!dml_split_stream_for_mpc_or_odm( - dc, &context->res_ctx, - hsplit_pipe, pipe_4to1, odm)) - goto validate_fail; - newly_split[pipe_4to1->pipe_idx] = true; - } - if (odm) - dml_build_mapped_resource(dc, context, pipe->stream); - } - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - - if (pipe->plane_state) { - if (!resource_build_scaling_params(pipe)) - goto validate_fail; - } - } - - /* Actual dsc count per stream dsc validation*/ - if (!dml_validate_dsc(dc, context)) { - vba->ValidationStatus[vba->soc.num_states] = DML_FAIL_DSC_VALIDATION_FAILURE; - goto validate_fail; - } - - if (repopulate_pipes) - pipe_cnt = dml_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); - *vlevel_out = vlevel; - *pipe_cnt_out = pipe_cnt; - - out = true; - goto validate_out; - -validate_fail: - out = false; - -validate_out: - return out; -} - -static void dml_calculate_dlg_params( - struct dc *dc, struct dc_state *context, - display_e2e_pipe_params_st *pipes, - int pipe_cnt, - int vlevel) -{ - int i, pipe_idx; - int plane_count; - - /* Writeback MCIF_WB arbitration parameters */ - if (dc->res_pool) - dc->res_pool->funcs->set_mcif_arb_params(dc, context, pipes, pipe_cnt); - - context->bw_ctx.bw.dcn.clk.dispclk_khz = context->bw_ctx.dml.vba.DISPCLK * 1000; - context->bw_ctx.bw.dcn.clk.dcfclk_khz = context->bw_ctx.dml.vba.DCFCLK * 1000; - context->bw_ctx.bw.dcn.clk.socclk_khz = context->bw_ctx.dml.vba.SOCCLK * 1000; - context->bw_ctx.bw.dcn.clk.dramclk_khz = context->bw_ctx.dml.vba.DRAMSpeed * 1000 / 16; - context->bw_ctx.bw.dcn.clk.dcfclk_deep_sleep_khz = context->bw_ctx.dml.vba.DCFCLKDeepSleep * 1000; - context->bw_ctx.bw.dcn.clk.fclk_khz = context->bw_ctx.dml.vba.FabricClock * 1000; - context->bw_ctx.bw.dcn.clk.p_state_change_support = - context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] - != dm_dram_clock_change_unsupported; - - context->bw_ctx.bw.dcn.clk.dppclk_khz = 0; - /* 'z9_support': is not a member of 'dc_clocks' - Commenting out till we have this support in dc_clocks - * context->bw_ctx.bw.dcn.clk.z9_support = (context->bw_ctx.dml.vba.StutterPeriod > 5000.0) ? - DCN_Z9_SUPPORT_ALLOW : DCN_Z9_SUPPORT_DISALLOW; - */ - plane_count = 0; - for (i = 0; i < dc->res_pool->pipe_count; i++) { - if (context->res_ctx.pipe_ctx[i].plane_state) - plane_count++; - } - - /* Commented out as per above error for now. - if (plane_count == 0) - context->bw_ctx.bw.dcn.clk.z9_support = DCN_Z9_SUPPORT_ALLOW; - */ - context->bw_ctx.bw.dcn.clk.dtbclk_en = is_dtbclk_required(dc, context); - context->bw_ctx.bw.dcn.clk.fclk_p_state_change_support = - context->bw_ctx.dml.vba.FCLKChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb]; - if (context->bw_ctx.bw.dcn.clk.dispclk_khz < dc->debug.min_disp_clk_khz) - context->bw_ctx.bw.dcn.clk.dispclk_khz = dc->debug.min_disp_clk_khz; - - for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { - if (!context->res_ctx.pipe_ctx[i].stream) - continue; - pipes[pipe_idx].pipe.dest.vstartup_start = get_vstartup(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx); - pipes[pipe_idx].pipe.dest.vupdate_offset = get_vupdate_offset(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx); - pipes[pipe_idx].pipe.dest.vupdate_width = get_vupdate_width(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx); - pipes[pipe_idx].pipe.dest.vready_offset = get_vready_offset(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx); - if (context->res_ctx.pipe_ctx[i].stream->mall_stream_config.type == SUBVP_PHANTOM) { - // Phantom pipe requires that DET_SIZE = 0 and no unbounded requests - context->res_ctx.pipe_ctx[i].det_buffer_size_kb = 0; - context->res_ctx.pipe_ctx[i].unbounded_req = false; - } else { - context->res_ctx.pipe_ctx[i].det_buffer_size_kb = context->bw_ctx.dml.ip.det_buffer_size_kbytes; - context->res_ctx.pipe_ctx[i].unbounded_req = pipes[pipe_idx].pipe.src.unbounded_req_mode; - } - - if (context->bw_ctx.bw.dcn.clk.dppclk_khz < pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000) - context->bw_ctx.bw.dcn.clk.dppclk_khz = pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000; - context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz = - pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000; - context->res_ctx.pipe_ctx[i].pipe_dlg_param = pipes[pipe_idx].pipe.dest; - pipe_idx++; - } - /*save a original dppclock copy*/ - context->bw_ctx.bw.dcn.clk.bw_dppclk_khz = context->bw_ctx.bw.dcn.clk.dppclk_khz; - context->bw_ctx.bw.dcn.clk.bw_dispclk_khz = context->bw_ctx.bw.dcn.clk.dispclk_khz; - context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz = context->bw_ctx.dml.soc.clock_limits[vlevel].dppclk_mhz * 1000; - context->bw_ctx.bw.dcn.clk.max_supported_dispclk_khz = context->bw_ctx.dml.soc.clock_limits[vlevel].dispclk_mhz * 1000; - context->bw_ctx.bw.dcn.compbuf_size_kb = context->bw_ctx.dml.ip.config_return_buffer_size_in_kbytes - - context->bw_ctx.dml.ip.det_buffer_size_kbytes * pipe_idx; - - for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { - bool cstate_en = context->bw_ctx.dml.vba.PrefetchMode[vlevel][context->bw_ctx.dml.vba.maxMpcComb] != 2; - - if (!context->res_ctx.pipe_ctx[i].stream) - continue; - - context->bw_ctx.dml.funcs.rq_dlg_get_dlg_reg(&context->bw_ctx.dml, - &context->res_ctx.pipe_ctx[i].dlg_regs, - &context->res_ctx.pipe_ctx[i].ttu_regs, - pipes, - pipe_cnt, - pipe_idx, - cstate_en, - context->bw_ctx.bw.dcn.clk.p_state_change_support, - false, false, true); - - context->bw_ctx.dml.funcs.rq_dlg_get_rq_reg(&context->bw_ctx.dml, - &context->res_ctx.pipe_ctx[i].rq_regs, - &pipes[pipe_idx].pipe); - pipe_idx++; - } -} - -static void dml_calculate_wm_and_dlg( - struct dc *dc, struct dc_state *context, - display_e2e_pipe_params_st *pipes, - int pipe_cnt, - int vlevel) -{ - int i, pipe_idx, vlevel_temp = 0; - - double dcfclk = context->bw_ctx.dml.soc.clock_limits[0].dcfclk_mhz; - double dcfclk_from_validation = context->bw_ctx.dml.vba.DCFCLKState[vlevel][context->bw_ctx.dml.vba.maxMpcComb]; - unsigned int min_dram_speed_mts = context->bw_ctx.dml.vba.DRAMSpeed; - bool pstate_en = context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] != - dm_dram_clock_change_unsupported; - - /* Set B: - * For Set B calculations use clocks from clock_limits[2] when available i.e. when SMU is present, - * otherwise use arbitrary low value from spreadsheet for DCFCLK as lower is safer for watermark - * calculations to cover bootup clocks. - * DCFCLK: soc.clock_limits[2] when available - * UCLK: soc.clock_limits[2] when available - */ - if (context->bw_ctx.dml.soc.num_states > 2) { - vlevel_temp = 2; - dcfclk = context->bw_ctx.dml.soc.clock_limits[2].dcfclk_mhz; - } else - dcfclk = 615; //DCFCLK Vmin_lv - - pipes[0].clks_cfg.voltage = vlevel_temp; - pipes[0].clks_cfg.dcfclk_mhz = dcfclk; - pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel_temp].socclk_mhz; - - if (dc->clk_mgr->bw_params->wm_table.nv_entries[WM_B].valid) { - context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_B].dml_input.pstate_latency_us; - context->bw_ctx.dml.soc.sr_enter_plus_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_B].dml_input.sr_enter_plus_exit_time_us; - context->bw_ctx.dml.soc.sr_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_B].dml_input.sr_exit_time_us; - } - context->bw_ctx.bw.dcn.watermarks.b.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.b.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.b.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.b.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.b.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.fclk_pstate_change_ns = get_fclk_watermark(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - //context->bw_ctx.bw.dcn.watermarks.b.usr_retraining_ns = get_wm_usr_retraining(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - - /* Temporary, to have some fclk_pstate_change_ns and usr_retraining_ns wm values until DML is implemented */ - //context->bw_ctx.bw.dcn.watermarks.b.usr_retraining = context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.pstate_change_ns / 8; - - /* Set D: - * All clocks min. - * DCFCLK: Min, as reported by PM FW when available - * UCLK : Min, as reported by PM FW when available - * sr_enter_exit/sr_exit should be lower than used for DRAM (TBD after bringup or later, use as decided in Clk Mgr) - */ - - if (context->bw_ctx.dml.soc.num_states > 2) { - vlevel_temp = 0; - dcfclk = dc->clk_mgr->bw_params->clk_table.entries[0].dcfclk_mhz; - } else - dcfclk = 615; //DCFCLK Vmin_lv - - pipes[0].clks_cfg.voltage = vlevel_temp; - pipes[0].clks_cfg.dcfclk_mhz = dcfclk; - pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel_temp].socclk_mhz; - - if (dc->clk_mgr->bw_params->wm_table.nv_entries[WM_D].valid) { - context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_D].dml_input.pstate_latency_us; - context->bw_ctx.dml.soc.sr_enter_plus_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_D].dml_input.sr_enter_plus_exit_time_us; - context->bw_ctx.dml.soc.sr_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_D].dml_input.sr_exit_time_us; - } - context->bw_ctx.bw.dcn.watermarks.d.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.d.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.d.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.d.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.d.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.fclk_pstate_change_ns = get_fclk_watermark(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - //context->bw_ctx.bw.dcn.watermarks.d.usr_retraining_ns = get_wm_usr_retraining(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - - /* Temporary, to have some fclk_pstate_change_ns and usr_retraining_ns wm values until DML is implemented */ - //context->bw_ctx.bw.dcn.watermarks.d.usr_retraining = context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.pstate_change_ns / 8; - /* Set C, for Dummy P-State: - * All clocks min. - * DCFCLK: Min, as reported by PM FW, when available - * UCLK : Min, as reported by PM FW, when available - * pstate latency as per UCLK state dummy pstate latency - */ - if (dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].valid) { - unsigned int min_dram_speed_mts_margin = 160; - - if ((!pstate_en)) - min_dram_speed_mts = dc->clk_mgr->bw_params->clk_table.entries[dc->clk_mgr->bw_params->clk_table.num_entries - 1].memclk_mhz * 16; - - /* find largest table entry that is lower than dram speed, but lower than DPM0 still uses DPM0 */ - for (i = 3; i > 0; i--) - if (min_dram_speed_mts + min_dram_speed_mts_margin > dc->clk_mgr->bw_params->dummy_pstate_table[i].dram_speed_mts) - break; - - context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->dummy_pstate_table[i].dummy_pstate_latency_us; - context->bw_ctx.dml.soc.dummy_pstate_latency_us = dc->clk_mgr->bw_params->dummy_pstate_table[i].dummy_pstate_latency_us; - context->bw_ctx.dml.soc.sr_enter_plus_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].dml_input.sr_enter_plus_exit_time_us; - context->bw_ctx.dml.soc.sr_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].dml_input.sr_exit_time_us; - } - context->bw_ctx.bw.dcn.watermarks.c.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.c.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.c.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.c.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.c.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.fclk_pstate_change_ns = get_fclk_watermark(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - //context->bw_ctx.bw.dcn.watermarks.c.usr_retraining_ns = get_wm_usr_retraining(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - - /* Temporary, to have some fclk_pstate_change_ns and usr_retraining_ns wm values until DML is implemented */ - //context->bw_ctx.bw.dcn.watermarks.c.usr_retraining = context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.pstate_change_ns / 8; - if ((!pstate_en) && (dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].valid)) { - /* The only difference between A and C is p-state latency, if p-state is not supported - * with full p-state latency we want to calculate DLG based on dummy p-state latency, - * Set A p-state watermark set to 0 previously, when p-state unsupported, for now keep as previous implementation. - */ - context->bw_ctx.bw.dcn.watermarks.a = context->bw_ctx.bw.dcn.watermarks.c; - context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = 0; - } else { - /* Set A: - * All clocks min. - * DCFCLK: Min, as reported by PM FW, when available - * UCLK: Min, as reported by PM FW, when available - */ - dml_update_soc_for_wm_a(dc, context); - context->bw_ctx.bw.dcn.watermarks.a.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.a.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.a.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.a.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.a.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - } - - pipes[0].clks_cfg.voltage = vlevel; - pipes[0].clks_cfg.dcfclk_mhz = dcfclk_from_validation; - pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel].socclk_mhz; - - for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { - if (!context->res_ctx.pipe_ctx[i].stream) - continue; - - pipes[pipe_idx].clks_cfg.dispclk_mhz = get_dispclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt); - pipes[pipe_idx].clks_cfg.dppclk_mhz = get_dppclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx); - - if (dc->config.forced_clocks) { - pipes[pipe_idx].clks_cfg.dispclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dispclk_mhz; - pipes[pipe_idx].clks_cfg.dppclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dppclk_mhz; - } - if (dc->debug.min_disp_clk_khz > pipes[pipe_idx].clks_cfg.dispclk_mhz * 1000) - pipes[pipe_idx].clks_cfg.dispclk_mhz = dc->debug.min_disp_clk_khz / 1000.0; - if (dc->debug.min_dpp_clk_khz > pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000) - pipes[pipe_idx].clks_cfg.dppclk_mhz = dc->debug.min_dpp_clk_khz / 1000.0; - - pipe_idx++; - } - - context->perf_params.stutter_period_us = context->bw_ctx.dml.vba.StutterPeriod; - - dml_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel); - - if (!pstate_en) - /* Restore full p-state latency */ - context->bw_ctx.dml.soc.dram_clock_change_latency_us = - dc->clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.pstate_latency_us; -} - -bool dml_validate(struct dc *dc, - struct dc_state *context, - bool fast_validate) -{ - bool out = false; - - BW_VAL_TRACE_SETUP(); - - int vlevel = 0; - int pipe_cnt = 0; - display_e2e_pipe_params_st *pipes = context->bw_ctx.dml.dml_pipe_state; - DC_LOGGER_INIT(dc->ctx->logger); - - BW_VAL_TRACE_COUNT(); - - out = dml_internal_validate(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate); - - if (pipe_cnt == 0) - goto validate_out; - - if (!out) - goto validate_fail; - - BW_VAL_TRACE_END_VOLTAGE_LEVEL(); - - if (fast_validate) { - BW_VAL_TRACE_SKIP(fast); - goto validate_out; - } - - dml_calculate_wm_and_dlg(dc, context, pipes, pipe_cnt, vlevel); - - BW_VAL_TRACE_END_WATERMARKS(); - - goto validate_out; - -validate_fail: - DC_LOG_WARNING("Mode Validation Warning: %s failed validation.\n", - dml_get_status_message(context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states])); - - BW_VAL_TRACE_SKIP(fail); - out = false; - -validate_out: - BW_VAL_TRACE_FINISH(); - - return out; -} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_wrapper_translation.c b/drivers/gpu/drm/amd/display/dc/dml/dml_wrapper_translation.c deleted file mode 100644 index 4ec5310a2962..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_wrapper_translation.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifdef DML_WRAPPER_TRANSLATION_ - -static void gfx10array_mode_to_dml_params( - enum array_mode_values array_mode, - enum legacy_tiling_compat_level compat_level, - unsigned int *sw_mode) -{ - switch (array_mode) { - case DC_ARRAY_LINEAR_ALLIGNED: - case DC_ARRAY_LINEAR_GENERAL: - *sw_mode = dm_sw_linear; - break; - case DC_ARRAY_2D_TILED_THIN1: -// DC_LEGACY_TILING_ADDR_GEN_ZERO - undefined as per current code hence removed -#if 0 - if (compat_level == DC_LEGACY_TILING_ADDR_GEN_ZERO) - *sw_mode = dm_sw_gfx7_2d_thin_l_vp; - else - *sw_mode = dm_sw_gfx7_2d_thin_gl; -#endif - break; - default: - ASSERT(0); /* Not supported */ - break; - } -} - -static void swizzle_to_dml_params( - enum swizzle_mode_values swizzle, - unsigned int *sw_mode) -{ - switch (swizzle) { - case DC_SW_LINEAR: - *sw_mode = dm_sw_linear; - break; - case DC_SW_4KB_S: - *sw_mode = dm_sw_4kb_s; - break; - case DC_SW_4KB_S_X: - *sw_mode = dm_sw_4kb_s_x; - break; - case DC_SW_4KB_D: - *sw_mode = dm_sw_4kb_d; - break; - case DC_SW_4KB_D_X: - *sw_mode = dm_sw_4kb_d_x; - break; - case DC_SW_64KB_S: - *sw_mode = dm_sw_64kb_s; - break; - case DC_SW_64KB_S_X: - *sw_mode = dm_sw_64kb_s_x; - break; - case DC_SW_64KB_S_T: - *sw_mode = dm_sw_64kb_s_t; - break; - case DC_SW_64KB_D: - *sw_mode = dm_sw_64kb_d; - break; - case DC_SW_64KB_D_X: - *sw_mode = dm_sw_64kb_d_x; - break; - case DC_SW_64KB_D_T: - *sw_mode = dm_sw_64kb_d_t; - break; - case DC_SW_64KB_R_X: - *sw_mode = dm_sw_64kb_r_x; - break; - case DC_SW_VAR_S: - *sw_mode = dm_sw_var_s; - break; - case DC_SW_VAR_S_X: - *sw_mode = dm_sw_var_s_x; - break; - case DC_SW_VAR_D: - *sw_mode = dm_sw_var_d; - break; - case DC_SW_VAR_D_X: - *sw_mode = dm_sw_var_d_x; - break; - - default: - ASSERT(0); /* Not supported */ - break; - } -} - -static void dc_timing_to_dml_timing(const struct dc_crtc_timing *timing, struct _vcs_dpi_display_pipe_dest_params_st *dest) -{ - dest->hblank_start = timing->h_total - timing->h_front_porch; - dest->hblank_end = dest->hblank_start - - timing->h_addressable - - timing->h_border_left - - timing->h_border_right; - dest->vblank_start = timing->v_total - timing->v_front_porch; - dest->vblank_end = dest->vblank_start - - timing->v_addressable - - timing->v_border_top - - timing->v_border_bottom; - dest->htotal = timing->h_total; - dest->vtotal = timing->v_total; - dest->hactive = timing->h_addressable; - dest->vactive = timing->v_addressable; - dest->interlaced = timing->flags.INTERLACE; - dest->pixel_rate_mhz = timing->pix_clk_100hz/10000.0; - if (timing->timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING) - dest->pixel_rate_mhz *= 2; -} - -static enum odm_combine_mode get_dml_odm_combine(const struct pipe_ctx *pipe) -{ - int odm_split_count = 0; - enum odm_combine_mode combine_mode = dm_odm_combine_mode_disabled; - struct pipe_ctx *next_pipe = pipe->next_odm_pipe; - - // Traverse pipe tree to determine odm split count - while (next_pipe) { - odm_split_count++; - next_pipe = next_pipe->next_odm_pipe; - } - pipe = pipe->prev_odm_pipe; - while (pipe) { - odm_split_count++; - pipe = pipe->prev_odm_pipe; - } - - // Translate split to DML odm combine factor - switch (odm_split_count) { - case 1: - combine_mode = dm_odm_combine_mode_2to1; - break; - case 3: - combine_mode = dm_odm_combine_mode_4to1; - break; - default: - combine_mode = dm_odm_combine_mode_disabled; - } - - return combine_mode; -} - -static int get_dml_output_type(enum signal_type dc_signal) -{ - int dml_output_type = -1; - - switch (dc_signal) { - case SIGNAL_TYPE_DISPLAY_PORT_MST: - case SIGNAL_TYPE_DISPLAY_PORT: - dml_output_type = dm_dp; - break; - case SIGNAL_TYPE_EDP: - dml_output_type = dm_edp; - break; - case SIGNAL_TYPE_HDMI_TYPE_A: - case SIGNAL_TYPE_DVI_SINGLE_LINK: - case SIGNAL_TYPE_DVI_DUAL_LINK: - dml_output_type = dm_hdmi; - break; - default: - break; - } - - return dml_output_type; -} - -static void populate_color_depth_and_encoding_from_timing(const struct dc_crtc_timing *timing, struct _vcs_dpi_display_output_params_st *dout) -{ - int output_bpc = 0; - - switch (timing->display_color_depth) { - case COLOR_DEPTH_666: - output_bpc = 6; - break; - case COLOR_DEPTH_888: - output_bpc = 8; - break; - case COLOR_DEPTH_101010: - output_bpc = 10; - break; - case COLOR_DEPTH_121212: - output_bpc = 12; - break; - case COLOR_DEPTH_141414: - output_bpc = 14; - break; - case COLOR_DEPTH_161616: - output_bpc = 16; - break; - case COLOR_DEPTH_999: - output_bpc = 9; - break; - case COLOR_DEPTH_111111: - output_bpc = 11; - break; - default: - output_bpc = 8; - break; - } - - switch (timing->pixel_encoding) { - case PIXEL_ENCODING_RGB: - case PIXEL_ENCODING_YCBCR444: - dout->output_format = dm_444; - dout->output_bpp = output_bpc * 3; - break; - case PIXEL_ENCODING_YCBCR420: - dout->output_format = dm_420; - dout->output_bpp = (output_bpc * 3.0) / 2; - break; - case PIXEL_ENCODING_YCBCR422: - if (timing->flags.DSC && !timing->dsc_cfg.ycbcr422_simple) - dout->output_format = dm_n422; - else - dout->output_format = dm_s422; - dout->output_bpp = output_bpc * 2; - break; - default: - dout->output_format = dm_444; - dout->output_bpp = output_bpc * 3; - } -} - -static enum source_format_class dc_source_format_to_dml_source_format(enum surface_pixel_format dc_format) -{ - enum source_format_class dml_format = dm_444_32; - - switch (dc_format) { - case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: - case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: - dml_format = dm_420_8; - break; - case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: - case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: - dml_format = dm_420_10; - break; - case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: - case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: - case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: - dml_format = dm_444_64; - break; - case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: - case SURFACE_PIXEL_FORMAT_GRPH_RGB565: - dml_format = dm_444_16; - break; - case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: - dml_format = dm_444_8; - break; - case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA: - dml_format = dm_rgbe_alpha; - break; - default: - dml_format = dm_444_32; - break; - } - - return dml_format; -} - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index b3d0a4ea2446..8919a2092ac5 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -399,6 +399,10 @@ struct pipe_ctx { struct dc_stream_state *stream; struct plane_resource plane_res; + + /** + * @stream_res: Reference to DCN resource components such OPP and DSC. + */ struct stream_resource stream_res; struct link_resource link_res; diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h index 6682d9e181c6..b304d450b038 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h @@ -194,6 +194,11 @@ enum dc_status dpcd_configure_lttpr_mode( enum dp_link_encoding dp_get_link_encoding_format(const struct dc_link_settings *link_settings); bool dp_retrieve_lttpr_cap(struct dc_link *link); +bool dp_is_lttpr_present(struct dc_link *link); +enum lttpr_mode dp_decide_lttpr_mode(struct dc_link *link, struct dc_link_settings *link_setting); +void dp_get_lttpr_mode_override(struct dc_link *link, enum lttpr_mode *override); +enum lttpr_mode dp_decide_8b_10b_lttpr_mode(struct dc_link *link); +enum lttpr_mode dp_decide_128b_132b_lttpr_mode(struct dc_link *link); bool dpcd_write_128b_132b_sst_payload_allocation_table( const struct dc_stream_state *stream, struct dc_link *link, diff --git a/drivers/gpu/drm/amd/display/dc/inc/dml_wrapper.h b/drivers/gpu/drm/amd/display/dc/inc/dml_wrapper.h deleted file mode 100644 index 5dcfbd8e2697..000000000000 --- a/drivers/gpu/drm/amd/display/dc/inc/dml_wrapper.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2015 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef DML_WRAPPER_H_ -#define DML_WRAPPER_H_ - -#include "dc.h" -#include "dml/display_mode_vba.h" - -bool dml_validate(struct dc *dc, struct dc_state *context, bool fast_validate); - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h index 68c2ed434d2c..cff5fd55a0ad 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h @@ -340,6 +340,8 @@ struct clk_mgr_internal { bool smu_present; void *wm_range_table; long long wm_range_table_addr; + + bool dpm_present; }; struct clk_mgr_internal_funcs { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h index d89bd55f110f..cd2be729846b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h @@ -268,6 +268,20 @@ enum dc_lut_mode { LUT_RAM_B }; +enum symclk_state { + SYMCLK_OFF_TX_OFF, + SYMCLK_ON_TX_ON, + SYMCLK_ON_TX_OFF, +}; + +struct phy_state { + struct { + uint8_t otg : 1; + uint8_t reserved : 7; + } symclk_ref_cnts; + enum symclk_state symclk_state; +}; + /** * speakersToChannels * diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h index 5097037e3962..8d86159d9de0 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h @@ -22,6 +22,16 @@ * */ +/** + * DOC: mpc-overview + * + * Multiple Pipe/Plane Combined (MPC) is a component in the hardware pipeline + * that performs blending of multiple planes, using global and per-pixel alpha. + * It also performs post-blending color correction operations according to the + * hardware capabilities, such as color transformation matrix and gamma 1D and + * 3D LUT. + */ + #ifndef __DC_MPCC_H__ #define __DC_MPCC_H__ @@ -48,14 +58,39 @@ enum mpcc_blend_mode { MPCC_BLEND_MODE_TOP_BOT_BLENDING }; +/** + * enum mpcc_alpha_blend_mode - define the alpha blend mode regarding pixel + * alpha and plane alpha values + */ enum mpcc_alpha_blend_mode { + /** + * @MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA: per pixel alpha using DPP + * alpha value + */ MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA, + /** + * @MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA_COMBINED_GLOBAL_GAIN: per + * pixel alpha using DPP alpha value multiplied by a global gain (plane + * alpha) + */ MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA_COMBINED_GLOBAL_GAIN, + /** + * @MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA: global alpha value, ignores + * pixel alpha and consider only plane alpha + */ MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA }; -/* - * MPCC blending configuration +/** + * struct mpcc_blnd_cfg - MPCC blending configuration + * + * @black_color: background color + * @alpha_mode: alpha blend mode (MPCC_ALPHA_BLND_MODE) + * @pre_multiplied_alpha: whether pixel color values were pre-multiplied by the + * alpha channel (MPCC_ALPHA_MULTIPLIED_MODE) + * @global_gain: used when blend mode considers both pixel alpha and plane + * alpha value and assumes the global alpha value. + * @global_alpha: plane alpha value */ struct mpcc_blnd_cfg { struct tg_color black_color; /* background color */ @@ -107,8 +142,15 @@ struct mpc_dwb_flow_control { int flow_ctrl_cnt1; }; -/* - * MPCC connection and blending configuration for a single MPCC instance. +/** + * struct mpcc - MPCC connection and blending configuration for a single MPCC instance. + * @mpcc_id: MPCC physical instance + * @dpp_id: DPP input to this MPCC + * @mpcc_bot: pointer to bottom layer MPCC. NULL when not connected. + * @blnd_cfg: the blending configuration for this MPCC + * @sm_cfg: stereo mix setting for this MPCC + * @shared_bottom: if MPCC output to both OPP and DWB endpoints, true. Otherwise, false. + * * This struct is used as a node in an MPC tree. */ struct mpcc { @@ -120,8 +162,12 @@ struct mpcc { bool shared_bottom; /* TRUE if MPCC output to both OPP and DWB endpoints, else FALSE */ }; -/* - * MPC tree represents all MPCC connections for a pipe. +/** + * struct mpc_tree - MPC tree represents all MPCC connections for a pipe. + * + * @opp_id: the OPP instance that owns this MPC tree + * @opp_list: the top MPCC layer of the MPC tree that outputs to OPP endpoint + * */ struct mpc_tree { int opp_id; /* The OPP instance that owns this MPC tree */ @@ -149,13 +195,18 @@ struct mpcc_state { uint32_t busy; }; +/** + * struct mpc_funcs - funcs + */ struct mpc_funcs { void (*read_mpcc_state)( struct mpc *mpc, int mpcc_inst, struct mpcc_state *s); - /* + /** + * @insert_plane: + * * Insert DPP into MPC tree based on specified blending position. * Only used for planes that are part of blending chain for OPP output * @@ -180,7 +231,9 @@ struct mpc_funcs { int dpp_id, int mpcc_id); - /* + /** + * @remove_mpcc: + * * Remove a specified MPCC from the MPC tree. * * Parameters: @@ -195,7 +248,9 @@ struct mpc_funcs { struct mpc_tree *tree, struct mpcc *mpcc); - /* + /** + * @mpc_init: + * * Reset the MPCC HW status by disconnecting all muxes. * * Parameters: @@ -208,7 +263,9 @@ struct mpc_funcs { struct mpc *mpc, unsigned int mpcc_id); - /* + /** + * @update_blending: + * * Update the blending configuration for a specified MPCC. * * Parameters: @@ -223,7 +280,9 @@ struct mpc_funcs { struct mpcc_blnd_cfg *blnd_cfg, int mpcc_id); - /* + /** + * @cursor_lock: + * * Lock cursor updates for the specified OPP. * OPP defines the set of MPCC that are locked together for cursor. * @@ -239,8 +298,10 @@ struct mpc_funcs { int opp_id, bool lock); - /* - * Add DPP into 'secondary' MPC tree based on specified blending position. + /** + * @insert_plane_to_secondary: + * + * Add DPP into secondary MPC tree based on specified blending position. * Only used for planes that are part of blending chain for DWB output * * Parameters: @@ -264,7 +325,9 @@ struct mpc_funcs { int dpp_id, int mpcc_id); - /* + /** + * @remove_mpcc_from_secondary: + * * Remove a specified DPP from the 'secondary' MPC tree. * * Parameters: diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index 4cfa733cf96f..72eef7a5ed83 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -137,7 +137,13 @@ struct crc_params { bool enable; }; +/** + * struct timing_generator - Entry point to Output Timing Generator feature. + */ struct timing_generator { + /** + * @funcs: Timing generator control functions + */ const struct timing_generator_funcs *funcs; struct dc_bios *bp; struct dc_context *ctx; @@ -148,7 +154,9 @@ struct dc_crtc_timing; struct drr_params; - +/** + * struct timing_generator_funcs - Control timing generator on a given device. + */ struct timing_generator_funcs { bool (*validate_timing)(struct timing_generator *tg, const struct dc_crtc_timing *timing); @@ -273,8 +281,8 @@ struct timing_generator_funcs { const struct crc_params *params); /** - * Get CRCs for the given timing generator. Return false if CRCs are - * not enabled (via configure_crc). + * @get_crc: Get CRCs for the given timing generator. Return false if + * CRCs are not enabled (via configure_crc). */ bool (*get_crc)(struct timing_generator *tg, uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index ccb3c719fc4d..d04b68dad413 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -32,11 +32,6 @@ #include "inc/hw/link_encoder.h" #include "core_status.h" -enum vline_select { - VLINE0, - VLINE1 -}; - struct pipe_ctx; struct dc_state; struct dc_stream_status; @@ -48,6 +43,7 @@ struct dc_phy_addr_space_config; struct dc_virtual_addr_space_config; struct dpp; struct dce_hwseq; +struct link_resource; struct hw_sequencer_funcs { void (*hardware_release)(struct dc *dc); @@ -88,6 +84,7 @@ struct hw_sequencer_funcs { struct pipe_ctx *pipe_ctx, bool enableTripleBuffer); void (*update_pending_status)(struct pipe_ctx *pipe_ctx); void (*power_down)(struct dc *dc); + void (*update_dsc_pg)(struct dc *dc, struct dc_state *context, bool safe_to_disable); /* Pipe Lock Related */ void (*pipe_control_lock)(struct dc *dc, @@ -116,8 +113,7 @@ struct hw_sequencer_funcs { int group_index, int group_size, struct pipe_ctx *grouped_pipes[]); void (*setup_periodic_interrupt)(struct dc *dc, - struct pipe_ctx *pipe_ctx, - enum vline_select vline); + struct pipe_ctx *pipe_ctx); void (*set_drr)(struct pipe_ctx **pipe_ctx, int num_pipes, struct dc_crtc_timing_adjust adjust); void (*set_static_screen_control)(struct pipe_ctx **pipe_ctx, @@ -218,6 +214,25 @@ struct hw_sequencer_funcs { void (*set_pipe)(struct pipe_ctx *pipe_ctx); + void (*enable_dp_link_output)(struct dc_link *link, + const struct link_resource *link_res, + enum signal_type signal, + enum clock_source_id clock_source, + const struct dc_link_settings *link_settings); + void (*enable_tmds_link_output)(struct dc_link *link, + const struct link_resource *link_res, + enum signal_type signal, + enum clock_source_id clock_source, + enum dc_color_depth color_depth, + uint32_t pixel_clock); + void (*enable_lvds_link_output)(struct dc_link *link, + const struct link_resource *link_res, + enum clock_source_id clock_source, + uint32_t pixel_clock); + void (*disable_link_output)(struct dc_link *link, + const struct link_resource *link_res, + enum signal_type signal); + void (*get_dcc_en_bits)(struct dc *dc, int *dcc_en_bits); /* Idle Optimization Related */ @@ -245,6 +260,10 @@ struct hw_sequencer_funcs { struct tg_color *color, int mpcc_id); + void (*update_phantom_vp_position)(struct dc *dc, + struct dc_state *context, + struct pipe_ctx *phantom_pipe); + void (*commit_subvp_config)(struct dc *dc, struct dc_state *context); void (*subvp_pipe_control_lock)(struct dc *dc, struct dc_state *context, @@ -271,6 +290,11 @@ void get_surface_visual_confirm_color( const struct pipe_ctx *pipe_ctx, struct tg_color *color); +void get_subvp_visual_confirm_color( + struct dc *dc, + struct pipe_ctx *pipe_ctx, + struct tg_color *color); + void get_hdr_visual_confirm_color( struct pipe_ctx *pipe_ctx, struct tg_color *color); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h index 1cdea0efe5c1..a4d61bb724b6 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h @@ -124,6 +124,8 @@ struct hwseq_private_funcs { void (*dsc_pg_control)(struct dce_hwseq *hws, unsigned int dsc_inst, bool power_on); + bool (*dsc_pg_status)(struct dce_hwseq *hws, + unsigned int dsc_inst); void (*update_odm)(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx); void (*program_all_writeback_pipes_in_tree)(struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h index 3482a877b6af..89964c980b87 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h @@ -55,9 +55,6 @@ struct link_hwss_ext { enum signal_type signal, enum clock_source_id clock_source, const struct dc_link_settings *link_settings); - void (*disable_dp_link_output)(struct dc_link *link, - const struct link_resource *link_res, - enum signal_type signal); void (*set_dp_link_test_pattern)(struct dc_link *link, const struct link_resource *link_res, struct encoder_set_dp_phy_pattern_param *tp_params); @@ -79,6 +76,9 @@ struct link_hwss { void (*setup_stream_encoder)(struct pipe_ctx *pipe_ctx); void (*reset_stream_encoder)(struct pipe_ctx *pipe_ctx); void (*setup_stream_attribute)(struct pipe_ctx *pipe_ctx); + void (*disable_link_output)(struct dc_link *link, + const struct link_resource *link_res, + enum signal_type signal); }; #endif /* __DC_LINK_HWSS_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 7614125c92c7..c37d1141febe 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -228,4 +228,6 @@ uint8_t resource_transmitter_to_phy_idx(const struct dc *dc, enum transmitter tr const struct link_hwss *get_link_hwss(const struct dc_link *link, const struct link_resource *link_res); +bool is_h_timing_divisible_by_2(struct dc_stream_state *stream); + #endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.c b/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.c index 5e92019539c8..4227adbc646a 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.c @@ -130,7 +130,7 @@ void enable_dio_dp_link_output(struct dc_link *link, dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_LINK_PHY); } -void disable_dio_dp_link_output(struct dc_link *link, +void disable_dio_link_output(struct dc_link *link, const struct link_resource *link_res, enum signal_type signal) { @@ -174,10 +174,10 @@ static const struct link_hwss dio_link_hwss = { .setup_stream_encoder = setup_dio_stream_encoder, .reset_stream_encoder = reset_dio_stream_encoder, .setup_stream_attribute = setup_dio_stream_attribute, + .disable_link_output = disable_dio_link_output, .ext = { .set_throttled_vcp_size = set_dio_throttled_vcp_size, .enable_dp_link_output = enable_dio_dp_link_output, - .disable_dp_link_output = disable_dio_dp_link_output, .set_dp_link_test_pattern = set_dio_dp_link_test_pattern, .set_dp_lane_settings = set_dio_dp_lane_settings, .update_stream_allocation_table = update_dio_stream_allocation_table, diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.h b/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.h index 08f22b32df48..126d37f847a1 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.h +++ b/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.h @@ -40,7 +40,7 @@ void enable_dio_dp_link_output(struct dc_link *link, enum signal_type signal, enum clock_source_id clock_source, const struct dc_link_settings *link_settings); -void disable_dio_dp_link_output(struct dc_link *link, +void disable_dio_link_output(struct dc_link *link, const struct link_resource *link_res, enum signal_type signal); void set_dio_dp_link_test_pattern(struct dc_link *link, diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dpia.c b/drivers/gpu/drm/amd/display/dc/link/link_hwss_dpia.c index 89d4e8159138..64f7ea6a9aa3 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dpia.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_hwss_dpia.c @@ -56,10 +56,10 @@ static const struct link_hwss dpia_link_hwss = { .setup_stream_encoder = setup_dio_stream_encoder, .reset_stream_encoder = reset_dio_stream_encoder, .setup_stream_attribute = setup_dio_stream_attribute, + .disable_link_output = disable_dio_link_output, .ext = { .set_throttled_vcp_size = set_dio_throttled_vcp_size, .enable_dp_link_output = enable_dio_dp_link_output, - .disable_dp_link_output = disable_dio_dp_link_output, .set_dp_link_test_pattern = set_dio_dp_link_test_pattern, .set_dp_lane_settings = set_dio_dp_lane_settings, .update_stream_allocation_table = update_dpia_stream_allocation_table, diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.c b/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.c index 226af06278ce..7d3147175ca2 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.c @@ -266,11 +266,11 @@ static const struct link_hwss hpo_dp_link_hwss = { .setup_stream_encoder = setup_hpo_dp_stream_encoder, .reset_stream_encoder = reset_hpo_dp_stream_encoder, .setup_stream_attribute = setup_hpo_dp_stream_attribute, + .disable_link_output = disable_hpo_dp_link_output, .ext = { .set_throttled_vcp_size = set_hpo_dp_throttled_vcp_size, .set_hblank_min_symbol_width = set_hpo_dp_hblank_min_symbol_width, .enable_dp_link_output = enable_hpo_dp_link_output, - .disable_dp_link_output = disable_hpo_dp_link_output, .set_dp_link_test_pattern = set_hpo_dp_link_test_pattern, .set_dp_lane_settings = set_hpo_dp_lane_settings, .update_stream_allocation_table = update_hpo_dp_stream_allocation_table, diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_hwss.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_hwss.c index 501173ce270e..9522fe0b36c9 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_hwss.c @@ -36,10 +36,18 @@ void virtual_setup_stream_attribute(struct pipe_ctx *pipe_ctx) void virtual_reset_stream_encoder(struct pipe_ctx *pipe_ctx) { } + +void virtual_disable_link_output(struct dc_link *link, + const struct link_resource *link_res, + enum signal_type signal) +{ +} + static const struct link_hwss virtual_link_hwss = { .setup_stream_encoder = virtual_setup_stream_encoder, .reset_stream_encoder = virtual_reset_stream_encoder, .setup_stream_attribute = virtual_setup_stream_attribute, + .disable_link_output = virtual_disable_link_output, }; const struct link_hwss *get_virtual_link_hwss(void) diff --git a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h index ced176d17bae..f34c45b19fcb 100644 --- a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h +++ b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h @@ -441,6 +441,7 @@ struct dmub_srv { /* Feature capabilities reported by fw */ struct dmub_feature_caps feature_caps; + struct dmub_visual_confirm_color visual_confirm_color; }; /** diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index d7f3619352f0..5d1aadade8a5 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -234,8 +234,7 @@ union dmub_psr_debug_flags { }; /** - * DMUB feature capabilities. - * After DMUB init, driver will query FW capabilities prior to enabling certain features. + * DMUB visual confirm color */ struct dmub_feature_caps { /** @@ -246,6 +245,16 @@ struct dmub_feature_caps { uint8_t reserved[6]; }; +struct dmub_visual_confirm_color { + /** + * Maximum 10 bits color value + */ + uint16_t color_r_cr; + uint16_t color_g_y; + uint16_t color_b_cb; + uint16_t panel_inst; +}; + #if defined(__cplusplus) } #endif @@ -645,6 +654,10 @@ enum dmub_cmd_type { */ DMUB_CMD__QUERY_FEATURE_CAPS = 6, /** + * Command type used to get visual confirm color. + */ + DMUB_CMD__GET_VISUAL_CONFIRM_COLOR = 8, + /** * Command type used for all PSR commands. */ DMUB_CMD__PSR = 64, @@ -747,6 +760,11 @@ enum dmub_cmd_dpia_type { DMUB_CMD__DPIA_MST_ALLOC_SLOTS = 2, }; +enum dmub_cmd_header_sub_type { + DMUB_CMD__SUB_TYPE_GENERAL = 0, + DMUB_CMD__SUB_TYPE_CURSOR_POSITION = 1 +}; + #pragma pack(push, 1) /** @@ -976,8 +994,17 @@ struct dmub_cmd_fw_assisted_mclk_switch_pipe_data_v2 { uint16_t vtotal; uint8_t main_pipe_index; uint8_t phantom_pipe_index; + /* Since the microschedule is calculated in terms of OTG lines, + * include any scaling factors to make sure when we get accurate + * conversion when programming MALL_START_LINE (which is in terms + * of HUBP lines). If 4K is being downscaled to 1080p, scale factor + * is 1/2 (numerator = 1, denominator = 2). + */ + uint8_t scale_factor_numerator; + uint8_t scale_factor_denominator; uint8_t is_drr; - uint8_t padding; + uint8_t main_split_pipe_index; + uint8_t phantom_split_pipe_index; } subvp_data; struct { @@ -999,7 +1026,11 @@ struct dmub_cmd_fw_assisted_mclk_switch_pipe_data_v2 { } vblank_data; } pipe_config; - enum mclk_switch_mode mode; + /* - subvp_data in the union (pipe_config) takes up 27 bytes. + * - Make the "mode" field a uint8_t instead of enum so we only use 1 byte (only + * for the DMCUB command, cast to enum once we populate the DMCUB subvp state). + */ + uint8_t mode; // enum mclk_switch_mode }; /** @@ -2766,6 +2797,31 @@ struct dmub_rb_cmd_query_feature_caps { struct dmub_cmd_query_feature_caps_data query_feature_caps_data; }; +/** + * Data passed from driver to FW in a DMUB_CMD__GET_VISUAL_CONFIRM_COLOR command. + */ +struct dmub_cmd_visual_confirm_color_data { + /** + * DMUB feature capabilities. + * After DMUB init, driver will query FW capabilities prior to enabling certain features. + */ +struct dmub_visual_confirm_color visual_confirm_color; +}; + +/** + * Definition of a DMUB_CMD__GET_VISUAL_CONFIRM_COLOR command. + */ +struct dmub_rb_cmd_get_visual_confirm_color { + /** + * Command header. + */ + struct dmub_cmd_header header; + /** + * Data passed from driver to FW in a DMUB_CMD__GET_VISUAL_CONFIRM_COLOR command. + */ + struct dmub_cmd_visual_confirm_color_data visual_confirm_color_data; +}; + struct dmub_optc_state { uint32_t v_total_max; uint32_t v_total_min; @@ -3138,6 +3194,11 @@ union dmub_rb_cmd { * Definition of a DMUB_CMD__QUERY_FEATURE_CAPS command. */ struct dmub_rb_cmd_query_feature_caps query_feature_caps; + + /** + * Definition of a DMUB_CMD__GET_VISUAL_CONFIRM_COLOR command. + */ + struct dmub_rb_cmd_get_visual_confirm_color visual_confirm_color; struct dmub_rb_cmd_drr_update drr_update; struct dmub_rb_cmd_fw_assisted_mclk_switch fw_assisted_mclk_switch; diff --git a/drivers/gpu/drm/amd/display/include/dal_asic_id.h b/drivers/gpu/drm/amd/display/include/dal_asic_id.h index 9f3558c0ef11..c3089c673975 100644 --- a/drivers/gpu/drm/amd/display/include/dal_asic_id.h +++ b/drivers/gpu/drm/amd/display/include/dal_asic_id.h @@ -215,6 +215,7 @@ enum { #define DEVICE_ID_NV_143F 0x143F #define FAMILY_VGH 144 #define DEVICE_ID_VGH_163F 0x163F +#define DEVICE_ID_VGH_1435 0x1435 #define VANGOGH_A0 0x01 #define VANGOGH_UNKNOWN 0xFF diff --git a/drivers/gpu/drm/amd/display/include/ddc_service_types.h b/drivers/gpu/drm/amd/display/include/ddc_service_types.h index 05096c644a60..a7ba5bd8dc16 100644 --- a/drivers/gpu/drm/amd/display/include/ddc_service_types.h +++ b/drivers/gpu/drm/amd/display/include/ddc_service_types.h @@ -128,8 +128,8 @@ struct av_sync_data { uint8_t aud_del_ins3;/* DPCD 0002Dh */ }; -static const uint8_t DP_SINK_DEVICE_STR_ID_1[] = {7, 1, 8, 7, 3, 0}; -static const uint8_t DP_SINK_DEVICE_STR_ID_2[] = {7, 1, 8, 7, 5, 0}; +static const uint8_t DP_SINK_DEVICE_STR_ID_1[] = {7, 1, 8, 7, 3}; +static const uint8_t DP_SINK_DEVICE_STR_ID_2[] = {7, 1, 8, 7, 5}; static const u8 DP_SINK_BRANCH_DEV_NAME_7580[] = "7580\x80u"; diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h index 79fabc51c991..d1e91d31d151 100644 --- a/drivers/gpu/drm/amd/display/include/link_service_types.h +++ b/drivers/gpu/drm/amd/display/include/link_service_types.h @@ -83,6 +83,7 @@ enum link_training_result { }; enum lttpr_mode { + LTTPR_MODE_UNKNOWN, LTTPR_MODE_NON_LTTPR, LTTPR_MODE_TRANSPARENT, LTTPR_MODE_NON_TRANSPARENT, @@ -246,8 +247,16 @@ union dpcd_training_lane_set { }; +/* AMD's copy of various payload data for MST. We have two copies of the payload table (one in DRM, + * one in DC) since DRM's MST helpers can't be accessed here. This stream allocation table should + * _ONLY_ be filled out from DM and then passed to DC, do NOT use these for _any_ kind of atomic + * state calculations in DM, or you will break something. + */ + +struct drm_dp_mst_port; + /* DP MST stream allocation (payload bandwidth number) */ -struct dp_mst_stream_allocation { +struct dc_dp_mst_stream_allocation { uint8_t vcp_id; /* number of slots required for the DP stream in * transport packet */ @@ -255,11 +264,11 @@ struct dp_mst_stream_allocation { }; /* DP MST stream allocation table */ -struct dp_mst_stream_allocation_table { +struct dc_dp_mst_stream_allocation_table { /* number of DP video streams */ int stream_count; /* array of stream allocations */ - struct dp_mst_stream_allocation stream_allocations[MAX_CONTROLLER_NUM]; + struct dc_dp_mst_stream_allocation stream_allocations[MAX_CONTROLLER_NUM]; }; #endif /*__DAL_LINK_SERVICE_TYPES_H__*/ |