diff options
author | Dave Airlie | 2017-10-23 03:17:54 +0200 |
---|---|---|
committer | Dave Airlie | 2017-10-23 03:17:54 +0200 |
commit | af9111336071ee9378e1db70ac8f4c2b7fcd17a1 (patch) | |
tree | 1e60c1bd032ba2bcb2e1b1d0b611195e66314bd8 /drivers/gpu | |
parent | Merge remote-tracking branch 'pfdo/drm-next' into drm-next (diff) | |
parent | drm/amd/display:: Fix NULL pointer in Raven hotplug (diff) | |
download | kernel-qcow2-linux-af9111336071ee9378e1db70ac8f4c2b7fcd17a1.tar.gz kernel-qcow2-linux-af9111336071ee9378e1db70ac8f4c2b7fcd17a1.tar.xz kernel-qcow2-linux-af9111336071ee9378e1db70ac8f4c2b7fcd17a1.zip |
Merge branch 'drm-next-4.15-dc' of git://people.freedesktop.org/~agd5f/linux into drm-next
Last batch of new stuff for DC. Highlights:
- Fix some memory leaks
- S3 fixes
- Hotplug fixes
- Fix some CX multi-display issues
- MST fixes
- DML updates from the hw team
- Various code cleanups
- Misc bug fixes
* 'drm-next-4.15-dc' of git://people.freedesktop.org/~agd5f/linux: (155 commits)
drm/amd/display:: Fix NULL pointer in Raven hotplug
drm/amd/display: Fix memoryleak during S3 resume.
drm/amd/display: add hardware_planes_only to list of affected planes
drm/amd/display: Fix brace style
drm/amd/display: Remove needless cast in amdgpu_dm_connector_init()
drm/amd/display: Fix brace style in amdgpu_dm_connector_ddc_get_modes()
drm/amd/display: Tidy up dm_drm_plane_reset()
drm/amd/display: Fix indentation in create_eml_sink()
drm/amd/display: Replace block with strncpy() in fill_audio_info()
drm/amd/display: Fix brace style in amdgpu_dm_initialize_drm_device()
drm/amd/display: Simplify handle_hpd_rx_irq()
drm/amd/display: Fix brace style in dm_handle_hpd_rx_irq()
drm/amd/display: Fix brace style in amdgpu_dm_update_connector_after_detect()
drm/amd/display: Fix indentation in dm_resume()
drm/amd/display: Fix indentation in dm_suspend()
drm/amd/display: Simplify dm_late_init()
amdgpu/dc: inline dml_round_to_multiple
amdgpu/dc: drop dml_util_is_420
drm/amd/display: Add bunch of missing license headers in DML
amdgpu/dc: inline a bunch of the dml wrappers.
...
Diffstat (limited to 'drivers/gpu')
88 files changed, 13890 insertions, 6064 deletions
diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig index 6d1086d0a277..ec3285f65517 100644 --- a/drivers/gpu/drm/amd/display/Kconfig +++ b/drivers/gpu/drm/amd/display/Kconfig @@ -17,6 +17,16 @@ config DRM_AMD_DC_PRE_VEGA by default. This includes Polaris, Carrizo, Tonga, Bonaire, and Hawaii. +config DRM_AMD_DC_FBC + bool "AMD FBC - Enable Frame Buffer Compression" + depends on DRM_AMD_DC + help + Choose this option if you want to use frame buffer compression + support. + This is a power optimisation feature, check its availability + on your hardware before enabling this option. + + config DRM_AMD_DC_DCN1_0 bool "DCN 1.0 Raven family" depends on DRM_AMD_DC && X86 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 8cc228ebdc9a..d0ee1b3b8b5c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -538,9 +538,8 @@ static int detect_mst_link_for_all_connectors(struct drm_device *dev) static int dm_late_init(void *handle) { struct drm_device *dev = ((struct amdgpu_device *)handle)->ddev; - int r = detect_mst_link_for_all_connectors(dev); - return r; + return detect_mst_link_for_all_connectors(dev); } static void s3_handle_mst(struct drm_device *dev, bool suspend) @@ -599,10 +598,7 @@ static int dm_suspend(void *handle) WARN_ON(adev->dm.cached_state); adev->dm.cached_state = drm_atomic_helper_suspend(adev->ddev); - dc_set_power_state( - dm->dc, - DC_ACPI_CM_POWER_STATE_D3 - ); + dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D3); return ret; } @@ -632,10 +628,7 @@ static int dm_resume(void *handle) struct amdgpu_display_manager *dm = &adev->dm; /* power on hardware */ - dc_set_power_state( - dm->dc, - DC_ACPI_CM_POWER_STATE_D0 - ); + dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D0); return 0; } @@ -648,6 +641,11 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev) struct drm_connector *connector; struct drm_crtc *crtc; struct drm_crtc_state *new_crtc_state; + struct dm_crtc_state *dm_crtc_state; + struct drm_plane *plane; + struct drm_plane_state *plane_state; + struct dm_plane_state *dm_plane_state; + struct dm_atomic_state *cached_state; int ret = 0; int i; @@ -686,6 +684,34 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev) for_each_new_crtc_in_state(adev->dm.cached_state, crtc, new_crtc_state, i) new_crtc_state->active_changed = true; + cached_state = to_dm_atomic_state(adev->dm.cached_state); + + /* + * During suspend, the cached state is saved before all streams are + * disabled. Refresh cached state to match actual current state before + * restoring it. + */ + WARN_ON(kref_read(&cached_state->context->refcount) > 1); + dc_release_state(cached_state->context); + + for_each_new_crtc_in_state(adev->dm.cached_state, crtc, new_crtc_state, i) { + dm_crtc_state = to_dm_crtc_state(new_crtc_state); + if (dm_crtc_state->stream) { + WARN_ON(kref_read(&dm_crtc_state->stream->refcount) > 1); + dc_stream_release(dm_crtc_state->stream); + dm_crtc_state->stream = NULL; + } + } + + for_each_new_plane_in_state(adev->dm.cached_state, plane, plane_state, i) { + dm_plane_state = to_dm_plane_state(plane_state); + if (dm_plane_state->dc_state) { + WARN_ON(kref_read(&dm_plane_state->dc_state->refcount) > 1); + dc_plane_state_release(dm_plane_state->dc_state); + dm_plane_state->dc_state = NULL; + } + } + ret = drm_atomic_helper_resume(ddev, adev->dm.cached_state); drm_atomic_state_put(adev->dm.cached_state); @@ -860,9 +886,9 @@ amdgpu_dm_update_connector_after_detect(struct amdgpu_dm_connector *aconnector) connector); aconnector->dc_sink = sink; - if (sink->dc_edid.length == 0) + if (sink->dc_edid.length == 0) { aconnector->edid = NULL; - else { + } else { aconnector->edid = (struct edid *) sink->dc_edid.raw_edid; @@ -980,8 +1006,9 @@ static void dm_handle_hpd_rx_irq(struct amdgpu_dm_connector *aconnector) dpcd_bytes_to_read); new_irq_handled = false; - } else + } else { break; + } } if (process_count == max_process_count) @@ -993,20 +1020,20 @@ static void handle_hpd_rx_irq(void *param) struct amdgpu_dm_connector *aconnector = (struct amdgpu_dm_connector *)param; struct drm_connector *connector = &aconnector->base; struct drm_device *dev = connector->dev; - const struct dc_link *dc_link = aconnector->dc_link; + struct dc_link *dc_link = aconnector->dc_link; bool is_mst_root_connector = aconnector->mst_mgr.mst_state; /* TODO:Temporary add mutex to protect hpd interrupt not have a gpio * conflict, after implement i2c helper, this mutex should be * retired. */ - if (aconnector->dc_link->type != dc_connection_mst_branch) + if (dc_link->type != dc_connection_mst_branch) mutex_lock(&aconnector->hpd_lock); - if (dc_link_handle_hpd_rx_irq(aconnector->dc_link, NULL) && + if (dc_link_handle_hpd_rx_irq(dc_link, NULL) && !is_mst_root_connector) { /* Downstream Port status changed. */ - if (dc_link_detect(aconnector->dc_link, DETECT_REASON_HPDRX)) { + if (dc_link_detect(dc_link, DETECT_REASON_HPDRX)) { amdgpu_dm_update_connector_after_detect(aconnector); @@ -1018,10 +1045,10 @@ static void handle_hpd_rx_irq(void *param) } } if ((dc_link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) || - (dc_link->type == dc_connection_mst_branch)) + (dc_link->type == dc_connection_mst_branch)) dm_handle_hpd_rx_irq(aconnector); - if (aconnector->dc_link->type != dc_connection_mst_branch) + if (dc_link->type != dc_connection_mst_branch) mutex_unlock(&aconnector->hpd_lock); } @@ -1381,9 +1408,8 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) goto fail_free_planes; aencoder = kzalloc(sizeof(*aencoder), GFP_KERNEL); - if (!aencoder) { + if (!aencoder) goto fail_free_connector; - } if (amdgpu_dm_encoder_init(dm->ddev, aencoder, i)) { DRM_ERROR("KMS: Failed to initialize encoder\n"); @@ -1754,7 +1780,9 @@ static int get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb, int r = amdgpu_bo_reserve(rbo, false); if (unlikely(r)) { - DRM_ERROR("Unable to reserve buffer\n"); + // Don't show error msg. when return -ERESTARTSYS + if (r != -ERESTARTSYS) + DRM_ERROR("Unable to reserve buffer: %d\n", r); return r; } @@ -2206,11 +2234,9 @@ static void fill_audio_info(struct audio_info *audio_info, cea_revision = drm_connector->display_info.cea_rev; - while (i < AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS && - edid_caps->display_name[i]) { - audio_info->display_name[i] = edid_caps->display_name[i]; - i++; - } + strncpy(audio_info->display_name, + edid_caps->display_name, + AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS - 1); if (cea_revision >= 3) { audio_info->mode_count = edid_caps->audio_mode_count; @@ -2318,8 +2344,16 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, drm_connector = &aconnector->base; - if (!aconnector->dc_sink) + if (!aconnector->dc_sink) { + /* + * Exclude MST from creating fake_sink + * TODO: need to enable MST into fake_sink feature + */ + if (aconnector->mst_port) + goto stream_create_fail; + create_fake_sink(aconnector); + } stream = dc_create_stream_for_sink(aconnector->dc_sink); @@ -2453,7 +2487,8 @@ amdgpu_dm_connector_detect(struct drm_connector *connector, bool force) * 2. This interface *is called* in context of user-mode ioctl. Which * makes it a bad place for *any* MST-related activit. */ - if (aconnector->base.force == DRM_FORCE_UNSPECIFIED) + if (aconnector->base.force == DRM_FORCE_UNSPECIFIED && + !aconnector->fake_enable) connected = (aconnector->dc_sink != NULL); else connected = (aconnector->base.force == DRM_FORCE_ON); @@ -2681,8 +2716,7 @@ static void create_eml_sink(struct amdgpu_dm_connector *aconnector) (edid->extensions + 1) * EDID_LENGTH, &init_params); - if (aconnector->base.force - == DRM_FORCE_ON) + if (aconnector->base.force == DRM_FORCE_ON) aconnector->dc_sink = aconnector->dc_link->local_sink ? aconnector->dc_link->local_sink : aconnector->dc_em_sink; @@ -2746,7 +2780,7 @@ int amdgpu_dm_connector_mode_valid(struct drm_connector *connector, stream->src.height = mode->vdisplay; stream->dst = stream->src; - if (dc_validate_stream(adev->dm.dc, stream)) + if (dc_validate_stream(adev->dm.dc, stream) == DC_OK) result = MODE_OK; dc_stream_release(stream); @@ -2791,7 +2825,7 @@ static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc, if (!dm_crtc_state->stream) return 0; - if (dc_validate_stream(dc, dm_crtc_state->stream)) + if (dc_validate_stream(dc, dm_crtc_state->stream) == DC_OK) return 0; return ret; @@ -2835,13 +2869,13 @@ static void dm_drm_plane_reset(struct drm_plane *plane) plane->funcs->atomic_destroy_state(plane, plane->state); amdgpu_state = kzalloc(sizeof(*amdgpu_state), GFP_KERNEL); - + WARN_ON(amdgpu_state == NULL); + if (amdgpu_state) { plane->state = &amdgpu_state->base; plane->state->plane = plane; plane->state->rotation = DRM_MODE_ROTATE_0; - } else - WARN_ON(1); + } } static struct drm_plane_state * @@ -2986,7 +3020,7 @@ static int dm_plane_atomic_check(struct drm_plane *plane, if (!dm_plane_state->dc_state) return 0; - if (dc_validate_plane(dc, dm_plane_state->dc_state)) + if (dc_validate_plane(dc, dm_plane_state->dc_state) == DC_OK) return 0; return -EINVAL; @@ -3272,8 +3306,9 @@ static void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector, drm_edid_to_eld(connector, edid); amdgpu_dm_get_native_mode(connector); - } else + } else { amdgpu_dm_connector->num_modes = 0; + } } static int amdgpu_dm_connector_get_modes(struct drm_connector *connector) @@ -3421,7 +3456,8 @@ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, struct dc *dc = dm->dc; struct dc_link *link = dc_get_link_at_index(dc, link_index); struct amdgpu_i2c_adapter *i2c; - ((struct dc_link *)link)->priv = aconnector; + + link->priv = aconnector; DRM_DEBUG_DRIVER("%s()\n", __func__); @@ -3661,10 +3697,10 @@ static void handle_cursor_update(struct drm_plane *plane, return; DRM_DEBUG_DRIVER("%s: crtc_id=%d with size %d to %d\n", - __func__, - amdgpu_crtc->crtc_id, - plane->state->crtc_w, - plane->state->crtc_h); + __func__, + amdgpu_crtc->crtc_id, + plane->state->crtc_w, + plane->state->crtc_h); ret = get_cursor_position(plane, crtc, &position); if (ret) @@ -3691,14 +3727,15 @@ static void handle_cursor_update(struct drm_plane *plane, attributes.pitch = attributes.width; - if (!dc_stream_set_cursor_attributes(crtc_state->stream, - &attributes)) - DRM_ERROR("DC failed to set cursor attributes\n"); + if (crtc_state->stream) { + if (!dc_stream_set_cursor_attributes(crtc_state->stream, + &attributes)) + DRM_ERROR("DC failed to set cursor attributes\n"); - if (crtc_state->stream) if (!dc_stream_set_cursor_position(crtc_state->stream, &position)) DRM_ERROR("DC failed to set cursor position\n"); + } } static void prepare_flip_isr(struct amdgpu_crtc *acrtc) @@ -3726,7 +3763,8 @@ static void prepare_flip_isr(struct amdgpu_crtc *acrtc) */ static void amdgpu_dm_do_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, - uint32_t target) + uint32_t target, + struct dc_state *state) { unsigned long flags; uint32_t target_vblank; @@ -3797,7 +3835,13 @@ static void amdgpu_dm_do_flip(struct drm_crtc *crtc, surface_updates->flip_addr = &addr; - dc_update_planes_and_stream(adev->dm.dc, surface_updates, 1, acrtc_state->stream, NULL); + dc_commit_updates_for_stream(adev->dm.dc, + surface_updates, + 1, + acrtc_state->stream, + NULL, + &surface_updates->surface, + state); DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n", __func__, @@ -3823,6 +3867,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, struct drm_crtc_state *new_pcrtc_state = drm_atomic_get_new_crtc_state(state, pcrtc); struct dm_crtc_state *acrtc_state = to_dm_crtc_state(new_pcrtc_state); + struct dm_atomic_state *dm_state = to_dm_atomic_state(state); int planes_count = 0; unsigned long flags; @@ -3880,7 +3925,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, amdgpu_dm_do_flip( crtc, fb, - drm_crtc_vblank_count(crtc) + *wait_for_vblank); + drm_crtc_vblank_count(crtc) + *wait_for_vblank, + dm_state->context); } } @@ -3900,7 +3946,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, if (false == dc_commit_planes_to_stream(dm->dc, plane_states_constructed, planes_count, - dc_stream_attach)) + dc_stream_attach, + dm_state->context)) dm_error("%s: Failed to attach plane!\n", __func__); } else { /*TODO BUG Here should go disable planes on CRTC. */ @@ -3931,6 +3978,8 @@ static int amdgpu_dm_atomic_commit(struct drm_device *dev, if (drm_atomic_crtc_needs_modeset(new_crtc_state) && dm_old_crtc_state->stream) manage_dm_interrupts(adev, acrtc, false); } + /* Add check here for SoC's that support hardware cursor plane, to + * unset legacy_cursor_update */ return drm_atomic_helper_commit(dev, state, nonblock); @@ -4120,7 +4169,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) dm->dc, status->plane_states, status->plane_count, - dm_new_crtc_state->stream)) + dm_new_crtc_state->stream, + dm_state->context)) dm_error("%s: Failed to update stream scaling!\n", __func__); } @@ -4339,7 +4389,8 @@ static int dm_update_crtcs_state(struct dc *dc, aconnector = amdgpu_dm_find_first_crtc_matching_connector(state, crtc); /* TODO This hack should go away */ - if (aconnector) { + if (aconnector && enable) { + // Make sure fake sink is created in plug-in scenario new_con_state = drm_atomic_get_connector_state(state, &aconnector->base); @@ -4368,12 +4419,13 @@ static int dm_update_crtcs_state(struct dc *dc, } } - if (dc_is_stream_unchanged(new_stream, dm_old_crtc_state->stream)) { + if (dc_is_stream_unchanged(new_stream, dm_old_crtc_state->stream) && + dc_is_stream_scaling_unchanged(new_stream, dm_old_crtc_state->stream)) { new_crtc_state->mode_changed = false; DRM_DEBUG_DRIVER("Mode change not required, setting mode_changed to %d", - new_crtc_state->mode_changed); + new_crtc_state->mode_changed); } @@ -4402,10 +4454,10 @@ static int dm_update_crtcs_state(struct dc *dc, crtc->base.id); /* i.e. reset mode */ - if (!dc_remove_stream_from_ctx( + if (dc_remove_stream_from_ctx( dc, dm_state->context, - dm_old_crtc_state->stream)) { + dm_old_crtc_state->stream) != DC_OK) { ret = -EINVAL; goto fail; } @@ -4416,6 +4468,13 @@ static int dm_update_crtcs_state(struct dc *dc, *lock_and_validation_needed = true; } else {/* Add stream for any updated/enabled CRTC */ + /* + * Quick fix to prevent NULL pointer on new_stream when + * added MST connectors not found in existing crtc_state in the chained mode + * TODO: need to dig out the root cause of that + */ + if (!aconnector || (!aconnector->dc_sink && aconnector->mst_port)) + goto next_crtc; if (modereset_required(new_crtc_state)) goto next_crtc; @@ -4431,10 +4490,10 @@ static int dm_update_crtcs_state(struct dc *dc, DRM_DEBUG_DRIVER("Enabling DRM crtc: %d\n", crtc->base.id); - if (!dc_add_stream_to_ctx( + if (dc_add_stream_to_ctx( dc, dm_state->context, - dm_new_crtc_state->stream)) { + dm_new_crtc_state->stream) != DC_OK) { ret = -EINVAL; goto fail; } @@ -4586,7 +4645,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_connector *connector; struct drm_connector_state *old_con_state, *new_con_state; struct drm_crtc *crtc; - struct drm_crtc_state *new_crtc_state; + struct drm_crtc_state *old_crtc_state, *new_crtc_state; /* * This bool will be set for true for any modeset/reset @@ -4595,18 +4654,34 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, bool lock_and_validation_needed = false; ret = drm_atomic_helper_check_modeset(dev, state); - if (ret) { DRM_ERROR("Atomic state validation failed with error :%d !\n", ret); return ret; } /* - * Hack: Commit needs planes right now, specifically for gamma - * TODO rework commit to check CRTC for gamma change + * legacy_cursor_update should be made false for SoC's having + * a dedicated hardware plane for cursor in amdgpu_dm_atomic_commit(), + * otherwise for software cursor plane, + * we should not add it to list of affected planes. */ - for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { - if (new_crtc_state->color_mgmt_changed) { + if (state->legacy_cursor_update) { + for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { + if (new_crtc_state->color_mgmt_changed) { + ret = drm_atomic_add_affected_planes(state, crtc); + if (ret) + goto fail; + } + } + } else { + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { + if (!new_crtc_state->enable) + continue; + + ret = drm_atomic_add_affected_connectors(state, crtc); + if (ret) + return ret; + ret = drm_atomic_add_affected_planes(state, crtc); if (ret) goto fail; @@ -4684,7 +4759,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, if (ret) goto fail; - if (!dc_validate_global_state(dc, dm_state->context)) { + if (dc_validate_global_state(dc, dm_state->context) != DC_OK) { ret = -EINVAL; goto fail; } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index 52b6e4a91d8b..ca5d0d1581dc 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -208,24 +208,21 @@ static void remove_timer_handler(struct amdgpu_device *adev, DM_IRQ_TABLE_LOCK(adev, irq_table_flags); } - if (handler_in == NULL) { - /* Remove ALL handlers. */ + /* Remove ALL handlers. */ + if (handler_in == NULL) continue; - } - if (handler_in == handler_temp) { - /* Remove a SPECIFIC handler. - * Found our handler - we can stop here. */ + /* Remove a SPECIFIC handler. + * Found our handler - we can stop here. */ + if (handler_in == handler_temp) break; - } } DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); - if (handler_in != NULL && handler_removed == false) { + if (handler_in != NULL && handler_removed == false) DRM_ERROR("DM_IRQ: handler: %p is not in the list!\n", handler_in); - } } static bool @@ -435,7 +432,7 @@ int amdgpu_dm_irq_suspend(struct amdgpu_device *adev) * Disable HW interrupt for HPD and HPDRX only since FLIP and VBLANK * will be disabled from manage_dm_interrupts on disable CRTC. */ - for (src = DC_IRQ_SOURCE_HPD1; src < DC_IRQ_SOURCE_HPD6RX; src++) { + for (src = DC_IRQ_SOURCE_HPD1; src <= DC_IRQ_SOURCE_HPD6RX; src++) { hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head; hnd_list_h = &adev->dm.irq_handler_list_high_tab[src]; if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h)) @@ -462,7 +459,7 @@ int amdgpu_dm_irq_resume_early(struct amdgpu_device *adev) DRM_DEBUG_KMS("DM_IRQ: early resume\n"); /* re-enable short pulse interrupts HW interrupt */ - for (src = DC_IRQ_SOURCE_HPD1RX; src < DC_IRQ_SOURCE_HPD6RX + 1; src++) { + for (src = DC_IRQ_SOURCE_HPD1RX; src <= DC_IRQ_SOURCE_HPD6RX; src++) { hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head; hnd_list_h = &adev->dm.irq_handler_list_high_tab[src]; if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h)) @@ -488,7 +485,7 @@ int amdgpu_dm_irq_resume_late(struct amdgpu_device *adev) * Renable HW interrupt for HPD and only since FLIP and VBLANK * will be enabled from manage_dm_interrupts on enable CRTC. */ - for (src = DC_IRQ_SOURCE_HPD1; src < DC_IRQ_SOURCE_HPD6; src++) { + for (src = DC_IRQ_SOURCE_HPD1; src <= DC_IRQ_SOURCE_HPD6; src++) { hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head; hnd_list_h = &adev->dm.irq_handler_list_high_tab[src]; if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h)) 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 dfcfb5a722e0..3b05da7a90e8 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 @@ -174,14 +174,60 @@ static const struct drm_connector_funcs dm_dp_mst_connector_funcs = { .atomic_get_property = amdgpu_dm_connector_atomic_get_property }; +static int dm_connector_update_modes(struct drm_connector *connector, + struct edid *edid) +{ + int ret; + + ret = drm_add_edid_modes(connector, edid); + drm_edid_to_eld(connector, edid); + + return ret; +} + static int dm_dp_mst_get_modes(struct drm_connector *connector) { struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); int ret = 0; - ret = drm_add_edid_modes(&aconnector->base, aconnector->edid); + if (!aconnector) + return dm_connector_update_modes(connector, NULL); + + if (!aconnector->edid) { + struct edid *edid; + struct dc_sink *dc_sink; + struct dc_sink_init_data init_params = { + .link = aconnector->dc_link, + .sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST }; + edid = drm_dp_mst_get_edid(connector, &aconnector->mst_port->mst_mgr, aconnector->port); - drm_edid_to_eld(&aconnector->base, aconnector->edid); + if (!edid) { + drm_mode_connector_update_edid_property( + &aconnector->base, + NULL); + return ret; + } + + aconnector->edid = edid; + + dc_sink = dc_link_add_remote_sink( + aconnector->dc_link, + (uint8_t *)edid, + (edid->extensions + 1) * EDID_LENGTH, + &init_params); + + dc_sink->priv = aconnector; + aconnector->dc_sink = dc_sink; + + if (aconnector->dc_sink) + amdgpu_dm_add_sink_to_freesync_module( + connector, edid); + + drm_mode_connector_update_edid_property( + &aconnector->base, edid); + } + + ret = dm_connector_update_modes(connector, aconnector->edid); return ret; } @@ -241,9 +287,10 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, struct amdgpu_device *adev = dev->dev_private; struct amdgpu_dm_connector *aconnector; struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; - drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { aconnector = to_amdgpu_dm_connector(connector); if (aconnector->mst_port == master && !aconnector->port) { @@ -253,11 +300,11 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, aconnector->port = port; drm_mode_connector_set_path_property(connector, pathprop); - drm_modeset_unlock(&dev->mode_config.connection_mutex); + drm_connector_list_iter_end(&conn_iter); return &aconnector->base; } } - drm_modeset_unlock(&dev->mode_config.connection_mutex); + drm_connector_list_iter_end(&conn_iter); aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL); if (!aconnector) @@ -343,92 +390,20 @@ static void dm_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr) { struct amdgpu_dm_connector *master = container_of(mgr, struct amdgpu_dm_connector, mst_mgr); struct drm_device *dev = master->base.dev; - struct amdgpu_device *adev = dev->dev_private; - struct drm_connector *connector; - struct amdgpu_dm_connector *aconnector; - struct edid *edid; - struct dc_sink *dc_sink; - - drm_modeset_lock_all(dev); - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - aconnector = to_amdgpu_dm_connector(connector); - if (aconnector->port && - aconnector->port->pdt != DP_PEER_DEVICE_NONE && - aconnector->port->pdt != DP_PEER_DEVICE_MST_BRANCHING && - !aconnector->dc_sink) { - /* - * This is plug in case, where port has been created but - * sink hasn't been created yet - */ - if (!aconnector->edid) { - struct dc_sink_init_data init_params = { - .link = aconnector->dc_link, - .sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST}; - edid = drm_dp_mst_get_edid(connector, &aconnector->mst_port->mst_mgr, aconnector->port); - - if (!edid) { - drm_mode_connector_update_edid_property( - &aconnector->base, - NULL); - continue; - } - - aconnector->edid = edid; - - dc_sink = dc_link_add_remote_sink( - aconnector->dc_link, - (uint8_t *)edid, - (edid->extensions + 1) * EDID_LENGTH, - &init_params); - - dc_sink->priv = aconnector; - aconnector->dc_sink = dc_sink; - - if (aconnector->dc_sink) - amdgpu_dm_add_sink_to_freesync_module( - connector, - edid); - - dm_restore_drm_connector_state(connector->dev, connector); - } else - edid = aconnector->edid; - - DRM_DEBUG_KMS("edid retrieved %p\n", edid); - drm_mode_connector_update_edid_property( - &aconnector->base, - aconnector->edid); - } - } - drm_modeset_unlock_all(dev); - - schedule_work(&adev->dm.mst_hotplug_work); + drm_kms_helper_hotplug_event(dev); } static void dm_dp_mst_register_connector(struct drm_connector *connector) { struct drm_device *dev = connector->dev; struct amdgpu_device *adev = dev->dev_private; - int i; - - drm_modeset_lock_all(dev); - if (adev->mode_info.rfbdev) { - /*Do not add if already registered in past*/ - for (i = 0; i < adev->mode_info.rfbdev->helper.connector_count; i++) { - if (adev->mode_info.rfbdev->helper.connector_info[i]->connector - == connector) { - drm_modeset_unlock_all(dev); - return; - } - } + if (adev->mode_info.rfbdev) drm_fb_helper_add_one_connector(&adev->mode_info.rfbdev->helper, connector); - } else DRM_ERROR("adev->mode_info.rfbdev is NULL\n"); - drm_modeset_unlock_all(dev); - drm_connector_register(connector); } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c index 26bf9918fcb7..5df8fd5b537c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c @@ -35,6 +35,12 @@ #include "amdgpu_dm_irq.h" #include "amdgpu_pm.h" +unsigned long long dm_get_timestamp(struct dc_context *ctx) +{ + /* TODO: return actual timestamp */ + return 0; +} + bool dm_write_persistent_data(struct dc_context *ctx, const struct dc_sink *sink, const char *module_name, diff --git a/drivers/gpu/drm/amd/display/dc/basics/logger.c b/drivers/gpu/drm/amd/display/dc/basics/logger.c index afb6d2d80e0c..e04e8ecd4874 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/logger.c +++ b/drivers/gpu/drm/amd/display/dc/basics/logger.c @@ -80,8 +80,6 @@ static bool construct(struct dc_context *ctx, struct dal_logger *logger, logger->buffer_read_offset = 0; logger->buffer_write_offset = 0; - logger->write_wrap_count = 0; - logger->read_wrap_count = 0; logger->open_count = 0; logger->flags.bits.ENABLE_CONSOLE = 1; @@ -162,23 +160,24 @@ static void log_to_debug_console(struct log_entry *entry) } /* Print everything unread existing in log_buffer to debug console*/ -static void flush_to_debug_console(struct dal_logger *logger) +void dm_logger_flush_buffer(struct dal_logger *logger, bool should_warn) { - int i = logger->buffer_read_offset; - char *string_start = &logger->log_buffer[i]; + char *string_start = &logger->log_buffer[logger->buffer_read_offset]; - dm_output_to_console( - "---------------- FLUSHING LOG BUFFER ----------------\n"); - while (i < logger->buffer_write_offset) { + if (should_warn) + dm_output_to_console( + "---------------- FLUSHING LOG BUFFER ----------------\n"); + while (logger->buffer_read_offset < logger->buffer_write_offset) { - if (logger->log_buffer[i] == '\0') { + if (logger->log_buffer[logger->buffer_read_offset] == '\0') { dm_output_to_console("%s", string_start); - string_start = (char *)logger->log_buffer + i + 1; + string_start = logger->log_buffer + logger->buffer_read_offset + 1; } - i++; + logger->buffer_read_offset++; } - dm_output_to_console( - "-------------- END FLUSHING LOG BUFFER --------------\n\n"); + if (should_warn) + dm_output_to_console( + "-------------- END FLUSHING LOG BUFFER --------------\n\n"); } static void log_to_internal_buffer(struct log_entry *entry) @@ -195,35 +194,17 @@ static void log_to_internal_buffer(struct log_entry *entry) if (size > 0 && size < logger->log_buffer_size) { - int total_free_space = 0; - int space_before_wrap = 0; - - if (logger->buffer_write_offset > logger->buffer_read_offset) { - total_free_space = logger->log_buffer_size - - logger->buffer_write_offset + - logger->buffer_read_offset; - space_before_wrap = logger->log_buffer_size - - logger->buffer_write_offset; - } else if (logger->buffer_write_offset < - logger->buffer_read_offset) { - total_free_space = logger->log_buffer_size - - logger->buffer_read_offset + - logger->buffer_write_offset; - space_before_wrap = total_free_space; - } else if (logger->write_wrap_count != - logger->read_wrap_count) { - /* Buffer is completely full already */ - total_free_space = 0; - space_before_wrap = 0; - } else { + int buffer_space = logger->log_buffer_size - + logger->buffer_write_offset; + + if (logger->buffer_write_offset == logger->buffer_read_offset) { /* Buffer is empty, start writing at beginning */ - total_free_space = logger->log_buffer_size; - space_before_wrap = logger->log_buffer_size; + buffer_space = logger->log_buffer_size; logger->buffer_write_offset = 0; logger->buffer_read_offset = 0; } - if (space_before_wrap > size) { + if (buffer_space > size) { /* No wrap around, copy 'size' bytes * from 'entry->buf' to 'log_buffer' */ @@ -232,28 +213,12 @@ static void log_to_internal_buffer(struct log_entry *entry) entry->buf, size); logger->buffer_write_offset += size; - } else if (total_free_space > size) { - /* We have enough room without flushing, - * but need to wrap around */ - - int space_after_wrap = total_free_space - - space_before_wrap; - - memmove(logger->log_buffer + - logger->buffer_write_offset, - entry->buf, space_before_wrap); - memmove(logger->log_buffer, entry->buf + - space_before_wrap, space_after_wrap); - - logger->buffer_write_offset = space_after_wrap; - logger->write_wrap_count++; - } else { /* Not enough room remaining, we should flush * existing logs */ /* Flush existing unread logs to console */ - flush_to_debug_console(logger); + dm_logger_flush_buffer(logger, true); /* Start writing to beginning of buffer */ memmove(logger->log_buffer, entry->buf, size); @@ -325,9 +290,10 @@ void dm_logger_write( log_heading(&entry); size = dm_log_to_buffer( - buffer, LOG_MAX_LINE_SIZE, msg, args); + buffer, LOG_MAX_LINE_SIZE - 1, msg, args); - entry.buf_offset += size; + buffer[entry.buf_offset + size] = '\0'; + entry.buf_offset += size + 1; /* --Flush log_entry buffer-- */ /* print to kernel console */ diff --git a/drivers/gpu/drm/amd/display/dc/basics/logger.h b/drivers/gpu/drm/amd/display/dc/basics/logger.h index 2f7a5df4c811..09722f0f8aa3 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/logger.h +++ b/drivers/gpu/drm/amd/display/dc/basics/logger.h @@ -26,42 +26,5 @@ #ifndef __DAL_LOGGER_H__ #define __DAL_LOGGER_H__ -/* Structure for keeping track of offsets, buffer, etc */ - -#define DAL_LOGGER_BUFFER_MAX_SIZE 2048 - -/*Connectivity log needs to output EDID, which needs at lease 256x3 bytes, - * change log line size to 896 to meet the request. - */ -#define LOG_MAX_LINE_SIZE 896 - -#include "include/logger_types.h" - -struct dal_logger { - - /* How far into the circular buffer has been read by dsat - * Read offset should never cross write offset. Write \0's to - * read data just to be sure? - */ - uint32_t buffer_read_offset; - - /* How far into the circular buffer we have written - * Write offset should never cross read offset - */ - uint32_t buffer_write_offset; - - uint32_t write_wrap_count; - uint32_t read_wrap_count; - - uint32_t open_count; - - char *log_buffer; /* Pointer to malloc'ed buffer */ - uint32_t log_buffer_size; /* Size of circular buffer */ - - uint32_t mask; /*array of masks for major elements*/ - - union logger_flags flags; - struct dc_context *ctx; -}; #endif /* __DAL_LOGGER_H__ */ 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 cb94e18cc455..43e9a9959288 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -1042,13 +1042,13 @@ static enum bp_result get_embedded_panel_info_v2_1( info->lcd_timing.misc_info.VERTICAL_CUT_OFF = 0; info->lcd_timing.misc_info.H_REPLICATION_BY2 = - lvds->lcd_timing.miscinfo & ATOM_H_REPLICATIONBY2; + !!(lvds->lcd_timing.miscinfo & ATOM_H_REPLICATIONBY2); info->lcd_timing.misc_info.V_REPLICATION_BY2 = - lvds->lcd_timing.miscinfo & ATOM_V_REPLICATIONBY2; + !!(lvds->lcd_timing.miscinfo & ATOM_V_REPLICATIONBY2); info->lcd_timing.misc_info.COMPOSITE_SYNC = - lvds->lcd_timing.miscinfo & ATOM_COMPOSITESYNC; + !!(lvds->lcd_timing.miscinfo & ATOM_COMPOSITESYNC); info->lcd_timing.misc_info.INTERLACE = - lvds->lcd_timing.miscinfo & ATOM_INTERLACE; + !!(lvds->lcd_timing.miscinfo & ATOM_INTERLACE); /* not provided by VBIOS*/ info->lcd_timing.misc_info.DOUBLE_CLOCK = 0; @@ -1056,7 +1056,7 @@ static enum bp_result get_embedded_panel_info_v2_1( info->ss_id = 0; info->realtek_eDPToLVDS = - (lvds->dplvdsrxid == eDP_TO_LVDS_REALTEK_ID ? 1:0); + !!(lvds->dplvdsrxid == eDP_TO_LVDS_REALTEK_ID); return BP_RESULT_OK; } diff --git a/drivers/gpu/drm/amd/display/dc/calcs/Makefile b/drivers/gpu/drm/amd/display/dc/calcs/Makefile index a095472bf4b5..41ef35995b02 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/Makefile +++ b/drivers/gpu/drm/amd/display/dc/calcs/Makefile @@ -5,7 +5,7 @@ CFLAGS_dcn_calcs.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_dcn_calc_auto.o := -mhard-float -msse -mpreferred-stack-boundary=4 -CFLAGS_dcn_calc_math.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_dcn_calc_math.o := -mhard-float -msse -mpreferred-stack-boundary=4 -Wno-tautological-compare BW_CALCS = dce_calcs.o bw_fixed.o custom_float.o diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c index 05cf5f77ec60..b6abe0f3bb15 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c @@ -25,6 +25,41 @@ #include "dcn_calc_math.h" +float dcn_bw_mod(const float arg1, const float arg2) +{ + if (arg1 != arg1) + return arg2; + if (arg2 != arg2) + return arg1; + return arg1 - arg1 * ((int) (arg1 / arg2)); +} + +float dcn_bw_min2(const float arg1, const float arg2) +{ + if (arg1 != arg1) + return arg2; + if (arg2 != arg2) + return arg1; + return arg1 < arg2 ? arg1 : arg2; +} + +unsigned int dcn_bw_max(const unsigned int arg1, const unsigned int arg2) +{ + if (arg1 != arg1) + return arg2; + if (arg2 != arg2) + return arg1; + return arg1 > arg2 ? arg1 : arg2; +} +float dcn_bw_max2(const float arg1, const float arg2) +{ + if (arg1 != arg1) + return arg2; + if (arg2 != arg2) + return arg1; + return arg1 > arg2 ? arg1 : arg2; +} + float dcn_bw_floor2(const float arg, const float significance) { if (significance == 0) @@ -40,6 +75,16 @@ float dcn_bw_ceil2(const float arg, const float significance) return flr + 0.00001 >= arg ? arg : flr + significance; } +float dcn_bw_max3(float v1, float v2, float v3) +{ + return v3 > dcn_bw_max2(v1, v2) ? v3 : dcn_bw_max2(v1, v2); +} + +float dcn_bw_max5(float v1, float v2, float v3, float v4, float v5) +{ + return dcn_bw_max3(v1, v2, v3) > dcn_bw_max2(v4, v5) ? dcn_bw_max3(v1, v2, v3) : dcn_bw_max2(v4, v5); +} + float dcn_bw_pow(float a, float exp) { float temp; diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.h b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.h index 6f66d9d164d1..f46ab0e24ca1 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.h +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.h @@ -26,38 +26,14 @@ #ifndef _DCN_CALC_MATH_H_ #define _DCN_CALC_MATH_H_ -static inline float dcn_bw_mod(const float arg1, const float arg2) -{ - return arg1 - arg1 * ((int) (arg1 / arg2)); -} - -static inline float dcn_bw_min2(const float arg1, const float arg2) -{ - return arg1 < arg2 ? arg1 : arg2; -} - -static inline unsigned int dcn_bw_max(const unsigned int arg1, const unsigned int arg2) -{ - return arg1 > arg2 ? arg1 : arg2; -} - -static inline float dcn_bw_max2(const float arg1, const float arg2) -{ - return arg1 > arg2 ? arg1 : arg2; -} - -static inline float dcn_bw_max3(float v1, float v2, float v3) -{ - return v3 > dcn_bw_max2(v1, v2) ? v3 : dcn_bw_max2(v1, v2); -} - -static inline float dcn_bw_max5(float v1, float v2, float v3, float v4, float v5) -{ - return dcn_bw_max3(v1, v2, v3) > dcn_bw_max2(v4, v5) ? dcn_bw_max3(v1, v2, v3) : dcn_bw_max2(v4, v5); -} - +float dcn_bw_mod(const float arg1, const float arg2); +float dcn_bw_min2(const float arg1, const float arg2); +unsigned int dcn_bw_max(const unsigned int arg1, const unsigned int arg2); +float dcn_bw_max2(const float arg1, const float arg2); float dcn_bw_floor2(const float arg, const float significance); float dcn_bw_ceil2(const float arg, const float significance); +float dcn_bw_max3(float v1, float v2, float v3); +float dcn_bw_max5(float v1, float v2, float v3, float v4, float v5); float dcn_bw_pow(float a, float exp); float dcn_bw_log(float a, float b); diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 8ca6c3e4e65a..e1515230c661 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -364,7 +364,8 @@ static void pipe_ctx_to_e2e_pipe_params ( } - input->dest.vactive = pipe->stream->timing.v_addressable; + input->dest.vactive = pipe->stream->timing.v_addressable + pipe->stream->timing.v_border_top + + pipe->stream->timing.v_border_bottom; input->dest.recout_width = pipe->plane_res.scl_data.recout.width; input->dest.recout_height = pipe->plane_res.scl_data.recout.height; @@ -385,10 +386,6 @@ static void pipe_ctx_to_e2e_pipe_params ( - pipe->stream->timing.v_addressable - pipe->stream->timing.v_border_bottom - pipe->stream->timing.v_border_top; - - input->dest.vsync_plus_back_porch = pipe->stream->timing.v_total - - pipe->stream->timing.v_addressable - - pipe->stream->timing.v_front_porch; input->dest.pixel_rate_mhz = pipe->stream->timing.pix_clk_khz/1000.0; input->dest.vstartup_start = pipe->pipe_dlg_param.vstartup_start; input->dest.vupdate_offset = pipe->pipe_dlg_param.vupdate_offset; @@ -458,9 +455,9 @@ static void dcn_bw_calc_rq_dlg_ttu( /*todo: soc->sr_enter_plus_exit_time??*/ dlg_sys_param.t_srx_delay_us = dc->dcn_ip->dcfclk_cstate_latency / v->dcf_clk_deep_sleep; - dml_rq_dlg_get_rq_params(dml, &rq_param, input.pipe.src); - extract_rq_regs(dml, rq_regs, rq_param); - dml_rq_dlg_get_dlg_params( + dml1_rq_dlg_get_rq_params(dml, &rq_param, input.pipe.src); + dml1_extract_rq_regs(dml, rq_regs, rq_param); + dml1_rq_dlg_get_dlg_params( dml, dlg_regs, ttu_regs, @@ -473,96 +470,6 @@ static void dcn_bw_calc_rq_dlg_ttu( pipe->plane_state->flip_immediate); } -static void dcn_dml_wm_override( - const struct dcn_bw_internal_vars *v, - struct display_mode_lib *dml, - struct dc_state *context, - const struct resource_pool *pool) -{ - int i, in_idx, active_count; - - struct _vcs_dpi_display_e2e_pipe_params_st *input = kzalloc(pool->pipe_count * sizeof(struct _vcs_dpi_display_e2e_pipe_params_st), - GFP_KERNEL); - struct wm { - double urgent; - struct _vcs_dpi_cstate_pstate_watermarks_st cpstate; - double pte_meta_urgent; - } a; - - - for (i = 0, in_idx = 0; i < pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - - if (!pipe->stream || !pipe->plane_state) - continue; - - input[in_idx].clks_cfg.dcfclk_mhz = v->dcfclk; - input[in_idx].clks_cfg.dispclk_mhz = v->dispclk; - input[in_idx].clks_cfg.dppclk_mhz = v->dppclk; - input[in_idx].clks_cfg.refclk_mhz = pool->ref_clock_inKhz / 1000; - input[in_idx].clks_cfg.socclk_mhz = v->socclk; - input[in_idx].clks_cfg.voltage = v->voltage_level; - input[in_idx].dout.output_format = (v->output_format[in_idx] == dcn_bw_420) ? dm_420 : dm_444; - input[in_idx].dout.output_type = (v->output[in_idx] == dcn_bw_hdmi) ? dm_hdmi : dm_dp; - //input[in_idx].dout.output_standard; - switch (v->output_deep_color[in_idx]) { - case dcn_bw_encoder_12bpc: - input[in_idx].dout.output_bpc = dm_out_12; - break; - case dcn_bw_encoder_10bpc: - input[in_idx].dout.output_bpc = dm_out_10; - break; - case dcn_bw_encoder_8bpc: - default: - input[in_idx].dout.output_bpc = dm_out_8; - break; - } - pipe_ctx_to_e2e_pipe_params(pipe, &input[in_idx].pipe); - dml_rq_dlg_get_rq_reg( - dml, - &pipe->rq_regs, - input[in_idx].pipe.src); - in_idx++; - } - active_count = in_idx; - - a.urgent = dml_wm_urgent_e2e(dml, input, active_count); - a.cpstate = dml_wm_cstate_pstate_e2e(dml, input, active_count); - a.pte_meta_urgent = dml_wm_pte_meta_urgent(dml, a.urgent); - - context->bw.dcn.watermarks.a.cstate_pstate.cstate_exit_ns = - a.cpstate.cstate_exit_us * 1000; - context->bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns = - a.cpstate.cstate_enter_plus_exit_us * 1000; - context->bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = - a.cpstate.pstate_change_us * 1000; - context->bw.dcn.watermarks.a.pte_meta_urgent_ns = a.pte_meta_urgent * 1000; - context->bw.dcn.watermarks.a.urgent_ns = a.urgent * 1000; - context->bw.dcn.watermarks.b = context->bw.dcn.watermarks.a; - context->bw.dcn.watermarks.c = context->bw.dcn.watermarks.a; - context->bw.dcn.watermarks.d = context->bw.dcn.watermarks.a; - - - for (i = 0, in_idx = 0; i < pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - - if (!pipe->stream || !pipe->plane_state) - continue; - - dml_rq_dlg_get_dlg_reg(dml, - &pipe->dlg_regs, - &pipe->ttu_regs, - input, active_count, - in_idx, - true, - true, - v->pte_enable == dcn_bw_yes, - pipe->plane_state->flip_immediate); - in_idx++; - } - kfree(input); -} - static void split_stream_across_pipes( struct resource_context *res_ctx, const struct resource_pool *pool, @@ -578,8 +485,10 @@ static void split_stream_across_pipes( secondary_pipe->pipe_idx = pipe_idx; secondary_pipe->plane_res.mi = pool->mis[secondary_pipe->pipe_idx]; + secondary_pipe->plane_res.hubp = pool->hubps[secondary_pipe->pipe_idx]; secondary_pipe->plane_res.ipp = pool->ipps[secondary_pipe->pipe_idx]; secondary_pipe->plane_res.xfm = pool->transforms[secondary_pipe->pipe_idx]; + secondary_pipe->plane_res.dpp = pool->dpps[secondary_pipe->pipe_idx]; if (primary_pipe->bottom_pipe) { ASSERT(primary_pipe->bottom_pipe != secondary_pipe); secondary_pipe->bottom_pipe = primary_pipe->bottom_pipe; @@ -719,6 +628,49 @@ static bool dcn_bw_apply_registry_override(struct dc *dc) return updated; } +void hack_disable_optional_pipe_split(struct dcn_bw_internal_vars *v) +{ + /* + * disable optional pipe split by lower dispclk bounding box + * at DPM0 + */ + v->max_dispclk[0] = v->max_dppclk_vmin0p65; +} + +void hack_force_pipe_split(struct dcn_bw_internal_vars *v, + unsigned int pixel_rate_khz) +{ + float pixel_rate_mhz = pixel_rate_khz / 1000; + + /* + * force enabling pipe split by lower dpp clock for DPM0 to just + * below the specify pixel_rate, so bw calc would split pipe. + */ + if (pixel_rate_mhz < v->max_dppclk[0]) + v->max_dppclk[0] = pixel_rate_mhz; +} + +void hack_bounding_box(struct dcn_bw_internal_vars *v, + struct dc_debug *dbg, + struct dc_state *context) +{ + if (dbg->pipe_split_policy == MPC_SPLIT_AVOID) { + hack_disable_optional_pipe_split(v); + } + + if (dbg->pipe_split_policy == MPC_SPLIT_AVOID_MULT_DISP && + context->stream_count >= 2) { + hack_disable_optional_pipe_split(v); + } + + if (context->stream_count == 1 && + dbg->force_single_disp_pipe_split) { + struct dc_stream_state *stream0 = context->streams[0]; + + hack_force_pipe_split(v, stream0->timing.pix_clk_khz); + } +} + bool dcn_validate_bandwidth( struct dc *dc, struct dc_state *context) @@ -730,6 +682,7 @@ bool dcn_validate_bandwidth( bool bw_limit_pass; float bw_limit; + PERFORMANCE_TRACE_START(); if (dcn_bw_apply_registry_override(dc)) dcn_bw_sync_calcs_and_dml(dc); @@ -850,9 +803,7 @@ bool dcn_validate_bandwidth( v->phyclk_per_state[1] = v->phyclkv_mid0p72; v->phyclk_per_state[0] = v->phyclkv_min0p65; - if (dc->debug.disable_pipe_split) { - v->max_dispclk[0] = v->max_dppclk_vmin0p65; - } + hack_bounding_box(v, &dc->debug, context); if (v->voltage_override == dcn_bw_v_max0p9) { v->voltage_override_level = number_of_states - 1; @@ -882,10 +833,11 @@ bool dcn_validate_bandwidth( v->htotal[input_idx] = pipe->stream->timing.h_total; v->vtotal[input_idx] = pipe->stream->timing.v_total; + v->vactive[input_idx] = pipe->stream->timing.v_addressable + + pipe->stream->timing.v_border_top + pipe->stream->timing.v_border_bottom; v->v_sync_plus_back_porch[input_idx] = pipe->stream->timing.v_total - - pipe->stream->timing.v_addressable + - v->vactive[input_idx] - pipe->stream->timing.v_front_porch; - v->vactive[input_idx] = pipe->stream->timing.v_addressable; v->pixel_clock[input_idx] = pipe->stream->timing.pix_clk_khz / 1000.0f; if (!pipe->plane_state) { @@ -1006,6 +958,10 @@ bool dcn_validate_bandwidth( else bw_consumed = v->fabric_and_dram_bandwidth_vmax0p9; + if (bw_consumed < v->fabric_and_dram_bandwidth) + if (dc->debug.voltage_align_fclk) + bw_consumed = v->fabric_and_dram_bandwidth; + display_pipe_configuration(v); calc_wm_sets_and_perf_params(context, v); context->bw.dcn.calc_clk.fclk_khz = (int)(bw_consumed * 1000000 / @@ -1018,9 +974,17 @@ bool dcn_validate_bandwidth( context->bw.dcn.calc_clk.min_active_dram_ccm_us = (int)(v->min_active_dram_clock_change_margin); context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz = (int)(v->dcf_clk_deep_sleep * 1000); context->bw.dcn.calc_clk.dcfclk_khz = (int)(v->dcfclk * 1000); + context->bw.dcn.calc_clk.dispclk_khz = (int)(v->dispclk * 1000); if (dc->debug.max_disp_clk == true) context->bw.dcn.calc_clk.dispclk_khz = (int)(dc->dcn_soc->max_dispclk_vmax0p9 * 1000); + + if (context->bw.dcn.calc_clk.dispclk_khz < + dc->debug.min_disp_clk_khz) { + context->bw.dcn.calc_clk.dispclk_khz = + dc->debug.min_disp_clk_khz; + } + context->bw.dcn.calc_clk.dppclk_div = (int)(v->dispclk_dppclk_ratio) == 2; for (i = 0, input_idx = 0; i < pool->pipe_count; i++) { @@ -1108,9 +1072,6 @@ bool dcn_validate_bandwidth( input_idx++; } - if (dc->debug.use_dml_wm) - dcn_dml_wm_override(v, (struct display_mode_lib *) - &dc->dml, context, pool); } if (v->voltage_level == 0) { @@ -1129,6 +1090,8 @@ bool dcn_validate_bandwidth( kernel_fpu_end(); + PERFORMANCE_TRACE_END(); + if (bw_limit_pass && v->voltage_level != 5) return true; else @@ -1263,7 +1226,7 @@ unsigned int dcn_find_dcfclk_suits_all( else dcf_clk = dc->dcn_soc->dcfclkv_min0p65*1000; - dm_logger_write(dc->ctx->logger, LOG_HW_MARKS, + dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS, "\tdcf_clk for voltage = %d\n", dcf_clk); return dcf_clk; } @@ -1386,6 +1349,53 @@ void dcn_bw_notify_pplib_of_wm_ranges(struct dc *dc) ranges.writer_wm_sets[3].min_drain_clk_khz = max_fclk_khz; ranges.writer_wm_sets[3].max_drain_clk_khz = max_fclk_khz; + if (dc->debug.pplib_wm_report_mode == WM_REPORT_OVERRIDE) { + ranges.reader_wm_sets[0].wm_inst = WM_A; + ranges.reader_wm_sets[0].min_drain_clk_khz = 300000; + ranges.reader_wm_sets[0].max_drain_clk_khz = 654000; + ranges.reader_wm_sets[0].min_fill_clk_khz = 800000; + ranges.reader_wm_sets[0].max_fill_clk_khz = 800000; + ranges.writer_wm_sets[0].wm_inst = WM_A; + ranges.writer_wm_sets[0].min_fill_clk_khz = 200000; + ranges.writer_wm_sets[0].max_fill_clk_khz = 757000; + ranges.writer_wm_sets[0].min_drain_clk_khz = 800000; + ranges.writer_wm_sets[0].max_drain_clk_khz = 800000; + + ranges.reader_wm_sets[1].wm_inst = WM_B; + ranges.reader_wm_sets[1].min_drain_clk_khz = 300000; + ranges.reader_wm_sets[1].max_drain_clk_khz = 654000; + ranges.reader_wm_sets[1].min_fill_clk_khz = 933000; + ranges.reader_wm_sets[1].max_fill_clk_khz = 933000; + ranges.writer_wm_sets[1].wm_inst = WM_B; + ranges.writer_wm_sets[1].min_fill_clk_khz = 200000; + ranges.writer_wm_sets[1].max_fill_clk_khz = 757000; + ranges.writer_wm_sets[1].min_drain_clk_khz = 933000; + ranges.writer_wm_sets[1].max_drain_clk_khz = 933000; + + + ranges.reader_wm_sets[2].wm_inst = WM_C; + ranges.reader_wm_sets[2].min_drain_clk_khz = 300000; + ranges.reader_wm_sets[2].max_drain_clk_khz = 654000; + ranges.reader_wm_sets[2].min_fill_clk_khz = 1067000; + ranges.reader_wm_sets[2].max_fill_clk_khz = 1067000; + ranges.writer_wm_sets[2].wm_inst = WM_C; + ranges.writer_wm_sets[2].min_fill_clk_khz = 200000; + ranges.writer_wm_sets[2].max_fill_clk_khz = 757000; + ranges.writer_wm_sets[2].min_drain_clk_khz = 1067000; + ranges.writer_wm_sets[2].max_drain_clk_khz = 1067000; + + ranges.reader_wm_sets[3].wm_inst = WM_D; + ranges.reader_wm_sets[3].min_drain_clk_khz = 300000; + ranges.reader_wm_sets[3].max_drain_clk_khz = 654000; + ranges.reader_wm_sets[3].min_fill_clk_khz = 1200000; + ranges.reader_wm_sets[3].max_fill_clk_khz = 1200000; + ranges.writer_wm_sets[3].wm_inst = WM_D; + ranges.writer_wm_sets[3].min_fill_clk_khz = 200000; + ranges.writer_wm_sets[3].max_fill_clk_khz = 757000; + ranges.writer_wm_sets[3].min_drain_clk_khz = 1200000; + ranges.writer_wm_sets[3].max_drain_clk_khz = 1200000; + } + /* Notify PP Lib/SMU which Watermarks to use for which clock ranges */ pp->set_wm_ranges(&pp->pp_smu, &ranges); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index f41f15faf019..a71392ffc46d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -38,6 +38,7 @@ #include "bios_parser_interface.h" #include "include/irq_service_interface.h" #include "transform.h" +#include "dpp.h" #include "timing_generator.h" #include "virtual/virtual_link_encoder.h" @@ -47,6 +48,7 @@ #include "dc_link_ddc.h" #include "dm_helpers.h" #include "mem_input.h" +#include "hubp.h" /******************************************************************************* @@ -332,10 +334,19 @@ static void set_dither_option(struct dc_stream_state *stream, { struct bit_depth_reduction_params params; struct dc_link *link = stream->status.link; - struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx; + struct pipe_ctx *pipes = NULL; + int i; + + for (i = 0; i < MAX_PIPES; i++) { + if (link->dc->current_state->res_ctx.pipe_ctx[i].stream == + stream) { + pipes = &link->dc->current_state->res_ctx.pipe_ctx[i]; + break; + } + } memset(¶ms, 0, sizeof(params)); - if (!stream) + if (!pipes) return; if (option > DITHER_OPTION_MAX) return; @@ -349,6 +360,36 @@ static void set_dither_option(struct dc_stream_state *stream, opp_program_bit_depth_reduction(pipes->stream_res.opp, ¶ms); } +void set_dpms( + struct dc *dc, + struct dc_stream_state *stream, + bool dpms_off) +{ + struct pipe_ctx *pipe_ctx = NULL; + int i; + + for (i = 0; i < MAX_PIPES; i++) { + if (dc->current_state->res_ctx.pipe_ctx[i].stream == stream) { + pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; + break; + } + } + + if (!pipe_ctx) { + ASSERT(0); + return; + } + + if (stream->dpms_off != dpms_off) { + stream->dpms_off = dpms_off; + if (dpms_off) + core_link_disable_stream(pipe_ctx, + KEEP_ACQUIRED_RESOURCE); + else + core_link_enable_stream(dc->current_state, pipe_ctx); + } +} + static void allocate_dc_stream_funcs(struct dc *dc) { if (dc->hwss.set_drr != NULL) { @@ -371,6 +412,9 @@ static void allocate_dc_stream_funcs(struct dc *dc) dc->stream_funcs.set_dither_option = set_dither_option; + dc->stream_funcs.set_dpms = + set_dpms; + dc->link_funcs.set_drive_settings = set_drive_settings; @@ -507,7 +551,7 @@ static bool construct(struct dc *dc, dc_version = resource_parse_asic_id(init_params->asic_id); dc->ctx->dce_version = dc_version; -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) dc->ctx->fbc_gpu_addr = init_params->fbc_gpu_addr; #endif /* Resource should construct all asic specific resources. @@ -749,7 +793,7 @@ bool dc_enable_stereo( * Applies given context to HW and copy it into current context. * It's up to the user to release the src context afterwards. */ -static bool dc_commit_state_no_check(struct dc *dc, struct dc_state *context) +static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *context) { struct dc_bios *dcb = dc->ctx->dc_bios; enum dc_status result = DC_ERROR_UNEXPECTED; @@ -763,41 +807,31 @@ static bool dc_commit_state_no_check(struct dc *dc, struct dc_state *context) if (!dcb->funcs->is_accelerated_mode(dcb)) dc->hwss.enable_accelerated_mode(dc); - dc->hwss.ready_shared_resources(dc); - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - pipe = &context->res_ctx.pipe_ctx[i]; - dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe); - } - result = dc->hwss.apply_ctx_to_hw(dc, context); - - program_timing_sync(dc, context); - for (i = 0; i < context->stream_count; i++) { const struct dc_sink *sink = context->streams[i]->sink; - for (j = 0; j < context->stream_status[i].plane_count; j++) { - dc->hwss.apply_ctx_for_surface( - dc, context->streams[i], - context->stream_status[i].plane_count, - context); + dc->hwss.apply_ctx_for_surface( + dc, context->streams[i], + context->stream_status[i].plane_count, + context); - /* - * enable stereo - * TODO rework dc_enable_stereo call to work with validation sets? - */ - for (k = 0; k < MAX_PIPES; k++) { - pipe = &context->res_ctx.pipe_ctx[k]; - - for (l = 0 ; pipe && l < context->stream_count; l++) { - if (context->streams[l] && - context->streams[l] == pipe->stream && - dc->hwss.setup_stereo) - dc->hwss.setup_stereo(pipe, dc); - } + /* + * enable stereo + * TODO rework dc_enable_stereo call to work with validation sets? + */ + for (k = 0; k < MAX_PIPES; k++) { + pipe = &context->res_ctx.pipe_ctx[k]; + + for (l = 0 ; pipe && l < context->stream_count; l++) { + if (context->streams[l] && + context->streams[l] == pipe->stream && + dc->hwss.setup_stereo) + dc->hwss.setup_stereo(pipe, dc); } } + + CONN_MSG_MODE(sink->link, "{%dx%d, %dx%d@%dKhz}", context->streams[i]->timing.h_addressable, context->streams[i]->timing.v_addressable, @@ -806,8 +840,27 @@ static bool dc_commit_state_no_check(struct dc *dc, struct dc_state *context) context->streams[i]->timing.pix_clk_khz); } + dc->hwss.ready_shared_resources(dc, context); + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + pipe = &context->res_ctx.pipe_ctx[i]; + dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe); + } + result = dc->hwss.apply_ctx_to_hw(dc, context); + + program_timing_sync(dc, context); + dc_enable_stereo(dc, context, dc_streams, context->stream_count); + for (i = 0; i < context->stream_count; i++) { + for (j = 0; j < MAX_PIPES; j++) { + pipe = &context->res_ctx.pipe_ctx[j]; + + if (!pipe->top_pipe && pipe->stream == context->streams[i]) + dc->hwss.pipe_control_lock(dc, pipe, false); + } + } + dc_release_state(dc->current_state); dc->current_state = context; @@ -816,7 +869,7 @@ static bool dc_commit_state_no_check(struct dc *dc, struct dc_state *context) dc->hwss.optimize_shared_resources(dc); - return (result == DC_OK); + return result; } bool dc_commit_state(struct dc *dc, struct dc_state *context) @@ -865,16 +918,24 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) return true; } +/* + * TODO this whole function needs to go + * + * dc_surface_update is needlessly complex. See if we can just replace this + * with a dc_plane_state and follow the atomic model a bit more closely here. + */ bool dc_commit_planes_to_stream( struct dc *dc, struct dc_plane_state **plane_states, uint8_t new_plane_count, - struct dc_stream_state *dc_stream) + struct dc_stream_state *dc_stream, + struct dc_state *state) { + /* no need to dynamically allocate this. it's pretty small */ struct dc_surface_update updates[MAX_SURFACES]; - struct dc_flip_addrs flip_addr[MAX_SURFACES]; - struct dc_plane_info plane_info[MAX_SURFACES]; - struct dc_scaling_info scaling_info[MAX_SURFACES]; + struct dc_flip_addrs *flip_addr; + struct dc_plane_info *plane_info; + struct dc_scaling_info *scaling_info; int i; struct dc_stream_update *stream_update = kzalloc(sizeof(struct dc_stream_update), GFP_KERNEL); @@ -884,10 +945,14 @@ bool dc_commit_planes_to_stream( return false; } + flip_addr = kcalloc(MAX_SURFACES, sizeof(struct dc_flip_addrs), + GFP_KERNEL); + plane_info = kcalloc(MAX_SURFACES, sizeof(struct dc_plane_info), + GFP_KERNEL); + scaling_info = kcalloc(MAX_SURFACES, sizeof(struct dc_scaling_info), + GFP_KERNEL); + memset(updates, 0, sizeof(updates)); - memset(flip_addr, 0, sizeof(flip_addr)); - memset(plane_info, 0, sizeof(plane_info)); - memset(scaling_info, 0, sizeof(scaling_info)); stream_update->src = dc_stream->src; stream_update->dst = dc_stream->dst; @@ -920,14 +985,15 @@ bool dc_commit_planes_to_stream( updates[i].scaling_info = &scaling_info[i]; } - dc_update_planes_and_stream( + dc_commit_updates_for_stream( dc, updates, new_plane_count, - dc_stream, stream_update); - - dc_post_update_surfaces_to_stream(dc); + dc_stream, stream_update, plane_states, state); + kfree(flip_addr); + kfree(plane_info); + kfree(scaling_info); kfree(stream_update); return true; } @@ -1030,7 +1096,6 @@ static enum surface_update_type get_plane_info_update_type( temp_plane_info.plane_size = u->surface->plane_size; temp_plane_info.rotation = u->surface->rotation; temp_plane_info.stereo_format = u->surface->stereo_format; - temp_plane_info.tiling_info = u->surface->tiling_info; if (surface_index == 0) temp_plane_info.visible = u->plane_info->visible; @@ -1043,10 +1108,26 @@ static enum surface_update_type get_plane_info_update_type( if (pixel_format_to_bpp(u->plane_info->format) != pixel_format_to_bpp(u->surface->format)) { + /* different bytes per element will require full bandwidth + * and DML calculation + */ return UPDATE_TYPE_FULL; - } else { - return UPDATE_TYPE_MED; } + + if (memcmp(&u->plane_info->tiling_info, &u->surface->tiling_info, + sizeof(union dc_tiling_info)) != 0) { + /* todo: below are HW dependent, we should add a hook to + * DCE/N resource and validated there. + */ + if (u->plane_info->tiling_info.gfx9.swizzle != DC_SW_LINEAR) { + /* swizzled mode requires RQ to be setup properly, + * thus need to run DML to calculate RQ settings + */ + return UPDATE_TYPE_FULL; + } + } + + return UPDATE_TYPE_MED; } static enum surface_update_type get_scaling_info_update_type( @@ -1150,192 +1231,20 @@ static struct dc_stream_status *stream_get_status( static const enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL; -void dc_update_planes_and_stream(struct dc *dc, - struct dc_surface_update *srf_updates, int surface_count, + +static void commit_planes_for_stream(struct dc *dc, + struct dc_surface_update *srf_updates, + int surface_count, struct dc_stream_state *stream, - struct dc_stream_update *stream_update) + struct dc_stream_update *stream_update, + enum surface_update_type update_type, + struct dc_state *context) { - struct dc_state *context; int i, j; - enum surface_update_type update_type; - const struct dc_stream_status *stream_status; - struct dc_context *dc_ctx = dc->ctx; - - stream_status = dc_stream_get_status(stream); - - ASSERT(stream_status); - if (!stream_status) - return; /* Cannot commit surface to stream that is not committed */ - -#ifdef ENABLE_FBC - if (srf_updates->flip_addr) { - if (srf_updates->flip_addr->address.grph.addr.low_part == 0) - ASSERT(0); - } -#endif - context = dc->current_state; - - /* update current stream with the new updates */ - if (stream_update) { - if ((stream_update->src.height != 0) && - (stream_update->src.width != 0)) - stream->src = stream_update->src; - - if ((stream_update->dst.height != 0) && - (stream_update->dst.width != 0)) - stream->dst = stream_update->dst; - - if (stream_update->out_transfer_func && - stream_update->out_transfer_func != - stream->out_transfer_func) { - if (stream->out_transfer_func != NULL) - dc_transfer_func_release(stream->out_transfer_func); - dc_transfer_func_retain(stream_update->out_transfer_func); - stream->out_transfer_func = - stream_update->out_transfer_func; - } - } - - /* do not perform surface update if surface has invalid dimensions - * (all zero) and no scaling_info is provided - */ - if (surface_count > 0 && - srf_updates->surface->src_rect.width == 0 && - srf_updates->surface->src_rect.height == 0 && - srf_updates->surface->dst_rect.width == 0 && - srf_updates->surface->dst_rect.height == 0 && - !srf_updates->scaling_info) { - ASSERT(false); - return; - } - - update_type = dc_check_update_surfaces_for_stream( - dc, srf_updates, surface_count, stream_update, stream_status); - - if (update_type >= update_surface_trace_level) - update_surface_trace(dc, srf_updates, surface_count); - - if (update_type >= UPDATE_TYPE_FULL) { - struct dc_plane_state *new_planes[MAX_SURFACES] = {0}; - - for (i = 0; i < surface_count; i++) - new_planes[i] = srf_updates[i].surface; - - /* initialize scratch memory for building context */ - context = dc_create_state(); - if (context == NULL) { - DC_ERROR("Failed to allocate new validate context!\n"); - return; - } - - dc_resource_state_copy_construct( - dc->current_state, context); - - /*remove old surfaces from context */ - if (!dc_rem_all_planes_for_stream(dc, stream, context)) { - - BREAK_TO_DEBUGGER(); - goto fail; - } - - /* add surface to context */ - if (!dc_add_all_planes_for_stream(dc, stream, new_planes, surface_count, context)) { - - BREAK_TO_DEBUGGER(); - goto fail; - } - } - - /* save update parameters into surface */ - for (i = 0; i < surface_count; i++) { - struct dc_plane_state *surface = srf_updates[i].surface; - - if (srf_updates[i].flip_addr) { - surface->address = srf_updates[i].flip_addr->address; - surface->flip_immediate = - srf_updates[i].flip_addr->flip_immediate; - } - - if (srf_updates[i].scaling_info) { - surface->scaling_quality = - srf_updates[i].scaling_info->scaling_quality; - surface->dst_rect = - srf_updates[i].scaling_info->dst_rect; - surface->src_rect = - srf_updates[i].scaling_info->src_rect; - surface->clip_rect = - srf_updates[i].scaling_info->clip_rect; - } - - if (srf_updates[i].plane_info) { - surface->color_space = - srf_updates[i].plane_info->color_space; - surface->format = - srf_updates[i].plane_info->format; - surface->plane_size = - srf_updates[i].plane_info->plane_size; - surface->rotation = - srf_updates[i].plane_info->rotation; - surface->horizontal_mirror = - srf_updates[i].plane_info->horizontal_mirror; - surface->stereo_format = - srf_updates[i].plane_info->stereo_format; - surface->tiling_info = - srf_updates[i].plane_info->tiling_info; - surface->visible = - srf_updates[i].plane_info->visible; - surface->per_pixel_alpha = - srf_updates[i].plane_info->per_pixel_alpha; - surface->dcc = - srf_updates[i].plane_info->dcc; - } - - if (update_type >= UPDATE_TYPE_MED) { - for (j = 0; j < dc->res_pool->pipe_count; j++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - - if (pipe_ctx->plane_state != surface) - continue; - - resource_build_scaling_params(pipe_ctx); - } - } - - if (srf_updates[i].gamma && - srf_updates[i].gamma != surface->gamma_correction) { - if (surface->gamma_correction != NULL) - dc_gamma_release(&surface->gamma_correction); - - dc_gamma_retain(srf_updates[i].gamma); - surface->gamma_correction = srf_updates[i].gamma; - } - - if (srf_updates[i].in_transfer_func && - srf_updates[i].in_transfer_func != surface->in_transfer_func) { - if (surface->in_transfer_func != NULL) - dc_transfer_func_release( - surface-> - in_transfer_func); - - dc_transfer_func_retain( - srf_updates[i].in_transfer_func); - surface->in_transfer_func = - srf_updates[i].in_transfer_func; - } - - if (srf_updates[i].hdr_static_metadata) - surface->hdr_static_ctx = - *(srf_updates[i].hdr_static_metadata); - } if (update_type == UPDATE_TYPE_FULL) { - if (!dc->res_pool->funcs->validate_bandwidth(dc, context)) { - BREAK_TO_DEBUGGER(); - goto fail; - } else { - dc->hwss.set_bandwidth(dc, context, false); - context_clock_trace(dc, context); - } + dc->hwss.set_bandwidth(dc, context, false); + context_clock_trace(dc, context); } if (update_type > UPDATE_TYPE_FAST) { @@ -1346,8 +1255,14 @@ void dc_update_planes_and_stream(struct dc *dc, } } - if (surface_count == 0) + if (surface_count == 0) { + /* + * In case of turning off screen, no need to program front end a second time. + * just return after program front end. + */ dc->hwss.apply_ctx_for_surface(dc, stream, surface_count, context); + return; + } /* Lock pipes for provided surfaces, or all active if full update*/ for (i = 0; i < surface_count; i++) { @@ -1373,10 +1288,6 @@ void dc_update_planes_and_stream(struct dc *dc, /* Full fe update*/ for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - struct pipe_ctx *cur_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[j]; - bool is_new_pipe_surface = cur_pipe_ctx->plane_state != pipe_ctx->plane_state; - struct dc_cursor_position position = { 0 }; - if (update_type != UPDATE_TYPE_FULL || !pipe_ctx->plane_state) continue; @@ -1387,17 +1298,6 @@ void dc_update_planes_and_stream(struct dc *dc, dc->hwss.apply_ctx_for_surface( dc, pipe_ctx->stream, stream_status->plane_count, context); } - - /* TODO: this is a hack w/a for switching from mpo to pipe split */ - dc_stream_set_cursor_position(pipe_ctx->stream, &position); - - if (is_new_pipe_surface) { - dc->hwss.update_plane_addr(dc, pipe_ctx); - dc->hwss.set_input_transfer_func( - pipe_ctx, pipe_ctx->plane_state); - dc->hwss.set_output_transfer_func( - pipe_ctx, pipe_ctx->stream); - } } if (update_type > UPDATE_TYPE_FAST) @@ -1423,7 +1323,9 @@ void dc_update_planes_and_stream(struct dc *dc, if (update_type == UPDATE_TYPE_FAST) continue; - if (srf_updates[i].in_transfer_func) + /* work around to program degamma regs for split pipe after set mode. */ + if (srf_updates[i].in_transfer_func || (pipe_ctx->top_pipe && + pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state)) dc->hwss.set_input_transfer_func( pipe_ctx, pipe_ctx->plane_state); @@ -1459,16 +1361,79 @@ void dc_update_planes_and_stream(struct dc *dc, break; } } +} - if (dc->current_state != context) { +void dc_commit_updates_for_stream(struct dc *dc, + struct dc_surface_update *srf_updates, + int surface_count, + struct dc_stream_state *stream, + struct dc_stream_update *stream_update, + struct dc_plane_state **plane_states, + struct dc_state *state) +{ + const struct dc_stream_status *stream_status; + enum surface_update_type update_type; + struct dc_state *context; + struct dc_context *dc_ctx = dc->ctx; + int i, j; + + stream_status = dc_stream_get_status(stream); + context = dc->current_state; + + update_type = dc_check_update_surfaces_for_stream( + dc, srf_updates, surface_count, stream_update, stream_status); + + if (update_type >= update_surface_trace_level) + update_surface_trace(dc, srf_updates, surface_count); + + + if (update_type >= UPDATE_TYPE_FULL) { + + /* initialize scratch memory for building context */ + context = dc_create_state(); + if (context == NULL) { + DC_ERROR("Failed to allocate new validate context!\n"); + return; + } + + dc_resource_state_copy_construct(state, context); + } + + + for (i = 0; i < surface_count; i++) { + struct dc_plane_state *surface = srf_updates[i].surface; - /* Since memory free requires elevated IRQL, an interrupt - * request is generated by mem free. If this happens - * between freeing and reassigning the context, our vsync - * interrupt will call into dc and cause a memory - * corruption BSOD. Hence, we first reassign the context, - * then free the old context. + /* TODO: On flip we don't build the state, so it still has the + * old address. Which is why we are updating the address here */ + if (srf_updates[i].flip_addr) + surface->address = srf_updates[i].flip_addr->address; + + if (update_type >= UPDATE_TYPE_MED) { + for (j = 0; j < dc->res_pool->pipe_count; j++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + + if (pipe_ctx->plane_state != surface) + continue; + + resource_build_scaling_params(pipe_ctx); + } + } + } + + commit_planes_for_stream( + dc, + srf_updates, + surface_count, + stream, + stream_update, + update_type, + context); + + if (update_type >= UPDATE_TYPE_FULL) + dc_post_update_surfaces_to_stream(dc); + + if (dc->current_state != context) { struct dc_state *old = dc->current_state; @@ -1476,10 +1441,9 @@ void dc_update_planes_and_stream(struct dc *dc, dc_release_state(old); } + return; -fail: - dc_release_state(context); } uint8_t dc_get_current_stream_count(struct dc *dc) 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 4a70948c91b1..c47da645d3b8 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -45,6 +45,7 @@ #include "dce/dce_11_0_enum.h" #include "dce/dce_11_0_sh_mask.h" +#define EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK 0x007C /* Copied from atombios.h */ #define LINK_INFO(...) \ dm_logger_write(dc_ctx->logger, LOG_HW_HOTPLUG, \ __VA_ARGS__) @@ -78,14 +79,15 @@ static void destruct(struct dc_link *link) dc_sink_release(link->remote_sinks[i]); } -static struct gpio *get_hpd_gpio(const struct dc_link *link) +struct gpio *get_hpd_gpio(struct dc_bios *dcb, + struct graphics_object_id link_id, + struct gpio_service *gpio_service) { enum bp_result bp_result; - struct dc_bios *dcb = link->ctx->dc_bios; struct graphics_object_hpd_info hpd_info; struct gpio_pin_info pin_info; - if (dcb->funcs->get_hpd_info(dcb, link->link_id, &hpd_info) != BP_RESULT_OK) + if (dcb->funcs->get_hpd_info(dcb, link_id, &hpd_info) != BP_RESULT_OK) return NULL; bp_result = dcb->funcs->get_gpio_pin_info(dcb, @@ -97,7 +99,7 @@ static struct gpio *get_hpd_gpio(const struct dc_link *link) } return dal_gpio_service_create_irq( - link->ctx->gpio_service, + gpio_service, pin_info.offset, pin_info.mask); } @@ -153,7 +155,7 @@ static bool program_hpd_filter( } /* Obtain HPD handle */ - hpd = get_hpd_gpio(link); + hpd = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service); if (!hpd) return result; @@ -186,7 +188,7 @@ static bool detect_sink(struct dc_link *link, enum dc_connection_type *type) struct gpio *hpd_pin; /* todo: may need to lock gpio access */ - hpd_pin = get_hpd_gpio(link); + hpd_pin = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service); if (hpd_pin == NULL) goto hpd_gpio_failure; @@ -496,6 +498,7 @@ static void detect_dp( } if (is_mst_supported(link)) { sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT_MST; + link->type = dc_connection_mst_branch; /* * This call will initiate MST topology discovery. Which @@ -524,12 +527,11 @@ static void detect_dp( if (reason == DETECT_REASON_BOOT) boot = true; - if (dm_helpers_dp_mst_start_top_mgr( + if (!dm_helpers_dp_mst_start_top_mgr( link->ctx, link, boot)) { - link->type = dc_connection_mst_branch; - } else { /* MST not supported */ + link->type = dc_connection_single; sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT; } } @@ -638,8 +640,8 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) if (link->dpcd_caps.sink_count.bits.SINK_COUNT) link->dpcd_sink_count = link->dpcd_caps.sink_count. bits.SINK_COUNT; - else - link->dpcd_sink_count = 1; + else + link->dpcd_sink_count = 1; dal_ddc_service_set_transaction_type( link->ddc, @@ -746,6 +748,7 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) if (link->type == dc_connection_mst_branch) { LINK_INFO("link=%d, mst branch is now Disconnected\n", link->link_index); + dm_helpers_dp_mst_stop_top_mgr(link->ctx, link); link->mst_stream_alloc_table.stream_count = 0; @@ -770,7 +773,7 @@ static enum hpd_source_id get_hpd_line( struct gpio *hpd; enum hpd_source_id hpd_id = HPD_SOURCEID_UNKNOWN; - hpd = get_hpd_gpio(link); + hpd = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service); if (hpd) { switch (dal_irq_get_source(hpd)) { @@ -940,7 +943,7 @@ static bool construct( goto create_fail; } - hpd_gpio = get_hpd_gpio(link); + hpd_gpio = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service); if (hpd_gpio != NULL) link->irq_source_hpd = dal_irq_get_source(hpd_gpio); @@ -1343,7 +1346,18 @@ static bool get_ext_hdmi_settings(struct pipe_ctx *pipe_ctx, sizeof(integrated_info->dp2_ext_hdmi_6g_reg_settings)); result = true; break; - + case ENGINE_ID_DIGD: + settings->slv_addr = integrated_info->dp3_ext_hdmi_slv_addr; + settings->reg_num = integrated_info->dp3_ext_hdmi_6g_reg_num; + settings->reg_num_6g = integrated_info->dp3_ext_hdmi_6g_reg_num; + memmove(settings->reg_settings, + integrated_info->dp3_ext_hdmi_reg_settings, + sizeof(integrated_info->dp3_ext_hdmi_reg_settings)); + memmove(settings->reg_settings_6g, + integrated_info->dp3_ext_hdmi_6g_reg_settings, + sizeof(integrated_info->dp3_ext_hdmi_6g_reg_settings)); + result = true; + break; default: break; } @@ -1680,7 +1694,9 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) is_over_340mhz = true; if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) { - if ((pipe_ctx->stream->sink->link->chip_caps >> 2) == 0x2) { + unsigned short masked_chip_caps = pipe_ctx->stream->sink->link->chip_caps & + EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK; + if (masked_chip_caps == (0x2 << 2)) { /* DP159, Retimer settings */ eng_id = pipe_ctx->stream_res.stream_enc->id; @@ -1691,7 +1707,7 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) write_i2c_default_retimer_setting(pipe_ctx, is_vga_mode, is_over_340mhz); } - } else if ((pipe_ctx->stream->sink->link->chip_caps >> 2) == 0x1) { + } else if (masked_chip_caps == (0x1 << 2)) { /* PI3EQX1204, Redriver settings */ write_i2c_redriver_setting(pipe_ctx, is_over_340mhz); } @@ -1782,7 +1798,7 @@ static void disable_link(struct dc_link *link, enum signal_type signal) else dp_disable_link_phy_mst(link, signal); } else - link->link_enc->funcs->disable_output(link->link_enc, signal); + link->link_enc->funcs->disable_output(link->link_enc, signal, link); } enum dc_status dc_link_validate_mode_timing( @@ -2319,16 +2335,20 @@ void core_link_enable_stream( if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) allocate_mst_payload(pipe_ctx); + + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + core_dc->hwss.unblank_stream(pipe_ctx, + &pipe_ctx->stream->sink->link->cur_link_settings); } -void core_link_disable_stream(struct pipe_ctx *pipe_ctx) +void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option) { struct dc *core_dc = pipe_ctx->stream->ctx->dc; if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) deallocate_mst_payload(pipe_ctx); - core_dc->hwss.disable_stream(pipe_ctx); + core_dc->hwss.disable_stream(pipe_ctx, option); disable_link(pipe_ctx->stream->sink->link, pipe_ctx->stream->signal); } 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 b735782b8fe0..ced42484dcfc 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 @@ -1700,6 +1700,12 @@ static void dp_test_send_link_training(struct dc_link *link) dp_retrain_link_dp_test(link, &link_settings, false); } +/* TODO hbr2 compliance eye output is unstable + * (toggling on and off) with debugger break + * This caueses intermittent PHY automation failure + * Need to look into the root cause */ +static uint8_t force_tps4_for_cp2520 = 1; + static void dp_test_send_phy_test_pattern(struct dc_link *link) { union phy_test_pattern dpcd_test_pattern; @@ -1758,10 +1764,16 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) test_pattern = DP_TEST_PATTERN_80BIT_CUSTOM; break; case PHY_TEST_PATTERN_CP2520_1: - test_pattern = DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE; + /* CP2520 pattern is unstable, temporarily use TPS4 instead */ + test_pattern = (force_tps4_for_cp2520 == 1) ? + DP_TEST_PATTERN_TRAINING_PATTERN4 : + DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE; break; case PHY_TEST_PATTERN_CP2520_2: - test_pattern = DP_TEST_PATTERN_CP2520_2; + /* CP2520 pattern is unstable, temporarily use TPS4 instead */ + test_pattern = (force_tps4_for_cp2520 == 1) ? + DP_TEST_PATTERN_TRAINING_PATTERN4 : + DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE; break; case PHY_TEST_PATTERN_CP2520_3: test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 5f815cab94b5..9a33b471270a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -89,12 +89,12 @@ void dp_enable_link_phy( if (dc_is_dp_sst_signal(signal)) { if (signal == SIGNAL_TYPE_EDP) { - link_enc->funcs->power_control(link_enc, true); + link->dc->hwss.edp_power_control(link->link_enc, true); link_enc->funcs->enable_dp_output( link_enc, link_settings, clock_source); - link_enc->funcs->backlight_control(link_enc, true); + link->dc->hwss.edp_backlight_control(link, true); } else link_enc->funcs->enable_dp_output( link_enc, @@ -138,12 +138,12 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) dp_receiver_power_ctrl(link, false); if (signal == SIGNAL_TYPE_EDP) { - link->link_enc->funcs->backlight_control(link->link_enc, false); + link->dc->hwss.edp_backlight_control(link, false); edp_receiver_ready_T9(link); - link->link_enc->funcs->disable_output(link->link_enc, signal); - link->link_enc->funcs->power_control(link->link_enc, false); + link->link_enc->funcs->disable_output(link->link_enc, signal, link); + link->dc->hwss.edp_power_control(link->link_enc, false); } else - link->link_enc->funcs->disable_output(link->link_enc, signal); + link->link_enc->funcs->disable_output(link->link_enc, signal, link); /* Clear current link setting.*/ memset(&link->cur_link_settings, 0, @@ -282,11 +282,12 @@ void dp_retrain_link_dp_test(struct dc_link *link, dp_receiver_power_ctrl(link, false); - link->dc->hwss.disable_stream(&pipes[i]); + link->dc->hwss.disable_stream(&pipes[i], KEEP_ACQUIRED_RESOURCE); link->link_enc->funcs->disable_output( link->link_enc, - SIGNAL_TYPE_DISPLAY_PORT); + SIGNAL_TYPE_DISPLAY_PORT, + link); /* Clear current link setting. */ memset(&link->cur_link_settings, 0, 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 77b3474a7c9e..d1cdf9f8853d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -31,6 +31,7 @@ #include "opp.h" #include "timing_generator.h" #include "transform.h" +#include "dpp.h" #include "core_types.h" #include "set_mode_types.h" #include "virtual/virtual_stream_encoder.h" @@ -242,7 +243,10 @@ bool resource_construct( pool->stream_enc_count++; } } - + dc->caps.dynamic_audio = false; + if (pool->audio_count < pool->stream_enc_count) { + dc->caps.dynamic_audio = true; + } for (i = 0; i < num_virtual_links; i++) { pool->stream_enc[pool->stream_enc_count] = virtual_stream_encoder_create( @@ -846,12 +850,20 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) */ pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; - pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable; - pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable; + pipe_ctx->plane_res.scl_data.recout.x += timing->h_border_left; + pipe_ctx->plane_res.scl_data.recout.y += timing->v_border_top; + + pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable + timing->h_border_left + timing->h_border_right; + pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable + timing->v_border_top + timing->v_border_bottom; /* Taps calculations */ - res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( - pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); + if (pipe_ctx->plane_res.xfm != NULL) + res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( + pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); + + if (pipe_ctx->plane_res.dpp != NULL) + res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps( + pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); if (!res) { /* Try 24 bpp linebuffer */ @@ -859,6 +871,9 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); + + res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps( + pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); } if (res) @@ -1021,9 +1036,9 @@ static int acquire_first_split_pipe( memset(pipe_ctx, 0, sizeof(*pipe_ctx)); pipe_ctx->stream_res.tg = pool->timing_generators[i]; - pipe_ctx->plane_res.mi = pool->mis[i]; + pipe_ctx->plane_res.hubp = pool->hubps[i]; pipe_ctx->plane_res.ipp = pool->ipps[i]; - pipe_ctx->plane_res.xfm = pool->transforms[i]; + pipe_ctx->plane_res.dpp = pool->dpps[i]; pipe_ctx->stream_res.opp = pool->opps[i]; pipe_ctx->pipe_idx = i; @@ -1070,9 +1085,6 @@ bool dc_add_plane_to_context( return false; } - /* retain new surfaces */ - dc_plane_state_retain(plane_state); - free_pipe = acquire_free_pipe_for_stream(context, pool, stream); #if defined(CONFIG_DRM_AMD_DC_DCN1_0) @@ -1082,11 +1094,11 @@ bool dc_add_plane_to_context( free_pipe = &context->res_ctx.pipe_ctx[pipe_idx]; } #endif - if (!free_pipe) { - stream_status->plane_states[i] = NULL; + if (!free_pipe) return false; - } + /* retain new surfaces */ + dc_plane_state_retain(plane_state); free_pipe->plane_state = plane_state; if (head_pipe != free_pipe) { @@ -1178,8 +1190,8 @@ bool dc_remove_plane_from_context( stream_status->plane_count--; - /* Trim back arrays */ - for (i = 0; i < stream_status->plane_count; i++) + /* Start at the plane we've just released, and move all the planes one index forward to "trim" the array */ + for (; i < stream_status->plane_count; i++) stream_status->plane_states[i] = stream_status->plane_states[i + 1]; stream_status->plane_states[stream_status->plane_count] = NULL; @@ -1312,6 +1324,28 @@ bool dc_is_stream_unchanged( return true; } +bool dc_is_stream_scaling_unchanged( + struct dc_stream_state *old_stream, struct dc_stream_state *stream) +{ + if (old_stream == stream) + return true; + + if (old_stream == NULL || stream == NULL) + return false; + + if (memcmp(&old_stream->src, + &stream->src, + sizeof(struct rect)) != 0) + return false; + + if (memcmp(&old_stream->dst, + &stream->dst, + sizeof(struct rect)) != 0) + return false; + + return true; +} + /* Maximum TMDS single link pixel clock 165MHz */ #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000 @@ -1330,7 +1364,7 @@ static void update_stream_engine_usage( } /* TODO: release audio object */ -static void update_audio_usage( +void update_audio_usage( struct resource_context *res_ctx, const struct resource_pool *pool, struct audio *audio, @@ -1356,8 +1390,10 @@ static int acquire_first_free_pipe( pipe_ctx->stream_res.tg = pool->timing_generators[i]; pipe_ctx->plane_res.mi = pool->mis[i]; + pipe_ctx->plane_res.hubp = pool->hubps[i]; pipe_ctx->plane_res.ipp = pool->ipps[i]; pipe_ctx->plane_res.xfm = pool->transforms[i]; + pipe_ctx->plane_res.dpp = pool->dpps[i]; pipe_ctx->stream_res.opp = pool->opps[i]; pipe_ctx->pipe_idx = i; @@ -1415,11 +1451,16 @@ static struct audio *find_first_free_audio( { int i; for (i = 0; i < pool->audio_count; i++) { + if ((res_ctx->is_audio_acquired[i] == false) && (res_ctx->is_stream_enc_acquired[i] == true)) { + return pool->audios[i]; + } + } + /*not found the matching one, first come first serve*/ + for (i = 0; i < pool->audio_count; i++) { if (res_ctx->is_audio_acquired[i] == false) { return pool->audios[i]; } } - return 0; } @@ -1438,7 +1479,7 @@ bool resource_is_stream_unchanged( return false; } -bool dc_add_stream_to_ctx( +enum dc_status dc_add_stream_to_ctx( struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *stream) @@ -1459,10 +1500,10 @@ bool dc_add_stream_to_ctx( if (res != DC_OK) DC_ERROR("Adding stream %p to context failed with err %d!\n", stream, res); - return res == DC_OK; + return res; } -bool dc_remove_stream_from_ctx( +enum dc_status dc_remove_stream_from_ctx( struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *stream) @@ -1632,10 +1673,11 @@ enum dc_status resource_map_pool_resources( /* acquire new resources */ pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream); -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#ifdef CONFIG_DRM_AMD_DC_DCN1_0 if (pipe_idx < 0) - acquire_first_split_pipe(&context->res_ctx, pool, stream); + pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream); #endif + if (pipe_idx < 0) return DC_NO_CONTROLLER_RESOURCE; @@ -1716,17 +1758,18 @@ void dc_resource_state_construct( dst_ctx->dis_clk = dc->res_pool->display_clock; } -bool dc_validate_global_state( +enum dc_status dc_validate_global_state( struct dc *dc, struct dc_state *new_ctx) { enum dc_status result = DC_ERROR_UNEXPECTED; int i, j; - if (dc->res_pool->funcs->validate_global && - dc->res_pool->funcs->validate_global( - dc, new_ctx) != DC_OK) - return false; + if (dc->res_pool->funcs->validate_global) { + result = dc->res_pool->funcs->validate_global(dc, new_ctx); + if (result != DC_OK) + return result; + } for (i = 0; new_ctx && i < new_ctx->stream_count; i++) { struct dc_stream_state *stream = new_ctx->streams[i]; @@ -2713,7 +2756,7 @@ void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream, fmt_bit_depth->pixel_encoding = pixel_encoding; } -bool dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) +enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) { struct dc *core_dc = dc; struct dc_link *link = stream->sink->link; @@ -2737,16 +2780,16 @@ bool dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) link, &stream->timing); - return res == DC_OK; + return res; } -bool dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state) +enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state) { - struct dc *core_dc = dc; + enum dc_status res = DC_OK; /* TODO For now validates pixel format only */ - if (core_dc->res_pool->funcs->validate_plane) - return core_dc->res_pool->funcs->validate_plane(plane_state) == DC_OK; + if (dc->res_pool->funcs->validate_plane) + return dc->res_pool->funcs->validate_plane(plane_state, &dc->caps); - return true; + return res; } 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 23df7bc020d2..5cf69af9693d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -173,7 +173,7 @@ struct dc_stream_status *dc_stream_get_status( * Update the cursor attributes and set cursor surface address */ bool dc_stream_set_cursor_attributes( - const struct dc_stream_state *stream, + struct dc_stream_state *stream, const struct dc_cursor_attributes *attributes) { int i; @@ -189,21 +189,51 @@ bool dc_stream_set_cursor_attributes( return false; } + if (attributes->address.quad_part == 0) { + dm_output_to_console("DC: Cursor address is 0!\n"); + return false; + } + core_dc = stream->ctx->dc; res_ctx = &core_dc->current_state->res_ctx; for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; - if (pipe_ctx->stream != stream || !pipe_ctx->plane_res.ipp) + if (pipe_ctx->stream != stream || (!pipe_ctx->plane_res.xfm && !pipe_ctx->plane_res.dpp)) continue; if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state) continue; - pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes( - pipe_ctx->plane_res.ipp, attributes); + + if (pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes != NULL) + pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes( + pipe_ctx->plane_res.ipp, attributes); + + if (pipe_ctx->plane_res.hubp != NULL && + pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes != NULL) + pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes( + pipe_ctx->plane_res.hubp, attributes); + + if (pipe_ctx->plane_res.mi != NULL && + pipe_ctx->plane_res.mi->funcs->set_cursor_attributes != NULL) + pipe_ctx->plane_res.mi->funcs->set_cursor_attributes( + pipe_ctx->plane_res.mi, attributes); + + + if (pipe_ctx->plane_res.xfm != NULL && + pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes != NULL) + pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes( + pipe_ctx->plane_res.xfm, attributes); + + if (pipe_ctx->plane_res.dpp != NULL && + pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes != NULL) + pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes( + pipe_ctx->plane_res.dpp, attributes); } + stream->cursor_attributes = *attributes; + return true; } @@ -231,6 +261,10 @@ bool dc_stream_set_cursor_position( for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; + struct mem_input *mi = pipe_ctx->plane_res.mi; + struct hubp *hubp = pipe_ctx->plane_res.hubp; + struct transform *xfm = pipe_ctx->plane_res.xfm; + struct dpp *dpp = pipe_ctx->plane_res.dpp; struct dc_cursor_position pos_cpy = *position; struct dc_cursor_mi_param param = { .pixel_clk_khz = stream->timing.pix_clk_khz, @@ -241,7 +275,9 @@ bool dc_stream_set_cursor_position( }; if (pipe_ctx->stream != stream || - !pipe_ctx->plane_res.ipp || !pipe_ctx->plane_state) + (!pipe_ctx->plane_res.mi && !pipe_ctx->plane_res.hubp) || + !pipe_ctx->plane_state || + (!pipe_ctx->plane_res.xfm && !pipe_ctx->plane_res.dpp)) continue; if (pipe_ctx->plane_state->address.type @@ -251,7 +287,22 @@ bool dc_stream_set_cursor_position( if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state) pos_cpy.enable = false; - ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, ¶m); + + if (ipp->funcs->ipp_cursor_set_position != NULL) + ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, ¶m); + + if (mi != NULL && mi->funcs->set_cursor_position != NULL) + mi->funcs->set_cursor_position(mi, &pos_cpy, ¶m); + + if (hubp != NULL && hubp->funcs->set_cursor_position != NULL) + hubp->funcs->set_cursor_position(hubp, &pos_cpy, ¶m); + + if (xfm != NULL && xfm->funcs->set_cursor_position != NULL) + xfm->funcs->set_cursor_position(xfm, &pos_cpy, ¶m, hubp->curs_attr.width); + + if (dpp != NULL && dpp->funcs->set_cursor_position != NULL) + dpp->funcs->set_cursor_position(dpp, &pos_cpy, ¶m, hubp->curs_attr.width); + } return true; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index d43783a45ab6..5aa2270f36fd 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -30,6 +30,7 @@ /* DC core (private) */ #include "core_types.h" #include "transform.h" +#include "dpp.h" /******************************************************************************* * Private functions diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 4ff543826476..9d8f4a55c74e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -38,7 +38,7 @@ #include "inc/compressor.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.1.01" +#define DC_VER "3.1.07" #define MAX_SURFACES 3 #define MAX_STREAMS 6 @@ -56,11 +56,12 @@ struct dc_caps { uint32_t max_planes; uint32_t max_downscale_ratio; uint32_t i2c_speed_in_khz; - unsigned int max_cursor_size; + unsigned int max_video_width; + bool dcc_const_color; + bool dynamic_audio; }; - struct dc_dcc_surface_param { struct dc_size surface_size; enum surface_pixel_format format; @@ -132,6 +133,10 @@ struct dc_stream_state_funcs { void (*set_dither_option)(struct dc_stream_state *stream, enum dc_dither_option option); + + void (*set_dpms)(struct dc *dc, + struct dc_stream_state *stream, + bool dpms_off); }; struct link_training_settings; @@ -162,6 +167,23 @@ struct dc_config { bool disable_disp_pll_sharing; }; +enum dcc_option { + DCC_ENABLE = 0, + DCC_DISABLE = 1, + DCC_HALF_REQ_DISALBE = 2, +}; + +enum pipe_split_policy { + MPC_SPLIT_DYNAMIC = 0, + MPC_SPLIT_AVOID = 1, + MPC_SPLIT_AVOID_MULT_DISP = 2, +}; + +enum wm_report_mode { + WM_REPORT_DEFAULT = 0, + WM_REPORT_OVERRIDE = 1, +}; + struct dc_debug { bool surface_visual_confirm; bool sanity_checks; @@ -170,14 +192,21 @@ struct dc_debug { bool timing_trace; bool clock_trace; bool validation_trace; + + /* stutter efficiency related */ bool disable_stutter; - bool disable_dcc; + bool use_max_lb; + enum dcc_option disable_dcc; + enum pipe_split_policy pipe_split_policy; + bool force_single_disp_pipe_split; + bool voltage_align_fclk; + bool disable_dfs_bypass; bool disable_dpp_power_gate; bool disable_hubp_power_gate; bool disable_pplib_wm_range; - bool use_dml_wm; - bool disable_pipe_split; + enum wm_report_mode pplib_wm_report_mode; + unsigned int min_disp_clk_khz; int sr_exit_time_dpm0_ns; int sr_enter_plus_exit_time_dpm0_ns; int sr_exit_time_ns; @@ -191,6 +220,11 @@ struct dc_debug { bool disable_dmcu; bool disable_psr; bool force_abm_enable; + bool disable_hbup_pg; + bool disable_dpp_pg; + bool disable_stereo_support; + bool vsr_support; + bool performance_trace; }; struct dc_state; struct resource_pool; @@ -233,7 +267,7 @@ struct dc { struct dm_pp_display_configuration prev_display_config; /* FBC compressor */ -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) struct compressor *fbc_compressor; #endif }; @@ -268,7 +302,7 @@ struct dc_init_data { struct dc_config flags; uint32_t log_mask; -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) uint64_t fbc_gpu_addr; #endif }; @@ -285,6 +319,38 @@ enum { TRANSFER_FUNC_POINTS = 1025 }; +// Moved here from color module for linux +enum color_transfer_func { + transfer_func_unknown, + transfer_func_srgb, + transfer_func_bt709, + transfer_func_pq2084, + transfer_func_pq2084_interim, + transfer_func_linear_0_1, + transfer_func_linear_0_125, + transfer_func_dolbyvision, + transfer_func_gamma_22, + transfer_func_gamma_26 +}; + +enum color_color_space { + color_space_unsupported, + color_space_srgb, + color_space_bt601, + color_space_bt709, + color_space_xv_ycc_bt601, + color_space_xv_ycc_bt709, + color_space_xr_rgb, + color_space_bt2020, + color_space_adobe, + color_space_dci_p3, + color_space_sc_rgb_ms_ref, + color_space_display_native, + color_space_app_ctrl, + color_space_dolby_vision, + color_space_custom_coordinates +}; + struct dc_hdr_static_metadata { /* display chromaticities and white point in units of 0.00001 */ unsigned int chromaticity_green_x; @@ -365,6 +431,12 @@ struct dc_plane_state { struct dc_gamma *gamma_correction; struct dc_transfer_func *in_transfer_func; + // sourceContentAttribute cache + bool is_source_input_valid; + struct dc_hdr_static_metadata source_input_mastering_info; + enum color_color_space source_input_color_space; + enum color_transfer_func source_input_tf; + enum dc_color_space color_space; enum surface_pixel_format format; enum dc_rotation_angle rotation; @@ -449,23 +521,6 @@ struct dc_flip_addrs { /* TODO: add flip duration for FreeSync */ }; -/* - * Set up surface attributes and associate to a stream - * The surfaces parameter is an absolute set of all surface active for the stream. - * If no surfaces are provided, the stream will be blanked; no memory read. - * Any flip related attribute changes must be done through this interface. - * - * After this call: - * Surfaces attributes are programmed and configured to be composed into stream. - * This does not trigger a flip. No surface address is programmed. - */ - -bool dc_commit_planes_to_stream( - struct dc *dc, - struct dc_plane_state **plane_states, - uint8_t new_plane_count, - struct dc_stream_state *stream); - bool dc_post_update_surfaces_to_stream( struct dc *dc); @@ -554,9 +609,12 @@ struct dc_stream_state { int phy_pix_clk; enum signal_type signal; + bool dpms_off; struct dc_stream_status status; + struct dc_cursor_attributes cursor_attributes; + /* from stream struct */ struct kref refcount; }; @@ -569,11 +627,10 @@ struct dc_stream_update { bool dc_is_stream_unchanged( struct dc_stream_state *old_stream, struct dc_stream_state *stream); +bool dc_is_stream_scaling_unchanged( + struct dc_stream_state *old_stream, struct dc_stream_state *stream); /* - * Setup stream attributes if no stream updates are provided - * there will be no impact on the stream parameters - * * Set up surface attributes and associate to a stream * The surfaces parameter is an absolute set of all surface active for the stream. * If no surfaces are provided, the stream will be blanked; no memory read. @@ -582,14 +639,22 @@ bool dc_is_stream_unchanged( * After this call: * Surfaces attributes are programmed and configured to be composed into stream. * This does not trigger a flip. No surface address is programmed. - * */ -void dc_update_planes_and_stream(struct dc *dc, - struct dc_surface_update *surface_updates, int surface_count, +bool dc_commit_planes_to_stream( + struct dc *dc, + struct dc_plane_state **plane_states, + uint8_t new_plane_count, struct dc_stream_state *dc_stream, - struct dc_stream_update *stream_update); + struct dc_state *state); +void dc_commit_updates_for_stream(struct dc *dc, + struct dc_surface_update *srf_updates, + int surface_count, + struct dc_stream_state *stream, + struct dc_stream_update *stream_update, + struct dc_plane_state **plane_states, + struct dc_state *state); /* * Log the current stream state. */ @@ -616,12 +681,12 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream, uint32_t *h_position, uint32_t *v_position); -bool dc_add_stream_to_ctx( +enum dc_status dc_add_stream_to_ctx( struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *stream); -bool dc_remove_stream_from_ctx( +enum dc_status dc_remove_stream_from_ctx( struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *stream); @@ -660,11 +725,11 @@ struct dc_validation_set { uint8_t plane_count; }; -bool dc_validate_stream(struct dc *dc, struct dc_stream_state *stream); +enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream); -bool dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state); +enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state); -bool dc_validate_global_state( +enum dc_status dc_validate_global_state( struct dc *dc, struct dc_state *new_ctx); @@ -991,7 +1056,7 @@ struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params); ******************************************************************************/ /* TODO: Deprecated once we switch to dc_set_cursor_position */ bool dc_stream_set_cursor_attributes( - const struct dc_stream_state *stream, + struct dc_stream_state *stream, const struct dc_cursor_attributes *attributes); bool dc_stream_set_cursor_position( 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 4ab109314e4b..1a9f57fb0838 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -204,6 +204,8 @@ enum surface_pixel_format { /*grow 444 video here if necessary */ }; + + /* Pixel format */ enum pixel_format { /*graph*/ diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 6b891fde400c..a8698e399111 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -92,7 +92,7 @@ struct dc_context { bool created_bios; struct gpio_service *gpio_service; struct i2caux *i2caux; -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) uint64_t fbc_gpu_addr; #endif }; @@ -151,6 +151,7 @@ enum dc_edid_status { EDID_BAD_INPUT, EDID_NO_RESPONSE, EDID_BAD_CHECKSUM, + EDID_THE_SAME, }; /* audio capability from EDID*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 2d3a41f744af..52506155e361 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -27,6 +27,10 @@ #include "hw_sequencer.h" +#define BL_REG_LIST()\ + SR(LVTMA_PWRSEQ_CNTL), \ + SR(LVTMA_PWRSEQ_STATE) + #define HWSEQ_DCEF_REG_LIST_DCE8() \ .DCFE_CLOCK_CONTROL[0] = mmCRTC0_CRTC_DCFE_CLOCK_CONTROL, \ .DCFE_CLOCK_CONTROL[1] = mmCRTC1_CRTC_DCFE_CLOCK_CONTROL, \ @@ -86,24 +90,27 @@ SRII(BLND_CONTROL, BLND, 0),\ SRII(BLND_CONTROL, BLND, 1),\ SR(BLNDV_CONTROL),\ - HWSEQ_PIXEL_RATE_REG_LIST(CRTC) + HWSEQ_PIXEL_RATE_REG_LIST(CRTC),\ + BL_REG_LIST() #define HWSEQ_DCE8_REG_LIST() \ HWSEQ_DCEF_REG_LIST_DCE8(), \ HWSEQ_BLND_REG_LIST(), \ - HWSEQ_PIXEL_RATE_REG_LIST(CRTC) + HWSEQ_PIXEL_RATE_REG_LIST(CRTC),\ + BL_REG_LIST() #define HWSEQ_DCE10_REG_LIST() \ HWSEQ_DCEF_REG_LIST(), \ HWSEQ_BLND_REG_LIST(), \ - HWSEQ_PIXEL_RATE_REG_LIST(CRTC) + HWSEQ_PIXEL_RATE_REG_LIST(CRTC), \ + BL_REG_LIST() #define HWSEQ_ST_REG_LIST() \ HWSEQ_DCE11_REG_LIST_BASE(), \ .DCFE_CLOCK_CONTROL[2] = mmDCFEV_CLOCK_CONTROL, \ .CRTC_H_BLANK_START_END[2] = mmCRTCV_H_BLANK_START_END, \ .BLND_V_UPDATE_LOCK[2] = mmBLNDV_V_UPDATE_LOCK, \ - .BLND_CONTROL[2] = mmBLNDV_CONTROL, + .BLND_CONTROL[2] = mmBLNDV_CONTROL #define HWSEQ_CZ_REG_LIST() \ HWSEQ_DCE11_REG_LIST_BASE(), \ @@ -123,16 +130,16 @@ SR(DCHUB_FB_LOCATION),\ SR(DCHUB_AGP_BASE),\ SR(DCHUB_AGP_BOT),\ - SR(DCHUB_AGP_TOP) + SR(DCHUB_AGP_TOP), \ + BL_REG_LIST() #define HWSEQ_DCE112_REG_LIST() \ HWSEQ_DCE10_REG_LIST(), \ HWSEQ_PIXEL_RATE_REG_LIST(CRTC), \ - HWSEQ_PHYPLL_REG_LIST(CRTC) + HWSEQ_PHYPLL_REG_LIST(CRTC), \ + BL_REG_LIST() #define HWSEQ_DCN_REG_LIST()\ - HWSEQ_PIXEL_RATE_REG_LIST(OTG), \ - HWSEQ_PHYPLL_REG_LIST(OTG), \ SRII(OTG_GLOBAL_SYNC_STATUS, OTG, 0), \ SRII(OTG_GLOBAL_SYNC_STATUS, OTG, 1), \ SRII(OTG_GLOBAL_SYNC_STATUS, OTG, 2), \ @@ -156,23 +163,15 @@ SR(REFCLK_CNTL), \ SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A),\ SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A),\ - SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A),\ - SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A),\ SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A),\ SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B),\ SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B),\ - SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B),\ - SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B),\ SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B),\ SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C),\ SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C),\ - SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C),\ - SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C),\ SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C),\ SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D),\ SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D),\ - SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D),\ - SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D),\ SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D),\ SR(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL),\ SR(DCHUBBUB_ARB_DRAM_STATE_CNTL),\ @@ -181,32 +180,11 @@ SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ SR(DCHUBBUB_TEST_DEBUG_INDEX), \ SR(DCHUBBUB_TEST_DEBUG_DATA), \ - SR(DC_IP_REQUEST_CNTL), \ - SR(DOMAIN0_PG_CONFIG), \ - SR(DOMAIN1_PG_CONFIG), \ - SR(DOMAIN2_PG_CONFIG), \ - SR(DOMAIN3_PG_CONFIG), \ - SR(DOMAIN4_PG_CONFIG), \ - SR(DOMAIN5_PG_CONFIG), \ - SR(DOMAIN6_PG_CONFIG), \ - SR(DOMAIN7_PG_CONFIG), \ - SR(DOMAIN0_PG_STATUS), \ - SR(DOMAIN1_PG_STATUS), \ - SR(DOMAIN2_PG_STATUS), \ - SR(DOMAIN3_PG_STATUS), \ - SR(DOMAIN4_PG_STATUS), \ - SR(DOMAIN5_PG_STATUS), \ - SR(DOMAIN6_PG_STATUS), \ - SR(DOMAIN7_PG_STATUS), \ SR(DIO_MEM_PWR_CTRL), \ SR(DCCG_GATE_DISABLE_CNTL), \ SR(DCCG_GATE_DISABLE_CNTL2), \ SR(DCFCLK_CNTL),\ SR(DCFCLK_CNTL), \ - SR(D1VGA_CONTROL), \ - SR(D2VGA_CONTROL), \ - SR(D3VGA_CONTROL), \ - SR(D4VGA_CONTROL), \ /* todo: get these from GVM instead of reading registers ourselves */\ MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32),\ MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32),\ @@ -221,17 +199,56 @@ MMHUB_SR(MC_VM_SYSTEM_APERTURE_LOW_ADDR),\ MMHUB_SR(MC_VM_SYSTEM_APERTURE_HIGH_ADDR) +#define HWSEQ_SR_WATERMARK_REG_LIST()\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D) + #define HWSEQ_DCN1_REG_LIST()\ HWSEQ_DCN_REG_LIST(), \ + HWSEQ_SR_WATERMARK_REG_LIST(), \ + HWSEQ_PIXEL_RATE_REG_LIST(OTG), \ + HWSEQ_PHYPLL_REG_LIST(OTG), \ SR(DCHUBBUB_SDPIF_FB_TOP),\ SR(DCHUBBUB_SDPIF_FB_BASE),\ SR(DCHUBBUB_SDPIF_FB_OFFSET),\ SR(DCHUBBUB_SDPIF_AGP_BASE),\ SR(DCHUBBUB_SDPIF_AGP_BOT),\ - SR(DCHUBBUB_SDPIF_AGP_TOP) - + SR(DCHUBBUB_SDPIF_AGP_TOP),\ + SR(DOMAIN0_PG_CONFIG), \ + SR(DOMAIN1_PG_CONFIG), \ + SR(DOMAIN2_PG_CONFIG), \ + SR(DOMAIN3_PG_CONFIG), \ + SR(DOMAIN4_PG_CONFIG), \ + SR(DOMAIN5_PG_CONFIG), \ + SR(DOMAIN6_PG_CONFIG), \ + SR(DOMAIN7_PG_CONFIG), \ + SR(DOMAIN0_PG_STATUS), \ + SR(DOMAIN1_PG_STATUS), \ + SR(DOMAIN2_PG_STATUS), \ + SR(DOMAIN3_PG_STATUS), \ + SR(DOMAIN4_PG_STATUS), \ + SR(DOMAIN5_PG_STATUS), \ + SR(DOMAIN6_PG_STATUS), \ + SR(DOMAIN7_PG_STATUS), \ + SR(D1VGA_CONTROL), \ + SR(D2VGA_CONTROL), \ + SR(D3VGA_CONTROL), \ + SR(D4VGA_CONTROL), \ + SR(DC_IP_REQUEST_CNTL), \ + BL_REG_LIST() struct dce_hwseq_registers { + + /* Backlight registers */ + uint32_t LVTMA_PWRSEQ_CNTL; + uint32_t LVTMA_PWRSEQ_STATE; + uint32_t DCFE_CLOCK_CONTROL[6]; uint32_t DCFEV_CLOCK_CONTROL; uint32_t DC_MEM_GLOBAL_PWR_REQ_CNTL; @@ -376,20 +393,28 @@ struct dce_hwseq_registers { HWS_SF(BLND_, V_UPDATE_LOCK, BLND_SCL_V_UPDATE_LOCK, mask_sh),\ HWS_SF(BLND_, V_UPDATE_LOCK, BLND_DCP_GRPH_SURF_V_UPDATE_LOCK, mask_sh),\ HWS_SF(BLND_, CONTROL, BLND_MODE, mask_sh),\ + HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh),\ + HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh),\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_) #define HWSEQ_DCE10_MASK_SH_LIST(mask_sh)\ HWSEQ_DCEF_MASK_SH_LIST(mask_sh, DCFE_),\ HWSEQ_BLND_MASK_SH_LIST(mask_sh, BLND_),\ - HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_) + HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_), \ + HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \ + HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh) #define HWSEQ_DCE11_MASK_SH_LIST(mask_sh)\ HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\ SF(DCFEV_CLOCK_CONTROL, DCFEV_CLOCK_ENABLE, mask_sh),\ + HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh),\ + HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh),\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_) #define HWSEQ_DCE112_MASK_SH_LIST(mask_sh)\ HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\ + HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh),\ + HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh),\ HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_) #define HWSEQ_GFX9_DCHUB_MASK_SH_LIST(mask_sh)\ @@ -397,14 +422,18 @@ struct dce_hwseq_registers { SF(DCHUB_FB_LOCATION, FB_BASE, mask_sh),\ SF(DCHUB_AGP_BASE, AGP_BASE, mask_sh),\ SF(DCHUB_AGP_BOT, AGP_BOT, mask_sh),\ - SF(DCHUB_AGP_TOP, AGP_TOP, mask_sh) + SF(DCHUB_AGP_TOP, AGP_TOP, mask_sh), \ + HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \ + HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh) #define HWSEQ_DCE12_MASK_SH_LIST(mask_sh)\ HWSEQ_DCEF_MASK_SH_LIST(mask_sh, DCFE0_DCFE_),\ HWSEQ_BLND_MASK_SH_LIST(mask_sh, BLND0_BLND_),\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_),\ HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_),\ - HWSEQ_GFX9_DCHUB_MASK_SH_LIST(mask_sh) + HWSEQ_GFX9_DCHUB_MASK_SH_LIST(mask_sh), \ + HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \ + HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh) #define HWSEQ_DCN_MASK_SH_LIST(mask_sh)\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, OTG0_),\ @@ -416,35 +445,12 @@ struct dce_hwseq_registers { HWS_SF(DPP_TOP0_, DPP_CONTROL, DPP_CLOCK_ENABLE, mask_sh), \ HWS_SF(OPP_PIPE0_, OPP_PIPE_CONTROL, OPP_PIPE_CLOCK_EN, mask_sh),\ HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, mask_sh), \ - HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ - HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN0_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN0_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN1_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN1_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN2_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN2_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN3_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN3_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN4_PG_CONFIG, DOMAIN4_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN4_PG_CONFIG, DOMAIN4_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN5_PG_CONFIG, DOMAIN5_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN5_PG_CONFIG, DOMAIN5_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN6_PG_CONFIG, DOMAIN6_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN6_PG_CONFIG, DOMAIN6_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN7_PG_CONFIG, DOMAIN7_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN0_PG_STATUS, DOMAIN0_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN1_PG_STATUS, DOMAIN1_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN2_PG_STATUS, DOMAIN2_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN3_PG_STATUS, DOMAIN3_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN4_PG_STATUS, DOMAIN4_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN5_PG_STATUS, DOMAIN5_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN6_PG_STATUS, DOMAIN6_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN7_PG_STATUS, DOMAIN7_PGFSM_PWR_STATUS, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, mask_sh), \ + HWS_SF(, DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, mask_sh), \ + HWS_SF(, DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_SAT_LEVEL, DCHUBBUB_ARB_SAT_LEVEL, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, mask_sh), \ HWS_SF(, DCFCLK_CNTL, DCFCLK_GATE_DIS, mask_sh) @@ -468,7 +474,34 @@ struct dce_hwseq_registers { HWS_SF(, VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32, PHYSICAL_PAGE_ADDR_LO32, mask_sh),\ HWS_SF(, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, PHYSICAL_PAGE_NUMBER_MSB, mask_sh),\ HWS_SF(, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, PHYSICAL_PAGE_NUMBER_LSB, mask_sh),\ - HWS_SF(, MC_VM_SYSTEM_APERTURE_LOW_ADDR, LOGICAL_ADDR, mask_sh) + HWS_SF(, MC_VM_SYSTEM_APERTURE_LOW_ADDR, LOGICAL_ADDR, mask_sh),\ + HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN0_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN0_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN1_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN1_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN2_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN2_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN3_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN3_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN4_PG_CONFIG, DOMAIN4_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN4_PG_CONFIG, DOMAIN4_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN5_PG_CONFIG, DOMAIN5_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN5_PG_CONFIG, DOMAIN5_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN6_PG_CONFIG, DOMAIN6_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN6_PG_CONFIG, DOMAIN6_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN7_PG_CONFIG, DOMAIN7_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN0_PG_STATUS, DOMAIN0_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN1_PG_STATUS, DOMAIN1_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN2_PG_STATUS, DOMAIN2_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN3_PG_STATUS, DOMAIN3_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN4_PG_STATUS, DOMAIN4_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN5_PG_STATUS, DOMAIN5_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN6_PG_STATUS, DOMAIN6_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN7_PG_STATUS, DOMAIN7_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ + HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \ + HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh) #define HWSEQ_REG_FIELD_LIST(type) \ type DCFE_CLOCK_ENABLE; \ @@ -498,7 +531,9 @@ struct dce_hwseq_registers { type PHYSICAL_PAGE_NUMBER_LSB;\ type LOGICAL_ADDR; \ type ENABLE_L1_TLB;\ - type SYSTEM_ACCESS_MODE; + type SYSTEM_ACCESS_MODE;\ + type LVTMA_BLON;\ + type LVTMA_PWRSEQ_TARGET_STATE_R; #define HWSEQ_DCN_REG_FIELD_LIST(type) \ type VUPDATE_NO_LOCK_EVENT_CLEAR; \ @@ -524,6 +559,8 @@ struct dce_hwseq_registers { type DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE;\ type DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE;\ type DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE;\ + type DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE;\ + type DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE;\ type DCHUBBUB_ARB_SAT_LEVEL;\ type DCHUBBUB_ARB_MIN_REQ_OUTSTAND;\ type OPP_PIPE_CLOCK_EN;\ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c index fa481d481132..d618fdd0cc82 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c @@ -37,6 +37,7 @@ #define CTX \ ipp_dce->base.ctx + static void dce_ipp_cursor_set_position( struct input_pixel_processor *ipp, const struct dc_cursor_position *position, @@ -133,6 +134,7 @@ static void dce_ipp_cursor_set_attributes( REG_UPDATE(CUR_UPDATE, CURSOR_UPDATE_LOCK, false); } + static void dce_ipp_program_prescale( struct input_pixel_processor *ipp, struct ipp_prescale_params *params) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 37aeddfb7431..fe88852b4774 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -82,13 +82,6 @@ #define DCE110_DIG_FE_SOURCE_SELECT_DIGF 0x20 #define DCE110_DIG_FE_SOURCE_SELECT_DIGG 0x40 -/* all values are in milliseconds */ -/* For eDP, after power-up/power/down, - * 300/500 msec max. delay from LCDVCC to black video generation */ -#define PANEL_POWER_UP_TIMEOUT 300 -#define PANEL_POWER_DOWN_TIMEOUT 500 -#define HPD_CHECK_INTERVAL 10 - /* Minimum pixel clock, in KHz. For TMDS signal is 25.00 MHz */ #define TMDS_MIN_PIXEL_CLOCK 25000 /* Maximum pixel clock, in KHz. For TMDS signal is 165.00 MHz */ @@ -122,8 +115,6 @@ static const struct link_encoder_funcs dce110_lnk_enc_funcs = { .psr_program_dp_dphy_fast_training = dce110_psr_program_dp_dphy_fast_training, .psr_program_secondary_packet = dce110_psr_program_secondary_packet, - .backlight_control = dce110_link_encoder_edp_backlight_control, - .power_control = dce110_link_encoder_edp_power_control, .connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe, .enable_hpd = dce110_link_encoder_enable_hpd, .disable_hpd = dce110_link_encoder_disable_hpd, @@ -493,165 +484,6 @@ static void configure_encoder( REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_ADVANCE, 1); } -static bool is_panel_powered_on(struct dce110_link_encoder *enc110) -{ - bool ret; - uint32_t value; - - REG_GET(LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, &value); - ret = value; - - return ret == 1; -} - - -/* TODO duplicate of dc_link.c version */ -static struct gpio *get_hpd_gpio(const struct link_encoder *enc) -{ - enum bp_result bp_result; - struct dc_bios *dcb = enc->ctx->dc_bios; - struct graphics_object_hpd_info hpd_info; - struct gpio_pin_info pin_info; - - if (dcb->funcs->get_hpd_info(dcb, enc->connector, &hpd_info) != BP_RESULT_OK) - return NULL; - - bp_result = dcb->funcs->get_gpio_pin_info(dcb, - hpd_info.hpd_int_gpio_uid, &pin_info); - - if (bp_result != BP_RESULT_OK) { - ASSERT(bp_result == BP_RESULT_NORECORD); - return NULL; - } - - return dal_gpio_service_create_irq( - enc->ctx->gpio_service, - pin_info.offset, - pin_info.mask); -} - -/* - * @brief - * eDP only. - */ -static void link_encoder_edp_wait_for_hpd_ready( - struct dce110_link_encoder *enc110, - bool power_up) -{ - struct dc_context *ctx = enc110->base.ctx; - struct graphics_object_id connector = enc110->base.connector; - struct gpio *hpd; - bool edp_hpd_high = false; - uint32_t time_elapsed = 0; - uint32_t timeout = power_up ? - PANEL_POWER_UP_TIMEOUT : PANEL_POWER_DOWN_TIMEOUT; - - if (dal_graphics_object_id_get_connector_id(connector) != - CONNECTOR_ID_EDP) { - BREAK_TO_DEBUGGER(); - return; - } - - if (!power_up) - /* from KV, we will not HPD low after turning off VCC - - * instead, we will check the SW timer in power_up(). */ - return; - - /* when we power on/off the eDP panel, - * we need to wait until SENSE bit is high/low */ - - /* obtain HPD */ - /* TODO what to do with this? */ - hpd = get_hpd_gpio(&enc110->base); - - if (!hpd) { - BREAK_TO_DEBUGGER(); - return; - } - - dal_gpio_open(hpd, GPIO_MODE_INTERRUPT); - - /* wait until timeout or panel detected */ - - do { - uint32_t detected = 0; - - dal_gpio_get_value(hpd, &detected); - - if (!(detected ^ power_up)) { - edp_hpd_high = true; - break; - } - - msleep(HPD_CHECK_INTERVAL); - - time_elapsed += HPD_CHECK_INTERVAL; - } while (time_elapsed < timeout); - - dal_gpio_close(hpd); - - dal_gpio_destroy_irq(&hpd); - - if (false == edp_hpd_high) { - dm_logger_write(ctx->logger, LOG_ERROR, - "%s: wait timed out!\n", __func__); - } -} - -/* - * @brief - * eDP only. Control the power of the eDP panel. - */ -void dce110_link_encoder_edp_power_control( - struct link_encoder *enc, - bool power_up) -{ - struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); - struct dc_context *ctx = enc110->base.ctx; - struct bp_transmitter_control cntl = { 0 }; - enum bp_result bp_result; - - if (dal_graphics_object_id_get_connector_id(enc110->base.connector) != - CONNECTOR_ID_EDP) { - BREAK_TO_DEBUGGER(); - return; - } - - if ((power_up && !is_panel_powered_on(enc110)) || - (!power_up && is_panel_powered_on(enc110))) { - - /* Send VBIOS command to prompt eDP panel power */ - - dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, - "%s: Panel Power action: %s\n", - __func__, (power_up ? "On":"Off")); - - cntl.action = power_up ? - TRANSMITTER_CONTROL_POWER_ON : - TRANSMITTER_CONTROL_POWER_OFF; - cntl.transmitter = enc110->base.transmitter; - cntl.connector_obj_id = enc110->base.connector; - cntl.coherent = false; - cntl.lanes_number = LANE_COUNT_FOUR; - cntl.hpd_sel = enc110->base.hpd_source; - - bp_result = link_transmitter_control(enc110, &cntl); - - if (BP_RESULT_OK != bp_result) { - - dm_logger_write(ctx->logger, LOG_ERROR, - "%s: Panel Power bp_result: %d\n", - __func__, bp_result); - } - } else { - dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, - "%s: Skipping Panel Power action: %s\n", - __func__, (power_up ? "On":"Off")); - } - - link_encoder_edp_wait_for_hpd_ready(enc110, true); -} - static void aux_initialize( struct dce110_link_encoder *enc110) { @@ -674,16 +506,6 @@ static void aux_initialize( } -/*todo: cloned in stream enc, fix*/ -static bool is_panel_backlight_on(struct dce110_link_encoder *enc110) -{ - uint32_t value; - - REG_GET(LVTMA_PWRSEQ_CNTL, LVTMA_BLON, &value); - - return value; -} - void dce110_psr_program_dp_dphy_fast_training(struct link_encoder *enc, bool exit_link_training_required) { @@ -718,69 +540,6 @@ void dce110_psr_program_secondary_packet(struct link_encoder *enc, DP_SEC_GSP0_PRIORITY, 1); } -/*todo: cloned in stream enc, fix*/ -/* - * @brief - * eDP only. Control the backlight of the eDP panel - */ -void dce110_link_encoder_edp_backlight_control( - struct link_encoder *enc, - bool enable) -{ - struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); - struct dc_context *ctx = enc110->base.ctx; - struct bp_transmitter_control cntl = { 0 }; - - if (dal_graphics_object_id_get_connector_id(enc110->base.connector) - != CONNECTOR_ID_EDP) { - BREAK_TO_DEBUGGER(); - return; - } - - if (enable && is_panel_backlight_on(enc110)) { - dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, - "%s: panel already powered up. Do nothing.\n", - __func__); - return; - } - - if (!enable && !is_panel_backlight_on(enc110)) { - dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, - "%s: panel already powered down. Do nothing.\n", - __func__); - return; - } - - /* Send VBIOS command to control eDP panel backlight */ - - dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, - "%s: backlight action: %s\n", - __func__, (enable ? "On":"Off")); - - cntl.action = enable ? - TRANSMITTER_CONTROL_BACKLIGHT_ON : - TRANSMITTER_CONTROL_BACKLIGHT_OFF; - /*cntl.engine_id = ctx->engine;*/ - cntl.transmitter = enc110->base.transmitter; - cntl.connector_obj_id = enc110->base.connector; - /*todo: unhardcode*/ - cntl.lanes_number = LANE_COUNT_FOUR; - cntl.hpd_sel = enc110->base.hpd_source; - - /* For eDP, the following delays might need to be considered - * after link training completed: - * idle period - min. accounts for required BS-Idle pattern, - * max. allows for source frame synchronization); - * 50 msec max. delay from valid video data from source - * to video on dislpay or backlight enable. - * - * Disable the delay for now. - * Enable it in the future if necessary. - */ - /* dc_service_sleep_in_milliseconds(50); */ - link_transmitter_control(enc110, &cntl); -} - static bool is_dig_enabled(const struct dce110_link_encoder *enc110) { uint32_t value; @@ -998,11 +757,6 @@ void dce110_link_encoder_construct( enc110->base.preferred_engine = ENGINE_ID_UNKNOWN; } - dm_logger_write(init_data->ctx->logger, LOG_I2C_AUX, - "Using channel: %s [%d]\n", - DECODE_CHANNEL_ID(init_data->channel), - init_data->channel); - /* Override features with DCE-specific values */ if (BP_RESULT_OK == bp_funcs->get_encoder_cap_info( enc110->base.ctx->dc_bios, enc110->base.id, @@ -1092,7 +846,7 @@ void dce110_link_encoder_hw_init( ASSERT(result == BP_RESULT_OK); } else if (enc110->base.connector.id == CONNECTOR_ID_EDP) { - enc->funcs->power_control(&enc110->base, true); + ctx->dc->hwss.edp_power_control(enc, true); } aux_initialize(enc110); @@ -1279,7 +1033,8 @@ void dce110_link_encoder_enable_dp_mst_output( */ void dce110_link_encoder_disable_output( struct link_encoder *enc, - enum signal_type signal) + enum signal_type signal, + struct dc_link *link) { struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); struct dc_context *ctx = enc110->base.ctx; @@ -1291,7 +1046,7 @@ void dce110_link_encoder_disable_output( return; } if (enc110->base.connector.id == CONNECTOR_ID_EDP) - dce110_link_encoder_edp_backlight_control(enc, false); + ctx->dc->hwss.edp_backlight_control(link, false); /* Power-down RX and disable GPU PHY should be paired. * Disabling PHY without powering down RX may cause * symbol lock loss, on which we will get DP Sink interrupt. */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index be0a45bdc5e2..494067dedd03 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -44,8 +44,6 @@ SRI(DC_HPD_CONTROL, HPD, id) #define LE_COMMON_REG_LIST_BASE(id) \ - SR(LVTMA_PWRSEQ_CNTL), \ - SR(LVTMA_PWRSEQ_STATE), \ SR(DMCU_RAM_ACCESS_CTRL), \ SR(DMCU_IRAM_RD_CTRL), \ SR(DMCU_IRAM_RD_DATA), \ @@ -104,8 +102,7 @@ LE_COMMON_REG_LIST_BASE(id), \ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ - SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \ - SR(DMU_MEM_PWR_CNTL) + SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id) struct dce110_link_enc_aux_registers { uint32_t AUX_CONTROL; @@ -117,10 +114,6 @@ struct dce110_link_enc_hpd_registers { }; struct dce110_link_enc_registers { - /* Backlight registers */ - uint32_t LVTMA_PWRSEQ_CNTL; - uint32_t LVTMA_PWRSEQ_STATE; - /* DMCU registers */ uint32_t MASTER_COMM_DATA_REG1; uint32_t MASTER_COMM_DATA_REG2; @@ -236,7 +229,8 @@ void dce110_link_encoder_enable_dp_mst_output( /* disable PHY output */ void dce110_link_encoder_disable_output( struct link_encoder *link_enc, - enum signal_type signal); + enum signal_type signal, + struct dc_link *link); /* set DP lane settings */ void dce110_link_encoder_dp_set_lane_settings( @@ -252,14 +246,6 @@ void dce110_link_encoder_update_mst_stream_allocation_table( struct link_encoder *enc, const struct link_mst_stream_allocation_table *table); -void dce110_link_encoder_edp_backlight_control( - struct link_encoder *enc, - bool enable); - -void dce110_link_encoder_edp_power_control( - struct link_encoder *enc, - bool power_up); - void dce110_link_encoder_connect_dig_be_to_fe( struct link_encoder *enc, enum engine_id engine, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index 83d9caa4f438..0790f25c7b3b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -361,7 +361,7 @@ static void program_grph_pixel_format( enum surface_pixel_format format) { uint32_t red_xbar = 0, blue_xbar = 0; /* no swap */ - uint32_t grph_depth, grph_format; + uint32_t grph_depth = 0, grph_format = 0; uint32_t sign = 0, floating = 0; if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR8888 || @@ -685,9 +685,6 @@ void dce_mem_input_construct( dce_mi->regs = regs; dce_mi->shifts = mi_shift; dce_mi->masks = mi_mask; - - dce_mi->base.mpcc_id = 0xf; - dce_mi->base.opp_id = 0xf; } void dce112_mem_input_construct( diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index b1cf591b3408..90911258bdb3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -743,7 +743,7 @@ static void dce100_destroy_resource_pool(struct resource_pool **pool) *pool = NULL; } -enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state) +enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state, struct dc_caps *caps) { if (plane_state->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h index f52cae24ee23..de8fdf438f9b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h @@ -16,7 +16,7 @@ struct resource_pool *dce100_create_resource_pool( uint8_t num_virtual_links, struct dc *dc); -enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state); +enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state, struct dc_caps *caps); enum dc_status dce100_add_stream_to_ctx( struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c index 3872febb4f6b..6923662413cd 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c @@ -514,7 +514,7 @@ void dce110_compressor_construct(struct dce110_compressor *compressor, compressor->base.lpt_channels_num = 0; compressor->base.attached_inst = 0; compressor->base.is_enabled = false; -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) compressor->base.funcs = &dce110_compressor_funcs; #endif 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 de154329b049..2a6d3ca12954 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 @@ -32,8 +32,9 @@ #include "dce110_hw_sequencer.h" #include "dce110_timing_generator.h" #include "dce/dce_hwseq.h" +#include "gpio_service_interface.h" -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) #include "dce110_compressor.h" #endif @@ -45,10 +46,10 @@ #include "transform.h" #include "stream_encoder.h" #include "link_encoder.h" +#include "link_hwss.h" #include "clock_source.h" #include "abm.h" #include "audio.h" -#include "dce/dce_hwseq.h" #include "reg_helper.h" /* include DCE11 register header files */ @@ -56,6 +57,24 @@ #include "dce/dce_11_0_sh_mask.h" #include "custom_float.h" +/* + * All values are in milliseconds; + * For eDP, after power-up/power/down, + * 300/500 msec max. delay from LCDVCC to black video generation + */ +#define PANEL_POWER_UP_TIMEOUT 300 +#define PANEL_POWER_DOWN_TIMEOUT 500 +#define HPD_CHECK_INTERVAL 10 + +#define CTX \ + hws->ctx +#define REG(reg)\ + hws->regs->reg + +#undef FN +#define FN(reg_name, field_name) \ + hws->shifts->field_name, hws->masks->field_name + struct dce110_hw_seq_reg_offsets { uint32_t crtc; }; @@ -761,10 +780,216 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx) } -void dce110_disable_stream(struct pipe_ctx *pipe_ctx) +/*todo: cloned in stream enc, fix*/ +static bool is_panel_backlight_on(struct dce_hwseq *hws) +{ + uint32_t value; + + REG_GET(LVTMA_PWRSEQ_CNTL, LVTMA_BLON, &value); + + return value; +} + +static bool is_panel_powered_on(struct dce_hwseq *hws) +{ + uint32_t value; + + REG_GET(LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, &value); + return value == 1; +} + +static enum bp_result link_transmitter_control( + struct dc_bios *bios, + struct bp_transmitter_control *cntl) +{ + enum bp_result result; + + result = bios->funcs->transmitter_control(bios, cntl); + + return result; +} + +/* + * @brief + * eDP only. + */ +void hwss_edp_wait_for_hpd_ready( + struct link_encoder *enc, + bool power_up) +{ + struct dc_context *ctx = enc->ctx; + struct graphics_object_id connector = enc->connector; + struct gpio *hpd; + bool edp_hpd_high = false; + uint32_t time_elapsed = 0; + uint32_t timeout = power_up ? + PANEL_POWER_UP_TIMEOUT : PANEL_POWER_DOWN_TIMEOUT; + + if (dal_graphics_object_id_get_connector_id(connector) + != CONNECTOR_ID_EDP) { + BREAK_TO_DEBUGGER(); + return; + } + + if (!power_up) + /* + * From KV, we will not HPD low after turning off VCC - + * instead, we will check the SW timer in power_up(). + */ + return; + + /* + * When we power on/off the eDP panel, + * we need to wait until SENSE bit is high/low. + */ + + /* obtain HPD */ + /* TODO what to do with this? */ + hpd = get_hpd_gpio(ctx->dc_bios, connector, ctx->gpio_service); + + if (!hpd) { + BREAK_TO_DEBUGGER(); + return; + } + + dal_gpio_open(hpd, GPIO_MODE_INTERRUPT); + + /* wait until timeout or panel detected */ + + do { + uint32_t detected = 0; + + dal_gpio_get_value(hpd, &detected); + + if (!(detected ^ power_up)) { + edp_hpd_high = true; + break; + } + + msleep(HPD_CHECK_INTERVAL); + + time_elapsed += HPD_CHECK_INTERVAL; + } while (time_elapsed < timeout); + + dal_gpio_close(hpd); + + dal_gpio_destroy_irq(&hpd); + + if (false == edp_hpd_high) { + dm_logger_write(ctx->logger, LOG_ERROR, + "%s: wait timed out!\n", __func__); + } +} + +void hwss_edp_power_control( + struct link_encoder *enc, + bool power_up) +{ + struct dc_context *ctx = enc->ctx; + struct dce_hwseq *hwseq = ctx->dc->hwseq; + struct bp_transmitter_control cntl = { 0 }; + enum bp_result bp_result; + + + if (dal_graphics_object_id_get_connector_id(enc->connector) + != CONNECTOR_ID_EDP) { + BREAK_TO_DEBUGGER(); + return; + } + + if (power_up != is_panel_powered_on(hwseq)) { + /* Send VBIOS command to prompt eDP panel power */ + + dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, + "%s: Panel Power action: %s\n", + __func__, (power_up ? "On":"Off")); + + cntl.action = power_up ? + TRANSMITTER_CONTROL_POWER_ON : + TRANSMITTER_CONTROL_POWER_OFF; + cntl.transmitter = enc->transmitter; + cntl.connector_obj_id = enc->connector; + cntl.coherent = false; + cntl.lanes_number = LANE_COUNT_FOUR; + cntl.hpd_sel = enc->hpd_source; + + bp_result = link_transmitter_control(ctx->dc_bios, &cntl); + + if (bp_result != BP_RESULT_OK) + dm_logger_write(ctx->logger, LOG_ERROR, + "%s: Panel Power bp_result: %d\n", + __func__, bp_result); + } else { + dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, + "%s: Skipping Panel Power action: %s\n", + __func__, (power_up ? "On":"Off")); + } + + hwss_edp_wait_for_hpd_ready(enc, true); +} + +/*todo: cloned in stream enc, fix*/ +/* + * @brief + * eDP only. Control the backlight of the eDP panel + */ +void hwss_edp_backlight_control( + struct dc_link *link, + bool enable) +{ + struct dce_hwseq *hws = link->dc->hwseq; + struct dc_context *ctx = link->dc->ctx; + struct bp_transmitter_control cntl = { 0 }; + + if (dal_graphics_object_id_get_connector_id(link->link_id) + != CONNECTOR_ID_EDP) { + BREAK_TO_DEBUGGER(); + return; + } + + if (enable && is_panel_backlight_on(hws)) { + dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, + "%s: panel already powered up. Do nothing.\n", + __func__); + return; + } + + /* Send VBIOS command to control eDP panel backlight */ + + dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, + "%s: backlight action: %s\n", + __func__, (enable ? "On":"Off")); + + cntl.action = enable ? + TRANSMITTER_CONTROL_BACKLIGHT_ON : + TRANSMITTER_CONTROL_BACKLIGHT_OFF; + + /*cntl.engine_id = ctx->engine;*/ + cntl.transmitter = link->link_enc->transmitter; + cntl.connector_obj_id = link->link_enc->connector; + /*todo: unhardcode*/ + cntl.lanes_number = LANE_COUNT_FOUR; + cntl.hpd_sel = link->link_enc->hpd_source; + + /* For eDP, the following delays might need to be considered + * after link training completed: + * idle period - min. accounts for required BS-Idle pattern, + * max. allows for source frame synchronization); + * 50 msec max. delay from valid video data from source + * to video on dislpay or backlight enable. + * + * Disable the delay for now. + * Enable it in the future if necessary. + */ + /* dc_service_sleep_in_milliseconds(50); */ + link_transmitter_control(link->dc->ctx->dc_bios, &cntl); +} + +void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option) { struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; + struct dc *dc = pipe_ctx->stream->ctx->dc; if (pipe_ctx->stream_res.audio) { pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio); @@ -775,6 +1000,13 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) else pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable( pipe_ctx->stream_res.stream_enc); + /*don't free audio if it is from retrain or internal disable stream*/ + if (option == FREE_ACQUIRED_RESOURCE && dc->caps.dynamic_audio == true) { + /*we have to dynamic arbitrate the audio endpoints*/ + pipe_ctx->stream_res.audio = NULL; + /*we free the resource, need reset is_audio_acquired*/ + update_audio_usage(&dc->current_state->res_ctx, dc->res_pool, pipe_ctx->stream_res.audio, false); + } /* TODO: notify audio driver for if audio modes list changed * add audio mode list change flag */ @@ -798,7 +1030,7 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) /* blank at encoder level */ if (dc_is_dp_signal(pipe_ctx->stream->signal)) { if (pipe_ctx->stream->sink->link->connector_signal == SIGNAL_TYPE_EDP) - link->link_enc->funcs->backlight_control(link->link_enc, false); + hwss_edp_backlight_control(link, false); pipe_ctx->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc); } link->link_enc->funcs->connect_dig_be_to_fe( @@ -820,7 +1052,7 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, params.link_settings.link_rate = link_settings->link_rate; pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, ¶ms); if (link->connector_signal == SIGNAL_TYPE_EDP) - link->link_enc->funcs->backlight_control(link->link_enc, true); + hwss_edp_backlight_control(link, true); } @@ -1132,33 +1364,21 @@ static enum dc_status apply_single_controller_ctx_to_hw( resource_build_info_frame(pipe_ctx); dce110_update_info_frame(pipe_ctx); if (!pipe_ctx_old->stream) { - core_link_enable_stream(context, pipe_ctx); - - - if (dc_is_dp_signal(pipe_ctx->stream->signal)) - dce110_unblank_stream(pipe_ctx, - &stream->sink->link->cur_link_settings); + if (!pipe_ctx->stream->dpms_off) + core_link_enable_stream(context, pipe_ctx); } pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; - /* program_scaler and allocate_mem_input are not new asic */ - if ((!pipe_ctx_old || - memcmp(&pipe_ctx_old->plane_res.scl_data, &pipe_ctx->plane_res.scl_data, - sizeof(struct scaler_data)) != 0) && - pipe_ctx->plane_state) { - program_scaler(dc, pipe_ctx); - } /* mst support - use total stream count */ -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - if (pipe_ctx->plane_res.mi->funcs->allocate_mem_input != NULL) -#endif + if (pipe_ctx->plane_res.mi != NULL) { pipe_ctx->plane_res.mi->funcs->allocate_mem_input( - pipe_ctx->plane_res.mi, - stream->timing.h_total, - stream->timing.v_total, - stream->timing.pix_clk_khz, - context->stream_count); + pipe_ctx->plane_res.mi, + stream->timing.h_total, + stream->timing.v_total, + stream->timing.pix_clk_khz, + context->stream_count); + } pipe_ctx->stream->sink->link->psr_enabled = false; @@ -1171,6 +1391,16 @@ static void power_down_encoders(struct dc *dc) { int i; enum connector_id connector_id; + enum signal_type signal = SIGNAL_TYPE_NONE; + + /* do not know BIOS back-front mapping, simply blank all. It will not + * hurt for non-DP + */ + for (i = 0; i < dc->res_pool->stream_enc_count; i++) { + dc->res_pool->stream_enc[i]->funcs->dp_blank( + dc->res_pool->stream_enc[i]); + } + for (i = 0; i < dc->link_count; i++) { connector_id = dal_graphics_object_id_get_connector_id(dc->links[i]->link_id); if ((connector_id == CONNECTOR_ID_DISPLAY_PORT) || @@ -1178,10 +1408,12 @@ static void power_down_encoders(struct dc *dc) if (!dc->links[i]->wa_flags.dp_keep_receiver_powered) dp_receiver_power_ctrl(dc->links[i], false); + if (connector_id == CONNECTOR_ID_EDP) + signal = SIGNAL_TYPE_EDP; } dc->links[i]->link_enc->funcs->disable_output( - dc->links[i]->link_enc, SIGNAL_TYPE_NONE); + dc->links[i]->link_enc, signal, dc->links[i]); } } @@ -1218,7 +1450,7 @@ static void power_down_all_hw_blocks(struct dc *dc) power_down_clock_sources(dc); -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) if (dc->fbc_compressor) dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); #endif @@ -1325,7 +1557,7 @@ static void set_safe_displaymarks( SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK }; for (i = 0; i < MAX_PIPES; i++) { - if (res_ctx->pipe_ctx[i].stream == NULL) + if (res_ctx->pipe_ctx[i].stream == NULL || res_ctx->pipe_ctx[i].plane_res.mi == NULL) continue; res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_display_marks( @@ -1334,6 +1566,7 @@ static void set_safe_displaymarks( max_marks, max_marks, MAX_WATERMARK); + if (i == underlay_idx) res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_chroma_display_marks( res_ctx->pipe_ctx[i].plane_res.mi, @@ -1341,6 +1574,7 @@ static void set_safe_displaymarks( max_marks, max_marks, MAX_WATERMARK); + } } @@ -1391,7 +1625,7 @@ static void set_static_screen_control(struct pipe_ctx **pipe_ctx, if (events->cursor_update) value |= 0x2; -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) value |= 0x84; #endif @@ -1521,7 +1755,7 @@ static void apply_min_clocks( } } -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) /* * Check if FBC can be enabled @@ -1644,7 +1878,10 @@ static void dce110_reset_hw_ctx_wrap( pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) { struct clock_source *old_clk = pipe_ctx_old->clock_source; - core_link_disable_stream(pipe_ctx_old); + /* disable already, no need to disable again */ + if (pipe_ctx->stream && !pipe_ctx->stream->dpms_off) + core_link_disable_stream(pipe_ctx_old, FREE_ACQUIRED_RESOURCE); + pipe_ctx_old->stream_res.tg->funcs->set_blank(pipe_ctx_old->stream_res.tg, true); if (!hwss_wait_for_blank_complete(pipe_ctx_old->stream_res.tg)) { dm_error("DC: failed to blank crtc!\n"); @@ -1713,7 +1950,7 @@ enum dc_status dce110_apply_ctx_to_hw( set_safe_displaymarks(&context->res_ctx, dc->res_pool); -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) if (dc->fbc_compressor) dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); #endif @@ -1889,6 +2126,7 @@ enum dc_status dce110_apply_ctx_to_hw( return status; } + /* pplib is notified if disp_num changed */ dc->hwss.set_bandwidth(dc, context, true); /* to save power */ @@ -1896,7 +2134,7 @@ enum dc_status dce110_apply_ctx_to_hw( dcb->funcs->set_scratch_critical_state(dcb, false); -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) if (dc->fbc_compressor) enable_fbc(dc, context); @@ -2305,7 +2543,7 @@ static void init_hw(struct dc *dc) abm->funcs->init_backlight(abm); abm->funcs->abm_init(abm); } -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) if (dc->fbc_compressor) dc->fbc_compressor->funcs->power_up_fbc(dc->fbc_compressor); #endif @@ -2490,6 +2728,8 @@ static void dce110_program_front_end_for_pipe( struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct xfm_grph_csc_adjustment adjust; struct out_csc_color_matrix tbl_entry; + struct pipe_ctx *cur_pipe_ctx = + &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; unsigned int i; memset(&tbl_entry, 0, sizeof(tbl_entry)); @@ -2553,6 +2793,15 @@ static void dce110_program_front_end_for_pipe( program_scaler(dc, pipe_ctx); +#if defined(CONFIG_DRM_AMD_DC_FBC) + if (dc->fbc_compressor && old_pipe->stream) { + if (plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL) + dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); + else + enable_fbc(dc, dc->current_state); + } +#endif + mi->funcs->mem_input_program_surface_config( mi, plane_state->format, @@ -2571,6 +2820,14 @@ static void dce110_program_front_end_for_pipe( &plane_state->tiling_info, plane_state->rotation); + /* Moved programming gamma from dc to hwss */ + if (cur_pipe_ctx->plane_state != pipe_ctx->plane_state) { + dc->hwss.set_input_transfer_func( + pipe_ctx, pipe_ctx->plane_state); + dc->hwss.set_output_transfer_func( + pipe_ctx, pipe_ctx->stream); + } + dm_logger_write(dc->ctx->logger, LOG_SURFACE, "Pipe:%d 0x%x: addr hi:0x%x, " "addr low:0x%x, " @@ -2683,7 +2940,7 @@ static void program_csc_matrix(struct pipe_ctx *pipe_ctx, } } -static void ready_shared_resources(struct dc *dc) {} +static void ready_shared_resources(struct dc *dc, struct dc_state *context) {} static void optimize_shared_resources(struct dc *dc) {} @@ -2720,7 +2977,8 @@ static const struct hw_sequencer_funcs dce110_funcs = { .wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect, .ready_shared_resources = ready_shared_resources, .optimize_shared_resources = optimize_shared_resources, - + .edp_backlight_control = hwss_edp_backlight_control, + .edp_power_control = hwss_edp_power_control, }; void dce110_hw_sequencer_construct(struct dc *dc) 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 db6c19cd15eb..4d72bb99be93 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 @@ -47,7 +47,7 @@ void dce110_set_displaymarks( void dce110_enable_stream(struct pipe_ctx *pipe_ctx); -void dce110_disable_stream(struct pipe_ctx *pipe_ctx); +void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option); void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, struct dc_link_settings *link_settings); @@ -68,5 +68,14 @@ void dce110_fill_display_configs( uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context); void dp_receiver_power_ctrl(struct dc_link *link, bool on); + +void hwss_edp_power_control( + struct link_encoder *enc, + bool power_up); + +void hwss_edp_backlight_control( + struct dc_link *link, + bool enable); + #endif /* __DC_HWSS_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 28e768de744c..db96d2b47ff1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -52,7 +52,7 @@ #include "dce/dce_abm.h" #include "dce/dce_dmcu.h" -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) #include "dce110/dce110_compressor.h" #endif @@ -849,7 +849,7 @@ static bool dce110_validate_bandwidth( static bool dce110_validate_surface_sets( struct dc_state *context) { - int i; + int i, j; for (i = 0; i < context->stream_count; i++) { if (context->stream_status[i].plane_count == 0) @@ -858,14 +858,27 @@ static bool dce110_validate_surface_sets( if (context->stream_status[i].plane_count > 2) return false; - if ((context->stream_status[i].plane_states[i]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) && - (context->stream_status[i].plane_states[i]->src_rect.width > 1920 || - context->stream_status[i].plane_states[i]->src_rect.height > 1080)) - return false; + for (j = 0; j < context->stream_status[i].plane_count; j++) { + struct dc_plane_state *plane = + context->stream_status[i].plane_states[j]; - /* irrespective of plane format, stream should be RGB encoded */ - if (context->streams[i]->timing.pixel_encoding != PIXEL_ENCODING_RGB) - return false; + /* underlay validation */ + if (plane->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { + + if ((plane->src_rect.width > 1920 || + plane->src_rect.height > 1080)) + return false; + + /* irrespective of plane format, + * stream should be RGB encoded + */ + if (context->streams[i]->timing.pixel_encoding + != PIXEL_ENCODING_RGB) + return false; + + } + + } } return true; @@ -1266,7 +1279,7 @@ static bool construct( } } -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) dc->fbc_compressor = dce110_compressor_create(ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile index 2d6d3a371858..ebeb88283a14 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile @@ -3,8 +3,8 @@ DCN10 = dcn10_resource.o dcn10_ipp.o dcn10_hw_sequencer.o \ dcn10_dpp.o dcn10_opp.o dcn10_timing_generator.o \ - dcn10_mem_input.o dcn10_mpc.o \ - dcn10_dpp_dscl.o dcn10_dpp_cm.o dcn10_dpp_cm_helper.o + dcn10_hubp.o dcn10_mpc.o \ + dcn10_dpp_dscl.o dcn10_dpp_cm.o dcn10_cm_common.o AMD_DAL_DCN10 = $(addprefix $(AMDDALPATH)/dc/dcn10/,$(DCN10)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c index f616e08759de..7f579cb19f4b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c @@ -26,7 +26,7 @@ #include "reg_helper.h" #include "dcn10_dpp.h" -#include "dcn10_dpp_cm_helper.h" +#include "dcn10_cm_common.h" #define REG(reg) reg diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.h index 1155ee522898..64836dcf21f2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.h @@ -23,8 +23,8 @@ * */ -#ifndef __DAL_DPP_DCN10_CM_HELPER_H__ -#define __DAL_DPP_DCN10_CM_HELPER_H__ +#ifndef __DAL_DCN10_CM_COMMON_H__ +#define __DAL_DCN10_CM_COMMON_H__ #define TF_HELPER_REG_FIELD_LIST(type) \ type exp_region0_lut_offset; \ 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 9d9604f05095..74e7c82bdc76 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -39,14 +39,14 @@ #define BLACK_OFFSET_CBCR 0x8000 #define REG(reg)\ - xfm->tf_regs->reg + dpp->tf_regs->reg #define CTX \ - xfm->base.ctx + dpp->base.ctx #undef FN #define FN(reg_name, field_name) \ - xfm->tf_shift->field_name, xfm->tf_mask->field_name + dpp->tf_shift->field_name, dpp->tf_mask->field_name enum pixel_format_description { PIXEL_FORMAT_FIXED = 0, @@ -99,7 +99,7 @@ enum gamut_remap_select { }; /* Program gamut remap in bypass mode */ -void dpp_set_gamut_remap_bypass(struct dcn10_dpp *xfm) +void dpp_set_gamut_remap_bypass(struct dcn10_dpp *dpp) { REG_SET(CM_GAMUT_REMAP_CONTROL, 0, CM_GAMUT_REMAP_MODE, 0); @@ -110,7 +110,7 @@ void dpp_set_gamut_remap_bypass(struct dcn10_dpp *xfm) bool dpp_get_optimal_number_of_taps( - struct transform *xfm, + struct dpp *dpp, struct scaler_data *scl_data, const struct scaling_taps *in_taps) { @@ -154,28 +154,29 @@ bool dpp_get_optimal_number_of_taps( else scl_data->taps.h_taps_c = in_taps->h_taps_c; - if (!xfm->ctx->dc->debug.always_scale) { + if (!dpp->ctx->dc->debug.always_scale) { if (IDENTITY_RATIO(scl_data->ratios.horz)) scl_data->taps.h_taps = 1; if (IDENTITY_RATIO(scl_data->ratios.vert)) scl_data->taps.v_taps = 1; - if (IDENTITY_RATIO(scl_data->ratios.horz_c)) - scl_data->taps.h_taps_c = 1; - if (IDENTITY_RATIO(scl_data->ratios.vert_c)) - scl_data->taps.v_taps_c = 1; + /* + * Spreadsheet doesn't handle taps_c is one properly, + * need to force Chroma to always be scaled to pass + * bandwidth validation. + */ } return true; } -void dpp_reset(struct transform *xfm_base) +void dpp_reset(struct dpp *dpp_base) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); - xfm->filter_h_c = NULL; - xfm->filter_v_c = NULL; - xfm->filter_h = NULL; - xfm->filter_v = NULL; + dpp->filter_h_c = NULL; + dpp->filter_v_c = NULL; + dpp->filter_h = NULL; + dpp->filter_v = NULL; /* set boundary mode to 0 */ REG_SET(DSCL_CONTROL, 0, SCL_BOUNDARY_MODE, 0); @@ -183,28 +184,28 @@ void dpp_reset(struct transform *xfm_base) -static void dcn10_dpp_cm_set_regamma_pwl( - struct transform *xfm_base, const struct pwl_params *params) +static void dpp1_cm_set_regamma_pwl( + struct dpp *dpp_base, const struct pwl_params *params) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); - dcn10_dpp_cm_power_on_regamma_lut(xfm_base, true); - dcn10_dpp_cm_configure_regamma_lut(xfm_base, xfm->is_write_to_ram_a_safe); + dpp1_cm_power_on_regamma_lut(dpp_base, true); + dpp1_cm_configure_regamma_lut(dpp_base, dpp->is_write_to_ram_a_safe); - if (xfm->is_write_to_ram_a_safe) - dcn10_dpp_cm_program_regamma_luta_settings(xfm_base, params); + if (dpp->is_write_to_ram_a_safe) + dpp1_cm_program_regamma_luta_settings(dpp_base, params); else - dcn10_dpp_cm_program_regamma_lutb_settings(xfm_base, params); + dpp1_cm_program_regamma_lutb_settings(dpp_base, params); - dcn10_dpp_cm_program_regamma_lut( - xfm_base, params->rgb_resulted, params->hw_points_num); + dpp1_cm_program_regamma_lut( + dpp_base, params->rgb_resulted, params->hw_points_num); } -static void dcn10_dpp_cm_set_regamma_mode( - struct transform *xfm_base, +static void dpp1_cm_set_regamma_mode( + struct dpp *dpp_base, enum opp_regamma mode) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); uint32_t re_mode = 0; uint32_t obuf_bypass = 0; /* need for pipe split */ uint32_t obuf_hupscale = 0; @@ -220,8 +221,8 @@ static void dcn10_dpp_cm_set_regamma_mode( re_mode = 2; break; case OPP_REGAMMA_USER: - re_mode = xfm->is_write_to_ram_a_safe ? 3 : 4; - xfm->is_write_to_ram_a_safe = !xfm->is_write_to_ram_a_safe; + re_mode = dpp->is_write_to_ram_a_safe ? 3 : 4; + dpp->is_write_to_ram_a_safe = !dpp->is_write_to_ram_a_safe; break; default: break; @@ -233,7 +234,7 @@ static void dcn10_dpp_cm_set_regamma_mode( OBUF_H_2X_UPSCALE_EN, obuf_hupscale); } -static void ippn10_setup_format_flags(enum surface_pixel_format input_format,\ +static void dpp1_setup_format_flags(enum surface_pixel_format input_format,\ enum pixel_format_description *fmt) { @@ -246,11 +247,11 @@ static void ippn10_setup_format_flags(enum surface_pixel_format input_format,\ *fmt = PIXEL_FORMAT_FIXED; } -static void ippn10_set_degamma_format_float( - struct transform *xfm_base, +static void dpp1_set_degamma_format_float( + struct dpp *dpp_base, bool is_float) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); if (is_float) { REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 3); @@ -261,8 +262,8 @@ static void ippn10_set_degamma_format_float( } } -void ippn10_cnv_setup ( - struct transform *xfm_base, +void dpp1_cnv_setup ( + struct dpp *dpp_base, enum surface_pixel_format input_format, enum expansion_mode mode) { @@ -272,10 +273,10 @@ void ippn10_cnv_setup ( enum dc_color_space color_space; enum dcn10_input_csc_select select; bool is_float; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); bool force_disable_cursor = false; - ippn10_setup_format_flags(input_format, &fmt); + dpp1_setup_format_flags(input_format, &fmt); alpha_en = 1; pixel_format = 0; color_space = COLOR_SPACE_SRGB; @@ -303,7 +304,7 @@ void ippn10_cnv_setup ( break; } - ippn10_set_degamma_format_float(xfm_base, is_float); + dpp1_set_degamma_format_float(dpp_base, is_float); switch (input_format) { case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: @@ -361,7 +362,7 @@ void ippn10_cnv_setup ( CNVC_SURFACE_PIXEL_FORMAT, pixel_format); REG_UPDATE(FORMAT_CONTROL, FORMAT_CONTROL__ALPHA_EN, alpha_en); - ippn10_program_input_csc(xfm_base, color_space, select); + dpp1_program_input_csc(dpp_base, color_space, select); if (force_disable_cursor) { REG_UPDATE(CURSOR_CONTROL, @@ -371,54 +372,110 @@ void ippn10_cnv_setup ( } } -static const struct transform_funcs dcn10_dpp_funcs = { - .transform_reset = dpp_reset, - .transform_set_scaler = dcn10_dpp_dscl_set_scaler_manual_scale, - .transform_get_optimal_number_of_taps = dpp_get_optimal_number_of_taps, - .transform_set_gamut_remap = dcn10_dpp_cm_set_gamut_remap, - .opp_set_csc_adjustment = dcn10_dpp_cm_set_output_csc_adjustment, - .opp_set_csc_default = dcn10_dpp_cm_set_output_csc_default, - .opp_power_on_regamma_lut = dcn10_dpp_cm_power_on_regamma_lut, - .opp_program_regamma_lut = dcn10_dpp_cm_program_regamma_lut, - .opp_configure_regamma_lut = dcn10_dpp_cm_configure_regamma_lut, - .opp_program_regamma_lutb_settings = dcn10_dpp_cm_program_regamma_lutb_settings, - .opp_program_regamma_luta_settings = dcn10_dpp_cm_program_regamma_luta_settings, - .opp_program_regamma_pwl = dcn10_dpp_cm_set_regamma_pwl, - .opp_set_regamma_mode = dcn10_dpp_cm_set_regamma_mode, - .ipp_set_degamma = ippn10_set_degamma, - .ipp_program_input_lut = ippn10_program_input_lut, - .ipp_program_degamma_pwl = ippn10_set_degamma_pwl, - .ipp_setup = ippn10_cnv_setup, - .ipp_full_bypass = ippn10_full_bypass, +void dpp1_set_cursor_attributes( + struct dpp *dpp_base, + const struct dc_cursor_attributes *attr) +{ + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); + enum dc_cursor_color_format color_format = attr->color_format; + + REG_UPDATE_2(CURSOR0_CONTROL, + CUR0_MODE, color_format, + CUR0_EXPANSION_MODE, 0); + + if (color_format == CURSOR_MODE_MONO) { + /* todo: clarify what to program these to */ + REG_UPDATE(CURSOR0_COLOR0, + CUR0_COLOR0, 0x00000000); + REG_UPDATE(CURSOR0_COLOR1, + CUR0_COLOR1, 0xFFFFFFFF); + } + + /* TODO: Fixed vs float */ + + REG_UPDATE_3(FORMAT_CONTROL, + CNVC_BYPASS, 0, + FORMAT_CONTROL__ALPHA_EN, 1, + FORMAT_EXPANSION_MODE, 0); +} + + +void dpp1_set_cursor_position( + struct dpp *dpp_base, + const struct dc_cursor_position *pos, + const struct dc_cursor_mi_param *param, + uint32_t width) +{ + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); + int src_x_offset = pos->x - pos->x_hotspot - param->viewport_x_start; + uint32_t cur_en = pos->enable ? 1 : 0; + + if (src_x_offset >= (int)param->viewport_width) + cur_en = 0; /* not visible beyond right edge*/ + + if (src_x_offset + (int)width < 0) + cur_en = 0; /* not visible beyond left edge*/ + + REG_UPDATE(CURSOR0_CONTROL, + CUR0_ENABLE, cur_en); + +} + +static const struct dpp_funcs dcn10_dpp_funcs = { + .dpp_reset = dpp_reset, + .dpp_set_scaler = dpp1_dscl_set_scaler_manual_scale, + .dpp_get_optimal_number_of_taps = dpp_get_optimal_number_of_taps, + .dpp_set_gamut_remap = dpp1_cm_set_gamut_remap, + .opp_set_csc_adjustment = dpp1_cm_set_output_csc_adjustment, + .opp_set_csc_default = dpp1_cm_set_output_csc_default, + .opp_power_on_regamma_lut = dpp1_cm_power_on_regamma_lut, + .opp_program_regamma_lut = dpp1_cm_program_regamma_lut, + .opp_configure_regamma_lut = dpp1_cm_configure_regamma_lut, + .opp_program_regamma_lutb_settings = dpp1_cm_program_regamma_lutb_settings, + .opp_program_regamma_luta_settings = dpp1_cm_program_regamma_luta_settings, + .opp_program_regamma_pwl = dpp1_cm_set_regamma_pwl, + .opp_set_regamma_mode = dpp1_cm_set_regamma_mode, + .ipp_set_degamma = dpp1_set_degamma, + .ipp_program_input_lut = dpp1_program_input_lut, + .ipp_program_degamma_pwl = dpp1_set_degamma_pwl, + .ipp_setup = dpp1_cnv_setup, + .ipp_full_bypass = dpp1_full_bypass, + .set_cursor_attributes = dpp1_set_cursor_attributes, + .set_cursor_position = dpp1_set_cursor_position, }; +static struct dpp_caps dcn10_dpp_cap = { + .dscl_data_proc_format = DSCL_DATA_PRCESSING_FIXED_FORMAT, + .dscl_calc_lb_num_partitions = dpp1_dscl_calc_lb_num_partitions, +}; /*****************************************/ /* Constructor, Destructor */ /*****************************************/ -void dcn10_dpp_construct( - struct dcn10_dpp *xfm, +void dpp1_construct( + struct dcn10_dpp *dpp, struct dc_context *ctx, uint32_t inst, const struct dcn_dpp_registers *tf_regs, const struct dcn_dpp_shift *tf_shift, const struct dcn_dpp_mask *tf_mask) { - xfm->base.ctx = ctx; + dpp->base.ctx = ctx; - xfm->base.inst = inst; - xfm->base.funcs = &dcn10_dpp_funcs; + dpp->base.inst = inst; + dpp->base.funcs = &dcn10_dpp_funcs; + dpp->base.caps = &dcn10_dpp_cap; - xfm->tf_regs = tf_regs; - xfm->tf_shift = tf_shift; - xfm->tf_mask = tf_mask; + dpp->tf_regs = tf_regs; + dpp->tf_shift = tf_shift; + dpp->tf_mask = tf_mask; - xfm->lb_pixel_depth_supported = + dpp->lb_pixel_depth_supported = LB_PIXEL_DEPTH_18BPP | LB_PIXEL_DEPTH_24BPP | LB_PIXEL_DEPTH_30BPP; - xfm->lb_bits_per_entry = LB_BITS_PER_ENTRY; - xfm->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x1404*/ + dpp->lb_bits_per_entry = LB_BITS_PER_ENTRY; + dpp->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x1404*/ } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index a1f6b01a2eb4..a9782b1aba47 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -25,10 +25,10 @@ #ifndef __DAL_DPP_DCN10_H__ #define __DAL_DPP_DCN10_H__ -#include "transform.h" +#include "dpp.h" -#define TO_DCN10_DPP(transform)\ - container_of(transform, struct dcn10_dpp, base) +#define TO_DCN10_DPP(dpp)\ + container_of(dpp, struct dcn10_dpp, base) /* TODO: Use correct number of taps. Using polaris values for now */ #define LB_TOTAL_NUMBER_OF_ENTRIES 5124 @@ -112,7 +112,9 @@ SRI(CM_DGAM_CONTROL, CM, id), \ SRI(FORMAT_CONTROL, CNVC_CFG, id), \ SRI(CNVC_SURFACE_PIXEL_FORMAT, CNVC_CFG, id), \ - SRI(CURSOR0_CONTROL, CNVC_CUR, id) + SRI(CURSOR0_CONTROL, CNVC_CUR, id), \ + SRI(CURSOR0_COLOR0, CNVC_CUR, id), \ + SRI(CURSOR0_COLOR1, CNVC_CUR, id) @@ -162,7 +164,8 @@ SRI(CM_IGAM_LUT_RW_CONTROL, CM, id), \ SRI(CM_IGAM_LUT_RW_INDEX, CM, id), \ SRI(CM_IGAM_LUT_SEQ_COLOR, CM, id), \ - SRI(CURSOR_CONTROL, CURSOR, id) + SRI(CURSOR_CONTROL, CURSOR, id), \ + SRI(CM_CMOUT_CONTROL, CM, id) #define TF_REG_LIST_SH_MASK_DCN(mask_sh)\ @@ -302,7 +305,9 @@ TF_SF(CNVC_CFG0_CNVC_SURFACE_PIXEL_FORMAT, CNVC_SURFACE_PIXEL_FORMAT, mask_sh), \ TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_MODE, mask_sh), \ TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_EXPANSION_MODE, mask_sh), \ - TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_ENABLE, mask_sh) + TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_ENABLE, mask_sh), \ + TF_SF(CNVC_CUR0_CURSOR0_COLOR0, CUR0_COLOR0, mask_sh), \ + TF_SF(CNVC_CUR0_CURSOR0_COLOR1, CUR0_COLOR1, mask_sh) #define TF_REG_LIST_SH_MASK_DCN10(mask_sh)\ TF_REG_LIST_SH_MASK_DCN(mask_sh),\ @@ -397,6 +402,7 @@ TF_SF(CM0_CM_CONTROL, CM_BYPASS_EN, mask_sh), \ TF_SF(CM0_CM_IGAM_LUT_SEQ_COLOR, CM_IGAM_LUT_SEQ_COLOR, mask_sh), \ TF_SF(CNVC_CFG0_FORMAT_CONTROL, OUTPUT_FP, mask_sh), \ + TF_SF(CM0_CM_CMOUT_CONTROL, CM_CMOUT_ROUND_TRUNC_MODE, mask_sh), \ TF_SF(CURSOR0_CURSOR_CONTROL, CURSOR_MODE, mask_sh), \ TF_SF(CURSOR0_CURSOR_CONTROL, CURSOR_PITCH, mask_sh), \ TF_SF(CURSOR0_CURSOR_CONTROL, CURSOR_LINES_PER_CHUNK, mask_sh), \ @@ -545,6 +551,7 @@ type CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET; \ type CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS; \ type CM_RGAM_LUT_MODE; \ + type CM_CMOUT_ROUND_TRUNC_MODE; \ type OBUF_BYPASS; \ type OBUF_H_2X_UPSCALE_EN; \ type CM_BLNDGAM_LUT_MODE; \ @@ -989,7 +996,9 @@ type CUR0_EXPANSION_MODE; \ type CUR0_ENABLE; \ type CM_BYPASS; \ - type FORMAT_CONTROL__ALPHA_EN + type FORMAT_CONTROL__ALPHA_EN; \ + type CUR0_COLOR0; \ + type CUR0_COLOR1 @@ -1075,6 +1084,7 @@ struct dcn_dpp_registers { uint32_t CM_RGAM_RAMA_REGION_0_1; uint32_t CM_RGAM_RAMA_REGION_32_33; uint32_t CM_RGAM_CONTROL; + uint32_t CM_CMOUT_CONTROL; uint32_t OBUF_CONTROL; uint32_t CM_BLNDGAM_LUT_WRITE_EN_MASK; uint32_t CM_BLNDGAM_CONTROL; @@ -1237,10 +1247,12 @@ struct dcn_dpp_registers { uint32_t CNVC_SURFACE_PIXEL_FORMAT; uint32_t CURSOR_CONTROL; uint32_t CURSOR0_CONTROL; + uint32_t CURSOR0_COLOR0; + uint32_t CURSOR0_COLOR1; }; struct dcn10_dpp { - struct transform base; + struct dpp base; const struct dcn_dpp_registers *tf_regs; const struct dcn_dpp_shift *tf_shift; @@ -1256,107 +1268,116 @@ struct dcn10_dpp { bool is_write_to_ram_a_safe; }; - - enum dcn10_input_csc_select { INPUT_CSC_SELECT_BYPASS = 0, INPUT_CSC_SELECT_ICSC, INPUT_CSC_SELECT_COMA }; -void ippn10_degamma_ram_select( - struct transform *xfm_base, +bool dpp1_dscl_is_lb_conf_valid( + int ceil_vratio, + int num_partitions, + int vtaps); + +void dpp1_dscl_calc_lb_num_partitions( + const struct scaler_data *scl_data, + enum lb_memory_config lb_config, + int *num_part_y, + int *num_part_c); + +void dpp1_degamma_ram_select( + struct dpp *dpp_base, bool use_ram_a); -void ippn10_program_degamma_luta_settings( - struct transform *xfm_base, +void dpp1_program_degamma_luta_settings( + struct dpp *dpp_base, const struct pwl_params *params); -void ippn10_program_degamma_lutb_settings( - struct transform *xfm_base, +void dpp1_program_degamma_lutb_settings( + struct dpp *dpp_base, const struct pwl_params *params); -void ippn10_program_degamma_lut( - struct transform *xfm_base, +void dpp1_program_degamma_lut( + struct dpp *dpp_base, const struct pwl_result_data *rgb, uint32_t num, bool is_ram_a); -void ippn10_power_on_degamma_lut( - struct transform *xfm_base, +void dpp1_power_on_degamma_lut( + struct dpp *dpp_base, bool power_on); -void ippn10_program_input_csc( - struct transform *xfm_base, +void dpp1_program_input_csc( + struct dpp *dpp_base, enum dc_color_space color_space, enum dcn10_input_csc_select select); -void ippn10_program_input_lut( - struct transform *xfm_base, +void dpp1_program_input_lut( + struct dpp *dpp_base, const struct dc_gamma *gamma); -void ippn10_full_bypass(struct transform *xfm_base); +void dpp1_full_bypass(struct dpp *dpp_base); -void ippn10_set_degamma( - struct transform *xfm_base, +void dpp1_set_degamma( + struct dpp *dpp_base, enum ipp_degamma_mode mode); -void ippn10_set_degamma_pwl(struct transform *xfm_base, +void dpp1_set_degamma_pwl(struct dpp *dpp_base, const struct pwl_params *params); bool dpp_get_optimal_number_of_taps( - struct transform *xfm, + struct dpp *dpp, struct scaler_data *scl_data, const struct scaling_taps *in_taps); -void dpp_reset(struct transform *xfm_base); +void dpp_reset(struct dpp *dpp_base); -void dcn10_dpp_cm_program_regamma_lut( - struct transform *xfm_base, +void dpp1_cm_program_regamma_lut( + struct dpp *dpp_base, const struct pwl_result_data *rgb, uint32_t num); -void dcn10_dpp_cm_power_on_regamma_lut( - struct transform *xfm_base, +void dpp1_cm_power_on_regamma_lut( + struct dpp *dpp_base, bool power_on); -void dcn10_dpp_cm_configure_regamma_lut( - struct transform *xfm_base, +void dpp1_cm_configure_regamma_lut( + struct dpp *dpp_base, bool is_ram_a); /*program re gamma RAM A*/ -void dcn10_dpp_cm_program_regamma_luta_settings( - struct transform *xfm_base, +void dpp1_cm_program_regamma_luta_settings( + struct dpp *dpp_base, const struct pwl_params *params); /*program re gamma RAM B*/ -void dcn10_dpp_cm_program_regamma_lutb_settings( - struct transform *xfm_base, +void dpp1_cm_program_regamma_lutb_settings( + struct dpp *dpp_base, const struct pwl_params *params); -void dcn10_dpp_cm_set_output_csc_adjustment( - struct transform *xfm_base, +void dpp1_cm_set_output_csc_adjustment( + struct dpp *dpp_base, const struct out_csc_color_matrix *tbl_entry); -void dcn10_dpp_cm_set_output_csc_default( - struct transform *xfm_base, +void dpp1_cm_set_output_csc_default( + struct dpp *dpp_base, const struct default_adjustment *default_adjust); -void dcn10_dpp_cm_set_gamut_remap( - struct transform *xfm, - const struct xfm_grph_csc_adjustment *adjust); +void dpp1_cm_set_gamut_remap( + struct dpp *dpp, + const struct dpp_grph_csc_adjustment *adjust); -void dcn10_dpp_dscl_set_scaler_manual_scale( - struct transform *xfm_base, +void dpp1_dscl_set_scaler_manual_scale( + struct dpp *dpp_base, const struct scaler_data *scl_data); -void ippn10_cnv_setup ( - struct transform *xfm_base, +void dpp1_cnv_setup ( + struct dpp *dpp_base, enum surface_pixel_format input_format, enum expansion_mode mode); -void ippn10_full_bypass(struct transform *xfm_base); +void dpp1_full_bypass(struct dpp *dpp_base); -void dcn10_dpp_construct(struct dcn10_dpp *xfm110, +void dpp1_construct(struct dcn10_dpp *dpp1, struct dc_context *ctx, uint32_t inst, const struct dcn_dpp_registers *tf_regs, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c index d0e72acfc1d5..7784001c3a17 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c @@ -29,8 +29,8 @@ #include "reg_helper.h" #include "dcn10_dpp.h" -#include "dcn10_dpp_cm_helper.h" #include "basics/conversion.h" +#include "dcn10_cm_common.h" #define NUM_PHASES 64 #define HORZ_MAX_TAPS 8 @@ -40,14 +40,14 @@ #define BLACK_OFFSET_CBCR 0x8000 #define REG(reg)\ - xfm->tf_regs->reg + dpp->tf_regs->reg #define CTX \ - xfm->base.ctx + dpp->base.ctx #undef FN #define FN(reg_name, field_name) \ - xfm->tf_shift->field_name, xfm->tf_mask->field_name + dpp->tf_shift->field_name, dpp->tf_mask->field_name struct dcn10_input_csc_matrix { enum dc_color_space color_space; @@ -120,7 +120,7 @@ static const struct dcn10_input_csc_matrix dcn10_input_csc_matrix[] = { static void program_gamut_remap( - struct dcn10_dpp *xfm, + struct dcn10_dpp *dpp, const uint16_t *regval, enum gamut_remap_select select) { @@ -146,10 +146,10 @@ static void program_gamut_remap( break; } - gam_regs.shifts.csc_c11 = xfm->tf_shift->CM_GAMUT_REMAP_C11; - gam_regs.masks.csc_c11 = xfm->tf_mask->CM_GAMUT_REMAP_C11; - gam_regs.shifts.csc_c12 = xfm->tf_shift->CM_GAMUT_REMAP_C12; - gam_regs.masks.csc_c12 = xfm->tf_mask->CM_GAMUT_REMAP_C12; + gam_regs.shifts.csc_c11 = dpp->tf_shift->CM_GAMUT_REMAP_C11; + gam_regs.masks.csc_c11 = dpp->tf_mask->CM_GAMUT_REMAP_C11; + gam_regs.shifts.csc_c12 = dpp->tf_shift->CM_GAMUT_REMAP_C12; + gam_regs.masks.csc_c12 = dpp->tf_mask->CM_GAMUT_REMAP_C12; if (select == GAMUT_REMAP_COEFF) { @@ -157,7 +157,7 @@ static void program_gamut_remap( gam_regs.csc_c33_c34 = REG(CM_GAMUT_REMAP_C33_C34); cm_helper_program_color_matrices( - xfm->base.ctx, + dpp->base.ctx, regval, &gam_regs); @@ -167,7 +167,7 @@ static void program_gamut_remap( gam_regs.csc_c33_c34 = REG(CM_COMA_C33_C34); cm_helper_program_color_matrices( - xfm->base.ctx, + dpp->base.ctx, regval, &gam_regs); @@ -177,7 +177,7 @@ static void program_gamut_remap( gam_regs.csc_c33_c34 = REG(CM_COMB_C33_C34); cm_helper_program_color_matrices( - xfm->base.ctx, + dpp->base.ctx, regval, &gam_regs); } @@ -188,15 +188,15 @@ static void program_gamut_remap( } -void dcn10_dpp_cm_set_gamut_remap( - struct transform *xfm, - const struct xfm_grph_csc_adjustment *adjust) +void dpp1_cm_set_gamut_remap( + struct dpp *dpp_base, + const struct dpp_grph_csc_adjustment *adjust) { - struct dcn10_dpp *dcn_xfm = TO_DCN10_DPP(xfm); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW) /* Bypass if type is bypass or hw */ - program_gamut_remap(dcn_xfm, NULL, GAMUT_REMAP_BYPASS); + program_gamut_remap(dpp, NULL, GAMUT_REMAP_BYPASS); else { struct fixed31_32 arr_matrix[12]; uint16_t arr_reg_val[12]; @@ -219,16 +219,16 @@ void dcn10_dpp_cm_set_gamut_remap( convert_float_matrix( arr_reg_val, arr_matrix, 12); - program_gamut_remap(dcn_xfm, arr_reg_val, GAMUT_REMAP_COEFF); + program_gamut_remap(dpp, arr_reg_val, GAMUT_REMAP_COEFF); } } -void dcn10_dpp_cm_set_output_csc_default( - struct transform *xfm_base, +void dpp1_cm_set_output_csc_default( + struct dpp *dpp_base, const struct default_adjustment *default_adjust) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); uint32_t ocsc_mode = 0; if (default_adjust != NULL) { @@ -260,35 +260,35 @@ void dcn10_dpp_cm_set_output_csc_default( } -static void dcn10_dpp_cm_get_reg_field( - struct dcn10_dpp *xfm, +static void dpp1_cm_get_reg_field( + struct dcn10_dpp *dpp, struct xfer_func_reg *reg) { - reg->shifts.exp_region0_lut_offset = xfm->tf_shift->CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET; - reg->masks.exp_region0_lut_offset = xfm->tf_mask->CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET; - reg->shifts.exp_region0_num_segments = xfm->tf_shift->CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; - reg->masks.exp_region0_num_segments = xfm->tf_mask->CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; - reg->shifts.exp_region1_lut_offset = xfm->tf_shift->CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET; - reg->masks.exp_region1_lut_offset = xfm->tf_mask->CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET; - reg->shifts.exp_region1_num_segments = xfm->tf_shift->CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; - reg->masks.exp_region1_num_segments = xfm->tf_mask->CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; - - reg->shifts.field_region_end = xfm->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_B; - reg->masks.field_region_end = xfm->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_B; - reg->shifts.field_region_end_slope = xfm->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B; - reg->masks.field_region_end_slope = xfm->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B; - reg->shifts.field_region_end_base = xfm->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_BASE_B; - reg->masks.field_region_end_base = xfm->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_BASE_B; - reg->shifts.field_region_linear_slope = xfm->tf_shift->CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; - reg->masks.field_region_linear_slope = xfm->tf_mask->CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; - reg->shifts.exp_region_start = xfm->tf_shift->CM_RGAM_RAMB_EXP_REGION_START_B; - reg->masks.exp_region_start = xfm->tf_mask->CM_RGAM_RAMB_EXP_REGION_START_B; - reg->shifts.exp_resion_start_segment = xfm->tf_shift->CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B; - reg->masks.exp_resion_start_segment = xfm->tf_mask->CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B; + reg->shifts.exp_region0_lut_offset = dpp->tf_shift->CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET; + reg->masks.exp_region0_lut_offset = dpp->tf_mask->CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET; + reg->shifts.exp_region0_num_segments = dpp->tf_shift->CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; + reg->masks.exp_region0_num_segments = dpp->tf_mask->CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; + reg->shifts.exp_region1_lut_offset = dpp->tf_shift->CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET; + reg->masks.exp_region1_lut_offset = dpp->tf_mask->CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET; + reg->shifts.exp_region1_num_segments = dpp->tf_shift->CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; + reg->masks.exp_region1_num_segments = dpp->tf_mask->CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; + + reg->shifts.field_region_end = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_B; + reg->masks.field_region_end = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_B; + reg->shifts.field_region_end_slope = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B; + reg->masks.field_region_end_slope = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B; + reg->shifts.field_region_end_base = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_BASE_B; + reg->masks.field_region_end_base = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_BASE_B; + reg->shifts.field_region_linear_slope = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; + reg->masks.field_region_linear_slope = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; + reg->shifts.exp_region_start = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_START_B; + reg->masks.exp_region_start = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_START_B; + reg->shifts.exp_resion_start_segment = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B; + reg->masks.exp_resion_start_segment = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B; } -static void dcn10_dpp_cm_program_color_matrix( - struct dcn10_dpp *xfm, +static void dpp1_cm_program_color_matrix( + struct dcn10_dpp *dpp, const struct out_csc_color_matrix *tbl_entry) { uint32_t mode; @@ -301,10 +301,10 @@ static void dcn10_dpp_cm_program_color_matrix( return; } - gam_regs.shifts.csc_c11 = xfm->tf_shift->CM_OCSC_C11; - gam_regs.masks.csc_c11 = xfm->tf_mask->CM_OCSC_C11; - gam_regs.shifts.csc_c12 = xfm->tf_shift->CM_OCSC_C12; - gam_regs.masks.csc_c12 = xfm->tf_mask->CM_OCSC_C12; + gam_regs.shifts.csc_c11 = dpp->tf_shift->CM_OCSC_C11; + gam_regs.masks.csc_c11 = dpp->tf_mask->CM_OCSC_C11; + gam_regs.shifts.csc_c12 = dpp->tf_shift->CM_OCSC_C12; + gam_regs.masks.csc_c12 = dpp->tf_mask->CM_OCSC_C12; if (mode == 4) { @@ -312,7 +312,7 @@ static void dcn10_dpp_cm_program_color_matrix( gam_regs.csc_c33_c34 = REG(CM_OCSC_C33_C34); cm_helper_program_color_matrices( - xfm->base.ctx, + dpp->base.ctx, tbl_entry->regval, &gam_regs); @@ -322,17 +322,17 @@ static void dcn10_dpp_cm_program_color_matrix( gam_regs.csc_c33_c34 = REG(CM_COMB_C33_C34); cm_helper_program_color_matrices( - xfm->base.ctx, + dpp->base.ctx, tbl_entry->regval, &gam_regs); } } -void dcn10_dpp_cm_set_output_csc_adjustment( - struct transform *xfm_base, +void dpp1_cm_set_output_csc_adjustment( + struct dpp *dpp_base, const struct out_csc_color_matrix *tbl_entry) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); //enum csc_color_mode config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; uint32_t ocsc_mode = 4; @@ -364,26 +364,26 @@ void dcn10_dpp_cm_set_output_csc_adjustment( */ REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode); - dcn10_dpp_cm_program_color_matrix(xfm, tbl_entry); + dpp1_cm_program_color_matrix(dpp, tbl_entry); } -void dcn10_dpp_cm_power_on_regamma_lut( - struct transform *xfm_base, +void dpp1_cm_power_on_regamma_lut( + struct dpp *dpp_base, bool power_on) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); REG_SET(CM_MEM_PWR_CTRL, 0, RGAM_MEM_PWR_FORCE, power_on == true ? 0:1); } -void dcn10_dpp_cm_program_regamma_lut( - struct transform *xfm_base, +void dpp1_cm_program_regamma_lut( + struct dpp *dpp_base, const struct pwl_result_data *rgb, uint32_t num) { uint32_t i; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); for (i = 0 ; i < num; i++) { REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].red_reg); REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].green_reg); @@ -400,11 +400,11 @@ void dcn10_dpp_cm_program_regamma_lut( } -void dcn10_dpp_cm_configure_regamma_lut( - struct transform *xfm_base, +void dpp1_cm_configure_regamma_lut( + struct dpp *dpp_base, bool is_ram_a) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); REG_UPDATE(CM_RGAM_LUT_WRITE_EN_MASK, CM_RGAM_LUT_WRITE_EN_MASK, 7); @@ -414,14 +414,14 @@ void dcn10_dpp_cm_configure_regamma_lut( } /*program re gamma RAM A*/ -void dcn10_dpp_cm_program_regamma_luta_settings( - struct transform *xfm_base, +void dpp1_cm_program_regamma_luta_settings( + struct dpp *dpp_base, const struct pwl_params *params) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); struct xfer_func_reg gam_regs; - dcn10_dpp_cm_get_reg_field(xfm, &gam_regs); + dpp1_cm_get_reg_field(dpp, &gam_regs); gam_regs.start_cntl_b = REG(CM_RGAM_RAMA_START_CNTL_B); gam_regs.start_cntl_g = REG(CM_RGAM_RAMA_START_CNTL_G); @@ -438,19 +438,19 @@ void dcn10_dpp_cm_program_regamma_luta_settings( gam_regs.region_start = REG(CM_RGAM_RAMA_REGION_0_1); gam_regs.region_end = REG(CM_RGAM_RAMA_REGION_32_33); - cm_helper_program_xfer_func(xfm->base.ctx, params, &gam_regs); + cm_helper_program_xfer_func(dpp->base.ctx, params, &gam_regs); } /*program re gamma RAM B*/ -void dcn10_dpp_cm_program_regamma_lutb_settings( - struct transform *xfm_base, +void dpp1_cm_program_regamma_lutb_settings( + struct dpp *dpp_base, const struct pwl_params *params) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); struct xfer_func_reg gam_regs; - dcn10_dpp_cm_get_reg_field(xfm, &gam_regs); + dpp1_cm_get_reg_field(dpp, &gam_regs); gam_regs.start_cntl_b = REG(CM_RGAM_RAMB_START_CNTL_B); gam_regs.start_cntl_g = REG(CM_RGAM_RAMB_START_CNTL_G); @@ -467,15 +467,15 @@ void dcn10_dpp_cm_program_regamma_lutb_settings( gam_regs.region_start = REG(CM_RGAM_RAMB_REGION_0_1); gam_regs.region_end = REG(CM_RGAM_RAMB_REGION_32_33); - cm_helper_program_xfer_func(xfm->base.ctx, params, &gam_regs); + cm_helper_program_xfer_func(dpp->base.ctx, params, &gam_regs); } -void ippn10_program_input_csc( - struct transform *xfm_base, +void dpp1_program_input_csc( + struct dpp *dpp_base, enum dc_color_space color_space, enum dcn10_input_csc_select select) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); int i; int arr_size = sizeof(dcn10_input_csc_matrix)/sizeof(struct dcn10_input_csc_matrix); const uint16_t *regval = NULL; @@ -503,10 +503,10 @@ void ippn10_program_input_csc( REG_SET(CM_ICSC_CONTROL, 0, CM_ICSC_MODE, selection); - gam_regs.shifts.csc_c11 = xfm->tf_shift->CM_ICSC_C11; - gam_regs.masks.csc_c11 = xfm->tf_mask->CM_ICSC_C11; - gam_regs.shifts.csc_c12 = xfm->tf_shift->CM_ICSC_C12; - gam_regs.masks.csc_c12 = xfm->tf_mask->CM_ICSC_C12; + gam_regs.shifts.csc_c11 = dpp->tf_shift->CM_ICSC_C11; + gam_regs.masks.csc_c11 = dpp->tf_mask->CM_ICSC_C11; + gam_regs.shifts.csc_c12 = dpp->tf_shift->CM_ICSC_C12; + gam_regs.masks.csc_c12 = dpp->tf_mask->CM_ICSC_C12; if (select == INPUT_CSC_SELECT_ICSC) { @@ -515,7 +515,7 @@ void ippn10_program_input_csc( gam_regs.csc_c33_c34 = REG(CM_ICSC_C33_C34); cm_helper_program_color_matrices( - xfm->base.ctx, + dpp->base.ctx, regval, &gam_regs); } else { @@ -524,21 +524,21 @@ void ippn10_program_input_csc( gam_regs.csc_c33_c34 = REG(CM_COMA_C33_C34); cm_helper_program_color_matrices( - xfm->base.ctx, + dpp->base.ctx, regval, &gam_regs); } } /*program de gamma RAM B*/ -void ippn10_program_degamma_lutb_settings( - struct transform *xfm_base, +void dpp1_program_degamma_lutb_settings( + struct dpp *dpp_base, const struct pwl_params *params) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); struct xfer_func_reg gam_regs; - dcn10_dpp_cm_get_reg_field(xfm, &gam_regs); + dpp1_cm_get_reg_field(dpp, &gam_regs); gam_regs.start_cntl_b = REG(CM_DGAM_RAMB_START_CNTL_B); gam_regs.start_cntl_g = REG(CM_DGAM_RAMB_START_CNTL_G); @@ -556,18 +556,18 @@ void ippn10_program_degamma_lutb_settings( gam_regs.region_end = REG(CM_DGAM_RAMB_REGION_14_15); - cm_helper_program_xfer_func(xfm->base.ctx, params, &gam_regs); + cm_helper_program_xfer_func(dpp->base.ctx, params, &gam_regs); } /*program de gamma RAM A*/ -void ippn10_program_degamma_luta_settings( - struct transform *xfm_base, +void dpp1_program_degamma_luta_settings( + struct dpp *dpp_base, const struct pwl_params *params) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); struct xfer_func_reg gam_regs; - dcn10_dpp_cm_get_reg_field(xfm, &gam_regs); + dpp1_cm_get_reg_field(dpp, &gam_regs); gam_regs.start_cntl_b = REG(CM_DGAM_RAMA_START_CNTL_B); gam_regs.start_cntl_g = REG(CM_DGAM_RAMA_START_CNTL_G); @@ -584,34 +584,35 @@ void ippn10_program_degamma_luta_settings( gam_regs.region_start = REG(CM_DGAM_RAMA_REGION_0_1); gam_regs.region_end = REG(CM_DGAM_RAMA_REGION_14_15); - cm_helper_program_xfer_func(xfm->base.ctx, params, &gam_regs); + cm_helper_program_xfer_func(dpp->base.ctx, params, &gam_regs); } -void ippn10_power_on_degamma_lut( - struct transform *xfm_base, +void dpp1_power_on_degamma_lut( + struct dpp *dpp_base, bool power_on) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, power_on == true ? 0:1); } -static void ippn10_enable_cm_block( - struct transform *xfm_base) +static void dpp1_enable_cm_block( + struct dpp *dpp_base) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); + REG_UPDATE(CM_CMOUT_CONTROL, CM_CMOUT_ROUND_TRUNC_MODE, 8); REG_UPDATE(CM_CONTROL, CM_BYPASS_EN, 0); } -void ippn10_set_degamma( - struct transform *xfm_base, +void dpp1_set_degamma( + struct dpp *dpp_base, enum ipp_degamma_mode mode) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - ippn10_enable_cm_block(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); + dpp1_enable_cm_block(dpp_base); switch (mode) { case IPP_DEGAMMA_MODE_BYPASS: @@ -630,11 +631,11 @@ void ippn10_set_degamma( } } -void ippn10_degamma_ram_select( - struct transform *xfm_base, +void dpp1_degamma_ram_select( + struct dpp *dpp_base, bool use_ram_a) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); if (use_ram_a) REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 3); @@ -643,13 +644,13 @@ void ippn10_degamma_ram_select( } -static bool ippn10_degamma_ram_inuse( - struct transform *xfm_base, +static bool dpp1_degamma_ram_inuse( + struct dpp *dpp_base, bool *ram_a_inuse) { bool ret = false; uint32_t status_reg = 0; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); REG_GET(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS, &status_reg); @@ -664,15 +665,15 @@ static bool ippn10_degamma_ram_inuse( return ret; } -void ippn10_program_degamma_lut( - struct transform *xfm_base, +void dpp1_program_degamma_lut( + struct dpp *dpp_base, const struct pwl_result_data *rgb, uint32_t num, bool is_ram_a) { uint32_t i; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_HOST_EN, 0); REG_UPDATE(CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_EN_MASK, 7); @@ -694,27 +695,27 @@ void ippn10_program_degamma_lut( } } -void ippn10_set_degamma_pwl(struct transform *xfm_base, +void dpp1_set_degamma_pwl(struct dpp *dpp_base, const struct pwl_params *params) { bool is_ram_a = true; - ippn10_power_on_degamma_lut(xfm_base, true); - ippn10_enable_cm_block(xfm_base); - ippn10_degamma_ram_inuse(xfm_base, &is_ram_a); + dpp1_power_on_degamma_lut(dpp_base, true); + dpp1_enable_cm_block(dpp_base); + dpp1_degamma_ram_inuse(dpp_base, &is_ram_a); if (is_ram_a == true) - ippn10_program_degamma_lutb_settings(xfm_base, params); + dpp1_program_degamma_lutb_settings(dpp_base, params); else - ippn10_program_degamma_luta_settings(xfm_base, params); + dpp1_program_degamma_luta_settings(dpp_base, params); - ippn10_program_degamma_lut(xfm_base, params->rgb_resulted, + dpp1_program_degamma_lut(dpp_base, params->rgb_resulted, params->hw_points_num, !is_ram_a); - ippn10_degamma_ram_select(xfm_base, !is_ram_a); + dpp1_degamma_ram_select(dpp_base, !is_ram_a); } -void ippn10_full_bypass(struct transform *xfm_base) +void dpp1_full_bypass(struct dpp *dpp_base) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); /* Input pixel format: ARGB8888 */ REG_SET(CNVC_SURFACE_PIXEL_FORMAT, 0, @@ -727,19 +728,19 @@ void ippn10_full_bypass(struct transform *xfm_base) FORMAT_EXPANSION_MODE, 0); /* COLOR_KEYER_CONTROL.COLOR_KEYER_EN = 0 this should be default */ - if (xfm->tf_mask->CM_BYPASS_EN) + if (dpp->tf_mask->CM_BYPASS_EN) REG_SET(CM_CONTROL, 0, CM_BYPASS_EN, 1); /* Setting degamma bypass for now */ REG_SET(CM_DGAM_CONTROL, 0, CM_DGAM_LUT_MODE, 0); } -static bool ippn10_ingamma_ram_inuse(struct transform *xfm_base, +static bool dpp1_ingamma_ram_inuse(struct dpp *dpp_base, bool *ram_a_inuse) { bool in_use = false; uint32_t status_reg = 0; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); REG_GET(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS, &status_reg); @@ -765,19 +766,19 @@ static bool ippn10_ingamma_ram_inuse(struct transform *xfm_base, * In the future, this function should support additional input gamma methods, * such as piecewise linear mapping, and input gamma bypass. */ -void ippn10_program_input_lut( - struct transform *xfm_base, +void dpp1_program_input_lut( + struct dpp *dpp_base, const struct dc_gamma *gamma) { int i; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); bool rama_occupied = false; uint32_t ram_num; // Power on LUT memory. REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, 1); - ippn10_enable_cm_block(xfm_base); + dpp1_enable_cm_block(dpp_base); // Determine whether to use RAM A or RAM B - ippn10_ingamma_ram_inuse(xfm_base, &rama_occupied); + dpp1_ingamma_ram_inuse(dpp_base, &rama_occupied); if (!rama_occupied) REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, 0); else diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c index 82b8887d4973..cbad36410b32 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c @@ -31,6 +31,7 @@ #include "dcn10_dpp.h" #include "basics/conversion.h" + #define NUM_PHASES 64 #define HORZ_MAX_TAPS 8 #define VERT_MAX_TAPS 8 @@ -39,14 +40,14 @@ #define BLACK_OFFSET_CBCR 0x8000 #define REG(reg)\ - xfm->tf_regs->reg + dpp->tf_regs->reg #define CTX \ - xfm->base.ctx + dpp->base.ctx #undef FN #define FN(reg_name, field_name) \ - xfm->tf_shift->field_name, xfm->tf_mask->field_name + dpp->tf_shift->field_name, dpp->tf_mask->field_name enum dcn10_coef_filter_type_sel { SCL_COEF_LUMA_VERT_FILTER = 0, @@ -57,22 +58,6 @@ enum dcn10_coef_filter_type_sel { SCL_COEF_ALPHA_HORZ_FILTER = 5 }; -enum lb_memory_config { - /* Enable all 3 pieces of memory */ - LB_MEMORY_CONFIG_0 = 0, - - /* Enable only the first piece of memory */ - LB_MEMORY_CONFIG_1 = 1, - - /* Enable only the second piece of memory */ - LB_MEMORY_CONFIG_2 = 2, - - /* Only applicable in 4:2:0 mode, enable all 3 pieces of memory and the - * last piece of chroma memory used for the luma storage - */ - LB_MEMORY_CONFIG_3 = 3 -}; - enum dscl_autocal_mode { AUTOCAL_MODE_OFF = 0, @@ -100,8 +85,8 @@ enum dscl_mode_sel { DSCL_MODE_DSCL_BYPASS = 6 }; -static void dpp_set_overscan( - struct dcn10_dpp *xfm, +static void dpp1_dscl_set_overscan( + struct dcn10_dpp *dpp, const struct scaler_data *data) { uint32_t left = data->recout.x; @@ -128,8 +113,8 @@ static void dpp_set_overscan( EXT_OVERSCAN_TOP, top); } -static void dpp_set_otg_blank( - struct dcn10_dpp *xfm, const struct scaler_data *data) +static void dpp1_dscl_set_otg_blank( + struct dcn10_dpp *dpp, const struct scaler_data *data) { uint32_t h_blank_start = data->h_active; uint32_t h_blank_end = 0; @@ -145,7 +130,7 @@ static void dpp_set_otg_blank( OTG_V_BLANK_END, v_blank_end); } -static int get_pixel_depth_val(enum lb_pixel_depth depth) +static int dpp1_dscl_get_pixel_depth_val(enum lb_pixel_depth depth) { if (depth == LB_PIXEL_DEPTH_30BPP) return 0; /* 10 bpc */ @@ -161,23 +146,36 @@ static int get_pixel_depth_val(enum lb_pixel_depth depth) } } -static enum dscl_mode_sel get_dscl_mode( - const struct scaler_data *data, bool dbg_always_scale) +static bool dpp1_dscl_is_video_format(enum pixel_format format) { - const long long one = dal_fixed31_32_one.value; - bool ycbcr = false; - bool format420 = false; + if (format >= PIXEL_FORMAT_VIDEO_BEGIN + && format <= PIXEL_FORMAT_VIDEO_END) + return true; + else + return false; +} - if (data->format == PIXEL_FORMAT_FP16) - return DSCL_MODE_DSCL_BYPASS; +static bool dpp1_dscl_is_420_format(enum pixel_format format) +{ + if (format == PIXEL_FORMAT_420BPP8 || + format == PIXEL_FORMAT_420BPP10) + return true; + else + return false; +} - if (data->format >= PIXEL_FORMAT_VIDEO_BEGIN - && data->format <= PIXEL_FORMAT_VIDEO_END) - ycbcr = true; +static enum dscl_mode_sel dpp1_dscl_get_dscl_mode( + struct dpp *dpp_base, + const struct scaler_data *data, + bool dbg_always_scale) +{ + const long long one = dal_fixed31_32_one.value; - if (data->format == PIXEL_FORMAT_420BPP8 || - data->format == PIXEL_FORMAT_420BPP10) - format420 = true; + if (dpp_base->caps->dscl_data_proc_format == DSCL_DATA_PRCESSING_FIXED_FORMAT) { + /* DSCL is processing data in fixed format */ + if (data->format == PIXEL_FORMAT_FP16) + return DSCL_MODE_DSCL_BYPASS; + } if (data->ratios.horz.value == one && data->ratios.vert.value == one @@ -186,8 +184,8 @@ static enum dscl_mode_sel get_dscl_mode( && !dbg_always_scale) return DSCL_MODE_SCALING_444_BYPASS; - if (!format420) { - if (ycbcr) + if (!dpp1_dscl_is_420_format(data->format)) { + if (dpp1_dscl_is_video_format(data->format)) return DSCL_MODE_SCALING_444_YCBCR_ENABLE; else return DSCL_MODE_SCALING_444_RGB_ENABLE; @@ -200,16 +198,17 @@ static enum dscl_mode_sel get_dscl_mode( return DSCL_MODE_SCALING_420_YCBCR_ENABLE; } -static void dpp_set_lb( - struct dcn10_dpp *xfm, +static void dpp1_dscl_set_lb( + struct dcn10_dpp *dpp, const struct line_buffer_params *lb_params, enum lb_memory_config mem_size_config) { - uint32_t pixel_depth = get_pixel_depth_val(lb_params->depth); - uint32_t dyn_pix_depth = lb_params->dynamic_pixel_depth; - /* LB */ - if (xfm->tf_mask->PIXEL_DEPTH) { + if (dpp->base.caps->dscl_data_proc_format == DSCL_DATA_PRCESSING_FIXED_FORMAT) { + /* DSCL caps: pixel data processed in fixed format */ + uint32_t pixel_depth = dpp1_dscl_get_pixel_depth_val(lb_params->depth); + uint32_t dyn_pix_depth = lb_params->dynamic_pixel_depth; + REG_SET_7(LB_DATA_FORMAT, 0, PIXEL_DEPTH, pixel_depth, /* Pixel depth stored in LB */ PIXEL_EXPAN_MODE, lb_params->pixel_expan_mode, /* Pixel expansion mode */ @@ -225,7 +224,7 @@ static void dpp_set_lb( LB_MAX_PARTITIONS, 63); } -static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio) +static const uint16_t *dpp1_dscl_get_filter_coeffs_64p(int taps, struct fixed31_32 ratio) { if (taps == 8) return get_filter_8tap_64p(ratio); @@ -250,8 +249,8 @@ static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio) } } -static void dpp_set_scaler_filter( - struct dcn10_dpp *xfm, +static void dpp1_dscl_set_scaler_filter( + struct dcn10_dpp *dpp, uint32_t taps, enum dcn10_coef_filter_type_sel filter_type, const uint16_t *filter) @@ -288,8 +287,8 @@ static void dpp_set_scaler_filter( } -static void dpp_set_scl_filter( - struct dcn10_dpp *xfm, +static void dpp1_dscl_set_scl_filter( + struct dcn10_dpp *dpp, const struct scaler_data *scl_data, bool chroma_coef_mode) { @@ -307,10 +306,10 @@ static void dpp_set_scl_filter( h_2tap_hardcode_coef_en = scl_data->taps.h_taps < 3 && scl_data->taps.h_taps_c < 3 - && (scl_data->taps.h_taps > 1 || scl_data->taps.h_taps_c > 1); + && (scl_data->taps.h_taps > 1 && scl_data->taps.h_taps_c > 1); v_2tap_hardcode_coef_en = scl_data->taps.v_taps < 3 && scl_data->taps.v_taps_c < 3 - && (scl_data->taps.v_taps > 1 || scl_data->taps.v_taps_c > 1); + && (scl_data->taps.v_taps > 1 && scl_data->taps.v_taps_c > 1); h_2tap_sharp_en = h_2tap_hardcode_coef_en && h_2tap_sharp_factor != 0; v_2tap_sharp_en = v_2tap_hardcode_coef_en && v_2tap_sharp_factor != 0; @@ -326,56 +325,56 @@ static void dpp_set_scl_filter( if (!v_2tap_hardcode_coef_en || !h_2tap_hardcode_coef_en) { bool filter_updated = false; - filter_h = get_filter_coeffs_64p( + filter_h = dpp1_dscl_get_filter_coeffs_64p( scl_data->taps.h_taps, scl_data->ratios.horz); - filter_v = get_filter_coeffs_64p( + filter_v = dpp1_dscl_get_filter_coeffs_64p( scl_data->taps.v_taps, scl_data->ratios.vert); - filter_updated = (filter_h && (filter_h != xfm->filter_h)) - || (filter_v && (filter_v != xfm->filter_v)); + filter_updated = (filter_h && (filter_h != dpp->filter_h)) + || (filter_v && (filter_v != dpp->filter_v)); if (chroma_coef_mode) { - filter_h_c = get_filter_coeffs_64p( + filter_h_c = dpp1_dscl_get_filter_coeffs_64p( scl_data->taps.h_taps_c, scl_data->ratios.horz_c); - filter_v_c = get_filter_coeffs_64p( + filter_v_c = dpp1_dscl_get_filter_coeffs_64p( scl_data->taps.v_taps_c, scl_data->ratios.vert_c); - filter_updated = filter_updated || (filter_h_c && (filter_h_c != xfm->filter_h_c)) - || (filter_v_c && (filter_v_c != xfm->filter_v_c)); + filter_updated = filter_updated || (filter_h_c && (filter_h_c != dpp->filter_h_c)) + || (filter_v_c && (filter_v_c != dpp->filter_v_c)); } if (filter_updated) { uint32_t scl_mode = REG_READ(SCL_MODE); if (!h_2tap_hardcode_coef_en && filter_h) { - dpp_set_scaler_filter( - xfm, scl_data->taps.h_taps, + dpp1_dscl_set_scaler_filter( + dpp, scl_data->taps.h_taps, SCL_COEF_LUMA_HORZ_FILTER, filter_h); } - xfm->filter_h = filter_h; + dpp->filter_h = filter_h; if (!v_2tap_hardcode_coef_en && filter_v) { - dpp_set_scaler_filter( - xfm, scl_data->taps.v_taps, + dpp1_dscl_set_scaler_filter( + dpp, scl_data->taps.v_taps, SCL_COEF_LUMA_VERT_FILTER, filter_v); } - xfm->filter_v = filter_v; + dpp->filter_v = filter_v; if (chroma_coef_mode) { if (!h_2tap_hardcode_coef_en && filter_h_c) { - dpp_set_scaler_filter( - xfm, scl_data->taps.h_taps_c, + dpp1_dscl_set_scaler_filter( + dpp, scl_data->taps.h_taps_c, SCL_COEF_CHROMA_HORZ_FILTER, filter_h_c); } if (!v_2tap_hardcode_coef_en && filter_v_c) { - dpp_set_scaler_filter( - xfm, scl_data->taps.v_taps_c, + dpp1_dscl_set_scaler_filter( + dpp, scl_data->taps.v_taps_c, SCL_COEF_CHROMA_VERT_FILTER, filter_v_c); } } - xfm->filter_h_c = filter_h_c; - xfm->filter_v_c = filter_v_c; + dpp->filter_h_c = filter_h_c; + dpp->filter_v_c = filter_v_c; coef_ram_current = get_reg_field_value_ex( - scl_mode, xfm->tf_mask->SCL_COEF_RAM_SELECT_CURRENT, - xfm->tf_shift->SCL_COEF_RAM_SELECT_CURRENT); + scl_mode, dpp->tf_mask->SCL_COEF_RAM_SELECT_CURRENT, + dpp->tf_shift->SCL_COEF_RAM_SELECT_CURRENT); /* Swap coefficient RAM and set chroma coefficient mode */ REG_SET_2(SCL_MODE, scl_mode, @@ -385,7 +384,7 @@ static void dpp_set_scl_filter( } } -static int get_lb_depth_bpc(enum lb_pixel_depth depth) +static int dpp1_dscl_get_lb_depth_bpc(enum lb_pixel_depth depth) { if (depth == LB_PIXEL_DEPTH_30BPP) return 10; @@ -401,7 +400,7 @@ static int get_lb_depth_bpc(enum lb_pixel_depth depth) } } -static void calc_lb_num_partitions( +void dpp1_dscl_calc_lb_num_partitions( const struct scaler_data *scl_data, enum lb_memory_config lb_config, int *num_part_y, @@ -411,7 +410,7 @@ static void calc_lb_num_partitions( scl_data->viewport.width : scl_data->recout.width; int line_size_c = scl_data->viewport_c.width < scl_data->recout.width ? scl_data->viewport_c.width : scl_data->recout.width; - int lb_bpc = get_lb_depth_bpc(scl_data->lb_params.depth); + int lb_bpc = dpp1_dscl_get_lb_depth_bpc(scl_data->lb_params.depth); int memory_line_size_y = (line_size * lb_bpc + 71) / 72; /* +71 to ceil */ int memory_line_size_c = (line_size_c * lb_bpc + 71) / 72; /* +71 to ceil */ int memory_line_size_a = (line_size + 5) / 6; /* +5 to ceil */ @@ -426,6 +425,7 @@ static void calc_lb_num_partitions( lb_memory_size_c = 1088; lb_memory_size_a = 1312; } else if (lb_config == LB_MEMORY_CONFIG_3) { + /* 420 mode: using 3rd mem from Y, Cr and Cb */ lb_memory_size = 816 + 1088 + 848 + 848 + 848; lb_memory_size_c = 816 + 1088; lb_memory_size_a = 984 + 1312 + 456; @@ -449,7 +449,7 @@ static void calc_lb_num_partitions( } -static bool is_lb_conf_valid(int ceil_vratio, int num_partitions, int vtaps) +bool dpp1_dscl_is_lb_conf_valid(int ceil_vratio, int num_partitions, int vtaps) { if (ceil_vratio > 2) return vtaps <= (num_partitions - ceil_vratio + 2); @@ -458,7 +458,7 @@ static bool is_lb_conf_valid(int ceil_vratio, int num_partitions, int vtaps) } /*find first match configuration which meets the min required lb size*/ -static enum lb_memory_config dpp10_find_lb_memory_config( +static enum lb_memory_config dpp1_dscl_find_lb_memory_config(struct dcn10_dpp *dpp, const struct scaler_data *scl_data) { int num_part_y, num_part_c; @@ -466,75 +466,67 @@ static enum lb_memory_config dpp10_find_lb_memory_config( int vtaps_c = scl_data->taps.v_taps_c; int ceil_vratio = dal_fixed31_32_ceil(scl_data->ratios.vert); int ceil_vratio_c = dal_fixed31_32_ceil(scl_data->ratios.vert_c); + enum lb_memory_config mem_cfg = LB_MEMORY_CONFIG_0; + + if (dpp->base.ctx->dc->debug.use_max_lb) + return mem_cfg; - calc_lb_num_partitions( + dpp->base.caps->dscl_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_1, &num_part_y, &num_part_c); - if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) - && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) + if (dpp1_dscl_is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) + && dpp1_dscl_is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) return LB_MEMORY_CONFIG_1; - calc_lb_num_partitions( + dpp->base.caps->dscl_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_2, &num_part_y, &num_part_c); - if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) - && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) + if (dpp1_dscl_is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) + && dpp1_dscl_is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) return LB_MEMORY_CONFIG_2; if (scl_data->format == PIXEL_FORMAT_420BPP8 || scl_data->format == PIXEL_FORMAT_420BPP10) { - calc_lb_num_partitions( + dpp->base.caps->dscl_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_3, &num_part_y, &num_part_c); - if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) - && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) + if (dpp1_dscl_is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) + && dpp1_dscl_is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) return LB_MEMORY_CONFIG_3; } - calc_lb_num_partitions( + dpp->base.caps->dscl_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_0, &num_part_y, &num_part_c); /*Ensure we can support the requested number of vtaps*/ - ASSERT(is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) - && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)); + ASSERT(dpp1_dscl_is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) + && dpp1_dscl_is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)); return LB_MEMORY_CONFIG_0; } -/*find first match configuration which meets the min required lb size*/ -static enum lb_memory_config find_lb_memory_config(struct dcn10_dpp *xfm, - const struct scaler_data *scl_data) -{ - enum lb_memory_config mem_cfg = LB_MEMORY_CONFIG_0; - - if (xfm->tf_mask->PIXEL_DEPTH) { - mem_cfg = dpp10_find_lb_memory_config(scl_data); - } - return mem_cfg; -} - -void dpp_set_scaler_auto_scale( - struct transform *xfm_base, +void dpp1_dscl_set_scaler_auto_scale( + struct dpp *dpp_base, const struct scaler_data *scl_data) { enum lb_memory_config lb_config; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - enum dscl_mode_sel dscl_mode = get_dscl_mode( - scl_data, xfm_base->ctx->dc->debug.always_scale); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); + enum dscl_mode_sel dscl_mode = dpp1_dscl_get_dscl_mode( + dpp_base, scl_data, dpp_base->ctx->dc->debug.always_scale); bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN && scl_data->format <= PIXEL_FORMAT_VIDEO_END; - dpp_set_overscan(xfm, scl_data); + dpp1_dscl_set_overscan(dpp, scl_data); - dpp_set_otg_blank(xfm, scl_data); + dpp1_dscl_set_otg_blank(dpp, scl_data); REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode); if (dscl_mode == DSCL_MODE_DSCL_BYPASS) return; - lb_config = find_lb_memory_config(xfm, scl_data); - dpp_set_lb(xfm, &scl_data->lb_params, lb_config); + lb_config = dpp1_dscl_find_lb_memory_config(dpp, scl_data); + dpp1_dscl_set_lb(dpp, &scl_data->lb_params, lb_config); if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) return; @@ -562,12 +554,12 @@ void dpp_set_scaler_auto_scale( SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1, SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1); - dpp_set_scl_filter(xfm, scl_data, ycbcr); + dpp1_dscl_set_scl_filter(dpp, scl_data, ycbcr); } -static void dpp_set_manual_ratio_init( - struct dcn10_dpp *xfm, const struct scaler_data *data) +static void dpp1_dscl_set_manual_ratio_init( + struct dcn10_dpp *dpp, const struct scaler_data *data) { uint32_t init_frac = 0; uint32_t init_int = 0; @@ -626,8 +618,8 @@ static void dpp_set_manual_ratio_init( -static void dpp_set_recout( - struct dcn10_dpp *xfm, const struct rect *recout) +static void dpp1_dscl_set_recout( + struct dcn10_dpp *dpp, const struct rect *recout) { REG_SET_2(RECOUT_START, 0, /* First pixel of RECOUT */ @@ -640,24 +632,24 @@ static void dpp_set_recout( RECOUT_WIDTH, recout->width, /* Number of RECOUT vertical lines */ RECOUT_HEIGHT, recout->height - - xfm->base.ctx->dc->debug.surface_visual_confirm * 4 * - (xfm->base.inst + 1)); + - dpp->base.ctx->dc->debug.surface_visual_confirm * 4 * + (dpp->base.inst + 1)); } /* Main function to program scaler and line buffer in manual scaling mode */ -void dcn10_dpp_dscl_set_scaler_manual_scale( - struct transform *xfm_base, +void dpp1_dscl_set_scaler_manual_scale( + struct dpp *dpp_base, const struct scaler_data *scl_data) { enum lb_memory_config lb_config; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - enum dscl_mode_sel dscl_mode = get_dscl_mode( - scl_data, xfm_base->ctx->dc->debug.always_scale); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); + enum dscl_mode_sel dscl_mode = dpp1_dscl_get_dscl_mode( + dpp_base, scl_data, dpp_base->ctx->dc->debug.always_scale); bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN && scl_data->format <= PIXEL_FORMAT_VIDEO_END; /* Recout */ - dpp_set_recout(xfm, &scl_data->recout); + dpp1_dscl_set_recout(dpp, &scl_data->recout); /* MPC Size */ REG_SET_2(MPC_SIZE, 0, @@ -673,8 +665,8 @@ void dcn10_dpp_dscl_set_scaler_manual_scale( return; /* LB */ - lb_config = find_lb_memory_config(xfm, scl_data); - dpp_set_lb(xfm, &scl_data->lb_params, lb_config); + lb_config = dpp1_dscl_find_lb_memory_config(dpp, scl_data); + dpp1_dscl_set_lb(dpp, &scl_data->lb_params, lb_config); if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) return; @@ -697,7 +689,7 @@ void dcn10_dpp_dscl_set_scaler_manual_scale( SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y); /* Manually calculate scale ratio and init values */ - dpp_set_manual_ratio_init(xfm, scl_data); + dpp1_dscl_set_manual_ratio_init(dpp, scl_data); /* HTaps/VTaps */ REG_SET_4(SCL_TAP_CONTROL, 0, @@ -706,5 +698,5 @@ void dcn10_dpp_dscl_set_scaler_manual_scale( SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1, SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1); - dpp_set_scl_filter(xfm, scl_data, ycbcr); + dpp1_dscl_set_scl_filter(dpp, scl_data, ycbcr); } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c index a28495d95a15..b13dee64e0ce 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c @@ -24,23 +24,23 @@ */ #include "dm_services.h" #include "dce_calcs.h" -#include "dcn10_mem_input.h" #include "reg_helper.h" #include "basics/conversion.h" +#include "dcn10_hubp.h" #define REG(reg)\ - mi->mi_regs->reg + hubp1->mi_regs->reg #define CTX \ - mi->base.ctx + hubp1->base.ctx #undef FN #define FN(reg_name, field_name) \ - mi->mi_shift->field_name, mi->mi_mask->field_name + hubp1->mi_shift->field_name, hubp1->mi_mask->field_name -static void min10_set_blank(struct mem_input *mem_input, bool blank) +void hubp1_set_blank(struct hubp *hubp, bool blank) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); uint32_t blank_en = blank ? 1 : 0; REG_UPDATE_2(DCHUBP_CNTL, @@ -51,24 +51,24 @@ static void min10_set_blank(struct mem_input *mem_input, bool blank) REG_WAIT(DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, 1, 1, 200); - mem_input->mpcc_id = 0xf; - mem_input->opp_id = 0xf; + hubp->mpcc_id = 0xf; + hubp->opp_id = 0xf; } } -static void min10_set_hubp_blank_en(struct mem_input *mem_input, bool blank) +static void hubp1_set_hubp_blank_en(struct hubp *hubp, bool blank) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); uint32_t blank_en = blank ? 1 : 0; REG_UPDATE(DCHUBP_CNTL, HUBP_BLANK_EN, blank_en); } -static void min10_vready_workaround(struct mem_input *mem_input, +static void hubp1_vready_workaround(struct hubp *hubp, struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest) { uint32_t value = 0; - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); /* set HBUBREQ_DEBUG_DB[12] = 1 */ value = REG_READ(HUBPREQ_DEBUG_DB); @@ -87,8 +87,8 @@ static void min10_vready_workaround(struct mem_input *mem_input, REG_WRITE(HUBPREQ_DEBUG_DB, value); } -static void min10_program_tiling( - struct dcn10_mem_input *mi, +void hubp1_program_tiling( + struct dcn10_hubp *hubp1, const union dc_tiling_info *info, const enum surface_pixel_format pixel_format) { @@ -107,8 +107,8 @@ static void min10_program_tiling( PIPE_ALIGNED, info->gfx9.pipe_aligned); } -static void min10_program_size_and_rotation( - struct dcn10_mem_input *mi, +void hubp1_program_size_and_rotation( + struct dcn10_hubp *hubp1, enum dc_rotation_angle rotation, enum surface_pixel_format format, const union plane_size *plane_size, @@ -169,8 +169,8 @@ static void min10_program_size_and_rotation( H_MIRROR_EN, mirror); } -static void min10_program_pixel_format( - struct dcn10_mem_input *mi, +void hubp1_program_pixel_format( + struct dcn10_hubp *hubp1, enum surface_pixel_format format) { uint32_t red_bar = 3; @@ -245,12 +245,12 @@ static void min10_program_pixel_format( /* don't see the need of program the xbar in DCN 1.0 */ } -static bool min10_program_surface_flip_and_addr( - struct mem_input *mem_input, +bool hubp1_program_surface_flip_and_addr( + struct hubp *hubp, const struct dc_plane_address *address, bool flip_immediate) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); /* program flip type */ REG_SET(DCSURF_FLIP_CONTROL, 0, @@ -387,28 +387,28 @@ static bool min10_program_surface_flip_and_addr( break; } - mem_input->request_address = *address; + hubp->request_address = *address; if (flip_immediate) - mem_input->current_address = *address; + hubp->current_address = *address; return true; } -static void min10_dcc_control(struct mem_input *mem_input, bool enable, +void hubp1_dcc_control(struct hubp *hubp, bool enable, bool independent_64b_blks) { uint32_t dcc_en = enable ? 1 : 0; uint32_t dcc_ind_64b_blk = independent_64b_blks ? 1 : 0; - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); REG_UPDATE_2(DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_EN, dcc_en, PRIMARY_SURFACE_DCC_IND_64B_BLK, dcc_ind_64b_blk); } -static void min10_program_surface_config( - struct mem_input *mem_input, +void hubp1_program_surface_config( + struct hubp *hubp, enum surface_pixel_format format, union dc_tiling_info *tiling_info, union plane_size *plane_size, @@ -416,20 +416,20 @@ static void min10_program_surface_config( struct dc_plane_dcc_param *dcc, bool horizontal_mirror) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); - min10_dcc_control(mem_input, dcc->enable, dcc->grph.independent_64b_blks); - min10_program_tiling(mi, tiling_info, format); - min10_program_size_and_rotation( - mi, rotation, format, plane_size, dcc, horizontal_mirror); - min10_program_pixel_format(mi, format); + hubp1_dcc_control(hubp, dcc->enable, dcc->grph.independent_64b_blks); + hubp1_program_tiling(hubp1, tiling_info, format); + hubp1_program_size_and_rotation( + hubp1, rotation, format, plane_size, dcc, horizontal_mirror); + hubp1_program_pixel_format(hubp1, format); } -static void min10_program_requestor( - struct mem_input *mem_input, +void hubp1_program_requestor( + struct hubp *hubp, struct _vcs_dpi_display_rq_regs_st *rq_regs) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); REG_UPDATE(HUBPRET_CONTROL, DET_BUF_PLANE1_BASE_ADDRESS, rq_regs->plane1_base_address); @@ -459,12 +459,12 @@ static void min10_program_requestor( } -static void min10_program_deadline( - struct mem_input *mem_input, +void hubp1_program_deadline( + struct hubp *hubp, struct _vcs_dpi_display_dlg_regs_st *dlg_attr, struct _vcs_dpi_display_ttu_regs_st *ttu_attr) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); /* DLG - Per hubp */ REG_SET_2(BLANK_OFFSET_0, 0, @@ -580,8 +580,8 @@ static void min10_program_deadline( ttu_attr->refcyc_per_req_delivery_pre_c); } -static void min10_setup( - struct mem_input *mem_input, +static void hubp1_setup( + struct hubp *hubp, struct _vcs_dpi_display_dlg_regs_st *dlg_attr, struct _vcs_dpi_display_ttu_regs_st *ttu_attr, struct _vcs_dpi_display_rq_regs_st *rq_regs, @@ -590,27 +590,15 @@ static void min10_setup( /* otg is locked when this func is called. Register are double buffered. * disable the requestors is not needed */ - min10_program_requestor(mem_input, rq_regs); - min10_program_deadline(mem_input, dlg_attr, ttu_attr); - min10_vready_workaround(mem_input, pipe_dest); + hubp1_program_requestor(hubp, rq_regs); + hubp1_program_deadline(hubp, dlg_attr, ttu_attr); + hubp1_vready_workaround(hubp, pipe_dest); } -static void min10_program_display_marks( - struct mem_input *mem_input, - struct dce_watermarks nbp, - struct dce_watermarks stutter, - struct dce_watermarks urgent, - uint32_t total_dest_line_time_ns) -{ - /* only for dce - * dcn use only program_watermarks - */ -} - -static bool min10_is_flip_pending(struct mem_input *mem_input) +bool hubp1_is_flip_pending(struct hubp *hubp) { uint32_t flip_pending = 0; - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); struct dc_plane_address earliest_inuse_address; REG_GET(DCSURF_FLIP_CONTROL, @@ -625,17 +613,20 @@ static bool min10_is_flip_pending(struct mem_input *mem_input) if (flip_pending) return true; - if (earliest_inuse_address.grph.addr.quad_part != mem_input->request_address.grph.addr.quad_part) + if (earliest_inuse_address.grph.addr.quad_part != hubp->request_address.grph.addr.quad_part) return true; - mem_input->current_address = mem_input->request_address; + hubp->current_address = hubp->request_address; return false; } -static void min10_set_vm_system_aperture_settings(struct mem_input *mem_input, +uint32_t aperture_default_system = 1; +uint32_t context0_default_system; /* = 0;*/ + +static void hubp1_set_vm_system_aperture_settings(struct hubp *hubp, struct vm_system_aperture_param *apt) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); PHYSICAL_ADDRESS_LOC mc_vm_apt_default; PHYSICAL_ADDRESS_LOC mc_vm_apt_low; PHYSICAL_ADDRESS_LOC mc_vm_apt_high; @@ -645,7 +636,7 @@ static void min10_set_vm_system_aperture_settings(struct mem_input *mem_input, mc_vm_apt_high.quad_part = apt->sys_high.quad_part >> 12; REG_SET_2(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, 0, - MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, 1, /* 1 = system physical memory */ + MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, aperture_default_system, /* 1 = system physical memory */ MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, mc_vm_apt_default.high_part); REG_SET(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, 0, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mc_vm_apt_default.low_part); @@ -661,10 +652,10 @@ static void min10_set_vm_system_aperture_settings(struct mem_input *mem_input, MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, mc_vm_apt_high.low_part); } -static void min10_set_vm_context0_settings(struct mem_input *mem_input, +static void hubp1_set_vm_context0_settings(struct hubp *hubp, const struct vm_context0_param *vm0) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); /* pte base */ REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, 0, VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, vm0->pte_base.high_part); @@ -684,9 +675,9 @@ static void min10_set_vm_context0_settings(struct mem_input *mem_input, VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, vm0->pte_end.low_part); /* fault handling */ - REG_SET(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, 0, - VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, vm0->fault_default.high_part); - /* VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_SYSTEM, 0 */ + REG_SET_2(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, 0, + VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, vm0->fault_default.high_part, + VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_SYSTEM, context0_default_system); REG_SET(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, 0, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, vm0->fault_default.low_part); @@ -696,12 +687,12 @@ static void min10_set_vm_context0_settings(struct mem_input *mem_input, SYSTEM_ACCESS_MODE, 3); } -static void min_set_viewport( - struct mem_input *mem_input, +void min_set_viewport( + struct hubp *hubp, const struct rect *viewport, const struct rect *viewport_c) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION, 0, PRI_VIEWPORT_WIDTH, viewport->width, @@ -730,7 +721,7 @@ static void min_set_viewport( PRI_VIEWPORT_Y_START_C, viewport_c->y); } -void dcn10_mem_input_read_state(struct dcn10_mem_input *mi, +void hubp1_read_state(struct dcn10_hubp *hubp1, struct dcn_hubp_state *s) { REG_GET(DCSURF_SURFACE_CONFIG, @@ -766,41 +757,204 @@ void dcn10_mem_input_read_state(struct dcn10_mem_input *mi, QoS_LEVEL_HIGH_WM, &s->qos_level_high_wm); } -static struct mem_input_funcs dcn10_mem_input_funcs = { - .mem_input_program_display_marks = min10_program_display_marks, - .mem_input_program_surface_flip_and_addr = - min10_program_surface_flip_and_addr, - .mem_input_program_surface_config = - min10_program_surface_config, - .mem_input_is_flip_pending = min10_is_flip_pending, - .mem_input_setup = min10_setup, - .mem_input_set_vm_system_aperture_settings = min10_set_vm_system_aperture_settings, - .mem_input_set_vm_context0_settings = min10_set_vm_context0_settings, - .set_blank = min10_set_blank, - .dcc_control = min10_dcc_control, +enum cursor_pitch { + CURSOR_PITCH_64_PIXELS = 0, + CURSOR_PITCH_128_PIXELS, + CURSOR_PITCH_256_PIXELS +}; + +enum cursor_lines_per_chunk { + CURSOR_LINE_PER_CHUNK_2 = 1, + CURSOR_LINE_PER_CHUNK_4, + CURSOR_LINE_PER_CHUNK_8, + CURSOR_LINE_PER_CHUNK_16 +}; + +static bool ippn10_cursor_program_control( + struct dcn10_hubp *hubp1, + bool pixel_data_invert, + enum dc_cursor_color_format color_format) +{ + if (REG(CURSOR_SETTINS)) + REG_SET_2(CURSOR_SETTINS, 0, + /* no shift of the cursor HDL schedule */ + CURSOR0_DST_Y_OFFSET, 0, + /* used to shift the cursor chunk request deadline */ + CURSOR0_CHUNK_HDL_ADJUST, 3); + else + REG_SET_2(CURSOR_SETTINGS, 0, + /* no shift of the cursor HDL schedule */ + CURSOR0_DST_Y_OFFSET, 0, + /* used to shift the cursor chunk request deadline */ + CURSOR0_CHUNK_HDL_ADJUST, 3); + + return true; +} + +static enum cursor_pitch ippn10_get_cursor_pitch( + unsigned int pitch) +{ + enum cursor_pitch hw_pitch; + + switch (pitch) { + case 64: + hw_pitch = CURSOR_PITCH_64_PIXELS; + break; + case 128: + hw_pitch = CURSOR_PITCH_128_PIXELS; + break; + case 256: + hw_pitch = CURSOR_PITCH_256_PIXELS; + break; + default: + DC_ERR("Invalid cursor pitch of %d. " + "Only 64/128/256 is supported on DCN.\n", pitch); + hw_pitch = CURSOR_PITCH_64_PIXELS; + break; + } + return hw_pitch; +} + +static enum cursor_lines_per_chunk ippn10_get_lines_per_chunk( + unsigned int cur_width, + enum dc_cursor_color_format format) +{ + enum cursor_lines_per_chunk line_per_chunk; + + if (format == CURSOR_MODE_MONO) + /* impl B. expansion in CUR Buffer reader */ + line_per_chunk = CURSOR_LINE_PER_CHUNK_16; + else if (cur_width <= 32) + line_per_chunk = CURSOR_LINE_PER_CHUNK_16; + else if (cur_width <= 64) + line_per_chunk = CURSOR_LINE_PER_CHUNK_8; + else if (cur_width <= 128) + line_per_chunk = CURSOR_LINE_PER_CHUNK_4; + else + line_per_chunk = CURSOR_LINE_PER_CHUNK_2; + + return line_per_chunk; +} + +void hubp1_cursor_set_attributes( + struct hubp *hubp, + const struct dc_cursor_attributes *attr) +{ + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); + enum cursor_pitch hw_pitch = ippn10_get_cursor_pitch(attr->pitch); + enum cursor_lines_per_chunk lpc = ippn10_get_lines_per_chunk( + attr->width, attr->color_format); + + hubp->curs_attr = *attr; + + REG_UPDATE(CURSOR_SURFACE_ADDRESS_HIGH, + CURSOR_SURFACE_ADDRESS_HIGH, attr->address.high_part); + REG_UPDATE(CURSOR_SURFACE_ADDRESS, + CURSOR_SURFACE_ADDRESS, attr->address.low_part); + + REG_UPDATE_2(CURSOR_SIZE, + CURSOR_WIDTH, attr->width, + CURSOR_HEIGHT, attr->height); + REG_UPDATE_3(CURSOR_CONTROL, + CURSOR_MODE, attr->color_format, + CURSOR_PITCH, hw_pitch, + CURSOR_LINES_PER_CHUNK, lpc); + ippn10_cursor_program_control(hubp1, + attr->attribute_flags.bits.INVERT_PIXEL_DATA, + attr->color_format); +} + +void hubp1_cursor_set_position( + struct hubp *hubp, + const struct dc_cursor_position *pos, + const struct dc_cursor_mi_param *param) +{ + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); + int src_x_offset = pos->x - pos->x_hotspot - param->viewport_x_start; + uint32_t cur_en = pos->enable ? 1 : 0; + uint32_t dst_x_offset = (src_x_offset >= 0) ? src_x_offset : 0; + + /* + * Guard aganst cursor_set_position() from being called with invalid + * attributes + * + * TODO: Look at combining cursor_set_position() and + * cursor_set_attributes() into cursor_update() + */ + if (hubp->curs_attr.address.quad_part == 0) + return; + + dst_x_offset *= param->ref_clk_khz; + dst_x_offset /= param->pixel_clk_khz; + + ASSERT(param->h_scale_ratio.value); + + if (param->h_scale_ratio.value) + dst_x_offset = dal_fixed31_32_floor(dal_fixed31_32_div( + dal_fixed31_32_from_int(dst_x_offset), + param->h_scale_ratio)); + + if (src_x_offset >= (int)param->viewport_width) + cur_en = 0; /* not visible beyond right edge*/ + + if (src_x_offset + (int)hubp->curs_attr.width < 0) + cur_en = 0; /* not visible beyond left edge*/ + + if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0) + hubp1_cursor_set_attributes(hubp, &hubp->curs_attr); + REG_UPDATE(CURSOR_CONTROL, + CURSOR_ENABLE, cur_en); + + REG_SET_2(CURSOR_POSITION, 0, + CURSOR_X_POSITION, pos->x, + CURSOR_Y_POSITION, pos->y); + + REG_SET_2(CURSOR_HOT_SPOT, 0, + CURSOR_HOT_SPOT_X, pos->x_hotspot, + CURSOR_HOT_SPOT_Y, pos->y_hotspot); + + REG_SET(CURSOR_DST_OFFSET, 0, + CURSOR_DST_X_OFFSET, dst_x_offset); + /* TODO Handle surface pixel formats other than 4:4:4 */ +} + +static struct hubp_funcs dcn10_hubp_funcs = { + .hubp_program_surface_flip_and_addr = + hubp1_program_surface_flip_and_addr, + .hubp_program_surface_config = + hubp1_program_surface_config, + .hubp_is_flip_pending = hubp1_is_flip_pending, + .hubp_setup = hubp1_setup, + .hubp_set_vm_system_aperture_settings = hubp1_set_vm_system_aperture_settings, + .hubp_set_vm_context0_settings = hubp1_set_vm_context0_settings, + .set_blank = hubp1_set_blank, + .dcc_control = hubp1_dcc_control, .mem_program_viewport = min_set_viewport, - .set_hubp_blank_en = min10_set_hubp_blank_en, + .set_hubp_blank_en = hubp1_set_hubp_blank_en, + .set_cursor_attributes = hubp1_cursor_set_attributes, + .set_cursor_position = hubp1_cursor_set_position, }; /*****************************************/ /* Constructor, Destructor */ /*****************************************/ -void dcn10_mem_input_construct( - struct dcn10_mem_input *mi, +void dcn10_hubp_construct( + struct dcn10_hubp *hubp1, struct dc_context *ctx, uint32_t inst, const struct dcn_mi_registers *mi_regs, const struct dcn_mi_shift *mi_shift, const struct dcn_mi_mask *mi_mask) { - mi->base.funcs = &dcn10_mem_input_funcs; - mi->base.ctx = ctx; - mi->mi_regs = mi_regs; - mi->mi_shift = mi_shift; - mi->mi_mask = mi_mask; - mi->base.inst = inst; - mi->base.opp_id = 0xf; - mi->base.mpcc_id = 0xf; + hubp1->base.funcs = &dcn10_hubp_funcs; + hubp1->base.ctx = ctx; + hubp1->mi_regs = mi_regs; + hubp1->mi_shift = mi_shift; + hubp1->mi_mask = mi_mask; + hubp1->base.inst = inst; + hubp1->base.opp_id = 0xf; + hubp1->base.mpcc_id = 0xf; } + diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h index aefd3e7bd7eb..66db453c801b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h @@ -25,11 +25,10 @@ #ifndef __DC_MEM_INPUT_DCN10_H__ #define __DC_MEM_INPUT_DCN10_H__ -#include "mem_input.h" - -#define TO_DCN10_MEM_INPUT(mi)\ - container_of(mi, struct dcn10_mem_input, base) +#include "hubp.h" +#define TO_DCN10_HUBP(hubp)\ + container_of(hubp, struct dcn10_hubp, base) #define MI_REG_LIST_DCN(id)\ SRI(DCHUBP_CNTL, HUBP, id),\ @@ -118,7 +117,17 @@ SRI(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, HUBPREQ, id),\ SRI(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, HUBPREQ, id),\ SR(DCHUBBUB_SDPIF_FB_BASE),\ - SR(DCHUBBUB_SDPIF_FB_OFFSET) + SR(DCHUBBUB_SDPIF_FB_OFFSET),\ + SRI(CURSOR_SETTINS, HUBPREQ, id), \ + SRI(CURSOR_SURFACE_ADDRESS_HIGH, CURSOR, id), \ + SRI(CURSOR_SURFACE_ADDRESS, CURSOR, id), \ + SRI(CURSOR_SIZE, CURSOR, id), \ + SRI(CURSOR_CONTROL, CURSOR, id), \ + SRI(CURSOR_POSITION, CURSOR, id), \ + SRI(CURSOR_HOT_SPOT, CURSOR, id), \ + SRI(CURSOR_DST_OFFSET, CURSOR, id) + + struct dcn_mi_registers { uint32_t DCHUBP_CNTL; @@ -215,6 +224,15 @@ struct dcn_mi_registers { uint32_t DCN_VM_AGP_BASE; uint32_t DCN_VM_AGP_BOT; uint32_t DCN_VM_AGP_TOP; + uint32_t CURSOR_SETTINS; + uint32_t CURSOR_SETTINGS; + uint32_t CURSOR_SURFACE_ADDRESS_HIGH; + uint32_t CURSOR_SURFACE_ADDRESS; + uint32_t CURSOR_SIZE; + uint32_t CURSOR_CONTROL; + uint32_t CURSOR_POSITION; + uint32_t CURSOR_HOT_SPOT; + uint32_t CURSOR_DST_OFFSET; }; #define MI_SF(reg_name, field_name, post_fix)\ @@ -351,6 +369,7 @@ struct dcn_mi_registers { MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_SYSTEM, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, MC_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, MC_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, mask_sh),\ @@ -360,7 +379,23 @@ struct dcn_mi_registers { MI_SF(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mask_sh) + MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mask_sh),\ + MI_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_DST_Y_OFFSET, mask_sh), \ + MI_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_CHUNK_HDL_ADJUST, mask_sh), \ + MI_SF(CURSOR0_CURSOR_SURFACE_ADDRESS_HIGH, CURSOR_SURFACE_ADDRESS_HIGH, mask_sh), \ + MI_SF(CURSOR0_CURSOR_SURFACE_ADDRESS, CURSOR_SURFACE_ADDRESS, mask_sh), \ + MI_SF(CURSOR0_CURSOR_SIZE, CURSOR_WIDTH, mask_sh), \ + MI_SF(CURSOR0_CURSOR_SIZE, CURSOR_HEIGHT, mask_sh), \ + MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_MODE, mask_sh), \ + MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_2X_MAGNIFY, mask_sh), \ + MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_PITCH, mask_sh), \ + MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_LINES_PER_CHUNK, mask_sh), \ + MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_ENABLE, mask_sh), \ + MI_SF(CURSOR0_CURSOR_POSITION, CURSOR_X_POSITION, mask_sh), \ + MI_SF(CURSOR0_CURSOR_POSITION, CURSOR_Y_POSITION, mask_sh), \ + MI_SF(CURSOR0_CURSOR_HOT_SPOT, CURSOR_HOT_SPOT_X, mask_sh), \ + MI_SF(CURSOR0_CURSOR_HOT_SPOT, CURSOR_HOT_SPOT_Y, mask_sh), \ + MI_SF(CURSOR0_CURSOR_DST_OFFSET, CURSOR_DST_X_OFFSET, mask_sh) #define DCN_MI_REG_FIELD_LIST(type) \ type HUBP_BLANK_EN;\ @@ -488,6 +523,7 @@ struct dcn_mi_registers { type VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB;\ type VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB;\ type VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB;\ + type VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_SYSTEM;\ type VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB;\ type ENABLE_L1_TLB;\ type SYSTEM_ACCESS_MODE;\ @@ -521,7 +557,24 @@ struct dcn_mi_registers { type PHYSICAL_PAGE_ADDR_LO32;\ type PHYSICAL_PAGE_NUMBER_MSB;\ type PHYSICAL_PAGE_NUMBER_LSB;\ - type LOGICAL_ADDR + type LOGICAL_ADDR;\ + type CURSOR0_DST_Y_OFFSET; \ + type CURSOR0_CHUNK_HDL_ADJUST; \ + type CURSOR_SURFACE_ADDRESS_HIGH; \ + type CURSOR_SURFACE_ADDRESS; \ + type CURSOR_WIDTH; \ + type CURSOR_HEIGHT; \ + type CURSOR_MODE; \ + type CURSOR_2X_MAGNIFY; \ + type CURSOR_PITCH; \ + type CURSOR_LINES_PER_CHUNK; \ + type CURSOR_ENABLE; \ + type CURSOR_X_POSITION; \ + type CURSOR_Y_POSITION; \ + type CURSOR_HOT_SPOT_X; \ + type CURSOR_HOT_SPOT_Y; \ + type CURSOR_DST_X_OFFSET; \ + type OUTPUT_FP struct dcn_mi_shift { DCN_MI_REG_FIELD_LIST(uint8_t); @@ -531,21 +584,83 @@ struct dcn_mi_mask { DCN_MI_REG_FIELD_LIST(uint32_t); }; -struct dcn10_mem_input { - struct mem_input base; +struct dcn10_hubp { + struct hubp base; const struct dcn_mi_registers *mi_regs; const struct dcn_mi_shift *mi_shift; const struct dcn_mi_mask *mi_mask; }; -void dcn10_mem_input_construct( - struct dcn10_mem_input *mi, +void hubp1_program_surface_config( + struct hubp *hubp, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + union plane_size *plane_size, + enum dc_rotation_angle rotation, + struct dc_plane_dcc_param *dcc, + bool horizontal_mirror); + +void hubp1_program_deadline( + struct hubp *hubp, + struct _vcs_dpi_display_dlg_regs_st *dlg_attr, + struct _vcs_dpi_display_ttu_regs_st *ttu_attr); + +void hubp1_program_requestor( + struct hubp *hubp, + struct _vcs_dpi_display_rq_regs_st *rq_regs); + +void hubp1_program_pixel_format( + struct dcn10_hubp *hubp, + enum surface_pixel_format format); + +void hubp1_program_size_and_rotation( + struct dcn10_hubp *hubp, + enum dc_rotation_angle rotation, + enum surface_pixel_format format, + const union plane_size *plane_size, + struct dc_plane_dcc_param *dcc, + bool horizontal_mirror); + +void hubp1_program_tiling( + struct dcn10_hubp *hubp, + const union dc_tiling_info *info, + const enum surface_pixel_format pixel_format); + +void hubp1_dcc_control(struct hubp *hubp, + bool enable, + bool independent_64b_blks); + +bool hubp1_program_surface_flip_and_addr( + struct hubp *hubp, + const struct dc_plane_address *address, + bool flip_immediate); + +bool hubp1_is_flip_pending(struct hubp *hubp); + +void hubp1_cursor_set_attributes( + struct hubp *hubp, + const struct dc_cursor_attributes *attr); + +void hubp1_cursor_set_position( + struct hubp *hubp, + const struct dc_cursor_position *pos, + const struct dc_cursor_mi_param *param); + +void hubp1_set_blank(struct hubp *hubp, bool blank); + +void min_set_viewport(struct hubp *hubp, + const struct rect *viewport, + const struct rect *viewport_c); + +void dcn10_hubp_construct( + struct dcn10_hubp *hubp1, struct dc_context *ctx, uint32_t inst, const struct dcn_mi_registers *mi_regs, const struct dcn_mi_shift *mi_shift, const struct dcn_mi_mask *mi_mask); + struct dcn_hubp_state { uint32_t pixel_format; uint32_t inuse_addr_hi; @@ -562,7 +677,7 @@ struct dcn_hubp_state { uint32_t qos_level_low_wm; uint32_t qos_level_high_wm; }; -void dcn10_mem_input_read_state(struct dcn10_mem_input *mi, +void hubp1_read_state(struct dcn10_hubp *hubp1, struct dcn_hubp_state *s); #endif 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 d3fee15aeb79..63c2f5266142 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 @@ -31,7 +31,6 @@ #include "dce110/dce110_hw_sequencer.h" #include "dce/dce_hwseq.h" #include "abm.h" -#include "dcn10/dcn10_mem_input.h" #include "dcn10/dcn10_timing_generator.h" #include "dcn10/dcn10_dpp.h" #include "dcn10/dcn10_mpc.h" @@ -41,6 +40,7 @@ #include "mpc.h" #include "reg_helper.h" #include "custom_float.h" +#include "dcn10_hubp.h" #define CTX \ hws->ctx @@ -172,10 +172,10 @@ static void dcn10_log_hw_state(struct dc *dc) "min_ttu_vblank \t qos_low_wm \t qos_high_wm \n"); for (i = 0; i < pool->pipe_count; i++) { - struct mem_input *mi = pool->mis[i]; + struct hubp *hubp = pool->hubps[i]; struct dcn_hubp_state s; - dcn10_mem_input_read_state(TO_DCN10_MEM_INPUT(mi), &s); + hubp1_read_state(TO_DCN10_HUBP(hubp), &s); DTN_INFO("[%d]:\t %xh \t %xh \t %d \t %d \t " "%xh \t %xh \t %xh \t " @@ -245,15 +245,19 @@ static void verify_allow_pstate_change_high( { /* pstate latency is ~20us so if we wait over 40us and pstate allow * still not asserted, we are probably stuck and going to hang + * + * TODO: Figure out why it takes ~100us on linux + * pstate takes around ~100us on linux. Unknown currently as to + * why it takes that long on linux */ - static unsigned int pstate_wait_timeout_us = 40; + static unsigned int pstate_wait_timeout_us = 200; + static unsigned int pstate_wait_expected_timeout_us = 40; static unsigned int max_sampled_pstate_wait_us; /* data collection */ static bool forced_pstate_allow; /* help with revert wa */ static bool should_log_hw_state; /* prevent hw state log by default */ unsigned int debug_index = 0x7; unsigned int debug_data; - unsigned int force_allow_pstate = 0x30; unsigned int i; if (forced_pstate_allow) { @@ -261,7 +265,9 @@ static void verify_allow_pstate_change_high( * we verify_allow_pstate_change_high. so disable force * here so we can check status */ - REG_WRITE(DCHUBBUB_ARB_DRAM_STATE_CNTL, 0); + REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL, + DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, 0, + DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, 0); forced_pstate_allow = false; } @@ -292,9 +298,15 @@ static void verify_allow_pstate_change_high( for (i = 0; i < pstate_wait_timeout_us; i++) { debug_data = REG_READ(DCHUBBUB_TEST_DEBUG_DATA); - if (debug_data & (1 << 30)) - return; + if (debug_data & (1 << 30)) { + + if (i > pstate_wait_expected_timeout_us) + dm_logger_write(hws->ctx->logger, LOG_WARNING, + "pstate took longer than expected ~%dus\n", + i); + return; + } if (max_sampled_pstate_wait_us < i) max_sampled_pstate_wait_us = i; @@ -304,13 +316,18 @@ static void verify_allow_pstate_change_high( /* force pstate allow to prevent system hang * and break to debugger to investigate */ - REG_WRITE(DCHUBBUB_ARB_DRAM_STATE_CNTL, force_allow_pstate); + REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL, + DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, 1, + DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, 1); forced_pstate_allow = true; if (should_log_hw_state) { dcn10_log_hw_state(hws->ctx->dc); } + dm_logger_write(hws->ctx->logger, LOG_WARNING, + "pstate TEST_DEBUG_DATA: 0x%X\n", + debug_data); BREAK_TO_DEBUGGER(); } @@ -451,7 +468,7 @@ static void program_watermarks( refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "URGENCY_WATERMARK_A calculated =%d\n" "HW register value = 0x%x\n", watermarks->a.urgent_ns, prog_wm_value); @@ -459,38 +476,37 @@ static void program_watermarks( prog_wm_value = convert_and_clamp(watermarks->a.pte_meta_urgent_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "PTE_META_URGENCY_WATERMARK_A calculated =%d\n" "HW register value = 0x%x\n", watermarks->a.pte_meta_urgent_ns, prog_wm_value); + if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A)) { + prog_wm_value = convert_and_clamp( + watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, + "SR_ENTER_EXIT_WATERMARK_A calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - prog_wm_value = convert_and_clamp( - watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, - refclk_mhz, 0x1fffff); - - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, - "SR_ENTER_EXIT_WATERMARK_A calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->a.cstate_pstate.cstate_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, - "SR_EXIT_WATERMARK_A calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value); + prog_wm_value = convert_and_clamp( + watermarks->a.cstate_pstate.cstate_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, + "SR_EXIT_WATERMARK_A calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value); + } prog_wm_value = convert_and_clamp( watermarks->a.cstate_pstate.pstate_change_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n" "HW register value = 0x%x\n\n", watermarks->a.cstate_pstate.pstate_change_ns, prog_wm_value); @@ -500,7 +516,7 @@ static void program_watermarks( prog_wm_value = convert_and_clamp( watermarks->b.urgent_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "URGENCY_WATERMARK_B calculated =%d\n" "HW register value = 0x%x\n", watermarks->b.urgent_ns, prog_wm_value); @@ -510,36 +526,38 @@ static void program_watermarks( watermarks->b.pte_meta_urgent_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "PTE_META_URGENCY_WATERMARK_B calculated =%d\n" "HW register value = 0x%x\n", watermarks->b.pte_meta_urgent_ns, prog_wm_value); - prog_wm_value = convert_and_clamp( - watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, - "SR_ENTER_WATERMARK_B calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); + if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B)) { + prog_wm_value = convert_and_clamp( + watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, + "SR_ENTER_WATERMARK_B calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - prog_wm_value = convert_and_clamp( - watermarks->b.cstate_pstate.cstate_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, - "SR_EXIT_WATERMARK_B calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value); + prog_wm_value = convert_and_clamp( + watermarks->b.cstate_pstate.cstate_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, + "SR_EXIT_WATERMARK_B calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value); + } prog_wm_value = convert_and_clamp( watermarks->b.cstate_pstate.pstate_change_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n\n" "HW register value = 0x%x\n", watermarks->b.cstate_pstate.pstate_change_ns, prog_wm_value); @@ -548,7 +566,7 @@ static void program_watermarks( prog_wm_value = convert_and_clamp( watermarks->c.urgent_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "URGENCY_WATERMARK_C calculated =%d\n" "HW register value = 0x%x\n", watermarks->c.urgent_ns, prog_wm_value); @@ -558,37 +576,38 @@ static void program_watermarks( watermarks->c.pte_meta_urgent_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "PTE_META_URGENCY_WATERMARK_C calculated =%d\n" "HW register value = 0x%x\n", watermarks->c.pte_meta_urgent_ns, prog_wm_value); - prog_wm_value = convert_and_clamp( - watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, - "SR_ENTER_WATERMARK_C calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); + if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C)) { + prog_wm_value = convert_and_clamp( + watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, + "SR_ENTER_WATERMARK_C calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - prog_wm_value = convert_and_clamp( - watermarks->c.cstate_pstate.cstate_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, - "SR_EXIT_WATERMARK_C calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value); - + prog_wm_value = convert_and_clamp( + watermarks->c.cstate_pstate.cstate_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, + "SR_EXIT_WATERMARK_C calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value); + } prog_wm_value = convert_and_clamp( watermarks->c.cstate_pstate.pstate_change_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n\n" "HW register value = 0x%x\n", watermarks->c.cstate_pstate.pstate_change_ns, prog_wm_value); @@ -597,7 +616,7 @@ static void program_watermarks( prog_wm_value = convert_and_clamp( watermarks->d.urgent_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "URGENCY_WATERMARK_D calculated =%d\n" "HW register value = 0x%x\n", watermarks->d.urgent_ns, prog_wm_value); @@ -606,37 +625,39 @@ static void program_watermarks( watermarks->d.pte_meta_urgent_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "PTE_META_URGENCY_WATERMARK_D calculated =%d\n" "HW register value = 0x%x\n", watermarks->d.pte_meta_urgent_ns, prog_wm_value); - prog_wm_value = convert_and_clamp( - watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, - "SR_ENTER_WATERMARK_D calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); + if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D)) { + prog_wm_value = convert_and_clamp( + watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, + "SR_ENTER_WATERMARK_D calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - prog_wm_value = convert_and_clamp( - watermarks->d.cstate_pstate.cstate_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, - "SR_EXIT_WATERMARK_D calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value); + prog_wm_value = convert_and_clamp( + watermarks->d.cstate_pstate.cstate_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, + "SR_EXIT_WATERMARK_D calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value); + } prog_wm_value = convert_and_clamp( watermarks->d.cstate_pstate.pstate_change_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n" "HW register value = 0x%x\n\n", watermarks->d.cstate_pstate.pstate_change_ns, prog_wm_value); @@ -771,20 +792,22 @@ static void power_on_plane( struct dce_hwseq *hws, int plane_id) { - REG_SET(DC_IP_REQUEST_CNTL, 0, - IP_REQUEST_EN, 1); - dpp_pg_control(hws, plane_id, true); - hubp_pg_control(hws, plane_id, true); - REG_SET(DC_IP_REQUEST_CNTL, 0, - IP_REQUEST_EN, 0); - dm_logger_write(hws->ctx->logger, LOG_DEBUG, - "Un-gated front end for pipe %d\n", plane_id); + if (REG(DC_IP_REQUEST_CNTL)) { + REG_SET(DC_IP_REQUEST_CNTL, 0, + IP_REQUEST_EN, 1); + dpp_pg_control(hws, plane_id, true); + hubp_pg_control(hws, plane_id, true); + REG_SET(DC_IP_REQUEST_CNTL, 0, + IP_REQUEST_EN, 0); + dm_logger_write(hws->ctx->logger, LOG_DEBUG, + "Un-gated front end for pipe %d\n", plane_id); + } } static void undo_DEGVIDCN10_253_wa(struct dc *dc) { struct dce_hwseq *hws = dc->hwseq; - struct mem_input *mi = dc->res_pool->mis[0]; + struct hubp *hubp = dc->res_pool->hubps[0]; int pwr_status = 0; REG_GET(DOMAIN0_PG_STATUS, DOMAIN0_PGFSM_PWR_STATUS, &pwr_status); @@ -792,7 +815,7 @@ static void undo_DEGVIDCN10_253_wa(struct dc *dc) if (pwr_status == 2) return; - mi->funcs->set_blank(mi, true); + hubp->funcs->set_blank(hubp, true); REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); @@ -802,17 +825,13 @@ static void undo_DEGVIDCN10_253_wa(struct dc *dc) IP_REQUEST_EN, 0); } -static void ready_shared_resources(struct dc *dc) -{ - if (dc->current_state->stream_count == 0 && - !dc->debug.disable_stutter) - undo_DEGVIDCN10_253_wa(dc); -} - static void apply_DEGVIDCN10_253_wa(struct dc *dc) { struct dce_hwseq *hws = dc->hwseq; - struct mem_input *mi = dc->res_pool->mis[0]; + struct hubp *hubp = dc->res_pool->hubps[0]; + + if (dc->debug.disable_stutter) + return; REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); @@ -821,14 +840,7 @@ static void apply_DEGVIDCN10_253_wa(struct dc *dc) REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); - mi->funcs->set_hubp_blank_en(mi, false); -} - -static void optimize_shared_resources(struct dc *dc) -{ - if (dc->current_state->stream_count == 0 && - !dc->debug.disable_stutter) - apply_DEGVIDCN10_253_wa(dc); + hubp->funcs->set_hubp_blank_en(hubp, false); } static void bios_golden_init(struct dc *dc) @@ -887,12 +899,13 @@ static void dcn10_init_hw(struct dc *dc) } for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct transform *xfm = dc->res_pool->transforms[i]; + struct dpp *dpp = dc->res_pool->dpps[i]; struct timing_generator *tg = dc->res_pool->timing_generators[i]; - xfm->funcs->transform_reset(xfm); + dpp->funcs->dpp_reset(dpp); dc->res_pool->mpc->funcs->remove( - dc->res_pool->mpc, dc->res_pool->opps[i], i); + dc->res_pool->mpc, &(dc->res_pool->opps[i]->mpc_tree), + dc->res_pool->opps[i]->inst, i); /* Blank controller using driver code instead of * command table. @@ -1028,12 +1041,11 @@ static void reset_back_end_for_pipe( return; } - /* TODOFPGA break core_link_disable_stream into 2 functions: - * disable_stream and disable_link. disable_link will disable PHYPLL - * which is used by otg. Move disable_link after disable_crtc - */ - if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) - core_link_disable_stream(pipe_ctx); + if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { + /* DPMS may already disable */ + if (!pipe_ctx->stream->dpms_off) + core_link_disable_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE); + } /* by upper caller loop, parent pipe: pipe0, will be reset last. * back end share by all pipes and will be disable only when disable @@ -1062,7 +1074,7 @@ static void reset_back_end_for_pipe( static void plane_atomic_disconnect(struct dc *dc, int fe_idx) { - struct mem_input *mi = dc->res_pool->mis[fe_idx]; + struct hubp *hubp = dc->res_pool->hubps[fe_idx]; struct mpc *mpc = dc->res_pool->mpc; int opp_id, z_idx; int mpcc_id = -1; @@ -1086,11 +1098,12 @@ static void plane_atomic_disconnect(struct dc *dc, if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); - mi->funcs->dcc_control(mi, false, false); + hubp->funcs->dcc_control(hubp, false, false); if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); - mpc->funcs->remove(mpc, dc->res_pool->opps[opp_id], fe_idx); + mpc->funcs->remove(mpc, &(dc->res_pool->opps[opp_id]->mpc_tree), + dc->res_pool->opps[opp_id]->inst, fe_idx); } /* disable HW used by plane. @@ -1099,20 +1112,20 @@ static void plane_atomic_disable(struct dc *dc, int fe_idx) { struct dce_hwseq *hws = dc->hwseq; - struct mem_input *mi = dc->res_pool->mis[fe_idx]; + struct hubp *hubp = dc->res_pool->hubps[fe_idx]; struct mpc *mpc = dc->res_pool->mpc; - int opp_id = mi->opp_id; + int opp_id = hubp->opp_id; if (opp_id == 0xf) return; - mpc->funcs->wait_for_idle(mpc, mi->mpcc_id); - dc->res_pool->opps[mi->opp_id]->mpcc_disconnect_pending[mi->mpcc_id] = false; + mpc->funcs->wait_for_idle(mpc, hubp->mpcc_id); + dc->res_pool->opps[hubp->opp_id]->mpcc_disconnect_pending[hubp->mpcc_id] = false; /*dm_logger_write(dc->ctx->logger, LOG_ERROR, "[debug_mpo: atomic disable finished on mpcc %d]\n", fe_idx);*/ - mi->funcs->set_blank(mi, true); + hubp->funcs->set_blank(hubp, true); if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); @@ -1137,20 +1150,22 @@ static void plane_atomic_disable(struct dc *dc, static void plane_atomic_power_down(struct dc *dc, int fe_idx) { struct dce_hwseq *hws = dc->hwseq; - struct transform *xfm = dc->res_pool->transforms[fe_idx]; - - REG_SET(DC_IP_REQUEST_CNTL, 0, - IP_REQUEST_EN, 1); - dpp_pg_control(hws, fe_idx, false); - hubp_pg_control(hws, fe_idx, false); - xfm->funcs->transform_reset(xfm); - REG_SET(DC_IP_REQUEST_CNTL, 0, - IP_REQUEST_EN, 0); - dm_logger_write(dc->ctx->logger, LOG_DEBUG, - "Power gated front end %d\n", fe_idx); - - if (dc->debug.sanity_checks) - verify_allow_pstate_change_high(dc->hwseq); + struct dpp *dpp = dc->res_pool->dpps[fe_idx]; + + if (REG(DC_IP_REQUEST_CNTL)) { + REG_SET(DC_IP_REQUEST_CNTL, 0, + IP_REQUEST_EN, 1); + dpp_pg_control(hws, fe_idx, false); + hubp_pg_control(hws, fe_idx, false); + dpp->funcs->dpp_reset(dpp); + REG_SET(DC_IP_REQUEST_CNTL, 0, + IP_REQUEST_EN, 0); + dm_logger_write(dc->ctx->logger, LOG_DEBUG, + "Power gated front end %d\n", fe_idx); + + if (dc->debug.sanity_checks) + verify_allow_pstate_change_high(dc->hwseq); + } } @@ -1160,7 +1175,7 @@ static void reset_front_end( { struct dce_hwseq *hws = dc->hwseq; struct timing_generator *tg; - int opp_id = dc->res_pool->mis[fe_idx]->opp_id; + int opp_id = dc->res_pool->hubps[fe_idx]->opp_id; /*Already reset*/ if (opp_id == 0xf) @@ -1192,7 +1207,7 @@ static void reset_front_end( static void dcn10_power_down_fe(struct dc *dc, int fe_idx) { struct dce_hwseq *hws = dc->hwseq; - struct transform *xfm = dc->res_pool->transforms[fe_idx]; + struct dpp *dpp = dc->res_pool->dpps[fe_idx]; reset_front_end(dc, fe_idx); @@ -1200,7 +1215,7 @@ static void dcn10_power_down_fe(struct dc *dc, int fe_idx) IP_REQUEST_EN, 1); dpp_pg_control(hws, fe_idx, false); hubp_pg_control(hws, fe_idx, false); - xfm->funcs->transform_reset(xfm); + dpp->funcs->dpp_reset(dpp); REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); dm_logger_write(dc->ctx->logger, LOG_DEBUG, @@ -1275,6 +1290,9 @@ static void reset_hw_ctx_wrap( if (!pipe_ctx_old->stream) continue; + if (pipe_ctx_old->top_pipe) + continue; + if (!pipe_ctx->stream || pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) { struct clock_source *old_clk = pipe_ctx_old->clock_source; @@ -1339,8 +1357,8 @@ static void dcn10_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_c if (plane_state == NULL) return; addr_patched = patch_address_for_sbs_tb_stereo(pipe_ctx, &addr); - pipe_ctx->plane_res.mi->funcs->mem_input_program_surface_flip_and_addr( - pipe_ctx->plane_res.mi, + pipe_ctx->plane_res.hubp->funcs->hubp_program_surface_flip_and_addr( + pipe_ctx->plane_res.hubp, &plane_state->address, plane_state->flip_immediate); plane_state->status.requested_address = plane_state->address; @@ -1351,34 +1369,34 @@ static void dcn10_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_c static bool dcn10_set_input_transfer_func( struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state) { - struct transform *xfm_base = pipe_ctx->plane_res.xfm; + struct dpp *dpp_base = pipe_ctx->plane_res.dpp; const struct dc_transfer_func *tf = NULL; bool result = true; - if (xfm_base == NULL) + if (dpp_base == NULL) return false; if (plane_state->in_transfer_func) tf = plane_state->in_transfer_func; if (plane_state->gamma_correction && dce_use_lut(plane_state)) - xfm_base->funcs->ipp_program_input_lut(xfm_base, + dpp_base->funcs->ipp_program_input_lut(dpp_base, plane_state->gamma_correction); if (tf == NULL) - xfm_base->funcs->ipp_set_degamma(xfm_base, IPP_DEGAMMA_MODE_BYPASS); + dpp_base->funcs->ipp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS); else if (tf->type == TF_TYPE_PREDEFINED) { switch (tf->tf) { case TRANSFER_FUNCTION_SRGB: - xfm_base->funcs->ipp_set_degamma(xfm_base, + dpp_base->funcs->ipp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_HW_sRGB); break; case TRANSFER_FUNCTION_BT709: - xfm_base->funcs->ipp_set_degamma(xfm_base, + dpp_base->funcs->ipp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_HW_xvYCC); break; case TRANSFER_FUNCTION_LINEAR: - xfm_base->funcs->ipp_set_degamma(xfm_base, + dpp_base->funcs->ipp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS); break; case TRANSFER_FUNCTION_PQ: @@ -1389,7 +1407,7 @@ static bool dcn10_set_input_transfer_func( break; } } else if (tf->type == TF_TYPE_BYPASS) { - xfm_base->funcs->ipp_set_degamma(xfm_base, IPP_DEGAMMA_MODE_BYPASS); + dpp_base->funcs->ipp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS); } else { /*TF_TYPE_DISTRIBUTED_POINTS*/ result = false; @@ -1716,25 +1734,25 @@ static bool dcn10_set_output_transfer_func( struct pipe_ctx *pipe_ctx, const struct dc_stream_state *stream) { - struct transform *xfm = pipe_ctx->plane_res.xfm; + struct dpp *dpp = pipe_ctx->plane_res.dpp; - if (xfm == NULL) + if (dpp == NULL) return false; - xfm->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; + dpp->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; if (stream->out_transfer_func && stream->out_transfer_func->type == TF_TYPE_PREDEFINED && stream->out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) { - xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_SRGB); + dpp->funcs->opp_set_regamma_mode(dpp, OPP_REGAMMA_SRGB); } else if (dcn10_translate_regamma_to_hw_format( - stream->out_transfer_func, &xfm->regamma_params)) { - xfm->funcs->opp_program_regamma_pwl(xfm, &xfm->regamma_params); - xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_USER); + stream->out_transfer_func, &dpp->regamma_params)) { + dpp->funcs->opp_program_regamma_pwl(dpp, &dpp->regamma_params); + dpp->funcs->opp_set_regamma_mode(dpp, OPP_REGAMMA_USER); } else { - xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_BYPASS); + dpp->funcs->opp_set_regamma_mode(dpp, OPP_REGAMMA_BYPASS); } return true; @@ -1745,8 +1763,8 @@ static void dcn10_pipe_control_lock( struct pipe_ctx *pipe, bool lock) { - struct mem_input *mi = NULL; - mi = dc->res_pool->mis[pipe->pipe_idx]; + struct hubp *hubp = NULL; + hubp = dc->res_pool->hubps[pipe->pipe_idx]; /* use TG master update lock to lock everything on the TG * therefore only top pipe need to lock */ @@ -1997,10 +2015,11 @@ static void dcn10_power_on_fe( plane_state->dst_rect.height); dm_logger_write(dc->ctx->logger, LOG_DC, - "Pipe %d: width, height, x, y\n" + "Pipe %d: width, height, x, y format:%d\n" "viewport:%d, %d, %d, %d\n" "recout: %d, %d, %d, %d\n", pipe_ctx->pipe_idx, + plane_state->format, pipe_ctx->plane_res.scl_data.viewport.width, pipe_ctx->plane_res.scl_data.viewport.height, pipe_ctx->plane_res.scl_data.viewport.x, @@ -2019,7 +2038,7 @@ static void dcn10_power_on_fe( static void program_gamut_remap(struct pipe_ctx *pipe_ctx) { - struct xfm_grph_csc_adjustment adjust; + struct dpp_grph_csc_adjustment adjust; memset(&adjust, 0, sizeof(adjust)); adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; @@ -2055,7 +2074,7 @@ static void program_gamut_remap(struct pipe_ctx *pipe_ctx) gamut_remap_matrix.matrix[10]; } - pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust); + pipe_ctx->plane_res.dpp->funcs->dpp_set_gamut_remap(pipe_ctx->plane_res.dpp, &adjust); } @@ -2077,7 +2096,7 @@ static void program_csc_matrix(struct pipe_ctx *pipe_ctx, tbl_entry.color_space = color_space; //tbl_entry.regval = matrix; - pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment(pipe_ctx->plane_res.xfm, &tbl_entry); + pipe_ctx->plane_res.dpp->funcs->opp_set_csc_adjustment(pipe_ctx->plane_res.dpp, &tbl_entry); } } static bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx) @@ -2167,7 +2186,7 @@ static void dcn10_get_surface_visual_confirm_color( } } -static void mmhub_read_vm_system_aperture_settings(struct dcn10_mem_input *mi, +static void mmhub_read_vm_system_aperture_settings(struct dcn10_hubp *hubp1, struct vm_system_aperture_param *apt, struct dce_hwseq *hws) { @@ -2192,7 +2211,7 @@ static void mmhub_read_vm_system_aperture_settings(struct dcn10_mem_input *mi, } /* Temporary read settings, future will get values from kmd directly */ -static void mmhub_read_vm_context0_settings(struct dcn10_mem_input *mi, +static void mmhub_read_vm_context0_settings(struct dcn10_hubp *hubp1, struct vm_context0_param *vm0, struct dce_hwseq *hws) { @@ -2236,22 +2255,22 @@ static void mmhub_read_vm_context0_settings(struct dcn10_mem_input *mi, vm0->pte_base.quad_part -= fb_offset.quad_part; } -static void dcn10_program_pte_vm(struct mem_input *mem_input, +static void dcn10_program_pte_vm(struct hubp *hubp, enum surface_pixel_format format, union dc_tiling_info *tiling_info, enum dc_rotation_angle rotation, struct dce_hwseq *hws) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); struct vm_system_aperture_param apt = { {{ 0 } } }; struct vm_context0_param vm0 = { { { 0 } } }; - mmhub_read_vm_system_aperture_settings(mi, &apt, hws); - mmhub_read_vm_context0_settings(mi, &vm0, hws); + mmhub_read_vm_system_aperture_settings(hubp1, &apt, hws); + mmhub_read_vm_context0_settings(hubp1, &vm0, hws); - mem_input->funcs->mem_input_set_vm_system_aperture_settings(mem_input, &apt); - mem_input->funcs->mem_input_set_vm_context0_settings(mem_input, &vm0); + hubp->funcs->hubp_set_vm_system_aperture_settings(hubp, &apt); + hubp->funcs->hubp_set_vm_context0_settings(hubp, &vm0); } static void update_dchubp_dpp( @@ -2260,11 +2279,10 @@ static void update_dchubp_dpp( struct dc_state *context) { struct dce_hwseq *hws = dc->hwseq; - struct mem_input *mi = pipe_ctx->plane_res.mi; - struct transform *xfm = pipe_ctx->plane_res.xfm; + struct hubp *hubp = pipe_ctx->plane_res.hubp; + struct dpp *dpp = pipe_ctx->plane_res.dpp; struct dc_plane_state *plane_state = pipe_ctx->plane_state; union plane_size size = plane_state->plane_size; - struct default_adjustment ocsc = {0}; struct mpcc_cfg mpcc_cfg = {0}; struct pipe_ctx *top_pipe; bool per_pixel_alpha = plane_state->per_pixel_alpha && pipe_ctx->bottom_pipe; @@ -2286,10 +2304,8 @@ static void update_dchubp_dpp( */ REG_UPDATE(DCHUBP_CNTL[pipe_ctx->pipe_idx], HUBP_VTG_SEL, pipe_ctx->stream_res.tg->inst); - dc->hwss.update_plane_addr(dc, pipe_ctx); - - mi->funcs->mem_input_setup( - mi, + hubp->funcs->hubp_setup( + hubp, &pipe_ctx->dlg_regs, &pipe_ctx->ttu_regs, &pipe_ctx->rq_regs, @@ -2299,19 +2315,20 @@ static void update_dchubp_dpp( if (dc->config.gpu_vm_support) dcn10_program_pte_vm( - pipe_ctx->plane_res.mi, + pipe_ctx->plane_res.hubp, plane_state->format, &plane_state->tiling_info, plane_state->rotation, hws ); - xfm->funcs->ipp_setup(xfm, + dpp->funcs->ipp_setup(dpp, plane_state->format, EXPANSION_MODE_ZERO); - mpcc_cfg.mi = mi; - mpcc_cfg.opp = pipe_ctx->stream_res.opp; + mpcc_cfg.dpp_id = hubp->inst; + mpcc_cfg.opp_id = pipe_ctx->stream_res.opp->inst; + mpcc_cfg.tree_cfg = &(pipe_ctx->stream_res.opp->mpc_tree); for (top_pipe = pipe_ctx->top_pipe; top_pipe; top_pipe = top_pipe->top_pipe) mpcc_cfg.z_index++; if (dc->debug.surface_visual_confirm) @@ -2328,25 +2345,27 @@ static void update_dchubp_dpp( mpcc_cfg.pre_multiplied_alpha = is_rgb_cspace( pipe_ctx->stream->output_color_space) && per_pixel_alpha; - dc->res_pool->mpc->funcs->add(dc->res_pool->mpc, &mpcc_cfg); + hubp->mpcc_id = dc->res_pool->mpc->funcs->add(dc->res_pool->mpc, &mpcc_cfg); + hubp->opp_id = mpcc_cfg.opp_id; pipe_ctx->plane_res.scl_data.lb_params.alpha_en = per_pixel_alpha; pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; /* scaler configuration */ - pipe_ctx->plane_res.xfm->funcs->transform_set_scaler( - pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data); - mi->funcs->mem_program_viewport(mi, + pipe_ctx->plane_res.dpp->funcs->dpp_set_scaler( + pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data); + + hubp->funcs->mem_program_viewport(hubp, &pipe_ctx->plane_res.scl_data.viewport, &pipe_ctx->plane_res.scl_data.viewport_c); /*gamut remap*/ program_gamut_remap(pipe_ctx); - /*TODO add adjustments parameters*/ - ocsc.out_color_space = pipe_ctx->stream->output_color_space; - pipe_ctx->plane_res.xfm->funcs->opp_set_csc_default(pipe_ctx->plane_res.xfm, &ocsc); + program_csc_matrix(pipe_ctx, + pipe_ctx->stream->output_color_space, + pipe_ctx->stream->csc_color_matrix.matrix); - mi->funcs->mem_input_program_surface_config( - mi, + hubp->funcs->hubp_program_surface_config( + hubp, plane_state->format, &plane_state->tiling_info, &size, @@ -2354,8 +2373,10 @@ static void update_dchubp_dpp( &plane_state->dcc, plane_state->horizontal_mirror); + dc->hwss.update_plane_addr(dc, pipe_ctx); + if (is_pipe_tree_visible(pipe_ctx)) - mi->funcs->set_blank(mi, false); + hubp->funcs->set_blank(hubp, false); } @@ -2393,6 +2414,10 @@ static void program_all_pipe_in_tree( } if (pipe_ctx->plane_state != NULL) { + struct dc_cursor_position position = { 0 }; + struct pipe_ctx *cur_pipe_ctx = + &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; + dcn10_power_on_fe(dc, pipe_ctx, context); /* temporary dcn1 wa: @@ -2407,6 +2432,19 @@ static void program_all_pipe_in_tree( toggle_watermark_change_req(dc->hwseq); update_dchubp_dpp(dc, pipe_ctx, context); + + /* TODO: this is a hack w/a for switching from mpo to pipe split */ + dc_stream_set_cursor_position(pipe_ctx->stream, &position); + + dc_stream_set_cursor_attributes(pipe_ctx->stream, + &pipe_ctx->stream->cursor_attributes); + + if (cur_pipe_ctx->plane_state != pipe_ctx->plane_state) { + dc->hwss.set_input_transfer_func( + pipe_ctx, pipe_ctx->plane_state); + dc->hwss.set_output_transfer_func( + pipe_ctx, pipe_ctx->stream); + } } if (dc->debug.sanity_checks) { @@ -2445,6 +2483,30 @@ static void dcn10_pplib_apply_display_requirements( dc->prev_display_config = *pp_display_cfg; } +static void optimize_shared_resources(struct dc *dc) +{ + if (dc->current_state->stream_count == 0) { + apply_DEGVIDCN10_253_wa(dc); + /* S0i2 message */ + dcn10_pplib_apply_display_requirements(dc, dc->current_state); + } + + if (dc->debug.pplib_wm_report_mode == WM_REPORT_OVERRIDE) + dcn_bw_notify_pplib_of_wm_ranges(dc); +} + +static void ready_shared_resources(struct dc *dc, struct dc_state *context) +{ + if (dc->current_state->stream_count == 0 && + !dc->debug.disable_stutter) + undo_DEGVIDCN10_253_wa(dc); + + /* S0i2 message */ + if (dc->current_state->stream_count == 0 && + context->stream_count != 0) + dcn10_pplib_apply_display_requirements(dc, context); +} + static void dcn10_apply_ctx_for_surface( struct dc *dc, const struct dc_stream_state *stream, @@ -2494,7 +2556,7 @@ static void dcn10_apply_ctx_for_surface( */ if (pipe_ctx->plane_state && !old_pipe_ctx->plane_state) { - if (pipe_ctx->plane_res.mi->opp_id != 0xf && pipe_ctx->stream_res.tg->inst == be_idx) { + if (pipe_ctx->plane_res.hubp->opp_id != 0xf && pipe_ctx->stream_res.tg->inst == be_idx) { dcn10_power_down_fe(dc, pipe_ctx->pipe_idx); /* * power down fe will unlock when calling reset, need @@ -2518,9 +2580,10 @@ static void dcn10_apply_ctx_for_surface( /* reset mpc */ dc->res_pool->mpc->funcs->remove( dc->res_pool->mpc, - old_pipe_ctx->stream_res.opp, + &(old_pipe_ctx->stream_res.opp->mpc_tree), + old_pipe_ctx->stream_res.opp->inst, old_pipe_ctx->pipe_idx); - old_pipe_ctx->stream_res.opp->mpcc_disconnect_pending[old_pipe_ctx->plane_res.mi->mpcc_id] = true; + old_pipe_ctx->stream_res.opp->mpcc_disconnect_pending[old_pipe_ctx->plane_res.hubp->mpcc_id] = true; /*dm_logger_write(dc->ctx->logger, LOG_ERROR, "[debug_mpo: apply_ctx disconnect pending on mpcc %d]\n", @@ -2532,6 +2595,7 @@ static void dcn10_apply_ctx_for_surface( old_pipe_ctx->top_pipe = NULL; old_pipe_ctx->bottom_pipe = NULL; old_pipe_ctx->plane_state = NULL; + old_pipe_ctx->stream = NULL; dm_logger_write(dc->ctx->logger, LOG_DC, "Reset mpcc for pipe %d\n", @@ -2803,7 +2867,7 @@ static void dcn10_wait_for_mpcc_disconnect( if (pipe_ctx->stream_res.opp->mpcc_disconnect_pending[i]) { res_pool->mpc->funcs->wait_for_idle(res_pool->mpc, i); pipe_ctx->stream_res.opp->mpcc_disconnect_pending[i] = false; - res_pool->mis[i]->funcs->set_blank(res_pool->mis[i], true); + res_pool->hubps[i]->funcs->set_blank(res_pool->hubps[i], true); /*dm_logger_write(dc->ctx->logger, LOG_ERROR, "[debug_mpo: wait_for_mpcc finished waiting on mpcc %d]\n", i);*/ @@ -2834,11 +2898,11 @@ void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) return; plane_state->status.is_flip_pending = - pipe_ctx->plane_res.mi->funcs->mem_input_is_flip_pending( - pipe_ctx->plane_res.mi); + pipe_ctx->plane_res.hubp->funcs->hubp_is_flip_pending( + pipe_ctx->plane_res.hubp); - plane_state->status.current_address = pipe_ctx->plane_res.mi->current_address; - if (pipe_ctx->plane_res.mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && + plane_state->status.current_address = pipe_ctx->plane_res.hubp->current_address; + if (pipe_ctx->plane_res.hubp->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && tg->funcs->is_stereo_left_eye) { plane_state->status.is_right_eye = !tg->funcs->is_stereo_left_eye(pipe_ctx->stream_res.tg); @@ -2882,6 +2946,8 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect, .ready_shared_resources = ready_shared_resources, .optimize_shared_resources = optimize_shared_resources, + .edp_backlight_control = hwss_edp_backlight_control, + .edp_power_control = hwss_edp_power_control }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c index 67bd6a738fe9..08db1e6b5166 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c @@ -37,188 +37,6 @@ #define CTX \ ippn10->base.ctx -static bool ippn10_cursor_program_control( - struct dcn10_ipp *ippn10, - bool pixel_data_invert, - enum dc_cursor_color_format color_format) -{ - if (REG(CURSOR_SETTINS)) - REG_SET_2(CURSOR_SETTINS, 0, - /* no shift of the cursor HDL schedule */ - CURSOR0_DST_Y_OFFSET, 0, - /* used to shift the cursor chunk request deadline */ - CURSOR0_CHUNK_HDL_ADJUST, 3); - else - REG_SET_2(CURSOR_SETTINGS, 0, - /* no shift of the cursor HDL schedule */ - CURSOR0_DST_Y_OFFSET, 0, - /* used to shift the cursor chunk request deadline */ - CURSOR0_CHUNK_HDL_ADJUST, 3); - - REG_UPDATE_2(CURSOR0_CONTROL, - CUR0_MODE, color_format, - CUR0_EXPANSION_MODE, 0); - - if (color_format == CURSOR_MODE_MONO) { - /* todo: clarify what to program these to */ - REG_UPDATE(CURSOR0_COLOR0, - CUR0_COLOR0, 0x00000000); - REG_UPDATE(CURSOR0_COLOR1, - CUR0_COLOR1, 0xFFFFFFFF); - } - - /* TODO: Fixed vs float */ - - REG_UPDATE_3(FORMAT_CONTROL, - CNVC_BYPASS, 0, - ALPHA_EN, 1, - FORMAT_EXPANSION_MODE, 0); - - return true; -} - -enum cursor_pitch { - CURSOR_PITCH_64_PIXELS = 0, - CURSOR_PITCH_128_PIXELS, - CURSOR_PITCH_256_PIXELS -}; - -enum cursor_lines_per_chunk { - CURSOR_LINE_PER_CHUNK_2 = 1, - CURSOR_LINE_PER_CHUNK_4, - CURSOR_LINE_PER_CHUNK_8, - CURSOR_LINE_PER_CHUNK_16 -}; - -static enum cursor_pitch ippn10_get_cursor_pitch( - unsigned int pitch) -{ - enum cursor_pitch hw_pitch; - - switch (pitch) { - case 64: - hw_pitch = CURSOR_PITCH_64_PIXELS; - break; - case 128: - hw_pitch = CURSOR_PITCH_128_PIXELS; - break; - case 256: - hw_pitch = CURSOR_PITCH_256_PIXELS; - break; - default: - DC_ERR("Invalid cursor pitch of %d. " - "Only 64/128/256 is supported on DCN.\n", pitch); - hw_pitch = CURSOR_PITCH_64_PIXELS; - break; - } - return hw_pitch; -} - -static enum cursor_lines_per_chunk ippn10_get_lines_per_chunk( - unsigned int cur_width, - enum dc_cursor_color_format format) -{ - enum cursor_lines_per_chunk line_per_chunk; - - if (format == CURSOR_MODE_MONO) - /* impl B. expansion in CUR Buffer reader */ - line_per_chunk = CURSOR_LINE_PER_CHUNK_16; - else if (cur_width <= 32) - line_per_chunk = CURSOR_LINE_PER_CHUNK_16; - else if (cur_width <= 64) - line_per_chunk = CURSOR_LINE_PER_CHUNK_8; - else if (cur_width <= 128) - line_per_chunk = CURSOR_LINE_PER_CHUNK_4; - else - line_per_chunk = CURSOR_LINE_PER_CHUNK_2; - - return line_per_chunk; -} - -static void ippn10_cursor_set_attributes( - struct input_pixel_processor *ipp, - const struct dc_cursor_attributes *attr) -{ - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - enum cursor_pitch hw_pitch = ippn10_get_cursor_pitch(attr->pitch); - enum cursor_lines_per_chunk lpc = ippn10_get_lines_per_chunk( - attr->width, attr->color_format); - - ippn10->curs_attr = *attr; - - REG_UPDATE(CURSOR_SURFACE_ADDRESS_HIGH, - CURSOR_SURFACE_ADDRESS_HIGH, attr->address.high_part); - REG_UPDATE(CURSOR_SURFACE_ADDRESS, - CURSOR_SURFACE_ADDRESS, attr->address.low_part); - - REG_UPDATE_2(CURSOR_SIZE, - CURSOR_WIDTH, attr->width, - CURSOR_HEIGHT, attr->height); - REG_UPDATE_3(CURSOR_CONTROL, - CURSOR_MODE, attr->color_format, - CURSOR_PITCH, hw_pitch, - CURSOR_LINES_PER_CHUNK, lpc); - ippn10_cursor_program_control(ippn10, - attr->attribute_flags.bits.INVERT_PIXEL_DATA, - attr->color_format); -} - -static void ippn10_cursor_set_position( - struct input_pixel_processor *ipp, - const struct dc_cursor_position *pos, - const struct dc_cursor_mi_param *param) -{ - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - int src_x_offset = pos->x - pos->x_hotspot - param->viewport_x_start; - uint32_t cur_en = pos->enable ? 1 : 0; - uint32_t dst_x_offset = (src_x_offset >= 0) ? src_x_offset : 0; - - /* - * Guard aganst cursor_set_position() from being called with invalid - * attributes - * - * TODO: Look at combining cursor_set_position() and - * cursor_set_attributes() into cursor_update() - */ - if (ippn10->curs_attr.address.quad_part == 0) - return; - - dst_x_offset *= param->ref_clk_khz; - dst_x_offset /= param->pixel_clk_khz; - - ASSERT(param->h_scale_ratio.value); - - if (param->h_scale_ratio.value) - dst_x_offset = dal_fixed31_32_floor(dal_fixed31_32_div( - dal_fixed31_32_from_int(dst_x_offset), - param->h_scale_ratio)); - - if (src_x_offset >= (int)param->viewport_width) - cur_en = 0; /* not visible beyond right edge*/ - - if (src_x_offset + (int)ippn10->curs_attr.width < 0) - cur_en = 0; /* not visible beyond left edge*/ - - if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0) - ippn10_cursor_set_attributes(ipp, &ippn10->curs_attr); - REG_UPDATE(CURSOR_CONTROL, - CURSOR_ENABLE, cur_en); - REG_UPDATE(CURSOR0_CONTROL, - CUR0_ENABLE, cur_en); - - REG_SET_2(CURSOR_POSITION, 0, - CURSOR_X_POSITION, pos->x, - CURSOR_Y_POSITION, pos->y); - - REG_SET_2(CURSOR_HOT_SPOT, 0, - CURSOR_HOT_SPOT_X, pos->x_hotspot, - CURSOR_HOT_SPOT_Y, pos->y_hotspot); - - REG_SET(CURSOR_DST_OFFSET, 0, - CURSOR_DST_X_OFFSET, dst_x_offset); - /* TODO Handle surface pixel formats other than 4:4:4 */ -} - /*****************************************/ /* Constructor, Destructor */ /*****************************************/ @@ -230,13 +48,6 @@ static void dcn10_ipp_destroy(struct input_pixel_processor **ipp) } static const struct ipp_funcs dcn10_ipp_funcs = { - .ipp_cursor_set_attributes = ippn10_cursor_set_attributes, - .ipp_cursor_set_position = ippn10_cursor_set_position, - .ipp_set_degamma = NULL, - .ipp_program_input_lut = NULL, - .ipp_full_bypass = NULL, - .ipp_setup = NULL, - .ipp_program_degamma_pwl = NULL, .ipp_destroy = dcn10_ipp_destroy }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index 082b39a65e6a..76573e1f5b01 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -65,7 +65,7 @@ static void mpc10_set_bg_color( MPCC_BG_B_CB, bg_b_cb); } -static void mpc10_assert_idle_mpcc(struct mpc *mpc, int id) +void mpc10_assert_idle_mpcc(struct mpc *mpc, int id) { struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); @@ -116,19 +116,21 @@ static void mpc10_assert_mpcc_idle_before_connect(struct dcn10_mpc *mpc10, int i } } -static void mpc10_mpcc_remove( +void mpc10_mpcc_remove( struct mpc *mpc, - struct output_pixel_processor *opp, + struct mpc_tree_cfg *tree_cfg, + int opp_id, int dpp_id) { struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); int mpcc_id, z_idx; - for (z_idx = 0; z_idx < opp->mpc_tree.num_pipes; z_idx++) - if (opp->mpc_tree.dpp[z_idx] == dpp_id) + /* find z_idx for the dpp to be removed */ + for (z_idx = 0; z_idx < tree_cfg->num_pipes; z_idx++) + if (tree_cfg->dpp[z_idx] == dpp_id) break; - if (z_idx == opp->mpc_tree.num_pipes) { + if (z_idx == tree_cfg->num_pipes) { /* In case of resume from S3/S4, remove mpcc from bios left over */ REG_SET(MPCC_OPP_ID[dpp_id], 0, MPCC_OPP_ID, 0xf); @@ -139,7 +141,7 @@ static void mpc10_mpcc_remove( return; } - mpcc_id = opp->mpc_tree.mpcc[z_idx]; + mpcc_id = tree_cfg->mpcc[z_idx]; REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, 0xf); @@ -149,82 +151,101 @@ static void mpc10_mpcc_remove( MPCC_BOT_SEL, 0xf); if (z_idx > 0) { - int top_mpcc_id = opp->mpc_tree.mpcc[z_idx - 1]; + int top_mpcc_id = tree_cfg->mpcc[z_idx - 1]; - if (z_idx + 1 < opp->mpc_tree.num_pipes) + if (z_idx + 1 < tree_cfg->num_pipes) + /* mpcc to be removed is in the middle of the tree */ REG_SET(MPCC_BOT_SEL[top_mpcc_id], 0, - MPCC_BOT_SEL, opp->mpc_tree.mpcc[z_idx + 1]); + MPCC_BOT_SEL, tree_cfg->mpcc[z_idx + 1]); else { + /* mpcc to be removed is at the bottom of the tree */ REG_SET(MPCC_BOT_SEL[top_mpcc_id], 0, MPCC_BOT_SEL, 0xf); REG_UPDATE(MPCC_CONTROL[top_mpcc_id], MPCC_MODE, MODE_TOP_ONLY); } - } else if (opp->mpc_tree.num_pipes > 1) - REG_SET(MUX[opp->inst], 0, - MPC_OUT_MUX, opp->mpc_tree.mpcc[z_idx + 1]); + } else if (tree_cfg->num_pipes > 1) + /* mpcc to be removed is at the top of the tree */ + REG_SET(MUX[opp_id], 0, + MPC_OUT_MUX, tree_cfg->mpcc[z_idx + 1]); else - REG_SET(MUX[opp->inst], 0, MPC_OUT_MUX, 0xf); + /* mpcc to be removed is the only one in the tree */ + REG_SET(MUX[opp_id], 0, MPC_OUT_MUX, 0xf); + /* mark this mpcc as not in use */ mpc10->mpcc_in_use_mask &= ~(1 << mpcc_id); - opp->mpc_tree.num_pipes--; - for (; z_idx < opp->mpc_tree.num_pipes; z_idx++) { - opp->mpc_tree.dpp[z_idx] = opp->mpc_tree.dpp[z_idx + 1]; - opp->mpc_tree.mpcc[z_idx] = opp->mpc_tree.mpcc[z_idx + 1]; + tree_cfg->num_pipes--; + for (; z_idx < tree_cfg->num_pipes; z_idx++) { + tree_cfg->dpp[z_idx] = tree_cfg->dpp[z_idx + 1]; + tree_cfg->mpcc[z_idx] = tree_cfg->mpcc[z_idx + 1]; } - opp->mpc_tree.dpp[opp->mpc_tree.num_pipes] = 0xdeadbeef; - opp->mpc_tree.mpcc[opp->mpc_tree.num_pipes] = 0xdeadbeef; + tree_cfg->dpp[tree_cfg->num_pipes] = 0xdeadbeef; + tree_cfg->mpcc[tree_cfg->num_pipes] = 0xdeadbeef; } -static void mpc10_mpcc_add(struct mpc *mpc, struct mpcc_cfg *cfg) +static void mpc10_add_to_tree_cfg( + struct mpc *mpc, + struct mpcc_cfg *cfg, + int mpcc_id) { struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); + int mpcc_mode = MODE_TOP_ONLY; + int position = cfg->z_index; + struct mpc_tree_cfg *tree_cfg = cfg->tree_cfg; int alpha_blnd_mode = cfg->per_pixel_alpha ? BLND_PP_ALPHA : BLND_GLOBAL_ALPHA; - int mpcc_mode = MODE_TOP_ONLY; - int mpcc_id, z_idx; + int z_idx; - ASSERT(cfg->z_index < mpc10->num_mpcc); + REG_SET(MPCC_OPP_ID[mpcc_id], 0, + MPCC_OPP_ID, cfg->opp_id); - for (z_idx = 0; z_idx < cfg->opp->mpc_tree.num_pipes; z_idx++) - if (cfg->opp->mpc_tree.dpp[z_idx] == cfg->mi->inst) - break; - if (z_idx == cfg->opp->mpc_tree.num_pipes) { - ASSERT(cfg->z_index <= cfg->opp->mpc_tree.num_pipes); - mpcc_id = mpc10_get_idle_mpcc_id(mpc10); - /*todo: remove hack*/ - mpcc_id = cfg->mi->inst; - ASSERT(!(mpc10->mpcc_in_use_mask & 1 << mpcc_id)); + REG_SET(MPCC_TOP_SEL[mpcc_id], 0, + MPCC_TOP_SEL, cfg->dpp_id); - if (mpc->ctx->dc->debug.sanity_checks) - mpc10_assert_mpcc_idle_before_connect(mpc10, mpcc_id); - } else { - ASSERT(cfg->z_index < cfg->opp->mpc_tree.num_pipes); - mpcc_id = cfg->opp->mpc_tree.mpcc[z_idx]; - mpc10_mpcc_remove(mpc, cfg->opp, cfg->mi->inst); - } + if (position == 0) { + /* idle dpp/mpcc is added to the top layer of tree */ - REG_SET(MPCC_OPP_ID[mpcc_id], 0, - MPCC_OPP_ID, cfg->opp->inst); + if (tree_cfg->num_pipes > 0) { + /* get instance of previous top mpcc */ + int prev_top_mpcc_id = tree_cfg->mpcc[0]; - REG_SET(MPCC_TOP_SEL[mpcc_id], 0, - MPCC_TOP_SEL, cfg->mi->inst); + REG_SET(MPCC_BOT_SEL[mpcc_id], 0, + MPCC_BOT_SEL, prev_top_mpcc_id); + mpcc_mode = MODE_BLEND; + } - if (cfg->z_index > 0) { - int top_mpcc_id = cfg->opp->mpc_tree.mpcc[cfg->z_index - 1]; + /* opp will get new output. from new added mpcc */ + REG_SET(MUX[cfg->opp_id], 0, MPC_OUT_MUX, mpcc_id); - REG_SET(MPCC_BOT_SEL[top_mpcc_id], 0, + } else if (position == tree_cfg->num_pipes) { + /* idle dpp/mpcc is added to the bottom layer of tree */ + + /* get instance of previous bottom mpcc, set to middle layer */ + int prev_bot_mpcc_id = tree_cfg->mpcc[tree_cfg->num_pipes - 1]; + + REG_SET(MPCC_BOT_SEL[prev_bot_mpcc_id], 0, MPCC_BOT_SEL, mpcc_id); - REG_UPDATE(MPCC_CONTROL[top_mpcc_id], + REG_UPDATE(MPCC_CONTROL[prev_bot_mpcc_id], MPCC_MODE, MODE_BLEND); - } else - REG_SET(MUX[cfg->opp->inst], 0, MPC_OUT_MUX, mpcc_id); - if (cfg->z_index < cfg->opp->mpc_tree.num_pipes) { - int bot_mpcc_id = cfg->opp->mpc_tree.mpcc[cfg->z_index]; + /* mpcc_id become new bottom mpcc*/ + REG_SET(MPCC_BOT_SEL[mpcc_id], 0, + MPCC_BOT_SEL, 0xf); + + } else { + /* idle dpp/mpcc is added to middle of tree */ + int above_mpcc_id = tree_cfg->mpcc[position - 1]; + int below_mpcc_id = tree_cfg->mpcc[position]; + /* mpcc above new mpcc_id has new bottom mux*/ + REG_SET(MPCC_BOT_SEL[above_mpcc_id], 0, + MPCC_BOT_SEL, mpcc_id); + REG_UPDATE(MPCC_CONTROL[above_mpcc_id], + MPCC_MODE, MODE_BLEND); + + /* mpcc_id bottom mux is from below mpcc*/ REG_SET(MPCC_BOT_SEL[mpcc_id], 0, - MPCC_BOT_SEL, bot_mpcc_id); + MPCC_BOT_SEL, below_mpcc_id); mpcc_mode = MODE_BLEND; } @@ -234,24 +255,91 @@ static void mpc10_mpcc_add(struct mpc *mpc, struct mpcc_cfg *cfg) MPCC_ALPHA_MULTIPLIED_MODE, cfg->pre_multiplied_alpha, MPCC_BLND_ACTIVE_OVERLAP_ONLY, false); + /* update mpc_tree_cfg with new mpcc */ + for (z_idx = tree_cfg->num_pipes; z_idx > position; z_idx--) { + tree_cfg->dpp[z_idx] = tree_cfg->dpp[z_idx - 1]; + tree_cfg->mpcc[z_idx] = tree_cfg->mpcc[z_idx - 1]; + } + tree_cfg->dpp[position] = cfg->dpp_id; + tree_cfg->mpcc[position] = mpcc_id; + tree_cfg->num_pipes++; +} + +int mpc10_mpcc_add(struct mpc *mpc, struct mpcc_cfg *cfg) +{ + struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); + int mpcc_id, z_idx; + + ASSERT(cfg->z_index < mpc10->num_mpcc); + + /* check in dpp already exists in mpc tree */ + for (z_idx = 0; z_idx < cfg->tree_cfg->num_pipes; z_idx++) + if (cfg->tree_cfg->dpp[z_idx] == cfg->dpp_id) + break; + if (z_idx == cfg->tree_cfg->num_pipes) { + ASSERT(cfg->z_index <= cfg->tree_cfg->num_pipes); + mpcc_id = mpc10_get_idle_mpcc_id(mpc10); + + /* + * TODO: remove hack + * Note: currently there is a bug in init_hw such that + * on resume from hibernate, BIOS sets up MPCC0, and + * we do mpcc_remove but the mpcc cannot go to idle + * after remove. This cause us to pick mpcc1 here, + * which causes a pstate hang for yet unknown reason. + */ + mpcc_id = cfg->dpp_id; + /* end hack*/ + + ASSERT(!(mpc10->mpcc_in_use_mask & 1 << mpcc_id)); + + if (mpc->ctx->dc->debug.sanity_checks) + mpc10_assert_mpcc_idle_before_connect(mpc10, mpcc_id); + } else { + ASSERT(cfg->z_index < cfg->tree_cfg->num_pipes); + mpcc_id = cfg->tree_cfg->mpcc[z_idx]; + mpc10_mpcc_remove(mpc, cfg->tree_cfg, cfg->opp_id, cfg->dpp_id); + } + + /* add dpp/mpcc pair to mpc_tree_cfg and update mpcc registers */ + mpc10_add_to_tree_cfg(mpc, cfg, mpcc_id); + + /* set background color */ mpc10_set_bg_color(mpc10, &cfg->black_color, mpcc_id); + /* mark this mpcc as in use */ mpc10->mpcc_in_use_mask |= 1 << mpcc_id; - for (z_idx = cfg->opp->mpc_tree.num_pipes; z_idx > cfg->z_index; z_idx--) { - cfg->opp->mpc_tree.dpp[z_idx] = cfg->opp->mpc_tree.dpp[z_idx - 1]; - cfg->opp->mpc_tree.mpcc[z_idx] = cfg->opp->mpc_tree.mpcc[z_idx - 1]; - } - cfg->opp->mpc_tree.dpp[cfg->z_index] = cfg->mi->inst; - cfg->opp->mpc_tree.mpcc[cfg->z_index] = mpcc_id; - cfg->opp->mpc_tree.num_pipes++; - cfg->mi->opp_id = cfg->opp->inst; - cfg->mi->mpcc_id = mpcc_id; + + return mpcc_id; +} + +void mpc10_update_blend_mode( + struct mpc *mpc, + struct mpcc_cfg *cfg) +{ + struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); + int mpcc_id, z_idx; + int alpha_blnd_mode = cfg->per_pixel_alpha ? + BLND_PP_ALPHA : BLND_GLOBAL_ALPHA; + + /* find z_idx for the dpp that requires blending mode update*/ + for (z_idx = 0; z_idx < cfg->tree_cfg->num_pipes; z_idx++) + if (cfg->tree_cfg->dpp[z_idx] == cfg->dpp_id) + break; + + ASSERT(z_idx < cfg->tree_cfg->num_pipes); + mpcc_id = cfg->tree_cfg->mpcc[z_idx]; + + REG_UPDATE_2(MPCC_CONTROL[mpcc_id], + MPCC_ALPHA_BLND_MODE, alpha_blnd_mode, + MPCC_ALPHA_MULTIPLIED_MODE, cfg->pre_multiplied_alpha); } const struct mpc_funcs dcn10_mpc_funcs = { .add = mpc10_mpcc_add, .remove = mpc10_mpcc_remove, - .wait_for_idle = mpc10_assert_idle_mpcc + .wait_for_idle = mpc10_assert_idle_mpcc, + .update_blend_mode = mpc10_update_blend_mode, }; void dcn10_mpc_construct(struct dcn10_mpc *mpc10, @@ -272,3 +360,4 @@ void dcn10_mpc_construct(struct dcn10_mpc *mpc10, mpc10->mpcc_in_use_mask = 0; mpc10->num_mpcc = num_mpcc; } + diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h index 94f890a0ad40..683ce4aaa76e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h @@ -34,7 +34,6 @@ #define MAX_OPP 6 #define MPC_COMMON_REG_LIST_DCN1_0(inst) \ - SRII(MUX, MPC_OUT, inst),\ SRII(MPCC_TOP_SEL, MPCC, inst),\ SRII(MPCC_BOT_SEL, MPCC, inst),\ SRII(MPCC_CONTROL, MPCC, inst),\ @@ -45,17 +44,19 @@ SRII(MPCC_BG_B_CB, MPCC, inst),\ SRII(MPCC_BG_B_CB, MPCC, inst) -struct dcn_mpc_registers { - uint32_t MPCC_TOP_SEL[MAX_MPCC]; - uint32_t MPCC_BOT_SEL[MAX_MPCC]; - uint32_t MPCC_CONTROL[MAX_MPCC]; - uint32_t MPCC_STATUS[MAX_MPCC]; - uint32_t MPCC_OPP_ID[MAX_MPCC]; - uint32_t MPCC_BG_G_Y[MAX_MPCC]; - uint32_t MPCC_BG_R_CR[MAX_MPCC]; - uint32_t MPCC_BG_B_CB[MAX_MPCC]; +#define MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0(inst) \ + SRII(MUX, MPC_OUT, inst) + +#define MPC_COMMON_REG_VARIABLE_LIST \ + uint32_t MPCC_TOP_SEL[MAX_MPCC]; \ + uint32_t MPCC_BOT_SEL[MAX_MPCC]; \ + uint32_t MPCC_CONTROL[MAX_MPCC]; \ + uint32_t MPCC_STATUS[MAX_MPCC]; \ + uint32_t MPCC_OPP_ID[MAX_MPCC]; \ + uint32_t MPCC_BG_G_Y[MAX_MPCC]; \ + uint32_t MPCC_BG_R_CR[MAX_MPCC]; \ + uint32_t MPCC_BG_B_CB[MAX_MPCC]; \ uint32_t MUX[MAX_OPP]; -}; #define MPC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ SF(MPCC0_MPCC_TOP_SEL, MPCC_TOP_SEL, mask_sh),\ @@ -87,6 +88,10 @@ struct dcn_mpc_registers { type MPCC_BG_B_CB;\ type MPC_OUT_MUX; +struct dcn_mpc_registers { + MPC_COMMON_REG_VARIABLE_LIST +}; + struct dcn_mpc_shift { MPC_REG_FIELD_LIST(uint8_t) }; @@ -112,4 +117,22 @@ void dcn10_mpc_construct(struct dcn10_mpc *mpcc10, const struct dcn_mpc_mask *mpc_mask, int num_mpcc); +int mpc10_mpcc_add( + struct mpc *mpc, + struct mpcc_cfg *cfg); + +void mpc10_mpcc_remove( + struct mpc *mpc, + struct mpc_tree_cfg *tree_cfg, + int opp_id, + int dpp_id); + +void mpc10_assert_idle_mpcc( + struct mpc *mpc, + int id); + +void mpc10_update_blend_mode( + struct mpc *mpc, + struct mpcc_cfg *cfg); + #endif 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 dc878f77837b..d911590d08bc 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -42,12 +42,12 @@ #include "dce/dce_stream_encoder.h" #include "dce/dce_clocks.h" #include "dce/dce_clock_source.h" -#include "dcn10/dcn10_mem_input.h" #include "dce/dce_audio.h" #include "dce/dce_hwseq.h" #include "../virtual/virtual_stream_encoder.h" #include "dce110/dce110_resource.h" #include "dce112/dce112_resource.h" +#include "dcn10_hubp.h" #include "vega10/soc15ip.h" @@ -329,7 +329,11 @@ static const struct dcn_mpc_registers mpc_regs = { MPC_COMMON_REG_LIST_DCN1_0(0), MPC_COMMON_REG_LIST_DCN1_0(1), MPC_COMMON_REG_LIST_DCN1_0(2), - MPC_COMMON_REG_LIST_DCN1_0(3) + MPC_COMMON_REG_LIST_DCN1_0(3), + MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0(0), + MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0(1), + MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0(2), + MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0(3) }; static const struct dcn_mpc_shift mpc_shift = { @@ -414,22 +418,24 @@ static const struct resource_caps res_cap = { }; static const struct dc_debug debug_defaults_drv = { - .disable_dcc = false, .sanity_checks = true, .disable_dmcu = true, .force_abm_enable = false, .timing_trace = false, .clock_trace = true, - /* spread sheet doesn't handle taps_c is one properly, - * need to enable scaler for video surface to pass - * bandwidth validation.*/ - .always_scale = true, + + .min_disp_clk_khz = 300000, + .disable_pplib_clock_request = true, .disable_pplib_wm_range = false, -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - .use_dml_wm = false, - .disable_pipe_split = true -#endif + .pplib_wm_report_mode = WM_REPORT_DEFAULT, + .pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP, + .force_single_disp_pipe_split = true, + .disable_dcc = DCC_ENABLE, + .voltage_align_fclk = true, + .disable_stereo_support = true, + .vsr_support = true, + .performance_trace = false, }; static const struct dc_debug debug_defaults_diags = { @@ -438,21 +444,17 @@ static const struct dc_debug debug_defaults_diags = { .timing_trace = true, .clock_trace = true, .disable_stutter = true, -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) .disable_pplib_clock_request = true, - .disable_pplib_wm_range = true, - .use_dml_wm = false, - .disable_pipe_split = false -#endif + .disable_pplib_wm_range = true }; -static void dcn10_dpp_destroy(struct transform **xfm) +static void dcn10_dpp_destroy(struct dpp **dpp) { - kfree(TO_DCN10_DPP(*xfm)); - *xfm = NULL; + kfree(TO_DCN10_DPP(*dpp)); + *dpp = NULL; } -static struct transform *dcn10_dpp_create( +static struct dpp *dcn10_dpp_create( struct dc_context *ctx, uint32_t inst) { @@ -462,8 +464,8 @@ static struct transform *dcn10_dpp_create( if (!dpp) return NULL; - dcn10_dpp_construct(dpp, ctx, inst, - &tf_regs[inst], &tf_shift, &tf_mask); + dpp1_construct(dpp, ctx, inst, + &tf_regs[inst], &tf_shift, &tf_mask); return &dpp->base; } @@ -702,15 +704,15 @@ static void destruct(struct dcn10_resource_pool *pool) if (pool->base.opps[i] != NULL) pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); - if (pool->base.transforms[i] != NULL) - dcn10_dpp_destroy(&pool->base.transforms[i]); + if (pool->base.dpps[i] != NULL) + dcn10_dpp_destroy(&pool->base.dpps[i]); if (pool->base.ipps[i] != NULL) pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); - if (pool->base.mis[i] != NULL) { - kfree(TO_DCN10_MEM_INPUT(pool->base.mis[i])); - pool->base.mis[i] = NULL; + if (pool->base.hubps[i] != NULL) { + kfree(TO_DCN10_HUBP(pool->base.hubps[i])); + pool->base.hubps[i] = NULL; } if (pool->base.irqs != NULL) { @@ -757,19 +759,19 @@ static void destruct(struct dcn10_resource_pool *pool) kfree(pool->base.pp_smu); } -static struct mem_input *dcn10_mem_input_create( +static struct hubp *dcn10_hubp_create( struct dc_context *ctx, uint32_t inst) { - struct dcn10_mem_input *mem_inputn10 = - kzalloc(sizeof(struct dcn10_mem_input), GFP_KERNEL); + struct dcn10_hubp *hubp1 = + kzalloc(sizeof(struct dcn10_hubp), GFP_KERNEL); - if (!mem_inputn10) + if (!hubp1) return NULL; - dcn10_mem_input_construct(mem_inputn10, ctx, inst, - &mi_regs[inst], &mi_shift, &mi_mask); - return &mem_inputn10->base; + dcn10_hubp_construct(hubp1, ctx, inst, + &mi_regs[inst], &mi_shift, &mi_mask); + return &hubp1->base; } static void get_pixel_clock_parameters( @@ -922,9 +924,9 @@ static struct pipe_ctx *dcn10_acquire_idle_pipe_for_layer( idle_pipe->stream_res.tg = head_pipe->stream_res.tg; idle_pipe->stream_res.opp = head_pipe->stream_res.opp; - idle_pipe->plane_res.mi = pool->mis[idle_pipe->pipe_idx]; + idle_pipe->plane_res.hubp = pool->hubps[idle_pipe->pipe_idx]; idle_pipe->plane_res.ipp = pool->ipps[idle_pipe->pipe_idx]; - idle_pipe->plane_res.xfm = pool->transforms[idle_pipe->pipe_idx]; + idle_pipe->plane_res.dpp = pool->dpps[idle_pipe->pipe_idx]; return idle_pipe; } @@ -1085,7 +1087,7 @@ static bool get_dcc_compression_cap(const struct dc *dc, memset(output, 0, sizeof(*output)); - if (dc->debug.disable_dcc) + if (dc->debug.disable_dcc == DCC_DISABLE) return false; if (!dcc_support_pixel_format(input->format, @@ -1129,6 +1131,10 @@ static bool get_dcc_compression_cap(const struct dc *dc, dcc_control = dcc_control__128_128_xxx; } + if (dc->debug.disable_dcc == DCC_HALF_REQ_DISALBE && + dcc_control != dcc_control__256_256_xxx) + return false; + switch (dcc_control) { case dcc_control__256_256_xxx: output->grph.rgb.max_uncompressed_blk_size = 256; @@ -1146,6 +1152,7 @@ static bool get_dcc_compression_cap(const struct dc *dc, output->grph.rgb.independent_64b_blks = true; break; } + output->capable = true; output->const_color_support = false; @@ -1162,6 +1169,15 @@ static void dcn10_destroy_resource_pool(struct resource_pool **pool) *pool = NULL; } +static enum dc_status dcn10_validate_plane(const struct dc_plane_state *plane_state, struct dc_caps *caps) +{ + if (plane_state->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN + && caps->max_video_width != 0 + && plane_state->src_rect.width > caps->max_video_width) + return DC_FAIL_SURFACE_VALIDATE; + + return DC_OK; +} static struct dc_cap_funcs cap_funcs = { .get_dcc_compression_cap = get_dcc_compression_cap @@ -1173,6 +1189,7 @@ static struct resource_funcs dcn10_res_pool_funcs = { .validate_guaranteed = dcn10_validate_guaranteed, .validate_bandwidth = dcn_validate_bandwidth, .acquire_idle_pipe_for_layer = dcn10_acquire_idle_pipe_for_layer, + .validate_plane = dcn10_validate_plane, .add_stream_to_ctx = dcn10_add_stream_to_ctx }; @@ -1212,6 +1229,7 @@ static bool construct( /* max pipe num for ASIC before check pipe fuses */ pool->base.pipe_count = pool->base.res_cap->num_timing_generator; + dc->caps.max_video_width = 3840; dc->caps.max_downscale_ratio = 200; dc->caps.i2c_speed_in_khz = 100; dc->caps.max_cursor_size = 256; @@ -1345,8 +1363,8 @@ static bool construct( if ((pipe_fuses & (1 << i)) != 0) continue; - pool->base.mis[j] = dcn10_mem_input_create(ctx, i); - if (pool->base.mis[j] == NULL) { + pool->base.hubps[j] = dcn10_hubp_create(ctx, i); + if (pool->base.hubps[j] == NULL) { BREAK_TO_DEBUGGER(); dm_error( "DC: failed to create memory input!\n"); @@ -1361,8 +1379,8 @@ static bool construct( goto ipp_create_fail; } - pool->base.transforms[j] = dcn10_dpp_create(ctx, i); - if (pool->base.transforms[j] == NULL) { + pool->base.dpps[j] = dcn10_dpp_create(ctx, i); + if (pool->base.dpps[j] == NULL) { BREAK_TO_DEBUGGER(); dm_error( "DC: failed to create dpp!\n"); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 7cd10cbc5497..1994865d4351 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -25,6 +25,7 @@ #include "reg_helper.h" #include "dcn10_timing_generator.h" +#include "dc.h" #define REG(reg)\ tgn10->tg_regs->reg @@ -299,6 +300,17 @@ static void tgn10_program_timing( static void tgn10_unblank_crtc(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + uint32_t vertical_interrupt_enable = 0; + + REG_GET(OTG_VERTICAL_INTERRUPT2_CONTROL, + OTG_VERTICAL_INTERRUPT2_INT_ENABLE, &vertical_interrupt_enable); + + /* temporary work around for vertical interrupt, once vertical interrupt enabled, + * this check will be removed. + */ + if (vertical_interrupt_enable) + REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL, + OTG_BLANK_DATA_DOUBLE_BUFFER_EN, 1); REG_UPDATE_2(OTG_BLANK_CONTROL, OTG_BLANK_DATA_EN, 0, @@ -487,6 +499,9 @@ static bool tgn10_validate_timing( timing->timing_3d_format != TIMING_3D_FORMAT_INBAND_FA) return false; + if (timing->timing_3d_format != TIMING_3D_FORMAT_NONE && + tg->ctx->dc->debug.disable_stereo_support) + return false; /* Temporarily blocking interlacing mode until it's supported */ if (timing->flags.INTERLACE == 1) return false; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h index 69da293e9b4a..7d4818d7aa31 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h @@ -65,17 +65,14 @@ SRI(OTG_NOM_VERT_POSITION, OTG, inst),\ SRI(OTG_BLACK_COLOR, OTG, inst),\ SRI(OTG_CLOCK_CONTROL, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT2_CONTROL, OTG, inst),\ SRI(OTG_VERTICAL_INTERRUPT2_POSITION, OTG, inst),\ SRI(OPTC_INPUT_CLOCK_CONTROL, ODM, inst),\ SRI(OPTC_DATA_SOURCE_SELECT, ODM, inst),\ SRI(OPTC_INPUT_GLOBAL_CONTROL, ODM, inst),\ SRI(OPPBUF_CONTROL, OPPBUF, inst),\ SRI(OPPBUF_3D_PARAMETERS_0, OPPBUF, inst),\ - SRI(CONTROL, VTG, inst),\ - SR(D1VGA_CONTROL),\ - SR(D2VGA_CONTROL),\ - SR(D3VGA_CONTROL),\ - SR(D4VGA_CONTROL) + SRI(CONTROL, VTG, inst) #define TG_COMMON_REG_LIST_DCN1_0(inst) \ TG_COMMON_REG_LIST_DCN(inst),\ @@ -121,6 +118,7 @@ struct dcn_tg_registers { uint32_t OTG_TEST_PATTERN_CONTROL; uint32_t OTG_TEST_PATTERN_COLOR; uint32_t OTG_CLOCK_CONTROL; + uint32_t OTG_VERTICAL_INTERRUPT2_CONTROL; uint32_t OTG_VERTICAL_INTERRUPT2_POSITION; uint32_t OPTC_INPUT_CLOCK_CONTROL; uint32_t OPTC_DATA_SOURCE_SELECT; @@ -128,11 +126,6 @@ struct dcn_tg_registers { uint32_t OPPBUF_CONTROL; uint32_t OPPBUF_3D_PARAMETERS_0; uint32_t CONTROL; - /*todo: move VGA to HWSS */ - uint32_t D1VGA_CONTROL; - uint32_t D2VGA_CONTROL; - uint32_t D3VGA_CONTROL; - uint32_t D4VGA_CONTROL; }; #define TG_COMMON_MASK_SH_LIST_DCN(mask_sh)\ @@ -205,6 +198,7 @@ struct dcn_tg_registers { SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_EN, mask_sh),\ SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_ON, mask_sh),\ SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_GATE_DIS, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT2_CONTROL, OTG_VERTICAL_INTERRUPT2_INT_ENABLE, mask_sh),\ SF(OTG0_OTG_VERTICAL_INTERRUPT2_POSITION, OTG_VERTICAL_INTERRUPT2_LINE_START, mask_sh),\ SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_EN, mask_sh),\ SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, mask_sh),\ @@ -311,6 +305,7 @@ struct dcn_tg_registers { type OTG_CLOCK_EN;\ type OTG_CLOCK_ON;\ type OTG_CLOCK_GATE_DIS;\ + type OTG_VERTICAL_INTERRUPT2_INT_ENABLE;\ type OTG_VERTICAL_INTERRUPT2_LINE_START;\ type OPTC_INPUT_CLK_EN;\ type OPTC_INPUT_CLK_ON;\ diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index a11991c382de..c8190c38a644 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -38,51 +38,6 @@ #undef DEPRECATED -/* - * - * general debug capabilities - * - */ -#if defined(CONFIG_DEBUG_KERNEL) || defined(CONFIG_DEBUG_DRIVER) - -#if defined(CONFIG_HAVE_KGDB) || defined(CONFIG_KGDB) -#define ASSERT_CRITICAL(expr) do { \ - if (WARN_ON(!(expr))) { \ - kgdb_breakpoint(); \ - } \ -} while (0) -#else -#define ASSERT_CRITICAL(expr) do { \ - if (WARN_ON(!(expr))) { \ - ; \ - } \ -} while (0) -#endif - -#if defined(CONFIG_DEBUG_KERNEL_DC) -#define ASSERT(expr) ASSERT_CRITICAL(expr) - -#else -#define ASSERT(expr) WARN_ON(!(expr)) -#endif - -#define BREAK_TO_DEBUGGER() ASSERT(0) - -#endif /* CONFIG_DEBUG_KERNEL || CONFIG_DEBUG_DRIVER */ - -#define DC_ERR(...) do { \ - dm_error(__VA_ARGS__); \ - BREAK_TO_DEBUGGER(); \ -} while (0) - -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) -#include <asm/fpu/api.h> -#endif - -#define dm_alloc(size) kzalloc(size, GFP_KERNEL) -#define dm_realloc(ptr, size) krealloc(ptr, size, GFP_KERNEL) -#define dm_free(ptr) kfree(ptr) - irq_handler_idx dm_register_interrupt( struct dc_context *ctx, struct dc_interrupt_params *int_params, @@ -418,6 +373,8 @@ bool dm_dmcu_set_pipe(struct dc_context *ctx, unsigned int controller_id); #define dm_log_to_buffer(buffer, size, fmt, args)\ vsnprintf(buffer, size, fmt, args) +unsigned long long dm_get_timestamp(struct dc_context *ctx); + /* * Debug and verification hooks */ diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index ec712d727665..87bab8e8139f 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -3,17 +3,19 @@ # It provides the general basic services required by other DAL # subcomponents. +CFLAGS_display_mode_vba.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_display_mode_lib.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_display_pipe_clocks.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_display_rq_dlg_calc.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_dml1_display_rq_dlg_calc.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_display_rq_dlg_helpers.o := -mhard-float -msse -mpreferred-stack-boundary=4 -CFLAGS_display_watermark.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_soc_bounding_box.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_dml_common_defs.o := -mhard-float -msse -mpreferred-stack-boundary=4 + DML = display_mode_lib.o display_rq_dlg_calc.o \ - display_rq_dlg_helpers.o display_watermark.o \ - soc_bounding_box.o dml_common_defs.o + display_rq_dlg_helpers.o dml1_display_rq_dlg_calc.o \ + soc_bounding_box.o dml_common_defs.o display_mode_vba.o AMD_DAL_DML = $(addprefix $(AMDDALPATH)/dc/dml/,$(DML)) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dc_features.h b/drivers/gpu/drm/amd/display/dc/dml/dc_features.h index 745c04cb764a..ea4cde952f4f 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dc_features.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dc_features.h @@ -25,9 +25,11 @@ #ifndef __DC_FEATURES_H__ #define __DC_FEATURES_H__ +// local features #define DC__PRESENT 1 #define DC__PRESENT__1 1 #define DC__NUM_DPP 4 +#define DC__VOLTAGE_STATES 7 #define DC__NUM_DPP__4 1 #define DC__NUM_DPP__0_PRESENT 1 #define DC__NUM_DPP__1_PRESENT 1 diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h index 143a3d418de0..b1ad3553f900 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h @@ -24,14 +24,12 @@ */ #ifndef __DISPLAY_MODE_ENUMS_H__ #define __DISPLAY_MODE_ENUMS_H__ + enum output_encoder_class { - dm_dp = 0, - dm_hdmi = 1, - dm_wb = 2 + dm_dp = 0, dm_hdmi = 1, dm_wb = 2, dm_edp }; enum output_format_class { - dm_444 = 0, - dm_420 = 1 + dm_444 = 0, dm_420 = 1, dm_n422, dm_s422 }; enum source_format_class { dm_444_16 = 0, @@ -40,18 +38,16 @@ enum source_format_class { dm_420_8 = 3, dm_420_10 = 4, dm_422_8 = 5, - dm_422_10 = 6 + dm_422_10 = 6, + dm_444_8 = 7, + dm_mono_8, + dm_mono_16 }; enum output_bpc_class { - dm_out_6 = 0, - dm_out_8 = 1, - dm_out_10 = 2, - dm_out_12 = 3, - dm_out_16 = 4 + dm_out_6 = 0, dm_out_8 = 1, dm_out_10 = 2, dm_out_12 = 3, dm_out_16 = 4 }; enum scan_direction_class { - dm_horz = 0, - dm_vert = 1 + dm_horz = 0, dm_vert = 1 }; enum dm_swizzle_mode { dm_sw_linear = 0, @@ -84,28 +80,32 @@ enum dm_swizzle_mode { dm_sw_SPARE_14 = 27, dm_sw_SPARE_15 = 28, dm_sw_var_s_x = 29, - dm_sw_var_d_x = 30 + dm_sw_var_d_x = 30, + dm_sw_64kb_r_x, + dm_sw_gfx7_2d_thin_lvp, + dm_sw_gfx7_2d_thin_gl }; enum lb_depth { - dm_lb_10 = 30, - dm_lb_8 = 24, - dm_lb_6 = 18, - dm_lb_12 = 36 + dm_lb_10 = 0, dm_lb_8 = 1, dm_lb_6 = 2, dm_lb_12 = 3, dm_lb_16 }; enum voltage_state { - dm_vmin = 0, - dm_vmid = 1, - dm_vnom = 2, - dm_vmax = 3, - dm_vmax_exceeded = 4 + dm_vmin = 0, dm_vmid = 1, dm_vnom = 2, dm_vmax = 3 }; enum source_macro_tile_size { - dm_4k_tile = 0, - dm_64k_tile = 1, - dm_256k_tile = 2 + dm_4k_tile = 0, dm_64k_tile = 1, dm_256k_tile = 2 }; enum cursor_bpp { - dm_cur_2bit = 0, - dm_cur_32bit = 1 + dm_cur_2bit = 0, dm_cur_32bit = 1, dm_cur_64bit = 2 }; +enum clock_change_support { + dm_dram_clock_change_uninitialized = 0, + dm_dram_clock_change_vactive, + dm_dram_clock_change_vblank, + dm_dram_clock_change_unsupported +}; + +enum output_standard { + dm_std_uninitialized = 0, dm_std_cvtr2, dm_std_cvt +}; + #endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c index c02c5522613b..4c31fa54af39 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c @@ -24,6 +24,7 @@ */ #include "display_mode_lib.h" +#include "dc_features.h" static void set_soc_bounding_box(struct _vcs_dpi_soc_bounding_box_st *soc, enum dml_project project) { @@ -126,21 +127,11 @@ static void set_ip_params(struct _vcs_dpi_ip_params_st *ip, enum dml_project pro } } -static void set_mode_evaluation(struct _vcs_dpi_mode_evaluation_st *me, enum dml_project project) -{ - if (project == DML_PROJECT_RAVEN1) { - me->voltage_override = dm_vmin; - } else { - BREAK_TO_DEBUGGER(); /* Invalid Project Specified */ - } -} - void dml_init_instance(struct display_mode_lib *lib, enum dml_project project) { if (lib->project != project) { set_soc_bounding_box(&lib->soc, project); set_ip_params(&lib->ip, project); - set_mode_evaluation(&lib->me, project); lib->project = project; } } diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h index eb1c8e6e7f23..26f4f2a3d90d 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h @@ -25,11 +25,12 @@ #ifndef __DISPLAY_MODE_LIB_H__ #define __DISPLAY_MODE_LIB_H__ + #include "dml_common_defs.h" #include "soc_bounding_box.h" -#include "display_watermark.h" +#include "display_mode_vba.h" #include "display_rq_dlg_calc.h" -#include "display_mode_support.h" +#include "dml1_display_rq_dlg_calc.h" enum dml_project { DML_PROJECT_UNDEFINED, @@ -39,10 +40,8 @@ enum dml_project { struct display_mode_lib { struct _vcs_dpi_ip_params_st ip; struct _vcs_dpi_soc_bounding_box_st soc; - struct _vcs_dpi_mode_evaluation_st me; enum dml_project project; - struct dml_ms_internal_vars vars; - struct _vcs_dpi_wm_calc_pipe_params_st wm_param[DC__NUM_PIPES__MAX]; + struct vba_vars_st vba; struct dal_logger *logger; }; 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 e589a5eadb6a..baf182177736 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 @@ -25,405 +25,533 @@ #ifndef __DISPLAY_MODE_STRUCTS_H__ #define __DISPLAY_MODE_STRUCTS_H__ +typedef struct _vcs_dpi_voltage_scaling_st voltage_scaling_st; +typedef struct _vcs_dpi_soc_bounding_box_st soc_bounding_box_st; +typedef struct _vcs_dpi_ip_params_st ip_params_st; +typedef struct _vcs_dpi_display_pipe_source_params_st display_pipe_source_params_st; +typedef struct _vcs_dpi_display_output_params_st display_output_params_st; +typedef struct _vcs_dpi_display_bandwidth_st display_bandwidth_st; +typedef struct _vcs_dpi_scaler_ratio_depth_st scaler_ratio_depth_st; +typedef struct _vcs_dpi_scaler_taps_st scaler_taps_st; +typedef struct _vcs_dpi_display_pipe_dest_params_st display_pipe_dest_params_st; +typedef struct _vcs_dpi_display_pipe_params_st display_pipe_params_st; +typedef struct _vcs_dpi_display_clocks_and_cfg_st display_clocks_and_cfg_st; +typedef struct _vcs_dpi_display_e2e_pipe_params_st display_e2e_pipe_params_st; +typedef struct _vcs_dpi_dchub_buffer_sizing_st dchub_buffer_sizing_st; +typedef struct _vcs_dpi_watermarks_perf_st watermarks_perf_st; +typedef struct _vcs_dpi_cstate_pstate_watermarks_st cstate_pstate_watermarks_st; +typedef struct _vcs_dpi_wm_calc_pipe_params_st wm_calc_pipe_params_st; +typedef struct _vcs_dpi_vratio_pre_st vratio_pre_st; +typedef struct _vcs_dpi_display_data_rq_misc_params_st display_data_rq_misc_params_st; +typedef struct _vcs_dpi_display_data_rq_sizing_params_st display_data_rq_sizing_params_st; +typedef struct _vcs_dpi_display_data_rq_dlg_params_st display_data_rq_dlg_params_st; +typedef struct _vcs_dpi_display_cur_rq_dlg_params_st display_cur_rq_dlg_params_st; +typedef struct _vcs_dpi_display_rq_dlg_params_st display_rq_dlg_params_st; +typedef struct _vcs_dpi_display_rq_sizing_params_st display_rq_sizing_params_st; +typedef struct _vcs_dpi_display_rq_misc_params_st display_rq_misc_params_st; +typedef struct _vcs_dpi_display_rq_params_st display_rq_params_st; +typedef struct _vcs_dpi_display_dlg_regs_st display_dlg_regs_st; +typedef struct _vcs_dpi_display_ttu_regs_st display_ttu_regs_st; +typedef struct _vcs_dpi_display_data_rq_regs_st display_data_rq_regs_st; +typedef struct _vcs_dpi_display_rq_regs_st display_rq_regs_st; +typedef struct _vcs_dpi_display_dlg_sys_params_st display_dlg_sys_params_st; +typedef struct _vcs_dpi_display_dlg_prefetch_param_st display_dlg_prefetch_param_st; +typedef struct _vcs_dpi_display_pipe_clock_st display_pipe_clock_st; +typedef struct _vcs_dpi_display_arb_params_st display_arb_params_st; + struct _vcs_dpi_voltage_scaling_st { + int state; + double dscclk_mhz; double dcfclk_mhz; + double socclk_mhz; + double dram_speed_mhz; + double fabricclk_mhz; double dispclk_mhz; - double dppclk_mhz; double dram_bw_per_chan_gbps; double phyclk_mhz; - double socclk_mhz; + double dppclk_mhz; }; -struct _vcs_dpi_soc_bounding_box_st { - double sr_exit_time_us; - double sr_enter_plus_exit_time_us; - double urgent_latency_us; - double writeback_latency_us; - double ideal_dram_bw_after_urgent_percent; - unsigned int max_request_size_bytes; - struct _vcs_dpi_voltage_scaling_st vmin; - struct _vcs_dpi_voltage_scaling_st vmid; - struct _vcs_dpi_voltage_scaling_st vnom; - struct _vcs_dpi_voltage_scaling_st vmax; - double downspread_percent; - double dram_page_open_time_ns; - double dram_rw_turnaround_time_ns; - double dram_return_buffer_per_channel_bytes; - unsigned int round_trip_ping_latency_dcfclk_cycles; - unsigned int urgent_out_of_order_return_per_channel_bytes; - unsigned int channel_interleave_bytes; - unsigned int num_banks; - unsigned int num_chans; - unsigned int vmm_page_size_bytes; - double dram_clock_change_latency_us; - double writeback_dram_clock_change_latency_us; - unsigned int return_bus_width_bytes; -}; - -struct _vcs_dpi_ip_params_st { - unsigned int rob_buffer_size_kbytes; - unsigned int det_buffer_size_kbytes; - unsigned int dpte_buffer_size_in_pte_reqs; - unsigned int dpp_output_buffer_pixels; - unsigned int opp_output_buffer_lines; - unsigned int pixel_chunk_size_kbytes; - unsigned char pte_enable; - unsigned int pte_chunk_size_kbytes; - unsigned int meta_chunk_size_kbytes; - unsigned int writeback_chunk_size_kbytes; - unsigned int line_buffer_size_bits; - unsigned int max_line_buffer_lines; +struct _vcs_dpi_soc_bounding_box_st { + double sr_exit_time_us; + double sr_enter_plus_exit_time_us; + double urgent_latency_us; + double writeback_latency_us; + double ideal_dram_bw_after_urgent_percent; + unsigned int max_request_size_bytes; + struct _vcs_dpi_voltage_scaling_st vmin; + struct _vcs_dpi_voltage_scaling_st vmid; + struct _vcs_dpi_voltage_scaling_st vnom; + struct _vcs_dpi_voltage_scaling_st vmax; + double downspread_percent; + double dram_page_open_time_ns; + double dram_rw_turnaround_time_ns; + double dram_return_buffer_per_channel_bytes; + double dram_channel_width_bytes; + double fabric_datapath_to_dcn_data_return_bytes; + double dcn_downspread_percent; + double dispclk_dppclk_vco_speed_mhz; + double dfs_vco_period_ps; + unsigned int round_trip_ping_latency_dcfclk_cycles; + unsigned int urgent_out_of_order_return_per_channel_bytes; + unsigned int channel_interleave_bytes; + unsigned int num_banks; + unsigned int num_chans; + unsigned int vmm_page_size_bytes; + double dram_clock_change_latency_us; + double writeback_dram_clock_change_latency_us; + unsigned int return_bus_width_bytes; + unsigned int voltage_override; + double xfc_bus_transport_time_us; + double xfc_xbuf_latency_tolerance_us; + struct _vcs_dpi_voltage_scaling_st clock_limits[7]; +}; + +struct _vcs_dpi_ip_params_st { + unsigned int max_inter_dcn_tile_repeaters; + unsigned int num_dsc; + unsigned int odm_capable; + unsigned int rob_buffer_size_kbytes; + unsigned int det_buffer_size_kbytes; + unsigned int dpte_buffer_size_in_pte_reqs; + unsigned int pde_proc_buffer_size_64k_reqs; + unsigned int dpp_output_buffer_pixels; + unsigned int opp_output_buffer_lines; + unsigned int pixel_chunk_size_kbytes; + unsigned char pte_enable; + unsigned int pte_chunk_size_kbytes; + unsigned int meta_chunk_size_kbytes; + unsigned int writeback_chunk_size_kbytes; + unsigned int line_buffer_size_bits; + unsigned int max_line_buffer_lines; + unsigned int writeback_luma_buffer_size_kbytes; + unsigned int writeback_chroma_buffer_size_kbytes; + unsigned int writeback_chroma_line_buffer_width_pixels; + unsigned int max_page_table_levels; + unsigned int max_num_dpp; + unsigned int max_num_otg; + unsigned int cursor_chunk_size; + unsigned int cursor_buffer_size; + unsigned int max_num_wb; + unsigned int max_dchub_pscl_bw_pix_per_clk; + unsigned int max_pscl_lb_bw_pix_per_clk; + unsigned int max_lb_vscl_bw_pix_per_clk; + unsigned int max_vscl_hscl_bw_pix_per_clk; + double max_hscl_ratio; + double max_vscl_ratio; + unsigned int hscl_mults; + unsigned int vscl_mults; + unsigned int max_hscl_taps; + unsigned int max_vscl_taps; + unsigned int xfc_supported; + unsigned int ptoi_supported; + unsigned int xfc_fill_constant_bytes; + double dispclk_ramp_margin_percent; + double xfc_fill_bw_overhead_percent; + double underscan_factor; + unsigned int min_vblank_lines; + unsigned int dppclk_delay_subtotal; + unsigned int dispclk_delay_subtotal; + unsigned int dcfclk_cstate_latency; + unsigned int dppclk_delay_scl; + unsigned int dppclk_delay_scl_lb_only; + unsigned int dppclk_delay_cnvc_formatter; + unsigned int dppclk_delay_cnvc_cursor; + unsigned int is_line_buffer_bpp_fixed; + unsigned int line_buffer_fixed_bpp; + unsigned int dcc_supported; + unsigned int IsLineBufferBppFixed; unsigned int LineBufferFixedBpp; - unsigned int writeback_luma_buffer_size_kbytes; - unsigned int writeback_chroma_buffer_size_kbytes; - unsigned int max_num_dpp; - unsigned int max_num_wb; - unsigned int max_dchub_pscl_bw_pix_per_clk; - unsigned int max_pscl_lb_bw_pix_per_clk; - unsigned int max_lb_vscl_bw_pix_per_clk; - unsigned int max_vscl_hscl_bw_pix_per_clk; - double max_hscl_ratio; - double max_vscl_ratio; - unsigned int hscl_mults; - unsigned int vscl_mults; - unsigned int max_hscl_taps; - unsigned int max_vscl_taps; - double dispclk_ramp_margin_percent; - double underscan_factor; - unsigned int min_vblank_lines; - unsigned int dppclk_delay_subtotal; - unsigned int dispclk_delay_subtotal; - unsigned int dcfclk_cstate_latency; - unsigned int max_inter_dcn_tile_repeaters; unsigned int can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one; unsigned int bug_forcing_LC_req_same_size_fixed; }; -struct _vcs_dpi_display_pipe_source_params_st { - int source_format; - unsigned char dcc; - unsigned int dcc_rate; - unsigned char vm; - int source_scan; - int sw_mode; - int macro_tile_size; - unsigned char is_display_sw; - unsigned int viewport_width; - unsigned int viewport_height; - unsigned int viewport_width_c; - unsigned int viewport_height_c; - unsigned int data_pitch; - unsigned int data_pitch_c; - unsigned int meta_pitch; - unsigned int meta_pitch_c; - unsigned int cur0_src_width; - int cur0_bpp; - unsigned char is_hsplit; - unsigned int hsplit_grp; -}; - -struct _vcs_dpi_display_output_params_st { - int output_bpc; - int output_type; - int output_format; - int output_standard; -}; - -struct _vcs_dpi_display_bandwidth_st { - double total_bw_consumed_gbps; - double guaranteed_urgent_return_bw_gbps; -}; - -struct _vcs_dpi_scaler_ratio_depth_st { - double hscl_ratio; - double vscl_ratio; - double hscl_ratio_c; - double vscl_ratio_c; - double vinit; - double vinit_c; - double vinit_bot; - double vinit_bot_c; - int lb_depth; -}; - -struct _vcs_dpi_scaler_taps_st { - unsigned int htaps; - unsigned int vtaps; - unsigned int htaps_c; - unsigned int vtaps_c; -}; - -struct _vcs_dpi_display_pipe_dest_params_st { - unsigned int recout_width; - unsigned int recout_height; - unsigned int full_recout_width; - unsigned int full_recout_height; - unsigned int hblank_start; - unsigned int hblank_end; - unsigned int vblank_start; - unsigned int vblank_end; - unsigned int htotal; - unsigned int vtotal; - unsigned int vactive; - unsigned int vstartup_start; - unsigned int vupdate_offset; - unsigned int vupdate_width; - unsigned int vready_offset; - unsigned int vsync_plus_back_porch; - unsigned char interlaced; - unsigned char underscan; - double pixel_rate_mhz; - unsigned char syncronized_vblank_all_planes; -}; - -struct _vcs_dpi_display_pipe_params_st { - struct _vcs_dpi_display_pipe_source_params_st src; - struct _vcs_dpi_display_pipe_dest_params_st dest; - struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth; - struct _vcs_dpi_scaler_taps_st scale_taps; -}; - -struct _vcs_dpi_display_clocks_and_cfg_st { - int voltage; - double dppclk_mhz; - double refclk_mhz; - double dispclk_mhz; - double dcfclk_mhz; - double socclk_mhz; -}; - -struct _vcs_dpi_display_e2e_pipe_params_st { - struct _vcs_dpi_display_pipe_params_st pipe; - struct _vcs_dpi_display_output_params_st dout; - struct _vcs_dpi_display_clocks_and_cfg_st clks_cfg; -}; - -struct _vcs_dpi_dchub_buffer_sizing_st { - unsigned int swath_width_y; - unsigned int swath_height_y; - unsigned int swath_height_c; - unsigned int detail_buffer_size_y; -}; - -struct _vcs_dpi_watermarks_perf_st { - double stutter_eff_in_active_region_percent; - double urgent_latency_supported_us; - double non_urgent_latency_supported_us; - double dram_clock_change_margin_us; - double dram_access_eff_percent; -}; - -struct _vcs_dpi_cstate_pstate_watermarks_st { - double cstate_exit_us; - double cstate_enter_plus_exit_us; - double pstate_change_us; -}; - -struct _vcs_dpi_wm_calc_pipe_params_st { - unsigned int num_dpp; - int voltage; - int output_type; - double dcfclk_mhz; - double socclk_mhz; - double dppclk_mhz; - double pixclk_mhz; - unsigned char interlace_en; - unsigned char pte_enable; - unsigned char dcc_enable; - double dcc_rate; - double bytes_per_pixel_c; - double bytes_per_pixel_y; - unsigned int swath_width_y; - unsigned int swath_height_y; - unsigned int swath_height_c; - unsigned int det_buffer_size_y; - double h_ratio; - double v_ratio; - unsigned int h_taps; - unsigned int h_total; - unsigned int v_total; - unsigned int v_active; - unsigned int e2e_index; - double display_pipe_line_delivery_time; - double read_bw; - unsigned int lines_in_det_y; - unsigned int lines_in_det_y_rounded_down_to_swath; - double full_det_buffering_time; - double dcfclk_deepsleep_mhz_per_plane; -}; - -struct _vcs_dpi_vratio_pre_st { - double vratio_pre_l; - double vratio_pre_c; -}; - -struct _vcs_dpi_display_data_rq_misc_params_st { - unsigned int full_swath_bytes; - unsigned int stored_swath_bytes; - unsigned int blk256_height; - unsigned int blk256_width; - unsigned int req_height; - unsigned int req_width; -}; - -struct _vcs_dpi_display_data_rq_sizing_params_st { - unsigned int chunk_bytes; - unsigned int min_chunk_bytes; - unsigned int meta_chunk_bytes; - unsigned int min_meta_chunk_bytes; - unsigned int mpte_group_bytes; - unsigned int dpte_group_bytes; -}; - -struct _vcs_dpi_display_data_rq_dlg_params_st { - unsigned int swath_width_ub; - unsigned int swath_height; - unsigned int req_per_swath_ub; - unsigned int meta_pte_bytes_per_frame_ub; - unsigned int dpte_req_per_row_ub; - unsigned int dpte_groups_per_row_ub; - unsigned int dpte_row_height; - unsigned int dpte_bytes_per_row_ub; - unsigned int meta_chunks_per_row_ub; - unsigned int meta_req_per_row_ub; - unsigned int meta_row_height; - unsigned int meta_bytes_per_row_ub; -}; - -struct _vcs_dpi_display_cur_rq_dlg_params_st { - unsigned char enable; - unsigned int swath_height; - unsigned int req_per_line; -}; - -struct _vcs_dpi_display_rq_dlg_params_st { - struct _vcs_dpi_display_data_rq_dlg_params_st rq_l; - struct _vcs_dpi_display_data_rq_dlg_params_st rq_c; - struct _vcs_dpi_display_cur_rq_dlg_params_st rq_cur0; -}; - -struct _vcs_dpi_display_rq_sizing_params_st { - struct _vcs_dpi_display_data_rq_sizing_params_st rq_l; - struct _vcs_dpi_display_data_rq_sizing_params_st rq_c; -}; - -struct _vcs_dpi_display_rq_misc_params_st { - struct _vcs_dpi_display_data_rq_misc_params_st rq_l; - struct _vcs_dpi_display_data_rq_misc_params_st rq_c; -}; - -struct _vcs_dpi_display_rq_params_st { - unsigned char yuv420; - unsigned char yuv420_10bpc; - struct _vcs_dpi_display_rq_misc_params_st misc; - struct _vcs_dpi_display_rq_sizing_params_st sizing; - struct _vcs_dpi_display_rq_dlg_params_st dlg; -}; - -struct _vcs_dpi_display_dlg_regs_st { - unsigned int refcyc_h_blank_end; - unsigned int dlg_vblank_end; - unsigned int min_dst_y_next_start; - unsigned int refcyc_per_htotal; - unsigned int refcyc_x_after_scaler; - unsigned int dst_y_after_scaler; - unsigned int dst_y_prefetch; - unsigned int dst_y_per_vm_vblank; - unsigned int dst_y_per_row_vblank; - unsigned int ref_freq_to_pix_freq; - unsigned int vratio_prefetch; - unsigned int vratio_prefetch_c; - unsigned int refcyc_per_pte_group_vblank_l; - unsigned int refcyc_per_pte_group_vblank_c; - unsigned int refcyc_per_meta_chunk_vblank_l; - unsigned int refcyc_per_meta_chunk_vblank_c; - unsigned int dst_y_per_pte_row_nom_l; - unsigned int dst_y_per_pte_row_nom_c; - unsigned int refcyc_per_pte_group_nom_l; - unsigned int refcyc_per_pte_group_nom_c; - unsigned int dst_y_per_meta_row_nom_l; - unsigned int dst_y_per_meta_row_nom_c; - unsigned int refcyc_per_meta_chunk_nom_l; - unsigned int refcyc_per_meta_chunk_nom_c; - unsigned int refcyc_per_line_delivery_pre_l; - unsigned int refcyc_per_line_delivery_pre_c; - unsigned int refcyc_per_line_delivery_l; - unsigned int refcyc_per_line_delivery_c; - unsigned int chunk_hdl_adjust_cur0; -}; - -struct _vcs_dpi_display_ttu_regs_st { - unsigned int qos_level_low_wm; - unsigned int qos_level_high_wm; - unsigned int min_ttu_vblank; - unsigned int qos_level_flip; - unsigned int refcyc_per_req_delivery_l; - unsigned int refcyc_per_req_delivery_c; - unsigned int refcyc_per_req_delivery_cur0; - unsigned int refcyc_per_req_delivery_pre_l; - unsigned int refcyc_per_req_delivery_pre_c; - unsigned int refcyc_per_req_delivery_pre_cur0; - unsigned int qos_level_fixed_l; - unsigned int qos_level_fixed_c; - unsigned int qos_level_fixed_cur0; - unsigned int qos_ramp_disable_l; - unsigned int qos_ramp_disable_c; - unsigned int qos_ramp_disable_cur0; -}; - -struct _vcs_dpi_display_data_rq_regs_st { - unsigned int chunk_size; - unsigned int min_chunk_size; - unsigned int meta_chunk_size; - unsigned int min_meta_chunk_size; - unsigned int dpte_group_size; - unsigned int mpte_group_size; - unsigned int swath_height; - unsigned int pte_row_height_linear; -}; - -struct _vcs_dpi_display_rq_regs_st { - struct _vcs_dpi_display_data_rq_regs_st rq_regs_l; - struct _vcs_dpi_display_data_rq_regs_st rq_regs_c; - unsigned int drq_expansion_mode; - unsigned int prq_expansion_mode; - unsigned int mrq_expansion_mode; - unsigned int crq_expansion_mode; - unsigned int plane1_base_address; -}; - -struct _vcs_dpi_display_dlg_sys_params_st { - double t_mclk_wm_us; - double t_urg_wm_us; - double t_sr_wm_us; - double t_extra_us; - double t_srx_delay_us; - double deepsleep_dcfclk_mhz; - double total_flip_bw; - unsigned int total_flip_bytes; -}; - -struct _vcs_dpi_display_dlg_prefetch_param_st { - double prefetch_bw; - unsigned int flip_bytes; -}; - -struct _vcs_dpi_display_pipe_clock_st { - double dcfclk_mhz; - double dispclk_mhz; - double dppclk_mhz[4]; - unsigned char dppclk_div[4]; -}; - -struct _vcs_dpi_display_arb_params_st { - int max_req_outstanding; - int min_req_outstanding; - int sat_level_us; -}; - -struct _vcs_dpi_mode_evaluation_st { - int voltage_override; +struct _vcs_dpi_display_xfc_params_st { + double xfc_tslv_vready_offset_us; + double xfc_tslv_vupdate_width_us; + double xfc_tslv_vupdate_offset_us; + int xfc_slv_chunk_size_bytes; +}; + +struct _vcs_dpi_display_pipe_source_params_st { + int source_format; + unsigned char dcc; + unsigned int dcc_override; + unsigned int dcc_rate; + unsigned char dcc_use_global; + unsigned char vm; + unsigned char vm_levels_force_en; + unsigned int vm_levels_force; + int source_scan; + int sw_mode; + int macro_tile_size; + unsigned char is_display_sw; + unsigned int viewport_width; + unsigned int viewport_height; + unsigned int viewport_y_y; + unsigned int viewport_y_c; + unsigned int viewport_width_c; + unsigned int viewport_height_c; + unsigned int data_pitch; + unsigned int data_pitch_c; + unsigned int meta_pitch; + unsigned int meta_pitch_c; + unsigned int cur0_src_width; + int cur0_bpp; + unsigned int cur1_src_width; + int cur1_bpp; + int num_cursors; + unsigned char is_hsplit; + unsigned char dynamic_metadata_enable; + unsigned int dynamic_metadata_lines_before_active; + unsigned int dynamic_metadata_xmit_bytes; + unsigned int hsplit_grp; + unsigned char xfc_enable; + unsigned char xfc_slave; + struct _vcs_dpi_display_xfc_params_st xfc_params; +}; +struct writeback_st { + int wb_src_height; + int wb_dst_width; + int wb_dst_height; + int wb_pixel_format; + int wb_htaps_luma; + int wb_vtaps_luma; + int wb_htaps_chroma; + int wb_vtaps_chroma; + int wb_hratio; + int wb_vratio; +}; + +struct _vcs_dpi_display_output_params_st { + int dp_lanes; + int output_bpp; + int dsc_enable; + int wb_enable; + int output_bpc; + int output_type; + int output_format; + int output_standard; + int dsc_slices; + struct writeback_st wb; +}; + +struct _vcs_dpi_display_bandwidth_st { + double total_bw_consumed_gbps; + double guaranteed_urgent_return_bw_gbps; +}; + +struct _vcs_dpi_scaler_ratio_depth_st { + double hscl_ratio; + double vscl_ratio; + double hscl_ratio_c; + double vscl_ratio_c; + double vinit; + double vinit_c; + double vinit_bot; + double vinit_bot_c; + int lb_depth; + int scl_enable; +}; + +struct _vcs_dpi_scaler_taps_st { + unsigned int htaps; + unsigned int vtaps; + unsigned int htaps_c; + unsigned int vtaps_c; +}; + +struct _vcs_dpi_display_pipe_dest_params_st { + unsigned int recout_width; + unsigned int recout_height; + unsigned int full_recout_width; + unsigned int full_recout_height; + unsigned int hblank_start; + unsigned int hblank_end; + unsigned int vblank_start; + unsigned int vblank_end; + unsigned int htotal; + unsigned int vtotal; + unsigned int vactive; + unsigned int hactive; + unsigned int vstartup_start; + unsigned int vupdate_offset; + unsigned int vupdate_width; + unsigned int vready_offset; + unsigned char interlaced; + unsigned char underscan; + double pixel_rate_mhz; + unsigned char synchronized_vblank_all_planes; + unsigned char otg_inst; + unsigned char odm_split_cnt; + unsigned char odm_combine; +}; + +struct _vcs_dpi_display_pipe_params_st { + display_pipe_source_params_st src; + display_pipe_dest_params_st dest; + scaler_ratio_depth_st scale_ratio_depth; + scaler_taps_st scale_taps; +}; + +struct _vcs_dpi_display_clocks_and_cfg_st { + int voltage; + double dppclk_mhz; + double refclk_mhz; + double dispclk_mhz; + double dcfclk_mhz; + double socclk_mhz; +}; + +struct _vcs_dpi_display_e2e_pipe_params_st { + display_pipe_params_st pipe; + display_output_params_st dout; + display_clocks_and_cfg_st clks_cfg; +}; + +struct _vcs_dpi_dchub_buffer_sizing_st { + unsigned int swath_width_y; + unsigned int swath_height_y; + unsigned int swath_height_c; + unsigned int detail_buffer_size_y; +}; + +struct _vcs_dpi_watermarks_perf_st { + double stutter_eff_in_active_region_percent; + double urgent_latency_supported_us; + double non_urgent_latency_supported_us; + double dram_clock_change_margin_us; + double dram_access_eff_percent; +}; + +struct _vcs_dpi_cstate_pstate_watermarks_st { + double cstate_exit_us; + double cstate_enter_plus_exit_us; + double pstate_change_us; +}; + +struct _vcs_dpi_wm_calc_pipe_params_st { + unsigned int num_dpp; + int voltage; + int output_type; + double dcfclk_mhz; + double socclk_mhz; + double dppclk_mhz; + double pixclk_mhz; + unsigned char interlace_en; + unsigned char pte_enable; + unsigned char dcc_enable; + double dcc_rate; + double bytes_per_pixel_c; + double bytes_per_pixel_y; + unsigned int swath_width_y; + unsigned int swath_height_y; + unsigned int swath_height_c; + unsigned int det_buffer_size_y; + double h_ratio; + double v_ratio; + unsigned int h_taps; + unsigned int h_total; + unsigned int v_total; + unsigned int v_active; + unsigned int e2e_index; + double display_pipe_line_delivery_time; + double read_bw; + unsigned int lines_in_det_y; + unsigned int lines_in_det_y_rounded_down_to_swath; + double full_det_buffering_time; + double dcfclk_deepsleep_mhz_per_plane; +}; + +struct _vcs_dpi_vratio_pre_st { + double vratio_pre_l; + double vratio_pre_c; +}; + +struct _vcs_dpi_display_data_rq_misc_params_st { + unsigned int full_swath_bytes; + unsigned int stored_swath_bytes; + unsigned int blk256_height; + unsigned int blk256_width; + unsigned int req_height; + unsigned int req_width; +}; + +struct _vcs_dpi_display_data_rq_sizing_params_st { + unsigned int chunk_bytes; + unsigned int min_chunk_bytes; + unsigned int meta_chunk_bytes; + unsigned int min_meta_chunk_bytes; + unsigned int mpte_group_bytes; + unsigned int dpte_group_bytes; +}; + +struct _vcs_dpi_display_data_rq_dlg_params_st { + unsigned int swath_width_ub; + unsigned int swath_height; + unsigned int req_per_swath_ub; + unsigned int meta_pte_bytes_per_frame_ub; + unsigned int dpte_req_per_row_ub; + unsigned int dpte_groups_per_row_ub; + unsigned int dpte_row_height; + unsigned int dpte_bytes_per_row_ub; + unsigned int meta_chunks_per_row_ub; + unsigned int meta_req_per_row_ub; + unsigned int meta_row_height; + unsigned int meta_bytes_per_row_ub; +}; + +struct _vcs_dpi_display_cur_rq_dlg_params_st { + unsigned char enable; + unsigned int swath_height; + unsigned int req_per_line; +}; + +struct _vcs_dpi_display_rq_dlg_params_st { + display_data_rq_dlg_params_st rq_l; + display_data_rq_dlg_params_st rq_c; + display_cur_rq_dlg_params_st rq_cur0; +}; + +struct _vcs_dpi_display_rq_sizing_params_st { + display_data_rq_sizing_params_st rq_l; + display_data_rq_sizing_params_st rq_c; +}; + +struct _vcs_dpi_display_rq_misc_params_st { + display_data_rq_misc_params_st rq_l; + display_data_rq_misc_params_st rq_c; +}; + +struct _vcs_dpi_display_rq_params_st { + unsigned char yuv420; + unsigned char yuv420_10bpc; + display_rq_misc_params_st misc; + display_rq_sizing_params_st sizing; + display_rq_dlg_params_st dlg; +}; + +struct _vcs_dpi_display_dlg_regs_st { + unsigned int refcyc_h_blank_end; + unsigned int dlg_vblank_end; + unsigned int min_dst_y_next_start; + unsigned int refcyc_per_htotal; + unsigned int refcyc_x_after_scaler; + unsigned int dst_y_after_scaler; + unsigned int dst_y_prefetch; + unsigned int dst_y_per_vm_vblank; + unsigned int dst_y_per_row_vblank; + unsigned int dst_y_per_vm_flip; + unsigned int dst_y_per_row_flip; + unsigned int ref_freq_to_pix_freq; + unsigned int vratio_prefetch; + unsigned int vratio_prefetch_c; + unsigned int refcyc_per_pte_group_vblank_l; + unsigned int refcyc_per_pte_group_vblank_c; + unsigned int refcyc_per_meta_chunk_vblank_l; + unsigned int refcyc_per_meta_chunk_vblank_c; + unsigned int refcyc_per_pte_group_flip_l; + unsigned int refcyc_per_pte_group_flip_c; + unsigned int refcyc_per_meta_chunk_flip_l; + unsigned int refcyc_per_meta_chunk_flip_c; + unsigned int dst_y_per_pte_row_nom_l; + unsigned int dst_y_per_pte_row_nom_c; + unsigned int refcyc_per_pte_group_nom_l; + unsigned int refcyc_per_pte_group_nom_c; + unsigned int dst_y_per_meta_row_nom_l; + unsigned int dst_y_per_meta_row_nom_c; + unsigned int refcyc_per_meta_chunk_nom_l; + unsigned int refcyc_per_meta_chunk_nom_c; + unsigned int refcyc_per_line_delivery_pre_l; + unsigned int refcyc_per_line_delivery_pre_c; + unsigned int refcyc_per_line_delivery_l; + unsigned int refcyc_per_line_delivery_c; + unsigned int chunk_hdl_adjust_cur0; + unsigned int chunk_hdl_adjust_cur1; + unsigned int vready_after_vcount0; + unsigned int dst_y_offset_cur0; + unsigned int dst_y_offset_cur1; + unsigned int xfc_reg_transfer_delay; + unsigned int xfc_reg_precharge_delay; + unsigned int xfc_reg_remote_surface_flip_latency; + unsigned int xfc_reg_prefetch_margin; + unsigned int dst_y_delta_drq_limit; +}; + +struct _vcs_dpi_display_ttu_regs_st { + unsigned int qos_level_low_wm; + unsigned int qos_level_high_wm; + unsigned int min_ttu_vblank; + unsigned int qos_level_flip; + unsigned int refcyc_per_req_delivery_l; + unsigned int refcyc_per_req_delivery_c; + unsigned int refcyc_per_req_delivery_cur0; + unsigned int refcyc_per_req_delivery_cur1; + unsigned int refcyc_per_req_delivery_pre_l; + unsigned int refcyc_per_req_delivery_pre_c; + unsigned int refcyc_per_req_delivery_pre_cur0; + unsigned int refcyc_per_req_delivery_pre_cur1; + unsigned int qos_level_fixed_l; + unsigned int qos_level_fixed_c; + unsigned int qos_level_fixed_cur0; + unsigned int qos_level_fixed_cur1; + unsigned int qos_ramp_disable_l; + unsigned int qos_ramp_disable_c; + unsigned int qos_ramp_disable_cur0; + unsigned int qos_ramp_disable_cur1; +}; + +struct _vcs_dpi_display_data_rq_regs_st { + unsigned int chunk_size; + unsigned int min_chunk_size; + unsigned int meta_chunk_size; + unsigned int min_meta_chunk_size; + unsigned int dpte_group_size; + unsigned int mpte_group_size; + unsigned int swath_height; + unsigned int pte_row_height_linear; +}; + +struct _vcs_dpi_display_rq_regs_st { + display_data_rq_regs_st rq_regs_l; + display_data_rq_regs_st rq_regs_c; + unsigned int drq_expansion_mode; + unsigned int prq_expansion_mode; + unsigned int mrq_expansion_mode; + unsigned int crq_expansion_mode; + unsigned int plane1_base_address; +}; + +struct _vcs_dpi_display_dlg_sys_params_st { + double t_mclk_wm_us; + double t_urg_wm_us; + double t_sr_wm_us; + double t_extra_us; + double mem_trip_us; + double t_srx_delay_us; + double deepsleep_dcfclk_mhz; + double total_flip_bw; + unsigned int total_flip_bytes; +}; + +struct _vcs_dpi_display_dlg_prefetch_param_st { + double prefetch_bw; + unsigned int flip_bytes; +}; + +struct _vcs_dpi_display_pipe_clock_st { + double dcfclk_mhz; + double dispclk_mhz; + double socclk_mhz; + double dscclk_mhz[6]; + double dppclk_mhz[6]; +}; + +struct _vcs_dpi_display_arb_params_st { + int max_req_outstanding; + int min_req_outstanding; + int sat_level_us; }; #endif /*__DISPLAY_MODE_STRUCTS_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h deleted file mode 100644 index d4ea0371cde2..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h +++ /dev/null @@ -1,194 +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 - * - */ -#ifndef __DISPLAY_MODE_SUPPORT_H__ -#define __DISPLAY_MODE_SUPPORT_H__ - -#include "dml_common_defs.h" - -struct display_mode_lib; - -#define NumberOfStates 4 -#define NumberOfStatesPlusTwo (NumberOfStates+2) - -struct dml_ms_internal_vars { - double ScaleRatioSupport; - double SourceFormatPixelAndScanSupport; - double TotalReadBandwidthConsumedGBytePerSecond; - double TotalWriteBandwidthConsumedGBytePerSecond; - double TotalBandwidthConsumedGBytePerSecond; - double DCCEnabledInAnyPlane; - double ReturnBWToDCNPerState; - double CriticalPoint; - double WritebackLatencySupport; - double RequiredOutputBW; - double TotalNumberOfActiveWriteback; - double TotalAvailableWritebackSupport; - double MaximumSwathWidth; - double NumberOfDPPRequiredForDETSize; - double NumberOfDPPRequiredForLBSize; - double MinDispclkUsingSingleDPP; - double MinDispclkUsingDualDPP; - double ViewportSizeSupport; - double SwathWidthGranularityY; - double RoundedUpMaxSwathSizeBytesY; - double SwathWidthGranularityC; - double RoundedUpMaxSwathSizeBytesC; - double LinesInDETLuma; - double LinesInDETChroma; - double EffectiveLBLatencyHidingSourceLinesLuma; - double EffectiveLBLatencyHidingSourceLinesChroma; - double EffectiveDETLBLinesLuma; - double EffectiveDETLBLinesChroma; - double ProjectedDCFCLKDeepSleep; - double MetaReqHeightY; - double MetaReqWidthY; - double MetaSurfaceWidthY; - double MetaSurfaceHeightY; - double MetaPteBytesPerFrameY; - double MetaRowBytesY; - double MacroTileBlockSizeBytesY; - double MacroTileBlockHeightY; - double DataPTEReqHeightY; - double DataPTEReqWidthY; - double DPTEBytesPerRowY; - double MetaReqHeightC; - double MetaReqWidthC; - double MetaSurfaceWidthC; - double MetaSurfaceHeightC; - double MetaPteBytesPerFrameC; - double MetaRowBytesC; - double MacroTileBlockSizeBytesC; - double MacroTileBlockHeightC; - double MacroTileBlockWidthC; - double DataPTEReqHeightC; - double DataPTEReqWidthC; - double DPTEBytesPerRowC; - double VInitY; - double MaxPartialSwY; - double VInitC; - double MaxPartialSwC; - double dst_x_after_scaler; - double dst_y_after_scaler; - double TimeCalc; - double VUpdateOffset; - double TotalRepeaterDelay; - double VUpdateWidth; - double VReadyOffset; - double TimeSetup; - double ExtraLatency; - double MaximumVStartup; - double BWAvailableForImmediateFlip; - double TotalImmediateFlipBytes; - double TimeForMetaPTEWithImmediateFlip; - double TimeForMetaPTEWithoutImmediateFlip; - double TimeForMetaAndDPTERowWithImmediateFlip; - double TimeForMetaAndDPTERowWithoutImmediateFlip; - double LineTimesToRequestPrefetchPixelDataWithImmediateFlip; - double LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip; - double MaximumReadBandwidthWithPrefetchWithImmediateFlip; - double MaximumReadBandwidthWithPrefetchWithoutImmediateFlip; - double VoltageOverrideLevel; - double VoltageLevelWithImmediateFlip; - double VoltageLevelWithoutImmediateFlip; - double ImmediateFlipSupported; - double VoltageLevel; - double DCFCLK; - double FabricAndDRAMBandwidth; - double SwathWidthYSingleDPP[DC__NUM_PIPES__MAX]; - double BytePerPixelInDETY[DC__NUM_PIPES__MAX]; - double BytePerPixelInDETC[DC__NUM_PIPES__MAX]; - double ReadBandwidth[DC__NUM_PIPES__MAX]; - double WriteBandwidth[DC__NUM_PIPES__MAX]; - double DCFCLKPerState[NumberOfStatesPlusTwo]; - double FabricAndDRAMBandwidthPerState[NumberOfStatesPlusTwo]; - double ReturnBWPerState[NumberOfStatesPlusTwo]; - double BandwidthSupport[NumberOfStatesPlusTwo]; - double UrgentRoundTripAndOutOfOrderLatencyPerState[NumberOfStatesPlusTwo]; - double ROBSupport[NumberOfStatesPlusTwo]; - double RequiredPHYCLK[DC__NUM_PIPES__MAX]; - double DIOSupport[NumberOfStatesPlusTwo]; - double PHYCLKPerState[NumberOfStatesPlusTwo]; - double PSCL_FACTOR[DC__NUM_PIPES__MAX]; - double PSCL_FACTOR_CHROMA[DC__NUM_PIPES__MAX]; - double MinDPPCLKUsingSingleDPP[DC__NUM_PIPES__MAX]; - double Read256BlockHeightY[DC__NUM_PIPES__MAX]; - double Read256BlockWidthY[DC__NUM_PIPES__MAX]; - double Read256BlockHeightC[DC__NUM_PIPES__MAX]; - double Read256BlockWidthC[DC__NUM_PIPES__MAX]; - double MaxSwathHeightY[DC__NUM_PIPES__MAX]; - double MaxSwathHeightC[DC__NUM_PIPES__MAX]; - double MinSwathHeightY[DC__NUM_PIPES__MAX]; - double MinSwathHeightC[DC__NUM_PIPES__MAX]; - double NumberOfDPPRequiredForDETAndLBSize[DC__NUM_PIPES__MAX]; - double TotalNumberOfActiveDPP[NumberOfStatesPlusTwo * 2]; - double RequiredDISPCLK[NumberOfStatesPlusTwo * 2]; - double DISPCLK_DPPCLK_Support[NumberOfStatesPlusTwo * 2]; - double MaxDispclk[NumberOfStatesPlusTwo]; - double MaxDppclk[NumberOfStatesPlusTwo]; - double NoOfDPP[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; - double TotalAvailablePipesSupport[NumberOfStatesPlusTwo * 2]; - double SwathWidthYPerState[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; - double SwathHeightYPerState[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; - double SwathHeightCPerState[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; - double DETBufferSizeYPerState[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; - double UrgentLatencySupportUsPerState[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; - double UrgentLatencySupport[NumberOfStatesPlusTwo * 2]; - double TotalNumberOfDCCActiveDPP[NumberOfStatesPlusTwo * 2]; - double DPTEBytesPerRow[DC__NUM_PIPES__MAX]; - double MetaPTEBytesPerFrame[DC__NUM_PIPES__MAX]; - double MetaRowBytes[DC__NUM_PIPES__MAX]; - double PrefillY[DC__NUM_PIPES__MAX]; - double MaxNumSwY[DC__NUM_PIPES__MAX]; - double PrefetchLinesY[DC__NUM_PIPES__MAX]; - double PrefillC[DC__NUM_PIPES__MAX]; - double MaxNumSwC[DC__NUM_PIPES__MAX]; - double PrefetchLinesC[DC__NUM_PIPES__MAX]; - double LineTimesForPrefetch[DC__NUM_PIPES__MAX]; - double PrefetchBW[DC__NUM_PIPES__MAX]; - double LinesForMetaPTEWithImmediateFlip[DC__NUM_PIPES__MAX]; - double LinesForMetaPTEWithoutImmediateFlip[DC__NUM_PIPES__MAX]; - double LinesForMetaAndDPTERowWithImmediateFlip[DC__NUM_PIPES__MAX]; - double LinesForMetaAndDPTERowWithoutImmediateFlip[DC__NUM_PIPES__MAX]; - double VRatioPreYWithImmediateFlip[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; - double VRatioPreCWithImmediateFlip[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; - double RequiredPrefetchPixelDataBWWithImmediateFlip[NumberOfStatesPlusTwo * 2 - * DC__NUM_PIPES__MAX]; - double VRatioPreYWithoutImmediateFlip[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; - double VRatioPreCWithoutImmediateFlip[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; - double RequiredPrefetchPixelDataBWWithoutImmediateFlip[NumberOfStatesPlusTwo * 2 - * DC__NUM_PIPES__MAX]; - double PrefetchSupportedWithImmediateFlip[NumberOfStatesPlusTwo * 2]; - double PrefetchSupportedWithoutImmediateFlip[NumberOfStatesPlusTwo * 2]; - double VRatioInPrefetchSupportedWithImmediateFlip[NumberOfStatesPlusTwo * 2]; - double VRatioInPrefetchSupportedWithoutImmediateFlip[NumberOfStatesPlusTwo * 2]; - double ModeSupportWithImmediateFlip[NumberOfStatesPlusTwo * 2]; - double ModeSupportWithoutImmediateFlip[NumberOfStatesPlusTwo * 2]; - double RequiredDISPCLKPerRatio[2]; - double DPPPerPlanePerRatio[2 * DC__NUM_PIPES__MAX]; - double DISPCLK_DPPCLK_SupportPerRatio[2]; - struct _vcs_dpi_wm_calc_pipe_params_st planes[DC__NUM_PIPES__MAX]; -}; - -#endif 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 new file mode 100644 index 000000000000..ea661ee44674 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -0,0 +1,6124 @@ +/* + * 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 "display_mode_lib.h" +#include "display_mode_vba.h" + +#include "dml_inline_defs.h" + +static const unsigned int NumberOfStates = DC__VOLTAGE_STATES; + +static void fetch_socbb_params(struct display_mode_lib *mode_lib); +static void fetch_ip_params(struct display_mode_lib *mode_lib); +static void fetch_pipe_params(struct display_mode_lib *mode_lib); +static void recalculate_params( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes); +static void recalculate(struct display_mode_lib *mode_lib); +static double adjust_ReturnBW( + struct display_mode_lib *mode_lib, + double ReturnBW, + bool DCCEnabledAnyPlane, + double ReturnBandwidthToDCN); +static void ModeSupportAndSystemConfiguration(struct display_mode_lib *mode_lib); +static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib); +static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation( + struct display_mode_lib *mode_lib); +static unsigned int dscceComputeDelay( + unsigned int bpc, + double bpp, + unsigned int sliceWidth, + unsigned int numSlices, + enum output_format_class pixelFormat); +static unsigned int dscComputeDelay(enum output_format_class pixelFormat); +// Super monster function with some 45 argument +static bool CalculatePrefetchSchedule( + struct display_mode_lib *mode_lib, + double DPPCLK, + double DISPCLK, + double PixelClock, + double DCFClkDeepSleep, + unsigned int DSCDelay, + unsigned int DPPPerPlane, + bool ScalerEnabled, + unsigned int NumberOfCursors, + double DPPCLKDelaySubtotal, + double DPPCLKDelaySCL, + double DPPCLKDelaySCLLBOnly, + double DPPCLKDelayCNVCFormater, + double DPPCLKDelayCNVCCursor, + double DISPCLKDelaySubtotal, + unsigned int ScalerRecoutWidth, + enum output_format_class OutputFormat, + unsigned int VBlank, + unsigned int HTotal, + unsigned int MaxInterDCNTileRepeaters, + unsigned int VStartup, + unsigned int PageTableLevels, + bool VirtualMemoryEnable, + bool DynamicMetadataEnable, + unsigned int DynamicMetadataLinesBeforeActiveRequired, + unsigned int DynamicMetadataTransmittedBytes, + bool DCCEnable, + double UrgentLatency, + double UrgentExtraLatency, + double TCalc, + unsigned int PDEAndMetaPTEBytesFrame, + unsigned int MetaRowByte, + unsigned int PixelPTEBytesPerRow, + double PrefetchSourceLinesY, + unsigned int SwathWidthY, + double BytePerPixelDETY, + double VInitPreFillY, + unsigned int MaxNumSwathY, + double PrefetchSourceLinesC, + double BytePerPixelDETC, + double VInitPreFillC, + unsigned int MaxNumSwathC, + unsigned int SwathHeightY, + unsigned int SwathHeightC, + double TWait, + bool XFCEnabled, + double XFCRemoteSurfaceFlipDelay, + bool InterlaceEnable, + bool ProgressiveToInterlaceUnitInOPP, + double *DSTXAfterScaler, + double *DSTYAfterScaler, + double *DestinationLinesForPrefetch, + double *PrefetchBandwidth, + double *DestinationLinesToRequestVMInVBlank, + double *DestinationLinesToRequestRowInVBlank, + double *VRatioPrefetchY, + double *VRatioPrefetchC, + double *RequiredPrefetchPixDataBW, + unsigned int *VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, + double *Tno_bw, + unsigned int *VUpdateOffsetPix, + unsigned int *VUpdateWidthPix, + unsigned int *VReadyOffsetPix); +static double RoundToDFSGranularityUp(double Clock, double VCOSpeed); +static double RoundToDFSGranularityDown(double Clock, double VCOSpeed); +static double CalculatePrefetchSourceLines( + struct display_mode_lib *mode_lib, + double VRatio, + double vtaps, + bool Interlace, + bool ProgressiveToInterlaceUnitInOPP, + unsigned int SwathHeight, + unsigned int ViewportYStart, + double *VInitPreFill, + unsigned int *MaxNumSwath); +static unsigned int CalculateVMAndRowBytes( + struct display_mode_lib *mode_lib, + bool DCCEnable, + unsigned int BlockHeight256Bytes, + unsigned int BlockWidth256Bytes, + enum source_format_class SourcePixelFormat, + unsigned int SurfaceTiling, + unsigned int BytePerPixel, + enum scan_direction_class ScanDirection, + unsigned int ViewportWidth, + unsigned int ViewportHeight, + unsigned int SwathWidthY, + bool VirtualMemoryEnable, + unsigned int VMMPageSize, + unsigned int PTEBufferSizeInRequests, + unsigned int PDEProcessingBufIn64KBReqs, + unsigned int Pitch, + unsigned int DCCMetaPitch, + unsigned int *MacroTileWidth, + unsigned int *MetaRowByte, + unsigned int *PixelPTEBytesPerRow, + bool *PTEBufferSizeNotExceeded, + unsigned int *dpte_row_height, + unsigned int *meta_row_height); +static double CalculateTWait( + unsigned int PrefetchMode, + double DRAMClockChangeLatency, + double UrgentLatency, + double SREnterPlusExitTime); +static double CalculateRemoteSurfaceFlipDelay( + struct display_mode_lib *mode_lib, + double VRatio, + double SwathWidth, + double Bpp, + double LineTime, + double XFCTSlvVupdateOffset, + double XFCTSlvVupdateWidth, + double XFCTSlvVreadyOffset, + double XFCXBUFLatencyTolerance, + double XFCFillBWOverhead, + double XFCSlvChunkSize, + double XFCBusTransportTime, + double TCalc, + double TWait, + double *SrcActiveDrainRate, + double *TInitXFill, + double *TslvChk); +static double CalculateWriteBackDISPCLK( + enum source_format_class WritebackPixelFormat, + double PixelClock, + double WritebackHRatio, + double WritebackVRatio, + unsigned int WritebackLumaHTaps, + unsigned int WritebackLumaVTaps, + unsigned int WritebackChromaHTaps, + unsigned int WritebackChromaVTaps, + double WritebackDestinationWidth, + unsigned int HTotal, + unsigned int WritebackChromaLineBufferWidth); +static void CalculateActiveRowBandwidth( + bool VirtualMemoryEnable, + enum source_format_class SourcePixelFormat, + double VRatio, + bool DCCEnable, + double LineTime, + unsigned int MetaRowByteLuma, + unsigned int MetaRowByteChroma, + unsigned int meta_row_height_luma, + unsigned int meta_row_height_chroma, + unsigned int PixelPTEBytesPerRowLuma, + unsigned int PixelPTEBytesPerRowChroma, + unsigned int dpte_row_height_luma, + unsigned int dpte_row_height_chroma, + double *meta_row_bw, + double *dpte_row_bw, + double *qual_row_bw); +static void CalculateFlipSchedule( + struct display_mode_lib *mode_lib, + double UrgentExtraLatency, + double UrgentLatency, + unsigned int MaxPageTableLevels, + bool VirtualMemoryEnable, + double BandwidthAvailableForImmediateFlip, + unsigned int TotImmediateFlipBytes, + enum source_format_class SourcePixelFormat, + unsigned int ImmediateFlipBytes, + double LineTime, + double Tno_bw, + double VRatio, + double PDEAndMetaPTEBytesFrame, + unsigned int MetaRowByte, + unsigned int PixelPTEBytesPerRow, + bool DCCEnable, + unsigned int dpte_row_height, + unsigned int meta_row_height, + double qual_row_bw, + double *DestinationLinesToRequestVMInImmediateFlip, + double *DestinationLinesToRequestRowInImmediateFlip, + double *final_flip_bw, + bool *ImmediateFlipSupportedForPipe); +static double CalculateWriteBackDelay( + enum source_format_class WritebackPixelFormat, + double WritebackHRatio, + double WritebackVRatio, + unsigned int WritebackLumaHTaps, + unsigned int WritebackLumaVTaps, + unsigned int WritebackChromaHTaps, + unsigned int WritebackChromaVTaps, + unsigned int WritebackDestinationWidth); +static void PixelClockAdjustmentForProgressiveToInterlaceUnit(struct display_mode_lib *mode_lib); +static unsigned int CursorBppEnumToBits(enum cursor_bpp ebpp); +static void ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_lib); + +void set_prefetch_mode( + struct display_mode_lib *mode_lib, + bool cstate_en, + bool pstate_en, + bool ignore_viewport_pos, + bool immediate_flip_support) +{ + unsigned int prefetch_mode; + + if (cstate_en && pstate_en) + prefetch_mode = 0; + else if (cstate_en) + prefetch_mode = 1; + else + prefetch_mode = 2; + if (prefetch_mode != mode_lib->vba.PrefetchMode + || ignore_viewport_pos != mode_lib->vba.IgnoreViewportPositioning + || immediate_flip_support != mode_lib->vba.ImmediateFlipSupport) { + DTRACE( + " Prefetch mode has changed from %i to %i. Recalculating.", + prefetch_mode, + mode_lib->vba.PrefetchMode); + mode_lib->vba.PrefetchMode = prefetch_mode; + mode_lib->vba.IgnoreViewportPositioning = ignore_viewport_pos; + mode_lib->vba.ImmediateFlipSupport = immediate_flip_support; + recalculate(mode_lib); + } +} + +unsigned int dml_get_voltage_level( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) +{ + bool need_recalculate = memcmp(&mode_lib->soc, &mode_lib->vba.soc, sizeof(mode_lib->vba.soc)) != 0 + || memcmp(&mode_lib->ip, &mode_lib->vba.ip, sizeof(mode_lib->vba.ip)) != 0 + || num_pipes != mode_lib->vba.cache_num_pipes + || memcmp(pipes, mode_lib->vba.cache_pipes, + sizeof(display_e2e_pipe_params_st) * num_pipes) != 0; + + mode_lib->vba.soc = mode_lib->soc; + mode_lib->vba.ip = mode_lib->ip; + memcpy(mode_lib->vba.cache_pipes, pipes, sizeof(*pipes) * num_pipes); + mode_lib->vba.cache_num_pipes = num_pipes; + + if (need_recalculate && pipes[0].clks_cfg.dppclk_mhz != 0) + recalculate(mode_lib); + else { + fetch_socbb_params(mode_lib); + fetch_ip_params(mode_lib); + fetch_pipe_params(mode_lib); + } + ModeSupportAndSystemConfigurationFull(mode_lib); + + return mode_lib->vba.VoltageLevel; +} + +#define dml_get_attr_func(attr, var) double get_##attr(struct display_mode_lib *mode_lib, const display_e2e_pipe_params_st *pipes, unsigned int num_pipes) \ +{ \ + recalculate_params(mode_lib, pipes, num_pipes); \ + return var; \ +} + +dml_get_attr_func(clk_dcf_deepsleep, mode_lib->vba.DCFClkDeepSleep); +dml_get_attr_func(wm_urgent, mode_lib->vba.UrgentWatermark); +dml_get_attr_func(wm_memory_trip, mode_lib->vba.MemoryTripWatermark); +dml_get_attr_func(wm_writeback_urgent, mode_lib->vba.WritebackUrgentWatermark); +dml_get_attr_func(wm_stutter_exit, mode_lib->vba.StutterExitWatermark); +dml_get_attr_func(wm_stutter_enter_exit, mode_lib->vba.StutterEnterPlusExitWatermark); +dml_get_attr_func(wm_dram_clock_change, mode_lib->vba.DRAMClockChangeWatermark); +dml_get_attr_func(wm_writeback_dram_clock_change, mode_lib->vba.WritebackDRAMClockChangeWatermark); +dml_get_attr_func(wm_xfc_underflow, mode_lib->vba.UrgentWatermark); // xfc_underflow maps to urgent +dml_get_attr_func(stutter_efficiency, mode_lib->vba.StutterEfficiency); +dml_get_attr_func(stutter_efficiency_no_vblank, mode_lib->vba.StutterEfficiencyNotIncludingVBlank); +dml_get_attr_func(urgent_latency, mode_lib->vba.MinUrgentLatencySupportUs); +dml_get_attr_func(urgent_extra_latency, mode_lib->vba.UrgentExtraLatency); +dml_get_attr_func(nonurgent_latency, mode_lib->vba.NonUrgentLatencyTolerance); +dml_get_attr_func( + dram_clock_change_latency, + mode_lib->vba.MinActiveDRAMClockChangeLatencySupported); +dml_get_attr_func(dispclk_calculated, mode_lib->vba.DISPCLK_calculated); +dml_get_attr_func(total_data_read_bw, mode_lib->vba.TotalDataReadBandwidth); +dml_get_attr_func(return_bw, mode_lib->vba.ReturnBW); +dml_get_attr_func(tcalc, mode_lib->vba.TCalc); + +#define dml_get_pipe_attr_func(attr, var) double get_##attr(struct display_mode_lib *mode_lib, const display_e2e_pipe_params_st *pipes, unsigned int num_pipes, unsigned int which_pipe) \ +{\ + unsigned int which_plane; \ + recalculate_params(mode_lib, pipes, num_pipes); \ + which_plane = mode_lib->vba.pipe_plane[which_pipe]; \ + return var[which_plane]; \ +} + +dml_get_pipe_attr_func(dsc_delay, mode_lib->vba.DSCDelay); +dml_get_pipe_attr_func(dppclk_calculated, mode_lib->vba.DPPCLK_calculated); +dml_get_pipe_attr_func(dscclk_calculated, mode_lib->vba.DSCCLK_calculated); +dml_get_pipe_attr_func(min_ttu_vblank, mode_lib->vba.MinTTUVBlank); +dml_get_pipe_attr_func(vratio_prefetch_l, mode_lib->vba.VRatioPrefetchY); +dml_get_pipe_attr_func(vratio_prefetch_c, mode_lib->vba.VRatioPrefetchC); +dml_get_pipe_attr_func(dst_x_after_scaler, mode_lib->vba.DSTXAfterScaler); +dml_get_pipe_attr_func(dst_y_after_scaler, mode_lib->vba.DSTYAfterScaler); +dml_get_pipe_attr_func(dst_y_per_vm_vblank, mode_lib->vba.DestinationLinesToRequestVMInVBlank); +dml_get_pipe_attr_func(dst_y_per_row_vblank, mode_lib->vba.DestinationLinesToRequestRowInVBlank); +dml_get_pipe_attr_func(dst_y_prefetch, mode_lib->vba.DestinationLinesForPrefetch); +dml_get_pipe_attr_func(dst_y_per_vm_flip, mode_lib->vba.DestinationLinesToRequestVMInImmediateFlip); +dml_get_pipe_attr_func( + dst_y_per_row_flip, + mode_lib->vba.DestinationLinesToRequestRowInImmediateFlip); + +dml_get_pipe_attr_func(xfc_transfer_delay, mode_lib->vba.XFCTransferDelay); +dml_get_pipe_attr_func(xfc_precharge_delay, mode_lib->vba.XFCPrechargeDelay); +dml_get_pipe_attr_func(xfc_remote_surface_flip_latency, mode_lib->vba.XFCRemoteSurfaceFlipLatency); +dml_get_pipe_attr_func(xfc_prefetch_margin, mode_lib->vba.XFCPrefetchMargin); + +unsigned int get_vstartup_calculated( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes, + unsigned int which_pipe) +{ + unsigned int which_plane; + + recalculate_params(mode_lib, pipes, num_pipes); + which_plane = mode_lib->vba.pipe_plane[which_pipe]; + return mode_lib->vba.VStartup[which_plane]; +} + +double get_total_immediate_flip_bytes( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) +{ + recalculate_params(mode_lib, pipes, num_pipes); + return mode_lib->vba.TotImmediateFlipBytes; +} + +double get_total_immediate_flip_bw( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) +{ + recalculate_params(mode_lib, pipes, num_pipes); + return mode_lib->vba.ImmediateFlipBW; +} + +double get_total_prefetch_bw( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) +{ + unsigned int k; + double total_prefetch_bw = 0.0; + + recalculate_params(mode_lib, pipes, num_pipes); + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) + total_prefetch_bw += mode_lib->vba.PrefetchBandwidth[k]; + return total_prefetch_bw; +} + +static void fetch_socbb_params(struct display_mode_lib *mode_lib) +{ + soc_bounding_box_st *soc = &mode_lib->vba.soc; + unsigned int i; + + // SOC Bounding Box Parameters + mode_lib->vba.ReturnBusWidth = soc->return_bus_width_bytes; + mode_lib->vba.NumberOfChannels = soc->num_chans; + mode_lib->vba.PercentOfIdealDRAMAndFabricBWReceivedAfterUrgLatency = + soc->ideal_dram_bw_after_urgent_percent; // there's always that one bastard variable that's so long it throws everything out of alignment! + mode_lib->vba.UrgentLatency = soc->urgent_latency_us; + mode_lib->vba.RoundTripPingLatencyCycles = soc->round_trip_ping_latency_dcfclk_cycles; + mode_lib->vba.UrgentOutOfOrderReturnPerChannel = + soc->urgent_out_of_order_return_per_channel_bytes; + mode_lib->vba.WritebackLatency = soc->writeback_latency_us; + mode_lib->vba.SRExitTime = soc->sr_exit_time_us; + mode_lib->vba.SREnterPlusExitTime = soc->sr_enter_plus_exit_time_us; + mode_lib->vba.DRAMClockChangeLatency = soc->dram_clock_change_latency_us; + mode_lib->vba.Downspreading = soc->downspread_percent; + mode_lib->vba.DRAMChannelWidth = soc->dram_channel_width_bytes; // new! + mode_lib->vba.FabricDatapathToDCNDataReturn = soc->fabric_datapath_to_dcn_data_return_bytes; // new! + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading = soc->dcn_downspread_percent; // new + mode_lib->vba.DISPCLKDPPCLKVCOSpeed = soc->dispclk_dppclk_vco_speed_mhz; // new + mode_lib->vba.VMMPageSize = soc->vmm_page_size_bytes; + // Set the voltage scaling clocks as the defaults. Most of these will + // be set to different values by the test + for (i = 0; i < DC__VOLTAGE_STATES; i++) + if (soc->clock_limits[i].state == mode_lib->vba.VoltageLevel) + break; + + mode_lib->vba.DCFCLK = soc->clock_limits[i].dcfclk_mhz; + mode_lib->vba.SOCCLK = soc->clock_limits[i].socclk_mhz; + mode_lib->vba.DRAMSpeed = soc->clock_limits[i].dram_speed_mhz; + mode_lib->vba.FabricClock = soc->clock_limits[i].fabricclk_mhz; + + mode_lib->vba.XFCBusTransportTime = soc->xfc_bus_transport_time_us; + mode_lib->vba.XFCXBUFLatencyTolerance = soc->xfc_xbuf_latency_tolerance_us; + + mode_lib->vba.SupportGFX7CompatibleTilingIn32bppAnd64bpp = false; + mode_lib->vba.MaxHSCLRatio = 4; + mode_lib->vba.MaxVSCLRatio = 4; + mode_lib->vba.MaxNumWriteback = 0; /*TODO*/ + mode_lib->vba.WritebackLumaAndChromaScalingSupported = true; + mode_lib->vba.Cursor64BppSupport = true; + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.DCFCLKPerState[i] = soc->clock_limits[i].dcfclk_mhz; + mode_lib->vba.FabricClockPerState[i] = soc->clock_limits[i].fabricclk_mhz; + mode_lib->vba.SOCCLKPerState[i] = soc->clock_limits[i].socclk_mhz; + mode_lib->vba.PHYCLKPerState[i] = soc->clock_limits[i].phyclk_mhz; + mode_lib->vba.MaxDppclk[i] = soc->clock_limits[i].dppclk_mhz; + mode_lib->vba.MaxDSCCLK[i] = soc->clock_limits[i].dscclk_mhz; + mode_lib->vba.DRAMSpeedPerState[i] = soc->clock_limits[i].dram_speed_mhz; + mode_lib->vba.MaxDispclk[i] = soc->clock_limits[i].dispclk_mhz; + } +} + +static void fetch_ip_params(struct display_mode_lib *mode_lib) +{ + ip_params_st *ip = &mode_lib->vba.ip; + + // IP Parameters + mode_lib->vba.MaxNumDPP = ip->max_num_dpp; + mode_lib->vba.MaxNumOTG = ip->max_num_otg; + mode_lib->vba.CursorChunkSize = ip->cursor_chunk_size; + mode_lib->vba.CursorBufferSize = ip->cursor_buffer_size; + + mode_lib->vba.MaxDCHUBToPSCLThroughput = ip->max_dchub_pscl_bw_pix_per_clk; + mode_lib->vba.MaxPSCLToLBThroughput = ip->max_pscl_lb_bw_pix_per_clk; + mode_lib->vba.ROBBufferSizeInKByte = ip->rob_buffer_size_kbytes; + mode_lib->vba.DETBufferSizeInKByte = ip->det_buffer_size_kbytes; + mode_lib->vba.PixelChunkSizeInKByte = ip->pixel_chunk_size_kbytes; + mode_lib->vba.MetaChunkSize = ip->meta_chunk_size_kbytes; + mode_lib->vba.PTEChunkSize = ip->pte_chunk_size_kbytes; + mode_lib->vba.WritebackChunkSize = ip->writeback_chunk_size_kbytes; + mode_lib->vba.LineBufferSize = ip->line_buffer_size_bits; + mode_lib->vba.MaxLineBufferLines = ip->max_line_buffer_lines; + mode_lib->vba.PTEBufferSizeInRequests = ip->dpte_buffer_size_in_pte_reqs; + mode_lib->vba.DPPOutputBufferPixels = ip->dpp_output_buffer_pixels; + mode_lib->vba.OPPOutputBufferLines = ip->opp_output_buffer_lines; + mode_lib->vba.WritebackInterfaceLumaBufferSize = ip->writeback_luma_buffer_size_kbytes; + mode_lib->vba.WritebackInterfaceChromaBufferSize = ip->writeback_chroma_buffer_size_kbytes; + mode_lib->vba.WritebackChromaLineBufferWidth = + ip->writeback_chroma_line_buffer_width_pixels; + mode_lib->vba.MaxPageTableLevels = ip->max_page_table_levels; + mode_lib->vba.MaxInterDCNTileRepeaters = ip->max_inter_dcn_tile_repeaters; + mode_lib->vba.NumberOfDSC = ip->num_dsc; + mode_lib->vba.ODMCapability = ip->odm_capable; + mode_lib->vba.DISPCLKRampingMargin = ip->dispclk_ramp_margin_percent; + + mode_lib->vba.XFCSupported = ip->xfc_supported; + mode_lib->vba.XFCFillBWOverhead = ip->xfc_fill_bw_overhead_percent; + mode_lib->vba.XFCFillConstant = ip->xfc_fill_constant_bytes; + mode_lib->vba.DPPCLKDelaySubtotal = ip->dppclk_delay_subtotal; + mode_lib->vba.DPPCLKDelaySCL = ip->dppclk_delay_scl; + mode_lib->vba.DPPCLKDelaySCLLBOnly = ip->dppclk_delay_scl_lb_only; + mode_lib->vba.DPPCLKDelayCNVCFormater = ip->dppclk_delay_cnvc_formatter; + mode_lib->vba.DPPCLKDelayCNVCCursor = ip->dppclk_delay_cnvc_cursor; + mode_lib->vba.DISPCLKDelaySubtotal = ip->dispclk_delay_subtotal; + + mode_lib->vba.ProgressiveToInterlaceUnitInOPP = ip->ptoi_supported; + + mode_lib->vba.PDEProcessingBufIn64KBReqs = ip->pde_proc_buffer_size_64k_reqs; +} + +static void fetch_pipe_params(struct display_mode_lib *mode_lib) +{ + display_e2e_pipe_params_st *pipes = mode_lib->vba.cache_pipes; + ip_params_st *ip = &mode_lib->vba.ip; + + unsigned int OTGInstPlane[DC__NUM_DPP__MAX]; + unsigned int j, k; + bool PlaneVisited[DC__NUM_DPP__MAX]; + bool visited[DC__NUM_DPP__MAX]; + + // Convert Pipes to Planes + for (k = 0; k < mode_lib->vba.cache_num_pipes; ++k) + visited[k] = false; + + mode_lib->vba.NumberOfActivePlanes = 0; + for (j = 0; j < mode_lib->vba.cache_num_pipes; ++j) { + display_pipe_source_params_st *src = &pipes[j].pipe.src; + display_pipe_dest_params_st *dst = &pipes[j].pipe.dest; + scaler_ratio_depth_st *scl = &pipes[j].pipe.scale_ratio_depth; + scaler_taps_st *taps = &pipes[j].pipe.scale_taps; + display_output_params_st *dout = &pipes[j].dout; + display_clocks_and_cfg_st *clks = &pipes[j].clks_cfg; + + if (visited[j]) + continue; + visited[j] = true; + + mode_lib->vba.pipe_plane[j] = mode_lib->vba.NumberOfActivePlanes; + + mode_lib->vba.DPPPerPlane[mode_lib->vba.NumberOfActivePlanes] = 1; + mode_lib->vba.SourceScan[mode_lib->vba.NumberOfActivePlanes] = + (enum scan_direction_class) (src->source_scan); + mode_lib->vba.ViewportWidth[mode_lib->vba.NumberOfActivePlanes] = + src->viewport_width; + mode_lib->vba.ViewportHeight[mode_lib->vba.NumberOfActivePlanes] = + src->viewport_height; + mode_lib->vba.ViewportYStartY[mode_lib->vba.NumberOfActivePlanes] = + src->viewport_y_y; + mode_lib->vba.ViewportYStartC[mode_lib->vba.NumberOfActivePlanes] = + src->viewport_y_c; + mode_lib->vba.PitchY[mode_lib->vba.NumberOfActivePlanes] = src->data_pitch; + mode_lib->vba.PitchC[mode_lib->vba.NumberOfActivePlanes] = src->data_pitch_c; + mode_lib->vba.DCCMetaPitchY[mode_lib->vba.NumberOfActivePlanes] = src->meta_pitch; + mode_lib->vba.HRatio[mode_lib->vba.NumberOfActivePlanes] = scl->hscl_ratio; + mode_lib->vba.VRatio[mode_lib->vba.NumberOfActivePlanes] = scl->vscl_ratio; + mode_lib->vba.ScalerEnabled[mode_lib->vba.NumberOfActivePlanes] = scl->scl_enable; + mode_lib->vba.Interlace[mode_lib->vba.NumberOfActivePlanes] = dst->interlaced; + if (mode_lib->vba.Interlace[mode_lib->vba.NumberOfActivePlanes]) + mode_lib->vba.VRatio[mode_lib->vba.NumberOfActivePlanes] *= 2.0; + mode_lib->vba.htaps[mode_lib->vba.NumberOfActivePlanes] = taps->htaps; + mode_lib->vba.vtaps[mode_lib->vba.NumberOfActivePlanes] = taps->vtaps; + mode_lib->vba.HTAPsChroma[mode_lib->vba.NumberOfActivePlanes] = taps->htaps_c; + mode_lib->vba.VTAPsChroma[mode_lib->vba.NumberOfActivePlanes] = taps->vtaps_c; + mode_lib->vba.HTotal[mode_lib->vba.NumberOfActivePlanes] = dst->htotal; + mode_lib->vba.VTotal[mode_lib->vba.NumberOfActivePlanes] = dst->vtotal; + mode_lib->vba.DCCEnable[mode_lib->vba.NumberOfActivePlanes] = + src->dcc_use_global ? + ip->dcc_supported : src->dcc && ip->dcc_supported; + mode_lib->vba.DCCRate[mode_lib->vba.NumberOfActivePlanes] = src->dcc_rate; + mode_lib->vba.SourcePixelFormat[mode_lib->vba.NumberOfActivePlanes] = + (enum source_format_class) (src->source_format); + mode_lib->vba.HActive[mode_lib->vba.NumberOfActivePlanes] = dst->hactive; + mode_lib->vba.VActive[mode_lib->vba.NumberOfActivePlanes] = dst->vactive; + mode_lib->vba.SurfaceTiling[mode_lib->vba.NumberOfActivePlanes] = + (enum dm_swizzle_mode) (src->sw_mode); + mode_lib->vba.ScalerRecoutWidth[mode_lib->vba.NumberOfActivePlanes] = + dst->recout_width; // TODO: or should this be full_recout_width???...maybe only when in hsplit mode? + mode_lib->vba.ODMCombineEnabled[mode_lib->vba.NumberOfActivePlanes] = + dst->odm_combine; + mode_lib->vba.OutputFormat[mode_lib->vba.NumberOfActivePlanes] = + (enum output_format_class) (dout->output_format); + mode_lib->vba.Output[mode_lib->vba.NumberOfActivePlanes] = + (enum output_encoder_class) (dout->output_type); + mode_lib->vba.OutputBpp[mode_lib->vba.NumberOfActivePlanes] = dout->output_bpp; + mode_lib->vba.OutputLinkDPLanes[mode_lib->vba.NumberOfActivePlanes] = + dout->dp_lanes; + mode_lib->vba.DSCEnabled[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_enable; + mode_lib->vba.NumberOfDSCSlices[mode_lib->vba.NumberOfActivePlanes] = + dout->dsc_slices; + mode_lib->vba.DSCInputBitPerComponent[mode_lib->vba.NumberOfActivePlanes] = + dout->output_bpc == 0 ? 12 : dout->output_bpc; + mode_lib->vba.WritebackEnable[mode_lib->vba.NumberOfActivePlanes] = dout->wb_enable; + mode_lib->vba.WritebackSourceHeight[mode_lib->vba.NumberOfActivePlanes] = + dout->wb.wb_src_height; + mode_lib->vba.WritebackDestinationWidth[mode_lib->vba.NumberOfActivePlanes] = + dout->wb.wb_dst_width; + mode_lib->vba.WritebackDestinationHeight[mode_lib->vba.NumberOfActivePlanes] = + dout->wb.wb_dst_height; + mode_lib->vba.WritebackPixelFormat[mode_lib->vba.NumberOfActivePlanes] = + (enum source_format_class) (dout->wb.wb_pixel_format); + mode_lib->vba.WritebackLumaHTaps[mode_lib->vba.NumberOfActivePlanes] = + dout->wb.wb_htaps_luma; + mode_lib->vba.WritebackLumaVTaps[mode_lib->vba.NumberOfActivePlanes] = + dout->wb.wb_vtaps_luma; + mode_lib->vba.WritebackChromaHTaps[mode_lib->vba.NumberOfActivePlanes] = + dout->wb.wb_htaps_chroma; + mode_lib->vba.WritebackChromaVTaps[mode_lib->vba.NumberOfActivePlanes] = + dout->wb.wb_vtaps_chroma; + mode_lib->vba.WritebackHRatio[mode_lib->vba.NumberOfActivePlanes] = + dout->wb.wb_hratio; + mode_lib->vba.WritebackVRatio[mode_lib->vba.NumberOfActivePlanes] = + dout->wb.wb_vratio; + + mode_lib->vba.DynamicMetadataEnable[mode_lib->vba.NumberOfActivePlanes] = + src->dynamic_metadata_enable; + mode_lib->vba.DynamicMetadataLinesBeforeActiveRequired[mode_lib->vba.NumberOfActivePlanes] = + src->dynamic_metadata_lines_before_active; + mode_lib->vba.DynamicMetadataTransmittedBytes[mode_lib->vba.NumberOfActivePlanes] = + src->dynamic_metadata_xmit_bytes; + + mode_lib->vba.XFCEnabled[mode_lib->vba.NumberOfActivePlanes] = src->xfc_enable + && ip->xfc_supported; + mode_lib->vba.XFCSlvChunkSize = src->xfc_params.xfc_slv_chunk_size_bytes; + mode_lib->vba.XFCTSlvVupdateOffset = src->xfc_params.xfc_tslv_vupdate_offset_us; + mode_lib->vba.XFCTSlvVupdateWidth = src->xfc_params.xfc_tslv_vupdate_width_us; + mode_lib->vba.XFCTSlvVreadyOffset = src->xfc_params.xfc_tslv_vready_offset_us; + mode_lib->vba.PixelClock[mode_lib->vba.NumberOfActivePlanes] = dst->pixel_rate_mhz; + mode_lib->vba.DPPCLK[mode_lib->vba.NumberOfActivePlanes] = clks->dppclk_mhz; + if (ip->is_line_buffer_bpp_fixed) + mode_lib->vba.LBBitPerPixel[mode_lib->vba.NumberOfActivePlanes] = + ip->line_buffer_fixed_bpp; + else { + unsigned int lb_depth; + + switch (scl->lb_depth) { + case dm_lb_6: + lb_depth = 18; + break; + case dm_lb_8: + lb_depth = 24; + break; + case dm_lb_10: + lb_depth = 30; + break; + case dm_lb_12: + lb_depth = 36; + break; + case dm_lb_16: + lb_depth = 48; + break; + default: + lb_depth = 36; + } + mode_lib->vba.LBBitPerPixel[mode_lib->vba.NumberOfActivePlanes] = lb_depth; + } + mode_lib->vba.NumberOfCursors[mode_lib->vba.NumberOfActivePlanes] = 0; + // The DML spreadsheet assumes that the two cursors utilize the same amount of bandwidth. We'll + // calculate things a little more accurately + for (k = 0; k < DC__NUM_CURSOR__MAX; ++k) { + switch (k) { + case 0: + mode_lib->vba.CursorBPP[mode_lib->vba.NumberOfActivePlanes][0] = + CursorBppEnumToBits( + (enum cursor_bpp) (src->cur0_bpp)); + mode_lib->vba.CursorWidth[mode_lib->vba.NumberOfActivePlanes][0] = + src->cur0_src_width; + if (src->cur0_src_width > 0) + mode_lib->vba.NumberOfCursors[mode_lib->vba.NumberOfActivePlanes]++; + break; + case 1: + mode_lib->vba.CursorBPP[mode_lib->vba.NumberOfActivePlanes][1] = + CursorBppEnumToBits( + (enum cursor_bpp) (src->cur1_bpp)); + mode_lib->vba.CursorWidth[mode_lib->vba.NumberOfActivePlanes][1] = + src->cur1_src_width; + if (src->cur1_src_width > 0) + mode_lib->vba.NumberOfCursors[mode_lib->vba.NumberOfActivePlanes]++; + break; + default: + dml_print( + "ERROR: Number of cursors specified exceeds supported maximum\n") + ; + } + } + + OTGInstPlane[mode_lib->vba.NumberOfActivePlanes] = dst->otg_inst; + + if (dst->odm_combine && !src->is_hsplit) + dml_print( + "ERROR: ODM Combine is specified but is_hsplit has not be specified for pipe %i\n", + j); + + if (src->is_hsplit) { + for (k = j + 1; k < mode_lib->vba.cache_num_pipes; ++k) { + display_pipe_source_params_st *src_k = &pipes[k].pipe.src; + display_output_params_st *dout_k = &pipes[k].dout; + + if (src_k->is_hsplit && !visited[k] + && src->hsplit_grp == src_k->hsplit_grp) { + mode_lib->vba.pipe_plane[k] = + mode_lib->vba.NumberOfActivePlanes; + mode_lib->vba.DPPPerPlane[mode_lib->vba.NumberOfActivePlanes]++; + if (mode_lib->vba.SourceScan[mode_lib->vba.NumberOfActivePlanes] + == dm_horz) + mode_lib->vba.ViewportWidth[mode_lib->vba.NumberOfActivePlanes] += + src_k->viewport_width; + else + mode_lib->vba.ViewportHeight[mode_lib->vba.NumberOfActivePlanes] += + src_k->viewport_height; + + mode_lib->vba.NumberOfDSCSlices[mode_lib->vba.NumberOfActivePlanes] += + dout_k->dsc_slices; + visited[k] = true; + } + } + } + + mode_lib->vba.NumberOfActivePlanes++; + } + + // handle overlays through dml_ml->vba.BlendingAndTiming + // dml_ml->vba.BlendingAndTiming tells you which instance to look at to get timing, the so called 'master' + + for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) + PlaneVisited[j] = false; + + for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) { + for (k = j + 1; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (!PlaneVisited[k] && OTGInstPlane[j] == OTGInstPlane[k]) { + // doesn't matter, so choose the smaller one + mode_lib->vba.BlendingAndTiming[j] = j; + PlaneVisited[j] = true; + mode_lib->vba.BlendingAndTiming[k] = j; + PlaneVisited[k] = true; + } + } + + if (!PlaneVisited[j]) { + mode_lib->vba.BlendingAndTiming[j] = j; + PlaneVisited[j] = true; + } + } + + // TODO: dml_ml->vba.ODMCombineEnabled => 2 * dml_ml->vba.DPPPerPlane...actually maybe not since all pipes are specified + // Do we want the dscclk to automatically be halved? Guess not since the value is specified + + mode_lib->vba.SynchronizedVBlank = pipes[0].pipe.dest.synchronized_vblank_all_planes; + for (k = 1; k < mode_lib->vba.cache_num_pipes; ++k) + ASSERT(mode_lib->vba.SynchronizedVBlank == pipes[k].pipe.dest.synchronized_vblank_all_planes); + + mode_lib->vba.VirtualMemoryEnable = false; + mode_lib->vba.OverridePageTableLevels = 0; + + for (k = 0; k < mode_lib->vba.cache_num_pipes; ++k) { + mode_lib->vba.VirtualMemoryEnable = mode_lib->vba.VirtualMemoryEnable + || !!pipes[k].pipe.src.vm; + mode_lib->vba.OverridePageTableLevels = + (pipes[k].pipe.src.vm_levels_force_en + && mode_lib->vba.OverridePageTableLevels + < pipes[k].pipe.src.vm_levels_force) ? + pipes[k].pipe.src.vm_levels_force : + mode_lib->vba.OverridePageTableLevels; + } + + if (mode_lib->vba.OverridePageTableLevels) + mode_lib->vba.MaxPageTableLevels = mode_lib->vba.OverridePageTableLevels; + + mode_lib->vba.VirtualMemoryEnable = mode_lib->vba.VirtualMemoryEnable && !!ip->pte_enable; + + mode_lib->vba.FabricAndDRAMBandwidth = dml_min( + mode_lib->vba.DRAMSpeed * mode_lib->vba.NumberOfChannels + * mode_lib->vba.DRAMChannelWidth, + mode_lib->vba.FabricClock * mode_lib->vba.FabricDatapathToDCNDataReturn) + / 1000.0; + + // TODO: Must be consistent across all pipes + // DCCProgrammingAssumesScanDirectionUnknown = src.dcc_scan_dir_unknown; +} + +static void recalculate(struct display_mode_lib *mode_lib) +{ + ModeSupportAndSystemConfiguration(mode_lib); + PixelClockAdjustmentForProgressiveToInterlaceUnit(mode_lib); + DisplayPipeConfiguration(mode_lib); + DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation(mode_lib); +} + +// in wm mode we pull the parameters needed from the display_e2e_pipe_params_st structs +// rather than working them out as in recalculate_ms +static void recalculate_params( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) +{ + // This is only safe to use memcmp because there are non-POD types in struct display_mode_lib + if (memcmp(&mode_lib->soc, &mode_lib->vba.soc, sizeof(mode_lib->vba.soc)) != 0 + || memcmp(&mode_lib->ip, &mode_lib->vba.ip, sizeof(mode_lib->vba.ip)) != 0 + || num_pipes != mode_lib->vba.cache_num_pipes + || memcmp( + pipes, + mode_lib->vba.cache_pipes, + sizeof(display_e2e_pipe_params_st) * num_pipes) != 0) { + mode_lib->vba.soc = mode_lib->soc; + mode_lib->vba.ip = mode_lib->ip; + memcpy(mode_lib->vba.cache_pipes, pipes, sizeof(*pipes) * num_pipes); + mode_lib->vba.cache_num_pipes = num_pipes; + recalculate(mode_lib); + } +} + +static void ModeSupportAndSystemConfiguration(struct display_mode_lib *mode_lib) +{ + soc_bounding_box_st *soc = &mode_lib->vba.soc; + unsigned int i, k; + unsigned int total_pipes = 0; + + mode_lib->vba.VoltageLevel = mode_lib->vba.cache_pipes[0].clks_cfg.voltage; + for (i = 1; i < mode_lib->vba.cache_num_pipes; ++i) + ASSERT(mode_lib->vba.VoltageLevel == -1 || mode_lib->vba.VoltageLevel == mode_lib->vba.cache_pipes[i].clks_cfg.voltage); + + mode_lib->vba.DCFCLK = mode_lib->vba.cache_pipes[0].clks_cfg.dcfclk_mhz; + mode_lib->vba.SOCCLK = mode_lib->vba.cache_pipes[0].clks_cfg.socclk_mhz; + + if (mode_lib->vba.cache_pipes[0].clks_cfg.dispclk_mhz > 0.0) + mode_lib->vba.DISPCLK = mode_lib->vba.cache_pipes[0].clks_cfg.dispclk_mhz; + else + mode_lib->vba.DISPCLK = soc->clock_limits[mode_lib->vba.VoltageLevel].dispclk_mhz; + + fetch_socbb_params(mode_lib); + fetch_ip_params(mode_lib); + fetch_pipe_params(mode_lib); + + // Total Available Pipes Support Check + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) + total_pipes += mode_lib->vba.DPPPerPlane[k]; + ASSERT(total_pipes <= DC__NUM_DPP__MAX); +} + +static double adjust_ReturnBW( + struct display_mode_lib *mode_lib, + double ReturnBW, + bool DCCEnabledAnyPlane, + double ReturnBandwidthToDCN) +{ + double CriticalCompression; + + if (DCCEnabledAnyPlane + && ReturnBandwidthToDCN + > mode_lib->vba.DCFCLK * mode_lib->vba.ReturnBusWidth / 4.0) + ReturnBW = + dml_min( + ReturnBW, + ReturnBandwidthToDCN * 4 + * (1.0 + - mode_lib->vba.UrgentLatency + / ((mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024 + / ReturnBandwidthToDCN + - mode_lib->vba.DCFCLK + * mode_lib->vba.ReturnBusWidth + / 4) + + mode_lib->vba.UrgentLatency)); + + CriticalCompression = 2.0 * mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLK + * mode_lib->vba.UrgentLatency + / (ReturnBandwidthToDCN * mode_lib->vba.UrgentLatency + + (mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024); + + if (DCCEnabledAnyPlane && CriticalCompression > 1.0 && CriticalCompression < 4.0) + ReturnBW = + dml_min( + ReturnBW, + 4.0 * ReturnBandwidthToDCN + * (mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024 + * mode_lib->vba.ReturnBusWidth + * mode_lib->vba.DCFCLK + * mode_lib->vba.UrgentLatency + / dml_pow( + (ReturnBandwidthToDCN + * mode_lib->vba.UrgentLatency + + (mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024), + 2)); + + return ReturnBW; +} + +static unsigned int dscceComputeDelay( + unsigned int bpc, + double bpp, + unsigned int sliceWidth, + unsigned int numSlices, + enum output_format_class pixelFormat) +{ + // valid bpc = source bits per component in the set of {8, 10, 12} + // valid bpp = increments of 1/16 of a bit + // min = 6/7/8 in N420/N422/444, respectively + // max = such that compression is 1:1 + //valid sliceWidth = number of pixels per slice line, must be less than or equal to 5184/numSlices (or 4096/numSlices in 420 mode) + //valid numSlices = number of slices in the horiziontal direction per DSC engine in the set of {1, 2, 3, 4} + //valid pixelFormat = pixel/color format in the set of {:N444_RGB, :S422, :N422, :N420} + + // fixed value + unsigned int rcModelSize = 8192; + + // N422/N420 operate at 2 pixels per clock + unsigned int pixelsPerClock, lstall, D, initalXmitDelay, w, s, ix, wx, p, l0, a, ax, l, + Delay, pixels; + + if (pixelFormat == dm_n422 || pixelFormat == dm_420) + pixelsPerClock = 2; + // #all other modes operate at 1 pixel per clock + else + pixelsPerClock = 1; + + //initial transmit delay as per PPS + initalXmitDelay = dml_round(rcModelSize / 2.0 / bpp / pixelsPerClock); + + //compute ssm delay + if (bpc == 8) + D = 81; + else if (bpc == 10) + D = 89; + else + D = 113; + + //divide by pixel per cycle to compute slice width as seen by DSC + w = sliceWidth / pixelsPerClock; + + //422 mode has an additional cycle of delay + if (pixelFormat == dm_s422) + s = 1; + else + s = 0; + + //main calculation for the dscce + ix = initalXmitDelay + 45; + wx = (w + 2) / 3; + p = 3 * wx - w; + l0 = ix / w; + a = ix + p * l0; + ax = (a + 2) / 3 + D + 6 + 1; + l = (ax + wx - 1) / wx; + if ((ix % w) == 0 && p != 0) + lstall = 1; + else + lstall = 0; + Delay = l * wx * (numSlices - 1) + ax + s + lstall + 22; + + //dsc processes 3 pixel containers per cycle and a container can contain 1 or 2 pixels + pixels = Delay * 3 * pixelsPerClock; + return pixels; +} + +static unsigned int dscComputeDelay(enum output_format_class pixelFormat) +{ + unsigned int Delay = 0; + + if (pixelFormat == dm_420) { + // sfr + Delay = Delay + 2; + // dsccif + Delay = Delay + 0; + // dscc - input deserializer + Delay = Delay + 3; + // dscc gets pixels every other cycle + Delay = Delay + 2; + // dscc - input cdc fifo + Delay = Delay + 12; + // dscc gets pixels every other cycle + Delay = Delay + 13; + // dscc - cdc uncertainty + Delay = Delay + 2; + // dscc - output cdc fifo + Delay = Delay + 7; + // dscc gets pixels every other cycle + Delay = Delay + 3; + // dscc - cdc uncertainty + Delay = Delay + 2; + // dscc - output serializer + Delay = Delay + 1; + // sft + Delay = Delay + 1; + } else if (pixelFormat == dm_n422) { + // sfr + Delay = Delay + 2; + // dsccif + Delay = Delay + 1; + // dscc - input deserializer + Delay = Delay + 5; + // dscc - input cdc fifo + Delay = Delay + 25; + // dscc - cdc uncertainty + Delay = Delay + 2; + // dscc - output cdc fifo + Delay = Delay + 10; + // dscc - cdc uncertainty + Delay = Delay + 2; + // dscc - output serializer + Delay = Delay + 1; + // sft + Delay = Delay + 1; + } else { + // sfr + Delay = Delay + 2; + // dsccif + Delay = Delay + 0; + // dscc - input deserializer + Delay = Delay + 3; + // dscc - input cdc fifo + Delay = Delay + 12; + // dscc - cdc uncertainty + Delay = Delay + 2; + // dscc - output cdc fifo + Delay = Delay + 7; + // dscc - output serializer + Delay = Delay + 1; + // dscc - cdc uncertainty + Delay = Delay + 2; + // sft + Delay = Delay + 1; + } + + return Delay; +} + +static bool CalculatePrefetchSchedule( + struct display_mode_lib *mode_lib, + double DPPCLK, + double DISPCLK, + double PixelClock, + double DCFClkDeepSleep, + unsigned int DSCDelay, + unsigned int DPPPerPlane, + bool ScalerEnabled, + unsigned int NumberOfCursors, + double DPPCLKDelaySubtotal, + double DPPCLKDelaySCL, + double DPPCLKDelaySCLLBOnly, + double DPPCLKDelayCNVCFormater, + double DPPCLKDelayCNVCCursor, + double DISPCLKDelaySubtotal, + unsigned int ScalerRecoutWidth, + enum output_format_class OutputFormat, + unsigned int VBlank, + unsigned int HTotal, + unsigned int MaxInterDCNTileRepeaters, + unsigned int VStartup, + unsigned int PageTableLevels, + bool VirtualMemoryEnable, + bool DynamicMetadataEnable, + unsigned int DynamicMetadataLinesBeforeActiveRequired, + unsigned int DynamicMetadataTransmittedBytes, + bool DCCEnable, + double UrgentLatency, + double UrgentExtraLatency, + double TCalc, + unsigned int PDEAndMetaPTEBytesFrame, + unsigned int MetaRowByte, + unsigned int PixelPTEBytesPerRow, + double PrefetchSourceLinesY, + unsigned int SwathWidthY, + double BytePerPixelDETY, + double VInitPreFillY, + unsigned int MaxNumSwathY, + double PrefetchSourceLinesC, + double BytePerPixelDETC, + double VInitPreFillC, + unsigned int MaxNumSwathC, + unsigned int SwathHeightY, + unsigned int SwathHeightC, + double TWait, + bool XFCEnabled, + double XFCRemoteSurfaceFlipDelay, + bool InterlaceEnable, + bool ProgressiveToInterlaceUnitInOPP, + double *DSTXAfterScaler, + double *DSTYAfterScaler, + double *DestinationLinesForPrefetch, + double *PrefetchBandwidth, + double *DestinationLinesToRequestVMInVBlank, + double *DestinationLinesToRequestRowInVBlank, + double *VRatioPrefetchY, + double *VRatioPrefetchC, + double *RequiredPrefetchPixDataBW, + unsigned int *VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, + double *Tno_bw, + unsigned int *VUpdateOffsetPix, + unsigned int *VUpdateWidthPix, + unsigned int *VReadyOffsetPix) +{ + bool MyError = false; + unsigned int DPPCycles, DISPCLKCycles; + double DSTTotalPixelsAfterScaler, TotalRepeaterDelayTime; + double Tdm, LineTime, Tsetup; + double dst_y_prefetch_equ; + double Tsw_oto; + double prefetch_bw_oto; + double Tvm_oto; + double Tr0_oto; + double Tpre_oto; + double dst_y_prefetch_oto; + double TimeForFetchingMetaPTE = 0; + double TimeForFetchingRowInVBlank = 0; + double LinesToRequestPrefetchPixelData = 0; + + if (ScalerEnabled) + DPPCycles = DPPCLKDelaySubtotal + DPPCLKDelaySCL; + else + DPPCycles = DPPCLKDelaySubtotal + DPPCLKDelaySCLLBOnly; + + DPPCycles = DPPCycles + DPPCLKDelayCNVCFormater + NumberOfCursors * DPPCLKDelayCNVCCursor; + + DISPCLKCycles = DISPCLKDelaySubtotal; + + if (DPPCLK == 0.0 || DISPCLK == 0.0) + return true; + + *DSTXAfterScaler = DPPCycles * PixelClock / DPPCLK + DISPCLKCycles * PixelClock / DISPCLK + + DSCDelay; + + if (DPPPerPlane > 1) + *DSTXAfterScaler = *DSTXAfterScaler + ScalerRecoutWidth; + + if (OutputFormat == dm_420 || (InterlaceEnable && ProgressiveToInterlaceUnitInOPP)) + *DSTYAfterScaler = 1; + else + *DSTYAfterScaler = 0; + + DSTTotalPixelsAfterScaler = ((double) (*DSTYAfterScaler * HTotal)) + *DSTXAfterScaler; + *DSTYAfterScaler = dml_floor(DSTTotalPixelsAfterScaler / HTotal, 1); + *DSTXAfterScaler = DSTTotalPixelsAfterScaler - ((double) (*DSTYAfterScaler * HTotal)); + + *VUpdateOffsetPix = dml_ceil(HTotal / 4.0, 1); + TotalRepeaterDelayTime = MaxInterDCNTileRepeaters * (2.0 / DPPCLK + 3.0 / DISPCLK); + *VUpdateWidthPix = (14.0 / DCFClkDeepSleep + 12.0 / DPPCLK + TotalRepeaterDelayTime) + * PixelClock; + + *VReadyOffsetPix = dml_max( + 150.0 / DPPCLK, + TotalRepeaterDelayTime + 20.0 / DCFClkDeepSleep + 10.0 / DPPCLK) + * PixelClock; + + Tsetup = (double) (*VUpdateOffsetPix + *VUpdateWidthPix + *VReadyOffsetPix) / PixelClock; + + LineTime = (double) HTotal / PixelClock; + + if (DynamicMetadataEnable) { + double Tdmbf, Tdmec, Tdmsks; + + Tdm = dml_max(0.0, UrgentExtraLatency - TCalc); + Tdmbf = DynamicMetadataTransmittedBytes / 4.0 / DISPCLK; + Tdmec = LineTime; + if (DynamicMetadataLinesBeforeActiveRequired == 0) + Tdmsks = VBlank * LineTime / 2.0; + else + Tdmsks = DynamicMetadataLinesBeforeActiveRequired * LineTime; + if (InterlaceEnable && !ProgressiveToInterlaceUnitInOPP) + Tdmsks = Tdmsks / 2; + if (VStartup * LineTime + < Tsetup + TWait + UrgentExtraLatency + Tdmbf + Tdmec + Tdmsks) { + MyError = true; + *VStartupRequiredWhenNotEnoughTimeForDynamicMetadata = (Tsetup + TWait + + UrgentExtraLatency + Tdmbf + Tdmec + Tdmsks) / LineTime; + } else + *VStartupRequiredWhenNotEnoughTimeForDynamicMetadata = 0.0; + } else + Tdm = 0; + + if (VirtualMemoryEnable) { + if (PageTableLevels == 4) + *Tno_bw = UrgentExtraLatency + UrgentLatency; + else if (PageTableLevels == 3) + *Tno_bw = UrgentExtraLatency; + else + *Tno_bw = 0; + } else if (DCCEnable) + *Tno_bw = LineTime; + else + *Tno_bw = LineTime / 4; + + dst_y_prefetch_equ = VStartup - dml_max(TCalc + TWait, XFCRemoteSurfaceFlipDelay) / LineTime + - (Tsetup + Tdm) / LineTime + - (*DSTYAfterScaler + *DSTXAfterScaler / HTotal); + + Tsw_oto = dml_max(PrefetchSourceLinesY, PrefetchSourceLinesC) * LineTime; + + prefetch_bw_oto = (MetaRowByte + PixelPTEBytesPerRow + + PrefetchSourceLinesY * SwathWidthY * dml_ceil(BytePerPixelDETY, 1) + + PrefetchSourceLinesC * SwathWidthY / 2 * dml_ceil(BytePerPixelDETC, 2)) + / Tsw_oto; + + if (VirtualMemoryEnable == true) { + Tvm_oto = + dml_max( + *Tno_bw + PDEAndMetaPTEBytesFrame / prefetch_bw_oto, + dml_max( + UrgentExtraLatency + + UrgentLatency + * (PageTableLevels + - 1), + LineTime / 4.0)); + } else + Tvm_oto = LineTime / 4.0; + + if ((VirtualMemoryEnable == true || DCCEnable == true)) { + Tr0_oto = dml_max( + (MetaRowByte + PixelPTEBytesPerRow) / prefetch_bw_oto, + dml_max(UrgentLatency, dml_max(LineTime - Tvm_oto, LineTime / 4))); + } else + Tr0_oto = LineTime - Tvm_oto; + + Tpre_oto = Tvm_oto + Tr0_oto + Tsw_oto; + + dst_y_prefetch_oto = Tpre_oto / LineTime; + + if (dst_y_prefetch_oto < dst_y_prefetch_equ) + *DestinationLinesForPrefetch = dst_y_prefetch_oto; + else + *DestinationLinesForPrefetch = dst_y_prefetch_equ; + + *DestinationLinesForPrefetch = dml_floor(4.0 * (*DestinationLinesForPrefetch + 0.125), 1) + / 4; + + dml_print("DML: VStartup: %d\n", VStartup); + dml_print("DML: TCalc: %f\n", TCalc); + dml_print("DML: TWait: %f\n", TWait); + dml_print("DML: XFCRemoteSurfaceFlipDelay: %f\n", XFCRemoteSurfaceFlipDelay); + dml_print("DML: LineTime: %f\n", LineTime); + dml_print("DML: Tsetup: %f\n", Tsetup); + dml_print("DML: Tdm: %f\n", Tdm); + dml_print("DML: DSTYAfterScaler: %f\n", *DSTYAfterScaler); + dml_print("DML: DSTXAfterScaler: %f\n", *DSTXAfterScaler); + dml_print("DML: HTotal: %d\n", HTotal); + + *PrefetchBandwidth = 0; + *DestinationLinesToRequestVMInVBlank = 0; + *DestinationLinesToRequestRowInVBlank = 0; + *VRatioPrefetchY = 0; + *VRatioPrefetchC = 0; + *RequiredPrefetchPixDataBW = 0; + if (*DestinationLinesForPrefetch > 1) { + *PrefetchBandwidth = (PDEAndMetaPTEBytesFrame + 2 * MetaRowByte + + 2 * PixelPTEBytesPerRow + + PrefetchSourceLinesY * SwathWidthY * dml_ceil(BytePerPixelDETY, 1) + + PrefetchSourceLinesC * SwathWidthY / 2 + * dml_ceil(BytePerPixelDETC, 2)) + / (*DestinationLinesForPrefetch * LineTime - *Tno_bw); + if (VirtualMemoryEnable) { + TimeForFetchingMetaPTE = + dml_max( + *Tno_bw + + (double) PDEAndMetaPTEBytesFrame + / *PrefetchBandwidth, + dml_max( + UrgentExtraLatency + + UrgentLatency + * (PageTableLevels + - 1), + LineTime / 4)); + } else { + if (NumberOfCursors > 0 || XFCEnabled) + TimeForFetchingMetaPTE = LineTime / 4; + else + TimeForFetchingMetaPTE = 0.0; + } + + if ((VirtualMemoryEnable == true || DCCEnable == true)) { + TimeForFetchingRowInVBlank = + dml_max( + (MetaRowByte + PixelPTEBytesPerRow) + / *PrefetchBandwidth, + dml_max( + UrgentLatency, + dml_max( + LineTime + - TimeForFetchingMetaPTE, + LineTime + / 4.0))); + } else { + if (NumberOfCursors > 0 || XFCEnabled) + TimeForFetchingRowInVBlank = LineTime - TimeForFetchingMetaPTE; + else + TimeForFetchingRowInVBlank = 0.0; + } + + *DestinationLinesToRequestVMInVBlank = dml_floor( + 4.0 * (TimeForFetchingMetaPTE / LineTime + 0.125), + 1) / 4.0; + + *DestinationLinesToRequestRowInVBlank = dml_floor( + 4.0 * (TimeForFetchingRowInVBlank / LineTime + 0.125), + 1) / 4.0; + + LinesToRequestPrefetchPixelData = + *DestinationLinesForPrefetch + - ((NumberOfCursors > 0 || VirtualMemoryEnable + || DCCEnable) ? + (*DestinationLinesToRequestVMInVBlank + + *DestinationLinesToRequestRowInVBlank) : + 0.0); + + if (LinesToRequestPrefetchPixelData > 0) { + + *VRatioPrefetchY = (double) PrefetchSourceLinesY + / LinesToRequestPrefetchPixelData; + *VRatioPrefetchY = dml_max(*VRatioPrefetchY, 1.0); + if ((SwathHeightY > 4) && (VInitPreFillY > 3)) { + if (LinesToRequestPrefetchPixelData > (VInitPreFillY - 3.0) / 2.0) { + *VRatioPrefetchY = + dml_max( + (double) PrefetchSourceLinesY + / LinesToRequestPrefetchPixelData, + (double) MaxNumSwathY + * SwathHeightY + / (LinesToRequestPrefetchPixelData + - (VInitPreFillY + - 3.0) + / 2.0)); + *VRatioPrefetchY = dml_max(*VRatioPrefetchY, 1.0); + } else { + MyError = true; + *VRatioPrefetchY = 0; + } + } + + *VRatioPrefetchC = (double) PrefetchSourceLinesC + / LinesToRequestPrefetchPixelData; + *VRatioPrefetchC = dml_max(*VRatioPrefetchC, 1.0); + + if ((SwathHeightC > 4)) { + if (LinesToRequestPrefetchPixelData > (VInitPreFillC - 3.0) / 2.0) { + *VRatioPrefetchC = + dml_max( + *VRatioPrefetchC, + (double) MaxNumSwathC + * SwathHeightC + / (LinesToRequestPrefetchPixelData + - (VInitPreFillC + - 3.0) + / 2.0)); + *VRatioPrefetchC = dml_max(*VRatioPrefetchC, 1.0); + } else { + MyError = true; + *VRatioPrefetchC = 0; + } + } + + *RequiredPrefetchPixDataBW = + DPPPerPlane + * ((double) PrefetchSourceLinesY + / LinesToRequestPrefetchPixelData + * dml_ceil( + BytePerPixelDETY, + 1) + + (double) PrefetchSourceLinesC + / LinesToRequestPrefetchPixelData + * dml_ceil( + BytePerPixelDETC, + 2) + / 2) + * SwathWidthY / LineTime; + } else { + MyError = true; + *VRatioPrefetchY = 0; + *VRatioPrefetchC = 0; + *RequiredPrefetchPixDataBW = 0; + } + + } else { + MyError = true; + } + + if (MyError) { + *PrefetchBandwidth = 0; + TimeForFetchingMetaPTE = 0; + TimeForFetchingRowInVBlank = 0; + *DestinationLinesToRequestVMInVBlank = 0; + *DestinationLinesToRequestRowInVBlank = 0; + *DestinationLinesForPrefetch = 0; + LinesToRequestPrefetchPixelData = 0; + *VRatioPrefetchY = 0; + *VRatioPrefetchC = 0; + *RequiredPrefetchPixDataBW = 0; + } + + return MyError; +} + +static double RoundToDFSGranularityUp(double Clock, double VCOSpeed) +{ + return VCOSpeed * 4 / dml_floor(VCOSpeed * 4 / Clock, 1); +} + +static double RoundToDFSGranularityDown(double Clock, double VCOSpeed) +{ + return VCOSpeed * 4 / dml_ceil(VCOSpeed * 4 / Clock, 1); +} + +static double CalculatePrefetchSourceLines( + struct display_mode_lib *mode_lib, + double VRatio, + double vtaps, + bool Interlace, + bool ProgressiveToInterlaceUnitInOPP, + unsigned int SwathHeight, + unsigned int ViewportYStart, + double *VInitPreFill, + unsigned int *MaxNumSwath) +{ + unsigned int MaxPartialSwath; + + if (ProgressiveToInterlaceUnitInOPP) + *VInitPreFill = dml_floor((VRatio + vtaps + 1) / 2.0, 1); + else + *VInitPreFill = dml_floor((VRatio + vtaps + 1 + Interlace * 0.5 * VRatio) / 2.0, 1); + + if (!mode_lib->vba.IgnoreViewportPositioning) { + + *MaxNumSwath = dml_ceil((*VInitPreFill - 1.0) / SwathHeight, 1) + 1.0; + + if (*VInitPreFill > 1.0) + MaxPartialSwath = (unsigned int) (*VInitPreFill - 2) % SwathHeight; + else + MaxPartialSwath = (unsigned int) (*VInitPreFill + SwathHeight - 2) + % SwathHeight; + MaxPartialSwath = dml_max(1U, MaxPartialSwath); + + } else { + + if (ViewportYStart != 0) + dml_print( + "WARNING DML: using viewport y position of 0 even though actual viewport y position is non-zero in prefetch source lines calculation\n"); + + *MaxNumSwath = dml_ceil(*VInitPreFill / SwathHeight, 1); + + if (*VInitPreFill > 1.0) + MaxPartialSwath = (unsigned int) (*VInitPreFill - 1) % SwathHeight; + else + MaxPartialSwath = (unsigned int) (*VInitPreFill + SwathHeight - 1) + % SwathHeight; + } + + return *MaxNumSwath * SwathHeight + MaxPartialSwath; +} + +static unsigned int CalculateVMAndRowBytes( + struct display_mode_lib *mode_lib, + bool DCCEnable, + unsigned int BlockHeight256Bytes, + unsigned int BlockWidth256Bytes, + enum source_format_class SourcePixelFormat, + unsigned int SurfaceTiling, + unsigned int BytePerPixel, + enum scan_direction_class ScanDirection, + unsigned int ViewportWidth, + unsigned int ViewportHeight, + unsigned int SwathWidth, + bool VirtualMemoryEnable, + unsigned int VMMPageSize, + unsigned int PTEBufferSizeInRequests, + unsigned int PDEProcessingBufIn64KBReqs, + unsigned int Pitch, + unsigned int DCCMetaPitch, + unsigned int *MacroTileWidth, + unsigned int *MetaRowByte, + unsigned int *PixelPTEBytesPerRow, + bool *PTEBufferSizeNotExceeded, + unsigned int *dpte_row_height, + unsigned int *meta_row_height) +{ + unsigned int MetaRequestHeight; + unsigned int MetaRequestWidth; + unsigned int MetaSurfWidth; + unsigned int MetaSurfHeight; + unsigned int MPDEBytesFrame; + unsigned int MetaPTEBytesFrame; + unsigned int DCCMetaSurfaceBytes; + + unsigned int MacroTileSizeBytes; + unsigned int MacroTileHeight; + unsigned int DPDE0BytesFrame; + unsigned int ExtraDPDEBytesFrame; + unsigned int PDEAndMetaPTEBytesFrame; + + if (DCCEnable == true) { + MetaRequestHeight = 8 * BlockHeight256Bytes; + MetaRequestWidth = 8 * BlockWidth256Bytes; + if (ScanDirection == dm_horz) { + *meta_row_height = MetaRequestHeight; + MetaSurfWidth = dml_ceil((double) SwathWidth - 1, MetaRequestWidth) + + MetaRequestWidth; + *MetaRowByte = MetaSurfWidth * MetaRequestHeight * BytePerPixel / 256.0; + } else { + *meta_row_height = MetaRequestWidth; + MetaSurfHeight = dml_ceil((double) SwathWidth - 1, MetaRequestHeight) + + MetaRequestHeight; + *MetaRowByte = MetaSurfHeight * MetaRequestWidth * BytePerPixel / 256.0; + } + if (ScanDirection == dm_horz) { + DCCMetaSurfaceBytes = DCCMetaPitch + * (dml_ceil(ViewportHeight - 1, 64 * BlockHeight256Bytes) + + 64 * BlockHeight256Bytes) * BytePerPixel + / 256; + } else { + DCCMetaSurfaceBytes = DCCMetaPitch + * (dml_ceil( + (double) ViewportHeight - 1, + 64 * BlockHeight256Bytes) + + 64 * BlockHeight256Bytes) * BytePerPixel + / 256; + } + if (VirtualMemoryEnable == true) { + MetaPTEBytesFrame = (dml_ceil( + (double) (DCCMetaSurfaceBytes - VMMPageSize) + / (8 * VMMPageSize), + 1) + 1) * 64; + MPDEBytesFrame = 128 * (mode_lib->vba.MaxPageTableLevels - 1); + } else { + MetaPTEBytesFrame = 0; + MPDEBytesFrame = 0; + } + } else { + MetaPTEBytesFrame = 0; + MPDEBytesFrame = 0; + *MetaRowByte = 0; + } + + if (SurfaceTiling == dm_sw_linear) { + MacroTileSizeBytes = 256; + MacroTileHeight = 1; + } else if (SurfaceTiling == dm_sw_4kb_s || SurfaceTiling == dm_sw_4kb_s_x + || SurfaceTiling == dm_sw_4kb_d || SurfaceTiling == dm_sw_4kb_d_x) { + MacroTileSizeBytes = 4096; + MacroTileHeight = 4 * BlockHeight256Bytes; + } else if (SurfaceTiling == dm_sw_64kb_s || SurfaceTiling == dm_sw_64kb_s_t + || SurfaceTiling == dm_sw_64kb_s_x || SurfaceTiling == dm_sw_64kb_d + || SurfaceTiling == dm_sw_64kb_d_t || SurfaceTiling == dm_sw_64kb_d_x + || SurfaceTiling == dm_sw_64kb_r_x) { + MacroTileSizeBytes = 65536; + MacroTileHeight = 16 * BlockHeight256Bytes; + } else { + MacroTileSizeBytes = 262144; + MacroTileHeight = 32 * BlockHeight256Bytes; + } + *MacroTileWidth = MacroTileSizeBytes / BytePerPixel / MacroTileHeight; + + if (VirtualMemoryEnable == true && mode_lib->vba.MaxPageTableLevels > 1) { + if (ScanDirection == dm_horz) { + DPDE0BytesFrame = + 64 + * (dml_ceil( + ((Pitch + * (dml_ceil( + ViewportHeight + - 1, + MacroTileHeight) + + MacroTileHeight) + * BytePerPixel) + - MacroTileSizeBytes) + / (8 + * 2097152), + 1) + 1); + } else { + DPDE0BytesFrame = + 64 + * (dml_ceil( + ((Pitch + * (dml_ceil( + (double) SwathWidth + - 1, + MacroTileHeight) + + MacroTileHeight) + * BytePerPixel) + - MacroTileSizeBytes) + / (8 + * 2097152), + 1) + 1); + } + ExtraDPDEBytesFrame = 128 * (mode_lib->vba.MaxPageTableLevels - 2); + } else { + DPDE0BytesFrame = 0; + ExtraDPDEBytesFrame = 0; + } + + PDEAndMetaPTEBytesFrame = MetaPTEBytesFrame + MPDEBytesFrame + DPDE0BytesFrame + + ExtraDPDEBytesFrame; + + if (VirtualMemoryEnable == true) { + unsigned int PTERequestSize; + unsigned int PixelPTEReqHeight; + unsigned int PixelPTEReqWidth; + double FractionOfPTEReturnDrop; + unsigned int EffectivePDEProcessingBufIn64KBReqs; + + if (SurfaceTiling == dm_sw_linear) { + PixelPTEReqHeight = 1; + PixelPTEReqWidth = 8.0 * VMMPageSize / BytePerPixel; + PTERequestSize = 64; + FractionOfPTEReturnDrop = 0; + } else if (MacroTileSizeBytes == 4096) { + PixelPTEReqHeight = MacroTileHeight; + PixelPTEReqWidth = 8 * *MacroTileWidth; + PTERequestSize = 64; + if (ScanDirection == dm_horz) + FractionOfPTEReturnDrop = 0; + else + FractionOfPTEReturnDrop = 7 / 8; + } else if (VMMPageSize == 4096 && MacroTileSizeBytes > 4096) { + PixelPTEReqHeight = 16 * BlockHeight256Bytes; + PixelPTEReqWidth = 16 * BlockWidth256Bytes; + PTERequestSize = 128; + FractionOfPTEReturnDrop = 0; + } else { + PixelPTEReqHeight = MacroTileHeight; + PixelPTEReqWidth = 8 * *MacroTileWidth; + PTERequestSize = 64; + FractionOfPTEReturnDrop = 0; + } + + if (SourcePixelFormat == dm_420_8 || SourcePixelFormat == dm_420_10) + EffectivePDEProcessingBufIn64KBReqs = PDEProcessingBufIn64KBReqs / 2; + else + EffectivePDEProcessingBufIn64KBReqs = PDEProcessingBufIn64KBReqs; + + if (SurfaceTiling == dm_sw_linear) { + *dpte_row_height = + dml_min( + 128, + 1 + << (unsigned int) dml_floor( + dml_log2( + dml_min( + (double) PTEBufferSizeInRequests + * PixelPTEReqWidth, + EffectivePDEProcessingBufIn64KBReqs + * 65536.0 + / BytePerPixel) + / Pitch), + 1)); + *PixelPTEBytesPerRow = PTERequestSize + * (dml_ceil( + (double) (Pitch * *dpte_row_height - 1) + / PixelPTEReqWidth, + 1) + 1); + } else if (ScanDirection == dm_horz) { + *dpte_row_height = PixelPTEReqHeight; + *PixelPTEBytesPerRow = PTERequestSize + * (dml_ceil(((double) SwathWidth - 1) / PixelPTEReqWidth, 1) + + 1); + } else { + *dpte_row_height = dml_min(PixelPTEReqWidth, *MacroTileWidth); + *PixelPTEBytesPerRow = PTERequestSize + * (dml_ceil( + ((double) SwathWidth - 1) + / PixelPTEReqHeight, + 1) + 1); + } + if (*PixelPTEBytesPerRow * (1 - FractionOfPTEReturnDrop) + <= 64 * PTEBufferSizeInRequests) { + *PTEBufferSizeNotExceeded = true; + } else { + *PTEBufferSizeNotExceeded = false; + } + } else { + *PixelPTEBytesPerRow = 0; + *PTEBufferSizeNotExceeded = true; + } + + return PDEAndMetaPTEBytesFrame; +} + +static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation( + struct display_mode_lib *mode_lib) +{ + unsigned int j, k; + + mode_lib->vba.WritebackDISPCLK = 0.0; + mode_lib->vba.DISPCLKWithRamping = 0; + mode_lib->vba.DISPCLKWithoutRamping = 0; + mode_lib->vba.GlobalDPPCLK = 0.0; + + // dml_ml->vba.DISPCLK and dml_ml->vba.DPPCLK Calculation + // + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.WritebackEnable[k]) { + mode_lib->vba.WritebackDISPCLK = + dml_max( + mode_lib->vba.WritebackDISPCLK, + CalculateWriteBackDISPCLK( + mode_lib->vba.WritebackPixelFormat[k], + mode_lib->vba.PixelClock[k], + mode_lib->vba.WritebackHRatio[k], + mode_lib->vba.WritebackVRatio[k], + mode_lib->vba.WritebackLumaHTaps[k], + mode_lib->vba.WritebackLumaVTaps[k], + mode_lib->vba.WritebackChromaHTaps[k], + mode_lib->vba.WritebackChromaVTaps[k], + mode_lib->vba.WritebackDestinationWidth[k], + mode_lib->vba.HTotal[k], + mode_lib->vba.WritebackChromaLineBufferWidth)); + } + } + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.HRatio[k] > 1) { + mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] = dml_min( + mode_lib->vba.MaxDCHUBToPSCLThroughput, + mode_lib->vba.MaxPSCLToLBThroughput + * mode_lib->vba.HRatio[k] + / dml_ceil( + mode_lib->vba.htaps[k] + / 6.0, + 1)); + } else { + mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] = dml_min( + mode_lib->vba.MaxDCHUBToPSCLThroughput, + mode_lib->vba.MaxPSCLToLBThroughput); + } + + mode_lib->vba.DPPCLKUsingSingleDPPLuma = + mode_lib->vba.PixelClock[k] + * dml_max( + mode_lib->vba.vtaps[k] / 6.0 + * dml_min( + 1.0, + mode_lib->vba.HRatio[k]), + dml_max( + mode_lib->vba.HRatio[k] + * mode_lib->vba.VRatio[k] + / mode_lib->vba.PSCL_THROUGHPUT_LUMA[k], + 1.0)); + + if ((mode_lib->vba.htaps[k] > 6 || mode_lib->vba.vtaps[k] > 6) + && mode_lib->vba.DPPCLKUsingSingleDPPLuma + < 2 * mode_lib->vba.PixelClock[k]) { + mode_lib->vba.DPPCLKUsingSingleDPPLuma = 2 * mode_lib->vba.PixelClock[k]; + } + + if ((mode_lib->vba.SourcePixelFormat[k] != dm_420_8 + && mode_lib->vba.SourcePixelFormat[k] != dm_420_10)) { + mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] = 0.0; + mode_lib->vba.DPPCLKUsingSingleDPP[k] = + mode_lib->vba.DPPCLKUsingSingleDPPLuma; + } else { + if (mode_lib->vba.HRatio[k] > 1) { + mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] = + dml_min( + mode_lib->vba.MaxDCHUBToPSCLThroughput, + mode_lib->vba.MaxPSCLToLBThroughput + * mode_lib->vba.HRatio[k] + / 2 + / dml_ceil( + mode_lib->vba.HTAPsChroma[k] + / 6.0, + 1.0)); + } else { + mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] = dml_min( + mode_lib->vba.MaxDCHUBToPSCLThroughput, + mode_lib->vba.MaxPSCLToLBThroughput); + } + mode_lib->vba.DPPCLKUsingSingleDPPChroma = + mode_lib->vba.PixelClock[k] + * dml_max( + mode_lib->vba.VTAPsChroma[k] + / 6.0 + * dml_min( + 1.0, + mode_lib->vba.HRatio[k] + / 2), + dml_max( + mode_lib->vba.HRatio[k] + * mode_lib->vba.VRatio[k] + / 4 + / mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k], + 1.0)); + + if ((mode_lib->vba.HTAPsChroma[k] > 6 || mode_lib->vba.VTAPsChroma[k] > 6) + && mode_lib->vba.DPPCLKUsingSingleDPPChroma + < 2 * mode_lib->vba.PixelClock[k]) { + mode_lib->vba.DPPCLKUsingSingleDPPChroma = 2 + * mode_lib->vba.PixelClock[k]; + } + + mode_lib->vba.DPPCLKUsingSingleDPP[k] = dml_max( + mode_lib->vba.DPPCLKUsingSingleDPPLuma, + mode_lib->vba.DPPCLKUsingSingleDPPChroma); + } + } + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.BlendingAndTiming[k] != k) + continue; + if (mode_lib->vba.ODMCombineEnabled[k]) { + mode_lib->vba.DISPCLKWithRamping = + dml_max( + mode_lib->vba.DISPCLKWithRamping, + mode_lib->vba.PixelClock[k] / 2 + * (1 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100) + * (1 + + mode_lib->vba.DISPCLKRampingMargin + / 100)); + mode_lib->vba.DISPCLKWithoutRamping = + dml_max( + mode_lib->vba.DISPCLKWithoutRamping, + mode_lib->vba.PixelClock[k] / 2 + * (1 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100)); + } else if (!mode_lib->vba.ODMCombineEnabled[k]) { + mode_lib->vba.DISPCLKWithRamping = + dml_max( + mode_lib->vba.DISPCLKWithRamping, + mode_lib->vba.PixelClock[k] + * (1 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100) + * (1 + + mode_lib->vba.DISPCLKRampingMargin + / 100)); + mode_lib->vba.DISPCLKWithoutRamping = + dml_max( + mode_lib->vba.DISPCLKWithoutRamping, + mode_lib->vba.PixelClock[k] + * (1 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100)); + } + } + + mode_lib->vba.DISPCLKWithRamping = dml_max( + mode_lib->vba.DISPCLKWithRamping, + mode_lib->vba.WritebackDISPCLK); + mode_lib->vba.DISPCLKWithoutRamping = dml_max( + mode_lib->vba.DISPCLKWithoutRamping, + mode_lib->vba.WritebackDISPCLK); + + ASSERT(mode_lib->vba.DISPCLKDPPCLKVCOSpeed != 0); + mode_lib->vba.DISPCLKWithRampingRoundedToDFSGranularity = RoundToDFSGranularityUp( + mode_lib->vba.DISPCLKWithRamping, + mode_lib->vba.DISPCLKDPPCLKVCOSpeed); + mode_lib->vba.DISPCLKWithoutRampingRoundedToDFSGranularity = RoundToDFSGranularityUp( + mode_lib->vba.DISPCLKWithoutRamping, + mode_lib->vba.DISPCLKDPPCLKVCOSpeed); + mode_lib->vba.MaxDispclkRoundedToDFSGranularity = RoundToDFSGranularityDown( + mode_lib->vba.soc.clock_limits[NumberOfStates - 1].dispclk_mhz, + mode_lib->vba.DISPCLKDPPCLKVCOSpeed); + if (mode_lib->vba.DISPCLKWithoutRampingRoundedToDFSGranularity + > mode_lib->vba.MaxDispclkRoundedToDFSGranularity) { + mode_lib->vba.DISPCLK_calculated = + mode_lib->vba.DISPCLKWithoutRampingRoundedToDFSGranularity; + } else if (mode_lib->vba.DISPCLKWithRampingRoundedToDFSGranularity + > mode_lib->vba.MaxDispclkRoundedToDFSGranularity) { + mode_lib->vba.DISPCLK_calculated = mode_lib->vba.MaxDispclkRoundedToDFSGranularity; + } else { + mode_lib->vba.DISPCLK_calculated = + mode_lib->vba.DISPCLKWithRampingRoundedToDFSGranularity; + } + DTRACE(" dispclk_mhz (calculated) = %f", mode_lib->vba.DISPCLK_calculated); + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.DPPCLK_calculated[k] = mode_lib->vba.DPPCLKUsingSingleDPP[k] + / mode_lib->vba.DPPPerPlane[k] + * (1 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100); + mode_lib->vba.GlobalDPPCLK = dml_max( + mode_lib->vba.GlobalDPPCLK, + mode_lib->vba.DPPCLK_calculated[k]); + } + mode_lib->vba.GlobalDPPCLK = RoundToDFSGranularityUp( + mode_lib->vba.GlobalDPPCLK, + mode_lib->vba.DISPCLKDPPCLKVCOSpeed); + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.DPPCLK_calculated[k] = mode_lib->vba.GlobalDPPCLK / 255 + * dml_ceil( + mode_lib->vba.DPPCLK_calculated[k] * 255 + / mode_lib->vba.GlobalDPPCLK, + 1); + DTRACE(" dppclk_mhz[%i] (calculated) = %f", k, mode_lib->vba.DPPCLK_calculated[k]); + } + + // Urgent Watermark + mode_lib->vba.DCCEnabledAnyPlane = false; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) + if (mode_lib->vba.DCCEnable[k]) + mode_lib->vba.DCCEnabledAnyPlane = true; + + mode_lib->vba.ReturnBandwidthToDCN = dml_min( + mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLK, + mode_lib->vba.FabricAndDRAMBandwidth * 1000) + * mode_lib->vba.PercentOfIdealDRAMAndFabricBWReceivedAfterUrgLatency / 100; + + mode_lib->vba.ReturnBW = mode_lib->vba.ReturnBandwidthToDCN; + mode_lib->vba.ReturnBW = adjust_ReturnBW( + mode_lib, + mode_lib->vba.ReturnBW, + mode_lib->vba.DCCEnabledAnyPlane, + mode_lib->vba.ReturnBandwidthToDCN); + + // Let's do this calculation again?? + mode_lib->vba.ReturnBandwidthToDCN = dml_min( + mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLK, + mode_lib->vba.FabricAndDRAMBandwidth * 1000); + mode_lib->vba.ReturnBW = adjust_ReturnBW( + mode_lib, + mode_lib->vba.ReturnBW, + mode_lib->vba.DCCEnabledAnyPlane, + mode_lib->vba.ReturnBandwidthToDCN); + + DTRACE(" dcfclk_mhz = %f", mode_lib->vba.DCFCLK); + DTRACE(" return_bw_to_dcn = %f", mode_lib->vba.ReturnBandwidthToDCN); + DTRACE(" return_bus_bw = %f", mode_lib->vba.ReturnBW); + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + bool MainPlaneDoesODMCombine = false; + + if (mode_lib->vba.SourceScan[k] == dm_horz) + mode_lib->vba.SwathWidthSingleDPPY[k] = mode_lib->vba.ViewportWidth[k]; + else + mode_lib->vba.SwathWidthSingleDPPY[k] = mode_lib->vba.ViewportHeight[k]; + + if (mode_lib->vba.ODMCombineEnabled[k] == true) + MainPlaneDoesODMCombine = true; + for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) + if (mode_lib->vba.BlendingAndTiming[k] == j + && mode_lib->vba.ODMCombineEnabled[j] == true) + MainPlaneDoesODMCombine = true; + + if (MainPlaneDoesODMCombine == true) + mode_lib->vba.SwathWidthY[k] = dml_min( + (double) mode_lib->vba.SwathWidthSingleDPPY[k], + dml_round( + mode_lib->vba.HActive[k] / 2.0 + * mode_lib->vba.HRatio[k])); + else + mode_lib->vba.SwathWidthY[k] = mode_lib->vba.SwathWidthSingleDPPY[k] + / mode_lib->vba.DPPPerPlane[k]; + } + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.SourcePixelFormat[k] == dm_444_64) { + mode_lib->vba.BytePerPixelDETY[k] = 8; + mode_lib->vba.BytePerPixelDETC[k] = 0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_32) { + mode_lib->vba.BytePerPixelDETY[k] = 4; + mode_lib->vba.BytePerPixelDETC[k] = 0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_16) { + mode_lib->vba.BytePerPixelDETY[k] = 2; + mode_lib->vba.BytePerPixelDETC[k] = 0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_8) { + mode_lib->vba.BytePerPixelDETY[k] = 1; + mode_lib->vba.BytePerPixelDETC[k] = 0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_8) { + mode_lib->vba.BytePerPixelDETY[k] = 1; + mode_lib->vba.BytePerPixelDETC[k] = 2; + } else { // dm_420_10 + mode_lib->vba.BytePerPixelDETY[k] = 4.0 / 3.0; + mode_lib->vba.BytePerPixelDETC[k] = 8.0 / 3.0; + } + } + + mode_lib->vba.TotalDataReadBandwidth = 0.0; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.ReadBandwidthPlaneLuma[k] = mode_lib->vba.SwathWidthSingleDPPY[k] + * dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1) + / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) + * mode_lib->vba.VRatio[k]; + mode_lib->vba.ReadBandwidthPlaneChroma[k] = mode_lib->vba.SwathWidthSingleDPPY[k] + / 2 * dml_ceil(mode_lib->vba.BytePerPixelDETC[k], 2) + / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) + * mode_lib->vba.VRatio[k] / 2; + DTRACE( + " read_bw[%i] = %fBps", + k, + mode_lib->vba.ReadBandwidthPlaneLuma[k] + + mode_lib->vba.ReadBandwidthPlaneChroma[k]); + mode_lib->vba.TotalDataReadBandwidth += mode_lib->vba.ReadBandwidthPlaneLuma[k] + + mode_lib->vba.ReadBandwidthPlaneChroma[k]; + } + + mode_lib->vba.TotalDCCActiveDPP = 0; + mode_lib->vba.TotalActiveDPP = 0; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.TotalActiveDPP = mode_lib->vba.TotalActiveDPP + + mode_lib->vba.DPPPerPlane[k]; + if (mode_lib->vba.DCCEnable[k]) + mode_lib->vba.TotalDCCActiveDPP = mode_lib->vba.TotalDCCActiveDPP + + mode_lib->vba.DPPPerPlane[k]; + } + + mode_lib->vba.UrgentRoundTripAndOutOfOrderLatency = + (mode_lib->vba.RoundTripPingLatencyCycles + 32) / mode_lib->vba.DCFCLK + + mode_lib->vba.UrgentOutOfOrderReturnPerChannel + * mode_lib->vba.NumberOfChannels + / mode_lib->vba.ReturnBW; + + mode_lib->vba.LastPixelOfLineExtraWatermark = 0; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + double DataFabricLineDeliveryTimeLuma, DataFabricLineDeliveryTimeChroma; + + if (mode_lib->vba.VRatio[k] <= 1.0) + mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k] = + (double) mode_lib->vba.SwathWidthY[k] + * mode_lib->vba.DPPPerPlane[k] + / mode_lib->vba.HRatio[k] + / mode_lib->vba.PixelClock[k]; + else + mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k] = + (double) mode_lib->vba.SwathWidthY[k] + / mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] + / mode_lib->vba.DPPCLK[k]; + + DataFabricLineDeliveryTimeLuma = mode_lib->vba.SwathWidthSingleDPPY[k] + * mode_lib->vba.SwathHeightY[k] + * dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1) + / (mode_lib->vba.ReturnBW * mode_lib->vba.ReadBandwidthPlaneLuma[k] + / mode_lib->vba.TotalDataReadBandwidth); + mode_lib->vba.LastPixelOfLineExtraWatermark = dml_max( + mode_lib->vba.LastPixelOfLineExtraWatermark, + DataFabricLineDeliveryTimeLuma + - mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k]); + + if (mode_lib->vba.BytePerPixelDETC[k] == 0) + mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k] = 0.0; + else if (mode_lib->vba.VRatio[k] / 2.0 <= 1.0) + mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k] = + mode_lib->vba.SwathWidthY[k] / 2.0 + * mode_lib->vba.DPPPerPlane[k] + / (mode_lib->vba.HRatio[k] / 2.0) + / mode_lib->vba.PixelClock[k]; + else + mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k] = + mode_lib->vba.SwathWidthY[k] / 2.0 + / mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] + / mode_lib->vba.DPPCLK[k]; + + DataFabricLineDeliveryTimeChroma = mode_lib->vba.SwathWidthSingleDPPY[k] / 2.0 + * mode_lib->vba.SwathHeightC[k] + * dml_ceil(mode_lib->vba.BytePerPixelDETC[k], 2) + / (mode_lib->vba.ReturnBW + * mode_lib->vba.ReadBandwidthPlaneChroma[k] + / mode_lib->vba.TotalDataReadBandwidth); + mode_lib->vba.LastPixelOfLineExtraWatermark = + dml_max( + mode_lib->vba.LastPixelOfLineExtraWatermark, + DataFabricLineDeliveryTimeChroma + - mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k]); + } + + mode_lib->vba.UrgentExtraLatency = mode_lib->vba.UrgentRoundTripAndOutOfOrderLatency + + (mode_lib->vba.TotalActiveDPP * mode_lib->vba.PixelChunkSizeInKByte + + mode_lib->vba.TotalDCCActiveDPP + * mode_lib->vba.MetaChunkSize) * 1024.0 + / mode_lib->vba.ReturnBW; + + if (mode_lib->vba.VirtualMemoryEnable) + mode_lib->vba.UrgentExtraLatency += mode_lib->vba.TotalActiveDPP + * mode_lib->vba.PTEChunkSize * 1024.0 / mode_lib->vba.ReturnBW; + + mode_lib->vba.UrgentWatermark = mode_lib->vba.UrgentLatency + + mode_lib->vba.LastPixelOfLineExtraWatermark + + mode_lib->vba.UrgentExtraLatency; + + DTRACE(" urgent_extra_latency = %fus", mode_lib->vba.UrgentExtraLatency); + DTRACE(" wm_urgent = %fus", mode_lib->vba.UrgentWatermark); + + mode_lib->vba.MemoryTripWatermark = mode_lib->vba.UrgentLatency; + + mode_lib->vba.TotalActiveWriteback = 0; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.WritebackEnable[k]) + mode_lib->vba.TotalActiveWriteback = mode_lib->vba.TotalActiveWriteback + 1; + } + + if (mode_lib->vba.TotalActiveWriteback <= 1) + mode_lib->vba.WritebackUrgentWatermark = mode_lib->vba.WritebackLatency; + else + mode_lib->vba.WritebackUrgentWatermark = mode_lib->vba.WritebackLatency + + mode_lib->vba.WritebackChunkSize * 1024.0 / 32 + / mode_lib->vba.SOCCLK; + + DTRACE(" wm_wb_urgent = %fus", mode_lib->vba.WritebackUrgentWatermark); + + // NB P-State/DRAM Clock Change Watermark + mode_lib->vba.DRAMClockChangeWatermark = mode_lib->vba.DRAMClockChangeLatency + + mode_lib->vba.UrgentWatermark; + + DTRACE(" wm_pstate_change = %fus", mode_lib->vba.DRAMClockChangeWatermark); + + DTRACE(" calculating wb pstate watermark"); + DTRACE(" total wb outputs %d", mode_lib->vba.TotalActiveWriteback); + DTRACE(" socclk frequency %f Mhz", mode_lib->vba.SOCCLK); + + if (mode_lib->vba.TotalActiveWriteback <= 1) + mode_lib->vba.WritebackDRAMClockChangeWatermark = + mode_lib->vba.DRAMClockChangeLatency + + mode_lib->vba.WritebackLatency; + else + mode_lib->vba.WritebackDRAMClockChangeWatermark = + mode_lib->vba.DRAMClockChangeLatency + + mode_lib->vba.WritebackLatency + + mode_lib->vba.WritebackChunkSize * 1024.0 / 32 + / mode_lib->vba.SOCCLK; + + DTRACE(" wm_wb_pstate %fus", mode_lib->vba.WritebackDRAMClockChangeWatermark); + + // Stutter Efficiency + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.LinesInDETY[k] = mode_lib->vba.DETBufferSizeY[k] + / mode_lib->vba.BytePerPixelDETY[k] / mode_lib->vba.SwathWidthY[k]; + mode_lib->vba.LinesInDETYRoundedDownToSwath[k] = dml_floor( + mode_lib->vba.LinesInDETY[k], + mode_lib->vba.SwathHeightY[k]); + mode_lib->vba.FullDETBufferingTimeY[k] = + mode_lib->vba.LinesInDETYRoundedDownToSwath[k] + * (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) + / mode_lib->vba.VRatio[k]; + if (mode_lib->vba.BytePerPixelDETC[k] > 0) { + mode_lib->vba.LinesInDETC[k] = mode_lib->vba.DETBufferSizeC[k] + / mode_lib->vba.BytePerPixelDETC[k] + / (mode_lib->vba.SwathWidthY[k] / 2); + mode_lib->vba.LinesInDETCRoundedDownToSwath[k] = dml_floor( + mode_lib->vba.LinesInDETC[k], + mode_lib->vba.SwathHeightC[k]); + mode_lib->vba.FullDETBufferingTimeC[k] = + mode_lib->vba.LinesInDETCRoundedDownToSwath[k] + * (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) + / (mode_lib->vba.VRatio[k] / 2); + } else { + mode_lib->vba.LinesInDETC[k] = 0; + mode_lib->vba.LinesInDETCRoundedDownToSwath[k] = 0; + mode_lib->vba.FullDETBufferingTimeC[k] = 999999; + } + } + + mode_lib->vba.MinFullDETBufferingTime = 999999.0; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.FullDETBufferingTimeY[k] + < mode_lib->vba.MinFullDETBufferingTime) { + mode_lib->vba.MinFullDETBufferingTime = + mode_lib->vba.FullDETBufferingTimeY[k]; + mode_lib->vba.FrameTimeForMinFullDETBufferingTime = + (double) mode_lib->vba.VTotal[k] * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]; + } + if (mode_lib->vba.FullDETBufferingTimeC[k] + < mode_lib->vba.MinFullDETBufferingTime) { + mode_lib->vba.MinFullDETBufferingTime = + mode_lib->vba.FullDETBufferingTimeC[k]; + mode_lib->vba.FrameTimeForMinFullDETBufferingTime = + (double) mode_lib->vba.VTotal[k] * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]; + } + } + + mode_lib->vba.AverageReadBandwidthGBytePerSecond = 0.0; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.DCCEnable[k]) { + mode_lib->vba.AverageReadBandwidthGBytePerSecond = + mode_lib->vba.AverageReadBandwidthGBytePerSecond + + mode_lib->vba.ReadBandwidthPlaneLuma[k] + / mode_lib->vba.DCCRate[k] + / 1000 + + mode_lib->vba.ReadBandwidthPlaneChroma[k] + / mode_lib->vba.DCCRate[k] + / 1000; + } else { + mode_lib->vba.AverageReadBandwidthGBytePerSecond = + mode_lib->vba.AverageReadBandwidthGBytePerSecond + + mode_lib->vba.ReadBandwidthPlaneLuma[k] + / 1000 + + mode_lib->vba.ReadBandwidthPlaneChroma[k] + / 1000; + } + if (mode_lib->vba.DCCEnable[k]) { + mode_lib->vba.AverageReadBandwidthGBytePerSecond = + mode_lib->vba.AverageReadBandwidthGBytePerSecond + + mode_lib->vba.ReadBandwidthPlaneLuma[k] + / 1000 / 256 + + mode_lib->vba.ReadBandwidthPlaneChroma[k] + / 1000 / 256; + } + if (mode_lib->vba.VirtualMemoryEnable) { + mode_lib->vba.AverageReadBandwidthGBytePerSecond = + mode_lib->vba.AverageReadBandwidthGBytePerSecond + + mode_lib->vba.ReadBandwidthPlaneLuma[k] + / 1000 / 512 + + mode_lib->vba.ReadBandwidthPlaneChroma[k] + / 1000 / 512; + } + } + + mode_lib->vba.PartOfBurstThatFitsInROB = + dml_min( + mode_lib->vba.MinFullDETBufferingTime + * mode_lib->vba.TotalDataReadBandwidth, + mode_lib->vba.ROBBufferSizeInKByte * 1024 + * mode_lib->vba.TotalDataReadBandwidth + / (mode_lib->vba.AverageReadBandwidthGBytePerSecond + * 1000)); + mode_lib->vba.StutterBurstTime = mode_lib->vba.PartOfBurstThatFitsInROB + * (mode_lib->vba.AverageReadBandwidthGBytePerSecond * 1000) + / mode_lib->vba.TotalDataReadBandwidth / mode_lib->vba.ReturnBW + + (mode_lib->vba.MinFullDETBufferingTime + * mode_lib->vba.TotalDataReadBandwidth + - mode_lib->vba.PartOfBurstThatFitsInROB) + / (mode_lib->vba.DCFCLK * 64); + if (mode_lib->vba.TotalActiveWriteback == 0) { + mode_lib->vba.StutterEfficiencyNotIncludingVBlank = (1 + - (mode_lib->vba.SRExitTime + mode_lib->vba.StutterBurstTime) + / mode_lib->vba.MinFullDETBufferingTime) * 100; + } else { + mode_lib->vba.StutterEfficiencyNotIncludingVBlank = 0; + } + + mode_lib->vba.SmallestVBlank = 999999; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.SynchronizedVBlank || mode_lib->vba.NumberOfActivePlanes == 1) { + mode_lib->vba.VBlankTime = (double) (mode_lib->vba.VTotal[k] + - mode_lib->vba.VActive[k]) * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]; + } else { + mode_lib->vba.VBlankTime = 0; + } + mode_lib->vba.SmallestVBlank = dml_min( + mode_lib->vba.SmallestVBlank, + mode_lib->vba.VBlankTime); + } + + mode_lib->vba.StutterEfficiency = (mode_lib->vba.StutterEfficiencyNotIncludingVBlank / 100 + * (mode_lib->vba.FrameTimeForMinFullDETBufferingTime + - mode_lib->vba.SmallestVBlank) + + mode_lib->vba.SmallestVBlank) + / mode_lib->vba.FrameTimeForMinFullDETBufferingTime * 100; + + // dml_ml->vba.DCFCLK Deep Sleep + mode_lib->vba.DCFClkDeepSleep = 8.0; + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; k++) { + if (mode_lib->vba.BytePerPixelDETC[k] > 0) { + mode_lib->vba.DCFCLKDeepSleepPerPlane = + dml_max( + 1.1 * mode_lib->vba.SwathWidthY[k] + * dml_ceil( + mode_lib->vba.BytePerPixelDETY[k], + 1) / 32 + / mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k], + 1.1 * mode_lib->vba.SwathWidthY[k] / 2.0 + * dml_ceil( + mode_lib->vba.BytePerPixelDETC[k], + 2) / 32 + / mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k]); + } else + mode_lib->vba.DCFCLKDeepSleepPerPlane = 1.1 * mode_lib->vba.SwathWidthY[k] + * dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1) / 64.0 + / mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k]; + mode_lib->vba.DCFCLKDeepSleepPerPlane = dml_max( + mode_lib->vba.DCFCLKDeepSleepPerPlane, + mode_lib->vba.PixelClock[k] / 16.0); + mode_lib->vba.DCFClkDeepSleep = dml_max( + mode_lib->vba.DCFClkDeepSleep, + mode_lib->vba.DCFCLKDeepSleepPerPlane); + + DTRACE( + " dcfclk_deepsleep_per_plane[%i] = %fMHz", + k, + mode_lib->vba.DCFCLKDeepSleepPerPlane); + } + + DTRACE(" dcfclk_deepsleep_mhz = %fMHz", mode_lib->vba.DCFClkDeepSleep); + + // Stutter Watermark + mode_lib->vba.StutterExitWatermark = mode_lib->vba.SRExitTime + + mode_lib->vba.LastPixelOfLineExtraWatermark + + mode_lib->vba.UrgentExtraLatency + 10 / mode_lib->vba.DCFClkDeepSleep; + mode_lib->vba.StutterEnterPlusExitWatermark = mode_lib->vba.SREnterPlusExitTime + + mode_lib->vba.LastPixelOfLineExtraWatermark + + mode_lib->vba.UrgentExtraLatency; + + DTRACE(" wm_cstate_exit = %fus", mode_lib->vba.StutterExitWatermark); + DTRACE(" wm_cstate_enter_exit = %fus", mode_lib->vba.StutterEnterPlusExitWatermark); + + // Urgent Latency Supported + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.EffectiveDETPlusLBLinesLuma = + dml_floor( + mode_lib->vba.LinesInDETY[k] + + dml_min( + mode_lib->vba.LinesInDETY[k] + * mode_lib->vba.DPPCLK[k] + * mode_lib->vba.BytePerPixelDETY[k] + * mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] + / (mode_lib->vba.ReturnBW + / mode_lib->vba.DPPPerPlane[k]), + (double) mode_lib->vba.EffectiveLBLatencyHidingSourceLinesLuma), + mode_lib->vba.SwathHeightY[k]); + + mode_lib->vba.UrgentLatencySupportUsLuma = mode_lib->vba.EffectiveDETPlusLBLinesLuma + * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) + / mode_lib->vba.VRatio[k] + - mode_lib->vba.EffectiveDETPlusLBLinesLuma + * mode_lib->vba.SwathWidthY[k] + * mode_lib->vba.BytePerPixelDETY[k] + / (mode_lib->vba.ReturnBW + / mode_lib->vba.DPPPerPlane[k]); + + if (mode_lib->vba.BytePerPixelDETC[k] > 0) { + mode_lib->vba.EffectiveDETPlusLBLinesChroma = + dml_floor( + mode_lib->vba.LinesInDETC[k] + + dml_min( + mode_lib->vba.LinesInDETC[k] + * mode_lib->vba.DPPCLK[k] + * mode_lib->vba.BytePerPixelDETC[k] + * mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] + / (mode_lib->vba.ReturnBW + / mode_lib->vba.DPPPerPlane[k]), + (double) mode_lib->vba.EffectiveLBLatencyHidingSourceLinesChroma), + mode_lib->vba.SwathHeightC[k]); + mode_lib->vba.UrgentLatencySupportUsChroma = + mode_lib->vba.EffectiveDETPlusLBLinesChroma + * (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) + / (mode_lib->vba.VRatio[k] / 2) + - mode_lib->vba.EffectiveDETPlusLBLinesChroma + * (mode_lib->vba.SwathWidthY[k] + / 2) + * mode_lib->vba.BytePerPixelDETC[k] + / (mode_lib->vba.ReturnBW + / mode_lib->vba.DPPPerPlane[k]); + mode_lib->vba.UrgentLatencySupportUs[k] = dml_min( + mode_lib->vba.UrgentLatencySupportUsLuma, + mode_lib->vba.UrgentLatencySupportUsChroma); + } else { + mode_lib->vba.UrgentLatencySupportUs[k] = + mode_lib->vba.UrgentLatencySupportUsLuma; + } + } + + mode_lib->vba.MinUrgentLatencySupportUs = 999999; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.MinUrgentLatencySupportUs = dml_min( + mode_lib->vba.MinUrgentLatencySupportUs, + mode_lib->vba.UrgentLatencySupportUs[k]); + } + + // Non-Urgent Latency Tolerance + mode_lib->vba.NonUrgentLatencyTolerance = mode_lib->vba.MinUrgentLatencySupportUs + - mode_lib->vba.UrgentWatermark; + + // DSCCLK + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if ((mode_lib->vba.BlendingAndTiming[k] != k) || !mode_lib->vba.DSCEnabled[k]) { + mode_lib->vba.DSCCLK_calculated[k] = 0.0; + } else { + if (mode_lib->vba.OutputFormat[k] == dm_420 + || mode_lib->vba.OutputFormat[k] == dm_n422) + mode_lib->vba.DSCFormatFactor = 2; + else + mode_lib->vba.DSCFormatFactor = 1; + if (mode_lib->vba.ODMCombineEnabled[k]) + mode_lib->vba.DSCCLK_calculated[k] = + mode_lib->vba.PixelClockBackEnd[k] / 6 + / mode_lib->vba.DSCFormatFactor + / (1 + - mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100); + else + mode_lib->vba.DSCCLK_calculated[k] = + mode_lib->vba.PixelClockBackEnd[k] / 3 + / mode_lib->vba.DSCFormatFactor + / (1 + - mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100); + } + } + + // DSC Delay + // TODO + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + double bpp = mode_lib->vba.OutputBpp[k]; + unsigned int slices = mode_lib->vba.NumberOfDSCSlices[k]; + + if (mode_lib->vba.DSCEnabled[k] && bpp != 0) { + if (!mode_lib->vba.ODMCombineEnabled[k]) { + mode_lib->vba.DSCDelay[k] = + dscceComputeDelay( + mode_lib->vba.DSCInputBitPerComponent[k], + bpp, + dml_ceil( + (double) mode_lib->vba.HActive[k] + / mode_lib->vba.NumberOfDSCSlices[k], + 1), + slices, + mode_lib->vba.OutputFormat[k]) + + dscComputeDelay( + mode_lib->vba.OutputFormat[k]); + } else { + mode_lib->vba.DSCDelay[k] = + 2 + * (dscceComputeDelay( + mode_lib->vba.DSCInputBitPerComponent[k], + bpp, + dml_ceil( + (double) mode_lib->vba.HActive[k] + / mode_lib->vba.NumberOfDSCSlices[k], + 1), + slices / 2.0, + mode_lib->vba.OutputFormat[k]) + + dscComputeDelay( + mode_lib->vba.OutputFormat[k])); + } + mode_lib->vba.DSCDelay[k] = mode_lib->vba.DSCDelay[k] + * mode_lib->vba.PixelClock[k] + / mode_lib->vba.PixelClockBackEnd[k]; + } else { + mode_lib->vba.DSCDelay[k] = 0; + } + } + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) + for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) // NumberOfPlanes + if (j != k && mode_lib->vba.BlendingAndTiming[k] == j + && mode_lib->vba.DSCEnabled[j]) + mode_lib->vba.DSCDelay[k] = mode_lib->vba.DSCDelay[j]; + + // Prefetch + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + unsigned int PDEAndMetaPTEBytesFrameY; + unsigned int PixelPTEBytesPerRowY; + unsigned int MetaRowByteY; + unsigned int MetaRowByteC; + unsigned int PDEAndMetaPTEBytesFrameC; + unsigned int PixelPTEBytesPerRowC; + + Calculate256BBlockSizes( + mode_lib->vba.SourcePixelFormat[k], + mode_lib->vba.SurfaceTiling[k], + dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1), + dml_ceil(mode_lib->vba.BytePerPixelDETC[k], 2), + &mode_lib->vba.BlockHeight256BytesY[k], + &mode_lib->vba.BlockHeight256BytesC[k], + &mode_lib->vba.BlockWidth256BytesY[k], + &mode_lib->vba.BlockWidth256BytesC[k]); + PDEAndMetaPTEBytesFrameY = CalculateVMAndRowBytes( + mode_lib, + mode_lib->vba.DCCEnable[k], + mode_lib->vba.BlockHeight256BytesY[k], + mode_lib->vba.BlockWidth256BytesY[k], + mode_lib->vba.SourcePixelFormat[k], + mode_lib->vba.SurfaceTiling[k], + dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1), + mode_lib->vba.SourceScan[k], + mode_lib->vba.ViewportWidth[k], + mode_lib->vba.ViewportHeight[k], + mode_lib->vba.SwathWidthY[k], + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.VMMPageSize, + mode_lib->vba.PTEBufferSizeInRequests, + mode_lib->vba.PDEProcessingBufIn64KBReqs, + mode_lib->vba.PitchY[k], + mode_lib->vba.DCCMetaPitchY[k], + &mode_lib->vba.MacroTileWidthY[k], + &MetaRowByteY, + &PixelPTEBytesPerRowY, + &mode_lib->vba.PTEBufferSizeNotExceeded[mode_lib->vba.VoltageLevel], + &mode_lib->vba.dpte_row_height[k], + &mode_lib->vba.meta_row_height[k]); + mode_lib->vba.PrefetchSourceLinesY[k] = CalculatePrefetchSourceLines( + mode_lib, + mode_lib->vba.VRatio[k], + mode_lib->vba.vtaps[k], + mode_lib->vba.Interlace[k], + mode_lib->vba.ProgressiveToInterlaceUnitInOPP, + mode_lib->vba.SwathHeightY[k], + mode_lib->vba.ViewportYStartY[k], + &mode_lib->vba.VInitPreFillY[k], + &mode_lib->vba.MaxNumSwathY[k]); + + if ((mode_lib->vba.SourcePixelFormat[k] != dm_444_64 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_32 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_16 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_8)) { + PDEAndMetaPTEBytesFrameC = + CalculateVMAndRowBytes( + mode_lib, + mode_lib->vba.DCCEnable[k], + mode_lib->vba.BlockHeight256BytesC[k], + mode_lib->vba.BlockWidth256BytesC[k], + mode_lib->vba.SourcePixelFormat[k], + mode_lib->vba.SurfaceTiling[k], + dml_ceil( + mode_lib->vba.BytePerPixelDETC[k], + 2), + mode_lib->vba.SourceScan[k], + mode_lib->vba.ViewportWidth[k] / 2, + mode_lib->vba.ViewportHeight[k] / 2, + mode_lib->vba.SwathWidthY[k] / 2, + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.VMMPageSize, + mode_lib->vba.PTEBufferSizeInRequests, + mode_lib->vba.PDEProcessingBufIn64KBReqs, + mode_lib->vba.PitchC[k], + 0, + &mode_lib->vba.MacroTileWidthC[k], + &MetaRowByteC, + &PixelPTEBytesPerRowC, + &mode_lib->vba.PTEBufferSizeNotExceeded[mode_lib->vba.VoltageLevel], + &mode_lib->vba.dpte_row_height_chroma[k], + &mode_lib->vba.meta_row_height_chroma[k]); + mode_lib->vba.PrefetchSourceLinesC[k] = CalculatePrefetchSourceLines( + mode_lib, + mode_lib->vba.VRatio[k] / 2, + mode_lib->vba.VTAPsChroma[k], + mode_lib->vba.Interlace[k], + mode_lib->vba.ProgressiveToInterlaceUnitInOPP, + mode_lib->vba.SwathHeightC[k], + mode_lib->vba.ViewportYStartC[k], + &mode_lib->vba.VInitPreFillC[k], + &mode_lib->vba.MaxNumSwathC[k]); + } else { + PixelPTEBytesPerRowC = 0; + PDEAndMetaPTEBytesFrameC = 0; + MetaRowByteC = 0; + mode_lib->vba.MaxNumSwathC[k] = 0; + mode_lib->vba.PrefetchSourceLinesC[k] = 0; + } + + mode_lib->vba.PixelPTEBytesPerRow[k] = PixelPTEBytesPerRowY + PixelPTEBytesPerRowC; + mode_lib->vba.PDEAndMetaPTEBytesFrame[k] = PDEAndMetaPTEBytesFrameY + + PDEAndMetaPTEBytesFrameC; + mode_lib->vba.MetaRowByte[k] = MetaRowByteY + MetaRowByteC; + + CalculateActiveRowBandwidth( + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.SourcePixelFormat[k], + mode_lib->vba.VRatio[k], + mode_lib->vba.DCCEnable[k], + mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k], + MetaRowByteY, + MetaRowByteC, + mode_lib->vba.meta_row_height[k], + mode_lib->vba.meta_row_height_chroma[k], + PixelPTEBytesPerRowY, + PixelPTEBytesPerRowC, + mode_lib->vba.dpte_row_height[k], + mode_lib->vba.dpte_row_height_chroma[k], + &mode_lib->vba.meta_row_bw[k], + &mode_lib->vba.dpte_row_bw[k], + &mode_lib->vba.qual_row_bw[k]); + } + + mode_lib->vba.TCalc = 24.0 / mode_lib->vba.DCFClkDeepSleep; + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.BlendingAndTiming[k] == k) { + if (mode_lib->vba.WritebackEnable[k] == true) { + mode_lib->vba.WritebackDelay[mode_lib->vba.VoltageLevel][k] = + mode_lib->vba.WritebackLatency + + CalculateWriteBackDelay( + mode_lib->vba.WritebackPixelFormat[k], + mode_lib->vba.WritebackHRatio[k], + mode_lib->vba.WritebackVRatio[k], + mode_lib->vba.WritebackLumaHTaps[k], + mode_lib->vba.WritebackLumaVTaps[k], + mode_lib->vba.WritebackChromaHTaps[k], + mode_lib->vba.WritebackChromaVTaps[k], + mode_lib->vba.WritebackDestinationWidth[k]) + / mode_lib->vba.DISPCLK; + } else + mode_lib->vba.WritebackDelay[mode_lib->vba.VoltageLevel][k] = 0; + for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) { + if (mode_lib->vba.BlendingAndTiming[j] == k + && mode_lib->vba.WritebackEnable[j] == true) { + mode_lib->vba.WritebackDelay[mode_lib->vba.VoltageLevel][k] = + dml_max( + mode_lib->vba.WritebackDelay[mode_lib->vba.VoltageLevel][k], + mode_lib->vba.WritebackLatency + + CalculateWriteBackDelay( + mode_lib->vba.WritebackPixelFormat[j], + mode_lib->vba.WritebackHRatio[j], + mode_lib->vba.WritebackVRatio[j], + mode_lib->vba.WritebackLumaHTaps[j], + mode_lib->vba.WritebackLumaVTaps[j], + mode_lib->vba.WritebackChromaHTaps[j], + mode_lib->vba.WritebackChromaVTaps[j], + mode_lib->vba.WritebackDestinationWidth[j]) + / mode_lib->vba.DISPCLK); + } + } + } + } + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) + for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) + if (mode_lib->vba.BlendingAndTiming[k] == j) + mode_lib->vba.WritebackDelay[mode_lib->vba.VoltageLevel][k] = + mode_lib->vba.WritebackDelay[mode_lib->vba.VoltageLevel][j]; + + mode_lib->vba.VStartupLines = 13; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.MaxVStartupLines[k] = + mode_lib->vba.VTotal[k] - mode_lib->vba.VActive[k] + - dml_max( + 1.0, + dml_ceil( + mode_lib->vba.WritebackDelay[mode_lib->vba.VoltageLevel][k] + / (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]), + 1)); + } + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) + mode_lib->vba.MaximumMaxVStartupLines = dml_max( + mode_lib->vba.MaximumMaxVStartupLines, + mode_lib->vba.MaxVStartupLines[k]); + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.cursor_bw[k] = 0.0; + for (j = 0; j < mode_lib->vba.NumberOfCursors[k]; ++j) + mode_lib->vba.cursor_bw[k] += mode_lib->vba.CursorWidth[k][j] + * mode_lib->vba.CursorBPP[k][j] / 8.0 + / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) + * mode_lib->vba.VRatio[k]; + } + + do { + double MaxTotalRDBandwidth = 0; + bool DestinationLineTimesForPrefetchLessThan2 = false; + bool VRatioPrefetchMoreThan4 = false; + bool prefetch_vm_bw_valid = true; + bool prefetch_row_bw_valid = true; + double TWait = CalculateTWait( + mode_lib->vba.PrefetchMode, + mode_lib->vba.DRAMClockChangeLatency, + mode_lib->vba.UrgentLatency, + mode_lib->vba.SREnterPlusExitTime); + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.XFCEnabled[k] == true) { + mode_lib->vba.XFCRemoteSurfaceFlipDelay = + CalculateRemoteSurfaceFlipDelay( + mode_lib, + mode_lib->vba.VRatio[k], + mode_lib->vba.SwathWidthY[k], + dml_ceil( + mode_lib->vba.BytePerPixelDETY[k], + 1), + mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k], + mode_lib->vba.XFCTSlvVupdateOffset, + mode_lib->vba.XFCTSlvVupdateWidth, + mode_lib->vba.XFCTSlvVreadyOffset, + mode_lib->vba.XFCXBUFLatencyTolerance, + mode_lib->vba.XFCFillBWOverhead, + mode_lib->vba.XFCSlvChunkSize, + mode_lib->vba.XFCBusTransportTime, + mode_lib->vba.TCalc, + TWait, + &mode_lib->vba.SrcActiveDrainRate, + &mode_lib->vba.TInitXFill, + &mode_lib->vba.TslvChk); + } else { + mode_lib->vba.XFCRemoteSurfaceFlipDelay = 0; + } + mode_lib->vba.ErrorResult[k] = + CalculatePrefetchSchedule( + mode_lib, + mode_lib->vba.DPPCLK[k], + mode_lib->vba.DISPCLK, + mode_lib->vba.PixelClock[k], + mode_lib->vba.DCFClkDeepSleep, + mode_lib->vba.DSCDelay[k], + mode_lib->vba.DPPPerPlane[k], + mode_lib->vba.ScalerEnabled[k], + mode_lib->vba.NumberOfCursors[k], + mode_lib->vba.DPPCLKDelaySubtotal, + mode_lib->vba.DPPCLKDelaySCL, + mode_lib->vba.DPPCLKDelaySCLLBOnly, + mode_lib->vba.DPPCLKDelayCNVCFormater, + mode_lib->vba.DPPCLKDelayCNVCCursor, + mode_lib->vba.DISPCLKDelaySubtotal, + (unsigned int) (mode_lib->vba.SwathWidthY[k] + / mode_lib->vba.HRatio[k]), + mode_lib->vba.OutputFormat[k], + mode_lib->vba.VTotal[k] + - mode_lib->vba.VActive[k], + mode_lib->vba.HTotal[k], + mode_lib->vba.MaxInterDCNTileRepeaters, + dml_min( + mode_lib->vba.VStartupLines, + mode_lib->vba.MaxVStartupLines[k]), + mode_lib->vba.MaxPageTableLevels, + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.DynamicMetadataEnable[k], + mode_lib->vba.DynamicMetadataLinesBeforeActiveRequired[k], + mode_lib->vba.DynamicMetadataTransmittedBytes[k], + mode_lib->vba.DCCEnable[k], + mode_lib->vba.UrgentLatency, + mode_lib->vba.UrgentExtraLatency, + mode_lib->vba.TCalc, + mode_lib->vba.PDEAndMetaPTEBytesFrame[k], + mode_lib->vba.MetaRowByte[k], + mode_lib->vba.PixelPTEBytesPerRow[k], + mode_lib->vba.PrefetchSourceLinesY[k], + mode_lib->vba.SwathWidthY[k], + mode_lib->vba.BytePerPixelDETY[k], + mode_lib->vba.VInitPreFillY[k], + mode_lib->vba.MaxNumSwathY[k], + mode_lib->vba.PrefetchSourceLinesC[k], + mode_lib->vba.BytePerPixelDETC[k], + mode_lib->vba.VInitPreFillC[k], + mode_lib->vba.MaxNumSwathC[k], + mode_lib->vba.SwathHeightY[k], + mode_lib->vba.SwathHeightC[k], + TWait, + mode_lib->vba.XFCEnabled[k], + mode_lib->vba.XFCRemoteSurfaceFlipDelay, + mode_lib->vba.Interlace[k], + mode_lib->vba.ProgressiveToInterlaceUnitInOPP, + &mode_lib->vba.DSTXAfterScaler[k], + &mode_lib->vba.DSTYAfterScaler[k], + &mode_lib->vba.DestinationLinesForPrefetch[k], + &mode_lib->vba.PrefetchBandwidth[k], + &mode_lib->vba.DestinationLinesToRequestVMInVBlank[k], + &mode_lib->vba.DestinationLinesToRequestRowInVBlank[k], + &mode_lib->vba.VRatioPrefetchY[k], + &mode_lib->vba.VRatioPrefetchC[k], + &mode_lib->vba.RequiredPrefetchPixDataBW[k], + &mode_lib->vba.VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, + &mode_lib->vba.Tno_bw[k], + &mode_lib->vba.VUpdateOffsetPix[k], + &mode_lib->vba.VUpdateWidthPix[k], + &mode_lib->vba.VReadyOffsetPix[k]); + if (mode_lib->vba.BlendingAndTiming[k] == k) { + mode_lib->vba.VStartup[k] = dml_min( + mode_lib->vba.VStartupLines, + mode_lib->vba.MaxVStartupLines[k]); + if (mode_lib->vba.VStartupRequiredWhenNotEnoughTimeForDynamicMetadata + != 0) { + mode_lib->vba.VStartup[k] = + mode_lib->vba.VStartupRequiredWhenNotEnoughTimeForDynamicMetadata; + } + } else { + mode_lib->vba.VStartup[k] = + dml_min( + mode_lib->vba.VStartupLines, + mode_lib->vba.MaxVStartupLines[mode_lib->vba.BlendingAndTiming[k]]); + } + } + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + + if (mode_lib->vba.PDEAndMetaPTEBytesFrame[k] == 0) + mode_lib->vba.prefetch_vm_bw[k] = 0; + else if (mode_lib->vba.DestinationLinesToRequestVMInVBlank[k] > 0) { + mode_lib->vba.prefetch_vm_bw[k] = + (double) mode_lib->vba.PDEAndMetaPTEBytesFrame[k] + / (mode_lib->vba.DestinationLinesToRequestVMInVBlank[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]); + } else { + mode_lib->vba.prefetch_vm_bw[k] = 0; + prefetch_vm_bw_valid = false; + } + if (mode_lib->vba.MetaRowByte[k] + mode_lib->vba.PixelPTEBytesPerRow[k] + == 0) + mode_lib->vba.prefetch_row_bw[k] = 0; + else if (mode_lib->vba.DestinationLinesToRequestRowInVBlank[k] > 0) { + mode_lib->vba.prefetch_row_bw[k] = + (double) (mode_lib->vba.MetaRowByte[k] + + mode_lib->vba.PixelPTEBytesPerRow[k]) + / (mode_lib->vba.DestinationLinesToRequestRowInVBlank[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]); + } else { + mode_lib->vba.prefetch_row_bw[k] = 0; + prefetch_row_bw_valid = false; + } + + MaxTotalRDBandwidth = + MaxTotalRDBandwidth + mode_lib->vba.cursor_bw[k] + + dml_max( + mode_lib->vba.prefetch_vm_bw[k], + dml_max( + mode_lib->vba.prefetch_row_bw[k], + dml_max( + mode_lib->vba.ReadBandwidthPlaneLuma[k] + + mode_lib->vba.ReadBandwidthPlaneChroma[k], + mode_lib->vba.RequiredPrefetchPixDataBW[k]) + + mode_lib->vba.meta_row_bw[k] + + mode_lib->vba.dpte_row_bw[k])); + + if (mode_lib->vba.DestinationLinesForPrefetch[k] < 2) + DestinationLineTimesForPrefetchLessThan2 = true; + if (mode_lib->vba.VRatioPrefetchY[k] > 4 + || mode_lib->vba.VRatioPrefetchC[k] > 4) + VRatioPrefetchMoreThan4 = true; + } + + if (MaxTotalRDBandwidth <= mode_lib->vba.ReturnBW && prefetch_vm_bw_valid + && prefetch_row_bw_valid && !VRatioPrefetchMoreThan4 + && !DestinationLineTimesForPrefetchLessThan2) + mode_lib->vba.PrefetchModeSupported = true; + else { + mode_lib->vba.PrefetchModeSupported = false; + dml_print( + "DML: CalculatePrefetchSchedule ***failed***. Bandwidth violation. Results are NOT valid\n"); + } + + if (mode_lib->vba.PrefetchModeSupported == true) { + double final_flip_bw[DC__NUM_DPP__MAX]; + unsigned int ImmediateFlipBytes[DC__NUM_DPP__MAX]; + double total_dcn_read_bw_with_flip = 0; + + mode_lib->vba.BandwidthAvailableForImmediateFlip = mode_lib->vba.ReturnBW; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.BandwidthAvailableForImmediateFlip = + mode_lib->vba.BandwidthAvailableForImmediateFlip + - mode_lib->vba.cursor_bw[k] + - dml_max( + mode_lib->vba.ReadBandwidthPlaneLuma[k] + + mode_lib->vba.ReadBandwidthPlaneChroma[k] + + mode_lib->vba.qual_row_bw[k], + mode_lib->vba.PrefetchBandwidth[k]); + } + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + ImmediateFlipBytes[k] = 0; + if ((mode_lib->vba.SourcePixelFormat[k] != dm_420_8 + && mode_lib->vba.SourcePixelFormat[k] != dm_420_10)) { + ImmediateFlipBytes[k] = + mode_lib->vba.PDEAndMetaPTEBytesFrame[k] + + mode_lib->vba.MetaRowByte[k] + + mode_lib->vba.PixelPTEBytesPerRow[k]; + } + } + mode_lib->vba.TotImmediateFlipBytes = 0; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if ((mode_lib->vba.SourcePixelFormat[k] != dm_420_8 + && mode_lib->vba.SourcePixelFormat[k] != dm_420_10)) { + mode_lib->vba.TotImmediateFlipBytes = + mode_lib->vba.TotImmediateFlipBytes + + ImmediateFlipBytes[k]; + } + } + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + CalculateFlipSchedule( + mode_lib, + mode_lib->vba.UrgentExtraLatency, + mode_lib->vba.UrgentLatency, + mode_lib->vba.MaxPageTableLevels, + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.BandwidthAvailableForImmediateFlip, + mode_lib->vba.TotImmediateFlipBytes, + mode_lib->vba.SourcePixelFormat[k], + ImmediateFlipBytes[k], + mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k], + mode_lib->vba.VRatio[k], + mode_lib->vba.Tno_bw[k], + mode_lib->vba.PDEAndMetaPTEBytesFrame[k], + mode_lib->vba.MetaRowByte[k], + mode_lib->vba.PixelPTEBytesPerRow[k], + mode_lib->vba.DCCEnable[k], + mode_lib->vba.dpte_row_height[k], + mode_lib->vba.meta_row_height[k], + mode_lib->vba.qual_row_bw[k], + &mode_lib->vba.DestinationLinesToRequestVMInImmediateFlip[k], + &mode_lib->vba.DestinationLinesToRequestRowInImmediateFlip[k], + &final_flip_bw[k], + &mode_lib->vba.ImmediateFlipSupportedForPipe[k]); + } + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + total_dcn_read_bw_with_flip = + total_dcn_read_bw_with_flip + + mode_lib->vba.cursor_bw[k] + + dml_max( + mode_lib->vba.prefetch_vm_bw[k], + dml_max( + mode_lib->vba.prefetch_row_bw[k], + final_flip_bw[k] + + dml_max( + mode_lib->vba.ReadBandwidthPlaneLuma[k] + + mode_lib->vba.ReadBandwidthPlaneChroma[k], + mode_lib->vba.RequiredPrefetchPixDataBW[k]))); + } + mode_lib->vba.ImmediateFlipSupported = true; + if (total_dcn_read_bw_with_flip > mode_lib->vba.ReturnBW) { + mode_lib->vba.ImmediateFlipSupported = false; + } + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.ImmediateFlipSupportedForPipe[k] == false) { + mode_lib->vba.ImmediateFlipSupported = false; + } + } + } else { + mode_lib->vba.ImmediateFlipSupported = false; + } + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.ErrorResult[k]) { + mode_lib->vba.PrefetchModeSupported = false; + dml_print( + "DML: CalculatePrefetchSchedule ***failed***. Prefetch schedule violation. Results are NOT valid\n"); + } + } + + mode_lib->vba.VStartupLines = mode_lib->vba.VStartupLines + 1; + } while (!((mode_lib->vba.PrefetchModeSupported + && (!mode_lib->vba.ImmediateFlipSupport + || mode_lib->vba.ImmediateFlipSupported)) + || mode_lib->vba.MaximumMaxVStartupLines < mode_lib->vba.VStartupLines)); + + //Display Pipeline Delivery Time in Prefetch + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.VRatioPrefetchY[k] <= 1) { + mode_lib->vba.DisplayPipeLineDeliveryTimeLumaPrefetch[k] = + mode_lib->vba.SwathWidthY[k] * mode_lib->vba.DPPPerPlane[k] + / mode_lib->vba.HRatio[k] + / mode_lib->vba.PixelClock[k]; + } else { + mode_lib->vba.DisplayPipeLineDeliveryTimeLumaPrefetch[k] = + mode_lib->vba.SwathWidthY[k] + / mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] + / mode_lib->vba.DPPCLK[k]; + } + if (mode_lib->vba.BytePerPixelDETC[k] == 0) { + mode_lib->vba.DisplayPipeLineDeliveryTimeChromaPrefetch[k] = 0; + } else { + if (mode_lib->vba.VRatioPrefetchC[k] <= 1) { + mode_lib->vba.DisplayPipeLineDeliveryTimeChromaPrefetch[k] = + mode_lib->vba.SwathWidthY[k] + * mode_lib->vba.DPPPerPlane[k] + / mode_lib->vba.HRatio[k] + / mode_lib->vba.PixelClock[k]; + } else { + mode_lib->vba.DisplayPipeLineDeliveryTimeChromaPrefetch[k] = + mode_lib->vba.SwathWidthY[k] + / mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] + / mode_lib->vba.DPPCLK[k]; + } + } + } + + // Min TTUVBlank + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.PrefetchMode == 0) { + mode_lib->vba.AllowDRAMClockChangeDuringVBlank[k] = true; + mode_lib->vba.AllowDRAMSelfRefreshDuringVBlank[k] = true; + mode_lib->vba.MinTTUVBlank[k] = dml_max( + mode_lib->vba.DRAMClockChangeWatermark, + dml_max( + mode_lib->vba.StutterEnterPlusExitWatermark, + mode_lib->vba.UrgentWatermark)); + } else if (mode_lib->vba.PrefetchMode == 1) { + mode_lib->vba.AllowDRAMClockChangeDuringVBlank[k] = false; + mode_lib->vba.AllowDRAMSelfRefreshDuringVBlank[k] = true; + mode_lib->vba.MinTTUVBlank[k] = dml_max( + mode_lib->vba.StutterEnterPlusExitWatermark, + mode_lib->vba.UrgentWatermark); + } else { + mode_lib->vba.AllowDRAMClockChangeDuringVBlank[k] = false; + mode_lib->vba.AllowDRAMSelfRefreshDuringVBlank[k] = false; + mode_lib->vba.MinTTUVBlank[k] = mode_lib->vba.UrgentWatermark; + } + if (!mode_lib->vba.DynamicMetadataEnable[k]) + mode_lib->vba.MinTTUVBlank[k] = mode_lib->vba.TCalc + + mode_lib->vba.MinTTUVBlank[k]; + } + + // DCC Configuration + mode_lib->vba.ActiveDPPs = 0; + // NB P-State/DRAM Clock Change Support + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.ActiveDPPs = mode_lib->vba.ActiveDPPs + mode_lib->vba.DPPPerPlane[k]; + } + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + double EffectiveLBLatencyHidingY; + double EffectiveLBLatencyHidingC; + double DPPOutputBufferLinesY; + double DPPOutputBufferLinesC; + double DPPOPPBufferingY; + double MaxDETBufferingTimeY; + double ActiveDRAMClockChangeLatencyMarginY; + + mode_lib->vba.LBLatencyHidingSourceLinesY = + dml_min( + mode_lib->vba.MaxLineBufferLines, + (unsigned int) dml_floor( + (double) mode_lib->vba.LineBufferSize + / mode_lib->vba.LBBitPerPixel[k] + / (mode_lib->vba.SwathWidthY[k] + / dml_max( + mode_lib->vba.HRatio[k], + 1.0)), + 1)) - (mode_lib->vba.vtaps[k] - 1); + + mode_lib->vba.LBLatencyHidingSourceLinesC = + dml_min( + mode_lib->vba.MaxLineBufferLines, + (unsigned int) dml_floor( + (double) mode_lib->vba.LineBufferSize + / mode_lib->vba.LBBitPerPixel[k] + / (mode_lib->vba.SwathWidthY[k] + / 2.0 + / dml_max( + mode_lib->vba.HRatio[k] + / 2, + 1.0)), + 1)) + - (mode_lib->vba.VTAPsChroma[k] - 1); + + EffectiveLBLatencyHidingY = mode_lib->vba.LBLatencyHidingSourceLinesY + / mode_lib->vba.VRatio[k] + * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + + EffectiveLBLatencyHidingC = mode_lib->vba.LBLatencyHidingSourceLinesC + / (mode_lib->vba.VRatio[k] / 2) + * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + + if (mode_lib->vba.SwathWidthY[k] > 2 * mode_lib->vba.DPPOutputBufferPixels) { + DPPOutputBufferLinesY = mode_lib->vba.DPPOutputBufferPixels + / mode_lib->vba.SwathWidthY[k]; + } else if (mode_lib->vba.SwathWidthY[k] > mode_lib->vba.DPPOutputBufferPixels) { + DPPOutputBufferLinesY = 0.5; + } else { + DPPOutputBufferLinesY = 1; + } + + if (mode_lib->vba.SwathWidthY[k] / 2 > 2 * mode_lib->vba.DPPOutputBufferPixels) { + DPPOutputBufferLinesC = mode_lib->vba.DPPOutputBufferPixels + / (mode_lib->vba.SwathWidthY[k] / 2); + } else if (mode_lib->vba.SwathWidthY[k] / 2 > mode_lib->vba.DPPOutputBufferPixels) { + DPPOutputBufferLinesC = 0.5; + } else { + DPPOutputBufferLinesC = 1; + } + + DPPOPPBufferingY = (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) + * (DPPOutputBufferLinesY + mode_lib->vba.OPPOutputBufferLines); + MaxDETBufferingTimeY = mode_lib->vba.FullDETBufferingTimeY[k] + + (mode_lib->vba.LinesInDETY[k] + - mode_lib->vba.LinesInDETYRoundedDownToSwath[k]) + / mode_lib->vba.SwathHeightY[k] + * (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]); + + ActiveDRAMClockChangeLatencyMarginY = DPPOPPBufferingY + EffectiveLBLatencyHidingY + + MaxDETBufferingTimeY - mode_lib->vba.DRAMClockChangeWatermark; + + if (mode_lib->vba.ActiveDPPs > 1) { + ActiveDRAMClockChangeLatencyMarginY = + ActiveDRAMClockChangeLatencyMarginY + - (1 - 1 / (mode_lib->vba.ActiveDPPs - 1)) + * mode_lib->vba.SwathHeightY[k] + * (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]); + } + + if (mode_lib->vba.BytePerPixelDETC[k] > 0) { + double DPPOPPBufferingC = (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) + * (DPPOutputBufferLinesC + + mode_lib->vba.OPPOutputBufferLines); + double MaxDETBufferingTimeC = + mode_lib->vba.FullDETBufferingTimeC[k] + + (mode_lib->vba.LinesInDETC[k] + - mode_lib->vba.LinesInDETCRoundedDownToSwath[k]) + / mode_lib->vba.SwathHeightC[k] + * (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]); + double ActiveDRAMClockChangeLatencyMarginC = DPPOPPBufferingC + + EffectiveLBLatencyHidingC + MaxDETBufferingTimeC + - mode_lib->vba.DRAMClockChangeWatermark; + + if (mode_lib->vba.ActiveDPPs > 1) { + ActiveDRAMClockChangeLatencyMarginC = + ActiveDRAMClockChangeLatencyMarginC + - (1 + - 1 + / (mode_lib->vba.ActiveDPPs + - 1)) + * mode_lib->vba.SwathHeightC[k] + * (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]); + } + mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] = dml_min( + ActiveDRAMClockChangeLatencyMarginY, + ActiveDRAMClockChangeLatencyMarginC); + } else { + mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] = + ActiveDRAMClockChangeLatencyMarginY; + } + + if (mode_lib->vba.WritebackEnable[k]) { + double WritebackDRAMClockChangeLatencyMargin; + + if (mode_lib->vba.WritebackPixelFormat[k] == dm_444_32) { + WritebackDRAMClockChangeLatencyMargin = + (double) (mode_lib->vba.WritebackInterfaceLumaBufferSize + + mode_lib->vba.WritebackInterfaceChromaBufferSize) + / (mode_lib->vba.WritebackDestinationWidth[k] + * mode_lib->vba.WritebackDestinationHeight[k] + / (mode_lib->vba.WritebackSourceHeight[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) + * 4) + - mode_lib->vba.WritebackDRAMClockChangeWatermark; + } else if (mode_lib->vba.WritebackPixelFormat[k] == dm_420_10) { + WritebackDRAMClockChangeLatencyMargin = + dml_min( + (double) mode_lib->vba.WritebackInterfaceLumaBufferSize + * 8.0 / 10, + 2.0 + * mode_lib->vba.WritebackInterfaceChromaBufferSize + * 8 / 10) + / (mode_lib->vba.WritebackDestinationWidth[k] + * mode_lib->vba.WritebackDestinationHeight[k] + / (mode_lib->vba.WritebackSourceHeight[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k])) + - mode_lib->vba.WritebackDRAMClockChangeWatermark; + } else { + WritebackDRAMClockChangeLatencyMargin = + dml_min( + (double) mode_lib->vba.WritebackInterfaceLumaBufferSize, + 2.0 + * mode_lib->vba.WritebackInterfaceChromaBufferSize) + / (mode_lib->vba.WritebackDestinationWidth[k] + * mode_lib->vba.WritebackDestinationHeight[k] + / (mode_lib->vba.WritebackSourceHeight[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k])) + - mode_lib->vba.WritebackDRAMClockChangeWatermark; + } + mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] = dml_min( + mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k], + WritebackDRAMClockChangeLatencyMargin); + } + } + + mode_lib->vba.MinActiveDRAMClockChangeMargin = 999999; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] + < mode_lib->vba.MinActiveDRAMClockChangeMargin) { + mode_lib->vba.MinActiveDRAMClockChangeMargin = + mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k]; + } + } + + mode_lib->vba.MinActiveDRAMClockChangeLatencySupported = + mode_lib->vba.MinActiveDRAMClockChangeMargin + + mode_lib->vba.DRAMClockChangeLatency; + + if (mode_lib->vba.MinActiveDRAMClockChangeMargin > 0) { + mode_lib->vba.DRAMClockChangeSupport = dm_dram_clock_change_vactive; + } else { + if (mode_lib->vba.SynchronizedVBlank || mode_lib->vba.NumberOfActivePlanes == 1) { + mode_lib->vba.DRAMClockChangeSupport = dm_dram_clock_change_vblank; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (!mode_lib->vba.AllowDRAMClockChangeDuringVBlank[k]) { + mode_lib->vba.DRAMClockChangeSupport = + dm_dram_clock_change_unsupported; + } + } + } else { + mode_lib->vba.DRAMClockChangeSupport = dm_dram_clock_change_unsupported; + } + } + + //XFC Parameters: + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.XFCEnabled[k] == true) { + double TWait; + + mode_lib->vba.XFCSlaveVUpdateOffset[k] = mode_lib->vba.XFCTSlvVupdateOffset; + mode_lib->vba.XFCSlaveVupdateWidth[k] = mode_lib->vba.XFCTSlvVupdateWidth; + mode_lib->vba.XFCSlaveVReadyOffset[k] = mode_lib->vba.XFCTSlvVreadyOffset; + TWait = CalculateTWait( + mode_lib->vba.PrefetchMode, + mode_lib->vba.DRAMClockChangeLatency, + mode_lib->vba.UrgentLatency, + mode_lib->vba.SREnterPlusExitTime); + mode_lib->vba.XFCRemoteSurfaceFlipDelay = CalculateRemoteSurfaceFlipDelay( + mode_lib, + mode_lib->vba.VRatio[k], + mode_lib->vba.SwathWidthY[k], + dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1), + mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k], + mode_lib->vba.XFCTSlvVupdateOffset, + mode_lib->vba.XFCTSlvVupdateWidth, + mode_lib->vba.XFCTSlvVreadyOffset, + mode_lib->vba.XFCXBUFLatencyTolerance, + mode_lib->vba.XFCFillBWOverhead, + mode_lib->vba.XFCSlvChunkSize, + mode_lib->vba.XFCBusTransportTime, + mode_lib->vba.TCalc, + TWait, + &mode_lib->vba.SrcActiveDrainRate, + &mode_lib->vba.TInitXFill, + &mode_lib->vba.TslvChk); + mode_lib->vba.XFCRemoteSurfaceFlipLatency[k] = + dml_floor( + mode_lib->vba.XFCRemoteSurfaceFlipDelay + / (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]), + 1); + mode_lib->vba.XFCTransferDelay[k] = + dml_ceil( + mode_lib->vba.XFCBusTransportTime + / (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]), + 1); + mode_lib->vba.XFCPrechargeDelay[k] = + dml_ceil( + (mode_lib->vba.XFCBusTransportTime + + mode_lib->vba.TInitXFill + + mode_lib->vba.TslvChk) + / (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]), + 1); + mode_lib->vba.InitFillLevel = mode_lib->vba.XFCXBUFLatencyTolerance + * mode_lib->vba.SrcActiveDrainRate; + mode_lib->vba.FinalFillMargin = + (mode_lib->vba.DestinationLinesToRequestVMInVBlank[k] + + mode_lib->vba.DestinationLinesToRequestRowInVBlank[k]) + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k] + * mode_lib->vba.SrcActiveDrainRate + + mode_lib->vba.XFCFillConstant; + mode_lib->vba.FinalFillLevel = mode_lib->vba.XFCRemoteSurfaceFlipDelay + * mode_lib->vba.SrcActiveDrainRate + + mode_lib->vba.FinalFillMargin; + mode_lib->vba.RemainingFillLevel = dml_max( + 0.0, + mode_lib->vba.FinalFillLevel - mode_lib->vba.InitFillLevel); + mode_lib->vba.TFinalxFill = mode_lib->vba.RemainingFillLevel + / (mode_lib->vba.SrcActiveDrainRate + * mode_lib->vba.XFCFillBWOverhead / 100); + mode_lib->vba.XFCPrefetchMargin[k] = + mode_lib->vba.XFCRemoteSurfaceFlipDelay + + mode_lib->vba.TFinalxFill + + (mode_lib->vba.DestinationLinesToRequestVMInVBlank[k] + + mode_lib->vba.DestinationLinesToRequestRowInVBlank[k]) + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]; + } else { + mode_lib->vba.XFCSlaveVUpdateOffset[k] = 0; + mode_lib->vba.XFCSlaveVupdateWidth[k] = 0; + mode_lib->vba.XFCSlaveVReadyOffset[k] = 0; + mode_lib->vba.XFCRemoteSurfaceFlipLatency[k] = 0; + mode_lib->vba.XFCPrechargeDelay[k] = 0; + mode_lib->vba.XFCTransferDelay[k] = 0; + mode_lib->vba.XFCPrefetchMargin[k] = 0; + } + } +} + +static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib) +{ + double BytePerPixDETY; + double BytePerPixDETC; + double Read256BytesBlockHeightY; + double Read256BytesBlockHeightC; + double Read256BytesBlockWidthY; + double Read256BytesBlockWidthC; + double MaximumSwathHeightY; + double MaximumSwathHeightC; + double MinimumSwathHeightY; + double MinimumSwathHeightC; + double SwathWidth; + double SwathWidthGranularityY; + double SwathWidthGranularityC; + double RoundedUpMaxSwathSizeBytesY; + double RoundedUpMaxSwathSizeBytesC; + unsigned int j, k; + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + bool MainPlaneDoesODMCombine = false; + + if (mode_lib->vba.SourcePixelFormat[k] == dm_444_64) { + BytePerPixDETY = 8; + BytePerPixDETC = 0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_32) { + BytePerPixDETY = 4; + BytePerPixDETC = 0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_16) { + BytePerPixDETY = 2; + BytePerPixDETC = 0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_8) { + BytePerPixDETY = 1; + BytePerPixDETC = 0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_8) { + BytePerPixDETY = 1; + BytePerPixDETC = 2; + } else { + BytePerPixDETY = 4.0 / 3.0; + BytePerPixDETC = 8.0 / 3.0; + } + + if ((mode_lib->vba.SourcePixelFormat[k] == dm_444_64 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_32 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_16 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_8)) { + if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear) { + Read256BytesBlockHeightY = 1; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_64) { + Read256BytesBlockHeightY = 4; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_32 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_16) { + Read256BytesBlockHeightY = 8; + } else { + Read256BytesBlockHeightY = 16; + } + Read256BytesBlockWidthY = 256 / dml_ceil(BytePerPixDETY, 1) + / Read256BytesBlockHeightY; + Read256BytesBlockHeightC = 0; + Read256BytesBlockWidthC = 0; + } else { + if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear) { + Read256BytesBlockHeightY = 1; + Read256BytesBlockHeightC = 1; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_8) { + Read256BytesBlockHeightY = 16; + Read256BytesBlockHeightC = 8; + } else { + Read256BytesBlockHeightY = 8; + Read256BytesBlockHeightC = 8; + } + Read256BytesBlockWidthY = 256 / dml_ceil(BytePerPixDETY, 1) + / Read256BytesBlockHeightY; + Read256BytesBlockWidthC = 256 / dml_ceil(BytePerPixDETC, 2) + / Read256BytesBlockHeightC; + } + + if (mode_lib->vba.SourceScan[k] == dm_horz) { + MaximumSwathHeightY = Read256BytesBlockHeightY; + MaximumSwathHeightC = Read256BytesBlockHeightC; + } else { + MaximumSwathHeightY = Read256BytesBlockWidthY; + MaximumSwathHeightC = Read256BytesBlockWidthC; + } + + if ((mode_lib->vba.SourcePixelFormat[k] == dm_444_64 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_32 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_16 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_8)) { + if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear + || (mode_lib->vba.SourcePixelFormat[k] == dm_444_64 + && (mode_lib->vba.SurfaceTiling[k] + == dm_sw_4kb_s + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_4kb_s_x + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_64kb_s + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_64kb_s_t + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_64kb_s_x + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_var_s + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_var_s_x) + && mode_lib->vba.SourceScan[k] == dm_horz)) { + MinimumSwathHeightY = MaximumSwathHeightY; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_8 + && mode_lib->vba.SourceScan[k] != dm_horz) { + MinimumSwathHeightY = MaximumSwathHeightY; + } else { + MinimumSwathHeightY = MaximumSwathHeightY / 2.0; + } + MinimumSwathHeightC = MaximumSwathHeightC; + } else { + if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear) { + MinimumSwathHeightY = MaximumSwathHeightY; + MinimumSwathHeightC = MaximumSwathHeightC; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_8 + && mode_lib->vba.SourceScan[k] == dm_horz) { + MinimumSwathHeightY = MaximumSwathHeightY / 2.0; + MinimumSwathHeightC = MaximumSwathHeightC; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_10 + && mode_lib->vba.SourceScan[k] == dm_horz) { + MinimumSwathHeightC = MaximumSwathHeightC / 2.0; + MinimumSwathHeightY = MaximumSwathHeightY; + } else { + MinimumSwathHeightY = MaximumSwathHeightY; + MinimumSwathHeightC = MaximumSwathHeightC; + } + } + + if (mode_lib->vba.SourceScan[k] == dm_horz) { + SwathWidth = mode_lib->vba.ViewportWidth[k]; + } else { + SwathWidth = mode_lib->vba.ViewportHeight[k]; + } + + if (mode_lib->vba.ODMCombineEnabled[k] == true) { + MainPlaneDoesODMCombine = true; + } + for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) { + if (mode_lib->vba.BlendingAndTiming[k] == j + && mode_lib->vba.ODMCombineEnabled[j] == true) { + MainPlaneDoesODMCombine = true; + } + } + + if (MainPlaneDoesODMCombine == true) { + SwathWidth = dml_min( + SwathWidth, + mode_lib->vba.HActive[k] / 2.0 * mode_lib->vba.HRatio[k]); + } else { + SwathWidth = SwathWidth / mode_lib->vba.DPPPerPlane[k]; + } + + SwathWidthGranularityY = 256 / dml_ceil(BytePerPixDETY, 1) / MaximumSwathHeightY; + RoundedUpMaxSwathSizeBytesY = (dml_ceil( + (double) (SwathWidth - 1), + SwathWidthGranularityY) + SwathWidthGranularityY) * BytePerPixDETY + * MaximumSwathHeightY; + if (mode_lib->vba.SourcePixelFormat[k] == dm_420_10) { + RoundedUpMaxSwathSizeBytesY = dml_ceil(RoundedUpMaxSwathSizeBytesY, 256) + + 256; + } + if (MaximumSwathHeightC > 0) { + SwathWidthGranularityC = 256.0 / dml_ceil(BytePerPixDETC, 2) + / MaximumSwathHeightC; + RoundedUpMaxSwathSizeBytesC = (dml_ceil( + (double) (SwathWidth / 2.0 - 1), + SwathWidthGranularityC) + SwathWidthGranularityC) + * BytePerPixDETC * MaximumSwathHeightC; + if (mode_lib->vba.SourcePixelFormat[k] == dm_420_10) { + RoundedUpMaxSwathSizeBytesC = dml_ceil( + RoundedUpMaxSwathSizeBytesC, + 256) + 256; + } + } else + RoundedUpMaxSwathSizeBytesC = 0.0; + + if (RoundedUpMaxSwathSizeBytesY + RoundedUpMaxSwathSizeBytesC + <= mode_lib->vba.DETBufferSizeInKByte * 1024.0 / 2.0) { + mode_lib->vba.SwathHeightY[k] = MaximumSwathHeightY; + mode_lib->vba.SwathHeightC[k] = MaximumSwathHeightC; + } else { + mode_lib->vba.SwathHeightY[k] = MinimumSwathHeightY; + mode_lib->vba.SwathHeightC[k] = MinimumSwathHeightC; + } + + if (mode_lib->vba.SwathHeightC[k] == 0) { + mode_lib->vba.DETBufferSizeY[k] = mode_lib->vba.DETBufferSizeInKByte * 1024; + mode_lib->vba.DETBufferSizeC[k] = 0; + } else if (mode_lib->vba.SwathHeightY[k] <= mode_lib->vba.SwathHeightC[k]) { + mode_lib->vba.DETBufferSizeY[k] = mode_lib->vba.DETBufferSizeInKByte + * 1024.0 / 2; + mode_lib->vba.DETBufferSizeC[k] = mode_lib->vba.DETBufferSizeInKByte + * 1024.0 / 2; + } else { + mode_lib->vba.DETBufferSizeY[k] = mode_lib->vba.DETBufferSizeInKByte + * 1024.0 * 2 / 3; + mode_lib->vba.DETBufferSizeC[k] = mode_lib->vba.DETBufferSizeInKByte + * 1024.0 / 3; + } + } +} + +bool Calculate256BBlockSizes( + enum source_format_class SourcePixelFormat, + enum dm_swizzle_mode SurfaceTiling, + unsigned int BytePerPixelY, + unsigned int BytePerPixelC, + unsigned int *BlockHeight256BytesY, + unsigned int *BlockHeight256BytesC, + unsigned int *BlockWidth256BytesY, + unsigned int *BlockWidth256BytesC) +{ + if ((SourcePixelFormat == dm_444_64 || SourcePixelFormat == dm_444_32 + || SourcePixelFormat == dm_444_16 + || SourcePixelFormat == dm_444_8)) { + if (SurfaceTiling == dm_sw_linear) { + *BlockHeight256BytesY = 1; + } else if (SourcePixelFormat == dm_444_64) { + *BlockHeight256BytesY = 4; + } else if (SourcePixelFormat == dm_444_8) { + *BlockHeight256BytesY = 16; + } else { + *BlockHeight256BytesY = 8; + } + *BlockWidth256BytesY = 256 / BytePerPixelY / *BlockHeight256BytesY; + *BlockHeight256BytesC = 0; + *BlockWidth256BytesC = 0; + } else { + if (SurfaceTiling == dm_sw_linear) { + *BlockHeight256BytesY = 1; + *BlockHeight256BytesC = 1; + } else if (SourcePixelFormat == dm_420_8) { + *BlockHeight256BytesY = 16; + *BlockHeight256BytesC = 8; + } else { + *BlockHeight256BytesY = 8; + *BlockHeight256BytesC = 8; + } + *BlockWidth256BytesY = 256 / BytePerPixelY / *BlockHeight256BytesY; + *BlockWidth256BytesC = 256 / BytePerPixelC / *BlockHeight256BytesC; + } + return true; +} + +static double CalculateTWait( + unsigned int PrefetchMode, + double DRAMClockChangeLatency, + double UrgentLatency, + double SREnterPlusExitTime) +{ + if (PrefetchMode == 0) { + return dml_max( + DRAMClockChangeLatency + UrgentLatency, + dml_max(SREnterPlusExitTime, UrgentLatency)); + } else if (PrefetchMode == 1) { + return dml_max(SREnterPlusExitTime, UrgentLatency); + } else { + return UrgentLatency; + } +} + +static double CalculateRemoteSurfaceFlipDelay( + struct display_mode_lib *mode_lib, + double VRatio, + double SwathWidth, + double Bpp, + double LineTime, + double XFCTSlvVupdateOffset, + double XFCTSlvVupdateWidth, + double XFCTSlvVreadyOffset, + double XFCXBUFLatencyTolerance, + double XFCFillBWOverhead, + double XFCSlvChunkSize, + double XFCBusTransportTime, + double TCalc, + double TWait, + double *SrcActiveDrainRate, + double *TInitXFill, + double *TslvChk) +{ + double TSlvSetup, AvgfillRate, result; + + *SrcActiveDrainRate = VRatio * SwathWidth * Bpp / LineTime; + TSlvSetup = XFCTSlvVupdateOffset + XFCTSlvVupdateWidth + XFCTSlvVreadyOffset; + *TInitXFill = XFCXBUFLatencyTolerance / (1 + XFCFillBWOverhead / 100); + AvgfillRate = *SrcActiveDrainRate * (1 + XFCFillBWOverhead / 100); + *TslvChk = XFCSlvChunkSize / AvgfillRate; + dml_print( + "DML::CalculateRemoteSurfaceFlipDelay: SrcActiveDrainRate: %f\n", + *SrcActiveDrainRate); + dml_print("DML::CalculateRemoteSurfaceFlipDelay: TSlvSetup: %f\n", TSlvSetup); + dml_print("DML::CalculateRemoteSurfaceFlipDelay: TInitXFill: %f\n", *TInitXFill); + dml_print("DML::CalculateRemoteSurfaceFlipDelay: AvgfillRate: %f\n", AvgfillRate); + dml_print("DML::CalculateRemoteSurfaceFlipDelay: TslvChk: %f\n", *TslvChk); + result = 2 * XFCBusTransportTime + TSlvSetup + TCalc + TWait + *TslvChk + *TInitXFill; // TODO: This doesn't seem to match programming guide + dml_print("DML::CalculateRemoteSurfaceFlipDelay: RemoteSurfaceFlipDelay: %f\n", result); + return result; +} + +static double CalculateWriteBackDISPCLK( + enum source_format_class WritebackPixelFormat, + double PixelClock, + double WritebackHRatio, + double WritebackVRatio, + unsigned int WritebackLumaHTaps, + unsigned int WritebackLumaVTaps, + unsigned int WritebackChromaHTaps, + unsigned int WritebackChromaVTaps, + double WritebackDestinationWidth, + unsigned int HTotal, + unsigned int WritebackChromaLineBufferWidth) +{ + double CalculateWriteBackDISPCLK = + 1.01 * PixelClock + * dml_max( + dml_ceil(WritebackLumaHTaps / 4.0, 1) + / WritebackHRatio, + dml_max( + (WritebackLumaVTaps + * dml_ceil( + 1.0 + / WritebackVRatio, + 1) + * dml_ceil( + WritebackDestinationWidth + / 4.0, + 1) + + dml_ceil( + WritebackDestinationWidth + / 4.0, + 1)) + / (double) HTotal + + dml_ceil( + 1.0 + / WritebackVRatio, + 1) + * (dml_ceil( + WritebackLumaVTaps + / 4.0, + 1) + + 4.0) + / (double) HTotal, + dml_ceil( + 1.0 + / WritebackVRatio, + 1) + * WritebackDestinationWidth + / (double) HTotal)); + if (WritebackPixelFormat != dm_444_32) { + CalculateWriteBackDISPCLK = + dml_max( + CalculateWriteBackDISPCLK, + 1.01 * PixelClock + * dml_max( + dml_ceil( + WritebackChromaHTaps + / 2.0, + 1) + / (2 + * WritebackHRatio), + dml_max( + (WritebackChromaVTaps + * dml_ceil( + 1 + / (2 + * WritebackVRatio), + 1) + * dml_ceil( + WritebackDestinationWidth + / 2.0 + / 2.0, + 1) + + dml_ceil( + WritebackDestinationWidth + / 2.0 + / WritebackChromaLineBufferWidth, + 1)) + / HTotal + + dml_ceil( + 1 + / (2 + * WritebackVRatio), + 1) + * (dml_ceil( + WritebackChromaVTaps + / 4.0, + 1) + + 4) + / HTotal, + dml_ceil( + 1.0 + / (2 + * WritebackVRatio), + 1) + * WritebackDestinationWidth + / 2.0 + / HTotal))); + } + return CalculateWriteBackDISPCLK; +} + +static double CalculateWriteBackDelay( + enum source_format_class WritebackPixelFormat, + double WritebackHRatio, + double WritebackVRatio, + unsigned int WritebackLumaHTaps, + unsigned int WritebackLumaVTaps, + unsigned int WritebackChromaHTaps, + unsigned int WritebackChromaVTaps, + unsigned int WritebackDestinationWidth) +{ + double CalculateWriteBackDelay = + dml_max( + dml_ceil(WritebackLumaHTaps / 4.0, 1) / WritebackHRatio, + WritebackLumaVTaps * dml_ceil(1.0 / WritebackVRatio, 1) + * dml_ceil( + WritebackDestinationWidth + / 4.0, + 1) + + dml_ceil(1.0 / WritebackVRatio, 1) + * (dml_ceil( + WritebackLumaVTaps + / 4.0, + 1) + 4)); + + if (WritebackPixelFormat != dm_444_32) { + CalculateWriteBackDelay = + dml_max( + CalculateWriteBackDelay, + dml_max( + dml_ceil( + WritebackChromaHTaps + / 2.0, + 1) + / (2 + * WritebackHRatio), + WritebackChromaVTaps + * dml_ceil( + 1 + / (2 + * WritebackVRatio), + 1) + * dml_ceil( + WritebackDestinationWidth + / 2.0 + / 2.0, + 1) + + dml_ceil( + 1 + / (2 + * WritebackVRatio), + 1) + * (dml_ceil( + WritebackChromaVTaps + / 4.0, + 1) + + 4))); + } + return CalculateWriteBackDelay; +} + +static void CalculateActiveRowBandwidth( + bool VirtualMemoryEnable, + enum source_format_class SourcePixelFormat, + double VRatio, + bool DCCEnable, + double LineTime, + unsigned int MetaRowByteLuma, + unsigned int MetaRowByteChroma, + unsigned int meta_row_height_luma, + unsigned int meta_row_height_chroma, + unsigned int PixelPTEBytesPerRowLuma, + unsigned int PixelPTEBytesPerRowChroma, + unsigned int dpte_row_height_luma, + unsigned int dpte_row_height_chroma, + double *meta_row_bw, + double *dpte_row_bw, + double *qual_row_bw) +{ + if (DCCEnable != true) { + *meta_row_bw = 0; + } else if (SourcePixelFormat == dm_420_8 || SourcePixelFormat == dm_420_10) { + *meta_row_bw = VRatio * MetaRowByteLuma / (meta_row_height_luma * LineTime) + + VRatio / 2 * MetaRowByteChroma + / (meta_row_height_chroma * LineTime); + } else { + *meta_row_bw = VRatio * MetaRowByteLuma / (meta_row_height_luma * LineTime); + } + + if (VirtualMemoryEnable != true) { + *dpte_row_bw = 0; + } else if (SourcePixelFormat == dm_420_8 || SourcePixelFormat == dm_420_10) { + *dpte_row_bw = VRatio * PixelPTEBytesPerRowLuma / (dpte_row_height_luma * LineTime) + + VRatio / 2 * PixelPTEBytesPerRowChroma + / (dpte_row_height_chroma * LineTime); + } else { + *dpte_row_bw = VRatio * PixelPTEBytesPerRowLuma / (dpte_row_height_luma * LineTime); + } + + if ((SourcePixelFormat == dm_420_8 || SourcePixelFormat == dm_420_10)) { + *qual_row_bw = *meta_row_bw + *dpte_row_bw; + } else { + *qual_row_bw = 0; + } +} + +static void CalculateFlipSchedule( + struct display_mode_lib *mode_lib, + double UrgentExtraLatency, + double UrgentLatency, + unsigned int MaxPageTableLevels, + bool VirtualMemoryEnable, + double BandwidthAvailableForImmediateFlip, + unsigned int TotImmediateFlipBytes, + enum source_format_class SourcePixelFormat, + unsigned int ImmediateFlipBytes, + double LineTime, + double Tno_bw, + double VRatio, + double PDEAndMetaPTEBytesFrame, + unsigned int MetaRowByte, + unsigned int PixelPTEBytesPerRow, + bool DCCEnable, + unsigned int dpte_row_height, + unsigned int meta_row_height, + double qual_row_bw, + double *DestinationLinesToRequestVMInImmediateFlip, + double *DestinationLinesToRequestRowInImmediateFlip, + double *final_flip_bw, + bool *ImmediateFlipSupportedForPipe) +{ + double min_row_time = 0.0; + + if (SourcePixelFormat == dm_420_8 || SourcePixelFormat == dm_420_10) { + *DestinationLinesToRequestVMInImmediateFlip = 0.0; + *DestinationLinesToRequestRowInImmediateFlip = 0.0; + *final_flip_bw = qual_row_bw; + *ImmediateFlipSupportedForPipe = true; + } else { + double TimeForFetchingMetaPTEImmediateFlip; + double TimeForFetchingRowInVBlankImmediateFlip; + + if (VirtualMemoryEnable == true) { + mode_lib->vba.ImmediateFlipBW = BandwidthAvailableForImmediateFlip + * ImmediateFlipBytes / TotImmediateFlipBytes; + TimeForFetchingMetaPTEImmediateFlip = + dml_max( + Tno_bw + + PDEAndMetaPTEBytesFrame + / mode_lib->vba.ImmediateFlipBW, + dml_max( + UrgentExtraLatency + + UrgentLatency + * (MaxPageTableLevels + - 1), + LineTime / 4.0)); + } else { + TimeForFetchingMetaPTEImmediateFlip = 0; + } + + *DestinationLinesToRequestVMInImmediateFlip = dml_floor( + 4.0 * (TimeForFetchingMetaPTEImmediateFlip / LineTime + 0.125), + 1) / 4.0; + + if ((VirtualMemoryEnable == true || DCCEnable == true)) { + mode_lib->vba.ImmediateFlipBW = BandwidthAvailableForImmediateFlip + * ImmediateFlipBytes / TotImmediateFlipBytes; + TimeForFetchingRowInVBlankImmediateFlip = dml_max( + (MetaRowByte + PixelPTEBytesPerRow) + / mode_lib->vba.ImmediateFlipBW, + dml_max(UrgentLatency, LineTime / 4.0)); + } else { + TimeForFetchingRowInVBlankImmediateFlip = 0; + } + + *DestinationLinesToRequestRowInImmediateFlip = dml_floor( + 4.0 * (TimeForFetchingRowInVBlankImmediateFlip / LineTime + 0.125), + 1) / 4.0; + + if (VirtualMemoryEnable == true) { + *final_flip_bw = + dml_max( + PDEAndMetaPTEBytesFrame + / (*DestinationLinesToRequestVMInImmediateFlip + * LineTime), + (MetaRowByte + PixelPTEBytesPerRow) + / (TimeForFetchingRowInVBlankImmediateFlip + * LineTime)); + } else if (MetaRowByte + PixelPTEBytesPerRow > 0) { + *final_flip_bw = (MetaRowByte + PixelPTEBytesPerRow) + / (TimeForFetchingRowInVBlankImmediateFlip * LineTime); + } else { + *final_flip_bw = 0; + } + + if (VirtualMemoryEnable && !DCCEnable) + min_row_time = dpte_row_height * LineTime / VRatio; + else if (!VirtualMemoryEnable && DCCEnable) + min_row_time = meta_row_height * LineTime / VRatio; + else + min_row_time = dml_min(dpte_row_height, meta_row_height) * LineTime + / VRatio; + + if (*DestinationLinesToRequestVMInImmediateFlip >= 8 + || *DestinationLinesToRequestRowInImmediateFlip >= 16 + || TimeForFetchingMetaPTEImmediateFlip + + 2 * TimeForFetchingRowInVBlankImmediateFlip + > min_row_time) + *ImmediateFlipSupportedForPipe = false; + else + *ImmediateFlipSupportedForPipe = true; + } +} + +static void PixelClockAdjustmentForProgressiveToInterlaceUnit(struct display_mode_lib *mode_lib) +{ + unsigned int k; + + //Progressive To dml_ml->vba.Interlace Unit Effect + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.PixelClockBackEnd[k] = mode_lib->vba.PixelClock[k]; + if (mode_lib->vba.Interlace[k] == 1 + && mode_lib->vba.ProgressiveToInterlaceUnitInOPP == true) { + mode_lib->vba.PixelClock[k] = 2 * mode_lib->vba.PixelClock[k]; + } + } +} + +static unsigned int CursorBppEnumToBits(enum cursor_bpp ebpp) +{ + switch (ebpp) { + case dm_cur_2bit: + return 2; + case dm_cur_32bit: + return 32; + case dm_cur_64bit: + return 64; + default: + return 0; + } +} + +static unsigned int TruncToValidBPP( + double DecimalBPP, + bool DSCEnabled, + enum output_encoder_class Output, + enum output_format_class Format, + unsigned int DSCInputBitPerComponent) +{ + if (Output == dm_hdmi) { + if (Format == dm_420) { + if (DecimalBPP >= 18) + return 18; + else if (DecimalBPP >= 15) + return 15; + else if (DecimalBPP >= 12) + return 12; + else + return 0; + } else if (Format == dm_444) { + if (DecimalBPP >= 36) + return 36; + else if (DecimalBPP >= 30) + return 30; + else if (DecimalBPP >= 24) + return 24; + else + return 0; + } else { + if (DecimalBPP / 1.5 >= 24) + return 24; + else if (DecimalBPP / 1.5 >= 20) + return 20; + else if (DecimalBPP / 1.5 >= 16) + return 16; + else + return 0; + } + } else { + if (DSCEnabled) { + if (Format == dm_420) { + if (DecimalBPP < 6) + return 0; + else if (DecimalBPP >= 1.5 * DSCInputBitPerComponent - 1 / 16) + return 1.5 * DSCInputBitPerComponent - 1 / 16; + else + return dml_floor(16 * DecimalBPP, 1) / 16; + } else if (Format == dm_n422) { + if (DecimalBPP < 7) + return 0; + else if (DecimalBPP >= 2 * DSCInputBitPerComponent - 1 / 16) + return 2 * DSCInputBitPerComponent - 1 / 16; + else + return dml_floor(16 * DecimalBPP, 1) / 16; + } else { + if (DecimalBPP < 8) + return 0; + else if (DecimalBPP >= 3 * DSCInputBitPerComponent - 1 / 16) + return 3 * DSCInputBitPerComponent - 1 / 16; + else + return dml_floor(16 * DecimalBPP, 1) / 16; + } + } else if (Format == dm_420) { + if (DecimalBPP >= 18) + return 18; + else if (DecimalBPP >= 15) + return 15; + else if (DecimalBPP >= 12) + return 12; + else + return 0; + } else if (Format == dm_s422 || Format == dm_n422) { + if (DecimalBPP >= 24) + return 24; + else if (DecimalBPP >= 20) + return 20; + else if (DecimalBPP >= 16) + return 16; + else + return 0; + } else { + if (DecimalBPP >= 36) + return 36; + else if (DecimalBPP >= 30) + return 30; + else if (DecimalBPP >= 24) + return 24; + else + return 0; + } + } +} + +static void ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_lib) +{ + int i; + unsigned int j, k; + /*MODE SUPPORT, VOLTAGE STATE AND SOC CONFIGURATION*/ + + /*Scale Ratio, taps Support Check*/ + + mode_lib->vba.ScaleRatioAndTapsSupport = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.ScalerEnabled[k] == false + && ((mode_lib->vba.SourcePixelFormat[k] != dm_444_64 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_32 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_16 + && mode_lib->vba.SourcePixelFormat[k] != dm_mono_16 + && mode_lib->vba.SourcePixelFormat[k] != dm_mono_8) + || mode_lib->vba.HRatio[k] != 1.0 + || mode_lib->vba.htaps[k] != 1.0 + || mode_lib->vba.VRatio[k] != 1.0 + || mode_lib->vba.vtaps[k] != 1.0)) { + mode_lib->vba.ScaleRatioAndTapsSupport = false; + } else if (mode_lib->vba.vtaps[k] < 1.0 || mode_lib->vba.vtaps[k] > 8.0 + || mode_lib->vba.htaps[k] < 1.0 || mode_lib->vba.htaps[k] > 8.0 + || (mode_lib->vba.htaps[k] > 1.0 + && (mode_lib->vba.htaps[k] % 2) == 1) + || mode_lib->vba.HRatio[k] > mode_lib->vba.MaxHSCLRatio + || mode_lib->vba.VRatio[k] > mode_lib->vba.MaxVSCLRatio + || mode_lib->vba.HRatio[k] > mode_lib->vba.htaps[k] + || mode_lib->vba.VRatio[k] > mode_lib->vba.vtaps[k] + || (mode_lib->vba.SourcePixelFormat[k] != dm_444_64 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_32 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_16 + && mode_lib->vba.SourcePixelFormat[k] != dm_mono_16 + && mode_lib->vba.SourcePixelFormat[k] != dm_mono_8 + && (mode_lib->vba.HRatio[k] / 2.0 + > mode_lib->vba.HTAPsChroma[k] + || mode_lib->vba.VRatio[k] / 2.0 + > mode_lib->vba.VTAPsChroma[k]))) { + mode_lib->vba.ScaleRatioAndTapsSupport = false; + } + } + /*Source Format, Pixel Format and Scan Support Check*/ + + mode_lib->vba.SourceFormatPixelAndScanSupport = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if ((mode_lib->vba.SurfaceTiling[k] == dm_sw_linear + && mode_lib->vba.SourceScan[k] != dm_horz) + || ((mode_lib->vba.SurfaceTiling[k] == dm_sw_4kb_d + || mode_lib->vba.SurfaceTiling[k] == dm_sw_4kb_d_x + || mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_d + || mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_d_t + || mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_d_x + || mode_lib->vba.SurfaceTiling[k] == dm_sw_var_d + || mode_lib->vba.SurfaceTiling[k] == dm_sw_var_d_x) + && mode_lib->vba.SourcePixelFormat[k] != dm_444_64) + || (mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_r_x + && (mode_lib->vba.SourcePixelFormat[k] == dm_mono_8 + || mode_lib->vba.SourcePixelFormat[k] + == dm_420_8 + || mode_lib->vba.SourcePixelFormat[k] + == dm_420_10)) + || (((mode_lib->vba.SurfaceTiling[k] + == dm_sw_gfx7_2d_thin_gl + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_gfx7_2d_thin_lvp) + && !((mode_lib->vba.SourcePixelFormat[k] + == dm_444_64 + || mode_lib->vba.SourcePixelFormat[k] + == dm_444_32) + && mode_lib->vba.SourceScan[k] + == dm_horz + && mode_lib->vba.SupportGFX7CompatibleTilingIn32bppAnd64bpp + == true + && mode_lib->vba.DCCEnable[k] + == false)) + || (mode_lib->vba.DCCEnable[k] == true + && (mode_lib->vba.SurfaceTiling[k] + == dm_sw_linear + || mode_lib->vba.SourcePixelFormat[k] + == dm_420_8 + || mode_lib->vba.SourcePixelFormat[k] + == dm_420_10)))) { + mode_lib->vba.SourceFormatPixelAndScanSupport = false; + } + } + /*Bandwidth Support Check*/ + + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.SourceScan[k] == dm_horz) { + mode_lib->vba.SwathWidthYSingleDPP[k] = mode_lib->vba.ViewportWidth[k]; + } else { + mode_lib->vba.SwathWidthYSingleDPP[k] = mode_lib->vba.ViewportHeight[k]; + } + if (mode_lib->vba.SourcePixelFormat[k] == dm_444_64) { + mode_lib->vba.BytePerPixelInDETY[k] = 8.0; + mode_lib->vba.BytePerPixelInDETC[k] = 0.0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_32) { + mode_lib->vba.BytePerPixelInDETY[k] = 4.0; + mode_lib->vba.BytePerPixelInDETC[k] = 0.0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_16 + || mode_lib->vba.SourcePixelFormat[k] == dm_mono_16) { + mode_lib->vba.BytePerPixelInDETY[k] = 2.0; + mode_lib->vba.BytePerPixelInDETC[k] = 0.0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_mono_8) { + mode_lib->vba.BytePerPixelInDETY[k] = 1.0; + mode_lib->vba.BytePerPixelInDETC[k] = 0.0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_8) { + mode_lib->vba.BytePerPixelInDETY[k] = 1.0; + mode_lib->vba.BytePerPixelInDETC[k] = 2.0; + } else { + mode_lib->vba.BytePerPixelInDETY[k] = 4.0 / 3; + mode_lib->vba.BytePerPixelInDETC[k] = 8.0 / 3; + } + } + mode_lib->vba.TotalReadBandwidthConsumedGBytePerSecond = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.ReadBandwidth[k] = mode_lib->vba.SwathWidthYSingleDPP[k] + * (dml_ceil(mode_lib->vba.BytePerPixelInDETY[k], 1.0) + * mode_lib->vba.VRatio[k] + + dml_ceil(mode_lib->vba.BytePerPixelInDETC[k], 2.0) + / 2.0 * mode_lib->vba.VRatio[k] / 2) + / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + if (mode_lib->vba.DCCEnable[k] == true) { + mode_lib->vba.ReadBandwidth[k] = mode_lib->vba.ReadBandwidth[k] + * (1 + 1 / 256); + } + if (mode_lib->vba.VirtualMemoryEnable == true + && mode_lib->vba.SourceScan[k] != dm_horz + && (mode_lib->vba.SurfaceTiling[k] == dm_sw_4kb_s + || mode_lib->vba.SurfaceTiling[k] == dm_sw_4kb_s_x + || mode_lib->vba.SurfaceTiling[k] == dm_sw_4kb_d + || mode_lib->vba.SurfaceTiling[k] == dm_sw_4kb_d_x)) { + mode_lib->vba.ReadBandwidth[k] = mode_lib->vba.ReadBandwidth[k] + * (1 + 1 / 64); + } else if (mode_lib->vba.VirtualMemoryEnable == true + && mode_lib->vba.SourceScan[k] == dm_horz + && (mode_lib->vba.SourcePixelFormat[k] == dm_444_64 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_32) + && (mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_s + || mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_s_t + || mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_s_x + || mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_d + || mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_d_t + || mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_d_x + || mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_r_x)) { + mode_lib->vba.ReadBandwidth[k] = mode_lib->vba.ReadBandwidth[k] + * (1 + 1 / 256); + } else if (mode_lib->vba.VirtualMemoryEnable == true) { + mode_lib->vba.ReadBandwidth[k] = mode_lib->vba.ReadBandwidth[k] + * (1 + 1 / 512); + } + mode_lib->vba.TotalReadBandwidthConsumedGBytePerSecond = + mode_lib->vba.TotalReadBandwidthConsumedGBytePerSecond + + mode_lib->vba.ReadBandwidth[k] / 1000.0; + } + mode_lib->vba.TotalWriteBandwidthConsumedGBytePerSecond = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.WritebackEnable[k] == true + && mode_lib->vba.WritebackPixelFormat[k] == dm_444_32) { + mode_lib->vba.WriteBandwidth[k] = mode_lib->vba.WritebackDestinationWidth[k] + * mode_lib->vba.WritebackDestinationHeight[k] + / (mode_lib->vba.WritebackSourceHeight[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) * 4.0; + } else if (mode_lib->vba.WritebackEnable[k] == true + && mode_lib->vba.WritebackPixelFormat[k] == dm_420_10) { + mode_lib->vba.WriteBandwidth[k] = mode_lib->vba.WritebackDestinationWidth[k] + * mode_lib->vba.WritebackDestinationHeight[k] + / (mode_lib->vba.WritebackSourceHeight[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) * 3.0; + } else if (mode_lib->vba.WritebackEnable[k] == true) { + mode_lib->vba.WriteBandwidth[k] = mode_lib->vba.WritebackDestinationWidth[k] + * mode_lib->vba.WritebackDestinationHeight[k] + / (mode_lib->vba.WritebackSourceHeight[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) * 1.5; + } else { + mode_lib->vba.WriteBandwidth[k] = 0.0; + } + mode_lib->vba.TotalWriteBandwidthConsumedGBytePerSecond = + mode_lib->vba.TotalWriteBandwidthConsumedGBytePerSecond + + mode_lib->vba.WriteBandwidth[k] / 1000.0; + } + mode_lib->vba.TotalBandwidthConsumedGBytePerSecond = + mode_lib->vba.TotalReadBandwidthConsumedGBytePerSecond + + mode_lib->vba.TotalWriteBandwidthConsumedGBytePerSecond; + mode_lib->vba.DCCEnabledInAnyPlane = false; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.DCCEnable[k] == true) { + mode_lib->vba.DCCEnabledInAnyPlane = true; + } + } + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.FabricAndDRAMBandwidthPerState[i] = dml_min( + mode_lib->vba.DRAMSpeedPerState[i] * mode_lib->vba.NumberOfChannels + * mode_lib->vba.DRAMChannelWidth, + mode_lib->vba.FabricClockPerState[i] + * mode_lib->vba.FabricDatapathToDCNDataReturn) + / 1000; + mode_lib->vba.ReturnBWToDCNPerState = dml_min( + mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLKPerState[i], + mode_lib->vba.FabricAndDRAMBandwidthPerState[i] * 1000.0) + * mode_lib->vba.PercentOfIdealDRAMAndFabricBWReceivedAfterUrgLatency + / 100; + mode_lib->vba.ReturnBWPerState[i] = mode_lib->vba.ReturnBWToDCNPerState; + if (mode_lib->vba.DCCEnabledInAnyPlane == true + && mode_lib->vba.ReturnBWToDCNPerState + > mode_lib->vba.DCFCLKPerState[i] + * mode_lib->vba.ReturnBusWidth + / 4.0) { + mode_lib->vba.ReturnBWPerState[i] = + dml_min( + mode_lib->vba.ReturnBWPerState[i], + mode_lib->vba.ReturnBWToDCNPerState * 4.0 + * (1.0 + - mode_lib->vba.UrgentLatency + / ((mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024.0 + / (mode_lib->vba.ReturnBWToDCNPerState + - mode_lib->vba.DCFCLKPerState[i] + * mode_lib->vba.ReturnBusWidth + / 4.0) + + mode_lib->vba.UrgentLatency))); + } + mode_lib->vba.CriticalPoint = + 2.0 * mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLKPerState[i] + * mode_lib->vba.UrgentLatency + / (mode_lib->vba.ReturnBWToDCNPerState + * mode_lib->vba.UrgentLatency + + (mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024.0); + if (mode_lib->vba.DCCEnabledInAnyPlane == true && mode_lib->vba.CriticalPoint > 1.0 + && mode_lib->vba.CriticalPoint < 4.0) { + mode_lib->vba.ReturnBWPerState[i] = + dml_min( + mode_lib->vba.ReturnBWPerState[i], + dml_pow( + 4.0 + * mode_lib->vba.ReturnBWToDCNPerState + * (mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024.0 + * mode_lib->vba.ReturnBusWidth + * mode_lib->vba.DCFCLKPerState[i] + * mode_lib->vba.UrgentLatency + / (mode_lib->vba.ReturnBWToDCNPerState + * mode_lib->vba.UrgentLatency + + (mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024.0), + 2)); + } + mode_lib->vba.ReturnBWToDCNPerState = dml_min( + mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLKPerState[i], + mode_lib->vba.FabricAndDRAMBandwidthPerState[i] * 1000.0); + if (mode_lib->vba.DCCEnabledInAnyPlane == true + && mode_lib->vba.ReturnBWToDCNPerState + > mode_lib->vba.DCFCLKPerState[i] + * mode_lib->vba.ReturnBusWidth + / 4.0) { + mode_lib->vba.ReturnBWPerState[i] = + dml_min( + mode_lib->vba.ReturnBWPerState[i], + mode_lib->vba.ReturnBWToDCNPerState * 4.0 + * (1.0 + - mode_lib->vba.UrgentLatency + / ((mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024.0 + / (mode_lib->vba.ReturnBWToDCNPerState + - mode_lib->vba.DCFCLKPerState[i] + * mode_lib->vba.ReturnBusWidth + / 4.0) + + mode_lib->vba.UrgentLatency))); + } + mode_lib->vba.CriticalPoint = + 2.0 * mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLKPerState[i] + * mode_lib->vba.UrgentLatency + / (mode_lib->vba.ReturnBWToDCNPerState + * mode_lib->vba.UrgentLatency + + (mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024.0); + if (mode_lib->vba.DCCEnabledInAnyPlane == true && mode_lib->vba.CriticalPoint > 1.0 + && mode_lib->vba.CriticalPoint < 4.0) { + mode_lib->vba.ReturnBWPerState[i] = + dml_min( + mode_lib->vba.ReturnBWPerState[i], + dml_pow( + 4.0 + * mode_lib->vba.ReturnBWToDCNPerState + * (mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024.0 + * mode_lib->vba.ReturnBusWidth + * mode_lib->vba.DCFCLKPerState[i] + * mode_lib->vba.UrgentLatency + / (mode_lib->vba.ReturnBWToDCNPerState + * mode_lib->vba.UrgentLatency + + (mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024.0), + 2)); + } + } + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + if ((mode_lib->vba.TotalReadBandwidthConsumedGBytePerSecond * 1000.0 + <= mode_lib->vba.ReturnBWPerState[i]) + && (mode_lib->vba.TotalBandwidthConsumedGBytePerSecond * 1000.0 + <= mode_lib->vba.FabricAndDRAMBandwidthPerState[i] + * 1000.0 + * mode_lib->vba.PercentOfIdealDRAMAndFabricBWReceivedAfterUrgLatency + / 100.0)) { + mode_lib->vba.BandwidthSupport[i] = true; + } else { + mode_lib->vba.BandwidthSupport[i] = false; + } + } + /*Writeback Latency support check*/ + + mode_lib->vba.WritebackLatencySupport = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.WritebackEnable[k] == true) { + if (mode_lib->vba.WritebackPixelFormat[k] == dm_444_32) { + if (mode_lib->vba.WriteBandwidth[k] + > (mode_lib->vba.WritebackInterfaceLumaBufferSize + + mode_lib->vba.WritebackInterfaceChromaBufferSize) + / mode_lib->vba.WritebackLatency) { + mode_lib->vba.WritebackLatencySupport = false; + } + } else { + if (mode_lib->vba.WriteBandwidth[k] + > 1.5 + * dml_min( + mode_lib->vba.WritebackInterfaceLumaBufferSize, + 2.0 + * mode_lib->vba.WritebackInterfaceChromaBufferSize) + / mode_lib->vba.WritebackLatency) { + mode_lib->vba.WritebackLatencySupport = false; + } + } + } + } + /*Re-ordering Buffer Support Check*/ + + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.UrgentRoundTripAndOutOfOrderLatencyPerState[i] = + (mode_lib->vba.RoundTripPingLatencyCycles + 32.0) + / mode_lib->vba.DCFCLKPerState[i] + + mode_lib->vba.UrgentOutOfOrderReturnPerChannel + * mode_lib->vba.NumberOfChannels + / mode_lib->vba.ReturnBWPerState[i]; + if ((mode_lib->vba.ROBBufferSizeInKByte - mode_lib->vba.PixelChunkSizeInKByte) + * 1024.0 / mode_lib->vba.ReturnBWPerState[i] + > mode_lib->vba.UrgentRoundTripAndOutOfOrderLatencyPerState[i]) { + mode_lib->vba.ROBSupport[i] = true; + } else { + mode_lib->vba.ROBSupport[i] = false; + } + } + /*Writeback Mode Support Check*/ + + mode_lib->vba.TotalNumberOfActiveWriteback = 0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.WritebackEnable[k] == true) { + mode_lib->vba.TotalNumberOfActiveWriteback = + mode_lib->vba.TotalNumberOfActiveWriteback + 1; + } + } + mode_lib->vba.WritebackModeSupport = true; + if (mode_lib->vba.TotalNumberOfActiveWriteback > mode_lib->vba.MaxNumWriteback) { + mode_lib->vba.WritebackModeSupport = false; + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.WritebackEnable[k] == true + && mode_lib->vba.Writeback10bpc420Supported != true + && mode_lib->vba.WritebackPixelFormat[k] == dm_420_10) { + mode_lib->vba.WritebackModeSupport = false; + } + } + /*Writeback Scale Ratio and Taps Support Check*/ + + mode_lib->vba.WritebackScaleRatioAndTapsSupport = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.WritebackEnable[k] == true) { + if (mode_lib->vba.WritebackLumaAndChromaScalingSupported == false + && (mode_lib->vba.WritebackHRatio[k] != 1.0 + || mode_lib->vba.WritebackVRatio[k] != 1.0)) { + mode_lib->vba.WritebackScaleRatioAndTapsSupport = false; + } + if (mode_lib->vba.WritebackHRatio[k] > mode_lib->vba.WritebackMaxHSCLRatio + || mode_lib->vba.WritebackVRatio[k] + > mode_lib->vba.WritebackMaxVSCLRatio + || mode_lib->vba.WritebackHRatio[k] + < mode_lib->vba.WritebackMinHSCLRatio + || mode_lib->vba.WritebackVRatio[k] + < mode_lib->vba.WritebackMinVSCLRatio + || mode_lib->vba.WritebackLumaHTaps[k] + > mode_lib->vba.WritebackMaxHSCLTaps + || mode_lib->vba.WritebackLumaVTaps[k] + > mode_lib->vba.WritebackMaxVSCLTaps + || mode_lib->vba.WritebackHRatio[k] + > mode_lib->vba.WritebackLumaHTaps[k] + || mode_lib->vba.WritebackVRatio[k] + > mode_lib->vba.WritebackLumaVTaps[k] + || (mode_lib->vba.WritebackLumaHTaps[k] > 2.0 + && ((mode_lib->vba.WritebackLumaHTaps[k] % 2) + == 1)) + || (mode_lib->vba.WritebackPixelFormat[k] != dm_444_32 + && (mode_lib->vba.WritebackChromaHTaps[k] + > mode_lib->vba.WritebackMaxHSCLTaps + || mode_lib->vba.WritebackChromaVTaps[k] + > mode_lib->vba.WritebackMaxVSCLTaps + || 2.0 + * mode_lib->vba.WritebackHRatio[k] + > mode_lib->vba.WritebackChromaHTaps[k] + || 2.0 + * mode_lib->vba.WritebackVRatio[k] + > mode_lib->vba.WritebackChromaVTaps[k] + || (mode_lib->vba.WritebackChromaHTaps[k] > 2.0 + && ((mode_lib->vba.WritebackChromaHTaps[k] % 2) == 1))))) { + mode_lib->vba.WritebackScaleRatioAndTapsSupport = false; + } + if (mode_lib->vba.WritebackVRatio[k] < 1.0) { + mode_lib->vba.WritebackLumaVExtra = + dml_max(1.0 - 2.0 / dml_ceil(1.0 / mode_lib->vba.WritebackVRatio[k], 1.0), 0.0); + } else { + mode_lib->vba.WritebackLumaVExtra = -1; + } + if ((mode_lib->vba.WritebackPixelFormat[k] == dm_444_32 + && mode_lib->vba.WritebackLumaVTaps[k] + > (mode_lib->vba.WritebackLineBufferLumaBufferSize + + mode_lib->vba.WritebackLineBufferChromaBufferSize) + / 3.0 + / mode_lib->vba.WritebackDestinationWidth[k] + - mode_lib->vba.WritebackLumaVExtra) + || (mode_lib->vba.WritebackPixelFormat[k] == dm_420_8 + && mode_lib->vba.WritebackLumaVTaps[k] + > mode_lib->vba.WritebackLineBufferLumaBufferSize + / mode_lib->vba.WritebackDestinationWidth[k] + - mode_lib->vba.WritebackLumaVExtra) + || (mode_lib->vba.WritebackPixelFormat[k] == dm_420_10 + && mode_lib->vba.WritebackLumaVTaps[k] + > mode_lib->vba.WritebackLineBufferLumaBufferSize + * 8.0 / 10.0 + / mode_lib->vba.WritebackDestinationWidth[k] + - mode_lib->vba.WritebackLumaVExtra)) { + mode_lib->vba.WritebackScaleRatioAndTapsSupport = false; + } + if (2.0 * mode_lib->vba.WritebackVRatio[k] < 1) { + mode_lib->vba.WritebackChromaVExtra = 0.0; + } else { + mode_lib->vba.WritebackChromaVExtra = -1; + } + if ((mode_lib->vba.WritebackPixelFormat[k] == dm_420_8 + && mode_lib->vba.WritebackChromaVTaps[k] + > mode_lib->vba.WritebackLineBufferChromaBufferSize + / mode_lib->vba.WritebackDestinationWidth[k] + - mode_lib->vba.WritebackChromaVExtra) + || (mode_lib->vba.WritebackPixelFormat[k] == dm_420_10 + && mode_lib->vba.WritebackChromaVTaps[k] + > mode_lib->vba.WritebackLineBufferChromaBufferSize + * 8.0 / 10.0 + / mode_lib->vba.WritebackDestinationWidth[k] + - mode_lib->vba.WritebackChromaVExtra)) { + mode_lib->vba.WritebackScaleRatioAndTapsSupport = false; + } + } + } + /*Maximum DISPCLK/DPPCLK Support check*/ + + mode_lib->vba.WritebackRequiredDISPCLK = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.WritebackEnable[k] == true) { + mode_lib->vba.WritebackRequiredDISPCLK = + dml_max( + mode_lib->vba.WritebackRequiredDISPCLK, + CalculateWriteBackDISPCLK( + mode_lib->vba.WritebackPixelFormat[k], + mode_lib->vba.PixelClock[k], + mode_lib->vba.WritebackHRatio[k], + mode_lib->vba.WritebackVRatio[k], + mode_lib->vba.WritebackLumaHTaps[k], + mode_lib->vba.WritebackLumaVTaps[k], + mode_lib->vba.WritebackChromaHTaps[k], + mode_lib->vba.WritebackChromaVTaps[k], + mode_lib->vba.WritebackDestinationWidth[k], + mode_lib->vba.HTotal[k], + mode_lib->vba.WritebackChromaLineBufferWidth)); + } + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.HRatio[k] > 1.0) { + mode_lib->vba.PSCL_FACTOR[k] = dml_min( + mode_lib->vba.MaxDCHUBToPSCLThroughput, + mode_lib->vba.MaxPSCLToLBThroughput + * mode_lib->vba.HRatio[k] + / dml_ceil( + mode_lib->vba.htaps[k] + / 6.0, + 1.0)); + } else { + mode_lib->vba.PSCL_FACTOR[k] = dml_min( + mode_lib->vba.MaxDCHUBToPSCLThroughput, + mode_lib->vba.MaxPSCLToLBThroughput); + } + if (mode_lib->vba.BytePerPixelInDETC[k] == 0.0) { + mode_lib->vba.PSCL_FACTOR_CHROMA[k] = 0.0; + mode_lib->vba.MinDPPCLKUsingSingleDPP[k] = + mode_lib->vba.PixelClock[k] + * dml_max3( + mode_lib->vba.vtaps[k] / 6.0 + * dml_min( + 1.0, + mode_lib->vba.HRatio[k]), + mode_lib->vba.HRatio[k] + * mode_lib->vba.VRatio[k] + / mode_lib->vba.PSCL_FACTOR[k], + 1.0); + if ((mode_lib->vba.htaps[k] > 6.0 || mode_lib->vba.vtaps[k] > 6.0) + && mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + < 2.0 * mode_lib->vba.PixelClock[k]) { + mode_lib->vba.MinDPPCLKUsingSingleDPP[k] = 2.0 + * mode_lib->vba.PixelClock[k]; + } + } else { + if (mode_lib->vba.HRatio[k] / 2.0 > 1.0) { + mode_lib->vba.PSCL_FACTOR_CHROMA[k] = + dml_min( + mode_lib->vba.MaxDCHUBToPSCLThroughput, + mode_lib->vba.MaxPSCLToLBThroughput + * mode_lib->vba.HRatio[k] + / 2.0 + / dml_ceil( + mode_lib->vba.HTAPsChroma[k] + / 6.0, + 1.0)); + } else { + mode_lib->vba.PSCL_FACTOR_CHROMA[k] = dml_min( + mode_lib->vba.MaxDCHUBToPSCLThroughput, + mode_lib->vba.MaxPSCLToLBThroughput); + } + mode_lib->vba.MinDPPCLKUsingSingleDPP[k] = + mode_lib->vba.PixelClock[k] + * dml_max5( + mode_lib->vba.vtaps[k] / 6.0 + * dml_min( + 1.0, + mode_lib->vba.HRatio[k]), + mode_lib->vba.HRatio[k] + * mode_lib->vba.VRatio[k] + / mode_lib->vba.PSCL_FACTOR[k], + mode_lib->vba.VTAPsChroma[k] + / 6.0 + * dml_min( + 1.0, + mode_lib->vba.HRatio[k] + / 2.0), + mode_lib->vba.HRatio[k] + * mode_lib->vba.VRatio[k] + / 4.0 + / mode_lib->vba.PSCL_FACTOR_CHROMA[k], + 1.0); + if ((mode_lib->vba.htaps[k] > 6.0 || mode_lib->vba.vtaps[k] > 6.0 + || mode_lib->vba.HTAPsChroma[k] > 6.0 + || mode_lib->vba.VTAPsChroma[k] > 6.0) + && mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + < 2.0 * mode_lib->vba.PixelClock[k]) { + mode_lib->vba.MinDPPCLKUsingSingleDPP[k] = 2.0 + * mode_lib->vba.PixelClock[k]; + } + } + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + Calculate256BBlockSizes( + mode_lib->vba.SourcePixelFormat[k], + mode_lib->vba.SurfaceTiling[k], + dml_ceil(mode_lib->vba.BytePerPixelInDETY[k], 1.0), + dml_ceil(mode_lib->vba.BytePerPixelInDETC[k], 2.0), + &mode_lib->vba.Read256BlockHeightY[k], + &mode_lib->vba.Read256BlockHeightC[k], + &mode_lib->vba.Read256BlockWidthY[k], + &mode_lib->vba.Read256BlockWidthC[k]); + if (mode_lib->vba.SourceScan[k] == dm_horz) { + mode_lib->vba.MaxSwathHeightY[k] = mode_lib->vba.Read256BlockHeightY[k]; + mode_lib->vba.MaxSwathHeightC[k] = mode_lib->vba.Read256BlockHeightC[k]; + } else { + mode_lib->vba.MaxSwathHeightY[k] = mode_lib->vba.Read256BlockWidthY[k]; + mode_lib->vba.MaxSwathHeightC[k] = mode_lib->vba.Read256BlockWidthC[k]; + } + if ((mode_lib->vba.SourcePixelFormat[k] == dm_444_64 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_32 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_16 + || mode_lib->vba.SourcePixelFormat[k] == dm_mono_16 + || mode_lib->vba.SourcePixelFormat[k] == dm_mono_8)) { + if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear + || (mode_lib->vba.SourcePixelFormat[k] == dm_444_64 + && (mode_lib->vba.SurfaceTiling[k] + == dm_sw_4kb_s + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_4kb_s_x + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_64kb_s + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_64kb_s_t + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_64kb_s_x + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_var_s + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_var_s_x) + && mode_lib->vba.SourceScan[k] == dm_horz)) { + mode_lib->vba.MinSwathHeightY[k] = mode_lib->vba.MaxSwathHeightY[k]; + } else { + mode_lib->vba.MinSwathHeightY[k] = mode_lib->vba.MaxSwathHeightY[k] + / 2.0; + } + mode_lib->vba.MinSwathHeightC[k] = mode_lib->vba.MaxSwathHeightC[k]; + } else { + if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear) { + mode_lib->vba.MinSwathHeightY[k] = mode_lib->vba.MaxSwathHeightY[k]; + mode_lib->vba.MinSwathHeightC[k] = mode_lib->vba.MaxSwathHeightC[k]; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_8 + && mode_lib->vba.SourceScan[k] == dm_horz) { + mode_lib->vba.MinSwathHeightY[k] = mode_lib->vba.MaxSwathHeightY[k] + / 2.0; + mode_lib->vba.MinSwathHeightC[k] = mode_lib->vba.MaxSwathHeightC[k]; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_10 + && mode_lib->vba.SourceScan[k] == dm_horz) { + mode_lib->vba.MinSwathHeightC[k] = mode_lib->vba.MaxSwathHeightC[k] + / 2.0; + mode_lib->vba.MinSwathHeightY[k] = mode_lib->vba.MaxSwathHeightY[k]; + } else { + mode_lib->vba.MinSwathHeightY[k] = mode_lib->vba.MaxSwathHeightY[k]; + mode_lib->vba.MinSwathHeightC[k] = mode_lib->vba.MaxSwathHeightC[k]; + } + } + if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear) { + mode_lib->vba.MaximumSwathWidthSupport = 8192.0; + } else { + mode_lib->vba.MaximumSwathWidthSupport = 5120.0; + } + mode_lib->vba.MaximumSwathWidthInDETBuffer = + dml_min( + mode_lib->vba.MaximumSwathWidthSupport, + mode_lib->vba.DETBufferSizeInKByte * 1024.0 / 2.0 + / (mode_lib->vba.BytePerPixelInDETY[k] + * mode_lib->vba.MinSwathHeightY[k] + + mode_lib->vba.BytePerPixelInDETC[k] + / 2.0 + * mode_lib->vba.MinSwathHeightC[k])); + if (mode_lib->vba.BytePerPixelInDETC[k] == 0.0) { + mode_lib->vba.MaximumSwathWidthInLineBuffer = + mode_lib->vba.LineBufferSize + * dml_max(mode_lib->vba.HRatio[k], 1.0) + / mode_lib->vba.LBBitPerPixel[k] + / (mode_lib->vba.vtaps[k] + + dml_max( + dml_ceil( + mode_lib->vba.VRatio[k], + 1.0) + - 2, + 0.0)); + } else { + mode_lib->vba.MaximumSwathWidthInLineBuffer = + dml_min( + mode_lib->vba.LineBufferSize + * dml_max( + mode_lib->vba.HRatio[k], + 1.0) + / mode_lib->vba.LBBitPerPixel[k] + / (mode_lib->vba.vtaps[k] + + dml_max( + dml_ceil( + mode_lib->vba.VRatio[k], + 1.0) + - 2, + 0.0)), + 2.0 * mode_lib->vba.LineBufferSize + * dml_max( + mode_lib->vba.HRatio[k] + / 2.0, + 1.0) + / mode_lib->vba.LBBitPerPixel[k] + / (mode_lib->vba.VTAPsChroma[k] + + dml_max( + dml_ceil( + mode_lib->vba.VRatio[k] + / 2.0, + 1.0) + - 2, + 0.0))); + } + mode_lib->vba.MaximumSwathWidth[k] = dml_min( + mode_lib->vba.MaximumSwathWidthInDETBuffer, + mode_lib->vba.MaximumSwathWidthInLineBuffer); + } + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.MaxDispclkRoundedDownToDFSGranularity = RoundToDFSGranularityDown( + mode_lib->vba.MaxDispclk[i], + mode_lib->vba.DISPCLKDPPCLKVCOSpeed); + mode_lib->vba.MaxDppclkRoundedDownToDFSGranularity = RoundToDFSGranularityDown( + mode_lib->vba.MaxDppclk[i], + mode_lib->vba.DISPCLKDPPCLKVCOSpeed); + mode_lib->vba.RequiredDISPCLK[i] = 0.0; + mode_lib->vba.DISPCLK_DPPCLK_Support[i] = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine = + mode_lib->vba.PixelClock[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + * (1.0 + + mode_lib->vba.DISPCLKRampingMargin + / 100.0); + if (mode_lib->vba.ODMCapability == true + && mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine + > mode_lib->vba.MaxDispclkRoundedDownToDFSGranularity) { + mode_lib->vba.ODMCombineEnablePerState[i][k] = true; + mode_lib->vba.PlaneRequiredDISPCLK = + mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine + / 2.0; + } else { + mode_lib->vba.ODMCombineEnablePerState[i][k] = false; + mode_lib->vba.PlaneRequiredDISPCLK = + mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine; + } + if (mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + <= mode_lib->vba.MaxDppclkRoundedDownToDFSGranularity + && mode_lib->vba.SwathWidthYSingleDPP[k] + <= mode_lib->vba.MaximumSwathWidth[k] + && mode_lib->vba.ODMCombineEnablePerState[i][k] == false) { + mode_lib->vba.NoOfDPP[i][k] = 1; + mode_lib->vba.RequiredDPPCLK[i][k] = + mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0); + } else { + mode_lib->vba.NoOfDPP[i][k] = 2; + mode_lib->vba.RequiredDPPCLK[i][k] = + mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + / 2.0; + } + mode_lib->vba.RequiredDISPCLK[i] = dml_max( + mode_lib->vba.RequiredDISPCLK[i], + mode_lib->vba.PlaneRequiredDISPCLK); + if ((mode_lib->vba.MinDPPCLKUsingSingleDPP[k] / mode_lib->vba.NoOfDPP[i][k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + > mode_lib->vba.MaxDppclkRoundedDownToDFSGranularity) + || (mode_lib->vba.PlaneRequiredDISPCLK + > mode_lib->vba.MaxDispclkRoundedDownToDFSGranularity)) { + mode_lib->vba.DISPCLK_DPPCLK_Support[i] = false; + } + } + mode_lib->vba.TotalNumberOfActiveDPP[i] = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.TotalNumberOfActiveDPP[i] = + mode_lib->vba.TotalNumberOfActiveDPP[i] + + mode_lib->vba.NoOfDPP[i][k]; + } + if ((mode_lib->vba.MaxDispclk[i] == mode_lib->vba.MaxDispclk[DC__VOLTAGE_STATES] + && mode_lib->vba.MaxDppclk[i] + == mode_lib->vba.MaxDppclk[DC__VOLTAGE_STATES]) + && (mode_lib->vba.TotalNumberOfActiveDPP[i] + > mode_lib->vba.MaxNumDPP + || mode_lib->vba.DISPCLK_DPPCLK_Support[i] == false)) { + mode_lib->vba.RequiredDISPCLK[i] = 0.0; + mode_lib->vba.DISPCLK_DPPCLK_Support[i] = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine = + mode_lib->vba.PixelClock[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0); + if (mode_lib->vba.ODMCapability == true + && mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine + > mode_lib->vba.MaxDispclkRoundedDownToDFSGranularity) { + mode_lib->vba.ODMCombineEnablePerState[i][k] = true; + mode_lib->vba.PlaneRequiredDISPCLK = + mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine + / 2.0; + } else { + mode_lib->vba.ODMCombineEnablePerState[i][k] = false; + mode_lib->vba.PlaneRequiredDISPCLK = + mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine; + } + if (mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + <= mode_lib->vba.MaxDppclkRoundedDownToDFSGranularity + && mode_lib->vba.SwathWidthYSingleDPP[k] + <= mode_lib->vba.MaximumSwathWidth[k] + && mode_lib->vba.ODMCombineEnablePerState[i][k] + == false) { + mode_lib->vba.NoOfDPP[i][k] = 1; + mode_lib->vba.RequiredDPPCLK[i][k] = + mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0); + } else { + mode_lib->vba.NoOfDPP[i][k] = 2; + mode_lib->vba.RequiredDPPCLK[i][k] = + mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + / 2.0; + } + mode_lib->vba.RequiredDISPCLK[i] = dml_max( + mode_lib->vba.RequiredDISPCLK[i], + mode_lib->vba.PlaneRequiredDISPCLK); + if ((mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + / mode_lib->vba.NoOfDPP[i][k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + > mode_lib->vba.MaxDppclkRoundedDownToDFSGranularity) + || (mode_lib->vba.PlaneRequiredDISPCLK + > mode_lib->vba.MaxDispclkRoundedDownToDFSGranularity)) { + mode_lib->vba.DISPCLK_DPPCLK_Support[i] = false; + } + } + mode_lib->vba.TotalNumberOfActiveDPP[i] = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.TotalNumberOfActiveDPP[i] = + mode_lib->vba.TotalNumberOfActiveDPP[i] + + mode_lib->vba.NoOfDPP[i][k]; + } + } + if (mode_lib->vba.TotalNumberOfActiveDPP[i] > mode_lib->vba.MaxNumDPP) { + mode_lib->vba.RequiredDISPCLK[i] = 0.0; + mode_lib->vba.DISPCLK_DPPCLK_Support[i] = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.ODMCombineEnablePerState[i][k] = false; + if (mode_lib->vba.SwathWidthYSingleDPP[k] + <= mode_lib->vba.MaximumSwathWidth[k]) { + mode_lib->vba.NoOfDPP[i][k] = 1; + mode_lib->vba.RequiredDPPCLK[i][k] = + mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0); + } else { + mode_lib->vba.NoOfDPP[i][k] = 2; + mode_lib->vba.RequiredDPPCLK[i][k] = + mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + / 2.0; + } + if (!(mode_lib->vba.MaxDispclk[i] + == mode_lib->vba.MaxDispclk[DC__VOLTAGE_STATES] + && mode_lib->vba.MaxDppclk[i] + == mode_lib->vba.MaxDppclk[DC__VOLTAGE_STATES])) { + mode_lib->vba.PlaneRequiredDISPCLK = + mode_lib->vba.PixelClock[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + * (1.0 + + mode_lib->vba.DISPCLKRampingMargin + / 100.0); + } else { + mode_lib->vba.PlaneRequiredDISPCLK = + mode_lib->vba.PixelClock[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0); + } + mode_lib->vba.RequiredDISPCLK[i] = dml_max( + mode_lib->vba.RequiredDISPCLK[i], + mode_lib->vba.PlaneRequiredDISPCLK); + if ((mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + / mode_lib->vba.NoOfDPP[i][k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + > mode_lib->vba.MaxDppclkRoundedDownToDFSGranularity) + || (mode_lib->vba.PlaneRequiredDISPCLK + > mode_lib->vba.MaxDispclkRoundedDownToDFSGranularity)) { + mode_lib->vba.DISPCLK_DPPCLK_Support[i] = false; + } + } + mode_lib->vba.TotalNumberOfActiveDPP[i] = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.TotalNumberOfActiveDPP[i] = + mode_lib->vba.TotalNumberOfActiveDPP[i] + + mode_lib->vba.NoOfDPP[i][k]; + } + } + mode_lib->vba.RequiredDISPCLK[i] = dml_max( + mode_lib->vba.RequiredDISPCLK[i], + mode_lib->vba.WritebackRequiredDISPCLK); + if (mode_lib->vba.MaxDispclkRoundedDownToDFSGranularity + < mode_lib->vba.WritebackRequiredDISPCLK) { + mode_lib->vba.DISPCLK_DPPCLK_Support[i] = false; + } + } + /*Viewport Size Check*/ + + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.ViewportSizeSupport[i] = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.ODMCombineEnablePerState[i][k] == true) { + if (dml_min( + mode_lib->vba.SwathWidthYSingleDPP[k], + dml_round( + mode_lib->vba.HActive[k] / 2.0 + * mode_lib->vba.HRatio[k])) + > mode_lib->vba.MaximumSwathWidth[k]) { + mode_lib->vba.ViewportSizeSupport[i] = false; + } + } else { + if (mode_lib->vba.SwathWidthYSingleDPP[k] / 2.0 + > mode_lib->vba.MaximumSwathWidth[k]) { + mode_lib->vba.ViewportSizeSupport[i] = false; + } + } + } + } + /*Total Available Pipes Support Check*/ + + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + if (mode_lib->vba.TotalNumberOfActiveDPP[i] <= mode_lib->vba.MaxNumDPP) { + mode_lib->vba.TotalAvailablePipesSupport[i] = true; + } else { + mode_lib->vba.TotalAvailablePipesSupport[i] = false; + } + } + /*Total Available OTG Support Check*/ + + mode_lib->vba.TotalNumberOfActiveOTG = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.BlendingAndTiming[k] == k) { + mode_lib->vba.TotalNumberOfActiveOTG = mode_lib->vba.TotalNumberOfActiveOTG + + 1.0; + } + } + if (mode_lib->vba.TotalNumberOfActiveOTG <= mode_lib->vba.MaxNumOTG) { + mode_lib->vba.NumberOfOTGSupport = true; + } else { + mode_lib->vba.NumberOfOTGSupport = false; + } + /*Display IO and DSC Support Check*/ + + mode_lib->vba.NonsupportedDSCInputBPC = false; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (!(mode_lib->vba.DSCInputBitPerComponent[k] == 12.0 + || mode_lib->vba.DSCInputBitPerComponent[k] == 10.0 + || mode_lib->vba.DSCInputBitPerComponent[k] == 8.0)) { + mode_lib->vba.NonsupportedDSCInputBPC = true; + } + } + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.RequiresDSC[i][k] = 0; + mode_lib->vba.RequiresFEC[i][k] = 0; + if (mode_lib->vba.BlendingAndTiming[k] == k) { + if (mode_lib->vba.Output[k] == dm_hdmi) { + mode_lib->vba.RequiresDSC[i][k] = 0; + mode_lib->vba.RequiresFEC[i][k] = 0; + mode_lib->vba.OutputBppPerState[i][k] = + TruncToValidBPP( + dml_min( + 600.0, + mode_lib->vba.PHYCLKPerState[i]) + / mode_lib->vba.PixelClockBackEnd[k] + * 24, + false, + mode_lib->vba.Output[k], + mode_lib->vba.OutputFormat[k], + mode_lib->vba.DSCInputBitPerComponent[k]); + } else if (mode_lib->vba.Output[k] == dm_dp + || mode_lib->vba.Output[k] == dm_edp) { + if (mode_lib->vba.Output[k] == dm_edp) { + mode_lib->vba.EffectiveFECOverhead = 0.0; + } else { + mode_lib->vba.EffectiveFECOverhead = + mode_lib->vba.FECOverhead; + } + if (mode_lib->vba.PHYCLKPerState[i] >= 270.0) { + mode_lib->vba.Outbpp = + TruncToValidBPP( + (1.0 + - mode_lib->vba.Downspreading + / 100.0) + * 270.0 + * mode_lib->vba.OutputLinkDPLanes[k] + / mode_lib->vba.PixelClockBackEnd[k] + * 8.0, + false, + mode_lib->vba.Output[k], + mode_lib->vba.OutputFormat[k], + mode_lib->vba.DSCInputBitPerComponent[k]); + mode_lib->vba.OutbppDSC = + TruncToValidBPP( + (1.0 + - mode_lib->vba.Downspreading + / 100.0) + * (1.0 + - mode_lib->vba.EffectiveFECOverhead + / 100.0) + * 270.0 + * mode_lib->vba.OutputLinkDPLanes[k] + / mode_lib->vba.PixelClockBackEnd[k] + * 8.0, + true, + mode_lib->vba.Output[k], + mode_lib->vba.OutputFormat[k], + mode_lib->vba.DSCInputBitPerComponent[k]); + if (mode_lib->vba.DSCEnabled[k] == true) { + mode_lib->vba.RequiresDSC[i][k] = true; + if (mode_lib->vba.Output[k] == dm_dp) { + mode_lib->vba.RequiresFEC[i][k] = + true; + } else { + mode_lib->vba.RequiresFEC[i][k] = + false; + } + mode_lib->vba.Outbpp = + mode_lib->vba.OutbppDSC; + } else { + mode_lib->vba.RequiresDSC[i][k] = false; + mode_lib->vba.RequiresFEC[i][k] = false; + } + mode_lib->vba.OutputBppPerState[i][k] = + mode_lib->vba.Outbpp; + } + if (mode_lib->vba.Outbpp == 0) { + mode_lib->vba.Outbpp = + TruncToValidBPP( + (1.0 + - mode_lib->vba.Downspreading + / 100.0) + * 540.0 + * mode_lib->vba.OutputLinkDPLanes[k] + / mode_lib->vba.PixelClockBackEnd[k] + * 8.0, + false, + mode_lib->vba.Output[k], + mode_lib->vba.OutputFormat[k], + mode_lib->vba.DSCInputBitPerComponent[k]); + mode_lib->vba.OutbppDSC = + TruncToValidBPP( + (1.0 + - mode_lib->vba.Downspreading + / 100.0) + * (1.0 + - mode_lib->vba.EffectiveFECOverhead + / 100.0) + * 540.0 + * mode_lib->vba.OutputLinkDPLanes[k] + / mode_lib->vba.PixelClockBackEnd[k] + * 8.0, + true, + mode_lib->vba.Output[k], + mode_lib->vba.OutputFormat[k], + mode_lib->vba.DSCInputBitPerComponent[k]); + if (mode_lib->vba.DSCEnabled[k] == true) { + mode_lib->vba.RequiresDSC[i][k] = true; + if (mode_lib->vba.Output[k] == dm_dp) { + mode_lib->vba.RequiresFEC[i][k] = + true; + } else { + mode_lib->vba.RequiresFEC[i][k] = + false; + } + mode_lib->vba.Outbpp = + mode_lib->vba.OutbppDSC; + } else { + mode_lib->vba.RequiresDSC[i][k] = false; + mode_lib->vba.RequiresFEC[i][k] = false; + } + mode_lib->vba.OutputBppPerState[i][k] = + mode_lib->vba.Outbpp; + } + if (mode_lib->vba.Outbpp == 0 + && mode_lib->vba.PHYCLKPerState[i] + >= 810.0) { + mode_lib->vba.Outbpp = + TruncToValidBPP( + (1.0 + - mode_lib->vba.Downspreading + / 100.0) + * 810.0 + * mode_lib->vba.OutputLinkDPLanes[k] + / mode_lib->vba.PixelClockBackEnd[k] + * 8.0, + false, + mode_lib->vba.Output[k], + mode_lib->vba.OutputFormat[k], + mode_lib->vba.DSCInputBitPerComponent[k]); + mode_lib->vba.OutbppDSC = + TruncToValidBPP( + (1.0 + - mode_lib->vba.Downspreading + / 100.0) + * (1.0 + - mode_lib->vba.EffectiveFECOverhead + / 100.0) + * 810.0 + * mode_lib->vba.OutputLinkDPLanes[k] + / mode_lib->vba.PixelClockBackEnd[k] + * 8.0, + true, + mode_lib->vba.Output[k], + mode_lib->vba.OutputFormat[k], + mode_lib->vba.DSCInputBitPerComponent[k]); + if (mode_lib->vba.DSCEnabled[k] == true + || mode_lib->vba.Outbpp == 0) { + mode_lib->vba.RequiresDSC[i][k] = true; + if (mode_lib->vba.Output[k] == dm_dp) { + mode_lib->vba.RequiresFEC[i][k] = + true; + } else { + mode_lib->vba.RequiresFEC[i][k] = + false; + } + mode_lib->vba.Outbpp = + mode_lib->vba.OutbppDSC; + } else { + mode_lib->vba.RequiresDSC[i][k] = false; + mode_lib->vba.RequiresFEC[i][k] = false; + } + mode_lib->vba.OutputBppPerState[i][k] = + mode_lib->vba.Outbpp; + } + } + } else { + mode_lib->vba.OutputBppPerState[i][k] = 0; + } + } + } + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.DIOSupport[i] = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.OutputBppPerState[i][k] == 0 + || (mode_lib->vba.OutputFormat[k] == dm_420 + && mode_lib->vba.ProgressiveToInterlaceUnitInOPP + == true)) { + mode_lib->vba.DIOSupport[i] = false; + } + } + } + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.DSCCLKRequiredMoreThanSupported[i] = false; + if (mode_lib->vba.BlendingAndTiming[k] == k) { + if ((mode_lib->vba.Output[k] == dm_dp + || mode_lib->vba.Output[k] == dm_edp)) { + if (mode_lib->vba.OutputFormat[k] == dm_420 + || mode_lib->vba.OutputFormat[k] + == dm_n422) { + mode_lib->vba.DSCFormatFactor = 2; + } else { + mode_lib->vba.DSCFormatFactor = 1; + } + if (mode_lib->vba.RequiresDSC[i][k] == true) { + if (mode_lib->vba.ODMCombineEnablePerState[i][k] + == true) { + if (mode_lib->vba.PixelClockBackEnd[k] / 6.0 + / mode_lib->vba.DSCFormatFactor + > (1.0 + - mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + * mode_lib->vba.MaxDSCCLK[i]) { + mode_lib->vba.DSCCLKRequiredMoreThanSupported[i] = + true; + } + } else { + if (mode_lib->vba.PixelClockBackEnd[k] / 3.0 + / mode_lib->vba.DSCFormatFactor + > (1.0 + - mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + * mode_lib->vba.MaxDSCCLK[i]) { + mode_lib->vba.DSCCLKRequiredMoreThanSupported[i] = + true; + } + } + } + } + } + } + } + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.NotEnoughDSCUnits[i] = false; + mode_lib->vba.TotalDSCUnitsRequired = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.RequiresDSC[i][k] == true) { + if (mode_lib->vba.ODMCombineEnablePerState[i][k] == true) { + mode_lib->vba.TotalDSCUnitsRequired = + mode_lib->vba.TotalDSCUnitsRequired + 2.0; + } else { + mode_lib->vba.TotalDSCUnitsRequired = + mode_lib->vba.TotalDSCUnitsRequired + 1.0; + } + } + } + if (mode_lib->vba.TotalDSCUnitsRequired > mode_lib->vba.NumberOfDSC) { + mode_lib->vba.NotEnoughDSCUnits[i] = true; + } + } + /*DSC Delay per state*/ + + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.BlendingAndTiming[k] != k) { + mode_lib->vba.slices = 0; + } else if (mode_lib->vba.RequiresDSC[i][k] == 0 + || mode_lib->vba.RequiresDSC[i][k] == false) { + mode_lib->vba.slices = 0; + } else if (mode_lib->vba.PixelClockBackEnd[k] > 3200.0) { + mode_lib->vba.slices = dml_ceil( + mode_lib->vba.PixelClockBackEnd[k] / 400.0, + 4.0); + } else if (mode_lib->vba.PixelClockBackEnd[k] > 1360.0) { + mode_lib->vba.slices = 8.0; + } else if (mode_lib->vba.PixelClockBackEnd[k] > 680.0) { + mode_lib->vba.slices = 4.0; + } else if (mode_lib->vba.PixelClockBackEnd[k] > 340.0) { + mode_lib->vba.slices = 2.0; + } else { + mode_lib->vba.slices = 1.0; + } + if (mode_lib->vba.OutputBppPerState[i][k] == 0 + || mode_lib->vba.OutputBppPerState[i][k] == 0) { + mode_lib->vba.bpp = 0.0; + } else { + mode_lib->vba.bpp = mode_lib->vba.OutputBppPerState[i][k]; + } + if (mode_lib->vba.RequiresDSC[i][k] == true && mode_lib->vba.bpp != 0.0) { + if (mode_lib->vba.ODMCombineEnablePerState[i][k] == false) { + mode_lib->vba.DSCDelayPerState[i][k] = + dscceComputeDelay( + mode_lib->vba.DSCInputBitPerComponent[k], + mode_lib->vba.bpp, + dml_ceil( + mode_lib->vba.HActive[k] + / mode_lib->vba.slices, + 1.0), + mode_lib->vba.slices, + mode_lib->vba.OutputFormat[k]) + + dscComputeDelay( + mode_lib->vba.OutputFormat[k]); + } else { + mode_lib->vba.DSCDelayPerState[i][k] = + 2.0 + * (dscceComputeDelay( + mode_lib->vba.DSCInputBitPerComponent[k], + mode_lib->vba.bpp, + dml_ceil( + mode_lib->vba.HActive[k] + / mode_lib->vba.slices, + 1.0), + mode_lib->vba.slices + / 2, + mode_lib->vba.OutputFormat[k]) + + dscComputeDelay( + mode_lib->vba.OutputFormat[k])); + } + mode_lib->vba.DSCDelayPerState[i][k] = + mode_lib->vba.DSCDelayPerState[i][k] + * mode_lib->vba.PixelClock[k] + / mode_lib->vba.PixelClockBackEnd[k]; + } else { + mode_lib->vba.DSCDelayPerState[i][k] = 0.0; + } + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + for (j = 0; j <= mode_lib->vba.NumberOfActivePlanes - 1; j++) { + if (mode_lib->vba.BlendingAndTiming[k] == j + && mode_lib->vba.RequiresDSC[i][j] == true) { + mode_lib->vba.DSCDelayPerState[i][k] = + mode_lib->vba.DSCDelayPerState[i][j]; + } + } + } + } + /*Urgent Latency Support Check*/ + + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + if (mode_lib->vba.ODMCombineEnablePerState[i][k] == true) { + mode_lib->vba.SwathWidthYPerState[i][k] = + dml_min( + mode_lib->vba.SwathWidthYSingleDPP[k], + dml_round( + mode_lib->vba.HActive[k] + / 2.0 + * mode_lib->vba.HRatio[k])); + } else { + mode_lib->vba.SwathWidthYPerState[i][k] = + mode_lib->vba.SwathWidthYSingleDPP[k] + / mode_lib->vba.NoOfDPP[i][k]; + } + mode_lib->vba.SwathWidthGranularityY = 256.0 + / dml_ceil(mode_lib->vba.BytePerPixelInDETY[k], 1.0) + / mode_lib->vba.MaxSwathHeightY[k]; + mode_lib->vba.RoundedUpMaxSwathSizeBytesY = (dml_ceil( + mode_lib->vba.SwathWidthYPerState[i][k] - 1.0, + mode_lib->vba.SwathWidthGranularityY) + + mode_lib->vba.SwathWidthGranularityY) + * mode_lib->vba.BytePerPixelInDETY[k] + * mode_lib->vba.MaxSwathHeightY[k]; + if (mode_lib->vba.SourcePixelFormat[k] == dm_420_10) { + mode_lib->vba.RoundedUpMaxSwathSizeBytesY = dml_ceil( + mode_lib->vba.RoundedUpMaxSwathSizeBytesY, + 256.0) + 256; + } + if (mode_lib->vba.MaxSwathHeightC[k] > 0.0) { + mode_lib->vba.SwathWidthGranularityC = 256.0 + / dml_ceil(mode_lib->vba.BytePerPixelInDETC[k], 2.0) + / mode_lib->vba.MaxSwathHeightC[k]; + mode_lib->vba.RoundedUpMaxSwathSizeBytesC = (dml_ceil( + mode_lib->vba.SwathWidthYPerState[i][k] / 2.0 - 1.0, + mode_lib->vba.SwathWidthGranularityC) + + mode_lib->vba.SwathWidthGranularityC) + * mode_lib->vba.BytePerPixelInDETC[k] + * mode_lib->vba.MaxSwathHeightC[k]; + if (mode_lib->vba.SourcePixelFormat[k] == dm_420_10) { + mode_lib->vba.RoundedUpMaxSwathSizeBytesC = dml_ceil( + mode_lib->vba.RoundedUpMaxSwathSizeBytesC, + 256.0) + 256; + } + } else { + mode_lib->vba.RoundedUpMaxSwathSizeBytesC = 0.0; + } + if (mode_lib->vba.RoundedUpMaxSwathSizeBytesY + + mode_lib->vba.RoundedUpMaxSwathSizeBytesC + <= mode_lib->vba.DETBufferSizeInKByte * 1024.0 / 2.0) { + mode_lib->vba.SwathHeightYPerState[i][k] = + mode_lib->vba.MaxSwathHeightY[k]; + mode_lib->vba.SwathHeightCPerState[i][k] = + mode_lib->vba.MaxSwathHeightC[k]; + } else { + mode_lib->vba.SwathHeightYPerState[i][k] = + mode_lib->vba.MinSwathHeightY[k]; + mode_lib->vba.SwathHeightCPerState[i][k] = + mode_lib->vba.MinSwathHeightC[k]; + } + if (mode_lib->vba.BytePerPixelInDETC[k] == 0.0) { + mode_lib->vba.LinesInDETLuma = mode_lib->vba.DETBufferSizeInKByte + * 1024.0 / mode_lib->vba.BytePerPixelInDETY[k] + / mode_lib->vba.SwathWidthYPerState[i][k]; + mode_lib->vba.LinesInDETChroma = 0.0; + } else if (mode_lib->vba.SwathHeightYPerState[i][k] + <= mode_lib->vba.SwathHeightCPerState[i][k]) { + mode_lib->vba.LinesInDETLuma = mode_lib->vba.DETBufferSizeInKByte + * 1024.0 / 2.0 / mode_lib->vba.BytePerPixelInDETY[k] + / mode_lib->vba.SwathWidthYPerState[i][k]; + mode_lib->vba.LinesInDETChroma = mode_lib->vba.DETBufferSizeInKByte + * 1024.0 / 2.0 / mode_lib->vba.BytePerPixelInDETC[k] + / (mode_lib->vba.SwathWidthYPerState[i][k] / 2.0); + } else { + mode_lib->vba.LinesInDETLuma = mode_lib->vba.DETBufferSizeInKByte + * 1024.0 * 2.0 / 3.0 + / mode_lib->vba.BytePerPixelInDETY[k] + / mode_lib->vba.SwathWidthYPerState[i][k]; + mode_lib->vba.LinesInDETChroma = mode_lib->vba.DETBufferSizeInKByte + * 1024.0 / 3.0 / mode_lib->vba.BytePerPixelInDETY[k] + / (mode_lib->vba.SwathWidthYPerState[i][k] / 2.0); + } + mode_lib->vba.EffectiveLBLatencyHidingSourceLinesLuma = + dml_min( + mode_lib->vba.MaxLineBufferLines, + dml_floor( + mode_lib->vba.LineBufferSize + / mode_lib->vba.LBBitPerPixel[k] + / (mode_lib->vba.SwathWidthYPerState[i][k] + / dml_max( + mode_lib->vba.HRatio[k], + 1.0)), + 1.0)) + - (mode_lib->vba.vtaps[k] - 1.0); + mode_lib->vba.EffectiveLBLatencyHidingSourceLinesChroma = + dml_min( + mode_lib->vba.MaxLineBufferLines, + dml_floor( + mode_lib->vba.LineBufferSize + / mode_lib->vba.LBBitPerPixel[k] + / (mode_lib->vba.SwathWidthYPerState[i][k] + / 2.0 + / dml_max( + mode_lib->vba.HRatio[k] + / 2.0, + 1.0)), + 1.0)) + - (mode_lib->vba.VTAPsChroma[k] - 1.0); + mode_lib->vba.EffectiveDETLBLinesLuma = + dml_floor( + mode_lib->vba.LinesInDETLuma + + dml_min( + mode_lib->vba.LinesInDETLuma + * mode_lib->vba.RequiredDISPCLK[i] + * mode_lib->vba.BytePerPixelInDETY[k] + * mode_lib->vba.PSCL_FACTOR[k] + / mode_lib->vba.ReturnBWPerState[i], + mode_lib->vba.EffectiveLBLatencyHidingSourceLinesLuma), + mode_lib->vba.SwathHeightYPerState[i][k]); + mode_lib->vba.EffectiveDETLBLinesChroma = + dml_floor( + mode_lib->vba.LinesInDETChroma + + dml_min( + mode_lib->vba.LinesInDETChroma + * mode_lib->vba.RequiredDISPCLK[i] + * mode_lib->vba.BytePerPixelInDETC[k] + * mode_lib->vba.PSCL_FACTOR_CHROMA[k] + / mode_lib->vba.ReturnBWPerState[i], + mode_lib->vba.EffectiveLBLatencyHidingSourceLinesChroma), + mode_lib->vba.SwathHeightCPerState[i][k]); + if (mode_lib->vba.BytePerPixelInDETC[k] == 0.0) { + mode_lib->vba.UrgentLatencySupportUsPerState[i][k] = + mode_lib->vba.EffectiveDETLBLinesLuma + * (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) + / mode_lib->vba.VRatio[k] + - mode_lib->vba.EffectiveDETLBLinesLuma + * mode_lib->vba.SwathWidthYPerState[i][k] + * dml_ceil( + mode_lib->vba.BytePerPixelInDETY[k], + 1.0) + / (mode_lib->vba.ReturnBWPerState[i] + / mode_lib->vba.NoOfDPP[i][k]); + } else { + mode_lib->vba.UrgentLatencySupportUsPerState[i][k] = + dml_min( + mode_lib->vba.EffectiveDETLBLinesLuma + * (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) + / mode_lib->vba.VRatio[k] + - mode_lib->vba.EffectiveDETLBLinesLuma + * mode_lib->vba.SwathWidthYPerState[i][k] + * dml_ceil( + mode_lib->vba.BytePerPixelInDETY[k], + 1.0) + / (mode_lib->vba.ReturnBWPerState[i] + / mode_lib->vba.NoOfDPP[i][k]), + mode_lib->vba.EffectiveDETLBLinesChroma + * (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) + / (mode_lib->vba.VRatio[k] + / 2.0) + - mode_lib->vba.EffectiveDETLBLinesChroma + * mode_lib->vba.SwathWidthYPerState[i][k] + / 2.0 + * dml_ceil( + mode_lib->vba.BytePerPixelInDETC[k], + 2.0) + / (mode_lib->vba.ReturnBWPerState[i] + / mode_lib->vba.NoOfDPP[i][k])); + } + } + } + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.UrgentLatencySupport[i] = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.UrgentLatencySupportUsPerState[i][k] + < mode_lib->vba.UrgentLatency / 1.0) { + mode_lib->vba.UrgentLatencySupport[i] = false; + } + } + } + /*Prefetch Check*/ + + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.TotalNumberOfDCCActiveDPP[i] = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.DCCEnable[k] == true) { + mode_lib->vba.TotalNumberOfDCCActiveDPP[i] = + mode_lib->vba.TotalNumberOfDCCActiveDPP[i] + + mode_lib->vba.NoOfDPP[i][k]; + } + } + } + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.ProjectedDCFCLKDeepSleep = 8.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.ProjectedDCFCLKDeepSleep = dml_max( + mode_lib->vba.ProjectedDCFCLKDeepSleep, + mode_lib->vba.PixelClock[k] / 16.0); + if (mode_lib->vba.BytePerPixelInDETC[k] == 0.0) { + if (mode_lib->vba.VRatio[k] <= 1.0) { + mode_lib->vba.ProjectedDCFCLKDeepSleep = + dml_max( + mode_lib->vba.ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil( + mode_lib->vba.BytePerPixelInDETY[k], + 1.0) + / 64.0 + * mode_lib->vba.HRatio[k] + * mode_lib->vba.PixelClock[k] + / mode_lib->vba.NoOfDPP[i][k]); + } else { + mode_lib->vba.ProjectedDCFCLKDeepSleep = + dml_max( + mode_lib->vba.ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil( + mode_lib->vba.BytePerPixelInDETY[k], + 1.0) + / 64.0 + * mode_lib->vba.PSCL_FACTOR[k] + * mode_lib->vba.RequiredDPPCLK[i][k]); + } + } else { + if (mode_lib->vba.VRatio[k] <= 1.0) { + mode_lib->vba.ProjectedDCFCLKDeepSleep = + dml_max( + mode_lib->vba.ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil( + mode_lib->vba.BytePerPixelInDETY[k], + 1.0) + / 32.0 + * mode_lib->vba.HRatio[k] + * mode_lib->vba.PixelClock[k] + / mode_lib->vba.NoOfDPP[i][k]); + } else { + mode_lib->vba.ProjectedDCFCLKDeepSleep = + dml_max( + mode_lib->vba.ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil( + mode_lib->vba.BytePerPixelInDETY[k], + 1.0) + / 32.0 + * mode_lib->vba.PSCL_FACTOR[k] + * mode_lib->vba.RequiredDPPCLK[i][k]); + } + if (mode_lib->vba.VRatio[k] / 2.0 <= 1.0) { + mode_lib->vba.ProjectedDCFCLKDeepSleep = + dml_max( + mode_lib->vba.ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil( + mode_lib->vba.BytePerPixelInDETC[k], + 2.0) + / 32.0 + * mode_lib->vba.HRatio[k] + / 2.0 + * mode_lib->vba.PixelClock[k] + / mode_lib->vba.NoOfDPP[i][k]); + } else { + mode_lib->vba.ProjectedDCFCLKDeepSleep = + dml_max( + mode_lib->vba.ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil( + mode_lib->vba.BytePerPixelInDETC[k], + 2.0) + / 32.0 + * mode_lib->vba.PSCL_FACTOR_CHROMA[k] + * mode_lib->vba.RequiredDPPCLK[i][k]); + } + } + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.PDEAndMetaPTEBytesPerFrameY = CalculateVMAndRowBytes( + mode_lib, + mode_lib->vba.DCCEnable[k], + mode_lib->vba.Read256BlockHeightY[k], + mode_lib->vba.Read256BlockWidthY[k], + mode_lib->vba.SourcePixelFormat[k], + mode_lib->vba.SurfaceTiling[k], + dml_ceil(mode_lib->vba.BytePerPixelInDETY[k], 1.0), + mode_lib->vba.SourceScan[k], + mode_lib->vba.ViewportWidth[k], + mode_lib->vba.ViewportHeight[k], + mode_lib->vba.SwathWidthYPerState[i][k], + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.VMMPageSize, + mode_lib->vba.PTEBufferSizeInRequests, + mode_lib->vba.PDEProcessingBufIn64KBReqs, + mode_lib->vba.PitchY[k], + mode_lib->vba.DCCMetaPitchY[k], + &mode_lib->vba.MacroTileWidthY[k], + &mode_lib->vba.MetaRowBytesY, + &mode_lib->vba.DPTEBytesPerRowY, + &mode_lib->vba.PTEBufferSizeNotExceededY[i][k], + &mode_lib->vba.dpte_row_height[k], + &mode_lib->vba.meta_row_height[k]); + mode_lib->vba.PrefetchLinesY[k] = CalculatePrefetchSourceLines( + mode_lib, + mode_lib->vba.VRatio[k], + mode_lib->vba.vtaps[k], + mode_lib->vba.Interlace[k], + mode_lib->vba.ProgressiveToInterlaceUnitInOPP, + mode_lib->vba.SwathHeightYPerState[i][k], + mode_lib->vba.ViewportYStartY[k], + &mode_lib->vba.PrefillY[k], + &mode_lib->vba.MaxNumSwY[k]); + if ((mode_lib->vba.SourcePixelFormat[k] != dm_444_64 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_32 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_16 + && mode_lib->vba.SourcePixelFormat[k] != dm_mono_16 + && mode_lib->vba.SourcePixelFormat[k] != dm_mono_8)) { + mode_lib->vba.PDEAndMetaPTEBytesPerFrameC = CalculateVMAndRowBytes( + mode_lib, + mode_lib->vba.DCCEnable[k], + mode_lib->vba.Read256BlockHeightY[k], + mode_lib->vba.Read256BlockWidthY[k], + mode_lib->vba.SourcePixelFormat[k], + mode_lib->vba.SurfaceTiling[k], + dml_ceil(mode_lib->vba.BytePerPixelInDETC[k], 2.0), + mode_lib->vba.SourceScan[k], + mode_lib->vba.ViewportWidth[k] / 2.0, + mode_lib->vba.ViewportHeight[k] / 2.0, + mode_lib->vba.SwathWidthYPerState[i][k] / 2.0, + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.VMMPageSize, + mode_lib->vba.PTEBufferSizeInRequests, + mode_lib->vba.PDEProcessingBufIn64KBReqs, + mode_lib->vba.PitchC[k], + 0.0, + &mode_lib->vba.MacroTileWidthC[k], + &mode_lib->vba.MetaRowBytesC, + &mode_lib->vba.DPTEBytesPerRowC, + &mode_lib->vba.PTEBufferSizeNotExceededC[i][k], + &mode_lib->vba.dpte_row_height_chroma[k], + &mode_lib->vba.meta_row_height_chroma[k]); + mode_lib->vba.PrefetchLinesC[k] = CalculatePrefetchSourceLines( + mode_lib, + mode_lib->vba.VRatio[k] / 2.0, + mode_lib->vba.VTAPsChroma[k], + mode_lib->vba.Interlace[k], + mode_lib->vba.ProgressiveToInterlaceUnitInOPP, + mode_lib->vba.SwathHeightCPerState[i][k], + mode_lib->vba.ViewportYStartC[k], + &mode_lib->vba.PrefillC[k], + &mode_lib->vba.MaxNumSwC[k]); + } else { + mode_lib->vba.PDEAndMetaPTEBytesPerFrameC = 0.0; + mode_lib->vba.MetaRowBytesC = 0.0; + mode_lib->vba.DPTEBytesPerRowC = 0.0; + mode_lib->vba.PrefetchLinesC[k] = 0.0; + mode_lib->vba.PTEBufferSizeNotExceededC[i][k] = true; + } + mode_lib->vba.PDEAndMetaPTEBytesPerFrame[k] = + mode_lib->vba.PDEAndMetaPTEBytesPerFrameY + + mode_lib->vba.PDEAndMetaPTEBytesPerFrameC; + mode_lib->vba.MetaRowBytes[k] = mode_lib->vba.MetaRowBytesY + + mode_lib->vba.MetaRowBytesC; + mode_lib->vba.DPTEBytesPerRow[k] = mode_lib->vba.DPTEBytesPerRowY + + mode_lib->vba.DPTEBytesPerRowC; + } + mode_lib->vba.ExtraLatency = + mode_lib->vba.UrgentRoundTripAndOutOfOrderLatencyPerState[i] + + (mode_lib->vba.TotalNumberOfActiveDPP[i] + * mode_lib->vba.PixelChunkSizeInKByte + + mode_lib->vba.TotalNumberOfDCCActiveDPP[i] + * mode_lib->vba.MetaChunkSize) + * 1024.0 + / mode_lib->vba.ReturnBWPerState[i]; + if (mode_lib->vba.VirtualMemoryEnable == true) { + mode_lib->vba.ExtraLatency = mode_lib->vba.ExtraLatency + + mode_lib->vba.TotalNumberOfActiveDPP[i] + * mode_lib->vba.PTEChunkSize * 1024.0 + / mode_lib->vba.ReturnBWPerState[i]; + } + mode_lib->vba.TimeCalc = 24.0 / mode_lib->vba.ProjectedDCFCLKDeepSleep; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.BlendingAndTiming[k] == k) { + if (mode_lib->vba.WritebackEnable[k] == true) { + mode_lib->vba.WritebackDelay[i][k] = + mode_lib->vba.WritebackLatency + + CalculateWriteBackDelay( + mode_lib->vba.WritebackPixelFormat[k], + mode_lib->vba.WritebackHRatio[k], + mode_lib->vba.WritebackVRatio[k], + mode_lib->vba.WritebackLumaHTaps[k], + mode_lib->vba.WritebackLumaVTaps[k], + mode_lib->vba.WritebackChromaHTaps[k], + mode_lib->vba.WritebackChromaVTaps[k], + mode_lib->vba.WritebackDestinationWidth[k]) + / mode_lib->vba.RequiredDISPCLK[i]; + } else { + mode_lib->vba.WritebackDelay[i][k] = 0.0; + } + for (j = 0; j <= mode_lib->vba.NumberOfActivePlanes - 1; j++) { + if (mode_lib->vba.BlendingAndTiming[j] == k + && mode_lib->vba.WritebackEnable[j] + == true) { + mode_lib->vba.WritebackDelay[i][k] = + dml_max( + mode_lib->vba.WritebackDelay[i][k], + mode_lib->vba.WritebackLatency + + CalculateWriteBackDelay( + mode_lib->vba.WritebackPixelFormat[j], + mode_lib->vba.WritebackHRatio[j], + mode_lib->vba.WritebackVRatio[j], + mode_lib->vba.WritebackLumaHTaps[j], + mode_lib->vba.WritebackLumaVTaps[j], + mode_lib->vba.WritebackChromaHTaps[j], + mode_lib->vba.WritebackChromaVTaps[j], + mode_lib->vba.WritebackDestinationWidth[j]) + / mode_lib->vba.RequiredDISPCLK[i]); + } + } + } + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + for (j = 0; j <= mode_lib->vba.NumberOfActivePlanes - 1; j++) { + if (mode_lib->vba.BlendingAndTiming[k] == j) { + mode_lib->vba.WritebackDelay[i][k] = + mode_lib->vba.WritebackDelay[i][j]; + } + } + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.MaximumVStartup[k] = + mode_lib->vba.VTotal[k] - mode_lib->vba.VActive[k] + - dml_max( + 1.0, + dml_ceil( + mode_lib->vba.WritebackDelay[i][k] + / (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]), + 1.0)); + } + mode_lib->vba.TWait = CalculateTWait( + mode_lib->vba.PrefetchMode, + mode_lib->vba.DRAMClockChangeLatency, + mode_lib->vba.UrgentLatency, + mode_lib->vba.SREnterPlusExitTime); + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.XFCEnabled[k] == true) { + mode_lib->vba.XFCRemoteSurfaceFlipDelay = + CalculateRemoteSurfaceFlipDelay( + mode_lib, + mode_lib->vba.VRatio[k], + mode_lib->vba.SwathWidthYPerState[i][k], + dml_ceil( + mode_lib->vba.BytePerPixelInDETY[k], + 1.0), + mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k], + mode_lib->vba.XFCTSlvVupdateOffset, + mode_lib->vba.XFCTSlvVupdateWidth, + mode_lib->vba.XFCTSlvVreadyOffset, + mode_lib->vba.XFCXBUFLatencyTolerance, + mode_lib->vba.XFCFillBWOverhead, + mode_lib->vba.XFCSlvChunkSize, + mode_lib->vba.XFCBusTransportTime, + mode_lib->vba.TimeCalc, + mode_lib->vba.TWait, + &mode_lib->vba.SrcActiveDrainRate, + &mode_lib->vba.TInitXFill, + &mode_lib->vba.TslvChk); + } else { + mode_lib->vba.XFCRemoteSurfaceFlipDelay = 0.0; + } + mode_lib->vba.IsErrorResult[i][k] = + CalculatePrefetchSchedule( + mode_lib, + mode_lib->vba.RequiredDPPCLK[i][k], + mode_lib->vba.RequiredDISPCLK[i], + mode_lib->vba.PixelClock[k], + mode_lib->vba.ProjectedDCFCLKDeepSleep, + mode_lib->vba.DSCDelayPerState[i][k], + mode_lib->vba.NoOfDPP[i][k], + mode_lib->vba.ScalerEnabled[k], + mode_lib->vba.NumberOfCursors[k], + mode_lib->vba.DPPCLKDelaySubtotal, + mode_lib->vba.DPPCLKDelaySCL, + mode_lib->vba.DPPCLKDelaySCLLBOnly, + mode_lib->vba.DPPCLKDelayCNVCFormater, + mode_lib->vba.DPPCLKDelayCNVCCursor, + mode_lib->vba.DISPCLKDelaySubtotal, + mode_lib->vba.SwathWidthYPerState[i][k] + / mode_lib->vba.HRatio[k], + mode_lib->vba.OutputFormat[k], + mode_lib->vba.VTotal[k] + - mode_lib->vba.VActive[k], + mode_lib->vba.HTotal[k], + mode_lib->vba.MaxInterDCNTileRepeaters, + mode_lib->vba.MaximumVStartup[k], + mode_lib->vba.MaxPageTableLevels, + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.DynamicMetadataEnable[k], + mode_lib->vba.DynamicMetadataLinesBeforeActiveRequired[k], + mode_lib->vba.DynamicMetadataTransmittedBytes[k], + mode_lib->vba.DCCEnable[k], + mode_lib->vba.UrgentLatency, + mode_lib->vba.ExtraLatency, + mode_lib->vba.TimeCalc, + mode_lib->vba.PDEAndMetaPTEBytesPerFrame[k], + mode_lib->vba.MetaRowBytes[k], + mode_lib->vba.DPTEBytesPerRow[k], + mode_lib->vba.PrefetchLinesY[k], + mode_lib->vba.SwathWidthYPerState[i][k], + mode_lib->vba.BytePerPixelInDETY[k], + mode_lib->vba.PrefillY[k], + mode_lib->vba.MaxNumSwY[k], + mode_lib->vba.PrefetchLinesC[k], + mode_lib->vba.BytePerPixelInDETC[k], + mode_lib->vba.PrefillC[k], + mode_lib->vba.MaxNumSwC[k], + mode_lib->vba.SwathHeightYPerState[i][k], + mode_lib->vba.SwathHeightCPerState[i][k], + mode_lib->vba.TWait, + mode_lib->vba.XFCEnabled[k], + mode_lib->vba.XFCRemoteSurfaceFlipDelay, + mode_lib->vba.Interlace[k], + mode_lib->vba.ProgressiveToInterlaceUnitInOPP, + mode_lib->vba.DSTXAfterScaler, + mode_lib->vba.DSTYAfterScaler, + &mode_lib->vba.LineTimesForPrefetch[k], + &mode_lib->vba.PrefetchBW[k], + &mode_lib->vba.LinesForMetaPTE[k], + &mode_lib->vba.LinesForMetaAndDPTERow[k], + &mode_lib->vba.VRatioPreY[i][k], + &mode_lib->vba.VRatioPreC[i][k], + &mode_lib->vba.RequiredPrefetchPixelDataBW[i][k], + &mode_lib->vba.VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, + &mode_lib->vba.Tno_bw[k], + &mode_lib->vba.VUpdateOffsetPix[k], + &mode_lib->vba.VUpdateWidthPix[k], + &mode_lib->vba.VReadyOffsetPix[k]); + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.cursor_bw[k] = mode_lib->vba.NumberOfCursors[k] + * mode_lib->vba.CursorWidth[k][0] + * mode_lib->vba.CursorBPP[k][0] / 8.0 + / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) + * mode_lib->vba.VRatio[k]; + } + mode_lib->vba.MaximumReadBandwidthWithPrefetch = 0.0; + mode_lib->vba.prefetch_vm_bw_valid = true; + mode_lib->vba.prefetch_row_bw_valid = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.PDEAndMetaPTEBytesPerFrame[k] == 0.0) { + mode_lib->vba.prefetch_vm_bw[k] = 0.0; + } else if (mode_lib->vba.LinesForMetaPTE[k] > 0.0) { + mode_lib->vba.prefetch_vm_bw[k] = + mode_lib->vba.PDEAndMetaPTEBytesPerFrame[k] + / (mode_lib->vba.LinesForMetaPTE[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]); + } else { + mode_lib->vba.prefetch_vm_bw[k] = 0.0; + mode_lib->vba.prefetch_vm_bw_valid = false; + } + if (mode_lib->vba.MetaRowBytes[k] + mode_lib->vba.DPTEBytesPerRow[k] + == 0.0) { + mode_lib->vba.prefetch_row_bw[k] = 0.0; + } else if (mode_lib->vba.LinesForMetaAndDPTERow[k] > 0.0) { + mode_lib->vba.prefetch_row_bw[k] = (mode_lib->vba.MetaRowBytes[k] + + mode_lib->vba.DPTEBytesPerRow[k]) + / (mode_lib->vba.LinesForMetaAndDPTERow[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]); + } else { + mode_lib->vba.prefetch_row_bw[k] = 0.0; + mode_lib->vba.prefetch_row_bw_valid = false; + } + mode_lib->vba.MaximumReadBandwidthWithPrefetch = + mode_lib->vba.MaximumReadBandwidthWithPrefetch + + mode_lib->vba.cursor_bw[k] + + dml_max4( + mode_lib->vba.prefetch_vm_bw[k], + mode_lib->vba.prefetch_row_bw[k], + mode_lib->vba.ReadBandwidth[k], + mode_lib->vba.RequiredPrefetchPixelDataBW[i][k]); + } + mode_lib->vba.PrefetchSupported[i] = true; + if (mode_lib->vba.MaximumReadBandwidthWithPrefetch + > mode_lib->vba.ReturnBWPerState[i] + || mode_lib->vba.prefetch_vm_bw_valid == false + || mode_lib->vba.prefetch_row_bw_valid == false) { + mode_lib->vba.PrefetchSupported[i] = false; + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.LineTimesForPrefetch[k] < 2.0 + || mode_lib->vba.LinesForMetaPTE[k] >= 8.0 + || mode_lib->vba.LinesForMetaAndDPTERow[k] >= 16.0 + || mode_lib->vba.IsErrorResult[i][k] == true) { + mode_lib->vba.PrefetchSupported[i] = false; + } + } + mode_lib->vba.VRatioInPrefetchSupported[i] = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.VRatioPreY[i][k] > 4.0 + || mode_lib->vba.VRatioPreC[i][k] > 4.0 + || mode_lib->vba.IsErrorResult[i][k] == true) { + mode_lib->vba.VRatioInPrefetchSupported[i] = false; + } + } + if (mode_lib->vba.PrefetchSupported[i] == true + && mode_lib->vba.VRatioInPrefetchSupported[i] == true) { + mode_lib->vba.BandwidthAvailableForImmediateFlip = + mode_lib->vba.ReturnBWPerState[i]; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.BandwidthAvailableForImmediateFlip = + mode_lib->vba.BandwidthAvailableForImmediateFlip + - mode_lib->vba.cursor_bw[k] + - dml_max( + mode_lib->vba.ReadBandwidth[k], + mode_lib->vba.PrefetchBW[k]); + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.ImmediateFlipBytes[k] = 0.0; + if ((mode_lib->vba.SourcePixelFormat[k] != dm_420_8 + && mode_lib->vba.SourcePixelFormat[k] != dm_420_10)) { + mode_lib->vba.ImmediateFlipBytes[k] = + mode_lib->vba.PDEAndMetaPTEBytesPerFrame[k] + + mode_lib->vba.MetaRowBytes[k] + + mode_lib->vba.DPTEBytesPerRow[k]; + } + } + mode_lib->vba.TotImmediateFlipBytes = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if ((mode_lib->vba.SourcePixelFormat[k] != dm_420_8 + && mode_lib->vba.SourcePixelFormat[k] != dm_420_10)) { + mode_lib->vba.TotImmediateFlipBytes = + mode_lib->vba.TotImmediateFlipBytes + + mode_lib->vba.ImmediateFlipBytes[k]; + } + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + CalculateFlipSchedule( + mode_lib, + mode_lib->vba.ExtraLatency, + mode_lib->vba.UrgentLatency, + mode_lib->vba.MaxPageTableLevels, + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.BandwidthAvailableForImmediateFlip, + mode_lib->vba.TotImmediateFlipBytes, + mode_lib->vba.SourcePixelFormat[k], + mode_lib->vba.ImmediateFlipBytes[k], + mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k], + mode_lib->vba.VRatio[k], + mode_lib->vba.Tno_bw[k], + mode_lib->vba.PDEAndMetaPTEBytesPerFrame[k], + mode_lib->vba.MetaRowBytes[k], + mode_lib->vba.DPTEBytesPerRow[k], + mode_lib->vba.DCCEnable[k], + mode_lib->vba.dpte_row_height[k], + mode_lib->vba.meta_row_height[k], + mode_lib->vba.qual_row_bw[k], + &mode_lib->vba.DestinationLinesToRequestVMInImmediateFlip[k], + &mode_lib->vba.DestinationLinesToRequestRowInImmediateFlip[k], + &mode_lib->vba.final_flip_bw[k], + &mode_lib->vba.ImmediateFlipSupportedForPipe[k]); + } + mode_lib->vba.total_dcn_read_bw_with_flip = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.total_dcn_read_bw_with_flip = + mode_lib->vba.total_dcn_read_bw_with_flip + + mode_lib->vba.cursor_bw[k] + + dml_max3( + mode_lib->vba.prefetch_vm_bw[k], + mode_lib->vba.prefetch_row_bw[k], + mode_lib->vba.final_flip_bw[k] + + dml_max( + mode_lib->vba.ReadBandwidth[k], + mode_lib->vba.RequiredPrefetchPixelDataBW[i][k])); + } + mode_lib->vba.ImmediateFlipSupportedForState[i] = true; + if (mode_lib->vba.total_dcn_read_bw_with_flip + > mode_lib->vba.ReturnBWPerState[i]) { + mode_lib->vba.ImmediateFlipSupportedForState[i] = false; + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.ImmediateFlipSupportedForPipe[k] == false) { + mode_lib->vba.ImmediateFlipSupportedForState[i] = false; + } + } + } else { + mode_lib->vba.ImmediateFlipSupportedForState[i] = false; + } + } + /*PTE Buffer Size Check*/ + + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.PTEBufferSizeNotExceeded[i] = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.PTEBufferSizeNotExceededY[i][k] == false + || mode_lib->vba.PTEBufferSizeNotExceededC[i][k] == false) { + mode_lib->vba.PTEBufferSizeNotExceeded[i] = false; + } + } + } + /*Cursor Support Check*/ + + mode_lib->vba.CursorSupport = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.CursorWidth[k][0] > 0.0) { + if (dml_floor( + dml_floor( + mode_lib->vba.CursorBufferSize + - mode_lib->vba.CursorChunkSize, + mode_lib->vba.CursorChunkSize) * 1024.0 + / (mode_lib->vba.CursorWidth[k][0] + * mode_lib->vba.CursorBPP[k][0] + / 8.0), + 1.0) + * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) + / mode_lib->vba.VRatio[k] < mode_lib->vba.UrgentLatency + || (mode_lib->vba.CursorBPP[k][0] == 64.0 + && mode_lib->vba.Cursor64BppSupport == false)) { + mode_lib->vba.CursorSupport = false; + } + } + } + /*Valid Pitch Check*/ + + mode_lib->vba.PitchSupport = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.AlignedYPitch[k] = dml_ceil( + dml_max(mode_lib->vba.PitchY[k], mode_lib->vba.ViewportWidth[k]), + mode_lib->vba.MacroTileWidthY[k]); + if (mode_lib->vba.AlignedYPitch[k] > mode_lib->vba.PitchY[k]) { + mode_lib->vba.PitchSupport = false; + } + if (mode_lib->vba.DCCEnable[k] == true) { + mode_lib->vba.AlignedDCCMetaPitch[k] = dml_ceil( + dml_max( + mode_lib->vba.DCCMetaPitchY[k], + mode_lib->vba.ViewportWidth[k]), + 64.0 * mode_lib->vba.Read256BlockWidthY[k]); + } else { + mode_lib->vba.AlignedDCCMetaPitch[k] = mode_lib->vba.DCCMetaPitchY[k]; + } + if (mode_lib->vba.AlignedDCCMetaPitch[k] > mode_lib->vba.DCCMetaPitchY[k]) { + mode_lib->vba.PitchSupport = false; + } + if (mode_lib->vba.SourcePixelFormat[k] != dm_444_64 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_32 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_16 + && mode_lib->vba.SourcePixelFormat[k] != dm_mono_16 + && mode_lib->vba.SourcePixelFormat[k] != dm_mono_8) { + mode_lib->vba.AlignedCPitch[k] = dml_ceil( + dml_max( + mode_lib->vba.PitchC[k], + mode_lib->vba.ViewportWidth[k] / 2.0), + mode_lib->vba.MacroTileWidthC[k]); + } else { + mode_lib->vba.AlignedCPitch[k] = mode_lib->vba.PitchC[k]; + } + if (mode_lib->vba.AlignedCPitch[k] > mode_lib->vba.PitchC[k]) { + mode_lib->vba.PitchSupport = false; + } + } + /*Mode Support, Voltage State and SOC Configuration*/ + + for (i = DC__VOLTAGE_STATES; i >= 0; i--) { + if (mode_lib->vba.ScaleRatioAndTapsSupport == true + && mode_lib->vba.SourceFormatPixelAndScanSupport == true + && mode_lib->vba.ViewportSizeSupport[i] == true + && mode_lib->vba.BandwidthSupport[i] == true + && mode_lib->vba.DIOSupport[i] == true + && mode_lib->vba.NotEnoughDSCUnits[i] == false + && mode_lib->vba.DSCCLKRequiredMoreThanSupported[i] == false + && mode_lib->vba.UrgentLatencySupport[i] == true + && mode_lib->vba.ROBSupport[i] == true + && mode_lib->vba.DISPCLK_DPPCLK_Support[i] == true + && mode_lib->vba.TotalAvailablePipesSupport[i] == true + && mode_lib->vba.NumberOfOTGSupport == true + && mode_lib->vba.WritebackModeSupport == true + && mode_lib->vba.WritebackLatencySupport == true + && mode_lib->vba.WritebackScaleRatioAndTapsSupport == true + && mode_lib->vba.CursorSupport == true + && mode_lib->vba.PitchSupport == true + && mode_lib->vba.PrefetchSupported[i] == true + && mode_lib->vba.VRatioInPrefetchSupported[i] == true + && mode_lib->vba.PTEBufferSizeNotExceeded[i] == true + && mode_lib->vba.NonsupportedDSCInputBPC == false) { + mode_lib->vba.ModeSupport[i] = true; + } else { + mode_lib->vba.ModeSupport[i] = false; + } + } + for (i = DC__VOLTAGE_STATES; i >= 0; i--) { + if (i == DC__VOLTAGE_STATES || mode_lib->vba.ModeSupport[i] == true) { + mode_lib->vba.VoltageLevel = i; + } + } + mode_lib->vba.DCFCLK = mode_lib->vba.DCFCLKPerState[mode_lib->vba.VoltageLevel]; + mode_lib->vba.DRAMSpeed = mode_lib->vba.DRAMSpeedPerState[mode_lib->vba.VoltageLevel]; + mode_lib->vba.FabricClock = mode_lib->vba.FabricClockPerState[mode_lib->vba.VoltageLevel]; + mode_lib->vba.SOCCLK = mode_lib->vba.SOCCLKPerState[mode_lib->vba.VoltageLevel]; + mode_lib->vba.FabricAndDRAMBandwidth = + mode_lib->vba.FabricAndDRAMBandwidthPerState[mode_lib->vba.VoltageLevel]; + mode_lib->vba.ImmediateFlipSupport = + mode_lib->vba.ImmediateFlipSupportedForState[mode_lib->vba.VoltageLevel]; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.DPPPerPlane[k] = mode_lib->vba.NoOfDPP[mode_lib->vba.VoltageLevel][k]; + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.BlendingAndTiming[k] == k) { + mode_lib->vba.ODMCombineEnabled[k] = + mode_lib->vba.ODMCombineEnablePerState[mode_lib->vba.VoltageLevel][k]; + } else { + mode_lib->vba.ODMCombineEnabled[k] = 0; + } + mode_lib->vba.DSCEnabled[k] = + mode_lib->vba.RequiresDSC[mode_lib->vba.VoltageLevel][k]; + mode_lib->vba.OutputBpp[k] = + mode_lib->vba.OutputBppPerState[mode_lib->vba.VoltageLevel][k]; + } +} 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 new file mode 100644 index 000000000000..4112409cd974 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h @@ -0,0 +1,598 @@ +/* + * 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 + * + */ + +#ifndef __DML2_DISPLAY_MODE_VBA_H__ +#define __DML2_DISPLAY_MODE_VBA_H__ + +#include "dml_common_defs.h" + +struct display_mode_lib; + +void set_prefetch_mode(struct display_mode_lib *mode_lib, + bool cstate_en, + bool pstate_en, + bool ignore_viewport_pos, + bool immediate_flip_support); + +#define dml_get_attr_decl(attr) double get_##attr(struct display_mode_lib *mode_lib, const display_e2e_pipe_params_st *pipes, unsigned int num_pipes) + +dml_get_attr_decl(clk_dcf_deepsleep); +dml_get_attr_decl(wm_urgent); +dml_get_attr_decl(wm_memory_trip); +dml_get_attr_decl(wm_writeback_urgent); +dml_get_attr_decl(wm_stutter_exit); +dml_get_attr_decl(wm_stutter_enter_exit); +dml_get_attr_decl(wm_dram_clock_change); +dml_get_attr_decl(wm_writeback_dram_clock_change); +dml_get_attr_decl(wm_xfc_underflow); +dml_get_attr_decl(stutter_efficiency_no_vblank); +dml_get_attr_decl(stutter_efficiency); +dml_get_attr_decl(urgent_latency); +dml_get_attr_decl(urgent_extra_latency); +dml_get_attr_decl(nonurgent_latency); +dml_get_attr_decl(dram_clock_change_latency); +dml_get_attr_decl(dispclk_calculated); +dml_get_attr_decl(total_data_read_bw); +dml_get_attr_decl(return_bw); +dml_get_attr_decl(tcalc); + +#define dml_get_pipe_attr_decl(attr) double get_##attr(struct display_mode_lib *mode_lib, const display_e2e_pipe_params_st *pipes, unsigned int num_pipes, unsigned int which_pipe) + +dml_get_pipe_attr_decl(dsc_delay); +dml_get_pipe_attr_decl(dppclk_calculated); +dml_get_pipe_attr_decl(dscclk_calculated); +dml_get_pipe_attr_decl(min_ttu_vblank); +dml_get_pipe_attr_decl(vratio_prefetch_l); +dml_get_pipe_attr_decl(vratio_prefetch_c); +dml_get_pipe_attr_decl(dst_x_after_scaler); +dml_get_pipe_attr_decl(dst_y_after_scaler); +dml_get_pipe_attr_decl(dst_y_per_vm_vblank); +dml_get_pipe_attr_decl(dst_y_per_row_vblank); +dml_get_pipe_attr_decl(dst_y_prefetch); +dml_get_pipe_attr_decl(dst_y_per_vm_flip); +dml_get_pipe_attr_decl(dst_y_per_row_flip); +dml_get_pipe_attr_decl(xfc_transfer_delay); +dml_get_pipe_attr_decl(xfc_precharge_delay); +dml_get_pipe_attr_decl(xfc_remote_surface_flip_latency); +dml_get_pipe_attr_decl(xfc_prefetch_margin); + +unsigned int get_vstartup_calculated( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes, + unsigned int which_pipe); + +double get_total_immediate_flip_bytes( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes); +double get_total_immediate_flip_bw( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes); +double get_total_prefetch_bw( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes); + +unsigned int dml_get_voltage_level( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes); + +bool Calculate256BBlockSizes( + enum source_format_class SourcePixelFormat, + enum dm_swizzle_mode SurfaceTiling, + unsigned int BytePerPixelY, + unsigned int BytePerPixelC, + unsigned int *BlockHeight256BytesY, + unsigned int *BlockHeight256BytesC, + unsigned int *BlockWidth256BytesY, + unsigned int *BlockWidth256BytesC); + + +struct vba_vars_st { + ip_params_st ip; + soc_bounding_box_st soc; + + unsigned int MaximumMaxVStartupLines; + double cursor_bw[DC__NUM_DPP__MAX]; + double meta_row_bw[DC__NUM_DPP__MAX]; + double dpte_row_bw[DC__NUM_DPP__MAX]; + double qual_row_bw[DC__NUM_DPP__MAX]; + double WritebackDISPCLK; + double PSCL_THROUGHPUT_LUMA[DC__NUM_DPP__MAX]; + double PSCL_THROUGHPUT_CHROMA[DC__NUM_DPP__MAX]; + double DPPCLKUsingSingleDPPLuma; + double DPPCLKUsingSingleDPPChroma; + double DPPCLKUsingSingleDPP[DC__NUM_DPP__MAX]; + double DISPCLKWithRamping; + double DISPCLKWithoutRamping; + double GlobalDPPCLK; + double DISPCLKWithRampingRoundedToDFSGranularity; + double DISPCLKWithoutRampingRoundedToDFSGranularity; + double MaxDispclkRoundedToDFSGranularity; + bool DCCEnabledAnyPlane; + double ReturnBandwidthToDCN; + unsigned int SwathWidthY[DC__NUM_DPP__MAX]; + unsigned int SwathWidthSingleDPPY[DC__NUM_DPP__MAX]; + double BytePerPixelDETY[DC__NUM_DPP__MAX]; + double BytePerPixelDETC[DC__NUM_DPP__MAX]; + double ReadBandwidthPlaneLuma[DC__NUM_DPP__MAX]; + double ReadBandwidthPlaneChroma[DC__NUM_DPP__MAX]; + unsigned int TotalActiveDPP; + unsigned int TotalDCCActiveDPP; + double UrgentRoundTripAndOutOfOrderLatency; + double DisplayPipeLineDeliveryTimeLuma[DC__NUM_DPP__MAX]; // WM + double DisplayPipeLineDeliveryTimeChroma[DC__NUM_DPP__MAX]; // WM + double LinesInDETY[DC__NUM_DPP__MAX]; // WM + double LinesInDETC[DC__NUM_DPP__MAX]; // WM + unsigned int LinesInDETYRoundedDownToSwath[DC__NUM_DPP__MAX]; // WM + unsigned int LinesInDETCRoundedDownToSwath[DC__NUM_DPP__MAX]; // WM + double FullDETBufferingTimeY[DC__NUM_DPP__MAX]; // WM + double FullDETBufferingTimeC[DC__NUM_DPP__MAX]; // WM + double MinFullDETBufferingTime; + double FrameTimeForMinFullDETBufferingTime; + double AverageReadBandwidthGBytePerSecond; + double PartOfBurstThatFitsInROB; + double StutterBurstTime; + //unsigned int NextPrefetchMode; + double VBlankTime; + double SmallestVBlank; + double DCFCLKDeepSleepPerPlane; + double EffectiveDETPlusLBLinesLuma; + double EffectiveDETPlusLBLinesChroma; + double UrgentLatencySupportUsLuma; + double UrgentLatencySupportUsChroma; + double UrgentLatencySupportUs[DC__NUM_DPP__MAX]; + unsigned int DSCFormatFactor; + unsigned int BlockHeight256BytesY[DC__NUM_DPP__MAX]; + unsigned int BlockHeight256BytesC[DC__NUM_DPP__MAX]; + unsigned int BlockWidth256BytesY[DC__NUM_DPP__MAX]; + unsigned int BlockWidth256BytesC[DC__NUM_DPP__MAX]; + double VInitPreFillY[DC__NUM_DPP__MAX]; + double VInitPreFillC[DC__NUM_DPP__MAX]; + unsigned int MaxNumSwathY[DC__NUM_DPP__MAX]; + unsigned int MaxNumSwathC[DC__NUM_DPP__MAX]; + double PrefetchSourceLinesY[DC__NUM_DPP__MAX]; + double PrefetchSourceLinesC[DC__NUM_DPP__MAX]; + double PixelPTEBytesPerRow[DC__NUM_DPP__MAX]; + double MetaRowByte[DC__NUM_DPP__MAX]; + unsigned int dpte_row_height[DC__NUM_DPP__MAX]; + unsigned int dpte_row_height_chroma[DC__NUM_DPP__MAX]; + unsigned int meta_row_height[DC__NUM_DPP__MAX]; + unsigned int meta_row_height_chroma[DC__NUM_DPP__MAX]; + + unsigned int MacroTileWidthY[DC__NUM_DPP__MAX]; + unsigned int MacroTileWidthC[DC__NUM_DPP__MAX]; + unsigned int MaxVStartupLines[DC__NUM_DPP__MAX]; + double WritebackDelay[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + bool PrefetchModeSupported; + bool AllowDRAMClockChangeDuringVBlank[DC__NUM_DPP__MAX]; + bool AllowDRAMSelfRefreshDuringVBlank[DC__NUM_DPP__MAX]; + double RequiredPrefetchPixDataBW[DC__NUM_DPP__MAX]; + double XFCRemoteSurfaceFlipDelay; + double TInitXFill; + double TslvChk; + double SrcActiveDrainRate; + double Tno_bw[DC__NUM_DPP__MAX]; + bool ImmediateFlipSupported; + + double prefetch_vm_bw[DC__NUM_DPP__MAX]; + double prefetch_row_bw[DC__NUM_DPP__MAX]; + bool ImmediateFlipSupportedForPipe[DC__NUM_DPP__MAX]; + unsigned int VStartupLines; + double DisplayPipeLineDeliveryTimeLumaPrefetch[DC__NUM_DPP__MAX]; + double DisplayPipeLineDeliveryTimeChromaPrefetch[DC__NUM_DPP__MAX]; + unsigned int ActiveDPPs; + unsigned int LBLatencyHidingSourceLinesY; + unsigned int LBLatencyHidingSourceLinesC; + double ActiveDRAMClockChangeLatencyMargin[DC__NUM_DPP__MAX]; + double MinActiveDRAMClockChangeMargin; + double XFCSlaveVUpdateOffset[DC__NUM_DPP__MAX]; + double XFCSlaveVupdateWidth[DC__NUM_DPP__MAX]; + double XFCSlaveVReadyOffset[DC__NUM_DPP__MAX]; + double InitFillLevel; + double FinalFillMargin; + double FinalFillLevel; + double RemainingFillLevel; + double TFinalxFill; + + + // + // SOC Bounding Box Parameters + // + double SRExitTime; + double SREnterPlusExitTime; + double UrgentLatency; + double WritebackLatency; + double PercentOfIdealDRAMAndFabricBWReceivedAfterUrgLatency; + double NumberOfChannels; + double DRAMChannelWidth; + double FabricDatapathToDCNDataReturn; + double ReturnBusWidth; + double Downspreading; + double DISPCLKDPPCLKDSCCLKDownSpreading; + double DISPCLKDPPCLKVCOSpeed; + double RoundTripPingLatencyCycles; + double UrgentOutOfOrderReturnPerChannel; + unsigned int VMMPageSize; + double DRAMClockChangeLatency; + double XFCBusTransportTime; + double XFCXBUFLatencyTolerance; + + // + // IP Parameters + // + unsigned int ROBBufferSizeInKByte; + double DETBufferSizeInKByte; + unsigned int DPPOutputBufferPixels; + unsigned int OPPOutputBufferLines; + unsigned int PixelChunkSizeInKByte; + double ReturnBW; + bool VirtualMemoryEnable; + unsigned int MaxPageTableLevels; + unsigned int OverridePageTableLevels; + unsigned int PTEChunkSize; + unsigned int MetaChunkSize; + unsigned int WritebackChunkSize; + bool ODMCapability; + unsigned int NumberOfDSC; + unsigned int LineBufferSize; + unsigned int MaxLineBufferLines; + unsigned int WritebackInterfaceLumaBufferSize; + unsigned int WritebackInterfaceChromaBufferSize; + unsigned int WritebackChromaLineBufferWidth; + double MaxDCHUBToPSCLThroughput; + double MaxPSCLToLBThroughput; + unsigned int PTEBufferSizeInRequests; + double DISPCLKRampingMargin; + unsigned int MaxInterDCNTileRepeaters; + bool XFCSupported; + double XFCSlvChunkSize; + double XFCFillBWOverhead; + double XFCFillConstant; + double XFCTSlvVupdateOffset; + double XFCTSlvVupdateWidth; + double XFCTSlvVreadyOffset; + double DPPCLKDelaySubtotal; + double DPPCLKDelaySCL; + double DPPCLKDelaySCLLBOnly; + double DPPCLKDelayCNVCFormater; + double DPPCLKDelayCNVCCursor; + double DISPCLKDelaySubtotal; + bool ProgressiveToInterlaceUnitInOPP; + unsigned int PDEProcessingBufIn64KBReqs; + + // Pipe/Plane Parameters + int VoltageLevel; + double FabricAndDRAMBandwidth; + double FabricClock; + double DRAMSpeed; + double DISPCLK; + double SOCCLK; + double DCFCLK; + + unsigned int NumberOfActivePlanes; + unsigned int ViewportWidth[DC__NUM_DPP__MAX]; + unsigned int ViewportHeight[DC__NUM_DPP__MAX]; + unsigned int ViewportYStartY[DC__NUM_DPP__MAX]; + unsigned int ViewportYStartC[DC__NUM_DPP__MAX]; + unsigned int PitchY[DC__NUM_DPP__MAX]; + unsigned int PitchC[DC__NUM_DPP__MAX]; + double HRatio[DC__NUM_DPP__MAX]; + double VRatio[DC__NUM_DPP__MAX]; + unsigned int htaps[DC__NUM_DPP__MAX]; + unsigned int vtaps[DC__NUM_DPP__MAX]; + unsigned int HTAPsChroma[DC__NUM_DPP__MAX]; + unsigned int VTAPsChroma[DC__NUM_DPP__MAX]; + unsigned int HTotal[DC__NUM_DPP__MAX]; + unsigned int VTotal[DC__NUM_DPP__MAX]; + unsigned int DPPPerPlane[DC__NUM_DPP__MAX]; + double PixelClock[DC__NUM_DPP__MAX]; + double PixelClockBackEnd[DC__NUM_DPP__MAX]; + double DPPCLK[DC__NUM_DPP__MAX]; + bool DCCEnable[DC__NUM_DPP__MAX]; + unsigned int DCCMetaPitchY[DC__NUM_DPP__MAX]; + enum scan_direction_class SourceScan[DC__NUM_DPP__MAX]; + enum source_format_class SourcePixelFormat[DC__NUM_DPP__MAX]; + bool WritebackEnable[DC__NUM_DPP__MAX]; + double WritebackDestinationWidth[DC__NUM_DPP__MAX]; + double WritebackDestinationHeight[DC__NUM_DPP__MAX]; + double WritebackSourceHeight[DC__NUM_DPP__MAX]; + enum source_format_class WritebackPixelFormat[DC__NUM_DPP__MAX]; + unsigned int WritebackLumaHTaps[DC__NUM_DPP__MAX]; + unsigned int WritebackLumaVTaps[DC__NUM_DPP__MAX]; + unsigned int WritebackChromaHTaps[DC__NUM_DPP__MAX]; + unsigned int WritebackChromaVTaps[DC__NUM_DPP__MAX]; + double WritebackHRatio[DC__NUM_DPP__MAX]; + double WritebackVRatio[DC__NUM_DPP__MAX]; + unsigned int HActive[DC__NUM_DPP__MAX]; + unsigned int VActive[DC__NUM_DPP__MAX]; + bool Interlace[DC__NUM_DPP__MAX]; + enum dm_swizzle_mode SurfaceTiling[DC__NUM_DPP__MAX]; + unsigned int ScalerRecoutWidth[DC__NUM_DPP__MAX]; + bool DynamicMetadataEnable[DC__NUM_DPP__MAX]; + unsigned int DynamicMetadataLinesBeforeActiveRequired[DC__NUM_DPP__MAX]; + unsigned int DynamicMetadataTransmittedBytes[DC__NUM_DPP__MAX]; + double DCCRate[DC__NUM_DPP__MAX]; + bool ODMCombineEnabled[DC__NUM_DPP__MAX]; + double OutputBpp[DC__NUM_DPP__MAX]; + unsigned int NumberOfDSCSlices[DC__NUM_DPP__MAX]; + bool DSCEnabled[DC__NUM_DPP__MAX]; + unsigned int DSCDelay[DC__NUM_DPP__MAX]; + unsigned int DSCInputBitPerComponent[DC__NUM_DPP__MAX]; + enum output_format_class OutputFormat[DC__NUM_DPP__MAX]; + enum output_encoder_class Output[DC__NUM_DPP__MAX]; + unsigned int BlendingAndTiming[DC__NUM_DPP__MAX]; + bool SynchronizedVBlank; + unsigned int NumberOfCursors[DC__NUM_DPP__MAX]; + unsigned int CursorWidth[DC__NUM_DPP__MAX][DC__NUM_CURSOR__MAX]; + unsigned int CursorBPP[DC__NUM_DPP__MAX][DC__NUM_CURSOR__MAX]; + bool XFCEnabled[DC__NUM_DPP__MAX]; + bool ScalerEnabled[DC__NUM_DPP__MAX]; + + // Intermediates/Informational + bool ImmediateFlipSupport; + unsigned int SwathHeightY[DC__NUM_DPP__MAX]; + unsigned int SwathHeightC[DC__NUM_DPP__MAX]; + unsigned int DETBufferSizeY[DC__NUM_DPP__MAX]; + unsigned int DETBufferSizeC[DC__NUM_DPP__MAX]; + unsigned int LBBitPerPixel[DC__NUM_DPP__MAX]; + double LastPixelOfLineExtraWatermark; + double TotalDataReadBandwidth; + unsigned int TotalActiveWriteback; + unsigned int EffectiveLBLatencyHidingSourceLinesLuma; + unsigned int EffectiveLBLatencyHidingSourceLinesChroma; + double BandwidthAvailableForImmediateFlip; + unsigned int PrefetchMode; + bool IgnoreViewportPositioning; + double PrefetchBandwidth[DC__NUM_DPP__MAX]; + bool ErrorResult[DC__NUM_DPP__MAX]; + double PDEAndMetaPTEBytesFrame[DC__NUM_DPP__MAX]; + + // + // Calculated dml_ml->vba.Outputs + // + double DCFClkDeepSleep; + double UrgentWatermark; + double UrgentExtraLatency; + double MemoryTripWatermark; + double WritebackUrgentWatermark; + double StutterExitWatermark; + double StutterEnterPlusExitWatermark; + double DRAMClockChangeWatermark; + double WritebackDRAMClockChangeWatermark; + double StutterEfficiency; + double StutterEfficiencyNotIncludingVBlank; + double MinUrgentLatencySupportUs; + double NonUrgentLatencyTolerance; + double MinActiveDRAMClockChangeLatencySupported; + enum clock_change_support DRAMClockChangeSupport; + + // These are the clocks calcuated by the library but they are not actually + // used explicitly. They are fetched by tests and then possibly used. The + // ultimate values to use are the ones specified by the parameters to DML + double DISPCLK_calculated; + double DSCCLK_calculated[DC__NUM_DPP__MAX]; + double DPPCLK_calculated[DC__NUM_DPP__MAX]; + + unsigned int VStartup[DC__NUM_DPP__MAX]; + unsigned int VUpdateOffsetPix[DC__NUM_DPP__MAX]; + unsigned int VUpdateWidthPix[DC__NUM_DPP__MAX]; + unsigned int VReadyOffsetPix[DC__NUM_DPP__MAX]; + unsigned int VStartupRequiredWhenNotEnoughTimeForDynamicMetadata; + + double ImmediateFlipBW; + unsigned int TotImmediateFlipBytes; + double TCalc; + double MinTTUVBlank[DC__NUM_DPP__MAX]; + double VRatioPrefetchY[DC__NUM_DPP__MAX]; + double VRatioPrefetchC[DC__NUM_DPP__MAX]; + double DSTXAfterScaler[DC__NUM_DPP__MAX]; + double DSTYAfterScaler[DC__NUM_DPP__MAX]; + + double DestinationLinesToRequestVMInVBlank[DC__NUM_DPP__MAX]; + double DestinationLinesToRequestRowInVBlank[DC__NUM_DPP__MAX]; + double DestinationLinesForPrefetch[DC__NUM_DPP__MAX]; + double DestinationLinesToRequestRowInImmediateFlip[DC__NUM_DPP__MAX]; + double DestinationLinesToRequestVMInImmediateFlip[DC__NUM_DPP__MAX]; + + double XFCTransferDelay[DC__NUM_DPP__MAX]; + double XFCPrechargeDelay[DC__NUM_DPP__MAX]; + double XFCRemoteSurfaceFlipLatency[DC__NUM_DPP__MAX]; + double XFCPrefetchMargin[DC__NUM_DPP__MAX]; + + display_e2e_pipe_params_st cache_pipes[DC__NUM_DPP__MAX]; + unsigned int cache_num_pipes; + unsigned int pipe_plane[DC__NUM_DPP__MAX]; + + /* vba mode support */ + /*inputs*/ + bool SupportGFX7CompatibleTilingIn32bppAnd64bpp; + double MaxHSCLRatio; + double MaxVSCLRatio; + unsigned int MaxNumWriteback; + bool WritebackLumaAndChromaScalingSupported; + bool Cursor64BppSupport; + double DCFCLKPerState[DC__VOLTAGE_STATES + 1]; + double FabricClockPerState[DC__VOLTAGE_STATES + 1]; + double SOCCLKPerState[DC__VOLTAGE_STATES + 1]; + double PHYCLKPerState[DC__VOLTAGE_STATES + 1]; + double MaxDppclk[DC__VOLTAGE_STATES + 1]; + double MaxDSCCLK[DC__VOLTAGE_STATES + 1]; + double DRAMSpeedPerState[DC__VOLTAGE_STATES + 1]; + double MaxDispclk[DC__VOLTAGE_STATES + 1]; + + /*outputs*/ + bool ScaleRatioAndTapsSupport; + bool SourceFormatPixelAndScanSupport; + unsigned int SwathWidthYSingleDPP[DC__NUM_DPP__MAX]; + double BytePerPixelInDETY[DC__NUM_DPP__MAX]; + double BytePerPixelInDETC[DC__NUM_DPP__MAX]; + double TotalReadBandwidthConsumedGBytePerSecond; + double ReadBandwidth[DC__NUM_DPP__MAX]; + double TotalWriteBandwidthConsumedGBytePerSecond; + double WriteBandwidth[DC__NUM_DPP__MAX]; + double TotalBandwidthConsumedGBytePerSecond; + bool DCCEnabledInAnyPlane; + bool WritebackLatencySupport; + bool WritebackModeSupport; + bool Writeback10bpc420Supported; + bool BandwidthSupport[DC__VOLTAGE_STATES + 1]; + unsigned int TotalNumberOfActiveWriteback; + double CriticalPoint; + double ReturnBWToDCNPerState; + double FabricAndDRAMBandwidthPerState[DC__VOLTAGE_STATES + 1]; + double ReturnBWPerState[DC__VOLTAGE_STATES + 1]; + double UrgentRoundTripAndOutOfOrderLatencyPerState[DC__VOLTAGE_STATES + 1]; + bool ODMCombineEnablePerState[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + bool PTEBufferSizeNotExceededY[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + bool PTEBufferSizeNotExceededC[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + bool PrefetchSupported[DC__VOLTAGE_STATES + 1]; + bool VRatioInPrefetchSupported[DC__VOLTAGE_STATES + 1]; + bool DISPCLK_DPPCLK_Support[DC__VOLTAGE_STATES + 1]; + bool TotalAvailablePipesSupport[DC__VOLTAGE_STATES + 1]; + bool UrgentLatencySupport[DC__VOLTAGE_STATES + 1]; + bool ModeSupport[DC__VOLTAGE_STATES + 1]; + bool DIOSupport[DC__VOLTAGE_STATES + 1]; + bool NotEnoughDSCUnits[DC__VOLTAGE_STATES + 1]; + bool DSCCLKRequiredMoreThanSupported[DC__VOLTAGE_STATES + 1]; + bool ROBSupport[DC__VOLTAGE_STATES + 1]; + bool PTEBufferSizeNotExceeded[DC__VOLTAGE_STATES + 1]; + bool RequiresDSC[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + bool IsErrorResult[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + bool ViewportSizeSupport[DC__VOLTAGE_STATES + 1]; + bool prefetch_vm_bw_valid; + bool prefetch_row_bw_valid; + bool NumberOfOTGSupport; + bool NonsupportedDSCInputBPC; + bool WritebackScaleRatioAndTapsSupport; + bool CursorSupport; + bool PitchSupport; + + double WritebackLineBufferLumaBufferSize; + double WritebackLineBufferChromaBufferSize; + double WritebackMinHSCLRatio; + double WritebackMinVSCLRatio; + double WritebackMaxHSCLRatio; + double WritebackMaxVSCLRatio; + double WritebackMaxHSCLTaps; + double WritebackMaxVSCLTaps; + unsigned int MaxNumDPP; + unsigned int MaxNumOTG; + double CursorBufferSize; + double CursorChunkSize; + unsigned int Mode; + unsigned int NoOfDPP[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + double OutputLinkDPLanes[DC__NUM_DPP__MAX]; + double SwathWidthYPerState[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + double SwathHeightYPerState[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + double SwathHeightCPerState[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + double UrgentLatencySupportUsPerState[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + double VRatioPreY[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + double VRatioPreC[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + double RequiredPrefetchPixelDataBW[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + double RequiredDPPCLK[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + double RequiredDISPCLK[DC__VOLTAGE_STATES + 1]; + double TotalNumberOfActiveDPP[DC__VOLTAGE_STATES + 1]; + double TotalNumberOfDCCActiveDPP[DC__VOLTAGE_STATES + 1]; + double PrefetchBW[DC__NUM_DPP__MAX]; + double PDEAndMetaPTEBytesPerFrame[DC__NUM_DPP__MAX]; + double MetaRowBytes[DC__NUM_DPP__MAX]; + double DPTEBytesPerRow[DC__NUM_DPP__MAX]; + double PrefetchLinesY[DC__NUM_DPP__MAX]; + double PrefetchLinesC[DC__NUM_DPP__MAX]; + unsigned int MaxNumSwY[DC__NUM_DPP__MAX]; + unsigned int MaxNumSwC[DC__NUM_DPP__MAX]; + double PrefillY[DC__NUM_DPP__MAX]; + double PrefillC[DC__NUM_DPP__MAX]; + double LineTimesForPrefetch[DC__NUM_DPP__MAX]; + double LinesForMetaPTE[DC__NUM_DPP__MAX]; + double LinesForMetaAndDPTERow[DC__NUM_DPP__MAX]; + double MinDPPCLKUsingSingleDPP[DC__NUM_DPP__MAX]; + double RequiresFEC[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + unsigned int OutputBppPerState[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + double DSCDelayPerState[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + unsigned int Read256BlockHeightY[DC__NUM_DPP__MAX]; + unsigned int Read256BlockWidthY[DC__NUM_DPP__MAX]; + unsigned int Read256BlockHeightC[DC__NUM_DPP__MAX]; + unsigned int Read256BlockWidthC[DC__NUM_DPP__MAX]; + unsigned int ImmediateFlipBytes[DC__NUM_DPP__MAX]; + double MaxSwathHeightY[DC__NUM_DPP__MAX]; + double MaxSwathHeightC[DC__NUM_DPP__MAX]; + double MinSwathHeightY[DC__NUM_DPP__MAX]; + double MinSwathHeightC[DC__NUM_DPP__MAX]; + double PSCL_FACTOR[DC__NUM_DPP__MAX]; + double PSCL_FACTOR_CHROMA[DC__NUM_DPP__MAX]; + double MaximumVStartup[DC__NUM_DPP__MAX]; + double AlignedDCCMetaPitch[DC__NUM_DPP__MAX]; + double AlignedYPitch[DC__NUM_DPP__MAX]; + double AlignedCPitch[DC__NUM_DPP__MAX]; + double MaximumSwathWidth[DC__NUM_DPP__MAX]; + double final_flip_bw[DC__NUM_DPP__MAX]; + double ImmediateFlipSupportedForState[DC__VOLTAGE_STATES + 1]; + + double WritebackLumaVExtra; + double WritebackChromaVExtra; + double WritebackRequiredDISPCLK; + double MaximumSwathWidthSupport; + double MaximumSwathWidthInDETBuffer; + double MaximumSwathWidthInLineBuffer; + double MaxDispclkRoundedDownToDFSGranularity; + double MaxDppclkRoundedDownToDFSGranularity; + double PlaneRequiredDISPCLKWithoutODMCombine; + double PlaneRequiredDISPCLK; + double TotalNumberOfActiveOTG; + double FECOverhead; + double EffectiveFECOverhead; + unsigned int Outbpp; + unsigned int OutbppDSC; + double TotalDSCUnitsRequired; + double bpp; + unsigned int slices; + double SwathWidthGranularityY; + double RoundedUpMaxSwathSizeBytesY; + double SwathWidthGranularityC; + double RoundedUpMaxSwathSizeBytesC; + double LinesInDETLuma; + double LinesInDETChroma; + double EffectiveDETLBLinesLuma; + double EffectiveDETLBLinesChroma; + double ProjectedDCFCLKDeepSleep; + double PDEAndMetaPTEBytesPerFrameY; + double PDEAndMetaPTEBytesPerFrameC; + unsigned int MetaRowBytesY; + unsigned int MetaRowBytesC; + unsigned int DPTEBytesPerRowC; + unsigned int DPTEBytesPerRowY; + double ExtraLatency; + double TimeCalc; + double TWait; + double MaximumReadBandwidthWithPrefetch; + double total_dcn_read_bw_with_flip; +}; + +#endif /* _DML2_DISPLAY_MODE_VBA_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c index 7a5fb1cef303..8ba962df42e6 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c @@ -22,8 +22,22 @@ * Authors: AMD * */ -#include "display_rq_dlg_calc.h" + #include "display_mode_lib.h" +#include "display_mode_vba.h" +#include "display_rq_dlg_calc.h" + +static void calculate_ttu_cursor(struct display_mode_lib *mode_lib, + double *refcyc_per_req_delivery_pre_cur, + double *refcyc_per_req_delivery_cur, + double refclk_freq_in_mhz, + double ref_freq_to_pix_freq, + double hscale_pixel_rate_l, + double hscl_ratio, + double vratio_pre_l, + double vratio_l, + unsigned int cur_width, + enum cursor_bpp cur_bpp); #include "dml_inline_defs.h" @@ -50,6 +64,8 @@ static unsigned int get_bytes_per_element(enum source_format_class source_format ret_val = 4; else ret_val = 2; + } else if (source_format == dm_444_8) { + ret_val = 1; } return ret_val; } @@ -64,123 +80,43 @@ static bool is_dual_plane(enum source_format_class source_format) return ret_val; } -static void get_blk256_size( - unsigned int *blk256_width, - unsigned int *blk256_height, - unsigned int bytes_per_element) -{ - if (bytes_per_element == 1) { - *blk256_width = 16; - *blk256_height = 16; - } else if (bytes_per_element == 2) { - *blk256_width = 16; - *blk256_height = 8; - } else if (bytes_per_element == 4) { - *blk256_width = 8; - *blk256_height = 8; - } else if (bytes_per_element == 8) { - *blk256_width = 8; - *blk256_height = 4; - } -} - -static double get_refcyc_per_delivery( - struct display_mode_lib *mode_lib, +static double get_refcyc_per_delivery(struct display_mode_lib *mode_lib, double refclk_freq_in_mhz, double pclk_freq_in_mhz, - int unsigned recout_width, + bool odm_combine, + unsigned int recout_width, + unsigned int hactive, double vratio, double hscale_pixel_rate, - int unsigned delivery_width, - int unsigned req_per_swath_ub) + unsigned int delivery_width, + unsigned int req_per_swath_ub) { double refcyc_per_delivery = 0.0; + if (vratio <= 1.0) { - refcyc_per_delivery = (double) refclk_freq_in_mhz * (double) recout_width - / pclk_freq_in_mhz / (double) req_per_swath_ub; + if (odm_combine) + refcyc_per_delivery = (double) refclk_freq_in_mhz + * dml_min((double) recout_width, (double) hactive / 2.0) + / pclk_freq_in_mhz / (double) req_per_swath_ub; + else + refcyc_per_delivery = (double) refclk_freq_in_mhz * (double) recout_width + / pclk_freq_in_mhz / (double) req_per_swath_ub; } else { refcyc_per_delivery = (double) refclk_freq_in_mhz * (double) delivery_width / (double) hscale_pixel_rate / (double) req_per_swath_ub; } - DTRACE("DLG: %s: refclk_freq_in_mhz = %3.2f", __func__, refclk_freq_in_mhz); - DTRACE("DLG: %s: pclk_freq_in_mhz = %3.2f", __func__, pclk_freq_in_mhz); - DTRACE("DLG: %s: recout_width = %d", __func__, recout_width); - DTRACE("DLG: %s: vratio = %3.2f", __func__, vratio); - DTRACE("DLG: %s: req_per_swath_ub = %d", __func__, req_per_swath_ub); - DTRACE("DLG: %s: refcyc_per_delivery= %3.2f", __func__, refcyc_per_delivery); + dml_print("DML_DLG: %s: refclk_freq_in_mhz = %3.2f\n", __func__, refclk_freq_in_mhz); + dml_print("DML_DLG: %s: pclk_freq_in_mhz = %3.2f\n", __func__, pclk_freq_in_mhz); + dml_print("DML_DLG: %s: recout_width = %d\n", __func__, recout_width); + dml_print("DML_DLG: %s: vratio = %3.2f\n", __func__, vratio); + dml_print("DML_DLG: %s: req_per_swath_ub = %d\n", __func__, req_per_swath_ub); + dml_print("DML_DLG: %s: refcyc_per_delivery= %3.2f\n", __func__, refcyc_per_delivery); return refcyc_per_delivery; } -static double get_vratio_pre( - struct display_mode_lib *mode_lib, - unsigned int max_num_sw, - unsigned int max_partial_sw, - unsigned int swath_height, - double vinit, - double l_sw) -{ - double prefill = dml_floor(vinit); - double vratio_pre = 1.0; - - vratio_pre = (max_num_sw * swath_height + max_partial_sw) / l_sw; - - if (swath_height > 4) { - double tmp0 = (max_num_sw * swath_height) / (l_sw - (prefill - 3.0) / 2.0); - if (tmp0 > vratio_pre) - vratio_pre = tmp0; - } - - DTRACE("DLG: %s: max_num_sw = %0d", __func__, max_num_sw); - DTRACE("DLG: %s: max_partial_sw = %0d", __func__, max_partial_sw); - DTRACE("DLG: %s: swath_height = %0d", __func__, swath_height); - DTRACE("DLG: %s: vinit = %3.2f", __func__, vinit); - DTRACE("DLG: %s: vratio_pre = %3.2f", __func__, vratio_pre); - - if (vratio_pre < 1.0) { - DTRACE("WARNING_DLG: %s: vratio_pre=%3.2f < 1.0, set to 1.0", __func__, vratio_pre); - vratio_pre = 1.0; - } - - if (vratio_pre > 4.0) { - DTRACE( - "WARNING_DLG: %s: vratio_pre=%3.2f > 4.0 (max scaling ratio). set to 4.0", - __func__, - vratio_pre); - vratio_pre = 4.0; - } - - return vratio_pre; -} - -static void get_swath_need( - struct display_mode_lib *mode_lib, - unsigned int *max_num_sw, - unsigned int *max_partial_sw, - unsigned int swath_height, - double vinit) -{ - double prefill = dml_floor(vinit); - unsigned int max_partial_sw_int; - - DTRACE("DLG: %s: swath_height = %0d", __func__, swath_height); - DTRACE("DLG: %s: vinit = %3.2f", __func__, vinit); - - ASSERT(prefill > 0.0 && prefill <= 8.0); - - *max_num_sw = (int unsigned) (dml_ceil((prefill - 1.0) / (double) swath_height) + 1.0); /* prefill has to be >= 1 */ - max_partial_sw_int = - (prefill == 1) ? - (swath_height - 1) : - ((int unsigned) (prefill - 2.0) % swath_height); - *max_partial_sw = (max_partial_sw_int < 1) ? 1 : max_partial_sw_int; /* ensure minimum of 1 is used */ - - DTRACE("DLG: %s: max_num_sw = %0d", __func__, *max_num_sw); - DTRACE("DLG: %s: max_partial_sw = %0d", __func__, *max_partial_sw); -} - static unsigned int get_blk_size_bytes(const enum source_macro_tile_size tile_size) { if (tile_size == dm_256k_tile) @@ -191,12 +127,11 @@ static unsigned int get_blk_size_bytes(const enum source_macro_tile_size tile_si return (4 * 1024); } -static void extract_rq_sizing_regs( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_data_rq_regs_st *rq_regs, - const struct _vcs_dpi_display_data_rq_sizing_params_st rq_sizing) +static void extract_rq_sizing_regs(struct display_mode_lib *mode_lib, + display_data_rq_regs_st *rq_regs, + const display_data_rq_sizing_params_st rq_sizing) { - DTRACE("DLG: %s: rq_sizing param", __func__); + dml_print("DML_DLG: %s: rq_sizing param\n", __func__); print__data_rq_sizing_params_st(mode_lib, rq_sizing); rq_regs->chunk_size = dml_log2(rq_sizing.chunk_bytes) - 10; @@ -216,25 +151,30 @@ static void extract_rq_sizing_regs( rq_regs->mpte_group_size = dml_log2(rq_sizing.mpte_group_bytes) - 6; } -void extract_rq_regs( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_regs_st *rq_regs, - const struct _vcs_dpi_display_rq_params_st rq_param) +static void extract_rq_regs(struct display_mode_lib *mode_lib, + display_rq_regs_st *rq_regs, + const display_rq_params_st rq_param) { unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; unsigned int detile_buf_plane1_addr = 0; extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), rq_param.sizing.rq_l); - if (rq_param.yuv420) + + rq_regs->rq_regs_l.pte_row_height_linear = dml_floor(dml_log2(rq_param.dlg.rq_l.dpte_row_height), + 1) - 3; + + if (rq_param.yuv420) { extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), rq_param.sizing.rq_c); + rq_regs->rq_regs_c.pte_row_height_linear = dml_floor(dml_log2(rq_param.dlg.rq_c.dpte_row_height), + 1) - 3; + } rq_regs->rq_regs_l.swath_height = dml_log2(rq_param.dlg.rq_l.swath_height); rq_regs->rq_regs_c.swath_height = dml_log2(rq_param.dlg.rq_c.swath_height); - /* FIXME: take the max between luma, chroma chunk size? - * okay for now, as we are setting chunk_bytes to 8kb anyways - */ - if (rq_param.sizing.rq_l.chunk_bytes >= 32 * 1024) { /*32kb */ + // FIXME: take the max between luma, chroma chunk size? + // okay for now, as we are setting chunk_bytes to 8kb anyways + if (rq_param.sizing.rq_l.chunk_bytes >= 32 * 1024) { //32kb rq_regs->drq_expansion_mode = 0; } else { rq_regs->drq_expansion_mode = 2; @@ -246,21 +186,19 @@ void extract_rq_regs( if (rq_param.yuv420) { if ((double) rq_param.misc.rq_l.stored_swath_bytes / (double) rq_param.misc.rq_c.stored_swath_bytes <= 1.5) { - detile_buf_plane1_addr = (detile_buf_size_in_bytes / 2.0 / 64.0); /* half to chroma */ + detile_buf_plane1_addr = (detile_buf_size_in_bytes / 2.0 / 64.0); // half to chroma } else { - detile_buf_plane1_addr = dml_round_to_multiple( - (unsigned int) ((2.0 * detile_buf_size_in_bytes) / 3.0), + detile_buf_plane1_addr = dml_round_to_multiple((unsigned int) ((2.0 * detile_buf_size_in_bytes) / 3.0), 256, - 0) / 64.0; /* 2/3 to chroma */ + 0) / 64.0; // 2/3 to chroma } } rq_regs->plane1_base_address = detile_buf_plane1_addr; } -static void handle_det_buf_split( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_params_st *rq_param, - const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param) +static void handle_det_buf_split(struct display_mode_lib *mode_lib, + display_rq_params_st *rq_param, + const display_pipe_source_params_st pipe_src_param) { unsigned int total_swath_bytes = 0; unsigned int swath_bytes_l = 0; @@ -279,12 +217,10 @@ static void handle_det_buf_split( full_swath_bytes_packed_c = rq_param->misc.rq_c.full_swath_bytes; if (rq_param->yuv420_10bpc) { - full_swath_bytes_packed_l = dml_round_to_multiple( - rq_param->misc.rq_l.full_swath_bytes * 2 / 3, + full_swath_bytes_packed_l = dml_round_to_multiple(rq_param->misc.rq_l.full_swath_bytes * 2 / 3, 256, 1) + 256; - full_swath_bytes_packed_c = dml_round_to_multiple( - rq_param->misc.rq_c.full_swath_bytes * 2 / 3, + full_swath_bytes_packed_c = dml_round_to_multiple(rq_param->misc.rq_c.full_swath_bytes * 2 / 3, 256, 1) + 256; } @@ -292,29 +228,19 @@ static void handle_det_buf_split( if (rq_param->yuv420) { total_swath_bytes = 2 * full_swath_bytes_packed_l + 2 * full_swath_bytes_packed_c; - if (total_swath_bytes <= detile_buf_size_in_bytes) { /*full 256b request */ + if (total_swath_bytes <= detile_buf_size_in_bytes) { //full 256b request req128_l = 0; req128_c = 0; swath_bytes_l = full_swath_bytes_packed_l; swath_bytes_c = full_swath_bytes_packed_c; - } else { /*128b request (for luma only for yuv420 8bpc) */ + } else { //128b request (for luma only for yuv420 8bpc) req128_l = 1; req128_c = 0; swath_bytes_l = full_swath_bytes_packed_l / 2; swath_bytes_c = full_swath_bytes_packed_c; } - - /* Bug workaround, luma and chroma req size needs to be the same. (see: DEGVIDCN10-137) - * TODO: Remove after rtl fix - */ - if (req128_l == 1) { - req128_c = 1; - DTRACE("DLG: %s: bug workaround DEGVIDCN10-137", __func__); - } - - /* Note: assumption, the config that pass in will fit into - * the detiled buffer. - */ + // Note: assumption, the config that pass in will fit into + // the detiled buffer. } else { total_swath_bytes = 2 * full_swath_bytes_packed_l; @@ -342,207 +268,47 @@ static void handle_det_buf_split( rq_param->dlg.rq_l.swath_height = 1 << log2_swath_height_l; rq_param->dlg.rq_c.swath_height = 1 << log2_swath_height_c; - DTRACE("DLG: %s: req128_l = %0d", __func__, req128_l); - DTRACE("DLG: %s: req128_c = %0d", __func__, req128_c); - DTRACE("DLG: %s: full_swath_bytes_packed_l = %0d", __func__, full_swath_bytes_packed_l); - DTRACE("DLG: %s: full_swath_bytes_packed_c = %0d", __func__, full_swath_bytes_packed_c); + dml_print("DML_DLG: %s: req128_l = %0d\n", __func__, req128_l); + dml_print("DML_DLG: %s: req128_c = %0d\n", __func__, req128_c); + dml_print("DML_DLG: %s: full_swath_bytes_packed_l = %0d\n", + __func__, + full_swath_bytes_packed_l); + dml_print("DML_DLG: %s: full_swath_bytes_packed_c = %0d\n", + __func__, + full_swath_bytes_packed_c); } -/* Need refactor. */ -void dml_rq_dlg_get_row_heights( - struct display_mode_lib *mode_lib, - unsigned int *o_dpte_row_height, - unsigned int *o_meta_row_height, +static void get_meta_and_pte_attr(struct display_mode_lib *mode_lib, + display_data_rq_dlg_params_st *rq_dlg_param, + display_data_rq_misc_params_st *rq_misc_param, + display_data_rq_sizing_params_st *rq_sizing_param, unsigned int vp_width, + unsigned int vp_height, unsigned int data_pitch, - int source_format, - int tiling, - int macro_tile_size, - int source_scan, - int is_chroma) + unsigned int meta_pitch, + unsigned int source_format, + unsigned int tiling, + unsigned int macro_tile_size, + unsigned int source_scan, + unsigned int is_chroma) { bool surf_linear = (tiling == dm_sw_linear); bool surf_vert = (source_scan == dm_vert); - unsigned int bytes_per_element = get_bytes_per_element( - (enum source_format_class) source_format, - is_chroma); - unsigned int log2_bytes_per_element = dml_log2(bytes_per_element); + unsigned int bytes_per_element; + unsigned int bytes_per_element_y = get_bytes_per_element((enum source_format_class)(source_format), + false); + unsigned int bytes_per_element_c = get_bytes_per_element((enum source_format_class)(source_format), + true); + unsigned int blk256_width = 0; unsigned int blk256_height = 0; - unsigned int log2_blk256_height; - unsigned int blk_bytes; - unsigned int log2_blk_bytes; - unsigned int log2_blk_height; - unsigned int log2_blk_width; - unsigned int log2_meta_req_bytes; - unsigned int log2_meta_req_height; - unsigned int log2_meta_req_width; - unsigned int log2_meta_row_height; - unsigned int log2_vmpg_bytes; - unsigned int dpte_buf_in_pte_reqs; - unsigned int log2_vmpg_height; - unsigned int log2_vmpg_width; - unsigned int log2_dpte_req_height_ptes; - unsigned int log2_dpte_req_width_ptes; - unsigned int log2_dpte_req_height; - unsigned int log2_dpte_req_width; - unsigned int log2_dpte_row_height_linear; - unsigned int log2_dpte_row_height; - unsigned int dpte_req_width; - - if (surf_linear) { - blk256_width = 256; - blk256_height = 1; - } else { - get_blk256_size(&blk256_width, &blk256_height, bytes_per_element); - } - - log2_blk256_height = dml_log2((double) blk256_height); - blk_bytes = surf_linear ? - 256 : get_blk_size_bytes((enum source_macro_tile_size) macro_tile_size); - log2_blk_bytes = dml_log2((double) blk_bytes); - log2_blk_height = 0; - log2_blk_width = 0; - - /* remember log rule - * "+" in log is multiply - * "-" in log is divide - * "/2" is like square root - * blk is vertical biased - */ - if (tiling != dm_sw_linear) - log2_blk_height = log2_blk256_height - + dml_ceil((double) (log2_blk_bytes - 8) / 2.0); - else - log2_blk_height = 0; /* blk height of 1 */ - - log2_blk_width = log2_blk_bytes - log2_bytes_per_element - log2_blk_height; - - /* ------- */ - /* meta */ - /* ------- */ - log2_meta_req_bytes = 6; /* meta request is 64b and is 8x8byte meta element */ - - /* each 64b meta request for dcn is 8x8 meta elements and - * a meta element covers one 256b block of the the data surface. - */ - log2_meta_req_height = log2_blk256_height + 3; /* meta req is 8x8 */ - log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element - - log2_meta_req_height; - log2_meta_row_height = 0; - - /* the dimensions of a meta row are meta_row_width x meta_row_height in elements. - * calculate upper bound of the meta_row_width - */ - if (!surf_vert) - log2_meta_row_height = log2_meta_req_height; - else - log2_meta_row_height = log2_meta_req_width; - - *o_meta_row_height = 1 << log2_meta_row_height; - - /* ------ */ - /* dpte */ - /* ------ */ - log2_vmpg_bytes = dml_log2(mode_lib->soc.vmm_page_size_bytes); - dpte_buf_in_pte_reqs = mode_lib->ip.dpte_buffer_size_in_pte_reqs; - - log2_vmpg_height = 0; - log2_vmpg_width = 0; - log2_dpte_req_height_ptes = 0; - log2_dpte_req_width_ptes = 0; - log2_dpte_req_height = 0; - log2_dpte_req_width = 0; - log2_dpte_row_height_linear = 0; - log2_dpte_row_height = 0; - dpte_req_width = 0; /* 64b dpte req width in data element */ - - if (surf_linear) { - log2_vmpg_height = 0; /* one line high */ - } else { - log2_vmpg_height = (log2_vmpg_bytes - 8) / 2 + log2_blk256_height; - } - log2_vmpg_width = log2_vmpg_bytes - log2_bytes_per_element - log2_vmpg_height; - - /* only 3 possible shapes for dpte request in dimensions of ptes: 8x1, 4x2, 2x4. */ - if (log2_blk_bytes <= log2_vmpg_bytes) - log2_dpte_req_height_ptes = 0; - else if (log2_blk_height - log2_vmpg_height >= 2) - log2_dpte_req_height_ptes = 2; - else - log2_dpte_req_height_ptes = log2_blk_height - log2_vmpg_height; - log2_dpte_req_width_ptes = 3 - log2_dpte_req_height_ptes; - - ASSERT((log2_dpte_req_width_ptes == 3 && log2_dpte_req_height_ptes == 0) || /* 8x1 */ - (log2_dpte_req_width_ptes == 2 && log2_dpte_req_height_ptes == 1) || /* 4x2 */ - (log2_dpte_req_width_ptes == 1 && log2_dpte_req_height_ptes == 2)); /* 2x4 */ - - /* the dpte request dimensions in data elements is dpte_req_width x dpte_req_height - * log2_wmpg_width is how much 1 pte represent, now trying to calculate how much 64b pte req represent - */ - log2_dpte_req_height = log2_vmpg_height + log2_dpte_req_height_ptes; - log2_dpte_req_width = log2_vmpg_width + log2_dpte_req_width_ptes; - dpte_req_width = 1 << log2_dpte_req_width; - - /* calculate pitch dpte row buffer can hold - * round the result down to a power of two. - */ - if (surf_linear) { - log2_dpte_row_height_linear = dml_floor( - dml_log2(dpte_buf_in_pte_reqs * dpte_req_width / data_pitch)); - - ASSERT(log2_dpte_row_height_linear >= 3); - - if (log2_dpte_row_height_linear > 7) - log2_dpte_row_height_linear = 7; - - log2_dpte_row_height = log2_dpte_row_height_linear; - } else { - /* the upper bound of the dpte_row_width without dependency on viewport position follows. */ - if (!surf_vert) { - log2_dpte_row_height = log2_dpte_req_height; - } else { - log2_dpte_row_height = - (log2_blk_width < log2_dpte_req_width) ? - log2_blk_width : log2_dpte_req_width; - } - } - - /* From programming guide: - * There is a special case of saving only half of ptes returned due to buffer space limits. - * this case applies to 4 and 8bpe in horizontal access of a vp_width greater than 2560+16 - * when the pte request is 2x4 ptes (which happens when vmpg_bytes =4kb and tile blk_bytes >=64kb). - */ - if (!surf_vert && vp_width > (2560 + 16) && bytes_per_element >= 4 && log2_vmpg_bytes == 12 - && log2_blk_bytes >= 16) { - log2_dpte_row_height = log2_dpte_row_height - 1; /*half of the full height */ - } - - *o_dpte_row_height = 1 << log2_dpte_row_height; -} - -static void get_surf_rq_param( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_data_rq_sizing_params_st *rq_sizing_param, - struct _vcs_dpi_display_data_rq_dlg_params_st *rq_dlg_param, - struct _vcs_dpi_display_data_rq_misc_params_st *rq_misc_param, - const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param, - bool is_chroma) -{ - bool mode_422 = 0; - unsigned int vp_width = 0; - unsigned int vp_height = 0; - unsigned int data_pitch = 0; - unsigned int meta_pitch = 0; - unsigned int ppe = mode_422 ? 2 : 1; - bool surf_linear; - bool surf_vert; - unsigned int bytes_per_element; + unsigned int blk256_width_y = 0; + unsigned int blk256_height_y = 0; + unsigned int blk256_width_c = 0; + unsigned int blk256_height_c = 0; unsigned int log2_bytes_per_element; - unsigned int blk256_width; - unsigned int blk256_height; unsigned int log2_blk256_width; unsigned int log2_blk256_height; unsigned int blk_bytes; @@ -558,6 +324,8 @@ static void get_surf_rq_param( unsigned int meta_row_width_ub; unsigned int log2_meta_chunk_bytes; unsigned int log2_meta_chunk_height; + + //full sized meta chunk width in unit of data elements unsigned int log2_meta_chunk_width; unsigned int log2_min_meta_chunk_bytes; unsigned int min_meta_chunk_width; @@ -572,93 +340,72 @@ static void get_surf_rq_param( unsigned int vmpg_bytes; unsigned int meta_pte_req_per_frame_ub; unsigned int meta_pte_bytes_per_frame_ub; - unsigned int log2_vmpg_bytes; - unsigned int dpte_buf_in_pte_reqs; - unsigned int log2_vmpg_height; - unsigned int log2_vmpg_width; - unsigned int log2_dpte_req_height_ptes; - unsigned int log2_dpte_req_width_ptes; - unsigned int log2_dpte_req_height; - unsigned int log2_dpte_req_width; - unsigned int log2_dpte_row_height_linear; - unsigned int log2_dpte_row_height; - unsigned int log2_dpte_group_width; - unsigned int dpte_row_width_ub; - unsigned int dpte_row_height; - unsigned int dpte_req_height; - unsigned int dpte_req_width; - unsigned int dpte_group_width; - unsigned int log2_dpte_group_bytes; - unsigned int log2_dpte_group_length; - unsigned int func_meta_row_height, func_dpte_row_height; - - /* FIXME check if ppe apply for both luma and chroma in 422 case */ - if (is_chroma) { - vp_width = pipe_src_param.viewport_width_c / ppe; - vp_height = pipe_src_param.viewport_height_c; - data_pitch = pipe_src_param.data_pitch_c; - meta_pitch = pipe_src_param.meta_pitch_c; + const unsigned int log2_vmpg_bytes = dml_log2(mode_lib->soc.vmm_page_size_bytes); + const unsigned int dpte_buf_in_pte_reqs = mode_lib->ip.dpte_buffer_size_in_pte_reqs; + const unsigned int pde_proc_buffer_size_64k_reqs = + mode_lib->ip.pde_proc_buffer_size_64k_reqs; + + unsigned int log2_vmpg_height = 0; + unsigned int log2_vmpg_width = 0; + unsigned int log2_dpte_req_height_ptes = 0; + unsigned int log2_dpte_req_height = 0; + unsigned int log2_dpte_req_width = 0; + unsigned int log2_dpte_row_height_linear = 0; + unsigned int log2_dpte_row_height = 0; + unsigned int log2_dpte_group_width = 0; + unsigned int dpte_row_width_ub = 0; + unsigned int dpte_req_height = 0; + unsigned int dpte_req_width = 0; + unsigned int dpte_group_width = 0; + unsigned int log2_dpte_group_bytes = 0; + unsigned int log2_dpte_group_length = 0; + unsigned int pde_buf_entries; + bool yuv420 = (source_format == dm_420_8 || source_format == dm_420_10); + + Calculate256BBlockSizes((enum source_format_class)(source_format), + (enum dm_swizzle_mode)(tiling), + bytes_per_element_y, + bytes_per_element_c, + &blk256_height_y, + &blk256_height_c, + &blk256_width_y, + &blk256_width_c); + + if (!is_chroma) { + blk256_width = blk256_width_y; + blk256_height = blk256_height_y; + bytes_per_element = bytes_per_element_y; } else { - vp_width = pipe_src_param.viewport_width / ppe; - vp_height = pipe_src_param.viewport_height; - data_pitch = pipe_src_param.data_pitch; - meta_pitch = pipe_src_param.meta_pitch; + blk256_width = blk256_width_c; + blk256_height = blk256_height_c; + bytes_per_element = bytes_per_element_c; } - rq_sizing_param->chunk_bytes = 8192; - - if (rq_sizing_param->chunk_bytes == 64 * 1024) - rq_sizing_param->min_chunk_bytes = 0; - else - rq_sizing_param->min_chunk_bytes = 1024; - - rq_sizing_param->meta_chunk_bytes = 2048; - rq_sizing_param->min_meta_chunk_bytes = 256; - - rq_sizing_param->mpte_group_bytes = 2048; - - surf_linear = (pipe_src_param.sw_mode == dm_sw_linear); - surf_vert = (pipe_src_param.source_scan == dm_vert); - - bytes_per_element = get_bytes_per_element( - (enum source_format_class) pipe_src_param.source_format, - is_chroma); log2_bytes_per_element = dml_log2(bytes_per_element); - blk256_width = 0; - blk256_height = 0; - if (surf_linear) { - blk256_width = 256 / bytes_per_element; - blk256_height = 1; - } else { - get_blk256_size(&blk256_width, &blk256_height, bytes_per_element); - } - - DTRACE("DLG: %s: surf_linear = %d", __func__, surf_linear); - DTRACE("DLG: %s: surf_vert = %d", __func__, surf_vert); - DTRACE("DLG: %s: blk256_width = %d", __func__, blk256_width); - DTRACE("DLG: %s: blk256_height = %d", __func__, blk256_height); + dml_print("DML_DLG: %s: surf_linear = %d\n", __func__, surf_linear); + dml_print("DML_DLG: %s: surf_vert = %d\n", __func__, surf_vert); + dml_print("DML_DLG: %s: blk256_width = %d\n", __func__, blk256_width); + dml_print("DML_DLG: %s: blk256_height = %d\n", __func__, blk256_height); log2_blk256_width = dml_log2((double) blk256_width); log2_blk256_height = dml_log2((double) blk256_height); - blk_bytes = - surf_linear ? 256 : get_blk_size_bytes( - (enum source_macro_tile_size) pipe_src_param.macro_tile_size); + blk_bytes = surf_linear ? + 256 : get_blk_size_bytes((enum source_macro_tile_size) macro_tile_size); log2_blk_bytes = dml_log2((double) blk_bytes); log2_blk_height = 0; log2_blk_width = 0; - /* remember log rule - * "+" in log is multiply - * "-" in log is divide - * "/2" is like square root - * blk is vertical biased - */ - if (pipe_src_param.sw_mode != dm_sw_linear) + // remember log rule + // "+" in log is multiply + // "-" in log is divide + // "/2" is like square root + // blk is vertical biased + if (tiling != dm_sw_linear) log2_blk_height = log2_blk256_height - + dml_ceil((double) (log2_blk_bytes - 8) / 2.0); + + dml_ceil((double) (log2_blk_bytes - 8) / 2.0, 1); else - log2_blk_height = 0; /* blk height of 1 */ + log2_blk_height = 0; // blk height of 1 log2_blk_width = log2_blk_bytes - log2_bytes_per_element - log2_blk_height; @@ -667,10 +414,8 @@ static void get_surf_rq_param( + blk256_width; rq_dlg_param->req_per_swath_ub = rq_dlg_param->swath_width_ub >> log2_blk256_width; } else { - rq_dlg_param->swath_width_ub = dml_round_to_multiple( - vp_height - 1, - blk256_height, - 1) + blk256_height; + rq_dlg_param->swath_width_ub = dml_round_to_multiple(vp_height - 1, blk256_height, 1) + + blk256_height; rq_dlg_param->req_per_swath_ub = rq_dlg_param->swath_width_ub >> log2_blk256_height; } @@ -684,15 +429,14 @@ static void get_surf_rq_param( rq_misc_param->blk256_height = blk256_height; rq_misc_param->blk256_width = blk256_width; - /* ------- */ - /* meta */ - /* ------- */ - log2_meta_req_bytes = 6; /* meta request is 64b and is 8x8byte meta element */ + // ------- + // meta + // ------- + log2_meta_req_bytes = 6; // meta request is 64b and is 8x8byte meta element - /* each 64b meta request for dcn is 8x8 meta elements and - * a meta element covers one 256b block of the the data surface. - */ - log2_meta_req_height = log2_blk256_height + 3; /* meta req is 8x8 byte, each byte represent 1 blk256 */ + // each 64b meta request for dcn is 8x8 meta elements and + // a meta element covers one 256b block of the the data surface. + log2_meta_req_height = log2_blk256_height + 3; // meta req is 8x8 byte, each byte represent 1 blk256 log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element - log2_meta_req_height; meta_req_width = 1 << log2_meta_req_width; @@ -700,9 +444,8 @@ static void get_surf_rq_param( log2_meta_row_height = 0; meta_row_width_ub = 0; - /* the dimensions of a meta row are meta_row_width x meta_row_height in elements. - * calculate upper bound of the meta_row_width - */ + // the dimensions of a meta row are meta_row_width x meta_row_height in elements. + // calculate upper bound of the meta_row_width if (!surf_vert) { log2_meta_row_height = log2_meta_req_height; meta_row_width_ub = dml_round_to_multiple(vp_width - 1, meta_req_width, 1) @@ -716,10 +459,12 @@ static void get_surf_rq_param( } rq_dlg_param->meta_bytes_per_row_ub = rq_dlg_param->meta_req_per_row_ub * 64; + rq_dlg_param->meta_row_height = 1 << log2_meta_row_height; + log2_meta_chunk_bytes = dml_log2(rq_sizing_param->meta_chunk_bytes); log2_meta_chunk_height = log2_meta_row_height; - /*full sized meta chunk width in unit of data elements */ + //full sized meta chunk width in unit of data elements log2_meta_chunk_width = log2_meta_chunk_bytes + 8 - log2_bytes_per_element - log2_meta_chunk_height; log2_min_meta_chunk_bytes = dml_log2(rq_sizing_param->min_meta_chunk_bytes); @@ -734,21 +479,24 @@ static void get_surf_rq_param( meta_blk_height = blk256_height * 64; meta_blk_width = meta_blk_bytes * 256 / bytes_per_element / meta_blk_height; meta_surface_bytes = meta_pitch - * (dml_round_to_multiple(vp_height - 1, meta_blk_height, 1) - + meta_blk_height) * bytes_per_element / 256; + * (dml_round_to_multiple(vp_height - 1, meta_blk_height, 1) + meta_blk_height) + * bytes_per_element / 256; vmpg_bytes = mode_lib->soc.vmm_page_size_bytes; - meta_pte_req_per_frame_ub = (dml_round_to_multiple( - meta_surface_bytes - vmpg_bytes, + meta_pte_req_per_frame_ub = (dml_round_to_multiple(meta_surface_bytes - vmpg_bytes, 8 * vmpg_bytes, 1) + 8 * vmpg_bytes) / (8 * vmpg_bytes); - meta_pte_bytes_per_frame_ub = meta_pte_req_per_frame_ub * 64; /*64B mpte request */ + meta_pte_bytes_per_frame_ub = meta_pte_req_per_frame_ub * 64; //64B mpte request rq_dlg_param->meta_pte_bytes_per_frame_ub = meta_pte_bytes_per_frame_ub; - DTRACE("DLG: %s: meta_blk_height = %d", __func__, meta_blk_height); - DTRACE("DLG: %s: meta_blk_width = %d", __func__, meta_blk_width); - DTRACE("DLG: %s: meta_surface_bytes = %d", __func__, meta_surface_bytes); - DTRACE("DLG: %s: meta_pte_req_per_frame_ub = %d", __func__, meta_pte_req_per_frame_ub); - DTRACE("DLG: %s: meta_pte_bytes_per_frame_ub = %d", __func__, meta_pte_bytes_per_frame_ub); + dml_print("DML_DLG: %s: meta_blk_height = %d\n", __func__, meta_blk_height); + dml_print("DML_DLG: %s: meta_blk_width = %d\n", __func__, meta_blk_width); + dml_print("DML_DLG: %s: meta_surface_bytes = %d\n", __func__, meta_surface_bytes); + dml_print("DML_DLG: %s: meta_pte_req_per_frame_ub = %d\n", + __func__, + meta_pte_req_per_frame_ub); + dml_print("DML_DLG: %s: meta_pte_bytes_per_frame_ub = %d\n", + __func__, + meta_pte_bytes_per_frame_ub); if (!surf_vert) meta_chunk_threshold = 2 * min_meta_chunk_width - meta_req_width; @@ -760,67 +508,58 @@ static void get_surf_rq_param( else rq_dlg_param->meta_chunks_per_row_ub = meta_chunk_per_row_int + 2; - rq_dlg_param->meta_row_height = 1 << log2_meta_row_height; - - /* ------ */ - /* dpte */ - /* ------ */ - log2_vmpg_bytes = dml_log2(mode_lib->soc.vmm_page_size_bytes); - dpte_buf_in_pte_reqs = mode_lib->ip.dpte_buffer_size_in_pte_reqs; - - log2_vmpg_height = 0; - log2_vmpg_width = 0; - log2_dpte_req_height_ptes = 0; - log2_dpte_req_width_ptes = 0; - log2_dpte_req_height = 0; - log2_dpte_req_width = 0; - log2_dpte_row_height_linear = 0; - log2_dpte_row_height = 0; - log2_dpte_group_width = 0; - dpte_row_width_ub = 0; - dpte_row_height = 0; - dpte_req_height = 0; /* 64b dpte req height in data element */ - dpte_req_width = 0; /* 64b dpte req width in data element */ - dpte_group_width = 0; - log2_dpte_group_bytes = 0; - log2_dpte_group_length = 0; - + // ------ + // dpte + // ------ if (surf_linear) { - log2_vmpg_height = 0; /* one line high */ + log2_vmpg_height = 0; // one line high } else { log2_vmpg_height = (log2_vmpg_bytes - 8) / 2 + log2_blk256_height; } log2_vmpg_width = log2_vmpg_bytes - log2_bytes_per_element - log2_vmpg_height; - /* only 3 possible shapes for dpte request in dimensions of ptes: 8x1, 4x2, 2x4. */ - if (log2_blk_bytes <= log2_vmpg_bytes) + // only 3 possible shapes for dpte request in dimensions of ptes: 8x1, 4x2, 2x4. + if (surf_linear) { //one 64B PTE request returns 8 PTEs log2_dpte_req_height_ptes = 0; - else if (log2_blk_height - log2_vmpg_height >= 2) - log2_dpte_req_height_ptes = 2; - else - log2_dpte_req_height_ptes = log2_blk_height - log2_vmpg_height; - log2_dpte_req_width_ptes = 3 - log2_dpte_req_height_ptes; - - /* Ensure we only have the 3 shapes */ - ASSERT((log2_dpte_req_width_ptes == 3 && log2_dpte_req_height_ptes == 0) || /* 8x1 */ - (log2_dpte_req_width_ptes == 2 && log2_dpte_req_height_ptes == 1) || /* 4x2 */ - (log2_dpte_req_width_ptes == 1 && log2_dpte_req_height_ptes == 2)); /* 2x4 */ - - /* The dpte request dimensions in data elements is dpte_req_width x dpte_req_height - * log2_vmpg_width is how much 1 pte represent, now calculating how much a 64b pte req represent - * That depends on the pte shape (i.e. 8x1, 4x2, 2x4) - */ - log2_dpte_req_height = log2_vmpg_height + log2_dpte_req_height_ptes; - log2_dpte_req_width = log2_vmpg_width + log2_dpte_req_width_ptes; + log2_dpte_req_width = log2_vmpg_width + 3; + log2_dpte_req_height = 0; + } else if (log2_blk_bytes == 12) { //4KB tile means 4kB page size + //one 64B req gives 8x1 PTEs for 4KB tile + log2_dpte_req_height_ptes = 0; + log2_dpte_req_width = log2_blk_width + 3; + log2_dpte_req_height = log2_blk_height + 0; + } else if ((log2_blk_bytes >= 16) && (log2_vmpg_bytes == 12)) { // tile block >= 64KB + //two 64B reqs of 2x4 PTEs give 16 PTEs to cover 64KB + log2_dpte_req_height_ptes = 4; + log2_dpte_req_width = log2_blk256_width + 4; // log2_64KB_width + log2_dpte_req_height = log2_blk256_height + 4; // log2_64KB_height + } else { //64KB page size and must 64KB tile block + //one 64B req gives 8x1 PTEs for 64KB tile + log2_dpte_req_height_ptes = 0; + log2_dpte_req_width = log2_blk_width + 3; + log2_dpte_req_height = log2_blk_height + 0; + } + + // The dpte request dimensions in data elements is dpte_req_width x dpte_req_height + // log2_vmpg_width is how much 1 pte represent, now calculating how much a 64b pte req represent + // That depends on the pte shape (i.e. 8x1, 4x2, 2x4) + //log2_dpte_req_height = log2_vmpg_height + log2_dpte_req_height_ptes; + //log2_dpte_req_width = log2_vmpg_width + log2_dpte_req_width_ptes; dpte_req_height = 1 << log2_dpte_req_height; dpte_req_width = 1 << log2_dpte_req_width; - /* calculate pitch dpte row buffer can hold - * round the result down to a power of two. - */ + // calculate pitch dpte row buffer can hold + // round the result down to a power of two. + pde_buf_entries = yuv420 ? (pde_proc_buffer_size_64k_reqs >> 1) : pde_proc_buffer_size_64k_reqs; if (surf_linear) { - log2_dpte_row_height_linear = dml_floor( - dml_log2(dpte_buf_in_pte_reqs * dpte_req_width / data_pitch)); + unsigned int dpte_row_height; + + log2_dpte_row_height_linear = dml_floor(dml_log2(dml_min(64 * 1024 * pde_buf_entries + / bytes_per_element, + dpte_buf_in_pte_reqs + * dpte_req_width) + / data_pitch), + 1); ASSERT(log2_dpte_row_height_linear >= 3); @@ -828,18 +567,16 @@ static void get_surf_rq_param( log2_dpte_row_height_linear = 7; log2_dpte_row_height = log2_dpte_row_height_linear; - rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height; - - /* For linear, the dpte row is pitch dependent and the pte requests wrap at the pitch boundary. - * the dpte_row_width_ub is the upper bound of data_pitch*dpte_row_height in elements with this unique buffering. - */ - dpte_row_width_ub = dml_round_to_multiple( - data_pitch * dpte_row_height - 1, + // For linear, the dpte row is pitch dependent and the pte requests wrap at the pitch boundary. + // the dpte_row_width_ub is the upper bound of data_pitch*dpte_row_height in elements with this unique buffering. + dpte_row_height = 1 << log2_dpte_row_height; + dpte_row_width_ub = dml_round_to_multiple(data_pitch * dpte_row_height - 1, dpte_req_width, 1) + dpte_req_width; rq_dlg_param->dpte_req_per_row_ub = dpte_row_width_ub / dpte_req_width; } else { - /* for tiled mode, row height is the same as req height and row store up to vp size upper bound */ + // the upper bound of the dpte_row_width without dependency on viewport position follows. + // for tiled mode, row height is the same as req height and row store up to vp size upper bound if (!surf_vert) { log2_dpte_row_height = log2_dpte_req_height; dpte_row_width_ub = dml_round_to_multiple(vp_width - 1, dpte_req_width, 1) @@ -853,103 +590,117 @@ static void get_surf_rq_param( + dpte_req_height; rq_dlg_param->dpte_req_per_row_ub = dpte_row_width_ub / dpte_req_height; } - rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height; - } - rq_dlg_param->dpte_bytes_per_row_ub = rq_dlg_param->dpte_req_per_row_ub * 64; - - /* From programming guide: - * There is a special case of saving only half of ptes returned due to buffer space limits. - * this case applies to 4 and 8bpe in horizontal access of a vp_width greater than 2560+16 - * when the pte request is 2x4 ptes (which happens when vmpg_bytes =4kb and tile blk_bytes >=64kb). - */ - if (!surf_vert && vp_width > (2560 + 16) && bytes_per_element >= 4 && log2_vmpg_bytes == 12 - && log2_blk_bytes >= 16) { - log2_dpte_row_height = log2_dpte_row_height - 1; /*half of the full height */ - rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height; } + if (log2_blk_bytes >= 16 && log2_vmpg_bytes == 12) // tile block >= 64KB + rq_dlg_param->dpte_bytes_per_row_ub = rq_dlg_param->dpte_req_per_row_ub * 128; //2*64B dpte request + else + rq_dlg_param->dpte_bytes_per_row_ub = rq_dlg_param->dpte_req_per_row_ub * 64; //64B dpte request + + rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height; - /* the dpte_group_bytes is reduced for the specific case of vertical - * access of a tile surface that has dpte request of 8x1 ptes. - */ - if (!surf_linear & (log2_dpte_req_height_ptes == 0) & surf_vert) /*reduced, in this case, will have page fault within a group */ + // the dpte_group_bytes is reduced for the specific case of vertical + // access of a tile surface that has dpte request of 8x1 ptes. + if (!surf_linear & (log2_dpte_req_height_ptes == 0) & surf_vert) //reduced, in this case, will have page fault within a group rq_sizing_param->dpte_group_bytes = 512; else - /*full size */ + //full size rq_sizing_param->dpte_group_bytes = 2048; - /*since pte request size is 64byte, the number of data pte requests per full sized group is as follows. */ + //since pte request size is 64byte, the number of data pte requests per full sized group is as follows. log2_dpte_group_bytes = dml_log2(rq_sizing_param->dpte_group_bytes); - log2_dpte_group_length = log2_dpte_group_bytes - 6; /*length in 64b requests */ + log2_dpte_group_length = log2_dpte_group_bytes - 6; //length in 64b requests - /* full sized data pte group width in elements */ + // full sized data pte group width in elements if (!surf_vert) log2_dpte_group_width = log2_dpte_group_length + log2_dpte_req_width; else log2_dpte_group_width = log2_dpte_group_length + log2_dpte_req_height; + //But if the tile block >=64KB and the page size is 4KB, then each dPTE request is 2*64B + if ((log2_blk_bytes >= 16) && (log2_vmpg_bytes == 12)) // tile block >= 64KB + log2_dpte_group_width = log2_dpte_group_width - 1; + dpte_group_width = 1 << log2_dpte_group_width; - /* since dpte groups are only aligned to dpte_req_width and not dpte_group_width, - * the upper bound for the dpte groups per row is as follows. - */ - rq_dlg_param->dpte_groups_per_row_ub = dml_ceil( - (double) dpte_row_width_ub / dpte_group_width); + // since dpte groups are only aligned to dpte_req_width and not dpte_group_width, + // the upper bound for the dpte groups per row is as follows. + rq_dlg_param->dpte_groups_per_row_ub = dml_ceil((double) dpte_row_width_ub / dpte_group_width, + 1); +} + +static void get_surf_rq_param(struct display_mode_lib *mode_lib, + display_data_rq_sizing_params_st *rq_sizing_param, + display_data_rq_dlg_params_st *rq_dlg_param, + display_data_rq_misc_params_st *rq_misc_param, + const display_pipe_source_params_st pipe_src_param, + bool is_chroma) +{ + bool mode_422 = 0; + unsigned int vp_width = 0; + unsigned int vp_height = 0; + unsigned int data_pitch = 0; + unsigned int meta_pitch = 0; + unsigned int ppe = mode_422 ? 2 : 1; + + // FIXME check if ppe apply for both luma and chroma in 422 case + if (is_chroma) { + vp_width = pipe_src_param.viewport_width_c / ppe; + vp_height = pipe_src_param.viewport_height_c; + data_pitch = pipe_src_param.data_pitch_c; + meta_pitch = pipe_src_param.meta_pitch_c; + } else { + vp_width = pipe_src_param.viewport_width / ppe; + vp_height = pipe_src_param.viewport_height; + data_pitch = pipe_src_param.data_pitch; + meta_pitch = pipe_src_param.meta_pitch; + } + + rq_sizing_param->chunk_bytes = 8192; + + if (rq_sizing_param->chunk_bytes == 64 * 1024) + rq_sizing_param->min_chunk_bytes = 0; + else + rq_sizing_param->min_chunk_bytes = 1024; + + rq_sizing_param->meta_chunk_bytes = 2048; + rq_sizing_param->min_meta_chunk_bytes = 256; - dml_rq_dlg_get_row_heights( - mode_lib, - &func_dpte_row_height, - &func_meta_row_height, + rq_sizing_param->mpte_group_bytes = 2048; + + get_meta_and_pte_attr(mode_lib, + rq_dlg_param, + rq_misc_param, + rq_sizing_param, vp_width, + vp_height, data_pitch, + meta_pitch, pipe_src_param.source_format, pipe_src_param.sw_mode, pipe_src_param.macro_tile_size, pipe_src_param.source_scan, is_chroma); - - /* Just a check to make sure this function and the new one give the same - * result. The standalone get_row_heights() function is based off of the - * code in this function so the same changes need to be made to both. - */ - if (rq_dlg_param->meta_row_height != func_meta_row_height) { - DTRACE( - "MISMATCH: rq_dlg_param->meta_row_height = %d", - rq_dlg_param->meta_row_height); - DTRACE("MISMATCH: func_meta_row_height = %d", func_meta_row_height); - ASSERT(0); - } - - if (rq_dlg_param->dpte_row_height != func_dpte_row_height) { - DTRACE( - "MISMATCH: rq_dlg_param->dpte_row_height = %d", - rq_dlg_param->dpte_row_height); - DTRACE("MISMATCH: func_dpte_row_height = %d", func_dpte_row_height); - ASSERT(0); - } } -void dml_rq_dlg_get_rq_params( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_params_st *rq_param, - const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param) +void dml_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, + display_rq_params_st *rq_param, + const display_pipe_source_params_st pipe_src_param) { - /* get param for luma surface */ + // get param for luma surface rq_param->yuv420 = pipe_src_param.source_format == dm_420_8 || pipe_src_param.source_format == dm_420_10; rq_param->yuv420_10bpc = pipe_src_param.source_format == dm_420_10; - get_surf_rq_param( - mode_lib, + get_surf_rq_param(mode_lib, &(rq_param->sizing.rq_l), &(rq_param->dlg.rq_l), &(rq_param->misc.rq_l), pipe_src_param, 0); - if (is_dual_plane((enum source_format_class) pipe_src_param.source_format)) { - /* get param for chroma surface */ - get_surf_rq_param( - mode_lib, + if (is_dual_plane((enum source_format_class)(pipe_src_param.source_format))) { + // get param for chroma surface + get_surf_rq_param(mode_lib, &(rq_param->sizing.rq_c), &(rq_param->dlg.rq_c), &(rq_param->misc.rq_c), @@ -957,355 +708,126 @@ void dml_rq_dlg_get_rq_params( 1); } - /* calculate how to split the det buffer space between luma and chroma */ + // calculate how to split the det buffer space between luma and chroma handle_det_buf_split(mode_lib, rq_param, pipe_src_param); print__rq_params_st(mode_lib, *rq_param); } -void dml_rq_dlg_get_rq_reg( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_regs_st *rq_regs, - const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param) +void dml_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, + display_rq_regs_st *rq_regs, + const display_pipe_source_params_st pipe_src_param) { - struct _vcs_dpi_display_rq_params_st rq_param = {0}; + display_rq_params_st rq_param = {0}; memset(rq_regs, 0, sizeof(*rq_regs)); - dml_rq_dlg_get_rq_params(mode_lib, &rq_param, pipe_src_param); extract_rq_regs(mode_lib, rq_regs, rq_param); print__rq_regs_st(mode_lib, *rq_regs); } -/* TODO: Need refactor, so this is used by dml_rq_dlg_get_dlg_params as well - * The problem is that there are some intermediate terms that would need by - * some dlg calculation (i.e. rest of prefetch and active prog guide calculation) - */ -void dml_rq_dlg_get_dlg_params_prefetch( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_dlg_prefetch_param_st *prefetch_param, - struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param, - struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param, - struct _vcs_dpi_display_e2e_pipe_params_st e2e_pipe_param, - const bool cstate_en, - const bool pstate_en, - const bool vm_en) -{ - /* Prefetch */ - unsigned int htotal = e2e_pipe_param.pipe.dest.htotal; - bool interlaced = e2e_pipe_param.pipe.dest.interlaced; - unsigned int min_vblank = mode_lib->ip.min_vblank_lines; - const double prefetch_xy_calc_in_dcfclk = 24.0; /* FIXME: ip_param */ - double min_dcfclk_mhz = dlg_sys_param.deepsleep_dcfclk_mhz; - double t_calc_us = prefetch_xy_calc_in_dcfclk / min_dcfclk_mhz; - - bool dcc_en = e2e_pipe_param.pipe.src.dcc; - bool dual_plane = is_dual_plane( - (enum source_format_class) e2e_pipe_param.pipe.src.source_format); - unsigned int bytes_per_element_l = get_bytes_per_element( - (enum source_format_class) e2e_pipe_param.pipe.src.source_format, - 0); - unsigned int bytes_per_element_c = get_bytes_per_element( - (enum source_format_class) e2e_pipe_param.pipe.src.source_format, - 1); - - double pclk_freq_in_mhz = e2e_pipe_param.pipe.dest.pixel_rate_mhz; - double dppclk_freq_in_mhz = e2e_pipe_param.clks_cfg.dppclk_mhz; - double dispclk_freq_in_mhz = e2e_pipe_param.clks_cfg.dispclk_mhz; - - double line_time_in_us = (htotal / pclk_freq_in_mhz); - double vinit_l = e2e_pipe_param.pipe.scale_ratio_depth.vinit; - double vinit_c = e2e_pipe_param.pipe.scale_ratio_depth.vinit_c; - double vinit_bot_l = e2e_pipe_param.pipe.scale_ratio_depth.vinit_bot; - double vinit_bot_c = e2e_pipe_param.pipe.scale_ratio_depth.vinit_bot_c; - - unsigned int swath_height_l = rq_dlg_param.rq_l.swath_height; - unsigned int swath_width_ub_l = rq_dlg_param.rq_l.swath_width_ub; - unsigned int dpte_bytes_per_row_ub_l = rq_dlg_param.rq_l.dpte_bytes_per_row_ub; - unsigned int meta_pte_bytes_per_frame_ub_l = rq_dlg_param.rq_l.meta_pte_bytes_per_frame_ub; - unsigned int meta_bytes_per_row_ub_l = rq_dlg_param.rq_l.meta_bytes_per_row_ub; - - unsigned int swath_height_c = rq_dlg_param.rq_c.swath_height; - unsigned int swath_width_ub_c = rq_dlg_param.rq_c.swath_width_ub; - unsigned int dpte_bytes_per_row_ub_c = rq_dlg_param.rq_c.dpte_bytes_per_row_ub; - unsigned int vupdate_offset = e2e_pipe_param.pipe.dest.vupdate_offset; - unsigned int vupdate_width = e2e_pipe_param.pipe.dest.vupdate_width; - unsigned int vready_offset = e2e_pipe_param.pipe.dest.vready_offset; - - const unsigned int dppclk_delay_subtotal = mode_lib->ip.dppclk_delay_subtotal; - const unsigned int dispclk_delay_subtotal = mode_lib->ip.dispclk_delay_subtotal; - unsigned int pixel_rate_delay_subtotal = dppclk_delay_subtotal * pclk_freq_in_mhz - / dppclk_freq_in_mhz - + dispclk_delay_subtotal * pclk_freq_in_mhz / dispclk_freq_in_mhz; - unsigned int dst_y_after_scaler = 0; - unsigned int dst_x_after_scaler = 0; - - unsigned int vstartup_start = e2e_pipe_param.pipe.dest.vstartup_start; - - double line_wait; - double line_o; - double line_setup; - double line_calc; - double dst_y_prefetch; - double t_pre_us; - int unsigned vm_bytes; - int unsigned meta_row_bytes; - int unsigned max_num_sw_l; - int unsigned max_num_sw_c; - int unsigned max_partial_sw_l; - int unsigned max_partial_sw_c; - - double max_vinit_l; - double max_vinit_c; - int unsigned lsw_l; - int unsigned lsw_c; - int unsigned sw_bytes_ub_l; - int unsigned sw_bytes_ub_c; - int unsigned sw_bytes; - int unsigned dpte_row_bytes; - - if (interlaced) - vstartup_start = vstartup_start / 2; - - if (vstartup_start >= min_vblank) { - min_vblank = vstartup_start + 1; - DTRACE( - "WARNING_DLG: %s: vstartup_start=%d should be less than min_vblank=%d", - __func__, - vstartup_start, - min_vblank); - } - - if (e2e_pipe_param.pipe.src.is_hsplit) - dst_x_after_scaler = pixel_rate_delay_subtotal - + e2e_pipe_param.pipe.dest.recout_width; - else - dst_x_after_scaler = pixel_rate_delay_subtotal; - - if (e2e_pipe_param.dout.output_format == dm_420) - dst_y_after_scaler = 1; - else - dst_y_after_scaler = 0; - - if (dst_x_after_scaler >= htotal) { - dst_x_after_scaler = dst_x_after_scaler - htotal; - dst_y_after_scaler = dst_y_after_scaler + 1; - } - - DTRACE("DLG: %s: htotal = %d", __func__, htotal); - DTRACE( - "DLG: %s: pixel_rate_delay_subtotal = %d", - __func__, - pixel_rate_delay_subtotal); - DTRACE("DLG: %s: dst_x_after_scaler = %d", __func__, dst_x_after_scaler); - DTRACE("DLG: %s: dst_y_after_scaler = %d", __func__, dst_y_after_scaler); - - line_wait = mode_lib->soc.urgent_latency_us; - if (cstate_en) - line_wait = dml_max(mode_lib->soc.sr_enter_plus_exit_time_us, line_wait); - if (pstate_en) - line_wait = dml_max( - mode_lib->soc.dram_clock_change_latency_us - + mode_lib->soc.urgent_latency_us, - line_wait); - line_wait = line_wait / line_time_in_us; - - line_o = (double) dst_y_after_scaler + dst_x_after_scaler / (double) htotal; - line_setup = (double) (vupdate_offset + vupdate_width + vready_offset) / (double) htotal; - line_calc = t_calc_us / line_time_in_us; - - DTRACE( - "DLG: %s: soc.sr_enter_plus_exit_time_us = %3.2f", - __func__, - (double) mode_lib->soc.sr_enter_plus_exit_time_us); - DTRACE( - "DLG: %s: soc.dram_clock_change_latency_us = %3.2f", - __func__, - (double) mode_lib->soc.dram_clock_change_latency_us); - - DTRACE("DLG: %s: urgent_latency_us = %3.2f", __func__, mode_lib->soc.urgent_latency_us); - DTRACE( - "DLG: %s: t_srx_delay_us = %3.2f", - __func__, - (double) dlg_sys_param.t_srx_delay_us); - DTRACE("DLG: %s: line_time_in_us = %3.2f", __func__, (double) line_time_in_us); - DTRACE("DLG: %s: vupdate_offset = %d", __func__, vupdate_offset); - DTRACE("DLG: %s: vupdate_width = %d", __func__, vupdate_width); - DTRACE("DLG: %s: vready_offset = %d", __func__, vready_offset); - DTRACE("DLG: %s: line_wait = %3.2f", __func__, line_wait); - DTRACE("DLG: %s: line_o = %3.2f", __func__, line_o); - DTRACE("DLG: %s: line_setup = %3.2f", __func__, line_setup); - DTRACE("DLG: %s: line_calc = %3.2f", __func__, line_calc); - - dst_y_prefetch = ((double) min_vblank - 1.0) - - (line_setup + line_calc + line_wait + line_o); - DTRACE("DLG: %s: dst_y_prefetch (before rnd) = %3.2f", __func__, dst_y_prefetch); - ASSERT(dst_y_prefetch >= 2.0); - - dst_y_prefetch = dml_floor(4.0 * (dst_y_prefetch + 0.125)) / 4; - DTRACE("DLG: %s: dst_y_prefetch (after rnd) = %3.2f", __func__, dst_y_prefetch); - - t_pre_us = dst_y_prefetch * line_time_in_us; - vm_bytes = 0; - meta_row_bytes = 0; - - if (dcc_en && vm_en) - vm_bytes = meta_pte_bytes_per_frame_ub_l; - if (dcc_en) - meta_row_bytes = meta_bytes_per_row_ub_l; - - max_num_sw_l = 0; - max_num_sw_c = 0; - max_partial_sw_l = 0; - max_partial_sw_c = 0; - - max_vinit_l = interlaced ? dml_max(vinit_l, vinit_bot_l) : vinit_l; - max_vinit_c = interlaced ? dml_max(vinit_c, vinit_bot_c) : vinit_c; - - get_swath_need(mode_lib, &max_num_sw_l, &max_partial_sw_l, swath_height_l, max_vinit_l); - if (dual_plane) - get_swath_need( - mode_lib, - &max_num_sw_c, - &max_partial_sw_c, - swath_height_c, - max_vinit_c); - - lsw_l = max_num_sw_l * swath_height_l + max_partial_sw_l; - lsw_c = max_num_sw_c * swath_height_c + max_partial_sw_c; - sw_bytes_ub_l = lsw_l * swath_width_ub_l * bytes_per_element_l; - sw_bytes_ub_c = lsw_c * swath_width_ub_c * bytes_per_element_c; - sw_bytes = 0; - dpte_row_bytes = 0; - - if (vm_en) { - if (dual_plane) - dpte_row_bytes = dpte_bytes_per_row_ub_l + dpte_bytes_per_row_ub_c; - else - dpte_row_bytes = dpte_bytes_per_row_ub_l; - } else { - dpte_row_bytes = 0; - } - - if (dual_plane) - sw_bytes = sw_bytes_ub_l + sw_bytes_ub_c; - else - sw_bytes = sw_bytes_ub_l; - - DTRACE("DLG: %s: sw_bytes_ub_l = %d", __func__, sw_bytes_ub_l); - DTRACE("DLG: %s: sw_bytes_ub_c = %d", __func__, sw_bytes_ub_c); - DTRACE("DLG: %s: sw_bytes = %d", __func__, sw_bytes); - DTRACE("DLG: %s: vm_bytes = %d", __func__, vm_bytes); - DTRACE("DLG: %s: meta_row_bytes = %d", __func__, meta_row_bytes); - DTRACE("DLG: %s: dpte_row_bytes = %d", __func__, dpte_row_bytes); - - prefetch_param->prefetch_bw = - (vm_bytes + 2 * dpte_row_bytes + 2 * meta_row_bytes + sw_bytes) / t_pre_us; - prefetch_param->flip_bytes = (vm_bytes + dpte_row_bytes + meta_row_bytes); -} - -/* Note: currently taken in as is. - * Nice to decouple code from hw register implement and extract code that are repeated for luma and chroma. - */ -void dml_rq_dlg_get_dlg_params( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_dlg_regs_st *disp_dlg_regs, - struct _vcs_dpi_display_ttu_regs_st *disp_ttu_regs, - const struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param, - const struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param, - const struct _vcs_dpi_display_e2e_pipe_params_st e2e_pipe_param, +// Note: currently taken in as is. +// Nice to decouple code from hw register implement and extract code that are repeated for luma and chroma. +void dml_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *e2e_pipe_param, + const unsigned int num_pipes, + const unsigned int pipe_idx, + display_dlg_regs_st *disp_dlg_regs, + display_ttu_regs_st *disp_ttu_regs, + const display_rq_dlg_params_st rq_dlg_param, + const display_dlg_sys_params_st dlg_sys_param, const bool cstate_en, const bool pstate_en, const bool vm_en, - const bool iflip_en) + const bool ignore_viewport_pos, + const bool immediate_flip_support) { - /* Timing */ - unsigned int htotal = e2e_pipe_param.pipe.dest.htotal; - unsigned int hblank_end = e2e_pipe_param.pipe.dest.hblank_end; - unsigned int vblank_start = e2e_pipe_param.pipe.dest.vblank_start; - unsigned int vblank_end = e2e_pipe_param.pipe.dest.vblank_end; - bool interlaced = e2e_pipe_param.pipe.dest.interlaced; + const display_pipe_source_params_st *src = &e2e_pipe_param[pipe_idx].pipe.src; + const display_pipe_dest_params_st *dst = &e2e_pipe_param[pipe_idx].pipe.dest; + const display_output_params_st *dout = &e2e_pipe_param[pipe_idx].dout; + const display_clocks_and_cfg_st *clks = &e2e_pipe_param[pipe_idx].clks_cfg; + const scaler_ratio_depth_st *scl = &e2e_pipe_param[pipe_idx].pipe.scale_ratio_depth; + const scaler_taps_st *taps = &e2e_pipe_param[pipe_idx].pipe.scale_taps; + + // ------------------------- + // Section 1.15.2.1: OTG dependent Params + // ------------------------- + // Timing + unsigned int htotal = dst->htotal; +// unsigned int hblank_start = dst.hblank_start; // TODO: Remove + unsigned int hblank_end = dst->hblank_end; + unsigned int vblank_start = dst->vblank_start; + unsigned int vblank_end = dst->vblank_end; unsigned int min_vblank = mode_lib->ip.min_vblank_lines; - double pclk_freq_in_mhz = e2e_pipe_param.pipe.dest.pixel_rate_mhz; - double refclk_freq_in_mhz = e2e_pipe_param.clks_cfg.refclk_mhz; - double dppclk_freq_in_mhz = e2e_pipe_param.clks_cfg.dppclk_mhz; - double dispclk_freq_in_mhz = e2e_pipe_param.clks_cfg.dispclk_mhz; + double dppclk_freq_in_mhz = clks->dppclk_mhz; + double dispclk_freq_in_mhz = clks->dispclk_mhz; + double refclk_freq_in_mhz = clks->refclk_mhz; + double pclk_freq_in_mhz = dst->pixel_rate_mhz; + bool interlaced = dst->interlaced; + + double ref_freq_to_pix_freq = refclk_freq_in_mhz / pclk_freq_in_mhz; - double ref_freq_to_pix_freq; - double prefetch_xy_calc_in_dcfclk; double min_dcfclk_mhz; double t_calc_us; double min_ttu_vblank; + double min_dst_y_ttu_vblank; - int unsigned dlg_vblank_start; - bool dcc_en; + unsigned int dlg_vblank_start; bool dual_plane; bool mode_422; unsigned int access_dir; - unsigned int bytes_per_element_l; - unsigned int bytes_per_element_c; unsigned int vp_height_l; unsigned int vp_width_l; unsigned int vp_height_c; unsigned int vp_width_c; + + // Scaling unsigned int htaps_l; unsigned int htaps_c; - double hratios_l; - double hratios_c; + double hratio_l; + double hratio_c; double vratio_l; double vratio_c; + bool scl_enable; + double line_time_in_us; - double vinit_l; - double vinit_c; - double vinit_bot_l; - double vinit_bot_c; - unsigned int swath_height_l; + // double vinit_l; + // double vinit_c; + // double vinit_bot_l; + // double vinit_bot_c; + + // unsigned int swath_height_l; unsigned int swath_width_ub_l; - unsigned int dpte_bytes_per_row_ub_l; + // unsigned int dpte_bytes_per_row_ub_l; unsigned int dpte_groups_per_row_ub_l; - unsigned int meta_pte_bytes_per_frame_ub_l; - unsigned int meta_bytes_per_row_ub_l; - unsigned int swath_height_c; + // unsigned int meta_pte_bytes_per_frame_ub_l; + // unsigned int meta_bytes_per_row_ub_l; + + // unsigned int swath_height_c; unsigned int swath_width_ub_c; - unsigned int dpte_bytes_per_row_ub_c; + // unsigned int dpte_bytes_per_row_ub_c; unsigned int dpte_groups_per_row_ub_c; + unsigned int meta_chunks_per_row_ub_l; + unsigned int meta_chunks_per_row_ub_c; unsigned int vupdate_offset; unsigned int vupdate_width; unsigned int vready_offset; + unsigned int dppclk_delay_subtotal; unsigned int dispclk_delay_subtotal; unsigned int pixel_rate_delay_subtotal; + unsigned int vstartup_start; unsigned int dst_x_after_scaler; unsigned int dst_y_after_scaler; double line_wait; - double line_o; - double line_setup; - double line_calc; double dst_y_prefetch; - double t_pre_us; - int unsigned vm_bytes; - int unsigned meta_row_bytes; - int unsigned max_num_sw_l; - int unsigned max_num_sw_c; - int unsigned max_partial_sw_l; - int unsigned max_partial_sw_c; - double max_vinit_l; - double max_vinit_c; - int unsigned lsw_l; - int unsigned lsw_c; - int unsigned sw_bytes_ub_l; - int unsigned sw_bytes_ub_c; - int unsigned sw_bytes; - int unsigned dpte_row_bytes; - double prefetch_bw; - double flip_bw; - double t_vm_us; - double t_r0_us; double dst_y_per_vm_vblank; double dst_y_per_row_vblank; + double dst_y_per_vm_flip; + double dst_y_per_row_flip; double min_dst_y_per_vm_vblank; double min_dst_y_per_row_vblank; double lsw; @@ -1314,6 +836,7 @@ void dml_rq_dlg_get_dlg_params( unsigned int req_per_swath_ub_l; unsigned int req_per_swath_ub_c; unsigned int meta_row_height_l; + unsigned int meta_row_height_c; unsigned int swath_width_pixels_ub_l; unsigned int swath_width_pixels_ub_c; unsigned int scaler_rec_in_width_l; @@ -1328,59 +851,52 @@ void dml_rq_dlg_get_dlg_params( double refcyc_per_line_delivery_pre_c; double refcyc_per_line_delivery_l; double refcyc_per_line_delivery_c; + double refcyc_per_req_delivery_pre_l; double refcyc_per_req_delivery_pre_c; double refcyc_per_req_delivery_l; double refcyc_per_req_delivery_c; + + unsigned int full_recout_width; + double xfc_transfer_delay; + double xfc_precharge_delay; + double xfc_remote_surface_flip_latency; + double xfc_dst_y_delta_drq_limit; + double xfc_prefetch_margin; double refcyc_per_req_delivery_pre_cur0; double refcyc_per_req_delivery_cur0; - int unsigned full_recout_width; - double hratios_cur0; - unsigned int cur0_src_width; - enum cursor_bpp cur0_bpp; - unsigned int cur0_req_size; - unsigned int cur0_req_width; - double cur0_width_ub; - double cur0_req_per_width; - double hactive_cur0; + double refcyc_per_req_delivery_pre_cur1; + double refcyc_per_req_delivery_cur1; memset(disp_dlg_regs, 0, sizeof(*disp_dlg_regs)); memset(disp_ttu_regs, 0, sizeof(*disp_ttu_regs)); - DTRACE("DLG: %s: cstate_en = %d", __func__, cstate_en); - DTRACE("DLG: %s: pstate_en = %d", __func__, pstate_en); - DTRACE("DLG: %s: vm_en = %d", __func__, vm_en); - DTRACE("DLG: %s: iflip_en = %d", __func__, iflip_en); - - /* ------------------------- */ - /* Section 1.5.2.1: OTG dependent Params */ - /* ------------------------- */ - DTRACE("DLG: %s: dppclk_freq_in_mhz = %3.2f", __func__, dppclk_freq_in_mhz); - DTRACE("DLG: %s: dispclk_freq_in_mhz = %3.2f", __func__, dispclk_freq_in_mhz); - DTRACE("DLG: %s: refclk_freq_in_mhz = %3.2f", __func__, refclk_freq_in_mhz); - DTRACE("DLG: %s: pclk_freq_in_mhz = %3.2f", __func__, pclk_freq_in_mhz); - DTRACE("DLG: %s: interlaced = %d", __func__, interlaced); - - ref_freq_to_pix_freq = refclk_freq_in_mhz / pclk_freq_in_mhz; + dml_print("DML_DLG: %s: cstate_en = %d\n", __func__, cstate_en); + dml_print("DML_DLG: %s: pstate_en = %d\n", __func__, pstate_en); + dml_print("DML_DLG: %s: vm_en = %d\n", __func__, vm_en); + dml_print("DML_DLG: %s: ignore_viewport_pos = %d\n", __func__, ignore_viewport_pos); + dml_print("DML_DLG: %s: immediate_flip_support = %d\n", __func__, immediate_flip_support); + + dml_print("DML_DLG: %s: dppclk_freq_in_mhz = %3.2f\n", __func__, dppclk_freq_in_mhz); + dml_print("DML_DLG: %s: dispclk_freq_in_mhz = %3.2f\n", __func__, dispclk_freq_in_mhz); + dml_print("DML_DLG: %s: refclk_freq_in_mhz = %3.2f\n", __func__, refclk_freq_in_mhz); + dml_print("DML_DLG: %s: pclk_freq_in_mhz = %3.2f\n", __func__, pclk_freq_in_mhz); + dml_print("DML_DLG: %s: interlaced = %d\n", __func__, interlaced); ASSERT(ref_freq_to_pix_freq < 4.0); + disp_dlg_regs->ref_freq_to_pix_freq = (unsigned int) (ref_freq_to_pix_freq * dml_pow(2, 19)); disp_dlg_regs->refcyc_per_htotal = (unsigned int) (ref_freq_to_pix_freq * (double) htotal * dml_pow(2, 8)); + disp_dlg_regs->dlg_vblank_end = interlaced ? (vblank_end / 2) : vblank_end; // 15 bits disp_dlg_regs->refcyc_h_blank_end = (unsigned int) ((double) hblank_end * (double) ref_freq_to_pix_freq); ASSERT(disp_dlg_regs->refcyc_h_blank_end < (unsigned int) dml_pow(2, 13)); - disp_dlg_regs->dlg_vblank_end = interlaced ? (vblank_end / 2) : vblank_end; /* 15 bits */ - prefetch_xy_calc_in_dcfclk = 24.0; /* FIXME: ip_param */ min_dcfclk_mhz = dlg_sys_param.deepsleep_dcfclk_mhz; - t_calc_us = prefetch_xy_calc_in_dcfclk / min_dcfclk_mhz; - min_ttu_vblank = dlg_sys_param.t_urg_wm_us; - if (cstate_en) - min_ttu_vblank = dml_max(dlg_sys_param.t_sr_wm_us, min_ttu_vblank); - if (pstate_en) - min_ttu_vblank = dml_max(dlg_sys_param.t_mclk_wm_us, min_ttu_vblank); - min_ttu_vblank = min_ttu_vblank + t_calc_us; + set_prefetch_mode(mode_lib, cstate_en, pstate_en, ignore_viewport_pos, immediate_flip_support); + t_calc_us = get_tcalc(mode_lib, e2e_pipe_param, num_pipes); + min_ttu_vblank = get_min_ttu_vblank(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); min_dst_y_ttu_vblank = min_ttu_vblank * pclk_freq_in_mhz / (double) htotal; dlg_vblank_start = interlaced ? (vblank_start / 2) : vblank_start; @@ -1389,383 +905,202 @@ void dml_rq_dlg_get_dlg_params( + min_dst_y_ttu_vblank) * dml_pow(2, 2)); ASSERT(disp_dlg_regs->min_dst_y_next_start < (unsigned int) dml_pow(2, 18)); - DTRACE("DLG: %s: min_dcfclk_mhz = %3.2f", __func__, min_dcfclk_mhz); - DTRACE("DLG: %s: min_ttu_vblank = %3.2f", __func__, min_ttu_vblank); - DTRACE( - "DLG: %s: min_dst_y_ttu_vblank = %3.2f", + dml_print("DML_DLG: %s: min_dcfclk_mhz = %3.2f\n", + __func__, + min_dcfclk_mhz); + dml_print("DML_DLG: %s: min_ttu_vblank = %3.2f\n", + __func__, + min_ttu_vblank); + dml_print("DML_DLG: %s: min_dst_y_ttu_vblank = %3.2f\n", __func__, min_dst_y_ttu_vblank); - DTRACE("DLG: %s: t_calc_us = %3.2f", __func__, t_calc_us); - DTRACE( - "DLG: %s: disp_dlg_regs->min_dst_y_next_start = 0x%0x", + dml_print("DML_DLG: %s: t_calc_us = %3.2f\n", + __func__, + t_calc_us); + dml_print("DML_DLG: %s: disp_dlg_regs->min_dst_y_next_start = 0x%0x\n", __func__, disp_dlg_regs->min_dst_y_next_start); - DTRACE( - "DLG: %s: ref_freq_to_pix_freq = %3.2f", + dml_print("DML_DLG: %s: ref_freq_to_pix_freq = %3.2f\n", __func__, ref_freq_to_pix_freq); - /* ------------------------- */ - /* Section 1.5.2.2: Prefetch, Active and TTU */ - /* ------------------------- */ - /* Prefetch Calc */ - /* Source */ - dcc_en = e2e_pipe_param.pipe.src.dcc; - dual_plane = is_dual_plane( - (enum source_format_class) e2e_pipe_param.pipe.src.source_format); - mode_422 = 0; /* FIXME */ - access_dir = (e2e_pipe_param.pipe.src.source_scan == dm_vert); /* vp access direction: horizontal or vertical accessed */ - bytes_per_element_l = get_bytes_per_element( - (enum source_format_class) e2e_pipe_param.pipe.src.source_format, - 0); - bytes_per_element_c = get_bytes_per_element( - (enum source_format_class) e2e_pipe_param.pipe.src.source_format, - 1); - vp_height_l = e2e_pipe_param.pipe.src.viewport_height; - vp_width_l = e2e_pipe_param.pipe.src.viewport_width; - vp_height_c = e2e_pipe_param.pipe.src.viewport_height_c; - vp_width_c = e2e_pipe_param.pipe.src.viewport_width_c; - - /* Scaling */ - htaps_l = e2e_pipe_param.pipe.scale_taps.htaps; - htaps_c = e2e_pipe_param.pipe.scale_taps.htaps_c; - hratios_l = e2e_pipe_param.pipe.scale_ratio_depth.hscl_ratio; - hratios_c = e2e_pipe_param.pipe.scale_ratio_depth.hscl_ratio_c; - vratio_l = e2e_pipe_param.pipe.scale_ratio_depth.vscl_ratio; - vratio_c = e2e_pipe_param.pipe.scale_ratio_depth.vscl_ratio_c; + // ------------------------- + // Section 1.15.2.2: Prefetch, Active and TTU + // ------------------------- + // Prefetch Calc + // Source +// dcc_en = src.dcc; + dual_plane = is_dual_plane((enum source_format_class)(src->source_format)); + mode_422 = 0; // FIXME + access_dir = (src->source_scan == dm_vert); // vp access direction: horizontal or vertical accessed +// bytes_per_element_l = get_bytes_per_element(source_format_class(src.source_format), 0); +// bytes_per_element_c = get_bytes_per_element(source_format_class(src.source_format), 1); + vp_height_l = src->viewport_height; + vp_width_l = src->viewport_width; + vp_height_c = src->viewport_height_c; + vp_width_c = src->viewport_width_c; + + // Scaling + htaps_l = taps->htaps; + htaps_c = taps->htaps_c; + hratio_l = scl->hscl_ratio; + hratio_c = scl->hscl_ratio_c; + vratio_l = scl->vscl_ratio; + vratio_c = scl->vscl_ratio_c; + scl_enable = scl->scl_enable; line_time_in_us = (htotal / pclk_freq_in_mhz); - vinit_l = e2e_pipe_param.pipe.scale_ratio_depth.vinit; - vinit_c = e2e_pipe_param.pipe.scale_ratio_depth.vinit_c; - vinit_bot_l = e2e_pipe_param.pipe.scale_ratio_depth.vinit_bot; - vinit_bot_c = e2e_pipe_param.pipe.scale_ratio_depth.vinit_bot_c; +// vinit_l = scl.vinit; +// vinit_c = scl.vinit_c; +// vinit_bot_l = scl.vinit_bot; +// vinit_bot_c = scl.vinit_bot_c; - swath_height_l = rq_dlg_param.rq_l.swath_height; +// unsigned int swath_height_l = rq_dlg_param.rq_l.swath_height; swath_width_ub_l = rq_dlg_param.rq_l.swath_width_ub; - dpte_bytes_per_row_ub_l = rq_dlg_param.rq_l.dpte_bytes_per_row_ub; +// unsigned int dpte_bytes_per_row_ub_l = rq_dlg_param.rq_l.dpte_bytes_per_row_ub; dpte_groups_per_row_ub_l = rq_dlg_param.rq_l.dpte_groups_per_row_ub; - meta_pte_bytes_per_frame_ub_l = rq_dlg_param.rq_l.meta_pte_bytes_per_frame_ub; - meta_bytes_per_row_ub_l = rq_dlg_param.rq_l.meta_bytes_per_row_ub; +// unsigned int meta_pte_bytes_per_frame_ub_l = rq_dlg_param.rq_l.meta_pte_bytes_per_frame_ub; +// unsigned int meta_bytes_per_row_ub_l = rq_dlg_param.rq_l.meta_bytes_per_row_ub; - swath_height_c = rq_dlg_param.rq_c.swath_height; +// unsigned int swath_height_c = rq_dlg_param.rq_c.swath_height; swath_width_ub_c = rq_dlg_param.rq_c.swath_width_ub; - dpte_bytes_per_row_ub_c = rq_dlg_param.rq_c.dpte_bytes_per_row_ub; + // dpte_bytes_per_row_ub_c = rq_dlg_param.rq_c.dpte_bytes_per_row_ub; dpte_groups_per_row_ub_c = rq_dlg_param.rq_c.dpte_groups_per_row_ub; meta_chunks_per_row_ub_l = rq_dlg_param.rq_l.meta_chunks_per_row_ub; - vupdate_offset = e2e_pipe_param.pipe.dest.vupdate_offset; - vupdate_width = e2e_pipe_param.pipe.dest.vupdate_width; - vready_offset = e2e_pipe_param.pipe.dest.vready_offset; + meta_chunks_per_row_ub_c = rq_dlg_param.rq_c.meta_chunks_per_row_ub; + vupdate_offset = dst->vupdate_offset; + vupdate_width = dst->vupdate_width; + vready_offset = dst->vready_offset; dppclk_delay_subtotal = mode_lib->ip.dppclk_delay_subtotal; dispclk_delay_subtotal = mode_lib->ip.dispclk_delay_subtotal; + + if (scl_enable) + dppclk_delay_subtotal += mode_lib->ip.dppclk_delay_scl; + else + dppclk_delay_subtotal += mode_lib->ip.dppclk_delay_scl_lb_only; + + dppclk_delay_subtotal += mode_lib->ip.dppclk_delay_cnvc_formatter + + src->num_cursors * mode_lib->ip.dppclk_delay_cnvc_cursor; + + if (dout->dsc_enable) { + double dsc_delay = get_dsc_delay(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); + + dispclk_delay_subtotal += dsc_delay; + } + pixel_rate_delay_subtotal = dppclk_delay_subtotal * pclk_freq_in_mhz / dppclk_freq_in_mhz + dispclk_delay_subtotal * pclk_freq_in_mhz / dispclk_freq_in_mhz; - vstartup_start = e2e_pipe_param.pipe.dest.vstartup_start; + vstartup_start = dst->vstartup_start; + if (interlaced) { + if (vstartup_start / 2.0 + - (double) (vready_offset + vupdate_width + vupdate_offset) / htotal + <= vblank_end / 2.0) + disp_dlg_regs->vready_after_vcount0 = 1; + else + disp_dlg_regs->vready_after_vcount0 = 0; + } else { + if (vstartup_start + - (double) (vready_offset + vupdate_width + vupdate_offset) / htotal + <= vblank_end) + disp_dlg_regs->vready_after_vcount0 = 1; + else + disp_dlg_regs->vready_after_vcount0 = 0; + } + // TODO: Where is this coming from? if (interlaced) vstartup_start = vstartup_start / 2; + // TODO: What if this min_vblank doesn't match the value in the dml_config_settings.cpp? if (vstartup_start >= min_vblank) { - DTRACE( - "WARNING_DLG: %s: vblank_start=%d vblank_end=%d", + dml_print("WARNING: DML_DLG: %s: vblank_start=%d vblank_end=%d\n", __func__, vblank_start, vblank_end); - DTRACE( - "WARNING_DLG: %s: vstartup_start=%d should be less than min_vblank=%d", + dml_print("WARNING: DML_DLG: %s: vstartup_start=%d should be less than min_vblank=%d\n", __func__, vstartup_start, min_vblank); min_vblank = vstartup_start + 1; - DTRACE( - "WARNING_DLG: %s: vstartup_start=%d should be less than min_vblank=%d", + dml_print("WARNING: DML_DLG: %s: vstartup_start=%d should be less than min_vblank=%d\n", __func__, vstartup_start, min_vblank); } - dst_x_after_scaler = 0; - dst_y_after_scaler = 0; - - if (e2e_pipe_param.pipe.src.is_hsplit) - dst_x_after_scaler = pixel_rate_delay_subtotal - + e2e_pipe_param.pipe.dest.recout_width; - else - dst_x_after_scaler = pixel_rate_delay_subtotal; - - if (e2e_pipe_param.dout.output_format == dm_420) - dst_y_after_scaler = 1; - else - dst_y_after_scaler = 0; + dst_x_after_scaler = get_dst_x_after_scaler(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); + dst_y_after_scaler = get_dst_y_after_scaler(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); - if (dst_x_after_scaler >= htotal) { - dst_x_after_scaler = dst_x_after_scaler - htotal; - dst_y_after_scaler = dst_y_after_scaler + 1; - } - - DTRACE("DLG: %s: htotal = %d", __func__, htotal); - DTRACE( - "DLG: %s: pixel_rate_delay_subtotal = %d", + dml_print("DML_DLG: %s: htotal = %d\n", __func__, htotal); + dml_print("DML_DLG: %s: pixel_rate_delay_subtotal = %d\n", __func__, pixel_rate_delay_subtotal); - DTRACE("DLG: %s: dst_x_after_scaler = %d", __func__, dst_x_after_scaler); - DTRACE("DLG: %s: dst_y_after_scaler = %d", __func__, dst_y_after_scaler); + dml_print("DML_DLG: %s: dst_x_after_scaler = %d\n", + __func__, + dst_x_after_scaler); + dml_print("DML_DLG: %s: dst_y_after_scaler = %d\n", + __func__, + dst_y_after_scaler); + // Lwait line_wait = mode_lib->soc.urgent_latency_us; if (cstate_en) line_wait = dml_max(mode_lib->soc.sr_enter_plus_exit_time_us, line_wait); if (pstate_en) - line_wait = dml_max( - mode_lib->soc.dram_clock_change_latency_us + line_wait = dml_max(mode_lib->soc.dram_clock_change_latency_us + mode_lib->soc.urgent_latency_us, line_wait); line_wait = line_wait / line_time_in_us; - line_o = (double) dst_y_after_scaler + dst_x_after_scaler / (double) htotal; - line_setup = (double) (vupdate_offset + vupdate_width + vready_offset) / (double) htotal; - line_calc = t_calc_us / line_time_in_us; + dst_y_prefetch = get_dst_y_prefetch(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); + dml_print("DML_DLG: %s: dst_y_prefetch (after rnd) = %3.2f\n", __func__, dst_y_prefetch); - DTRACE( - "DLG: %s: soc.sr_enter_plus_exit_time_us = %3.2f", - __func__, - (double) mode_lib->soc.sr_enter_plus_exit_time_us); - DTRACE( - "DLG: %s: soc.dram_clock_change_latency_us = %3.2f", - __func__, - (double) mode_lib->soc.dram_clock_change_latency_us); - DTRACE( - "DLG: %s: soc.urgent_latency_us = %3.2f", - __func__, - mode_lib->soc.urgent_latency_us); - - DTRACE("DLG: %s: swath_height_l = %d", __func__, swath_height_l); - if (dual_plane) - DTRACE("DLG: %s: swath_height_c = %d", __func__, swath_height_c); - - DTRACE( - "DLG: %s: t_srx_delay_us = %3.2f", - __func__, - (double) dlg_sys_param.t_srx_delay_us); - DTRACE("DLG: %s: line_time_in_us = %3.2f", __func__, (double) line_time_in_us); - DTRACE("DLG: %s: vupdate_offset = %d", __func__, vupdate_offset); - DTRACE("DLG: %s: vupdate_width = %d", __func__, vupdate_width); - DTRACE("DLG: %s: vready_offset = %d", __func__, vready_offset); - DTRACE("DLG: %s: line_time_in_us = %3.2f", __func__, line_time_in_us); - DTRACE("DLG: %s: line_wait = %3.2f", __func__, line_wait); - DTRACE("DLG: %s: line_o = %3.2f", __func__, line_o); - DTRACE("DLG: %s: line_setup = %3.2f", __func__, line_setup); - DTRACE("DLG: %s: line_calc = %3.2f", __func__, line_calc); - - dst_y_prefetch = ((double) min_vblank - 1.0) - - (line_setup + line_calc + line_wait + line_o); - DTRACE("DLG: %s: dst_y_prefetch (before rnd) = %3.2f", __func__, dst_y_prefetch); - ASSERT(dst_y_prefetch >= 2.0); - - dst_y_prefetch = dml_floor(4.0 * (dst_y_prefetch + 0.125)) / 4; - DTRACE("DLG: %s: dst_y_prefetch (after rnd) = %3.2f", __func__, dst_y_prefetch); - - t_pre_us = dst_y_prefetch * line_time_in_us; - vm_bytes = 0; - meta_row_bytes = 0; - - if (dcc_en && vm_en) - vm_bytes = meta_pte_bytes_per_frame_ub_l; - if (dcc_en) - meta_row_bytes = meta_bytes_per_row_ub_l; - - max_num_sw_l = 0; - max_num_sw_c = 0; - max_partial_sw_l = 0; - max_partial_sw_c = 0; - - max_vinit_l = interlaced ? dml_max(vinit_l, vinit_bot_l) : vinit_l; - max_vinit_c = interlaced ? dml_max(vinit_c, vinit_bot_c) : vinit_c; - - get_swath_need(mode_lib, &max_num_sw_l, &max_partial_sw_l, swath_height_l, max_vinit_l); - if (dual_plane) - get_swath_need( - mode_lib, - &max_num_sw_c, - &max_partial_sw_c, - swath_height_c, - max_vinit_c); - - lsw_l = max_num_sw_l * swath_height_l + max_partial_sw_l; - lsw_c = max_num_sw_c * swath_height_c + max_partial_sw_c; - sw_bytes_ub_l = lsw_l * swath_width_ub_l * bytes_per_element_l; - sw_bytes_ub_c = lsw_c * swath_width_ub_c * bytes_per_element_c; - sw_bytes = 0; - dpte_row_bytes = 0; - - if (vm_en) { - if (dual_plane) - dpte_row_bytes = dpte_bytes_per_row_ub_l + dpte_bytes_per_row_ub_c; - else - dpte_row_bytes = dpte_bytes_per_row_ub_l; - } else { - dpte_row_bytes = 0; - } - - if (dual_plane) - sw_bytes = sw_bytes_ub_l + sw_bytes_ub_c; - else - sw_bytes = sw_bytes_ub_l; - - DTRACE("DLG: %s: sw_bytes_ub_l = %d", __func__, sw_bytes_ub_l); - DTRACE("DLG: %s: sw_bytes_ub_c = %d", __func__, sw_bytes_ub_c); - DTRACE("DLG: %s: sw_bytes = %d", __func__, sw_bytes); - DTRACE("DLG: %s: vm_bytes = %d", __func__, vm_bytes); - DTRACE("DLG: %s: meta_row_bytes = %d", __func__, meta_row_bytes); - DTRACE("DLG: %s: dpte_row_bytes = %d", __func__, dpte_row_bytes); - - prefetch_bw = (vm_bytes + 2 * dpte_row_bytes + 2 * meta_row_bytes + sw_bytes) / t_pre_us; - flip_bw = ((vm_bytes + dpte_row_bytes + meta_row_bytes) * dlg_sys_param.total_flip_bw) - / (double) dlg_sys_param.total_flip_bytes; - t_vm_us = line_time_in_us / 4.0; - if (vm_en && dcc_en) { - t_vm_us = dml_max( - dlg_sys_param.t_extra_us, - dml_max((double) vm_bytes / prefetch_bw, t_vm_us)); - - if (iflip_en && !dual_plane) { - t_vm_us = dml_max(mode_lib->soc.urgent_latency_us, t_vm_us); - if (flip_bw > 0.) - t_vm_us = dml_max(vm_bytes / flip_bw, t_vm_us); - } - } - - t_r0_us = dml_max(dlg_sys_param.t_extra_us - t_vm_us, line_time_in_us - t_vm_us); - - if (vm_en || dcc_en) { - t_r0_us = dml_max( - (double) (dpte_row_bytes + meta_row_bytes) / prefetch_bw, - dlg_sys_param.t_extra_us); - t_r0_us = dml_max((double) (line_time_in_us - t_vm_us), t_r0_us); - - if (iflip_en && !dual_plane) { - t_r0_us = dml_max(mode_lib->soc.urgent_latency_us * 2.0, t_r0_us); - if (flip_bw > 0.) - t_r0_us = dml_max( - (dpte_row_bytes + meta_row_bytes) / flip_bw, - t_r0_us); - } - } - - disp_dlg_regs->dst_y_after_scaler = dst_y_after_scaler; /* in terms of line */ - disp_dlg_regs->refcyc_x_after_scaler = dst_x_after_scaler * ref_freq_to_pix_freq; /* in terms of refclk */ - ASSERT(disp_dlg_regs->refcyc_x_after_scaler < (unsigned int) dml_pow(2, 13)); - DTRACE( - "DLG: %s: disp_dlg_regs->dst_y_after_scaler = 0x%0x", - __func__, - disp_dlg_regs->dst_y_after_scaler); - DTRACE( - "DLG: %s: disp_dlg_regs->refcyc_x_after_scaler = 0x%0x", - __func__, - disp_dlg_regs->refcyc_x_after_scaler); - - disp_dlg_regs->dst_y_prefetch = (unsigned int) (dst_y_prefetch * dml_pow(2, 2)); - DTRACE( - "DLG: %s: disp_dlg_regs->dst_y_prefetch = %d", - __func__, - disp_dlg_regs->dst_y_prefetch); - - dst_y_per_vm_vblank = 0.0; - dst_y_per_row_vblank = 0.0; - - dst_y_per_vm_vblank = t_vm_us / line_time_in_us; - dst_y_per_vm_vblank = dml_floor(4.0 * (dst_y_per_vm_vblank + 0.125)) / 4.0; - disp_dlg_regs->dst_y_per_vm_vblank = (unsigned int) (dst_y_per_vm_vblank * dml_pow(2, 2)); - - dst_y_per_row_vblank = t_r0_us / line_time_in_us; - dst_y_per_row_vblank = dml_floor(4.0 * (dst_y_per_row_vblank + 0.125)) / 4.0; - disp_dlg_regs->dst_y_per_row_vblank = (unsigned int) (dst_y_per_row_vblank * dml_pow(2, 2)); - - DTRACE("DLG: %s: lsw_l = %d", __func__, lsw_l); - DTRACE("DLG: %s: lsw_c = %d", __func__, lsw_c); - DTRACE("DLG: %s: dpte_bytes_per_row_ub_l = %d", __func__, dpte_bytes_per_row_ub_l); - DTRACE("DLG: %s: dpte_bytes_per_row_ub_c = %d", __func__, dpte_bytes_per_row_ub_c); - - DTRACE("DLG: %s: prefetch_bw = %3.2f", __func__, prefetch_bw); - DTRACE("DLG: %s: flip_bw = %3.2f", __func__, flip_bw); - DTRACE("DLG: %s: t_pre_us = %3.2f", __func__, t_pre_us); - DTRACE("DLG: %s: t_vm_us = %3.2f", __func__, t_vm_us); - DTRACE("DLG: %s: t_r0_us = %3.2f", __func__, t_r0_us); - DTRACE("DLG: %s: dst_y_per_vm_vblank = %3.2f", __func__, dst_y_per_vm_vblank); - DTRACE("DLG: %s: dst_y_per_row_vblank = %3.2f", __func__, dst_y_per_row_vblank); - DTRACE("DLG: %s: dst_y_prefetch = %3.2f", __func__, dst_y_prefetch); + dst_y_per_vm_vblank = get_dst_y_per_vm_vblank(mode_lib, + e2e_pipe_param, + num_pipes, + pipe_idx); + dst_y_per_row_vblank = get_dst_y_per_row_vblank(mode_lib, + e2e_pipe_param, + num_pipes, + pipe_idx); + dst_y_per_vm_flip = get_dst_y_per_vm_flip(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); + dst_y_per_row_flip = get_dst_y_per_row_flip(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); min_dst_y_per_vm_vblank = 8.0; min_dst_y_per_row_vblank = 16.0; + + // magic! if (htotal <= 75) { min_vblank = 300; min_dst_y_per_vm_vblank = 100.0; min_dst_y_per_row_vblank = 100.0; } + dml_print("DML_DLG: %s: dst_y_per_vm_vblank = %3.2f\n", __func__, dst_y_per_vm_vblank); + dml_print("DML_DLG: %s: dst_y_per_row_vblank = %3.2f\n", __func__, dst_y_per_row_vblank); + ASSERT(dst_y_per_vm_vblank < min_dst_y_per_vm_vblank); ASSERT(dst_y_per_row_vblank < min_dst_y_per_row_vblank); ASSERT(dst_y_prefetch > (dst_y_per_vm_vblank + dst_y_per_row_vblank)); lsw = dst_y_prefetch - (dst_y_per_vm_vblank + dst_y_per_row_vblank); - DTRACE("DLG: %s: lsw = %3.2f", __func__, lsw); - - vratio_pre_l = get_vratio_pre( - mode_lib, - max_num_sw_l, - max_partial_sw_l, - swath_height_l, - max_vinit_l, - lsw); - vratio_pre_c = 1.0; - if (dual_plane) - vratio_pre_c = get_vratio_pre( - mode_lib, - max_num_sw_c, - max_partial_sw_c, - swath_height_c, - max_vinit_c, - lsw); - - DTRACE("DLG: %s: vratio_pre_l=%3.2f", __func__, vratio_pre_l); - DTRACE("DLG: %s: vratio_pre_c=%3.2f", __func__, vratio_pre_c); - - ASSERT(vratio_pre_l <= 4.0); - if (vratio_pre_l >= 4.0) - disp_dlg_regs->vratio_prefetch = (unsigned int) dml_pow(2, 21) - 1; - else - disp_dlg_regs->vratio_prefetch = (unsigned int) (vratio_pre_l * dml_pow(2, 19)); + dml_print("DML_DLG: %s: lsw = %3.2f\n", __func__, lsw); - ASSERT(vratio_pre_c <= 4.0); - if (vratio_pre_c >= 4.0) - disp_dlg_regs->vratio_prefetch_c = (unsigned int) dml_pow(2, 21) - 1; - else - disp_dlg_regs->vratio_prefetch_c = (unsigned int) (vratio_pre_c * dml_pow(2, 19)); + vratio_pre_l = get_vratio_prefetch_l(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); + vratio_pre_c = get_vratio_prefetch_c(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); - disp_dlg_regs->refcyc_per_pte_group_vblank_l = - (unsigned int) (dst_y_per_row_vblank * (double) htotal - * ref_freq_to_pix_freq / (double) dpte_groups_per_row_ub_l); - ASSERT(disp_dlg_regs->refcyc_per_pte_group_vblank_l < (unsigned int) dml_pow(2, 13)); - - disp_dlg_regs->refcyc_per_pte_group_vblank_c = - (unsigned int) (dst_y_per_row_vblank * (double) htotal - * ref_freq_to_pix_freq / (double) dpte_groups_per_row_ub_c); - ASSERT(disp_dlg_regs->refcyc_per_pte_group_vblank_c < (unsigned int) dml_pow(2, 13)); - - disp_dlg_regs->refcyc_per_meta_chunk_vblank_l = - (unsigned int) (dst_y_per_row_vblank * (double) htotal - * ref_freq_to_pix_freq / (double) meta_chunks_per_row_ub_l); - ASSERT(disp_dlg_regs->refcyc_per_meta_chunk_vblank_l < (unsigned int) dml_pow(2, 13)); + dml_print("DML_DLG: %s: vratio_pre_l=%3.2f\n", __func__, vratio_pre_l); + dml_print("DML_DLG: %s: vratio_pre_c=%3.2f\n", __func__, vratio_pre_c); - disp_dlg_regs->refcyc_per_meta_chunk_vblank_c = - disp_dlg_regs->refcyc_per_meta_chunk_vblank_l;/* dcc for 4:2:0 is not supported in dcn1.0. assigned to be the same as _l for now */ - - /* Active */ + // Active req_per_swath_ub_l = rq_dlg_param.rq_l.req_per_swath_ub; req_per_swath_ub_c = rq_dlg_param.rq_c.req_per_swath_ub; meta_row_height_l = rq_dlg_param.rq_l.meta_row_height; + meta_row_height_c = rq_dlg_param.rq_c.meta_row_height; swath_width_pixels_ub_l = 0; swath_width_pixels_ub_c = 0; scaler_rec_in_width_l = 0; @@ -1773,40 +1108,8 @@ void dml_rq_dlg_get_dlg_params( dpte_row_height_l = rq_dlg_param.rq_l.dpte_row_height; dpte_row_height_c = rq_dlg_param.rq_c.dpte_row_height; - disp_dlg_regs->dst_y_per_pte_row_nom_l = (unsigned int) ((double) dpte_row_height_l - / (double) vratio_l * dml_pow(2, 2)); - ASSERT(disp_dlg_regs->dst_y_per_pte_row_nom_l < (unsigned int) dml_pow(2, 17)); - - disp_dlg_regs->dst_y_per_pte_row_nom_c = (unsigned int) ((double) dpte_row_height_c - / (double) vratio_c * dml_pow(2, 2)); - ASSERT(disp_dlg_regs->dst_y_per_pte_row_nom_c < (unsigned int) dml_pow(2, 17)); - - disp_dlg_regs->dst_y_per_meta_row_nom_l = (unsigned int) ((double) meta_row_height_l - / (double) vratio_l * dml_pow(2, 2)); - ASSERT(disp_dlg_regs->dst_y_per_meta_row_nom_l < (unsigned int) dml_pow(2, 17)); - - disp_dlg_regs->dst_y_per_meta_row_nom_c = disp_dlg_regs->dst_y_per_meta_row_nom_l; /* dcc for 4:2:0 is not supported in dcn1.0. assigned to be the same as _l for now */ - - disp_dlg_regs->refcyc_per_pte_group_nom_l = (unsigned int) ((double) dpte_row_height_l - / (double) vratio_l * (double) htotal * ref_freq_to_pix_freq - / (double) dpte_groups_per_row_ub_l); - if (disp_dlg_regs->refcyc_per_pte_group_nom_l >= (unsigned int) dml_pow(2, 23)) - disp_dlg_regs->refcyc_per_pte_group_nom_l = dml_pow(2, 23) - 1; - - disp_dlg_regs->refcyc_per_pte_group_nom_c = (unsigned int) ((double) dpte_row_height_c - / (double) vratio_c * (double) htotal * ref_freq_to_pix_freq - / (double) dpte_groups_per_row_ub_c); - if (disp_dlg_regs->refcyc_per_pte_group_nom_c >= (unsigned int) dml_pow(2, 23)) - disp_dlg_regs->refcyc_per_pte_group_nom_c = dml_pow(2, 23) - 1; - - disp_dlg_regs->refcyc_per_meta_chunk_nom_l = (unsigned int) ((double) meta_row_height_l - / (double) vratio_l * (double) htotal * ref_freq_to_pix_freq - / (double) meta_chunks_per_row_ub_l); - if (disp_dlg_regs->refcyc_per_meta_chunk_nom_l >= (unsigned int) dml_pow(2, 23)) - disp_dlg_regs->refcyc_per_meta_chunk_nom_l = dml_pow(2, 23) - 1; - if (mode_422) { - swath_width_pixels_ub_l = swath_width_ub_l * 2; /* *2 for 2 pixel per element */ + swath_width_pixels_ub_l = swath_width_ub_l * 2; // *2 for 2 pixel per element swath_width_pixels_ub_c = swath_width_ub_c * 2; } else { swath_width_pixels_ub_l = swath_width_ub_l * 1; @@ -1821,15 +1124,15 @@ void dml_rq_dlg_get_dlg_params( if (htaps_l <= 1) min_hratio_fact_l = 2.0; else if (htaps_l <= 6) { - if ((hratios_l * 2.0) > 4.0) + if ((hratio_l * 2.0) > 4.0) min_hratio_fact_l = 4.0; else - min_hratio_fact_l = hratios_l * 2.0; + min_hratio_fact_l = hratio_l * 2.0; } else { - if (hratios_l > 4.0) + if (hratio_l > 4.0) min_hratio_fact_l = 4.0; else - min_hratio_fact_l = hratios_l; + min_hratio_fact_l = hratio_l; } hscale_pixel_rate_l = min_hratio_fact_l * dppclk_freq_in_mhz; @@ -1837,15 +1140,15 @@ void dml_rq_dlg_get_dlg_params( if (htaps_c <= 1) min_hratio_fact_c = 2.0; else if (htaps_c <= 6) { - if ((hratios_c * 2.0) > 4.0) + if ((hratio_c * 2.0) > 4.0) min_hratio_fact_c = 4.0; else - min_hratio_fact_c = hratios_c * 2.0; + min_hratio_fact_c = hratio_c * 2.0; } else { - if (hratios_c > 4.0) + if (hratio_c > 4.0) min_hratio_fact_c = 4.0; else - min_hratio_fact_c = hratios_c; + min_hratio_fact_c = hratio_c; } hscale_pixel_rate_c = min_hratio_fact_c * dppclk_freq_in_mhz; @@ -1859,97 +1162,90 @@ void dml_rq_dlg_get_dlg_params( refcyc_per_req_delivery_pre_c = 0.; refcyc_per_req_delivery_l = 0.; refcyc_per_req_delivery_c = 0.; - refcyc_per_req_delivery_pre_cur0 = 0.; - refcyc_per_req_delivery_cur0 = 0.; full_recout_width = 0; - if (e2e_pipe_param.pipe.src.is_hsplit) { - if (e2e_pipe_param.pipe.dest.full_recout_width == 0) { - DTRACE("DLG: %s: Warningfull_recout_width not set in hsplit mode", __func__); - full_recout_width = e2e_pipe_param.pipe.dest.recout_width * 2; /* assume half split for dcn1 */ + // In ODM + if (src->is_hsplit) { + // This "hack" is only allowed (and valid) for MPC combine. In ODM + // combine, you MUST specify the full_recout_width...according to Oswin + if (dst->full_recout_width == 0 && !dst->odm_combine) { + dml_print("DML_DLG: %s: Warning: full_recout_width not set in hsplit mode\n", + __func__); + full_recout_width = dst->recout_width * 2; // assume half split for dcn1 } else - full_recout_width = e2e_pipe_param.pipe.dest.full_recout_width; + full_recout_width = dst->full_recout_width; } else - full_recout_width = e2e_pipe_param.pipe.dest.recout_width; + full_recout_width = dst->recout_width; - refcyc_per_line_delivery_pre_l = get_refcyc_per_delivery( - mode_lib, + // mpc_combine and odm_combine are mutually exclusive + refcyc_per_line_delivery_pre_l = get_refcyc_per_delivery(mode_lib, refclk_freq_in_mhz, pclk_freq_in_mhz, + dst->odm_combine, full_recout_width, + dst->hactive, vratio_pre_l, hscale_pixel_rate_l, swath_width_pixels_ub_l, - 1); /* per line */ + 1); // per line - refcyc_per_line_delivery_l = get_refcyc_per_delivery( - mode_lib, + refcyc_per_line_delivery_l = get_refcyc_per_delivery(mode_lib, refclk_freq_in_mhz, pclk_freq_in_mhz, + dst->odm_combine, full_recout_width, + dst->hactive, vratio_l, hscale_pixel_rate_l, swath_width_pixels_ub_l, - 1); /* per line */ + 1); // per line - DTRACE("DLG: %s: full_recout_width = %d", __func__, full_recout_width); - DTRACE("DLG: %s: hscale_pixel_rate_l = %3.2f", __func__, hscale_pixel_rate_l); - DTRACE( - "DLG: %s: refcyc_per_line_delivery_pre_l = %3.2f", + dml_print("DML_DLG: %s: full_recout_width = %d\n", __func__, - refcyc_per_line_delivery_pre_l); - DTRACE( - "DLG: %s: refcyc_per_line_delivery_l = %3.2f", + full_recout_width); + dml_print("DML_DLG: %s: hscale_pixel_rate_l = %3.2f\n", + __func__, + hscale_pixel_rate_l); + dml_print("DML_DLG: %s: refcyc_per_line_delivery_pre_l = %3.2f\n", __func__, - refcyc_per_line_delivery_l); - - disp_dlg_regs->refcyc_per_line_delivery_pre_l = (unsigned int) dml_floor( refcyc_per_line_delivery_pre_l); - disp_dlg_regs->refcyc_per_line_delivery_l = (unsigned int) dml_floor( + dml_print("DML_DLG: %s: refcyc_per_line_delivery_l = %3.2f\n", + __func__, refcyc_per_line_delivery_l); - ASSERT(disp_dlg_regs->refcyc_per_line_delivery_pre_l < (unsigned int) dml_pow(2, 13)); - ASSERT(disp_dlg_regs->refcyc_per_line_delivery_l < (unsigned int) dml_pow(2, 13)); if (dual_plane) { - refcyc_per_line_delivery_pre_c = get_refcyc_per_delivery( - mode_lib, + refcyc_per_line_delivery_pre_c = get_refcyc_per_delivery(mode_lib, refclk_freq_in_mhz, pclk_freq_in_mhz, + dst->odm_combine, full_recout_width, + dst->hactive, vratio_pre_c, hscale_pixel_rate_c, swath_width_pixels_ub_c, - 1); /* per line */ + 1); // per line - refcyc_per_line_delivery_c = get_refcyc_per_delivery( - mode_lib, + refcyc_per_line_delivery_c = get_refcyc_per_delivery(mode_lib, refclk_freq_in_mhz, pclk_freq_in_mhz, + dst->odm_combine, full_recout_width, + dst->hactive, vratio_c, hscale_pixel_rate_c, swath_width_pixels_ub_c, - 1); /* per line */ + 1); // per line - DTRACE( - "DLG: %s: refcyc_per_line_delivery_pre_c = %3.2f", + dml_print("DML_DLG: %s: refcyc_per_line_delivery_pre_c = %3.2f\n", __func__, refcyc_per_line_delivery_pre_c); - DTRACE( - "DLG: %s: refcyc_per_line_delivery_c = %3.2f", + dml_print("DML_DLG: %s: refcyc_per_line_delivery_c = %3.2f\n", __func__, refcyc_per_line_delivery_c); - - disp_dlg_regs->refcyc_per_line_delivery_pre_c = (unsigned int) dml_floor( - refcyc_per_line_delivery_pre_c); - disp_dlg_regs->refcyc_per_line_delivery_c = (unsigned int) dml_floor( - refcyc_per_line_delivery_c); - ASSERT(disp_dlg_regs->refcyc_per_line_delivery_pre_c < (unsigned int) dml_pow(2, 13)); ASSERT(disp_dlg_regs->refcyc_per_line_delivery_c < (unsigned int) dml_pow(2, 13)); } - disp_dlg_regs->chunk_hdl_adjust_cur0 = 3; - /* TTU - Luma / Chroma */ - if (access_dir) { /* vertical access */ + // TTU - Luma / Chroma + if (access_dir) { // vertical access scaler_rec_in_width_l = vp_height_l; scaler_rec_in_width_c = vp_height_c; } else { @@ -1957,167 +1253,264 @@ void dml_rq_dlg_get_dlg_params( scaler_rec_in_width_c = vp_width_c; } - refcyc_per_req_delivery_pre_l = get_refcyc_per_delivery( - mode_lib, + refcyc_per_req_delivery_pre_l = get_refcyc_per_delivery(mode_lib, refclk_freq_in_mhz, pclk_freq_in_mhz, + dst->odm_combine, full_recout_width, + dst->hactive, vratio_pre_l, hscale_pixel_rate_l, scaler_rec_in_width_l, - req_per_swath_ub_l); /* per req */ - refcyc_per_req_delivery_l = get_refcyc_per_delivery( - mode_lib, + req_per_swath_ub_l); // per req + refcyc_per_req_delivery_l = get_refcyc_per_delivery(mode_lib, refclk_freq_in_mhz, pclk_freq_in_mhz, + dst->odm_combine, full_recout_width, + dst->hactive, vratio_l, hscale_pixel_rate_l, scaler_rec_in_width_l, - req_per_swath_ub_l); /* per req */ + req_per_swath_ub_l); // per req - DTRACE( - "DLG: %s: refcyc_per_req_delivery_pre_l = %3.2f", + dml_print("DML_DLG: %s: refcyc_per_req_delivery_pre_l = %3.2f\n", __func__, refcyc_per_req_delivery_pre_l); - DTRACE( - "DLG: %s: refcyc_per_req_delivery_l = %3.2f", + dml_print("DML_DLG: %s: refcyc_per_req_delivery_l = %3.2f\n", __func__, refcyc_per_req_delivery_l); - disp_ttu_regs->refcyc_per_req_delivery_pre_l = (unsigned int) (refcyc_per_req_delivery_pre_l - * dml_pow(2, 10)); - disp_ttu_regs->refcyc_per_req_delivery_l = (unsigned int) (refcyc_per_req_delivery_l - * dml_pow(2, 10)); - ASSERT(refcyc_per_req_delivery_pre_l < dml_pow(2, 13)); ASSERT(refcyc_per_req_delivery_l < dml_pow(2, 13)); if (dual_plane) { - refcyc_per_req_delivery_pre_c = get_refcyc_per_delivery( - mode_lib, + refcyc_per_req_delivery_pre_c = get_refcyc_per_delivery(mode_lib, refclk_freq_in_mhz, pclk_freq_in_mhz, + dst->odm_combine, full_recout_width, + dst->hactive, vratio_pre_c, hscale_pixel_rate_c, scaler_rec_in_width_c, - req_per_swath_ub_c); /* per req */ - refcyc_per_req_delivery_c = get_refcyc_per_delivery( - mode_lib, + req_per_swath_ub_c); // per req + refcyc_per_req_delivery_c = get_refcyc_per_delivery(mode_lib, refclk_freq_in_mhz, pclk_freq_in_mhz, + dst->odm_combine, full_recout_width, + dst->hactive, vratio_c, hscale_pixel_rate_c, scaler_rec_in_width_c, - req_per_swath_ub_c); /* per req */ + req_per_swath_ub_c); // per req - DTRACE( - "DLG: %s: refcyc_per_req_delivery_pre_c = %3.2f", + dml_print("DML_DLG: %s: refcyc_per_req_delivery_pre_c = %3.2f\n", __func__, refcyc_per_req_delivery_pre_c); - DTRACE( - "DLG: %s: refcyc_per_req_delivery_c = %3.2f", + dml_print("DML_DLG: %s: refcyc_per_req_delivery_c = %3.2f\n", __func__, refcyc_per_req_delivery_c); - disp_ttu_regs->refcyc_per_req_delivery_pre_c = - (unsigned int) (refcyc_per_req_delivery_pre_c * dml_pow(2, 10)); - disp_ttu_regs->refcyc_per_req_delivery_c = (unsigned int) (refcyc_per_req_delivery_c - * dml_pow(2, 10)); - ASSERT(refcyc_per_req_delivery_pre_c < dml_pow(2, 13)); ASSERT(refcyc_per_req_delivery_c < dml_pow(2, 13)); } - /* TTU - Cursor */ - hratios_cur0 = e2e_pipe_param.pipe.scale_ratio_depth.hscl_ratio; - cur0_src_width = e2e_pipe_param.pipe.src.cur0_src_width; /* cursor source width */ - cur0_bpp = (enum cursor_bpp) e2e_pipe_param.pipe.src.cur0_bpp; - cur0_req_size = 0; - cur0_req_width = 0; - cur0_width_ub = 0.0; - cur0_req_per_width = 0.0; - hactive_cur0 = 0.0; - - ASSERT(cur0_src_width <= 256); - - if (cur0_src_width > 0) { - unsigned int cur0_bit_per_pixel = 0; - - if (cur0_bpp == dm_cur_2bit) { - cur0_req_size = 64; /* byte */ - cur0_bit_per_pixel = 2; - } else { /* 32bit */ - cur0_bit_per_pixel = 32; - if (cur0_src_width >= 1 && cur0_src_width <= 16) - cur0_req_size = 64; - else if (cur0_src_width >= 17 && cur0_src_width <= 31) - cur0_req_size = 128; - else - cur0_req_size = 256; - } + // XFC + xfc_transfer_delay = get_xfc_transfer_delay(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); + xfc_precharge_delay = get_xfc_precharge_delay(mode_lib, + e2e_pipe_param, + num_pipes, + pipe_idx); + xfc_remote_surface_flip_latency = get_xfc_remote_surface_flip_latency(mode_lib, + e2e_pipe_param, + num_pipes, + pipe_idx); + xfc_dst_y_delta_drq_limit = xfc_remote_surface_flip_latency; + xfc_prefetch_margin = get_xfc_prefetch_margin(mode_lib, + e2e_pipe_param, + num_pipes, + pipe_idx); + + // TTU - Cursor + refcyc_per_req_delivery_pre_cur0 = 0.0; + refcyc_per_req_delivery_cur0 = 0.0; + if (src->num_cursors > 0) { + calculate_ttu_cursor(mode_lib, + &refcyc_per_req_delivery_pre_cur0, + &refcyc_per_req_delivery_cur0, + refclk_freq_in_mhz, + ref_freq_to_pix_freq, + hscale_pixel_rate_l, + scl->hscl_ratio, + vratio_pre_l, + vratio_l, + src->cur0_src_width, + (enum cursor_bpp)(src->cur0_bpp)); + } - cur0_req_width = (double) cur0_req_size / ((double) cur0_bit_per_pixel / 8.0); - cur0_width_ub = dml_ceil((double) cur0_src_width / (double) cur0_req_width) - * (double) cur0_req_width; - cur0_req_per_width = cur0_width_ub / (double) cur0_req_width; - hactive_cur0 = (double) cur0_src_width / hratios_cur0; /* FIXME: oswin to think about what to do for cursor */ + refcyc_per_req_delivery_pre_cur1 = 0.0; + refcyc_per_req_delivery_cur1 = 0.0; + if (src->num_cursors > 1) { + calculate_ttu_cursor(mode_lib, + &refcyc_per_req_delivery_pre_cur1, + &refcyc_per_req_delivery_cur1, + refclk_freq_in_mhz, + ref_freq_to_pix_freq, + hscale_pixel_rate_l, + scl->hscl_ratio, + vratio_pre_l, + vratio_l, + src->cur1_src_width, + (enum cursor_bpp)(src->cur1_bpp)); + } - if (vratio_pre_l <= 1.0) { - refcyc_per_req_delivery_pre_cur0 = hactive_cur0 * ref_freq_to_pix_freq - / (double) cur0_req_per_width; - } else { - refcyc_per_req_delivery_pre_cur0 = (double) refclk_freq_in_mhz - * (double) cur0_src_width / hscale_pixel_rate_l - / (double) cur0_req_per_width; - } + // TTU - Misc + // all hard-coded - disp_ttu_regs->refcyc_per_req_delivery_pre_cur0 = - (unsigned int) (refcyc_per_req_delivery_pre_cur0 * dml_pow(2, 10)); - ASSERT(refcyc_per_req_delivery_pre_cur0 < dml_pow(2, 13)); + // Assignment to register structures + disp_dlg_regs->dst_y_after_scaler = dst_y_after_scaler; // in terms of line + disp_dlg_regs->refcyc_x_after_scaler = dst_x_after_scaler * ref_freq_to_pix_freq; // in terms of refclk + ASSERT(disp_dlg_regs->refcyc_x_after_scaler < (unsigned int) dml_pow(2, 13)); + disp_dlg_regs->dst_y_prefetch = (unsigned int) (dst_y_prefetch * dml_pow(2, 2)); + disp_dlg_regs->dst_y_per_vm_vblank = (unsigned int) (dst_y_per_vm_vblank * dml_pow(2, 2)); + disp_dlg_regs->dst_y_per_row_vblank = (unsigned int) (dst_y_per_row_vblank * dml_pow(2, 2)); + disp_dlg_regs->dst_y_per_vm_flip = (unsigned int) (dst_y_per_vm_flip * dml_pow(2, 2)); + disp_dlg_regs->dst_y_per_row_flip = (unsigned int) (dst_y_per_row_flip * dml_pow(2, 2)); - if (vratio_l <= 1.0) { - refcyc_per_req_delivery_cur0 = hactive_cur0 * ref_freq_to_pix_freq - / (double) cur0_req_per_width; - } else { - refcyc_per_req_delivery_cur0 = (double) refclk_freq_in_mhz - * (double) cur0_src_width / hscale_pixel_rate_l - / (double) cur0_req_per_width; + disp_dlg_regs->vratio_prefetch = (unsigned int) (vratio_pre_l * dml_pow(2, 19)); + disp_dlg_regs->vratio_prefetch_c = (unsigned int) (vratio_pre_c * dml_pow(2, 19)); + + disp_dlg_regs->refcyc_per_pte_group_vblank_l = + (unsigned int) (dst_y_per_row_vblank * (double) htotal + * ref_freq_to_pix_freq / (double) dpte_groups_per_row_ub_l); + ASSERT(disp_dlg_regs->refcyc_per_pte_group_vblank_l < (unsigned int) dml_pow(2, 13)); + + if (dual_plane) { + disp_dlg_regs->refcyc_per_pte_group_vblank_c = (unsigned int) (dst_y_per_row_vblank + * (double) htotal * ref_freq_to_pix_freq + / (double) dpte_groups_per_row_ub_c); + ASSERT(disp_dlg_regs->refcyc_per_pte_group_vblank_c + < (unsigned int) dml_pow(2, 13)); + } + + disp_dlg_regs->refcyc_per_meta_chunk_vblank_l = + (unsigned int) (dst_y_per_row_vblank * (double) htotal + * ref_freq_to_pix_freq / (double) meta_chunks_per_row_ub_l); + ASSERT(disp_dlg_regs->refcyc_per_meta_chunk_vblank_l < (unsigned int) dml_pow(2, 13)); + + disp_dlg_regs->refcyc_per_meta_chunk_vblank_c = + disp_dlg_regs->refcyc_per_meta_chunk_vblank_l; // dcc for 4:2:0 is not supported in dcn1.0. assigned to be the same as _l for now + + disp_dlg_regs->refcyc_per_pte_group_flip_l = (unsigned int) (dst_y_per_row_flip * htotal + * ref_freq_to_pix_freq) / dpte_groups_per_row_ub_l; + disp_dlg_regs->refcyc_per_meta_chunk_flip_l = (unsigned int) (dst_y_per_row_flip * htotal + * ref_freq_to_pix_freq) / meta_chunks_per_row_ub_l; + + if (dual_plane) { + disp_dlg_regs->refcyc_per_pte_group_flip_c = (unsigned int) (dst_y_per_row_flip + * htotal * ref_freq_to_pix_freq) / dpte_groups_per_row_ub_c; + disp_dlg_regs->refcyc_per_meta_chunk_flip_c = (unsigned int) (dst_y_per_row_flip + * htotal * ref_freq_to_pix_freq) / meta_chunks_per_row_ub_c; + } + + disp_dlg_regs->dst_y_per_pte_row_nom_l = (unsigned int) ((double) dpte_row_height_l + / (double) vratio_l * dml_pow(2, 2)); + ASSERT(disp_dlg_regs->dst_y_per_pte_row_nom_l < (unsigned int) dml_pow(2, 17)); + + if (dual_plane) { + disp_dlg_regs->dst_y_per_pte_row_nom_c = (unsigned int) ((double) dpte_row_height_c + / (double) vratio_c * dml_pow(2, 2)); + if (disp_dlg_regs->dst_y_per_pte_row_nom_c >= (unsigned int) dml_pow(2, 17)) { + dml_print("DML_DLG: %s: Warning dst_y_per_pte_row_nom_c %u larger than supported by register format U15.2 %u\n", + __func__, + disp_dlg_regs->dst_y_per_pte_row_nom_c, + (unsigned int) dml_pow(2, 17) - 1); } + } - DTRACE("DLG: %s: cur0_req_width = %d", __func__, cur0_req_width); - DTRACE( - "DLG: %s: cur0_width_ub = %3.2f", - __func__, - cur0_width_ub); - DTRACE( - "DLG: %s: cur0_req_per_width = %3.2f", - __func__, - cur0_req_per_width); - DTRACE( - "DLG: %s: hactive_cur0 = %3.2f", - __func__, - hactive_cur0); - DTRACE( - "DLG: %s: refcyc_per_req_delivery_pre_cur0 = %3.2f", - __func__, - refcyc_per_req_delivery_pre_cur0); - DTRACE( - "DLG: %s: refcyc_per_req_delivery_cur0 = %3.2f", - __func__, - refcyc_per_req_delivery_cur0); + disp_dlg_regs->dst_y_per_meta_row_nom_l = (unsigned int) ((double) meta_row_height_l + / (double) vratio_l * dml_pow(2, 2)); + ASSERT(disp_dlg_regs->dst_y_per_meta_row_nom_l < (unsigned int) dml_pow(2, 17)); - disp_ttu_regs->refcyc_per_req_delivery_cur0 = - (unsigned int) (refcyc_per_req_delivery_cur0 * dml_pow(2, 10)); - ASSERT(refcyc_per_req_delivery_cur0 < dml_pow(2, 13)); - } else { - disp_ttu_regs->refcyc_per_req_delivery_pre_cur0 = 0; - disp_ttu_regs->refcyc_per_req_delivery_cur0 = 0; + disp_dlg_regs->dst_y_per_meta_row_nom_c = disp_dlg_regs->dst_y_per_meta_row_nom_l; // TODO: dcc for 4:2:0 is not supported in dcn1.0. assigned to be the same as _l for now + + disp_dlg_regs->refcyc_per_pte_group_nom_l = (unsigned int) ((double) dpte_row_height_l + / (double) vratio_l * (double) htotal * ref_freq_to_pix_freq + / (double) dpte_groups_per_row_ub_l); + if (disp_dlg_regs->refcyc_per_pte_group_nom_l >= (unsigned int) dml_pow(2, 23)) + disp_dlg_regs->refcyc_per_pte_group_nom_l = dml_pow(2, 23) - 1; + disp_dlg_regs->refcyc_per_meta_chunk_nom_l = (unsigned int) ((double) meta_row_height_l + / (double) vratio_l * (double) htotal * ref_freq_to_pix_freq + / (double) meta_chunks_per_row_ub_l); + if (disp_dlg_regs->refcyc_per_meta_chunk_nom_l >= (unsigned int) dml_pow(2, 23)) + disp_dlg_regs->refcyc_per_meta_chunk_nom_l = dml_pow(2, 23) - 1; + + if (dual_plane) { + disp_dlg_regs->refcyc_per_pte_group_nom_c = + (unsigned int) ((double) dpte_row_height_c / (double) vratio_c + * (double) htotal * ref_freq_to_pix_freq + / (double) dpte_groups_per_row_ub_c); + if (disp_dlg_regs->refcyc_per_pte_group_nom_c >= (unsigned int) dml_pow(2, 23)) + disp_dlg_regs->refcyc_per_pte_group_nom_c = dml_pow(2, 23) - 1; + + // TODO: Is this the right calculation? Does htotal need to be halved? + disp_dlg_regs->refcyc_per_meta_chunk_nom_c = + (unsigned int) ((double) meta_row_height_c / (double) vratio_c + * (double) htotal * ref_freq_to_pix_freq + / (double) meta_chunks_per_row_ub_c); + if (disp_dlg_regs->refcyc_per_meta_chunk_nom_c >= (unsigned int) dml_pow(2, 23)) + disp_dlg_regs->refcyc_per_meta_chunk_nom_c = dml_pow(2, 23) - 1; } - /* TTU - Misc */ + disp_dlg_regs->refcyc_per_line_delivery_pre_l = (unsigned int) dml_floor(refcyc_per_line_delivery_pre_l, + 1); + disp_dlg_regs->refcyc_per_line_delivery_l = (unsigned int) dml_floor(refcyc_per_line_delivery_l, + 1); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_pre_l < (unsigned int) dml_pow(2, 13)); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_l < (unsigned int) dml_pow(2, 13)); + + disp_dlg_regs->refcyc_per_line_delivery_pre_c = (unsigned int) dml_floor(refcyc_per_line_delivery_pre_c, + 1); + disp_dlg_regs->refcyc_per_line_delivery_c = (unsigned int) dml_floor(refcyc_per_line_delivery_c, + 1); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_pre_c < (unsigned int) dml_pow(2, 13)); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_c < (unsigned int) dml_pow(2, 13)); + + disp_dlg_regs->chunk_hdl_adjust_cur0 = 3; + disp_dlg_regs->dst_y_offset_cur0 = 0; + disp_dlg_regs->chunk_hdl_adjust_cur1 = 3; + disp_dlg_regs->dst_y_offset_cur1 = 0; + + disp_dlg_regs->xfc_reg_transfer_delay = xfc_transfer_delay; + disp_dlg_regs->xfc_reg_precharge_delay = xfc_precharge_delay; + disp_dlg_regs->xfc_reg_remote_surface_flip_latency = xfc_remote_surface_flip_latency; + disp_dlg_regs->xfc_reg_prefetch_margin = dml_ceil(xfc_prefetch_margin * refclk_freq_in_mhz, + 1); + + // slave has to have this value also set to off + if (src->xfc_enable && !src->xfc_slave) + disp_dlg_regs->dst_y_delta_drq_limit = dml_ceil(xfc_dst_y_delta_drq_limit, 1); + else + disp_dlg_regs->dst_y_delta_drq_limit = 0x7fff; // off + + disp_ttu_regs->refcyc_per_req_delivery_pre_l = (unsigned int) (refcyc_per_req_delivery_pre_l + * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_l = (unsigned int) (refcyc_per_req_delivery_l + * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_pre_c = (unsigned int) (refcyc_per_req_delivery_pre_c + * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_c = (unsigned int) (refcyc_per_req_delivery_c + * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_pre_cur0 = + (unsigned int) (refcyc_per_req_delivery_pre_cur0 * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_cur0 = (unsigned int) (refcyc_per_req_delivery_cur0 + * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_pre_cur1 = + (unsigned int) (refcyc_per_req_delivery_pre_cur1 * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_cur1 = (unsigned int) (refcyc_per_req_delivery_cur1 + * dml_pow(2, 10)); disp_ttu_regs->qos_level_low_wm = 0; ASSERT(disp_ttu_regs->qos_level_low_wm < dml_pow(2, 14)); disp_ttu_regs->qos_level_high_wm = (unsigned int) (4.0 * (double) htotal @@ -2139,118 +1532,232 @@ void dml_rq_dlg_get_dlg_params( print__dlg_regs_st(mode_lib, *disp_dlg_regs); } -void dml_rq_dlg_get_dlg_reg( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_dlg_regs_st *dlg_regs, - struct _vcs_dpi_display_ttu_regs_st *ttu_regs, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e_pipe_param, - const int unsigned num_pipes, - const int unsigned pipe_idx, +void dml_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib, + display_dlg_regs_st *dlg_regs, + display_ttu_regs_st *ttu_regs, + display_e2e_pipe_params_st *e2e_pipe_param, + const unsigned int num_pipes, + const unsigned int pipe_idx, const bool cstate_en, const bool pstate_en, const bool vm_en, - const bool iflip_en) + const bool ignore_viewport_pos, + const bool immediate_flip_support) { - struct _vcs_dpi_display_rq_params_st rq_param = {0}; - struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param = {0}; - struct _vcs_dpi_wm_calc_pipe_params_st *wm_param = mode_lib->wm_param; - struct _vcs_dpi_cstate_pstate_watermarks_st cstate_pstate_wm; - struct _vcs_dpi_display_dlg_prefetch_param_st prefetch_param; - double total_ret_bw; - double total_active_bw; - double total_prefetch_bw; - int unsigned total_flip_bytes; - int unsigned num_planes; - int i; - - memset(wm_param, 0, sizeof(mode_lib->wm_param)); - - /* Get watermark and Tex. */ - DTRACE("DLG: Start calculating system setting related parameters. num_pipes=%d", num_pipes); - num_planes = dml_wm_e2e_to_wm(mode_lib, e2e_pipe_param, num_pipes, wm_param); - - cstate_pstate_wm = dml_wm_cstate_pstate_e2e(mode_lib, e2e_pipe_param, num_pipes); - dlg_sys_param.t_mclk_wm_us = cstate_pstate_wm.pstate_change_us; - dlg_sys_param.t_sr_wm_us = cstate_pstate_wm.cstate_enter_plus_exit_us; - dlg_sys_param.t_urg_wm_us = dml_wm_urgent_e2e(mode_lib, e2e_pipe_param, num_pipes); - dlg_sys_param.t_srx_delay_us = mode_lib->ip.dcfclk_cstate_latency - / dml_wm_dcfclk_deepsleep_mhz_e2e(mode_lib, e2e_pipe_param, num_pipes); - dlg_sys_param.t_extra_us = dml_wm_urgent_extra(mode_lib, wm_param, num_planes); - dlg_sys_param.deepsleep_dcfclk_mhz = dml_wm_dcfclk_deepsleep_mhz_e2e( - mode_lib, + display_rq_params_st rq_param = {0}; + display_dlg_sys_params_st dlg_sys_param = {0}; + + // Get watermark and Tex. + dlg_sys_param.t_urg_wm_us = get_wm_urgent(mode_lib, e2e_pipe_param, num_pipes); + dlg_sys_param.deepsleep_dcfclk_mhz = get_clk_dcf_deepsleep(mode_lib, e2e_pipe_param, num_pipes); + dlg_sys_param.t_extra_us = get_urgent_extra_latency(mode_lib, e2e_pipe_param, num_pipes); + dlg_sys_param.mem_trip_us = get_wm_memory_trip(mode_lib, e2e_pipe_param, num_pipes); + dlg_sys_param.t_mclk_wm_us = get_wm_dram_clock_change(mode_lib, e2e_pipe_param, num_pipes); + dlg_sys_param.t_sr_wm_us = get_wm_stutter_enter_exit(mode_lib, e2e_pipe_param, num_pipes); + dlg_sys_param.total_flip_bw = get_total_immediate_flip_bw(mode_lib, + e2e_pipe_param, + num_pipes); + dlg_sys_param.total_flip_bytes = get_total_immediate_flip_bytes(mode_lib, + e2e_pipe_param, + num_pipes); + dlg_sys_param.t_srx_delay_us = mode_lib->ip.dcfclk_cstate_latency + / dlg_sys_param.deepsleep_dcfclk_mhz; // TODO: Deprecated print__dlg_sys_params_st(mode_lib, dlg_sys_param); - DTRACE("DLG: Start calculating total prefetch bw. num_planes=%d", num_planes); - total_ret_bw = dml_wm_calc_return_bw(mode_lib, wm_param, num_planes); - total_active_bw = dml_wm_calc_total_data_read_bw(mode_lib, wm_param, num_planes); - total_prefetch_bw = 0.0; - total_flip_bytes = 0; - - for (i = 0; i < num_pipes; i++) { - dml_rq_dlg_get_rq_params(mode_lib, &rq_param, e2e_pipe_param[i].pipe.src); - dml_rq_dlg_get_dlg_params_prefetch( - mode_lib, - &prefetch_param, - rq_param.dlg, - dlg_sys_param, - e2e_pipe_param[i], - cstate_en, - pstate_en, - vm_en); - total_prefetch_bw += prefetch_param.prefetch_bw; - total_flip_bytes += prefetch_param.flip_bytes; - DTRACE( - "DLG: pipe=%d, total_prefetch_bw=%3.2f total_flip_bytes=%d", - i, - total_prefetch_bw, - total_flip_bytes); - } - - dlg_sys_param.total_flip_bw = total_ret_bw - dml_max(total_active_bw, total_prefetch_bw); - - DTRACE("DLG: Done calculating total prefetch bw"); - DTRACE("DLG: num_pipes = %d", num_pipes); - DTRACE("DLG: total_ret_bw = %3.2f", total_ret_bw); - DTRACE("DLG: total_active_bw = %3.2f", total_active_bw); - DTRACE("DLG: total_prefetch_bw = %3.2f", total_prefetch_bw); - DTRACE("DLG: total_flip_bw = %3.2f", dlg_sys_param.total_flip_bw); - - if (dlg_sys_param.total_flip_bw < 0.0 && iflip_en) { - DTRACE("WARNING_DLG Insufficient bw for immediate flip!"); - dlg_sys_param.total_flip_bw = 0; - } + // system parameter calculation done - dlg_sys_param.total_flip_bytes = total_flip_bytes; - DTRACE("DLG: total_flip_bytes = %d", dlg_sys_param.total_flip_bytes); - DTRACE("DLG: Done calculating system setting related parameters."); - - /* system parameter calculation done */ - - DTRACE("DLG: Calculation for pipe[%d] start", pipe_idx); + dml_print("DML_DLG: Calculation for pipe[%d] start\n\n", pipe_idx); dml_rq_dlg_get_rq_params(mode_lib, &rq_param, e2e_pipe_param[pipe_idx].pipe.src); - dml_rq_dlg_get_dlg_params( - mode_lib, + dml_rq_dlg_get_dlg_params(mode_lib, + e2e_pipe_param, + num_pipes, + pipe_idx, dlg_regs, ttu_regs, rq_param.dlg, dlg_sys_param, - e2e_pipe_param[pipe_idx], cstate_en, pstate_en, vm_en, - iflip_en); - DTRACE("DLG: Calculation for pipe[%d] end", pipe_idx); + ignore_viewport_pos, + immediate_flip_support); + dml_print("DML_DLG: Calculation for pipe[%d] end\n", pipe_idx); } -void dml_rq_dlg_get_arb_params( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_arb_params_st *arb_param) +void dml_rq_dlg_get_arb_params(struct display_mode_lib *mode_lib, display_arb_params_st *arb_param) { memset(arb_param, 0, sizeof(*arb_param)); arb_param->max_req_outstanding = 256; arb_param->min_req_outstanding = 68; arb_param->sat_level_us = 60; } + +void calculate_ttu_cursor(struct display_mode_lib *mode_lib, + double *refcyc_per_req_delivery_pre_cur, + double *refcyc_per_req_delivery_cur, + double refclk_freq_in_mhz, + double ref_freq_to_pix_freq, + double hscale_pixel_rate_l, + double hscl_ratio, + double vratio_pre_l, + double vratio_l, + unsigned int cur_width, + enum cursor_bpp cur_bpp) +{ + unsigned int cur_src_width = cur_width; + unsigned int cur_req_size = 0; + unsigned int cur_req_width = 0; + double cur_width_ub = 0.0; + double cur_req_per_width = 0.0; + double hactive_cur = 0.0; + + ASSERT(cur_src_width <= 256); + + *refcyc_per_req_delivery_pre_cur = 0.0; + *refcyc_per_req_delivery_cur = 0.0; + if (cur_src_width > 0) { + unsigned int cur_bit_per_pixel = 0; + + if (cur_bpp == dm_cur_2bit) { + cur_req_size = 64; // byte + cur_bit_per_pixel = 2; + } else { // 32bit + cur_bit_per_pixel = 32; + if (cur_src_width >= 1 && cur_src_width <= 16) + cur_req_size = 64; + else if (cur_src_width >= 17 && cur_src_width <= 31) + cur_req_size = 128; + else + cur_req_size = 256; + } + + cur_req_width = (double) cur_req_size / ((double) cur_bit_per_pixel / 8.0); + cur_width_ub = dml_ceil((double) cur_src_width / (double) cur_req_width, 1) + * (double) cur_req_width; + cur_req_per_width = cur_width_ub / (double) cur_req_width; + hactive_cur = (double) cur_src_width / hscl_ratio; // FIXME: oswin to think about what to do for cursor + + if (vratio_pre_l <= 1.0) { + *refcyc_per_req_delivery_pre_cur = hactive_cur * ref_freq_to_pix_freq + / (double) cur_req_per_width; + } else { + *refcyc_per_req_delivery_pre_cur = (double) refclk_freq_in_mhz + * (double) cur_src_width / hscale_pixel_rate_l + / (double) cur_req_per_width; + } + + ASSERT(*refcyc_per_req_delivery_pre_cur < dml_pow(2, 13)); + + if (vratio_l <= 1.0) { + *refcyc_per_req_delivery_cur = hactive_cur * ref_freq_to_pix_freq + / (double) cur_req_per_width; + } else { + *refcyc_per_req_delivery_cur = (double) refclk_freq_in_mhz + * (double) cur_src_width / hscale_pixel_rate_l + / (double) cur_req_per_width; + } + + dml_print("DML_DLG: %s: cur_req_width = %d\n", + __func__, + cur_req_width); + dml_print("DML_DLG: %s: cur_width_ub = %3.2f\n", + __func__, + cur_width_ub); + dml_print("DML_DLG: %s: cur_req_per_width = %3.2f\n", + __func__, + cur_req_per_width); + dml_print("DML_DLG: %s: hactive_cur = %3.2f\n", + __func__, + hactive_cur); + dml_print("DML_DLG: %s: refcyc_per_req_delivery_pre_cur = %3.2f\n", + __func__, + *refcyc_per_req_delivery_pre_cur); + dml_print("DML_DLG: %s: refcyc_per_req_delivery_cur = %3.2f\n", + __func__, + *refcyc_per_req_delivery_cur); + + ASSERT(*refcyc_per_req_delivery_cur < dml_pow(2, 13)); + } +} + +unsigned int dml_rq_dlg_get_calculated_vstartup(struct display_mode_lib *mode_lib, + display_e2e_pipe_params_st *e2e_pipe_param, + const unsigned int num_pipes, + const unsigned int pipe_idx) +{ + unsigned int vstartup_pipe[DC__NUM_PIPES__MAX]; + bool visited[DC__NUM_PIPES__MAX]; + unsigned int pipe_inst = 0; + unsigned int i, j, k; + + for (k = 0; k < num_pipes; ++k) + visited[k] = false; + + for (i = 0; i < num_pipes; i++) { + if (e2e_pipe_param[i].pipe.src.is_hsplit && !visited[i]) { + unsigned int grp = e2e_pipe_param[i].pipe.src.hsplit_grp; + + for (j = i; j < num_pipes; j++) { + if (e2e_pipe_param[j].pipe.src.hsplit_grp == grp + && e2e_pipe_param[j].pipe.src.is_hsplit + && !visited[j]) { + vstartup_pipe[j] = get_vstartup_calculated(mode_lib, + e2e_pipe_param, + num_pipes, + pipe_inst); + visited[j] = true; + } + } + + pipe_inst++; + } + + if (!visited[i]) { + vstartup_pipe[i] = get_vstartup_calculated(mode_lib, + e2e_pipe_param, + num_pipes, + pipe_inst); + visited[i] = true; + pipe_inst++; + } + } + + return vstartup_pipe[pipe_idx]; + +} + +void dml_rq_dlg_get_row_heights(struct display_mode_lib *mode_lib, + unsigned int *o_dpte_row_height, + unsigned int *o_meta_row_height, + unsigned int vp_width, + unsigned int data_pitch, + int source_format, + int tiling, + int macro_tile_size, + int source_scan, + int is_chroma) +{ + display_data_rq_dlg_params_st rq_dlg_param; + display_data_rq_misc_params_st rq_misc_param; + display_data_rq_sizing_params_st rq_sizing_param; + + get_meta_and_pte_attr(mode_lib, + &rq_dlg_param, + &rq_misc_param, + &rq_sizing_param, + vp_width, + 0, // dummy + data_pitch, + 0, // dummy + source_format, + tiling, + macro_tile_size, + source_scan, + is_chroma); + + *o_dpte_row_height = rq_dlg_param.dpte_row_height; + *o_meta_row_height = rq_dlg_param.meta_row_height; +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.h b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.h index e63b13fb2887..efdd4c73d8f3 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.h @@ -22,103 +22,114 @@ * Authors: AMD * */ -#ifndef __DISPLAY_RQ_DLG_CALC_H__ -#define __DISPLAY_RQ_DLG_CALC_H__ + +#ifndef __DML2_DISPLAY_RQ_DLG_CALC_H__ +#define __DML2_DISPLAY_RQ_DLG_CALC_H__ #include "dml_common_defs.h" #include "display_rq_dlg_helpers.h" struct display_mode_lib; -void extract_rq_regs( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_regs_st *rq_regs, - const struct _vcs_dpi_display_rq_params_st rq_param); -/* Function: dml_rq_dlg_get_rq_params - * Calculate requestor related parameters that register definition agnostic - * (i.e. this layer does try to separate real values from register defintion) - * Input: - * pipe_src_param - pipe source configuration (e.g. vp, pitch, etc.) - * Output: - * rq_param - values that can be used to setup RQ (e.g. swath_height, plane1_addr, etc.) - */ +// Function: dml_rq_dlg_get_rq_params +// Calculate requestor related parameters that register definition agnostic +// (i.e. this layer does try to separate real values from register definition) +// Input: +// pipe_src_param - pipe source configuration (e.g. vp, pitch, etc.) +// Output: +// rq_param - values that can be used to setup RQ (e.g. swath_height, plane1_addr, etc.) +// void dml_rq_dlg_get_rq_params( struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_params_st *rq_param, - const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param); + display_rq_params_st *rq_param, + const display_pipe_source_params_st pipe_src_param); -/* Function: dml_rq_dlg_get_rq_reg - * Main entry point for test to get the register values out of this DML class. - * This function calls <get_rq_param> and <extract_rq_regs> fucntions to calculate - * and then populate the rq_regs struct - * Input: - * pipe_src_param - pipe source configuration (e.g. vp, pitch, etc.) - * Output: - * rq_regs - struct that holds all the RQ registers field value. - * See also: <display_rq_regs_st> - */ +// Function: dml_rq_dlg_get_rq_reg +// Main entry point for test to get the register values out of this DML class. +// This function calls <get_rq_param> and <extract_rq_regs> fucntions to calculate +// and then populate the rq_regs struct +// Input: +// pipe_src_param - pipe source configuration (e.g. vp, pitch, etc.) +// Output: +// rq_regs - struct that holds all the RQ registers field value. +// See also: <display_rq_regs_st> void dml_rq_dlg_get_rq_reg( struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_regs_st *rq_regs, - const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param); + display_rq_regs_st *rq_regs, + const display_pipe_source_params_st pipe_src_param); -/* Function: dml_rq_dlg_get_dlg_params - * Calculate deadline related parameters - */ -void dml_rq_dlg_get_dlg_params( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_dlg_regs_st *dlg_regs, - struct _vcs_dpi_display_ttu_regs_st *ttu_regs, - const struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param, - const struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param, - const struct _vcs_dpi_display_e2e_pipe_params_st e2e_pipe_param, +// Function: dml_rq_dlg_get_dlg_params +// Calculate deadline related parameters +// +void dml_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *e2e_pipe_param, + const unsigned int num_pipes, + const unsigned int pipe_idx, + display_dlg_regs_st *disp_dlg_regs, + display_ttu_regs_st *disp_ttu_regs, + const display_rq_dlg_params_st rq_dlg_param, + const display_dlg_sys_params_st dlg_sys_param, const bool cstate_en, const bool pstate_en, const bool vm_en, - const bool iflip_en); + const bool ignore_viewport_pos, + const bool immediate_flip_support); -/* Function: dml_rq_dlg_get_dlg_param_prefetch - * For flip_bw programming guide change, now dml needs to calculate the flip_bytes and prefetch_bw - * for ALL pipes and use this info to calculate the prefetch programming. - * Output: prefetch_param.prefetch_bw and flip_bytes - */ +// Function: dml_rq_dlg_get_dlg_param_prefetch +// For flip_bw programming guide change, now dml needs to calculate the flip_bytes and prefetch_bw +// for ALL pipes and use this info to calculate the prefetch programming. +// Output: prefetch_param.prefetch_bw and flip_bytes void dml_rq_dlg_get_dlg_params_prefetch( struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_dlg_prefetch_param_st *prefetch_param, - struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param, - struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param, - struct _vcs_dpi_display_e2e_pipe_params_st e2e_pipe_param, + display_dlg_prefetch_param_st *prefetch_param, + display_rq_dlg_params_st rq_dlg_param, + display_dlg_sys_params_st dlg_sys_param, + display_e2e_pipe_params_st e2e_pipe_param, const bool cstate_en, const bool pstate_en, const bool vm_en); -/* Function: dml_rq_dlg_get_dlg_reg - * Calculate and return DLG and TTU register struct given the system setting - * Output: - * dlg_regs - output DLG register struct - * ttu_regs - output DLG TTU register struct - * Input: - * e2e_pipe_param - "compacted" array of e2e pipe param struct - * num_pipes - num of active "pipe" or "route" - * pipe_idx - index that identifies the e2e_pipe_param that corresponding to this dlg - * cstate - 0: when calculate min_ttu_vblank it is assumed cstate is not required. 1: Normal mode, cstate is considered. - * Added for legacy or unrealistic timing tests. - */ +// Function: dml_rq_dlg_get_dlg_reg +// Calculate and return DLG and TTU register struct given the system setting +// Output: +// dlg_regs - output DLG register struct +// ttu_regs - output DLG TTU register struct +// Input: +// e2e_pipe_param - "compacted" array of e2e pipe param struct +// num_pipes - num of active "pipe" or "route" +// pipe_idx - index that identifies the e2e_pipe_param that corresponding to this dlg +// cstate - 0: when calculate min_ttu_vblank it is assumed cstate is not required. 1: Normal mode, cstate is considered. +// Added for legacy or unrealistic timing tests. void dml_rq_dlg_get_dlg_reg( struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_dlg_regs_st *dlg_regs, - struct _vcs_dpi_display_ttu_regs_st *ttu_regs, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e_pipe_param, + display_dlg_regs_st *dlg_regs, + display_ttu_regs_st *ttu_regs, + display_e2e_pipe_params_st *e2e_pipe_param, const unsigned int num_pipes, const unsigned int pipe_idx, const bool cstate_en, const bool pstate_en, const bool vm_en, - const bool iflip_en); + const bool ignore_viewport_pos, + const bool immediate_flip_support); -/* Function: dml_rq_dlg_get_row_heights - * Calculate dpte and meta row heights - */ +// Function: dml_rq_dlg_get_calculated_vstartup +// Calculate and return vstartup +// Output: +// unsigned int vstartup +// Input: +// e2e_pipe_param - "compacted" array of e2e pipe param struct +// num_pipes - num of active "pipe" or "route" +// pipe_idx - index that identifies the e2e_pipe_param that corresponding to this dlg +// NOTE: this MUST be called after setting the prefetch mode! +unsigned int dml_rq_dlg_get_calculated_vstartup( + struct display_mode_lib *mode_lib, + display_e2e_pipe_params_st *e2e_pipe_param, + const unsigned int num_pipes, + const unsigned int pipe_idx); + +// Function: dml_rq_dlg_get_row_heights +// Calculate dpte and meta row heights void dml_rq_dlg_get_row_heights( struct display_mode_lib *mode_lib, unsigned int *o_dpte_row_height, @@ -131,9 +142,7 @@ void dml_rq_dlg_get_row_heights( int source_scan, int is_chroma); -/* Function: dml_rq_dlg_get_arb_params */ -void dml_rq_dlg_get_arb_params( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_arb_params_st *arb_param); +// Function: dml_rq_dlg_get_arb_params +void dml_rq_dlg_get_arb_params(struct display_mode_lib *mode_lib, display_arb_params_st *arb_param); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c index 3dc11366cd36..189052e911fc 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c @@ -25,296 +25,368 @@ #include "display_rq_dlg_helpers.h" -void print__rq_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_params_st rq_param) +void print__rq_params_st(struct display_mode_lib *mode_lib, display_rq_params_st rq_param) { - DTRACE("RQ_DLG_CALC: *************************** "); - DTRACE("RQ_DLG_CALC: DISPLAY_RQ_PARAM_ST"); - DTRACE("RQ_DLG_CALC: <LUMA>"); + dml_print("DML_RQ_DLG_CALC: ***************************\n"); + dml_print("DML_RQ_DLG_CALC: DISPLAY_RQ_PARAM_ST\n"); + dml_print("DML_RQ_DLG_CALC: <LUMA>\n"); print__data_rq_sizing_params_st(mode_lib, rq_param.sizing.rq_l); - DTRACE("RQ_DLG_CALC: <CHROMA> === "); + dml_print("DML_RQ_DLG_CALC: <CHROMA> ===\n"); print__data_rq_sizing_params_st(mode_lib, rq_param.sizing.rq_c); - DTRACE("RQ_DLG_CALC: <LUMA>"); + dml_print("DML_RQ_DLG_CALC: <LUMA>\n"); print__data_rq_dlg_params_st(mode_lib, rq_param.dlg.rq_l); - DTRACE("RQ_DLG_CALC: <CHROMA>"); + dml_print("DML_RQ_DLG_CALC: <CHROMA>\n"); print__data_rq_dlg_params_st(mode_lib, rq_param.dlg.rq_c); - DTRACE("RQ_DLG_CALC: <LUMA>"); + dml_print("DML_RQ_DLG_CALC: <LUMA>\n"); print__data_rq_misc_params_st(mode_lib, rq_param.misc.rq_l); - DTRACE("RQ_DLG_CALC: <CHROMA>"); + dml_print("DML_RQ_DLG_CALC: <CHROMA>\n"); print__data_rq_misc_params_st(mode_lib, rq_param.misc.rq_c); - DTRACE("RQ_DLG_CALC: *************************** "); + dml_print("DML_RQ_DLG_CALC: ***************************\n"); } -void print__data_rq_sizing_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_data_rq_sizing_params_st rq_sizing) +void print__data_rq_sizing_params_st(struct display_mode_lib *mode_lib, display_data_rq_sizing_params_st rq_sizing) { - DTRACE("RQ_DLG_CALC: ===================================== "); - DTRACE("RQ_DLG_CALC: DISPLAY_DATA_RQ_SIZING_PARAM_ST"); - DTRACE("RQ_DLG_CALC: chunk_bytes = %0d", rq_sizing.chunk_bytes); - DTRACE("RQ_DLG_CALC: min_chunk_bytes = %0d", rq_sizing.min_chunk_bytes); - DTRACE("RQ_DLG_CALC: meta_chunk_bytes = %0d", rq_sizing.meta_chunk_bytes); - DTRACE("RQ_DLG_CALC: min_meta_chunk_bytes = %0d", rq_sizing.min_meta_chunk_bytes); - DTRACE("RQ_DLG_CALC: mpte_group_bytes = %0d", rq_sizing.mpte_group_bytes); - DTRACE("RQ_DLG_CALC: dpte_group_bytes = %0d", rq_sizing.dpte_group_bytes); - DTRACE("RQ_DLG_CALC: ===================================== "); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); + dml_print("DML_RQ_DLG_CALC: DISPLAY_DATA_RQ_SIZING_PARAM_ST\n"); + dml_print("DML_RQ_DLG_CALC: chunk_bytes = %0d\n", rq_sizing.chunk_bytes); + dml_print("DML_RQ_DLG_CALC: min_chunk_bytes = %0d\n", rq_sizing.min_chunk_bytes); + dml_print("DML_RQ_DLG_CALC: meta_chunk_bytes = %0d\n", rq_sizing.meta_chunk_bytes); + dml_print( + "DML_RQ_DLG_CALC: min_meta_chunk_bytes = %0d\n", + rq_sizing.min_meta_chunk_bytes); + dml_print("DML_RQ_DLG_CALC: mpte_group_bytes = %0d\n", rq_sizing.mpte_group_bytes); + dml_print("DML_RQ_DLG_CALC: dpte_group_bytes = %0d\n", rq_sizing.dpte_group_bytes); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__data_rq_dlg_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_data_rq_dlg_params_st rq_dlg_param) +void print__data_rq_dlg_params_st(struct display_mode_lib *mode_lib, display_data_rq_dlg_params_st rq_dlg_param) { - DTRACE("RQ_DLG_CALC: ===================================== "); - DTRACE("RQ_DLG_CALC: DISPLAY_DATA_RQ_DLG_PARAM_ST"); - DTRACE("RQ_DLG_CALC: swath_width_ub = %0d", rq_dlg_param.swath_width_ub); - DTRACE("RQ_DLG_CALC: swath_height = %0d", rq_dlg_param.swath_height); - DTRACE("RQ_DLG_CALC: req_per_swath_ub = %0d", rq_dlg_param.req_per_swath_ub); - DTRACE( - "RQ_DLG_CALC: meta_pte_bytes_per_frame_ub = %0d", + dml_print("DML_RQ_DLG_CALC: =====================================\n"); + dml_print("DML_RQ_DLG_CALC: DISPLAY_DATA_RQ_DLG_PARAM_ST\n"); + dml_print( + "DML_RQ_DLG_CALC: swath_width_ub = %0d\n", + rq_dlg_param.swath_width_ub); + dml_print( + "DML_RQ_DLG_CALC: swath_height = %0d\n", + rq_dlg_param.swath_height); + dml_print( + "DML_RQ_DLG_CALC: req_per_swath_ub = %0d\n", + rq_dlg_param.req_per_swath_ub); + dml_print( + "DML_RQ_DLG_CALC: meta_pte_bytes_per_frame_ub = %0d\n", rq_dlg_param.meta_pte_bytes_per_frame_ub); - DTRACE( - "RQ_DLG_CALC: dpte_req_per_row_ub = %0d", + dml_print( + "DML_RQ_DLG_CALC: dpte_req_per_row_ub = %0d\n", rq_dlg_param.dpte_req_per_row_ub); - DTRACE( - "RQ_DLG_CALC: dpte_groups_per_row_ub = %0d", + dml_print( + "DML_RQ_DLG_CALC: dpte_groups_per_row_ub = %0d\n", rq_dlg_param.dpte_groups_per_row_ub); - DTRACE("RQ_DLG_CALC: dpte_row_height = %0d", rq_dlg_param.dpte_row_height); - DTRACE( - "RQ_DLG_CALC: dpte_bytes_per_row_ub = %0d", + dml_print( + "DML_RQ_DLG_CALC: dpte_row_height = %0d\n", + rq_dlg_param.dpte_row_height); + dml_print( + "DML_RQ_DLG_CALC: dpte_bytes_per_row_ub = %0d\n", rq_dlg_param.dpte_bytes_per_row_ub); - DTRACE( - "RQ_DLG_CALC: meta_chunks_per_row_ub = %0d", + dml_print( + "DML_RQ_DLG_CALC: meta_chunks_per_row_ub = %0d\n", rq_dlg_param.meta_chunks_per_row_ub); - DTRACE( - "RQ_DLG_CALC: meta_req_per_row_ub = %0d", + dml_print( + "DML_RQ_DLG_CALC: meta_req_per_row_ub = %0d\n", rq_dlg_param.meta_req_per_row_ub); - DTRACE("RQ_DLG_CALC: meta_row_height = %0d", rq_dlg_param.meta_row_height); - DTRACE( - "RQ_DLG_CALC: meta_bytes_per_row_ub = %0d", + dml_print( + "DML_RQ_DLG_CALC: meta_row_height = %0d\n", + rq_dlg_param.meta_row_height); + dml_print( + "DML_RQ_DLG_CALC: meta_bytes_per_row_ub = %0d\n", rq_dlg_param.meta_bytes_per_row_ub); - DTRACE("RQ_DLG_CALC: ===================================== "); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__data_rq_misc_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_data_rq_misc_params_st rq_misc_param) +void print__data_rq_misc_params_st(struct display_mode_lib *mode_lib, display_data_rq_misc_params_st rq_misc_param) { - DTRACE("RQ_DLG_CALC: ===================================== "); - DTRACE("RQ_DLG_CALC: DISPLAY_DATA_RQ_MISC_PARAM_ST"); - DTRACE("RQ_DLG_CALC: full_swath_bytes = %0d", rq_misc_param.full_swath_bytes); - DTRACE("RQ_DLG_CALC: stored_swath_bytes = %0d", rq_misc_param.stored_swath_bytes); - DTRACE("RQ_DLG_CALC: blk256_width = %0d", rq_misc_param.blk256_width); - DTRACE("RQ_DLG_CALC: blk256_height = %0d", rq_misc_param.blk256_height); - DTRACE("RQ_DLG_CALC: req_width = %0d", rq_misc_param.req_width); - DTRACE("RQ_DLG_CALC: req_height = %0d", rq_misc_param.req_height); - DTRACE("RQ_DLG_CALC: ===================================== "); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); + dml_print("DML_RQ_DLG_CALC: DISPLAY_DATA_RQ_MISC_PARAM_ST\n"); + dml_print( + "DML_RQ_DLG_CALC: full_swath_bytes = %0d\n", + rq_misc_param.full_swath_bytes); + dml_print( + "DML_RQ_DLG_CALC: stored_swath_bytes = %0d\n", + rq_misc_param.stored_swath_bytes); + dml_print("DML_RQ_DLG_CALC: blk256_width = %0d\n", rq_misc_param.blk256_width); + dml_print("DML_RQ_DLG_CALC: blk256_height = %0d\n", rq_misc_param.blk256_height); + dml_print("DML_RQ_DLG_CALC: req_width = %0d\n", rq_misc_param.req_width); + dml_print("DML_RQ_DLG_CALC: req_height = %0d\n", rq_misc_param.req_height); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__rq_dlg_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param) +void print__rq_dlg_params_st(struct display_mode_lib *mode_lib, display_rq_dlg_params_st rq_dlg_param) { - DTRACE("RQ_DLG_CALC: ===================================== "); - DTRACE("RQ_DLG_CALC: DISPLAY_RQ_DLG_PARAM_ST"); - DTRACE("RQ_DLG_CALC: <LUMA> "); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); + dml_print("DML_RQ_DLG_CALC: DISPLAY_RQ_DLG_PARAM_ST\n"); + dml_print("DML_RQ_DLG_CALC: <LUMA>\n"); print__data_rq_dlg_params_st(mode_lib, rq_dlg_param.rq_l); - DTRACE("RQ_DLG_CALC: <CHROMA> "); + dml_print("DML_RQ_DLG_CALC: <CHROMA>\n"); print__data_rq_dlg_params_st(mode_lib, rq_dlg_param.rq_c); - DTRACE("RQ_DLG_CALC: ===================================== "); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__dlg_sys_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param) +void print__dlg_sys_params_st(struct display_mode_lib *mode_lib, display_dlg_sys_params_st dlg_sys_param) { - DTRACE("RQ_DLG_CALC: ===================================== "); - DTRACE("RQ_DLG_CALC: DISPLAY_RQ_DLG_PARAM_ST"); - DTRACE("RQ_DLG_CALC: t_mclk_wm_us = %3.2f", dlg_sys_param.t_mclk_wm_us); - DTRACE("RQ_DLG_CALC: t_urg_wm_us = %3.2f", dlg_sys_param.t_urg_wm_us); - DTRACE("RQ_DLG_CALC: t_sr_wm_us = %3.2f", dlg_sys_param.t_sr_wm_us); - DTRACE("RQ_DLG_CALC: t_extra_us = %3.2f", dlg_sys_param.t_extra_us); - DTRACE("RQ_DLG_CALC: t_srx_delay_us = %3.2f", dlg_sys_param.t_srx_delay_us); - DTRACE("RQ_DLG_CALC: deepsleep_dcfclk_mhz = %3.2f", dlg_sys_param.deepsleep_dcfclk_mhz); - DTRACE("RQ_DLG_CALC: ===================================== "); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); + dml_print("DML_RQ_DLG_CALC: DISPLAY_RQ_DLG_PARAM_ST\n"); + dml_print("DML_RQ_DLG_CALC: t_mclk_wm_us = %3.2f\n", dlg_sys_param.t_mclk_wm_us); + dml_print("DML_RQ_DLG_CALC: t_urg_wm_us = %3.2f\n", dlg_sys_param.t_urg_wm_us); + dml_print("DML_RQ_DLG_CALC: t_sr_wm_us = %3.2f\n", dlg_sys_param.t_sr_wm_us); + dml_print("DML_RQ_DLG_CALC: t_extra_us = %3.2f\n", dlg_sys_param.t_extra_us); + dml_print( + "DML_RQ_DLG_CALC: t_srx_delay_us = %3.2f\n", + dlg_sys_param.t_srx_delay_us); + dml_print( + "DML_RQ_DLG_CALC: deepsleep_dcfclk_mhz = %3.2f\n", + dlg_sys_param.deepsleep_dcfclk_mhz); + dml_print( + "DML_RQ_DLG_CALC: total_flip_bw = %3.2f\n", + dlg_sys_param.total_flip_bw); + dml_print( + "DML_RQ_DLG_CALC: total_flip_bytes = %i\n", + dlg_sys_param.total_flip_bytes); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__data_rq_regs_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_data_rq_regs_st rq_regs) +void print__data_rq_regs_st(struct display_mode_lib *mode_lib, display_data_rq_regs_st rq_regs) { - DTRACE("RQ_DLG_CALC: ===================================== "); - DTRACE("RQ_DLG_CALC: DISPLAY_DATA_RQ_REGS_ST"); - DTRACE("RQ_DLG_CALC: chunk_size = 0x%0x", rq_regs.chunk_size); - DTRACE("RQ_DLG_CALC: min_chunk_size = 0x%0x", rq_regs.min_chunk_size); - DTRACE("RQ_DLG_CALC: meta_chunk_size = 0x%0x", rq_regs.meta_chunk_size); - DTRACE("RQ_DLG_CALC: min_meta_chunk_size = 0x%0x", rq_regs.min_meta_chunk_size); - DTRACE("RQ_DLG_CALC: dpte_group_size = 0x%0x", rq_regs.dpte_group_size); - DTRACE("RQ_DLG_CALC: mpte_group_size = 0x%0x", rq_regs.mpte_group_size); - DTRACE("RQ_DLG_CALC: swath_height = 0x%0x", rq_regs.swath_height); - DTRACE("RQ_DLG_CALC: pte_row_height_linear = 0x%0x", rq_regs.pte_row_height_linear); - DTRACE("RQ_DLG_CALC: ===================================== "); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); + dml_print("DML_RQ_DLG_CALC: DISPLAY_DATA_RQ_REGS_ST\n"); + dml_print("DML_RQ_DLG_CALC: chunk_size = 0x%0x\n", rq_regs.chunk_size); + dml_print("DML_RQ_DLG_CALC: min_chunk_size = 0x%0x\n", rq_regs.min_chunk_size); + dml_print("DML_RQ_DLG_CALC: meta_chunk_size = 0x%0x\n", rq_regs.meta_chunk_size); + dml_print( + "DML_RQ_DLG_CALC: min_meta_chunk_size = 0x%0x\n", + rq_regs.min_meta_chunk_size); + dml_print("DML_RQ_DLG_CALC: dpte_group_size = 0x%0x\n", rq_regs.dpte_group_size); + dml_print("DML_RQ_DLG_CALC: mpte_group_size = 0x%0x\n", rq_regs.mpte_group_size); + dml_print("DML_RQ_DLG_CALC: swath_height = 0x%0x\n", rq_regs.swath_height); + dml_print( + "DML_RQ_DLG_CALC: pte_row_height_linear = 0x%0x\n", + rq_regs.pte_row_height_linear); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__rq_regs_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_regs_st rq_regs) +void print__rq_regs_st(struct display_mode_lib *mode_lib, display_rq_regs_st rq_regs) { - DTRACE("RQ_DLG_CALC: ===================================== "); - DTRACE("RQ_DLG_CALC: DISPLAY_RQ_REGS_ST"); - DTRACE("RQ_DLG_CALC: <LUMA> "); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); + dml_print("DML_RQ_DLG_CALC: DISPLAY_RQ_REGS_ST\n"); + dml_print("DML_RQ_DLG_CALC: <LUMA>\n"); print__data_rq_regs_st(mode_lib, rq_regs.rq_regs_l); - DTRACE("RQ_DLG_CALC: <CHROMA> "); + dml_print("DML_RQ_DLG_CALC: <CHROMA>\n"); print__data_rq_regs_st(mode_lib, rq_regs.rq_regs_c); - DTRACE("RQ_DLG_CALC: drq_expansion_mode = 0x%0x", rq_regs.drq_expansion_mode); - DTRACE("RQ_DLG_CALC: prq_expansion_mode = 0x%0x", rq_regs.prq_expansion_mode); - DTRACE("RQ_DLG_CALC: mrq_expansion_mode = 0x%0x", rq_regs.mrq_expansion_mode); - DTRACE("RQ_DLG_CALC: crq_expansion_mode = 0x%0x", rq_regs.crq_expansion_mode); - DTRACE("RQ_DLG_CALC: plane1_base_address = 0x%0x", rq_regs.plane1_base_address); - DTRACE("RQ_DLG_CALC: ===================================== "); + dml_print("DML_RQ_DLG_CALC: drq_expansion_mode = 0x%0x\n", rq_regs.drq_expansion_mode); + dml_print("DML_RQ_DLG_CALC: prq_expansion_mode = 0x%0x\n", rq_regs.prq_expansion_mode); + dml_print("DML_RQ_DLG_CALC: mrq_expansion_mode = 0x%0x\n", rq_regs.mrq_expansion_mode); + dml_print("DML_RQ_DLG_CALC: crq_expansion_mode = 0x%0x\n", rq_regs.crq_expansion_mode); + dml_print("DML_RQ_DLG_CALC: plane1_base_address = 0x%0x\n", rq_regs.plane1_base_address); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__dlg_regs_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_dlg_regs_st dlg_regs) +void print__dlg_regs_st(struct display_mode_lib *mode_lib, display_dlg_regs_st dlg_regs) { - DTRACE("RQ_DLG_CALC: ===================================== "); - DTRACE("RQ_DLG_CALC: DISPLAY_DLG_REGS_ST "); - DTRACE( - "RQ_DLG_CALC: refcyc_h_blank_end = 0x%0x", + dml_print("DML_RQ_DLG_CALC: =====================================\n"); + dml_print("DML_RQ_DLG_CALC: DISPLAY_DLG_REGS_ST\n"); + dml_print( + "DML_RQ_DLG_CALC: refcyc_h_blank_end = 0x%0x\n", dlg_regs.refcyc_h_blank_end); - DTRACE("RQ_DLG_CALC: dlg_vblank_end = 0x%0x", dlg_regs.dlg_vblank_end); - DTRACE( - "RQ_DLG_CALC: min_dst_y_next_start = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: dlg_vblank_end = 0x%0x\n", + dlg_regs.dlg_vblank_end); + dml_print( + "DML_RQ_DLG_CALC: min_dst_y_next_start = 0x%0x\n", dlg_regs.min_dst_y_next_start); - DTRACE( - "RQ_DLG_CALC: refcyc_per_htotal = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_htotal = 0x%0x\n", dlg_regs.refcyc_per_htotal); - DTRACE( - "RQ_DLG_CALC: refcyc_x_after_scaler = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_x_after_scaler = 0x%0x\n", dlg_regs.refcyc_x_after_scaler); - DTRACE( - "RQ_DLG_CALC: dst_y_after_scaler = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: dst_y_after_scaler = 0x%0x\n", dlg_regs.dst_y_after_scaler); - DTRACE("RQ_DLG_CALC: dst_y_prefetch = 0x%0x", dlg_regs.dst_y_prefetch); - DTRACE( - "RQ_DLG_CALC: dst_y_per_vm_vblank = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: dst_y_prefetch = 0x%0x\n", + dlg_regs.dst_y_prefetch); + dml_print( + "DML_RQ_DLG_CALC: dst_y_per_vm_vblank = 0x%0x\n", dlg_regs.dst_y_per_vm_vblank); - DTRACE( - "RQ_DLG_CALC: dst_y_per_row_vblank = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: dst_y_per_row_vblank = 0x%0x\n", dlg_regs.dst_y_per_row_vblank); - DTRACE( - "RQ_DLG_CALC: ref_freq_to_pix_freq = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: dst_y_per_vm_flip = 0x%0x\n", + dlg_regs.dst_y_per_vm_flip); + dml_print( + "DML_RQ_DLG_CALC: dst_y_per_row_flip = 0x%0x\n", + dlg_regs.dst_y_per_row_flip); + dml_print( + "DML_RQ_DLG_CALC: ref_freq_to_pix_freq = 0x%0x\n", dlg_regs.ref_freq_to_pix_freq); - DTRACE("RQ_DLG_CALC: vratio_prefetch = 0x%0x", dlg_regs.vratio_prefetch); - DTRACE( - "RQ_DLG_CALC: vratio_prefetch_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: vratio_prefetch = 0x%0x\n", + dlg_regs.vratio_prefetch); + dml_print( + "DML_RQ_DLG_CALC: vratio_prefetch_c = 0x%0x\n", dlg_regs.vratio_prefetch_c); - DTRACE( - "RQ_DLG_CALC: refcyc_per_pte_group_vblank_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_pte_group_vblank_l = 0x%0x\n", dlg_regs.refcyc_per_pte_group_vblank_l); - DTRACE( - "RQ_DLG_CALC: refcyc_per_pte_group_vblank_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_pte_group_vblank_c = 0x%0x\n", dlg_regs.refcyc_per_pte_group_vblank_c); - DTRACE( - "RQ_DLG_CALC: refcyc_per_meta_chunk_vblank_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_meta_chunk_vblank_l = 0x%0x\n", dlg_regs.refcyc_per_meta_chunk_vblank_l); - DTRACE( - "RQ_DLG_CALC: refcyc_per_meta_chunk_vblank_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_meta_chunk_vblank_c = 0x%0x\n", dlg_regs.refcyc_per_meta_chunk_vblank_c); - DTRACE( - "RQ_DLG_CALC: dst_y_per_pte_row_nom_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_pte_group_flip_l = 0x%0x\n", + dlg_regs.refcyc_per_pte_group_flip_l); + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_pte_group_flip_c = 0x%0x\n", + dlg_regs.refcyc_per_pte_group_flip_c); + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_meta_chunk_flip_l = 0x%0x\n", + dlg_regs.refcyc_per_meta_chunk_flip_l); + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_meta_chunk_flip_c = 0x%0x\n", + dlg_regs.refcyc_per_meta_chunk_flip_c); + dml_print( + "DML_RQ_DLG_CALC: dst_y_per_pte_row_nom_l = 0x%0x\n", dlg_regs.dst_y_per_pte_row_nom_l); - DTRACE( - "RQ_DLG_CALC: dst_y_per_pte_row_nom_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: dst_y_per_pte_row_nom_c = 0x%0x\n", dlg_regs.dst_y_per_pte_row_nom_c); - DTRACE( - "RQ_DLG_CALC: refcyc_per_pte_group_nom_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_pte_group_nom_l = 0x%0x\n", dlg_regs.refcyc_per_pte_group_nom_l); - DTRACE( - "RQ_DLG_CALC: refcyc_per_pte_group_nom_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_pte_group_nom_c = 0x%0x\n", dlg_regs.refcyc_per_pte_group_nom_c); - DTRACE( - "RQ_DLG_CALC: dst_y_per_meta_row_nom_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: dst_y_per_meta_row_nom_l = 0x%0x\n", dlg_regs.dst_y_per_meta_row_nom_l); - DTRACE( - "RQ_DLG_CALC: dst_y_per_meta_row_nom_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: dst_y_per_meta_row_nom_c = 0x%0x\n", dlg_regs.dst_y_per_meta_row_nom_c); - DTRACE( - "RQ_DLG_CALC: refcyc_per_meta_chunk_nom_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_meta_chunk_nom_l = 0x%0x\n", dlg_regs.refcyc_per_meta_chunk_nom_l); - DTRACE( - "RQ_DLG_CALC: refcyc_per_meta_chunk_nom_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_meta_chunk_nom_c = 0x%0x\n", dlg_regs.refcyc_per_meta_chunk_nom_c); - DTRACE( - "RQ_DLG_CALC: refcyc_per_line_delivery_pre_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_line_delivery_pre_l = 0x%0x\n", dlg_regs.refcyc_per_line_delivery_pre_l); - DTRACE( - "RQ_DLG_CALC: refcyc_per_line_delivery_pre_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_line_delivery_pre_c = 0x%0x\n", dlg_regs.refcyc_per_line_delivery_pre_c); - DTRACE( - "RQ_DLG_CALC: refcyc_per_line_delivery_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_line_delivery_l = 0x%0x\n", dlg_regs.refcyc_per_line_delivery_l); - DTRACE( - "RQ_DLG_CALC: refcyc_per_line_delivery_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_line_delivery_c = 0x%0x\n", dlg_regs.refcyc_per_line_delivery_c); - DTRACE( - "RQ_DLG_CALC: chunk_hdl_adjust_cur0 = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: chunk_hdl_adjust_cur0 = 0x%0x\n", dlg_regs.chunk_hdl_adjust_cur0); - DTRACE("RQ_DLG_CALC: ===================================== "); + dml_print( + "DML_RQ_DLG_CALC: dst_y_offset_cur1 = 0x%0x\n", + dlg_regs.dst_y_offset_cur1); + dml_print( + "DML_RQ_DLG_CALC: chunk_hdl_adjust_cur1 = 0x%0x\n", + dlg_regs.chunk_hdl_adjust_cur1); + dml_print( + "DML_RQ_DLG_CALC: vready_after_vcount0 = 0x%0x\n", + dlg_regs.vready_after_vcount0); + dml_print( + "DML_RQ_DLG_CALC: dst_y_delta_drq_limit = 0x%0x\n", + dlg_regs.dst_y_delta_drq_limit); + dml_print( + "DML_RQ_DLG_CALC: xfc_reg_transfer_delay = 0x%0x\n", + dlg_regs.xfc_reg_transfer_delay); + dml_print( + "DML_RQ_DLG_CALC: xfc_reg_precharge_delay = 0x%0x\n", + dlg_regs.xfc_reg_precharge_delay); + dml_print( + "DML_RQ_DLG_CALC: xfc_reg_remote_surface_flip_latency = 0x%0x\n", + dlg_regs.xfc_reg_remote_surface_flip_latency); + + dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__ttu_regs_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_ttu_regs_st ttu_regs) +void print__ttu_regs_st(struct display_mode_lib *mode_lib, display_ttu_regs_st ttu_regs) { - DTRACE("RQ_DLG_CALC: ===================================== "); - DTRACE("RQ_DLG_CALC: DISPLAY_TTU_REGS_ST "); - DTRACE( - "RQ_DLG_CALC: qos_level_low_wm = 0x%0x", + dml_print("DML_RQ_DLG_CALC: =====================================\n"); + dml_print("DML_RQ_DLG_CALC: DISPLAY_TTU_REGS_ST\n"); + dml_print( + "DML_RQ_DLG_CALC: qos_level_low_wm = 0x%0x\n", ttu_regs.qos_level_low_wm); - DTRACE( - "RQ_DLG_CALC: qos_level_high_wm = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: qos_level_high_wm = 0x%0x\n", ttu_regs.qos_level_high_wm); - DTRACE("RQ_DLG_CALC: min_ttu_vblank = 0x%0x", ttu_regs.min_ttu_vblank); - DTRACE("RQ_DLG_CALC: qos_level_flip = 0x%0x", ttu_regs.qos_level_flip); - DTRACE( - "RQ_DLG_CALC: refcyc_per_req_delivery_pre_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: min_ttu_vblank = 0x%0x\n", + ttu_regs.min_ttu_vblank); + dml_print( + "DML_RQ_DLG_CALC: qos_level_flip = 0x%0x\n", + ttu_regs.qos_level_flip); + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_req_delivery_pre_l = 0x%0x\n", ttu_regs.refcyc_per_req_delivery_pre_l); - DTRACE( - "RQ_DLG_CALC: refcyc_per_req_delivery_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_req_delivery_l = 0x%0x\n", ttu_regs.refcyc_per_req_delivery_l); - DTRACE( - "RQ_DLG_CALC: refcyc_per_req_delivery_pre_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_req_delivery_pre_c = 0x%0x\n", ttu_regs.refcyc_per_req_delivery_pre_c); - DTRACE( - "RQ_DLG_CALC: refcyc_per_req_delivery_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_req_delivery_c = 0x%0x\n", ttu_regs.refcyc_per_req_delivery_c); - DTRACE( - "RQ_DLG_CALC: refcyc_per_req_delivery_cur0 = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_req_delivery_cur0 = 0x%0x\n", ttu_regs.refcyc_per_req_delivery_cur0); - DTRACE( - "RQ_DLG_CALC: refcyc_per_req_delivery_pre_cur0 = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_req_delivery_pre_cur0 = 0x%0x\n", ttu_regs.refcyc_per_req_delivery_pre_cur0); - DTRACE( - "RQ_DLG_CALC: qos_level_fixed_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_req_delivery_cur1 = 0x%0x\n", + ttu_regs.refcyc_per_req_delivery_cur1); + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_req_delivery_pre_cur1 = 0x%0x\n", + ttu_regs.refcyc_per_req_delivery_pre_cur1); + dml_print( + "DML_RQ_DLG_CALC: qos_level_fixed_l = 0x%0x\n", ttu_regs.qos_level_fixed_l); - DTRACE( - "RQ_DLG_CALC: qos_ramp_disable_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: qos_ramp_disable_l = 0x%0x\n", ttu_regs.qos_ramp_disable_l); - DTRACE( - "RQ_DLG_CALC: qos_level_fixed_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: qos_level_fixed_c = 0x%0x\n", ttu_regs.qos_level_fixed_c); - DTRACE( - "RQ_DLG_CALC: qos_ramp_disable_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: qos_ramp_disable_c = 0x%0x\n", ttu_regs.qos_ramp_disable_c); - DTRACE( - "RQ_DLG_CALC: qos_level_fixed_cur0 = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: qos_level_fixed_cur0 = 0x%0x\n", ttu_regs.qos_level_fixed_cur0); - DTRACE( - "RQ_DLG_CALC: qos_ramp_disable_cur0 = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: qos_ramp_disable_cur0 = 0x%0x\n", ttu_regs.qos_ramp_disable_cur0); - DTRACE("RQ_DLG_CALC: ===================================== "); + dml_print( + "DML_RQ_DLG_CALC: qos_level_fixed_cur1 = 0x%0x\n", + ttu_regs.qos_level_fixed_cur1); + dml_print( + "DML_RQ_DLG_CALC: qos_ramp_disable_cur1 = 0x%0x\n", + ttu_regs.qos_ramp_disable_cur1); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); } diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.h b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.h index 7403ccaf637b..1f24db830737 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.h @@ -22,6 +22,7 @@ * Authors: AMD * */ + #ifndef __DISPLAY_RQ_DLG_HELPERS_H__ #define __DISPLAY_RQ_DLG_HELPERS_H__ @@ -31,36 +32,16 @@ /* Function: Printer functions * Print various struct */ -void print__rq_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_params_st rq_param); -void print__data_rq_sizing_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_data_rq_sizing_params_st rq_sizing); -void print__data_rq_dlg_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_data_rq_dlg_params_st rq_dlg_param); -void print__data_rq_misc_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_data_rq_misc_params_st rq_misc_param); -void print__rq_dlg_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param); -void print__dlg_sys_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param); +void print__rq_params_st(struct display_mode_lib *mode_lib, display_rq_params_st rq_param); +void print__data_rq_sizing_params_st(struct display_mode_lib *mode_lib, display_data_rq_sizing_params_st rq_sizing); +void print__data_rq_dlg_params_st(struct display_mode_lib *mode_lib, display_data_rq_dlg_params_st rq_dlg_param); +void print__data_rq_misc_params_st(struct display_mode_lib *mode_lib, display_data_rq_misc_params_st rq_misc_param); +void print__rq_dlg_params_st(struct display_mode_lib *mode_lib, display_rq_dlg_params_st rq_dlg_param); +void print__dlg_sys_params_st(struct display_mode_lib *mode_lib, display_dlg_sys_params_st dlg_sys_param); -void print__data_rq_regs_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_data_rq_regs_st data_rq_regs); -void print__rq_regs_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_regs_st rq_regs); -void print__dlg_regs_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_dlg_regs_st dlg_regs); -void print__ttu_regs_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_ttu_regs_st ttu_regs); +void print__data_rq_regs_st(struct display_mode_lib *mode_lib, display_data_rq_regs_st data_rq_regs); +void print__rq_regs_st(struct display_mode_lib *mode_lib, display_rq_regs_st rq_regs); +void print__dlg_regs_st(struct display_mode_lib *mode_lib, display_dlg_regs_st dlg_regs); +void print__ttu_regs_st(struct display_mode_lib *mode_lib, display_ttu_regs_st ttu_regs); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c b/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c deleted file mode 100644 index 142a3284ac44..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c +++ /dev/null @@ -1,1282 +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 "display_watermark.h" -#include "display_mode_lib.h" -#include "dml_inline_defs.h" - -static void get_bytes_per_pixel( - enum source_format_class format, - struct _vcs_dpi_wm_calc_pipe_params_st *plane) -{ - switch (format) { - case dm_444_64: - plane->bytes_per_pixel_y = 8.0; - plane->bytes_per_pixel_c = 0.0; - break; - case dm_444_32: - plane->bytes_per_pixel_y = 4.0; - plane->bytes_per_pixel_c = 0.0; - break; - case dm_444_16: - plane->bytes_per_pixel_y = 2.0; - plane->bytes_per_pixel_c = 0.0; - break; - case dm_422_10: - plane->bytes_per_pixel_y = 4.0; - plane->bytes_per_pixel_c = 0.0; - break; - case dm_422_8: - plane->bytes_per_pixel_y = 2.0; - plane->bytes_per_pixel_c = 0.0; - break; - case dm_420_8: - plane->bytes_per_pixel_y = 1.0; - plane->bytes_per_pixel_c = 2.0; - break; - case dm_420_10: - plane->bytes_per_pixel_y = 4.0 / 3; - plane->bytes_per_pixel_c = 8.0 / 3; - break; - default: - BREAK_TO_DEBUGGER(); /* invalid format in get_bytes_per_pixel */ - } -} - -static unsigned int get_swath_width_y( - struct _vcs_dpi_display_pipe_source_params_st *src_param, - unsigned int num_dpp) -{ - unsigned int val; - - /* note that we don't divide by num_dpp here because we have an interface which has already split - * any viewports - */ - if (src_param->source_scan == dm_horz) { - val = src_param->viewport_width; - } else { - val = src_param->viewport_height; - } - - return val; -} - -static void get_swath_height( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_pipe_source_params_st *src_param, - struct _vcs_dpi_wm_calc_pipe_params_st *plane, - unsigned int swath_width_y) -{ - double buffer_width; - - if (src_param->source_format == dm_444_64 || src_param->source_format == dm_444_32 - || src_param->source_format == dm_444_16) { - if (src_param->sw_mode == dm_sw_linear) { - plane->swath_height_y = 1; - } else if (src_param->source_format == dm_444_64) { - plane->swath_height_y = 4; - } else { - plane->swath_height_y = 8; - } - - if (src_param->source_scan != dm_horz) { - plane->swath_height_y = 256 / (unsigned int) plane->bytes_per_pixel_y - / plane->swath_height_y; - } - - plane->swath_height_c = 0; - - } else { - if (src_param->sw_mode == dm_sw_linear) { - plane->swath_height_y = 1; - plane->swath_height_c = 1; - } else if (src_param->source_format == dm_420_8) { - plane->swath_height_y = 16; - plane->swath_height_c = 8; - } else { - plane->swath_height_y = 8; - plane->swath_height_c = 8; - } - - if (src_param->source_scan != dm_horz) { - double bytes_per_pixel_c_ceil; - - plane->swath_height_y = 256 / dml_ceil(plane->bytes_per_pixel_y) - / plane->swath_height_y; - - bytes_per_pixel_c_ceil = dml_ceil_2(plane->bytes_per_pixel_c); - - plane->swath_height_c = 256 / bytes_per_pixel_c_ceil - / plane->swath_height_c; - } - } - - /* use swath height min if buffer isn't big enough */ - - buffer_width = ((double) mode_lib->ip.det_buffer_size_kbytes * 1024.0 / 2.0) - / (plane->bytes_per_pixel_y * (double) plane->swath_height_y - + (plane->bytes_per_pixel_c / 2.0 - * (double) plane->swath_height_c)); - - if ((double) swath_width_y <= buffer_width) { - /* do nothing, just keep code structure from Gabes vba */ - } else { - /* substitute swath height with swath height min */ - if (src_param->source_format == dm_444_64 || src_param->source_format == dm_444_32 - || src_param->source_format == dm_444_16) { - if ((src_param->sw_mode == dm_sw_linear) - || (src_param->source_format == dm_444_64 - && (src_param->sw_mode == dm_sw_4kb_s - || src_param->sw_mode - == dm_sw_4kb_s_x - || src_param->sw_mode - == dm_sw_64kb_s - || src_param->sw_mode - == dm_sw_64kb_s_t - || src_param->sw_mode - == dm_sw_64kb_s_x - || src_param->sw_mode - == dm_sw_var_s - || src_param->sw_mode - == dm_sw_var_s_x) - && src_param->source_scan == dm_horz)) { - /* do nothing, just keep code structure from Gabes vba */ - } else { - plane->swath_height_y = plane->swath_height_y / 2; - } - } else { - if (src_param->sw_mode == dm_sw_linear) { - /* do nothing, just keep code structure from Gabes vba */ - } else if (src_param->source_format == dm_420_8 - && src_param->source_scan == dm_horz) { - plane->swath_height_y = plane->swath_height_y / 2; - } else if (src_param->source_format == dm_420_10 - && src_param->source_scan == dm_horz) { - plane->swath_height_c = plane->swath_height_c / 2; - } - } - } - - if (plane->swath_height_c == 0) { - plane->det_buffer_size_y = mode_lib->ip.det_buffer_size_kbytes * 1024.0; - } else if (plane->swath_height_c <= plane->swath_height_y) { - plane->det_buffer_size_y = mode_lib->ip.det_buffer_size_kbytes * 1024.0 / 2.0; - } else { - plane->det_buffer_size_y = mode_lib->ip.det_buffer_size_kbytes * 1024.0 * 2.0 / 3.0; - } -} - -static void calc_display_pipe_line_delivery_time( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes) -{ - unsigned int i; - - for (i = 0; i < num_planes; i++) { - if (planes[i].v_ratio <= 1.0) { - planes[i].display_pipe_line_delivery_time = planes[i].swath_width_y - * planes[i].num_dpp / planes[i].h_ratio - / planes[i].pixclk_mhz; - } else { - double dchub_pscl_bw_per_clk; - - if (planes[i].h_ratio > 1) { - double num_hscl_kernels; - - num_hscl_kernels = dml_ceil((double) planes[i].h_taps / 6); - dchub_pscl_bw_per_clk = - dml_min( - (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk, - mode_lib->ip.max_pscl_lb_bw_pix_per_clk - * planes[i].h_ratio - / num_hscl_kernels); - } else { - dchub_pscl_bw_per_clk = - dml_min( - (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk, - (double) mode_lib->ip.max_pscl_lb_bw_pix_per_clk); - } - - planes[i].display_pipe_line_delivery_time = planes[i].swath_width_y - / dchub_pscl_bw_per_clk / planes[i].dppclk_mhz; - } - } -} - -static double calc_total_data_read_bw( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes) -{ - double val = 0.0; - unsigned int i; - - for (i = 0; i < num_planes; i++) { - double swath_width_y_plane = planes[i].swath_width_y * planes[i].num_dpp; - - planes[i].read_bw = swath_width_y_plane - * (dml_ceil(planes[i].bytes_per_pixel_y) - + dml_ceil_2(planes[i].bytes_per_pixel_c) / 2) - / (planes[i].h_total / planes[i].pixclk_mhz) * planes[i].v_ratio; - - val += planes[i].read_bw; - - DTRACE("plane[%d] start", i); - DTRACE("read_bw = %f", planes[i].read_bw); - DTRACE("plane[%d] end", i); - } - - return val; -} - -double dml_wm_calc_total_data_read_bw( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes) -{ - return calc_total_data_read_bw(mode_lib, planes, num_planes); -} - -static double calc_dcfclk_mhz( - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes) -{ - double dcfclk_mhz = -1.0; - unsigned int i; - - for (i = 0; i < num_planes; i++) { - /* voltage and dcfclk must be the same for all pipes */ - ASSERT(dcfclk_mhz == -1.0 || dcfclk_mhz == planes[i].dcfclk_mhz); - dcfclk_mhz = planes[i].dcfclk_mhz; - } - - return dcfclk_mhz; -} - -static enum voltage_state find_voltage( - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes) -{ - int voltage = -1; - unsigned int i; - - for (i = 0; i < num_planes; i++) { - ASSERT(voltage == -1 || voltage == planes[i].voltage); - voltage = planes[i].voltage; - } - - return (enum voltage_state) voltage; -} - -static bool find_dcc_enable(struct _vcs_dpi_wm_calc_pipe_params_st *planes, unsigned int num_planes) -{ - unsigned int i; - - for (i = 0; i < num_planes; i++) { - if (planes[i].dcc_enable) { - return true; - } - } - - return false; -} - -static double calc_return_bw( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes) -{ - struct _vcs_dpi_soc_bounding_box_st *soc; - double return_bw_mbps; - double dcfclk_mhz; - double return_bus_bw; - enum voltage_state voltage; - double return_bw_to_dcn; - bool dcc_enable; - double rob_chunk_diff; - double urgent_latency_traffic; - double critical_compression; - struct _vcs_dpi_voltage_scaling_st state; - - soc = &mode_lib->soc; - - dcfclk_mhz = calc_dcfclk_mhz(planes, num_planes); - return_bus_bw = dcfclk_mhz * soc->return_bus_width_bytes; - - DTRACE("INTERMEDIATE dcfclk_mhz = %f", dcfclk_mhz); - DTRACE("INTERMEDIATE return_bus_bw = %f", return_bus_bw); - - voltage = find_voltage(planes, num_planes); - return_bw_to_dcn = dml_socbb_return_bw_mhz(soc, voltage); - - dcc_enable = find_dcc_enable(planes, num_planes); - - return_bw_mbps = return_bw_to_dcn; - DTRACE("INTERMEDIATE return_bw_mbps = %f", return_bw_mbps); - - rob_chunk_diff = - (mode_lib->ip.rob_buffer_size_kbytes - mode_lib->ip.pixel_chunk_size_kbytes) - * 1024.0; - DTRACE("INTERMEDIATE rob_chunk_diff = %f", rob_chunk_diff); - - if (dcc_enable && return_bw_to_dcn > return_bus_bw / 4) { - double dcc_return_bw = - return_bw_to_dcn * 4.0 - * (1.0 - - soc->urgent_latency_us - / (rob_chunk_diff - / (return_bw_to_dcn - - return_bus_bw - / 4.0) - + soc->urgent_latency_us)); - return_bw_mbps = dml_min(return_bw_mbps, dcc_return_bw); - DTRACE("INTERMEDIATE dcc_return_bw = %f", dcc_return_bw); - } - - urgent_latency_traffic = return_bus_bw * soc->urgent_latency_us; - DTRACE("INTERMEDIATE urgent_latency_traffic = %f", urgent_latency_traffic); - critical_compression = 2.0 * urgent_latency_traffic - / (return_bw_to_dcn * soc->urgent_latency_us + rob_chunk_diff); - DTRACE("INTERMEDIATE critical_compression = %f", critical_compression); - - if (dcc_enable && critical_compression > 1.0 && critical_compression < 4.0) { - double crit_return_bw = (4 * return_bw_to_dcn * rob_chunk_diff - * urgent_latency_traffic); - crit_return_bw = crit_return_bw - / dml_pow( - return_bw_to_dcn * soc->urgent_latency_us - + rob_chunk_diff, - 2); - DTRACE("INTERMEDIATE critical_return_bw = %f", crit_return_bw); - return_bw_mbps = dml_min(return_bw_mbps, crit_return_bw); - } - - /* Gabe does this again for some reason using the value of return_bw_mpbs from the previous calculation - * and a lightly different return_bw_to_dcn - */ - - state = dml_socbb_voltage_scaling(soc, voltage); - return_bw_to_dcn = dml_min( - soc->return_bus_width_bytes * dcfclk_mhz, - state.dram_bw_per_chan_gbps * 1000.0 * (double) soc->num_chans); - - DTRACE("INTERMEDIATE rob_chunk_diff = %f", rob_chunk_diff); - - if (dcc_enable && return_bw_to_dcn > return_bus_bw / 4) { - double dcc_return_bw = - return_bw_to_dcn * 4.0 - * (1.0 - - soc->urgent_latency_us - / (rob_chunk_diff - / (return_bw_to_dcn - - return_bus_bw - / 4.0) - + soc->urgent_latency_us)); - return_bw_mbps = dml_min(return_bw_mbps, dcc_return_bw); - DTRACE("INTERMEDIATE dcc_return_bw = %f", dcc_return_bw); - } - - urgent_latency_traffic = return_bus_bw * soc->urgent_latency_us; - DTRACE("INTERMEDIATE urgent_latency_traffic = %f", urgent_latency_traffic); - critical_compression = 2.0 * urgent_latency_traffic - / (return_bw_to_dcn * soc->urgent_latency_us + rob_chunk_diff); - DTRACE("INTERMEDIATE critical_compression = %f", critical_compression); - - /* problem here? */ - if (dcc_enable && critical_compression > 1.0 && critical_compression < 4.0) { - double crit_return_bw = (4 * return_bw_to_dcn * rob_chunk_diff - * urgent_latency_traffic); - crit_return_bw = crit_return_bw - / dml_pow( - return_bw_to_dcn * soc->urgent_latency_us - + rob_chunk_diff, - 2); - DTRACE("INTERMEDIATE critical_return_bw = %f", crit_return_bw); - DTRACE("INTERMEDIATE return_bw_to_dcn = %f", return_bw_to_dcn); - DTRACE("INTERMEDIATE rob_chunk_diff = %f", rob_chunk_diff); - DTRACE("INTERMEDIATE urgent_latency_traffic = %f", urgent_latency_traffic); - - return_bw_mbps = dml_min(return_bw_mbps, crit_return_bw); - } - - DTRACE("INTERMEDIATE final return_bw_mbps = %f", return_bw_mbps); - return return_bw_mbps; -} - -double dml_wm_calc_return_bw( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes) -{ - return calc_return_bw(mode_lib, planes, num_planes); -} - -static double calc_last_pixel_of_line_extra_wm_us( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes) -{ - double val = 0.0; - double total_data_read_bw = calc_total_data_read_bw(mode_lib, planes, num_planes); - int voltage = -1; - unsigned int i; - double return_bw_mbps; - - for (i = 0; i < num_planes; i++) { - /* voltage mode must be the same for all pipes */ - ASSERT(voltage == -1 || voltage == planes[i].voltage); - voltage = planes[i].voltage; - } - return_bw_mbps = calc_return_bw(mode_lib, planes, num_planes); - - for (i = 0; i < num_planes; i++) { - double bytes_pp_y = dml_ceil(planes[i].bytes_per_pixel_y); - double bytes_pp_c = dml_ceil_2(planes[i].bytes_per_pixel_c); - double swath_bytes_y = (double) planes[i].swath_width_y - * (double) planes[i].swath_height_y * (double) bytes_pp_y; - double swath_bytes_c = ((double) planes[i].swath_width_y / 2.0) - * (double) planes[i].swath_height_c * (double) bytes_pp_c; - double data_fabric_line_delivery_time = (swath_bytes_y + swath_bytes_c) - / (return_bw_mbps * planes[i].read_bw / (double) planes[i].num_dpp - / total_data_read_bw); - - DTRACE( - "bytes_pp_y = %f, swath_width_y = %f, swath_height_y = %f, swath_bytes_y = %f", - bytes_pp_y, - (double) planes[i].swath_width_y, - (double) planes[i].swath_height_y, - swath_bytes_y); - DTRACE( - "bytes_pp_c = %f, swath_width_c = %f, swath_height_c = %f, swath_bytes_c = %f", - bytes_pp_c, - ((double) planes[i].swath_width_y / 2.0), - (double) planes[i].swath_height_c, - swath_bytes_c); - DTRACE( - "return_bw_mbps = %f, read_bw = %f, num_dpp = %d, total_data_read_bw = %f", - return_bw_mbps, - planes[i].read_bw, - planes[i].num_dpp, - total_data_read_bw); - DTRACE("data_fabric_line_delivery_time = %f", data_fabric_line_delivery_time); - DTRACE( - "display_pipe_line_delivery_time = %f", - planes[i].display_pipe_line_delivery_time); - - val = dml_max( - val, - data_fabric_line_delivery_time - - planes[i].display_pipe_line_delivery_time); - } - - DTRACE("last_pixel_of_line_extra_wm is %f us", val); - return val; -} - -static bool calc_pte_enable(struct _vcs_dpi_wm_calc_pipe_params_st *planes, unsigned int num_planes) -{ - unsigned int i; - - for (i = 0; i < num_planes; i++) { - if (planes[i].pte_enable) { - return true; - } - } - - return false; -} - -static void calc_lines_in_det_y(struct _vcs_dpi_wm_calc_pipe_params_st *plane) -{ - plane->lines_in_det_y = plane->det_buffer_size_y / plane->bytes_per_pixel_y - / plane->swath_width_y; - plane->lines_in_det_y_rounded_down_to_swath = dml_floor( - (double) plane->lines_in_det_y / plane->swath_height_y) - * plane->swath_height_y; - plane->full_det_buffering_time = plane->lines_in_det_y_rounded_down_to_swath - * (plane->h_total / plane->pixclk_mhz); -} - -/* CHECKME: not obviously 1:1 with calculation described in architectural - * document or spreadsheet */ -static void calc_dcfclk_deepsleep_mhz_per_plane( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *plane) -{ - double bus_width_per_pixel; - - if (plane->swath_height_c == 0) { - bus_width_per_pixel = dml_ceil(plane->bytes_per_pixel_y) / 64; - } else { - double bus_width_per_pixel_c; - - bus_width_per_pixel = dml_ceil(plane->bytes_per_pixel_y) / 32; - bus_width_per_pixel_c = dml_ceil(plane->bytes_per_pixel_c) / 32; - if (bus_width_per_pixel < bus_width_per_pixel_c) - bus_width_per_pixel = bus_width_per_pixel_c; - } - - if (plane->v_ratio <= 1) { - plane->dcfclk_deepsleep_mhz_per_plane = 1.1 * plane->pixclk_mhz / plane->num_dpp - * plane->h_ratio * bus_width_per_pixel; - } else if (plane->h_ratio > 1) { - double num_hscl_kernels = dml_ceil((double) plane->h_taps / 6); - double dchub_pscl_bw_per_clk = dml_min( - (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk, - mode_lib->ip.max_pscl_lb_bw_pix_per_clk * plane->h_ratio - / num_hscl_kernels); - - plane->dcfclk_deepsleep_mhz_per_plane = 1.1 * plane->dppclk_mhz - * dchub_pscl_bw_per_clk * bus_width_per_pixel; - } else { - double dchub_pscl_bw_per_clk = dml_min( - (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk, - (double) mode_lib->ip.max_pscl_lb_bw_pix_per_clk); - - plane->dcfclk_deepsleep_mhz_per_plane = 1.1 * plane->dppclk_mhz - * dchub_pscl_bw_per_clk * bus_width_per_pixel; - } - - plane->dcfclk_deepsleep_mhz_per_plane = dml_max( - plane->dcfclk_deepsleep_mhz_per_plane, - plane->pixclk_mhz / 16); -} - -/* Implementation of expected stutter efficiency from DCN1_Display_Mode.docx */ -double dml_wm_expected_stutter_eff_e2e( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes) -{ - double min_full_det_buffering_time_us; - double frame_time_for_min_full_det_buffering_time_us = 0.0; - struct _vcs_dpi_wm_calc_pipe_params_st *planes = mode_lib->wm_param; - unsigned int num_planes; - unsigned int i; - double total_data_read_bw_mbps; - double average_read_bw_gbps; - double min_full_det_buffer_size_bytes; - double rob_fill_size_bytes; - double part_of_burst_that_fits_in_rob; - int voltage; - double dcfclk_mhz; - unsigned int total_writeback; - double return_bw_mbps; - double stutter_burst_time_us; - double stutter_eff_not_including_vblank; - double smallest_vblank_us; - double stutter_eff; - - memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); - DTRACE("calculating expected stutter efficiency"); - - num_planes = dml_wm_e2e_to_wm(mode_lib, e2e, num_pipes, planes); - - for (i = 0; i < num_planes; i++) { - calc_lines_in_det_y(&planes[i]); - - DTRACE("swath width y plane %d = %d", i, planes[i].swath_width_y); - DTRACE("swath height y plane %d = %d", i, planes[i].swath_height_y); - DTRACE( - "bytes per pixel det y plane %d = %f", - i, - planes[i].bytes_per_pixel_y); - DTRACE( - "bytes per pixel det c plane %d = %f", - i, - planes[i].bytes_per_pixel_c); - DTRACE( - "det buffer size plane %d = %d", - i, - planes[i].det_buffer_size_y); - DTRACE("lines in det plane %d = %d", i, planes[i].lines_in_det_y); - DTRACE( - "lines in det rounded to swaths plane %d = %d", - i, - planes[i].lines_in_det_y_rounded_down_to_swath); - } - - min_full_det_buffering_time_us = 9999.0; - for (i = 0; i < num_planes; i++) { - if (planes[i].full_det_buffering_time < min_full_det_buffering_time_us) { - min_full_det_buffering_time_us = planes[i].full_det_buffering_time; - frame_time_for_min_full_det_buffering_time_us = (double) planes[i].v_total - * planes[i].h_total / planes[i].pixclk_mhz; - } - } - - DTRACE("INTERMEDIATE: min_full_det_buffering_time_us = %f", min_full_det_buffering_time_us); - - total_data_read_bw_mbps = calc_total_data_read_bw(mode_lib, planes, num_planes); - - average_read_bw_gbps = 0.0; - - for (i = 0; i < num_planes; i++) { - if (planes[i].dcc_enable) { - average_read_bw_gbps += planes[i].read_bw / planes[i].dcc_rate / 1000; - } else { - average_read_bw_gbps += planes[i].read_bw / 1000; - } - - if (planes[i].dcc_enable) { - average_read_bw_gbps += planes[i].read_bw / 1000 / 256; - } - - if (planes[i].pte_enable) { - average_read_bw_gbps += planes[i].read_bw / 1000 / 512; - } - } - - min_full_det_buffer_size_bytes = min_full_det_buffering_time_us * total_data_read_bw_mbps; - rob_fill_size_bytes = mode_lib->ip.rob_buffer_size_kbytes * 1024 * total_data_read_bw_mbps - / (average_read_bw_gbps * 1000); - part_of_burst_that_fits_in_rob = dml_min( - min_full_det_buffer_size_bytes, - rob_fill_size_bytes); - - voltage = -1; - dcfclk_mhz = -1.0; - total_writeback = 0; - - for (i = 0; i < num_pipes; i++) { - /* voltage and dcfclk must be the same for all pipes */ - ASSERT(voltage == -1 || voltage == e2e[i].clks_cfg.voltage); - voltage = e2e[i].clks_cfg.voltage; - ASSERT(dcfclk_mhz == -1.0 || dcfclk_mhz == e2e[i].clks_cfg.dcfclk_mhz); - dcfclk_mhz = e2e[i].clks_cfg.dcfclk_mhz; - - if (e2e[i].dout.output_type == dm_wb) - total_writeback++; - } - - return_bw_mbps = calc_return_bw(mode_lib, planes, num_planes); - - DTRACE("INTERMEDIATE: part_of_burst_that_fits_in_rob = %f", part_of_burst_that_fits_in_rob); - DTRACE("INTERMEDIATE: average_read_bw_gbps = %f", average_read_bw_gbps); - DTRACE("INTERMEDIATE: total_data_read_bw_mbps = %f", total_data_read_bw_mbps); - DTRACE("INTERMEDIATE: return_bw_mbps = %f", return_bw_mbps); - - stutter_burst_time_us = part_of_burst_that_fits_in_rob * (average_read_bw_gbps * 1000) - / total_data_read_bw_mbps / return_bw_mbps - + (min_full_det_buffering_time_us * total_data_read_bw_mbps - - part_of_burst_that_fits_in_rob) / (dcfclk_mhz * 64); - DTRACE("INTERMEDIATE: stutter_burst_time_us = %f", stutter_burst_time_us); - - if (total_writeback == 0) { - stutter_eff_not_including_vblank = (1.0 - - ((mode_lib->soc.sr_exit_time_us + stutter_burst_time_us) - / min_full_det_buffering_time_us)) * 100.0; - } else { - stutter_eff_not_including_vblank = 0.0; - } - - DTRACE("stutter_efficiency_not_including_vblank = %f", stutter_eff_not_including_vblank); - - smallest_vblank_us = 9999.0; - - for (i = 0; i < num_pipes; i++) { - double vblank_us; - if (e2e[i].pipe.dest.syncronized_vblank_all_planes != 0 || num_pipes == 1) { - vblank_us = (double) (e2e[i].pipe.dest.vtotal + 1 - - e2e[i].pipe.dest.vblank_start - + e2e[i].pipe.dest.vblank_end * e2e[i].pipe.dest.htotal) - / e2e[i].pipe.dest.pixel_rate_mhz; - } else { - vblank_us = 0.0; - } - - smallest_vblank_us = dml_min(smallest_vblank_us, vblank_us); - } - - DTRACE("smallest vblank = %f us", smallest_vblank_us); - - stutter_eff = 100.0 - * (((stutter_eff_not_including_vblank / 100.0) - * (frame_time_for_min_full_det_buffering_time_us - - smallest_vblank_us) + smallest_vblank_us) - / frame_time_for_min_full_det_buffering_time_us); - - DTRACE("stutter_efficiency = %f", stutter_eff); - - return stutter_eff_not_including_vblank; -} - -double dml_wm_expected_stutter_eff_e2e_with_vblank( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes) -{ - double min_full_det_buffering_time_us; - double frame_time_for_min_full_det_buffering_time_us = 0.0; - struct _vcs_dpi_wm_calc_pipe_params_st *planes = mode_lib->wm_param; - unsigned int num_planes; - unsigned int i; - double total_data_read_bw_mbps; - double average_read_bw_gbps; - double min_full_det_buffer_size_bytes; - double rob_fill_size_bytes; - double part_of_burst_that_fits_in_rob; - int voltage; - double dcfclk_mhz; - unsigned int total_writeback; - double return_bw_mbps; - double stutter_burst_time_us; - double stutter_eff_not_including_vblank; - double smallest_vblank_us; - double stutter_eff; - - memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); - num_planes = dml_wm_e2e_to_wm(mode_lib, e2e, num_pipes, planes); - - for (i = 0; i < num_planes; i++) { - calc_lines_in_det_y(&planes[i]); - } - - min_full_det_buffering_time_us = 9999.0; - for (i = 0; i < num_planes; i++) { - if (planes[i].full_det_buffering_time < min_full_det_buffering_time_us) { - min_full_det_buffering_time_us = planes[i].full_det_buffering_time; - frame_time_for_min_full_det_buffering_time_us = (double) planes[i].v_total - * planes[i].h_total / planes[i].pixclk_mhz; - } - } - - total_data_read_bw_mbps = calc_total_data_read_bw(mode_lib, planes, num_planes); - average_read_bw_gbps = 0.0; - - for (i = 0; i < num_planes; i++) { - if (planes[i].dcc_enable) { - average_read_bw_gbps += planes[i].read_bw / planes[i].dcc_rate / 1000; - } else { - average_read_bw_gbps += planes[i].read_bw / 1000; - } - - if (planes[i].dcc_enable) { - average_read_bw_gbps += planes[i].read_bw / 1000 / 256; - } - - if (planes[i].pte_enable) { - average_read_bw_gbps += planes[i].read_bw / 1000 / 512; - } - } - - min_full_det_buffer_size_bytes = min_full_det_buffering_time_us * total_data_read_bw_mbps; - rob_fill_size_bytes = mode_lib->ip.rob_buffer_size_kbytes * 1024 * total_data_read_bw_mbps - / (average_read_bw_gbps * 1000); - part_of_burst_that_fits_in_rob = dml_min( - min_full_det_buffer_size_bytes, - rob_fill_size_bytes); - - voltage = -1; - dcfclk_mhz = -1.0; - total_writeback = 0; - - for (i = 0; i < num_pipes; i++) { - /* voltage and dcfclk must be the same for all pipes */ - ASSERT(voltage == -1 || voltage == e2e[i].clks_cfg.voltage); - voltage = e2e[i].clks_cfg.voltage; - ASSERT(dcfclk_mhz == -1.0 || dcfclk_mhz == e2e[i].clks_cfg.dcfclk_mhz); - dcfclk_mhz = e2e[i].clks_cfg.dcfclk_mhz; - - if (e2e[i].dout.output_type == dm_wb) - total_writeback++; - } - - return_bw_mbps = calc_return_bw(mode_lib, planes, num_planes); - - stutter_burst_time_us = part_of_burst_that_fits_in_rob * (average_read_bw_gbps * 1000) - / total_data_read_bw_mbps / return_bw_mbps - + (min_full_det_buffering_time_us * total_data_read_bw_mbps - - part_of_burst_that_fits_in_rob) / (dcfclk_mhz * 64); - - if (total_writeback == 0) { - stutter_eff_not_including_vblank = (1.0 - - ((mode_lib->soc.sr_exit_time_us + stutter_burst_time_us) - / min_full_det_buffering_time_us)) * 100.0; - } else { - stutter_eff_not_including_vblank = 0.0; - } - - smallest_vblank_us = 9999.0; - - for (i = 0; i < num_pipes; i++) { - double vblank_us; - if (e2e[i].pipe.dest.syncronized_vblank_all_planes != 0 || num_pipes == 1) { - vblank_us = (double) (e2e[i].pipe.dest.vtotal + 1 - - e2e[i].pipe.dest.vblank_start - + e2e[i].pipe.dest.vblank_end * e2e[i].pipe.dest.htotal) - / e2e[i].pipe.dest.pixel_rate_mhz; - } else { - vblank_us = 0.0; - } - - smallest_vblank_us = dml_min(smallest_vblank_us, vblank_us); - } - - stutter_eff = 100.0 - * (((stutter_eff_not_including_vblank / 100.0) - * (frame_time_for_min_full_det_buffering_time_us - - smallest_vblank_us) + smallest_vblank_us) - / frame_time_for_min_full_det_buffering_time_us); - - - return stutter_eff; -} - -double urgent_extra_calc( - struct display_mode_lib *mode_lib, - double dcfclk_mhz, - double return_bw_mbps, - unsigned int total_active_dpp, - unsigned int total_dcc_active_dpp) -{ - double urgent_extra_latency_us = 0.0; - double urgent_round_trip_ooo_latency_us; - - urgent_round_trip_ooo_latency_us = - (((double) mode_lib->soc.round_trip_ping_latency_dcfclk_cycles + 32) - / dcfclk_mhz) - + (((double) (mode_lib->soc.urgent_out_of_order_return_per_channel_bytes - * mode_lib->soc.num_chans)) / return_bw_mbps); - - DTRACE( - "INTERMEDIATE round_trip_ping_latency_dcfclk_cycles = %d", - mode_lib->soc.round_trip_ping_latency_dcfclk_cycles); - DTRACE("INTERMEDIATE dcfclk_mhz = %f", dcfclk_mhz); - DTRACE( - "INTERMEDIATE urgent_out_of_order_return_per_channel_bytes = %d", - mode_lib->soc.urgent_out_of_order_return_per_channel_bytes); - - urgent_extra_latency_us = urgent_round_trip_ooo_latency_us - + ((double) total_active_dpp * mode_lib->ip.pixel_chunk_size_kbytes - + (double) total_dcc_active_dpp - * mode_lib->ip.meta_chunk_size_kbytes) - * 1024.0 / return_bw_mbps; /* to us */ - - DTRACE( - "INTERMEDIATE urgent_round_trip_ooo_latency_us = %f", - urgent_round_trip_ooo_latency_us); - DTRACE("INTERMEDIATE total_active_dpp = %d", total_active_dpp); - DTRACE( - "INTERMEDIATE pixel_chunk_size_kbytes = %d", - mode_lib->ip.pixel_chunk_size_kbytes); - DTRACE("INTERMEDIATE total_dcc_active_dpp = %d", total_dcc_active_dpp); - DTRACE( - "INTERMEDIATE meta_chunk_size_kbyte = %d", - mode_lib->ip.meta_chunk_size_kbytes); - DTRACE("INTERMEDIATE return_bw_mbps = %f", return_bw_mbps); - - return urgent_extra_latency_us; -} - -double dml_wm_urgent_extra_max(struct display_mode_lib *mode_lib) -{ - unsigned int total_active_dpp = DC__NUM_DPP; - unsigned int total_dcc_active_dpp = total_active_dpp; - double urgent_extra_latency_us = 0.0; - double dcfclk_mhz = 0.0; - double return_bw_mbps = 0.0; - int voltage = dm_vmin; - - /* use minimum voltage */ - return_bw_mbps = dml_socbb_return_bw_mhz(&mode_lib->soc, (enum voltage_state) voltage); - /* use minimum dcfclk */ - dcfclk_mhz = mode_lib->soc.vmin.dcfclk_mhz; - /* use max dpps and dpps with dcc */ - - urgent_extra_latency_us = urgent_extra_calc( - mode_lib, - dcfclk_mhz, - return_bw_mbps, - total_active_dpp, - total_dcc_active_dpp); - - DTRACE("urgent extra max = %f", urgent_extra_latency_us); - return urgent_extra_latency_us; -} - -double dml_wm_urgent_extra( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *pipes, - unsigned int num_pipes) -{ - unsigned int total_active_dpp = 0; - unsigned int total_dcc_active_dpp = 0; - double urgent_extra_latency_us = 0.0; - double dcfclk_mhz = 0.0; - double return_bw_mbps = 0.0; - int voltage = -1; - bool pte_enable = false; - unsigned int i; - - for (i = 0; i < num_pipes; i++) { - /* num_dpp must be greater than 0 */ - ASSERT(pipes[i].num_dpp > 0); - - /* voltage mode must be the same for all pipes */ - ASSERT(voltage == -1 || voltage == pipes[i].voltage); - voltage = pipes[i].voltage; - - /* dcfclk for all pipes must be the same */ - ASSERT(dcfclk_mhz == 0.0 || dcfclk_mhz == pipes[i].dcfclk_mhz); - dcfclk_mhz = pipes[i].dcfclk_mhz; - - total_active_dpp += pipes[i].num_dpp; - - if (pipes[i].dcc_enable) { - total_dcc_active_dpp += pipes[i].num_dpp; - } - } - - DTRACE("total active dpps %d", total_active_dpp); - DTRACE("total active dpps with dcc %d", total_dcc_active_dpp); - DTRACE("voltage state is %d", voltage); - - return_bw_mbps = calc_return_bw(mode_lib, pipes, num_pipes); - - DTRACE("return_bandwidth is %f MBps", return_bw_mbps); - - pte_enable = calc_pte_enable(pipes, num_pipes); - - /* calculate the maximum extra latency just for comparison purposes */ - /* dml_wm_urgent_extra_max(); */ - urgent_extra_latency_us = urgent_extra_calc( - mode_lib, - dcfclk_mhz, - return_bw_mbps, - total_active_dpp, - total_dcc_active_dpp); - - DTRACE("INTERMEDIATE urgent_extra_latency_us_before_pte = %f", urgent_extra_latency_us); - - if (pte_enable) { - urgent_extra_latency_us += total_active_dpp * mode_lib->ip.pte_chunk_size_kbytes - * 1024.0 / return_bw_mbps; - - DTRACE("INTERMEDIATE pte_enable = true"); - DTRACE("INTERMEDIATE total_active_dpp = %d", total_active_dpp); - DTRACE( - "INTERMEDIATE pte_chunk_size_kbytes = %d", - mode_lib->ip.pte_chunk_size_kbytes); - DTRACE("INTERMEDIATE return_bw_mbps = %f", return_bw_mbps); - } - - return urgent_extra_latency_us; -} - -double dml_wm_urgent_e2e( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *pipes, - unsigned int num_pipes) -{ - struct _vcs_dpi_wm_calc_pipe_params_st *wm = mode_lib->wm_param; - unsigned int combined_pipes; - double urgent_wm; - - memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); - combined_pipes = dml_wm_e2e_to_wm(mode_lib, pipes, num_pipes, wm); - - urgent_wm = dml_wm_urgent(mode_lib, wm, combined_pipes); - - return urgent_wm; -} - -double dml_wm_urgent( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes) -{ - double urgent_watermark; - double urgent_extra_latency_us; - double last_pixel_of_line_extra_wm_us = 0.0; - - DTRACE("calculating urgent watermark"); - calc_display_pipe_line_delivery_time(mode_lib, planes, num_planes); - urgent_extra_latency_us = dml_wm_urgent_extra(mode_lib, planes, num_planes); - - last_pixel_of_line_extra_wm_us = calc_last_pixel_of_line_extra_wm_us( - mode_lib, - planes, - num_planes); - - urgent_watermark = mode_lib->soc.urgent_latency_us + last_pixel_of_line_extra_wm_us - + urgent_extra_latency_us; - - DTRACE("INTERMEDIATE urgent_latency_us = %f", mode_lib->soc.urgent_latency_us); - DTRACE("INTERMEDIATE last_pixel_of_line_extra_wm_us = %f", last_pixel_of_line_extra_wm_us); - DTRACE("INTERMEDIATE urgent_extra_latency_us = %f", urgent_extra_latency_us); - - DTRACE("urgent_watermark_us = %f", urgent_watermark); - return urgent_watermark; -} - -double dml_wm_pte_meta_urgent(struct display_mode_lib *mode_lib, double urgent_wm_us) -{ - double val; - - val = urgent_wm_us + 2.0 * mode_lib->soc.urgent_latency_us; - DTRACE("pte_meta_urgent_watermark_us = %f", val); - - return val; -} - -double dml_wm_dcfclk_deepsleep_mhz_e2e( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *pipes, - unsigned int num_pipes) -{ - struct _vcs_dpi_wm_calc_pipe_params_st *planes = mode_lib->wm_param; - unsigned int num_planes; - double val; - - memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); - num_planes = dml_wm_e2e_to_wm(mode_lib, pipes, num_pipes, planes); - - val = dml_wm_dcfclk_deepsleep_mhz(mode_lib, planes, num_planes); - - return val; -} - -double dml_wm_dcfclk_deepsleep_mhz( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes) -{ - double val = 8.0; - unsigned int i; - - for (i = 0; i < num_planes; i++) { - calc_dcfclk_deepsleep_mhz_per_plane(mode_lib, &planes[i]); - - if (val < planes[i].dcfclk_deepsleep_mhz_per_plane) { - val = planes[i].dcfclk_deepsleep_mhz_per_plane; - } - - DTRACE("plane[%d] start", i); - DTRACE("dcfclk_deepsleep_per_plane = %f", planes[i].dcfclk_deepsleep_mhz_per_plane); - DTRACE("plane[%d] end", i); - } - - DTRACE("dcfclk_deepsleep_mhz = %f", val); - - return val; -} - -struct _vcs_dpi_cstate_pstate_watermarks_st dml_wm_cstate_pstate_e2e( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *pipes, - unsigned int num_pipes) -{ - struct _vcs_dpi_wm_calc_pipe_params_st *wm = mode_lib->wm_param; - unsigned int combined_pipes; - struct _vcs_dpi_cstate_pstate_watermarks_st cstate_pstate_wm; - - memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); - combined_pipes = dml_wm_e2e_to_wm(mode_lib, pipes, num_pipes, wm); - cstate_pstate_wm = dml_wm_cstate_pstate(mode_lib, wm, combined_pipes); - - - return cstate_pstate_wm; -} - -struct _vcs_dpi_cstate_pstate_watermarks_st dml_wm_cstate_pstate( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *pipes, - unsigned int num_pipes) -{ - struct _vcs_dpi_cstate_pstate_watermarks_st wm; - double urgent_extra_latency_us; - double urgent_watermark_us; - double last_pixel_of_line_extra_wm_us; - double dcfclk_deepsleep_freq; - - DTRACE("calculating cstate and pstate watermarks"); - urgent_extra_latency_us = dml_wm_urgent_extra(mode_lib, pipes, num_pipes); - urgent_watermark_us = dml_wm_urgent(mode_lib, pipes, num_pipes); - - last_pixel_of_line_extra_wm_us = calc_last_pixel_of_line_extra_wm_us( - mode_lib, - pipes, - num_pipes); - dcfclk_deepsleep_freq = dml_wm_dcfclk_deepsleep_mhz(mode_lib, pipes, num_pipes); - - wm.cstate_exit_us = mode_lib->soc.sr_exit_time_us + last_pixel_of_line_extra_wm_us - + urgent_extra_latency_us - + mode_lib->ip.dcfclk_cstate_latency / dcfclk_deepsleep_freq; - wm.cstate_enter_plus_exit_us = mode_lib->soc.sr_enter_plus_exit_time_us - + last_pixel_of_line_extra_wm_us + urgent_extra_latency_us; - wm.pstate_change_us = mode_lib->soc.dram_clock_change_latency_us + urgent_watermark_us; - - DTRACE("stutter_exit_watermark_us = %f", wm.cstate_exit_us); - DTRACE("stutter_enter_plus_exit_watermark_us = %f", wm.cstate_enter_plus_exit_us); - DTRACE("dram_clock_change_watermark_us = %f", wm.pstate_change_us); - - return wm; -} - -double dml_wm_writeback_pstate_e2e( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *pipes, - unsigned int num_pipes) -{ - struct _vcs_dpi_wm_calc_pipe_params_st *wm = mode_lib->wm_param; - unsigned int combined_pipes; - - memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); - combined_pipes = dml_wm_e2e_to_wm(mode_lib, pipes, num_pipes, wm); - - - return dml_wm_writeback_pstate(mode_lib, wm, combined_pipes); -} - -double dml_wm_writeback_pstate( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *pipes, - unsigned int num_pipes) -{ - unsigned int total_active_wb = 0; - double wm = 0.0; - double socclk_mhz = 0.0; - unsigned int i; - - DTRACE("calculating wb pstate watermark"); - for (i = 0; i < num_pipes; i++) { - if (pipes[i].output_type == dm_wb) - total_active_wb++; - ASSERT(socclk_mhz == 0.0 || socclk_mhz == pipes[i].socclk_mhz); - socclk_mhz = pipes[i].socclk_mhz; - } - - DTRACE("total wb outputs %d", total_active_wb); - DTRACE("socclk frequency %f Mhz", socclk_mhz); - - if (total_active_wb <= 1) { - wm = mode_lib->soc.writeback_dram_clock_change_latency_us; - } else { - wm = mode_lib->soc.writeback_dram_clock_change_latency_us - + (mode_lib->ip.writeback_chunk_size_kbytes * 1024.0) / 32.0 - / socclk_mhz; - } - - DTRACE("wb pstate watermark %f us", wm); - return wm; -} - -unsigned int dml_wm_e2e_to_wm( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes, - struct _vcs_dpi_wm_calc_pipe_params_st *wm) -{ - unsigned int num_planes = 0; - bool visited[DC__NUM_PIPES]; - unsigned int i, j; - - for (i = 0; i < num_pipes; i++) { - visited[i] = false; - } - - for (i = 0; i < num_pipes; i++) { - unsigned int num_dpp = 1; - - if (visited[i]) { - continue; - } - - visited[i] = true; - - if (e2e[i].pipe.src.is_hsplit) { - for (j = i + 1; j < num_pipes; j++) { - if (e2e[j].pipe.src.is_hsplit && !visited[j] - && (e2e[i].pipe.src.hsplit_grp - == e2e[j].pipe.src.hsplit_grp)) { - num_dpp++; - visited[j] = true; - } - } - } - - wm[num_planes].num_dpp = num_dpp; - wm[num_planes].voltage = e2e[i].clks_cfg.voltage; - wm[num_planes].output_type = e2e[i].dout.output_type; - wm[num_planes].dcfclk_mhz = e2e[i].clks_cfg.dcfclk_mhz; - wm[num_planes].socclk_mhz = e2e[i].clks_cfg.socclk_mhz; - wm[num_planes].dppclk_mhz = e2e[i].clks_cfg.dppclk_mhz; - wm[num_planes].pixclk_mhz = e2e[i].pipe.dest.pixel_rate_mhz; - - wm[num_planes].pte_enable = e2e[i].pipe.src.vm; - wm[num_planes].dcc_enable = e2e[i].pipe.src.dcc; - wm[num_planes].dcc_rate = e2e[i].pipe.src.dcc_rate; - - get_bytes_per_pixel( - (enum source_format_class) e2e[i].pipe.src.source_format, - &wm[num_planes]); - wm[num_planes].swath_width_y = get_swath_width_y(&e2e[i].pipe.src, num_dpp); - get_swath_height( - mode_lib, - &e2e[i].pipe.src, - &wm[num_planes], - wm[num_planes].swath_width_y); - - wm[num_planes].interlace_en = e2e[i].pipe.dest.interlaced; - wm[num_planes].h_ratio = e2e[i].pipe.scale_ratio_depth.hscl_ratio; - wm[num_planes].v_ratio = e2e[i].pipe.scale_ratio_depth.vscl_ratio; - if (wm[num_planes].interlace_en) { - wm[num_planes].v_ratio = 2 * wm[num_planes].v_ratio; - } - wm[num_planes].h_taps = e2e[i].pipe.scale_taps.htaps; - wm[num_planes].h_total = e2e[i].pipe.dest.htotal; - wm[num_planes].v_total = e2e[i].pipe.dest.vtotal; - wm[num_planes].v_active = e2e[i].pipe.dest.vactive; - wm[num_planes].e2e_index = i; - num_planes++; - } - - for (i = 0; i < num_planes; i++) { - DTRACE("plane[%d] start", i); - DTRACE("voltage = %d", wm[i].voltage); - DTRACE("v_active = %d", wm[i].v_active); - DTRACE("h_total = %d", wm[i].h_total); - DTRACE("v_total = %d", wm[i].v_total); - DTRACE("pixclk_mhz = %f", wm[i].pixclk_mhz); - DTRACE("dcfclk_mhz = %f", wm[i].dcfclk_mhz); - DTRACE("dppclk_mhz = %f", wm[i].dppclk_mhz); - DTRACE("h_ratio = %f", wm[i].h_ratio); - DTRACE("v_ratio = %f", wm[i].v_ratio); - DTRACE("interlaced = %d", wm[i].interlace_en); - DTRACE("h_taps = %d", wm[i].h_taps); - DTRACE("num_dpp = %d", wm[i].num_dpp); - DTRACE("swath_width_y = %d", wm[i].swath_width_y); - DTRACE("swath_height_y = %d", wm[i].swath_height_y); - DTRACE("swath_height_c = %d", wm[i].swath_height_c); - DTRACE("det_buffer_size_y = %d", wm[i].det_buffer_size_y); - DTRACE("dcc_rate = %f", wm[i].dcc_rate); - DTRACE("dcc_enable = %s", wm[i].dcc_enable ? "true" : "false"); - DTRACE("pte_enable = %s", wm[i].pte_enable ? "true" : "false"); - DTRACE("plane[%d] end", i); - } - - return num_planes; -} diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_watermark.h b/drivers/gpu/drm/amd/display/dc/dml/display_watermark.h deleted file mode 100644 index 94cde8b55e08..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dml/display_watermark.h +++ /dev/null @@ -1,98 +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 - * - */ -#ifndef __DISPLAY_WATERMARK_H__ -#define __DISPLAY_WATERMARK_H__ - -#include "dml_common_defs.h" - -struct display_mode_lib; - -double dml_wm_urgent_extra( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *pipes, - unsigned int num_pipes); -double dml_wm_urgent_extra_max(struct display_mode_lib *mode_lib); - -double dml_wm_urgent_e2e( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *pipes, - unsigned int num_pipes); -double dml_wm_urgent( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes); -double dml_wm_pte_meta_urgent(struct display_mode_lib *mode_lib, double urgent_wm_us); -double dml_wm_dcfclk_deepsleep_mhz_e2e( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *pipes, - unsigned int num_pipes); -double dml_wm_dcfclk_deepsleep_mhz( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes); - -struct _vcs_dpi_cstate_pstate_watermarks_st dml_wm_cstate_pstate_e2e( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *pipes, - unsigned int num_pipes); -struct _vcs_dpi_cstate_pstate_watermarks_st dml_wm_cstate_pstate( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *pipes, - unsigned int num_pipes); - -double dml_wm_writeback_pstate_e2e( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *pipes, - unsigned int num_pipes); -double dml_wm_writeback_pstate( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *pipes, - unsigned int num_pipes); - -double dml_wm_expected_stutter_eff_e2e( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes); -double dml_wm_expected_stutter_eff_e2e_with_vblank( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes); - -unsigned int dml_wm_e2e_to_wm( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes, - struct _vcs_dpi_wm_calc_pipe_params_st *wm); - -double dml_wm_calc_total_data_read_bw( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes); -double dml_wm_calc_return_bw( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes); - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c new file mode 100644 index 000000000000..1e4b1e383401 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c @@ -0,0 +1,1905 @@ +/* + * 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 "dml1_display_rq_dlg_calc.h" +#include "display_mode_lib.h" + +#include "dml_inline_defs.h" + +static unsigned int get_bytes_per_element(enum source_format_class source_format, bool is_chroma) +{ + unsigned int ret_val = 0; + + if (source_format == dm_444_16) { + if (!is_chroma) + ret_val = 2; + } else if (source_format == dm_444_32) { + if (!is_chroma) + ret_val = 4; + } else if (source_format == dm_444_64) { + if (!is_chroma) + ret_val = 8; + } else if (source_format == dm_420_8) { + if (is_chroma) + ret_val = 2; + else + ret_val = 1; + } else if (source_format == dm_420_10) { + if (is_chroma) + ret_val = 4; + else + ret_val = 2; + } + return ret_val; +} + +static bool is_dual_plane(enum source_format_class source_format) +{ + bool ret_val = 0; + + if ((source_format == dm_420_8) || (source_format == dm_420_10)) + ret_val = 1; + + return ret_val; +} + +static void get_blk256_size( + unsigned int *blk256_width, + unsigned int *blk256_height, + unsigned int bytes_per_element) +{ + if (bytes_per_element == 1) { + *blk256_width = 16; + *blk256_height = 16; + } else if (bytes_per_element == 2) { + *blk256_width = 16; + *blk256_height = 8; + } else if (bytes_per_element == 4) { + *blk256_width = 8; + *blk256_height = 8; + } else if (bytes_per_element == 8) { + *blk256_width = 8; + *blk256_height = 4; + } +} + +static double get_refcyc_per_delivery( + struct display_mode_lib *mode_lib, + double refclk_freq_in_mhz, + double pclk_freq_in_mhz, + unsigned int recout_width, + double vratio, + double hscale_pixel_rate, + unsigned int delivery_width, + unsigned int req_per_swath_ub) +{ + double refcyc_per_delivery = 0.0; + + if (vratio <= 1.0) { + refcyc_per_delivery = (double) refclk_freq_in_mhz * (double) recout_width + / pclk_freq_in_mhz / (double) req_per_swath_ub; + } else { + refcyc_per_delivery = (double) refclk_freq_in_mhz * (double) delivery_width + / (double) hscale_pixel_rate / (double) req_per_swath_ub; + } + + DTRACE("DLG: %s: refclk_freq_in_mhz = %3.2f", __func__, refclk_freq_in_mhz); + DTRACE("DLG: %s: pclk_freq_in_mhz = %3.2f", __func__, pclk_freq_in_mhz); + DTRACE("DLG: %s: recout_width = %d", __func__, recout_width); + DTRACE("DLG: %s: vratio = %3.2f", __func__, vratio); + DTRACE("DLG: %s: req_per_swath_ub = %d", __func__, req_per_swath_ub); + DTRACE("DLG: %s: refcyc_per_delivery= %3.2f", __func__, refcyc_per_delivery); + + return refcyc_per_delivery; + +} + +static double get_vratio_pre( + struct display_mode_lib *mode_lib, + unsigned int max_num_sw, + unsigned int max_partial_sw, + unsigned int swath_height, + double vinit, + double l_sw) +{ + double prefill = dml_floor(vinit, 1); + double vratio_pre = 1.0; + + vratio_pre = (max_num_sw * swath_height + max_partial_sw) / l_sw; + + if (swath_height > 4) { + double tmp0 = (max_num_sw * swath_height) / (l_sw - (prefill - 3.0) / 2.0); + + if (tmp0 > vratio_pre) + vratio_pre = tmp0; + } + + DTRACE("DLG: %s: max_num_sw = %0d", __func__, max_num_sw); + DTRACE("DLG: %s: max_partial_sw = %0d", __func__, max_partial_sw); + DTRACE("DLG: %s: swath_height = %0d", __func__, swath_height); + DTRACE("DLG: %s: vinit = %3.2f", __func__, vinit); + DTRACE("DLG: %s: vratio_pre = %3.2f", __func__, vratio_pre); + + if (vratio_pre < 1.0) { + DTRACE("WARNING_DLG: %s: vratio_pre=%3.2f < 1.0, set to 1.0", __func__, vratio_pre); + vratio_pre = 1.0; + } + + if (vratio_pre > 4.0) { + DTRACE( + "WARNING_DLG: %s: vratio_pre=%3.2f > 4.0 (max scaling ratio). set to 4.0", + __func__, + vratio_pre); + vratio_pre = 4.0; + } + + return vratio_pre; +} + +static void get_swath_need( + struct display_mode_lib *mode_lib, + unsigned int *max_num_sw, + unsigned int *max_partial_sw, + unsigned int swath_height, + double vinit) +{ + double prefill = dml_floor(vinit, 1); + unsigned int max_partial_sw_int; + + DTRACE("DLG: %s: swath_height = %0d", __func__, swath_height); + DTRACE("DLG: %s: vinit = %3.2f", __func__, vinit); + + ASSERT(prefill > 0.0 && prefill <= 8.0); + + *max_num_sw = (unsigned int) (dml_ceil((prefill - 1.0) / (double) swath_height, 1) + 1.0); /* prefill has to be >= 1 */ + max_partial_sw_int = + (prefill == 1) ? + (swath_height - 1) : + ((unsigned int) (prefill - 2.0) % swath_height); + *max_partial_sw = (max_partial_sw_int < 1) ? 1 : max_partial_sw_int; /* ensure minimum of 1 is used */ + + DTRACE("DLG: %s: max_num_sw = %0d", __func__, *max_num_sw); + DTRACE("DLG: %s: max_partial_sw = %0d", __func__, *max_partial_sw); +} + +static unsigned int get_blk_size_bytes(const enum source_macro_tile_size tile_size) +{ + if (tile_size == dm_256k_tile) + return (256 * 1024); + else if (tile_size == dm_64k_tile) + return (64 * 1024); + else + return (4 * 1024); +} + +static void extract_rq_sizing_regs( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_regs_st *rq_regs, + const struct _vcs_dpi_display_data_rq_sizing_params_st rq_sizing) +{ + DTRACE("DLG: %s: rq_sizing param", __func__); + print__data_rq_sizing_params_st(mode_lib, rq_sizing); + + rq_regs->chunk_size = dml_log2(rq_sizing.chunk_bytes) - 10; + + if (rq_sizing.min_chunk_bytes == 0) + rq_regs->min_chunk_size = 0; + else + rq_regs->min_chunk_size = dml_log2(rq_sizing.min_chunk_bytes) - 8 + 1; + + rq_regs->meta_chunk_size = dml_log2(rq_sizing.meta_chunk_bytes) - 10; + if (rq_sizing.min_meta_chunk_bytes == 0) + rq_regs->min_meta_chunk_size = 0; + else + rq_regs->min_meta_chunk_size = dml_log2(rq_sizing.min_meta_chunk_bytes) - 6 + 1; + + rq_regs->dpte_group_size = dml_log2(rq_sizing.dpte_group_bytes) - 6; + rq_regs->mpte_group_size = dml_log2(rq_sizing.mpte_group_bytes) - 6; +} + +void dml1_extract_rq_regs( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_regs_st *rq_regs, + const struct _vcs_dpi_display_rq_params_st rq_param) +{ + unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; + unsigned int detile_buf_plane1_addr = 0; + + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), rq_param.sizing.rq_l); + if (rq_param.yuv420) + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), rq_param.sizing.rq_c); + + rq_regs->rq_regs_l.swath_height = dml_log2(rq_param.dlg.rq_l.swath_height); + rq_regs->rq_regs_c.swath_height = dml_log2(rq_param.dlg.rq_c.swath_height); + + /* FIXME: take the max between luma, chroma chunk size? + * okay for now, as we are setting chunk_bytes to 8kb anyways + */ + if (rq_param.sizing.rq_l.chunk_bytes >= 32 * 1024) { /*32kb */ + rq_regs->drq_expansion_mode = 0; + } else { + rq_regs->drq_expansion_mode = 2; + } + rq_regs->prq_expansion_mode = 1; + rq_regs->mrq_expansion_mode = 1; + rq_regs->crq_expansion_mode = 1; + + if (rq_param.yuv420) { + if ((double) rq_param.misc.rq_l.stored_swath_bytes + / (double) rq_param.misc.rq_c.stored_swath_bytes <= 1.5) { + detile_buf_plane1_addr = (detile_buf_size_in_bytes / 2.0 / 64.0); /* half to chroma */ + } else { + detile_buf_plane1_addr = dml_round_to_multiple( + (unsigned int) ((2.0 * detile_buf_size_in_bytes) / 3.0), + 256, + 0) / 64.0; /* 2/3 to chroma */ + } + } + rq_regs->plane1_base_address = detile_buf_plane1_addr; +} + +static void handle_det_buf_split( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_params_st *rq_param, + const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param) +{ + unsigned int total_swath_bytes = 0; + unsigned int swath_bytes_l = 0; + unsigned int swath_bytes_c = 0; + unsigned int full_swath_bytes_packed_l = 0; + unsigned int full_swath_bytes_packed_c = 0; + bool req128_l = 0; + bool req128_c = 0; + bool surf_linear = (pipe_src_param.sw_mode == dm_sw_linear); + bool surf_vert = (pipe_src_param.source_scan == dm_vert); + unsigned int log2_swath_height_l = 0; + unsigned int log2_swath_height_c = 0; + unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; + + full_swath_bytes_packed_l = rq_param->misc.rq_l.full_swath_bytes; + full_swath_bytes_packed_c = rq_param->misc.rq_c.full_swath_bytes; + + if (rq_param->yuv420_10bpc) { + full_swath_bytes_packed_l = dml_round_to_multiple( + rq_param->misc.rq_l.full_swath_bytes * 2 / 3, + 256, + 1) + 256; + full_swath_bytes_packed_c = dml_round_to_multiple( + rq_param->misc.rq_c.full_swath_bytes * 2 / 3, + 256, + 1) + 256; + } + + if (rq_param->yuv420) { + total_swath_bytes = 2 * full_swath_bytes_packed_l + 2 * full_swath_bytes_packed_c; + + if (total_swath_bytes <= detile_buf_size_in_bytes) { /*full 256b request */ + req128_l = 0; + req128_c = 0; + swath_bytes_l = full_swath_bytes_packed_l; + swath_bytes_c = full_swath_bytes_packed_c; + } else { /*128b request (for luma only for yuv420 8bpc) */ + req128_l = 1; + req128_c = 0; + swath_bytes_l = full_swath_bytes_packed_l / 2; + swath_bytes_c = full_swath_bytes_packed_c; + } + + /* Bug workaround, luma and chroma req size needs to be the same. (see: DEGVIDCN10-137) + * TODO: Remove after rtl fix + */ + if (req128_l == 1) { + req128_c = 1; + DTRACE("DLG: %s: bug workaround DEGVIDCN10-137", __func__); + } + + /* Note: assumption, the config that pass in will fit into + * the detiled buffer. + */ + } else { + total_swath_bytes = 2 * full_swath_bytes_packed_l; + + if (total_swath_bytes <= detile_buf_size_in_bytes) + req128_l = 0; + else + req128_l = 1; + + swath_bytes_l = total_swath_bytes; + swath_bytes_c = 0; + } + rq_param->misc.rq_l.stored_swath_bytes = swath_bytes_l; + rq_param->misc.rq_c.stored_swath_bytes = swath_bytes_c; + + if (surf_linear) { + log2_swath_height_l = 0; + log2_swath_height_c = 0; + } else if (!surf_vert) { + log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_height) - req128_l; + log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_height) - req128_c; + } else { + log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_width) - req128_l; + log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_width) - req128_c; + } + rq_param->dlg.rq_l.swath_height = 1 << log2_swath_height_l; + rq_param->dlg.rq_c.swath_height = 1 << log2_swath_height_c; + + DTRACE("DLG: %s: req128_l = %0d", __func__, req128_l); + DTRACE("DLG: %s: req128_c = %0d", __func__, req128_c); + DTRACE("DLG: %s: full_swath_bytes_packed_l = %0d", __func__, full_swath_bytes_packed_l); + DTRACE("DLG: %s: full_swath_bytes_packed_c = %0d", __func__, full_swath_bytes_packed_c); +} + +/* Need refactor. */ +static void dml1_rq_dlg_get_row_heights( + struct display_mode_lib *mode_lib, + unsigned int *o_dpte_row_height, + unsigned int *o_meta_row_height, + unsigned int vp_width, + unsigned int data_pitch, + int source_format, + int tiling, + int macro_tile_size, + int source_scan, + int is_chroma) +{ + bool surf_linear = (tiling == dm_sw_linear); + bool surf_vert = (source_scan == dm_vert); + + unsigned int bytes_per_element = get_bytes_per_element( + (enum source_format_class) source_format, + is_chroma); + unsigned int log2_bytes_per_element = dml_log2(bytes_per_element); + unsigned int blk256_width = 0; + unsigned int blk256_height = 0; + + unsigned int log2_blk256_height; + unsigned int blk_bytes; + unsigned int log2_blk_bytes; + unsigned int log2_blk_height; + unsigned int log2_blk_width; + unsigned int log2_meta_req_bytes; + unsigned int log2_meta_req_height; + unsigned int log2_meta_req_width; + unsigned int log2_meta_row_height; + unsigned int log2_vmpg_bytes; + unsigned int dpte_buf_in_pte_reqs; + unsigned int log2_vmpg_height; + unsigned int log2_vmpg_width; + unsigned int log2_dpte_req_height_ptes; + unsigned int log2_dpte_req_width_ptes; + unsigned int log2_dpte_req_height; + unsigned int log2_dpte_req_width; + unsigned int log2_dpte_row_height_linear; + unsigned int log2_dpte_row_height; + unsigned int dpte_req_width; + + if (surf_linear) { + blk256_width = 256; + blk256_height = 1; + } else { + get_blk256_size(&blk256_width, &blk256_height, bytes_per_element); + } + + log2_blk256_height = dml_log2((double) blk256_height); + blk_bytes = surf_linear ? + 256 : get_blk_size_bytes((enum source_macro_tile_size) macro_tile_size); + log2_blk_bytes = dml_log2((double) blk_bytes); + log2_blk_height = 0; + log2_blk_width = 0; + + /* remember log rule + * "+" in log is multiply + * "-" in log is divide + * "/2" is like square root + * blk is vertical biased + */ + if (tiling != dm_sw_linear) + log2_blk_height = log2_blk256_height + + dml_ceil((double) (log2_blk_bytes - 8) / 2.0, 1); + else + log2_blk_height = 0; /* blk height of 1 */ + + log2_blk_width = log2_blk_bytes - log2_bytes_per_element - log2_blk_height; + + /* ------- */ + /* meta */ + /* ------- */ + log2_meta_req_bytes = 6; /* meta request is 64b and is 8x8byte meta element */ + + /* each 64b meta request for dcn is 8x8 meta elements and + * a meta element covers one 256b block of the the data surface. + */ + log2_meta_req_height = log2_blk256_height + 3; /* meta req is 8x8 */ + log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element + - log2_meta_req_height; + log2_meta_row_height = 0; + + /* the dimensions of a meta row are meta_row_width x meta_row_height in elements. + * calculate upper bound of the meta_row_width + */ + if (!surf_vert) + log2_meta_row_height = log2_meta_req_height; + else + log2_meta_row_height = log2_meta_req_width; + + *o_meta_row_height = 1 << log2_meta_row_height; + + /* ------ */ + /* dpte */ + /* ------ */ + log2_vmpg_bytes = dml_log2(mode_lib->soc.vmm_page_size_bytes); + dpte_buf_in_pte_reqs = mode_lib->ip.dpte_buffer_size_in_pte_reqs; + + log2_vmpg_height = 0; + log2_vmpg_width = 0; + log2_dpte_req_height_ptes = 0; + log2_dpte_req_width_ptes = 0; + log2_dpte_req_height = 0; + log2_dpte_req_width = 0; + log2_dpte_row_height_linear = 0; + log2_dpte_row_height = 0; + dpte_req_width = 0; /* 64b dpte req width in data element */ + + if (surf_linear) + log2_vmpg_height = 0; /* one line high */ + else + log2_vmpg_height = (log2_vmpg_bytes - 8) / 2 + log2_blk256_height; + log2_vmpg_width = log2_vmpg_bytes - log2_bytes_per_element - log2_vmpg_height; + + /* only 3 possible shapes for dpte request in dimensions of ptes: 8x1, 4x2, 2x4. */ + if (log2_blk_bytes <= log2_vmpg_bytes) + log2_dpte_req_height_ptes = 0; + else if (log2_blk_height - log2_vmpg_height >= 2) + log2_dpte_req_height_ptes = 2; + else + log2_dpte_req_height_ptes = log2_blk_height - log2_vmpg_height; + log2_dpte_req_width_ptes = 3 - log2_dpte_req_height_ptes; + + ASSERT((log2_dpte_req_width_ptes == 3 && log2_dpte_req_height_ptes == 0) || /* 8x1 */ + (log2_dpte_req_width_ptes == 2 && log2_dpte_req_height_ptes == 1) || /* 4x2 */ + (log2_dpte_req_width_ptes == 1 && log2_dpte_req_height_ptes == 2)); /* 2x4 */ + + /* the dpte request dimensions in data elements is dpte_req_width x dpte_req_height + * log2_wmpg_width is how much 1 pte represent, now trying to calculate how much 64b pte req represent + */ + log2_dpte_req_height = log2_vmpg_height + log2_dpte_req_height_ptes; + log2_dpte_req_width = log2_vmpg_width + log2_dpte_req_width_ptes; + dpte_req_width = 1 << log2_dpte_req_width; + + /* calculate pitch dpte row buffer can hold + * round the result down to a power of two. + */ + if (surf_linear) { + log2_dpte_row_height_linear = dml_floor( + dml_log2(dpte_buf_in_pte_reqs * dpte_req_width / data_pitch), + 1); + + ASSERT(log2_dpte_row_height_linear >= 3); + + if (log2_dpte_row_height_linear > 7) + log2_dpte_row_height_linear = 7; + + log2_dpte_row_height = log2_dpte_row_height_linear; + } else { + /* the upper bound of the dpte_row_width without dependency on viewport position follows. */ + if (!surf_vert) + log2_dpte_row_height = log2_dpte_req_height; + else + log2_dpte_row_height = + (log2_blk_width < log2_dpte_req_width) ? + log2_blk_width : log2_dpte_req_width; + } + + /* From programming guide: + * There is a special case of saving only half of ptes returned due to buffer space limits. + * this case applies to 4 and 8bpe in horizontal access of a vp_width greater than 2560+16 + * when the pte request is 2x4 ptes (which happens when vmpg_bytes =4kb and tile blk_bytes >=64kb). + */ + if (!surf_vert && vp_width > (2560 + 16) && bytes_per_element >= 4 && log2_vmpg_bytes == 12 + && log2_blk_bytes >= 16) + log2_dpte_row_height = log2_dpte_row_height - 1; /*half of the full height */ + + *o_dpte_row_height = 1 << log2_dpte_row_height; +} + +static void get_surf_rq_param( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_sizing_params_st *rq_sizing_param, + struct _vcs_dpi_display_data_rq_dlg_params_st *rq_dlg_param, + struct _vcs_dpi_display_data_rq_misc_params_st *rq_misc_param, + const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param, + bool is_chroma) +{ + bool mode_422 = 0; + unsigned int vp_width = 0; + unsigned int vp_height = 0; + unsigned int data_pitch = 0; + unsigned int meta_pitch = 0; + unsigned int ppe = mode_422 ? 2 : 1; + bool surf_linear; + bool surf_vert; + unsigned int bytes_per_element; + unsigned int log2_bytes_per_element; + unsigned int blk256_width; + unsigned int blk256_height; + unsigned int log2_blk256_width; + unsigned int log2_blk256_height; + unsigned int blk_bytes; + unsigned int log2_blk_bytes; + unsigned int log2_blk_height; + unsigned int log2_blk_width; + unsigned int log2_meta_req_bytes; + unsigned int log2_meta_req_height; + unsigned int log2_meta_req_width; + unsigned int meta_req_width; + unsigned int meta_req_height; + unsigned int log2_meta_row_height; + unsigned int meta_row_width_ub; + unsigned int log2_meta_chunk_bytes; + unsigned int log2_meta_chunk_height; + unsigned int log2_meta_chunk_width; + unsigned int log2_min_meta_chunk_bytes; + unsigned int min_meta_chunk_width; + unsigned int meta_chunk_width; + unsigned int meta_chunk_per_row_int; + unsigned int meta_row_remainder; + unsigned int meta_chunk_threshold; + unsigned int meta_blk_bytes; + unsigned int meta_blk_height; + unsigned int meta_blk_width; + unsigned int meta_surface_bytes; + unsigned int vmpg_bytes; + unsigned int meta_pte_req_per_frame_ub; + unsigned int meta_pte_bytes_per_frame_ub; + unsigned int log2_vmpg_bytes; + unsigned int dpte_buf_in_pte_reqs; + unsigned int log2_vmpg_height; + unsigned int log2_vmpg_width; + unsigned int log2_dpte_req_height_ptes; + unsigned int log2_dpte_req_width_ptes; + unsigned int log2_dpte_req_height; + unsigned int log2_dpte_req_width; + unsigned int log2_dpte_row_height_linear; + unsigned int log2_dpte_row_height; + unsigned int log2_dpte_group_width; + unsigned int dpte_row_width_ub; + unsigned int dpte_row_height; + unsigned int dpte_req_height; + unsigned int dpte_req_width; + unsigned int dpte_group_width; + unsigned int log2_dpte_group_bytes; + unsigned int log2_dpte_group_length; + unsigned int func_meta_row_height, func_dpte_row_height; + + /* FIXME check if ppe apply for both luma and chroma in 422 case */ + if (is_chroma) { + vp_width = pipe_src_param.viewport_width_c / ppe; + vp_height = pipe_src_param.viewport_height_c; + data_pitch = pipe_src_param.data_pitch_c; + meta_pitch = pipe_src_param.meta_pitch_c; + } else { + vp_width = pipe_src_param.viewport_width / ppe; + vp_height = pipe_src_param.viewport_height; + data_pitch = pipe_src_param.data_pitch; + meta_pitch = pipe_src_param.meta_pitch; + } + + rq_sizing_param->chunk_bytes = 8192; + + if (rq_sizing_param->chunk_bytes == 64 * 1024) + rq_sizing_param->min_chunk_bytes = 0; + else + rq_sizing_param->min_chunk_bytes = 1024; + + rq_sizing_param->meta_chunk_bytes = 2048; + rq_sizing_param->min_meta_chunk_bytes = 256; + + rq_sizing_param->mpte_group_bytes = 2048; + + surf_linear = (pipe_src_param.sw_mode == dm_sw_linear); + surf_vert = (pipe_src_param.source_scan == dm_vert); + + bytes_per_element = get_bytes_per_element( + (enum source_format_class) pipe_src_param.source_format, + is_chroma); + log2_bytes_per_element = dml_log2(bytes_per_element); + blk256_width = 0; + blk256_height = 0; + + if (surf_linear) { + blk256_width = 256 / bytes_per_element; + blk256_height = 1; + } else { + get_blk256_size(&blk256_width, &blk256_height, bytes_per_element); + } + + DTRACE("DLG: %s: surf_linear = %d", __func__, surf_linear); + DTRACE("DLG: %s: surf_vert = %d", __func__, surf_vert); + DTRACE("DLG: %s: blk256_width = %d", __func__, blk256_width); + DTRACE("DLG: %s: blk256_height = %d", __func__, blk256_height); + + log2_blk256_width = dml_log2((double) blk256_width); + log2_blk256_height = dml_log2((double) blk256_height); + blk_bytes = + surf_linear ? 256 : get_blk_size_bytes( + (enum source_macro_tile_size) pipe_src_param.macro_tile_size); + log2_blk_bytes = dml_log2((double) blk_bytes); + log2_blk_height = 0; + log2_blk_width = 0; + + /* remember log rule + * "+" in log is multiply + * "-" in log is divide + * "/2" is like square root + * blk is vertical biased + */ + if (pipe_src_param.sw_mode != dm_sw_linear) + log2_blk_height = log2_blk256_height + + dml_ceil((double) (log2_blk_bytes - 8) / 2.0, 1); + else + log2_blk_height = 0; /* blk height of 1 */ + + log2_blk_width = log2_blk_bytes - log2_bytes_per_element - log2_blk_height; + + if (!surf_vert) { + rq_dlg_param->swath_width_ub = dml_round_to_multiple(vp_width - 1, blk256_width, 1) + + blk256_width; + rq_dlg_param->req_per_swath_ub = rq_dlg_param->swath_width_ub >> log2_blk256_width; + } else { + rq_dlg_param->swath_width_ub = dml_round_to_multiple( + vp_height - 1, + blk256_height, + 1) + blk256_height; + rq_dlg_param->req_per_swath_ub = rq_dlg_param->swath_width_ub >> log2_blk256_height; + } + + if (!surf_vert) + rq_misc_param->full_swath_bytes = rq_dlg_param->swath_width_ub * blk256_height + * bytes_per_element; + else + rq_misc_param->full_swath_bytes = rq_dlg_param->swath_width_ub * blk256_width + * bytes_per_element; + + rq_misc_param->blk256_height = blk256_height; + rq_misc_param->blk256_width = blk256_width; + + /* ------- */ + /* meta */ + /* ------- */ + log2_meta_req_bytes = 6; /* meta request is 64b and is 8x8byte meta element */ + + /* each 64b meta request for dcn is 8x8 meta elements and + * a meta element covers one 256b block of the the data surface. + */ + log2_meta_req_height = log2_blk256_height + 3; /* meta req is 8x8 byte, each byte represent 1 blk256 */ + log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element + - log2_meta_req_height; + meta_req_width = 1 << log2_meta_req_width; + meta_req_height = 1 << log2_meta_req_height; + log2_meta_row_height = 0; + meta_row_width_ub = 0; + + /* the dimensions of a meta row are meta_row_width x meta_row_height in elements. + * calculate upper bound of the meta_row_width + */ + if (!surf_vert) { + log2_meta_row_height = log2_meta_req_height; + meta_row_width_ub = dml_round_to_multiple(vp_width - 1, meta_req_width, 1) + + meta_req_width; + rq_dlg_param->meta_req_per_row_ub = meta_row_width_ub / meta_req_width; + } else { + log2_meta_row_height = log2_meta_req_width; + meta_row_width_ub = dml_round_to_multiple(vp_height - 1, meta_req_height, 1) + + meta_req_height; + rq_dlg_param->meta_req_per_row_ub = meta_row_width_ub / meta_req_height; + } + rq_dlg_param->meta_bytes_per_row_ub = rq_dlg_param->meta_req_per_row_ub * 64; + + log2_meta_chunk_bytes = dml_log2(rq_sizing_param->meta_chunk_bytes); + log2_meta_chunk_height = log2_meta_row_height; + + /*full sized meta chunk width in unit of data elements */ + log2_meta_chunk_width = log2_meta_chunk_bytes + 8 - log2_bytes_per_element + - log2_meta_chunk_height; + log2_min_meta_chunk_bytes = dml_log2(rq_sizing_param->min_meta_chunk_bytes); + min_meta_chunk_width = 1 + << (log2_min_meta_chunk_bytes + 8 - log2_bytes_per_element + - log2_meta_chunk_height); + meta_chunk_width = 1 << log2_meta_chunk_width; + meta_chunk_per_row_int = (unsigned int) (meta_row_width_ub / meta_chunk_width); + meta_row_remainder = meta_row_width_ub % meta_chunk_width; + meta_chunk_threshold = 0; + meta_blk_bytes = 4096; + meta_blk_height = blk256_height * 64; + meta_blk_width = meta_blk_bytes * 256 / bytes_per_element / meta_blk_height; + meta_surface_bytes = meta_pitch + * (dml_round_to_multiple(vp_height - 1, meta_blk_height, 1) + + meta_blk_height) * bytes_per_element / 256; + vmpg_bytes = mode_lib->soc.vmm_page_size_bytes; + meta_pte_req_per_frame_ub = (dml_round_to_multiple( + meta_surface_bytes - vmpg_bytes, + 8 * vmpg_bytes, + 1) + 8 * vmpg_bytes) / (8 * vmpg_bytes); + meta_pte_bytes_per_frame_ub = meta_pte_req_per_frame_ub * 64; /*64B mpte request */ + rq_dlg_param->meta_pte_bytes_per_frame_ub = meta_pte_bytes_per_frame_ub; + + DTRACE("DLG: %s: meta_blk_height = %d", __func__, meta_blk_height); + DTRACE("DLG: %s: meta_blk_width = %d", __func__, meta_blk_width); + DTRACE("DLG: %s: meta_surface_bytes = %d", __func__, meta_surface_bytes); + DTRACE("DLG: %s: meta_pte_req_per_frame_ub = %d", __func__, meta_pte_req_per_frame_ub); + DTRACE("DLG: %s: meta_pte_bytes_per_frame_ub = %d", __func__, meta_pte_bytes_per_frame_ub); + + if (!surf_vert) + meta_chunk_threshold = 2 * min_meta_chunk_width - meta_req_width; + else + meta_chunk_threshold = 2 * min_meta_chunk_width - meta_req_height; + + if (meta_row_remainder <= meta_chunk_threshold) + rq_dlg_param->meta_chunks_per_row_ub = meta_chunk_per_row_int + 1; + else + rq_dlg_param->meta_chunks_per_row_ub = meta_chunk_per_row_int + 2; + + rq_dlg_param->meta_row_height = 1 << log2_meta_row_height; + + /* ------ */ + /* dpte */ + /* ------ */ + log2_vmpg_bytes = dml_log2(mode_lib->soc.vmm_page_size_bytes); + dpte_buf_in_pte_reqs = mode_lib->ip.dpte_buffer_size_in_pte_reqs; + + log2_vmpg_height = 0; + log2_vmpg_width = 0; + log2_dpte_req_height_ptes = 0; + log2_dpte_req_width_ptes = 0; + log2_dpte_req_height = 0; + log2_dpte_req_width = 0; + log2_dpte_row_height_linear = 0; + log2_dpte_row_height = 0; + log2_dpte_group_width = 0; + dpte_row_width_ub = 0; + dpte_row_height = 0; + dpte_req_height = 0; /* 64b dpte req height in data element */ + dpte_req_width = 0; /* 64b dpte req width in data element */ + dpte_group_width = 0; + log2_dpte_group_bytes = 0; + log2_dpte_group_length = 0; + + if (surf_linear) + log2_vmpg_height = 0; /* one line high */ + else + log2_vmpg_height = (log2_vmpg_bytes - 8) / 2 + log2_blk256_height; + log2_vmpg_width = log2_vmpg_bytes - log2_bytes_per_element - log2_vmpg_height; + + /* only 3 possible shapes for dpte request in dimensions of ptes: 8x1, 4x2, 2x4. */ + if (log2_blk_bytes <= log2_vmpg_bytes) + log2_dpte_req_height_ptes = 0; + else if (log2_blk_height - log2_vmpg_height >= 2) + log2_dpte_req_height_ptes = 2; + else + log2_dpte_req_height_ptes = log2_blk_height - log2_vmpg_height; + log2_dpte_req_width_ptes = 3 - log2_dpte_req_height_ptes; + + /* Ensure we only have the 3 shapes */ + ASSERT((log2_dpte_req_width_ptes == 3 && log2_dpte_req_height_ptes == 0) || /* 8x1 */ + (log2_dpte_req_width_ptes == 2 && log2_dpte_req_height_ptes == 1) || /* 4x2 */ + (log2_dpte_req_width_ptes == 1 && log2_dpte_req_height_ptes == 2)); /* 2x4 */ + + /* The dpte request dimensions in data elements is dpte_req_width x dpte_req_height + * log2_vmpg_width is how much 1 pte represent, now calculating how much a 64b pte req represent + * That depends on the pte shape (i.e. 8x1, 4x2, 2x4) + */ + log2_dpte_req_height = log2_vmpg_height + log2_dpte_req_height_ptes; + log2_dpte_req_width = log2_vmpg_width + log2_dpte_req_width_ptes; + dpte_req_height = 1 << log2_dpte_req_height; + dpte_req_width = 1 << log2_dpte_req_width; + + /* calculate pitch dpte row buffer can hold + * round the result down to a power of two. + */ + if (surf_linear) { + log2_dpte_row_height_linear = dml_floor( + dml_log2(dpte_buf_in_pte_reqs * dpte_req_width / data_pitch), + 1); + + ASSERT(log2_dpte_row_height_linear >= 3); + + if (log2_dpte_row_height_linear > 7) + log2_dpte_row_height_linear = 7; + + log2_dpte_row_height = log2_dpte_row_height_linear; + rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height; + + /* For linear, the dpte row is pitch dependent and the pte requests wrap at the pitch boundary. + * the dpte_row_width_ub is the upper bound of data_pitch*dpte_row_height in elements with this unique buffering. + */ + dpte_row_width_ub = dml_round_to_multiple( + data_pitch * dpte_row_height - 1, + dpte_req_width, + 1) + dpte_req_width; + rq_dlg_param->dpte_req_per_row_ub = dpte_row_width_ub / dpte_req_width; + } else { + /* for tiled mode, row height is the same as req height and row store up to vp size upper bound */ + if (!surf_vert) { + log2_dpte_row_height = log2_dpte_req_height; + dpte_row_width_ub = dml_round_to_multiple(vp_width - 1, dpte_req_width, 1) + + dpte_req_width; + rq_dlg_param->dpte_req_per_row_ub = dpte_row_width_ub / dpte_req_width; + } else { + log2_dpte_row_height = + (log2_blk_width < log2_dpte_req_width) ? + log2_blk_width : log2_dpte_req_width; + dpte_row_width_ub = dml_round_to_multiple(vp_height - 1, dpte_req_height, 1) + + dpte_req_height; + rq_dlg_param->dpte_req_per_row_ub = dpte_row_width_ub / dpte_req_height; + } + rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height; + } + rq_dlg_param->dpte_bytes_per_row_ub = rq_dlg_param->dpte_req_per_row_ub * 64; + + /* From programming guide: + * There is a special case of saving only half of ptes returned due to buffer space limits. + * this case applies to 4 and 8bpe in horizontal access of a vp_width greater than 2560+16 + * when the pte request is 2x4 ptes (which happens when vmpg_bytes =4kb and tile blk_bytes >=64kb). + */ + if (!surf_vert && vp_width > (2560 + 16) && bytes_per_element >= 4 && log2_vmpg_bytes == 12 + && log2_blk_bytes >= 16) { + log2_dpte_row_height = log2_dpte_row_height - 1; /*half of the full height */ + rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height; + } + + /* the dpte_group_bytes is reduced for the specific case of vertical + * access of a tile surface that has dpte request of 8x1 ptes. + */ + if (!surf_linear & (log2_dpte_req_height_ptes == 0) & surf_vert) /*reduced, in this case, will have page fault within a group */ + rq_sizing_param->dpte_group_bytes = 512; + else + /*full size */ + rq_sizing_param->dpte_group_bytes = 2048; + + /*since pte request size is 64byte, the number of data pte requests per full sized group is as follows. */ + log2_dpte_group_bytes = dml_log2(rq_sizing_param->dpte_group_bytes); + log2_dpte_group_length = log2_dpte_group_bytes - 6; /*length in 64b requests */ + + /* full sized data pte group width in elements */ + if (!surf_vert) + log2_dpte_group_width = log2_dpte_group_length + log2_dpte_req_width; + else + log2_dpte_group_width = log2_dpte_group_length + log2_dpte_req_height; + + dpte_group_width = 1 << log2_dpte_group_width; + + /* since dpte groups are only aligned to dpte_req_width and not dpte_group_width, + * the upper bound for the dpte groups per row is as follows. + */ + rq_dlg_param->dpte_groups_per_row_ub = dml_ceil( + (double) dpte_row_width_ub / dpte_group_width, + 1); + + dml1_rq_dlg_get_row_heights( + mode_lib, + &func_dpte_row_height, + &func_meta_row_height, + vp_width, + data_pitch, + pipe_src_param.source_format, + pipe_src_param.sw_mode, + pipe_src_param.macro_tile_size, + pipe_src_param.source_scan, + is_chroma); + + /* Just a check to make sure this function and the new one give the same + * result. The standalone get_row_heights() function is based off of the + * code in this function so the same changes need to be made to both. + */ + if (rq_dlg_param->meta_row_height != func_meta_row_height) { + DTRACE( + "MISMATCH: rq_dlg_param->meta_row_height = %d", + rq_dlg_param->meta_row_height); + DTRACE("MISMATCH: func_meta_row_height = %d", func_meta_row_height); + ASSERT(0); + } + + if (rq_dlg_param->dpte_row_height != func_dpte_row_height) { + DTRACE( + "MISMATCH: rq_dlg_param->dpte_row_height = %d", + rq_dlg_param->dpte_row_height); + DTRACE("MISMATCH: func_dpte_row_height = %d", func_dpte_row_height); + ASSERT(0); + } +} + +void dml1_rq_dlg_get_rq_params( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_params_st *rq_param, + const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param) +{ + /* get param for luma surface */ + rq_param->yuv420 = pipe_src_param.source_format == dm_420_8 + || pipe_src_param.source_format == dm_420_10; + rq_param->yuv420_10bpc = pipe_src_param.source_format == dm_420_10; + + get_surf_rq_param( + mode_lib, + &(rq_param->sizing.rq_l), + &(rq_param->dlg.rq_l), + &(rq_param->misc.rq_l), + pipe_src_param, + 0); + + if (is_dual_plane((enum source_format_class) pipe_src_param.source_format)) { + /* get param for chroma surface */ + get_surf_rq_param( + mode_lib, + &(rq_param->sizing.rq_c), + &(rq_param->dlg.rq_c), + &(rq_param->misc.rq_c), + pipe_src_param, + 1); + } + + /* calculate how to split the det buffer space between luma and chroma */ + handle_det_buf_split(mode_lib, rq_param, pipe_src_param); + print__rq_params_st(mode_lib, *rq_param); +} + +/* Note: currently taken in as is. + * Nice to decouple code from hw register implement and extract code that are repeated for luma and chroma. + */ +void dml1_rq_dlg_get_dlg_params( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_regs_st *disp_dlg_regs, + struct _vcs_dpi_display_ttu_regs_st *disp_ttu_regs, + const struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param, + const struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param, + const struct _vcs_dpi_display_e2e_pipe_params_st e2e_pipe_param, + const bool cstate_en, + const bool pstate_en, + const bool vm_en, + const bool iflip_en) +{ + /* Timing */ + unsigned int htotal = e2e_pipe_param.pipe.dest.htotal; + unsigned int hblank_end = e2e_pipe_param.pipe.dest.hblank_end; + unsigned int vblank_start = e2e_pipe_param.pipe.dest.vblank_start; + unsigned int vblank_end = e2e_pipe_param.pipe.dest.vblank_end; + bool interlaced = e2e_pipe_param.pipe.dest.interlaced; + unsigned int min_vblank = mode_lib->ip.min_vblank_lines; + + double pclk_freq_in_mhz = e2e_pipe_param.pipe.dest.pixel_rate_mhz; + double refclk_freq_in_mhz = e2e_pipe_param.clks_cfg.refclk_mhz; + double dppclk_freq_in_mhz = e2e_pipe_param.clks_cfg.dppclk_mhz; + double dispclk_freq_in_mhz = e2e_pipe_param.clks_cfg.dispclk_mhz; + + double ref_freq_to_pix_freq; + double prefetch_xy_calc_in_dcfclk; + double min_dcfclk_mhz; + double t_calc_us; + double min_ttu_vblank; + double min_dst_y_ttu_vblank; + unsigned int dlg_vblank_start; + bool dcc_en; + bool dual_plane; + bool mode_422; + unsigned int access_dir; + unsigned int bytes_per_element_l; + unsigned int bytes_per_element_c; + unsigned int vp_height_l; + unsigned int vp_width_l; + unsigned int vp_height_c; + unsigned int vp_width_c; + unsigned int htaps_l; + unsigned int htaps_c; + double hratios_l; + double hratios_c; + double vratio_l; + double vratio_c; + double line_time_in_us; + double vinit_l; + double vinit_c; + double vinit_bot_l; + double vinit_bot_c; + unsigned int swath_height_l; + unsigned int swath_width_ub_l; + unsigned int dpte_bytes_per_row_ub_l; + unsigned int dpte_groups_per_row_ub_l; + unsigned int meta_pte_bytes_per_frame_ub_l; + unsigned int meta_bytes_per_row_ub_l; + unsigned int swath_height_c; + unsigned int swath_width_ub_c; + unsigned int dpte_bytes_per_row_ub_c; + unsigned int dpte_groups_per_row_ub_c; + unsigned int meta_chunks_per_row_ub_l; + unsigned int vupdate_offset; + unsigned int vupdate_width; + unsigned int vready_offset; + unsigned int dppclk_delay_subtotal; + unsigned int dispclk_delay_subtotal; + unsigned int pixel_rate_delay_subtotal; + unsigned int vstartup_start; + unsigned int dst_x_after_scaler; + unsigned int dst_y_after_scaler; + double line_wait; + double line_o; + double line_setup; + double line_calc; + double dst_y_prefetch; + double t_pre_us; + unsigned int vm_bytes; + unsigned int meta_row_bytes; + unsigned int max_num_sw_l; + unsigned int max_num_sw_c; + unsigned int max_partial_sw_l; + unsigned int max_partial_sw_c; + double max_vinit_l; + double max_vinit_c; + unsigned int lsw_l; + unsigned int lsw_c; + unsigned int sw_bytes_ub_l; + unsigned int sw_bytes_ub_c; + unsigned int sw_bytes; + unsigned int dpte_row_bytes; + double prefetch_bw; + double flip_bw; + double t_vm_us; + double t_r0_us; + double dst_y_per_vm_vblank; + double dst_y_per_row_vblank; + double min_dst_y_per_vm_vblank; + double min_dst_y_per_row_vblank; + double lsw; + double vratio_pre_l; + double vratio_pre_c; + unsigned int req_per_swath_ub_l; + unsigned int req_per_swath_ub_c; + unsigned int meta_row_height_l; + unsigned int swath_width_pixels_ub_l; + unsigned int swath_width_pixels_ub_c; + unsigned int scaler_rec_in_width_l; + unsigned int scaler_rec_in_width_c; + unsigned int dpte_row_height_l; + unsigned int dpte_row_height_c; + double hscale_pixel_rate_l; + double hscale_pixel_rate_c; + double min_hratio_fact_l; + double min_hratio_fact_c; + double refcyc_per_line_delivery_pre_l; + double refcyc_per_line_delivery_pre_c; + double refcyc_per_line_delivery_l; + double refcyc_per_line_delivery_c; + double refcyc_per_req_delivery_pre_l; + double refcyc_per_req_delivery_pre_c; + double refcyc_per_req_delivery_l; + double refcyc_per_req_delivery_c; + double refcyc_per_req_delivery_pre_cur0; + double refcyc_per_req_delivery_cur0; + unsigned int full_recout_width; + double hratios_cur0; + unsigned int cur0_src_width; + enum cursor_bpp cur0_bpp; + unsigned int cur0_req_size; + unsigned int cur0_req_width; + double cur0_width_ub; + double cur0_req_per_width; + double hactive_cur0; + + memset(disp_dlg_regs, 0, sizeof(*disp_dlg_regs)); + memset(disp_ttu_regs, 0, sizeof(*disp_ttu_regs)); + + DTRACE("DLG: %s: cstate_en = %d", __func__, cstate_en); + DTRACE("DLG: %s: pstate_en = %d", __func__, pstate_en); + DTRACE("DLG: %s: vm_en = %d", __func__, vm_en); + DTRACE("DLG: %s: iflip_en = %d", __func__, iflip_en); + + /* ------------------------- */ + /* Section 1.5.2.1: OTG dependent Params */ + /* ------------------------- */ + DTRACE("DLG: %s: dppclk_freq_in_mhz = %3.2f", __func__, dppclk_freq_in_mhz); + DTRACE("DLG: %s: dispclk_freq_in_mhz = %3.2f", __func__, dispclk_freq_in_mhz); + DTRACE("DLG: %s: refclk_freq_in_mhz = %3.2f", __func__, refclk_freq_in_mhz); + DTRACE("DLG: %s: pclk_freq_in_mhz = %3.2f", __func__, pclk_freq_in_mhz); + DTRACE("DLG: %s: interlaced = %d", __func__, interlaced); + + ref_freq_to_pix_freq = refclk_freq_in_mhz / pclk_freq_in_mhz; + ASSERT(ref_freq_to_pix_freq < 4.0); + disp_dlg_regs->ref_freq_to_pix_freq = + (unsigned int) (ref_freq_to_pix_freq * dml_pow(2, 19)); + disp_dlg_regs->refcyc_per_htotal = (unsigned int) (ref_freq_to_pix_freq * (double) htotal + * dml_pow(2, 8)); + disp_dlg_regs->refcyc_h_blank_end = (unsigned int) ((double) hblank_end + * (double) ref_freq_to_pix_freq); + ASSERT(disp_dlg_regs->refcyc_h_blank_end < (unsigned int) dml_pow(2, 13)); + disp_dlg_regs->dlg_vblank_end = interlaced ? (vblank_end / 2) : vblank_end; /* 15 bits */ + + prefetch_xy_calc_in_dcfclk = 24.0; /* FIXME: ip_param */ + min_dcfclk_mhz = dlg_sys_param.deepsleep_dcfclk_mhz; + t_calc_us = prefetch_xy_calc_in_dcfclk / min_dcfclk_mhz; + min_ttu_vblank = dlg_sys_param.t_urg_wm_us; + if (cstate_en) + min_ttu_vblank = dml_max(dlg_sys_param.t_sr_wm_us, min_ttu_vblank); + if (pstate_en) + min_ttu_vblank = dml_max(dlg_sys_param.t_mclk_wm_us, min_ttu_vblank); + min_ttu_vblank = min_ttu_vblank + t_calc_us; + + min_dst_y_ttu_vblank = min_ttu_vblank * pclk_freq_in_mhz / (double) htotal; + dlg_vblank_start = interlaced ? (vblank_start / 2) : vblank_start; + + disp_dlg_regs->min_dst_y_next_start = (unsigned int) (((double) dlg_vblank_start + + min_dst_y_ttu_vblank) * dml_pow(2, 2)); + ASSERT(disp_dlg_regs->min_dst_y_next_start < (unsigned int) dml_pow(2, 18)); + + DTRACE("DLG: %s: min_dcfclk_mhz = %3.2f", __func__, min_dcfclk_mhz); + DTRACE("DLG: %s: min_ttu_vblank = %3.2f", __func__, min_ttu_vblank); + DTRACE( + "DLG: %s: min_dst_y_ttu_vblank = %3.2f", + __func__, + min_dst_y_ttu_vblank); + DTRACE("DLG: %s: t_calc_us = %3.2f", __func__, t_calc_us); + DTRACE( + "DLG: %s: disp_dlg_regs->min_dst_y_next_start = 0x%0x", + __func__, + disp_dlg_regs->min_dst_y_next_start); + DTRACE( + "DLG: %s: ref_freq_to_pix_freq = %3.2f", + __func__, + ref_freq_to_pix_freq); + + /* ------------------------- */ + /* Section 1.5.2.2: Prefetch, Active and TTU */ + /* ------------------------- */ + /* Prefetch Calc */ + /* Source */ + dcc_en = e2e_pipe_param.pipe.src.dcc; + dual_plane = is_dual_plane( + (enum source_format_class) e2e_pipe_param.pipe.src.source_format); + mode_422 = 0; /* FIXME */ + access_dir = (e2e_pipe_param.pipe.src.source_scan == dm_vert); /* vp access direction: horizontal or vertical accessed */ + bytes_per_element_l = get_bytes_per_element( + (enum source_format_class) e2e_pipe_param.pipe.src.source_format, + 0); + bytes_per_element_c = get_bytes_per_element( + (enum source_format_class) e2e_pipe_param.pipe.src.source_format, + 1); + vp_height_l = e2e_pipe_param.pipe.src.viewport_height; + vp_width_l = e2e_pipe_param.pipe.src.viewport_width; + vp_height_c = e2e_pipe_param.pipe.src.viewport_height_c; + vp_width_c = e2e_pipe_param.pipe.src.viewport_width_c; + + /* Scaling */ + htaps_l = e2e_pipe_param.pipe.scale_taps.htaps; + htaps_c = e2e_pipe_param.pipe.scale_taps.htaps_c; + hratios_l = e2e_pipe_param.pipe.scale_ratio_depth.hscl_ratio; + hratios_c = e2e_pipe_param.pipe.scale_ratio_depth.hscl_ratio_c; + vratio_l = e2e_pipe_param.pipe.scale_ratio_depth.vscl_ratio; + vratio_c = e2e_pipe_param.pipe.scale_ratio_depth.vscl_ratio_c; + + line_time_in_us = (htotal / pclk_freq_in_mhz); + vinit_l = e2e_pipe_param.pipe.scale_ratio_depth.vinit; + vinit_c = e2e_pipe_param.pipe.scale_ratio_depth.vinit_c; + vinit_bot_l = e2e_pipe_param.pipe.scale_ratio_depth.vinit_bot; + vinit_bot_c = e2e_pipe_param.pipe.scale_ratio_depth.vinit_bot_c; + + swath_height_l = rq_dlg_param.rq_l.swath_height; + swath_width_ub_l = rq_dlg_param.rq_l.swath_width_ub; + dpte_bytes_per_row_ub_l = rq_dlg_param.rq_l.dpte_bytes_per_row_ub; + dpte_groups_per_row_ub_l = rq_dlg_param.rq_l.dpte_groups_per_row_ub; + meta_pte_bytes_per_frame_ub_l = rq_dlg_param.rq_l.meta_pte_bytes_per_frame_ub; + meta_bytes_per_row_ub_l = rq_dlg_param.rq_l.meta_bytes_per_row_ub; + + swath_height_c = rq_dlg_param.rq_c.swath_height; + swath_width_ub_c = rq_dlg_param.rq_c.swath_width_ub; + dpte_bytes_per_row_ub_c = rq_dlg_param.rq_c.dpte_bytes_per_row_ub; + dpte_groups_per_row_ub_c = rq_dlg_param.rq_c.dpte_groups_per_row_ub; + + meta_chunks_per_row_ub_l = rq_dlg_param.rq_l.meta_chunks_per_row_ub; + vupdate_offset = e2e_pipe_param.pipe.dest.vupdate_offset; + vupdate_width = e2e_pipe_param.pipe.dest.vupdate_width; + vready_offset = e2e_pipe_param.pipe.dest.vready_offset; + + dppclk_delay_subtotal = mode_lib->ip.dppclk_delay_subtotal; + dispclk_delay_subtotal = mode_lib->ip.dispclk_delay_subtotal; + pixel_rate_delay_subtotal = dppclk_delay_subtotal * pclk_freq_in_mhz / dppclk_freq_in_mhz + + dispclk_delay_subtotal * pclk_freq_in_mhz / dispclk_freq_in_mhz; + + vstartup_start = e2e_pipe_param.pipe.dest.vstartup_start; + + if (interlaced) + vstartup_start = vstartup_start / 2; + + if (vstartup_start >= min_vblank) { + DTRACE( + "WARNING_DLG: %s: vblank_start=%d vblank_end=%d", + __func__, + vblank_start, + vblank_end); + DTRACE( + "WARNING_DLG: %s: vstartup_start=%d should be less than min_vblank=%d", + __func__, + vstartup_start, + min_vblank); + min_vblank = vstartup_start + 1; + DTRACE( + "WARNING_DLG: %s: vstartup_start=%d should be less than min_vblank=%d", + __func__, + vstartup_start, + min_vblank); + } + + dst_x_after_scaler = 0; + dst_y_after_scaler = 0; + + if (e2e_pipe_param.pipe.src.is_hsplit) + dst_x_after_scaler = pixel_rate_delay_subtotal + + e2e_pipe_param.pipe.dest.recout_width; + else + dst_x_after_scaler = pixel_rate_delay_subtotal; + + if (e2e_pipe_param.dout.output_format == dm_420) + dst_y_after_scaler = 1; + else + dst_y_after_scaler = 0; + + if (dst_x_after_scaler >= htotal) { + dst_x_after_scaler = dst_x_after_scaler - htotal; + dst_y_after_scaler = dst_y_after_scaler + 1; + } + + DTRACE("DLG: %s: htotal = %d", __func__, htotal); + DTRACE( + "DLG: %s: pixel_rate_delay_subtotal = %d", + __func__, + pixel_rate_delay_subtotal); + DTRACE("DLG: %s: dst_x_after_scaler = %d", __func__, dst_x_after_scaler); + DTRACE("DLG: %s: dst_y_after_scaler = %d", __func__, dst_y_after_scaler); + + line_wait = mode_lib->soc.urgent_latency_us; + if (cstate_en) + line_wait = dml_max(mode_lib->soc.sr_enter_plus_exit_time_us, line_wait); + if (pstate_en) + line_wait = dml_max( + mode_lib->soc.dram_clock_change_latency_us + + mode_lib->soc.urgent_latency_us, + line_wait); + line_wait = line_wait / line_time_in_us; + + line_o = (double) dst_y_after_scaler + dst_x_after_scaler / (double) htotal; + line_setup = (double) (vupdate_offset + vupdate_width + vready_offset) / (double) htotal; + line_calc = t_calc_us / line_time_in_us; + + DTRACE( + "DLG: %s: soc.sr_enter_plus_exit_time_us = %3.2f", + __func__, + (double) mode_lib->soc.sr_enter_plus_exit_time_us); + DTRACE( + "DLG: %s: soc.dram_clock_change_latency_us = %3.2f", + __func__, + (double) mode_lib->soc.dram_clock_change_latency_us); + DTRACE( + "DLG: %s: soc.urgent_latency_us = %3.2f", + __func__, + mode_lib->soc.urgent_latency_us); + + DTRACE("DLG: %s: swath_height_l = %d", __func__, swath_height_l); + if (dual_plane) + DTRACE("DLG: %s: swath_height_c = %d", __func__, swath_height_c); + + DTRACE( + "DLG: %s: t_srx_delay_us = %3.2f", + __func__, + (double) dlg_sys_param.t_srx_delay_us); + DTRACE("DLG: %s: line_time_in_us = %3.2f", __func__, (double) line_time_in_us); + DTRACE("DLG: %s: vupdate_offset = %d", __func__, vupdate_offset); + DTRACE("DLG: %s: vupdate_width = %d", __func__, vupdate_width); + DTRACE("DLG: %s: vready_offset = %d", __func__, vready_offset); + DTRACE("DLG: %s: line_time_in_us = %3.2f", __func__, line_time_in_us); + DTRACE("DLG: %s: line_wait = %3.2f", __func__, line_wait); + DTRACE("DLG: %s: line_o = %3.2f", __func__, line_o); + DTRACE("DLG: %s: line_setup = %3.2f", __func__, line_setup); + DTRACE("DLG: %s: line_calc = %3.2f", __func__, line_calc); + + dst_y_prefetch = ((double) min_vblank - 1.0) + - (line_setup + line_calc + line_wait + line_o); + DTRACE("DLG: %s: dst_y_prefetch (before rnd) = %3.2f", __func__, dst_y_prefetch); + ASSERT(dst_y_prefetch >= 2.0); + + dst_y_prefetch = dml_floor(4.0 * (dst_y_prefetch + 0.125), 1) / 4; + DTRACE("DLG: %s: dst_y_prefetch (after rnd) = %3.2f", __func__, dst_y_prefetch); + + t_pre_us = dst_y_prefetch * line_time_in_us; + vm_bytes = 0; + meta_row_bytes = 0; + + if (dcc_en && vm_en) + vm_bytes = meta_pte_bytes_per_frame_ub_l; + if (dcc_en) + meta_row_bytes = meta_bytes_per_row_ub_l; + + max_num_sw_l = 0; + max_num_sw_c = 0; + max_partial_sw_l = 0; + max_partial_sw_c = 0; + + max_vinit_l = interlaced ? dml_max(vinit_l, vinit_bot_l) : vinit_l; + max_vinit_c = interlaced ? dml_max(vinit_c, vinit_bot_c) : vinit_c; + + get_swath_need(mode_lib, &max_num_sw_l, &max_partial_sw_l, swath_height_l, max_vinit_l); + if (dual_plane) + get_swath_need( + mode_lib, + &max_num_sw_c, + &max_partial_sw_c, + swath_height_c, + max_vinit_c); + + lsw_l = max_num_sw_l * swath_height_l + max_partial_sw_l; + lsw_c = max_num_sw_c * swath_height_c + max_partial_sw_c; + sw_bytes_ub_l = lsw_l * swath_width_ub_l * bytes_per_element_l; + sw_bytes_ub_c = lsw_c * swath_width_ub_c * bytes_per_element_c; + sw_bytes = 0; + dpte_row_bytes = 0; + + if (vm_en) { + if (dual_plane) + dpte_row_bytes = dpte_bytes_per_row_ub_l + dpte_bytes_per_row_ub_c; + else + dpte_row_bytes = dpte_bytes_per_row_ub_l; + } else { + dpte_row_bytes = 0; + } + + if (dual_plane) + sw_bytes = sw_bytes_ub_l + sw_bytes_ub_c; + else + sw_bytes = sw_bytes_ub_l; + + DTRACE("DLG: %s: sw_bytes_ub_l = %d", __func__, sw_bytes_ub_l); + DTRACE("DLG: %s: sw_bytes_ub_c = %d", __func__, sw_bytes_ub_c); + DTRACE("DLG: %s: sw_bytes = %d", __func__, sw_bytes); + DTRACE("DLG: %s: vm_bytes = %d", __func__, vm_bytes); + DTRACE("DLG: %s: meta_row_bytes = %d", __func__, meta_row_bytes); + DTRACE("DLG: %s: dpte_row_bytes = %d", __func__, dpte_row_bytes); + + prefetch_bw = (vm_bytes + 2 * dpte_row_bytes + 2 * meta_row_bytes + sw_bytes) / t_pre_us; + flip_bw = ((vm_bytes + dpte_row_bytes + meta_row_bytes) * dlg_sys_param.total_flip_bw) + / (double) dlg_sys_param.total_flip_bytes; + t_vm_us = line_time_in_us / 4.0; + if (vm_en && dcc_en) { + t_vm_us = dml_max( + dlg_sys_param.t_extra_us, + dml_max((double) vm_bytes / prefetch_bw, t_vm_us)); + + if (iflip_en && !dual_plane) { + t_vm_us = dml_max(mode_lib->soc.urgent_latency_us, t_vm_us); + if (flip_bw > 0.) + t_vm_us = dml_max(vm_bytes / flip_bw, t_vm_us); + } + } + + t_r0_us = dml_max(dlg_sys_param.t_extra_us - t_vm_us, line_time_in_us - t_vm_us); + + if (vm_en || dcc_en) { + t_r0_us = dml_max( + (double) (dpte_row_bytes + meta_row_bytes) / prefetch_bw, + dlg_sys_param.t_extra_us); + t_r0_us = dml_max((double) (line_time_in_us - t_vm_us), t_r0_us); + + if (iflip_en && !dual_plane) { + t_r0_us = dml_max(mode_lib->soc.urgent_latency_us * 2.0, t_r0_us); + if (flip_bw > 0.) + t_r0_us = dml_max( + (dpte_row_bytes + meta_row_bytes) / flip_bw, + t_r0_us); + } + } + + disp_dlg_regs->dst_y_after_scaler = dst_y_after_scaler; /* in terms of line */ + disp_dlg_regs->refcyc_x_after_scaler = dst_x_after_scaler * ref_freq_to_pix_freq; /* in terms of refclk */ + ASSERT(disp_dlg_regs->refcyc_x_after_scaler < (unsigned int) dml_pow(2, 13)); + DTRACE( + "DLG: %s: disp_dlg_regs->dst_y_after_scaler = 0x%0x", + __func__, + disp_dlg_regs->dst_y_after_scaler); + DTRACE( + "DLG: %s: disp_dlg_regs->refcyc_x_after_scaler = 0x%0x", + __func__, + disp_dlg_regs->refcyc_x_after_scaler); + + disp_dlg_regs->dst_y_prefetch = (unsigned int) (dst_y_prefetch * dml_pow(2, 2)); + DTRACE( + "DLG: %s: disp_dlg_regs->dst_y_prefetch = %d", + __func__, + disp_dlg_regs->dst_y_prefetch); + + dst_y_per_vm_vblank = 0.0; + dst_y_per_row_vblank = 0.0; + + dst_y_per_vm_vblank = t_vm_us / line_time_in_us; + dst_y_per_vm_vblank = dml_floor(4.0 * (dst_y_per_vm_vblank + 0.125), 1) / 4.0; + disp_dlg_regs->dst_y_per_vm_vblank = (unsigned int) (dst_y_per_vm_vblank * dml_pow(2, 2)); + + dst_y_per_row_vblank = t_r0_us / line_time_in_us; + dst_y_per_row_vblank = dml_floor(4.0 * (dst_y_per_row_vblank + 0.125), 1) / 4.0; + disp_dlg_regs->dst_y_per_row_vblank = (unsigned int) (dst_y_per_row_vblank * dml_pow(2, 2)); + + DTRACE("DLG: %s: lsw_l = %d", __func__, lsw_l); + DTRACE("DLG: %s: lsw_c = %d", __func__, lsw_c); + DTRACE("DLG: %s: dpte_bytes_per_row_ub_l = %d", __func__, dpte_bytes_per_row_ub_l); + DTRACE("DLG: %s: dpte_bytes_per_row_ub_c = %d", __func__, dpte_bytes_per_row_ub_c); + + DTRACE("DLG: %s: prefetch_bw = %3.2f", __func__, prefetch_bw); + DTRACE("DLG: %s: flip_bw = %3.2f", __func__, flip_bw); + DTRACE("DLG: %s: t_pre_us = %3.2f", __func__, t_pre_us); + DTRACE("DLG: %s: t_vm_us = %3.2f", __func__, t_vm_us); + DTRACE("DLG: %s: t_r0_us = %3.2f", __func__, t_r0_us); + DTRACE("DLG: %s: dst_y_per_vm_vblank = %3.2f", __func__, dst_y_per_vm_vblank); + DTRACE("DLG: %s: dst_y_per_row_vblank = %3.2f", __func__, dst_y_per_row_vblank); + DTRACE("DLG: %s: dst_y_prefetch = %3.2f", __func__, dst_y_prefetch); + + min_dst_y_per_vm_vblank = 8.0; + min_dst_y_per_row_vblank = 16.0; + if (htotal <= 75) { + min_vblank = 300; + min_dst_y_per_vm_vblank = 100.0; + min_dst_y_per_row_vblank = 100.0; + } + + ASSERT(dst_y_per_vm_vblank < min_dst_y_per_vm_vblank); + ASSERT(dst_y_per_row_vblank < min_dst_y_per_row_vblank); + + ASSERT(dst_y_prefetch > (dst_y_per_vm_vblank + dst_y_per_row_vblank)); + lsw = dst_y_prefetch - (dst_y_per_vm_vblank + dst_y_per_row_vblank); + + DTRACE("DLG: %s: lsw = %3.2f", __func__, lsw); + + vratio_pre_l = get_vratio_pre( + mode_lib, + max_num_sw_l, + max_partial_sw_l, + swath_height_l, + max_vinit_l, + lsw); + vratio_pre_c = 1.0; + if (dual_plane) + vratio_pre_c = get_vratio_pre( + mode_lib, + max_num_sw_c, + max_partial_sw_c, + swath_height_c, + max_vinit_c, + lsw); + + DTRACE("DLG: %s: vratio_pre_l=%3.2f", __func__, vratio_pre_l); + DTRACE("DLG: %s: vratio_pre_c=%3.2f", __func__, vratio_pre_c); + + ASSERT(vratio_pre_l <= 4.0); + if (vratio_pre_l >= 4.0) + disp_dlg_regs->vratio_prefetch = (unsigned int) dml_pow(2, 21) - 1; + else + disp_dlg_regs->vratio_prefetch = (unsigned int) (vratio_pre_l * dml_pow(2, 19)); + + ASSERT(vratio_pre_c <= 4.0); + if (vratio_pre_c >= 4.0) + disp_dlg_regs->vratio_prefetch_c = (unsigned int) dml_pow(2, 21) - 1; + else + disp_dlg_regs->vratio_prefetch_c = (unsigned int) (vratio_pre_c * dml_pow(2, 19)); + + disp_dlg_regs->refcyc_per_pte_group_vblank_l = + (unsigned int) (dst_y_per_row_vblank * (double) htotal + * ref_freq_to_pix_freq / (double) dpte_groups_per_row_ub_l); + ASSERT(disp_dlg_regs->refcyc_per_pte_group_vblank_l < (unsigned int) dml_pow(2, 13)); + + disp_dlg_regs->refcyc_per_pte_group_vblank_c = + (unsigned int) (dst_y_per_row_vblank * (double) htotal + * ref_freq_to_pix_freq / (double) dpte_groups_per_row_ub_c); + ASSERT(disp_dlg_regs->refcyc_per_pte_group_vblank_c < (unsigned int) dml_pow(2, 13)); + + disp_dlg_regs->refcyc_per_meta_chunk_vblank_l = + (unsigned int) (dst_y_per_row_vblank * (double) htotal + * ref_freq_to_pix_freq / (double) meta_chunks_per_row_ub_l); + ASSERT(disp_dlg_regs->refcyc_per_meta_chunk_vblank_l < (unsigned int) dml_pow(2, 13)); + + disp_dlg_regs->refcyc_per_meta_chunk_vblank_c = + disp_dlg_regs->refcyc_per_meta_chunk_vblank_l;/* dcc for 4:2:0 is not supported in dcn1.0. assigned to be the same as _l for now */ + + /* Active */ + req_per_swath_ub_l = rq_dlg_param.rq_l.req_per_swath_ub; + req_per_swath_ub_c = rq_dlg_param.rq_c.req_per_swath_ub; + meta_row_height_l = rq_dlg_param.rq_l.meta_row_height; + swath_width_pixels_ub_l = 0; + swath_width_pixels_ub_c = 0; + scaler_rec_in_width_l = 0; + scaler_rec_in_width_c = 0; + dpte_row_height_l = rq_dlg_param.rq_l.dpte_row_height; + dpte_row_height_c = rq_dlg_param.rq_c.dpte_row_height; + + disp_dlg_regs->dst_y_per_pte_row_nom_l = (unsigned int) ((double) dpte_row_height_l + / (double) vratio_l * dml_pow(2, 2)); + ASSERT(disp_dlg_regs->dst_y_per_pte_row_nom_l < (unsigned int) dml_pow(2, 17)); + + disp_dlg_regs->dst_y_per_pte_row_nom_c = (unsigned int) ((double) dpte_row_height_c + / (double) vratio_c * dml_pow(2, 2)); + ASSERT(disp_dlg_regs->dst_y_per_pte_row_nom_c < (unsigned int) dml_pow(2, 17)); + + disp_dlg_regs->dst_y_per_meta_row_nom_l = (unsigned int) ((double) meta_row_height_l + / (double) vratio_l * dml_pow(2, 2)); + ASSERT(disp_dlg_regs->dst_y_per_meta_row_nom_l < (unsigned int) dml_pow(2, 17)); + + disp_dlg_regs->dst_y_per_meta_row_nom_c = disp_dlg_regs->dst_y_per_meta_row_nom_l; /* dcc for 4:2:0 is not supported in dcn1.0. assigned to be the same as _l for now */ + + disp_dlg_regs->refcyc_per_pte_group_nom_l = (unsigned int) ((double) dpte_row_height_l + / (double) vratio_l * (double) htotal * ref_freq_to_pix_freq + / (double) dpte_groups_per_row_ub_l); + if (disp_dlg_regs->refcyc_per_pte_group_nom_l >= (unsigned int) dml_pow(2, 23)) + disp_dlg_regs->refcyc_per_pte_group_nom_l = dml_pow(2, 23) - 1; + + disp_dlg_regs->refcyc_per_pte_group_nom_c = (unsigned int) ((double) dpte_row_height_c + / (double) vratio_c * (double) htotal * ref_freq_to_pix_freq + / (double) dpte_groups_per_row_ub_c); + if (disp_dlg_regs->refcyc_per_pte_group_nom_c >= (unsigned int) dml_pow(2, 23)) + disp_dlg_regs->refcyc_per_pte_group_nom_c = dml_pow(2, 23) - 1; + + disp_dlg_regs->refcyc_per_meta_chunk_nom_l = (unsigned int) ((double) meta_row_height_l + / (double) vratio_l * (double) htotal * ref_freq_to_pix_freq + / (double) meta_chunks_per_row_ub_l); + if (disp_dlg_regs->refcyc_per_meta_chunk_nom_l >= (unsigned int) dml_pow(2, 23)) + disp_dlg_regs->refcyc_per_meta_chunk_nom_l = dml_pow(2, 23) - 1; + + if (mode_422) { + swath_width_pixels_ub_l = swath_width_ub_l * 2; /* *2 for 2 pixel per element */ + swath_width_pixels_ub_c = swath_width_ub_c * 2; + } else { + swath_width_pixels_ub_l = swath_width_ub_l * 1; + swath_width_pixels_ub_c = swath_width_ub_c * 1; + } + + hscale_pixel_rate_l = 0.; + hscale_pixel_rate_c = 0.; + min_hratio_fact_l = 1.0; + min_hratio_fact_c = 1.0; + + if (htaps_l <= 1) + min_hratio_fact_l = 2.0; + else if (htaps_l <= 6) { + if ((hratios_l * 2.0) > 4.0) + min_hratio_fact_l = 4.0; + else + min_hratio_fact_l = hratios_l * 2.0; + } else { + if (hratios_l > 4.0) + min_hratio_fact_l = 4.0; + else + min_hratio_fact_l = hratios_l; + } + + hscale_pixel_rate_l = min_hratio_fact_l * dppclk_freq_in_mhz; + + if (htaps_c <= 1) + min_hratio_fact_c = 2.0; + else if (htaps_c <= 6) { + if ((hratios_c * 2.0) > 4.0) + min_hratio_fact_c = 4.0; + else + min_hratio_fact_c = hratios_c * 2.0; + } else { + if (hratios_c > 4.0) + min_hratio_fact_c = 4.0; + else + min_hratio_fact_c = hratios_c; + } + + hscale_pixel_rate_c = min_hratio_fact_c * dppclk_freq_in_mhz; + + refcyc_per_line_delivery_pre_l = 0.; + refcyc_per_line_delivery_pre_c = 0.; + refcyc_per_line_delivery_l = 0.; + refcyc_per_line_delivery_c = 0.; + + refcyc_per_req_delivery_pre_l = 0.; + refcyc_per_req_delivery_pre_c = 0.; + refcyc_per_req_delivery_l = 0.; + refcyc_per_req_delivery_c = 0.; + refcyc_per_req_delivery_pre_cur0 = 0.; + refcyc_per_req_delivery_cur0 = 0.; + + full_recout_width = 0; + if (e2e_pipe_param.pipe.src.is_hsplit) { + if (e2e_pipe_param.pipe.dest.full_recout_width == 0) { + DTRACE("DLG: %s: Warningfull_recout_width not set in hsplit mode", __func__); + full_recout_width = e2e_pipe_param.pipe.dest.recout_width * 2; /* assume half split for dcn1 */ + } else + full_recout_width = e2e_pipe_param.pipe.dest.full_recout_width; + } else + full_recout_width = e2e_pipe_param.pipe.dest.recout_width; + + refcyc_per_line_delivery_pre_l = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_pre_l, + hscale_pixel_rate_l, + swath_width_pixels_ub_l, + 1); /* per line */ + + refcyc_per_line_delivery_l = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_l, + hscale_pixel_rate_l, + swath_width_pixels_ub_l, + 1); /* per line */ + + DTRACE("DLG: %s: full_recout_width = %d", __func__, full_recout_width); + DTRACE("DLG: %s: hscale_pixel_rate_l = %3.2f", __func__, hscale_pixel_rate_l); + DTRACE( + "DLG: %s: refcyc_per_line_delivery_pre_l = %3.2f", + __func__, + refcyc_per_line_delivery_pre_l); + DTRACE( + "DLG: %s: refcyc_per_line_delivery_l = %3.2f", + __func__, + refcyc_per_line_delivery_l); + + disp_dlg_regs->refcyc_per_line_delivery_pre_l = (unsigned int) dml_floor( + refcyc_per_line_delivery_pre_l, + 1); + disp_dlg_regs->refcyc_per_line_delivery_l = (unsigned int) dml_floor( + refcyc_per_line_delivery_l, + 1); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_pre_l < (unsigned int) dml_pow(2, 13)); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_l < (unsigned int) dml_pow(2, 13)); + + if (dual_plane) { + refcyc_per_line_delivery_pre_c = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_pre_c, + hscale_pixel_rate_c, + swath_width_pixels_ub_c, + 1); /* per line */ + + refcyc_per_line_delivery_c = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_c, + hscale_pixel_rate_c, + swath_width_pixels_ub_c, + 1); /* per line */ + + DTRACE( + "DLG: %s: refcyc_per_line_delivery_pre_c = %3.2f", + __func__, + refcyc_per_line_delivery_pre_c); + DTRACE( + "DLG: %s: refcyc_per_line_delivery_c = %3.2f", + __func__, + refcyc_per_line_delivery_c); + + disp_dlg_regs->refcyc_per_line_delivery_pre_c = (unsigned int) dml_floor( + refcyc_per_line_delivery_pre_c, + 1); + disp_dlg_regs->refcyc_per_line_delivery_c = (unsigned int) dml_floor( + refcyc_per_line_delivery_c, + 1); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_pre_c < (unsigned int) dml_pow(2, 13)); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_c < (unsigned int) dml_pow(2, 13)); + } + disp_dlg_regs->chunk_hdl_adjust_cur0 = 3; + + /* TTU - Luma / Chroma */ + if (access_dir) { /* vertical access */ + scaler_rec_in_width_l = vp_height_l; + scaler_rec_in_width_c = vp_height_c; + } else { + scaler_rec_in_width_l = vp_width_l; + scaler_rec_in_width_c = vp_width_c; + } + + refcyc_per_req_delivery_pre_l = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_pre_l, + hscale_pixel_rate_l, + scaler_rec_in_width_l, + req_per_swath_ub_l); /* per req */ + refcyc_per_req_delivery_l = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_l, + hscale_pixel_rate_l, + scaler_rec_in_width_l, + req_per_swath_ub_l); /* per req */ + + DTRACE( + "DLG: %s: refcyc_per_req_delivery_pre_l = %3.2f", + __func__, + refcyc_per_req_delivery_pre_l); + DTRACE( + "DLG: %s: refcyc_per_req_delivery_l = %3.2f", + __func__, + refcyc_per_req_delivery_l); + + disp_ttu_regs->refcyc_per_req_delivery_pre_l = (unsigned int) (refcyc_per_req_delivery_pre_l + * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_l = (unsigned int) (refcyc_per_req_delivery_l + * dml_pow(2, 10)); + + ASSERT(refcyc_per_req_delivery_pre_l < dml_pow(2, 13)); + ASSERT(refcyc_per_req_delivery_l < dml_pow(2, 13)); + + if (dual_plane) { + refcyc_per_req_delivery_pre_c = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_pre_c, + hscale_pixel_rate_c, + scaler_rec_in_width_c, + req_per_swath_ub_c); /* per req */ + refcyc_per_req_delivery_c = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_c, + hscale_pixel_rate_c, + scaler_rec_in_width_c, + req_per_swath_ub_c); /* per req */ + + DTRACE( + "DLG: %s: refcyc_per_req_delivery_pre_c = %3.2f", + __func__, + refcyc_per_req_delivery_pre_c); + DTRACE( + "DLG: %s: refcyc_per_req_delivery_c = %3.2f", + __func__, + refcyc_per_req_delivery_c); + + disp_ttu_regs->refcyc_per_req_delivery_pre_c = + (unsigned int) (refcyc_per_req_delivery_pre_c * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_c = (unsigned int) (refcyc_per_req_delivery_c + * dml_pow(2, 10)); + + ASSERT(refcyc_per_req_delivery_pre_c < dml_pow(2, 13)); + ASSERT(refcyc_per_req_delivery_c < dml_pow(2, 13)); + } + + /* TTU - Cursor */ + hratios_cur0 = e2e_pipe_param.pipe.scale_ratio_depth.hscl_ratio; + cur0_src_width = e2e_pipe_param.pipe.src.cur0_src_width; /* cursor source width */ + cur0_bpp = (enum cursor_bpp) e2e_pipe_param.pipe.src.cur0_bpp; + cur0_req_size = 0; + cur0_req_width = 0; + cur0_width_ub = 0.0; + cur0_req_per_width = 0.0; + hactive_cur0 = 0.0; + + ASSERT(cur0_src_width <= 256); + + if (cur0_src_width > 0) { + unsigned int cur0_bit_per_pixel = 0; + + if (cur0_bpp == dm_cur_2bit) { + cur0_req_size = 64; /* byte */ + cur0_bit_per_pixel = 2; + } else { /* 32bit */ + cur0_bit_per_pixel = 32; + if (cur0_src_width >= 1 && cur0_src_width <= 16) + cur0_req_size = 64; + else if (cur0_src_width >= 17 && cur0_src_width <= 31) + cur0_req_size = 128; + else + cur0_req_size = 256; + } + + cur0_req_width = (double) cur0_req_size / ((double) cur0_bit_per_pixel / 8.0); + cur0_width_ub = dml_ceil((double) cur0_src_width / (double) cur0_req_width, 1) + * (double) cur0_req_width; + cur0_req_per_width = cur0_width_ub / (double) cur0_req_width; + hactive_cur0 = (double) cur0_src_width / hratios_cur0; /* FIXME: oswin to think about what to do for cursor */ + + if (vratio_pre_l <= 1.0) { + refcyc_per_req_delivery_pre_cur0 = hactive_cur0 * ref_freq_to_pix_freq + / (double) cur0_req_per_width; + } else { + refcyc_per_req_delivery_pre_cur0 = (double) refclk_freq_in_mhz + * (double) cur0_src_width / hscale_pixel_rate_l + / (double) cur0_req_per_width; + } + + disp_ttu_regs->refcyc_per_req_delivery_pre_cur0 = + (unsigned int) (refcyc_per_req_delivery_pre_cur0 * dml_pow(2, 10)); + ASSERT(refcyc_per_req_delivery_pre_cur0 < dml_pow(2, 13)); + + if (vratio_l <= 1.0) { + refcyc_per_req_delivery_cur0 = hactive_cur0 * ref_freq_to_pix_freq + / (double) cur0_req_per_width; + } else { + refcyc_per_req_delivery_cur0 = (double) refclk_freq_in_mhz + * (double) cur0_src_width / hscale_pixel_rate_l + / (double) cur0_req_per_width; + } + + DTRACE("DLG: %s: cur0_req_width = %d", __func__, cur0_req_width); + DTRACE( + "DLG: %s: cur0_width_ub = %3.2f", + __func__, + cur0_width_ub); + DTRACE( + "DLG: %s: cur0_req_per_width = %3.2f", + __func__, + cur0_req_per_width); + DTRACE( + "DLG: %s: hactive_cur0 = %3.2f", + __func__, + hactive_cur0); + DTRACE( + "DLG: %s: refcyc_per_req_delivery_pre_cur0 = %3.2f", + __func__, + refcyc_per_req_delivery_pre_cur0); + DTRACE( + "DLG: %s: refcyc_per_req_delivery_cur0 = %3.2f", + __func__, + refcyc_per_req_delivery_cur0); + + disp_ttu_regs->refcyc_per_req_delivery_cur0 = + (unsigned int) (refcyc_per_req_delivery_cur0 * dml_pow(2, 10)); + ASSERT(refcyc_per_req_delivery_cur0 < dml_pow(2, 13)); + } else { + disp_ttu_regs->refcyc_per_req_delivery_pre_cur0 = 0; + disp_ttu_regs->refcyc_per_req_delivery_cur0 = 0; + } + + /* TTU - Misc */ + disp_ttu_regs->qos_level_low_wm = 0; + ASSERT(disp_ttu_regs->qos_level_low_wm < dml_pow(2, 14)); + disp_ttu_regs->qos_level_high_wm = (unsigned int) (4.0 * (double) htotal + * ref_freq_to_pix_freq); + ASSERT(disp_ttu_regs->qos_level_high_wm < dml_pow(2, 14)); + + disp_ttu_regs->qos_level_flip = 14; + disp_ttu_regs->qos_level_fixed_l = 8; + disp_ttu_regs->qos_level_fixed_c = 8; + disp_ttu_regs->qos_level_fixed_cur0 = 8; + disp_ttu_regs->qos_ramp_disable_l = 0; + disp_ttu_regs->qos_ramp_disable_c = 0; + disp_ttu_regs->qos_ramp_disable_cur0 = 0; + + disp_ttu_regs->min_ttu_vblank = min_ttu_vblank * refclk_freq_in_mhz; + ASSERT(disp_ttu_regs->min_ttu_vblank < dml_pow(2, 24)); + + print__ttu_regs_st(mode_lib, *disp_ttu_regs); + print__dlg_regs_st(mode_lib, *disp_dlg_regs); +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.h b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.h new file mode 100644 index 000000000000..987d7671cd0f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.h @@ -0,0 +1,67 @@ +/* + * 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 + * + */ + +#ifndef __DISPLAY_RQ_DLG_CALC_H__ +#define __DISPLAY_RQ_DLG_CALC_H__ + +#include "dml_common_defs.h" +#include "display_rq_dlg_helpers.h" + +struct display_mode_lib; + +void dml1_extract_rq_regs( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_regs_st *rq_regs, + const struct _vcs_dpi_display_rq_params_st rq_param); +/* Function: dml_rq_dlg_get_rq_params + * Calculate requestor related parameters that register definition agnostic + * (i.e. this layer does try to separate real values from register definition) + * Input: + * pipe_src_param - pipe source configuration (e.g. vp, pitch, etc.) + * Output: + * rq_param - values that can be used to setup RQ (e.g. swath_height, plane1_addr, etc.) + */ +void dml1_rq_dlg_get_rq_params( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_params_st *rq_param, + const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param); + + +/* Function: dml_rq_dlg_get_dlg_params + * Calculate deadline related parameters + */ +void dml1_rq_dlg_get_dlg_params( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_regs_st *dlg_regs, + struct _vcs_dpi_display_ttu_regs_st *ttu_regs, + const struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param, + const struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param, + const struct _vcs_dpi_display_e2e_pipe_params_st e2e_pipe_param, + const bool cstate_en, + const bool pstate_en, + const bool vm_en, + const bool iflip_en); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c index df2d5099b90e..b953b02a1512 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c @@ -27,11 +27,12 @@ #include "../calcs/dcn_calc_math.h" #include "dml_inline_defs.h" + double dml_round(double a) { double round_pt = 0.5; - double ceil = dml_ceil(a); - double floor = dml_floor(a); + double ceil = dml_ceil(a, 1); + double floor = dml_floor(a, 1); if (a - floor >= round_pt) return ceil; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h index 81c53d879a16..b2847bc469fe 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h @@ -22,6 +22,7 @@ * Authors: AMD * */ + #ifndef __DC_COMMON_DEFS_H__ #define __DC_COMMON_DEFS_H__ @@ -30,7 +31,8 @@ #include "display_mode_structs.h" #include "display_mode_enums.h" -#define DTRACE(str, ...) dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); +#define dml_print(str, ...) {dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); } +#define DTRACE(str, ...) {dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); } double dml_round(double a); 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 a91b4a6c6154..e68086b8a22f 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 @@ -1,5 +1,31 @@ +/* + * 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 + * + */ + #ifndef __DML_INLINE_DEFS_H__ #define __DML_INLINE_DEFS_H__ + #include "dml_common_defs.h" #include "../calcs/dcn_calc_math.h" @@ -13,14 +39,29 @@ static inline double dml_max(double a, double b) return (double) dcn_bw_max2(a, b); } -static inline double dml_ceil(double a) +static inline double dml_max3(double a, double b, double c) +{ + return dml_max(dml_max(a, b), c); +} + +static inline double dml_max4(double a, double b, double c, double d) +{ + return dml_max(dml_max(a, b), dml_max(c, d)); +} + +static inline double dml_max5(double a, double b, double c, double d, double e) +{ + return dml_max(dml_max4(a, b, c, d), e); +} + +static inline double dml_ceil(double a, double granularity) { - return (double) dcn_bw_ceil2(a, 1); + return (double) dcn_bw_ceil2(a, granularity); } -static inline double dml_floor(double a) +static inline double dml_floor(double a, double granularity) { - return (double) dcn_bw_floor2(a, 1); + return (double) dcn_bw_floor2(a, granularity); } static inline int dml_log2(double x) diff --git a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c index 0745366d80bc..bc7d8c707221 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c +++ b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c @@ -24,51 +24,46 @@ */ #include "soc_bounding_box.h" #include "display_mode_lib.h" +#include "dc_features.h" #include "dml_inline_defs.h" -void dml_socbb_set_latencies( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_soc_bounding_box_st *from_box) +void dml_socbb_set_latencies(soc_bounding_box_st *to_box, soc_bounding_box_st *from_box) { - struct _vcs_dpi_soc_bounding_box_st *to_box = &mode_lib->soc; - to_box->dram_clock_change_latency_us = from_box->dram_clock_change_latency_us; to_box->sr_exit_time_us = from_box->sr_exit_time_us; to_box->sr_enter_plus_exit_time_us = from_box->sr_enter_plus_exit_time_us; to_box->urgent_latency_us = from_box->urgent_latency_us; to_box->writeback_latency_us = from_box->writeback_latency_us; - DTRACE("box.dram_clock_change_latency_us: %f", from_box->dram_clock_change_latency_us); - DTRACE("box.sr_exit_time_us: %f", from_box->sr_exit_time_us); - DTRACE("box.sr_enter_plus_exit_time_us: %f", from_box->sr_enter_plus_exit_time_us); - DTRACE("box.urgent_latency_us: %f", from_box->urgent_latency_us); - DTRACE("box.writeback_latency_us: %f", from_box->writeback_latency_us); - } -struct _vcs_dpi_voltage_scaling_st dml_socbb_voltage_scaling( - struct _vcs_dpi_soc_bounding_box_st *box, +voltage_scaling_st dml_socbb_voltage_scaling( + const soc_bounding_box_st *soc, enum voltage_state voltage) { - switch (voltage) { - case dm_vmin: - return box->vmin; - case dm_vnom: - return box->vnom; - case dm_vmax: - default: - return box->vmax; + const voltage_scaling_st *voltage_state; + const voltage_scaling_st * const voltage_end = soc->clock_limits + DC__VOLTAGE_STATES; + + for (voltage_state = soc->clock_limits; + voltage_state < voltage_end && voltage_state->state != voltage; + voltage_state++) { } + + if (voltage_state < voltage_end) + return *voltage_state; + return soc->clock_limits[DC__VOLTAGE_STATES - 1]; } -double dml_socbb_return_bw_mhz(struct _vcs_dpi_soc_bounding_box_st *box, enum voltage_state voltage) +double dml_socbb_return_bw_mhz(soc_bounding_box_st *box, enum voltage_state voltage) { double return_bw; - struct _vcs_dpi_voltage_scaling_st state = dml_socbb_voltage_scaling(box, voltage); + voltage_scaling_st state = dml_socbb_voltage_scaling(box, voltage); - return_bw = dml_min( - ((double) box->return_bus_width_bytes) * state.dcfclk_mhz, + return_bw = dml_min((double) box->return_bus_width_bytes * state.dcfclk_mhz, state.dram_bw_per_chan_gbps * 1000.0 * (double) box->num_chans * box->ideal_dram_bw_after_urgent_percent / 100.0); + + return_bw = dml_min((double) box->return_bus_width_bytes * state.fabricclk_mhz, return_bw); + return return_bw; } diff --git a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.h b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.h index 7bbae33f163e..7a65206a6d21 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.h +++ b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.h @@ -22,15 +22,14 @@ * Authors: AMD * */ + #ifndef __SOC_BOUNDING_BOX_H__ #define __SOC_BOUNDING_BOX_H__ #include "dml_common_defs.h" -struct display_mode_lib; - -void dml_socbb_set_latencies(struct display_mode_lib *mode_lib, struct _vcs_dpi_soc_bounding_box_st *from_box); -struct _vcs_dpi_voltage_scaling_st dml_socbb_voltage_scaling(struct _vcs_dpi_soc_bounding_box_st *box, enum voltage_state voltage); -double dml_socbb_return_bw_mhz(struct _vcs_dpi_soc_bounding_box_st *box, enum voltage_state voltage); +void dml_socbb_set_latencies(soc_bounding_box_st *to_box, soc_bounding_box_st *from_box); +voltage_scaling_st dml_socbb_voltage_scaling(const soc_bounding_box_st *box, enum voltage_state voltage); +double dml_socbb_return_bw_mhz(soc_bounding_box_st *box, enum voltage_state voltage); #endif diff --git a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c index d4e5ef64e489..80038e0e610f 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c @@ -130,9 +130,8 @@ failure_2: slot = service->busyness[index_of_id]; - if (slot) - kfree(slot); - }; + kfree(slot); + } failure_1: kfree(service); @@ -171,8 +170,7 @@ void dal_gpio_service_destroy( do { uint32_t *slot = (*ptr)->busyness[index_of_id]; - if (slot) - kfree(slot); + kfree(slot); ++index_of_id; } while (index_of_id < GPIO_ID_COUNT); diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_status.h b/drivers/gpu/drm/amd/display/dc/inc/core_status.h index b5759c0e5a2f..01df85641684 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_status.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_status.h @@ -35,13 +35,14 @@ enum dc_status { DC_FAIL_CONTROLLER_VALIDATE = 5, DC_FAIL_ENC_VALIDATE = 6, DC_FAIL_ATTACH_SURFACES = 7, - DC_FAIL_SURFACE_VALIDATE = 8, - DC_NO_DP_LINK_BANDWIDTH = 9, - DC_EXCEED_DONGLE_MAX_CLK = 10, - DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED = 11, - DC_FAIL_BANDWIDTH_VALIDATE = 12, /* BW and Watermark validation */ - DC_FAIL_SCALING = 13, - DC_FAIL_DP_LINK_TRAINING = 14, + DC_FAIL_DETACH_SURFACES = 8, + DC_FAIL_SURFACE_VALIDATE = 9, + DC_NO_DP_LINK_BANDWIDTH = 10, + DC_EXCEED_DONGLE_MAX_CLK = 11, + DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED = 12, + DC_FAIL_BANDWIDTH_VALIDATE = 13, /* BW and Watermark validation */ + DC_FAIL_SCALING = 14, + DC_FAIL_DP_LINK_TRAINING = 15, DC_ERROR_UNEXPECTED = -1 }; 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 ff23f268fe02..b69f321e2ab6 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -32,6 +32,7 @@ #include "ddc_service_types.h" #include "dc_bios_types.h" #include "mem_input.h" +#include "hubp.h" #if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "mpc.h" #endif @@ -58,6 +59,11 @@ struct link_init_data { TODO: remove it when DC is complete. */ }; +enum { + FREE_ACQUIRED_RESOURCE = 0, + KEEP_ACQUIRED_RESOURCE = 1, +}; + struct dc_link *link_create(const struct link_init_data *init_params); void link_destroy(struct dc_link **link); @@ -72,12 +78,13 @@ void core_link_enable_stream( struct dc_state *state, struct pipe_ctx *pipe_ctx); -void core_link_disable_stream(struct pipe_ctx *pipe_ctx); +void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option); void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable); /********** DAL Core*********************/ #include "display_clock.h" #include "transform.h" +#include "dpp.h" struct resource_pool; struct dc_state; @@ -106,7 +113,7 @@ struct resource_funcs { const struct resource_pool *pool, struct dc_stream_state *stream); - enum dc_status (*validate_plane)(const struct dc_plane_state *plane_state); + enum dc_status (*validate_plane)(const struct dc_plane_state *plane_state, struct dc_caps *caps); enum dc_status (*add_stream_to_ctx)( struct dc *dc, @@ -124,8 +131,10 @@ struct audio_support{ struct resource_pool { struct mem_input *mis[MAX_PIPES]; + struct hubp *hubps[MAX_PIPES]; struct input_pixel_processor *ipps[MAX_PIPES]; struct transform *transforms[MAX_PIPES]; + struct dpp *dpps[MAX_PIPES]; struct output_pixel_processor *opps[MAX_PIPES]; struct timing_generator *timing_generators[MAX_PIPES]; struct stream_encoder *stream_enc[MAX_PIPES * 2]; @@ -173,10 +182,11 @@ struct stream_resource { struct plane_resource { struct scaler_data scl_data; - + struct hubp *hubp; struct mem_input *mi; struct input_pixel_processor *ipp; struct transform *xfm; + struct dpp *dpp; }; struct pipe_ctx { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h new file mode 100644 index 000000000000..83a68460edcd --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h @@ -0,0 +1,134 @@ +/* + * Copyright 2012-15 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 __DAL_DPP_H__ +#define __DAL_DPP_H__ + +#include "transform.h" + +struct dpp { + const struct dpp_funcs *funcs; + struct dc_context *ctx; + int inst; + struct dpp_caps *caps; + struct pwl_params regamma_params; +}; + +struct dpp_grph_csc_adjustment { + struct fixed31_32 temperature_matrix[CSC_TEMPERATURE_MATRIX_SIZE]; + enum graphics_gamut_adjust_type gamut_adjust_type; +}; + +struct dpp_funcs { + void (*dpp_reset)(struct dpp *dpp); + + void (*dpp_set_scaler)(struct dpp *dpp, + const struct scaler_data *scl_data); + + void (*dpp_set_pixel_storage_depth)( + struct dpp *dpp, + enum lb_pixel_depth depth, + const struct bit_depth_reduction_params *bit_depth_params); + + bool (*dpp_get_optimal_number_of_taps)( + struct dpp *dpp, + struct scaler_data *scl_data, + const struct scaling_taps *in_taps); + + void (*dpp_set_gamut_remap)( + struct dpp *dpp, + const struct dpp_grph_csc_adjustment *adjust); + + void (*opp_set_csc_default)( + struct dpp *dpp, + const struct default_adjustment *default_adjust); + + void (*opp_set_csc_adjustment)( + struct dpp *dpp, + const struct out_csc_color_matrix *tbl_entry); + + void (*opp_power_on_regamma_lut)( + struct dpp *dpp, + bool power_on); + + void (*opp_program_regamma_lut)( + struct dpp *dpp, + const struct pwl_result_data *rgb, + uint32_t num); + + void (*opp_configure_regamma_lut)( + struct dpp *dpp, + bool is_ram_a); + + void (*opp_program_regamma_lutb_settings)( + struct dpp *dpp, + const struct pwl_params *params); + + void (*opp_program_regamma_luta_settings)( + struct dpp *dpp, + const struct pwl_params *params); + + void (*opp_program_regamma_pwl)( + struct dpp *dpp, const struct pwl_params *params); + + void (*opp_set_regamma_mode)( + struct dpp *dpp_base, + enum opp_regamma mode); + + void (*ipp_set_degamma)( + struct dpp *dpp_base, + enum ipp_degamma_mode mode); + + void (*ipp_program_input_lut)( + struct dpp *dpp_base, + const struct dc_gamma *gamma); + + void (*ipp_program_degamma_pwl)(struct dpp *dpp_base, + const struct pwl_params *params); + + void (*ipp_setup)( + struct dpp *dpp_base, + enum surface_pixel_format input_format, + enum expansion_mode mode); + + void (*ipp_full_bypass)(struct dpp *dpp_base); + + void (*set_cursor_attributes)( + struct dpp *dpp_base, + const struct dc_cursor_attributes *attr); + + void (*set_cursor_position)( + struct dpp *dpp_base, + const struct dc_cursor_position *pos, + const struct dc_cursor_mi_param *param, + uint32_t width + ); + +}; + + + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h new file mode 100644 index 000000000000..0d186be24cf4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h @@ -0,0 +1,105 @@ +/* + * Copyright 2012-15 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 __DAL_HUBP_H__ +#define __DAL_HUBP_H__ + +#include "mem_input.h" + +struct hubp { + struct hubp_funcs *funcs; + struct dc_context *ctx; + struct dc_plane_address request_address; + struct dc_plane_address current_address; + int inst; + int opp_id; + int mpcc_id; + struct dc_cursor_attributes curs_attr; +}; + + +struct hubp_funcs { + void (*hubp_setup)( + struct hubp *hubp, + struct _vcs_dpi_display_dlg_regs_st *dlg_regs, + struct _vcs_dpi_display_ttu_regs_st *ttu_regs, + struct _vcs_dpi_display_rq_regs_st *rq_regs, + struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest); + + void (*dcc_control)(struct hubp *hubp, bool enable, + bool independent_64b_blks); + void (*mem_program_viewport)( + struct hubp *hubp, + const struct rect *viewport, + const struct rect *viewport_c); + + bool (*hubp_program_surface_flip_and_addr)( + struct hubp *hubp, + const struct dc_plane_address *address, + bool flip_immediate); + + void (*hubp_program_pte_vm)( + struct hubp *hubp, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + enum dc_rotation_angle rotation); + + void (*hubp_set_vm_system_aperture_settings)( + struct hubp *hubp, + struct vm_system_aperture_param *apt); + + void (*hubp_set_vm_context0_settings)( + struct hubp *hubp, + const struct vm_context0_param *vm0); + + void (*hubp_program_surface_config)( + struct hubp *hubp, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + union plane_size *plane_size, + enum dc_rotation_angle rotation, + struct dc_plane_dcc_param *dcc, + bool horizontal_mirror); + + bool (*hubp_is_flip_pending)(struct hubp *hubp); + + void (*hubp_update_dchub)(struct hubp *hubp, + struct dchub_init_data *dh_data); + + void (*set_blank)(struct hubp *hubp, bool blank); + void (*set_hubp_blank_en)(struct hubp *hubp, bool blank); + + void (*set_cursor_attributes)( + struct hubp *hubp, + const struct dc_cursor_attributes *attr); + + void (*set_cursor_position)( + struct hubp *hubp, + const struct dc_cursor_position *pos, + const struct dc_cursor_mi_param *param); + +}; + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index 961bbcc9202c..3d33bcda7059 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -111,7 +111,7 @@ struct link_encoder_funcs { const struct dc_link_settings *link_settings, enum clock_source_id clock_source); void (*disable_output)(struct link_encoder *link_enc, - enum signal_type signal); + enum signal_type signal, struct dc_link *link); void (*dp_set_lane_settings)(struct link_encoder *enc, const struct link_training_settings *link_settings); void (*dp_set_phy_pattern)(struct link_encoder *enc, @@ -123,10 +123,6 @@ struct link_encoder_funcs { bool exit_link_training_required); void (*psr_program_secondary_packet)(struct link_encoder *enc, unsigned int sdp_transmit_line_num_deadline); - void (*backlight_control) (struct link_encoder *enc, - bool enable); - void (*power_control) (struct link_encoder *enc, - bool power_up); void (*connect_dig_be_to_fe)(struct link_encoder *enc, enum engine_id engine, bool connect); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index 6cef9ad0af91..3e1e7e6a8792 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -69,8 +69,6 @@ struct mem_input { struct dc_plane_address request_address; struct dc_plane_address current_address; int inst; - int opp_id; - int mpcc_id; struct stutter_modes stutter_mode; }; @@ -163,6 +161,15 @@ struct mem_input_funcs { void (*set_blank)(struct mem_input *mi, bool blank); void (*set_hubp_blank_en)(struct mem_input *mi, bool blank); + void (*set_cursor_attributes)( + struct mem_input *mem_input, + const struct dc_cursor_attributes *attr); + + void (*set_cursor_position)( + struct mem_input *mem_input, + const struct dc_cursor_position *pos, + const struct dc_cursor_mi_param *param); + }; #endif 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 4bbcff48acc8..d4188b2c0626 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h @@ -29,8 +29,9 @@ #include "opp.h" struct mpcc_cfg { - struct mem_input *mi; - struct output_pixel_processor *opp; + int dpp_id; + int opp_id; + struct mpc_tree_cfg *tree_cfg; unsigned int z_index; struct tg_color black_color; @@ -44,11 +45,17 @@ struct mpc { }; struct mpc_funcs { - void (*add)(struct mpc *mpc, struct mpcc_cfg *cfg); + int (*add)(struct mpc *mpc, struct mpcc_cfg *cfg); + void (*remove)(struct mpc *mpc, - struct output_pixel_processor *opp, + struct mpc_tree_cfg *tree_cfg, + int opp_id, int mpcc_inst); + void (*wait_for_idle)(struct mpc *mpc, int id); + + void (*update_blend_mode)(struct mpc *mpc, struct mpcc_cfg *cfg); + }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h index 785d39706832..7c08bc62c1f5 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h @@ -38,6 +38,7 @@ struct transform { const struct transform_funcs *funcs; struct dc_context *ctx; int inst; + struct dpp_caps *caps; struct pwl_params regamma_params; }; @@ -109,6 +110,22 @@ enum graphics_gamut_adjust_type { GRAPHICS_GAMUT_ADJUST_TYPE_SW /* use adjustments */ }; +enum lb_memory_config { + /* Enable all 3 pieces of memory */ + LB_MEMORY_CONFIG_0 = 0, + + /* Enable only the first piece of memory */ + LB_MEMORY_CONFIG_1 = 1, + + /* Enable only the second piece of memory */ + LB_MEMORY_CONFIG_2 = 2, + + /* Only applicable in 4:2:0 mode, enable all 3 pieces of memory and the + * last piece of chroma memory used for the luma storage + */ + LB_MEMORY_CONFIG_3 = 3 +}; + struct xfm_grph_csc_adjustment { struct fixed31_32 temperature_matrix[CSC_TEMPERATURE_MATRIX_SIZE]; enum graphics_gamut_adjust_type gamut_adjust_type; @@ -238,6 +255,17 @@ struct transform_funcs { void (*ipp_full_bypass)(struct transform *xfm_base); + void (*set_cursor_attributes)( + struct transform *xfm_base, + const struct dc_cursor_attributes *attr); + + void (*set_cursor_position)( + struct transform *xfm_base, + const struct dc_cursor_position *pos, + const struct dc_cursor_mi_param *param, + uint32_t width + ); + }; const uint16_t *get_filter_2tap_16p(void); @@ -251,4 +279,33 @@ const uint16_t *get_filter_6tap_64p(struct fixed31_32 ratio); const uint16_t *get_filter_7tap_64p(struct fixed31_32 ratio); const uint16_t *get_filter_8tap_64p(struct fixed31_32 ratio); + +/* Defines the pixel processing capability of the DSCL */ +enum dscl_data_processing_format { + DSCL_DATA_PRCESSING_FIXED_FORMAT, /* The DSCL processes pixel data in fixed format */ + DSCL_DATA_PRCESSING_FLOAT_FORMAT, /* The DSCL processes pixel data in float format */ +}; + +/* + * The DPP capabilities structure contains enumerations to specify the + * HW processing features and an associated function pointers to + * provide the function interface that can be overloaded for implementations + * based on different capabilities + */ +struct dpp_caps { + /* DSCL processing pixel data in fixed or float format */ + enum dscl_data_processing_format dscl_data_proc_format; + + /* Calculates the number of partitions in the line buffer. + * The implementation of this function is overloaded for + * different versions of DSCL LB. + */ + void (*dscl_calc_lb_num_partitions)( + const struct scaler_data *scl_data, + enum lb_memory_config lb_config, + int *num_part_y, + int *num_part_c); +}; + + #endif 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 aae7629b1c08..8734689a9245 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -28,6 +28,7 @@ #include "dc_types.h" #include "clock_source.h" #include "inc/hw/timing_generator.h" +#include "inc/hw/link_encoder.h" #include "core_status.h" enum pipe_gating_control { @@ -133,7 +134,8 @@ struct hw_sequencer_funcs { void (*enable_stream)(struct pipe_ctx *pipe_ctx); - void (*disable_stream)(struct pipe_ctx *pipe_ctx); + void (*disable_stream)(struct pipe_ctx *pipe_ctx, + int option); void (*unblank_stream)(struct pipe_ctx *pipe_ctx, struct dc_link_settings *link_settings); @@ -174,8 +176,14 @@ struct hw_sequencer_funcs { struct resource_pool *res_pool, struct pipe_ctx *pipe_ctx); - void (*ready_shared_resources)(struct dc *dc); + void (*ready_shared_resources)(struct dc *dc, struct dc_state *context); void (*optimize_shared_resources)(struct dc *dc); + void (*edp_power_control)( + struct link_encoder *enc, + bool enable); + void (*edp_backlight_control)( + struct dc_link *link, + bool enable); }; void color_space_to_black_color( 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 f7994cfc850d..f2b8c9a376d5 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h @@ -40,6 +40,10 @@ enum dc_status core_link_write_dpcd( const uint8_t *data, uint32_t size); +struct gpio *get_hpd_gpio(struct dc_bios *dcb, + struct graphics_object_id link_id, + struct gpio_service *gpio_service); + void dp_enable_link_phy( struct dc_link *link, enum signal_type signal, diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 614bb691ab59..5467332faf7b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -164,4 +164,9 @@ bool pipe_need_reprogram( void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream, struct bit_depth_reduction_params *fmt_bit_depth); +void update_audio_usage( + struct resource_context *res_ctx, + const struct resource_pool *pool, + struct audio *audio, + bool acquired); #endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/os_types.h b/drivers/gpu/drm/amd/display/dc/os_types.h index e0cd5278aae8..86170b40b5c5 100644 --- a/drivers/gpu/drm/amd/display/dc/os_types.h +++ b/drivers/gpu/drm/amd/display/dc/os_types.h @@ -56,5 +56,45 @@ #endif +/* + * + * general debug capabilities + * + */ +#if defined(CONFIG_DEBUG_KERNEL) || defined(CONFIG_DEBUG_DRIVER) + +#if defined(CONFIG_HAVE_KGDB) || defined(CONFIG_KGDB) +#define ASSERT_CRITICAL(expr) do { \ + if (WARN_ON(!(expr))) { \ + kgdb_breakpoint(); \ + } \ +} while (0) +#else +#define ASSERT_CRITICAL(expr) do { \ + if (WARN_ON(!(expr))) { \ + ; \ + } \ +} while (0) +#endif + +#if defined(CONFIG_DEBUG_KERNEL_DC) +#define ASSERT(expr) ASSERT_CRITICAL(expr) + +#else +#define ASSERT(expr) WARN_ON(!(expr)) +#endif + +#define BREAK_TO_DEBUGGER() ASSERT(0) + +#endif /* CONFIG_DEBUG_KERNEL || CONFIG_DEBUG_DRIVER */ + +#define DC_ERR(...) do { \ + dm_error(__VA_ARGS__); \ + BREAK_TO_DEBUGGER(); \ +} while (0) + +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#include <asm/fpu/api.h> +#endif #endif /* _OS_TYPES_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c index db513abd735a..88c2bde3f039 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c @@ -58,7 +58,8 @@ static void virtual_link_encoder_enable_dp_mst_output( static void virtual_link_encoder_disable_output( struct link_encoder *link_enc, - enum signal_type signal) {} + enum signal_type signal, + struct dc_link *link) {} static void virtual_link_encoder_dp_set_lane_settings( struct link_encoder *enc, @@ -72,14 +73,6 @@ static void virtual_link_encoder_update_mst_stream_allocation_table( struct link_encoder *enc, const struct link_mst_stream_allocation_table *table) {} -static void virtual_link_encoder_edp_backlight_control( - struct link_encoder *enc, - bool enable) {} - -static void virtual_link_encoder_edp_power_control( - struct link_encoder *enc, - bool power_up) {} - static void virtual_link_encoder_connect_dig_be_to_fe( struct link_encoder *enc, enum engine_id engine, @@ -105,8 +98,6 @@ static const struct link_encoder_funcs virtual_lnk_enc_funcs = { .dp_set_phy_pattern = virtual_link_encoder_dp_set_phy_pattern, .update_mst_stream_allocation_table = virtual_link_encoder_update_mst_stream_allocation_table, - .backlight_control = virtual_link_encoder_edp_backlight_control, - .power_control = virtual_link_encoder_edp_power_control, .connect_dig_be_to_fe = virtual_link_encoder_connect_dig_be_to_fe, .destroy = virtual_link_encoder_destroy }; diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h index 5aaf2dacfe38..8e1fe70097be 100644 --- a/drivers/gpu/drm/amd/display/include/logger_interface.h +++ b/drivers/gpu/drm/amd/display/include/logger_interface.h @@ -44,6 +44,8 @@ struct dal_logger *dal_logger_create(struct dc_context *ctx, uint32_t log_mask); uint32_t dal_logger_destroy(struct dal_logger **logger); +void dm_logger_flush_buffer(struct dal_logger *logger, bool should_warn); + void dm_logger_write( struct dal_logger *logger, enum dc_log_type log_type, @@ -157,4 +159,30 @@ void context_clock_trace( #define DTN_INFO_END() \ dm_dtn_log_end(dc_ctx) +#define PERFORMANCE_TRACE_START() \ + unsigned long long perf_trc_start_stmp = dm_get_timestamp(dc->ctx); \ + unsigned long long perf_trc_start_log_msk = dc->ctx->logger->mask; \ + unsigned int perf_trc_start_log_flags = dc->ctx->logger->flags.value; \ + if (dc->debug.performance_trace) {\ + dm_logger_flush_buffer(dc->ctx->logger, false);\ + dc->ctx->logger->mask = 1<<LOG_PERF_TRACE;\ + dc->ctx->logger->flags.bits.ENABLE_CONSOLE = 0;\ + dc->ctx->logger->flags.bits.ENABLE_BUFFER = 1;\ + } + +#define PERFORMANCE_TRACE_END() do {\ + unsigned long long perf_trc_end_stmp = dm_get_timestamp(dc->ctx);\ + if (dc->debug.performance_trace) {\ + dm_logger_write(dc->ctx->logger, \ + LOG_PERF_TRACE, \ + "%s duration: %d ticks\n", __func__,\ + perf_trc_end_stmp - perf_trc_start_stmp); \ + if (perf_trc_start_log_msk != 1<<LOG_PERF_TRACE) {\ + dc->ctx->logger->mask = perf_trc_start_log_msk;\ + dc->ctx->logger->flags.value = perf_trc_start_log_flags;\ + dm_logger_flush_buffer(dc->ctx->logger, false);\ + } \ + } \ +} while (0) + #endif /* __DAL_LOGGER_INTERFACE_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/logger_types.h b/drivers/gpu/drm/amd/display/include/logger_types.h index 1f22e84cedb9..e2ff8cd423d6 100644 --- a/drivers/gpu/drm/amd/display/include/logger_types.h +++ b/drivers/gpu/drm/amd/display/include/logger_types.h @@ -64,8 +64,7 @@ enum dc_log_type { LOG_EVENT_LINK_LOSS, LOG_EVENT_UNDERFLOW, LOG_IF_TRACE, - LOG_HW_MARKS, - LOG_PPLIB, + LOG_PERF_TRACE, LOG_SECTION_TOTAL_COUNT }; @@ -131,4 +130,37 @@ struct dc_log_type_info { char name[MAX_NAME_LEN]; }; +/* Structure for keeping track of offsets, buffer, etc */ + +#define DAL_LOGGER_BUFFER_MAX_SIZE 2048 + +/*Connectivity log needs to output EDID, which needs at lease 256x3 bytes, + * change log line size to 896 to meet the request. + */ +#define LOG_MAX_LINE_SIZE 896 + +struct dal_logger { + + /* How far into the circular buffer has been read by dsat + * Read offset should never cross write offset. Write \0's to + * read data just to be sure? + */ + uint32_t buffer_read_offset; + + /* How far into the circular buffer we have written + * Write offset should never cross read offset + */ + uint32_t buffer_write_offset; + + uint32_t open_count; + + char *log_buffer; /* Pointer to malloc'ed buffer */ + uint32_t log_buffer_size; /* Size of circular buffer */ + + uint32_t mask; /*array of masks for major elements*/ + + union logger_flags flags; + struct dc_context *ctx; +}; + #endif /* __DAL_LOGGER_TYPES_H__ */ |