Merge tag 'amd-drm-next-6.11-2024-06-28' of https://gitlab.freedesktop.org/agd5f/linux into drm-next
amd-drm-next-6.11-2024-06-28: amdgpu: - JPEG 5.x fixes - More FW loading cleanups - Misc code cleanups - GC 12.x fixes - ASPM fix - DCN 4.0.1 updates - SR-IOV fixes - HDCP fix - USB4 fixes - Silence UBSAN warnings - MES submission fixes - Update documentation for new products - DCC updates - Initial ISP 4.x plumbing - RAS fixes - Misc small fixes amdkfd: - Fix missing unlock in error path for adding queues Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> From: Alex Deucher <alexander.deucher@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20240628213135.427214-1-alexander.deucher@amd.com
This commit is contained in:
@@ -7,7 +7,9 @@ SteamDeck, VANGOGH, DCN 3.0.1, 10.3.1, VCN 3.1.0, 5.2.1, 11.5.0
|
||||
Ryzen 5000 series / Ryzen 7x30 series, GREEN SARDINE / Cezanne / Barcelo / Barcelo-R, DCN 2.1, 9.3, VCN 2.2, 4.1.1, 12.0.1
|
||||
Ryzen 6000 series / Ryzen 7x35 series / Ryzen 7x36 series, YELLOW CARP / Rembrandt / Rembrandt-R, 3.1.2, 10.3.3, VCN 3.1.1, 5.2.3, 13.0.3
|
||||
Ryzen 7000 series (AM5), Raphael, 3.1.5, 10.3.6, 3.1.2, 5.2.6, 13.0.5
|
||||
Ryzen 9000 series (AM5), Granite Ridge, 3.1.5, 10.3.6, 3.1.2, 5.2.6, 13.0.5
|
||||
Ryzen 7x45 series (FL1), Dragon Range, 3.1.5, 10.3.6, 3.1.2, 5.2.6, 13.0.5
|
||||
Ryzen 7x20 series, Mendocino, 3.1.6, 10.3.7, 3.1.1, 5.2.7, 13.0.8
|
||||
Ryzen 7x40 series, Phoenix, 3.1.4, 11.0.1 / 11.0.4, 4.0.2, 6.0.1, 13.0.4 / 13.0.11
|
||||
Ryzen 8x40 series, Hawk Point, 3.1.4, 11.0.1 / 11.0.4, 4.0.2, 6.0.1, 13.0.4 / 13.0.11
|
||||
Ryzen AI 300 series, Strix Point, 3.5.0, 11.5.0, 4.0.5, 6.1.0, 14.0.0
|
||||
|
||||
|
@@ -71,6 +71,17 @@ config DRM_AMDGPU_USERPTR
|
||||
This option selects CONFIG_HMM and CONFIG_HMM_MIRROR if it
|
||||
isn't already selected to enabled full userptr support.
|
||||
|
||||
config DRM_AMD_ISP
|
||||
bool "Enable AMD Image Signal Processor IP support"
|
||||
depends on DRM_AMDGPU
|
||||
select MFD_CORE
|
||||
select PM_GENERIC_DOMAINS if PM
|
||||
help
|
||||
Choose this option to enable ISP IP support for AMD SOCs.
|
||||
This adds the ISP (Image Signal Processor) IP driver and wires
|
||||
it up into the amdgpu driver. It is required for cameras
|
||||
on APUs which utilize mipi cameras.
|
||||
|
||||
config DRM_AMDGPU_WERROR
|
||||
bool "Force the compiler to throw an error instead of a warning when compiling"
|
||||
depends on DRM_AMDGPU
|
||||
|
||||
@@ -323,4 +323,12 @@ amdgpu-y += $(AMD_DISPLAY_FILES)
|
||||
|
||||
endif
|
||||
|
||||
# add isp block
|
||||
ifneq ($(CONFIG_DRM_AMD_ISP),)
|
||||
amdgpu-y += \
|
||||
amdgpu_isp.o \
|
||||
isp_v4_1_0.o \
|
||||
isp_v4_1_1.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_DRM_AMDGPU)+= amdgpu.o
|
||||
|
||||
@@ -112,6 +112,9 @@
|
||||
#include "amdgpu_xcp.h"
|
||||
#include "amdgpu_seq64.h"
|
||||
#include "amdgpu_reg_state.h"
|
||||
#if defined(CONFIG_DRM_AMD_ISP)
|
||||
#include "amdgpu_isp.h"
|
||||
#endif
|
||||
|
||||
#define MAX_GPU_INSTANCE 64
|
||||
|
||||
@@ -221,7 +224,6 @@ extern int amdgpu_mes;
|
||||
extern int amdgpu_mes_log_enable;
|
||||
extern int amdgpu_mes_kiq;
|
||||
extern int amdgpu_uni_mes;
|
||||
extern int amdgpu_jpeg_test;
|
||||
extern int amdgpu_noretry;
|
||||
extern int amdgpu_force_asic_type;
|
||||
extern int amdgpu_smartshift_bias;
|
||||
@@ -721,6 +723,7 @@ enum amd_hw_ip_block_type {
|
||||
XGMI_HWIP,
|
||||
DCI_HWIP,
|
||||
PCIE_HWIP,
|
||||
ISP_HWIP,
|
||||
MAX_HWIP
|
||||
};
|
||||
|
||||
@@ -1018,7 +1021,6 @@ struct amdgpu_device {
|
||||
|
||||
/* jpeg */
|
||||
struct amdgpu_jpeg jpeg;
|
||||
bool enable_jpeg_test;
|
||||
|
||||
/* vpe */
|
||||
struct amdgpu_vpe vpe;
|
||||
@@ -1048,6 +1050,11 @@ struct amdgpu_device {
|
||||
/* display related functionality */
|
||||
struct amdgpu_display_manager dm;
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_ISP)
|
||||
/* isp */
|
||||
struct amdgpu_isp isp;
|
||||
#endif
|
||||
|
||||
/* mes */
|
||||
bool enable_mes;
|
||||
bool enable_mes_kiq;
|
||||
|
||||
@@ -433,7 +433,7 @@ amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev,
|
||||
mem_channel_number = vram_info->v30.channel_num;
|
||||
mem_channel_width = vram_info->v30.channel_width;
|
||||
if (vram_width)
|
||||
*vram_width = mem_channel_number * (1 << mem_channel_width);
|
||||
*vram_width = mem_channel_number * 16;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
||||
@@ -5069,7 +5069,8 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev,
|
||||
struct amdgpu_hive_info *hive = NULL;
|
||||
|
||||
if (test_bit(AMDGPU_HOST_FLR, &reset_context->flags)) {
|
||||
amdgpu_virt_ready_to_reset(adev);
|
||||
if (!amdgpu_ras_get_fed_status(adev))
|
||||
amdgpu_virt_ready_to_reset(adev);
|
||||
amdgpu_virt_wait_reset(adev);
|
||||
clear_bit(AMDGPU_HOST_FLR, &reset_context->flags);
|
||||
r = amdgpu_virt_request_full_gpu(adev, true);
|
||||
@@ -5837,6 +5838,12 @@ retry: /* Rest of adevs pre asic reset from XGMI hive. */
|
||||
/* Actual ASIC resets if needed.*/
|
||||
/* Host driver will handle XGMI hive reset for SRIOV */
|
||||
if (amdgpu_sriov_vf(adev)) {
|
||||
if (amdgpu_ras_get_fed_status(adev) || amdgpu_virt_rcvd_ras_interrupt(adev)) {
|
||||
dev_dbg(adev->dev, "Detected RAS error, wait for FLR completion\n");
|
||||
amdgpu_ras_set_fed(adev, true);
|
||||
set_bit(AMDGPU_HOST_FLR, &reset_context->flags);
|
||||
}
|
||||
|
||||
r = amdgpu_device_reset_sriov(adev, reset_context);
|
||||
if (AMDGPU_RETRY_SRIOV_RESET(r) && (retry_limit--) > 0) {
|
||||
amdgpu_virt_release_full_gpu(adev, true);
|
||||
|
||||
@@ -106,6 +106,9 @@
|
||||
#include "jpeg_v5_0_0.h"
|
||||
|
||||
#include "amdgpu_vpe.h"
|
||||
#if defined(CONFIG_DRM_AMD_ISP)
|
||||
#include "amdgpu_isp.h"
|
||||
#endif
|
||||
|
||||
#define FIRMWARE_IP_DISCOVERY "amdgpu/ip_discovery.bin"
|
||||
MODULE_FIRMWARE(FIRMWARE_IP_DISCOVERY);
|
||||
@@ -225,6 +228,7 @@ static int hw_id_map[MAX_HWIP] = {
|
||||
[DCI_HWIP] = DCI_HWID,
|
||||
[PCIE_HWIP] = PCIE_HWID,
|
||||
[VPE_HWIP] = VPE_HWID,
|
||||
[ISP_HWIP] = ISP_HWID,
|
||||
};
|
||||
|
||||
static int amdgpu_discovery_read_binary_from_sysmem(struct amdgpu_device *adev, uint8_t *binary)
|
||||
@@ -711,6 +715,12 @@ static void amdgpu_discovery_read_from_harvest_table(struct amdgpu_device *adev,
|
||||
adev->sdma.sdma_mask &=
|
||||
~(1U << harvest_info->list[i].number_instance);
|
||||
break;
|
||||
#if defined(CONFIG_DRM_AMD_ISP)
|
||||
case ISP_HWID:
|
||||
adev->isp.harvest_config |=
|
||||
~(1U << harvest_info->list[i].number_instance);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -2294,8 +2304,6 @@ static int amdgpu_discovery_set_mm_ip_blocks(struct amdgpu_device *adev)
|
||||
case IP_VERSION(5, 0, 0):
|
||||
amdgpu_device_ip_block_add(adev, &vcn_v5_0_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &jpeg_v5_0_0_ip_block);
|
||||
if (amdgpu_jpeg_test)
|
||||
adev->enable_jpeg_test = true;
|
||||
break;
|
||||
default:
|
||||
dev_err(adev->dev,
|
||||
@@ -2378,6 +2386,24 @@ static int amdgpu_discovery_set_umsch_mm_ip_blocks(struct amdgpu_device *adev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_discovery_set_isp_ip_blocks(struct amdgpu_device *adev)
|
||||
{
|
||||
#if defined(CONFIG_DRM_AMD_ISP)
|
||||
switch (amdgpu_ip_version(adev, ISP_HWIP, 0)) {
|
||||
case IP_VERSION(4, 1, 0):
|
||||
amdgpu_device_ip_block_add(adev, &isp_v4_1_0_ip_block);
|
||||
break;
|
||||
case IP_VERSION(4, 1, 1):
|
||||
amdgpu_device_ip_block_add(adev, &isp_v4_1_1_ip_block);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
||||
{
|
||||
int r;
|
||||
@@ -2904,6 +2930,9 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = amdgpu_discovery_set_isp_ip_blocks(adev);
|
||||
if (r)
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -204,7 +204,6 @@ int amdgpu_force_asic_type = -1;
|
||||
int amdgpu_tmz = -1; /* auto */
|
||||
uint amdgpu_freesync_vid_mode;
|
||||
int amdgpu_reset_method = -1; /* auto */
|
||||
int amdgpu_jpeg_test;
|
||||
int amdgpu_num_kcq = -1;
|
||||
int amdgpu_smartshift_bias;
|
||||
int amdgpu_use_xgmi_p2p = 1;
|
||||
@@ -940,9 +939,6 @@ module_param_named(freesync_video, amdgpu_freesync_vid_mode, uint, 0444);
|
||||
MODULE_PARM_DESC(reset_method, "GPU reset method (-1 = auto (default), 0 = legacy, 1 = mode0, 2 = mode1, 3 = mode2, 4 = baco/bamaco)");
|
||||
module_param_named(reset_method, amdgpu_reset_method, int, 0644);
|
||||
|
||||
MODULE_PARM_DESC(jpeg_test, "jpeg test(0 = disable (default), 1 = enable)");
|
||||
module_param_named(jpeg_test, amdgpu_jpeg_test, int, 0444);
|
||||
|
||||
/**
|
||||
* DOC: bad_page_threshold (int) Bad page threshold is specifies the
|
||||
* threshold value of faulty pages detected by RAS ECC, which may
|
||||
|
||||
@@ -343,11 +343,6 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data,
|
||||
if (args->in.domains & ~AMDGPU_GEM_DOMAIN_MASK)
|
||||
return -EINVAL;
|
||||
|
||||
if ((flags & AMDGPU_GEM_CREATE_GFX12_DCC) &&
|
||||
((amdgpu_ip_version(adev, GC_HWIP, 0) < IP_VERSION(12, 0, 0)) ||
|
||||
!(args->in.domains & AMDGPU_GEM_DOMAIN_VRAM)))
|
||||
return -EINVAL;
|
||||
|
||||
if (!amdgpu_is_tmz(adev) && (flags & AMDGPU_GEM_CREATE_ENCRYPTED)) {
|
||||
DRM_NOTE_ONCE("Cannot allocate secure buffer since TMZ is disabled\n");
|
||||
return -EINVAL;
|
||||
|
||||
@@ -718,7 +718,11 @@ int amdgpu_gmc_flush_gpu_tlb_pasid(struct amdgpu_device *adev, uint16_t pasid,
|
||||
ndw += kiq->pmf->invalidate_tlbs_size;
|
||||
|
||||
spin_lock(&adev->gfx.kiq[inst].ring_lock);
|
||||
amdgpu_ring_alloc(ring, ndw);
|
||||
r = amdgpu_ring_alloc(ring, ndw);
|
||||
if (r) {
|
||||
spin_unlock(&adev->gfx.kiq[inst].ring_lock);
|
||||
goto error_unlock_reset;
|
||||
}
|
||||
if (adev->gmc.flush_tlb_needs_extra_type_2)
|
||||
kiq->pmf->kiq_invalidate_tlbs(ring, pasid, 2, all_hub);
|
||||
|
||||
|
||||
@@ -466,7 +466,8 @@ void amdgpu_irq_dispatch(struct amdgpu_device *adev,
|
||||
} else if (src_id >= AMDGPU_MAX_IRQ_SRC_ID) {
|
||||
DRM_DEBUG("Invalid src_id in IV: %d\n", src_id);
|
||||
|
||||
} else if ((client_id == AMDGPU_IRQ_CLIENTID_LEGACY) &&
|
||||
} else if (((client_id == AMDGPU_IRQ_CLIENTID_LEGACY) ||
|
||||
(client_id == SOC15_IH_CLIENTID_ISP)) &&
|
||||
adev->irq.virq[src_id]) {
|
||||
generic_handle_domain_irq(adev->irq.domain, src_id);
|
||||
|
||||
|
||||
@@ -0,0 +1,210 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/mfd/core.h>
|
||||
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_isp.h"
|
||||
#include "isp_v4_1_0.h"
|
||||
#include "isp_v4_1_1.h"
|
||||
|
||||
static int isp_sw_init(void *handle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int isp_sw_fini(void *handle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* isp_hw_init - start and test isp block
|
||||
*
|
||||
* @handle: handle for amdgpu_device pointer
|
||||
*
|
||||
*/
|
||||
static int isp_hw_init(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_isp *isp = &adev->isp;
|
||||
|
||||
const struct amdgpu_ip_block *ip_block =
|
||||
amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_ISP);
|
||||
|
||||
if (!ip_block)
|
||||
return -EINVAL;
|
||||
|
||||
if (isp->funcs->hw_init != NULL)
|
||||
return isp->funcs->hw_init(isp);
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/**
|
||||
* isp_hw_fini - stop the hardware block
|
||||
*
|
||||
* @handle: handle for amdgpu_device pointer
|
||||
*
|
||||
*/
|
||||
static int isp_hw_fini(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_isp *isp = &adev->isp;
|
||||
|
||||
if (isp->funcs->hw_fini != NULL)
|
||||
return isp->funcs->hw_fini(isp);
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int isp_suspend(void *handle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int isp_resume(void *handle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int isp_load_fw_by_psp(struct amdgpu_device *adev)
|
||||
{
|
||||
const struct common_firmware_header *hdr;
|
||||
char ucode_prefix[10];
|
||||
int r = 0;
|
||||
|
||||
/* get isp fw binary name and path */
|
||||
amdgpu_ucode_ip_version_decode(adev, ISP_HWIP, ucode_prefix,
|
||||
sizeof(ucode_prefix));
|
||||
|
||||
/* read isp fw */
|
||||
r = amdgpu_ucode_request(adev, &adev->isp.fw, "amdgpu/%s.bin", ucode_prefix);
|
||||
if (r) {
|
||||
amdgpu_ucode_release(&adev->isp.fw);
|
||||
return r;
|
||||
}
|
||||
|
||||
hdr = (const struct common_firmware_header *)adev->isp.fw->data;
|
||||
|
||||
adev->firmware.ucode[AMDGPU_UCODE_ID_ISP].ucode_id =
|
||||
AMDGPU_UCODE_ID_ISP;
|
||||
adev->firmware.ucode[AMDGPU_UCODE_ID_ISP].fw = adev->isp.fw;
|
||||
|
||||
adev->firmware.fw_size +=
|
||||
ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int isp_early_init(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_isp *isp = &adev->isp;
|
||||
|
||||
switch (amdgpu_ip_version(adev, ISP_HWIP, 0)) {
|
||||
case IP_VERSION(4, 1, 0):
|
||||
isp_v4_1_0_set_isp_funcs(isp);
|
||||
break;
|
||||
case IP_VERSION(4, 1, 1):
|
||||
isp_v4_1_1_set_isp_funcs(isp);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
isp->adev = adev;
|
||||
isp->parent = adev->dev;
|
||||
|
||||
if (isp_load_fw_by_psp(adev)) {
|
||||
DRM_DEBUG_DRIVER("%s: isp fw load failed\n", __func__);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool isp_is_idle(void *handle)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static int isp_wait_for_idle(void *handle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int isp_soft_reset(void *handle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int isp_set_clockgating_state(void *handle,
|
||||
enum amd_clockgating_state state)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int isp_set_powergating_state(void *handle,
|
||||
enum amd_powergating_state state)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct amd_ip_funcs isp_ip_funcs = {
|
||||
.name = "isp_ip",
|
||||
.early_init = isp_early_init,
|
||||
.late_init = NULL,
|
||||
.sw_init = isp_sw_init,
|
||||
.sw_fini = isp_sw_fini,
|
||||
.hw_init = isp_hw_init,
|
||||
.hw_fini = isp_hw_fini,
|
||||
.suspend = isp_suspend,
|
||||
.resume = isp_resume,
|
||||
.is_idle = isp_is_idle,
|
||||
.wait_for_idle = isp_wait_for_idle,
|
||||
.soft_reset = isp_soft_reset,
|
||||
.set_clockgating_state = isp_set_clockgating_state,
|
||||
.set_powergating_state = isp_set_powergating_state,
|
||||
};
|
||||
|
||||
const struct amdgpu_ip_block_version isp_v4_1_0_ip_block = {
|
||||
.type = AMD_IP_BLOCK_TYPE_ISP,
|
||||
.major = 4,
|
||||
.minor = 1,
|
||||
.rev = 0,
|
||||
.funcs = &isp_ip_funcs,
|
||||
};
|
||||
|
||||
const struct amdgpu_ip_block_version isp_v4_1_1_ip_block = {
|
||||
.type = AMD_IP_BLOCK_TYPE_ISP,
|
||||
.major = 4,
|
||||
.minor = 1,
|
||||
.rev = 1,
|
||||
.funcs = &isp_ip_funcs,
|
||||
};
|
||||
@@ -0,0 +1,60 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __AMDGPU_ISP_H__
|
||||
#define __AMDGPU_ISP_H__
|
||||
|
||||
#define ISP_REGS_OFFSET_END 0x629A4
|
||||
|
||||
struct amdgpu_isp;
|
||||
|
||||
struct isp_platform_data {
|
||||
void *adev;
|
||||
u32 asic_type;
|
||||
resource_size_t base_rmmio_size;
|
||||
};
|
||||
|
||||
struct isp_funcs {
|
||||
int (*hw_init)(struct amdgpu_isp *isp);
|
||||
int (*hw_fini)(struct amdgpu_isp *isp);
|
||||
};
|
||||
|
||||
struct amdgpu_isp {
|
||||
struct device *parent;
|
||||
struct amdgpu_device *adev;
|
||||
const struct isp_funcs *funcs;
|
||||
struct mfd_cell *isp_cell;
|
||||
struct resource *isp_res;
|
||||
struct isp_platform_data *isp_pdata;
|
||||
unsigned int harvest_config;
|
||||
const struct firmware *fw;
|
||||
};
|
||||
|
||||
extern const struct amdgpu_ip_block_version isp_v4_1_0_ip_block;
|
||||
extern const struct amdgpu_ip_block_version isp_v4_1_1_ip_block;
|
||||
|
||||
#endif /* __AMDGPU_ISP_H__ */
|
||||
@@ -60,6 +60,37 @@
|
||||
RREG32_SOC15(JPEG, inst_idx, mmUVD_DPG_LMA_DATA); \
|
||||
})
|
||||
|
||||
#define WREG32_SOC24_JPEG_DPG_MODE(inst_idx, offset, value, indirect) \
|
||||
do { \
|
||||
WREG32_SOC15(JPEG, GET_INST(JPEG, inst_idx), \
|
||||
regUVD_DPG_LMA_DATA, value); \
|
||||
WREG32_SOC15(JPEG, GET_INST(JPEG, inst_idx), \
|
||||
regUVD_DPG_LMA_MASK, 0xFFFFFFFF); \
|
||||
WREG32_SOC15( \
|
||||
JPEG, GET_INST(JPEG, inst_idx), \
|
||||
regUVD_DPG_LMA_CTL, \
|
||||
(UVD_DPG_LMA_CTL__READ_WRITE_MASK | \
|
||||
offset << UVD_DPG_LMA_CTL__READ_WRITE_ADDR__SHIFT | \
|
||||
indirect << UVD_DPG_LMA_CTL__SRAM_SEL__SHIFT)); \
|
||||
} while (0)
|
||||
|
||||
#define RREG32_SOC24_JPEG_DPG_MODE(inst_idx, offset, mask_en) \
|
||||
do { \
|
||||
WREG32_SOC15(JPEG, GET_INST(JPEG, inst_idx), \
|
||||
regUVD_DPG_LMA_MASK, 0xFFFFFFFF); \
|
||||
WREG32_SOC15(JPEG, GET_INST(JPEG, inst_idx), \
|
||||
regUVD_DPG_LMA_CTL, \
|
||||
(UVD_DPG_LMA_CTL__MASK_EN_MASK | \
|
||||
offset << UVD_DPG_LMA_CTL__READ_WRITE_ADDR__SHIFT)); \
|
||||
RREG32_SOC15(JPEG, inst_idx, regUVD_DPG_LMA_DATA); \
|
||||
} while (0)
|
||||
|
||||
#define ADD_SOC24_JPEG_TO_DPG_SRAM(inst_idx, offset, value, indirect) \
|
||||
do { \
|
||||
*adev->jpeg.inst[inst_idx].dpg_sram_curr_addr++ = offset; \
|
||||
*adev->jpeg.inst[inst_idx].dpg_sram_curr_addr++ = value; \
|
||||
} while (0)
|
||||
|
||||
struct amdgpu_jpeg_reg{
|
||||
unsigned jpeg_pitch[AMDGPU_MAX_JPEG_RINGS];
|
||||
};
|
||||
|
||||
@@ -1599,36 +1599,39 @@ u64 amdgpu_bo_print_info(int id, struct amdgpu_bo *bo, struct seq_file *m)
|
||||
u64 size;
|
||||
|
||||
if (dma_resv_trylock(bo->tbo.base.resv)) {
|
||||
|
||||
switch (bo->tbo.resource->mem_type) {
|
||||
case TTM_PL_VRAM:
|
||||
if (amdgpu_res_cpu_visible(adev, bo->tbo.resource))
|
||||
placement = "VRAM VISIBLE";
|
||||
else
|
||||
placement = "VRAM";
|
||||
break;
|
||||
case TTM_PL_TT:
|
||||
placement = "GTT";
|
||||
break;
|
||||
case AMDGPU_PL_GDS:
|
||||
placement = "GDS";
|
||||
break;
|
||||
case AMDGPU_PL_GWS:
|
||||
placement = "GWS";
|
||||
break;
|
||||
case AMDGPU_PL_OA:
|
||||
placement = "OA";
|
||||
break;
|
||||
case AMDGPU_PL_PREEMPT:
|
||||
placement = "PREEMPTIBLE";
|
||||
break;
|
||||
case AMDGPU_PL_DOORBELL:
|
||||
placement = "DOORBELL";
|
||||
break;
|
||||
case TTM_PL_SYSTEM:
|
||||
default:
|
||||
placement = "CPU";
|
||||
break;
|
||||
if (!bo->tbo.resource) {
|
||||
placement = "NONE";
|
||||
} else {
|
||||
switch (bo->tbo.resource->mem_type) {
|
||||
case TTM_PL_VRAM:
|
||||
if (amdgpu_res_cpu_visible(adev, bo->tbo.resource))
|
||||
placement = "VRAM VISIBLE";
|
||||
else
|
||||
placement = "VRAM";
|
||||
break;
|
||||
case TTM_PL_TT:
|
||||
placement = "GTT";
|
||||
break;
|
||||
case AMDGPU_PL_GDS:
|
||||
placement = "GDS";
|
||||
break;
|
||||
case AMDGPU_PL_GWS:
|
||||
placement = "GWS";
|
||||
break;
|
||||
case AMDGPU_PL_OA:
|
||||
placement = "OA";
|
||||
break;
|
||||
case AMDGPU_PL_PREEMPT:
|
||||
placement = "PREEMPTIBLE";
|
||||
break;
|
||||
case AMDGPU_PL_DOORBELL:
|
||||
placement = "DOORBELL";
|
||||
break;
|
||||
case TTM_PL_SYSTEM:
|
||||
default:
|
||||
placement = "CPU";
|
||||
break;
|
||||
}
|
||||
}
|
||||
dma_resv_unlock(bo->tbo.base.resv);
|
||||
} else {
|
||||
|
||||
@@ -2559,6 +2559,9 @@ static int psp_get_fw_type(struct amdgpu_firmware_info *ucode,
|
||||
case AMDGPU_UCODE_ID_JPEG_RAM:
|
||||
*type = GFX_FW_TYPE_JPEG_RAM;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_ISP:
|
||||
*type = GFX_FW_TYPE_ISP;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_MAXIMUM:
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
||||
@@ -120,7 +120,7 @@ const char *get_ras_block_str(struct ras_common_if *ras_block)
|
||||
/* typical ECC bad page rate is 1 bad page per 100MB VRAM */
|
||||
#define RAS_BAD_PAGE_COVER (100 * 1024 * 1024ULL)
|
||||
|
||||
#define MAX_UMC_POISON_POLLING_TIME_ASYNC 100 //ms
|
||||
#define MAX_UMC_POISON_POLLING_TIME_ASYNC 300 //ms
|
||||
|
||||
#define AMDGPU_RAS_RETIRE_PAGE_INTERVAL 100 //ms
|
||||
|
||||
@@ -1384,10 +1384,17 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev, struct ras_query_i
|
||||
memset(&qctx, 0, sizeof(qctx));
|
||||
qctx.event_id = amdgpu_ras_acquire_event_id(adev, amdgpu_ras_intr_triggered() ?
|
||||
RAS_EVENT_TYPE_ISR : RAS_EVENT_TYPE_INVALID);
|
||||
|
||||
if (!down_read_trylock(&adev->reset_domain->sem)) {
|
||||
ret = -EIO;
|
||||
goto out_fini_err_data;
|
||||
}
|
||||
|
||||
ret = amdgpu_ras_query_error_status_helper(adev, info,
|
||||
&err_data,
|
||||
&qctx,
|
||||
error_query_mode);
|
||||
up_read(&adev->reset_domain->sem);
|
||||
if (ret)
|
||||
goto out_fini_err_data;
|
||||
|
||||
@@ -2105,10 +2112,8 @@ static void amdgpu_ras_interrupt_poison_creation_handler(struct ras_manager *obj
|
||||
if (amdgpu_ip_version(obj->adev, UMC_HWIP, 0) >= IP_VERSION(12, 0, 0)) {
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(obj->adev);
|
||||
|
||||
amdgpu_ras_put_poison_req(obj->adev,
|
||||
AMDGPU_RAS_BLOCK__UMC, 0, NULL, NULL, false);
|
||||
|
||||
atomic_inc(&con->page_retirement_req_cnt);
|
||||
atomic_inc(&con->poison_creation_count);
|
||||
|
||||
wake_up(&con->page_retirement_wq);
|
||||
}
|
||||
@@ -2799,7 +2804,8 @@ static void amdgpu_ras_ecc_log_init(struct ras_ecc_log_info *ecc_log)
|
||||
memset(&ecc_log->ecc_key, 0xad, sizeof(ecc_log->ecc_key));
|
||||
|
||||
INIT_RADIX_TREE(&ecc_log->de_page_tree, GFP_KERNEL);
|
||||
ecc_log->de_updated = false;
|
||||
ecc_log->de_queried_count = 0;
|
||||
ecc_log->prev_de_queried_count = 0;
|
||||
}
|
||||
|
||||
static void amdgpu_ras_ecc_log_fini(struct ras_ecc_log_info *ecc_log)
|
||||
@@ -2818,7 +2824,8 @@ static void amdgpu_ras_ecc_log_fini(struct ras_ecc_log_info *ecc_log)
|
||||
mutex_unlock(&ecc_log->lock);
|
||||
|
||||
mutex_destroy(&ecc_log->lock);
|
||||
ecc_log->de_updated = false;
|
||||
ecc_log->de_queried_count = 0;
|
||||
ecc_log->prev_de_queried_count = 0;
|
||||
}
|
||||
|
||||
static void amdgpu_ras_do_page_retirement(struct work_struct *work)
|
||||
@@ -2850,60 +2857,116 @@ static void amdgpu_ras_do_page_retirement(struct work_struct *work)
|
||||
mutex_unlock(&con->umc_ecc_log.lock);
|
||||
}
|
||||
|
||||
static void amdgpu_ras_poison_creation_handler(struct amdgpu_device *adev,
|
||||
uint32_t timeout_ms)
|
||||
static int amdgpu_ras_poison_creation_handler(struct amdgpu_device *adev,
|
||||
uint32_t poison_creation_count)
|
||||
{
|
||||
int ret = 0;
|
||||
struct ras_ecc_log_info *ecc_log;
|
||||
struct ras_query_if info;
|
||||
uint32_t timeout = timeout_ms;
|
||||
uint32_t timeout = 0;
|
||||
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
|
||||
uint64_t de_queried_count;
|
||||
uint32_t new_detect_count, total_detect_count;
|
||||
uint32_t need_query_count = poison_creation_count;
|
||||
bool query_data_timeout = false;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.head.block = AMDGPU_RAS_BLOCK__UMC;
|
||||
|
||||
ecc_log = &ras->umc_ecc_log;
|
||||
ecc_log->de_updated = false;
|
||||
total_detect_count = 0;
|
||||
do {
|
||||
ret = amdgpu_ras_query_error_status(adev, &info);
|
||||
if (ret) {
|
||||
dev_err(adev->dev, "Failed to query ras error! ret:%d\n", ret);
|
||||
return;
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
de_queried_count = ecc_log->de_queried_count;
|
||||
if (de_queried_count > ecc_log->prev_de_queried_count) {
|
||||
new_detect_count = de_queried_count - ecc_log->prev_de_queried_count;
|
||||
ecc_log->prev_de_queried_count = de_queried_count;
|
||||
timeout = 0;
|
||||
} else {
|
||||
new_detect_count = 0;
|
||||
}
|
||||
|
||||
if (timeout && !ecc_log->de_updated) {
|
||||
msleep(1);
|
||||
timeout--;
|
||||
}
|
||||
} while (timeout && !ecc_log->de_updated);
|
||||
if (new_detect_count) {
|
||||
total_detect_count += new_detect_count;
|
||||
} else {
|
||||
if (!timeout && need_query_count)
|
||||
timeout = MAX_UMC_POISON_POLLING_TIME_ASYNC;
|
||||
|
||||
if (timeout_ms && !timeout) {
|
||||
dev_warn(adev->dev, "Can't find deferred error\n");
|
||||
return;
|
||||
if (timeout) {
|
||||
if (!--timeout) {
|
||||
query_data_timeout = true;
|
||||
break;
|
||||
}
|
||||
msleep(1);
|
||||
}
|
||||
}
|
||||
} while (total_detect_count < need_query_count);
|
||||
|
||||
if (query_data_timeout) {
|
||||
dev_warn(adev->dev, "Can't find deferred error! count: %u\n",
|
||||
(need_query_count - total_detect_count));
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
if (total_detect_count)
|
||||
schedule_delayed_work(&ras->page_retirement_dwork, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void amdgpu_ras_clear_poison_fifo(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
struct ras_poison_msg msg;
|
||||
int ret;
|
||||
|
||||
do {
|
||||
ret = kfifo_get(&con->poison_fifo, &msg);
|
||||
} while (ret);
|
||||
}
|
||||
|
||||
static int amdgpu_ras_poison_consumption_handler(struct amdgpu_device *adev,
|
||||
struct ras_poison_msg *poison_msg)
|
||||
uint32_t msg_count, uint32_t *gpu_reset)
|
||||
{
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
uint32_t reset = poison_msg->reset;
|
||||
uint16_t pasid = poison_msg->pasid;
|
||||
uint32_t reset_flags = 0, reset = 0;
|
||||
struct ras_poison_msg msg;
|
||||
int ret, i;
|
||||
|
||||
kgd2kfd_set_sram_ecc_flag(adev->kfd.dev);
|
||||
|
||||
if (poison_msg->pasid_fn)
|
||||
poison_msg->pasid_fn(adev, pasid, poison_msg->data);
|
||||
for (i = 0; i < msg_count; i++) {
|
||||
ret = amdgpu_ras_get_poison_req(adev, &msg);
|
||||
if (!ret)
|
||||
continue;
|
||||
|
||||
if (msg.pasid_fn)
|
||||
msg.pasid_fn(adev, msg.pasid, msg.data);
|
||||
|
||||
reset_flags |= msg.reset;
|
||||
}
|
||||
|
||||
/* for RMA, amdgpu_ras_poison_creation_handler will trigger gpu reset */
|
||||
if (reset && !con->is_rma) {
|
||||
if (reset_flags && !con->is_rma) {
|
||||
if (reset_flags & AMDGPU_RAS_GPU_RESET_MODE1_RESET)
|
||||
reset = AMDGPU_RAS_GPU_RESET_MODE1_RESET;
|
||||
else if (reset_flags & AMDGPU_RAS_GPU_RESET_MODE2_RESET)
|
||||
reset = AMDGPU_RAS_GPU_RESET_MODE2_RESET;
|
||||
else
|
||||
reset = reset_flags;
|
||||
|
||||
flush_delayed_work(&con->page_retirement_dwork);
|
||||
|
||||
con->gpu_reset_flags |= reset;
|
||||
amdgpu_ras_reset_gpu(adev);
|
||||
|
||||
*gpu_reset = reset;
|
||||
|
||||
/* Wait for gpu recovery to complete */
|
||||
flush_work(&con->recovery_work);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -2913,9 +2976,9 @@ static int amdgpu_ras_page_retirement_thread(void *param)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)param;
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
struct ras_poison_msg poison_msg;
|
||||
enum amdgpu_ras_block ras_block;
|
||||
bool poison_creation_is_handled = false;
|
||||
uint32_t poison_creation_count, msg_count;
|
||||
uint32_t gpu_reset;
|
||||
int ret;
|
||||
|
||||
while (!kthread_should_stop()) {
|
||||
|
||||
@@ -2926,33 +2989,61 @@ static int amdgpu_ras_page_retirement_thread(void *param)
|
||||
if (kthread_should_stop())
|
||||
break;
|
||||
|
||||
atomic_dec(&con->page_retirement_req_cnt);
|
||||
gpu_reset = 0;
|
||||
|
||||
if (!amdgpu_ras_get_poison_req(adev, &poison_msg))
|
||||
continue;
|
||||
do {
|
||||
poison_creation_count = atomic_read(&con->poison_creation_count);
|
||||
ret = amdgpu_ras_poison_creation_handler(adev, poison_creation_count);
|
||||
if (ret == -EIO)
|
||||
break;
|
||||
|
||||
ras_block = poison_msg.block;
|
||||
if (poison_creation_count) {
|
||||
atomic_sub(poison_creation_count, &con->poison_creation_count);
|
||||
atomic_sub(poison_creation_count, &con->page_retirement_req_cnt);
|
||||
}
|
||||
} while (atomic_read(&con->poison_creation_count));
|
||||
|
||||
dev_dbg(adev->dev, "Start processing ras block %s(%d)\n",
|
||||
ras_block_str(ras_block), ras_block);
|
||||
if (ret != -EIO) {
|
||||
msg_count = kfifo_len(&con->poison_fifo);
|
||||
if (msg_count) {
|
||||
ret = amdgpu_ras_poison_consumption_handler(adev,
|
||||
msg_count, &gpu_reset);
|
||||
if ((ret != -EIO) &&
|
||||
(gpu_reset != AMDGPU_RAS_GPU_RESET_MODE1_RESET))
|
||||
atomic_sub(msg_count, &con->page_retirement_req_cnt);
|
||||
}
|
||||
}
|
||||
|
||||
if (ras_block == AMDGPU_RAS_BLOCK__UMC) {
|
||||
amdgpu_ras_poison_creation_handler(adev,
|
||||
MAX_UMC_POISON_POLLING_TIME_ASYNC);
|
||||
poison_creation_is_handled = true;
|
||||
} else {
|
||||
/* poison_creation_is_handled:
|
||||
* false: no poison creation interrupt, but it has poison
|
||||
* consumption interrupt.
|
||||
* true: It has poison creation interrupt at the beginning,
|
||||
* but it has no poison creation interrupt later.
|
||||
*/
|
||||
amdgpu_ras_poison_creation_handler(adev,
|
||||
poison_creation_is_handled ?
|
||||
0 : MAX_UMC_POISON_POLLING_TIME_ASYNC);
|
||||
if ((ret == -EIO) || (gpu_reset == AMDGPU_RAS_GPU_RESET_MODE1_RESET)) {
|
||||
/* gpu mode-1 reset is ongoing or just completed ras mode-1 reset */
|
||||
/* Clear poison creation request */
|
||||
atomic_set(&con->poison_creation_count, 0);
|
||||
|
||||
amdgpu_ras_poison_consumption_handler(adev, &poison_msg);
|
||||
poison_creation_is_handled = false;
|
||||
/* Clear poison fifo */
|
||||
amdgpu_ras_clear_poison_fifo(adev);
|
||||
|
||||
/* Clear all poison requests */
|
||||
atomic_set(&con->page_retirement_req_cnt, 0);
|
||||
|
||||
if (ret == -EIO) {
|
||||
/* Wait for mode-1 reset to complete */
|
||||
down_read(&adev->reset_domain->sem);
|
||||
up_read(&adev->reset_domain->sem);
|
||||
}
|
||||
|
||||
/* Wake up work to save bad pages to eeprom */
|
||||
schedule_delayed_work(&con->page_retirement_dwork, 0);
|
||||
} else if (gpu_reset) {
|
||||
/* gpu just completed mode-2 reset or other reset */
|
||||
/* Clear poison consumption messages cached in fifo */
|
||||
msg_count = kfifo_len(&con->poison_fifo);
|
||||
if (msg_count) {
|
||||
amdgpu_ras_clear_poison_fifo(adev);
|
||||
atomic_sub(msg_count, &con->page_retirement_req_cnt);
|
||||
}
|
||||
|
||||
/* Wake up work to save bad pages to eeprom */
|
||||
schedule_delayed_work(&con->page_retirement_dwork, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3026,6 +3117,7 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev)
|
||||
mutex_init(&con->page_retirement_lock);
|
||||
init_waitqueue_head(&con->page_retirement_wq);
|
||||
atomic_set(&con->page_retirement_req_cnt, 0);
|
||||
atomic_set(&con->poison_creation_count, 0);
|
||||
con->page_retirement_thread =
|
||||
kthread_run(amdgpu_ras_page_retirement_thread, adev, "umc_page_retirement");
|
||||
if (IS_ERR(con->page_retirement_thread)) {
|
||||
@@ -3074,6 +3166,7 @@ static int amdgpu_ras_recovery_fini(struct amdgpu_device *adev)
|
||||
kthread_stop(con->page_retirement_thread);
|
||||
|
||||
atomic_set(&con->page_retirement_req_cnt, 0);
|
||||
atomic_set(&con->poison_creation_count, 0);
|
||||
|
||||
mutex_destroy(&con->page_rsv_lock);
|
||||
|
||||
|
||||
@@ -469,7 +469,8 @@ struct ras_ecc_log_info {
|
||||
struct mutex lock;
|
||||
siphash_key_t ecc_key;
|
||||
struct radix_tree_root de_page_tree;
|
||||
bool de_updated;
|
||||
uint64_t de_queried_count;
|
||||
uint64_t prev_de_queried_count;
|
||||
};
|
||||
|
||||
struct amdgpu_ras {
|
||||
@@ -531,6 +532,7 @@ struct amdgpu_ras {
|
||||
wait_queue_head_t page_retirement_wq;
|
||||
struct mutex page_retirement_lock;
|
||||
atomic_t page_retirement_req_cnt;
|
||||
atomic_t poison_creation_count;
|
||||
struct mutex page_rsv_lock;
|
||||
DECLARE_KFIFO(poison_fifo, struct ras_poison_msg, 128);
|
||||
struct ras_ecc_log_info umc_ecc_log;
|
||||
|
||||
@@ -714,6 +714,8 @@ const char *amdgpu_ucode_name(enum AMDGPU_UCODE_ID ucode_id)
|
||||
return "RS64_MEC_P2_STACK";
|
||||
case AMDGPU_UCODE_ID_CP_RS64_MEC_P3_STACK:
|
||||
return "RS64_MEC_P3_STACK";
|
||||
case AMDGPU_UCODE_ID_ISP:
|
||||
return "ISP";
|
||||
default:
|
||||
return "UNKNOWN UCODE";
|
||||
}
|
||||
@@ -1413,6 +1415,9 @@ void amdgpu_ucode_ip_version_decode(struct amdgpu_device *adev, int block_type,
|
||||
case VPE_HWIP:
|
||||
ip_name = "vpe";
|
||||
break;
|
||||
case ISP_HWIP:
|
||||
ip_name = "isp";
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
@@ -523,6 +523,7 @@ enum AMDGPU_UCODE_ID {
|
||||
AMDGPU_UCODE_ID_UMSCH_MM_CMD_BUFFER,
|
||||
AMDGPU_UCODE_ID_P2S_TABLE,
|
||||
AMDGPU_UCODE_ID_JPEG_RAM,
|
||||
AMDGPU_UCODE_ID_ISP,
|
||||
AMDGPU_UCODE_ID_MAXIMUM,
|
||||
};
|
||||
|
||||
|
||||
@@ -293,14 +293,15 @@ int amdgpu_umc_pasid_poison_handler(struct amdgpu_device *adev,
|
||||
|
||||
amdgpu_ras_error_data_fini(&err_data);
|
||||
} else {
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
|
||||
amdgpu_ras_put_poison_req(adev,
|
||||
block, pasid, pasid_fn, data, reset);
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
int ret;
|
||||
|
||||
ret = amdgpu_ras_put_poison_req(adev,
|
||||
block, pasid, pasid_fn, data, reset);
|
||||
if (!ret) {
|
||||
atomic_inc(&con->page_retirement_req_cnt);
|
||||
|
||||
wake_up(&con->page_retirement_wq);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (adev->virt.ops && adev->virt.ops->ras_poison_handler)
|
||||
|
||||
@@ -229,6 +229,22 @@ void amdgpu_virt_free_mm_table(struct amdgpu_device *adev)
|
||||
adev->virt.mm_table.gpu_addr = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_virt_rcvd_ras_interrupt() - receive ras interrupt
|
||||
* @adev: amdgpu device.
|
||||
* Check whether host sent RAS error message
|
||||
* Return: true if found, otherwise false
|
||||
*/
|
||||
bool amdgpu_virt_rcvd_ras_interrupt(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_virt *virt = &adev->virt;
|
||||
|
||||
if (!virt->ops || !virt->ops->rcvd_ras_intr)
|
||||
return false;
|
||||
|
||||
return virt->ops->rcvd_ras_intr(adev);
|
||||
}
|
||||
|
||||
|
||||
unsigned int amd_sriov_msg_checksum(void *obj,
|
||||
unsigned long obj_size,
|
||||
@@ -612,11 +628,14 @@ static void amdgpu_virt_update_vf2pf_work_item(struct work_struct *work)
|
||||
ret = amdgpu_virt_read_pf2vf_data(adev);
|
||||
if (ret) {
|
||||
adev->virt.vf2pf_update_retry_cnt++;
|
||||
if ((adev->virt.vf2pf_update_retry_cnt >= AMDGPU_VF2PF_UPDATE_MAX_RETRY_LIMIT) &&
|
||||
amdgpu_sriov_runtime(adev)) {
|
||||
|
||||
if ((amdgpu_virt_rcvd_ras_interrupt(adev) ||
|
||||
adev->virt.vf2pf_update_retry_cnt >= AMDGPU_VF2PF_UPDATE_MAX_RETRY_LIMIT) &&
|
||||
amdgpu_sriov_runtime(adev)) {
|
||||
|
||||
amdgpu_ras_set_fed(adev, true);
|
||||
if (amdgpu_reset_domain_schedule(adev->reset_domain,
|
||||
&adev->kfd.reset_work))
|
||||
&adev->kfd.reset_work))
|
||||
return;
|
||||
else
|
||||
dev_err(adev->dev, "Failed to queue work! at %s", __func__);
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
/* tonga/fiji use this offset */
|
||||
#define mmBIF_IOV_FUNC_IDENTIFIER 0x1503
|
||||
|
||||
#define AMDGPU_VF2PF_UPDATE_MAX_RETRY_LIMIT 5
|
||||
#define AMDGPU_VF2PF_UPDATE_MAX_RETRY_LIMIT 2
|
||||
|
||||
enum amdgpu_sriov_vf_mode {
|
||||
SRIOV_VF_MODE_BARE_METAL = 0,
|
||||
@@ -94,6 +94,7 @@ struct amdgpu_virt_ops {
|
||||
u32 data1, u32 data2, u32 data3);
|
||||
void (*ras_poison_handler)(struct amdgpu_device *adev,
|
||||
enum amdgpu_ras_block block);
|
||||
bool (*rcvd_ras_intr)(struct amdgpu_device *adev);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -352,6 +353,7 @@ void amdgpu_virt_ready_to_reset(struct amdgpu_device *adev);
|
||||
int amdgpu_virt_wait_reset(struct amdgpu_device *adev);
|
||||
int amdgpu_virt_alloc_mm_table(struct amdgpu_device *adev);
|
||||
void amdgpu_virt_free_mm_table(struct amdgpu_device *adev);
|
||||
bool amdgpu_virt_rcvd_ras_interrupt(struct amdgpu_device *adev);
|
||||
void amdgpu_virt_release_ras_err_handler_data(struct amdgpu_device *adev);
|
||||
void amdgpu_virt_init_data_exchange(struct amdgpu_device *adev);
|
||||
void amdgpu_virt_exchange_data(struct amdgpu_device *adev);
|
||||
|
||||
@@ -611,10 +611,9 @@ static int gfx_v11_0_init_toc_microcode(struct amdgpu_device *adev, const char *
|
||||
{
|
||||
const struct psp_firmware_header_v1_0 *toc_hdr;
|
||||
int err = 0;
|
||||
char fw_name[40];
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_toc.bin", ucode_prefix);
|
||||
err = amdgpu_ucode_request(adev, &adev->psp.toc_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->psp.toc_fw,
|
||||
"amdgpu/%s_toc.bin", ucode_prefix);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
@@ -653,7 +652,6 @@ static void gfx_v11_0_check_fw_cp_gfx_shadow(struct amdgpu_device *adev)
|
||||
|
||||
static int gfx_v11_0_init_microcode(struct amdgpu_device *adev)
|
||||
{
|
||||
char fw_name[40];
|
||||
char ucode_prefix[25];
|
||||
int err;
|
||||
const struct rlc_firmware_header_v2_0 *rlc_hdr;
|
||||
@@ -663,9 +661,8 @@ static int gfx_v11_0_init_microcode(struct amdgpu_device *adev)
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
amdgpu_ucode_ip_version_decode(adev, GC_HWIP, ucode_prefix, sizeof(ucode_prefix));
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp.bin", ucode_prefix);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw,
|
||||
"amdgpu/%s_pfp.bin", ucode_prefix);
|
||||
if (err)
|
||||
goto out;
|
||||
/* check pfp fw hdr version to decide if enable rs64 for gfx11.*/
|
||||
@@ -681,8 +678,8 @@ static int gfx_v11_0_init_microcode(struct amdgpu_device *adev)
|
||||
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_PFP);
|
||||
}
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me.bin", ucode_prefix);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.me_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.me_fw,
|
||||
"amdgpu/%s_me.bin", ucode_prefix);
|
||||
if (err)
|
||||
goto out;
|
||||
if (adev->gfx.rs64_enable) {
|
||||
@@ -696,10 +693,11 @@ static int gfx_v11_0_init_microcode(struct amdgpu_device *adev)
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 0, 0) &&
|
||||
adev->pdev->revision == 0xCE)
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/gc_11_0_0_rlc_1.bin");
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw,
|
||||
"amdgpu/gc_11_0_0_rlc_1.bin");
|
||||
else
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", ucode_prefix);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw,
|
||||
"amdgpu/%s_rlc.bin", ucode_prefix);
|
||||
if (err)
|
||||
goto out;
|
||||
rlc_hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data;
|
||||
@@ -710,8 +708,8 @@ static int gfx_v11_0_init_microcode(struct amdgpu_device *adev)
|
||||
goto out;
|
||||
}
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec.bin", ucode_prefix);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw,
|
||||
"amdgpu/%s_mec.bin", ucode_prefix);
|
||||
if (err)
|
||||
goto out;
|
||||
if (adev->gfx.rs64_enable) {
|
||||
@@ -4500,11 +4498,11 @@ static int gfx_v11_0_hw_init(void *handle)
|
||||
/* RLC autoload sequence 1: Program rlc ram */
|
||||
if (adev->gfx.imu.funcs->program_rlc_ram)
|
||||
adev->gfx.imu.funcs->program_rlc_ram(adev);
|
||||
/* rlc autoload firmware */
|
||||
r = gfx_v11_0_rlc_backdoor_autoload_enable(adev);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
/* rlc autoload firmware */
|
||||
r = gfx_v11_0_rlc_backdoor_autoload_enable(adev);
|
||||
if (r)
|
||||
return r;
|
||||
} else {
|
||||
if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) {
|
||||
if (adev->gfx.imu.funcs && (amdgpu_dpm > 0)) {
|
||||
|
||||
@@ -386,10 +386,9 @@ static int gfx_v12_0_init_toc_microcode(struct amdgpu_device *adev, const char *
|
||||
{
|
||||
const struct psp_firmware_header_v1_0 *toc_hdr;
|
||||
int err = 0;
|
||||
char fw_name[40];
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_toc.bin", ucode_prefix);
|
||||
err = amdgpu_ucode_request(adev, &adev->psp.toc_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->psp.toc_fw,
|
||||
"amdgpu/%s_toc.bin", ucode_prefix);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
@@ -407,7 +406,6 @@ out:
|
||||
|
||||
static int gfx_v12_0_init_microcode(struct amdgpu_device *adev)
|
||||
{
|
||||
char fw_name[40];
|
||||
char ucode_prefix[15];
|
||||
int err;
|
||||
const struct rlc_firmware_header_v2_0 *rlc_hdr;
|
||||
@@ -418,23 +416,23 @@ static int gfx_v12_0_init_microcode(struct amdgpu_device *adev)
|
||||
|
||||
amdgpu_ucode_ip_version_decode(adev, GC_HWIP, ucode_prefix, sizeof(ucode_prefix));
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp.bin", ucode_prefix);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw,
|
||||
"amdgpu/%s_pfp.bin", ucode_prefix);
|
||||
if (err)
|
||||
goto out;
|
||||
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_RS64_PFP);
|
||||
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_RS64_PFP_P0_STACK);
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me.bin", ucode_prefix);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.me_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.me_fw,
|
||||
"amdgpu/%s_me.bin", ucode_prefix);
|
||||
if (err)
|
||||
goto out;
|
||||
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_RS64_ME);
|
||||
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_RS64_ME_P0_STACK);
|
||||
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", ucode_prefix);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw,
|
||||
"amdgpu/%s_rlc.bin", ucode_prefix);
|
||||
if (err)
|
||||
goto out;
|
||||
rlc_hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data;
|
||||
@@ -445,8 +443,8 @@ static int gfx_v12_0_init_microcode(struct amdgpu_device *adev)
|
||||
goto out;
|
||||
}
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec.bin", ucode_prefix);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw, fw_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw,
|
||||
"amdgpu/%s_mec.bin", ucode_prefix);
|
||||
if (err)
|
||||
goto out;
|
||||
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_RS64_MEC);
|
||||
|
||||
@@ -55,6 +55,14 @@ MODULE_FIRMWARE("amdgpu/gc_9_4_4_rlc.bin");
|
||||
#define mmSMNAID_XCD1_MCA_SMU 0x38430400 /* SMN AID XCD1 */
|
||||
#define mmSMNXCD_XCD0_MCA_SMU 0x40430400 /* SMN XCD XCD0 */
|
||||
|
||||
#define XCC_REG_RANGE_0_LOW 0x2000 /* XCC gfxdec0 lower Bound */
|
||||
#define XCC_REG_RANGE_0_HIGH 0x3400 /* XCC gfxdec0 upper Bound */
|
||||
#define XCC_REG_RANGE_1_LOW 0xA000 /* XCC gfxdec1 lower Bound */
|
||||
#define XCC_REG_RANGE_1_HIGH 0x10000 /* XCC gfxdec1 upper Bound */
|
||||
|
||||
#define NORMALIZE_XCC_REG_OFFSET(offset) \
|
||||
(offset & 0xFFFF)
|
||||
|
||||
struct amdgpu_gfx_ras gfx_v9_4_3_ras;
|
||||
|
||||
static void gfx_v9_4_3_set_ring_funcs(struct amdgpu_device *adev);
|
||||
@@ -217,9 +225,24 @@ static void gfx_v9_4_3_init_golden_registers(struct amdgpu_device *adev)
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t gfx_v9_4_3_normalize_xcc_reg_offset(uint32_t reg)
|
||||
{
|
||||
uint32_t normalized_reg = NORMALIZE_XCC_REG_OFFSET(reg);
|
||||
|
||||
/* If it is an XCC reg, normalize the reg to keep
|
||||
lower 16 bits in local xcc */
|
||||
|
||||
if (((normalized_reg >= XCC_REG_RANGE_0_LOW) && (normalized_reg < XCC_REG_RANGE_0_HIGH)) ||
|
||||
((normalized_reg >= XCC_REG_RANGE_1_LOW) && (normalized_reg < XCC_REG_RANGE_1_HIGH)))
|
||||
return normalized_reg;
|
||||
else
|
||||
return reg;
|
||||
}
|
||||
|
||||
static void gfx_v9_4_3_write_data_to_reg(struct amdgpu_ring *ring, int eng_sel,
|
||||
bool wc, uint32_t reg, uint32_t val)
|
||||
{
|
||||
reg = gfx_v9_4_3_normalize_xcc_reg_offset(reg);
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
|
||||
amdgpu_ring_write(ring, WRITE_DATA_ENGINE_SEL(eng_sel) |
|
||||
WRITE_DATA_DST_SEL(0) |
|
||||
@@ -234,6 +257,12 @@ static void gfx_v9_4_3_wait_reg_mem(struct amdgpu_ring *ring, int eng_sel,
|
||||
uint32_t addr1, uint32_t ref, uint32_t mask,
|
||||
uint32_t inv)
|
||||
{
|
||||
/* Only do the normalization on regspace */
|
||||
if (mem_space == 0) {
|
||||
addr0 = gfx_v9_4_3_normalize_xcc_reg_offset(addr0);
|
||||
addr1 = gfx_v9_4_3_normalize_xcc_reg_offset(addr1);
|
||||
}
|
||||
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5));
|
||||
amdgpu_ring_write(ring,
|
||||
/* memory (1) or register (0) */
|
||||
@@ -2725,6 +2754,8 @@ static void gfx_v9_4_3_ring_emit_rreg(struct amdgpu_ring *ring, uint32_t reg,
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
reg = gfx_v9_4_3_normalize_xcc_reg_offset(reg);
|
||||
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_COPY_DATA, 4));
|
||||
amdgpu_ring_write(ring, 0 | /* src: register*/
|
||||
(5 << 8) | /* dst: memory */
|
||||
@@ -2742,6 +2773,8 @@ static void gfx_v9_4_3_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg,
|
||||
{
|
||||
uint32_t cmd = 0;
|
||||
|
||||
reg = gfx_v9_4_3_normalize_xcc_reg_offset(reg);
|
||||
|
||||
switch (ring->funcs->type) {
|
||||
case AMDGPU_RING_TYPE_GFX:
|
||||
cmd = WRITE_DATA_ENGINE_SEL(1) | WR_CONFIRM;
|
||||
|
||||
@@ -629,9 +629,11 @@ static bool gfxhub_v1_2_query_utcl2_poison_status(struct amdgpu_device *adev,
|
||||
|
||||
status = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regVM_L2_PROTECTION_FAULT_STATUS);
|
||||
fed = REG_GET_FIELD(status, VM_L2_PROTECTION_FAULT_STATUS, FED);
|
||||
/* reset page fault status */
|
||||
WREG32_P(SOC15_REG_OFFSET(GC, GET_INST(GC, xcc_id),
|
||||
regVM_L2_PROTECTION_FAULT_STATUS), 1, ~1);
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
/* clear page fault status and address */
|
||||
WREG32_P(SOC15_REG_OFFSET(GC, GET_INST(GC, xcc_id),
|
||||
regVM_L2_PROTECTION_FAULT_CNTL), 1, ~1);
|
||||
}
|
||||
|
||||
return fed;
|
||||
}
|
||||
|
||||
@@ -464,10 +464,6 @@ static uint64_t gmc_v12_0_map_mtype(struct amdgpu_device *adev, uint32_t flags)
|
||||
return AMDGPU_PTE_MTYPE_GFX12(0ULL, MTYPE_NC);
|
||||
case AMDGPU_VM_MTYPE_NC:
|
||||
return AMDGPU_PTE_MTYPE_GFX12(0ULL, MTYPE_NC);
|
||||
case AMDGPU_VM_MTYPE_WC:
|
||||
return AMDGPU_PTE_MTYPE_GFX12(0ULL, MTYPE_WC);
|
||||
case AMDGPU_VM_MTYPE_CC:
|
||||
return AMDGPU_PTE_MTYPE_GFX12(0ULL, MTYPE_CC);
|
||||
case AMDGPU_VM_MTYPE_UC:
|
||||
return AMDGPU_PTE_MTYPE_GFX12(0ULL, MTYPE_UC);
|
||||
default:
|
||||
|
||||
@@ -672,7 +672,8 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
|
||||
(amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(9, 4, 2)))
|
||||
return 0;
|
||||
|
||||
WREG32_P(hub->vm_l2_pro_fault_cntl, 1, ~1);
|
||||
if (!amdgpu_sriov_vf(adev))
|
||||
WREG32_P(hub->vm_l2_pro_fault_cntl, 1, ~1);
|
||||
|
||||
amdgpu_vm_update_fault_cache(adev, entry->pasid, addr, status, vmhub);
|
||||
|
||||
|
||||
@@ -135,6 +135,34 @@ static int ih_v6_0_toggle_ring_interrupts(struct amdgpu_device *adev,
|
||||
|
||||
tmp = RREG32(ih_regs->ih_rb_cntl);
|
||||
tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, RB_ENABLE, (enable ? 1 : 0));
|
||||
|
||||
if (enable) {
|
||||
/* Unset the CLEAR_OVERFLOW bit to make sure the next step
|
||||
* is switching the bit from 0 to 1
|
||||
*/
|
||||
tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0);
|
||||
if (amdgpu_sriov_vf(adev) && amdgpu_sriov_reg_indirect_ih(adev)) {
|
||||
if (psp_reg_program(&adev->psp, ih_regs->psp_reg_id, tmp))
|
||||
return -ETIMEDOUT;
|
||||
} else {
|
||||
WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp);
|
||||
}
|
||||
|
||||
/* Clear RB_OVERFLOW bit */
|
||||
tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
|
||||
if (amdgpu_sriov_vf(adev) && amdgpu_sriov_reg_indirect_ih(adev)) {
|
||||
if (psp_reg_program(&adev->psp, ih_regs->psp_reg_id, tmp))
|
||||
return -ETIMEDOUT;
|
||||
} else {
|
||||
WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp);
|
||||
}
|
||||
|
||||
/* Unset the CLEAR_OVERFLOW bit immediately so new overflows
|
||||
* can be detected.
|
||||
*/
|
||||
tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0);
|
||||
}
|
||||
|
||||
/* enable_intr field is only valid in ring0 */
|
||||
if (ih == &adev->irq.ih)
|
||||
tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, ENABLE_INTR, (enable ? 1 : 0));
|
||||
|
||||
@@ -535,6 +535,12 @@ static void ih_v6_1_set_self_irq_funcs(struct amdgpu_device *adev)
|
||||
static int ih_v6_1_early_init(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
int ret;
|
||||
|
||||
ret = amdgpu_irq_add_domain(adev);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ih_v6_1_set_interrupt_funcs(adev);
|
||||
ih_v6_1_set_self_irq_funcs(adev);
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "amdgpu.h"
|
||||
#include "isp_v4_1_0.h"
|
||||
|
||||
static const unsigned int isp_4_1_0_int_srcid[MAX_ISP410_INT_SRC] = {
|
||||
ISP_4_1__SRCID__ISP_RINGBUFFER_WPT9,
|
||||
ISP_4_1__SRCID__ISP_RINGBUFFER_WPT10,
|
||||
ISP_4_1__SRCID__ISP_RINGBUFFER_WPT11,
|
||||
ISP_4_1__SRCID__ISP_RINGBUFFER_WPT12,
|
||||
ISP_4_1__SRCID__ISP_RINGBUFFER_WPT13,
|
||||
ISP_4_1__SRCID__ISP_RINGBUFFER_WPT14,
|
||||
ISP_4_1__SRCID__ISP_RINGBUFFER_WPT15,
|
||||
ISP_4_1__SRCID__ISP_RINGBUFFER_WPT16
|
||||
};
|
||||
|
||||
static int isp_v4_1_0_hw_init(struct amdgpu_isp *isp)
|
||||
{
|
||||
struct amdgpu_device *adev = isp->adev;
|
||||
u64 isp_base;
|
||||
int int_idx;
|
||||
int r;
|
||||
|
||||
if (adev->rmmio_size == 0 || adev->rmmio_size < 0x5289)
|
||||
return -EINVAL;
|
||||
|
||||
isp_base = adev->rmmio_base;
|
||||
|
||||
isp->isp_cell = kcalloc(1, sizeof(struct mfd_cell), GFP_KERNEL);
|
||||
if (!isp->isp_cell) {
|
||||
r = -ENOMEM;
|
||||
DRM_ERROR("%s: isp mfd cell alloc failed\n", __func__);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
isp->isp_res = kcalloc(MAX_ISP410_INT_SRC + 1, sizeof(struct resource),
|
||||
GFP_KERNEL);
|
||||
if (!isp->isp_res) {
|
||||
r = -ENOMEM;
|
||||
DRM_ERROR("%s: isp mfd res alloc failed\n", __func__);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
isp->isp_pdata = kzalloc(sizeof(*isp->isp_pdata), GFP_KERNEL);
|
||||
if (!isp->isp_pdata) {
|
||||
r = -ENOMEM;
|
||||
DRM_ERROR("%s: isp platform data alloc failed\n", __func__);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* initialize isp platform data */
|
||||
isp->isp_pdata->adev = (void *)adev;
|
||||
isp->isp_pdata->asic_type = adev->asic_type;
|
||||
isp->isp_pdata->base_rmmio_size = adev->rmmio_size;
|
||||
|
||||
isp->isp_res[0].name = "isp_4_1_0_reg";
|
||||
isp->isp_res[0].flags = IORESOURCE_MEM;
|
||||
isp->isp_res[0].start = isp_base;
|
||||
isp->isp_res[0].end = isp_base + ISP_REGS_OFFSET_END;
|
||||
|
||||
for (int_idx = 0; int_idx < MAX_ISP410_INT_SRC; int_idx++) {
|
||||
isp->isp_res[int_idx + 1].name = "isp_4_1_0_irq";
|
||||
isp->isp_res[int_idx + 1].flags = IORESOURCE_IRQ;
|
||||
isp->isp_res[int_idx + 1].start =
|
||||
amdgpu_irq_create_mapping(adev, isp_4_1_0_int_srcid[int_idx]);
|
||||
isp->isp_res[int_idx + 1].end =
|
||||
isp->isp_res[int_idx + 1].start;
|
||||
}
|
||||
|
||||
isp->isp_cell[0].name = "amd_isp_capture";
|
||||
isp->isp_cell[0].num_resources = MAX_ISP410_INT_SRC + 1;
|
||||
isp->isp_cell[0].resources = &isp->isp_res[0];
|
||||
isp->isp_cell[0].platform_data = isp->isp_pdata;
|
||||
isp->isp_cell[0].pdata_size = sizeof(struct isp_platform_data);
|
||||
|
||||
r = mfd_add_hotplug_devices(isp->parent, isp->isp_cell, 1);
|
||||
if (r) {
|
||||
DRM_ERROR("%s: add mfd hotplug device failed\n", __func__);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
failure:
|
||||
|
||||
kfree(isp->isp_pdata);
|
||||
kfree(isp->isp_res);
|
||||
kfree(isp->isp_cell);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int isp_v4_1_0_hw_fini(struct amdgpu_isp *isp)
|
||||
{
|
||||
mfd_remove_devices(isp->parent);
|
||||
|
||||
kfree(isp->isp_res);
|
||||
kfree(isp->isp_cell);
|
||||
kfree(isp->isp_pdata);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct isp_funcs isp_v4_1_0_funcs = {
|
||||
.hw_init = isp_v4_1_0_hw_init,
|
||||
.hw_fini = isp_v4_1_0_hw_fini,
|
||||
};
|
||||
|
||||
void isp_v4_1_0_set_isp_funcs(struct amdgpu_isp *isp)
|
||||
{
|
||||
isp->funcs = &isp_v4_1_0_funcs;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ISP_V4_1_0_H__
|
||||
#define __ISP_V4_1_0_H__
|
||||
|
||||
#include "amdgpu_isp.h"
|
||||
|
||||
#include "ivsrcid/isp/irqsrcs_isp_4_1.h"
|
||||
|
||||
#define MAX_ISP410_INT_SRC 8
|
||||
|
||||
void isp_v4_1_0_set_isp_funcs(struct amdgpu_isp *isp);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,137 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "amdgpu.h"
|
||||
#include "isp_v4_1_1.h"
|
||||
|
||||
static const unsigned int isp_4_1_1_int_srcid[MAX_ISP411_INT_SRC] = {
|
||||
ISP_4_1__SRCID__ISP_RINGBUFFER_WPT9,
|
||||
ISP_4_1__SRCID__ISP_RINGBUFFER_WPT10,
|
||||
ISP_4_1__SRCID__ISP_RINGBUFFER_WPT11,
|
||||
ISP_4_1__SRCID__ISP_RINGBUFFER_WPT12,
|
||||
ISP_4_1__SRCID__ISP_RINGBUFFER_WPT13,
|
||||
ISP_4_1__SRCID__ISP_RINGBUFFER_WPT14,
|
||||
ISP_4_1__SRCID__ISP_RINGBUFFER_WPT15,
|
||||
ISP_4_1__SRCID__ISP_RINGBUFFER_WPT16
|
||||
};
|
||||
|
||||
static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp)
|
||||
{
|
||||
struct amdgpu_device *adev = isp->adev;
|
||||
u64 isp_base;
|
||||
int int_idx;
|
||||
int r;
|
||||
|
||||
if (adev->rmmio_size == 0 || adev->rmmio_size < 0x5289)
|
||||
return -EINVAL;
|
||||
|
||||
isp_base = adev->rmmio_base;
|
||||
|
||||
isp->isp_cell = kcalloc(1, sizeof(struct mfd_cell), GFP_KERNEL);
|
||||
if (!isp->isp_cell) {
|
||||
r = -ENOMEM;
|
||||
DRM_ERROR("%s: isp mfd cell alloc failed\n", __func__);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
isp->isp_res = kcalloc(MAX_ISP411_INT_SRC + 1, sizeof(struct resource),
|
||||
GFP_KERNEL);
|
||||
if (!isp->isp_res) {
|
||||
r = -ENOMEM;
|
||||
DRM_ERROR("%s: isp mfd res alloc failed\n", __func__);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
isp->isp_pdata = kzalloc(sizeof(*isp->isp_pdata), GFP_KERNEL);
|
||||
if (!isp->isp_pdata) {
|
||||
r = -ENOMEM;
|
||||
DRM_ERROR("%s: isp platform data alloc failed\n", __func__);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* initialize isp platform data */
|
||||
isp->isp_pdata->adev = (void *)adev;
|
||||
isp->isp_pdata->asic_type = adev->asic_type;
|
||||
isp->isp_pdata->base_rmmio_size = adev->rmmio_size;
|
||||
|
||||
isp->isp_res[0].name = "isp_4_1_1_reg";
|
||||
isp->isp_res[0].flags = IORESOURCE_MEM;
|
||||
isp->isp_res[0].start = isp_base;
|
||||
isp->isp_res[0].end = isp_base + ISP_REGS_OFFSET_END;
|
||||
|
||||
for (int_idx = 0; int_idx < MAX_ISP411_INT_SRC; int_idx++) {
|
||||
isp->isp_res[int_idx + 1].name = "isp_4_1_1_irq";
|
||||
isp->isp_res[int_idx + 1].flags = IORESOURCE_IRQ;
|
||||
isp->isp_res[int_idx + 1].start =
|
||||
amdgpu_irq_create_mapping(adev, isp_4_1_1_int_srcid[int_idx]);
|
||||
isp->isp_res[int_idx + 1].end =
|
||||
isp->isp_res[int_idx + 1].start;
|
||||
}
|
||||
|
||||
isp->isp_cell[0].name = "amd_isp_capture";
|
||||
isp->isp_cell[0].num_resources = MAX_ISP411_INT_SRC + 1;
|
||||
isp->isp_cell[0].resources = &isp->isp_res[0];
|
||||
isp->isp_cell[0].platform_data = isp->isp_pdata;
|
||||
isp->isp_cell[0].pdata_size = sizeof(struct isp_platform_data);
|
||||
|
||||
r = mfd_add_hotplug_devices(isp->parent, isp->isp_cell, 1);
|
||||
if (r) {
|
||||
DRM_ERROR("%s: add mfd hotplug device failed\n", __func__);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
failure:
|
||||
|
||||
kfree(isp->isp_pdata);
|
||||
kfree(isp->isp_res);
|
||||
kfree(isp->isp_cell);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int isp_v4_1_1_hw_fini(struct amdgpu_isp *isp)
|
||||
{
|
||||
mfd_remove_devices(isp->parent);
|
||||
|
||||
kfree(isp->isp_res);
|
||||
kfree(isp->isp_cell);
|
||||
kfree(isp->isp_pdata);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct isp_funcs isp_v4_1_1_funcs = {
|
||||
.hw_init = isp_v4_1_1_hw_init,
|
||||
.hw_fini = isp_v4_1_1_hw_fini,
|
||||
};
|
||||
|
||||
void isp_v4_1_1_set_isp_funcs(struct amdgpu_isp *isp)
|
||||
{
|
||||
isp->funcs = &isp_v4_1_1_funcs;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ISP_V4_1_1_H__
|
||||
#define __ISP_V4_1_1_H__
|
||||
|
||||
#include "amdgpu_isp.h"
|
||||
|
||||
#include "ivsrcid/isp/irqsrcs_isp_4_1.h"
|
||||
|
||||
#define MAX_ISP411_INT_SRC 8
|
||||
|
||||
void isp_v4_1_1_set_isp_funcs(struct amdgpu_isp *isp);
|
||||
|
||||
#endif
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "vcn/vcn_5_0_0_offset.h"
|
||||
#include "vcn/vcn_5_0_0_sh_mask.h"
|
||||
#include "ivsrcid/vcn/irqsrcs_vcn_4_0.h"
|
||||
#include "jpeg_v5_0_0.h"
|
||||
|
||||
static void jpeg_v5_0_0_set_dec_ring_funcs(struct amdgpu_device *adev);
|
||||
static void jpeg_v5_0_0_set_irq_funcs(struct amdgpu_device *adev);
|
||||
@@ -137,9 +138,9 @@ static int jpeg_v5_0_0_hw_init(void *handle)
|
||||
adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,
|
||||
(adev->doorbell_index.vcn.vcn_ring0_1 << 1), 0);
|
||||
|
||||
WREG32_SOC15(VCN, 0, regVCN_JPEG_DB_CTRL,
|
||||
ring->doorbell_index << VCN_JPEG_DB_CTRL__OFFSET__SHIFT |
|
||||
VCN_JPEG_DB_CTRL__EN_MASK);
|
||||
/* Skip ring test because pause DPG is not implemented. */
|
||||
if (adev->pg_flags & AMD_PG_SUPPORT_JPEG_DPG)
|
||||
return 0;
|
||||
|
||||
r = amdgpu_ring_test_helper(ring);
|
||||
if (r)
|
||||
@@ -239,7 +240,7 @@ static void jpeg_v5_0_0_enable_clock_gating(struct amdgpu_device *adev)
|
||||
WREG32_SOC15(JPEG, 0, regJPEG_CGC_GATE, data);
|
||||
}
|
||||
|
||||
static int jpeg_v5_0_0_disable_static_power_gating(struct amdgpu_device *adev)
|
||||
static int jpeg_v5_0_0_disable_power_gating(struct amdgpu_device *adev)
|
||||
{
|
||||
uint32_t data = 0;
|
||||
|
||||
@@ -252,14 +253,10 @@ static int jpeg_v5_0_0_disable_static_power_gating(struct amdgpu_device *adev)
|
||||
WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JPEG_POWER_STATUS), 0,
|
||||
~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);
|
||||
|
||||
/* keep the JPEG in static PG mode */
|
||||
WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JPEG_POWER_STATUS), 0,
|
||||
~UVD_JPEG_POWER_STATUS__JPEG_PG_MODE_MASK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jpeg_v5_0_0_enable_static_power_gating(struct amdgpu_device *adev)
|
||||
static int jpeg_v5_0_0_enable_power_gating(struct amdgpu_device *adev)
|
||||
{
|
||||
/* enable anti hang mechanism */
|
||||
WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JPEG_POWER_STATUS),
|
||||
@@ -277,6 +274,121 @@ static int jpeg_v5_0_0_enable_static_power_gating(struct amdgpu_device *adev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void jpeg_engine_5_0_0_dpg_clock_gating_mode(struct amdgpu_device *adev,
|
||||
int inst_idx, uint8_t indirect)
|
||||
{
|
||||
uint32_t data = 0;
|
||||
|
||||
// JPEG disable CGC
|
||||
if (adev->cg_flags & AMD_CG_SUPPORT_JPEG_MGCG)
|
||||
data = 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
|
||||
else
|
||||
data = 0 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
|
||||
|
||||
data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
|
||||
data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
|
||||
|
||||
if (indirect) {
|
||||
ADD_SOC24_JPEG_TO_DPG_SRAM(inst_idx, vcnipJPEG_CGC_CTRL, data, indirect);
|
||||
|
||||
// Turn on All JPEG clocks
|
||||
data = 0;
|
||||
ADD_SOC24_JPEG_TO_DPG_SRAM(inst_idx, vcnipJPEG_CGC_GATE, data, indirect);
|
||||
} else {
|
||||
WREG32_SOC24_JPEG_DPG_MODE(inst_idx, vcnipJPEG_CGC_CTRL, data, indirect);
|
||||
|
||||
// Turn on All JPEG clocks
|
||||
data = 0;
|
||||
WREG32_SOC24_JPEG_DPG_MODE(inst_idx, vcnipJPEG_CGC_GATE, data, indirect);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v5_0_0_start_dpg_mode - Jpeg start with dpg mode
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @inst_idx: instance number index
|
||||
* @indirect: indirectly write sram
|
||||
*
|
||||
* Start JPEG block with dpg mode
|
||||
*/
|
||||
static int jpeg_v5_0_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
|
||||
{
|
||||
struct amdgpu_ring *ring = adev->jpeg.inst[inst_idx].ring_dec;
|
||||
uint32_t reg_data = 0;
|
||||
|
||||
jpeg_v5_0_0_enable_power_gating(adev);
|
||||
|
||||
// enable dynamic power gating mode
|
||||
reg_data = RREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS);
|
||||
reg_data |= UVD_JPEG_POWER_STATUS__JPEG_PG_MODE_MASK;
|
||||
WREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS, reg_data);
|
||||
|
||||
if (indirect)
|
||||
adev->jpeg.inst[inst_idx].dpg_sram_curr_addr =
|
||||
(uint32_t *)adev->jpeg.inst[inst_idx].dpg_sram_cpu_addr;
|
||||
|
||||
jpeg_engine_5_0_0_dpg_clock_gating_mode(adev, inst_idx, indirect);
|
||||
|
||||
/* MJPEG global tiling registers */
|
||||
if (indirect)
|
||||
ADD_SOC24_JPEG_TO_DPG_SRAM(inst_idx, vcnipJPEG_DEC_GFX10_ADDR_CONFIG,
|
||||
adev->gfx.config.gb_addr_config, indirect);
|
||||
else
|
||||
WREG32_SOC24_JPEG_DPG_MODE(inst_idx, vcnipJPEG_DEC_GFX10_ADDR_CONFIG,
|
||||
adev->gfx.config.gb_addr_config, 1);
|
||||
|
||||
/* enable System Interrupt for JRBC */
|
||||
if (indirect)
|
||||
ADD_SOC24_JPEG_TO_DPG_SRAM(inst_idx, vcnipJPEG_SYS_INT_EN,
|
||||
JPEG_SYS_INT_EN__DJRBC0_MASK, indirect);
|
||||
else
|
||||
WREG32_SOC24_JPEG_DPG_MODE(inst_idx, vcnipJPEG_SYS_INT_EN,
|
||||
JPEG_SYS_INT_EN__DJRBC0_MASK, 1);
|
||||
|
||||
if (indirect) {
|
||||
/* add nop to workaround PSP size check */
|
||||
ADD_SOC24_JPEG_TO_DPG_SRAM(inst_idx, vcnipUVD_NO_OP, 0, indirect);
|
||||
|
||||
amdgpu_jpeg_psp_update_sram(adev, inst_idx, 0);
|
||||
}
|
||||
|
||||
WREG32_SOC15(VCN, 0, regVCN_JPEG_DB_CTRL,
|
||||
ring->doorbell_index << VCN_JPEG_DB_CTRL__OFFSET__SHIFT |
|
||||
VCN_JPEG_DB_CTRL__EN_MASK);
|
||||
|
||||
WREG32_SOC15(JPEG, inst_idx, regUVD_LMI_JRBC_RB_VMID, 0);
|
||||
WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_CNTL, (0x00000001L | 0x00000002L));
|
||||
WREG32_SOC15(JPEG, inst_idx, regUVD_LMI_JRBC_RB_64BIT_BAR_LOW,
|
||||
lower_32_bits(ring->gpu_addr));
|
||||
WREG32_SOC15(JPEG, inst_idx, regUVD_LMI_JRBC_RB_64BIT_BAR_HIGH,
|
||||
upper_32_bits(ring->gpu_addr));
|
||||
WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_RPTR, 0);
|
||||
WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_WPTR, 0);
|
||||
WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_CNTL, 0x00000002L);
|
||||
WREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_SIZE, ring->ring_size / 4);
|
||||
ring->wptr = RREG32_SOC15(JPEG, inst_idx, regUVD_JRBC_RB_WPTR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v5_0_0_stop_dpg_mode - Jpeg stop with dpg mode
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @inst_idx: instance number index
|
||||
*
|
||||
* Stop JPEG block with dpg mode
|
||||
*/
|
||||
static void jpeg_v5_0_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
|
||||
{
|
||||
uint32_t reg_data = 0;
|
||||
|
||||
reg_data = RREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS);
|
||||
reg_data &= ~UVD_JPEG_POWER_STATUS__JPEG_PG_MODE_MASK;
|
||||
WREG32_SOC15(JPEG, inst_idx, regUVD_JPEG_POWER_STATUS, reg_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v5_0_0_start - start JPEG block
|
||||
*
|
||||
@@ -292,8 +404,13 @@ static int jpeg_v5_0_0_start(struct amdgpu_device *adev)
|
||||
if (adev->pm.dpm_enabled)
|
||||
amdgpu_dpm_enable_jpeg(adev, true);
|
||||
|
||||
if (adev->pg_flags & AMD_PG_SUPPORT_JPEG_DPG) {
|
||||
r = jpeg_v5_0_0_start_dpg_mode(adev, 0, adev->jpeg.indirect_sram);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* disable power gating */
|
||||
r = jpeg_v5_0_0_disable_static_power_gating(adev);
|
||||
r = jpeg_v5_0_0_disable_power_gating(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
@@ -304,7 +421,6 @@ static int jpeg_v5_0_0_start(struct amdgpu_device *adev)
|
||||
WREG32_SOC15(JPEG, 0, regJPEG_DEC_GFX10_ADDR_CONFIG,
|
||||
adev->gfx.config.gb_addr_config);
|
||||
|
||||
|
||||
/* enable JMI channel */
|
||||
WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JMI_CNTL), 0,
|
||||
~UVD_JMI_CNTL__SOFT_RESET_MASK);
|
||||
@@ -314,6 +430,10 @@ static int jpeg_v5_0_0_start(struct amdgpu_device *adev)
|
||||
JPEG_SYS_INT_EN__DJRBC0_MASK,
|
||||
~JPEG_SYS_INT_EN__DJRBC0_MASK);
|
||||
|
||||
WREG32_SOC15(VCN, 0, regVCN_JPEG_DB_CTRL,
|
||||
ring->doorbell_index << VCN_JPEG_DB_CTRL__OFFSET__SHIFT |
|
||||
VCN_JPEG_DB_CTRL__EN_MASK);
|
||||
|
||||
WREG32_SOC15(JPEG, 0, regUVD_LMI_JRBC_RB_VMID, 0);
|
||||
WREG32_SOC15(JPEG, 0, regUVD_JRBC_RB_CNTL, (0x00000001L | 0x00000002L));
|
||||
WREG32_SOC15(JPEG, 0, regUVD_LMI_JRBC_RB_64BIT_BAR_LOW,
|
||||
@@ -340,17 +460,22 @@ static int jpeg_v5_0_0_stop(struct amdgpu_device *adev)
|
||||
{
|
||||
int r;
|
||||
|
||||
/* reset JMI */
|
||||
WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JMI_CNTL),
|
||||
UVD_JMI_CNTL__SOFT_RESET_MASK,
|
||||
~UVD_JMI_CNTL__SOFT_RESET_MASK);
|
||||
if (adev->pg_flags & AMD_PG_SUPPORT_JPEG_DPG) {
|
||||
jpeg_v5_0_0_stop_dpg_mode(adev, 0);
|
||||
} else {
|
||||
|
||||
jpeg_v5_0_0_enable_clock_gating(adev);
|
||||
/* reset JMI */
|
||||
WREG32_P(SOC15_REG_OFFSET(JPEG, 0, regUVD_JMI_CNTL),
|
||||
UVD_JMI_CNTL__SOFT_RESET_MASK,
|
||||
~UVD_JMI_CNTL__SOFT_RESET_MASK);
|
||||
|
||||
/* enable power gating */
|
||||
r = jpeg_v5_0_0_enable_static_power_gating(adev);
|
||||
if (r)
|
||||
return r;
|
||||
jpeg_v5_0_0_enable_clock_gating(adev);
|
||||
|
||||
/* enable power gating */
|
||||
r = jpeg_v5_0_0_enable_power_gating(adev);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (adev->pm.dpm_enabled)
|
||||
amdgpu_dpm_enable_jpeg(adev, false);
|
||||
|
||||
@@ -24,6 +24,12 @@
|
||||
#ifndef __JPEG_V5_0_0_H__
|
||||
#define __JPEG_V5_0_0_H__
|
||||
|
||||
#define vcnipJPEG_CGC_GATE 0x4160
|
||||
#define vcnipJPEG_CGC_CTRL 0x4161
|
||||
#define vcnipJPEG_SYS_INT_EN 0x4141
|
||||
#define vcnipUVD_NO_OP 0x0029
|
||||
#define vcnipJPEG_DEC_GFX10_ADDR_CONFIG 0x404A
|
||||
|
||||
extern const struct amdgpu_ip_block_version jpeg_v5_0_0_ip_block;
|
||||
|
||||
#endif /* __JPEG_V5_0_0_H__ */
|
||||
|
||||
@@ -566,9 +566,11 @@ static bool mmhub_v1_8_query_utcl2_poison_status(struct amdgpu_device *adev,
|
||||
|
||||
status = RREG32_SOC15(MMHUB, hub_inst, regVM_L2_PROTECTION_FAULT_STATUS);
|
||||
fed = REG_GET_FIELD(status, VM_L2_PROTECTION_FAULT_STATUS, FED);
|
||||
/* reset page fault status */
|
||||
WREG32_P(SOC15_REG_OFFSET(MMHUB, hub_inst,
|
||||
regVM_L2_PROTECTION_FAULT_STATUS), 1, ~1);
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
/* clear page fault status and address */
|
||||
WREG32_P(SOC15_REG_OFFSET(MMHUB, hub_inst,
|
||||
regVM_L2_PROTECTION_FAULT_STATUS), 1, ~1);
|
||||
}
|
||||
|
||||
return fed;
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ static int xgpu_ai_poll_ack(struct amdgpu_device *adev)
|
||||
timeout -= 5;
|
||||
} while (timeout > 1);
|
||||
|
||||
pr_err("Doesn't get TRN_MSG_ACK from pf in %d msec\n", AI_MAILBOX_POLL_ACK_TIMEDOUT);
|
||||
dev_err(adev->dev, "Doesn't get TRN_MSG_ACK from pf in %d msec\n", AI_MAILBOX_POLL_ACK_TIMEDOUT);
|
||||
|
||||
return -ETIME;
|
||||
}
|
||||
@@ -111,7 +111,7 @@ static int xgpu_ai_poll_msg(struct amdgpu_device *adev, enum idh_event event)
|
||||
timeout -= 10;
|
||||
} while (timeout > 1);
|
||||
|
||||
pr_err("Doesn't get msg:%d from pf, error=%d\n", event, r);
|
||||
dev_err(adev->dev, "Doesn't get msg:%d from pf, error=%d\n", event, r);
|
||||
|
||||
return -ETIME;
|
||||
}
|
||||
@@ -132,7 +132,7 @@ static void xgpu_ai_mailbox_trans_msg (struct amdgpu_device *adev,
|
||||
xgpu_ai_mailbox_set_valid(adev, false);
|
||||
trn = xgpu_ai_peek_ack(adev);
|
||||
if (trn) {
|
||||
pr_err("trn=%x ACK should not assert! wait again !\n", trn);
|
||||
dev_err_ratelimited(adev->dev, "trn=%x ACK should not assert! wait again !\n", trn);
|
||||
msleep(1);
|
||||
}
|
||||
} while(trn);
|
||||
@@ -155,7 +155,7 @@ static void xgpu_ai_mailbox_trans_msg (struct amdgpu_device *adev,
|
||||
/* start to poll ack */
|
||||
r = xgpu_ai_poll_ack(adev);
|
||||
if (r)
|
||||
pr_err("Doesn't get ack from pf, continue\n");
|
||||
dev_err(adev->dev, "Doesn't get ack from pf, continue\n");
|
||||
|
||||
xgpu_ai_mailbox_set_valid(adev, false);
|
||||
}
|
||||
@@ -173,7 +173,7 @@ static int xgpu_ai_send_access_requests(struct amdgpu_device *adev,
|
||||
req == IDH_REQ_GPU_RESET_ACCESS) {
|
||||
r = xgpu_ai_poll_msg(adev, IDH_READY_TO_ACCESS_GPU);
|
||||
if (r) {
|
||||
pr_err("Doesn't get READY_TO_ACCESS_GPU from pf, give up\n");
|
||||
dev_err(adev->dev, "Doesn't get READY_TO_ACCESS_GPU from pf, give up\n");
|
||||
return r;
|
||||
}
|
||||
/* Retrieve checksum from mailbox2 */
|
||||
@@ -231,7 +231,7 @@ static int xgpu_ai_mailbox_ack_irq(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
{
|
||||
DRM_DEBUG("get ack intr and do nothing.\n");
|
||||
dev_dbg(adev->dev, "get ack intr and do nothing.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -258,12 +258,15 @@ static int xgpu_ai_wait_reset(struct amdgpu_device *adev)
|
||||
{
|
||||
int timeout = AI_MAILBOX_POLL_FLR_TIMEDOUT;
|
||||
do {
|
||||
if (xgpu_ai_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL)
|
||||
if (xgpu_ai_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL) {
|
||||
dev_dbg(adev->dev, "Got AI IDH_FLR_NOTIFICATION_CMPL after %d ms\n", AI_MAILBOX_POLL_FLR_TIMEDOUT - timeout);
|
||||
return 0;
|
||||
}
|
||||
msleep(10);
|
||||
timeout -= 10;
|
||||
} while (timeout > 1);
|
||||
dev_warn(adev->dev, "waiting IDH_FLR_NOTIFICATION_CMPL timeout\n");
|
||||
|
||||
dev_dbg(adev->dev, "waiting AI IDH_FLR_NOTIFICATION_CMPL timeout\n");
|
||||
return -ETIME;
|
||||
}
|
||||
|
||||
@@ -405,6 +408,13 @@ static void xgpu_ai_ras_poison_handler(struct amdgpu_device *adev,
|
||||
xgpu_ai_send_access_requests(adev, IDH_RAS_POISON);
|
||||
}
|
||||
|
||||
static bool xgpu_ai_rcvd_ras_intr(struct amdgpu_device *adev)
|
||||
{
|
||||
enum idh_event msg = xgpu_ai_mailbox_peek_msg(adev);
|
||||
|
||||
return (msg == IDH_RAS_ERROR_DETECTED || msg == 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
const struct amdgpu_virt_ops xgpu_ai_virt_ops = {
|
||||
.req_full_gpu = xgpu_ai_request_full_gpu_access,
|
||||
.rel_full_gpu = xgpu_ai_release_full_gpu_access,
|
||||
@@ -414,4 +424,5 @@ const struct amdgpu_virt_ops xgpu_ai_virt_ops = {
|
||||
.trans_msg = xgpu_ai_mailbox_trans_msg,
|
||||
.req_init_data = xgpu_ai_request_init_data,
|
||||
.ras_poison_handler = xgpu_ai_ras_poison_handler,
|
||||
.rcvd_ras_intr = xgpu_ai_rcvd_ras_intr,
|
||||
};
|
||||
|
||||
@@ -51,7 +51,9 @@ enum idh_event {
|
||||
IDH_FAIL,
|
||||
IDH_QUERY_ALIVE,
|
||||
IDH_REQ_GPU_INIT_DATA_READY,
|
||||
|
||||
IDH_RAS_POISON_READY,
|
||||
IDH_PF_SOFT_FLR_NOTIFICATION,
|
||||
IDH_RAS_ERROR_DETECTED,
|
||||
IDH_TEXT_MESSAGE = 255,
|
||||
};
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ static int xgpu_nv_poll_ack(struct amdgpu_device *adev)
|
||||
timeout -= 5;
|
||||
} while (timeout > 1);
|
||||
|
||||
pr_err("Doesn't get TRN_MSG_ACK from pf in %d msec\n", NV_MAILBOX_POLL_ACK_TIMEDOUT);
|
||||
dev_err(adev->dev, "Doesn't get TRN_MSG_ACK from pf in %d msec \n", NV_MAILBOX_POLL_ACK_TIMEDOUT);
|
||||
|
||||
return -ETIME;
|
||||
}
|
||||
@@ -106,13 +106,16 @@ static int xgpu_nv_poll_msg(struct amdgpu_device *adev, enum idh_event event)
|
||||
|
||||
do {
|
||||
r = xgpu_nv_mailbox_rcv_msg(adev, event);
|
||||
if (!r)
|
||||
if (!r) {
|
||||
dev_dbg(adev->dev, "rcv_msg 0x%x after %llu ms\n", event, NV_MAILBOX_POLL_MSG_TIMEDOUT - timeout + now);
|
||||
return 0;
|
||||
}
|
||||
|
||||
msleep(10);
|
||||
now = (uint64_t)ktime_to_ms(ktime_get());
|
||||
} while (timeout > now);
|
||||
|
||||
dev_dbg(adev->dev, "nv_poll_msg timed out\n");
|
||||
|
||||
return -ETIME;
|
||||
}
|
||||
@@ -133,11 +136,12 @@ static void xgpu_nv_mailbox_trans_msg (struct amdgpu_device *adev,
|
||||
xgpu_nv_mailbox_set_valid(adev, false);
|
||||
trn = xgpu_nv_peek_ack(adev);
|
||||
if (trn) {
|
||||
pr_err("trn=%x ACK should not assert! wait again !\n", trn);
|
||||
dev_err_ratelimited(adev->dev, "trn=%x ACK should not assert! wait again !\n", trn);
|
||||
msleep(1);
|
||||
}
|
||||
} while (trn);
|
||||
|
||||
dev_dbg(adev->dev, "trans_msg req = 0x%x, data1 = 0x%x\n", req, data1);
|
||||
WREG32_NO_KIQ(mmMAILBOX_MSGBUF_TRN_DW0, req);
|
||||
WREG32_NO_KIQ(mmMAILBOX_MSGBUF_TRN_DW1, data1);
|
||||
WREG32_NO_KIQ(mmMAILBOX_MSGBUF_TRN_DW2, data2);
|
||||
@@ -147,7 +151,7 @@ static void xgpu_nv_mailbox_trans_msg (struct amdgpu_device *adev,
|
||||
/* start to poll ack */
|
||||
r = xgpu_nv_poll_ack(adev);
|
||||
if (r)
|
||||
pr_err("Doesn't get ack from pf, continue\n");
|
||||
dev_err(adev->dev, "Doesn't get ack from pf, continue\n");
|
||||
|
||||
xgpu_nv_mailbox_set_valid(adev, false);
|
||||
}
|
||||
@@ -185,7 +189,7 @@ send_request:
|
||||
goto send_request;
|
||||
|
||||
if (req != IDH_REQ_GPU_INIT_DATA) {
|
||||
pr_err("Doesn't get msg:%d from pf, error=%d\n", event, r);
|
||||
dev_err(adev->dev, "Doesn't get msg:%d from pf, error=%d\n", event, r);
|
||||
return r;
|
||||
} else /* host doesn't support REQ_GPU_INIT_DATA handshake */
|
||||
adev->virt.req_init_data_ver = 0;
|
||||
@@ -261,7 +265,7 @@ static int xgpu_nv_mailbox_ack_irq(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
{
|
||||
DRM_DEBUG("get ack intr and do nothing.\n");
|
||||
dev_dbg(adev->dev, "get ack intr and do nothing.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -291,12 +295,15 @@ static int xgpu_nv_wait_reset(struct amdgpu_device *adev)
|
||||
{
|
||||
int timeout = NV_MAILBOX_POLL_FLR_TIMEDOUT;
|
||||
do {
|
||||
if (xgpu_nv_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL)
|
||||
if (xgpu_nv_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL) {
|
||||
dev_dbg(adev->dev, "Got NV IDH_FLR_NOTIFICATION_CMPL after %d ms\n", NV_MAILBOX_POLL_FLR_TIMEDOUT - timeout);
|
||||
return 0;
|
||||
}
|
||||
msleep(10);
|
||||
timeout -= 10;
|
||||
} while (timeout > 1);
|
||||
dev_warn(adev->dev, "waiting IDH_FLR_NOTIFICATION_CMPL timeout\n");
|
||||
|
||||
dev_dbg(adev->dev, "waiting NV IDH_FLR_NOTIFICATION_CMPL timeout\n");
|
||||
return -ETIME;
|
||||
}
|
||||
|
||||
@@ -442,6 +449,13 @@ static void xgpu_nv_ras_poison_handler(struct amdgpu_device *adev,
|
||||
}
|
||||
}
|
||||
|
||||
static bool xgpu_nv_rcvd_ras_intr(struct amdgpu_device *adev)
|
||||
{
|
||||
enum idh_event msg = xgpu_nv_mailbox_peek_msg(adev);
|
||||
|
||||
return (msg == IDH_RAS_ERROR_DETECTED || msg == 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
const struct amdgpu_virt_ops xgpu_nv_virt_ops = {
|
||||
.req_full_gpu = xgpu_nv_request_full_gpu_access,
|
||||
.rel_full_gpu = xgpu_nv_release_full_gpu_access,
|
||||
@@ -451,4 +465,5 @@ const struct amdgpu_virt_ops xgpu_nv_virt_ops = {
|
||||
.wait_reset = xgpu_nv_wait_reset,
|
||||
.trans_msg = xgpu_nv_mailbox_trans_msg,
|
||||
.ras_poison_handler = xgpu_nv_ras_poison_handler,
|
||||
.rcvd_ras_intr = xgpu_nv_rcvd_ras_intr,
|
||||
};
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
#define NV_MAILBOX_POLL_ACK_TIMEDOUT 500
|
||||
#define NV_MAILBOX_POLL_MSG_TIMEDOUT 6000
|
||||
#define NV_MAILBOX_POLL_FLR_TIMEDOUT 5000
|
||||
#define NV_MAILBOX_POLL_FLR_TIMEDOUT 10000
|
||||
#define NV_MAILBOX_POLL_MSG_REP_MAX 11
|
||||
|
||||
enum idh_request {
|
||||
@@ -52,7 +52,8 @@ enum idh_event {
|
||||
IDH_QUERY_ALIVE,
|
||||
IDH_REQ_GPU_INIT_DATA_READY,
|
||||
IDH_RAS_POISON_READY,
|
||||
|
||||
IDH_PF_SOFT_FLR_NOTIFICATION,
|
||||
IDH_RAS_ERROR_DETECTED,
|
||||
IDH_TEXT_MESSAGE = 255,
|
||||
};
|
||||
|
||||
|
||||
@@ -345,6 +345,7 @@ static void nbif_v6_3_1_program_aspm(struct amdgpu_device *adev)
|
||||
{
|
||||
#ifdef CONFIG_PCIEASPM
|
||||
uint32_t def, data;
|
||||
u16 devctl2, ltr;
|
||||
|
||||
def = data = RREG32_SOC15(PCIE, 0, regPCIE_LC_CNTL);
|
||||
data &= ~PCIE_LC_CNTL__LC_L1_INACTIVITY_MASK;
|
||||
@@ -374,12 +375,17 @@ static void nbif_v6_3_1_program_aspm(struct amdgpu_device *adev)
|
||||
if (def != data)
|
||||
WREG32_SOC15(NBIO, 0, regRCC_STRAP0_RCC_BIF_STRAP5, data);
|
||||
|
||||
def = data = RREG32_SOC15(NBIO, 0, regBIF_CFG_DEV0_EPF0_DEVICE_CNTL2);
|
||||
data &= ~BIF_CFG_DEV0_EPF0_DEVICE_CNTL2__LTR_EN_MASK;
|
||||
pcie_capability_read_word(adev->pdev, PCI_EXP_DEVCTL2, &devctl2);
|
||||
data = def = devctl2;
|
||||
data &= ~PCI_EXP_DEVCTL2_LTR_EN;
|
||||
if (def != data)
|
||||
WREG32_SOC15(NBIO, 0, regBIF_CFG_DEV0_EPF0_DEVICE_CNTL2, data);
|
||||
pcie_capability_set_word(adev->pdev, PCI_EXP_DEVCTL2, (u16)data);
|
||||
|
||||
WREG32_SOC15(NBIO, 0, regBIF_CFG_DEV0_EPF0_PCIE_LTR_CAP, 0x10011001);
|
||||
ltr = pci_find_ext_capability(adev->pdev, PCI_EXT_CAP_ID_LTR);
|
||||
|
||||
if (ltr) {
|
||||
pci_write_config_dword(adev->pdev, ltr + PCI_LTR_MAX_SNOOP_LAT, 0x10011001);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* regPSWUSP0_PCIE_LC_CNTL2 should be replace by PCIE_LC_CNTL2 or someone else ? */
|
||||
|
||||
@@ -428,6 +428,7 @@ static int soc24_common_early_init(void *handle)
|
||||
|
||||
adev->pg_flags = AMD_PG_SUPPORT_VCN |
|
||||
AMD_PG_SUPPORT_JPEG |
|
||||
AMD_PG_SUPPORT_JPEG_DPG |
|
||||
AMD_PG_SUPPORT_VCN_DPG;
|
||||
adev->external_rev_id = adev->rev_id + 0x50;
|
||||
break;
|
||||
|
||||
@@ -557,7 +557,7 @@ static int umc_v12_0_update_ecc_status(struct amdgpu_device *adev,
|
||||
ret = amdgpu_umc_logs_ecc_err(adev, &con->umc_ecc_log.de_page_tree, ecc_err);
|
||||
if (ret) {
|
||||
if (ret == -EEXIST)
|
||||
con->umc_ecc_log.de_updated = true;
|
||||
con->umc_ecc_log.de_queried_count++;
|
||||
else
|
||||
dev_err(adev->dev, "Fail to log ecc error! ret:%d\n", ret);
|
||||
|
||||
@@ -566,7 +566,7 @@ static int umc_v12_0_update_ecc_status(struct amdgpu_device *adev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
con->umc_ecc_log.de_updated = true;
|
||||
con->umc_ecc_log.de_queried_count++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -230,6 +230,7 @@ static int add_queue_mes(struct device_queue_manager *dqm, struct queue *q,
|
||||
if (queue_type < 0) {
|
||||
dev_err(adev->dev, "Queue type not supported with MES, queue:%d\n",
|
||||
q->properties.type);
|
||||
up_read(&adev->reset_domain->sem);
|
||||
return -EINVAL;
|
||||
}
|
||||
queue_input.queue_type = (uint32_t)queue_type;
|
||||
|
||||
@@ -368,15 +368,6 @@ static inline bool is_dc_timing_adjust_needed(struct dm_crtc_state *old_state,
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void reverse_planes_order(struct dc_surface_update *array_of_surface_update,
|
||||
int planes_count)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0, j = planes_count - 1; i < j; i++, j--)
|
||||
swap(array_of_surface_update[i], array_of_surface_update[j]);
|
||||
}
|
||||
|
||||
/*
|
||||
* DC will program planes with their z-order determined by their ordering
|
||||
* in the dc_surface_updates array. This comparator is used to sort them
|
||||
@@ -1302,6 +1293,7 @@ static void dm_dmub_hw_resume(struct amdgpu_device *adev)
|
||||
struct dmub_srv *dmub_srv = adev->dm.dmub_srv;
|
||||
enum dmub_status status;
|
||||
bool init;
|
||||
int r;
|
||||
|
||||
if (!dmub_srv) {
|
||||
/* DMUB isn't supported on the ASIC. */
|
||||
@@ -1319,7 +1311,9 @@ static void dm_dmub_hw_resume(struct amdgpu_device *adev)
|
||||
DRM_WARN("Wait for DMUB auto-load failed: %d\n", status);
|
||||
} else {
|
||||
/* Perform the full hardware initialization. */
|
||||
dm_dmub_hw_init(adev);
|
||||
r = dm_dmub_hw_init(adev);
|
||||
if (r)
|
||||
DRM_ERROR("DMUB interface failed to initialize: status=%d\n", r);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11090,8 +11084,12 @@ static int dm_crtc_get_cursor_mode(struct amdgpu_device *adev,
|
||||
int cursor_scale_w, cursor_scale_h;
|
||||
int i;
|
||||
|
||||
/* Overlay cursor not supported on HW before DCN */
|
||||
if (amdgpu_ip_version(adev, DCE_HWIP, 0) == 0) {
|
||||
/* 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 in addition to DCE
|
||||
*/
|
||||
if (amdgpu_ip_version(adev, DCE_HWIP, 0) == 0 ||
|
||||
amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 0, 1)) {
|
||||
*cursor_mode = DM_CURSOR_NATIVE_MODE;
|
||||
return 0;
|
||||
}
|
||||
@@ -11234,7 +11232,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_crtc_state *old_crtc_state, *new_crtc_state;
|
||||
struct drm_plane *plane;
|
||||
struct drm_plane_state *old_plane_state, *new_plane_state;
|
||||
struct drm_plane_state *old_plane_state, *new_plane_state, *new_cursor_state;
|
||||
enum dc_status status;
|
||||
int ret, i;
|
||||
bool lock_and_validation_needed = false;
|
||||
@@ -11462,19 +11460,39 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
|
||||
drm_dbg_atomic(dev, "MPO enablement requested on crtc:[%p]\n", crtc);
|
||||
}
|
||||
|
||||
/* Check cursor planes restrictions */
|
||||
/* Check cursor restrictions */
|
||||
for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
|
||||
enum amdgpu_dm_cursor_mode required_cursor_mode;
|
||||
int is_rotated, is_scaled;
|
||||
|
||||
/* Overlay cusor not subject to native cursor restrictions */
|
||||
dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
|
||||
if (dm_new_crtc_state->cursor_mode == DM_CURSOR_OVERLAY_MODE)
|
||||
continue;
|
||||
|
||||
/* 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)) {
|
||||
new_cursor_state = drm_atomic_get_new_plane_state(state, crtc->cursor);
|
||||
|
||||
is_rotated = new_cursor_state &&
|
||||
((new_cursor_state->rotation & DRM_MODE_ROTATE_MASK) != DRM_MODE_ROTATE_0);
|
||||
is_scaled = new_cursor_state && ((new_cursor_state->src_w >> 16 != new_cursor_state->crtc_w) ||
|
||||
(new_cursor_state->src_h >> 16 != new_cursor_state->crtc_h));
|
||||
|
||||
if (is_rotated || is_scaled) {
|
||||
drm_dbg_driver(
|
||||
crtc->dev,
|
||||
"[CRTC:%d:%s] cannot enable hardware cursor due to rotation/scaling\n",
|
||||
crtc->base.id, crtc->name);
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* If HW can only do native cursor, check restrictions again */
|
||||
ret = dm_crtc_get_cursor_mode(adev, state, dm_new_crtc_state,
|
||||
&required_cursor_mode);
|
||||
|
||||
if (ret) {
|
||||
drm_dbg_driver(crtc->dev,
|
||||
"[CRTC:%d:%s] Checking cursor mode failed\n",
|
||||
|
||||
@@ -989,4 +989,7 @@ void *dm_allocate_gpu_mem(struct amdgpu_device *adev,
|
||||
enum dc_gpu_mem_alloc_type type,
|
||||
size_t size,
|
||||
long long *addr);
|
||||
|
||||
bool amdgpu_dm_is_headless(struct amdgpu_device *adev);
|
||||
|
||||
#endif /* __AMDGPU_DM_H__ */
|
||||
|
||||
@@ -162,33 +162,63 @@ static void amdgpu_dm_crtc_set_panel_sr_feature(
|
||||
}
|
||||
}
|
||||
|
||||
bool amdgpu_dm_is_headless(struct amdgpu_device *adev)
|
||||
{
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_list_iter iter;
|
||||
struct drm_device *dev;
|
||||
bool is_headless = true;
|
||||
|
||||
if (adev == NULL)
|
||||
return true;
|
||||
|
||||
dev = adev->dm.ddev;
|
||||
|
||||
drm_connector_list_iter_begin(dev, &iter);
|
||||
drm_for_each_connector_iter(connector, &iter) {
|
||||
|
||||
if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
|
||||
continue;
|
||||
|
||||
if (connector->status == connector_status_connected) {
|
||||
is_headless = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
drm_connector_list_iter_end(&iter);
|
||||
return is_headless;
|
||||
}
|
||||
|
||||
static void amdgpu_dm_idle_worker(struct work_struct *work)
|
||||
{
|
||||
struct idle_workqueue *idle_work;
|
||||
|
||||
idle_work = container_of(work, struct idle_workqueue, work);
|
||||
idle_work->dm->idle_workqueue->running = true;
|
||||
fsleep(HPD_DETECTION_PERIOD_uS);
|
||||
mutex_lock(&idle_work->dm->dc_lock);
|
||||
while (idle_work->enable) {
|
||||
if (!idle_work->dm->dc->idle_optimizations_allowed)
|
||||
break;
|
||||
|
||||
while (idle_work->enable) {
|
||||
fsleep(HPD_DETECTION_PERIOD_uS);
|
||||
mutex_lock(&idle_work->dm->dc_lock);
|
||||
if (!idle_work->dm->dc->idle_optimizations_allowed) {
|
||||
mutex_unlock(&idle_work->dm->dc_lock);
|
||||
break;
|
||||
}
|
||||
dc_allow_idle_optimizations(idle_work->dm->dc, false);
|
||||
|
||||
mutex_unlock(&idle_work->dm->dc_lock);
|
||||
fsleep(HPD_DETECTION_TIME_uS);
|
||||
mutex_lock(&idle_work->dm->dc_lock);
|
||||
|
||||
if (!amdgpu_dm_psr_is_active_allowed(idle_work->dm))
|
||||
if (!amdgpu_dm_is_headless(idle_work->dm->adev) &&
|
||||
!amdgpu_dm_psr_is_active_allowed(idle_work->dm)) {
|
||||
mutex_unlock(&idle_work->dm->dc_lock);
|
||||
break;
|
||||
}
|
||||
|
||||
dc_allow_idle_optimizations(idle_work->dm->dc, true);
|
||||
if (idle_work->enable)
|
||||
dc_allow_idle_optimizations(idle_work->dm->dc, true);
|
||||
mutex_unlock(&idle_work->dm->dc_lock);
|
||||
fsleep(HPD_DETECTION_PERIOD_uS);
|
||||
mutex_lock(&idle_work->dm->dc_lock);
|
||||
}
|
||||
mutex_unlock(&idle_work->dm->dc_lock);
|
||||
idle_work->dm->idle_workqueue->running = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -3795,6 +3795,7 @@ static int trigger_hpd_mst_set(void *data, u64 val)
|
||||
struct amdgpu_dm_connector *aconnector;
|
||||
struct drm_connector *connector;
|
||||
struct dc_link *link = NULL;
|
||||
int ret;
|
||||
|
||||
if (val == 1) {
|
||||
drm_connector_list_iter_begin(dev, &iter);
|
||||
@@ -3806,7 +3807,9 @@ static int trigger_hpd_mst_set(void *data, u64 val)
|
||||
dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD);
|
||||
mutex_unlock(&adev->dm.dc_lock);
|
||||
|
||||
drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true);
|
||||
ret = drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true);
|
||||
if (ret < 0)
|
||||
DRM_ERROR("DM_MST: Failed to set the device into MST mode!");
|
||||
}
|
||||
}
|
||||
} else if (val == 0) {
|
||||
|
||||
@@ -1239,8 +1239,11 @@ void dm_helpers_enable_periodic_detection(struct dc_context *ctx, bool enable)
|
||||
{
|
||||
struct amdgpu_device *adev = ctx->driver_context;
|
||||
|
||||
if (adev->dm.idle_workqueue)
|
||||
if (adev->dm.idle_workqueue) {
|
||||
adev->dm.idle_workqueue->enable = enable;
|
||||
if (enable && !adev->dm.idle_workqueue->running && amdgpu_dm_is_headless(adev))
|
||||
schedule_work(&adev->dm.idle_workqueue->work);
|
||||
}
|
||||
}
|
||||
|
||||
void dm_helpers_dp_mst_update_branch_bandwidth(
|
||||
|
||||
@@ -1691,7 +1691,7 @@ enum dc_status dm_dp_mst_is_port_support_mode(
|
||||
if (aconnector->mst_output_port->passthrough_aux) {
|
||||
if (bw_range.min_kbps > end_to_end_bw_in_kbps) {
|
||||
DRM_DEBUG_DRIVER("DSC passthrough. Max dsc compression can't fit into end-to-end bw\n");
|
||||
return DC_FAIL_BANDWIDTH_VALIDATE;
|
||||
return DC_FAIL_BANDWIDTH_VALIDATE;
|
||||
}
|
||||
} else {
|
||||
/*dsc bitstream decoded at the dp last link*/
|
||||
@@ -1756,7 +1756,7 @@ enum dc_status dm_dp_mst_is_port_support_mode(
|
||||
if (branch_max_throughput_mps != 0 &&
|
||||
((stream->timing.pix_clk_100hz / 10) > branch_max_throughput_mps * 1000)) {
|
||||
DRM_DEBUG_DRIVER("DSC is required but max throughput mps fails");
|
||||
return DC_FAIL_BANDWIDTH_VALIDATE;
|
||||
return DC_FAIL_BANDWIDTH_VALIDATE;
|
||||
}
|
||||
} else {
|
||||
DRM_DEBUG_DRIVER("DSC is required but can't find common dsc config.");
|
||||
|
||||
@@ -227,7 +227,8 @@ static void init_transmitter_control(struct bios_parser *bp)
|
||||
uint8_t frev;
|
||||
uint8_t crev = 0;
|
||||
|
||||
BIOS_CMD_TABLE_REVISION(dig1transmittercontrol, frev, crev);
|
||||
if (!BIOS_CMD_TABLE_REVISION(dig1transmittercontrol, frev, crev))
|
||||
BREAK_TO_DEBUGGER();
|
||||
|
||||
switch (crev) {
|
||||
case 6:
|
||||
|
||||
@@ -113,8 +113,6 @@ static void dcn201_update_clocks(struct clk_mgr *clk_mgr_base,
|
||||
dcn2_read_clocks_from_hw_dentist(clk_mgr_base);
|
||||
}
|
||||
|
||||
clk_mgr_helper_get_active_display_cnt(dc, context);
|
||||
|
||||
if (should_set_clock(safe_to_lower, new_clocks->phyclk_khz, clk_mgr_base->clks.phyclk_khz))
|
||||
clk_mgr_base->clks.phyclk_khz = new_clocks->phyclk_khz;
|
||||
|
||||
|
||||
@@ -163,9 +163,14 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base)
|
||||
{
|
||||
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
|
||||
unsigned int num_levels;
|
||||
struct clk_limit_num_entries *num_entries_per_clk = &clk_mgr_base->bw_params->clk_table.num_entries_per_clk;
|
||||
struct clk_limit_num_entries *num_entries_per_clk;
|
||||
unsigned int i;
|
||||
|
||||
if (!clk_mgr_base->bw_params)
|
||||
return;
|
||||
|
||||
num_entries_per_clk = &clk_mgr_base->bw_params->clk_table.num_entries_per_clk;
|
||||
|
||||
memset(&(clk_mgr_base->clks), 0, sizeof(struct dc_clocks));
|
||||
clk_mgr_base->clks.p_state_change_support = true;
|
||||
clk_mgr_base->clks.prev_p_state_change_support = true;
|
||||
@@ -173,9 +178,6 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base)
|
||||
clk_mgr->smu_present = false;
|
||||
clk_mgr->dpm_present = false;
|
||||
|
||||
if (!clk_mgr_base->bw_params)
|
||||
return;
|
||||
|
||||
if (!clk_mgr_base->force_smu_not_present && dcn30_smu_get_smu_version(clk_mgr, &clk_mgr->smu_ver))
|
||||
clk_mgr->smu_present = true;
|
||||
|
||||
|
||||
@@ -207,9 +207,14 @@ static void dcn401_build_wm_range_table(struct clk_mgr *clk_mgr)
|
||||
void dcn401_init_clocks(struct clk_mgr *clk_mgr_base)
|
||||
{
|
||||
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
|
||||
struct clk_limit_num_entries *num_entries_per_clk = &clk_mgr_base->bw_params->clk_table.num_entries_per_clk;
|
||||
struct clk_limit_num_entries *num_entries_per_clk;
|
||||
unsigned int i;
|
||||
|
||||
if (!clk_mgr_base->bw_params)
|
||||
return;
|
||||
|
||||
num_entries_per_clk = &clk_mgr_base->bw_params->clk_table.num_entries_per_clk;
|
||||
|
||||
memset(&(clk_mgr_base->clks), 0, sizeof(struct dc_clocks));
|
||||
clk_mgr_base->clks.p_state_change_support = true;
|
||||
clk_mgr_base->clks.prev_p_state_change_support = true;
|
||||
@@ -217,9 +222,6 @@ void dcn401_init_clocks(struct clk_mgr *clk_mgr_base)
|
||||
clk_mgr->smu_present = false;
|
||||
clk_mgr->dpm_present = false;
|
||||
|
||||
if (!clk_mgr_base->bw_params)
|
||||
return;
|
||||
|
||||
if (!clk_mgr_base->force_smu_not_present && dcn30_smu_get_smu_version(clk_mgr, &clk_mgr->smu_ver))
|
||||
clk_mgr->smu_present = true;
|
||||
|
||||
|
||||
@@ -1264,6 +1264,9 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
|
||||
apply_ctx_interdependent_lock(dc, dc->current_state, old_stream, false);
|
||||
dc->hwss.post_unlock_program_front_end(dc, dangling_context);
|
||||
}
|
||||
|
||||
if (dc->res_pool->funcs->prepare_mcache_programming)
|
||||
dc->res_pool->funcs->prepare_mcache_programming(dc, dangling_context);
|
||||
if (dc->hwss.program_front_end_for_ctx) {
|
||||
dc->hwss.interdependent_update_lock(dc, dc->current_state, true);
|
||||
dc->hwss.program_front_end_for_ctx(dc, dangling_context);
|
||||
@@ -2037,6 +2040,8 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
|
||||
}
|
||||
|
||||
/* Program all planes within new context*/
|
||||
if (dc->res_pool->funcs->prepare_mcache_programming)
|
||||
dc->res_pool->funcs->prepare_mcache_programming(dc, context);
|
||||
if (dc->hwss.program_front_end_for_ctx) {
|
||||
dc->hwss.interdependent_update_lock(dc, context, true);
|
||||
dc->hwss.program_front_end_for_ctx(dc, context);
|
||||
@@ -3884,6 +3889,9 @@ static void commit_planes_for_stream(struct dc *dc,
|
||||
odm_pipe->ttu_regs.min_ttu_vblank = MAX_TTU;
|
||||
}
|
||||
|
||||
if (update_type != UPDATE_TYPE_FAST && dc->res_pool->funcs->prepare_mcache_programming)
|
||||
dc->res_pool->funcs->prepare_mcache_programming(dc, context);
|
||||
|
||||
if ((update_type != UPDATE_TYPE_FAST) && stream->update_flags.bits.dsc_changed)
|
||||
if (top_pipe_to_program &&
|
||||
top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable) {
|
||||
@@ -3903,6 +3911,10 @@ static void commit_planes_for_stream(struct dc *dc,
|
||||
top_pipe_to_program->stream_res.tg);
|
||||
}
|
||||
|
||||
if (dc->hwss.wait_for_dcc_meta_propagation) {
|
||||
dc->hwss.wait_for_dcc_meta_propagation(dc, top_pipe_to_program);
|
||||
}
|
||||
|
||||
if (should_lock_all_pipes && dc->hwss.interdependent_update_lock) {
|
||||
if (dc->hwss.subvp_pipe_control_lock)
|
||||
dc->hwss.subvp_pipe_control_lock(dc, context, true, should_lock_all_pipes, NULL, subvp_prev_use);
|
||||
|
||||
@@ -595,6 +595,12 @@ void hwss_build_fast_sequence(struct dc *dc,
|
||||
if (!plane || !stream)
|
||||
return;
|
||||
|
||||
if (dc->hwss.wait_for_dcc_meta_propagation) {
|
||||
block_sequence[*num_steps].params.wait_for_dcc_meta_propagation_params.dc = dc;
|
||||
block_sequence[*num_steps].params.wait_for_dcc_meta_propagation_params.top_pipe_to_program = pipe_ctx;
|
||||
block_sequence[*num_steps].func = HUBP_WAIT_FOR_DCC_META_PROP;
|
||||
(*num_steps)++;
|
||||
}
|
||||
if (dc->hwss.subvp_pipe_control_lock_fast) {
|
||||
block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.dc = dc;
|
||||
block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.lock = true;
|
||||
@@ -835,6 +841,11 @@ void hwss_execute_sequence(struct dc *dc,
|
||||
case DMUB_SUBVP_SAVE_SURF_ADDR:
|
||||
hwss_subvp_save_surf_addr(params);
|
||||
break;
|
||||
case HUBP_WAIT_FOR_DCC_META_PROP:
|
||||
dc->hwss.wait_for_dcc_meta_propagation(
|
||||
params->wait_for_dcc_meta_propagation_params.dc,
|
||||
params->wait_for_dcc_meta_propagation_params.top_pipe_to_program);
|
||||
break;
|
||||
case DMUB_FAMS2_GLOBAL_CONTROL_LOCK_FAST:
|
||||
dc->hwss.fams2_global_control_lock_fast(params);
|
||||
break;
|
||||
|
||||
@@ -416,6 +416,35 @@ bool dc_stream_program_cursor_position(
|
||||
if (reset_idle_optimizations && !dc->debug.disable_dmub_reallow_idle)
|
||||
dc_allow_idle_optimizations(dc, true);
|
||||
|
||||
/* apply/update visual confirm */
|
||||
if (dc->debug.visual_confirm == VISUAL_CONFIRM_HW_CURSOR) {
|
||||
/* update software state */
|
||||
uint32_t color_value = MAX_TG_COLOR_VALUE;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
|
||||
|
||||
/* adjust visual confirm color for all pipes with current stream */
|
||||
if (stream == pipe_ctx->stream) {
|
||||
if (stream->cursor_position.enable) {
|
||||
pipe_ctx->visual_confirm_color.color_r_cr = color_value;
|
||||
pipe_ctx->visual_confirm_color.color_g_y = 0;
|
||||
pipe_ctx->visual_confirm_color.color_b_cb = 0;
|
||||
} else {
|
||||
pipe_ctx->visual_confirm_color.color_r_cr = 0;
|
||||
pipe_ctx->visual_confirm_color.color_g_y = 0;
|
||||
pipe_ctx->visual_confirm_color.color_b_cb = color_value;
|
||||
}
|
||||
|
||||
/* programming hardware */
|
||||
if (pipe_ctx->plane_state)
|
||||
dc->hwss.update_visual_confirm_color(dc, pipe_ctx,
|
||||
pipe_ctx->plane_res.hubp->mpcc_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ struct aux_payload;
|
||||
struct set_config_cmd_payload;
|
||||
struct dmub_notification;
|
||||
|
||||
#define DC_VER "3.2.289"
|
||||
#define DC_VER "3.2.290"
|
||||
|
||||
#define MAX_SURFACES 3
|
||||
#define MAX_PLANES 6
|
||||
@@ -333,6 +333,9 @@ struct dc_dcc_setting {
|
||||
uint32_t dcc_128_128_uncontrained : 1; //available in ASICs before DCN 3.0
|
||||
uint32_t dcc_256_128_128 : 1; //available starting with DCN 3.0
|
||||
uint32_t dcc_256_256_unconstrained : 1; //available in ASICs before DCN 3.0 (the best compression case)
|
||||
uint32_t dcc_256_256 : 1; //available in ASICs starting with DCN 4.0x (the best compression case)
|
||||
uint32_t dcc_256_128 : 1; //available in ASICs starting with DCN 4.0x
|
||||
uint32_t dcc_256_64 : 1; //available in ASICs starting with DCN 4.0x (the worst compression case)
|
||||
} dcc_controls;
|
||||
};
|
||||
|
||||
@@ -476,6 +479,7 @@ enum visual_confirm {
|
||||
VISUAL_CONFIRM_SUBVP = 14,
|
||||
VISUAL_CONFIRM_MCLK_SWITCH = 16,
|
||||
VISUAL_CONFIRM_FAMS2 = 19,
|
||||
VISUAL_CONFIRM_HW_CURSOR = 20,
|
||||
};
|
||||
|
||||
enum dc_psr_power_opts {
|
||||
@@ -1036,9 +1040,10 @@ struct dc_debug_options {
|
||||
unsigned int static_screen_wait_frames;
|
||||
uint32_t pwm_freq;
|
||||
bool force_chroma_subsampling_1tap;
|
||||
unsigned int dcc_meta_propagation_delay_us;
|
||||
bool disable_422_left_edge_pixel;
|
||||
bool dml21_force_pstate_method;
|
||||
uint32_t dml21_force_pstate_method_value;
|
||||
uint32_t dml21_force_pstate_method_values[MAX_PIPES];
|
||||
uint32_t dml21_disable_pstate_method_mask;
|
||||
union dmub_fams2_global_feature_config fams2_config;
|
||||
bool enable_legacy_clock_update;
|
||||
|
||||
@@ -245,7 +245,9 @@ bool dc_dmub_srv_cmd_run_list(struct dc_dmub_srv *dc_dmub_srv, unsigned int coun
|
||||
if (status == DMUB_STATUS_POWER_STATE_D3)
|
||||
return false;
|
||||
|
||||
dmub_srv_wait_for_idle(dmub, 100000);
|
||||
status = dmub_srv_wait_for_idle(dmub, 100000);
|
||||
if (status != DMUB_STATUS_OK)
|
||||
return false;
|
||||
|
||||
/* Requeue the command. */
|
||||
status = dmub_srv_cmd_queue(dmub, &cmd_list[i]);
|
||||
@@ -517,7 +519,8 @@ void dc_dmub_srv_get_visual_confirm_color_cmd(struct dc *dc, struct pipe_ctx *pi
|
||||
union dmub_rb_cmd cmd = { 0 };
|
||||
unsigned int panel_inst = 0;
|
||||
|
||||
dc_get_edp_link_panel_inst(dc, pipe_ctx->stream->link, &panel_inst);
|
||||
if (!dc_get_edp_link_panel_inst(dc, pipe_ctx->stream->link, &panel_inst))
|
||||
return;
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
|
||||
|
||||
@@ -1036,6 +1036,7 @@ enum replay_FW_Message_type {
|
||||
Replay_Set_Residency_Frameupdate_Timer,
|
||||
Replay_Set_Pseudo_VTotal,
|
||||
Replay_Disabled_Adaptive_Sync_SDP,
|
||||
Replay_Set_General_Cmd,
|
||||
};
|
||||
|
||||
union replay_error_status {
|
||||
|
||||
@@ -853,43 +853,30 @@ static void dccg401_enable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst
|
||||
}
|
||||
|
||||
/*get other front end connected to this backend*/
|
||||
static uint8_t dccg401_get_other_enabled_symclk_fe(struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst)
|
||||
static uint8_t dccg401_get_number_enabled_symclk_fe_connected_to_be(struct dccg *dccg, uint32_t link_enc_inst)
|
||||
{
|
||||
uint8_t num_enabled_symclk_fe = 0;
|
||||
uint32_t be_clk_en = 0, fe_clk_en[4] = {0}, be_clk_sel[4] = {0};
|
||||
uint32_t fe_clk_en[4] = {0}, be_clk_sel[4] = {0};
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
uint8_t i;
|
||||
|
||||
switch (link_enc_inst) {
|
||||
case 0:
|
||||
REG_GET_3(SYMCLKA_CLOCK_ENABLE, SYMCLKA_CLOCK_ENABLE, &be_clk_en,
|
||||
SYMCLKA_FE_EN, &fe_clk_en[0],
|
||||
SYMCLKA_FE_SRC_SEL, &be_clk_sel[0]);
|
||||
break;
|
||||
case 1:
|
||||
REG_GET_3(SYMCLKB_CLOCK_ENABLE, SYMCLKB_CLOCK_ENABLE, &be_clk_en,
|
||||
SYMCLKB_FE_EN, &fe_clk_en[1],
|
||||
SYMCLKB_FE_SRC_SEL, &be_clk_sel[1]);
|
||||
break;
|
||||
case 2:
|
||||
REG_GET_3(SYMCLKC_CLOCK_ENABLE, SYMCLKC_CLOCK_ENABLE, &be_clk_en,
|
||||
SYMCLKC_FE_EN, &fe_clk_en[2],
|
||||
SYMCLKC_FE_SRC_SEL, &be_clk_sel[2]);
|
||||
break;
|
||||
case 3:
|
||||
REG_GET_3(SYMCLKD_CLOCK_ENABLE, SYMCLKD_CLOCK_ENABLE, &be_clk_en,
|
||||
SYMCLKD_FE_EN, &fe_clk_en[3],
|
||||
SYMCLKD_FE_SRC_SEL, &be_clk_sel[3]);
|
||||
break;
|
||||
}
|
||||
if (be_clk_en) {
|
||||
/* for DPMST, this backend could be used by multiple front end.
|
||||
only disable the backend if this stream_enc_ins is the last active stream enc connected to this back_end*/
|
||||
uint8_t i;
|
||||
for (i = 0; i != link_enc_inst && i < ARRAY_SIZE(fe_clk_en); i++) {
|
||||
if (fe_clk_en[i] && be_clk_sel[i] == link_enc_inst)
|
||||
num_enabled_symclk_fe++;
|
||||
}
|
||||
REG_GET_2(SYMCLKA_CLOCK_ENABLE, SYMCLKA_FE_EN, &fe_clk_en[0],
|
||||
SYMCLKA_FE_SRC_SEL, &be_clk_sel[0]);
|
||||
|
||||
REG_GET_2(SYMCLKB_CLOCK_ENABLE, SYMCLKB_FE_EN, &fe_clk_en[1],
|
||||
SYMCLKB_FE_SRC_SEL, &be_clk_sel[1]);
|
||||
|
||||
REG_GET_2(SYMCLKC_CLOCK_ENABLE, SYMCLKC_FE_EN, &fe_clk_en[2],
|
||||
SYMCLKC_FE_SRC_SEL, &be_clk_sel[2]);
|
||||
|
||||
REG_GET_2(SYMCLKD_CLOCK_ENABLE, SYMCLKD_FE_EN, &fe_clk_en[3],
|
||||
SYMCLKD_FE_SRC_SEL, &be_clk_sel[3]);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fe_clk_en); i++) {
|
||||
if (fe_clk_en[i] && be_clk_sel[i] == link_enc_inst)
|
||||
num_enabled_symclk_fe++;
|
||||
}
|
||||
|
||||
return num_enabled_symclk_fe;
|
||||
}
|
||||
|
||||
@@ -921,9 +908,9 @@ static void dccg401_disable_symclk_se(struct dccg *dccg, uint32_t stream_enc_ins
|
||||
break;
|
||||
}
|
||||
|
||||
/*check other enabled symclk fe */
|
||||
num_enabled_symclk_fe = dccg401_get_other_enabled_symclk_fe(dccg, stream_enc_inst, link_enc_inst);
|
||||
/*only turn off backend clk if other front end attachecd to this backend are all off,
|
||||
/*check other enabled symclk fe connected to this be */
|
||||
num_enabled_symclk_fe = dccg401_get_number_enabled_symclk_fe_connected_to_be(dccg, link_enc_inst);
|
||||
/*only turn off backend clk if other front ends attached to this backend are all off,
|
||||
for mst, only turn off the backend if this is the last front end*/
|
||||
if (num_enabled_symclk_fe == 0) {
|
||||
switch (link_enc_inst) {
|
||||
|
||||
@@ -1361,7 +1361,10 @@ void dce110_link_encoder_dp_set_lane_settings(
|
||||
cntl.lane_settings = training_lane_set.raw;
|
||||
|
||||
/* call VBIOS table to set voltage swing and pre-emphasis */
|
||||
link_transmitter_control(enc110, &cntl);
|
||||
if (link_transmitter_control(enc110, &cntl) != BP_RESULT_OK) {
|
||||
DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", __func__);
|
||||
BREAK_TO_DEBUGGER();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -346,13 +346,29 @@ static void dmub_replay_send_cmd(struct dmub_replay *dmub,
|
||||
cmd.replay_disabled_adaptive_sync_sdp.header.sub_type =
|
||||
DMUB_CMD__REPLAY_DISABLED_ADAPTIVE_SYNC_SDP;
|
||||
cmd.replay_disabled_adaptive_sync_sdp.header.payload_bytes =
|
||||
sizeof(struct dmub_rb_cmd_replay_set_pseudo_vtotal);
|
||||
sizeof(struct dmub_rb_cmd_replay_disabled_adaptive_sync_sdp);
|
||||
//Cmd Body
|
||||
cmd.replay_disabled_adaptive_sync_sdp.data.panel_inst =
|
||||
cmd_element->disabled_adaptive_sync_sdp_data.panel_inst;
|
||||
cmd.replay_disabled_adaptive_sync_sdp.data.force_disabled =
|
||||
cmd_element->disabled_adaptive_sync_sdp_data.force_disabled;
|
||||
break;
|
||||
case Replay_Set_General_Cmd:
|
||||
//Header
|
||||
cmd.replay_set_general_cmd.header.sub_type =
|
||||
DMUB_CMD__REPLAY_SET_GENERAL_CMD;
|
||||
cmd.replay_set_general_cmd.header.payload_bytes =
|
||||
sizeof(struct dmub_rb_cmd_replay_set_general_cmd);
|
||||
//Cmd Body
|
||||
cmd.replay_set_general_cmd.data.panel_inst =
|
||||
cmd_element->set_general_cmd_data.panel_inst;
|
||||
cmd.replay_set_general_cmd.data.subtype =
|
||||
cmd_element->set_general_cmd_data.subtype;
|
||||
cmd.replay_set_general_cmd.data.param1 =
|
||||
cmd_element->set_general_cmd_data.param1;
|
||||
cmd.replay_set_general_cmd.data.param2 =
|
||||
cmd_element->set_general_cmd_data.param2;
|
||||
break;
|
||||
case Replay_Msg_Not_Support:
|
||||
default:
|
||||
return;
|
||||
|
||||
@@ -1104,6 +1104,7 @@ void dcn10_link_encoder_dp_set_lane_settings(
|
||||
union dpcd_training_lane_set training_lane_set = { { 0 } };
|
||||
int32_t lane = 0;
|
||||
struct bp_transmitter_control cntl = { 0 };
|
||||
enum bp_result result;
|
||||
|
||||
if (!link_settings) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
@@ -1138,7 +1139,12 @@ void dcn10_link_encoder_dp_set_lane_settings(
|
||||
cntl.lane_settings = training_lane_set.raw;
|
||||
|
||||
/* call VBIOS table to set voltage swing and pre-emphasis */
|
||||
link_transmitter_control(enc10, &cntl);
|
||||
result = link_transmitter_control(enc10, &cntl);
|
||||
|
||||
if (result != BP_RESULT_OK) {
|
||||
DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", __func__);
|
||||
BREAK_TO_DEBUGGER();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
#
|
||||
# (c) Copyright 2020 Advanced Micro Devices, Inc. All the rights reserved
|
||||
#
|
||||
# All rights reserved. This notice is intended as a precaution against
|
||||
# inadvertent publication and does not imply publication or any waiver
|
||||
# of confidentiality. The year included in the foregoing notice is the
|
||||
# year of creation of the work.
|
||||
#
|
||||
# Authors: AMD
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright © 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
#
|
||||
# Makefile for dcn30.
|
||||
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright © 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
#
|
||||
# Copyright 2020 Advanced Micro Devices, Inc. All the rights reserved
|
||||
#
|
||||
# All rights reserved. This notice is intended as a precaution against
|
||||
# inadvertent publication and does not imply publication or any waiver
|
||||
# of confidentiality. The year included in the foregoing notice is the
|
||||
# year of creation of the work.
|
||||
#
|
||||
# Authors: AMD
|
||||
#
|
||||
# Makefile for dcn31.
|
||||
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
#
|
||||
# (c) Copyright 2022 Advanced Micro Devices, Inc. All the rights reserved
|
||||
#
|
||||
# All rights reserved. This notice is intended as a precaution against
|
||||
# inadvertent publication and does not imply publication or any waiver
|
||||
# of confidentiality. The year included in the foregoing notice is the
|
||||
# year of creation of the work.
|
||||
#
|
||||
# Authors: AMD
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright © 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
#
|
||||
# Makefile for dcn314.
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#
|
||||
# Copyright © 2023 Advanced Micro Devices, Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright © 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
|
||||
DCN401 += dcn401_dio_link_encoder.o
|
||||
DCN401 += dcn401_dio_stream_encoder.o
|
||||
|
||||
@@ -1084,7 +1084,7 @@ static enum dcn_zstate_support_state decide_zstate_support(struct dc *dc, struc
|
||||
struct dc_stream_status *stream_status = &context->stream_status[0];
|
||||
int minmum_z8_residency = dc->debug.minimum_z8_residency_time > 0 ? dc->debug.minimum_z8_residency_time : 1000;
|
||||
bool allow_z8 = context->bw_ctx.dml.vba.StutterPeriod > (double)minmum_z8_residency;
|
||||
bool is_pwrseq0 = link->link_index == 0;
|
||||
bool is_pwrseq0 = (link && link->link_index == 0);
|
||||
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;
|
||||
|
||||
@@ -688,12 +688,11 @@ static void get_surf_rq_param(struct display_mode_lib *mode_lib,
|
||||
const display_pipe_source_params_st *pipe_src_param,
|
||||
bool is_chroma)
|
||||
{
|
||||
bool mode_422 = false;
|
||||
unsigned int vp_width = 0;
|
||||
unsigned int vp_height = 0;
|
||||
unsigned int data_pitch = 0;
|
||||
unsigned int meta_pitch = 0;
|
||||
unsigned int ppe = mode_422 ? 2 : 1;
|
||||
unsigned int ppe = 1;
|
||||
|
||||
// TODO check if ppe apply for both luma and chroma in 422 case
|
||||
if (is_chroma) {
|
||||
@@ -825,7 +824,6 @@ static void dml20_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib,
|
||||
double min_dst_y_ttu_vblank;
|
||||
unsigned int dlg_vblank_start;
|
||||
bool dual_plane;
|
||||
bool mode_422;
|
||||
unsigned int access_dir;
|
||||
unsigned int vp_height_l;
|
||||
unsigned int vp_width_l;
|
||||
@@ -971,7 +969,6 @@ static void dml20_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib,
|
||||
// Source
|
||||
// dcc_en = src.dcc;
|
||||
dual_plane = is_dual_plane((enum source_format_class)(src->source_format));
|
||||
mode_422 = false; // TODO
|
||||
access_dir = (src->source_scan == dm_vert); // vp access direction: horizontal or vertical accessed
|
||||
// bytes_per_element_l = get_bytes_per_element(source_format_class(src.source_format), 0);
|
||||
// bytes_per_element_c = get_bytes_per_element(source_format_class(src.source_format), 1);
|
||||
@@ -1148,13 +1145,8 @@ static void dml20_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib,
|
||||
dpte_row_height_l = rq_dlg_param->rq_l.dpte_row_height;
|
||||
dpte_row_height_c = rq_dlg_param->rq_c.dpte_row_height;
|
||||
|
||||
if (mode_422) {
|
||||
swath_width_pixels_ub_l = swath_width_ub_l * 2; // *2 for 2 pixel per element
|
||||
swath_width_pixels_ub_c = swath_width_ub_c * 2;
|
||||
} else {
|
||||
swath_width_pixels_ub_l = swath_width_ub_l * 1;
|
||||
swath_width_pixels_ub_c = swath_width_ub_c * 1;
|
||||
}
|
||||
swath_width_pixels_ub_l = swath_width_ub_l;
|
||||
swath_width_pixels_ub_c = swath_width_ub_c;
|
||||
|
||||
if (htaps_l <= 1)
|
||||
min_hratio_fact_l = 2.0;
|
||||
|
||||
@@ -688,12 +688,11 @@ static void get_surf_rq_param(struct display_mode_lib *mode_lib,
|
||||
const display_pipe_source_params_st *pipe_src_param,
|
||||
bool is_chroma)
|
||||
{
|
||||
bool mode_422 = false;
|
||||
unsigned int vp_width = 0;
|
||||
unsigned int vp_height = 0;
|
||||
unsigned int data_pitch = 0;
|
||||
unsigned int meta_pitch = 0;
|
||||
unsigned int ppe = mode_422 ? 2 : 1;
|
||||
unsigned int ppe = 1;
|
||||
|
||||
// TODO check if ppe apply for both luma and chroma in 422 case
|
||||
if (is_chroma) {
|
||||
@@ -825,7 +824,6 @@ static void dml20v2_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib,
|
||||
double min_dst_y_ttu_vblank;
|
||||
unsigned int dlg_vblank_start;
|
||||
bool dual_plane;
|
||||
bool mode_422;
|
||||
unsigned int access_dir;
|
||||
unsigned int vp_height_l;
|
||||
unsigned int vp_width_l;
|
||||
@@ -972,7 +970,6 @@ static void dml20v2_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib,
|
||||
// Source
|
||||
// dcc_en = src.dcc;
|
||||
dual_plane = is_dual_plane((enum source_format_class)(src->source_format));
|
||||
mode_422 = false; // TODO
|
||||
access_dir = (src->source_scan == dm_vert); // vp access direction: horizontal or vertical accessed
|
||||
// bytes_per_element_l = get_bytes_per_element(source_format_class(src.source_format), 0);
|
||||
// bytes_per_element_c = get_bytes_per_element(source_format_class(src.source_format), 1);
|
||||
@@ -1149,13 +1146,8 @@ static void dml20v2_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib,
|
||||
dpte_row_height_l = rq_dlg_param->rq_l.dpte_row_height;
|
||||
dpte_row_height_c = rq_dlg_param->rq_c.dpte_row_height;
|
||||
|
||||
if (mode_422) {
|
||||
swath_width_pixels_ub_l = swath_width_ub_l * 2; // *2 for 2 pixel per element
|
||||
swath_width_pixels_ub_c = swath_width_ub_c * 2;
|
||||
} else {
|
||||
swath_width_pixels_ub_l = swath_width_ub_l * 1;
|
||||
swath_width_pixels_ub_c = swath_width_ub_c * 1;
|
||||
}
|
||||
swath_width_pixels_ub_l = swath_width_ub_l;
|
||||
swath_width_pixels_ub_c = swath_width_ub_c;
|
||||
|
||||
if (htaps_l <= 1)
|
||||
min_hratio_fact_l = 2.0;
|
||||
|
||||
@@ -694,12 +694,11 @@ static void get_surf_rq_param(
|
||||
const display_pipe_params_st *pipe_param,
|
||||
bool is_chroma)
|
||||
{
|
||||
bool mode_422 = false;
|
||||
unsigned int vp_width = 0;
|
||||
unsigned int vp_height = 0;
|
||||
unsigned int data_pitch = 0;
|
||||
unsigned int meta_pitch = 0;
|
||||
unsigned int ppe = mode_422 ? 2 : 1;
|
||||
unsigned int ppe = 1;
|
||||
|
||||
// FIXME check if ppe apply for both luma and chroma in 422 case
|
||||
if (is_chroma) {
|
||||
@@ -868,7 +867,6 @@ static void dml_rq_dlg_get_dlg_params(
|
||||
double min_dst_y_ttu_vblank;
|
||||
unsigned int dlg_vblank_start;
|
||||
bool dual_plane;
|
||||
bool mode_422;
|
||||
unsigned int access_dir;
|
||||
unsigned int vp_height_l;
|
||||
unsigned int vp_width_l;
|
||||
@@ -1020,7 +1018,6 @@ static void dml_rq_dlg_get_dlg_params(
|
||||
// Source
|
||||
// dcc_en = src.dcc;
|
||||
dual_plane = is_dual_plane((enum source_format_class) (src->source_format));
|
||||
mode_422 = false; // FIXME
|
||||
access_dir = (src->source_scan == dm_vert); // vp access direction: horizontal or vertical accessed
|
||||
// bytes_per_element_l = get_bytes_per_element(source_format_class(src.source_format), 0);
|
||||
// bytes_per_element_c = get_bytes_per_element(source_format_class(src.source_format), 1);
|
||||
@@ -1197,13 +1194,8 @@ static void dml_rq_dlg_get_dlg_params(
|
||||
dpte_row_height_l = rq_dlg_param->rq_l.dpte_row_height;
|
||||
dpte_row_height_c = rq_dlg_param->rq_c.dpte_row_height;
|
||||
|
||||
if (mode_422) {
|
||||
swath_width_pixels_ub_l = swath_width_ub_l * 2; // *2 for 2 pixel per element
|
||||
swath_width_pixels_ub_c = swath_width_ub_c * 2;
|
||||
} else {
|
||||
swath_width_pixels_ub_l = swath_width_ub_l * 1;
|
||||
swath_width_pixels_ub_c = swath_width_ub_c * 1;
|
||||
}
|
||||
swath_width_pixels_ub_l = swath_width_ub_l;
|
||||
swath_width_pixels_ub_c = swath_width_ub_c;
|
||||
|
||||
if (hratio_l <= 1)
|
||||
min_hratio_fact_l = 2.0;
|
||||
|
||||
@@ -660,13 +660,12 @@ static void get_surf_rq_param(struct display_mode_lib *mode_lib,
|
||||
bool is_chroma,
|
||||
bool is_alpha)
|
||||
{
|
||||
bool mode_422 = 0;
|
||||
unsigned int vp_width = 0;
|
||||
unsigned int vp_height = 0;
|
||||
unsigned int data_pitch = 0;
|
||||
unsigned int meta_pitch = 0;
|
||||
unsigned int surface_height = 0;
|
||||
unsigned int ppe = mode_422 ? 2 : 1;
|
||||
unsigned int ppe = 1;
|
||||
|
||||
// FIXME check if ppe apply for both luma and chroma in 422 case
|
||||
if (is_chroma | is_alpha) {
|
||||
@@ -934,7 +933,6 @@ static void dml_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib,
|
||||
double min_dst_y_ttu_vblank = 0;
|
||||
unsigned int dlg_vblank_start = 0;
|
||||
bool dual_plane = false;
|
||||
bool mode_422 = false;
|
||||
unsigned int access_dir = 0;
|
||||
unsigned int vp_height_l = 0;
|
||||
unsigned int vp_width_l = 0;
|
||||
@@ -1083,7 +1081,6 @@ static void dml_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib,
|
||||
// Source
|
||||
// dcc_en = src.dcc;
|
||||
dual_plane = is_dual_plane((enum source_format_class)(src->source_format));
|
||||
mode_422 = false; // TODO
|
||||
access_dir = (src->source_scan == dm_vert); // vp access direction: horizontal or vertical accessed
|
||||
vp_height_l = src->viewport_height;
|
||||
vp_width_l = src->viewport_width;
|
||||
@@ -1301,13 +1298,8 @@ static void dml_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib,
|
||||
dpte_row_height_l = rq_dlg_param.rq_l.dpte_row_height;
|
||||
dpte_row_height_c = rq_dlg_param.rq_c.dpte_row_height;
|
||||
|
||||
if (mode_422) {
|
||||
swath_width_pixels_ub_l = swath_width_ub_l * 2; // *2 for 2 pixel per element
|
||||
swath_width_pixels_ub_c = swath_width_ub_c * 2;
|
||||
} else {
|
||||
swath_width_pixels_ub_l = swath_width_ub_l * 1;
|
||||
swath_width_pixels_ub_c = swath_width_ub_c * 1;
|
||||
}
|
||||
swath_width_pixels_ub_l = swath_width_ub_l;
|
||||
swath_width_pixels_ub_c = swath_width_ub_c;
|
||||
|
||||
if (hratio_l <= 1)
|
||||
min_hratio_fact_l = 2.0;
|
||||
|
||||
@@ -655,13 +655,12 @@ static void get_surf_rq_param(
|
||||
bool is_chroma,
|
||||
bool is_alpha)
|
||||
{
|
||||
bool mode_422 = 0;
|
||||
unsigned int vp_width = 0;
|
||||
unsigned int vp_height = 0;
|
||||
unsigned int data_pitch = 0;
|
||||
unsigned int meta_pitch = 0;
|
||||
unsigned int surface_height = 0;
|
||||
unsigned int ppe = mode_422 ? 2 : 1;
|
||||
unsigned int ppe = 1;
|
||||
|
||||
// FIXME check if ppe apply for both luma and chroma in 422 case
|
||||
if (is_chroma | is_alpha) {
|
||||
@@ -888,7 +887,6 @@ static void dml_rq_dlg_get_dlg_params(
|
||||
double min_ttu_vblank;
|
||||
unsigned int dlg_vblank_start;
|
||||
bool dual_plane;
|
||||
bool mode_422;
|
||||
unsigned int access_dir;
|
||||
unsigned int vp_height_l;
|
||||
unsigned int vp_width_l;
|
||||
@@ -1004,7 +1002,6 @@ static void dml_rq_dlg_get_dlg_params(
|
||||
// Prefetch Calc
|
||||
// Source
|
||||
dual_plane = is_dual_plane((enum source_format_class) (src->source_format));
|
||||
mode_422 = 0;
|
||||
access_dir = (src->source_scan == dm_vert); // vp access direction: horizontal or vertical accessed
|
||||
vp_height_l = src->viewport_height;
|
||||
vp_width_l = src->viewport_width;
|
||||
@@ -1142,13 +1139,8 @@ static void dml_rq_dlg_get_dlg_params(
|
||||
dpte_row_height_l = rq_dlg_param->rq_l.dpte_row_height;
|
||||
dpte_row_height_c = rq_dlg_param->rq_c.dpte_row_height;
|
||||
|
||||
if (mode_422) {
|
||||
swath_width_pixels_ub_l = swath_width_ub_l * 2; // *2 for 2 pixel per element
|
||||
swath_width_pixels_ub_c = swath_width_ub_c * 2;
|
||||
} else {
|
||||
swath_width_pixels_ub_l = swath_width_ub_l * 1;
|
||||
swath_width_pixels_ub_c = swath_width_ub_c * 1;
|
||||
}
|
||||
swath_width_pixels_ub_l = swath_width_ub_l;
|
||||
swath_width_pixels_ub_c = swath_width_ub_c;
|
||||
|
||||
if (hratio_l <= 1)
|
||||
min_hratio_fact_l = 2.0;
|
||||
|
||||
@@ -743,13 +743,12 @@ static void get_surf_rq_param(
|
||||
bool is_chroma,
|
||||
bool is_alpha)
|
||||
{
|
||||
bool mode_422 = 0;
|
||||
unsigned int vp_width = 0;
|
||||
unsigned int vp_height = 0;
|
||||
unsigned int data_pitch = 0;
|
||||
unsigned int meta_pitch = 0;
|
||||
unsigned int surface_height = 0;
|
||||
unsigned int ppe = mode_422 ? 2 : 1;
|
||||
unsigned int ppe = 1;
|
||||
|
||||
// FIXME check if ppe apply for both luma and chroma in 422 case
|
||||
if (is_chroma | is_alpha) {
|
||||
@@ -973,7 +972,6 @@ static void dml_rq_dlg_get_dlg_params(
|
||||
double min_ttu_vblank;
|
||||
unsigned int dlg_vblank_start;
|
||||
bool dual_plane;
|
||||
bool mode_422;
|
||||
unsigned int access_dir;
|
||||
unsigned int vp_height_l;
|
||||
unsigned int vp_width_l;
|
||||
@@ -1091,7 +1089,6 @@ static void dml_rq_dlg_get_dlg_params(
|
||||
// Prefetch Calc
|
||||
// Source
|
||||
dual_plane = is_dual_plane((enum source_format_class) (src->source_format));
|
||||
mode_422 = 0;
|
||||
access_dir = (src->source_scan == dm_vert); // vp access direction: horizontal or vertical accessed
|
||||
vp_height_l = src->viewport_height;
|
||||
vp_width_l = src->viewport_width;
|
||||
@@ -1230,13 +1227,8 @@ static void dml_rq_dlg_get_dlg_params(
|
||||
dpte_row_height_l = rq_dlg_param->rq_l.dpte_row_height;
|
||||
dpte_row_height_c = rq_dlg_param->rq_c.dpte_row_height;
|
||||
|
||||
if (mode_422) {
|
||||
swath_width_pixels_ub_l = swath_width_ub_l * 2; // *2 for 2 pixel per element
|
||||
swath_width_pixels_ub_c = swath_width_ub_c * 2;
|
||||
} else {
|
||||
swath_width_pixels_ub_l = swath_width_ub_l * 1;
|
||||
swath_width_pixels_ub_c = swath_width_ub_c * 1;
|
||||
}
|
||||
swath_width_pixels_ub_l = swath_width_ub_l;
|
||||
swath_width_pixels_ub_c = swath_width_ub_c;
|
||||
|
||||
if (hratio_l <= 1)
|
||||
min_hratio_fact_l = 2.0;
|
||||
|
||||
@@ -1000,7 +1000,7 @@ bool dml21_map_dc_state_into_dml_display_cfg(const struct dc *in_dc, struct dc_s
|
||||
/* apply forced pstate policy */
|
||||
if (dml_ctx->config.pmo.force_pstate_method_enable) {
|
||||
dml_dispcfg->plane_descriptors[disp_cfg_plane_location].overrides.uclk_pstate_change_strategy =
|
||||
dml21_force_pstate_method_to_uclk_state_change_strategy(dml_ctx->config.pmo.force_pstate_method_value);
|
||||
dml21_force_pstate_method_to_uclk_state_change_strategy(dml_ctx->config.pmo.force_pstate_method_values[stream_index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,8 @@ static void dml21_apply_debug_options(const struct dc *in_dc, struct dml2_contex
|
||||
/* UCLK P-State options */
|
||||
if (in_dc->debug.dml21_force_pstate_method) {
|
||||
dml_ctx->config.pmo.force_pstate_method_enable = true;
|
||||
dml_ctx->config.pmo.force_pstate_method_value = in_dc->debug.dml21_force_pstate_method_value;
|
||||
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;
|
||||
}
|
||||
@@ -257,6 +258,7 @@ static bool dml21_check_mode_support(const struct dc *in_dc, struct dc_state *co
|
||||
|
||||
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;
|
||||
|
||||
@@ -11521,8 +11521,8 @@ void dml2_core_calcs_get_dpte_row_height(
|
||||
unsigned int MacroTileWidthC;
|
||||
unsigned int MacroTileHeightY;
|
||||
unsigned int MacroTileHeightC;
|
||||
bool surf_linear_128_l;
|
||||
bool surf_linear_128_c;
|
||||
bool surf_linear_128_l = false;
|
||||
bool surf_linear_128_c = false;
|
||||
|
||||
CalculateBytePerPixelAndBlockSizes(
|
||||
SourcePixelFormat,
|
||||
|
||||
@@ -3142,62 +3142,62 @@ static unsigned int dml_get_tile_block_size_bytes(enum dml2_swizzle_mode sw_mode
|
||||
{
|
||||
switch (sw_mode) {
|
||||
case (dml2_sw_linear):
|
||||
return 256; break;
|
||||
return 256;
|
||||
case (dml2_sw_256b_2d):
|
||||
return 256; break;
|
||||
return 256;
|
||||
case (dml2_sw_4kb_2d):
|
||||
return 4096; break;
|
||||
return 4096;
|
||||
case (dml2_sw_64kb_2d):
|
||||
return 65536; break;
|
||||
return 65536;
|
||||
case (dml2_sw_256kb_2d):
|
||||
return 262144; break;
|
||||
return 262144;
|
||||
case (dml2_gfx11_sw_linear):
|
||||
return 256; break;
|
||||
return 256;
|
||||
case (dml2_gfx11_sw_64kb_d):
|
||||
return 65536; break;
|
||||
return 65536;
|
||||
case (dml2_gfx11_sw_64kb_d_t):
|
||||
return 65536; break;
|
||||
return 65536;
|
||||
case (dml2_gfx11_sw_64kb_d_x):
|
||||
return 65536; break;
|
||||
return 65536;
|
||||
case (dml2_gfx11_sw_64kb_r_x):
|
||||
return 65536; break;
|
||||
return 65536;
|
||||
case (dml2_gfx11_sw_256kb_d_x):
|
||||
return 262144; break;
|
||||
return 262144;
|
||||
case (dml2_gfx11_sw_256kb_r_x):
|
||||
return 262144; break;
|
||||
return 262144;
|
||||
default:
|
||||
DML2_ASSERT(0);
|
||||
return 256;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const char *dml2_core_internal_bw_type_str(enum dml2_core_internal_bw_type bw_type)
|
||||
{
|
||||
switch (bw_type) {
|
||||
case (dml2_core_internal_bw_sdp):
|
||||
return("dml2_core_internal_bw_sdp"); break;
|
||||
return("dml2_core_internal_bw_sdp");
|
||||
case (dml2_core_internal_bw_dram):
|
||||
return("dml2_core_internal_bw_dram"); break;
|
||||
return("dml2_core_internal_bw_dram");
|
||||
case (dml2_core_internal_bw_max):
|
||||
return("dml2_core_internal_bw_max"); break;
|
||||
return("dml2_core_internal_bw_max");
|
||||
default:
|
||||
return("dml2_core_internal_bw_unknown"); break;
|
||||
};
|
||||
return("dml2_core_internal_bw_unknown");
|
||||
}
|
||||
}
|
||||
|
||||
const char *dml2_core_internal_soc_state_type_str(enum dml2_core_internal_soc_state_type dml2_core_internal_soc_state_type)
|
||||
{
|
||||
switch (dml2_core_internal_soc_state_type) {
|
||||
case (dml2_core_internal_soc_state_sys_idle):
|
||||
return("dml2_core_internal_soc_state_sys_idle"); break;
|
||||
return("dml2_core_internal_soc_state_sys_idle");
|
||||
case (dml2_core_internal_soc_state_sys_active):
|
||||
return("dml2_core_internal_soc_state_sys_active"); break;
|
||||
return("dml2_core_internal_soc_state_sys_active");
|
||||
case (dml2_core_internal_soc_state_svp_prefetch):
|
||||
return("dml2_core_internal_soc_state_svp_prefetch"); break;
|
||||
return("dml2_core_internal_soc_state_svp_prefetch");
|
||||
case dml2_core_internal_soc_state_max:
|
||||
default:
|
||||
return("dml2_core_internal_soc_state_unknown"); break;
|
||||
};
|
||||
return("dml2_core_internal_soc_state_unknown");
|
||||
}
|
||||
}
|
||||
|
||||
static bool dml_is_vertical_rotation(enum dml2_rotation_angle Scan)
|
||||
|
||||
@@ -1163,7 +1163,6 @@ static bool is_config_schedulable(
|
||||
schedulable = true;
|
||||
|
||||
/* sort disallow times from greatest to least */
|
||||
unsigned int temp;
|
||||
for (i = 0; i < s->pmo_dcn4.num_timing_groups; i++) {
|
||||
bool swapped = false;
|
||||
|
||||
@@ -1172,9 +1171,8 @@ static bool is_config_schedulable(
|
||||
double jp1_disallow_us = s->pmo_dcn4.group_common_fams2_meta[s->pmo_dcn4.sorted_group_gtl_disallow_index[j + 1]].disallow_time_us;
|
||||
if (j_disallow_us < jp1_disallow_us) {
|
||||
/* swap as A < B */
|
||||
temp = s->pmo_dcn4.sorted_group_gtl_disallow_index[j];
|
||||
s->pmo_dcn4.sorted_group_gtl_disallow_index[j] = s->pmo_dcn4.sorted_group_gtl_disallow_index[j + 1];
|
||||
s->pmo_dcn4.sorted_group_gtl_disallow_index[j + 1] = temp;
|
||||
swap(s->pmo_dcn4.sorted_group_gtl_disallow_index[j],
|
||||
s->pmo_dcn4.sorted_group_gtl_disallow_index[j+1]);
|
||||
swapped = true;
|
||||
}
|
||||
}
|
||||
@@ -1232,9 +1230,8 @@ static bool is_config_schedulable(
|
||||
double jp1_period_us = s->pmo_dcn4.group_common_fams2_meta[s->pmo_dcn4.sorted_group_gtl_period_index[j + 1]].period_us;
|
||||
if (j_period_us < jp1_period_us) {
|
||||
/* swap as A < B */
|
||||
temp = s->pmo_dcn4.sorted_group_gtl_period_index[j];
|
||||
s->pmo_dcn4.sorted_group_gtl_period_index[j] = s->pmo_dcn4.sorted_group_gtl_period_index[j + 1];
|
||||
s->pmo_dcn4.sorted_group_gtl_period_index[j + 1] = temp;
|
||||
swap(s->pmo_dcn4.sorted_group_gtl_period_index[j],
|
||||
s->pmo_dcn4.sorted_group_gtl_period_index[j+1]);
|
||||
swapped = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,10 +96,15 @@ bool dml2_check_mode_supported(struct dml2_check_mode_supported_in_out *in_out)
|
||||
{
|
||||
struct dml2_instance *dml = (struct dml2_instance *)in_out->dml2_instance;
|
||||
struct dml2_check_mode_supported_locals *l = &dml->scratch.check_mode_supported_locals;
|
||||
/* Borrow the build_mode_programming_locals programming struct for DPMM call. */
|
||||
struct dml2_display_cfg_programming *dpmm_programming = dml->scratch.build_mode_programming_locals.mode_programming_params.programming;
|
||||
|
||||
bool result = false;
|
||||
bool mcache_success = false;
|
||||
|
||||
if (dpmm_programming)
|
||||
memset(dpmm_programming, 0, sizeof(struct dml2_display_cfg_programming));
|
||||
|
||||
setup_unoptimized_display_config_with_meta(dml, &l->base_display_config_with_meta, in_out->display_config);
|
||||
|
||||
l->mode_support_params.instance = &dml->core_instance;
|
||||
@@ -122,6 +127,18 @@ bool dml2_check_mode_supported(struct dml2_check_mode_supported_in_out *in_out)
|
||||
mcache_success = dml2_top_optimization_perform_optimization_phase(&l->optimization_phase_locals, &mcache_phase);
|
||||
}
|
||||
|
||||
/*
|
||||
* Call DPMM to map all requirements to minimum clock state
|
||||
*/
|
||||
if (result && dpmm_programming) {
|
||||
l->dppm_map_mode_params.min_clk_table = &dml->min_clk_table;
|
||||
l->dppm_map_mode_params.display_cfg = &l->base_display_config_with_meta;
|
||||
l->dppm_map_mode_params.programming = dpmm_programming;
|
||||
l->dppm_map_mode_params.soc_bb = &dml->soc_bbox;
|
||||
l->dppm_map_mode_params.ip = &dml->core_instance.clean_me_up.mode_lib.ip;
|
||||
result = dml->dpmm_instance.map_mode_to_soc_dpm(&l->dppm_map_mode_params);
|
||||
}
|
||||
|
||||
in_out->is_supported = mcache_success;
|
||||
result = result && in_out->is_supported;
|
||||
|
||||
|
||||
@@ -870,6 +870,7 @@ struct dml2_check_mode_supported_locals {
|
||||
struct dml2_optimization_phase_locals optimization_phase_locals;
|
||||
struct display_configuation_with_meta base_display_config_with_meta;
|
||||
struct display_configuation_with_meta optimized_display_config_with_meta;
|
||||
struct dml2_dpmm_map_mode_to_soc_dpm_params_in_out dppm_map_mode_params;
|
||||
};
|
||||
|
||||
struct optimization_init_function_params {
|
||||
|
||||
@@ -750,6 +750,8 @@ static void enable_phantom_plane(struct dml2_context *ctx,
|
||||
ctx->config.svp_pstate.callbacks.dc,
|
||||
state,
|
||||
curr_pipe->plane_state);
|
||||
if (!phantom_plane)
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(&phantom_plane->address, &curr_pipe->plane_state->address, sizeof(phantom_plane->address));
|
||||
|
||||
@@ -442,7 +442,6 @@ static bool optimize_pstate_with_svp_and_drr(struct dml2_context *dml2, struct d
|
||||
bool result = false;
|
||||
int drr_display_index = 0, non_svp_streams = 0;
|
||||
bool force_svp = dml2->config.svp_pstate.force_enable_subvp;
|
||||
bool advanced_pstate_switching = false;
|
||||
|
||||
display_state->bw_ctx.bw.dcn.clk.fw_based_mclk_switching = false;
|
||||
display_state->bw_ctx.bw.dcn.legacy_svp_drr_stream_index_valid = false;
|
||||
@@ -451,8 +450,7 @@ static bool optimize_pstate_with_svp_and_drr(struct dml2_context *dml2, struct d
|
||||
|
||||
if (!result) {
|
||||
pstate_optimization_done = true;
|
||||
} else if (!advanced_pstate_switching ||
|
||||
(s->mode_support_info.DRAMClockChangeSupport[0] != dml_dram_clock_change_unsupported && !force_svp)) {
|
||||
} else if (s->mode_support_info.DRAMClockChangeSupport[0] != dml_dram_clock_change_unsupported && !force_svp) {
|
||||
pstate_optimization_success = true;
|
||||
pstate_optimization_done = true;
|
||||
}
|
||||
@@ -628,6 +626,21 @@ static bool dml2_validate_and_build_resource(const struct dc *in_dc, struct dc_s
|
||||
|
||||
if (result) {
|
||||
unsigned int lowest_state_idx = s->mode_support_params.out_lowest_state_idx;
|
||||
double min_fclk_mhz_for_urgent_workaround = (double)dml2->config.min_fclk_for_urgent_workaround_khz / 1000.0;
|
||||
double max_frac_urgent = (double)dml2->config.max_frac_urgent_for_min_fclk_x1000 / 1000.0;
|
||||
|
||||
if (min_fclk_mhz_for_urgent_workaround > 0.0 && max_frac_urgent > 0.0 &&
|
||||
(dml2->v20.dml_core_ctx.mp.FractionOfUrgentBandwidth > max_frac_urgent ||
|
||||
dml2->v20.dml_core_ctx.mp.FractionOfUrgentBandwidthImmediateFlip > max_frac_urgent)) {
|
||||
unsigned int forced_lowest_state_idx = lowest_state_idx;
|
||||
|
||||
while (forced_lowest_state_idx < dml2->v20.dml_core_ctx.states.num_states &&
|
||||
dml2->v20.dml_core_ctx.states.state_array[forced_lowest_state_idx].fabricclk_mhz <= min_fclk_mhz_for_urgent_workaround) {
|
||||
forced_lowest_state_idx += 1;
|
||||
}
|
||||
lowest_state_idx = forced_lowest_state_idx;
|
||||
}
|
||||
|
||||
out_clks.dispclk_khz = (unsigned int)dml2->v20.dml_core_ctx.mp.Dispclk_calculated * 1000;
|
||||
out_clks.p_state_supported = s->mode_support_info.DRAMClockChangeSupport[0] != dml_dram_clock_change_unsupported;
|
||||
if (in_dc->config.use_default_clock_table &&
|
||||
@@ -672,12 +685,14 @@ static bool dml2_validate_and_build_resource(const struct dc *in_dc, struct dc_s
|
||||
|
||||
static bool dml2_validate_only(struct dc_state *context)
|
||||
{
|
||||
struct dml2_context *dml2 = context->bw_ctx.dml2;
|
||||
struct dml2_context *dml2;
|
||||
unsigned int result = 0;
|
||||
|
||||
if (!context || context->stream_count == 0)
|
||||
return true;
|
||||
|
||||
dml2 = context->bw_ctx.dml2;
|
||||
|
||||
/* Zero out before each call before proceeding */
|
||||
memset(&dml2->v20.scratch, 0, sizeof(struct dml2_wrapper_scratch));
|
||||
memset(&dml2->v20.dml_core_ctx.policy, 0, sizeof(struct dml_mode_eval_policy_st));
|
||||
@@ -806,6 +821,12 @@ void dml2_extract_dram_and_fclk_change_support(struct dml2_context *dml2,
|
||||
*dram_clk_change_support = (unsigned int) dml2->v20.dml_core_ctx.ms.support.DRAMClockChangeSupport[0];
|
||||
}
|
||||
|
||||
void dml2_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context, struct dml2_context *dml2)
|
||||
{
|
||||
if (dml2->architecture == dml2_architecture_21)
|
||||
dml21_prepare_mcache_programming(in_dc, context, dml2);
|
||||
}
|
||||
|
||||
void dml2_copy(struct dml2_context *dst_dml2,
|
||||
struct dml2_context *src_dml2)
|
||||
{
|
||||
|
||||
@@ -230,13 +230,15 @@ struct dml2_configuration_options {
|
||||
struct socbb_ip_params_external *external_socbb_ip_params;
|
||||
struct {
|
||||
bool force_pstate_method_enable;
|
||||
enum dml2_force_pstate_methods force_pstate_method_value;
|
||||
enum dml2_force_pstate_methods force_pstate_method_values[MAX_PIPES];
|
||||
} pmo;
|
||||
bool map_dc_pipes_with_callbacks;
|
||||
|
||||
bool use_clock_dc_limits;
|
||||
bool gpuvm_enable;
|
||||
struct dml2_soc_bb *bb_from_dmub;
|
||||
int max_frac_urgent_for_min_fclk_x1000;
|
||||
int min_fclk_for_urgent_workaround_khz;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -301,5 +303,5 @@ bool dml2_validate(const struct dc *in_dc,
|
||||
*/
|
||||
void dml2_extract_dram_and_fclk_change_support(struct dml2_context *dml2,
|
||||
unsigned int *fclk_change_support, unsigned int *dram_clk_change_support);
|
||||
|
||||
void dml2_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context, struct dml2_context *dml2);
|
||||
#endif //_DML2_WRAPPER_H_
|
||||
|
||||
@@ -153,58 +153,8 @@ void dpp401_set_cursor_position(
|
||||
uint32_t height)
|
||||
{
|
||||
struct dcn401_dpp *dpp = TO_DCN401_DPP(dpp_base);
|
||||
int x_pos = pos->x - param->recout.x;
|
||||
int y_pos = pos->y - param->recout.y;
|
||||
int x_hotspot = pos->x_hotspot;
|
||||
int y_hotspot = pos->y_hotspot;
|
||||
int rec_x_offset = x_pos - pos->x_hotspot;
|
||||
int rec_y_offset = y_pos - pos->y_hotspot;
|
||||
int cursor_height = (int)height;
|
||||
int cursor_width = (int)width;
|
||||
uint32_t cur_en = pos->enable ? 1 : 0;
|
||||
|
||||
// Transform cursor width / height and hotspots for offset calculations
|
||||
if (param->rotation == ROTATION_ANGLE_90 || param->rotation == ROTATION_ANGLE_270) {
|
||||
swap(cursor_height, cursor_width);
|
||||
swap(x_hotspot, y_hotspot);
|
||||
|
||||
if (param->rotation == ROTATION_ANGLE_90) {
|
||||
// hotspot = (-y, x)
|
||||
rec_x_offset = x_pos - (cursor_width - x_hotspot);
|
||||
rec_y_offset = y_pos - y_hotspot;
|
||||
} else if (param->rotation == ROTATION_ANGLE_270) {
|
||||
// hotspot = (y, -x)
|
||||
rec_x_offset = x_pos - x_hotspot;
|
||||
rec_y_offset = y_pos - (cursor_height - y_hotspot);
|
||||
}
|
||||
} else if (param->rotation == ROTATION_ANGLE_180) {
|
||||
// hotspot = (-x, -y)
|
||||
if (!param->mirror)
|
||||
rec_x_offset = x_pos - (cursor_width - x_hotspot);
|
||||
|
||||
rec_y_offset = y_pos - (cursor_height - y_hotspot);
|
||||
}
|
||||
|
||||
if (param->rotation == ROTATION_ANGLE_0 && !param->mirror) {
|
||||
if (rec_x_offset >= (int)param->recout.width)
|
||||
cur_en = 0; /* not visible beyond right edge*/
|
||||
|
||||
if (rec_y_offset >= (int)param->recout.height)
|
||||
cur_en = 0; /* not visible beyond bottom edge*/
|
||||
} else {
|
||||
if (rec_x_offset > (int)param->recout.width)
|
||||
cur_en = 0; /* not visible beyond right edge*/
|
||||
|
||||
if (rec_y_offset > (int)param->recout.height)
|
||||
cur_en = 0; /* not visible beyond bottom edge*/
|
||||
}
|
||||
|
||||
if (rec_x_offset + cursor_width <= 0)
|
||||
cur_en = 0; /* not visible beyond left edge*/
|
||||
|
||||
if (rec_y_offset + cursor_height <= 0)
|
||||
cur_en = 0; /* not visible beyond top edge*/
|
||||
|
||||
REG_UPDATE(CURSOR0_CONTROL, CUR0_ENABLE, cur_en);
|
||||
|
||||
dpp_base->pos.cur0_ctl.bits.cur0_enable = cur_en;
|
||||
|
||||
@@ -32,16 +32,6 @@
|
||||
|
||||
static void dsc_write_to_registers(struct display_stream_compressor *dsc, const struct dsc_reg_values *reg_vals);
|
||||
|
||||
/* Object I/F functions */
|
||||
static void dsc2_read_state(struct display_stream_compressor *dsc, struct dcn_dsc_state *s);
|
||||
static bool dsc2_validate_stream(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg);
|
||||
static void dsc2_set_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
|
||||
struct dsc_optc_config *dsc_optc_cfg);
|
||||
static void dsc2_enable(struct display_stream_compressor *dsc, int opp_pipe);
|
||||
static void dsc2_disable(struct display_stream_compressor *dsc);
|
||||
static void dsc2_disconnect(struct display_stream_compressor *dsc);
|
||||
static void dsc2_wait_disconnect_pending_clear(struct display_stream_compressor *dsc);
|
||||
|
||||
static const struct dsc_funcs dcn20_dsc_funcs = {
|
||||
.dsc_get_enc_caps = dsc2_get_enc_caps,
|
||||
.dsc_read_state = dsc2_read_state,
|
||||
@@ -156,7 +146,7 @@ void dsc2_get_enc_caps(struct dsc_enc_caps *dsc_enc_caps, int pixel_clock_100Hz)
|
||||
/* this function read dsc related register fields to be logged later in dcn10_log_hw_state
|
||||
* into a dcn_dsc_state struct.
|
||||
*/
|
||||
static void dsc2_read_state(struct display_stream_compressor *dsc, struct dcn_dsc_state *s)
|
||||
void dsc2_read_state(struct display_stream_compressor *dsc, struct dcn_dsc_state *s)
|
||||
{
|
||||
struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc);
|
||||
|
||||
@@ -173,7 +163,7 @@ static void dsc2_read_state(struct display_stream_compressor *dsc, struct dcn_ds
|
||||
}
|
||||
|
||||
|
||||
static bool dsc2_validate_stream(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg)
|
||||
bool dsc2_validate_stream(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg)
|
||||
{
|
||||
struct dsc_optc_config dsc_optc_cfg;
|
||||
struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc);
|
||||
@@ -196,7 +186,7 @@ void dsc_config_log(struct display_stream_compressor *dsc, const struct dsc_conf
|
||||
DC_LOG_DSC("\tcolor_depth %d", config->color_depth);
|
||||
}
|
||||
|
||||
static void dsc2_set_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
|
||||
void dsc2_set_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
|
||||
struct dsc_optc_config *dsc_optc_cfg)
|
||||
{
|
||||
bool is_config_ok;
|
||||
@@ -233,7 +223,7 @@ bool dsc2_get_packed_pps(struct display_stream_compressor *dsc, const struct dsc
|
||||
}
|
||||
|
||||
|
||||
static void dsc2_enable(struct display_stream_compressor *dsc, int opp_pipe)
|
||||
void dsc2_enable(struct display_stream_compressor *dsc, int opp_pipe)
|
||||
{
|
||||
struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc);
|
||||
int dsc_clock_en;
|
||||
@@ -258,7 +248,7 @@ static void dsc2_enable(struct display_stream_compressor *dsc, int opp_pipe)
|
||||
}
|
||||
|
||||
|
||||
static void dsc2_disable(struct display_stream_compressor *dsc)
|
||||
void dsc2_disable(struct display_stream_compressor *dsc)
|
||||
{
|
||||
struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc);
|
||||
int dsc_clock_en;
|
||||
@@ -277,14 +267,14 @@ static void dsc2_disable(struct display_stream_compressor *dsc)
|
||||
DSC_CLOCK_EN, 0);
|
||||
}
|
||||
|
||||
static void dsc2_wait_disconnect_pending_clear(struct display_stream_compressor *dsc)
|
||||
void dsc2_wait_disconnect_pending_clear(struct display_stream_compressor *dsc)
|
||||
{
|
||||
struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc);
|
||||
|
||||
REG_WAIT(DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_DOUBLE_BUFFER_REG_UPDATE_PENDING, 0, 2, 50000);
|
||||
}
|
||||
|
||||
static void dsc2_disconnect(struct display_stream_compressor *dsc)
|
||||
void dsc2_disconnect(struct display_stream_compressor *dsc)
|
||||
{
|
||||
struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc);
|
||||
|
||||
|
||||
@@ -454,7 +454,9 @@
|
||||
type DSCCIF_UPDATE_TAKEN_ACK; \
|
||||
type DSCRM_DSC_FORWARD_EN; \
|
||||
type DSCRM_DSC_OPP_PIPE_SOURCE; \
|
||||
type DSCRM_DSC_DOUBLE_BUFFER_REG_UPDATE_PENDING
|
||||
type DSCRM_DSC_DOUBLE_BUFFER_REG_UPDATE_PENDING; \
|
||||
type DSCRM_DSC_FORWARD_EN_STATUS
|
||||
|
||||
|
||||
struct dcn20_dsc_registers {
|
||||
uint32_t DSC_TOP_CONTROL;
|
||||
@@ -597,5 +599,14 @@ bool dsc2_get_packed_pps(struct display_stream_compressor *dsc,
|
||||
const struct dsc_config *dsc_cfg,
|
||||
uint8_t *dsc_packed_pps);
|
||||
|
||||
void dsc2_read_state(struct display_stream_compressor *dsc, struct dcn_dsc_state *s);
|
||||
bool dsc2_validate_stream(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg);
|
||||
void dsc2_set_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg,
|
||||
struct dsc_optc_config *dsc_optc_cfg);
|
||||
void dsc2_enable(struct display_stream_compressor *dsc, int opp_pipe);
|
||||
void dsc2_disable(struct display_stream_compressor *dsc);
|
||||
void dsc2_disconnect(struct display_stream_compressor *dsc);
|
||||
void dsc2_wait_disconnect_pending_clear(struct display_stream_compressor *dsc);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -27,6 +27,20 @@
|
||||
#include "dcn35_dsc.h"
|
||||
#include "reg_helper.h"
|
||||
|
||||
static void dsc35_enable(struct display_stream_compressor *dsc, int opp_pipe);
|
||||
|
||||
static const struct dsc_funcs dcn35_dsc_funcs = {
|
||||
.dsc_get_enc_caps = dsc2_get_enc_caps,
|
||||
.dsc_read_state = dsc2_read_state,
|
||||
.dsc_validate_stream = dsc2_validate_stream,
|
||||
.dsc_set_config = dsc2_set_config,
|
||||
.dsc_get_packed_pps = dsc2_get_packed_pps,
|
||||
.dsc_enable = dsc35_enable,
|
||||
.dsc_disable = dsc2_disable,
|
||||
.dsc_disconnect = dsc2_disconnect,
|
||||
.dsc_wait_disconnect_pending_clear = dsc2_wait_disconnect_pending_clear,
|
||||
};
|
||||
|
||||
/* Macro definitios for REG_SET macros*/
|
||||
#define CTX \
|
||||
dsc20->base.ctx
|
||||
@@ -49,9 +63,47 @@ void dsc35_construct(struct dcn20_dsc *dsc,
|
||||
const struct dcn35_dsc_shift *dsc_shift,
|
||||
const struct dcn35_dsc_mask *dsc_mask)
|
||||
{
|
||||
dsc2_construct(dsc, ctx, inst, dsc_regs,
|
||||
(const struct dcn20_dsc_shift *)(dsc_shift),
|
||||
(const struct dcn20_dsc_mask *)(dsc_mask));
|
||||
dsc->base.ctx = ctx;
|
||||
dsc->base.inst = inst;
|
||||
dsc->base.funcs = &dcn35_dsc_funcs;
|
||||
|
||||
dsc->dsc_regs = dsc_regs;
|
||||
dsc->dsc_shift = (const struct dcn20_dsc_shift *)(dsc_shift);
|
||||
dsc->dsc_mask = (const struct dcn20_dsc_mask *)(dsc_mask);
|
||||
|
||||
dsc->max_image_width = 5184;
|
||||
}
|
||||
|
||||
static void dsc35_enable(struct display_stream_compressor *dsc, int opp_pipe)
|
||||
{
|
||||
struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc);
|
||||
int dsc_clock_en;
|
||||
int dsc_fw_config;
|
||||
int enabled_opp_pipe;
|
||||
|
||||
DC_LOG_DSC("enable DSC %d at opp pipe %d", dsc->inst, opp_pipe);
|
||||
|
||||
// TODO: After an idle exit, the HW default values for power control
|
||||
// are changed intermittently due to unknown reasons. There are cases
|
||||
// when dscc memory are still in shutdown state during enablement.
|
||||
// Reset power control to hw default values.
|
||||
REG_UPDATE_2(DSCC_MEM_POWER_CONTROL,
|
||||
DSCC_MEM_PWR_FORCE, 0,
|
||||
DSCC_MEM_PWR_DIS, 0);
|
||||
|
||||
REG_GET(DSC_TOP_CONTROL, DSC_CLOCK_EN, &dsc_clock_en);
|
||||
REG_GET_2(DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_FORWARD_EN, &dsc_fw_config, DSCRM_DSC_OPP_PIPE_SOURCE, &enabled_opp_pipe);
|
||||
if ((dsc_clock_en || dsc_fw_config) && enabled_opp_pipe != opp_pipe) {
|
||||
DC_LOG_DSC("ERROR: DSC %d at opp pipe %d already enabled!", dsc->inst, enabled_opp_pipe);
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
REG_UPDATE(DSC_TOP_CONTROL,
|
||||
DSC_CLOCK_EN, 1);
|
||||
|
||||
REG_UPDATE_2(DSCRM_DSC_FORWARD_CONFIG,
|
||||
DSCRM_DSC_FORWARD_EN, 1,
|
||||
DSCRM_DSC_OPP_PIPE_SOURCE, opp_pipe);
|
||||
}
|
||||
|
||||
void dsc35_set_fgcg(struct dcn20_dsc *dsc20, bool enable)
|
||||
|
||||
@@ -208,7 +208,7 @@ static void dsc401_wait_disconnect_pending_clear(struct display_stream_compresso
|
||||
{
|
||||
struct dcn401_dsc *dsc401 = TO_DCN401_DSC(dsc);
|
||||
|
||||
REG_WAIT(DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_DOUBLE_BUFFER_REG_UPDATE_PENDING, 0, 2, 50000);
|
||||
REG_WAIT(DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_FORWARD_EN_STATUS, 0, 2, 50000);
|
||||
}
|
||||
|
||||
static void dsc401_disconnect(struct display_stream_compressor *dsc)
|
||||
|
||||
@@ -196,7 +196,8 @@
|
||||
DSC2_SF(DSCCIF0, DSCCIF_CONFIG0__BITS_PER_COMPONENT, mask_sh), \
|
||||
DSC_SF(DSCCIF0_DSCCIF_CONFIG0, DOUBLE_BUFFER_REG_UPDATE_PENDING, mask_sh), \
|
||||
DSC_SF(DSCRM0_DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_FORWARD_EN, mask_sh), \
|
||||
DSC_SF(DSCRM0_DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_OPP_PIPE_SOURCE, mask_sh)
|
||||
DSC_SF(DSCRM0_DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_OPP_PIPE_SOURCE, mask_sh), \
|
||||
DSC_SF(DSCRM0_DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_FORWARD_EN_STATUS, mask_sh)
|
||||
|
||||
struct dcn401_dsc_registers {
|
||||
uint32_t DSC_TOP_CONTROL;
|
||||
|
||||
@@ -616,7 +616,8 @@ static bool hubbub2_program_watermarks(
|
||||
hubbub1->base.ctx->dc->clk_mgr->clks.p_state_change_support == false)
|
||||
safe_to_lower = true;
|
||||
|
||||
hubbub1_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower);
|
||||
if (hubbub1_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))
|
||||
wm_pending = true;
|
||||
|
||||
REG_SET(DCHUBBUB_ARB_SAT_LEVEL, 0,
|
||||
DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz);
|
||||
|
||||
@@ -339,6 +339,7 @@ bool hubbub3_get_dcc_compression_cap(struct hubbub *hubbub,
|
||||
return false;
|
||||
|
||||
switch (dcc_control) {
|
||||
case dcc_control__256_256:
|
||||
case dcc_control__256_256_xxx:
|
||||
output->grph.rgb.max_uncompressed_blk_size = 256;
|
||||
output->grph.rgb.max_compressed_blk_size = 256;
|
||||
@@ -346,6 +347,7 @@ bool hubbub3_get_dcc_compression_cap(struct hubbub *hubbub,
|
||||
output->grph.rgb.dcc_controls.dcc_256_256_unconstrained = 1;
|
||||
output->grph.rgb.dcc_controls.dcc_256_128_128 = 1;
|
||||
break;
|
||||
case dcc_control__256_128:
|
||||
case dcc_control__128_128_xxx:
|
||||
output->grph.rgb.max_uncompressed_blk_size = 128;
|
||||
output->grph.rgb.max_compressed_blk_size = 128;
|
||||
@@ -353,6 +355,7 @@ bool hubbub3_get_dcc_compression_cap(struct hubbub *hubbub,
|
||||
output->grph.rgb.dcc_controls.dcc_128_128_uncontrained = 1;
|
||||
output->grph.rgb.dcc_controls.dcc_256_128_128 = 1;
|
||||
break;
|
||||
case dcc_control__256_64:
|
||||
case dcc_control__256_64_64:
|
||||
output->grph.rgb.max_uncompressed_blk_size = 256;
|
||||
output->grph.rgb.max_compressed_blk_size = 64;
|
||||
|
||||
@@ -866,6 +866,7 @@ static bool hubbub31_get_dcc_compression_cap(struct hubbub *hubbub,
|
||||
return false;
|
||||
|
||||
switch (dcc_control) {
|
||||
case dcc_control__256_256:
|
||||
case dcc_control__256_256_xxx:
|
||||
output->grph.rgb.max_uncompressed_blk_size = 256;
|
||||
output->grph.rgb.max_compressed_blk_size = 256;
|
||||
@@ -881,12 +882,14 @@ static bool hubbub31_get_dcc_compression_cap(struct hubbub *hubbub,
|
||||
output->grph.rgb.dcc_controls.dcc_256_128_128 = 1;
|
||||
break;
|
||||
case dcc_control__256_64_64:
|
||||
case dcc_control__256_64:
|
||||
output->grph.rgb.max_uncompressed_blk_size = 256;
|
||||
output->grph.rgb.max_compressed_blk_size = 64;
|
||||
output->grph.rgb.independent_64b_blks = true;
|
||||
output->grph.rgb.dcc_controls.dcc_256_64_64 = 1;
|
||||
break;
|
||||
case dcc_control__256_128_128:
|
||||
case dcc_control__256_128:
|
||||
output->grph.rgb.max_uncompressed_blk_size = 256;
|
||||
output->grph.rgb.max_compressed_blk_size = 128;
|
||||
output->grph.rgb.independent_64b_blks = false;
|
||||
|
||||
@@ -824,6 +824,285 @@ void hubbub401_det_request_size(
|
||||
}
|
||||
}
|
||||
}
|
||||
bool hubbub401_get_dcc_compression_cap(struct hubbub *hubbub,
|
||||
const struct dc_dcc_surface_param *input,
|
||||
struct dc_surface_dcc_cap *output)
|
||||
{
|
||||
struct dc *dc = hubbub->ctx->dc;
|
||||
/* DCN4_Programming_Guide_DCHUB.docx, Section 5.11.2.2 */
|
||||
enum dcc_control dcc_control;
|
||||
unsigned int plane0_bpe, plane1_bpe;
|
||||
enum segment_order segment_order_horz, segment_order_vert;
|
||||
enum segment_order p1_segment_order_horz, p1_segment_order_vert;
|
||||
bool req128_horz_wc, req128_vert_wc;
|
||||
unsigned int plane0_width = 0, plane0_height = 0, plane1_width = 0, plane1_height = 0;
|
||||
bool p1_req128_horz_wc, p1_req128_vert_wc, is_dual_plane;
|
||||
|
||||
memset(output, 0, sizeof(*output));
|
||||
|
||||
if (dc->debug.disable_dcc == DCC_DISABLE)
|
||||
return false;
|
||||
|
||||
switch (input->format) {
|
||||
default:
|
||||
is_dual_plane = false;
|
||||
|
||||
plane1_width = 0;
|
||||
plane1_height = 0;
|
||||
|
||||
if (input->surface_size.width > 6144 + 16)
|
||||
plane0_width = 6160;
|
||||
else
|
||||
plane0_width = input->surface_size.width;
|
||||
|
||||
if (input->surface_size.height > 6144 + 16)
|
||||
plane0_height = 6160;
|
||||
else
|
||||
plane0_height = input->surface_size.height;
|
||||
|
||||
break;
|
||||
case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
|
||||
case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
|
||||
case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
|
||||
case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
|
||||
is_dual_plane = true;
|
||||
|
||||
if (input->surface_size.width > 7680 + 16)
|
||||
plane0_width = 7696;
|
||||
else
|
||||
plane0_width = input->surface_size.width;
|
||||
|
||||
if (input->surface_size.height > 4320 + 16)
|
||||
plane0_height = 4336;
|
||||
else
|
||||
plane0_height = input->surface_size.height;
|
||||
|
||||
if (input->plane1_size.width > 7680 + 16)
|
||||
plane1_width = 7696 / 2;
|
||||
else
|
||||
plane1_width = input->plane1_size.width;
|
||||
|
||||
if (input->plane1_size.height > 4320 + 16)
|
||||
plane1_height = 4336 / 2;
|
||||
else
|
||||
plane1_height = input->plane1_size.height;
|
||||
|
||||
break;
|
||||
|
||||
case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA:
|
||||
is_dual_plane = true;
|
||||
|
||||
if (input->surface_size.width > 5120 + 16)
|
||||
plane0_width = 5136;
|
||||
else
|
||||
plane0_width = input->surface_size.width;
|
||||
|
||||
if (input->surface_size.height > 5120 + 16)
|
||||
plane0_height = 5136;
|
||||
else
|
||||
plane0_height = input->surface_size.height;
|
||||
|
||||
if (input->plane1_size.width > 5120 + 16)
|
||||
plane1_width = 5136;
|
||||
else
|
||||
plane1_width = input->plane1_size.width;
|
||||
|
||||
if (input->plane1_size.height > 5120 + 16)
|
||||
plane1_height = 5136;
|
||||
else
|
||||
plane1_height = input->plane1_size.height;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!hubbub->funcs->dcc_support_pixel_format_plane0_plane1(input->format,
|
||||
&plane0_bpe, &plane1_bpe))
|
||||
return false;
|
||||
|
||||
/* Find plane0 DCC Controls */
|
||||
if (!is_dual_plane) {
|
||||
|
||||
if (!hubbub->funcs->dcc_support_swizzle_addr3(input->swizzle_mode_addr3,
|
||||
input->plane0_pitch, plane0_bpe,
|
||||
&segment_order_horz, &segment_order_vert))
|
||||
return false;
|
||||
|
||||
hubbub401_det_request_size(TO_DCN20_HUBBUB(hubbub)->detile_buf_size, input->format,
|
||||
plane0_height, plane0_width, plane0_bpe,
|
||||
plane1_height, plane1_width, plane1_bpe,
|
||||
&req128_horz_wc, &req128_vert_wc, &p1_req128_horz_wc, &p1_req128_vert_wc);
|
||||
|
||||
if (!req128_horz_wc && !req128_vert_wc) {
|
||||
dcc_control = dcc_control__256_256;
|
||||
} else if (input->scan == SCAN_DIRECTION_HORIZONTAL) {
|
||||
if (!req128_horz_wc)
|
||||
dcc_control = dcc_control__256_256;
|
||||
else if (segment_order_horz == segment_order__contiguous)
|
||||
dcc_control = dcc_control__256_128;
|
||||
else
|
||||
dcc_control = dcc_control__256_64;
|
||||
} else if (input->scan == SCAN_DIRECTION_VERTICAL) {
|
||||
if (!req128_vert_wc)
|
||||
dcc_control = dcc_control__256_256;
|
||||
else if (segment_order_vert == segment_order__contiguous)
|
||||
dcc_control = dcc_control__256_128;
|
||||
else
|
||||
dcc_control = dcc_control__256_64;
|
||||
} else {
|
||||
if ((req128_horz_wc &&
|
||||
segment_order_horz == segment_order__non_contiguous) ||
|
||||
(req128_vert_wc &&
|
||||
segment_order_vert == segment_order__non_contiguous))
|
||||
/* access_dir not known, must use most constraining */
|
||||
dcc_control = dcc_control__256_64;
|
||||
else
|
||||
/* req128 is true for either horz and vert
|
||||
* but segment_order is contiguous
|
||||
*/
|
||||
dcc_control = dcc_control__256_128;
|
||||
}
|
||||
|
||||
if (dc->debug.disable_dcc == DCC_HALF_REQ_DISALBE &&
|
||||
dcc_control != dcc_control__256_256)
|
||||
return false;
|
||||
|
||||
switch (dcc_control) {
|
||||
case dcc_control__256_256:
|
||||
output->grph.rgb.dcc_controls.dcc_256_256 = 1;
|
||||
output->grph.rgb.dcc_controls.dcc_256_128 = 1;
|
||||
output->grph.rgb.dcc_controls.dcc_256_64 = 1;
|
||||
break;
|
||||
case dcc_control__256_128:
|
||||
output->grph.rgb.dcc_controls.dcc_256_128 = 1;
|
||||
output->grph.rgb.dcc_controls.dcc_256_64 = 1;
|
||||
break;
|
||||
case dcc_control__256_64:
|
||||
output->grph.rgb.dcc_controls.dcc_256_64 = 1;
|
||||
break;
|
||||
default:
|
||||
/* Shouldn't get here */
|
||||
ASSERT(0);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* For dual plane cases, need to examine both planes together */
|
||||
if (!hubbub->funcs->dcc_support_swizzle_addr3(input->swizzle_mode_addr3,
|
||||
input->plane0_pitch, plane0_bpe,
|
||||
&segment_order_horz, &segment_order_vert))
|
||||
return false;
|
||||
|
||||
if (!hubbub->funcs->dcc_support_swizzle_addr3(input->swizzle_mode_addr3,
|
||||
input->plane1_pitch, plane1_bpe,
|
||||
&p1_segment_order_horz, &p1_segment_order_vert))
|
||||
return false;
|
||||
|
||||
hubbub401_det_request_size(TO_DCN20_HUBBUB(hubbub)->detile_buf_size, input->format,
|
||||
plane0_height, plane0_width, plane0_bpe,
|
||||
plane1_height, plane1_width, plane1_bpe,
|
||||
&req128_horz_wc, &req128_vert_wc, &p1_req128_horz_wc, &p1_req128_vert_wc);
|
||||
|
||||
/* Determine Plane 0 DCC Controls */
|
||||
if (!req128_horz_wc && !req128_vert_wc) {
|
||||
dcc_control = dcc_control__256_256;
|
||||
} else if (input->scan == SCAN_DIRECTION_HORIZONTAL) {
|
||||
if (!req128_horz_wc)
|
||||
dcc_control = dcc_control__256_256;
|
||||
else if (segment_order_horz == segment_order__contiguous)
|
||||
dcc_control = dcc_control__256_128;
|
||||
else
|
||||
dcc_control = dcc_control__256_64;
|
||||
} else if (input->scan == SCAN_DIRECTION_VERTICAL) {
|
||||
if (!req128_vert_wc)
|
||||
dcc_control = dcc_control__256_256;
|
||||
else if (segment_order_vert == segment_order__contiguous)
|
||||
dcc_control = dcc_control__256_128;
|
||||
else
|
||||
dcc_control = dcc_control__256_64;
|
||||
} else {
|
||||
if ((req128_horz_wc &&
|
||||
segment_order_horz == segment_order__non_contiguous) ||
|
||||
(req128_vert_wc &&
|
||||
segment_order_vert == segment_order__non_contiguous))
|
||||
/* access_dir not known, must use most constraining */
|
||||
dcc_control = dcc_control__256_64;
|
||||
else
|
||||
/* req128 is true for either horz and vert
|
||||
* but segment_order is contiguous
|
||||
*/
|
||||
dcc_control = dcc_control__256_128;
|
||||
}
|
||||
|
||||
switch (dcc_control) {
|
||||
case dcc_control__256_256:
|
||||
output->video.luma.dcc_controls.dcc_256_256 = 1;
|
||||
output->video.luma.dcc_controls.dcc_256_128 = 1;
|
||||
output->video.luma.dcc_controls.dcc_256_64 = 1;
|
||||
break;
|
||||
case dcc_control__256_128:
|
||||
output->video.luma.dcc_controls.dcc_256_128 = 1;
|
||||
output->video.luma.dcc_controls.dcc_256_64 = 1;
|
||||
break;
|
||||
case dcc_control__256_64:
|
||||
output->video.luma.dcc_controls.dcc_256_64 = 1;
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Determine Plane 1 DCC Controls */
|
||||
if (!p1_req128_horz_wc && !p1_req128_vert_wc) {
|
||||
dcc_control = dcc_control__256_256;
|
||||
} else if (input->scan == SCAN_DIRECTION_HORIZONTAL) {
|
||||
if (!p1_req128_horz_wc)
|
||||
dcc_control = dcc_control__256_256;
|
||||
else if (p1_segment_order_horz == segment_order__contiguous)
|
||||
dcc_control = dcc_control__256_128;
|
||||
else
|
||||
dcc_control = dcc_control__256_64;
|
||||
} else if (input->scan == SCAN_DIRECTION_VERTICAL) {
|
||||
if (!p1_req128_vert_wc)
|
||||
dcc_control = dcc_control__256_256;
|
||||
else if (p1_segment_order_vert == segment_order__contiguous)
|
||||
dcc_control = dcc_control__256_128;
|
||||
else
|
||||
dcc_control = dcc_control__256_64;
|
||||
} else {
|
||||
if ((p1_req128_horz_wc &&
|
||||
p1_segment_order_horz == segment_order__non_contiguous) ||
|
||||
(p1_req128_vert_wc &&
|
||||
p1_segment_order_vert == segment_order__non_contiguous))
|
||||
/* access_dir not known, must use most constraining */
|
||||
dcc_control = dcc_control__256_64;
|
||||
else
|
||||
/* req128 is true for either horz and vert
|
||||
* but segment_order is contiguous
|
||||
*/
|
||||
dcc_control = dcc_control__256_128;
|
||||
}
|
||||
|
||||
switch (dcc_control) {
|
||||
case dcc_control__256_256:
|
||||
output->video.chroma.dcc_controls.dcc_256_256 = 1;
|
||||
output->video.chroma.dcc_controls.dcc_256_128 = 1;
|
||||
output->video.chroma.dcc_controls.dcc_256_64 = 1;
|
||||
break;
|
||||
case dcc_control__256_128:
|
||||
output->video.chroma.dcc_controls.dcc_256_128 = 1;
|
||||
output->video.chroma.dcc_controls.dcc_256_64 = 1;
|
||||
break;
|
||||
case dcc_control__256_64:
|
||||
output->video.chroma.dcc_controls.dcc_256_64 = 1;
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
output->capable = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void dcn401_program_det_segments(struct hubbub *hubbub, int hubp_inst, unsigned det_buffer_size_seg)
|
||||
{
|
||||
@@ -891,6 +1170,7 @@ static const struct hubbub_funcs hubbub4_01_funcs = {
|
||||
.init_vm_ctx = hubbub2_init_vm_ctx,
|
||||
.dcc_support_swizzle_addr3 = hubbub401_dcc_support_swizzle,
|
||||
.dcc_support_pixel_format_plane0_plane1 = hubbub401_dcc_support_pixel_format,
|
||||
.get_dcc_compression_cap = hubbub401_get_dcc_compression_cap,
|
||||
.wm_read_state = hubbub401_wm_read_state,
|
||||
.get_dchub_ref_freq = hubbub2_get_dchub_ref_freq,
|
||||
.program_watermarks = hubbub401_program_watermarks,
|
||||
|
||||
@@ -180,6 +180,11 @@ void hubbub401_det_request_size(
|
||||
bool *p0_req128_vert_wc,
|
||||
bool *p1_req128_horz_wc,
|
||||
bool *p1_req128_vert_wc);
|
||||
bool hubbub401_get_dcc_compression_cap(
|
||||
struct hubbub *hubbub,
|
||||
const struct dc_dcc_surface_param *input,
|
||||
struct dc_surface_dcc_cap *output);
|
||||
|
||||
void hubbub401_construct(struct dcn20_hubbub *hubbub2,
|
||||
struct dc_context *ctx,
|
||||
const struct dcn_hubbub_registers *hubbub_regs,
|
||||
|
||||
@@ -175,6 +175,8 @@
|
||||
uint32_t HUBP_3DLUT_ADDRESS_LOW;\
|
||||
uint32_t HUBP_3DLUT_CONTROL;\
|
||||
uint32_t HUBP_3DLUT_DLG_PARAM;\
|
||||
uint32_t DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE;\
|
||||
uint32_t DCHUBP_MCACHEID_CONFIG
|
||||
|
||||
#define DCN2_HUBP_REG_FIELD_VARIABLE_LIST(type) \
|
||||
DCN_HUBP_REG_FIELD_BASE_LIST(type); \
|
||||
@@ -269,6 +271,18 @@
|
||||
type HUBP_3DLUT_ADDRESS_HIGH;\
|
||||
type HUBP_3DLUT_ADDRESS_LOW;\
|
||||
type REFCYC_PER_3DLUT_GROUP;\
|
||||
type VIEWPORT_MCACHE_SPLIT_COORDINATE;\
|
||||
type VIEWPORT_MCACHE_SPLIT_COORDINATE_C;\
|
||||
type MCACHEID_REG_READ_1H_P0;\
|
||||
type MCACHEID_REG_READ_2H_P0;\
|
||||
type MCACHEID_REG_READ_1H_P1;\
|
||||
type MCACHEID_REG_READ_2H_P1;\
|
||||
type MCACHEID_MALL_PREF_1H_P0;\
|
||||
type MCACHEID_MALL_PREF_2H_P0;\
|
||||
type MCACHEID_MALL_PREF_1H_P1;\
|
||||
type MCACHEID_MALL_PREF_2H_P1
|
||||
|
||||
|
||||
|
||||
struct dcn_hubp2_registers {
|
||||
DCN401_HUBP_REG_COMMON_VARIABLE_LIST;
|
||||
|
||||
@@ -626,6 +626,26 @@ void hubp401_set_viewport(
|
||||
SEC_VIEWPORT_Y_START_C, viewport_c->y);
|
||||
}
|
||||
|
||||
void hubp401_program_mcache_id_and_split_coordinate(
|
||||
struct hubp *hubp,
|
||||
struct dml2_hubp_pipe_mcache_regs *mcache_regs)
|
||||
{
|
||||
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
|
||||
|
||||
REG_SET_8(DCHUBP_MCACHEID_CONFIG, 0,
|
||||
MCACHEID_REG_READ_1H_P0, mcache_regs->main.p0.mcache_id_first,
|
||||
MCACHEID_REG_READ_2H_P0, mcache_regs->main.p0.mcache_id_second,
|
||||
MCACHEID_REG_READ_1H_P1, mcache_regs->main.p1.mcache_id_first,
|
||||
MCACHEID_REG_READ_2H_P1, mcache_regs->main.p1.mcache_id_second,
|
||||
MCACHEID_MALL_PREF_1H_P0, mcache_regs->mall.p0.mcache_id_first,
|
||||
MCACHEID_MALL_PREF_2H_P0, mcache_regs->mall.p0.mcache_id_second,
|
||||
MCACHEID_MALL_PREF_1H_P1, mcache_regs->mall.p1.mcache_id_first,
|
||||
MCACHEID_MALL_PREF_2H_P1, mcache_regs->mall.p1.mcache_id_second);
|
||||
|
||||
REG_SET_2(DCSURF_VIEWPORT_MCACHE_SPLIT_COORDINATE, 0,
|
||||
VIEWPORT_MCACHE_SPLIT_COORDINATE, mcache_regs->main.p0.split_location,
|
||||
VIEWPORT_MCACHE_SPLIT_COORDINATE_C, mcache_regs->main.p1.split_location);
|
||||
}
|
||||
void hubp401_set_flip_int(struct hubp *hubp)
|
||||
{
|
||||
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
|
||||
@@ -654,13 +674,11 @@ void hubp401_cursor_set_position(
|
||||
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
|
||||
int x_pos = pos->x - param->recout.x;
|
||||
int y_pos = pos->y - param->recout.y;
|
||||
int x_hotspot = pos->x_hotspot;
|
||||
int y_hotspot = pos->y_hotspot;
|
||||
int rec_x_offset = x_pos - pos->x_hotspot;
|
||||
int rec_y_offset = y_pos - pos->y_hotspot;
|
||||
int cursor_height = (int)hubp->curs_attr.height;
|
||||
int cursor_width = (int)hubp->curs_attr.width;
|
||||
uint32_t dst_x_offset;
|
||||
int dst_x_offset;
|
||||
int x_pos_viewport = x_pos * param->viewport.width / param->recout.width;
|
||||
int x_hot_viewport = pos->x_hotspot * param->viewport.width / param->recout.width;
|
||||
uint32_t cur_en = pos->enable ? 1 : 0;
|
||||
|
||||
hubp->curs_pos = *pos;
|
||||
@@ -672,29 +690,13 @@ void hubp401_cursor_set_position(
|
||||
if (hubp->curs_attr.address.quad_part == 0)
|
||||
return;
|
||||
|
||||
// Transform cursor width / height and hotspots for offset calculations
|
||||
if (param->rotation == ROTATION_ANGLE_90 || param->rotation == ROTATION_ANGLE_270) {
|
||||
swap(cursor_height, cursor_width);
|
||||
swap(x_hotspot, y_hotspot);
|
||||
|
||||
if (param->rotation == ROTATION_ANGLE_90) {
|
||||
// hotspot = (-y, x)
|
||||
rec_x_offset = x_pos - (cursor_width - x_hotspot);
|
||||
rec_y_offset = y_pos - y_hotspot;
|
||||
} else if (param->rotation == ROTATION_ANGLE_270) {
|
||||
// hotspot = (y, -x)
|
||||
rec_x_offset = x_pos - x_hotspot;
|
||||
rec_y_offset = y_pos - (cursor_height - y_hotspot);
|
||||
}
|
||||
} else if (param->rotation == ROTATION_ANGLE_180) {
|
||||
// hotspot = (-x, -y)
|
||||
if (!param->mirror)
|
||||
rec_x_offset = x_pos - (cursor_width - x_hotspot);
|
||||
|
||||
rec_y_offset = y_pos - (cursor_height - y_hotspot);
|
||||
}
|
||||
|
||||
dst_x_offset = (rec_x_offset >= 0) ? rec_x_offset : 0;
|
||||
/* Translate the x position of the cursor from rect
|
||||
* space into viewport space. CURSOR_DST_X_OFFSET
|
||||
* is the offset relative to viewport start position.
|
||||
*/
|
||||
dst_x_offset = x_pos_viewport - x_hot_viewport *
|
||||
(1 + hubp->curs_attr.attribute_flags.bits.ENABLE_MAGNIFICATION);
|
||||
dst_x_offset = (dst_x_offset >= 0) ? dst_x_offset : 0;
|
||||
dst_x_offset *= param->ref_clk_khz;
|
||||
dst_x_offset /= param->pixel_clk_khz;
|
||||
|
||||
@@ -705,18 +707,6 @@ void hubp401_cursor_set_position(
|
||||
dc_fixpt_from_int(dst_x_offset),
|
||||
param->h_scale_ratio));
|
||||
|
||||
if (rec_x_offset >= (int)param->recout.width)
|
||||
cur_en = 0; /* not visible beyond right edge*/
|
||||
|
||||
if (rec_x_offset + cursor_width <= 0)
|
||||
cur_en = 0; /* not visible beyond left edge*/
|
||||
|
||||
if (rec_y_offset >= (int)param->recout.height)
|
||||
cur_en = 0; /* not visible beyond bottom edge*/
|
||||
|
||||
if (rec_y_offset + cursor_height <= 0)
|
||||
cur_en = 0; /* not visible beyond top edge*/
|
||||
|
||||
if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0)
|
||||
hubp->funcs->set_cursor_attributes(hubp, &hubp->curs_attr);
|
||||
|
||||
@@ -993,6 +983,7 @@ static struct hubp_funcs dcn401_hubp_funcs = {
|
||||
.phantom_hubp_post_enable = hubp32_phantom_hubp_post_enable,
|
||||
.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,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user