diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display')
384 files changed, 22233 insertions, 3971 deletions
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile index 8e949fe77312..89350aa9ca7e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile @@ -40,7 +40,8 @@ AMDGPUDM = \ amdgpu_dm_replay.o \ amdgpu_dm_quirks.o \ amdgpu_dm_wb.o \ - amdgpu_dm_colorop.o + amdgpu_dm_colorop.o \ + amdgpu_dm_ism.o ifdef CONFIG_DRM_AMD_DC_FP AMDGPUDM += dc_fpu.o 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 2328c1aa0ead..21635e80349a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT /* - * Copyright 2015 Advanced Micro Devices, Inc. + * Copyright 2015-2026 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -91,6 +91,7 @@ #include <drm/drm_fourcc.h> #include <drm/drm_edid.h> #include <drm/drm_eld.h> +#include <drm/drm_mode.h> #include <drm/drm_utils.h> #include <drm/drm_vblank.h> #include <drm/drm_audio_component.h> @@ -152,6 +153,9 @@ MODULE_FIRMWARE(FIRMWARE_DCN_36_DMUB); #define FIRMWARE_DCN_401_DMUB "amdgpu/dcn_4_0_1_dmcub.bin" MODULE_FIRMWARE(FIRMWARE_DCN_401_DMUB); +#define FIRMWARE_DCN_42_DMUB "amdgpu/dcn_4_2_dmcub.bin" +MODULE_FIRMWARE(FIRMWARE_DCN_42_DMUB); + /** * DOC: overview * @@ -1368,6 +1372,7 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev) case IP_VERSION(3, 5, 0): case IP_VERSION(3, 5, 1): case IP_VERSION(3, 6, 0): + case IP_VERSION(4, 2, 0): hw_params.ips_sequential_ono = adev->external_rev_id > 0x10; hw_params.lower_hbr3_phy_ssc = true; break; @@ -1815,6 +1820,9 @@ static void *dm_dmub_get_vbios_bounding_box(struct amdgpu_device *adev) case IP_VERSION(4, 0, 1): bb_size = sizeof(struct dml2_soc_bb); break; + case IP_VERSION(4, 2, 0): + bb_size = sizeof(struct dml2_soc_bb); + break; default: return NULL; } @@ -1859,6 +1867,9 @@ static enum dmub_ips_disable_type dm_get_default_ips_mode( case IP_VERSION(3, 5, 1): ret = DMUB_IPS_RCG_IN_ACTIVE_IPS2_IN_OFF; break; + case IP_VERSION(4, 2, 0): + ret = DMUB_IPS_DISABLE_ALL; + break; default: /* ASICs older than DCN35 do not have IPSs */ if (amdgpu_ip_version(adev, DCE_HWIP, 0) < IP_VERSION(3, 5, 0)) @@ -2002,6 +2013,13 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) if (amdgpu_ip_version(adev, DCE_HWIP, 0) >= IP_VERSION(3, 0, 0)) init_data.num_virtual_links = 1; + /* DCN42 and above dpia switch to unified link training path */ + if (amdgpu_ip_version(adev, DCE_HWIP, 0) >= IP_VERSION(4, 2, 0)) { + init_data.flags.consolidated_dpia_dp_lt = true; + init_data.flags.enable_dpia_pre_training = true; + init_data.flags.unify_link_enc_assignment = true; + init_data.flags.usb4_bw_alloc_support = true; + } retrieve_dmi_info(&adev->dm); if (adev->dm.edp0_on_dp1_quirk) init_data.flags.support_edp0_on_dp1 = true; @@ -2272,6 +2290,11 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev) &adev->dm.dmub_bo_gpu_addr, &adev->dm.dmub_bo_cpu_addr); + if (adev->dm.boot_time_crc_info.bo_ptr) + amdgpu_bo_free_kernel(&adev->dm.boot_time_crc_info.bo_ptr, + &adev->dm.boot_time_crc_info.gpu_addr, + &adev->dm.boot_time_crc_info.cpu_addr); + if (adev->dm.hpd_rx_offload_wq && adev->dm.dc) { for (i = 0; i < adev->dm.dc->caps.max_links; i++) { if (adev->dm.hpd_rx_offload_wq[i].wq) { @@ -2369,6 +2392,7 @@ static int load_dmcu_fw(struct amdgpu_device *adev) case IP_VERSION(3, 5, 1): case IP_VERSION(3, 6, 0): case IP_VERSION(4, 0, 1): + case IP_VERSION(4, 2, 0): return 0; default: break; @@ -2454,6 +2478,8 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev) DMUB_WINDOW_MEMORY_TYPE_FB, //DMUB_WINDOW_7_SCRATCH_MEM DMUB_WINDOW_MEMORY_TYPE_FB, //DMUB_WINDOW_IB_MEM DMUB_WINDOW_MEMORY_TYPE_FB, //DMUB_WINDOW_SHARED_STATE + DMUB_WINDOW_MEMORY_TYPE_FB, //DMUB_WINDOW_LSDMA_BUFFER + DMUB_WINDOW_MEMORY_TYPE_FB, //DMUB_WINDOW_CURSOR_OFFLOAD }; int r; @@ -2502,7 +2528,9 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev) case IP_VERSION(4, 0, 1): dmub_asic = DMUB_ASIC_DCN401; break; - + case IP_VERSION(4, 2, 0): + dmub_asic = DMUB_ASIC_DCN42; + break; default: /* ASIC doesn't support DMUB. */ return 0; @@ -2715,6 +2743,54 @@ static int detect_mst_link_for_all_connectors(struct drm_device *dev) return ret; } +static void amdgpu_dm_boot_time_crc_init(struct amdgpu_device *adev) +{ + struct dm_boot_time_crc_info *bootcrc_info = NULL; + struct dmub_srv *dmub = NULL; + union dmub_fw_boot_options option = {0}; + int ret = 0; + const uint32_t fb_size = 3 * 1024 * 1024; /* 3MB for DCC pattern */ + + if (!adev || !adev->dm.dc || !adev->dm.dc->ctx || + !adev->dm.dc->ctx->dmub_srv) { + return; + } + + dmub = adev->dm.dc->ctx->dmub_srv->dmub; + bootcrc_info = &adev->dm.boot_time_crc_info; + + if (!dmub || !dmub->hw_funcs.get_fw_boot_option) { + drm_dbg(adev_to_drm(adev), "failed to init boot time crc buffer\n"); + return; + } + + option = dmub->hw_funcs.get_fw_boot_option(dmub); + + /* Return if boot time CRC is not enabled */ + if (option.bits.bootcrc_en_at_S0i3 == 0) + return; + + /* Create a buffer for boot time CRC */ + ret = amdgpu_bo_create_kernel(adev, fb_size, PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT, + &bootcrc_info->bo_ptr, + &bootcrc_info->gpu_addr, + &bootcrc_info->cpu_addr); + + if (ret) { + drm_dbg(adev_to_drm(adev), "failed to create boot time crc buffer\n"); + } else { + bootcrc_info->size = fb_size; + + drm_dbg(adev_to_drm(adev), "boot time crc buffer created addr 0x%llx, size %u\n", + bootcrc_info->gpu_addr, bootcrc_info->size); + + /* Send the buffer info to DMUB */ + dc_dmub_srv_boot_time_crc_init(adev->dm.dc, + bootcrc_info->gpu_addr, bootcrc_info->size); + } +} + static int dm_late_init(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; @@ -2726,6 +2802,11 @@ static int dm_late_init(struct amdgpu_ip_block *ip_block) dmcu = adev->dm.dc->res_pool->dmcu; + /* Init the boot time CRC (skip in resume) */ + if ((adev->in_suspend == 0) && + (amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(3, 6, 0))) + amdgpu_dm_boot_time_crc_init(adev); + for (i = 0; i < 16; i++) linear_lut[i] = 0xFFFF * i / 15; @@ -3202,6 +3283,7 @@ static int dm_suspend(struct amdgpu_ip_block *ip_block) mutex_lock(&dm->dc_lock); + amdgpu_dm_ism_disable(dm); dc_allow_idle_optimizations(adev->dm.dc, false); dm->cached_dc_state = dc_state_create_copy(dm->dc->current_state); @@ -3235,6 +3317,9 @@ static int dm_suspend(struct amdgpu_ip_block *ip_block) amdgpu_dm_irq_suspend(adev); + scoped_guard(mutex, &dm->dc_lock) + amdgpu_dm_ism_disable(dm); + hpd_rx_irq_work_suspend(dm); dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D3); @@ -3525,6 +3610,7 @@ static int dm_resume(struct amdgpu_ip_block *ip_block) dc_resume(dm->dc); + amdgpu_dm_ism_enable(dm); amdgpu_dm_irq_resume_early(adev); for (i = 0; i < dc_state->stream_count; i++) { @@ -3585,6 +3671,9 @@ static int dm_resume(struct amdgpu_ip_block *ip_block) /* program HPD filter */ dc_resume(dm->dc); + scoped_guard(mutex, &dm->dc_lock) + amdgpu_dm_ism_enable(dm); + /* * early enable HPD Rx IRQ, should be done before set mode as short * pulse interrupts are used for MST @@ -3765,6 +3854,10 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector) caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps; caps->aux_support = false; + drm_object_property_set_value(&conn_base->base, + adev_to_drm(adev)->mode_config.panel_type_property, + caps->ext_caps->bits.oled ? DRM_MODE_PANEL_TYPE_OLED : DRM_MODE_PANEL_TYPE_UNKNOWN); + if (caps->ext_caps->bits.oled == 1 /* * || @@ -4386,105 +4479,6 @@ static int register_hpd_handlers(struct amdgpu_device *adev) return 0; } -#if defined(CONFIG_DRM_AMD_DC_SI) -/* Register IRQ sources and initialize IRQ callbacks */ -static int dce60_register_irq_handlers(struct amdgpu_device *adev) -{ - struct dc *dc = adev->dm.dc; - struct common_irq_params *c_irq_params; - struct dc_interrupt_params int_params = {0}; - int r; - int i; - unsigned int client_id = AMDGPU_IRQ_CLIENTID_LEGACY; - - int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT; - int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT; - - /* - * Actions of amdgpu_irq_add_id(): - * 1. Register a set() function with base driver. - * Base driver will call set() function to enable/disable an - * interrupt in DC hardware. - * 2. Register amdgpu_dm_irq_handler(). - * Base driver will call amdgpu_dm_irq_handler() for ALL interrupts - * coming from DC hardware. - * amdgpu_dm_irq_handler() will re-direct the interrupt to DC - * for acknowledging and handling. - */ - - /* Use VBLANK interrupt */ - for (i = 0; i < adev->mode_info.num_crtc; i++) { - r = amdgpu_irq_add_id(adev, client_id, i + 1, &adev->crtc_irq); - if (r) { - drm_err(adev_to_drm(adev), "Failed to add crtc irq id!\n"); - return r; - } - - int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; - int_params.irq_source = - dc_interrupt_to_irq_source(dc, i + 1, 0); - - if (int_params.irq_source == DC_IRQ_SOURCE_INVALID || - int_params.irq_source < DC_IRQ_SOURCE_VBLANK1 || - int_params.irq_source > DC_IRQ_SOURCE_VBLANK6) { - drm_err(adev_to_drm(adev), "Failed to register vblank irq!\n"); - return -EINVAL; - } - - c_irq_params = &adev->dm.vblank_params[int_params.irq_source - DC_IRQ_SOURCE_VBLANK1]; - - c_irq_params->adev = adev; - c_irq_params->irq_src = int_params.irq_source; - - if (!amdgpu_dm_irq_register_interrupt(adev, &int_params, - dm_crtc_high_irq, c_irq_params)) - return -ENOMEM; - } - - /* Use GRPH_PFLIP interrupt */ - for (i = VISLANDS30_IV_SRCID_D1_GRPH_PFLIP; - i <= VISLANDS30_IV_SRCID_D6_GRPH_PFLIP; i += 2) { - r = amdgpu_irq_add_id(adev, client_id, i, &adev->pageflip_irq); - if (r) { - drm_err(adev_to_drm(adev), "Failed to add page flip irq id!\n"); - return r; - } - - int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; - int_params.irq_source = - dc_interrupt_to_irq_source(dc, i, 0); - - if (int_params.irq_source == DC_IRQ_SOURCE_INVALID || - int_params.irq_source < DC_IRQ_SOURCE_PFLIP_FIRST || - int_params.irq_source > DC_IRQ_SOURCE_PFLIP_LAST) { - drm_err(adev_to_drm(adev), "Failed to register pflip irq!\n"); - return -EINVAL; - } - - c_irq_params = &adev->dm.pflip_params[int_params.irq_source - DC_IRQ_SOURCE_PFLIP_FIRST]; - - c_irq_params->adev = adev; - c_irq_params->irq_src = int_params.irq_source; - - if (!amdgpu_dm_irq_register_interrupt(adev, &int_params, - dm_pflip_high_irq, c_irq_params)) - return -ENOMEM; - } - - /* HPD */ - r = amdgpu_irq_add_id(adev, client_id, - VISLANDS30_IV_SRCID_HOTPLUG_DETECT_A, &adev->hpd_irq); - if (r) { - drm_err(adev_to_drm(adev), "Failed to add hpd irq id!\n"); - return r; - } - - r = register_hpd_handlers(adev); - - return r; -} -#endif - /* Register IRQ sources and initialize IRQ callbacks */ static int dce110_register_irq_handlers(struct amdgpu_device *adev) { @@ -4493,7 +4487,12 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) struct dc_interrupt_params int_params = {0}; int r; int i; + unsigned int src_id; unsigned int client_id = AMDGPU_IRQ_CLIENTID_LEGACY; + /* Use different interrupts for VBLANK on DCE 6 vs. newer. */ + const unsigned int vblank_d1 = + adev->dm.dc->ctx->dce_version >= DCE_VERSION_8_0 + ? VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0 : 1; if (adev->family >= AMDGPU_FAMILY_AI) client_id = SOC15_IH_CLIENTID_DCE; @@ -4514,8 +4513,9 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) */ /* Use VBLANK interrupt */ - for (i = VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0; i <= VISLANDS30_IV_SRCID_D6_VERTICAL_INTERRUPT0; i++) { - r = amdgpu_irq_add_id(adev, client_id, i, &adev->crtc_irq); + for (i = 0; i < adev->mode_info.num_crtc; i++) { + src_id = vblank_d1 + i; + r = amdgpu_irq_add_id(adev, client_id, src_id, &adev->crtc_irq); if (r) { drm_err(adev_to_drm(adev), "Failed to add crtc irq id!\n"); return r; @@ -4523,7 +4523,7 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; int_params.irq_source = - dc_interrupt_to_irq_source(dc, i, 0); + dc_interrupt_to_irq_source(dc, src_id, 0); if (int_params.irq_source == DC_IRQ_SOURCE_INVALID || int_params.irq_source < DC_IRQ_SOURCE_VBLANK1 || @@ -4542,33 +4542,36 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) return -ENOMEM; } - /* Use VUPDATE interrupt */ - for (i = VISLANDS30_IV_SRCID_D1_V_UPDATE_INT; i <= VISLANDS30_IV_SRCID_D6_V_UPDATE_INT; i += 2) { - r = amdgpu_irq_add_id(adev, client_id, i, &adev->vupdate_irq); - if (r) { - drm_err(adev_to_drm(adev), "Failed to add vupdate irq id!\n"); - return r; - } - - int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; - int_params.irq_source = - dc_interrupt_to_irq_source(dc, i, 0); + if (dc_supports_vrr(adev->dm.dc->ctx->dce_version)) { + /* Use VUPDATE interrupt */ + for (i = 0; i < adev->mode_info.num_crtc; i++) { + src_id = VISLANDS30_IV_SRCID_D1_V_UPDATE_INT + i * 2; + r = amdgpu_irq_add_id(adev, client_id, src_id, &adev->vupdate_irq); + if (r) { + drm_err(adev_to_drm(adev), "Failed to add vupdate irq id!\n"); + return r; + } - if (int_params.irq_source == DC_IRQ_SOURCE_INVALID || - int_params.irq_source < DC_IRQ_SOURCE_VUPDATE1 || - int_params.irq_source > DC_IRQ_SOURCE_VUPDATE6) { - drm_err(adev_to_drm(adev), "Failed to register vupdate irq!\n"); - return -EINVAL; - } + int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; + int_params.irq_source = + dc_interrupt_to_irq_source(dc, src_id, 0); - c_irq_params = &adev->dm.vupdate_params[int_params.irq_source - DC_IRQ_SOURCE_VUPDATE1]; + if (int_params.irq_source == DC_IRQ_SOURCE_INVALID || + int_params.irq_source < DC_IRQ_SOURCE_VUPDATE1 || + int_params.irq_source > DC_IRQ_SOURCE_VUPDATE6) { + drm_err(adev_to_drm(adev), "Failed to register vupdate irq!\n"); + return -EINVAL; + } - c_irq_params->adev = adev; - c_irq_params->irq_src = int_params.irq_source; + c_irq_params = &adev->dm.vupdate_params[ + int_params.irq_source - DC_IRQ_SOURCE_VUPDATE1]; + c_irq_params->adev = adev; + c_irq_params->irq_src = int_params.irq_source; - if (!amdgpu_dm_irq_register_interrupt(adev, &int_params, - dm_vupdate_high_irq, c_irq_params)) - return -ENOMEM; + if (!amdgpu_dm_irq_register_interrupt(adev, &int_params, + dm_vupdate_high_irq, c_irq_params)) + return -ENOMEM; + } } /* Use GRPH_PFLIP interrupt */ @@ -4910,14 +4913,37 @@ static void dm_atomic_destroy_state(struct drm_private_obj *obj, kfree(dm_state); } +static struct drm_private_state * +dm_atomic_create_state(struct drm_private_obj *obj) +{ + struct amdgpu_device *adev = drm_to_adev(obj->dev); + struct dm_atomic_state *dm_state; + struct dc_state *context; + + dm_state = kzalloc_obj(*dm_state); + if (!dm_state) + return ERR_PTR(-ENOMEM); + + context = dc_state_create_current_copy(adev->dm.dc); + if (!context) { + kfree(dm_state); + return ERR_PTR(-ENOMEM); + } + + __drm_atomic_helper_private_obj_create_state(obj, &dm_state->base); + dm_state->context = context; + + return &dm_state->base; +} + static struct drm_private_state_funcs dm_atomic_state_funcs = { + .atomic_create_state = dm_atomic_create_state, .atomic_duplicate_state = dm_atomic_duplicate_state, .atomic_destroy_state = dm_atomic_destroy_state, }; static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev) { - struct dm_atomic_state *state; int r; adev->mode_info.mode_config_initialized = true; @@ -4937,42 +4963,22 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev) /* indicates support for immediate flip */ adev_to_drm(adev)->mode_config.async_page_flip = true; - state = kzalloc_obj(*state); - if (!state) - return -ENOMEM; - - state->context = dc_state_create_current_copy(adev->dm.dc); - if (!state->context) { - kfree(state); - return -ENOMEM; - } - drm_atomic_private_obj_init(adev_to_drm(adev), &adev->dm.atomic_obj, - &state->base, &dm_atomic_state_funcs); r = amdgpu_display_modeset_create_props(adev); - if (r) { - dc_state_release(state->context); - kfree(state); + if (r) return r; - } #ifdef AMD_PRIVATE_COLOR - if (amdgpu_dm_create_color_properties(adev)) { - dc_state_release(state->context); - kfree(state); + if (amdgpu_dm_create_color_properties(adev)) return -ENOMEM; - } #endif r = amdgpu_dm_audio_init(adev); - if (r) { - dc_state_release(state->context); - kfree(state); + if (r) return r; - } return 0; } @@ -5540,6 +5546,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) case IP_VERSION(3, 5, 1): case IP_VERSION(3, 6, 0): case IP_VERSION(4, 0, 1): + case IP_VERSION(4, 2, 0): if (register_outbox_irq_handlers(dm->adev)) { drm_err(adev_to_drm(adev), "DM: Failed to initialize IRQ\n"); goto fail; @@ -5564,6 +5571,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) case IP_VERSION(3, 5, 1): case IP_VERSION(3, 6, 0): case IP_VERSION(4, 0, 1): + case IP_VERSION(4, 2, 0): psr_feature_enabled = true; break; default: @@ -5581,6 +5589,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) case IP_VERSION(3, 5, 0): case IP_VERSION(3, 5, 1): case IP_VERSION(3, 6, 0): + case IP_VERSION(4, 2, 0): replay_feature_enabled = true; break; @@ -5696,11 +5705,6 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) case CHIP_PITCAIRN: case CHIP_VERDE: case CHIP_OLAND: - if (dce60_register_irq_handlers(dm->adev)) { - drm_err(adev_to_drm(adev), "DM: Failed to initialize IRQ\n"); - goto fail; - } - break; #endif case CHIP_BONAIRE: case CHIP_HAWAII: @@ -5746,6 +5750,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) case IP_VERSION(3, 5, 1): case IP_VERSION(3, 6, 0): case IP_VERSION(4, 0, 1): + case IP_VERSION(4, 2, 0): if (dcn10_register_irq_handlers(dm->adev)) { drm_err(adev_to_drm(adev), "DM: Failed to initialize IRQ\n"); goto fail; @@ -5894,6 +5899,9 @@ static int dm_init_microcode(struct amdgpu_device *adev) case IP_VERSION(4, 0, 1): fw_name_dmub = FIRMWARE_DCN_401_DMUB; break; + case IP_VERSION(4, 2, 0): + fw_name_dmub = FIRMWARE_DCN_42_DMUB; + break; default: /* ASIC doesn't support DMUB. */ return 0; @@ -6021,6 +6029,7 @@ static int dm_early_init(struct amdgpu_ip_block *ip_block) case IP_VERSION(3, 5, 1): case IP_VERSION(3, 6, 0): case IP_VERSION(4, 0, 1): + case IP_VERSION(4, 2, 0): adev->mode_info.num_crtc = 4; adev->mode_info.num_hpd = 4; adev->mode_info.num_dig = 4; @@ -6037,8 +6046,8 @@ static int dm_early_init(struct amdgpu_ip_block *ip_block) adev->mode_info.funcs = &dm_display_funcs; /* - * Note: Do NOT change adev->audio_endpt_rreg and - * adev->audio_endpt_wreg because they are initialised in + * Note: Do NOT change adev->reg.audio_endpt.rreg and + * adev->reg.audio_endpt.wreg because they are initialised in * amdgpu_device_init() */ #if defined(CONFIG_DEBUG_KERNEL_DC) @@ -6721,11 +6730,11 @@ static void fill_stream_properties_from_drm_display_mode( && aconnector && aconnector->force_yuv420_output) timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420; - else if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCBCR422) + else if ((connector->display_info.color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422)) && aconnector && aconnector->force_yuv422_output) timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR422; - else if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCBCR444) + else if ((connector->display_info.color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444)) && stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR444; else @@ -8579,6 +8588,12 @@ static int to_drm_connector_type(enum signal_type st, uint32_t connector_id) return DRM_MODE_CONNECTOR_VGA; case SIGNAL_TYPE_DISPLAY_PORT: case SIGNAL_TYPE_DISPLAY_PORT_MST: + /* External DP bridges have a different connector type. */ + if (connector_id == CONNECTOR_ID_VGA) + return DRM_MODE_CONNECTOR_VGA; + else if (connector_id == CONNECTOR_ID_LVDS) + return DRM_MODE_CONNECTOR_LVDS; + return DRM_MODE_CONNECTOR_DisplayPort; case SIGNAL_TYPE_DVI_DUAL_LINK: case SIGNAL_TYPE_DVI_SINGLE_LINK: @@ -9074,6 +9089,8 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, if (connector_type == DRM_MODE_CONNECTOR_eDP) { struct drm_privacy_screen *privacy_screen; + drm_connector_attach_panel_type_property(&aconnector->base); + privacy_screen = drm_privacy_screen_get(adev_to_drm(adev)->dev, NULL); if (!IS_ERR(privacy_screen)) { drm_connector_attach_privacy_screen_provider(&aconnector->base, @@ -9251,8 +9268,7 @@ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, connector_type == DRM_MODE_CONNECTOR_HDMIB) amdgpu_dm_initialize_hdmi_connector(aconnector); - if (connector_type == DRM_MODE_CONNECTOR_DisplayPort - || connector_type == DRM_MODE_CONNECTOR_eDP) + if (dc_is_dp_signal(link->connector_signal)) amdgpu_dm_initialize_dp_connector(dm, aconnector, link->link_index); out_free: @@ -9326,31 +9342,7 @@ static void manage_dm_interrupts(struct amdgpu_device *adev, if (acrtc_state) { timing = &acrtc_state->stream->timing; - /* - * Depending on when the HW latching event of double-buffered - * registers happen relative to the PSR SDP deadline, and how - * bad the Panel clock has drifted since the last ALPM off - * event, there can be up to 3 frames of delay between sending - * the PSR exit cmd to DMUB fw, and when the panel starts - * displaying live frames. - * - * We can set: - * - * 20/100 * offdelay_ms = 3_frames_ms - * => offdelay_ms = 5 * 3_frames_ms - * - * This ensures that `3_frames_ms` will only be experienced as a - * 20% delay on top how long the display has been static, and - * thus make the delay less perceivable. - */ - if (acrtc_state->stream->link->psr_settings.psr_version < - DC_PSR_VERSION_UNSUPPORTED) { - offdelay = DIV64_U64_ROUND_UP((u64)5 * 3 * 10 * - timing->v_total * - timing->h_total, - timing->pix_clk_100hz); - config.offdelay_ms = offdelay ?: 30; - } else if (amdgpu_ip_version(adev, DCE_HWIP, 0) < + if (amdgpu_ip_version(adev, DCE_HWIP, 0) < IP_VERSION(3, 5, 0) || !(adev->flags & AMD_IS_APU)) { /* @@ -9895,7 +9887,8 @@ static void amdgpu_dm_enable_self_refresh(struct amdgpu_crtc *acrtc_attach, * a vblank event disable request to enable PSR/RP. PSR SU/RP * can be enabled immediately once OS demonstrates an * adequate number of fast atomic commits to notify KMD - * of update events. See `vblank_control_worker()`. + * of update events. + * See `amdgpu_dm_crtc_vblank_control_worker()`. */ if (!vrr_active && acrtc_attach->dm_irq_params.allow_sr_entry && @@ -10063,8 +10056,9 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, /* * If the dirty regions changed, PSR-SU need to be disabled temporarily * and enabled it again after dirty regions are stable to avoid video glitch. - * PSR-SU will be enabled in vblank_control_worker() if user pause the video - * during the PSR-SU was disabled. + * PSR-SU will be enabled in + * amdgpu_dm_crtc_vblank_control_worker() if user + * pause the video during the PSR-SU was disabled. */ if (acrtc_state->stream->link->psr_settings.psr_version >= DC_PSR_VERSION_SU_1 && acrtc_attach->dm_irq_params.allow_sr_entry && @@ -12314,10 +12308,11 @@ static int dm_crtc_get_cursor_mode(struct amdgpu_device *adev, int i; /* Overlay cursor not supported on HW before DCN - * DCN401 does not have the cursor-on-scaled-plane or cursor-on-yuv-plane restrictions - * as previous DCN generations, so enable native mode on DCN401 + * DCN401/420 does not have the cursor-on-scaled-plane or cursor-on-yuv-plane restrictions + * as previous DCN generations, so enable native mode on DCN401/420 */ - if (amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 0, 1)) { + if (amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 0, 1) || + amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 2, 0)) { *cursor_mode = DM_CURSOR_NATIVE_MODE; return 0; } @@ -12742,7 +12737,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, /* Check if rotation or scaling is enabled on DCN401 */ if ((drm_plane_mask(crtc->cursor) & new_crtc_state->plane_mask) && - amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 0, 1)) { + (amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 2, 0) || + amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 0, 1))) { new_cursor_state = drm_atomic_get_new_plane_state(state, crtc->cursor); is_rotated = new_cursor_state && diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index d15812d51d72..d1a14e0c12bd 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -123,6 +123,20 @@ struct dm_compressor_info { uint64_t gpu_addr; }; +/** + * struct dm_boot_time_crc_info - Buffer info used by boot time CRC + * @cpu_addr: MMIO cpu addr + * @bo_ptr: Pointer to the buffer object + * @gpu_addr: MMIO gpu addr + * @size: Size of the buffer + */ +struct dm_boot_time_crc_info { + void *cpu_addr; + struct amdgpu_bo *bo_ptr; + uint64_t gpu_addr; + uint32_t size; +}; + typedef void (*dmub_notify_interrupt_callback_t)(struct amdgpu_device *adev, struct dmub_notification *notify); /** @@ -698,6 +712,13 @@ struct amdgpu_display_manager { struct completion replied; char reply_data[0x40]; // Cannot include dmub_cmd here } fused_io[8]; + + /** + * @dm_boot_time_crc_info: + * + * Buffer info for the boot time crc. + */ + struct dm_boot_time_crc_info boot_time_crc_info; }; enum dsc_clock_force_state { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c index aa4658867e55..7ee051cb3c05 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c @@ -55,6 +55,10 @@ const u64 amdgpu_dm_supported_blnd_tfs = #define LUT3D_SIZE 17 +static const struct drm_colorop_funcs dm_colorop_funcs = { + .destroy = drm_colorop_destroy, +}; + int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_prop_enum_list *list) { struct drm_colorop *ops[MAX_COLOR_PIPELINE_OPS]; @@ -73,7 +77,7 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr goto cleanup; } - ret = drm_plane_colorop_curve_1d_init(dev, ops[i], plane, + ret = drm_plane_colorop_curve_1d_init(dev, ops[i], plane, &dm_colorop_funcs, amdgpu_dm_supported_degam_tfs, DRM_COLOROP_FLAG_ALLOW_BYPASS); if (ret) @@ -90,7 +94,8 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr goto cleanup; } - ret = drm_plane_colorop_mult_init(dev, ops[i], plane, DRM_COLOROP_FLAG_ALLOW_BYPASS); + ret = drm_plane_colorop_mult_init(dev, ops[i], plane, &dm_colorop_funcs, + DRM_COLOROP_FLAG_ALLOW_BYPASS); if (ret) goto cleanup; @@ -105,7 +110,9 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr goto cleanup; } - ret = drm_plane_colorop_ctm_3x4_init(dev, ops[i], plane, DRM_COLOROP_FLAG_ALLOW_BYPASS); + ret = drm_plane_colorop_ctm_3x4_init(dev, ops[i], plane, + &dm_colorop_funcs, + DRM_COLOROP_FLAG_ALLOW_BYPASS); if (ret) goto cleanup; @@ -121,7 +128,7 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr goto cleanup; } - ret = drm_plane_colorop_curve_1d_init(dev, ops[i], plane, + ret = drm_plane_colorop_curve_1d_init(dev, ops[i], plane, &dm_colorop_funcs, amdgpu_dm_supported_shaper_tfs, DRM_COLOROP_FLAG_ALLOW_BYPASS); if (ret) @@ -138,7 +145,9 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr goto cleanup; } - ret = drm_plane_colorop_curve_1d_lut_init(dev, ops[i], plane, MAX_COLOR_LUT_ENTRIES, + ret = drm_plane_colorop_curve_1d_lut_init(dev, ops[i], plane, + &dm_colorop_funcs, + MAX_COLOR_LUT_ENTRIES, DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR, DRM_COLOROP_FLAG_ALLOW_BYPASS); if (ret) @@ -155,7 +164,8 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr goto cleanup; } - ret = drm_plane_colorop_3dlut_init(dev, ops[i], plane, LUT3D_SIZE, + ret = drm_plane_colorop_3dlut_init(dev, ops[i], plane, + &dm_colorop_funcs, LUT3D_SIZE, DRM_COLOROP_LUT3D_INTERPOLATION_TETRAHEDRAL, DRM_COLOROP_FLAG_ALLOW_BYPASS); if (ret) @@ -173,7 +183,7 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr goto cleanup; } - ret = drm_plane_colorop_curve_1d_init(dev, ops[i], plane, + ret = drm_plane_colorop_curve_1d_init(dev, ops[i], plane, &dm_colorop_funcs, amdgpu_dm_supported_blnd_tfs, DRM_COLOROP_FLAG_ALLOW_BYPASS); if (ret) @@ -190,7 +200,8 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr goto cleanup; } - ret = drm_plane_colorop_curve_1d_lut_init(dev, ops[i], plane, MAX_COLOR_LUT_ENTRIES, + ret = drm_plane_colorop_curve_1d_lut_init(dev, ops[i], plane, &dm_colorop_funcs, + MAX_COLOR_LUT_ENTRIES, DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR, DRM_COLOROP_FLAG_ALLOW_BYPASS); if (ret) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c index b96fbc03c371..62573173e2ac 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c @@ -812,7 +812,6 @@ void amdgpu_dm_crtc_handle_crc_window_irq(struct drm_crtc *crtc) unsigned long flags1; bool forward_roi_change = false; bool notify_ta = false; - bool all_crc_ready = true; struct dc_stream_state *stream_state; int i; @@ -936,9 +935,6 @@ void amdgpu_dm_crtc_handle_crc_window_irq(struct drm_crtc *crtc) continue; } - if (!crtc_ctx->crc_info.crc[i].crc_ready) - all_crc_ready = false; - if (reset_crc_frame_count[i] || crtc_ctx->crc_info.crc[i].frame_count == UINT_MAX) /* Reset the reference frame count after user update the ROI * or it reaches the maximum value. @@ -948,9 +944,6 @@ void amdgpu_dm_crtc_handle_crc_window_irq(struct drm_crtc *crtc) crtc_ctx->crc_info.crc[i].frame_count += 1; } spin_unlock_irqrestore(&crtc_ctx->crc_info.lock, flags1); - - if (all_crc_ready) - complete_all(&crtc_ctx->crc_info.completion); } void amdgpu_dm_crtc_secure_display_create_contexts(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h index 95bdb8699d7f..8538513ea879 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h @@ -70,7 +70,6 @@ struct crc_data { struct crc_info { struct crc_data crc[MAX_CRC_WINDOW_NUM]; - struct completion completion; spinlock_t lock; }; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c index 304437c2284d..c3c588294665 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c @@ -124,37 +124,37 @@ bool amdgpu_dm_crtc_vrr_active(const struct dm_crtc_state *dm_state) * - Enable condition same as above * - Disable when vblank counter is enabled */ -static void amdgpu_dm_crtc_set_panel_sr_feature( - struct vblank_control_work *vblank_work, +void amdgpu_dm_crtc_set_panel_sr_feature( + struct amdgpu_display_manager *dm, + struct amdgpu_crtc *acrtc, + struct dc_stream_state *stream, bool vblank_enabled, bool allow_sr_entry) { - struct dc_link *link = vblank_work->stream->link; + struct dc_link *link = stream->link; bool is_sr_active = (link->replay_settings.replay_allow_active || link->psr_settings.psr_allow_active); bool is_crc_window_active = false; - bool vrr_active = amdgpu_dm_crtc_vrr_active_irq(vblank_work->acrtc); + bool vrr_active = amdgpu_dm_crtc_vrr_active_irq(acrtc); #ifdef CONFIG_DRM_AMD_SECURE_DISPLAY is_crc_window_active = - amdgpu_dm_crc_window_is_activated(&vblank_work->acrtc->base); + amdgpu_dm_crc_window_is_activated(&acrtc->base); #endif if (link->replay_settings.replay_feature_enabled && !vrr_active && allow_sr_entry && !is_sr_active && !is_crc_window_active) { - amdgpu_dm_replay_enable(vblank_work->stream, true); + amdgpu_dm_replay_enable(stream, true); } else if (vblank_enabled) { if (link->psr_settings.psr_version < DC_PSR_VERSION_SU_1 && is_sr_active) - amdgpu_dm_psr_disable(vblank_work->stream, false); + amdgpu_dm_psr_disable(stream, false); } else if (link->psr_settings.psr_feature_enabled && !vrr_active && allow_sr_entry && !is_sr_active && !is_crc_window_active) { struct amdgpu_dm_connector *aconn = - (struct amdgpu_dm_connector *) vblank_work->stream->dm_stream_context; + (struct amdgpu_dm_connector *) stream->dm_stream_context; if (!aconn->disallow_edp_enter_psr) { - struct amdgpu_display_manager *dm = vblank_work->dm; - - amdgpu_dm_psr_enable(vblank_work->stream); + amdgpu_dm_psr_enable(stream); if (dm->idle_workqueue && (dm->dc->config.disable_ips == DMUB_IPS_ENABLE) && dm->dc->idle_optimizations_allowed && @@ -251,33 +251,15 @@ static void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *work) mutex_lock(&dm->dc_lock); - if (vblank_work->enable) + if (vblank_work->enable) { dm->active_vblank_irq_count++; - else if (dm->active_vblank_irq_count) - dm->active_vblank_irq_count--; - - if (dm->active_vblank_irq_count > 0) - dc_allow_idle_optimizations(dm->dc, false); - - /* - * Control PSR based on vblank requirements from OS - * - * If panel supports PSR SU, there's no need to disable PSR when OS is - * submitting fast atomic commits (we infer this by whether the OS - * requests vblank events). Fast atomic commits will simply trigger a - * full-frame-update (FFU); a specific case of selective-update (SU) - * where the SU region is the full hactive*vactive region. See - * fill_dc_dirty_rects(). - */ - if (vblank_work->stream && vblank_work->stream->link && vblank_work->acrtc) { - amdgpu_dm_crtc_set_panel_sr_feature( - vblank_work, vblank_work->enable, - vblank_work->acrtc->dm_irq_params.allow_sr_entry); - } - - if (dm->active_vblank_irq_count == 0) { - dc_post_update_surfaces_to_stream(dm->dc); - dc_allow_idle_optimizations(dm->dc, true); + amdgpu_dm_ism_commit_event(&vblank_work->acrtc->ism, + DM_ISM_EVENT_EXIT_IDLE_REQUESTED); + } else { + if (dm->active_vblank_irq_count > 0) + dm->active_vblank_irq_count--; + amdgpu_dm_ism_commit_event(&vblank_work->acrtc->ism, + DM_ISM_EVENT_ENTER_IDLE_REQUESTED); } mutex_unlock(&dm->dc_lock); @@ -476,6 +458,9 @@ static struct drm_crtc_state *amdgpu_dm_crtc_duplicate_state(struct drm_crtc *cr static void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + + amdgpu_dm_ism_fini(&acrtc->ism); drm_crtc_cleanup(crtc); kfree(crtc); } @@ -719,6 +704,35 @@ static const struct drm_crtc_helper_funcs amdgpu_dm_crtc_helper_funcs = { .get_scanout_position = amdgpu_crtc_get_scanout_position, }; +/* + * This hysteresis filter as configured will: + * + * * Search through the latest 8[filter_history_size] entries in history, + * skipping entries that are older than [filter_old_history_threshold] frames + * (0 means ignore age) + * * Searches for short-idle-periods that lasted shorter than + * 4[filter_num_frames] frames-times + * * If there is at least 1[filter_entry_count] short-idle-period, then a delay + * of 4[activation_num_delay_frames] will applied before allowing idle + * optimizations again. + * * An additional delay of 11[sso_num_frames] is applied before enabling + * panel-specific optimizations. + * + * The values were determined empirically on another OS, optimizing for Z8 + * residency on APUs when running a productivity + web browsing test. + * + * TODO: Run similar tests to determine if these values are also optimal for + * Linux, and if each APU generation benefits differently. + */ +static struct amdgpu_dm_ism_config default_ism_config = { + .filter_num_frames = 4, + .filter_history_size = 8, + .filter_entry_count = 1, + .activation_num_delay_frames = 4, + .filter_old_history_threshold = 0, + .sso_num_frames = 11, +}; + int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, struct drm_plane *plane, uint32_t crtc_index) @@ -749,6 +763,8 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, if (res) goto fail; + amdgpu_dm_ism_init(&acrtc->ism, &default_ism_config); + drm_crtc_helper_add(&acrtc->base, &amdgpu_dm_crtc_helper_funcs); /* Create (reset) the plane state */ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h index c1212947a77b..3a8094013a5d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h @@ -27,6 +27,12 @@ #ifndef __AMDGPU_DM_CRTC_H__ #define __AMDGPU_DM_CRTC_H__ +void amdgpu_dm_crtc_set_panel_sr_feature( + struct amdgpu_display_manager *dm, + struct amdgpu_crtc *acrtc, + struct dc_stream_state *stream, + bool vblank_enabled, bool allow_sr_entry); + void amdgpu_dm_crtc_handle_vblank(struct amdgpu_crtc *acrtc); bool amdgpu_dm_crtc_modeset_required(struct drm_crtc_state *crtc_state, diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 24bc2a86904b..2409ac72b166 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -3305,6 +3305,52 @@ static int disallow_edp_enter_psr_set(void *data, u64 val) return 0; } +/* check if kernel disallow eDP enter replay state + * cat /sys/kernel/debug/dri/0/eDP-X/disallow_edp_enter_replay + * 0: allow edp enter replay; 1: disallow + */ +static int disallow_edp_enter_replay_get(void *data, u64 *val) +{ + struct amdgpu_dm_connector *aconnector = data; + + *val = (u64) aconnector->disallow_edp_enter_replay; + return 0; +} + +/* set kernel disallow eDP enter replay state + * echo 0x0 /sys/kernel/debug/dri/0/eDP-X/disallow_edp_enter_replay + * 0: allow edp enter replay; 1: disallow + * + * usage: test app read crc from PSR eDP rx. + * + * during kernel boot up, kernel write dpcd 0x37b to + * notify eDP rx replay enable. + * rx fw will start checking crc for rx internal logic. + * crc read count within dpcd 0x246 is not updated and + * value is 0. when eDP tx driver wants to read rx crc + * from dpcd 0x246, 0x270, read count 0 lead tx driver + * timeout. + * + * to avoid this, we add this debugfs to let test app to disbable + * rx replay. then test app can read non-zero crc read count. + * + * expected app sequence is as below: + * 1. disable eDP PHY and notify eDP rx with dpcd 0x600 = 2. + * 2. echo 0x1 /sys/kernel/debug/dri/0/eDP-X/disallow_edp_enter_replay + * 3. enable eDP PHY and notify eDP rx with dpcd 0x600 = 1 but + * without programming dpcd 0x37b. + * 4. read crc from rx dpcd 0x270, 0x246, etc. + * 5. echo 0x0 /sys/kernel/debug/dri/0/eDP-X/disallow_edp_enter_replay. + * this will let eDP back to normal with replay setup dpcd 0x37b. + */ +static int disallow_edp_enter_replay_set(void *data, u64 val) +{ + struct amdgpu_dm_connector *aconnector = data; + + aconnector->disallow_edp_enter_replay = val ? true : false; + return 0; +} + static int dmub_trace_mask_set(void *data, u64 val) { struct amdgpu_device *adev = data; @@ -3433,6 +3479,10 @@ DEFINE_DEBUGFS_ATTRIBUTE(disallow_edp_enter_psr_fops, disallow_edp_enter_psr_get, disallow_edp_enter_psr_set, "%llu\n"); +DEFINE_DEBUGFS_ATTRIBUTE(disallow_edp_enter_replay_fops, + disallow_edp_enter_replay_get, + disallow_edp_enter_replay_set, "%llu\n"); + DEFINE_DEBUGFS_ATTRIBUTE(ips_residency_cntl_fops, ips_residency_cntl_get, ips_residency_cntl_set, "%llu\n"); DEFINE_SHOW_ATTRIBUTE(current_backlight); @@ -3635,6 +3685,8 @@ void connector_debugfs_init(struct amdgpu_dm_connector *connector) &allow_edp_hotplug_detection_fops); debugfs_create_file("disallow_edp_enter_psr", 0644, dir, connector, &disallow_edp_enter_psr_fops); + debugfs_create_file("disallow_edp_enter_replay", 0644, dir, connector, + &disallow_edp_enter_replay_fops); } for (i = 0; i < ARRAY_SIZE(connector_debugfs_entries); i++) { 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 a09761f9882d..f3fa8eb4bcce 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 @@ -1016,6 +1016,9 @@ enum dc_edid_status dm_helpers_read_local_edid( else ddc = &aconnector->i2c->base; + if (link->dc->hwss.prepare_ddc) + link->dc->hwss.prepare_ddc(link); + /* some dongles read edid incorrectly the first time, * do check sum and retry to make sure read correct edid. */ @@ -1162,9 +1165,9 @@ void dm_helpers_override_panel_settings( link->panel_config.dsc.disable_dsc_edp = true; if (dc_get_edp_link_panel_inst(ctx->dc, link, &panel_inst) && panel_inst == 1) { - link->panel_config.psr.disable_psr = true; - link->panel_config.psr.disallow_psrsu = true;; - link->panel_config.psr.disallow_replay = true; + link->panel_config.psr.disable_psr = true; + link->panel_config.psr.disallow_psrsu = true; + link->panel_config.psr.disallow_replay = true; } } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.c new file mode 100644 index 000000000000..65a5cfe1e106 --- /dev/null +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.c @@ -0,0 +1,598 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright 2026 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include <linux/types.h> +#include <drm/drm_vblank.h> + +#include "dc.h" +#include "amdgpu.h" +#include "amdgpu_dm_ism.h" +#include "amdgpu_dm_crtc.h" +#include "amdgpu_dm_trace.h" + +/** + * dm_ism_next_state - Get next state based on current state and event + * + * This function defines the idle state management FSM. Invalid transitions + * are ignored and will not progress the FSM. + */ +static bool dm_ism_next_state(enum amdgpu_dm_ism_state current_state, + enum amdgpu_dm_ism_event event, + enum amdgpu_dm_ism_state *next_state) +{ + switch (STATE_EVENT(current_state, event)) { + case STATE_EVENT(DM_ISM_STATE_FULL_POWER_RUNNING, + DM_ISM_EVENT_ENTER_IDLE_REQUESTED): + *next_state = DM_ISM_STATE_HYSTERESIS_WAITING; + break; + case STATE_EVENT(DM_ISM_STATE_FULL_POWER_RUNNING, + DM_ISM_EVENT_BEGIN_CURSOR_UPDATE): + *next_state = DM_ISM_STATE_FULL_POWER_BUSY; + break; + + case STATE_EVENT(DM_ISM_STATE_FULL_POWER_BUSY, + DM_ISM_EVENT_ENTER_IDLE_REQUESTED): + *next_state = DM_ISM_STATE_HYSTERESIS_BUSY; + break; + case STATE_EVENT(DM_ISM_STATE_FULL_POWER_BUSY, + DM_ISM_EVENT_END_CURSOR_UPDATE): + *next_state = DM_ISM_STATE_FULL_POWER_RUNNING; + break; + + case STATE_EVENT(DM_ISM_STATE_HYSTERESIS_WAITING, + DM_ISM_EVENT_EXIT_IDLE_REQUESTED): + *next_state = DM_ISM_STATE_TIMER_ABORTED; + break; + case STATE_EVENT(DM_ISM_STATE_HYSTERESIS_WAITING, + DM_ISM_EVENT_BEGIN_CURSOR_UPDATE): + *next_state = DM_ISM_STATE_HYSTERESIS_BUSY; + break; + case STATE_EVENT(DM_ISM_STATE_HYSTERESIS_WAITING, + DM_ISM_EVENT_TIMER_ELAPSED): + *next_state = DM_ISM_STATE_OPTIMIZED_IDLE; + break; + case STATE_EVENT(DM_ISM_STATE_HYSTERESIS_WAITING, + DM_ISM_EVENT_IMMEDIATE): + *next_state = DM_ISM_STATE_OPTIMIZED_IDLE; + break; + + case STATE_EVENT(DM_ISM_STATE_HYSTERESIS_BUSY, + DM_ISM_EVENT_EXIT_IDLE_REQUESTED): + *next_state = DM_ISM_STATE_FULL_POWER_BUSY; + break; + case STATE_EVENT(DM_ISM_STATE_HYSTERESIS_BUSY, + DM_ISM_EVENT_END_CURSOR_UPDATE): + *next_state = DM_ISM_STATE_HYSTERESIS_WAITING; + break; + + case STATE_EVENT(DM_ISM_STATE_OPTIMIZED_IDLE, + DM_ISM_EVENT_EXIT_IDLE_REQUESTED): + *next_state = DM_ISM_STATE_FULL_POWER_RUNNING; + break; + case STATE_EVENT(DM_ISM_STATE_OPTIMIZED_IDLE, + DM_ISM_EVENT_BEGIN_CURSOR_UPDATE): + *next_state = DM_ISM_STATE_HYSTERESIS_BUSY; + break; + case STATE_EVENT(DM_ISM_STATE_OPTIMIZED_IDLE, + DM_ISM_EVENT_SSO_TIMER_ELAPSED): + case STATE_EVENT(DM_ISM_STATE_OPTIMIZED_IDLE, + DM_ISM_EVENT_IMMEDIATE): + *next_state = DM_ISM_STATE_OPTIMIZED_IDLE_SSO; + break; + + case STATE_EVENT(DM_ISM_STATE_OPTIMIZED_IDLE_SSO, + DM_ISM_EVENT_EXIT_IDLE_REQUESTED): + *next_state = DM_ISM_STATE_FULL_POWER_RUNNING; + break; + case STATE_EVENT(DM_ISM_STATE_OPTIMIZED_IDLE_SSO, + DM_ISM_EVENT_BEGIN_CURSOR_UPDATE): + *next_state = DM_ISM_STATE_HYSTERESIS_BUSY; + break; + + case STATE_EVENT(DM_ISM_STATE_TIMER_ABORTED, + DM_ISM_EVENT_IMMEDIATE): + *next_state = DM_ISM_STATE_FULL_POWER_RUNNING; + break; + + default: + return false; + } + return true; +} + +static uint64_t dm_ism_get_sso_delay(const struct amdgpu_dm_ism *ism, + const struct dc_stream_state *stream) +{ + const struct amdgpu_dm_ism_config *config = &ism->config; + uint32_t v_total, h_total; + uint64_t one_frame_ns, sso_delay_ns; + + if (!stream) + return 0; + + if (!config->sso_num_frames) + return 0; + + v_total = stream->timing.v_total; + h_total = stream->timing.h_total; + + one_frame_ns = div64_u64(v_total * h_total * 10000000ull, + stream->timing.pix_clk_100hz); + sso_delay_ns = config->sso_num_frames * one_frame_ns; + + return sso_delay_ns; +} + +/** + * dm_ism_get_idle_allow_delay - Calculate hysteresis-based idle allow delay + */ +static uint64_t dm_ism_get_idle_allow_delay(const struct amdgpu_dm_ism *ism, + const struct dc_stream_state *stream) +{ + const struct amdgpu_dm_ism_config *config = &ism->config; + uint32_t v_total, h_total; + uint64_t one_frame_ns, short_idle_ns, old_hist_ns; + uint32_t history_size; + int pos; + uint32_t short_idle_count = 0; + uint64_t ret_ns = 0; + + if (!stream) + return 0; + + if (!config->filter_num_frames) + return 0; + if (!config->filter_entry_count) + return 0; + if (!config->activation_num_delay_frames) + return 0; + + v_total = stream->timing.v_total; + h_total = stream->timing.h_total; + + one_frame_ns = div64_u64(v_total * h_total * 10000000ull, + stream->timing.pix_clk_100hz); + + short_idle_ns = config->filter_num_frames * one_frame_ns; + old_hist_ns = config->filter_old_history_threshold * one_frame_ns; + + /* + * Look back into the recent history and count how many times we entered + * idle power state for a short duration of time + */ + history_size = min( + max(config->filter_history_size, config->filter_entry_count), + AMDGPU_DM_IDLE_HIST_LEN); + pos = ism->next_record_idx; + + for (int k = 0; k < history_size; k++) { + if (pos <= 0 || pos > AMDGPU_DM_IDLE_HIST_LEN) + pos = AMDGPU_DM_IDLE_HIST_LEN; + pos -= 1; + + if (ism->records[pos].duration_ns <= short_idle_ns) + short_idle_count += 1; + + if (short_idle_count >= config->filter_entry_count) + break; + + if (old_hist_ns > 0 && + ism->last_idle_timestamp_ns - ism->records[pos].timestamp_ns > old_hist_ns) + break; + } + + if (short_idle_count >= config->filter_entry_count) + ret_ns = config->activation_num_delay_frames * one_frame_ns; + + return ret_ns; +} + +/** + * dm_ism_insert_record - Insert a record into the circular history buffer + */ +static void dm_ism_insert_record(struct amdgpu_dm_ism *ism) +{ + struct amdgpu_dm_ism_record *record; + + if (ism->next_record_idx < 0 || + ism->next_record_idx >= AMDGPU_DM_IDLE_HIST_LEN) + ism->next_record_idx = 0; + + record = &ism->records[ism->next_record_idx]; + ism->next_record_idx += 1; + + record->timestamp_ns = ktime_get_ns(); + record->duration_ns = + record->timestamp_ns - ism->last_idle_timestamp_ns; +} + + +static void dm_ism_set_last_idle_ts(struct amdgpu_dm_ism *ism) +{ + ism->last_idle_timestamp_ns = ktime_get_ns(); +} + + +static bool dm_ism_trigger_event(struct amdgpu_dm_ism *ism, + enum amdgpu_dm_ism_event event) +{ + enum amdgpu_dm_ism_state next_state; + + bool gotNextState = dm_ism_next_state(ism->current_state, event, + &next_state); + + if (gotNextState) { + ism->previous_state = ism->current_state; + ism->current_state = next_state; + } + + return gotNextState; +} + + +static void dm_ism_commit_idle_optimization_state(struct amdgpu_dm_ism *ism, + struct dc_stream_state *stream, + bool vblank_enabled, + bool allow_panel_sso) +{ + struct amdgpu_crtc *acrtc = ism_to_amdgpu_crtc(ism); + struct amdgpu_device *adev = drm_to_adev(acrtc->base.dev); + struct amdgpu_display_manager *dm = &adev->dm; + int r; + + trace_amdgpu_dm_ism_commit(dm->active_vblank_irq_count, + vblank_enabled, + allow_panel_sso); + + /* + * If there is an active vblank requestor, or if SSO is being engaged, + * then disallow idle optimizations. + */ + if (vblank_enabled || allow_panel_sso) + dc_allow_idle_optimizations(dm->dc, false); + + /* + * Control PSR based on vblank requirements from OS + * + * If panel supports PSR SU/Replay, there's no need to exit self-refresh + * when OS is submitting fast atomic commits, as they can allow + * self-refresh during vblank periods. + */ + if (stream && stream->link) { + /* + * If allow_panel_sso is true when disabling vblank, allow + * deeper panel sleep states such as PSR1 and Replay static + * screen optimization. + */ + if (!vblank_enabled && allow_panel_sso) { + amdgpu_dm_crtc_set_panel_sr_feature( + dm, acrtc, stream, false, + acrtc->dm_irq_params.allow_sr_entry); + } else if (vblank_enabled) { + /* Make sure to exit SSO on vblank enable */ + amdgpu_dm_crtc_set_panel_sr_feature( + dm, acrtc, stream, true, + acrtc->dm_irq_params.allow_sr_entry); + } + /* + * Else, vblank_enabled == false and allow_panel_sso == false; + * do nothing here. + */ + } + + /* + * Check for any active drm vblank requestors on other CRTCs + * (dm->active_vblank_irq_count) before allowing HW-wide idle + * optimizations. + * + * There's no need to have a "balanced" check when disallowing idle + * optimizations at the start of this func -- we should disallow + * whenever there's *an* active CRTC. + */ + if (!vblank_enabled && dm->active_vblank_irq_count == 0) { + dc_post_update_surfaces_to_stream(dm->dc); + + r = amdgpu_dpm_pause_power_profile(adev, true); + if (r) + dev_warn(adev->dev, "failed to set default power profile mode\n"); + + dc_allow_idle_optimizations(dm->dc, true); + + r = amdgpu_dpm_pause_power_profile(adev, false); + if (r) + dev_warn(adev->dev, "failed to restore the power profile mode\n"); + } +} + + +static enum amdgpu_dm_ism_event dm_ism_dispatch_power_state( + struct amdgpu_dm_ism *ism, + struct dm_crtc_state *acrtc_state, + enum amdgpu_dm_ism_event event) +{ + enum amdgpu_dm_ism_event ret = event; + const struct amdgpu_dm_ism_config *config = &ism->config; + uint64_t delay_ns, sso_delay_ns; + + switch (ism->previous_state) { + case DM_ISM_STATE_HYSTERESIS_WAITING: + /* + * Stop the timer if it was set, and we're not running from the + * idle allow worker. + */ + if (ism->current_state != DM_ISM_STATE_OPTIMIZED_IDLE && + ism->current_state != DM_ISM_STATE_OPTIMIZED_IDLE_SSO) + cancel_delayed_work(&ism->delayed_work); + break; + case DM_ISM_STATE_OPTIMIZED_IDLE: + if (ism->current_state == DM_ISM_STATE_OPTIMIZED_IDLE_SSO) + break; + /* If idle disallow, cancel SSO work and insert record */ + cancel_delayed_work(&ism->sso_delayed_work); + dm_ism_insert_record(ism); + dm_ism_commit_idle_optimization_state(ism, acrtc_state->stream, + true, false); + break; + case DM_ISM_STATE_OPTIMIZED_IDLE_SSO: + /* Disable idle optimization */ + dm_ism_insert_record(ism); + dm_ism_commit_idle_optimization_state(ism, acrtc_state->stream, + true, false); + break; + default: + break; + } + + switch (ism->current_state) { + case DM_ISM_STATE_HYSTERESIS_WAITING: + dm_ism_set_last_idle_ts(ism); + + /* CRTC can be disabled; allow immediate idle */ + if (!acrtc_state->stream) { + ret = DM_ISM_EVENT_IMMEDIATE; + break; + } + + delay_ns = dm_ism_get_idle_allow_delay(ism, + acrtc_state->stream); + if (delay_ns == 0) { + ret = DM_ISM_EVENT_IMMEDIATE; + break; + } + + /* Schedule worker */ + mod_delayed_work(system_unbound_wq, &ism->delayed_work, + nsecs_to_jiffies(delay_ns)); + + break; + case DM_ISM_STATE_OPTIMIZED_IDLE: + sso_delay_ns = dm_ism_get_sso_delay(ism, acrtc_state->stream); + if (sso_delay_ns == 0) + ret = DM_ISM_EVENT_IMMEDIATE; + else if (config->sso_num_frames < config->filter_num_frames) { + /* + * If sso_num_frames is less than hysteresis frames, it + * indicates that allowing idle here, then disallowing + * idle after sso_num_frames has expired, will likely + * have a negative power impact. Skip idle allow here, + * and let the sso_delayed_work handle it. + */ + mod_delayed_work(system_unbound_wq, + &ism->sso_delayed_work, + nsecs_to_jiffies(sso_delay_ns)); + } else { + /* Enable idle optimization without SSO */ + dm_ism_commit_idle_optimization_state( + ism, acrtc_state->stream, false, false); + mod_delayed_work(system_unbound_wq, + &ism->sso_delayed_work, + nsecs_to_jiffies(sso_delay_ns)); + } + break; + case DM_ISM_STATE_OPTIMIZED_IDLE_SSO: + /* Enable static screen optimizations. */ + dm_ism_commit_idle_optimization_state(ism, acrtc_state->stream, + false, true); + break; + case DM_ISM_STATE_TIMER_ABORTED: + dm_ism_insert_record(ism); + dm_ism_commit_idle_optimization_state(ism, acrtc_state->stream, + true, false); + ret = DM_ISM_EVENT_IMMEDIATE; + break; + default: + break; + } + + return ret; +} + +static char *dm_ism_events_str[DM_ISM_NUM_EVENTS] = { + [DM_ISM_EVENT_IMMEDIATE] = "IMMEDIATE", + [DM_ISM_EVENT_ENTER_IDLE_REQUESTED] = "ENTER_IDLE_REQUESTED", + [DM_ISM_EVENT_EXIT_IDLE_REQUESTED] = "EXIT_IDLE_REQUESTED", + [DM_ISM_EVENT_BEGIN_CURSOR_UPDATE] = "BEGIN_CURSOR_UPDATE", + [DM_ISM_EVENT_END_CURSOR_UPDATE] = "END_CURSOR_UPDATE", + [DM_ISM_EVENT_TIMER_ELAPSED] = "TIMER_ELAPSED", + [DM_ISM_EVENT_SSO_TIMER_ELAPSED] = "SSO_TIMER_ELAPSED", +}; + +static char *dm_ism_states_str[DM_ISM_NUM_STATES] = { + [DM_ISM_STATE_FULL_POWER_RUNNING] = "FULL_POWER_RUNNING", + [DM_ISM_STATE_FULL_POWER_BUSY] = "FULL_POWER_BUSY", + [DM_ISM_STATE_HYSTERESIS_WAITING] = "HYSTERESIS_WAITING", + [DM_ISM_STATE_HYSTERESIS_BUSY] = "HYSTERESIS_BUSY", + [DM_ISM_STATE_OPTIMIZED_IDLE] = "OPTIMIZED_IDLE", + [DM_ISM_STATE_OPTIMIZED_IDLE_SSO] = "OPTIMIZED_IDLE_SSO", + [DM_ISM_STATE_TIMER_ABORTED] = "TIMER_ABORTED", +}; + + +void amdgpu_dm_ism_commit_event(struct amdgpu_dm_ism *ism, + enum amdgpu_dm_ism_event event) +{ + enum amdgpu_dm_ism_event next_event = event; + struct amdgpu_crtc *acrtc = ism_to_amdgpu_crtc(ism); + struct amdgpu_device *adev = drm_to_adev(acrtc->base.dev); + struct amdgpu_display_manager *dm = &adev->dm; + struct dm_crtc_state *acrtc_state = to_dm_crtc_state(acrtc->base.state); + + /* ISM transitions must be called with mutex acquired */ + ASSERT(mutex_is_locked(&dm->dc_lock)); + + if (!acrtc_state) { + trace_amdgpu_dm_ism_event(acrtc->crtc_id, "NO_STATE", + "NO_STATE", "N/A"); + return; + } + + do { + bool transition = dm_ism_trigger_event(ism, event); + + next_event = DM_ISM_NUM_EVENTS; + if (transition) { + trace_amdgpu_dm_ism_event( + acrtc->crtc_id, + dm_ism_states_str[ism->previous_state], + dm_ism_states_str[ism->current_state], + dm_ism_events_str[event]); + next_event = dm_ism_dispatch_power_state( + ism, acrtc_state, next_event); + } else { + trace_amdgpu_dm_ism_event( + acrtc->crtc_id, + dm_ism_states_str[ism->current_state], + dm_ism_states_str[ism->current_state], + dm_ism_events_str[event]); + } + + event = next_event; + + } while (next_event < DM_ISM_NUM_EVENTS); +} + + +static void dm_ism_delayed_work_func(struct work_struct *work) +{ + struct amdgpu_dm_ism *ism = + container_of(work, struct amdgpu_dm_ism, delayed_work.work); + struct amdgpu_crtc *acrtc = ism_to_amdgpu_crtc(ism); + struct amdgpu_device *adev = drm_to_adev(acrtc->base.dev); + struct amdgpu_display_manager *dm = &adev->dm; + + guard(mutex)(&dm->dc_lock); + + amdgpu_dm_ism_commit_event(ism, DM_ISM_EVENT_TIMER_ELAPSED); +} + +static void dm_ism_sso_delayed_work_func(struct work_struct *work) +{ + struct amdgpu_dm_ism *ism = + container_of(work, struct amdgpu_dm_ism, sso_delayed_work.work); + struct amdgpu_crtc *acrtc = ism_to_amdgpu_crtc(ism); + struct amdgpu_device *adev = drm_to_adev(acrtc->base.dev); + struct amdgpu_display_manager *dm = &adev->dm; + + guard(mutex)(&dm->dc_lock); + + amdgpu_dm_ism_commit_event(ism, DM_ISM_EVENT_SSO_TIMER_ELAPSED); +} + +/** + * amdgpu_dm_ism_disable - Disable the ISM + * + * @dm: The amdgpu display manager + * + * Disable the idle state manager by disabling any ISM work, canceling pending + * work, and waiting for in-progress work to finish. After disabling, the system + * is left in DM_ISM_STATE_FULL_POWER_RUNNING state. + */ +void amdgpu_dm_ism_disable(struct amdgpu_display_manager *dm) +{ + struct drm_crtc *crtc; + struct amdgpu_crtc *acrtc; + struct amdgpu_dm_ism *ism; + + drm_for_each_crtc(crtc, dm->ddev) { + acrtc = to_amdgpu_crtc(crtc); + ism = &acrtc->ism; + + /* Cancel and disable any pending work */ + disable_delayed_work_sync(&ism->delayed_work); + disable_delayed_work_sync(&ism->sso_delayed_work); + + /* + * When disabled, leave in FULL_POWER_RUNNING state. + * EXIT_IDLE will not queue any work + */ + amdgpu_dm_ism_commit_event(ism, + DM_ISM_EVENT_EXIT_IDLE_REQUESTED); + } +} + +/** + * amdgpu_dm_ism_enable - enable the ISM + * + * @dm: The amdgpu display manager + * + * Re-enable the idle state manager by enabling work that was disabled by + * amdgpu_dm_ism_disable. + */ +void amdgpu_dm_ism_enable(struct amdgpu_display_manager *dm) +{ + struct drm_crtc *crtc; + struct amdgpu_crtc *acrtc; + struct amdgpu_dm_ism *ism; + + drm_for_each_crtc(crtc, dm->ddev) { + acrtc = to_amdgpu_crtc(crtc); + ism = &acrtc->ism; + + enable_delayed_work(&ism->delayed_work); + enable_delayed_work(&ism->sso_delayed_work); + } +} + +void amdgpu_dm_ism_init(struct amdgpu_dm_ism *ism, + struct amdgpu_dm_ism_config *config) +{ + ism->config = *config; + + ism->current_state = DM_ISM_STATE_FULL_POWER_RUNNING; + ism->previous_state = DM_ISM_STATE_FULL_POWER_RUNNING; + ism->next_record_idx = 0; + ism->last_idle_timestamp_ns = 0; + + INIT_DELAYED_WORK(&ism->delayed_work, dm_ism_delayed_work_func); + INIT_DELAYED_WORK(&ism->sso_delayed_work, dm_ism_sso_delayed_work_func); +} + + +void amdgpu_dm_ism_fini(struct amdgpu_dm_ism *ism) +{ + cancel_delayed_work_sync(&ism->sso_delayed_work); + cancel_delayed_work_sync(&ism->delayed_work); +} diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.h new file mode 100644 index 000000000000..fde0ddc8d4e4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.h @@ -0,0 +1,151 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2026 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __AMDGPU_DM_ISM_H__ +#define __AMDGPU_DM_ISM_H__ + +#include <linux/workqueue.h> + +struct amdgpu_crtc; +struct amdgpu_display_manager; + +#define AMDGPU_DM_IDLE_HIST_LEN 16 + +enum amdgpu_dm_ism_state { + DM_ISM_STATE_FULL_POWER_RUNNING, + DM_ISM_STATE_FULL_POWER_BUSY, + DM_ISM_STATE_HYSTERESIS_WAITING, + DM_ISM_STATE_HYSTERESIS_BUSY, + DM_ISM_STATE_OPTIMIZED_IDLE, + DM_ISM_STATE_OPTIMIZED_IDLE_SSO, + DM_ISM_STATE_TIMER_ABORTED, + DM_ISM_NUM_STATES, +}; + +enum amdgpu_dm_ism_event { + DM_ISM_EVENT_IMMEDIATE, + DM_ISM_EVENT_ENTER_IDLE_REQUESTED, + DM_ISM_EVENT_EXIT_IDLE_REQUESTED, + DM_ISM_EVENT_BEGIN_CURSOR_UPDATE, + DM_ISM_EVENT_END_CURSOR_UPDATE, + DM_ISM_EVENT_TIMER_ELAPSED, + DM_ISM_EVENT_SSO_TIMER_ELAPSED, + DM_ISM_NUM_EVENTS, +}; + +#define STATE_EVENT(state, event) (((state) << 8) | (event)) + +struct amdgpu_dm_ism_config { + + /** + * @filter_num_frames: Idle periods shorter than this number of frames + * will be considered a "short idle period" for filtering. + * + * 0 indicates no filtering (i.e. no idle allow delay will be applied) + */ + unsigned int filter_num_frames; + + /** + * @filter_history_size: Number of recent idle periods to consider when + * counting the number of short idle periods. + */ + unsigned int filter_history_size; + + /** + * @filter_entry_count: When the number of short idle periods within + * recent &filter_history_size reaches this count, the idle allow delay + * will be applied. + * + * 0 indicates no filtering (i.e. no idle allow delay will be applied) + */ + unsigned int filter_entry_count; + + /** + * @activation_num_delay_frames: Defines the number of frames to wait + * for the idle allow delay. + * + * 0 indicates no filtering (i.e. no idle allow delay will be applied) + */ + unsigned int activation_num_delay_frames; + + /** + * @filter_old_history_threshold: A time-based restriction on top of + * &filter_history_size. Idle periods older than this threshold (in + * number of frames) will be ignored when counting the number of short + * idle periods. + * + * 0 indicates no time-based restriction, i.e. history is limited only + * by &filter_history_size. + */ + unsigned int filter_old_history_threshold; + + /** + * @sso_num_frames: Number of frames to delay before enabling static + * screen optimizations, such as PSR1 and Replay low HZ idle mode. + * + * 0 indicates immediate SSO enable upon allowing idle. + */ + unsigned int sso_num_frames; +}; + +struct amdgpu_dm_ism_record { + /** + * @timestamp_ns: When idle was allowed + */ + unsigned long long timestamp_ns; + + /** + * @duration_ns: How long idle was allowed + */ + unsigned long long duration_ns; +}; + +struct amdgpu_dm_ism { + struct amdgpu_dm_ism_config config; + unsigned long long last_idle_timestamp_ns; + + enum amdgpu_dm_ism_state current_state; + enum amdgpu_dm_ism_state previous_state; + + struct amdgpu_dm_ism_record records[AMDGPU_DM_IDLE_HIST_LEN]; + int next_record_idx; + + struct delayed_work delayed_work; + struct delayed_work sso_delayed_work; +}; + +#define ism_to_amdgpu_crtc(ism_ptr) \ + container_of(ism_ptr, struct amdgpu_crtc, ism) + +void amdgpu_dm_ism_init(struct amdgpu_dm_ism *ism, + struct amdgpu_dm_ism_config *config); +void amdgpu_dm_ism_fini(struct amdgpu_dm_ism *ism); +void amdgpu_dm_ism_commit_event(struct amdgpu_dm_ism *ism, + enum amdgpu_dm_ism_event event); +void amdgpu_dm_ism_disable(struct amdgpu_display_manager *dm); +void amdgpu_dm_ism_enable(struct amdgpu_display_manager *dm); + +#endif diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c index 127207e18dcb..81e43534ec59 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT /* - * Copyright 2022 Advanced Micro Devices, Inc. + * Copyright 2022-2026 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -704,21 +704,21 @@ static void amdgpu_dm_plane_add_gfx12_modifiers(struct amdgpu_device *adev, uint8_t max_comp_block[] = {2, 1, 0}; uint64_t max_comp_block_mod[ARRAY_SIZE(max_comp_block)] = {0}; uint8_t i = 0, j = 0; - uint64_t gfx12_modifiers[] = {mod_256k, mod_64k, mod_4k, mod_256b, DRM_FORMAT_MOD_LINEAR}; + /* Note, linear (no DCC) gets added to the modifier list for all chips by the caller. */ + uint64_t gfx12_modifiers[] = {mod_256k, mod_64k, mod_4k, mod_256b}; for (i = 0; i < ARRAY_SIZE(max_comp_block); i++) max_comp_block_mod[i] = AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, max_comp_block[i]); /* With DCC: Best choice should be kept first. Hence, add all 256k modifiers of different * max compressed blocks first and then move on to the next smaller sized layouts. - * Do not add the linear modifier here, and hence the condition of size-1 for the loop */ - for (j = 0; j < ARRAY_SIZE(gfx12_modifiers) - 1; j++) + for (j = 0; j < ARRAY_SIZE(gfx12_modifiers); j++) for (i = 0; i < ARRAY_SIZE(max_comp_block); i++) amdgpu_dm_plane_add_modifier(mods, size, capacity, ver | dcc | max_comp_block_mod[i] | gfx12_modifiers[j]); - /* Without DCC. Add all modifiers including linear at the end */ + /* Without DCC. */ for (i = 0; i < ARRAY_SIZE(gfx12_modifiers); i++) amdgpu_dm_plane_add_modifier(mods, size, capacity, gfx12_modifiers[i]); @@ -759,6 +759,7 @@ static int amdgpu_dm_plane_get_plane_modifiers(struct amdgpu_device *adev, unsig case AMDGPU_FAMILY_GC_11_0_0: case AMDGPU_FAMILY_GC_11_0_1: case AMDGPU_FAMILY_GC_11_5_0: + case AMDGPU_FAMILY_GC_11_5_4: amdgpu_dm_plane_add_gfx11_modifiers(adev, mods, &size, &capacity); break; case AMDGPU_FAMILY_GC_12_0_0: @@ -953,11 +954,9 @@ static int amdgpu_dm_plane_helper_prepare_fb(struct drm_plane *plane, return r; } - r = dma_resv_reserve_fences(rbo->tbo.base.resv, 1); - if (r) { - drm_err(adev_to_drm(adev), "reserving fence slot failed (%d)\n", r); + r = dma_resv_reserve_fences(rbo->tbo.base.resv, TTM_NUM_MOVE_FENCES); + if (r) goto error_unlock; - } if (plane->type != DRM_PLANE_TYPE_CURSOR) domain = amdgpu_display_supported_domains(adev, rbo->flags); @@ -1373,8 +1372,16 @@ void amdgpu_dm_plane_handle_cursor_update(struct drm_plane *plane, /* turn off cursor */ if (crtc_state && crtc_state->stream) { mutex_lock(&adev->dm.dc_lock); + amdgpu_dm_ism_commit_event( + &amdgpu_crtc->ism, + DM_ISM_EVENT_BEGIN_CURSOR_UPDATE); + dc_stream_program_cursor_position(crtc_state->stream, &position); + + amdgpu_dm_ism_commit_event( + &amdgpu_crtc->ism, + DM_ISM_EVENT_END_CURSOR_UPDATE); mutex_unlock(&adev->dm.dc_lock); } return; @@ -1404,6 +1411,10 @@ void amdgpu_dm_plane_handle_cursor_update(struct drm_plane *plane, if (crtc_state->stream) { mutex_lock(&adev->dm.dc_lock); + amdgpu_dm_ism_commit_event( + &amdgpu_crtc->ism, + DM_ISM_EVENT_BEGIN_CURSOR_UPDATE); + if (!dc_stream_program_cursor_attributes(crtc_state->stream, &attributes)) DRM_ERROR("DC failed to set cursor attributes\n"); @@ -1411,6 +1422,10 @@ void amdgpu_dm_plane_handle_cursor_update(struct drm_plane *plane, if (!dc_stream_program_cursor_position(crtc_state->stream, &position)) DRM_ERROR("DC failed to set cursor position\n"); + + amdgpu_dm_ism_commit_event( + &amdgpu_crtc->ism, + DM_ISM_EVENT_END_CURSOR_UPDATE); mutex_unlock(&adev->dm.dc_lock); } } @@ -1907,7 +1922,8 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, drm_plane_create_zpos_immutable_property(plane, 255); } - if (plane->type == DRM_PLANE_TYPE_PRIMARY && + if ((plane->type == DRM_PLANE_TYPE_PRIMARY || + plane->type == DRM_PLANE_TYPE_OVERLAY) && plane_cap && (plane_cap->pixel_format_support.nv12 || plane_cap->pixel_format_support.p010)) { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h index aa56fd6d56c3..e0fab8878d19 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h @@ -753,6 +753,69 @@ TRACE_EVENT(amdgpu_dm_brightness, ) ); +TRACE_EVENT(amdgpu_dm_ism_commit, + TP_PROTO( + int active_vblank_irq_count, + bool vblank_enabled, + bool allow_panel_sso + ), + TP_ARGS( + active_vblank_irq_count, + vblank_enabled, + allow_panel_sso + ), + TP_STRUCT__entry( + __field(int, active_vblank_irq_count) + __field(bool, vblank_enabled) + __field(bool, allow_panel_sso) + ), + TP_fast_assign( + __entry->active_vblank_irq_count = active_vblank_irq_count; + __entry->vblank_enabled = vblank_enabled; + __entry->allow_panel_sso = allow_panel_sso; + ), + TP_printk( + "active_vblank_irq_count=%d vblank_enabled=%d allow_panel_sso=%d", + __entry->active_vblank_irq_count, + __entry->vblank_enabled, + __entry->allow_panel_sso + ) +); + +TRACE_EVENT(amdgpu_dm_ism_event, + TP_PROTO( + int crtc_id, + const char *prev_state, + const char *curr_state, + const char *event + ), + TP_ARGS( + crtc_id, + prev_state, + curr_state, + event + ), + TP_STRUCT__entry( + __field(int, crtc_id) + __string(prev_state, prev_state) + __string(curr_state, curr_state) + __string(event, event) + ), + TP_fast_assign( + __entry->crtc_id = crtc_id; + __assign_str(prev_state); + __assign_str(curr_state); + __assign_str(event); + ), + TP_printk( + "[CRTC %d] %s -> %s on event %s", + __entry->crtc_id, + __get_str(prev_state), + __get_str(curr_state), + __get_str(event)) +); + + #endif /* _AMDGPU_DM_TRACE_H_ */ #undef TRACE_INCLUDE_PATH diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c index d9527c05fc87..110f0173eee6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c @@ -106,11 +106,9 @@ static int amdgpu_dm_wb_prepare_job(struct drm_writeback_connector *wb_connector return r; } - r = dma_resv_reserve_fences(rbo->tbo.base.resv, 1); - if (r) { - drm_err(adev_to_drm(adev), "reserving fence slot failed (%d)\n", r); + r = dma_resv_reserve_fences(rbo->tbo.base.resv, TTM_NUM_MOVE_FENCES); + if (r) goto error_unlock; - } domain = amdgpu_display_supported_domains(adev, rbo->flags); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c index e46f8ce41d87..8ba9b4f56f87 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c @@ -53,12 +53,31 @@ inline void dc_assert_fp_enabled(void) { int depth; - depth = __this_cpu_read(fpu_recursion_depth); + depth = this_cpu_read(fpu_recursion_depth); ASSERT(depth >= 1); } /** + * dc_assert_fp_enabled - Check if FPU protection is enabled + * + * This function tells if the code is already under FPU protection or not. A + * function that works as an API for a set of FPU operations can use this + * function for checking if the caller invoked it after DC_FP_START(). For + * example, take a look at dcn20_fpu.c file. + * + * Similar to dc_assert_fp_enabled, but does not assert, returns status instead. + */ +inline bool dc_is_fp_enabled(void) +{ + int depth; + + depth = this_cpu_read(fpu_recursion_depth); + + return (depth >= 1); +} + +/** * dc_fpu_begin - Enables FPU protection * @function_name: A string containing the function name for debug purposes * (usually __func__) @@ -77,7 +96,7 @@ void dc_fpu_begin(const char *function_name, const int line) WARN_ON_ONCE(!in_task()); preempt_disable(); - depth = __this_cpu_inc_return(fpu_recursion_depth); + depth = this_cpu_inc_return(fpu_recursion_depth); if (depth == 1) { BUG_ON(!kernel_fpu_available()); kernel_fpu_begin(); @@ -100,7 +119,7 @@ void dc_fpu_end(const char *function_name, const int line) { int depth; - depth = __this_cpu_dec_return(fpu_recursion_depth); + depth = this_cpu_dec_return(fpu_recursion_depth); if (depth == 0) { kernel_fpu_end(); } else { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.h b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.h index 4e921632bc4e..5e95419d3798 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.h @@ -28,15 +28,30 @@ #define __DC_FPU_H__ void dc_assert_fp_enabled(void); +bool dc_is_fp_enabled(void); void dc_fpu_begin(const char *function_name, const int line); void dc_fpu_end(const char *function_name, const int line); #ifndef _LINUX_FPU_COMPILATION_UNIT #define DC_FP_START() dc_fpu_begin(__func__, __LINE__) #define DC_FP_END() dc_fpu_end(__func__, __LINE__) +#ifdef CONFIG_DRM_AMD_DC_FP +#define DC_RUN_WITH_PREEMPTION_ENABLED(code) \ + do { \ + bool dc_fp_enabled = dc_is_fp_enabled(); \ + if (dc_fp_enabled) \ + DC_FP_END(); \ + code; \ + if (dc_fp_enabled) \ + DC_FP_START(); \ + } while (0) +#else +#define DC_RUN_WITH_PREEMPTION_ENABLED(code) code +#endif // !CONFIG_DRM_AMD_DC_FP #else #define DC_FP_START() BUILD_BUG() #define DC_FP_END() BUILD_BUG() -#endif +#define DC_RUN_WITH_PREEMPTION_ENABLED(code) code +#endif // !_LINUX_FPU_COMPILATION_UNIT #endif /* __DC_FPU_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/basics/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/basics/dce_calcs.c index 8c54c02a0e26..f37a43f4172e 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/basics/dce_calcs.c @@ -2010,10 +2010,10 @@ static void calculate_bandwidth( } /*output link bit per pixel supported*/ for (k = 0; k <= maximum_number_of_surfaces - 1; k++) { - data->output_bpphdmi[k] = bw_def_na; - data->output_bppdp4_lane_hbr[k] = bw_def_na; - data->output_bppdp4_lane_hbr2[k] = bw_def_na; - data->output_bppdp4_lane_hbr3[k] = bw_def_na; + data->output_bpphdmi[k] = (uint32_t)bw_def_na; + data->output_bppdp4_lane_hbr[k] = (uint32_t)bw_def_na; + data->output_bppdp4_lane_hbr2[k] = (uint32_t)bw_def_na; + data->output_bppdp4_lane_hbr3[k] = (uint32_t)bw_def_na; if (data->enable[k]) { data->output_bpphdmi[k] = bw_fixed_to_int(bw_mul(bw_div(bw_min2(bw_int_to_fixed(600), data->max_phyclk), data->pixel_rate[k]), bw_int_to_fixed(24))); if (bw_meq(data->max_phyclk, bw_int_to_fixed(270))) { diff --git a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c index 6073cadde76c..fa10f85df3db 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c +++ b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c @@ -503,6 +503,7 @@ struct fixed31_32 dc_fixpt_from_int_dy(unsigned int int_value, unsigned int integer_bits, unsigned int fractional_bits) { + (void)integer_bits; struct fixed31_32 fixpt_value = dc_fixpt_from_int(int_value); fixpt_value.value |= (long long)frac_value << (FIXED31_32_BITS_PER_FRACTIONAL_PART - fractional_bits); diff --git a/drivers/gpu/drm/amd/display/dc/basics/vector.c b/drivers/gpu/drm/amd/display/dc/basics/vector.c index a8b750ff8573..e8736c134b8d 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/vector.c +++ b/drivers/gpu/drm/amd/display/dc/basics/vector.c @@ -56,6 +56,7 @@ static bool dal_vector_presized_costruct(struct vector *vector, void *initial_value, uint32_t struct_size) { + (void)ctx; uint32_t i; vector->container = NULL; diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index 73e3c45eeeba..dd362071a6c9 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -780,28 +780,31 @@ static enum bp_result bios_parser_encoder_control( return bp->cmd_tbl.dig_encoder_control(bp, cntl); } +static enum bp_result bios_parser_external_encoder_control( + struct dc_bios *dcb, + struct bp_external_encoder_control *cntl) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.external_encoder_control) + return BP_RESULT_UNSUPPORTED; + + return bp->cmd_tbl.external_encoder_control(bp, cntl); +} + static enum bp_result bios_parser_dac_load_detection( struct dc_bios *dcb, - enum engine_id engine_id, - enum dal_device_type device_type, - uint32_t enum_id) + enum engine_id engine_id) { struct bios_parser *bp = BP_FROM_DCB(dcb); struct dc_context *ctx = dcb->ctx; struct bp_load_detection_parameters bp_params = {0}; - enum bp_result bp_result; + enum bp_result bp_result = BP_RESULT_UNSUPPORTED; uint32_t bios_0_scratch; uint32_t device_id_mask = 0; - bp_params.engine_id = engine_id; - bp_params.device_id = get_support_mask_for_device_id(device_type, enum_id); - - if (engine_id != ENGINE_ID_DACA && - engine_id != ENGINE_ID_DACB) - return BP_RESULT_UNSUPPORTED; - - if (!bp->cmd_tbl.dac_load_detection) - return BP_RESULT_UNSUPPORTED; + bp_params.device_id = get_support_mask_for_device_id( + DEVICE_TYPE_CRT, engine_id == ENGINE_ID_DACB ? 2 : 1); if (bp_params.device_id == ATOM_DEVICE_CRT1_SUPPORT) device_id_mask = ATOM_S0_CRT1_MASK; @@ -815,7 +818,13 @@ static enum bp_result bios_parser_dac_load_detection( bios_0_scratch &= ~device_id_mask; dm_write_reg(ctx, bp->base.regs->BIOS_SCRATCH_0, bios_0_scratch); - bp_result = bp->cmd_tbl.dac_load_detection(bp, &bp_params); + if (engine_id == ENGINE_ID_DACA || engine_id == ENGINE_ID_DACB) { + if (!bp->cmd_tbl.dac_load_detection) + return BP_RESULT_UNSUPPORTED; + + bp_params.engine_id = engine_id; + bp_result = bp->cmd_tbl.dac_load_detection(bp, &bp_params); + } if (bp_result != BP_RESULT_OK) return bp_result; @@ -1954,7 +1963,7 @@ static enum bp_result get_gpio_i2c_info(struct bios_parser *bp, count = (le16_to_cpu(header->sHeader.usStructureSize) - sizeof(ATOM_COMMON_TABLE_HEADER)) / sizeof(ATOM_GPIO_I2C_ASSIGMENT); - if (count < record->sucI2cId.bfI2C_LineMux) + if (count <= record->sucI2cId.bfI2C_LineMux) return BP_RESULT_BADBIOSTABLE; /* get the GPIO_I2C_INFO */ @@ -2687,6 +2696,7 @@ static enum bp_result update_slot_layout_info(struct dc_bios *dcb, struct slot_layout_info *slot_layout_info, unsigned int record_offset) { + (void)i; unsigned int j; struct bios_parser *bp; ATOM_BRACKET_LAYOUT_RECORD *record; @@ -2912,6 +2922,8 @@ static const struct dc_vbios_funcs vbios_funcs = { .encoder_control = bios_parser_encoder_control, + .external_encoder_control = bios_parser_external_encoder_control, + .dac_load_detection = bios_parser_dac_load_detection, .transmitter_control = bios_parser_transmitter_control, diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 94fddf22f5a9..a1c08e1cc411 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -205,6 +205,7 @@ static enum bp_result bios_parser_get_src_obj(struct dc_bios *dcb, struct graphics_object_id object_id, uint32_t index, struct graphics_object_id *src_object_id) { + (void)index; struct bios_parser *bp = BP_FROM_DCB(dcb); unsigned int i; enum bp_result bp_result = BP_RESULT_BADINPUT; @@ -765,6 +766,7 @@ static enum bp_result bios_parser_get_device_tag( uint32_t device_tag_index, struct connector_device_tag_info *info) { + (void)device_tag_index; struct bios_parser *bp = BP_FROM_DCB(dcb); struct atom_display_object_path_v2 *object; @@ -809,6 +811,7 @@ static enum bp_result get_ss_info_v4_1( uint32_t index, struct spread_spectrum_info *ss_info) { + (void)index; enum bp_result result = BP_RESULT_OK; struct atom_display_controller_info_v4_1 *disp_cntl_tbl = NULL; struct atom_smu_info_v3_3 *smu_info = NULL; @@ -897,6 +900,7 @@ static enum bp_result get_ss_info_v4_2( uint32_t index, struct spread_spectrum_info *ss_info) { + (void)index; enum bp_result result = BP_RESULT_OK; struct atom_display_controller_info_v4_2 *disp_cntl_tbl = NULL; struct atom_smu_info_v3_1 *smu_info = NULL; @@ -977,6 +981,7 @@ static enum bp_result get_ss_info_v4_5( uint32_t index, struct spread_spectrum_info *ss_info) { + (void)index; enum bp_result result = BP_RESULT_OK; struct atom_display_controller_info_v4_5 *disp_cntl_tbl = NULL; @@ -1604,6 +1609,8 @@ static uint32_t bios_parser_get_ss_entry_number( struct dc_bios *dcb, enum as_signal_type signal) { + (void)dcb; + (void)signal; /* TODO: DAL2 atomfirmware implementation does not need this. * why DAL3 need this? */ @@ -3536,6 +3543,8 @@ static uint16_t bios_parser_pack_data_tables( struct dc_bios *dcb, void *dst) { + (void)dcb; + (void)dst; // TODO: There is data bytes alignment issue, disable it for now. return 0; } diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table.c b/drivers/gpu/drm/amd/display/dc/bios/command_table.c index b692fa37402d..f6e22dcecf29 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.c @@ -226,6 +226,28 @@ static enum bp_result encoder_control_dig2_v1( return result; } +static uint8_t dc_color_depth_to_atom(enum dc_color_depth color_depth) +{ + switch (color_depth) { + case COLOR_DEPTH_UNDEFINED: + return PANEL_BPC_UNDEFINE; + case COLOR_DEPTH_666: + return PANEL_6BIT_PER_COLOR; + default: + case COLOR_DEPTH_888: + return PANEL_8BIT_PER_COLOR; + case COLOR_DEPTH_101010: + return PANEL_10BIT_PER_COLOR; + case COLOR_DEPTH_121212: + return PANEL_12BIT_PER_COLOR; + case COLOR_DEPTH_141414: + dm_error("14-bit color not supported by ATOMBIOS\n"); + return PANEL_BPC_UNDEFINE; + case COLOR_DEPTH_161616: + return PANEL_16BIT_PER_COLOR; + } +} + static enum bp_result encoder_control_digx_v3( struct bios_parser *bp, struct bp_encoder_control *cntl) @@ -248,23 +270,7 @@ static enum bp_result encoder_control_digx_v3( cntl->signal, cntl->enable_dp_audio); params.ucLaneNum = (uint8_t)(cntl->lanes_number); - - switch (cntl->color_depth) { - case COLOR_DEPTH_888: - params.ucBitPerColor = PANEL_8BIT_PER_COLOR; - break; - case COLOR_DEPTH_101010: - params.ucBitPerColor = PANEL_10BIT_PER_COLOR; - break; - case COLOR_DEPTH_121212: - params.ucBitPerColor = PANEL_12BIT_PER_COLOR; - break; - case COLOR_DEPTH_161616: - params.ucBitPerColor = PANEL_16BIT_PER_COLOR; - break; - default: - break; - } + params.ucBitPerColor = dc_color_depth_to_atom(cntl->color_depth); if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params)) result = BP_RESULT_OK; @@ -294,23 +300,7 @@ static enum bp_result encoder_control_digx_v4( cntl->signal, cntl->enable_dp_audio)); params.ucLaneNum = (uint8_t)(cntl->lanes_number); - - switch (cntl->color_depth) { - case COLOR_DEPTH_888: - params.ucBitPerColor = PANEL_8BIT_PER_COLOR; - break; - case COLOR_DEPTH_101010: - params.ucBitPerColor = PANEL_10BIT_PER_COLOR; - break; - case COLOR_DEPTH_121212: - params.ucBitPerColor = PANEL_12BIT_PER_COLOR; - break; - case COLOR_DEPTH_161616: - params.ucBitPerColor = PANEL_16BIT_PER_COLOR; - break; - default: - break; - } + params.ucBitPerColor = dc_color_depth_to_atom(cntl->color_depth); if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params)) result = BP_RESULT_OK; @@ -334,23 +324,7 @@ static enum bp_result encoder_control_digx_v5( cntl->signal, cntl->enable_dp_audio)); params.ucLaneNum = (uint8_t)(cntl->lanes_number); - - switch (cntl->color_depth) { - case COLOR_DEPTH_888: - params.ucBitPerColor = PANEL_8BIT_PER_COLOR; - break; - case COLOR_DEPTH_101010: - params.ucBitPerColor = PANEL_10BIT_PER_COLOR; - break; - case COLOR_DEPTH_121212: - params.ucBitPerColor = PANEL_12BIT_PER_COLOR; - break; - case COLOR_DEPTH_161616: - params.ucBitPerColor = PANEL_16BIT_PER_COLOR; - break; - default: - break; - } + params.ucBitPerColor = dc_color_depth_to_atom(cntl->color_depth); if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A) switch (cntl->color_depth) { @@ -1797,30 +1771,7 @@ static enum bp_result select_crtc_source_v3( ¶ms.ucEncodeMode)) return BP_RESULT_BADINPUT; - switch (bp_params->color_depth) { - case COLOR_DEPTH_UNDEFINED: - params.ucDstBpc = PANEL_BPC_UNDEFINE; - break; - case COLOR_DEPTH_666: - params.ucDstBpc = PANEL_6BIT_PER_COLOR; - break; - default: - case COLOR_DEPTH_888: - params.ucDstBpc = PANEL_8BIT_PER_COLOR; - break; - case COLOR_DEPTH_101010: - params.ucDstBpc = PANEL_10BIT_PER_COLOR; - break; - case COLOR_DEPTH_121212: - params.ucDstBpc = PANEL_12BIT_PER_COLOR; - break; - case COLOR_DEPTH_141414: - dm_error("14-bit color not supported by SelectCRTC_Source v3\n"); - break; - case COLOR_DEPTH_161616: - params.ucDstBpc = PANEL_16BIT_PER_COLOR; - break; - } + params.ucDstBpc = dc_color_depth_to_atom(bp_params->color_depth); if (EXEC_BIOS_CMD_TABLE(SelectCRTC_Source, params)) result = BP_RESULT_OK; @@ -2569,6 +2520,7 @@ static enum bp_result external_encoder_control_v3( cpu_to_le16((uint16_t)cntl->connector_obj_id.id); break; case EXTERNAL_ENCODER_CONTROL_SETUP: + case EXTERNAL_ENCODER_CONTROL_ENABLE: /* EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 pixel clock unit in * 10KHz * output display device pixel clock frequency in unit of 10KHz. @@ -2585,26 +2537,24 @@ static enum bp_result external_encoder_control_v3( if (is_input_signal_dp) { /* Bit[0]: indicate link rate, =1: 2.7Ghz, =0: 1.62Ghz, * only valid in encoder setup with DP mode. */ - if (LINK_RATE_HIGH == cntl->link_rate) - cntl_params->ucConfig |= 1; + if (cntl->link_rate == LINK_RATE_LOW) + cntl_params->ucConfig |= + EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_1_62GHZ; + else if (cntl->link_rate == LINK_RATE_HIGH) + cntl_params->ucConfig |= + EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ; + else + dm_error("Link rate not supported by external encoder"); + /* output color depth Indicate encoder data bpc format * in DP mode, only valid in encoder setup in DP mode. */ - cntl_params->ucBitPerColor = - (uint8_t)(cntl->color_depth); + cntl_params->ucBitPerColor = dc_color_depth_to_atom(cntl->color_depth); } /* Indicate how many lanes used by external encoder, only valid * in encoder setup and enableoutput. */ cntl_params->ucLaneNum = (uint8_t)(cntl->lanes_number); break; - case EXTERNAL_ENCODER_CONTROL_ENABLE: - cntl_params->usPixelClock = - cpu_to_le16((uint16_t)(cntl->pixel_clock / 10)); - cntl_params->ucEncoderMode = - (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom( - cntl->signal, false); - cntl_params->ucLaneNum = (uint8_t)cntl->lanes_number; - break; default: break; } diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c index f2b1720a6a66..17ef515c6c69 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c @@ -783,6 +783,8 @@ static enum bp_result external_encoder_control_v3( struct bios_parser *bp, struct bp_external_encoder_control *cntl) { + (void)bp; + (void)cntl; /* TODO */ return BP_RESULT_OK; } diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c index 268e2414b34f..a93a8860535a 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c @@ -84,6 +84,7 @@ bool dal_bios_parser_init_cmd_tbl_helper2( case DCN_VERSION_3_51: case DCN_VERSION_3_6: case DCN_VERSION_4_01: + case DCN_VERSION_4_2: *h = dal_cmd_tbl_helper_dce112_get_table2(); return true; diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c b/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c index 3099128223df..cec61c9d7263 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c @@ -94,6 +94,7 @@ static uint8_t hpd_sel_to_atom(enum hpd_source_id id) static uint8_t dig_encoder_sel_to_atom(enum engine_id id) { + (void)id; /* On any ASIC after DCE80, we manually program the DIG_FE * selection (see connect_dig_be_to_fe function of the link * encoder), so translation should always return 0 (no FE). diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c index 349f0e5d5856..478465fba224 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c +++ b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c @@ -93,6 +93,7 @@ static uint8_t hpd_sel_to_atom(enum hpd_source_id id) static uint8_t dig_encoder_sel_to_atom(enum engine_id id) { + (void)id; /* On any ASIC after DCE80, we manually program the DIG_FE * selection (see connect_dig_be_to_fe function of the link * encoder), so translation should always return 0 (no FE). diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c index 1a5fefcde8af..6b8a87f2c49e 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c +++ b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c @@ -91,6 +91,7 @@ static uint8_t hpd_sel_to_atom(enum hpd_source_id id) static uint8_t dig_encoder_sel_to_atom(enum engine_id id) { + (void)id; /* On any ASIC after DCE80, we manually program the DIG_FE * selection (see connect_dig_be_to_fe function of the link * encoder), so translation should always return 0 (no FE). diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile b/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile index 60021671b386..98911ef56c2e 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile @@ -1,5 +1,5 @@ # -# Copyright 2017 Advanced Micro Devices, Inc. +# Copyright 2017-2026 Advanced Micro Devices, Inc. # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), @@ -29,18 +29,6 @@ AMD_DAL_CLK_MGR = $(addprefix $(AMDDALPATH)/dc/clk_mgr/,$(CLK_MGR)) AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR) - -ifdef CONFIG_DRM_AMD_DC_SI -############################################################################### -# DCE 60 -############################################################################### -CLK_MGR_DCE60 = dce60_clk_mgr.o - -AMD_DAL_CLK_MGR_DCE60 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dce60/,$(CLK_MGR_DCE60)) - -AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCE60) -endif - ############################################################################### # DCE 100 and DCE8x ############################################################################### @@ -188,4 +176,13 @@ CLK_MGR_DCN401 = dcn401_clk_mgr.o dcn401_clk_mgr_smu_msg.o AMD_DAL_CLK_MGR_DCN401 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dcn401/,$(CLK_MGR_DCN401)) AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN401) + +############################################################################### +# DCN42 +############################################################################### +CLK_MGR_DCN42 = dcn42_smu.o dcn42_clk_mgr.o + +AMD_DAL_CLK_MGR_DCN42 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dcn42/,$(CLK_MGR_DCN42)) + +AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN42) endif diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c index d237d7b41dfd..880bce368238 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c @@ -34,7 +34,6 @@ #include "dce110/dce110_clk_mgr.h" #include "dce112/dce112_clk_mgr.h" #include "dce120/dce120_clk_mgr.h" -#include "dce60/dce60_clk_mgr.h" #include "dcn10/rv1_clk_mgr.h" #include "dcn10/rv2_clk_mgr.h" #include "dcn20/dcn20_clk_mgr.h" @@ -49,6 +48,7 @@ #include "dcn32/dcn32_clk_mgr.h" #include "dcn35/dcn35_clk_mgr.h" #include "dcn401/dcn401_clk_mgr.h" +#include "dcn42/dcn42_clk_mgr.h" int clk_mgr_helper_get_active_display_cnt( struct dc *dc, @@ -78,6 +78,7 @@ int clk_mgr_helper_get_active_plane_cnt( struct dc *dc, struct dc_state *context) { + (void)dc; int i, total_plane_count; total_plane_count = 0; @@ -97,7 +98,7 @@ void clk_mgr_exit_optimized_pwr_state(const struct dc *dc, struct clk_mgr *clk_m { struct dc_link *edp_links[MAX_NUM_EDP]; struct dc_link *edp_link = NULL; - int edp_num; + unsigned int edp_num; unsigned int panel_inst; dc_get_edp_links(dc, edp_links, &edp_num); @@ -123,7 +124,7 @@ void clk_mgr_optimize_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr) { struct dc_link *edp_links[MAX_NUM_EDP]; struct dc_link *edp_link = NULL; - int edp_num; + unsigned int edp_num; unsigned int panel_inst; dc_get_edp_links(dc, edp_links, &edp_num); @@ -149,18 +150,7 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p struct hw_asic_id asic_id = ctx->asic_id; switch (asic_id.chip_family) { -#if defined(CONFIG_DRM_AMD_DC_SI) - case FAMILY_SI: { - struct clk_mgr_internal *clk_mgr = kzalloc_obj(*clk_mgr); - - if (clk_mgr == NULL) { - BREAK_TO_DEBUGGER(); - return NULL; - } - dce60_clk_mgr_construct(ctx, clk_mgr); - return &clk_mgr->base; - } -#endif + case FAMILY_SI: case FAMILY_CI: case FAMILY_KV: { struct clk_mgr_internal *clk_mgr = kzalloc_obj(*clk_mgr); @@ -374,6 +364,18 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p return &clk_mgr->base; } break; + case AMDGPU_FAMILY_GC_11_5_4: { + struct clk_mgr_dcn42 *clk_mgr = kzalloc(sizeof(*clk_mgr), GFP_KERNEL); + + if (clk_mgr == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dcn42_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); + return &clk_mgr->base.base; + } + break; #endif /* CONFIG_DRM_AMD_DC_FP */ default: ASSERT(0); /* Unknown Asic */ @@ -431,6 +433,9 @@ void dc_destroy_clk_mgr(struct clk_mgr *clk_mgr_base) case AMDGPU_FAMILY_GC_12_0_0: dcn401_clk_mgr_destroy(clk_mgr); break; + case AMDGPU_FAMILY_GC_11_5_4: + dcn42_clk_mgr_destroy(clk_mgr); + break; default: break; diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c index 6131ede2db7a..6d41df52d7c9 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c @@ -62,6 +62,18 @@ static const struct clk_mgr_mask disp_clk_mask = { CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) }; +/* Max clock values for each state indexed by "enum clocks_state": */ +static const struct state_dependent_clocks dce60_max_clks_by_state[] = { +/* ClocksStateInvalid - should not be used */ +{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, +/* ClocksStateUltraLow - not expected to be used for DCE 6.0 */ +{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, +/* ClocksStateLow */ +{ .display_clk_khz = 352000, .pixel_clk_khz = 330000}, +/* ClocksStateNominal */ +{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 }, +/* ClocksStatePerformance */ +{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 } }; /* Max clock values for each state indexed by "enum clocks_state": */ static const struct state_dependent_clocks dce80_max_clks_by_state[] = { @@ -126,6 +138,20 @@ int dce_adjust_dp_ref_freq_for_ss(struct clk_mgr_internal *clk_mgr_dce, int dp_r return dp_ref_clk_khz; } +static int dce60_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr_base) +{ + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); + struct dc_context *ctx = clk_mgr_base->ctx; + int dp_ref_clk_khz = 0; + + if (ASIC_REV_IS_TAHITI_P(ctx->asic_id.hw_internal_rev)) + dp_ref_clk_khz = ctx->dc_bios->fw_info.default_display_engine_pll_frequency; + else + dp_ref_clk_khz = clk_mgr_base->clks.dispclk_khz; + + return dce_adjust_dp_ref_freq_for_ss(clk_mgr, dp_ref_clk_khz); +} + int dce_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr_base) { struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); @@ -134,6 +160,9 @@ int dce_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr_base) int dp_ref_clk_khz; int target_div; + if (clk_mgr_base->ctx->dce_version <= DCE_VERSION_6_4) + return dce60_get_dp_ref_freq_khz(clk_mgr_base); + /* ASSERT DP Reference Clock source is from DFS*/ REG_GET(DPREFCLK_CNTL, DPREFCLK_SRC_SEL, &dprefclk_src_sel); ASSERT(dprefclk_src_sel == 0); @@ -441,27 +470,37 @@ void dce_clk_mgr_construct( struct clk_mgr *base = &clk_mgr->base; struct dm_pp_static_clock_info static_clk_info = {0}; - memcpy(clk_mgr->max_clks_by_state, - dce80_max_clks_by_state, - sizeof(dce80_max_clks_by_state)); + if (ctx->dce_version <= DCE_VERSION_6_4) + memcpy(clk_mgr->max_clks_by_state, + dce60_max_clks_by_state, + sizeof(dce60_max_clks_by_state)); + else + memcpy(clk_mgr->max_clks_by_state, + dce80_max_clks_by_state, + sizeof(dce80_max_clks_by_state)); + base->ctx = ctx; base->funcs = &dce_funcs; - clk_mgr->regs = &disp_clk_regs; - clk_mgr->clk_mgr_shift = &disp_clk_shift; - clk_mgr->clk_mgr_mask = &disp_clk_mask; - clk_mgr->dfs_bypass_disp_clk = 0; + if (ctx->dce_version >= DCE_VERSION_8_0) { + clk_mgr->regs = &disp_clk_regs; + clk_mgr->clk_mgr_shift = &disp_clk_shift; + clk_mgr->clk_mgr_mask = &disp_clk_mask; + } + clk_mgr->dfs_bypass_disp_clk = 0; clk_mgr->dprefclk_ss_percentage = 0; clk_mgr->dprefclk_ss_divider = 1000; clk_mgr->ss_on_dprefclk = false; - if (dm_pp_get_static_clocks(ctx, &static_clk_info)) - clk_mgr->max_clks_state = static_clk_info.max_clocks_state; - else - clk_mgr->max_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; - clk_mgr->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID; + if (ctx->dce_version >= DCE_VERSION_8_0) { + if (dm_pp_get_static_clocks(ctx, &static_clk_info)) + clk_mgr->max_clks_state = static_clk_info.max_clocks_state; + else + clk_mgr->max_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; + clk_mgr->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID; + } base->clks.max_supported_dispclk_khz = clk_mgr->max_clks_by_state[DM_PP_CLOCKS_STATE_PERFORMANCE].display_clk_khz; @@ -469,4 +508,3 @@ void dce_clk_mgr_construct( dce_clock_read_integrated_info(clk_mgr); dce_clock_read_ss_info(clk_mgr); } - diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c index d50b9440210e..cd4c45516616 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c @@ -92,7 +92,7 @@ static int determine_sclk_from_bounding_box( uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context) { uint8_t j; - uint32_t min_vertical_blank_time = -1; + uint32_t min_vertical_blank_time = (uint32_t)-1; for (j = 0; j < context->stream_count; j++) { struct dc_stream_state *stream = context->streams[j]; diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c deleted file mode 100644 index 69dd80d9f738..000000000000 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - - -#include "dccg.h" -#include "clk_mgr_internal.h" -#include "dce100/dce_clk_mgr.h" -#include "dce110/dce110_clk_mgr.h" -#include "dce60_clk_mgr.h" -#include "reg_helper.h" -#include "dmcu.h" -#include "core_types.h" -#include "dal_asic_id.h" - -/* - * Currently the register shifts and masks in this file are used for dce60 - * which has no DPREFCLK_CNTL register - * TODO: remove this when DENTIST_DISPCLK_CNTL - * is moved to dccg, where it belongs - */ -#include "dce/dce_6_0_d.h" -#include "dce/dce_6_0_sh_mask.h" - -#define REG(reg) \ - (clk_mgr->regs->reg) - -#undef FN -#define FN(reg_name, field_name) \ - clk_mgr->clk_mgr_shift->field_name, clk_mgr->clk_mgr_mask->field_name - -/* set register offset */ -#define SR(reg_name)\ - .reg_name = mm ## reg_name - -static const struct clk_mgr_registers disp_clk_regs = { - CLK_COMMON_REG_LIST_DCE60_BASE() -}; - -static const struct clk_mgr_shift disp_clk_shift = { - CLK_COMMON_MASK_SH_LIST_DCE60_COMMON_BASE(__SHIFT) -}; - -static const struct clk_mgr_mask disp_clk_mask = { - CLK_COMMON_MASK_SH_LIST_DCE60_COMMON_BASE(_MASK) -}; - - -/* Max clock values for each state indexed by "enum clocks_state": */ -static const struct state_dependent_clocks dce60_max_clks_by_state[] = { -/* ClocksStateInvalid - should not be used */ -{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, -/* ClocksStateUltraLow - not expected to be used for DCE 6.0 */ -{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, -/* ClocksStateLow */ -{ .display_clk_khz = 352000, .pixel_clk_khz = 330000}, -/* ClocksStateNominal */ -{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 }, -/* ClocksStatePerformance */ -{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 } }; - -static int dce60_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr_base) -{ - struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); - struct dc_context *ctx = clk_mgr_base->ctx; - int dp_ref_clk_khz = 0; - - if (ASIC_REV_IS_TAHITI_P(ctx->asic_id.hw_internal_rev)) - dp_ref_clk_khz = ctx->dc_bios->fw_info.default_display_engine_pll_frequency; - else - dp_ref_clk_khz = clk_mgr_base->clks.dispclk_khz; - - return dce_adjust_dp_ref_freq_for_ss(clk_mgr, dp_ref_clk_khz); -} - -static void dce60_pplib_apply_display_requirements( - struct dc *dc, - struct dc_state *context) -{ - struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; - - dce110_fill_display_configs(context, pp_display_cfg); - - if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) != 0) - dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg); -} - -static void dce60_update_clocks(struct clk_mgr *clk_mgr_base, - struct dc_state *context, - bool safe_to_lower) -{ - struct clk_mgr_internal *clk_mgr_dce = TO_CLK_MGR_INTERNAL(clk_mgr_base); - struct dm_pp_power_level_change_request level_change_req; - const int max_disp_clk = - clk_mgr_dce->max_clks_by_state[DM_PP_CLOCKS_STATE_PERFORMANCE].display_clk_khz; - int patched_disp_clk = MIN(max_disp_clk, context->bw_ctx.bw.dce.dispclk_khz); - - level_change_req.power_level = dce_get_required_clocks_state(clk_mgr_base, context); - /* get max clock state from PPLIB */ - if ((level_change_req.power_level < clk_mgr_dce->cur_min_clks_state && safe_to_lower) - || level_change_req.power_level > clk_mgr_dce->cur_min_clks_state) { - if (dm_pp_apply_power_level_change_request(clk_mgr_base->ctx, &level_change_req)) - clk_mgr_dce->cur_min_clks_state = level_change_req.power_level; - } - - if (should_set_clock(safe_to_lower, patched_disp_clk, clk_mgr_base->clks.dispclk_khz)) { - patched_disp_clk = dce_set_clock(clk_mgr_base, patched_disp_clk); - clk_mgr_base->clks.dispclk_khz = patched_disp_clk; - } - dce60_pplib_apply_display_requirements(clk_mgr_base->ctx->dc, context); -} - - - - - - - - -static struct clk_mgr_funcs dce60_funcs = { - .get_dp_ref_clk_frequency = dce60_get_dp_ref_freq_khz, - .update_clocks = dce60_update_clocks -}; - -void dce60_clk_mgr_construct( - struct dc_context *ctx, - struct clk_mgr_internal *clk_mgr) -{ - struct clk_mgr *base = &clk_mgr->base; - - dce_clk_mgr_construct(ctx, clk_mgr); - - memcpy(clk_mgr->max_clks_by_state, - dce60_max_clks_by_state, - sizeof(dce60_max_clks_by_state)); - - clk_mgr->regs = &disp_clk_regs; - clk_mgr->clk_mgr_shift = &disp_clk_shift; - clk_mgr->clk_mgr_mask = &disp_clk_mask; - clk_mgr->base.funcs = &dce60_funcs; - - base->clks.max_supported_dispclk_khz = - clk_mgr->max_clks_by_state[DM_PP_CLOCKS_STATE_PERFORMANCE].display_clk_khz; -} - diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c index e18097f82091..09e83097a623 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c @@ -740,7 +740,8 @@ void rn_clk_mgr_construct( if (clk_mgr->base.dentist_vco_freq_khz == 0) clk_mgr->base.dentist_vco_freq_khz = 3600000; - if (ctx->dc_bios->integrated_info->memory_type == LpDdr4MemType) { + if (ctx->dc_bios->integrated_info && + ctx->dc_bios->integrated_info->memory_type == LpDdr4MemType) { if (clk_mgr->periodic_retraining_disabled) { rn_bw_params.wm_table = lpddr4_wm_table_with_disabled_ppt; } else { diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c index b0aba3a6f13c..dcec9d0f8c34 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c @@ -421,10 +421,8 @@ static void dcn3_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base) clk_mgr_base->bw_params->dc_mode_softmax_memclk = dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_UCLK); /* Refresh bounding box */ - DC_FP_START(); clk_mgr_base->ctx->dc->res_pool->funcs->update_bw_bounding_box( clk_mgr->base.ctx->dc, clk_mgr_base->bw_params); - DC_FP_END(); } static bool dcn3_is_smu_present(struct clk_mgr *clk_mgr_base) @@ -523,6 +521,7 @@ void dcn3_clk_mgr_construct( struct pp_smu_funcs *pp_smu, struct dccg *dccg) { + (void)pp_smu; struct clk_state_registers_and_bypass s = { 0 }; clk_mgr->base.ctx = ctx; @@ -547,6 +546,7 @@ void dcn3_clk_mgr_construct( /* in case we don't get a value from the register, use default */ if (clk_mgr->base.dentist_vco_freq_khz == 0) clk_mgr->base.dentist_vco_freq_khz = 3650000; + /* Convert dprefclk units from MHz to KHz */ /* Value already divided by 10, some resolution lost */ diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c index 7aee02d56292..57ba7bc4d16e 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c @@ -733,11 +733,12 @@ void vg_clk_mgr_construct( if (clk_mgr->base.base.dentist_vco_freq_khz == 0) clk_mgr->base.base.dentist_vco_freq_khz = 3600000; - if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) { + if (ctx->dc_bios->integrated_info && + ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) vg_bw_params.wm_table = lpddr5_wm_table; - } else { + else vg_bw_params.wm_table = ddr4_wm_table; - } + /* Saved clocks configured at boot for debug purposes */ vg_dump_clk_registers(&clk_mgr->base.base.boot_snapshot, &clk_mgr->base.base, &log_info); diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c index 051052bd10c9..89fc482947ef 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c @@ -329,6 +329,9 @@ bool dcn31_are_clock_states_equal(struct dc_clocks *a, static void dcn31_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass, struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info) { + (void)regs_and_bypass; + (void)clk_mgr_base; + (void)log_info; return; } @@ -725,11 +728,12 @@ void dcn31_clk_mgr_construct( /* TODO: Check we get what we expect during bringup */ clk_mgr->base.base.dentist_vco_freq_khz = get_vco_frequency_from_reg(&clk_mgr->base); - if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) { + if (ctx->dc_bios->integrated_info && + ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) dcn31_bw_params.wm_table = lpddr5_wm_table; - } else { + else dcn31_bw_params.wm_table = ddr5_wm_table; - } + /* Saved clocks configured at boot for debug purposes */ dcn31_dump_clk_registers(&clk_mgr->base.base.boot_snapshot, &clk_mgr->base.base, &log_info); diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c index 0cb37827a62b..b08a70a2f571 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c @@ -395,6 +395,9 @@ bool dcn314_are_clock_states_equal(struct dc_clocks *a, static void dcn314_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass, struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info) { + (void)regs_and_bypass; + (void)clk_mgr_base; + (void)log_info; return; } @@ -842,7 +845,8 @@ void dcn314_clk_mgr_construct( /* TODO: Check we get what we expect during bringup */ clk_mgr->base.base.dentist_vco_freq_khz = get_vco_frequency_from_reg(&clk_mgr->base); - if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) + if (ctx->dc_bios->integrated_info && + ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) dcn314_bw_params.wm_table = lpddr5_wm_table; else dcn314_bw_params.wm_table = ddr5_wm_table; diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c index c49268db85f6..3a651c1a866d 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c @@ -247,6 +247,9 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base, static void dcn315_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass, struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info) { + (void)regs_and_bypass; + (void)clk_mgr_base; + (void)log_info; return; } @@ -652,11 +655,12 @@ void dcn315_clk_mgr_construct( if (clk_mgr->base.smu_ver > 0) clk_mgr->base.smu_present = true; - if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) { + if (ctx->dc_bios->integrated_info && + ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) dcn315_bw_params.wm_table = lpddr5_wm_table; - } else { + else dcn315_bw_params.wm_table = ddr5_wm_table; - } + /* Saved clocks configured at boot for debug purposes */ dcn315_dump_clk_registers(&clk_mgr->base.base.boot_snapshot, &clk_mgr->base.base, &log_info); diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c index 1769b1f26e75..e9d492d8c8d4 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c @@ -255,6 +255,9 @@ static void dcn316_update_clocks(struct clk_mgr *clk_mgr_base, static void dcn316_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass, struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info) { + (void)regs_and_bypass; + (void)clk_mgr_base; + (void)log_info; return; } @@ -636,11 +639,12 @@ void dcn316_clk_mgr_construct( clk_mgr->base.base.dentist_vco_freq_khz = 2500000; /* 2400MHz */ - if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) { + if (ctx->dc_bios->integrated_info && + ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) dcn316_bw_params.wm_table = lpddr5_wm_table; - } else { + else dcn316_bw_params.wm_table = ddr4_wm_table; - } + /* Saved clocks configured at boot for debug purposes */ dcn316_dump_clk_registers(&clk_mgr->base.base.boot_snapshot, &clk_mgr->base.base, &log_info); diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c index 2856b0337e87..fda6cade30a8 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c @@ -872,6 +872,7 @@ static uint32_t dcn32_get_vco_frequency_from_reg(struct clk_mgr_internal *clk_mg static void dcn32_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass, struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info) { + (void)log_info; struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); uint32_t dprefclk_did = 0; uint32_t dcfclk_did = 0; @@ -1059,11 +1060,9 @@ static void dcn32_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base) if (!clk_mgr->dpm_present) dcn32_patch_dpm_table(clk_mgr_base->bw_params); - DC_FP_START(); /* Refresh bounding box */ clk_mgr_base->ctx->dc->res_pool->funcs->update_bw_bounding_box( clk_mgr->base.ctx->dc, clk_mgr_base->bw_params); - DC_FP_END(); } static bool dcn32_are_clock_states_equal(struct dc_clocks *a, @@ -1147,6 +1146,7 @@ void dcn32_clk_mgr_construct( struct pp_smu_funcs *pp_smu, struct dccg *dccg) { + (void)pp_smu; struct clk_log_info log_info = {0}; clk_mgr->base.ctx = ctx; diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c index 6fc524752613..2798088842f4 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c @@ -1464,11 +1464,12 @@ void dcn35_clk_mgr_construct( /* TODO: Check we get what we expect during bringup */ clk_mgr->base.base.dentist_vco_freq_khz = get_vco_frequency_from_reg(&clk_mgr->base); - if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) { + if (ctx->dc_bios->integrated_info && + ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) dcn35_bw_params.wm_table = lpddr5_wm_table; - } else { + else dcn35_bw_params.wm_table = ddr5_wm_table; - } + /* Saved clocks configured at boot for debug purposes */ dcn35_save_clk_registers(&clk_mgr->base.base.boot_snapshot, clk_mgr); diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c index 604d256cb47a..9d8f81c3d3f0 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c @@ -204,7 +204,7 @@ int dcn35_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispcl khz_to_mhz_ceil(requested_dispclk_khz)); smu_print("requested_dispclk_khz = %d, actual_dispclk_set_mhz: %d\n", requested_dispclk_khz, actual_dispclk_set_mhz); - return actual_dispclk_set_mhz * 1000; + return (int)((long long)actual_dispclk_set_mhz * 1000); } int dcn35_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr) @@ -221,7 +221,7 @@ int dcn35_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr) /* TODO: add code for programing DP DTO, currently this is down by command table */ - return actual_dprefclk_set_mhz * 1000; + return (int)((long long)actual_dprefclk_set_mhz * 1000); } int dcn35_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_dcfclk_khz) @@ -238,7 +238,7 @@ int dcn35_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int requeste smu_print("requested_dcfclk_khz = %d, actual_dcfclk_set_mhz: %d\n", requested_dcfclk_khz, actual_dcfclk_set_mhz); - return actual_dcfclk_set_mhz * 1000; + return (int)((long long)actual_dcfclk_set_mhz * 1000); } int dcn35_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_min_ds_dcfclk_khz) @@ -255,7 +255,7 @@ int dcn35_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int re smu_print("requested_min_ds_dcfclk_khz = %d, actual_min_ds_dcfclk_mhz: %d\n", requested_min_ds_dcfclk_khz, actual_min_ds_dcfclk_mhz); - return actual_min_ds_dcfclk_mhz * 1000; + return (int)((long long)actual_min_ds_dcfclk_mhz * 1000); } int dcn35_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz) @@ -272,7 +272,7 @@ int dcn35_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz smu_print("requested_dpp_khz = %d, actual_dppclk_set_mhz: %d\n", requested_dpp_khz, actual_dppclk_set_mhz); - return actual_dppclk_set_mhz * 1000; + return (int)((long long)actual_dppclk_set_mhz * 1000); } void dcn35_smu_set_display_idle_optimization(struct clk_mgr_internal *clk_mgr, uint32_t idle_info) @@ -424,7 +424,7 @@ int dcn35_smu_get_dprefclk(struct clk_mgr_internal *clk_mgr) 0); smu_print("%s: SMU DPREF clk = %d mhz\n", __func__, dprefclk); - return dprefclk * 1000; + return (int)((long long)dprefclk * 1000); } int dcn35_smu_get_dtbclk(struct clk_mgr_internal *clk_mgr) @@ -439,7 +439,7 @@ int dcn35_smu_get_dtbclk(struct clk_mgr_internal *clk_mgr) 0); smu_print("%s: get_dtbclk = %dmhz\n", __func__, dtbclk); - return dtbclk * 1000; + return (int)((long long)dtbclk * 1000); } /* Arg = 1: Turn DTB on; 0: Turn DTB CLK OFF. when it is on, it is 600MHZ */ void dcn35_smu_set_dtbclk(struct clk_mgr_internal *clk_mgr, bool enable) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c index 03464f21d119..82c1a55a2271 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c @@ -333,6 +333,7 @@ bool dcn401_is_dc_mode_present(struct clk_mgr *clk_mgr_base) static void dcn401_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass, struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info) { + (void)log_info; struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); uint32_t dprefclk_did = 0; uint32_t dcfclk_did = 0; @@ -525,6 +526,7 @@ static void dcn401_update_clocks_update_dtb_dto(struct clk_mgr_internal *clk_mgr struct dc_state *context, int ref_dtbclk_khz) { + (void)ref_dtbclk_khz; int i; struct dccg *dccg = clk_mgr->dccg; struct pipe_ctx *otg_master; @@ -614,6 +616,7 @@ static void dcn401_update_clocks_update_dentist( struct clk_mgr_internal *clk_mgr, struct dc_state *context) { + (void)context; uint32_t new_disp_divider = 0; uint32_t new_dispclk_wdivider = 0; uint32_t dentist_dispclk_wdivider_readback = 0; diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c new file mode 100644 index 000000000000..ec888aed207d --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c @@ -0,0 +1,1183 @@ +// SPDX-License-Identifier: MIT +// +// Copyright 2026 Advanced Micro Devices, Inc. + +#include "dcn42_clk_mgr.h" + +#include "dccg.h" +#include "clk_mgr_internal.h" + +// For dce12_get_dp_ref_freq_khz +#include "dce100/dce_clk_mgr.h" + +// For dcn20_update_clocks_update_dpp_dto +#include "dcn20/dcn20_clk_mgr.h" + + + + +#include "reg_helper.h" +#include "core_types.h" +#include "dcn42_smu.h" +#include "dm_helpers.h" + +/* TODO: remove this include once we ported over remaining clk mgr functions*/ +#include "dcn30/dcn30_clk_mgr.h" +#include "dcn31/dcn31_clk_mgr.h" + +#include "dcn35/dcn35_clk_mgr.h" + +#include "dc_dmub_srv.h" +#include "link_service.h" +#include "logger_types.h" + +#include "clk/clk_15_0_0_offset.h" +#include "clk/clk_15_0_0_sh_mask.h" +#include "dcn/dcn_4_2_0_offset.h" +#include "dcn/dcn_4_2_0_sh_mask.h" + + +#undef DC_LOGGER +#define DC_LOGGER \ + dc_logger +#define DC_LOGGER_INIT(logger) \ + struct dal_logger *dc_logger = logger + +#undef FN +#define FN(reg_name, field_name) \ + clk_mgr->clk_mgr_shift->field_name, clk_mgr->clk_mgr_mask->field_name + +#define REG(reg) \ + (clk_mgr->regs->reg) + +// for DCN register access +#define DCN_BASE__INST0_SEG0 0x00000012 +#define DCN_BASE__INST0_SEG1 0x000000C0 + +#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg + +#define BASE(seg) BASE_INNER(seg) + +#define SR(reg_name) \ + .reg_name = BASE(reg ## reg_name ## _BASE_IDX) + reg ## reg_name + +// for CLKIP register access +#define CLK_BASE__INST0_SEG0 0x00016C00 + +#define CLK_BASE_INNER(seg) \ + CLK_BASE__INST0_SEG ## seg + +#define CLK_SR_DCN42(reg_name) \ + .reg_name = CLK_BASE(reg ## reg_name ## _BASE_IDX) + reg ## reg_name + +static const struct clk_mgr_registers clk_mgr_regs_dcn42 = { + CLK_REG_LIST_DCN42() +}; + +static const struct clk_mgr_shift clk_mgr_shift_dcn42 = { + CLK_COMMON_MASK_SH_LIST_DCN42(__SHIFT) +}; + +static const struct clk_mgr_mask clk_mgr_mask_dcn42 = { + CLK_COMMON_MASK_SH_LIST_DCN42(_MASK) +}; + +#define TO_CLK_MGR_DCN42(clk_mgr_int)\ + container_of(clk_mgr_int, struct clk_mgr_dcn42, base) + +bool dcn42_has_active_display(struct dc *dc, const struct dc_state *context) +{ + int i, active_count = 0; + + for (i = 0; i < context->stream_count; i++) { + const struct dc_stream_state *stream = context->streams[i]; + + /* Checking stream / link detection ensuring that PHY is active*/ + if (dc_is_hdmi_signal(stream->signal) || + dc_is_dvi_signal(stream->signal) || + (dc_is_dp_signal(stream->signal) && !stream->dpms_off)) + active_count++; + } + + for (i = 0; i < dc->link_count; i++) { + const struct dc_link *link = dc->links[i]; + + /* abusing the fact that the dig and phy are coupled to see if the phy is enabled */ + if (link->link_enc && link->link_enc->funcs->is_dig_enabled && + link->link_enc->funcs->is_dig_enabled(link->link_enc)) + active_count++; + } + + return active_count > 0; +} + +static uint32_t dcn42_get_clock_freq_from_clkip(struct clk_mgr *clk_mgr_base, enum clock_type clock) +{ + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); + uint64_t clock_freq_mhz = 0; + uint32_t timer_threshold = 0; + + // always safer to read the timer threshold instead of using cached value + REG_GET(CLK8_CLK_TICK_CNT_CONFIG_REG, TIMER_THRESHOLD, &timer_threshold); + + if (timer_threshold == 0) { + BREAK_TO_DEBUGGER(); + return 0; + } + + switch (clock) { + case clock_type_dispclk: + clock_freq_mhz = REG_READ(CLK8_CLK0_CURRENT_CNT); + break; + case clock_type_dppclk: + clock_freq_mhz = REG_READ(CLK8_CLK1_CURRENT_CNT); + break; + case clock_type_dprefclk: + clock_freq_mhz = REG_READ(CLK8_CLK2_CURRENT_CNT); + break; + case clock_type_dcfclk: + clock_freq_mhz = REG_READ(CLK8_CLK3_CURRENT_CNT); + break; + case clock_type_dtbclk: + clock_freq_mhz = REG_READ(CLK8_CLK4_CURRENT_CNT); + break; + default: + break; + } + + clock_freq_mhz *= DCN42_CLKIP_REFCLK; + clock_freq_mhz = div_u64(clock_freq_mhz, timer_threshold); + + // there are no DCN clocks over 0xFFFFFFFF MHz + ASSERT(clock_freq_mhz <= 0xFFFFFFFF); + + return (uint32_t)clock_freq_mhz; +} + +void dcn42_update_clocks_update_dtb_dto(struct clk_mgr_internal *clk_mgr, + struct dc_state *context, + int ref_dtbclk_khz) +{ + (void)clk_mgr; + (void)context; + (void)ref_dtbclk_khz; + /* DCN42 does not implement set_dtbclk_dto function, so this is a no-op */ +} + +void dcn42_update_clocks_update_dpp_dto(struct clk_mgr_internal *clk_mgr, + struct dc_state *context, bool safe_to_lower) +{ + int i; + bool dppclk_active[MAX_PIPES] = {0}; + + + clk_mgr->dccg->ref_dppclk = clk_mgr->base.clks.dppclk_khz; + for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) { + int dpp_inst = 0, dppclk_khz, prev_dppclk_khz; + + dppclk_khz = context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz; + + if (context->res_ctx.pipe_ctx[i].plane_res.dpp) + dpp_inst = context->res_ctx.pipe_ctx[i].plane_res.dpp->inst; + else if (!context->res_ctx.pipe_ctx[i].plane_res.dpp && dppclk_khz == 0) { + /* dpp == NULL && dppclk_khz == 0 is valid because of pipe harvesting. + * In this case just continue in loop + */ + continue; + } else if (!context->res_ctx.pipe_ctx[i].plane_res.dpp && dppclk_khz > 0) { + /* The software state is not valid if dpp resource is NULL and + * dppclk_khz > 0. + */ + ASSERT(false); + continue; + } + + prev_dppclk_khz = clk_mgr->dccg->pipe_dppclk_khz[i]; + + if (safe_to_lower || prev_dppclk_khz < dppclk_khz) + clk_mgr->dccg->funcs->update_dpp_dto( + clk_mgr->dccg, dpp_inst, dppclk_khz); + dppclk_active[dpp_inst] = true; + } + if (safe_to_lower) + for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) { + struct dpp *old_dpp = clk_mgr->base.ctx->dc->current_state->res_ctx.pipe_ctx[i].plane_res.dpp; + + if (old_dpp && !dppclk_active[old_dpp->inst]) + clk_mgr->dccg->funcs->update_dpp_dto(clk_mgr->dccg, old_dpp->inst, 0); + } +} + +void dcn42_update_clocks(struct clk_mgr *clk_mgr_base, + struct dc_state *context, + bool safe_to_lower) +{ + union dmub_rb_cmd cmd; + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); + struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk; + struct dc *dc = clk_mgr_base->ctx->dc; + bool update_dppclk = false; + bool update_dispclk = false; + bool dpp_clock_lowered = false; + bool has_active_display; + + if (dc->work_arounds.skip_clock_update) + return; + + has_active_display = dcn42_has_active_display(dc, context); + + if (new_clocks->dtbclk_en && new_clocks->ref_dtbclk_khz < 590000) + new_clocks->ref_dtbclk_khz = 600000; + /* + * if it is safe to lower, but we are already in the lower state, we don't have to do anything + * also if safe to lower is false, we just go in the higher state + */ + if (safe_to_lower) { + if (new_clocks->zstate_support != DCN_ZSTATE_SUPPORT_DISALLOW && + new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) { + dcn42_smu_set_zstate_support(clk_mgr, new_clocks->zstate_support); + clk_mgr_base->clks.zstate_support = new_clocks->zstate_support; + } + + if (clk_mgr_base->clks.dtbclk_en && !new_clocks->dtbclk_en) { + if (clk_mgr->base.ctx->dc->config.allow_0_dtb_clk) + dcn42_smu_set_dtbclk(clk_mgr, false); + clk_mgr_base->clks.dtbclk_en = new_clocks->dtbclk_en; + } + /* check that we're not already in lower */ + if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_LOW_POWER) { + /* if we can go lower, go lower */ + if (has_active_display == false) + clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_LOW_POWER; + } + } else { + if (new_clocks->zstate_support == DCN_ZSTATE_SUPPORT_DISALLOW && + new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) { + dcn42_smu_set_zstate_support(clk_mgr, DCN_ZSTATE_SUPPORT_DISALLOW); + clk_mgr_base->clks.zstate_support = new_clocks->zstate_support; + } + /* Only attempt to enable dtbclk if currently disabled AND new state requests it. + * For dcn42b (no dtbclk hardware), init_clk_states sets dtbclk_en=false and + * new_clocks->dtbclk_en should always be false, so this block never executes. + */ + if (!clk_mgr_base->clks.dtbclk_en && new_clocks->dtbclk_en) { + int actual_dtbclk = 0; + + dcn42_update_clocks_update_dtb_dto(clk_mgr, context, new_clocks->ref_dtbclk_khz); + dcn42_smu_set_dtbclk(clk_mgr, true); + actual_dtbclk = dcn42_get_clock_freq_from_clkip(clk_mgr_base, clock_type_dtbclk); + + if (actual_dtbclk > 590000) { + clk_mgr_base->clks.ref_dtbclk_khz = new_clocks->ref_dtbclk_khz; + clk_mgr_base->clks.dtbclk_en = new_clocks->dtbclk_en; + } + } + + /* check that we're not already in D0 */ + if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_MISSION_MODE) { + union display_idle_optimization_u idle_info = { 0 }; + + dcn42_smu_set_display_idle_optimization(clk_mgr, idle_info.data); + /* update power state */ + clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_MISSION_MODE; + } + } + if (dc->debug.force_min_dcfclk_mhz > 0) + new_clocks->dcfclk_khz = (new_clocks->dcfclk_khz > (dc->debug.force_min_dcfclk_mhz * 1000)) ? + new_clocks->dcfclk_khz : (dc->debug.force_min_dcfclk_mhz * 1000); + + if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, clk_mgr_base->clks.dcfclk_khz)) { + clk_mgr_base->clks.dcfclk_khz = new_clocks->dcfclk_khz; + clk_mgr_base->clks.fclk_khz = new_clocks->fclk_khz; + clk_mgr_base->clks.dramclk_khz = new_clocks->dramclk_khz; + dcn42_smu_set_hard_min_dcfclk(clk_mgr, clk_mgr_base->clks.dcfclk_khz); + } + + if (should_set_clock(safe_to_lower, + new_clocks->dcfclk_deep_sleep_khz, clk_mgr_base->clks.dcfclk_deep_sleep_khz)) { + clk_mgr_base->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz; + + /* Clamp the requested clock to PMFW based on DCN limit. */ + if (dc->debug.min_deep_sleep_dcfclk_khz > 0 && clk_mgr_base->clks.dcfclk_deep_sleep_khz < dc->debug.min_deep_sleep_dcfclk_khz) + clk_mgr_base->clks.dcfclk_deep_sleep_khz = dc->debug.min_deep_sleep_dcfclk_khz; + + dcn42_smu_set_min_deep_sleep_dcfclk(clk_mgr, clk_mgr_base->clks.dcfclk_deep_sleep_khz); + } + + // workaround: Limit dppclk to 100Mhz to avoid lower eDP panel switch to plus 4K monitor underflow. + + if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->base.clks.dppclk_khz)) { + if (clk_mgr->base.clks.dppclk_khz > new_clocks->dppclk_khz) + dpp_clock_lowered = true; + clk_mgr_base->clks.dppclk_khz = new_clocks->dppclk_khz; + update_dppclk = true; + } + + if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz) && + (new_clocks->dispclk_khz > 0 || (safe_to_lower && has_active_display == false))) { + int requested_dispclk_khz = new_clocks->dispclk_khz; + + dcn35_disable_otg_wa(clk_mgr_base, context, safe_to_lower, true); + + /* Clamp the requested clock to PMFW based on their limit. */ + if (dc->debug.min_disp_clk_khz > 0 && requested_dispclk_khz < dc->debug.min_disp_clk_khz) + requested_dispclk_khz = dc->debug.min_disp_clk_khz; + + dcn42_smu_set_dispclk(clk_mgr, requested_dispclk_khz); + clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz; + dcn35_disable_otg_wa(clk_mgr_base, context, safe_to_lower, false); + + update_dispclk = true; + } + + /* clock limits are received with MHz precision, divide by 1000 to prevent setting clocks at every call */ + if (!dc->debug.disable_dtb_ref_clk_switch && new_clocks->dtbclk_en && + should_set_clock(safe_to_lower, new_clocks->ref_dtbclk_khz / 1000, + clk_mgr_base->clks.ref_dtbclk_khz / 1000)) { + dcn42_update_clocks_update_dtb_dto(clk_mgr, context, new_clocks->ref_dtbclk_khz); + clk_mgr_base->clks.ref_dtbclk_khz = new_clocks->ref_dtbclk_khz; + } + + if (dpp_clock_lowered) { + // increase per DPP DTO before lowering global dppclk + dcn42_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower); + dcn42_smu_set_dppclk(clk_mgr, clk_mgr_base->clks.dppclk_khz); + } else { + // increase global DPPCLK before lowering per DPP DTO + if (update_dppclk || update_dispclk) + dcn42_smu_set_dppclk(clk_mgr, clk_mgr_base->clks.dppclk_khz); + dcn42_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower); + } + // notify DMCUB of latest clocks + memset(&cmd, 0, sizeof(cmd)); + cmd.notify_clocks.header.type = DMUB_CMD__CLK_MGR; + cmd.notify_clocks.header.sub_type = DMUB_CMD__CLK_MGR_NOTIFY_CLOCKS; + cmd.notify_clocks.clocks.dcfclk_khz = clk_mgr_base->clks.dcfclk_khz; + cmd.notify_clocks.clocks.dcfclk_deep_sleep_khz = + clk_mgr_base->clks.dcfclk_deep_sleep_khz; + cmd.notify_clocks.clocks.dispclk_khz = clk_mgr_base->clks.dispclk_khz; + cmd.notify_clocks.clocks.dppclk_khz = clk_mgr_base->clks.dppclk_khz; + + dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); +} + + +void dcn42_enable_pme_wa(struct clk_mgr *clk_mgr_base) +{ + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); + + dcn42_smu_enable_pme_wa(clk_mgr); +} + + +bool dcn42_are_clock_states_equal(struct dc_clocks *a, + struct dc_clocks *b) +{ + if (a->dispclk_khz != b->dispclk_khz) + return false; + else if (a->dppclk_khz != b->dppclk_khz) + return false; + else if (a->dcfclk_khz != b->dcfclk_khz) + return false; + else if (a->dcfclk_deep_sleep_khz != b->dcfclk_deep_sleep_khz) + return false; + else if (a->zstate_support != b->zstate_support) + return false; + else if (a->dtbclk_en != b->dtbclk_en) + return false; + + return true; +} + +static void dcn42_dump_clk_registers_internal(struct dcn42_clk_internal *internal, struct clk_mgr *clk_mgr_base) +{ + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); + + REG_GET(CLK8_CLK_TICK_CNT_CONFIG_REG, TIMER_THRESHOLD, &internal->CLK8_CLK_TICK_CNT__TIMER_THRESHOLD); + + // read dcf deep sleep divider + internal->CLK8_CLK0_DS_CNTL = REG_READ(CLK8_CLK0_DS_CNTL); + internal->CLK8_CLK3_DS_CNTL = REG_READ(CLK8_CLK3_DS_CNTL); + // read dispclk + internal->CLK8_CLK0_CURRENT_CNT = dcn42_get_clock_freq_from_clkip(clk_mgr_base, clock_type_dispclk); + internal->CLK8_CLK0_BYPASS_CNTL = REG_READ(CLK8_CLK0_BYPASS_CNTL); + // read dppclk + internal->CLK8_CLK1_CURRENT_CNT = dcn42_get_clock_freq_from_clkip(clk_mgr_base, clock_type_dppclk); + internal->CLK8_CLK1_BYPASS_CNTL = REG_READ(CLK8_CLK1_BYPASS_CNTL); + // read dprefclk + internal->CLK8_CLK2_CURRENT_CNT = dcn42_get_clock_freq_from_clkip(clk_mgr_base, clock_type_dprefclk); + internal->CLK8_CLK2_BYPASS_CNTL = REG_READ(CLK8_CLK2_BYPASS_CNTL); + // read dcfclk + internal->CLK8_CLK3_CURRENT_CNT = dcn42_get_clock_freq_from_clkip(clk_mgr_base, clock_type_dcfclk); + internal->CLK8_CLK3_BYPASS_CNTL = REG_READ(CLK8_CLK3_BYPASS_CNTL); + // read dtbclk + internal->CLK8_CLK4_CURRENT_CNT = dcn42_get_clock_freq_from_clkip(clk_mgr_base, clock_type_dtbclk); + internal->CLK8_CLK4_BYPASS_CNTL = REG_READ(CLK8_CLK4_BYPASS_CNTL); +} + +static void dcn42_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass, + struct clk_mgr_dcn42 *clk_mgr) +{ + struct dcn42_clk_internal internal = {0}; + char *bypass_clks[5] = {"0x0 DFS", "0x1 REFCLK", "0x2 ERROR", "0x3 400 FCH", "0x4 600 FCH"}; + + DC_LOGGER_INIT(clk_mgr->base.base.ctx->logger); + (void)dc_logger; + + dcn42_dump_clk_registers_internal(&internal, &clk_mgr->base.base); + regs_and_bypass->timer_threshold = internal.CLK8_CLK_TICK_CNT__TIMER_THRESHOLD; + regs_and_bypass->dcfclk = internal.CLK8_CLK3_CURRENT_CNT / 10; + regs_and_bypass->dcf_deep_sleep_divider = internal.CLK8_CLK3_DS_CNTL / 10; + regs_and_bypass->dcf_deep_sleep_allow = internal.CLK8_CLK3_DS_CNTL & 0x10; /*bit 4: CLK0_ALLOW_DS*/ + regs_and_bypass->dprefclk = internal.CLK8_CLK2_CURRENT_CNT / 10; + regs_and_bypass->dispclk = internal.CLK8_CLK0_CURRENT_CNT / 10; + regs_and_bypass->dppclk = internal.CLK8_CLK1_CURRENT_CNT / 10; + regs_and_bypass->dtbclk = internal.CLK8_CLK4_CURRENT_CNT / 10; + + regs_and_bypass->dispclk_bypass = get_reg_field_value(internal.CLK8_CLK0_BYPASS_CNTL, CLK8_CLK0_BYPASS_CNTL, CLK0_BYPASS_SEL); + regs_and_bypass->dppclk_bypass = get_reg_field_value(internal.CLK8_CLK1_BYPASS_CNTL, CLK8_CLK1_BYPASS_CNTL, CLK1_BYPASS_SEL); + regs_and_bypass->dprefclk_bypass = get_reg_field_value(internal.CLK8_CLK2_BYPASS_CNTL, CLK8_CLK2_BYPASS_CNTL, CLK2_BYPASS_SEL); + regs_and_bypass->dcfclk_bypass = get_reg_field_value(internal.CLK8_CLK3_BYPASS_CNTL, CLK8_CLK3_BYPASS_CNTL, CLK3_BYPASS_SEL); + + if (clk_mgr->base.base.ctx->dc->debug.pstate_enabled) { + DC_LOG_SMU("clk_type,clk_value,deepsleep_cntl,deepsleep_allow,bypass\n"); + + DC_LOG_SMU("dcfclk,%d,%d,%d,%s\n", + regs_and_bypass->dcfclk, + regs_and_bypass->dcf_deep_sleep_divider, + regs_and_bypass->dcf_deep_sleep_allow, + bypass_clks[(int) regs_and_bypass->dcfclk_bypass]); + + DC_LOG_SMU("dprefclk,%d,N/A,N/A,%s\n", + regs_and_bypass->dprefclk, + bypass_clks[(int) regs_and_bypass->dprefclk_bypass]); + + DC_LOG_SMU("dispclk,%d,N/A,N/A,%s\n", + regs_and_bypass->dispclk, + bypass_clks[(int) regs_and_bypass->dispclk_bypass]); + + //split + DC_LOG_SMU("SPLIT\n"); + + // REGISTER VALUES + DC_LOG_SMU("reg_name,value,clk_type\n"); + DC_LOG_SMU("CLK1_CLK3_CURRENT_CNT,%d,dcfclk\n", + internal.CLK8_CLK3_CURRENT_CNT); + + DC_LOG_SMU("CLK1_CLK3_DS_CNTL,%d,dcf_deep_sleep_divider\n", + internal.CLK8_CLK3_DS_CNTL); + + DC_LOG_SMU("CLK1_CLK3_ALLOW_DS,%d,dcf_deep_sleep_allow\n", + (internal.CLK8_CLK3_DS_CNTL & 0x10)); + + DC_LOG_SMU("CLK1_CLK2_CURRENT_CNT,%d,dprefclk\n", + internal.CLK8_CLK2_CURRENT_CNT); + + DC_LOG_SMU("CLK1_CLK0_CURRENT_CNT,%d,dispclk\n", + internal.CLK8_CLK0_CURRENT_CNT); + + DC_LOG_SMU("CLK1_CLK1_CURRENT_CNT,%d,dppclk\n", + internal.CLK8_CLK1_CURRENT_CNT); + + DC_LOG_SMU("CLK1_CLK4_CURRENT_CNT,%d,dtbclk\n", + internal.CLK8_CLK4_CURRENT_CNT); + + DC_LOG_SMU("CLK1_CLK3_BYPASS_CNTL,%d,dcfclk_bypass\n", + internal.CLK8_CLK3_BYPASS_CNTL); + + DC_LOG_SMU("CLK1_CLK2_BYPASS_CNTL,%d,dprefclk_bypass\n", + internal.CLK8_CLK2_BYPASS_CNTL); + + DC_LOG_SMU("CLK1_CLK0_BYPASS_CNTL,%d,dispclk_bypass\n", + internal.CLK8_CLK0_BYPASS_CNTL); + + DC_LOG_SMU("CLK1_CLK1_BYPASS_CNTL,%d,dppclk_bypass\n", + internal.CLK8_CLK1_BYPASS_CNTL); + } +} + +bool dcn42_is_spll_ssc_enabled(struct clk_mgr *clk_mgr_base) +{ + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); + struct dc_context *ctx = clk_mgr->base.ctx; + + + if (ctx->dc->config.ignore_dpref_ss) { + /*revert bios's ss info for test only*/ + return (clk_mgr->dprefclk_ss_percentage == 0); + } + /*need to update after BU*/ + return false; +} + +static void init_clk_states(struct clk_mgr *clk_mgr) +{ + uint32_t ref_dtbclk = clk_mgr->clks.ref_dtbclk_khz; + + memset(&(clk_mgr->clks), 0, sizeof(struct dc_clocks)); + + clk_mgr->clks.dtbclk_en = true; // request DTBCLK disable on first commit + clk_mgr->clks.ref_dtbclk_khz = ref_dtbclk; // restore ref_dtbclk + clk_mgr->clks.p_state_change_support = true; + clk_mgr->clks.prev_p_state_change_support = true; + clk_mgr->clks.pwr_state = DCN_PWR_STATE_UNKNOWN; + clk_mgr->clks.zstate_support = DCN_ZSTATE_SUPPORT_UNKNOWN; +} + +void dcn42_get_dpm_table_from_smu(struct clk_mgr_internal *clk_mgr, + struct dcn42_smu_dpm_clks *smu_dpm_clks) +{ + DpmClocks_t_dcn42 *table = smu_dpm_clks->dpm_clks; + + if (!clk_mgr->smu_ver) + return; + + if (!table || smu_dpm_clks->mc_address.quad_part == 0) + return; + + memset(table, 0, sizeof(*table)); + + dcn42_smu_set_dram_addr_high(clk_mgr, + smu_dpm_clks->mc_address.high_part); + dcn42_smu_set_dram_addr_low(clk_mgr, + smu_dpm_clks->mc_address.low_part); + dcn42_smu_transfer_dpm_table_smu_2_dram(clk_mgr); +} + +void dcn42_init_single_clock(unsigned int *entry_0, + uint32_t *smu_entry_0, + uint8_t num_levels) +{ + int i; + char *entry_i = (char *)entry_0; + + ASSERT(num_levels <= MAX_NUM_DPM_LVL); + if (num_levels > MAX_NUM_DPM_LVL) + num_levels = MAX_NUM_DPM_LVL; + + + for (i = 0; i < num_levels; i++) { + *((unsigned int *)entry_i) = smu_entry_0[i]; + entry_i += sizeof(struct clk_limit_table_entry); + } +} + +unsigned int dcn42_convert_wck_ratio(uint8_t wck_ratio) +{ + switch (wck_ratio) { + case WCK_RATIO_1_2: + return 2; + + case WCK_RATIO_1_4: + return 4; + + default: + break; + } + + return 1; +} + +void dcn42_init_clocks(struct clk_mgr *clk_mgr_base) +{ + struct clk_mgr_internal *clk_mgr_int = TO_CLK_MGR_INTERNAL(clk_mgr_base); + struct clk_mgr_dcn42 *clk_mgr = TO_CLK_MGR_DCN42(clk_mgr_int); + + DC_LOGGER_INIT(clk_mgr_base->ctx->logger); + (void)dc_logger; + + init_clk_states(clk_mgr_base); + + // to adjust dp_dto reference clock if ssc is enable otherwise to apply dprefclk + if (dcn42_is_spll_ssc_enabled(clk_mgr_base)) + clk_mgr_base->dp_dto_source_clock_in_khz = + dce_adjust_dp_ref_freq_for_ss(clk_mgr_int, clk_mgr_base->dprefclk_khz); + else + clk_mgr_base->dp_dto_source_clock_in_khz = clk_mgr_base->dprefclk_khz; + + DC_LOG_SMU("dp_dto_source_clock %d, dprefclk %d\n", clk_mgr_base->dp_dto_source_clock_in_khz, clk_mgr_base->dprefclk_khz); + dcn42_dump_clk_registers(&clk_mgr_base->boot_snapshot, clk_mgr); + + clk_mgr_base->clks.ref_dtbclk_khz = clk_mgr_base->boot_snapshot.dtbclk * 10; + clk_mgr_base->clks.dtbclk_en = clk_mgr_base->boot_snapshot.dtbclk > 59000; +} + +static struct clk_bw_params dcn42_bw_params = { + .vram_type = Ddr4MemType, + .num_channels = 1, + .clk_table = { + .num_entries = 4, + }, + +}; + +static struct wm_table ddr5_wm_table = { + .entries = { + { + .wm_inst = WM_A, + .wm_type = WM_TYPE_PSTATE_CHG, + .pstate_latency_us = 11.72, + .sr_exit_time_us = 28.0, + .sr_enter_plus_exit_time_us = 30.0, + .valid = true, + }, + { + .wm_inst = WM_B, + .wm_type = WM_TYPE_PSTATE_CHG, + .pstate_latency_us = 11.72, + .sr_exit_time_us = 28.0, + .sr_enter_plus_exit_time_us = 30.0, + .valid = true, + }, + { + .wm_inst = WM_C, + .wm_type = WM_TYPE_PSTATE_CHG, + .pstate_latency_us = 11.72, + .sr_exit_time_us = 28.0, + .sr_enter_plus_exit_time_us = 30.0, + .valid = true, + }, + { + .wm_inst = WM_D, + .wm_type = WM_TYPE_PSTATE_CHG, + .pstate_latency_us = 11.72, + .sr_exit_time_us = 28.0, + .sr_enter_plus_exit_time_us = 30.0, + .valid = true, + }, + } +}; + +static struct wm_table lpddr5_wm_table = { + .entries = { + { + .wm_inst = WM_A, + .wm_type = WM_TYPE_PSTATE_CHG, + .pstate_latency_us = 11.65333, + .sr_exit_time_us = 28.0, + .sr_enter_plus_exit_time_us = 30.0, + .valid = true, + }, + { + .wm_inst = WM_B, + .wm_type = WM_TYPE_PSTATE_CHG, + .pstate_latency_us = 11.65333, + .sr_exit_time_us = 28.0, + .sr_enter_plus_exit_time_us = 30.0, + .valid = true, + }, + { + .wm_inst = WM_C, + .wm_type = WM_TYPE_PSTATE_CHG, + .pstate_latency_us = 11.65333, + .sr_exit_time_us = 28.0, + .sr_enter_plus_exit_time_us = 30.0, + .valid = true, + }, + { + .wm_inst = WM_D, + .wm_type = WM_TYPE_PSTATE_CHG, + .pstate_latency_us = 11.65333, + .sr_exit_time_us = 28.0, + .sr_enter_plus_exit_time_us = 30.0, + .valid = true, + }, + } +}; + +struct dcn42_ss_info_table dcn42_ss_info_table = { + .ss_divider = 1000, + .ss_percentage = {0, 0, 375, 375, 375} +}; + +static void dcn42_read_ss_info_from_lut(struct clk_mgr_internal *clk_mgr) +{ + uint32_t clock_source; + + clock_source = (REG_READ(CLK8_CLK2_BYPASS_CNTL) & CLK8_CLK2_BYPASS_CNTL__CLK2_BYPASS_SEL_MASK); + // If it's DFS mode, clock_source is 0. + if (dcn42_is_spll_ssc_enabled(&clk_mgr->base) && (clock_source < ARRAY_SIZE(dcn42_ss_info_table.ss_percentage))) { + clk_mgr->dprefclk_ss_percentage = dcn42_ss_info_table.ss_percentage[clock_source]; + + if (clk_mgr->dprefclk_ss_percentage != 0) { + clk_mgr->ss_on_dprefclk = true; + clk_mgr->dprefclk_ss_divider = dcn42_ss_info_table.ss_divider; + } + } +} + +void dcn42_build_watermark_ranges(struct clk_bw_params *bw_params, struct dcn42_watermarks *table) +{ + int i, num_valid_sets; + + num_valid_sets = 0; + + for (i = 0; i < WM_SET_COUNT; i++) { + /* skip empty entries, the smu array has no holes*/ + if (!bw_params->wm_table.entries[i].valid) + continue; + + table->WatermarkRow[WM_DCFCLK][num_valid_sets].WmSetting = bw_params->wm_table.entries[i].wm_inst; + table->WatermarkRow[WM_DCFCLK][num_valid_sets].WmType = bw_params->wm_table.entries[i].wm_type; + /* We will not select WM based on fclk, so leave it as unconstrained */ + table->WatermarkRow[WM_DCFCLK][num_valid_sets].MinClock = 0; + table->WatermarkRow[WM_DCFCLK][num_valid_sets].MaxClock = 0xFFFF; + + if (table->WatermarkRow[WM_DCFCLK][num_valid_sets].WmType == WM_TYPE_PSTATE_CHG) { + if (i == 0) + table->WatermarkRow[WM_DCFCLK][num_valid_sets].MinMclk = 0; + else { + /* add 1 to make it non-overlapping with next lvl */ + table->WatermarkRow[WM_DCFCLK][num_valid_sets].MinMclk = + bw_params->clk_table.entries[i - 1].dcfclk_mhz + 1; + } + table->WatermarkRow[WM_DCFCLK][num_valid_sets].MaxMclk = + bw_params->clk_table.entries[i].dcfclk_mhz; + + } else { + /* unconstrained for memory retraining */ + table->WatermarkRow[WM_DCFCLK][num_valid_sets].MinClock = 0; + table->WatermarkRow[WM_DCFCLK][num_valid_sets].MaxClock = 0xFFFF; + + /* Modify previous watermark range to cover up to max */ + if (num_valid_sets > 0) + table->WatermarkRow[WM_DCFCLK][num_valid_sets - 1].MaxClock = 0xFFFF; + } + num_valid_sets++; + } + + ASSERT(num_valid_sets != 0); /* Must have at least one set of valid watermarks */ + + /* modify the min and max to make sure we cover the whole range*/ + table->WatermarkRow[WM_DCFCLK][0].MinMclk = 0; + table->WatermarkRow[WM_DCFCLK][0].MinClock = 0; + table->WatermarkRow[WM_DCFCLK][num_valid_sets - 1].MaxMclk = 0xFFFF; + table->WatermarkRow[WM_DCFCLK][num_valid_sets - 1].MaxClock = 0xFFFF; + + /* This is for writeback only, does not matter currently as no writeback support*/ + table->WatermarkRow[WM_SOCCLK][0].WmSetting = WM_A; + table->WatermarkRow[WM_SOCCLK][0].MinClock = 0; + table->WatermarkRow[WM_SOCCLK][0].MaxClock = 0xFFFF; + table->WatermarkRow[WM_SOCCLK][0].MinMclk = 0; + table->WatermarkRow[WM_SOCCLK][0].MaxMclk = 0xFFFF; +} + +void dcn42_notify_wm_ranges(struct clk_mgr *clk_mgr_base) +{ + int i = 0; + struct dcn42_watermarks *table = NULL; + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); + struct clk_mgr_dcn42 *clk_mgr_dcn42 = TO_CLK_MGR_DCN42(clk_mgr); + + if (!clk_mgr->smu_ver) + return; + /*send once already skip*/ + if (clk_mgr_base->bw_params->wm_table.entries[WM_A].valid == true) + return; + clk_mgr_dcn42->smu_wm_set.wm_set = (struct dcn42_watermarks *)dm_helpers_allocate_gpu_mem( + clk_mgr->base.ctx, + DC_MEM_ALLOC_TYPE_GART, + sizeof(struct dcn42_watermarks), + &clk_mgr_dcn42->smu_wm_set.mc_address.quad_part); + + ASSERT(clk_mgr_dcn42->smu_wm_set.wm_set); + + table = clk_mgr_dcn42->smu_wm_set.wm_set; + + if (!table || clk_mgr_dcn42->smu_wm_set.mc_address.quad_part == 0) + return; + + memset(table, 0, sizeof(*table)); + /*same as previous asic, set wm valid before building watermark ranges*/ + for (i = 0; i < WM_SET_COUNT; i++) { + clk_mgr_base->bw_params->wm_table.entries[i].wm_inst = i; + + if (i >= clk_mgr_base->bw_params->clk_table.num_entries) { + clk_mgr_base->bw_params->wm_table.entries[i].valid = false; + continue; + } + clk_mgr_base->bw_params->wm_table.entries[i].wm_type = WM_TYPE_PSTATE_CHG; + clk_mgr_base->bw_params->wm_table.entries[i].valid = true; + } + /* build watermark_range will check this valid range*/ + dcn42_build_watermark_ranges(clk_mgr_base->bw_params, table); + + dcn42_smu_set_dram_addr_high(clk_mgr, + clk_mgr_dcn42->smu_wm_set.mc_address.high_part); + dcn42_smu_set_dram_addr_low(clk_mgr, + clk_mgr_dcn42->smu_wm_set.mc_address.low_part); + dcn42_smu_transfer_wm_table_dram_2_smu(clk_mgr); + + if (clk_mgr_dcn42->smu_wm_set.wm_set && clk_mgr_dcn42->smu_wm_set.mc_address.quad_part != 0) + dm_helpers_free_gpu_mem(clk_mgr->base.ctx, DC_MEM_ALLOC_TYPE_GART, + clk_mgr_dcn42->smu_wm_set.wm_set); + +} + +void dcn42_set_low_power_state(struct clk_mgr *clk_mgr_base) +{ + struct dc *dc = clk_mgr_base->ctx->dc; + struct dc_state *context = dc->current_state; + + if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_LOW_POWER) { + /* if we can go lower, go lower */ + if (dcn42_has_active_display(dc, context) == false) + clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_LOW_POWER; + } + + if (clk_mgr_base->clks.pwr_state == DCN_PWR_STATE_LOW_POWER) { + union display_idle_optimization_u idle_info = { 0 }; + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); + + idle_info.idle_info.df_request_disabled = 1; + idle_info.idle_info.phy_ref_clk_off = 1; + idle_info.idle_info.s0i2_rdy = 1; + dcn42_smu_set_display_idle_optimization(clk_mgr, idle_info.data); + } +} + +void dcn42_exit_low_power_state(struct clk_mgr *clk_mgr_base) +{ + (void)clk_mgr_base; + +} + +static void dcn42_init_clocks_fpga(struct clk_mgr *clk_mgr) +{ + init_clk_states(clk_mgr); + +} + +void dcn42_update_clocks_fpga(struct clk_mgr *clk_mgr, + struct dc_state *context, + bool safe_to_lower) +{ + struct clk_mgr_internal *clk_mgr_int = TO_CLK_MGR_INTERNAL(clk_mgr); + struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk; + int fclk_adj = new_clocks->fclk_khz; + + /* TODO: remove this after correctly set by DML */ + new_clocks->dcfclk_khz = 400000; + new_clocks->socclk_khz = 400000; + + /* Min fclk = 1.2GHz since all the extra scemi logic seems to run off of it */ + //int fclk_adj = new_clocks->fclk_khz > 1200000 ? new_clocks->fclk_khz : 1200000; + new_clocks->fclk_khz = 4320000; + + if (should_set_clock(safe_to_lower, new_clocks->phyclk_khz, clk_mgr->clks.phyclk_khz)) + clk_mgr->clks.phyclk_khz = new_clocks->phyclk_khz; + + if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, clk_mgr->clks.dcfclk_khz)) + clk_mgr->clks.dcfclk_khz = new_clocks->dcfclk_khz; + + if (should_set_clock(safe_to_lower, + new_clocks->dcfclk_deep_sleep_khz, clk_mgr->clks.dcfclk_deep_sleep_khz)) + clk_mgr->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz; + + if (should_set_clock(safe_to_lower, new_clocks->socclk_khz, clk_mgr->clks.socclk_khz)) + clk_mgr->clks.socclk_khz = new_clocks->socclk_khz; + + if (should_set_clock(safe_to_lower, new_clocks->dramclk_khz, clk_mgr->clks.dramclk_khz)) + clk_mgr->clks.dramclk_khz = new_clocks->dramclk_khz; + + if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->clks.dppclk_khz)) + clk_mgr->clks.dppclk_khz = new_clocks->dppclk_khz; + + if (should_set_clock(safe_to_lower, fclk_adj, clk_mgr->clks.fclk_khz)) + clk_mgr->clks.fclk_khz = fclk_adj; + + if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr->clks.dispclk_khz)) + clk_mgr->clks.dispclk_khz = new_clocks->dispclk_khz; + + /* Both fclk and ref_dppclk run on the same scemi clock. + * So take the higher value since the DPP DTO is typically programmed + * such that max dppclk is 1:1 with ref_dppclk. + */ + if (clk_mgr->clks.fclk_khz > clk_mgr->clks.dppclk_khz) + clk_mgr->clks.dppclk_khz = clk_mgr->clks.fclk_khz; + if (clk_mgr->clks.dppclk_khz > clk_mgr->clks.fclk_khz) + clk_mgr->clks.fclk_khz = clk_mgr->clks.dppclk_khz; + + // Both fclk and ref_dppclk run on the same scemi clock. + clk_mgr_int->dccg->ref_dppclk = clk_mgr->clks.fclk_khz; + + dm_set_dcn_clocks(clk_mgr->ctx, &clk_mgr->clks); + if (clk_mgr->clks.dtbclk_en) { + dcn42_update_clocks_update_dtb_dto(clk_mgr_int, context, clk_mgr->clks.ref_dtbclk_khz); + } else { + clk_mgr->clks.ref_dtbclk_khz = 0; + } + dcn42_update_clocks_update_dpp_dto(clk_mgr_int, context, safe_to_lower); +} + +unsigned int dcn42_get_max_clock_khz(struct clk_mgr *clk_mgr_base, enum clk_type clk_type) +{ + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); + + unsigned int num_clk_levels; + + switch (clk_type) { + case CLK_TYPE_DISPCLK: + num_clk_levels = clk_mgr->base.bw_params->clk_table.num_entries_per_clk.num_dispclk_levels; + return num_clk_levels ? + clk_mgr->base.bw_params->clk_table.entries[num_clk_levels - 1].dispclk_mhz * 1000 : + clk_mgr->base.boot_snapshot.dispclk; + case CLK_TYPE_DPPCLK: + num_clk_levels = clk_mgr->base.bw_params->clk_table.num_entries_per_clk.num_dppclk_levels; + return num_clk_levels ? + clk_mgr->base.bw_params->clk_table.entries[num_clk_levels - 1].dppclk_mhz * 1000 : + clk_mgr->base.boot_snapshot.dppclk; + case CLK_TYPE_DSCCLK: + num_clk_levels = clk_mgr->base.bw_params->clk_table.num_entries_per_clk.num_dispclk_levels; + return num_clk_levels ? + clk_mgr->base.bw_params->clk_table.entries[num_clk_levels - 1].dispclk_mhz * 1000 / 3 : + clk_mgr->base.boot_snapshot.dispclk / 3; + default: + break; + } + + return 0; +} + +int dcn42_get_dispclk_from_dentist(struct clk_mgr *clk_mgr_base) +{ + (void)clk_mgr_base; + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); + uint32_t dispclk_wdivider; + int disp_divider; + + REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, &dispclk_wdivider); + disp_divider = dentist_get_divider_from_did(dispclk_wdivider); + + /* Return DISPCLK freq in Khz */ + if (disp_divider) + return (DENTIST_DIVIDER_RANGE_SCALE_FACTOR * clk_mgr->base.dentist_vco_freq_khz) / disp_divider; + + return 0; +} +bool dcn42_is_smu_present(struct clk_mgr *clk_mgr_base) +{ + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); + return clk_mgr->smu_present; +} + +void dcn42_get_smu_clocks(struct clk_mgr_internal *clk_mgr_int) +{ + struct clk_mgr *clk_mgr_base = &clk_mgr_int->base; + struct dcn42_smu_dpm_clks smu_dpm_clks = { 0 }; + + DC_LOGGER_INIT(clk_mgr_base->ctx->logger); + (void)dc_logger; + + smu_dpm_clks.dpm_clks = (DpmClocks_t_dcn42 *)dm_helpers_allocate_gpu_mem( + clk_mgr_base->ctx, + DC_MEM_ALLOC_TYPE_GART, + sizeof(DpmClocks_t_dcn42), + &smu_dpm_clks.mc_address.quad_part); + + ASSERT(smu_dpm_clks.dpm_clks); + if (clk_mgr_base->ctx->dc->debug.pstate_enabled && smu_dpm_clks.mc_address.quad_part != 0) { + int i; + DpmClocks_t_dcn42 *dpm_clks = smu_dpm_clks.dpm_clks; + + dcn42_get_dpm_table_from_smu(clk_mgr_int, &smu_dpm_clks); + DC_LOG_SMU("NumDcfClkLevelsEnabled: %d\n" + "NumDispClkLevelsEnabled: %d\n" + "NumSocClkLevelsEnabled: %d\n" + "VcnClkLevelsEnabled: %d\n" + "FClkLevelsEnabled: %d\n" + "NumMemPstatesEnabled: %d\n" + "MinGfxClk: %d\n" + "MaxGfxClk: %d\n", + dpm_clks->NumDcfClkLevelsEnabled, + dpm_clks->NumDispClkLevelsEnabled, + dpm_clks->NumSocClkLevelsEnabled, + dpm_clks->VcnClkLevelsEnabled, + dpm_clks->NumFclkLevelsEnabled, + dpm_clks->NumMemPstatesEnabled, + dpm_clks->MinGfxClk, + dpm_clks->MaxGfxClk); + + for (i = 0; i < NUM_DCFCLK_DPM_LEVELS; i++) { + DC_LOG_SMU("dpm_clks->DcfClocks[%d] = %d\n", + i, + dpm_clks->DcfClocks[i]); + } + for (i = 0; i < NUM_DISPCLK_DPM_LEVELS; i++) { + DC_LOG_SMU("dpm_clks->DispClocks[%d] = %d\n", + i, dpm_clks->DispClocks[i]); + } + for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++) { + DC_LOG_SMU("dpm_clks->SocClocks[%d] = %d\n", + i, dpm_clks->SocClocks[i]); + } + for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++) { + DC_LOG_SMU("dpm_clks->FclkClocks_Freq[%d] = %d\n", + i, dpm_clks->FclkClocks_Freq[i]); + DC_LOG_SMU("dpm_clks->FclkClocks_Voltage[%d] = %d\n", + i, dpm_clks->FclkClocks_Voltage[i]); + } + for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++) + DC_LOG_SMU("dpm_clks->SocVoltage[%d] = %d\n", + i, dpm_clks->SocVoltage[i]); + + for (i = 0; i < NUM_MEM_PSTATE_LEVELS; i++) { + DC_LOG_SMU("dpm_clks.MemPstateTable[%d].UClk = %d\n" + "dpm_clks->MemPstateTable[%d].MemClk= %d\n" + "dpm_clks->MemPstateTable[%d].Voltage = %d\n", + i, dpm_clks->MemPstateTable[i].UClk, + i, dpm_clks->MemPstateTable[i].MemClk, + i, dpm_clks->MemPstateTable[i].Voltage); + } + + if (clk_mgr_base->ctx->dc_bios->integrated_info && clk_mgr_base->ctx->dc->config.use_default_clock_table == false) { + /* DCFCLK */ + dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].dcfclk_mhz, + dpm_clks->DcfClocks, + dpm_clks->NumDcfClkLevelsEnabled); + clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dcfclk_levels = dpm_clks->NumDcfClkLevelsEnabled; + + /* SOCCLK */ + dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].socclk_mhz, + dpm_clks->SocClocks, + dpm_clks->NumSocClkLevelsEnabled); + clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_socclk_levels = dpm_clks->NumSocClkLevelsEnabled; + + /* DISPCLK */ + dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].dispclk_mhz, + dpm_clks->DispClocks, + dpm_clks->NumDispClkLevelsEnabled); + clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dispclk_levels = dpm_clks->NumDispClkLevelsEnabled; + + /* DPPCLK */ + dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].dppclk_mhz, + dpm_clks->DppClocks, + dpm_clks->NumDispClkLevelsEnabled); + clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dppclk_levels = dpm_clks->NumDispClkLevelsEnabled; + + /* FCLK */ + dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].fclk_mhz, + dpm_clks->FclkClocks_Freq, + NUM_FCLK_DPM_LEVELS); + clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_fclk_levels = dpm_clks->NumFclkLevelsEnabled; + clk_mgr_base->bw_params->clk_table.num_entries = dpm_clks->NumFclkLevelsEnabled; + + /* Memory Pstate table is in reverse order*/ + ASSERT(dpm_clks->NumMemPstatesEnabled <= NUM_MEM_PSTATE_LEVELS); + if (dpm_clks->NumMemPstatesEnabled > NUM_MEM_PSTATE_LEVELS) + dpm_clks->NumMemPstatesEnabled = NUM_MEM_PSTATE_LEVELS; + for (i = 0; i < dpm_clks->NumMemPstatesEnabled; i++) { + clk_mgr_base->bw_params->clk_table.entries[dpm_clks->NumMemPstatesEnabled - 1 - i].memclk_mhz = dpm_clks->MemPstateTable[i].MemClk; + clk_mgr_base->bw_params->clk_table.entries[dpm_clks->NumMemPstatesEnabled - 1 - i].wck_ratio = dcn42_convert_wck_ratio(dpm_clks->MemPstateTable[i].WckRatio) ; + } + clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_memclk_levels = dpm_clks->NumMemPstatesEnabled; + + /* DTBCLK*/ + clk_mgr_base->bw_params->clk_table.entries[0].dtbclk_mhz = 600; /* Fixed on platform */ + clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dtbclk_levels = 1; + } + } + if (smu_dpm_clks.dpm_clks && smu_dpm_clks.mc_address.quad_part != 0) + dm_helpers_free_gpu_mem(clk_mgr_base->ctx, DC_MEM_ALLOC_TYPE_GART, + smu_dpm_clks.dpm_clks); +} + +static struct clk_mgr_funcs dcn42_funcs = { + .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz, + .get_dtb_ref_clk_frequency = dcn31_get_dtb_ref_freq_khz, + .update_clocks = dcn42_update_clocks, + .init_clocks = dcn42_init_clocks, + .enable_pme_wa = dcn42_enable_pme_wa, + .are_clock_states_equal = dcn42_are_clock_states_equal, + .notify_wm_ranges = dcn42_notify_wm_ranges, + .set_low_power_state = dcn42_set_low_power_state, + .exit_low_power_state = dcn42_exit_low_power_state, + .get_max_clock_khz = dcn42_get_max_clock_khz, + .get_dispclk_from_dentist = dcn42_get_dispclk_from_dentist, + .is_smu_present = dcn42_is_smu_present, +}; + +struct clk_mgr_funcs dcn42_fpga_funcs = { + .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz, + .update_clocks = dcn42_update_clocks_fpga, + .init_clocks = dcn42_init_clocks_fpga, + .get_dtb_ref_clk_frequency = dcn31_get_dtb_ref_freq_khz, +}; + +void dcn42_clk_mgr_construct( + struct dc_context *ctx, + struct clk_mgr_dcn42 *clk_mgr, + struct pp_smu_funcs *pp_smu, + struct dccg *dccg) +{ + clk_mgr->base.base.ctx = ctx; + clk_mgr->base.base.funcs = &dcn42_funcs; + clk_mgr->base.regs = &clk_mgr_regs_dcn42; + clk_mgr->base.clk_mgr_shift = &clk_mgr_shift_dcn42; + clk_mgr->base.clk_mgr_mask = &clk_mgr_mask_dcn42; + + clk_mgr->base.pp_smu = pp_smu; + + clk_mgr->base.dccg = dccg; + clk_mgr->base.dfs_bypass_disp_clk = 0; + + clk_mgr->base.dprefclk_ss_percentage = 0; + clk_mgr->base.dprefclk_ss_divider = 1000; + clk_mgr->base.ss_on_dprefclk = false; + clk_mgr->base.dfs_ref_freq_khz = 48000; /*sync with pmfw*/ + clk_mgr->base.base.clks.ref_dtbclk_khz = 600000; + + /* Changed from DCN3.2_clock_frequency doc to match + * dcn32_dump_clk_registers from 4 * dentist_vco_freq_khz / + * dprefclk DID divider + */ + clk_mgr->base.base.dprefclk_khz = 600000; + + clk_mgr->base.smu_present = false; + clk_mgr->base.smu_ver = dcn42_smu_get_pmfw_version(&clk_mgr->base); + if (clk_mgr->base.smu_ver && clk_mgr->base.smu_ver != -1) + clk_mgr->base.smu_present = true; + + if (ctx->dc_bios->integrated_info) { + clk_mgr->base.base.dentist_vco_freq_khz = ctx->dc_bios->integrated_info->dentist_vco_freq; + + if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) + dcn42_bw_params.wm_table = lpddr5_wm_table; + else + dcn42_bw_params.wm_table = ddr5_wm_table; + dcn42_bw_params.vram_type = ctx->dc_bios->integrated_info->memory_type; + dcn42_bw_params.dram_channel_width_bytes = ctx->dc_bios->integrated_info->memory_type == 0x22 ? 8 : 4; + dcn42_bw_params.num_channels = ctx->dc_bios->integrated_info->ma_channel_number ? ctx->dc_bios->integrated_info->ma_channel_number : 1; + clk_mgr->base.base.dprefclk_khz = dcn42_smu_get_dprefclk(&clk_mgr->base); + clk_mgr->base.base.clks.ref_dtbclk_khz = dcn42_smu_get_dtbclk(&clk_mgr->base); + + clk_mgr->base.base.bw_params = &dcn42_bw_params; + + if (clk_mgr->base.smu_present) + dcn42_get_smu_clocks(&clk_mgr->base); + } + /* in case we don't get a value from the BIOS, use default */ + if (clk_mgr->base.base.dentist_vco_freq_khz == 0) + clk_mgr->base.base.dentist_vco_freq_khz = 3000000; /* 3000MHz */ + + /* Saved clocks configured at boot for debug purposes */ + dcn42_dump_clk_registers(&clk_mgr->base.base.boot_snapshot, clk_mgr); + + dce_clock_read_ss_info(&clk_mgr->base); + /*when clk src is from FCH, it could have ss, same clock src as DPREF clk*/ + + dcn42_read_ss_info_from_lut(&clk_mgr->base); + + clk_mgr->base.base.bw_params = &dcn42_bw_params; + if (clk_mgr->base.smu_present) + dcn42_get_smu_clocks(&clk_mgr->base); +} + +void dcn42_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr_int) +{ + struct clk_mgr_dcn42 *clk_mgr = TO_CLK_MGR_DCN42(clk_mgr_int); + + if (clk_mgr->smu_wm_set.wm_set && clk_mgr->smu_wm_set.mc_address.quad_part != 0) + dm_helpers_free_gpu_mem(clk_mgr_int->base.ctx, DC_MEM_ALLOC_TYPE_GART, + clk_mgr->smu_wm_set.wm_set); +} diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.h new file mode 100644 index 000000000000..9568ca06f00f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.h @@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2026 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef __DCN42_CLK_MGR_H__ +#define __DCN42_CLK_MGR_H__ +#include "clk_mgr_internal.h" + +#define NUM_CLOCK_SOURCES 5 +#define DCN42_CLKIP_REFCLK 48000 + +struct dcn42_watermarks; + +struct dcn42_smu_watermark_set { + struct dcn42_watermarks *wm_set; + union large_integer mc_address; +}; + +struct dcn42_ss_info_table { + uint32_t ss_divider; + uint32_t ss_percentage[NUM_CLOCK_SOURCES]; +}; + +struct clk_mgr_dcn42 { + struct clk_mgr_internal base; + struct dcn42_smu_watermark_set smu_wm_set; +}; + +bool dcn42_are_clock_states_equal(struct dc_clocks *a, + struct dc_clocks *b); +void dcn42_init_clocks(struct clk_mgr *clk_mgr); +void dcn42_update_clocks(struct clk_mgr *clk_mgr_base, + struct dc_state *context, + bool safe_to_lower); + +void dcn42_clk_mgr_construct(struct dc_context *ctx, + struct clk_mgr_dcn42 *clk_mgr, + struct pp_smu_funcs *pp_smu, + struct dccg *dccg); + +void dcn42_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr_int); + +void dcn42_init_single_clock(unsigned int *entry_0, + uint32_t *smu_entry_0, + uint8_t num_levels); +unsigned int dcn42_convert_wck_ratio(uint8_t wck_ratio); +extern struct dcn42_ss_info_table dcn42_ss_info_table; +void dcn42_build_watermark_ranges(struct clk_bw_params *bw_params, struct dcn42_watermarks *table); +void dcn42_enable_pme_wa(struct clk_mgr *clk_mgr_base); +void dcn42_notify_wm_ranges(struct clk_mgr *clk_mgr_base); +void dcn42_set_low_power_state(struct clk_mgr *clk_mgr_base); +void dcn42_exit_low_power_state(struct clk_mgr *clk_mgr_base); +unsigned int dcn42_get_max_clock_khz(struct clk_mgr *clk_mgr_base, enum clk_type clk_type); +bool dcn42_is_smu_present(struct clk_mgr *clk_mgr_base); +bool dcn42_has_active_display(struct dc *dc, const struct dc_state *context); +int dcn42_get_active_display_cnt_wa(struct dc *dc, struct dc_state *context, int *all_active_disps); +bool dcn42_has_active_display(struct dc *dc, const struct dc_state *context); +void dcn42_update_clocks_update_dpp_dto(struct clk_mgr_internal *clk_mgr, struct dc_state *context, bool safe_to_lower); +void dcn42_update_clocks_update_dtb_dto(struct clk_mgr_internal *clk_mgr, struct dc_state *context, int ref_dtbclk_khz); +bool dcn42_is_spll_ssc_enabled(struct clk_mgr *clk_mgr_base); +struct dcn42_smu_dpm_clks; /* Forward declaration for pointer parameter below */ +void dcn42_get_dpm_table_from_smu(struct clk_mgr_internal *clk_mgr, struct dcn42_smu_dpm_clks *smu_dpm_clks); +void dcn42_get_smu_clocks(struct clk_mgr_internal *clk_mgr_int); +void dcn42_update_clocks_fpga(struct clk_mgr *clk_mgr, struct dc_state *context, bool safe_to_lower); +int dcn42_get_dispclk_from_dentist(struct clk_mgr *clk_mgr_base); +#endif //__DCN42_CLK_MGR_H__ diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_smu.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_smu.c new file mode 100644 index 000000000000..c791bb1edb47 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_smu.c @@ -0,0 +1,431 @@ +// SPDX-License-Identifier: MIT +// +// Copyright 2026 Advanced Micro Devices, Inc. + + + +#include "core_types.h" +#include "clk_mgr_internal.h" +#include "reg_helper.h" +#include "dm_helpers.h" +#include "dcn42_smu.h" + +#include "mp/mp_15_0_0_offset.h" +#include "mp/mp_15_0_0_sh_mask.h" + +#ifdef BASE_INNER +#undef BASE_INNER +#endif + +#define MP1_BASE__INST0_SEG0 0x00016000 +#define MP1_BASE__INST0_SEG1 0x00016200 +#define MP1_BASE__INST0_SEG2 0x00E00000 +#define MP1_BASE__INST0_SEG3 0x00E80000 +#define MP1_BASE__INST0_SEG4 0x00EC0000 +#define MP1_BASE__INST0_SEG5 0x00F00000 +#define MP1_BASE__INST0_SEG6 0x02400400 +#define MP1_BASE__INST0_SEG7 0x0243F400 +#define MP1_BASE__INST0_SEG8 0x3C004000 +#define MP1_BASE__INST0_SEG9 0x3C3F4000 + +#define BASE_INNER(seg) MP1_BASE__INST0_SEG ## seg + +#define BASE(seg) BASE_INNER(seg) + +#define REG(reg_name) (BASE(reg##reg_name##_BASE_IDX) + reg##reg_name) + +#define FN(reg_name, field) \ + FD(reg_name##__##field) + +#include "logger_types.h" +#undef DC_LOGGER +#define DC_LOGGER \ + CTX->logger +#define smu_print(str, ...) {DC_LOG_SMU(str, ##__VA_ARGS__); } + +// VBIOS and DAL to PMFW Interface + +// DAL to PMFW interface registers +#define DAL_MSG_REG MP1_SMN_C2PMSG_71 +#define DAL_RESP_REG MP1_SMN_C2PMSG_72 +#define DAL_ARG_REG MP1_SMN_C2PMSG_73 + +/** @defgroup ResponseCodes PMFW Response Codes +* @{ +*/ +// SMU Response Codes: +#define DALSMC_Result_OK 0x01 ///< Message Response OK +#define DALSMC_Result_Failed 0xFF ///< Message Response Failed +#define DALSMC_Result_UnknownCmd 0xFE ///< Message Response Unknown Command +#define DALSMC_Result_CmdRejectedPrereq 0xFD ///< Message Response Command Failed Prerequisite +#define DALSMC_Result_CmdRejectedBusy 0xFC ///< Message Response Command Rejected due to PMFW is busy. Sender should retry sending this message +/** @}*/ + +// Message Definitions: +/** @defgroup definitions Message definitions +* @{ +*/ +#define DALSMC_MSG_TestMessage 0x01 ///< To check if PMFW is alive and responding. Requirement specified by PMFW team +#define DALSMC_MSG_GetPmfwVersion 0x02 ///< Get version +#define DALSMC_MSG_SetDispclkFreq 0x03 ///< Set display clock frequency in MHZ +#define DALSMC_MSG_SetDppclkFreq 0x04 ///< Set DPP clock frequency in MHZ +#define DALSMC_MSG_SetHardMinDcfclkByFreq 0x05 ///< Set DCF clock frequency hard min in MHZ +#define DALSMC_MSG_SetMinDeepSleepDcfclk 0x06 ///< Set DCF clock minimum frequency in deep sleep in MHZ +#define DALSMC_MSG_UpdatePmeRestore 0x07 ///< To ask PMFW to write into Azalia for PME wake up event +#define DALSMC_MSG_SetDramAddrHigh 0x08 ///< Set DRAM address high 32 bits for WM table transfer +#define DALSMC_MSG_SetDramAddrLow 0x09 ///< Set DRAM address low 32 bits for WM table transfer + +#define DALSMC_MSG_TransferTableSmu2Dram 0x0A ///< Transfer table from PMFW SRAM to system DRAM +#define DALSMC_MSG_TransferTableDram2Smu 0x0B ///< Transfer table from system DRAM to PMFW +#define DALSMC_MSG_SetDisplayIdleOptimizations 0x0C ///< Set Idle state optimization for display off +#define DALSMC_MSG_GetDprefclkFreq 0x0D ///< Get DPREF clock frequency. Return in MHZ +#define DALSMC_MSG_GetDtbclkFreq 0x0E ///< Get DTB clock frequency. Return in MHZ +#define DALSMC_MSG_AllowZstatesEntry 0x0F ///< Inform PMFW of display allowing Zstate entry +#define DALSMC_MSG_SetDtbClk 0x10 ///< Inform PMFW to turn of/off DTB cl0ck. arg = 1: turn DTB on with 600MHZ; arg = 0: turn DTB clk off +#define DALSMC_MSG_DispIPS2Exit 0x11 ///< Display IPS2 exit + +#define DALSMC_MSG_QueryIPS2Support 0x12 ///< Return 1: support; else not supported +#define DALSMC_Message_Count 0x13 ///< Total number of VBIS and DAL messages +/** @}*/ + + +union dcn42_dpia_host_router_bw { + struct { + uint32_t hr_id : 16; + uint32_t bw_mbps : 16; + } bits; + uint32_t all; +}; + +/* + * Function to be used instead of REG_WAIT macro because the wait ends when + * the register is NOT EQUAL to zero, and because `the translation in msg_if.h + * won't work with REG_WAIT. + */ +static uint32_t dcn42_smu_wait_for_response(struct clk_mgr_internal *clk_mgr, + unsigned int delay_us, unsigned int max_retries) +{ + uint32_t res_val; + + do { + res_val = REG_READ(DAL_RESP_REG); + if (res_val != DALSMC_Result_CmdRejectedBusy) + break; + + if (delay_us >= 1000) + msleep(delay_us/1000); + else if (delay_us > 0) + udelay(delay_us); + + if (clk_mgr->base.ctx->dc->debug.disable_timeout) + max_retries++; + } while (max_retries--); + + return res_val; +} + +static int dcn42_smu_send_msg_with_param(struct clk_mgr_internal *clk_mgr, + unsigned int msg_id, + unsigned int param) +{ + uint32_t result; + + result = dcn42_smu_wait_for_response(clk_mgr, 10, 2000000); + + if (result != DALSMC_Result_OK) { + DC_LOG_WARNING("SMU response after wait: %d, msg id = %d\n", result, msg_id); + + if (result == DALSMC_Result_CmdRejectedBusy) + return -1; + } + + /* First clear response register */ + REG_WRITE(DAL_RESP_REG, DALSMC_Result_CmdRejectedBusy); + + /* Set the parameter register for the SMU message, unit is Mhz */ + REG_WRITE(DAL_ARG_REG, param); + + /* Trigger the message transaction by writing the message ID */ + REG_WRITE(DAL_MSG_REG, msg_id); + + result = dcn42_smu_wait_for_response(clk_mgr, 10, 2000000); + + if (result == DALSMC_Result_Failed) { + if (msg_id == DALSMC_MSG_TransferTableDram2Smu && + param == TABLE_WATERMARKS) + DC_LOG_WARNING("Watermarks table not configured properly by SMU"); + REG_WRITE(DAL_RESP_REG, DALSMC_Result_OK); + DC_LOG_WARNING("SMU response after wait: %d, msg id = %d\n", result, msg_id); + return -1; + } + + if (IS_SMU_TIMEOUT(result)) { + ASSERT(0); + result = dcn42_smu_wait_for_response(clk_mgr, 10, 2000000); + //dm_helpers_smu_timeout(CTX, msg_id, param, 10 * 200000); + DC_LOG_WARNING("SMU response after wait: %d, msg id = %d\n", result, msg_id); + } + + return REG_READ(DAL_ARG_REG); +} + +int dcn42_smu_get_pmfw_version(struct clk_mgr_internal *clk_mgr) +{ + return dcn42_smu_send_msg_with_param( + clk_mgr, + DALSMC_MSG_GetPmfwVersion, + 0); +} + + +int dcn42_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispclk_khz) +{ + int actual_dispclk_set_mhz; + + if (!clk_mgr->smu_present) + return requested_dispclk_khz; + + /* Unit of SMU msg parameter is Mhz */ + actual_dispclk_set_mhz = dcn42_smu_send_msg_with_param( + clk_mgr, + DALSMC_MSG_SetDispclkFreq, + khz_to_mhz_ceil(requested_dispclk_khz)); + + smu_print("requested_dispclk_khz = %d, actual_dispclk_set_mhz: %d\n", + requested_dispclk_khz, actual_dispclk_set_mhz); + return (int)((long long)actual_dispclk_set_mhz * 1000); +} + + +int dcn42_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_dcfclk_khz) +{ + int actual_dcfclk_set_mhz; + + if (!clk_mgr->smu_present) + return requested_dcfclk_khz; + + actual_dcfclk_set_mhz = dcn42_smu_send_msg_with_param( + clk_mgr, + DALSMC_MSG_SetHardMinDcfclkByFreq, + khz_to_mhz_ceil(requested_dcfclk_khz)); + + smu_print("requested_dcfclk_khz = %d, actual_dcfclk_set_mhz: %d\n", + requested_dcfclk_khz, actual_dcfclk_set_mhz); + + return (int)((long long)actual_dcfclk_set_mhz * 1000); +} + +int dcn42_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_min_ds_dcfclk_khz) +{ + int actual_min_ds_dcfclk_mhz; + + if (!clk_mgr->smu_present) + return requested_min_ds_dcfclk_khz; + + actual_min_ds_dcfclk_mhz = dcn42_smu_send_msg_with_param( + clk_mgr, + DALSMC_MSG_SetMinDeepSleepDcfclk, + khz_to_mhz_ceil(requested_min_ds_dcfclk_khz)); + + smu_print("requested_min_ds_dcfclk_khz = %d, actual_min_ds_dcfclk_mhz: %d\n", + requested_min_ds_dcfclk_khz, actual_min_ds_dcfclk_mhz); + + return (int)((long long)actual_min_ds_dcfclk_mhz * 1000); +} + +int dcn42_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz) +{ + int actual_dppclk_set_mhz; + + if (!clk_mgr->smu_present) + return requested_dpp_khz; + + actual_dppclk_set_mhz = dcn42_smu_send_msg_with_param( + clk_mgr, + DALSMC_MSG_SetDppclkFreq, + khz_to_mhz_ceil(requested_dpp_khz)); + + smu_print("requested_dpp_khz = %d, actual_dppclk_set_mhz: %d\n", + requested_dpp_khz, actual_dppclk_set_mhz); + + return (int)((long long)actual_dppclk_set_mhz * 1000); +} + +void dcn42_smu_set_display_idle_optimization(struct clk_mgr_internal *clk_mgr, uint32_t idle_info) +{ + if (!clk_mgr->base.ctx->dc->debug.pstate_enabled) + return; + + if (!clk_mgr->smu_present) + return; + + dcn42_smu_send_msg_with_param( + clk_mgr, + DALSMC_MSG_SetDisplayIdleOptimizations, + idle_info); + smu_print("%s: SMC_MSG_SetDisplayIdleOptimizations idle_info = %x\n", __func__, idle_info); +} + +void dcn42_smu_enable_phy_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr, bool enable) +{ + union display_idle_optimization_u idle_info = { 0 }; + + if (!clk_mgr->smu_present) + return; + + if (enable) { + idle_info.idle_info.df_request_disabled = 1; + idle_info.idle_info.phy_ref_clk_off = 1; + } + + dcn42_smu_send_msg_with_param( + clk_mgr, + DALSMC_MSG_SetDisplayIdleOptimizations, + idle_info.data); + smu_print("%s smu_enable_phy_refclk_pwrdwn = %d\n", __func__, enable ? 1 : 0); +} + +void dcn42_smu_enable_pme_wa(struct clk_mgr_internal *clk_mgr) +{ + if (!clk_mgr->smu_present) + return; + + dcn42_smu_send_msg_with_param( + clk_mgr, + DALSMC_MSG_UpdatePmeRestore, + 0); + smu_print("%s: SMC_MSG_UpdatePmeRestore\n", __func__); +} + +void dcn42_smu_set_dram_addr_high(struct clk_mgr_internal *clk_mgr, uint32_t addr_high) +{ + if (!clk_mgr->smu_present) + return; + + dcn42_smu_send_msg_with_param(clk_mgr, + DALSMC_MSG_SetDramAddrHigh, addr_high); +} + +void dcn42_smu_set_dram_addr_low(struct clk_mgr_internal *clk_mgr, uint32_t addr_low) +{ + if (!clk_mgr->smu_present) + return; + + dcn42_smu_send_msg_with_param(clk_mgr, + DALSMC_MSG_SetDramAddrLow, addr_low); +} + +void dcn42_smu_transfer_dpm_table_smu_2_dram(struct clk_mgr_internal *clk_mgr) +{ + if (!clk_mgr->smu_present) + return; + + dcn42_smu_send_msg_with_param(clk_mgr, + DALSMC_MSG_TransferTableSmu2Dram, TABLE_DPMCLOCKS); +} + +void dcn42_smu_transfer_wm_table_dram_2_smu(struct clk_mgr_internal *clk_mgr) +{ + if (!clk_mgr->smu_present) + return; + + dcn42_smu_send_msg_with_param(clk_mgr, + DALSMC_MSG_TransferTableDram2Smu, TABLE_WATERMARKS); +} + +void dcn42_smu_set_zstate_support(struct clk_mgr_internal *clk_mgr, enum dcn_zstate_support_state support) +{ + unsigned int msg_id, param, retv; + + if (!clk_mgr->smu_present) + return; + + switch (support) { + + case DCN_ZSTATE_SUPPORT_ALLOW: + msg_id = DALSMC_MSG_AllowZstatesEntry; + param = (1 << 10) | (1 << 9) | (1 << 8); + smu_print("%s: SMC_MSG_AllowZstatesEntry msg = ALLOW, param = 0x%x\n", __func__, param); + break; + + case DCN_ZSTATE_SUPPORT_DISALLOW: + msg_id = DALSMC_MSG_AllowZstatesEntry; + param = 0; + smu_print("%s: SMC_MSG_AllowZstatesEntry msg_id = DISALLOW, param = 0x%x\n", __func__, param); + break; + + + case DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY: + msg_id = DALSMC_MSG_AllowZstatesEntry; + param = (1 << 10); + smu_print("%s: SMC_MSG_AllowZstatesEntry msg = ALLOW_Z10_ONLY, param = 0x%x\n", __func__, param); + break; + + case DCN_ZSTATE_SUPPORT_ALLOW_Z8_Z10_ONLY: + msg_id = DALSMC_MSG_AllowZstatesEntry; + param = (1 << 10) | (1 << 8); + smu_print("%s: SMC_MSG_AllowZstatesEntry msg = ALLOW_Z8_Z10_ONLY, param = 0x%x\n", __func__, param); + break; + + case DCN_ZSTATE_SUPPORT_ALLOW_Z8_ONLY: + msg_id = DALSMC_MSG_AllowZstatesEntry; + param = (1 << 8); + smu_print("%s: SMC_MSG_AllowZstatesEntry msg = ALLOW_Z8_ONLY, param = 0x%x\n", __func__, param); + break; + + default: //DCN_ZSTATE_SUPPORT_UNKNOWN + msg_id = DALSMC_MSG_AllowZstatesEntry; + param = 0; + break; + } + + + retv = dcn42_smu_send_msg_with_param( + clk_mgr, + msg_id, + param); + smu_print("%s: msg_id = %d, param = 0x%x, return = 0x%x\n", __func__, msg_id, param, retv); +} + +int dcn42_smu_get_dprefclk(struct clk_mgr_internal *clk_mgr) +{ + int dprefclk; + + if (!clk_mgr->smu_present) + return 0; + + dprefclk = dcn42_smu_send_msg_with_param(clk_mgr, + DALSMC_MSG_GetDprefclkFreq, + 0); + + smu_print("%s: SMU DPREF clk = %d mhz\n", __func__, dprefclk); + return (int)((long long)dprefclk * 1000); +} + +int dcn42_smu_get_dtbclk(struct clk_mgr_internal *clk_mgr) +{ + int dtbclk; + + if (!clk_mgr->smu_present) + return 0; + + dtbclk = dcn42_smu_send_msg_with_param(clk_mgr, + DALSMC_MSG_GetDtbclkFreq, + 0); + + smu_print("%s: get_dtbclk = %dmhz\n", __func__, dtbclk); + return (int)((long long)dtbclk * 1000); +} +/* Arg = 1: Turn DTB on; 0: Turn DTB CLK OFF. when it is on, it is 600MHZ */ +void dcn42_smu_set_dtbclk(struct clk_mgr_internal *clk_mgr, bool enable) +{ + if (!clk_mgr->smu_present) + return; + + dcn42_smu_send_msg_with_param( + clk_mgr, + DALSMC_MSG_SetDtbClk, + enable); + smu_print("%s: smu_set_dtbclk = %d\n", __func__, enable ? 1 : 0); +} + diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_smu.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_smu.h new file mode 100644 index 000000000000..8ba7ff04dc05 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_smu.h @@ -0,0 +1,190 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2026 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef DAL_DC_42_SMU_H_ +#define DAL_DC_42_SMU_H_ + +#include "os_types.h" + +#ifndef PMFW_DRIVER_IF_H +#define PMFW_DRIVER_IF_H +#define PMFW_DRIVER_IF_VERSION 7 + +typedef enum { + DSPCLK_DCFCLK = 0, + DSPCLK_DISPCLK, + DSPCLK_PIXCLK, + DSPCLK_PHYCLK, + DSPCLK_COUNT, +} DSPCLK_e; + +typedef struct { + uint16_t Freq; // in MHz + uint16_t Vid; // min voltage in SVI3 VID +} DisplayClockTable_t; + +typedef struct { + uint16_t MinClock; // This is either DCFCLK or SOCCLK (in MHz) + uint16_t MaxClock; // This is either DCFCLK or SOCCLK (in MHz) + uint16_t MinMclk; + uint16_t MaxMclk; + + uint8_t WmSetting; + uint8_t WmType; // Used for normal pstate change or memory retraining + uint8_t Padding[2]; +} WatermarkRowGeneric_t; + +#define NUM_WM_RANGES 4 +#define WM_PSTATE_CHG 0 +#define WM_RETRAINING 1 + +typedef enum { + WM_SOCCLK = 0, + WM_DCFCLK, + WM_COUNT, +} WM_CLOCK_e; + +typedef struct { + WatermarkRowGeneric_t WatermarkRow[WM_COUNT][NUM_WM_RANGES]; + + uint32_t MmHubPadding[7]; // SMU internal use +} Watermarks_t; + +#define NUM_DCFCLK_DPM_LEVELS 8 +#define NUM_DISPCLK_DPM_LEVELS 8 +#define NUM_DPPCLK_DPM_LEVELS 8 +#define NUM_SOCCLK_DPM_LEVELS 8 +#define NUM_VCN_DPM_LEVELS 8 +#define NUM_SOC_VOLTAGE_LEVELS 8 +#define NUM_VPE_DPM_LEVELS 8 +#define NUM_FCLK_DPM_LEVELS 8 +#define NUM_MEM_PSTATE_LEVELS 4 + +typedef enum { + WCK_RATIO_1_1 = 0, // DDR5, Wck:ck is always 1:1; + WCK_RATIO_1_2, + WCK_RATIO_1_4, + WCK_RATIO_MAX +} WCK_RATIO_e; + +typedef struct { + uint32_t UClk; + uint32_t MemClk; + uint32_t Voltage; + uint8_t WckRatio; + uint8_t Spare[3]; +} MemPstateTable_t; + + + // Watermarks + + +// Freq in MHz +// Voltage in milli volts with 2 fractional bits +typedef struct { + uint32_t DcfClocks[NUM_DCFCLK_DPM_LEVELS]; + uint32_t DispClocks[NUM_DISPCLK_DPM_LEVELS]; + uint32_t DppClocks[NUM_DPPCLK_DPM_LEVELS]; + uint32_t SocClocks[NUM_SOCCLK_DPM_LEVELS]; + uint32_t VClocks[NUM_VCN_DPM_LEVELS]; + uint32_t DClocks[NUM_VCN_DPM_LEVELS]; + uint32_t VPEClocks[NUM_VPE_DPM_LEVELS]; + uint32_t FclkClocks_Freq[NUM_FCLK_DPM_LEVELS]; + uint32_t FclkClocks_Voltage[NUM_FCLK_DPM_LEVELS]; + uint32_t SocVoltage[NUM_SOC_VOLTAGE_LEVELS]; + MemPstateTable_t MemPstateTable[NUM_MEM_PSTATE_LEVELS]; + + uint8_t NumDcfClkLevelsEnabled; + uint8_t NumDispClkLevelsEnabled; //Applies to both Dispclk and Dppclk + uint8_t NumSocClkLevelsEnabled; + uint8_t VcnClkLevelsEnabled; //Applies to both Vclk and Dclk + + uint8_t VpeClkLevelsEnabled; + uint8_t NumMemPstatesEnabled; + uint8_t NumFclkLevelsEnabled; + uint8_t spare; + + uint32_t MinGfxClk; + uint32_t MaxGfxClk; +} DpmClocks_t_dcn42; + +// Throttler Status Bitmask + + +#define TABLE_BIOS_IF 0 // Called by BIOS +#define TABLE_WATERMARKS 1 // Called by DAL through VBIOS +#define TABLE_CUSTOM_DPM 2 // Called by Driver +#define TABLE_SPARE1 3 +#define TABLE_DPMCLOCKS 4 // Called by Driver +#define TABLE_MOMENTARY_PM 5 // Called by Tools +#define TABLE_MODERN_STDBY 6 // Called by Tools for Modern Standby Log +#define TABLE_SMU_METRICS 7 // Called by Driver +#define TABLE_COUNT 8 + +#endif + +struct dcn42_watermarks { + // Watermarks + WatermarkRowGeneric_t WatermarkRow[WM_COUNT][NUM_WM_RANGES]; + uint32_t MmHubPadding[7]; // SMU internal use +}; + +struct dcn42_smu_dpm_clks { + DpmClocks_t_dcn42 *dpm_clks; + union large_integer mc_address; +}; + +struct display_idle_optimization { + unsigned int df_request_disabled : 1; + unsigned int phy_ref_clk_off : 1; + unsigned int s0i2_rdy : 1; + unsigned int reserved : 29; +}; + +union display_idle_optimization_u { + struct display_idle_optimization idle_info; + uint32_t data; +}; + +int dcn42_smu_get_pmfw_version(struct clk_mgr_internal *clk_mgr); +int dcn42_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispclk_khz); +int dcn42_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_dcfclk_khz); +int dcn42_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_min_ds_dcfclk_khz); +int dcn42_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz); +void dcn42_smu_set_display_idle_optimization(struct clk_mgr_internal *clk_mgr, uint32_t idle_info); +void dcn42_smu_enable_phy_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr, bool enable); +void dcn42_smu_enable_pme_wa(struct clk_mgr_internal *clk_mgr); +void dcn42_smu_set_dram_addr_high(struct clk_mgr_internal *clk_mgr, uint32_t addr_high); +void dcn42_smu_set_dram_addr_low(struct clk_mgr_internal *clk_mgr, uint32_t addr_low); +void dcn42_smu_transfer_dpm_table_smu_2_dram(struct clk_mgr_internal *clk_mgr); +void dcn42_smu_transfer_wm_table_dram_2_smu(struct clk_mgr_internal *clk_mgr); + +void dcn42_smu_set_zstate_support(struct clk_mgr_internal *clk_mgr, enum dcn_zstate_support_state support); +void dcn42_smu_set_dtbclk(struct clk_mgr_internal *clk_mgr, bool enable); +void dcn42_vbios_smu_enable_48mhz_tmdp_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr, bool enable); + +int dcn42_smu_get_dtbclk(struct clk_mgr_internal *clk_mgr); +int dcn42_smu_get_dprefclk(struct clk_mgr_internal *clk_mgr); + +#endif /* DAL_DC_42_SMU_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 3e87b6a553be..419f894c87b0 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -443,75 +443,6 @@ static bool set_long_vtotal(struct dc *dc, struct dc_stream_state *stream, struc } /** - * dc_stream_adjust_vmin_vmax - look up pipe context & update parts of DRR - * @dc: dc reference - * @stream: Initial dc stream state - * @adjust: Updated parameters for vertical_total_min and vertical_total_max - * - * Looks up the pipe context of dc_stream_state and updates the - * vertical_total_min and vertical_total_max of the DRR, Dynamic Refresh - * Rate, which is a power-saving feature that targets reducing panel - * refresh rate while the screen is static - * - * Return: %true if the pipe context is found and adjusted; - * %false if the pipe context is not found. - */ -bool dc_stream_adjust_vmin_vmax(struct dc *dc, - struct dc_stream_state *stream, - struct dc_crtc_timing_adjust *adjust) -{ - int i; - - /* - * Don't adjust DRR while there's bandwidth optimizations pending to - * avoid conflicting with firmware updates. - */ - if (dc->ctx->dce_version > DCE_VERSION_MAX) { - if (dc->optimized_required && - (stream->adjust.v_total_max != adjust->v_total_max || - stream->adjust.v_total_min != adjust->v_total_min)) { - stream->adjust.timing_adjust_pending = true; - return false; - } - } - - dc_exit_ips_for_hw_access(dc); - - stream->adjust.v_total_max = adjust->v_total_max; - stream->adjust.v_total_mid = adjust->v_total_mid; - stream->adjust.v_total_mid_frame_num = adjust->v_total_mid_frame_num; - stream->adjust.v_total_min = adjust->v_total_min; - stream->adjust.allow_otg_v_count_halt = adjust->allow_otg_v_count_halt; - - if (dc->caps.max_v_total != 0 && - (adjust->v_total_max > dc->caps.max_v_total || adjust->v_total_min > dc->caps.max_v_total)) { - stream->adjust.timing_adjust_pending = false; - if (adjust->allow_otg_v_count_halt) - return set_long_vtotal(dc, stream, adjust); - else - return false; - } - - for (i = 0; i < MAX_PIPES; i++) { - struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; - - if (pipe->stream == stream && pipe->stream_res.tg) { - dc->hwss.set_drr(&pipe, - 1, - *adjust); - stream->adjust.timing_adjust_pending = false; - - if (dc->hwss.notify_cursor_offload_drr_update) - dc->hwss.notify_cursor_offload_drr_update(dc, dc->current_state, stream); - - return true; - } - } - - return false; -} - -/** * dc_stream_get_last_used_drr_vtotal - Looks up the pipe context of * dc_stream_state and gets the last VTOTAL used by DRR (Dynamic Refresh Rate) * @@ -1165,11 +1096,8 @@ static bool dc_construct(struct dc *dc, #ifdef CONFIG_DRM_AMD_DC_FP dc->clk_mgr->force_smu_not_present = init_params->force_smu_not_present; - if (dc->res_pool->funcs->update_bw_bounding_box) { - DC_FP_START(); + if (dc->res_pool->funcs->update_bw_bounding_box) dc->res_pool->funcs->update_bw_bounding_box(dc, dc->clk_mgr->bw_params); - DC_FP_END(); - } dc->soc_and_ip_translator = dc_create_soc_and_ip_translator(dc_ctx->dce_version); if (!dc->soc_and_ip_translator) goto fail; @@ -1206,6 +1134,8 @@ static void disable_all_writeback_pipes_for_stream( struct dc_stream_state *stream, struct dc_state *context) { + (void)dc; + (void)context; int i; for (i = 0; i < stream->num_wb_info; i++) @@ -1217,6 +1147,8 @@ static void apply_ctx_interdependent_lock(struct dc *dc, struct dc_stream_state *stream, bool lock) { + (void)dc; + (void)context; int i; /* Checks if interdependent update function pointer is NULL or not, takes care of DCE110 case */ @@ -1274,6 +1206,8 @@ static void dc_update_visual_confirm_color(struct dc *dc, struct dc_state *conte get_fams2_visual_confirm_color(dc, context, pipe_ctx, &(pipe_ctx->visual_confirm_color)); else if (dc->debug.visual_confirm == VISUAL_CONFIRM_VABC) get_vabc_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color)); + else if (dc->debug.visual_confirm == VISUAL_CONFIRM_BOOSTED_REFRESH_RATE) + get_refresh_rate_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color)); } } } @@ -1323,6 +1257,83 @@ void dc_get_visual_confirm_for_stream( } } +/** + * dc_stream_adjust_vmin_vmax - look up pipe context & update parts of DRR + * @dc: dc reference + * @stream: Initial dc stream state + * @adjust: Updated parameters for vertical_total_min and vertical_total_max + * + * Looks up the pipe context of dc_stream_state and updates the + * vertical_total_min and vertical_total_max of the DRR, Dynamic Refresh + * Rate, which is a power-saving feature that targets reducing panel + * refresh rate while the screen is static + * + * Return: %true if the pipe context is found and adjusted; + * %false if the pipe context is not found. + */ +bool dc_stream_adjust_vmin_vmax(struct dc *dc, + struct dc_stream_state *stream, + struct dc_crtc_timing_adjust *adjust) +{ + int i; + + /* + * Don't adjust DRR while there's bandwidth optimizations pending to + * avoid conflicting with firmware updates. + */ + if (dc->ctx->dce_version > DCE_VERSION_MAX) { + if (dc->optimized_required && + (stream->adjust.v_total_max != adjust->v_total_max || + stream->adjust.v_total_min != adjust->v_total_min)) { + stream->adjust.timing_adjust_pending = true; + return false; + } + } + + dc_exit_ips_for_hw_access(dc); + + stream->adjust.v_total_max = adjust->v_total_max; + stream->adjust.v_total_mid = adjust->v_total_mid; + stream->adjust.v_total_mid_frame_num = adjust->v_total_mid_frame_num; + stream->adjust.v_total_min = adjust->v_total_min; + stream->adjust.allow_otg_v_count_halt = adjust->allow_otg_v_count_halt; + + if (dc->caps.max_v_total != 0 && + (adjust->v_total_max > dc->caps.max_v_total || adjust->v_total_min > dc->caps.max_v_total)) { + stream->adjust.timing_adjust_pending = false; + if (adjust->allow_otg_v_count_halt) + return set_long_vtotal(dc, stream, adjust); + else + return false; + } + + for (i = 0; i < MAX_PIPES; i++) { + struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; + + if (pipe->stream == stream && pipe->stream_res.tg) { + dc->hwss.set_drr(&pipe, + 1, + *adjust); + stream->adjust.timing_adjust_pending = false; + + if (dc->debug.visual_confirm == VISUAL_CONFIRM_BOOSTED_REFRESH_RATE) { + if (pipe->stream && pipe->plane_state) { + dc_update_visual_confirm_color(dc, dc->current_state, pipe); + dc->hwss.update_visual_confirm_color(dc, pipe, pipe->plane_res.hubp->mpcc_id); + + } + } + + if (dc->hwss.notify_cursor_offload_drr_update) + dc->hwss.notify_cursor_offload_drr_update(dc, dc->current_state, stream); + + return true; + } + } + + return false; +} + static void disable_dangling_plane(struct dc *dc, struct dc_state *context) { int i, j; @@ -1553,8 +1564,7 @@ static void detect_edp_presence(struct dc *dc) struct dc_link *edp_links[MAX_NUM_EDP]; struct dc_link *edp_link = NULL; enum dc_connection_type type; - int i; - int edp_num; + unsigned int i, edp_num; dc_get_edp_links(dc, edp_links, &edp_num); if (!edp_num) @@ -1913,10 +1923,77 @@ bool dc_validate_boot_timing(const struct dc *dc, return false; } - /* block DSC for now, as VBIOS does not currently support DSC timings */ if (crtc_timing->flags.DSC) { - DC_LOG_DEBUG("boot timing validation failed due to DSC\n"); - return false; + struct display_stream_compressor *dsc = NULL; + struct dcn_dsc_state dsc_state = {0}; + + /* Find DSC associated with this timing generator */ + if (tg_inst < dc->res_pool->res_cap->num_dsc) { + dsc = dc->res_pool->dscs[tg_inst]; + } + + if (!dsc || !dsc->funcs->dsc_read_state) { + DC_LOG_DEBUG("boot timing validation failed due to no DSC resource or read function\n"); + return false; + } + + /* Read current DSC hardware state */ + dsc->funcs->dsc_read_state(dsc, &dsc_state); + + /* Check if DSC is actually enabled in hardware */ + if (dsc_state.dsc_clock_en == 0) { + DC_LOG_DEBUG("boot timing validation failed due to DSC not enabled in hardware\n"); + return false; + } + + uint32_t num_slices_h = 0; + uint32_t num_slices_v = 0; + + if (dsc_state.dsc_slice_width > 0) { + num_slices_h = (crtc_timing->h_addressable + dsc_state.dsc_slice_width - 1) / dsc_state.dsc_slice_width; + } + + if (dsc_state.dsc_slice_height > 0) { + num_slices_v = (crtc_timing->v_addressable + dsc_state.dsc_slice_height - 1) / dsc_state.dsc_slice_height; + } + + if (crtc_timing->dsc_cfg.num_slices_h != num_slices_h) { + DC_LOG_DEBUG("boot timing validation failed due to num_slices_h mismatch\n"); + return false; + } + + if (crtc_timing->dsc_cfg.num_slices_v != num_slices_v) { + DC_LOG_DEBUG("boot timing validation failed due to num_slices_v mismatch\n"); + return false; + } + + if (crtc_timing->dsc_cfg.bits_per_pixel != dsc_state.dsc_bits_per_pixel) { + DC_LOG_DEBUG("boot timing validation failed due to bits_per_pixel mismatch\n"); + return false; + } + + if (crtc_timing->dsc_cfg.block_pred_enable != dsc_state.dsc_block_pred_enable) { + DC_LOG_DEBUG("boot timing validation failed due to block_pred_enable mismatch\n"); + return false; + } + + if (crtc_timing->dsc_cfg.linebuf_depth != dsc_state.dsc_line_buf_depth) { + DC_LOG_DEBUG("boot timing validation failed due to linebuf_depth mismatch\n"); + return false; + } + + if (crtc_timing->dsc_cfg.version_minor != dsc_state.dsc_version_minor) { + DC_LOG_DEBUG("boot timing validation failed due to version_minor mismatch\n"); + return false; + } + + if (crtc_timing->dsc_cfg.ycbcr422_simple != dsc_state.dsc_simple_422) { + DC_LOG_DEBUG("boot timing validation failed due to pixel encoding mismatch\n"); + return false; + } + + // Skip checks for is_frl, is_dp, and rc_buffer_size which are not programmed by vbios + // or not necessary for seamless boot validation. } if (dc_is_dp_signal(link->connector_signal)) { @@ -2607,6 +2684,16 @@ void dc_post_update_surfaces_to_stream(struct dc *dc) dc->optimized_required = false; } +void dc_get_default_tiling_info(const struct dc *dc, struct dc_tiling_info *tiling_info) +{ + if (!dc || !tiling_info) + return; + if (dc->res_pool && dc->res_pool->funcs && dc->res_pool->funcs->get_default_tiling_info) { + dc->res_pool->funcs->get_default_tiling_info(tiling_info); + return; + } +} + bool dc_set_generic_gpio_for_stereo(bool enable, struct gpio_service *gpio_service) { @@ -2749,28 +2836,12 @@ static struct surface_update_descriptor get_plane_info_update_type(const struct if (memcmp(tiling, &u->surface->tiling_info, sizeof(*tiling)) != 0) { update_flags->bits.swizzle_change = 1; - elevate_update_type(&update_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM); - switch (tiling->gfxversion) { - case DcGfxVersion9: - case DcGfxVersion10: - case DcGfxVersion11: - if (tiling->gfx9.swizzle != DC_SW_LINEAR) { - update_flags->bits.bandwidth_change = 1; - elevate_update_type(&update_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL); - } - break; - case DcGfxAddr3: - if (tiling->gfx_addr3.swizzle != DC_ADDR3_SW_LINEAR) { - update_flags->bits.bandwidth_change = 1; - elevate_update_type(&update_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL); - } - break; - case DcGfxVersion7: - case DcGfxVersion8: - case DcGfxVersionUnknown: - default: - break; + if (tiling->flags.avoid_full_update_on_tiling_change) { + elevate_update_type(&update_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM); + } else { + update_flags->bits.bandwidth_change = 1; + elevate_update_type(&update_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL); } } @@ -2885,16 +2956,27 @@ static struct surface_update_descriptor det_surface_update( elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); } - if (u->blend_tf || (u->gamma && dce_use_lut(u->plane_info ? u->plane_info->format : u->surface->format))) { + if (u->cm || (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->lut3d_func || u->func_shaper) { + if (u->cm && (u->cm->flags.bits.lut3d_enable || u->surface->cm.flags.bits.lut3d_enable)) { 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? @@ -2909,24 +2991,15 @@ static struct surface_update_descriptor det_surface_update( elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL); } - 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 (u->cm_hist_control) { + update_flags->bits.cm_hist_change = 1; + elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); } - if (check_config->enable_legacy_fast_update && (update_flags->bits.gamma_change || update_flags->bits.gamut_remap_change || update_flags->bits.input_csc_change || + update_flags->bits.cm_hist_change || update_flags->bits.coeff_reduction_change)) { elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL); } @@ -2938,6 +3011,7 @@ static struct surface_update_descriptor det_surface_update( */ static void force_immediate_gsl_plane_flip(struct dc *dc, struct dc_surface_update *updates, int surface_count) { + (void)dc; bool has_flip_immediate_plane = false; int i; @@ -3064,7 +3138,7 @@ struct surface_update_descriptor dc_check_update_surfaces_for_stream( { if (stream_update) stream_update->stream->update_flags.raw = 0; - for (size_t i = 0; i < surface_count; i++) + for (int i = 0; i < surface_count; i++) updates[i].surface->update_flags.raw = 0; return check_update_surfaces_for_stream(check_config, updates, surface_count, stream_update); @@ -3158,6 +3232,11 @@ static void copy_surface_update_to_plane( surface->gamma_correction.type = srf_update->gamma->type; } + if (srf_update->cm_hist_control) { + memcpy(&surface->cm_hist_control, + srf_update->cm_hist_control, + sizeof(surface->cm_hist_control)); + } if (srf_update->in_transfer_func) { surface->in_transfer_func.sdr_ref_white_level = @@ -3171,24 +3250,12 @@ static void copy_surface_update_to_plane( sizeof(struct dc_transfer_func_distributed_points)); } - 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; + /* Shaper, 3DLUT, 1DLUT */ + if (srf_update->cm) { + memcpy(&surface->cm, srf_update->cm, + sizeof(surface->cm)); } - 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; @@ -3197,17 +3264,6 @@ 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; @@ -3234,6 +3290,7 @@ static void copy_stream_update_to_stream(struct dc *dc, struct dc_stream_state *stream, struct dc_stream_update *update) { + (void)context; struct dc_context *dc_ctx = dc->ctx; if (update == NULL || stream == NULL) @@ -3509,6 +3566,7 @@ static void restore_minimal_pipe_split_policy(struct dc *dc, * @surface_count: surface update count * @stream: Corresponding stream to be updated * @stream_update: stream update + * @update_descriptor: describes what plane and stream changes to apply * @new_update_type: [out] determined update type by the function * @new_context: [out] new context allocated and validated if update type is * FULL, reference to current context if update type is less than FULL. @@ -3837,6 +3895,7 @@ static void commit_planes_do_stream_update(struct dc *dc, static bool dc_dmub_should_send_dirty_rect_cmd(struct dc *dc, struct dc_stream_state *stream) { + (void)dc; if ((stream->link->psr_settings.psr_version == DC_PSR_VERSION_SU_1 || stream->link->psr_settings.psr_version == DC_PSR_VERSION_1) && stream->ctx->dce_version >= DCN_VERSION_3_1) @@ -4491,11 +4550,9 @@ 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].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 && + if (srf_updates[i].cm && + srf_updates[i].cm->flags.bits.lut3d_enable && + srf_updates[i].cm->flags.bits.lut3d_dma_enable && dc->hwss.trigger_3dlut_dma_load) dc->hwss.trigger_3dlut_dma_load(dc, pipe_ctx); @@ -4639,6 +4696,7 @@ static bool could_mpcc_tree_change_for_active_pipes(struct dc *dc, int surface_count, bool *is_plane_addition) { + (void)srf_updates; struct dc_stream_status *cur_stream_status = stream_get_status(dc->current_state, stream); bool force_minimal_pipe_splitting = false; @@ -5063,6 +5121,9 @@ void populate_fast_updates(struct dc_fast_update *fast_update, fast_update[i].input_csc_color_matrix = srf_updates[i].input_csc_color_matrix; fast_update[i].coeff_reduction_factor = srf_updates[i].coeff_reduction_factor; fast_update[i].cursor_csc_color_matrix = srf_updates[i].cursor_csc_color_matrix; +#if defined(CONFIG_DRM_AMD_DC_DCN4_2) + fast_update[i].cm_hist_control = srf_updates[i].cm_hist_control; +#endif } } @@ -5080,6 +5141,9 @@ static bool fast_updates_exist(const struct dc_fast_update *fast_update, int sur fast_update[i].gamut_remap_matrix || fast_update[i].input_csc_color_matrix || fast_update[i].cursor_csc_color_matrix || +#if defined(CONFIG_DRM_AMD_DC_DCN4_2) + fast_update[i].cm_hist_control || +#endif fast_update[i].coeff_reduction_factor) return true; } @@ -5100,6 +5164,9 @@ bool fast_nonaddr_updates_exist(struct dc_fast_update *fast_update, int surface_ fast_update[i].gamma || fast_update[i].gamut_remap_matrix || fast_update[i].coeff_reduction_factor || +#if defined(CONFIG_DRM_AMD_DC_DCN4_2) + fast_update[i].cm_hist_control || +#endif fast_update[i].cursor_csc_color_matrix) return true; } @@ -5114,6 +5181,7 @@ static bool full_update_required_weak( const struct dc_stream_update *stream_update, const struct dc_stream_state *stream) { + (void)stream_update; const struct dc_state *context = dc->current_state; if (srf_updates) for (int i = 0; i < surface_count; i++) @@ -5141,6 +5209,12 @@ 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; @@ -5153,14 +5227,12 @@ static bool full_update_required( (srf_updates[i].sdr_white_level_nits && srf_updates[i].sdr_white_level_nits != srf_updates->surface->sdr_white_level_nits) || srf_updates[i].in_transfer_func || - srf_updates[i].func_shaper || - srf_updates[i].lut3d_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].cm2_params && - (srf_updates[i].cm2_params->component_settings.shaper_3dlut_setting != srf_updates[i].surface->mcm_shaper_3dlut_setting || - srf_updates[i].cm2_params->component_settings.lut1d_enable != srf_updates[i].surface->mcm_lut1d_enable)))) + (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))))) return true; } @@ -5479,6 +5551,7 @@ void dc_commit_updates_for_stream(struct dc *dc, struct dc_stream_update *stream_update, struct dc_state *state) { + (void)state; bool ret = false; dc_exit_ips_for_hw_access(dc); @@ -5540,6 +5613,9 @@ void dc_power_down_on_boot(struct dc *dc) { if (dc->ctx->dce_environment != DCE_ENV_VIRTUAL_HW && dc->hwss.power_down_on_boot) { + if (dc->current_state->stream_count > 0) + return; + if (dc->caps.ips_support) dc_exit_ips_for_hw_access(dc); dc->hwss.power_down_on_boot(dc); @@ -5551,12 +5627,12 @@ void dc_set_power_state(struct dc *dc, enum dc_acpi_cm_power_state power_state) if (!dc->current_state) return; + dc_exit_ips_for_hw_access(dc); + switch (power_state) { case DC_ACPI_CM_POWER_STATE_D0: dc_state_construct(dc, dc->current_state); - dc_exit_ips_for_hw_access(dc); - dc_z10_restore(dc); dc_dmub_srv_notify_fw_dc_power_state(dc->ctx->dmub_srv, power_state); @@ -5785,6 +5861,7 @@ void dc_lock_memory_clock_frequency(struct dc *dc) static void blank_and_force_memclk(struct dc *dc, bool apply, unsigned int memclk_mhz) { + (void)apply; struct dc_state *context = dc->current_state; struct hubp *hubp; struct pipe_ctx *pipe; @@ -5932,6 +6009,7 @@ bool dc_is_dmub_outbox_supported(struct dc *dc) case AMDGPU_FAMILY_GC_11_0_1: case AMDGPU_FAMILY_GC_11_5_0: + case AMDGPU_FAMILY_GC_11_5_4: if (!dc->debug.dpia_debug.bits.disable_dpia) return true; break; @@ -6328,8 +6406,7 @@ void dc_disable_accelerated_mode(struct dc *dc) */ void dc_notify_vsync_int_state(struct dc *dc, struct dc_stream_state *stream, bool enable) { - int i; - int edp_num; + unsigned int i, edp_num; struct pipe_ctx *pipe = NULL; struct dc_link *link = stream->sink->link; struct dc_link *edp_links[MAX_NUM_EDP]; @@ -6383,8 +6460,7 @@ bool dc_abm_save_restore( struct dc_stream_state *stream, struct abm_save_restore *pData) { - int i; - int edp_num; + unsigned int i, edp_num; struct pipe_ctx *pipe = NULL; struct dc_link *link = stream->sink->link; struct dc_link *edp_links[MAX_NUM_EDP]; @@ -6460,6 +6536,7 @@ void dc_query_current_properties(struct dc *dc, struct dc_current_properties *pr void dc_set_edp_power(const struct dc *dc, struct dc_link *edp_link, bool powerOn) { + (void)dc; if (edp_link->connector_signal != SIGNAL_TYPE_EDP) return; @@ -6586,6 +6663,7 @@ void dc_get_underflow_debug_data_for_otg(struct dc *dc, int primary_otg_inst, void dc_get_power_feature_status(struct dc *dc, int primary_otg_inst, struct power_features *out_data) { + (void)primary_otg_inst; out_data->uclk_p_state = dc->current_state->clk_mgr->clks.p_state_change_support; out_data->fams = dc->current_state->bw_ctx.bw.dcn.clk.fw_based_mclk_switching; } @@ -6884,7 +6962,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->blend_tf.type != TF_TYPE_BYPASS) ? 1 : 0; + state->mpc.mpcc_mode[i] = (plane_state->cm.blend_func.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 */ @@ -7282,6 +7360,23 @@ static bool update_planes_and_stream_prepare_v3( ASSERT(scratch->flow == UPDATE_V3_FLOW_INVALID); dc_exit_ips_for_hw_access(scratch->dc); + /* HWSS path determination needs to be done prior to updating the surface and stream states. */ + struct dc_fast_update fast_update[MAX_SURFACES] = { 0 }; + + populate_fast_updates(fast_update, + scratch->surface_updates, + scratch->surface_count, + scratch->stream_update); + + const bool is_hwss_fast_path_only = + fast_update_only(scratch->dc, + fast_update, + scratch->surface_updates, + scratch->surface_count, + scratch->stream_update, + scratch->stream) && + !scratch->dc->check_config.enable_legacy_fast_update; + if (!update_planes_and_stream_state( scratch->dc, scratch->surface_updates, @@ -7297,26 +7392,7 @@ static bool update_planes_and_stream_prepare_v3( if (scratch->new_context == scratch->dc->current_state) { ASSERT(scratch->update_type < UPDATE_TYPE_FULL); - // TODO: Do we need this to be alive in execute? - struct dc_fast_update fast_update[MAX_SURFACES] = { 0 }; - - populate_fast_updates( - fast_update, - scratch->surface_updates, - scratch->surface_count, - scratch->stream_update - ); - const bool fast = fast_update_only( - scratch->dc, - fast_update, - scratch->surface_updates, - scratch->surface_count, - scratch->stream_update, - scratch->stream - ) - // TODO: Can this be used to skip `populate_fast_updates`? - && !scratch->dc->check_config.enable_legacy_fast_update; - scratch->flow = fast + scratch->flow = is_hwss_fast_path_only ? UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FAST : UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FULL; return true; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c index 052d573408c3..db86e346307c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c @@ -1,5 +1,5 @@ /* - * Copyright 2015 Advanced Micro Devices, Inc. + * Copyright 2015-2026 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -249,6 +249,7 @@ void color_space_to_black_color( enum dc_color_space colorspace, struct tg_color *black_color) { + (void)dc; switch (colorspace) { case COLOR_SPACE_YCBCR601: case COLOR_SPACE_YCBCR709: @@ -846,6 +847,16 @@ void hwss_build_fast_sequence(struct dc *dc, block_sequence[*num_steps].func = DPP_PROGRAM_BIAS_AND_SCALE; (*num_steps)++; } + if (current_mpc_pipe->plane_state->update_flags.bits.cm_hist_change) { + block_sequence[*num_steps].params.control_cm_hist_params.dpp + = current_mpc_pipe->plane_res.dpp; + block_sequence[*num_steps].params.control_cm_hist_params.cm_hist_control + = current_mpc_pipe->plane_state->cm_hist_control; + block_sequence[*num_steps].params.control_cm_hist_params.color_space + = current_mpc_pipe->plane_state->color_space; + block_sequence[*num_steps].func = DPP_PROGRAM_CM_HIST; + (*num_steps)++; + } } if (hws->funcs.set_output_transfer_func && current_mpc_pipe->stream->update_flags.bits.out_tf) { block_sequence[*num_steps].params.set_output_transfer_func_params.dc = dc; @@ -1029,6 +1040,9 @@ void hwss_execute_sequence(struct dc *dc, case HUBP_PROGRAM_MCACHE_ID: hwss_program_mcache_id_and_split_coordinate(params); break; + case DPP_PROGRAM_CM_HIST: + hwss_program_cm_hist(params); + break; case PROGRAM_CURSOR_UPDATE_NOW: dc->hwss.program_cursor_offload_now( params->program_cursor_update_now_params.dc, @@ -2054,6 +2068,16 @@ void hwss_program_mcache_id_and_split_coordinate(union block_sequence_params *pa } +void hwss_program_cm_hist(union block_sequence_params *params) +{ + struct dpp *dpp = params->control_cm_hist_params.dpp; + + if (dpp && dpp->funcs->dpp_cm_hist_control) + dpp->funcs->dpp_cm_hist_control(dpp, + params->control_cm_hist_params.cm_hist_control, + params->control_cm_hist_params.color_space); +} + void get_surface_tile_visual_confirm_color( struct pipe_ctx *pipe_ctx, struct tg_color *color) @@ -3370,6 +3394,20 @@ void hwss_add_opp_program_bit_depth_reduction(struct block_sequence_state *seq_s } } +void hwss_add_dpp_program_cm_hist(struct block_sequence_state *seq_state, + struct dpp *dpp, + struct cm_hist_control cm_hist_control, + enum dc_color_space color_space) +{ + if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) { + seq_state->steps[*seq_state->num_steps].func = DPP_PROGRAM_CM_HIST; + seq_state->steps[*seq_state->num_steps].params.control_cm_hist_params.dpp = dpp; + seq_state->steps[*seq_state->num_steps].params.control_cm_hist_params.cm_hist_control = cm_hist_control; + seq_state->steps[*seq_state->num_steps].params.control_cm_hist_params.color_space = color_space; + (*seq_state->num_steps)++; + } +} + void hwss_add_dc_ip_request_cntl(struct block_sequence_state *seq_state, struct dc *dc, bool enable) @@ -4071,3 +4109,24 @@ void hwss_add_tg_get_frame_count(struct block_sequence_state *seq_state, (*seq_state->num_steps)++; } } + + +void get_refresh_rate_confirm_color(struct pipe_ctx *pipe_ctx, struct tg_color *color) +{ + uint32_t color_value = MAX_TG_COLOR_VALUE; + unsigned int refresh_rate = 0; + uint32_t scaling_factor = 0; + if (pipe_ctx && pipe_ctx->stream && color) { + refresh_rate = (pipe_ctx->stream->timing.pix_clk_100hz * 100) / (pipe_ctx->stream->adjust.v_total_max * pipe_ctx->stream->timing.h_total); + + uint32_t min_refresh_rate = pipe_ctx->stream->timing.min_refresh_in_uhz / 1000000; + uint32_t max_refresh_rate = pipe_ctx->stream->timing.max_refresh_in_uhz / 1000000; + + if (max_refresh_rate - min_refresh_rate) + scaling_factor = MAX_TG_COLOR_VALUE * (refresh_rate - min_refresh_rate) / (max_refresh_rate - min_refresh_rate); + + pipe_ctx->visual_confirm_color.color_r_cr = color_value; + pipe_ctx->visual_confirm_color.color_g_y = scaling_factor; + pipe_ctx->visual_confirm_color.color_b_cb = color_value; + } +} diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c index 7bb4504889be..f4e99ca7918f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c @@ -46,7 +46,7 @@ struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index) void dc_get_edp_links(const struct dc *dc, struct dc_link **edp_links, - int *edp_num) + unsigned int *edp_num) { int i; @@ -68,7 +68,7 @@ bool dc_get_edp_link_panel_inst(const struct dc *dc, unsigned int *inst_out) { struct dc_link *edp_links[MAX_NUM_EDP]; - int edp_num, i; + unsigned int edp_num, i; *inst_out = 0; if (link->connector_signal != SIGNAL_TYPE_EDP) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 03d125f794b0..66597a1f5b78 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -78,6 +78,7 @@ #include "dcn351/dcn351_resource.h" #include "dcn36/dcn36_resource.h" #include "dcn401/dcn401_resource.h" +#include "dcn42/dcn42_resource.h" #if defined(CONFIG_DRM_AMD_DC_FP) #include "dc_spl_translate.h" #endif @@ -252,6 +253,9 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) ASICREV_IS_GC_12_0_0_A0(asic_id.hw_internal_rev)) dc_version = DCN_VERSION_4_01; break; + case AMDGPU_FAMILY_GC_11_5_4: + dc_version = DCN_VERSION_4_2; + break; default: dc_version = DCE_VERSION_UNKNOWN; break; @@ -368,6 +372,9 @@ struct resource_pool *dc_create_resource_pool(struct dc *dc, case DCN_VERSION_4_01: res_pool = dcn401_create_resource_pool(init_data, dc); break; + case DCN_VERSION_4_2: + res_pool = dcn42_create_resource_pool(init_data, dc); + break; #endif /* CONFIG_DRM_AMD_DC_FP */ default: break; @@ -742,10 +749,10 @@ struct clock_source *resource_find_used_clk_src_for_sharing( return NULL; } -static enum pixel_format convert_pixel_format_to_dalsurface( +static enum dc_pixel_format convert_pixel_format_to_dalsurface( enum surface_pixel_format surface_pixel_format) { - enum pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN; + enum dc_pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN; switch (surface_pixel_format) { case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: @@ -1741,6 +1748,7 @@ enum dc_status resource_build_scaling_params_for_context( const struct dc *dc, struct dc_state *context) { + (void)dc; int i; for (i = 0; i < MAX_PIPES; i++) { @@ -1818,6 +1826,7 @@ int resource_find_free_pipe_used_as_sec_opp_head_by_cur_otg_master( struct resource_context *new_res_ctx, const struct pipe_ctx *cur_otg_master) { + (void)cur_res_ctx; const struct pipe_ctx *cur_sec_opp_head = cur_otg_master->next_odm_pipe; struct pipe_ctx *new_pipe; int free_pipe_idx = FREE_PIPE_INDEX_NOT_FOUND; @@ -1839,6 +1848,7 @@ int resource_find_free_pipe_used_in_cur_mpc_blending_tree( struct resource_context *new_res_ctx, const struct pipe_ctx *cur_opp_head) { + (void)cur_res_ctx; const struct pipe_ctx *cur_sec_dpp = cur_opp_head->bottom_pipe; struct pipe_ctx *new_pipe; int free_pipe_idx = FREE_PIPE_INDEX_NOT_FOUND; @@ -2424,7 +2434,6 @@ static void resource_log_pipe_for_stream(struct dc *dc, struct dc_state *state, int slice_idx, dpp_idx, plane_idx, slice_count, dpp_count; bool is_primary; - DC_LOGGER_INIT(dc->ctx->logger); slice_count = resource_get_opp_heads_for_otg_master(otg_master, &state->res_ctx, opp_heads); @@ -2935,6 +2944,7 @@ enum dc_status resource_add_otg_master_for_stream_output(struct dc_state *new_ct const struct resource_pool *pool, struct dc_stream_state *stream) { + (void)pool; struct dc *dc = stream->ctx->dc; return dc->res_pool->funcs->add_stream_to_ctx(dc, new_ctx, stream); @@ -3017,6 +3027,7 @@ static bool add_plane_to_opp_head_pipes(struct pipe_ctx *otg_master_pipe, struct dc_plane_state *plane_state, struct dc_state *context) { + (void)context; struct pipe_ctx *opp_head_pipe = otg_master_pipe; while (opp_head_pipe) { @@ -3609,6 +3620,7 @@ static struct hpo_dp_stream_encoder *find_first_free_match_hpo_dp_stream_enc_for const struct resource_pool *pool, struct dc_stream_state *stream) { + (void)stream; int i; for (i = 0; i < pool->hpo_dp_stream_enc_count; i++) { @@ -3628,6 +3640,7 @@ static struct audio *find_first_free_audio( enum engine_id id, enum dce_version dc_version) { + (void)dc_version; int i, available_audio_count; if (id == ENGINE_ID_UNKNOWN) @@ -5234,7 +5247,7 @@ unsigned int resource_pixel_format_to_bpp(enum surface_pixel_format format) return 64; default: ASSERT_CRITICAL(false); - return -1; + return UINT_MAX; } } static unsigned int get_max_audio_sample_rate(struct audio_mode *modes) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_state.c b/drivers/gpu/drm/amd/display/dc/core/dc_state.c index a40e5c44143f..40f7aa732258 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_state.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_state.c @@ -205,19 +205,33 @@ struct dc_state *dc_state_create(struct dc *dc, struct dc_state_create_params *p state->power_source = params ? params->power_source : DC_POWER_SOURCE_AC; #ifdef CONFIG_DRM_AMD_DC_FP + bool status; + if (dc->debug.using_dml2) { - if (!dml2_create(dc, &dc->dml2_options, &state->bw_ctx.dml2)) { + DC_FP_START(); + status = dml2_create(dc, &dc->dml2_options, &state->bw_ctx.dml2); + DC_FP_END(); + + if (!status) { dc_state_release(state); return NULL; } - if (dc->caps.dcmode_power_limits_present && !dml2_create(dc, &dc->dml2_dc_power_options, &state->bw_ctx.dml2_dc_power_source)) { - dc_state_release(state); - return NULL; + if (dc->caps.dcmode_power_limits_present) { + bool status; + + DC_FP_START(); + status = dml2_create(dc, &dc->dml2_dc_power_options, &state->bw_ctx.dml2_dc_power_source); + DC_FP_END(); + + if (!status) { + dc_state_release(state); + return NULL; + } } - } -#endif + } +#endif // CONFIG_DRM_AMD_DC_FP kref_init(&state->refcount); return state; @@ -235,14 +249,20 @@ void dc_state_copy(struct dc_state *dst_state, struct dc_state *src_state) #ifdef CONFIG_DRM_AMD_DC_FP dst_state->bw_ctx.dml2 = dst_dml2; - if (src_state->bw_ctx.dml2) + if (src_state->bw_ctx.dml2) { + DC_FP_START(); dml2_copy(dst_state->bw_ctx.dml2, src_state->bw_ctx.dml2); + DC_FP_END(); + } dst_state->bw_ctx.dml2_dc_power_source = dst_dml2_dc_power_source; - if (src_state->bw_ctx.dml2_dc_power_source) - dml2_copy(dst_state->bw_ctx.dml2_dc_power_source, src_state->bw_ctx.dml2_dc_power_source); -#endif + if (src_state->bw_ctx.dml2_dc_power_source) { + DC_FP_START(); + dml2_copy(dst_state->bw_ctx.dml2_dc_power_source, src_state->bw_ctx.dml2_dc_power_source); + DC_FP_END(); + } +#endif // CONFIG_DRM_AMD_DC_FP /* context refcount should not be overridden */ dst_state->refcount = refcount; } @@ -258,22 +278,35 @@ struct dc_state *dc_state_create_copy(struct dc_state *src_state) dc_state_copy_internal(new_state, src_state); #ifdef CONFIG_DRM_AMD_DC_FP + bool status; + new_state->bw_ctx.dml2 = NULL; new_state->bw_ctx.dml2_dc_power_source = NULL; - if (src_state->bw_ctx.dml2 && - !dml2_create_copy(&new_state->bw_ctx.dml2, src_state->bw_ctx.dml2)) { - dc_state_release(new_state); - return NULL; - } + if (src_state->bw_ctx.dml2) { + DC_FP_START(); + status = dml2_create_copy(&new_state->bw_ctx.dml2, src_state->bw_ctx.dml2); + DC_FP_END(); - if (src_state->bw_ctx.dml2_dc_power_source && - !dml2_create_copy(&new_state->bw_ctx.dml2_dc_power_source, src_state->bw_ctx.dml2_dc_power_source)) { - dc_state_release(new_state); - return NULL; + if (!status) { + dc_state_release(new_state); + return NULL; + } } -#endif + + if (src_state->bw_ctx.dml2_dc_power_source) { + DC_FP_START(); + status = dml2_create_copy(&new_state->bw_ctx.dml2_dc_power_source, + src_state->bw_ctx.dml2_dc_power_source); + DC_FP_END(); + + if (!status) { + dc_state_release(new_state); + return NULL; + } + } +#endif // CONFIG_DRM_AMD_DC_FP kref_init(&new_state->refcount); return new_state; @@ -351,11 +384,13 @@ static void dc_state_free(struct kref *kref) dc_state_destruct(state); #ifdef CONFIG_DRM_AMD_DC_FP + DC_FP_START(); dml2_destroy(state->bw_ctx.dml2); state->bw_ctx.dml2 = 0; dml2_destroy(state->bw_ctx.dml2_dc_power_source); state->bw_ctx.dml2_dc_power_source = 0; + DC_FP_END(); #endif kvfree(state); @@ -374,6 +409,7 @@ enum dc_status dc_state_add_stream( struct dc_state *state, struct dc_stream_state *stream) { + (void)dc; enum dc_status res; DC_LOGGER_INIT(dc->ctx->logger); @@ -749,6 +785,7 @@ struct dc_plane_state *dc_state_create_phantom_plane(const struct dc *dc, struct dc_state *state, struct dc_plane_state *main_plane) { + (void)main_plane; struct dc_plane_state *phantom_plane = dc_create_plane_state(dc); DC_LOGGER_INIT(dc->ctx->logger); 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 baf820e6eae8..e16de323f39c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -42,6 +42,13 @@ #define MAX(x, y) ((x > y) ? x : y) #endif +#include "dc_fpu.h" + +#if !defined(DC_RUN_WITH_PREEMPTION_ENABLED) +#define DC_RUN_WITH_PREEMPTION_ENABLED(code) code +#endif // !DC_RUN_WITH_PREEMPTION_ENABLED + + /******************************************************************************* * Private functions ******************************************************************************/ @@ -170,11 +177,15 @@ struct dc_stream_state *dc_create_stream_for_sink( if (sink == NULL) goto fail; - stream = kzalloc_obj(struct dc_stream_state, GFP_ATOMIC); + DC_RUN_WITH_PREEMPTION_ENABLED(stream = kzalloc_obj(struct dc_stream_state, GFP_ATOMIC)); + if (stream == NULL) goto fail; - stream->update_scratch = kzalloc((int32_t) dc_update_scratch_space_size(), GFP_ATOMIC); + DC_RUN_WITH_PREEMPTION_ENABLED(stream->update_scratch = + kzalloc((int32_t) dc_update_scratch_space_size(), + GFP_ATOMIC)); + if (stream->update_scratch == NULL) goto fail; @@ -245,7 +256,6 @@ const struct dc_stream_status *dc_stream_get_status_const( const struct dc_stream_state *stream) { struct dc *dc = stream->ctx->dc; - return dc_state_get_stream_status(dc->current_state, stream); } @@ -523,8 +533,10 @@ bool dc_stream_program_cursor_position( struct pipe_ctx *pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; /* trigger event on first pipe with current stream */ - if (stream == pipe_ctx->stream) { - pipe_ctx->stream_res.tg->funcs->program_manual_trigger(pipe_ctx->stream_res.tg); + if (stream == pipe_ctx->stream && + pipe_ctx->stream_res.tg->funcs->program_manual_trigger) { + pipe_ctx->stream_res.tg->funcs->program_manual_trigger( + pipe_ctx->stream_res.tg); break; } } @@ -984,7 +996,6 @@ void dc_stream_release_3dlut_for_stream( if (rmcm_3dlut) { rmcm_3dlut->isInUse = false; rmcm_3dlut->stream = NULL; - rmcm_3dlut->protection_bits = 0; } } @@ -996,7 +1007,6 @@ 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/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index d4c40b44d909..a59b176d8e55 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -57,6 +57,7 @@ void dc_plane_construct(struct dc_context *ctx, struct dc_plane_state *plane_sta void dc_plane_destruct(struct dc_plane_state *plane_state) { + (void)plane_state; // no more pointers to free within dc_plane_state } @@ -139,6 +140,9 @@ const struct dc_plane_status *dc_plane_get_status( if (pipe_ctx->plane_state && flags.bits.address) pipe_ctx->plane_state->status.is_flip_pending = false; + if (pipe_ctx->plane_state && flags.bits.histogram) + memset(&pipe_ctx->plane_state->status.cm_hist, 0, + sizeof(pipe_ctx->plane_state->status.cm_hist)); break; } @@ -154,6 +158,12 @@ const struct dc_plane_status *dc_plane_get_status( if (flags.bits.address) dc->hwss.update_pending_status(pipe_ctx); + if (flags.bits.histogram) { + struct dpp *dpp = pipe_ctx->plane_res.dpp; + + if (dpp && dpp->funcs->dpp_cm_hist_read) + dpp->funcs->dpp_cm_hist_read(dpp, &pipe_ctx->plane_state->status.cm_hist); + } } return plane_status; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 4c4239cac863..55ec281db3b7 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 Advanced Micro Devices, Inc. + * Copyright 2012-2026 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -63,7 +63,7 @@ struct dcn_dsc_reg_state; struct dcn_optc_reg_state; struct dcn_dccg_reg_state; -#define DC_VER "3.2.369" +#define DC_VER "3.2.376" /** * MAX_SURFACES - representative of the upper bound of surfaces that can be piped to a single CRTC @@ -520,7 +520,7 @@ struct dc_config { union allow_lttpr_non_transparent_mode allow_lttpr_non_transparent_mode; bool multi_mon_pp_mclk_switch; bool disable_dmcu; - bool enable_4to1MPC; + bool allow_4to1MPC; bool enable_windowed_mpo_odm; bool forceHBR2CP2520; // Used for switching between test patterns TPS4 and CP2520 uint32_t allow_edp_hotplug_detection; @@ -581,6 +581,7 @@ enum visual_confirm { VISUAL_CONFIRM_HW_CURSOR = 20, VISUAL_CONFIRM_VABC = 21, VISUAL_CONFIRM_DCC = 22, + VISUAL_CONFIRM_BOOSTED_REFRESH_RATE = 23, VISUAL_CONFIRM_EXPLICIT = 0x80000000, }; @@ -733,6 +734,8 @@ struct dc_clocks { struct { uint8_t base_efficiency; //LP1 uint8_t low_power_efficiency; //LP2 + uint8_t z8_stutter_efficiency; + int z8_stutter_period; } stutter_efficiency; }; @@ -1211,6 +1214,8 @@ struct dc_debug_options { unsigned int num_fast_flips_to_steady_state_override; bool enable_dmu_recovery; unsigned int force_vmin_threshold; + bool enable_otg_frame_sync_pwa; + unsigned int min_deep_sleep_dcfclk_khz; }; @@ -1400,15 +1405,50 @@ 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 @@ -1419,6 +1459,7 @@ struct dc_plane_status { struct dc_plane_address current_address; bool is_flip_pending; bool is_right_eye; + struct cm_hist cm_hist; }; union surface_update_flags { @@ -1455,6 +1496,7 @@ union surface_update_flags { uint32_t mcm_transfer_function_enable_change:1; /* disable or enable MCM transfer func */ uint32_t full_update:1; uint32_t sdr_white_level_nits:1; + uint32_t cm_hist_change:1; } bits; uint32_t raw; @@ -1484,14 +1526,18 @@ 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; @@ -1528,17 +1574,13 @@ 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; int sharpness_level; enum linear_light_scaling linear_light_scaling; unsigned int sdr_white_level_nits; + struct cm_hist_control cm_hist_control; struct spl_sharpness_range sharpness_range; enum sharpness_range_source sharpness_source; }; @@ -1682,6 +1724,10 @@ struct dc_scratch_space { struct panel_cntl *panel_cntl; struct link_encoder *link_enc; struct graphics_object_id link_id; + + /* External encoder eg. NUTMEG or TRAVIS used on CIK APUs. */ + struct graphics_object_id ext_enc_id; + /* Endpoint type distinguishes display endpoints which do not have entries * in the BIOS connector table from those that do. Helps when tracking link * encoder to display endpoint assignments. @@ -1843,6 +1889,9 @@ struct dc_fast_update { struct dc_transfer_func *out_transfer_func; struct dc_csc_transform *output_csc_transform; const struct dc_csc_transform *cursor_csc_color_matrix; +#if defined(CONFIG_DRM_AMD_DC_DCN4_2) + struct cm_hist_control *cm_hist_control; +#endif }; struct dc_surface_update { @@ -1872,9 +1921,11 @@ struct dc_surface_update { * change cm2_params.cm2_luts: Fast update */ const struct dc_cm2_parameters *cm2_params; + const struct dc_plane_cm *cm; const struct dc_csc_transform *cursor_csc_color_matrix; unsigned int sdr_white_level_nits; struct dc_bias_and_scale bias_and_scale; + struct cm_hist_control *cm_hist_control; }; struct dc_underflow_debug_data { @@ -1915,9 +1966,22 @@ 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); +/* + * dc_get_default_tiling_info() - Retrieve an ASIC-appropriate default tiling + * description for (typically) linear surfaces. + * + * This is used by OS/DM paths that need a valid, fully-initialized tiling + * description without hardcoding gfx-version specifics in the caller. + */ +void dc_get_default_tiling_info(const struct dc *dc, struct dc_tiling_info *tiling_info); + /** * struct dc_validation_set - Struct to store surface/stream associations for validation */ @@ -2016,7 +2080,7 @@ bool dc_get_edp_link_panel_inst(const struct dc *dc, /* Return an array of link pointers to edp links. */ void dc_get_edp_links(const struct dc *dc, struct dc_link **edp_links, - int *edp_num); + unsigned int *edp_num); void dc_set_edp_power(const struct dc *dc, struct dc_link *edp_link, bool powerOn); diff --git a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h index 40d7a7d83c40..6f96c5cf39fe 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h @@ -97,11 +97,12 @@ struct dc_vbios_funcs { enum bp_result (*encoder_control)( struct dc_bios *bios, struct bp_encoder_control *cntl); + enum bp_result (*external_encoder_control)( + struct dc_bios *bios, + struct bp_external_encoder_control *cntl); enum bp_result (*dac_load_detection)( struct dc_bios *bios, - enum engine_id engine_id, - enum dal_device_type device_type, - uint32_t enum_id); + enum engine_id engine_id); enum bp_result (*transmitter_control)( struct dc_bios *bios, struct bp_transmitter_control *cntl); diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c index b15360bcdacf..79c8b4cab053 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -958,7 +958,10 @@ void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv) { uint32_t i; - if (!dc_dmub_srv || !dc_dmub_srv->dmub) { + if (!dc_dmub_srv) + return; + + if (!dc_dmub_srv->dmub) { DC_LOG_ERROR("%s: invalid parameters.", __func__); return; } @@ -1082,6 +1085,7 @@ static void dc_build_cursor_attribute_update_payload1( struct dmub_cursor_attributes_cfg *pl_A, const uint8_t p_idx, const struct hubp *hubp, const struct dpp *dpp) { + (void)p_idx; /* Hubp */ pl_A->aHubp.SURFACE_ADDR_HIGH = hubp->att.SURFACE_ADDR_HIGH; pl_A->aHubp.SURFACE_ADDR = hubp->att.SURFACE_ADDR; @@ -1163,7 +1167,10 @@ void dc_dmub_srv_enable_dpia_trace(const struct dc *dc) { struct dc_dmub_srv *dc_dmub_srv = dc->ctx->dmub_srv; - if (!dc_dmub_srv || !dc_dmub_srv->dmub) { + if (!dc_dmub_srv) + return; + + if (!dc_dmub_srv->dmub) { DC_LOG_ERROR("%s: invalid parameters.", __func__); return; } @@ -2349,6 +2356,33 @@ bool dc_dmub_srv_is_cursor_offload_enabled(const struct dc *dc) return dc->ctx->dmub_srv && dc->ctx->dmub_srv->cursor_offload_enabled; } +void dc_dmub_srv_boot_time_crc_init(const struct dc *dc, uint64_t gpu_addr, uint32_t size) +{ + struct dc_dmub_srv *dc_dmub_srv; + struct dc_context *dc_ctx; + union dmub_rb_cmd cmd = {0}; + bool result = false; + + if (!dc || !dc->ctx || !dc->ctx->dmub_srv || size == 0) + return; + + dc_dmub_srv = dc->ctx->dmub_srv; + dc_ctx = dc_dmub_srv->ctx; + + memset(&cmd, 0, sizeof(cmd)); + cmd.boot_time_crc_init.header.type = DMUB_CMD__BOOT_TIME_CRC; + cmd.boot_time_crc_init.header.sub_type = DMUB_CMD__BOOT_TIME_CRC_INIT_MEM; + cmd.boot_time_crc_init.header.payload_bytes = + sizeof(struct dmub_rb_cmd_boot_time_crc_init); + cmd.boot_time_crc_init.data.buffer_addr.quad_part = gpu_addr; + cmd.boot_time_crc_init.data.buffer_size = size; + + result = dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT); + + if (!result) + DC_ERROR("Boot time crc init failed in DMUB"); +} + void dc_dmub_srv_release_hw(const struct dc *dc) { struct dc_dmub_srv *dc_dmub_srv = dc->ctx->dmub_srv; diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h index 72e0a41f39f0..6579cf9cce3c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h @@ -362,6 +362,15 @@ void dc_dmub_srv_program_cursor_now(struct dc *dc, const struct pipe_ctx *pipe); bool dc_dmub_srv_is_cursor_offload_enabled(const struct dc *dc); /** + * dc_dmub_srv_boot_time_crc_init() - Initializes DMUB boot time CRC. + * + * @dc - pointer to DC object + * @gpu_addr - address for the boot time CRC buffer + * @size - size of the boot time CRC buffer + */ +void dc_dmub_srv_boot_time_crc_init(const struct dc *dc, uint64_t gpu_addr, uint32_t size); + +/** * dc_dmub_srv_release_hw() - Notifies DMUB service that HW access is no longer required. * * @dc - pointer to DC object diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h index 5e3646b7550c..7fa336bf1115 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -947,8 +947,8 @@ union dp_tun_cap_support { /* DPCD[0xE000E] DP_IN_ADAPTER_INFO register. */ union dpia_info { struct { - uint8_t dpia_num :5; - uint8_t rsvd :3; + uint8_t dpia_num :6; + uint8_t rsvd :2; } bits; uint8_t raw; }; @@ -1374,7 +1374,7 @@ union dpcd_replay_configuration { unsigned char DESYNC_ERROR_STATUS : 1; unsigned char SINK_DEVICE_REPLAY_STATUS : 3; unsigned char SINK_FRAME_LOCKED : 2; - unsigned char RESERVED : 1; + unsigned char FRAME_SKIPPING_ERROR_STATUS : 1; } bits; unsigned char raw; }; diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c index 5a365bd19933..77299767096f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c @@ -108,6 +108,7 @@ static void set_reg_field_values(struct dc_reg_value_masks *field_value_mask, uint8_t shift1, uint32_t mask1, uint32_t field_value1, va_list ap) { + (void)addr; uint32_t shift, mask, field_value; int i = 1; @@ -751,6 +752,8 @@ char *dce_version_to_string(const int version) return "DCN 3.6"; case DCN_VERSION_4_01: return "DCN 4.0.1"; + case DCN_VERSION_4_2: + return "DCN 4.2"; default: return "Unknown"; } diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index cfa569a7bff1..c2ca08d26e37 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -218,7 +218,7 @@ enum surface_pixel_format { /* Pixel format */ -enum pixel_format { +enum dc_pixel_format { /*graph*/ PIXEL_FORMAT_UNINITIALIZED, PIXEL_FORMAT_INDEX8, @@ -271,6 +271,15 @@ enum tile_split_values_new { DC_SURF_TILE_SPLIT_1KB = 0x4, }; +enum otg_pwa_sync_mode { + DC_OTG_PWA_FRAME_SYNC_MODE_VSYNC = 0x0, + DC_OTG_PWA_FRAME_SYNC_MODE_VSTARTUP = 0x1, +}; +struct otc_pwa_frame_sync { + enum otg_pwa_sync_mode pwa_sync_mode; + uint32_t pwa_frame_sync_line_offset; +}; + /* TODO: These values come from hardware spec. We need to readdress this * if they ever change. */ @@ -436,6 +445,10 @@ enum dc_gfxversion { enum swizzle_mode_addr3_values swizzle; } gfx_addr3;/*gfx with addr3 and above*/ }; + + struct { + bool avoid_full_update_on_tiling_change; + } flags; }; /* Rotation angle */ @@ -1137,6 +1150,7 @@ struct mcif_buf_params { unsigned int warmup_pitch; unsigned int swlock; unsigned int p_vmid; + uint8_t tmz_id; }; @@ -1162,5 +1176,68 @@ struct phy_state { enum symclk_state symclk_state; }; +enum cm_hist_tap_point { + CM_HIST_TAP_POINT_1, + CM_HIST_TAP_POINT_2, + CM_HIST_TAP_POINT_3, + CM_HIST_TAP_POINT_4, +}; + +enum cm_hist_src { + CM_HIST_SRC1, + CM_HIST_SRC2, + CM_HIST_SRC3, +}; + +enum cm_hist_format { + CM_HIST_FORMAT_FIXED_POINT, + CM_HIST_FORMAT_FP16_POS, + CM_HIST_FORMAT_FP16_POS_AND_NEG, +}; + +enum cm_hist_read_channel_mask { + CM_HIST_READ_DISABLED, + CM_HIST_READ_CH1, + CM_HIST_READ_CH2, + CM_HIST_READ_CH1_CH2, + CM_HIST_READ_CH3, + CM_HIST_READ_CH1_CH3, + CM_HIST_READ_CH2_CH3, + CM_HIST_READ_ALL, +}; + +enum cm_hist_src1_mode { + CM_HIST_SRC1_MODE_R_OR_CR, + CM_HIST_SRC1_MODE_MAX_RGB, +}; + +enum cm_hist_src2_mode { + CM_HIST_SRC2_MODE_G_OR_Y, + CM_HIST_SRC2_MODE_RGB_TO_Y, +}; + +enum cm_hist_src3_mode { + CM_HIST_SRC3_MODE_B_OR_CB, + CM_HIST_SRC3_MODE_MIN_RGB, +}; + +struct cm_hist_control { + enum cm_hist_tap_point tap_point; + uint32_t channels_enabled; + enum cm_hist_src1_mode src_1_select; + enum cm_hist_src2_mode src_2_select; + enum cm_hist_src3_mode src_3_select; + enum cm_hist_src ch1_src; + enum cm_hist_src ch2_src; + enum cm_hist_src ch3_src; + enum cm_hist_format format; + enum cm_hist_read_channel_mask read_channel_mask; +}; + +struct cm_hist { + uint32_t ch1[256]; + uint32_t ch2[256]; + uint32_t ch3[256]; +}; #endif /* DC_HW_TYPES_H */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_plane.h b/drivers/gpu/drm/amd/display/dc/dc_plane.h index 14feb843e694..2ad6d9318566 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_plane.h +++ b/drivers/gpu/drm/amd/display/dc/dc_plane.h @@ -31,6 +31,7 @@ union dc_plane_status_update_flags { struct { uint32_t address : 1; + uint32_t histogram : 1; } bits; uint32_t raw; }; diff --git a/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c b/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c index 37d1a79e8241..52ed8deebf63 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c +++ b/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c @@ -63,7 +63,8 @@ static void populate_inits_from_splinits(struct scl_inits *inits, inits->h_c = dc_fixpt_from_int_dy(spl_inits->h_filter_init_int_c, spl_inits->h_filter_init_frac_c >> 5, 0, 19); inits->v_c = dc_fixpt_from_int_dy(spl_inits->v_filter_init_int_c, spl_inits->v_filter_init_frac_c >> 5, 0, 19); } -static void populate_splformat_from_format(enum spl_pixel_format *spl_pixel_format, const enum pixel_format pixel_format) +static void populate_splformat_from_format(enum spl_pixel_format *spl_pixel_format, + const enum dc_pixel_format pixel_format) { if (pixel_format < PIXEL_FORMAT_INVALID) *spl_pixel_format = (enum spl_pixel_format)pixel_format; @@ -89,6 +90,7 @@ void translate_SPL_in_params_from_pipe_ctx(struct pipe_ctx *pipe_ctx, struct spl spl_in->callbacks = dcn32_spl_callbacks; break; case DCN_VERSION_4_01: + case DCN_VERSION_4_2: spl_in->callbacks = dcn401_spl_callbacks; break; default: diff --git a/drivers/gpu/drm/amd/display/dc/dc_trace.h b/drivers/gpu/drm/amd/display/dc/dc_trace.h index bbec308a3a5e..b7a011646d53 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_trace.h +++ b/drivers/gpu/drm/amd/display/dc/dc_trace.h @@ -23,8 +23,8 @@ #include "amdgpu_dm_trace.h" -#define TRACE_DC_PIPE_STATE(pipe_ctx, index, max_pipes) \ - for (index = 0; index < max_pipes; ++index) { \ +#define TRACE_DC_PIPE_STATE(pipe_ctx, max_pipes) \ + for (int index = 0; index < max_pipes; ++index) { \ struct pipe_ctx *pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[index]; \ if (pipe_ctx->plane_state) \ trace_amdgpu_dm_dc_pipe_state(pipe_ctx->pipe_idx, pipe_ctx->plane_state, \ diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index bddb16bb76d4..fd8ec1660312 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -1,5 +1,5 @@ /* - * Copyright 2012-15 Advanced Micro Devices, Inc. + * Copyright 2012-2026 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -1144,10 +1144,12 @@ union replay_low_refresh_rate_enable_options { union replay_optimization { struct { - //BIT[0-3]: Replay Teams Optimization + //BIT[0-1]: Replay Teams Optimization unsigned int TEAMS_OPTIMIZATION_VER_1 :1; unsigned int TEAMS_OPTIMIZATION_VER_2 :1; - unsigned int RESERVED_2_3 :2; + //BIT[2]: Replay Live Capture with CVT + unsigned int LIVE_CAPTURE_WITH_CVT :1; + unsigned int RESERVED_3 :1; } bits; unsigned int raw; @@ -1194,6 +1196,10 @@ struct replay_config { union replay_optimization replay_optimization; /* Replay sub feature Frame Skipping is supported */ bool frame_skip_supported; + /* Replay Received Frame Skipping Error HPD. */ + bool received_frame_skipping_error_hpd; + /* Live capture with CVT is activated */ + bool live_capture_with_cvt_activated; }; /* Replay feature flags*/ @@ -1346,6 +1352,7 @@ enum dc_cm2_gpu_mem_layout { enum dc_cm2_gpu_mem_pixel_component_order { DC_CM2_GPU_MEM_PIXEL_COMPONENT_ORDER_RGBA, + DC_CM2_GPU_MEM_PIXEL_COMPONENT_ORDER_BGRA }; enum dc_cm2_gpu_mem_format { @@ -1367,6 +1374,9 @@ struct dc_cm2_gpu_mem_format_parameters { enum dc_cm2_gpu_mem_size { DC_CM2_GPU_MEM_SIZE_171717, + DC_CM2_GPU_MEM_SIZE_333333, + DC_CM2_GPU_MEM_SIZE_454545, + DC_CM2_GPU_MEM_SIZE_656565, DC_CM2_GPU_MEM_SIZE_TRANSFORMED, }; @@ -1477,4 +1487,28 @@ 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/dccg/Makefile b/drivers/gpu/drm/amd/display/dc/dccg/Makefile index 1d5cf0f8e79d..bf7e71166b5e 100644 --- a/drivers/gpu/drm/amd/display/dc/dccg/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dccg/Makefile @@ -1,5 +1,5 @@ -# Copyright 2022 Advanced Micro Devices, Inc. +# Copyright 2022-2026 Advanced Micro Devices, Inc. # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), @@ -100,4 +100,13 @@ DCCG_DCN401 = dcn401_dccg.o AMD_DAL_DCCG_DCN401 = $(addprefix $(AMDDALPATH)/dc/dccg/dcn401/,$(DCCG_DCN401)) AMD_DISPLAY_FILES += $(AMD_DAL_DCCG_DCN401) + +############################################################################### +# DCN42 +############################################################################### +DCCG_DCN42 = dcn42_dccg.o + +AMD_DAL_DCCG_DCN42 = $(addprefix $(AMDDALPATH)/dc/dccg/dcn42/,$(DCCG_DCN42)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DCCG_DCN42) endif diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn20/dcn20_dccg.h b/drivers/gpu/drm/amd/display/dc/dccg/dcn20/dcn20_dccg.h index 4c4e61bc91b5..088cf305a772 100644 --- a/drivers/gpu/drm/amd/display/dc/dccg/dcn20/dcn20_dccg.h +++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn20/dcn20_dccg.h @@ -1,5 +1,5 @@ /* - * Copyright 2018 Advanced Micro Devices, Inc. + * Copyright 2018-2026 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -366,6 +366,17 @@ type SYMCLK32_LE3_EN;\ type DP_DTO_ENABLE[MAX_PIPES]; +#define DCCG42_REG_FIELD_LIST(type) \ + type OTG0_ADD_PIXEL;\ + type OTG1_ADD_PIXEL;\ + type OTG2_ADD_PIXEL;\ + type OTG0_DROP_PIXEL;\ + type OTG1_DROP_PIXEL;\ + type OTG2_DROP_PIXEL;\ + type OTG3_ADD_PIXEL;\ + type OTG3_DROP_PIXEL;\ + type RESYNC_FIFO_LEVEL_ADJUST_EN; + struct dccg_shift { DCCG_REG_FIELD_LIST(uint8_t) DCCG3_REG_FIELD_LIST(uint8_t) @@ -374,6 +385,7 @@ struct dccg_shift { DCCG32_REG_FIELD_LIST(uint8_t) DCCG35_REG_FIELD_LIST(uint8_t) DCCG401_REG_FIELD_LIST(uint8_t) + DCCG42_REG_FIELD_LIST(uint8_t) }; struct dccg_mask { @@ -384,6 +396,7 @@ struct dccg_mask { DCCG32_REG_FIELD_LIST(uint32_t) DCCG35_REG_FIELD_LIST(uint32_t) DCCG401_REG_FIELD_LIST(uint32_t) + DCCG42_REG_FIELD_LIST(uint32_t) }; #define DCCG_REG_VARIABLE_LIST \ @@ -497,6 +510,7 @@ struct dccg_mask { struct dccg_registers { DCCG_REG_VARIABLE_LIST; + uint32_t OTG_ADD_DROP_PIXEL_CNTL; }; struct dcn_dccg { diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn31/dcn31_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn31/dcn31_dccg.c index 7f58acfe1177..a72bf413fad6 100644 --- a/drivers/gpu/drm/amd/display/dc/dccg/dcn31/dcn31_dccg.c +++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn31/dcn31_dccg.c @@ -165,6 +165,7 @@ void dccg31_set_dpstreamclk( int otg_inst, int dp_hpo_inst) { + (void)dp_hpo_inst; if (src == REFCLK) dccg31_disable_dpstreamclk(dccg, otg_inst); else @@ -644,6 +645,7 @@ void dccg31_get_dccg_ref_freq(struct dccg *dccg, unsigned int xtalin_freq_inKhz, unsigned int *dccg_ref_freq_inKhz) { + (void)dccg; /* * Assume refclk is sourced from xtalin * expect 24MHz diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn32/dcn32_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn32/dcn32_dccg.c index e817cd7c2b6a..18b9c5ceed43 100644 --- a/drivers/gpu/drm/amd/display/dc/dccg/dcn32/dcn32_dccg.c +++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn32/dcn32_dccg.c @@ -265,6 +265,7 @@ static void dccg32_get_dccg_ref_freq(struct dccg *dccg, unsigned int xtalin_freq_inKhz, unsigned int *dccg_ref_freq_inKhz) { + (void)dccg; /* * Assume refclk is sourced from xtalin * expect 100MHz diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c index 0b7908fbb115..efac64165ccd 100644 --- a/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c +++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c @@ -558,6 +558,7 @@ static void dccg35_set_symclk32_se_src_new( static int dccg35_is_symclk32_se_src_functional_le_new(struct dccg *dccg, int symclk_32_se_inst, int symclk_32_le_inst) { + (void)symclk_32_se_inst; uint32_t en; uint32_t src_sel; @@ -2373,6 +2374,7 @@ static void dccg35_disable_symclk_se_cb( uint32_t stream_enc_inst, uint32_t link_enc_inst) { + (void)link_enc_inst; dccg35_disable_symclk_fe_new(dccg, stream_enc_inst); /* DMU PHY sequence switches SYMCLK_BE (link_enc_inst) to ref clock once PHY is turned off */ diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c index a37f94dec6f2..97605a416031 100644 --- a/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c +++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c @@ -161,6 +161,7 @@ void dccg401_set_pixel_rate_div( enum pixel_rate_div tmds_div, enum pixel_rate_div unused) { + (void)unused; struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); uint32_t cur_tmds_div = PIXEL_RATE_DIV_NA; uint32_t dp_dto_int; @@ -353,6 +354,7 @@ void dccg401_get_dccg_ref_freq(struct dccg *dccg, unsigned int xtalin_freq_inKhz, unsigned int *dccg_ref_freq_inKhz) { + (void)dccg; /* * Assume refclk is sourced from xtalin * expect 100MHz @@ -526,10 +528,6 @@ static void dccg401_enable_dpstreamclk(struct dccg *dccg, int otg_inst, int dp_h BREAK_TO_DEBUGGER(); return; } - if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) - REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3, - DPSTREAMCLK_GATE_DISABLE, 1, - DPSTREAMCLK_ROOT_GATE_DISABLE, 1); } void dccg401_disable_dpstreamclk(struct dccg *dccg, int dp_hpo_inst) @@ -725,6 +723,7 @@ void dccg401_init(struct dccg *dccg) void dccg401_set_dto_dscclk(struct dccg *dccg, uint32_t inst, uint32_t num_slices_h) { + (void)num_slices_h; struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); switch (inst) { @@ -827,11 +826,22 @@ void dccg401_enable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint3 if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_FE_ROOT_GATE_DISABLE, 1); break; + case 4: + if (dccg_dcn->dccg_mask->SYMCLKE_FE_ROOT_GATE_DISABLE) { + REG_UPDATE_2(SYMCLKE_CLOCK_ENABLE, + SYMCLKE_FE_EN, 1, + SYMCLKE_FE_SRC_SEL, link_enc_inst); + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_FE_ROOT_GATE_DISABLE, 1); + } + break; + default: + return; } } void dccg401_disable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst) { + (void)link_enc_inst; struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); switch (stream_enc_inst) { @@ -855,6 +865,16 @@ void dccg401_disable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint SYMCLKD_FE_EN, 0, SYMCLKD_FE_SRC_SEL, 0); break; + case 4: + if (dccg_dcn->dccg_mask->SYMCLKE_FE_ROOT_GATE_DISABLE) { + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_FE_ROOT_GATE_DISABLE, 0); + REG_UPDATE_2(SYMCLKE_CLOCK_ENABLE, + SYMCLKE_FE_EN, 0, + SYMCLKE_FE_SRC_SEL, 0); + } + break; + default: + return; } } diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.c new file mode 100644 index 000000000000..b813310763e5 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.c @@ -0,0 +1,334 @@ +// SPDX-License-Identifier: MIT +// +// Copyright 2026 Advanced Micro Devices, Inc. + +#include "reg_helper.h" +#include "core_types.h" +#include "dcn35/dcn35_dccg.h" +#include "dcn42_dccg.h" + +#define TO_DCN_DCCG(dccg)\ + container_of(dccg, struct dcn_dccg, base) + +#define REG(reg) \ + (dccg_dcn->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + dccg_dcn->dccg_shift->field_name, dccg_dcn->dccg_mask->field_name + +#define CTX \ + dccg_dcn->base.ctx +#define DC_LOGGER \ + dccg->ctx->logger + +void dccg42_otg_add_pixel(struct dccg *dccg, + uint32_t otg_inst) +{ + struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); + + switch (otg_inst) { + case 0: + REG_UPDATE(OTG_ADD_DROP_PIXEL_CNTL, + OTG0_ADD_PIXEL, 1); + break; + case 1: + REG_UPDATE(OTG_ADD_DROP_PIXEL_CNTL, + OTG1_ADD_PIXEL, 1); + break; + case 2: + REG_UPDATE(OTG_ADD_DROP_PIXEL_CNTL, + OTG2_ADD_PIXEL, 1); + break; + case 3: + REG_UPDATE(OTG_ADD_DROP_PIXEL_CNTL, + OTG3_ADD_PIXEL, 1); + break; + default: + ASSERT(0); + } +} + +void dccg42_otg_drop_pixel(struct dccg *dccg, + uint32_t otg_inst) +{ + struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); + + switch (otg_inst) { + case 0: + REG_UPDATE(OTG_ADD_DROP_PIXEL_CNTL, + OTG0_DROP_PIXEL, 1); + break; + case 1: + REG_UPDATE(OTG_ADD_DROP_PIXEL_CNTL, + OTG1_DROP_PIXEL, 1); + break; + case 2: + REG_UPDATE(OTG_ADD_DROP_PIXEL_CNTL, + OTG2_DROP_PIXEL, 1); + break; + case 3: + REG_UPDATE(OTG_ADD_DROP_PIXEL_CNTL, + OTG3_DROP_PIXEL, 1); + break; + default: + ASSERT(0); + } +} + +void dccg42_enable_global_fgcg(struct dccg *dccg, bool value) +{ + struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); + + if (dccg->ctx->dc->debug.disable_clock_gate) + value = false; + REG_UPDATE(DCCG_GLOBAL_FGCG_REP_CNTL, DCCG_GLOBAL_FGCG_REP_DIS, !value); +} + +void dccg42_set_physymclk( + struct dccg *dccg, + int phy_inst, + enum physymclk_clock_source clk_src, + bool force_enable) +{ + struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); + + switch (phy_inst) { + case 0: + if (force_enable) { + REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, + PHYASYMCLK_ROOT_GATE_DISABLE, 1); + REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL, + PHYASYMCLK_EN, 1, + PHYASYMCLK_SRC_SEL, clk_src); + } else { + REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL, + PHYASYMCLK_EN, 0, + PHYASYMCLK_SRC_SEL, 0); + REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, + PHYASYMCLK_ROOT_GATE_DISABLE, + dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk ? 0 : 1); + } + break; + case 1: + if (force_enable) { + REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, + PHYBSYMCLK_ROOT_GATE_DISABLE, 1); + REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL, + PHYBSYMCLK_EN, 1, + PHYBSYMCLK_SRC_SEL, clk_src); + } else { + REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL, + PHYBSYMCLK_EN, 0, + PHYBSYMCLK_SRC_SEL, 0); + REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, + PHYBSYMCLK_ROOT_GATE_DISABLE, + dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk ? 0 : 1); + } + break; + case 2: + if (force_enable) { + REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, + PHYCSYMCLK_ROOT_GATE_DISABLE, 1); + REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL, + PHYCSYMCLK_EN, 1, + PHYCSYMCLK_SRC_SEL, clk_src); + } else { + REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL, + PHYCSYMCLK_EN, 0, + PHYCSYMCLK_SRC_SEL, 0); + REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, + PHYCSYMCLK_ROOT_GATE_DISABLE, + dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk ? 0 : 1); + } + break; + case 3: + if (force_enable) { + REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, + PHYDSYMCLK_ROOT_GATE_DISABLE, 1); + REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL, + PHYDSYMCLK_EN, 1, + PHYDSYMCLK_SRC_SEL, clk_src); + } else { + REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL, + PHYDSYMCLK_EN, 0, + PHYDSYMCLK_SRC_SEL, 0); + REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, + PHYDSYMCLK_ROOT_GATE_DISABLE, + dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk ? 0 : 1); + } + break; + case 4: + if (force_enable) { + REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, + PHYESYMCLK_ROOT_GATE_DISABLE, 1); + REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL, + PHYESYMCLK_EN, 1, + PHYESYMCLK_SRC_SEL, clk_src); + } else { + REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL, + PHYESYMCLK_EN, 0, + PHYESYMCLK_SRC_SEL, 0); + REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, + PHYESYMCLK_ROOT_GATE_DISABLE, + dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk ? 0 : 1); + } + break; + default: + BREAK_TO_DEBUGGER(); + return; + } +} + +void dccg42_set_pixel_rate_div( + struct dccg *dccg, + uint32_t otg_inst, + enum pixel_rate_div tmds_div, + enum pixel_rate_div unused) +{ + (void)unused; + struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); + uint32_t cur_tmds_div = PIXEL_RATE_DIV_NA; + uint32_t dp_dto_int; + uint32_t reg_val; + + // only 2 and 4 are valid on dcn401 + if (tmds_div != PIXEL_RATE_DIV_BY_2 && tmds_div != PIXEL_RATE_DIV_BY_4) { + return; + } + + dccg401_get_pixel_rate_div(dccg, otg_inst, &cur_tmds_div, &dp_dto_int); + if (tmds_div == cur_tmds_div) + return; + + // encode enum to register value + reg_val = tmds_div == PIXEL_RATE_DIV_BY_4 ? 1 : 0; + + switch (otg_inst) { + case 0: + REG_UPDATE(OTG_PIXEL_RATE_DIV, + OTG0_TMDS_PIXEL_RATE_DIV, reg_val); + break; + case 1: + REG_UPDATE(OTG_PIXEL_RATE_DIV, + OTG1_TMDS_PIXEL_RATE_DIV, reg_val); + break; + case 2: + REG_UPDATE(OTG_PIXEL_RATE_DIV, + OTG2_TMDS_PIXEL_RATE_DIV, reg_val); + break; + case 3: + REG_UPDATE(OTG_PIXEL_RATE_DIV, + OTG3_TMDS_PIXEL_RATE_DIV, reg_val); + break; + default: + BREAK_TO_DEBUGGER(); + return; + } +} + +void dccg42_trigger_dio_fifo_resync(struct dccg *dccg) +{ + struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); + + REG_UPDATE(DISPCLK_FREQ_CHANGE_CNTL, RESYNC_FIFO_LEVEL_ADJUST_EN, 1); + REG_UPDATE(DISPCLK_FREQ_CHANGE_CNTL, RESYNC_FIFO_LEVEL_ADJUST_EN, 0); + REG_WAIT(DISPCLK_FREQ_CHANGE_CNTL, DISPCLK_FREQ_RAMP_DONE, 1, 50, 2000); +} + +static void dccg42_init(struct dccg *dccg) +{ + int otg_inst; + struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); + + /* Set HPO stream encoder to use refclk to avoid case where PHY is + * disabled and SYMCLK32 for HPO SE is sourced from PHYD32CLK which + * will cause DCN to hang. + */ + for (otg_inst = 0; otg_inst < 4; otg_inst++) + dccg35_disable_symclk32_se(dccg, otg_inst); + + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) { + dccg401_disable_symclk32_le(dccg, 0); + dccg401_disable_symclk32_le(dccg, 1); + dccg401_disable_symclk32_le(dccg, 2); + dccg401_disable_symclk32_le(dccg, 3); + } + + if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) { + dccg401_disable_dpstreamclk(dccg, 0); + dccg401_disable_dpstreamclk(dccg, 1); + dccg401_disable_dpstreamclk(dccg, 2); + dccg401_disable_dpstreamclk(dccg, 3); + } + if (!dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) { + REG_UPDATE_5(DCCG_GATE_DISABLE_CNTL2, + PHYASYMCLK_ROOT_GATE_DISABLE, 1, + PHYBSYMCLK_ROOT_GATE_DISABLE, 1, + PHYCSYMCLK_ROOT_GATE_DISABLE, 1, + PHYDSYMCLK_ROOT_GATE_DISABLE, 1, + PHYESYMCLK_ROOT_GATE_DISABLE, 1); + } +} + + +static const struct dccg_funcs dccg42_funcs = { + .update_dpp_dto = dccg35_update_dpp_dto, + .dpp_root_clock_control = dccg35_dpp_root_clock_control, + .get_dccg_ref_freq = dccg401_get_dccg_ref_freq, + .dccg_init = dccg42_init, + .set_dpstreamclk = dccg401_set_dpstreamclk, + /* Redundant with above^ */ + /* .set_dpstreamclk_root_clock_gating = dccg35_set_dpstreamclk_root_clock_gating, */ + .enable_symclk32_se = dccg31_enable_symclk32_se, + .disable_symclk32_se = dccg35_disable_symclk32_se, + .enable_symclk32_le = dccg401_enable_symclk32_le, + .disable_symclk32_le = dccg401_disable_symclk32_le, + .set_symclk32_le_root_clock_gating = dccg31_set_symclk32_le_root_clock_gating, + .set_physymclk = dccg42_set_physymclk, + .set_dtbclk_dto = NULL, + .set_dto_dscclk = dccg401_set_dto_dscclk, + .set_ref_dscclk = dccg401_set_ref_dscclk, + .set_valid_pixel_rate = NULL, + .set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en, + .set_audio_dtbclk_dto = NULL, + .otg_add_pixel = dccg42_otg_add_pixel, + .otg_drop_pixel = dccg42_otg_drop_pixel, + .disable_dsc = dccg35_disable_dscclk, + .enable_dsc = dccg35_enable_dscclk, + .set_pixel_rate_div = dccg42_set_pixel_rate_div, + .get_pixel_rate_div = dccg401_get_pixel_rate_div, + .trigger_dio_fifo_resync = dccg42_trigger_dio_fifo_resync, + .set_dp_dto = dccg401_set_dp_dto, + .enable_symclk_se = dccg35_enable_symclk_se, + .disable_symclk_se = dccg35_disable_symclk_se, + .set_dtbclk_p_src = dccg401_set_dtbclk_p_src, + .dccg_root_gate_disable_control = dccg35_root_gate_disable_control, + .dccg_read_reg_state = dccg31_read_reg_state, + .dccg_enable_global_fgcg = dccg42_enable_global_fgcg, +}; + +struct dccg *dccg42_create( + struct dc_context *ctx, + const struct dccg_registers *regs, + const struct dccg_shift *dccg_shift, + const struct dccg_mask *dccg_mask) +{ + struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL); + struct dccg *base; + + if (dccg_dcn == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + base = &dccg_dcn->base; + base->ctx = ctx; + base->funcs = &dccg42_funcs; + + dccg_dcn->regs = regs; + dccg_dcn->dccg_shift = dccg_shift; + dccg_dcn->dccg_mask = dccg_mask; + + return &dccg_dcn->base; +} diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.h b/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.h new file mode 100644 index 000000000000..2076565b1caa --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.h @@ -0,0 +1,273 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2024-2026 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DCN42_DCCG_H__ +#define __DCN42_DCCG_H__ + +#include "dcn401/dcn401_dccg.h" + +#define DCCG_MASK_SH_LIST_DCN42_COMMON(mask_sh) \ + DCCG_SFI(DPPCLK_DTO_CTRL, DTO_DB_EN, DPPCLK, 0, mask_sh),\ + DCCG_SFI(DPPCLK_DTO_CTRL, DTO_DB_EN, DPPCLK, 1, mask_sh),\ + DCCG_SFI(DPPCLK_DTO_CTRL, DTO_DB_EN, DPPCLK, 2, mask_sh),\ + DCCG_SFI(DPPCLK_DTO_CTRL, DTO_DB_EN, DPPCLK, 3, mask_sh),\ + DCCG_SF(DPPCLK_CTRL, DPPCLK0_EN, mask_sh),\ + DCCG_SF(DPPCLK_CTRL, DPPCLK1_EN, mask_sh),\ + DCCG_SF(DPPCLK_CTRL, DPPCLK2_EN, mask_sh),\ + DCCG_SF(DPPCLK_CTRL, DPPCLK3_EN, mask_sh),\ + DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DISPCLK_STEP_DELAY, mask_sh),\ + DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DISPCLK_STEP_SIZE, mask_sh),\ + DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DISPCLK_FREQ_RAMP_DONE, mask_sh),\ + DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DISPCLK_MAX_ERRDET_CYCLES, mask_sh),\ + DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DCCG_FIFO_ERRDET_RESET, mask_sh),\ + DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DCCG_FIFO_ERRDET_STATE, mask_sh),\ + DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DCCG_FIFO_ERRDET_OVR_EN, mask_sh),\ + DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DISPCLK_CHG_FWD_CORR_DISABLE, mask_sh),\ + DCCG_SF(DPPCLK0_DTO_PARAM, DPPCLK0_DTO_PHASE, mask_sh),\ + DCCG_SF(DPPCLK0_DTO_PARAM, DPPCLK0_DTO_MODULO, mask_sh),\ + DCCG_SF(HDMICHARCLK0_CLOCK_CNTL, HDMICHARCLK0_EN, mask_sh),\ + DCCG_SF(HDMICHARCLK0_CLOCK_CNTL, HDMICHARCLK0_SRC_SEL, mask_sh),\ + DCCG_SF(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_EN, mask_sh),\ + DCCG_SF(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_SRC_SEL, mask_sh),\ + DCCG_SF(PHYBSYMCLK_CLOCK_CNTL, PHYBSYMCLK_EN, mask_sh),\ + DCCG_SF(PHYBSYMCLK_CLOCK_CNTL, PHYBSYMCLK_SRC_SEL, mask_sh),\ + DCCG_SF(PHYCSYMCLK_CLOCK_CNTL, PHYCSYMCLK_EN, mask_sh),\ + DCCG_SF(PHYCSYMCLK_CLOCK_CNTL, PHYCSYMCLK_SRC_SEL, mask_sh),\ + DCCG_SF(PHYDSYMCLK_CLOCK_CNTL, PHYDSYMCLK_EN, mask_sh),\ + DCCG_SF(PHYDSYMCLK_CLOCK_CNTL, PHYDSYMCLK_SRC_SEL, mask_sh),\ + DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK0_EN, mask_sh),\ + DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK1_EN, mask_sh),\ + DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK2_EN, mask_sh),\ + DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK3_EN, mask_sh),\ + DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK0_SRC_SEL, mask_sh),\ + DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK1_SRC_SEL, mask_sh),\ + DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK2_SRC_SEL, mask_sh),\ + DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK3_SRC_SEL, mask_sh),\ + DCCG_SF(HDMISTREAMCLK_CNTL, HDMISTREAMCLK0_EN, mask_sh),\ + DCCG_SF(HDMISTREAMCLK_CNTL, HDMISTREAMCLK0_SRC_SEL, mask_sh),\ + DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE0_SRC_SEL, mask_sh),\ + DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE1_SRC_SEL, mask_sh),\ + DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE2_SRC_SEL, mask_sh),\ + DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE3_SRC_SEL, mask_sh),\ + DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE0_EN, mask_sh),\ + DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE1_EN, mask_sh),\ + DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE2_EN, mask_sh),\ + DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE3_EN, mask_sh),\ + DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE0_SRC_SEL, mask_sh),\ + DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE1_SRC_SEL, mask_sh),\ + DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE2_SRC_SEL, mask_sh),\ + DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE3_SRC_SEL, mask_sh),\ + DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE0_EN, mask_sh),\ + DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE1_EN, mask_sh),\ + DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE2_EN, mask_sh),\ + DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE3_EN, mask_sh),\ + DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 0, mask_sh),\ + DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 1, mask_sh),\ + DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 2, mask_sh),\ + DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 3, mask_sh),\ + DCCG_SF(OTG_ADD_DROP_PIXEL_CNTL, OTG0_ADD_PIXEL, mask_sh),\ + DCCG_SF(OTG_ADD_DROP_PIXEL_CNTL, OTG1_ADD_PIXEL, mask_sh),\ + DCCG_SF(OTG_ADD_DROP_PIXEL_CNTL, OTG2_ADD_PIXEL, mask_sh),\ + DCCG_SF(OTG_ADD_DROP_PIXEL_CNTL, OTG3_ADD_PIXEL, mask_sh),\ + DCCG_SF(OTG_ADD_DROP_PIXEL_CNTL, OTG0_DROP_PIXEL, mask_sh),\ + DCCG_SF(OTG_ADD_DROP_PIXEL_CNTL, OTG1_DROP_PIXEL, mask_sh),\ + DCCG_SF(OTG_ADD_DROP_PIXEL_CNTL, OTG2_DROP_PIXEL, mask_sh),\ + DCCG_SF(OTG_ADD_DROP_PIXEL_CNTL, OTG3_DROP_PIXEL, mask_sh),\ + DCCG_SF(OTG_PIXEL_RATE_DIV, OTG0_TMDS_PIXEL_RATE_DIV, mask_sh),\ + DCCG_SF(OTG_PIXEL_RATE_DIV, DPDTO0_INT, mask_sh),\ + DCCG_SF(OTG_PIXEL_RATE_DIV, OTG1_TMDS_PIXEL_RATE_DIV, mask_sh),\ + DCCG_SF(OTG_PIXEL_RATE_DIV, DPDTO1_INT, mask_sh),\ + DCCG_SF(OTG_PIXEL_RATE_DIV, OTG2_TMDS_PIXEL_RATE_DIV, mask_sh),\ + DCCG_SF(OTG_PIXEL_RATE_DIV, DPDTO2_INT, mask_sh),\ + DCCG_SF(OTG_PIXEL_RATE_DIV, OTG3_TMDS_PIXEL_RATE_DIV, mask_sh),\ + DCCG_SF(OTG_PIXEL_RATE_DIV, DPDTO3_INT, mask_sh),\ + DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P0_SRC_SEL, mask_sh),\ + DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P0_EN, mask_sh),\ + DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P1_SRC_SEL, mask_sh),\ + DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P1_EN, mask_sh),\ + DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P2_SRC_SEL, mask_sh),\ + DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P2_EN, mask_sh),\ + DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P3_SRC_SEL, mask_sh),\ + DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P3_EN, mask_sh),\ + DCCG_SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO_SEL, mask_sh),\ + DCCG_SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL, mask_sh),\ + DCCG_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, mask_sh),\ + DCCG_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_RDIVIDER, mask_sh),\ + DCCG_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, mask_sh),\ + DCCG_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_MODE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYASYMCLK_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYBSYMCLK_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYCSYMCLK_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYDSYMCLK_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GLOBAL_FGCG_REP_CNTL, DCCG_GLOBAL_FGCG_REP_DIS, mask_sh),\ + DCCG_SFII(OTG, PIXEL_RATE_CNTL, DP_DTO, ENABLE, 0, mask_sh),\ + DCCG_SFII(OTG, PIXEL_RATE_CNTL, DP_DTO, ENABLE, 1, mask_sh),\ + DCCG_SFII(OTG, PIXEL_RATE_CNTL, DP_DTO, ENABLE, 2, mask_sh),\ + DCCG_SFII(OTG, PIXEL_RATE_CNTL, DP_DTO, ENABLE, 3, mask_sh),\ + DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 0, mask_sh),\ + DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 1, mask_sh),\ + DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 2, mask_sh),\ + DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 3, mask_sh),\ + DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK0_EN, mask_sh),\ + DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK1_EN, mask_sh),\ + DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK2_EN, mask_sh),\ + DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK3_EN, mask_sh),\ + DCCG_SF(DSCCLK0_DTO_PARAM, DSCCLK0_DTO_PHASE, mask_sh),\ + DCCG_SF(DSCCLK0_DTO_PARAM, DSCCLK0_DTO_MODULO, mask_sh),\ + DCCG_SF(DSCCLK1_DTO_PARAM, DSCCLK1_DTO_PHASE, mask_sh),\ + DCCG_SF(DSCCLK1_DTO_PARAM, DSCCLK1_DTO_MODULO, mask_sh),\ + DCCG_SF(DSCCLK2_DTO_PARAM, DSCCLK2_DTO_PHASE, mask_sh),\ + DCCG_SF(DSCCLK2_DTO_PARAM, DSCCLK2_DTO_MODULO, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL, DISPCLK_DCCG_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, HDMICHARCLK0_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, HDMISTREAMCLK0_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKA_FE_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKB_FE_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKC_FE_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKD_FE_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKA_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKB_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKC_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKD_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYASYMCLK_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYBSYMCLK_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYCSYMCLK_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYDSYMCLK_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE0_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE1_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE2_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE3_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_LE0_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_LE1_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_LE2_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_LE3_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_SE0_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_SE1_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_SE2_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_SE3_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_LE0_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_LE1_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_LE2_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_LE3_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL4, HDMICHARCLK0_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL4, PHYA_REFCLK_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL4, PHYB_REFCLK_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL4, PHYC_REFCLK_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL4, PHYD_REFCLK_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P0_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P1_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P2_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P3_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_FE_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_FE_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_FE_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_FE_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK0_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK1_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK2_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK3_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK0_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK1_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK2_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK3_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DSCCLK0_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DSCCLK1_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DSCCLK2_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DPPCLK0_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DPPCLK1_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DPPCLK2_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DPPCLK3_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL6, HDMISTREAMCLK0_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(SYMCLKA_CLOCK_ENABLE, SYMCLKA_CLOCK_ENABLE, mask_sh),\ + DCCG_SF(SYMCLKB_CLOCK_ENABLE, SYMCLKB_CLOCK_ENABLE, mask_sh),\ + DCCG_SF(SYMCLKC_CLOCK_ENABLE, SYMCLKC_CLOCK_ENABLE, mask_sh),\ + DCCG_SF(SYMCLKD_CLOCK_ENABLE, SYMCLKD_CLOCK_ENABLE, mask_sh),\ + DCCG_SF(SYMCLKA_CLOCK_ENABLE, SYMCLKA_FE_EN, mask_sh),\ + DCCG_SF(SYMCLKB_CLOCK_ENABLE, SYMCLKB_FE_EN, mask_sh),\ + DCCG_SF(SYMCLKC_CLOCK_ENABLE, SYMCLKC_FE_EN, mask_sh),\ + DCCG_SF(SYMCLKD_CLOCK_ENABLE, SYMCLKD_FE_EN, mask_sh),\ + DCCG_SF(SYMCLKA_CLOCK_ENABLE, SYMCLKA_FE_SRC_SEL, mask_sh),\ + DCCG_SF(SYMCLKB_CLOCK_ENABLE, SYMCLKB_FE_SRC_SEL, mask_sh),\ + DCCG_SF(SYMCLKC_CLOCK_ENABLE, SYMCLKC_FE_SRC_SEL, mask_sh),\ + DCCG_SF(SYMCLKD_CLOCK_ENABLE, SYMCLKD_FE_SRC_SEL, mask_sh) + +#define DCCG_MASK_SH_LIST_DCN42(mask_sh) \ + DCCG_MASK_SH_LIST_DCN42_COMMON(mask_sh),\ + DCCG_SF(PHYESYMCLK_CLOCK_CNTL, PHYESYMCLK_EN, mask_sh),\ + DCCG_SF(PHYESYMCLK_CLOCK_CNTL, PHYESYMCLK_SRC_SEL, mask_sh),\ + DCCG_SF(HDMISTREAMCLK0_DTO_PARAM, HDMISTREAMCLK0_DTO_PHASE, mask_sh),\ + DCCG_SF(HDMISTREAMCLK0_DTO_PARAM, HDMISTREAMCLK0_DTO_MODULO, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYESYMCLK_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DSCCLK3_DTO_PARAM, DSCCLK3_DTO_PHASE, mask_sh),\ + DCCG_SF(DSCCLK3_DTO_PARAM, DSCCLK3_DTO_MODULO, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYESYMCLK_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL4, PHYE_REFCLK_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_FE_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DSCCLK3_ROOT_GATE_DISABLE, mask_sh),\ + DCCG_SF(SYMCLKA_CLOCK_ENABLE, SYMCLKA_SRC_SEL, mask_sh),\ + DCCG_SF(SYMCLKB_CLOCK_ENABLE, SYMCLKB_SRC_SEL, mask_sh),\ + DCCG_SF(SYMCLKC_CLOCK_ENABLE, SYMCLKC_SRC_SEL, mask_sh),\ + DCCG_SF(SYMCLKD_CLOCK_ENABLE, SYMCLKD_SRC_SEL, mask_sh),\ + DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_SRC_SEL, mask_sh),\ + DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_CLOCK_ENABLE, mask_sh),\ + DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_FE_EN, mask_sh),\ + DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_FE_SRC_SEL, mask_sh),\ + DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, RESYNC_FIFO_LEVEL_ADJUST_EN, mask_sh) + + +void dccg42_otg_add_pixel(struct dccg *dccg, + uint32_t otg_inst); + +void dccg42_otg_drop_pixel(struct dccg *dccg, + uint32_t otg_inst); +void dccg42_enable_global_fgcg(struct dccg *dccg, bool value); + +void dccg42_set_physymclk( + struct dccg *dccg, + int phy_inst, + enum physymclk_clock_source clk_src, + bool force_enable); + +void dccg42_set_pixel_rate_div( + struct dccg *dccg, + uint32_t otg_inst, + enum pixel_rate_div tmds_div, + enum pixel_rate_div unused); + +void dccg42_trigger_dio_fifo_resync(struct dccg *dccg); + +struct dccg *dccg42_create( + struct dc_context *ctx, + const struct dccg_registers *regs, + const struct dccg_shift *dccg_shift, + const struct dccg_mask *dccg_mask); + +#endif //__DCN42_DCCG_H__ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c index 41169b42534c..469b4b8f88a3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c @@ -57,6 +57,7 @@ static bool dce_abm_set_pipe(struct abm *abm, uint32_t controller_id, uint32_t panel_inst) { + (void)panel_inst; struct dce_abm *abm_dce = TO_DCE_ABM(abm); uint32_t rampingBoundary = 0xFFFF; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h index 3d819fc5654c..1e9ab5ff3a31 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h @@ -1,5 +1,5 @@ /* - * Copyright 2012-16 Advanced Micro Devices, Inc. + * Copyright 2012-2026 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -300,6 +300,64 @@ ABM_SF(ABM0_DC_ABM1_HG_BIN_57_64_SHIFT_INDEX, \ ABM1_HG_BIN_57_64_SHIFT_INDEX, mask_sh) +#define ABM_MASK_SH_LIST_DCN42(mask_sh) \ + ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \ + ABM1_HG_NUM_OF_BINS_SEL, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \ + ABM1_HG_VMAX_SEL, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \ + ABM1_HG_BIN_BITWIDTH_SIZE_SEL, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \ + ABM1_IPCSC_COEFF_SEL_R, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \ + ABM1_IPCSC_COEFF_SEL_G, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \ + ABM1_IPCSC_COEFF_SEL_B, mask_sh), \ + ABM_SF(ABM0_BL1_PWM_CURRENT_ABM_LEVEL, \ + BL1_PWM_CURRENT_ABM_LEVEL, mask_sh), \ + ABM_SF(ABM0_BL1_PWM_TARGET_ABM_LEVEL, \ + BL1_PWM_TARGET_ABM_LEVEL, mask_sh), \ + ABM_SF(ABM0_BL1_PWM_USER_LEVEL, \ + BL1_PWM_USER_LEVEL, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \ + ABM1_LS_MIN_PIXEL_VALUE_THRES, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \ + ABM1_LS_MAX_PIXEL_VALUE_THRES, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \ + ABM1_HG_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \ + ABM1_LS_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \ + ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_ACE_OFFSET_SLOPE_DATA, \ + ABM1_ACE_SLOPE_DATA, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_ACE_OFFSET_SLOPE_DATA, \ + ABM1_ACE_OFFSET_DATA, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_ACE_PWL_CNTL, \ + ABM1_ACE_OFFSET_SLOPE_INDEX, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_ACE_PWL_CNTL, \ + ABM1_ACE_IGNORE_MASTER_LOCK_EN, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_ACE_PWL_CNTL, \ + ABM1_ACE_READBACK_DB_REG_VALUE_EN, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_ACE_PWL_CNTL, \ + ABM1_ACE_DBUF_REG_UPDATE_PENDING, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_ACE_PWL_CNTL, \ + ABM1_ACE_LOCK, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HG_RESULT_DATA, \ + ABM1_HG_RESULT_DATA, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HG_RESULT_INDEX, \ + ABM1_HG_RESULT_INDEX, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HG_BIN_33_40_SHIFT_INDEX, \ + ABM1_HG_BIN_33_40_SHIFT_INDEX, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HG_BIN_33_64_SHIFT_FLAG, \ + ABM1_HG_BIN_33_64_SHIFT_FLAG, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HG_BIN_41_48_SHIFT_INDEX, \ + ABM1_HG_BIN_41_48_SHIFT_INDEX, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HG_BIN_49_56_SHIFT_INDEX, \ + ABM1_HG_BIN_49_56_SHIFT_INDEX, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HG_BIN_57_64_SHIFT_INDEX, \ + ABM1_HG_BIN_57_64_SHIFT_INDEX, mask_sh) + #define ABM_REG_FIELD_LIST(type) \ type ABM1_HG_NUM_OF_BINS_SEL; \ type ABM1_HG_VMAX_SEL; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c index d18490cd0f1e..77df61bfaf27 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c @@ -350,6 +350,7 @@ static uint32_t calculate_required_audio_bw_in_symbols( uint32_t av_stream_map_lane_count, uint32_t audio_sdp_overhead) { + (void)channel_count; /* DP spec recommends between 1.05 to 1.1 safety margin to prevent sample under-run */ struct fixed31_32 audio_sdp_margin = dc_fixpt_from_fraction(110, 100); struct fixed31_32 horizontal_line_freq_khz = dc_fixpt_from_fraction( @@ -1027,6 +1028,7 @@ static void get_azalia_clock_info_hdmi( uint32_t actual_pixel_clock_100Hz, struct azalia_clock_info *azalia_clock_info) { + (void)crtc_pixel_clock_100hz; /* audio_dto_phase= 24 * 10,000; * 24MHz in [100Hz] units */ azalia_clock_info->audio_dto_phase = @@ -1043,6 +1045,7 @@ static void get_azalia_clock_info_dp( const struct audio_pll_info *pll_info, struct azalia_clock_info *azalia_clock_info) { + (void)requested_pixel_clock_100Hz; /* Reported dpDtoSourceClockInkhz value for * DCE8 already adjusted for SS, do not need any * adjustment here anymore @@ -1150,98 +1153,6 @@ void dce_aud_wall_dto_setup( } } -#if defined(CONFIG_DRM_AMD_DC_SI) -static void dce60_aud_wall_dto_setup( - struct audio *audio, - enum signal_type signal, - const struct audio_crtc_info *crtc_info, - const struct audio_pll_info *pll_info) -{ - struct dce_audio *aud = DCE_AUD(audio); - - struct azalia_clock_info clock_info = { 0 }; - - if (dc_is_hdmi_signal(signal)) { - uint32_t src_sel; - - /*DTO0 Programming goal: - -generate 24MHz, 128*Fs from 24MHz - -use DTO0 when an active HDMI port is connected - (optionally a DP is connected) */ - - /* calculate DTO settings */ - get_azalia_clock_info_hdmi( - crtc_info->requested_pixel_clock_100Hz, - crtc_info->calculated_pixel_clock_100Hz, - &clock_info); - - DC_LOG_HW_AUDIO("\n%s:Input::requested_pixel_clock_100Hz = %d"\ - "calculated_pixel_clock_100Hz =%d\n"\ - "audio_dto_module = %d audio_dto_phase =%d \n\n", __func__,\ - crtc_info->requested_pixel_clock_100Hz,\ - crtc_info->calculated_pixel_clock_100Hz,\ - clock_info.audio_dto_module,\ - clock_info.audio_dto_phase); - - /* On TN/SI, Program DTO source select and DTO select before - programming DTO modulo and DTO phase. These bits must be - programmed first, otherwise there will be no HDMI audio at boot - up. This is a HW sequence change (different from old ASICs). - Caution when changing this programming sequence. - - HDMI enabled, using DTO0 - program master CRTC for DTO0 */ - src_sel = pll_info->dto_source - DTO_SOURCE_ID0; - REG_UPDATE_2(DCCG_AUDIO_DTO_SOURCE, - DCCG_AUDIO_DTO0_SOURCE_SEL, src_sel, - DCCG_AUDIO_DTO_SEL, 0); - - /* module */ - REG_UPDATE(DCCG_AUDIO_DTO0_MODULE, - DCCG_AUDIO_DTO0_MODULE, clock_info.audio_dto_module); - - /* phase */ - REG_UPDATE(DCCG_AUDIO_DTO0_PHASE, - DCCG_AUDIO_DTO0_PHASE, clock_info.audio_dto_phase); - } else { - /*DTO1 Programming goal: - -generate 24MHz, 128*Fs from 24MHz (DCE6 does not support 512*Fs) - -default is to used DTO1, and switch to DTO0 when an audio - master HDMI port is connected - -use as default for DP - - calculate DTO settings */ - get_azalia_clock_info_dp( - crtc_info->requested_pixel_clock_100Hz, - pll_info, - &clock_info); - - /* Program DTO select before programming DTO modulo and DTO - phase. default to use DTO1 */ - - REG_UPDATE(DCCG_AUDIO_DTO_SOURCE, - DCCG_AUDIO_DTO_SEL, 1); - - /* DCCG_AUDIO_DTO2_USE_512FBR_DTO, 1) - * Cannot select 512fs for DP - * - * DCE6 has no DCCG_AUDIO_DTO2_USE_512FBR_DTO mask - */ - - /* module */ - REG_UPDATE(DCCG_AUDIO_DTO1_MODULE, - DCCG_AUDIO_DTO1_MODULE, clock_info.audio_dto_module); - - /* phase */ - REG_UPDATE(DCCG_AUDIO_DTO1_PHASE, - DCCG_AUDIO_DTO1_PHASE, clock_info.audio_dto_phase); - - /* DCE6 has no DCCG_AUDIO_DTO2_USE_512FBR_DTO mask in DCCG_AUDIO_DTO_SOURCE reg */ - - } -} -#endif - static bool dce_aud_endpoint_valid(struct audio *audio) { uint32_t value; @@ -1303,18 +1214,6 @@ static const struct audio_funcs funcs = { .destroy = dce_aud_destroy, }; -#if defined(CONFIG_DRM_AMD_DC_SI) -static const struct audio_funcs dce60_funcs = { - .endpoint_valid = dce_aud_endpoint_valid, - .hw_init = dce_aud_hw_init, - .wall_dto_setup = dce60_aud_wall_dto_setup, - .az_enable = dce_aud_az_enable, - .az_disable = dce_aud_az_disable, - .az_configure = dce_aud_az_configure, - .destroy = dce_aud_destroy, -}; -#endif - void dce_aud_destroy(struct audio **audio) { struct dce_audio *aud = DCE_AUD(*audio); @@ -1347,30 +1246,3 @@ struct audio *dce_audio_create( audio->masks = masks; return &audio->base; } - -#if defined(CONFIG_DRM_AMD_DC_SI) -struct audio *dce60_audio_create( - struct dc_context *ctx, - unsigned int inst, - const struct dce_audio_registers *reg, - const struct dce_audio_shift *shifts, - const struct dce_audio_mask *masks - ) -{ - struct dce_audio *audio = kzalloc_obj(*audio); - - if (audio == NULL) { - ASSERT_CRITICAL(audio); - return NULL; - } - - audio->base.ctx = ctx; - audio->base.inst = inst; - audio->base.funcs = &dce60_funcs; - - audio->regs = reg; - audio->shifts = shifts; - audio->masks = masks; - return &audio->base; -} -#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h index 1b7b8b079af4..3f1d161a0045 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h @@ -151,15 +151,6 @@ struct audio *dce_audio_create( const struct dce_audio_shift *shifts, const struct dce_audio_mask *masks); -#if defined(CONFIG_DRM_AMD_DC_SI) -struct audio *dce60_audio_create( - struct dc_context *ctx, - unsigned int inst, - const struct dce_audio_registers *reg, - const struct dce_audio_shift *shifts, - const struct dce_audio_mask *masks); -#endif - void dce_aud_destroy(struct audio **audio); void dce_aud_hw_init(struct audio *audio); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c deleted file mode 100644 index dca025b5ff1f..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c +++ /dev/null @@ -1,966 +0,0 @@ -/* - * Copyright 2012-16 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include <linux/slab.h> - -#include "dce_clk_mgr.h" - -#include "reg_helper.h" -#include "dmcu.h" -#include "core_types.h" -#include "dal_asic_id.h" - -#define TO_DCE_CLK_MGR(clocks)\ - container_of(clocks, struct dce_clk_mgr, base) - -#define REG(reg) \ - (clk_mgr_dce->regs->reg) - -#undef FN -#define FN(reg_name, field_name) \ - clk_mgr_dce->clk_mgr_shift->field_name, clk_mgr_dce->clk_mgr_mask->field_name - -#define CTX \ - clk_mgr_dce->base.ctx -#define DC_LOGGER \ - clk_mgr->ctx->logger - -/* Max clock values for each state indexed by "enum clocks_state": */ -static const struct state_dependent_clocks dce80_max_clks_by_state[] = { -/* ClocksStateInvalid - should not be used */ -{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, -/* ClocksStateUltraLow - not expected to be used for DCE 8.0 */ -{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, -/* ClocksStateLow */ -{ .display_clk_khz = 352000, .pixel_clk_khz = 330000}, -/* ClocksStateNominal */ -{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 }, -/* ClocksStatePerformance */ -{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 } }; - -static const struct state_dependent_clocks dce110_max_clks_by_state[] = { -/*ClocksStateInvalid - should not be used*/ -{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, -/*ClocksStateUltraLow - currently by HW design team not supposed to be used*/ -{ .display_clk_khz = 352000, .pixel_clk_khz = 330000 }, -/*ClocksStateLow*/ -{ .display_clk_khz = 352000, .pixel_clk_khz = 330000 }, -/*ClocksStateNominal*/ -{ .display_clk_khz = 467000, .pixel_clk_khz = 400000 }, -/*ClocksStatePerformance*/ -{ .display_clk_khz = 643000, .pixel_clk_khz = 400000 } }; - -static const struct state_dependent_clocks dce112_max_clks_by_state[] = { -/*ClocksStateInvalid - should not be used*/ -{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, -/*ClocksStateUltraLow - currently by HW design team not supposed to be used*/ -{ .display_clk_khz = 389189, .pixel_clk_khz = 346672 }, -/*ClocksStateLow*/ -{ .display_clk_khz = 459000, .pixel_clk_khz = 400000 }, -/*ClocksStateNominal*/ -{ .display_clk_khz = 667000, .pixel_clk_khz = 600000 }, -/*ClocksStatePerformance*/ -{ .display_clk_khz = 1132000, .pixel_clk_khz = 600000 } }; - -static const struct state_dependent_clocks dce120_max_clks_by_state[] = { -/*ClocksStateInvalid - should not be used*/ -{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, -/*ClocksStateUltraLow - currently by HW design team not supposed to be used*/ -{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, -/*ClocksStateLow*/ -{ .display_clk_khz = 460000, .pixel_clk_khz = 400000 }, -/*ClocksStateNominal*/ -{ .display_clk_khz = 670000, .pixel_clk_khz = 600000 }, -/*ClocksStatePerformance*/ -{ .display_clk_khz = 1133000, .pixel_clk_khz = 600000 } }; - -int dentist_get_divider_from_did(int did) -{ - if (did < DENTIST_BASE_DID_1) - did = DENTIST_BASE_DID_1; - if (did > DENTIST_MAX_DID) - did = DENTIST_MAX_DID; - - if (did < DENTIST_BASE_DID_2) { - return DENTIST_DIVIDER_RANGE_1_START + DENTIST_DIVIDER_RANGE_1_STEP - * (did - DENTIST_BASE_DID_1); - } else if (did < DENTIST_BASE_DID_3) { - return DENTIST_DIVIDER_RANGE_2_START + DENTIST_DIVIDER_RANGE_2_STEP - * (did - DENTIST_BASE_DID_2); - } else if (did < DENTIST_BASE_DID_4) { - return DENTIST_DIVIDER_RANGE_3_START + DENTIST_DIVIDER_RANGE_3_STEP - * (did - DENTIST_BASE_DID_3); - } else { - return DENTIST_DIVIDER_RANGE_4_START + DENTIST_DIVIDER_RANGE_4_STEP - * (did - DENTIST_BASE_DID_4); - } -} - -/* SW will adjust DP REF Clock average value for all purposes - * (DP DTO / DP Audio DTO and DP GTC) - if clock is spread for all cases: - -if SS enabled on DP Ref clock and HW de-spreading enabled with SW - calculations for DS_INCR/DS_MODULO (this is planned to be default case) - -if SS enabled on DP Ref clock and HW de-spreading enabled with HW - calculations (not planned to be used, but average clock should still - be valid) - -if SS enabled on DP Ref clock and HW de-spreading disabled - (should not be case with CIK) then SW should program all rates - generated according to average value (case as with previous ASICs) - */ -static int clk_mgr_adjust_dp_ref_freq_for_ss(struct dce_clk_mgr *clk_mgr_dce, int dp_ref_clk_khz) -{ - if (clk_mgr_dce->ss_on_dprefclk && clk_mgr_dce->dprefclk_ss_divider != 0) { - struct fixed31_32 ss_percentage = dc_fixpt_div_int( - dc_fixpt_from_fraction(clk_mgr_dce->dprefclk_ss_percentage, - clk_mgr_dce->dprefclk_ss_divider), 200); - struct fixed31_32 adj_dp_ref_clk_khz; - - ss_percentage = dc_fixpt_sub(dc_fixpt_one, ss_percentage); - adj_dp_ref_clk_khz = dc_fixpt_mul_int(ss_percentage, dp_ref_clk_khz); - dp_ref_clk_khz = dc_fixpt_floor(adj_dp_ref_clk_khz); - } - return dp_ref_clk_khz; -} - -static int dce_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr) -{ - struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr); - int dprefclk_wdivider; - int dprefclk_src_sel; - int dp_ref_clk_khz = 600000; - int target_div; - - /* ASSERT DP Reference Clock source is from DFS*/ - REG_GET(DPREFCLK_CNTL, DPREFCLK_SRC_SEL, &dprefclk_src_sel); - ASSERT(dprefclk_src_sel == 0); - - /* Read the mmDENTIST_DISPCLK_CNTL to get the currently - * programmed DID DENTIST_DPREFCLK_WDIVIDER*/ - REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, &dprefclk_wdivider); - - /* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/ - target_div = dentist_get_divider_from_did(dprefclk_wdivider); - - /* Calculate the current DFS clock, in kHz.*/ - dp_ref_clk_khz = (DENTIST_DIVIDER_RANGE_SCALE_FACTOR - * clk_mgr_dce->dentist_vco_freq_khz) / target_div; - - return clk_mgr_adjust_dp_ref_freq_for_ss(clk_mgr_dce, dp_ref_clk_khz); -} - -int dce12_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr) -{ - struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr); - - return clk_mgr_adjust_dp_ref_freq_for_ss(clk_mgr_dce, clk_mgr_dce->dprefclk_khz); -} - -/* unit: in_khz before mode set, get pixel clock from context. ASIC register - * may not be programmed yet - */ -static uint32_t get_max_pixel_clock_for_all_paths(struct dc_state *context) -{ - uint32_t max_pix_clk = 0; - int i; - - for (i = 0; i < MAX_PIPES; i++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - - if (pipe_ctx->stream == NULL) - continue; - - /* do not check under lay */ - if (pipe_ctx->top_pipe) - continue; - - if (pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz / 10 > max_pix_clk) - max_pix_clk = pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz / 10; - - /* raise clock state for HBR3/2 if required. Confirmed with HW DCE/DPCS - * logic for HBR3 still needs Nominal (0.8V) on VDDC rail - */ - if (dc_is_dp_signal(pipe_ctx->stream->signal) && - pipe_ctx->stream_res.pix_clk_params.requested_sym_clk > max_pix_clk) - max_pix_clk = pipe_ctx->stream_res.pix_clk_params.requested_sym_clk; - } - - return max_pix_clk; -} - -static enum dm_pp_clocks_state dce_get_required_clocks_state( - struct clk_mgr *clk_mgr, - struct dc_state *context) -{ - struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr); - int i; - enum dm_pp_clocks_state low_req_clk; - int max_pix_clk = get_max_pixel_clock_for_all_paths(context); - - /* Iterate from highest supported to lowest valid state, and update - * lowest RequiredState with the lowest state that satisfies - * all required clocks - */ - for (i = clk_mgr_dce->max_clks_state; i >= DM_PP_CLOCKS_STATE_ULTRA_LOW; i--) - if (context->bw_ctx.bw.dce.dispclk_khz > - clk_mgr_dce->max_clks_by_state[i].display_clk_khz - || max_pix_clk > - clk_mgr_dce->max_clks_by_state[i].pixel_clk_khz) - break; - - low_req_clk = i + 1; - if (low_req_clk > clk_mgr_dce->max_clks_state) { - /* set max clock state for high phyclock, invalid on exceeding display clock */ - if (clk_mgr_dce->max_clks_by_state[clk_mgr_dce->max_clks_state].display_clk_khz - < context->bw_ctx.bw.dce.dispclk_khz) - low_req_clk = DM_PP_CLOCKS_STATE_INVALID; - else - low_req_clk = clk_mgr_dce->max_clks_state; - } - - return low_req_clk; -} - -static int dce_set_clock( - struct clk_mgr *clk_mgr, - int requested_clk_khz) -{ - struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr); - struct bp_pixel_clock_parameters pxl_clk_params = { 0 }; - struct dc_bios *bp = clk_mgr->ctx->dc_bios; - int actual_clock = requested_clk_khz; - struct dmcu *dmcu = clk_mgr_dce->base.ctx->dc->res_pool->dmcu; - - /* Make sure requested clock isn't lower than minimum threshold*/ - if (requested_clk_khz > 0) - requested_clk_khz = max(requested_clk_khz, - clk_mgr_dce->dentist_vco_freq_khz / 64); - - /* Prepare to program display clock*/ - pxl_clk_params.target_pixel_clock_100hz = requested_clk_khz * 10; - pxl_clk_params.pll_id = CLOCK_SOURCE_ID_DFS; - - if (clk_mgr_dce->dfs_bypass_active) - pxl_clk_params.flags.SET_DISPCLK_DFS_BYPASS = true; - - bp->funcs->program_display_engine_pll(bp, &pxl_clk_params); - - if (clk_mgr_dce->dfs_bypass_active) { - /* Cache the fixed display clock*/ - clk_mgr_dce->dfs_bypass_disp_clk = - pxl_clk_params.dfs_bypass_display_clock; - actual_clock = pxl_clk_params.dfs_bypass_display_clock; - } - - /* from power down, we need mark the clock state as ClocksStateNominal - * from HWReset, so when resume we will call pplib voltage regulator.*/ - if (requested_clk_khz == 0) - clk_mgr_dce->cur_min_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; - - if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) - dmcu->funcs->set_psr_wait_loop(dmcu, actual_clock / 1000 / 7); - - return actual_clock; -} - -int dce112_set_clock(struct clk_mgr *clk_mgr, int requested_clk_khz) -{ - struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr); - struct bp_set_dce_clock_parameters dce_clk_params; - struct dc_bios *bp = clk_mgr->ctx->dc_bios; - struct dc *core_dc = clk_mgr->ctx->dc; - struct dmcu *dmcu = core_dc->res_pool->dmcu; - int actual_clock = requested_clk_khz; - /* Prepare to program display clock*/ - memset(&dce_clk_params, 0, sizeof(dce_clk_params)); - - /* Make sure requested clock isn't lower than minimum threshold*/ - if (requested_clk_khz > 0) - requested_clk_khz = max(requested_clk_khz, - clk_mgr_dce->dentist_vco_freq_khz / 62); - - dce_clk_params.target_clock_frequency = requested_clk_khz; - dce_clk_params.pll_id = CLOCK_SOURCE_ID_DFS; - dce_clk_params.clock_type = DCECLOCK_TYPE_DISPLAY_CLOCK; - - bp->funcs->set_dce_clock(bp, &dce_clk_params); - actual_clock = dce_clk_params.target_clock_frequency; - - /* from power down, we need mark the clock state as ClocksStateNominal - * from HWReset, so when resume we will call pplib voltage regulator.*/ - if (requested_clk_khz == 0) - clk_mgr_dce->cur_min_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; - - /*Program DP ref Clock*/ - /*VBIOS will determine DPREFCLK frequency, so we don't set it*/ - dce_clk_params.target_clock_frequency = 0; - dce_clk_params.clock_type = DCECLOCK_TYPE_DPREFCLK; - - if (!((clk_mgr->ctx->asic_id.chip_family == FAMILY_AI) && - ASICREV_IS_VEGA20_P(clk_mgr->ctx->asic_id.hw_internal_rev))) - dce_clk_params.flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK = - (dce_clk_params.pll_id == - CLOCK_SOURCE_COMBO_DISPLAY_PLL0); - else - dce_clk_params.flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK = false; - - bp->funcs->set_dce_clock(bp, &dce_clk_params); - - if (!IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment)) { - if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) { - if (clk_mgr_dce->dfs_bypass_disp_clk != actual_clock) - dmcu->funcs->set_psr_wait_loop(dmcu, - actual_clock / 1000 / 7); - } - } - - clk_mgr_dce->dfs_bypass_disp_clk = actual_clock; - return actual_clock; -} - -static void dce_clock_read_integrated_info(struct dce_clk_mgr *clk_mgr_dce) -{ - struct dc_debug_options *debug = &clk_mgr_dce->base.ctx->dc->debug; - struct dc_bios *bp = clk_mgr_dce->base.ctx->dc_bios; - struct integrated_info info = { { { 0 } } }; - struct dc_firmware_info fw_info = { { 0 } }; - int i; - - if (bp->integrated_info) - info = *bp->integrated_info; - - clk_mgr_dce->dentist_vco_freq_khz = info.dentist_vco_freq; - if (clk_mgr_dce->dentist_vco_freq_khz == 0) { - bp->funcs->get_firmware_info(bp, &fw_info); - clk_mgr_dce->dentist_vco_freq_khz = - fw_info.smu_gpu_pll_output_freq; - if (clk_mgr_dce->dentist_vco_freq_khz == 0) - clk_mgr_dce->dentist_vco_freq_khz = 3600000; - } - - /*update the maximum display clock for each power state*/ - for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { - enum dm_pp_clocks_state clk_state = DM_PP_CLOCKS_STATE_INVALID; - - switch (i) { - case 0: - clk_state = DM_PP_CLOCKS_STATE_ULTRA_LOW; - break; - - case 1: - clk_state = DM_PP_CLOCKS_STATE_LOW; - break; - - case 2: - clk_state = DM_PP_CLOCKS_STATE_NOMINAL; - break; - - case 3: - clk_state = DM_PP_CLOCKS_STATE_PERFORMANCE; - break; - - default: - clk_state = DM_PP_CLOCKS_STATE_INVALID; - break; - } - - /*Do not allow bad VBIOS/SBIOS to override with invalid values, - * check for > 100MHz*/ - if (info.disp_clk_voltage[i].max_supported_clk >= 100000) - clk_mgr_dce->max_clks_by_state[clk_state].display_clk_khz = - info.disp_clk_voltage[i].max_supported_clk; - } - - if (!debug->disable_dfs_bypass && bp->integrated_info) - if (bp->integrated_info->gpu_cap_info & DFS_BYPASS_ENABLE) - clk_mgr_dce->dfs_bypass_enabled = true; -} - -void dce_clock_read_ss_info(struct dce_clk_mgr *clk_mgr_dce) -{ - struct dc_bios *bp = clk_mgr_dce->base.ctx->dc_bios; - int ss_info_num = bp->funcs->get_ss_entry_number( - bp, AS_SIGNAL_TYPE_GPU_PLL); - - if (ss_info_num) { - struct spread_spectrum_info info = { { 0 } }; - enum bp_result result = bp->funcs->get_spread_spectrum_info( - bp, AS_SIGNAL_TYPE_GPU_PLL, 0, &info); - - /* Based on VBIOS, VBIOS will keep entry for GPU PLL SS - * even if SS not enabled and in that case - * SSInfo.spreadSpectrumPercentage !=0 would be sign - * that SS is enabled - */ - if (result == BP_RESULT_OK && - info.spread_spectrum_percentage != 0) { - clk_mgr_dce->ss_on_dprefclk = true; - clk_mgr_dce->dprefclk_ss_divider = info.spread_percentage_divider; - - if (info.type.CENTER_MODE == 0) { - /* TODO: Currently for DP Reference clock we - * need only SS percentage for - * downspread */ - clk_mgr_dce->dprefclk_ss_percentage = - info.spread_spectrum_percentage; - } - - return; - } - - result = bp->funcs->get_spread_spectrum_info( - bp, AS_SIGNAL_TYPE_DISPLAY_PORT, 0, &info); - - /* Based on VBIOS, VBIOS will keep entry for DPREFCLK SS - * even if SS not enabled and in that case - * SSInfo.spreadSpectrumPercentage !=0 would be sign - * that SS is enabled - */ - if (result == BP_RESULT_OK && - info.spread_spectrum_percentage != 0) { - clk_mgr_dce->ss_on_dprefclk = true; - clk_mgr_dce->dprefclk_ss_divider = info.spread_percentage_divider; - - if (info.type.CENTER_MODE == 0) { - /* Currently for DP Reference clock we - * need only SS percentage for - * downspread */ - clk_mgr_dce->dprefclk_ss_percentage = - info.spread_spectrum_percentage; - } - if (clk_mgr_dce->base.ctx->dc->debug.ignore_dpref_ss) - clk_mgr_dce->dprefclk_ss_percentage = 0; - } - } -} - -/** - * dce121_clock_patch_xgmi_ss_info() - Save XGMI spread spectrum info - * @clk_mgr: clock manager base structure - * - * Reads from VBIOS the XGMI spread spectrum info and saves it within - * the dce clock manager. This operation will overwrite the existing dprefclk - * SS values if the vBIOS query succeeds. Otherwise, it does nothing. It also - * sets the ->xgmi_enabled flag. - */ -void dce121_clock_patch_xgmi_ss_info(struct clk_mgr *clk_mgr) -{ - struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr); - enum bp_result result; - struct spread_spectrum_info info = { { 0 } }; - struct dc_bios *bp = clk_mgr_dce->base.ctx->dc_bios; - - clk_mgr_dce->xgmi_enabled = false; - - result = bp->funcs->get_spread_spectrum_info(bp, AS_SIGNAL_TYPE_XGMI, - 0, &info); - if (result == BP_RESULT_OK && info.spread_spectrum_percentage != 0) { - clk_mgr_dce->xgmi_enabled = true; - clk_mgr_dce->ss_on_dprefclk = true; - clk_mgr_dce->dprefclk_ss_divider = - info.spread_percentage_divider; - - if (info.type.CENTER_MODE == 0) { - /* Currently for DP Reference clock we - * need only SS percentage for - * downspread */ - clk_mgr_dce->dprefclk_ss_percentage = - info.spread_spectrum_percentage; - } - } -} - -void dce110_fill_display_configs( - const struct dc_state *context, - struct dm_pp_display_configuration *pp_display_cfg) -{ - int j; - int num_cfgs = 0; - - for (j = 0; j < context->stream_count; j++) { - int k; - - const struct dc_stream_state *stream = context->streams[j]; - struct dm_pp_single_disp_config *cfg = - &pp_display_cfg->disp_configs[num_cfgs]; - const struct pipe_ctx *pipe_ctx = NULL; - - for (k = 0; k < MAX_PIPES; k++) - if (stream == context->res_ctx.pipe_ctx[k].stream) { - pipe_ctx = &context->res_ctx.pipe_ctx[k]; - break; - } - - ASSERT(pipe_ctx != NULL); - - /* only notify active stream */ - if (stream->dpms_off) - continue; - - num_cfgs++; - cfg->signal = pipe_ctx->stream->signal; - cfg->pipe_idx = pipe_ctx->stream_res.tg->inst; - cfg->src_height = stream->src.height; - cfg->src_width = stream->src.width; - cfg->ddi_channel_mapping = - stream->link->ddi_channel_mapping.raw; - cfg->transmitter = - stream->link->link_enc->transmitter; - cfg->link_settings.lane_count = - stream->link->cur_link_settings.lane_count; - cfg->link_settings.link_rate = - stream->link->cur_link_settings.link_rate; - cfg->link_settings.link_spread = - stream->link->cur_link_settings.link_spread; - cfg->sym_clock = stream->phy_pix_clk; - /* Round v_refresh*/ - cfg->v_refresh = stream->timing.pix_clk_100hz * 100; - cfg->v_refresh /= stream->timing.h_total; - cfg->v_refresh = (cfg->v_refresh + stream->timing.v_total / 2) - / stream->timing.v_total; - } - - pp_display_cfg->display_count = num_cfgs; -} - -static uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context) -{ - uint8_t j; - uint32_t min_vertical_blank_time = -1; - - for (j = 0; j < context->stream_count; j++) { - struct dc_stream_state *stream = context->streams[j]; - uint32_t vertical_blank_in_pixels = 0; - uint32_t vertical_blank_time = 0; - - vertical_blank_in_pixels = stream->timing.h_total * - (stream->timing.v_total - - stream->timing.v_addressable); - - vertical_blank_time = vertical_blank_in_pixels - * 10000 / stream->timing.pix_clk_100hz; - - if (min_vertical_blank_time > vertical_blank_time) - min_vertical_blank_time = vertical_blank_time; - } - - return min_vertical_blank_time; -} - -static int determine_sclk_from_bounding_box( - const struct dc *dc, - int required_sclk) -{ - int i; - - /* - * Some asics do not give us sclk levels, so we just report the actual - * required sclk - */ - if (dc->sclk_lvls.num_levels == 0) - return required_sclk; - - for (i = 0; i < dc->sclk_lvls.num_levels; i++) { - if (dc->sclk_lvls.clocks_in_khz[i] >= required_sclk) - return dc->sclk_lvls.clocks_in_khz[i]; - } - /* - * even maximum level could not satisfy requirement, this - * is unexpected at this stage, should have been caught at - * validation time - */ - ASSERT(0); - return dc->sclk_lvls.clocks_in_khz[dc->sclk_lvls.num_levels - 1]; -} - -static void dce_pplib_apply_display_requirements( - struct dc *dc, - struct dc_state *context) -{ - struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; - - pp_display_cfg->avail_mclk_switch_time_us = dce110_get_min_vblank_time_us(context); - - dce110_fill_display_configs(context, pp_display_cfg); - - if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) != 0) - dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg); -} - -static void dce11_pplib_apply_display_requirements( - struct dc *dc, - struct dc_state *context) -{ - struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; - - pp_display_cfg->all_displays_in_sync = - context->bw_ctx.bw.dce.all_displays_in_sync; - pp_display_cfg->nb_pstate_switch_disable = - context->bw_ctx.bw.dce.nbp_state_change_enable == false; - pp_display_cfg->cpu_cc6_disable = - context->bw_ctx.bw.dce.cpuc_state_change_enable == false; - pp_display_cfg->cpu_pstate_disable = - context->bw_ctx.bw.dce.cpup_state_change_enable == false; - pp_display_cfg->cpu_pstate_separation_time = - context->bw_ctx.bw.dce.blackout_recovery_time_us; - - pp_display_cfg->min_memory_clock_khz = context->bw_ctx.bw.dce.yclk_khz - / MEMORY_TYPE_MULTIPLIER_CZ; - - pp_display_cfg->min_engine_clock_khz = determine_sclk_from_bounding_box( - dc, - context->bw_ctx.bw.dce.sclk_khz); - - /* - * As workaround for >4x4K lightup set dcfclock to min_engine_clock value. - * This is not required for less than 5 displays, - * thus don't request decfclk in dc to avoid impact - * on power saving. - * - */ - pp_display_cfg->min_dcfclock_khz = (context->stream_count > 4) ? - pp_display_cfg->min_engine_clock_khz : 0; - - pp_display_cfg->min_engine_clock_deep_sleep_khz - = context->bw_ctx.bw.dce.sclk_deep_sleep_khz; - - pp_display_cfg->avail_mclk_switch_time_us = - dce110_get_min_vblank_time_us(context); - /* TODO: dce11.2*/ - pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0; - - pp_display_cfg->disp_clk_khz = dc->res_pool->clk_mgr->clks.dispclk_khz; - - dce110_fill_display_configs(context, pp_display_cfg); - - /* TODO: is this still applicable?*/ - if (pp_display_cfg->display_count == 1) { - const struct dc_crtc_timing *timing = - &context->streams[0]->timing; - - pp_display_cfg->crtc_index = - pp_display_cfg->disp_configs[0].pipe_idx; - pp_display_cfg->line_time_in_us = timing->h_total * 10000 / timing->pix_clk_100hz; - } - - if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) != 0) - dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg); -} - -static void dce_update_clocks(struct clk_mgr *clk_mgr, - struct dc_state *context, - bool safe_to_lower) -{ - struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr); - struct dm_pp_power_level_change_request level_change_req; - int patched_disp_clk = context->bw_ctx.bw.dce.dispclk_khz; - - /*TODO: W/A for dal3 linux, investigate why this works */ - if (!clk_mgr_dce->dfs_bypass_active) - patched_disp_clk = patched_disp_clk * 115 / 100; - - level_change_req.power_level = dce_get_required_clocks_state(clk_mgr, context); - /* get max clock state from PPLIB */ - if ((level_change_req.power_level < clk_mgr_dce->cur_min_clks_state && safe_to_lower) - || level_change_req.power_level > clk_mgr_dce->cur_min_clks_state) { - if (dm_pp_apply_power_level_change_request(clk_mgr->ctx, &level_change_req)) - clk_mgr_dce->cur_min_clks_state = level_change_req.power_level; - } - - if (should_set_clock(safe_to_lower, patched_disp_clk, clk_mgr->clks.dispclk_khz)) { - patched_disp_clk = dce_set_clock(clk_mgr, patched_disp_clk); - clk_mgr->clks.dispclk_khz = patched_disp_clk; - } - dce_pplib_apply_display_requirements(clk_mgr->ctx->dc, context); -} - -static void dce11_update_clocks(struct clk_mgr *clk_mgr, - struct dc_state *context, - bool safe_to_lower) -{ - struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr); - struct dm_pp_power_level_change_request level_change_req; - int patched_disp_clk = context->bw_ctx.bw.dce.dispclk_khz; - - /*TODO: W/A for dal3 linux, investigate why this works */ - if (!clk_mgr_dce->dfs_bypass_active) - patched_disp_clk = patched_disp_clk * 115 / 100; - - level_change_req.power_level = dce_get_required_clocks_state(clk_mgr, context); - /* get max clock state from PPLIB */ - if ((level_change_req.power_level < clk_mgr_dce->cur_min_clks_state && safe_to_lower) - || level_change_req.power_level > clk_mgr_dce->cur_min_clks_state) { - if (dm_pp_apply_power_level_change_request(clk_mgr->ctx, &level_change_req)) - clk_mgr_dce->cur_min_clks_state = level_change_req.power_level; - } - - if (should_set_clock(safe_to_lower, patched_disp_clk, clk_mgr->clks.dispclk_khz)) { - context->bw_ctx.bw.dce.dispclk_khz = dce_set_clock(clk_mgr, patched_disp_clk); - clk_mgr->clks.dispclk_khz = patched_disp_clk; - } - dce11_pplib_apply_display_requirements(clk_mgr->ctx->dc, context); -} - -static void dce112_update_clocks(struct clk_mgr *clk_mgr, - struct dc_state *context, - bool safe_to_lower) -{ - struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr); - struct dm_pp_power_level_change_request level_change_req; - int patched_disp_clk = context->bw_ctx.bw.dce.dispclk_khz; - - /*TODO: W/A for dal3 linux, investigate why this works */ - if (!clk_mgr_dce->dfs_bypass_active) - patched_disp_clk = patched_disp_clk * 115 / 100; - - level_change_req.power_level = dce_get_required_clocks_state(clk_mgr, context); - /* get max clock state from PPLIB */ - if ((level_change_req.power_level < clk_mgr_dce->cur_min_clks_state && safe_to_lower) - || level_change_req.power_level > clk_mgr_dce->cur_min_clks_state) { - if (dm_pp_apply_power_level_change_request(clk_mgr->ctx, &level_change_req)) - clk_mgr_dce->cur_min_clks_state = level_change_req.power_level; - } - - if (should_set_clock(safe_to_lower, patched_disp_clk, clk_mgr->clks.dispclk_khz)) { - patched_disp_clk = dce112_set_clock(clk_mgr, patched_disp_clk); - clk_mgr->clks.dispclk_khz = patched_disp_clk; - } - dce11_pplib_apply_display_requirements(clk_mgr->ctx->dc, context); -} - -static void dce12_update_clocks(struct clk_mgr *clk_mgr, - struct dc_state *context, - bool safe_to_lower) -{ - struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr); - struct dm_pp_clock_for_voltage_req clock_voltage_req = {0}; - int max_pix_clk = get_max_pixel_clock_for_all_paths(context); - int patched_disp_clk = context->bw_ctx.bw.dce.dispclk_khz; - - /*TODO: W/A for dal3 linux, investigate why this works */ - if (!clk_mgr_dce->dfs_bypass_active) - patched_disp_clk = patched_disp_clk * 115 / 100; - - if (should_set_clock(safe_to_lower, patched_disp_clk, clk_mgr->clks.dispclk_khz)) { - clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DISPLAY_CLK; - /* - * When xGMI is enabled, the display clk needs to be adjusted - * with the WAFL link's SS percentage. - */ - if (clk_mgr_dce->xgmi_enabled) - patched_disp_clk = clk_mgr_adjust_dp_ref_freq_for_ss( - clk_mgr_dce, patched_disp_clk); - clock_voltage_req.clocks_in_khz = patched_disp_clk; - clk_mgr->clks.dispclk_khz = dce112_set_clock(clk_mgr, patched_disp_clk); - - dm_pp_apply_clock_for_voltage_request(clk_mgr->ctx, &clock_voltage_req); - } - - if (should_set_clock(safe_to_lower, max_pix_clk, clk_mgr->clks.phyclk_khz)) { - clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DISPLAYPHYCLK; - clock_voltage_req.clocks_in_khz = max_pix_clk; - clk_mgr->clks.phyclk_khz = max_pix_clk; - - dm_pp_apply_clock_for_voltage_request(clk_mgr->ctx, &clock_voltage_req); - } - dce11_pplib_apply_display_requirements(clk_mgr->ctx->dc, context); -} - -static const struct clk_mgr_funcs dce120_funcs = { - .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz, - .update_clocks = dce12_update_clocks -}; - -static const struct clk_mgr_funcs dce112_funcs = { - .get_dp_ref_clk_frequency = dce_get_dp_ref_freq_khz, - .update_clocks = dce112_update_clocks -}; - -static const struct clk_mgr_funcs dce110_funcs = { - .get_dp_ref_clk_frequency = dce_get_dp_ref_freq_khz, - .update_clocks = dce11_update_clocks, -}; - -static const struct clk_mgr_funcs dce_funcs = { - .get_dp_ref_clk_frequency = dce_get_dp_ref_freq_khz, - .update_clocks = dce_update_clocks -}; - -static void dce_clk_mgr_construct( - struct dce_clk_mgr *clk_mgr_dce, - struct dc_context *ctx, - const struct clk_mgr_registers *regs, - const struct clk_mgr_shift *clk_shift, - const struct clk_mgr_mask *clk_mask) -{ - struct clk_mgr *base = &clk_mgr_dce->base; - struct dm_pp_static_clock_info static_clk_info = {0}; - - base->ctx = ctx; - base->funcs = &dce_funcs; - - clk_mgr_dce->regs = regs; - clk_mgr_dce->clk_mgr_shift = clk_shift; - clk_mgr_dce->clk_mgr_mask = clk_mask; - - clk_mgr_dce->dfs_bypass_disp_clk = 0; - - clk_mgr_dce->dprefclk_ss_percentage = 0; - clk_mgr_dce->dprefclk_ss_divider = 1000; - clk_mgr_dce->ss_on_dprefclk = false; - - - if (dm_pp_get_static_clocks(ctx, &static_clk_info)) - clk_mgr_dce->max_clks_state = static_clk_info.max_clocks_state; - else - clk_mgr_dce->max_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; - clk_mgr_dce->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID; - - dce_clock_read_integrated_info(clk_mgr_dce); - dce_clock_read_ss_info(clk_mgr_dce); -} - -struct clk_mgr *dce_clk_mgr_create( - struct dc_context *ctx, - const struct clk_mgr_registers *regs, - const struct clk_mgr_shift *clk_shift, - const struct clk_mgr_mask *clk_mask) -{ - struct dce_clk_mgr *clk_mgr_dce = kzalloc_obj(*clk_mgr_dce); - - if (clk_mgr_dce == NULL) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - memcpy(clk_mgr_dce->max_clks_by_state, - dce80_max_clks_by_state, - sizeof(dce80_max_clks_by_state)); - - dce_clk_mgr_construct( - clk_mgr_dce, ctx, regs, clk_shift, clk_mask); - - return &clk_mgr_dce->base; -} - -struct clk_mgr *dce110_clk_mgr_create( - struct dc_context *ctx, - const struct clk_mgr_registers *regs, - const struct clk_mgr_shift *clk_shift, - const struct clk_mgr_mask *clk_mask) -{ - struct dce_clk_mgr *clk_mgr_dce = kzalloc_obj(*clk_mgr_dce); - - if (clk_mgr_dce == NULL) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - memcpy(clk_mgr_dce->max_clks_by_state, - dce110_max_clks_by_state, - sizeof(dce110_max_clks_by_state)); - - dce_clk_mgr_construct( - clk_mgr_dce, ctx, regs, clk_shift, clk_mask); - - clk_mgr_dce->base.funcs = &dce110_funcs; - - return &clk_mgr_dce->base; -} - -struct clk_mgr *dce112_clk_mgr_create( - struct dc_context *ctx, - const struct clk_mgr_registers *regs, - const struct clk_mgr_shift *clk_shift, - const struct clk_mgr_mask *clk_mask) -{ - struct dce_clk_mgr *clk_mgr_dce = kzalloc_obj(*clk_mgr_dce); - - if (clk_mgr_dce == NULL) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - memcpy(clk_mgr_dce->max_clks_by_state, - dce112_max_clks_by_state, - sizeof(dce112_max_clks_by_state)); - - dce_clk_mgr_construct( - clk_mgr_dce, ctx, regs, clk_shift, clk_mask); - - clk_mgr_dce->base.funcs = &dce112_funcs; - - return &clk_mgr_dce->base; -} - -struct clk_mgr *dce120_clk_mgr_create(struct dc_context *ctx) -{ - struct dce_clk_mgr *clk_mgr_dce = kzalloc_obj(*clk_mgr_dce); - - if (clk_mgr_dce == NULL) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - memcpy(clk_mgr_dce->max_clks_by_state, - dce120_max_clks_by_state, - sizeof(dce120_max_clks_by_state)); - - dce_clk_mgr_construct( - clk_mgr_dce, ctx, NULL, NULL, NULL); - - clk_mgr_dce->dprefclk_khz = 600000; - clk_mgr_dce->base.funcs = &dce120_funcs; - - return &clk_mgr_dce->base; -} - -struct clk_mgr *dce121_clk_mgr_create(struct dc_context *ctx) -{ - struct dce_clk_mgr *clk_mgr_dce = kzalloc_obj(*clk_mgr_dce); - - if (clk_mgr_dce == NULL) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - memcpy(clk_mgr_dce->max_clks_by_state, dce120_max_clks_by_state, - sizeof(dce120_max_clks_by_state)); - - dce_clk_mgr_construct(clk_mgr_dce, ctx, NULL, NULL, NULL); - - clk_mgr_dce->dprefclk_khz = 625000; - clk_mgr_dce->base.funcs = &dce120_funcs; - - return &clk_mgr_dce->base; -} - -void dce_clk_mgr_destroy(struct clk_mgr **clk_mgr) -{ - struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(*clk_mgr); - - kfree(clk_mgr_dce); - *clk_mgr = NULL; -} diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 5722be965422..34e54fdb9d13 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -539,6 +539,7 @@ static void dce112_get_pix_clk_dividers_helper ( struct pll_settings *pll_settings, struct pixel_clk_params *pix_clk_params) { + (void)clk_src; uint32_t actual_pixel_clock_100hz; actual_pixel_clock_100hz = pix_clk_params->requested_pix_clk_100hz; @@ -610,7 +611,7 @@ static uint32_t dce112_get_pix_clk_dividers( || pix_clk_params->requested_pix_clk_100hz == 0) { DC_LOG_ERROR( "%s: Invalid parameters!!\n", __func__); - return -1; + return (uint32_t)-1; } memset(pll_settings, 0, sizeof(*pll_settings)); @@ -621,7 +622,7 @@ static uint32_t dce112_get_pix_clk_dividers( pll_settings->calculated_pix_clk_100hz = clk_src->ext_clk_khz * 10; pll_settings->actual_pix_clk_100hz = pix_clk_params->requested_pix_clk_100hz; - return -1; + return (uint32_t)-1; } dce112_get_pix_clk_dividers_helper(clk_src, @@ -847,6 +848,7 @@ static bool dce110_program_pix_clk( enum dp_link_encoding encoding, struct pll_settings *pll_settings) { + (void)encoding; struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source); struct bp_pixel_clock_parameters bp_pc_params = {0}; @@ -921,6 +923,7 @@ static bool dce112_program_pix_clk( enum dp_link_encoding encoding, struct pll_settings *pll_settings) { + (void)encoding; struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source); struct bp_pixel_clock_parameters bp_pc_params = {0}; @@ -1070,6 +1073,7 @@ static bool dcn401_program_pix_clk( enum dp_link_encoding encoding, struct pll_settings *pll_settings) { + (void)encoding; struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source); unsigned int inst = pix_clk_params->controller_id - CONTROLLER_ID_D0; const struct pixel_rate_range_table_entry *e = @@ -1376,7 +1380,7 @@ static uint32_t dcn3_get_pix_clk_dividers( || pix_clk_params->requested_pix_clk_100hz == 0) { DC_LOG_ERROR( "%s: Invalid parameters!!\n", __func__); - return -1; + return UINT_MAX; } memset(pll_settings, 0, sizeof(*pll_settings)); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index e871b72e43ef..25ebd8a52ae4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -71,6 +71,7 @@ static const uint32_t abm_gain_stepsize = 0x0060; static bool dce_dmcu_init(struct dmcu *dmcu) { + (void)dmcu; // Do nothing return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c.c b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c.c index f5cd2392fc5f..f5261e8d7678 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c.c @@ -31,6 +31,7 @@ bool dce_i2c_oem_device_present( size_t slave_address ) { + (void)pool; struct dc *dc = ddc->ctx->dc; struct dc_bios *dcb = dc->ctx->dc_bios; struct graphics_object_id id = {0}; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c index 365dd2e37aea..fe239a96121e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c @@ -69,6 +69,7 @@ static enum i2c_channel_operation_result get_channel_status( struct dce_i2c_hw *dce_i2c_hw, uint8_t *returned_bytes) { + (void)returned_bytes; uint32_t i2c_sw_status = 0; uint32_t value = REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status); @@ -631,6 +632,7 @@ bool dce_i2c_submit_command_hw( struct i2c_command *cmd, struct dce_i2c_hw *dce_i2c_hw) { + (void)ddc; uint8_t index_of_payload = 0; bool result; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_sw.c b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_sw.c index 2d73b94c515c..52e05b9185f1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_sw.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_sw.c @@ -67,6 +67,7 @@ static void release_engine_dce_sw( struct resource_pool *pool, struct dce_i2c_sw *dce_i2c_sw) { + (void)pool; dal_ddc_close(dce_i2c_sw->ddc); dce_i2c_sw->ddc = NULL; } @@ -76,6 +77,7 @@ static bool wait_for_scl_high_sw( struct ddc *ddc, uint16_t clock_delay_div_4) { + (void)ctx; uint32_t scl_retry = 0; uint32_t scl_retry_max = I2C_SW_TIMEOUT_DELAY / clock_delay_div_4; @@ -469,6 +471,7 @@ bool dce_i2c_submit_command_sw( struct i2c_command *cmd, struct dce_i2c_sw *dce_i2c_sw) { + (void)ddc; uint8_t index_of_payload = 0; bool result; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c index 34bff9aef66c..ee55ec21d270 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c @@ -43,6 +43,7 @@ static void dce_ipp_cursor_set_position( const struct dc_cursor_position *position, const struct dc_cursor_mi_param *param) { + (void)param; struct dce_ipp *ipp_dce = TO_DCE_IPP(ipp); /* lock cursor registers */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 2ba3d3a3aac5..5f40ae9e3120 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -122,6 +122,33 @@ static const struct link_encoder_funcs dce110_lnk_enc_funcs = { .program_hpd_filter = dce110_program_hpd_filter, }; +static const struct link_encoder_funcs dce110_lnk_enc_funcs_no_hpd = { + .validate_output_with_stream = + dce110_link_encoder_validate_output_with_stream, + .hw_init = dce110_link_encoder_hw_init, + .setup = dce110_link_encoder_setup, + .enable_tmds_output = dce110_link_encoder_enable_tmds_output, + .enable_dp_output = dce110_link_encoder_enable_dp_output, + .enable_dp_mst_output = dce110_link_encoder_enable_dp_mst_output, + .enable_lvds_output = dce110_link_encoder_enable_lvds_output, + .enable_analog_output = dce110_link_encoder_enable_analog_output, + .disable_output = dce110_link_encoder_disable_output, + .dp_set_lane_settings = dce110_link_encoder_dp_set_lane_settings, + .dp_set_phy_pattern = dce110_link_encoder_dp_set_phy_pattern, + .update_mst_stream_allocation_table = + dce110_link_encoder_update_mst_stream_allocation_table, + .psr_program_dp_dphy_fast_training = + dce110_psr_program_dp_dphy_fast_training, + .psr_program_secondary_packet = dce110_psr_program_secondary_packet, + .connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe, + .is_dig_enabled = dce110_is_dig_enabled, + .destroy = dce110_link_encoder_destroy, + .get_max_link_cap = dce110_link_encoder_get_max_link_cap, + .get_dig_frontend = dce110_get_dig_frontend, + .get_hpd_state = dce110_get_hpd_state, + .program_hpd_filter = dce110_program_hpd_filter, +}; + static enum bp_result link_transmitter_control( struct dce110_link_encoder *enc110, struct bp_transmitter_control *cntl) @@ -820,6 +847,7 @@ bool dce110_link_encoder_validate_dp_output( const struct dce110_link_encoder *enc110, const struct dc_crtc_timing *crtc_timing) { + (void)enc110; if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) return false; @@ -865,7 +893,10 @@ void dce110_link_encoder_construct( const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs; enum bp_result result = BP_RESULT_OK; - enc110->base.funcs = &dce110_lnk_enc_funcs; + if (hpd_regs) + enc110->base.funcs = &dce110_lnk_enc_funcs; + else + enc110->base.funcs = &dce110_lnk_enc_funcs_no_hpd; enc110->base.ctx = init_data->ctx; enc110->base.id = init_data->encoder; enc110->base.analog_id = init_data->analog_encoder; @@ -1855,6 +1886,33 @@ static const struct link_encoder_funcs dce60_lnk_enc_funcs = { .program_hpd_filter = dce110_program_hpd_filter, }; +static const struct link_encoder_funcs dce60_lnk_enc_funcs_no_hpd = { + .validate_output_with_stream = + dce110_link_encoder_validate_output_with_stream, + .hw_init = dce110_link_encoder_hw_init, + .setup = dce110_link_encoder_setup, + .enable_tmds_output = dce110_link_encoder_enable_tmds_output, + .enable_dp_output = dce60_link_encoder_enable_dp_output, + .enable_dp_mst_output = dce60_link_encoder_enable_dp_mst_output, + .enable_lvds_output = dce110_link_encoder_enable_lvds_output, + .enable_analog_output = dce110_link_encoder_enable_analog_output, + .disable_output = dce110_link_encoder_disable_output, + .dp_set_lane_settings = dce110_link_encoder_dp_set_lane_settings, + .dp_set_phy_pattern = dce60_link_encoder_dp_set_phy_pattern, + .update_mst_stream_allocation_table = + dce110_link_encoder_update_mst_stream_allocation_table, + .psr_program_dp_dphy_fast_training = + dce110_psr_program_dp_dphy_fast_training, + .psr_program_secondary_packet = dce110_psr_program_secondary_packet, + .connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe, + .is_dig_enabled = dce110_is_dig_enabled, + .destroy = dce110_link_encoder_destroy, + .get_max_link_cap = dce110_link_encoder_get_max_link_cap, + .get_dig_frontend = dce110_get_dig_frontend, + .get_hpd_state = dce110_get_hpd_state, + .program_hpd_filter = dce110_program_hpd_filter, +}; + void dce60_link_encoder_construct( struct dce110_link_encoder *enc110, const struct encoder_init_data *init_data, @@ -1867,7 +1925,10 @@ void dce60_link_encoder_construct( const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs; enum bp_result result = BP_RESULT_OK; - enc110->base.funcs = &dce60_lnk_enc_funcs; + if (hpd_regs) + enc110->base.funcs = &dce60_lnk_enc_funcs; + else + enc110->base.funcs = &dce60_lnk_enc_funcs_no_hpd; enc110->base.ctx = init_data->ctx; enc110->base.id = init_data->encoder; enc110->base.analog_id = init_data->analog_encoder; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index 1c2009e38aa1..168c2d0a5eaa 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -317,6 +317,7 @@ static void dce_mi_program_display_marks( struct dce_watermarks urgent, uint32_t total_dest_line_time_ns) { + (void)stutter_enter; struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1; @@ -370,6 +371,7 @@ static void dce112_mi_program_display_marks(struct mem_input *mi, struct dce_watermarks urgent, uint32_t total_dest_line_time_ns) { + (void)stutter_entry; struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1; @@ -656,6 +658,8 @@ static void dce_mi_program_surface_config( struct dc_plane_dcc_param *dcc, bool horizontal_mirror) { + (void)dcc; + (void)horizontal_mirror; struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); REG_UPDATE(GRPH_ENABLE, GRPH_ENABLE, 1); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c index f342da5a5e50..61d478cfca6d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c @@ -600,6 +600,7 @@ void dce110_opp_set_dyn_expansion( enum dc_color_depth color_dpth, enum signal_type signal) { + (void)color_sp; struct dce110_opp *opp110 = TO_DCE110_OPP(opp); REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index 87c19f17c799..ed407e779c12 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -271,6 +271,8 @@ static void dce110_stream_encoder_dp_set_stream_attribute( bool use_vsc_sdp_for_colorimetry, uint32_t enable_sdp_splitting) { + (void)use_vsc_sdp_for_colorimetry; + (void)enable_sdp_splitting; uint32_t h_active_start; uint32_t v_active_start; uint32_t misc0 = 0; @@ -901,6 +903,7 @@ static void dce110_stream_encoder_dp_blank( struct dc_link *link, struct stream_encoder *enc) { + (void)link; struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); uint32_t reg1 = 0; uint32_t max_retries = DP_BLANK_MAX_RETRY * 10; @@ -951,6 +954,7 @@ static void dce110_stream_encoder_dp_unblank( struct stream_encoder *enc, const struct encoder_unblank_param *param) { + (void)link; struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); if (param->link_settings.link_rate != LINK_RATE_UNKNOWN) { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c index 1ab5ae9b5ea5..c1448ae47366 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c @@ -282,6 +282,7 @@ static void calculate_inits( const struct scaler_data *data, struct scl_ratios_inits *inits) { + (void)xfm_dce; struct fixed31_32 h_init; struct fixed31_32 v_init; @@ -1240,6 +1241,7 @@ static void program_color_matrix( const struct out_csc_color_matrix *tbl_entry, enum grph_color_adjust_option options) { + (void)options; { REG_SET_2(OUTPUT_CSC_C11_C12, 0, OUTPUT_CSC_C11, tbl_entry->regval[0], diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c index b686d89b79b2..93550c5e4d02 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c @@ -41,8 +41,7 @@ static unsigned int abm_feature_support(struct abm *abm, unsigned int panel_inst { struct dc_context *dc = abm->ctx; struct dc_link *edp_links[MAX_NUM_EDP]; - int i; - int edp_num; + unsigned int i, edp_num; unsigned int ret = ABM_FEATURE_NO_SUPPORT; dc_get_edp_links(dc->dc, edp_links, &edp_num); @@ -174,6 +173,7 @@ static bool dmub_abm_set_backlight_level_pwm_ex(struct abm *abm, unsigned int controller_id, unsigned int panel_inst) { + (void)controller_id; bool ret = false; unsigned int feature_support; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.c index a641ae04450c..806b5709c9e7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.c @@ -188,6 +188,7 @@ void dmub_abm_init_config(struct abm *abm, bool dmub_abm_set_pause(struct abm *abm, bool pause, unsigned int panel_inst, unsigned int stream_inst) { + (void)stream_inst; union dmub_rb_cmd cmd; struct dc_context *dc = abm->ctx; uint8_t panel_mask = 0x01 << panel_inst; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c index 7116fdd4c7ec..52673e2f504c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c @@ -28,6 +28,14 @@ #include "dc_types.h" #include "core_types.h" +static bool dmub_hw_lock_has_inbox0_lock(const struct dc *dc) +{ + return dc->ctx && dc->ctx->dmub_srv && + dc->hwss.dmub_hw_control_lock && + dc->hwss.dmub_hw_control_lock_fast && + dc->ctx->dmub_srv->dmub->meta_info.feature_bits.bits.inbox0_lock_support; +} + void dmub_hw_lock_mgr_cmd(struct dc_dmub_srv *dmub_srv, bool lock, union dmub_hw_lock_flags *hw_locks, @@ -74,7 +82,7 @@ bool dmub_hw_lock_mgr_does_link_require_lock(const struct dc *dc, const struct d if (link->psr_settings.psr_version == DC_PSR_VERSION_1) { struct dc_link *edp_links[MAX_NUM_EDP]; - int edp_num; + unsigned int edp_num; dc_get_edp_links(dc, edp_links, &edp_num); if (edp_num == 1) @@ -105,5 +113,13 @@ bool should_use_dmub_inbox1_lock(const struct dc *dc, const struct dc_link *link if (dc->ctx->dce_version >= DCN_VERSION_4_01) return false; + if (dmub_hw_lock_has_inbox0_lock(dc)) + return false; + return dmub_hw_lock_mgr_does_link_require_lock(dc, link); } + +bool should_use_dmub_inbox0_lock_for_link(const struct dc *dc, const struct dc_link *link) +{ + return dmub_hw_lock_has_inbox0_lock(dc) && dmub_hw_lock_mgr_does_link_require_lock(dc, link); +} diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.h b/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.h index 4c80ca8484ad..3e8caa930390 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.h @@ -46,7 +46,38 @@ void dmub_hw_lock_mgr_inbox0_cmd(struct dc_dmub_srv *dmub_srv, * Return: true if the inbox1 lock should be used, false otherwise */ bool should_use_dmub_inbox1_lock(const struct dc *dc, const struct dc_link *link); + +/** + * dmub_hw_lock_mgr_does_link_require_lock() - Returns true if the link has a feature that needs the HW lock. + * + * @dc: Pointer to DC object + * @link: The link to check + * + * Return: true if the link has a feature that needs the HW lock, false otherwise + */ bool dmub_hw_lock_mgr_does_link_require_lock(const struct dc *dc, const struct dc_link *link); + +/** + * dmub_hw_lock_mgr_does_context_require_lock() - Returns true if the context has any stream that needs the HW lock. + * + * @dc: Pointer to DC object + * @context: The context to check + * + * Return: true if the context has any stream that needs the HW lock, false otherwise + */ bool dmub_hw_lock_mgr_does_context_require_lock(const struct dc *dc, const struct dc_state *context); +/** + * should_use_dmub_inbox0_lock_for_link() - Checks if the inbox0 interlock with DMU should be used. + * + * Is not functionally equivalent to inbox1 as DMUB will not own programming of the relevant locking + * registers. + * + * @dc: pointer to DC object + * @link: optional pointer to the link object to check for enabled link features + * + * Return: true if the inbox0 lock should be used, false otherwise + */ +bool should_use_dmub_inbox0_lock_for_link(const struct dc *dc, const struct dc_link *link); + #endif /*_DMUB_HW_LOCK_MGR_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c index 28a218149b8b..0af1b8e0a49e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c @@ -216,6 +216,7 @@ static void dmub_replay_set_coasting_vtotal(struct dmub_replay *dmub, uint8_t panel_inst, uint16_t frame_skip_number) { + (void)panel_inst; union dmub_rb_cmd cmd; struct dc_context *dc = dmub->ctx; struct dmub_rb_cmd_replay_set_coasting_vtotal *pCmd = NULL; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c index 2c43c2422638..b265a72eeb70 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c @@ -40,6 +40,7 @@ static void set_flip_control( struct dce_mem_input *mem_input110, bool immediate) { + (void)immediate; uint32_t value = 0; value = dm_read_reg( @@ -165,6 +166,7 @@ static void program_tiling( const struct dc_tiling_info *info, const enum surface_pixel_format pixel_format) { + (void)pixel_format; uint32_t value = 0; set_reg_field_value(value, info->gfx8.num_banks, @@ -642,6 +644,8 @@ static void dce_mem_input_v_program_surface_config( struct dc_plane_dcc_param *dcc, bool horizotal_mirror) { + (void)dcc; + (void)horizotal_mirror; struct dce_mem_input *mem_input110 = TO_DCE_MEM_INPUT(mem_input); enable(mem_input110); @@ -927,6 +931,7 @@ static void dce_mem_input_v_program_display_marks( struct dce_watermarks urgent, uint32_t total_dest_line_time_ns) { + (void)stutter_enter; program_urgency_watermark_l( mem_input->ctx, urgent, @@ -970,6 +975,9 @@ static void dce110_allocate_mem_input_v( uint32_t pix_clk_khz,/* for current stream */ uint32_t total_stream_num) { + (void)h_total; + (void)v_total; + (void)total_stream_num; uint32_t addr; uint32_t value; uint32_t pix_dur; @@ -1009,6 +1017,8 @@ static void dce110_free_mem_input_v( struct mem_input *mi, uint32_t total_stream_num) { + (void)mi; + (void)total_stream_num; } static const struct mem_input_funcs dce110_mem_input_v_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c index e096d2b95ef9..cf63fac82832 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c @@ -110,6 +110,7 @@ static void program_color_matrix_v( const struct out_csc_color_matrix *tbl_entry, enum grph_color_adjust_option options) { + (void)options; struct dc_context *ctx = xfm_dce->base.ctx; uint32_t cntl_value = dm_read_reg(ctx, mmCOL_MAN_OUTPUT_CSC_CONTROL); bool use_set_a = (get_reg_field_value(cntl_value, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c index 9b65b77e8823..a4e76db46c9c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c @@ -551,5 +551,7 @@ void dce110_opp_set_regamma_mode_v( struct transform *xfm, enum opp_regamma mode) { + (void)xfm; + (void)mode; // TODO: need to implement the function } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c index 61b0807693fb..b015b27cd1c6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c @@ -66,6 +66,7 @@ static void dce110_timing_generator_apply_front_porch_workaround( struct timing_generator *tg, struct dc_crtc_timing *timing) { + (void)tg; if (timing->flags.INTERLACE == 1) { if (timing->v_front_porch < 2) timing->v_front_porch = 2; @@ -1115,6 +1116,7 @@ bool dce110_timing_generator_validate_timing( const struct dc_crtc_timing *timing, enum signal_type signal) { + (void)signal; uint32_t h_blank; uint32_t h_back_porch, hsync_offset, h_sync_start; @@ -1490,6 +1492,7 @@ void dce110_timing_generator_enable_reset_trigger( struct timing_generator *tg, int source_tg_inst) { + (void)source_tg_inst; uint32_t value; uint32_t rising_edge = 0; uint32_t falling_edge = 0; @@ -1959,6 +1962,12 @@ void dce110_tg_program_timing(struct timing_generator *tg, const enum signal_type signal, bool use_vbios) { + (void)vready_offset; + (void)vstartup_start; + (void)vupdate_offset; + (void)vupdate_width; + (void)pstate_keepout; + (void)signal; if (use_vbios) dce110_timing_generator_program_timing_generator(tg, timing); else diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c index 9837dec837ff..ba22c93acd81 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c @@ -442,6 +442,12 @@ static void dce110_timing_generator_v_program_timing(struct timing_generator *tg const enum signal_type signal, bool use_vbios) { + (void)vready_offset; + (void)vstartup_start; + (void)vupdate_offset; + (void)vupdate_width; + (void)pstate_keepout; + (void)signal; if (use_vbios) dce110_timing_generator_program_timing_generator(tg, timing); else @@ -621,6 +627,7 @@ static void dce110_timing_generator_v_setup_global_swap_lock( struct timing_generator *tg, const struct dcp_gsl_params *gsl_params) { + (void)gsl_params; DC_LOG_ERROR("Timing Sync not supported on underlay pipe\n"); return; } @@ -629,6 +636,7 @@ static void dce110_timing_generator_v_enable_reset_trigger( struct timing_generator *tg, int source_tg_inst) { + (void)source_tg_inst; DC_LOG_ERROR("Timing Sync not supported on underlay pipe\n"); return; } @@ -650,6 +658,7 @@ static void dce110_timing_generator_v_tear_down_global_swap_lock( static void dce110_timing_generator_v_disable_vga( struct timing_generator *tg) { + (void)tg; return; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c index 28d3b2663cd3..6be18665b1f7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c @@ -371,6 +371,9 @@ static void calculate_inits( struct rect *luma_viewport, struct rect *chroma_viewport) { + (void)xfm_dce; + (void)luma_viewport; + (void)chroma_viewport; inits->h_int_scale_ratio_luma = dc_fixpt_u2d19(data->ratios.horz) << 5; inits->v_int_scale_ratio_luma = @@ -619,6 +622,8 @@ static void dce110_xfmv_set_gamut_remap( struct transform *xfm, const struct xfm_grph_csc_adjustment *adjust) { + (void)xfm; + (void)adjust; /* DO NOTHING*/ } @@ -627,6 +632,7 @@ static void dce110_xfmv_set_pixel_storage_depth( enum lb_pixel_depth depth, const struct bit_depth_reduction_params *bit_depth_params) { + (void)bit_depth_params; struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); int pixel_depth = 0; int expan_mode = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c index 187f45a7f5e1..fe97d3946cab 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c @@ -284,6 +284,7 @@ static uint32_t align_to_chunks_number_per_line( struct dce112_compressor *cp110, uint32_t pixels) { + (void)cp110; return 256 * ((pixels + 255) / 256); } diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index 31c4f44ceaac..70410ef0c291 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -304,6 +304,7 @@ static void dce120_timing_generator_enable_reset_trigger( struct timing_generator *tg, int source) { + (void)source; enum trigger_source_select trig_src_select = TRIGGER_SOURCE_SELECT_LOGIC_ZERO; struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); uint32_t rising_edge = 0; @@ -701,6 +702,12 @@ static void dce120_tg_program_timing(struct timing_generator *tg, const enum signal_type signal, bool use_vbios) { + (void)vready_offset; + (void)vstartup_start; + (void)vupdate_offset; + (void)vupdate_width; + (void)pstate_keepout; + (void)signal; if (use_vbios) dce110_timing_generator_program_timing_generator(tg, timing); else diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c index 88e7a1fc9a30..53c03364f5d4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c @@ -115,6 +115,12 @@ static void dce80_timing_generator_program_timing(struct timing_generator *tg, const enum signal_type signal, bool use_vbios) { + (void)vready_offset; + (void)vstartup_start; + (void)vupdate_offset; + (void)vupdate_width; + (void)pstate_keepout; + (void)signal; if (!use_vbios) program_pix_dur(tg, timing->pix_clk_100hz); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c index dcd2cdfe91eb..c702a30563f9 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c @@ -381,10 +381,10 @@ bool cm_helper_translate_curve_to_hw_format(struct dc_context *ctx, } for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++) - seg_distr[i] = -1; + seg_distr[i] = (uint32_t)-1; for (k = 0; k < MAX_REGIONS_NUMBER; k++) { - if (seg_distr[k] != -1) + if (seg_distr[k] != (uint32_t)-1) hw_points += (1 << seg_distr[k]); } @@ -565,7 +565,7 @@ bool cm_helper_translate_curve_to_degamma_hw_format( for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++) - seg_distr[i] = -1; + seg_distr[i] = (uint32_t)-1; /* 12 segments * segments are from 2^-12 to 0 */ @@ -573,7 +573,7 @@ bool cm_helper_translate_curve_to_degamma_hw_format( seg_distr[i] = 4; for (k = 0; k < MAX_REGIONS_NUMBER; k++) { - if (seg_distr[k] != -1) + if (seg_distr[k] != (uint32_t)-1) hw_points += (1 << seg_distr[k]); } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c index 365a3215f6d5..e9efbb49586e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c @@ -44,6 +44,7 @@ static bool dwb1_get_caps(struct dwbc *dwbc, struct dwb_caps *caps) { + (void)dwbc; if (caps) { caps->adapter_id = 0; /* we only support 1 adapter currently */ caps->hw_version = DCN_VERSION_1_0; @@ -63,6 +64,7 @@ static bool dwb1_get_caps(struct dwbc *dwbc, struct dwb_caps *caps) static bool dwb1_enable(struct dwbc *dwbc, struct dc_dwb_params *params) { + (void)params; struct dcn10_dwbc *dwbc10 = TO_DCN10_DWBC(dwbc); /* disable first. */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dwb_scl.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dwb_scl.c index a0d437f0ce2b..f73c5f42ea68 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dwb_scl.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dwb_scl.c @@ -746,7 +746,7 @@ bool dwb_program_horz_scalar(struct dcn20_dwbc *dwbc20, src_width, dest_width); if (dc_fixpt_floor(tmp_h_ratio_luma) == 8) - h_ratio_luma = -1; + h_ratio_luma = (uint32_t)-1; else h_ratio_luma = dc_fixpt_u3d19(tmp_h_ratio_luma) << 5; @@ -824,7 +824,7 @@ bool dwb_program_vert_scalar(struct dcn20_dwbc *dwbc20, src_height, dest_height); if (dc_fixpt_floor(tmp_v_ratio_luma) == 8) - v_ratio_luma = -1; + v_ratio_luma = (uint32_t)-1; else v_ratio_luma = dc_fixpt_u3d19(tmp_v_ratio_luma) << 5; diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c index 227aa8672d17..9dbccf58dde5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c @@ -159,10 +159,10 @@ bool cm3_helper_translate_curve_to_hw_format(struct dc_context *ctx, } for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++) - seg_distr[i] = -1; + seg_distr[i] = (uint32_t)-1; for (k = 0; k < MAX_REGIONS_NUMBER; k++) { - if (seg_distr[k] != -1) + if (seg_distr[k] != (uint32_t)-1) hw_points += (1 << seg_distr[k]); } diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c index 05aac3e444b4..4c7e4fe3c680 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c @@ -77,6 +77,7 @@ static void apg31_se_audio_setup( unsigned int az_inst, struct audio_info *audio_info) { + (void)az_inst; struct dcn31_apg *apg31 = DCN31_APG_FROM_APG(apg); ASSERT(audio_info); diff --git a/drivers/gpu/drm/amd/display/dc/dio/Makefile b/drivers/gpu/drm/amd/display/dc/dio/Makefile index 2f5619078e1f..4832533b9514 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dio/Makefile @@ -1,5 +1,5 @@ # -# Copyright 2020 Advanced Micro Devices, Inc. +# Copyright 2020-2026 Advanced Micro Devices, Inc. # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), @@ -123,4 +123,13 @@ DIO_DCN401 = dcn401_dio_link_encoder.o dcn401_dio_stream_encoder.o AMD_DAL_DIO_DCN401 = $(addprefix $(AMDDALPATH)/dc/dio/dcn401/,$(DIO_DCN401)) AMD_DISPLAY_FILES += $(AMD_DAL_DIO_DCN401) + +############################################################################### +# DCN42 +############################################################################### +DIO_DCN42 = dcn42_dio_link_encoder.o dcn42_dio_stream_encoder.o + +AMD_DAL_DIO_DCN42 = $(addprefix $(AMDDALPATH)/dc/dio/dcn42/,$(DIO_DCN42)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DIO_DCN42) endif diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c index d928b4dcf6b8..d913f065ecca 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c @@ -249,6 +249,7 @@ void enc1_stream_encoder_dp_set_stream_attribute( bool use_vsc_sdp_for_colorimetry, uint32_t enable_sdp_splitting) { + (void)enable_sdp_splitting; uint32_t h_active_start; uint32_t v_active_start; uint32_t misc0 = 0; @@ -783,6 +784,7 @@ void enc1_stream_encoder_send_immediate_sdp_message( const uint8_t *custom_sdp_message, unsigned int sdp_message_size) { + (void)sdp_message_size; struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); uint32_t value = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.h index 54a6a4ebd636..755367506556 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.h @@ -1,5 +1,5 @@ /* - * Copyright 2012-15 Advanced Micro Devices, Inc. + * Copyright 2012-2026 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -190,6 +190,7 @@ struct dcn10_stream_enc_registers { uint32_t DIG_FE_CLK_CNTL; uint32_t DIG_FE_EN_CNTL; uint32_t STREAM_MAPPER_CONTROL; + uint32_t DIG_FE_AUDIO_CNTL; }; @@ -598,6 +599,11 @@ struct dcn10_stream_enc_registers { type DP_VID_N_INTERVAL;\ type DIG_FIFO_OUTPUT_PIXEL_PER_CYCLE;\ type DP_STEER_FIFO_ENABLE + +#define SE_REG_FIELD_LIST_DCN_AUDIO_COMMON(type) \ + type DIG_FE_INPUT_MUX_AUDIO_STREAM_SOURCE_SEL;\ + type APG_CLOCK_ENABLE + struct dcn10_stream_encoder_shift { SE_REG_FIELD_LIST_DCN1_0(uint8_t); uint8_t HDMI_ACP_SEND; @@ -606,6 +612,7 @@ struct dcn10_stream_encoder_shift { SE_REG_FIELD_LIST_DCN3_1_COMMON(uint8_t); SE_REG_FIELD_LIST_DCN3_5_COMMON(uint8_t); SE_REG_FIELD_LIST_DCN4_01_COMMON(uint32_t); + SE_REG_FIELD_LIST_DCN_AUDIO_COMMON(uint32_t); }; struct dcn10_stream_encoder_mask { @@ -616,6 +623,7 @@ struct dcn10_stream_encoder_mask { SE_REG_FIELD_LIST_DCN3_1_COMMON(uint32_t); SE_REG_FIELD_LIST_DCN3_5_COMMON(uint32_t); SE_REG_FIELD_LIST_DCN4_01_COMMON(uint32_t); + SE_REG_FIELD_LIST_DCN_AUDIO_COMMON(uint32_t); }; struct dcn10_stream_encoder { diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn314/dcn314_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn314/dcn314_dio_stream_encoder.c index 3e85e9c3d2cb..d1fd5462dca5 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn314/dcn314_dio_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn314/dcn314_dio_stream_encoder.c @@ -394,6 +394,8 @@ void enc314_dp_set_dsc_config(struct stream_encoder *enc, uint32_t dsc_bytes_per_pixel, uint32_t dsc_slice_width) { + (void)dsc_bytes_per_pixel; + (void)dsc_slice_width; struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); REG_UPDATE(DP_DSC_CNTL, DP_DSC_MODE, dsc_mode == OPTC_DSC_DISABLED ? 0 : 1); diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_stream_encoder.c index 3523d1cdc1a3..edafa3808455 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_stream_encoder.c @@ -356,6 +356,8 @@ static void enc32_dp_set_dsc_config(struct stream_encoder *enc, uint32_t dsc_bytes_per_pixel, uint32_t dsc_slice_width) { + (void)dsc_bytes_per_pixel; + (void)dsc_slice_width; struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); REG_UPDATE(DP_DSC_CNTL, DP_DSC_MODE, dsc_mode == OPTC_DSC_DISABLED ? 0 : 1); diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_stream_encoder.c index fd5d1dbf9dc6..de24dcd27e6c 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_stream_encoder.c @@ -369,6 +369,7 @@ static void enc35_stream_encoder_map_to_link( uint32_t stream_enc_inst, uint32_t link_enc_inst) { + (void)stream_enc_inst; struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); ASSERT(stream_enc_inst < 5 && link_enc_inst < 5); diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c index 99aab70ef3e1..2d33ed0c062d 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c @@ -57,6 +57,8 @@ static void enc401_dp_set_odm_combine( struct stream_encoder *enc, bool odm_combine) { + (void)enc; + (void)odm_combine; } /* setup stream encoder in dvi mode */ @@ -710,6 +712,7 @@ void enc401_stream_encoder_map_to_link( uint32_t stream_enc_inst, uint32_t link_enc_inst) { + (void)stream_enc_inst; struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); REG_UPDATE(STREAM_MAPPER_CONTROL, diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_link_encoder.c new file mode 100644 index 000000000000..35dfe3bb0c55 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_link_encoder.c @@ -0,0 +1,205 @@ +// SPDX-License-Identifier: MIT +// +// Copyright 2026 Advanced Micro Devices, Inc. + +#include "reg_helper.h" + +#include "core_types.h" +#include "link_encoder.h" +#include "dcn35/dcn35_dio_link_encoder.h" +#include "dcn42_dio_link_encoder.h" + +#ifndef MIN +#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) +#endif + +#define CTX \ + enc10->base.ctx +#define DC_LOGGER \ + enc10->base.ctx->logger + +#define REG(reg)\ + (enc10->link_regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + enc10->link_shift->field_name, enc10->link_mask->field_name + +#define HPD_REG(reg)\ + (enc10->hpd_regs->reg) + +#define HPD_REG_GET(reg_name, field, val) \ + generic_reg_get(CTX, HPD_REG(reg_name), \ + FN(reg_name, field), val) + +#define HPD_REG_SET_N(reg_name, n, initial_val, ...) \ + generic_reg_set_ex(CTX, \ + HPD_REG(reg_name), \ + initial_val, \ + n, __VA_ARGS__) + +#define HPD_REG_SET_2(reg, init_value, f1, v1, f2, v2) \ + HPD_REG_SET_N(reg, 2, init_value, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2) + +bool dcn42_get_hpd_state(struct link_encoder *enc) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + uint32_t state; + + HPD_REG_GET(DC_HPD_INT_STATUS, DC_HPD_SENSE, &state); + + return state; +} + +bool dcn42_program_hpd_filter(struct link_encoder *enc, int delay_on_connect_in_ms, int delay_on_disconnect_in_ms) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + + HPD_REG_SET_2(DC_HPD_TOGGLE_FILT_CNTL, 0, + DC_HPD_CONNECT_INT_DELAY, delay_on_connect_in_ms, + DC_HPD_DISCONNECT_INT_DELAY, delay_on_disconnect_in_ms); + + return true; +} + +static const struct link_encoder_funcs dcn42_link_enc_funcs = { + .read_state = link_enc2_read_state, + .validate_output_with_stream = + dcn30_link_encoder_validate_output_with_stream, + .hw_init = dcn35_link_encoder_init, + .setup = dcn35_link_encoder_setup, + .enable_tmds_output = dcn10_link_encoder_enable_tmds_output, + .enable_dp_output = dcn35_link_encoder_enable_dp_output, + .enable_dp_mst_output = dcn35_link_encoder_enable_dp_mst_output, + .disable_output = dcn35_link_encoder_disable_output, + .dp_set_lane_settings = dcn10_link_encoder_dp_set_lane_settings, + .dp_set_phy_pattern = dcn10_link_encoder_dp_set_phy_pattern, + .update_mst_stream_allocation_table = + dcn10_link_encoder_update_mst_stream_allocation_table, + .psr_program_dp_dphy_fast_training = + dcn10_psr_program_dp_dphy_fast_training, + .psr_program_secondary_packet = dcn10_psr_program_secondary_packet, + .connect_dig_be_to_fe = dcn10_link_encoder_connect_dig_be_to_fe, + .enable_hpd = dcn10_link_encoder_enable_hpd, + .disable_hpd = dcn10_link_encoder_disable_hpd, + .is_dig_enabled = dcn35_is_dig_enabled, + .destroy = dcn10_link_encoder_destroy, + .fec_set_enable = enc2_fec_set_enable, + .fec_set_ready = enc2_fec_set_ready, + .fec_is_active = enc2_fec_is_active, + .get_dig_frontend = dcn10_get_dig_frontend, + .get_dig_mode = dcn401_get_dig_mode, + .is_in_alt_mode = dcn32_link_encoder_is_in_alt_mode, + .get_max_link_cap = dcn32_link_encoder_get_max_link_cap, + .set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux, + .enable_dpia_output = dcn35_link_encoder_enable_dpia_output, + .disable_dpia_output = dcn35_link_encoder_disable_dpia_output, + .get_hpd_state = dcn42_get_hpd_state, + .program_hpd_filter = dcn42_program_hpd_filter, +}; + +void dcn42_link_encoder_construct( + struct dcn20_link_encoder *enc20, + const struct encoder_init_data *init_data, + const struct encoder_feature_support *enc_features, + const struct dcn10_link_enc_registers *link_regs, + const struct dcn10_link_enc_aux_registers *aux_regs, + const struct dcn10_link_enc_hpd_registers *hpd_regs, + const struct dcn10_link_enc_shift *link_shift, + const struct dcn10_link_enc_mask *link_mask) +{ + struct bp_connector_speed_cap_info bp_cap_info = {0}; + const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs; + enum bp_result result = BP_RESULT_OK; + struct dcn10_link_encoder *enc10 = &enc20->enc10; + + enc10->base.funcs = &dcn42_link_enc_funcs; + enc10->base.ctx = init_data->ctx; + enc10->base.id = init_data->encoder; + + enc10->base.hpd_source = init_data->hpd_source; + enc10->base.connector = init_data->connector; + + + enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; + + enc10->base.features = *enc_features; + if (enc10->base.connector.id == CONNECTOR_ID_USBC) + enc10->base.features.flags.bits.DP_IS_USB_C = 1; + + enc10->base.transmitter = init_data->transmitter; + + /* set the flag to indicate whether driver poll the I2C data pin + * while doing the DP sink detect + */ + +/* if (dal_adapter_service_is_feature_supported(as, + FEATURE_DP_SINK_DETECT_POLL_DATA_PIN)) + enc10->base.features.flags.bits. + DP_SINK_DETECT_POLL_DATA_PIN = true;*/ + + enc10->base.output_signals = + SIGNAL_TYPE_DVI_SINGLE_LINK | + SIGNAL_TYPE_DVI_DUAL_LINK | + SIGNAL_TYPE_LVDS | + SIGNAL_TYPE_DISPLAY_PORT | + SIGNAL_TYPE_DISPLAY_PORT_MST | + SIGNAL_TYPE_EDP | + SIGNAL_TYPE_HDMI_TYPE_A; + + enc10->link_regs = link_regs; + enc10->aux_regs = aux_regs; + enc10->hpd_regs = hpd_regs; + enc10->link_shift = link_shift; + enc10->link_mask = link_mask; + + switch (enc10->base.transmitter) { + case TRANSMITTER_UNIPHY_A: + enc10->base.preferred_engine = ENGINE_ID_DIGA; + break; + case TRANSMITTER_UNIPHY_B: + enc10->base.preferred_engine = ENGINE_ID_DIGB; + break; + case TRANSMITTER_UNIPHY_C: + enc10->base.preferred_engine = ENGINE_ID_DIGC; + break; + case TRANSMITTER_UNIPHY_D: + enc10->base.preferred_engine = ENGINE_ID_DIGD; + break; + case TRANSMITTER_UNIPHY_E: + enc10->base.preferred_engine = ENGINE_ID_DIGE; + break; + default: + ASSERT_CRITICAL(false); + enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; + } + + /* default to one to mirror Windows behavior */ + enc10->base.features.flags.bits.HDMI_6GB_EN = 1; + + if (bp_funcs->get_connector_speed_cap_info) + result = bp_funcs->get_connector_speed_cap_info(enc10->base.ctx->dc_bios, + enc10->base.connector, &bp_cap_info); + + /* Override features with DCE-specific values */ + if (result == BP_RESULT_OK) { + enc10->base.features.flags.bits.IS_HBR2_CAPABLE = + bp_cap_info.DP_HBR2_EN; + enc10->base.features.flags.bits.IS_HBR3_CAPABLE = + bp_cap_info.DP_HBR3_EN; + enc10->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; + enc10->base.features.flags.bits.IS_DP2_CAPABLE = 1; + enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN; + enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN; + enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN; + } else { + DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", + __func__, + result); + } + if (enc10->base.ctx->dc->debug.hdmi20_disable) { + enc10->base.features.flags.bits.HDMI_6GB_EN = 0; + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_link_encoder.h new file mode 100644 index 000000000000..4b5a9594f279 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_link_encoder.h @@ -0,0 +1,140 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2026 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef __DC_LINK_ENCODER__DCN42_H__ +#define __DC_LINK_ENCODER__DCN42_H__ + +#include "dcn401/dcn401_dio_link_encoder.h" + +#define LINK_ENCODER_MASK_SH_LIST_DCN42(mask_sh) \ + LE_SF(DIG0_DIG_BE_EN_CNTL, DIG_BE_ENABLE, mask_sh),\ + LE_SF(DIG0_DIG_BE_CNTL, DIG_RB_SWITCH_EN, mask_sh),\ + LE_SF(DIG0_DIG_BE_CNTL, DIG_HPD_SELECT, mask_sh),\ + LE_SF(DIG0_DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, mask_sh),\ + LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_MODE, mask_sh),\ + LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_CLK_EN, mask_sh),\ + LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_SOFT_RESET, mask_sh),\ + LE_SF(DIG0_DIG_BE_CLK_CNTL, HDCP_SOFT_RESET, mask_sh),\ + LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_SYMCLK_G_CLOCK_ON, mask_sh),\ + LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_SYMCLK_G_HDCP_CLOCK_ON, mask_sh),\ + LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_SYMCLK_G_TMDS_CLOCK_ON, mask_sh),\ + LE_SF(DIG0_DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, mask_sh),\ + LE_SF(DIG0_TMDS_CTL_BITS, TMDS_CTL0, mask_sh), \ + LE_SF(DP0_DP_DPHY_CNTL, DPHY_BYPASS, mask_sh),\ + LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE0, mask_sh),\ + LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE1, mask_sh),\ + LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE2, mask_sh),\ + LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE3, mask_sh),\ + LE_SF(DP0_DP_DPHY_PRBS_CNTL, DPHY_PRBS_EN, mask_sh),\ + LE_SF(DP0_DP_DPHY_PRBS_CNTL, DPHY_PRBS_SEL, mask_sh),\ + LE_SF(DP0_DP_DPHY_SYM0, DPHY_SYM1, mask_sh),\ + LE_SF(DP0_DP_DPHY_SYM0, DPHY_SYM2, mask_sh),\ + LE_SF(DP0_DP_DPHY_SYM0, DPHY_SYM3, mask_sh),\ + LE_SF(DP0_DP_DPHY_SYM1, DPHY_SYM4, mask_sh),\ + LE_SF(DP0_DP_DPHY_SYM1, DPHY_SYM5, mask_sh),\ + LE_SF(DP0_DP_DPHY_SYM1, DPHY_SYM6, mask_sh),\ + LE_SF(DP0_DP_DPHY_SYM2, DPHY_SYM7, mask_sh),\ + LE_SF(DP0_DP_DPHY_SYM2, DPHY_SYM8, mask_sh),\ + LE_SF(DP0_DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, mask_sh),\ + LE_SF(DP0_DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_ADVANCE, mask_sh),\ + LE_SF(DP0_DP_DPHY_FAST_TRAINING, DPHY_RX_FAST_TRAINING_CAPABLE, mask_sh),\ + LE_SF(DP0_DP_DPHY_BS_SR_SWAP_CNTL, DPHY_LOAD_BS_COUNT, mask_sh),\ + LE_SF(DP0_DP_DPHY_TRAINING_PATTERN_SEL, DPHY_TRAINING_PATTERN_SEL, mask_sh),\ + LE_SF(DP0_DP_DPHY_HBR2_PATTERN_CONTROL, DP_DPHY_HBR2_PATTERN_CONTROL, mask_sh),\ + LE_SF(DP0_DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, mask_sh),\ + LE_SF(DP0_DP_LINK_FRAMING_CNTL, DP_IDLE_BS_INTERVAL, mask_sh),\ + LE_SF(DP0_DP_LINK_FRAMING_CNTL, DP_VBID_DISABLE, mask_sh),\ + LE_SF(DP0_DP_LINK_FRAMING_CNTL, DP_VID_ENHANCED_FRAME_MODE, mask_sh),\ + LE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, mask_sh),\ + LE_SF(DP0_DP_CONFIG, DP_UDI_LANES, mask_sh),\ + LE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP0_LINE_NUM, mask_sh),\ + LE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP0_PRIORITY, mask_sh),\ + LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SRC0, mask_sh),\ + LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SRC1, mask_sh),\ + LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SLOT_COUNT0, mask_sh),\ + LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SLOT_COUNT1, mask_sh),\ + LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SRC2, mask_sh),\ + LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SRC3, mask_sh),\ + LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SLOT_COUNT2, mask_sh),\ + LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SLOT_COUNT3, mask_sh),\ + LE_SF(DP0_DP_MSE_SAT_UPDATE, DP_MSE_SAT_UPDATE, mask_sh),\ + LE_SF(DP0_DP_MSE_SAT_UPDATE, DP_MSE_16_MTP_KEEPOUT, mask_sh),\ + LE_SF(DP_AUX0_AUX_CONTROL, AUX_HPD_SEL, mask_sh),\ + LE_SF(DP_AUX0_AUX_CONTROL, AUX_LS_READ_EN, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_RECEIVE_WINDOW, mask_sh),\ + LE_SF(HPD0_DC_HPD_CONTROL, DC_HPD_EN, mask_sh),\ + LE_SF(HPD0_DC_HPD_INT_STATUS, DC_HPD_SENSE, mask_sh),\ + LE_SF(HPD0_DC_HPD_TOGGLE_FILT_CNTL, DC_HPD_CONNECT_INT_DELAY, mask_sh),\ + LE_SF(HPD0_DC_HPD_TOGGLE_FILT_CNTL, DC_HPD_DISCONNECT_INT_DELAY, mask_sh),\ + LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_EN, mask_sh),\ + LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_READY_SHADOW, mask_sh),\ + LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_ACTIVE_STATUS, mask_sh),\ + LE_SF(DIG0_TMDS_CTL_BITS, TMDS_CTL0, mask_sh), \ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_START_WINDOW, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_HALF_SYM_DETECT_LEN, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_TRANSITION_FILTER_EN, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_START, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_STOP, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_PHASE_DETECT_LEN, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_DETECTION_THRESHOLD, mask_sh), \ + LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_TX_PRECHARGE_LEN, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_TX_PRECHARGE_SYMBOLS, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_MODE_DET_CHECK_DELAY, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_PRECHARGE_SKIP, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN_MUL, mask_sh),\ + LE_SF(DIO_CLK_CNTL, DISPCLK_R_GATE_DIS, mask_sh),\ + LE_SF(DIO_CLK_CNTL, DISPCLK_G_GATE_DIS, mask_sh),\ + LE_SF(DIO_CLK_CNTL, REFCLK_R_GATE_DIS, mask_sh),\ + LE_SF(DIO_CLK_CNTL, REFCLK_G_GATE_DIS, mask_sh),\ + LE_SF(DIO_CLK_CNTL, SOCCLK_G_GATE_DIS, mask_sh),\ + LE_SF(DIO_CLK_CNTL, SYMCLK_FE_R_GATE_DIS, mask_sh),\ + LE_SF(DIO_CLK_CNTL, SYMCLK_FE_G_GATE_DIS, mask_sh),\ + LE_SF(DIO_CLK_CNTL, SYMCLK_R_GATE_DIS, mask_sh),\ + LE_SF(DIO_CLK_CNTL, SYMCLK_G_GATE_DIS, mask_sh),\ + LE_SF(DIO_CLK_CNTL, DIO_FGCG_REP_DIS, mask_sh),\ + LE_SF(DIO_CLK_CNTL, DISPCLK_G_HDCP_GATE_DIS, mask_sh),\ + LE_SF(DIO_CLK_CNTL, SYMCLKA_G_HDCP_GATE_DIS, mask_sh),\ + LE_SF(DIO_CLK_CNTL, SYMCLKB_G_HDCP_GATE_DIS, mask_sh),\ + LE_SF(DIO_CLK_CNTL, SYMCLKC_G_HDCP_GATE_DIS, mask_sh),\ + LE_SF(DIO_CLK_CNTL, SYMCLKD_G_HDCP_GATE_DIS, mask_sh),\ + LE_SF(DIO_CLK_CNTL, SYMCLKE_G_HDCP_GATE_DIS, mask_sh),\ + LE_SF(DIO_CLK_CNTL, SYMCLKF_G_HDCP_GATE_DIS, mask_sh),\ + LE_SF(DIO_CLK_CNTL, SYMCLKG_G_HDCP_GATE_DIS, mask_sh) + +void dcn42_link_encoder_construct( + struct dcn20_link_encoder *enc20, + const struct encoder_init_data *init_data, + const struct encoder_feature_support *enc_features, + const struct dcn10_link_enc_registers *link_regs, + const struct dcn10_link_enc_aux_registers *aux_regs, + const struct dcn10_link_enc_hpd_registers *hpd_regs, + const struct dcn10_link_enc_shift *link_shift, + const struct dcn10_link_enc_mask *link_mask); + +bool dcn42_get_hpd_state(struct link_encoder *enc); +bool dcn42_program_hpd_filter(struct link_encoder *enc, int delay_on_connect_in_ms, int delay_on_disconnect_in_ms); + +#endif /* __DC_LINK_ENCODER__DCN42_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_stream_encoder.c new file mode 100644 index 000000000000..65afbfcaa96b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_stream_encoder.c @@ -0,0 +1,522 @@ +// SPDX-License-Identifier: MIT +// +// Copyright 2026 Advanced Micro Devices, Inc. + +#include "dc_bios_types.h" +#include "dcn30/dcn30_dio_stream_encoder.h" +#include "dcn32/dcn32_dio_stream_encoder.h" +#include "dcn35/dcn35_dio_stream_encoder.h" +#include "dcn401/dcn401_dio_stream_encoder.h" +#include "dcn31/dcn31_apg.h" + +#include "dcn42_dio_stream_encoder.h" +#include "reg_helper.h" +#include "hw_shared.h" +#include "link_service.h" +#include "dpcd_defs.h" + +#define DC_LOGGER \ + enc1->base.ctx->logger + +#define REG(reg)\ + (enc1->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + enc1->se_shift->field_name, enc1->se_mask->field_name + +#define VBI_LINE_0 0 +#define HDMI_CLOCK_CHANNEL_RATE_MORE_340M 340000 + +#define CTX \ + enc1->base.ctx + +/* setup stream encoder in hdmi mode */ +static void enc42_stream_encoder_hdmi_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + int actual_pix_clk_khz, + bool enable_audio) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + if (!enc->ctx->dc->debug.avoid_vbios_exec_table) { + struct bp_encoder_control cntl = {0}; + + cntl.action = ENCODER_CONTROL_SETUP; + cntl.engine_id = enc1->base.id; + cntl.signal = SIGNAL_TYPE_HDMI_TYPE_A; + cntl.enable_dp_audio = enable_audio; + cntl.pixel_clock = actual_pix_clk_khz; + cntl.lanes_number = LANE_COUNT_FOUR; + + if (enc1->base.bp->funcs->encoder_control( + enc1->base.bp, &cntl) != BP_RESULT_OK) + return; + + } else { + + //Set pattern for clock channel, default vlue 0x63 does not work + REG_UPDATE(DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, 0x1F); + + //DIG_BE_TMDS_HDMI_MODE : TMDS-HDMI mode is already set in link_encoder_setup + + //DIG_SOURCE_SELECT is already set in dig_connect_to_otg + + /* DIG_START is removed from the register spec */ + } + + /* Configure pixel encoding */ + enc401_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing); + + /* setup HDMI engine */ + REG_UPDATE_4(HDMI_CONTROL, + HDMI_DEEP_COLOR_ENABLE, 0, + HDMI_DATA_SCRAMBLE_EN, 0, + HDMI_NO_EXTRA_NULL_PACKET_FILLED, 1, + HDMI_CLOCK_CHANNEL_RATE, 0); + + /* Configure color depth */ + switch (crtc_timing->display_color_depth) { + case COLOR_DEPTH_888: + REG_UPDATE(HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, 0); + break; + case COLOR_DEPTH_101010: + if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 1, + HDMI_DEEP_COLOR_ENABLE, 0); + } else { + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 1, + HDMI_DEEP_COLOR_ENABLE, 1); + } + break; + case COLOR_DEPTH_121212: + if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 2, + HDMI_DEEP_COLOR_ENABLE, 0); + } else { + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 2, + HDMI_DEEP_COLOR_ENABLE, 1); + } + break; + case COLOR_DEPTH_161616: + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 3, + HDMI_DEEP_COLOR_ENABLE, 1); + break; + default: + break; + } + + if (actual_pix_clk_khz >= HDMI_CLOCK_CHANNEL_RATE_MORE_340M) { + /* enable HDMI data scrambler + * HDMI_CLOCK_CHANNEL_RATE_MORE_340M + * Clock channel frequency is 1/4 of character rate. + */ + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DATA_SCRAMBLE_EN, 1, + HDMI_CLOCK_CHANNEL_RATE, 1); + } else if (crtc_timing->flags.LTE_340MCSC_SCRAMBLE) { + + /* TODO: New feature for DCE11, still need to implement */ + + /* enable HDMI data scrambler + * HDMI_CLOCK_CHANNEL_FREQ_EQUAL_TO_CHAR_RATE + * Clock channel frequency is the same + * as character rate + */ + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DATA_SCRAMBLE_EN, 1, + HDMI_CLOCK_CHANNEL_RATE, 0); + } + + /* Enable transmission of General Control packet on every frame */ + REG_UPDATE_3(HDMI_VBI_PACKET_CONTROL, + HDMI_GC_CONT, 1, + HDMI_GC_SEND, 1, + HDMI_NULL_SEND, 1); + + /* Disable Audio Content Protection packet transmission */ + REG_UPDATE(HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, 0); + /* following belongs to audio */ + /* Enable Audio InfoFrame packet transmission. */ + REG_UPDATE(HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, 1); + + /* Select line number on which to send Audio InfoFrame packets */ + REG_UPDATE(HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_LINE, + VBI_LINE_0 + 2); + + /* set HDMI GC AVMUTE */ + REG_UPDATE(HDMI_GC, HDMI_GC_AVMUTE, 0); +} + +static void enc42_stream_encoder_stop_dp_info_packets( + struct stream_encoder *enc) +{ + /* stop generic packets on DP */ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + uint32_t value = 0; + + REG_SET_9(DP_SEC_CNTL, 0, + DP_SEC_GSP0_ENABLE, 0, + DP_SEC_GSP1_ENABLE, 0, + DP_SEC_GSP2_ENABLE, 0, + DP_SEC_GSP3_ENABLE, 0, + DP_SEC_GSP4_ENABLE, 0, + DP_SEC_GSP5_ENABLE, 0, + DP_SEC_GSP6_ENABLE, 0, + DP_SEC_GSP7_ENABLE, 0, + DP_SEC_STREAM_ENABLE, 0); + + /* this register shared with audio info frame. + * therefore we need to keep master enabled + * if at least one of the fields is not 0 + */ + value = REG_READ(DP_SEC_CNTL); + if (value) + REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); +} + +static void enc42_stream_encoder_update_hdmi_info_packets( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + REG_UPDATE(HDMI_DB_CONTROL, HDMI_DB_DISABLE, 1); + REG_UPDATE(DIG_FE_AUDIO_CNTL, APG_CLOCK_ENABLE, 1); + + /*Always add mandatory packets first followed by optional ones*/ + enc3_update_hdmi_info_packet(enc1, 0, &info_frame->avi); + enc3_update_hdmi_info_packet(enc1, 5, &info_frame->hfvsif); + enc3_update_hdmi_info_packet(enc1, 2, &info_frame->gamut); + enc3_update_hdmi_info_packet(enc1, 1, &info_frame->vendor); + enc3_update_hdmi_info_packet(enc1, 3, &info_frame->spd); + enc3_update_hdmi_info_packet(enc1, 4, &info_frame->hdrsmd); + enc3_update_hdmi_info_packet(enc1, 6, &info_frame->vtem); +} + +static void enc42_dp_set_dsc_pps_info_packet(struct stream_encoder *enc, + bool enable, + uint8_t *dsc_packed_pps, + bool immediate_update) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + if (enable) { + struct dc_info_packet pps_sdp; + int i; + + /* Configure for PPS packet size (128 bytes) */ + REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP11_PPS, 1); + + /* Load PPS into infoframe (SDP) registers */ + pps_sdp.valid = true; + pps_sdp.hb0 = 0; + pps_sdp.hb1 = DC_DP_INFOFRAME_TYPE_PPS; + pps_sdp.hb2 = 127; + pps_sdp.hb3 = 0; + + for (i = 0; i < 4; i++) { + memcpy(pps_sdp.sb, &dsc_packed_pps[i * 32], 32); + enc1->base.vpg->funcs->update_generic_info_packet( + enc1->base.vpg, + 11 + i, + &pps_sdp, + immediate_update); + } + + /* SW should make sure VBID[6] update line number is bigger + * than PPS transmit line number + */ + REG_UPDATE(DP_GSP11_CNTL, + DP_SEC_GSP11_LINE_NUM, 2); + REG_UPDATE_2(DP_MSA_VBID_MISC, + DP_VBID6_LINE_REFERENCE, 0, + DP_VBID6_LINE_NUM, 3); + + /* Send PPS data at the line number specified above. + * DP spec requires PPS to be sent only when it changes, however since + * decoder has to be able to handle its change on every frame, we're + * sending it always (i.e. on every frame) to reduce the chance it'd be + * missed by decoder. If it turns out required to send PPS only when it + * changes, we can use DP_SEC_GSP11_SEND register. + */ + REG_UPDATE(DP_GSP11_CNTL, + DP_SEC_GSP11_ENABLE, 1); + REG_UPDATE(DP_SEC_CNTL, + DP_SEC_STREAM_ENABLE, 1); + } else { + /* Disable Generic Stream Packet 11 (GSP) transmission */ + REG_UPDATE(DP_GSP11_CNTL, DP_SEC_GSP11_ENABLE, 0); + REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP11_PPS, 0); + } +} + +static void enc42_se_dp_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + enc42_se_enable_audio_clock(enc, true); + + REG_UPDATE(DIG_FE_AUDIO_CNTL, + DIG_FE_INPUT_MUX_AUDIO_STREAM_SOURCE_SEL, az_inst); + + enc->apg->funcs->se_audio_setup(enc->apg, az_inst, info); +} + +#define DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT 0x8000 +#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC 1 + +static void enc42_se_setup_dp_audio( + struct stream_encoder *enc) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + /* --- DP Audio packet configurations --- */ + + /* ATP Configuration */ + REG_SET(DP_SEC_AUD_N, 0, + DP_SEC_AUD_N, DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT); + + /* Async/auto-calc timestamp mode */ + REG_SET(DP_SEC_TIMESTAMP, 0, DP_SEC_TIMESTAMP_MODE, + DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC); +} + +static void enc42_se_dp_audio_enable( + struct stream_encoder *enc) +{ + ASSERT (enc->apg); + enc42_se_enable_audio_clock(enc, true); + /*APG_CONTROL2 for DP*/ + enc42_se_setup_dp_audio(enc); + /*DP_SEC_CNTL programming*/ + enc1_se_enable_dp_audio(enc); + /*APG_en*/ + enc->apg->funcs->enable_apg(enc->apg); + +} + +static void enc42_se_disable_dp_audio( + struct stream_encoder *enc) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + uint32_t value = 0; + + /* Disable Audio packets */ + REG_UPDATE_5(DP_SEC_CNTL, + DP_SEC_ASP_ENABLE, 0, + DP_SEC_ATP_ENABLE, 0, + DP_SEC_AIP_ENABLE, 0, + DP_SEC_ACM_ENABLE, 0, + DP_SEC_STREAM_ENABLE, 0); + + /* This register shared with encoder info frame. Therefore we need to + * keep master enabled if at least on of the fields is not 0 + */ + value = REG_READ(DP_SEC_CNTL); + if (value != 0) + REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); +} + +static void enc42_se_dp_audio_disable( + struct stream_encoder *enc) +{ + + enc->apg->funcs->disable_apg(enc->apg); + enc42_se_disable_dp_audio(enc); + enc42_se_enable_audio_clock(enc, false); +} + +static void enc42_se_setup_hdmi_audio( + struct stream_encoder *enc, + const struct audio_crtc_info *crtc_info) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + struct audio_clock_info audio_clock_info = {0}; + + /* HDMI_AUDIO_PACKET_CONTROL */ + REG_UPDATE(HDMI_AUDIO_PACKET_CONTROL, + HDMI_AUDIO_DELAY_EN, 1); + + /* HDMI_ACR_PACKET_CONTROL */ + REG_UPDATE_2(HDMI_ACR_PACKET_CONTROL, + HDMI_ACR_AUTO_SEND, 1, + HDMI_ACR_SOURCE, 0); + + /* Program audio clock sample/regeneration parameters */ + get_audio_clock_info(crtc_info->color_depth, + crtc_info->requested_pixel_clock_100Hz, + crtc_info->calculated_pixel_clock_100Hz, + &audio_clock_info); + DC_LOG_HW_AUDIO("\n%s:Input::requested_pixel_clock_100Hz = %d" \ + "calculated_pixel_clock_100Hz = %d\n", __func__,\ + crtc_info->requested_pixel_clock_100Hz, \ + crtc_info->calculated_pixel_clock_100Hz); + + /* HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK */ + REG_UPDATE(HDMI_ACR_32_0, HDMI_ACR_CTS_32, audio_clock_info.cts_32khz); + + /* HDMI_ACR_32_1__HDMI_ACR_N_32_MASK */ + REG_UPDATE(HDMI_ACR_32_1, HDMI_ACR_N_32, audio_clock_info.n_32khz); + + /* HDMI_ACR_44_0__HDMI_ACR_CTS_44_MASK */ + REG_UPDATE(HDMI_ACR_44_0, HDMI_ACR_CTS_44, audio_clock_info.cts_44khz); + + /* HDMI_ACR_44_1__HDMI_ACR_N_44_MASK */ + REG_UPDATE(HDMI_ACR_44_1, HDMI_ACR_N_44, audio_clock_info.n_44khz); + + /* HDMI_ACR_48_0__HDMI_ACR_CTS_48_MASK */ + REG_UPDATE(HDMI_ACR_48_0, HDMI_ACR_CTS_48, audio_clock_info.cts_48khz); + + /* HDMI_ACR_48_1__HDMI_ACR_N_48_MASK */ + REG_UPDATE(HDMI_ACR_48_1, HDMI_ACR_N_48, audio_clock_info.n_48khz); + + /* Video driver cannot know in advance which sample rate will + * be used by HD Audio driver + * HDMI_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE field is + * programmed below in interruppt callback + */ +} + +static void enc42_se_hdmi_audio_disable( + struct stream_encoder *enc) +{ + ASSERT (enc->apg); + enc->apg->funcs->disable_apg(enc->apg); + enc42_se_enable_audio_clock(enc, false); +} + +void enc42_se_enable_audio_clock( + struct stream_encoder *enc, + bool enable) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + REG_UPDATE(DIG_FE_AUDIO_CNTL, APG_CLOCK_ENABLE, !!enable); +} + + +static void enc42_se_hdmi_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info, + struct audio_crtc_info *audio_crtc_info) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + ASSERT (enc->apg); + enc42_se_enable_audio_clock(enc, true); + /*ACR setup*/ + enc42_se_setup_hdmi_audio(enc, audio_crtc_info); + + REG_UPDATE(DIG_FE_AUDIO_CNTL, + DIG_FE_INPUT_MUX_AUDIO_STREAM_SOURCE_SEL, az_inst); + + /*APG_DBG_GEN_CONTROL*/ + enc->apg->funcs->se_audio_setup(enc->apg, az_inst, info); + /*APG enable*/ + enc->apg->funcs->enable_apg(enc->apg); +} + +static void enc42_audio_mute_control( + struct stream_encoder *enc, + bool mute) +{ + if (mute) + enc->apg->funcs->disable_apg(enc->apg); + else + enc->apg->funcs->enable_apg(enc->apg); +} +void enc42_reset_hdmi_stream_attribute( + struct stream_encoder *enc) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + REG_UPDATE_3(HDMI_CONTROL, + HDMI_DEEP_COLOR_ENABLE, 0, + HDMI_DATA_SCRAMBLE_EN, 0, + HDMI_CLOCK_CHANNEL_RATE, 0); +} + +static const struct stream_encoder_funcs dcn42_str_enc_funcs = { + .dp_set_stream_attribute = + enc401_stream_encoder_dp_set_stream_attribute, + .hdmi_set_stream_attribute = + enc42_stream_encoder_hdmi_set_stream_attribute, + .dvi_set_stream_attribute = + enc401_stream_encoder_dvi_set_stream_attribute, + .set_throttled_vcp_size = + enc1_stream_encoder_set_throttled_vcp_size, + .update_hdmi_info_packets = + enc42_stream_encoder_update_hdmi_info_packets, + .stop_hdmi_info_packets = + enc3_stream_encoder_stop_hdmi_info_packets, + .update_dp_info_packets_sdp_line_num = + enc3_stream_encoder_update_dp_info_packets_sdp_line_num, + .update_dp_info_packets = + enc3_stream_encoder_update_dp_info_packets, + .stop_dp_info_packets = + enc42_stream_encoder_stop_dp_info_packets, + .dp_blank = + enc1_stream_encoder_dp_blank, + .dp_unblank = + enc401_stream_encoder_dp_unblank, + .audio_mute_control = enc42_audio_mute_control, + + .dp_audio_setup = enc42_se_dp_audio_setup, + .dp_audio_enable = enc42_se_dp_audio_enable, + .dp_audio_disable = enc42_se_dp_audio_disable, + + .hdmi_audio_setup = enc42_se_hdmi_audio_setup, + .hdmi_audio_disable = enc42_se_hdmi_audio_disable, + .setup_stereo_sync = enc1_setup_stereo_sync, + .set_avmute = enc1_stream_encoder_set_avmute, + .dig_connect_to_otg = enc1_dig_connect_to_otg, + .dig_source_otg = enc1_dig_source_otg, + + .dp_get_pixel_format = enc1_stream_encoder_dp_get_pixel_format, + + .enc_read_state = enc401_read_state, + .dp_set_dsc_config = NULL, + .dp_set_dsc_pps_info_packet = enc42_dp_set_dsc_pps_info_packet, + .set_dynamic_metadata = enc401_set_dynamic_metadata, + .hdmi_reset_stream_attribute = enc42_reset_hdmi_stream_attribute, + .enable_stream = enc401_stream_encoder_enable, + + .set_input_mode = enc401_set_dig_input_mode, + .enable_fifo = enc35_enable_fifo, + .disable_fifo = enc35_disable_fifo, + .map_stream_to_link = enc401_stream_encoder_map_to_link, +}; + +void dcn42_dio_stream_encoder_construct( + struct dcn10_stream_encoder *enc1, + struct dc_context *ctx, + struct dc_bios *bp, + enum engine_id eng_id, + struct vpg *vpg, + struct apg *apg, + const struct dcn10_stream_enc_registers *regs, + const struct dcn10_stream_encoder_shift *se_shift, + const struct dcn10_stream_encoder_mask *se_mask) +{ + enc1->base.funcs = &dcn42_str_enc_funcs; + enc1->base.ctx = ctx; + enc1->base.id = eng_id; + enc1->base.bp = bp; + enc1->base.vpg = vpg; + enc1->base.apg = apg; + enc1->regs = regs; + enc1->se_shift = se_shift; + enc1->se_mask = se_mask; + enc1->base.stream_enc_inst = vpg->inst; +} diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_stream_encoder.h new file mode 100644 index 000000000000..7a98fee46081 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_stream_encoder.h @@ -0,0 +1,206 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2026 - Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_DIO_STREAM_ENCODER_DCN42_H__ +#define __DC_DIO_STREAM_ENCODER_DCN42_H__ + +#include "dcn30/dcn30_vpg.h" +#include "stream_encoder.h" +#include "dcn20/dcn20_stream_encoder.h" + +#define SE_COMMON_MASK_SH_LIST_DCN42(mask_sh)\ + SE_SF(DP0_DP_PIXEL_FORMAT, PIXEL_ENCODING_TYPE, mask_sh),\ + SE_SF(DP0_DP_PIXEL_FORMAT, UNCOMPRESSED_PIXEL_FORMAT, mask_sh),\ + SE_SF(DP0_DP_PIXEL_FORMAT, UNCOMPRESSED_COMPONENT_DEPTH, mask_sh),\ + SE_SF(DP0_DP_PIXEL_FORMAT, COMPRESSED_PIXEL_FORMAT, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_ENABLE, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_NO_EXTRA_NULL_PACKET_FILLED, mask_sh),\ + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_NULL_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GC, HDMI_GC_AVMUTE, mask_sh),\ + SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_X, mask_sh),\ + SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_Y, mask_sh),\ + SE_SF(DP0_DP_MSE_RATE_UPDATE, DP_MSE_RATE_UPDATE_PENDING, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP1_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP5_LINE_REFERENCE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND_PENDING, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL4, DP_SEC_GSP4_LINE_NUM, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL5, DP_SEC_GSP5_LINE_NUM, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND_ANY_LINE, mask_sh),\ + SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_DIS_DEFER, mask_sh),\ + SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, mask_sh),\ + SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, mask_sh),\ + SE_SF(DP0_DP_STEER_FIFO, DP_STEER_FIFO_RESET, mask_sh),\ + SE_SF(DP0_DP_STEER_FIFO, DP_STEER_FIFO_ENABLE, mask_sh),\ + SE_SF(DP0_DP_VID_TIMING, DP_VID_M_N_GEN_EN, mask_sh),\ + SE_SF(DP0_DP_VID_N, DP_VID_N, mask_sh),\ + SE_SF(DP0_DP_VID_M, DP_VID_M, mask_sh),\ + SE_SF(DIG0_HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_DELAY_EN, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUTO_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_SOURCE, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_32_0, HDMI_ACR_CTS_32, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_32_1, HDMI_ACR_N_32, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_44_0, HDMI_ACR_CTS_44, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_44_1, HDMI_ACR_N_44, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_48_0, HDMI_ACR_CTS_48, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_48_1, HDMI_ACR_N_48, mask_sh),\ + SE_SF(DP0_DP_SEC_AUD_N, DP_SEC_AUD_N, mask_sh),\ + SE_SF(DP0_DP_SEC_TIMESTAMP, DP_SEC_TIMESTAMP_MODE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ASP_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ATP_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_AIP_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ACM_ENABLE, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\ + SE_SF(DIG1_HDMI_CONTROL, TMDS_PIXEL_ENCODING, mask_sh),\ + SE_SF(DIG1_HDMI_CONTROL, TMDS_COLOR_FORMAT, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP4_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP6_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP7_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP7_SEND, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL6, DP_SEC_GSP7_LINE_NUM, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP11_PPS, mask_sh),\ + SE_SF(DP0_DP_GSP11_CNTL, DP_SEC_GSP11_ENABLE, mask_sh),\ + SE_SF(DP0_DP_GSP11_CNTL, DP_SEC_GSP11_LINE_NUM, mask_sh),\ + SE_SF(DP0_DP_DB_CNTL, DP_DB_DISABLE, mask_sh),\ + SE_SF(DP0_DP_MSA_COLORIMETRY, DP_MSA_MISC0, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_HTOTAL, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_VTOTAL, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_HSTART, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_VSTART, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCWIDTH, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCPOLARITY, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCWIDTH, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCPOLARITY, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_HWIDTH, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_VHEIGHT, mask_sh),\ + SE_SF(DIG0_HDMI_DB_CONTROL, HDMI_DB_DISABLE, mask_sh),\ + SE_SF(DP0_DP_VID_TIMING, DP_VID_N_INTERVAL, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DIG_SOURCE_SELECT, mask_sh), \ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC2_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC2_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC3_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC3_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC4_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC4_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC5_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC5_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC6_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC6_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC7_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC7_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC8_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC8_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC9_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC9_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC10_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC10_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC11_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC11_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC12_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC12_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC13_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC13_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC14_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC14_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL1, HDMI_GENERIC0_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL1, HDMI_GENERIC1_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL2, HDMI_GENERIC2_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL2, HDMI_GENERIC3_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL3, HDMI_GENERIC4_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL3, HDMI_GENERIC5_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL4, HDMI_GENERIC6_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL4, HDMI_GENERIC7_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL7, HDMI_GENERIC8_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL7, HDMI_GENERIC9_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL8, HDMI_GENERIC10_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL8, HDMI_GENERIC11_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL9, HDMI_GENERIC12_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL9, HDMI_GENERIC13_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL10, HDMI_GENERIC14_LINE, mask_sh),\ + SE_SF(DP0_DP_MSA_VBID_MISC, DP_VBID6_LINE_REFERENCE, mask_sh),\ + SE_SF(DP0_DP_MSA_VBID_MISC, DP_VBID6_LINE_NUM, mask_sh),\ + SE_SF(DME0_DME_CONTROL, METADATA_ENGINE_EN, mask_sh),\ + SE_SF(DME0_DME_CONTROL, METADATA_HUBP_REQUESTOR_ID, mask_sh),\ + SE_SF(DME0_DME_CONTROL, METADATA_STREAM_TYPE, mask_sh),\ + SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_LINE_REFERENCE, mask_sh),\ + SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_ENABLE, mask_sh),\ + SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE_REFERENCE, mask_sh),\ + SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, DOLBY_VISION_EN, mask_sh),\ + SE_SF(DIG0_DIG_FE_EN_CNTL, DIG_FE_ENABLE, mask_sh),\ + SE_SF(DIG0_DIG_FE_CLK_CNTL, DIG_FE_MODE, mask_sh),\ + SE_SF(DIG0_DIG_FE_CLK_CNTL, DIG_FE_CLK_EN, mask_sh),\ + SE_SF(DIG0_DIG_FE_CLK_CNTL, DIG_FE_SOFT_RESET, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh),\ + SE_SF(DP0_DP_SEC_FRAMING4, DP_SST_SDP_SPLITTING, mask_sh),\ + SE_SF(DIG0_DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_OUTPUT_PIXEL_PER_CYCLE, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_READ_START_LEVEL, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_ENABLE, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_RESET, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, mask_sh),\ + SE_SF(DIG0_STREAM_MAPPER_CONTROL, DIG_STREAM_LINK_TARGET, mask_sh),\ + SE_SF(DIG0_DIG_FE_AUDIO_CNTL, DIG_FE_INPUT_MUX_AUDIO_STREAM_SOURCE_SEL, mask_sh),\ + SE_SF(DIG0_DIG_FE_AUDIO_CNTL, APG_CLOCK_ENABLE, mask_sh) + +void dcn42_dio_stream_encoder_construct( + struct dcn10_stream_encoder *enc1, + struct dc_context *ctx, + struct dc_bios *bp, + enum engine_id eng_id, + struct vpg *vpg, + struct apg *apg, + const struct dcn10_stream_enc_registers *regs, + const struct dcn10_stream_encoder_shift *se_shift, + const struct dcn10_stream_encoder_mask *se_mask); + +void enc42_se_enable_audio_clock( + struct stream_encoder *enc, + bool enable); + +void enc42_reset_hdmi_stream_attribute( + struct stream_encoder *enc); +#endif /* __DC_DIO_STREAM_ENCODER_DCN42_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_link_encoder.c index 2655bc194a35..5b2bba0eff0e 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_link_encoder.c @@ -30,52 +30,92 @@ static bool virtual_link_encoder_validate_output_with_stream( struct link_encoder *enc, - const struct dc_stream_state *stream) { return true; } + const struct dc_stream_state *stream) { + (void)enc; + (void)stream; + return true; + } -static void virtual_link_encoder_hw_init(struct link_encoder *enc) {} +static void virtual_link_encoder_hw_init(struct link_encoder *enc) +{ + (void)enc; +} static void virtual_link_encoder_setup( - struct link_encoder *enc, - enum signal_type signal) {} + struct link_encoder *enc, enum signal_type signal) { + (void)enc; + (void)signal; + } static void virtual_link_encoder_enable_tmds_output( struct link_encoder *enc, enum clock_source_id clock_source, enum dc_color_depth color_depth, enum signal_type signal, - uint32_t pixel_clock) {} + uint32_t pixel_clock) { + (void)enc; + (void)clock_source; + (void)color_depth; + (void)signal; + (void)pixel_clock; + } static void virtual_link_encoder_enable_dp_output( struct link_encoder *enc, const struct dc_link_settings *link_settings, - enum clock_source_id clock_source) {} + enum clock_source_id clock_source) { + (void)enc; + (void)link_settings; + (void)clock_source; + } static void virtual_link_encoder_enable_dp_mst_output( struct link_encoder *enc, const struct dc_link_settings *link_settings, - enum clock_source_id clock_source) {} + enum clock_source_id clock_source) { + (void)enc; + (void)link_settings; + (void)clock_source; + } static void virtual_link_encoder_disable_output( struct link_encoder *link_enc, - enum signal_type signal) {} + enum signal_type signal) { + (void)link_enc; + (void)signal; + } static void virtual_link_encoder_dp_set_lane_settings( struct link_encoder *enc, const struct dc_link_settings *link_settings, - const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]) {} + const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]) { + (void)enc; + (void)link_settings; + (void)lane_settings; + } static void virtual_link_encoder_dp_set_phy_pattern( struct link_encoder *enc, - const struct encoder_set_dp_phy_pattern_param *param) {} + const struct encoder_set_dp_phy_pattern_param *param) { + (void)enc; + (void)param; + } static void virtual_link_encoder_update_mst_stream_allocation_table( struct link_encoder *enc, - const struct link_mst_stream_allocation_table *table) {} + const struct link_mst_stream_allocation_table *table) { + (void)enc; + (void)table; + } static void virtual_link_encoder_connect_dig_be_to_fe( struct link_encoder *enc, enum engine_id engine, - bool connect) {} + bool connect) { + (void)enc; + (void)engine; + (void)connect; + } static void virtual_link_encoder_destroy(struct link_encoder **enc) { @@ -86,6 +126,7 @@ static void virtual_link_encoder_destroy(struct link_encoder **enc) static void virtual_link_encoder_get_max_link_cap(struct link_encoder *enc, struct dc_link_settings *link_settings) { + (void)enc; /* Set Default link settings */ struct dc_link_settings max_link_cap = {LANE_COUNT_FOUR, LINK_RATE_HIGH, LINK_SPREAD_05_DOWNSPREAD_30KHZ, false, 0}; diff --git a/drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_stream_encoder.c index a9c8857476ac..27448f2b2467 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_stream_encoder.c @@ -31,80 +31,127 @@ static void virtual_stream_encoder_dp_set_stream_attribute( struct dc_crtc_timing *crtc_timing, enum dc_color_space output_color_space, bool use_vsc_sdp_for_colorimetry, - uint32_t enable_sdp_splitting) {} + uint32_t enable_sdp_splitting) { + (void)enc; + (void)crtc_timing; + (void)output_color_space; + (void)use_vsc_sdp_for_colorimetry; + (void)enable_sdp_splitting; + } static void virtual_stream_encoder_hdmi_set_stream_attribute( struct stream_encoder *enc, struct dc_crtc_timing *crtc_timing, int actual_pix_clk_khz, - bool enable_audio) {} + bool enable_audio) { + (void)enc; + (void)crtc_timing; + (void)actual_pix_clk_khz; + (void)enable_audio; + } static void virtual_stream_encoder_dvi_set_stream_attribute( struct stream_encoder *enc, struct dc_crtc_timing *crtc_timing, - bool is_dual_link) {} + bool is_dual_link) { + (void)enc; + (void)crtc_timing; + (void)is_dual_link; + } static void virtual_stream_encoder_set_throttled_vcp_size( struct stream_encoder *enc, - struct fixed31_32 avg_time_slots_per_mtp) -{} + struct fixed31_32 avg_time_slots_per_mtp) { + (void)enc; + (void)avg_time_slots_per_mtp; + } static void virtual_stream_encoder_update_hdmi_info_packets( struct stream_encoder *enc, - const struct encoder_info_frame *info_frame) {} + const struct encoder_info_frame *info_frame) { + (void)enc; + (void)info_frame; + } static void virtual_stream_encoder_stop_hdmi_info_packets( - struct stream_encoder *enc) {} + struct stream_encoder *enc) { + (void)enc; + } static void virtual_stream_encoder_set_avmute( - struct stream_encoder *enc, - bool enable) {} + struct stream_encoder *enc, bool enable) { + (void)enc; + (void)enable; + } static void virtual_stream_encoder_update_dp_info_packets( struct stream_encoder *enc, - const struct encoder_info_frame *info_frame) {} + const struct encoder_info_frame *info_frame) { + (void)enc; + (void)info_frame; + } static void virtual_stream_encoder_stop_dp_info_packets( - struct stream_encoder *enc) {} + struct stream_encoder *enc) { + (void)enc; + } static void virtual_stream_encoder_dp_blank( struct dc_link *link, - struct stream_encoder *enc) {} + struct stream_encoder *enc) { + (void)link; + (void)enc; + } static void virtual_stream_encoder_dp_unblank( struct dc_link *link, struct stream_encoder *enc, - const struct encoder_unblank_param *param) {} + const struct encoder_unblank_param *param) { + (void)enc; + (void)link; + (void)param; + } static void virtual_audio_mute_control( - struct stream_encoder *enc, - bool mute) {} + struct stream_encoder *enc, bool mute) { + (void)enc; + (void)mute; + } static void virtual_stream_encoder_reset_hdmi_stream_attribute( - struct stream_encoder *enc) -{} + struct stream_encoder *enc) +{ + (void)enc; +} static void virtual_enc_dp_set_odm_combine( - struct stream_encoder *enc, - bool odm_combine) -{} + struct stream_encoder *enc, bool odm_combine) { + (void)enc; + (void)odm_combine; + } static void virtual_dig_connect_to_otg( - struct stream_encoder *enc, - int tg_inst) -{} + struct stream_encoder *enc, int tg_inst) { + (void)enc; + (void)tg_inst; + } static void virtual_setup_stereo_sync( - struct stream_encoder *enc, - int tg_inst, - bool enable) -{} + struct stream_encoder *enc, + int tg_inst, bool enable) { + (void)enc; + (void)tg_inst; + (void)enable; + } static void virtual_stream_encoder_set_dsc_pps_info_packet( - struct stream_encoder *enc, - bool enable, - uint8_t *dsc_packed_pps, - bool immediate_update) -{} + struct stream_encoder *enc, bool enable, uint8_t *dsc_packed_pps, + bool immediate_update) +{ + (void)enc; + (void)enable; + (void)dsc_packed_pps; + (void)immediate_update; +} static const struct stream_encoder_funcs virtual_str_enc_funcs = { .dp_set_odm_combine = diff --git a/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c index 74962791302f..61553e24d53e 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c @@ -525,6 +525,7 @@ static void split_stream_across_pipes( struct pipe_ctx *primary_pipe, struct pipe_ctx *secondary_pipe) { + (void)res_ctx; int pipe_idx = secondary_pipe->pipe_idx; if (!primary_pipe->plane_state) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.c index c5e84190c17a..5679b79d6f53 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.c @@ -76,7 +76,7 @@ struct _vcs_dpi_ip_params_st dcn1_0_ip = { .line_buffer_size_bits = 589824, .max_line_buffer_lines = 12, .IsLineBufferBppFixed = 0, - .LineBufferFixedBpp = -1, + .LineBufferFixedBpp = (unsigned int)-1, .writeback_luma_buffer_size_kbytes = 12, .writeback_chroma_buffer_size_kbytes = 8, .max_num_dpp = 4, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c index 7aaf13bbd4e4..887744d56d6a 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c @@ -1316,6 +1316,7 @@ int dcn20_populate_dml_pipes_from_context(struct dc *dc, display_e2e_pipe_params_st *pipes, enum dc_validate_mode validate_mode) { + (void)validate_mode; int pipe_cnt, i; bool synchronized_vblank = true; struct resource_context *res_ctx = &context->res_ctx; @@ -2335,7 +2336,7 @@ bool dcn21_validate_bandwidth_fp(struct dc *dc, struct dc_state *context, /*Unsafe due to current pipe merge and split logic*/ ASSERT(context != dc->current_state); - out = dcn21_fast_validate_bw(dc, context, pipes, &pipe_cnt, pipe_split_from, &vlevel, validate_mode); + out = dcn21_fast_validate_bw(dc, context, pipes, &pipe_cnt, pipe_split_from, &vlevel, validate_mode, false); if (pipe_cnt == 0) goto validate_out; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c index 0c8c4a080c50..f5f636afe33c 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c @@ -501,6 +501,8 @@ static bool CalculatePrefetchSchedule( double *VUpdateWidthPix, double *VReadyOffsetPix) { + (void)mode_lib; + bool MyError = false; unsigned int DPPCycles, DISPCLKCycles; double DSTTotalPixelsAfterScaler, TotalRepeaterDelayTime; @@ -878,6 +880,7 @@ static unsigned int CalculateVMAndRowBytes( unsigned int *dpte_row_height, unsigned int *meta_row_height) { + (void)ViewportWidth; unsigned int MetaRequestHeight; unsigned int MetaRequestWidth; unsigned int MetaSurfWidth; @@ -2953,6 +2956,7 @@ static double CalculateRemoteSurfaceFlipDelay( double *TInitXFill, double *TslvChk) { + (void)mode_lib; double TSlvSetup, AvgfillRate, result; *SrcActiveDrainRate = VRatio * SwathWidth * Bpp / LineTime; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c index c935903b68e1..95b0a3501880 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c @@ -495,6 +495,7 @@ static bool CalculateDelayAfterScaler( double *DSTYAfterScaler ) { + (void)ReturnBW; unsigned int DPPCycles, DISPCLKCycles; double DataFabricLineDeliveryTimeLuma; double DataFabricLineDeliveryTimeChroma; @@ -592,6 +593,8 @@ static bool CalculatePrefetchSchedule( double *VUpdateWidthPix, double *VReadyOffsetPix) { + (void)mode_lib; + bool MyError = false; double TotalRepeaterDelayTime; double Tdm, LineTime, Tsetup; @@ -938,6 +941,7 @@ static unsigned int CalculateVMAndRowBytes( unsigned int *dpte_row_height, unsigned int *meta_row_height) { + (void)ViewportWidth; unsigned int MetaRequestHeight; unsigned int MetaRequestWidth; unsigned int MetaSurfWidth; @@ -3026,6 +3030,7 @@ static double CalculateRemoteSurfaceFlipDelay( double *TInitXFill, double *TslvChk) { + (void)mode_lib; double TSlvSetup, AvgfillRate, result; *SrcActiveDrainRate = VRatio * SwathWidth * Bpp / LineTime; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c index 9c58ff1069d6..591d9618bdc0 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c @@ -126,6 +126,7 @@ static double get_refcyc_per_delivery(struct display_mode_lib *mode_lib, unsigned int delivery_width, unsigned int req_per_swath_ub) { + (void)mode_lib; double refcyc_per_delivery = 0.0; if (vratio <= 1.0) { @@ -1538,6 +1539,9 @@ void dml20_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib, const bool ignore_viewport_pos, const bool immediate_flip_support) { + (void)vm_en; + (void)ignore_viewport_pos; + (void)immediate_flip_support; display_rq_params_st rq_param = {0}; display_dlg_sys_params_st dlg_sys_param = {0}; @@ -1588,6 +1592,7 @@ static void calculate_ttu_cursor(struct display_mode_lib *mode_lib, unsigned int cur_width, enum cursor_bpp cur_bpp) { + (void)mode_lib; unsigned int cur_src_width = cur_width; unsigned int cur_req_size = 0; unsigned int cur_req_width = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c index 570e6e39eb45..d4dddc9d535a 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c @@ -126,6 +126,7 @@ static double get_refcyc_per_delivery(struct display_mode_lib *mode_lib, unsigned int delivery_width, unsigned int req_per_swath_ub) { + (void)mode_lib; double refcyc_per_delivery = 0.0; if (vratio <= 1.0) { @@ -1539,6 +1540,9 @@ void dml20v2_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib, const bool ignore_viewport_pos, const bool immediate_flip_support) { + (void)vm_en; + (void)ignore_viewport_pos; + (void)immediate_flip_support; display_rq_params_st rq_param = {0}; display_dlg_sys_params_st dlg_sys_param = {0}; @@ -1589,6 +1593,7 @@ static void calculate_ttu_cursor(struct display_mode_lib *mode_lib, unsigned int cur_width, enum cursor_bpp cur_bpp) { + (void)mode_lib; unsigned int cur_src_width = cur_width; unsigned int cur_req_size = 0; unsigned int cur_req_width = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c index cd8cca651419..11570a0c9427 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c @@ -695,6 +695,9 @@ static bool CalculatePrefetchSchedule( double *VUpdateWidthPix, double *VReadyOffsetPix) { + (void)mode_lib; + (void)XFCEnabled; + bool MyError = false; unsigned int DPPCycles, DISPCLKCycles; double DSTTotalPixelsAfterScaler, TotalRepeaterDelayTime; @@ -1290,6 +1293,8 @@ static unsigned int CalculateVMAndRowBytes( unsigned int *DPDE0BytesFrame, unsigned int *MetaPTEBytesFrame) { + (void)SourcePixelFormat; + (void)ViewportWidth; unsigned int MPDEBytesFrame; unsigned int DCCMetaSurfaceBytes; unsigned int MacroTileSizeBytes; @@ -3040,6 +3045,7 @@ static double CalculateRemoteSurfaceFlipDelay( double *TInitXFill, double *TslvChk) { + (void)mode_lib; double TSlvSetup, AvgfillRate, result; *SrcActiveDrainRate = VRatio * SwathWidth * Bpp / LineTime; @@ -3187,6 +3193,7 @@ static void CalculateFlipSchedule( double *final_flip_bw, bool *ImmediateFlipSupportedForPipe) { + (void)mode_lib; double min_row_time = 0.0; unsigned int HostVMDynamicLevels; double TimeForFetchingMetaPTEImmediateFlip; @@ -5294,6 +5301,15 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport( double *StutterEnterPlusExitWatermark, double *MinActiveDRAMClockChangeLatencySupported) { + (void)DPPCLK; + (void)SwathWidthSingleDPPY; + (void)DCFCLK; + (void)UrgentOutOfOrderReturn; + (void)ReturnBW; + (void)GPUVMEnable; + (void)dpte_group_bytes; + (void)MetaChunkSize; + double EffectiveLBLatencyHidingY; double EffectiveLBLatencyHidingC; double DPPOutputBufferLinesY; @@ -5304,7 +5320,7 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport( double LinesInDETC; unsigned int LinesInDETYRoundedDownToSwath[DC__NUM_DPP__MAX]; unsigned int LinesInDETCRoundedDownToSwath; - double FullDETBufferingTimeY[DC__NUM_DPP__MAX]; + double FullDETBufferingTimeY[DC__NUM_DPP__MAX] = { 0 }; double FullDETBufferingTimeC; double ActiveDRAMClockChangeLatencyMarginY; double ActiveDRAMClockChangeLatencyMarginC; @@ -5885,6 +5901,9 @@ static void CalculateMetaAndPTETimes( double TimePerVMRequestVBlank[], double TimePerVMRequestFlip[]) { + (void)VRatioPrefetchY; + (void)VRatioPrefetchC; + unsigned int meta_chunk_width; unsigned int min_meta_chunk_width; unsigned int meta_chunk_per_row_int; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c index f549da082c01..8a611b3bec33 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c @@ -102,6 +102,7 @@ static double get_refcyc_per_delivery( unsigned int delivery_width, unsigned int req_per_swath_ub) { + (void)mode_lib; double refcyc_per_delivery = 0.0; if (vratio <= 1.0) { @@ -1647,6 +1648,9 @@ void dml21_rq_dlg_get_dlg_reg( const bool ignore_viewport_pos, const bool immediate_flip_support) { + (void)vm_en; + (void)ignore_viewport_pos; + (void)immediate_flip_support; display_rq_params_st rq_param = {0}; display_dlg_sys_params_st dlg_sys_param = {0}; @@ -1702,6 +1706,7 @@ static void calculate_ttu_cursor( unsigned int cur_width, enum cursor_bpp cur_bpp) { + (void)mode_lib; unsigned int cur_src_width = cur_width; unsigned int cur_req_size = 0; unsigned int cur_req_width = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c index e5f5c0663750..0cdd60869ce1 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c @@ -571,6 +571,7 @@ void dcn30_fpu_update_bw_bounding_box(struct dc *dc, unsigned int *dcfclk_mhz, unsigned int *dram_speed_mts) { + (void)bw_params; unsigned int i; dc_assert_fp_enabled(); @@ -720,6 +721,7 @@ void dcn3_fpu_build_wm_range_table(struct clk_mgr *base) void patch_dcn30_soc_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st *dcn3_0_ip) { + (void)dcn3_0_ip; dc_assert_fp_enabled(); if (dc->ctx->dc_bios->funcs->get_soc_bb_info) { diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c index 1df3412be346..634982173190 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c @@ -778,6 +778,8 @@ static bool CalculatePrefetchSchedule( double *RequiredPrefetchPixDataBWChroma, bool *NotEnoughTimeForDynamicMetadata) { + (void)SwathWidthY; + (void)SwathWidthC; struct vba_vars_st *v = &mode_lib->vba; double DPPCLKDelaySubtotalPlusCNVCFormater = v->DPPCLKDelaySubtotal + v->DPPCLKDelayCNVCFormater; bool MyError = false; @@ -1233,6 +1235,10 @@ static void CalculateDCCConfiguration( unsigned int *IndependentBlockLuma, unsigned int *IndependentBlockChroma) { + (void)SurfaceWidthChroma; + (void)SurfaceHeightChroma; + (void)BytePerPixelDETY; + (void)BytePerPixelDETC; int yuv420 = 0; int horz_div_l = 0; int horz_div_c = 0; @@ -1595,6 +1601,7 @@ static unsigned int CalculateVMAndRowBytes( unsigned int *DPDE0BytesFrame, unsigned int *MetaPTEBytesFrame) { + (void)SourcePixelFormat; unsigned int MPDEBytesFrame = 0; unsigned int DCCMetaSurfaceBytes = 0; unsigned int MacroTileSizeBytes = 0; @@ -3068,6 +3075,8 @@ double dml30_CalculateWriteBackDISPCLK( unsigned int HTotal, unsigned int WritebackLineBufferSize) { + (void)WritebackPixelFormat; + (void)WritebackVRatio; double DISPCLK_H = 0, DISPCLK_V = 0, DISPCLK_HB = 0; DISPCLK_H = PixelClock * dml_ceil(WritebackHTaps / 8.0, 1) / WritebackHRatio; @@ -3086,6 +3095,8 @@ static double CalculateWriteBackDelay( long WritebackSourceHeight, unsigned int HTotal) { + (void)WritebackPixelFormat; + (void)WritebackHRatio; double CalculateWriteBackDelay = 0; double Line_length = 0; double Output_lines_last_notclamped = 0; @@ -3199,6 +3210,8 @@ static void CalculateFlipSchedule( double *final_flip_bw, bool *ImmediateFlipSupportedForPipe) { + (void)mode_lib; + (void)HostVMMinPageSize; double min_row_time = 0.0; unsigned int HostVMDynamicLevelsTrips = 0; double TimeForFetchingMetaPTEImmediateFlip = 0; @@ -4968,6 +4981,10 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport( double BytePerPixelDETC[], enum clock_change_support *DRAMClockChangeSupport) { + (void)DCFCLK; + (void)ReturnBW; + (void)DPPCLK; + (void)DETBufferSizeC; struct vba_vars_st *v = &mode_lib->vba; double EffectiveLBLatencyHidingY = 0; double EffectiveLBLatencyHidingC = 0; @@ -5212,6 +5229,8 @@ static void CalculateUrgentBurstFactor( double *UrgentBurstFactorChroma, bool *NotEnoughUrgentLatencyHiding) { + (void)DETBufferSizeInKByte; + (void)VRatioC; double LinesInDETLuma = 0; double LinesInDETChroma = 0; unsigned int LinesInCursorBuffer = 0; @@ -5575,6 +5594,8 @@ static void CalculateVMGroupAndRequestTimes( double TimePerVMRequestVBlank[], double TimePerVMRequestFlip[]) { + (void)dpte_row_width_luma_ub; + (void)dpte_row_width_chroma_ub; int num_group_per_lower_vm_stage = 0; int num_req_per_lower_vm_stage = 0; unsigned int k; @@ -5857,6 +5878,7 @@ static void CalculateSwathAndDETConfiguration( bool ViewportSizeSupportPerPlane[], bool *ViewportSizeSupport) { + (void)HRatioChroma; int MaximumSwathHeightY[DC__NUM_DPP__MAX] = { 0 }; int MaximumSwathHeightC[DC__NUM_DPP__MAX] = { 0 }; int MinimumSwathHeightY = 0; @@ -6039,6 +6061,7 @@ static void CalculateSwathWidth( unsigned int swath_width_luma_ub[], unsigned int swath_width_chroma_ub[]) { + (void)BytePerPixY; unsigned int k, j; long surface_width_ub_l; long surface_height_ub_l; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c index 4fb37df54d59..472ac5ee165f 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c @@ -50,6 +50,7 @@ static double get_refcyc_per_delivery(struct display_mode_lib *mode_lib, unsigned int delivery_width, unsigned int req_per_swath_ub) { + (void)mode_lib; double refcyc_per_delivery = 0.0; if (vratio <= 1.0) { @@ -804,6 +805,7 @@ static void calculate_ttu_cursor(struct display_mode_lib *mode_lib, unsigned int cur_width, enum cursor_bpp cur_bpp) { + (void)mode_lib; unsigned int cur_src_width = cur_width; unsigned int cur_req_size = 0; unsigned int cur_req_width = 0; @@ -896,6 +898,9 @@ static void dml_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, const bool ignore_viewport_pos, const bool immediate_flip_support) { + (void)vm_en; + (void)ignore_viewport_pos; + (void)immediate_flip_support; const display_pipe_source_params_st *src = &e2e_pipe_param[pipe_idx].pipe.src; const display_pipe_dest_params_st *dst = &e2e_pipe_param[pipe_idx].pipe.dest; const display_output_params_st *dout = &e2e_pipe_param[pipe_idx].dout; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c index ed59c77bc6f6..9833467722b9 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c @@ -873,6 +873,11 @@ static bool CalculatePrefetchSchedule( double *VUpdateWidthPix, double *VReadyOffsetPix) { + (void)mode_lib; + (void)HostVMMinPageSize; + (void)SwathWidthY; + (void)SwathWidthC; + bool MyError = false; unsigned int DPPCycles, DISPCLKCycles; double DSTTotalPixelsAfterScaler; @@ -1491,6 +1496,10 @@ static void CalculateDCCConfiguration( unsigned int *IndependentBlockLuma, unsigned int *IndependentBlockChroma) { + (void)SurfaceWidthChroma; + (void)SurfaceHeightChroma; + (void)BytePerPixelDETY; + (void)BytePerPixelDETC; int yuv420; int horz_div_l; int horz_div_c; @@ -1823,6 +1832,7 @@ static unsigned int CalculateVMAndRowBytes( int *DPDE0BytesFrame, int *MetaPTEBytesFrame) { + (void)SourcePixelFormat; struct vba_vars_st *v = &mode_lib->vba; unsigned int MPDEBytesFrame; unsigned int DCCMetaSurfaceBytes; @@ -3365,6 +3375,8 @@ double dml31_CalculateWriteBackDISPCLK( unsigned int HTotal, unsigned int WritebackLineBufferSize) { + (void)WritebackPixelFormat; + (void)WritebackVRatio; double DISPCLK_H, DISPCLK_V, DISPCLK_HB; DISPCLK_H = PixelClock * dml_ceil(WritebackHTaps / 8.0, 1) / WritebackHRatio; @@ -3383,6 +3395,8 @@ static double CalculateWriteBackDelay( int WritebackSourceHeight, unsigned int HTotal) { + (void)WritebackPixelFormat; + (void)WritebackHRatio; double CalculateWriteBackDelay; double Line_length; double Output_lines_last_notclamped; @@ -5566,6 +5580,9 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport( double *Z8StutterExitWatermark, double *Z8StutterEnterPlusExitWatermark) { + (void)DCFCLK; + (void)ReturnBW; + (void)DETBufferSizeC; struct vba_vars_st *v = &mode_lib->vba; double EffectiveLBLatencyHidingY; double EffectiveLBLatencyHidingC; @@ -5831,6 +5848,7 @@ static void CalculateUrgentBurstFactor( double *UrgentBurstFactorChroma, bool *NotEnoughUrgentLatencyHiding) { + (void)VRatioC; double LinesInDETLuma; double LinesInDETChroma; unsigned int LinesInCursorBuffer; @@ -6213,6 +6231,8 @@ static void CalculateVMGroupAndRequestTimes( double TimePerVMRequestVBlank[], double TimePerVMRequestFlip[]) { + (void)dpte_row_width_luma_ub; + (void)dpte_row_width_chroma_ub; int num_group_per_lower_vm_stage; int num_req_per_lower_vm_stage; int k; @@ -6350,6 +6370,8 @@ static void CalculateStutterEfficiency( int *Z8NumberOfStutterBurstsPerFrame, double *StutterPeriod) { + (void)ConfigReturnBufferSizeInKByte; + struct vba_vars_st *v = &mode_lib->vba; double DETBufferingTimeY; @@ -6649,6 +6671,7 @@ static void CalculateSwathAndDETConfiguration( bool ViewportSizeSupportPerPlane[], bool *ViewportSizeSupport) { + (void)HRatioChroma; int MaximumSwathHeightY[DC__NUM_DPP__MAX]; int MaximumSwathHeightC[DC__NUM_DPP__MAX]; int MinimumSwathHeightY; @@ -6823,6 +6846,7 @@ static void CalculateSwathWidth( int swath_width_luma_ub[], int swath_width_chroma_ub[]) { + (void)BytePerPixY; enum odm_combine_mode MainPlaneODMCombine; int j, k; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c index bfeb01477f0c..dfa1bc31eb0a 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c @@ -51,6 +51,7 @@ static double get_refcyc_per_delivery( unsigned int delivery_width, unsigned int req_per_swath_ub) { + (void)mode_lib; double refcyc_per_delivery = 0.0; if (vratio <= 1.0) { @@ -785,6 +786,7 @@ static void calculate_ttu_cursor( unsigned int cur_width, enum cursor_bpp cur_bpp) { + (void)mode_lib; unsigned int cur_src_width = cur_width; unsigned int cur_req_size = 0; unsigned int cur_req_width = 0; @@ -859,6 +861,12 @@ static void dml_rq_dlg_get_dlg_params( const bool ignore_viewport_pos, const bool immediate_flip_support) { + (void)cstate_en; + (void)pstate_en; + (void)vm_en; + (void)ignore_viewport_pos; + (void)immediate_flip_support; + (void)dlg_sys_param; const display_pipe_source_params_st *src = &e2e_pipe_param[pipe_idx].pipe.src; const display_pipe_dest_params_st *dst = &e2e_pipe_param[pipe_idx].pipe.dest; const display_clocks_and_cfg_st *clks = &e2e_pipe_param[pipe_idx].clks_cfg; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c index df9d50b9b57c..ab016c294ba7 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c @@ -391,13 +391,9 @@ int dcn314_populate_dml_pipes_from_context_fpu(struct dc *dc, struct dc_state *c } context->bw_ctx.dml.ip.det_buffer_size_kbytes = DCN3_14_DEFAULT_DET_SIZE; - dc->config.enable_4to1MPC = false; if (pipe_cnt == 1 && pipe->plane_state && pipe->plane_state->rotation == ROTATION_ANGLE_0 && !dc->debug.disable_z9_mpc) { - if (is_dual_plane(pipe->plane_state->format) - && pipe->plane_state->src_rect.width <= 1920 && pipe->plane_state->src_rect.height <= 1080) { - dc->config.enable_4to1MPC = true; - } else if (!is_dual_plane(pipe->plane_state->format) && pipe->plane_state->src_rect.width <= 5120) { + if (!is_dual_plane(pipe->plane_state->format) && pipe->plane_state->src_rect.width <= 5120) { /* Limit to 5k max to avoid forced pipe split when there is not enough detile for swath */ context->bw_ctx.dml.ip.det_buffer_size_kbytes = 192; pipes[0].pipe.src.unbounded_req_mode = true; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c index 9f3938a50240..033fde774337 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c @@ -891,6 +891,11 @@ static bool CalculatePrefetchSchedule( double *VUpdateWidthPix, double *VReadyOffsetPix) { + (void)mode_lib; + (void)HostVMMinPageSize; + (void)SwathWidthY; + (void)SwathWidthC; + bool MyError = false; unsigned int DPPCycles, DISPCLKCycles; double DSTTotalPixelsAfterScaler; @@ -1508,6 +1513,10 @@ static void CalculateDCCConfiguration( unsigned int *IndependentBlockLuma, unsigned int *IndependentBlockChroma) { + (void)SurfaceWidthChroma; + (void)SurfaceHeightChroma; + (void)BytePerPixelDETY; + (void)BytePerPixelDETC; int yuv420; int horz_div_l; int horz_div_c; @@ -1840,6 +1849,7 @@ static unsigned int CalculateVMAndRowBytes( int *DPDE0BytesFrame, int *MetaPTEBytesFrame) { + (void)SourcePixelFormat; struct vba_vars_st *v = &mode_lib->vba; unsigned int MPDEBytesFrame; unsigned int DCCMetaSurfaceBytes; @@ -3471,6 +3481,8 @@ double dml314_CalculateWriteBackDISPCLK( unsigned int HTotal, unsigned int WritebackLineBufferSize) { + (void)WritebackPixelFormat; + (void)WritebackVRatio; double DISPCLK_H, DISPCLK_V, DISPCLK_HB; DISPCLK_H = PixelClock * dml_ceil(WritebackHTaps / 8.0, 1) / WritebackHRatio; @@ -3489,6 +3501,8 @@ static double CalculateWriteBackDelay( int WritebackSourceHeight, unsigned int HTotal) { + (void)WritebackPixelFormat; + (void)WritebackHRatio; double CalculateWriteBackDelay; double Line_length; double Output_lines_last_notclamped; @@ -5660,6 +5674,9 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport( double *Z8StutterExitWatermark, double *Z8StutterEnterPlusExitWatermark) { + (void)DCFCLK; + (void)ReturnBW; + (void)DETBufferSizeC; struct vba_vars_st *v = &mode_lib->vba; double EffectiveLBLatencyHidingY; double EffectiveLBLatencyHidingC; @@ -5925,6 +5942,7 @@ static void CalculateUrgentBurstFactor( double *UrgentBurstFactorChroma, bool *NotEnoughUrgentLatencyHiding) { + (void)VRatioC; double LinesInDETLuma; double LinesInDETChroma; unsigned int LinesInCursorBuffer; @@ -6308,6 +6326,8 @@ static void CalculateVMGroupAndRequestTimes( double TimePerVMRequestVBlank[], double TimePerVMRequestFlip[]) { + (void)dpte_row_width_luma_ub; + (void)dpte_row_width_chroma_ub; int num_group_per_lower_vm_stage; int num_req_per_lower_vm_stage; int k; @@ -6445,6 +6465,8 @@ static void CalculateStutterEfficiency( int *Z8NumberOfStutterBurstsPerFrame, double *StutterPeriod) { + (void)ConfigReturnBufferSizeInKByte; + struct vba_vars_st *v = &mode_lib->vba; double DETBufferingTimeY; @@ -6743,6 +6765,7 @@ static void CalculateSwathAndDETConfiguration( bool ViewportSizeSupportPerPlane[], bool *ViewportSizeSupport) { + (void)HRatioChroma; int MaximumSwathHeightY[DC__NUM_DPP__MAX]; int MaximumSwathHeightC[DC__NUM_DPP__MAX]; int MinimumSwathHeightY; @@ -6914,6 +6937,7 @@ static void CalculateSwathWidth( int swath_width_luma_ub[], int swath_width_chroma_ub[]) { + (void)BytePerPixY; enum odm_combine_mode MainPlaneODMCombine; int j, k; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_rq_dlg_calc_314.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_rq_dlg_calc_314.c index 04df263ff65e..40a916c2a9c6 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_rq_dlg_calc_314.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_rq_dlg_calc_314.c @@ -139,6 +139,7 @@ static double get_refcyc_per_delivery( unsigned int delivery_width, unsigned int req_per_swath_ub) { + (void)mode_lib; double refcyc_per_delivery = 0.0; if (vratio <= 1.0) { @@ -872,6 +873,7 @@ static void calculate_ttu_cursor( unsigned int cur_width, enum cursor_bpp cur_bpp) { + (void)mode_lib; unsigned int cur_src_width = cur_width; unsigned int cur_req_size = 0; unsigned int cur_req_width = 0; @@ -944,6 +946,12 @@ static void dml_rq_dlg_get_dlg_params( const bool ignore_viewport_pos, const bool immediate_flip_support) { + (void)cstate_en; + (void)pstate_en; + (void)vm_en; + (void)ignore_viewport_pos; + (void)immediate_flip_support; + (void)dlg_sys_param; const display_pipe_source_params_st *src = &e2e_pipe_param[pipe_idx].pipe.src; const display_pipe_dest_params_st *dst = &e2e_pipe_param[pipe_idx].pipe.dest; const display_clocks_and_cfg_st *clks = &e2e_pipe_param[pipe_idx].clks_cfg; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c index 8a0f128722b0..e29497204df7 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c @@ -3488,6 +3488,7 @@ bool dcn32_allow_subvp_high_refresh_rate(struct dc *dc, struct dc_state *context */ double dcn32_determine_max_vratio_prefetch(struct dc *dc, struct dc_state *context) { + (void)dc; double max_vratio_pre = __DML_MAX_BW_RATIO_PRE__; // Default value is 4 int i; @@ -3593,6 +3594,7 @@ bool dcn32_find_vactive_pipe(struct dc *dc, const struct dc_state *context, stru void dcn32_set_clock_limits(const struct _vcs_dpi_soc_bounding_box_st *soc_bb) { + (void)soc_bb; dc_assert_fp_enabled(); dcn3_2_soc.clock_limits[0].dcfclk_mhz = 1200.0; } diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c index 0748ef36a16a..5e72966a8daf 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c @@ -457,10 +457,11 @@ void dml32_CalculateSwathAndDETConfiguration( bool ViewportSizeSupportPerSurface[], bool *ViewportSizeSupport) { + (void)HRatioChroma; unsigned int MaximumSwathHeightY[DC__NUM_DPP__MAX]; unsigned int MaximumSwathHeightC[DC__NUM_DPP__MAX]; - unsigned int RoundedUpMaxSwathSizeBytesY[DC__NUM_DPP__MAX]; - unsigned int RoundedUpMaxSwathSizeBytesC[DC__NUM_DPP__MAX]; + unsigned int RoundedUpMaxSwathSizeBytesY[DC__NUM_DPP__MAX] = { 0 }; + unsigned int RoundedUpMaxSwathSizeBytesC[DC__NUM_DPP__MAX] = { 0 }; unsigned int RoundedUpSwathSizeBytesY; unsigned int RoundedUpSwathSizeBytesC; double SwathWidthdoubleDPP[DC__NUM_DPP__MAX]; @@ -716,6 +717,7 @@ void dml32_CalculateSwathWidth( unsigned int swath_width_luma_ub[], // per-pipe unsigned int swath_width_chroma_ub[]) // per-pipe { + (void)BytePerPixY; unsigned int k, j; enum odm_combine_mode MainSurfaceODMMode; @@ -2304,6 +2306,7 @@ unsigned int dml32_CalculateVMAndRowBytes( unsigned int *DPDE0BytesFrame, unsigned int *MetaPTEBytesFrame) { + (void)SourcePixelFormat; unsigned int MPDEBytesFrame; unsigned int DCCMetaSurfaceBytes; unsigned int ExtraDPDEBytesFrame; @@ -2745,6 +2748,7 @@ void dml32_CalculateUrgentBurstFactor( double *UrgentBurstFactorChroma, bool *NotEnoughUrgentLatencyHiding) { + (void)VRatioC; double LinesInDETLuma; double LinesInDETChroma; unsigned int LinesInCursorBuffer; @@ -2900,6 +2904,8 @@ double dml32_CalculateWriteBackDelay( unsigned int WritebackSourceHeight, unsigned int HTotal) { + (void)WritebackPixelFormat; + (void)WritebackHRatio; double CalculateWriteBackDelay; double Line_length; double Output_lines_last_notclamped; @@ -2977,6 +2983,9 @@ void dml32_UseMinimumDCFCLK( /* Output */ double DCFCLKState[][2]) { + (void)MaxAveragePercentOfIdealSDPPortBWDisplayCanUseInNormalSystemOperation; + (void)ReadBandwidthLuma; + (void)ReadBandwidthChroma; unsigned int i, j, k; unsigned int dummy1; double dummy2, dummy3; @@ -2988,7 +2997,7 @@ void dml32_UseMinimumDCFCLK( for (j = 0; j <= 1; ++j) { double PixelDCFCLKCyclesRequiredInPrefetch[DC__NUM_DPP__MAX]; double PrefetchPixelLinesTime[DC__NUM_DPP__MAX]; - double DCFCLKRequiredForPeakBandwidthPerSurface[DC__NUM_DPP__MAX]; + double DCFCLKRequiredForPeakBandwidthPerSurface[DC__NUM_DPP__MAX] = { 0 }; double DynamicMetadataVMExtraLatency[DC__NUM_DPP__MAX]; double MinimumTWait = 0.0; double DPTEBandwidth; @@ -3447,6 +3456,8 @@ bool dml32_CalculatePrefetchSchedule( double *VUpdateWidthPix, double *VReadyOffsetPix) { + (void)SwathWidthY; + (void)SwathWidthC; double DPPCLKDelaySubtotalPlusCNVCFormater = v->DPPCLKDelaySubtotal + v->DPPCLKDelayCNVCFormater; bool MyError = false; unsigned int DPPCycles, DISPCLKCycles; @@ -4145,6 +4156,7 @@ void dml32_CalculateFlipSchedule( double *final_flip_bw, bool *ImmediateFlipSupportedForPipe) { + (void)HostVMMinPageSize; double min_row_time = 0.0; unsigned int HostVMDynamicLevelsTrips; double TimeForFetchingMetaPTEImmediateFlip; @@ -4287,6 +4299,8 @@ void dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport( bool *USRRetrainingSupport, double ActiveDRAMClockChangeLatencyMargin[]) { + (void)DCFCLK; + (void)ReturnBW; unsigned int i, j, k; unsigned int SurfaceWithMinActiveFCLKChangeMargin = 0; unsigned int DRAMClockChangeSupportNumber = 0; @@ -4655,6 +4669,8 @@ double dml32_CalculateWriteBackDISPCLK( unsigned int WritebackLineBufferSize, double DISPCLKDPPCLKVCOSpeed) { + (void)WritebackPixelFormat; + (void)WritebackVRatio; double DISPCLK_H, DISPCLK_V, DISPCLK_HB; DISPCLK_H = PixelClock * dml_ceil(WritebackHTaps / 8.0, 1) / WritebackHRatio; @@ -5166,6 +5182,8 @@ void dml32_CalculateVMGroupAndRequestTimes( double TimePerVMRequestVBlank[], double TimePerVMRequestFlip[]) { + (void)dpte_row_width_luma_ub; + (void)dpte_row_width_chroma_ub; unsigned int k; unsigned int num_group_per_lower_vm_stage; unsigned int num_req_per_lower_vm_stage; @@ -5321,6 +5339,11 @@ void dml32_CalculateDCCConfiguration( unsigned int *IndependentBlockLuma, unsigned int *IndependentBlockChroma) { + (void)SurfaceWidthChroma; + (void)SurfaceHeightChroma; + (void)TilingFormat; + (void)BytePerPixelDETY; + (void)BytePerPixelDETC; typedef enum { REQ_256Bytes, REQ_128BytesNonContiguous, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c index 8a177d5ae213..7f40048dd67d 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c @@ -202,6 +202,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_5_soc = { void dcn35_build_wm_range_table_fpu(struct clk_mgr *clk_mgr) { + (void)clk_mgr; //TODO } @@ -528,14 +529,9 @@ int dcn35_populate_dml_pipes_from_context_fpu(struct dc *dc, } context->bw_ctx.dml.ip.det_buffer_size_kbytes = 384;/*per guide*/ - dc->config.enable_4to1MPC = false; if (pipe_cnt == 1 && pipe->plane_state && !dc->debug.disable_z9_mpc) { - if (is_dual_plane(pipe->plane_state->format) - && pipe->plane_state->src_rect.width <= 1920 && - pipe->plane_state->src_rect.height <= 1080) { - dc->config.enable_4to1MPC = true; - } else if (!is_dual_plane(pipe->plane_state->format) && + if (!is_dual_plane(pipe->plane_state->format) && pipe->plane_state->src_rect.width <= 5120) { /* * Limit to 5k max to avoid forced pipe split when there diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c index 77023b619f1e..73c2aee57f28 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c @@ -561,14 +561,9 @@ int dcn351_populate_dml_pipes_from_context_fpu(struct dc *dc, } context->bw_ctx.dml.ip.det_buffer_size_kbytes = 384;/*per guide*/ - dc->config.enable_4to1MPC = false; if (pipe_cnt == 1 && pipe->plane_state && !dc->debug.disable_z9_mpc) { - if (is_dual_plane(pipe->plane_state->format) - && pipe->plane_state->src_rect.width <= 1920 && - pipe->plane_state->src_rect.height <= 1080) { - dc->config.enable_4to1MPC = true; - } else if (!is_dual_plane(pipe->plane_state->format) && + if (!is_dual_plane(pipe->plane_state->format) && pipe->plane_state->src_rect.width <= 5120) { /* * Limit to 5k max to avoid forced pipe split when there diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c index da0cfbb071e6..684779ee54a3 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c @@ -162,6 +162,7 @@ void dml_log_pipe_params( display_e2e_pipe_params_st *pipes, int pipe_cnt) { + (void)mode_lib; display_pipe_source_params_st *pipe_src; display_pipe_dest_params_st *pipe_dest; scaler_ratio_depth_st *scale_ratio_depth; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c index 12ff65b6a7e5..3f27293a41cb 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c @@ -49,6 +49,8 @@ void print__rq_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dp void print__data_rq_sizing_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_data_rq_sizing_params_st *rq_sizing) { + (void)mode_lib; + (void)rq_sizing; dml_print("DML_RQ_DLG_CALC: =====================================\n"); dml_print("DML_RQ_DLG_CALC: DISPLAY_DATA_RQ_SIZING_PARAM_ST\n"); dml_print("DML_RQ_DLG_CALC: chunk_bytes = %0d\n", rq_sizing->chunk_bytes); @@ -64,6 +66,8 @@ void print__data_rq_sizing_params_st(struct display_mode_lib *mode_lib, const st void print__data_rq_dlg_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_data_rq_dlg_params_st *rq_dlg_param) { + (void)mode_lib; + (void)rq_dlg_param; dml_print("DML_RQ_DLG_CALC: =====================================\n"); dml_print("DML_RQ_DLG_CALC: DISPLAY_DATA_RQ_DLG_PARAM_ST\n"); dml_print( @@ -107,6 +111,8 @@ void print__data_rq_dlg_params_st(struct display_mode_lib *mode_lib, const struc void print__data_rq_misc_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_data_rq_misc_params_st *rq_misc_param) { + (void)mode_lib; + (void)rq_misc_param; dml_print("DML_RQ_DLG_CALC: =====================================\n"); dml_print("DML_RQ_DLG_CALC: DISPLAY_DATA_RQ_MISC_PARAM_ST\n"); dml_print( @@ -124,6 +130,8 @@ void print__data_rq_misc_params_st(struct display_mode_lib *mode_lib, const stru void print__dlg_sys_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_dlg_sys_params_st *dlg_sys_param) { + (void)dlg_sys_param; + (void)mode_lib; dml_print("DML_RQ_DLG_CALC: =====================================\n"); dml_print("DML_RQ_DLG_CALC: DISPLAY_RQ_DLG_PARAM_ST\n"); dml_print("DML_RQ_DLG_CALC: t_mclk_wm_us = %3.2f\n", dlg_sys_param->t_mclk_wm_us); @@ -144,6 +152,8 @@ void print__dlg_sys_params_st(struct display_mode_lib *mode_lib, const struct _v void print__data_rq_regs_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_data_rq_regs_st *rq_regs) { + (void)mode_lib; + (void)rq_regs; dml_print("DML_RQ_DLG_CALC: =====================================\n"); dml_print("DML_RQ_DLG_CALC: DISPLAY_DATA_RQ_REGS_ST\n"); dml_print("DML_RQ_DLG_CALC: chunk_size = 0x%0x\n", rq_regs->chunk_size); @@ -179,6 +189,8 @@ void print__rq_regs_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_ void print__dlg_regs_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_dlg_regs_st *dlg_regs) { + (void)dlg_regs; + (void)mode_lib; dml_print("DML_RQ_DLG_CALC: =====================================\n"); dml_print("DML_RQ_DLG_CALC: DISPLAY_DLG_REGS_ST\n"); dml_print( @@ -316,6 +328,8 @@ void print__dlg_regs_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi void print__ttu_regs_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_ttu_regs_st *ttu_regs) { + (void)mode_lib; + (void)ttu_regs; dml_print("DML_RQ_DLG_CALC: =====================================\n"); dml_print("DML_RQ_DLG_CALC: DISPLAY_TTU_REGS_ST\n"); dml_print( diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c index 88dc2b97e7bf..cf194bcba455 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c @@ -104,6 +104,7 @@ static double get_refcyc_per_delivery( unsigned int delivery_width, unsigned int req_per_swath_ub) { + (void)mode_lib; double refcyc_per_delivery = 0.0; if (vratio <= 1.0) { @@ -133,6 +134,7 @@ static double get_vratio_pre( double vinit, double l_sw) { + (void)mode_lib; double prefill = dml_floor(vinit, 1); double vratio_pre = 1.0; @@ -174,6 +176,7 @@ static void get_swath_need( unsigned int swath_height, double vinit) { + (void)mode_lib; double prefill = dml_floor(vinit, 1); unsigned int max_partial_sw_int; diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/Makefile b/drivers/gpu/drm/amd/display/dc/dml2_0/Makefile index 30cfc0848792..2625943d7f7e 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/Makefile @@ -53,25 +53,29 @@ subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dml2_0/dml21/src/inc subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dml2_0/dml21/inc subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dml2_0/dml21/ -CFLAGS_$(AMDDALPATH)/dc/dml2_0/display_mode_core.o := $(dml2_ccflags) $(frame_warn_flag) -CFLAGS_$(AMDDALPATH)/dc/dml2_0/display_mode_util.o := $(dml2_ccflags) -CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_wrapper_fpu.o := $(dml2_ccflags) -CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_utils.o := $(dml2_ccflags) -CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_policy.o := $(dml2_ccflags) -CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_translation_helper.o := $(dml2_ccflags) -CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_mall_phantom.o := $(dml2_ccflags) -CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml_display_rq_dlg_calc.o := $(dml2_ccflags) -CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_dc_resource_mgmt.o := $(dml2_ccflags) +# Add FPU flags to all dml2 files by default, remove NO_FPU flags. +# FPU flags step 1: Find all .c files in dal/dc/dml2_0 and it's subfolders +DML2_ABS_PATH := $(FULL_AMD_DISPLAY_PATH)/dc/dml2_0 +DML2_C_FILES := $(shell find $(DML2_ABS_PATH) -name '*.c' -type f) + +# FPU flags step 2: Convert to .o and make paths relative to $(AMDDALPATH)/dc/dml2_0/ +DML2_RELATIVE_O_FILES := $(patsubst $(DML2_ABS_PATH)/%,dc/dml2_0/%,$(patsubst %.c,%.o,$(DML2_C_FILES))) +# FPU flags step 3: Apply FPU flags to all .o files from dal/dc/dml2_0 and it's subfolders +$(foreach obj,$(DML2_RELATIVE_O_FILES),$(eval CFLAGS_$(AMDDALPATH)/$(obj) := $(dml2_ccflags))) +$(foreach obj,$(DML2_RELATIVE_O_FILES),$(eval CFLAGS_REMOVE_$(AMDDALPATH)/$(obj) := $(dml2_rcflags))) + +# FPU flags step 4: Replace CFLAGS per file for files with additional flags beyond dml2_ccflags and dml2_rcflags +CFLAGS_$(AMDDALPATH)/dc/dml2_0/display_mode_core.o := $(dml2_ccflags) $(frame_warn_flag) +CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.o := $(dml2_ccflags) $(frame_warn_flag) +CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.o := $(dml2_ccflags) $(frame_warn_flag) +CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_wrapper.o := $(dml2_rcflags) +CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/dml21_wrapper.o := $(dml2_rcflags) CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/display_mode_core.o := $(dml2_rcflags) -CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/display_mode_util.o := $(dml2_rcflags) -CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_wrapper_fpu.o := $(dml2_rcflags) -CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_utils.o := $(dml2_rcflags) -CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_policy.o := $(dml2_rcflags) -CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_translation_helper.o := $(dml2_rcflags) -CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_mall_phantom.o := $(dml2_rcflags) -CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml_display_rq_dlg_calc.o := $(dml2_rcflags) -CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_dc_resource_mgmt.o := $(dml2_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.o := $(dml2_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.o := $(dml2_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_wrapper.o := $(dml2_ccflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/dml21_wrapper.o := $(dml2_ccflags) DML2 = display_mode_core.o display_mode_util.o dml2_wrapper_fpu.o dml2_wrapper.o \ dml2_utils.o dml2_policy.o dml2_translation_helper.o dml2_dc_resource_mgmt.o dml2_mall_phantom.o \ @@ -81,39 +85,6 @@ AMD_DAL_DML2 = $(addprefix $(AMDDALPATH)/dc/dml2_0/,$(DML2)) AMD_DISPLAY_FILES += $(AMD_DAL_DML2) -CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.o := $(dml2_ccflags) -CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.o := $(dml2_ccflags) $(frame_warn_flag) -CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.o := $(dml2_ccflags) $(frame_warn_flag) -CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_top/dml2_top_interfaces.o := $(dml2_ccflags) -CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_top/dml2_top_soc15.o := $(dml2_ccflags) -CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.o := $(dml2_ccflags) -CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.o := $(dml2_ccflags) -CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.o := $(dml2_ccflags) -CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.o := $(dml2_ccflags) -CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.o := $(dml2_ccflags) -CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn3.o := $(dml2_ccflags) -CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.o := $(dml2_ccflags) -CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.o := $(dml2_ccflags) -CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_standalone_libraries/lib_float_math.o := $(dml2_ccflags) -CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/dml21_translation_helper.o := $(dml2_ccflags) -CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/dml21_utils.o := $(dml2_ccflags) - -CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.o := $(dml2_rcflags) -CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.o := $(dml2_rcflags) -CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.o := $(dml2_rcflags) -CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.o := $(dml2_rcflags) -CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_top/dml2_top_interfaces.o := $(dml2_rcflags) -CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_top/dml2_top_soc15.o := $(dml2_rcflags) -CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.o := $(dml2_rcflags) -CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.o := $(dml2_rcflags) -CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.o := $(dml2_rcflags) -CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.o := $(dml2_rcflags) -CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn3.o := $(dml2_rcflags) -CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.o := $(dml2_rcflags) -CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.o := $(dml2_rcflags) -CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_standalone_libraries/lib_float_math.o := $(dml2_rcflags) -CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/dml21_translation_helper.o := $(dml2_rcflags) -CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/dml21_utils.o := $(dml2_rcflags) DML21 := src/dml2_top/dml2_top_interfaces.o DML21 += src/dml2_top/dml2_top_soc15.o @@ -124,6 +95,7 @@ DML21 += src/dml2_core/dml2_core_dcn4_calcs.o DML21 += src/dml2_dpmm/dml2_dpmm_dcn4.o DML21 += src/dml2_dpmm/dml2_dpmm_factory.o DML21 += src/dml2_mcg/dml2_mcg_dcn4.o +DML21 += src/dml2_mcg/dml2_mcg_dcn42.o DML21 += src/dml2_mcg/dml2_mcg_factory.o DML21 += src/dml2_pmo/dml2_pmo_dcn3.o DML21 += src/dml2_pmo/dml2_pmo_factory.o @@ -131,6 +103,7 @@ DML21 += src/dml2_pmo/dml2_pmo_dcn4_fams2.o DML21 += src/dml2_standalone_libraries/lib_float_math.o DML21 += dml21_translation_helper.o DML21 += dml21_wrapper.o +DML21 += dml21_wrapper_fpu.o DML21 += dml21_utils.o AMD_DAL_DML21 = $(addprefix $(AMDDALPATH)/dc/dml2_0/dml21/,$(DML21)) diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/display_mode_core.c b/drivers/gpu/drm/amd/display/dc/dml2_0/display_mode_core.c index 09303c282495..8e8935995fca 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/display_mode_core.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/display_mode_core.c @@ -4089,8 +4089,8 @@ static void CalculateSwathAndDETConfiguration(struct display_mode_lib_scratch_st dml_uint_t MaximumSwathHeightC[__DML_NUM_PLANES__]; dml_uint_t RoundedUpMaxSwathSizeBytesY[__DML_NUM_PLANES__]; dml_uint_t RoundedUpMaxSwathSizeBytesC[__DML_NUM_PLANES__]; - dml_uint_t RoundedUpSwathSizeBytesY[__DML_NUM_PLANES__]; - dml_uint_t RoundedUpSwathSizeBytesC[__DML_NUM_PLANES__]; + dml_uint_t RoundedUpSwathSizeBytesY[__DML_NUM_PLANES__] = { 0 }; + dml_uint_t RoundedUpSwathSizeBytesC[__DML_NUM_PLANES__] = { 0 }; dml_uint_t SwathWidthSingleDPP[__DML_NUM_PLANES__]; dml_uint_t SwathWidthSingleDPPChroma[__DML_NUM_PLANES__]; diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c index bf5e7f4e0416..2f0e0048bea8 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c @@ -45,6 +45,9 @@ static enum dml2_project_id dml21_dcn_revision_to_dml2_project_id(enum dce_versi case DCN_VERSION_4_01: project_id = dml2_project_dcn4x_stage2_auto_drr_svp; break; + case DCN_VERSION_4_2: + project_id = dml2_project_dcn42; + break; default: project_id = dml2_project_invalid; DC_ERR("unsupported dcn version for DML21!"); @@ -87,7 +90,8 @@ static void populate_dml21_timing_config_from_stream_state(struct dml2_timing_cf struct pipe_ctx *pipe_ctx, struct dml2_context *dml_ctx) { - unsigned int hblank_start, vblank_start, min_hardware_refresh_in_uhz; + unsigned int hblank_start, vblank_start; + uint64_t min_hardware_refresh_in_uhz; uint32_t pix_clk_100hz; timing->h_active = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right + pipe_ctx->dsc_padding_params.dsc_hactive_padding; @@ -102,7 +106,7 @@ static void populate_dml21_timing_config_from_stream_state(struct dml2_timing_cf timing->h_total = stream->timing.h_total + pipe_ctx->dsc_padding_params.dsc_htotal_padding; timing->v_total = stream->timing.v_total; timing->h_sync_width = stream->timing.h_sync_width; - timing->interlaced = stream->timing.flags.INTERLACE; + timing->interlaced = (stream->timing.flags.INTERLACE != 0); hblank_start = stream->timing.h_total - stream->timing.h_front_porch; @@ -134,7 +138,11 @@ static void populate_dml21_timing_config_from_stream_state(struct dml2_timing_cf (timing->h_total * (long long)calc_max_hardware_v_total(stream))); } - timing->drr_config.min_refresh_uhz = max(stream->timing.min_refresh_in_uhz, min_hardware_refresh_in_uhz); + { + uint64_t min_refresh = max((uint64_t)stream->timing.min_refresh_in_uhz, min_hardware_refresh_in_uhz); + ASSERT(min_refresh <= ULONG_MAX); + timing->drr_config.min_refresh_uhz = (unsigned long)min_refresh; + } if (dml_ctx->config.callbacks.get_max_flickerless_instant_vtotal_increase && stream->ctx->dc->config.enable_fpo_flicker_detection == 1) @@ -615,12 +623,20 @@ static void populate_dml21_plane_config_from_plane_state(struct dml2_context *dm case DC_CM2_GPU_MEM_SIZE_171717: plane->tdlut.tdlut_width_mode = dml2_tdlut_width_17_cube; break; + case DC_CM2_GPU_MEM_SIZE_333333: + plane->tdlut.tdlut_width_mode = dml2_tdlut_width_33_cube; + break; + // handling when use case and HW support available + case DC_CM2_GPU_MEM_SIZE_454545: + case DC_CM2_GPU_MEM_SIZE_656565: + break; case DC_CM2_GPU_MEM_SIZE_TRANSFORMED: default: //plane->tdlut.tdlut_width_mode = dml2_tdlut_width_flatten; // dml2_tdlut_width_flatten undefined break; } } + plane->tdlut.setup_for_tdlut |= dml_ctx->config.force_tdlut_enable; plane->dynamic_meta_data.enable = false; @@ -686,7 +702,7 @@ unsigned int map_plane_to_dml21_display_cfg(const struct dml2_context *dml_ctx, if (!dml21_wrapper_get_plane_id(context, stream_id, plane, &plane_id)) { ASSERT(false); - return -1; + return UINT_MAX; } for (i = 0; i < __DML2_WRAPPER_MAX_STREAMS_PLANES__; i++) { @@ -734,8 +750,12 @@ bool dml21_map_dc_state_into_dml_display_cfg(const struct dc *in_dc, struct dc_s memset(&dml_ctx->v21.dml_to_dc_pipe_mapping, 0, sizeof(struct dml2_dml_to_dc_pipe_mapping)); dml_dispcfg->gpuvm_enable = dml_ctx->config.gpuvm_enable; - dml_dispcfg->gpuvm_max_page_table_levels = 4; - dml_dispcfg->hostvm_enable = false; + if (dml_ctx->v21.dml_init.soc_bb.gpuvm_max_page_table_levels) + dml_dispcfg->gpuvm_max_page_table_levels = dml_ctx->v21.dml_init.soc_bb.gpuvm_max_page_table_levels; + else + dml_dispcfg->gpuvm_max_page_table_levels = 4; + dml_dispcfg->hostvm_enable = dml_ctx->config.hostvm_enable; + dml_dispcfg->hostvm_max_non_cached_page_table_levels = dml_ctx->v21.dml_init.soc_bb.hostvm_max_non_cached_page_table_levels; dml_dispcfg->minimize_det_reallocation = true; dml_dispcfg->overrides.enable_subvp_implicit_pmo = true; @@ -820,6 +840,9 @@ void dml21_copy_clocks_to_dc_state(struct dml2_context *in_ctx, struct dc_state context->bw_ctx.bw.dcn.clk.subvp_prefetch_fclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.svp_prefetch_no_throttle.fclk_khz; context->bw_ctx.bw.dcn.clk.stutter_efficiency.base_efficiency = in_ctx->v21.mode_programming.programming->stutter.base_percent_efficiency; context->bw_ctx.bw.dcn.clk.stutter_efficiency.low_power_efficiency = in_ctx->v21.mode_programming.programming->stutter.low_power_percent_efficiency; + context->bw_ctx.bw.dcn.clk.stutter_efficiency.z8_stutter_efficiency = in_ctx->v21.mode_programming.programming->informative.power_management.z8.stutter_efficiency; + context->bw_ctx.bw.dcn.clk.stutter_efficiency.z8_stutter_period = in_ctx->v21.mode_programming.programming->informative.power_management.z8.stutter_period; + context->bw_ctx.bw.dcn.clk.zstate_support = in_ctx->v21.mode_programming.programming->z8_stutter.supported_in_blank; /*ignore meets_eco since it is not used*/ } static struct dml2_dchub_watermark_regs *wm_set_index_to_dc_wm_set(union dcn_watermark_set *watermarks, const enum dml2_dchub_watermark_reg_set_index wm_index) @@ -927,3 +950,31 @@ void dml21_set_dc_p_state_type( } } +void dml21_init_min_clocks_for_dc_state(struct dml2_context *in_ctx, struct dc_state *context) +{ + unsigned int lowest_dpm_state_index = 0; + struct dc_clocks *min_clocks = &context->bw_ctx.bw.dcn.clk; + + min_clocks->dispclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.clk_values_khz[lowest_dpm_state_index]; + min_clocks->dppclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.clk_values_khz[lowest_dpm_state_index]; + min_clocks->dcfclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dcfclk.clk_values_khz[lowest_dpm_state_index]; + min_clocks->dramclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.uclk.clk_values_khz[lowest_dpm_state_index]; + min_clocks->fclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.fclk.clk_values_khz[lowest_dpm_state_index]; + min_clocks->idle_dramclk_khz = 0; + min_clocks->idle_fclk_khz = 0; + min_clocks->dcfclk_deep_sleep_khz = 0; + min_clocks->fclk_p_state_change_support = true; + min_clocks->p_state_change_support = true; + min_clocks->dtbclk_en = false; + min_clocks->ref_dtbclk_khz = 0; + min_clocks->socclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.socclk.clk_values_khz[lowest_dpm_state_index]; + min_clocks->subvp_prefetch_dramclk_khz = 0; + min_clocks->subvp_prefetch_fclk_khz = 0; + min_clocks->phyclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.phyclk.clk_values_khz[lowest_dpm_state_index]; + min_clocks->stutter_efficiency.base_efficiency = 1; + min_clocks->stutter_efficiency.low_power_efficiency = 1; + min_clocks->stutter_efficiency.z8_stutter_efficiency = 1; + min_clocks->stutter_efficiency.z8_stutter_period = 100000; + min_clocks->zstate_support = DCN_ZSTATE_SUPPORT_ALLOW; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.h index 9880d3e0398e..f51d3d8a52c3 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.h +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.h @@ -25,4 +25,5 @@ void dml21_map_hw_resources(struct dml2_context *dml_ctx); void dml21_get_pipe_mcache_config(struct dc_state *context, struct pipe_ctx *pipe_ctx, struct dml2_per_plane_programming *pln_prog, struct dml2_pipe_configuration_descriptor *mcache_pipe_config); void dml21_set_dc_p_state_type(struct pipe_ctx *pipe_ctx, struct dml2_per_stream_programming *stream_programming, bool sub_vp_enabled); unsigned int map_plane_to_dml21_display_cfg(const struct dml2_context *dml_ctx, unsigned int stream_id, const struct dc_plane_state *plane, const struct dc_state *context); +void dml21_init_min_clocks_for_dc_state(struct dml2_context *in_ctx, struct dc_state *context); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.c index f667026cb43e..4724b08c77e1 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.c @@ -374,128 +374,142 @@ void dml21_handle_phantom_streams_planes(const struct dc *dc, struct dc_state *c dml2_map_dc_pipes(dml_ctx, context, NULL, &dml_ctx->v21.dml_to_dc_pipe_mapping, dc->current_state); } -void dml21_build_fams2_programming(const struct dc *dc, + +static unsigned int dml21_build_fams2_stream_programming_v2(const struct dc *dc, struct dc_state *context, struct dml2_context *dml_ctx) { - int i, j, k; + int dc_stream_idx, dc_plane_idx, dc_pipe_idx; unsigned int num_fams2_streams = 0; - /* reset fams2 data */ - memset(&context->bw_ctx.bw.dcn.fams2_stream_base_params, 0, sizeof(union dmub_cmd_fams2_config) * DML2_MAX_PLANES); - memset(&context->bw_ctx.bw.dcn.fams2_stream_sub_params, 0, sizeof(union dmub_cmd_fams2_config) * DML2_MAX_PLANES); - memset(&context->bw_ctx.bw.dcn.fams2_stream_sub_params_v2, 0, sizeof(union dmub_fams2_stream_static_sub_state_v2) * DML2_MAX_PLANES); - memset(&context->bw_ctx.bw.dcn.fams2_global_config, 0, sizeof(struct dmub_cmd_fams2_global_config)); + for (dc_stream_idx = 0; dc_stream_idx < context->stream_count; dc_stream_idx++) { + int dml_stream_idx; + struct dc_stream_state *phantom_stream; + struct dc_stream_status *phantom_status; + enum fams2_stream_type type = 0; - if ((dml_ctx->v21.mode_programming.programming->fams2_required) || - (dml_ctx->v21.mode_programming.programming->legacy_pstate_info_for_dmu)) { - for (i = 0; i < context->stream_count; i++) { - int dml_stream_idx; - struct dc_stream_state *phantom_stream; - struct dc_stream_status *phantom_status; - enum fams2_stream_type type = 0; + union dmub_cmd_fams2_config *static_base_state = &context->bw_ctx.bw.dcn.fams2_stream_base_params[num_fams2_streams]; + union dmub_cmd_fams2_config *static_sub_state = &context->bw_ctx.bw.dcn.fams2_stream_sub_params[num_fams2_streams]; - union dmub_cmd_fams2_config *static_base_state = &context->bw_ctx.bw.dcn.fams2_stream_base_params[num_fams2_streams]; - union dmub_cmd_fams2_config *static_sub_state = &context->bw_ctx.bw.dcn.fams2_stream_sub_params[num_fams2_streams]; + struct dc_stream_state *stream = context->streams[dc_stream_idx]; - struct dc_stream_state *stream = context->streams[i]; + if (context->stream_status[dc_stream_idx].plane_count == 0 || + dml_ctx->config.svp_pstate.callbacks.get_stream_subvp_type(context, stream) == SUBVP_PHANTOM) { + /* can ignore blanked or phantom streams */ + continue; + } - if (context->stream_status[i].plane_count == 0 || - dml_ctx->config.svp_pstate.callbacks.get_stream_subvp_type(context, stream) == SUBVP_PHANTOM) { - /* can ignore blanked or phantom streams */ - continue; - } + dml_stream_idx = dml21_helper_find_dml_pipe_idx_by_stream_id(dml_ctx, stream->stream_id); + if (dml_stream_idx < 0) { + ASSERT(dml_stream_idx >= 0); + continue; + } - dml_stream_idx = dml21_helper_find_dml_pipe_idx_by_stream_id(dml_ctx, stream->stream_id); - if (dml_stream_idx < 0) { - ASSERT(dml_stream_idx >= 0); - continue; + /* copy static state from PMO */ + memcpy(static_base_state, + &dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_base_params, + sizeof(union dmub_cmd_fams2_config)); + + memcpy(static_sub_state, + &dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_sub_params, + sizeof(union dmub_cmd_fams2_config)); + + switch (dc->debug.fams_version.minor) { + case 1: + default: + type = static_base_state->stream_v1.base.type; + + /* get information from context */ + ASSERT(context->stream_status[dc_stream_idx].plane_count >= 0 && + context->stream_status[dc_stream_idx].plane_count <= 0xFF); + ASSERT(context->stream_status[dc_stream_idx].primary_otg_inst >= 0 && + context->stream_status[dc_stream_idx].primary_otg_inst <= 0xFF); + static_base_state->stream_v1.base.num_planes = (uint8_t)context->stream_status[dc_stream_idx].plane_count; + static_base_state->stream_v1.base.otg_inst = (uint8_t)context->stream_status[dc_stream_idx].primary_otg_inst; + + /* populate pipe masks for planes */ + for (dc_plane_idx = 0; dc_plane_idx < context->stream_status[dc_stream_idx].plane_count; dc_plane_idx++) { + for (dc_pipe_idx = 0; dc_pipe_idx < dc->res_pool->pipe_count; dc_pipe_idx++) { + if (context->res_ctx.pipe_ctx[dc_pipe_idx].stream && + context->res_ctx.pipe_ctx[dc_pipe_idx].stream->stream_id == stream->stream_id && + context->res_ctx.pipe_ctx[dc_pipe_idx].plane_state == context->stream_status[dc_stream_idx].plane_states[dc_plane_idx]) { + static_base_state->stream_v1.base.pipe_mask |= (1 << dc_pipe_idx); + static_base_state->stream_v1.base.plane_pipe_masks[dc_plane_idx] |= (1 << dc_pipe_idx); + } + } } + } - /* copy static state from PMO */ - memcpy(static_base_state, - &dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_base_params, - sizeof(union dmub_cmd_fams2_config)); - - if (dc->debug.fams_version.major == 3) { - memcpy(&context->bw_ctx.bw.dcn.fams2_stream_sub_params_v2[num_fams2_streams], - &dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_sub_params_v2, - sizeof(union dmub_fams2_stream_static_sub_state_v2)); - } else { - memcpy(static_sub_state, - &dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_sub_params, - sizeof(union dmub_cmd_fams2_config)); - } + + /* get per method programming */ + switch (type) { + case FAMS2_STREAM_TYPE_VBLANK: + case FAMS2_STREAM_TYPE_VACTIVE: + case FAMS2_STREAM_TYPE_DRR: + break; + case FAMS2_STREAM_TYPE_SUBVP: + phantom_stream = dml_ctx->config.svp_pstate.callbacks.get_paired_subvp_stream(context, stream); + if (!phantom_stream) + break; + + phantom_status = dml_ctx->config.callbacks.get_stream_status(context, phantom_stream); + + /* phantom status should always be present */ + ASSERT(phantom_status); + if (!phantom_status) + break; switch (dc->debug.fams_version.minor) { case 1: default: - type = static_base_state->stream_v1.base.type; - - /* get information from context */ - static_base_state->stream_v1.base.num_planes = context->stream_status[i].plane_count; - static_base_state->stream_v1.base.otg_inst = context->stream_status[i].primary_otg_inst; - - /* populate pipe masks for planes */ - for (j = 0; j < context->stream_status[i].plane_count; j++) { - for (k = 0; k < dc->res_pool->pipe_count; k++) { - if (context->res_ctx.pipe_ctx[k].stream && - context->res_ctx.pipe_ctx[k].stream->stream_id == stream->stream_id && - context->res_ctx.pipe_ctx[k].plane_state == context->stream_status[i].plane_states[j]) { - static_base_state->stream_v1.base.pipe_mask |= (1 << k); - static_base_state->stream_v1.base.plane_pipe_masks[j] |= (1 << k); + ASSERT(phantom_status->primary_otg_inst >= 0 && + phantom_status->primary_otg_inst <= 0xFF); + static_sub_state->stream_v1.sub_state.subvp.phantom_otg_inst = (uint8_t)phantom_status->primary_otg_inst; + + /* populate pipe masks for phantom planes */ + for (dc_plane_idx = 0; dc_plane_idx < phantom_status->plane_count; dc_plane_idx++) { + for (dc_pipe_idx = 0; dc_pipe_idx < dc->res_pool->pipe_count; dc_pipe_idx++) { + if (context->res_ctx.pipe_ctx[dc_pipe_idx].stream && + context->res_ctx.pipe_ctx[dc_pipe_idx].stream->stream_id == phantom_stream->stream_id && + context->res_ctx.pipe_ctx[dc_pipe_idx].plane_state == phantom_status->plane_states[dc_plane_idx]) { + switch (dc->debug.fams_version.minor) { + case 1: + default: + static_sub_state->stream_v1.sub_state.subvp.phantom_pipe_mask |= (1 << dc_pipe_idx); + static_sub_state->stream_v1.sub_state.subvp.phantom_plane_pipe_masks[dc_plane_idx] |= (1 << dc_pipe_idx); + } } } } } + break; + default: + ASSERT(false); + break; + } + num_fams2_streams++; + } - /* get per method programming */ - switch (type) { - case FAMS2_STREAM_TYPE_VBLANK: - case FAMS2_STREAM_TYPE_VACTIVE: - case FAMS2_STREAM_TYPE_DRR: - break; - case FAMS2_STREAM_TYPE_SUBVP: - phantom_stream = dml_ctx->config.svp_pstate.callbacks.get_paired_subvp_stream(context, stream); - if (!phantom_stream) - break; - - phantom_status = dml_ctx->config.callbacks.get_stream_status(context, phantom_stream); - - /* phantom status should always be present */ - ASSERT(phantom_status); - if (!phantom_status) - break; - - switch (dc->debug.fams_version.minor) { - case 1: - default: - static_sub_state->stream_v1.sub_state.subvp.phantom_otg_inst = phantom_status->primary_otg_inst; - - /* populate pipe masks for phantom planes */ - for (j = 0; j < phantom_status->plane_count; j++) { - for (k = 0; k < dc->res_pool->pipe_count; k++) { - if (context->res_ctx.pipe_ctx[k].stream && - context->res_ctx.pipe_ctx[k].stream->stream_id == phantom_stream->stream_id && - context->res_ctx.pipe_ctx[k].plane_state == phantom_status->plane_states[j]) { - switch (dc->debug.fams_version.minor) { - case 1: - default: - static_sub_state->stream_v1.sub_state.subvp.phantom_pipe_mask |= (1 << k); - static_sub_state->stream_v1.sub_state.subvp.phantom_plane_pipe_masks[j] |= (1 << k); - } - } - } - } - } - break; - default: - ASSERT(false); - break; - } + return num_fams2_streams; +} + +void dml21_build_fams2_programming(const struct dc *dc, + struct dc_state *context, + struct dml2_context *dml_ctx) +{ + unsigned int num_fams2_streams = 0; + + /* reset fams2 data */ + memset(&context->bw_ctx.bw.dcn.fams2_stream_base_params, 0, sizeof(union dmub_cmd_fams2_config) * DML2_MAX_PLANES); + memset(&context->bw_ctx.bw.dcn.fams2_stream_sub_params, 0, sizeof(union dmub_cmd_fams2_config) * DML2_MAX_PLANES); + memset(&context->bw_ctx.bw.dcn.fams2_stream_sub_params_v2, 0, sizeof(union dmub_fams2_stream_static_sub_state_v2) * DML2_MAX_PLANES); + memset(&context->bw_ctx.bw.dcn.fams2_global_config, 0, sizeof(struct dmub_cmd_fams2_global_config)); - num_fams2_streams++; + if (dml_ctx->v21.mode_programming.programming->fams2_required || + dml_ctx->v21.mode_programming.programming->legacy_pstate_info_for_dmu) { + if (dc->debug.fams_version.major == 2) { + num_fams2_streams = dml21_build_fams2_stream_programming_v2(dc, context, dml_ctx); } } @@ -508,7 +522,8 @@ void dml21_build_fams2_programming(const struct dc *dc, context->bw_ctx.bw.dcn.fams2_global_config.num_streams = num_fams2_streams; } - context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching = context->bw_ctx.bw.dcn.fams2_global_config.features.bits.enable; + context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching = + (context->bw_ctx.bw.dcn.fams2_global_config.features.bits.enable != 0); } bool dml21_is_plane1_enabled(enum dml2_source_format_class source_format) diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.h index 4bff52eaaef8..bff945a4ab3a 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.h +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.h @@ -9,6 +9,7 @@ struct dc_state; struct dc_plane_state; struct pipe_ctx; +struct dc_dmub_srv; struct dml2_context; struct dml2_display_rq_regs; diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.c index 798abb2b2e67..7398f8b69adb 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.c @@ -9,16 +9,25 @@ #include "dml21_utils.h" #include "dml21_translation_helper.h" #include "dml2_dc_resource_mgmt.h" +#include "dml2_wrapper.h" +#include "dml2_wrapper_fpu.h" +#include "dml21_wrapper.h" +#include "dml21_wrapper_fpu.h" +#include "dc_fpu.h" + +#if !defined(DC_RUN_WITH_PREEMPTION_ENABLED) +#define DC_RUN_WITH_PREEMPTION_ENABLED(code) code +#endif // !DC_RUN_WITH_PREEMPTION_ENABLED #define INVALID -1 static bool dml21_allocate_memory(struct dml2_context **dml_ctx) { - *dml_ctx = vzalloc(sizeof(struct dml2_context)); + DC_RUN_WITH_PREEMPTION_ENABLED(*dml_ctx = vzalloc(sizeof(struct dml2_context))); if (!(*dml_ctx)) return false; - (*dml_ctx)->v21.dml_init.dml2_instance = vzalloc(sizeof(struct dml2_instance)); + DC_RUN_WITH_PREEMPTION_ENABLED((*dml_ctx)->v21.dml_init.dml2_instance = vzalloc(sizeof(struct dml2_instance))); if (!((*dml_ctx)->v21.dml_init.dml2_instance)) return false; @@ -28,45 +37,14 @@ static bool dml21_allocate_memory(struct dml2_context **dml_ctx) (*dml_ctx)->v21.mode_support.display_config = &(*dml_ctx)->v21.display_config; (*dml_ctx)->v21.mode_programming.display_config = (*dml_ctx)->v21.mode_support.display_config; - (*dml_ctx)->v21.mode_programming.programming = vzalloc(sizeof(struct dml2_display_cfg_programming)); + DC_RUN_WITH_PREEMPTION_ENABLED((*dml_ctx)->v21.mode_programming.programming = vzalloc(sizeof(struct dml2_display_cfg_programming))); + if (!((*dml_ctx)->v21.mode_programming.programming)) return false; return true; } -static void dml21_populate_configuration_options(const struct dc *in_dc, - struct dml2_context *dml_ctx, - const struct dml2_configuration_options *config) -{ - dml_ctx->config = *config; - - /* UCLK P-State options */ - if (in_dc->debug.dml21_force_pstate_method) { - dml_ctx->config.pmo.force_pstate_method_enable = true; - for (int i = 0; i < MAX_PIPES; i++) - dml_ctx->config.pmo.force_pstate_method_values[i] = in_dc->debug.dml21_force_pstate_method_values[i]; - } else { - dml_ctx->config.pmo.force_pstate_method_enable = false; - } -} - -static void dml21_init(const struct dc *in_dc, struct dml2_context *dml_ctx, const struct dml2_configuration_options *config) -{ - - dml_ctx->architecture = dml2_architecture_21; - - dml21_populate_configuration_options(in_dc, dml_ctx, config); - - DC_FP_START(); - - dml21_populate_dml_init_params(&dml_ctx->v21.dml_init, &dml_ctx->config, in_dc); - - dml2_initialize_instance(&dml_ctx->v21.dml_init); - - DC_FP_END(); -} - bool dml21_create(const struct dc *in_dc, struct dml2_context **dml_ctx, const struct dml2_configuration_options *config) { /* Allocate memory for initializing DML21 instance */ @@ -84,336 +62,6 @@ void dml21_destroy(struct dml2_context *dml2) vfree(dml2->v21.mode_programming.programming); } -static void dml21_calculate_rq_and_dlg_params(const struct dc *dc, struct dc_state *context, struct resource_context *out_new_hw_state, - struct dml2_context *in_ctx, unsigned int pipe_cnt) -{ - unsigned int dml_prog_idx = 0, dc_pipe_index = 0, num_dpps_required = 0; - struct dml2_per_plane_programming *pln_prog = NULL; - struct dml2_per_stream_programming *stream_prog = NULL; - struct pipe_ctx *dc_main_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__]; - struct pipe_ctx *dc_phantom_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__] = {0}; - int num_pipes; - unsigned int dml_phantom_prog_idx; - - context->bw_ctx.bw.dcn.clk.dppclk_khz = 0; - - /* copy global DCHUBBUB arbiter registers */ - memcpy(&context->bw_ctx.bw.dcn.arb_regs, &in_ctx->v21.mode_programming.programming->global_regs.arb_regs, sizeof(struct dml2_display_arb_regs)); - - /* legacy only */ - context->bw_ctx.bw.dcn.compbuf_size_kb = (int)in_ctx->v21.mode_programming.programming->global_regs.arb_regs.compbuf_size * 64; - - context->bw_ctx.bw.dcn.mall_ss_size_bytes = 0; - context->bw_ctx.bw.dcn.mall_ss_psr_active_size_bytes = 0; - context->bw_ctx.bw.dcn.mall_subvp_size_bytes = 0; - - /* phantom's start after main planes */ - dml_phantom_prog_idx = in_ctx->v21.mode_programming.programming->display_config.num_planes; - - for (dml_prog_idx = 0; dml_prog_idx < DML2_MAX_PLANES; dml_prog_idx++) { - pln_prog = &in_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx]; - - if (!pln_prog->plane_descriptor) - continue; - - stream_prog = &in_ctx->v21.mode_programming.programming->stream_programming[pln_prog->plane_descriptor->stream_index]; - num_dpps_required = pln_prog->num_dpps_required; - - if (num_dpps_required == 0) { - continue; - } - num_pipes = dml21_find_dc_pipes_for_plane(dc, context, in_ctx, dc_main_pipes, dc_phantom_pipes, dml_prog_idx); - - if (num_pipes <= 0) - continue; - - /* program each pipe */ - for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) { - dml21_program_dc_pipe(in_ctx, context, dc_main_pipes[dc_pipe_index], pln_prog, stream_prog); - - if (pln_prog->phantom_plane.valid && dc_phantom_pipes[dc_pipe_index]) { - dml21_program_dc_pipe(in_ctx, context, dc_phantom_pipes[dc_pipe_index], pln_prog, stream_prog); - } - } - - /* copy per plane mcache allocation */ - memcpy(&context->bw_ctx.bw.dcn.mcache_allocations[dml_prog_idx], &pln_prog->mcache_allocation, sizeof(struct dml2_mcache_surface_allocation)); - if (pln_prog->phantom_plane.valid) { - memcpy(&context->bw_ctx.bw.dcn.mcache_allocations[dml_phantom_prog_idx], - &pln_prog->phantom_plane.mcache_allocation, - sizeof(struct dml2_mcache_surface_allocation)); - - dml_phantom_prog_idx++; - } - } - - /* assign global clocks */ - context->bw_ctx.bw.dcn.clk.bw_dppclk_khz = context->bw_ctx.bw.dcn.clk.dppclk_khz; - context->bw_ctx.bw.dcn.clk.bw_dispclk_khz = context->bw_ctx.bw.dcn.clk.dispclk_khz; - if (in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.num_clk_values > 1) { - context->bw_ctx.bw.dcn.clk.max_supported_dispclk_khz = - in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.clk_values_khz[in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.num_clk_values] * 1000; - } else { - context->bw_ctx.bw.dcn.clk.max_supported_dispclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.clk_values_khz[0] * 1000; - } - - if (in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.num_clk_values > 1) { - context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz = - in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.clk_values_khz[in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.num_clk_values] * 1000; - } else { - context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.clk_values_khz[0] * 1000; - } - - /* get global mall allocation */ - if (dc->res_pool->funcs->calculate_mall_ways_from_bytes) { - context->bw_ctx.bw.dcn.clk.num_ways = dc->res_pool->funcs->calculate_mall_ways_from_bytes(dc, context->bw_ctx.bw.dcn.mall_subvp_size_bytes); - } else { - context->bw_ctx.bw.dcn.clk.num_ways = 0; - } -} - -static void dml21_prepare_mcache_params(struct dml2_context *dml_ctx, struct dc_state *context, struct dc_mcache_params *mcache_params) -{ - int dc_plane_idx = 0; - int dml_prog_idx, stream_idx, plane_idx; - struct dml2_per_plane_programming *pln_prog = NULL; - - for (stream_idx = 0; stream_idx < context->stream_count; stream_idx++) { - for (plane_idx = 0; plane_idx < context->stream_status[stream_idx].plane_count; plane_idx++) { - dml_prog_idx = map_plane_to_dml21_display_cfg(dml_ctx, context->streams[stream_idx]->stream_id, context->stream_status[stream_idx].plane_states[plane_idx], context); - if (dml_prog_idx == INVALID) { - continue; - } - pln_prog = &dml_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx]; - mcache_params[dc_plane_idx].valid = pln_prog->mcache_allocation.valid; - mcache_params[dc_plane_idx].num_mcaches_plane0 = pln_prog->mcache_allocation.num_mcaches_plane0; - mcache_params[dc_plane_idx].num_mcaches_plane1 = pln_prog->mcache_allocation.num_mcaches_plane1; - mcache_params[dc_plane_idx].requires_dedicated_mall_mcache = pln_prog->mcache_allocation.requires_dedicated_mall_mcache; - mcache_params[dc_plane_idx].last_slice_sharing.plane0_plane1 = pln_prog->mcache_allocation.last_slice_sharing.plane0_plane1; - memcpy(mcache_params[dc_plane_idx].mcache_x_offsets_plane0, - pln_prog->mcache_allocation.mcache_x_offsets_plane0, - sizeof(int) * (DML2_MAX_MCACHES + 1)); - memcpy(mcache_params[dc_plane_idx].mcache_x_offsets_plane1, - pln_prog->mcache_allocation.mcache_x_offsets_plane1, - sizeof(int) * (DML2_MAX_MCACHES + 1)); - dc_plane_idx++; - } - } -} - -static bool dml21_mode_check_and_programming(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx) -{ - bool result = false; - struct dml2_build_mode_programming_in_out *mode_programming = &dml_ctx->v21.mode_programming; - struct dc_mcache_params mcache_params[MAX_PLANES] = {0}; - - memset(&dml_ctx->v21.display_config, 0, sizeof(struct dml2_display_cfg)); - memset(&dml_ctx->v21.dml_to_dc_pipe_mapping, 0, sizeof(struct dml2_dml_to_dc_pipe_mapping)); - memset(&dml_ctx->v21.mode_programming.dml2_instance->scratch.build_mode_programming_locals.mode_programming_params, 0, sizeof(struct dml2_core_mode_programming_in_out)); - - if (!context) - return true; - - if (context->stream_count == 0) { - dml21_build_fams2_programming(in_dc, context, dml_ctx); - return true; - } - - /* scrub phantom's from current dc_state */ - dml_ctx->config.svp_pstate.callbacks.remove_phantom_streams_and_planes(in_dc, context); - dml_ctx->config.svp_pstate.callbacks.release_phantom_streams_and_planes(in_dc, context); - - /* Populate stream, plane mappings and other fields in display config. */ - result = dml21_map_dc_state_into_dml_display_cfg(in_dc, context, dml_ctx); - if (!result) - return false; - - DC_FP_START(); - result = dml2_build_mode_programming(mode_programming); - DC_FP_END(); - if (!result) - return false; - - /* Check and map HW resources */ - if (result && !dml_ctx->config.skip_hw_state_mapping) { - dml21_map_hw_resources(dml_ctx); - dml2_map_dc_pipes(dml_ctx, context, NULL, &dml_ctx->v21.dml_to_dc_pipe_mapping, in_dc->current_state); - /* if subvp phantoms are present, expand them into dc context */ - dml21_handle_phantom_streams_planes(in_dc, context, dml_ctx); - - if (in_dc->res_pool->funcs->program_mcache_pipe_config) { - //Prepare mcache params for each plane based on mcache output from DML - dml21_prepare_mcache_params(dml_ctx, context, mcache_params); - - //populate mcache regs to each pipe - dml_ctx->config.callbacks.allocate_mcache(context, mcache_params); - } - } - - /* Copy DML CLK, WM and REG outputs to bandwidth context */ - if (result && !dml_ctx->config.skip_hw_state_mapping) { - dml21_calculate_rq_and_dlg_params(in_dc, context, &context->res_ctx, dml_ctx, in_dc->res_pool->pipe_count); - dml21_copy_clocks_to_dc_state(dml_ctx, context); - dml21_extract_watermark_sets(in_dc, &context->bw_ctx.bw.dcn.watermarks, dml_ctx); - dml21_build_fams2_programming(in_dc, context, dml_ctx); - } - - return true; -} - -static bool dml21_check_mode_support(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx) -{ - bool is_supported = false; - struct dml2_initialize_instance_in_out *dml_init = &dml_ctx->v21.dml_init; - struct dml2_check_mode_supported_in_out *mode_support = &dml_ctx->v21.mode_support; - - memset(&dml_ctx->v21.display_config, 0, sizeof(struct dml2_display_cfg)); - memset(&dml_ctx->v21.dml_to_dc_pipe_mapping, 0, sizeof(struct dml2_dml_to_dc_pipe_mapping)); - memset(&dml_ctx->v21.mode_programming.dml2_instance->scratch.check_mode_supported_locals.mode_support_params, 0, sizeof(struct dml2_core_mode_support_in_out)); - - if (!context || context->stream_count == 0) - return true; - - /* Scrub phantom's from current dc_state */ - dml_ctx->config.svp_pstate.callbacks.remove_phantom_streams_and_planes(in_dc, context); - dml_ctx->config.svp_pstate.callbacks.release_phantom_streams_and_planes(in_dc, context); - - mode_support->dml2_instance = dml_init->dml2_instance; - dml21_map_dc_state_into_dml_display_cfg(in_dc, context, dml_ctx); - dml_ctx->v21.mode_programming.dml2_instance->scratch.build_mode_programming_locals.mode_programming_params.programming = dml_ctx->v21.mode_programming.programming; - DC_FP_START(); - is_supported = dml2_check_mode_supported(mode_support); - DC_FP_END(); - if (!is_supported) - return false; - - return true; -} - -bool dml21_validate(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx, - enum dc_validate_mode validate_mode) -{ - bool out = false; - - /* Use dml21_check_mode_support for DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX path */ - if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING) - out = dml21_check_mode_support(in_dc, context, dml_ctx); - else - out = dml21_mode_check_and_programming(in_dc, context, dml_ctx); - - return out; -} - -void dml21_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx) -{ - unsigned int dml_prog_idx, dml_phantom_prog_idx, dc_pipe_index; - int num_pipes; - struct pipe_ctx *dc_main_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__]; - struct pipe_ctx *dc_phantom_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__] = {0}; - - struct dml2_per_plane_programming *pln_prog = NULL; - struct dml2_plane_mcache_configuration_descriptor *mcache_config = NULL; - struct prepare_mcache_programming_locals *l = &dml_ctx->v21.scratch.prepare_mcache_locals; - - if (context->stream_count == 0) { - return; - } - - memset(&l->build_mcache_programming_params, 0, sizeof(struct dml2_build_mcache_programming_in_out)); - l->build_mcache_programming_params.dml2_instance = dml_ctx->v21.dml_init.dml2_instance; - - /* phantom's start after main planes */ - dml_phantom_prog_idx = dml_ctx->v21.mode_programming.programming->display_config.num_planes; - - /* Build mcache programming parameters per plane per pipe */ - for (dml_prog_idx = 0; dml_prog_idx < dml_ctx->v21.mode_programming.programming->display_config.num_planes; dml_prog_idx++) { - pln_prog = &dml_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx]; - - mcache_config = &l->build_mcache_programming_params.mcache_configurations[dml_prog_idx]; - memset(mcache_config, 0, sizeof(struct dml2_plane_mcache_configuration_descriptor)); - mcache_config->plane_descriptor = pln_prog->plane_descriptor; - mcache_config->mcache_allocation = &context->bw_ctx.bw.dcn.mcache_allocations[dml_prog_idx]; - mcache_config->num_pipes = pln_prog->num_dpps_required; - l->build_mcache_programming_params.num_configurations++; - - if (pln_prog->num_dpps_required == 0) { - continue; - } - - num_pipes = dml21_find_dc_pipes_for_plane(in_dc, context, dml_ctx, dc_main_pipes, dc_phantom_pipes, dml_prog_idx); - if (num_pipes <= 0 || dc_main_pipes[0]->stream == NULL || - dc_main_pipes[0]->plane_state == NULL) - continue; - - /* get config for each pipe */ - for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) { - ASSERT(dc_main_pipes[dc_pipe_index]); - dml21_get_pipe_mcache_config(context, dc_main_pipes[dc_pipe_index], pln_prog, &mcache_config->pipe_configurations[dc_pipe_index]); - } - - /* get config for each phantom pipe */ - if (pln_prog->phantom_plane.valid && - dc_phantom_pipes[0] && - dc_main_pipes[0]->stream && - dc_phantom_pipes[0]->plane_state) { - mcache_config = &l->build_mcache_programming_params.mcache_configurations[dml_phantom_prog_idx]; - memset(mcache_config, 0, sizeof(struct dml2_plane_mcache_configuration_descriptor)); - mcache_config->plane_descriptor = pln_prog->plane_descriptor; - mcache_config->mcache_allocation = &context->bw_ctx.bw.dcn.mcache_allocations[dml_phantom_prog_idx]; - mcache_config->num_pipes = pln_prog->num_dpps_required; - l->build_mcache_programming_params.num_configurations++; - - for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) { - ASSERT(dc_phantom_pipes[dc_pipe_index]); - dml21_get_pipe_mcache_config(context, dc_phantom_pipes[dc_pipe_index], pln_prog, &mcache_config->pipe_configurations[dc_pipe_index]); - } - - /* increment phantom index */ - dml_phantom_prog_idx++; - } - } - - /* Call to generate mcache programming per plane per pipe for the given display configuration */ - dml2_build_mcache_programming(&l->build_mcache_programming_params); - - /* get per plane per pipe mcache programming */ - for (dml_prog_idx = 0; dml_prog_idx < dml_ctx->v21.mode_programming.programming->display_config.num_planes; dml_prog_idx++) { - pln_prog = &dml_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx]; - - num_pipes = dml21_find_dc_pipes_for_plane(in_dc, context, dml_ctx, dc_main_pipes, dc_phantom_pipes, dml_prog_idx); - if (num_pipes <= 0 || dc_main_pipes[0]->stream == NULL || - dc_main_pipes[0]->plane_state == NULL) - continue; - - /* get config for each pipe */ - for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) { - ASSERT(dc_main_pipes[dc_pipe_index]); - if (l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_prog_idx][dc_pipe_index]) { - memcpy(&dc_main_pipes[dc_pipe_index]->mcache_regs, - l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_prog_idx][dc_pipe_index], - sizeof(struct dml2_hubp_pipe_mcache_regs)); - } - } - - /* get config for each phantom pipe */ - if (pln_prog->phantom_plane.valid && - dc_phantom_pipes[0] && - dc_main_pipes[0]->stream && - dc_phantom_pipes[0]->plane_state) { - for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) { - ASSERT(dc_phantom_pipes[dc_pipe_index]); - if (l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_phantom_prog_idx][dc_pipe_index]) { - memcpy(&dc_phantom_pipes[dc_pipe_index]->mcache_regs, - l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_phantom_prog_idx][dc_pipe_index], - sizeof(struct dml2_hubp_pipe_mcache_regs)); - } - } - /* increment phantom index */ - dml_phantom_prog_idx++; - } - } -} - void dml21_copy(struct dml2_context *dst_dml_ctx, struct dml2_context *src_dml_ctx) { @@ -439,12 +87,8 @@ void dml21_copy(struct dml2_context *dst_dml_ctx, dst_dml_ctx->v21.mode_programming.programming = dst_dml2_programming; - DC_FP_START(); - /* need to initialize copied instance for internal references to be correct */ dml2_initialize_instance(&dst_dml_ctx->v21.dml_init); - - DC_FP_END(); } bool dml21_create_copy(struct dml2_context **dst_dml_ctx, @@ -459,8 +103,3 @@ bool dml21_create_copy(struct dml2_context **dst_dml_ctx, return true; } -void dml21_reinit(const struct dc *in_dc, struct dml2_context *dml_ctx, const struct dml2_configuration_options *config) -{ - dml21_init(in_dc, dml_ctx, config); -} - diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.h index b508bbcc0e16..c4813c51251b 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.h +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.h @@ -34,36 +34,6 @@ void dml21_copy(struct dml2_context *dst_dml_ctx, struct dml2_context *src_dml_ctx); bool dml21_create_copy(struct dml2_context **dst_dml_ctx, struct dml2_context *src_dml_ctx); -void dml21_reinit(const struct dc *in_dc, struct dml2_context *dml_ctx, const struct dml2_configuration_options *config); - -/** - * dml21_validate - Determines if a display configuration is supported or not. - * @in_dc: dc. - * @context: dc_state to be validated. - * @dml_ctx: dml21 context. - * @validate_mode: DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX - * will not populate context.res_ctx. - * - * Based on fast_validate option internally would call: - * - * -dml21_mode_check_and_programming - for DC_VALIDATE_MODE_AND_PROGRAMMING option - * Calculates if dc_state can be supported on the input display - * configuration. If supported, generates the necessary HW - * programming for the new dc_state. - * - * -dml21_check_mode_support - for DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX option - * Calculates if dc_state can be supported for the input display - * config. - * - * Context: Two threads may not invoke this function concurrently unless they reference - * separate dc_states for validation. - * Return: True if mode is supported, false otherwise. - */ -bool dml21_validate(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx, - enum dc_validate_mode validate_mode); - -/* Prepare hubp mcache_regs for hubp mcache ID and split coordinate programming */ -void dml21_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx); /* Structure for inputting external SOCBB and DCNIP values for tool based debugging. */ struct socbb_ip_params_external { diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper_fpu.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper_fpu.c new file mode 100644 index 000000000000..cc992af6ac9c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper_fpu.c @@ -0,0 +1,381 @@ +// SPDX-License-Identifier: MIT +// +// Copyright 2026 Advanced Micro Devices, Inc. + +#include "dml2_internal_types.h" +#include "dml_top.h" +#include "dml2_core_dcn4_calcs.h" +#include "dml2_internal_shared_types.h" +#include "dml21_utils.h" +#include "dml21_translation_helper.h" +#include "dml2_dc_resource_mgmt.h" +#include "dml2_wrapper.h" +#include "dml2_wrapper_fpu.h" +#include "dml21_wrapper.h" +#include "dml21_wrapper_fpu.h" + +#define INVALID -1 + +static void dml21_populate_configuration_options(const struct dc *in_dc, + struct dml2_context *dml_ctx, + const struct dml2_configuration_options *config) +{ + dml_ctx->config = *config; + + /* UCLK P-State options */ + if (in_dc->debug.dml21_force_pstate_method) { + dml_ctx->config.pmo.force_pstate_method_enable = true; + for (int i = 0; i < MAX_PIPES; i++) + dml_ctx->config.pmo.force_pstate_method_values[i] = in_dc->debug.dml21_force_pstate_method_values[i]; + } else { + dml_ctx->config.pmo.force_pstate_method_enable = false; + } +} + +void dml21_init(const struct dc *in_dc, struct dml2_context *dml_ctx, const struct dml2_configuration_options *config) +{ + dml_ctx->architecture = dml2_architecture_21; + + dml21_populate_configuration_options(in_dc, dml_ctx, config); + + dml21_populate_dml_init_params(&dml_ctx->v21.dml_init, &dml_ctx->config, in_dc); + + dml2_initialize_instance(&dml_ctx->v21.dml_init); +} + +void dml21_reinit(const struct dc *in_dc, struct dml2_context *dml_ctx, const struct dml2_configuration_options *config) +{ + dml21_init(in_dc, dml_ctx, config); +} + +static void dml21_calculate_rq_and_dlg_params(const struct dc *dc, struct dc_state *context, struct resource_context *out_new_hw_state, + struct dml2_context *in_ctx, unsigned int pipe_cnt) +{ + unsigned int dml_prog_idx = 0, dc_pipe_index = 0, num_dpps_required = 0; + struct dml2_per_plane_programming *pln_prog = NULL; + struct dml2_per_stream_programming *stream_prog = NULL; + struct pipe_ctx *dc_main_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__]; + struct pipe_ctx *dc_phantom_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__] = {0}; + int num_pipes; + unsigned int dml_phantom_prog_idx; + + context->bw_ctx.bw.dcn.clk.dppclk_khz = 0; + + /* copy global DCHUBBUB arbiter registers */ + memcpy(&context->bw_ctx.bw.dcn.arb_regs, &in_ctx->v21.mode_programming.programming->global_regs.arb_regs, sizeof(struct dml2_display_arb_regs)); + + /* legacy only */ + context->bw_ctx.bw.dcn.compbuf_size_kb = (int)in_ctx->v21.mode_programming.programming->global_regs.arb_regs.compbuf_size * 64; + + context->bw_ctx.bw.dcn.mall_ss_size_bytes = 0; + context->bw_ctx.bw.dcn.mall_ss_psr_active_size_bytes = 0; + context->bw_ctx.bw.dcn.mall_subvp_size_bytes = 0; + + /* phantom's start after main planes */ + dml_phantom_prog_idx = in_ctx->v21.mode_programming.programming->display_config.num_planes; + + for (dml_prog_idx = 0; dml_prog_idx < DML2_MAX_PLANES; dml_prog_idx++) { + pln_prog = &in_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx]; + + if (!pln_prog->plane_descriptor) + continue; + + stream_prog = &in_ctx->v21.mode_programming.programming->stream_programming[pln_prog->plane_descriptor->stream_index]; + num_dpps_required = pln_prog->num_dpps_required; + + if (num_dpps_required == 0) { + continue; + } + num_pipes = dml21_find_dc_pipes_for_plane(dc, context, in_ctx, dc_main_pipes, dc_phantom_pipes, dml_prog_idx); + + if (num_pipes <= 0) + continue; + + /* program each pipe */ + for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) { + dml21_program_dc_pipe(in_ctx, context, dc_main_pipes[dc_pipe_index], pln_prog, stream_prog); + + if (pln_prog->phantom_plane.valid && dc_phantom_pipes[dc_pipe_index]) { + dml21_program_dc_pipe(in_ctx, context, dc_phantom_pipes[dc_pipe_index], pln_prog, stream_prog); + } + } + + /* copy per plane mcache allocation */ + memcpy(&context->bw_ctx.bw.dcn.mcache_allocations[dml_prog_idx], &pln_prog->mcache_allocation, sizeof(struct dml2_mcache_surface_allocation)); + if (pln_prog->phantom_plane.valid) { + memcpy(&context->bw_ctx.bw.dcn.mcache_allocations[dml_phantom_prog_idx], + &pln_prog->phantom_plane.mcache_allocation, + sizeof(struct dml2_mcache_surface_allocation)); + + dml_phantom_prog_idx++; + } + } + + /* assign global clocks */ + context->bw_ctx.bw.dcn.clk.bw_dppclk_khz = context->bw_ctx.bw.dcn.clk.dppclk_khz; + context->bw_ctx.bw.dcn.clk.bw_dispclk_khz = context->bw_ctx.bw.dcn.clk.dispclk_khz; + if (in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.num_clk_values > 1) { + context->bw_ctx.bw.dcn.clk.max_supported_dispclk_khz = + in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.clk_values_khz[in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.num_clk_values] * 1000; + } else { + context->bw_ctx.bw.dcn.clk.max_supported_dispclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.clk_values_khz[0] * 1000; + } + + if (in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.num_clk_values > 1) { + context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz = + in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.clk_values_khz[in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.num_clk_values] * 1000; + } else { + context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.clk_values_khz[0] * 1000; + } + + /* get global mall allocation */ + if (dc->res_pool->funcs->calculate_mall_ways_from_bytes) { + context->bw_ctx.bw.dcn.clk.num_ways = dc->res_pool->funcs->calculate_mall_ways_from_bytes(dc, context->bw_ctx.bw.dcn.mall_subvp_size_bytes); + } else { + context->bw_ctx.bw.dcn.clk.num_ways = 0; + } +} + +static void dml21_prepare_mcache_params(struct dml2_context *dml_ctx, struct dc_state *context, struct dc_mcache_params *mcache_params) +{ + int dc_plane_idx = 0; + int dml_prog_idx, stream_idx, plane_idx; + struct dml2_per_plane_programming *pln_prog = NULL; + + for (stream_idx = 0; stream_idx < context->stream_count; stream_idx++) { + for (plane_idx = 0; plane_idx < context->stream_status[stream_idx].plane_count; plane_idx++) { + dml_prog_idx = map_plane_to_dml21_display_cfg(dml_ctx, context->streams[stream_idx]->stream_id, context->stream_status[stream_idx].plane_states[plane_idx], context); + if (dml_prog_idx == INVALID) { + continue; + } + pln_prog = &dml_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx]; + mcache_params[dc_plane_idx].valid = pln_prog->mcache_allocation.valid; + mcache_params[dc_plane_idx].num_mcaches_plane0 = pln_prog->mcache_allocation.num_mcaches_plane0; + mcache_params[dc_plane_idx].num_mcaches_plane1 = pln_prog->mcache_allocation.num_mcaches_plane1; + mcache_params[dc_plane_idx].requires_dedicated_mall_mcache = pln_prog->mcache_allocation.requires_dedicated_mall_mcache; + mcache_params[dc_plane_idx].last_slice_sharing.plane0_plane1 = pln_prog->mcache_allocation.last_slice_sharing.plane0_plane1; + memcpy(mcache_params[dc_plane_idx].mcache_x_offsets_plane0, + pln_prog->mcache_allocation.mcache_x_offsets_plane0, + sizeof(int) * (DML2_MAX_MCACHES + 1)); + memcpy(mcache_params[dc_plane_idx].mcache_x_offsets_plane1, + pln_prog->mcache_allocation.mcache_x_offsets_plane1, + sizeof(int) * (DML2_MAX_MCACHES + 1)); + dc_plane_idx++; + } + } +} + +static bool dml21_check_mode_support(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx) +{ + bool is_supported = false; + struct dml2_initialize_instance_in_out *dml_init = &dml_ctx->v21.dml_init; + struct dml2_check_mode_supported_in_out *mode_support = &dml_ctx->v21.mode_support; + + memset(&dml_ctx->v21.display_config, 0, sizeof(struct dml2_display_cfg)); + memset(&dml_ctx->v21.dml_to_dc_pipe_mapping, 0, sizeof(struct dml2_dml_to_dc_pipe_mapping)); + memset(&dml_ctx->v21.mode_programming.dml2_instance->scratch.check_mode_supported_locals.mode_support_params, 0, sizeof(struct dml2_core_mode_support_in_out)); + + if (!context || context->stream_count == 0) + return true; + + /* Scrub phantom's from current dc_state */ + dml_ctx->config.svp_pstate.callbacks.remove_phantom_streams_and_planes(in_dc, context); + dml_ctx->config.svp_pstate.callbacks.release_phantom_streams_and_planes(in_dc, context); + + mode_support->dml2_instance = dml_init->dml2_instance; + dml21_map_dc_state_into_dml_display_cfg(in_dc, context, dml_ctx); + dml_ctx->v21.mode_programming.dml2_instance->scratch.build_mode_programming_locals.mode_programming_params.programming = dml_ctx->v21.mode_programming.programming; + + is_supported = dml2_check_mode_supported(mode_support); + + if (!is_supported) + return false; + + return true; +} + +static bool dml21_mode_check_and_programming(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx) +{ + bool result = false; + struct dml2_build_mode_programming_in_out *mode_programming = &dml_ctx->v21.mode_programming; + struct dc_mcache_params mcache_params[MAX_PLANES] = {0}; + + memset(&dml_ctx->v21.display_config, 0, sizeof(struct dml2_display_cfg)); + memset(&dml_ctx->v21.dml_to_dc_pipe_mapping, 0, sizeof(struct dml2_dml_to_dc_pipe_mapping)); + memset(&dml_ctx->v21.mode_programming.dml2_instance->scratch.build_mode_programming_locals.mode_programming_params, 0, sizeof(struct dml2_core_mode_programming_in_out)); + + if (!context) + return true; + + if (context->stream_count == 0) { + dml21_init_min_clocks_for_dc_state(dml_ctx, context); + dml21_build_fams2_programming(in_dc, context, dml_ctx); + return true; + } + + /* scrub phantom's from current dc_state */ + dml_ctx->config.svp_pstate.callbacks.remove_phantom_streams_and_planes(in_dc, context); + dml_ctx->config.svp_pstate.callbacks.release_phantom_streams_and_planes(in_dc, context); + + /* Populate stream, plane mappings and other fields in display config. */ + result = dml21_map_dc_state_into_dml_display_cfg(in_dc, context, dml_ctx); + if (!result) + return false; + + result = dml2_build_mode_programming(mode_programming); + + if (!result) + return false; + + /* Check and map HW resources */ + if (result && !dml_ctx->config.skip_hw_state_mapping) { + dml21_map_hw_resources(dml_ctx); + dml2_map_dc_pipes(dml_ctx, context, NULL, &dml_ctx->v21.dml_to_dc_pipe_mapping, in_dc->current_state); + /* if subvp phantoms are present, expand them into dc context */ + dml21_handle_phantom_streams_planes(in_dc, context, dml_ctx); + + if (in_dc->res_pool->funcs->program_mcache_pipe_config) { + //Prepare mcache params for each plane based on mcache output from DML + dml21_prepare_mcache_params(dml_ctx, context, mcache_params); + + //populate mcache regs to each pipe + dml_ctx->config.callbacks.allocate_mcache(context, mcache_params); + } + } + + /* Copy DML CLK, WM and REG outputs to bandwidth context */ + if (result && !dml_ctx->config.skip_hw_state_mapping) { + dml21_calculate_rq_and_dlg_params(in_dc, context, &context->res_ctx, dml_ctx, in_dc->res_pool->pipe_count); + dml21_copy_clocks_to_dc_state(dml_ctx, context); + dml21_extract_watermark_sets(in_dc, &context->bw_ctx.bw.dcn.watermarks, dml_ctx); + dml21_build_fams2_programming(in_dc, context, dml_ctx); + } + + return true; +} + +bool dml21_validate(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx, + enum dc_validate_mode validate_mode) +{ + bool out = false; + + /* Use dml21_check_mode_support for DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX path */ + if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING) + out = dml21_check_mode_support(in_dc, context, dml_ctx); + else + out = dml21_mode_check_and_programming(in_dc, context, dml_ctx); + + return out; +} + +void dml21_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx) +{ + unsigned int dml_prog_idx, dml_phantom_prog_idx, dc_pipe_index; + int num_pipes; + struct pipe_ctx *dc_main_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__]; + struct pipe_ctx *dc_phantom_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__] = {0}; + + struct dml2_per_plane_programming *pln_prog = NULL; + struct dml2_plane_mcache_configuration_descriptor *mcache_config = NULL; + struct prepare_mcache_programming_locals *l = &dml_ctx->v21.scratch.prepare_mcache_locals; + + if (context->stream_count == 0) { + return; + } + + memset(&l->build_mcache_programming_params, 0, sizeof(struct dml2_build_mcache_programming_in_out)); + l->build_mcache_programming_params.dml2_instance = dml_ctx->v21.dml_init.dml2_instance; + + /* phantom's start after main planes */ + dml_phantom_prog_idx = dml_ctx->v21.mode_programming.programming->display_config.num_planes; + + /* Build mcache programming parameters per plane per pipe */ + for (dml_prog_idx = 0; dml_prog_idx < dml_ctx->v21.mode_programming.programming->display_config.num_planes; dml_prog_idx++) { + pln_prog = &dml_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx]; + + mcache_config = &l->build_mcache_programming_params.mcache_configurations[dml_prog_idx]; + memset(mcache_config, 0, sizeof(struct dml2_plane_mcache_configuration_descriptor)); + mcache_config->plane_descriptor = pln_prog->plane_descriptor; + mcache_config->mcache_allocation = &context->bw_ctx.bw.dcn.mcache_allocations[dml_prog_idx]; + ASSERT(pln_prog->num_dpps_required <= 0x7F); + mcache_config->num_pipes = (char)pln_prog->num_dpps_required; + l->build_mcache_programming_params.num_configurations++; + + if (pln_prog->num_dpps_required == 0) { + continue; + } + + num_pipes = dml21_find_dc_pipes_for_plane(in_dc, context, dml_ctx, dc_main_pipes, dc_phantom_pipes, dml_prog_idx); + if (num_pipes <= 0 || dc_main_pipes[0]->stream == NULL || + dc_main_pipes[0]->plane_state == NULL) + continue; + + /* get config for each pipe */ + for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) { + ASSERT(dc_main_pipes[dc_pipe_index]); + dml21_get_pipe_mcache_config(context, dc_main_pipes[dc_pipe_index], pln_prog, &mcache_config->pipe_configurations[dc_pipe_index]); + } + + /* get config for each phantom pipe */ + if (pln_prog->phantom_plane.valid && + dc_phantom_pipes[0] && + dc_main_pipes[0]->stream && + dc_phantom_pipes[0]->plane_state) { + mcache_config = &l->build_mcache_programming_params.mcache_configurations[dml_phantom_prog_idx]; + memset(mcache_config, 0, sizeof(struct dml2_plane_mcache_configuration_descriptor)); + mcache_config->plane_descriptor = pln_prog->plane_descriptor; + mcache_config->mcache_allocation = &context->bw_ctx.bw.dcn.mcache_allocations[dml_phantom_prog_idx]; + ASSERT(pln_prog->num_dpps_required <= 0x7F); + mcache_config->num_pipes = (char)pln_prog->num_dpps_required; + l->build_mcache_programming_params.num_configurations++; + + for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) { + ASSERT(dc_phantom_pipes[dc_pipe_index]); + dml21_get_pipe_mcache_config(context, dc_phantom_pipes[dc_pipe_index], pln_prog, &mcache_config->pipe_configurations[dc_pipe_index]); + } + + /* increment phantom index */ + dml_phantom_prog_idx++; + } + } + + /* Call to generate mcache programming per plane per pipe for the given display configuration */ + dml2_build_mcache_programming(&l->build_mcache_programming_params); + + /* get per plane per pipe mcache programming */ + for (dml_prog_idx = 0; dml_prog_idx < dml_ctx->v21.mode_programming.programming->display_config.num_planes; dml_prog_idx++) { + pln_prog = &dml_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx]; + + num_pipes = dml21_find_dc_pipes_for_plane(in_dc, context, dml_ctx, dc_main_pipes, dc_phantom_pipes, dml_prog_idx); + if (num_pipes <= 0 || dc_main_pipes[0]->stream == NULL || + dc_main_pipes[0]->plane_state == NULL) + continue; + + /* get config for each pipe */ + for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) { + ASSERT(dc_main_pipes[dc_pipe_index]); + if (l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_prog_idx][dc_pipe_index]) { + memcpy(&dc_main_pipes[dc_pipe_index]->mcache_regs, + l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_prog_idx][dc_pipe_index], + sizeof(struct dml2_hubp_pipe_mcache_regs)); + } + } + + /* get config for each phantom pipe */ + if (pln_prog->phantom_plane.valid && + dc_phantom_pipes[0] && + dc_main_pipes[0]->stream && + dc_phantom_pipes[0]->plane_state) { + for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) { + ASSERT(dc_phantom_pipes[dc_pipe_index]); + if (l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_phantom_prog_idx][dc_pipe_index]) { + memcpy(&dc_phantom_pipes[dc_pipe_index]->mcache_regs, + l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_phantom_prog_idx][dc_pipe_index], + sizeof(struct dml2_hubp_pipe_mcache_regs)); + } + } + /* increment phantom index */ + dml_phantom_prog_idx++; + } + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper_fpu.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper_fpu.h new file mode 100644 index 000000000000..e5d9a456645f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper_fpu.h @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: MIT +// +// Copyright 2026 Advanced Micro Devices, Inc. + +#ifndef _DML21_WRAPPER_FPU_H_ +#define _DML21_WRAPPER_FPU_H_ + +#include "os_types.h" +#include "dml_top_soc_parameter_types.h" +#include "dml_top_display_cfg_types.h" + +struct dc; +struct dc_state; +struct dml2_configuration_options; +struct dml2_context; +enum dc_validate_mode; + +/** + * dml21_init - Initialize DML21 context + * @in_dc: dc. + * @dml_ctx: DML21 context to initialize. + * @config: dml21 configuration options. + * + * Performs FPU-requiring initialization. Must be called with FPU protection. + */ +void dml21_init(const struct dc *in_dc, struct dml2_context *dml_ctx, const struct dml2_configuration_options *config); + +/** + * dml21_validate - Determines if a display configuration is supported or not. + * @in_dc: dc. + * @context: dc_state to be validated. + * @dml_ctx: dml21 context. + * @validate_mode: DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX + * will not populate context.res_ctx. + * + * Based on fast_validate option internally would call: + * + * -dml21_mode_check_and_programming - for DC_VALIDATE_MODE_AND_PROGRAMMING option + * Calculates if dc_state can be supported on the input display + * configuration. If supported, generates the necessary HW + * programming for the new dc_state. + * + * -dml21_check_mode_support - for DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX option + * Calculates if dc_state can be supported for the input display + * config. + * + * Context: Two threads may not invoke this function concurrently unless they reference + * separate dc_states for validation. + * Return: True if mode is supported, false otherwise. + */ + +void dml21_reinit(const struct dc *in_dc, struct dml2_context *dml_ctx, + const struct dml2_configuration_options *config); +bool dml21_validate(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx, + enum dc_validate_mode validate_mode); + +/* Prepare hubp mcache_regs for hubp mcache ID and split coordinate programming */ +void dml21_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx); + +#endif /* _DML21_WRAPPER_FPU_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/dcn42_soc_bb.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/dcn42_soc_bb.h new file mode 100644 index 000000000000..c75778ea7a2c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/dcn42_soc_bb.h @@ -0,0 +1,263 @@ +/* SPDX-License-Identifier: MIT */ +// +// Copyright 2024 Advanced Micro Devices, Inc. + +#ifndef __DML_DML_DCN42_SOC_BB__ +#define __DML_DML_DCN42_SOC_BB__ + +#include "dml_top_soc_parameter_types.h" + +static const struct dml2_soc_qos_parameters dml_dcn42_variant_a_soc_qos_params = { + .derate_table = { + .system_active_urgent = { + .dram_derate_percent_pixel = 65, + .dram_derate_percent_vm = 30, + .dram_derate_percent_pixel_and_vm = 60, + .fclk_derate_percent = 80, + .dcfclk_derate_percent = 80, + }, + .system_active_average = { + .dram_derate_percent_pixel = 30, + .dram_derate_percent_vm = 30, + .dram_derate_percent_pixel_and_vm = 30, + .fclk_derate_percent = 60, + .dcfclk_derate_percent = 60, + }, + .dcn_mall_prefetch_urgent = { + .dram_derate_percent_pixel = 65, + .dram_derate_percent_vm = 30, + .dram_derate_percent_pixel_and_vm = 60, + .fclk_derate_percent = 80, + .dcfclk_derate_percent = 80, + }, + .dcn_mall_prefetch_average = { + .dram_derate_percent_pixel = 30, + .dram_derate_percent_vm = 30, + .dram_derate_percent_pixel_and_vm = 30, + .fclk_derate_percent = 60, + .dcfclk_derate_percent = 60, + }, + .system_idle_average = { + .dram_derate_percent_pixel = 30, + .dram_derate_percent_vm = 30, + .dram_derate_percent_pixel_and_vm = 30, + .fclk_derate_percent = 60, + .dcfclk_derate_percent = 60, + }, + }, + .writeback = { + .base_latency_us = 12, + .scaling_factor_us = 0, + .scaling_factor_mhz = 0, + }, + .qos_params = { + .dcn32x = { + .loaded_round_trip_latency_fclk_cycles = 106, + .urgent_latency_us = { + .base_latency_us = 4, + .base_latency_pixel_vm_us = 4, + .base_latency_vm_us = 4, + .scaling_factor_fclk_us = 0, + .scaling_factor_mhz = 0, + }, + .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096, + .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096, + .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096, + }, + }, + .qos_type = dml2_qos_param_type_dcn3, +}; + +static const struct dml2_soc_bb dml2_socbb_dcn42 = { + .clk_table = { + .wck_ratio = { + .clk_values_khz = {2}, + }, + .uclk = { + .clk_values_khz = {400000}, + .num_clk_values = 1, + }, + .fclk = { + .clk_values_khz = {400000}, + .num_clk_values = 1, + }, + .dcfclk = { + .clk_values_khz = {200000}, + .num_clk_values = 1, + }, + .dispclk = { + .clk_values_khz = {1500000}, + .num_clk_values = 1, + }, + .dppclk = { + .clk_values_khz = {1500000}, + .num_clk_values = 1, + }, + .dtbclk = { + .clk_values_khz = {600000}, + .num_clk_values = 1, + }, + .phyclk = { + .clk_values_khz = {810000}, + .num_clk_values = 1, + }, + .socclk = { + .clk_values_khz = {600000}, + .num_clk_values = 1, + }, + .dscclk = { + .clk_values_khz = {500000}, + .num_clk_values = 1, + }, + .phyclk_d18 = { + .clk_values_khz = {667000}, + .num_clk_values = 1, + }, + .phyclk_d32 = { + .clk_values_khz = {625000}, + .num_clk_values = 1, + }, + .dram_config = { + .channel_width_bytes = 4, + .channel_count = 4, + .alt_clock_bw_conversion = true, + }, + }, + + .qos_parameters = { + .derate_table = { + .system_active_urgent = { + .dram_derate_percent_pixel = 65, + .dram_derate_percent_vm = 30, + .dram_derate_percent_pixel_and_vm = 60, + .fclk_derate_percent = 80, + .dcfclk_derate_percent = 80, + }, + .system_active_average = { + .dram_derate_percent_pixel = 30, + .dram_derate_percent_vm = 30, + .dram_derate_percent_pixel_and_vm = 30, + .fclk_derate_percent = 60, + .dcfclk_derate_percent = 60, + }, + .dcn_mall_prefetch_urgent = { + .dram_derate_percent_pixel = 65, + .dram_derate_percent_vm = 30, + .dram_derate_percent_pixel_and_vm = 60, + .fclk_derate_percent = 80, + .dcfclk_derate_percent = 80, + }, + .dcn_mall_prefetch_average = { + .dram_derate_percent_pixel = 30, + .dram_derate_percent_vm = 30, + .dram_derate_percent_pixel_and_vm = 30, + .fclk_derate_percent = 60, + .dcfclk_derate_percent = 60, + }, + .system_idle_average = { + .dram_derate_percent_pixel = 30, + .dram_derate_percent_vm = 30, + .dram_derate_percent_pixel_and_vm = 30, + .fclk_derate_percent = 60, + .dcfclk_derate_percent = 60, + }, + }, + .writeback = { + .base_latency_us = 12, + .scaling_factor_us = 0, + .scaling_factor_mhz = 0, + }, + .qos_params = { + .dcn32x = { + .loaded_round_trip_latency_fclk_cycles = 106, + .urgent_latency_us = { + .base_latency_us = 4, + .base_latency_pixel_vm_us = 4, + .base_latency_vm_us = 4, + .scaling_factor_fclk_us = 0, + .scaling_factor_mhz = 0, + }, + .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096, + .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096, + .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096, + }, + }, + .qos_type = dml2_qos_param_type_dcn3, + }, + + .power_management_parameters = { + .dram_clk_change_blackout_us = 29, + .fclk_change_blackout_us = 0, + .g7_ppt_blackout_us = 0, + .stutter_enter_plus_exit_latency_us = 11, + .stutter_exit_latency_us = 9, + .z8_stutter_enter_plus_exit_latency_us = 300, + .z8_stutter_exit_latency_us = 200, + }, + + .vmin_limit = { + .dispclk_khz = 632 * 1000, + }, + + .dprefclk_mhz = 600, + .xtalclk_mhz = 24, + .pcie_refclk_mhz = 100, + .dchub_refclk_mhz = 50, + .mall_allocated_for_dcn_mbytes = 64, + .max_outstanding_reqs = 256, + .fabric_datapath_to_dcn_data_return_bytes = 32, + .return_bus_width_bytes = 64, + .hostvm_min_page_size_kbytes = 4, + .gpuvm_min_page_size_kbytes = 256, + .gpuvm_max_page_table_levels = 1, + .hostvm_max_non_cached_page_table_levels = 2, + .phy_downspread_percent = 0.38, + .dcn_downspread_percent = 0.38, + .dispclk_dppclk_vco_speed_mhz = 3000, + .do_urgent_latency_adjustment = 0, + .mem_word_bytes = 32, + .num_dcc_mcaches = 8, + .mcache_size_bytes = 2048, + .mcache_line_size_bytes = 32, + .max_fclk_for_uclk_dpm_khz = 2200 * 1000, +}; + +static const struct dml2_ip_capabilities dml2_dcn42_max_ip_caps = { + .pipe_count = 4, + .otg_count = 4, + .num_dsc = 4, + .max_num_dp2p0_streams = 4, + .max_num_hdmi_frl_outputs = 1, + .max_num_dp2p0_outputs = 4, + .rob_buffer_size_kbytes = 64, + .config_return_buffer_size_in_kbytes = 1792, + .config_return_buffer_segment_size_in_kbytes = 64, + .meta_fifo_size_in_kentries = 32, + .compressed_buffer_segment_size_in_kbytes = 64, + .cursor_buffer_size = 24, + .max_flip_time_us = 110, + .max_flip_time_lines = 50, + .hostvm_mode = 0, + .subvp_drr_scheduling_margin_us = 100, + .subvp_prefetch_end_to_mall_start_us = 15, + .subvp_fw_processing_delay = 15, + .max_vactive_det_fill_delay_us = 400, + + .fams2 = { + .max_allow_delay_us = 100 * 1000, + .scheduling_delay_us = 550, + .vertical_interrupt_ack_delay_us = 40, + .allow_programming_delay_us = 18, + .min_allow_width_us = 20, + .subvp_df_throttle_delay_us = 100, + .subvp_programming_delay_us = 200, + .subvp_prefetch_to_mall_delay_us = 18, + .drr_programming_delay_us = 35, + + .lock_timeout_us = 5000, + .recovery_timeout_us = 5000, + .flip_programming_delay_us = 300, + }, +}; + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_display_cfg_types.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_display_cfg_types.h index b44762e21550..4e9abe1a568d 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_display_cfg_types.h +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_display_cfg_types.h @@ -27,6 +27,19 @@ enum dml2_swizzle_mode { dml2_gfx11_sw_256kb_d_x, dml2_gfx11_sw_256kb_r_x, + dml2_sw_linear_256b, // GFX10 SW_LINEAR only accepts 256 byte aligned pitch + dml2_gfx10_sw_64kb_r_x, + dml2_gfx102_sw_64kb_s, + dml2_gfx102_sw_64kb_s_t, + dml2_gfx102_sw_64kb_s_x, + dml2_gfx102_sw_64kb_r_x, + + dml2_linear_64elements, // GFX7 LINEAR_ALIGNED accepts pitch alignment of the maximum of 64 elements or 256 bytes + dml2_gfx7_1d_thin, + dml2_gfx7_2d_thin_gen_zero, + dml2_gfx7_2d_thin_gen_one, + dml2_gfx7_2d_thin_arlene, + dml2_gfx7_2d_thin_anubis }; enum dml2_source_format_class { diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_soc_parameter_types.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_soc_parameter_types.h index c4cce870877a..6152155d6073 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_soc_parameter_types.h +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_soc_parameter_types.h @@ -160,6 +160,8 @@ struct dml2_soc_bb { unsigned long return_bus_width_bytes; unsigned long hostvm_min_page_size_kbytes; unsigned long gpuvm_min_page_size_kbytes; + unsigned int hostvm_max_non_cached_page_table_levels; + unsigned int gpuvm_max_page_table_levels; double phy_downspread_percent; double dcn_downspread_percent; double dispclk_dppclk_vco_speed_mhz; @@ -190,6 +192,7 @@ struct dml2_ip_capabilities { unsigned int max_flip_time_us; unsigned int max_flip_time_lines; unsigned int hostvm_mode; + bool dcn_mrq_present; unsigned int subvp_drr_scheduling_margin_us; unsigned int subvp_prefetch_end_to_mall_start_us; unsigned int subvp_fw_processing_delay; diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_types.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_types.h index 943fd3f040c3..98b26116cdc1 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_types.h +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_types.h @@ -19,6 +19,8 @@ enum dml2_project_id { dml2_project_dcn4x_stage1, dml2_project_dcn4x_stage2, dml2_project_dcn4x_stage2_auto_drr_svp, + dml2_project_dcn40, + dml2_project_dcn42, }; enum dml2_pstate_change_support { @@ -79,6 +81,7 @@ struct dml2_options { struct dml2_pmo_options pmo_options; }; + struct dml2_initialize_instance_in_out { struct dml2_instance *dml2_instance; struct dml2_options options; diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.c index eba948e187c1..99fc2f0666e2 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.c @@ -78,6 +78,86 @@ struct dml2_core_ip_params core_dcn4_ip_caps_base = { .subvp_swath_height_margin_lines = 16, }; +struct dml2_core_ip_params core_dcn42_ip_caps_base = { + .vblank_nom_default_us = 668, + .remote_iommu_outstanding_translations = 256, + .rob_buffer_size_kbytes = 64, + .config_return_buffer_size_in_kbytes = 1792, + .config_return_buffer_segment_size_in_kbytes = 64, + .compressed_buffer_segment_size_in_kbytes = 64, + .dpte_buffer_size_in_pte_reqs_luma = 68, + .dpte_buffer_size_in_pte_reqs_chroma = 36, + .pixel_chunk_size_kbytes = 8, + .alpha_pixel_chunk_size_kbytes = 4, + .min_pixel_chunk_size_bytes = 1024, + .writeback_chunk_size_kbytes = 8, + .line_buffer_size_bits = 1171920, + .max_line_buffer_lines = 32, + .writeback_interface_buffer_size_kbytes = 90, + + //Number of pipes after DCN Pipe harvesting + .max_num_dpp = 4, + .max_num_otg = 4, + .max_num_opp = 4, + .max_num_wb = 1, + .max_dchub_pscl_bw_pix_per_clk = 4, + .max_pscl_lb_bw_pix_per_clk = 2, + .max_lb_vscl_bw_pix_per_clk = 4, + .max_vscl_hscl_bw_pix_per_clk = 4, + .max_hscl_ratio = 6, + .max_vscl_ratio = 6, + .max_hscl_taps = 8, + .max_vscl_taps = 8, + .dispclk_ramp_margin_percent = 1, + .dppclk_delay_subtotal = 47, + .dppclk_delay_scl = 50, + .dppclk_delay_scl_lb_only = 16, + .dppclk_delay_cnvc_formatter = 28, + .dppclk_delay_cnvc_cursor = 6, + .cursor_buffer_size = 42, + .cursor_chunk_size = 2, + .dispclk_delay_subtotal = 125, + .max_inter_dcn_tile_repeaters = 8, + .writeback_max_hscl_ratio = 1, + .writeback_max_vscl_ratio = 1, + .writeback_min_hscl_ratio = 1, + .writeback_min_vscl_ratio = 1, + .writeback_max_hscl_taps = 1, + .writeback_max_vscl_taps = 1, + .writeback_line_buffer_buffer_size = 0, + .num_dsc = 4, + .maximum_dsc_bits_per_component = 12, + .maximum_pixels_per_line_per_dsc_unit = 5760, + .dsc422_native_support = true, + .dcc_supported = true, + .ptoi_supported = false, + + .cursor_64bpp_support = true, + .dynamic_metadata_vm_enabled = false, + + .max_num_hdmi_frl_outputs = 0, + .max_num_dp2p0_outputs = 2, + .max_num_dp2p0_streams = 4, + .imall_supported = 1, + .max_flip_time_us = 110, + .max_flip_time_lines = 50, + .words_per_channel = 16, + + .subvp_fw_processing_delay_us = 15, + .subvp_pstate_allow_width_us = 20, + .subvp_swath_height_margin_lines = 16, + + .dcn_mrq_present = 1, + .zero_size_buffer_entries = 512, + .compbuf_reserved_space_zs = 64, + .dcc_meta_buffer_size_bytes = 6272, + .meta_chunk_size_kbytes = 2, + .min_meta_chunk_size_bytes = 256, + + .dchub_arb_to_ret_delay = 102, + .hostvm_mode = 1, +}; + static void patch_ip_caps_with_explicit_ip_params(struct dml2_ip_capabilities *ip_caps, const struct dml2_core_ip_params *ip_params) { ip_caps->pipe_count = ip_params->max_num_dpp; @@ -107,6 +187,7 @@ static void patch_ip_params_with_ip_caps(struct dml2_core_ip_params *ip_params, { ip_params->max_num_dpp = ip_caps->pipe_count; ip_params->max_num_otg = ip_caps->otg_count; + ip_params->max_num_opp = ip_caps->otg_count; ip_params->num_dsc = ip_caps->num_dsc; ip_params->max_num_dp2p0_streams = ip_caps->max_num_dp2p0_streams; ip_params->max_num_dp2p0_outputs = ip_caps->max_num_dp2p0_outputs; @@ -153,6 +234,37 @@ bool core_dcn4_initialize(struct dml2_core_initialize_in_out *in_out) return true; } +bool core_dcn42_initialize(struct dml2_core_initialize_in_out *in_out) +{ + struct dml2_core_instance *core = in_out->instance; + + if (!in_out->minimum_clock_table) + return false; + else + core->minimum_clock_table = in_out->minimum_clock_table; + + if (in_out->explicit_ip_bb && in_out->explicit_ip_bb_size > 0) { + memcpy(&core->clean_me_up.mode_lib.ip, in_out->explicit_ip_bb, in_out->explicit_ip_bb_size); + + // FIXME_STAGE2: + // DV still uses stage1 ip_param_st for each variant, need to patch the ip_caps with ip_param info + // Should move DV to use ip_caps but need move more overrides to ip_caps + patch_ip_caps_with_explicit_ip_params(in_out->ip_caps, in_out->explicit_ip_bb); + core->clean_me_up.mode_lib.ip.subvp_pstate_allow_width_us = core_dcn4_ip_caps_base.subvp_pstate_allow_width_us; + core->clean_me_up.mode_lib.ip.subvp_fw_processing_delay_us = core_dcn4_ip_caps_base.subvp_pstate_allow_width_us; + core->clean_me_up.mode_lib.ip.subvp_swath_height_margin_lines = core_dcn4_ip_caps_base.subvp_swath_height_margin_lines; + } else { + memcpy(&core->clean_me_up.mode_lib.ip, &core_dcn42_ip_caps_base, sizeof(struct dml2_core_ip_params)); + patch_ip_params_with_ip_caps(&core->clean_me_up.mode_lib.ip, in_out->ip_caps); + core->clean_me_up.mode_lib.ip.imall_supported = false; + } + + memcpy(&core->clean_me_up.mode_lib.soc, in_out->soc_bb, sizeof(struct dml2_soc_bb)); + memcpy(&core->clean_me_up.mode_lib.ip_caps, in_out->ip_caps, sizeof(struct dml2_ip_capabilities)); + + return true; +} + static void create_phantom_stream_from_main_stream(struct dml2_stream_parameters *phantom, const struct dml2_stream_parameters *main, const struct dml2_implicit_svp_meta *meta) { diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.h index a68bb001a346..5c26d819a673 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.h +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.h @@ -5,6 +5,7 @@ #ifndef __DML2_CORE_DCN4_H__ #define __DML2_CORE_DCN4_H__ bool core_dcn4_initialize(struct dml2_core_initialize_in_out *in_out); +bool core_dcn42_initialize(struct dml2_core_initialize_in_out *in_out); bool core_dcn4_mode_support(struct dml2_core_mode_support_in_out *in_out); bool core_dcn4_mode_programming(struct dml2_core_mode_programming_in_out *in_out); bool core_dcn4_populate_informative(struct dml2_core_populate_informative_in_out *in_out); diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c index ca5ac3c0deb5..f6402e199354 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c @@ -202,7 +202,7 @@ static unsigned int dml_round_to_multiple(unsigned int num, unsigned int multipl return (num - remainder); } -static unsigned int dml_get_num_active_pipes(int unsigned num_planes, const struct core_display_cfg_support_info *cfg_support_info) +static unsigned int dml_get_num_active_pipes(unsigned int num_planes, const struct core_display_cfg_support_info *cfg_support_info) { unsigned int num_active_pipes = 0; @@ -546,9 +546,9 @@ static bool dml_is_vertical_rotation(enum dml2_rotation_angle Scan) return is_vert; } -static int unsigned dml_get_gfx_version(enum dml2_swizzle_mode sw_mode) +static unsigned int dml_get_gfx_version(enum dml2_swizzle_mode sw_mode) { - int unsigned version = 0; + unsigned int version = 0; if (sw_mode == dml2_sw_linear || sw_mode == dml2_sw_256b_2d || @@ -1761,7 +1761,7 @@ static unsigned int CalculateVMAndRowBytes(struct dml2_core_shared_calculate_vm_ *p->PixelPTEBytesPerRow = (unsigned int)((double)*p->dpte_row_width_ub / (double)*p->PixelPTEReqWidth * *p->PTERequestSize); // VBA_DELTA, VBA doesn't have programming value for pte row height linear. - *p->dpte_row_height_linear = (unsigned int)1 << (unsigned int)math_floor2(math_log((float)(p->PTEBufferSizeInRequests * PixelPTEReqWidth_linear / p->Pitch), 2.0), 1); + *p->dpte_row_height_linear = 1U << (unsigned int)math_floor2(math_log((float)(p->PTEBufferSizeInRequests * PixelPTEReqWidth_linear / p->Pitch), 2.0), 1); if (*p->dpte_row_height_linear > 128) *p->dpte_row_height_linear = 128; @@ -3377,7 +3377,7 @@ static void calculate_cursor_req_attributes( DML_LOG_VERBOSE("DML::%s: cursor_bytes_per_line = %d\n", __func__, *cursor_bytes_per_line); DML_LOG_VERBOSE("DML::%s: cursor_bytes_per_chunk = %d\n", __func__, *cursor_bytes_per_chunk); DML_LOG_VERBOSE("DML::%s: cursor_bytes = %d\n", __func__, *cursor_bytes); - DML_LOG_VERBOSE("DML::%s: cursor_pitch = %d\n", __func__, cursor_bpp == 2 ? 256 : (unsigned int)1 << (unsigned int)math_ceil2(math_log((float)cursor_width, 2), 1)); + DML_LOG_VERBOSE("DML::%s: cursor_pitch = %d\n", __func__, cursor_bpp == 2 ? 256 : 1U << (unsigned int)math_ceil2(math_log((float)cursor_width, 2), 1)); #endif } @@ -12205,15 +12205,15 @@ static void rq_dlg_get_wm_regs(const struct dml2_display_cfg *display_cfg, const { double refclk_freq_in_mhz = (display_cfg->overrides.hw.dlg_ref_clk_mhz > 0) ? (double)display_cfg->overrides.hw.dlg_ref_clk_mhz : mode_lib->soc.dchub_refclk_mhz; - wm_regs->fclk_pstate = (int unsigned)(mode_lib->mp.Watermark.FCLKChangeWatermark * refclk_freq_in_mhz); - wm_regs->sr_enter = (int unsigned)(mode_lib->mp.Watermark.StutterEnterPlusExitWatermark * refclk_freq_in_mhz); - wm_regs->sr_exit = (int unsigned)(mode_lib->mp.Watermark.StutterExitWatermark * refclk_freq_in_mhz); - wm_regs->sr_enter_z8 = (int unsigned)(mode_lib->mp.Watermark.Z8StutterEnterPlusExitWatermark * refclk_freq_in_mhz); - wm_regs->sr_exit_z8 = (int unsigned)(mode_lib->mp.Watermark.Z8StutterExitWatermark * refclk_freq_in_mhz); - wm_regs->temp_read_or_ppt = (int unsigned)(mode_lib->mp.Watermark.temp_read_or_ppt_watermark_us * refclk_freq_in_mhz); - wm_regs->uclk_pstate = (int unsigned)(mode_lib->mp.Watermark.DRAMClockChangeWatermark * refclk_freq_in_mhz); - wm_regs->urgent = (int unsigned)(mode_lib->mp.Watermark.UrgentWatermark * refclk_freq_in_mhz); - wm_regs->usr = (int unsigned)(mode_lib->mp.Watermark.USRRetrainingWatermark * refclk_freq_in_mhz); + wm_regs->fclk_pstate = (unsigned int)(mode_lib->mp.Watermark.FCLKChangeWatermark * refclk_freq_in_mhz); + wm_regs->sr_enter = (unsigned int)(mode_lib->mp.Watermark.StutterEnterPlusExitWatermark * refclk_freq_in_mhz); + wm_regs->sr_exit = (unsigned int)(mode_lib->mp.Watermark.StutterExitWatermark * refclk_freq_in_mhz); + wm_regs->sr_enter_z8 = (unsigned int)(mode_lib->mp.Watermark.Z8StutterEnterPlusExitWatermark * refclk_freq_in_mhz); + wm_regs->sr_exit_z8 = (unsigned int)(mode_lib->mp.Watermark.Z8StutterExitWatermark * refclk_freq_in_mhz); + wm_regs->temp_read_or_ppt = (unsigned int)(mode_lib->mp.Watermark.temp_read_or_ppt_watermark_us * refclk_freq_in_mhz); + wm_regs->uclk_pstate = (unsigned int)(mode_lib->mp.Watermark.DRAMClockChangeWatermark * refclk_freq_in_mhz); + wm_regs->urgent = (unsigned int)(mode_lib->mp.Watermark.UrgentWatermark * refclk_freq_in_mhz); + wm_regs->usr = (unsigned int)(mode_lib->mp.Watermark.USRRetrainingWatermark * refclk_freq_in_mhz); wm_regs->refcyc_per_trip_to_mem = (unsigned int)(mode_lib->mp.UrgentLatency * refclk_freq_in_mhz); wm_regs->refcyc_per_meta_trip_to_mem = (unsigned int)(mode_lib->mp.MetaTripToMemory * refclk_freq_in_mhz); wm_regs->frac_urg_bw_flip = (unsigned int)(mode_lib->mp.FractionOfUrgentBandwidthImmediateFlip * 1000); @@ -12262,11 +12262,15 @@ static void rq_dlg_get_rq_reg(struct dml2_display_rq_regs *rq_regs, unsigned int pixel_chunk_bytes = 0; unsigned int min_pixel_chunk_bytes = 0; + unsigned int meta_chunk_bytes = 0; + unsigned int min_meta_chunk_bytes = 0; unsigned int dpte_group_bytes = 0; unsigned int mpte_group_bytes = 0; unsigned int p1_pixel_chunk_bytes = 0; unsigned int p1_min_pixel_chunk_bytes = 0; + unsigned int p1_meta_chunk_bytes = 0; + unsigned int p1_min_meta_chunk_bytes = 0; unsigned int p1_dpte_group_bytes = 0; unsigned int p1_mpte_group_bytes = 0; @@ -12287,8 +12291,13 @@ static void rq_dlg_get_rq_reg(struct dml2_display_rq_regs *rq_regs, dpte_group_bytes = (unsigned int)(dml_get_dpte_group_size_in_bytes(mode_lib, pipe_idx)); mpte_group_bytes = (unsigned int)(dml_get_vm_group_size_in_bytes(mode_lib, pipe_idx)); + meta_chunk_bytes = (unsigned int)(mode_lib->ip.meta_chunk_size_kbytes * 1024); + min_meta_chunk_bytes = (unsigned int)(mode_lib->ip.min_meta_chunk_size_bytes); + p1_pixel_chunk_bytes = pixel_chunk_bytes; p1_min_pixel_chunk_bytes = min_pixel_chunk_bytes; + p1_meta_chunk_bytes = meta_chunk_bytes; + p1_min_meta_chunk_bytes = min_meta_chunk_bytes; p1_dpte_group_bytes = dpte_group_bytes; p1_mpte_group_bytes = mpte_group_bytes; @@ -12309,6 +12318,19 @@ static void rq_dlg_get_rq_reg(struct dml2_display_rq_regs *rq_regs, else rq_regs->rq_regs_c.min_chunk_size = log_and_substract_if_non_zero(p1_min_pixel_chunk_bytes, 8 - 1); + rq_regs->rq_regs_l.meta_chunk_size = log_and_substract_if_non_zero(meta_chunk_bytes, 10); + rq_regs->rq_regs_c.meta_chunk_size = log_and_substract_if_non_zero(p1_meta_chunk_bytes, 10); + + if (min_meta_chunk_bytes == 0) + rq_regs->rq_regs_l.min_meta_chunk_size = 0; + else + rq_regs->rq_regs_l.min_meta_chunk_size = log_and_substract_if_non_zero(min_meta_chunk_bytes, 6 - 1); + + if (min_meta_chunk_bytes == 0) + rq_regs->rq_regs_c.min_meta_chunk_size = 0; + else + rq_regs->rq_regs_c.min_meta_chunk_size = log_and_substract_if_non_zero(p1_min_meta_chunk_bytes, 6 - 1); + rq_regs->rq_regs_l.dpte_group_size = log_and_substract_if_non_zero(dpte_group_bytes, 6); rq_regs->rq_regs_l.mpte_group_size = log_and_substract_if_non_zero(mpte_group_bytes, 6); rq_regs->rq_regs_c.dpte_group_size = log_and_substract_if_non_zero(p1_dpte_group_bytes, 6); @@ -12670,7 +12692,7 @@ static void rq_dlg_get_dlg_reg( disp_dlg_regs->refcyc_per_vm_req_flip = (unsigned int)(math_pow(2, 23) - 1); - DML_ASSERT(disp_dlg_regs->dst_y_after_scaler < (unsigned int)8); + DML_ASSERT(disp_dlg_regs->dst_y_after_scaler < 8U); DML_ASSERT(disp_dlg_regs->refcyc_x_after_scaler < (unsigned int)math_pow(2, 13)); if (disp_dlg_regs->dst_y_per_pte_row_nom_l >= (unsigned int)math_pow(2, 17)) { @@ -13226,7 +13248,7 @@ void dml2_core_calcs_get_informative(const struct dml2_core_internal_display_mod out->informative.misc.cstate_max_cap_mode = dml_get_cstate_max_cap_mode(mode_lib); - out->min_clocks.dcn4x.dpprefclk_khz = (int unsigned)dml_get_global_dppclk_khz(mode_lib); + out->min_clocks.dcn4x.dpprefclk_khz = (unsigned int)dml_get_global_dppclk_khz(mode_lib); out->informative.qos.max_active_fclk_change_latency_supported = dml_get_fclk_change_latency(mode_lib); diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.c index cc4f0663c6d6..6cad99c21139 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.c @@ -21,6 +21,7 @@ bool dml2_core_create(enum dml2_project_id project_id, struct dml2_core_instance case dml2_project_dcn4x_stage1: result = false; break; + case dml2_project_dcn40: case dml2_project_dcn4x_stage2: case dml2_project_dcn4x_stage2_auto_drr_svp: out->initialize = &core_dcn4_initialize; @@ -30,6 +31,14 @@ bool dml2_core_create(enum dml2_project_id project_id, struct dml2_core_instance out->calculate_mcache_allocation = &core_dcn4_calculate_mcache_allocation; result = true; break; + case dml2_project_dcn42: + out->initialize = &core_dcn42_initialize; + out->mode_support = &core_dcn4_mode_support; + out->mode_programming = &core_dcn4_mode_programming; + out->populate_informative = &core_dcn4_populate_informative; + out->calculate_mcache_allocation = &core_dcn4_calculate_mcache_allocation; + result = true; + break; case dml2_project_invalid: default: break; diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.c index b57d0f6ea6a1..6930ba7ce5b7 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.c @@ -428,6 +428,9 @@ bool dml2_core_utils_is_phantom_pipe(const struct dml2_plane_parameters *plane_c unsigned int dml2_core_utils_get_tile_block_size_bytes(enum dml2_swizzle_mode sw_mode, unsigned int byte_per_pixel) { + if (dml2_core_utils_get_gfx_version(sw_mode) == 10 || dml2_core_utils_get_gfx_version(sw_mode) == 7) { + return dml2_core_utils_get_tile_block_size_bytes_backcompat(sw_mode, byte_per_pixel); + } if (sw_mode == dml2_sw_linear) return 256; @@ -459,14 +462,56 @@ unsigned int dml2_core_utils_get_tile_block_size_bytes(enum dml2_swizzle_mode sw }; } +unsigned int dml2_core_utils_get_tile_block_size_bytes_backcompat(enum dml2_swizzle_mode sw_mode, unsigned int byte_per_pixel) +{ + if (sw_mode == dml2_sw_linear_256b) + return 256; + else if (sw_mode == dml2_gfx10_sw_64kb_r_x) + return 65536; + else if (sw_mode == dml2_gfx102_sw_64kb_s) + return 65536; + else if (sw_mode == dml2_gfx102_sw_64kb_s_t) + return 65536; + else if (sw_mode == dml2_gfx102_sw_64kb_s_x) + return 65536; + else if (sw_mode == dml2_gfx102_sw_64kb_r_x) + return 65536; + else if (sw_mode == dml2_linear_64elements) + return 256; + else if (sw_mode == dml2_gfx7_1d_thin) + return 256; + else if (sw_mode == dml2_gfx7_2d_thin_gen_zero) + return (128 * 64 * byte_per_pixel); + else if (sw_mode == dml2_gfx7_2d_thin_gen_one) + return (128 * 128 * byte_per_pixel); + else if (sw_mode == dml2_gfx7_2d_thin_arlene) + return (64 * 32 * byte_per_pixel); + else if (sw_mode == dml2_gfx7_2d_thin_anubis) + return (128 * 128 * byte_per_pixel); + else { + DML_ASSERT(0); + return 256; + }; +} + bool dml2_core_utils_get_segment_horizontal_contiguous(enum dml2_swizzle_mode sw_mode, unsigned int byte_per_pixel) { - return (byte_per_pixel != 2); + if (dml2_core_utils_get_gfx_version(sw_mode) == 10 || dml2_core_utils_get_gfx_version(sw_mode) == 7) { + return dml2_core_utils_get_segment_horizontal_contiguous_backcompat(sw_mode, byte_per_pixel); + } else { + return (byte_per_pixel != 2); + } +} + +bool dml2_core_utils_get_segment_horizontal_contiguous_backcompat(enum dml2_swizzle_mode sw_mode, unsigned int byte_per_pixel) +{ + return !((byte_per_pixel == 4) && + ((sw_mode == dml2_gfx10_sw_64kb_r_x) || (sw_mode == dml2_gfx102_sw_64kb_s) || (sw_mode == dml2_gfx102_sw_64kb_s_t) || (sw_mode == dml2_gfx102_sw_64kb_s_x))); } bool dml2_core_utils_is_linear(enum dml2_swizzle_mode sw_mode) { - return sw_mode == dml2_sw_linear; + return (sw_mode == dml2_sw_linear || sw_mode == dml2_sw_linear_256b || sw_mode == dml2_linear_64elements); }; @@ -499,6 +544,20 @@ int unsigned dml2_core_utils_get_gfx_version(enum dml2_swizzle_mode sw_mode) sw_mode == dml2_gfx11_sw_256kb_d_x || sw_mode == dml2_gfx11_sw_256kb_r_x) version = 11; + else if (sw_mode == dml2_sw_linear_256b || + sw_mode == dml2_gfx10_sw_64kb_r_x || + sw_mode == dml2_gfx102_sw_64kb_s || + sw_mode == dml2_gfx102_sw_64kb_s_t || + sw_mode == dml2_gfx102_sw_64kb_s_x || + sw_mode == dml2_gfx102_sw_64kb_r_x) + version = 10; + else if (sw_mode == dml2_linear_64elements || + sw_mode == dml2_gfx7_1d_thin || + sw_mode == dml2_gfx7_2d_thin_gen_zero || + sw_mode == dml2_gfx7_2d_thin_gen_one || + sw_mode == dml2_gfx7_2d_thin_arlene || + sw_mode == dml2_gfx7_2d_thin_anubis) + version = 7; else { DML_LOG_VERBOSE("ERROR: Invalid sw_mode setting! val=%u\n", sw_mode); DML_ASSERT(0); diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.h index 95f0d017add4..471e73ed671c 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.h +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.h @@ -22,6 +22,8 @@ void dml2_core_utils_pipe_plane_mapping(const struct core_display_cfg_support_in bool dml2_core_utils_is_phantom_pipe(const struct dml2_plane_parameters *plane_cfg); unsigned int dml2_core_utils_get_tile_block_size_bytes(enum dml2_swizzle_mode sw_mode, unsigned int byte_per_pixel); bool dml2_core_utils_get_segment_horizontal_contiguous(enum dml2_swizzle_mode sw_mode, unsigned int byte_per_pixel); +unsigned int dml2_core_utils_get_tile_block_size_bytes_backcompat(enum dml2_swizzle_mode sw_mode, unsigned int byte_per_pixel); +bool dml2_core_utils_get_segment_horizontal_contiguous_backcompat(enum dml2_swizzle_mode sw_mode, unsigned int byte_per_pixel); bool dml2_core_utils_is_vertical_rotation(enum dml2_rotation_angle Scan); bool dml2_core_utils_is_linear(enum dml2_swizzle_mode sw_mode); int unsigned dml2_core_utils_get_gfx_version(enum dml2_swizzle_mode sw_mode); diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.c index 9d7741fd0adb..ab0b4a4b5d65 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.c @@ -279,6 +279,26 @@ static bool round_up_and_copy_to_next_dpm(unsigned long min_value, unsigned long bool result = false; int index = 0; + /* Guard against empty clock tables (e.g. DTBCLK on DCN42B where the + * clock is tied off and num_clk_values == 0). Without this check the + * else-if branch below would evaluate + * clk_values_khz[num_clk_values - 1] with num_clk_values == 0, which + * wraps the unsigned char index to 255 — a 235-element out-of-bounds + * read on an array of DML_MAX_CLK_TABLE_SIZE (20) entries. + * + * Semantic: if the clock doesn't exist on this ASIC but no frequency + * is required (min_value == 0), the request is trivially satisfied. + * If a non-zero frequency is required but the clock is absent, the + * configuration is unsupportable. + */ + if (clock_table->num_clk_values == 0) { + if (min_value == 0) { + *rounded_value = 0; + return true; + } + return false; + } + if (clock_table->num_clk_values > 2) { while (index < clock_table->num_clk_values && clock_table->clk_values_khz[index] < min_value) index++; @@ -802,3 +822,36 @@ bool dpmm_dcn4_map_watermarks(struct dml2_dpmm_map_watermarks_params_in_out *in_ return true; } +bool dpmm_dcn42_map_watermarks(struct dml2_dpmm_map_watermarks_params_in_out *in_out) +{ + const struct dml2_display_cfg *display_cfg = &in_out->display_cfg->display_config; + const struct dml2_core_internal_display_mode_lib *mode_lib = &in_out->core->clean_me_up.mode_lib; + struct dml2_dchub_global_register_set *dchubbub_regs = &in_out->programming->global_regs; + + double refclk_freq_in_mhz = (display_cfg->overrides.hw.dlg_ref_clk_mhz > 0) ? (double)display_cfg->overrides.hw.dlg_ref_clk_mhz : mode_lib->soc.dchub_refclk_mhz; + + /* set A */ + dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].fclk_pstate = (int unsigned)(mode_lib->mp.Watermark.FCLKChangeWatermark * refclk_freq_in_mhz); + dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].sr_enter = (int unsigned)(mode_lib->mp.Watermark.StutterEnterPlusExitWatermark * refclk_freq_in_mhz); + dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].sr_exit = (int unsigned)(mode_lib->mp.Watermark.StutterExitWatermark * refclk_freq_in_mhz); + dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].sr_enter_z8 = (int unsigned)(mode_lib->mp.Watermark.Z8StutterEnterPlusExitWatermark * refclk_freq_in_mhz); + dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].sr_exit_z8 = (int unsigned)(mode_lib->mp.Watermark.Z8StutterExitWatermark * refclk_freq_in_mhz); + dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].temp_read_or_ppt = (int unsigned)(mode_lib->mp.Watermark.temp_read_or_ppt_watermark_us * refclk_freq_in_mhz); + dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].uclk_pstate = (int unsigned)(mode_lib->mp.Watermark.DRAMClockChangeWatermark * refclk_freq_in_mhz); + dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].urgent = (int unsigned)(mode_lib->mp.Watermark.UrgentWatermark * refclk_freq_in_mhz); + dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].usr = (int unsigned)(mode_lib->mp.Watermark.USRRetrainingWatermark * refclk_freq_in_mhz); + dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].refcyc_per_trip_to_mem = (unsigned int)(mode_lib->mp.Watermark.UrgentWatermark * refclk_freq_in_mhz); + dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].refcyc_per_meta_trip_to_mem = (unsigned int)(mode_lib->mp.Watermark.UrgentWatermark * refclk_freq_in_mhz); + dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].frac_urg_bw_flip = (unsigned int)(mode_lib->mp.FractionOfUrgentBandwidthImmediateFlip * 1000); + dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].frac_urg_bw_nom = (unsigned int)(mode_lib->mp.FractionOfUrgentBandwidth * 1000); + dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].frac_urg_bw_mall = (unsigned int)(mode_lib->mp.FractionOfUrgentBandwidthMALL * 1000); + + /* set B */ + dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_B] = dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A]; + dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_C] = dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A]; + dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_D] = dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A]; + + dchubbub_regs->num_watermark_sets = 4; + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.h index e7b58f2efda4..5fbd07e238a8 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.h +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.h @@ -10,5 +10,6 @@ bool dpmm_dcn3_map_mode_to_soc_dpm(struct dml2_dpmm_map_mode_to_soc_dpm_params_in_out *in_out); bool dpmm_dcn4_map_mode_to_soc_dpm(struct dml2_dpmm_map_mode_to_soc_dpm_params_in_out *in_out); bool dpmm_dcn4_map_watermarks(struct dml2_dpmm_map_watermarks_params_in_out *in_out); +bool dpmm_dcn42_map_watermarks(struct dml2_dpmm_map_watermarks_params_in_out *in_out); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.c index dfd01440737d..1f2d9e97f5fd 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.c @@ -31,6 +31,7 @@ bool dml2_dpmm_create(enum dml2_project_id project_id, struct dml2_dpmm_instance out->map_watermarks = &dummy_map_watermarks; result = true; break; + case dml2_project_dcn40: case dml2_project_dcn4x_stage2: out->map_mode_to_soc_dpm = &dpmm_dcn3_map_mode_to_soc_dpm; out->map_watermarks = &dummy_map_watermarks; @@ -41,6 +42,11 @@ bool dml2_dpmm_create(enum dml2_project_id project_id, struct dml2_dpmm_instance out->map_watermarks = &dpmm_dcn4_map_watermarks; result = true; break; + case dml2_project_dcn42: + out->map_mode_to_soc_dpm = &dpmm_dcn4_map_mode_to_soc_dpm; + out->map_watermarks = &dpmm_dcn42_map_watermarks; + result = true; + break; case dml2_project_invalid: default: break; diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.c index a265f254152c..eab13e1c96fd 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.c @@ -178,9 +178,12 @@ static bool build_min_clock_table(const struct dml2_soc_bb *soc_bb, struct dml2_ min_table->max_clocks_khz.dispclk = soc_bb->clk_table.dispclk.clk_values_khz[soc_bb->clk_table.dispclk.num_clk_values - 1]; min_table->max_clocks_khz.dppclk = soc_bb->clk_table.dppclk.clk_values_khz[soc_bb->clk_table.dppclk.num_clk_values - 1]; - min_table->max_clocks_khz.dscclk = soc_bb->clk_table.dscclk.clk_values_khz[soc_bb->clk_table.dscclk.num_clk_values - 1]; - min_table->max_clocks_khz.dtbclk = soc_bb->clk_table.dtbclk.clk_values_khz[soc_bb->clk_table.dtbclk.num_clk_values - 1]; - min_table->max_clocks_khz.phyclk = soc_bb->clk_table.phyclk.clk_values_khz[soc_bb->clk_table.phyclk.num_clk_values - 1]; + min_table->max_clocks_khz.dscclk = (soc_bb->clk_table.dscclk.num_clk_values > 0) ? + soc_bb->clk_table.dscclk.clk_values_khz[soc_bb->clk_table.dscclk.num_clk_values - 1] : 0; + min_table->max_clocks_khz.dtbclk = (soc_bb->clk_table.dtbclk.num_clk_values > 0) ? + soc_bb->clk_table.dtbclk.clk_values_khz[soc_bb->clk_table.dtbclk.num_clk_values - 1] : 0; + min_table->max_clocks_khz.phyclk = (soc_bb->clk_table.phyclk.num_clk_values > 0) ? + soc_bb->clk_table.phyclk.clk_values_khz[soc_bb->clk_table.phyclk.num_clk_values - 1] : 0; min_table->max_ss_clocks_khz.dispclk = (unsigned int)((double)min_table->max_clocks_khz.dispclk / (1.0 + soc_bb->dcn_downspread_percent / 100.0)); min_table->max_ss_clocks_khz.dppclk = (unsigned int)((double)min_table->max_clocks_khz.dppclk / (1.0 + soc_bb->dcn_downspread_percent / 100.0)); diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.h index f54fde8fba90..02da6f45cbf7 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.h +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.h @@ -10,4 +10,4 @@ bool mcg_dcn4_build_min_clock_table(struct dml2_mcg_build_min_clock_table_params_in_out *in_out); bool mcg_dcn4_unit_test(void); -#endif
\ No newline at end of file +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn42.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn42.c new file mode 100644 index 000000000000..3eaeff39ee79 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn42.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: MIT +// +// Copyright 2026 Advanced Micro Devices, Inc. + +#include "dml2_mcg_dcn42.h" +#include "dml_top_soc_parameter_types.h" + +static unsigned long long uclk_to_dram_bw_kbps(unsigned long uclk_khz, const struct dml2_dram_params *dram_config, unsigned long wck_ratio) +{ + unsigned long long bw_kbps = 0; + + bw_kbps = (unsigned long long) uclk_khz * dram_config->channel_count * dram_config->channel_width_bytes * wck_ratio * 2; + return bw_kbps; +} + +static bool build_min_clk_table_coarse_grained(const struct dml2_soc_bb *soc_bb, struct dml2_mcg_min_clock_table *min_table) +{ + int i; + + for (i = 0; i < soc_bb->clk_table.fclk.num_clk_values; i++) { + if (i < soc_bb->clk_table.uclk.num_clk_values) { + min_table->dram_bw_table.entries[i].pre_derate_dram_bw_kbps = + uclk_to_dram_bw_kbps(soc_bb->clk_table.uclk.clk_values_khz[i], &soc_bb->clk_table.dram_config, soc_bb->clk_table.wck_ratio.clk_values_khz[i]); + min_table->dram_bw_table.entries[i].min_uclk_khz = soc_bb->clk_table.uclk.clk_values_khz[i]; + } else { + min_table->dram_bw_table.entries[i].pre_derate_dram_bw_kbps = min_table->dram_bw_table.entries[soc_bb->clk_table.uclk.num_clk_values - 1].pre_derate_dram_bw_kbps; + min_table->dram_bw_table.entries[i].min_uclk_khz = soc_bb->clk_table.uclk.clk_values_khz[soc_bb->clk_table.uclk.num_clk_values - 1]; + } + + min_table->dram_bw_table.entries[i].min_dcfclk_khz = soc_bb->clk_table.dcfclk.clk_values_khz[i]; + min_table->dram_bw_table.entries[i].min_fclk_khz = soc_bb->clk_table.fclk.clk_values_khz[i]; + } + min_table->dram_bw_table.num_entries = soc_bb->clk_table.fclk.num_clk_values; + + return true; +} + +static bool build_min_clock_table(const struct dml2_soc_bb *soc_bb, struct dml2_mcg_min_clock_table *min_table) +{ + bool result; + + if (!soc_bb || !min_table) + return false; + + + if (soc_bb->clk_table.uclk.num_clk_values > DML_MCG_MAX_CLK_TABLE_SIZE) + return false; + + min_table->fixed_clocks_khz.amclk = 0; + min_table->fixed_clocks_khz.dprefclk = soc_bb->dprefclk_mhz * 1000; + min_table->fixed_clocks_khz.pcierefclk = soc_bb->pcie_refclk_mhz * 1000; + min_table->fixed_clocks_khz.dchubrefclk = soc_bb->dchub_refclk_mhz * 1000; + min_table->fixed_clocks_khz.xtalclk = soc_bb->xtalclk_mhz * 1000; + + min_table->max_clocks_khz.dispclk = soc_bb->clk_table.dispclk.clk_values_khz[soc_bb->clk_table.dispclk.num_clk_values - 1]; + min_table->max_clocks_khz.dppclk = soc_bb->clk_table.dppclk.clk_values_khz[soc_bb->clk_table.dppclk.num_clk_values - 1]; + min_table->max_clocks_khz.dscclk = (soc_bb->clk_table.dscclk.num_clk_values > 0) ? + soc_bb->clk_table.dscclk.clk_values_khz[soc_bb->clk_table.dscclk.num_clk_values - 1] : 0; + min_table->max_clocks_khz.dtbclk = (soc_bb->clk_table.dtbclk.num_clk_values > 0) ? + soc_bb->clk_table.dtbclk.clk_values_khz[soc_bb->clk_table.dtbclk.num_clk_values - 1] : 0; + min_table->max_clocks_khz.phyclk = (soc_bb->clk_table.phyclk.num_clk_values > 0) ? + soc_bb->clk_table.phyclk.clk_values_khz[soc_bb->clk_table.phyclk.num_clk_values - 1] : 0; + + min_table->max_ss_clocks_khz.dispclk = (unsigned int)((double)min_table->max_clocks_khz.dispclk / (1.0 + soc_bb->dcn_downspread_percent / 100.0)); + min_table->max_ss_clocks_khz.dppclk = (unsigned int)((double)min_table->max_clocks_khz.dppclk / (1.0 + soc_bb->dcn_downspread_percent / 100.0)); + min_table->max_ss_clocks_khz.dtbclk = (unsigned int)((double)min_table->max_clocks_khz.dtbclk / (1.0 + soc_bb->dcn_downspread_percent / 100.0)); + + min_table->max_clocks_khz.dcfclk = soc_bb->clk_table.dcfclk.clk_values_khz[soc_bb->clk_table.dcfclk.num_clk_values - 1]; + min_table->max_clocks_khz.fclk = soc_bb->clk_table.fclk.clk_values_khz[soc_bb->clk_table.fclk.num_clk_values - 1]; + + result = build_min_clk_table_coarse_grained(soc_bb, min_table); + + return result; +} + +bool mcg_dcn42_build_min_clock_table(struct dml2_mcg_build_min_clock_table_params_in_out *in_out) +{ + return build_min_clock_table(in_out->soc_bb, in_out->min_clk_table); +} diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn42.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn42.h new file mode 100644 index 000000000000..d4ea49e3e674 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn42.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: MIT */ +// +// Copyright 2026 Advanced Micro Devices, Inc. + +#ifndef __DML2_MCG_DCN42_H__ +#define __DML2_MCG_DCN42_H__ + +#include "dml2_internal_shared_types.h" + +bool mcg_dcn42_build_min_clock_table(struct dml2_mcg_build_min_clock_table_params_in_out *in_out); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.c index c60b8fe90819..3dcd2c250633 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.c @@ -4,6 +4,7 @@ #include "dml2_mcg_factory.h" #include "dml2_mcg_dcn4.h" +#include "dml2_mcg_dcn42.h" #include "dml2_external_lib_deps.h" static bool dummy_build_min_clock_table(struct dml2_mcg_build_min_clock_table_params_in_out *in_out) @@ -25,11 +26,16 @@ bool dml2_mcg_create(enum dml2_project_id project_id, struct dml2_mcg_instance * out->build_min_clock_table = &dummy_build_min_clock_table; result = true; break; + case dml2_project_dcn40: case dml2_project_dcn4x_stage2: case dml2_project_dcn4x_stage2_auto_drr_svp: out->build_min_clock_table = &mcg_dcn4_build_min_clock_table; result = true; break; + case dml2_project_dcn42: + out->build_min_clock_table = &mcg_dcn42_build_min_clock_table; + result = true; + break; case dml2_project_invalid: default: break; diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c index c26e100fcaf2..e8691983c0eb 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c @@ -23,6 +23,7 @@ static const struct dml2_pmo_pstate_strategy base_strategy_list_1_display[] = { .allow_state_increase = true, }, + // Then VBlank { .per_stream_pstate_method = { dml2_pstate_method_vblank, dml2_pstate_method_na, dml2_pstate_method_na, dml2_pstate_method_na }, @@ -53,6 +54,7 @@ static const struct dml2_pmo_pstate_strategy base_strategy_list_2_display[] = { .allow_state_increase = true, }, + // Then VActive + VBlank { .per_stream_pstate_method = { dml2_pstate_method_vactive, dml2_pstate_method_vblank, dml2_pstate_method_na, dml2_pstate_method_na }, @@ -113,6 +115,7 @@ static const struct dml2_pmo_pstate_strategy base_strategy_list_3_display[] = { .allow_state_increase = true, }, + // VActive + 1 VBlank { .per_stream_pstate_method = { dml2_pstate_method_vactive, dml2_pstate_method_vactive, dml2_pstate_method_vblank, dml2_pstate_method_na }, @@ -149,6 +152,7 @@ static const struct dml2_pmo_pstate_strategy base_strategy_list_4_display[] = { .allow_state_increase = true, }, + // VActive + 1 VBlank { .per_stream_pstate_method = { dml2_pstate_method_vactive, dml2_pstate_method_vactive, dml2_pstate_method_vactive, dml2_pstate_method_vblank }, @@ -1651,6 +1655,7 @@ static bool validate_pstate_support_strategy_cofunctionality(struct dml2_pmo_ins if (svp_count > 0 && (pmo->options->disable_svp || !all_timings_support_svp(pmo, display_cfg, svp_stream_mask))) return false; + return is_config_schedulable(pmo, display_cfg, pstate_strategy); } @@ -1980,6 +1985,7 @@ static void reset_display_configuration(struct display_configuation_with_meta *d } } + static void setup_planes_for_drr_by_mask(struct display_configuation_with_meta *display_config, struct dml2_pmo_instance *pmo, int plane_mask) diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.c index 55d2464365d0..4d687fa86caa 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.c @@ -3,8 +3,8 @@ // Copyright 2024 Advanced Micro Devices, Inc. #include "dml2_pmo_factory.h" -#include "dml2_pmo_dcn4_fams2.h" #include "dml2_pmo_dcn3.h" +#include "dml2_pmo_dcn4_fams2.h" #include "dml2_external_lib_deps.h" static bool dummy_init_for_stutter(struct dml2_pmo_init_for_stutter_in_out *in_out) @@ -37,6 +37,7 @@ bool dml2_pmo_create(enum dml2_project_id project_id, struct dml2_pmo_instance * out->optimize_dcc_mcache = pmo_dcn4_fams2_optimize_dcc_mcache; result = true; break; + case dml2_project_dcn40: case dml2_project_dcn4x_stage2: out->initialize = pmo_dcn3_initialize; @@ -56,6 +57,7 @@ bool dml2_pmo_create(enum dml2_project_id project_id, struct dml2_pmo_instance * result = true; break; + case dml2_project_dcn42: case dml2_project_dcn4x_stage2_auto_drr_svp: out->initialize = pmo_dcn4_fams2_initialize; diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.h index b90f6263cd85..7218de1824cc 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.h +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.h @@ -10,4 +10,4 @@ bool dml2_pmo_create(enum dml2_project_id project_id, struct dml2_pmo_instance *out); -#endif
\ No newline at end of file +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_interfaces.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_interfaces.c index 5a33e2f357f4..a6c5031f69c1 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_interfaces.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_interfaces.c @@ -17,6 +17,8 @@ bool dml2_initialize_instance(struct dml2_initialize_instance_in_out *in_out) case dml2_project_dcn4x_stage1: case dml2_project_dcn4x_stage2: case dml2_project_dcn4x_stage2_auto_drr_svp: + case dml2_project_dcn40: + case dml2_project_dcn42: return dml2_top_soc15_initialize_instance(in_out); case dml2_project_invalid: default: diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_legacy.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_legacy.c index 5e14d85821e2..0e3177fe9d27 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_legacy.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_legacy.c @@ -3,7 +3,6 @@ // Copyright 2024 Advanced Micro Devices, Inc. #include "dml2_top_legacy.h" -#include "dml2_top_soc15.h" #include "dml2_core_factory.h" #include "dml2_pmo_factory.h" #include "display_mode_core_structs.h" diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/inc/dml2_internal_shared_types.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/inc/dml2_internal_shared_types.h index a6bd75f30d20..d328d92240b4 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/inc/dml2_internal_shared_types.h +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/inc/dml2_internal_shared_types.h @@ -410,6 +410,7 @@ struct dml2_core_mode_support_in_out { } legacy; }; + struct dml2_core_mode_programming_in_out { /* * Inputs @@ -501,6 +502,7 @@ struct dml2_core_instance { bool (*populate_informative)(struct dml2_core_populate_informative_in_out *in_out); bool (*calculate_mcache_allocation)(struct dml2_calculate_mcache_allocation_in_out *in_out); + struct { struct dml2_core_internal_display_mode_lib mode_lib; } clean_me_up; @@ -753,6 +755,7 @@ struct dml2_pmo_instance { bool (*test_for_stutter)(struct dml2_pmo_test_for_stutter_in_out *in_out); bool (*optimize_for_stutter)(struct dml2_pmo_optimize_for_stutter_in_out *in_out); + struct dml2_pmo_init_data init_data; struct dml2_pmo_scratch scratch; }; diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_dc_resource_mgmt.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_dc_resource_mgmt.c index 4cfe64aa8492..6ef93c6fc1cd 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_dc_resource_mgmt.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_dc_resource_mgmt.c @@ -35,7 +35,7 @@ #define MAX_MPCC_FACTOR 4 struct dc_plane_pipe_pool { - int pipes_assigned_to_plane[MAX_ODM_FACTOR][MAX_MPCC_FACTOR]; + unsigned int pipes_assigned_to_plane[MAX_ODM_FACTOR][MAX_MPCC_FACTOR]; bool pipe_used[MAX_ODM_FACTOR][MAX_MPCC_FACTOR]; int num_pipes_assigned_to_plane_for_mpcc_combine; int num_pipes_assigned_to_plane_for_odm_combine; @@ -143,7 +143,7 @@ static unsigned int find_pipes_assigned_to_plane(struct dml2_context *ctx, { int i; unsigned int num_found = 0; - unsigned int plane_id_assigned_to_pipe = -1; + unsigned int plane_id_assigned_to_pipe = UINT_MAX; for (i = 0; i < ctx->config.dcn_pipe_count; i++) { struct pipe_ctx *pipe = &state->res_ctx.pipe_ctx[i]; @@ -340,8 +340,8 @@ static bool is_pipe_in_candidate_array(const unsigned int pipe_idx, static bool find_more_pipes_for_stream(struct dml2_context *ctx, struct dc_state *state, // The state we want to find a free mapping in unsigned int stream_id, // The stream we want this pipe to drive - int *assigned_pipes, - int *assigned_pipe_count, + unsigned int *assigned_pipes, + unsigned int *assigned_pipe_count, int pipes_needed, const struct dc_state *existing_state) // The state (optional) that we want to minimize remapping relative to { @@ -366,7 +366,8 @@ static bool find_more_pipes_for_stream(struct dml2_context *ctx, if (!is_plane_using_pipe(pipe)) { pipes_needed--; // TODO: This doens't make sense really, pipe_idx should always be valid - pipe->pipe_idx = preferred_pipe_candidates[i]; + ASSERT(preferred_pipe_candidates[i] <= 0xFF); + pipe->pipe_idx = (uint8_t)preferred_pipe_candidates[i]; assigned_pipes[(*assigned_pipe_count)++] = pipe->pipe_idx; } } @@ -382,7 +383,8 @@ static bool find_more_pipes_for_stream(struct dml2_context *ctx, if (!is_plane_using_pipe(pipe)) { pipes_needed--; // TODO: This doens't make sense really, pipe_idx should always be valid - pipe->pipe_idx = i; + ASSERT(i >= 0 && i <= 0xFF); + pipe->pipe_idx = (uint8_t)i; assigned_pipes[(*assigned_pipe_count)++] = pipe->pipe_idx; } } @@ -393,7 +395,8 @@ static bool find_more_pipes_for_stream(struct dml2_context *ctx, if (!is_plane_using_pipe(pipe)) { pipes_needed--; // TODO: This doens't make sense really, pipe_idx should always be valid - pipe->pipe_idx = last_resort_pipe_candidates[i]; + ASSERT(last_resort_pipe_candidates[i] <= 0xFF); + pipe->pipe_idx = (uint8_t)last_resort_pipe_candidates[i]; assigned_pipes[(*assigned_pipe_count)++] = pipe->pipe_idx; } } @@ -406,8 +409,8 @@ static bool find_more_pipes_for_stream(struct dml2_context *ctx, static bool find_more_free_pipes(struct dml2_context *ctx, struct dc_state *state, // The state we want to find a free mapping in unsigned int stream_id, // The stream we want this pipe to drive - int *assigned_pipes, - int *assigned_pipe_count, + unsigned int *assigned_pipes, + unsigned int *assigned_pipe_count, int pipes_needed, const struct dc_state *existing_state) // The state (optional) that we want to minimize remapping relative to { @@ -432,7 +435,8 @@ static bool find_more_free_pipes(struct dml2_context *ctx, if (is_pipe_free(pipe)) { pipes_needed--; // TODO: This doens't make sense really, pipe_idx should always be valid - pipe->pipe_idx = preferred_pipe_candidates[i]; + ASSERT(preferred_pipe_candidates[i] <= 0xFF); + pipe->pipe_idx = (uint8_t)preferred_pipe_candidates[i]; assigned_pipes[(*assigned_pipe_count)++] = pipe->pipe_idx; } } @@ -448,7 +452,8 @@ static bool find_more_free_pipes(struct dml2_context *ctx, if (is_pipe_free(pipe)) { pipes_needed--; // TODO: This doens't make sense really, pipe_idx should always be valid - pipe->pipe_idx = i; + ASSERT(i >= 0 && i <= 0xFF); + pipe->pipe_idx = (uint8_t)i; assigned_pipes[(*assigned_pipe_count)++] = pipe->pipe_idx; } } @@ -459,7 +464,8 @@ static bool find_more_free_pipes(struct dml2_context *ctx, if (is_pipe_free(pipe)) { pipes_needed--; // TODO: This doens't make sense really, pipe_idx should always be valid - pipe->pipe_idx = last_resort_pipe_candidates[i]; + ASSERT(last_resort_pipe_candidates[i] <= 0xFF); + pipe->pipe_idx = (uint8_t)last_resort_pipe_candidates[i]; assigned_pipes[(*assigned_pipe_count)++] = pipe->pipe_idx; } } @@ -909,10 +915,10 @@ static unsigned int get_source_mpc_factor(const struct dml2_context *ctx, const struct dc_plane_state *plane) { struct pipe_ctx *dpp_pipes[MAX_PIPES] = {0}; - int dpp_pipe_count = ctx->config.callbacks.get_dpp_pipes_for_plane(plane, - &state->res_ctx, dpp_pipes); - ASSERT(dpp_pipe_count > 0); + if (ctx->config.callbacks.get_dpp_pipes_for_plane(plane, &state->res_ctx, dpp_pipes) <= 0) + ASSERT(false); + return ctx->config.callbacks.get_mpc_slice_count(dpp_pipes[0]); } diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_mall_phantom.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_mall_phantom.c index 66040c877d68..9bbe4e058be7 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_mall_phantom.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_mall_phantom.c @@ -357,7 +357,7 @@ static bool enough_pipes_for_subvp(struct dml2_context *ctx, struct dc_state *st */ static bool subvp_subvp_schedulable(struct dml2_context *ctx, struct dc_state *context) { - struct pipe_ctx *subvp_pipes[2]; + struct pipe_ctx *subvp_pipes[2] = { NULL, NULL }; struct dc_stream_state *phantom = NULL; uint32_t microschedule_lines = 0; uint32_t index = 0; @@ -369,6 +369,9 @@ static bool subvp_subvp_schedulable(struct dml2_context *ctx, struct dc_state *c struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; uint32_t time_us = 0; + if (pipe == NULL || pipe->stream == NULL) + continue; + /* Loop to calculate the maximum microschedule time between the two SubVP pipes, * and also to store the two main SubVP pipe pointers in subvp_pipes[2]. */ @@ -386,14 +389,19 @@ static bool subvp_subvp_schedulable(struct dml2_context *ctx, struct dc_state *c if (time_us > max_microschedule_us) max_microschedule_us = time_us; - subvp_pipes[index] = pipe; - index++; + if (index < 2) + subvp_pipes[index++] = pipe; // Maximum 2 SubVP pipes if (index == 2) break; } } + + /* Minimal guard to avoid C6001 before subvp_pipes[0]/[1] dereference */ + if (index < 2 || !subvp_pipes[0] || !subvp_pipes[1]) + return false; + vactive1_us = ((subvp_pipes[0]->stream->timing.v_addressable * subvp_pipes[0]->stream->timing.h_total) / (double)(subvp_pipes[0]->stream->timing.pix_clk_100hz * 100)) * 1000000; vactive2_us = ((subvp_pipes[1]->stream->timing.v_addressable * subvp_pipes[1]->stream->timing.h_total) / @@ -459,6 +467,11 @@ bool dml2_svp_drr_schedulable(struct dml2_context *ctx, struct dc_state *context break; } + if (pipe == NULL || pipe->stream == NULL) { + // Defensive: should never happen, try to catch in debug + ASSERT(0); + return false; + } phantom_stream = ctx->config.svp_pstate.callbacks.get_paired_subvp_stream(context, pipe->stream); main_timing = &pipe->stream->timing; phantom_timing = &phantom_stream->timing; @@ -542,13 +555,21 @@ static bool subvp_vblank_schedulable(struct dml2_context *ctx, struct dc_state * if (!found && pipe_mall_type == SUBVP_NONE) { // Found pipe which is not SubVP or Phantom (i.e. the VBLANK pipe). - vblank_index = i; + ASSERT(i <= 0xFF); + vblank_index = (uint8_t)i; found = true; } if (!subvp_pipe && pipe_mall_type == SUBVP_MAIN) subvp_pipe = pipe; } + + if (subvp_pipe == NULL) { + // Defensive: should never happen, catch in debug + ASSERT(0); + return false; + } + // Use ignore_msa_timing_param flag to identify as DRR if (found && context->res_ctx.pipe_ctx[vblank_index].stream->ignore_msa_timing_param) { // SUBVP + DRR case @@ -753,6 +774,12 @@ static void enable_phantom_plane(struct dml2_context *ctx, return; } + /* Minimal NULL guard for C6011 */ + if (!phantom_plane) { + ASSERT(0); + continue; + } + memcpy(&phantom_plane->address, &curr_pipe->plane_state->address, sizeof(phantom_plane->address)); memcpy(&phantom_plane->scaling_quality, &curr_pipe->plane_state->scaling_quality, sizeof(phantom_plane->scaling_quality)); @@ -880,6 +907,11 @@ bool dml2_svp_add_phantom_pipe_to_dc_state(struct dml2_context *ctx, struct dc_s if (ctx->config.svp_pstate.force_disable_subvp) return false; + if (!state) { + ASSERT(0); + return false; + } + if (!all_pipes_have_stream_and_plane(ctx, state)) return false; @@ -898,6 +930,10 @@ bool dml2_svp_add_phantom_pipe_to_dc_state(struct dml2_context *ctx, struct dc_s } if (enough_pipes_for_subvp(ctx, state) && assign_subvp_pipe(ctx, state, &dc_pipe_idx)) { + if (state->res_ctx.pipe_ctx[dc_pipe_idx].stream == NULL) { + ASSERT(0); + return false; + } dml_pipe_idx = dml2_helper_find_dml_pipe_idx_by_stream_id(ctx, state->res_ctx.pipe_ctx[dc_pipe_idx].stream->stream_id); svp_height = mode_support_info->SubViewportLinesNeededInMALL[dml_pipe_idx]; vstartup = dml_get_vstartup_calculated(&ctx->v20.dml_core_ctx, dml_pipe_idx); diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_translation_helper.c index d834cb595afa..cf3a69aba638 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_translation_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_translation_helper.c @@ -330,8 +330,8 @@ void dml2_init_soc_states(struct dml2_context *dml2, const struct dc *in_dc, { struct dml2_policy_build_synthetic_soc_states_scratch *s = &dml2->v20.scratch.create_scratch.build_synthetic_socbb_scratch; struct dml2_policy_build_synthetic_soc_states_params *p = &dml2->v20.scratch.build_synthetic_socbb_params; - unsigned int dcfclk_stas_mhz[NUM_DCFCLK_STAS] = {0}; - unsigned int dcfclk_stas_mhz_new[NUM_DCFCLK_STAS_NEW] = {0}; + int dcfclk_stas_mhz[NUM_DCFCLK_STAS] = {0}; + int dcfclk_stas_mhz_new[NUM_DCFCLK_STAS_NEW] = {0}; unsigned int dml_project = dml2->v20.dml_core_ctx.project; unsigned int i = 0; @@ -765,7 +765,7 @@ static void populate_dml_timing_cfg_from_stream_state(struct dml_timing_cfg_st * out->PixelClock[location] *= 2; out->HTotal[location] = in->timing.h_total; out->VTotal[location] = in->timing.v_total; - out->Interlace[location] = in->timing.flags.INTERLACE; + out->Interlace[location] = (in->timing.flags.INTERLACE != 0); hblank_start = in->timing.h_total - in->timing.h_front_porch; out->HBlankEnd[location] = hblank_start - in->timing.h_addressable @@ -1174,12 +1174,12 @@ static unsigned int map_plane_to_dml_display_cfg(const struct dml2_context *dml2 const struct dc_state *context, const struct dml_display_cfg_st *dml_dispcfg, unsigned int stream_id, int plane_index) { unsigned int plane_id; - int i = 0; - int location = -1; + unsigned int i = 0; + unsigned int location = UINT_MAX; if (!get_plane_id(context->bw_ctx.dml2, context, plane, stream_id, plane_index, &plane_id)) { ASSERT(false); - return -1; + return UINT_MAX; } for (i = 0; i < __DML2_WRAPPER_MAX_STREAMS_PLANES__; i++) { diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_utils.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_utils.c index 9a33158b63bf..6c7cdf102906 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_utils.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_utils.c @@ -255,7 +255,8 @@ static void populate_pipe_ctx_dlg_params_from_dml(struct pipe_ctx *pipe_ctx, str pipe_ctx->pipe_dlg_param.vupdate_width = dml_get_vupdate_width(mode_lib, pipe_idx); pipe_ctx->pipe_dlg_param.vready_offset = dml_get_vready_offset(mode_lib, pipe_idx); - pipe_ctx->pipe_dlg_param.otg_inst = pipe_ctx->stream_res.tg->inst; + ASSERT(pipe_ctx->stream_res.tg->inst >= 0 && pipe_ctx->stream_res.tg->inst <= 0xFF); + pipe_ctx->pipe_dlg_param.otg_inst = (unsigned char)pipe_ctx->stream_res.tg->inst; pipe_ctx->pipe_dlg_param.hactive = hactive; pipe_ctx->pipe_dlg_param.vactive = vactive; diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.c index 307186eb6af0..93b7613fc4f2 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.c @@ -6,8 +6,24 @@ */ #include "dml2_internal_types.h" +#include "dml2_wrapper.h" #include "dml2_wrapper_fpu.h" +#include "dml21_wrapper.h" +#include "dml21_wrapper_fpu.h" +#include "dc_fpu.h" + +#if !defined(DC_RUN_WITH_PREEMPTION_ENABLED) +#define DC_RUN_WITH_PREEMPTION_ENABLED(code) code +#endif // !DC_RUN_WITH_PREEMPTION_ENABLED + +struct dml2_context *dml2_allocate_memory(void) +{ + struct dml2_context *dml2; + + DC_RUN_WITH_PREEMPTION_ENABLED(dml2 = vzalloc(sizeof(struct dml2_context))); + return dml2; +} bool dml2_validate(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml2, enum dc_validate_mode validate_mode) { @@ -23,16 +39,12 @@ bool dml2_validate(const struct dc *in_dc, struct dc_state *context, struct dml2 return out; } - DC_FP_START(); - /* Use dml_validate_only for DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX path */ if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING) out = dml2_validate_only(context, validate_mode); else out = dml2_validate_and_build_resource(in_dc, context, validate_mode); - DC_FP_END(); - return out; } @@ -70,22 +82,20 @@ static void dml2_init(const struct dc *in_dc, const struct dml2_configuration_op break; } - DC_FP_START(); - initialize_dml2_ip_params(*dml2, in_dc, &(*dml2)->v20.dml_core_ctx.ip); initialize_dml2_soc_bbox(*dml2, in_dc, &(*dml2)->v20.dml_core_ctx.soc); initialize_dml2_soc_states(*dml2, in_dc, &(*dml2)->v20.dml_core_ctx.soc, &(*dml2)->v20.dml_core_ctx.states); - DC_FP_END(); } bool dml2_create(const struct dc *in_dc, const struct dml2_configuration_options *config, struct dml2_context **dml2) { // TODO : Temporarily add DCN_VERSION_3_2 for N-1 validation. Remove DCN_VERSION_3_2 after N-1 validation phase is complete. - if ((in_dc->debug.using_dml21) && (in_dc->ctx->dce_version >= DCN_VERSION_4_01)) + if ((in_dc->debug.using_dml21) && (in_dc->ctx->dce_version >= DCN_VERSION_4_01)) { return dml21_create(in_dc, dml2, config); + } // Allocate Mode Lib Ctx *dml2 = dml2_allocate_memory(); diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.h index 9a9c27962f68..5ee489682f2e 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.h +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.h @@ -239,6 +239,7 @@ struct dml2_configuration_options { bool use_clock_dc_limits; bool gpuvm_enable; + bool hostvm_enable; bool force_tdlut_enable; void *bb_from_dmub; }; diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper_fpu.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper_fpu.c index 203eef747262..66624cfc27b1 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper_fpu.c @@ -31,8 +31,10 @@ #include "dml2_translation_helper.h" #include "dml2_mall_phantom.h" #include "dml2_dc_resource_mgmt.h" -#include "dml21_wrapper.h" +#include "dml2_wrapper.h" #include "dml2_wrapper_fpu.h" +#include "dml21_wrapper.h" +#include "dml21_wrapper_fpu.h" void initialize_dml2_ip_params(struct dml2_context *dml2, const struct dc *in_dc, struct ip_params_st *out) { @@ -546,11 +548,6 @@ void dml2_apply_debug_options(const struct dc *dc, struct dml2_context *dml2) } } -inline struct dml2_context *dml2_allocate_memory(void) -{ - return (struct dml2_context *) vzalloc(sizeof(struct dml2_context)); -} - void dml2_destroy(struct dml2_context *dml2) { if (!dml2) diff --git a/drivers/gpu/drm/amd/display/dc/dpp/Makefile b/drivers/gpu/drm/amd/display/dc/dpp/Makefile index 8324a56fe7db..2595b2504f9d 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dpp/Makefile @@ -1,5 +1,5 @@ -# Copyright 2022 Advanced Micro Devices, Inc. +# Copyright 2022-2026 Advanced Micro Devices, Inc. # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), @@ -80,4 +80,12 @@ AMD_DAL_DPP_DCN401 = $(addprefix $(AMDDALPATH)/dc/dpp/dcn401/,$(DPP_DCN401)) AMD_DISPLAY_FILES += $(AMD_DAL_DPP_DCN401) +############################################################################### +# DCN42 +############################################################################### +DPP_DCN42 = dcn42_dpp.o + +AMD_DAL_DPP_DCN42 = $(addprefix $(AMDDALPATH)/dc/dpp/dcn42/,$(DPP_DCN42)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DPP_DCN42) endif diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.c index ce91e5d28956..ef605e0a75e3 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.c @@ -172,10 +172,14 @@ bool dpp1_get_optimal_number_of_taps( scl_data->taps.h_taps_c = in_taps->h_taps_c; if (!dpp->ctx->dc->debug.always_scale) { - if (IDENTITY_RATIO(scl_data->ratios.horz)) + if (IDENTITY_RATIO(scl_data->ratios.horz)) { scl_data->taps.h_taps = 1; - if (IDENTITY_RATIO(scl_data->ratios.vert)) + scl_data->taps.h_taps_c = 1; + } + if (IDENTITY_RATIO(scl_data->ratios.vert)) { scl_data->taps.v_taps = 1; + scl_data->taps.v_taps_c = 1; + } if (IDENTITY_RATIO(scl_data->ratios.horz_c)) scl_data->taps.h_taps_c = 1; if (IDENTITY_RATIO(scl_data->ratios.vert_c)) @@ -284,6 +288,7 @@ void dpp1_cnv_setup ( enum dc_color_space input_color_space, struct cnv_alpha_2bit_lut *alpha_2bit_lut) { + (void)alpha_2bit_lut; uint32_t pixel_format; uint32_t alpha_en; enum pixel_format_description fmt ; diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp_dscl.c index 808bca9fb804..0d2c9fcd3362 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp_dscl.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp_dscl.c @@ -102,7 +102,7 @@ static int dpp1_dscl_get_pixel_depth_val(enum lb_pixel_depth depth) } } -static bool dpp1_dscl_is_video_format(enum pixel_format format) +static bool dpp1_dscl_is_video_format(enum dc_pixel_format format) { if (format >= PIXEL_FORMAT_VIDEO_BEGIN && format <= PIXEL_FORMAT_VIDEO_END) @@ -111,7 +111,7 @@ static bool dpp1_dscl_is_video_format(enum pixel_format format) return false; } -static bool dpp1_dscl_is_420_format(enum pixel_format format) +static bool dpp1_dscl_is_420_format(enum dc_pixel_format format) { if (format == PIXEL_FORMAT_420BPP8 || format == PIXEL_FORMAT_420BPP10) diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp.c index c433f4b876e9..8d5000790904 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp.c @@ -92,7 +92,10 @@ void dpp2_power_on_obuf( void dpp2_dummy_program_input_lut( struct dpp *dpp_base, const struct dc_gamma *gamma) -{} +{ + (void)dpp_base; + (void)gamma; +} static void dpp2_cnv_setup ( struct dpp *dpp_base, @@ -369,7 +372,11 @@ void oppn20_dummy_program_regamma_pwl( struct dpp *dpp, const struct pwl_params *params, enum opp_regamma mode) -{} +{ + (void)dpp; + (void)params; + (void)mode; +} static struct dpp_funcs dcn20_dpp_funcs = { .dpp_read_state = dpp20_read_state, diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp_cm.c index 31613372e214..26f9485f165d 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp_cm.c @@ -1016,6 +1016,7 @@ static void dpp20_set_3dlut_mode( bool is_color_channel_12bits, bool is_lut_size17x17x17) { + (void)is_color_channel_12bits; uint32_t lut_mode; struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base); diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c index c7923531da83..e7880fc61b4a 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c @@ -524,10 +524,14 @@ bool dpp3_get_optimal_number_of_taps( scl_data->taps.v_taps_c = max_taps_c; if (!dpp->ctx->dc->debug.always_scale) { - if (IDENTITY_RATIO(scl_data->ratios.horz)) + if (IDENTITY_RATIO(scl_data->ratios.horz)) { scl_data->taps.h_taps = 1; - if (IDENTITY_RATIO(scl_data->ratios.vert)) + scl_data->taps.h_taps_c = 1; + } + if (IDENTITY_RATIO(scl_data->ratios.vert)) { scl_data->taps.v_taps = 1; + scl_data->taps.v_taps_c = 1; + } if (IDENTITY_RATIO(scl_data->ratios.horz_c)) scl_data->taps.h_taps_c = 1; if (IDENTITY_RATIO(scl_data->ratios.vert_c)) @@ -1303,6 +1307,7 @@ static void dpp3_set_3dlut_mode( bool is_color_channel_12bits, bool is_lut_size17x17x17) { + (void)is_color_channel_12bits; uint32_t lut_mode; struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp_cm.c index 82eca0e7b7d0..8170a86ad0ea 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp_cm.c @@ -80,6 +80,7 @@ static void dpp3_program_gammcor_lut( uint32_t num, bool is_ram_a) { + (void)is_ram_a; uint32_t i; struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); uint32_t last_base_value_red = rgb[num-1].red_reg + rgb[num-1].delta_red_reg; @@ -132,6 +133,8 @@ static void dpp3_power_on_gamcor_lut( if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.cm) { if (power_on) { REG_UPDATE(CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_FORCE, 0); + if (dpp_base->ctx->dc->caps.ips_v2_support) + REG_UPDATE(CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_DIS, 1); REG_WAIT(CM_MEM_PWR_STATUS, GAMCOR_MEM_PWR_STATE, 0, 1, 5); } else { dpp_base->ctx->dc->optimized_required = true; diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h index 58b9f1cd0825..debcf308cb3b 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h @@ -1,4 +1,5 @@ -/* Copyright 2023 Advanced Micro Devices, Inc. +/* SPDX-License-Identifier: MIT */ +/* Copyright 2023-2026 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -653,6 +654,8 @@ struct dcn401_dpp_registers { DPP_REG_VARIABLE_LIST_DCN401; + uint32_t ALPHA_2BIT_LUT01; + uint32_t ALPHA_2BIT_LUT23; }; struct dcn401_dpp_shift { diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c index 62bf7cea21d8..821d5173b59f 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c @@ -132,6 +132,9 @@ void dpp401_set_cursor_position( uint32_t width, uint32_t height) { + (void)param; + (void)width; + (void)height; struct dcn401_dpp *dpp = TO_DCN401_DPP(dpp_base); uint32_t cur_en = pos->enable ? 1 : 0; @@ -237,6 +240,8 @@ void dpp401_set_cursor_matrix( enum dc_color_space color_space, struct dc_csc_transform cursor_csc_color_matrix) { + (void)color_space; + (void)cursor_csc_color_matrix; //Since we don't have cursor matrix information, force bypass mode by passing in unknown color space dpp401_program_cursor_csc(dpp_base, COLOR_SPACE_UNKNOWN, NULL); } diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c index a62c4733ed3b..8b7e55e337d3 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c @@ -94,7 +94,7 @@ static int dpp401_dscl_get_pixel_depth_val(enum lb_pixel_depth depth) } } -static bool dpp401_dscl_is_video_format(enum pixel_format format) +static bool dpp401_dscl_is_video_format(enum dc_pixel_format format) { if (format >= PIXEL_FORMAT_VIDEO_BEGIN && format <= PIXEL_FORMAT_VIDEO_END) @@ -103,7 +103,7 @@ static bool dpp401_dscl_is_video_format(enum pixel_format format) return false; } -static bool dpp401_dscl_is_420_format(enum pixel_format format) +static bool dpp401_dscl_is_420_format(enum dc_pixel_format format) { if (format == PIXEL_FORMAT_420BPP8 || format == PIXEL_FORMAT_420BPP10) @@ -155,7 +155,12 @@ static void dpp401_power_on_dscl( if (dpp->tf_regs->DSCL_MEM_PWR_CTRL) { if (power_on) { REG_UPDATE(DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_FORCE, 0); - REG_WAIT(DSCL_MEM_PWR_STATUS, LUT_MEM_PWR_STATE, 0, 1, 5); + if (dpp->base.ctx->dc->caps.ips_v2_support) { + /*hw default changes to LS*/ + REG_UPDATE(DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_DIS, 1); + REG_WAIT(DSCL_MEM_PWR_STATUS, LUT_MEM_PWR_STATE, 0, 1, 100); + } else + REG_WAIT(DSCL_MEM_PWR_STATUS, LUT_MEM_PWR_STATE, 0, 1, 5); } else { if (dpp->base.ctx->dc->debug.enable_mem_low_power.bits.dscl) { dpp->base.ctx->dc->optimized_required = true; @@ -956,6 +961,15 @@ static void dpp401_dscl_program_isharp(struct dpp *dpp_base, *bs_coeffs_updated = false; PERF_TRACE(); + /*power on isharp_delta_mem first*/ + if (dpp_base->ctx->dc->caps.ips_v2_support) { + /*HW default is LS, need to wake up*/ + REG_UPDATE_2(ISHARP_DELTA_LUT_MEM_PWR_CTRL, + ISHARP_DELTA_LUT_MEM_PWR_FORCE, 0, + ISHARP_DELTA_LUT_MEM_PWR_DIS, 1); + REG_WAIT(ISHARP_DELTA_LUT_MEM_PWR_CTRL, + ISHARP_DELTA_LUT_MEM_PWR_STATE, 0, 1, 100); + } /* ISHARP_MODE */ REG_SET_6(ISHARP_MODE, 0, ISHARP_EN, scl_data->dscl_prog_data.isharp_en, @@ -1033,6 +1047,13 @@ static void dpp401_dscl_program_isharp(struct dpp *dpp_base, } } + /*power on isharp_delta_mem first*/ + if (dpp_base->ctx->dc->caps.ips_v2_support) { + /*HW default is LS, need to wake up*/ + REG_UPDATE_SEQ_2(ISHARP_DELTA_LUT_MEM_PWR_CTRL, + ISHARP_DELTA_LUT_MEM_PWR_FORCE, 0, + ISHARP_DELTA_LUT_MEM_PWR_DIS, 0); + } PERF_TRACE(); } // dpp401_dscl_program_isharp /** diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c new file mode 100644 index 000000000000..c126fb9d5bfa --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c @@ -0,0 +1,333 @@ +// SPDX-License-Identifier: MIT +// +// Copyright 2026 Advanced Micro Devices, Inc. + +#include "dm_services.h" +#include "core_types.h" +#include "reg_helper.h" +#include "dcn42_dpp.h" +#include "dcn35/dcn35_dpp.h" + +#define REG(reg)\ + dpp->tf_regs->reg + +#define CTX \ + dpp->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + dpp->tf_shift->field_name, dpp->tf_mask->field_name + +static const uint32_t *get_hist_rgb_luma_coefs(enum dc_color_space color_space) +{ + // Coefs in s.6.12. + // Y = 0.2126R + 0.7152G + 0.0722B + static const uint32_t luma_transform_bt_709[] = {0x1cb36, 0x1e6e2, 0x1b27b}; + // Y = 0.2627R + 0.678G + 0.0593B + static const uint32_t luma_transform_bt_2020[] = {0x1d0d0, 0x1e5b2, 0x1ae5c}; + + switch (color_space) { + case COLOR_SPACE_2020_RGB_FULLRANGE: + case COLOR_SPACE_2020_RGB_LIMITEDRANGE: + return luma_transform_bt_2020; + default: + return luma_transform_bt_709; + } +} + +static void dpp42_dpp_cm_hist_control( + struct dpp *dpp_base, + struct cm_hist_control cntl, + enum dc_color_space color_space) +{ + struct dcn42_dpp *dpp = TO_DCN42_DPP(dpp_base); + + REG_UPDATE_10( + CM_HIST_CNTL, + CM_HIST_SEL, cntl.tap_point, + CM_HIST_CH_EN, cntl.channels_enabled, + CM_HIST_SRC1_SEL, cntl.src_1_select, + CM_HIST_SRC2_SEL, cntl.src_2_select, + CM_HIST_SRC3_SEL, cntl.src_3_select, + CM_HIST_CH1_XBAR, cntl.ch1_src, + CM_HIST_CH2_XBAR, cntl.ch2_src, + CM_HIST_CH3_XBAR, cntl.ch3_src, + CM_HIST_FORMAT, cntl.format, + CM_HIST_READ_CHANNEL_MASK, cntl.read_channel_mask); + + if (cntl.src_2_select == CM_HIST_SRC2_MODE_RGB_TO_Y) { + const uint32_t *luma_transform = get_hist_rgb_luma_coefs(color_space); + + REG_UPDATE(CM_HIST_COEFA_SRC2, CM_HIST_COEFA_SRC2, luma_transform[0]); + REG_UPDATE(CM_HIST_COEFB_SRC2, CM_HIST_COEFB_SRC2, luma_transform[1]); + REG_UPDATE(CM_HIST_COEFC_SRC2, CM_HIST_COEFC_SRC2, luma_transform[2]); + } else { + REG_UPDATE(CM_HIST_COEFA_SRC2, CM_HIST_COEFA_SRC2, 0); + REG_UPDATE(CM_HIST_COEFB_SRC2, CM_HIST_COEFB_SRC2, 0x1f000); // 1 in s.6.12 + REG_UPDATE(CM_HIST_COEFC_SRC2, CM_HIST_COEFC_SRC2, 0); + } +} + +static bool dpp42_dpp_cm_hist_read(struct dpp *dpp_base, struct cm_hist *hist_out) +{ + struct dcn42_dpp *dpp = TO_DCN42_DPP(dpp_base); + uint32_t channel_mask = 0; + uint32_t rdy_status = 0, rdy_status_a = 0, rdy_status_b = 0; + bool ch1, ch2, ch3; + + if (hist_out == NULL) + return false; + + + REG_GET(CM_HIST_CNTL, CM_HIST_READ_CHANNEL_MASK, &channel_mask); + ch1 = (channel_mask & 1) > 0; + ch2 = (channel_mask & 2) > 0; + ch3 = (channel_mask & 4) > 0; + + REG_GET(CM_HIST_STATUS, CM_HIST_BUFA_RDY_STATUS, &rdy_status_a); + REG_GET(CM_HIST_STATUS, CM_HIST_BUFB_RDY_STATUS, &rdy_status_b); + + rdy_status = rdy_status_a || rdy_status_b; + + if (rdy_status) { + REG_UPDATE(CM_HIST_LOCK, CM_HIST_LOCK, 1); + REG_UPDATE(CM_HIST_INDEX, CM_HIST_INDEX, 0); + for (int i = 0; i < 256; i++) { + uint32_t temp; + + if (ch1) { + REG_GET(CM_HIST_DATA, CM_HIST_DATA, &temp); + hist_out->ch1[i] += temp; + } + if (ch2) { + REG_GET(CM_HIST_DATA, CM_HIST_DATA, &temp); + hist_out->ch2[i] += temp; + } + if (ch3) { + REG_GET(CM_HIST_DATA, CM_HIST_DATA, &temp); + hist_out->ch3[i] += temp; + } + } + REG_UPDATE(CM_HIST_LOCK, CM_HIST_LOCK, 0); + return true; + } else { + return false; + } +} + +static void dpp42_dpp_setup( + struct dpp *dpp_base, + enum surface_pixel_format format, + enum expansion_mode mode, + struct dc_csc_transform input_csc_color_matrix, + enum dc_color_space input_color_space, + struct cnv_alpha_2bit_lut *alpha_2bit_lut) +{ + struct dcn401_dpp *dpp = TO_DCN401_DPP(dpp_base); + uint32_t pixel_format = 0; + uint32_t alpha_en = 1; + enum dc_color_space color_space = COLOR_SPACE_SRGB; + enum dcn10_input_csc_select select = INPUT_CSC_SELECT_BYPASS; + uint32_t is_2bit = 0; + uint32_t alpha_plane_enable = 0; + uint32_t dealpha_en = 0, dealpha_ablnd_en = 0; + uint32_t realpha_en = 0, realpha_ablnd_en = 0; + struct out_csc_color_matrix tbl_entry; + int i; + + REG_SET_2(FORMAT_CONTROL, 0, + CNVC_BYPASS, 0, + FORMAT_EXPANSION_MODE, mode); + + REG_UPDATE(FORMAT_CONTROL, FORMAT_CNV16, 0); + REG_UPDATE(FORMAT_CONTROL, CNVC_BYPASS_MSB_ALIGN, 0); + REG_UPDATE(FORMAT_CONTROL, CLAMP_POSITIVE, 0); + REG_UPDATE(FORMAT_CONTROL, CLAMP_POSITIVE_C, 0); + + REG_UPDATE(FORMAT_CONTROL, FORMAT_CROSSBAR_R, 0); + REG_UPDATE(FORMAT_CONTROL, FORMAT_CROSSBAR_G, 1); + REG_UPDATE(FORMAT_CONTROL, FORMAT_CROSSBAR_B, 2); + + switch (format) { + case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: + pixel_format = 1; + break; + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + pixel_format = 3; + alpha_en = 0; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: + pixel_format = 8; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + pixel_format = 10; + is_2bit = 1; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: + pixel_format = 65; + color_space = COLOR_SPACE_YCBCR709; + select = INPUT_CSC_SELECT_ICSC; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: + pixel_format = 64; + color_space = COLOR_SPACE_YCBCR709; + select = INPUT_CSC_SELECT_ICSC; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: + pixel_format = 67; + color_space = COLOR_SPACE_YCBCR709; + select = INPUT_CSC_SELECT_ICSC; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: + pixel_format = 66; + color_space = COLOR_SPACE_YCBCR709; + select = INPUT_CSC_SELECT_ICSC; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616: + pixel_format = 26; /* ARGB16161616_UNORM */ + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: + pixel_format = 24; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + pixel_format = 25; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_AYCrCb8888: + pixel_format = 12; + color_space = COLOR_SPACE_YCBCR709; + select = INPUT_CSC_SELECT_ICSC; + break; + case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FIX: + pixel_format = 112; + alpha_en = 0; + break; + case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FIX: + pixel_format = 113; + alpha_en = 0; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_ACrYCb2101010: + pixel_format = 114; + color_space = COLOR_SPACE_YCBCR709; + select = INPUT_CSC_SELECT_ICSC; + is_2bit = 1; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_CrYCbA1010102: + pixel_format = 115; + color_space = COLOR_SPACE_YCBCR709; + select = INPUT_CSC_SELECT_ICSC; + is_2bit = 1; + break; + case SURFACE_PIXEL_FORMAT_GRPH_RGBE: + pixel_format = 116; + alpha_plane_enable = 0; + break; + case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA: + pixel_format = 116; + alpha_plane_enable = 1; + break; + case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FLOAT: + pixel_format = 118; + alpha_en = 0; + break; + case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FLOAT: + pixel_format = 119; + alpha_en = 0; + break; + default: + break; + } + + /* Set default color space based on format if none is given. */ + color_space = input_color_space ? input_color_space : color_space; + + if (is_2bit == 1 && alpha_2bit_lut != NULL) { + REG_UPDATE(ALPHA_2BIT_LUT01, ALPHA_2BIT_LUT0, alpha_2bit_lut->lut0); + REG_UPDATE(ALPHA_2BIT_LUT01, ALPHA_2BIT_LUT1, alpha_2bit_lut->lut1); + REG_UPDATE(ALPHA_2BIT_LUT23, ALPHA_2BIT_LUT2, alpha_2bit_lut->lut2); + REG_UPDATE(ALPHA_2BIT_LUT23, ALPHA_2BIT_LUT3, alpha_2bit_lut->lut3); + } + + REG_SET_2(CNVC_SURFACE_PIXEL_FORMAT, 0, + CNVC_SURFACE_PIXEL_FORMAT, pixel_format, + CNVC_ALPHA_PLANE_ENABLE, alpha_plane_enable); + REG_UPDATE(FORMAT_CONTROL, FORMAT_CONTROL__ALPHA_EN, alpha_en); + + REG_SET_2(PRE_DEALPHA, 0, + PRE_DEALPHA_EN, dealpha_en, + PRE_DEALPHA_ABLND_EN, dealpha_ablnd_en); + REG_SET_2(PRE_REALPHA, 0, + PRE_REALPHA_EN, realpha_en, + PRE_REALPHA_ABLND_EN, realpha_ablnd_en); + + /* If input adjustment exists, program the ICSC with those values. */ + if (input_csc_color_matrix.enable_adjustment == true) { + for (i = 0; i < 12; i++) + tbl_entry.regval[i] = input_csc_color_matrix.matrix[i]; + + tbl_entry.color_space = input_color_space; + + if (color_space >= COLOR_SPACE_YCBCR601) + select = INPUT_CSC_SELECT_ICSC; + else + select = INPUT_CSC_SELECT_BYPASS; + + dpp3_program_post_csc(dpp_base, color_space, select, + &tbl_entry); + } else { + dpp3_program_post_csc(dpp_base, color_space, select, NULL); + } +} + +static struct dpp_funcs dcn42_dpp_funcs = { + .dpp_program_gamcor_lut = dpp3_program_gamcor_lut, + .dpp_read_state = dpp401_read_state, + .dpp_reset = dpp_reset, + .dpp_set_scaler = dpp401_dscl_set_scaler_manual_scale, + .dpp_get_optimal_number_of_taps = dpp3_get_optimal_number_of_taps, + .dpp_set_pre_degam = dpp3_set_pre_degam, + .dpp_setup = dpp42_dpp_setup, + .dpp_program_cm_dealpha = dpp3_program_cm_dealpha, + .dpp_program_cm_bias = dpp3_program_cm_bias, + .dpp_program_bias_and_scale = dpp35_program_bias_and_scale_fcnv, + .dpp_cnv_set_alpha_keyer = dpp2_cnv_set_alpha_keyer, + .set_cursor_attributes = dpp401_set_cursor_attributes, + .set_cursor_position = dpp401_set_cursor_position, + .set_optional_cursor_attributes = dpp401_set_optional_cursor_attributes, + .dpp_dppclk_control = dpp35_dppclk_control, + .dpp_set_hdr_multiplier = dpp3_set_hdr_multiplier, + .set_cursor_matrix = dpp401_set_cursor_matrix, + .dpp_cm_hist_control = dpp42_dpp_cm_hist_control, + .dpp_cm_hist_read = dpp42_dpp_cm_hist_read, + .dpp_read_reg_state = dpp30_read_reg_state, +}; + + +static struct dpp_caps dcn42_dpp_cap = { + .dscl_data_proc_format = DSCL_DATA_PRCESSING_FLOAT_FORMAT, + .max_lb_partitions = 63, + .dscl_calc_lb_num_partitions = dscl401_calc_lb_num_partitions, +}; + +bool dpp42_construct( + struct dcn42_dpp *dpp, + struct dc_context *ctx, + uint32_t inst, + const struct dcn42_dpp_registers *tf_regs, + const struct dcn42_dpp_shift *tf_shift, + const struct dcn42_dpp_mask *tf_mask) +{ + dpp->base.ctx = ctx; + + dpp->base.inst = inst; + dpp->base.funcs = &dcn42_dpp_funcs; + dpp->base.caps = &dcn42_dpp_cap; + + dpp->tf_regs = tf_regs; + dpp->tf_shift = tf_shift; + dpp->tf_mask = tf_mask; + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.h b/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.h new file mode 100644 index 000000000000..f4ee419eabf7 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.h @@ -0,0 +1,469 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright 2026 Advanced Micro Devices, Inc. */ + +#ifndef __DCN42_DPP_H__ +#define __DCN42_DPP_H__ + +#include "dcn401/dcn401_dpp.h" + +#define TO_DCN42_DPP(dpp)\ + container_of(dpp, struct dcn42_dpp, base) + +#define DPP_REG_LIST_SH_MASK_DCN42_COMMON(mask_sh)\ + TF_SF(CM0_CM_MEM_PWR_STATUS, GAMCOR_MEM_PWR_STATE, mask_sh),\ + TF_SF(CM0_CM_DEALPHA, CM_DEALPHA_EN, mask_sh),\ + TF_SF(CM0_CM_DEALPHA, CM_DEALPHA_ABLND, mask_sh),\ + TF_SF(CM0_CM_BIAS_CR_R, CM_BIAS_CR_R, mask_sh),\ + TF_SF(CM0_CM_BIAS_Y_G_CB_B, CM_BIAS_Y_G, mask_sh),\ + TF_SF(CM0_CM_BIAS_Y_G_CB_B, CM_BIAS_CB_B, mask_sh),\ + TF_SF(CM0_CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_DIS, mask_sh),\ + TF_SF(CM0_CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_FORCE, mask_sh),\ + TF_SF(CM0_CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_DIS, mask_sh),\ + TF_SF(CNVC_CFG0_PRE_DEGAM, PRE_DEGAM_MODE, mask_sh),\ + TF_SF(CNVC_CFG0_PRE_DEGAM, PRE_DEGAM_SELECT, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_CONTROL, CM_GAMCOR_MODE, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_CONTROL, CM_GAMCOR_SELECT, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_CONTROL, CM_GAMCOR_PWL_DISABLE, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_CONTROL, CM_GAMCOR_MODE_CURRENT, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_CONTROL, CM_GAMCOR_SELECT_CURRENT, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_LUT_INDEX, CM_GAMCOR_LUT_INDEX, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_LUT_DATA, CM_GAMCOR_LUT_DATA, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_LUT_CONTROL, CM_GAMCOR_LUT_WRITE_COLOR_MASK, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_LUT_CONTROL, CM_GAMCOR_LUT_READ_COLOR_SEL, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_LUT_CONTROL, CM_GAMCOR_LUT_READ_DBG, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_LUT_CONTROL, CM_GAMCOR_LUT_HOST_SEL, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_LUT_CONTROL, CM_GAMCOR_LUT_CONFIG_MODE, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_RAMA_START_CNTL_B, CM_GAMCOR_RAMA_EXP_REGION_START_B, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_RAMA_START_CNTL_B, CM_GAMCOR_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_RAMA_START_SLOPE_CNTL_B, CM_GAMCOR_RAMA_EXP_REGION_START_SLOPE_B, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_RAMA_START_BASE_CNTL_B, CM_GAMCOR_RAMA_EXP_REGION_START_BASE_B, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_RAMA_END_CNTL1_B, CM_GAMCOR_RAMA_EXP_REGION_END_BASE_B, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_RAMA_END_CNTL2_B, CM_GAMCOR_RAMA_EXP_REGION_END_B, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_RAMA_END_CNTL2_B, CM_GAMCOR_RAMA_EXP_REGION_END_SLOPE_B, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_RAMA_OFFSET_B, CM_GAMCOR_RAMA_OFFSET_B, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_RAMA_REGION_0_1, CM_GAMCOR_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_RAMA_REGION_0_1, CM_GAMCOR_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_RAMA_REGION_0_1, CM_GAMCOR_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_RAMA_REGION_0_1, CM_GAMCOR_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ + TF_SF(DSCL0_DSCL_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT, mask_sh),\ + TF_SF(DSCL0_DSCL_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT, mask_sh),\ + TF_SF(DSCL0_DSCL_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM, mask_sh),\ + TF_SF(DSCL0_DSCL_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP, mask_sh),\ + TF_SF(DSCL0_OTG_H_BLANK, OTG_H_BLANK_START, mask_sh),\ + TF_SF(DSCL0_OTG_H_BLANK, OTG_H_BLANK_END, mask_sh),\ + TF_SF(DSCL0_OTG_V_BLANK, OTG_V_BLANK_START, mask_sh),\ + TF_SF(DSCL0_OTG_V_BLANK, OTG_V_BLANK_END, mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, INTERLEAVE_EN, mask_sh),\ + TF2_SF(DSCL0, LB_DATA_FORMAT__ALPHA_EN, mask_sh),\ + TF_SF(DSCL0_LB_MEMORY_CTRL, MEMORY_CONFIG, mask_sh),\ + TF_SF(DSCL0_LB_MEMORY_CTRL, LB_MAX_PARTITIONS, mask_sh),\ + TF_SF(DSCL0_DSCL_AUTOCAL, AUTOCAL_MODE, mask_sh),\ + TF_SF(DSCL0_DSCL_AUTOCAL, AUTOCAL_NUM_PIPE, mask_sh),\ + TF_SF(DSCL0_DSCL_CONTROL, SCL_BOUNDARY_MODE, mask_sh),\ + TF_SF(DSCL0_DSCL_AUTOCAL, AUTOCAL_PIPE_ID, mask_sh),\ + TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_V_NUM_TAPS, mask_sh),\ + TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_H_NUM_TAPS, mask_sh),\ + TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_V_NUM_TAPS_C, mask_sh),\ + TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_H_NUM_TAPS_C, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_SELECT, SCL_COEF_RAM_TAP_PAIR_IDX, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_SELECT, SCL_COEF_RAM_PHASE, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_SELECT, SCL_COEF_RAM_FILTER_TYPE, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_EVEN_TAP_COEF, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_EVEN_TAP_COEF_EN, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_ODD_TAP_COEF, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_ODD_TAP_COEF_EN, mask_sh),\ + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_H_2TAP_HARDCODE_COEF_EN, mask_sh),\ + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_H_2TAP_SHARP_EN, mask_sh),\ + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_H_2TAP_SHARP_FACTOR, mask_sh),\ + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_V_2TAP_HARDCODE_COEF_EN, mask_sh),\ + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_V_2TAP_SHARP_EN, mask_sh),\ + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_V_2TAP_SHARP_FACTOR, mask_sh),\ + TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT, mask_sh),\ + TF_SF(DSCL0_SCL_MODE, DSCL_MODE, mask_sh),\ + TF_SF(DSCL0_RECOUT_START, RECOUT_START_X, mask_sh),\ + TF_SF(DSCL0_RECOUT_START, RECOUT_START_Y, mask_sh),\ + TF_SF(DSCL0_RECOUT_SIZE, RECOUT_WIDTH, mask_sh),\ + TF_SF(DSCL0_RECOUT_SIZE, RECOUT_HEIGHT, mask_sh),\ + TF_SF(DSCL0_MPC_SIZE, MPC_WIDTH, mask_sh),\ + TF_SF(DSCL0_MPC_SIZE, MPC_HEIGHT, mask_sh),\ + TF_SF(DSCL0_SCL_HORZ_FILTER_SCALE_RATIO, SCL_H_SCALE_RATIO, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_SCALE_RATIO, SCL_V_SCALE_RATIO, mask_sh),\ + TF_SF(DSCL0_SCL_HORZ_FILTER_SCALE_RATIO_C, SCL_H_SCALE_RATIO_C, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_SCALE_RATIO_C, SCL_V_SCALE_RATIO_C, mask_sh),\ + TF_SF(DSCL0_SCL_HORZ_FILTER_INIT, SCL_H_INIT_FRAC, mask_sh),\ + TF_SF(DSCL0_SCL_HORZ_FILTER_INIT, SCL_H_INIT_INT, mask_sh),\ + TF_SF(DSCL0_SCL_HORZ_FILTER_INIT_C, SCL_H_INIT_FRAC_C, mask_sh),\ + TF_SF(DSCL0_SCL_HORZ_FILTER_INIT_C, SCL_H_INIT_INT_C, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT, SCL_V_INIT_FRAC, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT, SCL_V_INIT_INT, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT_C, SCL_V_INIT_FRAC_C, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT_C, SCL_V_INIT_INT_C, mask_sh),\ + TF_SF(DSCL0_SCL_MODE, SCL_CHROMA_COEF_MODE, mask_sh),\ + TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT_CURRENT, mask_sh), \ + TF_SF(CNVC_CFG0_PRE_DEALPHA, PRE_DEALPHA_EN, mask_sh), \ + TF_SF(CNVC_CFG0_PRE_DEALPHA, PRE_DEALPHA_ABLND_EN, mask_sh), \ + TF_SF(CNVC_CFG0_PRE_REALPHA, PRE_REALPHA_EN, mask_sh), \ + TF_SF(CNVC_CFG0_PRE_REALPHA, PRE_REALPHA_ABLND_EN, mask_sh), \ + TF_SF(CNVC_CFG0_PRE_CSC_MODE, PRE_CSC_MODE, mask_sh), \ + TF_SF(CNVC_CFG0_PRE_CSC_MODE, PRE_CSC_MODE_CURRENT, mask_sh), \ + TF_SF(CNVC_CFG0_PRE_CSC_C11_C12, PRE_CSC_C11, mask_sh), \ + TF_SF(CNVC_CFG0_PRE_CSC_C11_C12, PRE_CSC_C12, mask_sh), \ + TF_SF(CNVC_CFG0_PRE_CSC_C33_C34, PRE_CSC_C33, mask_sh), \ + TF_SF(CNVC_CFG0_PRE_CSC_C33_C34, PRE_CSC_C34, mask_sh), \ + TF_SF(CM0_CM_POST_CSC_CONTROL, CM_POST_CSC_MODE, mask_sh), \ + TF_SF(CM0_CM_POST_CSC_CONTROL, CM_POST_CSC_MODE_CURRENT, mask_sh), \ + TF_SF(CM0_CM_POST_CSC_C11_C12, CM_POST_CSC_C11, mask_sh), \ + TF_SF(CM0_CM_POST_CSC_C11_C12, CM_POST_CSC_C12, mask_sh), \ + TF_SF(CM0_CM_POST_CSC_C33_C34, CM_POST_CSC_C33, mask_sh), \ + TF_SF(CM0_CM_POST_CSC_C33_C34, CM_POST_CSC_C34, mask_sh), \ + TF_SF(CM0_CM_TEST_DEBUG_INDEX, CM_TEST_DEBUG_INDEX, mask_sh), \ + TF_SF(CNVC_CFG0_FORMAT_CONTROL, CNVC_BYPASS, mask_sh), \ + TF2_SF(CNVC_CFG0, FORMAT_CONTROL__ALPHA_EN, mask_sh), \ + TF_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_EXPANSION_MODE, mask_sh), \ + TF_SF(CNVC_CFG0_CNVC_SURFACE_PIXEL_FORMAT, CNVC_SURFACE_PIXEL_FORMAT, mask_sh), \ + TF_SF(CNVC_CFG0_CNVC_SURFACE_PIXEL_FORMAT, CNVC_ALPHA_PLANE_ENABLE, mask_sh), \ + TF_SF(CM_CUR0_CURSOR0_CONTROL, CUR0_MODE, mask_sh), \ + TF_SF(CM_CUR0_CURSOR0_CONTROL, CUR0_EXPANSION_MODE, mask_sh), \ + TF_SF(CM_CUR0_CURSOR0_CONTROL, CUR0_ENABLE, mask_sh), \ + TF_SF(CM_CUR0_CURSOR0_COLOR0, CUR0_COLOR0, mask_sh), \ + TF_SF(CM_CUR0_CURSOR0_COLOR1, CUR0_COLOR1, mask_sh), \ + TF_SF(CM_CUR0_CURSOR0_FP_SCALE_BIAS_G_Y, CUR0_FP_BIAS_G_Y, mask_sh), \ + TF_SF(CM_CUR0_CURSOR0_FP_SCALE_BIAS_G_Y, CUR0_FP_SCALE_G_Y, mask_sh), \ + TF_SF(CM_CUR0_CURSOR0_FP_SCALE_BIAS_RB_CRCB, CUR0_FP_BIAS_RB_CRCB, mask_sh), \ + TF_SF(CM_CUR0_CURSOR0_FP_SCALE_BIAS_RB_CRCB, CUR0_FP_SCALE_RB_CRCB, mask_sh), \ + TF_SF(CM_CUR0_CUR0_MATRIX_MODE, CUR0_MATRIX_MODE, mask_sh), \ + TF_SF(CM_CUR0_CUR0_MATRIX_MODE, CUR0_MATRIX_MODE_CURRENT, mask_sh), \ + TF_SF(CM_CUR0_CUR0_MATRIX_MODE, CUR0_MATRIX_COEF_FORMAT, mask_sh), \ + TF_SF(CM_CUR0_CUR0_MATRIX_C11_C12_A, CUR0_MATRIX_C11_A, mask_sh), \ + TF_SF(CM_CUR0_CUR0_MATRIX_C11_C12_A, CUR0_MATRIX_C12_A, mask_sh), \ + TF_SF(CM_CUR0_CUR0_MATRIX_C13_C14_A, CUR0_MATRIX_C13_A, mask_sh), \ + TF_SF(CM_CUR0_CUR0_MATRIX_C13_C14_A, CUR0_MATRIX_C14_A, mask_sh), \ + TF_SF(CM_CUR0_CUR0_MATRIX_C21_C22_A, CUR0_MATRIX_C21_A, mask_sh), \ + TF_SF(CM_CUR0_CUR0_MATRIX_C21_C22_A, CUR0_MATRIX_C22_A, mask_sh), \ + TF_SF(CM_CUR0_CUR0_MATRIX_C23_C24_A, CUR0_MATRIX_C23_A, mask_sh), \ + TF_SF(CM_CUR0_CUR0_MATRIX_C23_C24_A, CUR0_MATRIX_C24_A, mask_sh), \ + TF_SF(CM_CUR0_CUR0_MATRIX_C31_C32_A, CUR0_MATRIX_C31_A, mask_sh), \ + TF_SF(CM_CUR0_CUR0_MATRIX_C31_C32_A, CUR0_MATRIX_C32_A, mask_sh), \ + TF_SF(CM_CUR0_CUR0_MATRIX_C33_C34_A, CUR0_MATRIX_C33_A, mask_sh), \ + TF_SF(CM_CUR0_CUR0_MATRIX_C33_C34_A, CUR0_MATRIX_C34_A, mask_sh), \ + TF_SF(DPP_TOP0_DPP_CONTROL, DPP_CLOCK_ENABLE, mask_sh), \ + TF_SF(CM0_CM_HDR_MULT_COEF, CM_HDR_MULT_COEF, mask_sh), \ + TF_SF(CM0_CM_CONTROL, CM_BYPASS, mask_sh), \ + TF_SF(CM0_CM_HIST_CNTL, CM_HIST_SEL, mask_sh), \ + TF_SF(CM0_CM_HIST_CNTL, CM_HIST_CH_EN, mask_sh), \ + TF_SF(CM0_CM_HIST_CNTL, CM_HIST_SRC1_SEL, mask_sh), \ + TF_SF(CM0_CM_HIST_CNTL, CM_HIST_SRC2_SEL, mask_sh), \ + TF_SF(CM0_CM_HIST_CNTL, CM_HIST_SRC3_SEL, mask_sh), \ + TF_SF(CM0_CM_HIST_CNTL, CM_HIST_CH1_XBAR, mask_sh), \ + TF_SF(CM0_CM_HIST_CNTL, CM_HIST_CH2_XBAR, mask_sh), \ + TF_SF(CM0_CM_HIST_CNTL, CM_HIST_CH3_XBAR, mask_sh), \ + TF_SF(CM0_CM_HIST_CNTL, CM_HIST_FORMAT, mask_sh), \ + TF_SF(CM0_CM_HIST_CNTL, CM_HIST_READ_CHANNEL_MASK, mask_sh), \ + TF_SF(CM0_CM_HIST_LOCK, CM_HIST_LOCK, mask_sh), \ + TF_SF(CM0_CM_HIST_INDEX, CM_HIST_INDEX, mask_sh), \ + TF_SF(CM0_CM_HIST_DATA, CM_HIST_DATA, mask_sh), \ + TF_SF(CM0_CM_HIST_DATA, CM_HIST_DATA, mask_sh), \ + TF_SF(CM0_CM_HIST_STATUS, CM_HIST_BUFA_RDY_STATUS, mask_sh), \ + TF_SF(CM0_CM_HIST_STATUS, CM_HIST_BUFB_RDY_STATUS, mask_sh), \ + TF_SF(CM0_CM_HIST_SCALE_SRC1, CM_HIST_SCALE_SRC1, mask_sh), \ + TF_SF(CM0_CM_HIST_COEFA_SRC2, CM_HIST_COEFA_SRC2, mask_sh), \ + TF_SF(CM0_CM_HIST_COEFB_SRC2, CM_HIST_COEFB_SRC2, mask_sh), \ + TF_SF(CM0_CM_HIST_COEFC_SRC2, CM_HIST_COEFC_SRC2, mask_sh), \ + TF_SF(CM0_CM_HIST_SCALE_SRC3, CM_HIST_SCALE_SRC3, mask_sh), \ + TF_SF(CM0_CM_HIST_BIAS_SRC1, CM_HIST_BIAS_SRC1, mask_sh), \ + TF_SF(CM0_CM_HIST_BIAS_SRC2, CM_HIST_BIAS_SRC2, mask_sh), \ + TF_SF(CM0_CM_HIST_BIAS_SRC3, CM_HIST_BIAS_SRC3, mask_sh), \ + TF_SF(CURSOR0_0_CURSOR_CONTROL, CURSOR_MODE, mask_sh), \ + TF_SF(CURSOR0_0_CURSOR_CONTROL, CURSOR_PITCH, mask_sh), \ + TF_SF(CURSOR0_0_CURSOR_CONTROL, CURSOR_LINES_PER_CHUNK, mask_sh), \ + TF_SF(CURSOR0_0_CURSOR_CONTROL, CURSOR_ENABLE, mask_sh), \ + TF_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_CNV16, mask_sh), \ + TF_SF(CNVC_CFG0_FORMAT_CONTROL, CNVC_BYPASS_MSB_ALIGN, mask_sh), \ + TF_SF(CNVC_CFG0_FORMAT_CONTROL, CLAMP_POSITIVE, mask_sh), \ + TF_SF(CNVC_CFG0_FORMAT_CONTROL, CLAMP_POSITIVE_C, mask_sh), \ + TF_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_CROSSBAR_R, mask_sh), \ + TF_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_CROSSBAR_G, mask_sh), \ + TF_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_CROSSBAR_B, mask_sh), \ + TF_SF(CNVC_CFG0_ALPHA_2BIT_LUT01, ALPHA_2BIT_LUT0, mask_sh), \ + TF_SF(CNVC_CFG0_ALPHA_2BIT_LUT01, ALPHA_2BIT_LUT1, mask_sh), \ + TF_SF(CNVC_CFG0_ALPHA_2BIT_LUT23, ALPHA_2BIT_LUT2, mask_sh), \ + TF_SF(CNVC_CFG0_ALPHA_2BIT_LUT23, ALPHA_2BIT_LUT3, mask_sh), \ + TF_SF(CNVC_CFG0_FCNV_FP_BIAS_R, FCNV_FP_BIAS_R, mask_sh), \ + TF_SF(CNVC_CFG0_FCNV_FP_BIAS_G, FCNV_FP_BIAS_G, mask_sh), \ + TF_SF(CNVC_CFG0_FCNV_FP_BIAS_B, FCNV_FP_BIAS_B, mask_sh), \ + TF_SF(CNVC_CFG0_FCNV_FP_SCALE_R, FCNV_FP_SCALE_R, mask_sh), \ + TF_SF(CNVC_CFG0_FCNV_FP_SCALE_G, FCNV_FP_SCALE_G, mask_sh), \ + TF_SF(CNVC_CFG0_FCNV_FP_SCALE_B, FCNV_FP_SCALE_B, mask_sh), \ + TF_SF(CNVC_CFG0_COLOR_KEYER_CONTROL, COLOR_KEYER_EN, mask_sh), \ + TF_SF(CNVC_CFG0_COLOR_KEYER_CONTROL, LUMA_KEYER_EN, mask_sh), \ + TF_SF(CNVC_CFG0_COLOR_KEYER_CONTROL, COLOR_KEYER_MODE, mask_sh), \ + TF_SF(CNVC_CFG0_COLOR_KEYER_ALPHA, COLOR_KEYER_ALPHA_LOW, mask_sh), \ + TF_SF(CNVC_CFG0_COLOR_KEYER_ALPHA, COLOR_KEYER_ALPHA_HIGH, mask_sh), \ + TF_SF(CNVC_CFG0_COLOR_KEYER_RED, COLOR_KEYER_RED_LOW, mask_sh), \ + TF_SF(CNVC_CFG0_COLOR_KEYER_RED, COLOR_KEYER_RED_HIGH, mask_sh), \ + TF_SF(CNVC_CFG0_COLOR_KEYER_GREEN, COLOR_KEYER_GREEN_LOW, mask_sh), \ + TF_SF(CNVC_CFG0_COLOR_KEYER_GREEN, COLOR_KEYER_GREEN_HIGH, mask_sh), \ + TF_SF(CNVC_CFG0_COLOR_KEYER_BLUE, COLOR_KEYER_BLUE_LOW, mask_sh), \ + TF_SF(CNVC_CFG0_COLOR_KEYER_BLUE, COLOR_KEYER_BLUE_HIGH, mask_sh), \ + TF_SF(CM_CUR0_CURSOR0_CONTROL, CUR0_PIX_INV_MODE, mask_sh), \ + TF_SF(CM_CUR0_CURSOR0_CONTROL, CUR0_PIXEL_ALPHA_MOD_EN, mask_sh), \ + TF_SF(CM_CUR0_CURSOR0_CONTROL, CUR0_ROM_EN, mask_sh),\ + TF_SF(DSCL0_OBUF_MEM_PWR_CTRL, OBUF_MEM_PWR_FORCE, mask_sh),\ + TF_SF(DSCL0_DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_FORCE, mask_sh),\ + TF_SF(DSCL0_DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_DIS, mask_sh),\ + TF_SF(DSCL0_DSCL_MEM_PWR_STATUS, LUT_MEM_PWR_STATE, mask_sh),\ + TF_SF(DSCL0_DSCL_SC_MODE, SCL_SC_MATRIX_MODE, mask_sh),\ + TF_SF(DSCL0_DSCL_SC_MODE, SCL_SC_LTONL_EN, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_MODE, SCL_EASF_H_EN, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_MODE, SCL_EASF_H_RINGEST_FORCE_EN, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_MODE, SCL_EASF_H_2TAP_SHARP_FACTOR, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF_CNTL, SCL_EASF_H_BF1_EN, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF_CNTL, SCL_EASF_H_BF2_MODE, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF_CNTL, SCL_EASF_H_BF3_MODE, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF_CNTL, SCL_EASF_H_BF2_FLAT1_GAIN, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF_CNTL, SCL_EASF_H_BF2_FLAT2_GAIN, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF_CNTL, SCL_EASF_H_BF2_ROC_GAIN, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_RINGEST_EVENTAP_REDUCE, SCL_EASF_H_RINGEST_EVENTAP_REDUCEG1, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_RINGEST_EVENTAP_REDUCE, SCL_EASF_H_RINGEST_EVENTAP_REDUCEG2, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_RINGEST_EVENTAP_GAIN, SCL_EASF_H_RINGEST_EVENTAP_GAIN1, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_RINGEST_EVENTAP_GAIN, SCL_EASF_H_RINGEST_EVENTAP_GAIN2, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF_FINAL_MAX_MIN, SCL_EASF_H_BF_MAXA, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF_FINAL_MAX_MIN, SCL_EASF_H_BF_MAXB, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF_FINAL_MAX_MIN, SCL_EASF_H_BF_MINA, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF_FINAL_MAX_MIN, SCL_EASF_H_BF_MINB, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG0, SCL_EASF_H_BF1_PWL_IN_SEG0, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG0, SCL_EASF_H_BF1_PWL_BASE_SEG0, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG0, SCL_EASF_H_BF1_PWL_SLOPE_SEG0, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG1, SCL_EASF_H_BF1_PWL_IN_SEG1, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG1, SCL_EASF_H_BF1_PWL_BASE_SEG1, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG1, SCL_EASF_H_BF1_PWL_SLOPE_SEG1, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG2, SCL_EASF_H_BF1_PWL_IN_SEG2, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG2, SCL_EASF_H_BF1_PWL_BASE_SEG2, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG2, SCL_EASF_H_BF1_PWL_SLOPE_SEG2, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG3, SCL_EASF_H_BF1_PWL_IN_SEG3, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG3, SCL_EASF_H_BF1_PWL_BASE_SEG3, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG3, SCL_EASF_H_BF1_PWL_SLOPE_SEG3, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG4, SCL_EASF_H_BF1_PWL_IN_SEG4, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG4, SCL_EASF_H_BF1_PWL_BASE_SEG4, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG4, SCL_EASF_H_BF1_PWL_SLOPE_SEG4, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG5, SCL_EASF_H_BF1_PWL_IN_SEG5, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG5, SCL_EASF_H_BF1_PWL_BASE_SEG5, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG5, SCL_EASF_H_BF1_PWL_SLOPE_SEG5, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG6, SCL_EASF_H_BF1_PWL_IN_SEG6, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG6, SCL_EASF_H_BF1_PWL_BASE_SEG6, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG6, SCL_EASF_H_BF1_PWL_SLOPE_SEG6, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG7, SCL_EASF_H_BF1_PWL_IN_SEG7, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG7, SCL_EASF_H_BF1_PWL_BASE_SEG7, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG0, SCL_EASF_H_BF3_PWL_IN_SEG0, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG0, SCL_EASF_H_BF3_PWL_BASE_SEG0, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG0, SCL_EASF_H_BF3_PWL_SLOPE_SEG0, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG1, SCL_EASF_H_BF3_PWL_IN_SEG1, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG1, SCL_EASF_H_BF3_PWL_BASE_SEG1, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG1, SCL_EASF_H_BF3_PWL_SLOPE_SEG1, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG2, SCL_EASF_H_BF3_PWL_IN_SEG2, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG2, SCL_EASF_H_BF3_PWL_BASE_SEG2, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG2, SCL_EASF_H_BF3_PWL_SLOPE_SEG2, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG3, SCL_EASF_H_BF3_PWL_IN_SEG3, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG3, SCL_EASF_H_BF3_PWL_BASE_SEG3, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG3, SCL_EASF_H_BF3_PWL_SLOPE_SEG3, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG4, SCL_EASF_H_BF3_PWL_IN_SEG4, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG4, SCL_EASF_H_BF3_PWL_BASE_SEG4, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG4, SCL_EASF_H_BF3_PWL_SLOPE_SEG4, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG5, SCL_EASF_H_BF3_PWL_IN_SEG5, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG5, SCL_EASF_H_BF3_PWL_BASE_SEG5, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_MODE, SCL_EASF_V_EN, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_MODE, SCL_EASF_V_RINGEST_FORCE_EN, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_MODE, SCL_EASF_V_2TAP_SHARP_FACTOR, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF_CNTL, SCL_EASF_V_BF1_EN, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF_CNTL, SCL_EASF_V_BF2_MODE, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF_CNTL, SCL_EASF_V_BF3_MODE, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF_CNTL, SCL_EASF_V_BF2_FLAT1_GAIN, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF_CNTL, SCL_EASF_V_BF2_FLAT2_GAIN, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF_CNTL, SCL_EASF_V_BF2_ROC_GAIN, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_RINGEST_3TAP_CNTL1, SCL_EASF_V_RINGEST_3TAP_DNTILT_UPTILT, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_RINGEST_3TAP_CNTL1, SCL_EASF_V_RINGEST_3TAP_UPTILT_MAXVAL, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_RINGEST_3TAP_CNTL2, SCL_EASF_V_RINGEST_3TAP_DNTILT_SLOPE, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_RINGEST_3TAP_CNTL2, SCL_EASF_V_RINGEST_3TAP_UPTILT1_SLOPE, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_RINGEST_3TAP_CNTL3, SCL_EASF_V_RINGEST_3TAP_UPTILT2_SLOPE, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_RINGEST_3TAP_CNTL3, SCL_EASF_V_RINGEST_3TAP_UPTILT2_OFFSET, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_RINGEST_EVENTAP_REDUCE, SCL_EASF_V_RINGEST_EVENTAP_REDUCEG1, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_RINGEST_EVENTAP_REDUCE, SCL_EASF_V_RINGEST_EVENTAP_REDUCEG2, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_RINGEST_EVENTAP_GAIN, SCL_EASF_V_RINGEST_EVENTAP_GAIN1, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_RINGEST_EVENTAP_GAIN, SCL_EASF_V_RINGEST_EVENTAP_GAIN2, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF_FINAL_MAX_MIN, SCL_EASF_V_BF_MAXA, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF_FINAL_MAX_MIN, SCL_EASF_V_BF_MAXB, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF_FINAL_MAX_MIN, SCL_EASF_V_BF_MINA, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF_FINAL_MAX_MIN, SCL_EASF_V_BF_MINB, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG0, SCL_EASF_V_BF1_PWL_IN_SEG0, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG0, SCL_EASF_V_BF1_PWL_BASE_SEG0, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG0, SCL_EASF_V_BF1_PWL_SLOPE_SEG0, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG1, SCL_EASF_V_BF1_PWL_IN_SEG1, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG1, SCL_EASF_V_BF1_PWL_BASE_SEG1, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG1, SCL_EASF_V_BF1_PWL_SLOPE_SEG1, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG2, SCL_EASF_V_BF1_PWL_IN_SEG2, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG2, SCL_EASF_V_BF1_PWL_BASE_SEG2, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG2, SCL_EASF_V_BF1_PWL_SLOPE_SEG2, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG3, SCL_EASF_V_BF1_PWL_IN_SEG3, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG3, SCL_EASF_V_BF1_PWL_BASE_SEG3, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG3, SCL_EASF_V_BF1_PWL_SLOPE_SEG3, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG4, SCL_EASF_V_BF1_PWL_IN_SEG4, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG4, SCL_EASF_V_BF1_PWL_BASE_SEG4, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG4, SCL_EASF_V_BF1_PWL_SLOPE_SEG4, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG5, SCL_EASF_V_BF1_PWL_IN_SEG5, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG5, SCL_EASF_V_BF1_PWL_BASE_SEG5, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG5, SCL_EASF_V_BF1_PWL_SLOPE_SEG5, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG6, SCL_EASF_V_BF1_PWL_IN_SEG6, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG6, SCL_EASF_V_BF1_PWL_BASE_SEG6, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG6, SCL_EASF_V_BF1_PWL_SLOPE_SEG6, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG7, SCL_EASF_V_BF1_PWL_IN_SEG7, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG7, SCL_EASF_V_BF1_PWL_BASE_SEG7, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG0, SCL_EASF_V_BF3_PWL_IN_SEG0, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG0, SCL_EASF_V_BF3_PWL_BASE_SEG0, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG0, SCL_EASF_V_BF3_PWL_SLOPE_SEG0, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG1, SCL_EASF_V_BF3_PWL_IN_SEG1, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG1, SCL_EASF_V_BF3_PWL_BASE_SEG1, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG1, SCL_EASF_V_BF3_PWL_SLOPE_SEG1, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG2, SCL_EASF_V_BF3_PWL_IN_SEG2, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG2, SCL_EASF_V_BF3_PWL_BASE_SEG2, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG2, SCL_EASF_V_BF3_PWL_SLOPE_SEG2, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG3, SCL_EASF_V_BF3_PWL_IN_SEG3, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG3, SCL_EASF_V_BF3_PWL_BASE_SEG3, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG3, SCL_EASF_V_BF3_PWL_SLOPE_SEG3, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG4, SCL_EASF_V_BF3_PWL_IN_SEG4, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG4, SCL_EASF_V_BF3_PWL_BASE_SEG4, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG4, SCL_EASF_V_BF3_PWL_SLOPE_SEG4, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG5, SCL_EASF_V_BF3_PWL_IN_SEG5, mask_sh),\ + TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG5, SCL_EASF_V_BF3_PWL_BASE_SEG5, mask_sh),\ + TF_SF(DSCL0_DSCL_SC_MATRIX_C0C1, SCL_SC_MATRIX_C0, mask_sh),\ + TF_SF(DSCL0_DSCL_SC_MATRIX_C0C1, SCL_SC_MATRIX_C1, mask_sh),\ + TF_SF(DSCL0_DSCL_SC_MATRIX_C2C3, SCL_SC_MATRIX_C2, mask_sh),\ + TF_SF(DSCL0_DSCL_SC_MATRIX_C2C3, SCL_SC_MATRIX_C3, mask_sh),\ + TF_SF(DSCL0_ISHARP_DELTA_CTRL, ISHARP_DELTA_LUT_HOST_SELECT, mask_sh),\ + TF_SF(DSCL0_ISHARP_DELTA_LUT_MEM_PWR_CTRL, ISHARP_DELTA_LUT_MEM_PWR_DIS, mask_sh),\ + TF_SF(DSCL0_ISHARP_DELTA_LUT_MEM_PWR_CTRL, ISHARP_DELTA_LUT_MEM_PWR_FORCE, mask_sh),\ + TF_SF(DSCL0_ISHARP_DELTA_LUT_MEM_PWR_CTRL, ISHARP_DELTA_LUT_MEM_PWR_STATE, mask_sh),\ + TF_SF(DSCL0_ISHARP_DELTA_DATA, ISHARP_DELTA_DATA, mask_sh),\ + TF_SF(DSCL0_ISHARP_DELTA_INDEX, ISHARP_DELTA_INDEX, mask_sh),\ + TF_SF(DSCL0_ISHARP_MODE, ISHARP_EN, mask_sh),\ + TF_SF(DSCL0_ISHARP_MODE, ISHARP_NOISEDET_EN, mask_sh),\ + TF_SF(DSCL0_ISHARP_MODE, ISHARP_NOISEDET_MODE, mask_sh),\ + TF_SF(DSCL0_ISHARP_MODE, ISHARP_LBA_MODE, mask_sh),\ + TF_SF(DSCL0_ISHARP_MODE, ISHARP_DELTA_LUT_SELECT, mask_sh),\ + TF_SF(DSCL0_ISHARP_MODE, ISHARP_FMT_MODE, mask_sh),\ + TF_SF(DSCL0_ISHARP_MODE, ISHARP_FMT_NORM, mask_sh),\ + TF_SF(DSCL0_ISHARP_MODE, ISHARP_DELTA_LUT_SELECT_CURRENT, mask_sh),\ + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG0, ISHARP_LBA_PWL_IN_SEG0, mask_sh),\ + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG0, ISHARP_LBA_PWL_BASE_SEG0, mask_sh),\ + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG0, ISHARP_LBA_PWL_SLOPE_SEG0, mask_sh), \ + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG1, ISHARP_LBA_PWL_IN_SEG1, mask_sh),\ + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG1, ISHARP_LBA_PWL_BASE_SEG1, mask_sh),\ + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG1, ISHARP_LBA_PWL_SLOPE_SEG1, mask_sh),\ + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG2, ISHARP_LBA_PWL_IN_SEG2, mask_sh),\ + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG2, ISHARP_LBA_PWL_BASE_SEG2, mask_sh),\ + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG2, ISHARP_LBA_PWL_SLOPE_SEG2, mask_sh),\ + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG3, ISHARP_LBA_PWL_IN_SEG3, mask_sh),\ + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG3, ISHARP_LBA_PWL_BASE_SEG3, mask_sh),\ + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG3, ISHARP_LBA_PWL_SLOPE_SEG3, mask_sh),\ + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG4, ISHARP_LBA_PWL_IN_SEG4, mask_sh),\ + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG4, ISHARP_LBA_PWL_BASE_SEG4, mask_sh),\ + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG4, ISHARP_LBA_PWL_SLOPE_SEG4, mask_sh),\ + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG5, ISHARP_LBA_PWL_IN_SEG5, mask_sh),\ + TF_SF(DSCL0_ISHARP_LBA_PWL_SEG5, ISHARP_LBA_PWL_BASE_SEG5, mask_sh),\ + TF_SF(DSCL0_ISHARP_NOISEDET_THRESHOLD, ISHARP_NOISEDET_UTHRE, mask_sh),\ + TF_SF(DSCL0_ISHARP_NOISEDET_THRESHOLD, ISHARP_NOISEDET_DTHRE, mask_sh), \ + TF_SF(DSCL0_ISHARP_NOISE_GAIN_PWL, ISHARP_NOISEDET_PWL_START_IN, mask_sh), \ + TF_SF(DSCL0_ISHARP_NOISE_GAIN_PWL, ISHARP_NOISEDET_PWL_END_IN, mask_sh), \ + TF_SF(DSCL0_ISHARP_NOISE_GAIN_PWL, ISHARP_NOISEDET_PWL_SLOPE, mask_sh), \ + TF_SF(DSCL0_ISHARP_NLDELTA_SOFT_CLIP, ISHARP_NLDELTA_SCLIP_EN_P, mask_sh), \ + TF_SF(DSCL0_ISHARP_NLDELTA_SOFT_CLIP, ISHARP_NLDELTA_SCLIP_PIVOT_P, mask_sh), \ + TF_SF(DSCL0_ISHARP_NLDELTA_SOFT_CLIP, ISHARP_NLDELTA_SCLIP_SLOPE_P, mask_sh), \ + TF_SF(DSCL0_ISHARP_NLDELTA_SOFT_CLIP, ISHARP_NLDELTA_SCLIP_EN_N, mask_sh), \ + TF_SF(DSCL0_ISHARP_NLDELTA_SOFT_CLIP, ISHARP_NLDELTA_SCLIP_PIVOT_N, mask_sh), \ + TF_SF(DSCL0_ISHARP_NLDELTA_SOFT_CLIP, ISHARP_NLDELTA_SCLIP_SLOPE_N, mask_sh), \ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT, SCL_V_INIT_FRAC_BOT, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT, SCL_V_INIT_INT_BOT, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT_C, SCL_V_INIT_FRAC_BOT_C, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT_C, SCL_V_INIT_INT_BOT_C, mask_sh) + +#define DPP_REG_FIELD_LIST_DCN42(type) \ + DPP_REG_FIELD_LIST_DCN401(type); \ + type CM_HIST_SEL; \ + type CM_HIST_CH_EN; \ + type CM_HIST_SRC1_SEL; \ + type CM_HIST_SRC2_SEL; \ + type CM_HIST_SRC3_SEL; \ + type CM_HIST_CH1_XBAR; \ + type CM_HIST_CH2_XBAR; \ + type CM_HIST_CH3_XBAR; \ + type CM_HIST_FORMAT; \ + type CM_HIST_READ_CHANNEL_MASK; \ + type CM_HIST_LOCK; \ + type CM_HIST_INDEX; \ + type CM_HIST_DATA; \ + type CM_HIST_BUFA_RDY_STATUS; \ + type CM_HIST_BUFB_RDY_STATUS; \ + type CM_HIST_SCALE_SRC1; \ + type CM_HIST_COEFA_SRC2; \ + type CM_HIST_COEFB_SRC2; \ + type CM_HIST_COEFC_SRC2; \ + type CM_HIST_SCALE_SRC3; \ + type CM_HIST_BIAS_SRC1; \ + type CM_HIST_BIAS_SRC2; \ + type CM_HIST_BIAS_SRC3 + + +#define DPP_REG_VARIABLE_LIST_DCN42 \ + DPP_REG_VARIABLE_LIST_DCN401; \ + uint32_t ALPHA_2BIT_LUT01; \ + uint32_t ALPHA_2BIT_LUT23; \ + uint32_t CM_HIST_CNTL; \ + uint32_t CM_HIST_INDEX; \ + uint32_t CM_HIST_LOCK; \ + uint32_t CM_HIST_DATA; \ + uint32_t CM_HIST_STATUS; \ + uint32_t CM_HIST_SCALE_SRC1; \ + uint32_t CM_HIST_COEFA_SRC2; \ + uint32_t CM_HIST_COEFB_SRC2; \ + uint32_t CM_HIST_COEFC_SRC2; \ + uint32_t CM_HIST_SCALE_SRC3; \ + uint32_t CM_HIST_BIAS_SRC1; \ + uint32_t CM_HIST_BIAS_SRC2; \ + uint32_t CM_HIST_BIAS_SRC3 + +struct dcn42_dpp_registers { + DPP_REG_VARIABLE_LIST_DCN42; +}; + +struct dcn42_dpp_shift { + DPP_REG_FIELD_LIST_DCN42(uint8_t); +}; + +struct dcn42_dpp_mask { + DPP_REG_FIELD_LIST_DCN42(uint32_t); +}; +struct dcn42_dpp { + struct dpp base; + const struct dcn42_dpp_registers *tf_regs; + const struct dcn42_dpp_shift *tf_shift; + const struct dcn42_dpp_mask *tf_mask; + const uint16_t *filter_v; + const uint16_t *filter_h; + const uint16_t *filter_v_c; + const uint16_t *filter_h_c; + int lb_pixel_depth_supported; + int lb_memory_size; + int lb_bits_per_entry; + bool is_write_to_ram_a_safe; + struct scaler_data scl_data; + struct pwl_params pwl_data; +}; + +bool dpp42_construct(struct dcn42_dpp *dpp42, + struct dc_context *ctx, + uint32_t inst, + const struct dcn42_dpp_registers *tf_regs, + const struct dcn42_dpp_shift *tf_shift, + const struct dcn42_dpp_mask *tf_mask); + + +#endif /* __DCN42_DPP_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.c index c1bdbb38c690..3bf737195bac 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.c +++ b/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.c @@ -107,6 +107,11 @@ void dsc401_read_state(struct display_stream_compressor *dsc, struct dcn_dsc_sta REG_GET(DSCC_PPS_CONFIG7, SLICE_BPG_OFFSET, &s->dsc_slice_bpg_offset); REG_GET_2(DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_FORWARD_EN, &s->dsc_fw_en, DSCRM_DSC_OPP_PIPE_SOURCE, &s->dsc_opp_source); + REG_GET(DSCC_PPS_CONFIG1, BLOCK_PRED_ENABLE, &s->dsc_block_pred_enable); + REG_GET(DSCC_PPS_CONFIG0, LINEBUF_DEPTH, &s->dsc_line_buf_depth); + REG_GET(DSCC_PPS_CONFIG0, DSC_VERSION_MINOR, &s->dsc_version_minor); + REG_GET(DSCC_CONFIG1, DSCC_RATE_CONTROL_BUFFER_MODEL_SIZE, &s->dsc_rc_buffer_size); + REG_GET(DSCC_PPS_CONFIG0, SIMPLE_422, &s->dsc_simple_422); } diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dsc.h b/drivers/gpu/drm/amd/display/dc/dsc/dsc.h index ad7ef83694ea..a16c60d8532f 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/dsc.h +++ b/drivers/gpu/drm/amd/display/dc/dsc/dsc.h @@ -64,6 +64,11 @@ struct dcn_dsc_state { uint32_t dsc_chunk_size; uint32_t dsc_fw_en; uint32_t dsc_opp_source; + uint32_t dsc_block_pred_enable; + uint32_t dsc_line_buf_depth; + uint32_t dsc_version_minor; + uint32_t dsc_rc_buffer_size; + uint32_t dsc_simple_422; }; struct dcn_dsc_reg_state { diff --git a/drivers/gpu/drm/amd/display/dc/dwb/dcn30/dcn30_dwb.c b/drivers/gpu/drm/amd/display/dc/dwb/dcn30/dcn30_dwb.c index bc058f682438..0ee4f83a02eb 100644 --- a/drivers/gpu/drm/amd/display/dc/dwb/dcn30/dcn30_dwb.c +++ b/drivers/gpu/drm/amd/display/dc/dwb/dcn30/dcn30_dwb.c @@ -45,6 +45,7 @@ static bool dwb3_get_caps(struct dwbc *dwbc, struct dwb_caps *caps) { + (void)dwbc; if (caps) { caps->adapter_id = 0; /* we only support 1 adapter currently */ caps->hw_version = DCN_VERSION_3_0; diff --git a/drivers/gpu/drm/amd/display/dc/gpio/Makefile b/drivers/gpu/drm/amd/display/dc/gpio/Makefile index b72e2a9f9a28..f8142ebf363f 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/Makefile +++ b/drivers/gpu/drm/amd/display/dc/gpio/Makefile @@ -1,5 +1,5 @@ # -# Copyright 2017 Advanced Micro Devices, Inc. +# Copyright 2017-2026 Advanced Micro Devices, Inc. # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), @@ -132,3 +132,14 @@ AMD_DAL_GPIO_DCN401 = $(addprefix $(AMDDALPATH)/dc/gpio/dcn401/,$(GPIO_DCN401)) AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DCN401) +############################################################################### +# DCN 4.2 +############################################################################### + +GPIO_DCN42 = hw_translate_dcn42.o hw_factory_dcn42.o + +AMD_DAL_GPIO_DCN42 = $(addprefix $(AMDDALPATH)/dc/gpio/dcn42/,$(GPIO_DCN42)) + +AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DCN42) + + diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_factory_dcn42.c b/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_factory_dcn42.c new file mode 100644 index 000000000000..7d2090c7870e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_factory_dcn42.c @@ -0,0 +1,254 @@ +// SPDX-License-Identifier: MIT +// +// Copyright 2026 Advanced Micro Devices, Inc. + +#include "dm_services.h" +#include "include/gpio_types.h" +#include "../hw_factory.h" + + +#include "../hw_gpio.h" +#include "../hw_ddc.h" +#include "../hw_hpd.h" +#include "../hw_generic.h" + + + +#include "dcn/dcn_4_2_0_offset.h" +#include "dcn/dcn_4_2_0_sh_mask.h" +#include "dpcs/dpcs_4_0_0_offset.h" +#include "dpcs/dpcs_4_0_0_sh_mask.h" + +#include "reg_helper.h" +#include "../hpd_regs.h" +#include "hw_factory_dcn42.h" + +#define DCN_BASE__INST0_SEG2 0x000034C0 + +/* begin ********************* + * macros to expend register list macro defined in HW object header file */ + +/* DCN */ +#define block HPD +#define reg_num 0 + +#undef BASE_INNER +#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg + +#define BASE(seg) BASE_INNER(seg) + + + +#define REG(reg_name)\ + (BASE(reg ## reg_name ## _BASE_IDX) + reg ## reg_name) + +#define SF_HPD(reg_name, field_name, post_fix)\ + .field_name = HPD0_ ## reg_name ## __ ## field_name ## post_fix + +#define REGI(reg_name, block, id)\ + (BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name) + +#define SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +/* macros to expend register list macro defined in HW object header file + * end *********************/ + +// DC_GPIO_HPD_* registers are gone. +#undef HPD_REG_LIST +#define HPD_REG_LIST(id) \ + .int_status = REGI(DC_HPD_INT_STATUS, HPD, id),\ + .toggle_filt_cntl = REGI(DC_HPD_TOGGLE_FILT_CNTL, HPD, id) + +#define hpd_regs(id) \ +{\ + HPD_REG_LIST(id)\ +} + +static const struct hpd_registers hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4), +}; + +static const struct hpd_sh_mask hpd_shift = { + HPD_MASK_SH_LIST(__SHIFT) +}; + +static const struct hpd_sh_mask hpd_mask = { + HPD_MASK_SH_LIST(_MASK) +}; + +#include "../ddc_regs.h" + + /* set field name */ +#define SF_DDC(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +static const struct ddc_registers ddc_data_regs_dcn[] = { + ddc_data_regs_dcn2(1), + ddc_data_regs_dcn2(2), + ddc_data_regs_dcn2(3), + ddc_data_regs_dcn2(4), + ddc_data_regs_dcn2(5), + { + // add a dummy entry for cases no such port + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, + .ddc_setup = 0, + .phy_aux_cntl = 0, + .dc_gpio_aux_ctrl_5 = 0 + }, + { + DDC_GPIO_VGA_REG_LIST(DATA), + .ddc_setup = 0, + .phy_aux_cntl = 0, + .dc_gpio_aux_ctrl_5 = 0 + } +}; + +static const struct ddc_registers ddc_clk_regs_dcn[] = { + ddc_clk_regs_dcn2(1), + ddc_clk_regs_dcn2(2), + ddc_clk_regs_dcn2(3), + ddc_clk_regs_dcn2(4), + ddc_clk_regs_dcn2(5), + { + // add a dummy entry for cases no such port + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, + .ddc_setup = 0, + .phy_aux_cntl = 0, + .dc_gpio_aux_ctrl_5 = 0 + }, + { + DDC_GPIO_VGA_REG_LIST(CLK), + .ddc_setup = 0, + .phy_aux_cntl = 0, + .dc_gpio_aux_ctrl_5 = 0 + } +}; + +static const struct ddc_sh_mask ddc_shift[] = { + DDC_MASK_SH_LIST_DCN2(__SHIFT, 1), + DDC_MASK_SH_LIST_DCN2(__SHIFT, 2), + DDC_MASK_SH_LIST_DCN2(__SHIFT, 3), + DDC_MASK_SH_LIST_DCN2(__SHIFT, 4), + DDC_MASK_SH_LIST_DCN2(__SHIFT, 5), + DDC_MASK_SH_LIST_DCN2(__SHIFT, 6), + DDC_MASK_SH_LIST_DCN2_VGA(__SHIFT) +}; + +static const struct ddc_sh_mask ddc_mask[] = { + DDC_MASK_SH_LIST_DCN2(_MASK, 1), + DDC_MASK_SH_LIST_DCN2(_MASK, 2), + DDC_MASK_SH_LIST_DCN2(_MASK, 3), + DDC_MASK_SH_LIST_DCN2(_MASK, 4), + DDC_MASK_SH_LIST_DCN2(_MASK, 5), + DDC_MASK_SH_LIST_DCN2(_MASK, 6), + DDC_MASK_SH_LIST_DCN2_VGA(_MASK) +}; + +#include "../generic_regs.h" + +/* set field name */ +#define SF_GENERIC(reg_name, field_name, post_fix)\ + .field_name = 0 + +static const struct generic_registers generic_regs[] = { + {{ 0 }}, + {{ 0 }}, +}; + +static const struct generic_sh_mask generic_shift[] = { + { 0 }, + { 0 }, +}; + +static const struct generic_sh_mask generic_mask[] = { + { 0 }, + { 0 }, +}; + +static void define_generic_registers(struct hw_gpio_pin *pin, uint32_t en) +{ + struct hw_generic *generic = HW_GENERIC_FROM_BASE(pin); + + generic->regs = &generic_regs[en]; + generic->shifts = &generic_shift[en]; + generic->masks = &generic_mask[en]; + generic->base.regs = &generic_regs[en].gpio; +} + +static void define_ddc_registers( + struct hw_gpio_pin *pin, + uint32_t en) +{ + struct hw_ddc *ddc = HW_DDC_FROM_BASE(pin); + + switch (pin->id) { + case GPIO_ID_DDC_DATA: + ddc->regs = &ddc_data_regs_dcn[en]; + ddc->base.regs = &ddc_data_regs_dcn[en].gpio; + break; + case GPIO_ID_DDC_CLOCK: + ddc->regs = &ddc_clk_regs_dcn[en]; + ddc->base.regs = &ddc_clk_regs_dcn[en].gpio; + break; + default: + ASSERT_CRITICAL(false); + return; + } + + ddc->shifts = &ddc_shift[en]; + ddc->masks = &ddc_mask[en]; + +} + +static void define_hpd_registers(struct hw_gpio_pin *pin, uint32_t en) +{ + struct hw_hpd *hpd = HW_HPD_FROM_BASE(pin); + + hpd->regs = &hpd_regs[en]; + hpd->shifts = &hpd_shift; + hpd->masks = &hpd_mask; + hpd->base.regs = &hpd_regs[en].gpio; +} + + +/* function table */ +static const struct hw_factory_funcs funcs = { + .init_ddc_data = dal_hw_ddc_init, + .init_generic = dal_hw_generic_init, + .init_hpd = dal_hw_hpd_init, + .get_ddc_pin = dal_hw_ddc_get_pin, + .get_hpd_pin = dal_hw_hpd_get_pin, + .get_generic_pin = dal_hw_generic_get_pin, + .define_hpd_registers = define_hpd_registers, + .define_ddc_registers = define_ddc_registers, + .define_generic_registers = define_generic_registers +}; + +/* + * dal_hw_factory_dcn42_init + * + * @brief + * Initialize HW factory function pointers and pin info + * + * @param + * struct hw_factory *factory - [out] struct of function pointers + */ +void dal_hw_factory_dcn42_init(struct hw_factory *factory) +{ + factory->number_of_pins[GPIO_ID_DDC_DATA] = 8; + factory->number_of_pins[GPIO_ID_DDC_CLOCK] = 8; + factory->number_of_pins[GPIO_ID_GENERIC] = 4; + factory->number_of_pins[GPIO_ID_HPD] = 5; + factory->number_of_pins[GPIO_ID_GPIO_PAD] = 28; + factory->number_of_pins[GPIO_ID_VIP_PAD] = 0; + factory->number_of_pins[GPIO_ID_SYNC] = 0; + factory->number_of_pins[GPIO_ID_GSL] = 0;/*add this*/ + + factory->funcs = &funcs; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_factory_dcn42.h b/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_factory_dcn42.h new file mode 100644 index 000000000000..b723380eb17f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_factory_dcn42.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2026 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef __DAL_HW_FACTORY_DCN42_H__ +#define __DAL_HW_FACTORY_DCN42_H__ + +/* Initialize HW factory function pointers and pin info */ +void dal_hw_factory_dcn42_init(struct hw_factory *factory); + +#endif /* __DAL_HW_FACTORY_DCN42_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_translate_dcn42.c b/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_translate_dcn42.c new file mode 100644 index 000000000000..e7e1d9979876 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_translate_dcn42.c @@ -0,0 +1,206 @@ +// SPDX-License-Identifier: MIT +// +// Copyright 2026 Advanced Micro Devices, Inc. + +#include "hw_translate_dcn42.h" + +#include "dm_services.h" +#include "include/gpio_types.h" +#include "../hw_translate.h" + + +#include "dcn/dcn_4_2_0_offset.h" +#include "dcn/dcn_4_2_0_sh_mask.h" +#include "dpcs/dpcs_4_0_0_offset.h" +#include "dpcs/dpcs_4_0_0_sh_mask.h" + +#define DCN_BASE__INST0_SEG2 0x000034C0 + +/* begin ********************* + * macros to expend register list macro defined in HW object header file */ + +/* DCN */ +#define block HPD +#define reg_num 0 + +#undef BASE_INNER +#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg + +#define BASE(seg) BASE_INNER(seg) + +#undef REG +#define REG(reg_name)\ + (BASE(reg ## reg_name ## _BASE_IDX) + reg ## reg_name) +#define SF_HPD(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + + +/* macros to expend register list macro defined in HW object header file + * end *********************/ + + +static bool offset_to_id( + uint32_t offset, + uint32_t mask, + enum gpio_id *id, + uint32_t *en) +{ + (void)mask; + switch (offset) { + /* HPD */ + case REG(HPD0_DC_HPD_INT_STATUS): + *id = GPIO_ID_HPD; + *en = GPIO_HPD_1; + return true; + case REG(HPD1_DC_HPD_INT_STATUS): + *id = GPIO_ID_HPD; + *en = GPIO_HPD_2; + return true; + case REG(HPD2_DC_HPD_INT_STATUS): + *id = GPIO_ID_HPD; + *en = GPIO_HPD_3; + return true; + case REG(HPD3_DC_HPD_INT_STATUS): + *id = GPIO_ID_HPD; + *en = GPIO_HPD_4; + return true; + case REG(HPD4_DC_HPD_INT_STATUS): + *id = GPIO_ID_HPD; + *en = GPIO_HPD_5; + return true; + /* DDC */ + /* we don't care about the GPIO_ID for DDC + * in DdcHandle it will use GPIO_ID_DDC_DATA/GPIO_ID_DDC_CLOCK + * directly in the create method + */ + case REG(DC_GPIO_DDC1_A): + *en = GPIO_DDC_LINE_DDC1; + return true; + case REG(DC_GPIO_DDC2_A): + *en = GPIO_DDC_LINE_DDC2; + return true; + case REG(DC_GPIO_DDC3_A): + *en = GPIO_DDC_LINE_DDC3; + return true; + case REG(DC_GPIO_DDC4_A): + *en = GPIO_DDC_LINE_DDC4; + return true; + case REG(DC_GPIO_DDC5_A): + *en = GPIO_DDC_LINE_DDC5; + return true; + case REG(DC_GPIO_DDCVGA_A): + *en = GPIO_DDC_LINE_DDC_VGA; + return true; + default: + ASSERT_CRITICAL(false); + return false; + } +} + + +static bool id_to_offset( + enum gpio_id id, + uint32_t en, + struct gpio_pin_info *info) +{ + bool result = true; + + switch (id) { + case GPIO_ID_DDC_DATA: + info->mask = DC_GPIO_DDC1_A__DC_GPIO_DDC1DATA_A_MASK; + switch (en) { + case GPIO_DDC_LINE_DDC1: + info->offset = REG(DC_GPIO_DDC1_A); + break; + case GPIO_DDC_LINE_DDC2: + info->offset = REG(DC_GPIO_DDC2_A); + break; + case GPIO_DDC_LINE_DDC3: + info->offset = REG(DC_GPIO_DDC3_A); + break; + case GPIO_DDC_LINE_DDC4: + info->offset = REG(DC_GPIO_DDC4_A); + break; + case GPIO_DDC_LINE_DDC5: + info->offset = REG(DC_GPIO_DDC5_A); + break; + case GPIO_DDC_LINE_DDC_VGA: + info->offset = REG(DC_GPIO_DDCVGA_A); + break; + case GPIO_DDC_LINE_I2C_PAD: + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_DDC_CLOCK: + info->mask = DC_GPIO_DDC1_A__DC_GPIO_DDC1CLK_A_MASK; + switch (en) { + case GPIO_DDC_LINE_DDC1: + info->offset = REG(DC_GPIO_DDC1_A); + break; + case GPIO_DDC_LINE_DDC2: + info->offset = REG(DC_GPIO_DDC2_A); + break; + case GPIO_DDC_LINE_DDC3: + info->offset = REG(DC_GPIO_DDC3_A); + break; + case GPIO_DDC_LINE_DDC4: + info->offset = REG(DC_GPIO_DDC4_A); + break; + case GPIO_DDC_LINE_DDC5: + info->offset = REG(DC_GPIO_DDC5_A); + break; + case GPIO_DDC_LINE_DDC_VGA: + info->offset = REG(DC_GPIO_DDCVGA_A); + break; + case GPIO_DDC_LINE_I2C_PAD: + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_SYNC: + case GPIO_ID_VIP_PAD: + default: + ASSERT_CRITICAL(false); + result = false; + } + + if (result) { + info->offset_y = info->offset + 2; + info->offset_en = info->offset + 1; + info->offset_mask = info->offset - 1; + + info->mask_y = info->mask; + info->mask_en = info->mask; + info->mask_mask = info->mask; + } + + return result; +} + + +/* function table */ +static const struct hw_translate_funcs funcs = { + .offset_to_id = offset_to_id, + .id_to_offset = id_to_offset, +}; + + +/* + * dal_hw_translate_dcn42_init + * + * @brief + * Initialize Hw translate function pointers. + * + * @param + * struct hw_translate *tr - [out] struct of function pointers + * + */ +void dal_hw_translate_dcn42_init(struct hw_translate *tr) +{ + tr->funcs = &funcs; +} + + diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_translate_dcn42.h b/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_translate_dcn42.h new file mode 100644 index 000000000000..007b4d55fef1 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_translate_dcn42.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2026 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef __DAL_HW_TRANSLATE_DCN42_H__ +#define __DAL_HW_TRANSLATE_DCN42_H__ + +struct hw_translate; + +/* Initialize Hw translate function pointers */ +void dal_hw_translate_dcn42_init(struct hw_translate *tr); +#ifdef DAL_EMULATION_SUPPORTED +void dal_emulated_hw_translate_dcn42_init(struct hw_translate *tr); +#endif + +#endif /* __DAL_HW_TRANSLATE_DCN42_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c index 8bc67ca42197..d81a71ac00d2 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c @@ -53,12 +53,14 @@ #include "dcn315/hw_factory_dcn315.h" #include "dcn32/hw_factory_dcn32.h" #include "dcn401/hw_factory_dcn401.h" +#include "dcn42/hw_factory_dcn42.h" bool dal_hw_factory_init( struct hw_factory *factory, enum dce_version dce_version, enum dce_environment dce_environment) { + (void)dce_environment; switch (dce_version) { #if defined(CONFIG_DRM_AMD_DC_SI) case DCE_VERSION_6_0: @@ -118,6 +120,9 @@ bool dal_hw_factory_init( case DCN_VERSION_4_01: dal_hw_factory_dcn401_init(factory); return true; + case DCN_VERSION_4_2: + dal_hw_factory_dcn42_init(factory); + return true; default: ASSERT_CRITICAL(false); return false; diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c index 660510842ecf..f0d400972897 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c @@ -199,5 +199,6 @@ void dal_hw_gpio_construct( void dal_hw_gpio_destruct( struct hw_gpio *pin) { + (void)pin; ASSERT(!pin->base.opened); } diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c index cb79a2832287..e6e36a912b13 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c @@ -53,6 +53,7 @@ #include "dcn315/hw_translate_dcn315.h" #include "dcn32/hw_translate_dcn32.h" #include "dcn401/hw_translate_dcn401.h" +#include "dcn42/hw_translate_dcn42.h" /* * This unit @@ -63,6 +64,7 @@ bool dal_hw_translate_init( enum dce_version dce_version, enum dce_environment dce_environment) { + (void)dce_environment; switch (dce_version) { #if defined(CONFIG_DRM_AMD_DC_SI) case DCE_VERSION_6_0: @@ -119,6 +121,9 @@ bool dal_hw_translate_init( case DCN_VERSION_4_01: dal_hw_translate_dcn401_init(translate); return true; + case DCN_VERSION_4_2: + dal_hw_translate_dcn42_init(translate); + return true; default: BREAK_TO_DEBUGGER(); return false; diff --git a/drivers/gpu/drm/amd/display/dc/hpo/Makefile b/drivers/gpu/drm/amd/display/dc/hpo/Makefile index 7f2c9ee0dff1..25b196714bd8 100644 --- a/drivers/gpu/drm/amd/display/dc/hpo/Makefile +++ b/drivers/gpu/drm/amd/display/dc/hpo/Makefile @@ -1,5 +1,5 @@ # -# Copyright 2020 Advanced Micro Devices, Inc. +# Copyright 2020-2026 Advanced Micro Devices, Inc. # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), @@ -47,4 +47,13 @@ HPO_DCN32 = dcn32_hpo_dp_link_encoder.o AMD_DAL_HPO_DCN32 = $(addprefix $(AMDDALPATH)/dc/hpo/dcn32/,$(HPO_DCN32)) AMD_DISPLAY_FILES += $(AMD_DAL_HPO_DCN32) + +############################################################################### +# DCN42 +############################################################################### +HPO_DCN42 = dcn42_hpo_dp_link_encoder.o + +AMD_DAL_HPO_DCN42 = $(addprefix $(AMDDALPATH)/dc/hpo/dcn42/,$(HPO_DCN42)) + +AMD_DISPLAY_FILES += $(AMD_DAL_HPO_DCN42) endif diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.c index 759b453385c4..92ed130aeaec 100644 --- a/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.c @@ -640,6 +640,11 @@ static void dcn31_hpo_dp_stream_enc_audio_setup( REG_UPDATE(DP_STREAM_ENC_AUDIO_CONTROL, DP_STREAM_ENC_INPUT_MUX_AUDIO_STREAM_SOURCE_SEL, az_inst); + if (enc3->hpo_se_mask->DP_STREAM_ENC_APG_CLOCK_EN) { + /*enable apg clk*/ + REG_UPDATE(DP_STREAM_ENC_AUDIO_CONTROL, + DP_STREAM_ENC_APG_CLOCK_EN, 1); + } ASSERT(enc->apg); enc->apg->funcs->se_audio_setup(enc->apg, az_inst, info); } diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.h index 82c3b3ac1f0d..d96fcc59cc0e 100644 --- a/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 Advanced Micro Devices, Inc. + * Copyright 2019-2026 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -208,17 +208,24 @@ type CRC_CONT_MODE_ENABLE;\ type HBLANK_MINIMUM_SYMBOL_WIDTH +#define DCN4_2_HPO_DP_STREAM_ENC_REG_FIELD_LIST(type) \ + type DP_STREAM_ENC_APG_CLOCK_EN +#define DCN4_2_HPO_DP_STREAM_ENC_MASK_SH_LIST(mask_sh)\ + DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(mask_sh),\ + SE_SF(DP_STREAM_ENC0_DP_STREAM_ENC_AUDIO_CONTROL, DP_STREAM_ENC_APG_CLOCK_EN, mask_sh) struct dcn31_hpo_dp_stream_encoder_registers { DCN3_1_HPO_DP_STREAM_ENC_REGS; }; struct dcn31_hpo_dp_stream_encoder_shift { DCN3_1_HPO_DP_STREAM_ENC_REG_FIELD_LIST(uint8_t); + DCN4_2_HPO_DP_STREAM_ENC_REG_FIELD_LIST(uint8_t); }; struct dcn31_hpo_dp_stream_encoder_mask { DCN3_1_HPO_DP_STREAM_ENC_REG_FIELD_LIST(uint32_t); + DCN4_2_HPO_DP_STREAM_ENC_REG_FIELD_LIST(uint32_t); }; struct dcn31_hpo_dp_stream_encoder { @@ -241,5 +248,4 @@ void dcn31_hpo_dp_stream_encoder_construct( const struct dcn31_hpo_dp_stream_encoder_shift *hpo_se_shift, const struct dcn31_hpo_dp_stream_encoder_mask *hpo_se_mask); - #endif // __DAL_DCN31_HPO_STREAM_ENCODER_H__ diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn42/dcn42_hpo_dp_link_encoder.c b/drivers/gpu/drm/amd/display/dc/hpo/dcn42/dcn42_hpo_dp_link_encoder.c new file mode 100644 index 000000000000..4b86b1bf6503 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn42/dcn42_hpo_dp_link_encoder.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: MIT +// +// Copyright 2026 Advanced Micro Devices, Inc. + +#include "dc_bios_types.h" +#include "dcn31/dcn31_hpo_dp_link_encoder.h" +#include "dcn32/dcn32_hpo_dp_link_encoder.h" +#include "dcn42_hpo_dp_link_encoder.h" +#include "reg_helper.h" +#include "stream_encoder.h" + +#define DC_LOGGER \ + enc3->base.ctx->logger + +#define REG(reg)\ + (enc3->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + enc3->hpo_le_shift->field_name, enc3->hpo_le_mask->field_name + + +#define CTX \ + enc3->base.ctx + + +static void dcn42_hpo_dp_link_enc_read_state( + struct hpo_dp_link_encoder *enc, + struct hpo_dp_link_enc_state *state) +{ + struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc); + + ASSERT(state); + + REG_GET(DP_DPHY_SYM32_STATUS, + STATUS, &state->link_enc_enabled); + REG_GET(DP_DPHY_SYM32_CONTROL, + NUM_LANES, &state->lane_count); + REG_GET(DP_DPHY_SYM32_CONTROL, + MODE, (uint32_t *)&state->link_mode); + + REG_GET_2(DP_DPHY_SYM32_SAT_VC0, + SAT_STREAM_SOURCE, &state->stream_src[0], + SAT_SLOT_COUNT, &state->slot_count[0]); + REG_GET_2(DP_DPHY_SYM32_SAT_VC1, + SAT_STREAM_SOURCE, &state->stream_src[1], + SAT_SLOT_COUNT, &state->slot_count[1]); + REG_GET_2(DP_DPHY_SYM32_SAT_VC2, + SAT_STREAM_SOURCE, &state->stream_src[2], + SAT_SLOT_COUNT, &state->slot_count[2]); + + REG_GET_2(DP_DPHY_SYM32_VC_RATE_CNTL0, + STREAM_VC_RATE_X, &state->vc_rate_x[0], + STREAM_VC_RATE_Y, &state->vc_rate_y[0]); + REG_GET_2(DP_DPHY_SYM32_VC_RATE_CNTL1, + STREAM_VC_RATE_X, &state->vc_rate_x[1], + STREAM_VC_RATE_Y, &state->vc_rate_y[1]); + REG_GET_2(DP_DPHY_SYM32_VC_RATE_CNTL2, + STREAM_VC_RATE_X, &state->vc_rate_x[2], + STREAM_VC_RATE_Y, &state->vc_rate_y[2]); +} + +static struct hpo_dp_link_encoder_funcs dcn42_hpo_dp_link_encoder_funcs = { + .enable_link_phy = dcn31_hpo_dp_link_enc_enable_dp_output, + .disable_link_phy = dcn31_hpo_dp_link_enc_disable_output, + .link_enable = dcn31_hpo_dp_link_enc_enable, + .link_disable = dcn31_hpo_dp_link_enc_disable, + .set_link_test_pattern = dcn31_hpo_dp_link_enc_set_link_test_pattern, + .update_stream_allocation_table = dcn31_hpo_dp_link_enc_update_stream_allocation_table, + .set_throttled_vcp_size = dcn31_hpo_dp_link_enc_set_throttled_vcp_size, + .is_in_alt_mode = dcn32_hpo_dp_link_enc_is_in_alt_mode, + .read_state = dcn42_hpo_dp_link_enc_read_state, + .set_ffe = dcn31_hpo_dp_link_enc_set_ffe, +}; + +void hpo_dp_link_encoder42_construct(struct dcn31_hpo_dp_link_encoder *enc31, + struct dc_context *ctx, + uint32_t inst, + const struct dcn31_hpo_dp_link_encoder_registers *hpo_le_regs, + const struct dcn31_hpo_dp_link_encoder_shift *hpo_le_shift, + const struct dcn31_hpo_dp_link_encoder_mask *hpo_le_mask) +{ + enc31->base.ctx = ctx; + + enc31->base.inst = inst; + enc31->base.funcs = &dcn42_hpo_dp_link_encoder_funcs; + enc31->base.hpd_source = HPD_SOURCEID_UNKNOWN; + enc31->base.transmitter = TRANSMITTER_UNKNOWN; + + enc31->regs = hpo_le_regs; + enc31->hpo_le_shift = hpo_le_shift; + enc31->hpo_le_mask = hpo_le_mask; +} diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn42/dcn42_hpo_dp_link_encoder.h b/drivers/gpu/drm/amd/display/dc/hpo/dcn42/dcn42_hpo_dp_link_encoder.h new file mode 100644 index 000000000000..3e84d016507c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn42/dcn42_hpo_dp_link_encoder.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright 2026 Advanced Micro Devices, Inc. */ + + +#ifndef __DAL_DCN42_HPO_DP_LINK_ENCODER_H__ +#define __DAL_DCN42_HPO_DP_LINK_ENCODER_H__ + +#include "link_encoder.h" + +void hpo_dp_link_encoder42_construct(struct dcn31_hpo_dp_link_encoder *enc31, + struct dc_context *ctx, + uint32_t inst, + const struct dcn31_hpo_dp_link_encoder_registers *hpo_le_regs, + const struct dcn31_hpo_dp_link_encoder_shift *hpo_le_shift, + const struct dcn31_hpo_dp_link_encoder_mask *hpo_le_mask); + +#endif // __DAL_DCN32_HPO_DP_LINK_ENCODER_H__ diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/Makefile b/drivers/gpu/drm/amd/display/dc/hubbub/Makefile index 66ca5a6a0415..29c8e2651442 100644 --- a/drivers/gpu/drm/amd/display/dc/hubbub/Makefile +++ b/drivers/gpu/drm/amd/display/dc/hubbub/Makefile @@ -1,5 +1,5 @@ -# Copyright 2022 Advanced Micro Devices, Inc. +# Copyright 2022-2026 Advanced Micro Devices, Inc. # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), @@ -101,4 +101,12 @@ AMD_DAL_HUBBUB_DCN401 = $(addprefix $(AMDDALPATH)/dc/hubbub/dcn401/,$(HUBBUB_DCN AMD_DISPLAY_FILES += $(AMD_DAL_HUBBUB_DCN401) ############################################################################### +# DCN42 +############################################################################### +HUBBUB_DCN42 = dcn42_hubbub.o + +AMD_DAL_HUBBUB_DCN42 = $(addprefix $(AMDDALPATH)/dc/hubbub/dcn42/,$(HUBBUB_DCN42)) + +AMD_DISPLAY_FILES += $(AMD_DAL_HUBBUB_DCN42) + endif diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h b/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h index 990d3cd8e050..ff9a1ae29474 100644 --- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h +++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h @@ -1,5 +1,5 @@ /* - * Copyright 2016 Advanced Micro Devices, Inc. + * Copyright 2016-2026 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -441,6 +441,8 @@ struct dcn_hubbub_registers { type DCHUBBUB_ARB_ALLOW_DCFCLK_DEEP_SLEEP_FORCE_VALUE;\ type DCHUBBUB_ARB_ALLOW_DCFCLK_DEEP_SLEEP_FORCE_ENABLE +#define HUBBUB_REG_FIELD_LIST_DCN4_2(type) \ + type URGENT_ZERO_SIZE_REQ_EN struct dcn_hubbub_shift { DCN_HUBBUB_REG_FIELD_LIST(uint8_t); HUBBUB_STUTTER_REG_FIELD_LIST(uint8_t); @@ -449,6 +451,7 @@ struct dcn_hubbub_shift { HUBBUB_REG_FIELD_LIST_DCN32(uint8_t); HUBBUB_REG_FIELD_LIST_DCN35(uint8_t); HUBBUB_REG_FIELD_LIST_DCN4_01(uint8_t); + HUBBUB_REG_FIELD_LIST_DCN4_2(uint8_t); }; @@ -460,6 +463,7 @@ struct dcn_hubbub_mask { HUBBUB_REG_FIELD_LIST_DCN32(uint32_t); HUBBUB_REG_FIELD_LIST_DCN35(uint32_t); HUBBUB_REG_FIELD_LIST_DCN4_01(uint32_t); + HUBBUB_REG_FIELD_LIST_DCN4_2(uint8_t); }; diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn31/dcn31_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn31/dcn31_hubbub.c index 5a03758e3de6..3c298192f359 100644 --- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn31/dcn31_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn31/dcn31_hubbub.c @@ -943,6 +943,7 @@ static void hubbub31_get_dchub_ref_freq(struct hubbub *hubbub, unsigned int dccg_ref_freq_inKhz, unsigned int *dchub_ref_freq_inKhz) { + (void)dccg_ref_freq_inKhz; struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); uint32_t ref_div = 0; uint32_t ref_en = 0; diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn35/dcn35_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn35/dcn35_hubbub.c index 43ba399f4822..82d4e3e0e5e8 100644 --- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn35/dcn35_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn35/dcn35_hubbub.c @@ -259,6 +259,7 @@ void hubbub35_get_dchub_ref_freq(struct hubbub *hubbub, unsigned int dccg_ref_freq_inKhz, unsigned int *dchub_ref_freq_inKhz) { + (void)dccg_ref_freq_inKhz; struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); uint32_t ref_div = 0; uint32_t ref_en = 0; diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c index 941dce439e97..3b9542c08f3d 100644 --- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c @@ -70,6 +70,7 @@ bool hubbub401_program_urgent_watermarks( unsigned int refclk_mhz, bool safe_to_lower) { + (void)refclk_mhz; struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); bool wm_pending = false; @@ -188,6 +189,7 @@ bool hubbub401_program_stutter_watermarks( unsigned int refclk_mhz, bool safe_to_lower) { + (void)refclk_mhz; struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); bool wm_pending = false; @@ -287,6 +289,7 @@ bool hubbub401_program_pstate_watermarks( unsigned int refclk_mhz, bool safe_to_lower) { + (void)refclk_mhz; struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); bool wm_pending = false; @@ -414,6 +417,7 @@ bool hubbub401_program_usr_watermarks( unsigned int refclk_mhz, bool safe_to_lower) { + (void)refclk_mhz; struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); bool wm_pending = false; @@ -1151,8 +1155,6 @@ void dcn401_program_compbuf_segments(struct hubbub *hubbub, unsigned compbuf_siz { struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); - unsigned int cur_compbuf_size_seg = 0; - if (safe_to_increase || compbuf_size_seg <= hubbub2->compbuf_size_segments) { if (compbuf_size_seg > hubbub2->compbuf_size_segments) { REG_WAIT(DCHUBBUB_DET0_CTRL, DET0_SIZE_CURRENT, hubbub2->det0_size, 1, 100); @@ -1165,8 +1167,6 @@ void dcn401_program_compbuf_segments(struct hubbub *hubbub, unsigned compbuf_siz + hubbub2->det3_size + compbuf_size_seg <= hubbub2->crb_size_segs); REG_UPDATE(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE, compbuf_size_seg); hubbub2->compbuf_size_segments = compbuf_size_seg; - - ASSERT(REG_GET(DCHUBBUB_COMPBUF_CTRL, CONFIG_ERROR, &cur_compbuf_size_seg) && !cur_compbuf_size_seg); } } diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.c new file mode 100644 index 000000000000..73b6b0ffcb74 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.c @@ -0,0 +1,576 @@ +// SPDX-License-Identifier: MIT +// +// Copyright 2026 Advanced Micro Devices, Inc. + +#include "dcn30/dcn30_hubbub.h" +#include "dcn31/dcn31_hubbub.h" +#include "dcn32/dcn32_hubbub.h" +#include "dcn35/dcn35_hubbub.h" +#include "dcn401/dcn401_hubbub.h" +#include "dcn42/dcn42_hubbub.h" +#include "dm_services.h" +#include "reg_helper.h" + +#define DCN42_CRB_SEGMENT_SIZE_KB 64 + +#define CTX \ + hubbub2->base.ctx +#define DC_LOGGER \ + hubbub2->base.ctx->logger +#define REG(reg)\ + hubbub2->regs->reg + +#undef FN +#define FN(reg_name, field_name) \ + hubbub2->shifts->field_name, hubbub2->masks->field_name + +static bool hubbub42_program_urgent_watermarks( + struct hubbub *hubbub, + union dcn_watermark_set *watermarks, + bool safe_to_lower) +{ + struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); + bool wm_pending = false; + + /* Repeat for water mark set A, B, C and D. */ + /* clock state A */ + if (safe_to_lower || watermarks->dcn4x.a.urgent > hubbub2->watermarks.dcn4x.a.urgent) { + hubbub2->watermarks.dcn4x.a.urgent = watermarks->dcn4x.a.urgent; + REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, 0, + DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, watermarks->dcn4x.a.urgent); + } else if (watermarks->dcn4x.a.urgent < hubbub2->watermarks.dcn4x.a.urgent) + wm_pending = true; + + /* determine the transfer time for a quantity of data for a particular requestor.*/ + if (safe_to_lower || watermarks->dcn4x.a.frac_urg_bw_flip > hubbub2->watermarks.dcn4x.a.frac_urg_bw_flip) { + hubbub2->watermarks.dcn4x.a.frac_urg_bw_flip = watermarks->dcn4x.a.frac_urg_bw_flip; + REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, 0, + DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, watermarks->dcn4x.a.frac_urg_bw_flip); + } else if (watermarks->dcn4x.a.frac_urg_bw_flip < hubbub2->watermarks.dcn4x.a.frac_urg_bw_flip) + wm_pending = true; + + if (safe_to_lower || watermarks->dcn4x.a.frac_urg_bw_nom > hubbub2->watermarks.dcn4x.a.frac_urg_bw_nom) { + hubbub2->watermarks.dcn4x.a.frac_urg_bw_nom = watermarks->dcn4x.a.frac_urg_bw_nom; + REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, 0, + DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, watermarks->dcn4x.a.frac_urg_bw_nom); + } else if (watermarks->dcn4x.a.frac_urg_bw_nom < hubbub2->watermarks.dcn4x.a.frac_urg_bw_nom) + wm_pending = true; + + if (safe_to_lower || watermarks->dcn4x.a.refcyc_per_trip_to_mem > hubbub2->watermarks.dcn4x.a.refcyc_per_trip_to_mem) { + hubbub2->watermarks.dcn4x.a.refcyc_per_trip_to_mem = watermarks->dcn4x.a.refcyc_per_trip_to_mem; + REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, 0, + DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, watermarks->dcn4x.a.refcyc_per_trip_to_mem); + } else if (watermarks->dcn4x.a.refcyc_per_trip_to_mem < hubbub2->watermarks.dcn4x.a.refcyc_per_trip_to_mem) + wm_pending = true; + + /* clock state B */ + if (safe_to_lower || watermarks->dcn4x.b.urgent > hubbub2->watermarks.dcn4x.b.urgent) { + hubbub2->watermarks.dcn4x.b.urgent = watermarks->dcn4x.b.urgent; + REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, 0, + DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, watermarks->dcn4x.b.urgent); + } else if (watermarks->dcn4x.b.urgent < hubbub2->watermarks.dcn4x.b.urgent) + wm_pending = true; + + /* determine the transfer time for a quantity of data for a particular requestor.*/ + if (safe_to_lower || watermarks->dcn4x.b.frac_urg_bw_flip > hubbub2->watermarks.dcn4x.b.frac_urg_bw_flip) { + hubbub2->watermarks.dcn4x.b.frac_urg_bw_flip = watermarks->dcn4x.b.frac_urg_bw_flip; + REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, 0, + DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, watermarks->dcn4x.b.frac_urg_bw_flip); + } else if (watermarks->dcn4x.b.frac_urg_bw_flip < hubbub2->watermarks.dcn4x.b.frac_urg_bw_flip) + wm_pending = true; + + if (safe_to_lower || watermarks->dcn4x.b.frac_urg_bw_nom > hubbub2->watermarks.dcn4x.b.frac_urg_bw_nom) { + hubbub2->watermarks.dcn4x.b.frac_urg_bw_nom = watermarks->dcn4x.b.frac_urg_bw_nom; + REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, 0, + DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, watermarks->dcn4x.b.frac_urg_bw_nom); + } else if (watermarks->dcn4x.b.frac_urg_bw_nom < hubbub2->watermarks.dcn4x.b.frac_urg_bw_nom) + wm_pending = true; + + if (safe_to_lower || watermarks->dcn4x.b.refcyc_per_trip_to_mem > hubbub2->watermarks.dcn4x.b.refcyc_per_trip_to_mem) { + hubbub2->watermarks.dcn4x.b.refcyc_per_trip_to_mem = watermarks->dcn4x.b.refcyc_per_trip_to_mem; + REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, 0, + DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, watermarks->dcn4x.b.refcyc_per_trip_to_mem); + } else if (watermarks->dcn4x.b.refcyc_per_trip_to_mem < hubbub2->watermarks.dcn4x.b.refcyc_per_trip_to_mem) + wm_pending = true; + + /* clock state C */ + if (safe_to_lower || watermarks->dcn4x.c.urgent > hubbub2->watermarks.dcn4x.c.urgent) { + hubbub2->watermarks.dcn4x.c.urgent = watermarks->dcn4x.c.urgent; + REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, 0, + DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, watermarks->dcn4x.c.urgent); + } else if (watermarks->dcn4x.c.urgent < hubbub2->watermarks.dcn4x.c.urgent) + wm_pending = true; + + /* determine the transfer time for a quantity of data for a particular requestor.*/ + if (safe_to_lower || watermarks->dcn4x.c.frac_urg_bw_flip > hubbub2->watermarks.dcn4x.c.frac_urg_bw_flip) { + hubbub2->watermarks.dcn4x.c.frac_urg_bw_flip = watermarks->dcn4x.c.frac_urg_bw_flip; + REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, 0, + DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, watermarks->dcn4x.c.frac_urg_bw_flip); + } else if (watermarks->dcn4x.c.frac_urg_bw_flip < hubbub2->watermarks.dcn4x.c.frac_urg_bw_flip) + wm_pending = true; + + if (safe_to_lower || watermarks->dcn4x.c.frac_urg_bw_nom > hubbub2->watermarks.dcn4x.c.frac_urg_bw_nom) { + hubbub2->watermarks.dcn4x.c.frac_urg_bw_nom = watermarks->dcn4x.c.frac_urg_bw_nom; + REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, 0, + DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, watermarks->dcn4x.c.frac_urg_bw_nom); + } else if (watermarks->dcn4x.c.frac_urg_bw_nom < hubbub2->watermarks.dcn4x.c.frac_urg_bw_nom) + wm_pending = true; + + if (safe_to_lower || watermarks->dcn4x.c.refcyc_per_trip_to_mem > hubbub2->watermarks.dcn4x.c.refcyc_per_trip_to_mem) { + hubbub2->watermarks.dcn4x.c.refcyc_per_trip_to_mem = watermarks->dcn4x.c.refcyc_per_trip_to_mem; + REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, 0, + DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, watermarks->dcn4x.c.refcyc_per_trip_to_mem); + } else if (watermarks->dcn4x.c.refcyc_per_trip_to_mem < hubbub2->watermarks.dcn4x.c.refcyc_per_trip_to_mem) + wm_pending = true; + + /* clock state D */ + if (safe_to_lower || watermarks->dcn4x.d.urgent > hubbub2->watermarks.dcn4x.d.urgent) { + hubbub2->watermarks.dcn4x.d.urgent = watermarks->dcn4x.d.urgent; + REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, 0, + DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, watermarks->dcn4x.d.urgent); + } else if (watermarks->dcn4x.d.urgent < hubbub2->watermarks.dcn4x.d.urgent) + wm_pending = true; + + /* determine the transfer time for a quantity of data for a particular requestor.*/ + if (safe_to_lower || watermarks->dcn4x.d.frac_urg_bw_flip > hubbub2->watermarks.dcn4x.d.frac_urg_bw_flip) { + hubbub2->watermarks.dcn4x.d.frac_urg_bw_flip = watermarks->dcn4x.d.frac_urg_bw_flip; + REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, 0, + DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, watermarks->dcn4x.d.frac_urg_bw_flip); + } else if (watermarks->dcn4x.d.frac_urg_bw_flip < hubbub2->watermarks.dcn4x.d.frac_urg_bw_flip) + wm_pending = true; + + if (safe_to_lower || watermarks->dcn4x.d.frac_urg_bw_nom > hubbub2->watermarks.dcn4x.d.frac_urg_bw_nom) { + hubbub2->watermarks.dcn4x.d.frac_urg_bw_nom = watermarks->dcn4x.d.frac_urg_bw_nom; + REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, 0, + DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, watermarks->dcn4x.d.frac_urg_bw_nom); + } else if (watermarks->dcn4x.d.frac_urg_bw_nom < hubbub2->watermarks.dcn4x.d.frac_urg_bw_nom) + wm_pending = true; + + if (safe_to_lower || watermarks->dcn4x.d.refcyc_per_trip_to_mem > hubbub2->watermarks.dcn4x.d.refcyc_per_trip_to_mem) { + hubbub2->watermarks.dcn4x.d.refcyc_per_trip_to_mem = watermarks->dcn4x.d.refcyc_per_trip_to_mem; + REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, 0, + DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, watermarks->dcn4x.d.refcyc_per_trip_to_mem); + } else if (watermarks->dcn4x.d.refcyc_per_trip_to_mem < hubbub2->watermarks.dcn4x.d.refcyc_per_trip_to_mem) + wm_pending = true; + + return wm_pending; +} + +static bool hubbub42_program_stutter_watermarks( + struct hubbub *hubbub, + union dcn_watermark_set *watermarks, + bool safe_to_lower) +{ + struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); + bool wm_pending = false; + + /* clock state A */ + if (safe_to_lower || watermarks->dcn4x.a.sr_enter > hubbub2->watermarks.dcn4x.a.sr_enter) { + hubbub2->watermarks.dcn4x.a.sr_enter = watermarks->dcn4x.a.sr_enter; + REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, 0, + DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, watermarks->dcn4x.a.sr_enter); + } else if (watermarks->dcn4x.a.sr_enter < hubbub2->watermarks.dcn4x.a.sr_enter) + wm_pending = true; + + if (safe_to_lower || watermarks->dcn4x.a.sr_exit > hubbub2->watermarks.dcn4x.a.sr_exit) { + hubbub2->watermarks.dcn4x.a.sr_exit = watermarks->dcn4x.a.sr_exit; + REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, 0, + DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, watermarks->dcn4x.a.sr_exit); + } else if (watermarks->dcn4x.a.sr_exit < hubbub2->watermarks.dcn4x.a.sr_exit) + wm_pending = true; + + /* clock state B */ + if (safe_to_lower || watermarks->dcn4x.b.sr_enter > hubbub2->watermarks.dcn4x.b.sr_enter) { + hubbub2->watermarks.dcn4x.b.sr_enter = watermarks->dcn4x.b.sr_enter; + REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, 0, + DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, watermarks->dcn4x.b.sr_enter); + } else if (watermarks->dcn4x.b.sr_enter < hubbub2->watermarks.dcn4x.b.sr_enter) + wm_pending = true; + + if (safe_to_lower || watermarks->dcn4x.b.sr_exit > hubbub2->watermarks.dcn4x.b.sr_exit) { + hubbub2->watermarks.dcn4x.b.sr_exit = watermarks->dcn4x.b.sr_exit; + REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, 0, + DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, watermarks->dcn4x.b.sr_exit); + } else if (watermarks->dcn4x.b.sr_exit < hubbub2->watermarks.dcn4x.b.sr_exit) + wm_pending = true; + + /* clock state C */ + if (safe_to_lower || watermarks->dcn4x.c.sr_enter > hubbub2->watermarks.dcn4x.c.sr_enter) { + hubbub2->watermarks.dcn4x.c.sr_enter = watermarks->dcn4x.c.sr_enter; + REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, 0, + DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, watermarks->dcn4x.c.sr_enter); + } else if (watermarks->dcn4x.c.sr_enter < hubbub2->watermarks.dcn4x.c.sr_enter) + wm_pending = true; + + if (safe_to_lower || watermarks->dcn4x.c.sr_exit > hubbub2->watermarks.dcn4x.c.sr_exit) { + hubbub2->watermarks.dcn4x.c.sr_exit = watermarks->dcn4x.c.sr_exit; + REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, 0, + DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, watermarks->dcn4x.c.sr_exit); + } else if (watermarks->dcn4x.c.sr_exit < hubbub2->watermarks.dcn4x.c.sr_exit) + wm_pending = true; + + /* clock state D */ + if (safe_to_lower || watermarks->dcn4x.d.sr_enter > hubbub2->watermarks.dcn4x.d.sr_enter) { + hubbub2->watermarks.dcn4x.d.sr_enter = watermarks->dcn4x.d.sr_enter; + REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, 0, + DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, watermarks->dcn4x.d.sr_enter); + } else if (watermarks->dcn4x.d.sr_enter < hubbub2->watermarks.dcn4x.d.sr_enter) + wm_pending = true; + + if (safe_to_lower || watermarks->dcn4x.d.sr_exit > hubbub2->watermarks.dcn4x.d.sr_exit) { + hubbub2->watermarks.dcn4x.d.sr_exit = watermarks->dcn4x.d.sr_exit; + REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, 0, + DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, watermarks->dcn4x.d.sr_exit); + } else if (watermarks->dcn4x.d.sr_exit < hubbub2->watermarks.dcn4x.d.sr_exit) + wm_pending = true; + + return wm_pending; +} + +static bool hubbub42_program_pstate_watermarks( + struct hubbub *hubbub, + union dcn_watermark_set *watermarks, + bool safe_to_lower) +{ + struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); + bool wm_pending = false; + + /* Section for UCLK_PSTATE_CHANGE_WATERMARKS */ + /* UCLK state A */ + if (safe_to_lower || watermarks->dcn4x.a.uclk_pstate > hubbub2->watermarks.dcn4x.a.uclk_pstate) { + hubbub2->watermarks.dcn4x.a.uclk_pstate = watermarks->dcn4x.a.uclk_pstate; + REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, 0, + DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, watermarks->dcn4x.a.uclk_pstate); + } else if (watermarks->dcn4x.a.uclk_pstate < hubbub2->watermarks.dcn4x.a.uclk_pstate) + wm_pending = true; + + /* UCLK state B */ + if (safe_to_lower || watermarks->dcn4x.b.uclk_pstate > hubbub2->watermarks.dcn4x.b.uclk_pstate) { + hubbub2->watermarks.dcn4x.b.uclk_pstate = watermarks->dcn4x.b.uclk_pstate; + REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, 0, + DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, watermarks->dcn4x.b.uclk_pstate); + } else if (watermarks->dcn4x.b.uclk_pstate < hubbub2->watermarks.dcn4x.b.uclk_pstate) + wm_pending = true; + + /* UCLK state C */ + if (safe_to_lower || watermarks->dcn4x.c.uclk_pstate > hubbub2->watermarks.dcn4x.c.uclk_pstate) { + hubbub2->watermarks.dcn4x.c.uclk_pstate = watermarks->dcn4x.c.uclk_pstate; + REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, 0, + DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, watermarks->dcn4x.c.uclk_pstate); + } else if (watermarks->dcn4x.c.uclk_pstate < hubbub2->watermarks.dcn4x.c.uclk_pstate) + wm_pending = true; + + /* UCLK state D */ + if (safe_to_lower || watermarks->dcn4x.d.uclk_pstate > hubbub2->watermarks.dcn4x.d.uclk_pstate) { + hubbub2->watermarks.dcn4x.d.uclk_pstate = watermarks->dcn4x.d.uclk_pstate; + REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, 0, + DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, watermarks->dcn4x.d.uclk_pstate); + } else if (watermarks->dcn4x.d.uclk_pstate < hubbub2->watermarks.dcn4x.d.uclk_pstate) + wm_pending = true; + + /* Section for FCLK_PSTATE_CHANGE_WATERMARKS */ + /* FCLK state A */ + if (safe_to_lower || watermarks->dcn4x.a.fclk_pstate > hubbub2->watermarks.dcn4x.a.fclk_pstate) { + hubbub2->watermarks.dcn4x.a.fclk_pstate = watermarks->dcn4x.a.fclk_pstate; + REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, 0, + DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, watermarks->dcn4x.a.fclk_pstate); + } else if (watermarks->dcn4x.a.fclk_pstate < hubbub2->watermarks.dcn4x.a.fclk_pstate) + wm_pending = true; + + /* FCLK state B */ + if (safe_to_lower || watermarks->dcn4x.b.fclk_pstate > hubbub2->watermarks.dcn4x.b.fclk_pstate) { + hubbub2->watermarks.dcn4x.b.fclk_pstate = watermarks->dcn4x.b.fclk_pstate; + REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, 0, + DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, watermarks->dcn4x.b.fclk_pstate); + } else if (watermarks->dcn4x.b.fclk_pstate < hubbub2->watermarks.dcn4x.b.fclk_pstate) + wm_pending = true; + + /* FCLK state C */ + if (safe_to_lower || watermarks->dcn4x.c.fclk_pstate > hubbub2->watermarks.dcn4x.c.fclk_pstate) { + hubbub2->watermarks.dcn4x.c.fclk_pstate = watermarks->dcn4x.c.fclk_pstate; + REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, 0, + DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, watermarks->dcn4x.c.fclk_pstate); + } else if (watermarks->dcn4x.c.fclk_pstate < hubbub2->watermarks.dcn4x.c.fclk_pstate) + wm_pending = true; + + /* FCLK state D */ + if (safe_to_lower || watermarks->dcn4x.d.fclk_pstate > hubbub2->watermarks.dcn4x.d.fclk_pstate) { + hubbub2->watermarks.dcn4x.d.fclk_pstate = watermarks->dcn4x.d.fclk_pstate; + REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, 0, + DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, watermarks->dcn4x.d.fclk_pstate); + } else if (watermarks->dcn4x.d.fclk_pstate < hubbub2->watermarks.dcn4x.d.fclk_pstate) + wm_pending = true; + + return wm_pending; +} + +static bool hubbub42_program_usr_watermarks( + struct hubbub *hubbub, + union dcn_watermark_set *watermarks, + bool safe_to_lower) +{ + struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); + bool wm_pending = false; + + /* clock state A */ + if (safe_to_lower || watermarks->dcn4x.a.usr > hubbub2->watermarks.dcn4x.a.usr) { + hubbub2->watermarks.dcn4x.a.usr = watermarks->dcn4x.a.usr; + REG_SET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, 0, + DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, watermarks->dcn4x.a.usr); + } else if (watermarks->dcn4x.a.usr < hubbub2->watermarks.dcn4x.a.usr) + wm_pending = true; + + /* clock state B */ + if (safe_to_lower || watermarks->dcn4x.b.usr > hubbub2->watermarks.dcn4x.b.usr) { + hubbub2->watermarks.dcn4x.b.usr = watermarks->dcn4x.b.usr; + REG_SET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, 0, + DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, watermarks->dcn4x.b.usr); + } else if (watermarks->dcn4x.b.usr < hubbub2->watermarks.dcn4x.b.usr) + wm_pending = true; + + /* clock state C */ + if (safe_to_lower || watermarks->dcn4x.c.usr > hubbub2->watermarks.dcn4x.c.usr) { + hubbub2->watermarks.dcn4x.c.usr = watermarks->dcn4x.c.usr; + REG_SET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, 0, + DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, watermarks->dcn4x.c.usr); + } else if (watermarks->dcn4x.c.usr < hubbub2->watermarks.dcn4x.c.usr) + wm_pending = true; + + /* clock state D */ + if (safe_to_lower || watermarks->dcn4x.d.usr > hubbub2->watermarks.dcn4x.d.usr) { + hubbub2->watermarks.dcn4x.d.usr = watermarks->dcn4x.d.usr; + REG_SET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, 0, + DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, watermarks->dcn4x.d.usr); + } else if (watermarks->dcn4x.d.usr < hubbub2->watermarks.dcn4x.d.usr) + wm_pending = true; + + return wm_pending; +} + +static bool hubbub42_program_stutter_z8_watermarks( + struct hubbub *hubbub, + union dcn_watermark_set *watermarks, + bool safe_to_lower) +{ + struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); + bool wm_pending = false; + + /* clock state A */ + if (safe_to_lower || watermarks->dcn4x.a.sr_enter_z8 > hubbub2->watermarks.dcn4x.a.sr_enter_z8) { + hubbub2->watermarks.dcn4x.a.sr_enter_z8 = watermarks->dcn4x.a.sr_enter_z8; + REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, 0, + DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, watermarks->dcn4x.a.sr_enter_z8); + } else if (watermarks->dcn4x.a.sr_enter_z8 < hubbub2->watermarks.dcn4x.a.sr_enter_z8) + wm_pending = true; + + if (safe_to_lower || watermarks->dcn4x.a.sr_exit_z8 > hubbub2->watermarks.dcn4x.a.sr_exit_z8) { + hubbub2->watermarks.dcn4x.a.sr_exit_z8 = watermarks->dcn4x.a.sr_exit_z8; + REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, 0, + DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, watermarks->dcn4x.a.sr_exit_z8); + } else if (watermarks->dcn4x.a.sr_exit_z8 < hubbub2->watermarks.dcn4x.a.sr_exit_z8) + wm_pending = true; + + /* clock state B */ + if (safe_to_lower || watermarks->dcn4x.b.sr_enter_z8 > hubbub2->watermarks.dcn4x.b.sr_enter_z8) { + hubbub2->watermarks.dcn4x.b.sr_enter_z8 = watermarks->dcn4x.b.sr_enter_z8; + REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, 0, + DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, watermarks->dcn4x.b.sr_enter_z8); + } else if (watermarks->dcn4x.b.sr_enter_z8 < hubbub2->watermarks.dcn4x.b.sr_enter_z8) + wm_pending = true; + + if (safe_to_lower || watermarks->dcn4x.b.sr_exit_z8 > hubbub2->watermarks.dcn4x.b.sr_exit_z8) { + hubbub2->watermarks.dcn4x.b.sr_exit_z8 = watermarks->dcn4x.b.sr_exit_z8; + REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, 0, + DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, watermarks->dcn4x.b.sr_exit_z8); + } else if (watermarks->dcn4x.b.sr_exit_z8 < hubbub2->watermarks.dcn4x.b.sr_exit_z8) + wm_pending = true; + + /* clock state C */ + if (safe_to_lower || watermarks->dcn4x.c.sr_enter_z8 > hubbub2->watermarks.dcn4x.c.sr_enter_z8) { + hubbub2->watermarks.dcn4x.c.sr_enter_z8 = watermarks->dcn4x.c.sr_enter_z8; + REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, 0, + DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, watermarks->dcn4x.c.sr_enter_z8); + } else if (watermarks->dcn4x.c.sr_enter_z8 < hubbub2->watermarks.dcn4x.c.sr_enter_z8) + wm_pending = true; + + if (safe_to_lower || watermarks->dcn4x.c.sr_exit_z8 > hubbub2->watermarks.dcn4x.c.sr_exit_z8) { + hubbub2->watermarks.dcn4x.c.sr_exit_z8 = watermarks->dcn4x.c.sr_exit_z8; + REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, 0, + DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, watermarks->dcn4x.c.sr_exit_z8); + } else if (watermarks->dcn4x.c.sr_exit_z8 < hubbub2->watermarks.dcn4x.c.sr_exit_z8) + wm_pending = true; + + /* clock state D */ + if (safe_to_lower || watermarks->dcn4x.d.sr_enter_z8 > hubbub2->watermarks.dcn4x.d.sr_enter_z8) { + hubbub2->watermarks.dcn4x.d.sr_enter_z8 = watermarks->dcn4x.d.sr_enter_z8; + REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, 0, + DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, watermarks->dcn4x.d.sr_enter_z8); + } else if (watermarks->dcn4x.d.sr_enter_z8 < hubbub2->watermarks.dcn4x.d.sr_enter_z8) + wm_pending = true; + + if (safe_to_lower || watermarks->dcn4x.d.sr_exit_z8 > hubbub2->watermarks.dcn4x.d.sr_exit_z8) { + hubbub2->watermarks.dcn4x.d.sr_exit_z8 = watermarks->dcn4x.d.sr_exit_z8; + REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, 0, + DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, watermarks->dcn4x.d.sr_exit_z8); + } else if (watermarks->dcn4x.d.sr_exit_z8 < hubbub2->watermarks.dcn4x.d.sr_exit_z8) + wm_pending = true; + + return wm_pending; +} + +static void hubbub42_allow_self_refresh_control(struct hubbub *hubbub, bool allow) +{ + struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); + + /* + * DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE = 1 means do not allow stutter + * DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE = 0 means allow stutter + */ + + REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL, + DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, 0, + DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, !allow); +} +static void hubbub42_set_sdp_control(struct hubbub *hubbub, bool dc_control) +{ + struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); + + REG_UPDATE(DCHUBBUB_SDPIF_CFG0, + SDPIF_PORT_CONTROL, dc_control); +} + +static bool hubbub42_program_watermarks( + struct hubbub *hubbub, + union dcn_watermark_set *watermarks, + unsigned int refclk_mhz, + bool safe_to_lower) +{ + bool wm_pending = false; + struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); + + if (!safe_to_lower && hubbub->ctx->dc->debug.disable_stutter_for_wm_program) { + /* before raising watermarks, SDP control give to DF, stutter must be disabled */ + wm_pending = true; + hubbub42_set_sdp_control(hubbub, false); + hubbub42_allow_self_refresh_control(hubbub, false); + } + if (hubbub42_program_urgent_watermarks(hubbub, watermarks, safe_to_lower)) + wm_pending = true; + + if (hubbub42_program_stutter_watermarks(hubbub, watermarks, safe_to_lower)) + wm_pending = true; + + if (hubbub42_program_pstate_watermarks(hubbub, watermarks, safe_to_lower)) + wm_pending = true; + + if (hubbub42_program_usr_watermarks(hubbub, watermarks, safe_to_lower)) + wm_pending = true; + + if (hubbub42_program_stutter_z8_watermarks(hubbub, watermarks, safe_to_lower)) + wm_pending = true; + + REG_SET(DCHUBBUB_ARB_SAT_LEVEL, 0, + DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz); + REG_UPDATE_2(DCHUBBUB_ARB_DF_REQ_OUTSTAND, + DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 0xFF, + DCHUBBUB_ARB_MIN_REQ_OUTSTAND_COMMIT_THRESHOLD, 0xA);/*hw delta*/ + REG_UPDATE(DCHUBBUB_ARB_HOSTVM_CNTL, DCHUBBUB_ARB_MAX_QOS_COMMIT_THRESHOLD, 0xF); + + if (safe_to_lower || hubbub->ctx->dc->debug.disable_stutter) + hubbub42_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter); + if (safe_to_lower && hubbub->ctx->dc->debug.disable_stutter_for_wm_program) { + hubbub42_set_sdp_control(hubbub, true); + } + hubbub32_force_usr_retraining_allow(hubbub, hubbub->ctx->dc->debug.force_usr_allow); + + return wm_pending; +} + +static void hubbub42_set_request_limit(struct hubbub *hubbub, int memory_channel_count, int words_per_channel) +{ + (void)memory_channel_count; + (void)words_per_channel; + struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); + uint32_t request_limit = 96; //MAX(12 * memory_channel_count, 96); + + REG_UPDATE(SDPIF_REQUEST_RATE_LIMIT, SDPIF_REQUEST_RATE_LIMIT, request_limit); +} + +static bool dcn42_program_arbiter(struct hubbub *hubbub, struct dml2_display_arb_regs *arb_regs, + bool safe_to_lower) +{ + struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); + + bool wm_pending = false; + uint32_t temp; + + /* request backpressure and outstanding return threshold (unused)*/ + //REG_UPDATE(DCHUBBUB_TIMEOUT_DETECTION_CTRL1, DCHUBBUB_TIMEOUT_REQ_STALL_THRESHOLD, arb_regs->req_stall_threshold); + + /* 401 delta: do not update P-State stall threshold (handled by fw) */ + // REG_UPDATE(DCHUBBUB_TIMEOUT_DETECTION_CTRL2, DCHUBBUB_TIMEOUT_PSTATE_STALL_THRESHOLD, arb_regs->pstate_stall_threshold); + + if (safe_to_lower || arb_regs->allow_sdpif_rate_limit_when_cstate_req > hubbub2->allow_sdpif_rate_limit_when_cstate_req) { + hubbub2->allow_sdpif_rate_limit_when_cstate_req = arb_regs->allow_sdpif_rate_limit_when_cstate_req; + + /* only update the required bits */ + REG_GET(DCHUBBUB_CTRL_STATUS, DCHUBBUB_HW_DEBUG, &temp); + if (hubbub2->allow_sdpif_rate_limit_when_cstate_req) { + temp |= (1 << 5); + } else { + temp &= ~(1 << 5); + } + REG_UPDATE(DCHUBBUB_CTRL_STATUS, DCHUBBUB_HW_DEBUG, temp); + } else { + wm_pending = true; + } + + return wm_pending; +} + +static const struct hubbub_funcs hubbub42_funcs = { + .update_dchub = hubbub2_update_dchub, + .init_dchub_sys_ctx = hubbub31_init_dchub_sys_ctx, + .init_vm_ctx = hubbub2_init_vm_ctx, + .dcc_support_swizzle = hubbub3_dcc_support_swizzle, + .dcc_support_pixel_format = hubbub2_dcc_support_pixel_format, + .get_dcc_compression_cap = hubbub3_get_dcc_compression_cap, + .wm_read_state = hubbub35_wm_read_state, + .get_dchub_ref_freq = hubbub35_get_dchub_ref_freq, + .program_watermarks = hubbub42_program_watermarks, + .allow_self_refresh_control = hubbub42_allow_self_refresh_control, + .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled, + .force_wm_propagate_to_pipes = hubbub32_force_wm_propagate_to_pipes, + .force_pstate_change_control = hubbub3_force_pstate_change_control, + .init_watermarks = hubbub35_init_watermarks, + .init_crb = dcn401_init_crb, + .dchvm_init = dcn35_dchvm_init, + .hubbub_read_state = hubbub2_read_state, + .force_usr_retraining_allow = hubbub32_force_usr_retraining_allow, + .set_request_limit = hubbub42_set_request_limit, + .program_det_segments = dcn401_program_det_segments, + .program_compbuf_segments = dcn401_program_compbuf_segments, + .wait_for_det_update = dcn401_wait_for_det_update, + .program_arbiter = dcn42_program_arbiter, + .hubbub_read_reg_state = hubbub3_read_reg_state +}; + +void hubbub42_construct(struct dcn20_hubbub *hubbub2, + struct dc_context *ctx, + const struct dcn_hubbub_registers *hubbub_regs, + const struct dcn_hubbub_shift *hubbub_shift, + const struct dcn_hubbub_mask *hubbub_mask, + int det_size_kb, + int pixel_chunk_size_kb, + int config_return_buffer_size_kb) +{ + hubbub2->base.ctx = ctx; + hubbub2->base.funcs = &hubbub42_funcs; + hubbub2->regs = hubbub_regs; + hubbub2->shifts = hubbub_shift; + hubbub2->masks = hubbub_mask; + + hubbub2->detile_buf_size = det_size_kb * 1024; + hubbub2->pixel_chunk_size = pixel_chunk_size_kb * 1024; + hubbub2->crb_size_segs = config_return_buffer_size_kb / DCN42_CRB_SEGMENT_SIZE_KB; +} diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.h b/drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.h new file mode 100644 index 000000000000..926ddc156a2b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.h @@ -0,0 +1,268 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2026 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_HUBBUB_DCN42_H__ +#define __DC_HUBBUB_DCN42_H__ + +#include "dcn32/dcn32_hubbub.h" + +#define DCN42_CRB_SIZE_KB 1792 +#define DCN42_DEFAULT_DET_SIZE 320 +#define DCN42_CRB_SEGMENT_SIZE_KB 64 + +#define HUBBUB_REG_LIST_DCN42(id)\ + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A),\ + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B),\ + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C),\ + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D),\ + SR(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL),\ + SR(DCHUBBUB_ARB_DRAM_STATE_CNTL),\ + SR(DCHUBBUB_ARB_SAT_LEVEL),\ + SR(DCHUBBUB_ARB_DF_REQ_OUTSTAND),\ + SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ + SR(DCHUBBUB_SOFT_RESET),\ + SR(DCHUBBUB_CRC_CTRL), \ + SR(DCN_VM_FB_LOCATION_BASE),\ + SR(DCN_VM_FB_LOCATION_TOP),\ + SR(DCN_VM_FB_OFFSET),\ + SR(DCN_VM_AGP_BOT),\ + SR(DCN_VM_AGP_TOP),\ + SR(DCN_VM_AGP_BASE),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D),\ + SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A),\ + SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B),\ + SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C),\ + SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D),\ + SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A),\ + SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B),\ + SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C),\ + SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D),\ + SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A),\ + SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B),\ + SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C),\ + SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D),\ + SR(DCHUBBUB_DET0_CTRL),\ + SR(DCHUBBUB_DET1_CTRL),\ + SR(DCHUBBUB_DET2_CTRL),\ + SR(DCHUBBUB_DET3_CTRL),\ + SR(DCHUBBUB_COMPBUF_CTRL),\ + SR(COMPBUF_RESERVED_SPACE),\ + SR(DCHUBBUB_DEBUG_CTRL_0),\ + SR(DCHUBBUB_ARB_USR_RETRAINING_CNTL),\ + SR(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A),\ + SR(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B),\ + SR(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C),\ + SR(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D),\ + SR(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A),\ + SR(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B),\ + SR(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C),\ + SR(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D),\ + SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A),\ + SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B),\ + SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C),\ + SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D),\ + SR(DCN_VM_FAULT_ADDR_MSB),\ + SR(DCN_VM_FAULT_ADDR_LSB),\ + SR(DCN_VM_FAULT_CNTL),\ + SR(DCN_VM_FAULT_STATUS),\ + SR(SDPIF_REQUEST_RATE_LIMIT),\ + SR(DCHUBBUB_CLOCK_CNTL),\ + SR(DCHUBBUB_SDPIF_CFG0),\ + SR(DCHUBBUB_SDPIF_CFG1),\ + SR(DCHUBBUB_MEM_PWR_MODE_CTRL),\ + SR(DCHUBBUB_ARB_HOSTVM_CNTL),\ + SR(DCHVM_CTRL0),\ + SR(DCHVM_MEM_CTRL),\ + SR(DCHVM_CLK_CTRL),\ + SR(DCHVM_RIOMMU_CTRL0),\ + SR(DCHVM_RIOMMU_STAT0),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D),\ + SR(DCHUBBUB_ARB_QOS_FORCE) + +#define HUBBUB_MASK_SH_LIST_DCN4_2(mask_sh)\ + HUBBUB_MASK_SH_LIST_DCN32(mask_sh), \ + HUBBUB_SF(DCHVM_CTRL0, HOSTVM_INIT_REQ, mask_sh),\ + HUBBUB_SF(DCHVM_MEM_CTRL, HVM_GPUVMRET_PWR_REQ_DIS, mask_sh),\ + HUBBUB_SF(DCHVM_MEM_CTRL, HVM_GPUVMRET_FORCE_REQ, mask_sh),\ + HUBBUB_SF(DCHVM_MEM_CTRL, HVM_GPUVMRET_POWER_STATUS, mask_sh),\ + HUBBUB_SF(DCHVM_CLK_CTRL, HVM_DISPCLK_R_GATE_DIS, mask_sh),\ + HUBBUB_SF(DCHVM_CLK_CTRL, HVM_DISPCLK_G_GATE_DIS, mask_sh),\ + HUBBUB_SF(DCHVM_CLK_CTRL, HVM_DCFCLK_R_GATE_DIS, mask_sh),\ + HUBBUB_SF(DCHVM_CLK_CTRL, HVM_DCFCLK_G_GATE_DIS, mask_sh),\ + HUBBUB_SF(DCHVM_CLK_CTRL, TR_REQ_REQCLKREQ_MODE, mask_sh),\ + HUBBUB_SF(DCHVM_CLK_CTRL, TW_RSP_COMPCLKREQ_MODE, mask_sh),\ + HUBBUB_SF(DCHVM_RIOMMU_CTRL0, HOSTVM_PREFETCH_REQ, mask_sh),\ + HUBBUB_SF(DCHVM_RIOMMU_CTRL0, HOSTVM_POWERSTATUS, mask_sh),\ + HUBBUB_SF(DCHVM_RIOMMU_STAT0, RIOMMU_ACTIVE, mask_sh),\ + HUBBUB_SF(DCHVM_RIOMMU_STAT0, HOSTVM_PREFETCH_DONE, mask_sh),\ + HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE, mask_sh),\ + HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE_CURRENT, mask_sh),\ + HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, CONFIG_ERROR, mask_sh),\ + HUBBUB_SF(COMPBUF_RESERVED_SPACE, COMPBUF_RESERVED_SPACE_64B, mask_sh),\ + HUBBUB_SF(COMPBUF_RESERVED_SPACE, COMPBUF_RESERVED_SPACE_ZS, mask_sh),\ + HUBBUB_SF(DCHUBBUB_CLOCK_CNTL, DCHUBBUB_FGCG_REP_DIS, mask_sh),\ + HUBBUB_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MAX_REQ_OUTSTAND, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_CSTATE_DEEPSLEEP_LEGACY_MODE, mask_sh), \ + HUBBUB_SF(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, mask_sh), \ + HUBBUB_SF(DCHUBBUB_SOFT_RESET, DCHUBBUB_GLOBAL_SOFT_RESET, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_DCFCLK_DEEP_SLEEP_FORCE_VALUE, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_DCFCLK_DEEP_SLEEP_FORCE_ENABLE, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_HOSTVM_CNTL, DCHUBBUB_ARB_MAX_QOS_COMMIT_THRESHOLD, mask_sh),\ + HUBBUB_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND_COMMIT_THRESHOLD, mask_sh),\ + HUBBUB_SF(DCHUBBUB_ARB_SAT_LEVEL, DCHUBBUB_ARB_SAT_LEVEL, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MAX_REQ_OUTSTAND, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, mask_sh), \ + HUBBUB_SF(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, mask_sh), \ + HUBBUB_SF(DCN_VM_FB_LOCATION_BASE, FB_BASE, mask_sh), \ + HUBBUB_SF(DCN_VM_FB_LOCATION_TOP, FB_TOP, mask_sh), \ + HUBBUB_SF(DCN_VM_FB_OFFSET, FB_OFFSET, mask_sh), \ + HUBBUB_SF(DCN_VM_AGP_BOT, AGP_BOT, mask_sh), \ + HUBBUB_SF(DCN_VM_AGP_TOP, AGP_TOP, mask_sh), \ + HUBBUB_SF(DCN_VM_AGP_BASE, AGP_BASE, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, mask_sh), \ + HUBBUB_SF(DCHUBBUB_DEBUG_CTRL_0, DET_DEPTH, mask_sh),\ + HUBBUB_SF(DCHUBBUB_DET0_CTRL, DET0_SIZE, mask_sh),\ + HUBBUB_SF(DCHUBBUB_DET0_CTRL, DET0_SIZE_CURRENT, mask_sh),\ + HUBBUB_SF(DCHUBBUB_DET1_CTRL, DET1_SIZE, mask_sh),\ + HUBBUB_SF(DCHUBBUB_DET1_CTRL, DET1_SIZE_CURRENT, mask_sh),\ + HUBBUB_SF(DCHUBBUB_DET2_CTRL, DET2_SIZE, mask_sh),\ + HUBBUB_SF(DCHUBBUB_DET2_CTRL, DET2_SIZE_CURRENT, mask_sh),\ + HUBBUB_SF(DCHUBBUB_DET3_CTRL, DET3_SIZE, mask_sh),\ + HUBBUB_SF(DCHUBBUB_DET3_CTRL, DET3_SIZE_CURRENT, mask_sh),\ + HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE, mask_sh),\ + HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE_CURRENT, mask_sh),\ + HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, CONFIG_ERROR, mask_sh),\ + HUBBUB_SF(COMPBUF_RESERVED_SPACE, COMPBUF_RESERVED_SPACE_64B, mask_sh),\ + HUBBUB_SF(DCHUBBUB_ARB_USR_RETRAINING_CNTL, DCHUBBUB_ARB_ALLOW_USR_RETRAINING_FORCE_VALUE, mask_sh),\ + HUBBUB_SF(DCHUBBUB_ARB_USR_RETRAINING_CNTL, DCHUBBUB_ARB_ALLOW_USR_RETRAINING_FORCE_ENABLE, mask_sh),\ + HUBBUB_SF(DCHUBBUB_ARB_USR_RETRAINING_CNTL, DCHUBBUB_ARB_DO_NOT_FORCE_ALLOW_USR_RETRAINING_DURING_PSTATE_CHANGE_REQUEST, mask_sh),\ + HUBBUB_SF(DCHUBBUB_ARB_USR_RETRAINING_CNTL, DCHUBBUB_ARB_DO_NOT_FORCE_ALLOW_USR_RETRAINING_DURING_PRE_CSTATE, mask_sh),\ + HUBBUB_SF(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, mask_sh),\ + HUBBUB_SF(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, mask_sh),\ + HUBBUB_SF(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, mask_sh),\ + HUBBUB_SF(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, mask_sh),\ + HUBBUB_SF(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, mask_sh),\ + HUBBUB_SF(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, mask_sh),\ + HUBBUB_SF(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, mask_sh),\ + HUBBUB_SF(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, mask_sh),\ + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, mask_sh), \ + HUBBUB_SF(DCN_VM_FAULT_ADDR_MSB, DCN_VM_FAULT_ADDR_MSB, mask_sh), \ + HUBBUB_SF(DCN_VM_FAULT_ADDR_LSB, DCN_VM_FAULT_ADDR_LSB, mask_sh), \ + HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_STATUS_CLEAR, mask_sh), \ + HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_STATUS_MODE, mask_sh), \ + HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_INTERRUPT_ENABLE, mask_sh), \ + HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_RANGE_FAULT_DISABLE, mask_sh), \ + HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_PRQ_FAULT_DISABLE, mask_sh), \ + HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_STATUS, mask_sh), \ + HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_VMID, mask_sh), \ + HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_TABLE_LEVEL, mask_sh), \ + HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_PIPE, mask_sh), \ + HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_INTERRUPT_STATUS, mask_sh),\ + HUBBUB_SF(SDPIF_REQUEST_RATE_LIMIT, SDPIF_REQUEST_RATE_LIMIT, mask_sh),\ + HUBBUB_SF(DCHUBBUB_CLOCK_CNTL, DISPCLK_R_DCHUBBUB_GATE_DIS, mask_sh),\ + HUBBUB_SF(DCHUBBUB_CLOCK_CNTL, DCFCLK_R_DCHUBBUB_GATE_DIS, mask_sh),\ + HUBBUB_SF(DCHUBBUB_SDPIF_CFG0, SDPIF_PORT_CONTROL, mask_sh),\ + HUBBUB_SF(DCHUBBUB_SDPIF_CFG1, SDPIF_MAX_NUM_OUTSTANDING, mask_sh),\ + HUBBUB_SF(DCHUBBUB_MEM_PWR_MODE_CTRL, DET_MEM_PWR_LS_MODE, mask_sh),\ + HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL1, DCHUBBUB_TIMEOUT_ERROR_STATUS, mask_sh),\ + HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL1, DCHUBBUB_TIMEOUT_REQ_STALL_THRESHOLD, mask_sh),\ + HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL2, DCHUBBUB_TIMEOUT_PSTATE_STALL_THRESHOLD, mask_sh),\ + HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL2, DCHUBBUB_TIMEOUT_DETECTION_EN, mask_sh),\ + HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL2, DCHUBBUB_TIMEOUT_TIMER_RESET, mask_sh),\ + HUBBUB_SF(DCHUBBUB_CTRL_STATUS, ROB_OVERFLOW_STATUS, mask_sh),\ + HUBBUB_SF(DCHUBBUB_CTRL_STATUS, ROB_OVERFLOW_CLEAR, mask_sh),\ + HUBBUB_SF(DCHUBBUB_CTRL_STATUS, DCHUBBUB_HW_DEBUG, mask_sh),\ + HUBBUB_SF(DCHUBBUB_CTRL_STATUS, URGENT_ZERO_SIZE_REQ_EN, mask_sh),\ + HUBBUB_SF(DCHUBBUB_CTRL_STATUS, CSTATE_SWATH_CHK_GOOD_MODE, mask_sh) + +void hubbub42_construct(struct dcn20_hubbub *hubbub2, + struct dc_context *ctx, + const struct dcn_hubbub_registers *hubbub_regs, + const struct dcn_hubbub_shift *hubbub_shift, + const struct dcn_hubbub_mask *hubbub_mask, + int det_size_kb, + int pixel_chunk_size_kb, + int config_return_buffer_size_kb); +#endif diff --git a/drivers/gpu/drm/amd/display/dc/hubp/Makefile b/drivers/gpu/drm/amd/display/dc/hubp/Makefile index a2d1128de7a1..e0799bb873e6 100644 --- a/drivers/gpu/drm/amd/display/dc/hubp/Makefile +++ b/drivers/gpu/drm/amd/display/dc/hubp/Makefile @@ -1,5 +1,5 @@ -# Copyright 2022 Advanced Micro Devices, Inc. +# Copyright 2022-2026 Advanced Micro Devices, Inc. # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), @@ -94,4 +94,12 @@ AMD_DAL_HUBP_DCN401 = $(addprefix $(AMDDALPATH)/dc/hubp/dcn401/,$(HUBP_DCN401)) AMD_DISPLAY_FILES += $(AMD_DAL_HUBP_DCN401) +############################################################################### + +HUBP_DCN42 = dcn42_hubp.o + +AMD_DAL_HUBP_DCN42 = $(addprefix $(AMDDALPATH)/dc/hubp/dcn42/,$(HUBP_DCN42)) + +AMD_DISPLAY_FILES += $(AMD_DAL_HUBP_DCN42) + endif diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn10/dcn10_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn10/dcn10_hubp.c index 6378e3fd7249..7c97a774141f 100644 --- a/drivers/gpu/drm/amd/display/dc/hubp/dcn10/dcn10_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn10/dcn10_hubp.c @@ -143,6 +143,7 @@ void hubp1_program_tiling( const struct dc_tiling_info *info, const enum surface_pixel_format pixel_format) { + (void)pixel_format; struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); REG_UPDATE_6(DCSURF_ADDR_CONFIG, @@ -563,6 +564,7 @@ void hubp1_program_surface_config( bool horizontal_mirror, unsigned int compat_level) { + (void)compat_level; hubp1_dcc_control(hubp, dcc->enable, dcc->independent_64b_blks); hubp1_program_tiling(hubp, tiling_info, format); hubp1_program_size(hubp, format, plane_size, dcc); diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.c index 92288de4cc10..ceee5165fd6a 100644 --- a/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.c @@ -313,6 +313,7 @@ static void hubp2_program_tiling( const struct dc_tiling_info *info, const enum surface_pixel_format pixel_format) { + (void)pixel_format; REG_UPDATE_3(DCSURF_ADDR_CONFIG, NUM_PIPES, log_2(info->gfx9.num_pipes), PIPE_INTERLEAVE, info->gfx9.pipe_interleave, @@ -557,6 +558,7 @@ void hubp2_program_surface_config( bool horizontal_mirror, unsigned int compat_level) { + (void)compat_level; struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); hubp2_dcc_control(hubp, dcc->enable, dcc->independent_64b_blks); diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.h b/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.h index 7062e6653062..80be394a8852 100644 --- a/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.h +++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.h @@ -1,5 +1,5 @@ /* - * Copyright 2012-17 Advanced Micro Devices, Inc. + * Copyright 2012-2026 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -288,16 +288,22 @@ type MCACHEID_MALL_PREF_2H_P1;\ type HUBP_FGCG_REP_DIS +#define DCN42_HUBP_REG_FIELD_VARIABLE_LIST(type) \ + type HUBP_3DLUT_CROSSBAR_SEL_G;\ + type HUBP_3DLUT_CROSSBAR_SEL_B;\ + type HUBP_3DLUT_CROSSBAR_SEL_R struct dcn_hubp2_registers { DCN401_HUBP_REG_COMMON_VARIABLE_LIST; }; struct dcn_hubp2_shift { DCN401_HUBP_REG_FIELD_VARIABLE_LIST(uint8_t); + DCN42_HUBP_REG_FIELD_VARIABLE_LIST(uint8_t); }; struct dcn_hubp2_mask { DCN401_HUBP_REG_FIELD_VARIABLE_LIST(uint32_t); + DCN42_HUBP_REG_FIELD_VARIABLE_LIST(uint32_t); }; struct dcn20_hubp { diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.c index 0cc6f4558989..e2708e30eb1b 100644 --- a/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.c @@ -321,6 +321,7 @@ void hubp3_program_tiling( const struct dc_tiling_info *info, const enum surface_pixel_format pixel_format) { + (void)pixel_format; REG_UPDATE_4(DCSURF_ADDR_CONFIG, NUM_PIPES, log_2(info->gfx9.num_pipes), PIPE_INTERLEAVE, info->gfx9.pipe_interleave, @@ -418,6 +419,7 @@ void hubp3_program_surface_config( bool horizontal_mirror, unsigned int compat_level) { + (void)compat_level; struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); hubp3_dcc_control_sienna_cichlid(hubp, dcc); diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn35/dcn35_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn35/dcn35_hubp.c index 79c583e258c7..c879f4901c7d 100644 --- a/drivers/gpu/drm/amd/display/dc/hubp/dcn35/dcn35_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn35/dcn35_hubp.c @@ -179,6 +179,7 @@ void hubp35_program_surface_config( bool horizontal_mirror, unsigned int compat_level) { + (void)compat_level; struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); hubp3_dcc_control_sienna_cichlid(hubp, dcc); 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 c205500290ec..5a816442deee 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,33 +72,46 @@ int hubp401_get_3dlut_fl_done(struct hubp *hubp) return ret; } -void hubp401_program_3dlut_fl_addressing_mode(struct hubp *hubp, enum hubp_3dlut_fl_addressing_mode addr_mode) +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) { - struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); - - REG_UPDATE(HUBP_3DLUT_CONTROL, HUBP_3DLUT_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; + } } -void hubp401_program_3dlut_fl_width(struct hubp *hubp, enum hubp_3dlut_fl_width width) +void hubp401_program_3dlut_fl_crossbar(struct hubp *hubp, + const enum dc_cm_lut_pixel_format format) { struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); - REG_UPDATE(HUBP_3DLUT_CONTROL, HUBP_3DLUT_WIDTH, width); -} + 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; -void hubp401_program_3dlut_fl_tmz_protected(struct hubp *hubp, uint8_t protection_bits) -{ - struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); - - REG_UPDATE(HUBP_3DLUT_CONTROL, HUBP_3DLUT_TMZ, protection_bits); -} - -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) -{ - struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); + hubp401_get_3dlut_fl_xbar_map(format, + &bit_slice_y_g, + &bit_slice_cb_b, + &bit_slice_cr_r); REG_UPDATE_3(HUBP_3DLUT_CONTROL, HUBP_3DLUT_CROSSBAR_SELECT_Y_G, bit_slice_y_g, @@ -106,62 +119,122 @@ void hubp401_program_3dlut_fl_crossbar(struct hubp *hubp, HUBP_3DLUT_CROSSBAR_SELECT_CR_R, bit_slice_cr_r); } -void hubp401_update_3dlut_fl_bias_scale(struct hubp *hubp, uint16_t bias, uint16_t scale) +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) { - struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); + 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; + } - REG_UPDATE_2(_3DLUT_FL_BIAS_SCALE, HUBP0_3DLUT_FL_BIAS, bias, HUBP0_3DLUT_FL_SCALE, scale); + return width; } -void hubp401_program_3dlut_fl_mode(struct hubp *hubp, enum hubp_3dlut_fl_mode mode) +static enum hubp_3dlut_fl_format hubp401_get_3dlut_fl_format( + const enum dc_cm_lut_pixel_format dc_format) { - struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); + enum hubp_3dlut_fl_format hubp_format = hubp_3dlut_fl_format_unorm_12msb_bitslice; - REG_UPDATE(_3DLUT_FL_CONFIG, HUBP0_3DLUT_FL_MODE, mode); + 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; + } + + return hubp_format; } -void hubp401_program_3dlut_fl_format(struct hubp *hubp, enum hubp_3dlut_fl_format format) +static enum hubp_3dlut_fl_addressing_mode hubp401_get_3dlut_fl_addr_mode( + const enum dc_cm_lut_swizzle swizzle) { - struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); + 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; + } - REG_UPDATE(_3DLUT_FL_CONFIG, HUBP0_3DLUT_FL_FORMAT, format); + return addr_mode; } -void hubp401_program_3dlut_fl_config( - struct hubp *hubp, - struct hubp_fl_3dlut_config *cfg) +static enum hubp_3dlut_fl_mode hubp401_get_3dlut_fl_mode( + const enum dc_cm_lut_swizzle swizzle) { - struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); + 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; + } - uint32_t mpc_width = {(cfg->width == 17) ? 0 : 1}; - uint32_t width = {cfg->width}; + return mode; +} + +void hubp401_program_3dlut_fl_config(struct hubp *hubp, + const struct dc_3dlut_dma *config) +{ + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); - if (cfg->layout == DC_CM2_GPU_MEM_LAYOUT_1D_PACKED_LINEAR) - width = (cfg->width == 17) ? 4916 : 35940; + 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); REG_UPDATE_2(_3DLUT_FL_CONFIG, - HUBP0_3DLUT_FL_MODE, cfg->mode, - HUBP0_3DLUT_FL_FORMAT, cfg->format); + HUBP0_3DLUT_FL_MODE, mode, + HUBP0_3DLUT_FL_FORMAT, format); REG_UPDATE_2(_3DLUT_FL_BIAS_SCALE, - 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); + 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); } void hubp401_update_mall_sel(struct hubp *hubp, uint32_t mall_sel, bool c_cursor) @@ -584,6 +657,7 @@ void hubp401_program_tiling( const struct dc_tiling_info *info, const enum surface_pixel_format pixel_format) { + (void)pixel_format; /* DCSURF_ADDR_CONFIG still shows up in reg spec, but does not need to be programmed for DCN4x * All 4 fields NUM_PIPES, PIPE_INTERLEAVE, MAX_COMPRESSED_FRAGS and NUM_PKRS are irrelevant. * @@ -598,6 +672,7 @@ void hubp401_program_size( const struct plane_size *plane_size, struct dc_plane_dcc_param *dcc) { + (void)dcc; struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); uint32_t pitch, pitch_c; bool use_pitch_c = false; @@ -636,6 +711,7 @@ void hubp401_program_surface_config( bool horizontal_mirror, unsigned int compat_level) { + (void)compat_level; struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); hubp401_dcc_control(hubp, dcc); @@ -739,9 +815,8 @@ void hubp401_cursor_set_position( int x_pos_viewport = 0; int x_hot_viewport = 0; uint32_t cur_en = pos->enable ? 1 : 0; - + uint32_t x_hotspot_clamped = pos->x_hotspot; hubp->curs_pos = *pos; - /* Recout is zero for pipes if the entire dst_rect is contained * within preceeding ODM slices. */ @@ -772,6 +847,8 @@ void hubp401_cursor_set_position( ASSERT(param->h_scale_ratio.value); + if (x_hotspot_clamped > 0xFF) + x_hotspot_clamped = 0xFF; if (param->h_scale_ratio.value) dst_x_offset = dc_fixpt_floor(dc_fixpt_div( dc_fixpt_from_int(dst_x_offset), @@ -792,7 +869,7 @@ void hubp401_cursor_set_position( CURSOR_Y_POSITION, pos->y); REG_SET_2(CURSOR_HOT_SPOT, 0, - CURSOR_HOT_SPOT_X, pos->x_hotspot, + CURSOR_HOT_SPOT_X, x_hotspot_clamped, CURSOR_HOT_SPOT_Y, pos->y_hotspot); REG_SET(CURSOR_DST_OFFSET, 0, @@ -1058,19 +1135,13 @@ 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 4570b8016de5..043948f64b86 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,32 +328,17 @@ 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, - 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); + const enum dc_cm_lut_pixel_format format); 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_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_program_3dlut_fl_config(struct hubp *hubp, + const struct dc_3dlut_dma *config); 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 new file mode 100644 index 000000000000..ad6badcceb12 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.c @@ -0,0 +1,742 @@ +// SPDX-License-Identifier: MIT +// +// Copyright 2026 Advanced Micro Devices, Inc. + +#include "dcn401/dcn401_hubp.h" +#include "dcn42_hubp.h" +#include "reg_helper.h" + +#define REG(reg) \ + hubp2->hubp_regs->reg + +#define CTX \ + hubp2->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + hubp2->hubp_shift->field_name, hubp2->hubp_mask->field_name + +static void hubp42_set_fgcg(struct hubp *hubp, bool enable) +{ + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); + + REG_UPDATE(HUBP_CLK_CNTL, HUBP_FGCG_REP_DIS, !enable); +} + +static void hubp42_init(struct hubp *hubp) +{ + hubp3_init(hubp); + + hubp42_set_fgcg(hubp, hubp->ctx->dc->debug.enable_fine_grain_clock_gating.bits.dchub); + + /*do nothing for now for dcn3.5 or later*/ +} + +static void hubp42_program_pixel_format( + struct hubp *hubp, + enum surface_pixel_format format) +{ + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); + uint32_t green_bar = 1; + uint32_t red_bar = 3; + uint32_t blue_bar = 2; + + /* swap for ABGR format */ + if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR8888 + || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010 + || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS + || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616 + || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) { + red_bar = 2; + blue_bar = 3; + } + + REG_UPDATE_3(HUBPRET_CONTROL, + CROSSBAR_SRC_Y_G, green_bar, + CROSSBAR_SRC_CB_B, blue_bar, + CROSSBAR_SRC_CR_R, red_bar); + + /* Mapping is same as ipp programming (cnvc) */ + + switch (format) { + case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 1); + break; + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 3); + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 8); + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 10); + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616: /* we use crossbar already */ + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 26); /* ARGB16161616_UNORM */ + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:/*we use crossbar already*/ + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 24); + break; + + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 65); + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 64); + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 67); + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 66); + break; + case SURFACE_PIXEL_FORMAT_VIDEO_AYCrCb8888: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 12); + break; + case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FIX: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 112); + break; + case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FIX: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 113); + break; + case SURFACE_PIXEL_FORMAT_VIDEO_ACrYCb2101010: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 114); + break; + case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FLOAT: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 118); + break; + case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FLOAT: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 119); + break; + case SURFACE_PIXEL_FORMAT_GRPH_RGBE: + REG_UPDATE_2(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 116, + ALPHA_PLANE_EN, 0); + break; + case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA: + REG_UPDATE_2(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 116, + ALPHA_PLANE_EN, 1); + break; + default: + BREAK_TO_DEBUGGER(); + break; + } + + /* don't see the need of program the xbar in DCN 1.0 */ +} + +static void hubp42_program_deadline( + struct hubp *hubp, + struct dml2_display_dlg_regs *dlg_attr, + struct dml2_display_ttu_regs *ttu_attr) +{ + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); + + /* put DLG in mission mode */ + REG_WRITE(HUBPREQ_DEBUG_DB, 0); + + /* DLG - Per hubp */ + REG_SET_2(BLANK_OFFSET_0, 0, + REFCYC_H_BLANK_END, dlg_attr->refcyc_h_blank_end, + DLG_V_BLANK_END, dlg_attr->dlg_vblank_end); + + REG_SET(BLANK_OFFSET_1, 0, + MIN_DST_Y_NEXT_START, dlg_attr->min_dst_y_next_start); + + REG_SET(DST_DIMENSIONS, 0, + REFCYC_PER_HTOTAL, dlg_attr->refcyc_per_htotal); + + REG_SET_2(DST_AFTER_SCALER, 0, + REFCYC_X_AFTER_SCALER, dlg_attr->refcyc_x_after_scaler, + DST_Y_AFTER_SCALER, dlg_attr->dst_y_after_scaler); + + REG_SET(REF_FREQ_TO_PIX_FREQ, 0, + REF_FREQ_TO_PIX_FREQ, dlg_attr->ref_freq_to_pix_freq); + + /* DLG - Per luma/chroma */ + REG_SET(VBLANK_PARAMETERS_1, 0, + REFCYC_PER_PTE_GROUP_VBLANK_L, dlg_attr->refcyc_per_pte_group_vblank_l); + + if (REG(NOM_PARAMETERS_0)) + REG_SET(NOM_PARAMETERS_0, 0, + DST_Y_PER_PTE_ROW_NOM_L, dlg_attr->dst_y_per_pte_row_nom_l); + + if (REG(NOM_PARAMETERS_1)) + REG_SET(NOM_PARAMETERS_1, 0, + REFCYC_PER_PTE_GROUP_NOM_L, dlg_attr->refcyc_per_pte_group_nom_l); + + REG_SET(NOM_PARAMETERS_4, 0, + DST_Y_PER_META_ROW_NOM_L, dlg_attr->dst_y_per_meta_row_nom_l); + + REG_SET(NOM_PARAMETERS_5, 0, + REFCYC_PER_META_CHUNK_NOM_L, dlg_attr->refcyc_per_meta_chunk_nom_l); + + REG_SET_2(PER_LINE_DELIVERY, 0, + REFCYC_PER_LINE_DELIVERY_L, dlg_attr->refcyc_per_line_delivery_l, + REFCYC_PER_LINE_DELIVERY_C, dlg_attr->refcyc_per_line_delivery_c); + + REG_SET(VBLANK_PARAMETERS_2, 0, + REFCYC_PER_PTE_GROUP_VBLANK_C, dlg_attr->refcyc_per_pte_group_vblank_c); + + if (REG(NOM_PARAMETERS_2)) + REG_SET(NOM_PARAMETERS_2, 0, + DST_Y_PER_PTE_ROW_NOM_C, dlg_attr->dst_y_per_pte_row_nom_c); + + if (REG(NOM_PARAMETERS_3)) + REG_SET(NOM_PARAMETERS_3, 0, + REFCYC_PER_PTE_GROUP_NOM_C, dlg_attr->refcyc_per_pte_group_nom_c); + + REG_SET(NOM_PARAMETERS_6, 0, + DST_Y_PER_META_ROW_NOM_C, dlg_attr->dst_y_per_meta_row_nom_c); + + REG_SET(NOM_PARAMETERS_7, 0, + REFCYC_PER_META_CHUNK_NOM_C, dlg_attr->refcyc_per_meta_chunk_nom_c); + + /* TTU - per hubp */ + REG_SET_2(DCN_TTU_QOS_WM, 0, + QoS_LEVEL_LOW_WM, ttu_attr->qos_level_low_wm, + QoS_LEVEL_HIGH_WM, ttu_attr->qos_level_high_wm); + + /* TTU - per luma/chroma */ + /* Assumed surf0 is luma and 1 is chroma */ + + REG_SET_3(DCN_SURF0_TTU_CNTL0, 0, + REFCYC_PER_REQ_DELIVERY, ttu_attr->refcyc_per_req_delivery_l, + QoS_LEVEL_FIXED, ttu_attr->qos_level_fixed_l, + QoS_RAMP_DISABLE, ttu_attr->qos_ramp_disable_l); + + REG_SET_3(DCN_SURF1_TTU_CNTL0, 0, + REFCYC_PER_REQ_DELIVERY, ttu_attr->refcyc_per_req_delivery_c, + QoS_LEVEL_FIXED, ttu_attr->qos_level_fixed_c, + QoS_RAMP_DISABLE, ttu_attr->qos_ramp_disable_c); + + REG_SET_3(DCN_CUR0_TTU_CNTL0, 0, + REFCYC_PER_REQ_DELIVERY, ttu_attr->refcyc_per_req_delivery_cur0, + QoS_LEVEL_FIXED, ttu_attr->qos_level_fixed_cur0, + QoS_RAMP_DISABLE, ttu_attr->qos_ramp_disable_cur0); + + REG_SET(FLIP_PARAMETERS_1, 0, + REFCYC_PER_PTE_GROUP_FLIP_L, dlg_attr->refcyc_per_pte_group_flip_l); + REG_SET(HUBP_3DLUT_DLG_PARAM, 0, REFCYC_PER_3DLUT_GROUP, dlg_attr->refcyc_per_tdlut_group); + + REG_UPDATE(DCN_DMDATA_VM_CNTL, + REFCYC_PER_VM_DMDATA, dlg_attr->refcyc_per_vm_dmdata); +} + +void hubp42_program_requestor( + struct hubp *hubp, + struct dml2_display_rq_regs *rq_regs) +{ + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); + + REG_UPDATE(HUBPRET_CONTROL, + DET_BUF_PLANE1_BASE_ADDRESS, rq_regs->plane1_base_address); + REG_SET_4(DCN_EXPANSION_MODE, 0, + DRQ_EXPANSION_MODE, rq_regs->drq_expansion_mode, + PRQ_EXPANSION_MODE, rq_regs->prq_expansion_mode, + MRQ_EXPANSION_MODE, rq_regs->mrq_expansion_mode, + CRQ_EXPANSION_MODE, rq_regs->crq_expansion_mode); + REG_SET_8(DCHUBP_REQ_SIZE_CONFIG, 0, + CHUNK_SIZE, rq_regs->rq_regs_l.chunk_size, + MIN_CHUNK_SIZE, rq_regs->rq_regs_l.min_chunk_size, + META_CHUNK_SIZE, rq_regs->rq_regs_l.meta_chunk_size, + MIN_META_CHUNK_SIZE, rq_regs->rq_regs_l.min_meta_chunk_size, + DPTE_GROUP_SIZE, rq_regs->rq_regs_l.dpte_group_size, + VM_GROUP_SIZE, rq_regs->rq_regs_l.mpte_group_size, + SWATH_HEIGHT, rq_regs->rq_regs_l.swath_height, + PTE_ROW_HEIGHT_LINEAR, rq_regs->rq_regs_l.pte_row_height_linear); + REG_SET_7(DCHUBP_REQ_SIZE_CONFIG_C, 0, + CHUNK_SIZE_C, rq_regs->rq_regs_c.chunk_size, + MIN_CHUNK_SIZE_C, rq_regs->rq_regs_c.min_chunk_size, + META_CHUNK_SIZE_C, rq_regs->rq_regs_c.meta_chunk_size, + MIN_META_CHUNK_SIZE_C, rq_regs->rq_regs_c.min_meta_chunk_size, + DPTE_GROUP_SIZE_C, rq_regs->rq_regs_c.dpte_group_size, + SWATH_HEIGHT_C, rq_regs->rq_regs_c.swath_height, + PTE_ROW_HEIGHT_LINEAR_C, rq_regs->rq_regs_c.pte_row_height_linear); +} + + +void hubp42_setup( + struct hubp *hubp, + struct dml2_dchub_per_pipe_register_set *pipe_regs, + union dml2_global_sync_programming *pipe_global_sync, + struct dc_crtc_timing *timing) +{ + /* otg is locked when this func is called. Register are double buffered. + * disable the requestors is not needed + */ + hubp401_vready_at_or_After_vsync(hubp, pipe_global_sync, timing); + hubp42_program_requestor(hubp, &pipe_regs->rq_regs); + hubp42_program_deadline(hubp, &pipe_regs->dlg_regs, &pipe_regs->ttu_regs); +} +static void hubp42_program_surface_config( + struct hubp *hubp, + enum surface_pixel_format format, + struct dc_tiling_info *tiling_info, + struct plane_size *plane_size, + enum dc_rotation_angle rotation, + struct dc_plane_dcc_param *dcc, + bool horizontal_mirror, + unsigned int compat_level) +{ + (void)compat_level; + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); + + hubp3_dcc_control_sienna_cichlid(hubp, dcc); + hubp3_program_tiling(hubp2, tiling_info, format); + hubp2_program_size(hubp, format, plane_size, dcc); + hubp2_program_rotation(hubp, rotation, horizontal_mirror); + 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) +{ + 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, + bool flip_immediate) +{ + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); + + //program flip type + REG_UPDATE(DCSURF_FLIP_CONTROL, + SURFACE_FLIP_TYPE, flip_immediate); + + // Program VMID reg + if (flip_immediate == 0) + REG_UPDATE(VMID_SETTINGS_0, + VMID, address->vmid); + + if (address->type == PLN_ADDR_TYPE_GRPH_STEREO) { + REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_MODE_FOR_STEREOSYNC, 0); + REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_IN_STEREOSYNC, 0x1); + + } else { + // turn off stereo if not in stereo + REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_MODE_FOR_STEREOSYNC, 0x0); + REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_IN_STEREOSYNC, 0x0); + } + + /* HW automatically latch rest of address register on write to + * DCSURF_PRIMARY_SURFACE_ADDRESS if SURFACE_UPDATE_LOCK is not used + * + * program high first and then the low addr, order matters! + */ + switch (address->type) { + case PLN_ADDR_TYPE_GRAPHICS: + /* DCN1.0 does not support const color + * TODO: program DCHUBBUB_RET_PATH_DCC_CFGx_0/1 + * base on address->grph.dcc_const_color + * x = 0, 2, 4, 6 for pipe 0, 1, 2, 3 for rgb and luma + * x = 1, 3, 5, 7 for pipe 0, 1, 2, 3 for chroma + */ + + if (address->grph.addr.quad_part == 0) + break; + + REG_UPDATE_2(DCSURF_SURFACE_CONTROL, + PRIMARY_SURFACE_TMZ, address->tmz_surface, + PRIMARY_META_SURFACE_TMZ, address->tmz_surface); + + if (address->grph.meta_addr.quad_part != 0) { + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, + PRIMARY_META_SURFACE_ADDRESS_HIGH, + address->grph.meta_addr.high_part); + + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, + PRIMARY_META_SURFACE_ADDRESS, + address->grph.meta_addr.low_part); + } + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, + PRIMARY_SURFACE_ADDRESS_HIGH, + address->grph.addr.high_part); + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, + PRIMARY_SURFACE_ADDRESS, + address->grph.addr.low_part); + break; + case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE: + if (address->video_progressive.luma_addr.quad_part == 0 + || address->video_progressive.chroma_addr.quad_part == 0) + break; + + REG_UPDATE_4(DCSURF_SURFACE_CONTROL, + PRIMARY_SURFACE_TMZ, address->tmz_surface, + PRIMARY_SURFACE_TMZ_C, address->tmz_surface, + PRIMARY_META_SURFACE_TMZ, address->tmz_surface, + PRIMARY_META_SURFACE_TMZ_C, address->tmz_surface); + + if (address->video_progressive.luma_meta_addr.quad_part != 0) { + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, 0, + PRIMARY_META_SURFACE_ADDRESS_HIGH_C, + address->video_progressive.chroma_meta_addr.high_part); + + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, 0, + PRIMARY_META_SURFACE_ADDRESS_C, + address->video_progressive.chroma_meta_addr.low_part); + + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, + PRIMARY_META_SURFACE_ADDRESS_HIGH, + address->video_progressive.luma_meta_addr.high_part); + + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, + PRIMARY_META_SURFACE_ADDRESS, + address->video_progressive.luma_meta_addr.low_part); + } + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, 0, + PRIMARY_SURFACE_ADDRESS_HIGH_C, + address->video_progressive.chroma_addr.high_part); + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_C, 0, + PRIMARY_SURFACE_ADDRESS_C, + address->video_progressive.chroma_addr.low_part); + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, + PRIMARY_SURFACE_ADDRESS_HIGH, + address->video_progressive.luma_addr.high_part); + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, + PRIMARY_SURFACE_ADDRESS, + address->video_progressive.luma_addr.low_part); + break; + case PLN_ADDR_TYPE_GRPH_STEREO: + if (address->grph_stereo.left_addr.quad_part == 0) + break; + if (address->grph_stereo.right_addr.quad_part == 0) + break; + + REG_UPDATE_8(DCSURF_SURFACE_CONTROL, + PRIMARY_SURFACE_TMZ, address->tmz_surface, + PRIMARY_SURFACE_TMZ_C, address->tmz_surface, + PRIMARY_META_SURFACE_TMZ, address->tmz_surface, + PRIMARY_META_SURFACE_TMZ_C, address->tmz_surface, + SECONDARY_SURFACE_TMZ, address->tmz_surface, + SECONDARY_SURFACE_TMZ_C, address->tmz_surface, + SECONDARY_META_SURFACE_TMZ, address->tmz_surface, + SECONDARY_META_SURFACE_TMZ_C, address->tmz_surface); + + if (address->grph_stereo.right_meta_addr.quad_part != 0) { + + REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH_C, 0, + SECONDARY_META_SURFACE_ADDRESS_HIGH_C, + address->grph_stereo.right_alpha_meta_addr.high_part); + + REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS_C, 0, + SECONDARY_META_SURFACE_ADDRESS_C, + address->grph_stereo.right_alpha_meta_addr.low_part); + + REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, 0, + SECONDARY_META_SURFACE_ADDRESS_HIGH, + address->grph_stereo.right_meta_addr.high_part); + + REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS, 0, + SECONDARY_META_SURFACE_ADDRESS, + address->grph_stereo.right_meta_addr.low_part); + } + if (address->grph_stereo.left_meta_addr.quad_part != 0) { + + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, 0, + PRIMARY_META_SURFACE_ADDRESS_HIGH_C, + address->grph_stereo.left_alpha_meta_addr.high_part); + + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, 0, + PRIMARY_META_SURFACE_ADDRESS_C, + address->grph_stereo.left_alpha_meta_addr.low_part); + + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, + PRIMARY_META_SURFACE_ADDRESS_HIGH, + address->grph_stereo.left_meta_addr.high_part); + + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, + PRIMARY_META_SURFACE_ADDRESS, + address->grph_stereo.left_meta_addr.low_part); + } + + REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH_C, 0, + SECONDARY_SURFACE_ADDRESS_HIGH_C, + address->grph_stereo.right_alpha_addr.high_part); + + REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS_C, 0, + SECONDARY_SURFACE_ADDRESS_C, + address->grph_stereo.right_alpha_addr.low_part); + + REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, 0, + SECONDARY_SURFACE_ADDRESS_HIGH, + address->grph_stereo.right_addr.high_part); + + REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS, 0, + SECONDARY_SURFACE_ADDRESS, + address->grph_stereo.right_addr.low_part); + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, 0, + PRIMARY_SURFACE_ADDRESS_HIGH_C, + address->grph_stereo.left_alpha_addr.high_part); + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_C, 0, + PRIMARY_SURFACE_ADDRESS_C, + address->grph_stereo.left_alpha_addr.low_part); + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, + PRIMARY_SURFACE_ADDRESS_HIGH, + address->grph_stereo.left_addr.high_part); + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, + PRIMARY_SURFACE_ADDRESS, + address->grph_stereo.left_addr.low_part); + break; + case PLN_ADDR_TYPE_RGBEA: + if (address->rgbea.addr.quad_part == 0 + || address->rgbea.alpha_addr.quad_part == 0) + break; + + REG_UPDATE_4(DCSURF_SURFACE_CONTROL, + PRIMARY_SURFACE_TMZ, address->tmz_surface, + PRIMARY_SURFACE_TMZ_C, address->tmz_surface, + PRIMARY_META_SURFACE_TMZ, address->tmz_surface, + PRIMARY_META_SURFACE_TMZ_C, address->tmz_surface); + + if (address->rgbea.meta_addr.quad_part != 0) { + + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, 0, + PRIMARY_META_SURFACE_ADDRESS_HIGH_C, + address->rgbea.alpha_meta_addr.high_part); + + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, 0, + PRIMARY_META_SURFACE_ADDRESS_C, + address->rgbea.alpha_meta_addr.low_part); + + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, + PRIMARY_META_SURFACE_ADDRESS_HIGH, + address->rgbea.meta_addr.high_part); + + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, + PRIMARY_META_SURFACE_ADDRESS, + address->rgbea.meta_addr.low_part); + } + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, 0, + PRIMARY_SURFACE_ADDRESS_HIGH_C, + address->rgbea.alpha_addr.high_part); + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_C, 0, + PRIMARY_SURFACE_ADDRESS_C, + address->rgbea.alpha_addr.low_part); + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, + PRIMARY_SURFACE_ADDRESS_HIGH, + address->rgbea.addr.high_part); + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, + PRIMARY_SURFACE_ADDRESS, + address->rgbea.addr.low_part); + break; + default: + BREAK_TO_DEBUGGER(); + break; + } + + hubp->request_address = *address; + + return true; +} + +struct hubp_funcs dcn42_hubp_funcs = { + .hubp_enable_tripleBuffer = hubp2_enable_triplebuffer, + .hubp_is_triplebuffer_enabled = hubp2_is_triplebuffer_enabled, + .hubp_program_surface_flip_and_addr = hubp42_program_surface_flip_and_addr, + .hubp_program_surface_config = hubp42_program_surface_config, + .hubp_is_flip_pending = hubp2_is_flip_pending, + .hubp_setup2 = hubp42_setup, + .hubp_setup_interdependent2 = hubp401_setup_interdependent, + .hubp_set_vm_system_aperture_settings = hubp3_set_vm_system_aperture_settings, + .set_blank = hubp2_set_blank, + .set_blank_regs = hubp2_set_blank_regs, + .dcc_control = hubp3_dcc_control, + .hubp_reset = hubp_reset, + .mem_program_viewport = min_set_viewport, + .set_cursor_attributes = hubp32_cursor_set_attributes, + .set_cursor_position = hubp401_cursor_set_position, + .hubp_clk_cntl = hubp2_clk_cntl, + .hubp_vtg_sel = hubp2_vtg_sel, + .dmdata_set_attributes = hubp3_dmdata_set_attributes, + .dmdata_load = hubp2_dmdata_load, + .dmdata_status_done = hubp2_dmdata_status_done, + .hubp_read_state = hubp42_read_state, + .hubp_clear_underflow = hubp2_clear_underflow, + .hubp_set_flip_control_surface_gsl = hubp2_set_flip_control_surface_gsl, + .hubp_init = hubp42_init, + .set_unbounded_requesting = hubp31_set_unbounded_requesting, + .hubp_soft_reset = hubp31_soft_reset, + .hubp_set_flip_int = hubp1_set_flip_int, + .hubp_in_blank = hubp1_in_blank, + .program_extended_blank = hubp31_program_extended_blank_value, + .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_crossbar = hubp42_program_3dlut_fl_crossbar, + .hubp_get_3dlut_fl_done = hubp401_get_3dlut_fl_done, + .hubp_clear_tiling = hubp3_clear_tiling, + .hubp_program_3dlut_fl_config = hubp401_program_3dlut_fl_config, + .hubp_read_reg_state = hubp3_read_reg_state +}; + +bool hubp42_construct( + struct dcn20_hubp *hubp2, + struct dc_context *ctx, + uint32_t inst, + const struct dcn_hubp2_registers *hubp_regs, + const struct dcn_hubp2_shift *hubp_shift, + const struct dcn_hubp2_mask *hubp_mask) +{ + hubp2->base.funcs = &dcn42_hubp_funcs; + hubp2->base.ctx = ctx; + hubp2->hubp_regs = hubp_regs; + hubp2->hubp_shift = hubp_shift; + hubp2->hubp_mask = hubp_mask; + hubp2->base.inst = inst; + hubp2->base.opp_id = OPP_ID_INVALID; + hubp2->base.mpcc_id = 0xf; + + return true; +} + + +void hubp42_read_state(struct hubp *hubp) +{ + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); + struct dcn_hubp_state *s = &hubp2->state; + struct dcn_fl_regs_st *fl_regs = &s->fl_regs; + + hubp401_read_state(hubp); + + /* CONTROL */ + REG_GET_5(HUBP_3DLUT_CONTROL, + HUBP_3DLUT_ENABLE, &fl_regs->lut_enable, + HUBP_3DLUT_DONE, &fl_regs->lut_done, + HUBP_3DLUT_ADDRESSING_MODE, &fl_regs->lut_addr_mode, + HUBP_3DLUT_WIDTH, &fl_regs->lut_width, + HUBP_3DLUT_MPC_WIDTH, &fl_regs->lut_mpc_width); + + REG_GET_4(HUBP_3DLUT_CONTROL, + HUBP_3DLUT_TMZ, &fl_regs->lut_tmz, + HUBP_3DLUT_CROSSBAR_SEL_R, &fl_regs->lut_crossbar_sel_r, + HUBP_3DLUT_CROSSBAR_SEL_G, &fl_regs->lut_crossbar_sel_g, + HUBP_3DLUT_CROSSBAR_SEL_B, &fl_regs->lut_crossbar_sel_b); + + /* ADDR */ + REG_GET(HUBP_3DLUT_ADDRESS_HIGH, + HUBP_3DLUT_ADDRESS_HIGH, &fl_regs->lut_addr_hi); + REG_GET(HUBP_3DLUT_ADDRESS_LOW, + HUBP_3DLUT_ADDRESS_LOW, &fl_regs->lut_addr_lo); + /* CLK */ + REG_GET(HUBP_3DLUT_DLG_PARAM, + REFCYC_PER_3DLUT_GROUP, &fl_regs->refcyc_3dlut_group); + /* FL */ + REG_GET_2(_3DLUT_FL_BIAS_SCALE, + HUBP0_3DLUT_FL_BIAS, &fl_regs->lut_fl_bias, + HUBP0_3DLUT_FL_SCALE, &fl_regs->lut_fl_scale); + REG_GET_2(_3DLUT_FL_CONFIG, + HUBP0_3DLUT_FL_MODE, &fl_regs->lut_fl_mode, + HUBP0_3DLUT_FL_FORMAT, &fl_regs->lut_fl_format); +} 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 new file mode 100644 index 000000000000..88bb1337ab9d --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2026 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_HUBP_DCN42_H__ +#define __DC_HUBP_DCN42_H__ + +#include "dcn35/dcn35_hubp.h" + +#define HUBP_MASK_SH_LIST_DCN42(mask_sh)\ + HUBP_MASK_SH_LIST_DCN35(mask_sh),\ + HUBP_SF(HUBP0_3DLUT_FL_CONFIG, HUBP0_3DLUT_FL_MODE, mask_sh),\ + HUBP_SF(HUBP0_3DLUT_FL_CONFIG, HUBP0_3DLUT_FL_FORMAT, mask_sh),\ + HUBP_SF(HUBP0_3DLUT_FL_BIAS_SCALE, HUBP0_3DLUT_FL_BIAS, mask_sh),\ + HUBP_SF(HUBP0_3DLUT_FL_BIAS_SCALE, HUBP0_3DLUT_FL_SCALE, mask_sh),\ + HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_ENABLE, mask_sh),\ + HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_DONE, mask_sh),\ + HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_ADDRESSING_MODE, mask_sh),\ + HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_WIDTH, mask_sh),\ + HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_MPC_WIDTH, mask_sh),\ + HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_TMZ, mask_sh),\ + HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_CROSSBAR_SEL_B, mask_sh),\ + HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_CROSSBAR_SEL_G, mask_sh),\ + HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_CROSSBAR_SEL_R, mask_sh),\ + HUBP_SF(CURSOR0_0_HUBP_3DLUT_ADDRESS_HIGH, HUBP_3DLUT_ADDRESS_HIGH, mask_sh),\ + HUBP_SF(CURSOR0_0_HUBP_3DLUT_ADDRESS_LOW, HUBP_3DLUT_ADDRESS_LOW, mask_sh),\ + HUBP_SF(CURSOR0_0_HUBP_3DLUT_DLG_PARAM, REFCYC_PER_3DLUT_GROUP, mask_sh) + +struct dml2_display_rq_regs; + +bool hubp42_construct( + struct dcn20_hubp *hubp2, + struct dc_context *ctx, + uint32_t inst, + const struct dcn_hubp2_registers *hubp_regs, + 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_read_state(struct hubp *hubp); + +void hubp42_program_requestor( + struct hubp *hubp, + struct dml2_display_rq_regs *rq_regs); + +void hubp42_setup( + struct hubp *hubp, + struct dml2_dchub_per_pipe_register_set *pipe_regs, + union dml2_global_sync_programming *pipe_global_sync, + struct dc_crtc_timing *timing); + +#endif /* __DC_HUBP_DCN42_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/hwss/Makefile b/drivers/gpu/drm/amd/display/dc/hwss/Makefile index bee617ca0838..08cbbf87a19f 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/Makefile +++ b/drivers/gpu/drm/amd/display/dc/hwss/Makefile @@ -1,5 +1,4 @@ - -# Copyright 2022 Advanced Micro Devices, Inc. +# Copyright 2022-2026 Advanced Micro Devices, Inc. # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), @@ -199,4 +198,13 @@ HWSS_DCN401 = dcn401_hwseq.o dcn401_init.o AMD_DAL_HWSS_DCN401 = $(addprefix $(AMDDALPATH)/dc/hwss/dcn401/,$(HWSS_DCN401)) AMD_DISPLAY_FILES += $(AMD_DAL_HWSS_DCN401) + +############################################################################### + +HWSS_DCN42 = dcn42_hwseq.o dcn42_init.o + +AMD_DAL_HWSS_DCN42 = $(addprefix $(AMDDALPATH)/dc/hwss/dcn42/,$(HWSS_DCN42)) + +AMD_DISPLAY_FILES += $(AMD_DAL_HWSS_DCN42) + endif diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.h index f66a38f43a09..dc8feca578c5 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.h @@ -1,5 +1,5 @@ /* - * Copyright 2016 Advanced Micro Devices, Inc. + * Copyright 2016, 2026 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -700,6 +700,8 @@ struct dce_hwseq_registers { uint32_t DOMAIN23_PG_STATUS; uint32_t DOMAIN24_PG_STATUS; uint32_t DOMAIN25_PG_STATUS; + uint32_t DOMAIN26_PG_CONFIG; + uint32_t DOMAIN26_PG_STATUS; }; /* set field name */ #define HWS_SF(blk_name, reg_name, field_name, post_fix)\ @@ -1245,6 +1247,13 @@ struct dce_hwseq_registers { type DOMAIN25_PGFSM_PWR_STATUS; \ type DOMAIN_DESIRED_PWR_STATE; +#define HWSEQ_DCN42_REG_FIELD_LIST(type) \ + type DPIASYMCLK4_GATE_DISABLE;\ + type DPIASYMCLK5_GATE_DISABLE;\ + type DOMAIN26_POWER_FORCEON; \ + type DOMAIN26_POWER_GATE; \ + type DOMAIN26_PGFSM_PWR_STATUS; + struct dce_hwseq_shift { HWSEQ_REG_FIELD_LIST(uint8_t) HWSEQ_DCN_REG_FIELD_LIST(uint8_t) @@ -1253,6 +1262,7 @@ struct dce_hwseq_shift { HWSEQ_DCN31_REG_FIELD_LIST(uint8_t) HWSEQ_DCN35_REG_FIELD_LIST(uint8_t) HWSEQ_DCN401_REG_FIELD_LIST(uint8_t) + HWSEQ_DCN42_REG_FIELD_LIST(uint8_t) }; struct dce_hwseq_mask { @@ -1263,6 +1273,7 @@ struct dce_hwseq_mask { HWSEQ_DCN31_REG_FIELD_LIST(uint32_t) HWSEQ_DCN35_REG_FIELD_LIST(uint32_t) HWSEQ_DCN401_REG_FIELD_LIST(uint32_t) + HWSEQ_DCN42_REG_FIELD_LIST(uint32_t) }; diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c index 699a756bbc40..5273ca09fe12 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c @@ -86,9 +86,9 @@ hws->ctx #define DC_LOGGER \ - ctx->logger -#define DC_LOGGER_INIT() \ - struct dc_context *ctx = dc->ctx + dc_ctx->logger +#define DC_LOGGER_INIT(ctx) \ + struct dc_context *dc_ctx = ctx #define REG(reg)\ hws->regs->reg @@ -201,6 +201,8 @@ static void enable_display_pipe_clock_gating( struct dc_context *ctx, bool clock_gating) { + (void)ctx; + (void)clock_gating; /*TODO*/ } @@ -284,6 +286,7 @@ static bool dce110_set_input_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state) { + (void)dc; struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; const struct dc_transfer_func *tf = NULL; struct ipp_prescale_params prescale_params = { 0 }; @@ -488,15 +491,15 @@ dce110_translate_regamma_to_hw_format(const struct dc_transfer_func *output_tf, seg_distr[8] = 4; seg_distr[9] = 4; seg_distr[10] = 0; - seg_distr[11] = -1; - seg_distr[12] = -1; - seg_distr[13] = -1; - seg_distr[14] = -1; - seg_distr[15] = -1; + seg_distr[11] = (uint32_t)-1; + seg_distr[12] = (uint32_t)-1; + seg_distr[13] = (uint32_t)-1; + seg_distr[14] = (uint32_t)-1; + seg_distr[15] = (uint32_t)-1; } for (k = 0; k < 16; k++) { - if (seg_distr[k] != -1) + if (seg_distr[k] != (uint32_t)-1) hw_points += (1 << seg_distr[k]); } @@ -607,6 +610,7 @@ static bool dce110_set_output_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx, const struct dc_stream_state *stream) { + (void)dc; struct transform *xfm = pipe_ctx->plane_res.xfm; xfm->funcs->opp_power_on_regamma_lut(xfm, true); @@ -660,6 +664,30 @@ void dce110_update_info_frame(struct pipe_ctx *pipe_ctx) } } +static void +dce110_dac_encoder_control(struct pipe_ctx *pipe_ctx, bool enable) +{ + struct dc_link *link = pipe_ctx->stream->link; + struct dc_bios *bios = link->ctx->dc_bios; + struct bp_encoder_control encoder_control = {0}; + + encoder_control.action = enable ? ENCODER_CONTROL_ENABLE : ENCODER_CONTROL_DISABLE; + encoder_control.engine_id = link->link_enc->analog_engine; + encoder_control.pixel_clock = pipe_ctx->stream->timing.pix_clk_100hz / 10; + bios->funcs->encoder_control(bios, &encoder_control); +} + +static bool +dce110_dac_load_detect(struct dc_link *link) +{ + struct dc_bios *bios = link->ctx->dc_bios; + struct link_encoder *link_enc = link->link_enc; + enum bp_result bp_result; + + bp_result = bios->funcs->dac_load_detection(bios, link_enc->analog_engine); + return bp_result == BP_RESULT_OK; +} + void dce110_enable_stream(struct pipe_ctx *pipe_ctx) { enum dc_lane_count lane_count = @@ -672,6 +700,7 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx) uint32_t early_control = 0; struct timing_generator *tg = pipe_ctx->stream_res.tg; + link_hwss->setup_stream_attribute(pipe_ctx); link_hwss->setup_stream_encoder(pipe_ctx); dc->hwss.update_info_frame(pipe_ctx); @@ -690,6 +719,8 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx) tg->funcs->set_early_control(tg, early_control); + if (dc_is_rgb_signal(pipe_ctx->stream->signal)) + dce110_dac_encoder_control(pipe_ctx, true); } static enum bp_result link_transmitter_control( @@ -711,13 +742,14 @@ void dce110_edp_wait_for_hpd_ready( struct dc_link *link, bool power_up) { - struct dc_context *ctx = link->ctx; struct graphics_object_id connector = link->link_enc->connector; bool edp_hpd_high = false; uint32_t time_elapsed = 0; uint32_t timeout = power_up ? PANEL_POWER_UP_TIMEOUT : PANEL_POWER_DOWN_TIMEOUT; + DC_LOGGER_INIT(link->ctx); + if (dal_graphics_object_id_get_connector_id(connector) != CONNECTOR_ID_EDP) { BREAK_TO_DEBUGGER(); @@ -769,6 +801,7 @@ void dce110_edp_power_control( enum bp_result bp_result; uint8_t pwrseq_instance; + DC_LOGGER_INIT(ctx); if (dal_graphics_object_id_get_connector_id(link->link_enc->connector) != CONNECTOR_ID_EDP) { @@ -937,6 +970,8 @@ void dce110_edp_backlight_control( unsigned int pre_T11_delay = (link->dpcd_sink_ext_caps.bits.oled ? OLED_PRE_T11_DELAY : 0); unsigned int post_T7_delay = (link->dpcd_sink_ext_caps.bits.oled ? OLED_POST_T7_DELAY : 0); + DC_LOGGER_INIT(ctx); + if (dal_graphics_object_id_get_connector_id(link->link_enc->connector) != CONNECTOR_ID_EDP) { BREAK_TO_DEBUGGER(); @@ -1183,6 +1218,9 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) dccg->funcs->disable_symclk_se(dccg, stream_enc->stream_enc_inst, link_enc->transmitter - TRANSMITTER_UNIPHY_A); } + + if (dc_is_rgb_signal(pipe_ctx->stream->signal)) + dce110_dac_encoder_control(pipe_ctx, false); } void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, @@ -1505,6 +1543,7 @@ static enum dc_status dce110_enable_stream_timing( struct dc_state *context, struct dc *dc) { + (void)context; struct dc_stream_state *stream = pipe_ctx->stream; struct pipe_ctx *pipe_ctx_old = &dc->current_state->res_ctx. pipe_ctx[pipe_ctx->pipe_idx]; @@ -1534,7 +1573,7 @@ static enum dc_status dce110_enable_stream_timing( return DC_ERROR_UNEXPECTED; } - if (dc_is_hdmi_tmds_signal(stream->signal)) { + if (dc_is_tmds_signal(stream->signal)) { stream->link->phy_state.symclk_ref_cnts.otg = 1; if (stream->link->phy_state.symclk_state == SYMCLK_OFF_TX_OFF) stream->link->phy_state.symclk_state = SYMCLK_ON_TX_OFF; @@ -1564,6 +1603,22 @@ static enum dc_status dce110_enable_stream_timing( return DC_OK; } +static void +dce110_select_crtc_source(struct pipe_ctx *pipe_ctx) +{ + struct dc_link *link = pipe_ctx->stream->link; + struct dc_bios *bios = link->ctx->dc_bios; + struct bp_crtc_source_select crtc_source_select = {0}; + enum engine_id engine_id = link->link_enc->preferred_engine; + + if (dc_is_rgb_signal(pipe_ctx->stream->signal)) + engine_id = link->link_enc->analog_engine; + crtc_source_select.controller_id = CONTROLLER_ID_D0 + pipe_ctx->stream_res.tg->inst; + crtc_source_select.color_depth = pipe_ctx->stream->timing.display_color_depth; + crtc_source_select.engine_id = engine_id; + crtc_source_select.sink_signal = pipe_ctx->stream->signal; + bios->funcs->select_crtc_source(bios, &crtc_source_select); +} enum dc_status dce110_apply_single_controller_ctx_to_hw( struct pipe_ctx *pipe_ctx, @@ -1584,6 +1639,10 @@ enum dc_status dce110_apply_single_controller_ctx_to_hw( hws->funcs.disable_stream_gating(dc, pipe_ctx); } + if (pipe_ctx->stream->signal == SIGNAL_TYPE_RGB) { + dce110_select_crtc_source(pipe_ctx); + } + if (pipe_ctx->stream_res.audio != NULL) { struct audio_output audio_output = {0}; @@ -1663,7 +1722,8 @@ enum dc_status dce110_apply_single_controller_ctx_to_hw( pipe_ctx->stream_res.tg->funcs->set_static_screen_control( pipe_ctx->stream_res.tg, event_triggers, 2); - if (!dc_is_virtual_signal(pipe_ctx->stream->signal)) + if (!dc_is_virtual_signal(pipe_ctx->stream->signal) && + !dc_is_rgb_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_res.stream_enc->funcs->dig_connect_to_otg( pipe_ctx->stream_res.stream_enc, pipe_ctx->stream_res.tg->inst); @@ -1885,6 +1945,35 @@ static void clean_up_dsc_blocks(struct dc *dc) } } +static void dc_hwss_enable_otg_pwa( + struct dc *dc, + struct pipe_ctx *pipe_ctx) +{ + struct timing_generator *tg = NULL; + + if (dc->debug.enable_otg_frame_sync_pwa == 0) + return; + + if (pipe_ctx == NULL || pipe_ctx->stream_res.tg == NULL) + return; + tg = pipe_ctx->stream_res.tg; + + /*only enable this if one active*/ + if (tg->funcs->enable_otg_pwa) { + struct otc_pwa_frame_sync pwa_param = {0}; + + DC_LOGGER_INIT(dc->ctx); + /* mode 1 to choose generate pwa sync signal on line 0 counting + * from vstartup at very beginning of the frame + */ + pwa_param.pwa_frame_sync_line_offset = 0; + pwa_param.pwa_sync_mode = DC_OTG_PWA_FRAME_SYNC_MODE_VSTARTUP; + /*frame sync line for generating high frame sync*/ + tg->funcs->enable_otg_pwa(tg, &pwa_param); + DC_LOG_DC("Enable OTG PWA frame sync on TG %d\n", tg->inst); + } +} + /* * When ASIC goes from VBIOS/VGA mode to driver/accelerated mode we need: * 1. Power down all DC HW blocks @@ -1902,7 +1991,7 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context) struct pipe_ctx *pipe_ctx = NULL; struct dce_hwseq *hws = dc->hwseq; int edp_with_sink_num; - int edp_num; + unsigned int edp_num; int edp_stream_num; int i; bool can_apply_edp_fast_boot = false; @@ -1910,8 +1999,7 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context) bool keep_edp_vdd_on = false; bool should_clean_dsc_block = true; struct dc_bios *dcb = dc->ctx->dc_bios; - DC_LOGGER_INIT(); - + DC_LOGGER_INIT(dc->ctx); get_edp_links_with_sink(dc, edp_links_with_sink, &edp_with_sink_num); dc_get_edp_links(dc, edp_links, &edp_num); @@ -1962,6 +2050,7 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context) // If VBios supports it, we check it from reigster or other flags. pipe_ctx->stream_res.pix_clk_params.dio_se_pix_per_cycle = 1; } + dc_hwss_enable_otg_pwa(dc, pipe_ctx); } break; } @@ -2334,7 +2423,7 @@ static void dce110_reset_hw_ctx_wrap( BREAK_TO_DEBUGGER(); } pipe_ctx_old->stream_res.tg->funcs->disable_crtc(pipe_ctx_old->stream_res.tg); - if (dc_is_hdmi_tmds_signal(pipe_ctx_old->stream->signal)) + if (dc_is_tmds_signal(pipe_ctx_old->stream->signal)) pipe_ctx_old->stream->link->phy_state.symclk_ref_cnts.otg = 0; pipe_ctx_old->plane_res.mi->funcs->free_mem_input( pipe_ctx_old->plane_res.mi, dc->current_state->stream_count); @@ -2531,6 +2620,18 @@ enum dc_status dce110_apply_ctx_to_hw( #endif } + + if (dc->debug.enable_otg_frame_sync_pwa && context->stream_count == 1) { + /* only enable this on one OTG*/ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (pipe_ctx && pipe_ctx->stream != NULL) { + dc_hwss_enable_otg_pwa(dc, pipe_ctx); + break; + } + } + } if (dc->fbc_compressor) enable_fbc(dc, dc->current_state); @@ -2632,6 +2733,7 @@ static void program_gamut_remap(struct pipe_ctx *pipe_ctx) static void update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx) { + (void)dc; struct dc_plane_state *plane_state = pipe_ctx->plane_state; if (plane_state == NULL) @@ -2677,7 +2779,6 @@ static bool wait_for_reset_trigger_to_occur( struct dc_context *dc_ctx, struct timing_generator *tg) { - struct dc_context *ctx = dc_ctx; bool rc = false; /* To avoid endless loop we wait at most @@ -2719,10 +2820,11 @@ static void dce110_enable_timing_synchronization( int group_size, struct pipe_ctx *grouped_pipes[]) { - struct dc_context *dc_ctx = dc->ctx; + (void)state; + (void)group_index; struct dcp_gsl_params gsl_params = { 0 }; int i; - DC_LOGGER_INIT(); + DC_LOGGER_INIT(dc->ctx); DC_SYNC_INFO("GSL: Setting-up...\n"); @@ -2765,10 +2867,9 @@ static void dce110_enable_per_frame_crtc_position_reset( int group_size, struct pipe_ctx *grouped_pipes[]) { - struct dc_context *dc_ctx = dc->ctx; struct dcp_gsl_params gsl_params = { 0 }; int i; - DC_LOGGER_INIT(); + DC_LOGGER_INIT(dc->ctx); gsl_params.gsl_group = 0; gsl_params.gsl_master = 0; @@ -2796,6 +2897,8 @@ static void dce110_enable_per_frame_crtc_position_reset( static void dce110_init_pipes(struct dc *dc, struct dc_state *context) { + (void)context; + (void)dc; // Do nothing } @@ -3061,10 +3164,13 @@ static void dce110_post_unlock_program_front_end( struct dc *dc, struct dc_state *context) { + (void)dc; + (void)context; } static void dce110_power_down_fe(struct dc *dc, struct dc_state *state, struct pipe_ctx *pipe_ctx) { + (void)state; struct dce_hwseq *hws = dc->hwseq; int fe_idx = pipe_ctx->plane_res.mi ? pipe_ctx->plane_res.mi->inst : pipe_ctx->pipe_idx; @@ -3085,6 +3191,9 @@ static void dce110_wait_for_mpcc_disconnect( struct resource_pool *res_pool, struct pipe_ctx *pipe_ctx) { + (void)dc; + (void)res_pool; + (void)pipe_ctx; /* do nothing*/ } @@ -3094,6 +3203,10 @@ static void program_output_csc(struct dc *dc, uint16_t *matrix, int opp_id) { + (void)dc; + (void)colorspace; + (void)matrix; + (void)opp_id; int i; struct out_csc_color_matrix tbl_entry; @@ -3238,6 +3351,7 @@ void dce110_enable_lvds_link_output(struct dc_link *link, enum clock_source_id clock_source, uint32_t pixel_clock) { + (void)link_res; link->link_enc->funcs->enable_lvds_output( link->link_enc, clock_source, @@ -3252,6 +3366,7 @@ void dce110_enable_tmds_link_output(struct dc_link *link, enum dc_color_depth color_depth, uint32_t pixel_clock) { + (void)link_res; link->link_enc->funcs->enable_tmds_output( link->link_enc, clock_source, @@ -3261,15 +3376,6 @@ void dce110_enable_tmds_link_output(struct dc_link *link, link->phy_state.symclk_state = SYMCLK_ON_TX_ON; } -static void dce110_enable_analog_link_output( - struct dc_link *link, - uint32_t pix_clk_100hz) -{ - link->link_enc->funcs->enable_analog_output( - link->link_enc, - pix_clk_100hz); -} - void dce110_enable_dp_link_output( struct dc_link *link, const struct link_resource *link_res, @@ -3407,8 +3513,8 @@ static const struct hw_sequencer_funcs dce110_funcs = { .enable_lvds_link_output = dce110_enable_lvds_link_output, .enable_tmds_link_output = dce110_enable_tmds_link_output, .enable_dp_link_output = dce110_enable_dp_link_output, - .enable_analog_link_output = dce110_enable_analog_link_output, .disable_link_output = dce110_disable_link_output, + .dac_load_detect = dce110_dac_load_detect, }; static const struct hwseq_private_funcs dce110_private_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce120/dce120_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce120/dce120_hwseq.c index 2a62f63d0357..0689bbf12ad8 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dce120/dce120_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dce120/dce120_hwseq.c @@ -154,6 +154,10 @@ static bool dce120_enable_display_power_gating( struct dc_bios *dcb, enum pipe_gating_control power_gating) { + (void)dc; + (void)controller_id; + (void)dcb; + (void)power_gating; /* disable for bringup */ #if 0 enum bp_result bp_result = BP_RESULT_OK; diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c index a2d28be480e8..756ce8379538 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c @@ -60,9 +60,9 @@ #include "dc_state_priv.h" #define DC_LOGGER \ - dc_logger -#define DC_LOGGER_INIT(logger) \ - struct dal_logger *dc_logger = logger + dc_ctx->logger +#define DC_LOGGER_INIT(ctx) \ + struct dc_context *dc_ctx = ctx #define CTX \ hws->ctx @@ -86,6 +86,7 @@ static void print_microsec(struct dc_context *dc_ctx, struct dc_log_buffer_ctx *log_ctx, uint32_t ref_cycle) { + (void)log_ctx; const uint32_t ref_clk_mhz = dc_ctx->dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000; static const unsigned int frac = 1000; uint32_t us_x10 = (ref_cycle * frac) / ref_clk_mhz; @@ -252,6 +253,7 @@ void dcn10_lock_all_pipes(struct dc *dc, static void log_mpc_crc(struct dc *dc, struct dc_log_buffer_ctx *log_ctx) { + (void)log_ctx; struct dc_context *dc_ctx = dc->ctx; struct dce_hwseq *hws = dc->hwseq; @@ -450,6 +452,7 @@ static void dcn10_log_hubp_states(struct dc *dc, void *log_ctx) static void dcn10_log_color_state(struct dc *dc, struct dc_log_buffer_ctx *log_ctx) { + (void)log_ctx; struct dc_context *dc_ctx = dc->ctx; struct resource_pool *pool = dc->res_pool; bool is_gamut_remap_available = false; @@ -813,6 +816,7 @@ void dcn10_log_hw_state(struct dc *dc, bool dcn10_did_underflow_occur(struct dc *dc, struct pipe_ctx *pipe_ctx) { + (void)dc; struct hubp *hubp = pipe_ctx->plane_res.hubp; struct timing_generator *tg = pipe_ctx->stream_res.tg; @@ -1009,7 +1013,7 @@ static void power_on_plane_resources( struct dce_hwseq *hws, int plane_id) { - DC_LOGGER_INIT(hws->ctx->logger); + DC_LOGGER_INIT(hws->ctx); if (hws->funcs.dpp_root_clock_control) hws->funcs.dpp_root_clock_control(hws, plane_id, true); @@ -1181,6 +1185,7 @@ enum dc_status dcn10_enable_stream_timing( struct dc_state *context, struct dc *dc) { + (void)context; struct dc_stream_state *stream = pipe_ctx->stream; enum dc_color_space color_space; struct tg_color black_color = {0}; @@ -1284,9 +1289,10 @@ static void dcn10_reset_back_end_for_pipe( struct pipe_ctx *pipe_ctx, struct dc_state *context) { + (void)context; int i; struct dc_link *link; - DC_LOGGER_INIT(dc->ctx->logger); + DC_LOGGER_INIT(dc->ctx); if (pipe_ctx->stream_res.stream_enc == NULL) { pipe_ctx->stream = NULL; return; @@ -1422,12 +1428,10 @@ void dcn10_verify_allow_pstate_change_high(struct dc *dc) return; if (!hubbub->funcs->verify_allow_pstate_change_high(hubbub)) { - int i = 0; - if (should_log_hw_state) dcn10_log_hw_state(dc, NULL); - TRACE_DC_PIPE_STATE(pipe_ctx, i, MAX_PIPES); + TRACE_DC_PIPE_STATE(pipe_ctx, MAX_PIPES); BREAK_TO_DEBUGGER(); if (dcn10_hw_wa_force_recovery(dc)) { /*check again*/ @@ -1490,7 +1494,7 @@ void dcn10_plane_atomic_power_down(struct dc *dc, struct hubp *hubp) { struct dce_hwseq *hws = dc->hwseq; - DC_LOGGER_INIT(dc->ctx->logger); + DC_LOGGER_INIT(dc->ctx); if (REG(DC_IP_REQUEST_CNTL)) { REG_SET(DC_IP_REQUEST_CNTL, 0, @@ -1553,8 +1557,9 @@ void dcn10_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx) void dcn10_disable_plane(struct dc *dc, struct dc_state *state, struct pipe_ctx *pipe_ctx) { + (void)state; struct dce_hwseq *hws = dc->hwseq; - DC_LOGGER_INIT(dc->ctx->logger); + DC_LOGGER_INIT(dc->ctx); if (!pipe_ctx->plane_res.hubp || pipe_ctx->plane_res.hubp->power_gated) return; @@ -1906,7 +1911,7 @@ void dcn10_power_down_on_boot(struct dc *dc) { struct dc_link *edp_links[MAX_NUM_EDP]; struct dc_link *edp_link = NULL; - int edp_num; + unsigned int edp_num; int i = 0; dc_get_edp_links(dc, edp_links, &edp_num); @@ -2006,6 +2011,7 @@ static bool patch_address_for_sbs_tb_stereo( void dcn10_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx) { + (void)dc; bool addr_patched = false; PHYSICAL_ADDRESS_LOC addr; struct dc_plane_state *plane_state = pipe_ctx->plane_state; @@ -2032,6 +2038,7 @@ void dcn10_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx) bool dcn10_set_input_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state) { + (void)dc; struct dpp *dpp_base = pipe_ctx->plane_res.dpp; const struct dc_transfer_func *tf = NULL; bool result = true; @@ -2268,8 +2275,6 @@ static bool wait_for_reset_trigger_to_occur( { bool rc = false; - DC_LOGGER_INIT(dc_ctx->logger); - /* To avoid endless loop we wait at most * frames_to_wait_on_triggered_reset frames for the reset to occur. */ const uint32_t frames_to_wait_on_triggered_reset = 10; @@ -2384,7 +2389,6 @@ static uint8_t get_clock_divider(struct pipe_ctx *pipe, static int dcn10_align_pixel_clocks(struct dc *dc, int group_size, struct pipe_ctx *grouped_pipes[]) { - struct dc_context *dc_ctx = dc->ctx; int i, master = -1, embedded = -1; struct dc_crtc_timing *hw_crtc_timing; uint64_t phase[MAX_PIPES]; @@ -2397,7 +2401,7 @@ static int dcn10_align_pixel_clocks(struct dc *dc, int group_size, uint32_t dp_ref_clk_100hz = dc->res_pool->dp_clock_source->ctx->dc->clk_mgr->dprefclk_khz*10; - DC_LOGGER_INIT(dc_ctx->logger); + DC_LOGGER_INIT(dc->ctx); hw_crtc_timing = kzalloc_objs(*hw_crtc_timing, MAX_PIPES); if (!hw_crtc_timing) @@ -2477,12 +2481,12 @@ void dcn10_enable_vblanks_synchronization( int group_size, struct pipe_ctx *grouped_pipes[]) { - struct dc_context *dc_ctx = dc->ctx; + (void)group_index; struct output_pixel_processor *opp; struct timing_generator *tg; int i, width = 0, height = 0, master; - DC_LOGGER_INIT(dc_ctx->logger); + DC_LOGGER_INIT(dc->ctx); for (i = 1; i < group_size; i++) { opp = grouped_pipes[i]->stream_res.opp; @@ -2543,12 +2547,12 @@ void dcn10_enable_timing_synchronization( int group_size, struct pipe_ctx *grouped_pipes[]) { - struct dc_context *dc_ctx = dc->ctx; + (void)group_index; struct output_pixel_processor *opp; struct timing_generator *tg; int i, width = 0, height = 0; - DC_LOGGER_INIT(dc_ctx->logger); + DC_LOGGER_INIT(dc->ctx); DC_SYNC_INFO("Setting up OTG reset trigger\n"); @@ -2624,10 +2628,9 @@ void dcn10_enable_per_frame_crtc_position_reset( int group_size, struct pipe_ctx *grouped_pipes[]) { - struct dc_context *dc_ctx = dc->ctx; int i; - DC_LOGGER_INIT(dc_ctx->logger); + DC_LOGGER_INIT(dc->ctx); DC_SYNC_INFO("Setting up\n"); for (i = 0; i < group_size; i++) @@ -2649,6 +2652,7 @@ static void mmhub_read_vm_system_aperture_settings(struct dcn10_hubp *hubp1, struct vm_system_aperture_param *apt, struct dce_hwseq *hws) { + (void)hubp1; PHYSICAL_ADDRESS_LOC physical_page_number; uint32_t logical_addr_low; uint32_t logical_addr_high; @@ -2674,6 +2678,7 @@ static void mmhub_read_vm_context0_settings(struct dcn10_hubp *hubp1, struct vm_context0_param *vm0, struct dce_hwseq *hws) { + (void)hubp1; PHYSICAL_ADDRESS_LOC fb_base; PHYSICAL_ADDRESS_LOC fb_offset; uint32_t fb_base_value; @@ -2732,6 +2737,7 @@ static void dcn10_enable_plane( struct pipe_ctx *pipe_ctx, struct dc_state *context) { + (void)context; struct dce_hwseq *hws = dc->hwseq; if (dc->debug.sanity_checks) { @@ -2829,6 +2835,8 @@ void dcn10_program_output_csc(struct dc *dc, uint16_t *matrix, int opp_id) { + (void)dc; + (void)opp_id; if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) { if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment != NULL) { @@ -3594,6 +3602,10 @@ bool dcn10_dummy_display_power_gating( struct dc_bios *dcb, enum pipe_gating_control power_gating) { + (void)dc; + (void)controller_id; + (void)dcb; + (void)power_gating; return true; } @@ -4060,6 +4072,7 @@ enum dc_status dcn10_set_clock(struct dc *dc, uint32_t clk_khz, uint32_t stepping) { + (void)stepping; struct dc_state *context = dc->current_state; struct dc_clock_config clock_cfg = {0}; struct dc_clocks *current_clocks = &context->bw_ctx.bw.dcn.clk; diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c index 307e8f8060e6..288e4edaa9a2 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c @@ -75,6 +75,7 @@ void dcn20_log_color_state(struct dc *dc, struct dc_log_buffer_ctx *log_ctx) { + (void)log_ctx; struct dc_context *dc_ctx = dc->ctx; struct resource_pool *pool = dc->res_pool; bool is_gamut_remap_available = false; @@ -379,6 +380,7 @@ void dcn20_program_triple_buffer( struct pipe_ctx *pipe_ctx, bool enable_triple_buffer) { + (void)dc; if (pipe_ctx->plane_res.hubp && pipe_ctx->plane_res.hubp->funcs) { pipe_ctx->plane_res.hubp->funcs->hubp_enable_tripleBuffer( pipe_ctx->plane_res.hubp, @@ -893,7 +895,7 @@ enum dc_status dcn20_enable_stream_timing( dccg->funcs->set_dtbclk_dto(dccg, &dto_params); } - if (dc_is_hdmi_tmds_signal(stream->signal)) { + if (dc_is_tmds_signal(stream->signal)) { stream->link->phy_state.symclk_ref_cnts.otg = 1; if (stream->link->phy_state.symclk_state == SYMCLK_OFF_TX_OFF) stream->link->phy_state.symclk_state = SYMCLK_ON_TX_OFF; @@ -1175,6 +1177,8 @@ bool dcn20_set_input_transfer_func(struct dc *dc, void dcn20_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx) { + (void)context; + (void)dc; struct pipe_ctx *odm_pipe; int opp_cnt = 1; int opp_inst[MAX_PIPES] = { pipe_ctx->stream_res.opp->inst }; @@ -1297,6 +1301,7 @@ static void dcn20_power_on_plane_resources( void dcn20_enable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx, struct dc_state *context) { + (void)context; //if (dc->debug.sanity_checks) { // dcn10_verify_allow_pstate_change_high(dc); //} @@ -2652,6 +2657,7 @@ void dcn20_init_vm_ctx( struct dc_virtual_addr_space_config *va_config, int vmid) { + (void)hws; struct dcn_hubbub_virt_addr_config config; if (vmid == 0) { @@ -2670,6 +2676,7 @@ void dcn20_init_vm_ctx( int dcn20_init_sys_ctx(struct dce_hwseq *hws, struct dc *dc, struct dc_phy_addr_space_config *pa_config) { + (void)hws; struct dcn_hubbub_phys_addr_config config; config.system_aperture.fb_top = pa_config->system_aperture.fb_top; @@ -2799,6 +2806,7 @@ void dcn20_reset_back_end_for_pipe( struct pipe_ctx *pipe_ctx, struct dc_state *context) { + (void)context; struct dc_link *link = pipe_ctx->stream->link; const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res); struct dccg *dccg = dc->res_pool->dccg; @@ -2856,7 +2864,7 @@ void dcn20_reset_back_end_for_pipe( * the case where the same symclk is shared across multiple otg * instances */ - if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal)) + if (dc_is_tmds_signal(pipe_ctx->stream->signal)) link->phy_state.symclk_ref_cnts.otg = 0; if (link->phy_state.symclk_state == SYMCLK_ON_TX_OFF) { link_hwss->disable_link_output(link, @@ -3245,6 +3253,7 @@ void dcn20_set_disp_pattern_generator(const struct dc *dc, const struct tg_color *solid_color, int width, int height, int offset) { + (void)dc; pipe_ctx->stream_res.opp->funcs->opp_set_disp_pattern_generator(pipe_ctx->stream_res.opp, test_pattern, color_space, color_depth, solid_color, width, height, offset); } diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c index d04cfd403b7e..2aa0f1de8103 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c @@ -75,6 +75,7 @@ void dcn30_log_color_state(struct dc *dc, struct dc_log_buffer_ctx *log_ctx) { + (void)log_ctx; struct dc_context *dc_ctx = dc->ctx; struct resource_pool *pool = dc->res_pool; bool is_gamut_remap_available = false; @@ -645,7 +646,7 @@ void dcn30_init_hw(struct dc *dc) struct dc_bios *dcb = dc->ctx->dc_bios; struct resource_pool *res_pool = dc->res_pool; int i; - int edp_num; + unsigned int edp_num; uint32_t backlight = MAX_BACKLIGHT_LEVEL; uint32_t user_level = MAX_BACKLIGHT_LEVEL; @@ -1183,6 +1184,7 @@ void dcn30_set_disp_pattern_generator(const struct dc *dc, const struct tg_color *solid_color, int width, int height, int offset) { + (void)dc; pipe_ctx->stream_res.opp->funcs->opp_set_disp_pattern_generator(pipe_ctx->stream_res.opp, test_pattern, color_space, color_depth, solid_color, width, height, offset); } @@ -1237,6 +1239,7 @@ void dcn30_get_underflow_debug_data(const struct dc *dc, struct timing_generator *tg, struct dc_underflow_debug_data *out_data) { + (void)tg; struct hubbub *hubbub = dc->res_pool->hubbub; if (hubbub) { diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn303/dcn303_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn303/dcn303_hwseq.c index 3bc56ac346f3..6e1877a8682d 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn303/dcn303_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn303/dcn303_hwseq.c @@ -45,20 +45,31 @@ void dcn303_dpp_pg_control(struct dce_hwseq *hws, unsigned int dpp_inst, bool power_on) { + (void)dpp_inst; + (void)hws; + (void)power_on; /*DCN303 removes PG registers*/ } void dcn303_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on) { + (void)hubp_inst; + (void)hws; + (void)power_on; /*DCN303 removes PG registers*/ } void dcn303_dsc_pg_control(struct dce_hwseq *hws, unsigned int dsc_inst, bool power_on) { + (void)dsc_inst; + (void)hws; + (void)power_on; /*DCN303 removes PG registers*/ } void dcn303_enable_power_gating_plane(struct dce_hwseq *hws, bool enable) { + (void)enable; + (void)hws; /*DCN303 removes PG registers*/ } diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c index db2f7cbb12ff..b4afb2bc4493 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c @@ -484,6 +484,7 @@ void dcn31_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool p int dcn31_init_sys_ctx(struct dce_hwseq *hws, struct dc *dc, struct dc_phy_addr_space_config *pa_config) { + (void)hws; struct dcn_hubbub_phys_addr_config config = {0}; config.system_aperture.fb_top = pa_config->system_aperture.fb_top; @@ -511,9 +512,9 @@ static void dcn31_reset_back_end_for_pipe( struct pipe_ctx *pipe_ctx, struct dc_state *context) { + (void)context; struct dc_link *link; - DC_LOGGER_INIT(dc->ctx->logger); if (pipe_ctx->stream_res.stream_enc == NULL) { pipe_ctx->stream = NULL; return; @@ -549,7 +550,7 @@ static void dcn31_reset_back_end_for_pipe( * the case where the same symclk is shared across multiple otg * instances */ - if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal)) + if (dc_is_tmds_signal(pipe_ctx->stream->signal)) link->phy_state.symclk_ref_cnts.otg = 0; if (pipe_ctx->top_pipe == NULL) { diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c index 3e239124c17d..858a06b03b57 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c @@ -172,6 +172,7 @@ static unsigned int get_odm_config(struct pipe_ctx *pipe_ctx, unsigned int *opp_ void dcn314_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx) { + (void)context; struct pipe_ctx *odm_pipe; int opp_cnt = 0; int opp_inst[MAX_PIPES] = {0}; diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c index a0aaa727e9fa..b45ceb570a5c 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c @@ -570,6 +570,7 @@ bool dcn32_set_output_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx, const struct dc_stream_state *stream) { + (void)dc; int mpcc_id = pipe_ctx->plane_res.hubp->inst; struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc; const struct pwl_params *params = NULL; @@ -757,6 +758,9 @@ static void dcn32_initialize_min_clocks(struct dc *dc) { struct dc_clocks *clocks = &dc->current_state->bw_ctx.bw.dcn.clk; + if (!dc->clk_mgr || !dc->clk_mgr->bw_params || !dc->clk_mgr->funcs) + return; + clocks->dcfclk_deep_sleep_khz = DCN3_2_DCFCLK_DS_INIT_KHZ; clocks->dcfclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dcfclk_mhz * 1000; clocks->socclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].socclk_mhz * 1000; @@ -765,9 +769,10 @@ static void dcn32_initialize_min_clocks(struct dc *dc) clocks->ref_dtbclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dtbclk_mhz * 1000; clocks->fclk_p_state_change_support = true; clocks->p_state_change_support = true; + if (dc->debug.disable_boot_optimizations) { clocks->dispclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dispclk_mhz * 1000; - } else { + } else if (dc->clk_mgr->funcs->get_dispclk_from_dentist) { /* Even though DPG_EN = 1 for the connected display, it still requires the * correct timing so we cannot set DISPCLK to min freq or it could cause * audio corruption. Read current DISPCLK from DENTIST and request the same @@ -776,10 +781,10 @@ static void dcn32_initialize_min_clocks(struct dc *dc) clocks->dispclk_khz = dc->clk_mgr->funcs->get_dispclk_from_dentist(dc->clk_mgr); } - dc->clk_mgr->funcs->update_clocks( - dc->clk_mgr, - dc->current_state, - true); + if (dc->clk_mgr->funcs->update_clocks) + dc->clk_mgr->funcs->update_clocks(dc->clk_mgr, + dc->current_state, + true); } void dcn32_init_hw(struct dc *dc) @@ -789,7 +794,7 @@ void dcn32_init_hw(struct dc *dc) struct dc_bios *dcb = dc->ctx->dc_bios; struct resource_pool *res_pool = dc->res_pool; int i; - int edp_num; + unsigned int edp_num; uint32_t backlight = MAX_BACKLIGHT_LEVEL; uint32_t user_level = MAX_BACKLIGHT_LEVEL; @@ -1007,7 +1012,8 @@ void dcn32_init_hw(struct dc *dc) DMUB_FW_VERSION(7, 0, 35)) { /* FAMS2 is disabled */ dc->debug.fams2_config.bits.enable = false; - if (dc->debug.using_dml2 && dc->res_pool->funcs->update_bw_bounding_box) { + if (dc->debug.using_dml2 && dc->res_pool->funcs->update_bw_bounding_box && + dc->clk_mgr && dc->clk_mgr->bw_params) { /* update bounding box if FAMS2 disabled */ dc->res_pool->funcs->update_bw_bounding_box(dc, dc->clk_mgr->bw_params); } @@ -1138,6 +1144,7 @@ static unsigned int get_odm_config(struct pipe_ctx *pipe_ctx, unsigned int *opp_ void dcn32_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx) { + (void)context; struct pipe_ctx *odm_pipe; int opp_cnt = 0; int opp_inst[MAX_PIPES] = {0}; diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c index b5a4cefbd35f..f133b52ea958 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c @@ -60,15 +60,15 @@ #include "dcn20/dcn20_hwseq.h" #include "dc_state_priv.h" -#define DC_LOGGER_INIT(logger) \ - struct dal_logger *dc_logger = logger +#define DC_LOGGER \ + dc_ctx->logger +#define DC_LOGGER_INIT(ctx) \ + struct dc_context *dc_ctx = ctx #define CTX \ hws->ctx #define REG(reg)\ hws->regs->reg -#define DC_LOGGER \ - dc_logger #undef FN @@ -331,7 +331,7 @@ static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) struct pipe_ctx *odm_pipe; int opp_cnt = 1; - DC_LOGGER_INIT(stream->ctx->logger); + DC_LOGGER_INIT(stream->ctx); ASSERT(dsc); for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) @@ -428,6 +428,7 @@ static unsigned int get_odm_config(struct pipe_ctx *pipe_ctx, unsigned int *opp_ void dcn35_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx) { + (void)context; struct pipe_ctx *odm_pipe; int opp_cnt = 0; int opp_inst[MAX_PIPES] = {0}; @@ -520,7 +521,7 @@ void dcn35_power_down_on_boot(struct dc *dc) { struct dc_link *edp_links[MAX_NUM_EDP]; struct dc_link *edp_link = NULL; - int edp_num; + unsigned int edp_num; int i = 0; dc_get_edp_links(dc, edp_links, &edp_num); @@ -816,6 +817,7 @@ void dcn35_init_pipes(struct dc *dc, struct dc_state *context) void dcn35_enable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx, struct dc_state *context) { + (void)context; struct dpp *dpp = pipe_ctx->plane_res.dpp; /* enable DCFCLK current DCHUB */ @@ -897,7 +899,7 @@ void dcn35_disable_plane(struct dc *dc, struct dc_state *state, struct pipe_ctx bool is_phantom = dc_state_get_pipe_subvp_type(state, pipe_ctx) == SUBVP_PHANTOM; struct timing_generator *tg = is_phantom ? pipe_ctx->stream_res.tg : NULL; - DC_LOGGER_INIT(dc->ctx->logger); + DC_LOGGER_INIT(dc->ctx); if (!pipe_ctx->plane_res.hubp || pipe_ctx->plane_res.hubp->power_gated) return; @@ -921,7 +923,7 @@ void dcn35_calc_blocks_to_gate(struct dc *dc, struct dc_state *context, bool hpo_frl_stream_enc_acquired = false; bool hpo_dp_stream_enc_acquired = false; int i = 0, j = 0; - int edp_num = 0; + unsigned int edp_num = 0; struct dc_link *edp_links[MAX_NUM_EDP] = { NULL }; memset(update_state, 0, sizeof(struct pg_block_update)); 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 4dfb6c865831..9768b8f6b6fb 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,10 +95,6 @@ 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; @@ -144,7 +140,7 @@ void dcn401_init_hw(struct dc *dc) struct dc_bios *dcb = dc->ctx->dc_bios; struct resource_pool *res_pool = dc->res_pool; int i; - int edp_num; + unsigned int edp_num; uint32_t backlight = MAX_BACKLIGHT_LEVEL; uint32_t user_level = MAX_BACKLIGHT_LEVEL; bool dchub_ref_freq_changed; @@ -305,6 +301,7 @@ void dcn401_init_hw(struct dc *dc) } } } + for (i = 0; i < res_pool->audio_count; i++) { struct audio *audio = res_pool->audios[i]; @@ -377,293 +374,180 @@ void dcn401_init_hw(struct dc *dc) } } -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 dcn401_trigger_3dlut_dma_load(struct dc *dc, struct pipe_ctx *pipe_ctx) { - 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; + (void)dc; + struct hubp *hubp = pipe_ctx->plane_res.hubp; - 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; + if (hubp->funcs->hubp_enable_3dlut_fl) { + hubp->funcs->hubp_enable_3dlut_fl(hubp, true); } } -void dcn401_populate_mcm_luts(struct dc *dc, - struct pipe_ctx *pipe_ctx, - struct dc_cm2_func_luts mcm_luts, - bool lut_bank_a) +bool dcn401_set_mcm_luts(struct pipe_ctx *pipe_ctx, + const struct dc_plane_state *plane_state) { + 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; - 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; + struct dc_3dlut_dma lut3d_dma; + bool lut_enable; + bool lut_bank_a; bool rval; + bool result = true; - dcn401_get_mcm_lut_xable_from_pipe_ctx(dc, pipe_ctx, &shaper_xable, &lut3d_xable, &lut1d_xable); + /* 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); /* 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); + 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); 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 (!m_lut_params.pwl) { + 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); + } else { + lut_enable = false; } + 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 */ - if (mcm_luts.shaper && mcm_luts.lut3d_data.mpc_3dlut_enable) { + lut_enable = cm->flags.bits.shaper_enable; + if (lut_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) { + 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) { 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; + 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; } - 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); + if (!m_lut_params.pwl) { + lut_enable = false; } + } else { + lut_enable = false; } - /* 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_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; - } + 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); - //check for support - if (mpc->funcs->mcm.is_config_supported && - !mpc->funcs->mcm.is_config_supported(width)) - break; + /* 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 (mpc->funcs->program_lut_read_write_control) - mpc->funcs->program_lut_read_write_control(mpc, MCM_LUT_3DLUT, lut_bank_a, mpcc_id); + /* 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, 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); + mpc->funcs->program_lut_mode(mpc, MCM_LUT_3DLUT, lut_enable, lut_bank_a, cm->lut3d_dma.size, mpcc_id); - 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); - - 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); + /* 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); - if (hubp->funcs->hubp_program_3dlut_fl_addressing_mode) - hubp->funcs->hubp_program_3dlut_fl_addressing_mode(hubp, addr_mode); + if (mpc->funcs->update_3dlut_fast_load_select) + mpc->funcs->update_3dlut_fast_load_select(mpc, mpcc_id, hubp->inst); - 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 - 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; - } + /* 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_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); + hubp->funcs->hubp_program_3dlut_fl_crossbar(hubp, cm->lut3d_dma.format); - 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, &cm->lut3d_dma.addr); - if (hubp->funcs->hubp_enable_3dlut_fl) + 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); - } + } else { + /* GPU memory only supports fast load path */ + BREAK_TO_DEBUGGER(); + lut_enable = false; + result = false; } - break; + } 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; + } -void dcn401_trigger_3dlut_dma_load(struct dc *dc, struct pipe_ctx *pipe_ctx) -{ - struct hubp *hubp = pipe_ctx->plane_res.hubp; + /* 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_enable_3dlut_fl) { - hubp->funcs->hubp_enable_3dlut_fl(hubp, true); - } -} + if (mpc->funcs->update_3dlut_fast_load_select) + mpc->funcs->update_3dlut_fast_load_select(mpc, mpcc_id, 0xf); -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 (mpc->funcs->populate_lut) + mpc->funcs->populate_lut(mpc, MCM_LUT_3DLUT, &m_lut_params, lut_bank_a, mpcc_id); + } - 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; - } + /* 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); - 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); + if (hubp->funcs->hubp_enable_3dlut_fl) + hubp->funcs->hubp_enable_3dlut_fl(hubp, false); } return result; @@ -673,6 +557,7 @@ bool dcn401_set_output_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx, const struct dc_stream_state *stream) { + (void)dc; int mpcc_id = pipe_ctx->plane_res.hubp->inst; struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc; const struct pwl_params *params = NULL; @@ -734,6 +619,7 @@ static void enable_stream_timing_calc( struct drr_params *params, unsigned int *event_triggers) { + (void)dc; struct dc_stream_state *stream = pipe_ctx->stream; int i; @@ -987,6 +873,8 @@ void dcn401_enable_stream(struct pipe_ctx *pipe_ctx) } } + link_hwss->setup_stream_attribute(pipe_ctx); + if (dc->res_pool->dccg->funcs->set_pixel_rate_div) { dc->res_pool->dccg->funcs->set_pixel_rate_div( dc->res_pool->dccg, @@ -1211,6 +1099,25 @@ void dcn401_set_cursor_position(struct pipe_ctx *pipe_ctx) x_pos = pos_cpy.x - param.recout.x; y_pos = pos_cpy.y - param.recout.y; + /** + * If the cursor position is negative after recout adjustment, we need + * to shift the hotspot to compensate and clamp position to 0. This + * handles the case where cursor straddles the left/top edge of an + * overlay plane - the cursor is partially visible and needs correct + * hotspot adjustment to render the visible portion. + */ + if (x_pos < 0) { + pos_cpy.x_hotspot -= x_pos; + if (hubp->curs_attr.attribute_flags.bits.ENABLE_MAGNIFICATION) + adjust_hotspot_between_slices_for_2x_magnify(hubp->curs_attr.width, &pos_cpy); + x_pos = 0; + } + + if (y_pos < 0) { + pos_cpy.y_hotspot -= y_pos; + y_pos = 0; + } + recout_x_pos = x_pos - pos_cpy.x_hotspot; recout_y_pos = y_pos - pos_cpy.y_hotspot; @@ -1473,7 +1380,7 @@ void dcn401_optimize_bandwidth( dc->clk_mgr, context, true); - if (context->bw_ctx.bw.dcn.clk.zstate_support == DCN_ZSTATE_SUPPORT_ALLOW) { + if (context->bw_ctx.bw.dcn.clk.zstate_support != DCN_ZSTATE_SUPPORT_DISALLOW) { for (i = 0; i < dc->res_pool->pipe_count; ++i) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; @@ -1481,7 +1388,7 @@ void dcn401_optimize_bandwidth( && pipe_ctx->stream->adjust.v_total_min == pipe_ctx->stream->adjust.v_total_max && pipe_ctx->stream->adjust.v_total_max > pipe_ctx->stream->timing.v_total) pipe_ctx->plane_res.hubp->funcs->program_extended_blank(pipe_ctx->plane_res.hubp, - pipe_ctx->dlg_regs.min_dst_y_next_start); + pipe_ctx->hubp_regs.dlg_regs.min_dst_y_next_start); } } } @@ -1490,6 +1397,7 @@ void dcn401_dmub_hw_control_lock(struct dc *dc, struct dc_state *context, bool lock) { + (void)context; /* use always for now */ union dmub_inbox0_cmd_lock_hw hw_lock_cmd = { 0 }; @@ -1916,10 +1824,9 @@ 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->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) { + if (mpc_pipe->plane_state && + mpc_pipe->plane_state->cm.flags.bits.lut3d_enable && + mpc_pipe->plane_state->cm.flags.bits.lut3d_dma_enable) { wa_pipes[wa_pipe_ct++] = mpc_pipe; } } @@ -1965,10 +1872,10 @@ void dcn401_reset_back_end_for_pipe( struct pipe_ctx *pipe_ctx, struct dc_state *context) { + (void)context; struct dc_link *link = pipe_ctx->stream->link; const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res); - DC_LOGGER_INIT(dc->ctx->logger); if (pipe_ctx->stream_res.stream_enc == NULL) { pipe_ctx->stream = NULL; return; @@ -2021,7 +1928,7 @@ void dcn401_reset_back_end_for_pipe( * the case where the same symclk is shared across multiple otg * instances */ - if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal)) + if (dc_is_tmds_signal(pipe_ctx->stream->signal)) link->phy_state.symclk_ref_cnts.otg = 0; if (link->phy_state.symclk_state == SYMCLK_ON_TX_OFF) { link_hwss->disable_link_output(link, @@ -2047,6 +1954,22 @@ void dcn401_reset_back_end_for_pipe( DC_LOG_DEBUG("Reset back end for pipe %d, tg:%d\n", pipe_ctx->pipe_idx, pipe_ctx->stream_res.tg->inst); } +static void dc_hwss_disable_otg_pwa(struct dc *dc) +{ + if (dc->debug.enable_otg_frame_sync_pwa) { + int i; + + /*reset all the otg*/ + for (i = dc->res_pool->timing_generator_count - 1; i >= 0 ; i--) { + struct timing_generator *tg = dc->res_pool->timing_generators[i]; + + if (tg->funcs->disable_otg_pwa) { + tg->funcs->disable_otg_pwa(tg); + DC_LOG_DC("otg frame sync pwa disabled on otg%d\n", tg->inst); + } + } + } +} void dcn401_reset_hw_ctx_wrap( struct dc *dc, @@ -2055,6 +1978,7 @@ void dcn401_reset_hw_ctx_wrap( int i; struct dce_hwseq *hws = dc->hwseq; + dc_hwss_disable_otg_pwa(dc); /* Reset Back End*/ for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { struct pipe_ctx *pipe_ctx_old = @@ -2245,6 +2169,10 @@ void dcn401_program_pipe( pipe_ctx->stream_res.test_pattern_params.height, pipe_ctx->stream_res.test_pattern_params.offset); } + if (pipe_ctx->plane_state + && pipe_ctx->plane_state->update_flags.bits.cm_hist_change + && hws->funcs.program_cm_hist) + hws->funcs.program_cm_hist(dc, pipe_ctx, pipe_ctx->plane_state); } /* @@ -2396,6 +2324,13 @@ void dcn401_program_pipe_sequence( pipe_ctx->stream_res.test_pattern_params.offset); } + if (pipe_ctx->plane_state + && pipe_ctx->plane_state->update_flags.bits.cm_hist_change + && hws->funcs.program_cm_hist) { + + hwss_add_dpp_program_cm_hist(seq_state, pipe_ctx->plane_res.dpp, + pipe_ctx->plane_state->cm_hist_control, pipe_ctx->plane_state->color_space); + } } void dcn401_program_front_end_for_ctx( @@ -2408,8 +2343,6 @@ void dcn401_program_front_end_for_ctx( struct dce_hwseq *hws = dc->hwseq; struct pipe_ctx *pipe = NULL; - DC_LOGGER_INIT(dc->ctx->logger); - if (resource_is_pipe_topology_changed(dc->current_state, context)) resource_log_pipe_topology_update(dc, context); @@ -2573,8 +2506,6 @@ void dcn401_post_unlock_program_front_end( struct dce_hwseq *hwseq = dc->hwseq; int i; - DC_LOGGER_INIT(dc->ctx->logger); - for (i = 0; i < dc->res_pool->pipe_count; i++) if (resource_is_pipe_type(&dc->current_state->res_ctx.pipe_ctx[i], OPP_HEAD) && !resource_is_pipe_type(&context->res_ctx.pipe_ctx[i], OPP_HEAD)) @@ -2954,8 +2885,6 @@ void dcn401_plane_atomic_power_down(struct dc *dc, struct dce_hwseq *hws = dc->hwseq; uint32_t org_ip_request_cntl = 0; - DC_LOGGER_INIT(dc->ctx->logger); - if (REG(DC_IP_REQUEST_CNTL)) { REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl); if (org_ip_request_cntl == 0) @@ -3047,8 +2976,6 @@ void dcn401_plane_atomic_power_down_sequence(struct dc *dc, struct dce_hwseq *hws = dc->hwseq; uint32_t org_ip_request_cntl = 0; - DC_LOGGER_INIT(dc->ctx->logger); - /* Check and set DC_IP_REQUEST_CNTL if needed */ if (REG(DC_IP_REQUEST_CNTL)) { REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl); @@ -3321,6 +3248,7 @@ void dcn401_update_writeback_sequence( struct dc_state *context, struct block_sequence_state *seq_state) { + (void)context; struct dwbc *dwb; struct mcif_wb *mcif_wb; @@ -3526,6 +3454,7 @@ void dcn401_enable_plane_sequence(struct dc *dc, struct pipe_ctx *pipe_ctx, struct dc_state *context, struct block_sequence_state *seq_state) { + (void)context; struct dce_hwseq *hws = dc->hwseq; uint32_t org_ip_request_cntl = 0; 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 new file mode 100644 index 000000000000..46f2f9833d9e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c @@ -0,0 +1,1104 @@ +// SPDX-License-Identifier: MIT +// +// Copyright 2026 Advanced Micro Devices, Inc. + +#include "dm_services.h" +#include "dm_helpers.h" +#include "core_types.h" +#include "resource.h" +#include "dccg.h" +#include "dce/dce_hwseq.h" +#include "dcn30/dcn30_cm_common.h" +#include "reg_helper.h" +#include "abm.h" +#include "hubp.h" +#include "dchubbub.h" +#include "timing_generator.h" +#include "opp.h" +#include "ipp.h" +#include "mpc.h" +#include "mcif_wb.h" +#include "dc_dmub_srv.h" +#include "link_hwss.h" +#include "dpcd_defs.h" +#include "dcn401/dcn401_hwseq.h" +#include "dcn42_hwseq.h" +#include "clk_mgr.h" +#include "dsc.h" +#include "dcn20/dcn20_optc.h" +#include "dce/dmub_hw_lock_mgr.h" +#include "dcn42/dcn42_resource.h" +#include "link_service.h" +#include "../dcn10/dcn10_hwseq.h" +#include "../dcn20/dcn20_hwseq.h" +#include "dc_state_priv.h" +#include "dc_stream_priv.h" +#include "dcn35/dcn35_hwseq.h" +#include "dcn42/dcn42_hwseq.h" +#include "dce/dmub_hw_lock_mgr.h" +#include "dio/dcn10/dcn10_dio.h" + +#define DC_LOGGER \ + ctx->logger + +#define CTX \ + hws->ctx + +#define REG(reg)\ + hws->regs->reg + +#undef FN +#define FN(reg_name, field_name) \ + hws->shifts->field_name, hws->masks->field_name + + +static void print_pg_status(struct dc *dc, const char *debug_func, const char *debug_log) +{ + if (dc->debug.enable_pg_cntl_debug_logs && dc->res_pool->pg_cntl) { + if (dc->res_pool->pg_cntl->funcs->print_pg_status) + dc->res_pool->pg_cntl->funcs->print_pg_status(dc->res_pool->pg_cntl, debug_func, debug_log); + } +} +void dcn42_init_hw(struct dc *dc) +{ + struct abm **abms = dc->res_pool->multiple_abms; + struct dce_hwseq *hws = dc->hwseq; + struct dc_bios *dcb = dc->ctx->dc_bios; + struct resource_pool *res_pool = dc->res_pool; + int i; + unsigned int edp_num; + uint32_t backlight = MAX_BACKLIGHT_LEVEL; + uint32_t user_level = MAX_BACKLIGHT_LEVEL; + bool dchub_ref_freq_changed; + int current_dchub_ref_freq = 0; + + if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->init_clocks) { + dc->clk_mgr->funcs->init_clocks(dc->clk_mgr); + + // mark dcmode limits present if any clock has distinct AC and DC values from SMU + dc->caps.dcmode_power_limits_present = dc->clk_mgr->funcs->is_dc_mode_present && + dc->clk_mgr->funcs->is_dc_mode_present(dc->clk_mgr); + } + + // Initialize the dccg + if (res_pool->dccg->funcs->dccg_init) + res_pool->dccg->funcs->dccg_init(res_pool->dccg); + + // Disable DMUB Initialization until IPS state programming is finalized + //if (!dcb->funcs->is_accelerated_mode(dcb)) { + // hws->funcs.bios_golden_init(dc); + //} + + // Set default OPTC memory power states + if (dc->debug.enable_mem_low_power.bits.optc) { + // Shutdown when unassigned and light sleep in VBLANK + REG_SET_2(ODM_MEM_PWR_CTRL3, 0, ODM_MEM_UNASSIGNED_PWR_MODE, 3, ODM_MEM_VBLANK_PWR_MODE, 1); + } + + if (dc->debug.enable_mem_low_power.bits.vga) { + // Power down VGA memory + REG_UPDATE(MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, 1); + } + + if (dc->ctx->dc_bios->fw_info_valid) { + res_pool->ref_clocks.xtalin_clock_inKhz = + dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency; + + if (res_pool->hubbub) { + (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg, + dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency, + &res_pool->ref_clocks.dccg_ref_clock_inKhz); + + current_dchub_ref_freq = res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000; + + (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub, + res_pool->ref_clocks.dccg_ref_clock_inKhz, + &res_pool->ref_clocks.dchub_ref_clock_inKhz); + } else { + // Not all ASICs have DCCG sw component + res_pool->ref_clocks.dccg_ref_clock_inKhz = + res_pool->ref_clocks.xtalin_clock_inKhz; + res_pool->ref_clocks.dchub_ref_clock_inKhz = + res_pool->ref_clocks.xtalin_clock_inKhz; + } + } else + ASSERT_CRITICAL(false); + + for (i = 0; i < dc->link_count; i++) { + /* Power up AND update implementation according to the + * required signal (which may be different from the + * default signal on connector). + */ + struct dc_link *link = dc->links[i]; + + if (link->ep_type != DISPLAY_ENDPOINT_PHY) + continue; + + link->link_enc->funcs->hw_init(link->link_enc); + + /* Check for enabled DIG to identify enabled display */ + if (link->link_enc->funcs->is_dig_enabled && + link->link_enc->funcs->is_dig_enabled(link->link_enc)) { + link->link_status.link_active = true; + link->phy_state.symclk_state = SYMCLK_ON_TX_ON; + if (link->link_enc->funcs->fec_is_active && + link->link_enc->funcs->fec_is_active(link->link_enc)) + link->fec_state = dc_link_fec_enabled; + } + } + + /* enable_power_gating_plane before dsc_pg_control because + * FORCEON = 1 with hw default value on bootup, resume from s3 + */ + if (hws->funcs.enable_power_gating_plane) + hws->funcs.enable_power_gating_plane(dc->hwseq, true); + + /* we want to turn off all dp displays before doing detection */ + dc->link_srv->blank_all_dp_displays(dc); + + /* If taking control over from VBIOS, we may want to optimize our first + * mode set, so we need to skip powering down pipes until we know which + * pipes we want to use. + * Otherwise, if taking control is not possible, we need to power + * everything down. + */ + if (dcb->funcs->is_accelerated_mode(dcb) || !dc->config.seamless_boot_edp_requested) { + /* Disable boot optimizations means power down everything including PHY, DIG, + * and OTG (i.e. the boot is not optimized because we do a full power down). + */ + if (dc->hwss.enable_accelerated_mode && dc->debug.disable_boot_optimizations) + dc->hwss.enable_accelerated_mode(dc, dc->current_state); + else + hws->funcs.init_pipes(dc, dc->current_state); + + if (dc->res_pool->hubbub->funcs->allow_self_refresh_control) + dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub, + !dc->res_pool->hubbub->ctx->dc->debug.disable_stutter); + + } + + /* In headless boot cases, DIG may be turned + * on which causes HW/SW discrepancies. + * To avoid this, power down hardware on boot + * if DIG is turned on and seamless boot not enabled + */ + if (!dc->config.seamless_boot_edp_requested) { + struct dc_link *edp_links[MAX_NUM_EDP]; + struct dc_link *edp_link; + + dc_get_edp_links(dc, edp_links, &edp_num); + if (edp_num) { + for (i = 0; i < edp_num; i++) { + edp_link = edp_links[i]; + if (edp_link->link_enc->funcs->is_dig_enabled && + edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) && + dc->hwss.edp_backlight_control && + hws->funcs.power_down && + dc->hwss.edp_power_control) { + dc->hwss.edp_backlight_control(edp_link, false); + hws->funcs.power_down(dc); + dc->hwss.edp_power_control(edp_link, false); + } + } + } else { + for (i = 0; i < dc->link_count; i++) { + struct dc_link *link = dc->links[i]; + + if (link && link->link_enc && + link->link_enc->funcs->is_dig_enabled && + link->link_enc->funcs->is_dig_enabled(link->link_enc) && + hws->funcs.power_down) { + hws->funcs.power_down(dc); + break; + } + + } + } + } + + for (i = 0; i < res_pool->audio_count; i++) { + struct audio *audio = res_pool->audios[i]; + + audio->funcs->hw_init(audio); + } + + for (i = 0; i < dc->link_count; i++) { + struct dc_link *link = dc->links[i]; + + if (link->panel_cntl) { + backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl); + user_level = link->panel_cntl->stored_backlight_registers.USER_LEVEL; + } + } + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (abms[i] != NULL && abms[i]->funcs != NULL) + abms[i]->funcs->abm_init(abms[i], backlight, user_level); + } + + /* power AFMT HDMI memory TODO: may move to dis/en output save power*/ + if (dc->res_pool->dio && dc->res_pool->dio->funcs->mem_pwr_ctrl) + dc->res_pool->dio->funcs->mem_pwr_ctrl(dc->res_pool->dio, false); + + if (!dc->debug.disable_clock_gate) { + /* enable all DCN clock gating */ + REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0); + + REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0); + } + + dcn401_setup_hpo_hw_control(hws, true); + + if (!dcb->funcs->is_accelerated_mode(dcb) && dc->res_pool->hubbub->funcs->init_watermarks) + dc->res_pool->hubbub->funcs->init_watermarks(dc->res_pool->hubbub); + + if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->notify_wm_ranges) + dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr); + + if (dc->res_pool->hubbub->funcs->force_pstate_change_control) + dc->res_pool->hubbub->funcs->force_pstate_change_control( + dc->res_pool->hubbub, false, false); + + if (dc->res_pool->hubbub->funcs->init_crb) + dc->res_pool->hubbub->funcs->init_crb(dc->res_pool->hubbub); + + if (dc->res_pool->hubbub->funcs->set_request_limit && + dc->clk_mgr && dc->clk_mgr->bw_params && + dc->config.sdpif_request_limit_words_per_umc > 0) + dc->res_pool->hubbub->funcs->set_request_limit(dc->res_pool->hubbub, + dc->clk_mgr->bw_params->num_channels, + dc->config.sdpif_request_limit_words_per_umc); + + // Get DMCUB capabilities + if (dc->ctx->dmub_srv) { + dc_dmub_srv_query_caps_cmd(dc->ctx->dmub_srv); + dc->caps.dmub_caps.psr = dc->ctx->dmub_srv->dmub->feature_caps.psr; + dc->caps.dmub_caps.mclk_sw = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver > 0; + dc->caps.dmub_caps.fams_ver = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver; + + /* sw and fw FAMS versions must match for support */ + dc->debug.fams2_config.bits.enable &= + dc->caps.dmub_caps.fams_ver == dc->debug.fams_version.ver; + dchub_ref_freq_changed = + res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000 != current_dchub_ref_freq; + + if ((!dc->debug.fams2_config.bits.enable || dchub_ref_freq_changed) && + dc->res_pool->funcs->update_bw_bounding_box && + dc->clk_mgr && dc->clk_mgr->bw_params) { + /* update bounding box if FAMS2 disabled, or if dchub clk has changed */ + dc->res_pool->funcs->update_bw_bounding_box(dc, dc->clk_mgr->bw_params); + } + } + if (dc->res_pool->pg_cntl) { + if (dc->res_pool->pg_cntl->funcs->init_pg_status) + dc->res_pool->pg_cntl->funcs->init_pg_status(dc->res_pool->pg_cntl); + } + print_pg_status(dc, __func__, ": after init_pg_status"); +} + +void dcn42_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx) +{ + struct hubp *hubp = pipe_ctx->plane_res.hubp; + struct mpcc_blnd_cfg blnd_cfg = {0}; + bool per_pixel_alpha = pipe_ctx->plane_state->per_pixel_alpha; + int mpcc_id; + struct mpcc *new_mpcc; + struct mpc *mpc = dc->res_pool->mpc; + struct mpc_tree *mpc_tree_params = &(pipe_ctx->stream_res.opp->mpc_tree_params); + + + blnd_cfg.overlap_only = false; + blnd_cfg.global_gain = 0xfff; + + if (per_pixel_alpha) { + blnd_cfg.pre_multiplied_alpha = pipe_ctx->plane_state->pre_multiplied_alpha; + if (pipe_ctx->plane_state->global_alpha) { + blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA_COMBINED_GLOBAL_GAIN; + blnd_cfg.global_gain = pipe_ctx->plane_state->global_alpha_value; + } else { + blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA; + } + } else { + blnd_cfg.pre_multiplied_alpha = false; + blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA; + } + + if (pipe_ctx->plane_state->global_alpha) + blnd_cfg.global_alpha = pipe_ctx->plane_state->global_alpha_value; + else + blnd_cfg.global_alpha = 0xfff; + + blnd_cfg.background_color_bpc = 4; + blnd_cfg.bottom_gain_mode = 0; + blnd_cfg.top_gain = 0x1f000; + blnd_cfg.bottom_inside_gain = 0x1f000; + blnd_cfg.bottom_outside_gain = 0x1f000; + + if (pipe_ctx->plane_state->format + == SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA) + blnd_cfg.pre_multiplied_alpha = false; + + /* + * TODO: remove hack + * Note: currently there is a bug in init_hw such that + * on resume from hibernate, BIOS sets up MPCC0, and + * we do mpcc_remove but the mpcc cannot go to idle + * after remove. This cause us to pick mpcc1 here, + * which causes a pstate hang for yet unknown reason. + */ + mpcc_id = hubp->inst; + + /* If there is no full update, don't need to touch MPC tree*/ + if (!pipe_ctx->plane_state->update_flags.bits.full_update && + !pipe_ctx->update_flags.bits.mpcc) { + mpc->funcs->update_blending(mpc, &blnd_cfg, mpcc_id); + dc->hwss.update_visual_confirm_color(dc, pipe_ctx, mpcc_id); + return; + } + + /* check if this MPCC is already being used */ + new_mpcc = mpc->funcs->get_mpcc_for_dpp(mpc_tree_params, mpcc_id); + /* remove MPCC if being used */ + if (new_mpcc != NULL) + mpc->funcs->remove_mpcc(mpc, mpc_tree_params, new_mpcc); + else + if (dc->debug.sanity_checks) + mpc->funcs->assert_mpcc_idle_before_connect( + dc->res_pool->mpc, mpcc_id); + + /* Call MPC to insert new plane */ + new_mpcc = mpc->funcs->insert_plane(dc->res_pool->mpc, + mpc_tree_params, + &blnd_cfg, + NULL, + NULL, + hubp->inst, + mpcc_id); + dc->hwss.update_visual_confirm_color(dc, pipe_ctx, mpcc_id); + + ASSERT(new_mpcc != NULL); + hubp->opp_id = pipe_ctx->stream_res.opp->inst; + hubp->mpcc_id = mpcc_id; +} + +void dcn42_program_cm_hist( + struct dc *dc, + struct pipe_ctx *pipe_ctx, + const struct dc_plane_state *plane_state) +{ + (void)dc; + struct dpp *dpp = pipe_ctx->plane_res.dpp; + + if (dpp && dpp->funcs->dpp_cm_hist_control) + dpp->funcs->dpp_cm_hist_control(dpp, + plane_state->cm_hist_control, plane_state->color_space); +} + +static bool dc_is_rmcm_3dlut_supported(struct hubp *hubp, struct mpc *mpc) +{ + if (mpc->funcs->rmcm.power_on_shaper_3dlut && + mpc->funcs->rmcm.fl_3dlut_configure && + hubp->funcs->hubp_program_3dlut_fl_config) + return true; + + return false; +} + +bool dcn42_program_rmcm_luts( + struct hubp *hubp, + struct pipe_ctx *pipe_ctx, + const struct dc_plane_cm *cm, + struct mpc *mpc, + int mpcc_id) +{ + struct dpp *dpp_base = pipe_ctx->plane_res.dpp; + union mcm_lut_params m_lut_params = {0}; + + struct dc *dc = hubp->ctx->dc; + struct mpc_fl_3dlut_config mpc_fl_config; + + struct dc_stream_state *stream = pipe_ctx->stream; + bool bypass_rmcm_shaper = false; + // 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; + + /* Shaper */ + if (cm->flags.bits.shaper_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) { + ASSERT(false); + cm_helper_translate_curve_to_hw_format( + dc->ctx, + &cm->shaper_func, + &dpp_base->shaper_params, true); + m_lut_params.pwl = &dpp_base->shaper_params; + } + if (m_lut_params.pwl) { + if (mpc->funcs->rmcm.populate_lut) + mpc->funcs->rmcm.populate_lut(mpc, m_lut_params, lut_bank_a, mpcc_id); + if (mpc->funcs->rmcm.program_lut_mode) + mpc->funcs->rmcm.program_lut_mode(mpc, !bypass_rmcm_shaper, lut_bank_a, mpcc_id); + } else { + //RMCM 3dlut won't work without its shaper + return false; + } + } + + /* 3DLUT */ + if (!cm->flags.bits.lut3d_dma_enable) { + 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)) + return false; + + //seems to be only for the MCM + mpc_fl_config.enabled = cm->flags.bits.lut3d_enable; + mpc_fl_config.size = cm->lut3d_dma.size; + mpc_fl_config.select_lut_bank_a = lut_bank_a; + mpc_fl_config.bit_depth = 0; + mpc_fl_config.hubp_index = hubp->inst; + mpc_fl_config.bias = cm->lut3d_dma.bias; + mpc_fl_config.scale = cm->lut3d_dma.scale; + + //1. power down the block + mpc->funcs->rmcm.power_on_shaper_3dlut(mpc, mpcc_id, false); + + //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); + + //3. power on the block + mpc->funcs->rmcm.power_on_shaper_3dlut(mpc, mpcc_id, true); + } + + return true; +} + +bool dcn42_set_mcm_luts(struct pipe_ctx *pipe_ctx, + const struct dc_plane_state *plane_state) +{ + struct dc *dc = pipe_ctx->plane_res.hubp->ctx->dc; + 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 */ + dcn42_program_rmcm_luts( + hubp, + pipe_ctx, + cm, + mpc, + mpcc_id); + } + + return result; +} +void dcn42_hardware_release(struct dc *dc) +{ + dcn35_hardware_release(dc); + +} +static int count_active_streams(const struct dc *dc) +{ + int i, count = 0; + + for (i = 0; i < dc->current_state->stream_count; ++i) { + struct dc_stream_state *stream = dc->current_state->streams[i]; + + if (stream && (!stream->dpms_off || dc->config.disable_ips_in_dpms_off)) + count += 1; + } + + return count; +} + +void dcn42_calc_blocks_to_gate(struct dc *dc, struct dc_state *context, + struct pg_block_update *update_state) +{ + bool hpo_frl_stream_enc_acquired = false; + bool hpo_dp_stream_enc_acquired = false; + int i = 0, j = 0; + + memset(update_state, 0, sizeof(struct pg_block_update)); + + update_state->pg_res_update[PG_DIO] = true; + + for (i = 0; i < dc->res_pool->hpo_dp_stream_enc_count; i++) { + if (context->res_ctx.is_hpo_dp_stream_enc_acquired[i] && + dc->res_pool->hpo_dp_stream_enc[i]) { + hpo_dp_stream_enc_acquired = true; + break; + } + } + + if (!hpo_frl_stream_enc_acquired && !hpo_dp_stream_enc_acquired) + update_state->pg_res_update[PG_HPO] = true; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + for (j = 0; j < PG_HW_PIPE_RESOURCES_NUM_ELEMENT; j++) + update_state->pg_pipe_res_update[j][i] = true; + + if (!pipe_ctx) + continue; + + if (pipe_ctx->plane_res.hubp) + update_state->pg_pipe_res_update[PG_HUBP][pipe_ctx->plane_res.hubp->inst] = false; + + if (pipe_ctx->plane_res.dpp && pipe_ctx->plane_res.hubp) + update_state->pg_pipe_res_update[PG_DPP][pipe_ctx->plane_res.hubp->inst] = false; + + if (pipe_ctx->plane_res.dpp || pipe_ctx->stream_res.opp) + update_state->pg_pipe_res_update[PG_MPCC][pipe_ctx->plane_res.mpcc_inst] = false; + + if (pipe_ctx->stream_res.dsc) { + update_state->pg_pipe_res_update[PG_DSC][pipe_ctx->stream_res.dsc->inst] = false; + if (dc->caps.sequential_ono) { + update_state->pg_pipe_res_update[PG_HUBP][pipe_ctx->stream_res.dsc->inst] = false; + update_state->pg_pipe_res_update[PG_DPP][pipe_ctx->stream_res.dsc->inst] = false; + } + } + if (pipe_ctx->stream_res.opp) + update_state->pg_pipe_res_update[PG_OPP][pipe_ctx->stream_res.opp->inst] = false; + + if (pipe_ctx->stream_res.hpo_dp_stream_enc) + update_state->pg_pipe_res_update[PG_DPSTREAM][pipe_ctx->stream_res.hpo_dp_stream_enc->inst] = false; + + if (pipe_ctx->link_res.dio_link_enc) { + update_state->pg_res_update[PG_DIO] = false; + } + if (pipe_ctx->link_res.hpo_dp_link_enc) { + update_state->pg_res_update[PG_HPO] = false; + } + } + + + for (i = 0; i < dc->link_count; i++) { + update_state->pg_pipe_res_update[PG_PHYSYMCLK][dc->links[i]->link_enc_hw_inst] = true; + if (dc->links[i]->type != dc_connection_none) + update_state->pg_pipe_res_update[PG_PHYSYMCLK][dc->links[i]->link_enc_hw_inst] = false; + } + + /*domain24 controls all the otg, mpc, opp, as long as one otg is still up, avoid enabling OTG PG*/ + for (i = 0; i < dc->res_pool->timing_generator_count; i++) { + struct timing_generator *tg = dc->res_pool->timing_generators[i]; + if (tg && tg->funcs->is_tg_enabled(tg)) { + update_state->pg_pipe_res_update[PG_OPTC][i] = false; + } else { + // Update pg_pipe_res_enable state + if (dc->res_pool->pg_cntl->funcs->optc_pg_control) + dc->res_pool->pg_cntl->funcs->optc_pg_control(dc->res_pool->pg_cntl, i, false); + } + } + +} + +void dcn42_prepare_bandwidth( + struct dc *dc, + struct dc_state *context) +{ + + struct pg_block_update pg_update_state; + + if (dc->hwss.calc_blocks_to_ungate) { + dc->hwss.calc_blocks_to_ungate(dc, context, &pg_update_state); + + if (dc->hwss.root_clock_control) + dc->hwss.root_clock_control(dc, &pg_update_state, true); + /*power up required HW block*/ + if (dc->hwss.hw_block_power_up) + dc->hwss.hw_block_power_up(dc, &pg_update_state); + } + + dcn401_prepare_bandwidth(dc, context); +} + +void dcn42_optimize_bandwidth(struct dc *dc, struct dc_state *context) +{ + struct pg_block_update pg_update_state; + + print_pg_status(dc, __func__, ": before rcg and power up"); + + dcn401_optimize_bandwidth(dc, context); + + if (dc->hwss.calc_blocks_to_gate) { + dc->hwss.calc_blocks_to_gate(dc, context, &pg_update_state); + /*try to power down unused block*/ + if (dc->hwss.hw_block_power_down) + dc->hwss.hw_block_power_down(dc, &pg_update_state); + + if (dc->hwss.root_clock_control) + dc->hwss.root_clock_control(dc, &pg_update_state, false); + } + + print_pg_status(dc, __func__, ": after rcg and power up"); + +} + +void dcn42_calc_blocks_to_ungate(struct dc *dc, struct dc_state *context, + struct pg_block_update *update_state) +{ + bool hpo_dp_stream_enc_acquired = false; + int i = 0, j = 0; + + memset(update_state, 0, sizeof(struct pg_block_update)); + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *cur_pipe = &dc->current_state->res_ctx.pipe_ctx[i]; + struct pipe_ctx *new_pipe = &context->res_ctx.pipe_ctx[i]; + + if (cur_pipe == NULL || new_pipe == NULL) + continue; + + if ((!cur_pipe->plane_state && new_pipe->plane_state) || + (!cur_pipe->stream && new_pipe->stream) || + (cur_pipe->stream != new_pipe->stream && new_pipe->stream)) { + // New pipe addition + for (j = 0; j < PG_HW_PIPE_RESOURCES_NUM_ELEMENT; j++) { + if (j == PG_HUBP && new_pipe->plane_res.hubp) + update_state->pg_pipe_res_update[j][new_pipe->plane_res.hubp->inst] = true; + + if (j == PG_DPP && new_pipe->plane_res.dpp) + update_state->pg_pipe_res_update[j][new_pipe->plane_res.dpp->inst] = true; + + if (j == PG_MPCC && new_pipe->plane_res.dpp) + update_state->pg_pipe_res_update[j][new_pipe->plane_res.mpcc_inst] = true; + + if (j == PG_DSC && new_pipe->stream_res.dsc) + update_state->pg_pipe_res_update[j][new_pipe->stream_res.dsc->inst] = true; + + if (j == PG_OPP && new_pipe->stream_res.opp) + update_state->pg_pipe_res_update[j][new_pipe->stream_res.opp->inst] = true; + + if (j == PG_OPTC && new_pipe->stream_res.tg) + update_state->pg_pipe_res_update[j][new_pipe->stream_res.tg->inst] = true; + + if (j == PG_DPSTREAM && new_pipe->stream_res.hpo_dp_stream_enc) + update_state->pg_pipe_res_update[j][new_pipe->stream_res.hpo_dp_stream_enc->inst] = true; + } + } else if (cur_pipe->plane_state == new_pipe->plane_state || + cur_pipe == new_pipe) { + //unchanged pipes + for (j = 0; j < PG_HW_PIPE_RESOURCES_NUM_ELEMENT; j++) { + if (j == PG_HUBP && + cur_pipe->plane_res.hubp != new_pipe->plane_res.hubp && + new_pipe->plane_res.hubp) + update_state->pg_pipe_res_update[j][new_pipe->plane_res.hubp->inst] = true; + + if (j == PG_DPP && + cur_pipe->plane_res.dpp != new_pipe->plane_res.dpp && + new_pipe->plane_res.dpp) + update_state->pg_pipe_res_update[j][new_pipe->plane_res.dpp->inst] = true; + + if (j == PG_OPP && + cur_pipe->stream_res.opp != new_pipe->stream_res.opp && + new_pipe->stream_res.opp) + update_state->pg_pipe_res_update[j][new_pipe->stream_res.opp->inst] = true; + + if (j == PG_DSC && + cur_pipe->stream_res.dsc != new_pipe->stream_res.dsc && + new_pipe->stream_res.dsc) + update_state->pg_pipe_res_update[j][new_pipe->stream_res.dsc->inst] = true; + + if (j == PG_OPTC && + cur_pipe->stream_res.tg != new_pipe->stream_res.tg && + new_pipe->stream_res.tg) + update_state->pg_pipe_res_update[j][new_pipe->stream_res.tg->inst] = true; + + if (j == PG_DPSTREAM && + cur_pipe->stream_res.hpo_dp_stream_enc != new_pipe->stream_res.hpo_dp_stream_enc && + new_pipe->stream_res.hpo_dp_stream_enc) + update_state->pg_pipe_res_update[j][new_pipe->stream_res.hpo_dp_stream_enc->inst] = true; + } + } + } + + for (i = 0; i < dc->link_count; i++) + if (dc->links[i]->type != dc_connection_none) + update_state->pg_pipe_res_update[PG_PHYSYMCLK][dc->links[i]->link_enc_hw_inst] = true; + + for (i = 0; i < dc->res_pool->stream_enc_count; i++) { + if (dc->current_state->res_ctx.is_stream_enc_acquired[i]) { + update_state->pg_res_update[PG_DIO] = true; + break; + } + } + for (i = 0; i < dc->res_pool->hpo_dp_stream_enc_count; i++) { + if (context->res_ctx.is_hpo_dp_stream_enc_acquired[i] && + dc->res_pool->hpo_dp_stream_enc[i]) { + hpo_dp_stream_enc_acquired = true; + break; + } + } + + if (hpo_dp_stream_enc_acquired) + update_state->pg_res_update[PG_HPO] = true; + + if (count_active_streams(dc) > 0) { + update_state->pg_res_update[PG_DCCG] = true; + update_state->pg_res_update[PG_DCIO] = true; + update_state->pg_res_update[PG_DCHUBBUB] = true; + update_state->pg_res_update[PG_DCHVM] = true; + update_state->pg_res_update[PG_DCOH] = true; + } +} +/** + * dcn42_hw_block_power_down() - power down sequence + * + * The following sequence describes the ON-OFF (ONO) for power down: + * + * ONO Region 4, DCPG 25: hpo + * ONO Region 11, DCPG 3: dchubp3, dpp3 + * ONO Region 9, DCPG 2: dchubp2, dpp2 + * ONO Region 7, DCPG 1: dchubp1, dpp1 + * ONO Region 5, DCPG 0: dchubp0, dpp0 + * ONO Region 2, DCPG 23: dchubbub, dchububmem, dchvm + * ONO Region 12, DCPG 19: dsc3 + * ONO Region 10, DCPG 18: dsc2 + * ONO Region 8, DCPG 17: dsc1 + * ONO Region 6, DCPG 16: dsc0 + * ONO Region 3, DCPG 24: mpc, opp, optc, dwb + * ONO Region 1, DCPG 26: dio + * ONO Region 0, DCPG 22: dccg dcio dcoh - SKIPPED + * + * No seuential ONO power up/down order for DCN42 + * Driver PG should only be limited to DCHUBP/DPP, DSC, HPO and DIO, so further optimization can be done + * + * @dc: Current DC state + * @update_state: update PG sequence states for HW block + */ + void dcn42_hw_block_power_down(struct dc *dc, + struct pg_block_update *update_state) +{ + int i = 0; + struct pg_cntl *pg_cntl = dc->res_pool->pg_cntl; + bool block_disabled = true; + + if (!pg_cntl) + return; + if (dc->debug.ignore_pg) + return; + + if (update_state->pg_res_update[PG_HPO]) { + if (pg_cntl->funcs->hpo_pg_control) + pg_cntl->funcs->hpo_pg_control(pg_cntl, false); + } + + for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) { + if (update_state->pg_pipe_res_update[PG_HUBP][i] && + update_state->pg_pipe_res_update[PG_DPP][i]) { + if (pg_cntl->funcs->hubp_dpp_pg_control) + pg_cntl->funcs->hubp_dpp_pg_control(pg_cntl, i, false); + } + } + + if (update_state->pg_res_update[PG_DCHUBBUB]) { + if (pg_cntl->funcs->mem_pg_control) + pg_cntl->funcs->mem_pg_control(pg_cntl, false); + } + + for (i = dc->res_pool->res_cap->num_dsc-1; i >= 0; i--) { + if (update_state->pg_pipe_res_update[PG_DSC][i]) { + if (pg_cntl->funcs->dsc_pg_control) + pg_cntl->funcs->dsc_pg_control(pg_cntl, i, false); + } + } + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (!update_state->pg_pipe_res_update[PG_MPCC][i] || + !update_state->pg_pipe_res_update[PG_OPP][i] || + !update_state->pg_pipe_res_update[PG_OPTC][i]) { + block_disabled = false; + break; + } + } + + if (block_disabled) { + if (pg_cntl->funcs->plane_otg_pg_control) + pg_cntl->funcs->plane_otg_pg_control(pg_cntl, false); + } + + if (update_state->pg_res_update[PG_DIO]) { + if (pg_cntl->funcs->dio_pg_control) + pg_cntl->funcs->dio_pg_control(pg_cntl, false); + } + + if (update_state->pg_res_update[PG_DCCG] && + update_state->pg_res_update[PG_DCIO] && + update_state->pg_res_update[PG_DCOH]) { + // Driver PG should not power down DCCG, DCIO, DCOH. This is handled by IPS. + if (pg_cntl->funcs->io_clk_pg_control) + pg_cntl->funcs->io_clk_pg_control(pg_cntl, false); + } +} + +/** + * dcn42_hw_block_power_up() - power up sequence + * + * The following sequence describes the ON-OFF (ONO) for power up: + * + * ONO Region 0, DCPG 22: dccg dcio dcoh + * ONO Region 1, DCPG 26: dio + * ONO Region 3, DCPG 24: mpc, opp, optc, dwb + * ONO Region 6, DCPG 16: dsc0 + * ONO Region 8, DCPG 17: dsc1 + * ONO Region 10, DCPG 18: dsc2 + * ONO Region 12, DCPG 19: dsc3 + * ONO Region 2, DCPG 23: dchubbub, dchububmem, dchvm + * ONO Region 5, DCPG 0: dchubp0, dpp0 + * ONO Region 7, DCPG 1: dchubp1, dpp1 + * ONO Region 9, DCPG 2: dchubp2, dpp2 + * ONO Region 11, DCPG 3: dchubp3, dpp3 + * ONO Region 4, DCPG 25: hpo + * + * No sequential power up/down ordering for DCN42 + * + * @dc: Current DC state + * @update_state: update PG sequence states for HW block + */ +void dcn42_hw_block_power_up(struct dc *dc, + struct pg_block_update *update_state) +{ + int i = 0; + struct pg_cntl *pg_cntl = dc->res_pool->pg_cntl; + bool block_enabled = false; + + if (!pg_cntl) + return; + if (dc->debug.ignore_pg) + return; + + if (update_state->pg_res_update[PG_DCCG] || + update_state->pg_res_update[PG_DCIO] || + update_state->pg_res_update[PG_DCOH]) { + if (pg_cntl->funcs->io_clk_pg_control) + pg_cntl->funcs->io_clk_pg_control(pg_cntl, true); + } + + if (update_state->pg_res_update[PG_DIO]) { + if (pg_cntl->funcs->dio_pg_control) + pg_cntl->funcs->dio_pg_control(pg_cntl, true); + } + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (update_state->pg_pipe_res_update[PG_MPCC][i] || + update_state->pg_pipe_res_update[PG_OPP][i] || + update_state->pg_pipe_res_update[PG_OPTC][i]) { + block_enabled = true; + break; + } + } + if (block_enabled) { + if (pg_cntl->funcs->plane_otg_pg_control) + pg_cntl->funcs->plane_otg_pg_control(pg_cntl, true); + } + + for (i = 0; i < dc->res_pool->res_cap->num_dsc; i++) { + if (update_state->pg_pipe_res_update[PG_DSC][i]) { + if (pg_cntl->funcs->dsc_pg_control) + pg_cntl->funcs->dsc_pg_control(pg_cntl, i, true); + } + } + + if (update_state->pg_res_update[PG_DCHUBBUB]) { + if (pg_cntl->funcs->mem_pg_control) + pg_cntl->funcs->mem_pg_control(pg_cntl, true); + } + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (update_state->pg_pipe_res_update[PG_HUBP][i] && + update_state->pg_pipe_res_update[PG_DPP][i]) { + if (pg_cntl->funcs->hubp_dpp_pg_control) + pg_cntl->funcs->hubp_dpp_pg_control(pg_cntl, i, true); + } + } + if (update_state->pg_res_update[PG_HPO]) { + if (pg_cntl->funcs->hpo_pg_control) + pg_cntl->funcs->hpo_pg_control(pg_cntl, true); + } +} +void dcn42_root_clock_control(struct dc *dc, + struct pg_block_update *update_state, bool power_on) +{ + int i = 0; + struct pg_cntl *pg_cntl = dc->res_pool->pg_cntl; + + if (!pg_cntl) + return; + /*enable root clock first when power up*/ + if (power_on) { + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (update_state->pg_pipe_res_update[PG_HUBP][i] && + update_state->pg_pipe_res_update[PG_DPP][i]) { + if (dc->hwseq->funcs.dpp_root_clock_control) + dc->hwseq->funcs.dpp_root_clock_control(dc->hwseq, i, power_on); + } + if (update_state->pg_pipe_res_update[PG_DPSTREAM][i]) + if (dc->hwseq->funcs.dpstream_root_clock_control) + dc->hwseq->funcs.dpstream_root_clock_control(dc->hwseq, i, power_on); + } + + for (i = 0; i < dc->res_pool->dig_link_enc_count; i++) + if (update_state->pg_pipe_res_update[PG_PHYSYMCLK][i]) + if (dc->hwseq->funcs.physymclk_root_clock_control) + dc->hwseq->funcs.physymclk_root_clock_control(dc->hwseq, i, power_on); + + } + for (i = 0; i < dc->res_pool->res_cap->num_dsc; i++) { + if (update_state->pg_pipe_res_update[PG_DSC][i]) { + if (power_on) { + if (dc->res_pool->dccg->funcs->enable_dsc) + dc->res_pool->dccg->funcs->enable_dsc(dc->res_pool->dccg, i); + } else { + if (dc->res_pool->dccg->funcs->disable_dsc) + dc->res_pool->dccg->funcs->disable_dsc(dc->res_pool->dccg, i); + } + } + } + /*disable root clock first when power down*/ + if (!power_on) { + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (update_state->pg_pipe_res_update[PG_HUBP][i] && + update_state->pg_pipe_res_update[PG_DPP][i]) { + if (dc->hwseq->funcs.dpp_root_clock_control) + dc->hwseq->funcs.dpp_root_clock_control(dc->hwseq, i, power_on); + } + if (update_state->pg_pipe_res_update[PG_DPSTREAM][i]) + if (dc->hwseq->funcs.dpstream_root_clock_control) + dc->hwseq->funcs.dpstream_root_clock_control(dc->hwseq, i, power_on); + } + + for (i = 0; i < dc->res_pool->dig_link_enc_count; i++) + if (update_state->pg_pipe_res_update[PG_PHYSYMCLK][i]) + if (dc->hwseq->funcs.physymclk_root_clock_control) + dc->hwseq->funcs.physymclk_root_clock_control(dc->hwseq, i, power_on); + + } +} +void dcn42_setup_stereo(struct pipe_ctx *pipe_ctx, struct dc *dc) +{ + (void)dc; + struct crtc_stereo_flags flags = { 0 }; + struct dc_stream_state *stream = pipe_ctx->stream; + + dcn10_config_stereo_parameters(stream, &flags); + + pipe_ctx->stream_res.opp->funcs->opp_program_stereo( + pipe_ctx->stream_res.opp, + flags.PROGRAM_STEREO == 1, + &stream->timing); + + pipe_ctx->stream_res.tg->funcs->program_stereo( + pipe_ctx->stream_res.tg, + &stream->timing, + &flags); + + return; +} +void dcn42_dmub_hw_control_lock(struct dc *dc, struct dc_state *context, bool lock) +{ + + union dmub_inbox0_cmd_lock_hw hw_lock_cmd = { 0 }; + + if (!dc->ctx || !dc->ctx->dmub_srv) + return; + + /* Use helper to check PSR/Replay for all streams in context */ + + if (!dc->debug.fams2_config.bits.enable && !dc_dmub_srv_is_cursor_offload_enabled(dc) + && !dmub_hw_lock_mgr_does_context_require_lock(dc, context)) + return; + + hw_lock_cmd.bits.command_code = DMUB_INBOX0_CMD__HW_LOCK; + hw_lock_cmd.bits.hw_lock_client = HW_LOCK_CLIENT_DRIVER; + hw_lock_cmd.bits.lock = lock; + hw_lock_cmd.bits.should_release = !lock; + dmub_hw_lock_mgr_inbox0_cmd(dc->ctx->dmub_srv, hw_lock_cmd); +} + +void dcn42_dmub_hw_control_lock_fast(union block_sequence_params *params) +{ + struct dc *dc = params->dmub_hw_control_lock_fast_params.dc; + bool lock = params->dmub_hw_control_lock_fast_params.lock; + + /* Use helper to check PSR/Replay for the given stream in fast path */ + if (params->dmub_hw_control_lock_fast_params.is_required) { + union dmub_inbox0_cmd_lock_hw hw_lock_cmd = { 0 }; + hw_lock_cmd.bits.command_code = DMUB_INBOX0_CMD__HW_LOCK; + hw_lock_cmd.bits.hw_lock_client = HW_LOCK_CLIENT_DRIVER; + hw_lock_cmd.bits.lock = lock; + hw_lock_cmd.bits.should_release = !lock; + dmub_hw_lock_mgr_inbox0_cmd(dc->ctx->dmub_srv, hw_lock_cmd); + } +} + +/* In headless boot cases, DIG may be turned + * on which causes HW/SW discrepancies. + * To avoid this, power down hardware on boot + * if DIG is turned on + */ +void dcn42_power_down_on_boot(struct dc *dc) +{ + struct dc_link *edp_links[MAX_NUM_EDP]; + struct dc_link *edp_link = NULL; + unsigned int edp_num; + int i = 0; + + dc_get_edp_links(dc, edp_links, &edp_num); + if (edp_num) + edp_link = edp_links[0]; + + if (edp_link && edp_link->link_enc->funcs->is_dig_enabled && + edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) && + dc->hwseq->funcs.edp_backlight_control && + dc->hwseq->funcs.power_down && + dc->hwss.edp_power_control) { + dc->hwseq->funcs.edp_backlight_control(edp_link, false); + dc->hwseq->funcs.power_down(dc); + dc->hwss.edp_power_control(edp_link, false); + } else { + for (i = 0; i < dc->link_count; i++) { + struct dc_link *link = dc->links[i]; + + if (link->link_enc && link->link_enc->funcs->is_dig_enabled && + link->link_enc->funcs->is_dig_enabled(link->link_enc) && + dc->hwseq->funcs.power_down) { + dc->hwseq->funcs.power_down(dc); + break; + } + + } + } + + /* + * Call update_clocks with empty context + * to send DISPLAY_OFF + * Otherwise DISPLAY_OFF may not be asserted + */ + if (dc->clk_mgr->funcs->set_low_power_state) + dc->clk_mgr->funcs->set_low_power_state(dc->clk_mgr); +} 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 new file mode 100644 index 000000000000..c4cfeed45b19 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright 2026 Advanced Micro Devices, Inc. */ + +#ifndef __DC_HWSS_DCN42_H__ +#define __DC_HWSS_DCN42_H__ + +#include "dc.h" +#include "hw_sequencer_private.h" + +void dcn42_init_hw(struct dc *dc); +void dcn42_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx); + +void dcn42_program_cm_hist( + struct dc *dc, + struct pipe_ctx *pipe_ctx, + const struct dc_plane_state *plane_state); + +bool dcn42_set_mcm_luts(struct pipe_ctx *pipe_ctx, + const struct dc_plane_state *plane_state); + +bool dcn42_program_rmcm_luts( + struct hubp *hubp, + struct pipe_ctx *pipe_ctx, + const struct dc_plane_cm *cm, + struct mpc *mpc, + int mpcc_id); +void dcn42_hardware_release(struct dc *dc); + +void dcn42_prepare_bandwidth( + struct dc *dc, + struct dc_state *context); +void dcn42_optimize_bandwidth(struct dc *dc, struct dc_state *context); +void dcn42_calc_blocks_to_gate(struct dc *dc, struct dc_state *context, + struct pg_block_update *update_state); +void dcn42_calc_blocks_to_ungate(struct dc *dc, struct dc_state *context, + struct pg_block_update *update_state); +void dcn42_hw_block_power_down(struct dc *dc, + struct pg_block_update *update_state); +void dcn42_hw_block_power_up(struct dc *dc, + struct pg_block_update *update_state); +void dcn42_root_clock_control(struct dc *dc, + struct pg_block_update *update_state, bool power_on); +void dcn42_dmub_hw_control_lock(struct dc *dc, struct dc_state *context, bool lock); +void dcn42_dmub_hw_control_lock_fast(union block_sequence_params *params); +void dcn42_setup_stereo(struct pipe_ctx *pipe_ctx, struct dc *dc); +void dcn42_power_down_on_boot(struct dc *dc); +#endif diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.c new file mode 100644 index 000000000000..b324a2195e8a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.c @@ -0,0 +1,173 @@ +// SPDX-License-Identifier: MIT +// +// Copyright 2026 Advanced Micro Devices, Inc. + +#include "dce110/dce110_hwseq.h" +#include "dcn10/dcn10_hwseq.h" +#include "dcn20/dcn20_hwseq.h" +#include "dcn21/dcn21_hwseq.h" +#include "dcn30/dcn30_hwseq.h" +#include "dcn31/dcn31_hwseq.h" +#include "dcn32/dcn32_hwseq.h" +#include "dcn314/dcn314_hwseq.h" +#include "dcn35/dcn35_hwseq.h" +#include "dcn401/dcn401_hwseq.h" +#include "dcn42/dcn42_hwseq.h" +#include "dcn42_init.h" + +static const struct hw_sequencer_funcs dcn42_funcs = { + .program_gamut_remap = dcn401_program_gamut_remap, + .init_hw = dcn42_init_hw, + .apply_ctx_to_hw = dce110_apply_ctx_to_hw, + .power_down_on_boot = dcn42_power_down_on_boot, + .apply_ctx_for_surface = NULL, + .program_front_end_for_ctx = dcn401_program_front_end_for_ctx, + .clear_surface_dcc_and_tiling = dcn10_reset_surface_dcc_and_tiling, + .wait_for_pending_cleared = dcn10_wait_for_pending_cleared, + .post_unlock_program_front_end = dcn401_post_unlock_program_front_end, + .update_plane_addr = dcn20_update_plane_addr, + .update_dchub = dcn10_update_dchub, + .update_pending_status = dcn10_update_pending_status, + .program_output_csc = dcn20_program_output_csc, + .trigger_3dlut_dma_load = dcn401_trigger_3dlut_dma_load, + .enable_accelerated_mode = dce110_enable_accelerated_mode, + .enable_timing_synchronization = dcn10_enable_timing_synchronization, + .enable_per_frame_crtc_position_reset = dcn10_enable_per_frame_crtc_position_reset, + .update_info_frame = dcn31_update_info_frame, + .send_immediate_sdp_message = dcn10_send_immediate_sdp_message, + .enable_stream = dcn401_enable_stream, + .disable_stream = dce110_disable_stream, + .unblank_stream = dcn401_unblank_stream, + .blank_stream = dce110_blank_stream, + .enable_audio_stream = dce110_enable_audio_stream, + .disable_audio_stream = dce110_disable_audio_stream, + .disable_plane = dcn35_disable_plane, + .pipe_control_lock = dcn20_pipe_control_lock, + .interdependent_update_lock = dcn401_interdependent_update_lock, + .cursor_lock = dcn10_cursor_lock, + .prepare_bandwidth = dcn42_prepare_bandwidth, + .optimize_bandwidth = dcn42_optimize_bandwidth, + .update_bandwidth = dcn401_update_bandwidth, + .set_drr = dcn35_set_drr, + .get_position = dcn10_get_position, + .set_static_screen_control = dcn35_set_static_screen_control, + .setup_stereo = dcn42_setup_stereo, + .set_avmute = dcn30_set_avmute, + .log_hw_state = dcn10_log_hw_state, + .get_hw_state = dcn10_get_hw_state, + .clear_status_bits = dcn10_clear_status_bits, + .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect, + .edp_backlight_control = dce110_edp_backlight_control, + .edp_power_control = dce110_edp_power_control, + .edp_wait_for_hpd_ready = dce110_edp_wait_for_hpd_ready, + .edp_wait_for_T12 = dce110_edp_wait_for_T12, + .set_cursor_position = dcn401_set_cursor_position, + .set_cursor_attribute = dcn10_set_cursor_attribute, + .set_cursor_sdr_white_level = dcn10_set_cursor_sdr_white_level, + .abort_cursor_offload_update = dcn35_abort_cursor_offload_update, + .begin_cursor_offload_update = dcn35_begin_cursor_offload_update, + .commit_cursor_offload_update = dcn35_commit_cursor_offload_update, + .update_cursor_offload_pipe = dcn401_update_cursor_offload_pipe, + .notify_cursor_offload_drr_update = dcn35_notify_cursor_offload_drr_update, + .program_cursor_offload_now = dcn35_program_cursor_offload_now, + .setup_periodic_interrupt = dcn10_setup_periodic_interrupt, + .set_clock = dcn10_set_clock, + .get_clock = dcn10_get_clock, + .program_triplebuffer = dcn20_program_triple_buffer, + .enable_writeback = dcn30_enable_writeback, + .disable_writeback = dcn30_disable_writeback, + .update_writeback = dcn30_update_writeback, + .dmdata_status_done = dcn20_dmdata_status_done, + .program_dmdata_engine = dcn30_program_dmdata_engine, + .set_dmdata_attributes = dcn20_set_dmdata_attributes, + .init_sys_ctx = dcn31_init_sys_ctx, + .init_vm_ctx = dcn20_init_vm_ctx, + .set_flip_control_gsl = dcn20_set_flip_control_gsl, + .get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync, + .calc_vupdate_position = dcn10_calc_vupdate_position, + .apply_idle_power_optimizations = dcn35_apply_idle_power_optimizations, + .does_plane_fit_in_mall = NULL, + .set_backlight_level = dcn31_set_backlight_level, + .set_abm_immediate_disable = dcn21_set_abm_immediate_disable, + .hardware_release = dcn42_hardware_release, + .set_pipe = dcn21_set_pipe, + .enable_lvds_link_output = dce110_enable_lvds_link_output, + .enable_tmds_link_output = dce110_enable_tmds_link_output, + .enable_dp_link_output = dce110_enable_dp_link_output, + .disable_link_output = dcn401_disable_link_output, + .set_disp_pattern_generator = dcn30_set_disp_pattern_generator, + .optimize_pwr_state = dcn21_optimize_pwr_state, + .exit_optimized_pwr_state = dcn21_exit_optimized_pwr_state, + .get_dcc_en_bits = dcn10_get_dcc_en_bits, + .enable_phantom_streams = dcn32_enable_phantom_streams, + .disable_phantom_streams = dcn32_disable_phantom_streams, + .update_visual_confirm_color = dcn10_update_visual_confirm_color, + .update_phantom_vp_position = dcn32_update_phantom_vp_position, + .apply_update_flags_for_phantom = dcn32_apply_update_flags_for_phantom, + .wait_for_dcc_meta_propagation = dcn401_wait_for_dcc_meta_propagation, + .is_pipe_topology_transition_seamless = dcn32_is_pipe_topology_transition_seamless, + .dmub_hw_control_lock = dcn42_dmub_hw_control_lock, + .fams2_update_config = dcn401_fams2_update_config, + .dmub_hw_control_lock_fast = dcn42_dmub_hw_control_lock_fast, + .program_outstanding_updates = dcn401_program_outstanding_updates, + .wait_for_all_pending_updates = dcn30_wait_for_all_pending_updates, + .detect_pipe_changes = dcn401_detect_pipe_changes, + .enable_plane = dcn35_enable_plane, + .update_dchubp_dpp = dcn20_update_dchubp_dpp, + .post_unlock_reset_opp = dcn20_post_unlock_reset_opp, + .get_underflow_debug_data = dcn30_get_underflow_debug_data, + // Driver PG + .hw_block_power_up = dcn42_hw_block_power_up, + .hw_block_power_down = dcn42_hw_block_power_down, + .root_clock_control = dcn42_root_clock_control, + .calc_blocks_to_gate = dcn42_calc_blocks_to_gate, + .calc_blocks_to_ungate = dcn42_calc_blocks_to_ungate, + +}; + +static const struct hwseq_private_funcs dcn42_private_funcs = { + .init_pipes = dcn35_init_pipes, + .plane_atomic_disconnect = dcn10_plane_atomic_disconnect, + .update_mpcc = dcn42_update_mpcc, + .set_input_transfer_func = dcn32_set_input_transfer_func, + .set_output_transfer_func = dcn401_set_output_transfer_func, + .power_down = dce110_power_down, + .enable_display_power_gating = dcn10_dummy_display_power_gating, + .blank_pixel_data = dcn20_blank_pixel_data, + .reset_hw_ctx_wrap = dcn401_reset_hw_ctx_wrap, + .enable_stream_timing = dcn401_enable_stream_timing, + .edp_backlight_control = dce110_edp_backlight_control, + .setup_vupdate_interrupt = dcn20_setup_vupdate_interrupt, + .did_underflow_occur = dcn10_did_underflow_occur, + .init_blank = dcn32_init_blank, + .disable_vga = dcn20_disable_vga, + .bios_golden_init = dcn10_bios_golden_init, + .plane_atomic_disable = dcn35_plane_atomic_disable, + .program_all_writeback_pipes_in_tree = dcn30_program_all_writeback_pipes_in_tree, + .update_odm = dcn401_update_odm, + .dsc_pg_status = dcn32_dsc_pg_status, + .set_hdr_multiplier = dcn10_set_hdr_multiplier, + .wait_for_blank_complete = dcn20_wait_for_blank_complete, + .set_mcm_luts = dcn42_set_mcm_luts, + .program_mall_pipe_config = dcn32_program_mall_pipe_config, + .update_mall_sel = dcn32_update_mall_sel, + .calculate_dccg_k1_k2_values = NULL, + .apply_single_controller_ctx_to_hw = dce110_apply_single_controller_ctx_to_hw, + .reset_back_end_for_pipe = dcn401_reset_back_end_for_pipe, + .populate_mcm_luts = NULL, + .perform_3dlut_wa_unlock = dcn401_perform_3dlut_wa_unlock, + .program_cm_hist = dcn42_program_cm_hist, + .dpp_root_clock_control = dcn35_dpp_root_clock_control, + .dpstream_root_clock_control = dcn35_dpstream_root_clock_control, + .physymclk_root_clock_control = dcn35_physymclk_root_clock_control, + .resync_fifo_dccg_dio = dcn314_resync_fifo_dccg_dio, + .wait_for_pipe_update_if_needed = dcn10_wait_for_pipe_update_if_needed, + .set_wait_for_update_needed_for_pipe = dcn10_set_wait_for_update_needed_for_pipe, +}; + +void dcn42_hw_sequencer_init_functions(struct dc *dc) +{ + dc->hwss = dcn42_funcs; + dc->hwseq->funcs = dcn42_private_funcs; + +} diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.h new file mode 100644 index 000000000000..f66eb752eeeb --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright 2026 Advanced Micro Devices, Inc. */ + +#ifndef __DC_DCN42_INIT_H__ +#define __DC_DCN42_INIT_H__ + +struct dc; + +void dcn42_hw_sequencer_init_functions(struct dc *dc); + +#endif /* __DC_DCN401_INIT_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h index 4632a5761b16..d1dba7ffcd9b 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h @@ -1,5 +1,5 @@ /* - * Copyright 2015 Advanced Micro Devices, Inc. + * Copyright 2015-2026 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -174,6 +174,12 @@ struct program_mcache_id_and_split_coordinate { struct dml2_hubp_pipe_mcache_regs *mcache_regs; }; +struct control_cm_hist_params { + struct dpp *dpp; + struct cm_hist_control cm_hist_control; + enum dc_color_space color_space; +}; + struct program_cursor_update_now_params { struct dc *dc; struct pipe_ctx *pipe_ctx; @@ -755,6 +761,7 @@ union block_sequence_params { struct dmub_hw_control_lock_fast_params dmub_hw_control_lock_fast_params; struct program_surface_config_params program_surface_config_params; struct program_mcache_id_and_split_coordinate program_mcache_id_and_split_coordinate; + struct control_cm_hist_params control_cm_hist_params; struct program_cursor_update_now_params program_cursor_update_now_params; struct hubp_wait_pipe_read_start_params hubp_wait_pipe_read_start_params; struct apply_update_flags_for_phantom_params apply_update_flags_for_phantom_params; @@ -879,6 +886,7 @@ enum block_sequence_func { DMUB_HW_CONTROL_LOCK_FAST, HUBP_PROGRAM_SURFACE_CONFIG, HUBP_PROGRAM_MCACHE_ID, + DPP_PROGRAM_CM_HIST, PROGRAM_CURSOR_UPDATE_NOW, HUBP_WAIT_PIPE_READ_START, HWS_APPLY_UPDATE_FLAGS_FOR_PHANTOM, @@ -1189,6 +1197,8 @@ struct hw_sequencer_funcs { void (*disable_link_output)(struct dc_link *link, const struct link_resource *link_res, enum signal_type signal); + bool (*dac_load_detect)(struct dc_link *link); + void (*prepare_ddc)(struct dc_link *link); void (*get_dcc_en_bits)(struct dc *dc, int *dcc_en_bits); @@ -1355,6 +1365,10 @@ void get_dcc_visual_confirm_color( struct pipe_ctx *pipe_ctx, struct tg_color *color); +void get_refresh_rate_confirm_color( + struct pipe_ctx *pipe_ctx, + struct tg_color *color); + void set_p_state_switch_method( struct dc *dc, struct dc_state *context, @@ -1413,6 +1427,8 @@ void hwss_program_surface_config(union block_sequence_params *params); void hwss_program_mcache_id_and_split_coordinate(union block_sequence_params *params); +void hwss_program_cm_hist(union block_sequence_params *params); + void hwss_set_odm_combine(union block_sequence_params *params); void hwss_set_odm_bypass(union block_sequence_params *params); @@ -1763,6 +1779,11 @@ void hwss_add_opp_program_bit_depth_reduction(struct block_sequence_state *seq_s bool use_default_params, struct pipe_ctx *pipe_ctx); +void hwss_add_dpp_program_cm_hist(struct block_sequence_state *seq_state, + struct dpp *dpp, + struct cm_hist_control cm_hist_control, + enum dc_color_space color_space); + void hwss_add_dc_ip_request_cntl(struct block_sequence_state *seq_state, struct dc *dc, bool enable); diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h index 406db231bc72..8e3f54fb53fd 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h @@ -1,5 +1,5 @@ /* - * Copyright 2015 Advanced Micro Devices, Inc. + * Copyright 2015-2026 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -222,6 +222,9 @@ struct hwseq_private_funcs { void (*wait_for_pipe_update_if_needed)(struct dc *dc, struct pipe_ctx *pipe_ctx, bool is_surface_update_only); void (*set_wait_for_update_needed_for_pipe)(struct dc *dc, struct pipe_ctx *pipe_ctx); void (*dc_ip_request_cntl)(struct dc *dc, bool enable); + void (*program_cm_hist)(struct dc *dc, + struct pipe_ctx *pipe_ctx, + const struct dc_plane_state *plane_state); }; struct dce_hwseq { diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 43579b0e1482..e960ca9062ad 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -214,6 +214,7 @@ struct resource_funcs { unsigned int index); void (*get_panel_config_defaults)(struct dc_panel_config *panel_config); + void (*get_default_tiling_info)(struct dc_tiling_info *tiling_info); void (*build_pipe_pix_clk_params)(struct pipe_ctx *pipe_ctx); /* * Get indicator of power from a context that went through full validation diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h index 2c9a4a12bd8a..21224fd6b36d 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h @@ -1,5 +1,6 @@ +/* SPDX-License-Identifier: MIT */ /* - * Copyright 2012-16 Advanced Micro Devices, Inc. + * Copyright 2012-2026 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -95,6 +96,26 @@ struct dcn301_clk_internal { uint32_t CLK1_CLK3_BYPASS_CNTL; //dcfclk bypass }; +struct dcn42_clk_internal { + int dummy; + uint32_t CLK8_CLK0_CURRENT_CNT; //dispclk + uint32_t CLK8_CLK1_CURRENT_CNT; //dppclk + uint32_t CLK8_CLK2_CURRENT_CNT; //dprefclk + uint32_t CLK8_CLK3_CURRENT_CNT; //dcfclk + uint32_t CLK8_CLK4_CURRENT_CNT; //dtbclk + uint32_t CLK8_CLK0_DS_CNTL; //dispclk deep_sleep_divider + uint32_t CLK8_CLK1_DS_CNTL; //dppclk deep_sleep_divider + uint32_t CLK8_CLK2_DS_CNTL; //dprefclk deep_sleep_divider + uint32_t CLK8_CLK3_DS_CNTL; //dcfclk deep_sleep_divider + uint32_t CLK8_CLK4_DS_CNTL; //dtbclk deep_sleep_divider + uint32_t CLK8_CLK0_BYPASS_CNTL; //dispclk bypass + uint32_t CLK8_CLK1_BYPASS_CNTL; //dppclk bypass + uint32_t CLK8_CLK2_BYPASS_CNTL; //dprefclk bypass + uint32_t CLK8_CLK3_BYPASS_CNTL; //dcfclk bypass + uint32_t CLK8_CLK4_BYPASS_CNTL; //dtbclk bypass + uint32_t CLK8_CLK_TICK_CNT__TIMER_THRESHOLD; +}; + /* Will these bw structures be ASIC specific? */ #define MAX_NUM_DPM_LVL 8 @@ -194,6 +215,7 @@ struct clk_state_registers_and_bypass { uint32_t dcfclk_bypass; uint32_t dprefclk_bypass; uint32_t dispclk_bypass; + uint32_t timer_threshold; }; struct rv1_clk_internal { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h index bac8febad69a..c69ccfcebeb5 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h @@ -1,5 +1,6 @@ +/* SPDX-License-Identifier: MIT */ /* - * Copyright 2018 Advanced Micro Devices, Inc. + * Copyright 2018-2026 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -89,11 +90,6 @@ enum dentist_divider_range { .DPREFCLK_CNTL = mmDPREFCLK_CNTL, \ .DENTIST_DISPCLK_CNTL = mmDENTIST_DISPCLK_CNTL -#if defined(CONFIG_DRM_AMD_DC_SI) -#define CLK_COMMON_REG_LIST_DCE60_BASE() \ - SR(DENTIST_DISPCLK_CNTL) -#endif - #define CLK_COMMON_REG_LIST_DCN_BASE() \ SR(DENTIST_DISPCLK_CNTL) @@ -119,12 +115,6 @@ enum dentist_divider_range { CLK_SF(DPREFCLK_CNTL, DPREFCLK_SRC_SEL, mask_sh), \ CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, mask_sh) -#if defined(CONFIG_DRM_AMD_DC_SI) -#define CLK_COMMON_MASK_SH_LIST_DCE60_COMMON_BASE(mask_sh) \ - CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, mask_sh),\ - CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, mask_sh) -#endif - #define CLK_COMMON_MASK_SH_LIST_DCN_COMMON_BASE(mask_sh) \ CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, mask_sh),\ CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, mask_sh) @@ -234,6 +224,45 @@ enum dentist_divider_range { #define CLK_COMMON_MASK_SH_LIST_DCN401(mask_sh) \ CLK_COMMON_MASK_SH_LIST_DCN321(mask_sh) +#define CLK_REG_LIST_DCN42() \ + SR(DENTIST_DISPCLK_CNTL), \ + CLK_SR_DCN42(CLK8_CLK_TICK_CNT_CONFIG_REG), \ + CLK_SR_DCN42(CLK8_CLK0_CURRENT_CNT), \ + CLK_SR_DCN42(CLK8_CLK1_CURRENT_CNT), \ + CLK_SR_DCN42(CLK8_CLK2_CURRENT_CNT), \ + CLK_SR_DCN42(CLK8_CLK3_CURRENT_CNT), \ + CLK_SR_DCN42(CLK8_CLK4_CURRENT_CNT), \ + CLK_SR_DCN42(CLK8_CLK0_BYPASS_CNTL), \ + CLK_SR_DCN42(CLK8_CLK1_BYPASS_CNTL), \ + CLK_SR_DCN42(CLK8_CLK2_BYPASS_CNTL), \ + CLK_SR_DCN42(CLK8_CLK3_BYPASS_CNTL), \ + CLK_SR_DCN42(CLK8_CLK4_BYPASS_CNTL), \ + CLK_SR_DCN42(CLK8_CLK0_DS_CNTL), \ + CLK_SR_DCN42(CLK8_CLK1_DS_CNTL), \ + CLK_SR_DCN42(CLK8_CLK2_DS_CNTL), \ + CLK_SR_DCN42(CLK8_CLK3_DS_CNTL), \ + CLK_SR_DCN42(CLK8_CLK4_DS_CNTL) + +#define CLK_COMMON_MASK_SH_LIST_DCN42(mask_sh) \ + CLK_SF(CLK8_CLK_TICK_CNT_CONFIG_REG, TIMER_THRESHOLD, mask_sh), \ + CLK_SF(CLK8_CLK0_BYPASS_CNTL, CLK0_BYPASS_SEL, mask_sh), \ + CLK_SF(CLK8_CLK1_BYPASS_CNTL, CLK1_BYPASS_SEL, mask_sh), \ + CLK_SF(CLK8_CLK2_BYPASS_CNTL, CLK2_BYPASS_SEL, mask_sh), \ + CLK_SF(CLK8_CLK3_BYPASS_CNTL, CLK3_BYPASS_SEL, mask_sh), \ + CLK_SF(CLK8_CLK4_BYPASS_CNTL, CLK4_BYPASS_SEL, mask_sh), \ + CLK_SF(CLK8_CLK0_DS_CNTL, CLK0_DS_DIV_ID, mask_sh), \ + CLK_SF(CLK8_CLK1_DS_CNTL, CLK1_DS_DIV_ID, mask_sh), \ + CLK_SF(CLK8_CLK2_DS_CNTL, CLK2_DS_DIV_ID, mask_sh), \ + CLK_SF(CLK8_CLK3_DS_CNTL, CLK3_DS_DIV_ID, mask_sh), \ + CLK_SF(CLK8_CLK4_DS_CNTL, CLK4_DS_DIV_ID, mask_sh), \ + CLK_SF(CLK8_CLK0_DS_CNTL, CLK0_ALLOW_DS, mask_sh), \ + CLK_SF(CLK8_CLK1_DS_CNTL, CLK1_ALLOW_DS, mask_sh), \ + CLK_SF(CLK8_CLK2_DS_CNTL, CLK2_ALLOW_DS, mask_sh), \ + CLK_SF(CLK8_CLK3_DS_CNTL, CLK3_ALLOW_DS, mask_sh), \ + CLK_SF(CLK8_CLK4_DS_CNTL, CLK4_ALLOW_DS, mask_sh), \ + + + #define CLK_REG_FIELD_LIST(type) \ type DPREFCLK_SRC_SEL; \ type DENTIST_DPREFCLK_WDIVIDER; \ @@ -246,6 +275,42 @@ enum dentist_divider_range { type FbMult_int; \ type FbMult_frac; +#define CLK42_REG_LIST(clkip_num, type) \ + type CLK ## clkip_num ## _CLK_TICK_CNT_CONFIG_REG; \ + type CLK ## clkip_num ## _CLK0_CURRENT_CNT; \ + type CLK ## clkip_num ## _CLK1_CURRENT_CNT; \ + type CLK ## clkip_num ## _CLK2_CURRENT_CNT; \ + type CLK ## clkip_num ## _CLK3_CURRENT_CNT; \ + type CLK ## clkip_num ## _CLK4_CURRENT_CNT; \ + type CLK ## clkip_num ## _CLK0_BYPASS_CNTL; \ + type CLK ## clkip_num ## _CLK1_BYPASS_CNTL; \ + type CLK ## clkip_num ## _CLK2_BYPASS_CNTL; \ + type CLK ## clkip_num ## _CLK3_BYPASS_CNTL; \ + type CLK ## clkip_num ## _CLK4_BYPASS_CNTL; \ + type CLK ## clkip_num ## _CLK0_DS_CNTL; \ + type CLK ## clkip_num ## _CLK1_DS_CNTL; \ + type CLK ## clkip_num ## _CLK2_DS_CNTL; \ + type CLK ## clkip_num ## _CLK3_DS_CNTL; \ + type CLK ## clkip_num ## _CLK4_DS_CNTL; + +#define CLK42_REG_FIELD_LIST(type) \ + type TIMER_THRESHOLD; \ + type CLK0_BYPASS_SEL; \ + type CLK1_BYPASS_SEL; \ + type CLK2_BYPASS_SEL; \ + type CLK3_BYPASS_SEL; \ + type CLK4_BYPASS_SEL; \ + type CLK0_DS_DIV_ID; \ + type CLK1_DS_DIV_ID; \ + type CLK2_DS_DIV_ID; \ + type CLK3_DS_DIV_ID; \ + type CLK4_DS_DIV_ID; \ + type CLK0_ALLOW_DS; \ + type CLK1_ALLOW_DS; \ + type CLK2_ALLOW_DS; \ + type CLK3_ALLOW_DS; \ + type CLK4_ALLOW_DS; + /* *************************************************************************************** ****************** Clock Manager Private Structures *********************************** @@ -277,10 +342,10 @@ struct clk_mgr_registers { uint32_t CLK2_CLK2_DFS_CNTL; uint32_t CLK1_CLK0_CURRENT_CNT; - uint32_t CLK1_CLK1_CURRENT_CNT; - uint32_t CLK1_CLK2_CURRENT_CNT; - uint32_t CLK1_CLK3_CURRENT_CNT; - uint32_t CLK1_CLK4_CURRENT_CNT; + uint32_t CLK1_CLK1_CURRENT_CNT; + uint32_t CLK1_CLK2_CURRENT_CNT; + uint32_t CLK1_CLK3_CURRENT_CNT; + uint32_t CLK1_CLK4_CURRENT_CNT; uint32_t CLK1_CLK5_CURRENT_CNT; uint32_t CLK0_CLK0_DFS_CNTL; @@ -309,16 +374,19 @@ struct clk_mgr_registers { uint32_t CLK1_CLK5_ALLOW_DS; uint32_t CLK5_spll_field_8; uint32_t CLK6_spll_field_8; + CLK42_REG_LIST(8, uint32_t) }; struct clk_mgr_shift { CLK_REG_FIELD_LIST(uint8_t) CLK20_REG_FIELD_LIST(uint8_t) + CLK42_REG_FIELD_LIST(uint8_t) }; struct clk_mgr_mask { CLK_REG_FIELD_LIST(uint32_t) CLK20_REG_FIELD_LIST(uint32_t) + CLK42_REG_FIELD_LIST(uint32_t) }; enum clock_type { @@ -333,6 +401,8 @@ enum clock_type { clock_type_dscclk, clock_type_uclk, clock_type_dramclk, + clock_type_dprefclk, + clock_type_dtbclk, }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h index d88b57d4f512..39215ecb480e 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h @@ -1,5 +1,5 @@ /* - * Copyright 2012-15 Advanced Micro Devices, Inc. + * Copyright 2012-2026 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -367,6 +367,14 @@ struct dpp_funcs { void (*dpp_force_disable_cursor)(struct dpp *dpp_base); + void (*dpp_cm_hist_control)( + struct dpp *dpp_base, + struct cm_hist_control cm_hist_control, + enum dc_color_space color_space); + + bool (*dpp_cm_hist_read)( + struct dpp *dpp_base, + struct cm_hist *cm_hist); }; 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 a79019365af8..2a5a81d15950 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_transformed = 4916, //mpc default + hubp_3dlut_fl_width_17_transformed = 4916, //mpc default }; enum hubp_3dlut_fl_crossbar_bit_slice { @@ -99,22 +99,6 @@ 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; @@ -243,7 +227,6 @@ struct hubp_funcs { void (*hubp_disable_control)(struct hubp *hubp, bool disable_hubp); unsigned int (*hubp_get_underflow_status)(struct hubp *hubp); void (*hubp_init)(struct hubp *hubp); - void (*dmdata_set_attributes)( struct hubp *hubp, const struct dc_dmdata_attributes *attr); @@ -290,24 +273,15 @@ 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); + const struct dc_plane_address *address); + void (*hubp_program_3dlut_fl_config)(struct hubp *hubp, + const struct dc_3dlut_dma *config); 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 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 dc_cm_lut_pixel_format format); 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/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h index a61d12ec61bc..51581c10fd6b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h @@ -152,6 +152,13 @@ struct dc_rgb { uint32_t blue; }; +struct tetrahedral_33x33x33 { + struct dc_rgb lut0[8985]; + struct dc_rgb lut1[8984]; + struct dc_rgb lut2[8984]; + struct dc_rgb lut3[8984]; +}; + struct tetrahedral_17x17x17 { struct dc_rgb lut0[1229]; struct dc_rgb lut1[1228]; @@ -165,14 +172,23 @@ struct tetrahedral_9x9x9 { struct dc_rgb lut3[182]; }; +enum lut_dimension { + LUT_DIM_INVALID = 0, + LUT_DIM_9 = 9, + LUT_DIM_17 = 17, + LUT_DIM_33 = 33, +}; + struct tetrahedral_params { union { +//TODO: Uncomment when in use. +// struct tetrahedral_33x33x33 tetrahedral_33; struct tetrahedral_17x17x17 tetrahedral_17; struct tetrahedral_9x9x9 tetrahedral_9; }; bool use_tetrahedral_9; bool use_12bits; - + enum lut_dimension lut_dim; }; /* arr_curve_points - regamma regions/segments specification @@ -240,7 +256,7 @@ struct default_adjustment { enum dc_color_space out_color_space; enum dc_color_space in_color_space; enum dc_color_depth color_depth; - enum pixel_format surface_pixel_format; + enum dc_pixel_format surface_pixel_format; enum graphics_csc_adjust_type csc_adjust_type; bool force_hw_default; }; 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 a8d1abe20f62..f5617674bea8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h @@ -1,5 +1,5 @@ /* - * Copyright 2012-15 Advanced Micro Devices, Inc. + * Copyright 2012-2026 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -54,6 +54,7 @@ #include "dc_hw_types.h" #include "hw_shared.h" #include "transform.h" +#include "dc_types.h" #define MAX_MPCC 6 #define MAX_OPP 6 @@ -66,7 +67,6 @@ enum mpc_output_csc_mode { MPC_OUTPUT_CSC_COEF_B }; - enum mpcc_blend_mode { MPCC_BLEND_MODE_BYPASS, MPCC_BLEND_MODE_TOP_LAYER_PASSTHROUGH, @@ -102,13 +102,6 @@ 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, @@ -117,7 +110,7 @@ enum MCM_LUT_ID { struct mpc_fl_3dlut_config { bool enabled; - uint16_t width; + enum dc_cm_lut_size size; bool select_lut_bank_a; uint16_t bit_depth; int hubp_index; @@ -1043,6 +1036,24 @@ struct mpc_funcs { void (*update_3dlut_fast_load_select)(struct mpc *mpc, int mpcc_id, int hubp_idx); /** + * @get_3dlut_fast_load_status: + * + * Get 3D LUT fast load status and reference them with done, soft_underflow and hard_underflow pointers. + * + * Parameters: + * - [in/out] mpc - MPC context. + * - [in] mpcc_id + * - [in/out] done + * - [in/out] soft_underflow + * - [in/out] hard_underflow + * + * Return: + * + * void + */ + void (*get_3dlut_fast_load_status)(struct mpc *mpc, int mpcc_id, uint32_t *done, uint32_t *soft_underflow, uint32_t *hard_underflow); + + /** * @populate_lut: * * Populate LUT with given tetrahedral parameters. @@ -1058,8 +1069,11 @@ struct mpc_funcs { * * void */ - 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); + 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); /** * @program_lut_read_write_control: @@ -1070,13 +1084,18 @@ 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, bool lut_bank_a, int mpcc_id); + 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); /** * @program_lut_mode: @@ -1086,33 +1105,44 @@ struct mpc_funcs { * Parameters: * - [in/out] mpc - MPC context. * - [in] id - * - [in] xable + * - [in] enable * - [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 enum MCM_LUT_XABLE xable, - bool lut_bank_a, int mpcc_id); + 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); - /** - * @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; + /** + * @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); /** * @rmcm: @@ -1125,9 +1155,11 @@ 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, 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_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_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/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index 671ab1fc7320..2f70bb476c97 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -1,5 +1,5 @@ /* - * Copyright 2012-15 Advanced Micro Devices, Inc. + * Copyright 2012-2026 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -518,6 +518,8 @@ struct timing_generator_funcs { bool (*wait_update_lock_status)(struct timing_generator *tg, bool locked); void (*read_otg_state)(struct timing_generator *tg, struct dcn_otg_state *s); void (*optc_read_reg_state)(struct timing_generator *tg, struct dcn_optc_reg_state *optc_reg_state); + void (*enable_otg_pwa)(struct timing_generator *tg, struct otc_pwa_frame_sync *pwa_param); + void (*disable_otg_pwa)(struct timing_generator *tg); }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h index 5a1d9b708a9d..30990355985d 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h @@ -160,7 +160,7 @@ struct scaler_data { struct scaling_ratios ratios; struct scl_inits inits; struct sharpness_adj sharpness; - enum pixel_format format; + enum dc_pixel_format format; struct line_buffer_params lb_params; // Below struct holds the scaler values to program hw registers struct dscl_prog_data dscl_prog_data; diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 79746d931471..cecd3282a29f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -60,6 +60,7 @@ struct resource_caps { int num_hpo_dp_stream_encoder; int num_hpo_dp_link_encoder; int num_mpc_3dlut; + int num_rmcm; }; struct resource_straps { diff --git a/drivers/gpu/drm/amd/display/dc/irq/Makefile b/drivers/gpu/drm/amd/display/dc/irq/Makefile index b5e14d792378..807b73c2a758 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/Makefile +++ b/drivers/gpu/drm/amd/display/dc/irq/Makefile @@ -198,3 +198,12 @@ IRQ_DCN401 = irq_service_dcn401.o AMD_DAL_IRQ_DCN401= $(addprefix $(AMDDALPATH)/dc/irq/dcn401/,$(IRQ_DCN401)) AMD_DISPLAY_FILES += $(AMD_DAL_IRQ_DCN401) + +############################################################################### +# DCN 42 +############################################################################### +IRQ_DCN42 = irq_service_dcn42.o + +AMD_DAL_IRQ_DCN42= $(addprefix $(AMDDALPATH)/dc/irq/dcn42/,$(IRQ_DCN42)) + +AMD_DISPLAY_FILES += $(AMD_DAL_IRQ_DCN42) diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c index 676df39079fc..015f3659cf77 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c @@ -92,7 +92,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = { .enable_mask = DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK,\ .enable_value = {\ DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK,\ - ~DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK\ + (uint32_t)~DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK\ },\ .ack_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\ .ack_mask = DC_HPD_INT_CONTROL__DC_HPD_INT_ACK_MASK,\ @@ -107,7 +107,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = { .enable_mask = DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK,\ .enable_value = {\ DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK,\ - ~DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK },\ + (uint32_t)~DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK },\ .ack_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\ .ack_mask = DC_HPD_INT_CONTROL__DC_HPD_RX_INT_ACK_MASK,\ .ack_value = DC_HPD_INT_CONTROL__DC_HPD_RX_INT_ACK_MASK,\ @@ -121,7 +121,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = { GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK,\ .enable_value = {\ GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK,\ - ~GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK},\ + (uint32_t)~GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK},\ .ack_reg = mmDCP ## reg_num ## _GRPH_INTERRUPT_STATUS,\ .ack_mask = GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK,\ .ack_value = GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK,\ @@ -136,7 +136,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = { CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK,\ .enable_value = {\ CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK,\ - ~CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK},\ + (uint32_t)~CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK},\ .ack_reg = mmCRTC ## reg_num ## _CRTC_V_UPDATE_INT_STATUS,\ .ack_mask =\ CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_CLEAR_MASK,\ @@ -152,7 +152,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = { CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK,\ .enable_value = {\ CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK,\ - ~CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK},\ + (uint32_t)~CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK},\ .ack_reg = mmCRTC ## reg_num ## _CRTC_VERTICAL_INTERRUPT0_CONTROL,\ .ack_mask =\ CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_CLEAR_MASK,\ @@ -183,6 +183,7 @@ bool dal_irq_service_dummy_set(struct irq_service *irq_service, const struct irq_source_info *info, bool enable) { + (void)enable; DC_LOG_ERROR("%s: called for non-implemented irq source, src_id=%u, ext_id=%u\n", __func__, info->src_id, info->ext_id); @@ -328,6 +329,7 @@ enum dc_irq_source to_dal_irq_source_dce110( uint32_t src_id, uint32_t ext_id) { + (void)irq_service; switch (src_id) { case VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0: return DC_IRQ_SOURCE_VBLANK1; diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c b/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c index b473dae2abbb..dbab6e3737a1 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c @@ -79,7 +79,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = { block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ .enable_value = {\ block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ - ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \ + (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \ },\ .ack_reg = SRI(reg2, block, reg_num),\ .ack_mask = \ diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c index b5c5f42cf8f2..3e19dfdd0474 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c @@ -68,7 +68,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = { .enable_mask = DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK,\ .enable_value = {\ DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK,\ - ~DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK\ + (uint32_t)~DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK\ },\ .ack_reg = mmDC_HPD ## reg_num ## _INT_CONTROL,\ .ack_mask = DC_HPD1_INT_CONTROL__DC_HPD1_INT_ACK_MASK,\ @@ -83,7 +83,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = { .enable_mask = DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_EN_MASK,\ .enable_value = {\ DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_EN_MASK,\ - ~DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_EN_MASK },\ + (uint32_t)~DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_EN_MASK },\ .ack_reg = mmDC_HPD ## reg_num ## _INT_CONTROL,\ .ack_mask = DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_ACK_MASK,\ .ack_value = DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_ACK_MASK,\ @@ -98,7 +98,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = { GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK,\ .enable_value = {\ GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK,\ - ~GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK},\ + (uint32_t)~GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK},\ .ack_reg = mmDCP ## reg_num ## _GRPH_INTERRUPT_STATUS,\ .ack_mask = GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK,\ .ack_value = GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK,\ @@ -113,7 +113,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = { CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK,\ .enable_value = {\ CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK,\ - ~CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK},\ + (uint32_t)~CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK},\ .ack_reg = mmCRTC ## reg_num ## _CRTC_V_UPDATE_INT_STATUS,\ .ack_mask =\ CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_CLEAR_MASK,\ @@ -129,7 +129,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = { CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK,\ .enable_value = {\ CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK,\ - ~CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK},\ + (uint32_t)~CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK},\ .ack_reg = mmCRTC ## reg_num ## _CRTC_VERTICAL_INTERRUPT0_CONTROL,\ .ack_mask =\ CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_CLEAR_MASK,\ diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c b/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c index ca2e13702fbb..0bdb62b883aa 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c @@ -42,6 +42,9 @@ static enum dc_irq_source to_dal_irq_source_dcn10(struct irq_service *irq_servic uint32_t src_id, uint32_t ext_id) { + (void)irq_service; + (void)src_id; + (void)ext_id; switch (src_id) { case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP: return DC_IRQ_SOURCE_VBLANK1; @@ -176,7 +179,7 @@ static struct irq_source_info_funcs vupdate_no_lock_irq_info_funcs = { block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ .enable_value = {\ block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ - ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \ + (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \ },\ .ack_reg = SRI(reg2, block, reg_num),\ .ack_mask = \ diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c b/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c index 1c4c51abc259..8a0f4b5d6956 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c @@ -43,6 +43,9 @@ static enum dc_irq_source to_dal_irq_source_dcn20( uint32_t src_id, uint32_t ext_id) { + (void)irq_service; + (void)src_id; + (void)ext_id; switch (src_id) { case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP: return DC_IRQ_SOURCE_VBLANK1; @@ -179,7 +182,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = { block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ .enable_value = {\ block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ - ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \ + (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \ },\ .ack_reg = SRI(reg2, block, reg_num),\ .ack_mask = \ diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c index 9e0881472e38..9d13c0cc91f0 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c @@ -42,6 +42,9 @@ static enum dc_irq_source to_dal_irq_source_dcn21(struct irq_service *irq_servic uint32_t src_id, uint32_t ext_id) { + (void)irq_service; + (void)src_id; + (void)ext_id; switch (src_id) { case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP: return DC_IRQ_SOURCE_VBLANK1; @@ -189,7 +192,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = { block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ .enable_value = {\ block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ - ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \ + (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \ },\ .ack_reg = SRI(reg2, block, reg_num),\ .ack_mask = \ diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c b/drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c index 92bcd35723ca..78338af86666 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c @@ -50,6 +50,9 @@ static enum dc_irq_source to_dal_irq_source_dcn30( uint32_t src_id, uint32_t ext_id) { + (void)irq_service; + (void)src_id; + (void)ext_id; switch (src_id) { case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP: return DC_IRQ_SOURCE_VBLANK1; @@ -196,7 +199,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = { block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ .enable_value = {\ block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ - ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \ + (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \ },\ .ack_reg = SRI(reg2, block, reg_num),\ .ack_mask = \ diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn302/irq_service_dcn302.c b/drivers/gpu/drm/amd/display/dc/irq/dcn302/irq_service_dcn302.c index 16685d066c1a..2f47a9fbcd43 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn302/irq_service_dcn302.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn302/irq_service_dcn302.c @@ -37,6 +37,9 @@ static enum dc_irq_source to_dal_irq_source_dcn302(struct irq_service *irq_service, uint32_t src_id, uint32_t ext_id) { + (void)ext_id; + (void)irq_service; + (void)src_id; switch (src_id) { case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP: return DC_IRQ_SOURCE_VBLANK1; @@ -180,7 +183,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = { .enable_mask = block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ .enable_value = {\ block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ - ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \ + (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \ },\ .ack_reg = SRI(reg2, block, reg_num),\ .ack_mask = block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK,\ @@ -199,7 +202,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = { reg1 ## __ ## mask1 ## _MASK,\ .enable_value = {\ reg1 ## __ ## mask1 ## _MASK,\ - ~reg1 ## __ ## mask1 ## _MASK \ + (uint32_t)~reg1 ## __ ## mask1 ## _MASK \ },\ .ack_reg = SRI_DMUB(reg2),\ .ack_mask = \ diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn303/irq_service_dcn303.c b/drivers/gpu/drm/amd/display/dc/irq/dcn303/irq_service_dcn303.c index 01d83e1922d6..236a7278a8cf 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn303/irq_service_dcn303.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn303/irq_service_dcn303.c @@ -38,6 +38,9 @@ static enum dc_irq_source to_dal_irq_source_dcn303(struct irq_service *irq_servi uint32_t src_id, uint32_t ext_id) { + (void)irq_service; + (void)src_id; + (void)ext_id; switch (src_id) { case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP: return DC_IRQ_SOURCE_VBLANK1; @@ -123,7 +126,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = { .enable_mask = block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ .enable_value = {\ block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ - ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \ + (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \ },\ .ack_reg = SRI(reg2, block, reg_num),\ .ack_mask = block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK,\ diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn31/irq_service_dcn31.c b/drivers/gpu/drm/amd/display/dc/irq/dcn31/irq_service_dcn31.c index 2114c5669e6e..213e5da31b19 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn31/irq_service_dcn31.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn31/irq_service_dcn31.c @@ -40,6 +40,9 @@ static enum dc_irq_source to_dal_irq_source_dcn31(struct irq_service *irq_servic uint32_t src_id, uint32_t ext_id) { + (void)irq_service; + (void)src_id; + (void)ext_id; switch (src_id) { case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP: return DC_IRQ_SOURCE_VBLANK1; @@ -184,7 +187,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = { block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ .enable_value = {\ block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ - ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \ + (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \ },\ .ack_reg = SRI(reg2, block, reg_num),\ .ack_mask = \ @@ -198,7 +201,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = { reg1 ## __ ## mask1 ## _MASK,\ .enable_value = {\ reg1 ## __ ## mask1 ## _MASK,\ - ~reg1 ## __ ## mask1 ## _MASK \ + (uint32_t)~reg1 ## __ ## mask1 ## _MASK \ },\ .ack_reg = SRI_DMUB(reg2),\ .ack_mask = \ diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn314/irq_service_dcn314.c b/drivers/gpu/drm/amd/display/dc/irq/dcn314/irq_service_dcn314.c index 16f158e0fb60..8aacc229b002 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn314/irq_service_dcn314.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn314/irq_service_dcn314.c @@ -42,6 +42,9 @@ static enum dc_irq_source to_dal_irq_source_dcn314(struct irq_service *irq_servi uint32_t src_id, uint32_t ext_id) { + (void)irq_service; + (void)src_id; + (void)ext_id; switch (src_id) { case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP: return DC_IRQ_SOURCE_VBLANK1; @@ -186,7 +189,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = { block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ .enable_value = {\ block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ - ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \ + (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \ },\ .ack_reg = SRI(reg2, block, reg_num),\ .ack_mask = \ @@ -200,7 +203,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = { reg1 ## __ ## mask1 ## _MASK,\ .enable_value = {\ reg1 ## __ ## mask1 ## _MASK,\ - ~reg1 ## __ ## mask1 ## _MASK \ + (uint32_t)~reg1 ## __ ## mask1 ## _MASK \ },\ .ack_reg = SRI_DMUB(reg2),\ .ack_mask = \ diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn315/irq_service_dcn315.c b/drivers/gpu/drm/amd/display/dc/irq/dcn315/irq_service_dcn315.c index 8ee03c006ad6..b3bddc87afed 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn315/irq_service_dcn315.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn315/irq_service_dcn315.c @@ -47,6 +47,9 @@ static enum dc_irq_source to_dal_irq_source_dcn315( uint32_t src_id, uint32_t ext_id) { + (void)irq_service; + (void)src_id; + (void)ext_id; switch (src_id) { case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP: return DC_IRQ_SOURCE_VBLANK1; @@ -191,7 +194,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = { block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ .enable_value = {\ block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ - ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \ + (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \ },\ .ack_reg = SRI(reg2, block, reg_num),\ .ack_mask = \ @@ -205,7 +208,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = { reg1 ## __ ## mask1 ## _MASK,\ .enable_value = {\ reg1 ## __ ## mask1 ## _MASK,\ - ~reg1 ## __ ## mask1 ## _MASK \ + (uint32_t)~reg1 ## __ ## mask1 ## _MASK \ },\ .ack_reg = SRI_DMUB(reg2),\ .ack_mask = \ diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn32/irq_service_dcn32.c b/drivers/gpu/drm/amd/display/dc/irq/dcn32/irq_service_dcn32.c index 07e6f7dd6b99..f407ba72acdb 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn32/irq_service_dcn32.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn32/irq_service_dcn32.c @@ -41,6 +41,9 @@ static enum dc_irq_source to_dal_irq_source_dcn32( uint32_t src_id, uint32_t ext_id) { + (void)irq_service; + (void)src_id; + (void)ext_id; switch (src_id) { case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP: return DC_IRQ_SOURCE_VBLANK1; @@ -195,7 +198,7 @@ static struct irq_source_info_funcs vline2_irq_info_funcs = { block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ .enable_value = {\ block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ - ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \ + (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \ },\ .ack_reg = SRI(reg2, block, reg_num),\ .ack_mask = \ @@ -209,7 +212,7 @@ static struct irq_source_info_funcs vline2_irq_info_funcs = { reg1 ## __ ## mask1 ## _MASK,\ .enable_value = {\ reg1 ## __ ## mask1 ## _MASK,\ - ~reg1 ## __ ## mask1 ## _MASK \ + (uint32_t)~reg1 ## __ ## mask1 ## _MASK \ },\ .ack_reg = SRI_DMUB(reg2),\ .ack_mask = \ diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn35/irq_service_dcn35.c b/drivers/gpu/drm/amd/display/dc/irq/dcn35/irq_service_dcn35.c index 3d28a5007f53..2f2985075f88 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn35/irq_service_dcn35.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn35/irq_service_dcn35.c @@ -39,6 +39,9 @@ static enum dc_irq_source to_dal_irq_source_dcn35( uint32_t src_id, uint32_t ext_id) { + (void)irq_service; + (void)src_id; + (void)ext_id; switch (src_id) { case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP: return DC_IRQ_SOURCE_VBLANK1; @@ -184,7 +187,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = { REG_STRUCT[base + reg_num].enable_value[0] = \ block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ REG_STRUCT[base + reg_num].enable_value[1] = \ - ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK, \ + (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK, \ REG_STRUCT[base + reg_num].ack_reg = SRI(reg2, block, reg_num),\ REG_STRUCT[base + reg_num].ack_mask = \ block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK,\ @@ -198,7 +201,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = { REG_STRUCT[base].enable_value[0] = \ reg1 ## __ ## mask1 ## _MASK,\ REG_STRUCT[base].enable_value[1] = \ - ~reg1 ## __ ## mask1 ## _MASK, \ + (uint32_t)~reg1 ## __ ## mask1 ## _MASK, \ REG_STRUCT[base].ack_reg = SRI_DMUB(reg2),\ REG_STRUCT[base].ack_mask = \ reg2 ## __ ## mask2 ## _MASK,\ diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn351/irq_service_dcn351.c b/drivers/gpu/drm/amd/display/dc/irq/dcn351/irq_service_dcn351.c index f716c2590876..1ed75b53e131 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn351/irq_service_dcn351.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn351/irq_service_dcn351.c @@ -18,6 +18,9 @@ static enum dc_irq_source to_dal_irq_source_dcn351( uint32_t src_id, uint32_t ext_id) { + (void)irq_service; + (void)src_id; + (void)ext_id; switch (src_id) { case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP: return DC_IRQ_SOURCE_VBLANK1; @@ -163,7 +166,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = { REG_STRUCT[base + reg_num].enable_value[0] = \ block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ REG_STRUCT[base + reg_num].enable_value[1] = \ - ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK, \ + (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK, \ REG_STRUCT[base + reg_num].ack_reg = SRI(reg2, block, reg_num),\ REG_STRUCT[base + reg_num].ack_mask = \ block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK,\ @@ -177,7 +180,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = { REG_STRUCT[base].enable_value[0] = \ reg1 ## __ ## mask1 ## _MASK,\ REG_STRUCT[base].enable_value[1] = \ - ~reg1 ## __ ## mask1 ## _MASK, \ + (uint32_t)~reg1 ## __ ## mask1 ## _MASK, \ REG_STRUCT[base].ack_reg = SRI_DMUB(reg2),\ REG_STRUCT[base].ack_mask = \ reg2 ## __ ## mask2 ## _MASK,\ diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn36/irq_service_dcn36.c b/drivers/gpu/drm/amd/display/dc/irq/dcn36/irq_service_dcn36.c index e718004901cf..4c321c26f02f 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn36/irq_service_dcn36.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn36/irq_service_dcn36.c @@ -17,6 +17,9 @@ static enum dc_irq_source to_dal_irq_source_dcn36( uint32_t src_id, uint32_t ext_id) { + (void)irq_service; + (void)src_id; + (void)ext_id; switch (src_id) { case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP: return DC_IRQ_SOURCE_VBLANK1; @@ -162,7 +165,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = { REG_STRUCT[base + reg_num].enable_value[0] = \ block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ REG_STRUCT[base + reg_num].enable_value[1] = \ - ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK, \ + (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK, \ REG_STRUCT[base + reg_num].ack_reg = SRI(reg2, block, reg_num),\ REG_STRUCT[base + reg_num].ack_mask = \ block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK,\ @@ -176,7 +179,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = { REG_STRUCT[base].enable_value[0] = \ reg1 ## __ ## mask1 ## _MASK,\ REG_STRUCT[base].enable_value[1] = \ - ~reg1 ## __ ## mask1 ## _MASK, \ + (uint32_t)~reg1 ## __ ## mask1 ## _MASK, \ REG_STRUCT[base].ack_reg = SRI_DMUB(reg2),\ REG_STRUCT[base].ack_mask = \ reg2 ## __ ## mask2 ## _MASK,\ diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn401/irq_service_dcn401.c b/drivers/gpu/drm/amd/display/dc/irq/dcn401/irq_service_dcn401.c index 2cde50b2ae22..059c5c636fd9 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn401/irq_service_dcn401.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn401/irq_service_dcn401.c @@ -20,6 +20,9 @@ static enum dc_irq_source to_dal_irq_source_dcn401( uint32_t src_id, uint32_t ext_id) { + (void)irq_service; + (void)src_id; + (void)ext_id; switch (src_id) { case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP: return DC_IRQ_SOURCE_VBLANK1; @@ -175,7 +178,7 @@ static struct irq_source_info_funcs vline2_irq_info_funcs = { block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ .enable_value = {\ block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ - ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \ + (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \ },\ .ack_reg = SRI(reg2, block, reg_num),\ .ack_mask = \ @@ -189,7 +192,7 @@ static struct irq_source_info_funcs vline2_irq_info_funcs = { reg1 ## __ ## mask1 ## _MASK,\ .enable_value = {\ reg1 ## __ ## mask1 ## _MASK,\ - ~reg1 ## __ ## mask1 ## _MASK \ + (uint32_t)~reg1 ## __ ## mask1 ## _MASK \ },\ .ack_reg = SRI_DMUB(reg2),\ .ack_mask = \ diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn42/irq_service_dcn42.c b/drivers/gpu/drm/amd/display/dc/irq/dcn42/irq_service_dcn42.c new file mode 100644 index 000000000000..f4d1ce9079de --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn42/irq_service_dcn42.c @@ -0,0 +1,415 @@ +// SPDX-License-Identifier: MIT +// +// Copyright 2026 Advanced Micro Devices, Inc. + +#include "dm_services.h" +#include "include/logger_interface.h" +#include "../dce110/irq_service_dce110.h" + +#include "ivsrcid/dcn/irqsrcs_dcn_1_0.h" +#include "dcn/dcn_4_2_0_offset.h" +#include "dcn/dcn_4_2_0_sh_mask.h" + +#include "irq_service_dcn42.h" + +#define DCN_BASE__INST0_SEG2 0x000034C0 + +static enum dc_irq_source to_dal_irq_source_dcn42( + struct irq_service *irq_service, + uint32_t src_id, + uint32_t ext_id) +{ + (void)irq_service; + (void)src_id; + (void)ext_id; + switch (src_id) { + case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP: + return DC_IRQ_SOURCE_VBLANK1; + case DCN_1_0__SRCID__DC_D2_OTG_VSTARTUP: + return DC_IRQ_SOURCE_VBLANK2; + case DCN_1_0__SRCID__DC_D3_OTG_VSTARTUP: + return DC_IRQ_SOURCE_VBLANK3; + case DCN_1_0__SRCID__DC_D4_OTG_VSTARTUP: + return DC_IRQ_SOURCE_VBLANK4; + case DCN_1_0__SRCID__DC_D5_OTG_VSTARTUP: + return DC_IRQ_SOURCE_VBLANK5; + case DCN_1_0__SRCID__DC_D6_OTG_VSTARTUP: + return DC_IRQ_SOURCE_VBLANK6; + case DCN_1_0__SRCID__OTG1_VERTICAL_INTERRUPT0_CONTROL: + return DC_IRQ_SOURCE_DC1_VLINE0; + case DCN_1_0__SRCID__OTG2_VERTICAL_INTERRUPT0_CONTROL: + return DC_IRQ_SOURCE_DC2_VLINE0; + case DCN_1_0__SRCID__OTG3_VERTICAL_INTERRUPT0_CONTROL: + return DC_IRQ_SOURCE_DC3_VLINE0; + case DCN_1_0__SRCID__OTG4_VERTICAL_INTERRUPT0_CONTROL: + return DC_IRQ_SOURCE_DC4_VLINE0; + case DCN_1_0__SRCID__OTG5_VERTICAL_INTERRUPT0_CONTROL: + return DC_IRQ_SOURCE_DC5_VLINE0; + case DCN_1_0__SRCID__OTG6_VERTICAL_INTERRUPT0_CONTROL: + return DC_IRQ_SOURCE_DC6_VLINE0; + case DCN_1_0__SRCID__HUBP0_FLIP_INTERRUPT: + return DC_IRQ_SOURCE_PFLIP1; + case DCN_1_0__SRCID__HUBP1_FLIP_INTERRUPT: + return DC_IRQ_SOURCE_PFLIP2; + case DCN_1_0__SRCID__HUBP2_FLIP_INTERRUPT: + return DC_IRQ_SOURCE_PFLIP3; + case DCN_1_0__SRCID__HUBP3_FLIP_INTERRUPT: + return DC_IRQ_SOURCE_PFLIP4; + case DCN_1_0__SRCID__HUBP4_FLIP_INTERRUPT: + return DC_IRQ_SOURCE_PFLIP5; + case DCN_1_0__SRCID__HUBP5_FLIP_INTERRUPT: + return DC_IRQ_SOURCE_PFLIP6; + case DCN_1_0__SRCID__OTG0_IHC_V_UPDATE_NO_LOCK_INTERRUPT: + return DC_IRQ_SOURCE_VUPDATE1; + case DCN_1_0__SRCID__OTG1_IHC_V_UPDATE_NO_LOCK_INTERRUPT: + return DC_IRQ_SOURCE_VUPDATE2; + case DCN_1_0__SRCID__OTG2_IHC_V_UPDATE_NO_LOCK_INTERRUPT: + return DC_IRQ_SOURCE_VUPDATE3; + case DCN_1_0__SRCID__OTG3_IHC_V_UPDATE_NO_LOCK_INTERRUPT: + return DC_IRQ_SOURCE_VUPDATE4; + case DCN_1_0__SRCID__OTG4_IHC_V_UPDATE_NO_LOCK_INTERRUPT: + return DC_IRQ_SOURCE_VUPDATE5; + case DCN_1_0__SRCID__OTG5_IHC_V_UPDATE_NO_LOCK_INTERRUPT: + return DC_IRQ_SOURCE_VUPDATE6; + case DCN_1_0__SRCID__DMCUB_OUTBOX_LOW_PRIORITY_READY_INT: + return DC_IRQ_SOURCE_DMCUB_OUTBOX; + case DCN_1_0__SRCID__DC_HPD1_INT: + /* generic src_id for all HPD and HPDRX interrupts */ + switch (ext_id) { + case DCN_1_0__CTXID__DC_HPD1_INT: + return DC_IRQ_SOURCE_HPD1; + case DCN_1_0__CTXID__DC_HPD2_INT: + return DC_IRQ_SOURCE_HPD2; + case DCN_1_0__CTXID__DC_HPD3_INT: + return DC_IRQ_SOURCE_HPD3; + case DCN_1_0__CTXID__DC_HPD4_INT: + return DC_IRQ_SOURCE_HPD4; + case DCN_1_0__CTXID__DC_HPD5_INT: + return DC_IRQ_SOURCE_HPD5; + case DCN_1_0__CTXID__DC_HPD6_INT: + return DC_IRQ_SOURCE_HPD6; + case DCN_1_0__CTXID__DC_HPD1_RX_INT: + return DC_IRQ_SOURCE_HPD1RX; + case DCN_1_0__CTXID__DC_HPD2_RX_INT: + return DC_IRQ_SOURCE_HPD2RX; + case DCN_1_0__CTXID__DC_HPD3_RX_INT: + return DC_IRQ_SOURCE_HPD3RX; + case DCN_1_0__CTXID__DC_HPD4_RX_INT: + return DC_IRQ_SOURCE_HPD4RX; + case DCN_1_0__CTXID__DC_HPD5_RX_INT: + return DC_IRQ_SOURCE_HPD5RX; + case DCN_1_0__CTXID__DC_HPD6_RX_INT: + return DC_IRQ_SOURCE_HPD6RX; + default: + return DC_IRQ_SOURCE_INVALID; + } + break; + default: + return DC_IRQ_SOURCE_INVALID; + } + +} + +static struct irq_source_info_funcs hpd_irq_info_funcs = { + .set = NULL, + .ack = hpd0_ack +}; + +static struct irq_source_info_funcs hpd_rx_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +static struct irq_source_info_funcs pflip_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +static struct irq_source_info_funcs vupdate_no_lock_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +static struct irq_source_info_funcs vblank_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +static struct irq_source_info_funcs outbox_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +static struct irq_source_info_funcs vline0_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +static struct irq_source_info_funcs vline1_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +static struct irq_source_info_funcs vline2_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +#undef BASE_INNER +#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg + +/* compile time expand base address. */ +#define BASE(seg) \ + BASE_INNER(seg) + +#define SRI(reg_name, block, id)\ + (BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name) + +#define SRI_DMUB(reg_name)\ + (BASE(reg ## reg_name ## _BASE_IDX) + \ + reg ## reg_name) + +#define IRQ_REG_ENTRY(block, reg_num, reg1, mask1, reg2, mask2)\ + .enable_reg = SRI(reg1, block, reg_num),\ + .enable_mask = \ + block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ + .enable_value = {\ + block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ + (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \ + },\ + .ack_reg = SRI(reg2, block, reg_num),\ + .ack_mask = \ + block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK,\ + .ack_value = \ + block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK \ + +#define IRQ_REG_ENTRY_DMUB(reg1, mask1, reg2, mask2)\ + .enable_reg = SRI_DMUB(reg1),\ + .enable_mask = \ + reg1 ## __ ## mask1 ## _MASK,\ + .enable_value = {\ + reg1 ## __ ## mask1 ## _MASK,\ + (uint32_t)~reg1 ## __ ## mask1 ## _MASK \ + },\ + .ack_reg = SRI_DMUB(reg2),\ + .ack_mask = \ + reg2 ## __ ## mask2 ## _MASK,\ + .ack_value = \ + reg2 ## __ ## mask2 ## _MASK \ + +#define hpd_int_entry(reg_num)\ + [DC_IRQ_SOURCE_HPD1 + reg_num] = {\ + IRQ_REG_ENTRY(HPD, reg_num,\ + DC_HPD_INT_CONTROL, DC_HPD_INT_EN,\ + DC_HPD_INT_CONTROL, DC_HPD_INT_ACK),\ + .status_reg = SRI(DC_HPD_INT_STATUS, HPD, reg_num),\ + .funcs = &hpd_irq_info_funcs\ + } + +#define hpd_rx_int_entry(reg_num)\ + [DC_IRQ_SOURCE_HPD1RX + reg_num] = {\ + IRQ_REG_ENTRY(HPD, reg_num,\ + DC_HPD_INT_CONTROL, DC_HPD_RX_INT_EN,\ + DC_HPD_INT_CONTROL, DC_HPD_RX_INT_ACK),\ + .status_reg = SRI(DC_HPD_INT_STATUS, HPD, reg_num),\ + .funcs = &hpd_rx_irq_info_funcs\ + } +#define pflip_int_entry(reg_num)\ + [DC_IRQ_SOURCE_PFLIP1 + reg_num] = {\ + IRQ_REG_ENTRY(HUBPREQ, reg_num,\ + DCSURF_SURFACE_FLIP_INTERRUPT, SURFACE_FLIP_INT_MASK,\ + DCSURF_SURFACE_FLIP_INTERRUPT, SURFACE_FLIP_CLEAR),\ + .funcs = &pflip_irq_info_funcs\ + } + +#define vblank_int_entry(reg_num)\ + [DC_IRQ_SOURCE_VBLANK1 + reg_num] = {\ + IRQ_REG_ENTRY(OTG, reg_num,\ + OTG_GLOBAL_SYNC_STATUS, VSTARTUP_INT_EN,\ + OTG_GLOBAL_SYNC_STATUS, VSTARTUP_EVENT_CLEAR),\ + .funcs = &vblank_irq_info_funcs\ + } + +#define vupdate_no_lock_int_entry(reg_num)\ + [DC_IRQ_SOURCE_VUPDATE1 + reg_num] = {\ + IRQ_REG_ENTRY(OTG, reg_num,\ + OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_INT_EN,\ + OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_EVENT_CLEAR),\ + .funcs = &vupdate_no_lock_irq_info_funcs\ + } + +#define vline0_int_entry(reg_num)\ + [DC_IRQ_SOURCE_DC1_VLINE0 + reg_num] = {\ + IRQ_REG_ENTRY(OTG, reg_num,\ + OTG_VERTICAL_INTERRUPT0_CONTROL, OTG_VERTICAL_INTERRUPT0_INT_ENABLE,\ + OTG_VERTICAL_INTERRUPT0_CONTROL, OTG_VERTICAL_INTERRUPT0_CLEAR),\ + .funcs = &vline0_irq_info_funcs\ + } +#define vline1_int_entry(reg_num)\ + [DC_IRQ_SOURCE_DC1_VLINE1 + reg_num] = {\ + IRQ_REG_ENTRY(OTG, reg_num,\ + OTG_VERTICAL_INTERRUPT1_CONTROL, OTG_VERTICAL_INTERRUPT1_INT_ENABLE,\ + OTG_VERTICAL_INTERRUPT1_CONTROL, OTG_VERTICAL_INTERRUPT1_CLEAR),\ + .funcs = &vline1_irq_info_funcs\ + } +#define vline2_int_entry(reg_num)\ + [DC_IRQ_SOURCE_DC1_VLINE2 + reg_num] = {\ + IRQ_REG_ENTRY(OTG, reg_num,\ + OTG_VERTICAL_INTERRUPT2_CONTROL, OTG_VERTICAL_INTERRUPT2_INT_ENABLE,\ + OTG_VERTICAL_INTERRUPT2_CONTROL, OTG_VERTICAL_INTERRUPT2_CLEAR),\ + .funcs = &vline2_irq_info_funcs\ + } +#define dmub_outbox_int_entry()\ + [DC_IRQ_SOURCE_DMCUB_OUTBOX] = {\ + IRQ_REG_ENTRY_DMUB(\ + DMCUB_INTERRUPT_ENABLE, DMCUB_OUTBOX1_READY_INT_EN,\ + DMCUB_INTERRUPT_ACK, DMCUB_OUTBOX1_READY_INT_ACK),\ + .funcs = &outbox_irq_info_funcs\ + } + +#define dummy_irq_entry() \ + {\ + .funcs = &dummy_irq_info_funcs\ + } + +#define i2c_int_entry(reg_num) \ + [DC_IRQ_SOURCE_I2C_DDC ## reg_num] = dummy_irq_entry() + +#define dp_sink_int_entry(reg_num) \ + [DC_IRQ_SOURCE_DPSINK ## reg_num] = dummy_irq_entry() + +#define gpio_pad_int_entry(reg_num) \ + [DC_IRQ_SOURCE_GPIOPAD ## reg_num] = dummy_irq_entry() + +#define dc_underflow_int_entry(reg_num) \ + [DC_IRQ_SOURCE_DC ## reg_num ## UNDERFLOW] = dummy_irq_entry() + +static struct irq_source_info_funcs dummy_irq_info_funcs = { + .set = dal_irq_service_dummy_set, + .ack = dal_irq_service_dummy_ack +}; + +static const struct irq_source_info irq_source_info_dcn42[DAL_IRQ_SOURCES_NUMBER] = { + [DC_IRQ_SOURCE_INVALID] = dummy_irq_entry(), + /* HPD (1-4) */ + hpd_int_entry(0), + hpd_int_entry(1), + hpd_int_entry(2), + hpd_int_entry(3), + /* HPD RX (1-4) */ + hpd_rx_int_entry(0), + hpd_rx_int_entry(1), + hpd_rx_int_entry(2), + hpd_rx_int_entry(3), + /* I2C (1-6) */ + i2c_int_entry(1), + i2c_int_entry(2), + i2c_int_entry(3), + i2c_int_entry(4), + i2c_int_entry(5), + i2c_int_entry(6), + /* DP sink (1-6) keep table shape */ + dp_sink_int_entry(1), + dp_sink_int_entry(2), + dp_sink_int_entry(3), + dp_sink_int_entry(4), + dp_sink_int_entry(5), + dp_sink_int_entry(6), + [DC_IRQ_SOURCE_TIMER] = dummy_irq_entry(), + /* PFLIP (1-4) */ + pflip_int_entry(0), + pflip_int_entry(1), + pflip_int_entry(2), + pflip_int_entry(3), + [DC_IRQ_SOURCE_PFLIP5] = dummy_irq_entry(), + [DC_IRQ_SOURCE_PFLIP6] = dummy_irq_entry(), + [DC_IRQ_SOURCE_PFLIP_UNDERLAY0] = dummy_irq_entry(), + /* GPIO pads */ + gpio_pad_int_entry(0), + gpio_pad_int_entry(1), + gpio_pad_int_entry(2), + gpio_pad_int_entry(3), + gpio_pad_int_entry(4), + gpio_pad_int_entry(5), + gpio_pad_int_entry(6), + gpio_pad_int_entry(7), + gpio_pad_int_entry(8), + gpio_pad_int_entry(9), + gpio_pad_int_entry(10), + gpio_pad_int_entry(11), + gpio_pad_int_entry(12), + gpio_pad_int_entry(13), + gpio_pad_int_entry(14), + gpio_pad_int_entry(15), + gpio_pad_int_entry(16), + gpio_pad_int_entry(17), + gpio_pad_int_entry(18), + gpio_pad_int_entry(19), + gpio_pad_int_entry(20), + gpio_pad_int_entry(21), + gpio_pad_int_entry(22), + gpio_pad_int_entry(23), + gpio_pad_int_entry(24), + gpio_pad_int_entry(25), + gpio_pad_int_entry(26), + gpio_pad_int_entry(27), + gpio_pad_int_entry(28), + gpio_pad_int_entry(29), + gpio_pad_int_entry(30), + /* Underflow (1-4 active, keep 5-6 dummy) */ + dc_underflow_int_entry(1), + dc_underflow_int_entry(2), + dc_underflow_int_entry(3), + dc_underflow_int_entry(4), + dc_underflow_int_entry(5), + dc_underflow_int_entry(6), + [DC_IRQ_SOURCE_DMCU_SCP] = dummy_irq_entry(), + [DC_IRQ_SOURCE_VBIOS_SW] = dummy_irq_entry(), + vblank_int_entry(0), + vblank_int_entry(1), + vblank_int_entry(2), + vblank_int_entry(3), + [DC_IRQ_SOURCE_DC5_VLINE1] = dummy_irq_entry(), + [DC_IRQ_SOURCE_DC6_VLINE1] = dummy_irq_entry(), + dmub_outbox_int_entry(), + vupdate_no_lock_int_entry(0), + vupdate_no_lock_int_entry(1), + vupdate_no_lock_int_entry(2), + vupdate_no_lock_int_entry(3), + vline0_int_entry(0), + vline0_int_entry(1), + vline0_int_entry(2), + vline0_int_entry(3), + vline1_int_entry(0), + vline1_int_entry(1), + vline1_int_entry(2), + vline1_int_entry(3), + vline2_int_entry(0), + vline2_int_entry(1), + vline2_int_entry(2), + vline2_int_entry(3), +}; + +static const struct irq_service_funcs irq_service_funcs_dcn42 = { + .to_dal_irq_source = to_dal_irq_source_dcn42 +}; + +static void dcn42_irq_construct(struct irq_service *irq_service, + struct irq_service_init_data *init_data) +{ + dal_irq_service_construct(irq_service, init_data); + irq_service->info = irq_source_info_dcn42; + irq_service->funcs = &irq_service_funcs_dcn42; +} + +struct irq_service *dal_irq_service_dcn42_create(struct irq_service_init_data *init_data) +{ + struct irq_service *irq_service = kzalloc(sizeof(*irq_service), GFP_KERNEL); + + if (!irq_service) + return NULL; + + dcn42_irq_construct(irq_service, init_data); + return irq_service; +} diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn42/irq_service_dcn42.h b/drivers/gpu/drm/amd/display/dc/irq/dcn42/irq_service_dcn42.h new file mode 100644 index 000000000000..a3f70bce3a61 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn42/irq_service_dcn42.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2025 Advanced Micro Devices, Inc. + * + * DCN4.2 IRQ service interface (dal-dev only) + */ +#ifndef __IRQ_SERVICE_DCN42_H__ +#define __IRQ_SERVICE_DCN42_H__ + +#include "../dce110/irq_service_dce110.h" + +struct irq_service *dal_irq_service_dcn42_create( + struct irq_service_init_data *init_data); + +#endif /* __IRQ_SERVICE_DCN42_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c index 693d852b1c40..060460abc377 100644 --- a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c +++ b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c @@ -66,6 +66,7 @@ static void dp_retrain_link_dp_test(struct dc_link *link, struct dc_link_settings *link_setting, bool skip_video_pattern) { + (void)skip_video_pattern; struct pipe_ctx *pipes[MAX_PIPES]; struct dc_state *state = link->dc->current_state; struct dc_stream_update stream_update = { 0 }; @@ -483,6 +484,7 @@ static void set_crtc_test_pattern(struct dc_link *link, enum dp_test_pattern test_pattern, enum dp_test_pattern_color_space test_pattern_color_space) { + (void)test_pattern_color_space; enum controller_dp_test_pattern controller_test_pattern; enum dc_color_depth color_depth = pipe_ctx-> stream->timing.display_color_depth; diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dpia.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dpia.c index 81bf3c5e1fdf..2a87b23582f3 100644 --- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dpia.c +++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dpia.c @@ -81,6 +81,10 @@ static void set_dio_dpia_lane_settings(struct dc_link *link, const struct dc_link_settings *link_settings, const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]) { + (void)link; + (void)link_res; + (void)link_settings; + (void)lane_settings; } static void enable_dpia_link_output(struct dc_link *link, @@ -145,13 +149,9 @@ static void disable_dpia_link_output(struct dc_link *link, } static const struct link_hwss dpia_link_hwss = { - .setup_stream_encoder = setup_dio_stream_encoder, - .reset_stream_encoder = reset_dio_stream_encoder, - .setup_stream_attribute = setup_dio_stream_attribute, - .disable_link_output = disable_dpia_link_output, - .setup_audio_output = setup_dio_audio_output, - .enable_audio_packet = enable_dio_audio_packet, - .disable_audio_packet = disable_dio_audio_packet, + /* Ensure initialization order matches the declaration in link_hwss.h + * for strict compiler compliance and consistency across HWSS implementations + */ .ext = { .set_throttled_vcp_size = set_dio_throttled_vcp_size, .enable_dp_link_output = enable_dpia_link_output, @@ -159,6 +159,14 @@ static const struct link_hwss dpia_link_hwss = { .set_dp_lane_settings = set_dio_dpia_lane_settings, .update_stream_allocation_table = update_dpia_stream_allocation_table, }, + + .setup_stream_encoder = setup_dio_stream_encoder, + .reset_stream_encoder = reset_dio_stream_encoder, + .setup_stream_attribute = setup_dio_stream_attribute, + .disable_link_output = disable_dpia_link_output, + .setup_audio_output = setup_dio_audio_output, + .enable_audio_packet = enable_dio_audio_packet, + .disable_audio_packet = disable_dio_audio_packet, }; bool can_use_dpia_link_hwss(const struct dc_link *link, diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c index cec68c5dba13..dbbedeeed298 100644 --- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c +++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c @@ -110,6 +110,8 @@ void enable_hpo_dp_link_output(struct dc_link *link, enum clock_source_id clock_source, const struct dc_link_settings *link_settings) { + (void)signal; + (void)clock_source; if (!link_res->hpo_dp_link_enc) { DC_LOG_ERROR("%s: invalid hpo_dp_link_enc\n", __func__); return; @@ -160,6 +162,7 @@ static void set_hpo_dp_lane_settings(struct dc_link *link, const struct dc_link_settings *link_settings, const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]) { + (void)link; link_res->hpo_dp_link_enc->funcs->set_ffe( link_res->hpo_dp_link_enc, link_settings, @@ -170,6 +173,7 @@ void update_hpo_dp_stream_allocation_table(struct dc_link *link, const struct link_resource *link_res, const struct link_mst_stream_allocation_table *table) { + (void)link; link_res->hpo_dp_link_enc->funcs->update_stream_allocation_table( link_res->hpo_dp_link_enc, table); @@ -178,6 +182,7 @@ void update_hpo_dp_stream_allocation_table(struct dc_link *link, void setup_hpo_dp_audio_output(struct pipe_ctx *pipe_ctx, struct audio_output *audio_output, uint32_t audio_inst) { + (void)audio_output; pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_setup( pipe_ctx->stream_res.hpo_dp_stream_enc, audio_inst, @@ -218,6 +223,7 @@ static const struct link_hwss hpo_dp_link_hwss = { bool can_use_hpo_dp_link_hwss(const struct dc_link *link, const struct link_resource *link_res) { + (void)link; return link_res->hpo_dp_link_enc != NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c index 55c5148de800..6d5b7450b205 100644 --- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c +++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c @@ -74,6 +74,7 @@ static void dp_hpo_fixed_vs_pe_retimer_set_tx_ffe(struct dc_link *link, static void dp_hpo_fixed_vs_pe_retimer_program_override_test_pattern(struct dc_link *link, struct encoder_set_dp_phy_pattern_param *tp_params) { + (void)tp_params; uint8_t clk_src = 0xC4; uint8_t pattern = 0x4F; /* SQ128 */ diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_virtual.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_virtual.c index 64742c24f7e6..3aa1375cec71 100644 --- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_virtual.c +++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_virtual.c @@ -27,20 +27,26 @@ void virtual_setup_stream_encoder(struct pipe_ctx *pipe_ctx) { + (void)pipe_ctx; } void virtual_setup_stream_attribute(struct pipe_ctx *pipe_ctx) { + (void)pipe_ctx; } void virtual_reset_stream_encoder(struct pipe_ctx *pipe_ctx) { + (void)pipe_ctx; } static void virtual_disable_link_output(struct dc_link *link, const struct link_resource *link_res, enum signal_type signal) { + (void)link; + (void)link_res; + (void)signal; } static const struct link_hwss virtual_link_hwss = { diff --git a/drivers/gpu/drm/amd/display/dc/link/link_detection.c b/drivers/gpu/drm/amd/display/dc/link/link_detection.c index b2c020071cbf..59851924bfcd 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_detection.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.c @@ -150,14 +150,6 @@ static enum signal_type get_basic_signal_type(struct graphics_object_id encoder, default: return SIGNAL_TYPE_NONE; } - } else if (downstream.type == OBJECT_TYPE_ENCODER) { - switch (downstream.id) { - case ENCODER_ID_EXTERNAL_NUTMEG: - case ENCODER_ID_EXTERNAL_TRAVIS: - return SIGNAL_TYPE_DISPLAY_PORT; - default: - return SIGNAL_TYPE_NONE; - } } return SIGNAL_TYPE_NONE; @@ -174,6 +166,10 @@ static enum signal_type link_detect_sink_signal_type(struct dc_link *link, struct audio_support *aud_support; struct graphics_object_id enc_id; + /* External DP bridges should use DP signal regardless of connector type. */ + if (link->ext_enc_id.id) + return SIGNAL_TYPE_DISPLAY_PORT; + if (link->is_dig_mapping_flexible) enc_id = (struct graphics_object_id){.id = ENCODER_ID_UNKNOWN}; else @@ -356,7 +352,7 @@ static void query_dp_dual_mode_adaptor( *dongle = DISPLAY_DONGLE_DP_DVI_DONGLE; sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_DVI_MAX_TMDS_CLK; - CONN_DATA_DETECT(ddc->link, type2_dongle_buf, sizeof(type2_dongle_buf), + CONN_DATA_DETECT(link, type2_dongle_buf, sizeof(type2_dongle_buf), "DP-DVI passive dongle %dMhz: ", DP_ADAPTOR_DVI_MAX_TMDS_CLK / 1000); return; @@ -620,6 +616,14 @@ static bool detect_dp(struct dc_link *link, link->dpcd_caps.usb4_dp_tun_info.dp_tun_cap.raw = 0; } + if (link->ext_enc_id.id) { + /* Fix number of connected sinks reported by external DP bridge */ + link->dpcd_caps.sink_count.bits.SINK_COUNT = 1; + /* NUTMEG requires that we use HBR, doesn't work with RBR. */ + if (link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_00001A) + link->preferred_link_setting.link_rate = LINK_RATE_HIGH; + } + return true; } @@ -653,8 +657,6 @@ static bool wait_for_entering_dp_alt_mode(struct dc_link *link) unsigned long long time_taken_in_ns; int tries_taken; - DC_LOGGER_INIT(link->ctx->logger); - /** * this function will only exist if we are on dcn21 (is_in_alt_mode is a * function pointer, so checking to see if it is equal to 0 is the same @@ -725,8 +727,6 @@ static void revert_dpia_mst_dsc_always_on_wa(struct dc_link *link) static bool discover_dp_mst_topology(struct dc_link *link, enum dc_detect_reason reason) { - DC_LOGGER_INIT(link->ctx->logger); - LINK_INFO("link=%d, mst branch is now Connected\n", link->link_index); @@ -746,8 +746,6 @@ static bool discover_dp_mst_topology(struct dc_link *link, enum dc_detect_reason bool link_reset_cur_dp_mst_topology(struct dc_link *link) { - DC_LOGGER_INIT(link->ctx->logger); - LINK_INFO("link=%d, mst branch is now Disconnected\n", link->link_index); @@ -786,6 +784,7 @@ static void verify_link_capability_destructive(struct dc_link *link, struct dc_sink *sink, enum dc_detect_reason reason) { + (void)sink; bool should_prepare_phy_clocks = should_prepare_phy_clocks_for_link_verification(link->dc, reason); @@ -824,6 +823,7 @@ static void verify_link_capability_non_destructive(struct dc_link *link) static bool should_verify_link_capability_destructively(struct dc_link *link, enum dc_detect_reason reason) { + (void)reason; bool destrictive = false; struct dc_link_settings max_link_cap; bool is_link_enc_unavailable = false; @@ -903,11 +903,21 @@ static bool link_detect_evaluate_edid_header(uint8_t edid_header[8]) */ static bool link_detect_ddc_probe(struct dc_link *link) { + enum signal_type signal = link_detect_sink_signal_type(link, DETECT_REASON_HPD); + enum ddc_transaction_type transaction_type = get_ddc_transaction_type(signal); + uint8_t edid_header[8] = {0}; + uint8_t zero = 0; + bool ddc_probed; + if (!link->ddc) return false; - uint8_t edid_header[8] = {0}; - bool ddc_probed = i2c_read(link->ddc, 0x50, edid_header, sizeof(edid_header)); + if (link->dc->hwss.prepare_ddc) + link->dc->hwss.prepare_ddc(link); + + set_ddc_transaction_type(link->ddc, transaction_type); + + ddc_probed = link_query_ddc_data(link->ddc, 0x50, &zero, 1, edid_header, sizeof(edid_header)); if (!ddc_probed) return false; @@ -932,28 +942,10 @@ static bool link_detect_ddc_probe(struct dc_link *link) */ static bool link_detect_dac_load_detect(struct dc_link *link) { - struct dc_bios *bios = link->ctx->dc_bios; - struct link_encoder *link_enc = link->link_enc; - enum engine_id engine_id = link_enc->preferred_engine; - enum dal_device_type device_type = DEVICE_TYPE_CRT; - enum bp_result bp_result = BP_RESULT_UNSUPPORTED; - uint32_t enum_id; - - switch (engine_id) { - case ENGINE_ID_DACB: - enum_id = 2; - break; - case ENGINE_ID_DACA: - default: - engine_id = ENGINE_ID_DACA; - enum_id = 1; - break; - } - - if (bios->funcs->dac_load_detection) - bp_result = bios->funcs->dac_load_detection(bios, engine_id, device_type, enum_id); + if (!link->dc->hwss.dac_load_detect) + return false; - return bp_result == BP_RESULT_OK; + return link->dc->hwss.dac_load_detect(link); } /* @@ -981,8 +973,6 @@ static bool detect_link_and_local_sink(struct dc_link *link, enum dc_connection_type new_connection_type = dc_connection_none; const uint32_t post_oui_delay = 30; // 30ms - DC_LOGGER_INIT(link->ctx->logger); - if (dc_is_virtual_signal(link->connector_signal)) return false; @@ -1463,8 +1453,6 @@ bool link_detect(struct dc_link *link, enum dc_detect_reason reason) bool is_delegated_to_mst_top_mgr = false; enum dc_connection_type pre_link_type = link->type; - DC_LOGGER_INIT(link->ctx->logger); - is_local_sink_detect_success = detect_link_and_local_sink(link, reason); if (is_local_sink_detect_success && link->local_sink) diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c index 9b1d34c3438b..b4f46408a000 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c @@ -223,16 +223,32 @@ void link_get_master_pipes_with_dpms_on(const struct dc_link *link, } } -static bool get_ext_hdmi_settings(struct pipe_ctx *pipe_ctx, - enum engine_id eng_id, - struct ext_hdmi_settings *settings) +static struct ext_hdmi_settings create_ext_hdmi_settings( + uint8_t address, + uint8_t reg_num, + uint8_t reg_num_6g, + const struct i2c_reg_info *reg_settings, + const struct i2c_reg_info *reg_settings_6g +) { - bool result = false; - int i = 0; - struct integrated_info *integrated_info = - pipe_ctx->stream->ctx->dc_bios->integrated_info; + struct ext_hdmi_settings result = { + .slv_addr = address, + .reg_num = reg_num, + .reg_num_6g = reg_num_6g, + }; + + memcpy(result.reg_settings, reg_settings, sizeof(result.reg_settings)); + memcpy(result.reg_settings_6g, reg_settings_6g, sizeof(result.reg_settings_6g)); + return result; +} - if (integrated_info == NULL) +static bool get_ext_hdmi_settings( + const struct integrated_info *info, + enum engine_id eng_id, + struct ext_hdmi_settings *settings +) +{ + if (!settings || !info) return false; /* @@ -242,422 +258,268 @@ static bool get_ext_hdmi_settings(struct pipe_ctx *pipe_ctx, */ // Check if current bios contains ext Hdmi settings - if (integrated_info->gpu_cap_info & 0x20) { - switch (eng_id) { - case ENGINE_ID_DIGA: - settings->slv_addr = integrated_info->dp0_ext_hdmi_slv_addr; - settings->reg_num = integrated_info->dp0_ext_hdmi_6g_reg_num; - settings->reg_num_6g = integrated_info->dp0_ext_hdmi_6g_reg_num; - memmove(settings->reg_settings, - integrated_info->dp0_ext_hdmi_reg_settings, - sizeof(integrated_info->dp0_ext_hdmi_reg_settings)); - memmove(settings->reg_settings_6g, - integrated_info->dp0_ext_hdmi_6g_reg_settings, - sizeof(integrated_info->dp0_ext_hdmi_6g_reg_settings)); - result = true; - break; - case ENGINE_ID_DIGB: - settings->slv_addr = integrated_info->dp1_ext_hdmi_slv_addr; - settings->reg_num = integrated_info->dp1_ext_hdmi_6g_reg_num; - settings->reg_num_6g = integrated_info->dp1_ext_hdmi_6g_reg_num; - memmove(settings->reg_settings, - integrated_info->dp1_ext_hdmi_reg_settings, - sizeof(integrated_info->dp1_ext_hdmi_reg_settings)); - memmove(settings->reg_settings_6g, - integrated_info->dp1_ext_hdmi_6g_reg_settings, - sizeof(integrated_info->dp1_ext_hdmi_6g_reg_settings)); - result = true; - break; - case ENGINE_ID_DIGC: - settings->slv_addr = integrated_info->dp2_ext_hdmi_slv_addr; - settings->reg_num = integrated_info->dp2_ext_hdmi_6g_reg_num; - settings->reg_num_6g = integrated_info->dp2_ext_hdmi_6g_reg_num; - memmove(settings->reg_settings, - integrated_info->dp2_ext_hdmi_reg_settings, - sizeof(integrated_info->dp2_ext_hdmi_reg_settings)); - memmove(settings->reg_settings_6g, - integrated_info->dp2_ext_hdmi_6g_reg_settings, - sizeof(integrated_info->dp2_ext_hdmi_6g_reg_settings)); - result = true; - break; - case ENGINE_ID_DIGD: - settings->slv_addr = integrated_info->dp3_ext_hdmi_slv_addr; - settings->reg_num = integrated_info->dp3_ext_hdmi_6g_reg_num; - settings->reg_num_6g = integrated_info->dp3_ext_hdmi_6g_reg_num; - memmove(settings->reg_settings, - integrated_info->dp3_ext_hdmi_reg_settings, - sizeof(integrated_info->dp3_ext_hdmi_reg_settings)); - memmove(settings->reg_settings_6g, - integrated_info->dp3_ext_hdmi_6g_reg_settings, - sizeof(integrated_info->dp3_ext_hdmi_6g_reg_settings)); - result = true; - break; - default: - break; - } + if (!(info->gpu_cap_info & 0x20)) + return false; - if (result == true) { - // Validate settings from bios integrated info table - if (settings->slv_addr == 0) - return false; - if (settings->reg_num > 9) - return false; - if (settings->reg_num_6g > 3) - return false; + switch (eng_id) { + case ENGINE_ID_DIGA: + *settings = create_ext_hdmi_settings( + info->dp0_ext_hdmi_slv_addr, + info->dp0_ext_hdmi_reg_num, + info->dp0_ext_hdmi_6g_reg_num, + info->dp0_ext_hdmi_reg_settings, + info->dp0_ext_hdmi_6g_reg_settings + ); + break; + case ENGINE_ID_DIGB: + *settings = create_ext_hdmi_settings( + info->dp1_ext_hdmi_slv_addr, + info->dp1_ext_hdmi_reg_num, + info->dp1_ext_hdmi_6g_reg_num, + info->dp1_ext_hdmi_reg_settings, + info->dp1_ext_hdmi_6g_reg_settings + ); + break; + case ENGINE_ID_DIGC: + *settings = create_ext_hdmi_settings( + info->dp2_ext_hdmi_slv_addr, + info->dp2_ext_hdmi_reg_num, + info->dp2_ext_hdmi_6g_reg_num, + info->dp2_ext_hdmi_reg_settings, + info->dp2_ext_hdmi_6g_reg_settings + ); + break; + case ENGINE_ID_DIGD: + *settings = create_ext_hdmi_settings( + info->dp3_ext_hdmi_slv_addr, + info->dp3_ext_hdmi_reg_num, + info->dp3_ext_hdmi_6g_reg_num, + info->dp3_ext_hdmi_reg_settings, + info->dp3_ext_hdmi_6g_reg_settings + ); + break; + default: + return false; + } - for (i = 0; i < settings->reg_num; i++) { - if (settings->reg_settings[i].i2c_reg_index > 0x20) - return false; - } + // Validate settings from bios integrated info table + if ( + !settings->slv_addr + || settings->reg_num > ARRAY_SIZE(settings->reg_settings) + || settings->reg_num_6g > ARRAY_SIZE(settings->reg_settings_6g) + ) { + return false; + } - for (i = 0; i < settings->reg_num_6g; i++) { - if (settings->reg_settings_6g[i].i2c_reg_index > 0x20) - return false; - } - } + for (size_t i = 0; i < settings->reg_num; i++) { + if (settings->reg_settings[i].i2c_reg_index > 0x20) + return false; } - return result; + for (size_t i = 0; i < settings->reg_num_6g; i++) { + if (settings->reg_settings_6g[i].i2c_reg_index > 0x20) + return false; + } + return true; } -static bool write_i2c(struct pipe_ctx *pipe_ctx, - uint8_t address, uint8_t *buffer, uint32_t length) +static bool write_i2c( + const struct dc_link *link, + uint8_t address, + uint8_t *buffer, + uint32_t length +) { - struct i2c_command cmd = {0}; - struct i2c_payload payload = {0}; + struct i2c_payload payload = { + .write = true, + .address = address, + .length = length, + .data = buffer, + }; + struct i2c_command cmd = { + .payloads = &payload, + .number_of_payloads = 1, + .engine = I2C_COMMAND_ENGINE_DEFAULT, + .speed = link->ctx->dc->caps.i2c_speed_in_khz, + }; + + return dm_helpers_submit_i2c(link->ctx, link, &cmd); +} - memset(&payload, 0, sizeof(payload)); - memset(&cmd, 0, sizeof(cmd)); +static bool write_i2c_retimer_offset_value( + const struct dc_link *link, + uint8_t address, + uint8_t offset, + uint8_t value +) +{ + DC_LOGGER_INIT(link->ctx->logger); + uint8_t buffer[] = { offset, value }; + const bool success = write_i2c(link, address, buffer, sizeof(buffer)); + + RETIMER_REDRIVER_INFO( + "Retimer write, address: 0x%x, offset: 0x%x, value: 0x%x, success: %d\n", + address, offset, value, success + ); + return success; +} - cmd.number_of_payloads = 1; - cmd.engine = I2C_COMMAND_ENGINE_DEFAULT; - cmd.speed = pipe_ctx->stream->ctx->dc->caps.i2c_speed_in_khz; +static bool write_i2c_retimer_vga( + const struct dc_link *link, + uint8_t address +) +{ + DC_LOGGER_INIT(link->ctx->logger); + const uint8_t vga_data[][2] = { + { 0xFF, 0x01 }, + { 0x00, 0x23 }, + { 0xFF, 0x00 }, + }; + + for (size_t i = 0; i < ARRAY_SIZE(vga_data); i++) { + if (!write_i2c_retimer_offset_value(link, address, vga_data[i][0], vga_data[i][1])) { + DC_LOG_ERROR("Set retimer failed, vga index: %zu\n", i); + return false; + } + } + return true; +} - payload.address = address; - payload.data = buffer; - payload.length = length; - payload.write = true; - cmd.payloads = &payload; +static bool write_i2c_retimer_byte( + const struct dc_link *link, + uint8_t address, + uint8_t index, + uint8_t value +) +{ + DC_LOGGER_INIT(link->ctx->logger); + const uint8_t apply_rx_tx_change = 0x4; - if (dm_helpers_submit_i2c(pipe_ctx->stream->ctx, - pipe_ctx->stream->link, &cmd)) + if (index > 0x20) return true; - return false; + if (!write_i2c_retimer_offset_value(link, address, index, value)) { + DC_LOG_ERROR("Set retimer failed, 3g index: 0x%x, value: 0x%x\n", index, value); + return false; + } + + // Based on DP159 specs, APPLY_RX_TX_CHANGE bit in 0x0A + // needs to be set to 1 on every 0x0A-0x0C write. + if (0x0A <= index && index <= 0x0C) { + uint8_t offset = 0x0A; + + // Query current value from offset 0x0A + if (index == 0x0A) { + // Just written correct value, so no need to read it back + } else { + if (!link_query_ddc_data( + link->ddc, address, &offset, 1, &value, 1 + )) { + DC_LOG_ERROR("Set retimer failed, link_query_ddc_data\n"); + return false; + } + } + + value |= apply_rx_tx_change; + if (!write_i2c_retimer_offset_value(link, address, offset, value)) { + DC_LOG_ERROR("Set retimer failed, 3g offset: 0x%x, value: 0x%x\n", offset, value); + return false; + } + } + return true; } -static void write_i2c_retimer_setting( - struct pipe_ctx *pipe_ctx, +static bool write_i2c_retimer_setting( + const struct dc_link *link, bool is_vga_mode, bool is_over_340mhz, struct ext_hdmi_settings *settings) { - uint8_t slave_address = (settings->slv_addr >> 1); - uint8_t buffer[2]; - const uint8_t apply_rx_tx_change = 0x4; - uint8_t offset = 0xA; - uint8_t value = 0; - int i = 0; - bool i2c_success = false; - DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger); - - memset(&buffer, 0, sizeof(buffer)); - - /* Start Ext-Hdmi programming*/ - - for (i = 0; i < settings->reg_num; i++) { - /* Apply 3G settings */ - if (settings->reg_settings[i].i2c_reg_index <= 0x20) { - - buffer[0] = settings->reg_settings[i].i2c_reg_index; - buffer[1] = settings->reg_settings[i].i2c_reg_val; - i2c_success = write_i2c(pipe_ctx, slave_address, - buffer, sizeof(buffer)); - RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\ - offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n", - slave_address, buffer[0], buffer[1], i2c_success?1:0); - - if (!i2c_success) - goto i2c_write_fail; + DC_LOGGER_INIT(link->ctx->logger); + const uint8_t address = settings->slv_addr >> 1; - /* Based on DP159 specs, APPLY_RX_TX_CHANGE bit in 0x0A - * needs to be set to 1 on every 0xA-0xC write. - */ - if (settings->reg_settings[i].i2c_reg_index == 0xA || - settings->reg_settings[i].i2c_reg_index == 0xB || - settings->reg_settings[i].i2c_reg_index == 0xC) { - - /* Query current value from offset 0xA */ - if (settings->reg_settings[i].i2c_reg_index == 0xA) - value = settings->reg_settings[i].i2c_reg_val; - else { - i2c_success = - link_query_ddc_data( - pipe_ctx->stream->link->ddc, - slave_address, &offset, 1, &value, 1); - if (!i2c_success) - goto i2c_write_fail; - } + for (size_t i = 0; i < settings->reg_num; i++) { + const uint8_t index = settings->reg_settings[i].i2c_reg_index; + uint8_t value = settings->reg_settings[i].i2c_reg_val; - buffer[0] = offset; - /* Set APPLY_RX_TX_CHANGE bit to 1 */ - buffer[1] = value | apply_rx_tx_change; - i2c_success = write_i2c(pipe_ctx, slave_address, - buffer, sizeof(buffer)); - RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\ - offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", - slave_address, buffer[0], buffer[1], i2c_success?1:0); - if (!i2c_success) - goto i2c_write_fail; - } + if (!write_i2c_retimer_byte(link, address, index, value)) { + DC_LOG_ERROR("Set retimer failed, index: %zu\n", i); + return false; } } - /* Apply 3G settings */ if (is_over_340mhz) { - for (i = 0; i < settings->reg_num_6g; i++) { - /* Apply 3G settings */ - if (settings->reg_settings[i].i2c_reg_index <= 0x20) { - - buffer[0] = settings->reg_settings_6g[i].i2c_reg_index; - buffer[1] = settings->reg_settings_6g[i].i2c_reg_val; - i2c_success = write_i2c(pipe_ctx, slave_address, - buffer, sizeof(buffer)); - RETIMER_REDRIVER_INFO("above 340Mhz: retimer write to slave_address = 0x%x,\ - offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", - slave_address, buffer[0], buffer[1], i2c_success?1:0); - - if (!i2c_success) - goto i2c_write_fail; - - /* Based on DP159 specs, APPLY_RX_TX_CHANGE bit in 0x0A - * needs to be set to 1 on every 0xA-0xC write. - */ - if (settings->reg_settings_6g[i].i2c_reg_index == 0xA || - settings->reg_settings_6g[i].i2c_reg_index == 0xB || - settings->reg_settings_6g[i].i2c_reg_index == 0xC) { - - /* Query current value from offset 0xA */ - if (settings->reg_settings_6g[i].i2c_reg_index == 0xA) - value = settings->reg_settings_6g[i].i2c_reg_val; - else { - i2c_success = - link_query_ddc_data( - pipe_ctx->stream->link->ddc, - slave_address, &offset, 1, &value, 1); - if (!i2c_success) - goto i2c_write_fail; - } + for (size_t i = 0; i < settings->reg_num_6g; i++) { + const uint8_t index = settings->reg_settings_6g[i].i2c_reg_index; + uint8_t value = settings->reg_settings_6g[i].i2c_reg_val; - buffer[0] = offset; - /* Set APPLY_RX_TX_CHANGE bit to 1 */ - buffer[1] = value | apply_rx_tx_change; - i2c_success = write_i2c(pipe_ctx, slave_address, - buffer, sizeof(buffer)); - RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\ - offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", - slave_address, buffer[0], buffer[1], i2c_success?1:0); - if (!i2c_success) - goto i2c_write_fail; - } + if (!write_i2c_retimer_byte(link, address, index, value)) { + DC_LOG_ERROR("Set retimer failed, 6g index: %zu\n", i); + return false; } } } if (is_vga_mode) { - /* Program additional settings if using 640x480 resolution */ - - /* Write offset 0xFF to 0x01 */ - buffer[0] = 0xff; - buffer[1] = 0x01; - i2c_success = write_i2c(pipe_ctx, slave_address, - buffer, sizeof(buffer)); - RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\ - offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", - slave_address, buffer[0], buffer[1], i2c_success?1:0); - if (!i2c_success) - goto i2c_write_fail; - - /* Write offset 0x00 to 0x23 */ - buffer[0] = 0x00; - buffer[1] = 0x23; - i2c_success = write_i2c(pipe_ctx, slave_address, - buffer, sizeof(buffer)); - RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\ - offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", - slave_address, buffer[0], buffer[1], i2c_success?1:0); - if (!i2c_success) - goto i2c_write_fail; - - /* Write offset 0xff to 0x00 */ - buffer[0] = 0xff; - buffer[1] = 0x00; - i2c_success = write_i2c(pipe_ctx, slave_address, - buffer, sizeof(buffer)); - RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\ - offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", - slave_address, buffer[0], buffer[1], i2c_success?1:0); - if (!i2c_success) - goto i2c_write_fail; - - } - - return; - -i2c_write_fail: - DC_LOG_DEBUG("Set retimer failed"); + return write_i2c_retimer_vga(link, address); + } + return true; } -static void write_i2c_default_retimer_setting( - struct pipe_ctx *pipe_ctx, +static bool write_i2c_default_retimer_setting( + const struct dc_link *link, bool is_vga_mode, bool is_over_340mhz) { - uint8_t slave_address = (0xBA >> 1); - uint8_t buffer[2]; - bool i2c_success = false; - DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger); + const uint8_t address = 0xBA >> 1; - memset(&buffer, 0, sizeof(buffer)); - - /* Program Slave Address for tuning single integrity */ - /* Write offset 0x0A to 0x13 */ - buffer[0] = 0x0A; - buffer[1] = 0x13; - i2c_success = write_i2c(pipe_ctx, slave_address, - buffer, sizeof(buffer)); - RETIMER_REDRIVER_INFO("retimer writes default setting to slave_address = 0x%x,\ - offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", - slave_address, buffer[0], buffer[1], i2c_success?1:0); - if (!i2c_success) - goto i2c_write_fail; - - /* Write offset 0x0A to 0x17 */ - buffer[0] = 0x0A; - buffer[1] = 0x17; - i2c_success = write_i2c(pipe_ctx, slave_address, - buffer, sizeof(buffer)); - RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\ - offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", - slave_address, buffer[0], buffer[1], i2c_success?1:0); - if (!i2c_success) - goto i2c_write_fail; - - /* Write offset 0x0B to 0xDA or 0xD8 */ - buffer[0] = 0x0B; - buffer[1] = is_over_340mhz ? 0xDA : 0xD8; - i2c_success = write_i2c(pipe_ctx, slave_address, - buffer, sizeof(buffer)); - RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\ - offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", - slave_address, buffer[0], buffer[1], i2c_success?1:0); - if (!i2c_success) - goto i2c_write_fail; - - /* Write offset 0x0A to 0x17 */ - buffer[0] = 0x0A; - buffer[1] = 0x17; - i2c_success = write_i2c(pipe_ctx, slave_address, - buffer, sizeof(buffer)); - RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\ - offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n", - slave_address, buffer[0], buffer[1], i2c_success?1:0); - if (!i2c_success) - goto i2c_write_fail; - - /* Write offset 0x0C to 0x1D or 0x91 */ - buffer[0] = 0x0C; - buffer[1] = is_over_340mhz ? 0x1D : 0x91; - i2c_success = write_i2c(pipe_ctx, slave_address, - buffer, sizeof(buffer)); - RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\ - offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", - slave_address, buffer[0], buffer[1], i2c_success?1:0); - if (!i2c_success) - goto i2c_write_fail; - - /* Write offset 0x0A to 0x17 */ - buffer[0] = 0x0A; - buffer[1] = 0x17; - i2c_success = write_i2c(pipe_ctx, slave_address, - buffer, sizeof(buffer)); - RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\ - offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", - slave_address, buffer[0], buffer[1], i2c_success?1:0); - if (!i2c_success) - goto i2c_write_fail; + DC_LOGGER_INIT(link->ctx->logger); + const uint8_t data[][2] = { + { 0x0A, 0x13 }, + { 0x0A, 0x17 }, + { 0x0B, is_over_340mhz ? 0xDA : 0xD8 }, + { 0x0A, 0x17 }, + { 0x0C, is_over_340mhz ? 0x1D : 0x91 }, + { 0x0A, 0x17 }, + }; + + for (size_t i = 0; i < ARRAY_SIZE(data); i++) { + if (!write_i2c_retimer_offset_value(link, address, data[i][0], data[i][1])) { + DC_LOG_ERROR("Set default retimer failed, index: %zu\n", i); + return false; + } + } if (is_vga_mode) { - /* Program additional settings if using 640x480 resolution */ - - /* Write offset 0xFF to 0x01 */ - buffer[0] = 0xff; - buffer[1] = 0x01; - i2c_success = write_i2c(pipe_ctx, slave_address, - buffer, sizeof(buffer)); - RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\ - offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n", - slave_address, buffer[0], buffer[1], i2c_success?1:0); - if (!i2c_success) - goto i2c_write_fail; - - /* Write offset 0x00 to 0x23 */ - buffer[0] = 0x00; - buffer[1] = 0x23; - i2c_success = write_i2c(pipe_ctx, slave_address, - buffer, sizeof(buffer)); - RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\ - offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n", - slave_address, buffer[0], buffer[1], i2c_success?1:0); - if (!i2c_success) - goto i2c_write_fail; - - /* Write offset 0xff to 0x00 */ - buffer[0] = 0xff; - buffer[1] = 0x00; - i2c_success = write_i2c(pipe_ctx, slave_address, - buffer, sizeof(buffer)); - RETIMER_REDRIVER_INFO("retimer write default setting to slave_addr = 0x%x,\ - offset = 0x%x, reg_val= 0x%x, i2c_success = %d end here\n", - slave_address, buffer[0], buffer[1], i2c_success?1:0); - if (!i2c_success) - goto i2c_write_fail; - } - - return; - -i2c_write_fail: - DC_LOG_DEBUG("Set default retimer failed"); + return write_i2c_retimer_vga(link, address); + } + return true; } -static void write_i2c_redriver_setting( - struct pipe_ctx *pipe_ctx, +static bool write_i2c_redriver_setting( + const struct dc_link *link, bool is_over_340mhz) { - uint8_t slave_address = (0xF0 >> 1); - uint8_t buffer[16]; - bool i2c_success = false; - DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger); - - memset(&buffer, 0, sizeof(buffer)); - - // Program Slave Address for tuning single integrity - buffer[3] = 0x4E; - buffer[4] = 0x4E; - buffer[5] = 0x4E; - buffer[6] = is_over_340mhz ? 0x4E : 0x4A; - - i2c_success = write_i2c(pipe_ctx, slave_address, - buffer, sizeof(buffer)); - RETIMER_REDRIVER_INFO("redriver write 0 to all 16 reg offset expect following:\n\ - \t slave_addr = 0x%x, offset[3] = 0x%x, offset[4] = 0x%x,\ - offset[5] = 0x%x,offset[6] is_over_340mhz = 0x%x,\ - i2c_success = %d\n", - slave_address, buffer[3], buffer[4], buffer[5], buffer[6], i2c_success?1:0); - - if (!i2c_success) - DC_LOG_DEBUG("Set redriver failed"); + DC_LOGGER_INIT(link->ctx->logger); + const uint8_t address = 0xF0 >> 1; + uint8_t buffer[16] = { + [3] = 0x4E, + [4] = 0x4E, + [5] = 0x4E, + [6] = is_over_340mhz ? 0x4E : 0x4A, + }; + + const bool success = write_i2c(link, address, buffer, sizeof(buffer)); + + RETIMER_REDRIVER_INFO( + "Redriver write, address: 0x%x, buffer: { [3]: 0x%x, 0x%x, 0x%x, 0x%x }, success: %d\n", + address, buffer[3], buffer[4], buffer[5], buffer[6], success + ); + + if (!success) + DC_LOG_ERROR("Set redriver failed"); + return success; } static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off) @@ -1933,16 +1795,14 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) /* DP159, Retimer settings */ eng_id = pipe_ctx->stream_res.stream_enc->id; - if (get_ext_hdmi_settings(pipe_ctx, eng_id, &settings)) { - write_i2c_retimer_setting(pipe_ctx, - is_vga_mode, is_over_340mhz, &settings); + if (get_ext_hdmi_settings(stream->ctx->dc_bios->integrated_info, eng_id, &settings)) { + write_i2c_retimer_setting(link, is_vga_mode, is_over_340mhz, &settings); } else { - write_i2c_default_retimer_setting(pipe_ctx, - is_vga_mode, is_over_340mhz); + write_i2c_default_retimer_setting(link, is_vga_mode, is_over_340mhz); } } else if (masked_chip_caps == AMD_EXT_DISPLAY_PATH_CAPS__HDMI20_PI3EQX1204) { /* PI3EQX1204, Redriver settings */ - write_i2c_redriver_setting(pipe_ctx, is_over_340mhz); + write_i2c_redriver_setting(link, is_over_340mhz); } } @@ -2364,15 +2224,13 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx) false); if (masked_chip_caps == AMD_EXT_DISPLAY_PATH_CAPS__HDMI20_TISN65DP159RSBT) { /* DP159, Retimer settings */ - if (get_ext_hdmi_settings(pipe_ctx, eng_id, &settings)) - write_i2c_retimer_setting(pipe_ctx, - false, false, &settings); + if (get_ext_hdmi_settings(stream->ctx->dc_bios->integrated_info, eng_id, &settings)) + write_i2c_retimer_setting(link, false, false, &settings); else - write_i2c_default_retimer_setting(pipe_ctx, - false, false); + write_i2c_default_retimer_setting(link, false, false); } else if (masked_chip_caps == AMD_EXT_DISPLAY_PATH_CAPS__HDMI20_PI3EQX1204) { /* PI3EQX1204, Redriver settings */ - write_i2c_redriver_setting(pipe_ctx, false); + write_i2c_redriver_setting(link, false); } } diff --git a/drivers/gpu/drm/amd/display/dc/link/link_factory.c b/drivers/gpu/drm/amd/display/dc/link/link_factory.c index 21815ad01a29..7e7682d7dfc8 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_factory.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_factory.c @@ -367,6 +367,18 @@ static enum transmitter translate_encoder_to_transmitter( } } +static bool encoder_is_external_dp( + struct graphics_object_id encoder) +{ + switch (encoder.id) { + case ENCODER_ID_EXTERNAL_NUTMEG: + case ENCODER_ID_EXTERNAL_TRAVIS: + return true; + default: + return false; + } +} + static void link_destruct(struct dc_link *link) { int i; @@ -514,6 +526,13 @@ static bool construct_phy(struct dc_link *link, * so that we avoid initializing DDC and HPD, etc. */ bp_funcs->get_src_obj(bios, link->link_id, 0, &link_encoder); + + if (encoder_is_external_dp(link_encoder)) { + /* External DP bridge encoders: find the actual link encoder and use that. */ + link->ext_enc_id = link_encoder; + bp_funcs->get_src_obj(bios, link->ext_enc_id, 0, &link_encoder); + } + transmitter_from_encoder = translate_encoder_to_transmitter(link_encoder); link_analog_engine = find_analog_engine(link, &enc_init_data.analog_encoder); @@ -691,6 +710,13 @@ static bool construct_phy(struct dc_link *link, goto create_fail; } + /* For external DP bridge encoders: + * Set the connector signal to DisplayPort so that they can work with + * the pre-existing code paths for DP without a lot of code churn. + */ + if (link->ext_enc_id.id != ENCODER_ID_UNKNOWN) + link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT; + LINK_INFO("Connector[%d] description: signal: %s\n", init_params->connector_index, signal_type_to_string(link->connector_signal)); @@ -735,7 +761,8 @@ static bool construct_phy(struct dc_link *link, link->device_tag.dev_id)) continue; if (link->device_tag.dev_id.device_type == DEVICE_TYPE_CRT && - link->connector_signal != SIGNAL_TYPE_RGB) + link->connector_signal != SIGNAL_TYPE_RGB && + link->ext_enc_id.id == ENCODER_ID_UNKNOWN) continue; if (link->device_tag.dev_id.device_type == DEVICE_TYPE_LCD && link->connector_signal == SIGNAL_TYPE_RGB) diff --git a/drivers/gpu/drm/amd/display/dc/link/link_validation.c b/drivers/gpu/drm/amd/display/dc/link/link_validation.c index acdc162de535..eb791285ed06 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_validation.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_validation.c @@ -391,6 +391,7 @@ static const struct dc_tunnel_settings *get_dp_tunnel_settings(const struct dc_s */ enum dc_status link_validate_dp_tunnel_bandwidth(const struct dc *dc, const struct dc_state *new_ctx) { + (void)dc; struct dc_validation_dpia_set dpia_link_sets[MAX_DPIA_NUM] = { 0 }; uint8_t link_count = 0; enum dc_status result = DC_OK; diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c index cdc7587cf0b6..e12bf3dd3e46 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c @@ -743,6 +743,8 @@ static bool decide_dp_link_settings(struct dc_link *link, struct dc_link_setting { struct dc_link_settings initial_link_setting = { LANE_COUNT_ONE, LINK_RATE_LOW, LINK_SPREAD_DISABLED, false, 0}; + if (link->preferred_link_setting.link_rate != LINK_RATE_UNKNOWN) + initial_link_setting.link_rate = link->preferred_link_setting.link_rate; struct dc_link_settings current_link_setting = initial_link_setting; uint32_t link_bw; diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.c index 9b2f1a7da1d1..766b54631c79 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.c @@ -71,7 +71,7 @@ enum dc_status dpcd_get_tunneling_device_data(struct dc_link *link) link->dpcd_caps.usb4_dp_tun_info.dpia_info.raw = dpcd_dp_tun_data[DP_IN_ADAPTER_INFO - DP_TUNNELING_CAPABILITIES_SUPPORT]; link->dpcd_caps.usb4_dp_tun_info.usb4_driver_id = - dpcd_dp_tun_data[DP_USB4_DRIVER_ID - DP_TUNNELING_CAPABILITIES_SUPPORT]; + dpcd_dp_tun_data[DP_USB4_DRIVER_ID - DP_TUNNELING_CAPABILITIES_SUPPORT] & 0x0F; if (link->dpcd_caps.usb4_dp_tun_info.dp_tun_cap.bits.dpia_bw_alloc) { status = core_link_read_dpcd(link, USB4_DRIVER_BW_CAPABILITY, diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c index cc18a3bebef2..1860d44f63c1 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c @@ -223,9 +223,10 @@ static void handle_hpd_irq_vesa_replay_sink(struct dc_link *link) } } -static void handle_hpd_irq_replay_sink(struct dc_link *link) +static void handle_hpd_irq_replay_sink(struct dc_link *link, bool *need_re_enable) { union dpcd_replay_configuration replay_configuration = {0}; + union dpcd_replay_configuration replay_sink_status = {0}; /*AMD Replay version reuse DP_PSR_ERROR_STATUS for REPLAY_ERROR status.*/ union psr_error_status replay_error_status = {0}; bool ret = false; @@ -265,9 +266,17 @@ static void handle_hpd_irq_replay_sink(struct dc_link *link) &replay_error_status.raw, sizeof(replay_error_status.raw)); + dm_helpers_dp_read_dpcd( + link->ctx, + link, + DP_PR_REPLAY_SINK_STATUS, + &replay_sink_status.raw, + 1); + if (replay_error_status.bits.LINK_CRC_ERROR || replay_configuration.bits.DESYNC_ERROR_STATUS || - replay_configuration.bits.STATE_TRANSITION_ERROR_STATUS) { + replay_configuration.bits.STATE_TRANSITION_ERROR_STATUS || + replay_sink_status.bits.SINK_DEVICE_REPLAY_STATUS == 0x7) { bool allow_active; link->replay_settings.config.replay_error_status.raw |= replay_error_status.raw; @@ -299,8 +308,7 @@ static void handle_hpd_irq_replay_sink(struct dc_link *link) if (link->replay_settings.replay_allow_active) { allow_active = false; edp_set_replay_allow_active(link, &allow_active, true, false, NULL); - allow_active = true; - edp_set_replay_allow_active(link, &allow_active, true, false, NULL); + *need_re_enable = true; } } } @@ -460,6 +468,7 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link, union device_service_irq device_service_clear = {0}; enum dc_status result; bool status = false; + bool replay_re_enable_needed = false; if (out_link_loss) *out_link_loss = false; @@ -519,7 +528,7 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link, /* PSR-related error was detected and handled */ return true; - handle_hpd_irq_replay_sink(link); + handle_hpd_irq_replay_sink(link, &replay_re_enable_needed); /* If PSR-related error handled, Main link may be off, * so do not handle as a normal sink status change interrupt. @@ -538,16 +547,16 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link, return false; } - /* For now we only handle 'Downstream port status' case. + /* Handle 'Downstream port status' case for all DP link types. * If we got sink count changed it means * Downstream port status changed, * then DM should call DC to do the detection. - * NOTE: Do not handle link loss on eDP since it is internal link + * NOTE: Now includes eDP link loss detection and retraining */ - if ((link->connector_signal != SIGNAL_TYPE_EDP) && - dp_parse_link_loss_status( - link, - &hpd_irq_dpcd_data)) { + + if (dp_parse_link_loss_status( + link, + &hpd_irq_dpcd_data)) { /* Connectivity log: link loss */ CONN_DATA_LINK_LOSS(link, hpd_irq_dpcd_data.raw, @@ -576,6 +585,11 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link, != link->dpcd_sink_count) status = true; + if (replay_re_enable_needed) { + bool allow_active = true; + + edp_set_replay_allow_active(link, &allow_active, true, false, NULL); + } /* reasons for HPD RX: * 1. Link Loss - ie Re-train the Link * 2. MST sideband message diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_panel_replay.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_panel_replay.c index 7e45d1e767bb..96afce4ffbfa 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_panel_replay.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_panel_replay.c @@ -252,23 +252,24 @@ bool dp_pr_enable(struct dc_link *link, bool enable) if (!dp_pr_get_panel_inst(dc, link, &panel_inst)) return false; + if (link->replay_settings.replay_allow_active == enable) + return true; + if (enable && !dc_is_embedded_signal(link->connector_signal)) dp_pr_set_static_screen_param(link); - if (link->replay_settings.replay_allow_active != enable) { - //for sending PR enable commands to DMUB - memset(&cmd, 0, sizeof(cmd)); + // for sending PR enable commands to DMUB + memset(&cmd, 0, sizeof(cmd)); - cmd.pr_enable.header.type = DMUB_CMD__PR; - cmd.pr_enable.header.sub_type = DMUB_CMD__PR_ENABLE; - cmd.pr_enable.header.payload_bytes = sizeof(struct dmub_cmd_pr_enable_data); - cmd.pr_enable.data.panel_inst = panel_inst; - cmd.pr_enable.data.enable = enable ? 1 : 0; + cmd.pr_enable.header.type = DMUB_CMD__PR; + cmd.pr_enable.header.sub_type = DMUB_CMD__PR_ENABLE; + cmd.pr_enable.header.payload_bytes = sizeof(struct dmub_cmd_pr_enable_data); + cmd.pr_enable.data.panel_inst = panel_inst; + cmd.pr_enable.data.enable = enable ? 1 : 0; + dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); - dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + link->replay_settings.replay_allow_active = enable; - link->replay_settings.replay_allow_active = enable; - } return true; } @@ -389,7 +390,7 @@ bool dp_pr_get_state(const struct dc_link *link, uint64_t *state) const struct dc *dc = link->ctx->dc; unsigned int panel_inst = 0; uint32_t retry_count = 0; - uint32_t replay_state = 0; + uint32_t replay_state = PR_STATE_INVALID; if (!dp_pr_get_panel_inst(dc, link, &panel_inst)) return false; diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c index 08e2b572e0ff..ddff0db4ce70 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c @@ -554,6 +554,7 @@ enum link_training_result dp_check_link_loss_status( struct dc_link *link, const struct link_training_settings *link_training_setting) { + (void)link_training_setting; enum link_training_result status = LINK_TRAINING_SUCCESS; union lane_status lane_status; union lane_align_status_updated dpcd_lane_status_updated; @@ -1387,6 +1388,7 @@ bool dp_set_hw_training_pattern( enum dc_dp_training_pattern pattern, uint32_t offset) { + (void)offset; enum dp_test_pattern test_pattern = DP_TEST_PATTERN_UNSUPPORTED; switch (pattern) { diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.c index 11565f187ac7..1a6bfc45927d 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.c @@ -158,6 +158,7 @@ static enum link_training_result dp_perform_128b_132b_cds_done_sequence( const struct link_resource *link_res, struct link_training_settings *lt_settings) { + (void)link_res; /* Assumption: assume hardware has transmitted eq pattern */ enum dc_status status = DC_OK; enum link_training_result result = LINK_TRAINING_SUCCESS; diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c index 603537ffd128..34fa76d97b83 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c @@ -172,6 +172,7 @@ static uint8_t dpia_build_set_config_data( struct dc_link *link, struct link_training_settings *lt_settings) { + (void)link; union dpia_set_config_data data; data.raw = 0; @@ -290,6 +291,7 @@ static enum link_training_result dpia_training_cr_non_transparent( struct link_training_settings *lt_settings, uint32_t hop) { + (void)link_res; enum link_training_result result = LINK_TRAINING_CR_FAIL_LANE0; uint8_t repeater_cnt = 0; /* Number of hops/repeaters in display path. */ enum dc_status status = DC_ERROR_UNEXPECTED; @@ -457,6 +459,7 @@ static enum link_training_result dpia_training_cr_transparent( const struct link_resource *link_res, struct link_training_settings *lt_settings) { + (void)link_res; enum link_training_result result = LINK_TRAINING_CR_FAIL_LANE0; enum dc_status status; uint32_t retries_cr = 0; /* Number of consecutive attempts with same VS or PE. */ @@ -585,6 +588,7 @@ static enum link_training_result dpia_training_eq_non_transparent( struct link_training_settings *lt_settings, uint32_t hop) { + (void)link_res; enum link_training_result result = LINK_TRAINING_EQ_FAIL_EQ; uint8_t repeater_cnt = 0; /* Number of hops/repeaters in display path. */ uint32_t retries_eq = 0; @@ -730,6 +734,7 @@ static enum link_training_result dpia_training_eq_transparent( const struct link_resource *link_res, struct link_training_settings *lt_settings) { + (void)link_res; enum link_training_result result = LINK_TRAINING_EQ_FAIL_EQ; uint32_t retries_eq = 0; enum dc_status status; @@ -991,6 +996,7 @@ enum link_training_result dpia_perform_link_training( const struct dc_link_settings *link_setting, bool skip_video_pattern) { + (void)skip_video_pattern; enum link_training_result result; struct link_training_settings lt_settings = {0}; uint8_t repeater_cnt = 0; /* Number of hops/repeaters in display path. */ diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dpcd.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dpcd.c index 584b9295a12a..e4c2aa2bc364 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dpcd.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dpcd.c @@ -180,6 +180,7 @@ static void dpcd_reduce_address_range( uint8_t * const reduced_data, const uint32_t reduced_size) { + (void)extended_size; const uint32_t offset = reduced_address - extended_address; /* diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c index aa02b38e183a..4a2699a374b7 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c @@ -100,11 +100,7 @@ void dp_set_panel_mode(struct dc_link *link, enum dp_panel_mode panel_mode) enum dp_panel_mode dp_get_panel_mode(struct dc_link *link) { - /* We need to explicitly check that connector - * is not DP. Some Travis_VGA get reported - * by video bios as DP. - */ - if (link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT) { + if (link->ext_enc_id.id) { switch (link->dpcd_caps.branch_dev_id) { case DP_BRANCH_DEVICE_ID_0022B9: @@ -124,7 +120,7 @@ enum dp_panel_mode dp_get_panel_mode(struct dc_link *link) } break; case DP_BRANCH_DEVICE_ID_00001A: - /* alternate scrambler reset is required for Travis + /* alternate scrambler reset is required for NUTMEG * for the case when external chip does not provide * sink device id, alternate scrambler scheme will * be overriden later by querying Encoder feature @@ -851,6 +847,7 @@ bool edp_setup_psr(struct dc_link *link, case FAMILY_YELLOW_CARP: case AMDGPU_FAMILY_GC_10_3_6: case AMDGPU_FAMILY_GC_11_0_1: + case AMDGPU_FAMILY_GC_11_5_4: if (dc->debug.disable_z10 || dc->debug.psr_skip_crtc_disable) psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true; break; @@ -1098,8 +1095,6 @@ bool edp_send_replay_cmd(struct dc_link *link, if (!replay) return false; - DC_LOGGER_INIT(link->ctx->logger); - if (dp_pr_get_panel_inst(dc, link, &panel_inst)) cmd_data->panel_inst = panel_inst; else { diff --git a/drivers/gpu/drm/amd/display/dc/mmhubbub/Makefile b/drivers/gpu/drm/amd/display/dc/mmhubbub/Makefile index 2d4b7a85847d..afc376defa0b 100644 --- a/drivers/gpu/drm/amd/display/dc/mmhubbub/Makefile +++ b/drivers/gpu/drm/amd/display/dc/mmhubbub/Makefile @@ -1,5 +1,5 @@ # -# Copyright 2020 Advanced Micro Devices, Inc. +# Copyright 2020-2026 Advanced Micro Devices, Inc. # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), @@ -52,3 +52,11 @@ AMD_DAL_MMHUBBUB_DCN35 = $(addprefix $(AMDDALPATH)/dc/mmhubbub/dcn35/,$(MMHUBBUB AMD_DISPLAY_FILES += $(AMD_DAL_MMHUBBUB_DCN35) endif +############################################################################### +# DCN42 +############################################################################### +MMHUBBUB_DCN42 = dcn42_mmhubbub.o + +AMD_DAL_MMHUBBUB_DCN42 = $(addprefix $(AMDDALPATH)/dc/mmhubbub/dcn42/,$(MMHUBBUB_DCN42)) + +AMD_DISPLAY_FILES += $(AMD_DAL_MMHUBBUB_DCN42) diff --git a/drivers/gpu/drm/amd/display/dc/mmhubbub/dcn42/dcn42_mmhubbub.c b/drivers/gpu/drm/amd/display/dc/mmhubbub/dcn42/dcn42_mmhubbub.c new file mode 100644 index 000000000000..4700bdc8701d --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/mmhubbub/dcn42/dcn42_mmhubbub.c @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT +// +// Copyright 2026 Advanced Micro Devices, Inc. + +#include "dcn35/dcn35_mmhubbub.h" +#include "dcn42_mmhubbub.h" +#include "reg_helper.h" + +#define REG(reg) \ + ((const struct dcn35_mmhubbub_registers *)(mcif_wb30->mcif_wb_regs)) \ + ->reg + +#define CTX mcif_wb30->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + ((const struct dcn35_mmhubbub_shift *)(mcif_wb30->mcif_wb_shift)) \ + ->field_name, \ + ((const struct dcn35_mmhubbub_mask *)(mcif_wb30->mcif_wb_mask)) \ + ->field_name + +void dcn42_mmhubbub_set_fgcg(struct dcn30_mmhubbub *mcif_wb30, bool enabled) +{ + REG_UPDATE(MMHUBBUB_CLOCK_CNTL, MMHUBBUB_FGCG_REP_DIS, !enabled); +} diff --git a/drivers/gpu/drm/amd/display/dc/mmhubbub/dcn42/dcn42_mmhubbub.h b/drivers/gpu/drm/amd/display/dc/mmhubbub/dcn42/dcn42_mmhubbub.h new file mode 100644 index 000000000000..0dd1f0d2eb88 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/mmhubbub/dcn42/dcn42_mmhubbub.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright 2026 Advanced Micro Devices, Inc. */ + + +#ifndef __DCN42_MMHUBBUB_H +#define __DCN42_MMHUBBUB_H + +#include "mcif_wb.h" +#include "dcn32/dcn32_mmhubbub.h" +#include "dcn35/dcn35_mmhubbub.h" + +void dcn42_mmhubbub_set_fgcg(struct dcn30_mmhubbub *mcif_wb30, bool enabled); +#endif // __DCN42_MMHUBBUB_H diff --git a/drivers/gpu/drm/amd/display/dc/mpc/Makefile b/drivers/gpu/drm/amd/display/dc/mpc/Makefile index 5402c3529f5e..cc23aae3728a 100644 --- a/drivers/gpu/drm/amd/display/dc/mpc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/mpc/Makefile @@ -1,5 +1,5 @@ # -# Copyright 2020 Advanced Micro Devices, Inc. +# Copyright 2020-2026 Advanced Micro Devices, Inc. # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), @@ -69,4 +69,12 @@ AMD_DAL_MPC_DCN401 = $(addprefix $(AMDDALPATH)/dc/mpc/dcn401/,$(MPC_DCN401)) AMD_DISPLAY_FILES += $(AMD_DAL_MPC_DCN401) +############################################################################### +# DCN42 +############################################################################### +MPC_DCN42 = dcn42_mpc.o + +AMD_DAL_MPC_DCN42 = $(addprefix $(AMDDALPATH)/dc/mpc/dcn42/,$(MPC_DCN42)) + +AMD_DISPLAY_FILES += $(AMD_DAL_MPC_DCN42) endif diff --git a/drivers/gpu/drm/amd/display/dc/mpc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/mpc/dcn10/dcn10_mpc.c index b23c64004dd5..27e653234850 100644 --- a/drivers/gpu/drm/amd/display/dc/mpc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn10/dcn10_mpc.c @@ -118,9 +118,7 @@ void mpc1_assert_idle_mpcc(struct mpc *mpc, int id) struct mpcc *mpc1_get_mpcc(struct mpc *mpc, int mpcc_id) { - struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); - - ASSERT(mpcc_id < mpc10->num_mpcc); + ASSERT(mpcc_id < TO_DCN10_MPC(mpc)->num_mpcc); return &(mpc->mpcc_array[mpcc_id]); } diff --git a/drivers/gpu/drm/amd/display/dc/mpc/dcn30/dcn30_mpc.c b/drivers/gpu/drm/amd/display/dc/mpc/dcn30/dcn30_mpc.c index 6bfd2c1294e5..4c7bb0522a8c 100644 --- a/drivers/gpu/drm/amd/display/dc/mpc/dcn30/dcn30_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn30/dcn30_mpc.c @@ -117,6 +117,9 @@ void mpc3_set_out_rate_control( bool rate_2x_mode, struct mpc_dwb_flow_control *flow_control) { + (void)enable; + (void)rate_2x_mode; + (void)flow_control; struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); /* Always disable mpc out rate and flow control. @@ -908,6 +911,7 @@ static void mpc3_set_3dlut_mode( bool is_lut_size17x17x17, uint32_t rmu_idx) { + (void)is_color_channel_12bits; uint32_t lut_mode; struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); @@ -1428,7 +1432,7 @@ uint32_t mpcc3_acquire_rmu(struct mpc *mpc, int mpcc_id, int rmu_idx) } //no vacant RMU units or invalid parameters acquire_post_bldn_3dlut - return -1; + return (uint32_t)-1; } static int mpcc3_release_rmu(struct mpc *mpc, int mpcc_id) diff --git a/drivers/gpu/drm/amd/display/dc/mpc/dcn32/dcn32_mpc.c b/drivers/gpu/drm/amd/display/dc/mpc/dcn32/dcn32_mpc.c index badcef027b84..1f15ada109b6 100644 --- a/drivers/gpu/drm/amd/display/dc/mpc/dcn32/dcn32_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn32/dcn32_mpc.c @@ -884,6 +884,7 @@ void mpc32_set_3dlut_mode( bool is_lut_size17x17x17, uint32_t mpcc_id) { + (void)is_color_channel_12bits; uint32_t lut_mode; struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); 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 eeac13fdd6f5..e0617db2d0c1 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 @@ -1,5 +1,5 @@ /* - * Copyright 2023 Advanced Micro Devices, Inc. + * Copyright 2023-2026 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -47,6 +47,16 @@ void mpc401_update_3dlut_fast_load_select(struct mpc *mpc, int mpcc_id, int hubp REG_SET(MPCC_MCM_3DLUT_FAST_LOAD_SELECT[mpcc_id], 0, MPCC_MCM_3DLUT_FL_SEL, hubp_idx); } +void mpc401_get_3dlut_fast_load_status(struct mpc *mpc, int mpcc_id, uint32_t *done, uint32_t *soft_underflow, uint32_t *hard_underflow) +{ + struct dcn401_mpc *mpc401 = TO_DCN401_MPC(mpc); + + REG_GET_3(MPCC_MCM_3DLUT_FAST_LOAD_STATUS[mpcc_id], + MPCC_MCM_3DLUT_FL_DONE, done, + MPCC_MCM_3DLUT_FL_SOFT_UNDERFLOW, soft_underflow, + MPCC_MCM_3DLUT_FL_HARD_UNDERFLOW, hard_underflow); +} + void mpc401_set_movable_cm_location(struct mpc *mpc, enum mpcc_movable_cm_location location, int mpcc_id) { struct dcn401_mpc *mpc401 = TO_DCN401_MPC(mpc); @@ -63,56 +73,15 @@ void mpc401_set_movable_cm_location(struct mpc *mpc, enum mpcc_movable_cm_locati } } -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) +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) { 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; @@ -121,7 +90,7 @@ void mpc401_populate_lut(struct mpc *mpc, const enum MCM_LUT_ID id, const union 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: @@ -164,8 +133,6 @@ void mpc401_populate_lut(struct mpc *mpc, const enum MCM_LUT_ID id, const union 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) { @@ -188,8 +155,6 @@ void mpc401_populate_lut(struct mpc *mpc, const enum MCM_LUT_ID id, const union 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); @@ -222,46 +187,69 @@ void mpc401_populate_lut(struct mpc *mpc, const enum MCM_LUT_ID id, const union } +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 enum MCM_LUT_XABLE xable, - bool lut_bank_a, - int mpcc_id) + const bool enable, + const bool lut_bank_a, + const enum dc_cm_lut_size size, + const int mpcc_id) { + uint32_t lut_size; struct dcn401_mpc *mpc401 = TO_DCN401_MPC(mpc); switch (id) { case MCM_LUT_3DLUT: - switch (xable) { - case MCM_LUT_DISABLE: + 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); 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: - 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: + if (enable) { REG_UPDATE(MPCC_MCM_SHAPER_CONTROL[mpcc_id], MPCC_MCM_SHAPER_LUT_MODE, lut_bank_a ? 1 : 2); - break; + } else { + if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) + mpc32_power_on_shaper_3dlut(mpc, mpcc_id, false); + REG_UPDATE(MPCC_MCM_SHAPER_CONTROL[mpcc_id], MPCC_MCM_SHAPER_LUT_MODE, 0); } break; case MCM_LUT_1DLUT: - switch (xable) { - case MCM_LUT_DISABLE: - REG_UPDATE(MPCC_MCM_1DLUT_CONTROL[mpcc_id], - MPCC_MCM_1DLUT_MODE, 0); - break; - case MCM_LUT_ENABLE: + if (enable) { REG_UPDATE(MPCC_MCM_1DLUT_CONTROL[mpcc_id], MPCC_MCM_1DLUT_MODE, 2); - break; + } else { + if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) + mpc32_power_on_blnd_lut(mpc, mpcc_id, false); + REG_UPDATE(MPCC_MCM_1DLUT_CONTROL[mpcc_id], + MPCC_MCM_1DLUT_MODE, 0); } REG_UPDATE(MPCC_MCM_1DLUT_CONTROL[mpcc_id], MPCC_MCM_1DLUT_SELECT, lut_bank_a ? 0 : 1); @@ -269,14 +257,20 @@ void mpc401_program_lut_mode( } } -void mpc401_program_lut_read_write_control(struct mpc *mpc, const enum MCM_LUT_ID id, 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) { 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(MPCC_MCM_3DLUT_READ_WRITE_CONTROL[mpcc_id], MPCC_MCM_3DLUT_RAM_SEL, lut_bank_a ? 0 : 1); + 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); break; case MCM_LUT_SHAPER: mpc32_configure_shaper_lut(mpc, lut_bank_a, mpcc_id); @@ -568,6 +562,44 @@ 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, @@ -602,9 +634,11 @@ static const struct mpc_funcs dcn401_mpc_funcs = { .set_bg_color = mpc1_set_bg_color, .set_movable_cm_location = mpc401_set_movable_cm_location, .update_3dlut_fast_load_select = mpc401_update_3dlut_fast_load_select, + .get_3dlut_fast_load_status = mpc401_get_3dlut_fast_load_status, .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 fdc42f8ab3ff..c16560c84453 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 @@ -1,5 +1,5 @@ /* - * Copyright 2023 Advanced Micro Devices, Inc. + * Copyright 2023-2026 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -184,6 +184,7 @@ struct dcn401_mpc_mask { struct dcn401_mpc_registers { MPC_REG_VARIABLE_LIST_DCN4_01 + uint32_t MPCC_CONTROL2[MAX_MPCC]; }; struct dcn401_mpc { @@ -205,21 +206,32 @@ 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 enum MCM_LUT_XABLE xable, - bool lut_bank_a, - int mpcc_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); void mpc401_program_lut_read_write_control( struct mpc *mpc, const enum MCM_LUT_ID id, - bool lut_bank_a, - int mpcc_id); + const bool lut_bank_a, + const unsigned int bit_depth, + const int mpcc_id); void mpc401_set_gamut_remap( struct mpc *mpc, @@ -249,6 +261,13 @@ void mpc_read_gamut_remap(struct mpc *mpc, enum mpcc_gamut_remap_id gamut_remap_block_id, uint32_t *mode_select); +void mpc401_get_3dlut_fast_load_status( + struct mpc *mpc, + int mpcc_id, + uint32_t *done, + uint32_t *soft_underflow, + uint32_t *hard_underflow); + void mpc401_update_3dlut_fast_load_select( struct mpc *mpc, int mpcc_id, 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 new file mode 100644 index 000000000000..507dbdbea600 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.c @@ -0,0 +1,797 @@ +// SPDX-License-Identifier: MIT +// +// Copyright 2026 Advanced Micro Devices, Inc. + +#include "reg_helper.h" +#include "dc.h" +#include "dcn42_mpc.h" +#include "dcn10/dcn10_cm_common.h" +#include "basics/conversion.h" +#include "mpc.h" + +#define REG(reg)\ + mpc42->mpc_regs->reg + +#define CTX \ + mpc42->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + mpc42->mpc_shift->field_name, mpc42->mpc_mask->field_name + + +void mpc42_init_mpcc(struct mpcc *mpcc, int mpcc_inst) +{ + mpcc->mpcc_id = mpcc_inst; + mpcc->dpp_id = 0xf; + mpcc->mpcc_bot = NULL; + mpcc->blnd_cfg.overlap_only = false; + mpcc->blnd_cfg.global_alpha = 0xfff; + mpcc->blnd_cfg.global_gain = 0xfff; + mpcc->blnd_cfg.background_color_bpc = 4; + mpcc->blnd_cfg.bottom_gain_mode = 0; + mpcc->blnd_cfg.top_gain = 0x1f000; + mpcc->blnd_cfg.bottom_inside_gain = 0x1f000; + mpcc->blnd_cfg.bottom_outside_gain = 0x1f000; + mpcc->sm_cfg.enable = false; + mpcc->shared_bottom = false; +} + +void mpc42_update_blending( + struct mpc *mpc, + struct mpcc_blnd_cfg *blnd_cfg, + int mpcc_id) +{ + struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc); + + struct mpcc *mpcc = mpc1_get_mpcc(mpc, mpcc_id); + + REG_UPDATE_5(MPCC_CONTROL[mpcc_id], + MPCC_ALPHA_BLND_MODE, blnd_cfg->alpha_mode, + MPCC_ALPHA_MULTIPLIED_MODE, blnd_cfg->pre_multiplied_alpha, + MPCC_BLND_ACTIVE_OVERLAP_ONLY, blnd_cfg->overlap_only, + MPCC_BG_BPC, blnd_cfg->background_color_bpc, + MPCC_BOT_GAIN_MODE, blnd_cfg->bottom_gain_mode); + REG_UPDATE_2(MPCC_CONTROL2[mpcc_id], + MPCC_GLOBAL_ALPHA, blnd_cfg->global_alpha, + MPCC_GLOBAL_GAIN, blnd_cfg->global_gain); + + REG_SET(MPCC_TOP_GAIN[mpcc_id], 0, MPCC_TOP_GAIN, blnd_cfg->top_gain); + REG_SET(MPCC_BOT_GAIN_INSIDE[mpcc_id], 0, MPCC_BOT_GAIN_INSIDE, blnd_cfg->bottom_inside_gain); + REG_SET(MPCC_BOT_GAIN_OUTSIDE[mpcc_id], 0, MPCC_BOT_GAIN_OUTSIDE, blnd_cfg->bottom_outside_gain); + + mpcc->blnd_cfg = *blnd_cfg; +} + +/* RMCM Shaper functions */ +void mpc42_power_on_rmcm_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(MPC_RMCM_MEM_PWR_CTRL[mpcc_id], 0, + MPC_RMCM_3DLUT_MEM_PWR_DIS, power_on == true ? 0 : 1); + REG_SET(MPC_RMCM_MEM_PWR_CTRL[mpcc_id], 0, + MPC_RMCM_SHAPER_MEM_PWR_DIS, power_on == true ? 0 : 1); + /* wait for memory to fully power up */ + if (power_on && mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) { + REG_WAIT(MPC_RMCM_MEM_PWR_CTRL[mpcc_id], MPC_RMCM_SHAPER_MEM_PWR_STATE, 0, 1, max_retries); + REG_WAIT(MPC_RMCM_MEM_PWR_CTRL[mpcc_id], MPC_RMCM_3DLUT_MEM_PWR_STATE, 0, 1, max_retries); + } + + /*read status is not mandatory, it is just for debugging*/ + REG_GET(MPC_RMCM_MEM_PWR_CTRL[mpcc_id], MPC_RMCM_SHAPER_MEM_PWR_STATE, &power_status_shaper); + REG_GET(MPC_RMCM_MEM_PWR_CTRL[mpcc_id], MPC_RMCM_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_rmcm_shaper_lut( + struct mpc *mpc, + bool is_ram_a, + uint32_t mpcc_id) +{ + struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc); + + REG_UPDATE(MPC_RMCM_SHAPER_SCALE_G_B[mpcc_id], + MPC_RMCM_SHAPER_SCALE_B, 0x7000); + REG_UPDATE(MPC_RMCM_SHAPER_SCALE_G_B[mpcc_id], + MPC_RMCM_SHAPER_SCALE_G, 0x7000); + REG_UPDATE(MPC_RMCM_SHAPER_SCALE_R[mpcc_id], + MPC_RMCM_SHAPER_SCALE_R, 0x7000); + REG_UPDATE(MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK[mpcc_id], + MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK, 7); + REG_UPDATE(MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK[mpcc_id], + MPC_RMCM_SHAPER_LUT_WRITE_SEL, is_ram_a == true ? 0:1); + REG_SET(MPC_RMCM_SHAPER_LUT_INDEX[mpcc_id], 0, MPC_RMCM_SHAPER_LUT_INDEX, 0); +} + +void mpc42_program_rmcm_shaper_luta_settings( + struct mpc *mpc, + const struct pwl_params *params, + uint32_t mpcc_id) +{ + const struct gamma_curve *curve; + struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc); + + REG_SET_2(MPC_RMCM_SHAPER_RAMA_START_CNTL_B[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].blue.custom_float_x, + MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0); + REG_SET_2(MPC_RMCM_SHAPER_RAMA_START_CNTL_G[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].green.custom_float_x, + MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0); + REG_SET_2(MPC_RMCM_SHAPER_RAMA_START_CNTL_R[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].red.custom_float_x, + MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0); + + REG_SET_2(MPC_RMCM_SHAPER_RAMA_END_CNTL_B[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].blue.custom_float_x, + MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].blue.custom_float_y); + REG_SET_2(MPC_RMCM_SHAPER_RAMA_END_CNTL_G[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].green.custom_float_x, + MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].green.custom_float_y); + REG_SET_2(MPC_RMCM_SHAPER_RAMA_END_CNTL_R[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].red.custom_float_x, + MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].red.custom_float_y); + + curve = params->arr_curve_points; + if (curve) { + REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_0_1[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_2_3[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_4_5[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_6_7[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_8_9[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_10_11[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_12_13[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_14_15[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + + curve += 2; + REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_16_17[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_18_19[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_20_21[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_22_23[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_24_25[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_26_27[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_28_29[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_30_31[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_32_33[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + } +} + + +void mpc42_program_rmcm_shaper_lutb_settings( + struct mpc *mpc, + const struct pwl_params *params, + uint32_t mpcc_id) +{ + const struct gamma_curve *curve; + struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc); + + REG_SET_2(MPC_RMCM_SHAPER_RAMB_START_CNTL_B[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_B, params->corner_points[0].blue.custom_float_x, + MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_B, 0); + REG_SET_2(MPC_RMCM_SHAPER_RAMB_START_CNTL_G[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_B, params->corner_points[0].green.custom_float_x, + MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_B, 0); + REG_SET_2(MPC_RMCM_SHAPER_RAMB_START_CNTL_R[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_B, params->corner_points[0].red.custom_float_x, + MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_B, 0); + + REG_SET_2(MPC_RMCM_SHAPER_RAMB_END_CNTL_B[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_B, params->corner_points[1].blue.custom_float_x, + MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_BASE_B, params->corner_points[1].blue.custom_float_y); + REG_SET_2(MPC_RMCM_SHAPER_RAMB_END_CNTL_G[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_B, params->corner_points[1].green.custom_float_x, + MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_BASE_B, params->corner_points[1].green.custom_float_y); + REG_SET_2(MPC_RMCM_SHAPER_RAMB_END_CNTL_R[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_B, params->corner_points[1].red.custom_float_x, + MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_BASE_B, params->corner_points[1].red.custom_float_y); + + curve = params->arr_curve_points; + if (curve) { + REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_0_1[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_2_3[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + + curve += 2; + REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_4_5[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_6_7[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_8_9[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_10_11[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_12_13[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_14_15[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_16_17[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_18_19[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_20_21[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_22_23[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_24_25[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_26_27[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_28_29[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_30_31[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_32_33[mpcc_id], 0, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + } +} + +void mpc42_program_rmcm_shaper_lut( + struct mpc *mpc, + const struct pwl_result_data *rgb, + uint32_t num, + uint32_t mpcc_id) +{ + uint32_t i, red, green, blue; + uint32_t red_delta, green_delta, blue_delta; + uint32_t red_value, green_value, blue_value; + + struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc); + + for (i = 0; i < num; i++) { + + red = rgb[i].red_reg; + green = rgb[i].green_reg; + blue = rgb[i].blue_reg; + + red_delta = rgb[i].delta_red_reg; + green_delta = rgb[i].delta_green_reg; + blue_delta = rgb[i].delta_blue_reg; + + red_value = ((red_delta & 0x3ff) << 14) | (red & 0x3fff); + green_value = ((green_delta & 0x3ff) << 14) | (green & 0x3fff); + blue_value = ((blue_delta & 0x3ff) << 14) | (blue & 0x3fff); + + REG_SET(MPC_RMCM_SHAPER_LUT_DATA[mpcc_id], 0, MPC_RMCM_SHAPER_LUT_DATA, red_value); + REG_SET(MPC_RMCM_SHAPER_LUT_DATA[mpcc_id], 0, MPC_RMCM_SHAPER_LUT_DATA, green_value); + REG_SET(MPC_RMCM_SHAPER_LUT_DATA[mpcc_id], 0, MPC_RMCM_SHAPER_LUT_DATA, blue_value); + } +} + +void mpc42_enable_3dlut_fl(struct mpc *mpc, bool enable, int mpcc_id) +{ + struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc); + + //if enabled cho0se mpc 0, else: off (default value) + REG_UPDATE(MPC_RMCM_CNTL[mpcc_id], MPC_RMCM_CNTL, enable ? 0 : 0xF); //0xF is not connected + + REG_UPDATE(MPC_RMCM_3DLUT_READ_WRITE_CONTROL[mpcc_id], MPC_RMCM_3DLUT_WRITE_EN_MASK, 0); + + REG_UPDATE(MPC_RMCM_MEM_PWR_CTRL[mpcc_id], MPC_RMCM_3DLUT_MEM_PWR_DIS, enable ? 0 : 3); +} + +void mpc42_update_3dlut_fast_load_select(struct mpc *mpc, int mpcc_id, int hubp_idx) +{ + struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc); + + REG_SET(MPC_RMCM_3DLUT_FAST_LOAD_SELECT[mpcc_id], 0, + MPC_RMCM_3DLUT_FL_SEL, + hubp_idx); +} + +void mpc42_populate_rmcm_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_rmcm_shaper_3dlut(mpc, mpcc_id, true); + + mpc42_configure_rmcm_shaper_lut(mpc, next_mode == LUT_RAM_A, mpcc_id); + + if (next_mode == LUT_RAM_A) + mpc42_program_rmcm_shaper_luta_settings(mpc, lut_shaper, mpcc_id); + else + mpc42_program_rmcm_shaper_lutb_settings(mpc, lut_shaper, mpcc_id); + + mpc42_program_rmcm_shaper_lut( + mpc, lut_shaper->rgb_resulted, lut_shaper->hw_points_num, mpcc_id); + + mpc42_power_on_rmcm_shaper_3dlut(mpc, mpcc_id, false); +} + +void mpc42_program_rmcm_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(MPC_RMCM_3DLUT_MODE[mpcc_id], MPC_RMCM_3DLUT_MODE, + (!enabled) ? 0 : + (lut_bank_a) ? 1 : 2); + + REG_UPDATE(MPC_RMCM_3DLUT_READ_WRITE_CONTROL[mpcc_id], + MPC_RMCM_3DLUT_RAM_SEL, + (lut_bank_a) ? 0 : 1); + break; + case MCM_LUT_SHAPER: + REG_UPDATE(MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK[mpcc_id], + MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK, 7); + + REG_UPDATE(MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK[mpcc_id], + MPC_RMCM_SHAPER_LUT_WRITE_SEL, + lut_bank_a == true ? 0:1); + + REG_SET(MPC_RMCM_SHAPER_LUT_INDEX[mpcc_id], 0, + MPC_RMCM_SHAPER_LUT_INDEX, 0); + break; + default: + break; + } +} + +void mpc42_program_lut_mode(struct mpc *mpc, + bool enable, + 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 { + 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; + break; + } + + return width; +} + +void mpc42_program_rmcm_3dlut_size(struct mpc *mpc, + const enum dc_cm_lut_size size, + int mpcc_id) +{ + struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc); + uint32_t width = mpc42_get_rmcm_3dlut_width(size); + + REG_UPDATE(MPC_RMCM_3DLUT_MODE[mpcc_id], + MPC_RMCM_3DLUT_SIZE, width); +} + +void mpc42_program_rmcm_3dlut_fast_load_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(MPC_RMCM_3DLUT_OUT_OFFSET_R[mpcc_id], + MPC_RMCM_3DLUT_OUT_OFFSET_R, bias, + MPC_RMCM_3DLUT_OUT_SCALE_R, scale); + + REG_UPDATE_2(MPC_RMCM_3DLUT_OUT_OFFSET_G[mpcc_id], + MPC_RMCM_3DLUT_OUT_OFFSET_G, bias, + MPC_RMCM_3DLUT_OUT_SCALE_G, scale); + + REG_UPDATE_2(MPC_RMCM_3DLUT_OUT_OFFSET_B[mpcc_id], + MPC_RMCM_3DLUT_OUT_OFFSET_B, bias, + MPC_RMCM_3DLUT_OUT_SCALE_B, scale); +} + +void mpc42_program_rmcm_bit_depth(struct mpc *mpc, uint16_t bit_depth, int mpcc_id) +{ + struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc); + + REG_UPDATE(MPC_RMCM_3DLUT_READ_WRITE_CONTROL[mpcc_id], MPC_RMCM_3DLUT_WRITE_EN_MASK, 0xF); + + //program bit_depth + REG_UPDATE(MPC_RMCM_3DLUT_READ_WRITE_CONTROL[mpcc_id], + MPC_RMCM_3DLUT_30BIT_EN, + (bit_depth == 10) ? 1 : 0); +} + +void mpc42_set_fl_config( + struct mpc *mpc, + struct mpc_fl_3dlut_config *cfg, + int mpcc_id) +{ + struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc); + + uint32_t width = mpc42_get_rmcm_3dlut_width(cfg->size); + /* + From: Jie Zhou + + To program any of the memories content. The following sequence is used. + Set the MPCC_OGAM/SHAPER/3DLUT/1DLUT_PWR_DIS to 1 (Only need to set the one + that is being programmed) Set DISPCLK_G_PIPE<i>_GATE_DISABLE to 1 for the + MPCC pipe that’s being used, so the memory’s clock is ungated. Program the + target memory. Set the MPCC_OGAM/SHAPER/3DLUT/1DLUT_PWR_DIS back to 0. + Set DISPCLK_G_PIPE<i>_GATE_DISABLE back to 0 + */ + + //disconnect fl from mpc + REG_SET(MPCC_MCM_3DLUT_FAST_LOAD_SELECT[mpcc_id], 0, + MPCC_MCM_3DLUT_FL_SEL, 0xF); + + REG_UPDATE(MPC_RMCM_3DLUT_READ_WRITE_CONTROL[mpcc_id], + MPC_RMCM_3DLUT_WRITE_EN_MASK, 0xF); + + //program bit_depth + REG_UPDATE(MPC_RMCM_3DLUT_READ_WRITE_CONTROL[mpcc_id], + MPC_RMCM_3DLUT_30BIT_EN, (cfg->bit_depth == 10) ? 1 : 0); + + REG_UPDATE(MPC_RMCM_3DLUT_READ_WRITE_CONTROL[mpcc_id], + MPC_RMCM_3DLUT_RAM_SEL, (cfg->select_lut_bank_a) ? 0 : 1); + + //bias and scale + REG_UPDATE_2(MPC_RMCM_3DLUT_OUT_OFFSET_R[mpcc_id], + MPC_RMCM_3DLUT_OUT_OFFSET_R, cfg->bias, + MPC_RMCM_3DLUT_OUT_SCALE_R, cfg->scale); + + REG_UPDATE_2(MPC_RMCM_3DLUT_OUT_OFFSET_G[mpcc_id], + MPC_RMCM_3DLUT_OUT_OFFSET_G, cfg->bias, + MPC_RMCM_3DLUT_OUT_SCALE_G, cfg->scale); + + REG_UPDATE_2(MPC_RMCM_3DLUT_OUT_OFFSET_B[mpcc_id], + MPC_RMCM_3DLUT_OUT_OFFSET_B, cfg->bias, + MPC_RMCM_3DLUT_OUT_SCALE_B, cfg->scale); + + //width + REG_UPDATE_2(MPC_RMCM_3DLUT_MODE[mpcc_id], + MPC_RMCM_3DLUT_SIZE, width, + MPC_RMCM_3DLUT_MODE, (!cfg->enabled) ? 0 : (cfg->select_lut_bank_a) ? 1 : 2); + + //connect to hubp + REG_SET(MPC_RMCM_3DLUT_FAST_LOAD_SELECT[mpcc_id], 0, + MPC_RMCM_3DLUT_FL_SEL, cfg->hubp_index); + + //ENABLE + //if enabled pick mpc 0, else: off (0xF) + //in future we'll select specific MPC + REG_UPDATE(MPC_RMCM_CNTL[mpcc_id], MPC_RMCM_CNTL, cfg->enabled ? 0 : 0xF); +} + +void mpc42_read_mpcc_state( + struct mpc *mpc, + int mpcc_inst, + struct mpcc_state *s) +{ + struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc); + + mpc1_read_mpcc_state(mpc, mpcc_inst, s); + + if (mpcc_inst < 2) { + /* RMCM 3DLUT Status */ + REG_GET_4(MPC_RMCM_MEM_PWR_CTRL[mpcc_inst], MPC_RMCM_3DLUT_MEM_PWR_FORCE, &s->rmcm_regs.rmcm_3dlut_mem_pwr_force, + MPC_RMCM_3DLUT_MEM_PWR_DIS, &s->rmcm_regs.rmcm_3dlut_mem_pwr_dis, + MPC_RMCM_3DLUT_MEM_LOW_PWR_MODE, &s->rmcm_regs.rmcm_3dlut_mem_pwr_mode, + MPC_RMCM_3DLUT_MEM_PWR_STATE, &s->rmcm_regs.rmcm_3dlut_mem_pwr_state); + + REG_GET_3(MPC_RMCM_3DLUT_MODE[mpcc_inst], MPC_RMCM_3DLUT_SIZE, &s->rmcm_regs.rmcm_3dlut_size, + MPC_RMCM_3DLUT_MODE, &s->rmcm_regs.rmcm_3dlut_mode, + MPC_RMCM_3DLUT_MODE_CURRENT, &s->rmcm_regs.rmcm_3dlut_mode_cur); + + REG_GET_4(MPC_RMCM_3DLUT_READ_WRITE_CONTROL[mpcc_inst], MPC_RMCM_3DLUT_READ_SEL, &s->rmcm_regs.rmcm_3dlut_read_sel, + MPC_RMCM_3DLUT_30BIT_EN, &s->rmcm_regs.rmcm_3dlut_30bit_en, + MPC_RMCM_3DLUT_WRITE_EN_MASK, &s->rmcm_regs.rmcm_3dlut_wr_en_mask, + MPC_RMCM_3DLUT_RAM_SEL, &s->rmcm_regs.rmcm_3dlut_ram_sel); + + REG_GET(MPC_RMCM_3DLUT_OUT_NORM_FACTOR[mpcc_inst], MPC_RMCM_3DLUT_OUT_NORM_FACTOR, &s->rmcm_regs.rmcm_3dlut_out_norm_factor); + + REG_GET(MPC_RMCM_3DLUT_FAST_LOAD_SELECT[mpcc_inst], MPC_RMCM_3DLUT_FL_SEL, &s->rmcm_regs.rmcm_3dlut_fl_sel); + + REG_GET_2(MPC_RMCM_3DLUT_OUT_OFFSET_R[mpcc_inst], MPC_RMCM_3DLUT_OUT_OFFSET_R, &s->rmcm_regs.rmcm_3dlut_out_offset_r, + MPC_RMCM_3DLUT_OUT_SCALE_R, &s->rmcm_regs.rmcm_3dlut_out_scale_r); + + REG_GET_3(MPC_RMCM_3DLUT_FAST_LOAD_STATUS[mpcc_inst], MPC_RMCM_3DLUT_FL_DONE, &s->rmcm_regs.rmcm_3dlut_fl_done, + MPC_RMCM_3DLUT_FL_SOFT_UNDERFLOW, &s->rmcm_regs.rmcm_3dlut_fl_soft_underflow, + MPC_RMCM_3DLUT_FL_HARD_UNDERFLOW, &s->rmcm_regs.rmcm_3dlut_fl_hard_underflow); + + /* RMCM Shaper Status */ + REG_GET_4(MPC_RMCM_MEM_PWR_CTRL[mpcc_inst], MPC_RMCM_SHAPER_MEM_PWR_FORCE, &s->rmcm_regs.rmcm_shaper_mem_pwr_force, + MPC_RMCM_SHAPER_MEM_PWR_DIS, &s->rmcm_regs.rmcm_shaper_mem_pwr_dis, + MPC_RMCM_SHAPER_MEM_LOW_PWR_MODE, &s->rmcm_regs.rmcm_shaper_mem_pwr_mode, + MPC_RMCM_SHAPER_MEM_PWR_STATE, &s->rmcm_regs.rmcm_shaper_mem_pwr_state); + + REG_GET_2(MPC_RMCM_SHAPER_CONTROL[mpcc_inst], MPC_RMCM_SHAPER_LUT_MODE, &s->rmcm_regs.rmcm_shaper_lut_mode, + MPC_RMCM_SHAPER_MODE_CURRENT, &s->rmcm_regs.rmcm_shaper_mode_cur); + + REG_GET_2(MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK[mpcc_inst], MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK, &s->rmcm_regs.rmcm_shaper_lut_write_en_mask, + MPC_RMCM_SHAPER_LUT_WRITE_SEL, &s->rmcm_regs.rmcm_shaper_lut_write_sel); + + REG_GET(MPC_RMCM_SHAPER_OFFSET_B[mpcc_inst], MPC_RMCM_SHAPER_OFFSET_B, &s->rmcm_regs.rmcm_shaper_offset_b); + + REG_GET(MPC_RMCM_SHAPER_SCALE_G_B[mpcc_inst], MPC_RMCM_SHAPER_SCALE_B, &s->rmcm_regs.rmcm_shaper_scale_b); + + REG_GET_2(MPC_RMCM_SHAPER_RAMA_START_CNTL_B[mpcc_inst], MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_B, &s->rmcm_regs.rmcm_shaper_rama_exp_region_start_b, + MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, &s->rmcm_regs.rmcm_shaper_rama_exp_region_start_seg_b); + + REG_GET_2(MPC_RMCM_SHAPER_RAMA_END_CNTL_B[mpcc_inst], MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_B, &s->rmcm_regs.rmcm_shaper_rama_exp_region_end_b, + MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_BASE_B, &s->rmcm_regs.rmcm_shaper_rama_exp_region_end_base_b); + + REG_GET(MPC_RMCM_CNTL[mpcc_inst], MPC_RMCM_CNTL, &s->rmcm_regs.rmcm_cntl); + } +} + +static const struct mpc_funcs dcn42_mpc_funcs = { + .read_mpcc_state = mpc42_read_mpcc_state, + .insert_plane = mpc1_insert_plane, + .remove_mpcc = mpc1_remove_mpcc, + .mpc_init = mpc32_mpc_init, + .mpc_init_single_inst = mpc3_mpc_init_single_inst, + .update_blending = mpc42_update_blending, + .cursor_lock = mpc1_cursor_lock, + .get_mpcc_for_dpp = mpc1_get_mpcc_for_dpp, + .wait_for_idle = mpc2_assert_idle_mpcc, + .assert_mpcc_idle_before_connect = mpc2_assert_mpcc_idle_before_connect, + .init_mpcc_list_from_hw = mpc1_init_mpcc_list_from_hw, + .set_denorm = mpc3_set_denorm, + .set_denorm_clamp = mpc3_set_denorm_clamp, + .set_output_csc = mpc3_set_output_csc, + .set_ocsc_default = mpc3_set_ocsc_default, + .set_output_gamma = mpc3_set_output_gamma, + .set_dwb_mux = mpc3_set_dwb_mux, + .disable_dwb_mux = mpc3_disable_dwb_mux, + .is_dwb_idle = mpc3_is_dwb_idle, + .set_gamut_remap = mpc401_set_gamut_remap, + .program_shaper = mpc32_program_shaper, + .program_3dlut = mpc32_program_3dlut, + .program_1dlut = mpc32_program_post1dlut, + .power_on_mpc_mem_pwr = mpc3_power_on_ogam_lut, + .get_mpc_out_mux = mpc1_get_mpc_out_mux, + .mpc_read_reg_state = mpc3_read_reg_state, + .set_bg_color = mpc1_set_bg_color, + .set_movable_cm_location = mpc401_set_movable_cm_location, + .update_3dlut_fast_load_select = mpc401_update_3dlut_fast_load_select, + .get_3dlut_fast_load_status = mpc401_get_3dlut_fast_load_status, + .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, + .rmcm = { + .enable_3dlut_fl = mpc42_enable_3dlut_fl, + .update_3dlut_fast_load_select = mpc42_update_3dlut_fast_load_select, + .program_lut_read_write_control = mpc42_program_rmcm_lut_read_write_control, + .program_lut_mode = mpc42_program_lut_mode, + .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, + .power_on_shaper_3dlut = mpc42_power_on_rmcm_shaper_3dlut, + .populate_lut = mpc42_populate_rmcm_lut, + .fl_3dlut_configure = mpc42_set_fl_config, + }, +}; + +void dcn42_mpc_construct(struct dcn42_mpc *mpc42, + struct dc_context *ctx, + const struct dcn42_mpc_registers *mpc_regs, + const struct dcn42_mpc_shift *mpc_shift, + const struct dcn42_mpc_mask *mpc_mask, + int num_mpcc, + int num_rmu) +{ + int i; + + mpc42->base.ctx = ctx; + + mpc42->base.funcs = &dcn42_mpc_funcs; + + mpc42->mpc_regs = mpc_regs; + mpc42->mpc_shift = mpc_shift; + mpc42->mpc_mask = mpc_mask; + + mpc42->mpcc_in_use_mask = 0; + mpc42->num_mpcc = num_mpcc; + mpc42->num_rmu = num_rmu; + + for (i = 0; i < MAX_MPCC; i++) + mpc42_init_mpcc(&mpc42->base.mpcc_array[i], i); +} 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 new file mode 100644 index 000000000000..a5f7f4f2bb3b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.h @@ -0,0 +1,962 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright 2026 Advanced Micro Devices, Inc. */ + +#ifndef __DC_MPCC_DCN42_H__ +#define __DC_MPCC_DCN42_H__ + +#include "dcn401/dcn401_mpc.h" + +#define TO_DCN42_MPC(mpc_base) \ + container_of(mpc_base, struct dcn42_mpc, base) + +#define MPC_COMMON_MASK_SH_LIST_DCN42(mask_sh) \ + SF(MPCC0_MPCC_TOP_SEL, MPCC_TOP_SEL, mask_sh),\ + SF(MPCC0_MPCC_BOT_SEL, MPCC_BOT_SEL, mask_sh),\ + SF(MPCC0_MPCC_CONTROL, MPCC_MODE, mask_sh),\ + SF(MPCC0_MPCC_CONTROL, MPCC_ALPHA_BLND_MODE, mask_sh),\ + SF(MPCC0_MPCC_CONTROL, MPCC_ALPHA_MULTIPLIED_MODE, mask_sh),\ + SF(MPCC0_MPCC_CONTROL, MPCC_BLND_ACTIVE_OVERLAP_ONLY, mask_sh),\ + SF(MPCC0_MPCC_CONTROL2, MPCC_GLOBAL_ALPHA, mask_sh),\ + SF(MPCC0_MPCC_CONTROL2, MPCC_GLOBAL_GAIN, mask_sh),\ + SF(MPCC0_MPCC_STATUS, MPCC_IDLE, mask_sh),\ + SF(MPCC0_MPCC_STATUS, MPCC_BUSY, mask_sh),\ + SF(MPCC0_MPCC_OPP_ID, MPCC_OPP_ID, mask_sh),\ + SF(MPCC0_MPCC_BG_G_Y, MPCC_BG_G_Y, mask_sh),\ + SF(MPCC0_MPCC_BG_R_CR, MPCC_BG_R_CR, mask_sh),\ + SF(MPCC0_MPCC_BG_B_CB, MPCC_BG_B_CB, mask_sh),\ + SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_EN, mask_sh),\ + SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_MODE, mask_sh),\ + SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FRAME_ALT, mask_sh),\ + SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FIELD_ALT, mask_sh),\ + SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FORCE_NEXT_FRAME_POL, mask_sh),\ + SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FORCE_NEXT_TOP_POL, mask_sh),\ + SF(MPC_OUT0_MUX, MPC_OUT_MUX, mask_sh),\ + SF(MPCC0_MPCC_UPDATE_LOCK_SEL, MPCC_UPDATE_LOCK_SEL, mask_sh),\ + SF(MPCC0_MPCC_CONTROL, MPCC_BG_BPC, mask_sh),\ + SF(MPCC0_MPCC_CONTROL, MPCC_BOT_GAIN_MODE, mask_sh),\ + SF(MPCC0_MPCC_TOP_GAIN, MPCC_TOP_GAIN, mask_sh),\ + SF(MPCC0_MPCC_BOT_GAIN_INSIDE, MPCC_BOT_GAIN_INSIDE, mask_sh),\ + SF(MPCC0_MPCC_BOT_GAIN_OUTSIDE, MPCC_BOT_GAIN_OUTSIDE, mask_sh),\ + SF(MPCC0_MPCC_MOVABLE_CM_LOCATION_CONTROL, MPCC_MOVABLE_CM_LOCATION_CNTL, mask_sh),\ + SF(MPCC0_MPCC_MOVABLE_CM_LOCATION_CONTROL, MPCC_MOVABLE_CM_LOCATION_CNTL_CURRENT, mask_sh),\ + SF(MPC_OUT0_CSC_MODE, MPC_OCSC_MODE, mask_sh),\ + SF(MPC_OUT0_CSC_C11_C12_A, MPC_OCSC_C11_A, mask_sh),\ + SF(MPC_OUT0_CSC_C11_C12_A, MPC_OCSC_C12_A, mask_sh),\ + SF(MPCC0_MPCC_STATUS, MPCC_DISABLED, mask_sh),\ + SF(MPCC0_MPCC_MEM_PWR_CTRL, MPCC_OGAM_MEM_PWR_FORCE, mask_sh),\ + SF(MPCC0_MPCC_MEM_PWR_CTRL, MPCC_OGAM_MEM_PWR_DIS, mask_sh),\ + SF(MPCC0_MPCC_MEM_PWR_CTRL, MPCC_OGAM_MEM_LOW_PWR_MODE, mask_sh),\ + SF(MPCC0_MPCC_MEM_PWR_CTRL, MPCC_OGAM_MEM_PWR_STATE, mask_sh),\ + SF(MPC_OUT0_DENORM_CONTROL, MPC_OUT_DENORM_MODE, mask_sh),\ + SF(MPC_OUT0_DENORM_CONTROL, MPC_OUT_DENORM_CLAMP_MAX_R_CR, mask_sh),\ + SF(MPC_OUT0_DENORM_CONTROL, MPC_OUT_DENORM_CLAMP_MIN_R_CR, mask_sh),\ + SF(MPC_OUT0_DENORM_CLAMP_G_Y, MPC_OUT_DENORM_CLAMP_MAX_G_Y, mask_sh),\ + SF(MPC_OUT0_DENORM_CLAMP_G_Y, MPC_OUT_DENORM_CLAMP_MIN_G_Y, mask_sh),\ + SF(MPC_OUT0_DENORM_CLAMP_B_CB, MPC_OUT_DENORM_CLAMP_MAX_B_CB, mask_sh),\ + SF(MPC_OUT0_DENORM_CLAMP_B_CB, MPC_OUT_DENORM_CLAMP_MIN_B_CB, mask_sh),\ + SF(MPCC_OGAM0_MPCC_GAMUT_REMAP_MODE, MPCC_GAMUT_REMAP_MODE, mask_sh),\ + SF(MPCC_OGAM0_MPCC_GAMUT_REMAP_MODE, MPCC_GAMUT_REMAP_MODE_CURRENT, mask_sh),\ + SF(MPCC_OGAM0_MPCC_GAMUT_REMAP_COEF_FORMAT, MPCC_GAMUT_REMAP_COEF_FORMAT, mask_sh),\ + SF(MPCC_OGAM0_MPC_GAMUT_REMAP_C11_C12_A, MPCC_GAMUT_REMAP_C11_A, mask_sh),\ + SF(MPCC_OGAM0_MPC_GAMUT_REMAP_C11_C12_A, MPCC_GAMUT_REMAP_C12_A, mask_sh),\ + SF(MPC_DWB0_MUX, MPC_DWB0_MUX, mask_sh),\ + SF(MPC_DWB0_MUX, MPC_DWB0_MUX_STATUS, mask_sh),\ + SF(MPC_OUT0_MUX, MPC_OUT_RATE_CONTROL, mask_sh),\ + SF(MPC_OUT0_MUX, MPC_OUT_RATE_CONTROL_DISABLE, mask_sh),\ + SF(MPC_OUT0_MUX, MPC_OUT_FLOW_CONTROL_MODE, mask_sh),\ + SF(MPC_OUT0_MUX, MPC_OUT_FLOW_CONTROL_COUNT, mask_sh), \ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_REGION_0_1, MPCC_OGAM_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_REGION_0_1, MPCC_OGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_REGION_0_1, MPCC_OGAM_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_REGION_0_1, MPCC_OGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_END_CNTL2_B, MPCC_OGAM_RAMA_EXP_REGION_END_SLOPE_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_END_CNTL2_B, MPCC_OGAM_RAMA_EXP_REGION_END_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_END_CNTL1_B, MPCC_OGAM_RAMA_EXP_REGION_END_BASE_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_START_SLOPE_CNTL_B, MPCC_OGAM_RAMA_EXP_REGION_START_SLOPE_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_START_BASE_CNTL_B, MPCC_OGAM_RAMA_EXP_REGION_START_BASE_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_START_CNTL_B, MPCC_OGAM_RAMA_EXP_REGION_START_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_START_CNTL_B, MPCC_OGAM_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_OFFSET_B, MPCC_OGAM_RAMA_OFFSET_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_OFFSET_G, MPCC_OGAM_RAMA_OFFSET_G, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_OFFSET_R, MPCC_OGAM_RAMA_OFFSET_R, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_INDEX, MPCC_OGAM_LUT_INDEX, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_MODE, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_SELECT, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_PWL_DISABLE, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_MODE_CURRENT, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_SELECT_CURRENT, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_WRITE_COLOR_MASK, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_READ_COLOR_SEL, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_HOST_SEL, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_CONFIG_MODE, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_DATA, MPCC_OGAM_LUT_DATA, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_3DLUT_MODE, MPCC_MCM_3DLUT_MODE, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_3DLUT_MODE, MPCC_MCM_3DLUT_SIZE, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_3DLUT_MODE, MPCC_MCM_3DLUT_MODE_CURRENT, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_3DLUT_READ_WRITE_CONTROL, MPCC_MCM_3DLUT_WRITE_EN_MASK, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_3DLUT_READ_WRITE_CONTROL, MPCC_MCM_3DLUT_RAM_SEL, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_3DLUT_READ_WRITE_CONTROL, MPCC_MCM_3DLUT_30BIT_EN, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_3DLUT_READ_WRITE_CONTROL, MPCC_MCM_3DLUT_READ_SEL, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_3DLUT_INDEX, MPCC_MCM_3DLUT_INDEX, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_3DLUT_DATA, MPCC_MCM_3DLUT_DATA0, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_3DLUT_DATA, MPCC_MCM_3DLUT_DATA1, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_3DLUT_DATA_30BIT, MPCC_MCM_3DLUT_DATA_30BIT, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_SHAPER_CONTROL, MPCC_MCM_SHAPER_LUT_MODE, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_SHAPER_CONTROL, MPCC_MCM_SHAPER_MODE_CURRENT, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_SHAPER_OFFSET_R, MPCC_MCM_SHAPER_OFFSET_R, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_SHAPER_OFFSET_G, MPCC_MCM_SHAPER_OFFSET_G, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_SHAPER_OFFSET_B, MPCC_MCM_SHAPER_OFFSET_B, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_SHAPER_SCALE_R, MPCC_MCM_SHAPER_SCALE_R, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_SHAPER_SCALE_G_B, MPCC_MCM_SHAPER_SCALE_G, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_SHAPER_SCALE_G_B, MPCC_MCM_SHAPER_SCALE_B, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_SHAPER_LUT_INDEX, MPCC_MCM_SHAPER_LUT_INDEX, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_SHAPER_LUT_DATA, MPCC_MCM_SHAPER_LUT_DATA, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_SHAPER_LUT_WRITE_EN_MASK, MPCC_MCM_SHAPER_LUT_WRITE_EN_MASK, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_SHAPER_LUT_WRITE_EN_MASK, MPCC_MCM_SHAPER_LUT_WRITE_SEL, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_SHAPER_RAMA_START_CNTL_B, MPCC_MCM_SHAPER_RAMA_EXP_REGION_START_B, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_SHAPER_RAMA_START_CNTL_B, MPCC_MCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_SHAPER_RAMA_END_CNTL_B, MPCC_MCM_SHAPER_RAMA_EXP_REGION_END_B, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_SHAPER_RAMA_END_CNTL_B, MPCC_MCM_SHAPER_RAMA_EXP_REGION_END_BASE_B, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_SHAPER_RAMA_REGION_0_1, MPCC_MCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_SHAPER_RAMA_REGION_0_1, MPCC_MCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_SHAPER_RAMA_REGION_0_1, MPCC_MCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_SHAPER_RAMA_REGION_0_1, MPCC_MCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_1DLUT_CONTROL, MPCC_MCM_1DLUT_MODE, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_1DLUT_CONTROL, MPCC_MCM_1DLUT_SELECT, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_1DLUT_CONTROL, MPCC_MCM_1DLUT_PWL_DISABLE, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_1DLUT_CONTROL, MPCC_MCM_1DLUT_MODE_CURRENT, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_1DLUT_CONTROL, MPCC_MCM_1DLUT_SELECT_CURRENT, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_1DLUT_LUT_INDEX, MPCC_MCM_1DLUT_LUT_INDEX, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_1DLUT_LUT_DATA, MPCC_MCM_1DLUT_LUT_DATA, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_1DLUT_LUT_CONTROL, MPCC_MCM_1DLUT_LUT_WRITE_COLOR_MASK, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_1DLUT_LUT_CONTROL, MPCC_MCM_1DLUT_LUT_READ_COLOR_SEL, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_1DLUT_LUT_CONTROL, MPCC_MCM_1DLUT_LUT_HOST_SEL, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_1DLUT_LUT_CONTROL, MPCC_MCM_1DLUT_LUT_CONFIG_MODE, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_START_CNTL_B, MPCC_MCM_1DLUT_RAMA_EXP_REGION_START_B, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_START_CNTL_B, MPCC_MCM_1DLUT_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_START_SLOPE_CNTL_B, MPCC_MCM_1DLUT_RAMA_EXP_REGION_START_SLOPE_B, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_START_BASE_CNTL_B, MPCC_MCM_1DLUT_RAMA_EXP_REGION_START_BASE_B, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_END_CNTL1_B, MPCC_MCM_1DLUT_RAMA_EXP_REGION_END_BASE_B, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_END_CNTL2_B, MPCC_MCM_1DLUT_RAMA_EXP_REGION_END_B, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_END_CNTL2_B, MPCC_MCM_1DLUT_RAMA_EXP_REGION_END_SLOPE_B, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_OFFSET_B, MPCC_MCM_1DLUT_RAMA_OFFSET_B, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_REGION_0_1, MPCC_MCM_1DLUT_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_REGION_0_1, MPCC_MCM_1DLUT_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_REGION_0_1, MPCC_MCM_1DLUT_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_REGION_0_1, MPCC_MCM_1DLUT_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_SHAPER_MEM_PWR_FORCE, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_SHAPER_MEM_PWR_DIS, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_SHAPER_MEM_LOW_PWR_MODE, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_3DLUT_MEM_PWR_FORCE, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_3DLUT_MEM_PWR_DIS, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_3DLUT_MEM_LOW_PWR_MODE, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_1DLUT_MEM_PWR_FORCE, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_1DLUT_MEM_PWR_DIS, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_1DLUT_MEM_LOW_PWR_MODE, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_SHAPER_MEM_PWR_STATE, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_3DLUT_MEM_PWR_STATE, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_1DLUT_MEM_PWR_STATE, mask_sh),\ + SF(CUR_VUPDATE_LOCK_SET0, CUR_VUPDATE_LOCK_SET, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_FIRST_GAMUT_REMAP_COEF_FORMAT, MPCC_MCM_FIRST_GAMUT_REMAP_COEF_FORMAT, mask_sh), \ + SF(MPCC_MCM0_MPCC_MCM_FIRST_GAMUT_REMAP_MODE, MPCC_MCM_FIRST_GAMUT_REMAP_MODE, mask_sh), \ + SF(MPCC_MCM0_MPCC_MCM_FIRST_GAMUT_REMAP_MODE, MPCC_MCM_FIRST_GAMUT_REMAP_MODE_CURRENT, mask_sh), \ + SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C11_C12_A, MPCC_MCM_FIRST_GAMUT_REMAP_C11_A, mask_sh), \ + SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C11_C12_A, MPCC_MCM_FIRST_GAMUT_REMAP_C12_A, mask_sh), \ + SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C13_C14_A, MPCC_MCM_FIRST_GAMUT_REMAP_C13_A, mask_sh), \ + SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C13_C14_A, MPCC_MCM_FIRST_GAMUT_REMAP_C14_A, mask_sh), \ + SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C21_C22_A, MPCC_MCM_FIRST_GAMUT_REMAP_C21_A, mask_sh), \ + SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C21_C22_A, MPCC_MCM_FIRST_GAMUT_REMAP_C22_A, mask_sh), \ + SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C23_C24_A, MPCC_MCM_FIRST_GAMUT_REMAP_C23_A, mask_sh), \ + SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C23_C24_A, MPCC_MCM_FIRST_GAMUT_REMAP_C24_A, mask_sh), \ + SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C31_C32_A, MPCC_MCM_FIRST_GAMUT_REMAP_C31_A, mask_sh), \ + SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C31_C32_A, MPCC_MCM_FIRST_GAMUT_REMAP_C32_A, mask_sh), \ + SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C33_C34_A, MPCC_MCM_FIRST_GAMUT_REMAP_C33_A, mask_sh), \ + SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C33_C34_A, MPCC_MCM_FIRST_GAMUT_REMAP_C34_A, mask_sh), \ + SF(MPCC_MCM0_MPCC_MCM_SECOND_GAMUT_REMAP_COEF_FORMAT, MPCC_MCM_SECOND_GAMUT_REMAP_COEF_FORMAT, mask_sh), \ + SF(MPCC_MCM0_MPCC_MCM_SECOND_GAMUT_REMAP_MODE, MPCC_MCM_SECOND_GAMUT_REMAP_MODE, mask_sh), \ + SF(MPCC_MCM0_MPCC_MCM_SECOND_GAMUT_REMAP_MODE, MPCC_MCM_SECOND_GAMUT_REMAP_MODE_CURRENT, mask_sh), \ + SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C11_C12_A, MPCC_MCM_SECOND_GAMUT_REMAP_C11_A, mask_sh), \ + SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C11_C12_A, MPCC_MCM_SECOND_GAMUT_REMAP_C12_A, mask_sh), \ + SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C13_C14_A, MPCC_MCM_SECOND_GAMUT_REMAP_C13_A, mask_sh), \ + SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C13_C14_A, MPCC_MCM_SECOND_GAMUT_REMAP_C14_A, mask_sh), \ + SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C21_C22_A, MPCC_MCM_SECOND_GAMUT_REMAP_C21_A, mask_sh), \ + SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C21_C22_A, MPCC_MCM_SECOND_GAMUT_REMAP_C22_A, mask_sh), \ + SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C23_C24_A, MPCC_MCM_SECOND_GAMUT_REMAP_C23_A, mask_sh), \ + SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C23_C24_A, MPCC_MCM_SECOND_GAMUT_REMAP_C24_A, mask_sh), \ + SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C31_C32_A, MPCC_MCM_SECOND_GAMUT_REMAP_C31_A, mask_sh), \ + SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C31_C32_A, MPCC_MCM_SECOND_GAMUT_REMAP_C32_A, mask_sh), \ + SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C33_C34_A, MPCC_MCM_SECOND_GAMUT_REMAP_C33_A, mask_sh), \ + SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C33_C34_A, MPCC_MCM_SECOND_GAMUT_REMAP_C34_A, mask_sh), \ + SF(MPCC_MCM0_MPCC_MCM_3DLUT_FAST_LOAD_SELECT, MPCC_MCM_3DLUT_FL_SEL, mask_sh), \ + SF(MPCC_MCM0_MPCC_MCM_3DLUT_FAST_LOAD_STATUS, MPCC_MCM_3DLUT_FL_DONE, mask_sh), \ + SF(MPCC_MCM0_MPCC_MCM_3DLUT_FAST_LOAD_STATUS, MPCC_MCM_3DLUT_FL_SOFT_UNDERFLOW, mask_sh), \ + SF(MPCC_MCM0_MPCC_MCM_3DLUT_FAST_LOAD_STATUS, MPCC_MCM_3DLUT_FL_HARD_UNDERFLOW, mask_sh), \ + SF(MPCC_MCM0_MPCC_MCM_3DLUT_OUT_OFFSET_R, MPCC_MCM_3DLUT_OUT_OFFSET_R, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_3DLUT_OUT_OFFSET_R, MPCC_MCM_3DLUT_OUT_SCALE_R, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_3DLUT_OUT_OFFSET_G, MPCC_MCM_3DLUT_OUT_OFFSET_G, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_3DLUT_OUT_OFFSET_G, MPCC_MCM_3DLUT_OUT_SCALE_G, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_3DLUT_OUT_OFFSET_B, MPCC_MCM_3DLUT_OUT_OFFSET_B, mask_sh),\ + SF(MPCC_MCM0_MPCC_MCM_3DLUT_OUT_OFFSET_B, MPCC_MCM_3DLUT_OUT_SCALE_B, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_CONTROL, MPC_RMCM_SHAPER_LUT_MODE, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_CONTROL, MPC_RMCM_SHAPER_MODE_CURRENT, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_OFFSET_R, MPC_RMCM_SHAPER_OFFSET_R, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_OFFSET_G, MPC_RMCM_SHAPER_OFFSET_G, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_OFFSET_B, MPC_RMCM_SHAPER_OFFSET_B, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_SCALE_R, MPC_RMCM_SHAPER_SCALE_R, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_SCALE_G_B, MPC_RMCM_SHAPER_SCALE_G, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_SCALE_G_B, MPC_RMCM_SHAPER_SCALE_B, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_LUT_INDEX, MPC_RMCM_SHAPER_LUT_INDEX, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_LUT_DATA, MPC_RMCM_SHAPER_LUT_DATA, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK, MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK, MPC_RMCM_SHAPER_LUT_WRITE_SEL, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_START_CNTL_B, MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_B, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_START_CNTL_B, MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_START_CNTL_G, MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_G, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_START_CNTL_G, MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_G, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_START_CNTL_R, MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_R, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_START_CNTL_R, MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_R, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_END_CNTL_B, MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_B, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_END_CNTL_B, MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_BASE_B, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_END_CNTL_G, MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_G, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_END_CNTL_G, MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_BASE_G, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_END_CNTL_R, MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_R, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_END_CNTL_R, MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_BASE_R, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_0_1, MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_0_1, MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_0_1, MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_0_1, MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_2_3, MPC_RMCM_SHAPER_RAMA_EXP_REGION2_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_2_3, MPC_RMCM_SHAPER_RAMA_EXP_REGION2_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_2_3, MPC_RMCM_SHAPER_RAMA_EXP_REGION3_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_2_3, MPC_RMCM_SHAPER_RAMA_EXP_REGION3_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_4_5, MPC_RMCM_SHAPER_RAMA_EXP_REGION4_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_4_5, MPC_RMCM_SHAPER_RAMA_EXP_REGION4_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_4_5, MPC_RMCM_SHAPER_RAMA_EXP_REGION5_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_4_5, MPC_RMCM_SHAPER_RAMA_EXP_REGION5_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_6_7, MPC_RMCM_SHAPER_RAMA_EXP_REGION6_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_6_7, MPC_RMCM_SHAPER_RAMA_EXP_REGION6_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_6_7, MPC_RMCM_SHAPER_RAMA_EXP_REGION7_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_6_7, MPC_RMCM_SHAPER_RAMA_EXP_REGION7_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_8_9, MPC_RMCM_SHAPER_RAMA_EXP_REGION8_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_8_9, MPC_RMCM_SHAPER_RAMA_EXP_REGION8_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_8_9, MPC_RMCM_SHAPER_RAMA_EXP_REGION9_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_8_9, MPC_RMCM_SHAPER_RAMA_EXP_REGION9_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_10_11, MPC_RMCM_SHAPER_RAMA_EXP_REGION10_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_10_11, MPC_RMCM_SHAPER_RAMA_EXP_REGION10_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_10_11, MPC_RMCM_SHAPER_RAMA_EXP_REGION11_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_10_11, MPC_RMCM_SHAPER_RAMA_EXP_REGION11_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_12_13, MPC_RMCM_SHAPER_RAMA_EXP_REGION12_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_12_13, MPC_RMCM_SHAPER_RAMA_EXP_REGION12_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_12_13, MPC_RMCM_SHAPER_RAMA_EXP_REGION13_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_12_13, MPC_RMCM_SHAPER_RAMA_EXP_REGION13_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_14_15, MPC_RMCM_SHAPER_RAMA_EXP_REGION14_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_14_15, MPC_RMCM_SHAPER_RAMA_EXP_REGION14_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_14_15, MPC_RMCM_SHAPER_RAMA_EXP_REGION15_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_14_15, MPC_RMCM_SHAPER_RAMA_EXP_REGION15_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_16_17, MPC_RMCM_SHAPER_RAMA_EXP_REGION16_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_16_17, MPC_RMCM_SHAPER_RAMA_EXP_REGION16_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_16_17, MPC_RMCM_SHAPER_RAMA_EXP_REGION17_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_16_17, MPC_RMCM_SHAPER_RAMA_EXP_REGION17_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_18_19, MPC_RMCM_SHAPER_RAMA_EXP_REGION18_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_18_19, MPC_RMCM_SHAPER_RAMA_EXP_REGION18_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_18_19, MPC_RMCM_SHAPER_RAMA_EXP_REGION19_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_18_19, MPC_RMCM_SHAPER_RAMA_EXP_REGION19_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_20_21, MPC_RMCM_SHAPER_RAMA_EXP_REGION20_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_20_21, MPC_RMCM_SHAPER_RAMA_EXP_REGION20_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_20_21, MPC_RMCM_SHAPER_RAMA_EXP_REGION21_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_20_21, MPC_RMCM_SHAPER_RAMA_EXP_REGION21_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_22_23, MPC_RMCM_SHAPER_RAMA_EXP_REGION22_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_22_23, MPC_RMCM_SHAPER_RAMA_EXP_REGION22_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_22_23, MPC_RMCM_SHAPER_RAMA_EXP_REGION23_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_22_23, MPC_RMCM_SHAPER_RAMA_EXP_REGION23_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_24_25, MPC_RMCM_SHAPER_RAMA_EXP_REGION24_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_24_25, MPC_RMCM_SHAPER_RAMA_EXP_REGION24_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_24_25, MPC_RMCM_SHAPER_RAMA_EXP_REGION25_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_24_25, MPC_RMCM_SHAPER_RAMA_EXP_REGION25_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_26_27, MPC_RMCM_SHAPER_RAMA_EXP_REGION26_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_26_27, MPC_RMCM_SHAPER_RAMA_EXP_REGION26_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_26_27, MPC_RMCM_SHAPER_RAMA_EXP_REGION27_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_26_27, MPC_RMCM_SHAPER_RAMA_EXP_REGION27_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_28_29, MPC_RMCM_SHAPER_RAMA_EXP_REGION28_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_28_29, MPC_RMCM_SHAPER_RAMA_EXP_REGION28_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_28_29, MPC_RMCM_SHAPER_RAMA_EXP_REGION29_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_28_29, MPC_RMCM_SHAPER_RAMA_EXP_REGION29_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_30_31, MPC_RMCM_SHAPER_RAMA_EXP_REGION30_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_30_31, MPC_RMCM_SHAPER_RAMA_EXP_REGION30_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_30_31, MPC_RMCM_SHAPER_RAMA_EXP_REGION31_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_30_31, MPC_RMCM_SHAPER_RAMA_EXP_REGION31_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_32_33, MPC_RMCM_SHAPER_RAMA_EXP_REGION32_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_32_33, MPC_RMCM_SHAPER_RAMA_EXP_REGION32_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_32_33, MPC_RMCM_SHAPER_RAMA_EXP_REGION33_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_32_33, MPC_RMCM_SHAPER_RAMA_EXP_REGION33_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_START_CNTL_B, MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_B, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_START_CNTL_B, MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_B, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_START_CNTL_G, MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_G, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_START_CNTL_G, MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_G, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_START_CNTL_R, MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_R, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_START_CNTL_R, MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_R, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_END_CNTL_B, MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_B, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_END_CNTL_B, MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_BASE_B, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_END_CNTL_G, MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_G, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_END_CNTL_G, MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_BASE_G, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_END_CNTL_R, MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_R, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_END_CNTL_R, MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_BASE_R, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_0_1, MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_0_1, MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_0_1, MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_0_1, MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_2_3, MPC_RMCM_SHAPER_RAMB_EXP_REGION2_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_2_3, MPC_RMCM_SHAPER_RAMB_EXP_REGION2_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_2_3, MPC_RMCM_SHAPER_RAMB_EXP_REGION3_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_2_3, MPC_RMCM_SHAPER_RAMB_EXP_REGION3_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_4_5, MPC_RMCM_SHAPER_RAMB_EXP_REGION4_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_4_5, MPC_RMCM_SHAPER_RAMB_EXP_REGION4_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_4_5, MPC_RMCM_SHAPER_RAMB_EXP_REGION5_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_4_5, MPC_RMCM_SHAPER_RAMB_EXP_REGION5_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_6_7, MPC_RMCM_SHAPER_RAMB_EXP_REGION6_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_6_7, MPC_RMCM_SHAPER_RAMB_EXP_REGION6_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_6_7, MPC_RMCM_SHAPER_RAMB_EXP_REGION7_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_6_7, MPC_RMCM_SHAPER_RAMB_EXP_REGION7_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_8_9, MPC_RMCM_SHAPER_RAMB_EXP_REGION8_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_8_9, MPC_RMCM_SHAPER_RAMB_EXP_REGION8_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_8_9, MPC_RMCM_SHAPER_RAMB_EXP_REGION9_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_8_9, MPC_RMCM_SHAPER_RAMB_EXP_REGION9_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_10_11, MPC_RMCM_SHAPER_RAMB_EXP_REGION10_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_10_11, MPC_RMCM_SHAPER_RAMB_EXP_REGION10_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_10_11, MPC_RMCM_SHAPER_RAMB_EXP_REGION11_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_10_11, MPC_RMCM_SHAPER_RAMB_EXP_REGION11_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_12_13, MPC_RMCM_SHAPER_RAMB_EXP_REGION12_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_12_13, MPC_RMCM_SHAPER_RAMB_EXP_REGION12_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_12_13, MPC_RMCM_SHAPER_RAMB_EXP_REGION13_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_12_13, MPC_RMCM_SHAPER_RAMB_EXP_REGION13_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_14_15, MPC_RMCM_SHAPER_RAMB_EXP_REGION14_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_14_15, MPC_RMCM_SHAPER_RAMB_EXP_REGION14_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_14_15, MPC_RMCM_SHAPER_RAMB_EXP_REGION15_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_14_15, MPC_RMCM_SHAPER_RAMB_EXP_REGION15_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_16_17, MPC_RMCM_SHAPER_RAMB_EXP_REGION16_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_16_17, MPC_RMCM_SHAPER_RAMB_EXP_REGION16_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_16_17, MPC_RMCM_SHAPER_RAMB_EXP_REGION17_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_16_17, MPC_RMCM_SHAPER_RAMB_EXP_REGION17_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_18_19, MPC_RMCM_SHAPER_RAMB_EXP_REGION18_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_18_19, MPC_RMCM_SHAPER_RAMB_EXP_REGION18_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_18_19, MPC_RMCM_SHAPER_RAMB_EXP_REGION19_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_18_19, MPC_RMCM_SHAPER_RAMB_EXP_REGION19_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_20_21, MPC_RMCM_SHAPER_RAMB_EXP_REGION20_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_20_21, MPC_RMCM_SHAPER_RAMB_EXP_REGION20_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_20_21, MPC_RMCM_SHAPER_RAMB_EXP_REGION21_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_20_21, MPC_RMCM_SHAPER_RAMB_EXP_REGION21_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_22_23, MPC_RMCM_SHAPER_RAMB_EXP_REGION22_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_22_23, MPC_RMCM_SHAPER_RAMB_EXP_REGION22_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_22_23, MPC_RMCM_SHAPER_RAMB_EXP_REGION23_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_22_23, MPC_RMCM_SHAPER_RAMB_EXP_REGION23_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_24_25, MPC_RMCM_SHAPER_RAMB_EXP_REGION24_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_24_25, MPC_RMCM_SHAPER_RAMB_EXP_REGION24_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_24_25, MPC_RMCM_SHAPER_RAMB_EXP_REGION25_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_24_25, MPC_RMCM_SHAPER_RAMB_EXP_REGION25_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_26_27, MPC_RMCM_SHAPER_RAMB_EXP_REGION26_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_26_27, MPC_RMCM_SHAPER_RAMB_EXP_REGION26_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_26_27, MPC_RMCM_SHAPER_RAMB_EXP_REGION27_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_26_27, MPC_RMCM_SHAPER_RAMB_EXP_REGION27_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_28_29, MPC_RMCM_SHAPER_RAMB_EXP_REGION28_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_28_29, MPC_RMCM_SHAPER_RAMB_EXP_REGION28_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_28_29, MPC_RMCM_SHAPER_RAMB_EXP_REGION29_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_28_29, MPC_RMCM_SHAPER_RAMB_EXP_REGION29_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_30_31, MPC_RMCM_SHAPER_RAMB_EXP_REGION30_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_30_31, MPC_RMCM_SHAPER_RAMB_EXP_REGION30_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_30_31, MPC_RMCM_SHAPER_RAMB_EXP_REGION31_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_30_31, MPC_RMCM_SHAPER_RAMB_EXP_REGION31_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_32_33, MPC_RMCM_SHAPER_RAMB_EXP_REGION32_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_32_33, MPC_RMCM_SHAPER_RAMB_EXP_REGION32_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_32_33, MPC_RMCM_SHAPER_RAMB_EXP_REGION33_LUT_OFFSET, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_32_33, MPC_RMCM_SHAPER_RAMB_EXP_REGION33_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_3DLUT_MODE, MPC_RMCM_3DLUT_MODE, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_3DLUT_MODE, MPC_RMCM_3DLUT_SIZE, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_3DLUT_MODE, MPC_RMCM_3DLUT_MODE_CURRENT, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_3DLUT_INDEX, MPC_RMCM_3DLUT_INDEX, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_3DLUT_DATA, MPC_RMCM_3DLUT_DATA0, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_3DLUT_DATA, MPC_RMCM_3DLUT_DATA1, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_3DLUT_DATA_30BIT, MPC_RMCM_3DLUT_DATA_30BIT, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_3DLUT_READ_WRITE_CONTROL, MPC_RMCM_3DLUT_WRITE_EN_MASK, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_3DLUT_READ_WRITE_CONTROL, MPC_RMCM_3DLUT_RAM_SEL, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_3DLUT_READ_WRITE_CONTROL, MPC_RMCM_3DLUT_30BIT_EN, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_3DLUT_READ_WRITE_CONTROL, MPC_RMCM_3DLUT_READ_SEL, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_3DLUT_OUT_NORM_FACTOR, MPC_RMCM_3DLUT_OUT_NORM_FACTOR, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_3DLUT_OUT_OFFSET_R, MPC_RMCM_3DLUT_OUT_OFFSET_R, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_3DLUT_OUT_OFFSET_R, MPC_RMCM_3DLUT_OUT_SCALE_R, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_3DLUT_OUT_OFFSET_G, MPC_RMCM_3DLUT_OUT_OFFSET_G, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_3DLUT_OUT_OFFSET_G, MPC_RMCM_3DLUT_OUT_SCALE_G, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_3DLUT_OUT_OFFSET_B, MPC_RMCM_3DLUT_OUT_OFFSET_B, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_3DLUT_OUT_OFFSET_B, MPC_RMCM_3DLUT_OUT_SCALE_B, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_COEF_FORMAT, MPC_RMCM_GAMUT_REMAP_COEF_FORMAT, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_MODE, MPC_RMCM_GAMUT_REMAP_MODE, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_MODE, MPC_RMCM_GAMUT_REMAP_MODE_CURRENT, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C11_C12_A, MPC_RMCM_GAMUT_REMAP_C11_A, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C11_C12_A, MPC_RMCM_GAMUT_REMAP_C12_A, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C13_C14_A, MPC_RMCM_GAMUT_REMAP_C13_A, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C13_C14_A, MPC_RMCM_GAMUT_REMAP_C14_A, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C21_C22_A, MPC_RMCM_GAMUT_REMAP_C21_A, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C21_C22_A, MPC_RMCM_GAMUT_REMAP_C22_A, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C23_C24_A, MPC_RMCM_GAMUT_REMAP_C23_A, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C23_C24_A, MPC_RMCM_GAMUT_REMAP_C24_A, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C31_C32_A, MPC_RMCM_GAMUT_REMAP_C31_A, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C31_C32_A, MPC_RMCM_GAMUT_REMAP_C32_A, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C33_C34_A, MPC_RMCM_GAMUT_REMAP_C33_A, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C33_C34_A, MPC_RMCM_GAMUT_REMAP_C34_A, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C11_C12_B, MPC_RMCM_GAMUT_REMAP_C11_B, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C11_C12_B, MPC_RMCM_GAMUT_REMAP_C12_B, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C13_C14_B, MPC_RMCM_GAMUT_REMAP_C13_B, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C13_C14_B, MPC_RMCM_GAMUT_REMAP_C14_B, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C21_C22_B, MPC_RMCM_GAMUT_REMAP_C21_B, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C21_C22_B, MPC_RMCM_GAMUT_REMAP_C22_B, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C23_C24_B, MPC_RMCM_GAMUT_REMAP_C23_B, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C23_C24_B, MPC_RMCM_GAMUT_REMAP_C24_B, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C31_C32_B, MPC_RMCM_GAMUT_REMAP_C31_B, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C31_C32_B, MPC_RMCM_GAMUT_REMAP_C32_B, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C33_C34_B, MPC_RMCM_GAMUT_REMAP_C33_B, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C33_C34_B, MPC_RMCM_GAMUT_REMAP_C34_B, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_MEM_PWR_CTRL, MPC_RMCM_SHAPER_MEM_PWR_FORCE, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_MEM_PWR_CTRL, MPC_RMCM_SHAPER_MEM_PWR_DIS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_MEM_PWR_CTRL, MPC_RMCM_SHAPER_MEM_LOW_PWR_MODE, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_MEM_PWR_CTRL, MPC_RMCM_3DLUT_MEM_PWR_FORCE, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_MEM_PWR_CTRL, MPC_RMCM_3DLUT_MEM_PWR_DIS, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_MEM_PWR_CTRL, MPC_RMCM_3DLUT_MEM_LOW_PWR_MODE, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_MEM_PWR_CTRL, MPC_RMCM_SHAPER_MEM_PWR_STATE, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_MEM_PWR_CTRL, MPC_RMCM_3DLUT_MEM_PWR_STATE, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_3DLUT_FAST_LOAD_SELECT, MPC_RMCM_3DLUT_FL_SEL, mask_sh),\ + SF(MPC_RMCM0_MPC_RMCM_3DLUT_FAST_LOAD_STATUS, MPC_RMCM_3DLUT_FL_DONE, mask_sh), \ + SF(MPC_RMCM0_MPC_RMCM_3DLUT_FAST_LOAD_STATUS, MPC_RMCM_3DLUT_FL_SOFT_UNDERFLOW, mask_sh), \ + SF(MPC_RMCM0_MPC_RMCM_3DLUT_FAST_LOAD_STATUS, MPC_RMCM_3DLUT_FL_HARD_UNDERFLOW, mask_sh), \ + SF(MPC_RMCM0_MPC_RMCM_CNTL, MPC_RMCM_CNTL, mask_sh), \ + SF(MPC_RMCM0_MPC_RMCM_TEST_DEBUG_INDEX, MPC_RMCM_TEST_DEBUG_INDEX, mask_sh), \ + SF(MPC_RMCM0_MPC_RMCM_TEST_DEBUG_INDEX, MPC_RMCM_TEST_DEBUG_WRITE_EN, mask_sh), \ + SF(MPC_RMCM0_MPC_RMCM_TEST_DEBUG_DATA, MPC_RMCM_TEST_DEBUG_DATA, mask_sh) + +#define MPC_RMCM_REG_LIST_DCN42(inst)\ + SRII(MPC_RMCM_SHAPER_CONTROL, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_OFFSET_R, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_OFFSET_G, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_OFFSET_B, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_SCALE_R, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_SCALE_G_B, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_LUT_INDEX, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_LUT_DATA, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMA_START_CNTL_B, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMA_START_CNTL_G, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMA_START_CNTL_R, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMA_END_CNTL_B, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMA_END_CNTL_G, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMA_END_CNTL_R, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMA_REGION_0_1, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMA_REGION_2_3, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMA_REGION_4_5, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMA_REGION_6_7, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMA_REGION_8_9, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMA_REGION_10_11, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMA_REGION_12_13, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMA_REGION_14_15, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMA_REGION_16_17, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMA_REGION_18_19, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMA_REGION_20_21, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMA_REGION_22_23, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMA_REGION_24_25, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMA_REGION_26_27, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMA_REGION_28_29, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMA_REGION_30_31, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMA_REGION_32_33, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMB_START_CNTL_B, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMB_START_CNTL_G, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMB_START_CNTL_R, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMB_END_CNTL_B, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMB_END_CNTL_G, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMB_END_CNTL_R, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMB_REGION_0_1, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMB_REGION_2_3, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMB_REGION_4_5, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMB_REGION_6_7, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMB_REGION_8_9, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMB_REGION_10_11, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMB_REGION_12_13, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMB_REGION_14_15, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMB_REGION_16_17, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMB_REGION_18_19, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMB_REGION_20_21, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMB_REGION_22_23, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMB_REGION_24_25, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMB_REGION_26_27, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMB_REGION_28_29, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMB_REGION_30_31, MPC_RMCM, inst),\ + SRII(MPC_RMCM_SHAPER_RAMB_REGION_32_33, MPC_RMCM, inst),\ + SRII(MPC_RMCM_3DLUT_MODE, MPC_RMCM, inst), /*TODO: may need to add other 3DLUT regs*/\ + SRII(MPC_RMCM_3DLUT_INDEX, MPC_RMCM, inst),\ + SRII(MPC_RMCM_3DLUT_DATA, MPC_RMCM, inst),\ + SRII(MPC_RMCM_3DLUT_DATA_30BIT, MPC_RMCM, inst),\ + SRII(MPC_RMCM_3DLUT_READ_WRITE_CONTROL, MPC_RMCM, inst),\ + SRII(MPC_RMCM_3DLUT_OUT_NORM_FACTOR, MPC_RMCM, inst),\ + SRII(MPC_RMCM_3DLUT_OUT_OFFSET_R, MPC_RMCM, inst),\ + SRII(MPC_RMCM_3DLUT_OUT_OFFSET_G, MPC_RMCM, inst),\ + SRII(MPC_RMCM_3DLUT_OUT_OFFSET_B, MPC_RMCM, inst),\ + SRII(MPC_RMCM_GAMUT_REMAP_COEF_FORMAT, MPC_RMCM, inst),\ + SRII(MPC_RMCM_GAMUT_REMAP_MODE, MPC_RMCM, inst),\ + SRII(MPC_RMCM_GAMUT_REMAP_C11_C12_A, MPC_RMCM, inst),\ + SRII(MPC_RMCM_GAMUT_REMAP_C13_C14_A, MPC_RMCM, inst),\ + SRII(MPC_RMCM_GAMUT_REMAP_C21_C22_A, MPC_RMCM, inst),\ + SRII(MPC_RMCM_GAMUT_REMAP_C23_C24_A, MPC_RMCM, inst),\ + SRII(MPC_RMCM_GAMUT_REMAP_C31_C32_A, MPC_RMCM, inst),\ + SRII(MPC_RMCM_GAMUT_REMAP_C33_C34_A, MPC_RMCM, inst),\ + SRII(MPC_RMCM_GAMUT_REMAP_C11_C12_B, MPC_RMCM, inst),\ + SRII(MPC_RMCM_GAMUT_REMAP_C13_C14_B, MPC_RMCM, inst),\ + SRII(MPC_RMCM_GAMUT_REMAP_C21_C22_B, MPC_RMCM, inst),\ + SRII(MPC_RMCM_GAMUT_REMAP_C23_C24_B, MPC_RMCM, inst),\ + SRII(MPC_RMCM_GAMUT_REMAP_C31_C32_B, MPC_RMCM, inst),\ + SRII(MPC_RMCM_GAMUT_REMAP_C33_C34_B, MPC_RMCM, inst),\ + SRII(MPC_RMCM_MEM_PWR_CTRL, MPC_RMCM, inst),\ + SRII(MPC_RMCM_3DLUT_FAST_LOAD_SELECT, MPC_RMCM, inst),\ + SRII(MPC_RMCM_3DLUT_FAST_LOAD_STATUS, MPC_RMCM, inst),\ + SRII(MPC_RMCM_CNTL, MPC_RMCM, inst),\ + SRII(MPC_RMCM_TEST_DEBUG_INDEX, MPC_RMCM, inst),\ + SRII(MPC_RMCM_TEST_DEBUG_DATA, MPC_RMCM, inst) + + +#define MPC_REG_LIST_DCN42(inst) \ + MPC_REG_LIST_DCN4_01_RI(inst),\ + SRII(MPCC_CONTROL2, MPCC, inst) + +#define MPC_REG_FIELD_LIST_DCN42(type) \ + MPC_REG_FIELD_LIST_DCN4_01(type); \ + type MPCC_MCM_3DLUT_OUT_OFFSET_R;\ + type MPCC_MCM_3DLUT_OUT_SCALE_R;\ + type MPCC_MCM_3DLUT_OUT_OFFSET_G;\ + type MPCC_MCM_3DLUT_OUT_SCALE_G;\ + type MPCC_MCM_3DLUT_OUT_OFFSET_B;\ + type MPCC_MCM_3DLUT_OUT_SCALE_B;\ + type MPC_RMCM_SHAPER_LUT_MODE;\ + type MPC_RMCM_SHAPER_MODE_CURRENT;\ + type MPC_RMCM_SHAPER_OFFSET_R;\ + type MPC_RMCM_SHAPER_OFFSET_G;\ + type MPC_RMCM_SHAPER_OFFSET_B;\ + type MPC_RMCM_SHAPER_SCALE_R;\ + type MPC_RMCM_SHAPER_SCALE_G;\ + type MPC_RMCM_SHAPER_SCALE_B;\ + type MPC_RMCM_SHAPER_LUT_INDEX;\ + type MPC_RMCM_SHAPER_LUT_DATA;\ + type MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK;\ + type MPC_RMCM_SHAPER_LUT_WRITE_SEL; \ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_B; \ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B; \ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_G; \ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_G;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_R;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_R;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_B;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_BASE_B;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_G;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_BASE_G;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_R;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_BASE_R;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET; \ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS; \ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION2_LUT_OFFSET; \ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION2_NUM_SEGMENTS; \ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION3_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION3_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION4_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION4_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION5_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION5_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION6_LUT_OFFSET; \ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION6_NUM_SEGMENTS; \ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION7_LUT_OFFSET; \ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION7_NUM_SEGMENTS; \ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION8_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION8_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION9_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION9_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION10_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION10_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION11_LUT_OFFSET; \ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION11_NUM_SEGMENTS; \ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION12_LUT_OFFSET; \ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION12_NUM_SEGMENTS; \ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION13_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION13_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION14_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION14_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION15_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION15_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION16_LUT_OFFSET; \ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION16_NUM_SEGMENTS; \ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION17_LUT_OFFSET; \ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION17_NUM_SEGMENTS; \ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION18_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION18_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION19_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION19_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION20_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION20_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION21_LUT_OFFSET; \ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION21_NUM_SEGMENTS; \ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION22_LUT_OFFSET; \ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION22_NUM_SEGMENTS; \ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION23_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION23_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION24_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION24_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION25_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION25_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION26_LUT_OFFSET; \ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION26_NUM_SEGMENTS; \ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION27_LUT_OFFSET; \ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION27_NUM_SEGMENTS; \ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION28_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION28_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION29_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION29_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION30_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION30_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION31_LUT_OFFSET; \ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION31_NUM_SEGMENTS; \ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION32_LUT_OFFSET; \ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION32_NUM_SEGMENTS; \ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION33_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMA_EXP_REGION33_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_B; \ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_B; \ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_G; \ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_G;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_R;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_R;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_B;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_BASE_B;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_G;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_BASE_G;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_R;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_BASE_R;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET; \ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS; \ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION2_LUT_OFFSET; \ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION2_NUM_SEGMENTS; \ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION3_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION3_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION4_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION4_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION5_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION5_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION6_LUT_OFFSET; \ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION6_NUM_SEGMENTS; \ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION7_LUT_OFFSET; \ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION7_NUM_SEGMENTS; \ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION8_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION8_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION9_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION9_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION10_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION10_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION11_LUT_OFFSET; \ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION11_NUM_SEGMENTS; \ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION12_LUT_OFFSET; \ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION12_NUM_SEGMENTS; \ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION13_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION13_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION14_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION14_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION15_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION15_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION16_LUT_OFFSET; \ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION16_NUM_SEGMENTS; \ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION17_LUT_OFFSET; \ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION17_NUM_SEGMENTS; \ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION18_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION18_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION19_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION19_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION20_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION20_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION21_LUT_OFFSET; \ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION21_NUM_SEGMENTS; \ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION22_LUT_OFFSET; \ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION22_NUM_SEGMENTS; \ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION23_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION23_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION24_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION24_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION25_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION25_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION26_LUT_OFFSET; \ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION26_NUM_SEGMENTS; \ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION27_LUT_OFFSET; \ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION27_NUM_SEGMENTS; \ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION28_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION28_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION29_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION29_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION30_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION30_NUM_SEGMENTS;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION31_LUT_OFFSET; \ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION31_NUM_SEGMENTS; \ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION32_LUT_OFFSET; \ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION32_NUM_SEGMENTS; \ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION33_LUT_OFFSET;\ + type MPC_RMCM_SHAPER_RAMB_EXP_REGION33_NUM_SEGMENTS;\ + type MPC_RMCM_3DLUT_MODE;\ + type MPC_RMCM_3DLUT_SIZE;\ + type MPC_RMCM_3DLUT_MODE_CURRENT;\ + type MPC_RMCM_3DLUT_INDEX; \ + type MPC_RMCM_3DLUT_DATA0; \ + type MPC_RMCM_3DLUT_DATA1; \ + type MPC_RMCM_3DLUT_DATA_30BIT; \ + type MPC_RMCM_3DLUT_WRITE_EN_MASK;\ + type MPC_RMCM_3DLUT_RAM_SEL;\ + type MPC_RMCM_3DLUT_30BIT_EN;\ + type MPC_RMCM_3DLUT_READ_SEL;\ + type MPC_RMCM_3DLUT_OUT_NORM_FACTOR;\ + type MPC_RMCM_3DLUT_OUT_OFFSET_R;\ + type MPC_RMCM_3DLUT_OUT_SCALE_R; \ + type MPC_RMCM_3DLUT_OUT_OFFSET_G; \ + type MPC_RMCM_3DLUT_OUT_SCALE_G; \ + type MPC_RMCM_3DLUT_OUT_OFFSET_B; \ + type MPC_RMCM_3DLUT_OUT_SCALE_B;\ + type MPC_RMCM_GAMUT_REMAP_COEF_FORMAT;\ + type MPC_RMCM_GAMUT_REMAP_MODE;\ + type MPC_RMCM_GAMUT_REMAP_MODE_CURRENT;\ + type MPC_RMCM_GAMUT_REMAP_C11_A;\ + type MPC_RMCM_GAMUT_REMAP_C12_A;\ + type MPC_RMCM_GAMUT_REMAP_C13_A; \ + type MPC_RMCM_GAMUT_REMAP_C14_A; \ + type MPC_RMCM_GAMUT_REMAP_C21_A; \ + type MPC_RMCM_GAMUT_REMAP_C22_A; \ + type MPC_RMCM_GAMUT_REMAP_C23_A;\ + type MPC_RMCM_GAMUT_REMAP_C24_A;\ + type MPC_RMCM_GAMUT_REMAP_C31_A;\ + type MPC_RMCM_GAMUT_REMAP_C32_A;\ + type MPC_RMCM_GAMUT_REMAP_C33_A;\ + type MPC_RMCM_GAMUT_REMAP_C34_A;\ + type MPC_RMCM_GAMUT_REMAP_C11_B;\ + type MPC_RMCM_GAMUT_REMAP_C12_B;\ + type MPC_RMCM_GAMUT_REMAP_C13_B; \ + type MPC_RMCM_GAMUT_REMAP_C14_B; \ + type MPC_RMCM_GAMUT_REMAP_C21_B; \ + type MPC_RMCM_GAMUT_REMAP_C22_B; \ + type MPC_RMCM_GAMUT_REMAP_C23_B;\ + type MPC_RMCM_GAMUT_REMAP_C24_B;\ + type MPC_RMCM_GAMUT_REMAP_C31_B;\ + type MPC_RMCM_GAMUT_REMAP_C32_B;\ + type MPC_RMCM_GAMUT_REMAP_C33_B;\ + type MPC_RMCM_GAMUT_REMAP_C34_B;\ + type MPC_RMCM_SHAPER_MEM_PWR_FORCE; \ + type MPC_RMCM_SHAPER_MEM_PWR_DIS; \ + type MPC_RMCM_SHAPER_MEM_LOW_PWR_MODE; \ + type MPC_RMCM_3DLUT_MEM_PWR_FORCE;\ + type MPC_RMCM_3DLUT_MEM_PWR_DIS;\ + type MPC_RMCM_3DLUT_MEM_LOW_PWR_MODE;\ + type MPC_RMCM_SHAPER_MEM_PWR_STATE;\ + type MPC_RMCM_3DLUT_MEM_PWR_STATE;\ + type MPC_RMCM_3DLUT_FL_SEL;\ + type MPC_RMCM_3DLUT_FL_DONE; \ + type MPC_RMCM_3DLUT_FL_SOFT_UNDERFLOW; \ + type MPC_RMCM_3DLUT_FL_HARD_UNDERFLOW; \ + type MPC_RMCM_CNTL; \ + type MPC_RMCM_TEST_DEBUG_INDEX;\ + type MPC_RMCM_TEST_DEBUG_WRITE_EN;\ + type MPC_RMCM_TEST_DEBUG_DATA + +#define MPC_REG_VARIABLE_LIST_DCN42 \ + MPC_REG_VARIABLE_LIST_DCN4_01 \ + uint32_t MPCC_CONTROL2[MAX_MPCC];\ + uint32_t MPC_RMCM_SHAPER_CONTROL[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_OFFSET_R[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_OFFSET_G[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_OFFSET_B[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_SCALE_R[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_SCALE_G_B[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_LUT_INDEX[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_LUT_DATA[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMA_START_CNTL_B[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMA_START_CNTL_G[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMA_START_CNTL_R[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMA_END_CNTL_B[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMA_END_CNTL_G[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMA_END_CNTL_R[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMA_REGION_0_1[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMA_REGION_2_3[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMA_REGION_4_5[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMA_REGION_6_7[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMA_REGION_8_9[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMA_REGION_10_11[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMA_REGION_12_13[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMA_REGION_14_15[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMA_REGION_16_17[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMA_REGION_18_19[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMA_REGION_20_21[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMA_REGION_22_23[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMA_REGION_24_25[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMA_REGION_26_27[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMA_REGION_28_29[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMA_REGION_30_31[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMA_REGION_32_33[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMB_START_CNTL_B[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMB_START_CNTL_G[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMB_START_CNTL_R[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMB_END_CNTL_B[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMB_END_CNTL_G[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMB_END_CNTL_R[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMB_REGION_0_1[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMB_REGION_2_3[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMB_REGION_4_5[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMB_REGION_6_7[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMB_REGION_8_9[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMB_REGION_10_11[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMB_REGION_12_13[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMB_REGION_14_15[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMB_REGION_16_17[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMB_REGION_18_19[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMB_REGION_20_21[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMB_REGION_22_23[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMB_REGION_24_25[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMB_REGION_26_27[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMB_REGION_28_29[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMB_REGION_30_31[MAX_MPCC]; \ + uint32_t MPC_RMCM_SHAPER_RAMB_REGION_32_33[MAX_MPCC]; \ + uint32_t MPC_RMCM_3DLUT_MODE[MAX_MPCC]; \ + uint32_t MPC_RMCM_3DLUT_INDEX[MAX_MPCC]; \ + uint32_t MPC_RMCM_3DLUT_DATA[MAX_MPCC]; \ + uint32_t MPC_RMCM_3DLUT_DATA_30BIT[MAX_MPCC]; \ + uint32_t MPC_RMCM_3DLUT_READ_WRITE_CONTROL[MAX_MPCC]; \ + uint32_t MPC_RMCM_3DLUT_OUT_NORM_FACTOR[MAX_MPCC]; \ + uint32_t MPC_RMCM_3DLUT_OUT_OFFSET_R[MAX_MPCC]; \ + uint32_t MPC_RMCM_3DLUT_OUT_OFFSET_G[MAX_MPCC]; \ + uint32_t MPC_RMCM_3DLUT_OUT_OFFSET_B[MAX_MPCC]; \ + uint32_t MPC_RMCM_GAMUT_REMAP_COEF_FORMAT[MAX_MPCC]; \ + uint32_t MPC_RMCM_GAMUT_REMAP_MODE[MAX_MPCC]; \ + uint32_t MPC_RMCM_GAMUT_REMAP_C11_C12_A[MAX_MPCC]; \ + uint32_t MPC_RMCM_GAMUT_REMAP_C13_C14_A[MAX_MPCC]; \ + uint32_t MPC_RMCM_GAMUT_REMAP_C21_C22_A[MAX_MPCC]; \ + uint32_t MPC_RMCM_GAMUT_REMAP_C23_C24_A[MAX_MPCC]; \ + uint32_t MPC_RMCM_GAMUT_REMAP_C31_C32_A[MAX_MPCC]; \ + uint32_t MPC_RMCM_GAMUT_REMAP_C33_C34_A[MAX_MPCC]; \ + uint32_t MPC_RMCM_GAMUT_REMAP_C11_C12_B[MAX_MPCC]; \ + uint32_t MPC_RMCM_GAMUT_REMAP_C13_C14_B[MAX_MPCC]; \ + uint32_t MPC_RMCM_GAMUT_REMAP_C21_C22_B[MAX_MPCC]; \ + uint32_t MPC_RMCM_GAMUT_REMAP_C23_C24_B[MAX_MPCC]; \ + uint32_t MPC_RMCM_GAMUT_REMAP_C31_C32_B[MAX_MPCC]; \ + uint32_t MPC_RMCM_GAMUT_REMAP_C33_C34_B[MAX_MPCC]; \ + uint32_t MPC_RMCM_MEM_PWR_CTRL[MAX_MPCC]; \ + uint32_t MPC_RMCM_3DLUT_FAST_LOAD_SELECT[MAX_MPCC]; \ + uint32_t MPC_RMCM_3DLUT_FAST_LOAD_STATUS[MAX_MPCC]; \ + uint32_t MPC_RMCM_CNTL[MAX_MPCC]; \ + uint32_t MPC_RMCM_TEST_DEBUG_INDEX[MAX_MPCC]; \ + uint32_t MPC_RMCM_TEST_DEBUG_DATA[MAX_MPCC] + +struct dcn42_mpc_shift { + MPC_REG_FIELD_LIST_DCN42(uint8_t); +}; + +struct dcn42_mpc_mask { + MPC_REG_FIELD_LIST_DCN42(uint32_t); +}; + +struct dcn42_mpc_registers { + MPC_REG_VARIABLE_LIST_DCN42; +}; + +struct dcn42_mpc { + struct mpc base; + + int mpcc_in_use_mask; + int num_mpcc; + const struct dcn42_mpc_registers *mpc_regs; + const struct dcn42_mpc_shift *mpc_shift; + const struct dcn42_mpc_mask *mpc_mask; + int num_rmu; +}; +void dcn42_mpc_construct(struct dcn42_mpc *mpc401, + struct dc_context *ctx, + const struct dcn42_mpc_registers *mpc_regs, + const struct dcn42_mpc_shift *mpc_shift, + const struct dcn42_mpc_mask *mpc_mask, + int num_mpcc, + int num_rmu); + +void mpc42_init_mpcc(struct mpcc *mpcc, int mpcc_inst); + +/* RMCM */ +void mpc42_program_rmcm_shaper_lut( + struct mpc *mpc, + const struct pwl_result_data *rgb, + uint32_t num, + uint32_t mpcc_id); +void mpc42_program_rmcm_shaper_lutb_settings( + struct mpc *mpc, + const struct pwl_params *params, + uint32_t mpcc_id); +void mpc42_program_rmcm_shaper_luta_settings( + struct mpc *mpc, + const struct pwl_params *params, + uint32_t mpcc_id); +void mpc42_configure_rmcm_shaper_lut( + struct mpc *mpc, + bool is_ram_a, + uint32_t mpcc_id); +void mpc42_power_on_rmcm_shaper_3dlut( + struct mpc *mpc, + uint32_t mpcc_id, + bool power_on); +void mpc42_enable_3dlut_fl( + struct mpc *mpc, + bool enable, + int mpcc_id); +void mpc42_update_3dlut_fast_load_select( + struct mpc *mpc, + int mpcc_id, + int hubp_idx); +void mpc42_populate_rmcm_lut( + struct mpc *mpc, + const union mcm_lut_params params, + bool lut_bank_a, + int mpcc_id); +void mpc42_program_rmcm_lut_read_write_control( + struct mpc *mpc, + const enum MCM_LUT_ID id, + bool lut_bank_a, + bool enabled, + int mpcc_id); +void mpc42_program_lut_mode( + struct mpc *mpc, + bool enable, + bool lut_bank_a, + int mpcc_id); +void mpc42_program_rmcm_3dlut_size( + struct mpc *mpc, + const enum dc_cm_lut_size size, + int mpcc_id); +void mpc42_program_rmcm_3dlut_fast_load_bias_scale( + struct mpc *mpc, + uint16_t bias, + uint16_t scale, + int mpcc_id); +void mpc42_program_rmcm_bit_depth( + struct mpc *mpc, + uint16_t bit_depth, + int mpcc_id); + +void mpc42_set_fl_config( + struct mpc *mpc, + struct mpc_fl_3dlut_config *cfg, + int mpcc_id); + +void mpc42_read_mpcc_state( + struct mpc *mpc, + int mpcc_inst, + struct mpcc_state *s); + +void mpc42_update_blending( + struct mpc *mpc, + struct mpcc_blnd_cfg *blnd_cfg, + int mpcc_id); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/opp/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/opp/dcn10/dcn10_opp.c index 45d418636d0c..b49bd155cad4 100644 --- a/drivers/gpu/drm/amd/display/dc/opp/dcn10/dcn10_opp.c +++ b/drivers/gpu/drm/amd/display/dc/opp/dcn10/dcn10_opp.c @@ -250,6 +250,7 @@ void opp1_set_dyn_expansion( enum dc_color_depth color_dpth, enum signal_type signal) { + (void)color_sp; struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, diff --git a/drivers/gpu/drm/amd/display/dc/optc/Makefile b/drivers/gpu/drm/amd/display/dc/optc/Makefile index 29fb610c8660..06c98d70eabc 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/optc/Makefile @@ -104,11 +104,19 @@ AMD_DISPLAY_FILES += $(AMD_DAL_OPTC_DCN35) ############################################################################### -############################################################################### OPTC_DCN401 = dcn401_optc.o AMD_DAL_OPTC_DCN401 = $(addprefix $(AMDDALPATH)/dc/optc/dcn401/,$(OPTC_DCN401)) AMD_DISPLAY_FILES += $(AMD_DAL_OPTC_DCN401) + +############################################################################### + +OPTC_DCN42 = dcn42_optc.o + +AMD_DAL_OPTC_DCN42 = $(addprefix $(AMDDALPATH)/dc/optc/dcn42/,$(OPTC_DCN42)) + +AMD_DISPLAY_FILES += $(AMD_DAL_OPTC_DCN42) + endif diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.c index 6f7b0f816f2a..9e66b9b97c63 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.c +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.c @@ -164,6 +164,7 @@ void optc1_program_timing( const enum signal_type signal, bool use_vbios) { + (void)use_vbios; struct dc_crtc_timing patched_crtc_timing; uint32_t asic_blank_end; uint32_t asic_blank_start; @@ -855,6 +856,8 @@ void optc1_set_early_control( struct timing_generator *optc, uint32_t early_cntl) { + (void)optc; + (void)early_cntl; /* asic design change, do not need this control * empty for share caller logic */ @@ -1249,6 +1252,7 @@ void optc1_get_crtc_scanoutpos( static void optc1_enable_stereo(struct timing_generator *optc, const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags) { + (void)timing; struct optc *optc1 = DCN10TG_FROM_TG(optc); if (flags) { diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h index 0b3f974f452e..138081e6cc97 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h @@ -1,5 +1,5 @@ /* - * Copyright 2012-15 Advanced Micro Devices, Inc. + * Copyright 2012-2026 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -218,7 +218,7 @@ uint32_t OTG_CRC_SIG_BLUE_CONTROL_MASK; \ uint32_t OTG_CRC_SIG_RED_GREEN_MASK; \ uint32_t OTG_DLPC_CONTROL; \ - uint32_t OTG_DRR_CONTROL2; \ + uint32_t OTG_DRR_CONTOL2; \ uint32_t OTG_DRR_TIMING_INT_STATUS; \ uint32_t OTG_GLOBAL_CONTROL3; \ uint32_t OTG_GLOBAL_SYNC_STATUS; \ @@ -253,8 +253,20 @@ uint32_t OTG_CRC1_DATA_B32 +#define OPTC_REG_VARIABLE_LIST_DCN42 \ + uint32_t OTG_PWA_FRAME_SYNC_CONTROL; \ + uint32_t OTG_CRC0_DATA_R; \ + uint32_t OTG_CRC1_DATA_R; \ + uint32_t OTG_CRC2_DATA_R; \ + uint32_t OTG_CRC3_DATA_R; \ + uint32_t OTG_CRC0_DATA_G; \ + uint32_t OTG_CRC1_DATA_G; \ + uint32_t OTG_CRC2_DATA_G; \ + uint32_t OTG_CRC3_DATA_G + struct dcn_optc_registers { OPTC_REG_VARIABLE_LIST_DCN; + OPTC_REG_VARIABLE_LIST_DCN42; }; #define TG_COMMON_MASK_SH_LIST_DCN(mask_sh)\ @@ -664,6 +676,10 @@ struct dcn_optc_registers { type OTG_V_COUNT_STOP_TIMER; #define TG_REG_FIELD_LIST_DCN3_6(type) \ + type OPTC_RSMU_UNDERFLOW_CLEAR;\ + type OPTC_RSMU_UNDERFLOW_OCCURRED_STATUS;\ + type OPTC_RSMU_UNDERFLOW_INT_EN;\ + type OPTC_RSMU_UNDERFLOW_INT_STATUS;\ type OTG_CRC_POLY_SEL; \ type CRC0_R_CR32; \ type CRC0_G_Y32; \ @@ -679,6 +695,10 @@ struct dcn_optc_registers { type OTG_UNBLANK;\ type OTG_PSTATE_ALLOW_WIDTH_MIN; +#define TG_REG_FIELD_LIST_DCN42(type) \ + type OTG_PWA_FRAME_SYNC_EN;\ + type OTG_PWA_FRAME_SYNC_VCOUNT_MODE;\ + type OTG_PWA_FRAME_SYNC_LINE; struct dcn_optc_shift { TG_REG_FIELD_LIST(uint8_t) @@ -687,6 +707,7 @@ struct dcn_optc_shift { TG_REG_FIELD_LIST_DCN3_5(uint8_t) TG_REG_FIELD_LIST_DCN3_6(uint8_t) TG_REG_FIELD_LIST_DCN401(uint8_t) + TG_REG_FIELD_LIST_DCN42(uint8_t) }; struct dcn_optc_mask { @@ -696,6 +717,7 @@ struct dcn_optc_mask { TG_REG_FIELD_LIST_DCN3_5(uint32_t) TG_REG_FIELD_LIST_DCN3_6(uint32_t) TG_REG_FIELD_LIST_DCN401(uint32_t) + TG_REG_FIELD_LIST_DCN42(uint32_t) }; void dcn10_timing_generator_init(struct optc *optc); diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c index e7a90a437fff..39ce4d4a61a1 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c @@ -181,6 +181,7 @@ void optc2_set_odm_bypass(struct timing_generator *optc, void optc2_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, int segment_width, int last_segment_width) { + (void)last_segment_width; struct optc *optc1 = DCN10TG_FROM_TG(optc); uint32_t memory_mask; @@ -261,6 +262,7 @@ static void optc2_align_vblanks( uint8_t master_clock_divider, uint8_t slave_clock_divider) { + (void)slave_clock_divider; /* accessing slave OTG registers */ struct optc *optc1 = DCN10TG_FROM_TG(optc_slave); diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.c index ee4665aa49e9..d72574db1f07 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.c +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.c @@ -218,6 +218,7 @@ void optc3_set_odm_bypass(struct timing_generator *optc, void optc3_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, int segment_width, int last_segment_width) { + (void)last_segment_width; struct optc *optc1 = DCN10TG_FROM_TG(optc); uint32_t memory_mask = 0; diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c index c6417538090f..5f53f8747812 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c @@ -43,6 +43,7 @@ static void optc31_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, int segment_width, int last_segment_width) { + (void)last_segment_width; struct optc *optc1 = DCN10TG_FROM_TG(optc); uint32_t memory_mask = 0; int mem_count_per_opp = (segment_width + 2559) / 2560; @@ -363,7 +364,7 @@ void optc31_read_reg_state(struct timing_generator *optc, struct dcn_optc_reg_st optc_reg_state->otg_crc3_data_rg = REG_READ(OTG_CRC3_DATA_RG); optc_reg_state->otg_dlpc_control = REG_READ(OTG_DLPC_CONTROL); optc_reg_state->otg_double_buffer_control = REG_READ(OTG_DOUBLE_BUFFER_CONTROL); - optc_reg_state->otg_drr_control2 = REG_READ(OTG_DRR_CONTROL2); + optc_reg_state->otg_drr_control2 = REG_READ(OTG_DRR_CONTOL2); optc_reg_state->otg_drr_control = REG_READ(OTG_DRR_CONTROL); optc_reg_state->otg_drr_timing_int_status = REG_READ(OTG_DRR_TIMING_INT_STATUS); optc_reg_state->otg_drr_trigger_window = REG_READ(OTG_DRR_TRIGGER_WINDOW); diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.c index 43ff957288b2..a7cf34937b2f 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.c +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.c @@ -50,6 +50,7 @@ static void optc314_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, int segment_width, int last_segment_width) { + (void)last_segment_width; struct optc *optc1 = DCN10TG_FROM_TG(optc); uint32_t memory_mask = 0; int h_active = segment_width * opp_cnt; diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c index 3dcb0d0c931c..60e546b69a05 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c @@ -45,6 +45,7 @@ static void optc32_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, int segment_width, int last_segment_width) { + (void)last_segment_width; struct optc *optc1 = DCN10TG_FROM_TG(optc); uint32_t memory_mask = 0; int h_active = segment_width * opp_cnt; diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c index 5aafd0eedf66..a880e4a6d165 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c @@ -58,6 +58,7 @@ static void optc35_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, int segment_width, int last_segment_width) { + (void)last_segment_width; struct optc *optc1 = DCN10TG_FROM_TG(optc); uint32_t memory_mask = 0; int h_active = segment_width * opp_cnt; diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.c new file mode 100644 index 000000000000..ed66a2bbb8ae --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.c @@ -0,0 +1,291 @@ +// SPDX-License-Identifier: MIT +// +// Copyright 2026 Advanced Micro Devices, Inc. + +#include "dcn42_optc.h" +#include "dcn30/dcn30_optc.h" +#include "dcn31/dcn31_optc.h" +#include "dcn32/dcn32_optc.h" +#include "dcn35/dcn35_optc.h" +#include "dcn401/dcn401_optc.h" +#include "reg_helper.h" +#include "dc.h" +#include "dcn_calc_math.h" +#include "dc_dmub_srv.h" +#include "dc_trace.h" + +#define REG(reg)\ + optc1->tg_regs->reg + +#define CTX \ + optc1->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + optc1->tg_shift->field_name, optc1->tg_mask->field_name + +/* + * optc42_get_crc - Capture CRC result per component + * + * @optc: timing_generator instance. + * @r_cr: 16-bit primary CRC signature for red data. + * @g_y: 16-bit primary CRC signature for green data. + * @b_cb: 16-bit primary CRC signature for blue data. + * + * This function reads the CRC signature from the OPTC registers. Notice that + * we have three registers to keep the CRC result per color component (RGB). + * + * Returns: + * If CRC is disabled, return false; otherwise, return true, and the CRC + * results in the parameters. + */ + +static bool optc42_get_crc(struct timing_generator *optc, uint8_t idx, + uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb) +{ + uint32_t field = 0; + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_GET(OTG_CRC_CNTL, OTG_CRC_EN, &field); + + /* Early return if CRC is not enabled for this CRTC */ + if (!field) + return false; + + + switch (idx) { + case 0: + /* OTG_CRC0_DATA_RG has the CRC16 results for the red component */ + REG_GET(OTG_CRC0_DATA_R, + CRC0_R_CR, r_cr); + + /* OTG_CRC0_DATA_RG has the CRC16 results for the green component */ + REG_GET(OTG_CRC0_DATA_G, + CRC0_G_Y, g_y); + + /* OTG_CRC0_DATA_B has the CRC16 results for the blue component */ + REG_GET(OTG_CRC0_DATA_B, + CRC0_B_CB, b_cb); + break; + case 1: + /* OTG_CRC1_DATA_RG has the CRC16 results for the red component */ + REG_GET(OTG_CRC1_DATA_R, + CRC0_R_CR, r_cr); + + /* OTG_CRC1_DATA_RG has the CRC16 results for the green component */ + REG_GET(OTG_CRC1_DATA_G, + CRC0_G_Y, g_y); + + /* OTG_CRC1_DATA_B has the CRC16 results for the blue component */ + REG_GET(OTG_CRC1_DATA_B, + CRC0_B_CB, b_cb); + break; + default: + return false; + } + return true; +} + +void optc42_enable_pwa(struct timing_generator *optc, struct otc_pwa_frame_sync *pwa_sync_param) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + /*VCOUNT_MODE : + 00 OTG_PWA_FRAME_SYNC_VCOUNT_0 Vcount counting from VSYNC. + 01 OTG_PWA_FRAME_SYNC_VCOUNT_1 Vcount counting from VSTARTUP.*/ + + if (pwa_sync_param == NULL) + return; + if (optc1->base.ctx->dc->debug.enable_otg_frame_sync_pwa) { + /*take mode 1, use line number from vstartup to get output frame as earlier as possible*/ + REG_UPDATE_3(OTG_PWA_FRAME_SYNC_CONTROL, + OTG_PWA_FRAME_SYNC_EN, 1, + OTG_PWA_FRAME_SYNC_VCOUNT_MODE, pwa_sync_param->pwa_sync_mode, + OTG_PWA_FRAME_SYNC_LINE, pwa_sync_param->pwa_frame_sync_line_offset); + } +} +void optc42_disable_pwa(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_UPDATE(OTG_PWA_FRAME_SYNC_CONTROL, + OTG_PWA_FRAME_SYNC_EN, 0); +} +void optc42_clear_optc_underflow(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_UPDATE(OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, 1); + REG_UPDATE(OPTC_RSMU_UNDERFLOW, OPTC_RSMU_UNDERFLOW_CLEAR, 1); +} +bool optc42_is_optc_underflow_occurred(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + uint32_t underflow_occurred = 0, rsmu_underflow_occurred = 0; + + REG_GET(OPTC_INPUT_GLOBAL_CONTROL, + OPTC_UNDERFLOW_OCCURRED_STATUS, + &underflow_occurred); + + REG_GET(OPTC_RSMU_UNDERFLOW, + OPTC_RSMU_UNDERFLOW_OCCURRED_STATUS, + &rsmu_underflow_occurred); + return (underflow_occurred == 1 || rsmu_underflow_occurred); +} +/* disable_crtc */ +bool optc42_disable_crtc(struct timing_generator *optc) +{ + optc401_disable_crtc(optc); + optc42_clear_optc_underflow(optc); + + return true; +} +static void optc42_set_timing_double_buffer(struct timing_generator *optc, bool enable) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + uint32_t mode = enable ? 2 : 0; + /* actually we have 4 modes now, use as the same as previous dcn3x + * 00 OTG_DOUBLE_BUFFER_CONTROL_OTG_DRR_TIMING_DBUF_UPDATE_MODE_0 Double buffer update occurs at any time in a frame. + * 01 OTG_DOUBLE_BUFFER_CONTROL_OTG_DRR_TIMING_DBUF_UPDATE_MODE_1 Double buffer update occurs at OTG start of frame. + * 02 OTG_DOUBLE_BUFFER_CONTROL_OTG_DRR_TIMING_DBUF_UPDATE_MODE_2 Double buffer occurs DP start of frame. + * 03 OTG_DOUBLE_BUFFER_CONTROL_OTG_DRR_TIMING_DBUF_UPDATE_MODE_3 Reserved. + */ + + REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL, + OTG_DRR_TIMING_DBUF_UPDATE_MODE, mode); +} +void optc42_tg_init(struct timing_generator *optc) +{ + optc42_set_timing_double_buffer(optc, true); + optc42_clear_optc_underflow(optc); +} + +void optc42_lock_doublebuffer_enable(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + uint32_t v_blank_start = 0; + uint32_t v_blank_end = 0; + uint32_t h_blank_start = 0; + uint32_t h_blank_end = 0; + + REG_GET_2(OTG_V_BLANK_START_END, + OTG_V_BLANK_START, &v_blank_start, + OTG_V_BLANK_END, &v_blank_end); + REG_GET_2(OTG_H_BLANK_START_END, + OTG_H_BLANK_START, &h_blank_start, + OTG_H_BLANK_END, &h_blank_end); + + REG_UPDATE_2(OTG_GLOBAL_CONTROL1, + MASTER_UPDATE_LOCK_DB_START_Y, v_blank_start, + MASTER_UPDATE_LOCK_DB_END_Y, v_blank_start); + REG_UPDATE_2(OTG_GLOBAL_CONTROL4, + DIG_UPDATE_POSITION_X, 20, + DIG_UPDATE_POSITION_Y, v_blank_start); + REG_UPDATE_3(OTG_GLOBAL_CONTROL0, + MASTER_UPDATE_LOCK_DB_START_X, h_blank_start - 200 - 1, + MASTER_UPDATE_LOCK_DB_END_X, h_blank_end, + MASTER_UPDATE_LOCK_DB_EN, 1); + REG_UPDATE(OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, 1); + + REG_SET_3(OTG_VUPDATE_KEEPOUT, 0, + MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, 0, + MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, 100, + OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, 1); + + TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, true); +} + +static struct timing_generator_funcs dcn42_tg_funcs = { + .validate_timing = optc1_validate_timing, + .program_timing = optc1_program_timing, + .setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0, + .setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1, + .setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2, + .program_global_sync = optc401_program_global_sync, + .enable_crtc = optc401_enable_crtc, + .disable_crtc = optc42_disable_crtc, + .phantom_crtc_post_enable = optc401_phantom_crtc_post_enable, + .disable_phantom_crtc = optc401_disable_phantom_otg, + /* used by enable_timing_synchronization. Not need for FPGA */ + .is_counter_moving = optc1_is_counter_moving, + .get_position = optc1_get_position, + .get_frame_count = optc1_get_vblank_counter, + .get_scanoutpos = optc1_get_crtc_scanoutpos, + .get_otg_active_size = optc1_get_otg_active_size, + .set_early_control = optc1_set_early_control, + /* used by enable_timing_synchronization. Not need for FPGA */ + .wait_for_state = optc1_wait_for_state, + .set_blank_color = optc3_program_blank_color, + .did_triggered_reset_occur = optc1_did_triggered_reset_occur, + .triplebuffer_lock = optc3_triplebuffer_lock, + .triplebuffer_unlock = optc2_triplebuffer_unlock, + .enable_reset_trigger = optc1_enable_reset_trigger, + .enable_crtc_reset = optc1_enable_crtc_reset, + .disable_reset_trigger = optc1_disable_reset_trigger, + .lock = optc3_lock, + .unlock = optc1_unlock, + .lock_doublebuffer_enable = optc42_lock_doublebuffer_enable, + .lock_doublebuffer_disable = optc3_lock_doublebuffer_disable, + .enable_optc_clock = optc1_enable_optc_clock, + .set_drr = optc401_set_drr, + .get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal, + .set_vtotal_min_max = optc401_set_vtotal_min_max, + .set_static_screen_control = optc1_set_static_screen_control, + .program_stereo = optc1_program_stereo, + .is_stereo_left_eye = optc1_is_stereo_left_eye, + .tg_init = optc42_tg_init, + .is_tg_enabled = optc1_is_tg_enabled, + .is_optc_underflow_occurred = optc42_is_optc_underflow_occurred, + .clear_optc_underflow = optc42_clear_optc_underflow, + .setup_global_swap_lock = NULL, + .get_crc = optc42_get_crc, + .configure_crc = optc35_configure_crc, + .set_dsc_config = optc3_set_dsc_config, + .get_dsc_status = optc2_get_dsc_status, + .set_dwb_source = NULL, + .set_odm_bypass = optc401_set_odm_bypass, + .set_odm_combine = optc401_set_odm_combine, + .wait_odm_doublebuffer_pending_clear = optc32_wait_odm_doublebuffer_pending_clear, + .set_h_timing_div_manual_mode = optc401_set_h_timing_div_manual_mode, + .get_optc_source = optc2_get_optc_source, + .wait_otg_disable = optc35_wait_otg_disable, + .set_out_mux = optc401_set_out_mux, + .set_drr_trigger_window = optc3_set_drr_trigger_window, + .set_vtotal_change_limit = optc3_set_vtotal_change_limit, + .set_gsl = optc2_set_gsl, + .set_gsl_source_select = optc2_set_gsl_source_select, + .set_vtg_params = optc1_set_vtg_params, + .program_manual_trigger = optc2_program_manual_trigger, + .setup_manual_trigger = optc2_setup_manual_trigger, + .get_hw_timing = optc1_get_hw_timing, + .init_odm = optc3_init_odm, + .set_long_vtotal = optc35_set_long_vtotal, + .is_two_pixels_per_container = optc1_is_two_pixels_per_container, + .get_optc_double_buffer_pending = optc3_get_optc_double_buffer_pending, + .get_otg_double_buffer_pending = optc3_get_otg_update_pending, + .get_pipe_update_pending = optc3_get_pipe_update_pending, + .set_vupdate_keepout = optc401_set_vupdate_keepout, + .wait_update_lock_status = optc401_wait_update_lock_status, + .optc_read_reg_state = optc31_read_reg_state, + .read_otg_state = optc31_read_otg_state, + .enable_otg_pwa = optc42_enable_pwa, + .disable_otg_pwa = optc42_disable_pwa, +}; + +void dcn42_timing_generator_init(struct optc *optc1) +{ + optc1->base.funcs = &dcn42_tg_funcs; + + optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1; + optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1; + + optc1->min_h_blank = 32; + optc1->min_v_blank = 3; + optc1->min_v_blank_interlace = 5; + optc1->min_h_sync_width = 4; + optc1->min_v_sync_width = 1; + optc1->max_frame_count = 0xFFFFFF; + + dcn35_timing_generator_set_fgcg( + optc1, CTX->dc->debug.enable_fine_grain_clock_gating.bits.optc); +} + diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.h new file mode 100644 index 000000000000..fc7192f01b33 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.h @@ -0,0 +1,220 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2024 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_OPTC_DCN42_H__ +#define __DC_OPTC_DCN42_H__ + +#include "dcn10/dcn10_optc.h" + +#define OPTC_COMMON_MASK_SH_LIST_DCN42(mask_sh)\ + SF(OTG0_OTG_VSTARTUP_PARAM, VSTARTUP_START, mask_sh),\ + SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_OFFSET, mask_sh),\ + SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_WIDTH, mask_sh),\ + SF(OTG0_OTG_VREADY_PARAM, VREADY_OFFSET, mask_sh),\ + SF(OTG0_OTG_MASTER_UPDATE_LOCK, OTG_MASTER_UPDATE_LOCK, mask_sh),\ + SF(OTG0_OTG_MASTER_UPDATE_LOCK, UPDATE_LOCK_STATUS, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_START_X, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_END_X, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_EN, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_START_Y, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_END_Y, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL2, OTG_MASTER_UPDATE_LOCK_SEL, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL4, DIG_UPDATE_POSITION_X, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL4, DIG_UPDATE_POSITION_Y, mask_sh),\ + SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, mask_sh),\ + SF(OTG0_OTG_H_TOTAL, OTG_H_TOTAL, mask_sh),\ + SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_START, mask_sh),\ + SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_END, mask_sh),\ + SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_START, mask_sh),\ + SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_END, mask_sh),\ + SF(OTG0_OTG_H_SYNC_A_CNTL, OTG_H_SYNC_A_POL, mask_sh),\ + SF(OTG0_OTG_V_TOTAL, OTG_V_TOTAL, mask_sh),\ + SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_START, mask_sh),\ + SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_END, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_START, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_END, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A_CNTL, OTG_V_SYNC_A_POL, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A_CNTL, OTG_V_SYNC_MODE, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_CURRENT_MASTER_EN_STATE, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_MASTER_EN, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_START_POINT_CNTL, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_DISABLE_POINT_CNTL, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_FIELD_NUMBER_CNTL, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_OUT_MUX, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EN, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_LINE_NUM, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_POLARITY, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EYE_FLAG_POLARITY, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, mask_sh),\ + SF(OTG0_OTG_STEREO_STATUS, OTG_STEREO_CURRENT_EYE, mask_sh),\ + SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_EN, mask_sh),\ + SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_V_UPDATE_MODE, mask_sh),\ + SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_STEREO_SEL_OVR, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_MAX, OTG_V_TOTAL_MAX, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_MIN, OTG_V_TOTAL_MIN, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MIN_SEL, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MAX_SEL, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_FORCE_LOCK_ON_EVENT, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_SET_V_TOTAL_MIN_MASK, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_REPLACING_MIN_EN, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_REPLACING_MAX_EN, mask_sh),\ + SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_CLEAR, mask_sh),\ + SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_MODE, mask_sh),\ + SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_OCCURRED, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_SELECT, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_PIPE_SELECT, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_RISING_EDGE_DETECT_CNTL, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_POLARITY_SELECT, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FREQUENCY_SELECT, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_DELAY, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_CLEAR, mask_sh),\ + SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_EVENT_MASK, mask_sh),\ + SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_FRAME_COUNT, mask_sh),\ + SF(OTG0_OTG_STATUS_FRAME_COUNT, OTG_FRAME_COUNT, mask_sh),\ + SF(OTG0_OTG_STATUS, OTG_V_BLANK, mask_sh),\ + SF(OTG0_OTG_STATUS, OTG_V_ACTIVE_DISP, mask_sh),\ + SF(OTG0_OTG_STATUS_POSITION, OTG_HORZ_COUNT, mask_sh),\ + SF(OTG0_OTG_STATUS_POSITION, OTG_VERT_COUNT, mask_sh),\ + SF(OTG0_OTG_NOM_VERT_POSITION, OTG_VERT_COUNT_NOM, mask_sh),\ + SF(OTG0_OTG_M_CONST_DTO0, OTG_M_CONST_DTO_PHASE, mask_sh),\ + SF(OTG0_OTG_M_CONST_DTO1, OTG_M_CONST_DTO_MODULO, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_BUSY, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_EN, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_ON, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_GATE_DIS, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT0_CONTROL, OTG_VERTICAL_INTERRUPT0_INT_ENABLE, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT0_POSITION, OTG_VERTICAL_INTERRUPT0_LINE_START, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT0_POSITION, OTG_VERTICAL_INTERRUPT0_LINE_END, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT1_CONTROL, OTG_VERTICAL_INTERRUPT1_INT_ENABLE, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT1_POSITION, OTG_VERTICAL_INTERRUPT1_LINE_START, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT2_CONTROL, OTG_VERTICAL_INTERRUPT2_INT_ENABLE, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT2_POSITION, OTG_VERTICAL_INTERRUPT2_LINE_START, mask_sh),\ + SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_EN, mask_sh),\ + SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, mask_sh),\ + SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, mask_sh),\ + SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_OCCURRED_STATUS, mask_sh),\ + SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_DOUBLE_BUFFER_PENDING, mask_sh),\ + SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, mask_sh),\ + SF(ODM0_OPTC_RSMU_UNDERFLOW, OPTC_RSMU_UNDERFLOW_OCCURRED_STATUS, mask_sh),\ + SF(ODM0_OPTC_RSMU_UNDERFLOW, OPTC_RSMU_UNDERFLOW_CLEAR, mask_sh),\ + SF(ODM0_OPTC_RSMU_UNDERFLOW, OPTC_RSMU_UNDERFLOW_INT_EN, mask_sh),\ + SF(ODM0_OPTC_RSMU_UNDERFLOW, OPTC_RSMU_UNDERFLOW_INT_STATUS, mask_sh),\ + SF(VTG0_CONTROL, VTG0_ENABLE, mask_sh),\ + SF(VTG0_CONTROL, VTG0_FP2, mask_sh),\ + SF(VTG0_CONTROL, VTG0_VCOUNT_INIT, mask_sh),\ + SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_OCCURRED, mask_sh),\ + SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_CLEAR, mask_sh),\ + SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_AUTO_FORCE_VSYNC_MODE, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL0_EN, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL1_EN, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL2_EN, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_EN, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_FORCE_DELAY, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_CHECK_ALL_FIELDS, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL, OTG_CRC_CONT_EN, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL, OTG_CRC0_SELECT, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL, OTG_CRC_EN, mask_sh),\ + SF(OTG0_OTG_CRC0_DATA_R, CRC0_R_CR, mask_sh),\ + SF(OTG0_OTG_CRC0_DATA_G, CRC0_G_Y, mask_sh),\ + SF(OTG0_OTG_CRC0_DATA_B, CRC0_B_CB, mask_sh),\ + SF(OTG0_OTG_CRC1_DATA_R, CRC1_R_CR, mask_sh),\ + SF(OTG0_OTG_CRC1_DATA_G, CRC1_G_Y, mask_sh),\ + SF(OTG0_OTG_CRC1_DATA_B, CRC1_B_CB, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL, OTG_CRC0_WINDOWA_X_START, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL, OTG_CRC0_WINDOWA_X_END, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL, OTG_CRC0_WINDOWA_Y_START, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL, OTG_CRC0_WINDOWA_Y_END, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL, OTG_CRC0_WINDOWB_X_START, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL, OTG_CRC0_WINDOWB_X_END, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_START, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_END, mask_sh),\ + SF(OTG0_OTG_CRC1_WINDOWA_X_CONTROL, OTG_CRC1_WINDOWA_X_START, mask_sh),\ + SF(OTG0_OTG_CRC1_WINDOWA_X_CONTROL, OTG_CRC1_WINDOWA_X_END, mask_sh),\ + SF(OTG0_OTG_CRC1_WINDOWA_Y_CONTROL, OTG_CRC1_WINDOWA_Y_START, mask_sh),\ + SF(OTG0_OTG_CRC1_WINDOWA_Y_CONTROL, OTG_CRC1_WINDOWA_Y_END, mask_sh),\ + SF(OTG0_OTG_CRC1_WINDOWB_X_CONTROL, OTG_CRC1_WINDOWB_X_START, mask_sh),\ + SF(OTG0_OTG_CRC1_WINDOWB_X_CONTROL, OTG_CRC1_WINDOWB_X_END, mask_sh),\ + SF(OTG0_OTG_CRC1_WINDOWB_Y_CONTROL, OTG_CRC1_WINDOWB_Y_START, mask_sh),\ + SF(OTG0_OTG_CRC1_WINDOWB_Y_CONTROL, OTG_CRC1_WINDOWB_Y_END, mask_sh),\ + SF(OTG0_OTG_TRIGA_MANUAL_TRIG, OTG_TRIGA_MANUAL_TRIG, mask_sh),\ + SF(GSL_SOURCE_SELECT, GSL0_READY_SOURCE_SEL, mask_sh),\ + SF(GSL_SOURCE_SELECT, GSL1_READY_SOURCE_SEL, mask_sh),\ + SF(GSL_SOURCE_SELECT, GSL2_READY_SOURCE_SEL, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL2, MANUAL_FLOW_CONTROL_SEL, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, mask_sh),\ + SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_START_X, mask_sh),\ + SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_END_X, mask_sh), \ + SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_START_Y, mask_sh),\ + SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_END_Y, mask_sh),\ + SF(OTG0_OTG_VUPDATE_KEEPOUT, OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, mask_sh), \ + SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, mask_sh), \ + SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, mask_sh), \ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_MODE, mask_sh), \ + SF(OTG0_OTG_GSL_CONTROL, OTG_MASTER_UPDATE_LOCK_GSL_EN, mask_sh), \ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG0_SRC_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG1_SRC_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG2_SRC_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG3_SRC_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_NUM_OF_INPUT_SEGMENT, mask_sh),\ + SF(ODM0_OPTC_MEMORY_CONFIG, OPTC_MEM_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DATA_FORMAT, mask_sh),\ + SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DSC_MODE, mask_sh),\ + SF(ODM0_OPTC_BYTES_PER_PIXEL, OPTC_DSC_BYTES_PER_PIXEL, mask_sh),\ + SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_DSC_SLICE_WIDTH, mask_sh),\ + SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_SEGMENT_WIDTH, mask_sh),\ + SF(ODM0_OPTC_WIDTH_CONTROL2, OPTC_SEGMENT_WIDTH_LAST, mask_sh),\ + SF(OTG0_OTG_DRR_TRIGGER_WINDOW, OTG_DRR_TRIGGER_WINDOW_START_X, mask_sh),\ + SF(OTG0_OTG_DRR_TRIGGER_WINDOW, OTG_DRR_TRIGGER_WINDOW_END_X, mask_sh),\ + SF(OTG0_OTG_DRR_V_TOTAL_CHANGE, OTG_DRR_V_TOTAL_CHANGE_LIMIT, mask_sh),\ + SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE, mask_sh),\ + SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE_MANUAL, mask_sh),\ + SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_DRR_TIMING_DBUF_UPDATE_MODE, mask_sh),\ + SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_DRR_TIMING_DBUF_UPDATE_PENDING, mask_sh),\ + SF(OTG0_OTG_DRR_CONTROL, OTG_V_TOTAL_LAST_USED_BY_DRR, mask_sh),\ + SF(OTG0_OTG_PSTATE_REGISTER, OTG_PSTATE_KEEPOUT_START, mask_sh),\ + SF(OTG0_OTG_PSTATE_REGISTER, OTG_PSTATE_EXTEND, mask_sh),\ + SF(OTG0_OTG_PSTATE_REGISTER, OTG_UNBLANK, mask_sh),\ + SF(OTG0_OTG_PSTATE_REGISTER, OTG_PSTATE_ALLOW_WIDTH_MIN, mask_sh),\ + SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_FLIP_PENDING, mask_sh),\ + SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_DC_REG_UPDATE_PENDING, mask_sh),\ + SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_CURSOR_UPDATE_PENDING, mask_sh),\ + SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_VUPDATE_KEEPOUT_STATUS, mask_sh),\ + SF(OTG0_OTG_PWA_FRAME_SYNC_CONTROL, OTG_PWA_FRAME_SYNC_EN, mask_sh),\ + SF(OTG0_OTG_PWA_FRAME_SYNC_CONTROL, OTG_PWA_FRAME_SYNC_VCOUNT_MODE, mask_sh),\ + SF(OTG0_OTG_PWA_FRAME_SYNC_CONTROL, OTG_PWA_FRAME_SYNC_LINE, mask_sh),\ + SF(OTG0_INTERRUPT_DEST, OTG0_IHC_OTG_VERTICAL_INTERRUPT2_DEST, mask_sh),\ + SF(OPTC_CLOCK_CONTROL, OPTC_FGCG_REP_DIS, mask_sh) + +void dcn42_timing_generator_init(struct optc *optc1); +void optc42_enable_pwa(struct timing_generator *optc, struct otc_pwa_frame_sync *pwa_sync_param); +void optc42_disable_pwa(struct timing_generator *optc); +void optc42_tg_init(struct timing_generator *optc); +void optc42_clear_optc_underflow(struct timing_generator *optc); +bool optc42_is_optc_underflow_occurred(struct timing_generator *optc); +bool optc42_disable_crtc(struct timing_generator *optc); +void optc42_lock_doublebuffer_enable(struct timing_generator *optc); +#endif /* __DC_OPTC_DCN42_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/pg/Makefile b/drivers/gpu/drm/amd/display/dc/pg/Makefile index ec11d3157a57..56f610cc8406 100644 --- a/drivers/gpu/drm/amd/display/dc/pg/Makefile +++ b/drivers/gpu/drm/amd/display/dc/pg/Makefile @@ -1,5 +1,5 @@ # -# Copyright 2020 Advanced Micro Devices, Inc. +# Copyright 2020, 2026 Advanced Micro Devices, Inc. # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), @@ -32,4 +32,12 @@ PG_DCN35 = dcn35_pg_cntl.o AMD_DAL_PG_DCN35 = $(addprefix $(AMDDALPATH)/dc/pg/dcn35/,$(PG_DCN35)) AMD_DISPLAY_FILES += $(AMD_DAL_PG_DCN35) +############################################################################### +# DCN42 +############################################################################### +PG_DCN42 = dcn42_pg_cntl.o + +AMD_DAL_PG_DCN42 = $(addprefix $(AMDDALPATH)/dc/pg/dcn42/,$(PG_DCN42)) + +AMD_DISPLAY_FILES += $(AMD_DAL_PG_DCN42) endif diff --git a/drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.c b/drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.c new file mode 100644 index 000000000000..96290538a889 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.c @@ -0,0 +1,649 @@ +// SPDX-License-Identifier: MIT + +// Copyright 2026 Advanced Micro Devices, Inc. + +#include "reg_helper.h" +#include "core_types.h" +#include "dcn42_pg_cntl.h" +#include "dccg.h" + +#define TO_DCN_PG_CNTL(pg_cntl)\ + container_of(pg_cntl, struct dcn_pg_cntl, base) + +#define REG(reg) \ + (pg_cntl_dcn->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + pg_cntl_dcn->pg_cntl_shift->field_name, pg_cntl_dcn->pg_cntl_mask->field_name + +#define CTX \ + pg_cntl_dcn->base.ctx +#define DC_LOGGER \ + pg_cntl->ctx->logger + +static bool pg_cntl42_dsc_pg_status(struct pg_cntl *pg_cntl, unsigned int dsc_inst) +{ + struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl); + uint32_t pwr_status = 0; + + if (pg_cntl->ctx->dc->debug.ignore_pg) + return true; + + switch (dsc_inst) { + case 0: /* DSC0 */ + REG_GET(DOMAIN16_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, &pwr_status); + break; + case 1: /* DSC1 */ + REG_GET(DOMAIN17_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, &pwr_status); + break; + case 2: /* DSC2 */ + REG_GET(DOMAIN18_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, &pwr_status); + break; + case 3: /* DSC3 */ + REG_GET(DOMAIN19_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, &pwr_status); + break; + default: + BREAK_TO_DEBUGGER(); + break; + } + + return pwr_status == 0; +} + +void pg_cntl42_dsc_pg_control(struct pg_cntl *pg_cntl, unsigned int dsc_inst, bool power_on) +{ + struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl); + uint32_t power_gate = power_on ? 0 : 1; + uint32_t pwr_status = power_on ? 0 : 2; + uint32_t org_ip_request_cntl = 0; + bool block_enabled; + + /*need to enable dscclk regardless DSC_PG*/ + if (pg_cntl->ctx->dc->res_pool->dccg->funcs->enable_dsc && power_on) + pg_cntl->ctx->dc->res_pool->dccg->funcs->enable_dsc( + pg_cntl->ctx->dc->res_pool->dccg, dsc_inst); + + if (pg_cntl->ctx->dc->debug.ignore_pg || + pg_cntl->ctx->dc->debug.disable_dsc_power_gate || + pg_cntl->ctx->dc->idle_optimizations_allowed) + return; + + block_enabled = pg_cntl42_dsc_pg_status(pg_cntl, dsc_inst); + if (power_on) { + if (block_enabled) + return; + } else { + if (!block_enabled) + return; + } + + REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl); + if (org_ip_request_cntl == 0) + REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); + + if (power_on) { + if (pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg) + pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg, false); + } + switch (dsc_inst) { + case 0: /* DSC0 */ + REG_UPDATE(DOMAIN16_PG_CONFIG, + DOMAIN_POWER_GATE, power_gate); + + REG_WAIT(DOMAIN16_PG_STATUS, + DOMAIN_PGFSM_PWR_STATUS, pwr_status, + 1, 1000); + break; + case 1: /* DSC1 */ + REG_UPDATE(DOMAIN17_PG_CONFIG, + DOMAIN_POWER_GATE, power_gate); + + REG_WAIT(DOMAIN17_PG_STATUS, + DOMAIN_PGFSM_PWR_STATUS, pwr_status, + 1, 1000); + break; + case 2: /* DSC2 */ + REG_UPDATE(DOMAIN18_PG_CONFIG, + DOMAIN_POWER_GATE, power_gate); + + REG_WAIT(DOMAIN18_PG_STATUS, + DOMAIN_PGFSM_PWR_STATUS, pwr_status, + 1, 1000); + break; + case 3: /* DSC3 */ + REG_UPDATE(DOMAIN19_PG_CONFIG, + DOMAIN_POWER_GATE, power_gate); + + REG_WAIT(DOMAIN19_PG_STATUS, + DOMAIN_PGFSM_PWR_STATUS, pwr_status, + 1, 1000); + break; + default: + BREAK_TO_DEBUGGER(); + break; + } + + if (power_on) { + if (pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg) + pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg, true); + } + + if (dsc_inst < MAX_PIPES) + pg_cntl->pg_pipe_res_enable[PG_DSC][dsc_inst] = power_on; + + if (pg_cntl->ctx->dc->res_pool->dccg->funcs->disable_dsc && !power_on) { + /*this is to disable dscclk*/ + pg_cntl->ctx->dc->res_pool->dccg->funcs->disable_dsc( + pg_cntl->ctx->dc->res_pool->dccg, dsc_inst); + } +} + +static bool pg_cntl42_hubp_dpp_pg_status(struct pg_cntl *pg_cntl, unsigned int hubp_dpp_inst) +{ + struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl); + uint32_t pwr_status = 0; + + switch (hubp_dpp_inst) { + case 0: + /* DPP0 & HUBP0 */ + REG_GET(DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, &pwr_status); + break; + case 1: + /* DPP1 & HUBP1 */ + REG_GET(DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, &pwr_status); + break; + case 2: + /* DPP2 & HUBP2 */ + REG_GET(DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, &pwr_status); + break; + case 3: + /* DPP3 & HUBP3 */ + REG_GET(DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, &pwr_status); + break; + default: + BREAK_TO_DEBUGGER(); + break; + } + + return pwr_status == 0; +} + +void pg_cntl42_hubp_dpp_pg_control(struct pg_cntl *pg_cntl, unsigned int hubp_dpp_inst, bool power_on) +{ + struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl); + uint32_t power_gate = power_on ? 0 : 1; + uint32_t pwr_status = power_on ? 0 : 2; + uint32_t org_ip_request_cntl; + bool block_enabled; + bool skip_pg = pg_cntl->ctx->dc->debug.ignore_pg || + pg_cntl->ctx->dc->debug.disable_hubp_power_gate || + pg_cntl->ctx->dc->debug.disable_dpp_power_gate || + pg_cntl->ctx->dc->idle_optimizations_allowed; + + if (skip_pg && !power_on) + return; + + block_enabled = pg_cntl42_hubp_dpp_pg_status(pg_cntl, hubp_dpp_inst); + if (power_on) { + if (block_enabled) + return; + } else { + if (!block_enabled) + return; + } + + REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl); + if (org_ip_request_cntl == 0) + REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); + + if (power_on) { + if (pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg) + pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg, false); + } + + switch (hubp_dpp_inst) { + case 0: + /* DPP0 & HUBP0 */ + REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, power_gate); + REG_WAIT(DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000); + break; + case 1: + /* DPP1 & HUBP1 */ + REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, power_gate); + REG_WAIT(DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000); + break; + case 2: + /* DPP2 & HUBP2 */ + REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, power_gate); + REG_WAIT(DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000); + break; + case 3: + /* DPP3 & HUBP3 */ + REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, power_gate); + REG_WAIT(DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000); + break; + default: + BREAK_TO_DEBUGGER(); + break; + } + + if (power_on) { + if (pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg) + pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg, true); + } + DC_LOG_DEBUG("HUBP DPP instance %d, power %s", hubp_dpp_inst, + power_on ? "ON" : "OFF"); + + if (hubp_dpp_inst < MAX_PIPES) { + pg_cntl->pg_pipe_res_enable[PG_HUBP][hubp_dpp_inst] = power_on; + pg_cntl->pg_pipe_res_enable[PG_DPP][hubp_dpp_inst] = power_on; + } +} + +static bool pg_cntl42_hpo_pg_status(struct pg_cntl *pg_cntl) +{ + struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl); + uint32_t pwr_status = 0; + + REG_GET(DOMAIN25_PG_STATUS, + DOMAIN_PGFSM_PWR_STATUS, &pwr_status); + + return pwr_status == 0; +} + +void pg_cntl42_hpo_pg_control(struct pg_cntl *pg_cntl, bool power_on) +{ + struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl); + uint32_t power_gate = power_on ? 0 : 1; + uint32_t pwr_status = power_on ? 0 : 2; + uint32_t org_ip_request_cntl; + uint32_t power_forceon; + bool block_enabled; + + if (pg_cntl->ctx->dc->debug.ignore_pg || + pg_cntl->ctx->dc->debug.disable_hpo_power_gate || + pg_cntl->ctx->dc->idle_optimizations_allowed) + return; + + block_enabled = pg_cntl42_hpo_pg_status(pg_cntl); + if (power_on) { + if (block_enabled) + return; + } else { + if (!block_enabled) + return; + } + + REG_GET(DOMAIN25_PG_CONFIG, DOMAIN_POWER_FORCEON, &power_forceon); + if (power_forceon) + return; + + REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl); + if (org_ip_request_cntl == 0) + REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); + if (power_on) { + if (pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg) + pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg, false); + } + REG_UPDATE(DOMAIN25_PG_CONFIG, DOMAIN_POWER_GATE, power_gate); + REG_WAIT(DOMAIN25_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000); + + if (power_on) { + if (pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg) + pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg, true); + } + pg_cntl->pg_res_enable[PG_HPO] = power_on; +} + +static bool pg_cntl42_io_clk_status(struct pg_cntl *pg_cntl) +{ + struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl); + uint32_t pwr_status = 0; + + REG_GET(DOMAIN22_PG_STATUS, + DOMAIN_PGFSM_PWR_STATUS, &pwr_status); + + return pwr_status == 0; +} + +void pg_cntl42_io_clk_pg_control(struct pg_cntl *pg_cntl, bool power_on) +{ + struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl); + uint32_t power_gate = power_on ? 0 : 1; + uint32_t pwr_status = power_on ? 0 : 2; + uint32_t org_ip_request_cntl; + uint32_t power_forceon; + bool block_enabled; + + if (pg_cntl->ctx->dc->debug.ignore_pg || + pg_cntl->ctx->dc->idle_optimizations_allowed || + pg_cntl->ctx->dc->debug.disable_io_clk_power_gate) + return; + + block_enabled = pg_cntl42_io_clk_status(pg_cntl); + if (power_on) { + if (block_enabled) + return; + } else { + if (!block_enabled) + return; + } + + REG_GET(DOMAIN22_PG_CONFIG, DOMAIN_POWER_FORCEON, &power_forceon); + if (power_forceon) + return; + + if (!power_on) { + if (!pg_cntl->pg_res_enable[PG_DCCG] || !pg_cntl->pg_res_enable[PG_DCIO] || !pg_cntl->pg_res_enable[PG_DCOH]) + return; + } + REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl); + if (org_ip_request_cntl == 0) + REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); + + /* DCCG, DCOH, DCIO */ + REG_UPDATE(DOMAIN22_PG_CONFIG, DOMAIN_POWER_GATE, power_gate); + REG_WAIT(DOMAIN22_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000); + + pg_cntl->pg_res_enable[PG_DCCG] = power_on; + pg_cntl->pg_res_enable[PG_DCOH] = power_on; + pg_cntl->pg_res_enable[PG_DCIO] = power_on; +} + +static bool pg_cntl42_plane_otg_status(struct pg_cntl *pg_cntl) +{ + struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl); + uint32_t pwr_status = 0; + + REG_GET(DOMAIN24_PG_STATUS, + DOMAIN_PGFSM_PWR_STATUS, &pwr_status); + + return pwr_status == 0; +} + +void pg_cntl42_mpcc_pg_control(struct pg_cntl *pg_cntl, + unsigned int mpcc_inst, bool power_on) +{ + if (pg_cntl->ctx->dc->idle_optimizations_allowed) + return; + + if (mpcc_inst < MAX_PIPES) + pg_cntl->pg_pipe_res_enable[PG_MPCC][mpcc_inst] = power_on; +} + +void pg_cntl42_opp_pg_control(struct pg_cntl *pg_cntl, + unsigned int opp_inst, bool power_on) +{ + if (pg_cntl->ctx->dc->idle_optimizations_allowed) + return; + + if (opp_inst < MAX_PIPES) + pg_cntl->pg_pipe_res_enable[PG_OPP][opp_inst] = power_on; +} + +void pg_cntl42_optc_pg_control(struct pg_cntl *pg_cntl, + unsigned int optc_inst, bool power_on) +{ + // Defer the ONO domain power up/down to plane_otg_pg_control + if (pg_cntl->ctx->dc->idle_optimizations_allowed) + return; + + if (optc_inst < MAX_PIPES) + pg_cntl->pg_pipe_res_enable[PG_OPTC][optc_inst] = power_on; +} +static bool pg_cntl42_mem_status(struct pg_cntl *pg_cntl) +{ + struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl); + uint32_t pwr_status = 0; + + REG_GET(DOMAIN23_PG_STATUS, + DOMAIN_PGFSM_PWR_STATUS, &pwr_status); + + return pwr_status == 0; +} + +void pg_cntl42_mem_pg_control(struct pg_cntl *pg_cntl, bool power_on) +{ + struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl); + uint32_t power_gate = power_on ? 0 : 1; + uint32_t pwr_status = power_on ? 0 : 2; + uint32_t org_ip_request_cntl; + uint32_t power_forceon; + bool block_enabled; + + if (pg_cntl->ctx->dc->debug.ignore_pg || + pg_cntl->ctx->dc->idle_optimizations_allowed || + pg_cntl->ctx->dc->debug.disable_mem_power_gate) + return; + + block_enabled = pg_cntl42_mem_status(pg_cntl); + if (power_on) { + if (block_enabled) + return; + } else { + if (!block_enabled) + return; + } + + REG_GET(DOMAIN23_PG_CONFIG, DOMAIN_POWER_FORCEON, &power_forceon); + if (power_forceon) + return; + + if (!power_on) { + if (!pg_cntl->pg_res_enable[PG_DCHUBBUB] || !pg_cntl->pg_res_enable[PG_DCHVM]) + return; + } + REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl); + if (org_ip_request_cntl == 0) + REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); + + /* DCHUBBUB, DCHUBBUBMEMn, DCHVM */ + REG_UPDATE(DOMAIN23_PG_CONFIG, DOMAIN_POWER_GATE, power_gate); + REG_WAIT(DOMAIN23_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000); + + pg_cntl->pg_res_enable[PG_DCHUBBUB] = power_on; + pg_cntl->pg_res_enable[PG_DCHVM] = power_on; +} +static bool pg_cntl42_dio_pg_status(struct pg_cntl *pg_cntl) +{ + struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl); + uint32_t pwr_status = 0; + + REG_GET(DOMAIN26_PG_STATUS, + DOMAIN_PGFSM_PWR_STATUS, &pwr_status); + + return pwr_status == 0; +} + +void pg_cntl42_dio_pg_control(struct pg_cntl *pg_cntl, bool power_on) +{ + struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl); + uint32_t power_gate = power_on ? 0 : 1; + uint32_t pwr_status = power_on ? 0 : 2; + uint32_t org_ip_request_cntl; + bool block_enabled; + + if (pg_cntl->ctx->dc->debug.ignore_pg || + pg_cntl->ctx->dc->idle_optimizations_allowed || + pg_cntl->ctx->dc->debug.disable_dio_power_gate) + return; + + block_enabled = pg_cntl42_dio_pg_status(pg_cntl); + if (power_on) { + if (block_enabled) + return; + } else { + if (!block_enabled) + return; + } + + REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl); + if (org_ip_request_cntl == 0) + REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); + if (power_on) { + if (pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg) + pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg, false); + } + /* DIO */ + REG_UPDATE(DOMAIN26_PG_CONFIG, DOMAIN_POWER_GATE, power_gate); + REG_WAIT(DOMAIN26_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000); + + if (power_on) { + if (pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg) + pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg, true); + } + pg_cntl->pg_res_enable[PG_DIO] = power_on; + +} + +void pg_cntl42_plane_otg_pg_control(struct pg_cntl *pg_cntl, bool power_on) +{ + struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl); + uint32_t power_gate = power_on ? 0 : 1; + uint32_t pwr_status = power_on ? 0 : 2; + uint32_t org_ip_request_cntl; + int i; + bool block_enabled; + bool all_mpcc_disabled = true, all_opp_disabled = true; + bool all_optc_disabled = true, all_stream_disabled = true; + + if (pg_cntl->ctx->dc->debug.ignore_pg || + pg_cntl->ctx->dc->debug.disable_optc_power_gate || + pg_cntl->ctx->dc->idle_optimizations_allowed) + return; + + block_enabled = pg_cntl42_plane_otg_status(pg_cntl); + if (power_on) { + if (block_enabled) + return; + } else { + if (!block_enabled) + return; + } + + for (i = 0; i < pg_cntl->ctx->dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &pg_cntl->ctx->dc->current_state->res_ctx.pipe_ctx[i]; + + if (pipe_ctx) { + if (pipe_ctx->stream) + all_stream_disabled = false; + } + + if (pg_cntl->pg_pipe_res_enable[PG_MPCC][i]) + all_mpcc_disabled = false; + + if (pg_cntl->pg_pipe_res_enable[PG_OPP][i]) + all_opp_disabled = false; + + if (pg_cntl->pg_pipe_res_enable[PG_OPTC][i]) + all_optc_disabled = false; + } + + if (!power_on) { + if (!all_mpcc_disabled || !all_opp_disabled || !all_optc_disabled + || !all_stream_disabled) + return; + } + + REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl); + if (org_ip_request_cntl == 0) + REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); + + /* MPC, OPP, OPTC, DWB */ + REG_UPDATE(DOMAIN24_PG_CONFIG, DOMAIN_POWER_GATE, power_gate); + REG_WAIT(DOMAIN24_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000); + + for (i = 0; i < pg_cntl->ctx->dc->res_pool->pipe_count; i++) { + pg_cntl->pg_pipe_res_enable[PG_MPCC][i] = power_on; + pg_cntl->pg_pipe_res_enable[PG_OPP][i] = power_on; + pg_cntl->pg_pipe_res_enable[PG_OPTC][i] = power_on; + } +} + + +void pg_cntl42_init_pg_status(struct pg_cntl *pg_cntl) +{ + int i = 0; + bool block_enabled; + + pg_cntl->pg_res_enable[PG_HPO] = pg_cntl42_hpo_pg_status(pg_cntl); + + block_enabled = pg_cntl42_io_clk_status(pg_cntl); + pg_cntl->pg_res_enable[PG_DCCG] = block_enabled; + pg_cntl->pg_res_enable[PG_DCIO] = block_enabled; + pg_cntl->pg_res_enable[PG_DCOH] = block_enabled; + + block_enabled = pg_cntl42_dio_pg_status(pg_cntl); + pg_cntl->pg_res_enable[PG_DIO] = block_enabled; + + block_enabled = pg_cntl42_mem_status(pg_cntl); + pg_cntl->pg_res_enable[PG_DCHUBBUB] = block_enabled; + pg_cntl->pg_res_enable[PG_DCHVM] = block_enabled; + + for (i = 0; i < pg_cntl->ctx->dc->res_pool->pipe_count; i++) { + block_enabled = pg_cntl42_hubp_dpp_pg_status(pg_cntl, i); + pg_cntl->pg_pipe_res_enable[PG_HUBP][i] = block_enabled; + pg_cntl->pg_pipe_res_enable[PG_DPP][i] = block_enabled; + + block_enabled = pg_cntl42_dsc_pg_status(pg_cntl, i); + pg_cntl->pg_pipe_res_enable[PG_DSC][i] = block_enabled; + } + + block_enabled = pg_cntl42_plane_otg_status(pg_cntl); + for (i = 0; i < pg_cntl->ctx->dc->res_pool->pipe_count; i++) { + pg_cntl->pg_pipe_res_enable[PG_MPCC][i] = block_enabled; + pg_cntl->pg_pipe_res_enable[PG_OPP][i] = block_enabled; + pg_cntl->pg_pipe_res_enable[PG_OPTC][i] = block_enabled; + } +} + +static const struct pg_cntl_funcs pg_cntl42_funcs = { + .init_pg_status = pg_cntl42_init_pg_status, + .dsc_pg_control = pg_cntl42_dsc_pg_control, + .hubp_dpp_pg_control = pg_cntl42_hubp_dpp_pg_control, + .hpo_pg_control = pg_cntl42_hpo_pg_control, + .io_clk_pg_control = pg_cntl42_io_clk_pg_control, + .plane_otg_pg_control = pg_cntl42_plane_otg_pg_control, + .mpcc_pg_control = pg_cntl42_mpcc_pg_control, + .opp_pg_control = pg_cntl42_opp_pg_control, + .optc_pg_control = pg_cntl42_optc_pg_control, + .mem_pg_control = pg_cntl42_mem_pg_control, + .dio_pg_control = pg_cntl42_dio_pg_control +}; + +struct pg_cntl *pg_cntl42_create( + struct dc_context *ctx, + const struct pg_cntl_registers *regs, + const struct pg_cntl_shift *pg_cntl_shift, + const struct pg_cntl_mask *pg_cntl_mask) +{ + struct dcn_pg_cntl *pg_cntl_dcn = kzalloc(sizeof(*pg_cntl_dcn), GFP_KERNEL); + struct pg_cntl *base; + + if (pg_cntl_dcn == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + base = &pg_cntl_dcn->base; + base->ctx = ctx; + base->funcs = &pg_cntl42_funcs; + + pg_cntl_dcn->regs = regs; + pg_cntl_dcn->pg_cntl_shift = pg_cntl_shift; + pg_cntl_dcn->pg_cntl_mask = pg_cntl_mask; + + memset(base->pg_pipe_res_enable, 0, PG_HW_PIPE_RESOURCES_NUM_ELEMENT * MAX_PIPES * sizeof(bool)); + memset(base->pg_res_enable, 0, PG_HW_RESOURCES_NUM_ELEMENT * sizeof(bool)); + + return &pg_cntl_dcn->base; +} + +void dcn42_pg_cntl_destroy(struct pg_cntl **pg_cntl) +{ + struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(*pg_cntl); + + kfree(pg_cntl_dcn); + *pg_cntl = NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.h b/drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.h new file mode 100644 index 000000000000..a0aa14a796f4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.h @@ -0,0 +1,175 @@ +/* SPDX-License-Identifier: MIT */ + +/* Copyright 2026 Advanced Micro Devices, Inc.*/ + +#ifndef __DCN42_PG_CNTL_H__ +#define __DCN42_PG_CNTL_H__ + +#include "pg_cntl.h" + +#define PG_CNTL_REG_LIST_DCN42()\ + SR(DOMAIN0_PG_CONFIG), \ + SR(DOMAIN1_PG_CONFIG), \ + SR(DOMAIN2_PG_CONFIG), \ + SR(DOMAIN3_PG_CONFIG), \ + SR(DOMAIN16_PG_CONFIG), \ + SR(DOMAIN17_PG_CONFIG), \ + SR(DOMAIN18_PG_CONFIG), \ + SR(DOMAIN19_PG_CONFIG), \ + SR(DOMAIN22_PG_CONFIG), \ + SR(DOMAIN23_PG_CONFIG), \ + SR(DOMAIN24_PG_CONFIG), \ + SR(DOMAIN25_PG_CONFIG), \ + SR(DOMAIN26_PG_CONFIG), \ + SR(DOMAIN0_PG_STATUS), \ + SR(DOMAIN1_PG_STATUS), \ + SR(DOMAIN2_PG_STATUS), \ + SR(DOMAIN3_PG_STATUS), \ + SR(DOMAIN16_PG_STATUS), \ + SR(DOMAIN17_PG_STATUS), \ + SR(DOMAIN18_PG_STATUS), \ + SR(DOMAIN19_PG_STATUS), \ + SR(DOMAIN22_PG_STATUS), \ + SR(DOMAIN23_PG_STATUS), \ + SR(DOMAIN24_PG_STATUS), \ + SR(DOMAIN25_PG_STATUS), \ + SR(DOMAIN26_PG_STATUS), \ + SR(DC_IP_REQUEST_CNTL) + +#define PG_CNTL_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define PG_CNTL_MASK_SH_LIST_DCN42(mask_sh) \ + PG_CNTL_SF(DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + PG_CNTL_SF(DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + PG_CNTL_SF(DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + PG_CNTL_SF(DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + PG_CNTL_SF(DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + PG_CNTL_SF(DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + PG_CNTL_SF(DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + PG_CNTL_SF(DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + PG_CNTL_SF(DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + PG_CNTL_SF(DOMAIN16_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + PG_CNTL_SF(DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + PG_CNTL_SF(DOMAIN17_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + PG_CNTL_SF(DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + PG_CNTL_SF(DOMAIN18_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + PG_CNTL_SF(DOMAIN19_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + PG_CNTL_SF(DOMAIN19_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + PG_CNTL_SF(DOMAIN22_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + PG_CNTL_SF(DOMAIN22_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + PG_CNTL_SF(DOMAIN23_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + PG_CNTL_SF(DOMAIN23_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + PG_CNTL_SF(DOMAIN24_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + PG_CNTL_SF(DOMAIN24_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + PG_CNTL_SF(DOMAIN25_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + PG_CNTL_SF(DOMAIN25_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + PG_CNTL_SF(DOMAIN26_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + PG_CNTL_SF(DOMAIN26_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + PG_CNTL_SF(DOMAIN0_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \ + PG_CNTL_SF(DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + PG_CNTL_SF(DOMAIN1_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \ + PG_CNTL_SF(DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + PG_CNTL_SF(DOMAIN2_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \ + PG_CNTL_SF(DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + PG_CNTL_SF(DOMAIN3_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \ + PG_CNTL_SF(DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + PG_CNTL_SF(DOMAIN16_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \ + PG_CNTL_SF(DOMAIN16_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + PG_CNTL_SF(DOMAIN17_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \ + PG_CNTL_SF(DOMAIN17_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + PG_CNTL_SF(DOMAIN18_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \ + PG_CNTL_SF(DOMAIN18_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + PG_CNTL_SF(DOMAIN19_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \ + PG_CNTL_SF(DOMAIN19_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + PG_CNTL_SF(DOMAIN22_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \ + PG_CNTL_SF(DOMAIN22_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + PG_CNTL_SF(DOMAIN23_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \ + PG_CNTL_SF(DOMAIN23_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + PG_CNTL_SF(DOMAIN24_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \ + PG_CNTL_SF(DOMAIN24_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + PG_CNTL_SF(DOMAIN25_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \ + PG_CNTL_SF(DOMAIN25_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + PG_CNTL_SF(DOMAIN26_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \ + PG_CNTL_SF(DOMAIN26_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + PG_CNTL_SF(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh) + +struct pg_cntl_shift { + uint8_t IP_REQUEST_EN; + uint8_t DOMAIN_POWER_FORCEON; + uint8_t DOMAIN_POWER_GATE; + uint8_t DOMAIN_DESIRED_PWR_STATE; + uint8_t DOMAIN_PGFSM_PWR_STATUS; +}; +struct pg_cntl_mask { + uint32_t IP_REQUEST_EN; + uint32_t DOMAIN_POWER_FORCEON; + uint32_t DOMAIN_POWER_GATE; + uint32_t DOMAIN_DESIRED_PWR_STATE; + uint32_t DOMAIN_PGFSM_PWR_STATUS; +}; + +struct pg_cntl_registers { + uint32_t LONO_STATE; + uint32_t DC_IP_REQUEST_CNTL; + uint32_t DOMAIN0_PG_CONFIG; + uint32_t DOMAIN1_PG_CONFIG; + uint32_t DOMAIN2_PG_CONFIG; + uint32_t DOMAIN3_PG_CONFIG; + uint32_t DOMAIN16_PG_CONFIG; + uint32_t DOMAIN17_PG_CONFIG; + uint32_t DOMAIN18_PG_CONFIG; + uint32_t DOMAIN19_PG_CONFIG; + uint32_t DOMAIN22_PG_CONFIG; + uint32_t DOMAIN23_PG_CONFIG; + uint32_t DOMAIN24_PG_CONFIG; + uint32_t DOMAIN25_PG_CONFIG; + uint32_t DOMAIN26_PG_CONFIG; + uint32_t DOMAIN0_PG_STATUS; + uint32_t DOMAIN1_PG_STATUS; + uint32_t DOMAIN2_PG_STATUS; + uint32_t DOMAIN3_PG_STATUS; + uint32_t DOMAIN16_PG_STATUS; + uint32_t DOMAIN17_PG_STATUS; + uint32_t DOMAIN18_PG_STATUS; + uint32_t DOMAIN19_PG_STATUS; + uint32_t DOMAIN22_PG_STATUS; + uint32_t DOMAIN23_PG_STATUS; + uint32_t DOMAIN24_PG_STATUS; + uint32_t DOMAIN25_PG_STATUS; + uint32_t DOMAIN26_PG_STATUS; +}; + +struct dcn_pg_cntl { + struct pg_cntl base; + const struct pg_cntl_registers *regs; + const struct pg_cntl_shift *pg_cntl_shift; + const struct pg_cntl_mask *pg_cntl_mask; +}; + +void pg_cntl42_dsc_pg_control(struct pg_cntl *pg_cntl, unsigned int dsc_inst, bool power_on); +void pg_cntl42_hubp_dpp_pg_control(struct pg_cntl *pg_cntl, + unsigned int hubp_dpp_inst, bool power_on); +void pg_cntl42_hpo_pg_control(struct pg_cntl *pg_cntl, bool power_on); +void pg_cntl42_io_clk_pg_control(struct pg_cntl *pg_cntl, bool power_on); +void pg_cntl42_plane_otg_pg_control(struct pg_cntl *pg_cntl, bool power_on); +void pg_cntl42_mpcc_pg_control(struct pg_cntl *pg_cntl, + unsigned int mpcc_inst, bool power_on); +void pg_cntl42_opp_pg_control(struct pg_cntl *pg_cntl, + unsigned int opp_inst, bool power_on); +void pg_cntl42_optc_pg_control(struct pg_cntl *pg_cntl, + unsigned int optc_inst, bool power_on); +void pg_cntl42_mem_pg_control(struct pg_cntl *pg_cntl, bool power_on); +void pg_cntl42_dio_pg_control(struct pg_cntl *pg_cntl, bool power_on); +void dcn42_pg_cntl_destroy(struct pg_cntl **pg_cntl); +void pg_cntl42_init_pg_status(struct pg_cntl *pg_cntl); + +struct pg_cntl *pg_cntl42_create( + struct dc_context *ctx, + const struct pg_cntl_registers *regs, + const struct pg_cntl_shift *pg_cntl_shift, + const struct pg_cntl_mask *pg_cntl_mask); + +void dcn_pg_cntl_destroy(struct pg_cntl **pg_cntl); + +#endif /* DCN42_PG_CNTL */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/Makefile b/drivers/gpu/drm/amd/display/dc/resource/Makefile index 5b42da8b79c2..1a17a885fe84 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/Makefile +++ b/drivers/gpu/drm/amd/display/dc/resource/Makefile @@ -222,4 +222,22 @@ AMD_DAL_RESOURCE_DCN401 = $(addprefix $(AMDDALPATH)/dc/resource/dcn401/,$(RESOUR AMD_DISPLAY_FILES += $(AMD_DAL_RESOURCE_DCN401) +############################################################################### +# DCN42 +############################################################################### +RESOURCE_DCN42 = dcn42_resource.o dcn42_resource_fpu.o + +AMD_DAL_RESOURCE_DCN42 = $(addprefix $(AMDDALPATH)/dc/resource/dcn42/,$(RESOURCE_DCN42)) + +AMD_DISPLAY_FILES += $(AMD_DAL_RESOURCE_DCN42) + +# FPU Compile Flags for FPU files +resource_ccflags := $(CC_FLAGS_FPU) +resource_rcflags := $(CC_FLAGS_NO_FPU) + +CFLAGS_$(AMDDALPATH)/dc/resource/dcn42/dcn42_resource_fpu.o := $(resource_ccflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/resource/dcn42/dcn42_resource_fpu.o := $(resource_rcflags) + +############################################################################### endif + diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c index fdcf8db6be50..caafebe92129 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c @@ -632,6 +632,7 @@ static struct link_encoder *dce100_link_encoder_create( struct dc_context *ctx, const struct encoder_init_data *enc_init_data) { + (void)ctx; struct dce110_link_encoder *enc110 = kzalloc_obj(struct dce110_link_encoder); int link_regs_id; @@ -849,6 +850,7 @@ static enum dc_status build_mapped_resource( struct dc_state *context, struct dc_stream_state *stream) { + (void)dc; struct pipe_ctx *pipe_ctx = resource_get_otg_master_for_stream(&context->res_ctx, stream); if (!pipe_ctx) @@ -866,6 +868,7 @@ enum dc_status dce100_validate_bandwidth( struct dc_state *context, enum dc_validate_mode validate_mode) { + (void)validate_mode; int i; bool at_least_one_pipe = false; struct dc_stream_state *stream = NULL; @@ -926,6 +929,7 @@ enum dc_status dce100_validate_global( struct dc *dc, struct dc_state *context) { + (void)dc; if (!dce100_validate_surface_sets(context)) return DC_FAIL_SURFACE_VALIDATE; @@ -961,6 +965,7 @@ static void dce100_destroy_resource_pool(struct resource_pool **pool) enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state, struct dc_caps *caps) { + (void)caps; if (plane_state->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return DC_OK; @@ -1039,7 +1044,7 @@ static bool dce100_resource_construct( pool->base.res_cap = &res_cap; pool->base.funcs = &dce100_res_pool_funcs; - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE; bp = ctx->dc_bios; @@ -1111,7 +1116,7 @@ static bool dce100_resource_construct( /************************************************* * Resource + asic cap harcoding * *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE; pool->base.pipe_count = res_cap.num_timing_generator; pool->base.timing_generator_count = pool->base.res_cap->num_timing_generator; dc->caps.max_downscale_ratio = 200; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.c index ab71f645c90e..f83acfe7a15e 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.c @@ -667,6 +667,7 @@ static struct link_encoder *dce110_link_encoder_create( struct dc_context *ctx, const struct encoder_init_data *enc_init_data) { + (void)ctx; struct dce110_link_encoder *enc110 = kzalloc_obj(struct dce110_link_encoder); int link_regs_id; @@ -971,6 +972,7 @@ static enum dc_status dce110_validate_bandwidth( struct dc_state *context, enum dc_validate_mode validate_mode) { + (void)validate_mode; bool result = false; DC_LOG_BANDWIDTH_CALCS( @@ -1043,6 +1045,7 @@ static enum dc_status dce110_validate_bandwidth( static enum dc_status dce110_validate_plane(const struct dc_plane_state *plane_state, struct dc_caps *caps) { + (void)caps; if (((plane_state->dst_rect.width * 2) < plane_state->src_rect.width) || ((plane_state->dst_rect.height * 2) < plane_state->src_rect.height)) return DC_FAIL_SURFACE_VALIDATE; @@ -1099,6 +1102,7 @@ static enum dc_status dce110_validate_global( struct dc *dc, struct dc_state *context) { + (void)dc; if (!dce110_validate_surface_sets(context)) return DC_FAIL_SURFACE_VALIDATE; @@ -1130,6 +1134,7 @@ static struct pipe_ctx *dce110_acquire_underlay( const struct resource_pool *pool, const struct pipe_ctx *opp_head_pipe) { + (void)cur_ctx; struct dc_stream_state *stream = opp_head_pipe->stream; struct dc *dc = stream->ctx->dc; struct dce_hwseq *hws = dc->hwseq; @@ -1354,6 +1359,7 @@ static bool dce110_resource_construct( struct dce110_resource_pool *pool, struct hw_asic_id asic_id) { + (void)asic_id; unsigned int i; struct dc_context *ctx = dc->ctx; struct dc_bios *bp; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c index b7051bfd4326..458b14e4cb97 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c @@ -628,6 +628,7 @@ static struct link_encoder *dce112_link_encoder_create( struct dc_context *ctx, const struct encoder_init_data *enc_init_data) { + (void)ctx; struct dce110_link_encoder *enc110 = kzalloc_obj(struct dce110_link_encoder); int link_regs_id; @@ -852,6 +853,7 @@ static struct clock_source *find_matching_pll( const struct resource_pool *pool, const struct dc_stream_state *const stream) { + (void)res_ctx; switch (stream->link->link_enc->transmitter) { case TRANSMITTER_UNIPHY_A: return pool->clock_sources[DCE112_CLK_SRC_PLL0]; @@ -875,6 +877,7 @@ static enum dc_status build_mapped_resource( struct dc_state *context, struct dc_stream_state *stream) { + (void)dc; struct pipe_ctx *pipe_ctx = resource_get_otg_master_for_stream(&context->res_ctx, stream); if (!pipe_ctx) @@ -892,6 +895,7 @@ enum dc_status dce112_validate_bandwidth( struct dc_state *context, enum dc_validate_mode validate_mode) { + (void)validate_mode; bool result = false; DC_LOG_BANDWIDTH_CALCS( @@ -1037,6 +1041,7 @@ static enum dc_status dce112_validate_global( struct dc *dc, struct dc_state *context) { + (void)dc; if (!dce112_validate_surface_sets(context)) return DC_FAIL_SURFACE_VALIDATE; @@ -1240,7 +1245,7 @@ static bool dce112_resource_construct( /************************************************* * Resource + asic cap harcoding * *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE; pool->base.pipe_count = pool->base.res_cap->num_timing_generator; pool->base.timing_generator_count = pool->base.res_cap->num_timing_generator; dc->caps.max_downscale_ratio = 200; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce120/dce120_resource.c index 7ee70f7b3aa7..56bbf9dc1691 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dce120/dce120_resource.c @@ -712,6 +712,7 @@ static struct link_encoder *dce120_link_encoder_create( struct dc_context *ctx, const struct encoder_init_data *enc_init_data) { + (void)ctx; struct dce110_link_encoder *enc110 = kzalloc_obj(struct dce110_link_encoder); int link_regs_id; @@ -1081,7 +1082,7 @@ static bool dce120_resource_construct( /* TODO: Fill more data from GreenlandAsicCapability.cpp */ pool->base.pipe_count = res_cap.num_timing_generator; pool->base.timing_generator_count = pool->base.res_cap->num_timing_generator; - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE; dc->caps.max_downscale_ratio = 200; dc->caps.i2c_speed_in_khz = 100; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c index 3d52973dd7f2..6a25dcfcdf17 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c @@ -497,7 +497,7 @@ static void read_dce_straps( static struct audio *create_audio( struct dc_context *ctx, unsigned int inst) { - return dce60_audio_create(ctx, inst, + return dce_audio_create(ctx, inst, &audio_regs[inst], &audio_shift, &audio_mask); } diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c index 89927727a0d9..33be49b3c1b1 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c @@ -734,6 +734,7 @@ static struct link_encoder *dce80_link_encoder_create( struct dc_context *ctx, const struct encoder_init_data *enc_init_data) { + (void)ctx; struct dce110_link_encoder *enc110 = kzalloc_obj(struct dce110_link_encoder); int link_regs_id; @@ -934,7 +935,7 @@ static bool dce80_construct( /************************************************* * Resource + asic cap harcoding * *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE; pool->base.pipe_count = res_cap.num_timing_generator; pool->base.timing_generator_count = res_cap.num_timing_generator; dc->caps.max_downscale_ratio = 200; @@ -1137,7 +1138,7 @@ static bool dce81_construct( /************************************************* * Resource + asic cap harcoding * *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE; pool->base.pipe_count = res_cap_81.num_timing_generator; pool->base.timing_generator_count = res_cap_81.num_timing_generator; dc->caps.max_downscale_ratio = 200; @@ -1337,7 +1338,7 @@ static bool dce83_construct( /************************************************* * Resource + asic cap harcoding * *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE; pool->base.pipe_count = res_cap_83.num_timing_generator; pool->base.timing_generator_count = res_cap_83.num_timing_generator; dc->caps.max_downscale_ratio = 200; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c index 4663456a736a..0fdebe63d355 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c @@ -764,6 +764,7 @@ static struct link_encoder *dcn10_link_encoder_create( struct dc_context *ctx, const struct encoder_init_data *enc_init_data) { + (void)ctx; struct dcn10_link_encoder *enc10 = kzalloc_obj(struct dcn10_link_encoder); int link_regs_id; @@ -1082,6 +1083,7 @@ static enum dc_status build_mapped_resource( struct dc_state *context, struct dc_stream_state *stream) { + (void)dc; struct pipe_ctx *pipe_ctx = resource_get_otg_master_for_stream(&context->res_ctx, stream); if (!pipe_ctx) @@ -1116,6 +1118,7 @@ static struct pipe_ctx *dcn10_acquire_free_pipe_for_layer( const struct resource_pool *pool, const struct pipe_ctx *opp_head_pipe) { + (void)cur_ctx; struct resource_context *res_ctx = &new_ctx->res_ctx; struct pipe_ctx *head_pipe = resource_get_otg_master_for_stream(res_ctx, opp_head_pipe->stream); struct pipe_ctx *idle_pipe = resource_find_free_secondary_pipe_legacy(res_ctx, pool, head_pipe); @@ -1306,6 +1309,12 @@ static const struct dc_cap_funcs cap_funcs = { .get_dcc_compression_cap = dcn10_get_dcc_compression_cap }; +void dcn10_get_default_tiling_info(struct dc_tiling_info *tiling_info) +{ + tiling_info->gfxversion = DcGfxVersion9; + tiling_info->gfx9.swizzle = DC_SW_LINEAR; +} + static const struct resource_funcs dcn10_res_pool_funcs = { .destroy = dcn10_destroy_resource_pool, .link_enc_create = dcn10_link_encoder_create, @@ -1317,7 +1326,8 @@ static const struct resource_funcs dcn10_res_pool_funcs = { .add_stream_to_ctx = dcn10_add_stream_to_ctx, .patch_unknown_plane_state = dcn10_patch_unknown_plane_state, .find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link, - .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe + .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe, + .get_default_tiling_info = dcn10_get_default_tiling_info }; static uint32_t read_pipe_fuses(struct dc_context *ctx) @@ -1372,7 +1382,7 @@ static bool dcn10_resource_construct( /************************************************* * Resource + asic cap harcoding * *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE; /* max pipe num for ASIC before check pipe fuses */ pool->base.pipe_count = pool->base.res_cap->num_timing_generator; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.h index 7bc1be53e800..c7409298caa9 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.h +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.h @@ -53,5 +53,7 @@ struct stream_encoder *dcn10_find_first_free_match_stream_enc_for_link( unsigned int dcn10_get_vstartup_for_pipe(struct pipe_ctx *pipe_ctx); +void dcn10_get_default_tiling_info(struct dc_tiling_info *tiling_info); + #endif /* __DC_RESOURCE_DCN10_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c index 74e8d229c9dd..a99829f23965 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c @@ -944,6 +944,7 @@ struct link_encoder *dcn20_link_encoder_create( struct dc_context *ctx, const struct encoder_init_data *enc_init_data) { + (void)ctx; struct dcn20_link_encoder *enc20 = kzalloc_obj(struct dcn20_link_encoder); int link_regs_id; @@ -1344,6 +1345,7 @@ static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx) enum dc_status dcn20_build_mapped_resource(const struct dc *dc, struct dc_state *context, struct dc_stream_state *stream) { + (void)dc; enum dc_status status = DC_OK; struct pipe_ctx *pipe_ctx = resource_get_otg_master_for_stream(&context->res_ctx, stream); @@ -1571,6 +1573,7 @@ void dcn20_split_stream_for_mpc( struct pipe_ctx *primary_pipe, struct pipe_ctx *secondary_pipe) { + (void)res_ctx; int pipe_idx = secondary_pipe->pipe_idx; struct pipe_ctx *sec_bot_pipe = secondary_pipe->bottom_pipe; @@ -1716,6 +1719,7 @@ struct pipe_ctx *dcn20_find_secondary_pipe(struct dc *dc, const struct resource_pool *pool, const struct pipe_ctx *primary_pipe) { + (void)pool; struct pipe_ctx *secondary_pipe = NULL; if (dc && primary_pipe) { @@ -1848,6 +1852,11 @@ void dcn20_merge_pipes_for_validate( } } +static bool is_dual_plane(enum surface_pixel_format format) +{ + return format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN || format == SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA; +} + int dcn20_validate_apply_pipe_split_flags( struct dc *dc, struct dc_state *context, @@ -1932,8 +1941,15 @@ int dcn20_validate_apply_pipe_split_flags( for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; int pipe_plane = v->pipe_plane[pipe_idx]; - bool split4mpc = context->stream_count == 1 && plane_count == 1 - && dc->config.enable_4to1MPC && dc->res_pool->pipe_count >= 4; + bool split4mpc = false; + + if (context->stream_count == 1 && plane_count == 1 + && dc->config.allow_4to1MPC && dc->res_pool->pipe_count >= 4 + && !dc->debug.disable_z9_mpc + && pipe->plane_state && is_dual_plane(pipe->plane_state->format) + && pipe->plane_state->src_rect.width <= 1920 + && pipe->plane_state->src_rect.height <= 1080) + split4mpc = true; if (!context->res_ctx.pipe_ctx[i].stream) continue; @@ -2183,6 +2199,7 @@ struct pipe_ctx *dcn20_acquire_free_pipe_for_layer( const struct resource_pool *pool, const struct pipe_ctx *opp_head) { + (void)cur_ctx; struct resource_context *res_ctx = &new_ctx->res_ctx; struct pipe_ctx *otg_master = resource_get_otg_master_for_stream(res_ctx, opp_head->stream); struct pipe_ctx *sec_dpp_pipe = resource_find_free_secondary_pipe_legacy(res_ctx, pool, otg_master); @@ -2266,7 +2283,8 @@ static const struct resource_funcs dcn20_res_pool_funcs = { .set_mcif_arb_params = dcn20_set_mcif_arb_params, .populate_dml_pipes = dcn20_populate_dml_pipes_from_context, .find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link, - .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe + .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe, + .get_default_tiling_info = dcn10_get_default_tiling_info }; bool dcn20_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) @@ -2364,6 +2382,7 @@ static struct _vcs_dpi_ip_params_st *get_asic_rev_ip_params( static enum dml_project get_dml_project_version(uint32_t hw_internal_rev) { + (void)hw_internal_rev; return DML_PROJECT_NAVI10v2; } @@ -2375,8 +2394,6 @@ static bool init_soc_bounding_box(struct dc *dc, struct _vcs_dpi_ip_params_st *loaded_ip = get_asic_rev_ip_params(dc->ctx->asic_id.hw_internal_rev); - DC_LOGGER_INIT(dc->ctx->logger); - if (pool->base.pp_smu) { struct pp_smu_nv_clock_table max_clocks = {0}; unsigned int uclk_states[8] = {0}; @@ -2452,7 +2469,7 @@ static bool dcn20_resource_construct( /************************************************* * Resource + asic cap harcoding * *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE; dc->caps.max_downscale_ratio = 200; dc->caps.i2c_speed_in_khz = 100; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c index e289be70efb5..02b7dc07ad53 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c @@ -1114,7 +1114,8 @@ static struct resource_funcs dcn201_res_pool_funcs = { .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, .set_mcif_arb_params = dcn20_set_mcif_arb_params, .find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link, - .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe + .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe, + .get_default_tiling_info = dcn10_get_default_tiling_info }; static bool dcn201_resource_construct( diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c index 4333baac96ad..54ebf8cf607f 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c @@ -798,7 +798,8 @@ bool dcn21_fast_validate_bw(struct dc *dc, int *pipe_cnt_out, int *pipe_split_from, int *vlevel_out, - enum dc_validate_mode validate_mode) + enum dc_validate_mode validate_mode, + bool allow_self_refresh_only) { bool out = false; int split[MAX_PIPES] = { 0 }; @@ -829,18 +830,23 @@ bool dcn21_fast_validate_bw(struct dc *dc, vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt); if (vlevel > context->bw_ctx.dml.soc.num_states) { - /* - * If mode is unsupported or there's still no p-state support then - * fall back to favoring voltage. - * - * We don't actually support prefetch mode 2, so require that we - * at least support prefetch mode 1. - */ - context->bw_ctx.dml.soc.allow_dram_self_refresh_or_dram_clock_change_in_vblank = - dm_allow_self_refresh; - vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt); - if (vlevel > context->bw_ctx.dml.soc.num_states) + + if (allow_self_refresh_only) { + /* + * If mode is unsupported or there's still no p-state support then + * fall back to favoring voltage. + * + * We don't actually support prefetch mode 2, so require that we + * at least support prefetch mode 1. + */ + context->bw_ctx.dml.soc.allow_dram_self_refresh_or_dram_clock_change_in_vblank = + dm_allow_self_refresh; + vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt); + if (vlevel > context->bw_ctx.dml.soc.num_states) + goto validate_fail; + } else { goto validate_fail; + } } vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, vlevel, split, merge); @@ -1319,6 +1325,7 @@ static struct link_encoder *dcn21_link_encoder_create( struct dc_context *ctx, const struct encoder_init_data *enc_init_data) { + (void)ctx; struct dcn21_link_encoder *enc21 = kzalloc_obj(struct dcn21_link_encoder); int link_regs_id; @@ -1404,7 +1411,8 @@ static const struct resource_funcs dcn21_res_pool_funcs = { .find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link, .update_bw_bounding_box = dcn21_update_bw_bounding_box, .get_panel_config_defaults = dcn21_get_panel_config_defaults, - .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe + .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe, + .get_default_tiling_info = dcn10_get_default_tiling_info }; static bool dcn21_resource_construct( @@ -1427,7 +1435,7 @@ static bool dcn21_resource_construct( /************************************************* * Resource + asic cap harcoding * *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE; /* max pipe num for ASIC before check pipe fuses */ pool->base.pipe_count = pool->base.res_cap->num_timing_generator; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.h index a017fd9854d1..23d3a36872bb 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.h +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.h @@ -51,6 +51,7 @@ bool dcn21_fast_validate_bw( int *pipe_cnt_out, int *pipe_split_from, int *vlevel_out, - enum dc_validate_mode validate_mode); + enum dc_validate_mode validate_mode, + bool allow_self_refresh_only); #endif /* _DCN21_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c index 87b7b4ee04c6..4a864689c44f 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c @@ -952,6 +952,7 @@ static struct link_encoder *dcn30_link_encoder_create( struct dc_context *ctx, const struct encoder_init_data *enc_init_data) { + (void)ctx; struct dcn20_link_encoder *enc20 = kzalloc_obj(struct dcn20_link_encoder); @@ -1675,6 +1676,8 @@ noinline bool dcn30_internal_validate_bw( if (!pipes) return false; + dcn20_merge_pipes_for_validate(dc, context); + context->bw_ctx.dml.vba.maxMpcComb = 0; context->bw_ctx.dml.vba.VoltageLevel = 0; context->bw_ctx.dml.vba.DRAMClockChangeSupport[0][0] = dm_dram_clock_change_vactive; @@ -2282,7 +2285,8 @@ static const struct resource_funcs dcn30_res_pool_funcs = { .update_bw_bounding_box = dcn30_update_bw_bounding_box, .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, .get_panel_config_defaults = dcn30_get_panel_config_defaults, - .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe + .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe, + .get_default_tiling_info = dcn10_get_default_tiling_info }; #define CTX ctx @@ -2328,7 +2332,7 @@ static bool dcn30_resource_construct( /************************************************* * Resource + asic cap harcoding * *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE; pool->base.pipe_count = pool->base.res_cap->num_timing_generator; pool->base.mpcc_count = pool->base.res_cap->num_timing_generator; dc->caps.max_downscale_ratio = 600; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.c index 6bb1c62124bb..a74b150cbe9c 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.c @@ -908,6 +908,7 @@ static struct link_encoder *dcn301_link_encoder_create( struct dc_context *ctx, const struct encoder_init_data *enc_init_data) { + (void)ctx; struct dcn20_link_encoder *enc20 = kzalloc_obj(struct dcn20_link_encoder); @@ -1434,7 +1435,8 @@ static struct resource_funcs dcn301_res_pool_funcs = { .release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut, .update_bw_bounding_box = dcn301_update_bw_bounding_box, .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, - .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe + .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe, + .get_default_tiling_info = dcn10_get_default_tiling_info, }; static bool dcn301_resource_construct( @@ -1461,7 +1463,7 @@ static bool dcn301_resource_construct( /************************************************* * Resource + asic cap harcoding * *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE; pool->base.pipe_count = pool->base.res_cap->num_timing_generator; pool->base.mpcc_count = pool->base.res_cap->num_timing_generator; dc->caps.max_downscale_ratio = 600; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c index d02aafd06fd4..539c5aa6bffa 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c @@ -922,6 +922,7 @@ static struct link_encoder *dcn302_link_encoder_create( struct dc_context *ctx, const struct encoder_init_data *enc_init_data) { + (void)ctx; struct dcn20_link_encoder *enc20 = kzalloc_obj(struct dcn20_link_encoder); if (!enc20 || enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs)) @@ -1188,7 +1189,8 @@ static struct resource_funcs dcn302_res_pool_funcs = { .update_bw_bounding_box = dcn302_update_bw_bounding_box, .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, .get_panel_config_defaults = dcn302_get_panel_config_defaults, - .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe + .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe, + .get_default_tiling_info = dcn10_get_default_tiling_info }; static struct dc_cap_funcs cap_funcs = { @@ -1250,7 +1252,7 @@ static bool dcn302_resource_construct( /************************************************* * Resource + asic cap harcoding * *************************************************/ - pool->underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE; pool->pipe_count = pool->res_cap->num_timing_generator; pool->mpcc_count = pool->res_cap->num_timing_generator; dc->caps.max_downscale_ratio = 600; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c index 30b1403112c6..529eccb4ed3b 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c @@ -867,6 +867,7 @@ static struct link_encoder *dcn303_link_encoder_create( struct dc_context *ctx, const struct encoder_init_data *enc_init_data) { + (void)ctx; struct dcn20_link_encoder *enc20 = kzalloc_obj(struct dcn20_link_encoder); if (!enc20 || enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs)) @@ -1132,7 +1133,8 @@ static struct resource_funcs dcn303_res_pool_funcs = { .update_bw_bounding_box = dcn303_update_bw_bounding_box, .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, .get_panel_config_defaults = dcn303_get_panel_config_defaults, - .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe + .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe, + .get_default_tiling_info = dcn10_get_default_tiling_info }; static struct dc_cap_funcs cap_funcs = { @@ -1191,7 +1193,7 @@ static bool dcn303_resource_construct( /************************************************* * Resource + asic cap harcoding * *************************************************/ - pool->underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE; pool->pipe_count = pool->res_cap->num_timing_generator; pool->mpcc_count = pool->res_cap->num_timing_generator; dc->caps.max_downscale_ratio = 600; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c index 4e9c041c707a..ee4bc2c2e73a 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c @@ -1118,6 +1118,7 @@ static struct link_encoder *dcn31_link_encoder_create( struct dc_context *ctx, const struct encoder_init_data *enc_init_data) { + (void)ctx; struct dcn20_link_encoder *enc20 = kzalloc_obj(struct dcn20_link_encoder); @@ -1731,12 +1732,9 @@ int dcn31_populate_dml_pipes_from_context( pipe_cnt++; } context->bw_ctx.dml.ip.det_buffer_size_kbytes = DCN3_1_DEFAULT_DET_SIZE; - dc->config.enable_4to1MPC = false; + if (pipe_cnt == 1 && pipe->plane_state && !dc->debug.disable_z9_mpc) { - if (is_dual_plane(pipe->plane_state->format) - && pipe->plane_state->src_rect.width <= 1920 && pipe->plane_state->src_rect.height <= 1080) { - dc->config.enable_4to1MPC = true; - } else if (!is_dual_plane(pipe->plane_state->format) && pipe->plane_state->src_rect.width <= 5120) { + if (!is_dual_plane(pipe->plane_state->format) && pipe->plane_state->src_rect.width <= 5120) { /* Limit to 5k max to avoid forced pipe split when there is not enough detile for swath */ context->bw_ctx.dml.ip.det_buffer_size_kbytes = 192; pipes[0].pipe.src.unbounded_req_mode = true; @@ -1883,6 +1881,7 @@ static struct resource_funcs dcn31_res_pool_funcs = { .get_det_buffer_size = dcn31_get_det_buffer_size, .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe, .update_dc_state_for_encoder_switch = dcn31_update_dc_state_for_encoder_switch, + .get_default_tiling_info = dcn10_get_default_tiling_info, .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params }; @@ -1928,7 +1927,7 @@ static bool dcn31_resource_construct( /************************************************* * Resource + asic cap harcoding * *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE; pool->base.pipe_count = pool->base.res_cap->num_timing_generator; pool->base.mpcc_count = pool->base.res_cap->num_timing_generator; dc->caps.max_downscale_ratio = 600; @@ -1953,6 +1952,9 @@ static bool dcn31_resource_construct( dc->caps.is_apu = true; dc->caps.zstate_support = true; + /* Enable 4to1MPC by default */ + dc->config.allow_4to1MPC = true; + /* Color pipeline capabilities */ dc->caps.color.dpp.dcn_arch = 1; dc->caps.color.dpp.input_lut_shared = 0; @@ -2282,6 +2284,7 @@ enum dc_status dcn31_update_dc_state_for_encoder_switch(struct dc_link *link, struct pipe_ctx *pipes, struct audio_output *audio_output) { + (void)link_setting; struct dc_state *state = link->dc->current_state; int i; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c index e26a6427916a..5acc545bbe7f 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c @@ -1176,6 +1176,7 @@ static struct link_encoder *dcn31_link_encoder_create( struct dc_context *ctx, const struct encoder_init_data *enc_init_data) { + (void)ctx; struct dcn20_link_encoder *enc20 = kzalloc_obj(struct dcn20_link_encoder); @@ -1814,7 +1815,8 @@ static struct resource_funcs dcn314_res_pool_funcs = { .get_det_buffer_size = dcn31_get_det_buffer_size, .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe, .update_dc_state_for_encoder_switch = dcn31_update_dc_state_for_encoder_switch, - .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params + .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params, + .get_default_tiling_info = dcn10_get_default_tiling_info }; static struct clock_source *dcn30_clock_source_create( @@ -1858,9 +1860,12 @@ static bool dcn314_resource_construct( /************************************************* * Resource + asic cap harcoding * *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE; pool->base.pipe_count = pool->base.res_cap->num_timing_generator; pool->base.mpcc_count = pool->base.res_cap->num_timing_generator; + + /* Enable 4to1MPC by default */ + dc->config.allow_4to1MPC = true; dc->caps.max_downscale_ratio = 400; dc->caps.i2c_speed_in_khz = 100; dc->caps.i2c_speed_in_khz_hdcp = 100; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c index 131a6cd4c735..2ca673114841 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c @@ -1117,6 +1117,7 @@ static struct link_encoder *dcn31_link_encoder_create( struct dc_context *ctx, const struct encoder_init_data *enc_init_data) { + (void)ctx; struct dcn20_link_encoder *enc20 = kzalloc_obj(struct dcn20_link_encoder); @@ -1817,11 +1818,9 @@ static int dcn315_populate_dml_pipes_from_context( if (context->bw_ctx.dml.ip.det_buffer_size_kbytes > DCN3_15_MAX_DET_SIZE) context->bw_ctx.dml.ip.det_buffer_size_kbytes = DCN3_15_MAX_DET_SIZE; - dc->config.enable_4to1MPC = false; if (pipe_cnt == 1 && pipe->plane_state && !dc->debug.disable_z9_mpc) { if (is_dual_plane(pipe->plane_state->format) && pipe->plane_state->src_rect.width <= 1920 && pipe->plane_state->src_rect.height <= 1080) { - dc->config.enable_4to1MPC = true; context->bw_ctx.dml.ip.det_buffer_size_kbytes = (max_usable_det / DCN3_15_CRB_SEGMENT_SIZE_KB / 4) * DCN3_15_CRB_SEGMENT_SIZE_KB; } else if (!is_dual_plane(pipe->plane_state->format) @@ -1878,7 +1877,8 @@ static struct resource_funcs dcn315_res_pool_funcs = { .get_det_buffer_size = dcn31_get_det_buffer_size, .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe, .update_dc_state_for_encoder_switch = dcn31_update_dc_state_for_encoder_switch, - .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params + .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params, + .get_default_tiling_info = dcn10_get_default_tiling_info }; static bool dcn315_resource_construct( @@ -1899,8 +1899,11 @@ static bool dcn315_resource_construct( /************************************************* * Resource + asic cap harcoding * *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE; pool->base.pipe_count = pool->base.res_cap->num_timing_generator; + + /* Enable 4to1MPC by default */ + dc->config.allow_4to1MPC = true; pool->base.mpcc_count = pool->base.res_cap->num_timing_generator; dc->caps.max_downscale_ratio = 600; dc->caps.i2c_speed_in_khz = 100; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c index c8c0ce6efcfd..2242df112a3f 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c @@ -1110,6 +1110,7 @@ static struct link_encoder *dcn31_link_encoder_create( struct dc_context *ctx, const struct encoder_init_data *enc_init_data) { + (void)ctx; struct dcn20_link_encoder *enc20 = kzalloc_obj(struct dcn20_link_encoder); @@ -1701,11 +1702,9 @@ static int dcn316_populate_dml_pipes_from_context( if (context->bw_ctx.dml.ip.det_buffer_size_kbytes > DCN3_16_MAX_DET_SIZE) context->bw_ctx.dml.ip.det_buffer_size_kbytes = DCN3_16_MAX_DET_SIZE; ASSERT(context->bw_ctx.dml.ip.det_buffer_size_kbytes >= DCN3_16_DEFAULT_DET_SIZE); - dc->config.enable_4to1MPC = false; if (pipe_cnt == 1 && pipe->plane_state && !dc->debug.disable_z9_mpc) { if (is_dual_plane(pipe->plane_state->format) && pipe->plane_state->src_rect.width <= 1920 && pipe->plane_state->src_rect.height <= 1080) { - dc->config.enable_4to1MPC = true; context->bw_ctx.dml.ip.det_buffer_size_kbytes = (max_usable_det / DCN3_16_CRB_SEGMENT_SIZE_KB / 4) * DCN3_16_CRB_SEGMENT_SIZE_KB; } else if (!is_dual_plane(pipe->plane_state->format)) { @@ -1753,7 +1752,8 @@ static struct resource_funcs dcn316_res_pool_funcs = { .get_det_buffer_size = dcn31_get_det_buffer_size, .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe, .update_dc_state_for_encoder_switch = dcn31_update_dc_state_for_encoder_switch, - .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params + .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params, + .get_default_tiling_info = dcn10_get_default_tiling_info }; static bool dcn316_resource_construct( @@ -1774,9 +1774,13 @@ static bool dcn316_resource_construct( /************************************************* * Resource + asic cap harcoding * *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE; pool->base.pipe_count = pool->base.res_cap->num_timing_generator; pool->base.mpcc_count = pool->base.res_cap->num_timing_generator; + + /* Enable 4to1MPC by default */ + dc->config.allow_4to1MPC = true; + dc->caps.max_downscale_ratio = 600; dc->caps.i2c_speed_in_khz = 100; dc->caps.i2c_speed_in_khz_hdcp = 5; /*1.5 w/a applied by default*/ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c index c3a6ae14de18..82f81b586986 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c @@ -2147,6 +2147,7 @@ static struct resource_funcs dcn32_res_pool_funcs = { .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, .update_soc_for_wm_a = dcn30_update_soc_for_wm_a, .add_phantom_pipes = dcn32_add_phantom_pipes, + .get_default_tiling_info = dcn10_get_default_tiling_info, .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params, .calculate_mall_ways_from_bytes = dcn32_calculate_mall_ways_from_bytes, .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe, @@ -2225,7 +2226,7 @@ static bool dcn32_resource_construct( /************************************************* * Resource + asic cap harcoding * *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE; pool->base.timing_generator_count = num_pipes; pool->base.pipe_count = num_pipes; pool->base.mpcc_count = num_pipes; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource_helpers.c b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource_helpers.c index f5a4e97c40ce..4808c793590f 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource_helpers.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource_helpers.c @@ -41,6 +41,7 @@ uint32_t dcn32_helper_calculate_mall_bytes_for_cursor( struct pipe_ctx *pipe_ctx, bool ignore_cursor_buf) { + (void)dc; struct hubp *hubp = pipe_ctx->plane_res.hubp; uint32_t cursor_size = hubp->curs_attr.pitch * hubp->curs_attr.height; uint32_t cursor_mall_size_bytes = 0; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c index 990aec7eb3d0..c8c81870d50e 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c @@ -1654,6 +1654,7 @@ static struct resource_funcs dcn321_res_pool_funcs = { .calculate_mall_ways_from_bytes = dcn32_calculate_mall_ways_from_bytes, .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe, .get_max_hw_cursor_size = dcn32_get_max_hw_cursor_size, + .get_default_tiling_info = dcn10_get_default_tiling_info, }; static uint32_t read_pipe_fuses(struct dc_context *ctx) @@ -1729,7 +1730,7 @@ static bool dcn321_resource_construct( /************************************************* * Resource + asic cap harcoding * *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE; pool->base.timing_generator_count = num_pipes; pool->base.pipe_count = num_pipes; pool->base.mpcc_count = num_pipes; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c index 598b2f25881d..2a1b0b152501 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c @@ -1773,9 +1773,11 @@ static enum dc_status dcn35_validate_bandwidth(struct dc *dc, { bool out = false; + DC_FP_START(); out = dml2_validate(dc, context, context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2, validate_mode); + DC_FP_END(); if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING) return out ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE; @@ -1809,6 +1811,12 @@ static int populate_dml_pipes_from_context_fpu(struct dc *dc, return ret; } +void dcn35_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) +{ + DC_FP_START(); + dcn35_update_bw_bounding_box_fpu(dc, bw_params); + DC_FP_END(); +} static struct resource_funcs dcn35_res_pool_funcs = { .destroy = dcn35_destroy_resource_pool, .link_enc_create = dcn35_link_encoder_create, @@ -1830,14 +1838,15 @@ static struct resource_funcs dcn35_res_pool_funcs = { .find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link, .acquire_post_bldn_3dlut = dcn30_acquire_post_bldn_3dlut, .release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut, - .update_bw_bounding_box = dcn35_update_bw_bounding_box_fpu, + .update_bw_bounding_box = dcn35_update_bw_bounding_box, .patch_unknown_plane_state = dcn35_patch_unknown_plane_state, .get_panel_config_defaults = dcn35_get_panel_config_defaults, .get_preferred_eng_id_dpia = dcn35_get_preferred_eng_id_dpia, .get_det_buffer_size = dcn31_get_det_buffer_size, .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe, .update_dc_state_for_encoder_switch = dcn31_update_dc_state_for_encoder_switch, - .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params + .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params, + .get_default_tiling_info = dcn10_get_default_tiling_info }; static bool dcn35_resource_construct( @@ -1861,6 +1870,9 @@ static bool dcn35_resource_construct( clk_src_regs_init(3, D), clk_src_regs_init(4, E); + /* Enable 4to1MPC by default */ + dc->config.allow_4to1MPC = true; + #undef REG_STRUCT #define REG_STRUCT abm_regs abm_regs_init(0), @@ -1881,7 +1893,7 @@ static bool dcn35_resource_construct( /************************************************* * Resource + asic cap harcoding * *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE; pool->base.pipe_count = pool->base.res_cap->num_timing_generator; pool->base.mpcc_count = pool->base.res_cap->num_timing_generator; dc->caps.max_downscale_ratio = 600; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.h index 9c56ae76e0c7..6c2c61c711b9 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.h +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.h @@ -312,4 +312,5 @@ struct resource_pool *dcn35_create_resource_pool( #define DPP_REG_LIST_DCN35_RI(id)\ DPP_REG_LIST_DCN30_COMMON_RI(id) +void dcn35_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params); #endif /* _DCN35_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c index 7e15d07df7a3..bfd1016aa780 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c @@ -1753,9 +1753,11 @@ static enum dc_status dcn351_validate_bandwidth(struct dc *dc, { bool out = false; + DC_FP_START(); out = dml2_validate(dc, context, context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2, validate_mode); + DC_FP_END(); if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING) return out ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE; @@ -1782,6 +1784,12 @@ static int populate_dml_pipes_from_context_fpu(struct dc *dc, } +static void dcn351_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) +{ + DC_FP_START(); + dcn351_update_bw_bounding_box_fpu(dc, bw_params); + DC_FP_END(); +} static struct resource_funcs dcn351_res_pool_funcs = { .destroy = dcn351_destroy_resource_pool, .link_enc_create = dcn35_link_encoder_create, @@ -1803,14 +1811,15 @@ static struct resource_funcs dcn351_res_pool_funcs = { .find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link, .acquire_post_bldn_3dlut = dcn30_acquire_post_bldn_3dlut, .release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut, - .update_bw_bounding_box = dcn351_update_bw_bounding_box_fpu, + .update_bw_bounding_box = dcn351_update_bw_bounding_box, .patch_unknown_plane_state = dcn35_patch_unknown_plane_state, .get_panel_config_defaults = dcn35_get_panel_config_defaults, .get_preferred_eng_id_dpia = dcn351_get_preferred_eng_id_dpia, .get_det_buffer_size = dcn31_get_det_buffer_size, .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe, .update_dc_state_for_encoder_switch = dcn31_update_dc_state_for_encoder_switch, - .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params + .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params, + .get_default_tiling_info = dcn10_get_default_tiling_info }; static bool dcn351_resource_construct( @@ -1834,6 +1843,9 @@ static bool dcn351_resource_construct( clk_src_regs_init(3, D), clk_src_regs_init(4, E); + /* Enable 4to1MPC by default */ + dc->config.allow_4to1MPC = true; + #undef REG_STRUCT #define REG_STRUCT abm_regs abm_regs_init(0), @@ -1854,7 +1866,7 @@ static bool dcn351_resource_construct( /************************************************* * Resource + asic cap harcoding * *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE; pool->base.pipe_count = pool->base.res_cap->num_timing_generator; pool->base.mpcc_count = pool->base.res_cap->num_timing_generator; dc->caps.max_downscale_ratio = 600; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c index 83fee2ca61bf..07a6675a7329 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c @@ -1760,9 +1760,11 @@ static enum dc_status dcn35_validate_bandwidth(struct dc *dc, { bool out = false; + DC_FP_START(); out = dml2_validate(dc, context, context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2, validate_mode); + DC_FP_END(); if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING) return out ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE; @@ -1810,13 +1812,14 @@ static struct resource_funcs dcn36_res_pool_funcs = { .find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link, .acquire_post_bldn_3dlut = dcn30_acquire_post_bldn_3dlut, .release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut, - .update_bw_bounding_box = dcn35_update_bw_bounding_box_fpu, + .update_bw_bounding_box = dcn35_update_bw_bounding_box, .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, .get_panel_config_defaults = dcn35_get_panel_config_defaults, .get_preferred_eng_id_dpia = dcn36_get_preferred_eng_id_dpia, .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe, .update_dc_state_for_encoder_switch = dcn31_update_dc_state_for_encoder_switch, - .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params + .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params, + .get_default_tiling_info = dcn10_get_default_tiling_info, }; static bool dcn36_resource_construct( @@ -1860,7 +1863,7 @@ static bool dcn36_resource_construct( /************************************************* * Resource + asic cap harcoding * *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE; pool->base.pipe_count = pool->base.res_cap->num_timing_generator; pool->base.mpcc_count = pool->base.res_cap->num_timing_generator; dc->caps.max_downscale_ratio = 600; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c index e37aab939a41..cb93bfbe9e9e 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c @@ -1643,8 +1643,10 @@ static struct dc_cap_funcs cap_funcs = { .get_subvp_en = dcn32_subvp_in_use, }; -static void dcn401_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) +static void dcn401_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_params) { + dc_assert_fp_enabled(); + /* re-calculate the available MALL size if required */ if (bw_params->num_channels > 0) { dc->caps.max_cab_allocation_bytes = dcn401_calc_num_avail_chans_for_mall( @@ -1653,17 +1655,19 @@ static void dcn401_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *b dc->caps.mall_size_total = dc->caps.max_cab_allocation_bytes; } - DC_FP_START(); - if (dc->debug.using_dml2 && dc->current_state && dc->current_state->bw_ctx.dml2) dml2_reinit(dc, &dc->dml2_options, &dc->current_state->bw_ctx.dml2); if (dc->debug.using_dml2 && dc->current_state && dc->current_state->bw_ctx.dml2_dc_power_source) dml2_reinit(dc, &dc->dml2_dc_power_options, &dc->current_state->bw_ctx.dml2_dc_power_source); +} +static void dcn401_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) +{ + DC_FP_START(); + dcn401_update_bw_bounding_box_fpu(dc, bw_params); DC_FP_END(); } - enum dc_status dcn401_patch_unknown_plane_state(struct dc_plane_state *plane_state) { plane_state->tiling_info.gfxversion = DcGfxAddr3; @@ -1688,10 +1692,13 @@ enum dc_status dcn401_validate_bandwidth(struct dc *dc, } } - if (dc->debug.using_dml2) + if (dc->debug.using_dml2) { + DC_FP_START(); status = dml2_validate(dc, context, context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2, validate_mode) ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE; + DC_FP_END(); + } if (validate_mode == DC_VALIDATE_MODE_AND_PROGRAMMING && status == DC_OK && dc_state_is_subvp_in_use(context)) { /* check new stream configuration still supports cursor if subvp used */ @@ -1710,10 +1717,13 @@ enum dc_status dcn401_validate_bandwidth(struct dc *dc, if (validate_mode == DC_VALIDATE_MODE_AND_PROGRAMMING && status == DC_FAIL_HW_CURSOR_SUPPORT) { /* attempt to validate again with subvp disabled due to cursor */ - if (dc->debug.using_dml2) + if (dc->debug.using_dml2) { + DC_FP_START(); status = dml2_validate(dc, context, context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2, validate_mode) ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE; + DC_FP_END(); + } } return status; @@ -1722,9 +1732,13 @@ enum dc_status dcn401_validate_bandwidth(struct dc *dc, void dcn401_prepare_mcache_programming(struct dc *dc, struct dc_state *context) { - if (dc->debug.using_dml21) + if (dc->debug.using_dml21) { + DC_FP_START(); dml2_prepare_mcache_programming(dc, context, - context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2); + context->power_source == DC_POWER_SOURCE_DC ? + context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2); + DC_FP_END(); + } } static void dcn401_build_pipe_pix_clk_params(struct pipe_ctx *pipe_ctx) @@ -1790,7 +1804,7 @@ static void dcn401_build_pipe_pix_clk_params(struct pipe_ctx *pipe_ctx) } } -static int dcn401_get_power_profile(const struct dc_state *context) +int dcn401_get_power_profile(const struct dc_state *context) { int uclk_mhz = context->bw_ctx.bw.dcn.clk.dramclk_khz / 1000; int dpm_level = 0; @@ -1839,9 +1853,16 @@ static struct resource_funcs dcn401_res_pool_funcs = { .calculate_mall_ways_from_bytes = dcn32_calculate_mall_ways_from_bytes, .get_power_profile = dcn401_get_power_profile, .get_vstartup_for_pipe = dcn401_get_vstartup_for_pipe, - .get_max_hw_cursor_size = dcn32_get_max_hw_cursor_size + .get_max_hw_cursor_size = dcn32_get_max_hw_cursor_size, + .get_default_tiling_info = dcn401_get_default_tiling_info }; +void dcn401_get_default_tiling_info(struct dc_tiling_info *tiling_info) +{ + tiling_info->gfxversion = DcGfxAddr3; + tiling_info->gfx_addr3.swizzle = DC_ADDR3_SW_LINEAR; +} + static uint32_t read_pipe_fuses(struct dc_context *ctx) { uint32_t value = REG_READ(CC_DC_PIPE_DIS); @@ -1908,7 +1929,7 @@ static bool dcn401_resource_construct( /************************************************* * Resource + asic cap harcoding * *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE; pool->base.timing_generator_count = num_pipes; pool->base.pipe_count = num_pipes; pool->base.mpcc_count = num_pipes; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h index 08bec1755617..47f82b818262 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h @@ -28,8 +28,11 @@ enum dc_status dcn401_validate_bandwidth(struct dc *dc, void dcn401_prepare_mcache_programming(struct dc *dc, struct dc_state *context); +void dcn401_get_default_tiling_info(struct dc_tiling_info *tiling_info); + unsigned int dcn401_get_vstartup_for_pipe(struct pipe_ctx *pipe_ctx); +int dcn401_get_power_profile(const struct dc_state *context); /* Following are definitions for run time init of reg offsets */ /* HUBP */ 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 new file mode 100644 index 000000000000..c0d37f00fed9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c @@ -0,0 +1,2358 @@ +// SPDX-License-Identifier: MIT +// +// Copyright 2026 Advanced Micro Devices, Inc. + +#include "dm_services.h" +#include "dc.h" + +#include "dcn32/dcn32_init.h" +#include "dcn42/dcn42_init.h" + +#include "resource.h" +#include "include/irq_service_interface.h" + +#include "dcn42_resource.h" +#include "dcn42_resource_fpu.h" +#include "dcn20/dcn20_resource.h" +#include "dcn30/dcn30_resource.h" +#include "dcn31/dcn31_resource.h" +#include "dcn32/dcn32_resource.h" +#include "dcn35/dcn35_resource.h" +#include "dcn321/dcn321_resource.h" +#include "dcn401/dcn401_resource.h" + +#include "dcn10/dcn10_ipp.h" +#include "dcn35/dcn35_hubbub.h" +#include "dcn42/dcn42_hubbub.h" +#include "dcn401/dcn401_mpc.h" +#include "dcn42/dcn42_mpc.h" +#include "dcn35/dcn35_hubp.h" +#include "dcn42/dcn42_hubp.h" +#include "irq/dcn42/irq_service_dcn42.h" +#include "dcn42/dcn42_dpp.h" +#include "dcn401/dcn401_dsc.h" +#include "dcn42/dcn42_optc.h" +#include "dcn20/dcn20_hwseq.h" +#include "dcn30/dcn30_hwseq.h" +#include "dce110/dce110_hwseq.h" +#include "dcn35/dcn35_opp.h" +#include "dcn30/dcn30_vpg.h" +#include "dcn31/dcn31_vpg.h" +#include "dcn42/dcn42_dio_stream_encoder.h" +#include "dcn42/dcn42_pg_cntl.h" +#include "dcn31/dcn31_hpo_dp_stream_encoder.h" +#include "dcn31/dcn31_hpo_dp_link_encoder.h" +#include "dcn32/dcn32_hpo_dp_link_encoder.h" +#include "dcn42/dcn42_hpo_dp_link_encoder.h" +#include "dcn31/dcn31_apg.h" +#include "dcn31/dcn31_dio_link_encoder.h" +#include "dcn401/dcn401_dio_link_encoder.h" +#include "dcn10/dcn10_link_encoder.h" +#include "dcn321/dcn321_dio_link_encoder.h" +#include "dce/dce_clock_source.h" +#include "dce/dce_audio.h" +#include "dce/dce_hwseq.h" +#include "clk_mgr.h" +#include "dio/virtual/virtual_stream_encoder.h" +#include "dml/display_mode_vba.h" +#include "dcn42/dcn42_dccg.h" +#include "dcn10/dcn10_resource.h" +#include "link_service.h" +#include "dcn31/dcn31_panel_cntl.h" + +#include "dcn30/dcn30_dwb.h" +#include "dcn42/dcn42_mmhubbub.h" +#include "dcn42/dcn42_dio_link_encoder.h" + +#include "dcn/dcn_4_2_0_offset.h" +#include "dcn/dcn_4_2_0_sh_mask.h" +#include "dpcs/dpcs_4_0_0_offset.h" +#include "dpcs/dpcs_4_0_0_sh_mask.h" + +#include "reg_helper.h" +#include "dce/dmub_abm.h" +#include "dce/dmub_psr.h" +#include "dce/dmub_replay.h" +#include "dce/dce_aux.h" +#include "dce/dce_i2c.h" + +#include "dml/dcn30/display_mode_vba_30.h" +#include "vm_helper.h" +#include "dcn20/dcn20_vmid.h" + +#include "dc_state_priv.h" +#include "link_enc_cfg.h" + +#include "dml2_0/dml2_wrapper.h" + +#define regBIF_BX0_BIOS_SCRATCH_3 0x003b +#define regBIF_BX0_BIOS_SCRATCH_3_BASE_IDX 1 +#define regBIF_BX0_BIOS_SCRATCH_6 0x003e +#define regBIF_BX0_BIOS_SCRATCH_6_BASE_IDX 1 + +#define DC_LOGGER_INIT(logger) + +enum dcn401_clk_src_array_id { + DCN401_CLK_SRC_PLL0, + DCN401_CLK_SRC_PLL1, + DCN401_CLK_SRC_PLL2, + DCN401_CLK_SRC_PLL3, + DCN401_CLK_SRC_PLL4, + DCN401_CLK_SRC_TOTAL +}; + +/* begin + * macros to expend register list macro defined in HW object header file + */ + +/* DCN */ +#define BASE_INNER(seg) ctx->dcn_reg_offsets[seg] + +#define BASE(seg) BASE_INNER(seg) + +#define SR(reg_name) \ + REG_STRUCT.reg_name = BASE(reg##reg_name##_BASE_IDX) + \ + reg##reg_name +#define SR_ARR(reg_name, id) \ + REG_STRUCT[id].reg_name = BASE(reg##reg_name##_BASE_IDX) + \ + reg##reg_name +#define SR_ARR_INIT(reg_name, id, value) \ + REG_STRUCT[id].reg_name = value + +#define SRI(reg_name, block, id) \ + REG_STRUCT.reg_name = BASE(reg##block##id##_##reg_name##_BASE_IDX) + \ + reg##block##id##_##reg_name + +#define SRI_ARR(reg_name, block, id) \ + REG_STRUCT[id].reg_name = BASE(reg##block##id##_##reg_name##_BASE_IDX) + \ + reg##block##id##_##reg_name + +/* + * Used when a reg_name would otherwise begin with an integer + */ +#define SRI_ARR_US(reg_name, block, id) \ + REG_STRUCT[id].reg_name = BASE(reg##block##id##reg_name##_BASE_IDX) + \ + reg##block##id##reg_name +#define SR_ARR_I2C(reg_name, id) \ + REG_STRUCT[id - 1].reg_name = BASE(reg##reg_name##_BASE_IDX) + reg##reg_name + +#define SRI_ARR_I2C(reg_name, block, id) \ + REG_STRUCT[id - 1].reg_name = BASE(reg##block##id##_##reg_name##_BASE_IDX) + \ + reg##block##id##_##reg_name + + +#define SRI_ARR_ALPHABET(reg_name, block, index, id) \ + REG_STRUCT[index].reg_name = BASE(reg##block##id##_##reg_name##_BASE_IDX) + \ + reg##block##id##_##reg_name + +#define SRI2(reg_name, block, id) \ + .reg_name = BASE(reg##reg_name##_BASE_IDX) + \ + reg##reg_name +#define SRI2_ARR(reg_name, block, id) \ + REG_STRUCT[id].reg_name = BASE(reg##reg_name##_BASE_IDX) + \ + reg##reg_name + +#define SRIR(var_name, reg_name, block, id) \ + .var_name = BASE(reg##block##id##_##reg_name##_BASE_IDX) + \ + reg##block##id##_##reg_name + +#define SRII(reg_name, block, id) \ + REG_STRUCT.reg_name[id] = BASE(reg##block##id##_##reg_name##_BASE_IDX) + \ + reg##block##id##_##reg_name + +#define SRII_ARR_2(reg_name, block, id, inst) \ + REG_STRUCT[inst].reg_name[id] = BASE(reg##block##id##_##reg_name##_BASE_IDX) + \ + reg##block##id##_##reg_name + +#define SRII_MPC_RMU(reg_name, block, id) \ + .RMU##_##reg_name[id] = BASE(reg##block##id##_##reg_name##_BASE_IDX) + \ + reg##block##id##_##reg_name + +#define SRII_DWB(reg_name, temp_name, block, id) \ + REG_STRUCT.reg_name[id] = \ + BASE(reg##block##id##_##temp_name##_BASE_IDX) + \ + reg##block##id##_##temp_name + +#define DCCG_SRII(reg_name, block, id) \ + REG_STRUCT.block##_##reg_name[id] = \ + BASE(reg##block##id##_##reg_name##_BASE_IDX) + \ + reg##block##id##_##reg_name + +#define SF_DWB2(reg_name, block, id, field_name, post_fix) \ + .field_name = reg_name##__##field_name##post_fix + +#define VUPDATE_SRII(reg_name, block, id) \ + REG_STRUCT.reg_name[id] = BASE(reg##reg_name##_##block##id##_BASE_IDX) + \ + reg##reg_name##_##block##id + +/* NBIO */ +#define NBIO_BASE_INNER(seg) ctx->nbio_reg_offsets[seg] + +#define NBIO_BASE(seg) \ + NBIO_BASE_INNER(seg) + +#define NBIO_SR(reg_name) \ + REG_STRUCT.reg_name = NBIO_BASE(regBIF_BX0_##reg_name##_BASE_IDX) + \ + regBIF_BX0_##reg_name +#define NBIO_SR_ARR(reg_name, id) \ + REG_STRUCT[id].reg_name = NBIO_BASE(regBIF_BX0_##reg_name##_BASE_IDX) + \ + regBIF_BX0_##reg_name + +#define CTX ctx +#define REG(reg_name) \ + (ctx->dcn_reg_offsets[reg##reg_name##_BASE_IDX] + reg##reg_name) + +static struct bios_registers bios_regs; + +#define bios_regs_init() \ + NBIO_SR(BIOS_SCRATCH_3), \ + NBIO_SR(BIOS_SCRATCH_6) + +#define clk_src_regs_init(index, pllid) \ + CS_COMMON_REG_LIST_DCN42_RI(index, pllid) + +static struct dce110_clk_src_regs clk_src_regs[5]; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCN3_1_4(__SHIFT) +}; +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCN3_1_4(_MASK) +}; +#define abm_regs_init(id) \ + ABM_DCN42_REG_LIST_RI(id) + +static struct dce_abm_registers abm_regs[4]; + +static const struct dce_abm_shift abm_shift = { + ABM_MASK_SH_LIST_DCN42(__SHIFT)}; + +static const struct dce_abm_mask abm_mask = { + ABM_MASK_SH_LIST_DCN42(_MASK)}; + +#define audio_regs_init(id) \ + AUD_COMMON_REG_LIST_RI(id) + +static struct dce_audio_registers audio_regs[5]; + +static const struct dce_audio_shift audio_shift = { + DCN42_AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_audio_mask audio_mask = { + DCN42_AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +#define vpg_regs_init(id) \ + VPG_DCN401_REG_LIST_RI(id) + +static struct dcn31_vpg_registers vpg_regs[10]; + +static const struct dcn31_vpg_shift vpg_shift = { + DCN31_VPG_MASK_SH_LIST(__SHIFT)}; + +static const struct dcn31_vpg_mask vpg_mask = { + DCN31_VPG_MASK_SH_LIST(_MASK)}; + +#define apg_regs_init(id) \ + APG_DCN31_REG_LIST_RI(id) + +static struct dcn31_apg_registers apg_regs[10]; + +static const struct dcn31_apg_shift apg_shift = { + DCN31_APG_MASK_SH_LIST(__SHIFT)}; + +static const struct dcn31_apg_mask apg_mask = { + DCN31_APG_MASK_SH_LIST(_MASK)}; + +#define stream_enc_regs_init(id) \ + SE_DCN42_REG_LIST_RI(id) + +static struct dcn10_stream_enc_registers stream_enc_regs[5]; + +static const struct dcn10_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCN42(__SHIFT)}; + +static const struct dcn10_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCN42(_MASK)}; + +#define aux_regs_init(id) \ + DCN2_AUX_REG_LIST_RI(id) + +static struct dcn10_link_enc_aux_registers link_enc_aux_regs[5]; + +#define hpd_regs_init(id) \ + HPD_REG_LIST_RI(id) + +static struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[5]; + +#define link_regs_init(id, phyid) \ + LE_DCN401_REG_LIST_RI(id) + +static struct dcn10_link_enc_registers link_enc_regs[5]; + +static const struct dcn10_link_enc_shift le_shift = { + LINK_ENCODER_MASK_SH_LIST_DCN42(__SHIFT)}; + +static const struct dcn10_link_enc_mask le_mask = { + LINK_ENCODER_MASK_SH_LIST_DCN42(_MASK)}; + +#define hpo_dp_stream_encoder_reg_init(id) \ + DCN42_HPO_DP_STREAM_ENC_REG_LIST_RI(id) + +static struct dcn31_hpo_dp_stream_encoder_registers hpo_dp_stream_enc_regs[4]; + +static const struct dcn31_hpo_dp_stream_encoder_shift hpo_dp_se_shift = { + DCN4_2_HPO_DP_STREAM_ENC_MASK_SH_LIST(__SHIFT)}; + +static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { + DCN4_2_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK)}; + +#define hpo_dp_link_encoder_reg_init(id) \ + DCN42_HPO_DP_LINK_ENC_REG_LIST_RI(id) + +static struct dcn31_hpo_dp_link_encoder_registers hpo_dp_link_enc_regs[4]; + +static const struct dcn31_hpo_dp_link_encoder_shift hpo_dp_le_shift = { + DCN3_2_HPO_DP_LINK_ENC_MASK_SH_LIST(__SHIFT)}; + +static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { + DCN3_2_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK)}; + +#define dpp_regs_init(id) \ + DPP_REG_LIST_DCN42_COMMON_RI(id) + +static struct dcn42_dpp_registers dpp_regs[4]; + +static const struct dcn42_dpp_shift tf_shift = { + DPP_REG_LIST_SH_MASK_DCN42_COMMON(__SHIFT)}; + +static const struct dcn42_dpp_mask tf_mask = { + DPP_REG_LIST_SH_MASK_DCN42_COMMON(_MASK)}; + +#define opp_regs_init(id) \ + OPP_REG_LIST_DCN401_RI(id) + +static struct dcn20_opp_registers opp_regs[4]; + +static const struct dcn20_opp_shift opp_shift = { + OPP_MASK_SH_LIST_DCN20(__SHIFT)}; + +static const struct dcn20_opp_mask opp_mask = { + OPP_MASK_SH_LIST_DCN20(_MASK)}; + +#define aux_engine_regs_init(id) \ + AUX_COMMON_REG_LIST0_RI(id), SR_ARR_INIT(AUXN_IMPCAL, id, 0), \ + SR_ARR_INIT(AUXP_IMPCAL, id, 0), \ + SR_ARR_INIT(AUX_RESET_MASK, id, DP_AUX0_AUX_CONTROL__AUX_RESET_MASK), \ + SR_ARR_INIT(AUX_RESET_MASK, id, DP_AUX0_AUX_CONTROL__AUX_RESET_MASK) + +static struct dce110_aux_registers aux_engine_regs[5]; + +static const struct dce110_aux_registers_shift aux_shift = { + DCN_AUX_MASK_SH_LIST(__SHIFT)}; + +static const struct dce110_aux_registers_mask aux_mask = { + DCN_AUX_MASK_SH_LIST(_MASK)}; + +#define dwbc_regs_dcn401_init(id) \ + DWBC_COMMON_REG_LIST_DCN30_RI(id) + +static struct dcn30_dwbc_registers dwbc401_regs[1]; + +static const struct dcn30_dwbc_shift dwbc401_shift = { + DWBC_COMMON_MASK_SH_LIST_DCN30(__SHIFT)}; + +static const struct dcn30_dwbc_mask dwbc401_mask = { + DWBC_COMMON_MASK_SH_LIST_DCN30(_MASK)}; + +#define mcif_wb_regs_dcn3_init(id) \ + MCIF_WB_COMMON_REG_LIST_DCN3_5_RI(id) + +static struct dcn35_mmhubbub_registers mcif_wb35_regs[1]; + +static const struct dcn35_mmhubbub_shift mcif_wb35_shift = { + MCIF_WB_COMMON_MASK_SH_LIST_DCN3_5(__SHIFT)}; + +static const struct dcn35_mmhubbub_mask mcif_wb35_mask = { + MCIF_WB_COMMON_MASK_SH_LIST_DCN3_5(_MASK)}; + +#define dsc_regs_init(id) \ + DSC_REG_LIST_DCN401_RI(id) + +static struct dcn401_dsc_registers dsc_regs[4]; + +static const struct dcn401_dsc_shift dsc_shift = { + DSC_REG_LIST_SH_MASK_DCN401(__SHIFT)}; + +static const struct dcn401_dsc_mask dsc_mask = { + DSC_REG_LIST_SH_MASK_DCN401(_MASK)}; + +static struct dcn42_mpc_registers mpc_regs; + +#define dcn_mpc_regs_init() \ + MPC_REG_LIST_DCN42(0), \ + MPC_REG_LIST_DCN42(1), \ + MPC_REG_LIST_DCN42(2), \ + MPC_REG_LIST_DCN42(3), \ + MPC_OUT_MUX_REG_LIST_DCN3_0_RI(0), \ + MPC_OUT_MUX_REG_LIST_DCN3_0_RI(1), \ + MPC_OUT_MUX_REG_LIST_DCN3_0_RI(2), \ + MPC_OUT_MUX_REG_LIST_DCN3_0_RI(3), \ + MPC_DWB_MUX_REG_LIST_DCN3_0_RI(0), \ + MPC_RMCM_REG_LIST_DCN42(0), \ + MPC_RMCM_REG_LIST_DCN42(1) + +static const struct dcn42_mpc_shift mpc_shift = { + MPC_COMMON_MASK_SH_LIST_DCN42(__SHIFT)}; + +static const struct dcn42_mpc_mask mpc_mask = { + MPC_COMMON_MASK_SH_LIST_DCN42(_MASK)}; + +#define optc_regs_init(id) \ + OPTC_COMMON_REG_LIST_DCN42_RI(id) + +static struct dcn_optc_registers optc_regs[4]; + +static const struct dcn_optc_shift optc_shift = { + OPTC_COMMON_MASK_SH_LIST_DCN42(__SHIFT)}; + +static const struct dcn_optc_mask optc_mask = { + OPTC_COMMON_MASK_SH_LIST_DCN42(_MASK)}; + +#define hubp_regs_init(id) \ + HUBP_REG_LIST_DCN42_RI(id) + +static struct dcn_hubp2_registers hubp_regs[4]; + +static const struct dcn_hubp2_shift hubp_shift = { + HUBP_MASK_SH_LIST_DCN42(__SHIFT)}; + +static const struct dcn_hubp2_mask hubp_mask = { + HUBP_MASK_SH_LIST_DCN42(_MASK)}; + +static struct dcn_hubbub_registers hubbub_reg; + +#define hubbub_reg_init() \ + HUBBUB_REG_LIST_DCN42(0) + +static const struct dcn_hubbub_shift hubbub_shift = { + HUBBUB_MASK_SH_LIST_DCN4_2(__SHIFT)}; + +static const struct dcn_hubbub_mask hubbub_mask = { + HUBBUB_MASK_SH_LIST_DCN4_2(_MASK)}; + +static struct dccg_registers dccg_regs; + +#define dccg_regs_init() \ + DCCG_REG_LIST_DCN42_RI() + +static const struct dccg_shift dccg_shift = { + DCCG_MASK_SH_LIST_DCN42(__SHIFT)}; + +static const struct dccg_mask dccg_mask = { + DCCG_MASK_SH_LIST_DCN42(_MASK)}; + +static struct pg_cntl_registers pg_cntl_regs; + +#define pg_cntl_dcn42_regs_init() \ + PG_CNTL_REG_LIST_DCN42() + +static const struct pg_cntl_shift pg_cntl_shift = { + PG_CNTL_MASK_SH_LIST_DCN42(__SHIFT) +}; + +static const struct pg_cntl_mask pg_cntl_mask = { + PG_CNTL_MASK_SH_LIST_DCN42(_MASK) +}; +#define SRII2(reg_name_pre, reg_name_post, id) \ + .reg_name_pre##_##reg_name_post[id] = \ + BASE(reg##reg_name_pre##id##_##reg_name_post##_BASE_IDX) + \ + reg##reg_name_pre##id##_##reg_name_post + +#define HWSEQ_DCN42_REG_LIST() \ + SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ + SR(DIO_MEM_PWR_CTRL), \ + SR(ODM_MEM_PWR_CTRL3), \ + SR(MMHUBBUB_MEM_PWR_CNTL), \ + SR(DCCG_GATE_DISABLE_CNTL), \ + SR(DCCG_GATE_DISABLE_CNTL2), \ + SR(DCFCLK_CNTL), \ + SR(DC_MEM_GLOBAL_PWR_REQ_CNTL), \ + SRII(PIXEL_RATE_CNTL, OTG, 0), \ + SRII(PIXEL_RATE_CNTL, OTG, 1), \ + SRII(PIXEL_RATE_CNTL, OTG, 2), \ + SRII(PIXEL_RATE_CNTL, OTG, 3),\ + SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 0), \ + SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 1), \ + SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 2), \ + SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 3),\ + SR(MICROSECOND_TIME_BASE_DIV), \ + SR(MILLISECOND_TIME_BASE_DIV), \ + SR(DISPCLK_FREQ_CHANGE_CNTL), \ + SR(RBBMIF_TIMEOUT_DIS), \ + SR(RBBMIF_TIMEOUT_DIS_2), \ + SR(DCHUBBUB_CRC_CTRL), \ + SR(DPP_TOP0_DPP_CRC_CTRL), \ + SR(DPP_TOP0_DPP_CRC_VAL_R), \ + SR(DPP_TOP0_DPP_CRC_VAL_G), \ + SR(DPP_TOP0_DPP_CRC_VAL_B), \ + SR(MPC_CRC_CTRL), \ + SR(MPC_CRC_RESULT_R), \ + SR(MPC_CRC_RESULT_G), \ + SR(MPC_CRC_RESULT_B), \ + SR(MPC_CRC_RESULT_A), \ + SR(DOMAIN0_PG_CONFIG), \ + SR(DOMAIN1_PG_CONFIG), \ + SR(DOMAIN2_PG_CONFIG), \ + SR(DOMAIN3_PG_CONFIG), \ + SR(DOMAIN16_PG_CONFIG), \ + SR(DOMAIN17_PG_CONFIG), \ + SR(DOMAIN18_PG_CONFIG), \ + SR(DOMAIN19_PG_CONFIG), \ + SR(DOMAIN22_PG_CONFIG), \ + SR(DOMAIN23_PG_CONFIG), \ + SR(DOMAIN24_PG_CONFIG), \ + SR(DOMAIN25_PG_CONFIG), \ + SR(DOMAIN26_PG_CONFIG), \ + SR(DOMAIN0_PG_STATUS), \ + SR(DOMAIN1_PG_STATUS), \ + SR(DOMAIN2_PG_STATUS), \ + SR(DOMAIN3_PG_STATUS), \ + SR(DOMAIN16_PG_STATUS), \ + SR(DOMAIN17_PG_STATUS), \ + SR(DOMAIN18_PG_STATUS), \ + SR(DOMAIN19_PG_STATUS), \ + SR(DOMAIN22_PG_STATUS), \ + SR(DOMAIN23_PG_STATUS), \ + SR(DOMAIN24_PG_STATUS), \ + SR(DOMAIN25_PG_STATUS), \ + SR(DOMAIN26_PG_STATUS), \ + SR(DC_IP_REQUEST_CNTL), \ + SR(AZALIA_AUDIO_DTO), \ + SR(HPO_TOP_HW_CONTROL), \ + SR(AZALIA_CONTROLLER_CLOCK_GATING) + +static struct dce_hwseq_registers hwseq_reg; + +#define hwseq_reg_init() \ + HWSEQ_DCN42_REG_LIST() + +#define HWSEQ_DCN42_MASK_SH_LIST(mask_sh) \ + HWSEQ_DCN_MASK_SH_LIST(mask_sh), \ + HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, mask_sh), \ + HWS_SF(, DCHUBBUB_ARB_HOSTVM_CNTL, DISABLE_HOSTVM_FORCE_ALLOW_PSTATE, mask_sh), \ + HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN19_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN19_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN22_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN22_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN23_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN23_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN24_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN24_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN25_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN25_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN26_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN26_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN16_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN17_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN18_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN19_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN22_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN23_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN24_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN25_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN26_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ + HWS_SF(, AZALIA_AUDIO_DTO, AZALIA_AUDIO_DTO_MODULE, mask_sh), \ + HWS_SF(, HPO_TOP_CLOCK_CONTROL, HPO_HDMISTREAMCLK_G_GATE_DIS, mask_sh), \ + HWS_SF(, HPO_TOP_HW_CONTROL, HPO_IO_EN, mask_sh), \ + HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_UNASSIGNED_PWR_MODE, mask_sh), \ + HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_VBLANK_PWR_MODE, mask_sh), \ + HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh), \ + HWS_SF(, DMU_CLK_CNTL, DISPCLK_R_DMU_GATE_DIS, mask_sh),\ + HWS_SF(, DMU_CLK_CNTL, DISPCLK_G_RBBMIF_GATE_DIS, mask_sh),\ + HWS_SF(, DMU_CLK_CNTL, RBBMIF_FGCG_REP_DIS, mask_sh),\ + HWS_SF(, DMU_CLK_CNTL, DPREFCLK_ALLOW_DS_CLKSTOP, mask_sh),\ + HWS_SF(, DMU_CLK_CNTL, DISPCLK_ALLOW_DS_CLKSTOP, mask_sh),\ + HWS_SF(, DMU_CLK_CNTL, DPPCLK_ALLOW_DS_CLKSTOP, mask_sh),\ + HWS_SF(, DMU_CLK_CNTL, DTBCLK_ALLOW_DS_CLKSTOP, mask_sh),\ + HWS_SF(, DMU_CLK_CNTL, DCFCLK_ALLOW_DS_CLKSTOP, mask_sh),\ + HWS_SF(, DMU_CLK_CNTL, DPIACLK_ALLOW_DS_CLKSTOP, mask_sh),\ + HWS_SF(, DMU_CLK_CNTL, LONO_FGCG_REP_DIS, mask_sh),\ + HWS_SF(, DMU_CLK_CNTL, LONO_DISPCLK_GATE_DISABLE, mask_sh),\ + HWS_SF(, DMU_CLK_CNTL, LONO_SOCCLK_GATE_DISABLE, mask_sh),\ + HWS_SF(, DMU_CLK_CNTL, LONO_DMCUBCLK_GATE_DISABLE, mask_sh),\ + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKA_FE_GATE_DISABLE, mask_sh), \ + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKB_FE_GATE_DISABLE, mask_sh), \ + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKC_FE_GATE_DISABLE, mask_sh), \ + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKD_FE_GATE_DISABLE, mask_sh), \ + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKE_FE_GATE_DISABLE, mask_sh), \ + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, HDMICHARCLK0_GATE_DISABLE, mask_sh), \ + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKA_GATE_DISABLE, mask_sh), \ + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKB_GATE_DISABLE, mask_sh), \ + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKC_GATE_DISABLE, mask_sh), \ + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKD_GATE_DISABLE, mask_sh), \ + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKE_GATE_DISABLE, mask_sh), \ + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYASYMCLK_ROOT_GATE_DISABLE, mask_sh), \ + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYBSYMCLK_ROOT_GATE_DISABLE, mask_sh), \ + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYCSYMCLK_ROOT_GATE_DISABLE, mask_sh), \ + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYDSYMCLK_ROOT_GATE_DISABLE, mask_sh), \ + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYESYMCLK_ROOT_GATE_DISABLE, mask_sh),\ + HWS_SF(, DCCG_GATE_DISABLE_CNTL5, DTBCLK_P0_GATE_DISABLE, mask_sh),\ + HWS_SF(, DCCG_GATE_DISABLE_CNTL5, DTBCLK_P1_GATE_DISABLE, mask_sh),\ + HWS_SF(, DCCG_GATE_DISABLE_CNTL5, DTBCLK_P2_GATE_DISABLE, mask_sh),\ + HWS_SF(, DCCG_GATE_DISABLE_CNTL5, DTBCLK_P3_GATE_DISABLE, mask_sh),\ + HWS_SF(, DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK0_GATE_DISABLE, mask_sh),\ + HWS_SF(, DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK1_GATE_DISABLE, mask_sh),\ + HWS_SF(, DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK2_GATE_DISABLE, mask_sh),\ + HWS_SF(, DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK3_GATE_DISABLE, mask_sh),\ + HWS_SF(, DCCG_GATE_DISABLE_CNTL4, DPIASYMCLK0_GATE_DISABLE, mask_sh),\ + HWS_SF(, DCCG_GATE_DISABLE_CNTL4, DPIASYMCLK1_GATE_DISABLE, mask_sh),\ + HWS_SF(, DCCG_GATE_DISABLE_CNTL4, DPIASYMCLK2_GATE_DISABLE, mask_sh),\ + HWS_SF(, DCCG_GATE_DISABLE_CNTL4, DPIASYMCLK3_GATE_DISABLE, mask_sh),\ + HWS_SF(, DCCG_GATE_DISABLE_CNTL4, DPIASYMCLK4_GATE_DISABLE, mask_sh),\ + HWS_SF(, DCCG_GATE_DISABLE_CNTL4, DPIASYMCLK5_GATE_DISABLE, mask_sh) + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCN42_MASK_SH_LIST(__SHIFT)}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCN42_MASK_SH_LIST(_MASK)}; + +#define vmid_regs_init(id) \ + DCN20_VMID_REG_LIST_RI(id) + +static struct dcn_vmid_registers vmid_regs[16]; + +static const struct dcn20_vmid_shift vmid_shifts = { + DCN20_VMID_MASK_SH_LIST(__SHIFT)}; + +static const struct dcn20_vmid_mask vmid_masks = { + DCN20_VMID_MASK_SH_LIST(_MASK)}; + +static const struct resource_caps res_cap_dcn42 = { + .num_timing_generator = 4, + .num_opp = 4, + .num_dpp = 4, + .num_video_plane = 4, + .num_audio = 5, + .num_stream_encoder = 5, + .num_dig_link_enc = 5, + .num_usb4_dpia = 6, + .num_hpo_dp_stream_encoder = 4, + .num_hpo_dp_link_encoder = 4, + .num_pll = 5, + .num_dwb = 1, + .num_ddc = 5, + .num_vmid = 16, + .num_mpc_3dlut = 2, + .num_dsc = 4, + .num_rmcm = 2, +}; + +static const struct dc_plane_cap plane_cap = { + .type = DC_PLANE_TYPE_DCN_UNIVERSAL, + .per_pixel_alpha = true, + + .pixel_format_support = { + .argb8888 = true, + .nv12 = true, + .fp16 = true, + .p010 = true, + .ayuv = false, + }, + + .max_upscale_factor = {.argb8888 = 16000, .nv12 = 16000, .fp16 = 16000}, + + // 6:1 downscaling ratio: 1000/6 = 166.666 + .max_downscale_factor = {.argb8888 = 167, .nv12 = 167, .fp16 = 167}, + + .min_width = 64, + .min_height = 64}; + +static const struct dc_debug_options debug_defaults_drv = { + .disable_dmcu = true, + .force_abm_enable = false, + .clock_trace = true, + .disable_pplib_clock_request = false, + .disable_dpp_power_gate = true, + .disable_hubp_power_gate = true, + .disable_optc_power_gate = true, + .pipe_split_policy = MPC_SPLIT_AVOID, + .force_single_disp_pipe_split = false, + .disable_dcc = DCC_ENABLE, + .vsr_support = true, + .performance_trace = false, + .max_downscale_src_width = 4096, /*up to 4K for APU*/ + .disable_pplib_wm_range = false, + .scl_reset_length10 = true, + .sanity_checks = false, + .underflow_assert_delay_us = 0xFFFFFFFF, + .dwb_fi_phase = -1, // -1 = disable, + .dmub_command_table = true, + .pstate_enabled = true, + .enable_mem_low_power = { + .bits = { + .vga = false, + .i2c = true, + .dscl = true, + .cm = true, + .mpc = true, + .optc = true, + .vpg = true, + }}, + .root_clock_optimization = { + .bits = { + .dpp = true, + .dsc = true,/*dscclk and dsc pg*/ + .hdmistream = false, + .hdmichar = true, + .dpstream = true, + .symclk32_se = true, + .symclk32_le = true, + .symclk_fe = true, + .physymclk = false, + .dpiasymclk = true, + } + }, + .seamless_boot_odm_combine = DML_FAIL_SOURCE_PIXEL_FORMAT, + .enable_z9_disable_interface = true, /* Allow support for the PMFW interface for disable Z9*/ + .minimum_z8_residency_time = 1, /* Always allow when other conditions are met */ + .support_eDP1_5 = true, + .use_max_lb = true, + .force_disable_subvp = false, + .exit_idle_opt_for_cursor_updates = true, + .using_dml2 = true, + .using_dml21 = true, + .enable_single_display_2to1_odm_policy = true, + + // must match enable_single_display_2to1_odm_policy to support dynamic ODM transitions + .enable_double_buffered_dsc_pg_support = true, + .enable_dp_dig_pixel_rate_div_policy = 1, + .allow_sw_cursor_fallback = false, + .psp_disabled_wa = true, + .alloc_extra_way_for_cursor = true, + .min_prefetch_in_strobe_ns = 60000, // 60us + .disable_unbounded_requesting = false, + .dcc_meta_propagation_delay_us = 10, + .disable_timeout = true, + .min_disp_clk_khz = 50000, + .static_screen_wait_frames = 2, + .disable_z10 = false, + .ignore_pg = true, + .disable_stutter_for_wm_program = true, + .min_deep_sleep_dcfclk_khz = 8000, + .replay_skip_crtc_disabled = true, + .psr_skip_crtc_disable = true, +}; + +static const struct dc_check_config config_defaults = { + .enable_legacy_fast_update = false, +}; + +static struct dce_aux *dcn42_aux_engine_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct aux_engine_dce110 *aux_engine = + kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); + + if (!aux_engine) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT aux_engine_regs + aux_engine_regs_init(0), + aux_engine_regs_init(1), + aux_engine_regs_init(2), + aux_engine_regs_init(3), + aux_engine_regs_init(4); + + dce110_aux_engine_construct(aux_engine, ctx, inst, + SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, + &aux_engine_regs[inst], + &aux_mask, + &aux_shift, + ctx->dc->caps.extended_aux_timeout_support); + + return &aux_engine->base; +} + +#define i2c_inst_regs_init(id) \ + I2C_HW_ENGINE_COMMON_REG_LIST_DCN30_RI(id) + +static struct dce_i2c_registers i2c_hw_regs[5]; + +static const struct dce_i2c_shift i2c_shifts = { + I2C_COMMON_MASK_SH_LIST_DCN35(__SHIFT) +}; +static const struct dce_i2c_mask i2c_masks = { + I2C_COMMON_MASK_SH_LIST_DCN35(_MASK) +}; + +/* ========================================================== */ + +/* + * DPIA index | Preferred Encoder | Host Router + * 0 | C | 0 + * 1 | First Available | 0 + * 2 | D | 1 + * 3 | First Available | 1 + * 4 | E | 2 + * 5 | First Available | 2 + */ +/* ========================================================== */ +static const enum engine_id dpia_to_preferred_enc_id_table[] = { + ENGINE_ID_DIGC, + ENGINE_ID_DIGC, + ENGINE_ID_DIGD, + ENGINE_ID_DIGD, + ENGINE_ID_DIGE, + ENGINE_ID_DIGE +}; + +static enum engine_id dcn42_get_preferred_eng_id_dpia(unsigned int dpia_index) +{ + return dpia_to_preferred_enc_id_table[dpia_index]; +} + +static struct dce_i2c_hw *dcn42_i2c_hw_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_i2c_hw *dce_i2c_hw = + kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); + + if (!dce_i2c_hw) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT i2c_hw_regs + i2c_inst_regs_init(1), + i2c_inst_regs_init(2), + i2c_inst_regs_init(3), + i2c_inst_regs_init(4), + i2c_inst_regs_init(5); + dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, + &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); + + return dce_i2c_hw; +} + +static struct clock_source *dcn42_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); + + if (!clk_src) + return NULL; + + if (dcn401_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + kfree(clk_src); + BREAK_TO_DEBUGGER(); + return NULL; +} + +static struct hubbub *dcn42_hubbub_create(struct dc_context *ctx) +{ + int i; + + struct dcn20_hubbub *hubbub3 = kzalloc(sizeof(struct dcn20_hubbub), + GFP_KERNEL); + + if (!hubbub3) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT hubbub_reg + hubbub_reg_init(); + +#undef REG_STRUCT +#define REG_STRUCT vmid_regs + vmid_regs_init(0), + vmid_regs_init(1), + vmid_regs_init(2), + vmid_regs_init(3), + vmid_regs_init(4), + vmid_regs_init(5), + vmid_regs_init(6), + vmid_regs_init(7), + vmid_regs_init(8), + vmid_regs_init(9), + vmid_regs_init(10), + vmid_regs_init(11), + vmid_regs_init(12), + vmid_regs_init(13), + vmid_regs_init(14), + vmid_regs_init(15); + + hubbub42_construct(hubbub3, ctx, + &hubbub_reg, + &hubbub_shift, + &hubbub_mask, + DCN42_DEFAULT_DET_SIZE, + 8, + DCN42_CRB_SIZE_KB); + for (i = 0; i < res_cap_dcn42.num_vmid; i++) { + struct dcn20_vmid *vmid = &hubbub3->vmid[i]; + + vmid->ctx = ctx; + + vmid->regs = &vmid_regs[i]; + vmid->shifts = &vmid_shifts; + vmid->masks = &vmid_masks; + } + + return &hubbub3->base; +} + +static struct hubp *dcn42_hubp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn20_hubp *hubp2 = + kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL); + + if (!hubp2) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT hubp_regs + hubp_regs_init(0), + hubp_regs_init(1), + hubp_regs_init(2), + hubp_regs_init(3); + + if (hubp42_construct(hubp2, ctx, inst, + &hubp_regs[inst], &hubp_shift, &hubp_mask)) + return &hubp2->base; + + BREAK_TO_DEBUGGER(); + kfree(hubp2); + return NULL; +} +static const struct dc_panel_config dcn42_panel_config_defaults = { + .psr = { + .disable_psr = false, + .disallow_psrsu = false, + .disallow_replay = false, + }, + .ilr = { + .optimize_edp_link_rate = true, + }, +}; + +static void dcn42_dpp_destroy(struct dpp **dpp) +{ + kfree(TO_DCN42_DPP(*dpp)); + *dpp = NULL; +} + +static struct dpp *dcn42_dpp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn42_dpp *dpp42 = + kzalloc(sizeof(struct dcn42_dpp), GFP_KERNEL); + + if (!dpp42) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT dpp_regs + dpp_regs_init(0), + dpp_regs_init(1), + dpp_regs_init(2), + dpp_regs_init(3); + + if (dpp42_construct(dpp42, ctx, inst, + &dpp_regs[inst], &tf_shift, &tf_mask)) + return &dpp42->base; + + BREAK_TO_DEBUGGER(); + kfree(dpp42); + return NULL; +} + +static struct mpc *dcn42_mpc_create( + struct dc_context *ctx, + int num_mpcc, + int num_rmu) +{ + struct dcn42_mpc *mpc401 = kzalloc(sizeof(struct dcn42_mpc), + GFP_KERNEL); + + if (!mpc401) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT mpc_regs + dcn_mpc_regs_init(); + + dcn42_mpc_construct(mpc401, ctx, + &mpc_regs, + &mpc_shift, + &mpc_mask, + num_mpcc, + num_rmu); + + return &mpc401->base; +} + +static struct output_pixel_processor *dcn42_opp_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn20_opp *opp4 = + kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL); + + if (!opp4) { + BREAK_TO_DEBUGGER(); + return NULL; + } + +#undef REG_STRUCT +#define REG_STRUCT opp_regs + opp_regs_init(0), + opp_regs_init(1), + opp_regs_init(2), + opp_regs_init(3); + dcn20_opp_construct(opp4, ctx, inst, + &opp_regs[inst], &opp_shift, &opp_mask); + return &opp4->base; +} + +static struct timing_generator *dcn42_timing_generator_create( + struct dc_context *ctx, + uint32_t instance) +{ + struct optc *tgn10 = + kzalloc(sizeof(struct optc), GFP_KERNEL); + + if (!tgn10) + return NULL; +#undef REG_STRUCT +#define REG_STRUCT optc_regs + optc_regs_init(0), + optc_regs_init(1), + optc_regs_init(2), + optc_regs_init(3); + tgn10->base.inst = instance; + tgn10->base.ctx = ctx; + + tgn10->tg_regs = &optc_regs[instance]; + tgn10->tg_shift = &optc_shift; + tgn10->tg_mask = &optc_mask; + + dcn42_timing_generator_init(tgn10); + + return &tgn10->base; +} + +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 600000, + .hdmi_ycbcr420_supported = true, + .dp_ycbcr420_supported = true, + .fec_supported = true, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_HBR3_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true, + .flags.bits.IS_TPS4_CAPABLE = true}; + +static struct link_encoder *dcn42_link_encoder_create( + struct dc_context *ctx, + const struct encoder_init_data *enc_init_data) +{ + struct dcn20_link_encoder *enc20 = + kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); + + if (!enc20 || enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs)) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT link_enc_aux_regs + aux_regs_init(0), + aux_regs_init(1), + aux_regs_init(2), + aux_regs_init(3), + aux_regs_init(4); +#undef REG_STRUCT +#define REG_STRUCT link_enc_hpd_regs + hpd_regs_init(0), + hpd_regs_init(1), + hpd_regs_init(2), + hpd_regs_init(3), + hpd_regs_init(4); +#undef REG_STRUCT +#define REG_STRUCT link_enc_regs + link_regs_init(0, A), + link_regs_init(1, B), + link_regs_init(2, C), + link_regs_init(3, D), + link_regs_init(4, E); + + dcn42_link_encoder_construct(enc20, + enc_init_data, + &link_enc_feature, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source], + &le_shift, + &le_mask); + return &enc20->enc10.base; +} + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + generic_reg_get(ctx, regDC_PINSTRAPS + BASE(regDC_PINSTRAPS_BASE_IDX), + FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); +} + +static struct audio *dcn42_create_audio( + struct dc_context *ctx, unsigned int inst) +{ + +#undef REG_STRUCT +#define REG_STRUCT audio_regs + audio_regs_init(0), + audio_regs_init(1), + audio_regs_init(2), + audio_regs_init(3), + audio_regs_init(4); + + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + +static struct vpg *dcn42_vpg_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn31_vpg *vpg4 = kzalloc(sizeof(struct dcn31_vpg), GFP_KERNEL); + + if (!vpg4) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT vpg_regs + vpg_regs_init(0), + vpg_regs_init(1), + vpg_regs_init(2), + vpg_regs_init(3), + vpg_regs_init(4), + vpg_regs_init(5), + vpg_regs_init(6), + vpg_regs_init(7), + vpg_regs_init(8), + vpg_regs_init(9); + vpg31_construct(vpg4, ctx, inst, + &vpg_regs[inst], + &vpg_shift, + &vpg_mask); + + return &vpg4->base; +} + +static struct apg *dcn42_apg_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn31_apg *apg31 = kzalloc(sizeof(struct dcn31_apg), GFP_KERNEL); + + if (!apg31) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT apg_regs + apg_regs_init(0), + apg_regs_init(1), + apg_regs_init(2), + apg_regs_init(3), + apg_regs_init(4), + apg_regs_init(5), + apg_regs_init(6), + apg_regs_init(7), + apg_regs_init(8), + apg_regs_init(9); + + apg31_construct(apg31, ctx, inst, + &apg_regs[inst], + &apg_shift, + &apg_mask); + + return &apg31->base; +} + +static struct stream_encoder *dcn42_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dcn10_stream_encoder *enc1; + struct vpg *vpg; + struct apg *apg; + + uint32_t vpg_inst; + uint32_t apg_inst; + + /* Mapping of VPG, DME register blocks to DIO block instance */ + if (eng_id <= ENGINE_ID_DIGE) { + vpg_inst = eng_id; + apg_inst = eng_id; + } else + return NULL; + + enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); + vpg = dcn42_vpg_create(ctx, vpg_inst); + apg = dcn42_apg_create(ctx, apg_inst); + + if (!enc1 || !vpg || !apg) { + kfree(enc1); + kfree(vpg); + kfree(apg); + return NULL; + } +#undef REG_STRUCT +#define REG_STRUCT stream_enc_regs + stream_enc_regs_init(0), + stream_enc_regs_init(1), + stream_enc_regs_init(2), + stream_enc_regs_init(3), + stream_enc_regs_init(4); + + dcn42_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, + eng_id, vpg, apg, + &stream_enc_regs[eng_id], + &se_shift, &se_mask); + return &enc1->base; +} + +static struct hpo_dp_stream_encoder *dcn42_hpo_dp_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dcn31_hpo_dp_stream_encoder *hpo_dp_enc31; + struct vpg *vpg; + struct apg *apg; + uint32_t hpo_dp_inst; + uint32_t vpg_inst; + uint32_t apg_inst; + + ASSERT((eng_id >= ENGINE_ID_HPO_DP_0) && (eng_id <= ENGINE_ID_HPO_DP_3)); + hpo_dp_inst = eng_id - ENGINE_ID_HPO_DP_0; + + /* Mapping of VPG register blocks to HPO DP block instance: + * VPG[5] -> HPO_DP[0] + * VPG[6] -> HPO_DP[1] + * VPG[7] -> HPO_DP[2] + * VPG[8] -> HPO_DP[3] + */ + vpg_inst = hpo_dp_inst + 5; + + /* Mapping of APG register blocks to HPO DP block instance: + * APG[6] -> HPO_DP[0] + * APG[7] -> HPO_DP[1] + * APG[8] -> HPO_DP[2] + * APG[9] -> HPO_DP[3] + */ + apg_inst = hpo_dp_inst + 5; + + /* allocate HPO stream encoder and create VPG sub-block */ + hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_stream_encoder), GFP_KERNEL); + vpg = dcn42_vpg_create(ctx, vpg_inst); + apg = dcn42_apg_create(ctx, apg_inst); + + if (!hpo_dp_enc31 || !vpg || !apg) { + kfree(hpo_dp_enc31); + kfree(vpg); + kfree(apg); + return NULL; + } + +#undef REG_STRUCT +#define REG_STRUCT hpo_dp_stream_enc_regs + hpo_dp_stream_encoder_reg_init(0), + hpo_dp_stream_encoder_reg_init(1), + hpo_dp_stream_encoder_reg_init(2), + hpo_dp_stream_encoder_reg_init(3); + + dcn31_hpo_dp_stream_encoder_construct(hpo_dp_enc31, ctx, ctx->dc_bios, + hpo_dp_inst, eng_id, vpg, apg, + &hpo_dp_stream_enc_regs[hpo_dp_inst], + &hpo_dp_se_shift, &hpo_dp_se_mask); + + return &hpo_dp_enc31->base; +} + +static struct hpo_dp_link_encoder *dcn42_hpo_dp_link_encoder_create( + uint8_t inst, + struct dc_context *ctx) +{ + struct dcn31_hpo_dp_link_encoder *hpo_dp_enc31; + + /* allocate HPO link encoder */ + hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL); + if (!hpo_dp_enc31) + return NULL; /* out of memory */ + +#undef REG_STRUCT +#define REG_STRUCT hpo_dp_link_enc_regs + hpo_dp_link_encoder_reg_init(0), + hpo_dp_link_encoder_reg_init(1), + hpo_dp_link_encoder_reg_init(2), + hpo_dp_link_encoder_reg_init(3); + + hpo_dp_link_encoder42_construct(hpo_dp_enc31, ctx, inst, + &hpo_dp_link_enc_regs[inst], + &hpo_dp_le_shift, &hpo_dp_le_mask); + + return &hpo_dp_enc31->base; +} + +static struct dce_hwseq *dcn42_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); + +#undef REG_STRUCT +#define REG_STRUCT hwseq_reg + hwseq_reg_init(); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + } + + return hws; +} + +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = dcn42_create_audio, + .create_stream_encoder = dcn42_stream_encoder_create, + .create_hpo_dp_stream_encoder = dcn42_hpo_dp_stream_encoder_create, + .create_hpo_dp_link_encoder = dcn42_hpo_dp_link_encoder_create, + .create_hwseq = dcn42_hwseq_create, +}; + +static void dcn42_dsc_destroy(struct display_stream_compressor **dsc) +{ + kfree(container_of(*dsc, struct dcn401_dsc, base)); + *dsc = NULL; +} + +static void dcn42_resource_destruct(struct dcn42_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) { + if (pool->base.stream_enc[i]->vpg != NULL) { + kfree(DCN31_VPG_FROM_VPG(pool->base.stream_enc[i]->vpg)); + pool->base.stream_enc[i]->vpg = NULL; + } + if (pool->base.stream_enc[i]->apg != NULL) { + kfree(DCN31_APG_FROM_APG(pool->base.stream_enc[i]->apg)); + pool->base.stream_enc[i]->apg = NULL; + } + kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i])); + pool->base.stream_enc[i] = NULL; + } + } + + for (i = 0; i < pool->base.hpo_dp_stream_enc_count; i++) { + if (pool->base.hpo_dp_stream_enc[i] != NULL) { + if (pool->base.hpo_dp_stream_enc[i]->vpg != NULL) { + kfree(DCN31_VPG_FROM_VPG(pool->base.hpo_dp_stream_enc[i]->vpg)); + pool->base.hpo_dp_stream_enc[i]->vpg = NULL; + } + if (pool->base.hpo_dp_stream_enc[i]->apg != NULL) { + kfree(DCN31_APG_FROM_APG(pool->base.hpo_dp_stream_enc[i]->apg)); + pool->base.hpo_dp_stream_enc[i]->apg = NULL; + } + kfree(DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(pool->base.hpo_dp_stream_enc[i])); + pool->base.hpo_dp_stream_enc[i] = NULL; + } + } + + for (i = 0; i < pool->base.hpo_dp_link_enc_count; i++) { + if (pool->base.hpo_dp_link_enc[i] != NULL) { + kfree(DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(pool->base.hpo_dp_link_enc[i])); + pool->base.hpo_dp_link_enc[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_dsc; i++) { + if (pool->base.dscs[i] != NULL) + dcn42_dsc_destroy(&pool->base.dscs[i]); + } + + if (pool->base.mpc != NULL) { + kfree(TO_DCN20_MPC(pool->base.mpc)); + pool->base.mpc = NULL; + } + if (pool->base.hubbub != NULL) { + kfree(TO_DCN20_HUBBUB(pool->base.hubbub)); + pool->base.hubbub = NULL; + } + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.dpps[i] != NULL) + dcn42_dpp_destroy(&pool->base.dpps[i]); + + if (pool->base.ipps[i] != NULL) + pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.hubps[i] != NULL) { + kfree(TO_DCN20_HUBP(pool->base.hubps[i])); + pool->base.hubps[i] = NULL; + } + + if (pool->base.irqs != NULL) + dal_irq_service_destroy(&pool->base.irqs); + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + if (pool->base.engines[i] != NULL) + dce110_engine_destroy(&pool->base.engines[i]); + if (pool->base.hw_i2cs[i] != NULL) { + kfree(pool->base.hw_i2cs[i]); + pool->base.hw_i2cs[i] = NULL; + } + if (pool->base.sw_i2cs[i] != NULL) { + kfree(pool->base.sw_i2cs[i]); + pool->base.sw_i2cs[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_opp; i++) { + if (pool->base.opps[i] != NULL) + pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); + } + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + if (pool->base.timing_generators[i] != NULL) { + kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_dwb; i++) { + if (pool->base.dwbc[i] != NULL) { + kfree(TO_DCN30_DWBC(pool->base.dwbc[i])); + pool->base.dwbc[i] = NULL; + } + if (pool->base.mcif_wb[i] != NULL) { + kfree(TO_DCN30_MMHUBBUB(pool->base.mcif_wb[i])); + pool->base.mcif_wb[i] = NULL; + } + } + + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i]) + dce_aud_destroy(&pool->base.audios[i]); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) { + dcn20_clock_source_destroy(&pool->base.clock_sources[i]); + pool->base.clock_sources[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_mpc_3dlut; i++) { + if (pool->base.mpc_lut[i] != NULL) { + dc_3dlut_func_release(pool->base.mpc_lut[i]); + pool->base.mpc_lut[i] = NULL; + } + if (pool->base.mpc_shaper[i] != NULL) { + dc_transfer_func_release(pool->base.mpc_shaper[i]); + pool->base.mpc_shaper[i] = NULL; + } + } + + if (pool->base.dp_clock_source != NULL) { + dcn20_clock_source_destroy(&pool->base.dp_clock_source); + pool->base.dp_clock_source = NULL; + } + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + if (pool->base.multiple_abms[i] != NULL) + dce_abm_destroy(&pool->base.multiple_abms[i]); + } + + if (pool->base.psr != NULL) + dmub_psr_destroy(&pool->base.psr); + + if (pool->base.pg_cntl != NULL) + dcn_pg_cntl_destroy(&pool->base.pg_cntl); + if (pool->base.dccg != NULL) + dcn_dccg_destroy(&pool->base.dccg); + + if (pool->base.oem_device != NULL) { + struct dc *dc = pool->base.oem_device->ctx->dc; + + dc->link_srv->destroy_ddc_service(&pool->base.oem_device); + } +} + +static void dcn42_build_pipe_pix_clk_params(struct pipe_ctx *pipe_ctx) +{ + const struct dc_stream_state *stream = pipe_ctx->stream; + struct dc_link *link = stream->link; + struct link_encoder *link_enc = pipe_ctx->link_res.dio_link_enc; + struct pixel_clk_params *pixel_clk_params = &pipe_ctx->stream_res.pix_clk_params; + + pixel_clk_params->requested_pix_clk_100hz = stream->timing.pix_clk_100hz; + + if (pipe_ctx->dsc_padding_params.dsc_hactive_padding != 0) + pixel_clk_params->requested_pix_clk_100hz = pipe_ctx->dsc_padding_params.dsc_pix_clk_100hz; + + if (!pipe_ctx->stream->ctx->dc->config.unify_link_enc_assignment) + link_enc = link_enc_cfg_get_link_enc(link); + if (link_enc) + pixel_clk_params->encoder_object_id = link_enc->id; + + pixel_clk_params->signal_type = pipe_ctx->stream->signal; + pixel_clk_params->controller_id = pipe_ctx->stream_res.tg->inst + 1; + /* TODO: un-hardcode*/ + + /* TODO - DP2.0 HW: calculate requested_sym_clk for UHBR rates */ + + pixel_clk_params->requested_sym_clk = LINK_RATE_LOW * + LINK_RATE_REF_FREQ_IN_KHZ; + pixel_clk_params->flags.ENABLE_SS = 0; + pixel_clk_params->color_depth = + stream->timing.display_color_depth; + pixel_clk_params->flags.DISPLAY_BLANKED = 1; + pixel_clk_params->pixel_encoding = stream->timing.pixel_encoding; + + if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) + pixel_clk_params->color_depth = COLOR_DEPTH_888; + + if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING) + pixel_clk_params->requested_pix_clk_100hz *= 2; + if (dc_is_tmds_signal(stream->signal) && + stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) + pixel_clk_params->requested_pix_clk_100hz /= 2; + + pipe_ctx->clock_source->funcs->get_pix_clk_dividers( + pipe_ctx->clock_source, + &pipe_ctx->stream_res.pix_clk_params, + &pipe_ctx->pll_settings); + + pixel_clk_params->dio_se_pix_per_cycle = 1; + if (dc_is_tmds_signal(stream->signal) && + stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) { + pixel_clk_params->dio_se_pix_per_cycle = 2; + } else if (dc_is_dp_signal(stream->signal)) { + /* round up to nearest power of 2, or max at 8 pixels per cycle */ + if (pixel_clk_params->requested_pix_clk_100hz > 4 * stream->ctx->dc->clk_mgr->dprefclk_khz * 10) { + pixel_clk_params->dio_se_pix_per_cycle = 8; + } else if (pixel_clk_params->requested_pix_clk_100hz > 2 * stream->ctx->dc->clk_mgr->dprefclk_khz * 10) { + pixel_clk_params->dio_se_pix_per_cycle = 4; + } else if (pixel_clk_params->requested_pix_clk_100hz > stream->ctx->dc->clk_mgr->dprefclk_khz * 10) { + pixel_clk_params->dio_se_pix_per_cycle = 2; + } else { + pixel_clk_params->dio_se_pix_per_cycle = 1; + } + } +} + +static bool dcn42_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t dwb_count = pool->res_cap->num_dwb; + + for (i = 0; i < dwb_count; i++) { + struct dcn30_dwbc *dwbc42 = kzalloc(sizeof(struct dcn30_dwbc), + GFP_KERNEL); + + if (!dwbc42) { + dm_error("DC: failed to create dwbc42!\n"); + return false; + } + +#undef REG_STRUCT +#define REG_STRUCT dwbc401_regs + dwbc_regs_dcn401_init(0); + + dcn30_dwbc_construct(dwbc42, ctx, + &dwbc401_regs[i], + &dwbc401_shift, + &dwbc401_mask, + i); + + pool->dwbc[i] = &dwbc42->base; + } + return true; +} + +static void dcn42_mmhubbub_init(struct dcn30_mmhubbub *mcif_wb30, + struct dc_context *ctx) +{ + dcn42_mmhubbub_set_fgcg( + mcif_wb30, + ctx->dc->debug.enable_fine_grain_clock_gating.bits.mmhubbub); +} + +static bool dcn42_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t pipe_count = pool->res_cap->num_dwb; + + for (i = 0; i < pipe_count; i++) { + struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub), + GFP_KERNEL); + + if (!mcif_wb30) { + dm_error("DC: failed to create mcif_wb30!\n"); + return false; + } + +#undef REG_STRUCT +#define REG_STRUCT mcif_wb35_regs + mcif_wb_regs_dcn3_init(0); + + dcn35_mmhubbub_construct(mcif_wb30, ctx, + &mcif_wb35_regs[i], + &mcif_wb35_shift, + &mcif_wb35_mask, + i); + + dcn42_mmhubbub_init(mcif_wb30, ctx); + + pool->mcif_wb[i] = &mcif_wb30->base; + } + return true; +} + +static struct display_stream_compressor *dcn42_dsc_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn401_dsc *dsc = + kzalloc(sizeof(struct dcn401_dsc), GFP_KERNEL); + + if (!dsc) { + BREAK_TO_DEBUGGER(); + return NULL; + } + +#undef REG_STRUCT +#define REG_STRUCT dsc_regs + dsc_regs_init(0), + dsc_regs_init(1), + dsc_regs_init(2), + dsc_regs_init(3); + + dsc401_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask); + dsc401_set_fgcg(dsc, ctx->dc->debug.enable_fine_grain_clock_gating.bits.dsc); + + dsc->max_image_width = 5760; + + return &dsc->base; +} + +static void dcn42_destroy_resource_pool(struct resource_pool **pool) +{ + struct dcn42_resource_pool *dcn42_pool = TO_DCN42_RES_POOL(*pool); + + dcn42_resource_destruct(dcn42_pool); + kfree(dcn42_pool); + *pool = NULL; +} + +static struct dc_cap_funcs cap_funcs = { + .get_dcc_compression_cap = dcn20_get_dcc_compression_cap}; + +static void dcn42_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_params) +{ + (void)bw_params; + dc_assert_fp_enabled(); + + if (dc->current_state && dc->current_state->bw_ctx.dml2) + dml2_reinit(dc, &dc->dml2_options, &dc->current_state->bw_ctx.dml2); +} + +static void dcn42_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) +{ + DC_FP_START(); + dcn42_update_bw_bounding_box_fpu(dc, bw_params); + DC_FP_END(); +} +enum dc_status dcn42_validate_bandwidth(struct dc *dc, + struct dc_state *context, + enum dc_validate_mode validate_mode) +{ + bool out = false; + + DC_FP_START(); + + out = dml2_validate(dc, context, context->bw_ctx.dml2, + validate_mode); + + if (validate_mode == DC_VALIDATE_MODE_AND_PROGRAMMING) { + /*not required for mode enumeration*/ + dcn42_decide_zstate_support(dc, context); + } + + DC_FP_END(); + + return out ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE; +} +void dcn42_prepare_mcache_programming(struct dc *dc, + struct dc_state *context) +{ + if (dc->debug.using_dml21) { + DC_FP_START(); + dml2_prepare_mcache_programming(dc, context, + context->power_source == DC_POWER_SOURCE_DC ? + context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2); + DC_FP_END(); + } +} +/* Create a minimal link encoder object not associated with a particular + * physical connector. + * resource_funcs.link_enc_create_minimal + */ +static struct link_encoder *dcn42_link_enc_create_minimal( + struct dc_context *ctx, enum engine_id eng_id) +{ + struct dcn20_link_encoder *enc20; + + if ((eng_id - ENGINE_ID_DIGA) > ctx->dc->res_pool->res_cap->num_dig_link_enc) + return NULL; + + enc20 = kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); + if (!enc20) + return NULL; + + dcn31_link_encoder_construct_minimal( + enc20, + ctx, + &link_enc_feature, + &link_enc_regs[eng_id - ENGINE_ID_DIGA], + eng_id); + + return &enc20->enc10.base; +} +static void dcn42_get_panel_config_defaults(struct dc_panel_config *panel_config) +{ + *panel_config = dcn42_panel_config_defaults; +} +static unsigned int dcn42_get_max_hw_cursor_size(const struct dc *dc, + struct dc_state *state, + const struct dc_stream_state *stream) +{ + (void)state; + (void)stream; + return dc->caps.max_cursor_size; +} +static struct resource_funcs dcn42_res_pool_funcs = { + .destroy = dcn42_destroy_resource_pool, + .link_enc_create = dcn42_link_encoder_create, + .link_enc_create_minimal = dcn42_link_enc_create_minimal, + .link_encs_assign = link_enc_cfg_link_encs_assign, + .link_enc_unassign = link_enc_cfg_link_enc_unassign, + .panel_cntl_create = dcn32_panel_cntl_create, + .validate_bandwidth = dcn42_validate_bandwidth, + .calculate_wm_and_dlg = NULL, + .populate_dml_pipes = NULL, + .acquire_free_pipe_as_secondary_dpp_pipe = dcn32_acquire_free_pipe_as_secondary_dpp_pipe, + .acquire_free_pipe_as_secondary_opp_head = dcn32_acquire_free_pipe_as_secondary_opp_head, + .release_pipe = dcn20_release_pipe, + .add_stream_to_ctx = dcn30_add_stream_to_ctx, + .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, + .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, + .populate_dml_writeback_from_context = dcn30_populate_dml_writeback_from_context, + .set_mcif_arb_params = dcn30_set_mcif_arb_params, + .find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link, + .acquire_post_bldn_3dlut = dcn32_acquire_post_bldn_3dlut, + .release_post_bldn_3dlut = dcn32_release_post_bldn_3dlut, + .update_bw_bounding_box = dcn42_update_bw_bounding_box, + .patch_unknown_plane_state = dcn35_patch_unknown_plane_state, + .get_panel_config_defaults = dcn42_get_panel_config_defaults, + .get_preferred_eng_id_dpia = dcn42_get_preferred_eng_id_dpia, + .update_soc_for_wm_a = dcn30_update_soc_for_wm_a, + .add_phantom_pipes = dcn32_add_phantom_pipes, + .calculate_mall_ways_from_bytes = dcn32_calculate_mall_ways_from_bytes, + .prepare_mcache_programming = dcn42_prepare_mcache_programming, + .build_pipe_pix_clk_params = dcn42_build_pipe_pix_clk_params, + .get_power_profile = dcn401_get_power_profile, + .get_vstartup_for_pipe = dcn401_get_vstartup_for_pipe, + .get_max_hw_cursor_size = dcn42_get_max_hw_cursor_size, + .get_default_tiling_info = dcn10_get_default_tiling_info +}; + +static uint32_t read_pipe_fuses(struct dc_context *ctx) +{ + uint32_t value = REG_READ(CC_DC_PIPE_DIS); + + if (value == 0 && ctx->dce_environment == DCE_ENV_DIAG) + value = 0xF; + /* DCN401 support max 4 pipes */ + value = value & 0xf; + return value; +} + +static bool dcn42_resource_construct( + uint8_t num_virtual_links, + struct dc *dc, + struct dcn42_resource_pool *pool) +{ + int i, j; + struct dc_context *ctx = dc->ctx; + struct irq_service_init_data init_data; + uint32_t pipe_fuses; + uint32_t num_pipes; + +#undef REG_STRUCT +#define REG_STRUCT bios_regs + bios_regs_init(); + +#undef REG_STRUCT +#define REG_STRUCT clk_src_regs + clk_src_regs_init(0, A), + clk_src_regs_init(1, B), + clk_src_regs_init(2, C), + clk_src_regs_init(3, D), + clk_src_regs_init(4, E); + +#undef REG_STRUCT +#define REG_STRUCT abm_regs + abm_regs_init(0), + abm_regs_init(1), + abm_regs_init(2), + abm_regs_init(3); +#undef REG_STRUCT +#define REG_STRUCT dccg_regs + dccg_regs_init(); + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = &res_cap_dcn42; + + /* max number of pipes for ASIC before checking for pipe fuses */ + num_pipes = pool->base.res_cap->num_dpp; + pipe_fuses = read_pipe_fuses(ctx); + + for (i = 0; i < pool->base.res_cap->num_dpp; i++) + if (pipe_fuses & 1 << i) + num_pipes--; + + if (pipe_fuses & 1) + ASSERT(0); // Unexpected - Pipe 0 should always be fully functional! + + if (pipe_fuses & CC_DC_PIPE_DIS__DC_FULL_DIS_MASK) + ASSERT(0); // Entire DCN is harvested! + + pool->base.funcs = &dcn42_res_pool_funcs; + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE; + pool->base.timing_generator_count = pool->base.res_cap->num_timing_generator; + pool->base.pipe_count = num_pipes; + pool->base.mpcc_count = num_pipes; + dc->caps.ips_v2_support = true; + dc->caps.max_downscale_ratio = 600; + dc->caps.i2c_speed_in_khz = 100; + dc->caps.i2c_speed_in_khz_hdcp = 100; /*1.4 w/a applied by default*/ + /* TODO: Bring max cursor size back to 256 after subvp cursor corruption is fixed*/ + dc->caps.max_cursor_size = 64; + dc->caps.max_buffered_cursor_size = 64; + dc->caps.cursor_not_scaled = true; + dc->caps.min_horizontal_blanking_period = 80; + dc->caps.dmdata_alloc_size = 2048; + dc->caps.mall_size_per_mem_channel = 4; + /* total size = mall per channel * num channels * 1024 * 1024 */ + dc->caps.mall_size_total = dc->caps.mall_size_per_mem_channel * + dc->ctx->dc_bios->vram_info.num_chans * 1048576; + dc->caps.cursor_cache_size = dc->caps.max_cursor_size * dc->caps.max_cursor_size * 8; + dc->caps.cache_line_size = 64; + dc->caps.cache_num_ways = 16; + + /* Calculate the available MALL space */ + dc->caps.max_cab_allocation_bytes = + dcn32_calc_num_avail_chans_for_mall(dc, dc->ctx->dc_bios->vram_info.num_chans) * + dc->caps.mall_size_per_mem_channel * 1024 * 1024; + dc->caps.mall_size_total = dc->caps.max_cab_allocation_bytes; + + dc->caps.subvp_fw_processing_delay_us = 15; + dc->caps.subvp_drr_max_vblank_margin_us = 40; + dc->caps.subvp_prefetch_end_to_mall_start_us = 15; + dc->caps.subvp_swath_height_margin_lines = 16; + dc->caps.subvp_pstate_allow_width_us = 20; + dc->caps.subvp_vertical_int_margin_us = 30; + dc->caps.subvp_drr_vblank_start_margin_us = 100; // 100us margin + + dc->caps.max_slave_planes = 2; + dc->caps.max_slave_yuv_planes = 2; + dc->caps.max_slave_rgb_planes = 2; + dc->caps.post_blend_color_processing = true; + dc->caps.force_dp_tps4_for_cp2520 = true; + if (dc->config.forceHBR2CP2520) + dc->caps.force_dp_tps4_for_cp2520 = false; + dc->caps.dp_hdmi21_pcon_support = true; + dc->caps.dp_hpo = true; + dc->caps.edp_dsc_support = true; + dc->caps.extended_aux_timeout_support = true; + dc->caps.dmcub_support = true; + dc->caps.is_apu = true; + dc->caps.seamless_odm = true; + dc->caps.zstate_support = true; + dc->caps.ips_support = true; + dc->caps.max_v_total = (1 << 15) - 1; + dc->caps.vtotal_limited_by_fp2 = true; + + dc->caps.seamless_odm = true; + dc->caps.zstate_support = true; + dc->caps.ips_support = true; + dc->caps.max_v_total = (1 << 15) - 1; + dc->caps.vtotal_limited_by_fp2 = true; + + /* Color pipeline capabilities */ + dc->caps.color.dpp.dcn_arch = 1; + dc->caps.color.dpp.input_lut_shared = 0; + dc->caps.color.dpp.icsc = 1; + dc->caps.color.dpp.dgam_ram = 0; // must use gamma_corr + dc->caps.color.dpp.dgam_rom_caps.srgb = 1; + dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; + dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 1; + dc->caps.color.dpp.dgam_rom_caps.pq = 1; + dc->caps.color.dpp.dgam_rom_caps.hlg = 1; + dc->caps.color.dpp.post_csc = 1; + dc->caps.color.dpp.gamma_corr = 1; + dc->caps.color.dpp.dgam_rom_for_yuv = 0; + + dc->caps.color.dpp.hw_3d_lut = 0; + dc->caps.color.dpp.ogam_ram = 0; + // no OGAM ROM on DCN2 and later ASICs + dc->caps.color.dpp.ogam_rom_caps.srgb = 0; + dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0; + dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.dpp.ogam_rom_caps.pq = 0; + dc->caps.color.dpp.ogam_rom_caps.hlg = 0; + dc->caps.color.dpp.ocsc = 0; + + dc->caps.color.mpc.gamut_remap = 1; + //configurable to be before or after BLND in MPCC + dc->caps.color.mpc.num_3dluts = pool->base.res_cap->num_mpc_3dlut; + dc->caps.color.mpc.num_rmcm_3dluts = 2; + dc->caps.color.mpc.ogam_ram = 1; + dc->caps.color.mpc.ogam_rom_caps.srgb = 0; + dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; + dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.mpc.ogam_rom_caps.pq = 0; + dc->caps.color.mpc.ogam_rom_caps.hlg = 0; + dc->caps.color.mpc.ocsc = 1; + dc->caps.color.mpc.preblend = true; + dc->caps.color.mpc.mcm_3d_lut_caps.dma_3d_lut = 1; + dc->caps.color.mpc.mcm_3d_lut_caps.lut_dim_caps.dim_9 = 1; + dc->caps.color.mpc.mcm_3d_lut_caps.lut_dim_caps.dim_17 = 1; + dc->caps.color.mpc.mcm_3d_lut_caps.mem_layout_support.linear_1d = 1; + dc->caps.color.mpc.mcm_3d_lut_caps.mem_layout_support.swizzle_3d_bgr = 1; + dc->caps.color.mpc.mcm_3d_lut_caps.mem_layout_support.swizzle_3d_rgb = 1; + dc->caps.color.mpc.mcm_3d_lut_caps.mem_format_support.unorm_12msb = 1; + dc->caps.color.mpc.mcm_3d_lut_caps.mem_format_support.unorm_12lsb = 1; + dc->caps.color.mpc.mcm_3d_lut_caps.mem_format_support.float_fp1_5_10 = 1; + dc->caps.color.mpc.mcm_3d_lut_caps.mem_pixel_order_support.order_rgba = 1; + dc->caps.color.mpc.mcm_3d_lut_caps.mem_pixel_order_support.order_bgra = 1; + dc->caps.color.mpc.rmcm_3d_lut_caps.dma_3d_lut = 1; + dc->caps.color.mpc.rmcm_3d_lut_caps.lut_dim_caps.dim_17 = 1; + dc->caps.color.mpc.rmcm_3d_lut_caps.lut_dim_caps.dim_33 = 1; + dc->caps.color.mpc.rmcm_3d_lut_caps.mem_layout_support.linear_1d = 1; + dc->caps.color.mpc.rmcm_3d_lut_caps.mem_layout_support.swizzle_3d_bgr = 1; + dc->caps.color.mpc.rmcm_3d_lut_caps.mem_layout_support.swizzle_3d_rgb = 1; + dc->caps.color.mpc.rmcm_3d_lut_caps.mem_format_support.unorm_12msb = 1; + dc->caps.color.mpc.rmcm_3d_lut_caps.mem_format_support.unorm_12lsb = 1; + dc->caps.color.mpc.rmcm_3d_lut_caps.mem_format_support.float_fp1_5_10 = 1; + dc->caps.color.mpc.rmcm_3d_lut_caps.mem_pixel_order_support.order_rgba = 1; + dc->caps.color.mpc.rmcm_3d_lut_caps.mem_pixel_order_support.order_bgra = 1; + + dc->caps.num_of_host_routers = 3; + dc->caps.num_of_dpias_per_host_router = 2; + + /* max_disp_clock_khz_at_vmin is slightly lower than the STA value in order + * to provide some margin. + * It's expected for furture ASIC to have equal or higher value, in order to + * have determinstic power improvement from generate to genration. + * (i.e., we should not expect new ASIC generation with lower vmin rate) + */ + dc->caps.max_disp_clock_khz_at_vmin = 650000; + dc->config.use_spl = true; + dc->config.prefer_easf = true; + + dc->config.dcn_sharpness_range.sdr_rgb_min = 0; + dc->config.dcn_sharpness_range.sdr_rgb_max = 1750; + dc->config.dcn_sharpness_range.sdr_rgb_mid = 750; + dc->config.dcn_sharpness_range.sdr_yuv_min = 0; + dc->config.dcn_sharpness_range.sdr_yuv_max = 3500; + dc->config.dcn_sharpness_range.sdr_yuv_mid = 1500; + dc->config.dcn_sharpness_range.hdr_rgb_min = 0; + dc->config.dcn_sharpness_range.hdr_rgb_max = 2750; + dc->config.dcn_sharpness_range.hdr_rgb_mid = 1500; + + dc->config.dcn_override_sharpness_range.sdr_rgb_min = 0; + dc->config.dcn_override_sharpness_range.sdr_rgb_max = 3250; + dc->config.dcn_override_sharpness_range.sdr_rgb_mid = 1250; + dc->config.dcn_override_sharpness_range.sdr_yuv_min = 0; + dc->config.dcn_override_sharpness_range.sdr_yuv_max = 3500; + dc->config.dcn_override_sharpness_range.sdr_yuv_mid = 1500; + dc->config.dcn_override_sharpness_range.hdr_rgb_min = 0; + dc->config.dcn_override_sharpness_range.hdr_rgb_max = 2750; + dc->config.dcn_override_sharpness_range.hdr_rgb_mid = 1500; + + dc->config.use_pipe_ctx_sync_logic = true; + dc->config.dc_mode_clk_limit_support = false; + dc->config.enable_windowed_mpo_odm = true; + /* Use psp mailbox to enable assr */ + dc->config.use_assr_psp_message = true; + /* dcn42 and afterward always support external panel replay */ + dc->config.frame_update_cmd_version2 = true; + + /* read VBIOS LTTPR caps */ + { + if (ctx->dc_bios->funcs->get_lttpr_caps) { + enum bp_result bp_query_result; + uint8_t is_vbios_lttpr_enable = 0; + + bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable); + dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable; + } + + dc->caps.vbios_lttpr_aware = true; + } + dc->check_config = config_defaults; + + if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) + dc->debug = debug_defaults_drv; + + /*HW default is to have all the FGCG enabled, SW no need to program them*/ + dc->debug.enable_fine_grain_clock_gating.u32All = 0xFFFF; + // Init the vm_helper + if (dc->vm_helper) + vm_helper_init(dc->vm_helper, 16); + + /************************************************* + * Create resources * + *************************************************/ + + /* Clock Sources for Pixel Clock*/ + pool->base.clock_sources[DCN401_CLK_SRC_PLL0] = + dcn42_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL0, + &clk_src_regs[0], false); + pool->base.clock_sources[DCN401_CLK_SRC_PLL1] = + dcn42_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL1, + &clk_src_regs[1], false); + pool->base.clock_sources[DCN401_CLK_SRC_PLL2] = + dcn42_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL2, + &clk_src_regs[2], false); + pool->base.clock_sources[DCN401_CLK_SRC_PLL3] = + dcn42_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL3, + &clk_src_regs[3], false); + pool->base.clock_sources[DCN401_CLK_SRC_PLL4] = + dcn42_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL4, + &clk_src_regs[4], false); + + pool->base.clk_src_count = DCN401_CLK_SRC_TOTAL; + + /* todo: not reuse phy_pll registers */ + pool->base.dp_clock_source = + dcn42_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_ID_DP_DTO, + &clk_src_regs[0], true); + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + } + + /* DCCG */ + pool->base.dccg = dccg42_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); + if (pool->base.dccg == NULL) { + dm_error("DC: failed to create dccg!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + +#undef REG_STRUCT +#define REG_STRUCT pg_cntl_regs + pg_cntl_dcn42_regs_init(); + + pool->base.pg_cntl = pg_cntl42_create(ctx, &pg_cntl_regs, &pg_cntl_shift, &pg_cntl_mask); + if (pool->base.pg_cntl == NULL) { + dm_error("DC: failed to create power gate control!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + /* IRQ Service */ + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dcn42_create(&init_data); + if (!pool->base.irqs) + goto create_fail; + + /* HUBBUB */ + pool->base.hubbub = dcn42_hubbub_create(ctx); + if (pool->base.hubbub == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create hubbub!\n"); + goto create_fail; + } + + /* HUBPs, DPPs, OPPs, TGs, ABMs */ + for (i = 0, j = 0; i < pool->base.res_cap->num_timing_generator; i++) { + /* if pipe is disabled, skip instance of HW pipe, + * i.e, skip ASIC register instance + */ + if (pipe_fuses & 1 << i) + continue; + + pool->base.hubps[j] = dcn42_hubp_create(ctx, i); + if (pool->base.hubps[j] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create hubps!\n"); + goto create_fail; + } + + pool->base.dpps[j] = dcn42_dpp_create(ctx, i); + if (pool->base.dpps[j] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create dpps!\n"); + goto create_fail; + } + + pool->base.opps[j] = dcn42_opp_create(ctx, i); + if (pool->base.opps[j] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create output pixel processor!\n"); + goto create_fail; + } + + pool->base.timing_generators[j] = dcn42_timing_generator_create( + ctx, i); + if (pool->base.timing_generators[j] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto create_fail; + } + + pool->base.multiple_abms[j] = dmub_abm_create(ctx, + &abm_regs[i], + &abm_shift, + &abm_mask); + if (pool->base.multiple_abms[j] == NULL) { + dm_error("DC: failed to create abm for pipe %d!\n", i); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + /* index for resource pool arrays for next valid pipe */ + j++; + } + + /* PSR */ + pool->base.psr = dmub_psr_create(ctx); + if (pool->base.psr == NULL) { + dm_error("DC: failed to create psr obj!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + /* Replay */ + pool->base.replay = dmub_replay_create(ctx); + if (pool->base.replay == NULL) { + dm_error("DC: failed to create replay obj!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + /* MPCCs */ + pool->base.mpc = dcn42_mpc_create(ctx, pool->base.res_cap->num_timing_generator, + pool->base.res_cap->num_mpc_3dlut); + if (pool->base.mpc == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mpc!\n"); + goto create_fail; + } + + /* DSCs */ + for (i = 0; i < pool->base.res_cap->num_dsc; i++) { + pool->base.dscs[i] = dcn42_dsc_create(ctx, i); + if (pool->base.dscs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create display stream compressor %d!\n", i); + goto create_fail; + } + } + + /* DWB */ + if (!dcn42_dwbc_create(ctx, &pool->base)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create dwbc!\n"); + goto create_fail; + } + + /* MMHUBBUB */ + if (!dcn42_mmhubbub_create(ctx, &pool->base)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mcif_wb!\n"); + goto create_fail; + } + + /* AUX and I2C */ + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + pool->base.engines[i] = dcn42_aux_engine_create(ctx, i); + + if (pool->base.engines[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create aux engine!!\n"); + goto create_fail; + } + pool->base.hw_i2cs[i] = dcn42_i2c_hw_create(ctx, i); + if (pool->base.hw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create hw i2c!!\n"); + goto create_fail; + } + pool->base.sw_i2cs[i] = NULL; + } + /* DCN4.2 has 6 DPIA */ + pool->base.usb4_dpia_count = dc->caps.num_of_host_routers * dc->caps.num_of_dpias_per_host_router; + if (dc->debug.dpia_debug.bits.disable_dpia) + pool->base.usb4_dpia_count = 0; + + /* Audio, HWSeq, Stream Encoders including HPO and virtual, MPC 3D LUTs */ + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto create_fail; + + /* HW Sequencer init functions and Plane caps */ + dcn42_hw_sequencer_init_functions(dc); + + dc->caps.max_planes = pool->base.pipe_count; + + for (i = 0; i < dc->caps.max_planes; ++i) + dc->caps.planes[i] = plane_cap; + + dc->caps.max_odm_combine_factor = 4; + + dc->cap_funcs = cap_funcs; + dc->dcn_ip->max_num_dpp = pool->base.pipe_count; + + // For now enable SDPIF_REQUEST_RATE_LIMIT on DCN4_01 when vram_info.num_chans provided + if (dc->config.sdpif_request_limit_words_per_umc == 0) + dc->config.sdpif_request_limit_words_per_umc = 16; + + dc->dml2_options.dcn_pipe_count = pool->base.pipe_count; + /*this will use real soc clock table*/ + dc->dml2_options.use_native_soc_bb_construction = true; + dc->dml2_options.minimize_dispclk_using_odm = false; + if (dc->config.EnableMinDispClkODM) + dc->dml2_options.minimize_dispclk_using_odm = true; + dc->dml2_options.enable_windowed_mpo_odm = dc->config.enable_windowed_mpo_odm; + dc->dml2_options.map_dc_pipes_with_callbacks = true; + dc->dml2_options.force_tdlut_enable = true; + + resource_init_common_dml2_callbacks(dc, &dc->dml2_options); + dc->dml2_options.callbacks.can_support_mclk_switch_using_fw_based_vblank_stretch = + &dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch; + dc->dml2_options.svp_pstate.callbacks.release_dsc = &dcn20_release_dsc; + dc->dml2_options.svp_pstate.callbacks.calculate_mall_ways_from_bytes = + pool->base.funcs->calculate_mall_ways_from_bytes; + + dc->dml2_options.svp_pstate.subvp_fw_processing_delay_us = dc->caps.subvp_fw_processing_delay_us; + dc->dml2_options.svp_pstate.subvp_prefetch_end_to_mall_start_us = dc->caps.subvp_prefetch_end_to_mall_start_us; + dc->dml2_options.svp_pstate.subvp_pstate_allow_width_us = dc->caps.subvp_pstate_allow_width_us; + dc->dml2_options.svp_pstate.subvp_swath_height_margin_lines = dc->caps.subvp_swath_height_margin_lines; + + dc->dml2_options.svp_pstate.force_disable_subvp = dc->debug.force_disable_subvp; + dc->dml2_options.svp_pstate.force_enable_subvp = dc->debug.force_subvp_mclk_switch; + + dc->dml2_options.mall_cfg.cache_line_size_bytes = dc->caps.cache_line_size; + dc->dml2_options.mall_cfg.cache_num_ways = dc->caps.cache_num_ways; + dc->dml2_options.mall_cfg.max_cab_allocation_bytes = + dc->caps.max_cab_allocation_bytes; + dc->dml2_options.mall_cfg.mblk_height_4bpe_pixels = DCN3_2_MBLK_HEIGHT_4BPE; + dc->dml2_options.mall_cfg.mblk_height_8bpe_pixels = DCN3_2_MBLK_HEIGHT_8BPE; + dc->dml2_options.mall_cfg.mblk_size_bytes = DCN3_2_MALL_MBLK_SIZE_BYTES; + dc->dml2_options.mall_cfg.mblk_width_pixels = DCN3_2_MBLK_WIDTH; + + dc->dml2_options.max_segments_per_hubp = 24; + dc->dml2_options.det_segment_size = DCN42_CRB_SEGMENT_SIZE_KB; + dc->dml2_options.gpuvm_enable = true; + dc->dml2_options.hostvm_enable = true; + + /* SPL */ + dc->caps.scl_caps.sharpener_support = true; + + return true; + +create_fail: + + dcn42_resource_destruct(pool); + + return false; +} +struct resource_pool *dcn42_create_resource_pool( + const struct dc_init_data *init_data, + struct dc *dc) +{ + struct dcn42_resource_pool *pool = + kzalloc(sizeof(struct dcn401_resource_pool), GFP_KERNEL); + + if (!pool) + return NULL; + + if (dcn42_resource_construct(init_data->num_virtual_links, dc, pool)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + kfree(pool); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.h new file mode 100644 index 000000000000..60acf0e423d9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.h @@ -0,0 +1,591 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2026 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef _DCN42_RESOURCE_H_ +#define _DCN42_RESOURCE_H_ + +#include "core_types.h" + +#define TO_DCN42_RES_POOL(pool) \ + container_of(pool, struct dcn42_resource_pool, base) + +/* DPP */ +#define DPP_REG_LIST_DCN42_COMMON_RI(id) \ + SRI_ARR(CM_DEALPHA, CM, id), SRI_ARR(CM_MEM_PWR_STATUS, CM, id), \ + SRI_ARR(CM_BIAS_CR_R, CM, id), SRI_ARR(CM_BIAS_Y_G_CB_B, CM, id), \ + SRI_ARR(PRE_DEGAM, CNVC_CFG, id), SRI_ARR(CM_GAMCOR_CONTROL, CM, id), \ + SRI_ARR(CM_GAMCOR_LUT_CONTROL, CM, id), \ + SRI_ARR(CM_GAMCOR_LUT_INDEX, CM, id), \ + SRI_ARR(CM_GAMCOR_LUT_INDEX, CM, id), \ + SRI_ARR(CM_GAMCOR_LUT_DATA, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_START_CNTL_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_START_CNTL_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_START_CNTL_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_START_SLOPE_CNTL_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_START_SLOPE_CNTL_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_START_SLOPE_CNTL_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_END_CNTL1_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_END_CNTL2_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_END_CNTL1_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_END_CNTL2_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_END_CNTL1_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_END_CNTL2_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_REGION_0_1, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_REGION_32_33, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_OFFSET_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_OFFSET_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_OFFSET_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_START_BASE_CNTL_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_START_BASE_CNTL_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_START_BASE_CNTL_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_START_CNTL_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_START_CNTL_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_START_CNTL_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_START_SLOPE_CNTL_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_START_SLOPE_CNTL_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_START_SLOPE_CNTL_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_END_CNTL1_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_END_CNTL2_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_END_CNTL1_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_END_CNTL2_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_END_CNTL1_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_END_CNTL2_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_REGION_0_1, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_REGION_32_33, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_OFFSET_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_OFFSET_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_OFFSET_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_START_BASE_CNTL_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_START_BASE_CNTL_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_START_BASE_CNTL_R, CM, id), \ + SRI_ARR(CM_HIST_CNTL, CM, id), \ + SRI_ARR(CM_HIST_LOCK, CM, id), \ + SRI_ARR(CM_HIST_INDEX, CM, id), \ + SRI_ARR(CM_HIST_DATA, CM, id), \ + SRI_ARR(CM_HIST_STATUS, CM, id), \ + SRI_ARR(CM_HIST_SCALE_SRC1, CM, id), \ + SRI_ARR(CM_HIST_COEFA_SRC2, CM, id), \ + SRI_ARR(CM_HIST_COEFB_SRC2, CM, id), \ + SRI_ARR(CM_HIST_COEFC_SRC2, CM, id), \ + SRI_ARR(CM_HIST_SCALE_SRC3, CM, id), \ + SRI_ARR(CM_HIST_BIAS_SRC1, CM, id), \ + SRI_ARR(CM_HIST_BIAS_SRC2, CM, id), \ + SRI_ARR(CM_HIST_BIAS_SRC3, CM, id), \ + SRI_ARR(DSCL_EXT_OVERSCAN_LEFT_RIGHT, DSCL, id), \ + SRI_ARR(DSCL_EXT_OVERSCAN_TOP_BOTTOM, DSCL, id), \ + SRI_ARR(OTG_H_BLANK, DSCL, id), SRI_ARR(OTG_V_BLANK, DSCL, id), \ + SRI_ARR(SCL_MODE, DSCL, id), SRI_ARR(LB_DATA_FORMAT, DSCL, id), \ + SRI_ARR(LB_MEMORY_CTRL, DSCL, id), SRI_ARR(DSCL_AUTOCAL, DSCL, id), \ + SRI_ARR(SCL_TAP_CONTROL, DSCL, id), \ + SRI_ARR(SCL_COEF_RAM_TAP_SELECT, DSCL, id), \ + SRI_ARR(SCL_COEF_RAM_TAP_DATA, DSCL, id), \ + SRI_ARR(DSCL_2TAP_CONTROL, DSCL, id), SRI_ARR(MPC_SIZE, DSCL, id), \ + SRI_ARR(SCL_HORZ_FILTER_SCALE_RATIO, DSCL, id), \ + SRI_ARR(SCL_VERT_FILTER_SCALE_RATIO, DSCL, id), \ + SRI_ARR(SCL_HORZ_FILTER_SCALE_RATIO_C, DSCL, id), \ + SRI_ARR(SCL_VERT_FILTER_SCALE_RATIO_C, DSCL, id), \ + SRI_ARR(SCL_HORZ_FILTER_INIT, DSCL, id), \ + SRI_ARR(SCL_HORZ_FILTER_INIT_C, DSCL, id), \ + SRI_ARR(SCL_VERT_FILTER_INIT, DSCL, id), \ + SRI_ARR(SCL_VERT_FILTER_INIT_C, DSCL, id), \ + SRI_ARR(RECOUT_START, DSCL, id), SRI_ARR(RECOUT_SIZE, DSCL, id), \ + SRI_ARR(PRE_DEALPHA, CNVC_CFG, id), SRI_ARR(PRE_REALPHA, CNVC_CFG, id), \ + SRI_ARR(PRE_CSC_MODE, CNVC_CFG, id), \ + SRI_ARR(PRE_CSC_C11_C12, CNVC_CFG, id), \ + SRI_ARR(PRE_CSC_C33_C34, CNVC_CFG, id), \ + SRI_ARR(PRE_CSC_B_C11_C12, CNVC_CFG, id), \ + SRI_ARR(PRE_CSC_B_C33_C34, CNVC_CFG, id), \ + SRI_ARR(CM_POST_CSC_CONTROL, CM, id), \ + SRI_ARR(CM_POST_CSC_C11_C12, CM, id), \ + SRI_ARR(CM_POST_CSC_C33_C34, CM, id), \ + SRI_ARR(CM_POST_CSC_B_C11_C12, CM, id), \ + SRI_ARR(CM_POST_CSC_B_C33_C34, CM, id), \ + SRI_ARR(CM_MEM_PWR_CTRL, CM, id), SRI_ARR(CM_CONTROL, CM, id), \ + SRI_ARR(CM_TEST_DEBUG_INDEX, CM, id), \ + SRI_ARR(CM_TEST_DEBUG_DATA, CM, id), \ + SRI_ARR(FORMAT_CONTROL, CNVC_CFG, id), \ + SRI_ARR(CNVC_SURFACE_PIXEL_FORMAT, CNVC_CFG, id), \ + SRI_ARR(CURSOR0_CONTROL, CM_CUR, id), \ + SRI_ARR(CURSOR0_COLOR0, CM_CUR, id), \ + SRI_ARR(CURSOR0_COLOR1, CM_CUR, id), \ + SRI_ARR(CURSOR0_FP_SCALE_BIAS_G_Y, CM_CUR, id), \ + SRI_ARR(CURSOR0_FP_SCALE_BIAS_RB_CRCB, CM_CUR, id), \ + SRI_ARR(CUR0_MATRIX_MODE, CM_CUR, id), \ + SRI_ARR(CUR0_MATRIX_C11_C12_A, CM_CUR, id), \ + SRI_ARR(CUR0_MATRIX_C13_C14_A, CM_CUR, id), \ + SRI_ARR(CUR0_MATRIX_C21_C22_A, CM_CUR, id), \ + SRI_ARR(CUR0_MATRIX_C23_C24_A, CM_CUR, id), \ + SRI_ARR(CUR0_MATRIX_C31_C32_A, CM_CUR, id), \ + SRI_ARR(CUR0_MATRIX_C33_C34_A, CM_CUR, id), \ + SRI_ARR(CUR0_MATRIX_C11_C12_B, CM_CUR, id), \ + SRI_ARR(CUR0_MATRIX_C13_C14_B, CM_CUR, id), \ + SRI_ARR(CUR0_MATRIX_C21_C22_B, CM_CUR, id), \ + SRI_ARR(CUR0_MATRIX_C23_C24_B, CM_CUR, id), \ + SRI_ARR(CUR0_MATRIX_C31_C32_B, CM_CUR, id), \ + SRI_ARR(CUR0_MATRIX_C33_C34_B, CM_CUR, id), \ + SRI_ARR(DPP_CONTROL, DPP_TOP, id), SRI_ARR(CM_HDR_MULT_COEF, CM, id), \ + SRI_ARR(CURSOR_CONTROL, CURSOR0_, id), \ + SRI_ARR(ALPHA_2BIT_LUT01, CNVC_CFG, id), \ + SRI_ARR(ALPHA_2BIT_LUT23, CNVC_CFG, id), \ + SRI_ARR(FCNV_FP_BIAS_R, CNVC_CFG, id), \ + SRI_ARR(FCNV_FP_BIAS_G, CNVC_CFG, id), \ + SRI_ARR(FCNV_FP_BIAS_B, CNVC_CFG, id), \ + SRI_ARR(FCNV_FP_SCALE_R, CNVC_CFG, id), \ + SRI_ARR(FCNV_FP_SCALE_G, CNVC_CFG, id), \ + SRI_ARR(FCNV_FP_SCALE_B, CNVC_CFG, id), \ + SRI_ARR(COLOR_KEYER_CONTROL, CNVC_CFG, id), \ + SRI_ARR(COLOR_KEYER_ALPHA, CNVC_CFG, id), \ + SRI_ARR(COLOR_KEYER_RED, CNVC_CFG, id), \ + SRI_ARR(COLOR_KEYER_GREEN, CNVC_CFG, id), \ + SRI_ARR(COLOR_KEYER_BLUE, CNVC_CFG, id), \ + SRI_ARR(OBUF_MEM_PWR_CTRL, DSCL, id), \ + SRI_ARR(DSCL_MEM_PWR_STATUS, DSCL, id), \ + SRI_ARR(DSCL_MEM_PWR_CTRL, DSCL, id), \ + SRI_ARR(DSCL_CONTROL, DSCL, id), \ + SRI_ARR(DSCL_SC_MODE, DSCL, id), \ + SRI_ARR(DSCL_EASF_H_MODE, DSCL, id), \ + SRI_ARR(DSCL_EASF_H_BF_CNTL, DSCL, id), \ + SRI_ARR(DSCL_EASF_H_RINGEST_EVENTAP_REDUCE, DSCL, id), \ + SRI_ARR(DSCL_EASF_H_RINGEST_EVENTAP_GAIN, DSCL, id), \ + SRI_ARR(DSCL_EASF_H_BF_FINAL_MAX_MIN, DSCL, id), \ + SRI_ARR(DSCL_EASF_H_BF1_PWL_SEG0, DSCL, id), \ + SRI_ARR(DSCL_EASF_H_BF1_PWL_SEG1, DSCL, id), \ + SRI_ARR(DSCL_EASF_H_BF1_PWL_SEG2, DSCL, id), \ + SRI_ARR(DSCL_EASF_H_BF1_PWL_SEG3, DSCL, id), \ + SRI_ARR(DSCL_EASF_H_BF1_PWL_SEG4, DSCL, id), \ + SRI_ARR(DSCL_EASF_H_BF1_PWL_SEG5, DSCL, id), \ + SRI_ARR(DSCL_EASF_H_BF1_PWL_SEG6, DSCL, id), \ + SRI_ARR(DSCL_EASF_H_BF1_PWL_SEG7, DSCL, id), \ + SRI_ARR(DSCL_EASF_H_BF3_PWL_SEG0, DSCL, id), \ + SRI_ARR(DSCL_EASF_H_BF3_PWL_SEG1, DSCL, id), \ + SRI_ARR(DSCL_EASF_H_BF3_PWL_SEG2, DSCL, id), \ + SRI_ARR(DSCL_EASF_H_BF3_PWL_SEG3, DSCL, id), \ + SRI_ARR(DSCL_EASF_H_BF3_PWL_SEG4, DSCL, id), \ + SRI_ARR(DSCL_EASF_H_BF3_PWL_SEG5, DSCL, id), \ + SRI_ARR(DSCL_EASF_V_MODE, DSCL, id), \ + SRI_ARR(DSCL_EASF_V_BF_CNTL, DSCL, id), \ + SRI_ARR(DSCL_EASF_V_RINGEST_3TAP_CNTL1, DSCL, id), \ + SRI_ARR(DSCL_EASF_V_RINGEST_3TAP_CNTL2, DSCL, id), \ + SRI_ARR(DSCL_EASF_V_RINGEST_3TAP_CNTL3, DSCL, id), \ + SRI_ARR(DSCL_EASF_V_RINGEST_EVENTAP_REDUCE, DSCL, id), \ + SRI_ARR(DSCL_EASF_V_RINGEST_EVENTAP_GAIN, DSCL, id), \ + SRI_ARR(DSCL_EASF_V_BF_FINAL_MAX_MIN, DSCL, id), \ + SRI_ARR(DSCL_EASF_V_BF1_PWL_SEG0, DSCL, id), \ + SRI_ARR(DSCL_EASF_V_BF1_PWL_SEG1, DSCL, id), \ + SRI_ARR(DSCL_EASF_V_BF1_PWL_SEG2, DSCL, id), \ + SRI_ARR(DSCL_EASF_V_BF1_PWL_SEG3, DSCL, id), \ + SRI_ARR(DSCL_EASF_V_BF1_PWL_SEG4, DSCL, id), \ + SRI_ARR(DSCL_EASF_V_BF1_PWL_SEG5, DSCL, id), \ + SRI_ARR(DSCL_EASF_V_BF1_PWL_SEG6, DSCL, id), \ + SRI_ARR(DSCL_EASF_V_BF1_PWL_SEG7, DSCL, id), \ + SRI_ARR(DSCL_EASF_V_BF3_PWL_SEG0, DSCL, id), \ + SRI_ARR(DSCL_EASF_V_BF3_PWL_SEG1, DSCL, id), \ + SRI_ARR(DSCL_EASF_V_BF3_PWL_SEG2, DSCL, id), \ + SRI_ARR(DSCL_EASF_V_BF3_PWL_SEG3, DSCL, id), \ + SRI_ARR(DSCL_EASF_V_BF3_PWL_SEG4, DSCL, id), \ + SRI_ARR(DSCL_EASF_V_BF3_PWL_SEG5, DSCL, id), \ + SRI_ARR(DSCL_SC_MATRIX_C0C1, DSCL, id), \ + SRI_ARR(DSCL_SC_MATRIX_C2C3, DSCL, id), \ + SRI_ARR(ISHARP_MODE, DSCL, id), \ + SRI_ARR(ISHARP_DELTA_LUT_MEM_PWR_CTRL, DSCL, id), \ + SRI_ARR(ISHARP_NOISEDET_THRESHOLD, DSCL, id), \ + SRI_ARR(ISHARP_NOISE_GAIN_PWL, DSCL, id), \ + SRI_ARR(ISHARP_LBA_PWL_SEG0, DSCL, id), \ + SRI_ARR(ISHARP_LBA_PWL_SEG1, DSCL, id), \ + SRI_ARR(ISHARP_LBA_PWL_SEG2, DSCL, id), \ + SRI_ARR(ISHARP_LBA_PWL_SEG3, DSCL, id), \ + SRI_ARR(ISHARP_LBA_PWL_SEG4, DSCL, id), \ + SRI_ARR(ISHARP_LBA_PWL_SEG5, DSCL, id), \ + SRI_ARR(ISHARP_DELTA_CTRL, DSCL, id), \ + SRI_ARR(ISHARP_DELTA_DATA, DSCL, id), \ + SRI_ARR(ISHARP_DELTA_INDEX, DSCL, id), \ + SRI_ARR(ISHARP_NLDELTA_SOFT_CLIP, DSCL, id), \ + SRI_ARR(SCL_VERT_FILTER_INIT_BOT, DSCL, id), \ + SRI_ARR(SCL_VERT_FILTER_INIT_BOT_C, DSCL, id) + +/* Stream encoder */ +#define SE_DCN42_REG_LIST_RI(id) \ + SRI_ARR(HDMI_CONTROL, DIG, id), SRI_ARR(HDMI_DB_CONTROL, DIG, id), \ + SRI_ARR(HDMI_GC, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL0, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL1, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL2, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL3, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL4, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL5, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL6, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL7, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL8, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL9, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL10, DIG, id), \ + SRI_ARR(HDMI_INFOFRAME_CONTROL0, DIG, id), \ + SRI_ARR(HDMI_VBI_PACKET_CONTROL, DIG, id), \ + SRI_ARR(HDMI_AUDIO_PACKET_CONTROL, DIG, id), \ + SRI_ARR(HDMI_ACR_PACKET_CONTROL, DIG, id), \ + SRI_ARR(HDMI_ACR_32_0, DIG, id), SRI_ARR(HDMI_ACR_32_1, DIG, id), \ + SRI_ARR(HDMI_ACR_44_0, DIG, id), SRI_ARR(HDMI_ACR_44_1, DIG, id), \ + SRI_ARR(HDMI_ACR_48_0, DIG, id), SRI_ARR(HDMI_ACR_48_1, DIG, id), \ + SRI_ARR(DP_DB_CNTL, DP, id), SRI_ARR(DP_MSA_MISC, DP, id), \ + SRI_ARR(DP_MSA_VBID_MISC, DP, id), SRI_ARR(DP_MSA_COLORIMETRY, DP, id), \ + SRI_ARR(DP_MSA_TIMING_PARAM1, DP, id), \ + SRI_ARR(DP_MSA_TIMING_PARAM2, DP, id), \ + SRI_ARR(DP_MSA_TIMING_PARAM3, DP, id), \ + SRI_ARR(DP_MSA_TIMING_PARAM4, DP, id), \ + SRI_ARR(DP_MSE_RATE_CNTL, DP, id), SRI_ARR(DP_MSE_RATE_UPDATE, DP, id), \ + SRI_ARR(DP_PIXEL_FORMAT, DP, id), SRI_ARR(DP_SEC_CNTL, DP, id), \ + SRI_ARR(DP_SEC_CNTL1, DP, id), SRI_ARR(DP_SEC_CNTL2, DP, id), \ + SRI_ARR(DP_SEC_CNTL5, DP, id), SRI_ARR(DP_SEC_CNTL6, DP, id), \ + SRI_ARR(DP_STEER_FIFO, DP, id), SRI_ARR(DP_VID_M, DP, id), \ + SRI_ARR(DP_VID_N, DP, id), SRI_ARR(DP_VID_STREAM_CNTL, DP, id), \ + SRI_ARR(DP_VID_TIMING, DP, id), SRI_ARR(DP_SEC_AUD_N, DP, id), \ + SRI_ARR(DP_SEC_TIMESTAMP, DP, id), \ + SRI_ARR(DP_SEC_METADATA_TRANSMISSION, DP, id), \ + SRI_ARR(HDMI_METADATA_PACKET_CONTROL, DIG, id), \ + SRI_ARR(DP_SEC_FRAMING4, DP, id), SRI_ARR(DP_GSP11_CNTL, DP, id), \ + SRI_ARR(DME_CONTROL, DME, id), \ + SRI_ARR(DP_SEC_METADATA_TRANSMISSION, DP, id), \ + SRI_ARR(HDMI_METADATA_PACKET_CONTROL, DIG, id), \ + SRI_ARR(DIG_FE_CNTL, DIG, id), \ + SRI_ARR(DIG_FE_EN_CNTL, DIG, id), \ + SRI_ARR(DIG_FE_CLK_CNTL, DIG, id), \ + SRI_ARR(DIG_CLOCK_PATTERN, DIG, id), \ + SRI_ARR(DIG_FIFO_CTRL0, DIG, id), \ + SRI_ARR(STREAM_MAPPER_CONTROL, DIG, id),\ + SRI_ARR(DIG_FE_AUDIO_CNTL, DIG, id) + +/* HPO DP stream encoder */ +#define DCN42_HPO_DP_STREAM_ENC_REG_LIST_RI(id) \ + SR_ARR(DP_STREAM_MAPPER_CONTROL0, id), \ + SR_ARR(DP_STREAM_MAPPER_CONTROL1, id), \ + SR_ARR(DP_STREAM_MAPPER_CONTROL2, id), \ + SR_ARR(DP_STREAM_MAPPER_CONTROL3, id), \ + SRI_ARR(DP_STREAM_ENC_CLOCK_CONTROL, DP_STREAM_ENC, id), \ + SRI_ARR(DP_STREAM_ENC_INPUT_MUX_CONTROL, DP_STREAM_ENC, id), \ + SRI_ARR(DP_STREAM_ENC_AUDIO_CONTROL, DP_STREAM_ENC, id), \ + SRI_ARR(DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, DP_STREAM_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_CONTROL, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_PIXEL_FORMAT, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_PIXEL_FORMAT_DOUBLE_BUFFER_CONTROL, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA0, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA1, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA2, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA3, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA4, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA5, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA6, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA7, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA8, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA_CONTROL, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA_DOUBLE_BUFFER_CONTROL, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_FIFO_CONTROL, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_STREAM_CONTROL, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_VBID_CONTROL, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_SDP_CONTROL, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_SDP_GSP_CONTROL0, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_SDP_GSP_CONTROL2, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_SDP_GSP_CONTROL3, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_SDP_GSP_CONTROL5, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_SDP_GSP_CONTROL11, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_SDP_METADATA_PACKET_CONTROL, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_SDP_AUDIO_CONTROL0, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_CRC_CONTROL, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_HBLANK_CONTROL, DP_SYM32_ENC, id) + +/*HPO DP link encoder regs */ +#define DCN42_HPO_DP_LINK_ENC_REG_LIST_RI(id) \ + SRI_ARR(DP_LINK_ENC_CLOCK_CONTROL, DP_LINK_ENC, id), \ + SRI_ARR(DP_DPHY_SYM32_CONTROL, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_STATUS, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CONFIG, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_PRBS_SEED0, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_PRBS_SEED1, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_PRBS_SEED2, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_PRBS_SEED3, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_SQ_PULSE, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM0, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM1, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM2, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM3, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM4, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM5, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM6, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM7, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM8, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM9, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM10, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_SAT_VC0, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_SAT_VC1, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_SAT_VC2, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_SAT_VC3, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_VC_RATE_CNTL0, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_VC_RATE_CNTL1, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_VC_RATE_CNTL2, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_VC_RATE_CNTL3, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_SAT_UPDATE, DP_DPHY_SYM32, id) + +#define VPG_DCN42_REG_LIST_RI(id) \ + SRI(VPG_GENERIC_STATUS, VPG, id), \ + SRI(VPG_GENERIC_PACKET_ACCESS_CTRL, VPG, id), \ + SRI(VPG_GENERIC_PACKET_DATA, VPG, id), \ + SRI(VPG_GSP_FRAME_UPDATE_CTRL, VPG, id), \ + SRI(VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG, id), \ + SRI(VPG_MEM_PWR, VPG, id) + +/* DCCG */ +#define DCCG_REG_LIST_DCN42_RI() \ + SR(DPPCLK_DTO_CTRL), \ + DCCG_SRII(DTO_PARAM, DPPCLK, 0), \ + DCCG_SRII(DTO_PARAM, DPPCLK, 1), \ + DCCG_SRII(DTO_PARAM, DPPCLK, 2), \ + DCCG_SRII(DTO_PARAM, DPPCLK, 3), \ + DCCG_SRII(CLOCK_CNTL, HDMICHARCLK, 0), \ + SR(HDMISTREAMCLK0_DTO_PARAM),\ + SR(DCCG_GLOBAL_FGCG_REP_CNTL),\ + SR(DISPCLK_FREQ_CHANGE_CNTL), \ + SR(PHYASYMCLK_CLOCK_CNTL), \ + SR(PHYBSYMCLK_CLOCK_CNTL), \ + SR(PHYCSYMCLK_CLOCK_CNTL), \ + SR(PHYDSYMCLK_CLOCK_CNTL), \ + SR(PHYESYMCLK_CLOCK_CNTL), \ + SR(DPSTREAMCLK_CNTL), \ + SR(HDMISTREAMCLK_CNTL), \ + SR(SYMCLK32_SE_CNTL), \ + SR(SYMCLK32_LE_CNTL), \ + DCCG_SRII(PIXEL_RATE_CNTL, OTG, 0), \ + DCCG_SRII(PIXEL_RATE_CNTL, OTG, 1), \ + DCCG_SRII(PIXEL_RATE_CNTL, OTG, 2), \ + DCCG_SRII(PIXEL_RATE_CNTL, OTG, 3), \ + SR(OTG_PIXEL_RATE_DIV), \ + SR(DTBCLK_P_CNTL), \ + SR(DCCG_AUDIO_DTO_SOURCE), \ + SR(DENTIST_DISPCLK_CNTL), \ + SR(DPPCLK_CTRL), \ + DCCG_SRII(MODULO, DP_DTO, 0), \ + DCCG_SRII(MODULO, DP_DTO, 1), \ + DCCG_SRII(MODULO, DP_DTO, 2), \ + DCCG_SRII(MODULO, DP_DTO, 3), \ + DCCG_SRII(PHASE, DP_DTO, 0), \ + DCCG_SRII(PHASE, DP_DTO, 1), \ + DCCG_SRII(PHASE, DP_DTO, 2), \ + DCCG_SRII(PHASE, DP_DTO, 3), \ + SR(OTG_ADD_DROP_PIXEL_CNTL), \ + SR(DSCCLK0_DTO_PARAM), \ + SR(DSCCLK1_DTO_PARAM), \ + SR(DSCCLK2_DTO_PARAM), \ + SR(DSCCLK3_DTO_PARAM), \ + SR(DSCCLK_DTO_CTRL), \ + SR(DCCG_GATE_DISABLE_CNTL), \ + SR(DCCG_GATE_DISABLE_CNTL2), \ + SR(DCCG_GATE_DISABLE_CNTL3), \ + SR(DCCG_GATE_DISABLE_CNTL4), \ + SR(DCCG_GATE_DISABLE_CNTL5), \ + SR(DCCG_GATE_DISABLE_CNTL6), \ + SR(SYMCLKA_CLOCK_ENABLE), \ + SR(SYMCLKB_CLOCK_ENABLE), \ + SR(SYMCLKC_CLOCK_ENABLE), \ + SR(SYMCLKD_CLOCK_ENABLE), \ + SR(SYMCLKE_CLOCK_ENABLE) + +#define DCN42_AUD_COMMON_MASK_SH_LIST(mask_sh) \ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh), \ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ + SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL, mask_sh),\ + SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO_SEL, mask_sh),\ + SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_USE_512FBR_DTO, mask_sh),\ + SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO1_USE_512FBR_DTO, mask_sh),\ + SF(DCCG_AUDIO_DTO0_MODULE, DCCG_AUDIO_DTO0_MODULE, mask_sh),\ + SF(DCCG_AUDIO_DTO0_PHASE, DCCG_AUDIO_DTO0_PHASE, mask_sh),\ + SF(DCCG_AUDIO_DTO1_MODULE, DCCG_AUDIO_DTO1_MODULE, mask_sh),\ + SF(DCCG_AUDIO_DTO1_PHASE, DCCG_AUDIO_DTO1_PHASE, mask_sh),\ + SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES, AUDIO_RATE_CAPABILITIES, mask_sh),\ + SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, CLKSTOP, mask_sh),\ + SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, EPSS, mask_sh) + + /* HPO FRL stream encoder */ +#define DCN42_HPO_FRL_STREAM_ENC_REG_LIST_RI(id) \ + DCN3_0_HPO_FRL_STREAM_ENC_REG_LIST_RI(id), \ + SR_ARR(HDMI_STREAM_ENC_AUDIO_CONTROL, id),\ + SR_ARR(HDMI_TB_ENC_MEM_CTRL, id),\ + SR_ARR(HDMI_FRL_ENC_MEM_CTRL, id) +/* OPTC */ +#define OPTC_COMMON_REG_LIST_DCN42_RI(inst) \ + SRI_ARR(OTG_VSTARTUP_PARAM, OTG, inst), \ + SRI_ARR(OTG_VUPDATE_PARAM, OTG, inst), \ + SRI_ARR(OTG_VREADY_PARAM, OTG, inst), \ + SRI_ARR(OTG_MASTER_UPDATE_LOCK, OTG, inst), \ + SRI_ARR(OTG_MASTER_UPDATE_MODE, OTG, inst), \ + SRI_ARR(OTG_V_COUNT_STOP_CONTROL, OTG, inst), \ + SRI_ARR(OTG_V_COUNT_STOP_CONTROL2, OTG, inst), \ + SRI_ARR(OTG_GSL_CONTROL, OTG, inst), \ + SRI2_ARR(OPTC_CLOCK_CONTROL, OPTC, inst),\ + SRI_ARR(OTG_GLOBAL_CONTROL0, OTG, inst), \ + SRI_ARR(OTG_GLOBAL_CONTROL1, OTG, inst), \ + SRI_ARR(OTG_GLOBAL_CONTROL2, OTG, inst), \ + SRI_ARR(OTG_GLOBAL_CONTROL4, OTG, inst), \ + SRI_ARR(OTG_DOUBLE_BUFFER_CONTROL, OTG, inst), \ + SRI_ARR(OTG_H_TOTAL, OTG, inst), \ + SRI_ARR(OTG_H_BLANK_START_END, OTG, inst), \ + SRI_ARR(OTG_H_SYNC_A, OTG, inst),\ + SRI_ARR(OTG_H_SYNC_A_CNTL, OTG, inst), \ + SRI_ARR(OTG_H_TIMING_CNTL, OTG, inst), \ + SRI_ARR(OTG_V_TOTAL, OTG, inst), \ + SRI_ARR(OTG_V_BLANK_START_END, OTG, inst), \ + SRI_ARR(OTG_V_SYNC_A, OTG, inst), \ + SRI_ARR(OTG_V_SYNC_A_CNTL, OTG, inst), \ + SRI_ARR(OTG_CONTROL, OTG, inst), \ + SRI_ARR(OTG_STEREO_CONTROL, OTG, inst), \ + SRI_ARR(OTG_3D_STRUCTURE_CONTROL, OTG, inst), \ + SRI_ARR(OTG_STEREO_STATUS, OTG, inst), \ + SRI_ARR(OTG_V_TOTAL_MAX, OTG, inst), \ + SRI_ARR(OTG_V_TOTAL_MIN, OTG, inst), \ + SRI_ARR(OTG_V_TOTAL_CONTROL, OTG, inst), \ + SRI_ARR(OTG_TRIGA_CNTL, OTG, inst), \ + SRI_ARR(OTG_FORCE_COUNT_NOW_CNTL, OTG, inst), \ + SRI_ARR(OTG_STATIC_SCREEN_CONTROL, OTG, inst), \ + SRI_ARR(OTG_STATUS_FRAME_COUNT, OTG, inst), \ + SRI_ARR(OTG_STATUS, OTG, inst), \ + SRI_ARR(OTG_STATUS_POSITION, OTG, inst), \ + SRI_ARR(OTG_NOM_VERT_POSITION, OTG, inst), \ + SRI_ARR(OTG_M_CONST_DTO0, OTG, inst), \ + SRI_ARR(OTG_M_CONST_DTO1, OTG, inst), \ + SRI_ARR(OTG_CLOCK_CONTROL, OTG, inst), \ + SRI_ARR(OTG_VERTICAL_INTERRUPT0_CONTROL, OTG, inst), \ + SRI_ARR(OTG_VERTICAL_INTERRUPT0_POSITION, OTG, inst), \ + SRI_ARR(OTG_VERTICAL_INTERRUPT1_CONTROL, OTG, inst), \ + SRI_ARR(OTG_VERTICAL_INTERRUPT1_POSITION, OTG, inst), \ + SRI_ARR(OTG_VERTICAL_INTERRUPT2_CONTROL, OTG, inst), \ + SRI_ARR(OTG_VERTICAL_INTERRUPT2_POSITION, OTG, inst), \ + SRI_ARR(OPTC_INPUT_CLOCK_CONTROL, ODM, inst), \ + SRI_ARR(OPTC_DATA_SOURCE_SELECT, ODM, inst), \ + SRI_ARR(OPTC_INPUT_GLOBAL_CONTROL, ODM, inst), \ + SRI_ARR(OPTC_RSMU_UNDERFLOW, ODM, inst), \ + SRI_ARR(OPTC_UNDERFLOW_THRESHOLD, ODM, inst), \ + SRI_ARR(CONTROL, VTG, inst), \ + SRI_ARR(OTG_VERT_SYNC_CONTROL, OTG, inst), \ + SRI_ARR(OTG_GSL_CONTROL, OTG, inst), \ + SRI_ARR(OTG_CRC_CNTL, OTG, inst), \ + SRI_ARR(OTG_CRC0_DATA_R, OTG, inst), \ + SRI_ARR(OTG_CRC0_DATA_G, OTG, inst), \ + SRI_ARR(OTG_CRC0_DATA_B, OTG, inst), \ + SRI_ARR(OTG_CRC1_DATA_R, OTG, inst), \ + SRI_ARR(OTG_CRC1_DATA_G, OTG, inst), \ + SRI_ARR(OTG_CRC1_DATA_B, OTG, inst), \ + SRI_ARR(OTG_CRC0_WINDOWA_X_CONTROL, OTG, inst), \ + SRI_ARR(OTG_CRC0_WINDOWA_Y_CONTROL, OTG, inst), \ + SRI_ARR(OTG_CRC0_WINDOWB_X_CONTROL, OTG, inst), \ + SRI_ARR(OTG_CRC0_WINDOWB_Y_CONTROL, OTG, inst), \ + SRI_ARR(OTG_CRC1_WINDOWA_X_CONTROL, OTG, inst), \ + SRI_ARR(OTG_CRC1_WINDOWA_Y_CONTROL, OTG, inst), \ + SRI_ARR(OTG_CRC1_WINDOWB_X_CONTROL, OTG, inst), \ + SRI_ARR(OTG_CRC1_WINDOWB_Y_CONTROL, OTG, inst), \ + SRI_ARR(OTG_CRC0_WINDOWA_X_CONTROL_READBACK, OTG, inst),\ + SRI_ARR(OTG_CRC0_WINDOWA_Y_CONTROL_READBACK, OTG, inst),\ + SRI_ARR(OTG_CRC0_WINDOWB_X_CONTROL_READBACK, OTG, inst),\ + SRI_ARR(OTG_CRC0_WINDOWB_Y_CONTROL_READBACK, OTG, inst),\ + SRI_ARR(OTG_CRC1_WINDOWA_X_CONTROL_READBACK, OTG, inst),\ + SRI_ARR(OTG_CRC1_WINDOWA_Y_CONTROL_READBACK, OTG, inst),\ + SRI_ARR(OTG_CRC1_WINDOWB_X_CONTROL_READBACK, OTG, inst),\ + SRI_ARR(OTG_CRC1_WINDOWB_Y_CONTROL_READBACK, OTG, inst),\ + SR_ARR(GSL_SOURCE_SELECT, inst), \ + SRI_ARR(OTG_TRIGA_MANUAL_TRIG, OTG, inst), \ + SRI_ARR(OTG_GLOBAL_CONTROL1, OTG, inst), \ + SRI_ARR(OTG_GLOBAL_CONTROL2, OTG, inst), \ + SRI_ARR(OTG_GSL_WINDOW_X, OTG, inst), \ + SRI_ARR(OTG_GSL_WINDOW_Y, OTG, inst), \ + SRI_ARR(OTG_VUPDATE_KEEPOUT, OTG, inst), \ + SRI_ARR(OTG_DRR_TRIGGER_WINDOW, OTG, inst), \ + SRI_ARR(OTG_DRR_V_TOTAL_CHANGE, OTG, inst), \ + SRI_ARR(OPTC_DATA_FORMAT_CONTROL, ODM, inst), \ + SRI_ARR(OPTC_BYTES_PER_PIXEL, ODM, inst), \ + SRI_ARR(OPTC_WIDTH_CONTROL, ODM, inst), \ + SRI_ARR(OPTC_WIDTH_CONTROL2, ODM, inst), \ + SRI_ARR(OPTC_MEMORY_CONFIG, ODM, inst), \ + SRI_ARR(OTG_DRR_CONTROL, OTG, inst), \ + SRI_ARR(OTG_PSTATE_REGISTER, OTG, inst), \ + SRI_ARR(OTG_PWA_FRAME_SYNC_CONTROL, OTG, inst),\ + SRI_ARR(OTG_PIPE_UPDATE_STATUS, OTG, inst),\ + SRI_ARR(INTERRUPT_DEST, OTG, inst) + +/* CLK SRC */ +#define CS_COMMON_REG_LIST_DCN42_RI(index, pllid) \ + SRI_ARR_ALPHABET(PIXCLK_RESYNC_CNTL, PHYPLL, index, pllid), \ + SRII_ARR_2(PHASE, DP_DTO, 0, index), \ + SRII_ARR_2(PHASE, DP_DTO, 1, index), \ + SRII_ARR_2(PHASE, DP_DTO, 2, index), \ + SRII_ARR_2(PHASE, DP_DTO, 3, index), \ + SRII_ARR_2(MODULO, DP_DTO, 0, index), \ + SRII_ARR_2(MODULO, DP_DTO, 1, index), \ + SRII_ARR_2(MODULO, DP_DTO, 2, index), \ + SRII_ARR_2(MODULO, DP_DTO, 3, index), \ + SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 0, index), \ + SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 1, index), \ + SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 2, index), \ + SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 3, index) + +/* ABM */ +#define ABM_DCN42_REG_LIST_RI(id) \ + SRI_ARR(DC_ABM1_HG_SAMPLE_RATE, ABM, id), \ + SRI_ARR(DC_ABM1_LS_SAMPLE_RATE, ABM, id), \ + SRI_ARR(DC_ABM1_HG_MISC_CTRL, ABM, id), \ + SRI_ARR(DC_ABM1_IPCSC_COEFF_SEL, ABM, id), \ + SRI_ARR(BL1_PWM_BL_UPDATE_SAMPLE_RATE, ABM, id), \ + SRI_ARR(BL1_PWM_CURRENT_ABM_LEVEL, ABM, id), \ + SRI_ARR(BL1_PWM_TARGET_ABM_LEVEL, ABM, id), \ + SRI_ARR(BL1_PWM_USER_LEVEL, ABM, id), \ + SRI_ARR(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, ABM, id), \ + SRI_ARR(DC_ABM1_HGLS_REG_READ_PROGRESS, ABM, id), \ + SRI_ARR(DC_ABM1_HG_BIN_33_40_SHIFT_INDEX, ABM, id), \ + SRI_ARR(DC_ABM1_HG_BIN_33_64_SHIFT_FLAG, ABM, id), \ + SRI_ARR(DC_ABM1_HG_BIN_41_48_SHIFT_INDEX, ABM, id), \ + SRI_ARR(DC_ABM1_HG_BIN_49_56_SHIFT_INDEX, ABM, id), \ + SRI_ARR(DC_ABM1_HG_BIN_57_64_SHIFT_INDEX, ABM, id), \ + SRI_ARR(DC_ABM1_HG_RESULT_DATA, ABM, id), \ + SRI_ARR(DC_ABM1_HG_RESULT_INDEX, ABM, id), \ + SRI_ARR(DC_ABM1_ACE_OFFSET_SLOPE_DATA, ABM, id), \ + SRI_ARR(DC_ABM1_ACE_PWL_CNTL, ABM, id) + +/* HUBP */ +#define HUBP_REG_LIST_DCN42_RI(id) \ + HUBP_REG_LIST_DCN30_RI(id), SRI_ARR(DCHUBP_MALL_CONFIG, HUBP, id), \ + SRI_ARR(DCHUBP_VMPG_CONFIG, HUBP, id), \ + SRI_ARR(UCLK_PSTATE_FORCE, HUBPREQ, id), \ + SRI_ARR(HUBP_3DLUT_DLG_PARAM, CURSOR0_, id), \ + HUBP_3DLUT_FL_REG_LIST_DCN401(id) +struct dcn42_resource_pool { + struct resource_pool base; +}; +struct resource_pool *dcn42_create_resource_pool( + const struct dc_init_data *init_data, + struct dc *dc); + +enum dc_status dcn42_validate_bandwidth(struct dc *dc, + struct dc_state *context, + enum dc_validate_mode validate_mode); + +void dcn42_prepare_mcache_programming(struct dc *dc, struct dc_state *context); +int dcn42_get_power_profile(const struct dc_state *context); + +#endif /* _DCN42_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource_fpu.c b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource_fpu.c new file mode 100644 index 000000000000..33b9775420d3 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource_fpu.c @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: MIT +// +// Copyright 2026 Advanced Micro Devices, Inc. + + + +#include "dc.h" +#include "dcn42_resource_fpu.h" + +#define DC_LOGGER_INIT(logger) + + +void dcn42_decide_zstate_support(struct dc *dc, struct dc_state *context) +{ + enum dcn_zstate_support_state support = DCN_ZSTATE_SUPPORT_DISALLOW; + unsigned int i, plane_count = 0; + + DC_LOGGER_INIT(dc->ctx->logger); + + dc_assert_fp_enabled(); + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (context->res_ctx.pipe_ctx[i].plane_state) + plane_count++; + } + /*dcn42 has no z10*/ + if (context->stream_count == 0 || plane_count == 0) { + support = DCN_ZSTATE_SUPPORT_ALLOW_Z8_ONLY; + } else if (context->stream_count == 1 && context->streams[0]->signal == SIGNAL_TYPE_EDP) { + struct dc_link *link = context->streams[0]->sink->link; + bool is_psr = (link && (link->psr_settings.psr_version == DC_PSR_VERSION_1 || + link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) && !link->panel_config.psr.disable_psr); + bool is_replay = link && link->replay_settings.replay_feature_enabled; + + if (is_psr || is_replay) + support = DCN_ZSTATE_SUPPORT_ALLOW_Z8_ONLY; + else { + /*here we allow z8 for eDP based on dml21 output*/ + support = context->bw_ctx.bw.dcn.clk.zstate_support ? DCN_ZSTATE_SUPPORT_ALLOW_Z8_ONLY : DCN_ZSTATE_SUPPORT_DISALLOW; + } + + DC_LOG_SMU("zstate_support: %d, StutterPeriod: %d\n, z8_stutter_efficiency: %d\n", + support, (int)context->bw_ctx.bw.dcn.clk.stutter_efficiency.z8_stutter_period, + (int)context->bw_ctx.bw.dcn.clk.stutter_efficiency.z8_stutter_efficiency); + } + context->bw_ctx.bw.dcn.clk.zstate_support = support; + +} diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.h b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource_fpu.h index eca3e5168089..e32103220507 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.h +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource_fpu.h @@ -1,5 +1,6 @@ +/* SPDX-License-Identifier: MIT */ /* - * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com> + * Copyright 2026 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,18 +20,14 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * - * Authors: AMD - * */ -#ifndef DAL_DC_DCE_DCE60_CLK_MGR_H_ -#define DAL_DC_DCE_DCE60_CLK_MGR_H_ +#ifndef _DCN42_RESOURCE_FPU_H_ +#define _DCN42_RESOURCE_FPU_H_ -#include "dc.h" +#include "core_types.h" -void dce60_clk_mgr_construct( - struct dc_context *ctx, - struct clk_mgr_internal *clk_mgr_dce); +void dcn42_decide_zstate_support(struct dc *dc, struct dc_state *context); -#endif /* DAL_DC_DCE_DCE60_CLK_MGR_H_ */ +#endif /* _DCN42_RESOURCE_FPU_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/Makefile b/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/Makefile index bc93356a0b5b..d168fb1eacf7 100644 --- a/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/Makefile +++ b/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/Makefile @@ -8,11 +8,14 @@ soc_and_ip_translator_ccflags := $(CC_FLAGS_FPU) soc_and_ip_translator_rcflags := $(CC_FLAGS_NO_FPU) CFLAGS_$(AMDDALPATH)/dc/soc_and_ip_translator/dcn401/dcn401_soc_and_ip_translator.o := $(soc_and_ip_translator_ccflags) +CFLAGS_$(AMDDALPATH)/dc/soc_and_ip_translator/dcn42/dcn42_soc_and_ip_translator.o := $(soc_and_ip_translator_ccflags) CFLAGS_REMOVE_$(AMDDALPATH)/dc/soc_and_ip_translator/dcn401/dcn401_soc_and_ip_translator.o := $(soc_and_ip_translator_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/soc_and_ip_translator/dcn42/dcn42_soc_and_ip_translator.o := $(soc_and_ip_translator_rcflags) soc_and_ip_translator := soc_and_ip_translator.o soc_and_ip_translator += dcn401/dcn401_soc_and_ip_translator.o +soc_and_ip_translator += dcn42/dcn42_soc_and_ip_translator.o AMD_DAL_soc_and_ip_translator := $(addprefix $(AMDDALPATH)/dc/soc_and_ip_translator/, $(soc_and_ip_translator)) diff --git a/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn401/dcn401_soc_and_ip_translator.c b/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn401/dcn401_soc_and_ip_translator.c index 3190c76eb482..1b397fa7e05c 100644 --- a/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn401/dcn401_soc_and_ip_translator.c +++ b/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn401/dcn401_soc_and_ip_translator.c @@ -102,6 +102,9 @@ static void dcn401_convert_dc_clock_table_to_soc_bb_clock_table( } } else { dml_clk_table->uclk.clk_values_khz[i] = dc_clk_table->entries[i].memclk_mhz * 1000; + #ifdef ENABLE_WCK + dml_clk_table->wck_ratio.clk_values_khz[i] = dc_clk_table->entries[i].wck_ratio; + #endif } } else { dml_clk_table->uclk.clk_values_khz[i] = 0; diff --git a/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn42/dcn42_soc_and_ip_translator.c b/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn42/dcn42_soc_and_ip_translator.c index c9e224d262c9..146a6e47934b 100644 --- a/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn42/dcn42_soc_and_ip_translator.c +++ b/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn42/dcn42_soc_and_ip_translator.c @@ -3,7 +3,7 @@ // Copyright 2025 Advanced Micro Devices, Inc. #include "dcn42_soc_and_ip_translator.h" -#include "soc_and_ip_translator/dcn401/dcn401_soc_and_ip_translator.h" +#include "../dcn401/dcn401_soc_and_ip_translator.h" #include "bounding_boxes/dcn42_soc_bb.h" /* soc_and_ip_translator component used to get up-to-date values for bounding box. @@ -11,13 +11,180 @@ * This component provides an interface to get DCN-specific bounding box values. */ +static void get_default_soc_bb(struct dml2_soc_bb *soc_bb, const struct dc *dc) +{ + { + memcpy(soc_bb, &dml2_socbb_dcn42, sizeof(struct dml2_soc_bb)); + memcpy(&soc_bb->qos_parameters, &dml_dcn42_variant_a_soc_qos_params, sizeof(struct dml2_soc_qos_parameters)); + } +} + +/* + * DC clock table is obtained from SMU during runtime. + * SMU stands for System Management Unit. It is a power management processor. + * It owns the initialization of dc's clock table and programming of clock values + * based on dc's requests. + * Our clock values in base soc bb is a dummy placeholder. The real clock values + * are retrieved from SMU firmware to dc clock table at runtime. + * This function overrides our dummy placeholder values with real values in dc + * clock table. + */ +static void dcn42_convert_dc_clock_table_to_soc_bb_clock_table( + struct dml2_soc_state_table *dml_clk_table, + struct dml2_soc_vmin_clock_limits *vmin_limit, + const struct clk_bw_params *dc_bw_params) +{ + int i; + const struct clk_limit_table *dc_clk_table; + + if (dc_bw_params == NULL) + /* skip if bw params could not be obtained from smu */ + return; + + dc_clk_table = &dc_bw_params->clk_table; + + /* fclk/dcfclk - dcn42 pmfw table can have 0 entries for inactive dpm levels + * for use with dml we need to fill in using an active value aiming for >= 2x DCFCLK + */ + if (dc_clk_table->num_entries_per_clk.num_fclk_levels && dc_clk_table->num_entries_per_clk.num_dcfclk_levels) { + dml_clk_table->fclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_dcfclk_levels; + dml_clk_table->dcfclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_dcfclk_levels; + for (i = 0; i < min(DML_MAX_CLK_TABLE_SIZE, MAX_NUM_DPM_LVL); i++) { + if (i < dc_clk_table->num_entries_per_clk.num_dcfclk_levels) { + int j, max_fclk = 0; + + dml_clk_table->dcfclk.clk_values_khz[i] = dc_clk_table->entries[i].dcfclk_mhz * 1000; + for (j = 0; j < MAX_NUM_DPM_LVL; j++) { + if (dc_clk_table->entries[j].fclk_mhz * 1000 > max_fclk) + max_fclk = dc_clk_table->entries[j].fclk_mhz * 1000; + dml_clk_table->fclk.clk_values_khz[i] = max_fclk; + if (max_fclk >= 2 * dml_clk_table->dcfclk.clk_values_khz[i]) + break; + } + } else { + dml_clk_table->dcfclk.clk_values_khz[i] = 0; + dml_clk_table->fclk.clk_values_khz[i] = 0; + } + } + } + + /* uclk */ + if (dc_clk_table->num_entries_per_clk.num_memclk_levels) { + dml_clk_table->uclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_memclk_levels; + for (i = 0; i < min(DML_MAX_CLK_TABLE_SIZE, MAX_NUM_DPM_LVL); i++) { + if (i < dml_clk_table->uclk.num_clk_values) { + dml_clk_table->uclk.clk_values_khz[i] = dc_clk_table->entries[i].memclk_mhz * 1000; + dml_clk_table->wck_ratio.clk_values_khz[i] = dc_clk_table->entries[i].wck_ratio; + } else { + dml_clk_table->uclk.clk_values_khz[i] = 0; + dml_clk_table->wck_ratio.clk_values_khz[i] = 0; + } + } + } + + /* dispclk */ + if (dc_clk_table->num_entries_per_clk.num_dispclk_levels) { + dml_clk_table->dispclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_dispclk_levels; + for (i = 0; i < min(DML_MAX_CLK_TABLE_SIZE, MAX_NUM_DPM_LVL); i++) { + if (i < dml_clk_table->dispclk.num_clk_values) { + dml_clk_table->dispclk.clk_values_khz[i] = dc_clk_table->entries[i].dispclk_mhz * 1000; + } else { + dml_clk_table->dispclk.clk_values_khz[i] = 0; + } + } + vmin_limit->dispclk_khz = min(dc_clk_table->entries[0].dispclk_mhz * 1000, vmin_limit->dispclk_khz); + /* dispclk is always fine-grain */ + dml_clk_table->dispclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_dispclk_levels >= 2 ? 2 : 1; + dml_clk_table->dispclk.clk_values_khz[0] = 0; + dml_clk_table->dispclk.clk_values_khz[1] = dc_clk_table->entries[dc_clk_table->num_entries_per_clk.num_dispclk_levels - 1].dispclk_mhz * 1000; + } + + /* dppclk */ + if (dc_clk_table->num_entries_per_clk.num_dppclk_levels) { + dml_clk_table->dppclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_dppclk_levels; + for (i = 0; i < min(DML_MAX_CLK_TABLE_SIZE, MAX_NUM_DPM_LVL); i++) { + if (i < dml_clk_table->dppclk.num_clk_values) { + dml_clk_table->dppclk.clk_values_khz[i] = dc_clk_table->entries[i].dppclk_mhz * 1000; + } else { + dml_clk_table->dppclk.clk_values_khz[i] = 0; + } + } + /* dppclk is always fine-grain */ + dml_clk_table->dppclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_dppclk_levels >= 2 ? 2 : 1; + dml_clk_table->dppclk.clk_values_khz[0] = 0; + dml_clk_table->dppclk.clk_values_khz[1] = dc_clk_table->entries[dc_clk_table->num_entries_per_clk.num_dppclk_levels - 1].dppclk_mhz * 1000; + } + + /* dtbclk */ + if (dc_clk_table->num_entries_per_clk.num_dtbclk_levels) { + dml_clk_table->dtbclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_dtbclk_levels; + for (i = 0; i < min(DML_MAX_CLK_TABLE_SIZE, MAX_NUM_DPM_LVL); i++) { + if (i < dml_clk_table->dtbclk.num_clk_values) { + dml_clk_table->dtbclk.clk_values_khz[i] = dc_clk_table->entries[i].dtbclk_mhz * 1000; + } else { + dml_clk_table->dtbclk.clk_values_khz[i] = 0; + } + } + } + + /* socclk */ + if (dc_clk_table->num_entries_per_clk.num_socclk_levels) { + dml_clk_table->socclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_socclk_levels; + for (i = 0; i < min(DML_MAX_CLK_TABLE_SIZE, MAX_NUM_DPM_LVL); i++) { + if (i < dml_clk_table->socclk.num_clk_values) { + dml_clk_table->socclk.clk_values_khz[i] = dc_clk_table->entries[i].socclk_mhz * 1000; + } else { + dml_clk_table->socclk.clk_values_khz[i] = 0; + } + } + } + + /* dram config */ + dml_clk_table->dram_config.channel_count = dc_bw_params->num_channels; + dml_clk_table->dram_config.channel_width_bytes = dc_bw_params->dram_channel_width_bytes; +} + +static void dcn42_update_soc_bb_with_values_from_clk_mgr(struct dml2_soc_bb *soc_bb, const struct dc *dc) +{ + soc_bb->dprefclk_mhz = dc->clk_mgr->dprefclk_khz / 1000; + soc_bb->dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; + soc_bb->mall_allocated_for_dcn_mbytes = dc->caps.mall_size_total / (1024 * 1024); + + if (dc->clk_mgr->funcs->is_smu_present && + dc->clk_mgr->funcs->is_smu_present(dc->clk_mgr)) { + dcn42_convert_dc_clock_table_to_soc_bb_clock_table(&soc_bb->clk_table, &soc_bb->vmin_limit, + dc->clk_mgr->bw_params); + } +} + +static void apply_soc_bb_updates(struct dml2_soc_bb *soc_bb, const struct dc *dc, const struct dml2_configuration_options *config) +{ + (void)config; + /* Individual modification can be overwritten even if it was obtained by a previous function. + * Modifications are acquired in order of priority (lowest to highest). + */ + dc_assert_fp_enabled(); + + dcn42_update_soc_bb_with_values_from_clk_mgr(soc_bb, dc); + dcn401_update_soc_bb_with_values_from_vbios(soc_bb, dc); + dcn401_update_soc_bb_with_values_from_software_policy(soc_bb, dc); +} + +void dcn42_get_soc_bb(struct dml2_soc_bb *soc_bb, const struct dc *dc, const struct dml2_configuration_options *config) +{ + //get default soc_bb with static values + get_default_soc_bb(soc_bb, dc); + //update soc_bb values with more accurate values + apply_soc_bb_updates(soc_bb, dc, config); +} + static void dcn42_get_ip_caps(struct dml2_ip_capabilities *ip_caps) { *ip_caps = dml2_dcn42_max_ip_caps; } static struct soc_and_ip_translator_funcs dcn42_translator_funcs = { - .get_soc_bb = dcn401_get_soc_bb, + .get_soc_bb = dcn42_get_soc_bb, .get_ip_caps = dcn42_get_ip_caps, }; @@ -25,3 +192,4 @@ void dcn42_construct_soc_and_ip_translator(struct soc_and_ip_translator *soc_and { soc_and_ip_translator->translator_funcs = &dcn42_translator_funcs; } + diff --git a/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn42/dcn42_soc_and_ip_translator.h b/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn42/dcn42_soc_and_ip_translator.h index 914dcbb369a7..1dded5426152 100644 --- a/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn42/dcn42_soc_and_ip_translator.h +++ b/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn42/dcn42_soc_and_ip_translator.h @@ -12,5 +12,6 @@ #include "soc_and_ip_translator.h" void dcn42_construct_soc_and_ip_translator(struct soc_and_ip_translator *soc_and_ip_translator); +void dcn42_get_soc_bb(struct dml2_soc_bb *soc_bb, const struct dc *dc, const struct dml2_configuration_options *config); #endif /* _DCN42_SOC_AND_IP_TRANSLATOR_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/soc_and_ip_translator.c b/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/soc_and_ip_translator.c index 6617c9d2d5f8..bad0bd79fa94 100644 --- a/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/soc_and_ip_translator.c +++ b/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/soc_and_ip_translator.c @@ -4,6 +4,7 @@ #include "soc_and_ip_translator.h" #include "soc_and_ip_translator/dcn401/dcn401_soc_and_ip_translator.h" +#include "soc_and_ip_translator/dcn42/dcn42_soc_and_ip_translator.h" static void dc_construct_soc_and_ip_translator(struct soc_and_ip_translator *soc_and_ip_translator, enum dce_version dc_version) @@ -12,6 +13,9 @@ static void dc_construct_soc_and_ip_translator(struct soc_and_ip_translator *soc case DCN_VERSION_4_01: dcn401_construct_soc_and_ip_translator(soc_and_ip_translator); break; + case DCN_VERSION_4_2: + dcn42_construct_soc_and_ip_translator(soc_and_ip_translator); + break; default: break; } diff --git a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h index 3b6bba017040..c18ff8f00bb8 100644 --- a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h +++ b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h @@ -1,5 +1,6 @@ +/* SPDX-License-Identifier: MIT */ /* - * Copyright 2019 Advanced Micro Devices, Inc. + * Copyright 2019-2026 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -119,6 +120,7 @@ enum dmub_asic { DMUB_ASIC_DCN351, DMUB_ASIC_DCN36, DMUB_ASIC_DCN401, + DMUB_ASIC_DCN42, DMUB_ASIC_MAX, }; @@ -602,6 +604,7 @@ struct dmub_srv { struct dmub_srv_dcn32_regs *regs_dcn32; struct dmub_srv_dcn35_regs *regs_dcn35; const struct dmub_srv_dcn401_regs *regs_dcn401; + struct dmub_srv_dcn42_regs *regs_dcn42; struct dmub_srv_base_funcs funcs; struct dmub_srv_hw_funcs hw_funcs; struct dmub_srv_inbox inbox1; diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 6f388c910e18..fe9431cea3e5 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -909,7 +909,8 @@ union dmub_fw_meta_feature_bits { struct { uint32_t shared_state_link_detection : 1; /**< 1 supports link detection via shared state */ uint32_t cursor_offload_v1_support: 1; /**< 1 supports cursor offload */ - uint32_t reserved : 30; + uint32_t inbox0_lock_support: 1; /**< 1 supports inbox0 lock mechanism */ + uint32_t reserved : 29; } bits; /**< status bits */ uint32_t all; /**< 32-bit access to status bits */ }; @@ -1535,14 +1536,12 @@ enum dmub_gpint_command { * 1 - Enable ips measurement */ DMUB_GPINT__IPS_RESIDENCY = 121, - /** * DESC: Enable measurements for various task duration * ARGS: 0 - Disable measurement * 1 - Enable measurement */ DMUB_GPINT__TRACE_DMUB_WAKE_ACTIVITY = 123, - /** * DESC: Gets IPS residency in microseconds * ARGS: 0 - Return IPS1 residency @@ -1552,21 +1551,18 @@ enum dmub_gpint_command { * RETURN: Total residency in microseconds - lower 32 bits */ DMUB_GPINT__GET_IPS_RESIDENCY_DURATION_US_LO = 124, - /** * DESC: Gets IPS1 histogram counts * ARGS: Bucket index * RETURN: Total count for the bucket */ DMUB_GPINT__GET_IPS1_HISTOGRAM_COUNTER = 125, - /** * DESC: Gets IPS2 histogram counts * ARGS: Bucket index * RETURN: Total count for the bucket */ DMUB_GPINT__GET_IPS2_HISTOGRAM_COUNTER = 126, - /** * DESC: Gets IPS residency * ARGS: 0 - Return IPS1 residency @@ -1576,21 +1572,18 @@ enum dmub_gpint_command { * RETURN: Total residency in milli-percent. */ DMUB_GPINT__GET_IPS_RESIDENCY_PERCENT = 127, - /** * DESC: Gets IPS1_RCG histogram counts * ARGS: Bucket index * RETURN: Total count for the bucket */ DMUB_GPINT__GET_IPS1_RCG_HISTOGRAM_COUNTER = 128, - /** * DESC: Gets IPS1_ONO2_ON histogram counts * ARGS: Bucket index * RETURN: Total count for the bucket */ DMUB_GPINT__GET_IPS1_ONO2_ON_HISTOGRAM_COUNTER = 129, - /** * DESC: Gets IPS entry counter during residency measurement * ARGS: 0 - Return IPS1 entry counts @@ -1600,7 +1593,6 @@ enum dmub_gpint_command { * RETURN: Entry counter for selected IPS mode */ DMUB_GPINT__GET_IPS_RESIDENCY_ENTRY_COUNTER = 130, - /** * DESC: Gets IPS inactive residency in microseconds * ARGS: 0 - Return IPS1_MAX residency @@ -1610,7 +1602,6 @@ enum dmub_gpint_command { * RETURN: Total inactive residency in microseconds - lower 32 bits */ DMUB_GPINT__GET_IPS_INACTIVE_RESIDENCY_DURATION_US_LO = 131, - /** * DESC: Gets IPS inactive residency in microseconds * ARGS: 0 - Return IPS1_MAX residency @@ -1620,7 +1611,6 @@ enum dmub_gpint_command { * RETURN: Total inactive residency in microseconds - upper 32 bits */ DMUB_GPINT__GET_IPS_INACTIVE_RESIDENCY_DURATION_US_HI = 132, - /** * DESC: Gets IPS residency in microseconds * ARGS: 0 - Return IPS1 residency @@ -1679,7 +1669,7 @@ union dmub_inbox0_cmd_lock_hw { uint32_t lock: 1; /**< Lock */ uint32_t should_release: 1; /**< Release */ - uint32_t reserved: 7; /**< Reserved for extending more clients, HW, etc. */ + uint32_t reserved: 7; /**< Reserved for extending more clients, HW, etc. */ } bits; uint32_t all; }; @@ -1897,6 +1887,15 @@ enum dmub_cmd_type { */ DMUB_CMD__PR = 94, + /** + * Command type used for all IHC commands. + */ + DMUB_CMD__IHC = 95, + + /** + * Command type use for boot time crc commands. + */ + DMUB_CMD__BOOT_TIME_CRC = 96, /** * Command type use for VBIOS shared commands. @@ -2610,9 +2609,9 @@ struct dmub_fams2_stream_static_state { uint8_t allow_to_target_delay_otg_vlines; // time from allow vline to target vline union { struct { - uint8_t is_drr: 1; // stream is DRR enabled - uint8_t clamp_vtotal_min: 1; // clamp vtotal to min instead of nominal - uint8_t min_ttu_vblank_usable: 1; // if min ttu vblank is above wm, no force pstate is needed in blank + uint8_t is_drr : 1; // stream is DRR enabled + uint8_t clamp_vtotal_min : 1; // clamp vtotal to min instead of nominal + uint8_t min_ttu_vblank_usable : 1; // if min ttu vblank is above wm, no force pstate is needed in blank } bits; uint8_t all; } config; @@ -4437,6 +4436,8 @@ enum dmub_cmd_replay_general_subtype { REPLAY_GENERAL_CMD_SET_LOW_RR_ACTIVATE, REPLAY_GENERAL_CMD_VIDEO_CONFERENCING, REPLAY_GENERAL_CMD_SET_CONTINUOUSLY_RESYNC, + REPLAY_GENERAL_CMD_SET_COASTING_VTOTAL_WITHOUT_FRAME_UPDATE, + REPLAY_GENERAL_CMD_LIVE_CAPTURE_WITH_CVT, }; struct dmub_alpm_auxless_data { @@ -4655,6 +4656,18 @@ struct dmub_rb_cmd_replay_enable_data { * This does not support HDMI/DP2 for now. */ uint8_t phy_rate; + /** + * @hpo_stream_enc_inst: HPO stream encoder instance + */ + uint8_t hpo_stream_enc_inst; + /** + * @hpo_link_enc_inst: HPO link encoder instance + */ + uint8_t hpo_link_enc_inst; + /** + * @pad: Align structure to 4 byte boundary. + */ + uint8_t pad[2]; }; /** @@ -4960,6 +4973,52 @@ union dmub_replay_cmd_set { }; /** + * IHC command sub-types. + */ +enum dmub_cmd_ihc_type { + /** + * Set DIG HDCP interrupt destination. + */ + DMUB_CMD__IHC_SET_DIG_HDCP_INTERRUPT_DEST = 0, +}; + +/** + * Data passed from driver to FW in a DMUB_CMD__IHC command. + */ +struct dmub_cmd_ihc_data { + /** + * DIG engine ID (0-3). + */ + uint8_t dig_id; + /** + * 1 = route to DMU, 0 = route to CPU. + */ + uint8_t to_dmu : 1; + /** + * Reserved bits. + */ + uint8_t reserved : 7; + /** + * Padding. + */ + uint8_t pad[2]; +}; + +/** + * Definition of a DMUB_CMD__IHC command. + */ +struct dmub_rb_cmd_ihc { + /** + * Command header. + */ + struct dmub_cmd_header header; + /** + * IHC command data. + */ + struct dmub_cmd_ihc_data data; +}; + +/** * SMART POWER OLED command sub-types. */ enum dmub_cmd_smart_power_oled_type { @@ -5222,8 +5281,8 @@ enum dmub_cmd_lsdma_type { */ DMUB_CMD__LSDMA_LINEAR_COPY = 1, /** - * LSDMA copies data from source to destination linearly in sub window - */ + * LSDMA copies data from source to destination linearly in sub window + */ DMUB_CMD__LSDMA_LINEAR_SUB_WINDOW_COPY = 2, /** * Send the tiled-to-tiled copy command @@ -6213,6 +6272,7 @@ struct dmub_cmd_edid_cea_amd_vsdb { uint16_t amd_vsdb_version; /**< AMD VSDB version */ uint16_t min_frame_rate; /**< Maximum frame rate */ uint16_t max_frame_rate; /**< Minimum frame rate */ + uint8_t freesync_mccs_vcp_code; /**< Freesync MCCS VCP code */ }; /** @@ -6786,6 +6846,29 @@ struct dmub_rb_cmd_pr_general_cmd { }; /** + * Command type of a DMUB_CMD__BOOT_TIME_CRC command + */ +enum dmub_cmd_boot_time_crc_type { + DMUB_CMD__BOOT_TIME_CRC_INIT_MEM = 0 +}; + +/** + * Data passed from driver to FW in a DMUB_CMD__BOOT_TIME_CRC_INIT command. + */ +struct dmub_cmd_boot_time_crc_init_data { + union dmub_addr buffer_addr; + uint32_t buffer_size; +}; + +/** + * Definition of a DMUB_CMD__BOOT_TIME_CRC_INIT command. + */ +struct dmub_rb_cmd_boot_time_crc_init { + struct dmub_cmd_header header; + struct dmub_cmd_boot_time_crc_init_data data; +}; + +/** * union dmub_rb_cmd - DMUB inbox command. */ union dmub_rb_cmd { @@ -7142,6 +7225,14 @@ union dmub_rb_cmd { struct dmub_rb_cmd_pr_update_state pr_update_state; struct dmub_rb_cmd_pr_general_cmd pr_general_cmd; + /** + * Definition of a DMUB_CMD__IHC command. + */ + struct dmub_rb_cmd_ihc ihc; + /** + * Definition of a DMUB_CMD__BOOT_TIME_CRC_INIT command. + */ + struct dmub_rb_cmd_boot_time_crc_init boot_time_crc_init; }; /** diff --git a/drivers/gpu/drm/amd/display/dmub/src/Makefile b/drivers/gpu/drm/amd/display/dmub/src/Makefile index 468b768c11ae..ac7b17d8fb0f 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/Makefile +++ b/drivers/gpu/drm/amd/display/dmub/src/Makefile @@ -1,5 +1,5 @@ # -# Copyright 2019 Advanced Micro Devices, Inc. +# Copyright 2019-2026 Advanced Micro Devices, Inc. # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), @@ -28,6 +28,7 @@ DMUB += dmub_dcn35.o DMUB += dmub_dcn351.o DMUB += dmub_dcn36.o DMUB += dmub_dcn401.o +DMUB += dmub_dcn42.o AMD_DAL_DMUB = $(addprefix $(AMDDALPATH)/dmub/src/,$(DMUB)) diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c index 54df2147e4dc..0b152926f75b 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c @@ -194,6 +194,7 @@ void dmub_dcn20_setup_windows(struct dmub_srv *dmub, const struct dmub_window *cw6, const struct dmub_window *region6) { + (void)region6; union dmub_addr offset; uint64_t fb_base, fb_offset; @@ -396,6 +397,7 @@ union dmub_fw_boot_status dmub_dcn20_get_fw_boot_status(struct dmub_srv *dmub) void dmub_dcn20_enable_dmub_boot_options(struct dmub_srv *dmub, const struct dmub_srv_hw_params *params) { + (void)params; union dmub_fw_boot_options boot_options = {0}; REG_WRITE(DMCUB_SCRATCH14, boot_options.all); @@ -460,20 +462,26 @@ void dmub_dcn20_get_diagnostic_data(struct dmub_srv *dmub) dmub->debug.inbox0_size = REG_READ(DMCUB_INBOX0_SIZE); REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled); - dmub->debug.is_dmcub_enabled = is_dmub_enabled; + ASSERT(is_dmub_enabled <= 0xFF); + dmub->debug.is_dmcub_enabled = (uint8_t)is_dmub_enabled; REG_GET(DMCUB_CNTL, DMCUB_SOFT_RESET, &is_soft_reset); - dmub->debug.is_dmcub_soft_reset = is_soft_reset; + ASSERT(is_soft_reset <= 0xFF); + dmub->debug.is_dmcub_soft_reset = (uint8_t)is_soft_reset; REG_GET(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS, &is_sec_reset); - dmub->debug.is_dmcub_secure_reset = is_sec_reset; + ASSERT(is_sec_reset <= 0xFF); + dmub->debug.is_dmcub_secure_reset = (uint8_t)is_sec_reset; REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled); - dmub->debug.is_traceport_en = is_traceport_enabled; + ASSERT(is_traceport_enabled <= 0xFF); + dmub->debug.is_traceport_en = (uint8_t)is_traceport_enabled; REG_GET(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE, &is_cw0_enabled); - dmub->debug.is_cw0_enabled = is_cw0_enabled; + ASSERT(is_cw0_enabled <= 0xFF); + dmub->debug.is_cw0_enabled = (uint8_t)is_cw0_enabled; REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled); - dmub->debug.is_cw6_enabled = is_cw6_enabled; + ASSERT(is_cw6_enabled <= 0xFF); + dmub->debug.is_cw6_enabled = (uint8_t)is_cw6_enabled; } diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c index 84a6eb3f677d..23a33db07edc 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c @@ -127,6 +127,7 @@ void dmub_dcn30_setup_windows(struct dmub_srv *dmub, const struct dmub_window *cw6, const struct dmub_window *region6) { + (void)region6; union dmub_addr offset; /* sienna_cichlid has hardwired virtual addressing for CW2-CW7 */ diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c index a0cefc03b21d..478d79a6e246 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c @@ -195,6 +195,8 @@ void dmub_dcn31_setup_windows(struct dmub_srv *dmub, const struct dmub_window *cw6, const struct dmub_window *region6) { + (void)cw2; + (void)region6; union dmub_addr offset; offset = cw3->offset; @@ -466,25 +468,32 @@ void dmub_dcn31_get_diagnostic_data(struct dmub_srv *dmub) dmub->debug.outbox1_size = REG_READ(DMCUB_OUTBOX1_SIZE); REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled); - dmub->debug.is_dmcub_enabled = is_dmub_enabled; + ASSERT(is_dmub_enabled <= 0xFF); + dmub->debug.is_dmcub_enabled = (uint8_t)is_dmub_enabled; REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &is_pwait); - dmub->debug.is_pwait = is_pwait; + ASSERT(is_pwait <= 0xFF); + dmub->debug.is_pwait = (uint8_t)is_pwait; REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &is_soft_reset); - dmub->debug.is_dmcub_soft_reset = is_soft_reset; + ASSERT(is_soft_reset <= 0xFF); + dmub->debug.is_dmcub_soft_reset = (uint8_t)is_soft_reset; REG_GET(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS, &is_sec_reset); - dmub->debug.is_dmcub_secure_reset = is_sec_reset; + ASSERT(is_sec_reset <= 0xFF); + dmub->debug.is_dmcub_secure_reset = (uint8_t)is_sec_reset; REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled); - dmub->debug.is_traceport_en = is_traceport_enabled; + ASSERT(is_traceport_enabled <= 0xFF); + dmub->debug.is_traceport_en = (uint8_t)is_traceport_enabled; REG_GET(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE, &is_cw0_enabled); - dmub->debug.is_cw0_enabled = is_cw0_enabled; + ASSERT(is_cw0_enabled <= 0xFF); + dmub->debug.is_cw0_enabled = (uint8_t)is_cw0_enabled; REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled); - dmub->debug.is_cw6_enabled = is_cw6_enabled; + ASSERT(is_cw6_enabled <= 0xFF); + dmub->debug.is_cw6_enabled = (uint8_t)is_cw6_enabled; } bool dmub_dcn31_should_detect(struct dmub_srv *dmub) diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c index 2f99a2772599..3f9fb9e05b79 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c @@ -237,6 +237,8 @@ void dmub_dcn32_setup_windows(struct dmub_srv *dmub, const struct dmub_window *cw6, const struct dmub_window *region6) { + (void)cw2; + (void)region6; union dmub_addr offset; offset = cw3->offset; @@ -486,19 +488,24 @@ void dmub_dcn32_get_diagnostic_data(struct dmub_srv *dmub) dmub->debug.outbox1_size = REG_READ(DMCUB_OUTBOX1_SIZE); REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled); - dmub->debug.is_dmcub_enabled = is_dmub_enabled; + ASSERT(is_dmub_enabled <= 0xFF); + dmub->debug.is_dmcub_enabled = (uint8_t)is_dmub_enabled; REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &is_pwait); - dmub->debug.is_pwait = is_pwait; + ASSERT(is_pwait <= 0xFF); + dmub->debug.is_pwait = (uint8_t)is_pwait; REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &is_soft_reset); - dmub->debug.is_dmcub_soft_reset = is_soft_reset; + ASSERT(is_soft_reset <= 0xFF); + dmub->debug.is_dmcub_soft_reset = (uint8_t)is_soft_reset; REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled); - dmub->debug.is_traceport_en = is_traceport_enabled; + ASSERT(is_traceport_enabled <= 0xFF); + dmub->debug.is_traceport_en = (uint8_t)is_traceport_enabled; REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled); - dmub->debug.is_cw6_enabled = is_cw6_enabled; + ASSERT(is_cw6_enabled <= 0xFF); + dmub->debug.is_cw6_enabled = (uint8_t)is_cw6_enabled; dmub->debug.gpint_datain0 = REG_READ(DMCUB_GPINT_DATAIN0); } diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c index 639f9835e5e9..69fb6084232e 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c @@ -222,6 +222,7 @@ void dmub_dcn35_setup_windows(struct dmub_srv *dmub, const struct dmub_window *cw6, const struct dmub_window *region6) { + (void)cw2; union dmub_addr offset; offset = cw3->offset; @@ -402,7 +403,7 @@ void dmub_dcn35_enable_dmub_boot_options(struct dmub_srv *dmub, const struct dmu union dmub_fw_boot_options boot_options = {0}; if (!dmub->dpia_supported) { - dmub->dpia_supported = dmub_dcn35_get_fw_boot_option(dmub).bits.enable_dpia; + dmub->dpia_supported = dmub_dcn35_get_fw_boot_option(dmub).bits.enable_dpia != 0; } boot_options.bits.z10_disable = params->disable_z10; @@ -508,19 +509,24 @@ void dmub_dcn35_get_diagnostic_data(struct dmub_srv *dmub) dmub->debug.outbox1_size = REG_READ(DMCUB_OUTBOX1_SIZE); REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled); - dmub->debug.is_dmcub_enabled = is_dmub_enabled; + ASSERT(is_dmub_enabled <= 0xFF); + dmub->debug.is_dmcub_enabled = (uint8_t)is_dmub_enabled; REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &is_pwait); - dmub->debug.is_pwait = is_pwait; + ASSERT(is_pwait <= 0xFF); + dmub->debug.is_pwait = (uint8_t)is_pwait; REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &is_soft_reset); - dmub->debug.is_dmcub_soft_reset = is_soft_reset; + ASSERT(is_soft_reset <= 0xFF); + dmub->debug.is_dmcub_soft_reset = (uint8_t)is_soft_reset; REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled); - dmub->debug.is_traceport_en = is_traceport_enabled; + ASSERT(is_traceport_enabled <= 0xFF); + dmub->debug.is_traceport_en = (uint8_t)is_traceport_enabled; REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled); - dmub->debug.is_cw6_enabled = is_cw6_enabled; + ASSERT(is_cw6_enabled <= 0xFF); + dmub->debug.is_cw6_enabled = (uint8_t)is_cw6_enabled; dmub->debug.gpint_datain0 = REG_READ(DMCUB_GPINT_DATAIN0); } diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c index 16ed07f0e96d..e5a78df80d72 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c @@ -213,6 +213,7 @@ void dmub_dcn401_setup_windows(struct dmub_srv *dmub, const struct dmub_window *cw6, const struct dmub_window *region6) { + (void)cw2; union dmub_addr offset; offset = cw3->offset; @@ -473,25 +474,32 @@ void dmub_dcn401_get_diagnostic_data(struct dmub_srv *dmub) dmub->debug.outbox1_size = REG_READ(DMCUB_OUTBOX1_SIZE); REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled); - dmub->debug.is_dmcub_enabled = is_dmub_enabled; + ASSERT(is_dmub_enabled <= 0xFF); + dmub->debug.is_dmcub_enabled = (uint8_t)is_dmub_enabled; REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &is_pwait); - dmub->debug.is_pwait = is_pwait; + ASSERT(is_pwait <= 0xFF); + dmub->debug.is_pwait = (uint8_t)is_pwait; REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &is_soft_reset); - dmub->debug.is_dmcub_soft_reset = is_soft_reset; + ASSERT(is_soft_reset <= 0xFF); + dmub->debug.is_dmcub_soft_reset = (uint8_t)is_soft_reset; REG_GET(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS, &is_sec_reset); - dmub->debug.is_dmcub_secure_reset = is_sec_reset; + ASSERT(is_sec_reset <= 0xFF); + dmub->debug.is_dmcub_secure_reset = (uint8_t)is_sec_reset; REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled); - dmub->debug.is_traceport_en = is_traceport_enabled; + ASSERT(is_traceport_enabled <= 0xFF); + dmub->debug.is_traceport_en = (uint8_t)is_traceport_enabled; REG_GET(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE, &is_cw0_enabled); - dmub->debug.is_cw0_enabled = is_cw0_enabled; + ASSERT(is_cw0_enabled <= 0xFF); + dmub->debug.is_cw0_enabled = (uint8_t)is_cw0_enabled; REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled); - dmub->debug.is_cw6_enabled = is_cw6_enabled; + ASSERT(is_cw6_enabled <= 0xFF); + dmub->debug.is_cw6_enabled = (uint8_t)is_cw6_enabled; dmub->debug.gpint_datain0 = REG_READ(DMCUB_GPINT_DATAIN0); } diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn42.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn42.c new file mode 100644 index 000000000000..a09aa19ad379 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn42.c @@ -0,0 +1,759 @@ +// SPDX-License-Identifier: MIT +// +// Copyright 2026 Advanced Micro Devices, Inc. + +#include "../dmub_srv.h" +#include "dmub_reg.h" +#include "dmub_dcn35.h" +#include "dmub_dcn401.h" +#include "dmub_dcn42.h" + +#include "dcn/dcn_4_2_0_offset.h" +#include "dcn/dcn_4_2_0_sh_mask.h" + +#define BASE_INNER(seg) ctx->dcn_reg_offsets[seg] +#define CTX dmub +#define REGS dmub->regs_dcn42 +#define REG_OFFSET_EXP(reg_name) (BASE(reg##reg_name##_BASE_IDX) + reg##reg_name) + +void dmub_srv_dcn42_regs_init(struct dmub_srv *dmub, struct dc_context *ctx) +{ + struct dmub_srv_dcn42_regs *regs = dmub->regs_dcn42; +#define REG_STRUCT regs + +#define DMUB_SR(reg) REG_STRUCT->offset.reg = REG_OFFSET_EXP(reg); + DMUB_DCN42_REGS() + DMCUB_INTERNAL_REGS() +#undef DMUB_SR + +#define DMUB_SF(reg, field) REG_STRUCT->mask.reg##__##field = FD_MASK(reg, field); + DMUB_DCN42_FIELDS() +#undef DMUB_SF + +#define DMUB_SF(reg, field) REG_STRUCT->shift.reg##__##field = FD_SHIFT(reg, field); + DMUB_DCN42_FIELDS() +#undef DMUB_SF +#undef REG_STRUCT +} + +void dmub_dcn42_enable_dmub_boot_options(struct dmub_srv *dmub, const struct dmub_srv_hw_params *params) +{ + union dmub_fw_boot_options boot_options = {0}; + + if (!dmub->dpia_supported) { + dmub->dpia_supported = dmub_dcn42_get_fw_boot_option(dmub).bits.enable_dpia != 0; + } + + boot_options.bits.z10_disable = params->disable_z10; + boot_options.bits.dpia_supported = params->dpia_supported; + boot_options.bits.enable_dpia = dmub->dpia_supported && !params->disable_dpia; + boot_options.bits.usb4_cm_version = params->usb4_cm_version; + boot_options.bits.dpia_hpd_int_enable_supported = params->dpia_hpd_int_enable_supported; + boot_options.bits.power_optimization = params->power_optimization; + boot_options.bits.disable_clk_ds = params->disallow_dispclk_dppclk_ds; + boot_options.bits.disable_clk_gate = params->disable_clock_gate; + boot_options.bits.ips_disable = params->disable_ips; + boot_options.bits.ips_sequential_ono = params->ips_sequential_ono; + boot_options.bits.disable_sldo_opt = params->disable_sldo_opt; + boot_options.bits.enable_non_transparent_setconfig = params->enable_non_transparent_setconfig; + boot_options.bits.lower_hbr3_phy_ssc = params->lower_hbr3_phy_ssc; + boot_options.bits.skip_phy_access = params->disallow_phy_access; + boot_options.bits.disable_dpia_bw_allocation = params->disable_dpia_bw_allocation; + + REG_WRITE(DMCUB_SCRATCH14, boot_options.all); +} + +static void dmub_dcn42_get_fb_base_offset(struct dmub_srv *dmub, + uint64_t *fb_base, + uint64_t *fb_offset) +{ + uint32_t tmp; + + /* + if (dmub->soc_fb_info.fb_base || dmub->soc_fb_info.fb_offset) { + *fb_base = dmub->soc_fb_info.fb_base; + *fb_offset = dmub->soc_fb_info.fb_offset; + return; + } + */ + + REG_GET(DCN_VM_FB_LOCATION_BASE, FB_BASE, &tmp); + *fb_base = (uint64_t)tmp << 24; + + REG_GET(DCN_VM_FB_OFFSET, FB_OFFSET, &tmp); + *fb_offset = (uint64_t)tmp << 24; +} + +static inline void dmub_dcn42_translate_addr(const union dmub_addr *addr_in, + uint64_t fb_base, + uint64_t fb_offset, + union dmub_addr *addr_out) +{ + addr_out->quad_part = addr_in->quad_part - fb_base + fb_offset; +} + +void dmub_dcn42_reset(struct dmub_srv *dmub) +{ + union dmub_gpint_data_register cmd; + const uint32_t timeout = 100000; + uint32_t in_reset, is_enabled, scratch, i, pwait_mode; + + REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &in_reset); + REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_enabled); + + if (in_reset == 0 && is_enabled != 0) { + cmd.bits.status = 1; + cmd.bits.command_code = DMUB_GPINT__STOP_FW; + cmd.bits.param = 0; + + dmub->hw_funcs.set_gpint(dmub, cmd); + + for (i = 0; i < timeout; ++i) { + if (dmub->hw_funcs.is_gpint_acked(dmub, cmd)) + break; + + udelay(1); + } + + for (i = 0; i < timeout; ++i) { + scratch = REG_READ(DMCUB_SCRATCH7); + if (scratch == DMUB_GPINT__STOP_FW_RESPONSE) + break; + + udelay(1); + } + + for (i = 0; i < timeout; ++i) { + REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &pwait_mode); + if (pwait_mode & (1 << 0)) + break; + + udelay(1); + } + /* Force reset in case we timed out, DMCUB is likely hung. */ + } + + if (is_enabled) { + REG_UPDATE(DMCUB_CNTL2, DMCUB_SOFT_RESET, 1); + udelay(1); + REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0); + } + + REG_WRITE(DMCUB_INBOX1_RPTR, 0); + REG_WRITE(DMCUB_INBOX1_WPTR, 0); + REG_WRITE(DMCUB_OUTBOX1_RPTR, 0); + REG_WRITE(DMCUB_OUTBOX1_WPTR, 0); + REG_WRITE(DMCUB_OUTBOX0_RPTR, 0); + REG_WRITE(DMCUB_OUTBOX0_WPTR, 0); + REG_WRITE(DMCUB_SCRATCH0, 0); + + /* Clear the GPINT command manually so we don't send anything during boot. */ + cmd.all = 0; + dmub->hw_funcs.set_gpint(dmub, cmd); +} + +void dmub_dcn42_reset_release(struct dmub_srv *dmub) +{ + REG_WRITE(DMCUB_SCRATCH15, dmub->psp_version & 0x001100FF); + + REG_UPDATE_3(DMU_CLK_CNTL, + LONO_DISPCLK_GATE_DISABLE, 1, + LONO_SOCCLK_GATE_DISABLE, 1, + LONO_DMCUBCLK_GATE_DISABLE, 1); + + REG_UPDATE_2(DMCUB_CNTL, DMCUB_ENABLE, 1, DMCUB_TRACEPORT_EN, 1); + REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 0); + REG_UPDATE(DMCUB_CNTL2, DMCUB_SOFT_RESET, 0); +} + +void dmub_dcn42_backdoor_load(struct dmub_srv *dmub, + const struct dmub_window *cw0, + const struct dmub_window *cw1) +{ + union dmub_addr offset; + uint64_t fb_base, fb_offset; + + dmub_dcn42_get_fb_base_offset(dmub, &fb_base, &fb_offset); + + dmub_dcn42_translate_addr(&cw0->offset, fb_base, fb_offset, &offset); + + REG_WRITE(DMCUB_REGION3_CW0_OFFSET, offset.u.low_part); + REG_WRITE(DMCUB_REGION3_CW0_OFFSET_HIGH, offset.u.high_part); + REG_WRITE(DMCUB_REGION3_CW0_BASE_ADDRESS, cw0->region.base); + REG_SET_2(DMCUB_REGION3_CW0_TOP_ADDRESS, 0, + DMCUB_REGION3_CW0_TOP_ADDRESS, cw0->region.top, + DMCUB_REGION3_CW0_ENABLE, 1); + + dmub_dcn42_translate_addr(&cw1->offset, fb_base, fb_offset, &offset); + + REG_WRITE(DMCUB_REGION3_CW1_OFFSET, offset.u.low_part); + REG_WRITE(DMCUB_REGION3_CW1_OFFSET_HIGH, offset.u.high_part); + REG_WRITE(DMCUB_REGION3_CW1_BASE_ADDRESS, cw1->region.base); + REG_SET_2(DMCUB_REGION3_CW1_TOP_ADDRESS, 0, + DMCUB_REGION3_CW1_TOP_ADDRESS, cw1->region.top, + DMCUB_REGION3_CW1_ENABLE, 1); + + /* TODO: Do we need to set DMCUB_MEM_UNIT_ID? */ + REG_UPDATE(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 0); +} + +void dmub_dcn42_backdoor_load_zfb_mode(struct dmub_srv *dmub, + const struct dmub_window *cw0, + const struct dmub_window *cw1) +{ + union dmub_addr offset; + + REG_UPDATE(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 1); + offset = cw0->offset; + REG_WRITE(DMCUB_REGION3_CW0_OFFSET, offset.u.low_part); + REG_WRITE(DMCUB_REGION3_CW0_OFFSET_HIGH, offset.u.high_part); + REG_WRITE(DMCUB_REGION3_CW0_BASE_ADDRESS, cw0->region.base); + REG_SET_2(DMCUB_REGION3_CW0_TOP_ADDRESS, 0, + DMCUB_REGION3_CW0_TOP_ADDRESS, cw0->region.top, + DMCUB_REGION3_CW0_ENABLE, 1); + offset = cw1->offset; + REG_WRITE(DMCUB_REGION3_CW1_OFFSET, offset.u.low_part); + REG_WRITE(DMCUB_REGION3_CW1_OFFSET_HIGH, offset.u.high_part); + REG_WRITE(DMCUB_REGION3_CW1_BASE_ADDRESS, cw1->region.base); + REG_SET_2(DMCUB_REGION3_CW1_TOP_ADDRESS, 0, + DMCUB_REGION3_CW1_TOP_ADDRESS, cw1->region.top, + DMCUB_REGION3_CW1_ENABLE, 1); + REG_UPDATE_2(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 0, DMCUB_MEM_UNIT_ID, + 0x20); +} +void dmub_dcn42_setup_windows(struct dmub_srv *dmub, + const struct dmub_window *cw2, + const struct dmub_window *cw3, + const struct dmub_window *cw4, + const struct dmub_window *cw5, + const struct dmub_window *cw6, + const struct dmub_window *region6) +{ + (void)cw2; + union dmub_addr offset; + + offset = cw3->offset; + + REG_WRITE(DMCUB_REGION3_CW3_OFFSET, offset.u.low_part); + REG_WRITE(DMCUB_REGION3_CW3_OFFSET_HIGH, offset.u.high_part); + REG_WRITE(DMCUB_REGION3_CW3_BASE_ADDRESS, cw3->region.base); + REG_SET_2(DMCUB_REGION3_CW3_TOP_ADDRESS, 0, + DMCUB_REGION3_CW3_TOP_ADDRESS, cw3->region.top, + DMCUB_REGION3_CW3_ENABLE, 1); + + offset = cw4->offset; + + REG_WRITE(DMCUB_REGION3_CW4_OFFSET, offset.u.low_part); + REG_WRITE(DMCUB_REGION3_CW4_OFFSET_HIGH, offset.u.high_part); + REG_WRITE(DMCUB_REGION3_CW4_BASE_ADDRESS, cw4->region.base); + REG_SET_2(DMCUB_REGION3_CW4_TOP_ADDRESS, 0, + DMCUB_REGION3_CW4_TOP_ADDRESS, cw4->region.top, + DMCUB_REGION3_CW4_ENABLE, 1); + + offset = cw5->offset; + + REG_WRITE(DMCUB_REGION3_CW5_OFFSET, offset.u.low_part); + REG_WRITE(DMCUB_REGION3_CW5_OFFSET_HIGH, offset.u.high_part); + REG_WRITE(DMCUB_REGION3_CW5_BASE_ADDRESS, cw5->region.base); + REG_SET_2(DMCUB_REGION3_CW5_TOP_ADDRESS, 0, + DMCUB_REGION3_CW5_TOP_ADDRESS, cw5->region.top, + DMCUB_REGION3_CW5_ENABLE, 1); + + REG_WRITE(DMCUB_REGION5_OFFSET, offset.u.low_part); + REG_WRITE(DMCUB_REGION5_OFFSET_HIGH, offset.u.high_part); + REG_SET_2(DMCUB_REGION5_TOP_ADDRESS, 0, + DMCUB_REGION5_TOP_ADDRESS, + cw5->region.top - cw5->region.base - 1, + DMCUB_REGION5_ENABLE, 1); + + offset = cw6->offset; + + REG_WRITE(DMCUB_REGION3_CW6_OFFSET, offset.u.low_part); + REG_WRITE(DMCUB_REGION3_CW6_OFFSET_HIGH, offset.u.high_part); + REG_WRITE(DMCUB_REGION3_CW6_BASE_ADDRESS, cw6->region.base); + REG_SET_2(DMCUB_REGION3_CW6_TOP_ADDRESS, 0, + DMCUB_REGION3_CW6_TOP_ADDRESS, cw6->region.top, + DMCUB_REGION3_CW6_ENABLE, 1); + + offset = region6->offset; + + REG_WRITE(DMCUB_REGION6_OFFSET, offset.u.low_part); + REG_WRITE(DMCUB_REGION6_OFFSET_HIGH, offset.u.high_part); + REG_SET_2(DMCUB_REGION6_TOP_ADDRESS, 0, + DMCUB_REGION6_TOP_ADDRESS, + region6->region.top - region6->region.base - 1, + DMCUB_REGION6_ENABLE, 1); +} + +uint32_t dmub_dcn42_get_inbox1_wptr(struct dmub_srv *dmub) +{ + return REG_READ(DMCUB_INBOX1_WPTR); +} + +uint32_t dmub_dcn42_get_inbox1_rptr(struct dmub_srv *dmub) +{ + return REG_READ(DMCUB_INBOX1_RPTR); +} + +void dmub_dcn42_setup_out_mailbox(struct dmub_srv *dmub, + const struct dmub_region *outbox1) +{ + REG_WRITE(DMCUB_OUTBOX1_BASE_ADDRESS, outbox1->base); + REG_WRITE(DMCUB_OUTBOX1_SIZE, outbox1->top - outbox1->base); +} + +uint32_t dmub_dcn42_get_outbox1_wptr(struct dmub_srv *dmub) +{ + /** + * outbox1 wptr register is accessed without locks (dal & dc) + * and to be called only by dmub_srv_stat_get_notification() + */ + return REG_READ(DMCUB_OUTBOX1_WPTR); +} + +void dmub_dcn42_set_outbox1_rptr(struct dmub_srv *dmub, uint32_t rptr_offset) +{ + /** + * outbox1 rptr register is accessed without locks (dal & dc) + * and to be called only by dmub_srv_stat_get_notification() + */ + REG_WRITE(DMCUB_OUTBOX1_RPTR, rptr_offset); +} + +bool dmub_dcn42_is_supported(struct dmub_srv *dmub) +{ + // DCN without DMUB is not a supported configuration; safe to assume that it is always + // present. + return true; +} + +union dmub_fw_boot_options dmub_dcn42_get_fw_boot_option(struct dmub_srv *dmub) +{ + union dmub_fw_boot_options option; + + option.all = REG_READ(DMCUB_SCRATCH14); + return option; +} + +void dmub_dcn42_setup_outbox0(struct dmub_srv *dmub, + const struct dmub_region *outbox0) +{ + REG_WRITE(DMCUB_OUTBOX0_BASE_ADDRESS, outbox0->base); + + REG_WRITE(DMCUB_OUTBOX0_SIZE, outbox0->top - outbox0->base); +} + +bool dmub_dcn42_should_detect(struct dmub_srv *dmub) +{ + uint32_t fw_boot_status = REG_READ(DMCUB_SCRATCH0); + bool should_detect = (fw_boot_status & DMUB_FW_BOOT_STATUS_BIT_DETECTION_REQUIRED) != 0; + return should_detect; +} + +void dmub_dcn42_send_inbox0_cmd(struct dmub_srv *dmub, union dmub_inbox0_data_register data) +{ + REG_WRITE(DMCUB_INBOX0_WPTR, data.inbox0_cmd_common.all); +} + +uint32_t dmub_dcn42_read_inbox0_ack_register(struct dmub_srv *dmub) +{ + return REG_READ(DMCUB_SCRATCH17); +} + +bool dmub_dcn42_is_hw_powered_up(struct dmub_srv *dmub) +{ + union dmub_fw_boot_status status; + uint32_t is_enable; + + REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_enable); + if (is_enable == 0) + return false; + + status.all = REG_READ(DMCUB_SCRATCH0); + + return (status.bits.dal_fw && status.bits.hw_power_init_done && status.bits.mailbox_rdy) || + (!status.bits.dal_fw && status.bits.mailbox_rdy); +} + +void dmub_dcn42_set_inbox1_wptr(struct dmub_srv *dmub, uint32_t wptr_offset) +{ + REG_WRITE(DMCUB_INBOX1_WPTR, wptr_offset); +} + +bool dmub_dcn42_is_hw_init(struct dmub_srv *dmub) +{ + union dmub_fw_boot_status status; + uint32_t is_hw_init; + + status.all = REG_READ(DMCUB_SCRATCH0); + REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_hw_init); + + return is_hw_init != 0 && status.bits.dal_fw; +} + +union dmub_fw_boot_status dmub_dcn42_get_fw_boot_status(struct dmub_srv *dmub) +{ + union dmub_fw_boot_status status; + + status.all = REG_READ(DMCUB_SCRATCH0); + return status; +} + +void dmub_dcn42_skip_dmub_panel_power_sequence(struct dmub_srv *dmub, bool skip) +{ + union dmub_fw_boot_options boot_options; + boot_options.all = REG_READ(DMCUB_SCRATCH14); + boot_options.bits.skip_phy_init_panel_sequence = skip; + REG_WRITE(DMCUB_SCRATCH14, boot_options.all); +} + +void dmub_dcn42_configure_dmub_in_system_memory(struct dmub_srv *dmub) +{ + /* DMCUB_REGION3_TMR_AXI_SPACE values: + * 0b011 (0x3) - FB physical address + * 0b100 (0x4) - GPU virtual address + * + * Default value is 0x3 (FB Physical address for TMR). When programming + * DMUB to be in system memory, change to 0x4. The system memory allocated + * is accessible by both GPU and CPU, so we use GPU virtual address. + */ + REG_WRITE(DMCUB_REGION3_TMR_AXI_SPACE, 0x4); +} + +void dmub_dcn42_clear_inbox0_ack_register(struct dmub_srv *dmub) +{ + REG_WRITE(DMCUB_SCRATCH17, 0); +} + +void dmub_dcn42_send_reg_inbox0_cmd_msg(struct dmub_srv *dmub, + union dmub_rb_cmd *cmd) +{ + uint32_t *dwords = (uint32_t *)cmd; + int32_t payload_size_bytes = cmd->cmd_common.header.payload_bytes; + uint32_t msg_index; + static_assert(sizeof(*cmd) == 64, "DMUB command size mismatch"); + + /* read remaining data based on payload size */ + for (msg_index = 0; msg_index < 15; msg_index++) { + if (payload_size_bytes <= msg_index * 4) { + break; + } + + switch (msg_index) { + case 0: + REG_WRITE(DMCUB_REG_INBOX0_MSG0, dwords[msg_index + 1]); + break; + case 1: + REG_WRITE(DMCUB_REG_INBOX0_MSG1, dwords[msg_index + 1]); + break; + case 2: + REG_WRITE(DMCUB_REG_INBOX0_MSG2, dwords[msg_index + 1]); + break; + case 3: + REG_WRITE(DMCUB_REG_INBOX0_MSG3, dwords[msg_index + 1]); + break; + case 4: + REG_WRITE(DMCUB_REG_INBOX0_MSG4, dwords[msg_index + 1]); + break; + case 5: + REG_WRITE(DMCUB_REG_INBOX0_MSG5, dwords[msg_index + 1]); + break; + case 6: + REG_WRITE(DMCUB_REG_INBOX0_MSG6, dwords[msg_index + 1]); + break; + case 7: + REG_WRITE(DMCUB_REG_INBOX0_MSG7, dwords[msg_index + 1]); + break; + case 8: + REG_WRITE(DMCUB_REG_INBOX0_MSG8, dwords[msg_index + 1]); + break; + case 9: + REG_WRITE(DMCUB_REG_INBOX0_MSG9, dwords[msg_index + 1]); + break; + case 10: + REG_WRITE(DMCUB_REG_INBOX0_MSG10, dwords[msg_index + 1]); + break; + case 11: + REG_WRITE(DMCUB_REG_INBOX0_MSG11, dwords[msg_index + 1]); + break; + case 12: + REG_WRITE(DMCUB_REG_INBOX0_MSG12, dwords[msg_index + 1]); + break; + case 13: + REG_WRITE(DMCUB_REG_INBOX0_MSG13, dwords[msg_index + 1]); + break; + case 14: + REG_WRITE(DMCUB_REG_INBOX0_MSG14, dwords[msg_index + 1]); + break; + } + } + + /* writing to INBOX RDY register will trigger DMUB REG INBOX0 RDY + * interrupt. + */ + REG_WRITE(DMCUB_REG_INBOX0_RDY, dwords[0]); +} + +uint32_t dmub_dcn42_read_reg_inbox0_rsp_int_status(struct dmub_srv *dmub) +{ + uint32_t status; + + REG_GET(HOST_INTERRUPT_CSR, HOST_REG_INBOX0_RSP_INT_STAT, &status); + return status; +} + +void dmub_dcn42_read_reg_inbox0_cmd_rsp(struct dmub_srv *dmub, + union dmub_rb_cmd *cmd) +{ + uint32_t *dwords = (uint32_t *)cmd; + + static_assert(sizeof(*cmd) == 64, "DMUB command size mismatch"); + + dwords[0] = REG_READ(DMCUB_REG_INBOX0_RSP); + dwords[1] = REG_READ(DMCUB_REG_INBOX0_MSG0); + dwords[2] = REG_READ(DMCUB_REG_INBOX0_MSG1); + dwords[3] = REG_READ(DMCUB_REG_INBOX0_MSG2); + dwords[4] = REG_READ(DMCUB_REG_INBOX0_MSG3); + dwords[5] = REG_READ(DMCUB_REG_INBOX0_MSG4); + dwords[6] = REG_READ(DMCUB_REG_INBOX0_MSG5); + dwords[7] = REG_READ(DMCUB_REG_INBOX0_MSG6); + dwords[8] = REG_READ(DMCUB_REG_INBOX0_MSG7); + dwords[9] = REG_READ(DMCUB_REG_INBOX0_MSG8); + dwords[10] = REG_READ(DMCUB_REG_INBOX0_MSG9); + dwords[11] = REG_READ(DMCUB_REG_INBOX0_MSG10); + dwords[12] = REG_READ(DMCUB_REG_INBOX0_MSG11); + dwords[13] = REG_READ(DMCUB_REG_INBOX0_MSG12); + dwords[14] = REG_READ(DMCUB_REG_INBOX0_MSG13); + dwords[15] = REG_READ(DMCUB_REG_INBOX0_MSG14); +} + +void dmub_dcn42_write_reg_inbox0_rsp_int_ack(struct dmub_srv *dmub) +{ + REG_UPDATE(HOST_INTERRUPT_CSR, HOST_REG_INBOX0_RSP_INT_ACK, 1); +} + +void dmub_dcn42_clear_reg_inbox0_rsp_int_ack(struct dmub_srv *dmub) +{ + REG_UPDATE(HOST_INTERRUPT_CSR, HOST_REG_INBOX0_RSP_INT_ACK, 0); +} + +void dmub_dcn42_enable_reg_inbox0_rsp_int(struct dmub_srv *dmub, bool enable) +{ + REG_UPDATE(HOST_INTERRUPT_CSR, HOST_REG_INBOX0_RSP_INT_EN, enable ? 1:0); +} + +void dmub_dcn42_write_reg_outbox0_rdy_int_ack(struct dmub_srv *dmub) +{ + REG_UPDATE(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_ACK, 1); + REG_UPDATE(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_ACK, 0); +} + +void dmub_dcn42_read_reg_outbox0_msg(struct dmub_srv *dmub, uint32_t *msg) +{ + *msg = REG_READ(DMCUB_REG_OUTBOX0_MSG0); +} + + +void dmub_dcn42_enable_reg_outbox0_rdy_int(struct dmub_srv *dmub, bool enable) +{ + REG_UPDATE(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_EN, enable ? 1:0); +} + +uint32_t dmub_dcn42_read_reg_outbox0_rdy_int_status(struct dmub_srv *dmub) +{ + uint32_t status; + + REG_GET(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_STAT, &status); + return status; +} + +void dmub_dcn42_setup_mailbox(struct dmub_srv *dmub, + const struct dmub_region *inbox1) +{ + REG_WRITE(DMCUB_INBOX1_BASE_ADDRESS, inbox1->base); + REG_WRITE(DMCUB_INBOX1_SIZE, inbox1->top - inbox1->base); +} + +void dmub_dcn42_set_gpint(struct dmub_srv *dmub, + union dmub_gpint_data_register reg) +{ + REG_WRITE(DMCUB_GPINT_DATAIN1, reg.all); +} + +bool dmub_dcn42_is_gpint_acked(struct dmub_srv *dmub, + union dmub_gpint_data_register reg) +{ + union dmub_gpint_data_register test; + + reg.bits.status = 0; + test.all = REG_READ(DMCUB_GPINT_DATAIN1); + + return test.all == reg.all; +} + +uint32_t dmub_dcn42_get_gpint_response(struct dmub_srv *dmub) +{ + return REG_READ(DMCUB_SCRATCH7); +} + +uint32_t dmub_dcn42_get_gpint_dataout(struct dmub_srv *dmub) +{ + uint32_t dataout = REG_READ(DMCUB_GPINT_DATAOUT); + + REG_UPDATE(DMCUB_INTERRUPT_ENABLE, DMCUB_GPINT_IH_INT_EN, 0); + + REG_WRITE(DMCUB_GPINT_DATAOUT, 0); + REG_UPDATE(DMCUB_INTERRUPT_ACK, DMCUB_GPINT_IH_INT_ACK, 1); + REG_UPDATE(DMCUB_INTERRUPT_ACK, DMCUB_GPINT_IH_INT_ACK, 0); + + REG_UPDATE(DMCUB_INTERRUPT_ENABLE, DMCUB_GPINT_IH_INT_EN, 1); + + return dataout; +} + +uint32_t dmub_dcn42_get_outbox0_wptr(struct dmub_srv *dmub) +{ + return REG_READ(DMCUB_OUTBOX0_WPTR); +} + +void dmub_dcn42_set_outbox0_rptr(struct dmub_srv *dmub, uint32_t rptr_offset) +{ + REG_WRITE(DMCUB_OUTBOX0_RPTR, rptr_offset); +} + +uint32_t dmub_dcn42_get_current_time(struct dmub_srv *dmub) +{ + return REG_READ(DMCUB_TIMER_CURRENT); +} + +void dmub_dcn42_get_diagnostic_data(struct dmub_srv *dmub) +{ + uint32_t is_dmub_enabled, is_soft_reset, is_sec_reset, is_pwait; + uint32_t is_traceport_enabled, is_cw0_enabled, is_cw6_enabled; + struct dmub_timeout_info timeout = {0}; + + if (!dmub) + return; + + /* timeout data filled externally, cache before resetting memory */ + timeout = dmub->debug.timeout_info; + memset(&dmub->debug, 0, sizeof(dmub->debug)); + dmub->debug.timeout_info = timeout; + + dmub->debug.dmcub_version = dmub->fw_version; + + dmub->debug.scratch[0] = REG_READ(DMCUB_SCRATCH0); + dmub->debug.scratch[1] = REG_READ(DMCUB_SCRATCH1); + dmub->debug.scratch[2] = REG_READ(DMCUB_SCRATCH2); + dmub->debug.scratch[3] = REG_READ(DMCUB_SCRATCH3); + dmub->debug.scratch[4] = REG_READ(DMCUB_SCRATCH4); + dmub->debug.scratch[5] = REG_READ(DMCUB_SCRATCH5); + dmub->debug.scratch[6] = REG_READ(DMCUB_SCRATCH6); + dmub->debug.scratch[7] = REG_READ(DMCUB_SCRATCH7); + dmub->debug.scratch[8] = REG_READ(DMCUB_SCRATCH8); + dmub->debug.scratch[9] = REG_READ(DMCUB_SCRATCH9); + dmub->debug.scratch[10] = REG_READ(DMCUB_SCRATCH10); + dmub->debug.scratch[11] = REG_READ(DMCUB_SCRATCH11); + dmub->debug.scratch[12] = REG_READ(DMCUB_SCRATCH12); + dmub->debug.scratch[13] = REG_READ(DMCUB_SCRATCH13); + dmub->debug.scratch[14] = REG_READ(DMCUB_SCRATCH14); + dmub->debug.scratch[15] = REG_READ(DMCUB_SCRATCH15); + dmub->debug.scratch[16] = REG_READ(DMCUB_SCRATCH16); + + dmub->debug.undefined_address_fault_addr = REG_READ(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR); + dmub->debug.inst_fetch_fault_addr = REG_READ(DMCUB_INST_FETCH_FAULT_ADDR); + dmub->debug.data_write_fault_addr = REG_READ(DMCUB_DATA_WRITE_FAULT_ADDR); + + dmub->debug.inbox1_rptr = REG_READ(DMCUB_INBOX1_RPTR); + dmub->debug.inbox1_wptr = REG_READ(DMCUB_INBOX1_WPTR); + dmub->debug.inbox1_size = REG_READ(DMCUB_INBOX1_SIZE); + + dmub->debug.inbox0_rptr = REG_READ(DMCUB_INBOX0_RPTR); + dmub->debug.inbox0_wptr = REG_READ(DMCUB_INBOX0_WPTR); + dmub->debug.inbox0_size = REG_READ(DMCUB_INBOX0_SIZE); + + dmub->debug.outbox1_rptr = REG_READ(DMCUB_OUTBOX1_RPTR); + dmub->debug.outbox1_wptr = REG_READ(DMCUB_OUTBOX1_WPTR); + dmub->debug.outbox1_size = REG_READ(DMCUB_OUTBOX1_SIZE); + + REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled); + ASSERT(is_dmub_enabled <= 0xFF); + dmub->debug.is_dmcub_enabled = (uint8_t)is_dmub_enabled; + + REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &is_pwait); + ASSERT(is_pwait <= 0xFF); + dmub->debug.is_pwait = (uint8_t)is_pwait; + + REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &is_soft_reset); + ASSERT(is_soft_reset <= 0xFF); + dmub->debug.is_dmcub_soft_reset = (uint8_t)is_soft_reset; + + REG_GET(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS, &is_sec_reset); + ASSERT(is_sec_reset <= 0xFF); + dmub->debug.is_dmcub_secure_reset = (uint8_t)is_sec_reset; + + REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled); + ASSERT(is_traceport_enabled <= 0xFF); + dmub->debug.is_traceport_en = (uint8_t)is_traceport_enabled; + + REG_GET(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE, &is_cw0_enabled); + ASSERT(is_cw0_enabled <= 0xFF); + dmub->debug.is_cw0_enabled = (uint8_t)is_cw0_enabled; + + REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled); + ASSERT(is_cw6_enabled <= 0xFF); + dmub->debug.is_cw6_enabled = (uint8_t)is_cw6_enabled; + + dmub->debug.gpint_datain0 = REG_READ(DMCUB_GPINT_DATAIN0); +} + +bool dmub_dcn42_get_preos_fw_info(struct dmub_srv *dmub) +{ + uint64_t region3_cw5_offset; + uint32_t top_addr, top_addr_enable, offset_low; + uint32_t offset_high, base_addr, fw_version; + bool is_vbios_fw = false; + + memset(&dmub->preos_info, 0, sizeof(dmub->preos_info)); + + fw_version = REG_READ(DMCUB_SCRATCH1); + is_vbios_fw = ((fw_version >> 6) & 0x01) ? true : false; + if (!is_vbios_fw) + return false; + + dmub->preos_info.boot_status = REG_READ(DMCUB_SCRATCH0); + dmub->preos_info.fw_version = REG_READ(DMCUB_SCRATCH1); + dmub->preos_info.boot_options = REG_READ(DMCUB_SCRATCH14); + REG_GET(DMCUB_REGION3_CW5_TOP_ADDRESS, + DMCUB_REGION3_CW5_ENABLE, &top_addr_enable); + if (top_addr_enable) { + dmub_dcn42_get_fb_base_offset(dmub, + &dmub->preos_info.fb_base, &dmub->preos_info.fb_offset); + offset_low = REG_READ(DMCUB_REGION3_CW5_OFFSET); + offset_high = REG_READ(DMCUB_REGION3_CW5_OFFSET_HIGH); + region3_cw5_offset = ((uint64_t)offset_high << 32) | offset_low; + dmub->preos_info.trace_buffer_phy_addr = region3_cw5_offset + - dmub->preos_info.fb_base + dmub->preos_info.fb_offset; + + REG_GET(DMCUB_REGION3_CW5_TOP_ADDRESS, + DMCUB_REGION3_CW5_TOP_ADDRESS, &top_addr); + base_addr = REG_READ(DMCUB_REGION3_CW5_BASE_ADDRESS) & 0x1FFFFFFF; + dmub->preos_info.trace_buffer_size = + (top_addr > base_addr) ? (top_addr - base_addr + 1) : 0; + } + + return true; +} + +void dmub_dcn42_write_reg_outbox0_rsp(struct dmub_srv *dmub, uint32_t *rsp) +{ + REG_WRITE(DMCUB_REG_OUTBOX0_RSP, *rsp); +} + +uint32_t dmub_dcn42_read_reg_outbox0_rsp_int_status(struct dmub_srv *dmub) +{ + uint32_t status; + + REG_GET(DMCUB_INTERRUPT_STATUS, DMCUB_REG_OUTBOX0_RSP_INT_STAT, &status); + return status; +} diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn42.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn42.h new file mode 100644 index 000000000000..c53f7691d1a8 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn42.h @@ -0,0 +1,303 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2026 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef _DMUB_DCN42_H_ +#define _DMUB_DCN42_H_ + +#include "dmub_dcn35.h" +#include "dmub_dcn401.h" + + +struct dmub_srv; + +/* DCN42 register definitions. */ + +#define DMUB_DCN42_REGS() \ + DMUB_SR(DMCUB_CNTL) \ + DMUB_SR(DMCUB_CNTL2) \ + DMUB_SR(DMCUB_SEC_CNTL) \ + DMUB_SR(DMCUB_INBOX0_SIZE) \ + DMUB_SR(DMCUB_INBOX0_RPTR) \ + DMUB_SR(DMCUB_INBOX0_WPTR) \ + DMUB_SR(DMCUB_INBOX1_BASE_ADDRESS) \ + DMUB_SR(DMCUB_INBOX1_SIZE) \ + DMUB_SR(DMCUB_INBOX1_RPTR) \ + DMUB_SR(DMCUB_INBOX1_WPTR) \ + DMUB_SR(DMCUB_OUTBOX0_BASE_ADDRESS) \ + DMUB_SR(DMCUB_OUTBOX0_SIZE) \ + DMUB_SR(DMCUB_OUTBOX0_RPTR) \ + DMUB_SR(DMCUB_OUTBOX0_WPTR) \ + DMUB_SR(DMCUB_OUTBOX1_BASE_ADDRESS) \ + DMUB_SR(DMCUB_OUTBOX1_SIZE) \ + DMUB_SR(DMCUB_OUTBOX1_RPTR) \ + DMUB_SR(DMCUB_OUTBOX1_WPTR) \ + DMUB_SR(DMCUB_REGION3_CW0_OFFSET) \ + DMUB_SR(DMCUB_REGION3_CW1_OFFSET) \ + DMUB_SR(DMCUB_REGION3_CW2_OFFSET) \ + DMUB_SR(DMCUB_REGION3_CW3_OFFSET) \ + DMUB_SR(DMCUB_REGION3_CW4_OFFSET) \ + DMUB_SR(DMCUB_REGION3_CW5_OFFSET) \ + DMUB_SR(DMCUB_REGION3_CW6_OFFSET) \ + DMUB_SR(DMCUB_REGION3_CW7_OFFSET) \ + DMUB_SR(DMCUB_REGION3_CW0_OFFSET_HIGH) \ + DMUB_SR(DMCUB_REGION3_CW1_OFFSET_HIGH) \ + DMUB_SR(DMCUB_REGION3_CW2_OFFSET_HIGH) \ + DMUB_SR(DMCUB_REGION3_CW3_OFFSET_HIGH) \ + DMUB_SR(DMCUB_REGION3_CW4_OFFSET_HIGH) \ + DMUB_SR(DMCUB_REGION3_CW5_OFFSET_HIGH) \ + DMUB_SR(DMCUB_REGION3_CW6_OFFSET_HIGH) \ + DMUB_SR(DMCUB_REGION3_CW7_OFFSET_HIGH) \ + DMUB_SR(DMCUB_REGION3_CW0_BASE_ADDRESS) \ + DMUB_SR(DMCUB_REGION3_CW1_BASE_ADDRESS) \ + DMUB_SR(DMCUB_REGION3_CW2_BASE_ADDRESS) \ + DMUB_SR(DMCUB_REGION3_CW3_BASE_ADDRESS) \ + DMUB_SR(DMCUB_REGION3_CW4_BASE_ADDRESS) \ + DMUB_SR(DMCUB_REGION3_CW5_BASE_ADDRESS) \ + DMUB_SR(DMCUB_REGION3_CW6_BASE_ADDRESS) \ + DMUB_SR(DMCUB_REGION3_CW7_BASE_ADDRESS) \ + DMUB_SR(DMCUB_REGION3_CW0_TOP_ADDRESS) \ + DMUB_SR(DMCUB_REGION3_CW1_TOP_ADDRESS) \ + DMUB_SR(DMCUB_REGION3_CW2_TOP_ADDRESS) \ + DMUB_SR(DMCUB_REGION3_CW3_TOP_ADDRESS) \ + DMUB_SR(DMCUB_REGION3_CW4_TOP_ADDRESS) \ + DMUB_SR(DMCUB_REGION3_CW5_TOP_ADDRESS) \ + DMUB_SR(DMCUB_REGION3_CW6_TOP_ADDRESS) \ + DMUB_SR(DMCUB_REGION3_CW7_TOP_ADDRESS) \ + DMUB_SR(DMCUB_REGION4_OFFSET) \ + DMUB_SR(DMCUB_REGION4_OFFSET_HIGH) \ + DMUB_SR(DMCUB_REGION4_TOP_ADDRESS) \ + DMUB_SR(DMCUB_REGION5_OFFSET) \ + DMUB_SR(DMCUB_REGION5_OFFSET_HIGH) \ + DMUB_SR(DMCUB_REGION5_TOP_ADDRESS) \ + DMUB_SR(DMCUB_REGION6_OFFSET) \ + DMUB_SR(DMCUB_REGION6_OFFSET_HIGH) \ + DMUB_SR(DMCUB_REGION6_TOP_ADDRESS) \ + DMUB_SR(DMCUB_SCRATCH0) \ + DMUB_SR(DMCUB_SCRATCH1) \ + DMUB_SR(DMCUB_SCRATCH2) \ + DMUB_SR(DMCUB_SCRATCH3) \ + DMUB_SR(DMCUB_SCRATCH4) \ + DMUB_SR(DMCUB_SCRATCH5) \ + DMUB_SR(DMCUB_SCRATCH6) \ + DMUB_SR(DMCUB_SCRATCH7) \ + DMUB_SR(DMCUB_SCRATCH8) \ + DMUB_SR(DMCUB_SCRATCH9) \ + DMUB_SR(DMCUB_SCRATCH10) \ + DMUB_SR(DMCUB_SCRATCH11) \ + DMUB_SR(DMCUB_SCRATCH12) \ + DMUB_SR(DMCUB_SCRATCH13) \ + DMUB_SR(DMCUB_SCRATCH14) \ + DMUB_SR(DMCUB_SCRATCH15) \ + DMUB_SR(DMCUB_SCRATCH16) \ + DMUB_SR(DMCUB_SCRATCH17) \ + DMUB_SR(DMCUB_SCRATCH18) \ + DMUB_SR(DMCUB_SCRATCH19) \ + DMUB_SR(DMCUB_SCRATCH20) \ + DMUB_SR(DMCUB_SCRATCH21) \ + DMUB_SR(DMCUB_GPINT_DATAIN0) \ + DMUB_SR(DMCUB_GPINT_DATAIN1) \ + DMUB_SR(DMCUB_GPINT_DATAOUT) \ + DMUB_SR(MMHUBBUB_SOFT_RESET) \ + DMUB_SR(DCN_VM_FB_LOCATION_BASE) \ + DMUB_SR(DCN_VM_FB_OFFSET) \ + DMUB_SR(DMCUB_TIMER_CURRENT) \ + DMUB_SR(DMCUB_INST_FETCH_FAULT_ADDR) \ + DMUB_SR(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR) \ + DMUB_SR(DMCUB_DATA_WRITE_FAULT_ADDR) \ + DMUB_SR(DMCUB_REGION3_TMR_AXI_SPACE) \ + DMUB_SR(DMCUB_INTERRUPT_ENABLE) \ + DMUB_SR(DMCUB_INTERRUPT_ACK) \ + DMUB_SR(DMU_CLK_CNTL) \ + DMUB_SR(DMCUB_INTERRUPT_STATUS) \ + DMUB_SR(DMCUB_REG_INBOX0_RDY) \ + DMUB_SR(DMCUB_REG_INBOX0_MSG0) \ + DMUB_SR(DMCUB_REG_INBOX0_MSG1) \ + DMUB_SR(DMCUB_REG_INBOX0_MSG2) \ + DMUB_SR(DMCUB_REG_INBOX0_MSG3) \ + DMUB_SR(DMCUB_REG_INBOX0_MSG4) \ + DMUB_SR(DMCUB_REG_INBOX0_MSG5) \ + DMUB_SR(DMCUB_REG_INBOX0_MSG6) \ + DMUB_SR(DMCUB_REG_INBOX0_MSG7) \ + DMUB_SR(DMCUB_REG_INBOX0_MSG8) \ + DMUB_SR(DMCUB_REG_INBOX0_MSG9) \ + DMUB_SR(DMCUB_REG_INBOX0_MSG10) \ + DMUB_SR(DMCUB_REG_INBOX0_MSG11) \ + DMUB_SR(DMCUB_REG_INBOX0_MSG12) \ + DMUB_SR(DMCUB_REG_INBOX0_MSG13) \ + DMUB_SR(DMCUB_REG_INBOX0_MSG14) \ + DMUB_SR(DMCUB_REG_INBOX0_RSP) \ + DMUB_SR(DMCUB_REG_OUTBOX0_RDY) \ + DMUB_SR(DMCUB_REG_OUTBOX0_MSG0) \ + DMUB_SR(DMCUB_REG_OUTBOX0_RSP) \ + DMUB_SR(HOST_INTERRUPT_CSR) + +#define DMUB_DCN42_FIELDS() \ + DMUB_SF(DMCUB_CNTL, DMCUB_ENABLE) \ + DMUB_SF(DMCUB_CNTL, DMCUB_TRACEPORT_EN) \ + DMUB_SF(DMCUB_CNTL2, DMCUB_SOFT_RESET) \ + DMUB_SF(DMCUB_SEC_CNTL, DMCUB_SEC_RESET) \ + DMUB_SF(DMCUB_SEC_CNTL, DMCUB_MEM_UNIT_ID) \ + DMUB_SF(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS) \ + DMUB_SF(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_TOP_ADDRESS) \ + DMUB_SF(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE) \ + DMUB_SF(DMCUB_REGION3_CW1_TOP_ADDRESS, DMCUB_REGION3_CW1_TOP_ADDRESS) \ + DMUB_SF(DMCUB_REGION3_CW1_TOP_ADDRESS, DMCUB_REGION3_CW1_ENABLE) \ + DMUB_SF(DMCUB_REGION3_CW2_TOP_ADDRESS, DMCUB_REGION3_CW2_TOP_ADDRESS) \ + DMUB_SF(DMCUB_REGION3_CW2_TOP_ADDRESS, DMCUB_REGION3_CW2_ENABLE) \ + DMUB_SF(DMCUB_REGION3_CW3_TOP_ADDRESS, DMCUB_REGION3_CW3_TOP_ADDRESS) \ + DMUB_SF(DMCUB_REGION3_CW3_TOP_ADDRESS, DMCUB_REGION3_CW3_ENABLE) \ + DMUB_SF(DMCUB_REGION3_CW4_TOP_ADDRESS, DMCUB_REGION3_CW4_TOP_ADDRESS) \ + DMUB_SF(DMCUB_REGION3_CW4_TOP_ADDRESS, DMCUB_REGION3_CW4_ENABLE) \ + DMUB_SF(DMCUB_REGION3_CW5_TOP_ADDRESS, DMCUB_REGION3_CW5_TOP_ADDRESS) \ + DMUB_SF(DMCUB_REGION3_CW5_TOP_ADDRESS, DMCUB_REGION3_CW5_ENABLE) \ + DMUB_SF(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_TOP_ADDRESS) \ + DMUB_SF(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE) \ + DMUB_SF(DMCUB_REGION3_CW7_TOP_ADDRESS, DMCUB_REGION3_CW7_TOP_ADDRESS) \ + DMUB_SF(DMCUB_REGION3_CW7_TOP_ADDRESS, DMCUB_REGION3_CW7_ENABLE) \ + DMUB_SF(DMCUB_REGION4_TOP_ADDRESS, DMCUB_REGION4_TOP_ADDRESS) \ + DMUB_SF(DMCUB_REGION4_TOP_ADDRESS, DMCUB_REGION4_ENABLE) \ + DMUB_SF(DMCUB_REGION5_TOP_ADDRESS, DMCUB_REGION5_TOP_ADDRESS) \ + DMUB_SF(DMCUB_REGION5_TOP_ADDRESS, DMCUB_REGION5_ENABLE) \ + DMUB_SF(DMCUB_REGION6_TOP_ADDRESS, DMCUB_REGION6_TOP_ADDRESS) \ + DMUB_SF(DMCUB_REGION6_TOP_ADDRESS, DMCUB_REGION6_ENABLE) \ + DMUB_SF(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET) \ + DMUB_SF(DCN_VM_FB_LOCATION_BASE, FB_BASE) \ + DMUB_SF(DCN_VM_FB_OFFSET, FB_OFFSET) \ + DMUB_SF(DMCUB_INBOX0_WPTR, DMCUB_INBOX0_WPTR) \ + DMUB_SF(DMCUB_REGION3_TMR_AXI_SPACE, DMCUB_REGION3_TMR_AXI_SPACE) \ + DMUB_SF(DMCUB_INTERRUPT_ENABLE, DMCUB_GPINT_IH_INT_EN) \ + DMUB_SF(DMCUB_INTERRUPT_ACK, DMCUB_GPINT_IH_INT_ACK) \ + DMUB_SF(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS) \ + DMUB_SF(DMU_CLK_CNTL, LONO_DISPCLK_GATE_DISABLE) \ + DMUB_SF(DMU_CLK_CNTL, LONO_SOCCLK_GATE_DISABLE) \ + DMUB_SF(DMU_CLK_CNTL, LONO_DMCUBCLK_GATE_DISABLE) \ + DMUB_SF(DMCUB_INTERRUPT_STATUS, DMCUB_REG_OUTBOX0_RSP_INT_STAT) \ + DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_INBOX0_RSP_INT_ACK) \ + DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_INBOX0_RSP_INT_STAT) \ + DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_INBOX0_RSP_INT_EN) \ + DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_ACK) \ + DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_STAT) \ + DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_EN) + +struct dmub_srv_dcn42_reg_offset { +#define DMUB_SR(reg) uint32_t reg; + DMUB_DCN42_REGS() + DMCUB_INTERNAL_REGS() +#undef DMUB_SR +}; + +struct dmub_srv_dcn42_reg_shift { +#define DMUB_SF(reg, field) uint8_t reg##__##field; + DMUB_DCN42_FIELDS() +#undef DMUB_SF +}; + +struct dmub_srv_dcn42_reg_mask { +#define DMUB_SF(reg, field) uint32_t reg##__##field; + DMUB_DCN42_FIELDS() +#undef DMUB_SF +}; + +struct dmub_srv_dcn42_regs { + struct dmub_srv_dcn42_reg_offset offset; + struct dmub_srv_dcn42_reg_mask mask; + struct dmub_srv_dcn42_reg_shift shift; +}; + +/* Function declarations */ + +/* Initialization and configuration */ +void dmub_srv_dcn42_regs_init(struct dmub_srv *dmub, struct dc_context *ctx); +void dmub_dcn42_enable_dmub_boot_options(struct dmub_srv *dmub, const struct dmub_srv_hw_params *params); +void dmub_dcn42_skip_dmub_panel_power_sequence(struct dmub_srv *dmub, bool skip); +void dmub_dcn42_configure_dmub_in_system_memory(struct dmub_srv *dmub); + +/* Reset and control */ +void dmub_dcn42_reset(struct dmub_srv *dmub); +void dmub_dcn42_reset_release(struct dmub_srv *dmub); + +/* Firmware loading */ +void dmub_dcn42_backdoor_load(struct dmub_srv *dmub, const struct dmub_window *cw0, const struct dmub_window *cw1); +void dmub_dcn42_backdoor_load_zfb_mode(struct dmub_srv *dmub, const struct dmub_window *cw0, const struct dmub_window *cw1); +void dmub_dcn42_setup_windows(struct dmub_srv *dmub, const struct dmub_window *cw2, const struct dmub_window *cw3, const struct dmub_window *cw4, const struct dmub_window *cw5, const struct dmub_window *cw6, const struct dmub_window *region6); + +/* Mailbox operations - Inbox1 */ +void dmub_dcn42_setup_mailbox(struct dmub_srv *dmub, const struct dmub_region *inbox1); +uint32_t dmub_dcn42_get_inbox1_wptr(struct dmub_srv *dmub); +uint32_t dmub_dcn42_get_inbox1_rptr(struct dmub_srv *dmub); +void dmub_dcn42_set_inbox1_wptr(struct dmub_srv *dmub, uint32_t wptr_offset); + +/* Mailbox operations - Outbox1 */ +void dmub_dcn42_setup_out_mailbox(struct dmub_srv *dmub, const struct dmub_region *outbox1); +uint32_t dmub_dcn42_get_outbox1_wptr(struct dmub_srv *dmub); +void dmub_dcn42_set_outbox1_rptr(struct dmub_srv *dmub, uint32_t rptr_offset); + +/* Mailbox operations - Outbox0 */ +void dmub_dcn42_setup_outbox0(struct dmub_srv *dmub, const struct dmub_region *outbox0); +uint32_t dmub_dcn42_get_outbox0_wptr(struct dmub_srv *dmub); +void dmub_dcn42_set_outbox0_rptr(struct dmub_srv *dmub, uint32_t rptr_offset); + +/* Mailbox operations - Inbox0 */ +void dmub_dcn42_send_inbox0_cmd(struct dmub_srv *dmub, union dmub_inbox0_data_register data); +void dmub_dcn42_clear_inbox0_ack_register(struct dmub_srv *dmub); +uint32_t dmub_dcn42_read_inbox0_ack_register(struct dmub_srv *dmub); + +/* REG Inbox0/Outbox0 operations */ +void dmub_dcn42_send_reg_inbox0_cmd_msg(struct dmub_srv *dmub, union dmub_rb_cmd *cmd); +uint32_t dmub_dcn42_read_reg_inbox0_rsp_int_status(struct dmub_srv *dmub); +void dmub_dcn42_read_reg_inbox0_cmd_rsp(struct dmub_srv *dmub, union dmub_rb_cmd *cmd); +void dmub_dcn42_write_reg_inbox0_rsp_int_ack(struct dmub_srv *dmub); +void dmub_dcn42_clear_reg_inbox0_rsp_int_ack(struct dmub_srv *dmub); +void dmub_dcn42_enable_reg_inbox0_rsp_int(struct dmub_srv *dmub, bool enable); + +void dmub_dcn42_write_reg_outbox0_rdy_int_ack(struct dmub_srv *dmub); +void dmub_dcn42_read_reg_outbox0_msg(struct dmub_srv *dmub, uint32_t *msg); +void dmub_dcn42_write_reg_outbox0_rsp(struct dmub_srv *dmub, uint32_t *rsp); +uint32_t dmub_dcn42_read_reg_outbox0_rsp_int_status(struct dmub_srv *dmub); +void dmub_dcn42_enable_reg_outbox0_rdy_int(struct dmub_srv *dmub, bool enable); +uint32_t dmub_dcn42_read_reg_outbox0_rdy_int_status(struct dmub_srv *dmub); + +/* GPINT operations */ +void dmub_dcn42_set_gpint(struct dmub_srv *dmub, union dmub_gpint_data_register reg); +bool dmub_dcn42_is_gpint_acked(struct dmub_srv *dmub, union dmub_gpint_data_register reg); +uint32_t dmub_dcn42_get_gpint_response(struct dmub_srv *dmub); +uint32_t dmub_dcn42_get_gpint_dataout(struct dmub_srv *dmub); + +/* Status and detection */ +bool dmub_dcn42_is_hw_init(struct dmub_srv *dmub); +bool dmub_dcn42_is_supported(struct dmub_srv *dmub); +bool dmub_dcn42_is_hw_powered_up(struct dmub_srv *dmub); +bool dmub_dcn42_should_detect(struct dmub_srv *dmub); + + +/* Firmware boot status and options */ +union dmub_fw_boot_status dmub_dcn42_get_fw_boot_status(struct dmub_srv *dmub); +union dmub_fw_boot_options dmub_dcn42_get_fw_boot_option(struct dmub_srv *dmub); + +/* Timing and diagnostics */ +uint32_t dmub_dcn42_get_current_time(struct dmub_srv *dmub); +void dmub_dcn42_get_diagnostic_data(struct dmub_srv *dmub); +bool dmub_dcn42_get_preos_fw_info(struct dmub_srv *dmub); + +#endif /* _DMUB_DCN42_H_ */ diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_reg.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_reg.c index ca0c8a54b635..b5566ef8d4f3 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_reg.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_reg.c @@ -45,6 +45,7 @@ static void set_reg_field_values(struct dmub_reg_value_masks *field_value_mask, uint32_t mask1, uint32_t field_value1, va_list ap) { + (void)addr; uint32_t shift, mask, field_value; int i = 1; @@ -57,8 +58,9 @@ static void set_reg_field_values(struct dmub_reg_value_masks *field_value_mask, mask = va_arg(ap, uint32_t); field_value = va_arg(ap, uint32_t); + ASSERT(shift <= 0xFF); set_reg_field_value_masks(field_value_mask, field_value, mask, - shift); + (uint8_t)shift); i++; } } diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c index 83cf4888fb54..10d23f5f5d94 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c @@ -1,5 +1,6 @@ +// SPDX-License-Identifier: MIT /* - * Copyright 2019 Advanced Micro Devices, Inc. + * Copyright 2019-2026 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -22,7 +23,6 @@ * Authors: AMD * */ - #include "../dmub_srv.h" #include "dmub_dcn20.h" #include "dmub_dcn21.h" @@ -40,6 +40,7 @@ #include "dmub_dcn351.h" #include "dmub_dcn36.h" #include "dmub_dcn401.h" +#include "dmub_dcn42.h" #include "os_types.h" /* * Note: the DMUB service is standalone. No additional headers should be @@ -87,6 +88,7 @@ static struct dmub_srv_dcn32_regs dmub_srv_dcn32_regs; static struct dmub_srv_dcn35_regs dmub_srv_dcn35_regs; +struct dmub_srv_dcn42_regs dmub_srv_dcn42_regs; static inline uint32_t dmub_align(uint32_t val, uint32_t factor) { @@ -410,6 +412,64 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic) funcs->is_hw_powered_up = dmub_dcn35_is_hw_powered_up; funcs->should_detect = dmub_dcn35_should_detect; break; + case DMUB_ASIC_DCN42: + dmub->regs_dcn42 = &dmub_srv_dcn42_regs; + funcs->configure_dmub_in_system_memory = dmub_dcn42_configure_dmub_in_system_memory; + funcs->send_inbox0_cmd = dmub_dcn42_send_inbox0_cmd; + funcs->clear_inbox0_ack_register = dmub_dcn42_clear_inbox0_ack_register; + funcs->read_inbox0_ack_register = dmub_dcn42_read_inbox0_ack_register; + funcs->reset = dmub_dcn42_reset; + funcs->reset_release = dmub_dcn42_reset_release; + funcs->backdoor_load = dmub_dcn42_backdoor_load; + funcs->backdoor_load_zfb_mode = dmub_dcn42_backdoor_load_zfb_mode; + funcs->setup_windows = dmub_dcn42_setup_windows; + funcs->setup_mailbox = dmub_dcn42_setup_mailbox; + funcs->get_inbox1_wptr = dmub_dcn42_get_inbox1_wptr; + funcs->get_inbox1_rptr = dmub_dcn42_get_inbox1_rptr; + funcs->set_inbox1_wptr = dmub_dcn42_set_inbox1_wptr; + funcs->setup_out_mailbox = dmub_dcn42_setup_out_mailbox; + funcs->get_outbox1_wptr = dmub_dcn42_get_outbox1_wptr; + funcs->set_outbox1_rptr = dmub_dcn42_set_outbox1_rptr; + funcs->is_supported = dmub_dcn42_is_supported; + funcs->is_hw_init = dmub_dcn42_is_hw_init; + funcs->set_gpint = dmub_dcn42_set_gpint; + funcs->is_gpint_acked = dmub_dcn42_is_gpint_acked; + funcs->get_gpint_response = dmub_dcn42_get_gpint_response; + funcs->get_gpint_dataout = dmub_dcn42_get_gpint_dataout; + funcs->get_fw_status = dmub_dcn42_get_fw_boot_status; + funcs->get_fw_boot_option = dmub_dcn42_get_fw_boot_option; + funcs->enable_dmub_boot_options = dmub_dcn42_enable_dmub_boot_options; + funcs->skip_dmub_panel_power_sequence = dmub_dcn42_skip_dmub_panel_power_sequence; + /*outbox0 call stacks*/ + funcs->setup_outbox0 = dmub_dcn42_setup_outbox0; + funcs->get_outbox0_wptr = dmub_dcn42_get_outbox0_wptr; + funcs->set_outbox0_rptr = dmub_dcn42_set_outbox0_rptr; + + funcs->get_current_time = dmub_dcn42_get_current_time; + funcs->get_diagnostic_data = dmub_dcn42_get_diagnostic_data; + funcs->get_preos_fw_info = dmub_dcn42_get_preos_fw_info; + + /*carried from dcn401*/ + funcs->send_reg_inbox0_cmd_msg = dmub_dcn42_send_reg_inbox0_cmd_msg; + funcs->read_reg_inbox0_rsp_int_status = dmub_dcn42_read_reg_inbox0_rsp_int_status; + funcs->read_reg_inbox0_cmd_rsp = dmub_dcn42_read_reg_inbox0_cmd_rsp; + funcs->write_reg_inbox0_rsp_int_ack = dmub_dcn42_write_reg_inbox0_rsp_int_ack; + funcs->clear_reg_inbox0_rsp_int_ack = dmub_dcn42_clear_reg_inbox0_rsp_int_ack; + funcs->enable_reg_inbox0_rsp_int = dmub_dcn42_enable_reg_inbox0_rsp_int; + default_inbox_type = DMUB_CMD_INTERFACE_FB; /*still default to FB for now*/ + + funcs->write_reg_outbox0_rdy_int_ack = dmub_dcn42_write_reg_outbox0_rdy_int_ack; + funcs->read_reg_outbox0_msg = dmub_dcn42_read_reg_outbox0_msg; + funcs->write_reg_outbox0_rsp = dmub_dcn42_write_reg_outbox0_rsp; + funcs->read_reg_outbox0_rdy_int_status = dmub_dcn42_read_reg_outbox0_rdy_int_status; + funcs->read_reg_outbox0_rsp_int_status = dmub_dcn42_read_reg_outbox0_rsp_int_status; + funcs->enable_reg_inbox0_rsp_int = dmub_dcn42_enable_reg_inbox0_rsp_int; + funcs->enable_reg_outbox0_rdy_int = dmub_dcn42_enable_reg_outbox0_rdy_int; + funcs->init_reg_offsets = dmub_srv_dcn42_regs_init; + + funcs->is_hw_powered_up = dmub_dcn42_is_hw_powered_up; + funcs->should_detect = dmub_dcn42_should_detect; + break; case DMUB_ASIC_DCN401: dmub->regs_dcn401 = &dmub_srv_dcn401_regs; @@ -974,8 +1034,8 @@ enum dmub_status dmub_srv_wait_for_auto_load(struct dmub_srv *dmub, static void dmub_srv_update_reg_inbox0_status(struct dmub_srv *dmub) { if (dmub->reg_inbox0.is_pending) { - dmub->reg_inbox0.is_pending = dmub->hw_funcs.read_reg_inbox0_rsp_int_status && - !dmub->hw_funcs.read_reg_inbox0_rsp_int_status(dmub); + dmub->reg_inbox0.is_pending = (dmub->hw_funcs.read_reg_inbox0_rsp_int_status && + !dmub->hw_funcs.read_reg_inbox0_rsp_int_status(dmub)) != 0; if (!dmub->reg_inbox0.is_pending) { /* ack the rsp interrupt */ @@ -1260,7 +1320,7 @@ void dmub_srv_set_power_state(struct dmub_srv *dmub, enum dmub_srv_power_state_t enum dmub_status dmub_srv_reg_cmd_execute(struct dmub_srv *dmub, union dmub_rb_cmd *cmd) { - uint32_t num_pending = 0; + uint64_t num_pending = 0; if (!dmub->hw_init) return DMUB_STATUS_INVALID; @@ -1288,7 +1348,7 @@ enum dmub_status dmub_srv_reg_cmd_execute(struct dmub_srv *dmub, union dmub_rb_c dmub->reg_inbox0.num_submitted++; dmub->reg_inbox0.is_pending = true; - dmub->reg_inbox0.is_multi_pending = cmd->cmd_common.header.multi_cmd_pending; + dmub->reg_inbox0.is_multi_pending = cmd->cmd_common.header.multi_cmd_pending != 0; return DMUB_STATUS_OK; } diff --git a/drivers/gpu/drm/amd/display/include/bios_parser_types.h b/drivers/gpu/drm/amd/display/include/bios_parser_types.h index f40dc612ec73..b5d97b394131 100644 --- a/drivers/gpu/drm/amd/display/include/bios_parser_types.h +++ b/drivers/gpu/drm/amd/display/include/bios_parser_types.h @@ -93,6 +93,8 @@ enum bp_external_encoder_control_action { EXTERNAL_ENCODER_CONTROL_SETUP = 0xf, EXTERNAL_ENCODER_CONTROL_UNBLANK = 0x10, EXTERNAL_ENCODER_CONTROL_BLANK = 0x11, + EXTERNAL_ENCODER_CONTROL_DAC_LOAD_DETECT = 0x12, + EXTERNAL_ENCODER_CONTROL_DDC_SETUP = 0x14, }; enum bp_pipe_control_action { diff --git a/drivers/gpu/drm/amd/display/include/dal_asic_id.h b/drivers/gpu/drm/amd/display/include/dal_asic_id.h index 8aea50aa9533..92510af1bd65 100644 --- a/drivers/gpu/drm/amd/display/include/dal_asic_id.h +++ b/drivers/gpu/drm/amd/display/include/dal_asic_id.h @@ -252,6 +252,7 @@ enum { #define AMDGPU_FAMILY_GC_11_0_0 145 #define AMDGPU_FAMILY_GC_11_0_1 148 #define AMDGPU_FAMILY_GC_11_5_0 150 +#define AMDGPU_FAMILY_GC_11_5_4 154 #define GC_11_0_0_A0 0x1 #define GC_11_0_2_A0 0x10 #define GC_11_0_3_A0 0x20 diff --git a/drivers/gpu/drm/amd/display/include/dal_types.h b/drivers/gpu/drm/amd/display/include/dal_types.h index a021d12acd74..d30eb24cf11e 100644 --- a/drivers/gpu/drm/amd/display/include/dal_types.h +++ b/drivers/gpu/drm/amd/display/include/dal_types.h @@ -65,6 +65,7 @@ enum dce_version { DCN_VERSION_3_51, DCN_VERSION_3_6, DCN_VERSION_4_01, + DCN_VERSION_4_2, DCN_VERSION_MAX }; diff --git a/drivers/gpu/drm/amd/display/include/dpcd_defs.h b/drivers/gpu/drm/amd/display/include/dpcd_defs.h index 1afa10e85eb5..4a8ca0ac1266 100644 --- a/drivers/gpu/drm/amd/display/include/dpcd_defs.h +++ b/drivers/gpu/drm/amd/display/include/dpcd_defs.h @@ -64,6 +64,9 @@ #ifndef DP_PR_ERROR_STATUS // can remove this once the define gets into linux drm_dp_helper.h #define DP_PR_ERROR_STATUS 0x2020 /* DP 2.0 */ #endif /* DP_PR_ERROR_STATUS */ +#ifndef DP_PR_REPLAY_SINK_STATUS // can remove this once the define gets into linux drm_dp_helper.h +#define DP_PR_REPLAY_SINK_STATUS 0x2022 +#endif /* DP_PR_REPLAY_SINK_STATUS */ #ifndef DP_PR_LINK_CRC_ERROR // can remove this once the define gets into linux drm_dp_helper.h #define DP_PR_LINK_CRC_ERROR (1 << 0) #endif /* DP_PR_LINK_CRC_ERROR */ diff --git a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c index 2639163b8ba2..1f225d0d6c44 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c +++ b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c @@ -896,6 +896,7 @@ static void build_de_pq(struct pwl_float_data_ex *de_pq, uint32_t hw_points_num, const struct hw_x_point *coordinate_x) { + (void)coordinate_x; uint32_t i; struct fixed31_32 output; struct fixed31_32 *de_pq_table = mod_color_get_table(type_de_pq_table); @@ -1339,6 +1340,7 @@ static void scale_gamma_dx(struct pwl_float_data *pwl_rgb, const struct dc_gamma *ramp, struct dividers dividers) { + (void)dividers; uint32_t i; struct fixed31_32 min = dc_fixpt_zero; struct fixed31_32 max = dc_fixpt_one; diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 19de72173052..c9150019aab0 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -114,6 +114,7 @@ static unsigned int calc_duration_in_us_from_v_total( const struct mod_vrr_params *in_vrr, unsigned int v_total) { + (void)in_vrr; unsigned int duration_in_us = (unsigned int)(div64_u64(((unsigned long long)(v_total) * 10000) * stream->timing.h_total, @@ -218,6 +219,7 @@ static void update_v_total_for_static_ramp( const struct dc_stream_state *stream, struct mod_vrr_params *in_out_vrr) { + (void)core_freesync; unsigned int v_total = 0; unsigned int current_duration_in_us = calc_duration_in_us_from_v_total( @@ -292,6 +294,7 @@ static void apply_below_the_range(struct core_freesync *core_freesync, unsigned int last_render_time_in_us, struct mod_vrr_params *in_out_vrr) { + (void)core_freesync; unsigned int inserted_frame_duration_in_us = 0; unsigned int mid_point_frames_ceil = 0; unsigned int mid_point_frames_floor = 0; @@ -447,6 +450,7 @@ static void apply_fixed_refresh(struct core_freesync *core_freesync, unsigned int last_render_time_in_us, struct mod_vrr_params *in_out_vrr) { + (void)core_freesync; bool update = false; unsigned int max_render_time_in_us = in_out_vrr->max_duration_in_us; @@ -545,6 +549,7 @@ static bool vrr_settings_require_update(struct core_freesync *core_freesync, unsigned int max_refresh_in_uhz, struct mod_vrr_params *in_vrr) { + (void)core_freesync; if (in_vrr->state != in_config->state) { return true; } else if (in_vrr->state == VRR_STATE_ACTIVE_FIXED && @@ -946,6 +951,7 @@ void mod_freesync_build_vrr_infopacket(struct mod_freesync *mod_freesync, struct dc_info_packet *infopacket, bool pack_sdp_v1_3) { + (void)mod_freesync; /* SPD info packet for FreeSync * VTEM info packet for HdmiVRR * Check if Freesync is supported. Return if false. If true, diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h index 26a351a184f3..d07387a961dd 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h @@ -501,6 +501,7 @@ static inline void callback_in_ms(uint16_t time, struct mod_hdcp_output *output) static inline void set_watchdog_in_ms(struct mod_hdcp *hdcp, uint16_t time, struct mod_hdcp_output *output) { + (void)hdcp; output->watchdog_timer_needed = 1; output->watchdog_timer_delay = time; } |
