mirror of
https://github.com/torvalds/linux.git
synced 2026-05-13 16:59:27 +02:00
amd-drm-next-7.1-2026-03-12:
amdgpu: - SMU13 fix - SMU14 fix - Fixes for bring up hw testing - Kerneldoc fix - GC12 idle power fix for compute workloads - DCCG fixes - UserQ fixes - Move test for fbdev object to a generic helper - GC 12.1 updates - Use struct drm_edid in non-DC code - Include IP discovery data in devcoredump - SMU 13.x updates - Misc cleanups - DML 2.1 fixes - Enable NV12/P010 support on primary planes - Enable color encoding and color range on overlay planes - DC underflow fixes - HWSS fast path fixes - Replay fixes - DCN 4.2 updates - Support newer IP discovery tables - LSDMA 7.1 support - IH 7.1 fixes - SoC v1 updates - GC12.1 updates - PSP 15 updates - XGMI fixes - GPUVM locking fix amdkfd: - Fix missing BO unreserve in an error path radeon: - Move test for fbdev object to a generic helper -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQQgO5Idg2tXNTSZAr293/aFa7yZ2AUCabMItwAKCRC93/aFa7yZ 2BiwAQD3yQsA6xuspaMXduQwFE0tu6rL6bB+NSB7bfM2YYdE1AEAqi2GQPOlfohH DK/zb58ZPoeJfCdShPPQ85cSkPSu2wY= =OtzL -----END PGP SIGNATURE----- Merge tag 'amd-drm-next-7.1-2026-03-12' of https://gitlab.freedesktop.org/agd5f/linux into drm-next amd-drm-next-7.1-2026-03-12: amdgpu: - SMU13 fix - SMU14 fix - Fixes for bring up hw testing - Kerneldoc fix - GC12 idle power fix for compute workloads - DCCG fixes - UserQ fixes - Move test for fbdev object to a generic helper - GC 12.1 updates - Use struct drm_edid in non-DC code - Include IP discovery data in devcoredump - SMU 13.x updates - Misc cleanups - DML 2.1 fixes - Enable NV12/P010 support on primary planes - Enable color encoding and color range on overlay planes - DC underflow fixes - HWSS fast path fixes - Replay fixes - DCN 4.2 updates - Support newer IP discovery tables - LSDMA 7.1 support - IH 7.1 fixes - SoC v1 updates - GC12.1 updates - PSP 15 updates - XGMI fixes - GPUVM locking fix amdkfd: - Fix missing BO unreserve in an error path radeon: - Move test for fbdev object to a generic helper From: Alex Deucher <alexander.deucher@amd.com> Link: https://patch.msgid.link/20260312184425.3875669-1-alexander.deucher@amd.com Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
commit
02e778f123
|
|
@ -86,7 +86,7 @@ amdgpu-y += \
|
|||
nbio_v7_2.o hdp_v4_0.o hdp_v5_0.o aldebaran_reg_init.o aldebaran.o soc21.o soc24.o \
|
||||
sienna_cichlid.o smu_v13_0_10.o nbio_v4_3.o hdp_v6_0.o nbio_v7_7.o hdp_v5_2.o lsdma_v6_0.o \
|
||||
nbio_v7_9.o aqua_vanjaram.o nbio_v7_11.o lsdma_v7_0.o hdp_v7_0.o nbif_v6_3_1.o \
|
||||
cyan_skillfish_reg_init.o soc_v1_0.o
|
||||
cyan_skillfish_reg_init.o soc_v1_0.o lsdma_v7_1.o
|
||||
|
||||
# add DF block
|
||||
amdgpu-y += \
|
||||
|
|
|
|||
|
|
@ -246,10 +246,10 @@ amdgpu_connector_find_encoder(struct drm_connector *connector,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static struct edid *
|
||||
static const struct drm_edid *
|
||||
amdgpu_connector_get_hardcoded_edid(struct amdgpu_device *adev)
|
||||
{
|
||||
return drm_edid_duplicate(drm_edid_raw(adev->mode_info.bios_hardcoded_edid));
|
||||
return drm_edid_dup(adev->mode_info.bios_hardcoded_edid);
|
||||
}
|
||||
|
||||
static void amdgpu_connector_get_edid(struct drm_connector *connector)
|
||||
|
|
@ -268,8 +268,8 @@ static void amdgpu_connector_get_edid(struct drm_connector *connector)
|
|||
if ((amdgpu_connector_encoder_get_dp_bridge_encoder_id(connector) !=
|
||||
ENCODER_OBJECT_ID_NONE) &&
|
||||
amdgpu_connector->ddc_bus->has_aux) {
|
||||
amdgpu_connector->edid = drm_get_edid(connector,
|
||||
&amdgpu_connector->ddc_bus->aux.ddc);
|
||||
amdgpu_connector->edid = drm_edid_read_ddc(connector,
|
||||
&amdgpu_connector->ddc_bus->aux.ddc);
|
||||
} else if ((connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
|
||||
(connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
|
||||
struct amdgpu_connector_atom_dig *dig = amdgpu_connector->con_priv;
|
||||
|
|
@ -277,14 +277,14 @@ static void amdgpu_connector_get_edid(struct drm_connector *connector)
|
|||
if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT ||
|
||||
dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) &&
|
||||
amdgpu_connector->ddc_bus->has_aux)
|
||||
amdgpu_connector->edid = drm_get_edid(connector,
|
||||
&amdgpu_connector->ddc_bus->aux.ddc);
|
||||
amdgpu_connector->edid = drm_edid_read_ddc(connector,
|
||||
&amdgpu_connector->ddc_bus->aux.ddc);
|
||||
else if (amdgpu_connector->ddc_bus)
|
||||
amdgpu_connector->edid = drm_get_edid(connector,
|
||||
&amdgpu_connector->ddc_bus->adapter);
|
||||
amdgpu_connector->edid = drm_edid_read_ddc(connector,
|
||||
&amdgpu_connector->ddc_bus->adapter);
|
||||
} else if (amdgpu_connector->ddc_bus) {
|
||||
amdgpu_connector->edid = drm_get_edid(connector,
|
||||
&amdgpu_connector->ddc_bus->adapter);
|
||||
amdgpu_connector->edid = drm_edid_read_ddc(connector,
|
||||
&amdgpu_connector->ddc_bus->adapter);
|
||||
}
|
||||
|
||||
if (!amdgpu_connector->edid) {
|
||||
|
|
@ -292,30 +292,22 @@ static void amdgpu_connector_get_edid(struct drm_connector *connector)
|
|||
if (((connector->connector_type == DRM_MODE_CONNECTOR_LVDS) ||
|
||||
(connector->connector_type == DRM_MODE_CONNECTOR_eDP))) {
|
||||
amdgpu_connector->edid = amdgpu_connector_get_hardcoded_edid(adev);
|
||||
drm_connector_update_edid_property(connector, amdgpu_connector->edid);
|
||||
drm_edid_connector_update(connector, amdgpu_connector->edid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void amdgpu_connector_free_edid(struct drm_connector *connector)
|
||||
{
|
||||
struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
|
||||
|
||||
kfree(amdgpu_connector->edid);
|
||||
amdgpu_connector->edid = NULL;
|
||||
}
|
||||
|
||||
static int amdgpu_connector_ddc_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
|
||||
int ret;
|
||||
|
||||
if (amdgpu_connector->edid) {
|
||||
drm_connector_update_edid_property(connector, amdgpu_connector->edid);
|
||||
ret = drm_add_edid_modes(connector, amdgpu_connector->edid);
|
||||
drm_edid_connector_update(connector, amdgpu_connector->edid);
|
||||
ret = drm_edid_connector_add_modes(connector);
|
||||
return ret;
|
||||
}
|
||||
drm_connector_update_edid_property(connector, NULL);
|
||||
drm_edid_connector_update(connector, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -754,7 +746,7 @@ static void amdgpu_connector_destroy(struct drm_connector *connector)
|
|||
{
|
||||
struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
|
||||
|
||||
amdgpu_connector_free_edid(connector);
|
||||
drm_edid_free(amdgpu_connector->edid);
|
||||
kfree(amdgpu_connector->con_priv);
|
||||
drm_connector_unregister(connector);
|
||||
drm_connector_cleanup(connector);
|
||||
|
|
@ -873,7 +865,7 @@ amdgpu_connector_vga_detect(struct drm_connector *connector, bool force)
|
|||
dret = amdgpu_display_ddc_probe(amdgpu_connector, false);
|
||||
if (dret) {
|
||||
amdgpu_connector->detected_by_load = false;
|
||||
amdgpu_connector_free_edid(connector);
|
||||
drm_edid_free(amdgpu_connector->edid);
|
||||
amdgpu_connector_get_edid(connector);
|
||||
|
||||
if (!amdgpu_connector->edid) {
|
||||
|
|
@ -883,13 +875,13 @@ amdgpu_connector_vga_detect(struct drm_connector *connector, bool force)
|
|||
ret = connector_status_connected;
|
||||
} else {
|
||||
amdgpu_connector->use_digital =
|
||||
!!(amdgpu_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
|
||||
drm_edid_is_digital(amdgpu_connector->edid);
|
||||
|
||||
/* some oems have boards with separate digital and analog connectors
|
||||
* with a shared ddc line (often vga + hdmi)
|
||||
*/
|
||||
if (amdgpu_connector->use_digital && amdgpu_connector->shared_ddc) {
|
||||
amdgpu_connector_free_edid(connector);
|
||||
drm_edid_free(amdgpu_connector->edid);
|
||||
ret = connector_status_disconnected;
|
||||
} else {
|
||||
ret = connector_status_connected;
|
||||
|
|
@ -984,7 +976,7 @@ static void amdgpu_connector_shared_ddc(enum drm_connector_status *status,
|
|||
/* hpd is our only option in this case */
|
||||
if (!amdgpu_display_hpd_sense(adev,
|
||||
amdgpu_connector->hpd.hpd)) {
|
||||
amdgpu_connector_free_edid(connector);
|
||||
drm_edid_free(amdgpu_connector->edid);
|
||||
*status = connector_status_disconnected;
|
||||
}
|
||||
}
|
||||
|
|
@ -1053,7 +1045,7 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force)
|
|||
}
|
||||
if (dret) {
|
||||
amdgpu_connector->detected_by_load = false;
|
||||
amdgpu_connector_free_edid(connector);
|
||||
drm_edid_free(amdgpu_connector->edid);
|
||||
amdgpu_connector_get_edid(connector);
|
||||
|
||||
if (!amdgpu_connector->edid) {
|
||||
|
|
@ -1063,13 +1055,13 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force)
|
|||
broken_edid = true; /* defer use_digital to later */
|
||||
} else {
|
||||
amdgpu_connector->use_digital =
|
||||
!!(amdgpu_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
|
||||
drm_edid_is_digital(amdgpu_connector->edid);
|
||||
|
||||
/* some oems have boards with separate digital and analog connectors
|
||||
* with a shared ddc line (often vga + hdmi)
|
||||
*/
|
||||
if ((!amdgpu_connector->use_digital) && amdgpu_connector->shared_ddc) {
|
||||
amdgpu_connector_free_edid(connector);
|
||||
drm_edid_free(amdgpu_connector->edid);
|
||||
ret = connector_status_disconnected;
|
||||
} else {
|
||||
ret = connector_status_connected;
|
||||
|
|
@ -1417,7 +1409,7 @@ amdgpu_connector_dp_detect(struct drm_connector *connector, bool force)
|
|||
goto out;
|
||||
}
|
||||
|
||||
amdgpu_connector_free_edid(connector);
|
||||
drm_edid_free(amdgpu_connector->edid);
|
||||
|
||||
if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
|
||||
(connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
|
||||
#include "amdgpu_reset.h"
|
||||
#include "amdgpu_psp_ta.h"
|
||||
#include "amdgpu_userq.h"
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
|
||||
|
|
@ -2156,6 +2157,53 @@ static const struct file_operations amdgpu_pt_info_fops = {
|
|||
.release = single_release,
|
||||
};
|
||||
|
||||
static int amdgpu_mqd_info_read(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct amdgpu_usermode_queue *queue = m->private;
|
||||
struct amdgpu_bo *bo;
|
||||
int r;
|
||||
|
||||
if (!queue || !queue->mqd.obj)
|
||||
return -EINVAL;
|
||||
|
||||
bo = amdgpu_bo_ref(queue->mqd.obj);
|
||||
r = amdgpu_bo_reserve(bo, true);
|
||||
if (r) {
|
||||
amdgpu_bo_unref(&bo);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
seq_printf(m, "queue_type: %d\n", queue->queue_type);
|
||||
seq_printf(m, "mqd_gpu_address: 0x%llx\n", amdgpu_bo_gpu_offset(queue->mqd.obj));
|
||||
|
||||
amdgpu_bo_unreserve(bo);
|
||||
amdgpu_bo_unref(&bo);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_mqd_info_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, amdgpu_mqd_info_read, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations amdgpu_mqd_info_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = amdgpu_mqd_info_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
void amdgpu_debugfs_userq_init(struct drm_file *file, struct amdgpu_usermode_queue *queue, int qid)
|
||||
{
|
||||
char queue_name[32];
|
||||
|
||||
scnprintf(queue_name, sizeof(queue_name), "queue_%d", qid);
|
||||
queue->debugfs_queue = debugfs_create_dir(queue_name, file->debugfs_client);
|
||||
debugfs_create_file("mqd_info", 0444, queue->debugfs_queue, queue, &amdgpu_mqd_info_fops);
|
||||
}
|
||||
|
||||
void amdgpu_debugfs_vm_init(struct drm_file *file)
|
||||
{
|
||||
debugfs_create_file("vm_pagetable_info", 0444, file->debugfs_client, file,
|
||||
|
|
@ -2174,4 +2222,9 @@ int amdgpu_debugfs_regs_init(struct amdgpu_device *adev)
|
|||
void amdgpu_debugfs_vm_init(struct drm_file *file)
|
||||
{
|
||||
}
|
||||
void amdgpu_debugfs_userq_init(struct drm_file *file,
|
||||
struct amdgpu_usermode_queue *queue,
|
||||
int qid)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
/*
|
||||
* Debugfs
|
||||
*/
|
||||
struct amdgpu_usermode_queue;
|
||||
|
||||
int amdgpu_debugfs_regs_init(struct amdgpu_device *adev);
|
||||
int amdgpu_debugfs_init(struct amdgpu_device *adev);
|
||||
|
|
@ -34,4 +35,7 @@ void amdgpu_debugfs_firmware_init(struct amdgpu_device *adev);
|
|||
void amdgpu_debugfs_gem_init(struct amdgpu_device *adev);
|
||||
void amdgpu_debugfs_mes_event_log_init(struct amdgpu_device *adev);
|
||||
void amdgpu_debugfs_vm_init(struct drm_file *file);
|
||||
void amdgpu_debugfs_userq_init(struct drm_file *file,
|
||||
struct amdgpu_usermode_queue *queue,
|
||||
int qid);
|
||||
|
||||
|
|
|
|||
|
|
@ -261,6 +261,8 @@ amdgpu_devcoredump_read(char *buffer, loff_t offset, size_t count,
|
|||
}
|
||||
}
|
||||
|
||||
amdgpu_discovery_dump(coredump->adev, &p);
|
||||
|
||||
/* IP firmware information */
|
||||
drm_printf(&p, "\nIP Firmwares\n");
|
||||
amdgpu_devcoredump_fw_info(coredump->adev, &p);
|
||||
|
|
|
|||
|
|
@ -1995,8 +1995,10 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
|
|||
break;
|
||||
default:
|
||||
r = amdgpu_discovery_set_ip_blocks(adev);
|
||||
if (r)
|
||||
if (r) {
|
||||
adev->num_ip_blocks = 0;
|
||||
return r;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -2550,6 +2552,8 @@ int amdgpu_device_set_cg_state(struct amdgpu_device *adev,
|
|||
i = state == AMD_CG_STATE_GATE ? j : adev->num_ip_blocks - j - 1;
|
||||
if (!adev->ip_blocks[i].status.late_initialized)
|
||||
continue;
|
||||
if (!adev->ip_blocks[i].version)
|
||||
continue;
|
||||
/* skip CG for GFX, SDMA on S0ix */
|
||||
if (adev->in_s0ix &&
|
||||
(adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GFX ||
|
||||
|
|
@ -2589,6 +2593,8 @@ int amdgpu_device_set_pg_state(struct amdgpu_device *adev,
|
|||
i = state == AMD_PG_STATE_GATE ? j : adev->num_ip_blocks - j - 1;
|
||||
if (!adev->ip_blocks[i].status.late_initialized)
|
||||
continue;
|
||||
if (!adev->ip_blocks[i].version)
|
||||
continue;
|
||||
/* skip PG for GFX, SDMA on S0ix */
|
||||
if (adev->in_s0ix &&
|
||||
(adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GFX ||
|
||||
|
|
@ -2796,6 +2802,8 @@ static int amdgpu_device_ip_fini_early(struct amdgpu_device *adev)
|
|||
int i, r;
|
||||
|
||||
for (i = 0; i < adev->num_ip_blocks; i++) {
|
||||
if (!adev->ip_blocks[i].version)
|
||||
continue;
|
||||
if (!adev->ip_blocks[i].version->funcs->early_fini)
|
||||
continue;
|
||||
|
||||
|
|
@ -2873,6 +2881,8 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev)
|
|||
if (!adev->ip_blocks[i].status.sw)
|
||||
continue;
|
||||
|
||||
if (!adev->ip_blocks[i].version)
|
||||
continue;
|
||||
if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) {
|
||||
amdgpu_ucode_free_bo(adev);
|
||||
amdgpu_free_static_csa(&adev->virt.csa_obj);
|
||||
|
|
@ -2899,6 +2909,8 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev)
|
|||
for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
|
||||
if (!adev->ip_blocks[i].status.late_initialized)
|
||||
continue;
|
||||
if (!adev->ip_blocks[i].version)
|
||||
continue;
|
||||
if (adev->ip_blocks[i].version->funcs->late_fini)
|
||||
adev->ip_blocks[i].version->funcs->late_fini(&adev->ip_blocks[i]);
|
||||
adev->ip_blocks[i].status.late_initialized = false;
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@
|
|||
#include "sdma_v7_1.h"
|
||||
#include "lsdma_v6_0.h"
|
||||
#include "lsdma_v7_0.h"
|
||||
#include "lsdma_v7_1.h"
|
||||
#include "vcn_v2_0.h"
|
||||
#include "jpeg_v2_0.h"
|
||||
#include "vcn_v3_0.h"
|
||||
|
|
@ -132,6 +133,7 @@ MODULE_FIRMWARE("amdgpu/picasso_ip_discovery.bin");
|
|||
MODULE_FIRMWARE("amdgpu/arcturus_ip_discovery.bin");
|
||||
MODULE_FIRMWARE("amdgpu/aldebaran_ip_discovery.bin");
|
||||
|
||||
/* Note: These registers are consistent across all the SOCs */
|
||||
#define mmIP_DISCOVERY_VERSION 0x16A00
|
||||
#define mmRCC_CONFIG_MEMSIZE 0xde3
|
||||
#define mmMP0_SMN_C2PMSG_33 0x16061
|
||||
|
|
@ -139,6 +141,10 @@ MODULE_FIRMWARE("amdgpu/aldebaran_ip_discovery.bin");
|
|||
#define mmMM_INDEX_HI 0x6
|
||||
#define mmMM_DATA 0x1
|
||||
|
||||
#define mmDRIVER_SCRATCH_0 0x94
|
||||
#define mmDRIVER_SCRATCH_1 0x95
|
||||
#define mmDRIVER_SCRATCH_2 0x96
|
||||
|
||||
static const char *hw_id_names[HW_ID_MAX] = {
|
||||
[MP1_HWID] = "MP1",
|
||||
[MP2_HWID] = "MP2",
|
||||
|
|
@ -253,39 +259,12 @@ static int hw_id_map[MAX_HWIP] = {
|
|||
[ATU_HWIP] = ATU_HWID,
|
||||
};
|
||||
|
||||
static int amdgpu_discovery_read_binary_from_sysmem(struct amdgpu_device *adev, uint8_t *binary)
|
||||
static int amdgpu_discovery_get_tmr_info(struct amdgpu_device *adev,
|
||||
bool *is_tmr_in_sysmem)
|
||||
{
|
||||
u64 tmr_offset, tmr_size, pos;
|
||||
void *discv_regn;
|
||||
int ret;
|
||||
|
||||
ret = amdgpu_acpi_get_tmr_info(adev, &tmr_offset, &tmr_size);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pos = tmr_offset + tmr_size - DISCOVERY_TMR_OFFSET;
|
||||
|
||||
/* This region is read-only and reserved from system use */
|
||||
discv_regn = memremap(pos, adev->discovery.size, MEMREMAP_WC);
|
||||
if (discv_regn) {
|
||||
memcpy(binary, discv_regn, adev->discovery.size);
|
||||
memunmap(discv_regn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
#define IP_DISCOVERY_V2 2
|
||||
#define IP_DISCOVERY_V4 4
|
||||
|
||||
static int amdgpu_discovery_read_binary_from_mem(struct amdgpu_device *adev,
|
||||
uint8_t *binary)
|
||||
{
|
||||
bool sz_valid = true;
|
||||
uint64_t vram_size;
|
||||
int i, ret = 0;
|
||||
u32 msg;
|
||||
u64 vram_size, tmr_offset, tmr_size;
|
||||
u32 msg, tmr_offset_lo, tmr_offset_hi;
|
||||
int i, ret;
|
||||
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
/* It can take up to two second for IFWI init to complete on some dGPUs,
|
||||
|
|
@ -305,51 +284,98 @@ static int amdgpu_discovery_read_binary_from_mem(struct amdgpu_device *adev,
|
|||
}
|
||||
|
||||
vram_size = RREG32(mmRCC_CONFIG_MEMSIZE);
|
||||
if (!vram_size || vram_size == U32_MAX)
|
||||
sz_valid = false;
|
||||
if (vram_size == U32_MAX)
|
||||
return -ENXIO;
|
||||
else if (!vram_size)
|
||||
*is_tmr_in_sysmem = true;
|
||||
else
|
||||
vram_size <<= 20;
|
||||
*is_tmr_in_sysmem = false;
|
||||
|
||||
/*
|
||||
* If in VRAM, discovery TMR is marked for reservation. If it is in system mem,
|
||||
* then it is not required to be reserved.
|
||||
*/
|
||||
if (sz_valid) {
|
||||
if (amdgpu_sriov_vf(adev) && adev->virt.is_dynamic_crit_regn_enabled) {
|
||||
/* For SRIOV VFs with dynamic critical region enabled,
|
||||
* we will get the IPD binary via below call.
|
||||
* If dynamic critical is disabled, fall through to normal seq.
|
||||
*/
|
||||
if (amdgpu_virt_get_dynamic_data_info(adev,
|
||||
AMD_SRIOV_MSG_IPD_TABLE_ID, binary,
|
||||
&adev->discovery.size)) {
|
||||
dev_err(adev->dev,
|
||||
"failed to read discovery info from dynamic critical region.");
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
/* init the default tmr size and offset */
|
||||
adev->discovery.size = DISCOVERY_TMR_SIZE;
|
||||
if (vram_size)
|
||||
adev->discovery.offset = (vram_size << 20) - DISCOVERY_TMR_OFFSET;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && adev->virt.is_dynamic_crit_regn_enabled) {
|
||||
adev->discovery.offset =
|
||||
adev->virt.crit_regn_tbl[AMD_SRIOV_MSG_IPD_TABLE_ID].offset;
|
||||
adev->discovery.size =
|
||||
adev->virt.crit_regn_tbl[AMD_SRIOV_MSG_IPD_TABLE_ID].size_kb << 10;
|
||||
if (!adev->discovery.offset || !adev->discovery.size)
|
||||
return -EINVAL;
|
||||
} else {
|
||||
tmr_size = RREG32(mmDRIVER_SCRATCH_2);
|
||||
if (tmr_size) {
|
||||
/* It's preferred to transition to PSP mailbox reg interface
|
||||
* for both bare-metal and passthrough if available */
|
||||
adev->discovery.size = (u32)tmr_size;
|
||||
tmr_offset_lo = RREG32(mmDRIVER_SCRATCH_0);
|
||||
tmr_offset_hi = RREG32(mmDRIVER_SCRATCH_1);
|
||||
adev->discovery.offset = ((u64)le32_to_cpu(tmr_offset_hi) << 32 |
|
||||
le32_to_cpu(tmr_offset_lo));
|
||||
} else if (!vram_size) {
|
||||
/* fall back to apci approach to query tmr offset if vram_size is 0 */
|
||||
ret = amdgpu_acpi_get_tmr_info(adev, &tmr_offset, &tmr_size);
|
||||
if (ret)
|
||||
return ret;
|
||||
adev->discovery.size = (u32)tmr_size;
|
||||
adev->discovery.offset = tmr_offset + tmr_size - DISCOVERY_TMR_OFFSET;
|
||||
}
|
||||
}
|
||||
|
||||
adev->discovery.bin = kzalloc(adev->discovery.size, GFP_KERNEL);
|
||||
if (!adev->discovery.bin)
|
||||
return -ENOMEM;
|
||||
adev->discovery.debugfs_blob.data = adev->discovery.bin;
|
||||
adev->discovery.debugfs_blob.size = adev->discovery.size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_discovery_read_binary_from_sysmem(struct amdgpu_device *adev, uint8_t *binary)
|
||||
{
|
||||
void *discv_regn;
|
||||
|
||||
/* This region is read-only and reserved from system use */
|
||||
discv_regn = memremap(adev->discovery.offset, adev->discovery.size, MEMREMAP_WC);
|
||||
if (discv_regn) {
|
||||
memcpy(binary, discv_regn, adev->discovery.size);
|
||||
memunmap(discv_regn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
#define IP_DISCOVERY_V2 2
|
||||
#define IP_DISCOVERY_V4 4
|
||||
|
||||
static int amdgpu_discovery_read_binary_from_mem(struct amdgpu_device *adev,
|
||||
uint8_t *binary,
|
||||
bool is_tmr_in_sysmem)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!is_tmr_in_sysmem) {
|
||||
if (amdgpu_sriov_vf(adev) &&
|
||||
amdgpu_sriov_xgmi_connected_to_cpu(adev)) {
|
||||
ret = amdgpu_discovery_read_binary_from_sysmem(adev, binary);
|
||||
} else {
|
||||
uint64_t pos = vram_size - DISCOVERY_TMR_OFFSET;
|
||||
|
||||
amdgpu_device_vram_access(adev, pos, (uint32_t *)binary,
|
||||
adev->discovery.size, false);
|
||||
amdgpu_device_vram_access(adev, adev->discovery.offset,
|
||||
(uint32_t *)binary,
|
||||
adev->discovery.size, false);
|
||||
adev->discovery.reserve_tmr = true;
|
||||
}
|
||||
} else {
|
||||
ret = amdgpu_discovery_read_binary_from_sysmem(adev, binary);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
dev_err(adev->dev,
|
||||
"failed to read discovery info from memory, vram size read: %llx",
|
||||
vram_size);
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int amdgpu_discovery_read_binary_from_file(struct amdgpu_device *adev,
|
||||
uint8_t *binary,
|
||||
const char *fw_name)
|
||||
uint8_t *binary,
|
||||
const char *fw_name)
|
||||
{
|
||||
const struct firmware *fw;
|
||||
int r;
|
||||
|
|
@ -431,14 +457,12 @@ static void amdgpu_discovery_harvest_config_quirk(struct amdgpu_device *adev)
|
|||
}
|
||||
|
||||
static int amdgpu_discovery_verify_npsinfo(struct amdgpu_device *adev,
|
||||
struct binary_header *bhdr)
|
||||
struct table_info *info)
|
||||
{
|
||||
uint8_t *discovery_bin = adev->discovery.bin;
|
||||
struct table_info *info;
|
||||
uint16_t checksum;
|
||||
uint16_t offset;
|
||||
|
||||
info = &bhdr->table_list[NPS_INFO];
|
||||
offset = le16_to_cpu(info->offset);
|
||||
checksum = le16_to_cpu(info->checksum);
|
||||
|
||||
|
|
@ -491,23 +515,125 @@ static const char *amdgpu_discovery_get_fw_name(struct amdgpu_device *adev)
|
|||
}
|
||||
}
|
||||
|
||||
static int amdgpu_discovery_get_table_info(struct amdgpu_device *adev,
|
||||
struct table_info **info,
|
||||
uint16_t table_id)
|
||||
{
|
||||
struct binary_header *bhdr =
|
||||
(struct binary_header *)adev->discovery.bin;
|
||||
struct binary_header_v2 *bhdrv2;
|
||||
|
||||
switch (bhdr->version_major) {
|
||||
case 2:
|
||||
bhdrv2 = (struct binary_header_v2 *)adev->discovery.bin;
|
||||
*info = &bhdrv2->table_list[table_id];
|
||||
break;
|
||||
case 1:
|
||||
*info = &bhdr->table_list[table_id];
|
||||
break;
|
||||
default:
|
||||
dev_err(adev->dev, "Invalid ip discovery table version\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_discovery_table_check(struct amdgpu_device *adev,
|
||||
uint8_t *discovery_bin,
|
||||
uint16_t table_id)
|
||||
{
|
||||
int r, act_val, exp_val, table_size;
|
||||
uint16_t offset, checksum;
|
||||
struct table_info *info;
|
||||
bool check_table = true;
|
||||
char *table_name;
|
||||
|
||||
r = amdgpu_discovery_get_table_info(adev, &info, table_id);
|
||||
if (r)
|
||||
return r;
|
||||
offset = le16_to_cpu(info->offset);
|
||||
checksum = le16_to_cpu(info->checksum);
|
||||
|
||||
switch (table_id) {
|
||||
case IP_DISCOVERY:
|
||||
struct ip_discovery_header *ihdr =
|
||||
(struct ip_discovery_header *)(discovery_bin + offset);
|
||||
act_val = le32_to_cpu(ihdr->signature);
|
||||
exp_val = DISCOVERY_TABLE_SIGNATURE;
|
||||
table_size = le16_to_cpu(ihdr->size);
|
||||
table_name = "data table";
|
||||
break;
|
||||
case GC:
|
||||
struct gpu_info_header *ghdr =
|
||||
(struct gpu_info_header *)(discovery_bin + offset);
|
||||
act_val = le32_to_cpu(ghdr->table_id);
|
||||
exp_val = GC_TABLE_ID;
|
||||
table_size = le16_to_cpu(ghdr->size);
|
||||
table_name = "gc table";
|
||||
break;
|
||||
case HARVEST_INFO:
|
||||
struct harvest_info_header *hhdr =
|
||||
(struct harvest_info_header *)(discovery_bin + offset);
|
||||
act_val = le32_to_cpu(hhdr->signature);
|
||||
exp_val = HARVEST_TABLE_SIGNATURE;
|
||||
table_size = sizeof(struct harvest_table);
|
||||
table_name = "harvest table";
|
||||
break;
|
||||
case VCN_INFO:
|
||||
struct vcn_info_header *vhdr =
|
||||
(struct vcn_info_header *)(discovery_bin + offset);
|
||||
act_val = le32_to_cpu(vhdr->table_id);
|
||||
exp_val = VCN_INFO_TABLE_ID;
|
||||
table_size = le32_to_cpu(vhdr->size_bytes);
|
||||
table_name = "vcn table";
|
||||
break;
|
||||
case MALL_INFO:
|
||||
struct mall_info_header *mhdr =
|
||||
(struct mall_info_header *)(discovery_bin + offset);
|
||||
act_val = le32_to_cpu(mhdr->table_id);
|
||||
exp_val = MALL_INFO_TABLE_ID;
|
||||
table_size = le32_to_cpu(mhdr->size_bytes);
|
||||
table_name = "mall table";
|
||||
check_table = false;
|
||||
break;
|
||||
default:
|
||||
dev_err(adev->dev, "invalid ip discovery table id %d specified\n", table_id);
|
||||
check_table = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (check_table && offset) {
|
||||
if (act_val != exp_val) {
|
||||
dev_err(adev->dev, "invalid ip discovery %s signature\n", table_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!amdgpu_discovery_verify_checksum(adev, discovery_bin + offset,
|
||||
table_size, checksum)) {
|
||||
dev_err(adev->dev, "invalid ip discovery %s checksum\n", table_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_discovery_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct table_info *info;
|
||||
struct binary_header *bhdr;
|
||||
uint8_t *discovery_bin;
|
||||
const char *fw_name;
|
||||
uint16_t offset;
|
||||
uint16_t size;
|
||||
uint16_t checksum;
|
||||
uint16_t table_id;
|
||||
bool is_tmr_in_sysmem;
|
||||
int r;
|
||||
|
||||
adev->discovery.bin = kzalloc(DISCOVERY_TMR_SIZE, GFP_KERNEL);
|
||||
if (!adev->discovery.bin)
|
||||
return -ENOMEM;
|
||||
adev->discovery.size = DISCOVERY_TMR_SIZE;
|
||||
adev->discovery.debugfs_blob.data = adev->discovery.bin;
|
||||
adev->discovery.debugfs_blob.size = adev->discovery.size;
|
||||
r = amdgpu_discovery_get_tmr_info(adev, &is_tmr_in_sysmem);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
discovery_bin = adev->discovery.bin;
|
||||
/* Read from file if it is the preferred option */
|
||||
|
|
@ -520,7 +646,8 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)
|
|||
goto out;
|
||||
} else {
|
||||
drm_dbg(&adev->ddev, "use ip discovery information from memory");
|
||||
r = amdgpu_discovery_read_binary_from_mem(adev, discovery_bin);
|
||||
r = amdgpu_discovery_read_binary_from_mem(adev, discovery_bin,
|
||||
is_tmr_in_sysmem);
|
||||
if (r)
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -547,118 +674,10 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)
|
|||
goto out;
|
||||
}
|
||||
|
||||
info = &bhdr->table_list[IP_DISCOVERY];
|
||||
offset = le16_to_cpu(info->offset);
|
||||
checksum = le16_to_cpu(info->checksum);
|
||||
|
||||
if (offset) {
|
||||
struct ip_discovery_header *ihdr =
|
||||
(struct ip_discovery_header *)(discovery_bin + offset);
|
||||
if (le32_to_cpu(ihdr->signature) != DISCOVERY_TABLE_SIGNATURE) {
|
||||
dev_err(adev->dev, "invalid ip discovery data table signature\n");
|
||||
r = -EINVAL;
|
||||
for (table_id = 0; table_id <= MALL_INFO; table_id++) {
|
||||
r = amdgpu_discovery_table_check(adev, discovery_bin, table_id);
|
||||
if (r)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!amdgpu_discovery_verify_checksum(adev, discovery_bin + offset,
|
||||
le16_to_cpu(ihdr->size),
|
||||
checksum)) {
|
||||
dev_err(adev->dev, "invalid ip discovery data table checksum\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
info = &bhdr->table_list[GC];
|
||||
offset = le16_to_cpu(info->offset);
|
||||
checksum = le16_to_cpu(info->checksum);
|
||||
|
||||
if (offset) {
|
||||
struct gpu_info_header *ghdr =
|
||||
(struct gpu_info_header *)(discovery_bin + offset);
|
||||
|
||||
if (le32_to_cpu(ghdr->table_id) != GC_TABLE_ID) {
|
||||
dev_err(adev->dev, "invalid ip discovery gc table id\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!amdgpu_discovery_verify_checksum(adev, discovery_bin + offset,
|
||||
le32_to_cpu(ghdr->size),
|
||||
checksum)) {
|
||||
dev_err(adev->dev, "invalid gc data table checksum\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
info = &bhdr->table_list[HARVEST_INFO];
|
||||
offset = le16_to_cpu(info->offset);
|
||||
checksum = le16_to_cpu(info->checksum);
|
||||
|
||||
if (offset) {
|
||||
struct harvest_info_header *hhdr =
|
||||
(struct harvest_info_header *)(discovery_bin + offset);
|
||||
|
||||
if (le32_to_cpu(hhdr->signature) != HARVEST_TABLE_SIGNATURE) {
|
||||
dev_err(adev->dev, "invalid ip discovery harvest table signature\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!amdgpu_discovery_verify_checksum(adev,
|
||||
discovery_bin + offset,
|
||||
sizeof(struct harvest_table), checksum)) {
|
||||
dev_err(adev->dev, "invalid harvest data table checksum\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
info = &bhdr->table_list[VCN_INFO];
|
||||
offset = le16_to_cpu(info->offset);
|
||||
checksum = le16_to_cpu(info->checksum);
|
||||
|
||||
if (offset) {
|
||||
struct vcn_info_header *vhdr =
|
||||
(struct vcn_info_header *)(discovery_bin + offset);
|
||||
|
||||
if (le32_to_cpu(vhdr->table_id) != VCN_INFO_TABLE_ID) {
|
||||
dev_err(adev->dev, "invalid ip discovery vcn table id\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!amdgpu_discovery_verify_checksum(adev,
|
||||
discovery_bin + offset,
|
||||
le32_to_cpu(vhdr->size_bytes), checksum)) {
|
||||
dev_err(adev->dev, "invalid vcn data table checksum\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
info = &bhdr->table_list[MALL_INFO];
|
||||
offset = le16_to_cpu(info->offset);
|
||||
checksum = le16_to_cpu(info->checksum);
|
||||
|
||||
if (0 && offset) {
|
||||
struct mall_info_header *mhdr =
|
||||
(struct mall_info_header *)(discovery_bin + offset);
|
||||
|
||||
if (le32_to_cpu(mhdr->table_id) != MALL_INFO_TABLE_ID) {
|
||||
dev_err(adev->dev, "invalid ip discovery mall table id\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!amdgpu_discovery_verify_checksum(adev,
|
||||
discovery_bin + offset,
|
||||
le32_to_cpu(mhdr->size_bytes), checksum)) {
|
||||
dev_err(adev->dev, "invalid mall data table checksum\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -770,14 +789,15 @@ static void amdgpu_discovery_read_from_harvest_table(struct amdgpu_device *adev,
|
|||
uint32_t *umc_harvest_count)
|
||||
{
|
||||
uint8_t *discovery_bin = adev->discovery.bin;
|
||||
struct binary_header *bhdr;
|
||||
struct table_info *info;
|
||||
struct harvest_table *harvest_info;
|
||||
u16 offset;
|
||||
int i;
|
||||
uint32_t umc_harvest_config = 0;
|
||||
u64 umc_harvest_config = 0;
|
||||
|
||||
bhdr = (struct binary_header *)discovery_bin;
|
||||
offset = le16_to_cpu(bhdr->table_list[HARVEST_INFO].offset);
|
||||
if (amdgpu_discovery_get_table_info(adev, &info, HARVEST_INFO))
|
||||
return;
|
||||
offset = le16_to_cpu(info->offset);
|
||||
|
||||
if (!offset) {
|
||||
dev_err(adev->dev, "invalid harvest table offset\n");
|
||||
|
|
@ -830,7 +850,7 @@ static void amdgpu_discovery_read_from_harvest_table(struct amdgpu_device *adev,
|
|||
}
|
||||
}
|
||||
|
||||
adev->umc.active_mask = ((1 << adev->umc.node_inst_num) - 1) &
|
||||
adev->umc.active_mask = ((1ULL << adev->umc.node_inst_num) - 1ULL) &
|
||||
~umc_harvest_config;
|
||||
}
|
||||
|
||||
|
|
@ -1195,13 +1215,8 @@ static int amdgpu_discovery_sysfs_ips(struct amdgpu_device *adev,
|
|||
ip_hw_instance->num_instance);
|
||||
ip_hw_instance->num_base_addresses = ip->num_base_address;
|
||||
|
||||
for (kk = 0; kk < ip_hw_instance->num_base_addresses; kk++) {
|
||||
if (reg_base_64)
|
||||
ip_hw_instance->base_addr[kk] =
|
||||
lower_32_bits(le64_to_cpu(ip->base_address_64[kk])) & 0x3FFFFFFF;
|
||||
else
|
||||
ip_hw_instance->base_addr[kk] = ip->base_address[kk];
|
||||
}
|
||||
for (kk = 0; kk < ip_hw_instance->num_base_addresses; kk++)
|
||||
ip_hw_instance->base_addr[kk] = ip->base_address[kk];
|
||||
|
||||
kobject_init(&ip_hw_instance->kobj, &ip_hw_instance_ktype);
|
||||
ip_hw_instance->kobj.kset = &ip_hw_id->hw_id_kset;
|
||||
|
|
@ -1224,7 +1239,7 @@ static int amdgpu_discovery_sysfs_recurse(struct amdgpu_device *adev)
|
|||
{
|
||||
struct ip_discovery_top *ip_top = adev->discovery.ip_top;
|
||||
uint8_t *discovery_bin = adev->discovery.bin;
|
||||
struct binary_header *bhdr;
|
||||
struct table_info *info;
|
||||
struct ip_discovery_header *ihdr;
|
||||
struct die_header *dhdr;
|
||||
struct kset *die_kset = &ip_top->die_kset;
|
||||
|
|
@ -1232,10 +1247,12 @@ static int amdgpu_discovery_sysfs_recurse(struct amdgpu_device *adev)
|
|||
size_t ip_offset;
|
||||
int ii, res;
|
||||
|
||||
bhdr = (struct binary_header *)discovery_bin;
|
||||
res = amdgpu_discovery_get_table_info(adev, &info, IP_DISCOVERY);
|
||||
if (res)
|
||||
return res;
|
||||
ihdr = (struct ip_discovery_header
|
||||
*)(discovery_bin +
|
||||
le16_to_cpu(bhdr->table_list[IP_DISCOVERY].offset));
|
||||
le16_to_cpu(info->offset));
|
||||
num_dies = le16_to_cpu(ihdr->num_dies);
|
||||
|
||||
DRM_DEBUG("number of dies: %d\n", num_dies);
|
||||
|
|
@ -1379,12 +1396,54 @@ static void amdgpu_discovery_sysfs_fini(struct amdgpu_device *adev)
|
|||
kobject_put(&ip_top->kobj);
|
||||
}
|
||||
|
||||
/* devcoredump support */
|
||||
void amdgpu_discovery_dump(struct amdgpu_device *adev, struct drm_printer *p)
|
||||
{
|
||||
struct ip_discovery_top *ip_top = adev->discovery.ip_top;
|
||||
struct ip_die_entry *ip_die_entry;
|
||||
struct list_head *el_die, *el_hw_id, *el_hw_inst;
|
||||
struct ip_hw_id *hw_id;
|
||||
struct kset *die_kset;
|
||||
struct ip_hw_instance *ip_inst;
|
||||
int i = 0, j;
|
||||
|
||||
die_kset = &ip_top->die_kset;
|
||||
|
||||
drm_printf(p, "\nHW IP Discovery\n");
|
||||
spin_lock(&die_kset->list_lock);
|
||||
list_for_each(el_die, &die_kset->list) {
|
||||
drm_printf(p, "die %d\n", i++);
|
||||
ip_die_entry = to_ip_die_entry(list_to_kobj(el_die));
|
||||
|
||||
list_for_each(el_hw_id, &ip_die_entry->ip_kset.list) {
|
||||
hw_id = to_ip_hw_id(list_to_kobj(el_hw_id));
|
||||
drm_printf(p, "hw_id %d %s\n", hw_id->hw_id, hw_id_names[hw_id->hw_id]);
|
||||
|
||||
list_for_each(el_hw_inst, &hw_id->hw_id_kset.list) {
|
||||
ip_inst = to_ip_hw_instance(list_to_kobj(el_hw_inst));
|
||||
drm_printf(p, "\tinstance %d\n", ip_inst->num_instance);
|
||||
drm_printf(p, "\tmajor %d\n", ip_inst->major);
|
||||
drm_printf(p, "\tminor %d\n", ip_inst->minor);
|
||||
drm_printf(p, "\trevision %d\n", ip_inst->revision);
|
||||
drm_printf(p, "\tharvest 0x%01X\n", ip_inst->harvest);
|
||||
drm_printf(p, "\tnum_base_addresses %d\n",
|
||||
ip_inst->num_base_addresses);
|
||||
for (j = 0; j < ip_inst->num_base_addresses; j++)
|
||||
drm_printf(p, "\tbase_addr[%d] 0x%08X\n",
|
||||
j, ip_inst->base_addr[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
spin_unlock(&die_kset->list_lock);
|
||||
}
|
||||
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
|
||||
{
|
||||
uint8_t num_base_address, subrev, variant;
|
||||
struct binary_header *bhdr;
|
||||
struct table_info *info;
|
||||
struct ip_discovery_header *ihdr;
|
||||
struct die_header *dhdr;
|
||||
uint8_t *discovery_bin;
|
||||
|
|
@ -1409,10 +1468,12 @@ static int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
|
|||
adev->sdma.sdma_mask = 0;
|
||||
adev->vcn.inst_mask = 0;
|
||||
adev->jpeg.inst_mask = 0;
|
||||
bhdr = (struct binary_header *)discovery_bin;
|
||||
r = amdgpu_discovery_get_table_info(adev, &info, IP_DISCOVERY);
|
||||
if (r)
|
||||
return r;
|
||||
ihdr = (struct ip_discovery_header
|
||||
*)(discovery_bin +
|
||||
le16_to_cpu(bhdr->table_list[IP_DISCOVERY].offset));
|
||||
le16_to_cpu(info->offset));
|
||||
num_dies = le16_to_cpu(ihdr->num_dies);
|
||||
|
||||
DRM_DEBUG("number of dies: %d\n", num_dies);
|
||||
|
|
@ -1585,14 +1646,15 @@ static void amdgpu_discovery_harvest_ip(struct amdgpu_device *adev)
|
|||
{
|
||||
uint8_t *discovery_bin = adev->discovery.bin;
|
||||
struct ip_discovery_header *ihdr;
|
||||
struct binary_header *bhdr;
|
||||
struct table_info *info;
|
||||
int vcn_harvest_count = 0;
|
||||
int umc_harvest_count = 0;
|
||||
uint16_t offset, ihdr_ver;
|
||||
uint16_t ihdr_ver;
|
||||
|
||||
bhdr = (struct binary_header *)discovery_bin;
|
||||
offset = le16_to_cpu(bhdr->table_list[IP_DISCOVERY].offset);
|
||||
ihdr = (struct ip_discovery_header *)(discovery_bin + offset);
|
||||
if (amdgpu_discovery_get_table_info(adev, &info, IP_DISCOVERY))
|
||||
return;
|
||||
ihdr = (struct ip_discovery_header *)(discovery_bin +
|
||||
le16_to_cpu(info->offset));
|
||||
ihdr_ver = le16_to_cpu(ihdr->version);
|
||||
/*
|
||||
* Harvest table does not fit Navi1x and legacy GPUs,
|
||||
|
|
@ -1640,7 +1702,7 @@ union gc_info {
|
|||
static int amdgpu_discovery_get_gfx_info(struct amdgpu_device *adev)
|
||||
{
|
||||
uint8_t *discovery_bin = adev->discovery.bin;
|
||||
struct binary_header *bhdr;
|
||||
struct table_info *info;
|
||||
union gc_info *gc_info;
|
||||
u16 offset;
|
||||
|
||||
|
|
@ -1649,8 +1711,9 @@ static int amdgpu_discovery_get_gfx_info(struct amdgpu_device *adev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
bhdr = (struct binary_header *)discovery_bin;
|
||||
offset = le16_to_cpu(bhdr->table_list[GC].offset);
|
||||
if (amdgpu_discovery_get_table_info(adev, &info, GC))
|
||||
return -EINVAL;
|
||||
offset = le16_to_cpu(info->offset);
|
||||
|
||||
if (!offset)
|
||||
return 0;
|
||||
|
|
@ -1749,7 +1812,7 @@ union mall_info {
|
|||
static int amdgpu_discovery_get_mall_info(struct amdgpu_device *adev)
|
||||
{
|
||||
uint8_t *discovery_bin = adev->discovery.bin;
|
||||
struct binary_header *bhdr;
|
||||
struct table_info *info;
|
||||
union mall_info *mall_info;
|
||||
u32 u, mall_size_per_umc, m_s_present, half_use;
|
||||
u64 mall_size;
|
||||
|
|
@ -1760,8 +1823,9 @@ static int amdgpu_discovery_get_mall_info(struct amdgpu_device *adev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
bhdr = (struct binary_header *)discovery_bin;
|
||||
offset = le16_to_cpu(bhdr->table_list[MALL_INFO].offset);
|
||||
if (amdgpu_discovery_get_table_info(adev, &info, MALL_INFO))
|
||||
return -EINVAL;
|
||||
offset = le16_to_cpu(info->offset);
|
||||
|
||||
if (!offset)
|
||||
return 0;
|
||||
|
|
@ -1806,7 +1870,7 @@ union vcn_info {
|
|||
static int amdgpu_discovery_get_vcn_info(struct amdgpu_device *adev)
|
||||
{
|
||||
uint8_t *discovery_bin = adev->discovery.bin;
|
||||
struct binary_header *bhdr;
|
||||
struct table_info *info;
|
||||
union vcn_info *vcn_info;
|
||||
u16 offset;
|
||||
int v;
|
||||
|
|
@ -1826,8 +1890,9 @@ static int amdgpu_discovery_get_vcn_info(struct amdgpu_device *adev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
bhdr = (struct binary_header *)discovery_bin;
|
||||
offset = le16_to_cpu(bhdr->table_list[VCN_INFO].offset);
|
||||
if (amdgpu_discovery_get_table_info(adev, &info, VCN_INFO))
|
||||
return -EINVAL;
|
||||
offset = le16_to_cpu(info->offset);
|
||||
|
||||
if (!offset)
|
||||
return 0;
|
||||
|
|
@ -1864,14 +1929,26 @@ static int amdgpu_discovery_refresh_nps_info(struct amdgpu_device *adev,
|
|||
uint64_t vram_size, pos, offset;
|
||||
struct nps_info_header *nhdr;
|
||||
struct binary_header bhdr;
|
||||
struct binary_header_v2 bhdrv2;
|
||||
uint16_t checksum;
|
||||
|
||||
vram_size = (uint64_t)RREG32(mmRCC_CONFIG_MEMSIZE) << 20;
|
||||
pos = vram_size - DISCOVERY_TMR_OFFSET;
|
||||
amdgpu_device_vram_access(adev, pos, &bhdr, sizeof(bhdr), false);
|
||||
|
||||
offset = le16_to_cpu(bhdr.table_list[NPS_INFO].offset);
|
||||
checksum = le16_to_cpu(bhdr.table_list[NPS_INFO].checksum);
|
||||
switch (bhdr.version_major) {
|
||||
case 2:
|
||||
amdgpu_device_vram_access(adev, pos, &bhdrv2, sizeof(bhdrv2), false);
|
||||
offset = le16_to_cpu(bhdrv2.table_list[NPS_INFO].offset);
|
||||
checksum = le16_to_cpu(bhdrv2.table_list[NPS_INFO].checksum);
|
||||
break;
|
||||
case 1:
|
||||
offset = le16_to_cpu(bhdr.table_list[NPS_INFO].offset);
|
||||
checksum = le16_to_cpu(bhdr.table_list[NPS_INFO].checksum);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
amdgpu_device_vram_access(adev, (pos + offset), nps_data,
|
||||
sizeof(*nps_data), false);
|
||||
|
|
@ -1894,7 +1971,7 @@ int amdgpu_discovery_get_nps_info(struct amdgpu_device *adev,
|
|||
{
|
||||
uint8_t *discovery_bin = adev->discovery.bin;
|
||||
struct amdgpu_gmc_memrange *mem_ranges;
|
||||
struct binary_header *bhdr;
|
||||
struct table_info *info;
|
||||
union nps_info *nps_info;
|
||||
union nps_info nps_data;
|
||||
u16 offset;
|
||||
|
|
@ -1915,14 +1992,15 @@ int amdgpu_discovery_get_nps_info(struct amdgpu_device *adev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
bhdr = (struct binary_header *)discovery_bin;
|
||||
offset = le16_to_cpu(bhdr->table_list[NPS_INFO].offset);
|
||||
if (amdgpu_discovery_get_table_info(adev, &info, NPS_INFO))
|
||||
return -EINVAL;
|
||||
offset = le16_to_cpu(info->offset);
|
||||
|
||||
if (!offset)
|
||||
return -ENOENT;
|
||||
|
||||
/* If verification fails, return as if NPS table doesn't exist */
|
||||
if (amdgpu_discovery_verify_npsinfo(adev, bhdr))
|
||||
if (amdgpu_discovery_verify_npsinfo(adev, info))
|
||||
return -ENOENT;
|
||||
|
||||
nps_info = (union nps_info *)(discovery_bin + offset);
|
||||
|
|
@ -3226,6 +3304,9 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
|||
case IP_VERSION(7, 0, 1):
|
||||
adev->lsdma.funcs = &lsdma_v7_0_funcs;
|
||||
break;
|
||||
case IP_VERSION(7, 1, 0):
|
||||
adev->lsdma.funcs = &lsdma_v7_1_funcs;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,10 +30,12 @@
|
|||
#define DISCOVERY_TMR_OFFSET (64 << 10)
|
||||
|
||||
struct ip_discovery_top;
|
||||
struct drm_printer;
|
||||
|
||||
struct amdgpu_discovery_info {
|
||||
struct debugfs_blob_wrapper debugfs_blob;
|
||||
struct ip_discovery_top *ip_top;
|
||||
uint64_t offset;
|
||||
uint32_t size;
|
||||
uint8_t *bin;
|
||||
bool reserve_tmr;
|
||||
|
|
@ -47,4 +49,6 @@ int amdgpu_discovery_get_nps_info(struct amdgpu_device *adev,
|
|||
struct amdgpu_gmc_memrange **ranges,
|
||||
int *range_cnt, bool refresh);
|
||||
|
||||
void amdgpu_discovery_dump(struct amdgpu_device *adev, struct drm_printer *p);
|
||||
|
||||
#endif /* __AMDGPU_DISCOVERY__ */
|
||||
|
|
|
|||
|
|
@ -1738,21 +1738,6 @@ bool amdgpu_crtc_get_scanout_position(struct drm_crtc *crtc,
|
|||
stime, etime, mode);
|
||||
}
|
||||
|
||||
static bool
|
||||
amdgpu_display_robj_is_fb(struct amdgpu_device *adev, struct amdgpu_bo *robj)
|
||||
{
|
||||
struct drm_device *dev = adev_to_drm(adev);
|
||||
struct drm_fb_helper *fb_helper = dev->fb_helper;
|
||||
|
||||
if (!fb_helper || !fb_helper->buffer)
|
||||
return false;
|
||||
|
||||
if (gem_to_amdgpu_bo(fb_helper->buffer->gem) != robj)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int amdgpu_display_suspend_helper(struct amdgpu_device *adev)
|
||||
{
|
||||
struct drm_device *dev = adev_to_drm(adev);
|
||||
|
|
@ -1775,7 +1760,6 @@ int amdgpu_display_suspend_helper(struct amdgpu_device *adev)
|
|||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
|
||||
struct drm_framebuffer *fb = crtc->primary->fb;
|
||||
struct amdgpu_bo *robj;
|
||||
|
||||
if (amdgpu_crtc->cursor_bo && !adev->enable_virtual_display) {
|
||||
struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
|
||||
|
|
@ -1790,8 +1774,9 @@ int amdgpu_display_suspend_helper(struct amdgpu_device *adev)
|
|||
if (!fb || !fb->obj[0])
|
||||
continue;
|
||||
|
||||
robj = gem_to_amdgpu_bo(fb->obj[0]);
|
||||
if (!amdgpu_display_robj_is_fb(adev, robj)) {
|
||||
if (!drm_fb_helper_gem_is_fb(dev->fb_helper, fb->obj[0])) {
|
||||
struct amdgpu_bo *robj = gem_to_amdgpu_bo(fb->obj[0]);
|
||||
|
||||
r = amdgpu_bo_reserve(robj, true);
|
||||
if (r == 0) {
|
||||
amdgpu_bo_unpin(robj);
|
||||
|
|
|
|||
|
|
@ -94,6 +94,10 @@ enum amdgpu_memory_partition {
|
|||
#define AMDGPU_GMC9_FAULT_SOURCE_DATA_WRITE 0x20
|
||||
#define AMDGPU_GMC9_FAULT_SOURCE_DATA_EXE 0x10
|
||||
|
||||
#define AMDGPU_GMC121_FAULT_SOURCE_DATA_READ 0x400000
|
||||
#define AMDGPU_GMC121_FAULT_SOURCE_DATA_WRITE 0x200000
|
||||
#define AMDGPU_GMC121_FAULT_SOURCE_DATA_EXE 0x100000
|
||||
|
||||
/*
|
||||
* GMC page fault information
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ void amdgpu_driver_unload_kms(struct drm_device *dev)
|
|||
{
|
||||
struct amdgpu_device *adev = drm_to_adev(dev);
|
||||
|
||||
if (adev == NULL)
|
||||
if (adev == NULL || !adev->num_ip_blocks)
|
||||
return;
|
||||
|
||||
amdgpu_unregister_gpu_instance(adev);
|
||||
|
|
|
|||
|
|
@ -159,9 +159,9 @@ struct amdgpu_mes {
|
|||
|
||||
int hung_queue_db_array_size;
|
||||
int hung_queue_hqd_info_offset;
|
||||
struct amdgpu_bo *hung_queue_db_array_gpu_obj[AMDGPU_MAX_MES_PIPES];
|
||||
uint64_t hung_queue_db_array_gpu_addr[AMDGPU_MAX_MES_PIPES];
|
||||
void *hung_queue_db_array_cpu_addr[AMDGPU_MAX_MES_PIPES];
|
||||
struct amdgpu_bo *hung_queue_db_array_gpu_obj[AMDGPU_MAX_MES_INST_PIPES];
|
||||
uint64_t hung_queue_db_array_gpu_addr[AMDGPU_MAX_MES_INST_PIPES];
|
||||
void *hung_queue_db_array_cpu_addr[AMDGPU_MAX_MES_INST_PIPES];
|
||||
|
||||
/* cooperative dispatch */
|
||||
bool enable_coop_mode;
|
||||
|
|
|
|||
|
|
@ -368,15 +368,15 @@ struct amdgpu_mode_info {
|
|||
|
||||
struct drm_property *plane_ctm_property;
|
||||
/**
|
||||
* @shaper_lut_property: Plane property to set pre-blending shaper LUT
|
||||
* that converts color content before 3D LUT. If
|
||||
* plane_shaper_tf_property != Identity TF, AMD color module will
|
||||
* @plane_shaper_lut_property: Plane property to set pre-blending
|
||||
* shaper LUT that converts color content before 3D LUT.
|
||||
* If plane_shaper_tf_property != Identity TF, AMD color module will
|
||||
* combine the user LUT values with pre-defined TF into the LUT
|
||||
* parameters to be programmed.
|
||||
*/
|
||||
struct drm_property *plane_shaper_lut_property;
|
||||
/**
|
||||
* @shaper_lut_size_property: Plane property for the size of
|
||||
* @plane_shaper_lut_size_property: Plane property for the size of
|
||||
* pre-blending shaper LUT as supported by the driver (read-only).
|
||||
*/
|
||||
struct drm_property *plane_shaper_lut_size_property;
|
||||
|
|
@ -400,10 +400,10 @@ struct amdgpu_mode_info {
|
|||
*/
|
||||
struct drm_property *plane_lut3d_property;
|
||||
/**
|
||||
* @plane_degamma_lut_size_property: Plane property to define the max
|
||||
* size of 3D LUT as supported by the driver (read-only). The max size
|
||||
* is the max size of one dimension and, therefore, the max number of
|
||||
* entries for 3D LUT array is the 3D LUT size cubed;
|
||||
* @plane_lut3d_size_property: Plane property to define the max size
|
||||
* of 3D LUT as supported by the driver (read-only). The max size is
|
||||
* the max size of one dimension and, therefore, the max number of
|
||||
* entries for 3D LUT array is the 3D LUT size cubed.
|
||||
*/
|
||||
struct drm_property *plane_lut3d_size_property;
|
||||
/**
|
||||
|
|
@ -624,7 +624,7 @@ struct amdgpu_connector {
|
|||
bool use_digital;
|
||||
/* we need to mind the EDID between detect
|
||||
and get modes due to analog/digital/tvencoder */
|
||||
struct edid *edid;
|
||||
const struct drm_edid *edid;
|
||||
void *con_priv;
|
||||
bool dac_load_detect;
|
||||
bool detected_by_load; /* if the connection status was determined by load */
|
||||
|
|
|
|||
|
|
@ -3096,6 +3096,13 @@ static int psp_load_non_psp_fw(struct psp_context *psp)
|
|||
*/
|
||||
continue;
|
||||
|
||||
/* IMU ucode is part of IFWI and MP0 15.0.8 would load it */
|
||||
if (amdgpu_ip_version(adev, MP0_HWIP, 0) ==
|
||||
IP_VERSION(15, 0, 8) &&
|
||||
(ucode->ucode_id == AMDGPU_UCODE_ID_IMU_I ||
|
||||
ucode->ucode_id == AMDGPU_UCODE_ID_IMU_D))
|
||||
continue;
|
||||
|
||||
psp_print_fw_hdr(psp, ucode);
|
||||
|
||||
ret = psp_execute_ip_fw_load(psp, ucode);
|
||||
|
|
|
|||
|
|
@ -291,22 +291,22 @@ void amdgpu_ucode_print_rlc_hdr(const struct common_firmware_header *hdr)
|
|||
break;
|
||||
case 5:
|
||||
/* rlc_hdr v2_5 */
|
||||
DRM_INFO("rlc_iram_ucode_size_bytes: %u\n",
|
||||
DRM_DEBUG("rlc_iram_ucode_size_bytes: %u\n",
|
||||
le32_to_cpu(rlc_hdr_v2_5->v2_2.rlc_iram_ucode_size_bytes));
|
||||
DRM_INFO("rlc_iram_ucode_offset_bytes: %u\n",
|
||||
DRM_DEBUG("rlc_iram_ucode_offset_bytes: %u\n",
|
||||
le32_to_cpu(rlc_hdr_v2_5->v2_2.rlc_iram_ucode_offset_bytes));
|
||||
DRM_INFO("rlc_dram_ucode_size_bytes: %u\n",
|
||||
DRM_DEBUG("rlc_dram_ucode_size_bytes: %u\n",
|
||||
le32_to_cpu(rlc_hdr_v2_5->v2_2.rlc_dram_ucode_size_bytes));
|
||||
DRM_INFO("rlc_dram_ucode_offset_bytes: %u\n",
|
||||
DRM_DEBUG("rlc_dram_ucode_offset_bytes: %u\n",
|
||||
le32_to_cpu(rlc_hdr_v2_5->v2_2.rlc_dram_ucode_offset_bytes));
|
||||
/* rlc_hdr v2_5 */
|
||||
DRM_INFO("rlc_1_iram_ucode_size_bytes: %u\n",
|
||||
DRM_DEBUG("rlc_1_iram_ucode_size_bytes: %u\n",
|
||||
le32_to_cpu(rlc_hdr_v2_5->rlc_1_iram_ucode_size_bytes));
|
||||
DRM_INFO("rlc_1_iram_ucode_offset_bytes: %u\n",
|
||||
DRM_DEBUG("rlc_1_iram_ucode_offset_bytes: %u\n",
|
||||
le32_to_cpu(rlc_hdr_v2_5->rlc_1_iram_ucode_offset_bytes));
|
||||
DRM_INFO("rlc_1_dram_ucode_size_bytes: %u\n",
|
||||
DRM_DEBUG("rlc_1_dram_ucode_size_bytes: %u\n",
|
||||
le32_to_cpu(rlc_hdr_v2_5->rlc_1_dram_ucode_size_bytes));
|
||||
DRM_INFO("rlc_1_dram_ucode_offset_bytes: %u\n",
|
||||
DRM_DEBUG("rlc_1_dram_ucode_offset_bytes: %u\n",
|
||||
le32_to_cpu(rlc_hdr_v2_5->rlc_1_dram_ucode_offset_bytes));
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -709,46 +709,6 @@ static int amdgpu_userq_priority_permit(struct drm_file *filp,
|
|||
return -EACCES;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
static int amdgpu_mqd_info_read(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct amdgpu_usermode_queue *queue = m->private;
|
||||
struct amdgpu_bo *bo;
|
||||
int r;
|
||||
|
||||
if (!queue || !queue->mqd.obj)
|
||||
return -EINVAL;
|
||||
|
||||
bo = amdgpu_bo_ref(queue->mqd.obj);
|
||||
r = amdgpu_bo_reserve(bo, true);
|
||||
if (r) {
|
||||
amdgpu_bo_unref(&bo);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
seq_printf(m, "queue_type: %d\n", queue->queue_type);
|
||||
seq_printf(m, "mqd_gpu_address: 0x%llx\n", amdgpu_bo_gpu_offset(queue->mqd.obj));
|
||||
|
||||
amdgpu_bo_unreserve(bo);
|
||||
amdgpu_bo_unref(&bo);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_mqd_info_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, amdgpu_mqd_info_read, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations amdgpu_mqd_info_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = amdgpu_mqd_info_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
#endif
|
||||
|
||||
static int
|
||||
amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
|
||||
{
|
||||
|
|
@ -758,7 +718,6 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
|
|||
const struct amdgpu_userq_funcs *uq_funcs;
|
||||
struct amdgpu_usermode_queue *queue;
|
||||
struct amdgpu_db_info db_info;
|
||||
char *queue_name;
|
||||
bool skip_map_queue;
|
||||
u32 qid;
|
||||
uint64_t index;
|
||||
|
|
@ -819,17 +778,15 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
|
|||
amdgpu_userq_input_va_validate(adev, queue, args->in.rptr_va, AMDGPU_GPU_PAGE_SIZE) ||
|
||||
amdgpu_userq_input_va_validate(adev, queue, args->in.wptr_va, AMDGPU_GPU_PAGE_SIZE)) {
|
||||
r = -EINVAL;
|
||||
kfree(queue);
|
||||
goto unlock;
|
||||
goto free_queue;
|
||||
}
|
||||
|
||||
/* Convert relative doorbell offset into absolute doorbell index */
|
||||
index = amdgpu_userq_get_doorbell_index(uq_mgr, &db_info, filp);
|
||||
if (index == (uint64_t)-EINVAL) {
|
||||
drm_file_err(uq_mgr->file, "Failed to get doorbell for queue\n");
|
||||
kfree(queue);
|
||||
r = -EINVAL;
|
||||
goto unlock;
|
||||
goto free_queue;
|
||||
}
|
||||
|
||||
queue->doorbell_index = index;
|
||||
|
|
@ -837,42 +794,15 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
|
|||
r = amdgpu_userq_fence_driver_alloc(adev, queue);
|
||||
if (r) {
|
||||
drm_file_err(uq_mgr->file, "Failed to alloc fence driver\n");
|
||||
goto unlock;
|
||||
goto free_queue;
|
||||
}
|
||||
|
||||
r = uq_funcs->mqd_create(queue, &args->in);
|
||||
if (r) {
|
||||
drm_file_err(uq_mgr->file, "Failed to create Queue\n");
|
||||
amdgpu_userq_fence_driver_free(queue);
|
||||
kfree(queue);
|
||||
goto unlock;
|
||||
goto clean_fence_driver;
|
||||
}
|
||||
|
||||
/* drop this refcount during queue destroy */
|
||||
kref_init(&queue->refcount);
|
||||
|
||||
/* Wait for mode-1 reset to complete */
|
||||
down_read(&adev->reset_domain->sem);
|
||||
r = xa_err(xa_store_irq(&adev->userq_doorbell_xa, index, queue, GFP_KERNEL));
|
||||
if (r) {
|
||||
kfree(queue);
|
||||
up_read(&adev->reset_domain->sem);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
r = xa_alloc(&uq_mgr->userq_xa, &qid, queue,
|
||||
XA_LIMIT(1, AMDGPU_MAX_USERQ_COUNT), GFP_KERNEL);
|
||||
if (r) {
|
||||
drm_file_err(uq_mgr->file, "Failed to allocate a queue id\n");
|
||||
amdgpu_userq_fence_driver_free(queue);
|
||||
uq_funcs->mqd_destroy(queue);
|
||||
kfree(queue);
|
||||
r = -ENOMEM;
|
||||
up_read(&adev->reset_domain->sem);
|
||||
goto unlock;
|
||||
}
|
||||
up_read(&adev->reset_domain->sem);
|
||||
|
||||
/* don't map the queue if scheduling is halted */
|
||||
if (adev->userq_halt_for_enforce_isolation &&
|
||||
((queue->queue_type == AMDGPU_HW_IP_GFX) ||
|
||||
|
|
@ -884,31 +814,52 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
|
|||
r = amdgpu_userq_map_helper(queue);
|
||||
if (r) {
|
||||
drm_file_err(uq_mgr->file, "Failed to map Queue\n");
|
||||
xa_erase(&uq_mgr->userq_xa, qid);
|
||||
amdgpu_userq_fence_driver_free(queue);
|
||||
uq_funcs->mqd_destroy(queue);
|
||||
kfree(queue);
|
||||
goto unlock;
|
||||
down_read(&adev->reset_domain->sem);
|
||||
goto clean_mqd;
|
||||
}
|
||||
}
|
||||
|
||||
queue_name = kasprintf(GFP_KERNEL, "queue-%d", qid);
|
||||
if (!queue_name) {
|
||||
/* drop this refcount during queue destroy */
|
||||
kref_init(&queue->refcount);
|
||||
|
||||
/* Wait for mode-1 reset to complete */
|
||||
down_read(&adev->reset_domain->sem);
|
||||
|
||||
r = xa_alloc(&uq_mgr->userq_xa, &qid, queue,
|
||||
XA_LIMIT(1, AMDGPU_MAX_USERQ_COUNT), GFP_KERNEL);
|
||||
if (r) {
|
||||
if (!skip_map_queue)
|
||||
amdgpu_userq_unmap_helper(queue);
|
||||
|
||||
r = -ENOMEM;
|
||||
goto unlock;
|
||||
goto clean_mqd;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
/* Queue dentry per client to hold MQD information */
|
||||
queue->debugfs_queue = debugfs_create_dir(queue_name, filp->debugfs_client);
|
||||
debugfs_create_file("mqd_info", 0444, queue->debugfs_queue, queue, &amdgpu_mqd_info_fops);
|
||||
#endif
|
||||
r = xa_err(xa_store_irq(&adev->userq_doorbell_xa, index, queue, GFP_KERNEL));
|
||||
if (r) {
|
||||
xa_erase(&uq_mgr->userq_xa, qid);
|
||||
if (!skip_map_queue)
|
||||
amdgpu_userq_unmap_helper(queue);
|
||||
|
||||
goto clean_mqd;
|
||||
}
|
||||
up_read(&adev->reset_domain->sem);
|
||||
|
||||
amdgpu_debugfs_userq_init(filp, queue, qid);
|
||||
amdgpu_userq_init_hang_detect_work(queue);
|
||||
kfree(queue_name);
|
||||
|
||||
args->out.queue_id = qid;
|
||||
atomic_inc(&uq_mgr->userq_count[queue->queue_type]);
|
||||
mutex_unlock(&uq_mgr->userq_mutex);
|
||||
return 0;
|
||||
|
||||
clean_mqd:
|
||||
uq_funcs->mqd_destroy(queue);
|
||||
up_read(&adev->reset_domain->sem);
|
||||
clean_fence_driver:
|
||||
amdgpu_userq_fence_driver_free(queue);
|
||||
free_queue:
|
||||
kfree(queue);
|
||||
unlock:
|
||||
mutex_unlock(&uq_mgr->userq_mutex);
|
||||
|
||||
|
|
@ -1089,12 +1040,12 @@ amdgpu_userq_bo_validate(struct amdgpu_device *adev, struct drm_exec *exec,
|
|||
struct amdgpu_bo *bo;
|
||||
int ret;
|
||||
|
||||
spin_lock(&vm->status_lock);
|
||||
spin_lock(&vm->invalidated_lock);
|
||||
while (!list_empty(&vm->invalidated)) {
|
||||
bo_va = list_first_entry(&vm->invalidated,
|
||||
struct amdgpu_bo_va,
|
||||
base.vm_status);
|
||||
spin_unlock(&vm->status_lock);
|
||||
spin_unlock(&vm->invalidated_lock);
|
||||
|
||||
bo = bo_va->base.bo;
|
||||
ret = drm_exec_prepare_obj(exec, &bo->tbo.base, 2);
|
||||
|
|
@ -1111,9 +1062,9 @@ amdgpu_userq_bo_validate(struct amdgpu_device *adev, struct drm_exec *exec,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
spin_lock(&vm->status_lock);
|
||||
spin_lock(&vm->invalidated_lock);
|
||||
}
|
||||
spin_unlock(&vm->status_lock);
|
||||
spin_unlock(&vm->invalidated_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -162,6 +162,7 @@ enum AMDGIM_FEATURE_FLAG {
|
|||
AMDGIM_FEATURE_RAS_TELEMETRY = (1 << 10),
|
||||
AMDGIM_FEATURE_RAS_CPER = (1 << 11),
|
||||
AMDGIM_FEATURE_XGMI_TA_EXT_PEER_LINK = (1 << 12),
|
||||
AMDGIM_FEATURE_XGMI_CONNECTED_TO_CPU = (1 << 13),
|
||||
};
|
||||
|
||||
enum AMDGIM_REG_ACCESS_FLAG {
|
||||
|
|
@ -412,6 +413,9 @@ struct amdgpu_video_codec_info;
|
|||
#define amdgpu_sriov_xgmi_ta_ext_peer_link_en(adev) \
|
||||
((adev)->virt.gim_feature & AMDGIM_FEATURE_XGMI_TA_EXT_PEER_LINK)
|
||||
|
||||
#define amdgpu_sriov_xgmi_connected_to_cpu(adev) \
|
||||
((adev)->virt.gim_feature & AMDGIM_FEATURE_XGMI_CONNECTED_TO_CPU)
|
||||
|
||||
static inline bool is_virtual_machine(void)
|
||||
{
|
||||
#if defined(CONFIG_X86)
|
||||
|
|
|
|||
|
|
@ -153,12 +153,10 @@ static void amdgpu_vm_bo_evicted(struct amdgpu_vm_bo_base *vm_bo)
|
|||
|
||||
vm_bo->moved = true;
|
||||
amdgpu_vm_assert_locked(vm);
|
||||
spin_lock(&vm_bo->vm->status_lock);
|
||||
if (bo->tbo.type == ttm_bo_type_kernel)
|
||||
list_move(&vm_bo->vm_status, &vm->evicted);
|
||||
else
|
||||
list_move_tail(&vm_bo->vm_status, &vm->evicted);
|
||||
spin_unlock(&vm_bo->vm->status_lock);
|
||||
}
|
||||
/**
|
||||
* amdgpu_vm_bo_moved - vm_bo is moved
|
||||
|
|
@ -171,9 +169,7 @@ static void amdgpu_vm_bo_evicted(struct amdgpu_vm_bo_base *vm_bo)
|
|||
static void amdgpu_vm_bo_moved(struct amdgpu_vm_bo_base *vm_bo)
|
||||
{
|
||||
amdgpu_vm_assert_locked(vm_bo->vm);
|
||||
spin_lock(&vm_bo->vm->status_lock);
|
||||
list_move(&vm_bo->vm_status, &vm_bo->vm->moved);
|
||||
spin_unlock(&vm_bo->vm->status_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -187,9 +183,7 @@ static void amdgpu_vm_bo_moved(struct amdgpu_vm_bo_base *vm_bo)
|
|||
static void amdgpu_vm_bo_idle(struct amdgpu_vm_bo_base *vm_bo)
|
||||
{
|
||||
amdgpu_vm_assert_locked(vm_bo->vm);
|
||||
spin_lock(&vm_bo->vm->status_lock);
|
||||
list_move(&vm_bo->vm_status, &vm_bo->vm->idle);
|
||||
spin_unlock(&vm_bo->vm->status_lock);
|
||||
vm_bo->moved = false;
|
||||
}
|
||||
|
||||
|
|
@ -203,9 +197,9 @@ static void amdgpu_vm_bo_idle(struct amdgpu_vm_bo_base *vm_bo)
|
|||
*/
|
||||
static void amdgpu_vm_bo_invalidated(struct amdgpu_vm_bo_base *vm_bo)
|
||||
{
|
||||
spin_lock(&vm_bo->vm->status_lock);
|
||||
spin_lock(&vm_bo->vm->invalidated_lock);
|
||||
list_move(&vm_bo->vm_status, &vm_bo->vm->invalidated);
|
||||
spin_unlock(&vm_bo->vm->status_lock);
|
||||
spin_unlock(&vm_bo->vm->invalidated_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -218,10 +212,9 @@ static void amdgpu_vm_bo_invalidated(struct amdgpu_vm_bo_base *vm_bo)
|
|||
*/
|
||||
static void amdgpu_vm_bo_evicted_user(struct amdgpu_vm_bo_base *vm_bo)
|
||||
{
|
||||
amdgpu_vm_assert_locked(vm_bo->vm);
|
||||
vm_bo->moved = true;
|
||||
spin_lock(&vm_bo->vm->status_lock);
|
||||
list_move(&vm_bo->vm_status, &vm_bo->vm->evicted_user);
|
||||
spin_unlock(&vm_bo->vm->status_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -235,13 +228,10 @@ static void amdgpu_vm_bo_evicted_user(struct amdgpu_vm_bo_base *vm_bo)
|
|||
static void amdgpu_vm_bo_relocated(struct amdgpu_vm_bo_base *vm_bo)
|
||||
{
|
||||
amdgpu_vm_assert_locked(vm_bo->vm);
|
||||
if (vm_bo->bo->parent) {
|
||||
spin_lock(&vm_bo->vm->status_lock);
|
||||
if (vm_bo->bo->parent)
|
||||
list_move(&vm_bo->vm_status, &vm_bo->vm->relocated);
|
||||
spin_unlock(&vm_bo->vm->status_lock);
|
||||
} else {
|
||||
else
|
||||
amdgpu_vm_bo_idle(vm_bo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -255,9 +245,7 @@ static void amdgpu_vm_bo_relocated(struct amdgpu_vm_bo_base *vm_bo)
|
|||
static void amdgpu_vm_bo_done(struct amdgpu_vm_bo_base *vm_bo)
|
||||
{
|
||||
amdgpu_vm_assert_locked(vm_bo->vm);
|
||||
spin_lock(&vm_bo->vm->status_lock);
|
||||
list_move(&vm_bo->vm_status, &vm_bo->vm->done);
|
||||
spin_unlock(&vm_bo->vm->status_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -271,13 +259,13 @@ static void amdgpu_vm_bo_reset_state_machine(struct amdgpu_vm *vm)
|
|||
{
|
||||
struct amdgpu_vm_bo_base *vm_bo, *tmp;
|
||||
|
||||
amdgpu_vm_assert_locked(vm);
|
||||
|
||||
spin_lock(&vm->status_lock);
|
||||
spin_lock(&vm->invalidated_lock);
|
||||
list_splice_init(&vm->done, &vm->invalidated);
|
||||
list_for_each_entry(vm_bo, &vm->invalidated, vm_status)
|
||||
vm_bo->moved = true;
|
||||
spin_unlock(&vm->invalidated_lock);
|
||||
|
||||
amdgpu_vm_assert_locked(vm);
|
||||
list_for_each_entry_safe(vm_bo, tmp, &vm->idle, vm_status) {
|
||||
struct amdgpu_bo *bo = vm_bo->bo;
|
||||
|
||||
|
|
@ -287,14 +275,13 @@ static void amdgpu_vm_bo_reset_state_machine(struct amdgpu_vm *vm)
|
|||
else if (bo->parent)
|
||||
list_move(&vm_bo->vm_status, &vm_bo->vm->relocated);
|
||||
}
|
||||
spin_unlock(&vm->status_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_vm_update_shared - helper to update shared memory stat
|
||||
* @base: base structure for tracking BO usage in a VM
|
||||
*
|
||||
* Takes the vm status_lock and updates the shared memory stat. If the basic
|
||||
* Takes the vm stats_lock and updates the shared memory stat. If the basic
|
||||
* stat changed (e.g. buffer was moved) amdgpu_vm_update_stats need to be called
|
||||
* as well.
|
||||
*/
|
||||
|
|
@ -307,7 +294,7 @@ static void amdgpu_vm_update_shared(struct amdgpu_vm_bo_base *base)
|
|||
bool shared;
|
||||
|
||||
dma_resv_assert_held(bo->tbo.base.resv);
|
||||
spin_lock(&vm->status_lock);
|
||||
spin_lock(&vm->stats_lock);
|
||||
shared = drm_gem_object_is_shared_for_memory_stats(&bo->tbo.base);
|
||||
if (base->shared != shared) {
|
||||
base->shared = shared;
|
||||
|
|
@ -319,7 +306,7 @@ static void amdgpu_vm_update_shared(struct amdgpu_vm_bo_base *base)
|
|||
vm->stats[bo_memtype].drm.private += size;
|
||||
}
|
||||
}
|
||||
spin_unlock(&vm->status_lock);
|
||||
spin_unlock(&vm->stats_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -344,11 +331,11 @@ void amdgpu_vm_bo_update_shared(struct amdgpu_bo *bo)
|
|||
* be bo->tbo.resource
|
||||
* @sign: if we should add (+1) or subtract (-1) from the stat
|
||||
*
|
||||
* Caller need to have the vm status_lock held. Useful for when multiple update
|
||||
* Caller need to have the vm stats_lock held. Useful for when multiple update
|
||||
* need to happen at the same time.
|
||||
*/
|
||||
static void amdgpu_vm_update_stats_locked(struct amdgpu_vm_bo_base *base,
|
||||
struct ttm_resource *res, int sign)
|
||||
struct ttm_resource *res, int sign)
|
||||
{
|
||||
struct amdgpu_vm *vm = base->vm;
|
||||
struct amdgpu_bo *bo = base->bo;
|
||||
|
|
@ -372,7 +359,8 @@ static void amdgpu_vm_update_stats_locked(struct amdgpu_vm_bo_base *base,
|
|||
*/
|
||||
if (bo->flags & AMDGPU_GEM_CREATE_DISCARDABLE)
|
||||
vm->stats[res_memtype].drm.purgeable += size;
|
||||
if (!(bo->preferred_domains & amdgpu_mem_type_to_domain(res_memtype)))
|
||||
if (!(bo->preferred_domains &
|
||||
amdgpu_mem_type_to_domain(res_memtype)))
|
||||
vm->stats[bo_memtype].evicted += size;
|
||||
}
|
||||
}
|
||||
|
|
@ -391,9 +379,9 @@ void amdgpu_vm_update_stats(struct amdgpu_vm_bo_base *base,
|
|||
{
|
||||
struct amdgpu_vm *vm = base->vm;
|
||||
|
||||
spin_lock(&vm->status_lock);
|
||||
spin_lock(&vm->stats_lock);
|
||||
amdgpu_vm_update_stats_locked(base, res, sign);
|
||||
spin_unlock(&vm->status_lock);
|
||||
spin_unlock(&vm->stats_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -419,10 +407,10 @@ void amdgpu_vm_bo_base_init(struct amdgpu_vm_bo_base *base,
|
|||
base->next = bo->vm_bo;
|
||||
bo->vm_bo = base;
|
||||
|
||||
spin_lock(&vm->status_lock);
|
||||
spin_lock(&vm->stats_lock);
|
||||
base->shared = drm_gem_object_is_shared_for_memory_stats(&bo->tbo.base);
|
||||
amdgpu_vm_update_stats_locked(base, bo->tbo.resource, +1);
|
||||
spin_unlock(&vm->status_lock);
|
||||
spin_unlock(&vm->stats_lock);
|
||||
|
||||
if (!amdgpu_vm_is_bo_always_valid(vm, bo))
|
||||
return;
|
||||
|
|
@ -481,25 +469,25 @@ int amdgpu_vm_lock_done_list(struct amdgpu_vm *vm, struct drm_exec *exec,
|
|||
int ret;
|
||||
|
||||
/* We can only trust prev->next while holding the lock */
|
||||
spin_lock(&vm->status_lock);
|
||||
spin_lock(&vm->invalidated_lock);
|
||||
while (!list_is_head(prev->next, &vm->done)) {
|
||||
bo_va = list_entry(prev->next, typeof(*bo_va), base.vm_status);
|
||||
|
||||
bo = bo_va->base.bo;
|
||||
if (bo) {
|
||||
amdgpu_bo_ref(bo);
|
||||
spin_unlock(&vm->status_lock);
|
||||
spin_unlock(&vm->invalidated_lock);
|
||||
|
||||
ret = drm_exec_prepare_obj(exec, &bo->tbo.base, 1);
|
||||
amdgpu_bo_unref(&bo);
|
||||
if (unlikely(ret))
|
||||
return ret;
|
||||
|
||||
spin_lock(&vm->status_lock);
|
||||
spin_lock(&vm->invalidated_lock);
|
||||
}
|
||||
prev = prev->next;
|
||||
}
|
||||
spin_unlock(&vm->status_lock);
|
||||
spin_unlock(&vm->invalidated_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -595,7 +583,7 @@ int amdgpu_vm_validate(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
|||
void *param)
|
||||
{
|
||||
uint64_t new_vm_generation = amdgpu_vm_generation(adev, vm);
|
||||
struct amdgpu_vm_bo_base *bo_base;
|
||||
struct amdgpu_vm_bo_base *bo_base, *tmp;
|
||||
struct amdgpu_bo *bo;
|
||||
int r;
|
||||
|
||||
|
|
@ -608,13 +596,7 @@ int amdgpu_vm_validate(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
|||
return r;
|
||||
}
|
||||
|
||||
spin_lock(&vm->status_lock);
|
||||
while (!list_empty(&vm->evicted)) {
|
||||
bo_base = list_first_entry(&vm->evicted,
|
||||
struct amdgpu_vm_bo_base,
|
||||
vm_status);
|
||||
spin_unlock(&vm->status_lock);
|
||||
|
||||
list_for_each_entry_safe(bo_base, tmp, &vm->evicted, vm_status) {
|
||||
bo = bo_base->bo;
|
||||
|
||||
r = validate(param, bo);
|
||||
|
|
@ -627,26 +609,21 @@ int amdgpu_vm_validate(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
|||
vm->update_funcs->map_table(to_amdgpu_bo_vm(bo));
|
||||
amdgpu_vm_bo_relocated(bo_base);
|
||||
}
|
||||
spin_lock(&vm->status_lock);
|
||||
}
|
||||
while (ticket && !list_empty(&vm->evicted_user)) {
|
||||
bo_base = list_first_entry(&vm->evicted_user,
|
||||
struct amdgpu_vm_bo_base,
|
||||
vm_status);
|
||||
spin_unlock(&vm->status_lock);
|
||||
|
||||
bo = bo_base->bo;
|
||||
dma_resv_assert_held(bo->tbo.base.resv);
|
||||
if (ticket) {
|
||||
list_for_each_entry_safe(bo_base, tmp, &vm->evicted_user,
|
||||
vm_status) {
|
||||
bo = bo_base->bo;
|
||||
dma_resv_assert_held(bo->tbo.base.resv);
|
||||
|
||||
r = validate(param, bo);
|
||||
if (r)
|
||||
return r;
|
||||
r = validate(param, bo);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
amdgpu_vm_bo_invalidated(bo_base);
|
||||
|
||||
spin_lock(&vm->status_lock);
|
||||
amdgpu_vm_bo_invalidated(bo_base);
|
||||
}
|
||||
}
|
||||
spin_unlock(&vm->status_lock);
|
||||
|
||||
amdgpu_vm_eviction_lock(vm);
|
||||
vm->evicting = false;
|
||||
|
|
@ -675,9 +652,7 @@ bool amdgpu_vm_ready(struct amdgpu_vm *vm)
|
|||
ret = !vm->evicting;
|
||||
amdgpu_vm_eviction_unlock(vm);
|
||||
|
||||
spin_lock(&vm->status_lock);
|
||||
ret &= list_empty(&vm->evicted);
|
||||
spin_unlock(&vm->status_lock);
|
||||
|
||||
spin_lock(&vm->immediate.lock);
|
||||
ret &= !vm->immediate.stopped;
|
||||
|
|
@ -971,18 +946,13 @@ int amdgpu_vm_update_pdes(struct amdgpu_device *adev,
|
|||
struct amdgpu_vm *vm, bool immediate)
|
||||
{
|
||||
struct amdgpu_vm_update_params params;
|
||||
struct amdgpu_vm_bo_base *entry;
|
||||
struct amdgpu_vm_bo_base *entry, *tmp;
|
||||
bool flush_tlb_needed = false;
|
||||
LIST_HEAD(relocated);
|
||||
int r, idx;
|
||||
|
||||
amdgpu_vm_assert_locked(vm);
|
||||
|
||||
spin_lock(&vm->status_lock);
|
||||
list_splice_init(&vm->relocated, &relocated);
|
||||
spin_unlock(&vm->status_lock);
|
||||
|
||||
if (list_empty(&relocated))
|
||||
if (list_empty(&vm->relocated))
|
||||
return 0;
|
||||
|
||||
if (!drm_dev_enter(adev_to_drm(adev), &idx))
|
||||
|
|
@ -998,7 +968,7 @@ int amdgpu_vm_update_pdes(struct amdgpu_device *adev,
|
|||
if (r)
|
||||
goto error;
|
||||
|
||||
list_for_each_entry(entry, &relocated, vm_status) {
|
||||
list_for_each_entry(entry, &vm->relocated, vm_status) {
|
||||
/* vm_flush_needed after updating moved PDEs */
|
||||
flush_tlb_needed |= entry->moved;
|
||||
|
||||
|
|
@ -1014,9 +984,7 @@ int amdgpu_vm_update_pdes(struct amdgpu_device *adev,
|
|||
if (flush_tlb_needed)
|
||||
atomic64_inc(&vm->tlb_seq);
|
||||
|
||||
while (!list_empty(&relocated)) {
|
||||
entry = list_first_entry(&relocated, struct amdgpu_vm_bo_base,
|
||||
vm_status);
|
||||
list_for_each_entry_safe(entry, tmp, &vm->relocated, vm_status) {
|
||||
amdgpu_vm_bo_idle(entry);
|
||||
}
|
||||
|
||||
|
|
@ -1243,9 +1211,9 @@ int amdgpu_vm_update_range(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
|||
void amdgpu_vm_get_memory(struct amdgpu_vm *vm,
|
||||
struct amdgpu_mem_stats stats[__AMDGPU_PL_NUM])
|
||||
{
|
||||
spin_lock(&vm->status_lock);
|
||||
spin_lock(&vm->stats_lock);
|
||||
memcpy(stats, vm->stats, sizeof(*stats) * __AMDGPU_PL_NUM);
|
||||
spin_unlock(&vm->status_lock);
|
||||
spin_unlock(&vm->stats_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1612,29 +1580,24 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev,
|
|||
struct amdgpu_vm *vm,
|
||||
struct ww_acquire_ctx *ticket)
|
||||
{
|
||||
struct amdgpu_bo_va *bo_va;
|
||||
struct amdgpu_bo_va *bo_va, *tmp;
|
||||
struct dma_resv *resv;
|
||||
bool clear, unlock;
|
||||
int r;
|
||||
|
||||
spin_lock(&vm->status_lock);
|
||||
while (!list_empty(&vm->moved)) {
|
||||
bo_va = list_first_entry(&vm->moved, struct amdgpu_bo_va,
|
||||
base.vm_status);
|
||||
spin_unlock(&vm->status_lock);
|
||||
|
||||
list_for_each_entry_safe(bo_va, tmp, &vm->moved, base.vm_status) {
|
||||
/* Per VM BOs never need to bo cleared in the page tables */
|
||||
r = amdgpu_vm_bo_update(adev, bo_va, false);
|
||||
if (r)
|
||||
return r;
|
||||
spin_lock(&vm->status_lock);
|
||||
}
|
||||
|
||||
spin_lock(&vm->invalidated_lock);
|
||||
while (!list_empty(&vm->invalidated)) {
|
||||
bo_va = list_first_entry(&vm->invalidated, struct amdgpu_bo_va,
|
||||
base.vm_status);
|
||||
resv = bo_va->base.bo->tbo.base.resv;
|
||||
spin_unlock(&vm->status_lock);
|
||||
spin_unlock(&vm->invalidated_lock);
|
||||
|
||||
/* Try to reserve the BO to avoid clearing its ptes */
|
||||
if (!adev->debug_vm && dma_resv_trylock(resv)) {
|
||||
|
|
@ -1666,9 +1629,9 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev,
|
|||
bo_va->base.bo->tbo.resource->mem_type == TTM_PL_SYSTEM))
|
||||
amdgpu_vm_bo_evicted_user(&bo_va->base);
|
||||
|
||||
spin_lock(&vm->status_lock);
|
||||
spin_lock(&vm->invalidated_lock);
|
||||
}
|
||||
spin_unlock(&vm->status_lock);
|
||||
spin_unlock(&vm->invalidated_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2211,9 +2174,9 @@ void amdgpu_vm_bo_del(struct amdgpu_device *adev,
|
|||
}
|
||||
}
|
||||
|
||||
spin_lock(&vm->status_lock);
|
||||
spin_lock(&vm->invalidated_lock);
|
||||
list_del(&bo_va->base.vm_status);
|
||||
spin_unlock(&vm->status_lock);
|
||||
spin_unlock(&vm->invalidated_lock);
|
||||
|
||||
list_for_each_entry_safe(mapping, next, &bo_va->valids, list) {
|
||||
list_del(&mapping->list);
|
||||
|
|
@ -2321,10 +2284,10 @@ void amdgpu_vm_bo_move(struct amdgpu_bo *bo, struct ttm_resource *new_mem,
|
|||
for (bo_base = bo->vm_bo; bo_base; bo_base = bo_base->next) {
|
||||
struct amdgpu_vm *vm = bo_base->vm;
|
||||
|
||||
spin_lock(&vm->status_lock);
|
||||
spin_lock(&vm->stats_lock);
|
||||
amdgpu_vm_update_stats_locked(bo_base, bo->tbo.resource, -1);
|
||||
amdgpu_vm_update_stats_locked(bo_base, new_mem, +1);
|
||||
spin_unlock(&vm->status_lock);
|
||||
spin_unlock(&vm->stats_lock);
|
||||
}
|
||||
|
||||
amdgpu_vm_bo_invalidate(bo, evicted);
|
||||
|
|
@ -2593,11 +2556,12 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
|||
INIT_LIST_HEAD(&vm->relocated);
|
||||
INIT_LIST_HEAD(&vm->moved);
|
||||
INIT_LIST_HEAD(&vm->idle);
|
||||
spin_lock_init(&vm->invalidated_lock);
|
||||
INIT_LIST_HEAD(&vm->invalidated);
|
||||
spin_lock_init(&vm->status_lock);
|
||||
INIT_LIST_HEAD(&vm->freed);
|
||||
INIT_LIST_HEAD(&vm->done);
|
||||
INIT_KFIFO(vm->faults);
|
||||
spin_lock_init(&vm->stats_lock);
|
||||
|
||||
r = amdgpu_vm_init_entities(adev, vm);
|
||||
if (r)
|
||||
|
|
@ -3065,7 +3029,6 @@ void amdgpu_debugfs_vm_bo_info(struct amdgpu_vm *vm, struct seq_file *m)
|
|||
|
||||
amdgpu_vm_assert_locked(vm);
|
||||
|
||||
spin_lock(&vm->status_lock);
|
||||
seq_puts(m, "\tIdle BOs:\n");
|
||||
list_for_each_entry_safe(bo_va, tmp, &vm->idle, base.vm_status) {
|
||||
if (!bo_va->base.bo)
|
||||
|
|
@ -3103,11 +3066,13 @@ void amdgpu_debugfs_vm_bo_info(struct amdgpu_vm *vm, struct seq_file *m)
|
|||
id = 0;
|
||||
|
||||
seq_puts(m, "\tInvalidated BOs:\n");
|
||||
spin_lock(&vm->invalidated_lock);
|
||||
list_for_each_entry_safe(bo_va, tmp, &vm->invalidated, base.vm_status) {
|
||||
if (!bo_va->base.bo)
|
||||
continue;
|
||||
total_invalidated += amdgpu_bo_print_info(id++, bo_va->base.bo, m);
|
||||
}
|
||||
spin_unlock(&vm->invalidated_lock);
|
||||
total_invalidated_objs = id;
|
||||
id = 0;
|
||||
|
||||
|
|
@ -3117,7 +3082,6 @@ void amdgpu_debugfs_vm_bo_info(struct amdgpu_vm *vm, struct seq_file *m)
|
|||
continue;
|
||||
total_done += amdgpu_bo_print_info(id++, bo_va->base.bo, m);
|
||||
}
|
||||
spin_unlock(&vm->status_lock);
|
||||
total_done_objs = id;
|
||||
|
||||
seq_printf(m, "\tTotal idle size: %12lld\tobjs:\t%d\n", total_idle,
|
||||
|
|
|
|||
|
|
@ -205,11 +205,11 @@ struct amdgpu_vm_bo_base {
|
|||
/* protected by bo being reserved */
|
||||
struct amdgpu_vm_bo_base *next;
|
||||
|
||||
/* protected by vm status_lock */
|
||||
/* protected by vm reservation and invalidated_lock */
|
||||
struct list_head vm_status;
|
||||
|
||||
/* if the bo is counted as shared in mem stats
|
||||
* protected by vm status_lock */
|
||||
* protected by vm BO being reserved */
|
||||
bool shared;
|
||||
|
||||
/* protected by the BO being reserved */
|
||||
|
|
@ -345,10 +345,8 @@ struct amdgpu_vm {
|
|||
bool evicting;
|
||||
unsigned int saved_flags;
|
||||
|
||||
/* Lock to protect vm_bo add/del/move on all lists of vm */
|
||||
spinlock_t status_lock;
|
||||
|
||||
/* Memory statistics for this vm, protected by status_lock */
|
||||
/* Memory statistics for this vm, protected by stats_lock */
|
||||
spinlock_t stats_lock;
|
||||
struct amdgpu_mem_stats stats[__AMDGPU_PL_NUM];
|
||||
|
||||
/*
|
||||
|
|
@ -356,6 +354,8 @@ struct amdgpu_vm {
|
|||
* PDs, PTs or per VM BOs. The state transits are:
|
||||
*
|
||||
* evicted -> relocated (PDs, PTs) or moved (per VM BOs) -> idle
|
||||
*
|
||||
* Lists are protected by the root PD dma_resv lock.
|
||||
*/
|
||||
|
||||
/* Per-VM and PT BOs who needs a validation */
|
||||
|
|
@ -376,7 +376,10 @@ struct amdgpu_vm {
|
|||
* state transits are:
|
||||
*
|
||||
* evicted_user or invalidated -> done
|
||||
*
|
||||
* Lists are protected by the invalidated_lock.
|
||||
*/
|
||||
spinlock_t invalidated_lock;
|
||||
|
||||
/* BOs for user mode queues that need a validation */
|
||||
struct list_head evicted_user;
|
||||
|
|
|
|||
|
|
@ -544,9 +544,7 @@ static void amdgpu_vm_pt_free(struct amdgpu_vm_bo_base *entry)
|
|||
entry->bo->vm_bo = NULL;
|
||||
ttm_bo_set_bulk_move(&entry->bo->tbo, NULL);
|
||||
|
||||
spin_lock(&entry->vm->status_lock);
|
||||
list_del(&entry->vm_status);
|
||||
spin_unlock(&entry->vm->status_lock);
|
||||
amdgpu_bo_unref(&entry->bo);
|
||||
}
|
||||
|
||||
|
|
@ -590,7 +588,6 @@ static void amdgpu_vm_pt_add_list(struct amdgpu_vm_update_params *params,
|
|||
struct amdgpu_vm_pt_cursor seek;
|
||||
struct amdgpu_vm_bo_base *entry;
|
||||
|
||||
spin_lock(¶ms->vm->status_lock);
|
||||
for_each_amdgpu_vm_pt_dfs_safe(params->adev, params->vm, cursor, seek, entry) {
|
||||
if (entry && entry->bo)
|
||||
list_move(&entry->vm_status, ¶ms->tlb_flush_waitlist);
|
||||
|
|
@ -598,7 +595,6 @@ static void amdgpu_vm_pt_add_list(struct amdgpu_vm_update_params *params,
|
|||
|
||||
/* enter start node now */
|
||||
list_move(&cursor->entry->vm_status, ¶ms->tlb_flush_waitlist);
|
||||
spin_unlock(¶ms->vm->status_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -161,7 +161,8 @@ union amd_sriov_msg_feature_flags {
|
|||
uint32_t ras_telemetry : 1;
|
||||
uint32_t ras_cper : 1;
|
||||
uint32_t xgmi_ta_ext_peer_link : 1;
|
||||
uint32_t reserved : 19;
|
||||
uint32_t xgmi_connected_to_cpu : 1;
|
||||
uint32_t reserved : 18;
|
||||
} flags;
|
||||
uint32_t all;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1298,7 +1298,7 @@ static void dce_v10_0_audio_write_speaker_allocation(struct drm_encoder *encoder
|
|||
return;
|
||||
}
|
||||
|
||||
sad_count = drm_edid_to_speaker_allocation(amdgpu_connector->edid, &sadb);
|
||||
sad_count = drm_edid_to_speaker_allocation(drm_edid_raw(amdgpu_connector->edid), &sadb);
|
||||
if (sad_count < 0) {
|
||||
DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
|
||||
sad_count = 0;
|
||||
|
|
@ -1368,7 +1368,7 @@ static void dce_v10_0_audio_write_sad_regs(struct drm_encoder *encoder)
|
|||
return;
|
||||
}
|
||||
|
||||
sad_count = drm_edid_to_sad(amdgpu_connector->edid, &sads);
|
||||
sad_count = drm_edid_to_sad(drm_edid_raw(amdgpu_connector->edid), &sads);
|
||||
if (sad_count < 0)
|
||||
DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
|
||||
if (sad_count <= 0)
|
||||
|
|
|
|||
|
|
@ -1265,7 +1265,7 @@ static void dce_v6_0_audio_write_speaker_allocation(struct drm_encoder *encoder)
|
|||
return;
|
||||
}
|
||||
|
||||
sad_count = drm_edid_to_speaker_allocation(amdgpu_connector->edid, &sadb);
|
||||
sad_count = drm_edid_to_speaker_allocation(drm_edid_raw(amdgpu_connector->edid), &sadb);
|
||||
if (sad_count < 0) {
|
||||
DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
|
||||
sad_count = 0;
|
||||
|
|
@ -1346,7 +1346,7 @@ static void dce_v6_0_audio_write_sad_regs(struct drm_encoder *encoder)
|
|||
return;
|
||||
}
|
||||
|
||||
sad_count = drm_edid_to_sad(amdgpu_connector->edid, &sads);
|
||||
sad_count = drm_edid_to_sad(drm_edid_raw(amdgpu_connector->edid), &sads);
|
||||
if (sad_count < 0)
|
||||
DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
|
||||
if (sad_count <= 0)
|
||||
|
|
|
|||
|
|
@ -1271,7 +1271,7 @@ static void dce_v8_0_audio_write_speaker_allocation(struct drm_encoder *encoder)
|
|||
return;
|
||||
}
|
||||
|
||||
sad_count = drm_edid_to_speaker_allocation(amdgpu_connector->edid, &sadb);
|
||||
sad_count = drm_edid_to_speaker_allocation(drm_edid_raw(amdgpu_connector->edid), &sadb);
|
||||
if (sad_count < 0) {
|
||||
DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
|
||||
sad_count = 0;
|
||||
|
|
@ -1339,7 +1339,7 @@ static void dce_v8_0_audio_write_sad_regs(struct drm_encoder *encoder)
|
|||
return;
|
||||
}
|
||||
|
||||
sad_count = drm_edid_to_sad(amdgpu_connector->edid, &sads);
|
||||
sad_count = drm_edid_to_sad(drm_edid_raw(amdgpu_connector->edid), &sads);
|
||||
if (sad_count < 0)
|
||||
DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
|
||||
if (sad_count <= 0)
|
||||
|
|
|
|||
|
|
@ -1155,11 +1155,13 @@ static int gfx_v12_1_sw_init(struct amdgpu_ip_block *ip_block)
|
|||
break;
|
||||
}
|
||||
|
||||
/* recalculate compute rings to use based on hardware configuration */
|
||||
num_compute_rings = (adev->gfx.mec.num_pipe_per_mec *
|
||||
adev->gfx.mec.num_queue_per_pipe) / 2;
|
||||
adev->gfx.num_compute_rings = min(adev->gfx.num_compute_rings,
|
||||
num_compute_rings);
|
||||
if (adev->gfx.num_compute_rings) {
|
||||
/* recalculate compute rings to use based on hardware configuration */
|
||||
num_compute_rings = (adev->gfx.mec.num_pipe_per_mec *
|
||||
adev->gfx.mec.num_queue_per_pipe) / 2;
|
||||
adev->gfx.num_compute_rings = min(adev->gfx.num_compute_rings,
|
||||
num_compute_rings);
|
||||
}
|
||||
|
||||
num_xcc = NUM_XCC(adev->gfx.xcc_mask);
|
||||
|
||||
|
|
@ -2794,6 +2796,33 @@ static void gfx_v12_1_xcc_fini(struct amdgpu_device *adev,
|
|||
gfx_v12_1_xcc_enable_gui_idle_interrupt(adev, false, xcc_id);
|
||||
}
|
||||
|
||||
static int gfx_v12_1_set_userq_eop_interrupts(struct amdgpu_device *adev,
|
||||
bool enable)
|
||||
{
|
||||
unsigned int irq_type;
|
||||
int m, p, r;
|
||||
|
||||
if (adev->gfx.disable_kq) {
|
||||
for (m = 0; m < adev->gfx.mec.num_mec; ++m) {
|
||||
for (p = 0; p < adev->gfx.mec.num_pipe_per_mec; p++) {
|
||||
irq_type = AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP
|
||||
+ (m * adev->gfx.mec.num_pipe_per_mec)
|
||||
+ p;
|
||||
if (enable)
|
||||
r = amdgpu_irq_get(adev, &adev->gfx.eop_irq,
|
||||
irq_type);
|
||||
else
|
||||
r = amdgpu_irq_put(adev, &adev->gfx.eop_irq,
|
||||
irq_type);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gfx_v12_1_hw_fini(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
|
|
@ -2801,6 +2830,7 @@ static int gfx_v12_1_hw_fini(struct amdgpu_ip_block *ip_block)
|
|||
|
||||
amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0);
|
||||
amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0);
|
||||
gfx_v12_1_set_userq_eop_interrupts(adev, false);
|
||||
|
||||
num_xcc = NUM_XCC(adev->gfx.xcc_mask);
|
||||
for (i = 0; i < num_xcc; i++) {
|
||||
|
|
@ -2868,10 +2898,26 @@ static int gfx_v12_1_early_init(struct amdgpu_ip_block *ip_block)
|
|||
{
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
|
||||
|
||||
switch (amdgpu_user_queue) {
|
||||
case -1:
|
||||
default:
|
||||
adev->gfx.disable_kq = true;
|
||||
adev->gfx.disable_uq = true;
|
||||
break;
|
||||
case 0:
|
||||
adev->gfx.disable_kq = false;
|
||||
adev->gfx.disable_uq = true;
|
||||
break;
|
||||
}
|
||||
|
||||
adev->gfx.funcs = &gfx_v12_1_gfx_funcs;
|
||||
|
||||
adev->gfx.num_compute_rings = min(amdgpu_gfx_get_num_kcq(adev),
|
||||
AMDGPU_MAX_COMPUTE_RINGS);
|
||||
if (adev->gfx.disable_kq)
|
||||
adev->gfx.num_compute_rings = 0;
|
||||
else
|
||||
adev->gfx.num_compute_rings = min(amdgpu_gfx_get_num_kcq(adev),
|
||||
AMDGPU_MAX_COMPUTE_RINGS);
|
||||
|
||||
gfx_v12_1_set_kiq_pm4_funcs(adev);
|
||||
gfx_v12_1_set_ring_funcs(adev);
|
||||
|
|
@ -2898,6 +2944,10 @@ static int gfx_v12_1_late_init(struct amdgpu_ip_block *ip_block)
|
|||
if (r)
|
||||
return r;
|
||||
|
||||
r = gfx_v12_1_set_userq_eop_interrupts(adev, true);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -3630,12 +3680,6 @@ static int gfx_v12_1_eop_irq(struct amdgpu_device *adev,
|
|||
return -EINVAL;
|
||||
|
||||
switch (me_id) {
|
||||
case 0:
|
||||
if (pipe_id == 0)
|
||||
amdgpu_fence_process(&adev->gfx.gfx_ring[0]);
|
||||
else
|
||||
amdgpu_fence_process(&adev->gfx.gfx_ring[1]);
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
for (i = 0; i < adev->gfx.num_compute_rings; i++) {
|
||||
|
|
@ -3652,6 +3696,9 @@ static int gfx_v12_1_eop_irq(struct amdgpu_device *adev,
|
|||
amdgpu_fence_process(ring);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dev_dbg(adev->dev, "Unexpected me %d in eop_irq\n", me_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3719,29 +3766,23 @@ static void gfx_v12_1_handle_priv_fault(struct amdgpu_device *adev,
|
|||
if (xcc_id == -EINVAL)
|
||||
return;
|
||||
|
||||
switch (me_id) {
|
||||
case 0:
|
||||
for (i = 0; i < adev->gfx.num_gfx_rings; i++) {
|
||||
ring = &adev->gfx.gfx_ring[i];
|
||||
/* we only enabled 1 gfx queue per pipe for now */
|
||||
if (ring->me == me_id && ring->pipe == pipe_id)
|
||||
drm_sched_fault(&ring->sched);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
for (i = 0; i < adev->gfx.num_compute_rings; i++) {
|
||||
ring = &adev->gfx.compute_ring
|
||||
if (!adev->gfx.disable_kq) {
|
||||
switch (me_id) {
|
||||
case 1:
|
||||
case 2:
|
||||
for (i = 0; i < adev->gfx.num_compute_rings; i++) {
|
||||
ring = &adev->gfx.compute_ring
|
||||
[i +
|
||||
xcc_id * adev->gfx.num_compute_rings];
|
||||
if (ring->me == me_id && ring->pipe == pipe_id &&
|
||||
ring->queue == queue_id)
|
||||
drm_sched_fault(&ring->sched);
|
||||
if (ring->me == me_id && ring->pipe == pipe_id &&
|
||||
ring->queue == queue_id)
|
||||
drm_sched_fault(&ring->sched);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dev_dbg(adev->dev, "Unexpected me %d in priv_fault\n", me_id);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2355,7 +2355,7 @@ static int gfx_v9_0_sw_init(struct amdgpu_ip_block *ip_block)
|
|||
for (i = 0; i < GFX9_NUM_SW_GFX_RINGS; i++) {
|
||||
ring = &adev->gfx.sw_gfx_ring[i];
|
||||
ring->ring_obj = NULL;
|
||||
sprintf(ring->name, amdgpu_sw_ring_name(i));
|
||||
strscpy(ring->name, amdgpu_sw_ring_name(i), sizeof(ring->name));
|
||||
ring->use_doorbell = true;
|
||||
ring->doorbell_index = adev->doorbell_index.gfx_ring0 << 1;
|
||||
ring->is_sw_ring = true;
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ static int gmc_v12_1_process_interrupt(struct amdgpu_device *adev,
|
|||
|
||||
if (entry->src_id == UTCL2_1_0__SRCID__RETRY) {
|
||||
retry_fault = true;
|
||||
write_fault = !!(entry->src_data[1] & 0x200000);
|
||||
write_fault = !!(entry->src_data[1] & AMDGPU_GMC121_FAULT_SOURCE_DATA_WRITE);
|
||||
}
|
||||
|
||||
if (entry->client_id == SOC_V1_0_IH_CLIENTID_VMC) {
|
||||
|
|
|
|||
|
|
@ -289,6 +289,13 @@ static uint32_t ih_v7_0_setup_retry_doorbell(u32 doorbell_index)
|
|||
return val;
|
||||
}
|
||||
|
||||
#define regIH_RING1_CLIENT_CFG_INDEX_V7_1 0x122
|
||||
#define regIH_RING1_CLIENT_CFG_INDEX_V7_1_BASE_IDX 0
|
||||
#define regIH_RING1_CLIENT_CFG_DATA_V7_1 0x123
|
||||
#define regIH_RING1_CLIENT_CFG_DATA_V7_1_BASE_IDX 0
|
||||
#define regIH_CHICKEN_V7_1 0x129
|
||||
#define regIH_CHICKEN_V7_1_BASE_IDX 0
|
||||
|
||||
/**
|
||||
* ih_v7_0_irq_init - init and enable the interrupt ring
|
||||
*
|
||||
|
|
@ -307,6 +314,7 @@ static int ih_v7_0_irq_init(struct amdgpu_device *adev)
|
|||
u32 tmp;
|
||||
int ret;
|
||||
int i;
|
||||
u32 reg_addr;
|
||||
|
||||
/* disable irqs */
|
||||
ret = ih_v7_0_toggle_interrupts(adev, false);
|
||||
|
|
@ -318,10 +326,15 @@ static int ih_v7_0_irq_init(struct amdgpu_device *adev)
|
|||
if (unlikely((adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) ||
|
||||
(adev->firmware.load_type == AMDGPU_FW_LOAD_RLC_BACKDOOR_AUTO))) {
|
||||
if (ih[0]->use_bus_addr) {
|
||||
ih_chicken = RREG32_SOC15(OSSSYS, 0, regIH_CHICKEN);
|
||||
if (amdgpu_ip_version(adev, OSSSYS_HWIP, 0) == IP_VERSION(7, 1, 0))
|
||||
reg_addr = SOC15_REG_OFFSET(OSSSYS, 0, regIH_CHICKEN_V7_1);
|
||||
else
|
||||
reg_addr = SOC15_REG_OFFSET(OSSSYS, 0, regIH_CHICKEN);
|
||||
ih_chicken = RREG32(reg_addr);
|
||||
/* The reg fields definitions are identical in ih v7_0 and ih v7_1 */
|
||||
ih_chicken = REG_SET_FIELD(ih_chicken,
|
||||
IH_CHICKEN, MC_SPACE_GPA_ENABLE, 1);
|
||||
WREG32_SOC15(OSSSYS, 0, regIH_CHICKEN, ih_chicken);
|
||||
WREG32(reg_addr, ih_chicken);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -358,17 +371,26 @@ static int ih_v7_0_irq_init(struct amdgpu_device *adev)
|
|||
|
||||
/* Redirect the interrupts to IH RB1 for dGPU */
|
||||
if (adev->irq.ih1.ring_size) {
|
||||
tmp = RREG32_SOC15(OSSSYS, 0, regIH_RING1_CLIENT_CFG_INDEX);
|
||||
if (amdgpu_ip_version(adev, OSSSYS_HWIP, 0) == IP_VERSION(7, 1, 0))
|
||||
reg_addr = SOC15_REG_OFFSET(OSSSYS, 0, regIH_RING1_CLIENT_CFG_INDEX_V7_1);
|
||||
else
|
||||
reg_addr = SOC15_REG_OFFSET(OSSSYS, 0, regIH_RING1_CLIENT_CFG_INDEX);
|
||||
tmp = RREG32(reg_addr);
|
||||
/* The reg fields definitions are identical in ih v7_0 and ih v7_1 */
|
||||
tmp = REG_SET_FIELD(tmp, IH_RING1_CLIENT_CFG_INDEX, INDEX, 0);
|
||||
WREG32_SOC15(OSSSYS, 0, regIH_RING1_CLIENT_CFG_INDEX, tmp);
|
||||
WREG32(reg_addr, tmp);
|
||||
|
||||
tmp = RREG32_SOC15(OSSSYS, 0, regIH_RING1_CLIENT_CFG_DATA);
|
||||
if (amdgpu_ip_version(adev, OSSSYS_HWIP, 0) == IP_VERSION(7, 1, 0))
|
||||
reg_addr = SOC15_REG_OFFSET(OSSSYS, 0, regIH_RING1_CLIENT_CFG_DATA_V7_1);
|
||||
else
|
||||
reg_addr = SOC15_REG_OFFSET(OSSSYS, 0, regIH_RING1_CLIENT_CFG_DATA);
|
||||
tmp = RREG32(reg_addr);
|
||||
/* The reg fields definitions are identical in ih v7_0 and ih v7_1 */
|
||||
tmp = REG_SET_FIELD(tmp, IH_RING1_CLIENT_CFG_DATA, CLIENT_ID, 0xa);
|
||||
tmp = REG_SET_FIELD(tmp, IH_RING1_CLIENT_CFG_DATA, SOURCE_ID, 0x0);
|
||||
tmp = REG_SET_FIELD(tmp, IH_RING1_CLIENT_CFG_DATA,
|
||||
SOURCE_ID_MATCH_ENABLE, 0x1);
|
||||
|
||||
WREG32_SOC15(OSSSYS, 0, regIH_RING1_CLIENT_CFG_DATA, tmp);
|
||||
WREG32(reg_addr, tmp);
|
||||
}
|
||||
|
||||
pci_set_master(adev->pdev);
|
||||
|
|
|
|||
99
drivers/gpu/drm/amd/amdgpu/lsdma_v7_1.c
Normal file
99
drivers/gpu/drm/amd/amdgpu/lsdma_v7_1.c
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Copyright 2026 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include "amdgpu.h"
|
||||
#include "lsdma_v7_1.h"
|
||||
#include "amdgpu_lsdma.h"
|
||||
|
||||
#include "lsdma/lsdma_7_1_0_offset.h"
|
||||
#include "lsdma/lsdma_7_1_0_sh_mask.h"
|
||||
|
||||
static int lsdma_v7_1_wait_pio_status(struct amdgpu_device *adev)
|
||||
{
|
||||
return amdgpu_lsdma_wait_for(adev, SOC15_REG_OFFSET(LSDMA, 0, regLSDMA_PIO_STATUS),
|
||||
LSDMA_PIO_STATUS__PIO_IDLE_MASK | LSDMA_PIO_STATUS__PIO_FIFO_EMPTY_MASK,
|
||||
LSDMA_PIO_STATUS__PIO_IDLE_MASK | LSDMA_PIO_STATUS__PIO_FIFO_EMPTY_MASK);
|
||||
}
|
||||
|
||||
static int lsdma_v7_1_copy_mem(struct amdgpu_device *adev,
|
||||
uint64_t src_addr,
|
||||
uint64_t dst_addr,
|
||||
uint64_t size)
|
||||
{
|
||||
int ret;
|
||||
uint32_t tmp;
|
||||
|
||||
WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_SRC_ADDR_LO, lower_32_bits(src_addr));
|
||||
WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_SRC_ADDR_HI, upper_32_bits(src_addr));
|
||||
|
||||
WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_DST_ADDR_LO, lower_32_bits(dst_addr));
|
||||
WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_DST_ADDR_HI, upper_32_bits(dst_addr));
|
||||
|
||||
WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_CONTROL, 0x0);
|
||||
|
||||
tmp = RREG32_SOC15(LSDMA, 0, regLSDMA_PIO_COMMAND);
|
||||
tmp = REG_SET_FIELD(tmp, LSDMA_PIO_COMMAND, COUNT, size);
|
||||
tmp = REG_SET_FIELD(tmp, LSDMA_PIO_COMMAND, RAW_WAIT, 0);
|
||||
tmp = REG_SET_FIELD(tmp, LSDMA_PIO_COMMAND, CONSTANT_FILL, 0);
|
||||
WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_COMMAND, tmp);
|
||||
|
||||
ret = lsdma_v7_1_wait_pio_status(adev);
|
||||
if (ret)
|
||||
dev_err(adev->dev, "LSDMA PIO failed to copy memory!\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lsdma_v7_1_fill_mem(struct amdgpu_device *adev,
|
||||
uint64_t dst_addr,
|
||||
uint32_t data,
|
||||
uint64_t size)
|
||||
{
|
||||
int ret;
|
||||
uint32_t tmp;
|
||||
|
||||
WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_CONSTFILL_DATA, data);
|
||||
|
||||
WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_DST_ADDR_LO, lower_32_bits(dst_addr));
|
||||
WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_DST_ADDR_HI, upper_32_bits(dst_addr));
|
||||
|
||||
WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_CONTROL, 0x0);
|
||||
|
||||
tmp = RREG32_SOC15(LSDMA, 0, regLSDMA_PIO_COMMAND);
|
||||
tmp = REG_SET_FIELD(tmp, LSDMA_PIO_COMMAND, COUNT, size);
|
||||
tmp = REG_SET_FIELD(tmp, LSDMA_PIO_COMMAND, RAW_WAIT, 0);
|
||||
tmp = REG_SET_FIELD(tmp, LSDMA_PIO_COMMAND, CONSTANT_FILL, 1);
|
||||
WREG32_SOC15(LSDMA, 0, regLSDMA_PIO_COMMAND, tmp);
|
||||
|
||||
ret = lsdma_v7_1_wait_pio_status(adev);
|
||||
if (ret)
|
||||
dev_err(adev->dev, "LSDMA PIO failed to fill memory!\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const struct amdgpu_lsdma_funcs lsdma_v7_1_funcs = {
|
||||
.copy_mem = lsdma_v7_1_copy_mem,
|
||||
.fill_mem = lsdma_v7_1_fill_mem,
|
||||
};
|
||||
31
drivers/gpu/drm/amd/amdgpu/lsdma_v7_1.h
Normal file
31
drivers/gpu/drm/amd/amdgpu/lsdma_v7_1.h
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright 2026 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LSDMA_V7_1_H__
|
||||
#define __LSDMA_V7_1_H__
|
||||
|
||||
#include "soc15_common.h"
|
||||
|
||||
extern const struct amdgpu_lsdma_funcs lsdma_v7_1_funcs;
|
||||
|
||||
#endif /* __LSDMA_V7_1_H__ */
|
||||
|
|
@ -731,6 +731,9 @@ static int mes_v12_0_set_hw_resources(struct amdgpu_mes *mes, int pipe)
|
|||
int i;
|
||||
struct amdgpu_device *adev = mes->adev;
|
||||
union MESAPI_SET_HW_RESOURCES mes_set_hw_res_pkt;
|
||||
uint32_t mes_rev = (pipe == AMDGPU_MES_SCHED_PIPE) ?
|
||||
(mes->sched_version & AMDGPU_MES_VERSION_MASK) :
|
||||
(mes->kiq_version & AMDGPU_MES_VERSION_MASK);
|
||||
|
||||
memset(&mes_set_hw_res_pkt, 0, sizeof(mes_set_hw_res_pkt));
|
||||
|
||||
|
|
@ -785,7 +788,7 @@ static int mes_v12_0_set_hw_resources(struct amdgpu_mes *mes, int pipe)
|
|||
* handling support, other queue will not use the oversubscribe timer.
|
||||
* handling mode - 0: disabled; 1: basic version; 2: basic+ version
|
||||
*/
|
||||
mes_set_hw_res_pkt.oversubscription_timer = 50;
|
||||
mes_set_hw_res_pkt.oversubscription_timer = mes_rev < 0x8b ? 0 : 50;
|
||||
mes_set_hw_res_pkt.unmapped_doorbell_handling = 1;
|
||||
|
||||
if (amdgpu_mes_log_enable) {
|
||||
|
|
|
|||
|
|
@ -1611,7 +1611,6 @@ static int mes_v12_1_sw_fini(struct amdgpu_ip_block *ip_block)
|
|||
amdgpu_bo_free_kernel(&adev->mes.eop_gpu_obj[inst],
|
||||
&adev->mes.eop_gpu_addr[inst],
|
||||
NULL);
|
||||
amdgpu_ucode_release(&adev->mes.fw[inst]);
|
||||
|
||||
if (adev->enable_uni_mes || pipe == AMDGPU_MES_SCHED_PIPE) {
|
||||
amdgpu_bo_free_kernel(&adev->mes.ring[inst].mqd_obj,
|
||||
|
|
@ -1622,6 +1621,9 @@ static int mes_v12_1_sw_fini(struct amdgpu_ip_block *ip_block)
|
|||
}
|
||||
}
|
||||
|
||||
for (pipe = 0; pipe < AMDGPU_MAX_MES_PIPES; pipe++)
|
||||
amdgpu_ucode_release(&adev->mes.fw[pipe]);
|
||||
|
||||
for (xcc_id = 0; xcc_id < num_xcc; xcc_id++) {
|
||||
if (!adev->enable_uni_mes) {
|
||||
amdgpu_bo_free_kernel(&adev->gfx.kiq[xcc_id].ring.mqd_obj,
|
||||
|
|
|
|||
|
|
@ -478,7 +478,7 @@ static int soc24_common_hw_init(struct amdgpu_ip_block *ip_block)
|
|||
if (adev->nbio.funcs->remap_hdp_registers)
|
||||
adev->nbio.funcs->remap_hdp_registers(adev);
|
||||
|
||||
if (adev->df.funcs->hw_init)
|
||||
if (adev->df.funcs && adev->df.funcs->hw_init)
|
||||
adev->df.funcs->hw_init(adev);
|
||||
|
||||
/* enable the doorbell aperture */
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ static void soc_v1_0_doorbell_index_init(struct amdgpu_device *adev)
|
|||
adev->doorbell_index.userqueue_end = AMDGPU_SOC_V1_0_DOORBELL_USERQUEUE_END;
|
||||
adev->doorbell_index.xcc_doorbell_range = AMDGPU_SOC_V1_0_DOORBELL_XCC_RANGE;
|
||||
|
||||
adev->doorbell_index.sdma_doorbell_range = 20;
|
||||
adev->doorbell_index.sdma_doorbell_range = 14;
|
||||
for (i = 0; i < adev->sdma.num_instances; i++)
|
||||
adev->doorbell_index.sdma_engine[i] =
|
||||
AMDGPU_SOC_V1_0_DOORBELL_sDMA_ENGINE_START +
|
||||
|
|
@ -214,23 +214,35 @@ static bool soc_v1_0_need_full_reset(struct amdgpu_device *adev)
|
|||
|
||||
static bool soc_v1_0_need_reset_on_init(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 sol_reg;
|
||||
|
||||
if (adev->flags & AMD_IS_APU)
|
||||
return false;
|
||||
|
||||
/* Check sOS sign of life register to confirm sys driver and sOS
|
||||
* are already been loaded.
|
||||
*/
|
||||
sol_reg = RREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_81);
|
||||
if (sol_reg)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static enum amd_reset_method
|
||||
soc_v1_0_asic_reset_method(struct amdgpu_device *adev)
|
||||
{
|
||||
if ((adev->gmc.xgmi.supported && adev->gmc.xgmi.connected_to_cpu) ||
|
||||
(amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(15, 0, 8))) {
|
||||
if (amdgpu_reset_method != -1)
|
||||
dev_warn_once(adev->dev, "Reset override isn't supported, using Mode2 instead.\n");
|
||||
|
||||
return AMD_RESET_METHOD_MODE2;
|
||||
}
|
||||
|
||||
return amdgpu_reset_method;
|
||||
}
|
||||
|
||||
static int soc_v1_0_asic_reset(struct amdgpu_device *adev)
|
||||
{
|
||||
switch (soc_v1_0_asic_reset_method(adev)) {
|
||||
case AMD_RESET_METHOD_MODE2:
|
||||
dev_info(adev->dev, "MODE2 reset\n");
|
||||
return amdgpu_dpm_mode2_reset(adev);
|
||||
default:
|
||||
dev_info(adev->dev, "Invalid reset method Not supported\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -244,6 +256,7 @@ static const struct amdgpu_asic_funcs soc_v1_0_asic_funcs = {
|
|||
.need_reset_on_init = &soc_v1_0_need_reset_on_init,
|
||||
.encode_ext_smn_addressing = &soc_v1_0_encode_ext_smn_addressing,
|
||||
.reset = soc_v1_0_asic_reset,
|
||||
.reset_method = &soc_v1_0_asic_reset_method,
|
||||
};
|
||||
|
||||
static int soc_v1_0_common_early_init(struct amdgpu_ip_block *ip_block)
|
||||
|
|
@ -268,7 +281,8 @@ static int soc_v1_0_common_early_init(struct amdgpu_ip_block *ip_block)
|
|||
|
||||
switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
|
||||
case IP_VERSION(12, 1, 0):
|
||||
adev->cg_flags = 0;
|
||||
adev->cg_flags = AMD_CG_SUPPORT_GFX_CGCG |
|
||||
AMD_CG_SUPPORT_GFX_CGLS;
|
||||
adev->pg_flags = 0;
|
||||
adev->external_rev_id = adev->rev_id + 0x50;
|
||||
break;
|
||||
|
|
@ -809,7 +823,7 @@ int soc_v1_0_init_soc_config(struct amdgpu_device *adev)
|
|||
{
|
||||
int ret, i;
|
||||
int xcc_inst_per_aid = 4;
|
||||
uint16_t xcc_mask;
|
||||
uint16_t xcc_mask, sdma_mask = 0;
|
||||
|
||||
xcc_mask = adev->gfx.xcc_mask;
|
||||
adev->aid_mask = 0;
|
||||
|
|
@ -819,10 +833,12 @@ int soc_v1_0_init_soc_config(struct amdgpu_device *adev)
|
|||
}
|
||||
|
||||
adev->sdma.num_inst_per_xcc = 2;
|
||||
adev->sdma.num_instances =
|
||||
NUM_XCC(adev->gfx.xcc_mask) * adev->sdma.num_inst_per_xcc;
|
||||
adev->sdma.sdma_mask =
|
||||
GENMASK(adev->sdma.num_instances - 1, 0);
|
||||
for_each_inst(i, adev->gfx.xcc_mask)
|
||||
sdma_mask |=
|
||||
GENMASK(adev->sdma.num_inst_per_xcc - 1, 0) <<
|
||||
(i * adev->sdma.num_inst_per_xcc);
|
||||
adev->sdma.sdma_mask = sdma_mask;
|
||||
adev->sdma.num_instances = NUM_XCC(adev->sdma.sdma_mask);
|
||||
|
||||
ret = soc_v1_0_xcp_mgr_init(adev);
|
||||
if (ret)
|
||||
|
|
|
|||
|
|
@ -2720,7 +2720,7 @@ static int get_wave_state(struct device_queue_manager *dqm,
|
|||
ctl_stack, ctl_stack_used_size, save_area_used_size);
|
||||
}
|
||||
|
||||
static void get_queue_checkpoint_info(struct device_queue_manager *dqm,
|
||||
static int get_queue_checkpoint_info(struct device_queue_manager *dqm,
|
||||
const struct queue *q,
|
||||
u32 *mqd_size,
|
||||
u32 *ctl_stack_size)
|
||||
|
|
@ -2728,6 +2728,7 @@ static void get_queue_checkpoint_info(struct device_queue_manager *dqm,
|
|||
struct mqd_manager *mqd_mgr;
|
||||
enum KFD_MQD_TYPE mqd_type =
|
||||
get_mqd_type_from_queue_type(q->properties.type);
|
||||
int ret = 0;
|
||||
|
||||
dqm_lock(dqm);
|
||||
mqd_mgr = dqm->mqd_mgrs[mqd_type];
|
||||
|
|
@ -2735,9 +2736,11 @@ static void get_queue_checkpoint_info(struct device_queue_manager *dqm,
|
|||
*ctl_stack_size = 0;
|
||||
|
||||
if (q->properties.type == KFD_QUEUE_TYPE_COMPUTE && mqd_mgr->get_checkpoint_info)
|
||||
mqd_mgr->get_checkpoint_info(mqd_mgr, q->mqd, ctl_stack_size);
|
||||
ret = mqd_mgr->get_checkpoint_info(mqd_mgr, q->mqd, ctl_stack_size);
|
||||
|
||||
dqm_unlock(dqm);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int checkpoint_mqd(struct device_queue_manager *dqm,
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ struct device_queue_manager_ops {
|
|||
|
||||
int (*reset_queues)(struct device_queue_manager *dqm,
|
||||
uint16_t pasid);
|
||||
void (*get_queue_checkpoint_info)(struct device_queue_manager *dqm,
|
||||
int (*get_queue_checkpoint_info)(struct device_queue_manager *dqm,
|
||||
const struct queue *q, u32 *mqd_size,
|
||||
u32 *ctl_stack_size);
|
||||
|
||||
|
|
|
|||
|
|
@ -102,7 +102,8 @@ struct mqd_manager {
|
|||
u32 *ctl_stack_used_size,
|
||||
u32 *save_area_used_size);
|
||||
|
||||
void (*get_checkpoint_info)(struct mqd_manager *mm, void *mqd, uint32_t *ctl_stack_size);
|
||||
int (*get_checkpoint_info)(struct mqd_manager *mm, void *mqd,
|
||||
uint32_t *ctl_stack_size);
|
||||
|
||||
void (*checkpoint_mqd)(struct mqd_manager *mm,
|
||||
void *mqd,
|
||||
|
|
|
|||
|
|
@ -385,11 +385,14 @@ static int get_wave_state(struct mqd_manager *mm, void *mqd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void get_checkpoint_info(struct mqd_manager *mm, void *mqd, u32 *ctl_stack_size)
|
||||
static int get_checkpoint_info(struct mqd_manager *mm, void *mqd, u32 *ctl_stack_size)
|
||||
{
|
||||
struct v9_mqd *m = get_mqd(mqd);
|
||||
|
||||
*ctl_stack_size = m->cp_hqd_cntl_stack_size * NUM_XCC(mm->dev->xcc_mask);
|
||||
if (check_mul_overflow(m->cp_hqd_cntl_stack_size, NUM_XCC(mm->dev->xcc_mask), ctl_stack_size))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst, void *ctl_stack_dst)
|
||||
|
|
|
|||
|
|
@ -274,10 +274,11 @@ static int get_wave_state(struct mqd_manager *mm, void *mqd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void get_checkpoint_info(struct mqd_manager *mm, void *mqd, u32 *ctl_stack_size)
|
||||
static int get_checkpoint_info(struct mqd_manager *mm, void *mqd, u32 *ctl_stack_size)
|
||||
{
|
||||
/* Control stack is stored in user mode */
|
||||
*ctl_stack_size = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst, void *ctl_stack_dst)
|
||||
|
|
|
|||
|
|
@ -585,7 +585,7 @@ static void kfd_procfs_add_sysfs_stats(struct kfd_process *p)
|
|||
ret = kobject_init_and_add(pdd->kobj_stats,
|
||||
&procfs_stats_type,
|
||||
p->kobj,
|
||||
stats_dir_filename);
|
||||
"%s", stats_dir_filename);
|
||||
|
||||
if (ret) {
|
||||
pr_warn("Creating KFD proc/stats_%s folder failed",
|
||||
|
|
@ -632,7 +632,7 @@ static void kfd_procfs_add_sysfs_counters(struct kfd_process *p)
|
|||
return;
|
||||
|
||||
ret = kobject_init_and_add(kobj_counters, &sysfs_counters_type,
|
||||
p->kobj, counters_dir_filename);
|
||||
p->kobj, "%s", counters_dir_filename);
|
||||
if (ret) {
|
||||
pr_warn("Creating KFD proc/%s folder failed",
|
||||
counters_dir_filename);
|
||||
|
|
|
|||
|
|
@ -593,6 +593,7 @@ int pqm_update_queue_properties(struct process_queue_manager *pqm,
|
|||
p->queue_size)) {
|
||||
pr_debug("ring buf 0x%llx size 0x%llx not mapped on GPU\n",
|
||||
p->queue_address, p->queue_size);
|
||||
amdgpu_bo_unreserve(vm->root.bo);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
|
|
@ -1069,6 +1070,7 @@ int pqm_get_queue_checkpoint_info(struct process_queue_manager *pqm,
|
|||
uint32_t *ctl_stack_size)
|
||||
{
|
||||
struct process_queue_node *pqn;
|
||||
int ret;
|
||||
|
||||
pqn = get_queue_by_qid(pqm, qid);
|
||||
if (!pqn) {
|
||||
|
|
@ -1081,9 +1083,14 @@ int pqm_get_queue_checkpoint_info(struct process_queue_manager *pqm,
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
pqn->q->device->dqm->ops.get_queue_checkpoint_info(pqn->q->device->dqm,
|
||||
ret = pqn->q->device->dqm->ops.get_queue_checkpoint_info(pqn->q->device->dqm,
|
||||
pqn->q, mqd_size,
|
||||
ctl_stack_size);
|
||||
if (ret) {
|
||||
pr_debug("amdkfd: Overflow while computing stack size for queue %d\n", qid);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2473,6 +2473,8 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
|
|||
DMUB_WINDOW_MEMORY_TYPE_FB, //DMUB_WINDOW_7_SCRATCH_MEM
|
||||
DMUB_WINDOW_MEMORY_TYPE_FB, //DMUB_WINDOW_IB_MEM
|
||||
DMUB_WINDOW_MEMORY_TYPE_FB, //DMUB_WINDOW_SHARED_STATE
|
||||
DMUB_WINDOW_MEMORY_TYPE_FB, //DMUB_WINDOW_LSDMA_BUFFER
|
||||
DMUB_WINDOW_MEMORY_TYPE_FB, //DMUB_WINDOW_CURSOR_OFFLOAD
|
||||
};
|
||||
int r;
|
||||
|
||||
|
|
|
|||
|
|
@ -62,6 +62,9 @@ static const uint32_t rgb_formats[] = {
|
|||
DRM_FORMAT_XBGR8888,
|
||||
DRM_FORMAT_ABGR8888,
|
||||
DRM_FORMAT_RGB565,
|
||||
DRM_FORMAT_NV21,
|
||||
DRM_FORMAT_NV12,
|
||||
DRM_FORMAT_P010
|
||||
};
|
||||
|
||||
static const uint32_t overlay_formats[] = {
|
||||
|
|
@ -1908,7 +1911,8 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
|
|||
drm_plane_create_zpos_immutable_property(plane, 255);
|
||||
}
|
||||
|
||||
if (plane->type == DRM_PLANE_TYPE_PRIMARY &&
|
||||
if ((plane->type == DRM_PLANE_TYPE_PRIMARY ||
|
||||
plane->type == DRM_PLANE_TYPE_OVERLAY) &&
|
||||
plane_cap &&
|
||||
(plane_cap->pixel_format_support.nv12 ||
|
||||
plane_cap->pixel_format_support.p010)) {
|
||||
|
|
|
|||
|
|
@ -794,13 +794,11 @@ static enum bp_result bios_parser_external_encoder_control(
|
|||
|
||||
static enum bp_result bios_parser_dac_load_detection(
|
||||
struct dc_bios *dcb,
|
||||
enum engine_id engine_id,
|
||||
struct graphics_object_id ext_enc_id)
|
||||
enum engine_id engine_id)
|
||||
{
|
||||
struct bios_parser *bp = BP_FROM_DCB(dcb);
|
||||
struct dc_context *ctx = dcb->ctx;
|
||||
struct bp_load_detection_parameters bp_params = {0};
|
||||
struct bp_external_encoder_control ext_cntl = {0};
|
||||
enum bp_result bp_result = BP_RESULT_UNSUPPORTED;
|
||||
uint32_t bios_0_scratch;
|
||||
uint32_t device_id_mask = 0;
|
||||
|
|
@ -826,13 +824,6 @@ static enum bp_result bios_parser_dac_load_detection(
|
|||
|
||||
bp_params.engine_id = engine_id;
|
||||
bp_result = bp->cmd_tbl.dac_load_detection(bp, &bp_params);
|
||||
} else if (ext_enc_id.id) {
|
||||
if (!bp->cmd_tbl.external_encoder_control)
|
||||
return BP_RESULT_UNSUPPORTED;
|
||||
|
||||
ext_cntl.action = EXTERNAL_ENCODER_CONTROL_DAC_LOAD_DETECT;
|
||||
ext_cntl.encoder_id = ext_enc_id;
|
||||
bp_result = bp->cmd_tbl.external_encoder_control(bp, &ext_cntl);
|
||||
}
|
||||
|
||||
if (bp_result != BP_RESULT_OK)
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@
|
|||
#include "dcn32/dcn32_clk_mgr.h"
|
||||
#include "dcn35/dcn35_clk_mgr.h"
|
||||
#include "dcn401/dcn401_clk_mgr.h"
|
||||
#include "dcn42/dcn42_clk_mgr.h"
|
||||
|
||||
int clk_mgr_helper_get_active_display_cnt(
|
||||
struct dc *dc,
|
||||
|
|
@ -362,6 +363,18 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p
|
|||
return &clk_mgr->base;
|
||||
}
|
||||
break;
|
||||
case AMDGPU_FAMILY_GC_11_5_4: {
|
||||
struct clk_mgr_dcn42 *clk_mgr = kzalloc(sizeof(*clk_mgr), GFP_KERNEL);
|
||||
|
||||
if (clk_mgr == NULL) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dcn42_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg);
|
||||
return &clk_mgr->base.base;
|
||||
}
|
||||
break;
|
||||
#endif /* CONFIG_DRM_AMD_DC_FP */
|
||||
default:
|
||||
ASSERT(0); /* Unknown Asic */
|
||||
|
|
@ -419,6 +432,9 @@ void dc_destroy_clk_mgr(struct clk_mgr *clk_mgr_base)
|
|||
case AMDGPU_FAMILY_GC_12_0_0:
|
||||
dcn401_clk_mgr_destroy(clk_mgr);
|
||||
break;
|
||||
case AMDGPU_FAMILY_GC_11_5_4:
|
||||
dcn42_clk_mgr_destroy(clk_mgr);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -547,6 +547,7 @@ void dcn3_clk_mgr_construct(
|
|||
/* in case we don't get a value from the register, use default */
|
||||
if (clk_mgr->base.dentist_vco_freq_khz == 0)
|
||||
clk_mgr->base.dentist_vco_freq_khz = 3650000;
|
||||
|
||||
/* Convert dprefclk units from MHz to KHz */
|
||||
/* Value already divided by 10, some resolution lost */
|
||||
|
||||
|
|
|
|||
|
|
@ -31,59 +31,19 @@
|
|||
#include "link_service.h"
|
||||
#include "logger_types.h"
|
||||
|
||||
#include "clk/clk_15_0_0_offset.h"
|
||||
#include "clk/clk_15_0_0_sh_mask.h"
|
||||
#include "dcn/dcn_4_2_0_offset.h"
|
||||
#include "dcn/dcn_4_2_0_sh_mask.h"
|
||||
|
||||
|
||||
#undef DC_LOGGER
|
||||
#define DC_LOGGER \
|
||||
clk_mgr->base.base.ctx->logger
|
||||
|
||||
|
||||
#define DCN_BASE__INST0_SEG1 0x000000C0
|
||||
|
||||
#define regCLK8_CLK2_BYPASS_CNTL 0x4c2a
|
||||
#define regCLK8_CLK2_BYPASS_CNTL_BASE_IDX 0
|
||||
#define CLK8_CLK2_BYPASS_CNTL__CLK2_BYPASS_SEL__SHIFT 0x0
|
||||
#define CLK8_CLK2_BYPASS_CNTL__CLK2_BYPASS_DIV__SHIFT 0x10
|
||||
#define CLK8_CLK2_BYPASS_CNTL__CLK2_BYPASS_SEL_MASK 0x00000007L
|
||||
#define CLK8_CLK2_BYPASS_CNTL__CLK2_BYPASS_DIV_MASK 0x000F0000L
|
||||
|
||||
#define regDENTIST_DISPCLK_CNTL 0x0064
|
||||
#define regDENTIST_DISPCLK_CNTL_BASE_IDX 1
|
||||
|
||||
// DENTIST_DISPCLK_CNTL
|
||||
#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_WDIVIDER__SHIFT 0x0
|
||||
#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_RDIVIDER__SHIFT 0x8
|
||||
#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_CHG_DONE__SHIFT 0x13
|
||||
#define DENTIST_DISPCLK_CNTL__DENTIST_DPPCLK_CHG_DONE__SHIFT 0x14
|
||||
#define DENTIST_DISPCLK_CNTL__DENTIST_DPPCLK_WDIVIDER__SHIFT 0x18
|
||||
#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_WDIVIDER_MASK 0x0000007FL
|
||||
#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_RDIVIDER_MASK 0x00007F00L
|
||||
#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_CHG_DONE_MASK 0x00080000L
|
||||
#define DENTIST_DISPCLK_CNTL__DENTIST_DPPCLK_CHG_DONE_MASK 0x00100000L
|
||||
#define DENTIST_DISPCLK_CNTL__DENTIST_DPPCLK_WDIVIDER_MASK 0x7F000000L
|
||||
#define mmDENTIST_DISPCLK_CNTL 0x0124
|
||||
#define mmCLK8_CLK_TICK_CNT_CONFIG_REG 0x1B851
|
||||
#define mmCLK8_CLK0_CURRENT_CNT 0x1B853
|
||||
#define mmCLK8_CLK1_CURRENT_CNT 0x1B854
|
||||
#define mmCLK8_CLK2_CURRENT_CNT 0x1B855
|
||||
#define mmCLK8_CLK3_CURRENT_CNT 0x1B856
|
||||
#define mmCLK8_CLK4_CURRENT_CNT 0x1B857
|
||||
|
||||
|
||||
#define mmCLK8_CLK0_BYPASS_CNTL 0x1B81A
|
||||
#define mmCLK8_CLK1_BYPASS_CNTL 0x1B822
|
||||
#define mmCLK8_CLK2_BYPASS_CNTL 0x1B82A
|
||||
#define mmCLK8_CLK3_BYPASS_CNTL 0x1B832
|
||||
#define mmCLK8_CLK4_BYPASS_CNTL 0x1B83A
|
||||
|
||||
|
||||
#define mmCLK8_CLK0_DS_CNTL 0x1B814
|
||||
#define mmCLK8_CLK1_DS_CNTL 0x1B81C
|
||||
#define mmCLK8_CLK2_DS_CNTL 0x1B824
|
||||
#define mmCLK8_CLK3_DS_CNTL 0x1B82C
|
||||
#define mmCLK8_CLK4_DS_CNTL 0x1B834
|
||||
|
||||
|
||||
dc_logger
|
||||
#define DC_LOGGER_INIT(logger) \
|
||||
struct dal_logger *dc_logger = logger
|
||||
|
||||
#define DCN42_CLKIP_REFCLK 48000
|
||||
|
||||
#undef FN
|
||||
#define FN(reg_name, field_name) \
|
||||
|
|
@ -92,16 +52,25 @@
|
|||
#define REG(reg) \
|
||||
(clk_mgr->regs->reg)
|
||||
|
||||
// for DCN register access
|
||||
#define DCN_BASE__INST0_SEG0 0x00000012
|
||||
#define DCN_BASE__INST0_SEG1 0x000000C0
|
||||
|
||||
#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg
|
||||
|
||||
#define BASE(seg) BASE_INNER(seg)
|
||||
|
||||
#define SR(reg_name)\
|
||||
.reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \
|
||||
reg ## reg_name
|
||||
#define SR(reg_name) \
|
||||
.reg_name = BASE(reg ## reg_name ## _BASE_IDX) + reg ## reg_name
|
||||
|
||||
#define CLK_SR_DCN42(reg_name)\
|
||||
.reg_name = mm ## reg_name
|
||||
// for CLKIP register access
|
||||
#define CLK_BASE__INST0_SEG0 0x00016C00
|
||||
|
||||
#define CLK_BASE_INNER(seg) \
|
||||
CLK_BASE__INST0_SEG ## seg
|
||||
|
||||
#define CLK_SR_DCN42(reg_name) \
|
||||
.reg_name = CLK_BASE(reg ## reg_name ## _BASE_IDX) + reg ## reg_name
|
||||
|
||||
static const struct clk_mgr_registers clk_mgr_regs_dcn42 = {
|
||||
CLK_REG_LIST_DCN42()
|
||||
|
|
@ -115,26 +84,21 @@ static const struct clk_mgr_mask clk_mgr_mask_dcn42 = {
|
|||
CLK_COMMON_MASK_SH_LIST_DCN42(_MASK)
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define TO_CLK_MGR_DCN42(clk_mgr_int)\
|
||||
container_of(clk_mgr_int, struct clk_mgr_dcn42, base)
|
||||
|
||||
int dcn42_get_active_display_cnt_wa(
|
||||
struct dc *dc,
|
||||
struct dc_state *context,
|
||||
int *all_active_disps)
|
||||
bool dcn42_has_active_display(struct dc *dc, const struct dc_state *context)
|
||||
{
|
||||
int i, display_count = 0;
|
||||
bool tmds_present = false;
|
||||
int i, active_count = 0;
|
||||
|
||||
for (i = 0; i < context->stream_count; i++) {
|
||||
const struct dc_stream_state *stream = context->streams[i];
|
||||
|
||||
if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A ||
|
||||
stream->signal == SIGNAL_TYPE_DVI_SINGLE_LINK ||
|
||||
stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK)
|
||||
tmds_present = true;
|
||||
/* Checking stream / link detection ensuring that PHY is active*/
|
||||
if (dc_is_hdmi_signal(stream->signal) ||
|
||||
dc_is_dvi_signal(stream->signal) ||
|
||||
(dc_is_dp_signal(stream->signal) && !stream->dpms_off))
|
||||
active_count++;
|
||||
}
|
||||
|
||||
for (i = 0; i < dc->link_count; i++) {
|
||||
|
|
@ -143,15 +107,53 @@ int dcn42_get_active_display_cnt_wa(
|
|||
/* abusing the fact that the dig and phy are coupled to see if the phy is enabled */
|
||||
if (link->link_enc && link->link_enc->funcs->is_dig_enabled &&
|
||||
link->link_enc->funcs->is_dig_enabled(link->link_enc))
|
||||
display_count++;
|
||||
active_count++;
|
||||
}
|
||||
if (all_active_disps != NULL)
|
||||
*all_active_disps = display_count;
|
||||
/* WA for hang on HDMI after display off back on*/
|
||||
if (display_count == 0 && tmds_present)
|
||||
display_count = 1;
|
||||
|
||||
return display_count;
|
||||
return active_count > 0;
|
||||
}
|
||||
|
||||
static uint32_t dcn42_get_clock_freq_from_clkip(struct clk_mgr *clk_mgr_base, enum clock_type clock)
|
||||
{
|
||||
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
|
||||
uint64_t clock_freq_mhz = 0;
|
||||
uint32_t timer_threshold = 0;
|
||||
|
||||
// always safer to read the timer threshold instead of using cached value
|
||||
REG_GET(CLK8_CLK_TICK_CNT_CONFIG_REG, TIMER_THRESHOLD, &timer_threshold);
|
||||
|
||||
if (timer_threshold == 0) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (clock) {
|
||||
case clock_type_dispclk:
|
||||
clock_freq_mhz = REG_READ(CLK8_CLK0_CURRENT_CNT);
|
||||
break;
|
||||
case clock_type_dppclk:
|
||||
clock_freq_mhz = REG_READ(CLK8_CLK1_CURRENT_CNT);
|
||||
break;
|
||||
case clock_type_dprefclk:
|
||||
clock_freq_mhz = REG_READ(CLK8_CLK2_CURRENT_CNT);
|
||||
break;
|
||||
case clock_type_dcfclk:
|
||||
clock_freq_mhz = REG_READ(CLK8_CLK3_CURRENT_CNT);
|
||||
break;
|
||||
case clock_type_dtbclk:
|
||||
clock_freq_mhz = REG_READ(CLK8_CLK4_CURRENT_CNT);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
clock_freq_mhz *= DCN42_CLKIP_REFCLK;
|
||||
clock_freq_mhz = div_u64(clock_freq_mhz, timer_threshold);
|
||||
|
||||
// there are no DCN clocks over 0xFFFFFFFF MHz
|
||||
ASSERT(clock_freq_mhz <= 0xFFFFFFFF);
|
||||
|
||||
return (uint32_t)clock_freq_mhz;
|
||||
}
|
||||
|
||||
void dcn42_update_clocks_update_dtb_dto(struct clk_mgr_internal *clk_mgr,
|
||||
|
|
@ -213,22 +215,18 @@ void dcn42_update_clocks(struct clk_mgr *clk_mgr_base,
|
|||
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
|
||||
struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk;
|
||||
struct dc *dc = clk_mgr_base->ctx->dc;
|
||||
int display_count = 0;
|
||||
bool update_dppclk = false;
|
||||
bool update_dispclk = false;
|
||||
bool dpp_clock_lowered = false;
|
||||
int all_active_disps = 0;
|
||||
bool has_active_display;
|
||||
|
||||
if (dc->work_arounds.skip_clock_update)
|
||||
return;
|
||||
|
||||
display_count = dcn42_get_active_display_cnt_wa(dc, context, &all_active_disps);
|
||||
has_active_display = dcn42_has_active_display(dc, context);
|
||||
|
||||
/*dml21 issue*/
|
||||
ASSERT(new_clocks->dtbclk_en && new_clocks->ref_dtbclk_khz > 590000); //remove this section if assert is hit
|
||||
if (new_clocks->dtbclk_en && new_clocks->ref_dtbclk_khz < 590000)
|
||||
new_clocks->ref_dtbclk_khz = 600000;
|
||||
|
||||
/*
|
||||
* if it is safe to lower, but we are already in the lower state, we don't have to do anything
|
||||
* also if safe to lower is false, we just go in the higher state
|
||||
|
|
@ -248,7 +246,7 @@ void dcn42_update_clocks(struct clk_mgr *clk_mgr_base,
|
|||
/* check that we're not already in lower */
|
||||
if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_LOW_POWER) {
|
||||
/* if we can go lower, go lower */
|
||||
if (display_count == 0)
|
||||
if (has_active_display == false)
|
||||
clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_LOW_POWER;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -262,9 +260,7 @@ void dcn42_update_clocks(struct clk_mgr *clk_mgr_base,
|
|||
|
||||
dcn42_update_clocks_update_dtb_dto(clk_mgr, context, new_clocks->ref_dtbclk_khz);
|
||||
dcn42_smu_set_dtbclk(clk_mgr, true);
|
||||
if (clk_mgr_base->boot_snapshot.timer_threhold)
|
||||
actual_dtbclk = REG_READ(CLK8_CLK4_CURRENT_CNT) / (clk_mgr_base->boot_snapshot.timer_threhold / 48000);
|
||||
|
||||
actual_dtbclk = dcn42_get_clock_freq_from_clkip(clk_mgr_base, clock_type_dtbclk);
|
||||
|
||||
if (actual_dtbclk > 590000) {
|
||||
clk_mgr_base->clks.ref_dtbclk_khz = new_clocks->ref_dtbclk_khz;
|
||||
|
|
@ -308,7 +304,7 @@ void dcn42_update_clocks(struct clk_mgr *clk_mgr_base,
|
|||
}
|
||||
|
||||
if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz) &&
|
||||
(new_clocks->dispclk_khz > 0 || (safe_to_lower && display_count == 0))) {
|
||||
(new_clocks->dispclk_khz > 0 || (safe_to_lower && has_active_display == false))) {
|
||||
int requested_dispclk_khz = new_clocks->dispclk_khz;
|
||||
|
||||
dcn35_disable_otg_wa(clk_mgr_base, context, safe_to_lower, true);
|
||||
|
|
@ -386,34 +382,27 @@ bool dcn42_are_clock_states_equal(struct dc_clocks *a,
|
|||
static void dcn42_dump_clk_registers_internal(struct dcn42_clk_internal *internal, struct clk_mgr *clk_mgr_base)
|
||||
{
|
||||
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
|
||||
uint32_t ratio = 1;
|
||||
|
||||
internal->CLK8_CLK_TICK_CNT__TIMER_THRESHOLD = REG_READ(CLK8_CLK_TICK_CNT_CONFIG_REG) & 0xFFFFFF;
|
||||
|
||||
ratio = internal->CLK8_CLK_TICK_CNT__TIMER_THRESHOLD / 48000;
|
||||
ASSERT(ratio != 0);
|
||||
|
||||
if (ratio) {
|
||||
// read dcf deep sleep divider
|
||||
internal->CLK8_CLK0_DS_CNTL = REG_READ(CLK8_CLK0_DS_CNTL);
|
||||
internal->CLK8_CLK3_DS_CNTL = REG_READ(CLK8_CLK3_DS_CNTL);
|
||||
// read dispclk
|
||||
internal->CLK8_CLK0_CURRENT_CNT = REG_READ(CLK8_CLK0_CURRENT_CNT) / ratio;
|
||||
internal->CLK8_CLK0_BYPASS_CNTL = REG_READ(CLK8_CLK0_BYPASS_CNTL);
|
||||
// read dppclk
|
||||
internal->CLK8_CLK1_CURRENT_CNT = REG_READ(CLK8_CLK1_CURRENT_CNT) / ratio;
|
||||
internal->CLK8_CLK1_BYPASS_CNTL = REG_READ(CLK8_CLK1_BYPASS_CNTL);
|
||||
// read dprefclk
|
||||
internal->CLK8_CLK2_CURRENT_CNT = REG_READ(CLK8_CLK2_CURRENT_CNT) / ratio;
|
||||
internal->CLK8_CLK2_BYPASS_CNTL = REG_READ(CLK8_CLK2_BYPASS_CNTL);
|
||||
// read dcfclk
|
||||
internal->CLK8_CLK3_CURRENT_CNT = REG_READ(CLK8_CLK3_CURRENT_CNT) / ratio;
|
||||
internal->CLK8_CLK3_BYPASS_CNTL = REG_READ(CLK8_CLK3_BYPASS_CNTL);
|
||||
// read dtbclk
|
||||
internal->CLK8_CLK4_CURRENT_CNT = REG_READ(CLK8_CLK4_CURRENT_CNT) / ratio;
|
||||
internal->CLK8_CLK4_BYPASS_CNTL = REG_READ(CLK8_CLK4_BYPASS_CNTL);
|
||||
}
|
||||
REG_GET(CLK8_CLK_TICK_CNT_CONFIG_REG, TIMER_THRESHOLD, &internal->CLK8_CLK_TICK_CNT__TIMER_THRESHOLD);
|
||||
|
||||
// read dcf deep sleep divider
|
||||
internal->CLK8_CLK0_DS_CNTL = REG_READ(CLK8_CLK0_DS_CNTL);
|
||||
internal->CLK8_CLK3_DS_CNTL = REG_READ(CLK8_CLK3_DS_CNTL);
|
||||
// read dispclk
|
||||
internal->CLK8_CLK0_CURRENT_CNT = dcn42_get_clock_freq_from_clkip(clk_mgr_base, clock_type_dispclk);
|
||||
internal->CLK8_CLK0_BYPASS_CNTL = REG_READ(CLK8_CLK0_BYPASS_CNTL);
|
||||
// read dppclk
|
||||
internal->CLK8_CLK1_CURRENT_CNT = dcn42_get_clock_freq_from_clkip(clk_mgr_base, clock_type_dppclk);
|
||||
internal->CLK8_CLK1_BYPASS_CNTL = REG_READ(CLK8_CLK1_BYPASS_CNTL);
|
||||
// read dprefclk
|
||||
internal->CLK8_CLK2_CURRENT_CNT = dcn42_get_clock_freq_from_clkip(clk_mgr_base, clock_type_dprefclk);
|
||||
internal->CLK8_CLK2_BYPASS_CNTL = REG_READ(CLK8_CLK2_BYPASS_CNTL);
|
||||
// read dcfclk
|
||||
internal->CLK8_CLK3_CURRENT_CNT = dcn42_get_clock_freq_from_clkip(clk_mgr_base, clock_type_dcfclk);
|
||||
internal->CLK8_CLK3_BYPASS_CNTL = REG_READ(CLK8_CLK3_BYPASS_CNTL);
|
||||
// read dtbclk
|
||||
internal->CLK8_CLK4_CURRENT_CNT = dcn42_get_clock_freq_from_clkip(clk_mgr_base, clock_type_dtbclk);
|
||||
internal->CLK8_CLK4_BYPASS_CNTL = REG_READ(CLK8_CLK4_BYPASS_CNTL);
|
||||
}
|
||||
|
||||
static void dcn42_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
|
||||
|
|
@ -422,8 +411,11 @@ static void dcn42_dump_clk_registers(struct clk_state_registers_and_bypass *regs
|
|||
struct dcn42_clk_internal internal = {0};
|
||||
char *bypass_clks[5] = {"0x0 DFS", "0x1 REFCLK", "0x2 ERROR", "0x3 400 FCH", "0x4 600 FCH"};
|
||||
|
||||
DC_LOGGER_INIT(clk_mgr->base.base.ctx->logger);
|
||||
(void)dc_logger;
|
||||
|
||||
dcn42_dump_clk_registers_internal(&internal, &clk_mgr->base.base);
|
||||
regs_and_bypass->timer_threhold = internal.CLK8_CLK_TICK_CNT__TIMER_THRESHOLD;
|
||||
regs_and_bypass->timer_threshold = internal.CLK8_CLK_TICK_CNT__TIMER_THRESHOLD;
|
||||
regs_and_bypass->dcfclk = internal.CLK8_CLK3_CURRENT_CNT / 10;
|
||||
regs_and_bypass->dcf_deep_sleep_divider = internal.CLK8_CLK3_DS_CNTL / 10;
|
||||
regs_and_bypass->dcf_deep_sleep_allow = internal.CLK8_CLK3_DS_CNTL & 0x10; /*bit 4: CLK0_ALLOW_DS*/
|
||||
|
|
@ -432,18 +424,10 @@ static void dcn42_dump_clk_registers(struct clk_state_registers_and_bypass *regs
|
|||
regs_and_bypass->dppclk = internal.CLK8_CLK1_CURRENT_CNT / 10;
|
||||
regs_and_bypass->dtbclk = internal.CLK8_CLK4_CURRENT_CNT / 10;
|
||||
|
||||
regs_and_bypass->dppclk_bypass = internal.CLK8_CLK1_BYPASS_CNTL & 0x0007;
|
||||
if (regs_and_bypass->dppclk_bypass > 4)
|
||||
regs_and_bypass->dppclk_bypass = 0;
|
||||
regs_and_bypass->dcfclk_bypass = internal.CLK8_CLK3_BYPASS_CNTL & 0x0007;
|
||||
if (regs_and_bypass->dcfclk_bypass > 4)
|
||||
regs_and_bypass->dcfclk_bypass = 0;
|
||||
regs_and_bypass->dispclk_bypass = internal.CLK8_CLK0_BYPASS_CNTL & 0x0007;
|
||||
if (regs_and_bypass->dispclk_bypass > 4)
|
||||
regs_and_bypass->dispclk_bypass = 0;
|
||||
regs_and_bypass->dprefclk_bypass = internal.CLK8_CLK2_BYPASS_CNTL & 0x0007;
|
||||
if (regs_and_bypass->dprefclk_bypass > 4)
|
||||
regs_and_bypass->dprefclk_bypass = 0;
|
||||
regs_and_bypass->dispclk_bypass = get_reg_field_value(internal.CLK8_CLK0_BYPASS_CNTL, CLK8_CLK0_BYPASS_CNTL, CLK0_BYPASS_SEL);
|
||||
regs_and_bypass->dppclk_bypass = get_reg_field_value(internal.CLK8_CLK1_BYPASS_CNTL, CLK8_CLK1_BYPASS_CNTL, CLK1_BYPASS_SEL);
|
||||
regs_and_bypass->dprefclk_bypass = get_reg_field_value(internal.CLK8_CLK2_BYPASS_CNTL, CLK8_CLK2_BYPASS_CNTL, CLK2_BYPASS_SEL);
|
||||
regs_and_bypass->dcfclk_bypass = get_reg_field_value(internal.CLK8_CLK3_BYPASS_CNTL, CLK8_CLK3_BYPASS_CNTL, CLK3_BYPASS_SEL);
|
||||
|
||||
if (clk_mgr->base.base.ctx->dc->debug.pstate_enabled) {
|
||||
DC_LOG_SMU("clk_type,clk_value,deepsleep_cntl,deepsleep_allow,bypass\n");
|
||||
|
|
@ -467,7 +451,6 @@ static void dcn42_dump_clk_registers(struct clk_state_registers_and_bypass *regs
|
|||
|
||||
// REGISTER VALUES
|
||||
DC_LOG_SMU("reg_name,value,clk_type\n");
|
||||
|
||||
DC_LOG_SMU("CLK1_CLK3_CURRENT_CNT,%d,dcfclk\n",
|
||||
internal.CLK8_CLK3_CURRENT_CNT);
|
||||
|
||||
|
|
@ -588,6 +571,9 @@ void dcn42_init_clocks(struct clk_mgr *clk_mgr_base)
|
|||
struct clk_mgr_dcn42 *clk_mgr = TO_CLK_MGR_DCN42(clk_mgr_int);
|
||||
struct dcn42_smu_dpm_clks smu_dpm_clks = { 0 };
|
||||
|
||||
DC_LOGGER_INIT(clk_mgr_base->ctx->logger);
|
||||
(void)dc_logger;
|
||||
|
||||
init_clk_states(clk_mgr_base);
|
||||
|
||||
// to adjust dp_dto reference clock if ssc is enable otherwise to apply dprefclk
|
||||
|
|
@ -597,6 +583,7 @@ void dcn42_init_clocks(struct clk_mgr *clk_mgr_base)
|
|||
else
|
||||
clk_mgr_base->dp_dto_source_clock_in_khz = clk_mgr_base->dprefclk_khz;
|
||||
|
||||
DC_LOG_SMU("dp_dto_source_clock %d, dprefclk %d\n", clk_mgr_base->dp_dto_source_clock_in_khz, clk_mgr_base->dprefclk_khz);
|
||||
dcn42_dump_clk_registers(&clk_mgr_base->boot_snapshot, clk_mgr);
|
||||
|
||||
clk_mgr_base->clks.ref_dtbclk_khz = clk_mgr_base->boot_snapshot.dtbclk * 10;
|
||||
|
|
@ -605,6 +592,12 @@ void dcn42_init_clocks(struct clk_mgr *clk_mgr_base)
|
|||
clk_mgr_base->clks.dtbclk_en = true;
|
||||
}
|
||||
|
||||
if (clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dcfclk_levels != 0) {
|
||||
/*skip to get clock table and notify pmfw watermark range again*/
|
||||
DC_LOG_SMU("skip to get dpm_clks from pmfw from resume and acr\n");
|
||||
return;
|
||||
}
|
||||
|
||||
smu_dpm_clks.dpm_clks = (DpmClocks_t_dcn42 *)dm_helpers_allocate_gpu_mem(
|
||||
clk_mgr_base->ctx,
|
||||
DC_MEM_ALLOC_TYPE_GART,
|
||||
|
|
@ -711,10 +704,9 @@ void dcn42_init_clocks(struct clk_mgr *clk_mgr_base)
|
|||
/* DTBCLK*/
|
||||
clk_mgr_base->bw_params->clk_table.entries[0].dtbclk_mhz = clk_mgr_base->clks.ref_dtbclk_khz / 1000;
|
||||
clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dtbclk_levels = 1;
|
||||
|
||||
/* Refresh bounding box */
|
||||
clk_mgr_base->ctx->dc->res_pool->funcs->update_bw_bounding_box(
|
||||
clk_mgr_base->ctx->dc, clk_mgr_base->bw_params);
|
||||
clk_mgr_base->ctx->dc, clk_mgr_base->bw_params);
|
||||
}
|
||||
}
|
||||
if (smu_dpm_clks.dpm_clks && smu_dpm_clks.mc_address.quad_part != 0)
|
||||
|
|
@ -826,7 +818,6 @@ static void dcn42_read_ss_info_from_lut(struct clk_mgr_internal *clk_mgr)
|
|||
}
|
||||
}
|
||||
|
||||
/* Exposed for dcn42b reuse */
|
||||
void dcn42_build_watermark_ranges(struct clk_bw_params *bw_params, struct dcn42_watermarks *table)
|
||||
{
|
||||
int i, num_valid_sets;
|
||||
|
|
@ -885,18 +876,42 @@ void dcn42_build_watermark_ranges(struct clk_bw_params *bw_params, struct dcn42_
|
|||
|
||||
void dcn42_notify_wm_ranges(struct clk_mgr *clk_mgr_base)
|
||||
{
|
||||
int i = 0;
|
||||
struct dcn42_watermarks *table = NULL;
|
||||
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
|
||||
struct clk_mgr_dcn42 *clk_mgr_dcn42 = TO_CLK_MGR_DCN42(clk_mgr);
|
||||
struct dcn42_watermarks *table = clk_mgr_dcn42->smu_wm_set.wm_set;
|
||||
|
||||
if (!clk_mgr->smu_ver)
|
||||
return;
|
||||
/*send once already skip*/
|
||||
if (clk_mgr_base->bw_params->wm_table.entries[WM_A].valid == true)
|
||||
return;
|
||||
clk_mgr_dcn42->smu_wm_set.wm_set = (struct dcn42_watermarks *)dm_helpers_allocate_gpu_mem(
|
||||
clk_mgr->base.ctx,
|
||||
DC_MEM_ALLOC_TYPE_GART,
|
||||
sizeof(struct dcn42_watermarks),
|
||||
&clk_mgr_dcn42->smu_wm_set.mc_address.quad_part);
|
||||
|
||||
ASSERT(clk_mgr_dcn42->smu_wm_set.wm_set);
|
||||
|
||||
table = clk_mgr_dcn42->smu_wm_set.wm_set;
|
||||
|
||||
if (!table || clk_mgr_dcn42->smu_wm_set.mc_address.quad_part == 0)
|
||||
return;
|
||||
|
||||
memset(table, 0, sizeof(*table));
|
||||
/*same as previous asic, set wm valid before building watermark ranges*/
|
||||
for (i = 0; i < WM_SET_COUNT; i++) {
|
||||
clk_mgr_base->bw_params->wm_table.entries[i].wm_inst = i;
|
||||
|
||||
if (i >= clk_mgr_base->bw_params->clk_table.num_entries) {
|
||||
clk_mgr_base->bw_params->wm_table.entries[i].valid = false;
|
||||
continue;
|
||||
}
|
||||
clk_mgr_base->bw_params->wm_table.entries[i].wm_type = WM_TYPE_PSTATE_CHG;
|
||||
clk_mgr_base->bw_params->wm_table.entries[i].valid = true;
|
||||
}
|
||||
/* build watermark_range will check this valid range*/
|
||||
dcn42_build_watermark_ranges(clk_mgr_base->bw_params, table);
|
||||
|
||||
dcn42_smu_set_dram_addr_high(clk_mgr,
|
||||
|
|
@ -904,18 +919,21 @@ void dcn42_notify_wm_ranges(struct clk_mgr *clk_mgr_base)
|
|||
dcn42_smu_set_dram_addr_low(clk_mgr,
|
||||
clk_mgr_dcn42->smu_wm_set.mc_address.low_part);
|
||||
dcn42_smu_transfer_wm_table_dram_2_smu(clk_mgr);
|
||||
|
||||
if (clk_mgr_dcn42->smu_wm_set.wm_set && clk_mgr_dcn42->smu_wm_set.mc_address.quad_part != 0)
|
||||
dm_helpers_free_gpu_mem(clk_mgr->base.ctx, DC_MEM_ALLOC_TYPE_GART,
|
||||
clk_mgr_dcn42->smu_wm_set.wm_set);
|
||||
|
||||
}
|
||||
|
||||
void dcn42_set_low_power_state(struct clk_mgr *clk_mgr_base)
|
||||
{
|
||||
int display_count;
|
||||
struct dc *dc = clk_mgr_base->ctx->dc;
|
||||
struct dc_state *context = dc->current_state;
|
||||
|
||||
if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_LOW_POWER) {
|
||||
display_count = dcn42_get_active_display_cnt_wa(dc, context, NULL);
|
||||
/* if we can go lower, go lower */
|
||||
if (display_count == 0)
|
||||
if (dcn42_has_active_display(dc, context) == false)
|
||||
clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_LOW_POWER;
|
||||
}
|
||||
|
||||
|
|
@ -1096,14 +1114,7 @@ void dcn42_clk_mgr_construct(
|
|||
clk_mgr->base.dprefclk_ss_divider = 1000;
|
||||
clk_mgr->base.ss_on_dprefclk = false;
|
||||
clk_mgr->base.dfs_ref_freq_khz = 48000; /*sync with pmfw*/
|
||||
|
||||
clk_mgr->smu_wm_set.wm_set = (struct dcn42_watermarks *)dm_helpers_allocate_gpu_mem(
|
||||
clk_mgr->base.base.ctx,
|
||||
DC_MEM_ALLOC_TYPE_GART,
|
||||
sizeof(struct dcn42_watermarks),
|
||||
&clk_mgr->smu_wm_set.mc_address.quad_part);
|
||||
|
||||
ASSERT(clk_mgr->smu_wm_set.wm_set);
|
||||
clk_mgr->base.base.clks.ref_dtbclk_khz = 600000;
|
||||
|
||||
/* Changed from DCN3.2_clock_frequency doc to match
|
||||
* dcn32_dump_clk_registers from 4 * dentist_vco_freq_khz /
|
||||
|
|
@ -1112,6 +1123,9 @@ void dcn42_clk_mgr_construct(
|
|||
clk_mgr->base.base.dprefclk_khz = 600000;
|
||||
|
||||
clk_mgr->base.smu_present = false;
|
||||
clk_mgr->base.smu_ver = dcn42_smu_get_pmfw_version(&clk_mgr->base);
|
||||
if (clk_mgr->base.smu_ver && clk_mgr->base.smu_ver != -1)
|
||||
clk_mgr->base.smu_present = true;
|
||||
|
||||
if (ctx->dc_bios->integrated_info) {
|
||||
clk_mgr->base.base.dentist_vco_freq_khz = ctx->dc_bios->integrated_info->dentist_vco_freq;
|
||||
|
|
@ -1122,7 +1136,9 @@ void dcn42_clk_mgr_construct(
|
|||
dcn42_bw_params.wm_table = ddr5_wm_table;
|
||||
dcn42_bw_params.vram_type = ctx->dc_bios->integrated_info->memory_type;
|
||||
dcn42_bw_params.dram_channel_width_bytes = ctx->dc_bios->integrated_info->memory_type == 0x22 ? 8 : 4;
|
||||
dcn42_bw_params.num_channels = ctx->dc_bios->integrated_info->ma_channel_number ? ctx->dc_bios->integrated_info->ma_channel_number : 4;
|
||||
dcn42_bw_params.num_channels = ctx->dc_bios->integrated_info->ma_channel_number ? ctx->dc_bios->integrated_info->ma_channel_number : 1;
|
||||
clk_mgr->base.base.dprefclk_khz = dcn42_smu_get_dprefclk(&clk_mgr->base);
|
||||
clk_mgr->base.base.clks.ref_dtbclk_khz = dcn42_smu_get_dtbclk(&clk_mgr->base);
|
||||
}
|
||||
/* in case we don't get a value from the BIOS, use default */
|
||||
if (clk_mgr->base.base.dentist_vco_freq_khz == 0)
|
||||
|
|
@ -1131,9 +1147,6 @@ void dcn42_clk_mgr_construct(
|
|||
/* Saved clocks configured at boot for debug purposes */
|
||||
dcn42_dump_clk_registers(&clk_mgr->base.base.boot_snapshot, clk_mgr);
|
||||
|
||||
if (clk_mgr->base.smu_present)
|
||||
clk_mgr->base.base.dprefclk_khz = dcn42_smu_get_dprefclk(&clk_mgr->base);
|
||||
clk_mgr->base.base.clks.ref_dtbclk_khz = 600000;
|
||||
dce_clock_read_ss_info(&clk_mgr->base);
|
||||
/*when clk src is from FCH, it could have ss, same clock src as DPREF clk*/
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@ void dcn42_clk_mgr_construct(struct dc_context *ctx,
|
|||
|
||||
void dcn42_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr_int);
|
||||
|
||||
/* Exposed for dcn42b reuse */
|
||||
void dcn42_init_single_clock(unsigned int *entry_0,
|
||||
uint32_t *smu_entry_0,
|
||||
uint8_t num_levels);
|
||||
|
|
@ -76,4 +75,5 @@ int dcn42_get_active_display_cnt_wa(struct dc *dc, struct dc_state *context, int
|
|||
void dcn42_update_clocks_update_dpp_dto(struct clk_mgr_internal *clk_mgr, struct dc_state *context, bool safe_to_lower);
|
||||
void dcn42_update_clocks_update_dtb_dto(struct clk_mgr_internal *clk_mgr, struct dc_state *context, int ref_dtbclk_khz);
|
||||
bool dcn42_is_spll_ssc_enabled(struct clk_mgr *clk_mgr_base);
|
||||
bool dcn42_has_active_display(struct dc *dc, const struct dc_state *context);
|
||||
#endif //__DCN42_CLK_MGR_H__
|
||||
|
|
|
|||
|
|
@ -2895,16 +2895,27 @@ static struct surface_update_descriptor det_surface_update(
|
|||
elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
|
||||
}
|
||||
|
||||
if (u->blend_tf || (u->gamma && dce_use_lut(u->plane_info ? u->plane_info->format : u->surface->format))) {
|
||||
if (u->cm || (u->gamma && dce_use_lut(u->plane_info ? u->plane_info->format : u->surface->format))) {
|
||||
update_flags->bits.gamma_change = 1;
|
||||
elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
|
||||
}
|
||||
|
||||
if (u->lut3d_func || u->func_shaper) {
|
||||
if (u->cm && (u->cm->flags.bits.lut3d_enable || u->surface->cm.flags.bits.lut3d_enable)) {
|
||||
update_flags->bits.lut_3d = 1;
|
||||
elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
|
||||
}
|
||||
|
||||
if (u->cm && u->cm->flags.bits.lut3d_dma_enable != u->surface->cm.flags.bits.lut3d_dma_enable &&
|
||||
u->cm->flags.bits.lut3d_enable && u->surface->cm.flags.bits.lut3d_enable) {
|
||||
/* Toggling 3DLUT loading between DMA and Host is illegal */
|
||||
BREAK_TO_DEBUGGER();
|
||||
}
|
||||
|
||||
if (u->cm && u->cm->flags.bits.lut3d_enable && !u->cm->flags.bits.lut3d_dma_enable) {
|
||||
/* Host loading 3DLUT requires full update but only stream lock */
|
||||
elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_STREAM);
|
||||
}
|
||||
|
||||
if (u->hdr_mult.value)
|
||||
if (u->hdr_mult.value != u->surface->hdr_mult.value) {
|
||||
// TODO: Should be fast?
|
||||
|
|
@ -2919,24 +2930,15 @@ static struct surface_update_descriptor det_surface_update(
|
|||
elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
|
||||
}
|
||||
|
||||
if (u->cm2_params) {
|
||||
if (u->cm2_params->component_settings.shaper_3dlut_setting != u->surface->mcm_shaper_3dlut_setting
|
||||
|| u->cm2_params->component_settings.lut1d_enable != u->surface->mcm_lut1d_enable
|
||||
|| u->cm2_params->cm2_luts.lut3d_data.lut3d_src != u->surface->mcm_luts.lut3d_data.lut3d_src) {
|
||||
update_flags->bits.mcm_transfer_function_enable_change = 1;
|
||||
elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
|
||||
}
|
||||
if (u->cm_hist_control) {
|
||||
update_flags->bits.cm_hist_change = 1;
|
||||
elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
|
||||
}
|
||||
|
||||
if (update_flags->bits.lut_3d &&
|
||||
u->surface->mcm_luts.lut3d_data.lut3d_src != DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM) {
|
||||
elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
|
||||
}
|
||||
|
||||
if (check_config->enable_legacy_fast_update &&
|
||||
(update_flags->bits.gamma_change ||
|
||||
update_flags->bits.gamut_remap_change ||
|
||||
update_flags->bits.input_csc_change ||
|
||||
update_flags->bits.cm_hist_change ||
|
||||
update_flags->bits.coeff_reduction_change)) {
|
||||
elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
|
||||
}
|
||||
|
|
@ -3168,6 +3170,11 @@ static void copy_surface_update_to_plane(
|
|||
surface->gamma_correction.type =
|
||||
srf_update->gamma->type;
|
||||
}
|
||||
if (srf_update->cm_hist_control) {
|
||||
memcpy(&surface->cm_hist_control,
|
||||
srf_update->cm_hist_control,
|
||||
sizeof(surface->cm_hist_control));
|
||||
}
|
||||
|
||||
if (srf_update->in_transfer_func) {
|
||||
surface->in_transfer_func.sdr_ref_white_level =
|
||||
|
|
@ -3181,24 +3188,12 @@ static void copy_surface_update_to_plane(
|
|||
sizeof(struct dc_transfer_func_distributed_points));
|
||||
}
|
||||
|
||||
if (srf_update->cm2_params) {
|
||||
surface->mcm_shaper_3dlut_setting = srf_update->cm2_params->component_settings.shaper_3dlut_setting;
|
||||
surface->mcm_lut1d_enable = srf_update->cm2_params->component_settings.lut1d_enable;
|
||||
surface->mcm_luts = srf_update->cm2_params->cm2_luts;
|
||||
/* Shaper, 3DLUT, 1DLUT */
|
||||
if (srf_update->cm) {
|
||||
memcpy(&surface->cm, srf_update->cm,
|
||||
sizeof(surface->cm));
|
||||
}
|
||||
|
||||
if (srf_update->func_shaper) {
|
||||
memcpy(&surface->in_shaper_func, srf_update->func_shaper,
|
||||
sizeof(surface->in_shaper_func));
|
||||
|
||||
if (surface->mcm_shaper_3dlut_setting >= DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER)
|
||||
surface->mcm_luts.shaper = &surface->in_shaper_func;
|
||||
}
|
||||
|
||||
if (srf_update->lut3d_func)
|
||||
memcpy(&surface->lut3d_func, srf_update->lut3d_func,
|
||||
sizeof(surface->lut3d_func));
|
||||
|
||||
if (srf_update->hdr_mult.value)
|
||||
surface->hdr_mult =
|
||||
srf_update->hdr_mult;
|
||||
|
|
@ -3207,17 +3202,6 @@ static void copy_surface_update_to_plane(
|
|||
surface->sdr_white_level_nits =
|
||||
srf_update->sdr_white_level_nits;
|
||||
|
||||
if (srf_update->blend_tf) {
|
||||
memcpy(&surface->blend_tf, srf_update->blend_tf,
|
||||
sizeof(surface->blend_tf));
|
||||
|
||||
if (surface->mcm_lut1d_enable)
|
||||
surface->mcm_luts.lut1d_func = &surface->blend_tf;
|
||||
}
|
||||
|
||||
if (srf_update->cm2_params || srf_update->blend_tf)
|
||||
surface->lut_bank_a = !surface->lut_bank_a;
|
||||
|
||||
if (srf_update->input_csc_color_matrix)
|
||||
surface->input_csc_color_matrix =
|
||||
*srf_update->input_csc_color_matrix;
|
||||
|
|
@ -4501,11 +4485,9 @@ static void commit_planes_for_stream(struct dc *dc,
|
|||
if (!should_update_pipe_for_plane(context, pipe_ctx, plane_state))
|
||||
continue;
|
||||
|
||||
if (srf_updates[i].cm2_params &&
|
||||
srf_updates[i].cm2_params->cm2_luts.lut3d_data.lut3d_src ==
|
||||
DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM &&
|
||||
srf_updates[i].cm2_params->component_settings.shaper_3dlut_setting ==
|
||||
DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER_3DLUT &&
|
||||
if (srf_updates[i].cm &&
|
||||
srf_updates[i].cm->flags.bits.lut3d_enable &&
|
||||
srf_updates[i].cm->flags.bits.lut3d_dma_enable &&
|
||||
dc->hwss.trigger_3dlut_dma_load)
|
||||
dc->hwss.trigger_3dlut_dma_load(dc, pipe_ctx);
|
||||
|
||||
|
|
@ -5073,6 +5055,7 @@ void populate_fast_updates(struct dc_fast_update *fast_update,
|
|||
fast_update[i].input_csc_color_matrix = srf_updates[i].input_csc_color_matrix;
|
||||
fast_update[i].coeff_reduction_factor = srf_updates[i].coeff_reduction_factor;
|
||||
fast_update[i].cursor_csc_color_matrix = srf_updates[i].cursor_csc_color_matrix;
|
||||
fast_update[i].cm_hist_control = srf_updates[i].cm_hist_control;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5090,6 +5073,7 @@ static bool fast_updates_exist(const struct dc_fast_update *fast_update, int sur
|
|||
fast_update[i].gamut_remap_matrix ||
|
||||
fast_update[i].input_csc_color_matrix ||
|
||||
fast_update[i].cursor_csc_color_matrix ||
|
||||
fast_update[i].cm_hist_control ||
|
||||
fast_update[i].coeff_reduction_factor)
|
||||
return true;
|
||||
}
|
||||
|
|
@ -5110,6 +5094,7 @@ bool fast_nonaddr_updates_exist(struct dc_fast_update *fast_update, int surface_
|
|||
fast_update[i].gamma ||
|
||||
fast_update[i].gamut_remap_matrix ||
|
||||
fast_update[i].coeff_reduction_factor ||
|
||||
fast_update[i].cm_hist_control ||
|
||||
fast_update[i].cursor_csc_color_matrix)
|
||||
return true;
|
||||
}
|
||||
|
|
@ -5151,6 +5136,12 @@ static bool full_update_required(
|
|||
const struct dc_stream_update *stream_update,
|
||||
const struct dc_stream_state *stream)
|
||||
{
|
||||
const union dc_plane_cm_flags blend_only_flags = {
|
||||
.bits = {
|
||||
.blend_enable = 1,
|
||||
}
|
||||
};
|
||||
|
||||
if (full_update_required_weak(dc, srf_updates, surface_count, stream_update, stream))
|
||||
return true;
|
||||
|
||||
|
|
@ -5163,14 +5154,12 @@ static bool full_update_required(
|
|||
(srf_updates[i].sdr_white_level_nits &&
|
||||
srf_updates[i].sdr_white_level_nits != srf_updates->surface->sdr_white_level_nits) ||
|
||||
srf_updates[i].in_transfer_func ||
|
||||
srf_updates[i].func_shaper ||
|
||||
srf_updates[i].lut3d_func ||
|
||||
srf_updates[i].surface->force_full_update ||
|
||||
(srf_updates[i].flip_addr &&
|
||||
srf_updates[i].flip_addr->address.tmz_surface != srf_updates[i].surface->address.tmz_surface) ||
|
||||
(srf_updates[i].cm2_params &&
|
||||
(srf_updates[i].cm2_params->component_settings.shaper_3dlut_setting != srf_updates[i].surface->mcm_shaper_3dlut_setting ||
|
||||
srf_updates[i].cm2_params->component_settings.lut1d_enable != srf_updates[i].surface->mcm_lut1d_enable))))
|
||||
(srf_updates[i].cm &&
|
||||
((srf_updates[i].cm->flags.all != blend_only_flags.all && srf_updates[i].cm->flags.all != 0) ||
|
||||
(srf_updates[i].surface->cm.flags.all != blend_only_flags.all && srf_updates[i].surface->cm.flags.all != 0)))))
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -5945,6 +5934,7 @@ bool dc_is_dmub_outbox_supported(struct dc *dc)
|
|||
|
||||
case AMDGPU_FAMILY_GC_11_0_1:
|
||||
case AMDGPU_FAMILY_GC_11_5_0:
|
||||
case AMDGPU_FAMILY_GC_11_5_4:
|
||||
if (!dc->debug.dpia_debug.bits.disable_dpia)
|
||||
return true;
|
||||
break;
|
||||
|
|
@ -6897,7 +6887,7 @@ bool dc_capture_register_software_state(struct dc *dc, struct dc_register_softwa
|
|||
struct dc_plane_state *plane_state = pipe_ctx->plane_state;
|
||||
|
||||
/* MPCC blending tree and mode control - capture actual blend configuration */
|
||||
state->mpc.mpcc_mode[i] = (plane_state->blend_tf.type != TF_TYPE_BYPASS) ? 1 : 0;
|
||||
state->mpc.mpcc_mode[i] = (plane_state->cm.blend_func.type != TF_TYPE_BYPASS) ? 1 : 0;
|
||||
state->mpc.mpcc_alpha_blend_mode[i] = plane_state->per_pixel_alpha ? 1 : 0;
|
||||
state->mpc.mpcc_alpha_multiplied_mode[i] = plane_state->pre_multiplied_alpha ? 1 : 0;
|
||||
state->mpc.mpcc_blnd_active_overlap_only[i] = 0; /* Default - no overlap restriction */
|
||||
|
|
@ -7295,6 +7285,23 @@ static bool update_planes_and_stream_prepare_v3(
|
|||
ASSERT(scratch->flow == UPDATE_V3_FLOW_INVALID);
|
||||
dc_exit_ips_for_hw_access(scratch->dc);
|
||||
|
||||
/* HWSS path determination needs to be done prior to updating the surface and stream states. */
|
||||
struct dc_fast_update fast_update[MAX_SURFACES] = { 0 };
|
||||
|
||||
populate_fast_updates(fast_update,
|
||||
scratch->surface_updates,
|
||||
scratch->surface_count,
|
||||
scratch->stream_update);
|
||||
|
||||
const bool is_hwss_fast_path_only =
|
||||
fast_update_only(scratch->dc,
|
||||
fast_update,
|
||||
scratch->surface_updates,
|
||||
scratch->surface_count,
|
||||
scratch->stream_update,
|
||||
scratch->stream) &&
|
||||
!scratch->dc->check_config.enable_legacy_fast_update;
|
||||
|
||||
if (!update_planes_and_stream_state(
|
||||
scratch->dc,
|
||||
scratch->surface_updates,
|
||||
|
|
@ -7310,26 +7317,7 @@ static bool update_planes_and_stream_prepare_v3(
|
|||
if (scratch->new_context == scratch->dc->current_state) {
|
||||
ASSERT(scratch->update_type < UPDATE_TYPE_FULL);
|
||||
|
||||
// TODO: Do we need this to be alive in execute?
|
||||
struct dc_fast_update fast_update[MAX_SURFACES] = { 0 };
|
||||
|
||||
populate_fast_updates(
|
||||
fast_update,
|
||||
scratch->surface_updates,
|
||||
scratch->surface_count,
|
||||
scratch->stream_update
|
||||
);
|
||||
const bool fast = fast_update_only(
|
||||
scratch->dc,
|
||||
fast_update,
|
||||
scratch->surface_updates,
|
||||
scratch->surface_count,
|
||||
scratch->stream_update,
|
||||
scratch->stream
|
||||
)
|
||||
// TODO: Can this be used to skip `populate_fast_updates`?
|
||||
&& !scratch->dc->check_config.enable_legacy_fast_update;
|
||||
scratch->flow = fast
|
||||
scratch->flow = is_hwss_fast_path_only
|
||||
? UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FAST
|
||||
: UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FULL;
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -2431,7 +2431,6 @@ static void resource_log_pipe_for_stream(struct dc *dc, struct dc_state *state,
|
|||
|
||||
int slice_idx, dpp_idx, plane_idx, slice_count, dpp_count;
|
||||
bool is_primary;
|
||||
DC_LOGGER_INIT(dc->ctx->logger);
|
||||
|
||||
slice_count = resource_get_opp_heads_for_otg_master(otg_master,
|
||||
&state->res_ctx, opp_heads);
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include "dc_dmub_srv.h"
|
||||
#include "dc_state_priv.h"
|
||||
#include "dc_stream_priv.h"
|
||||
#include "dce/dmub_hw_lock_mgr.h"
|
||||
|
||||
#define DC_LOGGER dc->ctx->logger
|
||||
#ifndef MIN
|
||||
|
|
@ -171,10 +172,12 @@ struct dc_stream_state *dc_create_stream_for_sink(
|
|||
goto fail;
|
||||
|
||||
stream = kzalloc_obj(struct dc_stream_state, GFP_ATOMIC);
|
||||
|
||||
if (stream == NULL)
|
||||
goto fail;
|
||||
|
||||
stream->update_scratch = kzalloc((int32_t) dc_update_scratch_space_size(), GFP_ATOMIC);
|
||||
|
||||
if (stream->update_scratch == NULL)
|
||||
goto fail;
|
||||
|
||||
|
|
@ -245,7 +248,6 @@ const struct dc_stream_status *dc_stream_get_status_const(
|
|||
const struct dc_stream_state *stream)
|
||||
{
|
||||
struct dc *dc = stream->ctx->dc;
|
||||
|
||||
return dc_state_get_stream_status(dc->current_state, stream);
|
||||
}
|
||||
|
||||
|
|
@ -257,6 +259,7 @@ void program_cursor_attributes(
|
|||
struct resource_context *res_ctx;
|
||||
struct pipe_ctx *pipe_to_program = NULL;
|
||||
bool enable_cursor_offload = dc_dmub_srv_is_cursor_offload_enabled(dc);
|
||||
bool unlock_dmub = false;
|
||||
|
||||
if (!stream)
|
||||
return;
|
||||
|
|
@ -275,6 +278,12 @@ void program_cursor_attributes(
|
|||
if (enable_cursor_offload && dc->hwss.begin_cursor_offload_update) {
|
||||
dc->hwss.begin_cursor_offload_update(dc, pipe_ctx);
|
||||
} else {
|
||||
if (dc->hwss.dmub_hw_control_lock && pipe_ctx->stream &&
|
||||
should_use_dmub_inbox0_lock_for_link(dc, pipe_ctx->stream->link)) {
|
||||
dc->hwss.dmub_hw_control_lock(dc, dc->current_state, true);
|
||||
unlock_dmub = true;
|
||||
}
|
||||
|
||||
dc->hwss.cursor_lock(dc, pipe_to_program, true);
|
||||
if (pipe_to_program->next_odm_pipe)
|
||||
dc->hwss.cursor_lock(dc, pipe_to_program->next_odm_pipe, true);
|
||||
|
|
@ -297,6 +306,9 @@ void program_cursor_attributes(
|
|||
dc->hwss.cursor_lock(dc, pipe_to_program, false);
|
||||
if (pipe_to_program->next_odm_pipe)
|
||||
dc->hwss.cursor_lock(dc, pipe_to_program->next_odm_pipe, false);
|
||||
|
||||
if (unlock_dmub)
|
||||
dc->hwss.dmub_hw_control_lock(dc, dc->current_state, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -404,6 +416,7 @@ void program_cursor_position(
|
|||
struct resource_context *res_ctx;
|
||||
struct pipe_ctx *pipe_to_program = NULL;
|
||||
bool enable_cursor_offload = dc_dmub_srv_is_cursor_offload_enabled(dc);
|
||||
bool unlock_dmub = false;
|
||||
|
||||
if (!stream)
|
||||
return;
|
||||
|
|
@ -423,10 +436,16 @@ void program_cursor_position(
|
|||
if (!pipe_to_program) {
|
||||
pipe_to_program = pipe_ctx;
|
||||
|
||||
if (enable_cursor_offload && dc->hwss.begin_cursor_offload_update)
|
||||
if (enable_cursor_offload && dc->hwss.begin_cursor_offload_update) {
|
||||
dc->hwss.begin_cursor_offload_update(dc, pipe_ctx);
|
||||
else
|
||||
} else {
|
||||
if (dc->hwss.dmub_hw_control_lock && pipe_ctx->stream &&
|
||||
should_use_dmub_inbox0_lock_for_link(dc, pipe_ctx->stream->link)) {
|
||||
dc->hwss.dmub_hw_control_lock(dc, dc->current_state, true);
|
||||
unlock_dmub = true;
|
||||
}
|
||||
dc->hwss.cursor_lock(dc, pipe_to_program, true);
|
||||
}
|
||||
}
|
||||
|
||||
dc->hwss.set_cursor_position(pipe_ctx);
|
||||
|
|
@ -438,10 +457,14 @@ void program_cursor_position(
|
|||
}
|
||||
|
||||
if (pipe_to_program) {
|
||||
if (enable_cursor_offload && dc->hwss.commit_cursor_offload_update)
|
||||
if (enable_cursor_offload && dc->hwss.commit_cursor_offload_update) {
|
||||
dc->hwss.commit_cursor_offload_update(dc, pipe_to_program);
|
||||
else
|
||||
} else {
|
||||
dc->hwss.cursor_lock(dc, pipe_to_program, false);
|
||||
|
||||
if (unlock_dmub)
|
||||
dc->hwss.dmub_hw_control_lock(dc, dc->current_state, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -523,8 +546,10 @@ bool dc_stream_program_cursor_position(
|
|||
struct pipe_ctx *pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
|
||||
|
||||
/* trigger event on first pipe with current stream */
|
||||
if (stream == pipe_ctx->stream) {
|
||||
pipe_ctx->stream_res.tg->funcs->program_manual_trigger(pipe_ctx->stream_res.tg);
|
||||
if (stream == pipe_ctx->stream &&
|
||||
pipe_ctx->stream_res.tg->funcs->program_manual_trigger) {
|
||||
pipe_ctx->stream_res.tg->funcs->program_manual_trigger(
|
||||
pipe_ctx->stream_res.tg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -984,7 +1009,6 @@ void dc_stream_release_3dlut_for_stream(
|
|||
if (rmcm_3dlut) {
|
||||
rmcm_3dlut->isInUse = false;
|
||||
rmcm_3dlut->stream = NULL;
|
||||
rmcm_3dlut->protection_bits = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -996,7 +1020,6 @@ void dc_stream_init_rmcm_3dlut(struct dc *dc)
|
|||
for (int i = 0; i < num_rmcm; i++) {
|
||||
dc->res_pool->rmcm_3dlut[i].isInUse = false;
|
||||
dc->res_pool->rmcm_3dlut[i].stream = NULL;
|
||||
dc->res_pool->rmcm_3dlut[i].protection_bits = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -139,6 +139,9 @@ const struct dc_plane_status *dc_plane_get_status(
|
|||
|
||||
if (pipe_ctx->plane_state && flags.bits.address)
|
||||
pipe_ctx->plane_state->status.is_flip_pending = false;
|
||||
if (pipe_ctx->plane_state && flags.bits.histogram)
|
||||
memset(&pipe_ctx->plane_state->status.cm_hist, 0,
|
||||
sizeof(pipe_ctx->plane_state->status.cm_hist));
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
@ -154,6 +157,12 @@ const struct dc_plane_status *dc_plane_get_status(
|
|||
|
||||
if (flags.bits.address)
|
||||
dc->hwss.update_pending_status(pipe_ctx);
|
||||
if (flags.bits.histogram) {
|
||||
struct dpp *dpp = pipe_ctx->plane_res.dpp;
|
||||
|
||||
if (dpp && dpp->funcs->dpp_cm_hist_read)
|
||||
dpp->funcs->dpp_cm_hist_read(dpp, &pipe_ctx->plane_state->status.cm_hist);
|
||||
}
|
||||
}
|
||||
|
||||
return plane_status;
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ struct dcn_dsc_reg_state;
|
|||
struct dcn_optc_reg_state;
|
||||
struct dcn_dccg_reg_state;
|
||||
|
||||
#define DC_VER "3.2.372"
|
||||
#define DC_VER "3.2.373"
|
||||
|
||||
/**
|
||||
* MAX_SURFACES - representative of the upper bound of surfaces that can be piped to a single CRTC
|
||||
|
|
@ -1404,15 +1404,50 @@ struct lut_mem_mapping {
|
|||
struct dc_rmcm_3dlut {
|
||||
bool isInUse;
|
||||
const struct dc_stream_state *stream;
|
||||
uint8_t protection_bits;
|
||||
};
|
||||
|
||||
struct dc_3dlut {
|
||||
struct kref refcount;
|
||||
struct tetrahedral_params lut_3d;
|
||||
struct fixed31_32 hdr_multiplier;
|
||||
union dc_3dlut_state state;
|
||||
};
|
||||
|
||||
/* 3DLUT DMA (Fast Load) params */
|
||||
struct dc_3dlut_dma {
|
||||
struct dc_plane_address addr;
|
||||
enum dc_cm_lut_swizzle swizzle;
|
||||
enum dc_cm_lut_pixel_format format;
|
||||
uint16_t bias; /* FP1.5.10 */
|
||||
uint16_t scale; /* FP1.5.10 */
|
||||
enum dc_cm_lut_size size;
|
||||
};
|
||||
|
||||
/* color manager */
|
||||
union dc_plane_cm_flags {
|
||||
unsigned int all;
|
||||
struct {
|
||||
unsigned int shaper_enable : 1;
|
||||
unsigned int lut3d_enable : 1;
|
||||
unsigned int blend_enable : 1;
|
||||
/* whether legacy (lut3d_func) or DMA is valid */
|
||||
unsigned int lut3d_dma_enable : 1;
|
||||
/* RMCM lut to be used instead of MCM */
|
||||
unsigned int rmcm_enable : 1;
|
||||
unsigned int reserved: 27;
|
||||
} bits;
|
||||
};
|
||||
|
||||
struct dc_plane_cm {
|
||||
struct kref refcount;
|
||||
struct dc_transfer_func shaper_func;
|
||||
union {
|
||||
struct dc_3dlut lut3d_func;
|
||||
struct dc_3dlut_dma lut3d_dma;
|
||||
};
|
||||
struct dc_transfer_func blend_func;
|
||||
union dc_plane_cm_flags flags;
|
||||
};
|
||||
|
||||
/*
|
||||
* This structure is filled in by dc_surface_get_status and contains
|
||||
* the last requested address and the currently active address so the called
|
||||
|
|
@ -1490,14 +1525,18 @@ struct dc_plane_state {
|
|||
struct fixed31_32 hdr_mult;
|
||||
struct colorspace_transform gamut_remap_matrix;
|
||||
|
||||
// TODO: No longer used, remove
|
||||
struct dc_hdr_static_metadata hdr_static_ctx;
|
||||
|
||||
enum dc_color_space color_space;
|
||||
|
||||
bool lut_bank_a;
|
||||
struct dc_hdr_static_metadata hdr_static_ctx;
|
||||
struct dc_3dlut lut3d_func;
|
||||
struct dc_transfer_func in_shaper_func;
|
||||
struct dc_transfer_func blend_tf;
|
||||
enum dc_cm2_shaper_3dlut_setting mcm_shaper_3dlut_setting;
|
||||
bool mcm_lut1d_enable;
|
||||
struct dc_cm2_func_luts mcm_luts;
|
||||
enum mpcc_movable_cm_location mcm_location;
|
||||
struct dc_plane_cm cm;
|
||||
|
||||
struct dc_transfer_func *gamcor_tf;
|
||||
enum surface_pixel_format format;
|
||||
|
|
@ -1534,11 +1573,6 @@ struct dc_plane_state {
|
|||
|
||||
bool is_statically_allocated;
|
||||
enum chroma_cositing cositing;
|
||||
enum dc_cm2_shaper_3dlut_setting mcm_shaper_3dlut_setting;
|
||||
bool mcm_lut1d_enable;
|
||||
struct dc_cm2_func_luts mcm_luts;
|
||||
bool lut_bank_a;
|
||||
enum mpcc_movable_cm_location mcm_location;
|
||||
struct dc_csc_transform cursor_csc_color_matrix;
|
||||
bool adaptive_sharpness_en;
|
||||
int adaptive_sharpness_policy;
|
||||
|
|
@ -1884,6 +1918,7 @@ struct dc_surface_update {
|
|||
* change cm2_params.cm2_luts: Fast update
|
||||
*/
|
||||
const struct dc_cm2_parameters *cm2_params;
|
||||
const struct dc_plane_cm *cm;
|
||||
const struct dc_csc_transform *cursor_csc_color_matrix;
|
||||
unsigned int sdr_white_level_nits;
|
||||
struct dc_bias_and_scale bias_and_scale;
|
||||
|
|
@ -1928,6 +1963,10 @@ struct dc_3dlut *dc_create_3dlut_func(void);
|
|||
void dc_3dlut_func_release(struct dc_3dlut *lut);
|
||||
void dc_3dlut_func_retain(struct dc_3dlut *lut);
|
||||
|
||||
struct dc_plane_cm *dc_plane_cm_create(void);
|
||||
void dc_plane_cm_release(struct dc_plane_cm *cm);
|
||||
void dc_plane_cm_retain(struct dc_plane_cm *cm);
|
||||
|
||||
void dc_post_update_surfaces_to_stream(
|
||||
struct dc *dc);
|
||||
|
||||
|
|
|
|||
|
|
@ -102,8 +102,7 @@ struct dc_vbios_funcs {
|
|||
struct bp_external_encoder_control *cntl);
|
||||
enum bp_result (*dac_load_detection)(
|
||||
struct dc_bios *bios,
|
||||
enum engine_id engine_id,
|
||||
struct graphics_object_id ext_enc_id);
|
||||
enum engine_id engine_id);
|
||||
enum bp_result (*transmitter_control)(
|
||||
struct dc_bios *bios,
|
||||
struct bp_transmitter_control *cntl);
|
||||
|
|
|
|||
|
|
@ -1374,7 +1374,7 @@ union dpcd_replay_configuration {
|
|||
unsigned char DESYNC_ERROR_STATUS : 1;
|
||||
unsigned char SINK_DEVICE_REPLAY_STATUS : 3;
|
||||
unsigned char SINK_FRAME_LOCKED : 2;
|
||||
unsigned char RESERVED : 1;
|
||||
unsigned char FRAME_SKIPPING_ERROR_STATUS : 1;
|
||||
} bits;
|
||||
unsigned char raw;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
union dc_plane_status_update_flags {
|
||||
struct {
|
||||
uint32_t address : 1;
|
||||
uint32_t histogram : 1;
|
||||
} bits;
|
||||
uint32_t raw;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ void translate_SPL_in_params_from_pipe_ctx(struct pipe_ctx *pipe_ctx, struct spl
|
|||
spl_in->callbacks = dcn32_spl_callbacks;
|
||||
break;
|
||||
case DCN_VERSION_4_01:
|
||||
case DCN_VERSION_4_2:
|
||||
spl_in->callbacks = dcn401_spl_callbacks;
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@
|
|||
|
||||
#include "amdgpu_dm_trace.h"
|
||||
|
||||
#define TRACE_DC_PIPE_STATE(pipe_ctx, index, max_pipes) \
|
||||
for (index = 0; index < max_pipes; ++index) { \
|
||||
#define TRACE_DC_PIPE_STATE(pipe_ctx, max_pipes) \
|
||||
for (int index = 0; index < max_pipes; ++index) { \
|
||||
struct pipe_ctx *pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[index]; \
|
||||
if (pipe_ctx->plane_state) \
|
||||
trace_amdgpu_dm_dc_pipe_state(pipe_ctx->pipe_idx, pipe_ctx->plane_state, \
|
||||
|
|
|
|||
|
|
@ -1194,6 +1194,8 @@ struct replay_config {
|
|||
union replay_optimization replay_optimization;
|
||||
/* Replay sub feature Frame Skipping is supported */
|
||||
bool frame_skip_supported;
|
||||
/* Replay Received Frame Skipping Error HPD. */
|
||||
bool received_frame_skipping_error_hpd;
|
||||
};
|
||||
|
||||
/* Replay feature flags*/
|
||||
|
|
@ -1481,4 +1483,28 @@ struct dc_validation_dpia_set {
|
|||
uint32_t required_bw;
|
||||
};
|
||||
|
||||
enum dc_cm_lut_swizzle {
|
||||
CM_LUT_3D_SWIZZLE_LINEAR_RGB,
|
||||
CM_LUT_3D_SWIZZLE_LINEAR_BGR,
|
||||
CM_LUT_1D_PACKED_LINEAR
|
||||
};
|
||||
|
||||
enum dc_cm_lut_pixel_format {
|
||||
CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12MSB,
|
||||
CM_LUT_PIXEL_FORMAT_BGRA16161616_UNORM_12MSB,
|
||||
CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12LSB,
|
||||
CM_LUT_PIXEL_FORMAT_BGRA16161616_UNORM_12LSB,
|
||||
CM_LUT_PIXEL_FORMAT_RGBA16161616_FLOAT_FP1_5_10,
|
||||
CM_LUT_PIXEL_FORMAT_BGRA16161616_FLOAT_FP1_5_10
|
||||
};
|
||||
|
||||
enum dc_cm_lut_size {
|
||||
CM_LUT_SIZE_NONE,
|
||||
CM_LUT_SIZE_999,
|
||||
CM_LUT_SIZE_171717,
|
||||
CM_LUT_SIZE_333333,
|
||||
CM_LUT_SIZE_454545,
|
||||
CM_LUT_SIZE_656565,
|
||||
};
|
||||
|
||||
#endif /* DC_TYPES_H_ */
|
||||
|
|
|
|||
|
|
@ -38,7 +38,11 @@
|
|||
DCCG_SRII(PIXEL_RATE_CNTL, OTG, 0),\
|
||||
DCCG_SRII(PIXEL_RATE_CNTL, OTG, 1),\
|
||||
SR(DISPCLK_FREQ_CHANGE_CNTL),\
|
||||
SR(DC_MEM_GLOBAL_PWR_REQ_CNTL)
|
||||
SR(DC_MEM_GLOBAL_PWR_REQ_CNTL),\
|
||||
SR(MICROSECOND_TIME_BASE_DIV),\
|
||||
SR(MILLISECOND_TIME_BASE_DIV),\
|
||||
SR(DCCG_GATE_DISABLE_CNTL),\
|
||||
SR(DCCG_GATE_DISABLE_CNTL2)
|
||||
|
||||
#define DCCG_REG_LIST_DCN2() \
|
||||
DCCG_COMMON_REG_LIST_DCN_BASE(),\
|
||||
|
|
@ -370,7 +374,8 @@
|
|||
type OTG1_DROP_PIXEL;\
|
||||
type OTG2_DROP_PIXEL;\
|
||||
type OTG3_ADD_PIXEL;\
|
||||
type OTG3_DROP_PIXEL;
|
||||
type OTG3_DROP_PIXEL;\
|
||||
type RESYNC_FIFO_LEVEL_ADJUST_EN;
|
||||
|
||||
struct dccg_shift {
|
||||
DCCG_REG_FIELD_LIST(uint8_t)
|
||||
|
|
|
|||
|
|
@ -96,6 +96,25 @@ static void dccg21_update_dpp_dto(struct dccg *dccg, int dpp_inst, int req_dppcl
|
|||
dccg->pipe_dppclk_khz[dpp_inst] = req_dppclk;
|
||||
}
|
||||
|
||||
/*
|
||||
* On DCN21 S0i3 resume, BIOS programs MICROSECOND_TIME_BASE_DIV to
|
||||
* 0x00120464 as a marker that golden init has already been done.
|
||||
* dcn21_s0i3_golden_init_wa() reads this marker later in bios_golden_init()
|
||||
* to decide whether to skip golden init.
|
||||
*
|
||||
* dccg2_init() unconditionally overwrites MICROSECOND_TIME_BASE_DIV to
|
||||
* 0x00120264, destroying the marker before it can be read.
|
||||
*
|
||||
* Guard the call: if the S0i3 marker is present, skip dccg2_init() so the
|
||||
* WA can function correctly. bios_golden_init() will handle init in that case.
|
||||
*/
|
||||
static void dccg21_init(struct dccg *dccg)
|
||||
{
|
||||
if (dccg2_is_s0i3_golden_init_wa_done(dccg))
|
||||
return;
|
||||
|
||||
dccg2_init(dccg);
|
||||
}
|
||||
|
||||
static const struct dccg_funcs dccg21_funcs = {
|
||||
.update_dpp_dto = dccg21_update_dpp_dto,
|
||||
|
|
@ -103,7 +122,7 @@ static const struct dccg_funcs dccg21_funcs = {
|
|||
.set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en,
|
||||
.otg_add_pixel = dccg2_otg_add_pixel,
|
||||
.otg_drop_pixel = dccg2_otg_drop_pixel,
|
||||
.dccg_init = dccg2_init,
|
||||
.dccg_init = dccg21_init,
|
||||
.refclk_setup = dccg2_refclk_setup, /* Deprecated - for backward compatibility only */
|
||||
.allow_clock_gating = dccg2_allow_clock_gating,
|
||||
.enable_memory_low_power = dccg2_enable_memory_low_power,
|
||||
|
|
|
|||
|
|
@ -34,7 +34,13 @@
|
|||
DCCG_SRII(DTO_PARAM, DPPCLK, 1),\
|
||||
DCCG_SRII(DTO_PARAM, DPPCLK, 2),\
|
||||
DCCG_SRII(DTO_PARAM, DPPCLK, 3),\
|
||||
SR(REFCLK_CNTL)
|
||||
SR(REFCLK_CNTL),\
|
||||
SR(DISPCLK_FREQ_CHANGE_CNTL),\
|
||||
SR(DC_MEM_GLOBAL_PWR_REQ_CNTL),\
|
||||
SR(MICROSECOND_TIME_BASE_DIV),\
|
||||
SR(MILLISECOND_TIME_BASE_DIV),\
|
||||
SR(DCCG_GATE_DISABLE_CNTL),\
|
||||
SR(DCCG_GATE_DISABLE_CNTL2)
|
||||
|
||||
#define DCCG_MASK_SH_LIST_DCN301(mask_sh) \
|
||||
DCCG_SFI(DPPCLK_DTO_CTRL, DTO_ENABLE, DPPCLK, 0, mask_sh),\
|
||||
|
|
|
|||
|
|
@ -64,9 +64,12 @@
|
|||
SR(DSCCLK1_DTO_PARAM),\
|
||||
SR(DSCCLK2_DTO_PARAM),\
|
||||
SR(DSCCLK_DTO_CTRL),\
|
||||
SR(DCCG_GATE_DISABLE_CNTL),\
|
||||
SR(DCCG_GATE_DISABLE_CNTL2),\
|
||||
SR(DCCG_GATE_DISABLE_CNTL3),\
|
||||
SR(HDMISTREAMCLK0_DTO_PARAM)
|
||||
SR(HDMISTREAMCLK0_DTO_PARAM),\
|
||||
SR(DC_MEM_GLOBAL_PWR_REQ_CNTL),\
|
||||
SR(MICROSECOND_TIME_BASE_DIV)
|
||||
|
||||
|
||||
#define DCCG_MASK_SH_LIST_DCN31(mask_sh) \
|
||||
|
|
|
|||
|
|
@ -70,11 +70,14 @@
|
|||
SR(DSCCLK2_DTO_PARAM),\
|
||||
SR(DSCCLK3_DTO_PARAM),\
|
||||
SR(DSCCLK_DTO_CTRL),\
|
||||
SR(DCCG_GATE_DISABLE_CNTL),\
|
||||
SR(DCCG_GATE_DISABLE_CNTL2),\
|
||||
SR(DCCG_GATE_DISABLE_CNTL3),\
|
||||
SR(HDMISTREAMCLK0_DTO_PARAM),\
|
||||
SR(OTG_PIXEL_RATE_DIV),\
|
||||
SR(DTBCLK_P_CNTL)
|
||||
SR(DTBCLK_P_CNTL),\
|
||||
SR(DC_MEM_GLOBAL_PWR_REQ_CNTL),\
|
||||
SR(MICROSECOND_TIME_BASE_DIV)
|
||||
|
||||
#define DCCG_MASK_SH_LIST_DCN314_COMMON(mask_sh) \
|
||||
DCCG_SFI(DPPCLK_DTO_CTRL, DTO_DB_EN, DPPCLK, 0, mask_sh),\
|
||||
|
|
|
|||
|
|
@ -827,6 +827,16 @@ void dccg401_enable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint3
|
|||
if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_FE_ROOT_GATE_DISABLE, 1);
|
||||
break;
|
||||
case 4:
|
||||
if (dccg_dcn->dccg_mask->SYMCLKE_FE_ROOT_GATE_DISABLE) {
|
||||
REG_UPDATE_2(SYMCLKE_CLOCK_ENABLE,
|
||||
SYMCLKE_FE_EN, 1,
|
||||
SYMCLKE_FE_SRC_SEL, link_enc_inst);
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_FE_ROOT_GATE_DISABLE, 1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -855,6 +865,16 @@ void dccg401_disable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint
|
|||
SYMCLKD_FE_EN, 0,
|
||||
SYMCLKD_FE_SRC_SEL, 0);
|
||||
break;
|
||||
case 4:
|
||||
if (dccg_dcn->dccg_mask->SYMCLKE_FE_ROOT_GATE_DISABLE) {
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_FE_ROOT_GATE_DISABLE, 0);
|
||||
REG_UPDATE_2(SYMCLKE_CLOCK_ENABLE,
|
||||
SYMCLKE_FE_EN, 0,
|
||||
SYMCLKE_FE_SRC_SEL, 0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -180,6 +180,61 @@ void dccg42_set_physymclk(
|
|||
}
|
||||
}
|
||||
|
||||
void dccg42_set_pixel_rate_div(
|
||||
struct dccg *dccg,
|
||||
uint32_t otg_inst,
|
||||
enum pixel_rate_div tmds_div,
|
||||
enum pixel_rate_div unused)
|
||||
{
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
uint32_t cur_tmds_div = PIXEL_RATE_DIV_NA;
|
||||
uint32_t dp_dto_int;
|
||||
uint32_t reg_val;
|
||||
|
||||
// only 2 and 4 are valid on dcn401
|
||||
if (tmds_div != PIXEL_RATE_DIV_BY_2 && tmds_div != PIXEL_RATE_DIV_BY_4) {
|
||||
return;
|
||||
}
|
||||
|
||||
dccg401_get_pixel_rate_div(dccg, otg_inst, &cur_tmds_div, &dp_dto_int);
|
||||
if (tmds_div == cur_tmds_div)
|
||||
return;
|
||||
|
||||
// encode enum to register value
|
||||
reg_val = tmds_div == PIXEL_RATE_DIV_BY_4 ? 1 : 0;
|
||||
|
||||
switch (otg_inst) {
|
||||
case 0:
|
||||
REG_UPDATE(OTG_PIXEL_RATE_DIV,
|
||||
OTG0_TMDS_PIXEL_RATE_DIV, reg_val);
|
||||
break;
|
||||
case 1:
|
||||
REG_UPDATE(OTG_PIXEL_RATE_DIV,
|
||||
OTG1_TMDS_PIXEL_RATE_DIV, reg_val);
|
||||
break;
|
||||
case 2:
|
||||
REG_UPDATE(OTG_PIXEL_RATE_DIV,
|
||||
OTG2_TMDS_PIXEL_RATE_DIV, reg_val);
|
||||
break;
|
||||
case 3:
|
||||
REG_UPDATE(OTG_PIXEL_RATE_DIV,
|
||||
OTG3_TMDS_PIXEL_RATE_DIV, reg_val);
|
||||
break;
|
||||
default:
|
||||
BREAK_TO_DEBUGGER();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void dccg42_trigger_dio_fifo_resync(struct dccg *dccg)
|
||||
{
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
|
||||
REG_UPDATE(DISPCLK_FREQ_CHANGE_CNTL, RESYNC_FIFO_LEVEL_ADJUST_EN, 1);
|
||||
REG_UPDATE(DISPCLK_FREQ_CHANGE_CNTL, RESYNC_FIFO_LEVEL_ADJUST_EN, 0);
|
||||
REG_WAIT(DISPCLK_FREQ_CHANGE_CNTL, DISPCLK_FREQ_RAMP_DONE, 1, 50, 2000);
|
||||
}
|
||||
|
||||
static void dccg42_init(struct dccg *dccg)
|
||||
{
|
||||
int otg_inst;
|
||||
|
|
@ -240,9 +295,9 @@ static const struct dccg_funcs dccg42_funcs = {
|
|||
.otg_drop_pixel = dccg42_otg_drop_pixel,
|
||||
.disable_dsc = dccg35_disable_dscclk,
|
||||
.enable_dsc = dccg35_enable_dscclk,
|
||||
.set_pixel_rate_div = dccg401_set_pixel_rate_div,
|
||||
.set_pixel_rate_div = dccg42_set_pixel_rate_div,
|
||||
.get_pixel_rate_div = dccg401_get_pixel_rate_div,
|
||||
.trigger_dio_fifo_resync = dccg35_trigger_dio_fifo_resync,
|
||||
.trigger_dio_fifo_resync = dccg42_trigger_dio_fifo_resync,
|
||||
.set_dp_dto = dccg401_set_dp_dto,
|
||||
.enable_symclk_se = dccg35_enable_symclk_se,
|
||||
.disable_symclk_se = dccg35_disable_symclk_se,
|
||||
|
|
|
|||
|
|
@ -238,7 +238,8 @@
|
|||
DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_SRC_SEL, mask_sh),\
|
||||
DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_CLOCK_ENABLE, mask_sh),\
|
||||
DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_FE_EN, mask_sh),\
|
||||
DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_FE_SRC_SEL, mask_sh)
|
||||
DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_FE_SRC_SEL, mask_sh),\
|
||||
DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, RESYNC_FIFO_LEVEL_ADJUST_EN, mask_sh)
|
||||
|
||||
|
||||
void dccg42_otg_add_pixel(struct dccg *dccg,
|
||||
|
|
@ -254,6 +255,14 @@ void dccg42_set_physymclk(
|
|||
enum physymclk_clock_source clk_src,
|
||||
bool force_enable);
|
||||
|
||||
void dccg42_set_pixel_rate_div(
|
||||
struct dccg *dccg,
|
||||
uint32_t otg_inst,
|
||||
enum pixel_rate_div tmds_div,
|
||||
enum pixel_rate_div unused);
|
||||
|
||||
void dccg42_trigger_dio_fifo_resync(struct dccg *dccg);
|
||||
|
||||
struct dccg *dccg42_create(
|
||||
struct dc_context *ctx,
|
||||
const struct dccg_registers *regs,
|
||||
|
|
|
|||
|
|
@ -28,6 +28,14 @@
|
|||
#include "dc_types.h"
|
||||
#include "core_types.h"
|
||||
|
||||
static bool dmub_hw_lock_has_inbox0_lock(const struct dc *dc)
|
||||
{
|
||||
return dc->ctx && dc->ctx->dmub_srv &&
|
||||
dc->hwss.dmub_hw_control_lock &&
|
||||
dc->hwss.dmub_hw_control_lock_fast &&
|
||||
dc->ctx->dmub_srv->dmub->meta_info.feature_bits.bits.inbox0_lock_support;
|
||||
}
|
||||
|
||||
void dmub_hw_lock_mgr_cmd(struct dc_dmub_srv *dmub_srv,
|
||||
bool lock,
|
||||
union dmub_hw_lock_flags *hw_locks,
|
||||
|
|
@ -105,5 +113,13 @@ bool should_use_dmub_inbox1_lock(const struct dc *dc, const struct dc_link *link
|
|||
if (dc->ctx->dce_version >= DCN_VERSION_4_01)
|
||||
return false;
|
||||
|
||||
if (dmub_hw_lock_has_inbox0_lock(dc))
|
||||
return false;
|
||||
|
||||
return dmub_hw_lock_mgr_does_link_require_lock(dc, link);
|
||||
}
|
||||
|
||||
bool should_use_dmub_inbox0_lock_for_link(const struct dc *dc, const struct dc_link *link)
|
||||
{
|
||||
return dmub_hw_lock_has_inbox0_lock(dc) && dmub_hw_lock_mgr_does_link_require_lock(dc, link);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,38 @@ void dmub_hw_lock_mgr_inbox0_cmd(struct dc_dmub_srv *dmub_srv,
|
|||
* Return: true if the inbox1 lock should be used, false otherwise
|
||||
*/
|
||||
bool should_use_dmub_inbox1_lock(const struct dc *dc, const struct dc_link *link);
|
||||
|
||||
/**
|
||||
* dmub_hw_lock_mgr_does_link_require_lock() - Returns true if the link has a feature that needs the HW lock.
|
||||
*
|
||||
* @dc: Pointer to DC object
|
||||
* @link: The link to check
|
||||
*
|
||||
* Return: true if the link has a feature that needs the HW lock, false otherwise
|
||||
*/
|
||||
bool dmub_hw_lock_mgr_does_link_require_lock(const struct dc *dc, const struct dc_link *link);
|
||||
|
||||
/**
|
||||
* dmub_hw_lock_mgr_does_context_require_lock() - Returns true if the context has any stream that needs the HW lock.
|
||||
*
|
||||
* @dc: Pointer to DC object
|
||||
* @context: The context to check
|
||||
*
|
||||
* Return: true if the context has any stream that needs the HW lock, false otherwise
|
||||
*/
|
||||
bool dmub_hw_lock_mgr_does_context_require_lock(const struct dc *dc, const struct dc_state *context);
|
||||
|
||||
/**
|
||||
* should_use_dmub_inbox0_lock_for_link() - Checks if the inbox0 interlock with DMU should be used.
|
||||
*
|
||||
* Is not functionally equivalent to inbox1 as DMUB will not own programming of the relevant locking
|
||||
* registers.
|
||||
*
|
||||
* @dc: pointer to DC object
|
||||
* @link: optional pointer to the link object to check for enabled link features
|
||||
*
|
||||
* Return: true if the inbox0 lock should be used, false otherwise
|
||||
*/
|
||||
bool should_use_dmub_inbox0_lock_for_link(const struct dc *dc, const struct dc_link *link);
|
||||
|
||||
#endif /*_DMUB_HW_LOCK_MGR_H_ */
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.o := $(dml2
|
|||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.o := $(dml2_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.o := $(dml2_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.o := $(dml2_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn42.o := $(dml2_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.o := $(dml2_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn3.o := $(dml2_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.o := $(dml2_ccflags)
|
||||
|
|
@ -107,6 +108,7 @@ CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_top/dml2_top_soc15.o := $(d
|
|||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn42.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn3.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.o := $(dml2_rcflags)
|
||||
|
|
@ -124,6 +126,7 @@ DML21 += src/dml2_core/dml2_core_dcn4_calcs.o
|
|||
DML21 += src/dml2_dpmm/dml2_dpmm_dcn4.o
|
||||
DML21 += src/dml2_dpmm/dml2_dpmm_factory.o
|
||||
DML21 += src/dml2_mcg/dml2_mcg_dcn4.o
|
||||
DML21 += src/dml2_mcg/dml2_mcg_dcn42.o
|
||||
DML21 += src/dml2_mcg/dml2_mcg_factory.o
|
||||
DML21 += src/dml2_pmo/dml2_pmo_dcn3.o
|
||||
DML21 += src/dml2_pmo/dml2_pmo_factory.o
|
||||
|
|
|
|||
|
|
@ -4089,8 +4089,8 @@ static void CalculateSwathAndDETConfiguration(struct display_mode_lib_scratch_st
|
|||
dml_uint_t MaximumSwathHeightC[__DML_NUM_PLANES__];
|
||||
dml_uint_t RoundedUpMaxSwathSizeBytesY[__DML_NUM_PLANES__];
|
||||
dml_uint_t RoundedUpMaxSwathSizeBytesC[__DML_NUM_PLANES__];
|
||||
dml_uint_t RoundedUpSwathSizeBytesY[__DML_NUM_PLANES__];
|
||||
dml_uint_t RoundedUpSwathSizeBytesC[__DML_NUM_PLANES__];
|
||||
dml_uint_t RoundedUpSwathSizeBytesY[__DML_NUM_PLANES__] = { 0 };
|
||||
dml_uint_t RoundedUpSwathSizeBytesC[__DML_NUM_PLANES__] = { 0 };
|
||||
dml_uint_t SwathWidthSingleDPP[__DML_NUM_PLANES__];
|
||||
dml_uint_t SwathWidthSingleDPPChroma[__DML_NUM_PLANES__];
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,9 @@ static enum dml2_project_id dml21_dcn_revision_to_dml2_project_id(enum dce_versi
|
|||
case DCN_VERSION_4_01:
|
||||
project_id = dml2_project_dcn4x_stage2_auto_drr_svp;
|
||||
break;
|
||||
case DCN_VERSION_4_2:
|
||||
project_id = dml2_project_dcn42;
|
||||
break;
|
||||
default:
|
||||
project_id = dml2_project_invalid;
|
||||
DC_ERR("unsupported dcn version for DML21!");
|
||||
|
|
@ -598,29 +601,31 @@ static void populate_dml21_plane_config_from_plane_state(struct dml2_context *dm
|
|||
|
||||
plane->composition.viewport.stationary = false;
|
||||
|
||||
if (plane_state->mcm_luts.lut3d_data.lut3d_src == DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM) {
|
||||
if (plane_state->cm.flags.bits.lut3d_dma_enable) {
|
||||
plane->tdlut.setup_for_tdlut = true;
|
||||
|
||||
switch (plane_state->mcm_luts.lut3d_data.gpu_mem_params.layout) {
|
||||
case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_RGB:
|
||||
case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_BGR:
|
||||
switch (plane_state->cm.lut3d_dma.swizzle) {
|
||||
case CM_LUT_3D_SWIZZLE_LINEAR_RGB:
|
||||
case CM_LUT_3D_SWIZZLE_LINEAR_BGR:
|
||||
plane->tdlut.tdlut_addressing_mode = dml2_tdlut_sw_linear;
|
||||
break;
|
||||
case DC_CM2_GPU_MEM_LAYOUT_1D_PACKED_LINEAR:
|
||||
case CM_LUT_1D_PACKED_LINEAR:
|
||||
default:
|
||||
plane->tdlut.tdlut_addressing_mode = dml2_tdlut_simple_linear;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (plane_state->mcm_luts.lut3d_data.gpu_mem_params.size) {
|
||||
case DC_CM2_GPU_MEM_SIZE_171717:
|
||||
plane->tdlut.tdlut_width_mode = dml2_tdlut_width_17_cube;
|
||||
switch (plane_state->cm.lut3d_dma.size) {
|
||||
case CM_LUT_SIZE_333333:
|
||||
plane->tdlut.tdlut_width_mode = dml2_tdlut_width_33_cube;
|
||||
break;
|
||||
case DC_CM2_GPU_MEM_SIZE_TRANSFORMED:
|
||||
case CM_LUT_SIZE_171717:
|
||||
default:
|
||||
//plane->tdlut.tdlut_width_mode = dml2_tdlut_width_flatten; // dml2_tdlut_width_flatten undefined
|
||||
plane->tdlut.tdlut_width_mode = dml2_tdlut_width_17_cube;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
plane->tdlut.setup_for_tdlut |= dml_ctx->config.force_tdlut_enable;
|
||||
|
||||
plane->dynamic_meta_data.enable = false;
|
||||
|
|
@ -824,6 +829,9 @@ void dml21_copy_clocks_to_dc_state(struct dml2_context *in_ctx, struct dc_state
|
|||
context->bw_ctx.bw.dcn.clk.subvp_prefetch_fclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.svp_prefetch_no_throttle.fclk_khz;
|
||||
context->bw_ctx.bw.dcn.clk.stutter_efficiency.base_efficiency = in_ctx->v21.mode_programming.programming->stutter.base_percent_efficiency;
|
||||
context->bw_ctx.bw.dcn.clk.stutter_efficiency.low_power_efficiency = in_ctx->v21.mode_programming.programming->stutter.low_power_percent_efficiency;
|
||||
context->bw_ctx.bw.dcn.clk.stutter_efficiency.z8_stutter_efficiency = in_ctx->v21.mode_programming.programming->informative.power_management.z8.stutter_efficiency;
|
||||
context->bw_ctx.bw.dcn.clk.stutter_efficiency.z8_stutter_period = in_ctx->v21.mode_programming.programming->informative.power_management.z8.stutter_period;
|
||||
context->bw_ctx.bw.dcn.clk.zstate_support = in_ctx->v21.mode_programming.programming->z8_stutter.supported_in_blank; /*ignore meets_eco since it is not used*/
|
||||
}
|
||||
|
||||
static struct dml2_dchub_watermark_regs *wm_set_index_to_dc_wm_set(union dcn_watermark_set *watermarks, const enum dml2_dchub_watermark_reg_set_index wm_index)
|
||||
|
|
@ -931,3 +939,31 @@ void dml21_set_dc_p_state_type(
|
|||
}
|
||||
}
|
||||
|
||||
void dml21_init_min_clocks_for_dc_state(struct dml2_context *in_ctx, struct dc_state *context)
|
||||
{
|
||||
unsigned int lowest_dpm_state_index = 0;
|
||||
struct dc_clocks *min_clocks = &context->bw_ctx.bw.dcn.clk;
|
||||
|
||||
min_clocks->dispclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.clk_values_khz[lowest_dpm_state_index];
|
||||
min_clocks->dppclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.clk_values_khz[lowest_dpm_state_index];
|
||||
min_clocks->dcfclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dcfclk.clk_values_khz[lowest_dpm_state_index];
|
||||
min_clocks->dramclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.uclk.clk_values_khz[lowest_dpm_state_index];
|
||||
min_clocks->fclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.fclk.clk_values_khz[lowest_dpm_state_index];
|
||||
min_clocks->idle_dramclk_khz = 0;
|
||||
min_clocks->idle_fclk_khz = 0;
|
||||
min_clocks->dcfclk_deep_sleep_khz = 0;
|
||||
min_clocks->fclk_p_state_change_support = true;
|
||||
min_clocks->p_state_change_support = true;
|
||||
min_clocks->dtbclk_en = false;
|
||||
min_clocks->ref_dtbclk_khz = 0;
|
||||
min_clocks->socclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.socclk.clk_values_khz[lowest_dpm_state_index];
|
||||
min_clocks->subvp_prefetch_dramclk_khz = 0;
|
||||
min_clocks->subvp_prefetch_fclk_khz = 0;
|
||||
min_clocks->phyclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.phyclk.clk_values_khz[lowest_dpm_state_index];
|
||||
min_clocks->stutter_efficiency.base_efficiency = 1;
|
||||
min_clocks->stutter_efficiency.low_power_efficiency = 1;
|
||||
min_clocks->stutter_efficiency.z8_stutter_efficiency = 1;
|
||||
min_clocks->stutter_efficiency.z8_stutter_period = 100000;
|
||||
min_clocks->zstate_support = DCN_ZSTATE_SUPPORT_ALLOW;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,4 +25,5 @@ void dml21_map_hw_resources(struct dml2_context *dml_ctx);
|
|||
void dml21_get_pipe_mcache_config(struct dc_state *context, struct pipe_ctx *pipe_ctx, struct dml2_per_plane_programming *pln_prog, struct dml2_pipe_configuration_descriptor *mcache_pipe_config);
|
||||
void dml21_set_dc_p_state_type(struct pipe_ctx *pipe_ctx, struct dml2_per_stream_programming *stream_programming, bool sub_vp_enabled);
|
||||
unsigned int map_plane_to_dml21_display_cfg(const struct dml2_context *dml_ctx, unsigned int stream_id, const struct dc_plane_state *plane, const struct dc_state *context);
|
||||
void dml21_init_min_clocks_for_dc_state(struct dml2_context *in_ctx, struct dc_state *context);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -374,6 +374,7 @@ void dml21_handle_phantom_streams_planes(const struct dc *dc, struct dc_state *c
|
|||
dml2_map_dc_pipes(dml_ctx, context, NULL, &dml_ctx->v21.dml_to_dc_pipe_mapping, dc->current_state);
|
||||
}
|
||||
|
||||
|
||||
static unsigned int dml21_build_fams2_stream_programming_v2(const struct dc *dc,
|
||||
struct dc_state *context,
|
||||
struct dml2_context *dml_ctx)
|
||||
|
|
|
|||
|
|
@ -9,16 +9,21 @@
|
|||
#include "dml21_utils.h"
|
||||
#include "dml21_translation_helper.h"
|
||||
#include "dml2_dc_resource_mgmt.h"
|
||||
#include "dc_fpu.h"
|
||||
|
||||
#if !defined(DC_RUN_WITH_PREEMPTION_ENABLED)
|
||||
#define DC_RUN_WITH_PREEMPTION_ENABLED(code) code
|
||||
#endif // !DC_RUN_WITH_PREEMPTION_ENABLED
|
||||
|
||||
#define INVALID -1
|
||||
|
||||
static bool dml21_allocate_memory(struct dml2_context **dml_ctx)
|
||||
{
|
||||
*dml_ctx = vzalloc(sizeof(struct dml2_context));
|
||||
DC_RUN_WITH_PREEMPTION_ENABLED(*dml_ctx = vzalloc(sizeof(struct dml2_context)));
|
||||
if (!(*dml_ctx))
|
||||
return false;
|
||||
|
||||
(*dml_ctx)->v21.dml_init.dml2_instance = vzalloc(sizeof(struct dml2_instance));
|
||||
DC_RUN_WITH_PREEMPTION_ENABLED((*dml_ctx)->v21.dml_init.dml2_instance = vzalloc(sizeof(struct dml2_instance)));
|
||||
if (!((*dml_ctx)->v21.dml_init.dml2_instance))
|
||||
return false;
|
||||
|
||||
|
|
@ -28,7 +33,7 @@ static bool dml21_allocate_memory(struct dml2_context **dml_ctx)
|
|||
(*dml_ctx)->v21.mode_support.display_config = &(*dml_ctx)->v21.display_config;
|
||||
(*dml_ctx)->v21.mode_programming.display_config = (*dml_ctx)->v21.mode_support.display_config;
|
||||
|
||||
(*dml_ctx)->v21.mode_programming.programming = vzalloc(sizeof(struct dml2_display_cfg_programming));
|
||||
DC_RUN_WITH_PREEMPTION_ENABLED((*dml_ctx)->v21.mode_programming.programming = vzalloc(sizeof(struct dml2_display_cfg_programming)));
|
||||
if (!((*dml_ctx)->v21.mode_programming.programming))
|
||||
return false;
|
||||
|
||||
|
|
@ -70,8 +75,9 @@ static void dml21_init(const struct dc *in_dc, struct dml2_context *dml_ctx, con
|
|||
bool dml21_create(const struct dc *in_dc, struct dml2_context **dml_ctx, const struct dml2_configuration_options *config)
|
||||
{
|
||||
/* Allocate memory for initializing DML21 instance */
|
||||
if (!dml21_allocate_memory(dml_ctx))
|
||||
if (!dml21_allocate_memory(dml_ctx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dml21_init(in_dc, *dml_ctx, config);
|
||||
|
||||
|
|
@ -215,6 +221,7 @@ static bool dml21_mode_check_and_programming(const struct dc *in_dc, struct dc_s
|
|||
return true;
|
||||
|
||||
if (context->stream_count == 0) {
|
||||
dml21_init_min_clocks_for_dc_state(dml_ctx, context);
|
||||
dml21_build_fams2_programming(in_dc, context, dml_ctx);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,263 @@
|
|||
/* SPDX-License-Identifier: MIT */
|
||||
//
|
||||
// Copyright 2024 Advanced Micro Devices, Inc.
|
||||
|
||||
#ifndef __DML_DML_DCN42_SOC_BB__
|
||||
#define __DML_DML_DCN42_SOC_BB__
|
||||
|
||||
#include "dml_top_soc_parameter_types.h"
|
||||
|
||||
static const struct dml2_soc_qos_parameters dml_dcn42_variant_a_soc_qos_params = {
|
||||
.derate_table = {
|
||||
.system_active_urgent = {
|
||||
.dram_derate_percent_pixel = 65,
|
||||
.dram_derate_percent_vm = 30,
|
||||
.dram_derate_percent_pixel_and_vm = 60,
|
||||
.fclk_derate_percent = 80,
|
||||
.dcfclk_derate_percent = 80,
|
||||
},
|
||||
.system_active_average = {
|
||||
.dram_derate_percent_pixel = 30,
|
||||
.dram_derate_percent_vm = 30,
|
||||
.dram_derate_percent_pixel_and_vm = 30,
|
||||
.fclk_derate_percent = 60,
|
||||
.dcfclk_derate_percent = 60,
|
||||
},
|
||||
.dcn_mall_prefetch_urgent = {
|
||||
.dram_derate_percent_pixel = 65,
|
||||
.dram_derate_percent_vm = 30,
|
||||
.dram_derate_percent_pixel_and_vm = 60,
|
||||
.fclk_derate_percent = 80,
|
||||
.dcfclk_derate_percent = 80,
|
||||
},
|
||||
.dcn_mall_prefetch_average = {
|
||||
.dram_derate_percent_pixel = 30,
|
||||
.dram_derate_percent_vm = 30,
|
||||
.dram_derate_percent_pixel_and_vm = 30,
|
||||
.fclk_derate_percent = 60,
|
||||
.dcfclk_derate_percent = 60,
|
||||
},
|
||||
.system_idle_average = {
|
||||
.dram_derate_percent_pixel = 30,
|
||||
.dram_derate_percent_vm = 30,
|
||||
.dram_derate_percent_pixel_and_vm = 30,
|
||||
.fclk_derate_percent = 60,
|
||||
.dcfclk_derate_percent = 60,
|
||||
},
|
||||
},
|
||||
.writeback = {
|
||||
.base_latency_us = 12,
|
||||
.scaling_factor_us = 0,
|
||||
.scaling_factor_mhz = 0,
|
||||
},
|
||||
.qos_params = {
|
||||
.dcn32x = {
|
||||
.loaded_round_trip_latency_fclk_cycles = 106,
|
||||
.urgent_latency_us = {
|
||||
.base_latency_us = 4,
|
||||
.base_latency_pixel_vm_us = 4,
|
||||
.base_latency_vm_us = 4,
|
||||
.scaling_factor_fclk_us = 0,
|
||||
.scaling_factor_mhz = 0,
|
||||
},
|
||||
.urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096,
|
||||
.urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096,
|
||||
.urgent_out_of_order_return_per_channel_vm_only_bytes = 4096,
|
||||
},
|
||||
},
|
||||
.qos_type = dml2_qos_param_type_dcn3,
|
||||
};
|
||||
|
||||
static const struct dml2_soc_bb dml2_socbb_dcn42 = {
|
||||
.clk_table = {
|
||||
.wck_ratio = {
|
||||
.clk_values_khz = {2},
|
||||
},
|
||||
.uclk = {
|
||||
.clk_values_khz = {400000},
|
||||
.num_clk_values = 1,
|
||||
},
|
||||
.fclk = {
|
||||
.clk_values_khz = {400000},
|
||||
.num_clk_values = 1,
|
||||
},
|
||||
.dcfclk = {
|
||||
.clk_values_khz = {200000},
|
||||
.num_clk_values = 1,
|
||||
},
|
||||
.dispclk = {
|
||||
.clk_values_khz = {1500000},
|
||||
.num_clk_values = 1,
|
||||
},
|
||||
.dppclk = {
|
||||
.clk_values_khz = {1500000},
|
||||
.num_clk_values = 1,
|
||||
},
|
||||
.dtbclk = {
|
||||
.clk_values_khz = {600000},
|
||||
.num_clk_values = 1,
|
||||
},
|
||||
.phyclk = {
|
||||
.clk_values_khz = {810000},
|
||||
.num_clk_values = 1,
|
||||
},
|
||||
.socclk = {
|
||||
.clk_values_khz = {600000},
|
||||
.num_clk_values = 1,
|
||||
},
|
||||
.dscclk = {
|
||||
.clk_values_khz = {500000},
|
||||
.num_clk_values = 1,
|
||||
},
|
||||
.phyclk_d18 = {
|
||||
.clk_values_khz = {667000},
|
||||
.num_clk_values = 1,
|
||||
},
|
||||
.phyclk_d32 = {
|
||||
.clk_values_khz = {625000},
|
||||
.num_clk_values = 1,
|
||||
},
|
||||
.dram_config = {
|
||||
.channel_width_bytes = 4,
|
||||
.channel_count = 4,
|
||||
.alt_clock_bw_conversion = true,
|
||||
},
|
||||
},
|
||||
|
||||
.qos_parameters = {
|
||||
.derate_table = {
|
||||
.system_active_urgent = {
|
||||
.dram_derate_percent_pixel = 65,
|
||||
.dram_derate_percent_vm = 30,
|
||||
.dram_derate_percent_pixel_and_vm = 60,
|
||||
.fclk_derate_percent = 80,
|
||||
.dcfclk_derate_percent = 80,
|
||||
},
|
||||
.system_active_average = {
|
||||
.dram_derate_percent_pixel = 30,
|
||||
.dram_derate_percent_vm = 30,
|
||||
.dram_derate_percent_pixel_and_vm = 30,
|
||||
.fclk_derate_percent = 60,
|
||||
.dcfclk_derate_percent = 60,
|
||||
},
|
||||
.dcn_mall_prefetch_urgent = {
|
||||
.dram_derate_percent_pixel = 65,
|
||||
.dram_derate_percent_vm = 30,
|
||||
.dram_derate_percent_pixel_and_vm = 60,
|
||||
.fclk_derate_percent = 80,
|
||||
.dcfclk_derate_percent = 80,
|
||||
},
|
||||
.dcn_mall_prefetch_average = {
|
||||
.dram_derate_percent_pixel = 30,
|
||||
.dram_derate_percent_vm = 30,
|
||||
.dram_derate_percent_pixel_and_vm = 30,
|
||||
.fclk_derate_percent = 60,
|
||||
.dcfclk_derate_percent = 60,
|
||||
},
|
||||
.system_idle_average = {
|
||||
.dram_derate_percent_pixel = 30,
|
||||
.dram_derate_percent_vm = 30,
|
||||
.dram_derate_percent_pixel_and_vm = 30,
|
||||
.fclk_derate_percent = 60,
|
||||
.dcfclk_derate_percent = 60,
|
||||
},
|
||||
},
|
||||
.writeback = {
|
||||
.base_latency_us = 12,
|
||||
.scaling_factor_us = 0,
|
||||
.scaling_factor_mhz = 0,
|
||||
},
|
||||
.qos_params = {
|
||||
.dcn32x = {
|
||||
.loaded_round_trip_latency_fclk_cycles = 106,
|
||||
.urgent_latency_us = {
|
||||
.base_latency_us = 4,
|
||||
.base_latency_pixel_vm_us = 4,
|
||||
.base_latency_vm_us = 4,
|
||||
.scaling_factor_fclk_us = 0,
|
||||
.scaling_factor_mhz = 0,
|
||||
},
|
||||
.urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096,
|
||||
.urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096,
|
||||
.urgent_out_of_order_return_per_channel_vm_only_bytes = 4096,
|
||||
},
|
||||
},
|
||||
.qos_type = dml2_qos_param_type_dcn3,
|
||||
},
|
||||
|
||||
.power_management_parameters = {
|
||||
.dram_clk_change_blackout_us = 29,
|
||||
.fclk_change_blackout_us = 0,
|
||||
.g7_ppt_blackout_us = 0,
|
||||
.stutter_enter_plus_exit_latency_us = 11,
|
||||
.stutter_exit_latency_us = 9,
|
||||
.z8_stutter_enter_plus_exit_latency_us = 300,
|
||||
.z8_stutter_exit_latency_us = 200,
|
||||
},
|
||||
|
||||
.vmin_limit = {
|
||||
.dispclk_khz = 632 * 1000,
|
||||
},
|
||||
|
||||
.dprefclk_mhz = 600,
|
||||
.xtalclk_mhz = 24,
|
||||
.pcie_refclk_mhz = 100,
|
||||
.dchub_refclk_mhz = 50,
|
||||
.mall_allocated_for_dcn_mbytes = 64,
|
||||
.max_outstanding_reqs = 256,
|
||||
.fabric_datapath_to_dcn_data_return_bytes = 32,
|
||||
.return_bus_width_bytes = 64,
|
||||
.hostvm_min_page_size_kbytes = 4,
|
||||
.gpuvm_min_page_size_kbytes = 256,
|
||||
.gpuvm_max_page_table_levels = 1,
|
||||
.hostvm_max_non_cached_page_table_levels = 2,
|
||||
.phy_downspread_percent = 0.38,
|
||||
.dcn_downspread_percent = 0.38,
|
||||
.dispclk_dppclk_vco_speed_mhz = 3000,
|
||||
.do_urgent_latency_adjustment = 0,
|
||||
.mem_word_bytes = 32,
|
||||
.num_dcc_mcaches = 8,
|
||||
.mcache_size_bytes = 2048,
|
||||
.mcache_line_size_bytes = 32,
|
||||
.max_fclk_for_uclk_dpm_khz = 2200 * 1000,
|
||||
};
|
||||
|
||||
static const struct dml2_ip_capabilities dml2_dcn42_max_ip_caps = {
|
||||
.pipe_count = 4,
|
||||
.otg_count = 4,
|
||||
.num_dsc = 4,
|
||||
.max_num_dp2p0_streams = 4,
|
||||
.max_num_hdmi_frl_outputs = 1,
|
||||
.max_num_dp2p0_outputs = 4,
|
||||
.rob_buffer_size_kbytes = 64,
|
||||
.config_return_buffer_size_in_kbytes = 1792,
|
||||
.config_return_buffer_segment_size_in_kbytes = 64,
|
||||
.meta_fifo_size_in_kentries = 32,
|
||||
.compressed_buffer_segment_size_in_kbytes = 64,
|
||||
.cursor_buffer_size = 24,
|
||||
.max_flip_time_us = 110,
|
||||
.max_flip_time_lines = 50,
|
||||
.hostvm_mode = 0,
|
||||
.subvp_drr_scheduling_margin_us = 100,
|
||||
.subvp_prefetch_end_to_mall_start_us = 15,
|
||||
.subvp_fw_processing_delay = 15,
|
||||
.max_vactive_det_fill_delay_us = 400,
|
||||
|
||||
.fams2 = {
|
||||
.max_allow_delay_us = 100 * 1000,
|
||||
.scheduling_delay_us = 550,
|
||||
.vertical_interrupt_ack_delay_us = 40,
|
||||
.allow_programming_delay_us = 18,
|
||||
.min_allow_width_us = 20,
|
||||
.subvp_df_throttle_delay_us = 100,
|
||||
.subvp_programming_delay_us = 200,
|
||||
.subvp_prefetch_to_mall_delay_us = 18,
|
||||
.drr_programming_delay_us = 35,
|
||||
|
||||
.lock_timeout_us = 5000,
|
||||
.recovery_timeout_us = 5000,
|
||||
.flip_programming_delay_us = 300,
|
||||
},
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -27,6 +27,19 @@ enum dml2_swizzle_mode {
|
|||
dml2_gfx11_sw_256kb_d_x,
|
||||
dml2_gfx11_sw_256kb_r_x,
|
||||
|
||||
dml2_sw_linear_256b, // GFX10 SW_LINEAR only accepts 256 byte aligned pitch
|
||||
dml2_gfx10_sw_64kb_r_x,
|
||||
dml2_gfx102_sw_64kb_s,
|
||||
dml2_gfx102_sw_64kb_s_t,
|
||||
dml2_gfx102_sw_64kb_s_x,
|
||||
dml2_gfx102_sw_64kb_r_x,
|
||||
|
||||
dml2_linear_64elements, // GFX7 LINEAR_ALIGNED accepts pitch alignment of the maximum of 64 elements or 256 bytes
|
||||
dml2_gfx7_1d_thin,
|
||||
dml2_gfx7_2d_thin_gen_zero,
|
||||
dml2_gfx7_2d_thin_gen_one,
|
||||
dml2_gfx7_2d_thin_arlene,
|
||||
dml2_gfx7_2d_thin_anubis
|
||||
};
|
||||
|
||||
enum dml2_source_format_class {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ enum dml2_project_id {
|
|||
dml2_project_dcn4x_stage1,
|
||||
dml2_project_dcn4x_stage2,
|
||||
dml2_project_dcn4x_stage2_auto_drr_svp,
|
||||
dml2_project_dcn40,
|
||||
dml2_project_dcn42,
|
||||
};
|
||||
|
||||
enum dml2_pstate_change_support {
|
||||
|
|
@ -79,6 +81,7 @@ struct dml2_options {
|
|||
struct dml2_pmo_options pmo_options;
|
||||
};
|
||||
|
||||
|
||||
struct dml2_initialize_instance_in_out {
|
||||
struct dml2_instance *dml2_instance;
|
||||
struct dml2_options options;
|
||||
|
|
|
|||
|
|
@ -78,6 +78,86 @@ struct dml2_core_ip_params core_dcn4_ip_caps_base = {
|
|||
.subvp_swath_height_margin_lines = 16,
|
||||
};
|
||||
|
||||
struct dml2_core_ip_params core_dcn42_ip_caps_base = {
|
||||
.vblank_nom_default_us = 668,
|
||||
.remote_iommu_outstanding_translations = 256,
|
||||
.rob_buffer_size_kbytes = 64,
|
||||
.config_return_buffer_size_in_kbytes = 1792,
|
||||
.config_return_buffer_segment_size_in_kbytes = 64,
|
||||
.compressed_buffer_segment_size_in_kbytes = 64,
|
||||
.dpte_buffer_size_in_pte_reqs_luma = 68,
|
||||
.dpte_buffer_size_in_pte_reqs_chroma = 36,
|
||||
.pixel_chunk_size_kbytes = 8,
|
||||
.alpha_pixel_chunk_size_kbytes = 4,
|
||||
.min_pixel_chunk_size_bytes = 1024,
|
||||
.writeback_chunk_size_kbytes = 8,
|
||||
.line_buffer_size_bits = 1171920,
|
||||
.max_line_buffer_lines = 32,
|
||||
.writeback_interface_buffer_size_kbytes = 90,
|
||||
|
||||
//Number of pipes after DCN Pipe harvesting
|
||||
.max_num_dpp = 4,
|
||||
.max_num_otg = 4,
|
||||
.max_num_opp = 4,
|
||||
.max_num_wb = 1,
|
||||
.max_dchub_pscl_bw_pix_per_clk = 4,
|
||||
.max_pscl_lb_bw_pix_per_clk = 2,
|
||||
.max_lb_vscl_bw_pix_per_clk = 4,
|
||||
.max_vscl_hscl_bw_pix_per_clk = 4,
|
||||
.max_hscl_ratio = 6,
|
||||
.max_vscl_ratio = 6,
|
||||
.max_hscl_taps = 8,
|
||||
.max_vscl_taps = 8,
|
||||
.dispclk_ramp_margin_percent = 1,
|
||||
.dppclk_delay_subtotal = 47,
|
||||
.dppclk_delay_scl = 50,
|
||||
.dppclk_delay_scl_lb_only = 16,
|
||||
.dppclk_delay_cnvc_formatter = 28,
|
||||
.dppclk_delay_cnvc_cursor = 6,
|
||||
.cursor_buffer_size = 42,
|
||||
.cursor_chunk_size = 2,
|
||||
.dispclk_delay_subtotal = 125,
|
||||
.max_inter_dcn_tile_repeaters = 8,
|
||||
.writeback_max_hscl_ratio = 1,
|
||||
.writeback_max_vscl_ratio = 1,
|
||||
.writeback_min_hscl_ratio = 1,
|
||||
.writeback_min_vscl_ratio = 1,
|
||||
.writeback_max_hscl_taps = 1,
|
||||
.writeback_max_vscl_taps = 1,
|
||||
.writeback_line_buffer_buffer_size = 0,
|
||||
.num_dsc = 4,
|
||||
.maximum_dsc_bits_per_component = 12,
|
||||
.maximum_pixels_per_line_per_dsc_unit = 5760,
|
||||
.dsc422_native_support = true,
|
||||
.dcc_supported = true,
|
||||
.ptoi_supported = false,
|
||||
|
||||
.cursor_64bpp_support = true,
|
||||
.dynamic_metadata_vm_enabled = false,
|
||||
|
||||
.max_num_hdmi_frl_outputs = 0,
|
||||
.max_num_dp2p0_outputs = 2,
|
||||
.max_num_dp2p0_streams = 4,
|
||||
.imall_supported = 1,
|
||||
.max_flip_time_us = 110,
|
||||
.max_flip_time_lines = 50,
|
||||
.words_per_channel = 16,
|
||||
|
||||
.subvp_fw_processing_delay_us = 15,
|
||||
.subvp_pstate_allow_width_us = 20,
|
||||
.subvp_swath_height_margin_lines = 16,
|
||||
|
||||
.dcn_mrq_present = 1,
|
||||
.zero_size_buffer_entries = 512,
|
||||
.compbuf_reserved_space_zs = 64,
|
||||
.dcc_meta_buffer_size_bytes = 6272,
|
||||
.meta_chunk_size_kbytes = 2,
|
||||
.min_meta_chunk_size_bytes = 256,
|
||||
|
||||
.dchub_arb_to_ret_delay = 102,
|
||||
.hostvm_mode = 1,
|
||||
};
|
||||
|
||||
static void patch_ip_caps_with_explicit_ip_params(struct dml2_ip_capabilities *ip_caps, const struct dml2_core_ip_params *ip_params)
|
||||
{
|
||||
ip_caps->pipe_count = ip_params->max_num_dpp;
|
||||
|
|
@ -153,6 +233,37 @@ bool core_dcn4_initialize(struct dml2_core_initialize_in_out *in_out)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool core_dcn42_initialize(struct dml2_core_initialize_in_out *in_out)
|
||||
{
|
||||
struct dml2_core_instance *core = in_out->instance;
|
||||
|
||||
if (!in_out->minimum_clock_table)
|
||||
return false;
|
||||
else
|
||||
core->minimum_clock_table = in_out->minimum_clock_table;
|
||||
|
||||
if (in_out->explicit_ip_bb && in_out->explicit_ip_bb_size > 0) {
|
||||
memcpy(&core->clean_me_up.mode_lib.ip, in_out->explicit_ip_bb, in_out->explicit_ip_bb_size);
|
||||
|
||||
// FIXME_STAGE2:
|
||||
// DV still uses stage1 ip_param_st for each variant, need to patch the ip_caps with ip_param info
|
||||
// Should move DV to use ip_caps but need move more overrides to ip_caps
|
||||
patch_ip_caps_with_explicit_ip_params(in_out->ip_caps, in_out->explicit_ip_bb);
|
||||
core->clean_me_up.mode_lib.ip.subvp_pstate_allow_width_us = core_dcn4_ip_caps_base.subvp_pstate_allow_width_us;
|
||||
core->clean_me_up.mode_lib.ip.subvp_fw_processing_delay_us = core_dcn4_ip_caps_base.subvp_pstate_allow_width_us;
|
||||
core->clean_me_up.mode_lib.ip.subvp_swath_height_margin_lines = core_dcn4_ip_caps_base.subvp_swath_height_margin_lines;
|
||||
} else {
|
||||
memcpy(&core->clean_me_up.mode_lib.ip, &core_dcn42_ip_caps_base, sizeof(struct dml2_core_ip_params));
|
||||
patch_ip_params_with_ip_caps(&core->clean_me_up.mode_lib.ip, in_out->ip_caps);
|
||||
core->clean_me_up.mode_lib.ip.imall_supported = false;
|
||||
}
|
||||
|
||||
memcpy(&core->clean_me_up.mode_lib.soc, in_out->soc_bb, sizeof(struct dml2_soc_bb));
|
||||
memcpy(&core->clean_me_up.mode_lib.ip_caps, in_out->ip_caps, sizeof(struct dml2_ip_capabilities));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void create_phantom_stream_from_main_stream(struct dml2_stream_parameters *phantom, const struct dml2_stream_parameters *main,
|
||||
const struct dml2_implicit_svp_meta *meta)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#ifndef __DML2_CORE_DCN4_H__
|
||||
#define __DML2_CORE_DCN4_H__
|
||||
bool core_dcn4_initialize(struct dml2_core_initialize_in_out *in_out);
|
||||
bool core_dcn42_initialize(struct dml2_core_initialize_in_out *in_out);
|
||||
bool core_dcn4_mode_support(struct dml2_core_mode_support_in_out *in_out);
|
||||
bool core_dcn4_mode_programming(struct dml2_core_mode_programming_in_out *in_out);
|
||||
bool core_dcn4_populate_informative(struct dml2_core_populate_informative_in_out *in_out);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ bool dml2_core_create(enum dml2_project_id project_id, struct dml2_core_instance
|
|||
case dml2_project_dcn4x_stage1:
|
||||
result = false;
|
||||
break;
|
||||
case dml2_project_dcn40:
|
||||
case dml2_project_dcn4x_stage2:
|
||||
case dml2_project_dcn4x_stage2_auto_drr_svp:
|
||||
out->initialize = &core_dcn4_initialize;
|
||||
|
|
@ -30,6 +31,14 @@ bool dml2_core_create(enum dml2_project_id project_id, struct dml2_core_instance
|
|||
out->calculate_mcache_allocation = &core_dcn4_calculate_mcache_allocation;
|
||||
result = true;
|
||||
break;
|
||||
case dml2_project_dcn42:
|
||||
out->initialize = &core_dcn42_initialize;
|
||||
out->mode_support = &core_dcn4_mode_support;
|
||||
out->mode_programming = &core_dcn4_mode_programming;
|
||||
out->populate_informative = &core_dcn4_populate_informative;
|
||||
out->calculate_mcache_allocation = &core_dcn4_calculate_mcache_allocation;
|
||||
result = true;
|
||||
break;
|
||||
case dml2_project_invalid:
|
||||
default:
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -428,6 +428,9 @@ bool dml2_core_utils_is_phantom_pipe(const struct dml2_plane_parameters *plane_c
|
|||
|
||||
unsigned int dml2_core_utils_get_tile_block_size_bytes(enum dml2_swizzle_mode sw_mode, unsigned int byte_per_pixel)
|
||||
{
|
||||
if (dml2_core_utils_get_gfx_version(sw_mode) == 10 || dml2_core_utils_get_gfx_version(sw_mode) == 7) {
|
||||
return dml2_core_utils_get_tile_block_size_bytes_backcompat(sw_mode, byte_per_pixel);
|
||||
}
|
||||
|
||||
if (sw_mode == dml2_sw_linear)
|
||||
return 256;
|
||||
|
|
@ -459,14 +462,56 @@ unsigned int dml2_core_utils_get_tile_block_size_bytes(enum dml2_swizzle_mode sw
|
|||
};
|
||||
}
|
||||
|
||||
unsigned int dml2_core_utils_get_tile_block_size_bytes_backcompat(enum dml2_swizzle_mode sw_mode, unsigned int byte_per_pixel)
|
||||
{
|
||||
if (sw_mode == dml2_sw_linear_256b)
|
||||
return 256;
|
||||
else if (sw_mode == dml2_gfx10_sw_64kb_r_x)
|
||||
return 65536;
|
||||
else if (sw_mode == dml2_gfx102_sw_64kb_s)
|
||||
return 65536;
|
||||
else if (sw_mode == dml2_gfx102_sw_64kb_s_t)
|
||||
return 65536;
|
||||
else if (sw_mode == dml2_gfx102_sw_64kb_s_x)
|
||||
return 65536;
|
||||
else if (sw_mode == dml2_gfx102_sw_64kb_r_x)
|
||||
return 65536;
|
||||
else if (sw_mode == dml2_linear_64elements)
|
||||
return 256;
|
||||
else if (sw_mode == dml2_gfx7_1d_thin)
|
||||
return 256;
|
||||
else if (sw_mode == dml2_gfx7_2d_thin_gen_zero)
|
||||
return (128 * 64 * byte_per_pixel);
|
||||
else if (sw_mode == dml2_gfx7_2d_thin_gen_one)
|
||||
return (128 * 128 * byte_per_pixel);
|
||||
else if (sw_mode == dml2_gfx7_2d_thin_arlene)
|
||||
return (64 * 32 * byte_per_pixel);
|
||||
else if (sw_mode == dml2_gfx7_2d_thin_anubis)
|
||||
return (128 * 128 * byte_per_pixel);
|
||||
else {
|
||||
DML_ASSERT(0);
|
||||
return 256;
|
||||
};
|
||||
}
|
||||
|
||||
bool dml2_core_utils_get_segment_horizontal_contiguous(enum dml2_swizzle_mode sw_mode, unsigned int byte_per_pixel)
|
||||
{
|
||||
return (byte_per_pixel != 2);
|
||||
if (dml2_core_utils_get_gfx_version(sw_mode) == 10 || dml2_core_utils_get_gfx_version(sw_mode) == 7) {
|
||||
return dml2_core_utils_get_segment_horizontal_contiguous_backcompat(sw_mode, byte_per_pixel);
|
||||
} else {
|
||||
return (byte_per_pixel != 2);
|
||||
}
|
||||
}
|
||||
|
||||
bool dml2_core_utils_get_segment_horizontal_contiguous_backcompat(enum dml2_swizzle_mode sw_mode, unsigned int byte_per_pixel)
|
||||
{
|
||||
return !((byte_per_pixel == 4) &&
|
||||
((sw_mode == dml2_gfx10_sw_64kb_r_x) || (sw_mode == dml2_gfx102_sw_64kb_s) || (sw_mode == dml2_gfx102_sw_64kb_s_t) || (sw_mode == dml2_gfx102_sw_64kb_s_x)));
|
||||
}
|
||||
|
||||
bool dml2_core_utils_is_linear(enum dml2_swizzle_mode sw_mode)
|
||||
{
|
||||
return sw_mode == dml2_sw_linear;
|
||||
return (sw_mode == dml2_sw_linear || sw_mode == dml2_sw_linear_256b || sw_mode == dml2_linear_64elements);
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -499,6 +544,20 @@ int unsigned dml2_core_utils_get_gfx_version(enum dml2_swizzle_mode sw_mode)
|
|||
sw_mode == dml2_gfx11_sw_256kb_d_x ||
|
||||
sw_mode == dml2_gfx11_sw_256kb_r_x)
|
||||
version = 11;
|
||||
else if (sw_mode == dml2_sw_linear_256b ||
|
||||
sw_mode == dml2_gfx10_sw_64kb_r_x ||
|
||||
sw_mode == dml2_gfx102_sw_64kb_s ||
|
||||
sw_mode == dml2_gfx102_sw_64kb_s_t ||
|
||||
sw_mode == dml2_gfx102_sw_64kb_s_x ||
|
||||
sw_mode == dml2_gfx102_sw_64kb_r_x)
|
||||
version = 10;
|
||||
else if (sw_mode == dml2_linear_64elements ||
|
||||
sw_mode == dml2_gfx7_1d_thin ||
|
||||
sw_mode == dml2_gfx7_2d_thin_gen_zero ||
|
||||
sw_mode == dml2_gfx7_2d_thin_gen_one ||
|
||||
sw_mode == dml2_gfx7_2d_thin_arlene ||
|
||||
sw_mode == dml2_gfx7_2d_thin_anubis)
|
||||
version = 7;
|
||||
else {
|
||||
DML_LOG_VERBOSE("ERROR: Invalid sw_mode setting! val=%u\n", sw_mode);
|
||||
DML_ASSERT(0);
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ void dml2_core_utils_pipe_plane_mapping(const struct core_display_cfg_support_in
|
|||
bool dml2_core_utils_is_phantom_pipe(const struct dml2_plane_parameters *plane_cfg);
|
||||
unsigned int dml2_core_utils_get_tile_block_size_bytes(enum dml2_swizzle_mode sw_mode, unsigned int byte_per_pixel);
|
||||
bool dml2_core_utils_get_segment_horizontal_contiguous(enum dml2_swizzle_mode sw_mode, unsigned int byte_per_pixel);
|
||||
unsigned int dml2_core_utils_get_tile_block_size_bytes_backcompat(enum dml2_swizzle_mode sw_mode, unsigned int byte_per_pixel);
|
||||
bool dml2_core_utils_get_segment_horizontal_contiguous_backcompat(enum dml2_swizzle_mode sw_mode, unsigned int byte_per_pixel);
|
||||
bool dml2_core_utils_is_vertical_rotation(enum dml2_rotation_angle Scan);
|
||||
bool dml2_core_utils_is_linear(enum dml2_swizzle_mode sw_mode);
|
||||
int unsigned dml2_core_utils_get_gfx_version(enum dml2_swizzle_mode sw_mode);
|
||||
|
|
|
|||
|
|
@ -802,3 +802,36 @@ bool dpmm_dcn4_map_watermarks(struct dml2_dpmm_map_watermarks_params_in_out *in_
|
|||
|
||||
return true;
|
||||
}
|
||||
bool dpmm_dcn42_map_watermarks(struct dml2_dpmm_map_watermarks_params_in_out *in_out)
|
||||
{
|
||||
const struct dml2_display_cfg *display_cfg = &in_out->display_cfg->display_config;
|
||||
const struct dml2_core_internal_display_mode_lib *mode_lib = &in_out->core->clean_me_up.mode_lib;
|
||||
struct dml2_dchub_global_register_set *dchubbub_regs = &in_out->programming->global_regs;
|
||||
|
||||
double refclk_freq_in_mhz = (display_cfg->overrides.hw.dlg_ref_clk_mhz > 0) ? (double)display_cfg->overrides.hw.dlg_ref_clk_mhz : mode_lib->soc.dchub_refclk_mhz;
|
||||
|
||||
/* set A */
|
||||
dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].fclk_pstate = (int unsigned)(mode_lib->mp.Watermark.FCLKChangeWatermark * refclk_freq_in_mhz);
|
||||
dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].sr_enter = (int unsigned)(mode_lib->mp.Watermark.StutterEnterPlusExitWatermark * refclk_freq_in_mhz);
|
||||
dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].sr_exit = (int unsigned)(mode_lib->mp.Watermark.StutterExitWatermark * refclk_freq_in_mhz);
|
||||
dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].sr_enter_z8 = (int unsigned)(mode_lib->mp.Watermark.Z8StutterEnterPlusExitWatermark * refclk_freq_in_mhz);
|
||||
dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].sr_exit_z8 = (int unsigned)(mode_lib->mp.Watermark.Z8StutterExitWatermark * refclk_freq_in_mhz);
|
||||
dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].temp_read_or_ppt = (int unsigned)(mode_lib->mp.Watermark.temp_read_or_ppt_watermark_us * refclk_freq_in_mhz);
|
||||
dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].uclk_pstate = (int unsigned)(mode_lib->mp.Watermark.DRAMClockChangeWatermark * refclk_freq_in_mhz);
|
||||
dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].urgent = (int unsigned)(mode_lib->mp.Watermark.UrgentWatermark * refclk_freq_in_mhz);
|
||||
dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].usr = (int unsigned)(mode_lib->mp.Watermark.USRRetrainingWatermark * refclk_freq_in_mhz);
|
||||
dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].refcyc_per_trip_to_mem = (unsigned int)(mode_lib->mp.Watermark.UrgentWatermark * refclk_freq_in_mhz);
|
||||
dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].refcyc_per_meta_trip_to_mem = (unsigned int)(mode_lib->mp.Watermark.UrgentWatermark * refclk_freq_in_mhz);
|
||||
dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].frac_urg_bw_flip = (unsigned int)(mode_lib->mp.FractionOfUrgentBandwidthImmediateFlip * 1000);
|
||||
dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].frac_urg_bw_nom = (unsigned int)(mode_lib->mp.FractionOfUrgentBandwidth * 1000);
|
||||
dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].frac_urg_bw_mall = (unsigned int)(mode_lib->mp.FractionOfUrgentBandwidthMALL * 1000);
|
||||
|
||||
/* set B */
|
||||
dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_B] = dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A];
|
||||
dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_C] = dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A];
|
||||
dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_D] = dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A];
|
||||
|
||||
dchubbub_regs->num_watermark_sets = 4;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,5 +10,6 @@
|
|||
bool dpmm_dcn3_map_mode_to_soc_dpm(struct dml2_dpmm_map_mode_to_soc_dpm_params_in_out *in_out);
|
||||
bool dpmm_dcn4_map_mode_to_soc_dpm(struct dml2_dpmm_map_mode_to_soc_dpm_params_in_out *in_out);
|
||||
bool dpmm_dcn4_map_watermarks(struct dml2_dpmm_map_watermarks_params_in_out *in_out);
|
||||
bool dpmm_dcn42_map_watermarks(struct dml2_dpmm_map_watermarks_params_in_out *in_out);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ bool dml2_dpmm_create(enum dml2_project_id project_id, struct dml2_dpmm_instance
|
|||
out->map_watermarks = &dummy_map_watermarks;
|
||||
result = true;
|
||||
break;
|
||||
case dml2_project_dcn40:
|
||||
case dml2_project_dcn4x_stage2:
|
||||
out->map_mode_to_soc_dpm = &dpmm_dcn3_map_mode_to_soc_dpm;
|
||||
out->map_watermarks = &dummy_map_watermarks;
|
||||
|
|
@ -41,6 +42,11 @@ bool dml2_dpmm_create(enum dml2_project_id project_id, struct dml2_dpmm_instance
|
|||
out->map_watermarks = &dpmm_dcn4_map_watermarks;
|
||||
result = true;
|
||||
break;
|
||||
case dml2_project_dcn42:
|
||||
out->map_mode_to_soc_dpm = &dpmm_dcn4_map_mode_to_soc_dpm;
|
||||
out->map_watermarks = &dpmm_dcn42_map_watermarks;
|
||||
result = true;
|
||||
break;
|
||||
case dml2_project_invalid:
|
||||
default:
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -10,4 +10,4 @@
|
|||
bool mcg_dcn4_build_min_clock_table(struct dml2_mcg_build_min_clock_table_params_in_out *in_out);
|
||||
bool mcg_dcn4_unit_test(void);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,76 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Copyright 2026 Advanced Micro Devices, Inc.
|
||||
|
||||
#include "dml2_mcg_dcn42.h"
|
||||
#include "dml_top_soc_parameter_types.h"
|
||||
|
||||
static unsigned long long uclk_to_dram_bw_kbps(unsigned long uclk_khz, const struct dml2_dram_params *dram_config, unsigned long wck_ratio)
|
||||
{
|
||||
unsigned long long bw_kbps = 0;
|
||||
|
||||
bw_kbps = (unsigned long long) uclk_khz * dram_config->channel_count * dram_config->channel_width_bytes * wck_ratio * 2;
|
||||
return bw_kbps;
|
||||
}
|
||||
|
||||
static bool build_min_clk_table_coarse_grained(const struct dml2_soc_bb *soc_bb, struct dml2_mcg_min_clock_table *min_table)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < soc_bb->clk_table.fclk.num_clk_values; i++) {
|
||||
if (i < soc_bb->clk_table.uclk.num_clk_values) {
|
||||
min_table->dram_bw_table.entries[i].pre_derate_dram_bw_kbps =
|
||||
uclk_to_dram_bw_kbps(soc_bb->clk_table.uclk.clk_values_khz[i], &soc_bb->clk_table.dram_config, soc_bb->clk_table.wck_ratio.clk_values_khz[i]);
|
||||
min_table->dram_bw_table.entries[i].min_uclk_khz = soc_bb->clk_table.uclk.clk_values_khz[i];
|
||||
} else {
|
||||
min_table->dram_bw_table.entries[i].pre_derate_dram_bw_kbps = min_table->dram_bw_table.entries[soc_bb->clk_table.uclk.num_clk_values - 1].pre_derate_dram_bw_kbps;
|
||||
min_table->dram_bw_table.entries[i].min_uclk_khz = soc_bb->clk_table.uclk.clk_values_khz[soc_bb->clk_table.uclk.num_clk_values - 1];
|
||||
}
|
||||
|
||||
min_table->dram_bw_table.entries[i].min_dcfclk_khz = soc_bb->clk_table.dcfclk.clk_values_khz[i];
|
||||
min_table->dram_bw_table.entries[i].min_fclk_khz = soc_bb->clk_table.fclk.clk_values_khz[i];
|
||||
}
|
||||
min_table->dram_bw_table.num_entries = soc_bb->clk_table.fclk.num_clk_values;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool build_min_clock_table(const struct dml2_soc_bb *soc_bb, struct dml2_mcg_min_clock_table *min_table)
|
||||
{
|
||||
bool result;
|
||||
|
||||
if (!soc_bb || !min_table)
|
||||
return false;
|
||||
|
||||
|
||||
if (soc_bb->clk_table.uclk.num_clk_values > DML_MCG_MAX_CLK_TABLE_SIZE)
|
||||
return false;
|
||||
|
||||
min_table->fixed_clocks_khz.amclk = 0;
|
||||
min_table->fixed_clocks_khz.dprefclk = soc_bb->dprefclk_mhz * 1000;
|
||||
min_table->fixed_clocks_khz.pcierefclk = soc_bb->pcie_refclk_mhz * 1000;
|
||||
min_table->fixed_clocks_khz.dchubrefclk = soc_bb->dchub_refclk_mhz * 1000;
|
||||
min_table->fixed_clocks_khz.xtalclk = soc_bb->xtalclk_mhz * 1000;
|
||||
|
||||
min_table->max_clocks_khz.dispclk = soc_bb->clk_table.dispclk.clk_values_khz[soc_bb->clk_table.dispclk.num_clk_values - 1];
|
||||
min_table->max_clocks_khz.dppclk = soc_bb->clk_table.dppclk.clk_values_khz[soc_bb->clk_table.dppclk.num_clk_values - 1];
|
||||
min_table->max_clocks_khz.dscclk = soc_bb->clk_table.dscclk.clk_values_khz[soc_bb->clk_table.dscclk.num_clk_values - 1];
|
||||
min_table->max_clocks_khz.dtbclk = soc_bb->clk_table.dtbclk.clk_values_khz[soc_bb->clk_table.dtbclk.num_clk_values - 1];
|
||||
min_table->max_clocks_khz.phyclk = soc_bb->clk_table.phyclk.clk_values_khz[soc_bb->clk_table.phyclk.num_clk_values - 1];
|
||||
|
||||
min_table->max_ss_clocks_khz.dispclk = (unsigned int)((double)min_table->max_clocks_khz.dispclk / (1.0 + soc_bb->dcn_downspread_percent / 100.0));
|
||||
min_table->max_ss_clocks_khz.dppclk = (unsigned int)((double)min_table->max_clocks_khz.dppclk / (1.0 + soc_bb->dcn_downspread_percent / 100.0));
|
||||
min_table->max_ss_clocks_khz.dtbclk = (unsigned int)((double)min_table->max_clocks_khz.dtbclk / (1.0 + soc_bb->dcn_downspread_percent / 100.0));
|
||||
|
||||
min_table->max_clocks_khz.dcfclk = soc_bb->clk_table.dcfclk.clk_values_khz[soc_bb->clk_table.dcfclk.num_clk_values - 1];
|
||||
min_table->max_clocks_khz.fclk = soc_bb->clk_table.fclk.clk_values_khz[soc_bb->clk_table.fclk.num_clk_values - 1];
|
||||
|
||||
result = build_min_clk_table_coarse_grained(soc_bb, min_table);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool mcg_dcn42_build_min_clock_table(struct dml2_mcg_build_min_clock_table_params_in_out *in_out)
|
||||
{
|
||||
return build_min_clock_table(in_out->soc_bb, in_out->min_clk_table);
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
/* SPDX-License-Identifier: MIT */
|
||||
//
|
||||
// Copyright 2026 Advanced Micro Devices, Inc.
|
||||
|
||||
#ifndef __DML2_MCG_DCN42_H__
|
||||
#define __DML2_MCG_DCN42_H__
|
||||
|
||||
#include "dml2_internal_shared_types.h"
|
||||
|
||||
bool mcg_dcn42_build_min_clock_table(struct dml2_mcg_build_min_clock_table_params_in_out *in_out);
|
||||
|
||||
#endif
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "dml2_mcg_factory.h"
|
||||
#include "dml2_mcg_dcn4.h"
|
||||
#include "dml2_mcg_dcn42.h"
|
||||
#include "dml2_external_lib_deps.h"
|
||||
|
||||
static bool dummy_build_min_clock_table(struct dml2_mcg_build_min_clock_table_params_in_out *in_out)
|
||||
|
|
@ -25,11 +26,16 @@ bool dml2_mcg_create(enum dml2_project_id project_id, struct dml2_mcg_instance *
|
|||
out->build_min_clock_table = &dummy_build_min_clock_table;
|
||||
result = true;
|
||||
break;
|
||||
case dml2_project_dcn40:
|
||||
case dml2_project_dcn4x_stage2:
|
||||
case dml2_project_dcn4x_stage2_auto_drr_svp:
|
||||
out->build_min_clock_table = &mcg_dcn4_build_min_clock_table;
|
||||
result = true;
|
||||
break;
|
||||
case dml2_project_dcn42:
|
||||
out->build_min_clock_table = &mcg_dcn42_build_min_clock_table;
|
||||
result = true;
|
||||
break;
|
||||
case dml2_project_invalid:
|
||||
default:
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ static const struct dml2_pmo_pstate_strategy base_strategy_list_1_display[] = {
|
|||
.allow_state_increase = true,
|
||||
},
|
||||
|
||||
|
||||
// Then VBlank
|
||||
{
|
||||
.per_stream_pstate_method = { dml2_pstate_method_vblank, dml2_pstate_method_na, dml2_pstate_method_na, dml2_pstate_method_na },
|
||||
|
|
@ -53,6 +54,7 @@ static const struct dml2_pmo_pstate_strategy base_strategy_list_2_display[] = {
|
|||
.allow_state_increase = true,
|
||||
},
|
||||
|
||||
|
||||
// Then VActive + VBlank
|
||||
{
|
||||
.per_stream_pstate_method = { dml2_pstate_method_vactive, dml2_pstate_method_vblank, dml2_pstate_method_na, dml2_pstate_method_na },
|
||||
|
|
@ -113,6 +115,7 @@ static const struct dml2_pmo_pstate_strategy base_strategy_list_3_display[] = {
|
|||
.allow_state_increase = true,
|
||||
},
|
||||
|
||||
|
||||
// VActive + 1 VBlank
|
||||
{
|
||||
.per_stream_pstate_method = { dml2_pstate_method_vactive, dml2_pstate_method_vactive, dml2_pstate_method_vblank, dml2_pstate_method_na },
|
||||
|
|
@ -149,6 +152,7 @@ static const struct dml2_pmo_pstate_strategy base_strategy_list_4_display[] = {
|
|||
.allow_state_increase = true,
|
||||
},
|
||||
|
||||
|
||||
// VActive + 1 VBlank
|
||||
{
|
||||
.per_stream_pstate_method = { dml2_pstate_method_vactive, dml2_pstate_method_vactive, dml2_pstate_method_vactive, dml2_pstate_method_vblank },
|
||||
|
|
@ -1651,6 +1655,7 @@ static bool validate_pstate_support_strategy_cofunctionality(struct dml2_pmo_ins
|
|||
if (svp_count > 0 && (pmo->options->disable_svp || !all_timings_support_svp(pmo, display_cfg, svp_stream_mask)))
|
||||
return false;
|
||||
|
||||
|
||||
return is_config_schedulable(pmo, display_cfg, pstate_strategy);
|
||||
}
|
||||
|
||||
|
|
@ -1980,6 +1985,7 @@ static void reset_display_configuration(struct display_configuation_with_meta *d
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static void setup_planes_for_drr_by_mask(struct display_configuation_with_meta *display_config,
|
||||
struct dml2_pmo_instance *pmo,
|
||||
int plane_mask)
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
// Copyright 2024 Advanced Micro Devices, Inc.
|
||||
|
||||
#include "dml2_pmo_factory.h"
|
||||
#include "dml2_pmo_dcn4_fams2.h"
|
||||
#include "dml2_pmo_dcn3.h"
|
||||
#include "dml2_pmo_dcn4_fams2.h"
|
||||
#include "dml2_external_lib_deps.h"
|
||||
|
||||
static bool dummy_init_for_stutter(struct dml2_pmo_init_for_stutter_in_out *in_out)
|
||||
|
|
@ -37,6 +37,7 @@ bool dml2_pmo_create(enum dml2_project_id project_id, struct dml2_pmo_instance *
|
|||
out->optimize_dcc_mcache = pmo_dcn4_fams2_optimize_dcc_mcache;
|
||||
result = true;
|
||||
break;
|
||||
case dml2_project_dcn40:
|
||||
case dml2_project_dcn4x_stage2:
|
||||
out->initialize = pmo_dcn3_initialize;
|
||||
|
||||
|
|
@ -56,6 +57,7 @@ bool dml2_pmo_create(enum dml2_project_id project_id, struct dml2_pmo_instance *
|
|||
|
||||
result = true;
|
||||
break;
|
||||
case dml2_project_dcn42:
|
||||
case dml2_project_dcn4x_stage2_auto_drr_svp:
|
||||
out->initialize = pmo_dcn4_fams2_initialize;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,4 +10,4 @@
|
|||
|
||||
bool dml2_pmo_create(enum dml2_project_id project_id, struct dml2_pmo_instance *out);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ bool dml2_initialize_instance(struct dml2_initialize_instance_in_out *in_out)
|
|||
case dml2_project_dcn4x_stage1:
|
||||
case dml2_project_dcn4x_stage2:
|
||||
case dml2_project_dcn4x_stage2_auto_drr_svp:
|
||||
case dml2_project_dcn40:
|
||||
case dml2_project_dcn42:
|
||||
return dml2_top_soc15_initialize_instance(in_out);
|
||||
case dml2_project_invalid:
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
// Copyright 2024 Advanced Micro Devices, Inc.
|
||||
|
||||
#include "dml2_top_legacy.h"
|
||||
#include "dml2_top_soc15.h"
|
||||
#include "dml2_core_factory.h"
|
||||
#include "dml2_pmo_factory.h"
|
||||
#include "display_mode_core_structs.h"
|
||||
|
|
|
|||
|
|
@ -410,6 +410,7 @@ struct dml2_core_mode_support_in_out {
|
|||
} legacy;
|
||||
};
|
||||
|
||||
|
||||
struct dml2_core_mode_programming_in_out {
|
||||
/*
|
||||
* Inputs
|
||||
|
|
@ -501,6 +502,7 @@ struct dml2_core_instance {
|
|||
bool (*populate_informative)(struct dml2_core_populate_informative_in_out *in_out);
|
||||
bool (*calculate_mcache_allocation)(struct dml2_calculate_mcache_allocation_in_out *in_out);
|
||||
|
||||
|
||||
struct {
|
||||
struct dml2_core_internal_display_mode_lib mode_lib;
|
||||
} clean_me_up;
|
||||
|
|
@ -753,6 +755,7 @@ struct dml2_pmo_instance {
|
|||
bool (*test_for_stutter)(struct dml2_pmo_test_for_stutter_in_out *in_out);
|
||||
bool (*optimize_for_stutter)(struct dml2_pmo_optimize_for_stutter_in_out *in_out);
|
||||
|
||||
|
||||
struct dml2_pmo_init_data init_data;
|
||||
struct dml2_pmo_scratch scratch;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -357,7 +357,7 @@ static bool enough_pipes_for_subvp(struct dml2_context *ctx, struct dc_state *st
|
|||
*/
|
||||
static bool subvp_subvp_schedulable(struct dml2_context *ctx, struct dc_state *context)
|
||||
{
|
||||
struct pipe_ctx *subvp_pipes[2];
|
||||
struct pipe_ctx *subvp_pipes[2] = { NULL, NULL };
|
||||
struct dc_stream_state *phantom = NULL;
|
||||
uint32_t microschedule_lines = 0;
|
||||
uint32_t index = 0;
|
||||
|
|
@ -369,6 +369,9 @@ static bool subvp_subvp_schedulable(struct dml2_context *ctx, struct dc_state *c
|
|||
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||
uint32_t time_us = 0;
|
||||
|
||||
if (pipe == NULL || pipe->stream == NULL)
|
||||
continue;
|
||||
|
||||
/* Loop to calculate the maximum microschedule time between the two SubVP pipes,
|
||||
* and also to store the two main SubVP pipe pointers in subvp_pipes[2].
|
||||
*/
|
||||
|
|
@ -386,14 +389,19 @@ static bool subvp_subvp_schedulable(struct dml2_context *ctx, struct dc_state *c
|
|||
if (time_us > max_microschedule_us)
|
||||
max_microschedule_us = time_us;
|
||||
|
||||
subvp_pipes[index] = pipe;
|
||||
index++;
|
||||
if (index < 2)
|
||||
subvp_pipes[index++] = pipe;
|
||||
|
||||
// Maximum 2 SubVP pipes
|
||||
if (index == 2)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Minimal guard to avoid C6001 before subvp_pipes[0]/[1] dereference */
|
||||
if (index < 2 || !subvp_pipes[0] || !subvp_pipes[1])
|
||||
return false;
|
||||
|
||||
vactive1_us = ((subvp_pipes[0]->stream->timing.v_addressable * subvp_pipes[0]->stream->timing.h_total) /
|
||||
(double)(subvp_pipes[0]->stream->timing.pix_clk_100hz * 100)) * 1000000;
|
||||
vactive2_us = ((subvp_pipes[1]->stream->timing.v_addressable * subvp_pipes[1]->stream->timing.h_total) /
|
||||
|
|
@ -459,6 +467,11 @@ bool dml2_svp_drr_schedulable(struct dml2_context *ctx, struct dc_state *context
|
|||
break;
|
||||
}
|
||||
|
||||
if (pipe == NULL || pipe->stream == NULL) {
|
||||
// Defensive: should never happen, try to catch in debug
|
||||
ASSERT(0);
|
||||
return false;
|
||||
}
|
||||
phantom_stream = ctx->config.svp_pstate.callbacks.get_paired_subvp_stream(context, pipe->stream);
|
||||
main_timing = &pipe->stream->timing;
|
||||
phantom_timing = &phantom_stream->timing;
|
||||
|
|
@ -549,6 +562,13 @@ static bool subvp_vblank_schedulable(struct dml2_context *ctx, struct dc_state *
|
|||
if (!subvp_pipe && pipe_mall_type == SUBVP_MAIN)
|
||||
subvp_pipe = pipe;
|
||||
}
|
||||
|
||||
if (subvp_pipe == NULL) {
|
||||
// Defensive: should never happen, catch in debug
|
||||
ASSERT(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Use ignore_msa_timing_param flag to identify as DRR
|
||||
if (found && context->res_ctx.pipe_ctx[vblank_index].stream->ignore_msa_timing_param) {
|
||||
// SUBVP + DRR case
|
||||
|
|
@ -753,6 +773,12 @@ static void enable_phantom_plane(struct dml2_context *ctx,
|
|||
return;
|
||||
}
|
||||
|
||||
/* Minimal NULL guard for C6011 */
|
||||
if (!phantom_plane) {
|
||||
ASSERT(0);
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(&phantom_plane->address, &curr_pipe->plane_state->address, sizeof(phantom_plane->address));
|
||||
memcpy(&phantom_plane->scaling_quality, &curr_pipe->plane_state->scaling_quality,
|
||||
sizeof(phantom_plane->scaling_quality));
|
||||
|
|
@ -880,6 +906,11 @@ bool dml2_svp_add_phantom_pipe_to_dc_state(struct dml2_context *ctx, struct dc_s
|
|||
if (ctx->config.svp_pstate.force_disable_subvp)
|
||||
return false;
|
||||
|
||||
if (!state) {
|
||||
ASSERT(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!all_pipes_have_stream_and_plane(ctx, state))
|
||||
return false;
|
||||
|
||||
|
|
@ -898,6 +929,10 @@ bool dml2_svp_add_phantom_pipe_to_dc_state(struct dml2_context *ctx, struct dc_s
|
|||
}
|
||||
|
||||
if (enough_pipes_for_subvp(ctx, state) && assign_subvp_pipe(ctx, state, &dc_pipe_idx)) {
|
||||
if (state->res_ctx.pipe_ctx[dc_pipe_idx].stream == NULL) {
|
||||
ASSERT(0);
|
||||
return false;
|
||||
}
|
||||
dml_pipe_idx = dml2_helper_find_dml_pipe_idx_by_stream_id(ctx, state->res_ctx.pipe_ctx[dc_pipe_idx].stream->stream_id);
|
||||
svp_height = mode_support_info->SubViewportLinesNeededInMALL[dml_pipe_idx];
|
||||
vstartup = dml_get_vstartup_calculated(&ctx->v20.dml_core_ctx, dml_pipe_idx);
|
||||
|
|
|
|||
|
|
@ -84,8 +84,9 @@ static void dml2_init(const struct dc *in_dc, const struct dml2_configuration_op
|
|||
bool dml2_create(const struct dc *in_dc, const struct dml2_configuration_options *config, struct dml2_context **dml2)
|
||||
{
|
||||
// TODO : Temporarily add DCN_VERSION_3_2 for N-1 validation. Remove DCN_VERSION_3_2 after N-1 validation phase is complete.
|
||||
if ((in_dc->debug.using_dml21) && (in_dc->ctx->dce_version >= DCN_VERSION_4_01))
|
||||
if ((in_dc->debug.using_dml21) && (in_dc->ctx->dce_version >= DCN_VERSION_4_01)) {
|
||||
return dml21_create(in_dc, dml2, config);
|
||||
}
|
||||
|
||||
// Allocate Mode Lib Ctx
|
||||
*dml2 = dml2_allocate_memory();
|
||||
|
|
|
|||
|
|
@ -172,10 +172,14 @@ bool dpp1_get_optimal_number_of_taps(
|
|||
scl_data->taps.h_taps_c = in_taps->h_taps_c;
|
||||
|
||||
if (!dpp->ctx->dc->debug.always_scale) {
|
||||
if (IDENTITY_RATIO(scl_data->ratios.horz))
|
||||
if (IDENTITY_RATIO(scl_data->ratios.horz)) {
|
||||
scl_data->taps.h_taps = 1;
|
||||
if (IDENTITY_RATIO(scl_data->ratios.vert))
|
||||
scl_data->taps.h_taps_c = 1;
|
||||
}
|
||||
if (IDENTITY_RATIO(scl_data->ratios.vert)) {
|
||||
scl_data->taps.v_taps = 1;
|
||||
scl_data->taps.v_taps_c = 1;
|
||||
}
|
||||
if (IDENTITY_RATIO(scl_data->ratios.horz_c))
|
||||
scl_data->taps.h_taps_c = 1;
|
||||
if (IDENTITY_RATIO(scl_data->ratios.vert_c))
|
||||
|
|
|
|||
|
|
@ -524,10 +524,14 @@ bool dpp3_get_optimal_number_of_taps(
|
|||
scl_data->taps.v_taps_c = max_taps_c;
|
||||
|
||||
if (!dpp->ctx->dc->debug.always_scale) {
|
||||
if (IDENTITY_RATIO(scl_data->ratios.horz))
|
||||
if (IDENTITY_RATIO(scl_data->ratios.horz)) {
|
||||
scl_data->taps.h_taps = 1;
|
||||
if (IDENTITY_RATIO(scl_data->ratios.vert))
|
||||
scl_data->taps.h_taps_c = 1;
|
||||
}
|
||||
if (IDENTITY_RATIO(scl_data->ratios.vert)) {
|
||||
scl_data->taps.v_taps = 1;
|
||||
scl_data->taps.v_taps_c = 1;
|
||||
}
|
||||
if (IDENTITY_RATIO(scl_data->ratios.horz_c))
|
||||
scl_data->taps.h_taps_c = 1;
|
||||
if (IDENTITY_RATIO(scl_data->ratios.vert_c))
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user