Merge tag 'amd-drm-next-6.4-2023-03-17' of https://gitlab.freedesktop.org/agd5f/linux into drm-next

amd-drm-next-6.4-2023-03-17:

amdgpu:
- Misc code cleanups
- Documentation fixes
- Make kobj structures const
- Add thermal throttling adjustments for supported APUs
- UMC RAS fixes
- Display reset fixes
- DCN 3.2 fixes
- Freesync fixes
- DC code reorg
- Generalize dmabuf import to work with KFD
- DC DML fixes
- SRIOV fixes
- UVD code cleanups
- IH 4.4.2 updates
- HDP 4.4.2 updates
- SDMA 4.4.2 updates
- PSP 13.0.6 updates
- Add capped/uncapped workload handling for supported APUs
- DCN 3.1.4 updates
- Re-org DC Kconfig
- USB4 fixes
- Reorg DC plane and stream handling
- Register vga_switcheroo for apple-gmux
- SMU 13.0.6 updates
- Fix error checking in read_mm_registers functions for affected families
- VCN 4.0.4 fix
- Drop redundant pci_enable_pcie_error_reporting() call
- RDNA2 SMU OD suspend/resume fix
- Expose additional memory stats via fdinfo
- RAS fixes
- Misc display fixes
- DP MST fixes
- IOMMU regression fix for KFD

amdkfd:
- Make kobj structures const
- Support for exporting buffers via dmabuf
- Multi-VMA page migration fixes
- NBIO fixes
- Misc code cleanups
- Fix possible double free
- Fix possible UAF

radeon:
- iMac fix

UAPI:
- KFD dmabuf export support.  Required for importing KFD buffers into GEM contexts and for RDMA P2P support.
  Proposed user mode changes: https://github.com/fxkamd/ROCT-Thunk-Interface/commits/fxkamd/dmabuf

From: Alex Deucher <alexander.deucher@amd.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230317164416.138340-1-alexander.deucher@amd.com
This commit is contained in:
Dave Airlie 2023-03-20 16:44:36 +10:00
commit 90031bc33f
278 changed files with 16123 additions and 3305 deletions

View File

@ -173,7 +173,7 @@ The alpha blending equation is configured from DRM to DC interface by the
following path:
1. When updating a :c:type:`drm_plane_state <drm_plane_state>`, DM calls
:c:type:`fill_blending_from_plane_state()` that maps
:c:type:`amdgpu_dm_plane_fill_blending_from_plane_state()` that maps
:c:type:`drm_plane_state <drm_plane_state>` attributes to
:c:type:`dc_plane_info <dc_plane_info>` struct to be handled in the
OS-agnostic component (DC).

View File

@ -3,6 +3,7 @@
config DRM_AMDGPU
tristate "AMD GPU"
depends on DRM && PCI && MMU
depends on !UML
select FW_LOADER
select DRM_DISPLAY_DP_HELPER
select DRM_DISPLAY_HDMI_HELPER

View File

@ -54,7 +54,7 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \
amdgpu_ucode.o amdgpu_bo_list.o amdgpu_ctx.o amdgpu_sync.o \
amdgpu_gtt_mgr.o amdgpu_preempt_mgr.o amdgpu_vram_mgr.o amdgpu_virt.o \
amdgpu_atomfirmware.o amdgpu_vf_error.o amdgpu_sched.o \
amdgpu_debugfs.o amdgpu_ids.o amdgpu_gmc.o \
amdgpu_debugfs.o amdgpu_ids.o amdgpu_gmc.o amdgpu_mmhub.o amdgpu_hdp.o \
amdgpu_xgmi.o amdgpu_csa.o amdgpu_ras.o amdgpu_vm_cpu.o \
amdgpu_vm_sdma.o amdgpu_discovery.o amdgpu_ras_eeprom.o amdgpu_nbio.o \
amdgpu_umc.o smu_v11_0_i2c.o amdgpu_fru_eeprom.o amdgpu_rap.o \
@ -148,6 +148,7 @@ amdgpu-y += \
sdma_v3_0.o \
sdma_v4_0.o \
sdma_v4_4.o \
sdma_v4_4_2.o \
sdma_v5_0.o \
sdma_v5_2.o \
sdma_v6_0.o

View File

@ -50,7 +50,6 @@
#include <linux/hashtable.h>
#include <linux/dma-fence.h>
#include <linux/pci.h>
#include <linux/aer.h>
#include <drm/ttm/ttm_bo.h>
#include <drm/ttm/ttm_placement.h>
@ -1005,7 +1004,6 @@ struct amdgpu_device {
bool in_runpm;
bool has_pr3;
bool pm_sysfs_en;
bool ucode_sysfs_en;
bool psp_sysfs_en;
@ -1095,18 +1093,14 @@ void amdgpu_mm_wreg8(struct amdgpu_device *adev, uint32_t offset, uint8_t value)
uint8_t amdgpu_mm_rreg8(struct amdgpu_device *adev, uint32_t offset);
u32 amdgpu_device_indirect_rreg(struct amdgpu_device *adev,
u32 pcie_index, u32 pcie_data,
u32 reg_addr);
u64 amdgpu_device_indirect_rreg64(struct amdgpu_device *adev,
u32 pcie_index, u32 pcie_data,
u32 reg_addr);
void amdgpu_device_indirect_wreg(struct amdgpu_device *adev,
u32 pcie_index, u32 pcie_data,
u32 reg_addr, u32 reg_data);
void amdgpu_device_indirect_wreg64(struct amdgpu_device *adev,
u32 pcie_index, u32 pcie_data,
u32 reg_addr, u64 reg_data);
u32 amdgpu_device_get_rev_id(struct amdgpu_device *adev);
bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type);
bool amdgpu_device_has_dc_support(struct amdgpu_device *adev);

View File

@ -308,6 +308,8 @@ int amdgpu_amdkfd_gpuvm_import_dmabuf(struct amdgpu_device *adev,
uint64_t va, void *drm_priv,
struct kgd_mem **mem, uint64_t *size,
uint64_t *mmap_offset);
int amdgpu_amdkfd_gpuvm_export_dmabuf(struct kgd_mem *mem,
struct dma_buf **dmabuf);
int amdgpu_amdkfd_get_tile_config(struct amdgpu_device *adev,
struct tile_config *config);
void amdgpu_amdkfd_ras_poison_consumption_handler(struct amdgpu_device *adev,

View File

@ -711,6 +711,21 @@ kfd_mem_dmaunmap_attachment(struct kgd_mem *mem,
}
}
static int kfd_mem_export_dmabuf(struct kgd_mem *mem)
{
if (!mem->dmabuf) {
struct dma_buf *ret = amdgpu_gem_prime_export(
&mem->bo->tbo.base,
mem->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_WRITABLE ?
DRM_RDWR : 0);
if (IS_ERR(ret))
return PTR_ERR(ret);
mem->dmabuf = ret;
}
return 0;
}
static int
kfd_mem_attach_dmabuf(struct amdgpu_device *adev, struct kgd_mem *mem,
struct amdgpu_bo **bo)
@ -718,16 +733,9 @@ kfd_mem_attach_dmabuf(struct amdgpu_device *adev, struct kgd_mem *mem,
struct drm_gem_object *gobj;
int ret;
if (!mem->dmabuf) {
mem->dmabuf = amdgpu_gem_prime_export(&mem->bo->tbo.base,
mem->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_WRITABLE ?
DRM_RDWR : 0);
if (IS_ERR(mem->dmabuf)) {
ret = PTR_ERR(mem->dmabuf);
mem->dmabuf = NULL;
return ret;
}
}
ret = kfd_mem_export_dmabuf(mem);
if (ret)
return ret;
gobj = amdgpu_gem_prime_import(adev_to_drm(adev), mem->dmabuf);
if (IS_ERR(gobj))
@ -1575,7 +1583,7 @@ size_t amdgpu_amdkfd_get_available_memory(struct amdgpu_device *adev)
{
uint64_t reserved_for_pt =
ESTIMATE_PT_SIZE(amdgpu_amdkfd_total_mem_size);
size_t available;
ssize_t available;
spin_lock(&kfd_mem_limit.mem_limit_lock);
available = adev->gmc.real_vram_size
@ -1584,6 +1592,9 @@ size_t amdgpu_amdkfd_get_available_memory(struct amdgpu_device *adev)
- reserved_for_pt;
spin_unlock(&kfd_mem_limit.mem_limit_lock);
if (available < 0)
available = 0;
return ALIGN_DOWN(available, VRAM_AVAILABLITY_ALIGN);
}
@ -2210,30 +2221,27 @@ int amdgpu_amdkfd_gpuvm_import_dmabuf(struct amdgpu_device *adev,
struct amdgpu_bo *bo;
int ret;
if (dma_buf->ops != &amdgpu_dmabuf_ops)
/* Can't handle non-graphics buffers */
return -EINVAL;
obj = dma_buf->priv;
if (drm_to_adev(obj->dev) != adev)
/* Can't handle buffers from other devices */
return -EINVAL;
obj = amdgpu_gem_prime_import(adev_to_drm(adev), dma_buf);
if (IS_ERR(obj))
return PTR_ERR(obj);
bo = gem_to_amdgpu_bo(obj);
if (!(bo->preferred_domains & (AMDGPU_GEM_DOMAIN_VRAM |
AMDGPU_GEM_DOMAIN_GTT)))
AMDGPU_GEM_DOMAIN_GTT))) {
/* Only VRAM and GTT BOs are supported */
return -EINVAL;
ret = -EINVAL;
goto err_put_obj;
}
*mem = kzalloc(sizeof(struct kgd_mem), GFP_KERNEL);
if (!*mem)
return -ENOMEM;
if (!*mem) {
ret = -ENOMEM;
goto err_put_obj;
}
ret = drm_vma_node_allow(&obj->vma_node, drm_priv);
if (ret) {
kfree(*mem);
return ret;
}
if (ret)
goto err_free_mem;
if (size)
*size = amdgpu_bo_size(bo);
@ -2250,7 +2258,8 @@ int amdgpu_amdkfd_gpuvm_import_dmabuf(struct amdgpu_device *adev,
| KFD_IOC_ALLOC_MEM_FLAGS_WRITABLE
| KFD_IOC_ALLOC_MEM_FLAGS_EXECUTABLE;
drm_gem_object_get(&bo->tbo.base);
get_dma_buf(dma_buf);
(*mem)->dmabuf = dma_buf;
(*mem)->bo = bo;
(*mem)->va = va;
(*mem)->domain = (bo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM) ?
@ -2262,6 +2271,29 @@ int amdgpu_amdkfd_gpuvm_import_dmabuf(struct amdgpu_device *adev,
(*mem)->is_imported = true;
return 0;
err_free_mem:
kfree(*mem);
err_put_obj:
drm_gem_object_put(obj);
return ret;
}
int amdgpu_amdkfd_gpuvm_export_dmabuf(struct kgd_mem *mem,
struct dma_buf **dma_buf)
{
int ret;
mutex_lock(&mem->lock);
ret = kfd_mem_export_dmabuf(mem);
if (ret)
goto out;
get_dma_buf(mem->dmabuf);
*dma_buf = mem->dmabuf;
out:
mutex_unlock(&mem->lock);
return ret;
}
/* Evict a userptr BO by stopping the queues if necessary

View File

@ -35,6 +35,7 @@
#include <linux/devcoredump.h>
#include <generated/utsrelease.h>
#include <linux/pci-p2pdma.h>
#include <linux/apple-gmux.h>
#include <drm/drm_aperture.h>
#include <drm/drm_atomic_helper.h>
@ -675,20 +676,20 @@ void amdgpu_mm_wdoorbell64(struct amdgpu_device *adev, u32 index, u64 v)
* amdgpu_device_indirect_rreg - read an indirect register
*
* @adev: amdgpu_device pointer
* @pcie_index: mmio register offset
* @pcie_data: mmio register offset
* @reg_addr: indirect register address to read from
*
* Returns the value of indirect register @reg_addr
*/
u32 amdgpu_device_indirect_rreg(struct amdgpu_device *adev,
u32 pcie_index, u32 pcie_data,
u32 reg_addr)
{
unsigned long flags;
u32 r;
unsigned long flags, pcie_index, pcie_data;
void __iomem *pcie_index_offset;
void __iomem *pcie_data_offset;
u32 r;
pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev);
pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev);
spin_lock_irqsave(&adev->pcie_idx_lock, flags);
pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4;
@ -706,20 +707,20 @@ u32 amdgpu_device_indirect_rreg(struct amdgpu_device *adev,
* amdgpu_device_indirect_rreg64 - read a 64bits indirect register
*
* @adev: amdgpu_device pointer
* @pcie_index: mmio register offset
* @pcie_data: mmio register offset
* @reg_addr: indirect register address to read from
*
* Returns the value of indirect register @reg_addr
*/
u64 amdgpu_device_indirect_rreg64(struct amdgpu_device *adev,
u32 pcie_index, u32 pcie_data,
u32 reg_addr)
{
unsigned long flags;
u64 r;
unsigned long flags, pcie_index, pcie_data;
void __iomem *pcie_index_offset;
void __iomem *pcie_data_offset;
u64 r;
pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev);
pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev);
spin_lock_irqsave(&adev->pcie_idx_lock, flags);
pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4;
@ -749,13 +750,15 @@ u64 amdgpu_device_indirect_rreg64(struct amdgpu_device *adev,
*
*/
void amdgpu_device_indirect_wreg(struct amdgpu_device *adev,
u32 pcie_index, u32 pcie_data,
u32 reg_addr, u32 reg_data)
{
unsigned long flags;
unsigned long flags, pcie_index, pcie_data;
void __iomem *pcie_index_offset;
void __iomem *pcie_data_offset;
pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev);
pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev);
spin_lock_irqsave(&adev->pcie_idx_lock, flags);
pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4;
pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4;
@ -778,13 +781,15 @@ void amdgpu_device_indirect_wreg(struct amdgpu_device *adev,
*
*/
void amdgpu_device_indirect_wreg64(struct amdgpu_device *adev,
u32 pcie_index, u32 pcie_data,
u32 reg_addr, u64 reg_data)
{
unsigned long flags;
unsigned long flags, pcie_index, pcie_data;
void __iomem *pcie_index_offset;
void __iomem *pcie_data_offset;
pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev);
pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev);
spin_lock_irqsave(&adev->pcie_idx_lock, flags);
pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4;
pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4;
@ -802,6 +807,18 @@ void amdgpu_device_indirect_wreg64(struct amdgpu_device *adev,
spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
}
/**
* amdgpu_device_get_rev_id - query device rev_id
*
* @adev: amdgpu_device pointer
*
* Return device rev_id
*/
u32 amdgpu_device_get_rev_id(struct amdgpu_device *adev)
{
return adev->nbio.funcs->get_rev_id(adev);
}
/**
* amdgpu_invalid_rreg - dummy reg read function
*
@ -3773,8 +3790,6 @@ int amdgpu_device_init(struct amdgpu_device *adev,
}
}
pci_enable_pcie_error_reporting(adev->pdev);
/* Post card if necessary */
if (amdgpu_device_need_post(adev)) {
if (!adev->bios) {
@ -3864,11 +3879,8 @@ int amdgpu_device_init(struct amdgpu_device *adev,
adev->mm_stats.log2_max_MBps = ilog2(max(1u, max_MBps));
r = amdgpu_pm_sysfs_init(adev);
if (r) {
adev->pm_sysfs_en = false;
DRM_ERROR("registering pm debugfs failed (%d).\n", r);
} else
adev->pm_sysfs_en = true;
if (r)
DRM_ERROR("registering pm sysfs failed (%d).\n", r);
r = amdgpu_ucode_sysfs_init(adev);
if (r) {
@ -3930,12 +3942,15 @@ int amdgpu_device_init(struct amdgpu_device *adev,
if ((adev->pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
vga_client_register(adev->pdev, amdgpu_device_vga_set_decode);
if (amdgpu_device_supports_px(ddev)) {
px = true;
px = amdgpu_device_supports_px(ddev);
if (px || (!pci_is_thunderbolt_attached(adev->pdev) &&
apple_gmux_detect(NULL, NULL)))
vga_switcheroo_register_client(adev->pdev,
&amdgpu_switcheroo_ops, px);
if (px)
vga_switcheroo_init_domain_pm_ops(adev->dev, &adev->vga_pm_domain);
}
if (adev->gmc.xgmi.pending_reset)
queue_delayed_work(system_wq, &mgpu_info.delayed_reset_work,
@ -4011,7 +4026,7 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
if (adev->mman.initialized)
drain_workqueue(adev->mman.bdev.wq);
if (adev->pm_sysfs_en)
if (adev->pm.sysfs_initialized)
amdgpu_pm_sysfs_fini(adev);
if (adev->ucode_sysfs_en)
amdgpu_ucode_sysfs_fini(adev);
@ -4039,6 +4054,7 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
void amdgpu_device_fini_sw(struct amdgpu_device *adev)
{
int idx;
bool px;
amdgpu_fence_driver_sw_fini(adev);
amdgpu_device_ip_fini(adev);
@ -4057,10 +4073,16 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev)
kfree(adev->bios);
adev->bios = NULL;
if (amdgpu_device_supports_px(adev_to_drm(adev))) {
px = amdgpu_device_supports_px(adev_to_drm(adev));
if (px || (!pci_is_thunderbolt_attached(adev->pdev) &&
apple_gmux_detect(NULL, NULL)))
vga_switcheroo_unregister_client(adev->pdev);
if (px)
vga_switcheroo_fini_domain_pm_ops(adev->dev);
}
if ((adev->pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
vga_client_unregister(adev->pdev);
@ -4145,8 +4167,6 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)
if (amdgpu_acpi_smart_shift_update(dev, AMDGPU_SS_DEV_D3))
DRM_WARN("smart shift update failed\n");
drm_kms_helper_poll_disable(dev);
if (fbcon)
drm_fb_helper_set_suspend_unlocked(adev_to_drm(adev)->fb_helper, true);
@ -4243,8 +4263,6 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon)
if (fbcon)
drm_fb_helper_set_suspend_unlocked(adev_to_drm(adev)->fb_helper, false);
drm_kms_helper_poll_enable(dev);
amdgpu_ras_resume(adev);
if (adev->mode_info.num_crtc) {
@ -5582,7 +5600,7 @@ int amdgpu_device_baco_enter(struct drm_device *dev)
struct amdgpu_device *adev = drm_to_adev(dev);
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
if (!amdgpu_device_supports_baco(adev_to_drm(adev)))
if (!amdgpu_device_supports_baco(dev))
return -ENOTSUPP;
if (ras && adev->ras_enabled &&
@ -5598,7 +5616,7 @@ int amdgpu_device_baco_exit(struct drm_device *dev)
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
int ret = 0;
if (!amdgpu_device_supports_baco(adev_to_drm(adev)))
if (!amdgpu_device_supports_baco(dev))
return -ENOTSUPP;
ret = amdgpu_dpm_baco_exit(adev);

View File

@ -41,6 +41,7 @@
#include "vega10_ih.h"
#include "vega20_ih.h"
#include "sdma_v4_0.h"
#include "sdma_v4_4_2.h"
#include "uvd_v7_0.h"
#include "vce_v4_0.h"
#include "vcn_v1_0.h"
@ -711,7 +712,7 @@ static void ip_hw_instance_release(struct kobject *kobj)
kfree(ip_hw_instance);
}
static struct kobj_type ip_hw_instance_ktype = {
static const struct kobj_type ip_hw_instance_ktype = {
.release = ip_hw_instance_release,
.sysfs_ops = &ip_hw_instance_sysfs_ops,
.default_groups = ip_hw_instance_groups,
@ -730,7 +731,7 @@ static void ip_hw_id_release(struct kobject *kobj)
kfree(ip_hw_id);
}
static struct kobj_type ip_hw_id_ktype = {
static const struct kobj_type ip_hw_id_ktype = {
.release = ip_hw_id_release,
.sysfs_ops = &kobj_sysfs_ops,
};
@ -793,18 +794,18 @@ static const struct sysfs_ops ip_die_entry_sysfs_ops = {
.show = ip_die_entry_attr_show,
};
static struct kobj_type ip_die_entry_ktype = {
static const struct kobj_type ip_die_entry_ktype = {
.release = ip_die_entry_release,
.sysfs_ops = &ip_die_entry_sysfs_ops,
.default_groups = ip_die_entry_groups,
};
static struct kobj_type die_kobj_ktype = {
static const struct kobj_type die_kobj_ktype = {
.release = die_kobj_release,
.sysfs_ops = &kobj_sysfs_ops,
};
static struct kobj_type ip_discovery_ktype = {
static const struct kobj_type ip_discovery_ktype = {
.release = ip_disc_release,
.sysfs_ops = &kobj_sysfs_ops,
};
@ -1591,6 +1592,7 @@ static int amdgpu_discovery_set_ih_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(4, 2, 0):
case IP_VERSION(4, 2, 1):
case IP_VERSION(4, 4, 0):
case IP_VERSION(4, 4, 2):
amdgpu_device_ip_block_add(adev, &vega20_ih_ip_block);
break;
case IP_VERSION(5, 0, 0):
@ -1649,6 +1651,7 @@ static int amdgpu_discovery_set_psp_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(13, 0, 2):
case IP_VERSION(13, 0, 3):
case IP_VERSION(13, 0, 5):
case IP_VERSION(13, 0, 6):
case IP_VERSION(13, 0, 7):
case IP_VERSION(13, 0, 8):
case IP_VERSION(13, 0, 10):
@ -1842,6 +1845,9 @@ static int amdgpu_discovery_set_sdma_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(4, 4, 0):
amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
break;
case IP_VERSION(4, 4, 2):
amdgpu_device_ip_block_add(adev, &sdma_v4_4_2_ip_block);
break;
case IP_VERSION(5, 0, 0):
case IP_VERSION(5, 0, 1):
case IP_VERSION(5, 0, 2):
@ -2304,6 +2310,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(4, 2, 0):
case IP_VERSION(4, 2, 1):
case IP_VERSION(4, 4, 0):
case IP_VERSION(4, 4, 2):
adev->hdp.funcs = &hdp_v4_0_funcs;
break;
case IP_VERSION(5, 0, 0):

View File

@ -1618,6 +1618,8 @@ int amdgpu_display_suspend_helper(struct amdgpu_device *adev)
struct drm_connector_list_iter iter;
int r;
drm_kms_helper_poll_disable(dev);
/* turn off display hw */
drm_modeset_lock_all(dev);
drm_connector_list_iter_begin(dev, &iter);
@ -1694,6 +1696,8 @@ int amdgpu_display_resume_helper(struct amdgpu_device *adev)
drm_modeset_unlock_all(dev);
drm_kms_helper_poll_enable(dev);
return 0;
}

View File

@ -60,12 +60,13 @@ void amdgpu_show_fdinfo(struct seq_file *m, struct file *f)
struct amdgpu_fpriv *fpriv = file->driver_priv;
struct amdgpu_vm *vm = &fpriv->vm;
uint64_t vram_mem = 0, gtt_mem = 0, cpu_mem = 0;
struct amdgpu_mem_stats stats;
ktime_t usage[AMDGPU_HW_IP_NUM];
uint32_t bus, dev, fn, domain;
unsigned int hw_ip;
int ret;
memset(&stats, 0, sizeof(stats));
bus = adev->pdev->bus->number;
domain = pci_domain_nr(adev->pdev->bus);
dev = PCI_SLOT(adev->pdev->devfn);
@ -75,7 +76,7 @@ void amdgpu_show_fdinfo(struct seq_file *m, struct file *f)
if (ret)
return;
amdgpu_vm_get_memory(vm, &vram_mem, &gtt_mem, &cpu_mem);
amdgpu_vm_get_memory(vm, &stats);
amdgpu_bo_unreserve(vm->root.bo);
amdgpu_ctx_mgr_usage(&fpriv->ctx_mgr, usage);
@ -90,9 +91,22 @@ void amdgpu_show_fdinfo(struct seq_file *m, struct file *f)
seq_printf(m, "drm-driver:\t%s\n", file->minor->dev->driver->name);
seq_printf(m, "drm-pdev:\t%04x:%02x:%02x.%d\n", domain, bus, dev, fn);
seq_printf(m, "drm-client-id:\t%Lu\n", vm->immediate.fence_context);
seq_printf(m, "drm-memory-vram:\t%llu KiB\n", vram_mem/1024UL);
seq_printf(m, "drm-memory-gtt: \t%llu KiB\n", gtt_mem/1024UL);
seq_printf(m, "drm-memory-cpu: \t%llu KiB\n", cpu_mem/1024UL);
seq_printf(m, "drm-memory-vram:\t%llu KiB\n", stats.vram/1024UL);
seq_printf(m, "drm-memory-gtt: \t%llu KiB\n", stats.gtt/1024UL);
seq_printf(m, "drm-memory-cpu: \t%llu KiB\n", stats.cpu/1024UL);
seq_printf(m, "amd-memory-visible-vram:\t%llu KiB\n",
stats.visible_vram/1024UL);
seq_printf(m, "amd-evicted-vram:\t%llu KiB\n",
stats.evicted_vram/1024UL);
seq_printf(m, "amd-evicted-visible-vram:\t%llu KiB\n",
stats.evicted_visible_vram/1024UL);
seq_printf(m, "amd-requested-vram:\t%llu KiB\n",
stats.requested_vram/1024UL);
seq_printf(m, "amd-requested-visible-vram:\t%llu KiB\n",
stats.requested_visible_vram/1024UL);
seq_printf(m, "amd-requested-gtt:\t%llu KiB\n",
stats.requested_gtt/1024UL);
for (hw_ip = 0; hw_ip < AMDGPU_HW_IP_NUM; ++hw_ip) {
if (!usage[hw_ip])
continue;

View File

@ -725,7 +725,7 @@ int amdgpu_gfx_ras_sw_init(struct amdgpu_device *adev)
/* If not define special ras_late_init function, use gfx default ras_late_init */
if (!ras->ras_block.ras_late_init)
ras->ras_block.ras_late_init = amdgpu_ras_block_late_init;
ras->ras_block.ras_late_init = amdgpu_gfx_ras_late_init;
/* If not defined special ras_cb function, use default ras_cb */
if (!ras->ras_block.ras_cb)

View File

@ -447,13 +447,42 @@ void amdgpu_gmc_filter_faults_remove(struct amdgpu_device *adev, uint64_t addr,
} while (fault->timestamp < tmp);
}
int amdgpu_gmc_ras_early_init(struct amdgpu_device *adev)
int amdgpu_gmc_ras_sw_init(struct amdgpu_device *adev)
{
if (!adev->gmc.xgmi.connected_to_cpu) {
adev->gmc.xgmi.ras = &xgmi_ras;
amdgpu_ras_register_ras_block(adev, &adev->gmc.xgmi.ras->ras_block);
adev->gmc.xgmi.ras_if = &adev->gmc.xgmi.ras->ras_block.ras_comm;
}
int r;
/* umc ras block */
r = amdgpu_umc_ras_sw_init(adev);
if (r)
return r;
/* mmhub ras block */
r = amdgpu_mmhub_ras_sw_init(adev);
if (r)
return r;
/* hdp ras block */
r = amdgpu_hdp_ras_sw_init(adev);
if (r)
return r;
/* mca.x ras block */
r = amdgpu_mca_mp0_ras_sw_init(adev);
if (r)
return r;
r = amdgpu_mca_mp1_ras_sw_init(adev);
if (r)
return r;
r = amdgpu_mca_mpio_ras_sw_init(adev);
if (r)
return r;
/* xgmi ras block */
r = amdgpu_xgmi_ras_sw_init(adev);
if (r)
return r;
return 0;
}

View File

@ -104,6 +104,8 @@ struct amdgpu_vmhub {
uint32_t vm_cntx_cntl_vm_fault;
uint32_t vm_l2_bank_select_reserved_cid2;
uint32_t vm_contexts_disable;
const struct amdgpu_vmhub_funcs *vmhub_funcs;
};
@ -351,7 +353,7 @@ bool amdgpu_gmc_filter_faults(struct amdgpu_device *adev,
uint16_t pasid, uint64_t timestamp);
void amdgpu_gmc_filter_faults_remove(struct amdgpu_device *adev, uint64_t addr,
uint16_t pasid);
int amdgpu_gmc_ras_early_init(struct amdgpu_device *adev);
int amdgpu_gmc_ras_sw_init(struct amdgpu_device *adev);
int amdgpu_gmc_ras_late_init(struct amdgpu_device *adev);
void amdgpu_gmc_ras_fini(struct amdgpu_device *adev);
int amdgpu_gmc_allocate_vm_inv_eng(struct amdgpu_device *adev);

View File

@ -0,0 +1,48 @@
/*
* Copyright 2023 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 "amdgpu.h"
#include "amdgpu_ras.h"
int amdgpu_hdp_ras_sw_init(struct amdgpu_device *adev)
{
int err;
struct amdgpu_hdp_ras *ras;
if (!adev->hdp.ras)
return 0;
ras = adev->hdp.ras;
err = amdgpu_ras_register_ras_block(adev, &ras->ras_block);
if (err) {
dev_err(adev->dev, "Failed to register hdp ras block!\n");
return err;
}
strcpy(ras->ras_block.ras_comm.name, "hdp");
ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__HDP;
ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
adev->hdp.ras_if = &ras->ras_block.ras_comm;
/* hdp ras follows amdgpu_ras_block_late_init_default for late init */
return 0;
}

View File

@ -43,5 +43,5 @@ struct amdgpu_hdp {
struct amdgpu_hdp_ras *ras;
};
int amdgpu_hdp_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *ras_block);
int amdgpu_hdp_ras_sw_init(struct amdgpu_device *adev);
#endif /* __AMDGPU_HDP_H__ */

View File

@ -236,19 +236,28 @@ int amdgpu_jpeg_process_poison_irq(struct amdgpu_device *adev,
return 0;
}
void jpeg_set_ras_funcs(struct amdgpu_device *adev)
int amdgpu_jpeg_ras_sw_init(struct amdgpu_device *adev)
{
int err;
struct amdgpu_jpeg_ras *ras;
if (!adev->jpeg.ras)
return;
return 0;
amdgpu_ras_register_ras_block(adev, &adev->jpeg.ras->ras_block);
ras = adev->jpeg.ras;
err = amdgpu_ras_register_ras_block(adev, &ras->ras_block);
if (err) {
dev_err(adev->dev, "Failed to register jpeg ras block!\n");
return err;
}
strcpy(adev->jpeg.ras->ras_block.ras_comm.name, "jpeg");
adev->jpeg.ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__JPEG;
adev->jpeg.ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__POISON;
adev->jpeg.ras_if = &adev->jpeg.ras->ras_block.ras_comm;
strcpy(ras->ras_block.ras_comm.name, "jpeg");
ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__JPEG;
ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__POISON;
adev->jpeg.ras_if = &ras->ras_block.ras_comm;
/* If don't define special ras_late_init function, use default ras_late_init */
if (!adev->jpeg.ras->ras_block.ras_late_init)
adev->jpeg.ras->ras_block.ras_late_init = amdgpu_ras_block_late_init;
if (!ras->ras_block.ras_late_init)
ras->ras_block.ras_late_init = amdgpu_ras_block_late_init;
return 0;
}

View File

@ -72,6 +72,6 @@ int amdgpu_jpeg_dec_ring_test_ib(struct amdgpu_ring *ring, long timeout);
int amdgpu_jpeg_process_poison_irq(struct amdgpu_device *adev,
struct amdgpu_irq_src *source,
struct amdgpu_iv_entry *entry);
void jpeg_set_ras_funcs(struct amdgpu_device *adev);
int amdgpu_jpeg_ras_sw_init(struct amdgpu_device *adev);
#endif /*__AMDGPU_JPEG_H__*/

View File

@ -70,3 +70,75 @@ void amdgpu_mca_query_ras_error_count(struct amdgpu_device *adev,
amdgpu_mca_reset_error_count(adev, mc_status_addr);
}
int amdgpu_mca_mp0_ras_sw_init(struct amdgpu_device *adev)
{
int err;
struct amdgpu_mca_ras_block *ras;
if (!adev->mca.mp0.ras)
return 0;
ras = adev->mca.mp0.ras;
err = amdgpu_ras_register_ras_block(adev, &ras->ras_block);
if (err) {
dev_err(adev->dev, "Failed to register mca.mp0 ras block!\n");
return err;
}
strcpy(ras->ras_block.ras_comm.name, "mca.mp0");
ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__MCA;
ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
adev->mca.mp0.ras_if = &ras->ras_block.ras_comm;
return 0;
}
int amdgpu_mca_mp1_ras_sw_init(struct amdgpu_device *adev)
{
int err;
struct amdgpu_mca_ras_block *ras;
if (!adev->mca.mp1.ras)
return 0;
ras = adev->mca.mp1.ras;
err = amdgpu_ras_register_ras_block(adev, &ras->ras_block);
if (err) {
dev_err(adev->dev, "Failed to register mca.mp1 ras block!\n");
return err;
}
strcpy(ras->ras_block.ras_comm.name, "mca.mp1");
ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__MCA;
ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
adev->mca.mp1.ras_if = &ras->ras_block.ras_comm;
return 0;
}
int amdgpu_mca_mpio_ras_sw_init(struct amdgpu_device *adev)
{
int err;
struct amdgpu_mca_ras_block *ras;
if (!adev->mca.mpio.ras)
return 0;
ras = adev->mca.mpio.ras;
err = amdgpu_ras_register_ras_block(adev, &ras->ras_block);
if (err) {
dev_err(adev->dev, "Failed to register mca.mpio ras block!\n");
return err;
}
strcpy(ras->ras_block.ras_comm.name, "mca.mpio");
ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__MCA;
ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
adev->mca.mpio.ras_if = &ras->ras_block.ras_comm;
return 0;
}

View File

@ -30,12 +30,7 @@ struct amdgpu_mca_ras {
struct amdgpu_mca_ras_block *ras;
};
struct amdgpu_mca_funcs {
void (*init)(struct amdgpu_device *adev);
};
struct amdgpu_mca {
const struct amdgpu_mca_funcs *funcs;
struct amdgpu_mca_ras mp0;
struct amdgpu_mca_ras mp1;
struct amdgpu_mca_ras mpio;
@ -55,5 +50,7 @@ void amdgpu_mca_reset_error_count(struct amdgpu_device *adev,
void amdgpu_mca_query_ras_error_count(struct amdgpu_device *adev,
uint64_t mc_status_addr,
void *ras_error_status);
int amdgpu_mca_mp0_ras_sw_init(struct amdgpu_device *adev);
int amdgpu_mca_mp1_ras_sw_init(struct amdgpu_device *adev);
int amdgpu_mca_mpio_ras_sw_init(struct amdgpu_device *adev);
#endif

View File

@ -0,0 +1,46 @@
/*
* Copyright (C) 2023 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) 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 "amdgpu.h"
#include "amdgpu_ras.h"
int amdgpu_mmhub_ras_sw_init(struct amdgpu_device *adev)
{
int err;
struct amdgpu_mmhub_ras *ras;
if (!adev->mmhub.ras)
return 0;
ras = adev->mmhub.ras;
err = amdgpu_ras_register_ras_block(adev, &ras->ras_block);
if (err) {
dev_err(adev->dev, "Failed to register mmhub ras block!\n");
return err;
}
strcpy(ras->ras_block.ras_comm.name, "mmhub");
ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__MMHUB;
ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
adev->mmhub.ras_if = &ras->ras_block.ras_comm;
/* mmhub ras follows amdgpu_ras_block_late_init_default for late init */
return 0;
}

View File

@ -48,5 +48,7 @@ struct amdgpu_mmhub {
struct amdgpu_mmhub_ras *ras;
};
int amdgpu_mmhub_ras_sw_init(struct amdgpu_device *adev);
#endif

View File

@ -22,6 +22,29 @@
#include "amdgpu.h"
#include "amdgpu_ras.h"
int amdgpu_nbio_ras_sw_init(struct amdgpu_device *adev)
{
int err;
struct amdgpu_nbio_ras *ras;
if (!adev->nbio.ras)
return 0;
ras = adev->nbio.ras;
err = amdgpu_ras_register_ras_block(adev, &ras->ras_block);
if (err) {
dev_err(adev->dev, "Failed to register pcie_bif ras block!\n");
return err;
}
strcpy(ras->ras_block.ras_comm.name, "pcie_bif");
ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__PCIE_BIF;
ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
adev->nbio.ras_if = &ras->ras_block.ras_comm;
return 0;
}
int amdgpu_nbio_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *ras_block)
{
int r;

View File

@ -106,5 +106,6 @@ struct amdgpu_nbio {
struct amdgpu_nbio_ras *ras;
};
int amdgpu_nbio_ras_sw_init(struct amdgpu_device *adev);
int amdgpu_nbio_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *ras_block);
#endif

View File

@ -1265,24 +1265,41 @@ void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
trace_amdgpu_bo_move(abo, new_mem->mem_type, old_mem->mem_type);
}
void amdgpu_bo_get_memory(struct amdgpu_bo *bo, uint64_t *vram_mem,
uint64_t *gtt_mem, uint64_t *cpu_mem)
void amdgpu_bo_get_memory(struct amdgpu_bo *bo,
struct amdgpu_mem_stats *stats)
{
unsigned int domain;
uint64_t size = amdgpu_bo_size(bo);
domain = amdgpu_mem_type_to_domain(bo->tbo.resource->mem_type);
switch (domain) {
case AMDGPU_GEM_DOMAIN_VRAM:
*vram_mem += amdgpu_bo_size(bo);
stats->vram += size;
if (amdgpu_bo_in_cpu_visible_vram(bo))
stats->visible_vram += size;
break;
case AMDGPU_GEM_DOMAIN_GTT:
*gtt_mem += amdgpu_bo_size(bo);
stats->gtt += size;
break;
case AMDGPU_GEM_DOMAIN_CPU:
default:
*cpu_mem += amdgpu_bo_size(bo);
stats->cpu += size;
break;
}
if (bo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM) {
stats->requested_vram += size;
if (bo->flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED)
stats->requested_visible_vram += size;
if (domain != AMDGPU_GEM_DOMAIN_VRAM) {
stats->evicted_vram += size;
if (bo->flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED)
stats->evicted_visible_vram += size;
}
} else if (bo->preferred_domains & AMDGPU_GEM_DOMAIN_GTT) {
stats->requested_gtt += size;
}
}
/**

View File

@ -126,6 +126,27 @@ struct amdgpu_bo_vm {
struct amdgpu_vm_bo_base entries[];
};
struct amdgpu_mem_stats {
/* current VRAM usage, includes visible VRAM */
uint64_t vram;
/* current visible VRAM usage */
uint64_t visible_vram;
/* current GTT usage */
uint64_t gtt;
/* current system memory usage */
uint64_t cpu;
/* sum of evicted buffers, includes visible VRAM */
uint64_t evicted_vram;
/* sum of evicted buffers due to CPU access */
uint64_t evicted_visible_vram;
/* how much userspace asked for, includes vis.VRAM */
uint64_t requested_vram;
/* how much userspace asked for */
uint64_t requested_visible_vram;
/* how much userspace asked for */
uint64_t requested_gtt;
};
static inline struct amdgpu_bo *ttm_to_amdgpu_bo(struct ttm_buffer_object *tbo)
{
return container_of(tbo, struct amdgpu_bo, tbo);
@ -325,8 +346,8 @@ int amdgpu_bo_sync_wait_resv(struct amdgpu_device *adev, struct dma_resv *resv,
int amdgpu_bo_sync_wait(struct amdgpu_bo *bo, void *owner, bool intr);
u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo);
u64 amdgpu_bo_gpu_offset_no_check(struct amdgpu_bo *bo);
void amdgpu_bo_get_memory(struct amdgpu_bo *bo, uint64_t *vram_mem,
uint64_t *gtt_mem, uint64_t *cpu_mem);
void amdgpu_bo_get_memory(struct amdgpu_bo *bo,
struct amdgpu_mem_stats *stats);
void amdgpu_bo_add_to_shadow_list(struct amdgpu_bo_vm *vmbo);
int amdgpu_bo_restore_shadow(struct amdgpu_bo *shadow,
struct dma_fence **fence);

View File

@ -191,6 +191,7 @@ static int psp_early_init(void *handle)
psp_v12_0_set_psp_funcs(psp);
break;
case IP_VERSION(13, 0, 2):
case IP_VERSION(13, 0, 6):
psp_v13_0_set_psp_funcs(psp);
break;
case IP_VERSION(13, 0, 1):

View File

@ -2554,21 +2554,24 @@ int amdgpu_ras_init(struct amdgpu_device *adev)
/* initialize nbio ras function ahead of any other
* ras functions so hardware fatal error interrupt
* can be enabled as early as possible */
switch (adev->asic_type) {
case CHIP_VEGA20:
case CHIP_ARCTURUS:
case CHIP_ALDEBARAN:
if (!adev->gmc.xgmi.connected_to_cpu) {
switch (adev->ip_versions[NBIO_HWIP][0]) {
case IP_VERSION(7, 4, 0):
case IP_VERSION(7, 4, 1):
case IP_VERSION(7, 4, 4):
if (!adev->gmc.xgmi.connected_to_cpu)
adev->nbio.ras = &nbio_v7_4_ras;
amdgpu_ras_register_ras_block(adev, &adev->nbio.ras->ras_block);
adev->nbio.ras_if = &adev->nbio.ras->ras_block.ras_comm;
}
break;
default:
/* nbio ras is not available */
break;
}
/* nbio ras block needs to be enabled ahead of other ras blocks
* to handle fatal error */
r = amdgpu_nbio_ras_sw_init(adev);
if (r)
return r;
if (adev->nbio.ras &&
adev->nbio.ras->init_ras_controller_interrupt) {
r = adev->nbio.ras->init_ras_controller_interrupt(adev);
@ -3073,9 +3076,6 @@ int amdgpu_ras_register_ras_block(struct amdgpu_device *adev,
if (!adev || !ras_block_obj)
return -EINVAL;
if (!amdgpu_ras_asic_supported(adev))
return 0;
ras_node = kzalloc(sizeof(*ras_node), GFP_KERNEL);
if (!ras_node)
return -ENOMEM;

View File

@ -208,6 +208,36 @@ int amdgpu_umc_process_ras_data_cb(struct amdgpu_device *adev,
return amdgpu_umc_do_page_retirement(adev, ras_error_status, entry, true);
}
int amdgpu_umc_ras_sw_init(struct amdgpu_device *adev)
{
int err;
struct amdgpu_umc_ras *ras;
if (!adev->umc.ras)
return 0;
ras = adev->umc.ras;
err = amdgpu_ras_register_ras_block(adev, &ras->ras_block);
if (err) {
dev_err(adev->dev, "Failed to register umc ras block!\n");
return err;
}
strcpy(adev->umc.ras->ras_block.ras_comm.name, "umc");
ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__UMC;
ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
adev->umc.ras_if = &ras->ras_block.ras_comm;
if (!ras->ras_block.ras_late_init)
ras->ras_block.ras_late_init = amdgpu_umc_ras_late_init;
if (ras->ras_block.ras_cb)
ras->ras_block.ras_cb = amdgpu_umc_process_ras_data_cb;
return 0;
}
int amdgpu_umc_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *ras_block)
{
int r;

View File

@ -87,6 +87,7 @@ struct amdgpu_umc {
unsigned long active_mask;
};
int amdgpu_umc_ras_sw_init(struct amdgpu_device *adev);
int amdgpu_umc_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *ras_block);
int amdgpu_umc_poison_handler(struct amdgpu_device *adev, bool reset);
int amdgpu_umc_process_ecc_irq(struct amdgpu_device *adev,

View File

@ -1118,14 +1118,11 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo,
{
struct amdgpu_device *adev = ring->adev;
struct dma_fence *f = NULL;
uint32_t offset, data[4];
struct amdgpu_job *job;
struct amdgpu_ib *ib;
uint32_t data[4];
uint64_t addr;
long r;
int i;
unsigned offset_idx = 0;
unsigned offset[3] = { UVD_BASE_SI, 0, 0 };
int i, r;
r = amdgpu_job_alloc_with_ib(ring->adev, &adev->uvd.entity,
AMDGPU_FENCE_OWNER_UNDEFINED,
@ -1134,16 +1131,15 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo,
if (r)
return r;
if (adev->asic_type >= CHIP_VEGA10) {
offset_idx = 1 + ring->me;
offset[1] = adev->reg_offset[UVD_HWIP][0][1];
offset[2] = adev->reg_offset[UVD_HWIP][1][1];
}
if (adev->asic_type >= CHIP_VEGA10)
offset = adev->reg_offset[UVD_HWIP][ring->me][1];
else
offset = UVD_BASE_SI;
data[0] = PACKET0(offset[offset_idx] + UVD_GPCOM_VCPU_DATA0, 0);
data[1] = PACKET0(offset[offset_idx] + UVD_GPCOM_VCPU_DATA1, 0);
data[2] = PACKET0(offset[offset_idx] + UVD_GPCOM_VCPU_CMD, 0);
data[3] = PACKET0(offset[offset_idx] + UVD_NO_OP, 0);
data[0] = PACKET0(offset + UVD_GPCOM_VCPU_DATA0, 0);
data[1] = PACKET0(offset + UVD_GPCOM_VCPU_DATA1, 0);
data[2] = PACKET0(offset + UVD_GPCOM_VCPU_CMD, 0);
data[3] = PACKET0(offset + UVD_NO_OP, 0);
ib = &job->ibs[0];
addr = amdgpu_bo_gpu_offset(bo);
@ -1160,14 +1156,6 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo,
ib->length_dw = 16;
if (direct) {
r = dma_resv_wait_timeout(bo->tbo.base.resv,
DMA_RESV_USAGE_KERNEL, false,
msecs_to_jiffies(10));
if (r == 0)
r = -ETIMEDOUT;
if (r < 0)
goto err_free;
r = amdgpu_job_submit_direct(job, ring, &f);
if (r)
goto err_free;

View File

@ -26,6 +26,7 @@
#include <linux/firmware.h>
#include <linux/module.h>
#include <linux/dmi.h>
#include <linux/pci.h>
#include <linux/debugfs.h>
#include <drm/drm_drv.h>
@ -114,6 +115,24 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
adev->vcn.indirect_sram = true;
/*
* Some Steam Deck's BIOS versions are incompatible with the
* indirect SRAM mode, leading to amdgpu being unable to get
* properly probed (and even potentially crashing the kernel).
* Hence, check for these versions here - notice this is
* restricted to Vangogh (Deck's APU).
*/
if (adev->ip_versions[UVD_HWIP][0] == IP_VERSION(3, 0, 2)) {
const char *bios_ver = dmi_get_system_info(DMI_BIOS_VERSION);
if (bios_ver && (!strncmp("F7A0113", bios_ver, 7) ||
!strncmp("F7A0114", bios_ver, 7))) {
adev->vcn.indirect_sram = false;
dev_info(adev->dev,
"Steam Deck quirk: indirect SRAM disabled on BIOS %s\n", bios_ver);
}
}
hdr = (const struct common_firmware_header *)adev->vcn.fw->data;
adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version);
@ -1162,19 +1181,28 @@ int amdgpu_vcn_process_poison_irq(struct amdgpu_device *adev,
return 0;
}
void amdgpu_vcn_set_ras_funcs(struct amdgpu_device *adev)
int amdgpu_vcn_ras_sw_init(struct amdgpu_device *adev)
{
int err;
struct amdgpu_vcn_ras *ras;
if (!adev->vcn.ras)
return;
return 0;
amdgpu_ras_register_ras_block(adev, &adev->vcn.ras->ras_block);
ras = adev->vcn.ras;
err = amdgpu_ras_register_ras_block(adev, &ras->ras_block);
if (err) {
dev_err(adev->dev, "Failed to register vcn ras block!\n");
return err;
}
strcpy(adev->vcn.ras->ras_block.ras_comm.name, "vcn");
adev->vcn.ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__VCN;
adev->vcn.ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__POISON;
adev->vcn.ras_if = &adev->vcn.ras->ras_block.ras_comm;
strcpy(ras->ras_block.ras_comm.name, "vcn");
ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__VCN;
ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__POISON;
adev->vcn.ras_if = &ras->ras_block.ras_comm;
/* If don't define special ras_late_init function, use default ras_late_init */
if (!adev->vcn.ras->ras_block.ras_late_init)
adev->vcn.ras->ras_block.ras_late_init = amdgpu_ras_block_late_init;
if (!ras->ras_block.ras_late_init)
ras->ras_block.ras_late_init = amdgpu_ras_block_late_init;
return 0;
}

View File

@ -400,6 +400,6 @@ void amdgpu_debugfs_vcn_fwlog_init(struct amdgpu_device *adev,
int amdgpu_vcn_process_poison_irq(struct amdgpu_device *adev,
struct amdgpu_irq_src *source,
struct amdgpu_iv_entry *entry);
void amdgpu_vcn_set_ras_funcs(struct amdgpu_device *adev);
int amdgpu_vcn_ras_sw_init(struct amdgpu_device *adev);
#endif

View File

@ -124,6 +124,8 @@ enum AMDGIM_FEATURE_FLAG {
AMDGIM_FEATURE_PP_ONE_VF = (1 << 4),
/* Indirect Reg Access enabled */
AMDGIM_FEATURE_INDIRECT_REG_ACCESS = (1 << 5),
/* AV1 Support MODE*/
AMDGIM_FEATURE_AV1_SUPPORT = (1 << 6),
};
enum AMDGIM_REG_ACCESS_FLAG {
@ -322,6 +324,8 @@ static inline bool is_virtual_machine(void)
((!amdgpu_in_reset(adev)) && adev->virt.tdr_debug)
#define amdgpu_sriov_is_normal(adev) \
((!amdgpu_in_reset(adev)) && (!adev->virt.tdr_debug))
#define amdgpu_sriov_is_av1_support(adev) \
((adev)->virt.gim_feature & AMDGIM_FEATURE_AV1_SUPPORT)
bool amdgpu_virt_mmio_blocked(struct amdgpu_device *adev);
void amdgpu_virt_init_setting(struct amdgpu_device *adev);
void amdgpu_virt_kiq_reg_write_reg_wait(struct amdgpu_device *adev,

View File

@ -867,6 +867,8 @@ int amdgpu_vm_update_range(struct amdgpu_device *adev, struct amdgpu_vm *vm,
pages_addr[idx - 1] + PAGE_SIZE))
break;
}
if (!contiguous)
count--;
num_entries = count *
AMDGPU_GPU_PAGES_IN_CPU_PAGE;
}
@ -918,8 +920,8 @@ int amdgpu_vm_update_range(struct amdgpu_device *adev, struct amdgpu_vm *vm,
return r;
}
void amdgpu_vm_get_memory(struct amdgpu_vm *vm, uint64_t *vram_mem,
uint64_t *gtt_mem, uint64_t *cpu_mem)
void amdgpu_vm_get_memory(struct amdgpu_vm *vm,
struct amdgpu_mem_stats *stats)
{
struct amdgpu_bo_va *bo_va, *tmp;
@ -927,41 +929,36 @@ void amdgpu_vm_get_memory(struct amdgpu_vm *vm, uint64_t *vram_mem,
list_for_each_entry_safe(bo_va, tmp, &vm->idle, base.vm_status) {
if (!bo_va->base.bo)
continue;
amdgpu_bo_get_memory(bo_va->base.bo, vram_mem,
gtt_mem, cpu_mem);
amdgpu_bo_get_memory(bo_va->base.bo, stats);
}
list_for_each_entry_safe(bo_va, tmp, &vm->evicted, base.vm_status) {
if (!bo_va->base.bo)
continue;
amdgpu_bo_get_memory(bo_va->base.bo, vram_mem,
gtt_mem, cpu_mem);
amdgpu_bo_get_memory(bo_va->base.bo, stats);
}
list_for_each_entry_safe(bo_va, tmp, &vm->relocated, base.vm_status) {
if (!bo_va->base.bo)
continue;
amdgpu_bo_get_memory(bo_va->base.bo, vram_mem,
gtt_mem, cpu_mem);
amdgpu_bo_get_memory(bo_va->base.bo, stats);
}
list_for_each_entry_safe(bo_va, tmp, &vm->moved, base.vm_status) {
if (!bo_va->base.bo)
continue;
amdgpu_bo_get_memory(bo_va->base.bo, vram_mem,
gtt_mem, cpu_mem);
amdgpu_bo_get_memory(bo_va->base.bo, stats);
}
list_for_each_entry_safe(bo_va, tmp, &vm->invalidated, base.vm_status) {
if (!bo_va->base.bo)
continue;
amdgpu_bo_get_memory(bo_va->base.bo, vram_mem,
gtt_mem, cpu_mem);
amdgpu_bo_get_memory(bo_va->base.bo, stats);
}
list_for_each_entry_safe(bo_va, tmp, &vm->done, base.vm_status) {
if (!bo_va->base.bo)
continue;
amdgpu_bo_get_memory(bo_va->base.bo, vram_mem,
gtt_mem, cpu_mem);
amdgpu_bo_get_memory(bo_va->base.bo, stats);
}
spin_unlock(&vm->status_lock);
}
/**
* amdgpu_vm_bo_update - update all BO mappings in the vm page table
*

View File

@ -40,6 +40,7 @@ struct amdgpu_bo_va;
struct amdgpu_job;
struct amdgpu_bo_list_entry;
struct amdgpu_bo_vm;
struct amdgpu_mem_stats;
/*
* GPUVM handling
@ -457,8 +458,8 @@ void amdgpu_vm_set_task_info(struct amdgpu_vm *vm);
void amdgpu_vm_move_to_lru_tail(struct amdgpu_device *adev,
struct amdgpu_vm *vm);
void amdgpu_vm_get_memory(struct amdgpu_vm *vm, uint64_t *vram_mem,
uint64_t *gtt_mem, uint64_t *cpu_mem);
void amdgpu_vm_get_memory(struct amdgpu_vm *vm,
struct amdgpu_mem_stats *stats);
int amdgpu_vm_pt_clear(struct amdgpu_device *adev, struct amdgpu_vm *vm,
struct amdgpu_bo_vm *vmbo, bool immediate);

View File

@ -308,7 +308,7 @@ static const struct sysfs_ops amdgpu_xgmi_hive_ops = {
.show = amdgpu_xgmi_show_attrs,
};
struct kobj_type amdgpu_xgmi_hive_type = {
static const struct kobj_type amdgpu_xgmi_hive_type = {
.release = amdgpu_xgmi_hive_release,
.sysfs_ops = &amdgpu_xgmi_hive_ops,
.default_groups = amdgpu_xgmi_hive_groups,
@ -1048,12 +1048,30 @@ struct amdgpu_ras_block_hw_ops xgmi_ras_hw_ops = {
struct amdgpu_xgmi_ras xgmi_ras = {
.ras_block = {
.ras_comm = {
.name = "xgmi_wafl",
.block = AMDGPU_RAS_BLOCK__XGMI_WAFL,
.type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE,
},
.hw_ops = &xgmi_ras_hw_ops,
.ras_late_init = amdgpu_xgmi_ras_late_init,
},
};
int amdgpu_xgmi_ras_sw_init(struct amdgpu_device *adev)
{
int err;
struct amdgpu_xgmi_ras *ras;
if (!adev->gmc.xgmi.ras)
return 0;
ras = adev->gmc.xgmi.ras;
err = amdgpu_ras_register_ras_block(adev, &ras->ras_block);
if (err) {
dev_err(adev->dev, "Failed to register xgmi_wafl_pcs ras block!\n");
return err;
}
strcpy(ras->ras_block.ras_comm.name, "xgmi_wafl_pcs");
ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__XGMI_WAFL;
ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
adev->gmc.xgmi.ras_if = &ras->ras_block.ras_comm;
return 0;
}

View File

@ -73,5 +73,6 @@ static inline bool amdgpu_xgmi_same_hive(struct amdgpu_device *adev,
adev->gmc.xgmi.hive_id &&
adev->gmc.xgmi.hive_id == bo_adev->gmc.xgmi.hive_id);
}
int amdgpu_xgmi_ras_sw_init(struct amdgpu_device *adev);
#endif

View File

@ -93,7 +93,8 @@ union amd_sriov_msg_feature_flags {
uint32_t mm_bw_management : 1;
uint32_t pp_one_vf_mode : 1;
uint32_t reg_indirect_acc : 1;
uint32_t reserved : 26;
uint32_t av1_support : 1;
uint32_t reserved : 25;
} flags;
uint32_t all;
};

View File

@ -7266,7 +7266,6 @@ static int gfx_v10_0_hw_fini(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
int r;
uint32_t tmp;
amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0);
amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0);
@ -7285,17 +7284,9 @@ static int gfx_v10_0_hw_fini(void *handle)
if (amdgpu_sriov_vf(adev)) {
gfx_v10_0_cp_gfx_enable(adev, false);
/* Program KIQ position of RLC_CP_SCHEDULERS during destroy */
if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(10, 3, 0)) {
tmp = RREG32_SOC15(GC, 0, mmRLC_CP_SCHEDULERS_Sienna_Cichlid);
tmp &= 0xffffff00;
WREG32_SOC15(GC, 0, mmRLC_CP_SCHEDULERS_Sienna_Cichlid, tmp);
} else {
tmp = RREG32_SOC15(GC, 0, mmRLC_CP_SCHEDULERS);
tmp &= 0xffffff00;
WREG32_SOC15(GC, 0, mmRLC_CP_SCHEDULERS, tmp);
}
/* Remove the steps of clearing KIQ position.
* It causes GFX hang when another Win guest is rendering.
*/
return 0;
}
gfx_v10_0_cp_enable(adev, false);

View File

@ -699,25 +699,8 @@ static void gmc_v10_0_set_umc_funcs(struct amdgpu_device *adev)
default:
break;
}
if (adev->umc.ras) {
amdgpu_ras_register_ras_block(adev, &adev->umc.ras->ras_block);
strcpy(adev->umc.ras->ras_block.ras_comm.name, "umc");
adev->umc.ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__UMC;
adev->umc.ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
adev->umc.ras_if = &adev->umc.ras->ras_block.ras_comm;
/* If don't define special ras_late_init function, use default ras_late_init */
if (!adev->umc.ras->ras_block.ras_late_init)
adev->umc.ras->ras_block.ras_late_init = amdgpu_umc_ras_late_init;
/* If not defined special ras_cb function, use default ras_cb */
if (!adev->umc.ras->ras_block.ras_cb)
adev->umc.ras->ras_block.ras_cb = amdgpu_umc_process_ras_data_cb;
}
}
static void gmc_v10_0_set_mmhub_funcs(struct amdgpu_device *adev)
{
switch (adev->ip_versions[MMHUB_HWIP][0]) {
@ -754,7 +737,6 @@ static void gmc_v10_0_set_gfxhub_funcs(struct amdgpu_device *adev)
static int gmc_v10_0_early_init(void *handle)
{
int r;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
gmc_v10_0_set_mmhub_funcs(adev);
@ -770,10 +752,6 @@ static int gmc_v10_0_early_init(void *handle)
adev->gmc.private_aperture_end =
adev->gmc.private_aperture_start + (4ULL << 30) - 1;
r = amdgpu_gmc_ras_early_init(adev);
if (r)
return r;
return 0;
}
@ -1024,6 +1002,10 @@ static int gmc_v10_0_sw_init(void *handle)
amdgpu_vm_manager_init(adev);
r = amdgpu_gmc_ras_sw_init(adev);
if (r)
return r;
return 0;
}

View File

@ -581,23 +581,6 @@ static void gmc_v11_0_set_umc_funcs(struct amdgpu_device *adev)
default:
break;
}
if (adev->umc.ras) {
amdgpu_ras_register_ras_block(adev, &adev->umc.ras->ras_block);
strcpy(adev->umc.ras->ras_block.ras_comm.name, "umc");
adev->umc.ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__UMC;
adev->umc.ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
adev->umc.ras_if = &adev->umc.ras->ras_block.ras_comm;
/* If don't define special ras_late_init function, use default ras_late_init */
if (!adev->umc.ras->ras_block.ras_late_init)
adev->umc.ras->ras_block.ras_late_init = amdgpu_umc_ras_late_init;
/* If not define special ras_cb function, use default ras_cb */
if (!adev->umc.ras->ras_block.ras_cb)
adev->umc.ras->ras_block.ras_cb = amdgpu_umc_process_ras_data_cb;
}
}
@ -846,6 +829,10 @@ static int gmc_v11_0_sw_init(void *handle)
amdgpu_vm_manager_init(adev);
r = amdgpu_gmc_ras_sw_init(adev);
if (r)
return r;
return 0;
}
@ -875,6 +862,12 @@ static int gmc_v11_0_sw_fini(void *handle)
static void gmc_v11_0_init_golden_registers(struct amdgpu_device *adev)
{
if (amdgpu_sriov_vf(adev)) {
struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
WREG32(hub->vm_contexts_disable, 0);
return;
}
}
/**

View File

@ -1318,23 +1318,6 @@ static void gmc_v9_0_set_umc_funcs(struct amdgpu_device *adev)
default:
break;
}
if (adev->umc.ras) {
amdgpu_ras_register_ras_block(adev, &adev->umc.ras->ras_block);
strcpy(adev->umc.ras->ras_block.ras_comm.name, "umc");
adev->umc.ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__UMC;
adev->umc.ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
adev->umc.ras_if = &adev->umc.ras->ras_block.ras_comm;
/* If don't define special ras_late_init function, use default ras_late_init */
if (!adev->umc.ras->ras_block.ras_late_init)
adev->umc.ras->ras_block.ras_late_init = amdgpu_umc_ras_late_init;
/* If not defined special ras_cb function, use default ras_cb */
if (!adev->umc.ras->ras_block.ras_cb)
adev->umc.ras->ras_block.ras_cb = amdgpu_umc_process_ras_data_cb;
}
}
static void gmc_v9_0_set_mmhub_funcs(struct amdgpu_device *adev)
@ -1368,15 +1351,6 @@ static void gmc_v9_0_set_mmhub_ras_funcs(struct amdgpu_device *adev)
/* mmhub ras is not available */
break;
}
if (adev->mmhub.ras) {
amdgpu_ras_register_ras_block(adev, &adev->mmhub.ras->ras_block);
strcpy(adev->mmhub.ras->ras_block.ras_comm.name, "mmhub");
adev->mmhub.ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__MMHUB;
adev->mmhub.ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE;
adev->mmhub.ras_if = &adev->mmhub.ras->ras_block.ras_comm;
}
}
static void gmc_v9_0_set_gfxhub_funcs(struct amdgpu_device *adev)
@ -1387,26 +1361,34 @@ static void gmc_v9_0_set_gfxhub_funcs(struct amdgpu_device *adev)
static void gmc_v9_0_set_hdp_ras_funcs(struct amdgpu_device *adev)
{
adev->hdp.ras = &hdp_v4_0_ras;
amdgpu_ras_register_ras_block(adev, &adev->hdp.ras->ras_block);
adev->hdp.ras_if = &adev->hdp.ras->ras_block.ras_comm;
}
static void gmc_v9_0_set_mca_funcs(struct amdgpu_device *adev)
static void gmc_v9_0_set_mca_ras_funcs(struct amdgpu_device *adev)
{
struct amdgpu_mca *mca = &adev->mca;
/* is UMC the right IP to check for MCA? Maybe DF? */
switch (adev->ip_versions[UMC_HWIP][0]) {
case IP_VERSION(6, 7, 0):
if (!adev->gmc.xgmi.connected_to_cpu)
adev->mca.funcs = &mca_v3_0_funcs;
if (!adev->gmc.xgmi.connected_to_cpu) {
mca->mp0.ras = &mca_v3_0_mp0_ras;
mca->mp1.ras = &mca_v3_0_mp1_ras;
mca->mpio.ras = &mca_v3_0_mpio_ras;
}
break;
default:
break;
}
}
static void gmc_v9_0_set_xgmi_ras_funcs(struct amdgpu_device *adev)
{
if (!adev->gmc.xgmi.connected_to_cpu)
adev->gmc.xgmi.ras = &xgmi_ras;
}
static int gmc_v9_0_early_init(void *handle)
{
int r;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
/* ARCT and VEGA20 don't have XGMI defined in their IP discovery tables */
@ -1427,7 +1409,8 @@ static int gmc_v9_0_early_init(void *handle)
gmc_v9_0_set_mmhub_ras_funcs(adev);
gmc_v9_0_set_gfxhub_funcs(adev);
gmc_v9_0_set_hdp_ras_funcs(adev);
gmc_v9_0_set_mca_funcs(adev);
gmc_v9_0_set_mca_ras_funcs(adev);
gmc_v9_0_set_xgmi_ras_funcs(adev);
adev->gmc.shared_aperture_start = 0x2000000000000000ULL;
adev->gmc.shared_aperture_end =
@ -1436,10 +1419,6 @@ static int gmc_v9_0_early_init(void *handle)
adev->gmc.private_aperture_end =
adev->gmc.private_aperture_start + (4ULL << 30) - 1;
r = amdgpu_gmc_ras_early_init(adev);
if (r)
return r;
return 0;
}
@ -1644,8 +1623,6 @@ static int gmc_v9_0_sw_init(void *handle)
adev->gfxhub.funcs->init(adev);
adev->mmhub.funcs->init(adev);
if (adev->mca.funcs)
adev->mca.funcs->init(adev);
spin_lock_init(&adev->gmc.invalidate_lock);
@ -1798,6 +1775,10 @@ static int gmc_v9_0_sw_init(void *handle)
gmc_v9_0_save_registers(adev);
r = amdgpu_gmc_ras_sw_init(adev);
if (r)
return r;
return 0;
}

View File

@ -49,7 +49,8 @@ static void hdp_v4_0_flush_hdp(struct amdgpu_device *adev,
static void hdp_v4_0_invalidate_hdp(struct amdgpu_device *adev,
struct amdgpu_ring *ring)
{
if (adev->ip_versions[HDP_HWIP][0] == IP_VERSION(4, 4, 0))
if (adev->ip_versions[HDP_HWIP][0] == IP_VERSION(4, 4, 0) ||
adev->ip_versions[HDP_HWIP][0] == IP_VERSION(4, 4, 2))
return;
if (!ring || !ring->funcs->emit_wreg)
@ -160,11 +161,6 @@ struct amdgpu_ras_block_hw_ops hdp_v4_0_ras_hw_ops = {
struct amdgpu_hdp_ras hdp_v4_0_ras = {
.ras_block = {
.ras_comm = {
.name = "hdp",
.block = AMDGPU_RAS_BLOCK__HDP,
.type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE,
},
.hw_ops = &hdp_v4_0_ras_hw_ops,
},
};

View File

@ -138,6 +138,10 @@ static int jpeg_v2_5_sw_init(void *handle)
adev->jpeg.inst[i].external.jpeg_pitch = SOC15_REG_OFFSET(JPEG, i, mmUVD_JPEG_PITCH);
}
r = amdgpu_jpeg_ras_sw_init(adev);
if (r)
return r;
return 0;
}
@ -806,6 +810,4 @@ static void jpeg_v2_5_set_ras_funcs(struct amdgpu_device *adev)
default:
break;
}
jpeg_set_ras_funcs(adev);
}

View File

@ -113,6 +113,10 @@ static int jpeg_v4_0_sw_init(void *handle)
adev->jpeg.internal.jpeg_pitch = regUVD_JPEG_PITCH_INTERNAL_OFFSET;
adev->jpeg.inst->external.jpeg_pitch = SOC15_REG_OFFSET(JPEG, 0, regUVD_JPEG_PITCH);
r = amdgpu_jpeg_ras_sw_init(adev);
if (r)
return r;
return 0;
}
@ -685,6 +689,4 @@ static void jpeg_v4_0_set_ras_funcs(struct amdgpu_device *adev)
default:
break;
}
jpeg_set_ras_funcs(adev);
}

View File

@ -51,19 +51,13 @@ static int mca_v3_0_ras_block_match(struct amdgpu_ras_block_object *block_obj,
return -EINVAL;
}
const struct amdgpu_ras_block_hw_ops mca_v3_0_mp0_hw_ops = {
static const struct amdgpu_ras_block_hw_ops mca_v3_0_mp0_hw_ops = {
.query_ras_error_count = mca_v3_0_mp0_query_ras_error_count,
.query_ras_error_address = NULL,
};
struct amdgpu_mca_ras_block mca_v3_0_mp0_ras = {
.ras_block = {
.ras_comm = {
.block = AMDGPU_RAS_BLOCK__MCA,
.sub_block_index = AMDGPU_RAS_MCA_BLOCK__MP0,
.type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE,
.name = "mp0",
},
.hw_ops = &mca_v3_0_mp0_hw_ops,
.ras_block_match = mca_v3_0_ras_block_match,
},
@ -77,19 +71,13 @@ static void mca_v3_0_mp1_query_ras_error_count(struct amdgpu_device *adev,
ras_error_status);
}
const struct amdgpu_ras_block_hw_ops mca_v3_0_mp1_hw_ops = {
static const struct amdgpu_ras_block_hw_ops mca_v3_0_mp1_hw_ops = {
.query_ras_error_count = mca_v3_0_mp1_query_ras_error_count,
.query_ras_error_address = NULL,
};
struct amdgpu_mca_ras_block mca_v3_0_mp1_ras = {
.ras_block = {
.ras_comm = {
.block = AMDGPU_RAS_BLOCK__MCA,
.sub_block_index = AMDGPU_RAS_MCA_BLOCK__MP1,
.type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE,
.name = "mp1",
},
.hw_ops = &mca_v3_0_mp1_hw_ops,
.ras_block_match = mca_v3_0_ras_block_match,
},
@ -103,40 +91,14 @@ static void mca_v3_0_mpio_query_ras_error_count(struct amdgpu_device *adev,
ras_error_status);
}
const struct amdgpu_ras_block_hw_ops mca_v3_0_mpio_hw_ops = {
static const struct amdgpu_ras_block_hw_ops mca_v3_0_mpio_hw_ops = {
.query_ras_error_count = mca_v3_0_mpio_query_ras_error_count,
.query_ras_error_address = NULL,
};
struct amdgpu_mca_ras_block mca_v3_0_mpio_ras = {
.ras_block = {
.ras_comm = {
.block = AMDGPU_RAS_BLOCK__MCA,
.sub_block_index = AMDGPU_RAS_MCA_BLOCK__MPIO,
.type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE,
.name = "mpio",
},
.hw_ops = &mca_v3_0_mpio_hw_ops,
.ras_block_match = mca_v3_0_ras_block_match,
},
};
static void mca_v3_0_init(struct amdgpu_device *adev)
{
struct amdgpu_mca *mca = &adev->mca;
mca->mp0.ras = &mca_v3_0_mp0_ras;
mca->mp1.ras = &mca_v3_0_mp1_ras;
mca->mpio.ras = &mca_v3_0_mpio_ras;
amdgpu_ras_register_ras_block(adev, &mca->mp0.ras->ras_block);
amdgpu_ras_register_ras_block(adev, &mca->mp1.ras->ras_block);
amdgpu_ras_register_ras_block(adev, &mca->mpio.ras->ras_block);
mca->mp0.ras_if = &mca->mp0.ras->ras_block.ras_comm;
mca->mp1.ras_if = &mca->mp1.ras->ras_block.ras_comm;
mca->mpio.ras_if = &mca->mpio.ras->ras_block.ras_comm;
}
const struct amdgpu_mca_funcs mca_v3_0_funcs = {
.init = mca_v3_0_init,
};

View File

@ -21,6 +21,8 @@
#ifndef __MCA_V3_0_H__
#define __MCA_V3_0_H__
extern const struct amdgpu_mca_funcs mca_v3_0_funcs;
extern struct amdgpu_mca_ras_block mca_v3_0_mp0_ras;
extern struct amdgpu_mca_ras_block mca_v3_0_mp1_ras;
extern struct amdgpu_mca_ras_block mca_v3_0_mpio_ras;
#endif

View File

@ -517,6 +517,9 @@ static void mmhub_v3_0_init(struct amdgpu_device *adev)
hub->vm_l2_bank_select_reserved_cid2 =
SOC15_REG_OFFSET(MMHUB, 0, regMMVM_L2_BANK_SELECT_RESERVED_CID2);
hub->vm_contexts_disable =
SOC15_REG_OFFSET(MMHUB, 0, regMMVM_CONTEXTS_DISABLE);
hub->vmhub_funcs = &mmhub_v3_0_vmhub_funcs;
}

View File

@ -280,47 +280,6 @@ static int nv_query_video_codecs(struct amdgpu_device *adev, bool encode,
}
}
/*
* Indirect registers accessor
*/
static u32 nv_pcie_rreg(struct amdgpu_device *adev, u32 reg)
{
unsigned long address, data;
address = adev->nbio.funcs->get_pcie_index_offset(adev);
data = adev->nbio.funcs->get_pcie_data_offset(adev);
return amdgpu_device_indirect_rreg(adev, address, data, reg);
}
static void nv_pcie_wreg(struct amdgpu_device *adev, u32 reg, u32 v)
{
unsigned long address, data;
address = adev->nbio.funcs->get_pcie_index_offset(adev);
data = adev->nbio.funcs->get_pcie_data_offset(adev);
amdgpu_device_indirect_wreg(adev, address, data, reg, v);
}
static u64 nv_pcie_rreg64(struct amdgpu_device *adev, u32 reg)
{
unsigned long address, data;
address = adev->nbio.funcs->get_pcie_index_offset(adev);
data = adev->nbio.funcs->get_pcie_data_offset(adev);
return amdgpu_device_indirect_rreg64(adev, address, data, reg);
}
static void nv_pcie_wreg64(struct amdgpu_device *adev, u32 reg, u64 v)
{
unsigned long address, data;
address = adev->nbio.funcs->get_pcie_index_offset(adev);
data = adev->nbio.funcs->get_pcie_data_offset(adev);
amdgpu_device_indirect_wreg64(adev, address, data, reg, v);
}
static u32 nv_didt_rreg(struct amdgpu_device *adev, u32 reg)
{
unsigned long flags, address, data;
@ -561,21 +520,6 @@ static int nv_set_vce_clocks(struct amdgpu_device *adev, u32 evclk, u32 ecclk)
return 0;
}
static void nv_pcie_gen3_enable(struct amdgpu_device *adev)
{
if (pci_is_root_bus(adev->pdev->bus))
return;
if (amdgpu_pcie_gen2 == 0)
return;
if (!(adev->pm.pcie_gen_mask & (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2 |
CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)))
return;
/* todo */
}
static void nv_program_aspm(struct amdgpu_device *adev)
{
if (!amdgpu_device_should_use_aspm(adev))
@ -608,11 +552,6 @@ void nv_set_virt_ops(struct amdgpu_device *adev)
adev->virt.ops = &xgpu_nv_virt_ops;
}
static uint32_t nv_get_rev_id(struct amdgpu_device *adev)
{
return adev->nbio.funcs->get_rev_id(adev);
}
static bool nv_need_full_reset(struct amdgpu_device *adev)
{
return true;
@ -738,10 +677,10 @@ static int nv_common_early_init(void *handle)
}
adev->smc_rreg = NULL;
adev->smc_wreg = NULL;
adev->pcie_rreg = &nv_pcie_rreg;
adev->pcie_wreg = &nv_pcie_wreg;
adev->pcie_rreg64 = &nv_pcie_rreg64;
adev->pcie_wreg64 = &nv_pcie_wreg64;
adev->pcie_rreg = &amdgpu_device_indirect_rreg;
adev->pcie_wreg = &amdgpu_device_indirect_wreg;
adev->pcie_rreg64 = &amdgpu_device_indirect_rreg64;
adev->pcie_wreg64 = &amdgpu_device_indirect_wreg64;
adev->pciep_rreg = amdgpu_device_pcie_port_rreg;
adev->pciep_wreg = amdgpu_device_pcie_port_wreg;
@ -754,7 +693,7 @@ static int nv_common_early_init(void *handle)
adev->asic_funcs = &nv_asic_funcs;
adev->rev_id = nv_get_rev_id(adev);
adev->rev_id = amdgpu_device_get_rev_id(adev);
adev->external_rev_id = 0xff;
/* TODO: split the GC and PG flags based on the relevant IP version for which
* they are relevant.
@ -1055,8 +994,8 @@ static int nv_common_late_init(void *handle)
amdgpu_virt_update_sriov_video_codec(adev,
sriov_sc_video_codecs_encode_array,
ARRAY_SIZE(sriov_sc_video_codecs_encode_array),
sriov_sc_video_codecs_decode_array_vcn1,
ARRAY_SIZE(sriov_sc_video_codecs_decode_array_vcn1));
sriov_sc_video_codecs_decode_array_vcn0,
ARRAY_SIZE(sriov_sc_video_codecs_decode_array_vcn0));
}
}
@ -1088,8 +1027,6 @@ static int nv_common_hw_init(void *handle)
if (adev->nbio.funcs->apply_l1_link_width_reconfig_wa)
adev->nbio.funcs->apply_l1_link_width_reconfig_wa(adev);
/* enable pcie gen2/3 link */
nv_pcie_gen3_enable(adev);
/* enable aspm */
nv_program_aspm(adev);
/* setup nbio registers */

View File

@ -48,6 +48,7 @@ MODULE_FIRMWARE("amdgpu/psp_13_0_10_sos.bin");
MODULE_FIRMWARE("amdgpu/psp_13_0_10_ta.bin");
MODULE_FIRMWARE("amdgpu/psp_13_0_11_toc.bin");
MODULE_FIRMWARE("amdgpu/psp_13_0_11_ta.bin");
MODULE_FIRMWARE("amdgpu/psp_13_0_6_sos.bin");
/* For large FW files the time to complete can be very long */
#define USBC_PD_POLLING_LIMIT_S 240
@ -100,6 +101,7 @@ static int psp_v13_0_init_microcode(struct psp_context *psp)
return err;
break;
case IP_VERSION(13, 0, 0):
case IP_VERSION(13, 0, 6):
case IP_VERSION(13, 0, 7):
case IP_VERSION(13, 0, 10):
err = psp_init_sos_microcode(psp, ucode_prefix);

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-15 Advanced Micro Devices, Inc.
* Copyright 2022 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -19,9 +19,12 @@
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: AMD
*
*/
// TODO - remove this file after external build dependencies is resolved.
/* NOTE: This file is pending to be removed, do not add new code to this file */
#ifndef __SDMA_V4_4_2_H__
#define __SDMA_V4_4_2_H__
extern const struct amd_ip_funcs sdma_v4_4_2_ip_funcs;
extern const struct amdgpu_ip_block_version sdma_v4_4_2_ip_block;
#endif

View File

@ -191,47 +191,6 @@ static int soc15_query_video_codecs(struct amdgpu_device *adev, bool encode,
}
}
/*
* Indirect registers accessor
*/
static u32 soc15_pcie_rreg(struct amdgpu_device *adev, u32 reg)
{
unsigned long address, data;
address = adev->nbio.funcs->get_pcie_index_offset(adev);
data = adev->nbio.funcs->get_pcie_data_offset(adev);
return amdgpu_device_indirect_rreg(adev, address, data, reg);
}
static void soc15_pcie_wreg(struct amdgpu_device *adev, u32 reg, u32 v)
{
unsigned long address, data;
address = adev->nbio.funcs->get_pcie_index_offset(adev);
data = adev->nbio.funcs->get_pcie_data_offset(adev);
amdgpu_device_indirect_wreg(adev, address, data, reg, v);
}
static u64 soc15_pcie_rreg64(struct amdgpu_device *adev, u32 reg)
{
unsigned long address, data;
address = adev->nbio.funcs->get_pcie_index_offset(adev);
data = adev->nbio.funcs->get_pcie_data_offset(adev);
return amdgpu_device_indirect_rreg64(adev, address, data, reg);
}
static void soc15_pcie_wreg64(struct amdgpu_device *adev, u32 reg, u64 v)
{
unsigned long address, data;
address = adev->nbio.funcs->get_pcie_index_offset(adev);
data = adev->nbio.funcs->get_pcie_data_offset(adev);
amdgpu_device_indirect_wreg64(adev, address, data, reg, v);
}
static u32 soc15_uvd_ctx_rreg(struct amdgpu_device *adev, u32 reg)
{
unsigned long flags, address, data;
@ -651,24 +610,6 @@ static int soc15_set_vce_clocks(struct amdgpu_device *adev, u32 evclk, u32 ecclk
return 0;
}
static void soc15_pcie_gen3_enable(struct amdgpu_device *adev)
{
if (pci_is_root_bus(adev->pdev->bus))
return;
if (amdgpu_pcie_gen2 == 0)
return;
if (adev->flags & AMD_IS_APU)
return;
if (!(adev->pm.pcie_gen_mask & (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2 |
CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)))
return;
/* todo */
}
static void soc15_program_aspm(struct amdgpu_device *adev)
{
if (!amdgpu_device_should_use_aspm(adev))
@ -695,11 +636,6 @@ const struct amdgpu_ip_block_version vega10_common_ip_block =
.funcs = &soc15_common_ip_funcs,
};
static uint32_t soc15_get_rev_id(struct amdgpu_device *adev)
{
return adev->nbio.funcs->get_rev_id(adev);
}
static void soc15_reg_base_init(struct amdgpu_device *adev)
{
/* Set IP register base before any HW register access */
@ -936,10 +872,10 @@ static int soc15_common_early_init(void *handle)
}
adev->smc_rreg = NULL;
adev->smc_wreg = NULL;
adev->pcie_rreg = &soc15_pcie_rreg;
adev->pcie_wreg = &soc15_pcie_wreg;
adev->pcie_rreg64 = &soc15_pcie_rreg64;
adev->pcie_wreg64 = &soc15_pcie_wreg64;
adev->pcie_rreg = &amdgpu_device_indirect_rreg;
adev->pcie_wreg = &amdgpu_device_indirect_wreg;
adev->pcie_rreg64 = &amdgpu_device_indirect_rreg64;
adev->pcie_wreg64 = &amdgpu_device_indirect_wreg64;
adev->uvd_ctx_rreg = &soc15_uvd_ctx_rreg;
adev->uvd_ctx_wreg = &soc15_uvd_ctx_wreg;
adev->didt_rreg = &soc15_didt_rreg;
@ -949,7 +885,7 @@ static int soc15_common_early_init(void *handle)
adev->se_cac_rreg = &soc15_se_cac_rreg;
adev->se_cac_wreg = &soc15_se_cac_wreg;
adev->rev_id = soc15_get_rev_id(adev);
adev->rev_id = amdgpu_device_get_rev_id(adev);
adev->external_rev_id = 0xFF;
/* TODO: split the GC and PG flags based on the relevant IP version for which
* they are relevant.
@ -1230,8 +1166,6 @@ static int soc15_common_hw_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
/* enable pcie gen2/3 link */
soc15_pcie_gen3_enable(adev);
/* enable aspm */
soc15_program_aspm(adev);
/* setup nbio registers */

View File

@ -102,6 +102,59 @@ static const struct amdgpu_video_codecs vcn_4_0_0_video_codecs_decode_vcn1 =
.codec_array = vcn_4_0_0_video_codecs_decode_array_vcn1,
};
/* SRIOV SOC21, not const since data is controlled by host */
static struct amdgpu_video_codec_info sriov_vcn_4_0_0_video_codecs_encode_array_vcn0[] = {
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 2304, 0)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 4096, 2304, 0)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1, 8192, 4352, 0)},
};
static struct amdgpu_video_codec_info sriov_vcn_4_0_0_video_codecs_encode_array_vcn1[] = {
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 2304, 0)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 4096, 2304, 0)},
};
static struct amdgpu_video_codecs sriov_vcn_4_0_0_video_codecs_encode_vcn0 = {
.codec_count = ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_encode_array_vcn0),
.codec_array = sriov_vcn_4_0_0_video_codecs_encode_array_vcn0,
};
static struct amdgpu_video_codecs sriov_vcn_4_0_0_video_codecs_encode_vcn1 = {
.codec_count = ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_encode_array_vcn1),
.codec_array = sriov_vcn_4_0_0_video_codecs_encode_array_vcn1,
};
static struct amdgpu_video_codec_info sriov_vcn_4_0_0_video_codecs_decode_array_vcn0[] = {
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1, 8192, 4352, 0)},
};
static struct amdgpu_video_codec_info sriov_vcn_4_0_0_video_codecs_decode_array_vcn1[] = {
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)},
};
static struct amdgpu_video_codecs sriov_vcn_4_0_0_video_codecs_decode_vcn0 = {
.codec_count = ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_decode_array_vcn0),
.codec_array = sriov_vcn_4_0_0_video_codecs_decode_array_vcn0,
};
static struct amdgpu_video_codecs sriov_vcn_4_0_0_video_codecs_decode_vcn1 = {
.codec_count = ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_decode_array_vcn1),
.codec_array = sriov_vcn_4_0_0_video_codecs_decode_array_vcn1,
};
static int soc21_query_video_codecs(struct amdgpu_device *adev, bool encode,
const struct amdgpu_video_codecs **codecs)
{
@ -112,62 +165,37 @@ static int soc21_query_video_codecs(struct amdgpu_device *adev, bool encode,
case IP_VERSION(4, 0, 0):
case IP_VERSION(4, 0, 2):
case IP_VERSION(4, 0, 4):
if (adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0) {
if (encode)
*codecs = &vcn_4_0_0_video_codecs_encode_vcn1;
else
*codecs = &vcn_4_0_0_video_codecs_decode_vcn1;
if (amdgpu_sriov_vf(adev)) {
if ((adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0) ||
!amdgpu_sriov_is_av1_support(adev)) {
if (encode)
*codecs = &sriov_vcn_4_0_0_video_codecs_encode_vcn1;
else
*codecs = &sriov_vcn_4_0_0_video_codecs_decode_vcn1;
} else {
if (encode)
*codecs = &sriov_vcn_4_0_0_video_codecs_encode_vcn0;
else
*codecs = &sriov_vcn_4_0_0_video_codecs_decode_vcn0;
}
} else {
if (encode)
*codecs = &vcn_4_0_0_video_codecs_encode_vcn0;
else
*codecs = &vcn_4_0_0_video_codecs_decode_vcn0;
if ((adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0)) {
if (encode)
*codecs = &vcn_4_0_0_video_codecs_encode_vcn1;
else
*codecs = &vcn_4_0_0_video_codecs_decode_vcn1;
} else {
if (encode)
*codecs = &vcn_4_0_0_video_codecs_encode_vcn0;
else
*codecs = &vcn_4_0_0_video_codecs_decode_vcn0;
}
}
return 0;
default:
return -EINVAL;
}
}
/*
* Indirect registers accessor
*/
static u32 soc21_pcie_rreg(struct amdgpu_device *adev, u32 reg)
{
unsigned long address, data;
address = adev->nbio.funcs->get_pcie_index_offset(adev);
data = adev->nbio.funcs->get_pcie_data_offset(adev);
return amdgpu_device_indirect_rreg(adev, address, data, reg);
}
static void soc21_pcie_wreg(struct amdgpu_device *adev, u32 reg, u32 v)
{
unsigned long address, data;
address = adev->nbio.funcs->get_pcie_index_offset(adev);
data = adev->nbio.funcs->get_pcie_data_offset(adev);
amdgpu_device_indirect_wreg(adev, address, data, reg, v);
}
static u64 soc21_pcie_rreg64(struct amdgpu_device *adev, u32 reg)
{
unsigned long address, data;
address = adev->nbio.funcs->get_pcie_index_offset(adev);
data = adev->nbio.funcs->get_pcie_data_offset(adev);
return amdgpu_device_indirect_rreg64(adev, address, data, reg);
}
static void soc21_pcie_wreg64(struct amdgpu_device *adev, u32 reg, u64 v)
{
unsigned long address, data;
address = adev->nbio.funcs->get_pcie_index_offset(adev);
data = adev->nbio.funcs->get_pcie_data_offset(adev);
amdgpu_device_indirect_wreg64(adev, address, data, reg, v);
}
static u32 soc21_didt_rreg(struct amdgpu_device *adev, u32 reg)
{
@ -412,21 +440,6 @@ static int soc21_set_vce_clocks(struct amdgpu_device *adev, u32 evclk, u32 ecclk
return 0;
}
static void soc21_pcie_gen3_enable(struct amdgpu_device *adev)
{
if (pci_is_root_bus(adev->pdev->bus))
return;
if (amdgpu_pcie_gen2 == 0)
return;
if (!(adev->pm.pcie_gen_mask & (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2 |
CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)))
return;
/* todo */
}
static void soc21_program_aspm(struct amdgpu_device *adev)
{
if (!amdgpu_device_should_use_aspm(adev))
@ -453,11 +466,6 @@ const struct amdgpu_ip_block_version soc21_common_ip_block =
.funcs = &soc21_common_ip_funcs,
};
static uint32_t soc21_get_rev_id(struct amdgpu_device *adev)
{
return adev->nbio.funcs->get_rev_id(adev);
}
static bool soc21_need_full_reset(struct amdgpu_device *adev)
{
switch (adev->ip_versions[GC_HWIP][0]) {
@ -582,10 +590,10 @@ static int soc21_common_early_init(void *handle)
adev->rmmio_remap.bus_addr = adev->rmmio_base + MMIO_REG_HOLE_OFFSET;
adev->smc_rreg = NULL;
adev->smc_wreg = NULL;
adev->pcie_rreg = &soc21_pcie_rreg;
adev->pcie_wreg = &soc21_pcie_wreg;
adev->pcie_rreg64 = &soc21_pcie_rreg64;
adev->pcie_wreg64 = &soc21_pcie_wreg64;
adev->pcie_rreg = &amdgpu_device_indirect_rreg;
adev->pcie_wreg = &amdgpu_device_indirect_wreg;
adev->pcie_rreg64 = &amdgpu_device_indirect_rreg64;
adev->pcie_wreg64 = &amdgpu_device_indirect_wreg64;
adev->pciep_rreg = amdgpu_device_pcie_port_rreg;
adev->pciep_wreg = amdgpu_device_pcie_port_wreg;
@ -598,7 +606,7 @@ static int soc21_common_early_init(void *handle)
adev->asic_funcs = &soc21_asic_funcs;
adev->rev_id = soc21_get_rev_id(adev);
adev->rev_id = amdgpu_device_get_rev_id(adev);
adev->external_rev_id = 0xff;
switch (adev->ip_versions[GC_HWIP][0]) {
case IP_VERSION(11, 0, 0):
@ -730,8 +738,23 @@ static int soc21_common_late_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
if (amdgpu_sriov_vf(adev))
if (amdgpu_sriov_vf(adev)) {
xgpu_nv_mailbox_get_irq(adev);
if ((adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0) ||
!amdgpu_sriov_is_av1_support(adev)) {
amdgpu_virt_update_sriov_video_codec(adev,
sriov_vcn_4_0_0_video_codecs_encode_array_vcn1,
ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_encode_array_vcn1),
sriov_vcn_4_0_0_video_codecs_decode_array_vcn1,
ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_decode_array_vcn1));
} else {
amdgpu_virt_update_sriov_video_codec(adev,
sriov_vcn_4_0_0_video_codecs_encode_array_vcn0,
ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_encode_array_vcn0),
sriov_vcn_4_0_0_video_codecs_decode_array_vcn0,
ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_decode_array_vcn0));
}
}
return 0;
}
@ -755,8 +778,6 @@ static int soc21_common_hw_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
/* enable pcie gen2/3 link */
soc21_pcie_gen3_enable(adev);
/* enable aspm */
soc21_program_aspm(adev);
/* setup nbio registers */

View File

@ -225,6 +225,10 @@ static int vcn_v2_5_sw_init(void *handle)
if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
adev->vcn.pause_dpg_mode = vcn_v2_5_pause_dpg_mode;
r = amdgpu_vcn_ras_sw_init(adev);
if (r)
return r;
return 0;
}
@ -2031,6 +2035,4 @@ static void vcn_v2_5_set_ras_funcs(struct amdgpu_device *adev)
default:
break;
}
amdgpu_vcn_set_ras_funcs(adev);
}

View File

@ -181,6 +181,10 @@ static int vcn_v4_0_sw_init(void *handle)
if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
adev->vcn.pause_dpg_mode = vcn_v4_0_pause_dpg_mode;
r = amdgpu_vcn_ras_sw_init(adev);
if (r)
return r;
return 0;
}
@ -2123,6 +2127,4 @@ static void vcn_v4_0_set_ras_funcs(struct amdgpu_device *adev)
default:
break;
}
amdgpu_vcn_set_ras_funcs(adev);
}

View File

@ -321,7 +321,8 @@ static int vega20_ih_irq_init(struct amdgpu_device *adev)
/* psp firmware won't program IH_CHICKEN for aldebaran
* driver needs to program it properly according to
* MC_SPACE type in IH_RB_CNTL */
if (adev->ip_versions[OSSSYS_HWIP][0] == IP_VERSION(4, 4, 0)) {
if ((adev->ip_versions[OSSSYS_HWIP][0] == IP_VERSION(4, 4, 0)) ||
(adev->ip_versions[OSSSYS_HWIP][0] == IP_VERSION(4, 4, 2))) {
ih_chicken = RREG32_SOC15(OSSSYS, 0, mmIH_CHICKEN_ALDEBARAN);
if (adev->irq.ih.use_bus_addr) {
ih_chicken = REG_SET_FIELD(ih_chicken, IH_CHICKEN,
@ -551,12 +552,14 @@ static int vega20_ih_sw_init(void *handle)
adev->irq.ih1.use_doorbell = true;
adev->irq.ih1.doorbell_index = (adev->doorbell_index.ih + 1) << 1;
r = amdgpu_ih_ring_init(adev, &adev->irq.ih2, PAGE_SIZE, true);
if (r)
return r;
if (adev->ip_versions[OSSSYS_HWIP][0] != IP_VERSION(4, 4, 2)) {
r = amdgpu_ih_ring_init(adev, &adev->irq.ih2, PAGE_SIZE, true);
if (r)
return r;
adev->irq.ih2.use_doorbell = true;
adev->irq.ih2.doorbell_index = (adev->doorbell_index.ih + 2) << 1;
adev->irq.ih2.use_doorbell = true;
adev->irq.ih2.doorbell_index = (adev->doorbell_index.ih + 2) << 1;
}
/* initialize ih control registers offset */
vega20_ih_init_register_offset(adev);

View File

@ -1105,24 +1105,6 @@ static int vi_set_vce_clocks(struct amdgpu_device *adev, u32 evclk, u32 ecclk)
return 0;
}
static void vi_pcie_gen3_enable(struct amdgpu_device *adev)
{
if (pci_is_root_bus(adev->pdev->bus))
return;
if (amdgpu_pcie_gen2 == 0)
return;
if (adev->flags & AMD_IS_APU)
return;
if (!(adev->pm.pcie_gen_mask & (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2 |
CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)))
return;
/* todo */
}
static void vi_enable_aspm(struct amdgpu_device *adev)
{
u32 data, orig;
@ -1743,8 +1725,6 @@ static int vi_common_hw_init(void *handle)
/* move the golden regs per IP block */
vi_init_golden_registers(adev);
/* enable pcie gen2/3 link */
vi_pcie_gen3_enable(adev);
/* enable aspm */
vi_program_aspm(adev);
/* enable the doorbell aperture */

View File

@ -1312,14 +1312,14 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep,
args->n_success = i+1;
}
mutex_unlock(&p->mutex);
err = amdgpu_amdkfd_gpuvm_sync_memory(dev->adev, (struct kgd_mem *) mem, true);
if (err) {
pr_debug("Sync memory failed, wait interrupted by user signal\n");
goto sync_memory_failed;
}
mutex_unlock(&p->mutex);
/* Flush TLBs after waiting for the page table updates to complete */
for (i = 0; i < args->n_devices; i++) {
peer_pdd = kfd_process_device_data_by_id(p, devices_arr[i]);
@ -1335,9 +1335,9 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep,
bind_process_to_device_failed:
get_mem_obj_from_handle_failed:
map_memory_to_gpu_failed:
sync_memory_failed:
mutex_unlock(&p->mutex);
copy_from_user_failed:
sync_memory_failed:
kfree(devices_arr);
return err;
@ -1351,6 +1351,7 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep,
void *mem;
long err = 0;
uint32_t *devices_arr = NULL, i;
bool flush_tlb;
if (!args->n_devices) {
pr_debug("Device IDs array empty\n");
@ -1403,16 +1404,19 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep,
}
args->n_success = i+1;
}
mutex_unlock(&p->mutex);
if (kfd_flush_tlb_after_unmap(pdd->dev)) {
flush_tlb = kfd_flush_tlb_after_unmap(pdd->dev);
if (flush_tlb) {
err = amdgpu_amdkfd_gpuvm_sync_memory(pdd->dev->adev,
(struct kgd_mem *) mem, true);
if (err) {
pr_debug("Sync memory failed, wait interrupted by user signal\n");
goto sync_memory_failed;
}
}
mutex_unlock(&p->mutex);
if (flush_tlb) {
/* Flush TLBs after waiting for the page table updates to complete */
for (i = 0; i < args->n_devices; i++) {
peer_pdd = kfd_process_device_data_by_id(p, devices_arr[i]);
@ -1428,9 +1432,9 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep,
bind_process_to_device_failed:
get_mem_obj_from_handle_failed:
unmap_memory_from_gpu_failed:
sync_memory_failed:
mutex_unlock(&p->mutex);
copy_from_user_failed:
sync_memory_failed:
kfree(devices_arr);
return err;
}
@ -1586,6 +1590,58 @@ static int kfd_ioctl_import_dmabuf(struct file *filep,
return r;
}
static int kfd_ioctl_export_dmabuf(struct file *filep,
struct kfd_process *p, void *data)
{
struct kfd_ioctl_export_dmabuf_args *args = data;
struct kfd_process_device *pdd;
struct dma_buf *dmabuf;
struct kfd_dev *dev;
void *mem;
int ret = 0;
dev = kfd_device_by_id(GET_GPU_ID(args->handle));
if (!dev)
return -EINVAL;
mutex_lock(&p->mutex);
pdd = kfd_get_process_device_data(dev, p);
if (!pdd) {
ret = -EINVAL;
goto err_unlock;
}
mem = kfd_process_device_translate_handle(pdd,
GET_IDR_HANDLE(args->handle));
if (!mem) {
ret = -EINVAL;
goto err_unlock;
}
ret = amdgpu_amdkfd_gpuvm_export_dmabuf(mem, &dmabuf);
mutex_unlock(&p->mutex);
if (ret)
goto err_out;
ret = dma_buf_fd(dmabuf, args->flags);
if (ret < 0) {
dma_buf_put(dmabuf);
goto err_out;
}
/* dma_buf_fd assigns the reference count to the fd, no need to
* put the reference here.
*/
args->dmabuf_fd = ret;
return 0;
err_unlock:
mutex_unlock(&p->mutex);
err_out:
return ret;
}
/* Handle requests for watching SMI events */
static int kfd_ioctl_smi_events(struct file *filep,
struct kfd_process *p, void *data)
@ -2768,6 +2824,9 @@ static const struct amdkfd_ioctl_desc amdkfd_ioctls[] = {
AMDKFD_IOCTL_DEF(AMDKFD_IOC_AVAILABLE_MEMORY,
kfd_ioctl_get_available_memory, 0),
AMDKFD_IOCTL_DEF(AMDKFD_IOC_EXPORT_DMABUF,
kfd_ioctl_export_dmabuf, 0),
};
#define AMDKFD_CORE_IOCTL_COUNT ARRAY_SIZE(amdkfd_ioctls)

View File

@ -59,6 +59,7 @@ static int kfd_gtt_sa_init(struct kfd_dev *kfd, unsigned int buf_size,
unsigned int chunk_size);
static void kfd_gtt_sa_fini(struct kfd_dev *kfd);
static int kfd_resume_iommu(struct kfd_dev *kfd);
static int kfd_resume(struct kfd_dev *kfd);
static void kfd_device_info_set_sdma_info(struct kfd_dev *kfd)
@ -624,7 +625,7 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd,
svm_migrate_init(kfd->adev);
if (kgd2kfd_resume_iommu(kfd))
if (kfd_resume_iommu(kfd))
goto device_iommu_error;
if (kfd_resume(kfd))
@ -772,6 +773,14 @@ int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm)
}
int kgd2kfd_resume_iommu(struct kfd_dev *kfd)
{
if (!kfd->init_complete)
return 0;
return kfd_resume_iommu(kfd);
}
static int kfd_resume_iommu(struct kfd_dev *kfd)
{
int err = 0;

View File

@ -289,7 +289,7 @@ static unsigned long svm_migrate_unsuccessful_pages(struct migrate_vma *migrate)
static int
svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
struct migrate_vma *migrate, struct dma_fence **mfence,
dma_addr_t *scratch)
dma_addr_t *scratch, uint64_t ttm_res_offset)
{
uint64_t npages = migrate->npages;
struct device *dev = adev->dev;
@ -299,19 +299,13 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
uint64_t i, j;
int r;
pr_debug("svms 0x%p [0x%lx 0x%lx]\n", prange->svms, prange->start,
prange->last);
pr_debug("svms 0x%p [0x%lx 0x%lx 0x%llx]\n", prange->svms, prange->start,
prange->last, ttm_res_offset);
src = scratch;
dst = (uint64_t *)(scratch + npages);
r = svm_range_vram_node_new(adev, prange, true);
if (r) {
dev_dbg(adev->dev, "fail %d to alloc vram\n", r);
goto out;
}
amdgpu_res_first(prange->ttm_res, prange->offset << PAGE_SHIFT,
amdgpu_res_first(prange->ttm_res, ttm_res_offset,
npages << PAGE_SHIFT, &cursor);
for (i = j = 0; i < npages; i++) {
struct page *spage;
@ -391,14 +385,14 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
migrate->dst[i + 3] = 0;
}
#endif
out:
return r;
}
static long
svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
struct vm_area_struct *vma, uint64_t start,
uint64_t end, uint32_t trigger)
uint64_t end, uint32_t trigger, uint64_t ttm_res_offset)
{
struct kfd_process *p = container_of(prange->svms, struct kfd_process, svms);
uint64_t npages = (end - start) >> PAGE_SHIFT;
@ -451,7 +445,7 @@ svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
else
pr_debug("0x%lx pages migrated\n", cpages);
r = svm_migrate_copy_to_vram(adev, prange, &migrate, &mfence, scratch);
r = svm_migrate_copy_to_vram(adev, prange, &migrate, &mfence, scratch, ttm_res_offset);
migrate_vma_pages(&migrate);
pr_debug("successful/cpages/npages 0x%lx/0x%lx/0x%lx\n",
@ -499,6 +493,7 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,
unsigned long addr, start, end;
struct vm_area_struct *vma;
struct amdgpu_device *adev;
uint64_t ttm_res_offset;
unsigned long cpages = 0;
long r = 0;
@ -520,6 +515,13 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,
start = prange->start << PAGE_SHIFT;
end = (prange->last + 1) << PAGE_SHIFT;
r = svm_range_vram_node_new(adev, prange, true);
if (r) {
dev_dbg(adev->dev, "fail %ld to alloc vram\n", r);
return r;
}
ttm_res_offset = prange->offset << PAGE_SHIFT;
for (addr = start; addr < end;) {
unsigned long next;
@ -528,18 +530,21 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,
break;
next = min(vma->vm_end, end);
r = svm_migrate_vma_to_vram(adev, prange, vma, addr, next, trigger);
r = svm_migrate_vma_to_vram(adev, prange, vma, addr, next, trigger, ttm_res_offset);
if (r < 0) {
pr_debug("failed %ld to migrate\n", r);
break;
} else {
cpages += r;
}
ttm_res_offset += next - addr;
addr = next;
}
if (cpages)
prange->actual_loc = best_loc;
else
svm_range_vram_node_free(prange);
return r < 0 ? r : 0;
}

View File

@ -77,6 +77,7 @@ static int kfd_init(void)
static void kfd_exit(void)
{
kfd_cleanup_processes();
kfd_debugfs_fini();
kfd_process_destroy_wq();
kfd_procfs_shutdown();

View File

@ -928,6 +928,7 @@ bool kfd_dev_is_large_bar(struct kfd_dev *dev);
int kfd_process_create_wq(void);
void kfd_process_destroy_wq(void);
void kfd_cleanup_processes(void);
struct kfd_process *kfd_create_process(struct file *filep);
struct kfd_process *kfd_get_process(const struct task_struct *task);
struct kfd_process *kfd_lookup_process_by_pasid(u32 pasid);

View File

@ -344,7 +344,7 @@ static const struct sysfs_ops kfd_procfs_ops = {
.show = kfd_procfs_show,
};
static struct kobj_type procfs_type = {
static const struct kobj_type procfs_type = {
.release = kfd_procfs_kobj_release,
.sysfs_ops = &kfd_procfs_ops,
};
@ -469,7 +469,7 @@ static const struct sysfs_ops procfs_queue_ops = {
.show = kfd_procfs_queue_show,
};
static struct kobj_type procfs_queue_type = {
static const struct kobj_type procfs_queue_type = {
.sysfs_ops = &procfs_queue_ops,
.default_groups = procfs_queue_groups,
};
@ -478,7 +478,7 @@ static const struct sysfs_ops procfs_stats_ops = {
.show = kfd_procfs_stats_show,
};
static struct kobj_type procfs_stats_type = {
static const struct kobj_type procfs_stats_type = {
.sysfs_ops = &procfs_stats_ops,
.release = kfd_procfs_kobj_release,
};
@ -487,7 +487,7 @@ static const struct sysfs_ops sysfs_counters_ops = {
.show = kfd_sysfs_counters_show,
};
static struct kobj_type sysfs_counters_type = {
static const struct kobj_type sysfs_counters_type = {
.sysfs_ops = &sysfs_counters_ops,
.release = kfd_procfs_kobj_release,
};
@ -1167,6 +1167,17 @@ static void kfd_process_free_notifier(struct mmu_notifier *mn)
kfd_unref_process(container_of(mn, struct kfd_process, mmu_notifier));
}
static void kfd_process_notifier_release_internal(struct kfd_process *p)
{
cancel_delayed_work_sync(&p->eviction_work);
cancel_delayed_work_sync(&p->restore_work);
/* Indicate to other users that MM is no longer valid */
p->mm = NULL;
mmu_notifier_put(&p->mmu_notifier);
}
static void kfd_process_notifier_release(struct mmu_notifier *mn,
struct mm_struct *mm)
{
@ -1181,17 +1192,22 @@ static void kfd_process_notifier_release(struct mmu_notifier *mn,
return;
mutex_lock(&kfd_processes_mutex);
/*
* Do early return if table is empty.
*
* This could potentially happen if this function is called concurrently
* by mmu_notifier and by kfd_cleanup_pocesses.
*
*/
if (hash_empty(kfd_processes_table)) {
mutex_unlock(&kfd_processes_mutex);
return;
}
hash_del_rcu(&p->kfd_processes);
mutex_unlock(&kfd_processes_mutex);
synchronize_srcu(&kfd_processes_srcu);
cancel_delayed_work_sync(&p->eviction_work);
cancel_delayed_work_sync(&p->restore_work);
/* Indicate to other users that MM is no longer valid */
p->mm = NULL;
mmu_notifier_put(&p->mmu_notifier);
kfd_process_notifier_release_internal(p);
}
static const struct mmu_notifier_ops kfd_process_mmu_notifier_ops = {
@ -1200,6 +1216,43 @@ static const struct mmu_notifier_ops kfd_process_mmu_notifier_ops = {
.free_notifier = kfd_process_free_notifier,
};
/*
* This code handles the case when driver is being unloaded before all
* mm_struct are released. We need to safely free the kfd_process and
* avoid race conditions with mmu_notifier that might try to free them.
*
*/
void kfd_cleanup_processes(void)
{
struct kfd_process *p;
struct hlist_node *p_temp;
unsigned int temp;
HLIST_HEAD(cleanup_list);
/*
* Move all remaining kfd_process from the process table to a
* temp list for processing. Once done, callback from mmu_notifier
* release will not see the kfd_process in the table and do early return,
* avoiding double free issues.
*/
mutex_lock(&kfd_processes_mutex);
hash_for_each_safe(kfd_processes_table, temp, p_temp, p, kfd_processes) {
hash_del_rcu(&p->kfd_processes);
synchronize_srcu(&kfd_processes_srcu);
hlist_add_head(&p->kfd_processes, &cleanup_list);
}
mutex_unlock(&kfd_processes_mutex);
hlist_for_each_entry_safe(p, p_temp, &cleanup_list, kfd_processes)
kfd_process_notifier_release_internal(p);
/*
* Ensures that all outstanding free_notifier get called, triggering
* the release of the kfd_process struct.
*/
mmu_notifier_synchronize();
}
static int kfd_process_init_cwsr_apu(struct kfd_process *p, struct file *filep)
{
unsigned long offset;

View File

@ -218,8 +218,8 @@ static int init_user_queue(struct process_queue_manager *pqm,
return 0;
cleanup:
if (dev->shared_resources.enable_mes)
uninit_queue(*q);
uninit_queue(*q);
*q = NULL;
return retval;
}

View File

@ -278,7 +278,7 @@ static const struct sysfs_ops sysprops_ops = {
.show = sysprops_show,
};
static struct kobj_type sysprops_type = {
static const struct kobj_type sysprops_type = {
.release = kfd_topology_kobj_release,
.sysfs_ops = &sysprops_ops,
};
@ -318,7 +318,7 @@ static const struct sysfs_ops iolink_ops = {
.show = iolink_show,
};
static struct kobj_type iolink_type = {
static const struct kobj_type iolink_type = {
.release = kfd_topology_kobj_release,
.sysfs_ops = &iolink_ops,
};
@ -350,7 +350,7 @@ static const struct sysfs_ops mem_ops = {
.show = mem_show,
};
static struct kobj_type mem_type = {
static const struct kobj_type mem_type = {
.release = kfd_topology_kobj_release,
.sysfs_ops = &mem_ops,
};
@ -395,7 +395,7 @@ static const struct sysfs_ops cache_ops = {
.show = kfd_cache_show,
};
static struct kobj_type cache_type = {
static const struct kobj_type cache_type = {
.release = kfd_topology_kobj_release,
.sysfs_ops = &cache_ops,
};
@ -566,7 +566,7 @@ static const struct sysfs_ops node_ops = {
.show = node_show,
};
static struct kobj_type node_type = {
static const struct kobj_type node_type = {
.release = kfd_topology_kobj_release,
.sysfs_ops = &node_ops,
};

View File

@ -8,7 +8,7 @@ config DRM_AMD_DC
depends on BROKEN || !CC_IS_CLANG || X86_64 || SPARC64 || ARM64
select SND_HDA_COMPONENT if SND_HDA_CORE
# !CC_IS_CLANG: https://github.com/ClangBuiltLinux/linux/issues/1752
select DRM_AMD_DC_DCN if (X86 || PPC_LONG_DOUBLE_128 || (ARM64 && KERNEL_MODE_NEON && !CC_IS_CLANG))
select DRM_AMD_DC_FP if (X86 || PPC64 || (ARM64 && KERNEL_MODE_NEON && !CC_IS_CLANG))
help
Choose this option if you want to use the new display engine
support for AMDGPU. This adds required support for Vega and
@ -20,16 +20,10 @@ config DRM_AMD_DC
panic on most architectures. We'll revert this when the following bug report
has been resolved: https://github.com/llvm/llvm-project/issues/41896.
config DRM_AMD_DC_DCN
config DRM_AMD_DC_FP
def_bool n
help
Raven, Navi, and newer family support for display engine
config DRM_AMD_DC_HDCP
bool "Enable HDCP support in DC"
depends on DRM_AMD_DC
help
Choose this option if you want to support HDCP authentication.
Floating point support, required for DCN-based SoCs
config DRM_AMD_DC_SI
bool "AMD DC support for Southern Islands ASICs"
@ -50,7 +44,7 @@ config DEBUG_KERNEL_DC
config DRM_AMD_SECURE_DISPLAY
bool "Enable secure display support"
depends on DEBUG_FS
depends on DRM_AMD_DC_DCN
depends on DRM_AMD_DC_FP
help
Choose this option if you want to
support secure display

View File

@ -36,18 +36,14 @@ subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/info_packet
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/power
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dmub/inc
ifdef CONFIG_DRM_AMD_DC_HDCP
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/hdcp
endif
#TODO: remove when Timing Sync feature is complete
subdir-ccflags-y += -DBUILD_FEATURE_TIMING_SYNC=0
DAL_LIBS = amdgpu_dm dc modules/freesync modules/color modules/info_packet modules/power dmub/src
ifdef CONFIG_DRM_AMD_DC_HDCP
DAL_LIBS += modules/hdcp
endif
AMD_DAL = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DISPLAY_PATH)/,$(DAL_LIBS)))

View File

@ -33,7 +33,7 @@ AMDGPUDM = \
amdgpu_dm_mst_types.o \
amdgpu_dm_color.o
ifdef CONFIG_DRM_AMD_DC_DCN
ifdef CONFIG_DRM_AMD_DC_FP
AMDGPUDM += dc_fpu.o
endif
@ -41,9 +41,7 @@ ifneq ($(CONFIG_DRM_AMD_DC),)
AMDGPUDM += amdgpu_dm_services.o amdgpu_dm_helpers.o amdgpu_dm_pp_smu.o amdgpu_dm_psr.o
endif
ifdef CONFIG_DRM_AMD_DC_HDCP
AMDGPUDM += amdgpu_dm_hdcp.o
endif
ifneq ($(CONFIG_DEBUG_FS),)
AMDGPUDM += amdgpu_dm_crc.o amdgpu_dm_debugfs.o

View File

@ -52,10 +52,8 @@
#include "amdgpu_dm.h"
#include "amdgpu_dm_plane.h"
#include "amdgpu_dm_crtc.h"
#ifdef CONFIG_DRM_AMD_DC_HDCP
#include "amdgpu_dm_hdcp.h"
#include <drm/display/drm_hdcp_helper.h>
#endif
#include "amdgpu_pm.h"
#include "amdgpu_atombios.h"
@ -344,12 +342,52 @@ static inline bool is_dc_timing_adjust_needed(struct dm_crtc_state *old_state,
{
if (new_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED)
return true;
else if (amdgpu_dm_vrr_active(old_state) != amdgpu_dm_vrr_active(new_state))
else if (amdgpu_dm_crtc_vrr_active(old_state) != amdgpu_dm_crtc_vrr_active(new_state))
return true;
else
return false;
}
static inline void reverse_planes_order(struct dc_surface_update *array_of_surface_update,
int planes_count)
{
int i, j;
for (i = 0, j = planes_count - 1; i < j; i++, j--)
swap(array_of_surface_update[i], array_of_surface_update[j]);
}
/**
* update_planes_and_stream_adapter() - Send planes to be updated in DC
*
* DC has a generic way to update planes and stream via
* dc_update_planes_and_stream function; however, DM might need some
* adjustments and preparation before calling it. This function is a wrapper
* for the dc_update_planes_and_stream that does any required configuration
* before passing control to DC.
*/
static inline bool update_planes_and_stream_adapter(struct dc *dc,
int update_type,
int planes_count,
struct dc_stream_state *stream,
struct dc_stream_update *stream_update,
struct dc_surface_update *array_of_surface_update)
{
reverse_planes_order(array_of_surface_update, planes_count);
/*
* Previous frame finished and HW is ready for optimization.
*/
if (update_type == UPDATE_TYPE_FAST)
dc_post_update_surfaces_to_stream(dc);
return dc_update_planes_and_stream(dc,
array_of_surface_update,
planes_count,
stream,
stream_update);
}
/**
* dm_pflip_high_irq() - Handle pageflip interrupt
* @interrupt_params: ignored
@ -394,7 +432,7 @@ static void dm_pflip_high_irq(void *interrupt_params)
WARN_ON(!e);
vrr_active = amdgpu_dm_vrr_active_irq(amdgpu_crtc);
vrr_active = amdgpu_dm_crtc_vrr_active_irq(amdgpu_crtc);
/* Fixed refresh rate, or VRR scanout position outside front-porch? */
if (!vrr_active ||
@ -468,7 +506,7 @@ static void dm_vupdate_high_irq(void *interrupt_params)
acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VUPDATE);
if (acrtc) {
vrr_active = amdgpu_dm_vrr_active_irq(acrtc);
vrr_active = amdgpu_dm_crtc_vrr_active_irq(acrtc);
drm_dev = acrtc->base.dev;
vblank = &drm_dev->vblank[acrtc->base.index];
previous_timestamp = atomic64_read(&irq_params->previous_timestamp);
@ -492,7 +530,7 @@ static void dm_vupdate_high_irq(void *interrupt_params)
* if a pageflip happened inside front-porch.
*/
if (vrr_active) {
dm_crtc_handle_vblank(acrtc);
amdgpu_dm_crtc_handle_vblank(acrtc);
/* BTR processing for pre-DCE12 ASICs */
if (acrtc->dm_irq_params.stream &&
@ -532,7 +570,7 @@ static void dm_crtc_high_irq(void *interrupt_params)
if (!acrtc)
return;
vrr_active = amdgpu_dm_vrr_active_irq(acrtc);
vrr_active = amdgpu_dm_crtc_vrr_active_irq(acrtc);
DC_LOG_VBLANK("crtc:%d, vupdate-vrr:%d, planes:%d\n", acrtc->crtc_id,
vrr_active, acrtc->dm_irq_params.active_planes);
@ -544,7 +582,7 @@ static void dm_crtc_high_irq(void *interrupt_params)
* to dm_vupdate_high_irq after end of front-porch.
*/
if (!vrr_active)
dm_crtc_handle_vblank(acrtc);
amdgpu_dm_crtc_handle_vblank(acrtc);
/**
* Following stuff must happen at start of vblank, for crc
@ -675,7 +713,14 @@ static void dmub_hpd_callback(struct amdgpu_device *adev,
drm_for_each_connector_iter(connector, &iter) {
aconnector = to_amdgpu_dm_connector(connector);
if (link && aconnector->dc_link == link) {
DRM_INFO("DMUB HPD callback: link_index=%u\n", link_index);
if (notify->type == DMUB_NOTIFICATION_HPD)
DRM_INFO("DMUB HPD callback: link_index=%u\n", link_index);
else if (notify->type == DMUB_NOTIFICATION_HPD_IRQ)
DRM_INFO("DMUB HPD IRQ callback: link_index=%u\n", link_index);
else
DRM_WARN("DMUB Unknown HPD callback type %d, link_index=%u\n",
notify->type, link_index);
hpd_aconnector = aconnector;
break;
}
@ -1488,9 +1533,7 @@ static void retrieve_dmi_info(struct amdgpu_display_manager *dm)
static int amdgpu_dm_init(struct amdgpu_device *adev)
{
struct dc_init_data init_data;
#ifdef CONFIG_DRM_AMD_DC_HDCP
struct dc_callback_init init_params;
#endif
int r;
adev->dm.ddev = adev_to_drm(adev);
@ -1498,9 +1541,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
/* Zero all the fields */
memset(&init_data, 0, sizeof(init_data));
#ifdef CONFIG_DRM_AMD_DC_HDCP
memset(&init_params, 0, sizeof(init_params));
#endif
mutex_init(&adev->dm.dpia_aux_lock);
mutex_init(&adev->dm.dc_lock);
@ -1726,7 +1767,6 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
DRM_ERROR("amdgpu: failed to initialize vblank_workqueue.\n");
}
#ifdef CONFIG_DRM_AMD_DC_HDCP
if (adev->dm.dc->caps.max_links > 0 && adev->family >= AMDGPU_FAMILY_RV) {
adev->dm.hdcp_workqueue = hdcp_create_workqueue(adev, &init_params.cp_psp, adev->dm.dc);
@ -1737,7 +1777,6 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
dc_init_callbacks(adev->dm.dc, &init_params);
}
#endif
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
adev->dm.secure_display_ctxs = amdgpu_dm_crtc_secure_display_create_contexts(adev);
if (!adev->dm.secure_display_ctxs) {
@ -1844,7 +1883,6 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
adev->dm.secure_display_ctxs = NULL;
}
#endif
#ifdef CONFIG_DRM_AMD_DC_HDCP
if (adev->dm.hdcp_workqueue) {
hdcp_destroy(&adev->dev->kobj, adev->dm.hdcp_workqueue);
adev->dm.hdcp_workqueue = NULL;
@ -1852,7 +1890,6 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
if (adev->dm.dc)
dc_deinit_callbacks(adev->dm.dc);
#endif
dc_dmub_srv_destroy(&adev->dm.dc->ctx->dmub_srv);
@ -2273,7 +2310,7 @@ static int dm_late_init(void *handle)
struct dc_link *edp_links[MAX_NUM_EDP];
int edp_num;
get_edp_links(adev->dm.dc, edp_links, &edp_num);
dc_get_edp_links(adev->dm.dc, edp_links, &edp_num);
for (i = 0; i < edp_num; i++) {
if (!dmub_init_abm_config(adev->dm.dc->res_pool, params, i))
return -EINVAL;
@ -2449,11 +2486,11 @@ static void dm_gpureset_toggle_interrupts(struct amdgpu_device *adev,
enable ? "enable" : "disable");
if (enable) {
rc = dm_enable_vblank(&acrtc->base);
rc = amdgpu_dm_crtc_enable_vblank(&acrtc->base);
if (rc)
DRM_WARN("Failed to enable vblank interrupts\n");
} else {
dm_disable_vblank(&acrtc->base);
amdgpu_dm_crtc_disable_vblank(&acrtc->base);
}
}
@ -2496,7 +2533,7 @@ static enum dc_status amdgpu_dm_commit_zero_streams(struct dc *dc)
goto fail;
}
res = dc_commit_state(dc, context);
res = dc_commit_streams(dc, context->streams, context->stream_count);
fail:
dc_release_state(context);
@ -2682,10 +2719,13 @@ static void dm_gpureset_commit_state(struct dc_state *dc_state,
bundle->surface_updates[m].surface->force_full_update =
true;
}
dc_commit_updates_for_stream(
dm->dc, bundle->surface_updates,
dc_state->stream_status->plane_count,
dc_state->streams[k], &bundle->stream_update, dc_state);
update_planes_and_stream_adapter(dm->dc,
UPDATE_TYPE_FULL,
dc_state->stream_status->plane_count,
dc_state->streams[k],
&bundle->stream_update,
bundle->surface_updates);
}
cleanup:
@ -2755,7 +2795,7 @@ static int dm_resume(void *handle)
dc_enable_dmub_outbox(adev->dm.dc);
}
WARN_ON(!dc_commit_state(dm->dc, dc_state));
WARN_ON(!dc_commit_streams(dm->dc, dc_state->streams, dc_state->stream_count));
dm_gpureset_commit_state(dm->cached_dc_state, dm);
@ -2923,7 +2963,7 @@ const struct amdgpu_ip_block_version dm_ip_block =
static const struct drm_mode_config_funcs amdgpu_dm_mode_funcs = {
.fb_create = amdgpu_display_user_framebuffer_create,
.get_format_info = amd_get_format_info,
.get_format_info = amdgpu_dm_plane_get_format_info,
.atomic_check = amdgpu_dm_atomic_check,
.atomic_commit = drm_atomic_helper_commit,
};
@ -2974,8 +3014,14 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
caps->aux_support = true;
luminance_range = &conn_base->display_info.luminance_range;
caps->aux_min_input_signal = luminance_range->min_luminance;
caps->aux_max_input_signal = luminance_range->max_luminance;
if (luminance_range->max_luminance) {
caps->aux_min_input_signal = luminance_range->min_luminance;
caps->aux_max_input_signal = luminance_range->max_luminance;
} else {
caps->aux_min_input_signal = 0;
caps->aux_max_input_signal = 512;
}
}
void amdgpu_dm_update_connector_after_detect(
@ -3111,11 +3157,9 @@ void amdgpu_dm_update_connector_after_detect(
aconnector->edid = NULL;
kfree(aconnector->timing_requested);
aconnector->timing_requested = NULL;
#ifdef CONFIG_DRM_AMD_DC_HDCP
/* Set CP to DESIRED if it was ENABLED, so we can re-enable it again on hotplug */
if (connector->state->content_protection == DRM_MODE_CONTENT_PROTECTION_ENABLED)
connector->state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
#endif
}
mutex_unlock(&dev->mode_config.mutex);
@ -3132,9 +3176,7 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector)
struct drm_device *dev = connector->dev;
enum dc_connection_type new_connection_type = dc_connection_none;
struct amdgpu_device *adev = drm_to_adev(dev);
#ifdef CONFIG_DRM_AMD_DC_HDCP
struct dm_connector_state *dm_con_state = to_dm_connector_state(connector->state);
#endif
bool ret = false;
if (adev->dm.disable_hpd_irq)
@ -3146,12 +3188,10 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector)
*/
mutex_lock(&aconnector->hpd_lock);
#ifdef CONFIG_DRM_AMD_DC_HDCP
if (adev->dm.hdcp_workqueue) {
hdcp_reset_display(adev->dm.hdcp_workqueue, aconnector->dc_link->link_index);
dm_con_state->update_hdcp = true;
}
#endif
if (aconnector->fake_enable)
aconnector->fake_enable = false;
@ -3398,12 +3438,10 @@ static void handle_hpd_rx_irq(void *param)
}
}
}
#ifdef CONFIG_DRM_AMD_DC_HDCP
if (hpd_irq_data.bytes.device_service_irq.bits.CP_IRQ) {
if (adev->dm.hdcp_workqueue)
hdcp_handle_cpirq(adev->dm.hdcp_workqueue, aconnector->base.index);
}
#endif
if (dc_link->type != dc_connection_mst_branch)
drm_dp_cec_irq(&aconnector->dm_dp_aux.aux);
@ -4320,9 +4358,6 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
if (plane->type != DC_PLANE_TYPE_DCN_UNIVERSAL)
continue;
if (!plane->blends_with_above || !plane->blends_with_below)
continue;
if (!plane->pixel_format_support.argb8888)
continue;
@ -4947,7 +4982,7 @@ fill_dc_plane_info_and_addr(struct amdgpu_device *adev,
if (ret)
return ret;
ret = fill_plane_buffer_attributes(adev, afb, plane_info->format,
ret = amdgpu_dm_plane_fill_plane_buffer_attributes(adev, afb, plane_info->format,
plane_info->rotation, tiling_flags,
&plane_info->tiling_info,
&plane_info->plane_size,
@ -4956,7 +4991,7 @@ fill_dc_plane_info_and_addr(struct amdgpu_device *adev,
if (ret)
return ret;
fill_blending_from_plane_state(
amdgpu_dm_plane_fill_blending_from_plane_state(
plane_state, &plane_info->per_pixel_alpha, &plane_info->pre_multiplied_alpha,
&plane_info->global_alpha, &plane_info->global_alpha_value);
@ -4975,7 +5010,7 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
int ret;
bool force_disable_dcc = false;
ret = fill_dc_scaling_info(adev, plane_state, &scaling_info);
ret = amdgpu_dm_plane_fill_dc_scaling_info(adev, plane_state, &scaling_info);
if (ret)
return ret;
@ -5105,9 +5140,9 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
for (; flip_addrs->dirty_rect_count < num_clips; clips++)
fill_dc_dirty_rect(new_plane_state->plane,
&dirty_rects[i], clips->x1,
clips->y1, clips->x2 - clips->x1,
clips->y2 - clips->y1,
&dirty_rects[flip_addrs->dirty_rect_count],
clips->x1, clips->y1,
clips->x2 - clips->x1, clips->y2 - clips->y1,
&flip_addrs->dirty_rect_count,
false);
return;
@ -5753,7 +5788,6 @@ static bool is_freesync_video_mode(const struct drm_display_mode *mode,
return true;
}
#if defined(CONFIG_DRM_AMD_DC_DCN)
static void update_dsc_caps(struct amdgpu_dm_connector *aconnector,
struct dc_sink *sink, struct dc_stream_state *stream,
struct dsc_dec_dpcd_caps *dsc_caps)
@ -5784,6 +5818,10 @@ static void apply_dsc_policy_for_edp(struct amdgpu_dm_connector *aconnector,
struct dc *dc = sink->ctx->dc;
struct dc_dsc_bw_range bw_range = {0};
struct dc_dsc_config dsc_cfg = {0};
struct dc_dsc_config_options dsc_options = {0};
dc_dsc_get_default_config_option(dc, &dsc_options);
dsc_options.max_target_bpp_limit_override_x16 = max_dsc_target_bpp_limit_override * 16;
verified_link_cap = dc_link_get_link_cap(stream->link);
link_bw_in_kbps = dc_link_bandwidth_kbps(stream->link, verified_link_cap);
@ -5806,8 +5844,7 @@ static void apply_dsc_policy_for_edp(struct amdgpu_dm_connector *aconnector,
if (bw_range.max_kbps < link_bw_in_kbps) {
if (dc_dsc_compute_config(dc->res_pool->dscs[0],
dsc_caps,
dc->debug.dsc_min_slice_height_override,
max_dsc_target_bpp_limit_override,
&dsc_options,
0,
&stream->timing,
&dsc_cfg)) {
@ -5821,8 +5858,7 @@ static void apply_dsc_policy_for_edp(struct amdgpu_dm_connector *aconnector,
if (dc_dsc_compute_config(dc->res_pool->dscs[0],
dsc_caps,
dc->debug.dsc_min_slice_height_override,
max_dsc_target_bpp_limit_override,
&dsc_options,
link_bw_in_kbps,
&stream->timing,
&dsc_cfg)) {
@ -5843,6 +5879,10 @@ static void apply_dsc_policy_for_stream(struct amdgpu_dm_connector *aconnector,
u32 dsc_max_supported_bw_in_kbps;
u32 max_dsc_target_bpp_limit_override =
drm_connector->display_info.max_dsc_bpp;
struct dc_dsc_config_options dsc_options = {0};
dc_dsc_get_default_config_option(dc, &dsc_options);
dsc_options.max_target_bpp_limit_override_x16 = max_dsc_target_bpp_limit_override * 16;
link_bandwidth_kbps = dc_link_bandwidth_kbps(aconnector->dc_link,
dc_link_get_link_cap(aconnector->dc_link));
@ -5861,8 +5901,7 @@ static void apply_dsc_policy_for_stream(struct amdgpu_dm_connector *aconnector,
if (sink->link->dpcd_caps.dongle_type == DISPLAY_DONGLE_NONE) {
if (dc_dsc_compute_config(aconnector->dc_link->ctx->dc->res_pool->dscs[0],
dsc_caps,
aconnector->dc_link->ctx->dc->debug.dsc_min_slice_height_override,
max_dsc_target_bpp_limit_override,
&dsc_options,
link_bandwidth_kbps,
&stream->timing,
&stream->timing.dsc_cfg)) {
@ -5879,8 +5918,7 @@ static void apply_dsc_policy_for_stream(struct amdgpu_dm_connector *aconnector,
dsc_max_supported_bw_in_kbps > 0)
if (dc_dsc_compute_config(aconnector->dc_link->ctx->dc->res_pool->dscs[0],
dsc_caps,
aconnector->dc_link->ctx->dc->debug.dsc_min_slice_height_override,
max_dsc_target_bpp_limit_override,
&dsc_options,
dsc_max_supported_bw_in_kbps,
&stream->timing,
&stream->timing.dsc_cfg)) {
@ -5904,7 +5942,6 @@ static void apply_dsc_policy_for_stream(struct amdgpu_dm_connector *aconnector,
if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_bits_per_pixel)
stream->timing.dsc_cfg.bits_per_pixel = aconnector->dsc_settings.dsc_bits_per_pixel;
}
#endif /* CONFIG_DRM_AMD_DC_DCN */
static struct dc_stream_state *
create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
@ -5927,9 +5964,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
int mode_refresh;
int preferred_refresh = 0;
enum color_transfer_func tf = TRANSFER_FUNC_UNKNOWN;
#if defined(CONFIG_DRM_AMD_DC_DCN)
struct dsc_dec_dpcd_caps dsc_caps;
#endif
struct dc_sink *sink = NULL;
@ -6028,12 +6063,10 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
stream->timing = *aconnector->timing_requested;
}
#if defined(CONFIG_DRM_AMD_DC_DCN)
/* SST DSC determination policy */
update_dsc_caps(aconnector, sink, stream, &dsc_caps);
if (aconnector->dsc_settings.dsc_force_enable != DSC_CLK_FORCE_DISABLE && dsc_caps.is_dsc_supported)
apply_dsc_policy_for_stream(aconnector, sink, stream, &dsc_caps);
#endif
update_stream_scaling_settings(&mode, dm_state, stream);
@ -6759,7 +6792,6 @@ const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs = {
.atomic_check = dm_encoder_helper_atomic_check
};
#if defined(CONFIG_DRM_AMD_DC_DCN)
static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
struct dc_state *dc_state,
struct dsc_mst_fairness_vars *vars)
@ -6833,7 +6865,6 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
}
return 0;
}
#endif
static int to_drm_connector_type(enum signal_type st)
{
@ -7158,12 +7189,18 @@ static int amdgpu_dm_connector_get_modes(struct drm_connector *connector)
to_amdgpu_dm_connector(connector);
struct drm_encoder *encoder;
struct edid *edid = amdgpu_dm_connector->edid;
struct dc_link_settings *verified_link_cap =
&amdgpu_dm_connector->dc_link->verified_link_cap;
const struct dc *dc = amdgpu_dm_connector->dc_link->dc;
encoder = amdgpu_dm_connector_to_encoder(connector);
if (!drm_edid_is_valid(edid)) {
amdgpu_dm_connector->num_modes =
drm_add_modes_noedid(connector, 640, 480);
if (dc->link_srv->dp_get_encoding_format(verified_link_cap) == DP_128b_132b_ENCODING)
amdgpu_dm_connector->num_modes +=
drm_add_modes_noedid(connector, 1920, 1080);
} else {
amdgpu_dm_connector_ddc_get_modes(connector, edid);
amdgpu_dm_connector_add_common_modes(encoder, connector);
@ -7262,10 +7299,8 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
if (!aconnector->mst_root)
drm_connector_attach_vrr_capable_property(&aconnector->base);
#ifdef CONFIG_DRM_AMD_DC_HDCP
if (adev->dm.hdcp_workqueue)
drm_connector_attach_content_protection_property(&aconnector->base, true);
#endif
}
}
@ -7527,7 +7562,6 @@ is_scaling_state_different(const struct dm_connector_state *dm_state,
return false;
}
#ifdef CONFIG_DRM_AMD_DC_HDCP
static bool is_content_protection_different(struct drm_crtc_state *new_crtc_state,
struct drm_crtc_state *old_crtc_state,
struct drm_connector_state *new_conn_state,
@ -7647,7 +7681,6 @@ static bool is_content_protection_different(struct drm_crtc_state *new_crtc_stat
pr_debug("[HDCP_DM] DESIRED->ENABLED %s :false\n", __func__);
return false;
}
#endif
static void remove_stream(struct amdgpu_device *adev,
struct amdgpu_crtc *acrtc,
@ -7716,7 +7749,7 @@ static void update_freesync_state_on_stream(
&vrr_params);
if (adev->family < AMDGPU_FAMILY_AI &&
amdgpu_dm_vrr_active(new_crtc_state)) {
amdgpu_dm_crtc_vrr_active(new_crtc_state)) {
mod_freesync_handle_v_update(dm->freesync_module,
new_stream, &vrr_params);
@ -7834,8 +7867,8 @@ static void update_stream_irq_parameters(
static void amdgpu_dm_handle_vrr_transition(struct dm_crtc_state *old_state,
struct dm_crtc_state *new_state)
{
bool old_vrr_active = amdgpu_dm_vrr_active(old_state);
bool new_vrr_active = amdgpu_dm_vrr_active(new_state);
bool old_vrr_active = amdgpu_dm_crtc_vrr_active(old_state);
bool new_vrr_active = amdgpu_dm_crtc_vrr_active(new_state);
if (!old_vrr_active && new_vrr_active) {
/* Transition VRR inactive -> active:
@ -7846,7 +7879,7 @@ static void amdgpu_dm_handle_vrr_transition(struct dm_crtc_state *old_state,
* We also need vupdate irq for the actual core vblank handling
* at end of vblank.
*/
WARN_ON(dm_set_vupdate_irq(new_state->base.crtc, true) != 0);
WARN_ON(amdgpu_dm_crtc_set_vupdate_irq(new_state->base.crtc, true) != 0);
WARN_ON(drm_crtc_vblank_get(new_state->base.crtc) != 0);
DRM_DEBUG_DRIVER("%s: crtc=%u VRR off->on: Get vblank ref\n",
__func__, new_state->base.crtc->base.id);
@ -7854,7 +7887,7 @@ static void amdgpu_dm_handle_vrr_transition(struct dm_crtc_state *old_state,
/* Transition VRR active -> inactive:
* Allow vblank irq disable again for fixed refresh rate.
*/
WARN_ON(dm_set_vupdate_irq(new_state->base.crtc, false) != 0);
WARN_ON(amdgpu_dm_crtc_set_vupdate_irq(new_state->base.crtc, false) != 0);
drm_crtc_vblank_put(new_state->base.crtc);
DRM_DEBUG_DRIVER("%s: crtc=%u VRR on->off: Drop vblank ref\n",
__func__, new_state->base.crtc->base.id);
@ -7873,7 +7906,7 @@ static void amdgpu_dm_commit_cursors(struct drm_atomic_state *state)
*/
for_each_old_plane_in_state(state, plane, old_plane_state, i)
if (plane->type == DRM_PLANE_TYPE_CURSOR)
handle_cursor_update(plane, old_plane_state);
amdgpu_dm_plane_handle_cursor_update(plane, old_plane_state);
}
static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
@ -7896,7 +7929,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
int planes_count = 0, vpos, hpos;
unsigned long flags;
u32 target_vblank, last_flip_vblank;
bool vrr_active = amdgpu_dm_vrr_active(acrtc_state);
bool vrr_active = amdgpu_dm_crtc_vrr_active(acrtc_state);
bool cursor_update = false;
bool pflip_present = false;
bool dirty_rects_changed = false;
@ -7958,7 +7991,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
bundle->surface_updates[planes_count].gamut_remap_matrix = &dc_plane->gamut_remap_matrix;
}
fill_dc_scaling_info(dm->adev, new_plane_state,
amdgpu_dm_plane_fill_dc_scaling_info(dm->adev, new_plane_state,
&bundle->scaling_infos[planes_count]);
bundle->surface_updates[planes_count].scaling_info =
@ -8178,12 +8211,12 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
acrtc_state->stream->link->psr_settings.psr_allow_active)
amdgpu_dm_psr_disable(acrtc_state->stream);
dc_commit_updates_for_stream(dm->dc,
bundle->surface_updates,
planes_count,
acrtc_state->stream,
&bundle->stream_update,
dc_state);
update_planes_and_stream_adapter(dm->dc,
acrtc_state->update_type,
planes_count,
acrtc_state->stream,
&bundle->stream_update,
bundle->surface_updates);
/**
* Enable or disable the interrupts on the backend.
@ -8446,7 +8479,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
* aconnector as needed
*/
if (modeset_required(new_crtc_state, dm_new_crtc_state->stream, dm_old_crtc_state->stream)) {
if (amdgpu_dm_crtc_modeset_required(new_crtc_state, dm_new_crtc_state->stream, dm_old_crtc_state->stream)) {
DRM_DEBUG_ATOMIC("Atomic commit: SET crtc id %d: [%p]\n", acrtc->crtc_id, acrtc);
@ -8501,7 +8534,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
dm_enable_per_frame_crtc_master_sync(dc_state);
mutex_lock(&dm->dc_lock);
WARN_ON(!dc_commit_state(dm->dc, dc_state));
WARN_ON(!dc_commit_streams(dm->dc, dc_state->streams, dc_state->stream_count));
/* Allow idle optimization when vblank count is 0 for display off */
if (dm->active_vblank_irq_count == 0)
@ -8527,7 +8560,6 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
acrtc->otg_inst = status->primary_otg_inst;
}
}
#ifdef CONFIG_DRM_AMD_DC_HDCP
for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) {
struct dm_connector_state *dm_new_con_state = to_dm_connector_state(new_con_state);
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(dm_new_con_state->base.crtc);
@ -8638,7 +8670,6 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
new_con_state->hdcp_content_type, enable_encryption);
}
}
#endif
/* Handle connector state changes */
for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) {
@ -8715,12 +8746,11 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
mutex_lock(&dm->dc_lock);
dc_commit_updates_for_stream(dm->dc,
dummy_updates,
status->plane_count,
dm_new_crtc_state->stream,
&stream_update,
dc_state);
dc_update_planes_and_stream(dm->dc,
dummy_updates,
status->plane_count,
dm_new_crtc_state->stream,
&stream_update);
mutex_unlock(&dm->dc_lock);
}
@ -9274,7 +9304,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
if (modereset_required(new_crtc_state))
goto skip_modeset;
if (modeset_required(new_crtc_state, new_stream,
if (amdgpu_dm_crtc_modeset_required(new_crtc_state, new_stream,
dm_old_crtc_state->stream)) {
WARN_ON(dm_new_crtc_state->stream);
@ -9625,7 +9655,7 @@ static int dm_update_plane_state(struct dc *dc,
if (!needs_reset)
return 0;
ret = dm_plane_helper_check_state(new_plane_state, new_crtc_state);
ret = amdgpu_dm_plane_helper_check_state(new_plane_state, new_crtc_state);
if (ret)
return ret;
@ -9771,7 +9801,6 @@ static int dm_check_crtc_cursor(struct drm_atomic_state *state,
return 0;
}
#if defined(CONFIG_DRM_AMD_DC_DCN)
static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm_crtc *crtc)
{
struct drm_connector *connector;
@ -9797,7 +9826,6 @@ static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm
return drm_dp_mst_add_affected_dsc_crtcs(state, &aconnector->mst_root->mst_mgr);
}
#endif
/**
* amdgpu_dm_atomic_check() - Atomic check implementation for AMDgpu DM.
@ -9841,11 +9869,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
bool lock_and_validation_needed = false;
bool is_top_most_overlay = true;
struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state;
#if defined(CONFIG_DRM_AMD_DC_DCN)
struct drm_dp_mst_topology_mgr *mgr;
struct drm_dp_mst_topology_state *mst_state;
struct dsc_mst_fairness_vars vars[MAX_PIPES];
#endif
trace_amdgpu_dm_atomic_check_begin(state);
@ -9876,7 +9902,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
new_crtc_state->connectors_changed = true;
}
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dc_resource_is_dsc_encoding_supported(dc)) {
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
if (drm_atomic_crtc_needs_modeset(new_crtc_state)) {
@ -9888,7 +9913,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
}
}
}
#endif
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
@ -10026,13 +10050,11 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
}
}
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dc_resource_is_dsc_encoding_supported(dc)) {
ret = pre_validate_dsc(state, &dm_state, vars);
if (ret != 0)
goto fail;
}
#endif
/* Run this here since we want to validate the streams we created */
ret = drm_atomic_helper_check_planes(dev, state);
@ -10098,7 +10120,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
lock_and_validation_needed = true;
}
#if defined(CONFIG_DRM_AMD_DC_DCN)
/* set the slot info for each mst_state based on the link encoding format */
for_each_new_mst_mgr_in_state(state, mgr, mst_state, i) {
struct amdgpu_dm_connector *aconnector;
@ -10118,7 +10139,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
}
drm_connector_list_iter_end(&iter);
}
#endif
/**
* Streams and planes are reset when there are changes that affect
@ -10146,7 +10166,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
goto fail;
}
#if defined(CONFIG_DRM_AMD_DC_DCN)
ret = compute_mst_dsc_configs_for_state(state, dm_state->context, vars);
if (ret) {
DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state() failed\n");
@ -10158,7 +10177,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
DRM_DEBUG_DRIVER("dm_update_mst_vcpi_slots_for_dsc() failed\n");
goto fail;
}
#endif
/*
* Perform validation of MST topology in the state:

View File

@ -461,9 +461,7 @@ struct amdgpu_display_manager {
struct amdgpu_dm_backlight_caps backlight_caps[AMDGPU_DM_MAX_NUM_EDP];
struct mod_freesync *freesync_module;
#ifdef CONFIG_DRM_AMD_DC_HDCP
struct hdcp_workqueue *hdcp_workqueue;
#endif
/**
* @vblank_control_workqueue:
@ -747,9 +745,7 @@ struct dm_connector_state {
uint8_t underscan_hborder;
bool underscan_enable;
bool freesync_capable;
#ifdef CONFIG_DRM_AMD_DC_HDCP
bool update_hdcp;
#endif
uint8_t abm_level;
int vcpi_slots;
uint64_t pbn;

View File

@ -34,7 +34,7 @@
#include "amdgpu_dm_trace.h"
#include "amdgpu_dm_debugfs.h"
void dm_crtc_handle_vblank(struct amdgpu_crtc *acrtc)
void amdgpu_dm_crtc_handle_vblank(struct amdgpu_crtc *acrtc)
{
struct drm_crtc *crtc = &acrtc->base;
struct drm_device *dev = crtc->dev;
@ -54,14 +54,14 @@ void dm_crtc_handle_vblank(struct amdgpu_crtc *acrtc)
spin_unlock_irqrestore(&dev->event_lock, flags);
}
bool modeset_required(struct drm_crtc_state *crtc_state,
bool amdgpu_dm_crtc_modeset_required(struct drm_crtc_state *crtc_state,
struct dc_stream_state *new_stream,
struct dc_stream_state *old_stream)
{
return crtc_state->active && drm_atomic_crtc_needs_modeset(crtc_state);
}
bool amdgpu_dm_vrr_active_irq(struct amdgpu_crtc *acrtc)
bool amdgpu_dm_crtc_vrr_active_irq(struct amdgpu_crtc *acrtc)
{
return acrtc->dm_irq_params.freesync_config.state ==
@ -70,7 +70,7 @@ bool amdgpu_dm_vrr_active_irq(struct amdgpu_crtc *acrtc)
VRR_STATE_ACTIVE_FIXED;
}
int dm_set_vupdate_irq(struct drm_crtc *crtc, bool enable)
int amdgpu_dm_crtc_set_vupdate_irq(struct drm_crtc *crtc, bool enable)
{
enum dc_irq_source irq_source;
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
@ -89,7 +89,7 @@ int dm_set_vupdate_irq(struct drm_crtc *crtc, bool enable)
return rc;
}
bool amdgpu_dm_vrr_active(struct dm_crtc_state *dm_state)
bool amdgpu_dm_crtc_vrr_active(struct dm_crtc_state *dm_state)
{
return dm_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE ||
dm_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED;
@ -159,11 +159,11 @@ static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable)
if (enable) {
/* vblank irq on -> Only need vupdate irq in vrr mode */
if (amdgpu_dm_vrr_active(acrtc_state))
rc = dm_set_vupdate_irq(crtc, true);
if (amdgpu_dm_crtc_vrr_active(acrtc_state))
rc = amdgpu_dm_crtc_set_vupdate_irq(crtc, true);
} else {
/* vblank irq off -> vupdate irq off */
rc = dm_set_vupdate_irq(crtc, false);
rc = amdgpu_dm_crtc_set_vupdate_irq(crtc, false);
}
if (rc)
@ -199,12 +199,12 @@ static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable)
return 0;
}
int dm_enable_vblank(struct drm_crtc *crtc)
int amdgpu_dm_crtc_enable_vblank(struct drm_crtc *crtc)
{
return dm_set_vblank(crtc, true);
}
void dm_disable_vblank(struct drm_crtc *crtc)
void amdgpu_dm_crtc_disable_vblank(struct drm_crtc *crtc)
{
dm_set_vblank(crtc, false);
}
@ -300,8 +300,8 @@ static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = {
.verify_crc_source = amdgpu_dm_crtc_verify_crc_source,
.get_crc_sources = amdgpu_dm_crtc_get_crc_sources,
.get_vblank_counter = amdgpu_get_vblank_counter_kms,
.enable_vblank = dm_enable_vblank,
.disable_vblank = dm_disable_vblank,
.enable_vblank = amdgpu_dm_crtc_enable_vblank,
.disable_vblank = amdgpu_dm_crtc_disable_vblank,
.get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp,
#if defined(CONFIG_DEBUG_FS)
.late_register = amdgpu_dm_crtc_late_register,
@ -381,7 +381,7 @@ static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc,
dm_update_crtc_active_planes(crtc, crtc_state);
if (WARN_ON(unlikely(!dm_crtc_state->stream &&
modeset_required(crtc_state, NULL, dm_crtc_state->stream)))) {
amdgpu_dm_crtc_modeset_required(crtc_state, NULL, dm_crtc_state->stream)))) {
return ret;
}

View File

@ -27,21 +27,21 @@
#ifndef __AMDGPU_DM_CRTC_H__
#define __AMDGPU_DM_CRTC_H__
void dm_crtc_handle_vblank(struct amdgpu_crtc *acrtc);
void amdgpu_dm_crtc_handle_vblank(struct amdgpu_crtc *acrtc);
bool modeset_required(struct drm_crtc_state *crtc_state,
bool amdgpu_dm_crtc_modeset_required(struct drm_crtc_state *crtc_state,
struct dc_stream_state *new_stream,
struct dc_stream_state *old_stream);
int dm_set_vupdate_irq(struct drm_crtc *crtc, bool enable);
int amdgpu_dm_crtc_set_vupdate_irq(struct drm_crtc *crtc, bool enable);
bool amdgpu_dm_vrr_active_irq(struct amdgpu_crtc *acrtc);
bool amdgpu_dm_crtc_vrr_active_irq(struct amdgpu_crtc *acrtc);
bool amdgpu_dm_vrr_active(struct dm_crtc_state *dm_state);
bool amdgpu_dm_crtc_vrr_active(struct dm_crtc_state *dm_state);
int dm_enable_vblank(struct drm_crtc *crtc);
int amdgpu_dm_crtc_enable_vblank(struct drm_crtc *crtc);
void dm_disable_vblank(struct drm_crtc *crtc);
void amdgpu_dm_crtc_disable_vblank(struct drm_crtc *crtc);
int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
struct drm_plane *plane,

View File

@ -724,7 +724,7 @@ static ssize_t dp_phy_test_pattern_debugfs_write(struct file *f, const char __us
for (i = 0; i < (unsigned int)(link_training_settings.link_settings.lane_count); i++)
link_training_settings.hw_lane_settings[i] = link->cur_lane_setting[i];
dc_link_set_test_pattern(
dc_link_dp_set_test_pattern(
link,
test_pattern,
DP_TEST_PATTERN_COLOR_SPACE_RGB,
@ -947,7 +947,6 @@ static ssize_t dp_dsc_passthrough_set(struct file *f, const char __user *buf,
return 0;
}
#ifdef CONFIG_DRM_AMD_DC_HDCP
/*
* Returns the HDCP capability of the Display (1.4 for now).
*
@ -984,7 +983,6 @@ static int hdcp_sink_capability_show(struct seq_file *m, void *data)
return 0;
}
#endif
/*
* Returns whether the connected display is internal and not hotpluggable.
@ -2593,9 +2591,7 @@ DEFINE_SHOW_ATTRIBUTE(dp_dsc_fec_support);
DEFINE_SHOW_ATTRIBUTE(dmub_fw_state);
DEFINE_SHOW_ATTRIBUTE(dmub_tracebuffer);
DEFINE_SHOW_ATTRIBUTE(dp_lttpr_status);
#ifdef CONFIG_DRM_AMD_DC_HDCP
DEFINE_SHOW_ATTRIBUTE(hdcp_sink_capability);
#endif
DEFINE_SHOW_ATTRIBUTE(internal_display);
DEFINE_SHOW_ATTRIBUTE(psr_capability);
DEFINE_SHOW_ATTRIBUTE(dp_is_mst_connector);
@ -2726,9 +2722,7 @@ static const struct {
{"phy_settings", &dp_phy_settings_debugfs_fop},
{"lttpr_status", &dp_lttpr_status_fops},
{"test_pattern", &dp_phy_test_pattern_fops},
#ifdef CONFIG_DRM_AMD_DC_HDCP
{"hdcp_sink_capability", &hdcp_sink_capability_fops},
#endif
{"sdp_message", &sdp_message_fops},
{"aux_dpcd_address", &dp_dpcd_address_debugfs_fops},
{"aux_dpcd_size", &dp_dpcd_size_debugfs_fops},
@ -2749,14 +2743,13 @@ static const struct {
{"is_dpia_link", &is_dpia_link_fops}
};
#ifdef CONFIG_DRM_AMD_DC_HDCP
static const struct {
char *name;
const struct file_operations *fops;
} hdmi_debugfs_entries[] = {
{"hdcp_sink_capability", &hdcp_sink_capability_fops}
};
#endif
/*
* Force YUV420 output if available from the given mode
*/
@ -2800,6 +2793,22 @@ static int psr_get(void *data, u64 *val)
return 0;
}
/*
* Read PSR state residency
*/
static int psr_read_residency(void *data, u64 *val)
{
struct amdgpu_dm_connector *connector = data;
struct dc_link *link = connector->dc_link;
u32 residency;
link->dc->link_srv->edp_get_psr_residency(link, &residency);
*val = (u64)residency;
return 0;
}
/*
* Set dmcub trace event IRQ enable or disable.
* Usage to enable dmcub trace event IRQ: echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_dmcub_trace_event_en
@ -2835,6 +2844,8 @@ DEFINE_DEBUGFS_ATTRIBUTE(dmcub_trace_event_state_fops, dmcub_trace_event_state_g
dmcub_trace_event_state_set, "%llu\n");
DEFINE_DEBUGFS_ATTRIBUTE(psr_fops, psr_get, NULL, "%llu\n");
DEFINE_DEBUGFS_ATTRIBUTE(psr_residency_fops, psr_read_residency, NULL,
"%llu\n");
DEFINE_SHOW_ATTRIBUTE(current_backlight);
DEFINE_SHOW_ATTRIBUTE(target_backlight);
@ -2998,6 +3009,8 @@ void connector_debugfs_init(struct amdgpu_dm_connector *connector)
if (connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) {
debugfs_create_file_unsafe("psr_capability", 0444, dir, connector, &psr_capability_fops);
debugfs_create_file_unsafe("psr_state", 0444, dir, connector, &psr_fops);
debugfs_create_file_unsafe("psr_residency", 0444, dir,
connector, &psr_residency_fops);
debugfs_create_file("amdgpu_current_backlight_pwm", 0444, dir, connector,
&current_backlight_fops);
debugfs_create_file("amdgpu_target_backlight_pwm", 0444, dir, connector,
@ -3015,7 +3028,6 @@ void connector_debugfs_init(struct amdgpu_dm_connector *connector)
connector->debugfs_dpcd_address = 0;
connector->debugfs_dpcd_size = 0;
#ifdef CONFIG_DRM_AMD_DC_HDCP
if (connector->base.connector_type == DRM_MODE_CONNECTOR_HDMIA) {
for (i = 0; i < ARRAY_SIZE(hdmi_debugfs_entries); i++) {
debugfs_create_file(hdmi_debugfs_entries[i].name,
@ -3023,7 +3035,6 @@ void connector_debugfs_init(struct amdgpu_dm_connector *connector)
hdmi_debugfs_entries[i].fops);
}
}
#endif
}
#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY

View File

@ -559,9 +559,10 @@ static void update_config(void *handle, struct cp_psp_stream_config *config)
link->dp.rev = aconnector->dc_link->dpcd_caps.dpcd_rev.raw;
link->dp.assr_enabled = config->assr_enabled;
link->dp.mst_enabled = config->mst_enabled;
link->dp.dp2_enabled = config->dp2_enabled;
link->dp.usb4_enabled = config->usb4_enabled;
display->adjust.disable = MOD_HDCP_DISPLAY_DISABLE_AUTHENTICATION;
link->adjust.auth_delay = 0;
link->adjust.auth_delay = 2;
link->adjust.hdcp1.disable = 0;
conn_state = aconnector->base.state;

View File

@ -177,6 +177,40 @@ void dm_helpers_dp_update_branch_info(
const struct dc_link *link)
{}
static void dm_helpers_construct_old_payload(
struct dc_link *link,
int pbn_per_slot,
struct drm_dp_mst_atomic_payload *new_payload,
struct drm_dp_mst_atomic_payload *old_payload)
{
struct link_mst_stream_allocation_table current_link_table =
link->mst_stream_alloc_table;
struct link_mst_stream_allocation *dc_alloc;
int i;
*old_payload = *new_payload;
/* Set correct time_slots/PBN of old payload.
* other fields (delete & dsc_enabled) in
* struct drm_dp_mst_atomic_payload are don't care fields
* while calling drm_dp_remove_payload()
*/
for (i = 0; i < current_link_table.stream_count; i++) {
dc_alloc =
&current_link_table.stream_allocations[i];
if (dc_alloc->vcp_id == new_payload->vcpi) {
old_payload->time_slots = dc_alloc->slot_count;
old_payload->pbn = dc_alloc->slot_count * pbn_per_slot;
break;
}
}
/* make sure there is an old payload*/
ASSERT(i != current_link_table.stream_count);
}
/*
* Writes payload allocation table in immediate downstream device.
*/
@ -188,7 +222,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
{
struct amdgpu_dm_connector *aconnector;
struct drm_dp_mst_topology_state *mst_state;
struct drm_dp_mst_atomic_payload *payload;
struct drm_dp_mst_atomic_payload *target_payload, *new_payload, old_payload;
struct drm_dp_mst_topology_mgr *mst_mgr;
aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
@ -204,17 +238,26 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
mst_state = to_drm_dp_mst_topology_state(mst_mgr->base.state);
/* It's OK for this to fail */
payload = drm_atomic_get_mst_payload_state(mst_state, aconnector->mst_output_port);
if (enable)
drm_dp_add_payload_part1(mst_mgr, mst_state, payload);
else
drm_dp_remove_payload(mst_mgr, mst_state, payload, payload);
new_payload = drm_atomic_get_mst_payload_state(mst_state, aconnector->mst_output_port);
if (enable) {
target_payload = new_payload;
drm_dp_add_payload_part1(mst_mgr, mst_state, new_payload);
} else {
/* construct old payload by VCPI*/
dm_helpers_construct_old_payload(stream->link, mst_state->pbn_div,
new_payload, &old_payload);
target_payload = &old_payload;
drm_dp_remove_payload(mst_mgr, mst_state, &old_payload, new_payload);
}
/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
* AUX message. The sequence is slot 1-63 allocated sequence for each
* stream. AMD ASIC stream slot allocation should follow the same
* sequence. copy DRM MST allocation to dc */
fill_dc_mst_payload_table_from_drm(stream->link, enable, payload, proposed_table);
fill_dc_mst_payload_table_from_drm(stream->link, enable, target_payload, proposed_table);
return true;
}
@ -468,8 +511,8 @@ bool dm_helpers_dp_read_dpcd(
return false;
}
return drm_dp_dpcd_read(&aconnector->dm_dp_aux.aux, address,
data, size) > 0;
return drm_dp_dpcd_read(&aconnector->dm_dp_aux.aux, address, data,
size) == size;
}
bool dm_helpers_dp_write_dpcd(
@ -525,7 +568,6 @@ bool dm_helpers_submit_i2c(
return result;
}
#if defined(CONFIG_DRM_AMD_DC_DCN)
static bool execute_synaptics_rc_command(struct drm_dp_aux *aux,
bool is_write_cmd,
unsigned char cmd,
@ -693,7 +735,6 @@ static uint8_t write_dsc_enable_synaptics_non_virtual_dpcd_mst(
return ret;
}
#endif
bool dm_helpers_dp_write_dsc_enable(
struct dc_context *ctx,
@ -719,13 +760,11 @@ bool dm_helpers_dp_write_dsc_enable(
if (!aconnector->dsc_aux)
return false;
#if defined(CONFIG_DRM_AMD_DC_DCN)
// apply w/a to synaptics
if (needs_dsc_aux_workaround(aconnector->dc_link) &&
(aconnector->mst_downstream_port_present.byte & 0x7) != 0x3)
return write_dsc_enable_synaptics_non_virtual_dpcd_mst(
aconnector->dsc_aux, stream, enable_dsc);
#endif
port = aconnector->mst_output_port;
@ -763,17 +802,13 @@ bool dm_helpers_dp_write_dsc_enable(
}
if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT || stream->signal == SIGNAL_TYPE_EDP) {
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (stream->sink->link->dpcd_caps.dongle_type == DISPLAY_DONGLE_NONE) {
#endif
ret = dm_helpers_dp_write_dpcd(ctx, stream->link, DP_DSC_ENABLE, &enable_dsc, 1);
DC_LOG_DC("Send DSC %s to SST RX\n", enable_dsc ? "enable" : "disable");
#if defined(CONFIG_DRM_AMD_DC_DCN)
} else if (stream->sink->link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER) {
ret = dm_helpers_dp_write_dpcd(ctx, stream->link, DP_DSC_ENABLE, &enable_dsc, 1);
DC_LOG_DC("Send DSC %s to DP-HDMI PCON\n", enable_dsc ? "enable" : "disable");
}
#endif
}
return ret;

View File

@ -31,10 +31,7 @@
#include "amdgpu.h"
#include "amdgpu_dm.h"
#include "amdgpu_dm_mst_types.h"
#ifdef CONFIG_DRM_AMD_DC_HDCP
#include "amdgpu_dm_hdcp.h"
#endif
#include "dc.h"
#include "dm_helpers.h"
@ -201,7 +198,6 @@ static const struct drm_connector_funcs dm_dp_mst_connector_funcs = {
.early_unregister = amdgpu_dm_mst_connector_early_unregister,
};
#if defined(CONFIG_DRM_AMD_DC_DCN)
bool needs_dsc_aux_workaround(struct dc_link *link)
{
if (link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_90CC24 &&
@ -212,6 +208,21 @@ bool needs_dsc_aux_workaround(struct dc_link *link)
return false;
}
bool is_synaptics_cascaded_panamera(struct dc_link *link, struct drm_dp_mst_port *port)
{
u8 branch_vendor_data[4] = { 0 }; // Vendor data 0x50C ~ 0x50F
if (drm_dp_dpcd_read(port->mgr->aux, DP_BRANCH_VENDOR_SPECIFIC_START, &branch_vendor_data, 4) == 4) {
if (link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_90CC24 &&
IS_SYNAPTICS_CASCADED_PANAMERA(link->dpcd_caps.branch_dev_name, branch_vendor_data)) {
DRM_INFO("Synaptics Cascaded MST hub\n");
return true;
}
}
return false;
}
static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector *aconnector)
{
struct dc_sink *dc_sink = aconnector->dc_sink;
@ -235,6 +246,10 @@ static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector *aconnecto
needs_dsc_aux_workaround(aconnector->dc_link))
aconnector->dsc_aux = &aconnector->mst_root->dm_dp_aux.aux;
/* synaptics cascaded MST hub case */
if (!aconnector->dsc_aux && is_synaptics_cascaded_panamera(aconnector->dc_link, port))
aconnector->dsc_aux = port->mgr->aux;
if (!aconnector->dsc_aux)
return false;
@ -271,7 +286,6 @@ static bool retrieve_downstream_port_device(struct amdgpu_dm_connector *aconnect
return true;
}
#endif
static int dm_dp_mst_get_modes(struct drm_connector *connector)
{
@ -362,7 +376,6 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector)
* plugged back with same display index, its hdcp properties
* will be retrieved from hdcp_work within dm_dp_mst_get_modes
*/
#ifdef CONFIG_DRM_AMD_DC_HDCP
if (aconnector->dc_sink && connector->state) {
struct drm_device *dev = connector->dev;
struct amdgpu_device *adev = drm_to_adev(dev);
@ -374,13 +387,11 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector)
connector->state->content_protection =
hdcp_w->content_protection[connector->index];
}
#endif
if (aconnector->dc_sink) {
amdgpu_dm_update_freesync_caps(
connector, aconnector->edid);
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (!validate_dsc_caps_on_connector(aconnector))
memset(&aconnector->dc_sink->dsc_caps,
0, sizeof(aconnector->dc_sink->dsc_caps));
@ -388,7 +399,6 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector)
if (!retrieve_downstream_port_device(aconnector))
memset(&aconnector->mst_downstream_port_present,
0, sizeof(aconnector->mst_downstream_port_present));
#endif
}
}
@ -647,8 +657,6 @@ int dm_mst_get_pbn_divider(struct dc_link *link)
dc_link_get_link_cap(link)) / (8 * 1000 * 54);
}
#if defined(CONFIG_DRM_AMD_DC_DCN)
struct dsc_mst_fairness_params {
struct dc_crtc_timing *timing;
struct dc_sink *sink;
@ -662,12 +670,25 @@ struct dsc_mst_fairness_params {
struct amdgpu_dm_connector *aconnector;
};
static int kbps_to_peak_pbn(int kbps)
static uint16_t get_fec_overhead_multiplier(struct dc_link *dc_link)
{
u8 link_coding_cap;
uint16_t fec_overhead_multiplier_x1000 = PBN_FEC_OVERHEAD_MULTIPLIER_8B_10B;
link_coding_cap = dc_link_dp_mst_decide_link_encoding_format(dc_link);
if (link_coding_cap == DP_128b_132b_ENCODING)
fec_overhead_multiplier_x1000 = PBN_FEC_OVERHEAD_MULTIPLIER_128B_132B;
return fec_overhead_multiplier_x1000;
}
static int kbps_to_peak_pbn(int kbps, uint16_t fec_overhead_multiplier_x1000)
{
u64 peak_kbps = kbps;
peak_kbps *= 1006;
peak_kbps = div_u64(peak_kbps, 1000);
peak_kbps *= fec_overhead_multiplier_x1000;
peak_kbps = div_u64(peak_kbps, 1000 * 1000);
return (int) DIV64_U64_ROUND_UP(peak_kbps * 64, (54 * 8 * 1000));
}
@ -678,16 +699,19 @@ static void set_dsc_configs_from_fairness_vars(struct dsc_mst_fairness_params *p
{
struct drm_connector *drm_connector;
int i;
struct dc_dsc_config_options dsc_options = {0};
for (i = 0; i < count; i++) {
drm_connector = &params[i].aconnector->base;
dc_dsc_get_default_config_option(params[i].sink->ctx->dc, &dsc_options);
dsc_options.max_target_bpp_limit_override_x16 = drm_connector->display_info.max_dsc_bpp * 16;
memset(&params[i].timing->dsc_cfg, 0, sizeof(params[i].timing->dsc_cfg));
if (vars[i + k].dsc_enabled && dc_dsc_compute_config(
params[i].sink->ctx->dc->res_pool->dscs[0],
&params[i].sink->dsc_caps.dsc_dec_caps,
params[i].sink->ctx->dc->debug.dsc_min_slice_height_override,
drm_connector->display_info.max_dsc_bpp,
&dsc_options,
0,
params[i].timing,
&params[i].timing->dsc_cfg)) {
@ -730,15 +754,16 @@ static int bpp_x16_from_pbn(struct dsc_mst_fairness_params param, int pbn)
u64 kbps;
struct drm_connector *drm_connector = &param.aconnector->base;
uint32_t max_dsc_target_bpp_limit_override =
drm_connector->display_info.max_dsc_bpp;
struct dc_dsc_config_options dsc_options = {0};
dc_dsc_get_default_config_option(param.sink->ctx->dc, &dsc_options);
dsc_options.max_target_bpp_limit_override_x16 = drm_connector->display_info.max_dsc_bpp * 16;
kbps = div_u64((u64)pbn * 994 * 8 * 54, 64);
dc_dsc_compute_config(
param.sink->ctx->dc->res_pool->dscs[0],
&param.sink->dsc_caps.dsc_dec_caps,
param.sink->ctx->dc->debug.dsc_min_slice_height_override,
max_dsc_target_bpp_limit_override,
&dsc_options,
(int) kbps, param.timing, &dsc_config);
return dsc_config.bits_per_pixel;
@ -761,11 +786,12 @@ static int increase_dsc_bpp(struct drm_atomic_state *state,
int link_timeslots_used;
int fair_pbn_alloc;
int ret = 0;
uint16_t fec_overhead_multiplier_x1000 = get_fec_overhead_multiplier(dc_link);
for (i = 0; i < count; i++) {
if (vars[i + k].dsc_enabled) {
initial_slack[i] =
kbps_to_peak_pbn(params[i].bw_range.max_kbps) - vars[i + k].pbn;
kbps_to_peak_pbn(params[i].bw_range.max_kbps, fec_overhead_multiplier_x1000) - vars[i + k].pbn;
bpp_increased[i] = false;
remaining_to_increase += 1;
} else {
@ -861,6 +887,7 @@ static int try_disable_dsc(struct drm_atomic_state *state,
int next_index;
int remaining_to_try = 0;
int ret;
uint16_t fec_overhead_multiplier_x1000 = get_fec_overhead_multiplier(dc_link);
for (i = 0; i < count; i++) {
if (vars[i + k].dsc_enabled
@ -890,7 +917,7 @@ static int try_disable_dsc(struct drm_atomic_state *state,
if (next_index == -1)
break;
vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps, fec_overhead_multiplier_x1000);
ret = drm_dp_atomic_find_time_slots(state,
params[next_index].port->mgr,
params[next_index].port,
@ -903,7 +930,7 @@ static int try_disable_dsc(struct drm_atomic_state *state,
vars[next_index].dsc_enabled = false;
vars[next_index].bpp_x16 = 0;
} else {
vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.max_kbps, fec_overhead_multiplier_x1000);
ret = drm_dp_atomic_find_time_slots(state,
params[next_index].port->mgr,
params[next_index].port,
@ -932,6 +959,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
int count = 0;
int i, k, ret;
bool debugfs_overwrite = false;
uint16_t fec_overhead_multiplier_x1000 = get_fec_overhead_multiplier(dc_link);
memset(params, 0, sizeof(params));
@ -993,7 +1021,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
/* Try no compression */
for (i = 0; i < count; i++) {
vars[i + k].aconnector = params[i].aconnector;
vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps, fec_overhead_multiplier_x1000);
vars[i + k].dsc_enabled = false;
vars[i + k].bpp_x16 = 0;
ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port,
@ -1012,7 +1040,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
/* Try max compression */
for (i = 0; i < count; i++) {
if (params[i].compression_possible && params[i].clock_force_enable != DSC_CLK_FORCE_DISABLE) {
vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.min_kbps);
vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.min_kbps, fec_overhead_multiplier_x1000);
vars[i + k].dsc_enabled = true;
vars[i + k].bpp_x16 = params[i].bw_range.min_target_bpp_x16;
ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
@ -1020,7 +1048,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
if (ret < 0)
return ret;
} else {
vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps, fec_overhead_multiplier_x1000);
vars[i + k].dsc_enabled = false;
vars[i + k].bpp_x16 = 0;
ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
@ -1154,6 +1182,7 @@ int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
bool computed_streams[MAX_PIPES];
struct amdgpu_dm_connector *aconnector;
struct drm_dp_mst_topology_mgr *mst_mgr;
struct resource_pool *res_pool;
int link_vars_start_index = 0;
int ret = 0;
@ -1162,6 +1191,7 @@ int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
for (i = 0; i < dc_state->stream_count; i++) {
stream = dc_state->streams[i];
res_pool = stream->ctx->dc->res_pool;
if (stream->signal != SIGNAL_TYPE_DISPLAY_PORT_MST)
continue;
@ -1177,7 +1207,8 @@ int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
if (computed_streams[i])
continue;
if (dcn20_remove_stream_from_ctx(stream->ctx->dc, dc_state, stream) != DC_OK)
if (!res_pool->funcs->remove_stream_from_ctx ||
res_pool->funcs->remove_stream_from_ctx(stream->ctx->dc, dc_state, stream) != DC_OK)
return -EINVAL;
if (!is_dsc_need_re_compute(state, dc_state, stream->link))
@ -1435,14 +1466,12 @@ static bool is_dsc_common_config_possible(struct dc_stream_state *stream,
return bw_range->max_target_bpp_x16 && bw_range->min_target_bpp_x16;
}
#endif /* CONFIG_DRM_AMD_DC_DCN */
enum dc_status dm_dp_mst_is_port_support_mode(
struct amdgpu_dm_connector *aconnector,
struct dc_stream_state *stream)
{
int bpp, pbn, branch_max_throughput_mps = 0;
#if defined(CONFIG_DRM_AMD_DC_DCN)
struct dc_link_settings cur_link_settings;
unsigned int end_to_end_bw_in_kbps = 0;
unsigned int upper_link_bw_in_kbps = 0, down_link_bw_in_kbps = 0;
@ -1484,16 +1513,13 @@ enum dc_status dm_dp_mst_is_port_support_mode(
return DC_FAIL_BANDWIDTH_VALIDATE;
}
} else {
#endif
/* check if mode could be supported within full_pbn */
bpp = convert_dc_color_depth_into_bpc(stream->timing.display_color_depth) * 3;
pbn = drm_dp_calc_pbn_mode(stream->timing.pix_clk_100hz / 10, bpp, false);
if (pbn > aconnector->mst_output_port->full_pbn)
return DC_FAIL_BANDWIDTH_VALIDATE;
#if defined(CONFIG_DRM_AMD_DC_DCN)
}
#endif
/* check is mst dsc output bandwidth branch_overall_throughput_0_mps */
switch (stream->timing.pixel_encoding) {

View File

@ -34,6 +34,21 @@
#define SYNAPTICS_RC_OFFSET 0x4BC
#define SYNAPTICS_RC_DATA 0x4C0
#define DP_BRANCH_VENDOR_SPECIFIC_START 0x50C
/**
* Panamera MST Hub detection
* Offset DPCD 050Eh == 0x5A indicates cascaded MST hub case
* Check from beginning of branch device vendor specific field (050Ch)
*/
#define IS_SYNAPTICS_PANAMERA(branchDevName) (((int)branchDevName[4] & 0xF0) == 0x50 ? 1 : 0)
#define BRANCH_HW_REVISION_PANAMERA_A2 0x10
#define SYNAPTICS_CASCADED_HUB_ID 0x5A
#define IS_SYNAPTICS_CASCADED_PANAMERA(devName, data) ((IS_SYNAPTICS_PANAMERA(devName) && ((int)data[2] == SYNAPTICS_CASCADED_HUB_ID)) ? 1 : 0)
#define PBN_FEC_OVERHEAD_MULTIPLIER_8B_10B 1031
#define PBN_FEC_OVERHEAD_MULTIPLIER_128B_132B 1000
struct amdgpu_display_manager;
struct amdgpu_dm_connector;

View File

@ -90,12 +90,12 @@ enum dm_micro_swizzle {
MICRO_SWIZZLE_R = 3
};
const struct drm_format_info *amd_get_format_info(const struct drm_mode_fb_cmd2 *cmd)
const struct drm_format_info *amdgpu_dm_plane_get_format_info(const struct drm_mode_fb_cmd2 *cmd)
{
return amdgpu_lookup_format_info(cmd->pixel_format, cmd->modifier[0]);
}
void fill_blending_from_plane_state(const struct drm_plane_state *plane_state,
void amdgpu_dm_plane_fill_blending_from_plane_state(const struct drm_plane_state *plane_state,
bool *per_pixel_alpha, bool *pre_multiplied_alpha,
bool *global_alpha, int *global_alpha_value)
{
@ -741,25 +741,7 @@ static int get_plane_formats(const struct drm_plane *plane,
return num_formats;
}
#ifdef CONFIG_DRM_AMD_DC_HDR
static int attach_color_mgmt_properties(struct amdgpu_display_manager *dm, struct drm_plane *plane)
{
drm_object_attach_property(&plane->base,
dm->degamma_lut_property,
0);
drm_object_attach_property(&plane->base,
dm->degamma_lut_size_property,
MAX_COLOR_LUT_ENTRIES);
drm_object_attach_property(&plane->base, dm->ctm_property,
0);
drm_object_attach_property(&plane->base, dm->sdr_boost_property,
DEFAULT_SDR_BOOST);
return 0;
}
#endif
int fill_plane_buffer_attributes(struct amdgpu_device *adev,
int amdgpu_dm_plane_fill_plane_buffer_attributes(struct amdgpu_device *adev,
const struct amdgpu_framebuffer *afb,
const enum surface_pixel_format format,
const enum dc_rotation_angle rotation,
@ -918,7 +900,7 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane,
dm_plane_state_new->dc_state;
bool force_disable_dcc = !plane_state->dcc.enable;
fill_plane_buffer_attributes(
amdgpu_dm_plane_fill_plane_buffer_attributes(
adev, afb, plane_state->format, plane_state->rotation,
afb->tiling_flags,
&plane_state->tiling_info, &plane_state->plane_size,
@ -999,7 +981,7 @@ static void get_min_max_dc_plane_scaling(struct drm_device *dev,
*min_downscale = 1000;
}
int dm_plane_helper_check_state(struct drm_plane_state *state,
int amdgpu_dm_plane_helper_check_state(struct drm_plane_state *state,
struct drm_crtc_state *new_crtc_state)
{
struct drm_framebuffer *fb = state->fb;
@ -1053,7 +1035,7 @@ int dm_plane_helper_check_state(struct drm_plane_state *state,
state, new_crtc_state, min_scale, max_scale, true, true);
}
int fill_dc_scaling_info(struct amdgpu_device *adev,
int amdgpu_dm_plane_fill_dc_scaling_info(struct amdgpu_device *adev,
const struct drm_plane_state *state,
struct dc_scaling_info *scaling_info)
{
@ -1161,11 +1143,11 @@ static int dm_plane_atomic_check(struct drm_plane *plane,
if (!new_crtc_state)
return -EINVAL;
ret = dm_plane_helper_check_state(new_plane_state, new_crtc_state);
ret = amdgpu_dm_plane_helper_check_state(new_plane_state, new_crtc_state);
if (ret)
return ret;
ret = fill_dc_scaling_info(adev, new_plane_state, &scaling_info);
ret = amdgpu_dm_plane_fill_dc_scaling_info(adev, new_plane_state, &scaling_info);
if (ret)
return ret;
@ -1229,7 +1211,7 @@ static int get_cursor_position(struct drm_plane *plane, struct drm_crtc *crtc,
return 0;
}
void handle_cursor_update(struct drm_plane *plane,
void amdgpu_dm_plane_handle_cursor_update(struct drm_plane *plane,
struct drm_plane_state *old_plane_state)
{
struct amdgpu_device *adev = drm_to_adev(plane->dev);
@ -1314,7 +1296,7 @@ static void dm_plane_atomic_async_update(struct drm_plane *plane,
plane->state->crtc_w = new_state->crtc_w;
plane->state->crtc_h = new_state->crtc_h;
handle_cursor_update(plane, old_state);
amdgpu_dm_plane_handle_cursor_update(plane, old_state);
}
static const struct drm_plane_helper_funcs dm_plane_helper_funcs = {
@ -1337,10 +1319,6 @@ static void dm_drm_plane_reset(struct drm_plane *plane)
if (amdgpu_state)
__drm_atomic_helper_plane_reset(plane, &amdgpu_state->base);
#ifdef CONFIG_DRM_AMD_DC_HDR
if (amdgpu_state)
amdgpu_state->sdr_boost = DEFAULT_SDR_BOOST;
#endif
}
static struct drm_plane_state *
@ -1360,15 +1338,6 @@ dm_drm_plane_duplicate_state(struct drm_plane *plane)
dc_plane_state_retain(dm_plane_state->dc_state);
}
#ifdef CONFIG_DRM_AMD_DC_HDR
if (dm_plane_state->degamma_lut)
drm_property_blob_get(dm_plane_state->degamma_lut);
if (dm_plane_state->ctm)
drm_property_blob_get(dm_plane_state->ctm);
dm_plane_state->sdr_boost = old_dm_plane_state->sdr_boost;
#endif
return &dm_plane_state->base;
}
@ -1436,103 +1405,12 @@ static void dm_drm_plane_destroy_state(struct drm_plane *plane,
{
struct dm_plane_state *dm_plane_state = to_dm_plane_state(state);
#ifdef CONFIG_DRM_AMD_DC_HDR
drm_property_blob_put(dm_plane_state->degamma_lut);
drm_property_blob_put(dm_plane_state->ctm);
#endif
if (dm_plane_state->dc_state)
dc_plane_state_release(dm_plane_state->dc_state);
drm_atomic_helper_plane_destroy_state(plane, state);
}
#ifdef CONFIG_DRM_AMD_DC_HDR
/* copied from drm_atomic_uapi.c */
static int atomic_replace_property_blob_from_id(struct drm_device *dev,
struct drm_property_blob **blob,
uint64_t blob_id,
ssize_t expected_size,
ssize_t expected_elem_size,
bool *replaced)
{
struct drm_property_blob *new_blob = NULL;
if (blob_id != 0) {
new_blob = drm_property_lookup_blob(dev, blob_id);
if (new_blob == NULL)
return -EINVAL;
if (expected_size > 0 &&
new_blob->length != expected_size) {
drm_property_blob_put(new_blob);
return -EINVAL;
}
if (expected_elem_size > 0 &&
new_blob->length % expected_elem_size != 0) {
drm_property_blob_put(new_blob);
return -EINVAL;
}
}
*replaced |= drm_property_replace_blob(blob, new_blob);
drm_property_blob_put(new_blob);
return 0;
}
int dm_drm_plane_set_property(struct drm_plane *plane,
struct drm_plane_state *state,
struct drm_property *property,
uint64_t val)
{
struct amdgpu_device *adev = drm_to_adev(plane->dev);
struct dm_plane_state *dm_plane_state = to_dm_plane_state(state);
int ret = 0;
bool replaced;
if (property == adev->dm.degamma_lut_property) {
ret = atomic_replace_property_blob_from_id(adev_to_drm(adev),
&dm_plane_state->degamma_lut,
val, -1, sizeof(struct drm_color_lut),
&replaced);
} else if (property == adev->dm.ctm_property) {
ret = atomic_replace_property_blob_from_id(adev_to_drm(adev),
&dm_plane_state->ctm,
val,
sizeof(struct drm_color_ctm), -1,
&replaced);
} else if (property == adev->dm.sdr_boost_property) {
dm_plane_state->sdr_boost = val;
} else {
return -EINVAL;
}
return ret;
}
int dm_drm_plane_get_property(struct drm_plane *plane,
const struct drm_plane_state *state,
struct drm_property *property,
uint64_t *val)
{
struct dm_plane_state *dm_plane_state = to_dm_plane_state(state);
struct amdgpu_device *adev = drm_to_adev(plane->dev);
if (property == adev->dm.degamma_lut_property) {
*val = (dm_plane_state->degamma_lut) ?
dm_plane_state->degamma_lut->base.id : 0;
} else if (property == adev->dm.ctm_property) {
*val = (dm_plane_state->ctm) ? dm_plane_state->ctm->base.id : 0;
} else if (property == adev->dm.sdr_boost_property) {
*val = dm_plane_state->sdr_boost;
} else {
return -EINVAL;
}
return 0;
}
#endif
static const struct drm_plane_funcs dm_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
@ -1541,10 +1419,6 @@ static const struct drm_plane_funcs dm_plane_funcs = {
.atomic_duplicate_state = dm_drm_plane_duplicate_state,
.atomic_destroy_state = dm_drm_plane_destroy_state,
.format_mod_supported = dm_plane_format_mod_supported,
#ifdef CONFIG_DRM_AMD_DC_HDR
.atomic_set_property = dm_drm_plane_set_property,
.atomic_get_property = dm_drm_plane_get_property,
#endif
};
int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
@ -1615,9 +1489,6 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
drm_plane_helper_add(plane, &dm_plane_helper_funcs);
#ifdef CONFIG_DRM_AMD_DC_HDR
attach_color_mgmt_properties(dm, plane);
#endif
/* Create (reset) the plane state */
if (plane->funcs->reset)
plane->funcs->reset(plane);

View File

@ -29,17 +29,17 @@
#include "dc.h"
void handle_cursor_update(struct drm_plane *plane,
void amdgpu_dm_plane_handle_cursor_update(struct drm_plane *plane,
struct drm_plane_state *old_plane_state);
int fill_dc_scaling_info(struct amdgpu_device *adev,
int amdgpu_dm_plane_fill_dc_scaling_info(struct amdgpu_device *adev,
const struct drm_plane_state *state,
struct dc_scaling_info *scaling_info);
int dm_plane_helper_check_state(struct drm_plane_state *state,
int amdgpu_dm_plane_helper_check_state(struct drm_plane_state *state,
struct drm_crtc_state *new_crtc_state);
int fill_plane_buffer_attributes(struct amdgpu_device *adev,
int amdgpu_dm_plane_fill_plane_buffer_attributes(struct amdgpu_device *adev,
const struct amdgpu_framebuffer *afb,
const enum surface_pixel_format format,
const enum dc_rotation_angle rotation,
@ -56,9 +56,9 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
unsigned long possible_crtcs,
const struct dc_plane_cap *plane_cap);
const struct drm_format_info *amd_get_format_info(const struct drm_mode_fb_cmd2 *cmd);
const struct drm_format_info *amdgpu_dm_plane_get_format_info(const struct drm_mode_fb_cmd2 *cmd);
void fill_blending_from_plane_state(const struct drm_plane_state *plane_state,
void amdgpu_dm_plane_fill_blending_from_plane_state(const struct drm_plane_state *plane_state,
bool *per_pixel_alpha, bool *pre_multiplied_alpha,
bool *global_alpha, int *global_alpha_value);

View File

@ -22,14 +22,13 @@
#
# Makefile for Display Core (dc) component.
DC_LIBS = basics bios dml clk_mgr dce gpio irq link virtual
DC_LIBS = basics bios dml clk_mgr dce gpio irq link virtual dsc
ifdef CONFIG_DRM_AMD_DC_DCN
ifdef CONFIG_DRM_AMD_DC_FP
KCOV_INSTRUMENT := n
DC_LIBS += dcn20
DC_LIBS += dsc
DC_LIBS += dcn10
DC_LIBS += dcn21
DC_LIBS += dcn201
@ -56,9 +55,7 @@ ifdef CONFIG_DRM_AMD_DC_SI
DC_LIBS += dce60
endif
ifdef CONFIG_DRM_AMD_DC_HDCP
DC_LIBS += hdcp
endif
AMD_DC = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DISPLAY_PATH)/dc/,$(DC_LIBS)))

View File

@ -2064,7 +2064,7 @@ static enum bp_result bios_parser_get_encoder_cap_info(
if (!info)
return BP_RESULT_BADINPUT;
#if defined(CONFIG_DRM_AMD_DC_DCN)
#if defined(CONFIG_DRM_AMD_DC_FP)
/* encoder cap record not available in v1_5 */
if (bp->object_info_tbl.revision.minor == 5)
return BP_RESULT_NORECORD;

View File

@ -74,7 +74,7 @@ CLK_MGR_DCE120 = dce120_clk_mgr.o
AMD_DAL_CLK_MGR_DCE120 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dce120/,$(CLK_MGR_DCE120))
AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCE120)
ifdef CONFIG_DRM_AMD_DC_DCN
ifdef CONFIG_DRM_AMD_DC_FP
###############################################################################
# DCN10
###############################################################################

View File

@ -104,7 +104,7 @@ void clk_mgr_exit_optimized_pwr_state(const struct dc *dc, struct clk_mgr *clk_m
int edp_num;
unsigned int panel_inst;
get_edp_links(dc, edp_links, &edp_num);
dc_get_edp_links(dc, edp_links, &edp_num);
if (dc->hwss.exit_optimized_pwr_state)
dc->hwss.exit_optimized_pwr_state(dc, dc->current_state);
@ -116,7 +116,7 @@ void clk_mgr_exit_optimized_pwr_state(const struct dc *dc, struct clk_mgr *clk_m
if (!edp_link->psr_settings.psr_feature_enabled)
continue;
clk_mgr->psr_allow_active_cache = edp_link->psr_settings.psr_allow_active;
dc_link_set_psr_allow_active(edp_link, &allow_active, false, false, NULL);
dc->link_srv->edp_set_psr_allow_active(edp_link, &allow_active, false, false, NULL);
}
}
@ -129,13 +129,13 @@ void clk_mgr_optimize_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr)
int edp_num;
unsigned int panel_inst;
get_edp_links(dc, edp_links, &edp_num);
dc_get_edp_links(dc, edp_links, &edp_num);
if (edp_num) {
for (panel_inst = 0; panel_inst < edp_num; panel_inst++) {
edp_link = edp_links[panel_inst];
if (!edp_link->psr_settings.psr_feature_enabled)
continue;
dc_link_set_psr_allow_active(edp_link,
dc->link_srv->edp_set_psr_allow_active(edp_link,
&clk_mgr->psr_allow_active_cache, false, false, NULL);
}
}
@ -221,7 +221,7 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p
dce120_clk_mgr_construct(ctx, clk_mgr);
return &clk_mgr->base;
}
#if defined(CONFIG_DRM_AMD_DC_DCN)
#if defined(CONFIG_DRM_AMD_DC_FP)
case FAMILY_RV: {
struct clk_mgr_internal *clk_mgr = kzalloc(sizeof(*clk_mgr), GFP_KERNEL);
@ -351,7 +351,7 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p
}
break;
#endif
#endif /* CONFIG_DRM_AMD_DC_FP - Family RV */
default:
ASSERT(0); /* Unknown Asic */
break;
@ -364,7 +364,7 @@ void dc_destroy_clk_mgr(struct clk_mgr *clk_mgr_base)
{
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
#ifdef CONFIG_DRM_AMD_DC_DCN
#ifdef CONFIG_DRM_AMD_DC_FP
switch (clk_mgr_base->ctx->asic_id.chip_family) {
case FAMILY_NV:
if (ASICREV_IS_SIENNA_CICHLID_P(clk_mgr_base->ctx->asic_id.hw_internal_rev)) {
@ -405,7 +405,7 @@ void dc_destroy_clk_mgr(struct clk_mgr *clk_mgr_base)
default:
break;
}
#endif
#endif /* CONFIG_DRM_AMD_DC_FP */
kfree(clk_mgr);
}

View File

@ -162,7 +162,7 @@ static void dcn201_update_clocks(struct clk_mgr *clk_mgr_base,
}
}
struct clk_mgr_funcs dcn201_funcs = {
static struct clk_mgr_funcs dcn201_funcs = {
.get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
.update_clocks = dcn201_update_clocks,
.init_clocks = dcn201_init_clocks,

View File

@ -706,7 +706,7 @@ void rn_clk_mgr_construct(
enum pp_smu_status status = 0;
int is_green_sardine = 0;
#if defined(CONFIG_DRM_AMD_DC_DCN)
#if defined(CONFIG_DRM_AMD_DC_FP)
is_green_sardine = ASICREV_IS_GREEN_SARDINE(ctx->asic_id.hw_internal_rev);
#endif

View File

@ -108,6 +108,11 @@ static int dcn314_get_active_display_cnt_wa(
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_dp_signal(stream->signal) && !stream->dpms_off)
display_count++;
}
for (i = 0; i < dc->link_count; i++) {

View File

@ -255,27 +255,60 @@ static void dcn32_update_dppclk_dispclk_freq(struct clk_mgr_internal *clk_mgr, s
}
}
void dcn32_update_clocks_update_dpp_dto(struct clk_mgr_internal *clk_mgr,
struct dc_state *context, bool safe_to_lower)
{
int i;
clk_mgr->dccg->ref_dppclk = clk_mgr->base.clks.dppclk_khz;
for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) {
int dpp_inst, dppclk_khz, prev_dppclk_khz;
dppclk_khz = context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz;
if (context->res_ctx.pipe_ctx[i].plane_res.dpp)
dpp_inst = context->res_ctx.pipe_ctx[i].plane_res.dpp->inst;
else if (!context->res_ctx.pipe_ctx[i].plane_res.dpp && dppclk_khz == 0) {
/* dpp == NULL && dppclk_khz == 0 is valid because of pipe harvesting.
* In this case just continue in loop
*/
continue;
} else if (!context->res_ctx.pipe_ctx[i].plane_res.dpp && dppclk_khz > 0) {
/* The software state is not valid if dpp resource is NULL and
* dppclk_khz > 0.
*/
ASSERT(false);
continue;
}
prev_dppclk_khz = clk_mgr->dccg->pipe_dppclk_khz[i];
if (safe_to_lower || prev_dppclk_khz < dppclk_khz)
clk_mgr->dccg->funcs->update_dpp_dto(
clk_mgr->dccg, dpp_inst, dppclk_khz);
}
}
static void dcn32_update_clocks_update_dentist(
struct clk_mgr_internal *clk_mgr,
struct dc_state *context,
uint32_t old_dispclk_khz)
struct dc_state *context)
{
uint32_t new_disp_divider = 0;
uint32_t old_disp_divider = 0;
uint32_t new_dispclk_wdivider = 0;
uint32_t old_dispclk_wdivider = 0;
uint32_t i;
uint32_t dentist_dispclk_wdivider_readback = 0;
struct dc *dc = clk_mgr->base.ctx->dc;
if (old_dispclk_khz == 0 || clk_mgr->base.clks.dispclk_khz == 0)
if (clk_mgr->base.clks.dispclk_khz == 0)
return;
new_disp_divider = DENTIST_DIVIDER_RANGE_SCALE_FACTOR
* clk_mgr->base.dentist_vco_freq_khz / clk_mgr->base.clks.dispclk_khz;
old_disp_divider = DENTIST_DIVIDER_RANGE_SCALE_FACTOR
* clk_mgr->base.dentist_vco_freq_khz / old_dispclk_khz;
new_dispclk_wdivider = dentist_get_did_from_divider(new_disp_divider);
old_dispclk_wdivider = dentist_get_did_from_divider(old_disp_divider);
REG_GET(DENTIST_DISPCLK_CNTL,
DENTIST_DISPCLK_WDIVIDER, &old_dispclk_wdivider);
/* When changing divider to or from 127, some extra programming is required to prevent corruption */
if (old_dispclk_wdivider == 127 && new_dispclk_wdivider != 127) {
@ -314,6 +347,17 @@ static void dcn32_update_clocks_update_dentist(
if (clk_mgr->smu_present)
dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DISPCLK, khz_to_mhz_ceil(temp_dispclk_khz));
if (dc->debug.override_dispclk_programming) {
REG_GET(DENTIST_DISPCLK_CNTL,
DENTIST_DISPCLK_WDIVIDER, &dentist_dispclk_wdivider_readback);
if (dentist_dispclk_wdivider_readback != 126) {
REG_UPDATE(DENTIST_DISPCLK_CNTL,
DENTIST_DISPCLK_WDIVIDER, 126);
REG_WAIT(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, 1, 50, 2000);
}
}
for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
struct dccg *dccg = clk_mgr->base.ctx->dc->res_pool->dccg;
@ -341,6 +385,18 @@ static void dcn32_update_clocks_update_dentist(
/* do requested DISPCLK updates*/
if (clk_mgr->smu_present)
dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DISPCLK, khz_to_mhz_ceil(clk_mgr->base.clks.dispclk_khz));
if (dc->debug.override_dispclk_programming) {
REG_GET(DENTIST_DISPCLK_CNTL,
DENTIST_DISPCLK_WDIVIDER, &dentist_dispclk_wdivider_readback);
if (dentist_dispclk_wdivider_readback > new_dispclk_wdivider) {
REG_UPDATE(DENTIST_DISPCLK_CNTL,
DENTIST_DISPCLK_WDIVIDER, new_dispclk_wdivider);
REG_WAIT(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, 1, 50, 2000);
}
}
}
static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
@ -361,7 +417,6 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
bool p_state_change_support;
bool fclk_p_state_change_support;
int total_plane_count;
int old_dispclk_khz = clk_mgr_base->clks.dispclk_khz;
if (dc->work_arounds.skip_clock_update)
return;
@ -503,19 +558,19 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
if (dc->config.forced_clocks == false || (force_reset && safe_to_lower)) {
if (dpp_clock_lowered) {
/* if clock is being lowered, increase DTO before lowering refclk */
dcn20_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower);
dcn32_update_clocks_update_dentist(clk_mgr, context, old_dispclk_khz);
dcn32_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower);
dcn32_update_clocks_update_dentist(clk_mgr, context);
if (clk_mgr->smu_present)
dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DPPCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dppclk_khz));
} else {
/* if clock is being raised, increase refclk before lowering DTO */
if (update_dppclk || update_dispclk)
dcn32_update_clocks_update_dentist(clk_mgr, context, old_dispclk_khz);
dcn32_update_clocks_update_dentist(clk_mgr, context);
/* There is a check inside dcn20_update_clocks_update_dpp_dto which ensures
* that we do not lower dto when it is not safe to lower. We do not need to
* compare the current and new dppclk before calling this function.
*/
dcn20_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower);
dcn32_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower);
}
}

View File

@ -32,6 +32,9 @@ void dcn32_clk_mgr_construct(struct dc_context *ctx,
struct pp_smu_funcs *pp_smu,
struct dccg *dccg);
void dcn32_update_clocks_update_dpp_dto(struct clk_mgr_internal *clk_mgr,
struct dc_state *context, bool safe_to_lower);
void dcn32_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr);

View File

@ -53,7 +53,6 @@
#include "link_encoder.h"
#include "link_enc_cfg.h"
#include "dc_link.h"
#include "link.h"
#include "dm_helpers.h"
#include "mem_input.h"
@ -74,6 +73,8 @@
#include "dc_trace.h"
#include "hw_sequencer_private.h"
#include "dce/dmub_outbox.h"
#define CTX \
@ -147,7 +148,7 @@ static void destroy_links(struct dc *dc)
for (i = 0; i < dc->link_count; i++) {
if (NULL != dc->links[i])
link_destroy(&dc->links[i]);
dc->link_srv->destroy_link(&dc->links[i]);
}
}
@ -216,7 +217,7 @@ static bool create_links(
link_init_params.connector_index = i;
link_init_params.link_index = dc->link_count;
link_init_params.dc = dc;
link = link_create(&link_init_params);
link = dc->link_srv->create_link(&link_init_params);
if (link) {
dc->links[dc->link_count] = link;
@ -238,7 +239,7 @@ static bool create_links(
link_init_params.dc = dc;
link_init_params.is_dpia_link = true;
link = link_create(&link_init_params);
link = dc->link_srv->create_link(&link_init_params);
if (link) {
dc->links[dc->link_count] = link;
link->dc = dc;
@ -399,6 +400,14 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc,
{
int i;
/*
* Don't adjust DRR while there's bandwidth optimizations pending to
* avoid conflicting with firmware updates.
*/
if (dc->ctx->dce_version > DCE_VERSION_MAX)
if (dc->optimized_required || dc->wm_optimized_required)
return false;
stream->adjust.v_total_max = adjust->v_total_max;
stream->adjust.v_total_mid = adjust->v_total_mid;
stream->adjust.v_total_mid_frame_num = adjust->v_total_mid_frame_num;
@ -814,6 +823,9 @@ static void dc_destruct(struct dc *dc)
dc_destroy_resource_pool(dc);
if (dc->link_srv)
link_destroy_link_service(&dc->link_srv);
if (dc->ctx->gpio_service)
dal_gpio_service_destroy(&dc->ctx->gpio_service);
@ -973,6 +985,8 @@ static bool dc_construct(struct dc *dc,
goto fail;
}
dc->link_srv = link_create_link_service();
dc->res_pool = dc_create_resource_pool(dc, init_params, dc_ctx->dce_version);
if (!dc->res_pool)
goto fail;
@ -984,7 +998,7 @@ static bool dc_construct(struct dc *dc,
dc->clk_mgr = dc_clk_mgr_create(dc->ctx, dc->res_pool->pp_smu, dc->res_pool->dccg);
if (!dc->clk_mgr)
goto fail;
#ifdef CONFIG_DRM_AMD_DC_DCN
#ifdef CONFIG_DRM_AMD_DC_FP
dc->clk_mgr->force_smu_not_present = init_params->force_smu_not_present;
if (dc->res_pool->funcs->update_bw_bounding_box) {
@ -1057,6 +1071,53 @@ static void apply_ctx_interdependent_lock(struct dc *dc, struct dc_state *contex
}
}
static void phantom_pipe_blank(
struct dc *dc,
struct timing_generator *tg,
int width,
int height)
{
struct dce_hwseq *hws = dc->hwseq;
enum dc_color_space color_space;
struct tg_color black_color = {0};
struct output_pixel_processor *opp = NULL;
uint32_t num_opps, opp_id_src0, opp_id_src1;
uint32_t otg_active_width, otg_active_height;
uint32_t i;
/* program opp dpg blank color */
color_space = COLOR_SPACE_SRGB;
color_space_to_black_color(dc, color_space, &black_color);
otg_active_width = width;
otg_active_height = height;
/* get the OPTC source */
tg->funcs->get_optc_source(tg, &num_opps, &opp_id_src0, &opp_id_src1);
ASSERT(opp_id_src0 < dc->res_pool->res_cap->num_opp);
for (i = 0; i < dc->res_pool->res_cap->num_opp; i++) {
if (dc->res_pool->opps[i] != NULL && dc->res_pool->opps[i]->inst == opp_id_src0) {
opp = dc->res_pool->opps[i];
break;
}
}
if (opp && opp->funcs->opp_set_disp_pattern_generator)
opp->funcs->opp_set_disp_pattern_generator(
opp,
CONTROLLER_DP_TEST_PATTERN_SOLID_COLOR,
CONTROLLER_DP_COLOR_SPACE_UDEFINED,
COLOR_DEPTH_UNDEFINED,
&black_color,
otg_active_width,
otg_active_height,
0);
if (tg->funcs->is_tg_enabled(tg))
hws->funcs.wait_for_blank_complete(opp);
}
static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
{
int i, j;
@ -1115,8 +1176,14 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
* again for different use.
*/
if (old_stream->mall_stream_config.type == SUBVP_PHANTOM) {
if (tg->funcs->enable_crtc)
if (tg->funcs->enable_crtc) {
int main_pipe_width, main_pipe_height;
main_pipe_width = old_stream->mall_stream_config.paired_stream->dst.width;
main_pipe_height = old_stream->mall_stream_config.paired_stream->dst.height;
phantom_pipe_blank(dc, tg, main_pipe_width, main_pipe_height);
tg->funcs->enable_crtc(tg);
}
}
dc_rem_all_planes_for_stream(dc, old_stream, dangling_context);
disable_all_writeback_pipes_for_stream(dc, old_stream, dangling_context);
@ -1199,7 +1266,7 @@ static void disable_vbios_mode_if_required(
pipe->stream_res.pix_clk_params.requested_pix_clk_100hz;
if (pix_clk_100hz != requested_pix_clk_100hz) {
link_set_dpms_off(pipe);
dc->link_srv->set_dpms_off(pipe);
pipe->stream->dpms_off = false;
}
}
@ -1298,7 +1365,7 @@ static void detect_edp_presence(struct dc *dc)
int i;
int edp_num;
get_edp_links(dc, edp_links, &edp_num);
dc_get_edp_links(dc, edp_links, &edp_num);
if (!edp_num)
return;
@ -1324,16 +1391,12 @@ void dc_hardware_init(struct dc *dc)
void dc_init_callbacks(struct dc *dc,
const struct dc_callback_init *init_params)
{
#ifdef CONFIG_DRM_AMD_DC_HDCP
dc->ctx->cp_psp = init_params->cp_psp;
#endif
}
void dc_deinit_callbacks(struct dc *dc)
{
#ifdef CONFIG_DRM_AMD_DC_HDCP
memset(&dc->ctx->cp_psp, 0, sizeof(dc->ctx->cp_psp));
#endif
}
void dc_destroy(struct dc **dc)
@ -1658,7 +1721,7 @@ bool dc_validate_boot_timing(const struct dc *dc,
return false;
}
if (link_is_edp_ilr_optimization_required(link, crtc_timing)) {
if (dc->link_srv->edp_is_ilr_optimization_required(link, crtc_timing)) {
DC_LOG_EVENT_LINK_TRAINING("Seamless boot disabled to optimize eDP link rate\n");
return false;
}
@ -2001,53 +2064,6 @@ enum dc_status dc_commit_streams(struct dc *dc,
return res;
}
/* TODO: When the transition to the new commit sequence is done, remove this
* function in favor of dc_commit_streams. */
bool dc_commit_state(struct dc *dc, struct dc_state *context)
{
enum dc_status result = DC_ERROR_UNEXPECTED;
int i;
/* TODO: Since change commit sequence can have a huge impact,
* we decided to only enable it for DCN3x. However, as soon as
* we get more confident about this change we'll need to enable
* the new sequence for all ASICs. */
if (dc->ctx->dce_version >= DCN_VERSION_3_2) {
result = dc_commit_streams(dc, context->streams, context->stream_count);
return result == DC_OK;
}
if (!streams_changed(dc, context->streams, context->stream_count)) {
return DC_OK;
}
DC_LOG_DC("%s: %d streams\n",
__func__, context->stream_count);
for (i = 0; i < context->stream_count; i++) {
struct dc_stream_state *stream = context->streams[i];
dc_stream_log(dc, stream);
}
/*
* Previous validation was perfomred with fast_validation = true and
* the full DML state required for hardware programming was skipped.
*
* Re-validate here to calculate these parameters / watermarks.
*/
result = dc_validate_global_state(dc, context, false);
if (result != DC_OK) {
DC_LOG_ERROR("DC commit global validation failure: %s (%d)",
dc_status_to_str(result), result);
return result;
}
result = dc_commit_state_no_check(dc, context);
return (result == DC_OK);
}
bool dc_acquire_release_mpc_3dlut(
struct dc *dc, bool acquire,
struct dc_stream_state *stream,
@ -2134,27 +2150,33 @@ void dc_post_update_surfaces_to_stream(struct dc *dc)
post_surface_trace(dc);
if (dc->ctx->dce_version >= DCE_VERSION_MAX)
TRACE_DCN_CLOCK_STATE(&context->bw_ctx.bw.dcn.clk);
else
/*
* Only relevant for DCN behavior where we can guarantee the optimization
* is safe to apply - retain the legacy behavior for DCE.
*/
if (dc->ctx->dce_version < DCE_VERSION_MAX)
TRACE_DCE_CLOCK_STATE(&context->bw_ctx.bw.dce);
else {
TRACE_DCN_CLOCK_STATE(&context->bw_ctx.bw.dcn.clk);
if (is_flip_pending_in_pipes(dc, context))
return;
if (is_flip_pending_in_pipes(dc, context))
return;
for (i = 0; i < dc->res_pool->pipe_count; i++)
if (context->res_ctx.pipe_ctx[i].stream == NULL ||
context->res_ctx.pipe_ctx[i].plane_state == NULL) {
context->res_ctx.pipe_ctx[i].pipe_idx = i;
dc->hwss.disable_plane(dc, &context->res_ctx.pipe_ctx[i]);
}
for (i = 0; i < dc->res_pool->pipe_count; i++)
if (context->res_ctx.pipe_ctx[i].stream == NULL ||
context->res_ctx.pipe_ctx[i].plane_state == NULL) {
context->res_ctx.pipe_ctx[i].pipe_idx = i;
dc->hwss.disable_plane(dc, &context->res_ctx.pipe_ctx[i]);
}
process_deferred_updates(dc);
process_deferred_updates(dc);
dc->hwss.optimize_bandwidth(dc, context);
dc->hwss.optimize_bandwidth(dc, context);
if (dc->debug.enable_double_buffered_dsc_pg_support)
dc->hwss.update_dsc_pg(dc, context, true);
if (dc->debug.enable_double_buffered_dsc_pg_support)
dc->hwss.update_dsc_pg(dc, context, true);
}
dc->optimized_required = false;
dc->wm_optimized_required = false;
@ -3173,7 +3195,9 @@ static void commit_planes_do_stream_update(struct dc *dc,
dc->hwss.update_info_frame(pipe_ctx);
if (dc_is_dp_signal(pipe_ctx->stream->signal))
link_dp_source_sequence_trace(pipe_ctx->stream->link, DPCD_SOURCE_SEQ_AFTER_UPDATE_INFO_FRAME);
dc->link_srv->dp_trace_source_sequence(
pipe_ctx->stream->link,
DPCD_SOURCE_SEQ_AFTER_UPDATE_INFO_FRAME);
}
if (stream_update->hdr_static_metadata &&
@ -3209,13 +3233,15 @@ static void commit_planes_do_stream_update(struct dc *dc,
continue;
if (stream_update->dsc_config)
link_update_dsc_config(pipe_ctx);
dc->link_srv->update_dsc_config(pipe_ctx);
if (stream_update->mst_bw_update) {
if (stream_update->mst_bw_update->is_increase)
link_increase_mst_payload(pipe_ctx, stream_update->mst_bw_update->mst_stream_bw);
dc->link_srv->increase_mst_payload(pipe_ctx,
stream_update->mst_bw_update->mst_stream_bw);
else
link_reduce_mst_payload(pipe_ctx, stream_update->mst_bw_update->mst_stream_bw);
dc->link_srv->reduce_mst_payload(pipe_ctx,
stream_update->mst_bw_update->mst_stream_bw);
}
if (stream_update->pending_test_pattern) {
@ -3229,7 +3255,7 @@ static void commit_planes_do_stream_update(struct dc *dc,
if (stream_update->dpms_off) {
if (*stream_update->dpms_off) {
link_set_dpms_off(pipe_ctx);
dc->link_srv->set_dpms_off(pipe_ctx);
/* for dpms, keep acquired resources*/
if (pipe_ctx->stream_res.audio && !dc->debug.az_endpoint_mute_only)
pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
@ -3239,7 +3265,7 @@ static void commit_planes_do_stream_update(struct dc *dc,
} else {
if (get_seamless_boot_stream_count(context) == 0)
dc->hwss.prepare_bandwidth(dc, dc->current_state);
link_set_dpms_on(dc->current_state, pipe_ctx);
dc->link_srv->set_dpms_on(dc->current_state, pipe_ctx);
}
}
@ -3510,14 +3536,9 @@ static void commit_planes_for_stream(struct dc *dc,
/* Since phantom pipe programming is moved to post_unlock_program_front_end,
* move the SubVP lock to after the phantom pipes have been setup
*/
if (should_lock_all_pipes && dc->hwss.interdependent_update_lock) {
if (dc->hwss.subvp_pipe_control_lock)
dc->hwss.subvp_pipe_control_lock(dc, context, false, should_lock_all_pipes, NULL, subvp_prev_use);
} else {
if (dc->hwss.subvp_pipe_control_lock)
dc->hwss.subvp_pipe_control_lock(dc, context, false, should_lock_all_pipes, NULL, subvp_prev_use);
}
if (dc->hwss.subvp_pipe_control_lock)
dc->hwss.subvp_pipe_control_lock(dc, context, false, should_lock_all_pipes,
NULL, subvp_prev_use);
return;
}
@ -4083,24 +4104,30 @@ void dc_commit_updates_for_stream(struct dc *dc,
struct dc_context *dc_ctx = dc->ctx;
int i, j;
stream_status = dc_stream_get_status(stream);
context = dc->current_state;
update_type = dc_check_update_surfaces_for_stream(
dc, srf_updates, surface_count, stream_update, stream_status);
/* TODO: Since change commit sequence can have a huge impact,
* we decided to only enable it for DCN3x. However, as soon as
* we get more confident about this change we'll need to enable
* the new sequence for all ASICs.
*/
if (dc->ctx->dce_version >= DCN_VERSION_3_2) {
/*
* Previous frame finished and HW is ready for optimization.
*/
if (update_type == UPDATE_TYPE_FAST)
dc_post_update_surfaces_to_stream(dc);
dc_update_planes_and_stream(dc, srf_updates,
surface_count, stream,
stream_update);
return;
}
stream_status = dc_stream_get_status(stream);
context = dc->current_state;
update_type = dc_check_update_surfaces_for_stream(
dc, srf_updates, surface_count, stream_update, stream_status);
if (update_type >= update_surface_trace_level)
update_surface_trace(dc, srf_updates, surface_count);
@ -4123,12 +4150,9 @@ void dc_commit_updates_for_stream(struct dc *dc,
if (new_pipe->plane_state && new_pipe->plane_state != old_pipe->plane_state)
new_pipe->plane_state->force_full_update = true;
}
} else if (update_type == UPDATE_TYPE_FAST && dc_ctx->dce_version >= DCE_VERSION_MAX) {
} else if (update_type == UPDATE_TYPE_FAST) {
/*
* Previous frame finished and HW is ready for optimization.
*
* Only relevant for DCN behavior where we can guarantee the optimization
* is safe to apply - retain the legacy behavior for DCE.
*/
dc_post_update_surfaces_to_stream(dc);
}
@ -4305,7 +4329,7 @@ void dc_resume(struct dc *dc)
uint32_t i;
for (i = 0; i < dc->link_count; i++)
link_resume(dc->links[i]);
dc->link_srv->resume(dc->links[i]);
}
bool dc_is_dmcu_initialized(struct dc *dc)
@ -4317,157 +4341,6 @@ bool dc_is_dmcu_initialized(struct dc *dc)
return false;
}
bool dc_is_oem_i2c_device_present(
struct dc *dc,
size_t slave_address)
{
if (dc->res_pool->oem_device)
return dce_i2c_oem_device_present(
dc->res_pool,
dc->res_pool->oem_device,
slave_address);
return false;
}
bool dc_submit_i2c(
struct dc *dc,
uint32_t link_index,
struct i2c_command *cmd)
{
struct dc_link *link = dc->links[link_index];
struct ddc_service *ddc = link->ddc;
return dce_i2c_submit_command(
dc->res_pool,
ddc->ddc_pin,
cmd);
}
bool dc_submit_i2c_oem(
struct dc *dc,
struct i2c_command *cmd)
{
struct ddc_service *ddc = dc->res_pool->oem_device;
if (ddc)
return dce_i2c_submit_command(
dc->res_pool,
ddc->ddc_pin,
cmd);
return false;
}
static bool link_add_remote_sink_helper(struct dc_link *dc_link, struct dc_sink *sink)
{
if (dc_link->sink_count >= MAX_SINKS_PER_LINK) {
BREAK_TO_DEBUGGER();
return false;
}
dc_sink_retain(sink);
dc_link->remote_sinks[dc_link->sink_count] = sink;
dc_link->sink_count++;
return true;
}
/*
* dc_link_add_remote_sink() - Create a sink and attach it to an existing link
*
* EDID length is in bytes
*/
struct dc_sink *dc_link_add_remote_sink(
struct dc_link *link,
const uint8_t *edid,
int len,
struct dc_sink_init_data *init_data)
{
struct dc_sink *dc_sink;
enum dc_edid_status edid_status;
if (len > DC_MAX_EDID_BUFFER_SIZE) {
dm_error("Max EDID buffer size breached!\n");
return NULL;
}
if (!init_data) {
BREAK_TO_DEBUGGER();
return NULL;
}
if (!init_data->link) {
BREAK_TO_DEBUGGER();
return NULL;
}
dc_sink = dc_sink_create(init_data);
if (!dc_sink)
return NULL;
memmove(dc_sink->dc_edid.raw_edid, edid, len);
dc_sink->dc_edid.length = len;
if (!link_add_remote_sink_helper(
link,
dc_sink))
goto fail_add_sink;
edid_status = dm_helpers_parse_edid_caps(
link,
&dc_sink->dc_edid,
&dc_sink->edid_caps);
/*
* Treat device as no EDID device if EDID
* parsing fails
*/
if (edid_status != EDID_OK && edid_status != EDID_PARTIAL_VALID) {
dc_sink->dc_edid.length = 0;
dm_error("Bad EDID, status%d!\n", edid_status);
}
return dc_sink;
fail_add_sink:
dc_sink_release(dc_sink);
return NULL;
}
/*
* dc_link_remove_remote_sink() - Remove a remote sink from a dc_link
*
* Note that this just removes the struct dc_sink - it doesn't
* program hardware or alter other members of dc_link
*/
void dc_link_remove_remote_sink(struct dc_link *link, struct dc_sink *sink)
{
int i;
if (!link->sink_count) {
BREAK_TO_DEBUGGER();
return;
}
for (i = 0; i < link->sink_count; i++) {
if (link->remote_sinks[i] == sink) {
dc_sink_release(sink);
link->remote_sinks[i] = NULL;
/* shrink array to remove empty place */
while (i < link->sink_count - 1) {
link->remote_sinks[i] = link->remote_sinks[i+1];
i++;
}
link->remote_sinks[i] = NULL;
link->sink_count--;
return;
}
}
}
void get_clock_requirements_for_state(struct dc_state *state, struct AsicStateEx *info)
{
info->displayClock = (unsigned int)state->bw_ctx.bw.dcn.clk.dispclk_khz;
@ -4990,7 +4863,7 @@ void dc_notify_vsync_int_state(struct dc *dc, struct dc_stream_state *stream, bo
return;
}
get_edp_links(dc, edp_links, &edp_num);
dc_get_edp_links(dc, edp_links, &edp_num);
/* Determine panel inst */
for (i = 0; i < edp_num; i++) {

View File

@ -73,28 +73,38 @@ struct out_csc_color_matrix_type {
static const struct out_csc_color_matrix_type output_csc_matrix[] = {
{ COLOR_SPACE_RGB_TYPE,
{ 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
{ 0x2000, 0, 0, 0,
0, 0x2000, 0, 0,
0, 0, 0x2000, 0} },
{ COLOR_SPACE_RGB_LIMITED_TYPE,
{ 0x1B67, 0, 0, 0x201, 0, 0x1B67, 0, 0x201, 0, 0, 0x1B67, 0x201} },
{ 0x1B67, 0, 0, 0x201,
0, 0x1B67, 0, 0x201,
0, 0, 0x1B67, 0x201} },
{ COLOR_SPACE_YCBCR601_TYPE,
{ 0xE04, 0xF444, 0xFDB9, 0x1004, 0x831, 0x1016, 0x320, 0x201, 0xFB45,
0xF6B7, 0xE04, 0x1004} },
{ 0xE04, 0xF444, 0xFDB9, 0x1004,
0x831, 0x1016, 0x320, 0x201,
0xFB45, 0xF6B7, 0xE04, 0x1004} },
{ COLOR_SPACE_YCBCR709_TYPE,
{ 0xE04, 0xF345, 0xFEB7, 0x1004, 0x5D3, 0x1399, 0x1FA,
0x201, 0xFCCA, 0xF533, 0xE04, 0x1004} },
{ 0xE04, 0xF345, 0xFEB7, 0x1004,
0x5D3, 0x1399, 0x1FA, 0x201,
0xFCCA, 0xF533, 0xE04, 0x1004} },
/* TODO: correct values below */
{ COLOR_SPACE_YCBCR601_LIMITED_TYPE,
{ 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991,
0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} },
{ 0xE00, 0xF447, 0xFDB9, 0x1000,
0x991, 0x12C9, 0x3A6, 0x200,
0xFB47, 0xF6B9, 0xE00, 0x1000} },
{ COLOR_SPACE_YCBCR709_LIMITED_TYPE,
{ 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3,
0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} },
{ 0xE00, 0xF349, 0xFEB7, 0x1000,
0x6CE, 0x16E3, 0x24F, 0x200,
0xFCCB, 0xF535, 0xE00, 0x1000} },
{ COLOR_SPACE_YCBCR2020_TYPE,
{ 0x1000, 0xF149, 0xFEB7, 0x1004, 0x0868, 0x15B2,
0x01E6, 0x201, 0xFB88, 0xF478, 0x1000, 0x1004} },
{ 0x1000, 0xF149, 0xFEB7, 0x1004,
0x0868, 0x15B2, 0x01E6, 0x201,
0xFB88, 0xF478, 0x1000, 0x1004} },
{ COLOR_SPACE_YCBCR709_BLACK_TYPE,
{ 0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x0000,
0x0000, 0x0200, 0x0000, 0x0000, 0x0000, 0x1000} },
{ 0x0000, 0x0000, 0x0000, 0x1000,
0x0000, 0x0000, 0x0000, 0x0200,
0x0000, 0x0000, 0x0000, 0x1000} },
};
static bool is_rgb_type(

View File

@ -48,7 +48,7 @@ static bool is_dig_link_enc_stream(struct dc_stream_state *stream)
/* DIGs do not support DP2.0 streams with 128b/132b encoding. */
struct dc_link_settings link_settings = {0};
link_decide_link_settings(stream, &link_settings);
stream->ctx->dc->link_srv->dp_decide_link_settings(stream, &link_settings);
if ((link_settings.link_rate >= LINK_RATE_LOW) &&
link_settings.link_rate <= LINK_RATE_HIGH3) {
is_dig_stream = true;

View File

@ -34,70 +34,443 @@
* in this file which calls link functions.
*/
#include "link.h"
#include "dce/dce_i2c.h"
struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index)
{
return dc->links[link_index];
}
void dc_get_edp_links(const struct dc *dc,
struct dc_link **edp_links,
int *edp_num)
{
int i;
*edp_num = 0;
for (i = 0; i < dc->link_count; i++) {
// report any eDP links, even unconnected DDI's
if (!dc->links[i])
continue;
if (dc->links[i]->connector_signal == SIGNAL_TYPE_EDP) {
edp_links[*edp_num] = dc->links[i];
if (++(*edp_num) == MAX_NUM_EDP)
return;
}
}
}
bool dc_get_edp_link_panel_inst(const struct dc *dc,
const struct dc_link *link,
unsigned int *inst_out)
{
struct dc_link *edp_links[MAX_NUM_EDP];
int edp_num, i;
*inst_out = 0;
if (link->connector_signal != SIGNAL_TYPE_EDP)
return false;
dc_get_edp_links(dc, edp_links, &edp_num);
for (i = 0; i < edp_num; i++) {
if (link == edp_links[i])
break;
(*inst_out)++;
}
return true;
}
bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
{
return link_detect(link, reason);
return link->dc->link_srv->detect_link(link, reason);
}
bool dc_link_detect_connection_type(struct dc_link *link,
enum dc_connection_type *type)
{
return link_detect_connection_type(link, type);
return link->dc->link_srv->detect_connection_type(link, type);
}
const struct dc_link_status *dc_link_get_status(const struct dc_link *link)
{
return link_get_status(link);
return link->dc->link_srv->get_status(link);
}
#ifdef CONFIG_DRM_AMD_DC_HDCP
/* return true if the connected receiver supports the hdcp version */
bool dc_link_is_hdcp14(struct dc_link *link, enum signal_type signal)
{
return link_is_hdcp14(link, signal);
return link->dc->link_srv->is_hdcp1x_supported(link, signal);
}
bool dc_link_is_hdcp22(struct dc_link *link, enum signal_type signal)
{
return link_is_hdcp22(link, signal);
return link->dc->link_srv->is_hdcp2x_supported(link, signal);
}
#endif
void dc_link_clear_dprx_states(struct dc_link *link)
{
link_clear_dprx_states(link);
link->dc->link_srv->clear_dprx_states(link);
}
bool dc_link_reset_cur_dp_mst_topology(struct dc_link *link)
{
return link_reset_cur_dp_mst_topology(link);
return link->dc->link_srv->reset_cur_dp_mst_topology(link);
}
uint32_t dc_link_bandwidth_kbps(
const struct dc_link *link,
const struct dc_link_settings *link_settings)
{
return dp_link_bandwidth_kbps(link, link_settings);
}
uint32_t dc_bandwidth_in_kbps_from_timing(
const struct dc_crtc_timing *timing)
{
return link_timing_bandwidth_kbps(timing);
return link->dc->link_srv->dp_link_bandwidth_kbps(link, link_settings);
}
void dc_get_cur_link_res_map(const struct dc *dc, uint32_t *map)
{
link_get_cur_res_map(dc, map);
dc->link_srv->get_cur_res_map(dc, map);
}
void dc_restore_link_res_map(const struct dc *dc, uint32_t *map)
{
link_restore_res_map(dc, map);
dc->link_srv->restore_res_map(dc, map);
}
bool dc_link_update_dsc_config(struct pipe_ctx *pipe_ctx)
{
return link_update_dsc_config(pipe_ctx);
struct dc_link *link = pipe_ctx->stream->link;
return link->dc->link_srv->update_dsc_config(pipe_ctx);
}
bool dc_is_oem_i2c_device_present(
struct dc *dc,
size_t slave_address)
{
if (dc->res_pool->oem_device)
return dce_i2c_oem_device_present(
dc->res_pool,
dc->res_pool->oem_device,
slave_address);
return false;
}
bool dc_submit_i2c(
struct dc *dc,
uint32_t link_index,
struct i2c_command *cmd)
{
struct dc_link *link = dc->links[link_index];
struct ddc_service *ddc = link->ddc;
return dce_i2c_submit_command(
dc->res_pool,
ddc->ddc_pin,
cmd);
}
bool dc_submit_i2c_oem(
struct dc *dc,
struct i2c_command *cmd)
{
struct ddc_service *ddc = dc->res_pool->oem_device;
if (ddc)
return dce_i2c_submit_command(
dc->res_pool,
ddc->ddc_pin,
cmd);
return false;
}
void dc_link_dp_handle_automated_test(struct dc_link *link)
{
link->dc->link_srv->dp_handle_automated_test(link);
}
bool dc_link_dp_set_test_pattern(
struct dc_link *link,
enum dp_test_pattern test_pattern,
enum dp_test_pattern_color_space test_pattern_color_space,
const struct link_training_settings *p_link_settings,
const unsigned char *p_custom_pattern,
unsigned int cust_pattern_size)
{
return link->dc->link_srv->dp_set_test_pattern(link, test_pattern,
test_pattern_color_space, p_link_settings,
p_custom_pattern, cust_pattern_size);
}
void dc_link_set_drive_settings(struct dc *dc,
struct link_training_settings *lt_settings,
struct dc_link *link)
{
struct link_resource link_res;
dc->link_srv->get_cur_link_res(link, &link_res);
dc->link_srv->dp_set_drive_settings(link, &link_res, lt_settings);
}
void dc_link_set_preferred_link_settings(struct dc *dc,
struct dc_link_settings *link_setting,
struct dc_link *link)
{
dc->link_srv->dp_set_preferred_link_settings(dc, link_setting, link);
}
void dc_link_set_preferred_training_settings(struct dc *dc,
struct dc_link_settings *link_setting,
struct dc_link_training_overrides *lt_overrides,
struct dc_link *link,
bool skip_immediate_retrain)
{
dc->link_srv->dp_set_preferred_training_settings(dc, link_setting,
lt_overrides, link, skip_immediate_retrain);
}
bool dc_dp_trace_is_initialized(struct dc_link *link)
{
return link->dc->link_srv->dp_trace_is_initialized(link);
}
void dc_dp_trace_set_is_logged_flag(struct dc_link *link,
bool in_detection,
bool is_logged)
{
link->dc->link_srv->dp_trace_set_is_logged_flag(link, in_detection, is_logged);
}
bool dc_dp_trace_is_logged(struct dc_link *link, bool in_detection)
{
return link->dc->link_srv->dp_trace_is_logged(link, in_detection);
}
unsigned long long dc_dp_trace_get_lt_end_timestamp(struct dc_link *link,
bool in_detection)
{
return link->dc->link_srv->dp_trace_get_lt_end_timestamp(link, in_detection);
}
const struct dp_trace_lt_counts *dc_dp_trace_get_lt_counts(struct dc_link *link,
bool in_detection)
{
return link->dc->link_srv->dp_trace_get_lt_counts(link, in_detection);
}
unsigned int dc_dp_trace_get_link_loss_count(struct dc_link *link)
{
return link->dc->link_srv->dp_trace_get_link_loss_count(link);
}
struct dc_sink *dc_link_add_remote_sink(
struct dc_link *link,
const uint8_t *edid,
int len,
struct dc_sink_init_data *init_data)
{
return link->dc->link_srv->add_remote_sink(link, edid, len, init_data);
}
void dc_link_remove_remote_sink(struct dc_link *link, struct dc_sink *sink)
{
link->dc->link_srv->remove_remote_sink(link, sink);
}
int dc_link_aux_transfer_raw(struct ddc_service *ddc,
struct aux_payload *payload,
enum aux_return_code_type *operation_result)
{
const struct dc *dc = ddc->link->dc;
return dc->link_srv->aux_transfer_raw(
ddc, payload, operation_result);
}
uint32_t dc_link_bw_kbps_from_raw_frl_link_rate_data(
struct dc *dc, uint8_t bw)
{
return dc->link_srv->bw_kbps_from_raw_frl_link_rate_data(bw);
}
bool dc_link_decide_edp_link_settings(struct dc_link *link,
struct dc_link_settings *link_setting, uint32_t req_bw)
{
return link->dc->link_srv->edp_decide_link_settings(link, link_setting, req_bw);
}
bool dc_link_dp_get_max_link_enc_cap(const struct dc_link *link,
struct dc_link_settings *max_link_enc_cap)
{
return link->dc->link_srv->dp_get_max_link_enc_cap(link, max_link_enc_cap);
}
enum dp_link_encoding dc_link_dp_mst_decide_link_encoding_format(
const struct dc_link *link)
{
return link->dc->link_srv->mst_decide_link_encoding_format(link);
}
const struct dc_link_settings *dc_link_get_link_cap(const struct dc_link *link)
{
return link->dc->link_srv->dp_get_verified_link_cap(link);
}
bool dc_link_is_dp_sink_present(struct dc_link *link)
{
return link->dc->link_srv->dp_is_sink_present(link);
}
bool dc_link_is_fec_supported(const struct dc_link *link)
{
return link->dc->link_srv->dp_is_fec_supported(link);
}
void dc_link_overwrite_extended_receiver_cap(
struct dc_link *link)
{
link->dc->link_srv->dp_overwrite_extended_receiver_cap(link);
}
bool dc_link_should_enable_fec(const struct dc_link *link)
{
return link->dc->link_srv->dp_should_enable_fec(link);
}
int dc_link_dp_dpia_handle_usb4_bandwidth_allocation_for_link(
struct dc_link *link, int peak_bw)
{
return link->dc->link_srv->dpia_handle_usb4_bandwidth_allocation_for_link(link, peak_bw);
}
void dc_link_handle_usb4_bw_alloc_response(struct dc_link *link, uint8_t bw, uint8_t result)
{
link->dc->link_srv->dpia_handle_bw_alloc_response(link, bw, result);
}
bool dc_link_check_link_loss_status(
struct dc_link *link,
union hpd_irq_data *hpd_irq_dpcd_data)
{
return link->dc->link_srv->dp_parse_link_loss_status(link, hpd_irq_dpcd_data);
}
bool dc_link_dp_allow_hpd_rx_irq(const struct dc_link *link)
{
return link->dc->link_srv->dp_should_allow_hpd_rx_irq(link);
}
void dc_link_dp_handle_link_loss(struct dc_link *link)
{
link->dc->link_srv->dp_handle_link_loss(link);
}
enum dc_status dc_link_dp_read_hpd_rx_irq_data(
struct dc_link *link,
union hpd_irq_data *irq_data)
{
return link->dc->link_srv->dp_read_hpd_rx_irq_data(link, irq_data);
}
bool dc_link_handle_hpd_rx_irq(struct dc_link *link,
union hpd_irq_data *out_hpd_irq_dpcd_data, bool *out_link_loss,
bool defer_handling, bool *has_left_work)
{
return link->dc->link_srv->dp_handle_hpd_rx_irq(link, out_hpd_irq_dpcd_data,
out_link_loss, defer_handling, has_left_work);
}
void dc_link_dp_receiver_power_ctrl(struct dc_link *link, bool on)
{
link->dc->link_srv->dpcd_write_rx_power_ctrl(link, on);
}
enum lttpr_mode dc_link_decide_lttpr_mode(struct dc_link *link,
struct dc_link_settings *link_setting)
{
return link->dc->link_srv->dp_decide_lttpr_mode(link, link_setting);
}
void dc_link_edp_panel_backlight_power_on(struct dc_link *link, bool wait_for_hpd)
{
link->dc->link_srv->edp_panel_backlight_power_on(link, wait_for_hpd);
}
int dc_link_get_backlight_level(const struct dc_link *link)
{
return link->dc->link_srv->edp_get_backlight_level(link);
}
bool dc_link_get_backlight_level_nits(struct dc_link *link,
uint32_t *backlight_millinits_avg,
uint32_t *backlight_millinits_peak)
{
return link->dc->link_srv->edp_get_backlight_level_nits(link,
backlight_millinits_avg,
backlight_millinits_peak);
}
bool dc_link_set_backlight_level(const struct dc_link *link,
uint32_t backlight_pwm_u16_16,
uint32_t frame_ramp)
{
return link->dc->link_srv->edp_set_backlight_level(link,
backlight_pwm_u16_16, frame_ramp);
}
bool dc_link_set_backlight_level_nits(struct dc_link *link,
bool isHDR,
uint32_t backlight_millinits,
uint32_t transition_time_in_ms)
{
return link->dc->link_srv->edp_set_backlight_level_nits(link, isHDR,
backlight_millinits, transition_time_in_ms);
}
int dc_link_get_target_backlight_pwm(const struct dc_link *link)
{
return link->dc->link_srv->edp_get_target_backlight_pwm(link);
}
bool dc_link_get_psr_state(const struct dc_link *link, enum dc_psr_state *state)
{
return link->dc->link_srv->edp_get_psr_state(link, state);
}
bool dc_link_set_psr_allow_active(struct dc_link *link, const bool *allow_active,
bool wait, bool force_static, const unsigned int *power_opts)
{
return link->dc->link_srv->edp_set_psr_allow_active(link, allow_active, wait,
force_static, power_opts);
}
bool dc_link_setup_psr(struct dc_link *link,
const struct dc_stream_state *stream, struct psr_config *psr_config,
struct psr_context *psr_context)
{
return link->dc->link_srv->edp_setup_psr(link, stream, psr_config, psr_context);
}
bool dc_link_wait_for_t12(struct dc_link *link)
{
return link->dc->link_srv->edp_wait_for_t12(link);
}
bool dc_link_get_hpd_state(struct dc_link *link)
{
return link->dc->link_srv->get_hpd_state(link);
}
void dc_link_enable_hpd(const struct dc_link *link)
{
link->dc->link_srv->enable_hpd(link);
}
void dc_link_disable_hpd(const struct dc_link *link)
{
link->dc->link_srv->disable_hpd(link);
}
void dc_link_enable_hpd_filter(struct dc_link *link, bool enable)
{
link->dc->link_srv->enable_hpd_filter(link, enable);
}

View File

@ -232,7 +232,7 @@ struct resource_pool *dc_create_resource_pool(struct dc *dc,
init_data->num_virtual_links, dc);
break;
#if defined(CONFIG_DRM_AMD_DC_DCN)
#if defined(CONFIG_DRM_AMD_DC_FP)
case DCN_VERSION_1_0:
case DCN_VERSION_1_01:
res_pool = dcn10_create_resource_pool(init_data, dc);
@ -276,7 +276,7 @@ struct resource_pool *dc_create_resource_pool(struct dc *dc,
case DCN_VERSION_3_21:
res_pool = dcn321_create_resource_pool(init_data, dc);
break;
#endif
#endif /* CONFIG_DRM_AMD_DC_FP */
default:
break;
}
@ -2213,7 +2213,7 @@ enum dc_status dc_remove_stream_from_ctx(
del_pipe->stream_res.stream_enc,
false);
if (link_is_dp_128b_132b_signal(del_pipe)) {
if (dc->link_srv->dp_is_128b_132b_signal(del_pipe)) {
update_hpo_dp_stream_engine_usage(
&new_ctx->res_ctx, dc->res_pool,
del_pipe->stream_res.hpo_dp_stream_enc,
@ -2513,9 +2513,10 @@ enum dc_status resource_map_pool_resources(
* and link settings
*/
if (dc_is_dp_signal(stream->signal)) {
if (!link_decide_link_settings(stream, &pipe_ctx->link_config.dp_link_settings))
if (!dc->link_srv->dp_decide_link_settings(stream, &pipe_ctx->link_config.dp_link_settings))
return DC_FAIL_DP_LINK_BANDWIDTH;
if (link_dp_get_encoding_format(&pipe_ctx->link_config.dp_link_settings) == DP_128b_132b_ENCODING) {
if (dc->link_srv->dp_get_encoding_format(
&pipe_ctx->link_config.dp_link_settings) == DP_128b_132b_ENCODING) {
pipe_ctx->stream_res.hpo_dp_stream_enc =
find_first_free_match_hpo_dp_stream_enc_for_link(
&context->res_ctx, pool, stream);
@ -3685,7 +3686,7 @@ enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream)
/* TODO: validate audio ASIC caps, encoder */
if (res == DC_OK)
res = link_validate_mode_timing(stream,
res = dc->link_srv->validate_mode_timing(stream,
link,
&stream->timing);
@ -3812,7 +3813,7 @@ bool get_temp_dp_link_res(struct dc_link *link,
memset(link_res, 0, sizeof(*link_res));
if (link_dp_get_encoding_format(link_settings) == DP_128b_132b_ENCODING) {
if (dc->link_srv->dp_get_encoding_format(link_settings) == DP_128b_132b_ENCODING) {
link_res->hpo_dp_link_enc = get_temp_hpo_dp_link_enc(res_ctx,
dc->res_pool, link);
if (!link_res->hpo_dp_link_enc)
@ -4027,14 +4028,14 @@ bool dc_resource_acquire_secondary_pipe_for_mpc_odm(
else
sec_pipe->stream_res.opp = sec_pipe->top_pipe->stream_res.opp;
if (sec_pipe->stream->timing.flags.DSC == 1) {
#if defined(CONFIG_DRM_AMD_DC_DCN)
#if defined(CONFIG_DRM_AMD_DC_FP)
dcn20_acquire_dsc(dc, &state->res_ctx, &sec_pipe->stream_res.dsc, pipe_idx);
#endif
ASSERT(sec_pipe->stream_res.dsc);
if (sec_pipe->stream_res.dsc == NULL)
return false;
}
#if defined(CONFIG_DRM_AMD_DC_DCN)
#if defined(CONFIG_DRM_AMD_DC_FP)
dcn20_build_mapped_resource(dc, state, sec_pipe->stream);
#endif
}
@ -4046,7 +4047,7 @@ enum dc_status update_dp_encoder_resources_for_test_harness(const struct dc *dc,
struct dc_state *context,
struct pipe_ctx *pipe_ctx)
{
if (link_dp_get_encoding_format(&pipe_ctx->link_config.dp_link_settings) == DP_128b_132b_ENCODING) {
if (dc->link_srv->dp_get_encoding_format(&pipe_ctx->link_config.dp_link_settings) == DP_128b_132b_ENCODING) {
if (pipe_ctx->stream_res.hpo_dp_stream_enc == NULL) {
pipe_ctx->stream_res.hpo_dp_stream_enc =
find_first_free_match_hpo_dp_stream_enc_for_link(

View File

@ -47,9 +47,7 @@ int dc_setup_system_context(struct dc *dc, struct dc_phy_addr_space_config *pa_c
*/
memcpy(&dc->vm_pa_config, pa_config, sizeof(struct dc_phy_addr_space_config));
dc->vm_pa_config.valid = true;
#if defined(CONFIG_DRM_AMD_DC_DCN)
dc_z10_save_init(dc);
#endif
}
return num_vmids;

View File

@ -29,9 +29,7 @@
#include "dc_types.h"
#include "grph_object_defs.h"
#include "logger_types.h"
#if defined(CONFIG_DRM_AMD_DC_HDCP)
#include "hdcp_types.h"
#endif
#include "hdcp_msg_types.h"
#include "gpio_types.h"
#include "link_service_types.h"
#include "grph_object_ctrl_defs.h"
@ -47,7 +45,7 @@ struct aux_payload;
struct set_config_cmd_payload;
struct dmub_notification;
#define DC_VER "3.2.223"
#define DC_VER "3.2.227"
#define MAX_SURFACES 3
#define MAX_PLANES 6
@ -84,8 +82,6 @@ enum det_size {
struct dc_plane_cap {
enum dc_plane_type type;
uint32_t blends_with_above : 1;
uint32_t blends_with_below : 1;
uint32_t per_pixel_alpha : 1;
struct {
uint32_t argb8888 : 1;
@ -716,6 +712,7 @@ struct dc_bounding_box_overrides {
struct dc_state;
struct resource_pool;
struct dce_hwseq;
struct link_service;
/**
* struct dc_debug_options - DC debug struct
@ -795,6 +792,7 @@ struct dc_debug_options {
unsigned int force_odm_combine; //bit vector based on otg inst
unsigned int seamless_boot_odm_combine;
unsigned int force_odm_combine_4to1; //bit vector based on otg inst
int minimum_z8_residency_time;
bool disable_z9_mpc;
unsigned int force_fclk_khz;
bool enable_tri_buf;
@ -874,6 +872,7 @@ struct dc_debug_options {
bool disable_unbounded_requesting;
bool dig_fifo_off_in_blank;
bool temp_mst_deallocation_sequence;
bool override_dispclk_programming;
};
struct gpu_info_soc_bounding_box_v1_0;
@ -890,6 +889,7 @@ struct dc {
uint8_t link_count;
struct dc_link *links[MAX_PIPES * 2];
struct link_service *link_srv;
struct dc_state *current_state;
struct resource_pool *res_pool;
@ -991,11 +991,7 @@ struct dc_init_data {
};
struct dc_callback_init {
#ifdef CONFIG_DRM_AMD_DC_HDCP
struct cp_psp cp_psp;
#else
uint8_t reserved;
#endif
};
struct dc *dc_create(const struct dc_init_data *init_params);
@ -1362,10 +1358,6 @@ enum dc_status dc_commit_streams(struct dc *dc,
struct dc_stream_state *streams[],
uint8_t stream_count);
/* TODO: When the transition to the new commit sequence is done, remove this
* function in favor of dc_commit_streams. */
bool dc_commit_state(struct dc *dc, struct dc_state *context);
struct dc_state *dc_create_state(struct dc *dc);
struct dc_state *dc_copy_state(struct dc_state *src_ctx);
void dc_retain_state(struct dc_state *context);
@ -1378,9 +1370,163 @@ struct dc_plane_state *dc_get_surface_for_mpcc(struct dc *dc,
uint32_t dc_get_opp_for_plane(struct dc *dc, struct dc_plane_state *plane);
/* The function returns minimum bandwidth required to drive a given timing
* return - minimum required timing bandwidth in kbps.
*/
uint32_t dc_bandwidth_in_kbps_from_timing(const struct dc_crtc_timing *timing);
/* Link Interfaces */
/* TODO: remove this after resolving external dependencies */
#include "dc_link.h"
/*
* A link contains one or more sinks and their connected status.
* The currently active signal type (HDMI, DP-SST, DP-MST) is also reported.
*/
struct dc_link {
struct dc_sink *remote_sinks[MAX_SINKS_PER_LINK];
unsigned int sink_count;
struct dc_sink *local_sink;
unsigned int link_index;
enum dc_connection_type type;
enum signal_type connector_signal;
enum dc_irq_source irq_source_hpd;
enum dc_irq_source irq_source_hpd_rx;/* aka DP Short Pulse */
bool is_hpd_filter_disabled;
bool dp_ss_off;
/**
* @link_state_valid:
*
* If there is no link and local sink, this variable should be set to
* false. Otherwise, it should be set to true; usually, the function
* core_link_enable_stream sets this field to true.
*/
bool link_state_valid;
bool aux_access_disabled;
bool sync_lt_in_progress;
bool skip_stream_reenable;
bool is_internal_display;
/** @todo Rename. Flag an endpoint as having a programmable mapping to a DIG encoder. */
bool is_dig_mapping_flexible;
bool hpd_status; /* HPD status of link without physical HPD pin. */
bool is_hpd_pending; /* Indicates a new received hpd */
bool is_automated; /* Indicates automated testing */
bool edp_sink_present;
struct dp_trace dp_trace;
/* caps is the same as reported_link_cap. link_traing use
* reported_link_cap. Will clean up. TODO
*/
struct dc_link_settings reported_link_cap;
struct dc_link_settings verified_link_cap;
struct dc_link_settings cur_link_settings;
struct dc_lane_settings cur_lane_setting[LANE_COUNT_DP_MAX];
struct dc_link_settings preferred_link_setting;
/* preferred_training_settings are override values that
* come from DM. DM is responsible for the memory
* management of the override pointers.
*/
struct dc_link_training_overrides preferred_training_settings;
struct dp_audio_test_data audio_test_data;
uint8_t ddc_hw_inst;
uint8_t hpd_src;
uint8_t link_enc_hw_inst;
/* DIG link encoder ID. Used as index in link encoder resource pool.
* For links with fixed mapping to DIG, this is not changed after dc_link
* object creation.
*/
enum engine_id eng_id;
bool test_pattern_enabled;
union compliance_test_state compliance_test_state;
void *priv;
struct ddc_service *ddc;
bool aux_mode;
/* Private to DC core */
const struct dc *dc;
struct dc_context *ctx;
struct panel_cntl *panel_cntl;
struct link_encoder *link_enc;
struct graphics_object_id link_id;
/* Endpoint type distinguishes display endpoints which do not have entries
* in the BIOS connector table from those that do. Helps when tracking link
* encoder to display endpoint assignments.
*/
enum display_endpoint_type ep_type;
union ddi_channel_mapping ddi_channel_mapping;
struct connector_device_tag_info device_tag;
struct dpcd_caps dpcd_caps;
uint32_t dongle_max_pix_clk;
unsigned short chip_caps;
unsigned int dpcd_sink_count;
struct hdcp_caps hdcp_caps;
enum edp_revision edp_revision;
union dpcd_sink_ext_caps dpcd_sink_ext_caps;
struct psr_settings psr_settings;
/* Drive settings read from integrated info table */
struct dc_lane_settings bios_forced_drive_settings;
/* Vendor specific LTTPR workaround variables */
uint8_t vendor_specific_lttpr_link_rate_wa;
bool apply_vendor_specific_lttpr_link_rate_wa;
/* MST record stream using this link */
struct link_flags {
bool dp_keep_receiver_powered;
bool dp_skip_DID2;
bool dp_skip_reset_segment;
bool dp_skip_fs_144hz;
bool dp_mot_reset_segment;
/* Some USB4 docks do not handle turning off MST DSC once it has been enabled. */
bool dpia_mst_dsc_always_on;
/* Forced DPIA into TBT3 compatibility mode. */
bool dpia_forced_tbt3_mode;
bool dongle_mode_timing_override;
} wa_flags;
struct link_mst_stream_allocation_table mst_stream_alloc_table;
struct dc_link_status link_status;
struct dprx_states dprx_states;
struct gpio *hpd_gpio;
enum dc_link_fec_state fec_state;
bool link_powered_externally; // Used to bypass hardware sequencing delays when panel is powered down forcibly
struct dc_panel_config panel_config;
struct phy_state phy_state;
// BW ALLOCATON USB4 ONLY
struct dc_dpia_bw_alloc dpia_bw_alloc_config;
};
/* Return an enumerated dc_link.
* dc_link order is constant and determined at
* boot time. They cannot be created or destroyed.
* Use dc_get_caps() to get number of links.
*/
struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index);
/* Return instance id of the edp link. Inst 0 is primary edp link. */
bool dc_get_edp_link_panel_inst(const struct dc *dc,
const struct dc_link *link,
unsigned int *inst_out);
/* Return an array of link pointers to edp links. */
void dc_get_edp_links(const struct dc *dc,
struct dc_link **edp_links,
int *edp_num);
/* The function initiates detection handshake over the given link. It first
* determines if there are display connections over the link. If so it initiates
@ -1404,6 +1550,38 @@ uint32_t dc_get_opp_for_plane(struct dc *dc, struct dc_plane_state *plane);
*/
bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason);
struct dc_sink_init_data;
/* When link connection type is dc_connection_mst_branch, remote sink can be
* added to the link. The interface creates a remote sink and associates it with
* current link. The sink will be retained by link until remove remote sink is
* called.
*
* @dc_link - link the remote sink will be added to.
* @edid - byte array of EDID raw data.
* @len - size of the edid in byte
* @init_data -
*/
struct dc_sink *dc_link_add_remote_sink(
struct dc_link *dc_link,
const uint8_t *edid,
int len,
struct dc_sink_init_data *init_data);
/* Remove remote sink from a link with dc_connection_mst_branch connection type.
* @link - link the sink should be removed from
* @sink - sink to be removed.
*/
void dc_link_remove_remote_sink(
struct dc_link *link,
struct dc_sink *sink);
/* Enable HPD interrupt handler for a given link */
void dc_link_enable_hpd(const struct dc_link *link);
/* Disable HPD interrupt handler for a given link */
void dc_link_disable_hpd(const struct dc_link *link);
/* determine if there is a sink connected to the link
*
* @type - dc_connection_single if connected, dc_connection_none otherwise.
@ -1417,14 +1595,115 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason);
bool dc_link_detect_connection_type(struct dc_link *link,
enum dc_connection_type *type);
/* query current hpd pin value
* return - true HPD is asserted (HPD high), false otherwise (HPD low)
*
*/
bool dc_link_get_hpd_state(struct dc_link *link);
/* Getter for cached link status from given link */
const struct dc_link_status *dc_link_get_status(const struct dc_link *link);
#ifdef CONFIG_DRM_AMD_DC_HDCP
/* enable/disable hardware HPD filter.
*
* @link - The link the HPD pin is associated with.
* @enable = true - enable hardware HPD filter. HPD event will only queued to irq
* handler once after no HPD change has been detected within dc default HPD
* filtering interval since last HPD event. i.e if display keeps toggling hpd
* pulses within default HPD interval, no HPD event will be received until HPD
* toggles have stopped. Then HPD event will be queued to irq handler once after
* dc default HPD filtering interval since last HPD event.
*
* @enable = false - disable hardware HPD filter. HPD event will be queued
* immediately to irq handler after no HPD change has been detected within
* IRQ_HPD (aka HPD short pulse) interval (i.e 2ms).
*/
void dc_link_enable_hpd_filter(struct dc_link *link, bool enable);
/* submit i2c read/write payloads through ddc channel
* @link_index - index to a link with ddc in i2c mode
* @cmd - i2c command structure
* return - true if success, false otherwise.
*/
bool dc_submit_i2c(
struct dc *dc,
uint32_t link_index,
struct i2c_command *cmd);
/* submit i2c read/write payloads through oem channel
* @link_index - index to a link with ddc in i2c mode
* @cmd - i2c command structure
* return - true if success, false otherwise.
*/
bool dc_submit_i2c_oem(
struct dc *dc,
struct i2c_command *cmd);
enum aux_return_code_type;
/* Attempt to transfer the given aux payload. This function does not perform
* retries or handle error states. The reply is returned in the payload->reply
* and the result through operation_result. Returns the number of bytes
* transferred,or -1 on a failure.
*/
int dc_link_aux_transfer_raw(struct ddc_service *ddc,
struct aux_payload *payload,
enum aux_return_code_type *operation_result);
bool dc_is_oem_i2c_device_present(
struct dc *dc,
size_t slave_address
);
/* return true if the connected receiver supports the hdcp version */
bool dc_link_is_hdcp14(struct dc_link *link, enum signal_type signal);
bool dc_link_is_hdcp22(struct dc_link *link, enum signal_type signal);
#endif
/* Notify DC about DP RX Interrupt (aka DP IRQ_HPD).
*
* TODO - When defer_handling is true the function will have a different purpose.
* It no longer does complete hpd rx irq handling. We should create a separate
* interface specifically for this case.
*
* Return:
* true - Downstream port status changed. DM should call DC to do the
* detection.
* false - no change in Downstream port status. No further action required
* from DM.
*/
bool dc_link_handle_hpd_rx_irq(struct dc_link *dc_link,
union hpd_irq_data *hpd_irq_dpcd_data, bool *out_link_loss,
bool defer_handling, bool *has_left_work);
/* handle DP specs define test automation sequence*/
void dc_link_dp_handle_automated_test(struct dc_link *link);
/* handle DP Link loss sequence and try to recover RX link loss with best
* effort
*/
void dc_link_dp_handle_link_loss(struct dc_link *link);
/* Determine if hpd rx irq should be handled or ignored
* return true - hpd rx irq should be handled.
* return false - it is safe to ignore hpd rx irq event
*/
bool dc_link_dp_allow_hpd_rx_irq(const struct dc_link *link);
/* Determine if link loss is indicated with a given hpd_irq_dpcd_data.
* @link - link the hpd irq data associated with
* @hpd_irq_dpcd_data - input hpd irq data
* return - true if hpd irq data indicates a link lost
*/
bool dc_link_check_link_loss_status(struct dc_link *link,
union hpd_irq_data *hpd_irq_dpcd_data);
/* Read hpd rx irq data from a given link
* @link - link where the hpd irq data should be read from
* @irq_data - output hpd irq data
* return - DC_OK if hpd irq data is read successfully, otherwise hpd irq data
* read has failed.
*/
enum dc_status dc_link_dp_read_hpd_rx_irq_data(
struct dc_link *link,
union hpd_irq_data *irq_data);
/* The function clears recorded DP RX states in the link. DM should call this
* function when it is resuming from S3 power state to previously connected links.
@ -1450,12 +1729,6 @@ uint32_t dc_link_bandwidth_kbps(
const struct dc_link *link,
const struct dc_link_settings *link_setting);
/* The function returns minimum bandwidth required to drive a given timing
* return - minimum required timing bandwidth in kbps.
*/
uint32_t dc_bandwidth_in_kbps_from_timing(
const struct dc_crtc_timing *timing);
/* The function takes a snapshot of current link resource allocation state
* @dc: pointer to dc of the dm calling this
* @map: a dc link resource snapshot defined internally to dc.
@ -1493,6 +1766,269 @@ void dc_restore_link_res_map(const struct dc *dc, uint32_t *map);
* interface i.e stream_update->dsc_config
*/
bool dc_link_update_dsc_config(struct pipe_ctx *pipe_ctx);
/* translate a raw link rate data to bandwidth in kbps */
uint32_t dc_link_bw_kbps_from_raw_frl_link_rate_data(
struct dc *dc, uint8_t bw);
/* determine the optimal bandwidth given link and required bw.
* @link - current detected link
* @req_bw - requested bandwidth in kbps
* @link_settings - returned most optimal link settings that can fit the
* requested bandwidth
* return - false if link can't support requested bandwidth, true if link
* settings is found.
*/
bool dc_link_decide_edp_link_settings(struct dc_link *link,
struct dc_link_settings *link_settings,
uint32_t req_bw);
/* return the max dp link settings can be driven by the link without considering
* connected RX device and its capability
*/
bool dc_link_dp_get_max_link_enc_cap(const struct dc_link *link,
struct dc_link_settings *max_link_enc_cap);
/* determine when the link is driving MST mode, what DP link channel coding
* format will be used. The decision will remain unchanged until next HPD event.
*
* @link - a link with DP RX connection
* return - if stream is committed to this link with MST signal type, type of
* channel coding format dc will choose.
*/
enum dp_link_encoding dc_link_dp_mst_decide_link_encoding_format(
const struct dc_link *link);
/* get max dp link settings the link can enable with all things considered. (i.e
* TX/RX/Cable capabilities and dp override policies.
*
* @link - a link with DP RX connection
* return - max dp link settings the link can enable.
*
*/
const struct dc_link_settings *dc_link_get_link_cap(const struct dc_link *link);
/* Check if a RX (ex. DP sink, MST hub, passive or active dongle) is connected
* to a link with dp connector signal type.
* @link - a link with dp connector signal type
* return - true if connected, false otherwise
*/
bool dc_link_is_dp_sink_present(struct dc_link *link);
/* Force DP lane settings update to main-link video signal and notify the change
* to DP RX via DPCD. This is a debug interface used for video signal integrity
* tuning purpose. The interface assumes link has already been enabled with DP
* signal.
*
* @lt_settings - a container structure with desired hw_lane_settings
*/
void dc_link_set_drive_settings(struct dc *dc,
struct link_training_settings *lt_settings,
struct dc_link *link);
/* Enable a test pattern in Link or PHY layer in an active link for compliance
* test or debugging purpose. The test pattern will remain until next un-plug.
*
* @link - active link with DP signal output enabled.
* @test_pattern - desired test pattern to output.
* NOTE: set to DP_TEST_PATTERN_VIDEO_MODE to disable previous test pattern.
* @test_pattern_color_space - for video test pattern choose a desired color
* space.
* @p_link_settings - For PHY pattern choose a desired link settings
* @p_custom_pattern - some test pattern will require a custom input to
* customize some pattern details. Otherwise keep it to NULL.
* @cust_pattern_size - size of the custom pattern input.
*
*/
bool dc_link_dp_set_test_pattern(
struct dc_link *link,
enum dp_test_pattern test_pattern,
enum dp_test_pattern_color_space test_pattern_color_space,
const struct link_training_settings *p_link_settings,
const unsigned char *p_custom_pattern,
unsigned int cust_pattern_size);
/* Force DP link settings to always use a specific value until reboot to a
* specific link. If link has already been enabled, the interface will also
* switch to desired link settings immediately. This is a debug interface to
* generic dp issue trouble shooting.
*/
void dc_link_set_preferred_link_settings(struct dc *dc,
struct dc_link_settings *link_setting,
struct dc_link *link);
/* Force DP link to customize a specific link training behavior by overriding to
* standard DP specs defined protocol. This is a debug interface to trouble shoot
* display specific link training issues or apply some display specific
* workaround in link training.
*
* @link_settings - if not NULL, force preferred link settings to the link.
* @lt_override - a set of override pointers. If any pointer is none NULL, dc
* will apply this particular override in future link training. If NULL is
* passed in, dc resets previous overrides.
* NOTE: DM must keep the memory from override pointers until DM resets preferred
* training settings.
*/
void dc_link_set_preferred_training_settings(struct dc *dc,
struct dc_link_settings *link_setting,
struct dc_link_training_overrides *lt_overrides,
struct dc_link *link,
bool skip_immediate_retrain);
/* return - true if FEC is supported with connected DP RX, false otherwise */
bool dc_link_is_fec_supported(const struct dc_link *link);
/* query FEC enablement policy to determine if FEC will be enabled by dc during
* link enablement.
* return - true if FEC should be enabled, false otherwise.
*/
bool dc_link_should_enable_fec(const struct dc_link *link);
/* determine lttpr mode the current link should be enabled with a specific link
* settings.
*/
enum lttpr_mode dc_link_decide_lttpr_mode(struct dc_link *link,
struct dc_link_settings *link_setting);
/* Force DP RX to update its power state.
* NOTE: this interface doesn't update dp main-link. Calling this function will
* cause DP TX main-link and DP RX power states out of sync. DM has to restore
* RX power state back upon finish DM specific execution requiring DP RX in a
* specific power state.
* @on - true to set DP RX in D0 power state, false to set DP RX in D3 power
* state.
*/
void dc_link_dp_receiver_power_ctrl(struct dc_link *link, bool on);
/* Force link to read base dp receiver caps from dpcd 000h - 00Fh and overwrite
* current value read from extended receiver cap from 02200h - 0220Fh.
* Some DP RX has problems of providing accurate DP receiver caps from extended
* field, this interface is a workaround to revert link back to use base caps.
*/
void dc_link_overwrite_extended_receiver_cap(
struct dc_link *link);
void dc_link_edp_panel_backlight_power_on(struct dc_link *link,
bool wait_for_hpd);
/* Set backlight level of an embedded panel (eDP, LVDS).
* backlight_pwm_u16_16 is unsigned 32 bit with 16 bit integer
* and 16 bit fractional, where 1.0 is max backlight value.
*/
bool dc_link_set_backlight_level(const struct dc_link *dc_link,
uint32_t backlight_pwm_u16_16,
uint32_t frame_ramp);
/* Set/get nits-based backlight level of an embedded panel (eDP, LVDS). */
bool dc_link_set_backlight_level_nits(struct dc_link *link,
bool isHDR,
uint32_t backlight_millinits,
uint32_t transition_time_in_ms);
bool dc_link_get_backlight_level_nits(struct dc_link *link,
uint32_t *backlight_millinits,
uint32_t *backlight_millinits_peak);
int dc_link_get_backlight_level(const struct dc_link *dc_link);
int dc_link_get_target_backlight_pwm(const struct dc_link *link);
bool dc_link_set_psr_allow_active(struct dc_link *dc_link, const bool *enable,
bool wait, bool force_static, const unsigned int *power_opts);
bool dc_link_get_psr_state(const struct dc_link *dc_link, enum dc_psr_state *state);
bool dc_link_setup_psr(struct dc_link *dc_link,
const struct dc_stream_state *stream, struct psr_config *psr_config,
struct psr_context *psr_context);
/* On eDP links this function call will stall until T12 has elapsed.
* If the panel is not in power off state, this function will return
* immediately.
*/
bool dc_link_wait_for_t12(struct dc_link *link);
/* Determine if dp trace has been initialized to reflect upto date result *
* return - true if trace is initialized and has valid data. False dp trace
* doesn't have valid result.
*/
bool dc_dp_trace_is_initialized(struct dc_link *link);
/* Query a dp trace flag to indicate if the current dp trace data has been
* logged before
*/
bool dc_dp_trace_is_logged(struct dc_link *link,
bool in_detection);
/* Set dp trace flag to indicate whether DM has already logged the current dp
* trace data. DM can set is_logged to true upon logging and check
* dc_dp_trace_is_logged before logging to avoid logging the same result twice.
*/
void dc_dp_trace_set_is_logged_flag(struct dc_link *link,
bool in_detection,
bool is_logged);
/* Obtain driver time stamp for last dp link training end. The time stamp is
* formatted based on dm_get_timestamp DM function.
* @in_detection - true to get link training end time stamp of last link
* training in detection sequence. false to get link training end time stamp
* of last link training in commit (dpms) sequence
*/
unsigned long long dc_dp_trace_get_lt_end_timestamp(struct dc_link *link,
bool in_detection);
/* Get how many link training attempts dc has done with latest sequence.
* @in_detection - true to get link training count of last link
* training in detection sequence. false to get link training count of last link
* training in commit (dpms) sequence
*/
const struct dp_trace_lt_counts *dc_dp_trace_get_lt_counts(struct dc_link *link,
bool in_detection);
/* Get how many link loss has happened since last link training attempts */
unsigned int dc_dp_trace_get_link_loss_count(struct dc_link *link);
/*
* USB4 DPIA BW ALLOCATION PUBLIC FUNCTIONS
*/
/*
* Send a request from DP-Tx requesting to allocate BW remotely after
* allocating it locally. This will get processed by CM and a CB function
* will be called.
*
* @link: pointer to the dc_link struct instance
* @req_bw: The requested bw in Kbyte to allocated
*
* return: none
*/
void dc_link_set_usb4_req_bw_req(struct dc_link *link, int req_bw);
/*
* Handle function for when the status of the Request above is complete.
* We will find out the result of allocating on CM and update structs.
*
* @link: pointer to the dc_link struct instance
* @bw: Allocated or Estimated BW depending on the result
* @result: Response type
*
* return: none
*/
void dc_link_handle_usb4_bw_alloc_response(struct dc_link *link,
uint8_t bw, uint8_t result);
/*
* Handle the USB4 BW Allocation related functionality here:
* Plug => Try to allocate max bw from timing parameters supported by the sink
* Unplug => de-allocate bw
*
* @link: pointer to the dc_link struct instance
* @peak_bw: Peak bw used by the link/sink
*
* return: allocated bw else return 0
*/
int dc_link_dp_dpia_handle_usb4_bandwidth_allocation_for_link(
struct dc_link *link, int peak_bw);
/* Sink Interfaces - A sink corresponds to a display output device */
struct dc_container_id {
@ -1511,7 +2047,7 @@ struct dc_sink_dsc_caps {
// 'true' if these are virtual DPCD's DSC caps (immediately upstream of sink in MST topology),
// 'false' if they are sink's DSC caps
bool is_virtual_dpcd_dsc;
#if defined(CONFIG_DRM_AMD_DC_DCN)
#if defined(CONFIG_DRM_AMD_DC_FP)
// 'true' if MST topology supports DSC passthrough for sink
// 'false' if MST topology does not support DSC passthrough
bool is_dsc_passthrough_supported;
@ -1603,7 +2139,6 @@ void dc_resume(struct dc *dc);
void dc_power_down_on_boot(struct dc *dc);
#if defined(CONFIG_DRM_AMD_DC_HDCP)
/*
* HDCP Interfaces
*/
@ -1611,7 +2146,6 @@ enum hdcp_message_status dc_process_hdcp_msg(
enum signal_type signal,
struct dc_link *link,
struct hdcp_protection_message *message_info);
#endif
bool dc_is_dmcu_initialized(struct dc *dc);
enum dc_status dc_set_clock(struct dc *dc, enum dc_clock_type clock_type, uint32_t clk_khz, uint32_t stepping);

View File

@ -421,7 +421,6 @@ void dc_dmub_srv_get_visual_confirm_color_cmd(struct dc *dc, struct pipe_ctx *pi
}
}
#ifdef CONFIG_DRM_AMD_DC_DCN
/**
* populate_subvp_cmd_drr_info - Helper to populate DRR pipe info for the DMCUB subvp command
*
@ -638,7 +637,7 @@ static void populate_subvp_cmd_pipe_info(struct dc *dc,
pipe_data->pipe_config.subvp_data.main_vblank_end =
main_timing->v_total - main_timing->v_front_porch - main_timing->v_addressable;
pipe_data->pipe_config.subvp_data.mall_region_lines = phantom_timing->v_addressable;
pipe_data->pipe_config.subvp_data.main_pipe_index = subvp_pipe->pipe_idx;
pipe_data->pipe_config.subvp_data.main_pipe_index = subvp_pipe->stream_res.tg->inst;
pipe_data->pipe_config.subvp_data.is_drr = subvp_pipe->stream->ignore_msa_timing_param;
/* Calculate the scaling factor from the src and dst height.
@ -680,11 +679,11 @@ static void populate_subvp_cmd_pipe_info(struct dc *dc,
struct pipe_ctx *phantom_pipe = &context->res_ctx.pipe_ctx[j];
if (phantom_pipe->stream == subvp_pipe->stream->mall_stream_config.paired_stream) {
pipe_data->pipe_config.subvp_data.phantom_pipe_index = phantom_pipe->pipe_idx;
pipe_data->pipe_config.subvp_data.phantom_pipe_index = phantom_pipe->stream_res.tg->inst;
if (phantom_pipe->bottom_pipe) {
pipe_data->pipe_config.subvp_data.phantom_split_pipe_index = phantom_pipe->bottom_pipe->pipe_idx;
pipe_data->pipe_config.subvp_data.phantom_split_pipe_index = phantom_pipe->bottom_pipe->plane_res.hubp->inst;
} else if (phantom_pipe->next_odm_pipe) {
pipe_data->pipe_config.subvp_data.phantom_split_pipe_index = phantom_pipe->next_odm_pipe->pipe_idx;
pipe_data->pipe_config.subvp_data.phantom_split_pipe_index = phantom_pipe->next_odm_pipe->plane_res.hubp->inst;
} else {
pipe_data->pipe_config.subvp_data.phantom_split_pipe_index = 0;
}
@ -750,7 +749,8 @@ void dc_dmub_setup_subvp_dmub_command(struct dc *dc,
!pipe->top_pipe && !pipe->prev_odm_pipe &&
pipe->stream->mall_stream_config.type == SUBVP_MAIN) {
populate_subvp_cmd_pipe_info(dc, context, &cmd, pipe, cmd_pipe_index++);
} else if (pipe->plane_state && pipe->stream->mall_stream_config.type == SUBVP_NONE) {
} else if (pipe->plane_state && pipe->stream->mall_stream_config.type == SUBVP_NONE &&
!pipe->top_pipe && !pipe->prev_odm_pipe) {
// Don't need to check for ActiveDRAMClockChangeMargin < 0, not valid in cases where
// we run through DML without calculating "natural" P-state support
populate_subvp_cmd_vblank_pipe_info(dc, context, &cmd, pipe, cmd_pipe_index++);
@ -775,7 +775,6 @@ void dc_dmub_setup_subvp_dmub_command(struct dc *dc,
dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
dc_dmub_srv_wait_idle(dc->ctx->dmub_srv);
}
#endif
bool dc_dmub_srv_get_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv, struct dmub_diagnostic_data *diag_data)
{

View File

@ -921,12 +921,6 @@ struct dpcd_usb4_dp_tunneling_info {
#ifndef DP_DFP_CAPABILITY_EXTENSION_SUPPORT
#define DP_DFP_CAPABILITY_EXTENSION_SUPPORT 0x0A3
#endif
#ifndef DP_LINK_SQUARE_PATTERN
#define DP_LINK_SQUARE_PATTERN 0x10F
#endif
#ifndef DP_CABLE_ATTRIBUTES_UPDATED_BY_DPTX
#define DP_CABLE_ATTRIBUTES_UPDATED_BY_DPTX 0x110
#endif
#ifndef DP_DSC_CONFIGURATION
#define DP_DSC_CONFIGURATION 0x161
#endif
@ -939,12 +933,6 @@ struct dpcd_usb4_dp_tunneling_info {
#ifndef DP_128b_132b_TRAINING_AUX_RD_INTERVAL
#define DP_128b_132b_TRAINING_AUX_RD_INTERVAL 0x2216
#endif
#ifndef DP_LINK_SQUARE_PATTERN
#define DP_LINK_SQUARE_PATTERN 0x10F
#endif
#ifndef DP_CABLE_ATTRIBUTES_UPDATED_BY_DPRX
#define DP_CABLE_ATTRIBUTES_UPDATED_BY_DPRX 0x2217
#endif
#ifndef DP_TEST_264BIT_CUSTOM_PATTERN_7_0
#define DP_TEST_264BIT_CUSTOM_PATTERN_7_0 0X2230
#endif
@ -988,10 +976,6 @@ struct dpcd_usb4_dp_tunneling_info {
#define DP_INTRA_HOP_AUX_REPLY_INDICATION (1 << 3)
/* TODO - Use DRM header to replace above once available */
#endif // DP_INTRA_HOP_AUX_REPLY_INDICATION
#ifndef DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE
#define DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE 0x50
#endif
union dp_main_line_channel_coding_cap {
struct {
uint8_t DP_8b_10b_SUPPORTED :1;
@ -1261,4 +1245,161 @@ union dpcd_sink_ext_caps {
} bits;
uint8_t raw;
};
enum dc_link_fec_state {
dc_link_fec_not_ready,
dc_link_fec_ready,
dc_link_fec_enabled
};
union dpcd_psr_configuration {
struct {
unsigned char ENABLE : 1;
unsigned char TRANSMITTER_ACTIVE_IN_PSR : 1;
unsigned char CRC_VERIFICATION : 1;
unsigned char FRAME_CAPTURE_INDICATION : 1;
/* For eDP 1.4, PSR v2*/
unsigned char LINE_CAPTURE_INDICATION : 1;
/* For eDP 1.4, PSR v2*/
unsigned char IRQ_HPD_WITH_CRC_ERROR : 1;
unsigned char ENABLE_PSR2 : 1;
unsigned char EARLY_TRANSPORT_ENABLE : 1;
} bits;
unsigned char raw;
};
union dpcd_alpm_configuration {
struct {
unsigned char ENABLE : 1;
unsigned char IRQ_HPD_ENABLE : 1;
unsigned char RESERVED : 6;
} bits;
unsigned char raw;
};
union dpcd_sink_active_vtotal_control_mode {
struct {
unsigned char ENABLE : 1;
unsigned char RESERVED : 7;
} bits;
unsigned char raw;
};
union psr_error_status {
struct {
unsigned char LINK_CRC_ERROR :1;
unsigned char RFB_STORAGE_ERROR :1;
unsigned char VSC_SDP_ERROR :1;
unsigned char RESERVED :5;
} bits;
unsigned char raw;
};
union psr_sink_psr_status {
struct {
unsigned char SINK_SELF_REFRESH_STATUS :3;
unsigned char RESERVED :5;
} bits;
unsigned char raw;
};
struct edp_trace_power_timestamps {
uint64_t poweroff;
uint64_t poweron;
};
struct dp_trace_lt_counts {
unsigned int total;
unsigned int fail;
};
enum link_training_result {
LINK_TRAINING_SUCCESS,
LINK_TRAINING_CR_FAIL_LANE0,
LINK_TRAINING_CR_FAIL_LANE1,
LINK_TRAINING_CR_FAIL_LANE23,
/* CR DONE bit is cleared during EQ step */
LINK_TRAINING_EQ_FAIL_CR,
/* CR DONE bit is cleared but LANE0_CR_DONE is set during EQ step */
LINK_TRAINING_EQ_FAIL_CR_PARTIAL,
/* other failure during EQ step */
LINK_TRAINING_EQ_FAIL_EQ,
LINK_TRAINING_LQA_FAIL,
/* one of the CR,EQ or symbol lock is dropped */
LINK_TRAINING_LINK_LOSS,
/* Abort link training (because sink unplugged) */
LINK_TRAINING_ABORT,
DP_128b_132b_LT_FAILED,
DP_128b_132b_MAX_LOOP_COUNT_REACHED,
DP_128b_132b_CHANNEL_EQ_DONE_TIMEOUT,
DP_128b_132b_CDS_DONE_TIMEOUT,
};
struct dp_trace_lt {
struct dp_trace_lt_counts counts;
struct dp_trace_timestamps {
unsigned long long start;
unsigned long long end;
} timestamps;
enum link_training_result result;
bool is_logged;
};
struct dp_trace {
struct dp_trace_lt detect_lt_trace;
struct dp_trace_lt commit_lt_trace;
unsigned int link_loss_count;
bool is_initialized;
struct edp_trace_power_timestamps edp_trace_power_timestamps;
};
/* TODO - This is a temporary location for any new DPCD definitions.
* We should move these to drm_dp header.
*/
#ifndef DP_LINK_SQUARE_PATTERN
#define DP_LINK_SQUARE_PATTERN 0x10F
#endif
#ifndef DP_CABLE_ATTRIBUTES_UPDATED_BY_DPRX
#define DP_CABLE_ATTRIBUTES_UPDATED_BY_DPRX 0x2217
#endif
#ifndef DP_CABLE_ATTRIBUTES_UPDATED_BY_DPTX
#define DP_CABLE_ATTRIBUTES_UPDATED_BY_DPTX 0x110
#endif
#ifndef DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE
#define DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE 0x50
#endif
#ifndef DP_TUNNELING_IRQ
#define DP_TUNNELING_IRQ (1 << 5)
#endif
/** USB4 DPCD BW Allocation Registers Chapter 10.7 **/
#ifndef DP_TUNNELING_CAPABILITIES
#define DP_TUNNELING_CAPABILITIES 0xE000D /* 1.4a */
#endif
#ifndef USB4_DRIVER_ID
#define USB4_DRIVER_ID 0xE000F /* 1.4a */
#endif
#ifndef USB4_DRIVER_BW_CAPABILITY
#define USB4_DRIVER_BW_CAPABILITY 0xE0020 /* 1.4a */
#endif
#ifndef DP_IN_ADAPTER_TUNNEL_INFO
#define DP_IN_ADAPTER_TUNNEL_INFO 0xE0021 /* 1.4a */
#endif
#ifndef DP_BW_GRANULALITY
#define DP_BW_GRANULALITY 0xE0022 /* 1.4a */
#endif
#ifndef ESTIMATED_BW
#define ESTIMATED_BW 0xE0023 /* 1.4a */
#endif
#ifndef ALLOCATED_BW
#define ALLOCATED_BW 0xE0024 /* 1.4a */
#endif
#ifndef DP_TUNNELING_STATUS
#define DP_TUNNELING_STATUS 0xE0025 /* 1.4a */
#endif
#ifndef DPTX_BW_ALLOCATION_MODE_CONTROL
#define DPTX_BW_ALLOCATION_MODE_CONTROL 0xE0030 /* 1.4a */
#endif
#ifndef REQUESTED_BW
#define REQUESTED_BW 0xE0031 /* 1.4a */
#endif
#endif /* DC_DP_TYPES_H */

View File

@ -54,6 +54,12 @@ struct dc_dsc_policy {
bool enable_dsc_when_not_needed;
};
struct dc_dsc_config_options {
uint32_t dsc_min_slice_height_override;
uint32_t max_target_bpp_limit_override_x16;
uint32_t slice_height_granularity;
};
bool dc_dsc_parse_dsc_dpcd(const struct dc *dc,
const uint8_t *dpcd_dsc_basic_data,
const uint8_t *dpcd_dsc_ext_data,
@ -71,8 +77,7 @@ bool dc_dsc_compute_bandwidth_range(
bool dc_dsc_compute_config(
const struct display_stream_compressor *dsc,
const struct dsc_dec_dpcd_caps *dsc_sink_caps,
uint32_t dsc_min_slice_height_override,
uint32_t max_target_bpp_limit_override,
const struct dc_dsc_config_options *options,
uint32_t target_bandwidth_kbps,
const struct dc_crtc_timing *timing,
struct dc_dsc_config *dsc_cfg);
@ -100,4 +105,6 @@ void dc_dsc_policy_set_enable_dsc_when_not_needed(bool enable);
void dc_dsc_policy_set_disable_dsc_stream_overhead(bool disable);
void dc_dsc_get_default_config_option(const struct dc *dc, struct dc_dsc_config_options *options);
#endif

View File

@ -829,7 +829,7 @@ struct dc_dsc_config {
uint32_t version_minor; /* DSC minor version. Full version is formed as 1.version_minor. */
bool ycbcr422_simple; /* Tell DSC engine to convert YCbCr 4:2:2 to 'YCbCr 4:2:2 simple'. */
int32_t rc_buffer_size; /* DSC RC buffer block size in bytes */
#if defined(CONFIG_DRM_AMD_DC_DCN)
#if defined(CONFIG_DRM_AMD_DC_FP)
bool is_frl; /* indicate if DSC is applied based on HDMI FRL sink's capability */
#endif
bool is_dp; /* indicate if DSC is applied based on DP's capability */
@ -1085,5 +1085,19 @@ struct tg_color {
uint16_t color_b_cb;
};
enum symclk_state {
SYMCLK_OFF_TX_OFF,
SYMCLK_ON_TX_ON,
SYMCLK_ON_TX_OFF,
};
struct phy_state {
struct {
uint8_t otg : 1;
uint8_t reserved : 7;
} symclk_ref_cnts;
enum symclk_state symclk_state;
};
#endif /* DC_HW_TYPES_H */

Some files were not shown because too many files have changed in this diff Show More