diff options
| author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2026-07-24 16:21:27 +0200 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2026-07-24 16:21:27 +0200 |
| commit | 8f9aa2c90530ab92301a82231ae44f3722becd93 (patch) | |
| tree | fb282e955b0a880b07131a135257fe3ec764e928 /drivers/gpu/drm/amd | |
| parent | 93467b31bec6da512b51544e5e4584f2745e995e (diff) | |
| parent | 155b42bec9cbb6b8cdc47dd9bd09503a81fbe493 (diff) | |
Merge v7.1.5linux-rolling-stable
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/gpu/drm/amd')
35 files changed, 1533 insertions, 736 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index 72a5a29e63f6..abc319488969 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -1914,13 +1914,6 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu( mutex_lock(&mem->lock); - /* Unpin MMIO/DOORBELL BO's that were pinned during allocation */ - if (mem->alloc_flags & - (KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL | - KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP)) { - amdgpu_amdkfd_gpuvm_unpin_bo(mem->bo); - } - mapped_to_gpu_memory = mem->mapped_to_gpu_memory; is_imported = mem->is_imported; mutex_unlock(&mem->lock); @@ -1934,6 +1927,15 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu( return -EBUSY; } + /* At this point the BO is guaranteed to be freed, so unpin the + * MMIO/DOORBELL BOs that were pinned during allocation. + */ + if (mem->alloc_flags & + (KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL | + KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP)) { + amdgpu_amdkfd_gpuvm_unpin_bo(mem->bo); + } + /* Make sure restore workers don't access the BO any more */ mutex_lock(&process_info->lock); if (!list_empty(&mem->validate_list)) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c index d386bc775d03..f89f3a37a45b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c @@ -229,6 +229,7 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf sizing_pass = buffer == NULL; iter.data = buffer; + iter.start = 0; iter.offset = 0; iter.remain = count; @@ -553,7 +554,7 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check, coredump->rings_dw = kzalloc(total_ring_size, GFP_NOWAIT); coredump->rings = kcalloc(ring_count, sizeof(struct amdgpu_coredump_ring), GFP_NOWAIT); if (coredump->rings && coredump->rings_dw) { - for (i = 0, off = 0, idx = 0; i < adev->num_rings; i++) { + for (i = 0, off = 0, idx = 0; i < adev->num_rings && idx < ring_count; i++) { ring = adev->rings[i]; if (atomic_read(&ring->fence_drv.last_seq) == ring->fence_drv.sync_seq && diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index feab90e3efd1..4f8489626624 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3747,6 +3747,8 @@ int amdgpu_device_init(struct amdgpu_device *adev, mutex_init(&adev->gfx.workload_profile_mutex); mutex_init(&adev->vcn.workload_profile_mutex); + spin_lock_init(&adev->irq.lock); + amdgpu_device_init_apu_flags(adev); r = amdgpu_device_check_arguments(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index fe6d988e7f24..1120f8225ac0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -27,6 +27,7 @@ */ #include <linux/ktime.h> #include <linux/module.h> +#include <linux/overflow.h> #include <linux/pagemap.h> #include <linux/pci.h> #include <linux/dma-buf.h> @@ -1228,13 +1229,14 @@ int amdgpu_gem_list_handles_ioctl(struct drm_device *dev, void *data, return ret; } -static int amdgpu_gem_align_pitch(struct amdgpu_device *adev, - int width, - int cpp, - bool tiled) +static unsigned int amdgpu_gem_align_pitch(struct amdgpu_device *adev, + unsigned int width, + unsigned int cpp, + bool tiled) { - int aligned = width; - int pitch_mask = 0; + unsigned int aligned = width; + unsigned int pitch_mask = 0; + unsigned int pitch; switch (cpp) { case 1: @@ -1249,9 +1251,12 @@ static int amdgpu_gem_align_pitch(struct amdgpu_device *adev, break; } - aligned += pitch_mask; + if (check_add_overflow(aligned, pitch_mask, &aligned)) + return 0; aligned &= ~pitch_mask; - return aligned * cpp; + if (check_mul_overflow(aligned, cpp, &pitch)) + return 0; + return pitch; } int amdgpu_mode_dumb_create(struct drm_file *file_priv, @@ -1278,8 +1283,12 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv, args->pitch = amdgpu_gem_align_pitch(adev, args->width, DIV_ROUND_UP(args->bpp, 8), 0); + if (!args->pitch) + return -EINVAL; args->size = (u64)args->pitch * args->height; args->size = ALIGN(args->size, PAGE_SIZE); + if (!args->size) + return -EINVAL; domain = amdgpu_bo_get_preferred_domain(adev, amdgpu_display_supported_domains(adev, flags)); r = amdgpu_gem_object_create(adev, args->size, 0, domain, flags, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c index 254a4e983f40..40b8506ac66f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c @@ -309,8 +309,6 @@ int amdgpu_irq_init(struct amdgpu_device *adev) unsigned int irq, flags; int r; - spin_lock_init(&adev->irq.lock); - /* Enable MSI if not disabled by module parameter */ adev->irq.msi_enabled = false; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c index 823ba17e32af..cc6d1a4e4c3a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c @@ -99,6 +99,7 @@ int amdgpu_mca_mp0_ras_sw_init(struct amdgpu_device *adev) strcpy(ras->ras_block.ras_comm.name, "mca.mp0"); ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__MCA; + ras->ras_block.ras_comm.sub_block_index = AMDGPU_RAS_MCA_BLOCK__MP0; ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE; adev->mca.mp0.ras_if = &ras->ras_block.ras_comm; @@ -123,6 +124,7 @@ int amdgpu_mca_mp1_ras_sw_init(struct amdgpu_device *adev) strcpy(ras->ras_block.ras_comm.name, "mca.mp1"); ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__MCA; + ras->ras_block.ras_comm.sub_block_index = AMDGPU_RAS_MCA_BLOCK__MP1; ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE; adev->mca.mp1.ras_if = &ras->ras_block.ras_comm; @@ -147,6 +149,7 @@ int amdgpu_mca_mpio_ras_sw_init(struct amdgpu_device *adev) strcpy(ras->ras_block.ras_comm.name, "mca.mpio"); ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__MCA; + ras->ras_block.ras_comm.sub_block_index = AMDGPU_RAS_MCA_BLOCK__MPIO; ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE; adev->mca.mpio.ras_if = &ras->ras_block.ras_comm; diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v12_1.c b/drivers/gpu/drm/amd/amdgpu/mes_v12_1.c index cec801278126..be86802fef33 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v12_1.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v12_1.c @@ -2016,7 +2016,7 @@ static int mes_v12_1_map_test_bo(struct amdgpu_device *adev, error: amdgpu_sync_free(&sync); - return 0; + return r; } static int mes_v12_1_test_ring(struct amdgpu_device *adev, int xcc_id, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 8785f7810157..78068b2c9685 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -2362,6 +2362,9 @@ static int criu_restore_memory_of_gpu(struct kfd_process_device *pdd, const bool criu_resume = true; u64 offset; + if (bo_priv->idr_handle > INT_MAX) + return -EINVAL; + if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL) { if (bo_bucket->size != kfd_doorbell_process_slice(pdd->dev->kfd)) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index 31187ddbb79e..ee413117b0ff 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -3095,32 +3095,24 @@ int kfd_dqm_suspend_bad_queue_mes(struct kfd_node *knode, u32 pasid, u32 doorbel list_for_each_entry(q, &qpd->queues_list, list) { if (q->doorbell_id == doorbell_id && q->properties.is_active) { - ret = suspend_all_queues_mes(dqm); - if (ret) { - dev_err(dev, "Suspending all queues failed"); - goto out; - } + /* suspend all queues will save any good queues and mark the rest as bad */ + suspend_all_queues_mes(dqm); q->properties.is_evicted = true; q->properties.is_active = false; decrement_queue_count(dqm, qpd, q); + /* this will remove the bad queue and sched a GPU reset if needed */ ret = remove_queue_mes(dqm, q, qpd); - if (ret) { - dev_err(dev, "Removing bad queue failed"); - goto out; - } - - ret = resume_all_queues_mes(dqm); if (ret) - dev_err(dev, "Resuming all queues failed"); - + dev_err(dev, "Removing bad queue failed"); + /* resume the good queues */ + resume_all_queues_mes(dqm); break; } } } -out: dqm_unlock(dqm); kfd_unref_process(p); return ret; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_events.c index e65b323aafbf..81900b49d9d5 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_events.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.c @@ -483,6 +483,11 @@ int kfd_criu_restore_event(struct file *devkfd, } *priv_data_offset += sizeof(*ev_priv); + if (ev_priv->event_id > INT_MAX) { + ret = -EINVAL; + goto exit; + } + if (ev_priv->user_handle) { ret = kfd_kmap_event_page(p, ev_priv->user_handle); if (ret) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v12_1.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v12_1.c index c90c0d99b1e3..475589b924e9 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v12_1.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v12_1.c @@ -32,6 +32,10 @@ #include "amdgpu_amdkfd.h" #include "kfd_device_queue_manager.h" +static void update_mqd(struct mqd_manager *mm, void *mqd, + struct queue_properties *q, + struct mqd_update_info *minfo); + static inline struct v12_1_compute_mqd *get_mqd(void *mqd) { return (struct v12_1_compute_mqd *)mqd; @@ -215,7 +219,7 @@ static void init_mqd(struct mqd_manager *mm, void **mqd, *mqd = m; if (gart_addr) *gart_addr = addr; - mm->update_mqd(mm, m, q, NULL); + update_mqd(mm, m, q, NULL); } static int load_mqd(struct mqd_manager *mm, void *mqd, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index d28ca581cad0..888fbaf069be 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -910,7 +910,7 @@ static void kfd_process_free_id(struct kfd_process *process) { struct kfd_process *primary_process; - if (process->context_id != KFD_CONTEXT_ID_PRIMARY) + if (process->context_id == KFD_CONTEXT_ID_PRIMARY) return; primary_process = kfd_lookup_process_by_mm(process->lead_thread->mm); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index 3841943da5ec..0b54ad8036b6 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -4115,6 +4115,7 @@ exit: list_for_each_entry_safe(criu_svm_md, next, &svms->criu_svm_metadata_list, list) { pr_debug("freeing criu_svm_md[]\n\tstart: 0x%llx\n", criu_svm_md->data.start_addr); + list_del(&criu_svm_md->list); kfree(criu_svm_md); } 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 f8c13bad4ac2..1ecd7bef9ed8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -12553,13 +12553,11 @@ static bool amdgpu_dm_crtc_mem_type_changed(struct drm_device *dev, struct drm_plane_state *new_plane_state, *old_plane_state; drm_for_each_plane_mask(plane, dev, crtc_state->plane_mask) { - new_plane_state = drm_atomic_get_plane_state(state, plane); - old_plane_state = drm_atomic_get_plane_state(state, plane); + new_plane_state = drm_atomic_get_new_plane_state(state, plane); + old_plane_state = drm_atomic_get_old_plane_state(state, plane); - if (IS_ERR(new_plane_state) || IS_ERR(old_plane_state)) { - drm_err(dev, "Failed to get plane state for plane %s\n", plane->name); - return false; - } + if (!old_plane_state || !new_plane_state) + continue; if (old_plane_state->fb && new_plane_state->fb && get_mem_type(old_plane_state->fb) != get_mem_type(new_plane_state->fb)) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index a3cb05490dc9..ee214f7592e5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -95,8 +95,11 @@ static u32 edid_extract_panel_id(struct edid *edid) (u32)EDID_PRODUCT_ID(edid); } -static void apply_edid_quirks(struct drm_device *dev, struct edid *edid, struct dc_edid_caps *edid_caps) +static void apply_edid_quirks(struct dc_link *link, struct edid *edid, + struct dc_edid_caps *edid_caps) { + struct amdgpu_dm_connector *aconnector = link->priv; + struct drm_device *dev = aconnector->base.dev; uint32_t panel_id = edid_extract_panel_id(edid); switch (panel_id) { @@ -126,6 +129,11 @@ static void apply_edid_quirks(struct drm_device *dev, struct edid *edid, struct drm_dbg_driver(dev, "Disabling VSC on monitor with panel id %X\n", panel_id); edid_caps->panel_patch.disable_colorimetry = true; break; + /* Workaround for monitors that get corrupted by the PHY SSC reduction */ + case drm_edid_encode_panel_id('D', 'E', 'L', 0x4147): + drm_dbg_driver(dev, "Skip PHY SSC reduction on panel id %X\n", panel_id); + link->wa_flags.skip_phy_ssc_reduction = true; + break; default: return; } @@ -147,7 +155,6 @@ enum dc_edid_status dm_helpers_parse_edid_caps( { struct amdgpu_dm_connector *aconnector = link->priv; struct drm_connector *connector = &aconnector->base; - struct drm_device *dev = connector->dev; struct edid *edid_buf = edid ? (struct edid *) edid->raw_edid : NULL; struct cea_sad *sads; int sad_count = -1; @@ -181,7 +188,7 @@ enum dc_edid_status dm_helpers_parse_edid_caps( if (edid_caps->edid_hdmi) populate_hdmi_info_from_connector(&connector->display_info.hdmi, edid_caps); - apply_edid_quirks(dev, edid_buf, edid_caps); + apply_edid_quirks(link, edid_buf, edid_caps); sad_count = drm_edid_to_sad((struct edid *) edid->raw_edid, &sads); if (sad_count <= 0) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index b3530fbf32f7..5f2c62fcba9b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -2956,27 +2956,16 @@ static struct surface_update_descriptor det_surface_update( elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); } - if (u->cm || (u->gamma && dce_use_lut(u->plane_info ? u->plane_info->format : u->surface->format))) { + if (u->blend_tf || (u->gamma && dce_use_lut(u->plane_info ? u->plane_info->format : u->surface->format))) { update_flags->bits.gamma_change = 1; elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); } - if (u->cm && (u->cm->flags.bits.lut3d_enable || u->surface->cm.flags.bits.lut3d_enable)) { + if (u->lut3d_func || u->func_shaper) { update_flags->bits.lut_3d = 1; elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); } - if (u->cm && u->cm->flags.bits.lut3d_dma_enable != u->surface->cm.flags.bits.lut3d_dma_enable && - u->cm->flags.bits.lut3d_enable && u->surface->cm.flags.bits.lut3d_enable) { - /* Toggling 3DLUT loading between DMA and Host is illegal */ - BREAK_TO_DEBUGGER(); - } - - if (u->cm && u->cm->flags.bits.lut3d_enable && !u->cm->flags.bits.lut3d_dma_enable) { - /* Host loading 3DLUT requires full update but only stream lock */ - elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_STREAM); - } - if (u->hdr_mult.value) if (u->hdr_mult.value != u->surface->hdr_mult.value) { // TODO: Should be fast? @@ -2995,6 +2984,20 @@ static struct surface_update_descriptor det_surface_update( update_flags->bits.cm_hist_change = 1; elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); } + if (u->cm2_params) { + if (u->cm2_params->component_settings.shaper_3dlut_setting != u->surface->mcm_shaper_3dlut_setting + || u->cm2_params->component_settings.lut1d_enable != u->surface->mcm_lut1d_enable + || u->cm2_params->cm2_luts.lut3d_data.lut3d_src != u->surface->mcm_luts.lut3d_data.lut3d_src) { + update_flags->bits.mcm_transfer_function_enable_change = 1; + elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL); + } + } + + if (update_flags->bits.lut_3d && + u->surface->mcm_luts.lut3d_data.lut3d_src != DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM) { + elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL); + } + if (check_config->enable_legacy_fast_update && (update_flags->bits.gamma_change || update_flags->bits.gamut_remap_change || @@ -3250,12 +3253,24 @@ static void copy_surface_update_to_plane( sizeof(struct dc_transfer_func_distributed_points)); } - /* Shaper, 3DLUT, 1DLUT */ - if (srf_update->cm) { - memcpy(&surface->cm, srf_update->cm, - sizeof(surface->cm)); + if (srf_update->cm2_params) { + surface->mcm_shaper_3dlut_setting = srf_update->cm2_params->component_settings.shaper_3dlut_setting; + surface->mcm_lut1d_enable = srf_update->cm2_params->component_settings.lut1d_enable; + surface->mcm_luts = srf_update->cm2_params->cm2_luts; } + if (srf_update->func_shaper) { + memcpy(&surface->in_shaper_func, srf_update->func_shaper, + sizeof(surface->in_shaper_func)); + + if (surface->mcm_shaper_3dlut_setting >= DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER) + surface->mcm_luts.shaper = &surface->in_shaper_func; + } + + if (srf_update->lut3d_func) + memcpy(&surface->lut3d_func, srf_update->lut3d_func, + sizeof(surface->lut3d_func)); + if (srf_update->hdr_mult.value) surface->hdr_mult = srf_update->hdr_mult; @@ -3264,6 +3279,17 @@ static void copy_surface_update_to_plane( surface->sdr_white_level_nits = srf_update->sdr_white_level_nits; + if (srf_update->blend_tf) { + memcpy(&surface->blend_tf, srf_update->blend_tf, + sizeof(surface->blend_tf)); + + if (surface->mcm_lut1d_enable) + surface->mcm_luts.lut1d_func = &surface->blend_tf; + } + + if (srf_update->cm2_params || srf_update->blend_tf) + surface->lut_bank_a = !surface->lut_bank_a; + if (srf_update->input_csc_color_matrix) surface->input_csc_color_matrix = *srf_update->input_csc_color_matrix; @@ -4550,9 +4576,11 @@ static void commit_planes_for_stream(struct dc *dc, if (!should_update_pipe_for_plane(context, pipe_ctx, plane_state)) continue; - if (srf_updates[i].cm && - srf_updates[i].cm->flags.bits.lut3d_enable && - srf_updates[i].cm->flags.bits.lut3d_dma_enable && + if (srf_updates[i].cm2_params && + srf_updates[i].cm2_params->cm2_luts.lut3d_data.lut3d_src == + DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM && + srf_updates[i].cm2_params->component_settings.shaper_3dlut_setting == + DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER_3DLUT && dc->hwss.trigger_3dlut_dma_load) dc->hwss.trigger_3dlut_dma_load(dc, pipe_ctx); @@ -5209,12 +5237,6 @@ static bool full_update_required( const struct dc_stream_update *stream_update, const struct dc_stream_state *stream) { - const union dc_plane_cm_flags blend_only_flags = { - .bits = { - .blend_enable = 1, - } - }; - if (full_update_required_weak(dc, srf_updates, surface_count, stream_update, stream)) return true; @@ -5229,10 +5251,7 @@ static bool full_update_required( srf_updates[i].in_transfer_func || srf_updates[i].surface->force_full_update || (srf_updates[i].flip_addr && - srf_updates[i].flip_addr->address.tmz_surface != srf_updates[i].surface->address.tmz_surface) || - (srf_updates[i].cm && - ((srf_updates[i].cm->flags.all != blend_only_flags.all && srf_updates[i].cm->flags.all != 0) || - (srf_updates[i].surface->cm.flags.all != blend_only_flags.all && srf_updates[i].surface->cm.flags.all != 0))))) + srf_updates[i].flip_addr->address.tmz_surface != srf_updates[i].surface->address.tmz_surface))) return true; } @@ -6966,7 +6985,7 @@ bool dc_capture_register_software_state(struct dc *dc, struct dc_register_softwa struct dc_plane_state *plane_state = pipe_ctx->plane_state; /* MPCC blending tree and mode control - capture actual blend configuration */ - state->mpc.mpcc_mode[i] = (plane_state->cm.blend_func.type != TF_TYPE_BYPASS) ? 1 : 0; + state->mpc.mpcc_mode[i] = (plane_state->blend_tf.type != TF_TYPE_BYPASS) ? 1 : 0; state->mpc.mpcc_alpha_blend_mode[i] = plane_state->per_pixel_alpha ? 1 : 0; state->mpc.mpcc_alpha_multiplied_mode[i] = plane_state->pre_multiplied_alpha ? 1 : 0; state->mpc.mpcc_blnd_active_overlap_only[i] = 0; /* Default - no overlap restriction */ 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 e16de323f39c..717451828361 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -996,6 +996,7 @@ void dc_stream_release_3dlut_for_stream( if (rmcm_3dlut) { rmcm_3dlut->isInUse = false; rmcm_3dlut->stream = NULL; + rmcm_3dlut->protection_bits = 0; } } @@ -1007,6 +1008,7 @@ void dc_stream_init_rmcm_3dlut(struct dc *dc) for (int i = 0; i < num_rmcm; i++) { dc->res_pool->rmcm_3dlut[i].isInUse = false; dc->res_pool->rmcm_3dlut[i].stream = NULL; + dc->res_pool->rmcm_3dlut[i].protection_bits = 0; } } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 37714d4371fb..55152f12af48 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1407,50 +1407,15 @@ struct lut_mem_mapping { struct dc_rmcm_3dlut { bool isInUse; const struct dc_stream_state *stream; + uint8_t protection_bits; }; struct dc_3dlut { struct kref refcount; struct tetrahedral_params lut_3d; + struct fixed31_32 hdr_multiplier; union dc_3dlut_state state; }; - -/* 3DLUT DMA (Fast Load) params */ -struct dc_3dlut_dma { - struct dc_plane_address addr; - enum dc_cm_lut_swizzle swizzle; - enum dc_cm_lut_pixel_format format; - uint16_t bias; /* FP1.5.10 */ - uint16_t scale; /* FP1.5.10 */ - enum dc_cm_lut_size size; -}; - -/* color manager */ -union dc_plane_cm_flags { - unsigned int all; - struct { - unsigned int shaper_enable : 1; - unsigned int lut3d_enable : 1; - unsigned int blend_enable : 1; - /* whether legacy (lut3d_func) or DMA is valid */ - unsigned int lut3d_dma_enable : 1; - /* RMCM lut to be used instead of MCM */ - unsigned int rmcm_enable : 1; - unsigned int reserved: 27; - } bits; -}; - -struct dc_plane_cm { - struct kref refcount; - struct dc_transfer_func shaper_func; - union { - struct dc_3dlut lut3d_func; - struct dc_3dlut_dma lut3d_dma; - }; - struct dc_transfer_func blend_func; - union dc_plane_cm_flags flags; -}; - /* * This structure is filled in by dc_surface_get_status and contains * the last requested address and the currently active address so the called @@ -1528,18 +1493,14 @@ struct dc_plane_state { struct fixed31_32 hdr_mult; struct colorspace_transform gamut_remap_matrix; + // TODO: No longer used, remove + struct dc_hdr_static_metadata hdr_static_ctx; + enum dc_color_space color_space; - bool lut_bank_a; - struct dc_hdr_static_metadata hdr_static_ctx; struct dc_3dlut lut3d_func; struct dc_transfer_func in_shaper_func; struct dc_transfer_func blend_tf; - enum dc_cm2_shaper_3dlut_setting mcm_shaper_3dlut_setting; - bool mcm_lut1d_enable; - struct dc_cm2_func_luts mcm_luts; - enum mpcc_movable_cm_location mcm_location; - struct dc_plane_cm cm; struct dc_transfer_func *gamcor_tf; enum surface_pixel_format format; @@ -1576,6 +1537,11 @@ struct dc_plane_state { bool is_statically_allocated; enum chroma_cositing cositing; + enum dc_cm2_shaper_3dlut_setting mcm_shaper_3dlut_setting; + bool mcm_lut1d_enable; + struct dc_cm2_func_luts mcm_luts; + bool lut_bank_a; + enum mpcc_movable_cm_location mcm_location; struct dc_csc_transform cursor_csc_color_matrix; bool adaptive_sharpness_en; int adaptive_sharpness_policy; @@ -1968,10 +1934,6 @@ struct dc_3dlut *dc_create_3dlut_func(void); void dc_3dlut_func_release(struct dc_3dlut *lut); void dc_3dlut_func_retain(struct dc_3dlut *lut); -struct dc_plane_cm *dc_plane_cm_create(void); -void dc_plane_cm_release(struct dc_plane_cm *cm); -void dc_plane_cm_retain(struct dc_plane_cm *cm); - void dc_post_update_surfaces_to_stream( struct dc *dc); diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index c08d5c005df6..62e35dcb585c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -1493,28 +1493,4 @@ struct dc_validation_dpia_set { uint32_t required_bw; }; -enum dc_cm_lut_swizzle { - CM_LUT_3D_SWIZZLE_LINEAR_RGB, - CM_LUT_3D_SWIZZLE_LINEAR_BGR, - CM_LUT_1D_PACKED_LINEAR -}; - -enum dc_cm_lut_pixel_format { - CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12MSB, - CM_LUT_PIXEL_FORMAT_BGRA16161616_UNORM_12MSB, - CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12LSB, - CM_LUT_PIXEL_FORMAT_BGRA16161616_UNORM_12LSB, - CM_LUT_PIXEL_FORMAT_RGBA16161616_FLOAT_FP1_5_10, - CM_LUT_PIXEL_FORMAT_BGRA16161616_FLOAT_FP1_5_10 -}; - -enum dc_cm_lut_size { - CM_LUT_SIZE_NONE, - CM_LUT_SIZE_999, - CM_LUT_SIZE_171717, - CM_LUT_SIZE_333333, - CM_LUT_SIZE_454545, - CM_LUT_SIZE_656565, -}; - #endif /* DC_TYPES_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c index 5a816442deee..3c7a6569b692 100644 --- a/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c @@ -41,12 +41,12 @@ hubp2->hubp_shift->field_name, hubp2->hubp_mask->field_name void hubp401_program_3dlut_fl_addr(struct hubp *hubp, - const struct dc_plane_address *address) + const struct dc_plane_address address) { struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); - REG_UPDATE(HUBP_3DLUT_ADDRESS_HIGH, HUBP_3DLUT_ADDRESS_HIGH, address->lut3d.addr.high_part); - REG_WRITE(HUBP_3DLUT_ADDRESS_LOW, address->lut3d.addr.low_part); + REG_UPDATE(HUBP_3DLUT_ADDRESS_HIGH, HUBP_3DLUT_ADDRESS_HIGH, address.lut3d.addr.high_part); + REG_WRITE(HUBP_3DLUT_ADDRESS_LOW, address.lut3d.addr.low_part); } void hubp401_program_3dlut_fl_dlg_param(struct hubp *hubp, int refcyc_per_3dlut_group) @@ -72,169 +72,96 @@ int hubp401_get_3dlut_fl_done(struct hubp *hubp) return ret; } -static void hubp401_get_3dlut_fl_xbar_map( - const enum dc_cm_lut_pixel_format format, - enum hubp_3dlut_fl_crossbar_bit_slice *bit_slice_y_g, - enum hubp_3dlut_fl_crossbar_bit_slice *bit_slice_cb_b, - enum hubp_3dlut_fl_crossbar_bit_slice *bit_slice_cr_r) +void hubp401_program_3dlut_fl_addressing_mode(struct hubp *hubp, enum hubp_3dlut_fl_addressing_mode addr_mode) { - switch (format) { - case CM_LUT_PIXEL_FORMAT_BGRA16161616_UNORM_12MSB: - case CM_LUT_PIXEL_FORMAT_BGRA16161616_UNORM_12LSB: - case CM_LUT_PIXEL_FORMAT_BGRA16161616_FLOAT_FP1_5_10: - /* BGRA */ - *bit_slice_cr_r = hubp_3dlut_fl_crossbar_bit_slice_32_47; - *bit_slice_y_g = hubp_3dlut_fl_crossbar_bit_slice_16_31; - *bit_slice_cb_b = hubp_3dlut_fl_crossbar_bit_slice_0_15; - break; - case CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12MSB: - case CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12LSB: - case CM_LUT_PIXEL_FORMAT_RGBA16161616_FLOAT_FP1_5_10: - default: - /* RGBA */ - *bit_slice_cr_r = hubp_3dlut_fl_crossbar_bit_slice_0_15; - *bit_slice_y_g = hubp_3dlut_fl_crossbar_bit_slice_16_31; - *bit_slice_cb_b = hubp_3dlut_fl_crossbar_bit_slice_32_47; - break; - } + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); + + REG_UPDATE(HUBP_3DLUT_CONTROL, HUBP_3DLUT_ADDRESSING_MODE, addr_mode); } -void hubp401_program_3dlut_fl_crossbar(struct hubp *hubp, - const enum dc_cm_lut_pixel_format format) +void hubp401_program_3dlut_fl_width(struct hubp *hubp, enum hubp_3dlut_fl_width width) { struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); - enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_y_g = 0; - enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_cb_b = 0; - enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_cr_r = 0; + REG_UPDATE(HUBP_3DLUT_CONTROL, HUBP_3DLUT_WIDTH, width); +} - hubp401_get_3dlut_fl_xbar_map(format, - &bit_slice_y_g, - &bit_slice_cb_b, - &bit_slice_cr_r); +void hubp401_program_3dlut_fl_tmz_protected(struct hubp *hubp, uint8_t protection_bits) +{ + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); - REG_UPDATE_3(HUBP_3DLUT_CONTROL, - HUBP_3DLUT_CROSSBAR_SELECT_Y_G, bit_slice_y_g, - HUBP_3DLUT_CROSSBAR_SELECT_CB_B, bit_slice_cb_b, - HUBP_3DLUT_CROSSBAR_SELECT_CR_R, bit_slice_cr_r); + REG_UPDATE(HUBP_3DLUT_CONTROL, HUBP_3DLUT_TMZ, protection_bits); } -static enum hubp_3dlut_fl_width hubp401_get_3dlut_fl_width( - const enum dc_cm_lut_size size, - const enum dc_cm_lut_swizzle swizzle) +void hubp401_program_3dlut_fl_crossbar(struct hubp *hubp, + enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_y_g, + enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_cb_b, + enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_cr_r) { - enum hubp_3dlut_fl_width width = 0; - - switch (size) { - case CM_LUT_SIZE_333333: - ASSERT(swizzle != CM_LUT_1D_PACKED_LINEAR); - width = hubp_3dlut_fl_width_33; - break; - case CM_LUT_SIZE_171717: - if (swizzle != CM_LUT_1D_PACKED_LINEAR) { - width = hubp_3dlut_fl_width_17; - } else { - width = hubp_3dlut_fl_width_17_transformed; - } - break; - default: - width = 0; - break; - } + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); - return width; + REG_UPDATE_3(HUBP_3DLUT_CONTROL, + HUBP_3DLUT_CROSSBAR_SELECT_Y_G, bit_slice_y_g, + HUBP_3DLUT_CROSSBAR_SELECT_CB_B, bit_slice_cb_b, + HUBP_3DLUT_CROSSBAR_SELECT_CR_R, bit_slice_cr_r); } -static enum hubp_3dlut_fl_format hubp401_get_3dlut_fl_format( - const enum dc_cm_lut_pixel_format dc_format) +void hubp401_update_3dlut_fl_bias_scale(struct hubp *hubp, uint16_t bias, uint16_t scale) { - enum hubp_3dlut_fl_format hubp_format = hubp_3dlut_fl_format_unorm_12msb_bitslice; - - switch (dc_format) { - case CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12MSB: - case CM_LUT_PIXEL_FORMAT_BGRA16161616_UNORM_12MSB: - hubp_format = hubp_3dlut_fl_format_unorm_12msb_bitslice; - break; - case CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12LSB: - case CM_LUT_PIXEL_FORMAT_BGRA16161616_UNORM_12LSB: - hubp_format = hubp_3dlut_fl_format_unorm_12lsb_bitslice; - break; - case CM_LUT_PIXEL_FORMAT_RGBA16161616_FLOAT_FP1_5_10: - case CM_LUT_PIXEL_FORMAT_BGRA16161616_FLOAT_FP1_5_10: - hubp_format = hubp_3dlut_fl_format_float_fp1_5_10; - break; - default: - BREAK_TO_DEBUGGER(); - break; - } + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); - return hubp_format; + REG_UPDATE_2(_3DLUT_FL_BIAS_SCALE, HUBP0_3DLUT_FL_BIAS, bias, HUBP0_3DLUT_FL_SCALE, scale); } -static enum hubp_3dlut_fl_addressing_mode hubp401_get_3dlut_fl_addr_mode( - const enum dc_cm_lut_swizzle swizzle) +void hubp401_program_3dlut_fl_mode(struct hubp *hubp, enum hubp_3dlut_fl_mode mode) { - enum hubp_3dlut_fl_addressing_mode addr_mode; - - switch (swizzle) { - case CM_LUT_1D_PACKED_LINEAR: - addr_mode = hubp_3dlut_fl_addressing_mode_simple_linear; - break; - case CM_LUT_3D_SWIZZLE_LINEAR_RGB: - case CM_LUT_3D_SWIZZLE_LINEAR_BGR: - default: - addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear; - break; - } + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); - return addr_mode; + REG_UPDATE(_3DLUT_FL_CONFIG, HUBP0_3DLUT_FL_MODE, mode); } -static enum hubp_3dlut_fl_mode hubp401_get_3dlut_fl_mode( - const enum dc_cm_lut_swizzle swizzle) +void hubp401_program_3dlut_fl_format(struct hubp *hubp, enum hubp_3dlut_fl_format format) { - enum hubp_3dlut_fl_mode mode; - - switch (swizzle) { - case CM_LUT_3D_SWIZZLE_LINEAR_RGB: - mode = hubp_3dlut_fl_mode_native_1; - break; - case CM_LUT_3D_SWIZZLE_LINEAR_BGR: - mode = hubp_3dlut_fl_mode_native_2; - break; - case CM_LUT_1D_PACKED_LINEAR: - mode = hubp_3dlut_fl_mode_transform; - break; - default: - mode = hubp_3dlut_fl_mode_disable; - break; - } + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); - return mode; + REG_UPDATE(_3DLUT_FL_CONFIG, HUBP0_3DLUT_FL_FORMAT, format); } -void hubp401_program_3dlut_fl_config(struct hubp *hubp, - const struct dc_3dlut_dma *config) +void hubp401_program_3dlut_fl_config( + struct hubp *hubp, + struct hubp_fl_3dlut_config *cfg) { struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); - enum hubp_3dlut_fl_width width = hubp401_get_3dlut_fl_width(config->size, config->swizzle); - enum hubp_3dlut_fl_format format = hubp401_get_3dlut_fl_format(config->format); - enum hubp_3dlut_fl_addressing_mode addr_mode = hubp401_get_3dlut_fl_addr_mode(config->swizzle); - enum hubp_3dlut_fl_mode mode = hubp401_get_3dlut_fl_mode(config->swizzle); + uint32_t mpc_width = {(cfg->width == 17) ? 0 : 1}; + uint32_t width = {cfg->width}; + + if (cfg->layout == DC_CM2_GPU_MEM_LAYOUT_1D_PACKED_LINEAR) + width = (cfg->width == 17) ? 4916 : 35940; REG_UPDATE_2(_3DLUT_FL_CONFIG, - HUBP0_3DLUT_FL_MODE, mode, - HUBP0_3DLUT_FL_FORMAT, format); + HUBP0_3DLUT_FL_MODE, cfg->mode, + HUBP0_3DLUT_FL_FORMAT, cfg->format); REG_UPDATE_2(_3DLUT_FL_BIAS_SCALE, - HUBP0_3DLUT_FL_BIAS, config->bias, - HUBP0_3DLUT_FL_SCALE, config->scale); - - REG_UPDATE_3(HUBP_3DLUT_CONTROL, - HUBP_3DLUT_WIDTH, width, - HUBP_3DLUT_ADDRESSING_MODE, addr_mode, - HUBP_3DLUT_TMZ, config->addr.tmz_surface); + HUBP0_3DLUT_FL_BIAS, cfg->bias, + HUBP0_3DLUT_FL_SCALE, cfg->scale); + + REG_UPDATE(HUBP_3DLUT_ADDRESS_HIGH, + HUBP_3DLUT_ADDRESS_HIGH, cfg->address.lut3d.addr.high_part); + REG_UPDATE(HUBP_3DLUT_ADDRESS_LOW, + HUBP_3DLUT_ADDRESS_LOW, cfg->address.lut3d.addr.low_part); + + //cross bar + REG_UPDATE_8(HUBP_3DLUT_CONTROL, + HUBP_3DLUT_MPC_WIDTH, mpc_width, + HUBP_3DLUT_WIDTH, width, + HUBP_3DLUT_CROSSBAR_SELECT_CR_R, cfg->crossbar_bit_slice_cr_r, + HUBP_3DLUT_CROSSBAR_SELECT_Y_G, cfg->crossbar_bit_slice_y_g, + HUBP_3DLUT_CROSSBAR_SELECT_CB_B, cfg->crossbar_bit_slice_cb_b, + HUBP_3DLUT_ADDRESSING_MODE, cfg->addr_mode, + HUBP_3DLUT_TMZ, cfg->protection_bits, + HUBP_3DLUT_ENABLE, cfg->enabled ? 1 : 0); } void hubp401_update_mall_sel(struct hubp *hubp, uint32_t mall_sel, bool c_cursor) @@ -1135,13 +1062,19 @@ static struct hubp_funcs dcn401_hubp_funcs = { .hubp_update_mall_sel = hubp401_update_mall_sel, .hubp_prepare_subvp_buffering = hubp32_prepare_subvp_buffering, .hubp_program_mcache_id_and_split_coordinate = hubp401_program_mcache_id_and_split_coordinate, + .hubp_update_3dlut_fl_bias_scale = hubp401_update_3dlut_fl_bias_scale, + .hubp_program_3dlut_fl_mode = hubp401_program_3dlut_fl_mode, + .hubp_program_3dlut_fl_format = hubp401_program_3dlut_fl_format, .hubp_program_3dlut_fl_addr = hubp401_program_3dlut_fl_addr, - .hubp_program_3dlut_fl_config = hubp401_program_3dlut_fl_config, .hubp_program_3dlut_fl_dlg_param = hubp401_program_3dlut_fl_dlg_param, .hubp_enable_3dlut_fl = hubp401_enable_3dlut_fl, + .hubp_program_3dlut_fl_addressing_mode = hubp401_program_3dlut_fl_addressing_mode, + .hubp_program_3dlut_fl_width = hubp401_program_3dlut_fl_width, + .hubp_program_3dlut_fl_tmz_protected = hubp401_program_3dlut_fl_tmz_protected, .hubp_program_3dlut_fl_crossbar = hubp401_program_3dlut_fl_crossbar, .hubp_get_3dlut_fl_done = hubp401_get_3dlut_fl_done, .hubp_clear_tiling = hubp401_clear_tiling, + .hubp_program_3dlut_fl_config = hubp401_program_3dlut_fl_config, .hubp_read_reg_state = hubp3_read_reg_state }; diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.h b/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.h index 043948f64b86..4570b8016de5 100644 --- a/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.h +++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.h @@ -328,17 +328,32 @@ int hubp401_get_3dlut_fl_done(struct hubp *hubp); void hubp401_set_unbounded_requesting(struct hubp *hubp, bool enable); +void hubp401_update_3dlut_fl_bias_scale(struct hubp *hubp, uint16_t bias, uint16_t scale); + void hubp401_program_3dlut_fl_crossbar(struct hubp *hubp, - const enum dc_cm_lut_pixel_format format); + enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_y_g, + enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_cb_b, + enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_cr_r); + +void hubp401_program_3dlut_fl_tmz_protected(struct hubp *hubp, uint8_t protection_bits); + +void hubp401_program_3dlut_fl_width(struct hubp *hubp, enum hubp_3dlut_fl_width width); + +void hubp401_program_3dlut_fl_addressing_mode(struct hubp *hubp, enum hubp_3dlut_fl_addressing_mode addr_mode); void hubp401_enable_3dlut_fl(struct hubp *hubp, bool enable); void hubp401_program_3dlut_fl_dlg_param(struct hubp *hubp, int refcyc_per_3dlut_group); -void hubp401_program_3dlut_fl_addr(struct hubp *hubp, const struct dc_plane_address *address); +void hubp401_program_3dlut_fl_addr(struct hubp *hubp, const struct dc_plane_address address); -void hubp401_program_3dlut_fl_config(struct hubp *hubp, - const struct dc_3dlut_dma *config); +void hubp401_program_3dlut_fl_format(struct hubp *hubp, enum hubp_3dlut_fl_format format); + +void hubp401_program_3dlut_fl_mode(struct hubp *hubp, enum hubp_3dlut_fl_mode mode); + +void hubp401_program_3dlut_fl_config( + struct hubp *hubp, + struct hubp_fl_3dlut_config *cfg); void hubp401_clear_tiling(struct hubp *hubp); diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.c index ad6badcceb12..e4602c3ddc66 100644 --- a/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.c @@ -311,84 +311,19 @@ static void hubp42_program_surface_config( hubp42_program_pixel_format(hubp, format); } -static void hubp42_get_3dlut_fl_xbar_map( - const enum dc_cm_lut_pixel_format format, - enum hubp_3dlut_fl_crossbar_bit_slice *bit_slice_y_g, - enum hubp_3dlut_fl_crossbar_bit_slice *bit_slice_cb_b, - enum hubp_3dlut_fl_crossbar_bit_slice *bit_slice_cr_r) -{ - switch (format) { - case CM_LUT_PIXEL_FORMAT_BGRA16161616_UNORM_12MSB: - case CM_LUT_PIXEL_FORMAT_BGRA16161616_UNORM_12LSB: - case CM_LUT_PIXEL_FORMAT_BGRA16161616_FLOAT_FP1_5_10: - /* BGRA */ - *bit_slice_cr_r = hubp_3dlut_fl_crossbar_bit_slice_32_47; - *bit_slice_y_g = hubp_3dlut_fl_crossbar_bit_slice_16_31; - *bit_slice_cb_b = hubp_3dlut_fl_crossbar_bit_slice_0_15; - break; - case CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12MSB: - case CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12LSB: - case CM_LUT_PIXEL_FORMAT_RGBA16161616_FLOAT_FP1_5_10: - default: - /* RGBA */ - *bit_slice_cr_r = hubp_3dlut_fl_crossbar_bit_slice_0_15; - *bit_slice_y_g = hubp_3dlut_fl_crossbar_bit_slice_16_31; - *bit_slice_cb_b = hubp_3dlut_fl_crossbar_bit_slice_32_47; - break; - } -} - void hubp42_program_3dlut_fl_crossbar(struct hubp *hubp, - const enum dc_cm_lut_pixel_format format) + enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_r, + enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_g, + enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_b) { struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); - enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_g = 0; - enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_b = 0; - enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_r = 0; - - hubp42_get_3dlut_fl_xbar_map(format, - &bit_slice_g, - &bit_slice_b, - &bit_slice_r); - REG_UPDATE_3(HUBP_3DLUT_CONTROL, HUBP_3DLUT_CROSSBAR_SEL_R, bit_slice_r, HUBP_3DLUT_CROSSBAR_SEL_G, bit_slice_g, HUBP_3DLUT_CROSSBAR_SEL_B, bit_slice_b); } -static uint32_t hubp42_get_3dlut_fl_mpc_width( - const enum dc_cm_lut_size size) -{ - uint32_t width = 0; - - switch (size) { - case CM_LUT_SIZE_333333: - width = 1; - break; - case CM_LUT_SIZE_171717: - default: - width = 0; - break; - } - - return width; -} - -void hubp42_program_3dlut_fl_config(struct hubp *hubp, - const struct dc_3dlut_dma *config) -{ - struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); - - uint32_t mpc_width = hubp42_get_3dlut_fl_mpc_width(config->size); - - REG_UPDATE(HUBP_3DLUT_CONTROL, - HUBP_3DLUT_MPC_WIDTH, mpc_width); - - hubp401_program_3dlut_fl_config(hubp, config); -} - static bool hubp42_program_surface_flip_and_addr( struct hubp *hubp, const struct dc_plane_address *address, @@ -670,10 +605,15 @@ struct hubp_funcs dcn42_hubp_funcs = { .hubp_set_flip_int = hubp1_set_flip_int, .hubp_in_blank = hubp1_in_blank, .program_extended_blank = hubp31_program_extended_blank_value, + .hubp_update_3dlut_fl_bias_scale = hubp401_update_3dlut_fl_bias_scale, + .hubp_program_3dlut_fl_mode = hubp401_program_3dlut_fl_mode, + .hubp_program_3dlut_fl_format = hubp401_program_3dlut_fl_format, .hubp_program_3dlut_fl_addr = hubp401_program_3dlut_fl_addr, - .hubp_program_3dlut_fl_config = hubp42_program_3dlut_fl_config, .hubp_program_3dlut_fl_dlg_param = hubp401_program_3dlut_fl_dlg_param, .hubp_enable_3dlut_fl = hubp401_enable_3dlut_fl, + .hubp_program_3dlut_fl_addressing_mode = hubp401_program_3dlut_fl_addressing_mode, + .hubp_program_3dlut_fl_width = hubp401_program_3dlut_fl_width, + .hubp_program_3dlut_fl_tmz_protected = hubp401_program_3dlut_fl_tmz_protected, .hubp_program_3dlut_fl_crossbar = hubp42_program_3dlut_fl_crossbar, .hubp_get_3dlut_fl_done = hubp401_get_3dlut_fl_done, .hubp_clear_tiling = hubp3_clear_tiling, diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.h b/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.h index 88bb1337ab9d..f0e614136228 100644 --- a/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.h +++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.h @@ -58,11 +58,11 @@ bool hubp42_construct( const struct dcn_hubp2_shift *hubp_shift, const struct dcn_hubp2_mask *hubp_mask); -void hubp42_program_3dlut_fl_crossbar(struct hubp *hubp, - const enum dc_cm_lut_pixel_format format); - -void hubp42_program_3dlut_fl_config(struct hubp *hubp, - const struct dc_3dlut_dma *config); +void hubp42_program_3dlut_fl_crossbar( + struct hubp *hubp, + enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_r, + enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_g, + enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_b); void hubp42_read_state(struct hubp *hubp); diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c index 9768b8f6b6fb..98e78aa2259c 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c @@ -95,6 +95,10 @@ void dcn401_program_gamut_remap(struct pipe_ctx *pipe_ctx) unsigned int mpcc_id = pipe_ctx->plane_res.mpcc_inst; struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc; + //For now assert if location is not pre-blend + if (pipe_ctx->plane_state) + ASSERT(pipe_ctx->plane_state->mcm_location == MPCC_MOVABLE_CM_LOCATION_BEFORE); + // program MPCC_MCM_FIRST_GAMUT_REMAP memset(&mpc_adjust, 0, sizeof(mpc_adjust)); mpc_adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; @@ -374,180 +378,300 @@ void dcn401_init_hw(struct dc *dc) } } -void dcn401_trigger_3dlut_dma_load(struct dc *dc, struct pipe_ctx *pipe_ctx) +static void dcn401_get_mcm_lut_xable_from_pipe_ctx(struct dc *dc, struct pipe_ctx *pipe_ctx, + enum MCM_LUT_XABLE *shaper_xable, + enum MCM_LUT_XABLE *lut3d_xable, + enum MCM_LUT_XABLE *lut1d_xable) { - (void)dc; - struct hubp *hubp = pipe_ctx->plane_res.hubp; + enum dc_cm2_shaper_3dlut_setting shaper_3dlut_setting = DC_CM2_SHAPER_3DLUT_SETTING_BYPASS_ALL; + bool lut1d_enable = false; + struct mpc *mpc = dc->res_pool->mpc; + int mpcc_id = pipe_ctx->plane_res.hubp->inst; - if (hubp->funcs->hubp_enable_3dlut_fl) { - hubp->funcs->hubp_enable_3dlut_fl(hubp, true); + if (!pipe_ctx->plane_state) + return; + shaper_3dlut_setting = pipe_ctx->plane_state->mcm_shaper_3dlut_setting; + lut1d_enable = pipe_ctx->plane_state->mcm_lut1d_enable; + mpc->funcs->set_movable_cm_location(mpc, MPCC_MOVABLE_CM_LOCATION_BEFORE, mpcc_id); + pipe_ctx->plane_state->mcm_location = MPCC_MOVABLE_CM_LOCATION_BEFORE; + + *lut1d_xable = lut1d_enable ? MCM_LUT_ENABLE : MCM_LUT_DISABLE; + + switch (shaper_3dlut_setting) { + case DC_CM2_SHAPER_3DLUT_SETTING_BYPASS_ALL: + *lut3d_xable = *shaper_xable = MCM_LUT_DISABLE; + break; + case DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER: + *lut3d_xable = MCM_LUT_DISABLE; + *shaper_xable = MCM_LUT_ENABLE; + break; + case DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER_3DLUT: + *lut3d_xable = *shaper_xable = MCM_LUT_ENABLE; + break; } } -bool dcn401_set_mcm_luts(struct pipe_ctx *pipe_ctx, - const struct dc_plane_state *plane_state) +void dcn401_populate_mcm_luts(struct dc *dc, + struct pipe_ctx *pipe_ctx, + struct dc_cm2_func_luts mcm_luts, + bool lut_bank_a) { - struct dc *dc = pipe_ctx->plane_res.hubp->ctx->dc; struct dpp *dpp_base = pipe_ctx->plane_res.dpp; struct hubp *hubp = pipe_ctx->plane_res.hubp; - const struct dc_plane_cm *cm = &plane_state->cm; int mpcc_id = hubp->inst; struct mpc *mpc = dc->res_pool->mpc; union mcm_lut_params m_lut_params; - struct dc_3dlut_dma lut3d_dma; - bool lut_enable; - bool lut_bank_a; + enum dc_cm2_transfer_func_source lut3d_src = mcm_luts.lut3d_data.lut3d_src; + enum hubp_3dlut_fl_format format = 0; + enum hubp_3dlut_fl_mode mode; + enum hubp_3dlut_fl_width width = 0; + enum hubp_3dlut_fl_addressing_mode addr_mode; + enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_y_g = 0; + enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cb_b = 0; + enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cr_r = 0; + enum MCM_LUT_XABLE shaper_xable = MCM_LUT_DISABLE; + enum MCM_LUT_XABLE lut3d_xable = MCM_LUT_DISABLE; + enum MCM_LUT_XABLE lut1d_xable = MCM_LUT_DISABLE; bool rval; - bool result = true; - /* decide LUT bank based on current in use */ - mpc->funcs->get_lut_mode(mpc, MCM_LUT_1DLUT, mpcc_id, &lut_enable, &lut_bank_a); - if (!lut_enable) { - mpc->funcs->get_lut_mode(mpc, MCM_LUT_SHAPER, mpcc_id, &lut_enable, &lut_bank_a); - } - if (!lut_enable) { - mpc->funcs->get_lut_mode(mpc, MCM_LUT_3DLUT, mpcc_id, &lut_enable, &lut_bank_a); - } - - /* switch to the next bank */ - if (lut_enable) { - lut_bank_a = !lut_bank_a; - } - - /* MCM location fixed to pre-blend */ - mpc->funcs->set_movable_cm_location(mpc, MPCC_MOVABLE_CM_LOCATION_BEFORE, mpcc_id); + dcn401_get_mcm_lut_xable_from_pipe_ctx(dc, pipe_ctx, &shaper_xable, &lut3d_xable, &lut1d_xable); /* 1D LUT */ - lut_enable = cm->flags.bits.blend_enable; - memset(&m_lut_params, 0, sizeof(m_lut_params)); - if (lut_enable) { - if (cm->blend_func.type == TF_TYPE_HWPWL) - m_lut_params.pwl = &cm->blend_func.pwl; - else if (cm->blend_func.type == TF_TYPE_DISTRIBUTED_POINTS) { - rval = cm3_helper_translate_curve_to_hw_format(plane_state->ctx, - &cm->blend_func, - &dpp_base->regamma_params, - false); + if (mcm_luts.lut1d_func) { + memset(&m_lut_params, 0, sizeof(m_lut_params)); + if (mcm_luts.lut1d_func->type == TF_TYPE_HWPWL) + m_lut_params.pwl = &mcm_luts.lut1d_func->pwl; + else if (mcm_luts.lut1d_func->type == TF_TYPE_DISTRIBUTED_POINTS) { + rval = cm3_helper_translate_curve_to_hw_format(mpc->ctx, + mcm_luts.lut1d_func, + &dpp_base->regamma_params, false); m_lut_params.pwl = rval ? &dpp_base->regamma_params : NULL; } - - if (!m_lut_params.pwl) { - lut_enable = false; + if (m_lut_params.pwl) { + if (mpc->funcs->populate_lut) + mpc->funcs->populate_lut(mpc, MCM_LUT_1DLUT, m_lut_params, lut_bank_a, mpcc_id); } - } else { - lut_enable = false; + if (mpc->funcs->program_lut_mode) + mpc->funcs->program_lut_mode(mpc, MCM_LUT_1DLUT, lut1d_xable && m_lut_params.pwl, lut_bank_a, mpcc_id); } - if (mpc->funcs->program_lut_mode) - mpc->funcs->program_lut_mode(mpc, MCM_LUT_1DLUT, lut_enable, lut_bank_a, CM_LUT_SIZE_NONE, mpcc_id); - if (lut_enable && mpc->funcs->populate_lut) - mpc->funcs->populate_lut(mpc, MCM_LUT_1DLUT, &m_lut_params, lut_bank_a, mpcc_id); - /* Shaper */ - lut_enable = cm->flags.bits.shaper_enable; - if (lut_enable) { + if (mcm_luts.shaper && mcm_luts.lut3d_data.mpc_3dlut_enable) { memset(&m_lut_params, 0, sizeof(m_lut_params)); - if (cm->shaper_func.type == TF_TYPE_HWPWL) - m_lut_params.pwl = &cm->shaper_func.pwl; - else if (cm->shaper_func.type == TF_TYPE_DISTRIBUTED_POINTS) { + if (mcm_luts.shaper->type == TF_TYPE_HWPWL) + m_lut_params.pwl = &mcm_luts.shaper->pwl; + else if (mcm_luts.shaper->type == TF_TYPE_DISTRIBUTED_POINTS) { ASSERT(false); - rval = cm3_helper_translate_curve_to_hw_format(plane_state->ctx, - &cm->shaper_func, - &dpp_base->shaper_params, - true); - m_lut_params.pwl = rval ? &dpp_base->shaper_params : NULL; + rval = cm3_helper_translate_curve_to_hw_format(mpc->ctx, + mcm_luts.shaper, + &dpp_base->regamma_params, true); + m_lut_params.pwl = rval ? &dpp_base->regamma_params : NULL; } - if (!m_lut_params.pwl) { - lut_enable = false; + if (m_lut_params.pwl) { + if (mpc->funcs->mcm.populate_lut) + mpc->funcs->mcm.populate_lut(mpc, m_lut_params, lut_bank_a, mpcc_id); + if (mpc->funcs->program_lut_mode) + mpc->funcs->program_lut_mode(mpc, MCM_LUT_SHAPER, MCM_LUT_ENABLE, lut_bank_a, mpcc_id); } - } else { - lut_enable = false; } - if (mpc->funcs->program_lut_mode) - mpc->funcs->program_lut_mode(mpc, MCM_LUT_SHAPER, lut_enable, lut_bank_a, CM_LUT_SIZE_NONE, mpcc_id); - if (lut_enable && mpc->funcs->populate_lut) - mpc->funcs->populate_lut(mpc, MCM_LUT_SHAPER, &m_lut_params, lut_bank_a, mpcc_id); + /* 3DLUT */ + switch (lut3d_src) { + case DC_CM2_TRANSFER_FUNC_SOURCE_SYSMEM: + memset(&m_lut_params, 0, sizeof(m_lut_params)); + if (hubp->funcs->hubp_enable_3dlut_fl) + hubp->funcs->hubp_enable_3dlut_fl(hubp, false); - /* NOTE: Toggling from DMA->Host is not supported atomically as hardware - * blocks writes until 3DLUT FL mode is cleared from HUBP on VUpdate. - * Expectation is either option is used consistently. - */ + if (mcm_luts.lut3d_data.lut3d_func && mcm_luts.lut3d_data.lut3d_func->state.bits.initialized) { + m_lut_params.lut3d = &mcm_luts.lut3d_data.lut3d_func->lut_3d; + if (mpc->funcs->populate_lut) + mpc->funcs->populate_lut(mpc, MCM_LUT_3DLUT, m_lut_params, lut_bank_a, mpcc_id); + if (mpc->funcs->program_lut_mode) + mpc->funcs->program_lut_mode(mpc, MCM_LUT_3DLUT, lut3d_xable, lut_bank_a, + mpcc_id); + } + break; + case DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM: + switch (mcm_luts.lut3d_data.gpu_mem_params.size) { +#if defined(CONFIG_DRM_AMD_DC_DCN4_2) + case DC_CM2_GPU_MEM_SIZE_333333: + if (dc->caps.color.mpc.rmcm_3d_lut_caps.lut_dim_caps.dim_33) + width = hubp_3dlut_fl_width_33; + break; +#endif + case DC_CM2_GPU_MEM_SIZE_171717: + width = hubp_3dlut_fl_width_17; + break; + case DC_CM2_GPU_MEM_SIZE_TRANSFORMED: + width = hubp_3dlut_fl_width_transformed; + break; + default: + //TODO: handle default case + break; + } - /* 3DLUT */ - lut_enable = cm->flags.bits.lut3d_enable; - if (lut_enable && cm->flags.bits.lut3d_dma_enable) { - /* Fast (DMA) Load Mode */ - /* MPC */ - if (mpc->funcs->program_lut_mode) - mpc->funcs->program_lut_mode(mpc, MCM_LUT_3DLUT, lut_enable, lut_bank_a, cm->lut3d_dma.size, mpcc_id); + //check for support + if (mpc->funcs->mcm.is_config_supported && + !mpc->funcs->mcm.is_config_supported(width)) + break; - /* only supports 12 bit */ if (mpc->funcs->program_lut_read_write_control) - mpc->funcs->program_lut_read_write_control(mpc, MCM_LUT_3DLUT, lut_bank_a, 12, mpcc_id); + mpc->funcs->program_lut_read_write_control(mpc, MCM_LUT_3DLUT, lut_bank_a, mpcc_id); + if (mpc->funcs->program_lut_mode) + mpc->funcs->program_lut_mode(mpc, MCM_LUT_3DLUT, lut3d_xable, lut_bank_a, mpcc_id); - if (mpc->funcs->update_3dlut_fast_load_select) - mpc->funcs->update_3dlut_fast_load_select(mpc, mpcc_id, hubp->inst); + if (hubp->funcs->hubp_program_3dlut_fl_addr) + hubp->funcs->hubp_program_3dlut_fl_addr(hubp, mcm_luts.lut3d_data.gpu_mem_params.addr); - /* HUBP */ - if (hubp->funcs->hubp_program_3dlut_fl_config) - hubp->funcs->hubp_program_3dlut_fl_config(hubp, &cm->lut3d_dma); + if (mpc->funcs->mcm.program_bit_depth) + mpc->funcs->mcm.program_bit_depth(mpc, mcm_luts.lut3d_data.gpu_mem_params.bit_depth, mpcc_id); - if (hubp->funcs->hubp_program_3dlut_fl_crossbar) - hubp->funcs->hubp_program_3dlut_fl_crossbar(hubp, cm->lut3d_dma.format); + switch (mcm_luts.lut3d_data.gpu_mem_params.layout) { + case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_RGB: + mode = hubp_3dlut_fl_mode_native_1; + addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear; + break; + case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_BGR: + mode = hubp_3dlut_fl_mode_native_2; + addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear; + break; + case DC_CM2_GPU_MEM_LAYOUT_1D_PACKED_LINEAR: + mode = hubp_3dlut_fl_mode_transform; + addr_mode = hubp_3dlut_fl_addressing_mode_simple_linear; + break; + default: + mode = hubp_3dlut_fl_mode_disable; + addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear; + break; + } + if (hubp->funcs->hubp_program_3dlut_fl_mode) + hubp->funcs->hubp_program_3dlut_fl_mode(hubp, mode); - if (hubp->funcs->hubp_program_3dlut_fl_addr) - hubp->funcs->hubp_program_3dlut_fl_addr(hubp, &cm->lut3d_dma.addr); + if (hubp->funcs->hubp_program_3dlut_fl_addressing_mode) + hubp->funcs->hubp_program_3dlut_fl_addressing_mode(hubp, addr_mode); - if (hubp->funcs->hubp_enable_3dlut_fl) { - hubp->funcs->hubp_enable_3dlut_fl(hubp, true); - } else { - /* GPU memory only supports fast load path */ - BREAK_TO_DEBUGGER(); - lut_enable = false; - result = false; + switch (mcm_luts.lut3d_data.gpu_mem_params.format_params.format) { + case DC_CM2_GPU_MEM_FORMAT_16161616_UNORM_12MSB: + format = hubp_3dlut_fl_format_unorm_12msb_bitslice; + break; + case DC_CM2_GPU_MEM_FORMAT_16161616_UNORM_12LSB: + format = hubp_3dlut_fl_format_unorm_12lsb_bitslice; + break; + case DC_CM2_GPU_MEM_FORMAT_16161616_FLOAT_FP1_5_10: + format = hubp_3dlut_fl_format_float_fp1_5_10; + break; + } + if (hubp->funcs->hubp_program_3dlut_fl_format) + hubp->funcs->hubp_program_3dlut_fl_format(hubp, format); + if (hubp->funcs->hubp_update_3dlut_fl_bias_scale && + mpc->funcs->mcm.program_bias_scale) { + mpc->funcs->mcm.program_bias_scale(mpc, + mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.bias, + mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.scale, + mpcc_id); + hubp->funcs->hubp_update_3dlut_fl_bias_scale(hubp, + mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.bias, + mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.scale); } - } else { - /* Legacy (Host) Load Mode */ - memset(&m_lut_params, 0, sizeof(m_lut_params)); - if (cm->flags.bits.lut3d_enable && cm->lut3d_func.state.bits.initialized) { - m_lut_params.lut3d = &cm->lut3d_func.lut_3d; - } else { - lut_enable = false; + //navi 4x has a bug and r and blue are swapped and need to be worked around here in + //TODO: need to make a method for get_xbar per asic OR do the workaround in program_crossbar for 4x + switch (mcm_luts.lut3d_data.gpu_mem_params.component_order) { + case DC_CM2_GPU_MEM_PIXEL_COMPONENT_ORDER_RGBA: + default: + crossbar_bit_slice_cr_r = hubp_3dlut_fl_crossbar_bit_slice_0_15; + crossbar_bit_slice_y_g = hubp_3dlut_fl_crossbar_bit_slice_16_31; + crossbar_bit_slice_cb_b = hubp_3dlut_fl_crossbar_bit_slice_32_47; + break; } - /* MPC */ - if (mpc->funcs->program_lut_mode) - mpc->funcs->program_lut_mode(mpc, - MCM_LUT_3DLUT, - lut_enable, - lut_bank_a, - cm->lut3d_func.lut_3d.use_tetrahedral_9 ? CM_LUT_SIZE_999 : CM_LUT_SIZE_171717, - mpcc_id); - - if (lut_enable) { - if (mpc->funcs->program_lut_read_write_control) - mpc->funcs->program_lut_read_write_control(mpc, - MCM_LUT_3DLUT, - lut_bank_a, - cm->lut3d_func.lut_3d.use_12bits ? 12 : 10, - mpcc_id); + if (hubp->funcs->hubp_program_3dlut_fl_crossbar) + hubp->funcs->hubp_program_3dlut_fl_crossbar(hubp, + crossbar_bit_slice_cr_r, + crossbar_bit_slice_y_g, + crossbar_bit_slice_cb_b); - if (mpc->funcs->update_3dlut_fast_load_select) - mpc->funcs->update_3dlut_fast_load_select(mpc, mpcc_id, 0xf); + if (mpc->funcs->mcm.program_lut_read_write_control) + mpc->funcs->mcm.program_lut_read_write_control(mpc, MCM_LUT_3DLUT, lut_bank_a, true, mpcc_id); - if (mpc->funcs->populate_lut) - mpc->funcs->populate_lut(mpc, MCM_LUT_3DLUT, &m_lut_params, lut_bank_a, mpcc_id); - } + if (mpc->funcs->mcm.program_3dlut_size) + mpc->funcs->mcm.program_3dlut_size(mpc, width, mpcc_id); - /* HUBP */ - memset(&lut3d_dma, 0, sizeof(lut3d_dma)); - if (hubp->funcs->hubp_program_3dlut_fl_config) - hubp->funcs->hubp_program_3dlut_fl_config(hubp, &lut3d_dma); + if (mpc->funcs->update_3dlut_fast_load_select) + mpc->funcs->update_3dlut_fast_load_select(mpc, mpcc_id, hubp->inst); if (hubp->funcs->hubp_enable_3dlut_fl) - hubp->funcs->hubp_enable_3dlut_fl(hubp, false); + hubp->funcs->hubp_enable_3dlut_fl(hubp, true); + else { + if (mpc->funcs->program_lut_mode) { + mpc->funcs->program_lut_mode(mpc, MCM_LUT_SHAPER, MCM_LUT_DISABLE, lut_bank_a, mpcc_id); + mpc->funcs->program_lut_mode(mpc, MCM_LUT_3DLUT, MCM_LUT_DISABLE, lut_bank_a, mpcc_id); + mpc->funcs->program_lut_mode(mpc, MCM_LUT_1DLUT, MCM_LUT_DISABLE, lut_bank_a, mpcc_id); + } + } + break; + + } +} + +void dcn401_trigger_3dlut_dma_load(struct dc *dc, struct pipe_ctx *pipe_ctx) +{ + (void)dc; + struct hubp *hubp = pipe_ctx->plane_res.hubp; + + if (hubp->funcs->hubp_enable_3dlut_fl) { + hubp->funcs->hubp_enable_3dlut_fl(hubp, true); + } +} + +bool dcn401_set_mcm_luts(struct pipe_ctx *pipe_ctx, + const struct dc_plane_state *plane_state) +{ + struct dpp *dpp_base = pipe_ctx->plane_res.dpp; + int mpcc_id = pipe_ctx->plane_res.hubp->inst; + struct dc *dc = pipe_ctx->stream_res.opp->ctx->dc; + struct mpc *mpc = dc->res_pool->mpc; + bool result; + const struct pwl_params *lut_params = NULL; + bool rval; + + if (plane_state->mcm_luts.lut3d_data.lut3d_src == DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM) { + dcn401_populate_mcm_luts(dc, pipe_ctx, plane_state->mcm_luts, plane_state->lut_bank_a); + return true; + } + + mpc->funcs->set_movable_cm_location(mpc, MPCC_MOVABLE_CM_LOCATION_BEFORE, mpcc_id); + pipe_ctx->plane_state->mcm_location = MPCC_MOVABLE_CM_LOCATION_BEFORE; + // 1D LUT + if (plane_state->blend_tf.type == TF_TYPE_HWPWL) + lut_params = &plane_state->blend_tf.pwl; + else if (plane_state->blend_tf.type == TF_TYPE_DISTRIBUTED_POINTS) { + rval = cm3_helper_translate_curve_to_hw_format(plane_state->ctx, + &plane_state->blend_tf, + &dpp_base->regamma_params, false); + lut_params = rval ? &dpp_base->regamma_params : NULL; + } + result = mpc->funcs->program_1dlut(mpc, lut_params, mpcc_id); + lut_params = NULL; + + // Shaper + if (plane_state->in_shaper_func.type == TF_TYPE_HWPWL) + lut_params = &plane_state->in_shaper_func.pwl; + else if (plane_state->in_shaper_func.type == TF_TYPE_DISTRIBUTED_POINTS) { + // TODO: dpp_base replace + rval = cm3_helper_translate_curve_to_hw_format(plane_state->ctx, + &plane_state->in_shaper_func, + &dpp_base->shaper_params, true); + lut_params = rval ? &dpp_base->shaper_params : NULL; + } + result &= mpc->funcs->program_shaper(mpc, lut_params, mpcc_id); + + // 3D + if (mpc->funcs->program_3dlut) { + if (plane_state->lut3d_func.state.bits.initialized == 1) + result &= mpc->funcs->program_3dlut(mpc, &plane_state->lut3d_func.lut_3d, mpcc_id); + else + result &= mpc->funcs->program_3dlut(mpc, NULL, mpcc_id); } return result; @@ -1824,9 +1948,10 @@ void dcn401_perform_3dlut_wa_unlock(struct pipe_ctx *pipe_ctx) for (odm_pipe = pipe_ctx; odm_pipe != NULL; odm_pipe = odm_pipe->next_odm_pipe) { for (mpc_pipe = odm_pipe; mpc_pipe != NULL; mpc_pipe = mpc_pipe->bottom_pipe) { - if (mpc_pipe->plane_state && - mpc_pipe->plane_state->cm.flags.bits.lut3d_enable && - mpc_pipe->plane_state->cm.flags.bits.lut3d_dma_enable) { + if (mpc_pipe->plane_state && mpc_pipe->plane_state->mcm_luts.lut3d_data.lut3d_src + == DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM + && mpc_pipe->plane_state->mcm_shaper_3dlut_setting + == DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER_3DLUT) { wa_pipes[wa_pipe_ct++] = mpc_pipe; } } diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c index 46f2f9833d9e..53ff5a02af02 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c @@ -394,6 +394,68 @@ void dcn42_program_cm_hist( plane_state->cm_hist_control, plane_state->color_space); } +static void dc_get_lut_xbar( + enum dc_cm2_gpu_mem_pixel_component_order order, + enum hubp_3dlut_fl_crossbar_bit_slice *cr_r, + enum hubp_3dlut_fl_crossbar_bit_slice *y_g, + enum hubp_3dlut_fl_crossbar_bit_slice *cb_b) +{ + switch (order) { + case DC_CM2_GPU_MEM_PIXEL_COMPONENT_ORDER_RGBA: + *cr_r = hubp_3dlut_fl_crossbar_bit_slice_32_47; + *y_g = hubp_3dlut_fl_crossbar_bit_slice_16_31; + *cb_b = hubp_3dlut_fl_crossbar_bit_slice_0_15; + break; + case DC_CM2_GPU_MEM_PIXEL_COMPONENT_ORDER_BGRA: + *cr_r = hubp_3dlut_fl_crossbar_bit_slice_0_15; + *y_g = hubp_3dlut_fl_crossbar_bit_slice_16_31; + *cb_b = hubp_3dlut_fl_crossbar_bit_slice_32_47; + break; + } +} + +static void dc_get_lut_mode( + enum dc_cm2_gpu_mem_layout layout, + enum hubp_3dlut_fl_mode *mode, + enum hubp_3dlut_fl_addressing_mode *addr_mode) +{ + switch (layout) { + case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_RGB: + *mode = hubp_3dlut_fl_mode_native_1; + *addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear; + break; + case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_BGR: + *mode = hubp_3dlut_fl_mode_native_2; + *addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear; + break; + case DC_CM2_GPU_MEM_LAYOUT_1D_PACKED_LINEAR: + *mode = hubp_3dlut_fl_mode_transform; + *addr_mode = hubp_3dlut_fl_addressing_mode_simple_linear; + break; + default: + *mode = hubp_3dlut_fl_mode_disable; + *addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear; + break; + } +} + +static void dc_get_lut_format( + enum dc_cm2_gpu_mem_format dc_format, + enum hubp_3dlut_fl_format *format) +{ + switch (dc_format) { + case DC_CM2_GPU_MEM_FORMAT_16161616_UNORM_12MSB: + *format = hubp_3dlut_fl_format_unorm_12msb_bitslice; + break; + case DC_CM2_GPU_MEM_FORMAT_16161616_UNORM_12LSB: + *format = hubp_3dlut_fl_format_unorm_12lsb_bitslice; + break; + case DC_CM2_GPU_MEM_FORMAT_16161616_FLOAT_FP1_5_10: + *format = hubp_3dlut_fl_format_float_fp1_5_10; + break; + } +} + static bool dc_is_rmcm_3dlut_supported(struct hubp *hubp, struct mpc *mpc) { if (mpc->funcs->rmcm.power_on_shaper_3dlut && @@ -404,17 +466,119 @@ static bool dc_is_rmcm_3dlut_supported(struct hubp *hubp, struct mpc *mpc) return false; } +static bool is_rmcm_3dlut_fl_supported(struct dc *dc, enum dc_cm2_gpu_mem_size size) +{ + if (!dc->caps.color.mpc.rmcm_3d_lut_caps.dma_3d_lut) + return false; + if (size == DC_CM2_GPU_MEM_SIZE_171717) + return (dc->caps.color.mpc.rmcm_3d_lut_caps.lut_dim_caps.dim_17); + else if (size == DC_CM2_GPU_MEM_SIZE_333333) + return (dc->caps.color.mpc.rmcm_3d_lut_caps.lut_dim_caps.dim_33); + return false; +} + +static void dcn42_set_mcm_location_post_blend(struct dc *dc, struct pipe_ctx *pipe_ctx, bool bPostBlend) +{ + struct mpc *mpc = dc->res_pool->mpc; + int mpcc_id = pipe_ctx->plane_res.hubp->inst; + + if (!pipe_ctx->plane_state) + return; + + mpc->funcs->set_movable_cm_location(mpc, MPCC_MOVABLE_CM_LOCATION_BEFORE, mpcc_id); + pipe_ctx->plane_state->mcm_location = (bPostBlend) ? + MPCC_MOVABLE_CM_LOCATION_AFTER : + MPCC_MOVABLE_CM_LOCATION_BEFORE; +} + +static void dcn42_get_mcm_lut_xable_from_pipe_ctx(struct dc *dc, struct pipe_ctx *pipe_ctx, + enum MCM_LUT_XABLE *shaper_xable, + enum MCM_LUT_XABLE *lut3d_xable, + enum MCM_LUT_XABLE *lut1d_xable) +{ + enum dc_cm2_shaper_3dlut_setting shaper_3dlut_setting = DC_CM2_SHAPER_3DLUT_SETTING_BYPASS_ALL; + bool lut1d_enable = false; + struct mpc *mpc = dc->res_pool->mpc; + int mpcc_id = pipe_ctx->plane_res.hubp->inst; + + if (!pipe_ctx->plane_state) + return; + shaper_3dlut_setting = pipe_ctx->plane_state->mcm_shaper_3dlut_setting; + lut1d_enable = pipe_ctx->plane_state->mcm_lut1d_enable; + mpc->funcs->set_movable_cm_location(mpc, MPCC_MOVABLE_CM_LOCATION_BEFORE, mpcc_id); + pipe_ctx->plane_state->mcm_location = MPCC_MOVABLE_CM_LOCATION_BEFORE; + + *lut1d_xable = lut1d_enable ? MCM_LUT_ENABLE : MCM_LUT_DISABLE; + + switch (shaper_3dlut_setting) { + case DC_CM2_SHAPER_3DLUT_SETTING_BYPASS_ALL: + *lut3d_xable = *shaper_xable = MCM_LUT_DISABLE; + break; + case DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER: + *lut3d_xable = MCM_LUT_DISABLE; + *shaper_xable = MCM_LUT_ENABLE; + break; + case DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER_3DLUT: + *lut3d_xable = *shaper_xable = MCM_LUT_ENABLE; + break; + } +} + +static void fl_get_lut_mode( + enum dc_cm2_gpu_mem_layout layout, + enum dc_cm2_gpu_mem_size size, + enum hubp_3dlut_fl_mode *mode, + enum hubp_3dlut_fl_addressing_mode *addr_mode, + enum hubp_3dlut_fl_width *width) +{ + *width = hubp_3dlut_fl_width_17; + + if (size == DC_CM2_GPU_MEM_SIZE_333333) + *width = hubp_3dlut_fl_width_33; + + switch (layout) { + case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_RGB: + *mode = hubp_3dlut_fl_mode_native_1; + *addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear; + break; + case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_BGR: + *mode = hubp_3dlut_fl_mode_native_2; + *addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear; + break; + case DC_CM2_GPU_MEM_LAYOUT_1D_PACKED_LINEAR: + *mode = hubp_3dlut_fl_mode_transform; + *addr_mode = hubp_3dlut_fl_addressing_mode_simple_linear; + break; + default: + *mode = hubp_3dlut_fl_mode_disable; + *addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear; + break; + } +} + bool dcn42_program_rmcm_luts( struct hubp *hubp, struct pipe_ctx *pipe_ctx, - const struct dc_plane_cm *cm, + enum dc_cm2_transfer_func_source lut3d_src, + struct dc_cm2_func_luts *mcm_luts, struct mpc *mpc, + bool lut_bank_a, int mpcc_id) { struct dpp *dpp_base = pipe_ctx->plane_res.dpp; union mcm_lut_params m_lut_params = {0}; + enum MCM_LUT_XABLE shaper_xable, lut3d_xable = MCM_LUT_DISABLE, lut1d_xable; + enum hubp_3dlut_fl_mode mode; + enum hubp_3dlut_fl_addressing_mode addr_mode; + enum hubp_3dlut_fl_format format = hubp_3dlut_fl_format_unorm_12msb_bitslice; + enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_y_g = hubp_3dlut_fl_crossbar_bit_slice_16_31; + enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cb_b = hubp_3dlut_fl_crossbar_bit_slice_0_15; + enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cr_r = hubp_3dlut_fl_crossbar_bit_slice_32_47; + enum hubp_3dlut_fl_width width = hubp_3dlut_fl_width_17; + struct dc *dc = hubp->ctx->dc; + struct hubp_fl_3dlut_config fl_config; struct mpc_fl_3dlut_config mpc_fl_config; struct dc_stream_state *stream = pipe_ctx->stream; @@ -422,23 +586,25 @@ bool dcn42_program_rmcm_luts( // true->false when it can be allocated at DI time struct dc_rmcm_3dlut *rmcm_3dlut = dc_stream_get_3dlut_for_stream(dc, stream, false); - bool lut_bank_a = true; // TODO get from HW - //check to see current pipe is part of a stream with allocated rmcm 3dlut if (!rmcm_3dlut) return false; + rmcm_3dlut->protection_bits = mcm_luts->lut3d_data.rmcm_tmz; + + dcn42_get_mcm_lut_xable_from_pipe_ctx(dc, pipe_ctx, &shaper_xable, &lut3d_xable, &lut1d_xable); + /* Shaper */ - if (cm->flags.bits.shaper_enable) { + if (mcm_luts->shaper) { memset(&m_lut_params, 0, sizeof(m_lut_params)); - if (cm->shaper_func.type == TF_TYPE_HWPWL) { - m_lut_params.pwl = &cm->shaper_func.pwl; - } else if (cm->shaper_func.type == TF_TYPE_DISTRIBUTED_POINTS) { + if (mcm_luts->shaper->type == TF_TYPE_HWPWL) { + m_lut_params.pwl = &mcm_luts->shaper->pwl; + } else if (mcm_luts->shaper->type == TF_TYPE_DISTRIBUTED_POINTS) { ASSERT(false); cm_helper_translate_curve_to_hw_format( dc->ctx, - &cm->shaper_func, + mcm_luts->shaper, &dpp_base->shaper_params, true); m_lut_params.pwl = &dpp_base->shaper_params; } @@ -454,21 +620,58 @@ bool dcn42_program_rmcm_luts( } /* 3DLUT */ - if (!cm->flags.bits.lut3d_dma_enable) { + switch (lut3d_src) { + case DC_CM2_TRANSFER_FUNC_SOURCE_SYSMEM: memset(&m_lut_params, 0, sizeof(m_lut_params)); // Don't know what to do in this case. - } else { - if (!dc_is_rmcm_3dlut_supported(hubp, mpc)) + //case DC_CM2_TRANSFER_FUNC_SOURCE_SYSMEM: + break; + case DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM: + fl_get_lut_mode(mcm_luts->lut3d_data.gpu_mem_params.layout, + mcm_luts->lut3d_data.gpu_mem_params.size, + &mode, + &addr_mode, + &width); + + if (!dc_is_rmcm_3dlut_supported(hubp, mpc) || + !mpc->funcs->rmcm.is_config_supported( + (width == hubp_3dlut_fl_width_17 || + width == hubp_3dlut_fl_width_transformed) ? 17 : 33)) return false; + // setting native or transformed mode, + dc_get_lut_mode(mcm_luts->lut3d_data.gpu_mem_params.layout, &mode, &addr_mode); + //seems to be only for the MCM - mpc_fl_config.enabled = cm->flags.bits.lut3d_enable; - mpc_fl_config.size = cm->lut3d_dma.size; + dc_get_lut_format(mcm_luts->lut3d_data.gpu_mem_params.format_params.format, &format); + + dc_get_lut_xbar( + mcm_luts->lut3d_data.gpu_mem_params.component_order, + &crossbar_bit_slice_cr_r, + &crossbar_bit_slice_y_g, + &crossbar_bit_slice_cb_b); + + fl_config.mode = mode; + fl_config.enabled = lut3d_xable != MCM_LUT_DISABLE; + fl_config.address = mcm_luts->lut3d_data.gpu_mem_params.addr; + fl_config.format = format; + fl_config.crossbar_bit_slice_y_g = crossbar_bit_slice_y_g; + fl_config.crossbar_bit_slice_cb_b = crossbar_bit_slice_cb_b; + fl_config.crossbar_bit_slice_cr_r = crossbar_bit_slice_cr_r; + fl_config.width = width; + fl_config.protection_bits = rmcm_3dlut->protection_bits; + fl_config.addr_mode = addr_mode; + fl_config.layout = mcm_luts->lut3d_data.gpu_mem_params.layout; + fl_config.bias = mcm_luts->lut3d_data.gpu_mem_params.format_params.float_params.bias; + fl_config.scale = mcm_luts->lut3d_data.gpu_mem_params.format_params.float_params.scale; + + mpc_fl_config.enabled = fl_config.enabled; + mpc_fl_config.width = width; mpc_fl_config.select_lut_bank_a = lut_bank_a; - mpc_fl_config.bit_depth = 0; + mpc_fl_config.bit_depth = mcm_luts->lut3d_data.gpu_mem_params.bit_depth; mpc_fl_config.hubp_index = hubp->inst; - mpc_fl_config.bias = cm->lut3d_dma.bias; - mpc_fl_config.scale = cm->lut3d_dma.scale; + mpc_fl_config.bias = mcm_luts->lut3d_data.gpu_mem_params.format_params.float_params.bias; + mpc_fl_config.scale = mcm_luts->lut3d_data.gpu_mem_params.format_params.float_params.scale; //1. power down the block mpc->funcs->rmcm.power_on_shaper_3dlut(mpc, mpcc_id, false); @@ -476,44 +679,268 @@ bool dcn42_program_rmcm_luts( //2. program RMCM - 3dlut reg programming mpc->funcs->rmcm.fl_3dlut_configure(mpc, &mpc_fl_config, mpcc_id); - /* HUBP */ - if (hubp->funcs->hubp_program_3dlut_fl_config) - hubp->funcs->hubp_program_3dlut_fl_config(hubp, &cm->lut3d_dma); - - if (hubp->funcs->hubp_program_3dlut_fl_addr) - hubp->funcs->hubp_program_3dlut_fl_addr(hubp, &cm->lut3d_dma.addr); + hubp->funcs->hubp_program_3dlut_fl_config(hubp, &fl_config); //3. power on the block mpc->funcs->rmcm.power_on_shaper_3dlut(mpc, mpcc_id, true); + + break; + default: + return false; } return true; } -bool dcn42_set_mcm_luts(struct pipe_ctx *pipe_ctx, - const struct dc_plane_state *plane_state) +void dcn42_populate_mcm_luts(struct dc *dc, + struct pipe_ctx *pipe_ctx, + struct dc_cm2_func_luts mcm_luts, + bool lut_bank_a) { - struct dc *dc = pipe_ctx->plane_res.hubp->ctx->dc; + struct dpp *dpp_base = pipe_ctx->plane_res.dpp; struct hubp *hubp = pipe_ctx->plane_res.hubp; - const struct dc_plane_cm *cm = &plane_state->cm; - struct mpc *mpc = dc->res_pool->mpc; int mpcc_id = hubp->inst; - bool result; - - /* MCM */ - result = dcn401_set_mcm_luts(pipe_ctx, plane_state); - - /* RMCM */ - if (cm->flags.bits.rmcm_enable && cm->flags.bits.lut3d_dma_enable) { - /* TODO - move RMCM to its own block */ + struct mpc *mpc = dc->res_pool->mpc; + union mcm_lut_params m_lut_params; + enum dc_cm2_transfer_func_source lut3d_src = mcm_luts.lut3d_data.lut3d_src; + enum hubp_3dlut_fl_format format = 0; + enum hubp_3dlut_fl_mode mode; + enum hubp_3dlut_fl_width width = 0; + enum hubp_3dlut_fl_addressing_mode addr_mode; + enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_y_g = 0; + enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cb_b = 0; + enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cr_r = 0; + enum MCM_LUT_XABLE shaper_xable = MCM_LUT_DISABLE; + enum MCM_LUT_XABLE lut3d_xable = MCM_LUT_DISABLE; + enum MCM_LUT_XABLE lut1d_xable = MCM_LUT_DISABLE; + bool rval; + + dcn42_get_mcm_lut_xable_from_pipe_ctx(dc, pipe_ctx, &shaper_xable, &lut3d_xable, &lut1d_xable); + + //MCM - setting its location (Before/After) blender + //set to post blend (true) + dcn42_set_mcm_location_post_blend( + dc, + pipe_ctx, + mcm_luts.lut3d_data.mpc_mcm_post_blend); + + //RMCM - 3dLUT+Shaper + if (mcm_luts.lut3d_data.rmcm_3dlut_enable && + is_rmcm_3dlut_fl_supported(dc, mcm_luts.lut3d_data.gpu_mem_params.size)) { dcn42_program_rmcm_luts( hubp, pipe_ctx, - cm, + lut3d_src, + &mcm_luts, mpc, + lut_bank_a, mpcc_id); } + /* 1D LUT */ + if (mcm_luts.lut1d_func) { + memset(&m_lut_params, 0, sizeof(m_lut_params)); + if (mcm_luts.lut1d_func->type == TF_TYPE_HWPWL) + m_lut_params.pwl = &mcm_luts.lut1d_func->pwl; + else if (mcm_luts.lut1d_func->type == TF_TYPE_DISTRIBUTED_POINTS) { + rval = cm3_helper_translate_curve_to_hw_format(mpc->ctx, + mcm_luts.lut1d_func, + &dpp_base->regamma_params, false); + m_lut_params.pwl = rval ? &dpp_base->regamma_params : NULL; + } + if (m_lut_params.pwl) { + if (mpc->funcs->populate_lut) + mpc->funcs->populate_lut(mpc, MCM_LUT_1DLUT, m_lut_params, lut_bank_a, mpcc_id); + } + if (mpc->funcs->program_lut_mode) + mpc->funcs->program_lut_mode(mpc, MCM_LUT_1DLUT, lut1d_xable && m_lut_params.pwl, lut_bank_a, mpcc_id); + } + + /* Shaper */ + if (mcm_luts.shaper && mcm_luts.lut3d_data.mpc_3dlut_enable) { + memset(&m_lut_params, 0, sizeof(m_lut_params)); + if (mcm_luts.shaper->type == TF_TYPE_HWPWL) + m_lut_params.pwl = &mcm_luts.shaper->pwl; + else if (mcm_luts.shaper->type == TF_TYPE_DISTRIBUTED_POINTS) { + ASSERT(false); + rval = cm3_helper_translate_curve_to_hw_format(mpc->ctx, + mcm_luts.shaper, + &dpp_base->regamma_params, true); + m_lut_params.pwl = rval ? &dpp_base->regamma_params : NULL; + } + if (m_lut_params.pwl) { + if (mpc->funcs->mcm.populate_lut) + mpc->funcs->mcm.populate_lut(mpc, m_lut_params, lut_bank_a, mpcc_id); + if (mpc->funcs->program_lut_mode) + mpc->funcs->program_lut_mode(mpc, MCM_LUT_SHAPER, MCM_LUT_ENABLE, lut_bank_a, mpcc_id); + } + } + + /* 3DLUT */ + switch (lut3d_src) { + case DC_CM2_TRANSFER_FUNC_SOURCE_SYSMEM: + memset(&m_lut_params, 0, sizeof(m_lut_params)); + if (hubp->funcs->hubp_enable_3dlut_fl) + hubp->funcs->hubp_enable_3dlut_fl(hubp, false); + + if (mcm_luts.lut3d_data.lut3d_func && mcm_luts.lut3d_data.lut3d_func->state.bits.initialized) { + m_lut_params.lut3d = &mcm_luts.lut3d_data.lut3d_func->lut_3d; + if (mpc->funcs->populate_lut) + mpc->funcs->populate_lut(mpc, MCM_LUT_3DLUT, m_lut_params, lut_bank_a, mpcc_id); + if (mpc->funcs->program_lut_mode) + mpc->funcs->program_lut_mode(mpc, MCM_LUT_3DLUT, lut3d_xable, lut_bank_a, + mpcc_id); + } + break; + case DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM: + switch (mcm_luts.lut3d_data.gpu_mem_params.size) { + case DC_CM2_GPU_MEM_SIZE_333333: + width = hubp_3dlut_fl_width_33; + break; + case DC_CM2_GPU_MEM_SIZE_171717: + width = hubp_3dlut_fl_width_17; + break; + case DC_CM2_GPU_MEM_SIZE_TRANSFORMED: + width = hubp_3dlut_fl_width_transformed; + break; + default: + //TODO: Handle default case + break; + } + + //check for support + if (mpc->funcs->mcm.is_config_supported && + !mpc->funcs->mcm.is_config_supported(width)) + break; + + if (mpc->funcs->program_lut_read_write_control) + mpc->funcs->program_lut_read_write_control(mpc, MCM_LUT_3DLUT, lut_bank_a, mpcc_id); + if (mpc->funcs->program_lut_mode) + mpc->funcs->program_lut_mode(mpc, MCM_LUT_3DLUT, lut3d_xable, lut_bank_a, mpcc_id); + + if (hubp->funcs->hubp_program_3dlut_fl_addr) + hubp->funcs->hubp_program_3dlut_fl_addr(hubp, mcm_luts.lut3d_data.gpu_mem_params.addr); + + if (mpc->funcs->mcm.program_bit_depth) + mpc->funcs->mcm.program_bit_depth(mpc, mcm_luts.lut3d_data.gpu_mem_params.bit_depth, mpcc_id); + + dc_get_lut_mode(mcm_luts.lut3d_data.gpu_mem_params.layout, &mode, &addr_mode); + if (hubp->funcs->hubp_program_3dlut_fl_mode) + hubp->funcs->hubp_program_3dlut_fl_mode(hubp, mode); + + if (hubp->funcs->hubp_program_3dlut_fl_addressing_mode) + hubp->funcs->hubp_program_3dlut_fl_addressing_mode(hubp, addr_mode); + + switch (mcm_luts.lut3d_data.gpu_mem_params.format_params.format) { + case DC_CM2_GPU_MEM_FORMAT_16161616_UNORM_12MSB: + format = hubp_3dlut_fl_format_unorm_12msb_bitslice; + break; + case DC_CM2_GPU_MEM_FORMAT_16161616_UNORM_12LSB: + format = hubp_3dlut_fl_format_unorm_12lsb_bitslice; + break; + case DC_CM2_GPU_MEM_FORMAT_16161616_FLOAT_FP1_5_10: + format = hubp_3dlut_fl_format_float_fp1_5_10; + break; + } + if (hubp->funcs->hubp_program_3dlut_fl_format) + hubp->funcs->hubp_program_3dlut_fl_format(hubp, format); + if (hubp->funcs->hubp_update_3dlut_fl_bias_scale && + mpc->funcs->mcm.program_bias_scale) { + mpc->funcs->mcm.program_bias_scale(mpc, + mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.bias, + mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.scale, + mpcc_id); + hubp->funcs->hubp_update_3dlut_fl_bias_scale(hubp, + mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.bias, + mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.scale); + } + + //navi 4x has a bug and r and blue are swapped and need to be worked around here in + //TODO: need to make a method for get_xbar per asic OR do the workaround in program_crossbar for 4x + dc_get_lut_xbar( + mcm_luts.lut3d_data.gpu_mem_params.component_order, + &crossbar_bit_slice_cr_r, + &crossbar_bit_slice_y_g, + &crossbar_bit_slice_cb_b); + + if (hubp->funcs->hubp_program_3dlut_fl_crossbar) + hubp->funcs->hubp_program_3dlut_fl_crossbar(hubp, + crossbar_bit_slice_cr_r, + crossbar_bit_slice_y_g, + crossbar_bit_slice_cb_b); + + if (mpc->funcs->mcm.program_lut_read_write_control) + mpc->funcs->mcm.program_lut_read_write_control(mpc, MCM_LUT_3DLUT, lut_bank_a, true, mpcc_id); + + if (mpc->funcs->mcm.program_3dlut_size) + mpc->funcs->mcm.program_3dlut_size(mpc, width, mpcc_id); + + if (mpc->funcs->update_3dlut_fast_load_select) + mpc->funcs->update_3dlut_fast_load_select(mpc, mpcc_id, hubp->inst); + + if (hubp->funcs->hubp_enable_3dlut_fl) + hubp->funcs->hubp_enable_3dlut_fl(hubp, true); + else { + if (mpc->funcs->program_lut_mode) { + mpc->funcs->program_lut_mode(mpc, MCM_LUT_SHAPER, MCM_LUT_DISABLE, lut_bank_a, mpcc_id); + mpc->funcs->program_lut_mode(mpc, MCM_LUT_3DLUT, MCM_LUT_DISABLE, lut_bank_a, mpcc_id); + mpc->funcs->program_lut_mode(mpc, MCM_LUT_1DLUT, MCM_LUT_DISABLE, lut_bank_a, mpcc_id); + } + } + break; + } +} + +bool dcn42_set_mcm_luts(struct pipe_ctx *pipe_ctx, + const struct dc_plane_state *plane_state) +{ + struct dpp *dpp_base = pipe_ctx->plane_res.dpp; + int mpcc_id = pipe_ctx->plane_res.hubp->inst; + struct dc *dc = pipe_ctx->stream_res.opp->ctx->dc; + struct mpc *mpc = dc->res_pool->mpc; + bool result; + const struct pwl_params *lut_params = NULL; + bool rval; + + if (plane_state->mcm_luts.lut3d_data.lut3d_src == DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM) { + dcn42_populate_mcm_luts(dc, pipe_ctx, plane_state->mcm_luts, plane_state->lut_bank_a); + return true; + } + + mpc->funcs->set_movable_cm_location(mpc, MPCC_MOVABLE_CM_LOCATION_BEFORE, mpcc_id); + pipe_ctx->plane_state->mcm_location = MPCC_MOVABLE_CM_LOCATION_BEFORE; + // 1D LUT + if (plane_state->blend_tf.type == TF_TYPE_HWPWL) + lut_params = &plane_state->blend_tf.pwl; + else if (plane_state->blend_tf.type == TF_TYPE_DISTRIBUTED_POINTS) { + rval = cm3_helper_translate_curve_to_hw_format(plane_state->ctx, + &plane_state->blend_tf, + &dpp_base->regamma_params, false); + lut_params = rval ? &dpp_base->regamma_params : NULL; + } + result = mpc->funcs->program_1dlut(mpc, lut_params, mpcc_id); + lut_params = NULL; + + // Shaper + if (plane_state->in_shaper_func.type == TF_TYPE_HWPWL) + lut_params = &plane_state->in_shaper_func.pwl; + else if (plane_state->in_shaper_func.type == TF_TYPE_DISTRIBUTED_POINTS) { + // TODO: dpp_base replace + rval = cm3_helper_translate_curve_to_hw_format(plane_state->ctx, + &plane_state->in_shaper_func, + &dpp_base->shaper_params, true); + lut_params = rval ? &dpp_base->shaper_params : NULL; + } + result &= mpc->funcs->program_shaper(mpc, lut_params, mpcc_id); + + // 3D + if (mpc->funcs->program_3dlut) { + if (plane_state->lut3d_func.state.bits.initialized == 1) + result &= mpc->funcs->program_3dlut(mpc, &plane_state->lut3d_func.lut_3d, mpcc_id); + else + result &= mpc->funcs->program_3dlut(mpc, NULL, mpcc_id); + } + return result; } void dcn42_hardware_release(struct dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.h index c4cfeed45b19..0539ee0ffaee 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.h @@ -18,11 +18,18 @@ void dcn42_program_cm_hist( bool dcn42_set_mcm_luts(struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state); +void dcn42_populate_mcm_luts(struct dc *dc, + struct pipe_ctx *pipe_ctx, + struct dc_cm2_func_luts mcm_luts, + bool lut_bank_a); + bool dcn42_program_rmcm_luts( struct hubp *hubp, struct pipe_ctx *pipe_ctx, - const struct dc_plane_cm *cm, + enum dc_cm2_transfer_func_source lut3d_src, + struct dc_cm2_func_luts *mcm_luts, struct mpc *mpc, + bool lut_bank_a, int mpcc_id); void dcn42_hardware_release(struct dc *dc); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h index 2a5a81d15950..fc005aadfd55 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h @@ -89,7 +89,7 @@ enum hubp_3dlut_fl_addressing_mode { enum hubp_3dlut_fl_width { hubp_3dlut_fl_width_17 = 17, hubp_3dlut_fl_width_33 = 33, - hubp_3dlut_fl_width_17_transformed = 4916, //mpc default + hubp_3dlut_fl_width_transformed = 4916, //mpc default }; enum hubp_3dlut_fl_crossbar_bit_slice { @@ -99,6 +99,22 @@ enum hubp_3dlut_fl_crossbar_bit_slice { hubp_3dlut_fl_crossbar_bit_slice_48_63 = 3 }; +struct hubp_fl_3dlut_config { + bool enabled; + enum hubp_3dlut_fl_width width; + enum hubp_3dlut_fl_mode mode; + enum hubp_3dlut_fl_format format; + uint16_t bias; + uint16_t scale; + struct dc_plane_address address; + enum hubp_3dlut_fl_addressing_mode addr_mode; + enum dc_cm2_gpu_mem_layout layout; + uint8_t protection_bits; + enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_y_g; + enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cb_b; + enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cr_r; +}; + struct hubp { const struct hubp_funcs *funcs; struct dc_context *ctx; @@ -273,15 +289,24 @@ struct hubp_funcs { void (*hubp_wait_pipe_read_start)(struct hubp *hubp); void (*hubp_program_mcache_id_and_split_coordinate)(struct hubp *hubp, struct dml2_hubp_pipe_mcache_regs *mcache_regs); + void (*hubp_update_3dlut_fl_bias_scale)(struct hubp *hubp, uint16_t bias, uint16_t scale); + void (*hubp_program_3dlut_fl_mode)(struct hubp *hubp, + enum hubp_3dlut_fl_mode mode); + void (*hubp_program_3dlut_fl_format)(struct hubp *hubp, + enum hubp_3dlut_fl_format format); void (*hubp_program_3dlut_fl_addr)(struct hubp *hubp, - const struct dc_plane_address *address); - void (*hubp_program_3dlut_fl_config)(struct hubp *hubp, - const struct dc_3dlut_dma *config); + const struct dc_plane_address address); void (*hubp_program_3dlut_fl_dlg_param)(struct hubp *hubp, int refcyc_per_3dlut_group); void (*hubp_enable_3dlut_fl)(struct hubp *hubp, bool enable); + void (*hubp_program_3dlut_fl_addressing_mode)(struct hubp *hubp, enum hubp_3dlut_fl_addressing_mode addr_mode); + void (*hubp_program_3dlut_fl_width)(struct hubp *hubp, enum hubp_3dlut_fl_width width); + void (*hubp_program_3dlut_fl_tmz_protected)(struct hubp *hubp, uint8_t protection_bits); void (*hubp_program_3dlut_fl_crossbar)(struct hubp *hubp, - enum dc_cm_lut_pixel_format format); + enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_y_g, + enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_cb_b, + enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_cr_r); int (*hubp_get_3dlut_fl_done)(struct hubp *hubp); + void (*hubp_program_3dlut_fl_config)(struct hubp *hubp, struct hubp_fl_3dlut_config *cfg); void (*hubp_clear_tiling)(struct hubp *hubp); uint32_t (*hubp_get_current_read_line)(struct hubp *hubp); uint32_t (*hubp_get_det_config_error)(struct hubp *hubp); 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 f5617674bea8..54eb2eba68bf 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h @@ -54,7 +54,6 @@ #include "dc_hw_types.h" #include "hw_shared.h" #include "transform.h" -#include "dc_types.h" #define MAX_MPCC 6 #define MAX_OPP 6 @@ -102,6 +101,13 @@ enum mpcc_movable_cm_location { MPCC_MOVABLE_CM_LOCATION_AFTER, }; +enum MCM_LUT_XABLE { + MCM_LUT_DISABLE, + MCM_LUT_DISABLED = MCM_LUT_DISABLE, + MCM_LUT_ENABLE, + MCM_LUT_ENABLED = MCM_LUT_ENABLE, +}; + enum MCM_LUT_ID { MCM_LUT_3DLUT, MCM_LUT_1DLUT, @@ -110,7 +116,7 @@ enum MCM_LUT_ID { struct mpc_fl_3dlut_config { bool enabled; - enum dc_cm_lut_size size; + uint16_t width; bool select_lut_bank_a; uint16_t bit_depth; int hubp_index; @@ -1069,11 +1075,8 @@ struct mpc_funcs { * * void */ - void (*populate_lut)(struct mpc *mpc, - const enum MCM_LUT_ID id, - const union mcm_lut_params *params, - const bool lut_bank_a, - const int mpcc_id); + void (*populate_lut)(struct mpc *mpc, const enum MCM_LUT_ID id, const union mcm_lut_params params, + bool lut_bank_a, int mpcc_id); /** * @program_lut_read_write_control: @@ -1084,18 +1087,13 @@ struct mpc_funcs { * - [in/out] mpc - MPC context. * - [in] id * - [in] lut_bank_a - * - [in] bit_depth * - [in] mpcc_id * * Return: * * void */ - void (*program_lut_read_write_control)(struct mpc *mpc, - const enum MCM_LUT_ID id, - const bool lut_bank_a, - const unsigned int bit_depth, - const int mpcc_id); + void (*program_lut_read_write_control)(struct mpc *mpc, const enum MCM_LUT_ID id, bool lut_bank_a, int mpcc_id); /** * @program_lut_mode: @@ -1105,44 +1103,33 @@ struct mpc_funcs { * Parameters: * - [in/out] mpc - MPC context. * - [in] id - * - [in] enable + * - [in] xable * - [in] lut_bank_a - * - [in] size * - [in] mpcc_id * * Return: * * void */ - void (*program_lut_mode)(struct mpc *mpc, - const enum MCM_LUT_ID id, - const bool enable, - const bool lut_bank_a, - const enum dc_cm_lut_size size, - const int mpcc_id); - + void (*program_lut_mode)(struct mpc *mpc, const enum MCM_LUT_ID id, const enum MCM_LUT_XABLE xable, + bool lut_bank_a, int mpcc_id); /** - * @get_lut_mode: - * - * Obtains enablement and ram bank status. - * - * Parameters: - * - [in/out] mpc - MPC context. - * - [in] id - * - [in] mpcc_id - * - [out] enable - * - [out] lut_bank_a - * - * Return: - * - * void - */ - void (*get_lut_mode)(struct mpc *mpc, - const enum MCM_LUT_ID id, - const int mpcc_id, - bool *enable, - bool *lut_bank_a); + * @mcm: + * + * MPC MCM new HW sequential programming functions + */ + struct { + void (*program_3dlut_size)(struct mpc *mpc, uint32_t width, int mpcc_id); + void (*program_bias_scale)(struct mpc *mpc, uint16_t bias, uint16_t scale, int mpcc_id); + void (*program_bit_depth)(struct mpc *mpc, uint16_t bit_depth, int mpcc_id); + bool (*is_config_supported)(uint32_t width); + void (*program_lut_read_write_control)(struct mpc *mpc, const enum MCM_LUT_ID id, + bool lut_bank_a, bool enabled, int mpcc_id); + + void (*populate_lut)(struct mpc *mpc, const union mcm_lut_params params, + bool lut_bank_a, int mpcc_id); + } mcm; /** * @rmcm: @@ -1155,11 +1142,9 @@ struct mpc_funcs { void (*update_3dlut_fast_load_select)(struct mpc *mpc, int mpcc_id, int hubp_idx); void (*program_lut_read_write_control)(struct mpc *mpc, const enum MCM_LUT_ID id, bool lut_bank_a, bool enabled, int mpcc_id); - void (*program_lut_mode)(struct mpc *mpc, - bool enable, - bool lut_bank_a, - int mpcc_id); - void (*program_3dlut_size)(struct mpc *mpc, const enum dc_cm_lut_size size, int mpcc_id); + void (*program_lut_mode)(struct mpc *mpc, const enum MCM_LUT_XABLE xable, + bool lut_bank_a, int mpcc_id); + void (*program_3dlut_size)(struct mpc *mpc, uint32_t width, int mpcc_id); void (*program_bias_scale)(struct mpc *mpc, uint16_t bias, uint16_t scale, int mpcc_id); void (*program_bit_depth)(struct mpc *mpc, uint16_t bit_depth, int mpcc_id); bool (*is_config_supported)(uint32_t width); diff --git a/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.c b/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.c index e0617db2d0c1..ce1ee2062e41 100644 --- a/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.c @@ -73,15 +73,56 @@ void mpc401_set_movable_cm_location(struct mpc *mpc, enum mpcc_movable_cm_locati } } -void mpc401_populate_lut(struct mpc *mpc, - const enum MCM_LUT_ID id, - const union mcm_lut_params *params, - const bool lut_bank_a, - const int mpcc_id) +static enum dc_lut_mode get3dlut_config( + struct mpc *mpc, + bool *is_17x17x17, + bool *is_12bits_color_channel, + int mpcc_id) +{ + uint32_t i_mode, i_enable_10bits, lut_size; + enum dc_lut_mode mode; + struct dcn401_mpc *mpc401 = TO_DCN401_MPC(mpc); + + REG_GET(MPCC_MCM_3DLUT_MODE[mpcc_id], + MPCC_MCM_3DLUT_MODE_CURRENT, &i_mode); + + REG_GET(MPCC_MCM_3DLUT_READ_WRITE_CONTROL[mpcc_id], + MPCC_MCM_3DLUT_30BIT_EN, &i_enable_10bits); + + switch (i_mode) { + case 0: + mode = LUT_BYPASS; + break; + case 1: + mode = LUT_RAM_A; + break; + case 2: + mode = LUT_RAM_B; + break; + default: + mode = LUT_BYPASS; + break; + } + if (i_enable_10bits > 0) + *is_12bits_color_channel = false; + else + *is_12bits_color_channel = true; + + REG_GET(MPCC_MCM_3DLUT_MODE[mpcc_id], MPCC_MCM_3DLUT_SIZE, &lut_size); + + if (lut_size == 0) + *is_17x17x17 = true; + else + *is_17x17x17 = false; + + return mode; +} + +void mpc401_populate_lut(struct mpc *mpc, const enum MCM_LUT_ID id, const union mcm_lut_params params, bool lut_bank_a, int mpcc_id) { const enum dc_lut_mode next_mode = lut_bank_a ? LUT_RAM_A : LUT_RAM_B; - const struct pwl_params *lut1d = params->pwl; - const struct pwl_params *lut_shaper = params->pwl; + const struct pwl_params *lut1d = params.pwl; + const struct pwl_params *lut_shaper = params.pwl; bool is_17x17x17; bool is_12bits_color_channel; const struct dc_rgb *lut0; @@ -90,7 +131,7 @@ void mpc401_populate_lut(struct mpc *mpc, const struct dc_rgb *lut3; int lut_size0; int lut_size; - const struct tetrahedral_params *lut3d = params->lut3d; + const struct tetrahedral_params *lut3d = params.lut3d; switch (id) { case MCM_LUT_1DLUT: @@ -133,6 +174,8 @@ void mpc401_populate_lut(struct mpc *mpc, mpc32_power_on_shaper_3dlut(mpc, mpcc_id, true); + get3dlut_config(mpc, &is_17x17x17, &is_12bits_color_channel, mpcc_id); + is_17x17x17 = !lut3d->use_tetrahedral_9; is_12bits_color_channel = lut3d->use_12bits; if (is_17x17x17) { @@ -155,6 +198,8 @@ void mpc401_populate_lut(struct mpc *mpc, sizeof(lut3d->tetrahedral_9.lut1[0]); } + mpc32_select_3dlut_ram(mpc, next_mode, + is_12bits_color_channel, mpcc_id); mpc32_select_3dlut_ram_mask(mpc, 0x1, mpcc_id); if (is_12bits_color_channel) mpc32_set3dlut_ram12(mpc, lut0, lut_size0, mpcc_id); @@ -187,69 +232,46 @@ void mpc401_populate_lut(struct mpc *mpc, } -static uint32_t mpc401_cm_lut_size_to_3dlut_size(const enum dc_cm_lut_size cm_size) -{ - uint32_t size = 0; - - switch (cm_size) { - case CM_LUT_SIZE_999: - size = 1; - break; - case CM_LUT_SIZE_171717: - size = 0; - break; - default: - /* invalid LUT size */ - ASSERT(false); - size = 0; - break; - } - - return size; -} - void mpc401_program_lut_mode( struct mpc *mpc, const enum MCM_LUT_ID id, - const bool enable, - const bool lut_bank_a, - const enum dc_cm_lut_size size, - const int mpcc_id) + const enum MCM_LUT_XABLE xable, + bool lut_bank_a, + int mpcc_id) { - uint32_t lut_size; struct dcn401_mpc *mpc401 = TO_DCN401_MPC(mpc); switch (id) { case MCM_LUT_3DLUT: - if (enable) { - lut_size = mpc401_cm_lut_size_to_3dlut_size(size); - REG_UPDATE_2(MPCC_MCM_3DLUT_MODE[mpcc_id], - MPCC_MCM_3DLUT_MODE, lut_bank_a ? 1 : 2, - MPCC_MCM_3DLUT_SIZE, lut_size); - } else { - if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) - mpc32_power_on_shaper_3dlut(mpc, mpcc_id, false); + switch (xable) { + case MCM_LUT_DISABLE: REG_UPDATE(MPCC_MCM_3DLUT_MODE[mpcc_id], MPCC_MCM_3DLUT_MODE, 0); + break; + case MCM_LUT_ENABLE: + REG_UPDATE(MPCC_MCM_3DLUT_MODE[mpcc_id], MPCC_MCM_3DLUT_MODE, lut_bank_a ? 1 : 2); + break; } break; case MCM_LUT_SHAPER: - if (enable) { - REG_UPDATE(MPCC_MCM_SHAPER_CONTROL[mpcc_id], MPCC_MCM_SHAPER_LUT_MODE, lut_bank_a ? 1 : 2); - } else { - if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) - mpc32_power_on_shaper_3dlut(mpc, mpcc_id, false); + switch (xable) { + case MCM_LUT_DISABLE: REG_UPDATE(MPCC_MCM_SHAPER_CONTROL[mpcc_id], MPCC_MCM_SHAPER_LUT_MODE, 0); + break; + case MCM_LUT_ENABLE: + REG_UPDATE(MPCC_MCM_SHAPER_CONTROL[mpcc_id], MPCC_MCM_SHAPER_LUT_MODE, lut_bank_a ? 1 : 2); + break; } break; case MCM_LUT_1DLUT: - if (enable) { - REG_UPDATE(MPCC_MCM_1DLUT_CONTROL[mpcc_id], - MPCC_MCM_1DLUT_MODE, 2); - } else { - if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) - mpc32_power_on_blnd_lut(mpc, mpcc_id, false); + switch (xable) { + case MCM_LUT_DISABLE: REG_UPDATE(MPCC_MCM_1DLUT_CONTROL[mpcc_id], MPCC_MCM_1DLUT_MODE, 0); + break; + case MCM_LUT_ENABLE: + REG_UPDATE(MPCC_MCM_1DLUT_CONTROL[mpcc_id], + MPCC_MCM_1DLUT_MODE, 2); + break; } REG_UPDATE(MPCC_MCM_1DLUT_CONTROL[mpcc_id], MPCC_MCM_1DLUT_SELECT, lut_bank_a ? 0 : 1); @@ -257,20 +279,14 @@ void mpc401_program_lut_mode( } } -void mpc401_program_lut_read_write_control(struct mpc *mpc, - const enum MCM_LUT_ID id, - const bool lut_bank_a, - const unsigned int bit_depth, - const int mpcc_id) +void mpc401_program_lut_read_write_control(struct mpc *mpc, const enum MCM_LUT_ID id, bool lut_bank_a, int mpcc_id) { struct dcn401_mpc *mpc401 = TO_DCN401_MPC(mpc); switch (id) { case MCM_LUT_3DLUT: mpc32_select_3dlut_ram_mask(mpc, 0xf, mpcc_id); - REG_UPDATE_2(MPCC_MCM_3DLUT_READ_WRITE_CONTROL[mpcc_id], - MPCC_MCM_3DLUT_30BIT_EN, (bit_depth == 10) ? 1 : 0, - MPCC_MCM_3DLUT_RAM_SEL, lut_bank_a ? 0 : 1); + REG_UPDATE(MPCC_MCM_3DLUT_READ_WRITE_CONTROL[mpcc_id], MPCC_MCM_3DLUT_RAM_SEL, lut_bank_a ? 0 : 1); break; case MCM_LUT_SHAPER: mpc32_configure_shaper_lut(mpc, lut_bank_a, mpcc_id); @@ -562,44 +578,6 @@ void mpc401_get_gamut_remap(struct mpc *mpc, arr_reg_val, ARRAY_SIZE(arr_reg_val)); } -void mpc401_get_lut_mode(struct mpc *mpc, - const enum MCM_LUT_ID id, - const int mpcc_id, - bool *enable, - bool *lut_bank_a) -{ - struct dcn401_mpc *mpc401 = TO_DCN401_MPC(mpc); - - uint32_t lut_mode = 0; - uint32_t lut_select = 0; - - *enable = false; - *lut_bank_a = true; - - switch (id) { - case MCM_LUT_SHAPER: - REG_GET(MPCC_MCM_SHAPER_CONTROL[mpcc_id], - MPCC_MCM_SHAPER_MODE_CURRENT, &lut_mode); - *enable = lut_mode != 0; - *lut_bank_a = lut_mode != 2; - break; - case MCM_LUT_1DLUT: - REG_GET_2(MPCC_MCM_1DLUT_CONTROL[mpcc_id], - MPCC_MCM_1DLUT_MODE_CURRENT, &lut_mode, - MPCC_MCM_1DLUT_SELECT_CURRENT, &lut_select); - *enable = lut_mode != 0; - *lut_bank_a = lut_mode == 0 || lut_select == 0; - break; - case MCM_LUT_3DLUT: - default: - REG_GET(MPCC_MCM_3DLUT_MODE[mpcc_id], - MPCC_MCM_3DLUT_MODE_CURRENT, &lut_mode); - *enable = lut_mode != 0; - *lut_bank_a = lut_mode != 2; - break; - } -} - static const struct mpc_funcs dcn401_mpc_funcs = { .read_mpcc_state = mpc1_read_mpcc_state, .insert_plane = mpc1_insert_plane, @@ -638,7 +616,6 @@ static const struct mpc_funcs dcn401_mpc_funcs = { .populate_lut = mpc401_populate_lut, .program_lut_read_write_control = mpc401_program_lut_read_write_control, .program_lut_mode = mpc401_program_lut_mode, - .get_lut_mode = mpc401_get_lut_mode, }; diff --git a/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.h b/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.h index c16560c84453..6d842d7b95c7 100644 --- a/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.h +++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.h @@ -206,32 +206,21 @@ void dcn401_mpc_construct(struct dcn401_mpc *mpc401, int num_rmu); void mpc401_set_movable_cm_location(struct mpc *mpc, enum mpcc_movable_cm_location location, int mpcc_id); -void mpc401_populate_lut(struct mpc *mpc, - const enum MCM_LUT_ID id, - const union mcm_lut_params *params, - bool lut_bank_a, - int mpcc_id); +void mpc401_populate_lut(struct mpc *mpc, const enum MCM_LUT_ID id, const union mcm_lut_params params, + bool lut_bank_a, int mpcc_id); void mpc401_program_lut_mode( struct mpc *mpc, const enum MCM_LUT_ID id, - const bool enable, - const bool lut_bank_a, - const enum dc_cm_lut_size size, - const int mpcc_id); - -void mpc401_get_lut_mode(struct mpc *mpc, - const enum MCM_LUT_ID id, - const int mpcc_id, - bool *enable, - bool *lut_bank_a); + const enum MCM_LUT_XABLE xable, + bool lut_bank_a, + int mpcc_id); void mpc401_program_lut_read_write_control( struct mpc *mpc, const enum MCM_LUT_ID id, - const bool lut_bank_a, - const unsigned int bit_depth, - const int mpcc_id); + bool lut_bank_a, + int mpcc_id); void mpc401_set_gamut_remap( struct mpc *mpc, diff --git a/drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.c b/drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.c index 507dbdbea600..38c0e8f96d40 100644 --- a/drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.c @@ -63,6 +63,154 @@ void mpc42_update_blending( mpcc->blnd_cfg = *blnd_cfg; } +/* Shaper functions */ +void mpc42_power_on_shaper_3dlut( + struct mpc *mpc, + uint32_t mpcc_id, + bool power_on) +{ + uint32_t power_status_shaper = 2; + uint32_t power_status_3dlut = 2; + struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc); + int max_retries = 10; + + REG_SET(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], 0, + MPCC_MCM_3DLUT_MEM_PWR_DIS, power_on == true ? 1:0); + REG_SET(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], 0, + MPCC_MCM_SHAPER_MEM_PWR_DIS, power_on == true ? 1:0); + /* wait for memory to fully power up */ + if (power_on && mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) { + REG_WAIT(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], MPCC_MCM_SHAPER_MEM_PWR_STATE, 0, 1, max_retries); + REG_WAIT(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], MPCC_MCM_3DLUT_MEM_PWR_STATE, 0, 1, max_retries); + } + + /*read status is not mandatory, it is just for debugging*/ + REG_GET(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], MPCC_MCM_SHAPER_MEM_PWR_STATE, &power_status_shaper); + REG_GET(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], MPCC_MCM_3DLUT_MEM_PWR_STATE, &power_status_3dlut); + + if (power_status_shaper != 0 && power_on == true) + BREAK_TO_DEBUGGER(); + + if (power_status_3dlut != 0 && power_on == true) + BREAK_TO_DEBUGGER(); +} + +void mpc42_configure_shaper_lut( + struct mpc *mpc, + bool is_ram_a, + uint32_t mpcc_id) +{ + struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc); + + REG_UPDATE(MPCC_MCM_SHAPER_SCALE_G_B[mpcc_id], + MPCC_MCM_SHAPER_SCALE_B, 0x7000); + REG_UPDATE(MPCC_MCM_SHAPER_SCALE_G_B[mpcc_id], + MPCC_MCM_SHAPER_SCALE_G, 0x7000); + REG_UPDATE(MPCC_MCM_SHAPER_SCALE_R[mpcc_id], + MPCC_MCM_SHAPER_SCALE_R, 0x7000); + REG_UPDATE(MPCC_MCM_SHAPER_LUT_WRITE_EN_MASK[mpcc_id], + MPCC_MCM_SHAPER_LUT_WRITE_EN_MASK, 7); + REG_UPDATE(MPCC_MCM_SHAPER_LUT_WRITE_EN_MASK[mpcc_id], + MPCC_MCM_SHAPER_LUT_WRITE_SEL, is_ram_a == true ? 0:1); + REG_SET(MPCC_MCM_SHAPER_LUT_INDEX[mpcc_id], 0, MPCC_MCM_SHAPER_LUT_INDEX, 0); +} + + +void mpc42_program_3dlut_size(struct mpc *mpc, uint32_t width, int mpcc_id) +{ + struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc); + uint32_t size = 0xff; + + REG_GET(MPCC_MCM_3DLUT_MODE[mpcc_id], MPCC_MCM_3DLUT_SIZE, &size); + + REG_UPDATE(MPCC_MCM_3DLUT_MODE[mpcc_id], MPCC_MCM_3DLUT_SIZE, + (width == 33) ? 2 : + (width == 17) ? 0 : 2); + + REG_GET(MPCC_MCM_3DLUT_MODE[mpcc_id], MPCC_MCM_3DLUT_SIZE, &size); +} + +void mpc42_program_3dlut_fl_bias_scale(struct mpc *mpc, uint16_t bias, uint16_t scale, int mpcc_id) +{ + struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc); + + REG_UPDATE_2(MPCC_MCM_3DLUT_OUT_OFFSET_R[mpcc_id], + MPCC_MCM_3DLUT_OUT_OFFSET_R, bias, + MPCC_MCM_3DLUT_OUT_SCALE_R, scale); + + REG_UPDATE_2(MPCC_MCM_3DLUT_OUT_OFFSET_G[mpcc_id], + MPCC_MCM_3DLUT_OUT_OFFSET_G, bias, + MPCC_MCM_3DLUT_OUT_SCALE_G, scale); + + REG_UPDATE_2(MPCC_MCM_3DLUT_OUT_OFFSET_B[mpcc_id], + MPCC_MCM_3DLUT_OUT_OFFSET_B, bias, + MPCC_MCM_3DLUT_OUT_SCALE_B, scale); +} + +void mpc42_program_bit_depth(struct mpc *mpc, uint16_t bit_depth, int mpcc_id) +{ + struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc); + + REG_UPDATE(MPCC_MCM_3DLUT_READ_WRITE_CONTROL[mpcc_id], MPCC_MCM_3DLUT_WRITE_EN_MASK, 0xF); + + //program bit_depth + REG_UPDATE(MPCC_MCM_3DLUT_READ_WRITE_CONTROL[mpcc_id], + MPCC_MCM_3DLUT_30BIT_EN, + (bit_depth == 10) ? 1 : 0); +} + +bool mpc42_is_config_supported(uint32_t width) +{ + if (width == 17) + return true; + + return false; +} + +void mpc42_populate_lut(struct mpc *mpc, const union mcm_lut_params params, + bool lut_bank_a, int mpcc_id) +{ + const enum dc_lut_mode next_mode = lut_bank_a ? LUT_RAM_A : LUT_RAM_B; + const struct pwl_params *lut_shaper = params.pwl; + + if (lut_shaper == NULL) + return; + if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) + mpc42_power_on_shaper_3dlut(mpc, mpcc_id, true); + + mpc42_configure_shaper_lut(mpc, next_mode == LUT_RAM_A, mpcc_id); + + if (next_mode == LUT_RAM_A) + mpc32_program_shaper_luta_settings(mpc, lut_shaper, mpcc_id); + else + mpc32_program_shaper_lutb_settings(mpc, lut_shaper, mpcc_id); + + mpc32_program_shaper_lut( + mpc, lut_shaper->rgb_resulted, lut_shaper->hw_points_num, mpcc_id); + + mpc42_power_on_shaper_3dlut(mpc, mpcc_id, false); +} + +void mpc42_program_lut_read_write_control(struct mpc *mpc, const enum MCM_LUT_ID id, + bool lut_bank_a, bool enabled, int mpcc_id) +{ + struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc); + + switch (id) { + case MCM_LUT_3DLUT: + REG_UPDATE(MPCC_MCM_3DLUT_MODE[mpcc_id], MPCC_MCM_3DLUT_MODE, + (!enabled) ? 0 : + (lut_bank_a) ? 1 : 2); + REG_UPDATE(MPCC_MCM_3DLUT_READ_WRITE_CONTROL[mpcc_id], MPCC_MCM_3DLUT_RAM_SEL, lut_bank_a ? 0 : 1); + break; + case MCM_LUT_SHAPER: + mpc32_configure_shaper_lut(mpc, lut_bank_a, mpcc_id); + break; + default: + break; + } +} + /* RMCM Shaper functions */ void mpc42_power_on_rmcm_shaper_3dlut( struct mpc *mpc, @@ -526,47 +674,32 @@ void mpc42_program_rmcm_lut_read_write_control(struct mpc *mpc, const enum MCM_L } } -void mpc42_program_lut_mode(struct mpc *mpc, - bool enable, - bool lut_bank_a, - int mpcc_id) +void mpc42_program_lut_mode(struct mpc *mpc, const enum MCM_LUT_XABLE xable, + bool lut_bank_a, int mpcc_id) { struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc); - if (enable) { - REG_UPDATE(MPC_RMCM_SHAPER_CONTROL[mpcc_id], MPC_RMCM_SHAPER_LUT_MODE, lut_bank_a ? 1 : 2); - } else { + switch (xable) { + case MCM_LUT_DISABLE: REG_UPDATE(MPC_RMCM_SHAPER_CONTROL[mpcc_id], MPC_RMCM_SHAPER_LUT_MODE, 0); - } -} - -static uint32_t mpc42_get_rmcm_3dlut_width( - const enum dc_cm_lut_size size) -{ - uint32_t width = 0; - - switch (size) { - case CM_LUT_SIZE_333333: - width = 2; break; - case CM_LUT_SIZE_171717: - default: - width = 0; + case MCM_LUT_ENABLE: + REG_UPDATE(MPC_RMCM_SHAPER_CONTROL[mpcc_id], MPC_RMCM_SHAPER_LUT_MODE, lut_bank_a ? 1 : 2); break; } - - return width; } -void mpc42_program_rmcm_3dlut_size(struct mpc *mpc, - const enum dc_cm_lut_size size, - int mpcc_id) +void mpc42_program_rmcm_3dlut_size(struct mpc *mpc, uint32_t width, int mpcc_id) { struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc); - uint32_t width = mpc42_get_rmcm_3dlut_width(size); + uint32_t size = 0xff; + + REG_GET(MPC_RMCM_3DLUT_MODE[mpcc_id], MPC_RMCM_3DLUT_SIZE, &size); - REG_UPDATE(MPC_RMCM_3DLUT_MODE[mpcc_id], - MPC_RMCM_3DLUT_SIZE, width); + REG_UPDATE(MPC_RMCM_3DLUT_MODE[mpcc_id], MPC_RMCM_3DLUT_SIZE, + (width == 33) ? 2 : 0); + + REG_GET(MPC_RMCM_3DLUT_MODE[mpcc_id], MPC_RMCM_3DLUT_SIZE, &size); } void mpc42_program_rmcm_3dlut_fast_load_bias_scale(struct mpc *mpc, uint16_t bias, uint16_t scale, int mpcc_id) @@ -598,6 +731,14 @@ void mpc42_program_rmcm_bit_depth(struct mpc *mpc, uint16_t bit_depth, int mpcc_ (bit_depth == 10) ? 1 : 0); } +bool mpc42_is_rmcm_config_supported(uint32_t width) +{ + if (width == 17 || width == 33) + return true; + + return false; +} + void mpc42_set_fl_config( struct mpc *mpc, struct mpc_fl_3dlut_config *cfg, @@ -605,7 +746,6 @@ void mpc42_set_fl_config( { struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc); - uint32_t width = mpc42_get_rmcm_3dlut_width(cfg->size); /* From: Jie Zhou @@ -646,7 +786,7 @@ void mpc42_set_fl_config( //width REG_UPDATE_2(MPC_RMCM_3DLUT_MODE[mpcc_id], - MPC_RMCM_3DLUT_SIZE, width, + MPC_RMCM_3DLUT_SIZE, (cfg->width == 33) ? 2 : 0, MPC_RMCM_3DLUT_MODE, (!cfg->enabled) ? 0 : (cfg->select_lut_bank_a) ? 1 : 2); //connect to hubp @@ -659,6 +799,182 @@ void mpc42_set_fl_config( REG_UPDATE(MPC_RMCM_CNTL[mpcc_id], MPC_RMCM_CNTL, cfg->enabled ? 0 : 0xF); } +//static void rmcm_program_gamut_remap( +// struct mpc *mpc, +// unsigned int mpcc_id, +// const uint16_t *regval, +// enum mpcc_gamut_remap_id gamut_remap_block_id, +// enum mpcc_gamut_remap_mode_select mode_select) +//{ +// struct color_matrices_reg gamut_regs; +// struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc); +// +// if (gamut_remap_block_id == MPCC_OGAM_GAMUT_REMAP || +// gamut_remap_block_id == MPCC_MCM_FIRST_GAMUT_REMAP || +// gamut_remap_block_id == MPCC_MCM_SECOND_GAMUT_REMAP) { +// mpc_program_gamut_remap(mpc, mpcc_id, regval, gamut_remap_block_id, mode_select); +// return; +// } +// if (gamut_remap_block_id == MPCC_OGAM_GAMUT_REMAP) { +// +// if (regval == NULL || mode_select == MPCC_GAMUT_REMAP_MODE_SELECT_0) { +// REG_SET(MPC_RMCM_GAMUT_REMAP_MODE[mpcc_id], 0, +// MPC_RMCM_GAMUT_REMAP_MODE, mode_select); +// return; +// } +// +// gamut_regs.shifts.csc_c11 = mpc42->mpc_shift->MPCC_GAMUT_REMAP_C11_A; +// gamut_regs.masks.csc_c11 = mpc42->mpc_mask->MPCC_GAMUT_REMAP_C11_A; +// gamut_regs.shifts.csc_c12 = mpc42->mpc_shift->MPCC_GAMUT_REMAP_C12_A; +// gamut_regs.masks.csc_c12 = mpc42->mpc_mask->MPCC_GAMUT_REMAP_C12_A; +// +// switch (mode_select) { +// case MPCC_GAMUT_REMAP_MODE_SELECT_1: +// gamut_regs.csc_c11_c12 = REG(MPC_RMCM_GAMUT_REMAP_C11_C12_A[mpcc_id]); +// gamut_regs.csc_c33_c34 = REG(MPC_RMCM_GAMUT_REMAP_C33_C34_A[mpcc_id]); +// break; +// case MPCC_GAMUT_REMAP_MODE_SELECT_2: +// gamut_regs.csc_c11_c12 = REG(MPC_RMCM_GAMUT_REMAP_C11_C12_B[mpcc_id]); +// gamut_regs.csc_c33_c34 = REG(MPC_RMCM_GAMUT_REMAP_C33_C34_B[mpcc_id]); +// break; +// default: +// break; +// } +// +// cm_helper_program_color_matrices( +// mpc->ctx, +// regval, +// &gamut_regs); +// +// //select coefficient set to use, set A (MODE_1) or set B (MODE_2) +// REG_SET(MPC_RMCM_GAMUT_REMAP_MODE[mpcc_id], 0, MPC_RMCM_GAMUT_REMAP_MODE, mode_select); +// } +//} + +//static bool is_mpc_legacy_gamut_id(enum mpcc_gamut_remap_id gamut_remap_block_id) +//{ +// if (gamut_remap_block_id == MPCC_OGAM_GAMUT_REMAP || +// gamut_remap_block_id == MPCC_MCM_FIRST_GAMUT_REMAP || +// gamut_remap_block_id == MPCC_MCM_SECOND_GAMUT_REMAP) { +// return true; +// } +// return false; +//} +//static void program_gamut_remap( +// struct mpc *mpc, +// unsigned int mpcc_id, +// const uint16_t *regval, +// enum mpcc_gamut_remap_id gamut_remap_block_id, +// enum mpcc_gamut_remap_mode_select mode_select) +//{ +// if (is_mpc_legacy_gamut_id(gamut_remap_block_id)) +// mpc_program_gamut_remap(mpc, mpcc_id, regval, gamut_remap_block_id, mode_select); +// else +// rmcm_program_gamut_remap(mpc, mpcc_id, regval, gamut_remap_block_id, mode_select); +//} + +//void mpc42_set_gamut_remap( +// struct mpc *mpc, +// int mpcc_id, +// const struct mpc_grph_gamut_adjustment *adjust) +//{ +// struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc); +// unsigned int i = 0; +// uint32_t mode_select = 0; +// +// if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW) { +// /* Bypass / Disable if type is bypass or hw */ +// program_gamut_remap(mpc, mpcc_id, NULL, +// adjust->mpcc_gamut_remap_block_id, MPCC_GAMUT_REMAP_MODE_SELECT_0); +// } else { +// struct fixed31_32 arr_matrix[12]; +// uint16_t arr_reg_val[12]; +// +// for (i = 0; i < 12; i++) +// arr_matrix[i] = adjust->temperature_matrix[i]; +// +// convert_float_matrix(arr_reg_val, arr_matrix, 12); +// +// if (is_mpc_legacy_gamut_id(adjust->mpcc_gamut_remap_block_id)) +// REG_GET(MPCC_GAMUT_REMAP_MODE[mpcc_id], +// MPCC_GAMUT_REMAP_MODE_CURRENT, &mode_select); +// else +// REG_GET(MPC_RMCM_GAMUT_REMAP_MODE[mpcc_id], +// MPC_RMCM_GAMUT_REMAP_MODE_CURRENT, &mode_select); +// +// //If current set in use not set A (MODE_1), then use set A, otherwise use set B +// if (mode_select != MPCC_GAMUT_REMAP_MODE_SELECT_1) +// mode_select = MPCC_GAMUT_REMAP_MODE_SELECT_1; +// else +// mode_select = MPCC_GAMUT_REMAP_MODE_SELECT_2; +// +// program_gamut_remap(mpc, mpcc_id, arr_reg_val, +// adjust->mpcc_gamut_remap_block_id, mode_select); +// } +//} + +//static void read_gamut_remap(struct mpc *mpc, +// int mpcc_id, +// uint16_t *regval, +// enum mpcc_gamut_remap_id gamut_remap_block_id, +// uint32_t *mode_select) +//{ +// struct color_matrices_reg gamut_regs = {0}; +// struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc); +// +// if (is_mpc_legacy_gamut_id(gamut_remap_block_id)) { +// mpc_read_gamut_remap(mpc, mpcc_id, regval, gamut_remap_block_id, mode_select); +// } +// if (gamut_remap_block_id == MPCC_RMCM_GAMUT_REMAP) { +// //current coefficient set in use +// REG_GET(MPC_RMCM_GAMUT_REMAP_MODE[mpcc_id], MPC_RMCM_GAMUT_REMAP_MODE, mode_select); +// +// gamut_regs.shifts.csc_c11 = mpc42->mpc_shift->MPCC_GAMUT_REMAP_C11_A; +// gamut_regs.masks.csc_c11 = mpc42->mpc_mask->MPCC_GAMUT_REMAP_C11_A; +// gamut_regs.shifts.csc_c12 = mpc42->mpc_shift->MPCC_GAMUT_REMAP_C12_A; +// gamut_regs.masks.csc_c12 = mpc42->mpc_mask->MPCC_GAMUT_REMAP_C12_A; +// +// switch (*mode_select) { +// case MPCC_GAMUT_REMAP_MODE_SELECT_1: +// gamut_regs.csc_c11_c12 = REG(MPC_RMCM_GAMUT_REMAP_C11_C12_A[mpcc_id]); +// gamut_regs.csc_c33_c34 = REG(MPC_RMCM_GAMUT_REMAP_C33_C34_A[mpcc_id]); +// break; +// case MPCC_GAMUT_REMAP_MODE_SELECT_2: +// gamut_regs.csc_c11_c12 = REG(MPC_RMCM_GAMUT_REMAP_C11_C12_B[mpcc_id]); +// gamut_regs.csc_c33_c34 = REG(MPC_RMCM_GAMUT_REMAP_C33_C34_B[mpcc_id]); +// break; +// default: +// break; +// } +// } +// +// if (*mode_select != MPCC_GAMUT_REMAP_MODE_SELECT_0) { +// cm_helper_read_color_matrices( +// mpc42->base.ctx, +// regval, +// &gamut_regs); +// } +//} + +//void mpc42_get_gamut_remap(struct mpc *mpc, +// int mpcc_id, +// struct mpc_grph_gamut_adjustment *adjust) +//{ +// uint16_t arr_reg_val[12] = {0}; +// uint32_t mode_select; +// +// read_gamut_remap(mpc, mpcc_id, arr_reg_val, adjust->mpcc_gamut_remap_block_id, &mode_select); +// +// if (mode_select == MPCC_GAMUT_REMAP_MODE_SELECT_0) { +// adjust->gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; +// return; +// } +// +// adjust->gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW; +// convert_hw_matrix(adjust->temperature_matrix, +// arr_reg_val, ARRAY_SIZE(arr_reg_val)); +//} + void mpc42_read_mpcc_state( struct mpc *mpc, int mpcc_inst, @@ -755,7 +1071,14 @@ static const struct mpc_funcs dcn42_mpc_funcs = { .populate_lut = mpc401_populate_lut, .program_lut_read_write_control = mpc401_program_lut_read_write_control, .program_lut_mode = mpc401_program_lut_mode, - .get_lut_mode = mpc401_get_lut_mode, + .mcm = { + .program_lut_read_write_control = mpc42_program_lut_read_write_control, + .program_3dlut_size = mpc42_program_3dlut_size, + .program_bias_scale = mpc42_program_3dlut_fl_bias_scale, + .program_bit_depth = mpc42_program_bit_depth, + .is_config_supported = mpc42_is_config_supported, + .populate_lut = mpc42_populate_lut, + }, .rmcm = { .enable_3dlut_fl = mpc42_enable_3dlut_fl, .update_3dlut_fast_load_select = mpc42_update_3dlut_fast_load_select, @@ -764,6 +1087,7 @@ static const struct mpc_funcs dcn42_mpc_funcs = { .program_3dlut_size = mpc42_program_rmcm_3dlut_size, .program_bias_scale = mpc42_program_rmcm_3dlut_fast_load_bias_scale, .program_bit_depth = mpc42_program_rmcm_bit_depth, + .is_config_supported = mpc42_is_rmcm_config_supported, .power_on_shaper_3dlut = mpc42_power_on_rmcm_shaper_3dlut, .populate_lut = mpc42_populate_rmcm_lut, .fl_3dlut_configure = mpc42_set_fl_config, diff --git a/drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.h b/drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.h index a5f7f4f2bb3b..12a12c28e553 100644 --- a/drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.h +++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.h @@ -884,6 +884,49 @@ void dcn42_mpc_construct(struct dcn42_mpc *mpc401, void mpc42_init_mpcc(struct mpcc *mpcc, int mpcc_inst); +void mpc42_program_shaper_lutb_settings( + struct mpc *mpc, + const struct pwl_params *params, + uint32_t mpcc_id); +void mpc42_program_shaper_luta_settings( + struct mpc *mpc, + const struct pwl_params *params, + uint32_t mpcc_id); +void mpc42_configure_shaper_lut( + struct mpc *mpc, + bool is_ram_a, + uint32_t mpcc_id); +void mpc42_power_on_shaper_3dlut( + struct mpc *mpc, + uint32_t mpcc_id, + bool power_on); +void mpc42_program_3dlut_size( + struct mpc *mpc, + uint32_t width, + int mpcc_id); +void mpc42_program_3dlut_fl_bias_scale( + struct mpc *mpc, + uint16_t bias, + uint16_t scale, + int mpcc_id); +void mpc42_program_bit_depth( + struct mpc *mpc, + uint16_t bit_depth, + int mpcc_id); +void mpc42_populate_lut( + struct mpc *mpc, + const union mcm_lut_params params, + bool lut_bank_a, + int mpcc_id); +void mpc42_program_lut_read_write_control( + struct mpc *mpc, + const enum MCM_LUT_ID id, + bool lut_bank_a, + bool enabled, + int mpcc_id); + +bool mpc42_is_config_supported(uint32_t width); + /* RMCM */ void mpc42_program_rmcm_shaper_lut( struct mpc *mpc, @@ -927,12 +970,12 @@ void mpc42_program_rmcm_lut_read_write_control( int mpcc_id); void mpc42_program_lut_mode( struct mpc *mpc, - bool enable, + const enum MCM_LUT_XABLE xable, bool lut_bank_a, int mpcc_id); void mpc42_program_rmcm_3dlut_size( struct mpc *mpc, - const enum dc_cm_lut_size size, + uint32_t width, int mpcc_id); void mpc42_program_rmcm_3dlut_fast_load_bias_scale( struct mpc *mpc, @@ -944,6 +987,8 @@ void mpc42_program_rmcm_bit_depth( uint16_t bit_depth, int mpcc_id); +bool mpc42_is_rmcm_config_supported(uint32_t width); + void mpc42_set_fl_config( struct mpc *mpc, struct mpc_fl_3dlut_config *cfg, diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c index c0d37f00fed9..2c1f72cf1a63 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c @@ -666,7 +666,6 @@ static const struct resource_caps res_cap_dcn42 = { .num_vmid = 16, .num_mpc_3dlut = 2, .num_dsc = 4, - .num_rmcm = 2, }; static const struct dc_plane_cap plane_cap = { diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c index 00473c6284d5..614db22d62f3 100644 --- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c @@ -502,6 +502,8 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream, * * @stream: contains data we may need to construct VSIF (i.e. timing_3d_format, etc.) * @info_packet: output structure where to store VSIF + * @ALLMEnabled: indicates whether ALLM HF-VSIF should be generated + * @ALLMValue: ALLM bit value to advertise in HF-VSIF */ void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream, struct dc_info_packet *info_packet) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 736304e73ca4..952391aecf2d 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -244,6 +244,10 @@ static ssize_t amdgpu_set_power_dpm_state(struct device *dev, enum amd_pm_state_type state; int ret; + /* Reject empty/whitespace strings - fuzzing found this is not validated */ + if (count == 0 || sysfs_streq(buf, "")) + return -EINVAL; + if (sysfs_streq(buf, "battery")) state = POWER_STATE_TYPE_BATTERY; else if (sysfs_streq(buf, "balanced")) @@ -364,6 +368,10 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, enum amd_dpm_forced_level level; int ret = 0; + /* Reject empty/whitespace strings - fuzzing found this is not validated */ + if (count == 0 || sysfs_streq(buf, "")) + return -EINVAL; + if (sysfs_streq(buf, "low")) level = AMD_DPM_FORCED_LEVEL_LOW; else if (sysfs_streq(buf, "high")) @@ -902,6 +910,10 @@ static ssize_t amdgpu_set_pp_features(struct device *dev, uint64_t featuremask; int ret; + /* Reject empty/whitespace strings - fuzzing found kstrtou64 accepts "" as 0 */ + if (count == 0 || sysfs_streq(buf, "")) + return -EINVAL; + ret = kstrtou64(buf, 0, &featuremask); if (ret) return -EINVAL; @@ -1027,6 +1039,10 @@ static ssize_t amdgpu_read_mask(const char *buf, size_t count, uint32_t *mask) *mask = 0; + /* Reject empty/whitespace strings - fuzzing found this is not validated */ + if (count == 0 || sysfs_streq(buf, "")) + return -EINVAL; + bytes = min(count, sizeof(buf_cpy) - 1); memcpy(buf_cpy, buf, bytes); buf_cpy[bytes] = '\0'; @@ -1378,6 +1394,10 @@ static ssize_t amdgpu_set_pp_power_profile_mode(struct device *dev, long int profile_mode = 0; const char delimiter[3] = {' ', '\n', '\0'}; + /* Reject empty/whitespace strings - fuzzing found this is not validated */ + if (count == 0 || sysfs_streq(buf, "")) + return -EINVAL; + tmp[0] = *(buf); tmp[1] = '\0'; ret = kstrtol(tmp, 0, &profile_mode); @@ -2505,12 +2525,12 @@ static ssize_t amdgpu_set_pm_policy_attr(struct device *dev, .dev_attr = __ATTR(_name, 0644, amdgpu_get_pm_policy_attr, \ amdgpu_set_pm_policy_attr), \ .id = PP_PM_POLICY_##_id, \ - }; + } #define AMDGPU_PM_POLICY_ATTR_VAR(_name) pm_policy_attr_##_name.dev_attr.attr -AMDGPU_PM_POLICY_ATTR(soc_pstate, SOC_PSTATE) -AMDGPU_PM_POLICY_ATTR(xgmi_plpd, XGMI_PLPD) +AMDGPU_PM_POLICY_ATTR(soc_pstate, SOC_PSTATE); +AMDGPU_PM_POLICY_ATTR(xgmi_plpd, XGMI_PLPD); static struct attribute *pm_policy_attrs[] = { &AMDGPU_PM_POLICY_ATTR_VAR(soc_pstate), |
