diff options
Diffstat (limited to 'drivers')
306 files changed, 15964 insertions, 10260 deletions
diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c index 38cc738..24f83f9 100644 --- a/drivers/dma-buf/sw_sync.c +++ b/drivers/dma-buf/sw_sync.c @@ -321,8 +321,16 @@ static int sw_sync_debugfs_open(struct inode *inode, struct file *file) static int sw_sync_debugfs_release(struct inode *inode, struct file *file) { struct sync_timeline *obj = file->private_data; + struct sync_pt *pt, *next; + + spin_lock_irq(&obj->lock); + + list_for_each_entry_safe(pt, next, &obj->pt_list, link) { + dma_fence_set_error(&pt->base, -ENOENT); + dma_fence_signal_locked(&pt->base); + } - smp_wmb(); + spin_unlock_irq(&obj->lock); sync_timeline_put(obj); return 0; diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 83cb2a8..4d9f218 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -110,7 +110,7 @@ config DRM_FBDEV_OVERALLOC config DRM_LOAD_EDID_FIRMWARE bool "Allow to specify an EDID data set instead of probing for it" - depends on DRM_KMS_HELPER + depends on DRM help Say Y here, if you want to use EDID data to be loaded from the /lib/firmware directory or one of the provided built-in @@ -184,6 +184,7 @@ config DRM_AMDGPU select BACKLIGHT_CLASS_DEVICE select BACKLIGHT_LCD_SUPPORT select INTERVAL_TREE + select CHASH help Choose this option if you have a recent AMD Radeon graphics card. @@ -191,6 +192,8 @@ config DRM_AMDGPU source "drivers/gpu/drm/amd/amdgpu/Kconfig" +source "drivers/gpu/drm/amd/lib/Kconfig" + source "drivers/gpu/drm/nouveau/Kconfig" source "drivers/gpu/drm/i915/Kconfig" @@ -278,6 +281,8 @@ source "drivers/gpu/drm/tinydrm/Kconfig" source "drivers/gpu/drm/pl111/Kconfig" +source "drivers/gpu/drm/tve200/Kconfig" + # Keep legacy drivers last menuconfig DRM_LEGACY diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index a8acc19..a3fdc5a 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -28,6 +28,7 @@ drm-$(CONFIG_DRM_PANEL) += drm_panel.o drm-$(CONFIG_OF) += drm_of.o drm-$(CONFIG_AGP) += drm_agpsupport.o drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o +drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \ drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \ @@ -36,7 +37,6 @@ drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \ drm_scdc_helper.o drm_gem_framebuffer_helper.o drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o -drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o drm_kms_helper-$(CONFIG_DRM_DP_AUX_CHARDEV) += drm_dp_aux_dev.o @@ -44,14 +44,13 @@ drm_kms_helper-$(CONFIG_DRM_DP_AUX_CHARDEV) += drm_dp_aux_dev.o obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o obj-$(CONFIG_DRM_DEBUG_MM_SELFTEST) += selftests/ -CFLAGS_drm_trace_points.o := -I$(src) - obj-$(CONFIG_DRM) += drm.o obj-$(CONFIG_DRM_MIPI_DSI) += drm_mipi_dsi.o obj-$(CONFIG_DRM_ARM) += arm/ obj-$(CONFIG_DRM_TTM) += ttm/ obj-$(CONFIG_DRM_TDFX) += tdfx/ obj-$(CONFIG_DRM_R128) += r128/ +obj-y += amd/lib/ obj-$(CONFIG_HSA_AMD) += amd/amdkfd/ obj-$(CONFIG_DRM_RADEON)+= radeon/ obj-$(CONFIG_DRM_AMDGPU)+= amd/amdgpu/ @@ -100,3 +99,4 @@ obj-$(CONFIG_DRM_ZTE) += zte/ obj-$(CONFIG_DRM_MXSFB) += mxsfb/ obj-$(CONFIG_DRM_TINYDRM) += tinydrm/ obj-$(CONFIG_DRM_PL111) += pl111/ +obj-$(CONFIG_DRM_TVE200) += tve200/ diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index 658bac0..25a95c9 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -133,5 +133,3 @@ include $(FULL_AMD_PATH)/powerplay/Makefile amdgpu-y += $(AMD_POWERPLAY_FILES) obj-$(CONFIG_DRM_AMDGPU)+= amdgpu.o - -CFLAGS_amdgpu_trace_points.o := -I$(src) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 103635a..ebfc267 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -65,6 +65,7 @@ #include "amdgpu_uvd.h" #include "amdgpu_vce.h" #include "amdgpu_vcn.h" +#include "amdgpu_mn.h" #include "gpu_scheduler.h" #include "amdgpu_virt.h" @@ -91,7 +92,7 @@ extern int amdgpu_dpm; extern int amdgpu_fw_load_type; extern int amdgpu_aspm; extern int amdgpu_runtime_pm; -extern unsigned amdgpu_ip_block_mask; +extern uint amdgpu_ip_block_mask; extern int amdgpu_bapm; extern int amdgpu_deep_color; extern int amdgpu_vm_size; @@ -104,14 +105,14 @@ extern int amdgpu_sched_jobs; extern int amdgpu_sched_hw_submission; extern int amdgpu_no_evict; extern int amdgpu_direct_gma_size; -extern unsigned amdgpu_pcie_gen_cap; -extern unsigned amdgpu_pcie_lane_cap; -extern unsigned amdgpu_cg_mask; -extern unsigned amdgpu_pg_mask; -extern unsigned amdgpu_sdma_phase_quantum; +extern uint amdgpu_pcie_gen_cap; +extern uint amdgpu_pcie_lane_cap; +extern uint amdgpu_cg_mask; +extern uint amdgpu_pg_mask; +extern uint amdgpu_sdma_phase_quantum; extern char *amdgpu_disable_cu; extern char *amdgpu_virtual_display; -extern unsigned amdgpu_pp_feature_mask; +extern uint amdgpu_pp_feature_mask; extern int amdgpu_vram_page_split; extern int amdgpu_ngg; extern int amdgpu_prim_buf_per_se; @@ -178,6 +179,7 @@ struct amdgpu_cs_parser; struct amdgpu_job; struct amdgpu_irq_src; struct amdgpu_fpriv; +struct amdgpu_bo_va_mapping; enum amdgpu_cp_irq { AMDGPU_CP_IRQ_GFX_EOP = 0, @@ -292,14 +294,25 @@ struct amdgpu_buffer_funcs { /* provided by hw blocks that can write ptes, e.g., sdma */ struct amdgpu_vm_pte_funcs { + /* number of dw to reserve per operation */ + unsigned copy_pte_num_dw; + /* copy pte entries from GART */ void (*copy_pte)(struct amdgpu_ib *ib, uint64_t pe, uint64_t src, unsigned count); + /* write pte one entry at a time with addr mapping */ void (*write_pte)(struct amdgpu_ib *ib, uint64_t pe, uint64_t value, unsigned count, uint32_t incr); + + /* maximum nums of PTEs/PDEs in a single operation */ + uint32_t set_max_nums_pte_pde; + + /* number of dw to reserve per operation */ + unsigned set_pte_pde_num_dw; + /* for linear pte/pde updates without addr mapping */ void (*set_pte_pde)(struct amdgpu_ib *ib, uint64_t pe, @@ -332,6 +345,7 @@ struct amdgpu_gart_funcs { struct amdgpu_ih_funcs { /* ring read/write ptr handling, called from interrupt context */ u32 (*get_wptr)(struct amdgpu_device *adev); + bool (*prescreen_iv)(struct amdgpu_device *adev); void (*decode_iv)(struct amdgpu_device *adev, struct amdgpu_iv_entry *entry); void (*set_rptr)(struct amdgpu_device *adev); @@ -399,6 +413,7 @@ void amdgpu_gem_prime_unpin(struct drm_gem_object *obj); struct reservation_object *amdgpu_gem_prime_res_obj(struct drm_gem_object *); void *amdgpu_gem_prime_vmap(struct drm_gem_object *obj); void amdgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); +int amdgpu_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma); int amdgpu_gem_debugfs_init(struct amdgpu_device *adev); /* sub-allocation manager, it has to be protected by another lock. @@ -455,9 +470,10 @@ struct amdgpu_sa_bo { */ void amdgpu_gem_force_release(struct amdgpu_device *adev); int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size, - int alignment, u32 initial_domain, - u64 flags, bool kernel, - struct drm_gem_object **obj); + int alignment, u32 initial_domain, + u64 flags, bool kernel, + struct reservation_object *resv, + struct drm_gem_object **obj); int amdgpu_mode_dumb_create(struct drm_file *file_priv, struct drm_device *dev, @@ -731,8 +747,8 @@ struct amdgpu_ctx_mgr { struct amdgpu_ctx *amdgpu_ctx_get(struct amdgpu_fpriv *fpriv, uint32_t id); int amdgpu_ctx_put(struct amdgpu_ctx *ctx); -uint64_t amdgpu_ctx_add_fence(struct amdgpu_ctx *ctx, struct amdgpu_ring *ring, - struct dma_fence *fence); +int amdgpu_ctx_add_fence(struct amdgpu_ctx *ctx, struct amdgpu_ring *ring, + struct dma_fence *fence, uint64_t *seq); struct dma_fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx, struct amdgpu_ring *ring, uint64_t seq); @@ -1014,7 +1030,6 @@ struct amdgpu_gfx { /* reset mask */ uint32_t grbm_soft_reset; uint32_t srbm_soft_reset; - bool in_reset; /* s3/s4 mask */ bool in_suspend; /* NGG */ @@ -1056,6 +1071,7 @@ struct amdgpu_cs_parser { /* buffer objects */ struct ww_acquire_ctx ticket; struct amdgpu_bo_list *bo_list; + struct amdgpu_mn *mn; struct amdgpu_bo_list_entry vm_pd; struct list_head validated; struct dma_fence *fence; @@ -1183,6 +1199,9 @@ struct amdgpu_firmware { /* gpu info firmware data pointer */ const struct firmware *gpu_info_fw; + + void *fw_buf_ptr; + uint64_t fw_buf_mc; }; /* @@ -1197,20 +1216,6 @@ void amdgpu_benchmark(struct amdgpu_device *adev, int test_number); void amdgpu_test_moves(struct amdgpu_device *adev); /* - * MMU Notifier - */ -#if defined(CONFIG_MMU_NOTIFIER) -int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr); -void amdgpu_mn_unregister(struct amdgpu_bo *bo); -#else -static inline int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr) -{ - return -ENODEV; -} -static inline void amdgpu_mn_unregister(struct amdgpu_bo *bo) {} -#endif - -/* * Debugfs */ struct amdgpu_debugfs { @@ -1592,6 +1597,7 @@ struct amdgpu_device { /* record last mm index being written through WREG32*/ unsigned long last_mm_index; + bool in_sriov_reset; }; static inline struct amdgpu_device *amdgpu_ttm_adev(struct ttm_bo_device *bdev) @@ -1759,6 +1765,7 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring) #define amdgpu_ring_init_cond_exec(r) (r)->funcs->init_cond_exec((r)) #define amdgpu_ring_patch_cond_exec(r,o) (r)->funcs->patch_cond_exec((r),(o)) #define amdgpu_ih_get_wptr(adev) (adev)->irq.ih_funcs->get_wptr((adev)) +#define amdgpu_ih_prescreen_iv(adev) (adev)->irq.ih_funcs->prescreen_iv((adev)) #define amdgpu_ih_decode_iv(adev, iv) (adev)->irq.ih_funcs->decode_iv((adev), (iv)) #define amdgpu_ih_set_rptr(adev) (adev)->irq.ih_funcs->set_rptr((adev)) #define amdgpu_display_vblank_get_counter(adev, crtc) (adev)->mode_info.funcs->vblank_get_counter((adev), (crtc)) @@ -1791,18 +1798,6 @@ void amdgpu_cs_report_moved_bytes(struct amdgpu_device *adev, u64 num_bytes, u64 num_vis_bytes); void amdgpu_ttm_placement_from_domain(struct amdgpu_bo *abo, u32 domain); bool amdgpu_ttm_bo_is_amdgpu_bo(struct ttm_buffer_object *bo); -int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages); -int amdgpu_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr, - uint32_t flags); -bool amdgpu_ttm_tt_has_userptr(struct ttm_tt *ttm); -struct mm_struct *amdgpu_ttm_tt_get_usermm(struct ttm_tt *ttm); -bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start, - unsigned long end); -bool amdgpu_ttm_tt_userptr_invalidated(struct ttm_tt *ttm, - int *last_invalidated); -bool amdgpu_ttm_tt_is_readonly(struct ttm_tt *ttm); -uint64_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm, - struct ttm_mem_reg *mem); void amdgpu_vram_location(struct amdgpu_device *adev, struct amdgpu_mc *mc, u64 base); void amdgpu_gart_location(struct amdgpu_device *adev, struct amdgpu_mc *mc); void amdgpu_ttm_set_active_vram_size(struct amdgpu_device *adev, u64 size); @@ -1885,10 +1880,9 @@ static inline int amdgpu_acpi_init(struct amdgpu_device *adev) { return 0; } static inline void amdgpu_acpi_fini(struct amdgpu_device *adev) { } #endif -struct amdgpu_bo_va_mapping * -amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser, - uint64_t addr, struct amdgpu_bo **bo); -int amdgpu_cs_sysvm_access_required(struct amdgpu_cs_parser *parser); +int amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser, + uint64_t addr, struct amdgpu_bo **bo, + struct amdgpu_bo_va_mapping **mapping); #include "amdgpu_object.h" #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c index b9dbbf9..dc7e25c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c @@ -169,6 +169,8 @@ static const struct kfd2kgd_calls kfd2kgd = { .get_vmem_size = get_vmem_size, .get_gpu_clock_counter = get_gpu_clock_counter, .get_max_engine_clock_in_mhz = get_max_engine_clock_in_mhz, + .alloc_pasid = amdgpu_vm_alloc_pasid, + .free_pasid = amdgpu_vm_free_pasid, .program_sh_mem_settings = kgd_program_sh_mem_settings, .set_pasid_vmid_mapping = kgd_set_pasid_vmid_mapping, .init_pipeline = kgd_init_pipeline, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c index 309f241..c678c69 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c @@ -128,6 +128,8 @@ static const struct kfd2kgd_calls kfd2kgd = { .get_vmem_size = get_vmem_size, .get_gpu_clock_counter = get_gpu_clock_counter, .get_max_engine_clock_in_mhz = get_max_engine_clock_in_mhz, + .alloc_pasid = amdgpu_vm_alloc_pasid, + .free_pasid = amdgpu_vm_free_pasid, .program_sh_mem_settings = kgd_program_sh_mem_settings, .set_pasid_vmid_mapping = kgd_set_pasid_vmid_mapping, .init_pipeline = kgd_init_pipeline, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c index fd435a9..383204e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c @@ -45,7 +45,6 @@ struct amdgpu_cgs_device { static int amdgpu_cgs_alloc_gpu_mem(struct cgs_device *cgs_device, enum cgs_gpu_mem_type type, uint64_t size, uint64_t align, - uint64_t min_offset, uint64_t max_offset, cgs_handle_t *handle) { CGS_FUNC_ADEV; @@ -53,13 +52,6 @@ static int amdgpu_cgs_alloc_gpu_mem(struct cgs_device *cgs_device, int ret = 0; uint32_t domain = 0; struct amdgpu_bo *obj; - struct ttm_placement placement; - struct ttm_place place; - - if (min_offset > max_offset) { - BUG_ON(1); - return -EINVAL; - } /* fail if the alignment is not a power of 2 */ if (((align != 1) && (align & (align - 1))) @@ -73,41 +65,19 @@ static int amdgpu_cgs_alloc_gpu_mem(struct cgs_device *cgs_device, flags = AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED | AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS; domain = AMDGPU_GEM_DOMAIN_VRAM; - if (max_offset > adev->mc.real_vram_size) - return -EINVAL; - place.fpfn = min_offset >> PAGE_SHIFT; - place.lpfn = max_offset >> PAGE_SHIFT; - place.flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | - TTM_PL_FLAG_VRAM; break; case CGS_GPU_MEM_TYPE__INVISIBLE_CONTIG_FB: case CGS_GPU_MEM_TYPE__INVISIBLE_FB: flags = AMDGPU_GEM_CREATE_NO_CPU_ACCESS | AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS; domain = AMDGPU_GEM_DOMAIN_VRAM; - if (adev->mc.visible_vram_size < adev->mc.real_vram_size) { - place.fpfn = - max(min_offset, adev->mc.visible_vram_size) >> PAGE_SHIFT; - place.lpfn = - min(max_offset, adev->mc.real_vram_size) >> PAGE_SHIFT; - place.flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | - TTM_PL_FLAG_VRAM; - } - break; case CGS_GPU_MEM_TYPE__GART_CACHEABLE: domain = AMDGPU_GEM_DOMAIN_GTT; - place.fpfn = min_offset >> PAGE_SHIFT; - place.lpfn = max_offset >> PAGE_SHIFT; - place.flags = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_TT; break; case CGS_GPU_MEM_TYPE__GART_WRITECOMBINE: flags = AMDGPU_GEM_CREATE_CPU_GTT_USWC; domain = AMDGPU_GEM_DOMAIN_GTT; - place.fpfn = min_offset >> PAGE_SHIFT; - place.lpfn = max_offset >> PAGE_SHIFT; - place.flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_TT | - TTM_PL_FLAG_UNCACHED; break; default: return -EINVAL; @@ -116,15 +86,8 @@ static int amdgpu_cgs_alloc_gpu_mem(struct cgs_device *cgs_device, *handle = 0; - placement.placement = &place; - placement.num_placement = 1; - placement.busy_placement = &place; - placement.num_busy_placement = 1; - - ret = amdgpu_bo_create_restricted(adev, size, PAGE_SIZE, - true, domain, flags, - NULL, &placement, NULL, - 0, &obj); + ret = amdgpu_bo_create(adev, size, align, true, domain, flags, + NULL, NULL, 0, &obj); if (ret) { DRM_ERROR("(%d) bo create failed\n", ret); return ret; @@ -155,19 +118,14 @@ static int amdgpu_cgs_gmap_gpu_mem(struct cgs_device *cgs_device, cgs_handle_t h uint64_t *mcaddr) { int r; - u64 min_offset, max_offset; struct amdgpu_bo *obj = (struct amdgpu_bo *)handle; WARN_ON_ONCE(obj->placement.num_placement > 1); - min_offset = obj->placements[0].fpfn << PAGE_SHIFT; - max_offset = obj->placements[0].lpfn << PAGE_SHIFT; - r = amdgpu_bo_reserve(obj, true); if (unlikely(r != 0)) return r; - r = amdgpu_bo_pin_restricted(obj, obj->preferred_domains, - min_offset, max_offset, mcaddr); + r = amdgpu_bo_pin(obj, obj->preferred_domains, mcaddr); amdgpu_bo_unreserve(obj); return r; } @@ -675,6 +633,85 @@ static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device, if (!adev->pm.fw) { switch (adev->asic_type) { + case CHIP_TAHITI: + strcpy(fw_name, "radeon/tahiti_smc.bin"); + break; + case CHIP_PITCAIRN: + if ((adev->pdev->revision == 0x81) && + ((adev->pdev->device == 0x6810) || + (adev->pdev->device == 0x6811))) { + info->is_kicker = true; + strcpy(fw_name, "radeon/pitcairn_k_smc.bin"); + } else { + strcpy(fw_name, "radeon/pitcairn_smc.bin"); + } + break; + case CHIP_VERDE: + if (((adev->pdev->device == 0x6820) && + ((adev->pdev->revision == 0x81) || + (adev->pdev->revision == 0x83))) || + ((adev->pdev->device == 0x6821) && + ((adev->pdev->revision == 0x83) || + (adev->pdev->revision == 0x87))) || + ((adev->pdev->revision == 0x87) && + ((adev->pdev->device == 0x6823) || + (adev->pdev->device == 0x682b)))) { + info->is_kicker = true; + strcpy(fw_name, "radeon/verde_k_smc.bin"); + } else { + strcpy(fw_name, "radeon/verde_smc.bin"); + } + break; + case CHIP_OLAND: + if (((adev->pdev->revision == 0x81) && + ((adev->pdev->device == 0x6600) || + (adev->pdev->device == 0x6604) || + (adev->pdev->device == 0x6605) || + (adev->pdev->device == 0x6610))) || + ((adev->pdev->revision == 0x83) && + (adev->pdev->device == 0x6610))) { + info->is_kicker = true; + strcpy(fw_name, "radeon/oland_k_smc.bin"); + } else { + strcpy(fw_name, "radeon/oland_smc.bin"); + } + break; + case CHIP_HAINAN: + if (((adev->pdev->revision == 0x81) && + (adev->pdev->device == 0x6660)) || + ((adev->pdev->revision == 0x83) && + ((adev->pdev->device == 0x6660) || + (adev->pdev->device == 0x6663) || + (adev->pdev->device == 0x6665) || + (adev->pdev->device == 0x6667)))) { + info->is_kicker = true; + strcpy(fw_name, "radeon/hainan_k_smc.bin"); + } else if ((adev->pdev->revision == 0xc3) && + (adev->pdev->device == 0x6665)) { + info->is_kicker = true; + strcpy(fw_name, "radeon/banks_k_2_smc.bin"); + } else { + strcpy(fw_name, "radeon/hainan_smc.bin"); + } + break; + case CHIP_BONAIRE: + if ((adev->pdev->revision == 0x80) || + (adev->pdev->revision == 0x81) || + (adev->pdev->device == 0x665f)) { + info->is_kicker = true; + strcpy(fw_name, "radeon/bonaire_k_smc.bin"); + } else { + strcpy(fw_name, "radeon/bonaire_smc.bin"); + } + break; + case CHIP_HAWAII: + if (adev->pdev->revision == 0x80) { + info->is_kicker = true; + strcpy(fw_name, "radeon/hawaii_k_smc.bin"); + } else { + strcpy(fw_name, "radeon/hawaii_smc.bin"); + } + break; case CHIP_TOPAZ: if (((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0x81)) || ((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0x83)) || @@ -838,6 +875,9 @@ static int amdgpu_cgs_query_system_info(struct cgs_device *cgs_device, case CGS_SYSTEM_INFO_PCIE_SUB_SYS_VENDOR_ID: sys_info->value = adev->pdev->subsystem_vendor; break; + case CGS_SYSTEM_INFO_PCIE_BUS_DEVFN: + sys_info->value = adev->pdev->devfn; + break; default: return -ENODEV; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c index 8d1cf2d..f51b41f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c @@ -346,10 +346,8 @@ static void amdgpu_connector_free_edid(struct drm_connector *connector) { struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); - if (amdgpu_connector->edid) { - kfree(amdgpu_connector->edid); - amdgpu_connector->edid = NULL; - } + kfree(amdgpu_connector->edid); + amdgpu_connector->edid = NULL; } static int amdgpu_connector_ddc_get_modes(struct drm_connector *connector) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 60d8bed..c6a214f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -473,11 +473,16 @@ static int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p, return -EPERM; /* Check if we have user pages and nobody bound the BO already */ - if (lobj->user_pages && bo->tbo.ttm->state != tt_bound) { - size_t size = sizeof(struct page *); - - size *= bo->tbo.ttm->num_pages; - memcpy(bo->tbo.ttm->pages, lobj->user_pages, size); + if (amdgpu_ttm_tt_userptr_needs_pages(bo->tbo.ttm) && + lobj->user_pages) { + amdgpu_ttm_placement_from_domain(bo, + AMDGPU_GEM_DOMAIN_CPU); + r = ttm_bo_validate(&bo->tbo, &bo->placement, true, + false); + if (r) + return r; + amdgpu_ttm_tt_set_user_pages(bo->tbo.ttm, + lobj->user_pages); binding_userptr = true; } @@ -502,7 +507,6 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, struct amdgpu_fpriv *fpriv = p->filp->driver_priv; struct amdgpu_bo_list_entry *e; struct list_head duplicates; - bool need_mmap_lock = false; unsigned i, tries = 10; int r; @@ -510,9 +514,9 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, p->bo_list = amdgpu_bo_list_get(fpriv, cs->in.bo_list_handle); if (p->bo_list) { - need_mmap_lock = p->bo_list->first_userptr != - p->bo_list->num_entries; amdgpu_bo_list_get_list(p->bo_list, &p->validated); + if (p->bo_list->first_userptr != p->bo_list->num_entries) + p->mn = amdgpu_mn_get(p->adev); } INIT_LIST_HEAD(&duplicates); @@ -521,9 +525,6 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, if (p->uf_entry.robj) list_add(&p->uf_entry.tv.head, &p->validated); - if (need_mmap_lock) - down_read(¤t->mm->mmap_sem); - while (1) { struct list_head need_pages; unsigned i; @@ -543,23 +544,25 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, INIT_LIST_HEAD(&need_pages); for (i = p->bo_list->first_userptr; i < p->bo_list->num_entries; ++i) { + struct amdgpu_bo *bo; e = &p->bo_list->array[i]; + bo = e->robj; - if (amdgpu_ttm_tt_userptr_invalidated(e->robj->tbo.ttm, + if (amdgpu_ttm_tt_userptr_invalidated(bo->tbo.ttm, &e->user_invalidated) && e->user_pages) { /* We acquired a page array, but somebody * invalidated it. Free it and try again */ release_pages(e->user_pages, - e->robj->tbo.ttm->num_pages, + bo->tbo.ttm->num_pages, false); kvfree(e->user_pages); e->user_pages = NULL; } - if (e->robj->tbo.ttm->state != tt_bound && + if (amdgpu_ttm_tt_userptr_needs_pages(bo->tbo.ttm) && !e->user_pages) { list_del(&e->tv.head); list_add(&e->tv.head, &need_pages); @@ -636,9 +639,6 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, amdgpu_cs_report_moved_bytes(p->adev, p->bytes_moved, p->bytes_moved_vis); - fpriv->vm.last_eviction_counter = - atomic64_read(&p->adev->num_evictions); - if (p->bo_list) { struct amdgpu_bo *gds = p->bo_list->gds_obj; struct amdgpu_bo *gws = p->bo_list->gws_obj; @@ -679,9 +679,6 @@ error_validate: error_free_pages: - if (need_mmap_lock) - up_read(¤t->mm->mmap_sem); - if (p->bo_list) { for (i = p->bo_list->first_userptr; i < p->bo_list->num_entries; ++i) { @@ -728,11 +725,7 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, { unsigned i; - if (!error) - ttm_eu_fence_buffer_objects(&parser->ticket, - &parser->validated, - parser->fence); - else if (backoff) + if (error && backoff) ttm_eu_backoff_reservation(&parser->ticket, &parser->validated); @@ -768,10 +761,6 @@ static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p) if (r) return r; - r = amdgpu_sync_fence(adev, &p->job->sync, vm->last_dir_update); - if (r) - return r; - r = amdgpu_vm_clear_freed(adev, vm, NULL); if (r) return r; @@ -825,7 +814,13 @@ static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p) } - r = amdgpu_vm_clear_moved(adev, vm, &p->job->sync); + r = amdgpu_vm_handle_moved(adev, vm); + if (r) + return r; + + r = amdgpu_sync_fence(adev, &p->job->sync, vm->last_update); + if (r) + return r; if (amdgpu_vm_debug && p->bo_list) { /* Invalidate all BOs to test for userspace bugs */ @@ -835,7 +830,7 @@ static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p) if (!bo) continue; - amdgpu_vm_bo_invalidate(adev, bo); + amdgpu_vm_bo_invalidate(adev, bo, false); } } @@ -860,7 +855,7 @@ static int amdgpu_cs_ib_vm_chunk(struct amdgpu_device *adev, } if (p->job->vm) { - p->job->vm_pd_addr = amdgpu_bo_gpu_offset(vm->root.bo); + p->job->vm_pd_addr = amdgpu_bo_gpu_offset(vm->root.base.bo); r = amdgpu_bo_vm_update_pte(p); if (r) @@ -928,11 +923,11 @@ static int amdgpu_cs_ib_fill(struct amdgpu_device *adev, uint64_t offset; uint8_t *kptr; - m = amdgpu_cs_find_mapping(parser, chunk_ib->va_start, - &aobj); - if (!aobj) { + r = amdgpu_cs_find_mapping(parser, chunk_ib->va_start, + &aobj, &m); + if (r) { DRM_ERROR("IB va_start is invalid\n"); - return -EINVAL; + return r; } if ((chunk_ib->va_start + chunk_ib->ib_bytes) > @@ -1133,14 +1128,31 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p, struct amdgpu_ring *ring = p->job->ring; struct amd_sched_entity *entity = &p->ctx->rings[ring->idx].entity; struct amdgpu_job *job; + unsigned i; + uint64_t seq; + int r; + amdgpu_mn_lock(p->mn); + if (p->bo_list) { + for (i = p->bo_list->first_userptr; + i < p->bo_list->num_entries; ++i) { + struct amdgpu_bo *bo = p->bo_list->array[i].robj; + + if (amdgpu_ttm_tt_userptr_needs_pages(bo->tbo.ttm)) { + amdgpu_mn_unlock(p->mn); + return -ERESTARTSYS; + } + } + } + job = p->job; p->job = NULL; r = amd_sched_job_init(&job->base, &ring->sched, entity, p->filp); if (r) { amdgpu_job_free(job); + amdgpu_mn_unlock(p->mn); return r; } @@ -1148,14 +1160,28 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p, job->fence_ctx = entity->fence_context; p->fence = dma_fence_get(&job->base.s_fence->finished); + r = amdgpu_ctx_add_fence(p->ctx, ring, p->fence, &seq); + if (r) { + dma_fence_put(p->fence); + dma_fence_put(&job->base.s_fence->finished); + amdgpu_job_free(job); + amdgpu_mn_unlock(p->mn); + return r; + } + amdgpu_cs_post_dependencies(p); - cs->out.handle = amdgpu_ctx_add_fence(p->ctx, ring, p->fence); - job->uf_sequence = cs->out.handle; + cs->out.handle = seq; + job->uf_sequence = seq; + amdgpu_job_free_resources(job); trace_amdgpu_cs_ioctl(job); amd_sched_entity_push_job(&job->base); + + ttm_eu_fence_buffer_objects(&p->ticket, &p->validated, p->fence); + amdgpu_mn_unlock(p->mn); + return 0; } @@ -1383,6 +1409,7 @@ static int amdgpu_cs_wait_any_fence(struct amdgpu_device *adev, array[i] = fence; } else { /* NULL, the fence has been already signaled */ r = 1; + first = i; goto out; } } @@ -1462,78 +1489,36 @@ err_free_fences: * virtual memory address. Returns allocation structure when found, NULL * otherwise. */ -struct amdgpu_bo_va_mapping * -amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser, - uint64_t addr, struct amdgpu_bo **bo) +int amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser, + uint64_t addr, struct amdgpu_bo **bo, + struct amdgpu_bo_va_mapping **map) { + struct amdgpu_fpriv *fpriv = parser->filp->driver_priv; + struct amdgpu_vm *vm = &fpriv->vm; struct amdgpu_bo_va_mapping *mapping; - unsigned i; - - if (!parser->bo_list) - return NULL; + int r; addr /= AMDGPU_GPU_PAGE_SIZE; - for (i = 0; i < parser->bo_list->num_entries; i++) { - struct amdgpu_bo_list_entry *lobj; - - lobj = &parser->bo_list->array[i]; - if (!lobj->bo_va) - continue; - - list_for_each_entry(mapping, &lobj->bo_va->valids, list) { - if (mapping->start > addr || - addr > mapping->last) - continue; - - *bo = lobj->bo_va->base.bo; - return mapping; - } - - list_for_each_entry(mapping, &lobj->bo_va->invalids, list) { - if (mapping->start > addr || - addr > mapping->last) - continue; + mapping = amdgpu_vm_bo_lookup_mapping(vm, addr); + if (!mapping || !mapping->bo_va || !mapping->bo_va->base.bo) + return -EINVAL; - *bo = lobj->bo_va->base.bo; - return mapping; - } - } + *bo = mapping->bo_va->base.bo; + *map = mapping; - return NULL; -} + /* Double check that the BO is reserved by this CS */ + if (READ_ONCE((*bo)->tbo.resv->lock.ctx) != &parser->ticket) + return -EINVAL; -/** - * amdgpu_cs_sysvm_access_required - make BOs accessible by the system VM - * - * @parser: command submission parser context - * - * Helper for UVD/VCE VM emulation, make sure BOs are accessible by the system VM. - */ -int amdgpu_cs_sysvm_access_required(struct amdgpu_cs_parser *parser) -{ - unsigned i; - int r; + r = amdgpu_ttm_bind(&(*bo)->tbo, &(*bo)->tbo.mem); + if (unlikely(r)) + return r; - if (!parser->bo_list) + if ((*bo)->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS) return 0; - for (i = 0; i < parser->bo_list->num_entries; i++) { - struct amdgpu_bo *bo = parser->bo_list->array[i].robj; - - r = amdgpu_ttm_bind(&bo->tbo, &bo->tbo.mem); - if (unlikely(r)) - return r; - - if (bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS) - continue; - - bo->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS; - amdgpu_ttm_placement_from_domain(bo, bo->allowed_domains); - r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false); - if (unlikely(r)) - return r; - } - - return 0; + (*bo)->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS; + amdgpu_ttm_placement_from_domain(*bo, (*bo)->allowed_domains); + return ttm_bo_validate(&(*bo)->tbo, &(*bo)->placement, false, false); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index a11e443..75c933b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c @@ -246,8 +246,8 @@ int amdgpu_ctx_put(struct amdgpu_ctx *ctx) return 0; } -uint64_t amdgpu_ctx_add_fence(struct amdgpu_ctx *ctx, struct amdgpu_ring *ring, - struct dma_fence *fence) +int amdgpu_ctx_add_fence(struct amdgpu_ctx *ctx, struct amdgpu_ring *ring, + struct dma_fence *fence, uint64_t* handler) { struct amdgpu_ctx_ring *cring = & ctx->rings[ring->idx]; uint64_t seq = cring->sequence; @@ -258,9 +258,9 @@ uint64_t amdgpu_ctx_add_fence(struct amdgpu_ctx *ctx, struct amdgpu_ring *ring, other = cring->fences[idx]; if (other) { signed long r; - r = dma_fence_wait_timeout(other, false, MAX_SCHEDULE_TIMEOUT); + r = dma_fence_wait_timeout(other, true, MAX_SCHEDULE_TIMEOUT); if (r < 0) - DRM_ERROR("Error (%ld) waiting for fence!\n", r); + return r; } dma_fence_get(fence); @@ -271,8 +271,10 @@ uint64_t amdgpu_ctx_add_fence(struct amdgpu_ctx *ctx, struct amdgpu_ring *ring, spin_unlock(&ctx->ring_lock); dma_fence_put(other); + if (handler) + *handler = seq; - return seq; + return 0; } struct dma_fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index e630d91..3e84ddf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -65,6 +65,7 @@ MODULE_FIRMWARE("amdgpu/raven_gpu_info.bin"); static int amdgpu_debugfs_regs_init(struct amdgpu_device *adev); static void amdgpu_debugfs_regs_cleanup(struct amdgpu_device *adev); static int amdgpu_debugfs_test_ib_ring_init(struct amdgpu_device *adev); +static int amdgpu_debugfs_vbios_dump_init(struct amdgpu_device *adev); static const char *amdgpu_asic_name[] = { "TAHITI", @@ -402,6 +403,15 @@ void amdgpu_pci_config_reset(struct amdgpu_device *adev) */ static int amdgpu_doorbell_init(struct amdgpu_device *adev) { + /* No doorbell on SI hardware generation */ + if (adev->asic_type < CHIP_BONAIRE) { + adev->doorbell.base = 0; + adev->doorbell.size = 0; + adev->doorbell.num_doorbells = 0; + adev->doorbell.ptr = NULL; + return 0; + } + /* doorbell bar mapping */ adev->doorbell.base = pci_resource_start(adev->pdev, 2); adev->doorbell.size = pci_resource_len(adev->pdev, 2); @@ -887,6 +897,20 @@ static uint32_t cail_ioreg_read(struct card_info *info, uint32_t reg) return r; } +static ssize_t amdgpu_atombios_get_vbios_version(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + struct atom_context *ctx = adev->mode_info.atom_context; + + return snprintf(buf, PAGE_SIZE, "%s\n", ctx->vbios_version); +} + +static DEVICE_ATTR(vbios_version, 0444, amdgpu_atombios_get_vbios_version, + NULL); + /** * amdgpu_atombios_fini - free the driver info and callbacks for atombios * @@ -906,6 +930,7 @@ static void amdgpu_atombios_fini(struct amdgpu_device *adev) adev->mode_info.atom_context = NULL; kfree(adev->mode_info.atom_card_info); adev->mode_info.atom_card_info = NULL; + device_remove_file(adev->dev, &dev_attr_vbios_version); } /** @@ -922,6 +947,7 @@ static int amdgpu_atombios_init(struct amdgpu_device *adev) { struct card_info *atom_card_info = kzalloc(sizeof(struct card_info), GFP_KERNEL); + int ret; if (!atom_card_info) return -ENOMEM; @@ -958,6 +984,13 @@ static int amdgpu_atombios_init(struct amdgpu_device *adev) amdgpu_atombios_scratch_regs_init(adev); amdgpu_atombios_allocate_fb_scratch(adev); } + + ret = device_create_file(adev->dev, &dev_attr_vbios_version); + if (ret) { + DRM_ERROR("Failed to create device file for VBIOS version\n"); + return ret; + } + return 0; } @@ -1757,10 +1790,8 @@ static int amdgpu_fini(struct amdgpu_device *adev) adev->ip_blocks[i].status.late_initialized = false; } - if (amdgpu_sriov_vf(adev)) { - amdgpu_bo_free_kernel(&adev->virt.csa_obj, &adev->virt.csa_vmid0_addr, NULL); + if (amdgpu_sriov_vf(adev)) amdgpu_virt_release_full_gpu(adev, false); - } return 0; } @@ -2051,9 +2082,8 @@ int amdgpu_device_init(struct amdgpu_device *adev, DRM_INFO("register mmio base: 0x%08X\n", (uint32_t)adev->rmmio_base); DRM_INFO("register mmio size: %u\n", (unsigned)adev->rmmio_size); - if (adev->asic_type >= CHIP_BONAIRE) - /* doorbell bar mapping */ - amdgpu_doorbell_init(adev); + /* doorbell bar mapping */ + amdgpu_doorbell_init(adev); /* io port mapping */ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { @@ -2201,6 +2231,10 @@ int amdgpu_device_init(struct amdgpu_device *adev, if (r) DRM_ERROR("registering firmware debugfs failed (%d).\n", r); + r = amdgpu_debugfs_vbios_dump_init(adev); + if (r) + DRM_ERROR("Creating vbios dump debugfs failed (%d).\n", r); + if ((amdgpu_testing & 1)) { if (adev->accel_working) amdgpu_test_moves(adev); @@ -2276,8 +2310,7 @@ void amdgpu_device_fini(struct amdgpu_device *adev) adev->rio_mem = NULL; iounmap(adev->rmmio); adev->rmmio = NULL; - if (adev->asic_type >= CHIP_BONAIRE) - amdgpu_doorbell_fini(adev); + amdgpu_doorbell_fini(adev); amdgpu_debugfs_regs_cleanup(adev); } @@ -2546,7 +2579,8 @@ static bool amdgpu_need_full_reset(struct amdgpu_device *adev) if ((adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) || (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC) || (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_ACP) || - (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_DCE)) { + (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_DCE) || + adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP) { if (adev->ip_blocks[i].status.hang) { DRM_INFO("Some block need full reset!\n"); return true; @@ -2654,7 +2688,7 @@ int amdgpu_sriov_gpu_reset(struct amdgpu_device *adev, struct amdgpu_job *job) mutex_lock(&adev->virt.lock_reset); atomic_inc(&adev->gpu_reset_counter); - adev->gfx.in_reset = true; + adev->in_sriov_reset = true; /* block TTM */ resched = ttm_bo_lock_delayed_workqueue(&adev->mman.bdev); @@ -2765,7 +2799,7 @@ give_up_reset: dev_info(adev->dev, "GPU reset successed!\n"); } - adev->gfx.in_reset = false; + adev->in_sriov_reset = false; mutex_unlock(&adev->virt.lock_reset); return r; } @@ -3463,10 +3497,7 @@ static ssize_t amdgpu_debugfs_sensor_read(struct file *f, char __user *buf, valuesize = sizeof(values); if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->read_sensor) - r = adev->powerplay.pp_funcs->read_sensor(adev->powerplay.pp_handle, idx, &values[0], &valuesize); - else if (adev->pm.funcs && adev->pm.funcs->read_sensor) - r = adev->pm.funcs->read_sensor(adev, idx, &values[0], - &valuesize); + r = amdgpu_dpm_read_sensor(adev, idx, &values[0], &valuesize); else return -EINVAL; @@ -3754,6 +3785,28 @@ int amdgpu_debugfs_init(struct drm_minor *minor) { return 0; } + +static int amdgpu_debugfs_get_vbios_dump(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + struct amdgpu_device *adev = dev->dev_private; + + seq_write(m, adev->bios, adev->bios_size); + return 0; +} + +static const struct drm_info_list amdgpu_vbios_dump_list[] = { + {"amdgpu_vbios", + amdgpu_debugfs_get_vbios_dump, + 0, NULL}, +}; + +static int amdgpu_debugfs_vbios_dump_init(struct amdgpu_device *adev) +{ + return amdgpu_debugfs_add_files(adev, + amdgpu_vbios_dump_list, 1); +} #else static int amdgpu_debugfs_test_ib_ring_init(struct amdgpu_device *adev) { @@ -3763,5 +3816,9 @@ static int amdgpu_debugfs_regs_init(struct amdgpu_device *adev) { return 0; } +static int amdgpu_debugfs_vbios_dump_init(struct amdgpu_device *adev) +{ + return 0; +} static void amdgpu_debugfs_regs_cleanup(struct amdgpu_device *adev) { } #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c index 1cb52fd..e997ebbe43 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c @@ -960,8 +960,10 @@ u8 amdgpu_encode_pci_lane_width(u32 lanes) } struct amd_vce_state* -amdgpu_get_vce_clock_state(struct amdgpu_device *adev, unsigned idx) +amdgpu_get_vce_clock_state(void *handle, u32 idx) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + if (idx < adev->pm.dpm.num_of_vce_states) return &adev->pm.dpm.vce_states[idx]; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h index 8c96a4c..f79f9ea 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h @@ -241,177 +241,119 @@ enum amdgpu_pcie_gen { AMDGPU_PCIE_GEN_INVALID = 0xffff }; -struct amdgpu_dpm_funcs { - int (*get_temperature)(struct amdgpu_device *adev); - int (*pre_set_power_state)(struct amdgpu_device *adev); - int (*set_power_state)(struct amdgpu_device *adev); - void (*post_set_power_state)(struct amdgpu_device *adev); - void (*display_configuration_changed)(struct amdgpu_device *adev); - u32 (*get_sclk)(struct amdgpu_device *adev, bool low); - u32 (*get_mclk)(struct amdgpu_device *adev, bool low); - void (*print_power_state)(struct amdgpu_device *adev, struct amdgpu_ps *ps); - void (*debugfs_print_current_performance_level)(struct amdgpu_device *adev, struct seq_file *m); - int (*force_performance_level)(struct amdgpu_device *adev, enum amd_dpm_forced_level level); - bool (*vblank_too_short)(struct amdgpu_device *adev); - void (*powergate_uvd)(struct amdgpu_device *adev, bool gate); - void (*powergate_vce)(struct amdgpu_device *adev, bool gate); - void (*enable_bapm)(struct amdgpu_device *adev, bool enable); - void (*set_fan_control_mode)(struct amdgpu_device *adev, u32 mode); - u32 (*get_fan_control_mode)(struct amdgpu_device *adev); - int (*set_fan_speed_percent)(struct amdgpu_device *adev, u32 speed); - int (*get_fan_speed_percent)(struct amdgpu_device *adev, u32 *speed); - int (*force_clock_level)(struct amdgpu_device *adev, enum pp_clock_type type, uint32_t mask); - int (*print_clock_levels)(struct amdgpu_device *adev, enum pp_clock_type type, char *buf); - int (*get_sclk_od)(struct amdgpu_device *adev); - int (*set_sclk_od)(struct amdgpu_device *adev, uint32_t value); - int (*get_mclk_od)(struct amdgpu_device *adev); - int (*set_mclk_od)(struct amdgpu_device *adev, uint32_t value); - int (*check_state_equal)(struct amdgpu_device *adev, - struct amdgpu_ps *cps, - struct amdgpu_ps *rps, - bool *equal); - int (*read_sensor)(struct amdgpu_device *adev, int idx, void *value, - int *size); - - struct amd_vce_state* (*get_vce_clock_state)(struct amdgpu_device *adev, unsigned idx); - int (*reset_power_profile_state)(struct amdgpu_device *adev, - struct amd_pp_profile *request); - int (*get_power_profile_state)(struct amdgpu_device *adev, - struct amd_pp_profile *query); - int (*set_power_profile_state)(struct amdgpu_device *adev, - struct amd_pp_profile *request); - int (*switch_power_profile)(struct amdgpu_device *adev, - enum amd_pp_profile_type type); -}; +#define amdgpu_dpm_pre_set_power_state(adev) \ + ((adev)->powerplay.pp_funcs->pre_set_power_state((adev)->powerplay.pp_handle)) + +#define amdgpu_dpm_set_power_state(adev) \ + ((adev)->powerplay.pp_funcs->set_power_state((adev)->powerplay.pp_handle)) + +#define amdgpu_dpm_post_set_power_state(adev) \ + ((adev)->powerplay.pp_funcs->post_set_power_state((adev)->powerplay.pp_handle)) + +#define amdgpu_dpm_display_configuration_changed(adev) \ + ((adev)->powerplay.pp_funcs->display_configuration_changed((adev)->powerplay.pp_handle)) -#define amdgpu_dpm_pre_set_power_state(adev) (adev)->pm.funcs->pre_set_power_state((adev)) -#define amdgpu_dpm_set_power_state(adev) (adev)->pm.funcs->set_power_state((adev)) -#define amdgpu_dpm_post_set_power_state(adev) (adev)->pm.funcs->post_set_power_state((adev)) -#define amdgpu_dpm_display_configuration_changed(adev) (adev)->pm.funcs->display_configuration_changed((adev)) -#define amdgpu_dpm_print_power_state(adev, ps) (adev)->pm.funcs->print_power_state((adev), (ps)) -#define amdgpu_dpm_vblank_too_short(adev) (adev)->pm.funcs->vblank_too_short((adev)) -#define amdgpu_dpm_enable_bapm(adev, e) (adev)->pm.funcs->enable_bapm((adev), (e)) +#define amdgpu_dpm_print_power_state(adev, ps) \ + ((adev)->powerplay.pp_funcs->print_power_state((adev)->powerplay.pp_handle, (ps))) + +#define amdgpu_dpm_vblank_too_short(adev) \ + ((adev)->powerplay.pp_funcs->vblank_too_short((adev)->powerplay.pp_handle)) + +#define amdgpu_dpm_enable_bapm(adev, e) \ + ((adev)->powerplay.pp_funcs->enable_bapm((adev)->powerplay.pp_handle, (e))) #define amdgpu_dpm_read_sensor(adev, idx, value, size) \ - ((adev)->pp_enabled ? \ - (adev)->powerplay.pp_funcs->read_sensor(adev->powerplay.pp_handle, (idx), (value), (size)) : \ - (adev)->pm.funcs->read_sensor((adev), (idx), (value), (size))) + ((adev)->powerplay.pp_funcs->read_sensor((adev)->powerplay.pp_handle, (idx), (value), (size))) #define amdgpu_dpm_get_temperature(adev) \ - ((adev)->pp_enabled ? \ - (adev)->powerplay.pp_funcs->get_temperature((adev)->powerplay.pp_handle) : \ - (adev)->pm.funcs->get_temperature((adev))) + ((adev)->powerplay.pp_funcs->get_temperature((adev)->powerplay.pp_handle)) #define amdgpu_dpm_set_fan_control_mode(adev, m) \ - ((adev)->pp_enabled ? \ - (adev)->powerplay.pp_funcs->set_fan_control_mode((adev)->powerplay.pp_handle, (m)) : \ - (adev)->pm.funcs->set_fan_control_mode((adev), (m))) + ((adev)->powerplay.pp_funcs->set_fan_control_mode((adev)->powerplay.pp_handle, (m))) #define amdgpu_dpm_get_fan_control_mode(adev) \ - ((adev)->pp_enabled ? \ - (adev)->powerplay.pp_funcs->get_fan_control_mode((adev)->powerplay.pp_handle) : \ - (adev)->pm.funcs->get_fan_control_mode((adev))) + ((adev)->powerplay.pp_funcs->get_fan_control_mode((adev)->powerplay.pp_handle)) #define amdgpu_dpm_set_fan_speed_percent(adev, s) \ - ((adev)->pp_enabled ? \ - (adev)->powerplay.pp_funcs->set_fan_speed_percent((adev)->powerplay.pp_handle, (s)) : \ - (adev)->pm.funcs->set_fan_speed_percent((adev), (s))) + ((adev)->powerplay.pp_funcs->set_fan_speed_percent((adev)->powerplay.pp_handle, (s))) #define amdgpu_dpm_get_fan_speed_percent(adev, s) \ - ((adev)->pp_enabled ? \ - (adev)->powerplay.pp_funcs->get_fan_speed_percent((adev)->powerplay.pp_handle, (s)) : \ - (adev)->pm.funcs->get_fan_speed_percent((adev), (s))) + ((adev)->powerplay.pp_funcs->get_fan_speed_percent((adev)->powerplay.pp_handle, (s))) #define amdgpu_dpm_get_fan_speed_rpm(adev, s) \ - ((adev)->pp_enabled ? \ - (adev)->powerplay.pp_funcs->get_fan_speed_rpm((adev)->powerplay.pp_handle, (s)) : \ - -EINVAL) + ((adev)->powerplay.pp_funcs->get_fan_speed_rpm)((adev)->powerplay.pp_handle, (s)) #define amdgpu_dpm_get_sclk(adev, l) \ - ((adev)->pp_enabled ? \ - (adev)->powerplay.pp_funcs->get_sclk((adev)->powerplay.pp_handle, (l)) : \ - (adev)->pm.funcs->get_sclk((adev), (l))) + ((adev)->powerplay.pp_funcs->get_sclk((adev)->powerplay.pp_handle, (l))) #define amdgpu_dpm_get_mclk(adev, l) \ - ((adev)->pp_enabled ? \ - (adev)->powerplay.pp_funcs->get_mclk((adev)->powerplay.pp_handle, (l)) : \ - (adev)->pm.funcs->get_mclk((adev), (l))) - + ((adev)->powerplay.pp_funcs->get_mclk((adev)->powerplay.pp_handle, (l))) #define amdgpu_dpm_force_performance_level(adev, l) \ - ((adev)->pp_enabled ? \ - (adev)->powerplay.pp_funcs->force_performance_level((adev)->powerplay.pp_handle, (l)) : \ - (adev)->pm.funcs->force_performance_level((adev), (l))) + ((adev)->powerplay.pp_funcs->force_performance_level((adev)->powerplay.pp_handle, (l))) #define amdgpu_dpm_powergate_uvd(adev, g) \ - ((adev)->pp_enabled ? \ - (adev)->powerplay.pp_funcs->powergate_uvd((adev)->powerplay.pp_handle, (g)) : \ - (adev)->pm.funcs->powergate_uvd((adev), (g))) + ((adev)->powerplay.pp_funcs->powergate_uvd((adev)->powerplay.pp_handle, (g))) #define amdgpu_dpm_powergate_vce(adev, g) \ - ((adev)->pp_enabled ? \ - (adev)->powerplay.pp_funcs->powergate_vce((adev)->powerplay.pp_handle, (g)) : \ - (adev)->pm.funcs->powergate_vce((adev), (g))) + ((adev)->powerplay.pp_funcs->powergate_vce((adev)->powerplay.pp_handle, (g))) #define amdgpu_dpm_get_current_power_state(adev) \ - (adev)->powerplay.pp_funcs->get_current_power_state((adev)->powerplay.pp_handle) + ((adev)->powerplay.pp_funcs->get_current_power_state((adev)->powerplay.pp_handle)) #define amdgpu_dpm_get_pp_num_states(adev, data) \ - (adev)->powerplay.pp_funcs->get_pp_num_states((adev)->powerplay.pp_handle, data) + ((adev)->powerplay.pp_funcs->get_pp_num_states((adev)->powerplay.pp_handle, data)) #define amdgpu_dpm_get_pp_table(adev, table) \ - (adev)->powerplay.pp_funcs->get_pp_table((adev)->powerplay.pp_handle, table) + ((adev)->powerplay.pp_funcs->get_pp_table((adev)->powerplay.pp_handle, table)) #define amdgpu_dpm_set_pp_table(adev, buf, size) \ - (adev)->powerplay.pp_funcs->set_pp_table((adev)->powerplay.pp_handle, buf, size) + ((adev)->powerplay.pp_funcs->set_pp_table((adev)->powerplay.pp_handle, buf, size)) #define amdgpu_dpm_print_clock_levels(adev, type, buf) \ - (adev)->powerplay.pp_funcs->print_clock_levels((adev)->powerplay.pp_handle, type, buf) + ((adev)->powerplay.pp_funcs->print_clock_levels((adev)->powerplay.pp_handle, type, buf)) #define amdgpu_dpm_force_clock_level(adev, type, level) \ - (adev)->powerplay.pp_funcs->force_clock_level((adev)->powerplay.pp_handle, type, level) + ((adev)->powerplay.pp_funcs->force_clock_level((adev)->powerplay.pp_handle, type, level)) #define amdgpu_dpm_get_sclk_od(adev) \ - (adev)->powerplay.pp_funcs->get_sclk_od((adev)->powerplay.pp_handle) + ((adev)->powerplay.pp_funcs->get_sclk_od((adev)->powerplay.pp_handle)) #define amdgpu_dpm_set_sclk_od(adev, value) \ - (adev)->powerplay.pp_funcs->set_sclk_od((adev)->powerplay.pp_handle, value) + ((adev)->powerplay.pp_funcs->set_sclk_od((adev)->powerplay.pp_handle, value)) #define amdgpu_dpm_get_mclk_od(adev) \ - ((adev)->powerplay.pp_funcs->get_mclk_od((adev)->powerplay.pp_handle)) + ((adev)->powerplay.pp_funcs->get_mclk_od((adev)->powerplay.pp_handle)) #define amdgpu_dpm_set_mclk_od(adev, value) \ - ((adev)->powerplay.pp_funcs->set_mclk_od((adev)->powerplay.pp_handle, value)) + ((adev)->powerplay.pp_funcs->set_mclk_od((adev)->powerplay.pp_handle, value)) -#define amdgpu_dpm_dispatch_task(adev, event_id, input, output) \ - (adev)->powerplay.pp_funcs->dispatch_tasks((adev)->powerplay.pp_handle, (event_id), (input), (output)) +#define amdgpu_dpm_dispatch_task(adev, task_id, input, output) \ + ((adev)->powerplay.pp_funcs->dispatch_tasks)((adev)->powerplay.pp_handle, (task_id), (input), (output)) -#define amgdpu_dpm_check_state_equal(adev, cps, rps, equal) (adev)->pm.funcs->check_state_equal((adev), (cps),(rps),(equal)) +#define amdgpu_dpm_check_state_equal(adev, cps, rps, equal) \ + ((adev)->powerplay.pp_funcs->check_state_equal((adev)->powerplay.pp_handle, (cps), (rps), (equal))) #define amdgpu_dpm_get_vce_clock_state(adev, i) \ - ((adev)->pp_enabled ? \ - (adev)->powerplay.pp_funcs->get_vce_clock_state((adev)->powerplay.pp_handle, (i)) : \ - (adev)->pm.funcs->get_vce_clock_state((adev), (i))) + ((adev)->powerplay.pp_funcs->get_vce_clock_state((adev)->powerplay.pp_handle, (i))) -#define amdgpu_dpm_get_performance_level(adev) \ - ((adev)->pp_enabled ? \ - (adev)->powerplay.pp_funcs->get_performance_level((adev)->powerplay.pp_handle) : \ - (adev)->pm.dpm.forced_level) +#define amdgpu_dpm_get_performance_level(adev) \ + ((adev)->powerplay.pp_funcs->get_performance_level((adev)->powerplay.pp_handle)) #define amdgpu_dpm_reset_power_profile_state(adev, request) \ - ((adev)->powerplay.pp_funcs->reset_power_profile_state(\ + ((adev)->powerplay.pp_funcs->reset_power_profile_state(\ (adev)->powerplay.pp_handle, request)) #define amdgpu_dpm_get_power_profile_state(adev, query) \ - ((adev)->powerplay.pp_funcs->get_power_profile_state(\ + ((adev)->powerplay.pp_funcs->get_power_profile_state(\ (adev)->powerplay.pp_handle, query)) #define amdgpu_dpm_set_power_profile_state(adev, request) \ - ((adev)->powerplay.pp_funcs->set_power_profile_state(\ + ((adev)->powerplay.pp_funcs->set_power_profile_state(\ (adev)->powerplay.pp_handle, request)) #define amdgpu_dpm_switch_power_profile(adev, type) \ - ((adev)->powerplay.pp_funcs->switch_power_profile(\ + ((adev)->powerplay.pp_funcs->switch_power_profile(\ (adev)->powerplay.pp_handle, type)) struct amdgpu_dpm { @@ -485,7 +427,6 @@ struct amdgpu_pm { struct amdgpu_dpm dpm; const struct firmware *fw; /* SMC firmware */ uint32_t fw_version; - const struct amdgpu_dpm_funcs *funcs; uint32_t pcie_gen_mask; uint32_t pcie_mlw_mask; struct amd_pp_display_configuration pm_display_cfg;/* set by DAL */ @@ -551,6 +492,6 @@ u16 amdgpu_get_pcie_lane_support(struct amdgpu_device *adev, u8 amdgpu_encode_pci_lane_width(u32 lanes); struct amd_vce_state* -amdgpu_get_vce_clock_state(struct amdgpu_device *adev, unsigned idx); +amdgpu_get_vce_clock_state(void *handle, u32 idx); #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 0f16986..4f98960 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -69,9 +69,10 @@ * - 3.17.0 - Add AMDGPU_NUM_VRAM_CPU_PAGE_FAULTS. * - 3.18.0 - Export gpu always on cu bitmap * - 3.19.0 - Add support for UVD MJPEG decode + * - 3.20.0 - Add support for local BOs */ #define KMS_DRIVER_MAJOR 3 -#define KMS_DRIVER_MINOR 19 +#define KMS_DRIVER_MINOR 20 #define KMS_DRIVER_PATCHLEVEL 0 int amdgpu_vram_limit = 0; @@ -91,7 +92,7 @@ int amdgpu_dpm = -1; int amdgpu_fw_load_type = -1; int amdgpu_aspm = -1; int amdgpu_runtime_pm = -1; -unsigned amdgpu_ip_block_mask = 0xffffffff; +uint amdgpu_ip_block_mask = 0xffffffff; int amdgpu_bapm = -1; int amdgpu_deep_color = 0; int amdgpu_vm_size = -1; @@ -106,14 +107,14 @@ int amdgpu_sched_jobs = 32; int amdgpu_sched_hw_submission = 2; int amdgpu_no_evict = 0; int amdgpu_direct_gma_size = 0; -unsigned amdgpu_pcie_gen_cap = 0; -unsigned amdgpu_pcie_lane_cap = 0; -unsigned amdgpu_cg_mask = 0xffffffff; -unsigned amdgpu_pg_mask = 0xffffffff; -unsigned amdgpu_sdma_phase_quantum = 32; +uint amdgpu_pcie_gen_cap = 0; +uint amdgpu_pcie_lane_cap = 0; +uint amdgpu_cg_mask = 0xffffffff; +uint amdgpu_pg_mask = 0xffffffff; +uint amdgpu_sdma_phase_quantum = 32; char *amdgpu_disable_cu = NULL; char *amdgpu_virtual_display = NULL; -unsigned amdgpu_pp_feature_mask = 0xffffffff; +uint amdgpu_pp_feature_mask = 0xffffffff; int amdgpu_ngg = 0; int amdgpu_prim_buf_per_se = 0; int amdgpu_pos_buf_per_se = 0; @@ -608,6 +609,8 @@ amdgpu_pci_remove(struct pci_dev *pdev) drm_dev_unregister(dev); drm_dev_unref(dev); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); } static void @@ -852,6 +855,7 @@ static struct drm_driver kms_driver = { .gem_prime_import_sg_table = amdgpu_gem_prime_import_sg_table, .gem_prime_vmap = amdgpu_gem_prime_vmap, .gem_prime_vunmap = amdgpu_gem_prime_vunmap, + .gem_prime_mmap = amdgpu_gem_prime_mmap, .name = DRIVER_NAME, .desc = DRIVER_DESC, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c index 9afa9c0..562930b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c @@ -149,7 +149,7 @@ static int amdgpufb_create_pinned_object(struct amdgpu_fbdev *rfbdev, AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED | AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS | AMDGPU_GEM_CREATE_VRAM_CLEARED, - true, &gobj); + true, NULL, &gobj); if (ret) { pr_err("failed to allocate framebuffer (%d)\n", aligned_size); return -ENOMEM; @@ -303,10 +303,10 @@ static int amdgpu_fbdev_destroy(struct drm_device *dev, struct amdgpu_fbdev *rfb if (rfb->obj) { amdgpufb_destroy_pinned_object(rfb->obj); rfb->obj = NULL; + drm_framebuffer_unregister_private(&rfb->base); + drm_framebuffer_cleanup(&rfb->base); } drm_fb_helper_fini(&rfbdev->helper); - drm_framebuffer_unregister_private(&rfb->base); - drm_framebuffer_cleanup(&rfb->base); return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 7171968..b0d45c8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -44,11 +44,12 @@ void amdgpu_gem_object_free(struct drm_gem_object *gobj) } int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size, - int alignment, u32 initial_domain, - u64 flags, bool kernel, - struct drm_gem_object **obj) + int alignment, u32 initial_domain, + u64 flags, bool kernel, + struct reservation_object *resv, + struct drm_gem_object **obj) { - struct amdgpu_bo *robj; + struct amdgpu_bo *bo; int r; *obj = NULL; @@ -59,7 +60,7 @@ int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size, retry: r = amdgpu_bo_create(adev, size, alignment, kernel, initial_domain, - flags, NULL, NULL, 0, &robj); + flags, NULL, resv, 0, &bo); if (r) { if (r != -ERESTARTSYS) { if (initial_domain == AMDGPU_GEM_DOMAIN_VRAM) { @@ -71,7 +72,7 @@ retry: } return r; } - *obj = &robj->gem_base; + *obj = &bo->gem_base; return 0; } @@ -112,7 +113,17 @@ int amdgpu_gem_object_open(struct drm_gem_object *obj, struct amdgpu_fpriv *fpriv = file_priv->driver_priv; struct amdgpu_vm *vm = &fpriv->vm; struct amdgpu_bo_va *bo_va; + struct mm_struct *mm; int r; + + mm = amdgpu_ttm_tt_get_usermm(abo->tbo.ttm); + if (mm && mm != current->mm) + return -EPERM; + + if (abo->flags & AMDGPU_GEM_CREATE_VM_ALWAYS_VALID && + abo->tbo.resv != vm->root.base.bo->tbo.resv) + return -EPERM; + r = amdgpu_bo_reserve(abo, false); if (r) return r; @@ -127,35 +138,6 @@ int amdgpu_gem_object_open(struct drm_gem_object *obj, return 0; } -static int amdgpu_gem_vm_check(void *param, struct amdgpu_bo *bo) -{ - /* if anything is swapped out don't swap it in here, - just abort and wait for the next CS */ - if (!amdgpu_bo_gpu_accessible(bo)) - return -ERESTARTSYS; - - if (bo->shadow && !amdgpu_bo_gpu_accessible(bo->shadow)) - return -ERESTARTSYS; - - return 0; -} - -static bool amdgpu_gem_vm_ready(struct amdgpu_device *adev, - struct amdgpu_vm *vm, - struct list_head *list) -{ - struct ttm_validate_buffer *entry; - - list_for_each_entry(entry, list, head) { - struct amdgpu_bo *bo = - container_of(entry->bo, struct amdgpu_bo, tbo); - if (amdgpu_gem_vm_check(NULL, bo)) - return false; - } - - return !amdgpu_vm_validate_pt_bos(adev, vm, amdgpu_gem_vm_check, NULL); -} - void amdgpu_gem_object_close(struct drm_gem_object *obj, struct drm_file *file_priv) { @@ -165,13 +147,14 @@ void amdgpu_gem_object_close(struct drm_gem_object *obj, struct amdgpu_vm *vm = &fpriv->vm; struct amdgpu_bo_list_entry vm_pd; - struct list_head list; + struct list_head list, duplicates; struct ttm_validate_buffer tv; struct ww_acquire_ctx ticket; struct amdgpu_bo_va *bo_va; int r; INIT_LIST_HEAD(&list); + INIT_LIST_HEAD(&duplicates); tv.bo = &bo->tbo; tv.shared = true; @@ -179,7 +162,7 @@ void amdgpu_gem_object_close(struct drm_gem_object *obj, amdgpu_vm_get_pd_bo(vm, &list, &vm_pd); - r = ttm_eu_reserve_buffers(&ticket, &list, false, NULL); + r = ttm_eu_reserve_buffers(&ticket, &list, false, &duplicates); if (r) { dev_err(adev->dev, "leaking bo va because " "we fail to reserve bo (%d)\n", r); @@ -189,7 +172,7 @@ void amdgpu_gem_object_close(struct drm_gem_object *obj, if (bo_va && --bo_va->ref_count == 0) { amdgpu_vm_bo_rmv(adev, bo_va); - if (amdgpu_gem_vm_ready(adev, vm, &list)) { + if (amdgpu_vm_ready(vm)) { struct dma_fence *fence = NULL; r = amdgpu_vm_clear_freed(adev, vm, &fence); @@ -214,18 +197,22 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_fpriv *fpriv = filp->driver_priv; + struct amdgpu_vm *vm = &fpriv->vm; union drm_amdgpu_gem_create *args = data; + uint64_t flags = args->in.domain_flags; uint64_t size = args->in.bo_size; + struct reservation_object *resv = NULL; struct drm_gem_object *gobj; uint32_t handle; - bool kernel = false; int r; /* reject invalid gem flags */ - if (args->in.domain_flags & ~(AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED | - AMDGPU_GEM_CREATE_NO_CPU_ACCESS | - AMDGPU_GEM_CREATE_CPU_GTT_USWC | - AMDGPU_GEM_CREATE_VRAM_CLEARED)) + if (flags & ~(AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED | + AMDGPU_GEM_CREATE_NO_CPU_ACCESS | + AMDGPU_GEM_CREATE_CPU_GTT_USWC | + AMDGPU_GEM_CREATE_VRAM_CLEARED | + AMDGPU_GEM_CREATE_VM_ALWAYS_VALID)) return -EINVAL; /* reject invalid gem domains */ @@ -240,7 +227,7 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data, /* create a gem object to contain this object in */ if (args->in.domains & (AMDGPU_GEM_DOMAIN_GDS | AMDGPU_GEM_DOMAIN_GWS | AMDGPU_GEM_DOMAIN_OA)) { - kernel = true; + flags |= AMDGPU_GEM_CREATE_NO_CPU_ACCESS; if (args->in.domains == AMDGPU_GEM_DOMAIN_GDS) size = size << AMDGPU_GDS_SHIFT; else if (args->in.domains == AMDGPU_GEM_DOMAIN_GWS) @@ -252,10 +239,25 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data, } size = roundup(size, PAGE_SIZE); + if (flags & AMDGPU_GEM_CREATE_VM_ALWAYS_VALID) { + r = amdgpu_bo_reserve(vm->root.base.bo, false); + if (r) + return r; + + resv = vm->root.base.bo->tbo.resv; + } + r = amdgpu_gem_object_create(adev, size, args->in.alignment, (u32)(0xffffffff & args->in.domains), - args->in.domain_flags, - kernel, &gobj); + flags, false, resv, &gobj); + if (flags & AMDGPU_GEM_CREATE_VM_ALWAYS_VALID) { + if (!r) { + struct amdgpu_bo *abo = gem_to_amdgpu_bo(gobj); + + abo->parent = amdgpu_bo_ref(vm->root.base.bo); + } + amdgpu_bo_unreserve(vm->root.base.bo); + } if (r) return r; @@ -297,9 +299,8 @@ int amdgpu_gem_userptr_ioctl(struct drm_device *dev, void *data, } /* create a gem object to contain this object in */ - r = amdgpu_gem_object_create(adev, args->size, 0, - AMDGPU_GEM_DOMAIN_CPU, 0, - 0, &gobj); + r = amdgpu_gem_object_create(adev, args->size, 0, AMDGPU_GEM_DOMAIN_CPU, + 0, 0, NULL, &gobj); if (r) return r; @@ -317,8 +318,6 @@ int amdgpu_gem_userptr_ioctl(struct drm_device *dev, void *data, } if (args->flags & AMDGPU_GEM_USERPTR_VALIDATE) { - down_read(¤t->mm->mmap_sem); - r = amdgpu_ttm_tt_get_user_pages(bo->tbo.ttm, bo->tbo.ttm->pages); if (r) @@ -333,8 +332,6 @@ int amdgpu_gem_userptr_ioctl(struct drm_device *dev, void *data, amdgpu_bo_unreserve(bo); if (r) goto free_pages; - - up_read(¤t->mm->mmap_sem); } r = drm_gem_handle_create(filp, gobj, &handle); @@ -511,10 +508,10 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, struct list_head *list, uint32_t operation) { - int r = -ERESTARTSYS; + int r; - if (!amdgpu_gem_vm_ready(adev, vm, list)) - goto error; + if (!amdgpu_vm_ready(vm)) + return; r = amdgpu_vm_update_directories(adev, vm); if (r) @@ -551,7 +548,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data, struct amdgpu_bo_list_entry vm_pd; struct ttm_validate_buffer tv; struct ww_acquire_ctx ticket; - struct list_head list; + struct list_head list, duplicates; uint64_t va_flags; int r = 0; @@ -587,6 +584,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data, } INIT_LIST_HEAD(&list); + INIT_LIST_HEAD(&duplicates); if ((args->operation != AMDGPU_VA_OP_CLEAR) && !(args->flags & AMDGPU_VM_PAGE_PRT)) { gobj = drm_gem_object_lookup(filp, args->handle); @@ -603,7 +601,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data, amdgpu_vm_get_pd_bo(&fpriv->vm, &list, &vm_pd); - r = ttm_eu_reserve_buffers(&ticket, &list, true, NULL); + r = ttm_eu_reserve_buffers(&ticket, &list, true, &duplicates); if (r) goto error_unref; @@ -669,6 +667,7 @@ error_unref: int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { + struct amdgpu_device *adev = dev->dev_private; struct drm_amdgpu_gem_op *args = data; struct drm_gem_object *gobj; struct amdgpu_bo *robj; @@ -716,6 +715,9 @@ int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data, if (robj->allowed_domains == AMDGPU_GEM_DOMAIN_VRAM) robj->allowed_domains |= AMDGPU_GEM_DOMAIN_GTT; + if (robj->flags & AMDGPU_GEM_CREATE_VM_ALWAYS_VALID) + amdgpu_vm_bo_invalidate(adev, robj, true); + amdgpu_bo_unreserve(robj); break; default: @@ -745,8 +747,7 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv, r = amdgpu_gem_object_create(adev, args->size, 0, AMDGPU_GEM_DOMAIN_VRAM, AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, - ttm_bo_type_device, - &gobj); + false, NULL, &gobj); if (r) return -ENOMEM; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c index 4f6c68f..4fcd98e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c @@ -260,8 +260,13 @@ int amdgpu_gfx_compute_mqd_sw_init(struct amdgpu_device *adev, /* create MQD for KIQ */ ring = &adev->gfx.kiq.ring; if (!ring->mqd_obj) { + /* originaly the KIQ MQD is put in GTT domain, but for SRIOV VRAM domain is a must + * otherwise hypervisor trigger SAVE_VF fail after driver unloaded which mean MQD + * deallocated and gart_unbind, to strict diverage we decide to use VRAM domain for + * KIQ MQD no matter SRIOV or Bare-metal + */ r = amdgpu_bo_create_kernel(adev, mqd_size, PAGE_SIZE, - AMDGPU_GEM_DOMAIN_GTT, &ring->mqd_obj, + AMDGPU_GEM_DOMAIN_VRAM, &ring->mqd_obj, &ring->mqd_gpu_addr, &ring->mqd_ptr); if (r) { dev_warn(adev->dev, "failed to create ring mqd ob (%d)", r); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c index 3ab4c65..f5f27e4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c @@ -169,6 +169,12 @@ restart_ih: while (adev->irq.ih.rptr != wptr) { u32 ring_index = adev->irq.ih.rptr >> 2; + /* Prescreening of high-frequency interrupts */ + if (!amdgpu_ih_prescreen_iv(adev)) { + adev->irq.ih.rptr &= adev->irq.ih.ptr_mask; + continue; + } + /* Before dispatching irq to IP blocks, send it to amdkfd */ amdgpu_amdkfd_interrupt(adev, (const void *) &adev->irq.ih.ring[ring_index]); @@ -190,3 +196,79 @@ restart_ih: return IRQ_HANDLED; } + +/** + * amdgpu_ih_add_fault - Add a page fault record + * + * @adev: amdgpu device pointer + * @key: 64-bit encoding of PASID and address + * + * This should be called when a retry page fault interrupt is + * received. If this is a new page fault, it will be added to a hash + * table. The return value indicates whether this is a new fault, or + * a fault that was already known and is already being handled. + * + * If there are too many pending page faults, this will fail. Retry + * interrupts should be ignored in this case until there is enough + * free space. + * + * Returns 0 if the fault was added, 1 if the fault was already known, + * -ENOSPC if there are too many pending faults. + */ +int amdgpu_ih_add_fault(struct amdgpu_device *adev, u64 key) +{ + unsigned long flags; + int r = -ENOSPC; + + if (WARN_ON_ONCE(!adev->irq.ih.faults)) + /* Should be allocated in <IP>_ih_sw_init on GPUs that + * support retry faults and require retry filtering. + */ + return r; + + spin_lock_irqsave(&adev->irq.ih.faults->lock, flags); + + /* Only let the hash table fill up to 50% for best performance */ + if (adev->irq.ih.faults->count >= (1 << (AMDGPU_PAGEFAULT_HASH_BITS-1))) + goto unlock_out; + + r = chash_table_copy_in(&adev->irq.ih.faults->hash, key, NULL); + if (!r) + adev->irq.ih.faults->count++; + + /* chash_table_copy_in should never fail unless we're losing count */ + WARN_ON_ONCE(r < 0); + +unlock_out: + spin_unlock_irqrestore(&adev->irq.ih.faults->lock, flags); + return r; +} + +/** + * amdgpu_ih_clear_fault - Remove a page fault record + * + * @adev: amdgpu device pointer + * @key: 64-bit encoding of PASID and address + * + * This should be called when a page fault has been handled. Any + * future interrupt with this key will be processed as a new + * page fault. + */ +void amdgpu_ih_clear_fault(struct amdgpu_device *adev, u64 key) +{ + unsigned long flags; + int r; + + if (!adev->irq.ih.faults) + return; + + spin_lock_irqsave(&adev->irq.ih.faults->lock, flags); + + r = chash_table_remove(&adev->irq.ih.faults->hash, key, NULL); + if (!WARN_ON_ONCE(r < 0)) { + adev->irq.ih.faults->count--; + WARN_ON_ONCE(adev->irq.ih.faults->count < 0); + } + + spin_unlock_irqrestore(&adev->irq.ih.faults->lock, flags); +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h index 3de8e74..ada89358 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h @@ -24,6 +24,8 @@ #ifndef __AMDGPU_IH_H__ #define __AMDGPU_IH_H__ +#include <linux/chash.h> + struct amdgpu_device; /* * vega10+ IH clients @@ -69,6 +71,13 @@ enum amdgpu_ih_clientid #define AMDGPU_IH_CLIENTID_LEGACY 0 +#define AMDGPU_PAGEFAULT_HASH_BITS 8 +struct amdgpu_retryfault_hashtable { + DECLARE_CHASH_TABLE(hash, AMDGPU_PAGEFAULT_HASH_BITS, 8, 0); + spinlock_t lock; + int count; +}; + /* * R6xx+ IH ring */ @@ -87,6 +96,7 @@ struct amdgpu_ih_ring { bool use_doorbell; bool use_bus_addr; dma_addr_t rb_dma_addr; /* only used when use_bus_addr = true */ + struct amdgpu_retryfault_hashtable *faults; }; #define AMDGPU_IH_SRC_DATA_MAX_SIZE_DW 4 @@ -109,5 +119,7 @@ int amdgpu_ih_ring_init(struct amdgpu_device *adev, unsigned ring_size, bool use_bus_addr); void amdgpu_ih_ring_fini(struct amdgpu_device *adev); int amdgpu_ih_process(struct amdgpu_device *adev); +int amdgpu_ih_add_fault(struct amdgpu_device *adev, u64 key); +void amdgpu_ih_clear_fault(struct amdgpu_device *adev, u64 key); #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index e162290..4fd06f8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -825,7 +825,7 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) } r = amdgpu_vm_init(adev, &fpriv->vm, - AMDGPU_VM_CONTEXT_GFX); + AMDGPU_VM_CONTEXT_GFX, 0); if (r) { kfree(fpriv); goto out_suspend; @@ -841,8 +841,11 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) if (amdgpu_sriov_vf(adev)) { r = amdgpu_map_static_csa(adev, &fpriv->vm, &fpriv->csa_va); - if (r) + if (r) { + amdgpu_vm_fini(adev, &fpriv->vm); + kfree(fpriv); goto out_suspend; + } } mutex_init(&fpriv->bo_list_lock); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c index 3b0f2ec..bd67f4c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c @@ -50,8 +50,10 @@ struct amdgpu_mn { struct hlist_node node; /* objects protected by lock */ - struct mutex lock; + struct rw_semaphore lock; struct rb_root_cached objects; + struct mutex read_lock; + atomic_t recursion; }; struct amdgpu_mn_node { @@ -74,7 +76,7 @@ static void amdgpu_mn_destroy(struct work_struct *work) struct amdgpu_bo *bo, *next_bo; mutex_lock(&adev->mn_lock); - mutex_lock(&rmn->lock); + down_write(&rmn->lock); hash_del(&rmn->node); rbtree_postorder_for_each_entry_safe(node, next_node, &rmn->objects.rb_root, it.rb) { @@ -84,7 +86,7 @@ static void amdgpu_mn_destroy(struct work_struct *work) } kfree(node); } - mutex_unlock(&rmn->lock); + up_write(&rmn->lock); mutex_unlock(&adev->mn_lock); mmu_notifier_unregister_no_release(&rmn->mn, rmn->mm); kfree(rmn); @@ -106,6 +108,53 @@ static void amdgpu_mn_release(struct mmu_notifier *mn, schedule_work(&rmn->work); } + +/** + * amdgpu_mn_lock - take the write side lock for this mn + */ +void amdgpu_mn_lock(struct amdgpu_mn *mn) +{ + if (mn) + down_write(&mn->lock); +} + +/** + * amdgpu_mn_unlock - drop the write side lock for this mn + */ +void amdgpu_mn_unlock(struct amdgpu_mn *mn) +{ + if (mn) + up_write(&mn->lock); +} + +/** + * amdgpu_mn_read_lock - take the rmn read lock + * + * @rmn: our notifier + * + * Take the rmn read side lock. + */ +static void amdgpu_mn_read_lock(struct amdgpu_mn *rmn) +{ + mutex_lock(&rmn->read_lock); + if (atomic_inc_return(&rmn->recursion) == 1) + down_read_non_owner(&rmn->lock); + mutex_unlock(&rmn->read_lock); +} + +/** + * amdgpu_mn_read_unlock - drop the rmn read lock + * + * @rmn: our notifier + * + * Drop the rmn read side lock. + */ +static void amdgpu_mn_read_unlock(struct amdgpu_mn *rmn) +{ + if (atomic_dec_return(&rmn->recursion) == 0) + up_read_non_owner(&rmn->lock); +} + /** * amdgpu_mn_invalidate_node - unmap all BOs of a node * @@ -126,23 +175,12 @@ static void amdgpu_mn_invalidate_node(struct amdgpu_mn_node *node, if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, start, end)) continue; - r = amdgpu_bo_reserve(bo, true); - if (r) { - DRM_ERROR("(%ld) failed to reserve user bo\n", r); - continue; - } - r = reservation_object_wait_timeout_rcu(bo->tbo.resv, true, false, MAX_SCHEDULE_TIMEOUT); if (r <= 0) DRM_ERROR("(%ld) failed to wait for user bo\n", r); - amdgpu_ttm_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_CPU); - r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false); - if (r) - DRM_ERROR("(%ld) failed to validate user bo\n", r); - - amdgpu_bo_unreserve(bo); + amdgpu_ttm_tt_mark_user_pages(bo->tbo.ttm); } } @@ -168,7 +206,7 @@ static void amdgpu_mn_invalidate_range_start(struct mmu_notifier *mn, /* notification is exclusive, but interval is inclusive */ end -= 1; - mutex_lock(&rmn->lock); + amdgpu_mn_read_lock(rmn); it = interval_tree_iter_first(&rmn->objects, start, end); while (it) { @@ -179,13 +217,32 @@ static void amdgpu_mn_invalidate_range_start(struct mmu_notifier *mn, amdgpu_mn_invalidate_node(node, start, end); } +} - mutex_unlock(&rmn->lock); +/** + * amdgpu_mn_invalidate_range_end - callback to notify about mm change + * + * @mn: our notifier + * @mn: the mm this callback is about + * @start: start of updated range + * @end: end of updated range + * + * Release the lock again to allow new command submissions. + */ +static void amdgpu_mn_invalidate_range_end(struct mmu_notifier *mn, + struct mm_struct *mm, + unsigned long start, + unsigned long end) +{ + struct amdgpu_mn *rmn = container_of(mn, struct amdgpu_mn, mn); + + amdgpu_mn_read_unlock(rmn); } static const struct mmu_notifier_ops amdgpu_mn_ops = { .release = amdgpu_mn_release, .invalidate_range_start = amdgpu_mn_invalidate_range_start, + .invalidate_range_end = amdgpu_mn_invalidate_range_end, }; /** @@ -195,7 +252,7 @@ static const struct mmu_notifier_ops amdgpu_mn_ops = { * * Creates a notifier context for current->mm. */ -static struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev) +struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev) { struct mm_struct *mm = current->mm; struct amdgpu_mn *rmn; @@ -220,8 +277,10 @@ static struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev) rmn->adev = adev; rmn->mm = mm; rmn->mn.ops = &amdgpu_mn_ops; - mutex_init(&rmn->lock); + init_rwsem(&rmn->lock); rmn->objects = RB_ROOT_CACHED; + mutex_init(&rmn->read_lock); + atomic_set(&rmn->recursion, 0); r = __mmu_notifier_register(&rmn->mn, mm); if (r) @@ -267,7 +326,7 @@ int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr) INIT_LIST_HEAD(&bos); - mutex_lock(&rmn->lock); + down_write(&rmn->lock); while ((it = interval_tree_iter_first(&rmn->objects, addr, end))) { kfree(node); @@ -281,7 +340,7 @@ int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr) if (!node) { node = kmalloc(sizeof(struct amdgpu_mn_node), GFP_KERNEL); if (!node) { - mutex_unlock(&rmn->lock); + up_write(&rmn->lock); return -ENOMEM; } } @@ -296,7 +355,7 @@ int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr) interval_tree_insert(&node->it, &rmn->objects); - mutex_unlock(&rmn->lock); + up_write(&rmn->lock); return 0; } @@ -322,7 +381,7 @@ void amdgpu_mn_unregister(struct amdgpu_bo *bo) return; } - mutex_lock(&rmn->lock); + down_write(&rmn->lock); /* save the next list entry for later */ head = bo->mn_list.next; @@ -337,6 +396,7 @@ void amdgpu_mn_unregister(struct amdgpu_bo *bo) kfree(node); } - mutex_unlock(&rmn->lock); + up_write(&rmn->lock); mutex_unlock(&adev->mn_lock); } + diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/psm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h index fbdff3e..d0095a3 100644 --- a/drivers/gpu/drm/amd/powerplay/eventmgr/psm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h @@ -1,5 +1,5 @@ /* - * Copyright 2015 Advanced Micro Devices, Inc. + * Copyright 2017 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,20 +19,34 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * + * Authors: Christian König */ -#include "eventmgr.h" -#include "eventinit.h" -#include "eventmanagement.h" -#include "eventmanager.h" -#include "power_state.h" -#include "hardwaremanager.h" +#ifndef __AMDGPU_MN_H__ +#define __AMDGPU_MN_H__ -int psm_get_ui_state(struct pp_eventmgr *eventmgr, enum PP_StateUILabel ui_label, unsigned long *state_id); - -int psm_get_state_by_classification(struct pp_eventmgr *eventmgr, enum PP_StateClassificationFlag flag, unsigned long *state_id); - -int psm_set_states(struct pp_eventmgr *eventmgr, unsigned long *state_id); +/* + * MMU Notifier + */ +struct amdgpu_mn; -int psm_adjust_power_state_dynamic(struct pp_eventmgr *eventmgr, bool skip); +#if defined(CONFIG_MMU_NOTIFIER) +void amdgpu_mn_lock(struct amdgpu_mn *mn); +void amdgpu_mn_unlock(struct amdgpu_mn *mn); +struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev); +int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr); +void amdgpu_mn_unregister(struct amdgpu_bo *bo); +#else +static inline void amdgpu_mn_lock(struct amdgpu_mn *mn) {} +static inline void amdgpu_mn_unlock(struct amdgpu_mn *mn) {} +static inline struct amdgpu_mn *amdgpu_mn_get(struct amdgpu_device *adev) +{ + return NULL; +} +static inline int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr) +{ + return -ENODEV; +} +static inline void amdgpu_mn_unregister(struct amdgpu_bo *bo) {} +#endif -int psm_adjust_power_state_static(struct pp_eventmgr *eventmgr, bool skip); +#endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 9e495da..6982bae 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -64,11 +64,12 @@ bool amdgpu_ttm_bo_is_amdgpu_bo(struct ttm_buffer_object *bo) return false; } -static void amdgpu_ttm_placement_init(struct amdgpu_device *adev, - struct ttm_placement *placement, - struct ttm_place *places, - u32 domain, u64 flags) +void amdgpu_ttm_placement_from_domain(struct amdgpu_bo *abo, u32 domain) { + struct amdgpu_device *adev = amdgpu_ttm_adev(abo->tbo.bdev); + struct ttm_placement *placement = &abo->placement; + struct ttm_place *places = abo->placements; + u64 flags = abo->flags; u32 c = 0; if (domain & AMDGPU_GEM_DOMAIN_VRAM) { @@ -151,27 +152,6 @@ static void amdgpu_ttm_placement_init(struct amdgpu_device *adev, placement->busy_placement = places; } -void amdgpu_ttm_placement_from_domain(struct amdgpu_bo *abo, u32 domain) -{ - struct amdgpu_device *adev = amdgpu_ttm_adev(abo->tbo.bdev); - - amdgpu_ttm_placement_init(adev, &abo->placement, abo->placements, - domain, abo->flags); -} - -static void amdgpu_fill_placement_to_bo(struct amdgpu_bo *bo, - struct ttm_placement *placement) -{ - BUG_ON(placement->num_placement > (AMDGPU_GEM_DOMAIN_MAX + 1)); - - memcpy(bo->placements, placement->placement, - placement->num_placement * sizeof(struct ttm_place)); - bo->placement.num_placement = placement->num_placement; - bo->placement.num_busy_placement = placement->num_busy_placement; - bo->placement.placement = bo->placements; - bo->placement.busy_placement = bo->placements; -} - /** * amdgpu_bo_create_reserved - create reserved BO for kernel use * @@ -303,14 +283,13 @@ void amdgpu_bo_free_kernel(struct amdgpu_bo **bo, u64 *gpu_addr, *cpu_addr = NULL; } -int amdgpu_bo_create_restricted(struct amdgpu_device *adev, - unsigned long size, int byte_align, - bool kernel, u32 domain, u64 flags, - struct sg_table *sg, - struct ttm_placement *placement, - struct reservation_object *resv, - uint64_t init_value, - struct amdgpu_bo **bo_ptr) +static int amdgpu_bo_do_create(struct amdgpu_device *adev, + unsigned long size, int byte_align, + bool kernel, u32 domain, u64 flags, + struct sg_table *sg, + struct reservation_object *resv, + uint64_t init_value, + struct amdgpu_bo **bo_ptr) { struct amdgpu_bo *bo; enum ttm_bo_type type; @@ -384,10 +363,11 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev, bo->flags &= ~AMDGPU_GEM_CREATE_CPU_GTT_USWC; #endif - amdgpu_fill_placement_to_bo(bo, placement); - /* Kernel allocation are uninterruptible */ + bo->tbo.bdev = &adev->mman.bdev; + amdgpu_ttm_placement_from_domain(bo, domain); initial_bytes_moved = atomic64_read(&adev->num_bytes_moved); + /* Kernel allocation are uninterruptible */ r = ttm_bo_init_reserved(&adev->mman.bdev, &bo->tbo, size, type, &bo->placement, page_align, !kernel, NULL, acc_size, sg, resv, &amdgpu_ttm_bo_destroy); @@ -442,27 +422,17 @@ static int amdgpu_bo_create_shadow(struct amdgpu_device *adev, unsigned long size, int byte_align, struct amdgpu_bo *bo) { - struct ttm_placement placement = {0}; - struct ttm_place placements[AMDGPU_GEM_DOMAIN_MAX + 1]; int r; if (bo->shadow) return 0; - memset(&placements, 0, sizeof(placements)); - amdgpu_ttm_placement_init(adev, &placement, placements, - AMDGPU_GEM_DOMAIN_GTT, - AMDGPU_GEM_CREATE_CPU_GTT_USWC | - AMDGPU_GEM_CREATE_SHADOW); - - r = amdgpu_bo_create_restricted(adev, size, byte_align, true, - AMDGPU_GEM_DOMAIN_GTT, - AMDGPU_GEM_CREATE_CPU_GTT_USWC | - AMDGPU_GEM_CREATE_SHADOW, - NULL, &placement, - bo->tbo.resv, - 0, - &bo->shadow); + r = amdgpu_bo_do_create(adev, size, byte_align, true, + AMDGPU_GEM_DOMAIN_GTT, + AMDGPU_GEM_CREATE_CPU_GTT_USWC | + AMDGPU_GEM_CREATE_SHADOW, + NULL, bo->tbo.resv, 0, + &bo->shadow); if (!r) { bo->shadow->parent = amdgpu_bo_ref(bo); mutex_lock(&adev->shadow_list_lock); @@ -484,18 +454,11 @@ int amdgpu_bo_create(struct amdgpu_device *adev, uint64_t init_value, struct amdgpu_bo **bo_ptr) { - struct ttm_placement placement = {0}; - struct ttm_place placements[AMDGPU_GEM_DOMAIN_MAX + 1]; uint64_t parent_flags = flags & ~AMDGPU_GEM_CREATE_SHADOW; int r; - memset(&placements, 0, sizeof(placements)); - amdgpu_ttm_placement_init(adev, &placement, placements, - domain, parent_flags); - - r = amdgpu_bo_create_restricted(adev, size, byte_align, kernel, domain, - parent_flags, sg, &placement, resv, - init_value, bo_ptr); + r = amdgpu_bo_do_create(adev, size, byte_align, kernel, domain, + parent_flags, sg, resv, init_value, bo_ptr); if (r) return r; @@ -672,7 +635,6 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, { struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); int r, i; - unsigned fpfn, lpfn; if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm)) return -EPERM; @@ -704,22 +666,16 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, } bo->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS; + /* force to pin into visible video ram */ + if (!(bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)) + bo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED; amdgpu_ttm_placement_from_domain(bo, domain); for (i = 0; i < bo->placement.num_placement; i++) { - /* force to pin into visible video ram */ - if ((bo->placements[i].flags & TTM_PL_FLAG_VRAM) && - !(bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS) && - (!max_offset || max_offset > - adev->mc.visible_vram_size)) { - if (WARN_ON_ONCE(min_offset > - adev->mc.visible_vram_size)) - return -EINVAL; - fpfn = min_offset >> PAGE_SHIFT; - lpfn = adev->mc.visible_vram_size >> PAGE_SHIFT; - } else { - fpfn = min_offset >> PAGE_SHIFT; - lpfn = max_offset >> PAGE_SHIFT; - } + unsigned fpfn, lpfn; + + fpfn = min_offset >> PAGE_SHIFT; + lpfn = max_offset >> PAGE_SHIFT; + if (fpfn > bo->placements[i].fpfn) bo->placements[i].fpfn = fpfn; if (!bo->placements[i].lpfn || @@ -929,7 +885,7 @@ void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, return; abo = container_of(bo, struct amdgpu_bo, tbo); - amdgpu_vm_bo_invalidate(adev, abo); + amdgpu_vm_bo_invalidate(adev, abo, evict); amdgpu_bo_kunmap(abo); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h index a288fa6..39b6bf6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h @@ -35,6 +35,7 @@ /* bo virtual addresses in a vm */ struct amdgpu_bo_va_mapping { + struct amdgpu_bo_va *bo_va; struct list_head list; struct rb_node rb; uint64_t start; @@ -49,12 +50,17 @@ struct amdgpu_bo_va { struct amdgpu_vm_bo_base base; /* protected by bo being reserved */ - struct dma_fence *last_pt_update; unsigned ref_count; + /* all other members protected by the VM PD being reserved */ + struct dma_fence *last_pt_update; + /* mappings for this bo_va */ struct list_head invalids; struct list_head valids; + + /* If the mappings are cleared or filled */ + bool cleared; }; struct amdgpu_bo { @@ -189,14 +195,6 @@ int amdgpu_bo_create(struct amdgpu_device *adev, struct reservation_object *resv, uint64_t init_value, struct amdgpu_bo **bo_ptr); -int amdgpu_bo_create_restricted(struct amdgpu_device *adev, - unsigned long size, int byte_align, - bool kernel, u32 domain, u64 flags, - struct sg_table *sg, - struct ttm_placement *placement, - struct reservation_object *resv, - uint64_t init_value, - struct amdgpu_bo **bo_ptr); int amdgpu_bo_create_reserved(struct amdgpu_device *adev, unsigned long size, int align, u32 domain, struct amdgpu_bo **bo_ptr, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 7df503a..f6ce529 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -74,7 +74,7 @@ void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev) adev->pm.dpm.ac_power = true; else adev->pm.dpm.ac_power = false; - if (adev->pm.funcs->enable_bapm) + if (adev->powerplay.pp_funcs->enable_bapm) amdgpu_dpm_enable_bapm(adev, adev->pm.dpm.ac_power); mutex_unlock(&adev->pm.mutex); } @@ -88,9 +88,9 @@ static ssize_t amdgpu_get_dpm_state(struct device *dev, struct amdgpu_device *adev = ddev->dev_private; enum amd_pm_state_type pm; - if (adev->pp_enabled) { + if (adev->powerplay.pp_funcs->get_current_power_state) pm = amdgpu_dpm_get_current_power_state(adev); - } else + else pm = adev->pm.dpm.user_state; return snprintf(buf, PAGE_SIZE, "%s\n", @@ -119,7 +119,7 @@ static ssize_t amdgpu_set_dpm_state(struct device *dev, } if (adev->pp_enabled) { - amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_ENABLE_USER_STATE, &state, NULL); + amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_ENABLE_USER_STATE, &state, NULL); } else { mutex_lock(&adev->pm.mutex); adev->pm.dpm.user_state = state; @@ -140,13 +140,17 @@ static ssize_t amdgpu_get_dpm_forced_performance_level(struct device *dev, { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; - enum amd_dpm_forced_level level; + enum amd_dpm_forced_level level = 0xff; if ((adev->flags & AMD_IS_PX) && (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) return snprintf(buf, PAGE_SIZE, "off\n"); - level = amdgpu_dpm_get_performance_level(adev); + if (adev->powerplay.pp_funcs->get_performance_level) + level = amdgpu_dpm_get_performance_level(adev); + else + level = adev->pm.dpm.forced_level; + return snprintf(buf, PAGE_SIZE, "%s\n", (level == AMD_DPM_FORCED_LEVEL_AUTO) ? "auto" : (level == AMD_DPM_FORCED_LEVEL_LOW) ? "low" : @@ -167,7 +171,7 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev, struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; enum amd_dpm_forced_level level; - enum amd_dpm_forced_level current_level; + enum amd_dpm_forced_level current_level = 0xff; int ret = 0; /* Can't force performance level when the card is off */ @@ -175,7 +179,8 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev, (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) return -EINVAL; - current_level = amdgpu_dpm_get_performance_level(adev); + if (adev->powerplay.pp_funcs->get_performance_level) + current_level = amdgpu_dpm_get_performance_level(adev); if (strncmp("low", buf, strlen("low")) == 0) { level = AMD_DPM_FORCED_LEVEL_LOW; @@ -203,9 +208,7 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev, if (current_level == level) return count; - if (adev->pp_enabled) - amdgpu_dpm_force_performance_level(adev, level); - else { + if (adev->powerplay.pp_funcs->force_performance_level) { mutex_lock(&adev->pm.mutex); if (adev->pm.dpm.thermal_active) { count = -EINVAL; @@ -233,7 +236,7 @@ static ssize_t amdgpu_get_pp_num_states(struct device *dev, struct pp_states_info data; int i, buf_len; - if (adev->pp_enabled) + if (adev->powerplay.pp_funcs->get_pp_num_states) amdgpu_dpm_get_pp_num_states(adev, &data); buf_len = snprintf(buf, PAGE_SIZE, "states: %d\n", data.nums); @@ -257,8 +260,8 @@ static ssize_t amdgpu_get_pp_cur_state(struct device *dev, enum amd_pm_state_type pm = 0; int i = 0; - if (adev->pp_enabled) { - + if (adev->powerplay.pp_funcs->get_current_power_state + && adev->powerplay.pp_funcs->get_pp_num_states) { pm = amdgpu_dpm_get_current_power_state(adev); amdgpu_dpm_get_pp_num_states(adev, &data); @@ -280,25 +283,10 @@ static ssize_t amdgpu_get_pp_force_state(struct device *dev, { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; - struct pp_states_info data; - enum amd_pm_state_type pm = 0; - int i; - - if (adev->pp_force_state_enabled && adev->pp_enabled) { - pm = amdgpu_dpm_get_current_power_state(adev); - amdgpu_dpm_get_pp_num_states(adev, &data); - - for (i = 0; i < data.nums; i++) { - if (pm == data.states[i]) - break; - } - if (i == data.nums) - i = -EINVAL; - - return snprintf(buf, PAGE_SIZE, "%d\n", i); - - } else + if (adev->pp_force_state_enabled) + return amdgpu_get_pp_cur_state(dev, attr, buf); + else return snprintf(buf, PAGE_SIZE, "\n"); } @@ -330,7 +318,7 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev, if (state != POWER_STATE_TYPE_INTERNAL_BOOT && state != POWER_STATE_TYPE_DEFAULT) { amdgpu_dpm_dispatch_task(adev, - AMD_PP_EVENT_ENABLE_USER_STATE, &state, NULL); + AMD_PP_TASK_ENABLE_USER_STATE, &state, NULL); adev->pp_force_state_enabled = true; } } @@ -347,7 +335,7 @@ static ssize_t amdgpu_get_pp_table(struct device *dev, char *table = NULL; int size; - if (adev->pp_enabled) + if (adev->powerplay.pp_funcs->get_pp_table) size = amdgpu_dpm_get_pp_table(adev, &table); else return 0; @@ -368,7 +356,7 @@ static ssize_t amdgpu_set_pp_table(struct device *dev, struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; - if (adev->pp_enabled) + if (adev->powerplay.pp_funcs->set_pp_table) amdgpu_dpm_set_pp_table(adev, buf, count); return count; @@ -380,14 +368,11 @@ static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev, { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; - ssize_t size = 0; - if (adev->pp_enabled) - size = amdgpu_dpm_print_clock_levels(adev, PP_SCLK, buf); - else if (adev->pm.funcs->print_clock_levels) - size = adev->pm.funcs->print_clock_levels(adev, PP_SCLK, buf); - - return size; + if (adev->powerplay.pp_funcs->print_clock_levels) + return amdgpu_dpm_print_clock_levels(adev, PP_SCLK, buf); + else + return snprintf(buf, PAGE_SIZE, "\n"); } static ssize_t amdgpu_set_pp_dpm_sclk(struct device *dev, @@ -416,10 +401,9 @@ static ssize_t amdgpu_set_pp_dpm_sclk(struct device *dev, mask |= 1 << level; } - if (adev->pp_enabled) + if (adev->powerplay.pp_funcs->force_clock_level) amdgpu_dpm_force_clock_level(adev, PP_SCLK, mask); - else if (adev->pm.funcs->force_clock_level) - adev->pm.funcs->force_clock_level(adev, PP_SCLK, mask); + fail: return count; } @@ -430,14 +414,11 @@ static ssize_t amdgpu_get_pp_dpm_mclk(struct device *dev, { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; - ssize_t size = 0; - - if (adev->pp_enabled) - size = amdgpu_dpm_print_clock_levels(adev, PP_MCLK, buf); - else if (adev->pm.funcs->print_clock_levels) - size = adev->pm.funcs->print_clock_levels(adev, PP_MCLK, buf); - return size; + if (adev->powerplay.pp_funcs->print_clock_levels) + return amdgpu_dpm_print_clock_levels(adev, PP_MCLK, buf); + else + return snprintf(buf, PAGE_SIZE, "\n"); } static ssize_t amdgpu_set_pp_dpm_mclk(struct device *dev, @@ -465,11 +446,9 @@ static ssize_t amdgpu_set_pp_dpm_mclk(struct device *dev, } mask |= 1 << level; } - - if (adev->pp_enabled) + if (adev->powerplay.pp_funcs->force_clock_level) amdgpu_dpm_force_clock_level(adev, PP_MCLK, mask); - else if (adev->pm.funcs->force_clock_level) - adev->pm.funcs->force_clock_level(adev, PP_MCLK, mask); + fail: return count; } @@ -480,14 +459,11 @@ static ssize_t amdgpu_get_pp_dpm_pcie(struct device *dev, { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; - ssize_t size = 0; - - if (adev->pp_enabled) - size = amdgpu_dpm_print_clock_levels(adev, PP_PCIE, buf); - else if (adev->pm.funcs->print_clock_levels) - size = adev->pm.funcs->print_clock_levels(adev, PP_PCIE, buf); - return size; + if (adev->powerplay.pp_funcs->print_clock_levels) + return amdgpu_dpm_print_clock_levels(adev, PP_PCIE, buf); + else + return snprintf(buf, PAGE_SIZE, "\n"); } static ssize_t amdgpu_set_pp_dpm_pcie(struct device *dev, @@ -515,11 +491,9 @@ static ssize_t amdgpu_set_pp_dpm_pcie(struct device *dev, } mask |= 1 << level; } - - if (adev->pp_enabled) + if (adev->powerplay.pp_funcs->force_clock_level) amdgpu_dpm_force_clock_level(adev, PP_PCIE, mask); - else if (adev->pm.funcs->force_clock_level) - adev->pm.funcs->force_clock_level(adev, PP_PCIE, mask); + fail: return count; } @@ -532,10 +506,8 @@ static ssize_t amdgpu_get_pp_sclk_od(struct device *dev, struct amdgpu_device *adev = ddev->dev_private; uint32_t value = 0; - if (adev->pp_enabled) + if (adev->powerplay.pp_funcs->get_sclk_od) value = amdgpu_dpm_get_sclk_od(adev); - else if (adev->pm.funcs->get_sclk_od) - value = adev->pm.funcs->get_sclk_od(adev); return snprintf(buf, PAGE_SIZE, "%d\n", value); } @@ -556,12 +528,12 @@ static ssize_t amdgpu_set_pp_sclk_od(struct device *dev, count = -EINVAL; goto fail; } + if (adev->powerplay.pp_funcs->set_sclk_od) + amdgpu_dpm_set_sclk_od(adev, (uint32_t)value); if (adev->pp_enabled) { - amdgpu_dpm_set_sclk_od(adev, (uint32_t)value); - amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_READJUST_POWER_STATE, NULL, NULL); - } else if (adev->pm.funcs->set_sclk_od) { - adev->pm.funcs->set_sclk_od(adev, (uint32_t)value); + amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_READJUST_POWER_STATE, NULL, NULL); + } else { adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; amdgpu_pm_compute_clocks(adev); } @@ -578,10 +550,8 @@ static ssize_t amdgpu_get_pp_mclk_od(struct device *dev, struct amdgpu_device *adev = ddev->dev_private; uint32_t value = 0; - if (adev->pp_enabled) + if (adev->powerplay.pp_funcs->get_mclk_od) value = amdgpu_dpm_get_mclk_od(adev); - else if (adev->pm.funcs->get_mclk_od) - value = adev->pm.funcs->get_mclk_od(adev); return snprintf(buf, PAGE_SIZE, "%d\n", value); } @@ -602,12 +572,12 @@ static ssize_t amdgpu_set_pp_mclk_od(struct device *dev, count = -EINVAL; goto fail; } + if (adev->powerplay.pp_funcs->set_mclk_od) + amdgpu_dpm_set_mclk_od(adev, (uint32_t)value); if (adev->pp_enabled) { - amdgpu_dpm_set_mclk_od(adev, (uint32_t)value); - amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_READJUST_POWER_STATE, NULL, NULL); - } else if (adev->pm.funcs->set_mclk_od) { - adev->pm.funcs->set_mclk_od(adev, (uint32_t)value); + amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_READJUST_POWER_STATE, NULL, NULL); + } else { adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; amdgpu_pm_compute_clocks(adev); } @@ -621,14 +591,11 @@ static ssize_t amdgpu_get_pp_power_profile(struct device *dev, { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; - int ret = 0; + int ret = 0xff; - if (adev->pp_enabled) + if (adev->powerplay.pp_funcs->get_power_profile_state) ret = amdgpu_dpm_get_power_profile_state( adev, query); - else if (adev->pm.funcs->get_power_profile_state) - ret = adev->pm.funcs->get_power_profile_state( - adev, query); if (ret) return ret; @@ -675,15 +642,12 @@ static ssize_t amdgpu_set_pp_power_profile(struct device *dev, char *sub_str, buf_cpy[128], *tmp_str; const char delimiter[3] = {' ', '\n', '\0'}; long int value; - int ret = 0; + int ret = 0xff; if (strncmp("reset", buf, strlen("reset")) == 0) { - if (adev->pp_enabled) + if (adev->powerplay.pp_funcs->reset_power_profile_state) ret = amdgpu_dpm_reset_power_profile_state( adev, request); - else if (adev->pm.funcs->reset_power_profile_state) - ret = adev->pm.funcs->reset_power_profile_state( - adev, request); if (ret) { count = -EINVAL; goto fail; @@ -692,12 +656,10 @@ static ssize_t amdgpu_set_pp_power_profile(struct device *dev, } if (strncmp("set", buf, strlen("set")) == 0) { - if (adev->pp_enabled) + if (adev->powerplay.pp_funcs->set_power_profile_state) ret = amdgpu_dpm_set_power_profile_state( adev, request); - else if (adev->pm.funcs->set_power_profile_state) - ret = adev->pm.funcs->set_power_profile_state( - adev, request); + if (ret) { count = -EINVAL; goto fail; @@ -745,13 +707,8 @@ static ssize_t amdgpu_set_pp_power_profile(struct device *dev, loop++; } - - if (adev->pp_enabled) - ret = amdgpu_dpm_set_power_profile_state( - adev, request); - else if (adev->pm.funcs->set_power_profile_state) - ret = adev->pm.funcs->set_power_profile_state( - adev, request); + if (adev->powerplay.pp_funcs->set_power_profile_state) + ret = amdgpu_dpm_set_power_profile_state(adev, request); if (ret) count = -EINVAL; @@ -831,7 +788,7 @@ static ssize_t amdgpu_hwmon_show_temp(struct device *dev, (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) return -EINVAL; - if (!adev->pp_enabled && !adev->pm.funcs->get_temperature) + if (!adev->powerplay.pp_funcs->get_temperature) temp = 0; else temp = amdgpu_dpm_get_temperature(adev); @@ -862,7 +819,7 @@ static ssize_t amdgpu_hwmon_get_pwm1_enable(struct device *dev, struct amdgpu_device *adev = dev_get_drvdata(dev); u32 pwm_mode = 0; - if (!adev->pp_enabled && !adev->pm.funcs->get_fan_control_mode) + if (!adev->powerplay.pp_funcs->get_fan_control_mode) return -EINVAL; pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); @@ -879,7 +836,7 @@ static ssize_t amdgpu_hwmon_set_pwm1_enable(struct device *dev, int err; int value; - if (!adev->pp_enabled && !adev->pm.funcs->set_fan_control_mode) + if (!adev->powerplay.pp_funcs->set_fan_control_mode) return -EINVAL; err = kstrtoint(buf, 10, &value); @@ -919,9 +876,11 @@ static ssize_t amdgpu_hwmon_set_pwm1(struct device *dev, value = (value * 100) / 255; - err = amdgpu_dpm_set_fan_speed_percent(adev, value); - if (err) - return err; + if (adev->powerplay.pp_funcs->set_fan_speed_percent) { + err = amdgpu_dpm_set_fan_speed_percent(adev, value); + if (err) + return err; + } return count; } @@ -932,11 +891,13 @@ static ssize_t amdgpu_hwmon_get_pwm1(struct device *dev, { struct amdgpu_device *adev = dev_get_drvdata(dev); int err; - u32 speed; + u32 speed = 0; - err = amdgpu_dpm_get_fan_speed_percent(adev, &speed); - if (err) - return err; + if (adev->powerplay.pp_funcs->get_fan_speed_percent) { + err = amdgpu_dpm_get_fan_speed_percent(adev, &speed); + if (err) + return err; + } speed = (speed * 255) / 100; @@ -949,11 +910,13 @@ static ssize_t amdgpu_hwmon_get_fan1_input(struct device *dev, { struct amdgpu_device *adev = dev_get_drvdata(dev); int err; - u32 speed; + u32 speed = 0; - err = amdgpu_dpm_get_fan_speed_rpm(adev, &speed); - if (err) - return err; + if (adev->powerplay.pp_funcs->get_fan_speed_rpm) { + err = amdgpu_dpm_get_fan_speed_rpm(adev, &speed); + if (err) + return err; + } return sprintf(buf, "%i\n", speed); } @@ -1008,21 +971,21 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, return 0; /* mask fan attributes if we have no bindings for this asic to expose */ - if ((!adev->pm.funcs->get_fan_speed_percent && + if ((!adev->powerplay.pp_funcs->get_fan_speed_percent && attr == &sensor_dev_attr_pwm1.dev_attr.attr) || /* can't query fan */ - (!adev->pm.funcs->get_fan_control_mode && + (!adev->powerplay.pp_funcs->get_fan_control_mode && attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr)) /* can't query state */ effective_mode &= ~S_IRUGO; - if ((!adev->pm.funcs->set_fan_speed_percent && + if ((!adev->powerplay.pp_funcs->set_fan_speed_percent && attr == &sensor_dev_attr_pwm1.dev_attr.attr) || /* can't manage fan */ - (!adev->pm.funcs->set_fan_control_mode && + (!adev->powerplay.pp_funcs->set_fan_control_mode && attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr)) /* can't manage state */ effective_mode &= ~S_IWUSR; /* hide max/min values if we can't both query and manage the fan */ - if ((!adev->pm.funcs->set_fan_speed_percent && - !adev->pm.funcs->get_fan_speed_percent) && + if ((!adev->powerplay.pp_funcs->set_fan_speed_percent && + !adev->powerplay.pp_funcs->get_fan_speed_percent) && (attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || attr == &sensor_dev_attr_pwm1_min.dev_attr.attr)) return 0; @@ -1055,7 +1018,7 @@ void amdgpu_dpm_thermal_work_handler(struct work_struct *work) if (!adev->pm.dpm_enabled) return; - if (adev->pm.funcs->get_temperature) { + if (adev->powerplay.pp_funcs->get_temperature) { int temp = amdgpu_dpm_get_temperature(adev); if (temp < adev->pm.dpm.thermal.min_temp) @@ -1087,7 +1050,7 @@ static struct amdgpu_ps *amdgpu_dpm_pick_power_state(struct amdgpu_device *adev, true : false; /* check if the vblank period is too short to adjust the mclk */ - if (single_display && adev->pm.funcs->vblank_too_short) { + if (single_display && adev->powerplay.pp_funcs->vblank_too_short) { if (amdgpu_dpm_vblank_too_short(adev)) single_display = false; } @@ -1216,7 +1179,7 @@ static void amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev) struct amdgpu_ps *ps; enum amd_pm_state_type dpm_state; int ret; - bool equal; + bool equal = false; /* if dpm init failed */ if (!adev->pm.dpm_enabled) @@ -1236,7 +1199,7 @@ static void amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev) else return; - if (amdgpu_dpm == 1) { + if (amdgpu_dpm == 1 && adev->powerplay.pp_funcs->print_power_state) { printk("switching from power state:\n"); amdgpu_dpm_print_power_state(adev, adev->pm.dpm.current_ps); printk("switching to power state:\n"); @@ -1245,15 +1208,17 @@ static void amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev) /* update whether vce is active */ ps->vce_active = adev->pm.dpm.vce_active; - - amdgpu_dpm_display_configuration_changed(adev); + if (adev->powerplay.pp_funcs->display_configuration_changed) + amdgpu_dpm_display_configuration_changed(adev); ret = amdgpu_dpm_pre_set_power_state(adev); if (ret) return; - if ((0 != amgdpu_dpm_check_state_equal(adev, adev->pm.dpm.current_ps, adev->pm.dpm.requested_ps, &equal))) - equal = false; + if (adev->powerplay.pp_funcs->check_state_equal) { + if (0 != amdgpu_dpm_check_state_equal(adev, adev->pm.dpm.current_ps, adev->pm.dpm.requested_ps, &equal)) + equal = false; + } if (equal) return; @@ -1264,7 +1229,7 @@ static void amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev) adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs; adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count; - if (adev->pm.funcs->force_performance_level) { + if (adev->powerplay.pp_funcs->force_performance_level) { if (adev->pm.dpm.thermal_active) { enum amd_dpm_forced_level level = adev->pm.dpm.forced_level; /* force low perf level for thermal */ @@ -1280,7 +1245,7 @@ static void amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev) void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable) { - if (adev->pp_enabled || adev->pm.funcs->powergate_uvd) { + if (adev->powerplay.pp_funcs->powergate_uvd) { /* enable/disable UVD */ mutex_lock(&adev->pm.mutex); amdgpu_dpm_powergate_uvd(adev, !enable); @@ -1302,7 +1267,7 @@ void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable) void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable) { - if (adev->pp_enabled || adev->pm.funcs->powergate_vce) { + if (adev->powerplay.pp_funcs->powergate_vce) { /* enable/disable VCE */ mutex_lock(&adev->pm.mutex); amdgpu_dpm_powergate_vce(adev, !enable); @@ -1337,8 +1302,7 @@ void amdgpu_pm_print_power_states(struct amdgpu_device *adev) { int i; - if (adev->pp_enabled) - /* TO DO */ + if (adev->powerplay.pp_funcs->print_power_state == NULL) return; for (i = 0; i < adev->pm.dpm.num_ps; i++) @@ -1353,10 +1317,8 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev) if (adev->pm.sysfs_initialized) return 0; - if (!adev->pp_enabled) { - if (adev->pm.funcs->get_temperature == NULL) - return 0; - } + if (adev->powerplay.pp_funcs->get_temperature == NULL) + return 0; adev->pm.int_hwmon_dev = hwmon_device_register_with_groups(adev->dev, DRIVER_NAME, adev, @@ -1496,7 +1458,7 @@ void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) } if (adev->pp_enabled) { - amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE, NULL, NULL); + amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_DISPLAY_CONFIG_CHANGE, NULL, NULL); } else { mutex_lock(&adev->pm.mutex); adev->pm.dpm.new_active_crtcs = 0; @@ -1634,8 +1596,8 @@ static int amdgpu_debugfs_pm_info(struct seq_file *m, void *data) return amdgpu_debugfs_pm_info_pp(m, adev); } else { mutex_lock(&adev->pm.mutex); - if (adev->pm.funcs->debugfs_print_current_performance_level) - adev->pm.funcs->debugfs_print_current_performance_level(adev, m); + if (adev->powerplay.pp_funcs->debugfs_print_current_performance_level) + adev->powerplay.pp_funcs->debugfs_print_current_performance_level(adev, m); else seq_printf(m, "Debugfs support not implemented for this asic\n"); mutex_unlock(&adev->pm.mutex); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c index b7e1c02..2d2f0960 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c @@ -87,17 +87,28 @@ static int amdgpu_pp_early_init(void *handle) case CHIP_OLAND: case CHIP_HAINAN: amd_pp->ip_funcs = &si_dpm_ip_funcs; + amd_pp->pp_funcs = &si_dpm_funcs; break; #endif #ifdef CONFIG_DRM_AMDGPU_CIK case CHIP_BONAIRE: case CHIP_HAWAII: - amd_pp->ip_funcs = &ci_dpm_ip_funcs; + if (amdgpu_dpm == -1) { + amd_pp->ip_funcs = &ci_dpm_ip_funcs; + amd_pp->pp_funcs = &ci_dpm_funcs; + } else { + adev->pp_enabled = true; + if (amdgpu_create_pp_handle(adev)) + return -EINVAL; + amd_pp->ip_funcs = &pp_ip_funcs; + amd_pp->pp_funcs = &pp_dpm_funcs; + } break; case CHIP_KABINI: case CHIP_MULLINS: case CHIP_KAVERI: amd_pp->ip_funcs = &kv_dpm_ip_funcs; + amd_pp->pp_funcs = &kv_dpm_funcs; break; #endif default: @@ -128,7 +139,7 @@ static int amdgpu_pp_late_init(void *handle) if (adev->pp_enabled && adev->pm.dpm_enabled) { amdgpu_pm_sysfs_init(adev); - amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_COMPLETE_INIT, NULL, NULL); + amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_COMPLETE_INIT, NULL, NULL); } return ret; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c index 5b3f928..90af8e8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c @@ -57,6 +57,40 @@ void amdgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr) ttm_bo_kunmap(&bo->dma_buf_vmap); } +int amdgpu_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) +{ + struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); + unsigned asize = amdgpu_bo_size(bo); + int ret; + + if (!vma->vm_file) + return -ENODEV; + + if (adev == NULL) + return -ENODEV; + + /* Check for valid size. */ + if (asize < vma->vm_end - vma->vm_start) + return -EINVAL; + + if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) || + (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)) { + return -EPERM; + } + vma->vm_pgoff += amdgpu_bo_mmap_offset(bo) >> PAGE_SHIFT; + + /* prime mmap does not need to check access, so allow here */ + ret = drm_vma_node_allow(&obj->vma_node, vma->vm_file->private_data); + if (ret) + return ret; + + ret = ttm_bo_mmap(vma->vm_file, vma, &adev->mman.bdev); + drm_vma_node_revoke(&obj->vma_node, vma->vm_file->private_data); + + return ret; +} + struct drm_gem_object * amdgpu_gem_prime_import_sg_table(struct drm_device *dev, struct dma_buf_attachment *attach, @@ -136,7 +170,8 @@ struct dma_buf *amdgpu_gem_prime_export(struct drm_device *dev, { struct amdgpu_bo *bo = gem_to_amdgpu_bo(gobj); - if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm)) + if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) || + bo->flags & AMDGPU_GEM_CREATE_VM_ALWAYS_VALID) return ERR_PTR(-EPERM); return drm_gem_prime_export(dev, gobj, flags); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 8c2204c..447d446 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -57,21 +57,23 @@ static int psp_sw_init(void *handle) psp->prep_cmd_buf = psp_v3_1_prep_cmd_buf; psp->ring_init = psp_v3_1_ring_init; psp->ring_create = psp_v3_1_ring_create; + psp->ring_stop = psp_v3_1_ring_stop; psp->ring_destroy = psp_v3_1_ring_destroy; psp->cmd_submit = psp_v3_1_cmd_submit; psp->compare_sram_data = psp_v3_1_compare_sram_data; psp->smu_reload_quirk = psp_v3_1_smu_reload_quirk; + psp->mode1_reset = psp_v3_1_mode1_reset; break; case CHIP_RAVEN: -#if 0 psp->init_microcode = psp_v10_0_init_microcode; -#endif psp->prep_cmd_buf = psp_v10_0_prep_cmd_buf; psp->ring_init = psp_v10_0_ring_init; psp->ring_create = psp_v10_0_ring_create; + psp->ring_stop = psp_v10_0_ring_stop; psp->ring_destroy = psp_v10_0_ring_destroy; psp->cmd_submit = psp_v10_0_cmd_submit; psp->compare_sram_data = psp_v10_0_compare_sram_data; + psp->mode1_reset = psp_v10_0_mode1_reset; break; default: return -EINVAL; @@ -90,6 +92,12 @@ static int psp_sw_init(void *handle) static int psp_sw_fini(void *handle) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + release_firmware(adev->psp.sos_fw); + adev->psp.sos_fw = NULL; + release_firmware(adev->psp.asd_fw); + adev->psp.asd_fw = NULL; return 0; } @@ -253,15 +261,18 @@ static int psp_asd_load(struct psp_context *psp) static int psp_hw_start(struct psp_context *psp) { + struct amdgpu_device *adev = psp->adev; int ret; - ret = psp_bootloader_load_sysdrv(psp); - if (ret) - return ret; + if (!amdgpu_sriov_vf(adev) || !adev->in_sriov_reset) { + ret = psp_bootloader_load_sysdrv(psp); + if (ret) + return ret; - ret = psp_bootloader_load_sos(psp); - if (ret) - return ret; + ret = psp_bootloader_load_sos(psp); + if (ret) + return ret; + } ret = psp_ring_create(psp, PSP_RING_TYPE__KM); if (ret) @@ -453,6 +464,16 @@ static int psp_hw_fini(void *handle) static int psp_suspend(void *handle) { + int ret; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct psp_context *psp = &adev->psp; + + ret = psp_ring_stop(psp, PSP_RING_TYPE__KM); + if (ret) { + DRM_ERROR("PSP ring stop failed\n"); + return ret; + } + return 0; } @@ -487,6 +508,22 @@ failed: return ret; } +static bool psp_check_reset(void* handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->flags & AMD_IS_APU) + return true; + + return false; +} + +static int psp_reset(void* handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + return psp_mode1_reset(&adev->psp); +} + static bool psp_check_fw_loading_status(struct amdgpu_device *adev, enum AMDGPU_UCODE_ID ucode_type) { @@ -530,8 +567,9 @@ const struct amd_ip_funcs psp_ip_funcs = { .suspend = psp_suspend, .resume = psp_resume, .is_idle = NULL, + .check_soft_reset = psp_check_reset, .wait_for_idle = NULL, - .soft_reset = NULL, + .soft_reset = psp_reset, .set_clockgating_state = psp_set_clockgating_state, .set_powergating_state = psp_set_powergating_state, }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h index 538fa9d..ce465455 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h @@ -66,6 +66,8 @@ struct psp_context struct psp_gfx_cmd_resp *cmd); int (*ring_init)(struct psp_context *psp, enum psp_ring_type ring_type); int (*ring_create)(struct psp_context *psp, enum psp_ring_type ring_type); + int (*ring_stop)(struct psp_context *psp, + enum psp_ring_type ring_type); int (*ring_destroy)(struct psp_context *psp, enum psp_ring_type ring_type); int (*cmd_submit)(struct psp_context *psp, struct amdgpu_firmware_info *ucode, @@ -74,6 +76,7 @@ struct psp_context struct amdgpu_firmware_info *ucode, enum AMDGPU_UCODE_ID ucode_type); bool (*smu_reload_quirk)(struct psp_context *psp); + int (*mode1_reset)(struct psp_context *psp); /* fence buffer */ struct amdgpu_bo *fw_pri_bo; @@ -123,6 +126,7 @@ struct amdgpu_psp_funcs { #define psp_prep_cmd_buf(ucode, type) (psp)->prep_cmd_buf((ucode), (type)) #define psp_ring_init(psp, type) (psp)->ring_init((psp), (type)) #define psp_ring_create(psp, type) (psp)->ring_create((psp), (type)) +#define psp_ring_stop(psp, type) (psp)->ring_stop((psp), (type)) #define psp_ring_destroy(psp, type) ((psp)->ring_destroy((psp), (type))) #define psp_cmd_submit(psp, ucode, cmd_mc, fence_mc, index) \ (psp)->cmd_submit((psp), (ucode), (cmd_mc), (fence_mc), (index)) @@ -136,6 +140,8 @@ struct amdgpu_psp_funcs { ((psp)->bootloader_load_sos ? (psp)->bootloader_load_sos((psp)) : 0) #define psp_smu_reload_quirk(psp) \ ((psp)->smu_reload_quirk ? (psp)->smu_reload_quirk((psp)) : false) +#define psp_mode1_reset(psp) \ + ((psp)->mode1_reset ? (psp)->mode1_reset((psp)) : false) extern const struct amd_ip_funcs psp_ip_funcs; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h index 1c88bd5..213988f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h @@ -14,62 +14,6 @@ #define AMDGPU_JOB_GET_TIMELINE_NAME(job) \ job->base.s_fence->finished.ops->get_timeline_name(&job->base.s_fence->finished) -TRACE_EVENT(amdgpu_ttm_tt_populate, - TP_PROTO(struct amdgpu_device *adev, uint64_t dma_address, uint64_t phys_address), - TP_ARGS(adev, dma_address, phys_address), - TP_STRUCT__entry( - __field(uint16_t, domain) - __field(uint8_t, bus) - __field(uint8_t, slot) - __field(uint8_t, func) - __field(uint64_t, dma) - __field(uint64_t, phys) - ), - TP_fast_assign( - __entry->domain = pci_domain_nr(adev->pdev->bus); - __entry->bus = adev->pdev->bus->number; - __entry->slot = PCI_SLOT(adev->pdev->devfn); - __entry->func = PCI_FUNC(adev->pdev->devfn); - __entry->dma = dma_address; - __entry->phys = phys_address; - ), - TP_printk("%04x:%02x:%02x.%x: 0x%llx => 0x%llx", - (unsigned)__entry->domain, - (unsigned)__entry->bus, - (unsigned)__entry->slot, - (unsigned)__entry->func, - (unsigned long long)__entry->dma, - (unsigned long long)__entry->phys) -); - -TRACE_EVENT(amdgpu_ttm_tt_unpopulate, - TP_PROTO(struct amdgpu_device *adev, uint64_t dma_address, uint64_t phys_address), - TP_ARGS(adev, dma_address, phys_address), - TP_STRUCT__entry( - __field(uint16_t, domain) - __field(uint8_t, bus) - __field(uint8_t, slot) - __field(uint8_t, func) - __field(uint64_t, dma) - __field(uint64_t, phys) - ), - TP_fast_assign( - __entry->domain = pci_domain_nr(adev->pdev->bus); - __entry->bus = adev->pdev->bus->number; - __entry->slot = PCI_SLOT(adev->pdev->devfn); - __entry->func = PCI_FUNC(adev->pdev->devfn); - __entry->dma = dma_address; - __entry->phys = phys_address; - ), - TP_printk("%04x:%02x:%02x.%x: 0x%llx => 0x%llx", - (unsigned)__entry->domain, - (unsigned)__entry->bus, - (unsigned)__entry->slot, - (unsigned)__entry->func, - (unsigned long long)__entry->dma, - (unsigned long long)__entry->phys) -); - TRACE_EVENT(amdgpu_mm_rreg, TP_PROTO(unsigned did, uint32_t reg, uint32_t value), TP_ARGS(did, reg, value), @@ -473,5 +417,5 @@ TRACE_EVENT(amdgpu_ttm_bo_move, /* This part must be outside protection */ #undef TRACE_INCLUDE_PATH -#define TRACE_INCLUDE_PATH . +#define TRACE_INCLUDE_PATH ../../drivers/gpu/drm/amd/amdgpu #include <trace/define_trace.h> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace_points.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace_points.c index 385b7e1..9ec96b9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace_points.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace_points.c @@ -1,4 +1,23 @@ /* Copyright Red Hat Inc 2010. + * + * 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. + * * Author : Dave Airlie <airlied@redhat.com> */ #include <drm/drmP.h> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 7ef6c28..15a2857 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -42,6 +42,7 @@ #include <linux/swap.h> #include <linux/pagemap.h> #include <linux/debugfs.h> +#include <linux/iommu.h> #include "amdgpu.h" #include "amdgpu_trace.h" #include "bif/bif_4_1_d.h" @@ -608,6 +609,7 @@ struct amdgpu_ttm_tt { spinlock_t guptasklock; struct list_head guptasks; atomic_t mmu_invalidations; + uint32_t last_set_pages; struct list_head list; }; @@ -621,6 +623,8 @@ int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages) if (!(gtt->userflags & AMDGPU_GEM_USERPTR_READONLY)) flags |= FOLL_WRITE; + down_read(¤t->mm->mmap_sem); + if (gtt->userflags & AMDGPU_GEM_USERPTR_ANONONLY) { /* check that we only use anonymous memory to prevent problems with writeback */ @@ -628,8 +632,10 @@ int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages) struct vm_area_struct *vma; vma = find_vma(gtt->usermm, gtt->userptr); - if (!vma || vma->vm_file || vma->vm_end < end) + if (!vma || vma->vm_file || vma->vm_end < end) { + up_read(¤t->mm->mmap_sem); return -EPERM; + } } do { @@ -656,42 +662,44 @@ int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages) } while (pinned < ttm->num_pages); + up_read(¤t->mm->mmap_sem); return 0; release_pages: release_pages(pages, pinned, 0); + up_read(¤t->mm->mmap_sem); return r; } -static void amdgpu_trace_dma_map(struct ttm_tt *ttm) +void amdgpu_ttm_tt_set_user_pages(struct ttm_tt *ttm, struct page **pages) { - struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev); struct amdgpu_ttm_tt *gtt = (void *)ttm; unsigned i; - if (unlikely(trace_amdgpu_ttm_tt_populate_enabled())) { - for (i = 0; i < ttm->num_pages; i++) { - trace_amdgpu_ttm_tt_populate( - adev, - gtt->ttm.dma_address[i], - page_to_phys(ttm->pages[i])); - } + gtt->last_set_pages = atomic_read(>t->mmu_invalidations); + for (i = 0; i < ttm->num_pages; ++i) { + if (ttm->pages[i]) + put_page(ttm->pages[i]); + + ttm->pages[i] = pages ? pages[i] : NULL; } } -static void amdgpu_trace_dma_unmap(struct ttm_tt *ttm) +void amdgpu_ttm_tt_mark_user_pages(struct ttm_tt *ttm) { - struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev); struct amdgpu_ttm_tt *gtt = (void *)ttm; unsigned i; - if (unlikely(trace_amdgpu_ttm_tt_unpopulate_enabled())) { - for (i = 0; i < ttm->num_pages; i++) { - trace_amdgpu_ttm_tt_unpopulate( - adev, - gtt->ttm.dma_address[i], - page_to_phys(ttm->pages[i])); - } + for (i = 0; i < ttm->num_pages; ++i) { + struct page *page = ttm->pages[i]; + + if (!page) + continue; + + if (!(gtt->userflags & AMDGPU_GEM_USERPTR_READONLY)) + set_page_dirty(page); + + mark_page_accessed(page); } } @@ -721,8 +729,6 @@ static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm) drm_prime_sg_to_page_addr_arrays(ttm->sg, ttm->pages, gtt->ttm.dma_address, ttm->num_pages); - amdgpu_trace_dma_map(ttm); - return 0; release_sg: @@ -734,7 +740,6 @@ static void amdgpu_ttm_tt_unpin_userptr(struct ttm_tt *ttm) { struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev); struct amdgpu_ttm_tt *gtt = (void *)ttm; - struct sg_page_iter sg_iter; int write = !(gtt->userflags & AMDGPU_GEM_USERPTR_READONLY); enum dma_data_direction direction = write ? @@ -747,16 +752,7 @@ static void amdgpu_ttm_tt_unpin_userptr(struct ttm_tt *ttm) /* free the sg table and pages again */ dma_unmap_sg(adev->dev, ttm->sg->sgl, ttm->sg->nents, direction); - for_each_sg_page(ttm->sg->sgl, &sg_iter, ttm->sg->nents, 0) { - struct page *page = sg_page_iter_page(&sg_iter); - if (!(gtt->userflags & AMDGPU_GEM_USERPTR_READONLY)) - set_page_dirty(page); - - mark_page_accessed(page); - put_page(page); - } - - amdgpu_trace_dma_unmap(ttm); + amdgpu_ttm_tt_mark_user_pages(ttm); sg_free_table(ttm->sg); } @@ -818,7 +814,6 @@ int amdgpu_ttm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *bo_mem) struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); struct ttm_tt *ttm = bo->ttm; struct ttm_mem_reg tmp; - struct ttm_placement placement; struct ttm_place placements; int r; @@ -834,7 +829,7 @@ int amdgpu_ttm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *bo_mem) placement.busy_placement = &placements; placements.fpfn = 0; placements.lpfn = adev->mc.gart_size >> PAGE_SHIFT; - placements.flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_TT; + placements.flags = bo->mem.placement | TTM_PL_FLAG_TT; r = ttm_bo_mem_space(bo, &placement, &tmp, true, false); if (unlikely(r)) @@ -941,8 +936,6 @@ static int amdgpu_ttm_tt_populate(struct ttm_tt *ttm) { struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev); struct amdgpu_ttm_tt *gtt = (void *)ttm; - unsigned i; - int r; bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); if (ttm->state != tt_unpopulated) @@ -962,52 +955,26 @@ static int amdgpu_ttm_tt_populate(struct ttm_tt *ttm) drm_prime_sg_to_page_addr_arrays(ttm->sg, ttm->pages, gtt->ttm.dma_address, ttm->num_pages); ttm->state = tt_unbound; - r = 0; - goto trace_mappings; + return 0; } #ifdef CONFIG_SWIOTLB if (swiotlb_nr_tbl()) { - r = ttm_dma_populate(>t->ttm, adev->dev); - goto trace_mappings; + return ttm_dma_populate(>t->ttm, adev->dev); } #endif - r = ttm_pool_populate(ttm); - if (r) { - return r; - } - - for (i = 0; i < ttm->num_pages; i++) { - gtt->ttm.dma_address[i] = pci_map_page(adev->pdev, ttm->pages[i], - 0, PAGE_SIZE, - PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(adev->pdev, gtt->ttm.dma_address[i])) { - while (i--) { - pci_unmap_page(adev->pdev, gtt->ttm.dma_address[i], - PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - gtt->ttm.dma_address[i] = 0; - } - ttm_pool_unpopulate(ttm); - return -EFAULT; - } - } - - r = 0; -trace_mappings: - if (likely(!r)) - amdgpu_trace_dma_map(ttm); - return r; + return ttm_populate_and_map_pages(adev->dev, >t->ttm); } static void amdgpu_ttm_tt_unpopulate(struct ttm_tt *ttm) { struct amdgpu_device *adev; struct amdgpu_ttm_tt *gtt = (void *)ttm; - unsigned i; bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); if (gtt && gtt->userptr) { + amdgpu_ttm_tt_set_user_pages(ttm, NULL); kfree(ttm->sg); ttm->page_flags &= ~TTM_PAGE_FLAG_SG; return; @@ -1018,8 +985,6 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_tt *ttm) adev = amdgpu_ttm_adev(ttm->bdev); - amdgpu_trace_dma_unmap(ttm); - #ifdef CONFIG_SWIOTLB if (swiotlb_nr_tbl()) { ttm_dma_unpopulate(>t->ttm, adev->dev); @@ -1027,14 +992,7 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_tt *ttm) } #endif - for (i = 0; i < ttm->num_pages; i++) { - if (gtt->ttm.dma_address[i]) { - pci_unmap_page(adev->pdev, gtt->ttm.dma_address[i], - PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - } - } - - ttm_pool_unpopulate(ttm); + ttm_unmap_and_unpopulate_pages(adev->dev, >t->ttm); } int amdgpu_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr, @@ -1051,6 +1009,7 @@ int amdgpu_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr, spin_lock_init(>t->guptasklock); INIT_LIST_HEAD(>t->guptasks); atomic_set(>t->mmu_invalidations, 0); + gtt->last_set_pages = 0; return 0; } @@ -1103,6 +1062,16 @@ bool amdgpu_ttm_tt_userptr_invalidated(struct ttm_tt *ttm, return prev_invalidated != *last_invalidated; } +bool amdgpu_ttm_tt_userptr_needs_pages(struct ttm_tt *ttm) +{ + struct amdgpu_ttm_tt *gtt = (void *)ttm; + + if (gtt == NULL || !gtt->userptr) + return false; + + return atomic_read(>t->mmu_invalidations) != gtt->last_set_pages; +} + bool amdgpu_ttm_tt_is_readonly(struct ttm_tt *ttm) { struct amdgpu_ttm_tt *gtt = (void *)ttm; @@ -1202,14 +1171,14 @@ static int amdgpu_ttm_access_memory(struct ttm_buffer_object *bo, } spin_lock_irqsave(&adev->mmio_idx_lock, flags); - WREG32(mmMM_INDEX, ((uint32_t)aligned_pos) | 0x80000000); - WREG32(mmMM_INDEX_HI, aligned_pos >> 31); + WREG32_NO_KIQ(mmMM_INDEX, ((uint32_t)aligned_pos) | 0x80000000); + WREG32_NO_KIQ(mmMM_INDEX_HI, aligned_pos >> 31); if (!write || mask != 0xffffffff) - value = RREG32(mmMM_DATA); + value = RREG32_NO_KIQ(mmMM_DATA); if (write) { value &= ~mask; value |= (*(uint32_t *)buf << shift) & mask; - WREG32(mmMM_DATA, value); + WREG32_NO_KIQ(mmMM_DATA, value); } spin_unlock_irqrestore(&adev->mmio_idx_lock, flags); if (!write) { @@ -1557,8 +1526,8 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo, struct dma_fence **fence) { struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); - /* max_bytes applies to SDMA_OP_PTEPDE as well as SDMA_OP_CONST_FILL*/ - uint32_t max_bytes = adev->mman.buffer_funcs->fill_max_bytes; + uint32_t max_bytes = 8 * + adev->vm_manager.vm_pte_funcs->set_max_nums_pte_pde; struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring; struct drm_mm_node *mm_node; @@ -1590,8 +1559,8 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo, ++mm_node; } - /* 10 double words for each SDMA_OP_PTEPDE cmd */ - num_dw = num_loops * 10; + /* num of dwords for each SDMA_OP_PTEPDE cmd */ + num_dw = num_loops * adev->vm_manager.vm_pte_funcs->set_pte_pde_num_dw; /* for IB padding */ num_dw += 64; @@ -1697,9 +1666,9 @@ static ssize_t amdgpu_ttm_vram_read(struct file *f, char __user *buf, return result; spin_lock_irqsave(&adev->mmio_idx_lock, flags); - WREG32(mmMM_INDEX, ((uint32_t)*pos) | 0x80000000); - WREG32(mmMM_INDEX_HI, *pos >> 31); - value = RREG32(mmMM_DATA); + WREG32_NO_KIQ(mmMM_INDEX, ((uint32_t)*pos) | 0x80000000); + WREG32_NO_KIQ(mmMM_INDEX_HI, *pos >> 31); + value = RREG32_NO_KIQ(mmMM_DATA); spin_unlock_irqrestore(&adev->mmio_idx_lock, flags); r = put_user(value, (uint32_t *)buf); @@ -1715,10 +1684,50 @@ static ssize_t amdgpu_ttm_vram_read(struct file *f, char __user *buf, return result; } +static ssize_t amdgpu_ttm_vram_write(struct file *f, const char __user *buf, + size_t size, loff_t *pos) +{ + struct amdgpu_device *adev = file_inode(f)->i_private; + ssize_t result = 0; + int r; + + if (size & 0x3 || *pos & 0x3) + return -EINVAL; + + if (*pos >= adev->mc.mc_vram_size) + return -ENXIO; + + while (size) { + unsigned long flags; + uint32_t value; + + if (*pos >= adev->mc.mc_vram_size) + return result; + + r = get_user(value, (uint32_t *)buf); + if (r) + return r; + + spin_lock_irqsave(&adev->mmio_idx_lock, flags); + WREG32_NO_KIQ(mmMM_INDEX, ((uint32_t)*pos) | 0x80000000); + WREG32_NO_KIQ(mmMM_INDEX_HI, *pos >> 31); + WREG32_NO_KIQ(mmMM_DATA, value); + spin_unlock_irqrestore(&adev->mmio_idx_lock, flags); + + result += 4; + buf += 4; + *pos += 4; + size -= 4; + } + + return result; +} + static const struct file_operations amdgpu_ttm_vram_fops = { .owner = THIS_MODULE, .read = amdgpu_ttm_vram_read, - .llseek = default_llseek + .write = amdgpu_ttm_vram_write, + .llseek = default_llseek, }; #ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS @@ -1770,6 +1779,53 @@ static const struct file_operations amdgpu_ttm_gtt_fops = { #endif +static ssize_t amdgpu_iova_to_phys_read(struct file *f, char __user *buf, + size_t size, loff_t *pos) +{ + struct amdgpu_device *adev = file_inode(f)->i_private; + int r; + uint64_t phys; + struct iommu_domain *dom; + + // always return 8 bytes + if (size != 8) + return -EINVAL; + + // only accept page addresses + if (*pos & 0xFFF) + return -EINVAL; + + dom = iommu_get_domain_for_dev(adev->dev); + if (dom) + phys = iommu_iova_to_phys(dom, *pos); + else + phys = *pos; + + r = copy_to_user(buf, &phys, 8); + if (r) + return -EFAULT; + + return 8; +} + +static const struct file_operations amdgpu_ttm_iova_fops = { + .owner = THIS_MODULE, + .read = amdgpu_iova_to_phys_read, + .llseek = default_llseek +}; + +static const struct { + char *name; + const struct file_operations *fops; + int domain; +} ttm_debugfs_entries[] = { + { "amdgpu_vram", &amdgpu_ttm_vram_fops, TTM_PL_VRAM }, +#ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS + { "amdgpu_gtt", &amdgpu_ttm_gtt_fops, TTM_PL_TT }, +#endif + { "amdgpu_iova", &amdgpu_ttm_iova_fops, TTM_PL_SYSTEM }, +}; + #endif static int amdgpu_ttm_debugfs_init(struct amdgpu_device *adev) @@ -1780,22 +1836,21 @@ static int amdgpu_ttm_debugfs_init(struct amdgpu_device *adev) struct drm_minor *minor = adev->ddev->primary; struct dentry *ent, *root = minor->debugfs_root; - ent = debugfs_create_file("amdgpu_vram", S_IFREG | S_IRUGO, root, - adev, &amdgpu_ttm_vram_fops); - if (IS_ERR(ent)) - return PTR_ERR(ent); - i_size_write(ent->d_inode, adev->mc.mc_vram_size); - adev->mman.vram = ent; - -#ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS - ent = debugfs_create_file("amdgpu_gtt", S_IFREG | S_IRUGO, root, - adev, &amdgpu_ttm_gtt_fops); - if (IS_ERR(ent)) - return PTR_ERR(ent); - i_size_write(ent->d_inode, adev->mc.gart_size); - adev->mman.gtt = ent; + for (count = 0; count < ARRAY_SIZE(ttm_debugfs_entries); count++) { + ent = debugfs_create_file( + ttm_debugfs_entries[count].name, + S_IFREG | S_IRUGO, root, + adev, + ttm_debugfs_entries[count].fops); + if (IS_ERR(ent)) + return PTR_ERR(ent); + if (ttm_debugfs_entries[count].domain == TTM_PL_VRAM) + i_size_write(ent->d_inode, adev->mc.mc_vram_size); + else if (ttm_debugfs_entries[count].domain == TTM_PL_TT) + i_size_write(ent->d_inode, adev->mc.gart_size); + adev->mman.debugfs_entries[count] = ent; + } -#endif count = ARRAY_SIZE(amdgpu_ttm_debugfs_list); #ifdef CONFIG_SWIOTLB @@ -1805,7 +1860,6 @@ static int amdgpu_ttm_debugfs_init(struct amdgpu_device *adev) return amdgpu_debugfs_add_files(adev, amdgpu_ttm_debugfs_list, count); #else - return 0; #endif } @@ -1813,14 +1867,9 @@ static int amdgpu_ttm_debugfs_init(struct amdgpu_device *adev) static void amdgpu_ttm_debugfs_fini(struct amdgpu_device *adev) { #if defined(CONFIG_DEBUG_FS) + unsigned i; - debugfs_remove(adev->mman.vram); - adev->mman.vram = NULL; - -#ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS - debugfs_remove(adev->mman.gtt); - adev->mman.gtt = NULL; -#endif - + for (i = 0; i < ARRAY_SIZE(ttm_debugfs_entries); i++) + debugfs_remove(adev->mman.debugfs_entries[i]); #endif } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index 43093bf..7abae68 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -24,6 +24,7 @@ #ifndef __AMDGPU_TTM_H__ #define __AMDGPU_TTM_H__ +#include "amdgpu.h" #include "gpu_scheduler.h" #define AMDGPU_PL_GDS (TTM_PL_PRIV + 0) @@ -45,8 +46,7 @@ struct amdgpu_mman { bool initialized; #if defined(CONFIG_DEBUG_FS) - struct dentry *vram; - struct dentry *gtt; + struct dentry *debugfs_entries[8]; #endif /* buffer handling */ @@ -82,4 +82,20 @@ bool amdgpu_ttm_is_bound(struct ttm_tt *ttm); int amdgpu_ttm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *bo_mem); int amdgpu_ttm_recover_gart(struct amdgpu_device *adev); +int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages); +void amdgpu_ttm_tt_set_user_pages(struct ttm_tt *ttm, struct page **pages); +void amdgpu_ttm_tt_mark_user_pages(struct ttm_tt *ttm); +int amdgpu_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr, + uint32_t flags); +bool amdgpu_ttm_tt_has_userptr(struct ttm_tt *ttm); +struct mm_struct *amdgpu_ttm_tt_get_usermm(struct ttm_tt *ttm); +bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start, + unsigned long end); +bool amdgpu_ttm_tt_userptr_invalidated(struct ttm_tt *ttm, + int *last_invalidated); +bool amdgpu_ttm_tt_userptr_needs_pages(struct ttm_tt *ttm); +bool amdgpu_ttm_tt_is_readonly(struct ttm_tt *ttm); +uint64_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm, + struct ttm_mem_reg *mem); + #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c index 36c7633..6564902 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c @@ -270,12 +270,8 @@ amdgpu_ucode_get_load_type(struct amdgpu_device *adev, int load_type) else return AMDGPU_FW_LOAD_SMU; case CHIP_VEGA10: - if (!load_type) - return AMDGPU_FW_LOAD_DIRECT; - else - return AMDGPU_FW_LOAD_PSP; case CHIP_RAVEN: - if (load_type != 2) + if (!load_type) return AMDGPU_FW_LOAD_DIRECT; else return AMDGPU_FW_LOAD_PSP; @@ -364,8 +360,6 @@ static int amdgpu_ucode_patch_jt(struct amdgpu_firmware_info *ucode, int amdgpu_ucode_init_bo(struct amdgpu_device *adev) { struct amdgpu_bo **bo = &adev->firmware.fw_buf; - uint64_t fw_mc_addr; - void *fw_buf_ptr = NULL; uint64_t fw_offset = 0; int i, err; struct amdgpu_firmware_info *ucode = NULL; @@ -376,37 +370,39 @@ int amdgpu_ucode_init_bo(struct amdgpu_device *adev) return 0; } - err = amdgpu_bo_create(adev, adev->firmware.fw_size, PAGE_SIZE, true, - amdgpu_sriov_vf(adev) ? AMDGPU_GEM_DOMAIN_VRAM : AMDGPU_GEM_DOMAIN_GTT, - AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS, - NULL, NULL, 0, bo); - if (err) { - dev_err(adev->dev, "(%d) Firmware buffer allocate failed\n", err); - goto failed; - } + if (!amdgpu_sriov_vf(adev) || !adev->in_sriov_reset) { + err = amdgpu_bo_create(adev, adev->firmware.fw_size, PAGE_SIZE, true, + amdgpu_sriov_vf(adev) ? AMDGPU_GEM_DOMAIN_VRAM : AMDGPU_GEM_DOMAIN_GTT, + AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS, + NULL, NULL, 0, bo); + if (err) { + dev_err(adev->dev, "(%d) Firmware buffer allocate failed\n", err); + goto failed; + } - err = amdgpu_bo_reserve(*bo, false); - if (err) { - dev_err(adev->dev, "(%d) Firmware buffer reserve failed\n", err); - goto failed_reserve; - } + err = amdgpu_bo_reserve(*bo, false); + if (err) { + dev_err(adev->dev, "(%d) Firmware buffer reserve failed\n", err); + goto failed_reserve; + } - err = amdgpu_bo_pin(*bo, amdgpu_sriov_vf(adev) ? AMDGPU_GEM_DOMAIN_VRAM : AMDGPU_GEM_DOMAIN_GTT, - &fw_mc_addr); - if (err) { - dev_err(adev->dev, "(%d) Firmware buffer pin failed\n", err); - goto failed_pin; - } + err = amdgpu_bo_pin(*bo, amdgpu_sriov_vf(adev) ? AMDGPU_GEM_DOMAIN_VRAM : AMDGPU_GEM_DOMAIN_GTT, + &adev->firmware.fw_buf_mc); + if (err) { + dev_err(adev->dev, "(%d) Firmware buffer pin failed\n", err); + goto failed_pin; + } - err = amdgpu_bo_kmap(*bo, &fw_buf_ptr); - if (err) { - dev_err(adev->dev, "(%d) Firmware buffer kmap failed\n", err); - goto failed_kmap; - } + err = amdgpu_bo_kmap(*bo, &adev->firmware.fw_buf_ptr); + if (err) { + dev_err(adev->dev, "(%d) Firmware buffer kmap failed\n", err); + goto failed_kmap; + } - amdgpu_bo_unreserve(*bo); + amdgpu_bo_unreserve(*bo); + } - memset(fw_buf_ptr, 0, adev->firmware.fw_size); + memset(adev->firmware.fw_buf_ptr, 0, adev->firmware.fw_size); /* * if SMU loaded firmware, it needn't add SMC, UVD, and VCE @@ -425,14 +421,14 @@ int amdgpu_ucode_init_bo(struct amdgpu_device *adev) ucode = &adev->firmware.ucode[i]; if (ucode->fw) { header = (const struct common_firmware_header *)ucode->fw->data; - amdgpu_ucode_init_single_fw(adev, ucode, fw_mc_addr + fw_offset, - (void *)((uint8_t *)fw_buf_ptr + fw_offset)); + amdgpu_ucode_init_single_fw(adev, ucode, adev->firmware.fw_buf_mc + fw_offset, + adev->firmware.fw_buf_ptr + fw_offset); if (i == AMDGPU_UCODE_ID_CP_MEC1 && adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) { const struct gfx_firmware_header_v1_0 *cp_hdr; cp_hdr = (const struct gfx_firmware_header_v1_0 *)ucode->fw->data; - amdgpu_ucode_patch_jt(ucode, fw_mc_addr + fw_offset, - fw_buf_ptr + fw_offset); + amdgpu_ucode_patch_jt(ucode, adev->firmware.fw_buf_mc + fw_offset, + adev->firmware.fw_buf_ptr + fw_offset); fw_offset += ALIGN(le32_to_cpu(cp_hdr->jt_size) << 2, PAGE_SIZE); } fw_offset += ALIGN(ucode->ucode_size, PAGE_SIZE); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c index e19928d..e8bd50c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c @@ -269,6 +269,7 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev) int amdgpu_uvd_sw_fini(struct amdgpu_device *adev) { + int i; kfree(adev->uvd.saved_bo); amd_sched_entity_fini(&adev->uvd.ring.sched, &adev->uvd.entity); @@ -279,6 +280,9 @@ int amdgpu_uvd_sw_fini(struct amdgpu_device *adev) amdgpu_ring_fini(&adev->uvd.ring); + for (i = 0; i < AMDGPU_MAX_UVD_ENC_RINGS; ++i) + amdgpu_ring_fini(&adev->uvd.ring_enc[i]); + release_firmware(adev->uvd.fw); return 0; @@ -410,10 +414,10 @@ static int amdgpu_uvd_cs_pass1(struct amdgpu_uvd_cs_ctx *ctx) uint64_t addr = amdgpu_uvd_get_addr_from_ctx(ctx); int r = 0; - mapping = amdgpu_cs_find_mapping(ctx->parser, addr, &bo); - if (mapping == NULL) { + r = amdgpu_cs_find_mapping(ctx->parser, addr, &bo, &mapping); + if (r) { DRM_ERROR("Can't find BO for addr 0x%08Lx\n", addr); - return -EINVAL; + return r; } if (!ctx->parser->adev->uvd.address_64_bit) { @@ -737,10 +741,10 @@ static int amdgpu_uvd_cs_pass2(struct amdgpu_uvd_cs_ctx *ctx) uint64_t addr = amdgpu_uvd_get_addr_from_ctx(ctx); int r; - mapping = amdgpu_cs_find_mapping(ctx->parser, addr, &bo); - if (mapping == NULL) { + r = amdgpu_cs_find_mapping(ctx->parser, addr, &bo, &mapping); + if (r) { DRM_ERROR("Can't find BO for addr 0x%08Lx\n", addr); - return -EINVAL; + return r; } start = amdgpu_bo_gpu_offset(bo); @@ -917,10 +921,6 @@ int amdgpu_uvd_ring_parse_cs(struct amdgpu_cs_parser *parser, uint32_t ib_idx) return -EINVAL; } - r = amdgpu_cs_sysvm_access_required(parser); - if (r) - return r; - ctx.parser = parser; ctx.buf_sizes = buf_sizes; ctx.ib_idx = ib_idx; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c index c855366..b46280c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c @@ -559,6 +559,7 @@ static int amdgpu_vce_cs_reloc(struct amdgpu_cs_parser *p, uint32_t ib_idx, struct amdgpu_bo_va_mapping *mapping; struct amdgpu_bo *bo; uint64_t addr; + int r; if (index == 0xffffffff) index = 0; @@ -567,11 +568,11 @@ static int amdgpu_vce_cs_reloc(struct amdgpu_cs_parser *p, uint32_t ib_idx, ((uint64_t)amdgpu_get_ib_value(p, ib_idx, hi)) << 32; addr += ((uint64_t)size) * ((uint64_t)index); - mapping = amdgpu_cs_find_mapping(p, addr, &bo); - if (mapping == NULL) { + r = amdgpu_cs_find_mapping(p, addr, &bo, &mapping); + if (r) { DRM_ERROR("Can't find BO for addr 0x%010Lx %d %d %d %d\n", addr, lo, hi, size, index); - return -EINVAL; + return r; } if ((addr + (uint64_t)size) > @@ -652,10 +653,6 @@ int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx) p->job->vm = NULL; ib->gpu_addr = amdgpu_sa_bo_gpu_addr(ib->sa_bo); - r = amdgpu_cs_sysvm_access_required(p); - if (r) - return r; - while (idx < ib->length_dw) { uint32_t len = amdgpu_get_ib_value(p, ib_idx, idx); uint32_t cmd = amdgpu_get_ib_value(p, ib_idx, idx + 1); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index bd20ff0..bbcc670 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -27,12 +27,59 @@ */ #include <linux/dma-fence-array.h> #include <linux/interval_tree_generic.h> +#include <linux/idr.h> #include <drm/drmP.h> #include <drm/amdgpu_drm.h> #include "amdgpu.h" #include "amdgpu_trace.h" /* + * PASID manager + * + * PASIDs are global address space identifiers that can be shared + * between the GPU, an IOMMU and the driver. VMs on different devices + * may use the same PASID if they share the same address + * space. Therefore PASIDs are allocated using a global IDA. VMs are + * looked up from the PASID per amdgpu_device. + */ +static DEFINE_IDA(amdgpu_vm_pasid_ida); + +/** + * amdgpu_vm_alloc_pasid - Allocate a PASID + * @bits: Maximum width of the PASID in bits, must be at least 1 + * + * Allocates a PASID of the given width while keeping smaller PASIDs + * available if possible. + * + * Returns a positive integer on success. Returns %-EINVAL if bits==0. + * Returns %-ENOSPC if no PASID was available. Returns %-ENOMEM on + * memory allocation failure. + */ +int amdgpu_vm_alloc_pasid(unsigned int bits) +{ + int pasid = -EINVAL; + + for (bits = min(bits, 31U); bits > 0; bits--) { + pasid = ida_simple_get(&amdgpu_vm_pasid_ida, + 1U << (bits - 1), 1U << bits, + GFP_KERNEL); + if (pasid != -ENOSPC) + break; + } + + return pasid; +} + +/** + * amdgpu_vm_free_pasid - Free a PASID + * @pasid: PASID to free + */ +void amdgpu_vm_free_pasid(unsigned int pasid) +{ + ida_simple_remove(&amdgpu_vm_pasid_ida, pasid); +} + +/* * GPUVM * GPUVM is similar to the legacy gart on older asics, however * rather than there being a single global gart table @@ -140,7 +187,7 @@ void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm, struct list_head *validated, struct amdgpu_bo_list_entry *entry) { - entry->robj = vm->root.bo; + entry->robj = vm->root.base.bo; entry->priority = 0; entry->tv.bo = &entry->robj->tbo; entry->tv.shared = true; @@ -149,86 +196,80 @@ void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm, } /** - * amdgpu_vm_validate_layer - validate a single page table level + * amdgpu_vm_validate_pt_bos - validate the page table BOs * - * @parent: parent page table level + * @adev: amdgpu device pointer + * @vm: vm providing the BOs * @validate: callback to do the validation * @param: parameter for the validation callback * * Validate the page table BOs on command submission if neccessary. */ -static int amdgpu_vm_validate_level(struct amdgpu_vm_pt *parent, - int (*validate)(void *, struct amdgpu_bo *), - void *param, bool use_cpu_for_update, - struct ttm_bo_global *glob) +int amdgpu_vm_validate_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm, + int (*validate)(void *p, struct amdgpu_bo *bo), + void *param) { - unsigned i; + struct ttm_bo_global *glob = adev->mman.bdev.glob; int r; - if (use_cpu_for_update) { - r = amdgpu_bo_kmap(parent->bo, NULL); - if (r) - return r; - } - - if (!parent->entries) - return 0; + spin_lock(&vm->status_lock); + while (!list_empty(&vm->evicted)) { + struct amdgpu_vm_bo_base *bo_base; + struct amdgpu_bo *bo; - for (i = 0; i <= parent->last_entry_used; ++i) { - struct amdgpu_vm_pt *entry = &parent->entries[i]; + bo_base = list_first_entry(&vm->evicted, + struct amdgpu_vm_bo_base, + vm_status); + spin_unlock(&vm->status_lock); - if (!entry->bo) - continue; + bo = bo_base->bo; + BUG_ON(!bo); + if (bo->parent) { + r = validate(param, bo); + if (r) + return r; - r = validate(param, entry->bo); - if (r) - return r; + spin_lock(&glob->lru_lock); + ttm_bo_move_to_lru_tail(&bo->tbo); + if (bo->shadow) + ttm_bo_move_to_lru_tail(&bo->shadow->tbo); + spin_unlock(&glob->lru_lock); + } - spin_lock(&glob->lru_lock); - ttm_bo_move_to_lru_tail(&entry->bo->tbo); - if (entry->bo->shadow) - ttm_bo_move_to_lru_tail(&entry->bo->shadow->tbo); - spin_unlock(&glob->lru_lock); + if (bo->tbo.type == ttm_bo_type_kernel && + vm->use_cpu_for_update) { + r = amdgpu_bo_kmap(bo, NULL); + if (r) + return r; + } - /* - * Recurse into the sub directory. This is harmless because we - * have only a maximum of 5 layers. - */ - r = amdgpu_vm_validate_level(entry, validate, param, - use_cpu_for_update, glob); - if (r) - return r; + spin_lock(&vm->status_lock); + if (bo->tbo.type != ttm_bo_type_kernel) + list_move(&bo_base->vm_status, &vm->moved); + else + list_move(&bo_base->vm_status, &vm->relocated); } + spin_unlock(&vm->status_lock); - return r; + return 0; } /** - * amdgpu_vm_validate_pt_bos - validate the page table BOs + * amdgpu_vm_ready - check VM is ready for updates * - * @adev: amdgpu device pointer - * @vm: vm providing the BOs - * @validate: callback to do the validation - * @param: parameter for the validation callback + * @vm: VM to check * - * Validate the page table BOs on command submission if neccessary. + * Check if all VM PDs/PTs are ready for updates */ -int amdgpu_vm_validate_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm, - int (*validate)(void *p, struct amdgpu_bo *bo), - void *param) +bool amdgpu_vm_ready(struct amdgpu_vm *vm) { - uint64_t num_evictions; + bool ready; - /* We only need to validate the page tables - * if they aren't already valid. - */ - num_evictions = atomic64_read(&adev->num_evictions); - if (num_evictions == vm->last_eviction_counter) - return 0; + spin_lock(&vm->status_lock); + ready = list_empty(&vm->evicted); + spin_unlock(&vm->status_lock); - return amdgpu_vm_validate_level(&vm->root, validate, param, - vm->use_cpu_for_update, - adev->mman.bdev.glob); + return ready; } /** @@ -294,11 +335,11 @@ static int amdgpu_vm_alloc_levels(struct amdgpu_device *adev, /* walk over the address space and allocate the page tables */ for (pt_idx = from; pt_idx <= to; ++pt_idx) { - struct reservation_object *resv = vm->root.bo->tbo.resv; + struct reservation_object *resv = vm->root.base.bo->tbo.resv; struct amdgpu_vm_pt *entry = &parent->entries[pt_idx]; struct amdgpu_bo *pt; - if (!entry->bo) { + if (!entry->base.bo) { r = amdgpu_bo_create(adev, amdgpu_vm_bo_size(adev, level), AMDGPU_GPU_PAGE_SIZE, true, @@ -319,9 +360,14 @@ static int amdgpu_vm_alloc_levels(struct amdgpu_device *adev, /* Keep a reference to the root directory to avoid * freeing them up in the wrong order. */ - pt->parent = amdgpu_bo_ref(vm->root.bo); - - entry->bo = pt; + pt->parent = amdgpu_bo_ref(parent->base.bo); + + entry->base.vm = vm; + entry->base.bo = pt; + list_add_tail(&entry->base.bo_list, &pt->va); + spin_lock(&vm->status_lock); + list_add(&entry->base.vm_status, &vm->relocated); + spin_unlock(&vm->status_lock); entry->addr = 0; } @@ -988,7 +1034,7 @@ static int amdgpu_vm_wait_pd(struct amdgpu_device *adev, struct amdgpu_vm *vm, int r; amdgpu_sync_create(&sync); - amdgpu_sync_resv(adev, &sync, vm->root.bo->tbo.resv, owner); + amdgpu_sync_resv(adev, &sync, vm->root.base.bo->tbo.resv, owner); r = amdgpu_sync_wait(&sync, true); amdgpu_sync_free(&sync); @@ -1007,18 +1053,17 @@ static int amdgpu_vm_wait_pd(struct amdgpu_device *adev, struct amdgpu_vm *vm, */ static int amdgpu_vm_update_level(struct amdgpu_device *adev, struct amdgpu_vm *vm, - struct amdgpu_vm_pt *parent, - unsigned level) + struct amdgpu_vm_pt *parent) { struct amdgpu_bo *shadow; struct amdgpu_ring *ring = NULL; uint64_t pd_addr, shadow_addr = 0; - uint32_t incr = amdgpu_vm_bo_size(adev, level + 1); uint64_t last_pde = ~0, last_pt = ~0, last_shadow = ~0; unsigned count = 0, pt_idx, ndw = 0; struct amdgpu_job *job; struct amdgpu_pte_update_params params; struct dma_fence *fence = NULL; + uint32_t incr; int r; @@ -1027,10 +1072,10 @@ static int amdgpu_vm_update_level(struct amdgpu_device *adev, memset(¶ms, 0, sizeof(params)); params.adev = adev; - shadow = parent->bo->shadow; + shadow = parent->base.bo->shadow; if (vm->use_cpu_for_update) { - pd_addr = (unsigned long)amdgpu_bo_kptr(parent->bo); + pd_addr = (unsigned long)amdgpu_bo_kptr(parent->base.bo); r = amdgpu_vm_wait_pd(adev, vm, AMDGPU_FENCE_OWNER_VM); if (unlikely(r)) return r; @@ -1046,7 +1091,7 @@ static int amdgpu_vm_update_level(struct amdgpu_device *adev, /* assume the worst case */ ndw += parent->last_entry_used * 6; - pd_addr = amdgpu_bo_gpu_offset(parent->bo); + pd_addr = amdgpu_bo_gpu_offset(parent->base.bo); if (shadow) { shadow_addr = amdgpu_bo_gpu_offset(shadow); @@ -1066,12 +1111,17 @@ static int amdgpu_vm_update_level(struct amdgpu_device *adev, /* walk over the address space and update the directory */ for (pt_idx = 0; pt_idx <= parent->last_entry_used; ++pt_idx) { - struct amdgpu_bo *bo = parent->entries[pt_idx].bo; + struct amdgpu_vm_pt *entry = &parent->entries[pt_idx]; + struct amdgpu_bo *bo = entry->base.bo; uint64_t pde, pt; if (bo == NULL) continue; + spin_lock(&vm->status_lock); + list_del_init(&entry->base.vm_status); + spin_unlock(&vm->status_lock); + pt = amdgpu_bo_gpu_offset(bo); pt = amdgpu_gart_get_vm_pde(adev, pt); /* Don't update huge pages here */ @@ -1082,6 +1132,7 @@ static int amdgpu_vm_update_level(struct amdgpu_device *adev, parent->entries[pt_idx].addr = pt | AMDGPU_PTE_VALID; pde = pd_addr + pt_idx * 8; + incr = amdgpu_bo_size(bo); if (((last_pde + 8 * count) != pde) || ((last_pt + incr * count) != pt) || (count == AMDGPU_VM_MAX_UPDATE_SIZE)) { @@ -1109,7 +1160,7 @@ static int amdgpu_vm_update_level(struct amdgpu_device *adev, } if (count) { - if (vm->root.bo->shadow) + if (vm->root.base.bo->shadow) params.func(¶ms, last_shadow, last_pt, count, incr, AMDGPU_PTE_VALID); @@ -1122,7 +1173,8 @@ static int amdgpu_vm_update_level(struct amdgpu_device *adev, amdgpu_job_free(job); } else { amdgpu_ring_pad_ib(ring, params.ib); - amdgpu_sync_resv(adev, &job->sync, parent->bo->tbo.resv, + amdgpu_sync_resv(adev, &job->sync, + parent->base.bo->tbo.resv, AMDGPU_FENCE_OWNER_VM); if (shadow) amdgpu_sync_resv(adev, &job->sync, @@ -1135,26 +1187,11 @@ static int amdgpu_vm_update_level(struct amdgpu_device *adev, if (r) goto error_free; - amdgpu_bo_fence(parent->bo, fence, true); - dma_fence_put(vm->last_dir_update); - vm->last_dir_update = dma_fence_get(fence); - dma_fence_put(fence); + amdgpu_bo_fence(parent->base.bo, fence, true); + dma_fence_put(vm->last_update); + vm->last_update = fence; } } - /* - * Recurse into the subdirectories. This recursion is harmless because - * we only have a maximum of 5 layers. - */ - for (pt_idx = 0; pt_idx <= parent->last_entry_used; ++pt_idx) { - struct amdgpu_vm_pt *entry = &parent->entries[pt_idx]; - - if (!entry->bo) - continue; - - r = amdgpu_vm_update_level(adev, vm, entry, level + 1); - if (r) - return r; - } return 0; @@ -1170,7 +1207,8 @@ error_free: * * Mark all PD level as invalid after an error. */ -static void amdgpu_vm_invalidate_level(struct amdgpu_vm_pt *parent) +static void amdgpu_vm_invalidate_level(struct amdgpu_vm *vm, + struct amdgpu_vm_pt *parent) { unsigned pt_idx; @@ -1181,11 +1219,15 @@ static void amdgpu_vm_invalidate_level(struct amdgpu_vm_pt *parent) for (pt_idx = 0; pt_idx <= parent->last_entry_used; ++pt_idx) { struct amdgpu_vm_pt *entry = &parent->entries[pt_idx]; - if (!entry->bo) + if (!entry->base.bo) continue; entry->addr = ~0ULL; - amdgpu_vm_invalidate_level(entry); + spin_lock(&vm->status_lock); + if (list_empty(&entry->base.vm_status)) + list_add(&entry->base.vm_status, &vm->relocated); + spin_unlock(&vm->status_lock); + amdgpu_vm_invalidate_level(vm, entry); } } @@ -1203,9 +1245,38 @@ int amdgpu_vm_update_directories(struct amdgpu_device *adev, { int r; - r = amdgpu_vm_update_level(adev, vm, &vm->root, 0); - if (r) - amdgpu_vm_invalidate_level(&vm->root); + spin_lock(&vm->status_lock); + while (!list_empty(&vm->relocated)) { + struct amdgpu_vm_bo_base *bo_base; + struct amdgpu_bo *bo; + + bo_base = list_first_entry(&vm->relocated, + struct amdgpu_vm_bo_base, + vm_status); + spin_unlock(&vm->status_lock); + + bo = bo_base->bo->parent; + if (bo) { + struct amdgpu_vm_bo_base *parent; + struct amdgpu_vm_pt *pt; + + parent = list_first_entry(&bo->va, + struct amdgpu_vm_bo_base, + bo_list); + pt = container_of(parent, struct amdgpu_vm_pt, base); + + r = amdgpu_vm_update_level(adev, vm, pt); + if (r) { + amdgpu_vm_invalidate_level(vm, &vm->root); + return r; + } + spin_lock(&vm->status_lock); + } else { + spin_lock(&vm->status_lock); + list_del_init(&bo_base->vm_status); + } + } + spin_unlock(&vm->status_lock); if (vm->use_cpu_for_update) { /* Flush HDP */ @@ -1236,7 +1307,7 @@ void amdgpu_vm_get_entry(struct amdgpu_pte_update_params *p, uint64_t addr, *entry = &p->vm->root; while ((*entry)->entries) { idx = addr >> (p->adev->vm_manager.block_size * level--); - idx %= amdgpu_bo_size((*entry)->bo) / 8; + idx %= amdgpu_bo_size((*entry)->base.bo) / 8; *parent = *entry; *entry = &(*entry)->entries[idx]; } @@ -1272,7 +1343,7 @@ static void amdgpu_vm_handle_huge_pages(struct amdgpu_pte_update_params *p, p->src || !(flags & AMDGPU_PTE_VALID)) { - dst = amdgpu_bo_gpu_offset(entry->bo); + dst = amdgpu_bo_gpu_offset(entry->base.bo); dst = amdgpu_gart_get_vm_pde(p->adev, dst); flags = AMDGPU_PTE_VALID; } else { @@ -1298,18 +1369,18 @@ static void amdgpu_vm_handle_huge_pages(struct amdgpu_pte_update_params *p, tmp = p->pages_addr; p->pages_addr = NULL; - pd_addr = (unsigned long)amdgpu_bo_kptr(parent->bo); + pd_addr = (unsigned long)amdgpu_bo_kptr(parent->base.bo); pde = pd_addr + (entry - parent->entries) * 8; amdgpu_vm_cpu_set_ptes(p, pde, dst, 1, 0, flags); p->pages_addr = tmp; } else { - if (parent->bo->shadow) { - pd_addr = amdgpu_bo_gpu_offset(parent->bo->shadow); + if (parent->base.bo->shadow) { + pd_addr = amdgpu_bo_gpu_offset(parent->base.bo->shadow); pde = pd_addr + (entry - parent->entries) * 8; amdgpu_vm_do_set_ptes(p, pde, dst, 1, 0, flags); } - pd_addr = amdgpu_bo_gpu_offset(parent->bo); + pd_addr = amdgpu_bo_gpu_offset(parent->base.bo); pde = pd_addr + (entry - parent->entries) * 8; amdgpu_vm_do_set_ptes(p, pde, dst, 1, 0, flags); } @@ -1360,7 +1431,7 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params, if (entry->addr & AMDGPU_PDE_PTE) continue; - pt = entry->bo; + pt = entry->base.bo; if (use_cpu_update) { pe_start = (unsigned long)amdgpu_bo_kptr(pt); } else { @@ -1396,8 +1467,6 @@ static int amdgpu_vm_frag_ptes(struct amdgpu_pte_update_params *params, uint64_t start, uint64_t end, uint64_t dst, uint64_t flags) { - int r; - /** * The MC L1 TLB supports variable sized pages, based on a fragment * field in the PTE. When this field is set to a non-zero value, page @@ -1416,39 +1485,38 @@ static int amdgpu_vm_frag_ptes(struct amdgpu_pte_update_params *params, * Userspace can support this by aligning virtual base address and * allocation size to the fragment size. */ - unsigned pages_per_frag = params->adev->vm_manager.fragment_size; - uint64_t frag_flags = AMDGPU_PTE_FRAG(pages_per_frag); - uint64_t frag_align = 1 << pages_per_frag; - - uint64_t frag_start = ALIGN(start, frag_align); - uint64_t frag_end = end & ~(frag_align - 1); + unsigned max_frag = params->adev->vm_manager.fragment_size; + int r; /* system pages are non continuously */ - if (params->src || !(flags & AMDGPU_PTE_VALID) || - (frag_start >= frag_end)) + if (params->src || !(flags & AMDGPU_PTE_VALID)) return amdgpu_vm_update_ptes(params, start, end, dst, flags); - /* handle the 4K area at the beginning */ - if (start != frag_start) { - r = amdgpu_vm_update_ptes(params, start, frag_start, - dst, flags); + while (start != end) { + uint64_t frag_flags, frag_end; + unsigned frag; + + /* This intentionally wraps around if no bit is set */ + frag = min((unsigned)ffs(start) - 1, + (unsigned)fls64(end - start) - 1); + if (frag >= max_frag) { + frag_flags = AMDGPU_PTE_FRAG(max_frag); + frag_end = end & ~((1ULL << max_frag) - 1); + } else { + frag_flags = AMDGPU_PTE_FRAG(frag); + frag_end = start + (1 << frag); + } + + r = amdgpu_vm_update_ptes(params, start, frag_end, dst, + flags | frag_flags); if (r) return r; - dst += (frag_start - start) * AMDGPU_GPU_PAGE_SIZE; - } - /* handle the area in the middle */ - r = amdgpu_vm_update_ptes(params, frag_start, frag_end, dst, - flags | frag_flags); - if (r) - return r; - - /* handle the 4K area at the end */ - if (frag_end != end) { - dst += (frag_end - frag_start) * AMDGPU_GPU_PAGE_SIZE; - r = amdgpu_vm_update_ptes(params, frag_end, end, dst, flags); + dst += (frag_end - start) * AMDGPU_GPU_PAGE_SIZE; + start = frag_end; } - return r; + + return 0; } /** @@ -1456,7 +1524,6 @@ static int amdgpu_vm_frag_ptes(struct amdgpu_pte_update_params *params, * * @adev: amdgpu_device pointer * @exclusive: fence we need to sync to - * @src: address where to copy page table entries from * @pages_addr: DMA addresses to use for mapping * @vm: requested vm * @start: start of mapped range @@ -1470,7 +1537,6 @@ static int amdgpu_vm_frag_ptes(struct amdgpu_pte_update_params *params, */ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, struct dma_fence *exclusive, - uint64_t src, dma_addr_t *pages_addr, struct amdgpu_vm *vm, uint64_t start, uint64_t last, @@ -1488,7 +1554,6 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, memset(¶ms, 0, sizeof(params)); params.adev = adev; params.vm = vm; - params.src = src; /* sync to everything on unmapping */ if (!(flags & AMDGPU_PTE_VALID)) @@ -1517,10 +1582,12 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, nptes = last - start + 1; /* - * reserve space for one command every (1 << BLOCK_SIZE) + * reserve space for two commands every (1 << BLOCK_SIZE) * entries or 2k dwords (whatever is smaller) + * + * The second command is for the shadow pagetables. */ - ncmds = (nptes >> min(adev->vm_manager.block_size, 11u)) + 1; + ncmds = ((nptes >> min(adev->vm_manager.block_size, 11u)) + 1) * 2; /* padding, etc. */ ndw = 64; @@ -1528,15 +1595,9 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, /* one PDE write for each huge page */ ndw += ((nptes >> adev->vm_manager.block_size) + 1) * 6; - if (src) { - /* only copy commands needed */ - ndw += ncmds * 7; - - params.func = amdgpu_vm_do_copy_ptes; - - } else if (pages_addr) { + if (pages_addr) { /* copy commands needed */ - ndw += ncmds * 7; + ndw += ncmds * adev->vm_manager.vm_pte_funcs->copy_pte_num_dw; /* and also PTEs */ ndw += nptes * 2; @@ -1545,10 +1606,11 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, } else { /* set page commands needed */ - ndw += ncmds * 10; + ndw += ncmds * adev->vm_manager.vm_pte_funcs->set_pte_pde_num_dw; - /* two extra commands for begin/end of fragment */ - ndw += 2 * 10; + /* extra commands for begin/end fragments */ + ndw += 2 * adev->vm_manager.vm_pte_funcs->set_pte_pde_num_dw + * adev->vm_manager.fragment_size; params.func = amdgpu_vm_do_set_ptes; } @@ -1559,7 +1621,7 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, params.ib = &job->ibs[0]; - if (!src && pages_addr) { + if (pages_addr) { uint64_t *pte; unsigned i; @@ -1580,12 +1642,12 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, if (r) goto error_free; - r = amdgpu_sync_resv(adev, &job->sync, vm->root.bo->tbo.resv, + r = amdgpu_sync_resv(adev, &job->sync, vm->root.base.bo->tbo.resv, owner); if (r) goto error_free; - r = reservation_object_reserve_shared(vm->root.bo->tbo.resv); + r = reservation_object_reserve_shared(vm->root.base.bo->tbo.resv); if (r) goto error_free; @@ -1600,14 +1662,14 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, if (r) goto error_free; - amdgpu_bo_fence(vm->root.bo, f, true); + amdgpu_bo_fence(vm->root.base.bo, f, true); dma_fence_put(*fence); *fence = f; return 0; error_free: amdgpu_job_free(job); - amdgpu_vm_invalidate_level(&vm->root); + amdgpu_vm_invalidate_level(vm, &vm->root); return r; } @@ -1636,7 +1698,7 @@ static int amdgpu_vm_bo_split_mapping(struct amdgpu_device *adev, struct drm_mm_node *nodes, struct dma_fence **fence) { - uint64_t pfn, src = 0, start = mapping->start; + uint64_t pfn, start = mapping->start; int r; /* normally,bo_va->flags only contians READABLE and WIRTEABLE bit go here @@ -1691,8 +1753,7 @@ static int amdgpu_vm_bo_split_mapping(struct amdgpu_device *adev, addr += pfn << PAGE_SHIFT; last = min((uint64_t)mapping->last, start + max_entries - 1); - r = amdgpu_vm_bo_update_mapping(adev, exclusive, - src, pages_addr, vm, + r = amdgpu_vm_bo_update_mapping(adev, exclusive, pages_addr, vm, start, last, flags, addr, fence); if (r) @@ -1730,7 +1791,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, dma_addr_t *pages_addr = NULL; struct ttm_mem_reg *mem; struct drm_mm_node *nodes; - struct dma_fence *exclusive; + struct dma_fence *exclusive, **last_update; uint64_t flags; int r; @@ -1756,38 +1817,43 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, else flags = 0x0; - spin_lock(&vm->status_lock); - if (!list_empty(&bo_va->base.vm_status)) + if (clear || (bo && bo->tbo.resv == vm->root.base.bo->tbo.resv)) + last_update = &vm->last_update; + else + last_update = &bo_va->last_pt_update; + + if (!clear && bo_va->base.moved) { + bo_va->base.moved = false; list_splice_init(&bo_va->valids, &bo_va->invalids); - spin_unlock(&vm->status_lock); + + } else if (bo_va->cleared != clear) { + list_splice_init(&bo_va->valids, &bo_va->invalids); + } list_for_each_entry(mapping, &bo_va->invalids, list) { r = amdgpu_vm_bo_split_mapping(adev, exclusive, pages_addr, vm, mapping, flags, nodes, - &bo_va->last_pt_update); + last_update); if (r) return r; } - if (trace_amdgpu_vm_bo_mapping_enabled()) { - list_for_each_entry(mapping, &bo_va->valids, list) - trace_amdgpu_vm_bo_mapping(mapping); - - list_for_each_entry(mapping, &bo_va->invalids, list) - trace_amdgpu_vm_bo_mapping(mapping); + if (vm->use_cpu_for_update) { + /* Flush HDP */ + mb(); + amdgpu_gart_flush_gpu_tlb(adev, 0); } spin_lock(&vm->status_lock); - list_splice_init(&bo_va->invalids, &bo_va->valids); list_del_init(&bo_va->base.vm_status); - if (clear) - list_add(&bo_va->base.vm_status, &vm->cleared); spin_unlock(&vm->status_lock); - if (vm->use_cpu_for_update) { - /* Flush HDP */ - mb(); - amdgpu_gart_flush_gpu_tlb(adev, 0); + list_splice_init(&bo_va->invalids, &bo_va->valids); + bo_va->cleared = clear; + + if (trace_amdgpu_vm_bo_mapping_enabled()) { + list_for_each_entry(mapping, &bo_va->valids, list) + trace_amdgpu_vm_bo_mapping(mapping); } return 0; @@ -1895,7 +1961,7 @@ static void amdgpu_vm_free_mapping(struct amdgpu_device *adev, */ static void amdgpu_vm_prt_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm) { - struct reservation_object *resv = vm->root.bo->tbo.resv; + struct reservation_object *resv = vm->root.base.bo->tbo.resv; struct dma_fence *excl, **shared; unsigned i, shared_count; int r; @@ -1953,7 +2019,7 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev, if (vm->pte_support_ats) init_pte_value = AMDGPU_PTE_SYSTEM; - r = amdgpu_vm_bo_update_mapping(adev, NULL, 0, NULL, vm, + r = amdgpu_vm_bo_update_mapping(adev, NULL, NULL, vm, mapping->start, mapping->last, init_pte_value, 0, &f); amdgpu_vm_free_mapping(adev, vm, mapping, f); @@ -1975,29 +2041,35 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev, } /** - * amdgpu_vm_clear_moved - clear moved BOs in the PT + * amdgpu_vm_handle_moved - handle moved BOs in the PT * * @adev: amdgpu_device pointer * @vm: requested vm + * @sync: sync object to add fences to * - * Make sure all moved BOs are cleared in the PT. + * Make sure all BOs which are moved are updated in the PTs. * Returns 0 for success. * - * PTs have to be reserved and mutex must be locked! + * PTs have to be reserved! */ -int amdgpu_vm_clear_moved(struct amdgpu_device *adev, struct amdgpu_vm *vm, - struct amdgpu_sync *sync) +int amdgpu_vm_handle_moved(struct amdgpu_device *adev, + struct amdgpu_vm *vm) { - struct amdgpu_bo_va *bo_va = NULL; + bool clear; int r = 0; spin_lock(&vm->status_lock); while (!list_empty(&vm->moved)) { + struct amdgpu_bo_va *bo_va; + bo_va = list_first_entry(&vm->moved, struct amdgpu_bo_va, base.vm_status); spin_unlock(&vm->status_lock); - r = amdgpu_vm_bo_update(adev, bo_va, true); + /* Per VM BOs never need to bo cleared in the page tables */ + clear = bo_va->base.bo->tbo.resv != vm->root.base.bo->tbo.resv; + + r = amdgpu_vm_bo_update(adev, bo_va, clear); if (r) return r; @@ -2005,9 +2077,6 @@ int amdgpu_vm_clear_moved(struct amdgpu_device *adev, struct amdgpu_vm *vm, } spin_unlock(&vm->status_lock); - if (bo_va) - r = amdgpu_sync_fence(adev, sync, bo_va->last_pt_update); - return r; } @@ -2049,6 +2118,39 @@ struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev, return bo_va; } + +/** + * amdgpu_vm_bo_insert_mapping - insert a new mapping + * + * @adev: amdgpu_device pointer + * @bo_va: bo_va to store the address + * @mapping: the mapping to insert + * + * Insert a new mapping into all structures. + */ +static void amdgpu_vm_bo_insert_map(struct amdgpu_device *adev, + struct amdgpu_bo_va *bo_va, + struct amdgpu_bo_va_mapping *mapping) +{ + struct amdgpu_vm *vm = bo_va->base.vm; + struct amdgpu_bo *bo = bo_va->base.bo; + + mapping->bo_va = bo_va; + list_add(&mapping->list, &bo_va->invalids); + amdgpu_vm_it_insert(mapping, &vm->va); + + if (mapping->flags & AMDGPU_PTE_PRT) + amdgpu_vm_prt_get(adev); + + if (bo && bo->tbo.resv == vm->root.base.bo->tbo.resv) { + spin_lock(&vm->status_lock); + if (list_empty(&bo_va->base.vm_status)) + list_add(&bo_va->base.vm_status, &vm->moved); + spin_unlock(&vm->status_lock); + } + trace_amdgpu_vm_bo_map(bo_va, mapping); +} + /** * amdgpu_vm_bo_map - map bo inside a vm * @@ -2100,17 +2202,12 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev, if (!mapping) return -ENOMEM; - INIT_LIST_HEAD(&mapping->list); mapping->start = saddr; mapping->last = eaddr; mapping->offset = offset; mapping->flags = flags; - list_add(&mapping->list, &bo_va->invalids); - amdgpu_vm_it_insert(mapping, &vm->va); - - if (flags & AMDGPU_PTE_PRT) - amdgpu_vm_prt_get(adev); + amdgpu_vm_bo_insert_map(adev, bo_va, mapping); return 0; } @@ -2137,7 +2234,6 @@ int amdgpu_vm_bo_replace_map(struct amdgpu_device *adev, { struct amdgpu_bo_va_mapping *mapping; struct amdgpu_bo *bo = bo_va->base.bo; - struct amdgpu_vm *vm = bo_va->base.vm; uint64_t eaddr; int r; @@ -2171,11 +2267,7 @@ int amdgpu_vm_bo_replace_map(struct amdgpu_device *adev, mapping->offset = offset; mapping->flags = flags; - list_add(&mapping->list, &bo_va->invalids); - amdgpu_vm_it_insert(mapping, &vm->va); - - if (flags & AMDGPU_PTE_PRT) - amdgpu_vm_prt_get(adev); + amdgpu_vm_bo_insert_map(adev, bo_va, mapping); return 0; } @@ -2221,6 +2313,7 @@ int amdgpu_vm_bo_unmap(struct amdgpu_device *adev, list_del(&mapping->list); amdgpu_vm_it_remove(mapping, &vm->va); + mapping->bo_va = NULL; trace_amdgpu_vm_bo_unmap(bo_va, mapping); if (valid) @@ -2306,6 +2399,7 @@ int amdgpu_vm_bo_clear_mappings(struct amdgpu_device *adev, if (tmp->last > eaddr) tmp->last = eaddr; + tmp->bo_va = NULL; list_add(&tmp->list, &vm->freed); trace_amdgpu_vm_bo_unmap(NULL, tmp); } @@ -2332,6 +2426,19 @@ int amdgpu_vm_bo_clear_mappings(struct amdgpu_device *adev, } /** + * amdgpu_vm_bo_lookup_mapping - find mapping by address + * + * @vm: the requested VM + * + * Find a mapping by it's address. + */ +struct amdgpu_bo_va_mapping *amdgpu_vm_bo_lookup_mapping(struct amdgpu_vm *vm, + uint64_t addr) +{ + return amdgpu_vm_it_iter_first(&vm->va, addr, addr); +} + +/** * amdgpu_vm_bo_rmv - remove a bo to a specific vm * * @adev: amdgpu_device pointer @@ -2356,6 +2463,7 @@ void amdgpu_vm_bo_rmv(struct amdgpu_device *adev, list_for_each_entry_safe(mapping, next, &bo_va->valids, list) { list_del(&mapping->list); amdgpu_vm_it_remove(mapping, &vm->va); + mapping->bo_va = NULL; trace_amdgpu_vm_bo_unmap(bo_va, mapping); list_add(&mapping->list, &vm->freed); } @@ -2380,15 +2488,36 @@ void amdgpu_vm_bo_rmv(struct amdgpu_device *adev, * Mark @bo as invalid. */ void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev, - struct amdgpu_bo *bo) + struct amdgpu_bo *bo, bool evicted) { struct amdgpu_vm_bo_base *bo_base; list_for_each_entry(bo_base, &bo->va, bo_list) { + struct amdgpu_vm *vm = bo_base->vm; + + bo_base->moved = true; + if (evicted && bo->tbo.resv == vm->root.base.bo->tbo.resv) { + spin_lock(&bo_base->vm->status_lock); + if (bo->tbo.type == ttm_bo_type_kernel) + list_move(&bo_base->vm_status, &vm->evicted); + else + list_move_tail(&bo_base->vm_status, + &vm->evicted); + spin_unlock(&bo_base->vm->status_lock); + continue; + } + + if (bo->tbo.type == ttm_bo_type_kernel) { + spin_lock(&bo_base->vm->status_lock); + if (list_empty(&bo_base->vm_status)) + list_add(&bo_base->vm_status, &vm->relocated); + spin_unlock(&bo_base->vm->status_lock); + continue; + } + spin_lock(&bo_base->vm->status_lock); if (list_empty(&bo_base->vm_status)) - list_add(&bo_base->vm_status, - &bo_base->vm->moved); + list_add(&bo_base->vm_status, &vm->moved); spin_unlock(&bo_base->vm->status_lock); } } @@ -2458,7 +2587,7 @@ void amdgpu_vm_adjust_size(struct amdgpu_device *adev, uint64_t vm_size, uint32_ * Init @vm fields. */ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, - int vm_context) + int vm_context, unsigned int pasid) { const unsigned align = min(AMDGPU_VM_PTB_ALIGN_SIZE, AMDGPU_VM_PTE_COUNT(adev) * 8); @@ -2474,8 +2603,9 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, for (i = 0; i < AMDGPU_MAX_VMHUBS; i++) vm->reserved_vmid[i] = NULL; spin_lock_init(&vm->status_lock); + INIT_LIST_HEAD(&vm->evicted); + INIT_LIST_HEAD(&vm->relocated); INIT_LIST_HEAD(&vm->moved); - INIT_LIST_HEAD(&vm->cleared); INIT_LIST_HEAD(&vm->freed); /* create scheduler entity for page table updates */ @@ -2506,7 +2636,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, vm->use_cpu_for_update ? "CPU" : "SDMA"); WARN_ONCE((vm->use_cpu_for_update & !amdgpu_vm_is_large_bar(adev)), "CPU update of VM recommended only for large BAR system\n"); - vm->last_dir_update = NULL; + vm->last_update = NULL; flags = AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS | AMDGPU_GEM_CREATE_VRAM_CLEARED; @@ -2519,30 +2649,46 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, r = amdgpu_bo_create(adev, amdgpu_vm_bo_size(adev, 0), align, true, AMDGPU_GEM_DOMAIN_VRAM, flags, - NULL, NULL, init_pde_value, &vm->root.bo); + NULL, NULL, init_pde_value, &vm->root.base.bo); if (r) goto error_free_sched_entity; - r = amdgpu_bo_reserve(vm->root.bo, false); - if (r) - goto error_free_root; - - vm->last_eviction_counter = atomic64_read(&adev->num_evictions); + vm->root.base.vm = vm; + list_add_tail(&vm->root.base.bo_list, &vm->root.base.bo->va); + INIT_LIST_HEAD(&vm->root.base.vm_status); if (vm->use_cpu_for_update) { - r = amdgpu_bo_kmap(vm->root.bo, NULL); + r = amdgpu_bo_reserve(vm->root.base.bo, false); if (r) goto error_free_root; + + r = amdgpu_bo_kmap(vm->root.base.bo, NULL); + amdgpu_bo_unreserve(vm->root.base.bo); + if (r) + goto error_free_root; + } + + if (pasid) { + unsigned long flags; + + spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags); + r = idr_alloc(&adev->vm_manager.pasid_idr, vm, pasid, pasid + 1, + GFP_ATOMIC); + spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags); + if (r < 0) + goto error_free_root; + + vm->pasid = pasid; } - amdgpu_bo_unreserve(vm->root.bo); + INIT_KFIFO(vm->faults); return 0; error_free_root: - amdgpu_bo_unref(&vm->root.bo->shadow); - amdgpu_bo_unref(&vm->root.bo); - vm->root.bo = NULL; + amdgpu_bo_unref(&vm->root.base.bo->shadow); + amdgpu_bo_unref(&vm->root.base.bo); + vm->root.base.bo = NULL; error_free_sched_entity: amd_sched_entity_fini(&ring->sched, &vm->entity); @@ -2561,9 +2707,11 @@ static void amdgpu_vm_free_levels(struct amdgpu_vm_pt *level) { unsigned i; - if (level->bo) { - amdgpu_bo_unref(&level->bo->shadow); - amdgpu_bo_unref(&level->bo); + if (level->base.bo) { + list_del(&level->base.bo_list); + list_del(&level->base.vm_status); + amdgpu_bo_unref(&level->base.bo->shadow); + amdgpu_bo_unref(&level->base.bo); } if (level->entries) @@ -2586,8 +2734,21 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm) { struct amdgpu_bo_va_mapping *mapping, *tmp; bool prt_fini_needed = !!adev->gart.gart_funcs->set_prt; + u64 fault; int i; + /* Clear pending page faults from IH when the VM is destroyed */ + while (kfifo_get(&vm->faults, &fault)) + amdgpu_ih_clear_fault(adev, fault); + + if (vm->pasid) { + unsigned long flags; + + spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags); + idr_remove(&adev->vm_manager.pasid_idr, vm->pasid); + spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags); + } + amd_sched_entity_fini(vm->entity.sched, &vm->entity); if (!RB_EMPTY_ROOT(&vm->va.rb_root)) { @@ -2610,7 +2771,7 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm) } amdgpu_vm_free_levels(&vm->root); - dma_fence_put(vm->last_dir_update); + dma_fence_put(vm->last_update); for (i = 0; i < AMDGPU_MAX_VMHUBS; i++) amdgpu_vm_free_reserved_vmid(adev, vm, i); } @@ -2668,6 +2829,8 @@ void amdgpu_vm_manager_init(struct amdgpu_device *adev) adev->vm_manager.vm_update_mode = 0; #endif + idr_init(&adev->vm_manager.pasid_idr); + spin_lock_init(&adev->vm_manager.pasid_lock); } /** @@ -2681,6 +2844,9 @@ void amdgpu_vm_manager_fini(struct amdgpu_device *adev) { unsigned i, j; + WARN_ON(!idr_is_empty(&adev->vm_manager.pasid_idr)); + idr_destroy(&adev->vm_manager.pasid_idr); + for (i = 0; i < AMDGPU_MAX_VMHUBS; ++i) { struct amdgpu_vm_id_manager *id_mgr = &adev->vm_manager.id_mgr[i]; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h index 6716355..0af0906 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h @@ -25,6 +25,7 @@ #define __AMDGPU_VM_H__ #include <linux/rbtree.h> +#include <linux/idr.h> #include "gpu_scheduler.h" #include "amdgpu_sync.h" @@ -105,17 +106,24 @@ struct amdgpu_vm_bo_base { /* protected by spinlock */ struct list_head vm_status; + + /* protected by the BO being reserved */ + bool moved; }; struct amdgpu_vm_pt { - struct amdgpu_bo *bo; - uint64_t addr; + struct amdgpu_vm_bo_base base; + uint64_t addr; /* array of page tables, one for each directory entry */ - struct amdgpu_vm_pt *entries; - unsigned last_entry_used; + struct amdgpu_vm_pt *entries; + unsigned last_entry_used; }; +#define AMDGPU_VM_FAULT(pasid, addr) (((u64)(pasid) << 48) | (addr)) +#define AMDGPU_VM_FAULT_PASID(fault) ((u64)(fault) >> 48) +#define AMDGPU_VM_FAULT_ADDR(fault) ((u64)(fault) & 0xfffffffff000ULL) + struct amdgpu_vm { /* tree of virtual addresses mapped */ struct rb_root_cached va; @@ -123,19 +131,21 @@ struct amdgpu_vm { /* protecting invalidated */ spinlock_t status_lock; + /* BOs who needs a validation */ + struct list_head evicted; + + /* PT BOs which relocated and their parent need an update */ + struct list_head relocated; + /* BOs moved, but not yet updated in the PT */ struct list_head moved; - /* BOs cleared in the PT because of a move */ - struct list_head cleared; - /* BO mappings freed, but not yet updated in the PT */ struct list_head freed; /* contains the page directory */ struct amdgpu_vm_pt root; - struct dma_fence *last_dir_update; - uint64_t last_eviction_counter; + struct dma_fence *last_update; /* protecting freed */ spinlock_t freed_lock; @@ -143,8 +153,9 @@ struct amdgpu_vm { /* Scheduler entity for page table updates */ struct amd_sched_entity entity; - /* client id */ + /* client id and PASID (TODO: replace client_id with PASID) */ u64 client_id; + unsigned int pasid; /* dedicated to vm */ struct amdgpu_vm_id *reserved_vmid[AMDGPU_MAX_VMHUBS]; @@ -153,6 +164,9 @@ struct amdgpu_vm { /* Flag to indicate ATS support from PTE for GFX9 */ bool pte_support_ats; + + /* Up to 128 pending page faults */ + DECLARE_KFIFO(faults, u64, 128); }; struct amdgpu_vm_id { @@ -215,16 +229,25 @@ struct amdgpu_vm_manager { * BIT1[= 0] Compute updated by SDMA [= 1] by CPU */ int vm_update_mode; + + /* PASID to VM mapping, will be used in interrupt context to + * look up VM of a page fault + */ + struct idr pasid_idr; + spinlock_t pasid_lock; }; +int amdgpu_vm_alloc_pasid(unsigned int bits); +void amdgpu_vm_free_pasid(unsigned int pasid); void amdgpu_vm_manager_init(struct amdgpu_device *adev); void amdgpu_vm_manager_fini(struct amdgpu_device *adev); int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, - int vm_context); + int vm_context, unsigned int pasid); void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm); void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm, struct list_head *validated, struct amdgpu_bo_list_entry *entry); +bool amdgpu_vm_ready(struct amdgpu_vm *vm); int amdgpu_vm_validate_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm, int (*callback)(void *p, struct amdgpu_bo *bo), void *param); @@ -243,13 +266,13 @@ int amdgpu_vm_update_directories(struct amdgpu_device *adev, int amdgpu_vm_clear_freed(struct amdgpu_device *adev, struct amdgpu_vm *vm, struct dma_fence **fence); -int amdgpu_vm_clear_moved(struct amdgpu_device *adev, struct amdgpu_vm *vm, - struct amdgpu_sync *sync); +int amdgpu_vm_handle_moved(struct amdgpu_device *adev, + struct amdgpu_vm *vm); int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va, bool clear); void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev, - struct amdgpu_bo *bo); + struct amdgpu_bo *bo, bool evicted); struct amdgpu_bo_va *amdgpu_vm_bo_find(struct amdgpu_vm *vm, struct amdgpu_bo *bo); struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev, @@ -269,6 +292,8 @@ int amdgpu_vm_bo_unmap(struct amdgpu_device *adev, int amdgpu_vm_bo_clear_mappings(struct amdgpu_device *adev, struct amdgpu_vm *vm, uint64_t saddr, uint64_t size); +struct amdgpu_bo_va_mapping *amdgpu_vm_bo_lookup_mapping(struct amdgpu_vm *vm, + uint64_t addr); void amdgpu_vm_bo_rmv(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va); void amdgpu_vm_set_fragment_size(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/amdgpu/atom.c b/drivers/gpu/drm/amd/amdgpu/atom.c index d69aa2e..69500a8 100644 --- a/drivers/gpu/drm/amd/amdgpu/atom.c +++ b/drivers/gpu/drm/amd/amdgpu/atom.c @@ -1343,8 +1343,11 @@ struct atom_context *amdgpu_atom_parse(struct card_info *card, void *bios) idx = 0x80; str = CSTR(idx); - if (*str != '\0') + if (*str != '\0') { pr_info("ATOM BIOS: %s\n", str); + strlcpy(ctx->vbios_version, str, sizeof(ctx->vbios_version)); + } + return ctx; } diff --git a/drivers/gpu/drm/amd/amdgpu/atom.h b/drivers/gpu/drm/amd/amdgpu/atom.h index ddd8045..a391709 100644 --- a/drivers/gpu/drm/amd/amdgpu/atom.h +++ b/drivers/gpu/drm/amd/amdgpu/atom.h @@ -140,6 +140,7 @@ struct atom_context { int io_mode; uint32_t *scratch; int scratch_size_bytes; + char vbios_version[20]; }; extern int amdgpu_atom_debug; diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c index cb508a2..68ce1bd 100644 --- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c @@ -307,7 +307,6 @@ static int ci_set_power_limit(struct amdgpu_device *adev, u32 n); static int ci_set_overdrive_target_tdp(struct amdgpu_device *adev, u32 target_tdp); static int ci_update_uvd_dpm(struct amdgpu_device *adev, bool gate); -static void ci_dpm_set_dpm_funcs(struct amdgpu_device *adev); static void ci_dpm_set_irq_funcs(struct amdgpu_device *adev); static PPSMC_Result amdgpu_ci_send_msg_to_smc_with_parameter(struct amdgpu_device *adev, @@ -883,8 +882,9 @@ static int ci_power_control_set_level(struct amdgpu_device *adev) return ret; } -static void ci_dpm_powergate_uvd(struct amdgpu_device *adev, bool gate) +static void ci_dpm_powergate_uvd(void *handle, bool gate) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct ci_power_info *pi = ci_get_pi(adev); pi->uvd_power_gated = gate; @@ -901,8 +901,9 @@ static void ci_dpm_powergate_uvd(struct amdgpu_device *adev, bool gate) } } -static bool ci_dpm_vblank_too_short(struct amdgpu_device *adev) +static bool ci_dpm_vblank_too_short(void *handle) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; u32 vblank_time = amdgpu_dpm_get_vblank_time(adev); u32 switch_limit = adev->mc.vram_type == AMDGPU_VRAM_TYPE_GDDR5 ? 450 : 300; @@ -1210,11 +1211,12 @@ static int ci_fan_ctrl_stop_smc_fan_control(struct amdgpu_device *adev) } } -static int ci_dpm_get_fan_speed_percent(struct amdgpu_device *adev, +static int ci_dpm_get_fan_speed_percent(void *handle, u32 *speed) { u32 duty, duty100; u64 tmp64; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; if (adev->pm.no_fan) return -ENOENT; @@ -1237,12 +1239,13 @@ static int ci_dpm_get_fan_speed_percent(struct amdgpu_device *adev, return 0; } -static int ci_dpm_set_fan_speed_percent(struct amdgpu_device *adev, +static int ci_dpm_set_fan_speed_percent(void *handle, u32 speed) { u32 tmp; u32 duty, duty100; u64 tmp64; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct ci_power_info *pi = ci_get_pi(adev); if (adev->pm.no_fan) @@ -1271,8 +1274,10 @@ static int ci_dpm_set_fan_speed_percent(struct amdgpu_device *adev, return 0; } -static void ci_dpm_set_fan_control_mode(struct amdgpu_device *adev, u32 mode) +static void ci_dpm_set_fan_control_mode(void *handle, u32 mode) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + switch (mode) { case AMD_FAN_CTRL_NONE: if (adev->pm.dpm.fan.ucode_fan_control) @@ -1292,8 +1297,9 @@ static void ci_dpm_set_fan_control_mode(struct amdgpu_device *adev, u32 mode) } } -static u32 ci_dpm_get_fan_control_mode(struct amdgpu_device *adev) +static u32 ci_dpm_get_fan_control_mode(void *handle) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct ci_power_info *pi = ci_get_pi(adev); if (pi->fan_is_controlled_by_smc) @@ -4378,9 +4384,10 @@ static u32 ci_get_lowest_enabled_level(struct amdgpu_device *adev, } -static int ci_dpm_force_performance_level(struct amdgpu_device *adev, +static int ci_dpm_force_performance_level(void *handle, enum amd_dpm_forced_level level) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct ci_power_info *pi = ci_get_pi(adev); u32 tmp, levels, i; int ret; @@ -5291,8 +5298,9 @@ static void ci_update_requested_ps(struct amdgpu_device *adev, adev->pm.dpm.requested_ps = &pi->requested_rps; } -static int ci_dpm_pre_set_power_state(struct amdgpu_device *adev) +static int ci_dpm_pre_set_power_state(void *handle) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct ci_power_info *pi = ci_get_pi(adev); struct amdgpu_ps requested_ps = *adev->pm.dpm.requested_ps; struct amdgpu_ps *new_ps = &requested_ps; @@ -5304,8 +5312,9 @@ static int ci_dpm_pre_set_power_state(struct amdgpu_device *adev) return 0; } -static void ci_dpm_post_set_power_state(struct amdgpu_device *adev) +static void ci_dpm_post_set_power_state(void *handle) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct ci_power_info *pi = ci_get_pi(adev); struct amdgpu_ps *new_ps = &pi->requested_rps; @@ -5479,8 +5488,9 @@ static void ci_dpm_disable(struct amdgpu_device *adev) ci_update_current_ps(adev, boot_ps); } -static int ci_dpm_set_power_state(struct amdgpu_device *adev) +static int ci_dpm_set_power_state(void *handle) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct ci_power_info *pi = ci_get_pi(adev); struct amdgpu_ps *new_ps = &pi->requested_rps; struct amdgpu_ps *old_ps = &pi->current_rps; @@ -5551,8 +5561,10 @@ static void ci_dpm_reset_asic(struct amdgpu_device *adev) } #endif -static void ci_dpm_display_configuration_changed(struct amdgpu_device *adev) +static void ci_dpm_display_configuration_changed(void *handle) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + ci_program_display_gap(adev); } @@ -6105,9 +6117,10 @@ static int ci_dpm_init(struct amdgpu_device *adev) } static void -ci_dpm_debugfs_print_current_performance_level(struct amdgpu_device *adev, +ci_dpm_debugfs_print_current_performance_level(void *handle, struct seq_file *m) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct ci_power_info *pi = ci_get_pi(adev); struct amdgpu_ps *rps = &pi->current_rps; u32 sclk = ci_get_average_sclk_freq(adev); @@ -6131,12 +6144,13 @@ ci_dpm_debugfs_print_current_performance_level(struct amdgpu_device *adev, seq_printf(m, "GPU load: %u %%\n", activity_percent); } -static void ci_dpm_print_power_state(struct amdgpu_device *adev, - struct amdgpu_ps *rps) +static void ci_dpm_print_power_state(void *handle, void *current_ps) { + struct amdgpu_ps *rps = (struct amdgpu_ps *)current_ps; struct ci_ps *ps = ci_get_ps(rps); struct ci_pl *pl; int i; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; amdgpu_dpm_print_class_info(rps->class, rps->class2); amdgpu_dpm_print_cap_info(rps->caps); @@ -6158,20 +6172,23 @@ static inline bool ci_are_power_levels_equal(const struct ci_pl *ci_cpl1, (ci_cpl1->pcie_lane == ci_cpl2->pcie_lane)); } -static int ci_check_state_equal(struct amdgpu_device *adev, - struct amdgpu_ps *cps, - struct amdgpu_ps *rps, +static int ci_check_state_equal(void *handle, + void *current_ps, + void *request_ps, bool *equal) { struct ci_ps *ci_cps; struct ci_ps *ci_rps; int i; + struct amdgpu_ps *cps = (struct amdgpu_ps *)current_ps; + struct amdgpu_ps *rps = (struct amdgpu_ps *)request_ps; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; if (adev == NULL || cps == NULL || rps == NULL || equal == NULL) return -EINVAL; - ci_cps = ci_get_ps(cps); - ci_rps = ci_get_ps(rps); + ci_cps = ci_get_ps((struct amdgpu_ps *)cps); + ci_rps = ci_get_ps((struct amdgpu_ps *)rps); if (ci_cps == NULL) { *equal = false; @@ -6199,8 +6216,9 @@ static int ci_check_state_equal(struct amdgpu_device *adev, return 0; } -static u32 ci_dpm_get_sclk(struct amdgpu_device *adev, bool low) +static u32 ci_dpm_get_sclk(void *handle, bool low) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct ci_power_info *pi = ci_get_pi(adev); struct ci_ps *requested_state = ci_get_ps(&pi->requested_rps); @@ -6210,8 +6228,9 @@ static u32 ci_dpm_get_sclk(struct amdgpu_device *adev, bool low) return requested_state->performance_levels[requested_state->performance_level_count - 1].sclk; } -static u32 ci_dpm_get_mclk(struct amdgpu_device *adev, bool low) +static u32 ci_dpm_get_mclk(void *handle, bool low) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct ci_power_info *pi = ci_get_pi(adev); struct ci_ps *requested_state = ci_get_ps(&pi->requested_rps); @@ -6222,10 +6241,11 @@ static u32 ci_dpm_get_mclk(struct amdgpu_device *adev, bool low) } /* get temperature in millidegrees */ -static int ci_dpm_get_temp(struct amdgpu_device *adev) +static int ci_dpm_get_temp(void *handle) { u32 temp; int actual_temp = 0; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; temp = (RREG32_SMC(ixCG_MULT_THERMAL_STATUS) & CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK) >> CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT; @@ -6261,7 +6281,6 @@ static int ci_dpm_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - ci_dpm_set_dpm_funcs(adev); ci_dpm_set_irq_funcs(adev); return 0; @@ -6551,9 +6570,10 @@ static int ci_dpm_set_powergating_state(void *handle, return 0; } -static int ci_dpm_print_clock_levels(struct amdgpu_device *adev, +static int ci_dpm_print_clock_levels(void *handle, enum pp_clock_type type, char *buf) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct ci_power_info *pi = ci_get_pi(adev); struct ci_single_dpm_table *sclk_table = &pi->dpm_table.sclk_table; struct ci_single_dpm_table *mclk_table = &pi->dpm_table.mclk_table; @@ -6618,9 +6638,10 @@ static int ci_dpm_print_clock_levels(struct amdgpu_device *adev, return size; } -static int ci_dpm_force_clock_level(struct amdgpu_device *adev, +static int ci_dpm_force_clock_level(void *handle, enum pp_clock_type type, uint32_t mask) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct ci_power_info *pi = ci_get_pi(adev); if (adev->pm.dpm.forced_level & (AMD_DPM_FORCED_LEVEL_AUTO | @@ -6664,8 +6685,9 @@ static int ci_dpm_force_clock_level(struct amdgpu_device *adev, return 0; } -static int ci_dpm_get_sclk_od(struct amdgpu_device *adev) +static int ci_dpm_get_sclk_od(void *handle) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct ci_power_info *pi = ci_get_pi(adev); struct ci_single_dpm_table *sclk_table = &(pi->dpm_table.sclk_table); struct ci_single_dpm_table *golden_sclk_table = @@ -6680,8 +6702,9 @@ static int ci_dpm_get_sclk_od(struct amdgpu_device *adev) return value; } -static int ci_dpm_set_sclk_od(struct amdgpu_device *adev, uint32_t value) +static int ci_dpm_set_sclk_od(void *handle, uint32_t value) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct ci_power_info *pi = ci_get_pi(adev); struct ci_ps *ps = ci_get_ps(adev->pm.dpm.requested_ps); struct ci_single_dpm_table *golden_sclk_table = @@ -6698,8 +6721,9 @@ static int ci_dpm_set_sclk_od(struct amdgpu_device *adev, uint32_t value) return 0; } -static int ci_dpm_get_mclk_od(struct amdgpu_device *adev) +static int ci_dpm_get_mclk_od(void *handle) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct ci_power_info *pi = ci_get_pi(adev); struct ci_single_dpm_table *mclk_table = &(pi->dpm_table.mclk_table); struct ci_single_dpm_table *golden_mclk_table = @@ -6714,8 +6738,9 @@ static int ci_dpm_get_mclk_od(struct amdgpu_device *adev) return value; } -static int ci_dpm_set_mclk_od(struct amdgpu_device *adev, uint32_t value) +static int ci_dpm_set_mclk_od(void *handle, uint32_t value) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct ci_power_info *pi = ci_get_pi(adev); struct ci_ps *ps = ci_get_ps(adev->pm.dpm.requested_ps); struct ci_single_dpm_table *golden_mclk_table = @@ -6732,9 +6757,10 @@ static int ci_dpm_set_mclk_od(struct amdgpu_device *adev, uint32_t value) return 0; } -static int ci_dpm_get_power_profile_state(struct amdgpu_device *adev, +static int ci_dpm_get_power_profile_state(void *handle, struct amd_pp_profile *query) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct ci_power_info *pi = ci_get_pi(adev); if (!pi || !query) @@ -6851,9 +6877,10 @@ static int ci_set_power_profile_state(struct amdgpu_device *adev, return result; } -static int ci_dpm_set_power_profile_state(struct amdgpu_device *adev, +static int ci_dpm_set_power_profile_state(void *handle, struct amd_pp_profile *request) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct ci_power_info *pi = ci_get_pi(adev); int ret = -1; @@ -6906,9 +6933,10 @@ static int ci_dpm_set_power_profile_state(struct amdgpu_device *adev, return 0; } -static int ci_dpm_reset_power_profile_state(struct amdgpu_device *adev, +static int ci_dpm_reset_power_profile_state(void *handle, struct amd_pp_profile *request) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct ci_power_info *pi = ci_get_pi(adev); if (!pi || !request) @@ -6927,9 +6955,10 @@ static int ci_dpm_reset_power_profile_state(struct amdgpu_device *adev, return -EINVAL; } -static int ci_dpm_switch_power_profile(struct amdgpu_device *adev, +static int ci_dpm_switch_power_profile(void *handle, enum amd_pp_profile_type type) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct ci_power_info *pi = ci_get_pi(adev); struct amd_pp_profile request = {0}; @@ -6944,11 +6973,12 @@ static int ci_dpm_switch_power_profile(struct amdgpu_device *adev, return 0; } -static int ci_dpm_read_sensor(struct amdgpu_device *adev, int idx, +static int ci_dpm_read_sensor(void *handle, int idx, void *value, int *size) { u32 activity_percent = 50; int ret; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; /* size must be at least 4 bytes for all sensors */ if (*size < 4) @@ -7003,7 +7033,7 @@ const struct amd_ip_funcs ci_dpm_ip_funcs = { .set_powergating_state = ci_dpm_set_powergating_state, }; -static const struct amdgpu_dpm_funcs ci_dpm_funcs = { +const struct amd_pm_funcs ci_dpm_funcs = { .get_temperature = &ci_dpm_get_temp, .pre_set_power_state = &ci_dpm_pre_set_power_state, .set_power_state = &ci_dpm_set_power_state, @@ -7035,12 +7065,6 @@ static const struct amdgpu_dpm_funcs ci_dpm_funcs = { .read_sensor = ci_dpm_read_sensor, }; -static void ci_dpm_set_dpm_funcs(struct amdgpu_device *adev) -{ - if (adev->pm.funcs == NULL) - adev->pm.funcs = &ci_dpm_funcs; -} - static const struct amdgpu_irq_src_funcs ci_dpm_irq_funcs = { .set = ci_dpm_set_interrupt_state, .process = ci_dpm_process_interrupt, diff --git a/drivers/gpu/drm/amd/amdgpu/cik_dpm.h b/drivers/gpu/drm/amd/amdgpu/cik_dpm.h index b1c8e7b..c7b4349 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik_dpm.h +++ b/drivers/gpu/drm/amd/amdgpu/cik_dpm.h @@ -26,5 +26,6 @@ extern const struct amd_ip_funcs ci_dpm_ip_funcs; extern const struct amd_ip_funcs kv_dpm_ip_funcs; - +extern const struct amd_pm_funcs ci_dpm_funcs; +extern const struct amd_pm_funcs kv_dpm_funcs; #endif diff --git a/drivers/gpu/drm/amd/amdgpu/cik_ih.c b/drivers/gpu/drm/amd/amdgpu/cik_ih.c index b891843..07d3d89 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/cik_ih.c @@ -228,6 +228,19 @@ static u32 cik_ih_get_wptr(struct amdgpu_device *adev) * [127:96] - reserved */ +/** + * cik_ih_prescreen_iv - prescreen an interrupt vector + * + * @adev: amdgpu_device pointer + * + * Returns true if the interrupt vector should be further processed. + */ +static bool cik_ih_prescreen_iv(struct amdgpu_device *adev) +{ + /* Process all interrupts */ + return true; +} + /** * cik_ih_decode_iv - decode an interrupt vector * @@ -433,6 +446,7 @@ static const struct amd_ip_funcs cik_ih_ip_funcs = { static const struct amdgpu_ih_funcs cik_ih_funcs = { .get_wptr = cik_ih_get_wptr, + .prescreen_iv = cik_ih_prescreen_iv, .decode_iv = cik_ih_decode_iv, .set_rptr = cik_ih_set_rptr }; diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c index f508f4d..60cecd1 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c +++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c @@ -1387,8 +1387,13 @@ static void cik_sdma_set_buffer_funcs(struct amdgpu_device *adev) } static const struct amdgpu_vm_pte_funcs cik_sdma_vm_pte_funcs = { + .copy_pte_num_dw = 7, .copy_pte = cik_sdma_vm_copy_pte, + .write_pte = cik_sdma_vm_write_pte, + + .set_max_nums_pte_pde = 0x1fffff >> 3, + .set_pte_pde_num_dw = 10, .set_pte_pde = cik_sdma_vm_set_pte_pde, }; diff --git a/drivers/gpu/drm/amd/amdgpu/cz_ih.c b/drivers/gpu/drm/amd/amdgpu/cz_ih.c index 0c1209c..b6cdf4a 100644 --- a/drivers/gpu/drm/amd/amdgpu/cz_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/cz_ih.c @@ -208,6 +208,19 @@ static u32 cz_ih_get_wptr(struct amdgpu_device *adev) } /** + * cz_ih_prescreen_iv - prescreen an interrupt vector + * + * @adev: amdgpu_device pointer + * + * Returns true if the interrupt vector should be further processed. + */ +static bool cz_ih_prescreen_iv(struct amdgpu_device *adev) +{ + /* Process all interrupts */ + return true; +} + +/** * cz_ih_decode_iv - decode an interrupt vector * * @adev: amdgpu_device pointer @@ -414,6 +427,7 @@ static const struct amd_ip_funcs cz_ih_ip_funcs = { static const struct amdgpu_ih_funcs cz_ih_funcs = { .get_wptr = cz_ih_get_wptr, + .prescreen_iv = cz_ih_prescreen_iv, .decode_iv = cz_ih_decode_iv, .set_rptr = cz_ih_set_rptr }; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index fc260c1..dfc10b1 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -125,24 +125,39 @@ MODULE_FIRMWARE("amdgpu/fiji_mec2.bin"); MODULE_FIRMWARE("amdgpu/fiji_rlc.bin"); MODULE_FIRMWARE("amdgpu/polaris11_ce.bin"); +MODULE_FIRMWARE("amdgpu/polaris11_ce_2.bin"); MODULE_FIRMWARE("amdgpu/polaris11_pfp.bin"); +MODULE_FIRMWARE("amdgpu/polaris11_pfp_2.bin"); MODULE_FIRMWARE("amdgpu/polaris11_me.bin"); +MODULE_FIRMWARE("amdgpu/polaris11_me_2.bin"); MODULE_FIRMWARE("amdgpu/polaris11_mec.bin"); +MODULE_FIRMWARE("amdgpu/polaris11_mec_2.bin"); MODULE_FIRMWARE("amdgpu/polaris11_mec2.bin"); +MODULE_FIRMWARE("amdgpu/polaris11_mec2_2.bin"); MODULE_FIRMWARE("amdgpu/polaris11_rlc.bin"); MODULE_FIRMWARE("amdgpu/polaris10_ce.bin"); +MODULE_FIRMWARE("amdgpu/polaris10_ce_2.bin"); MODULE_FIRMWARE("amdgpu/polaris10_pfp.bin"); +MODULE_FIRMWARE("amdgpu/polaris10_pfp_2.bin"); MODULE_FIRMWARE("amdgpu/polaris10_me.bin"); +MODULE_FIRMWARE("amdgpu/polaris10_me_2.bin"); MODULE_FIRMWARE("amdgpu/polaris10_mec.bin"); +MODULE_FIRMWARE("amdgpu/polaris10_mec_2.bin"); MODULE_FIRMWARE("amdgpu/polaris10_mec2.bin"); +MODULE_FIRMWARE("amdgpu/polaris10_mec2_2.bin"); MODULE_FIRMWARE("amdgpu/polaris10_rlc.bin"); MODULE_FIRMWARE("amdgpu/polaris12_ce.bin"); +MODULE_FIRMWARE("amdgpu/polaris12_ce_2.bin"); MODULE_FIRMWARE("amdgpu/polaris12_pfp.bin"); +MODULE_FIRMWARE("amdgpu/polaris12_pfp_2.bin"); MODULE_FIRMWARE("amdgpu/polaris12_me.bin"); +MODULE_FIRMWARE("amdgpu/polaris12_me_2.bin"); MODULE_FIRMWARE("amdgpu/polaris12_mec.bin"); +MODULE_FIRMWARE("amdgpu/polaris12_mec_2.bin"); MODULE_FIRMWARE("amdgpu/polaris12_mec2.bin"); +MODULE_FIRMWARE("amdgpu/polaris12_mec2_2.bin"); MODULE_FIRMWARE("amdgpu/polaris12_rlc.bin"); static const struct amdgpu_gds_reg_offset amdgpu_gds_reg_offset[] = @@ -918,8 +933,17 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev) BUG(); } - snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp.bin", chip_name); - err = request_firmware(&adev->gfx.pfp_fw, fw_name, adev->dev); + if (adev->asic_type >= CHIP_POLARIS10 && adev->asic_type <= CHIP_POLARIS12) { + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp_2.bin", chip_name); + err = request_firmware(&adev->gfx.pfp_fw, fw_name, adev->dev); + if (err == -ENOENT) { + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp.bin", chip_name); + err = request_firmware(&adev->gfx.pfp_fw, fw_name, adev->dev); + } + } else { + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp.bin", chip_name); + err = request_firmware(&adev->gfx.pfp_fw, fw_name, adev->dev); + } if (err) goto out; err = amdgpu_ucode_validate(adev->gfx.pfp_fw); @@ -929,8 +953,17 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev) adev->gfx.pfp_fw_version = le32_to_cpu(cp_hdr->header.ucode_version); adev->gfx.pfp_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version); - snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me.bin", chip_name); - err = request_firmware(&adev->gfx.me_fw, fw_name, adev->dev); + if (adev->asic_type >= CHIP_POLARIS10 && adev->asic_type <= CHIP_POLARIS12) { + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me_2.bin", chip_name); + err = request_firmware(&adev->gfx.me_fw, fw_name, adev->dev); + if (err == -ENOENT) { + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me.bin", chip_name); + err = request_firmware(&adev->gfx.me_fw, fw_name, adev->dev); + } + } else { + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me.bin", chip_name); + err = request_firmware(&adev->gfx.me_fw, fw_name, adev->dev); + } if (err) goto out; err = amdgpu_ucode_validate(adev->gfx.me_fw); @@ -941,8 +974,17 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev) adev->gfx.me_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version); - snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ce.bin", chip_name); - err = request_firmware(&adev->gfx.ce_fw, fw_name, adev->dev); + if (adev->asic_type >= CHIP_POLARIS10 && adev->asic_type <= CHIP_POLARIS12) { + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ce_2.bin", chip_name); + err = request_firmware(&adev->gfx.ce_fw, fw_name, adev->dev); + if (err == -ENOENT) { + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ce.bin", chip_name); + err = request_firmware(&adev->gfx.ce_fw, fw_name, adev->dev); + } + } else { + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ce.bin", chip_name); + err = request_firmware(&adev->gfx.ce_fw, fw_name, adev->dev); + } if (err) goto out; err = amdgpu_ucode_validate(adev->gfx.ce_fw); @@ -1012,8 +1054,17 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev) for (i = 0 ; i < (rlc_hdr->reg_list_size_bytes >> 2); i++) adev->gfx.rlc.register_restore[i] = le32_to_cpu(tmp[i]); - snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec.bin", chip_name); - err = request_firmware(&adev->gfx.mec_fw, fw_name, adev->dev); + if (adev->asic_type >= CHIP_POLARIS10 && adev->asic_type <= CHIP_POLARIS12) { + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec_2.bin", chip_name); + err = request_firmware(&adev->gfx.mec_fw, fw_name, adev->dev); + if (err == -ENOENT) { + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec.bin", chip_name); + err = request_firmware(&adev->gfx.mec_fw, fw_name, adev->dev); + } + } else { + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec.bin", chip_name); + err = request_firmware(&adev->gfx.mec_fw, fw_name, adev->dev); + } if (err) goto out; err = amdgpu_ucode_validate(adev->gfx.mec_fw); @@ -1025,8 +1076,17 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev) if ((adev->asic_type != CHIP_STONEY) && (adev->asic_type != CHIP_TOPAZ)) { - snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2.bin", chip_name); - err = request_firmware(&adev->gfx.mec2_fw, fw_name, adev->dev); + if (adev->asic_type >= CHIP_POLARIS10 && adev->asic_type <= CHIP_POLARIS12) { + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2_2.bin", chip_name); + err = request_firmware(&adev->gfx.mec2_fw, fw_name, adev->dev); + if (err == -ENOENT) { + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2.bin", chip_name); + err = request_firmware(&adev->gfx.mec2_fw, fw_name, adev->dev); + } + } else { + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2.bin", chip_name); + err = request_firmware(&adev->gfx.mec2_fw, fw_name, adev->dev); + } if (!err) { err = amdgpu_ucode_validate(adev->gfx.mec2_fw); if (err) @@ -2053,6 +2113,7 @@ static int gfx_v8_0_sw_fini(void *handle) amdgpu_gfx_compute_mqd_sw_fini(adev); amdgpu_gfx_kiq_free_ring(&adev->gfx.kiq.ring, &adev->gfx.kiq.irq); amdgpu_gfx_kiq_fini(adev); + amdgpu_bo_free_kernel(&adev->virt.csa_obj, &adev->virt.csa_vmid0_addr, NULL); gfx_v8_0_mec_fini(adev); gfx_v8_0_rlc_fini(adev); @@ -4577,12 +4638,10 @@ static int gfx_v8_0_mqd_init(struct amdgpu_ring *ring) mqd->compute_static_thread_mgmt_se2 = 0xffffffff; mqd->compute_static_thread_mgmt_se3 = 0xffffffff; mqd->compute_misc_reserved = 0x00000003; - if (!(adev->flags & AMD_IS_APU)) { - mqd->dynamic_cu_mask_addr_lo = lower_32_bits(ring->mqd_gpu_addr - + offsetof(struct vi_mqd_allocation, dynamic_cu_mask)); - mqd->dynamic_cu_mask_addr_hi = upper_32_bits(ring->mqd_gpu_addr - + offsetof(struct vi_mqd_allocation, dynamic_cu_mask)); - } + mqd->dynamic_cu_mask_addr_lo = lower_32_bits(ring->mqd_gpu_addr + + offsetof(struct vi_mqd_allocation, dynamic_cu_mask)); + mqd->dynamic_cu_mask_addr_hi = upper_32_bits(ring->mqd_gpu_addr + + offsetof(struct vi_mqd_allocation, dynamic_cu_mask)); eop_base_addr = ring->eop_gpu_addr >> 8; mqd->cp_hqd_eop_base_addr_lo = eop_base_addr; mqd->cp_hqd_eop_base_addr_hi = upper_32_bits(eop_base_addr); @@ -4753,7 +4812,7 @@ static int gfx_v8_0_kiq_init_queue(struct amdgpu_ring *ring) gfx_v8_0_kiq_setting(ring); - if (adev->gfx.in_reset) { /* for GPU_RESET case */ + if (adev->in_sriov_reset) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct vi_mqd_allocation)); @@ -4790,7 +4849,7 @@ static int gfx_v8_0_kcq_init_queue(struct amdgpu_ring *ring) struct vi_mqd *mqd = ring->mqd_ptr; int mqd_idx = ring - &adev->gfx.compute_ring[0]; - if (!adev->gfx.in_reset && !adev->gfx.in_suspend) { + if (!adev->in_sriov_reset && !adev->gfx.in_suspend) { memset((void *)mqd, 0, sizeof(struct vi_mqd_allocation)); ((struct vi_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF; ((struct vi_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF; @@ -4802,7 +4861,7 @@ static int gfx_v8_0_kcq_init_queue(struct amdgpu_ring *ring) if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(struct vi_mqd_allocation)); - } else if (adev->gfx.in_reset) { /* for GPU_RESET case */ + } else if (adev->in_sriov_reset) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct vi_mqd_allocation)); @@ -4975,12 +5034,69 @@ static int gfx_v8_0_hw_init(void *handle) return r; } +static int gfx_v8_0_kcq_disable(struct amdgpu_ring *kiq_ring,struct amdgpu_ring *ring) +{ + struct amdgpu_device *adev = kiq_ring->adev; + uint32_t scratch, tmp = 0; + int r, i; + + r = amdgpu_gfx_scratch_get(adev, &scratch); + if (r) { + DRM_ERROR("Failed to get scratch reg (%d).\n", r); + return r; + } + WREG32(scratch, 0xCAFEDEAD); + + r = amdgpu_ring_alloc(kiq_ring, 10); + if (r) { + DRM_ERROR("Failed to lock KIQ (%d).\n", r); + amdgpu_gfx_scratch_free(adev, scratch); + return r; + } + + /* unmap queues */ + amdgpu_ring_write(kiq_ring, PACKET3(PACKET3_UNMAP_QUEUES, 4)); + amdgpu_ring_write(kiq_ring, /* Q_sel: 0, vmid: 0, engine: 0, num_Q: 1 */ + PACKET3_UNMAP_QUEUES_ACTION(1) | /* RESET_QUEUES */ + PACKET3_UNMAP_QUEUES_QUEUE_SEL(0) | + PACKET3_UNMAP_QUEUES_ENGINE_SEL(0) | + PACKET3_UNMAP_QUEUES_NUM_QUEUES(1)); + amdgpu_ring_write(kiq_ring, PACKET3_UNMAP_QUEUES_DOORBELL_OFFSET0(ring->doorbell_index)); + amdgpu_ring_write(kiq_ring, 0); + amdgpu_ring_write(kiq_ring, 0); + amdgpu_ring_write(kiq_ring, 0); + /* write to scratch for completion */ + amdgpu_ring_write(kiq_ring, PACKET3(PACKET3_SET_UCONFIG_REG, 1)); + amdgpu_ring_write(kiq_ring, (scratch - PACKET3_SET_UCONFIG_REG_START)); + amdgpu_ring_write(kiq_ring, 0xDEADBEEF); + amdgpu_ring_commit(kiq_ring); + + for (i = 0; i < adev->usec_timeout; i++) { + tmp = RREG32(scratch); + if (tmp == 0xDEADBEEF) + break; + DRM_UDELAY(1); + } + if (i >= adev->usec_timeout) { + DRM_ERROR("KCQ disabled failed (scratch(0x%04X)=0x%08X)\n", scratch, tmp); + r = -EINVAL; + } + amdgpu_gfx_scratch_free(adev, scratch); + return r; +} + static int gfx_v8_0_hw_fini(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + int i; amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0); amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0); + + /* disable KCQ to avoid CPC touch memory not valid anymore */ + for (i = 0; i < adev->gfx.num_compute_rings; i++) + gfx_v8_0_kcq_disable(&adev->gfx.kiq.ring, &adev->gfx.compute_ring[i]); + if (amdgpu_sriov_vf(adev)) { pr_debug("For SRIOV client, shouldn't do anything.\n"); return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 69182ee..deeaee14 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -66,38 +66,70 @@ MODULE_FIRMWARE("amdgpu/raven_rlc.bin"); static const struct amdgpu_gds_reg_offset amdgpu_gds_reg_offset[] = { - {SOC15_REG_OFFSET(GC, 0, mmGDS_VMID0_BASE), SOC15_REG_OFFSET(GC, 0, mmGDS_VMID0_SIZE), - SOC15_REG_OFFSET(GC, 0, mmGDS_GWS_VMID0), SOC15_REG_OFFSET(GC, 0, mmGDS_OA_VMID0)}, - {SOC15_REG_OFFSET(GC, 0, mmGDS_VMID1_BASE), SOC15_REG_OFFSET(GC, 0, mmGDS_VMID1_SIZE), - SOC15_REG_OFFSET(GC, 0, mmGDS_GWS_VMID1), SOC15_REG_OFFSET(GC, 0, mmGDS_OA_VMID1)}, - {SOC15_REG_OFFSET(GC, 0, mmGDS_VMID2_BASE), SOC15_REG_OFFSET(GC, 0, mmGDS_VMID2_SIZE), - SOC15_REG_OFFSET(GC, 0, mmGDS_GWS_VMID2), SOC15_REG_OFFSET(GC, 0, mmGDS_OA_VMID2)}, - {SOC15_REG_OFFSET(GC, 0, mmGDS_VMID3_BASE), SOC15_REG_OFFSET(GC, 0, mmGDS_VMID3_SIZE), - SOC15_REG_OFFSET(GC, 0, mmGDS_GWS_VMID3), SOC15_REG_OFFSET(GC, 0, mmGDS_OA_VMID3)}, - {SOC15_REG_OFFSET(GC, 0, mmGDS_VMID4_BASE), SOC15_REG_OFFSET(GC, 0, mmGDS_VMID4_SIZE), - SOC15_REG_OFFSET(GC, 0, mmGDS_GWS_VMID4), SOC15_REG_OFFSET(GC, 0, mmGDS_OA_VMID4)}, - {SOC15_REG_OFFSET(GC, 0, mmGDS_VMID5_BASE), SOC15_REG_OFFSET(GC, 0, mmGDS_VMID5_SIZE), - SOC15_REG_OFFSET(GC, 0, mmGDS_GWS_VMID5), SOC15_REG_OFFSET(GC, 0, mmGDS_OA_VMID5)}, - {SOC15_REG_OFFSET(GC, 0, mmGDS_VMID6_BASE), SOC15_REG_OFFSET(GC, 0, mmGDS_VMID6_SIZE), - SOC15_REG_OFFSET(GC, 0, mmGDS_GWS_VMID6), SOC15_REG_OFFSET(GC, 0, mmGDS_OA_VMID6)}, - {SOC15_REG_OFFSET(GC, 0, mmGDS_VMID7_BASE), SOC15_REG_OFFSET(GC, 0, mmGDS_VMID7_SIZE), - SOC15_REG_OFFSET(GC, 0, mmGDS_GWS_VMID7), SOC15_REG_OFFSET(GC, 0, mmGDS_OA_VMID7)}, - {SOC15_REG_OFFSET(GC, 0, mmGDS_VMID8_BASE), SOC15_REG_OFFSET(GC, 0, mmGDS_VMID8_SIZE), - SOC15_REG_OFFSET(GC, 0, mmGDS_GWS_VMID8), SOC15_REG_OFFSET(GC, 0, mmGDS_OA_VMID8)}, - {SOC15_REG_OFFSET(GC, 0, mmGDS_VMID9_BASE), SOC15_REG_OFFSET(GC, 0, mmGDS_VMID9_SIZE), - SOC15_REG_OFFSET(GC, 0, mmGDS_GWS_VMID9), SOC15_REG_OFFSET(GC, 0, mmGDS_OA_VMID9)}, - {SOC15_REG_OFFSET(GC, 0, mmGDS_VMID10_BASE), SOC15_REG_OFFSET(GC, 0, mmGDS_VMID10_SIZE), - SOC15_REG_OFFSET(GC, 0, mmGDS_GWS_VMID10), SOC15_REG_OFFSET(GC, 0, mmGDS_OA_VMID10)}, - {SOC15_REG_OFFSET(GC, 0, mmGDS_VMID11_BASE), SOC15_REG_OFFSET(GC, 0, mmGDS_VMID11_SIZE), - SOC15_REG_OFFSET(GC, 0, mmGDS_GWS_VMID11), SOC15_REG_OFFSET(GC, 0, mmGDS_OA_VMID11)}, - {SOC15_REG_OFFSET(GC, 0, mmGDS_VMID12_BASE), SOC15_REG_OFFSET(GC, 0, mmGDS_VMID12_SIZE), - SOC15_REG_OFFSET(GC, 0, mmGDS_GWS_VMID12), SOC15_REG_OFFSET(GC, 0, mmGDS_OA_VMID12)}, - {SOC15_REG_OFFSET(GC, 0, mmGDS_VMID13_BASE), SOC15_REG_OFFSET(GC, 0, mmGDS_VMID13_SIZE), - SOC15_REG_OFFSET(GC, 0, mmGDS_GWS_VMID13), SOC15_REG_OFFSET(GC, 0, mmGDS_OA_VMID13)}, - {SOC15_REG_OFFSET(GC, 0, mmGDS_VMID14_BASE), SOC15_REG_OFFSET(GC, 0, mmGDS_VMID14_SIZE), - SOC15_REG_OFFSET(GC, 0, mmGDS_GWS_VMID14), SOC15_REG_OFFSET(GC, 0, mmGDS_OA_VMID14)}, - {SOC15_REG_OFFSET(GC, 0, mmGDS_VMID15_BASE), SOC15_REG_OFFSET(GC, 0, mmGDS_VMID15_SIZE), - SOC15_REG_OFFSET(GC, 0, mmGDS_GWS_VMID15), SOC15_REG_OFFSET(GC, 0, mmGDS_OA_VMID15)} + { SOC15_REG_OFFSET(GC, 0, mmGDS_VMID0_BASE), + SOC15_REG_OFFSET(GC, 0, mmGDS_VMID0_SIZE), + SOC15_REG_OFFSET(GC, 0, mmGDS_GWS_VMID0), + SOC15_REG_OFFSET(GC, 0, mmGDS_OA_VMID0) }, + { SOC15_REG_OFFSET(GC, 0, mmGDS_VMID1_BASE), + SOC15_REG_OFFSET(GC, 0, mmGDS_VMID1_SIZE), + SOC15_REG_OFFSET(GC, 0, mmGDS_GWS_VMID1), + SOC15_REG_OFFSET(GC, 0, mmGDS_OA_VMID1) }, + { SOC15_REG_OFFSET(GC, 0, mmGDS_VMID2_BASE), + SOC15_REG_OFFSET(GC, 0, mmGDS_VMID2_SIZE), + SOC15_REG_OFFSET(GC, 0, mmGDS_GWS_VMID2), + SOC15_REG_OFFSET(GC, 0, mmGDS_OA_VMID2) }, + { SOC15_REG_OFFSET(GC, 0, mmGDS_VMID3_BASE), + SOC15_REG_OFFSET(GC, 0, mmGDS_VMID3_SIZE), + SOC15_REG_OFFSET(GC, 0, mmGDS_GWS_VMID3), + SOC15_REG_OFFSET(GC, 0, mmGDS_OA_VMID3) }, + { SOC15_REG_OFFSET(GC, 0, mmGDS_VMID4_BASE), + SOC15_REG_OFFSET(GC, 0, mmGDS_VMID4_SIZE), + SOC15_REG_OFFSET(GC, 0, mmGDS_GWS_VMID4), + SOC15_REG_OFFSET(GC, 0, mmGDS_OA_VMID4) }, + { SOC15_REG_OFFSET(GC, 0, mmGDS_VMID5_BASE), + SOC15_REG_OFFSET(GC, 0, mmGDS_VMID5_SIZE), + SOC15_REG_OFFSET(GC, 0, mmGDS_GWS_VMID5), + SOC15_REG_OFFSET(GC, 0, mmGDS_OA_VMID5) }, + { SOC15_REG_OFFSET(GC, 0, mmGDS_VMID6_BASE), + SOC15_REG_OFFSET(GC, 0, mmGDS_VMID6_SIZE), + SOC15_REG_OFFSET(GC, 0, mmGDS_GWS_VMID6), + SOC15_REG_OFFSET(GC, 0, mmGDS_OA_VMID6) }, + { SOC15_REG_OFFSET(GC, 0, mmGDS_VMID7_BASE), + SOC15_REG_OFFSET(GC, 0, mmGDS_VMID7_SIZE), + SOC15_REG_OFFSET(GC, 0, mmGDS_GWS_VMID7), + SOC15_REG_OFFSET(GC, 0, mmGDS_OA_VMID7) }, + { SOC15_REG_OFFSET(GC, 0, mmGDS_VMID8_BASE), + SOC15_REG_OFFSET(GC, 0, mmGDS_VMID8_SIZE), + SOC15_REG_OFFSET(GC, 0, mmGDS_GWS_VMID8), + SOC15_REG_OFFSET(GC, 0, mmGDS_OA_VMID8) }, + { SOC15_REG_OFFSET(GC, 0, mmGDS_VMID9_BASE), + SOC15_REG_OFFSET(GC, 0, mmGDS_VMID9_SIZE), + SOC15_REG_OFFSET(GC, 0, mmGDS_GWS_VMID9), + SOC15_REG_OFFSET(GC, 0, mmGDS_OA_VMID9) }, + { SOC15_REG_OFFSET(GC, 0, mmGDS_VMID10_BASE), + SOC15_REG_OFFSET(GC, 0, mmGDS_VMID10_SIZE), + SOC15_REG_OFFSET(GC, 0, mmGDS_GWS_VMID10), + SOC15_REG_OFFSET(GC, 0, mmGDS_OA_VMID10) }, + { SOC15_REG_OFFSET(GC, 0, mmGDS_VMID11_BASE), + SOC15_REG_OFFSET(GC, 0, mmGDS_VMID11_SIZE), + SOC15_REG_OFFSET(GC, 0, mmGDS_GWS_VMID11), + SOC15_REG_OFFSET(GC, 0, mmGDS_OA_VMID11) }, + { SOC15_REG_OFFSET(GC, 0, mmGDS_VMID12_BASE), + SOC15_REG_OFFSET(GC, 0, mmGDS_VMID12_SIZE), + SOC15_REG_OFFSET(GC, 0, mmGDS_GWS_VMID12), + SOC15_REG_OFFSET(GC, 0, mmGDS_OA_VMID12)}, + { SOC15_REG_OFFSET(GC, 0, mmGDS_VMID13_BASE), + SOC15_REG_OFFSET(GC, 0, mmGDS_VMID13_SIZE), + SOC15_REG_OFFSET(GC, 0, mmGDS_GWS_VMID13), + SOC15_REG_OFFSET(GC, 0, mmGDS_OA_VMID13) }, + { SOC15_REG_OFFSET(GC, 0, mmGDS_VMID14_BASE), + SOC15_REG_OFFSET(GC, 0, mmGDS_VMID14_SIZE), + SOC15_REG_OFFSET(GC, 0, mmGDS_GWS_VMID14), + SOC15_REG_OFFSET(GC, 0, mmGDS_OA_VMID14) }, + { SOC15_REG_OFFSET(GC, 0, mmGDS_VMID15_BASE), + SOC15_REG_OFFSET(GC, 0, mmGDS_VMID15_SIZE), + SOC15_REG_OFFSET(GC, 0, mmGDS_GWS_VMID15), + SOC15_REG_OFFSET(GC, 0, mmGDS_OA_VMID15) } }; static const u32 golden_settings_gc_9_0[] = @@ -352,6 +384,25 @@ err1: return r; } + +static void gfx_v9_0_free_microcode(struct amdgpu_device *adev) +{ + release_firmware(adev->gfx.pfp_fw); + adev->gfx.pfp_fw = NULL; + release_firmware(adev->gfx.me_fw); + adev->gfx.me_fw = NULL; + release_firmware(adev->gfx.ce_fw); + adev->gfx.ce_fw = NULL; + release_firmware(adev->gfx.rlc_fw); + adev->gfx.rlc_fw = NULL; + release_firmware(adev->gfx.mec_fw); + adev->gfx.mec_fw = NULL; + release_firmware(adev->gfx.mec2_fw); + adev->gfx.mec2_fw = NULL; + + kfree(adev->gfx.rlc.register_list_format); +} + static int gfx_v9_0_init_microcode(struct amdgpu_device *adev) { const char *chip_name; @@ -1120,30 +1171,22 @@ static int gfx_v9_0_ngg_en(struct amdgpu_device *adev) { struct amdgpu_ring *ring = &adev->gfx.gfx_ring[0]; int r; - u32 data; - u32 size; - u32 base; + u32 data, base; if (!amdgpu_ngg) return 0; /* Program buffer size */ - data = 0; - size = adev->gfx.ngg.buf[NGG_PRIM].size / 256; - data = REG_SET_FIELD(data, WD_BUF_RESOURCE_1, INDEX_BUF_SIZE, size); - - size = adev->gfx.ngg.buf[NGG_POS].size / 256; - data = REG_SET_FIELD(data, WD_BUF_RESOURCE_1, POS_BUF_SIZE, size); - + data = REG_SET_FIELD(0, WD_BUF_RESOURCE_1, INDEX_BUF_SIZE, + adev->gfx.ngg.buf[NGG_PRIM].size >> 8); + data = REG_SET_FIELD(data, WD_BUF_RESOURCE_1, POS_BUF_SIZE, + adev->gfx.ngg.buf[NGG_POS].size >> 8); WREG32_SOC15(GC, 0, mmWD_BUF_RESOURCE_1, data); - data = 0; - size = adev->gfx.ngg.buf[NGG_CNTL].size / 256; - data = REG_SET_FIELD(data, WD_BUF_RESOURCE_2, CNTL_SB_BUF_SIZE, size); - - size = adev->gfx.ngg.buf[NGG_PARAM].size / 1024; - data = REG_SET_FIELD(data, WD_BUF_RESOURCE_2, PARAM_BUF_SIZE, size); - + data = REG_SET_FIELD(0, WD_BUF_RESOURCE_2, CNTL_SB_BUF_SIZE, + adev->gfx.ngg.buf[NGG_CNTL].size >> 8); + data = REG_SET_FIELD(data, WD_BUF_RESOURCE_2, PARAM_BUF_SIZE, + adev->gfx.ngg.buf[NGG_PARAM].size >> 10); WREG32_SOC15(GC, 0, mmWD_BUF_RESOURCE_2, data); /* Program buffer base address */ @@ -1306,7 +1349,10 @@ static int gfx_v9_0_sw_init(void *handle) for (i = 0; i < adev->gfx.num_gfx_rings; i++) { ring = &adev->gfx.gfx_ring[i]; ring->ring_obj = NULL; - sprintf(ring->name, "gfx"); + if (!i) + sprintf(ring->name, "gfx"); + else + sprintf(ring->name, "gfx_%d", i); ring->use_doorbell = true; ring->doorbell_index = AMDGPU_DOORBELL64_GFX_RING0 << 1; r = amdgpu_ring_init(adev, ring, 1024, @@ -1346,7 +1392,7 @@ static int gfx_v9_0_sw_init(void *handle) return r; /* create MQD for all compute queues as wel as KIQ for SRIOV case */ - r = amdgpu_gfx_compute_mqd_sw_init(adev, sizeof(struct v9_mqd)); + r = amdgpu_gfx_compute_mqd_sw_init(adev, sizeof(struct v9_mqd_allocation)); if (r) return r; @@ -1398,9 +1444,11 @@ static int gfx_v9_0_sw_fini(void *handle) amdgpu_gfx_compute_mqd_sw_fini(adev); amdgpu_gfx_kiq_free_ring(&adev->gfx.kiq.ring, &adev->gfx.kiq.irq); amdgpu_gfx_kiq_fini(adev); + amdgpu_bo_free_kernel(&adev->virt.csa_obj, &adev->virt.csa_vmid0_addr, NULL); gfx_v9_0_mec_fini(adev); gfx_v9_0_ngg_fini(adev); + gfx_v9_0_free_microcode(adev); return 0; } @@ -1740,11 +1788,7 @@ static int gfx_v9_0_init_rlc_save_restore_list(struct amdgpu_device *adev) static void gfx_v9_0_enable_save_restore_machine(struct amdgpu_device *adev) { - u32 tmp = 0; - - tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_SRM_CNTL)); - tmp |= RLC_SRM_CNTL__SRM_ENABLE_MASK; - WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_SRM_CNTL), tmp); + WREG32_FIELD15(GC, 0, RLC_SRM_CNTL, SRM_ENABLE, 1); } static void pwr_10_0_gfxip_control_over_cgpg(struct amdgpu_device *adev, @@ -1822,16 +1866,11 @@ static void gfx_v9_0_enable_sck_slow_down_on_power_up(struct amdgpu_device *adev uint32_t default_data = 0; default_data = data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_PG_CNTL)); - - if (enable == true) { - data |= RLC_PG_CNTL__SMU_CLK_SLOWDOWN_ON_PU_ENABLE_MASK; - if (default_data != data) - WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_PG_CNTL), data); - } else { - data &= ~RLC_PG_CNTL__SMU_CLK_SLOWDOWN_ON_PU_ENABLE_MASK; - if(default_data != data) - WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_PG_CNTL), data); - } + data = REG_SET_FIELD(data, RLC_PG_CNTL, + SMU_CLK_SLOWDOWN_ON_PU_ENABLE, + enable ? 1 : 0); + if (default_data != data) + WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_PG_CNTL), data); } static void gfx_v9_0_enable_sck_slow_down_on_power_down(struct amdgpu_device *adev, @@ -1841,16 +1880,11 @@ static void gfx_v9_0_enable_sck_slow_down_on_power_down(struct amdgpu_device *ad uint32_t default_data = 0; default_data = data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_PG_CNTL)); - - if (enable == true) { - data |= RLC_PG_CNTL__SMU_CLK_SLOWDOWN_ON_PD_ENABLE_MASK; - if(default_data != data) - WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_PG_CNTL), data); - } else { - data &= ~RLC_PG_CNTL__SMU_CLK_SLOWDOWN_ON_PD_ENABLE_MASK; - if(default_data != data) - WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_PG_CNTL), data); - } + data = REG_SET_FIELD(data, RLC_PG_CNTL, + SMU_CLK_SLOWDOWN_ON_PD_ENABLE, + enable ? 1 : 0); + if(default_data != data) + WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_PG_CNTL), data); } static void gfx_v9_0_enable_cp_power_gating(struct amdgpu_device *adev, @@ -1860,16 +1894,11 @@ static void gfx_v9_0_enable_cp_power_gating(struct amdgpu_device *adev, uint32_t default_data = 0; default_data = data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_PG_CNTL)); - - if (enable == true) { - data &= ~RLC_PG_CNTL__CP_PG_DISABLE_MASK; - if(default_data != data) - WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_PG_CNTL), data); - } else { - data |= RLC_PG_CNTL__CP_PG_DISABLE_MASK; - if(default_data != data) - WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_PG_CNTL), data); - } + data = REG_SET_FIELD(data, RLC_PG_CNTL, + CP_PG_DISABLE, + enable ? 0 : 1); + if(default_data != data) + WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_PG_CNTL), data); } static void gfx_v9_0_enable_gfx_cg_power_gating(struct amdgpu_device *adev, @@ -1878,10 +1907,9 @@ static void gfx_v9_0_enable_gfx_cg_power_gating(struct amdgpu_device *adev, uint32_t data, default_data; default_data = data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_PG_CNTL)); - if (enable == true) - data |= RLC_PG_CNTL__GFX_POWER_GATING_ENABLE_MASK; - else - data &= ~RLC_PG_CNTL__GFX_POWER_GATING_ENABLE_MASK; + data = REG_SET_FIELD(data, RLC_PG_CNTL, + GFX_POWER_GATING_ENABLE, + enable ? 1 : 0); if(default_data != data) WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_PG_CNTL), data); } @@ -1892,10 +1920,9 @@ static void gfx_v9_0_enable_gfx_pipeline_powergating(struct amdgpu_device *adev, uint32_t data, default_data; default_data = data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_PG_CNTL)); - if (enable == true) - data |= RLC_PG_CNTL__GFX_PIPELINE_PG_ENABLE_MASK; - else - data &= ~RLC_PG_CNTL__GFX_PIPELINE_PG_ENABLE_MASK; + data = REG_SET_FIELD(data, RLC_PG_CNTL, + GFX_PIPELINE_PG_ENABLE, + enable ? 1 : 0); if(default_data != data) WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_PG_CNTL), data); @@ -1910,10 +1937,9 @@ static void gfx_v9_0_enable_gfx_static_mg_power_gating(struct amdgpu_device *ade uint32_t data, default_data; default_data = data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_PG_CNTL)); - if (enable == true) - data |= RLC_PG_CNTL__STATIC_PER_CU_PG_ENABLE_MASK; - else - data &= ~RLC_PG_CNTL__STATIC_PER_CU_PG_ENABLE_MASK; + data = REG_SET_FIELD(data, RLC_PG_CNTL, + STATIC_PER_CU_PG_ENABLE, + enable ? 1 : 0); if(default_data != data) WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_PG_CNTL), data); } @@ -1924,10 +1950,9 @@ static void gfx_v9_0_enable_gfx_dynamic_mg_power_gating(struct amdgpu_device *ad uint32_t data, default_data; default_data = data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_PG_CNTL)); - if (enable == true) - data |= RLC_PG_CNTL__DYN_PER_CU_PG_ENABLE_MASK; - else - data &= ~RLC_PG_CNTL__DYN_PER_CU_PG_ENABLE_MASK; + data = REG_SET_FIELD(data, RLC_PG_CNTL, + DYN_PER_CU_PG_ENABLE, + enable ? 1 : 0); if(default_data != data) WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_PG_CNTL), data); } @@ -1967,13 +1992,8 @@ static void gfx_v9_0_init_pg(struct amdgpu_device *adev) void gfx_v9_0_rlc_stop(struct amdgpu_device *adev) { - u32 tmp = RREG32_SOC15(GC, 0, mmRLC_CNTL); - - tmp = REG_SET_FIELD(tmp, RLC_CNTL, RLC_ENABLE_F32, 0); - WREG32_SOC15(GC, 0, mmRLC_CNTL, tmp); - + WREG32_FIELD15(GC, 0, RLC_CNTL, RLC_ENABLE_F32, 0); gfx_v9_0_enable_gui_idle_interrupt(adev, false); - gfx_v9_0_wait_for_rlc_serdes(adev); } @@ -2045,8 +2065,10 @@ static int gfx_v9_0_rlc_resume(struct amdgpu_device *adev) { int r; - if (amdgpu_sriov_vf(adev)) + if (amdgpu_sriov_vf(adev)) { + gfx_v9_0_init_csb(adev); return 0; + } gfx_v9_0_rlc_stop(adev); @@ -2463,6 +2485,13 @@ static int gfx_v9_0_mqd_init(struct amdgpu_ring *ring) mqd->compute_static_thread_mgmt_se3 = 0xffffffff; mqd->compute_misc_reserved = 0x00000003; + mqd->dynamic_cu_mask_addr_lo = + lower_32_bits(ring->mqd_gpu_addr + + offsetof(struct v9_mqd_allocation, dynamic_cu_mask)); + mqd->dynamic_cu_mask_addr_hi = + upper_32_bits(ring->mqd_gpu_addr + + offsetof(struct v9_mqd_allocation, dynamic_cu_mask)); + eop_base_addr = ring->eop_gpu_addr >> 8; mqd->cp_hqd_eop_base_addr_lo = eop_base_addr; mqd->cp_hqd_eop_base_addr_hi = upper_32_bits(eop_base_addr); @@ -2486,10 +2515,10 @@ static int gfx_v9_0_mqd_init(struct amdgpu_ring *ring) DOORBELL_SOURCE, 0); tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, DOORBELL_HIT, 0); - } - else + } else { tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, DOORBELL_EN, 0); + } mqd->cp_hqd_pq_doorbell_control = tmp; @@ -2692,10 +2721,10 @@ static int gfx_v9_0_kiq_init_queue(struct amdgpu_ring *ring) gfx_v9_0_kiq_setting(ring); - if (adev->gfx.in_reset) { /* for GPU_RESET case */ + if (adev->in_sriov_reset) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) - memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(*mqd)); + memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct v9_mqd_allocation)); /* reset ring buffer */ ring->wptr = 0; @@ -2707,7 +2736,9 @@ static int gfx_v9_0_kiq_init_queue(struct amdgpu_ring *ring) soc15_grbm_select(adev, 0, 0, 0, 0); mutex_unlock(&adev->srbm_mutex); } else { - memset((void *)mqd, 0, sizeof(*mqd)); + memset((void *)mqd, 0, sizeof(struct v9_mqd_allocation)); + ((struct v9_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF; + ((struct v9_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF; mutex_lock(&adev->srbm_mutex); soc15_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0); gfx_v9_0_mqd_init(ring); @@ -2716,7 +2747,7 @@ static int gfx_v9_0_kiq_init_queue(struct amdgpu_ring *ring) mutex_unlock(&adev->srbm_mutex); if (adev->gfx.mec.mqd_backup[mqd_idx]) - memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(*mqd)); + memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(struct v9_mqd_allocation)); } return 0; @@ -2728,8 +2759,10 @@ static int gfx_v9_0_kcq_init_queue(struct amdgpu_ring *ring) struct v9_mqd *mqd = ring->mqd_ptr; int mqd_idx = ring - &adev->gfx.compute_ring[0]; - if (!adev->gfx.in_reset && !adev->gfx.in_suspend) { - memset((void *)mqd, 0, sizeof(*mqd)); + if (!adev->in_sriov_reset && !adev->gfx.in_suspend) { + memset((void *)mqd, 0, sizeof(struct v9_mqd_allocation)); + ((struct v9_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF; + ((struct v9_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF; mutex_lock(&adev->srbm_mutex); soc15_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0); gfx_v9_0_mqd_init(ring); @@ -2737,11 +2770,11 @@ static int gfx_v9_0_kcq_init_queue(struct amdgpu_ring *ring) mutex_unlock(&adev->srbm_mutex); if (adev->gfx.mec.mqd_backup[mqd_idx]) - memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(*mqd)); - } else if (adev->gfx.in_reset) { /* for GPU_RESET case */ + memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(struct v9_mqd_allocation)); + } else if (adev->in_sriov_reset) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) - memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(*mqd)); + memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct v9_mqd_allocation)); /* reset ring buffer */ ring->wptr = 0; @@ -2882,12 +2915,70 @@ static int gfx_v9_0_hw_init(void *handle) return r; } +static int gfx_v9_0_kcq_disable(struct amdgpu_ring *kiq_ring,struct amdgpu_ring *ring) +{ + struct amdgpu_device *adev = kiq_ring->adev; + uint32_t scratch, tmp = 0; + int r, i; + + r = amdgpu_gfx_scratch_get(adev, &scratch); + if (r) { + DRM_ERROR("Failed to get scratch reg (%d).\n", r); + return r; + } + WREG32(scratch, 0xCAFEDEAD); + + r = amdgpu_ring_alloc(kiq_ring, 10); + if (r) { + DRM_ERROR("Failed to lock KIQ (%d).\n", r); + amdgpu_gfx_scratch_free(adev, scratch); + return r; + } + + /* unmap queues */ + amdgpu_ring_write(kiq_ring, PACKET3(PACKET3_UNMAP_QUEUES, 4)); + amdgpu_ring_write(kiq_ring, /* Q_sel: 0, vmid: 0, engine: 0, num_Q: 1 */ + PACKET3_UNMAP_QUEUES_ACTION(1) | /* RESET_QUEUES */ + PACKET3_UNMAP_QUEUES_QUEUE_SEL(0) | + PACKET3_UNMAP_QUEUES_ENGINE_SEL(0) | + PACKET3_UNMAP_QUEUES_NUM_QUEUES(1)); + amdgpu_ring_write(kiq_ring, PACKET3_UNMAP_QUEUES_DOORBELL_OFFSET0(ring->doorbell_index)); + amdgpu_ring_write(kiq_ring, 0); + amdgpu_ring_write(kiq_ring, 0); + amdgpu_ring_write(kiq_ring, 0); + /* write to scratch for completion */ + amdgpu_ring_write(kiq_ring, PACKET3(PACKET3_SET_UCONFIG_REG, 1)); + amdgpu_ring_write(kiq_ring, (scratch - PACKET3_SET_UCONFIG_REG_START)); + amdgpu_ring_write(kiq_ring, 0xDEADBEEF); + amdgpu_ring_commit(kiq_ring); + + for (i = 0; i < adev->usec_timeout; i++) { + tmp = RREG32(scratch); + if (tmp == 0xDEADBEEF) + break; + DRM_UDELAY(1); + } + if (i >= adev->usec_timeout) { + DRM_ERROR("KCQ disabled failed (scratch(0x%04X)=0x%08X)\n", scratch, tmp); + r = -EINVAL; + } + amdgpu_gfx_scratch_free(adev, scratch); + return r; +} + + static int gfx_v9_0_hw_fini(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + int i; amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0); amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0); + + /* disable KCQ to avoid CPC touch memory not valid anymore */ + for (i = 0; i < adev->gfx.num_compute_rings; i++) + gfx_v9_0_kcq_disable(&adev->gfx.kiq.ring, &adev->gfx.compute_ring[i]); + if (amdgpu_sriov_vf(adev)) { pr_debug("For SRIOV client, shouldn't do anything.\n"); return 0; @@ -2930,15 +3021,10 @@ static bool gfx_v9_0_is_idle(void *handle) static int gfx_v9_0_wait_for_idle(void *handle) { unsigned i; - u32 tmp; struct amdgpu_device *adev = (struct amdgpu_device *)handle; for (i = 0; i < adev->usec_timeout; i++) { - /* read MC_STATUS */ - tmp = RREG32_SOC15(GC, 0, mmGRBM_STATUS) & - GRBM_STATUS__GUI_ACTIVE_MASK; - - if (!REG_GET_FIELD(tmp, GRBM_STATUS, GUI_ACTIVE)) + if (gfx_v9_0_is_idle(handle)) return 0; udelay(1); } @@ -3499,7 +3585,9 @@ static void gfx_v9_0_ring_emit_hdp_flush(struct amdgpu_ring *ring) u32 ref_and_mask, reg_mem_engine; struct nbio_hdp_flush_reg *nbio_hf_reg; - if (ring->adev->asic_type == CHIP_VEGA10) + if (ring->adev->flags & AMD_IS_APU) + nbio_hf_reg = &nbio_v7_0_hdp_flush_reg; + else nbio_hf_reg = &nbio_v6_1_hdp_flush_reg; if (ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE) { @@ -3528,7 +3616,7 @@ static void gfx_v9_0_ring_emit_hdp_flush(struct amdgpu_ring *ring) static void gfx_v9_0_ring_emit_hdp_invalidate(struct amdgpu_ring *ring) { gfx_v9_0_write_data_to_reg(ring, 0, true, - SOC15_REG_OFFSET(HDP, 0, mmHDP_DEBUG0), 1); + SOC15_REG_OFFSET(HDP, 0, mmHDP_READ_CACHE_INVALIDATE), 1); } static void gfx_v9_0_ring_emit_ib_gfx(struct amdgpu_ring *ring, @@ -3757,6 +3845,12 @@ static void gfx_v9_0_ring_emit_de_meta(struct amdgpu_ring *ring) amdgpu_ring_write_multiple(ring, (void *)&de_payload, sizeof(de_payload) >> 2); } +static void gfx_v9_0_ring_emit_tmz(struct amdgpu_ring *ring, bool start) +{ + amdgpu_ring_write(ring, PACKET3(PACKET3_FRAME_CONTROL, 0)); + amdgpu_ring_write(ring, FRAME_CMD(start ? 0 : 1)); /* frame_end */ +} + static void gfx_v9_ring_emit_cntxcntl(struct amdgpu_ring *ring, uint32_t flags) { uint32_t dw2 = 0; @@ -3764,6 +3858,8 @@ static void gfx_v9_ring_emit_cntxcntl(struct amdgpu_ring *ring, uint32_t flags) if (amdgpu_sriov_vf(ring->adev)) gfx_v9_0_ring_emit_ce_meta(ring); + gfx_v9_0_ring_emit_tmz(ring, true); + dw2 |= 0x80000000; /* set load_enable otherwise this package is just NOPs */ if (flags & AMDGPU_HAVE_CTX_SWITCH) { /* set load_global_config & load_global_uconfig */ @@ -3814,12 +3910,6 @@ static void gfx_v9_0_ring_emit_patch_cond_exec(struct amdgpu_ring *ring, unsigne ring->ring[offset] = (ring->ring_size>>2) - offset + cur; } -static void gfx_v9_0_ring_emit_tmz(struct amdgpu_ring *ring, bool start) -{ - amdgpu_ring_write(ring, PACKET3(PACKET3_FRAME_CONTROL, 0)); - amdgpu_ring_write(ring, FRAME_CMD(start ? 0 : 1)); /* frame_end */ -} - static void gfx_v9_0_ring_emit_rreg(struct amdgpu_ring *ring, uint32_t reg) { struct amdgpu_device *adev = ring->adev; diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c index 6c8040e..c17996e 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c @@ -319,6 +319,12 @@ void gfxhub_v1_0_set_fault_enable_default(struct amdgpu_device *adev, WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value); tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL, EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value); + if (!value) { + tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL, + CRASH_ON_NO_RETRY_FAULT, 1); + tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL, + CRASH_ON_RETRY_FAULT, 1); + } WREG32_SOC15(GC, 0, mmVM_L2_PROTECTION_FAULT_CNTL, tmp); } diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c index 5be9c83..f4603a7 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c @@ -831,7 +831,7 @@ static int gmc_v6_0_sw_init(void *handle) if (r) return r; - amdgpu_vm_adjust_size(adev, 64, 4); + amdgpu_vm_adjust_size(adev, 64, 9); adev->vm_manager.max_pfn = adev->vm_manager.vm_size << 18; adev->mc.mc_mask = 0xffffffffffULL; @@ -901,6 +901,8 @@ static int gmc_v6_0_sw_fini(void *handle) gmc_v6_0_gart_fini(adev); amdgpu_gem_force_release(adev); amdgpu_bo_fini(adev); + release_firmware(adev->mc.fw); + adev->mc.fw = NULL; return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index eace9e7..b0528ca 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c @@ -970,7 +970,7 @@ static int gmc_v7_0_sw_init(void *handle) * Currently set to 4GB ((1 << 20) 4k pages). * Max GPUVM size for cayman and SI is 40 bits. */ - amdgpu_vm_adjust_size(adev, 64, 4); + amdgpu_vm_adjust_size(adev, 64, 9); adev->vm_manager.max_pfn = adev->vm_manager.vm_size << 18; /* Set the internal MC address mask @@ -1050,6 +1050,8 @@ static int gmc_v7_0_sw_fini(void *handle) gmc_v7_0_gart_fini(adev); amdgpu_gem_force_release(adev); amdgpu_bo_fini(adev); + release_firmware(adev->mc.fw); + adev->mc.fw = NULL; return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index 3b3326d..f368cfe 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -1067,7 +1067,7 @@ static int gmc_v8_0_sw_init(void *handle) * Currently set to 4GB ((1 << 20) 4k pages). * Max GPUVM size for cayman and SI is 40 bits. */ - amdgpu_vm_adjust_size(adev, 64, 4); + amdgpu_vm_adjust_size(adev, 64, 9); adev->vm_manager.max_pfn = adev->vm_manager.vm_size << 18; /* Set the internal MC address mask @@ -1147,6 +1147,8 @@ static int gmc_v8_0_sw_fini(void *handle) gmc_v8_0_gart_fini(adev); amdgpu_gem_force_release(adev); amdgpu_bo_fini(adev); + release_firmware(adev->mc.fw); + adev->mc.fw = NULL; return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index d04d0b1..6216993 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -32,6 +32,8 @@ #include "vega10/DC/dce_12_0_offset.h" #include "vega10/DC/dce_12_0_sh_mask.h" #include "vega10/vega10_enum.h" +#include "vega10/MMHUB/mmhub_1_0_offset.h" +#include "vega10/ATHUB/athub_1_0_offset.h" #include "soc15_common.h" @@ -71,13 +73,25 @@ static const u32 golden_settings_vega10_hdp[] = 0xf6e, 0x0fffffff, 0x00000000, }; +static const u32 golden_settings_mmhub_1_0_0[] = +{ + SOC15_REG_OFFSET(MMHUB, 0, mmDAGB1_WRCLI2), 0x00000007, 0xfe5fe0fa, + SOC15_REG_OFFSET(MMHUB, 0, mmMMEA1_DRAM_WR_CLI2GRP_MAP0), 0x00000030, 0x55555565 +}; + +static const u32 golden_settings_athub_1_0_0[] = +{ + SOC15_REG_OFFSET(ATHUB, 0, mmRPB_ARB_CNTL), 0x0000ff00, 0x00000800, + SOC15_REG_OFFSET(ATHUB, 0, mmRPB_ARB_CNTL2), 0x00ff00ff, 0x00080008 +}; + static int gmc_v9_0_vm_fault_interrupt_state(struct amdgpu_device *adev, struct amdgpu_irq_src *src, unsigned type, enum amdgpu_interrupt_state state) { struct amdgpu_vmhub *hub; - u32 tmp, reg, bits, i; + u32 tmp, reg, bits, i, j; bits = VM_CONTEXT1_CNTL__RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | VM_CONTEXT1_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | @@ -89,43 +103,26 @@ static int gmc_v9_0_vm_fault_interrupt_state(struct amdgpu_device *adev, switch (state) { case AMDGPU_IRQ_STATE_DISABLE: - /* MM HUB */ - hub = &adev->vmhub[AMDGPU_MMHUB]; - for (i = 0; i< 16; i++) { - reg = hub->vm_context0_cntl + i; - tmp = RREG32(reg); - tmp &= ~bits; - WREG32(reg, tmp); - } - - /* GFX HUB */ - hub = &adev->vmhub[AMDGPU_GFXHUB]; - for (i = 0; i < 16; i++) { - reg = hub->vm_context0_cntl + i; - tmp = RREG32(reg); - tmp &= ~bits; - WREG32(reg, tmp); + for (j = 0; j < AMDGPU_MAX_VMHUBS; j++) { + hub = &adev->vmhub[j]; + for (i = 0; i < 16; i++) { + reg = hub->vm_context0_cntl + i; + tmp = RREG32(reg); + tmp &= ~bits; + WREG32(reg, tmp); + } } break; case AMDGPU_IRQ_STATE_ENABLE: - /* MM HUB */ - hub = &adev->vmhub[AMDGPU_MMHUB]; - for (i = 0; i< 16; i++) { - reg = hub->vm_context0_cntl + i; - tmp = RREG32(reg); - tmp |= bits; - WREG32(reg, tmp); - } - - /* GFX HUB */ - hub = &adev->vmhub[AMDGPU_GFXHUB]; - for (i = 0; i < 16; i++) { - reg = hub->vm_context0_cntl + i; - tmp = RREG32(reg); - tmp |= bits; - WREG32(reg, tmp); + for (j = 0; j < AMDGPU_MAX_VMHUBS; j++) { + hub = &adev->vmhub[j]; + for (i = 0; i < 16; i++) { + reg = hub->vm_context0_cntl + i; + tmp = RREG32(reg); + tmp |= bits; + WREG32(reg, tmp); + } } - break; default: break; } @@ -682,8 +679,17 @@ static void gmc_v9_0_init_golden_registers(struct amdgpu_device *adev) { switch (adev->asic_type) { case CHIP_VEGA10: + amdgpu_program_register_sequence(adev, + golden_settings_mmhub_1_0_0, + (const u32)ARRAY_SIZE(golden_settings_mmhub_1_0_0)); + amdgpu_program_register_sequence(adev, + golden_settings_athub_1_0_0, + (const u32)ARRAY_SIZE(golden_settings_athub_1_0_0)); break; case CHIP_RAVEN: + amdgpu_program_register_sequence(adev, + golden_settings_athub_1_0_0, + (const u32)ARRAY_SIZE(golden_settings_athub_1_0_0)); break; default: break; @@ -713,12 +719,6 @@ static int gmc_v9_0_gart_enable(struct amdgpu_device *adev) if (r) return r; - /* After HDP is initialized, flush HDP.*/ - if (adev->flags & AMD_IS_APU) - nbio_v7_0_hdp_flush(adev); - else - nbio_v6_1_hdp_flush(adev); - switch (adev->asic_type) { case CHIP_RAVEN: mmhub_v1_0_initialize_power_gating(adev); @@ -736,13 +736,16 @@ static int gmc_v9_0_gart_enable(struct amdgpu_device *adev) if (r) return r; - tmp = RREG32_SOC15(HDP, 0, mmHDP_MISC_CNTL); - tmp |= HDP_MISC_CNTL__FLUSH_INVALIDATE_CACHE_MASK; - WREG32_SOC15(HDP, 0, mmHDP_MISC_CNTL, tmp); + WREG32_FIELD15(HDP, 0, HDP_MISC_CNTL, FLUSH_INVALIDATE_CACHE, 1); tmp = RREG32_SOC15(HDP, 0, mmHDP_HOST_PATH_CNTL); WREG32_SOC15(HDP, 0, mmHDP_HOST_PATH_CNTL, tmp); + /* After HDP is initialized, flush HDP.*/ + if (adev->flags & AMD_IS_APU) + nbio_v7_0_hdp_flush(adev); + else + nbio_v6_1_hdp_flush(adev); if (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_ALWAYS) value = false; @@ -751,7 +754,6 @@ static int gmc_v9_0_gart_enable(struct amdgpu_device *adev) gfxhub_v1_0_set_fault_enable_default(adev, value); mmhub_v1_0_set_fault_enable_default(adev, value); - gmc_v9_0_gart_flush_gpu_tlb(adev, 0); DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", @@ -770,17 +772,11 @@ static int gmc_v9_0_hw_init(void *handle) gmc_v9_0_init_golden_registers(adev); if (adev->mode_info.num_crtc) { - u32 tmp; - /* Lockout access through VGA aperture*/ - tmp = RREG32_SOC15(DCE, 0, mmVGA_HDP_CONTROL); - tmp = REG_SET_FIELD(tmp, VGA_HDP_CONTROL, VGA_MEMORY_DISABLE, 1); - WREG32_SOC15(DCE, 0, mmVGA_HDP_CONTROL, tmp); + WREG32_FIELD15(DCE, 0, VGA_HDP_CONTROL, VGA_MEMORY_DISABLE, 1); /* disable VGA render */ - tmp = RREG32_SOC15(DCE, 0, mmVGA_RENDER_CONTROL); - tmp = REG_SET_FIELD(tmp, VGA_RENDER_CONTROL, VGA_VSTATUS_CNTL, 0); - WREG32_SOC15(DCE, 0, mmVGA_RENDER_CONTROL, tmp); + WREG32_FIELD15(DCE, 0, VGA_RENDER_CONTROL, VGA_VSTATUS_CNTL, 0); } r = gmc_v9_0_gart_enable(adev); @@ -822,9 +818,7 @@ static int gmc_v9_0_suspend(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - gmc_v9_0_hw_fini(adev); - - return 0; + return gmc_v9_0_hw_fini(adev); } static int gmc_v9_0_resume(void *handle) diff --git a/drivers/gpu/drm/amd/amdgpu/iceland_ih.c b/drivers/gpu/drm/amd/amdgpu/iceland_ih.c index 7a0ea27..65ed6d3 100644 --- a/drivers/gpu/drm/amd/amdgpu/iceland_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/iceland_ih.c @@ -208,6 +208,19 @@ static u32 iceland_ih_get_wptr(struct amdgpu_device *adev) } /** + * iceland_ih_prescreen_iv - prescreen an interrupt vector + * + * @adev: amdgpu_device pointer + * + * Returns true if the interrupt vector should be further processed. + */ +static bool iceland_ih_prescreen_iv(struct amdgpu_device *adev) +{ + /* Process all interrupts */ + return true; +} + +/** * iceland_ih_decode_iv - decode an interrupt vector * * @adev: amdgpu_device pointer @@ -412,6 +425,7 @@ static const struct amd_ip_funcs iceland_ih_ip_funcs = { static const struct amdgpu_ih_funcs iceland_ih_funcs = { .get_wptr = iceland_ih_get_wptr, + .prescreen_iv = iceland_ih_prescreen_iv, .decode_iv = iceland_ih_decode_iv, .set_rptr = iceland_ih_set_rptr }; diff --git a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c index 3bbf2cc..b57399a 100644 --- a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c @@ -42,7 +42,6 @@ #define KV_MINIMUM_ENGINE_CLOCK 800 #define SMC_RAM_END 0x40000 -static void kv_dpm_set_dpm_funcs(struct amdgpu_device *adev); static void kv_dpm_set_irq_funcs(struct amdgpu_device *adev); static int kv_enable_nb_dpm(struct amdgpu_device *adev, bool enable); @@ -64,7 +63,7 @@ static int kv_set_thermal_temperature_range(struct amdgpu_device *adev, int min_temp, int max_temp); static int kv_init_fps_limits(struct amdgpu_device *adev); -static void kv_dpm_powergate_uvd(struct amdgpu_device *adev, bool gate); +static void kv_dpm_powergate_uvd(void *handle, bool gate); static void kv_dpm_powergate_vce(struct amdgpu_device *adev, bool gate); static void kv_dpm_powergate_samu(struct amdgpu_device *adev, bool gate); static void kv_dpm_powergate_acp(struct amdgpu_device *adev, bool gate); @@ -1245,8 +1244,9 @@ static void kv_update_requested_ps(struct amdgpu_device *adev, adev->pm.dpm.requested_ps = &pi->requested_rps; } -static void kv_dpm_enable_bapm(struct amdgpu_device *adev, bool enable) +static void kv_dpm_enable_bapm(void *handle, bool enable) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct kv_power_info *pi = kv_get_pi(adev); int ret; @@ -1672,8 +1672,9 @@ static int kv_update_acp_dpm(struct amdgpu_device *adev, bool gate) return kv_enable_acp_dpm(adev, !gate); } -static void kv_dpm_powergate_uvd(struct amdgpu_device *adev, bool gate) +static void kv_dpm_powergate_uvd(void *handle, bool gate) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct kv_power_info *pi = kv_get_pi(adev); int ret; @@ -1868,10 +1869,11 @@ static int kv_enable_nb_dpm(struct amdgpu_device *adev, return ret; } -static int kv_dpm_force_performance_level(struct amdgpu_device *adev, +static int kv_dpm_force_performance_level(void *handle, enum amd_dpm_forced_level level) { int ret; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; if (level == AMD_DPM_FORCED_LEVEL_HIGH) { ret = kv_force_dpm_highest(adev); @@ -1892,8 +1894,9 @@ static int kv_dpm_force_performance_level(struct amdgpu_device *adev, return 0; } -static int kv_dpm_pre_set_power_state(struct amdgpu_device *adev) +static int kv_dpm_pre_set_power_state(void *handle) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct kv_power_info *pi = kv_get_pi(adev); struct amdgpu_ps requested_ps = *adev->pm.dpm.requested_ps; struct amdgpu_ps *new_ps = &requested_ps; @@ -1907,8 +1910,9 @@ static int kv_dpm_pre_set_power_state(struct amdgpu_device *adev) return 0; } -static int kv_dpm_set_power_state(struct amdgpu_device *adev) +static int kv_dpm_set_power_state(void *handle) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct kv_power_info *pi = kv_get_pi(adev); struct amdgpu_ps *new_ps = &pi->requested_rps; struct amdgpu_ps *old_ps = &pi->current_rps; @@ -1981,8 +1985,9 @@ static int kv_dpm_set_power_state(struct amdgpu_device *adev) return 0; } -static void kv_dpm_post_set_power_state(struct amdgpu_device *adev) +static void kv_dpm_post_set_power_state(void *handle) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct kv_power_info *pi = kv_get_pi(adev); struct amdgpu_ps *new_ps = &pi->requested_rps; @@ -2848,9 +2853,10 @@ static int kv_dpm_init(struct amdgpu_device *adev) } static void -kv_dpm_debugfs_print_current_performance_level(struct amdgpu_device *adev, +kv_dpm_debugfs_print_current_performance_level(void *handle, struct seq_file *m) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct kv_power_info *pi = kv_get_pi(adev); u32 current_index = (RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX) & @@ -2875,11 +2881,12 @@ kv_dpm_debugfs_print_current_performance_level(struct amdgpu_device *adev, } static void -kv_dpm_print_power_state(struct amdgpu_device *adev, - struct amdgpu_ps *rps) +kv_dpm_print_power_state(void *handle, void *request_ps) { int i; + struct amdgpu_ps *rps = (struct amdgpu_ps *)request_ps; struct kv_ps *ps = kv_get_ps(rps); + struct amdgpu_device *adev = (struct amdgpu_device *)handle; amdgpu_dpm_print_class_info(rps->class, rps->class2); amdgpu_dpm_print_cap_info(rps->caps); @@ -2905,13 +2912,14 @@ static void kv_dpm_fini(struct amdgpu_device *adev) amdgpu_free_extended_power_table(adev); } -static void kv_dpm_display_configuration_changed(struct amdgpu_device *adev) +static void kv_dpm_display_configuration_changed(void *handle) { } -static u32 kv_dpm_get_sclk(struct amdgpu_device *adev, bool low) +static u32 kv_dpm_get_sclk(void *handle, bool low) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct kv_power_info *pi = kv_get_pi(adev); struct kv_ps *requested_state = kv_get_ps(&pi->requested_rps); @@ -2921,18 +2929,20 @@ static u32 kv_dpm_get_sclk(struct amdgpu_device *adev, bool low) return requested_state->levels[requested_state->num_levels - 1].sclk; } -static u32 kv_dpm_get_mclk(struct amdgpu_device *adev, bool low) +static u32 kv_dpm_get_mclk(void *handle, bool low) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct kv_power_info *pi = kv_get_pi(adev); return pi->sys_info.bootup_uma_clk; } /* get temperature in millidegrees */ -static int kv_dpm_get_temp(struct amdgpu_device *adev) +static int kv_dpm_get_temp(void *handle) { u32 temp; int actual_temp = 0; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; temp = RREG32_SMC(0xC0300E0C); @@ -2950,7 +2960,6 @@ static int kv_dpm_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - kv_dpm_set_dpm_funcs(adev); kv_dpm_set_irq_funcs(adev); return 0; @@ -3222,14 +3231,17 @@ static inline bool kv_are_power_levels_equal(const struct kv_pl *kv_cpl1, (kv_cpl1->force_nbp_state == kv_cpl2->force_nbp_state)); } -static int kv_check_state_equal(struct amdgpu_device *adev, - struct amdgpu_ps *cps, - struct amdgpu_ps *rps, +static int kv_check_state_equal(void *handle, + void *current_ps, + void *request_ps, bool *equal) { struct kv_ps *kv_cps; struct kv_ps *kv_rps; int i; + struct amdgpu_ps *cps = (struct amdgpu_ps *)current_ps; + struct amdgpu_ps *rps = (struct amdgpu_ps *)request_ps; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; if (adev == NULL || cps == NULL || rps == NULL || equal == NULL) return -EINVAL; @@ -3262,9 +3274,10 @@ static int kv_check_state_equal(struct amdgpu_device *adev, return 0; } -static int kv_dpm_read_sensor(struct amdgpu_device *adev, int idx, +static int kv_dpm_read_sensor(void *handle, int idx, void *value, int *size) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct kv_power_info *pi = kv_get_pi(adev); uint32_t sclk; u32 pl_index = @@ -3312,7 +3325,7 @@ const struct amd_ip_funcs kv_dpm_ip_funcs = { .set_powergating_state = kv_dpm_set_powergating_state, }; -static const struct amdgpu_dpm_funcs kv_dpm_funcs = { +const struct amd_pm_funcs kv_dpm_funcs = { .get_temperature = &kv_dpm_get_temp, .pre_set_power_state = &kv_dpm_pre_set_power_state, .set_power_state = &kv_dpm_set_power_state, @@ -3330,12 +3343,6 @@ static const struct amdgpu_dpm_funcs kv_dpm_funcs = { .read_sensor = &kv_dpm_read_sensor, }; -static void kv_dpm_set_dpm_funcs(struct amdgpu_device *adev) -{ - if (adev->pm.funcs == NULL) - adev->pm.funcs = &kv_dpm_funcs; -} - static const struct amdgpu_irq_src_funcs kv_dpm_irq_funcs = { .set = kv_dpm_set_interrupt_state, .process = kv_dpm_process_interrupt, diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c index 74cb647..cc21c4b 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c @@ -273,7 +273,7 @@ static const struct pctl_data pctl0_data[] = { {0x135, 0x12a810}, {0x149, 0x7a82c} }; -#define PCTL0_DATA_LEN (sizeof(pctl0_data)/sizeof(pctl0_data[0])) +#define PCTL0_DATA_LEN (ARRAY_SIZE(pctl0_data)) #define PCTL0_RENG_EXEC_END_PTR 0x151 #define PCTL0_STCTRL_REG_SAVE_RANGE0_BASE 0xa640 @@ -309,7 +309,7 @@ static const struct pctl_data pctl1_data[] = { {0x1f0, 0x5000a7f6}, {0x1f1, 0x5000a7e4} }; -#define PCTL1_DATA_LEN (sizeof(pctl1_data)/sizeof(pctl1_data[0])) +#define PCTL1_DATA_LEN (ARRAY_SIZE(pctl1_data)) #define PCTL1_RENG_EXEC_END_PTR 0x1f1 #define PCTL1_STCTRL_REG_SAVE_RANGE0_BASE 0xa000 @@ -561,6 +561,13 @@ void mmhub_v1_0_set_fault_enable_default(struct amdgpu_device *adev, bool value) WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value); tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL, EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value); + if (!value) { + tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL, + CRASH_ON_NO_RETRY_FAULT, 1); + tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL, + CRASH_ON_RETRY_FAULT, 1); + } + WREG32_SOC15(MMHUB, 0, mmVM_L2_PROTECTION_FAULT_CNTL, tmp); } diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.h b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.h index 1e91b9a..67e7857 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.h +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.h @@ -24,7 +24,7 @@ #ifndef __MXGPU_AI_H__ #define __MXGPU_AI_H__ -#define AI_MAILBOX_TIMEDOUT 5000 +#define AI_MAILBOX_TIMEDOUT 12000 enum idh_request { IDH_REQ_GPU_INIT_ACCESS = 1, diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_vi.h b/drivers/gpu/drm/amd/amdgpu/mxgpu_vi.h index c791d73..f13dc6c 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_vi.h +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_vi.h @@ -23,7 +23,7 @@ #ifndef __MXGPU_VI_H__ #define __MXGPU_VI_H__ -#define VI_MAILBOX_TIMEDOUT 5000 +#define VI_MAILBOX_TIMEDOUT 12000 #define VI_MAILBOX_RESET_TIME 12 /* VI mailbox messages request */ diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c index f7cf994..dea7c90 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c @@ -35,6 +35,8 @@ #include "raven1/GC/gc_9_1_offset.h" #include "raven1/SDMA0/sdma0_4_1_offset.h" +MODULE_FIRMWARE("amdgpu/raven_asd.bin"); + static int psp_v10_0_get_fw_type(struct amdgpu_firmware_info *ucode, enum psp_gfx_fw_type *type) { @@ -136,15 +138,13 @@ int psp_v10_0_prep_cmd_buf(struct amdgpu_firmware_info *ucode, struct psp_gfx_cm { int ret; uint64_t fw_mem_mc_addr = ucode->mc_addr; - struct common_firmware_header *header; memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp)); - header = (struct common_firmware_header *)ucode->fw; cmd->cmd_id = GFX_CMD_ID_LOAD_IP_FW; cmd->cmd.cmd_load_ip_fw.fw_phy_addr_lo = lower_32_bits(fw_mem_mc_addr); cmd->cmd.cmd_load_ip_fw.fw_phy_addr_hi = upper_32_bits(fw_mem_mc_addr); - cmd->cmd.cmd_load_ip_fw.fw_size = le32_to_cpu(header->ucode_size_bytes); + cmd->cmd.cmd_load_ip_fw.fw_size = ucode->ucode_size; ret = psp_v10_0_get_fw_type(ucode, &cmd->cmd.cmd_load_ip_fw.fw_type); if (ret) @@ -209,7 +209,7 @@ int psp_v10_0_ring_create(struct psp_context *psp, enum psp_ring_type ring_type) return ret; } -int psp_v10_0_ring_destroy(struct psp_context *psp, enum psp_ring_type ring_type) +int psp_v10_0_ring_stop(struct psp_context *psp, enum psp_ring_type ring_type) { int ret = 0; struct psp_ring *ring; @@ -229,6 +229,19 @@ int psp_v10_0_ring_destroy(struct psp_context *psp, enum psp_ring_type ring_type ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64), 0x80000000, 0x80000000, false); + return ret; +} + +int psp_v10_0_ring_destroy(struct psp_context *psp, enum psp_ring_type ring_type) +{ + int ret = 0; + struct psp_ring *ring = &psp->km_ring; + struct amdgpu_device *adev = psp->adev; + + ret = psp_v10_0_ring_stop(psp, ring_type); + if (ret) + DRM_ERROR("Fail to stop psp ring\n"); + amdgpu_bo_free_kernel(&adev->firmware.rbuf, &ring->ring_mem_mc_addr, (void **)&ring->ring_mem); @@ -245,15 +258,20 @@ int psp_v10_0_cmd_submit(struct psp_context *psp, struct psp_gfx_rb_frame * write_frame = psp->km_ring.ring_mem; struct psp_ring *ring = &psp->km_ring; struct amdgpu_device *adev = psp->adev; + uint32_t ring_size_dw = ring->ring_size / 4; + uint32_t rb_frame_size_dw = sizeof(struct psp_gfx_rb_frame) / 4; /* KM (GPCOM) prepare write pointer */ psp_write_ptr_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67); /* Update KM RB frame pointer to new frame */ - if ((psp_write_ptr_reg % ring->ring_size) == 0) + if ((psp_write_ptr_reg % ring_size_dw) == 0) write_frame = ring->ring_mem; else - write_frame = ring->ring_mem + (psp_write_ptr_reg / (sizeof(struct psp_gfx_rb_frame) / 4)); + write_frame = ring->ring_mem + (psp_write_ptr_reg / rb_frame_size_dw); + + /* Initialize KM RB frame */ + memset(write_frame, 0, sizeof(struct psp_gfx_rb_frame)); /* Update KM RB frame */ write_frame->cmd_buf_addr_hi = upper_32_bits(cmd_buf_mc_addr); @@ -263,8 +281,7 @@ int psp_v10_0_cmd_submit(struct psp_context *psp, write_frame->fence_value = index; /* Update the write Pointer in DWORDs */ - psp_write_ptr_reg += sizeof(struct psp_gfx_rb_frame) / 4; - psp_write_ptr_reg = (psp_write_ptr_reg >= ring->ring_size) ? 0 : psp_write_ptr_reg; + psp_write_ptr_reg = (psp_write_ptr_reg + rb_frame_size_dw) % ring_size_dw; WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67, psp_write_ptr_reg); return 0; @@ -390,3 +407,10 @@ bool psp_v10_0_compare_sram_data(struct psp_context *psp, return true; } + + +int psp_v10_0_mode1_reset(struct psp_context *psp) +{ + DRM_INFO("psp mode 1 reset not supported now! \n"); + return -EINVAL; +} diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.h b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.h index e76cde2..451e830 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.h +++ b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.h @@ -34,6 +34,8 @@ extern int psp_v10_0_ring_init(struct psp_context *psp, enum psp_ring_type ring_type); extern int psp_v10_0_ring_create(struct psp_context *psp, enum psp_ring_type ring_type); +extern int psp_v10_0_ring_stop(struct psp_context *psp, + enum psp_ring_type ring_type); extern int psp_v10_0_ring_destroy(struct psp_context *psp, enum psp_ring_type ring_type); extern int psp_v10_0_cmd_submit(struct psp_context *psp, @@ -43,4 +45,6 @@ extern int psp_v10_0_cmd_submit(struct psp_context *psp, extern bool psp_v10_0_compare_sram_data(struct psp_context *psp, struct amdgpu_firmware_info *ucode, enum AMDGPU_UCODE_ID ucode_type); + +extern int psp_v10_0_mode1_reset(struct psp_context *psp); #endif diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c index 2a535a4..cee5c39 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c @@ -319,7 +319,7 @@ int psp_v3_1_ring_create(struct psp_context *psp, enum psp_ring_type ring_type) return ret; } -int psp_v3_1_ring_destroy(struct psp_context *psp, enum psp_ring_type ring_type) +int psp_v3_1_ring_stop(struct psp_context *psp, enum psp_ring_type ring_type) { int ret = 0; struct psp_ring *ring; @@ -339,6 +339,19 @@ int psp_v3_1_ring_destroy(struct psp_context *psp, enum psp_ring_type ring_type) ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64), 0x80000000, 0x80000000, false); + return ret; +} + +int psp_v3_1_ring_destroy(struct psp_context *psp, enum psp_ring_type ring_type) +{ + int ret = 0; + struct psp_ring *ring = &psp->km_ring; + struct amdgpu_device *adev = psp->adev; + + ret = psp_v3_1_ring_stop(psp, ring_type); + if (ret) + DRM_ERROR("Fail to stop psp ring\n"); + amdgpu_bo_free_kernel(&adev->firmware.rbuf, &ring->ring_mem_mc_addr, (void **)&ring->ring_mem); @@ -517,3 +530,37 @@ bool psp_v3_1_smu_reload_quirk(struct psp_context *psp) reg = RREG32_SOC15(NBIO, 0, mmPCIE_DATA2); return (reg & MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK) ? true : false; } + +int psp_v3_1_mode1_reset(struct psp_context *psp) +{ + int ret; + uint32_t offset; + struct amdgpu_device *adev = psp->adev; + + offset = SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64); + + ret = psp_wait_for(psp, offset, 0x80000000, 0x8000FFFF, false); + + if (ret) { + DRM_INFO("psp is not working correctly before mode1 reset!\n"); + return -EINVAL; + } + + /*send the mode 1 reset command*/ + WREG32(offset, 0x70000); + + mdelay(1000); + + offset = SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_33); + + ret = psp_wait_for(psp, offset, 0x80000000, 0x80000000, false); + + if (ret) { + DRM_INFO("psp mode 1 reset failed!\n"); + return -EINVAL; + } + + DRM_INFO("psp mode1 reset succeed \n"); + + return 0; +} diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.h b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.h index 9dcd0b2..b05dbad 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.h +++ b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.h @@ -41,6 +41,8 @@ extern int psp_v3_1_ring_init(struct psp_context *psp, enum psp_ring_type ring_type); extern int psp_v3_1_ring_create(struct psp_context *psp, enum psp_ring_type ring_type); +extern int psp_v3_1_ring_stop(struct psp_context *psp, + enum psp_ring_type ring_type); extern int psp_v3_1_ring_destroy(struct psp_context *psp, enum psp_ring_type ring_type); extern int psp_v3_1_cmd_submit(struct psp_context *psp, @@ -51,4 +53,5 @@ extern bool psp_v3_1_compare_sram_data(struct psp_context *psp, struct amdgpu_firmware_info *ucode, enum AMDGPU_UCODE_ID ucode_type); extern bool psp_v3_1_smu_reload_quirk(struct psp_context *psp); +extern int psp_v3_1_mode1_reset(struct psp_context *psp); #endif diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c index f2d0710..acdee3a 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c @@ -1324,8 +1324,13 @@ static void sdma_v2_4_set_buffer_funcs(struct amdgpu_device *adev) } static const struct amdgpu_vm_pte_funcs sdma_v2_4_vm_pte_funcs = { + .copy_pte_num_dw = 7, .copy_pte = sdma_v2_4_vm_copy_pte, + .write_pte = sdma_v2_4_vm_write_pte, + + .set_max_nums_pte_pde = 0x1fffff >> 3, + .set_pte_pde_num_dw = 10, .set_pte_pde = sdma_v2_4_vm_set_pte_pde, }; diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c index b1de44f..72f31cc 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c @@ -379,8 +379,10 @@ static void sdma_v3_0_ring_set_wptr(struct amdgpu_ring *ring) struct amdgpu_device *adev = ring->adev; if (ring->use_doorbell) { + u32 *wb = (u32 *)&adev->wb.wb[ring->wptr_offs]; + /* XXX check if swapping is necessary on BE */ - adev->wb.wb[ring->wptr_offs] = lower_32_bits(ring->wptr) << 2; + WRITE_ONCE(*wb, (lower_32_bits(ring->wptr) << 2)); WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr) << 2); } else { int me = (ring == &ring->adev->sdma.instance[0].ring) ? 0 : 1; @@ -641,10 +643,11 @@ static void sdma_v3_0_enable(struct amdgpu_device *adev, bool enable) static int sdma_v3_0_gfx_resume(struct amdgpu_device *adev) { struct amdgpu_ring *ring; - u32 rb_cntl, ib_cntl; + u32 rb_cntl, ib_cntl, wptr_poll_cntl; u32 rb_bufsz; u32 wb_offset; u32 doorbell; + u64 wptr_gpu_addr; int i, j, r; for (i = 0; i < adev->sdma.num_instances; i++) { @@ -707,6 +710,20 @@ static int sdma_v3_0_gfx_resume(struct amdgpu_device *adev) } WREG32(mmSDMA0_GFX_DOORBELL + sdma_offsets[i], doorbell); + /* setup the wptr shadow polling */ + wptr_gpu_addr = adev->wb.gpu_addr + (ring->wptr_offs * 4); + + WREG32(mmSDMA0_GFX_RB_WPTR_POLL_ADDR_LO + sdma_offsets[i], + lower_32_bits(wptr_gpu_addr)); + WREG32(mmSDMA0_GFX_RB_WPTR_POLL_ADDR_HI + sdma_offsets[i], + upper_32_bits(wptr_gpu_addr)); + wptr_poll_cntl = RREG32(mmSDMA0_GFX_RB_WPTR_POLL_CNTL + sdma_offsets[i]); + if (amdgpu_sriov_vf(adev)) + wptr_poll_cntl = REG_SET_FIELD(wptr_poll_cntl, SDMA0_GFX_RB_WPTR_POLL_CNTL, F32_POLL_ENABLE, 1); + else + wptr_poll_cntl = REG_SET_FIELD(wptr_poll_cntl, SDMA0_GFX_RB_WPTR_POLL_CNTL, F32_POLL_ENABLE, 0); + WREG32(mmSDMA0_GFX_RB_WPTR_POLL_CNTL + sdma_offsets[i], wptr_poll_cntl); + /* enable DMA RB */ rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_ENABLE, 1); WREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[i], rb_cntl); @@ -1713,11 +1730,11 @@ static void sdma_v3_0_emit_fill_buffer(struct amdgpu_ib *ib, } static const struct amdgpu_buffer_funcs sdma_v3_0_buffer_funcs = { - .copy_max_bytes = 0x1fffff, + .copy_max_bytes = 0x3fffe0, /* not 0x3fffff due to HW limitation */ .copy_num_dw = 7, .emit_copy_buffer = sdma_v3_0_emit_copy_buffer, - .fill_max_bytes = 0x1fffff, + .fill_max_bytes = 0x3fffe0, /* not 0x3fffff due to HW limitation */ .fill_num_dw = 5, .emit_fill_buffer = sdma_v3_0_emit_fill_buffer, }; @@ -1731,8 +1748,14 @@ static void sdma_v3_0_set_buffer_funcs(struct amdgpu_device *adev) } static const struct amdgpu_vm_pte_funcs sdma_v3_0_vm_pte_funcs = { + .copy_pte_num_dw = 7, .copy_pte = sdma_v3_0_vm_copy_pte, + .write_pte = sdma_v3_0_vm_write_pte, + + /* not 0x3fffff due to HW limitation */ + .set_max_nums_pte_pde = 0x3fffe0 >> 3, + .set_pte_pde_num_dw = 10, .set_pte_pde = sdma_v3_0_vm_set_pte_pde, }; diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index fd7c72a..c26d205 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c @@ -54,7 +54,7 @@ static void sdma_v4_0_set_vm_pte_funcs(struct amdgpu_device *adev); static void sdma_v4_0_set_irq_funcs(struct amdgpu_device *adev); static const u32 golden_settings_sdma_4[] = { - SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_CHICKEN_BITS), 0xfe931f07, 0x02831f07, + SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_CHICKEN_BITS), 0xfe931f07, 0x02831d07, SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_CLK_CTRL), 0xff000ff0, 0x3f000100, SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_GFX_IB_CNTL), 0x800f0100, 0x00000100, SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_GFX_RB_WPTR_POLL_CNTL), 0xfffffff7, 0x00403000, @@ -89,7 +89,7 @@ static const u32 golden_settings_sdma_vg10[] = { static const u32 golden_settings_sdma_4_1[] = { - SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_CHICKEN_BITS), 0xfe931f07, 0x02831f07, + SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_CHICKEN_BITS), 0xfe931f07, 0x02831d07, SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_CLK_CTRL), 0xffffffff, 0x3f000100, SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_GFX_IB_CNTL), 0x800f0111, 0x00000100, SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_GFX_RB_WPTR_POLL_CNTL), 0xfffffff7, 0x00403000, @@ -398,7 +398,7 @@ static void sdma_v4_0_ring_emit_hdp_invalidate(struct amdgpu_ring *ring) { amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_SRBM_WRITE) | SDMA_PKT_SRBM_WRITE_HEADER_BYTE_EN(0xf)); - amdgpu_ring_write(ring, SOC15_REG_OFFSET(HDP, 0, mmHDP_DEBUG0)); + amdgpu_ring_write(ring, SOC15_REG_OFFSET(HDP, 0, mmHDP_READ_CACHE_INVALIDATE)); amdgpu_ring_write(ring, 1); } @@ -1264,6 +1264,11 @@ static int sdma_v4_0_sw_fini(void *handle) for (i = 0; i < adev->sdma.num_instances; i++) amdgpu_ring_fini(&adev->sdma.instance[i].ring); + for (i = 0; i < adev->sdma.num_instances; i++) { + release_firmware(adev->sdma.instance[i].fw); + adev->sdma.instance[i].fw = NULL; + } + return 0; } @@ -1714,8 +1719,13 @@ static void sdma_v4_0_set_buffer_funcs(struct amdgpu_device *adev) } static const struct amdgpu_vm_pte_funcs sdma_v4_0_vm_pte_funcs = { + .copy_pte_num_dw = 7, .copy_pte = sdma_v4_0_vm_copy_pte, + .write_pte = sdma_v4_0_vm_write_pte, + + .set_max_nums_pte_pde = 0x400000 >> 3, + .set_pte_pde_num_dw = 10, .set_pte_pde = sdma_v4_0_vm_set_pte_pde, }; diff --git a/drivers/gpu/drm/amd/amdgpu/si_dma.c b/drivers/gpu/drm/amd/amdgpu/si_dma.c index 112969f..3fa2fbf 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dma.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dma.c @@ -887,8 +887,13 @@ static void si_dma_set_buffer_funcs(struct amdgpu_device *adev) } static const struct amdgpu_vm_pte_funcs si_dma_vm_pte_funcs = { + .copy_pte_num_dw = 5, .copy_pte = si_dma_vm_copy_pte, + .write_pte = si_dma_vm_write_pte, + + .set_max_nums_pte_pde = 0xffff8 >> 3, + .set_pte_pde_num_dw = 9, .set_pte_pde = si_dma_vm_set_pte_pde, }; diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c index d63873f..9b8db60 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c @@ -1847,7 +1847,6 @@ static int si_calculate_sclk_params(struct amdgpu_device *adev, static void si_thermal_start_smc_fan_control(struct amdgpu_device *adev); static void si_fan_ctrl_set_default_mode(struct amdgpu_device *adev); -static void si_dpm_set_dpm_funcs(struct amdgpu_device *adev); static void si_dpm_set_irq_funcs(struct amdgpu_device *adev); static struct si_power_info *si_get_pi(struct amdgpu_device *adev) @@ -3060,9 +3059,9 @@ static int si_get_vce_clock_voltage(struct amdgpu_device *adev, return ret; } -static bool si_dpm_vblank_too_short(struct amdgpu_device *adev) +static bool si_dpm_vblank_too_short(void *handle) { - + struct amdgpu_device *adev = (struct amdgpu_device *)handle; u32 vblank_time = amdgpu_dpm_get_vblank_time(adev); /* we never hit the non-gddr5 limit so disable it */ u32 switch_limit = adev->mc.vram_type == AMDGPU_VRAM_TYPE_GDDR5 ? 450 : 0; @@ -3871,9 +3870,10 @@ static int si_restrict_performance_levels_before_switch(struct amdgpu_device *ad 0 : -EINVAL; } -static int si_dpm_force_performance_level(struct amdgpu_device *adev, +static int si_dpm_force_performance_level(void *handle, enum amd_dpm_forced_level level) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_ps *rps = adev->pm.dpm.current_ps; struct si_ps *ps = si_get_ps(rps); u32 levels = ps->performance_level_count; @@ -6575,11 +6575,12 @@ static int si_fan_ctrl_stop_smc_fan_control(struct amdgpu_device *adev) } } -static int si_dpm_get_fan_speed_percent(struct amdgpu_device *adev, +static int si_dpm_get_fan_speed_percent(void *handle, u32 *speed) { u32 duty, duty100; u64 tmp64; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; if (adev->pm.no_fan) return -ENOENT; @@ -6600,9 +6601,10 @@ static int si_dpm_get_fan_speed_percent(struct amdgpu_device *adev, return 0; } -static int si_dpm_set_fan_speed_percent(struct amdgpu_device *adev, +static int si_dpm_set_fan_speed_percent(void *handle, u32 speed) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct si_power_info *si_pi = si_get_pi(adev); u32 tmp; u32 duty, duty100; @@ -6633,8 +6635,10 @@ static int si_dpm_set_fan_speed_percent(struct amdgpu_device *adev, return 0; } -static void si_dpm_set_fan_control_mode(struct amdgpu_device *adev, u32 mode) +static void si_dpm_set_fan_control_mode(void *handle, u32 mode) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + if (mode) { /* stop auto-manage */ if (adev->pm.dpm.fan.ucode_fan_control) @@ -6649,8 +6653,9 @@ static void si_dpm_set_fan_control_mode(struct amdgpu_device *adev, u32 mode) } } -static u32 si_dpm_get_fan_control_mode(struct amdgpu_device *adev) +static u32 si_dpm_get_fan_control_mode(void *handle) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct si_power_info *si_pi = si_get_pi(adev); u32 tmp; @@ -6946,8 +6951,9 @@ static void si_dpm_disable(struct amdgpu_device *adev) ni_update_current_ps(adev, boot_ps); } -static int si_dpm_pre_set_power_state(struct amdgpu_device *adev) +static int si_dpm_pre_set_power_state(void *handle) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); struct amdgpu_ps requested_ps = *adev->pm.dpm.requested_ps; struct amdgpu_ps *new_ps = &requested_ps; @@ -6984,8 +6990,9 @@ static int si_power_control_set_level(struct amdgpu_device *adev) return 0; } -static int si_dpm_set_power_state(struct amdgpu_device *adev) +static int si_dpm_set_power_state(void *handle) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); struct amdgpu_ps *new_ps = &eg_pi->requested_rps; struct amdgpu_ps *old_ps = &eg_pi->current_rps; @@ -7086,8 +7093,9 @@ static int si_dpm_set_power_state(struct amdgpu_device *adev) return 0; } -static void si_dpm_post_set_power_state(struct amdgpu_device *adev) +static void si_dpm_post_set_power_state(void *handle) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); struct amdgpu_ps *new_ps = &eg_pi->requested_rps; @@ -7103,8 +7111,10 @@ void si_dpm_reset_asic(struct amdgpu_device *adev) } #endif -static void si_dpm_display_configuration_changed(struct amdgpu_device *adev) +static void si_dpm_display_configuration_changed(void *handle) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + si_program_display_gap(adev); } @@ -7486,9 +7496,10 @@ static void si_dpm_fini(struct amdgpu_device *adev) amdgpu_free_extended_power_table(adev); } -static void si_dpm_debugfs_print_current_performance_level(struct amdgpu_device *adev, +static void si_dpm_debugfs_print_current_performance_level(void *handle, struct seq_file *m) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); struct amdgpu_ps *rps = &eg_pi->current_rps; struct si_ps *ps = si_get_ps(rps); @@ -7860,10 +7871,11 @@ static int si_dpm_set_powergating_state(void *handle, } /* get temperature in millidegrees */ -static int si_dpm_get_temp(struct amdgpu_device *adev) +static int si_dpm_get_temp(void *handle) { u32 temp; int actual_temp = 0; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; temp = (RREG32(CG_MULT_THERMAL_STATUS) & CTF_TEMP_MASK) >> CTF_TEMP_SHIFT; @@ -7878,8 +7890,9 @@ static int si_dpm_get_temp(struct amdgpu_device *adev) return actual_temp; } -static u32 si_dpm_get_sclk(struct amdgpu_device *adev, bool low) +static u32 si_dpm_get_sclk(void *handle, bool low) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); struct si_ps *requested_state = si_get_ps(&eg_pi->requested_rps); @@ -7889,8 +7902,9 @@ static u32 si_dpm_get_sclk(struct amdgpu_device *adev, bool low) return requested_state->performance_levels[requested_state->performance_level_count - 1].sclk; } -static u32 si_dpm_get_mclk(struct amdgpu_device *adev, bool low) +static u32 si_dpm_get_mclk(void *handle, bool low) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); struct si_ps *requested_state = si_get_ps(&eg_pi->requested_rps); @@ -7900,9 +7914,11 @@ static u32 si_dpm_get_mclk(struct amdgpu_device *adev, bool low) return requested_state->performance_levels[requested_state->performance_level_count - 1].mclk; } -static void si_dpm_print_power_state(struct amdgpu_device *adev, - struct amdgpu_ps *rps) +static void si_dpm_print_power_state(void *handle, + void *current_ps) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_ps *rps = (struct amdgpu_ps *)current_ps; struct si_ps *ps = si_get_ps(rps); struct rv7xx_pl *pl; int i; @@ -7927,7 +7943,6 @@ static int si_dpm_early_init(void *handle) struct amdgpu_device *adev = (struct amdgpu_device *)handle; - si_dpm_set_dpm_funcs(adev); si_dpm_set_irq_funcs(adev); return 0; } @@ -7942,20 +7957,23 @@ static inline bool si_are_power_levels_equal(const struct rv7xx_pl *si_cpl1, (si_cpl1->vddci == si_cpl2->vddci)); } -static int si_check_state_equal(struct amdgpu_device *adev, - struct amdgpu_ps *cps, - struct amdgpu_ps *rps, +static int si_check_state_equal(void *handle, + void *current_ps, + void *request_ps, bool *equal) { struct si_ps *si_cps; struct si_ps *si_rps; int i; + struct amdgpu_ps *cps = (struct amdgpu_ps *)current_ps; + struct amdgpu_ps *rps = (struct amdgpu_ps *)request_ps; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; if (adev == NULL || cps == NULL || rps == NULL || equal == NULL) return -EINVAL; - si_cps = si_get_ps(cps); - si_rps = si_get_ps(rps); + si_cps = si_get_ps((struct amdgpu_ps *)cps); + si_rps = si_get_ps((struct amdgpu_ps *)rps); if (si_cps == NULL) { printk("si_cps is NULL\n"); @@ -7983,9 +8001,10 @@ static int si_check_state_equal(struct amdgpu_device *adev, return 0; } -static int si_dpm_read_sensor(struct amdgpu_device *adev, int idx, +static int si_dpm_read_sensor(void *handle, int idx, void *value, int *size) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); struct amdgpu_ps *rps = &eg_pi->current_rps; struct si_ps *ps = si_get_ps(rps); @@ -8041,7 +8060,7 @@ const struct amd_ip_funcs si_dpm_ip_funcs = { .set_powergating_state = si_dpm_set_powergating_state, }; -static const struct amdgpu_dpm_funcs si_dpm_funcs = { +const struct amd_pm_funcs si_dpm_funcs = { .get_temperature = &si_dpm_get_temp, .pre_set_power_state = &si_dpm_pre_set_power_state, .set_power_state = &si_dpm_set_power_state, @@ -8062,12 +8081,6 @@ static const struct amdgpu_dpm_funcs si_dpm_funcs = { .read_sensor = &si_dpm_read_sensor, }; -static void si_dpm_set_dpm_funcs(struct amdgpu_device *adev) -{ - if (adev->pm.funcs == NULL) - adev->pm.funcs = &si_dpm_funcs; -} - static const struct amdgpu_irq_src_funcs si_dpm_irq_funcs = { .set = si_dpm_set_interrupt_state, .process = si_dpm_process_interrupt, diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.h b/drivers/gpu/drm/amd/amdgpu/si_dpm.h index 51ce21c..9fe343d 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.h +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.h @@ -246,6 +246,7 @@ enum si_display_gap }; extern const struct amd_ip_funcs si_dpm_ip_funcs; +extern const struct amd_pm_funcs si_dpm_funcs; struct ni_leakage_coeffients { diff --git a/drivers/gpu/drm/amd/amdgpu/si_ih.c b/drivers/gpu/drm/amd/amdgpu/si_ih.c index ce25e03..d2c6b80 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/si_ih.c @@ -118,6 +118,19 @@ static u32 si_ih_get_wptr(struct amdgpu_device *adev) return (wptr & adev->irq.ih.ptr_mask); } +/** + * si_ih_prescreen_iv - prescreen an interrupt vector + * + * @adev: amdgpu_device pointer + * + * Returns true if the interrupt vector should be further processed. + */ +static bool si_ih_prescreen_iv(struct amdgpu_device *adev) +{ + /* Process all interrupts */ + return true; +} + static void si_ih_decode_iv(struct amdgpu_device *adev, struct amdgpu_iv_entry *entry) { @@ -288,6 +301,7 @@ static const struct amd_ip_funcs si_ih_ip_funcs = { static const struct amdgpu_ih_funcs si_ih_funcs = { .get_wptr = si_ih_get_wptr, + .prescreen_iv = si_ih_prescreen_iv, .decode_iv = si_ih_decode_iv, .set_rptr = si_ih_set_rptr }; diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index f2c3a49..245a18a 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -407,18 +407,27 @@ static int soc15_read_register(struct amdgpu_device *adev, u32 se_num, return -EINVAL; } -static void soc15_gpu_pci_config_reset(struct amdgpu_device *adev) +static int soc15_asic_reset(struct amdgpu_device *adev) { u32 i; - dev_info(adev->dev, "GPU pci config reset\n"); + amdgpu_atombios_scratch_regs_engine_hung(adev, true); + + dev_info(adev->dev, "GPU reset\n"); /* disable BM */ pci_clear_master(adev->pdev); - /* reset */ - amdgpu_pci_config_reset(adev); - udelay(100); + pci_save_state(adev->pdev); + + for (i = 0; i < AMDGPU_MAX_IP_NUM; i++) { + if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP){ + adev->ip_blocks[i].version->funcs->soft_reset((void *)adev); + break; + } + } + + pci_restore_state(adev->pdev); /* wait for asic to come out of reset */ for (i = 0; i < adev->usec_timeout; i++) { @@ -430,14 +439,6 @@ static void soc15_gpu_pci_config_reset(struct amdgpu_device *adev) udelay(1); } -} - -static int soc15_asic_reset(struct amdgpu_device *adev) -{ - amdgpu_atombios_scratch_regs_engine_hung(adev, true); - - soc15_gpu_pci_config_reset(adev); - amdgpu_atombios_scratch_regs_engine_hung(adev, false); return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/tonga_ih.c b/drivers/gpu/drm/amd/amdgpu/tonga_ih.c index 923df2c..5ed0069 100644 --- a/drivers/gpu/drm/amd/amdgpu/tonga_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/tonga_ih.c @@ -219,6 +219,19 @@ static u32 tonga_ih_get_wptr(struct amdgpu_device *adev) } /** + * tonga_ih_prescreen_iv - prescreen an interrupt vector + * + * @adev: amdgpu_device pointer + * + * Returns true if the interrupt vector should be further processed. + */ +static bool tonga_ih_prescreen_iv(struct amdgpu_device *adev) +{ + /* Process all interrupts */ + return true; +} + +/** * tonga_ih_decode_iv - decode an interrupt vector * * @adev: amdgpu_device pointer @@ -478,6 +491,7 @@ static const struct amd_ip_funcs tonga_ih_ip_funcs = { static const struct amdgpu_ih_funcs tonga_ih_funcs = { .get_wptr = tonga_ih_get_wptr, + .prescreen_iv = tonga_ih_prescreen_iv, .decode_iv = tonga_ih_decode_iv, .set_rptr = tonga_ih_set_rptr }; diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c index 23a8575..b8ed8fa 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c @@ -1161,7 +1161,7 @@ static void uvd_v7_0_ring_emit_hdp_flush(struct amdgpu_ring *ring) */ static void uvd_v7_0_ring_emit_hdp_invalidate(struct amdgpu_ring *ring) { - amdgpu_ring_write(ring, PACKET0(SOC15_REG_OFFSET(HDP, 0, mmHDP_DEBUG0), 0)); + amdgpu_ring_write(ring, PACKET0(SOC15_REG_OFFSET(HDP, 0, mmHDP_READ_CACHE_INVALIDATE), 0)); amdgpu_ring_write(ring, 1); } diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c index 11134d5..7574554 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c @@ -1011,10 +1011,6 @@ static int vce_v4_0_process_interrupt(struct amdgpu_device *adev, { DRM_DEBUG("IH: VCE\n"); - WREG32_P(SOC15_REG_OFFSET(VCE, 0, mmVCE_SYS_INT_STATUS), - VCE_SYS_INT_STATUS__VCE_SYS_INT_TRAP_INTERRUPT_INT_MASK, - ~VCE_SYS_INT_STATUS__VCE_SYS_INT_TRAP_INTERRUPT_INT_MASK); - switch (entry->src_data[0]) { case 0: case 1: diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c index 21e7b88..1eb4d79 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c @@ -812,7 +812,7 @@ static void vcn_v1_0_dec_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 */ static void vcn_v1_0_dec_ring_emit_hdp_invalidate(struct amdgpu_ring *ring) { - amdgpu_ring_write(ring, PACKET0(SOC15_REG_OFFSET(HDP, 0, mmHDP_DEBUG0), 0)); + amdgpu_ring_write(ring, PACKET0(SOC15_REG_OFFSET(HDP, 0, mmHDP_READ_CACHE_INVALIDATE), 0)); amdgpu_ring_write(ring, 1); } diff --git a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c index 56150e8..a3b30d8 100644 --- a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c @@ -219,14 +219,92 @@ static u32 vega10_ih_get_wptr(struct amdgpu_device *adev) wptr, adev->irq.ih.rptr, tmp); adev->irq.ih.rptr = tmp; - tmp = RREG32(SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL)); + tmp = RREG32_NO_KIQ(SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL)); tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); - WREG32(SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL), tmp); + WREG32_NO_KIQ(SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL), tmp); } return (wptr & adev->irq.ih.ptr_mask); } /** + * vega10_ih_prescreen_iv - prescreen an interrupt vector + * + * @adev: amdgpu_device pointer + * + * Returns true if the interrupt vector should be further processed. + */ +static bool vega10_ih_prescreen_iv(struct amdgpu_device *adev) +{ + u32 ring_index = adev->irq.ih.rptr >> 2; + u32 dw0, dw3, dw4, dw5; + u16 pasid; + u64 addr, key; + struct amdgpu_vm *vm; + int r; + + dw0 = le32_to_cpu(adev->irq.ih.ring[ring_index + 0]); + dw3 = le32_to_cpu(adev->irq.ih.ring[ring_index + 3]); + dw4 = le32_to_cpu(adev->irq.ih.ring[ring_index + 4]); + dw5 = le32_to_cpu(adev->irq.ih.ring[ring_index + 5]); + + /* Filter retry page faults, let only the first one pass. If + * there are too many outstanding faults, ignore them until + * some faults get cleared. + */ + switch (dw0 & 0xff) { + case AMDGPU_IH_CLIENTID_VMC: + case AMDGPU_IH_CLIENTID_UTCL2: + break; + default: + /* Not a VM fault */ + return true; + } + + /* Not a retry fault */ + if (!(dw5 & 0x80)) + return true; + + pasid = dw3 & 0xffff; + /* No PASID, can't identify faulting process */ + if (!pasid) + return true; + + addr = ((u64)(dw5 & 0xf) << 44) | ((u64)dw4 << 12); + key = AMDGPU_VM_FAULT(pasid, addr); + r = amdgpu_ih_add_fault(adev, key); + + /* Hash table is full or the fault is already being processed, + * ignore further page faults + */ + if (r != 0) + goto ignore_iv; + + /* Track retry faults in per-VM fault FIFO. */ + spin_lock(&adev->vm_manager.pasid_lock); + vm = idr_find(&adev->vm_manager.pasid_idr, pasid); + spin_unlock(&adev->vm_manager.pasid_lock); + if (WARN_ON_ONCE(!vm)) { + /* VM not found, process it normally */ + amdgpu_ih_clear_fault(adev, key); + return true; + } + /* No locking required with single writer and single reader */ + r = kfifo_put(&vm->faults, key); + if (!r) { + /* FIFO is full. Ignore it until there is space */ + amdgpu_ih_clear_fault(adev, key); + goto ignore_iv; + } + + /* It's the first fault for this address, process it normally */ + return true; + +ignore_iv: + adev->irq.ih.rptr += 32; + return false; +} + +/** * vega10_ih_decode_iv - decode an interrupt vector * * @adev: amdgpu_device pointer @@ -310,6 +388,14 @@ static int vega10_ih_sw_init(void *handle) adev->irq.ih.use_doorbell = true; adev->irq.ih.doorbell_index = AMDGPU_DOORBELL64_IH << 1; + adev->irq.ih.faults = kmalloc(sizeof(*adev->irq.ih.faults), GFP_KERNEL); + if (!adev->irq.ih.faults) + return -ENOMEM; + INIT_CHASH_TABLE(adev->irq.ih.faults->hash, + AMDGPU_PAGEFAULT_HASH_BITS, 8, 0); + spin_lock_init(&adev->irq.ih.faults->lock); + adev->irq.ih.faults->count = 0; + r = amdgpu_irq_init(adev); return r; @@ -322,6 +408,9 @@ static int vega10_ih_sw_fini(void *handle) amdgpu_irq_fini(adev); amdgpu_ih_ring_fini(adev); + kfree(adev->irq.ih.faults); + adev->irq.ih.faults = NULL; + return 0; } @@ -410,6 +499,7 @@ const struct amd_ip_funcs vega10_ih_ip_funcs = { static const struct amdgpu_ih_funcs vega10_ih_funcs = { .get_wptr = vega10_ih_get_wptr, + .prescreen_iv = vega10_ih_prescreen_iv, .decode_iv = vega10_ih_decode_iv, .set_rptr = vega10_ih_set_rptr }; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index 61fff25..5df12b2 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -168,13 +168,6 @@ static bool device_iommu_pasid_init(struct kfd_dev *kfd) pasid_limit = min_t(unsigned int, (unsigned int)(1 << kfd->device_info->max_pasid_bits), iommu_info.max_pasids); - /* - * last pasid is used for kernel queues doorbells - * in the future the last pasid might be used for a kernel thread. - */ - pasid_limit = min_t(unsigned int, - pasid_limit, - kfd->doorbell_process_limit - 1); err = amd_iommu_init_device(kfd->pdev, pasid_limit); if (err < 0) { diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c b/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c index acf4d2a..feb76c2 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c @@ -24,16 +24,15 @@ #include <linux/mman.h> #include <linux/slab.h> #include <linux/io.h> +#include <linux/idr.h> /* - * This extension supports a kernel level doorbells management for - * the kernel queues. - * Basically the last doorbells page is devoted to kernel queues - * and that's assures that any user process won't get access to the - * kernel doorbells page + * This extension supports a kernel level doorbells management for the + * kernel queues using the first doorbell page reserved for the kernel. */ -#define KERNEL_DOORBELL_PASID 1 +static DEFINE_IDA(doorbell_ida); +static unsigned int max_doorbell_slices; #define KFD_SIZE_OF_DOORBELL_IN_BYTES 4 /* @@ -84,13 +83,16 @@ int kfd_doorbell_init(struct kfd_dev *kfd) (doorbell_aperture_size - doorbell_start_offset) / doorbell_process_allocation(); else - doorbell_process_limit = 0; + return -ENOSPC; + + if (!max_doorbell_slices || + doorbell_process_limit < max_doorbell_slices) + max_doorbell_slices = doorbell_process_limit; kfd->doorbell_base = kfd->shared_resources.doorbell_physical_address + doorbell_start_offset; kfd->doorbell_id_offset = doorbell_start_offset / sizeof(u32); - kfd->doorbell_process_limit = doorbell_process_limit - 1; kfd->doorbell_kernel_ptr = ioremap(kfd->doorbell_base, doorbell_process_allocation()); @@ -185,11 +187,10 @@ u32 __iomem *kfd_get_kernel_doorbell(struct kfd_dev *kfd, return NULL; /* - * Calculating the kernel doorbell offset using "faked" kernel - * pasid that allocated for kernel queues only + * Calculating the kernel doorbell offset using the first + * doorbell page. */ - *doorbell_off = KERNEL_DOORBELL_PASID * (doorbell_process_allocation() / - sizeof(u32)) + inx; + *doorbell_off = kfd->doorbell_id_offset + inx; pr_debug("Get kernel queue doorbell\n" " doorbell offset == 0x%08X\n" @@ -228,11 +229,12 @@ unsigned int kfd_queue_id_to_doorbell(struct kfd_dev *kfd, { /* * doorbell_id_offset accounts for doorbells taken by KGD. - * pasid * doorbell_process_allocation/sizeof(u32) adjusts - * to the process's doorbells + * index * doorbell_process_allocation/sizeof(u32) adjusts to + * the process's doorbells. */ return kfd->doorbell_id_offset + - process->pasid * (doorbell_process_allocation()/sizeof(u32)) + + process->doorbell_index + * doorbell_process_allocation() / sizeof(u32) + queue_id; } @@ -250,5 +252,21 @@ phys_addr_t kfd_get_process_doorbells(struct kfd_dev *dev, struct kfd_process *process) { return dev->doorbell_base + - process->pasid * doorbell_process_allocation(); + process->doorbell_index * doorbell_process_allocation(); +} + +int kfd_alloc_process_doorbells(struct kfd_process *process) +{ + int r = ida_simple_get(&doorbell_ida, 1, max_doorbell_slices, + GFP_KERNEL); + if (r > 0) + process->doorbell_index = r; + + return r; +} + +void kfd_free_process_doorbells(struct kfd_process *process) +{ + if (process->doorbell_index) + ida_simple_remove(&doorbell_ida, process->doorbell_index); } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_module.c b/drivers/gpu/drm/amd/amdkfd/kfd_module.c index 0d73bea..6c5a9ca 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_module.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_module.c @@ -103,10 +103,6 @@ static int __init kfd_module_init(void) return -1; } - err = kfd_pasid_init(); - if (err < 0) - return err; - err = kfd_chardev_init(); if (err < 0) goto err_ioctl; @@ -126,7 +122,6 @@ static int __init kfd_module_init(void) err_topology: kfd_chardev_exit(); err_ioctl: - kfd_pasid_exit(); return err; } @@ -137,7 +132,6 @@ static void __exit kfd_module_exit(void) kfd_process_destroy_wq(); kfd_topology_shutdown(); kfd_chardev_exit(); - kfd_pasid_exit(); dev_info(kfd_device, "Removed module\n"); } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_pasid.c b/drivers/gpu/drm/amd/amdkfd/kfd_pasid.c index 1e06de0..d6a7961 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_pasid.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_pasid.c @@ -20,78 +20,64 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#include <linux/slab.h> #include <linux/types.h> #include "kfd_priv.h" -static unsigned long *pasid_bitmap; -static unsigned int pasid_limit; -static DEFINE_MUTEX(pasid_mutex); - -int kfd_pasid_init(void) -{ - pasid_limit = KFD_MAX_NUM_OF_PROCESSES; - - pasid_bitmap = kcalloc(BITS_TO_LONGS(pasid_limit), sizeof(long), - GFP_KERNEL); - if (!pasid_bitmap) - return -ENOMEM; - - set_bit(0, pasid_bitmap); /* PASID 0 is reserved. */ - - return 0; -} - -void kfd_pasid_exit(void) -{ - kfree(pasid_bitmap); -} +static unsigned int pasid_bits = 16; +static const struct kfd2kgd_calls *kfd2kgd; bool kfd_set_pasid_limit(unsigned int new_limit) { - if (new_limit < pasid_limit) { - bool ok; - - mutex_lock(&pasid_mutex); - - /* ensure that no pasids >= new_limit are in-use */ - ok = (find_next_bit(pasid_bitmap, pasid_limit, new_limit) == - pasid_limit); - if (ok) - pasid_limit = new_limit; - - mutex_unlock(&pasid_mutex); - - return ok; + if (new_limit < 2) + return false; + + if (new_limit < (1U << pasid_bits)) { + if (kfd2kgd) + /* We've already allocated user PASIDs, too late to + * change the limit + */ + return false; + + while (new_limit < (1U << pasid_bits)) + pasid_bits--; } return true; } -inline unsigned int kfd_get_pasid_limit(void) +unsigned int kfd_get_pasid_limit(void) { - return pasid_limit; + return 1U << pasid_bits; } unsigned int kfd_pasid_alloc(void) { - unsigned int found; - - mutex_lock(&pasid_mutex); - - found = find_first_zero_bit(pasid_bitmap, pasid_limit); - if (found == pasid_limit) - found = 0; - else - set_bit(found, pasid_bitmap); + int r; + + /* Find the first best KFD device for calling KGD */ + if (!kfd2kgd) { + struct kfd_dev *dev = NULL; + unsigned int i = 0; + + while ((dev = kfd_topology_enum_kfd_devices(i)) != NULL) { + if (dev && dev->kfd2kgd) { + kfd2kgd = dev->kfd2kgd; + break; + } + i++; + } + + if (!kfd2kgd) + return false; + } - mutex_unlock(&pasid_mutex); + r = kfd2kgd->alloc_pasid(pasid_bits); - return found; + return r > 0 ? r : 0; } void kfd_pasid_free(unsigned int pasid) { - if (!WARN_ON(pasid == 0 || pasid >= pasid_limit)) - clear_bit(pasid, pasid_bitmap); + if (kfd2kgd) + kfd2kgd->free_pasid(pasid); } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index b87e96c..634083e 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -157,9 +157,6 @@ struct kfd_dev { * to HW doorbell, GFX reserved some * at the start) */ - size_t doorbell_process_limit; /* Number of processes we have doorbell - * space for. - */ u32 __iomem *doorbell_kernel_ptr; /* This is a pointer for a doorbells * page used by kernel queue */ @@ -495,6 +492,7 @@ struct kfd_process { struct rcu_head rcu; unsigned int pasid; + unsigned int doorbell_index; /* * List of kfd_process_device structures, @@ -584,6 +582,10 @@ void write_kernel_doorbell(u32 __iomem *db, u32 value); unsigned int kfd_queue_id_to_doorbell(struct kfd_dev *kfd, struct kfd_process *process, unsigned int queue_id); +phys_addr_t kfd_get_process_doorbells(struct kfd_dev *dev, + struct kfd_process *process); +int kfd_alloc_process_doorbells(struct kfd_process *process); +void kfd_free_process_doorbells(struct kfd_process *process); /* GTT Sub-Allocator */ @@ -695,8 +697,6 @@ int pm_send_unmap_queue(struct packet_manager *pm, enum kfd_queue_type type, void pm_release_ib(struct packet_manager *pm); uint64_t kfd_get_number_elems(struct kfd_dev *kfd); -phys_addr_t kfd_get_process_doorbells(struct kfd_dev *dev, - struct kfd_process *process); /* Events */ extern const struct kfd_event_interrupt_class event_interrupt_class_cik; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index c74cf22..9e65ce3 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -183,6 +183,7 @@ static void kfd_process_wq_release(struct work_struct *work) kfd_event_free_process(p); kfd_pasid_free(p->pasid); + kfd_free_process_doorbells(p); mutex_unlock(&p->mutex); @@ -288,6 +289,9 @@ static struct kfd_process *create_process(const struct task_struct *thread) if (process->pasid == 0) goto err_alloc_pasid; + if (kfd_alloc_process_doorbells(process) < 0) + goto err_alloc_doorbells; + mutex_init(&process->mutex); process->mm = thread->mm; @@ -329,6 +333,8 @@ err_process_pqm_init: mmu_notifier_unregister_no_release(&process->mmu_notifier, process->mm); err_mmu_notifier: mutex_destroy(&process->mutex); + kfd_free_process_doorbells(process); +err_alloc_doorbells: kfd_pasid_free(process->pasid); err_alloc_pasid: kfree(process->queues); diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h index 70e8c20..20457bb 100644 --- a/drivers/gpu/drm/amd/include/amd_shared.h +++ b/drivers/gpu/drm/amd/include/amd_shared.h @@ -25,6 +25,8 @@ #define AMD_MAX_USEC_TIMEOUT 200000 /* 200 ms */ +struct seq_file; + /* * Supported ASIC types */ @@ -144,6 +146,12 @@ enum amd_fan_ctrl_mode { AMD_FAN_CTRL_AUTO = 2, }; +enum pp_clock_type { + PP_SCLK, + PP_MCLK, + PP_PCIE, +}; + /* CG flags */ #define AMD_CG_SUPPORT_GFX_MGCG (1 << 0) #define AMD_CG_SUPPORT_GFX_MGLS (1 << 1) @@ -249,4 +257,62 @@ struct amd_ip_funcs { void (*get_clockgating_state)(void *handle, u32 *flags); }; +enum amd_pp_task; + +struct pp_states_info; + +struct amd_pm_funcs { + int (*get_temperature)(void *handle); + int (*pre_set_power_state)(void *handle); + int (*set_power_state)(void *handle); + void (*post_set_power_state)(void *handle); + void (*display_configuration_changed)(void *handle); + u32 (*get_sclk)(void *handle, bool low); + u32 (*get_mclk)(void *handle, bool low); + void (*print_power_state)(void *handle, void *ps); + void (*debugfs_print_current_performance_level)(void *handle, struct seq_file *m); + int (*force_performance_level)(void *handle, enum amd_dpm_forced_level level); + bool (*vblank_too_short)(void *handle); + void (*powergate_uvd)(void *handle, bool gate); + void (*powergate_vce)(void *handle, bool gate); + void (*enable_bapm)(void *handle, bool enable); + void (*set_fan_control_mode)(void *handle, u32 mode); + u32 (*get_fan_control_mode)(void *handle); + int (*set_fan_speed_percent)(void *handle, u32 speed); + int (*get_fan_speed_percent)(void *handle, u32 *speed); + int (*force_clock_level)(void *handle, enum pp_clock_type type, uint32_t mask); + int (*print_clock_levels)(void *handle, enum pp_clock_type type, char *buf); + int (*get_sclk_od)(void *handle); + int (*set_sclk_od)(void *handle, uint32_t value); + int (*get_mclk_od)(void *handle); + int (*set_mclk_od)(void *handle, uint32_t value); + int (*check_state_equal)(void *handle, + void *cps, + void *rps, + bool *equal); + int (*read_sensor)(void *handle, int idx, void *value, + int *size); + + struct amd_vce_state* (*get_vce_clock_state)(void *handle, u32 idx); + int (*reset_power_profile_state)(void *handle, + struct amd_pp_profile *request); + int (*get_power_profile_state)(void *handle, + struct amd_pp_profile *query); + int (*set_power_profile_state)(void *handle, + struct amd_pp_profile *request); + int (*switch_power_profile)(void *handle, + enum amd_pp_profile_type type); + int (*load_firmware)(void *handle); + int (*wait_for_fw_loading_complete)(void *handle); + enum amd_dpm_forced_level (*get_performance_level)(void *handle); + enum amd_pm_state_type (*get_current_power_state)(void *handle); + int (*dispatch_tasks)(void *handle, enum amd_pp_task task_id, + void *input, void *output); + int (*get_fan_speed_rpm)(void *handle, uint32_t *rpm); + int (*get_pp_num_states)(void *handle, struct pp_states_info *data); + int (*get_pp_table)(void *handle, char **table); + int (*set_pp_table)(void *handle, const char *buf, size_t size); +}; + + #endif /* __AMD_SHARED_H__ */ diff --git a/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_0_1_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_0_1_sh_mask.h index 34c6ff5..6af9f02 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_0_1_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_0_1_sh_mask.h @@ -5454,5 +5454,7 @@ #define ROM_SW_DATA_64__ROM_SW_DATA__SHIFT 0x0 #define CURRENT_PG_STATUS__VCE_PG_STATUS_MASK 0x00000002 #define CURRENT_PG_STATUS__UVD_PG_STATUS_MASK 0x00000004 +#define SMC_SYSCON_MISC_CNTL__pre_fetcher_en_MASK 0x1 +#define SMC_SYSCON_MISC_CNTL__pre_fetcher_en__SHIFT 0 #endif /* SMU_7_0_1_SH_MASK_H */ diff --git a/drivers/gpu/drm/amd/include/atomfirmware.h b/drivers/gpu/drm/amd/include/atomfirmware.h index 837296d..7c92f47 100644 --- a/drivers/gpu/drm/amd/include/atomfirmware.h +++ b/drivers/gpu/drm/amd/include/atomfirmware.h @@ -1017,6 +1017,19 @@ struct atom_14nm_combphy_tmds_vs_set uint8_t margin_deemph_lane0__deemph_sel_val; }; +struct atom_i2c_reg_info { + uint8_t ucI2cRegIndex; + uint8_t ucI2cRegVal; +}; + +struct atom_hdmi_retimer_redriver_set { + uint8_t HdmiSlvAddr; + uint8_t HdmiRegNum; + uint8_t Hdmi6GRegNum; + struct atom_i2c_reg_info HdmiRegSetting[9]; //For non 6G Hz use + struct atom_i2c_reg_info Hdmi6GhzRegSetting[3]; //For 6G Hz use. +}; + struct atom_integrated_system_info_v1_11 { struct atom_common_table_header table_header; @@ -1052,7 +1065,11 @@ struct atom_integrated_system_info_v1_11 struct atom_14nm_dpphy_dp_tuningset dp_tuningset; struct atom_14nm_dpphy_dp_tuningset dp_hbr3_tuningset; struct atom_camera_data camera_info; - uint32_t reserved[138]; + struct atom_hdmi_retimer_redriver_set dp0_retimer_set; //for DP0 + struct atom_hdmi_retimer_redriver_set dp1_retimer_set; //for DP1 + struct atom_hdmi_retimer_redriver_set dp2_retimer_set; //for DP2 + struct atom_hdmi_retimer_redriver_set dp3_retimer_set; //for DP3 + uint32_t reserved[108]; }; diff --git a/drivers/gpu/drm/amd/include/cgs_common.h b/drivers/gpu/drm/amd/include/cgs_common.h index 0214f63..030b146 100644 --- a/drivers/gpu/drm/amd/include/cgs_common.h +++ b/drivers/gpu/drm/amd/include/cgs_common.h @@ -100,6 +100,7 @@ enum cgs_system_info_id { CGS_SYSTEM_INFO_GFX_SE_INFO, CGS_SYSTEM_INFO_PCIE_SUB_SYS_ID, CGS_SYSTEM_INFO_PCIE_SUB_SYS_VENDOR_ID, + CGS_SYSTEM_INFO_PCIE_BUS_DEVFN, CGS_SYSTEM_INFO_ID_MAXIMUM, }; @@ -193,8 +194,6 @@ struct cgs_acpi_method_info { * @type: memory type * @size: size in bytes * @align: alignment in bytes - * @min_offset: minimum offset from start of heap - * @max_offset: maximum offset from start of heap * @handle: memory handle (output) * * The memory types CGS_GPU_MEM_TYPE_*_CONTIG_FB force contiguous @@ -216,7 +215,6 @@ struct cgs_acpi_method_info { */ typedef int (*cgs_alloc_gpu_mem_t)(struct cgs_device *cgs_device, enum cgs_gpu_mem_type type, uint64_t size, uint64_t align, - uint64_t min_offset, uint64_t max_offset, cgs_handle_t *handle); /** @@ -310,6 +308,22 @@ typedef uint32_t (*cgs_read_ind_register_t)(struct cgs_device *cgs_device, enum typedef void (*cgs_write_ind_register_t)(struct cgs_device *cgs_device, enum cgs_ind_reg space, unsigned index, uint32_t value); +#define CGS_REG_FIELD_SHIFT(reg, field) reg##__##field##__SHIFT +#define CGS_REG_FIELD_MASK(reg, field) reg##__##field##_MASK + +#define CGS_REG_SET_FIELD(orig_val, reg, field, field_val) \ + (((orig_val) & ~CGS_REG_FIELD_MASK(reg, field)) | \ + (CGS_REG_FIELD_MASK(reg, field) & ((field_val) << CGS_REG_FIELD_SHIFT(reg, field)))) + +#define CGS_REG_GET_FIELD(value, reg, field) \ + (((value) & CGS_REG_FIELD_MASK(reg, field)) >> CGS_REG_FIELD_SHIFT(reg, field)) + +#define CGS_WREG32_FIELD(device, reg, field, val) \ + cgs_write_register(device, mm##reg, (cgs_read_register(device, mm##reg) & ~CGS_REG_FIELD_MASK(reg, field)) | (val) << CGS_REG_FIELD_SHIFT(reg, field)) + +#define CGS_WREG32_FIELD_IND(device, space, reg, field, val) \ + cgs_write_ind_register(device, space, ix##reg, (cgs_read_ind_register(device, space, ix##reg) & ~CGS_REG_FIELD_MASK(reg, field)) | (val) << CGS_REG_FIELD_SHIFT(reg, field)) + /** * cgs_get_pci_resource() - provide access to a device resource (PCI BAR) * @cgs_device: opaque device handle @@ -463,8 +477,8 @@ struct cgs_device #define CGS_OS_CALL(func,dev,...) \ (((struct cgs_device *)dev)->os_ops->func(dev, ##__VA_ARGS__)) -#define cgs_alloc_gpu_mem(dev,type,size,align,min_off,max_off,handle) \ - CGS_CALL(alloc_gpu_mem,dev,type,size,align,min_off,max_off,handle) +#define cgs_alloc_gpu_mem(dev,type,size,align,handle) \ + CGS_CALL(alloc_gpu_mem,dev,type,size,align,handle) #define cgs_free_gpu_mem(dev,handle) \ CGS_CALL(free_gpu_mem,dev,handle) #define cgs_gmap_gpu_mem(dev,handle,mcaddr) \ diff --git a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h index 94277cb..f516fd1 100644 --- a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h @@ -112,6 +112,9 @@ struct tile_config { * * @get_max_engine_clock_in_mhz: Retrieves maximum GPU clock in MHz * + * @alloc_pasid: Allocate a PASID + * @free_pasid: Free a PASID + * * @program_sh_mem_settings: A function that should initiate the memory * properties such as main aperture memory type (cache / non cached) and * secondary aperture base address, size and memory type. @@ -160,6 +163,9 @@ struct kfd2kgd_calls { uint32_t (*get_max_engine_clock_in_mhz)(struct kgd_dev *kgd); + int (*alloc_pasid)(unsigned int bits); + void (*free_pasid)(unsigned int pasid); + /* Register access functions */ void (*program_sh_mem_settings)(struct kgd_dev *kgd, uint32_t vmid, uint32_t sh_mem_config, uint32_t sh_mem_ape1_base, diff --git a/drivers/gpu/drm/amd/include/linux/chash.h b/drivers/gpu/drm/amd/include/linux/chash.h new file mode 100644 index 0000000..6dc1599 --- /dev/null +++ b/drivers/gpu/drm/amd/include/linux/chash.h @@ -0,0 +1,366 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef _LINUX_CHASH_H +#define _LINUX_CHASH_H + +#include <linux/types.h> +#include <linux/hash.h> +#include <linux/bug.h> +#include <asm/bitsperlong.h> + +#if BITS_PER_LONG == 32 +# define _CHASH_LONG_SHIFT 5 +#elif BITS_PER_LONG == 64 +# define _CHASH_LONG_SHIFT 6 +#else +# error "Unexpected BITS_PER_LONG" +#endif + +struct __chash_table { + u8 bits; + u8 key_size; + unsigned int value_size; + u32 size_mask; + unsigned long *occup_bitmap, *valid_bitmap; + union { + u32 *keys32; + u64 *keys64; + }; + u8 *values; + +#ifdef CONFIG_CHASH_STATS + u64 hits, hits_steps, hits_time_ns; + u64 miss, miss_steps, miss_time_ns; + u64 relocs, reloc_dist; +#endif +}; + +#define __CHASH_BITMAP_SIZE(bits) \ + (((1 << (bits)) + BITS_PER_LONG - 1) / BITS_PER_LONG) +#define __CHASH_ARRAY_SIZE(bits, size) \ + ((((size) << (bits)) + sizeof(long) - 1) / sizeof(long)) + +#define __CHASH_DATA_SIZE(bits, key_size, value_size) \ + (__CHASH_BITMAP_SIZE(bits) * 2 + \ + __CHASH_ARRAY_SIZE(bits, key_size) + \ + __CHASH_ARRAY_SIZE(bits, value_size)) + +#define STRUCT_CHASH_TABLE(bits, key_size, value_size) \ + struct { \ + struct __chash_table table; \ + unsigned long data \ + [__CHASH_DATA_SIZE(bits, key_size, value_size)];\ + } + +/** + * struct chash_table - Dynamically allocated closed hash table + * + * Use this struct for dynamically allocated hash tables (using + * chash_table_alloc and chash_table_free), where the size is + * determined at runtime. + */ +struct chash_table { + struct __chash_table table; + unsigned long *data; +}; + +/** + * DECLARE_CHASH_TABLE - macro to declare a closed hash table + * @table: name of the declared hash table + * @bts: Table size will be 2^bits entries + * @key_sz: Size of hash keys in bytes, 4 or 8 + * @val_sz: Size of data values in bytes, can be 0 + * + * This declares the hash table variable with a static size. + * + * The closed hash table stores key-value pairs with low memory and + * lookup overhead. In operation it performs no dynamic memory + * management. The data being stored does not require any + * list_heads. The hash table performs best with small @val_sz and as + * long as some space (about 50%) is left free in the table. But the + * table can still work reasonably efficiently even when filled up to + * about 90%. If bigger data items need to be stored and looked up, + * store the pointer to it as value in the hash table. + * + * @val_sz may be 0. This can be useful when all the stored + * information is contained in the key itself and the fact that it is + * in the hash table (or not). + */ +#define DECLARE_CHASH_TABLE(table, bts, key_sz, val_sz) \ + STRUCT_CHASH_TABLE(bts, key_sz, val_sz) table + +#ifdef CONFIG_CHASH_STATS +#define __CHASH_STATS_INIT(prefix), \ + prefix.hits = 0, \ + prefix.hits_steps = 0, \ + prefix.hits_time_ns = 0, \ + prefix.miss = 0, \ + prefix.miss_steps = 0, \ + prefix.miss_time_ns = 0, \ + prefix.relocs = 0, \ + prefix.reloc_dist = 0 +#else +#define __CHASH_STATS_INIT(prefix) +#endif + +#define __CHASH_TABLE_INIT(prefix, data, bts, key_sz, val_sz) \ + prefix.bits = (bts), \ + prefix.key_size = (key_sz), \ + prefix.value_size = (val_sz), \ + prefix.size_mask = ((1 << bts) - 1), \ + prefix.occup_bitmap = &data[0], \ + prefix.valid_bitmap = &data \ + [__CHASH_BITMAP_SIZE(bts)], \ + prefix.keys64 = (u64 *)&data \ + [__CHASH_BITMAP_SIZE(bts) * 2], \ + prefix.values = (u8 *)&data \ + [__CHASH_BITMAP_SIZE(bts) * 2 + \ + __CHASH_ARRAY_SIZE(bts, key_sz)] \ + __CHASH_STATS_INIT(prefix) + +/** + * DEFINE_CHASH_TABLE - macro to define and initialize a closed hash table + * @tbl: name of the declared hash table + * @bts: Table size will be 2^bits entries + * @key_sz: Size of hash keys in bytes, 4 or 8 + * @val_sz: Size of data values in bytes, can be 0 + * + * Note: the macro can be used for global and local hash table variables. + */ +#define DEFINE_CHASH_TABLE(tbl, bts, key_sz, val_sz) \ + DECLARE_CHASH_TABLE(tbl, bts, key_sz, val_sz) = { \ + .table = { \ + __CHASH_TABLE_INIT(, (tbl).data, bts, key_sz, val_sz) \ + }, \ + .data = {0} \ + } + +/** + * INIT_CHASH_TABLE - Initialize a hash table declared by DECLARE_CHASH_TABLE + * @tbl: name of the declared hash table + * @bts: Table size will be 2^bits entries + * @key_sz: Size of hash keys in bytes, 4 or 8 + * @val_sz: Size of data values in bytes, can be 0 + */ +#define INIT_CHASH_TABLE(tbl, bts, key_sz, val_sz) \ + __CHASH_TABLE_INIT(((tbl).table), (tbl).data, bts, key_sz, val_sz) + +int chash_table_alloc(struct chash_table *table, u8 bits, u8 key_size, + unsigned int value_size, gfp_t gfp_mask); +void chash_table_free(struct chash_table *table); + +/** + * chash_table_dump_stats - Dump statistics of a closed hash table + * @tbl: Pointer to the table structure + * + * Dumps some performance statistics of the table gathered in operation + * in the kernel log using pr_debug. If CONFIG_DYNAMIC_DEBUG is enabled, + * user must turn on messages for chash.c (file chash.c +p). + */ +#ifdef CONFIG_CHASH_STATS +#define chash_table_dump_stats(tbl) __chash_table_dump_stats(&(*tbl).table) + +void __chash_table_dump_stats(struct __chash_table *table); +#else +#define chash_table_dump_stats(tbl) +#endif + +/** + * chash_table_reset_stats - Reset statistics of a closed hash table + * @tbl: Pointer to the table structure + */ +#ifdef CONFIG_CHASH_STATS +#define chash_table_reset_stats(tbl) __chash_table_reset_stats(&(*tbl).table) + +static inline void __chash_table_reset_stats(struct __chash_table *table) +{ + (void)table __CHASH_STATS_INIT((*table)); +} +#else +#define chash_table_reset_stats(tbl) +#endif + +/** + * chash_table_copy_in - Copy a new value into the hash table + * @tbl: Pointer to the table structure + * @key: Key of the entry to add or update + * @value: Pointer to value to copy, may be NULL + * + * If @key already has an entry, its value is replaced. Otherwise a + * new entry is added. If @value is NULL, the value is left unchanged + * or uninitialized. Returns 1 if an entry already existed, 0 if a new + * entry was added or %-ENOMEM if there was no free space in the + * table. + */ +#define chash_table_copy_in(tbl, key, value) \ + __chash_table_copy_in(&(*tbl).table, key, value) + +int __chash_table_copy_in(struct __chash_table *table, u64 key, + const void *value); + +/** + * chash_table_copy_out - Copy a value out of the hash table + * @tbl: Pointer to the table structure + * @key: Key of the entry to find + * @value: Pointer to value to copy, may be NULL + * + * If @value is not NULL and the table has a non-0 value_size, the + * value at @key is copied to @value. Returns the slot index of the + * entry or %-EINVAL if @key was not found. + */ +#define chash_table_copy_out(tbl, key, value) \ + __chash_table_copy_out(&(*tbl).table, key, value, false) + +int __chash_table_copy_out(struct __chash_table *table, u64 key, + void *value, bool remove); + +/** + * chash_table_remove - Remove an entry from the hash table + * @tbl: Pointer to the table structure + * @key: Key of the entry to find + * @value: Pointer to value to copy, may be NULL + * + * If @value is not NULL and the table has a non-0 value_size, the + * value at @key is copied to @value. The entry is removed from the + * table. Returns the slot index of the removed entry or %-EINVAL if + * @key was not found. + */ +#define chash_table_remove(tbl, key, value) \ + __chash_table_copy_out(&(*tbl).table, key, value, true) + +/* + * Low level iterator API used internally by the above functions. + */ +struct chash_iter { + struct __chash_table *table; + unsigned long mask; + int slot; +}; + +/** + * CHASH_ITER_INIT - Initialize a hash table iterator + * @tbl: Pointer to hash table to iterate over + * @s: Initial slot number + */ +#define CHASH_ITER_INIT(table, s) { \ + table, \ + 1UL << ((s) & (BITS_PER_LONG - 1)), \ + s \ + } +/** + * CHASH_ITER_SET - Set hash table iterator to new slot + * @iter: Iterator + * @s: Slot number + */ +#define CHASH_ITER_SET(iter, s) \ + (iter).mask = 1UL << ((s) & (BITS_PER_LONG - 1)), \ + (iter).slot = (s) +/** + * CHASH_ITER_INC - Increment hash table iterator + * @table: Hash table to iterate over + * + * Wraps around at the end. + */ +#define CHASH_ITER_INC(iter) do { \ + (iter).mask = (iter).mask << 1 | \ + (iter).mask >> (BITS_PER_LONG - 1); \ + (iter).slot = ((iter).slot + 1) & (iter).table->size_mask; \ + } while (0) + +static inline bool chash_iter_is_valid(const struct chash_iter iter) +{ + BUG_ON((unsigned)iter.slot >= (1 << iter.table->bits)); + return !!(iter.table->valid_bitmap[iter.slot >> _CHASH_LONG_SHIFT] & + iter.mask); +} +static inline bool chash_iter_is_empty(const struct chash_iter iter) +{ + BUG_ON((unsigned)iter.slot >= (1 << iter.table->bits)); + return !(iter.table->occup_bitmap[iter.slot >> _CHASH_LONG_SHIFT] & + iter.mask); +} + +static inline void chash_iter_set_valid(const struct chash_iter iter) +{ + BUG_ON((unsigned)iter.slot >= (1 << iter.table->bits)); + iter.table->valid_bitmap[iter.slot >> _CHASH_LONG_SHIFT] |= iter.mask; + iter.table->occup_bitmap[iter.slot >> _CHASH_LONG_SHIFT] |= iter.mask; +} +static inline void chash_iter_set_invalid(const struct chash_iter iter) +{ + BUG_ON((unsigned)iter.slot >= (1 << iter.table->bits)); + iter.table->valid_bitmap[iter.slot >> _CHASH_LONG_SHIFT] &= ~iter.mask; +} +static inline void chash_iter_set_empty(const struct chash_iter iter) +{ + BUG_ON((unsigned)iter.slot >= (1 << iter.table->bits)); + iter.table->occup_bitmap[iter.slot >> _CHASH_LONG_SHIFT] &= ~iter.mask; +} + +static inline u32 chash_iter_key32(const struct chash_iter iter) +{ + BUG_ON(iter.table->key_size != 4); + BUG_ON((unsigned)iter.slot >= (1 << iter.table->bits)); + return iter.table->keys32[iter.slot]; +} +static inline u64 chash_iter_key64(const struct chash_iter iter) +{ + BUG_ON(iter.table->key_size != 8); + BUG_ON((unsigned)iter.slot >= (1 << iter.table->bits)); + return iter.table->keys64[iter.slot]; +} +static inline u64 chash_iter_key(const struct chash_iter iter) +{ + BUG_ON((unsigned)iter.slot >= (1 << iter.table->bits)); + return (iter.table->key_size == 4) ? + iter.table->keys32[iter.slot] : iter.table->keys64[iter.slot]; +} + +static inline u32 chash_iter_hash32(const struct chash_iter iter) +{ + BUG_ON(iter.table->key_size != 4); + return hash_32(chash_iter_key32(iter), iter.table->bits); +} + +static inline u32 chash_iter_hash64(const struct chash_iter iter) +{ + BUG_ON(iter.table->key_size != 8); + return hash_64(chash_iter_key64(iter), iter.table->bits); +} + +static inline u32 chash_iter_hash(const struct chash_iter iter) +{ + return (iter.table->key_size == 4) ? + hash_32(chash_iter_key32(iter), iter.table->bits) : + hash_64(chash_iter_key64(iter), iter.table->bits); +} + +static inline void *chash_iter_value(const struct chash_iter iter) +{ + BUG_ON((unsigned)iter.slot >= (1 << iter.table->bits)); + return iter.table->values + + ((unsigned long)iter.slot * iter.table->value_size); +} + +#endif /* _LINUX_CHASH_H */ diff --git a/drivers/gpu/drm/amd/include/v9_structs.h b/drivers/gpu/drm/amd/include/v9_structs.h index 9a9e6c7..2fb25ab 100644 --- a/drivers/gpu/drm/amd/include/v9_structs.h +++ b/drivers/gpu/drm/amd/include/v9_structs.h @@ -284,8 +284,8 @@ struct v9_mqd { uint32_t gds_save_mask_hi; uint32_t ctx_save_base_addr_lo; uint32_t ctx_save_base_addr_hi; - uint32_t reserved_126; - uint32_t reserved_127; + uint32_t dynamic_cu_mask_addr_lo; + uint32_t dynamic_cu_mask_addr_hi; uint32_t cp_mqd_base_addr_lo; uint32_t cp_mqd_base_addr_hi; uint32_t cp_hqd_active; @@ -672,6 +672,14 @@ struct v9_mqd { uint32_t reserved_511; }; +struct v9_mqd_allocation { + struct v9_mqd mqd; + uint32_t wptr_poll_mem; + uint32_t rptr_report_mem; + uint32_t dynamic_cu_mask; + uint32_t dynamic_rb_mask; +}; + /* from vega10 all CSA format is shifted to chain ib compatible mode */ struct v9_ce_ib_state { /* section of non chained ib part */ diff --git a/drivers/gpu/drm/amd/include/vi_structs.h b/drivers/gpu/drm/amd/include/vi_structs.h index 3e606a7..2023482 100644 --- a/drivers/gpu/drm/amd/include/vi_structs.h +++ b/drivers/gpu/drm/amd/include/vi_structs.h @@ -423,265 +423,6 @@ struct vi_mqd_allocation { uint32_t dynamic_rb_mask; }; -struct cz_mqd { - uint32_t header; - uint32_t compute_dispatch_initiator; - uint32_t compute_dim_x; - uint32_t compute_dim_y; - uint32_t compute_dim_z; - uint32_t compute_start_x; - uint32_t compute_start_y; - uint32_t compute_start_z; - uint32_t compute_num_thread_x; - uint32_t compute_num_thread_y; - uint32_t compute_num_thread_z; - uint32_t compute_pipelinestat_enable; - uint32_t compute_perfcount_enable; - uint32_t compute_pgm_lo; - uint32_t compute_pgm_hi; - uint32_t compute_tba_lo; - uint32_t compute_tba_hi; - uint32_t compute_tma_lo; - uint32_t compute_tma_hi; - uint32_t compute_pgm_rsrc1; - uint32_t compute_pgm_rsrc2; - uint32_t compute_vmid; - uint32_t compute_resource_limits; - uint32_t compute_static_thread_mgmt_se0; - uint32_t compute_static_thread_mgmt_se1; - uint32_t compute_tmpring_size; - uint32_t compute_static_thread_mgmt_se2; - uint32_t compute_static_thread_mgmt_se3; - uint32_t compute_restart_x; - uint32_t compute_restart_y; - uint32_t compute_restart_z; - uint32_t compute_thread_trace_enable; - uint32_t compute_misc_reserved; - uint32_t compute_dispatch_id; - uint32_t compute_threadgroup_id; - uint32_t compute_relaunch; - uint32_t compute_wave_restore_addr_lo; - uint32_t compute_wave_restore_addr_hi; - uint32_t compute_wave_restore_control; - uint32_t reserved_39; - uint32_t reserved_40; - uint32_t reserved_41; - uint32_t reserved_42; - uint32_t reserved_43; - uint32_t reserved_44; - uint32_t reserved_45; - uint32_t reserved_46; - uint32_t reserved_47; - uint32_t reserved_48; - uint32_t reserved_49; - uint32_t reserved_50; - uint32_t reserved_51; - uint32_t reserved_52; - uint32_t reserved_53; - uint32_t reserved_54; - uint32_t reserved_55; - uint32_t reserved_56; - uint32_t reserved_57; - uint32_t reserved_58; - uint32_t reserved_59; - uint32_t reserved_60; - uint32_t reserved_61; - uint32_t reserved_62; - uint32_t reserved_63; - uint32_t reserved_64; - uint32_t compute_user_data_0; - uint32_t compute_user_data_1; - uint32_t compute_user_data_2; - uint32_t compute_user_data_3; - uint32_t compute_user_data_4; - uint32_t compute_user_data_5; - uint32_t compute_user_data_6; - uint32_t compute_user_data_7; - uint32_t compute_user_data_8; - uint32_t compute_user_data_9; - uint32_t compute_user_data_10; - uint32_t compute_user_data_11; - uint32_t compute_user_data_12; - uint32_t compute_user_data_13; - uint32_t compute_user_data_14; - uint32_t compute_user_data_15; - uint32_t cp_compute_csinvoc_count_lo; - uint32_t cp_compute_csinvoc_count_hi; - uint32_t reserved_83; - uint32_t reserved_84; - uint32_t reserved_85; - uint32_t cp_mqd_query_time_lo; - uint32_t cp_mqd_query_time_hi; - uint32_t cp_mqd_connect_start_time_lo; - uint32_t cp_mqd_connect_start_time_hi; - uint32_t cp_mqd_connect_end_time_lo; - uint32_t cp_mqd_connect_end_time_hi; - uint32_t cp_mqd_connect_end_wf_count; - uint32_t cp_mqd_connect_end_pq_rptr; - uint32_t cp_mqd_connect_end_pq_wptr; - uint32_t cp_mqd_connect_end_ib_rptr; - uint32_t reserved_96; - uint32_t reserved_97; - uint32_t cp_mqd_save_start_time_lo; - uint32_t cp_mqd_save_start_time_hi; - uint32_t cp_mqd_save_end_time_lo; - uint32_t cp_mqd_save_end_time_hi; - uint32_t cp_mqd_restore_start_time_lo; - uint32_t cp_mqd_restore_start_time_hi; - uint32_t cp_mqd_restore_end_time_lo; - uint32_t cp_mqd_restore_end_time_hi; - uint32_t reserved_106; - uint32_t reserved_107; - uint32_t gds_cs_ctxsw_cnt0; - uint32_t gds_cs_ctxsw_cnt1; - uint32_t gds_cs_ctxsw_cnt2; - uint32_t gds_cs_ctxsw_cnt3; - uint32_t reserved_112; - uint32_t reserved_113; - uint32_t cp_pq_exe_status_lo; - uint32_t cp_pq_exe_status_hi; - uint32_t cp_packet_id_lo; - uint32_t cp_packet_id_hi; - uint32_t cp_packet_exe_status_lo; - uint32_t cp_packet_exe_status_hi; - uint32_t gds_save_base_addr_lo; - uint32_t gds_save_base_addr_hi; - uint32_t gds_save_mask_lo; - uint32_t gds_save_mask_hi; - uint32_t ctx_save_base_addr_lo; - uint32_t ctx_save_base_addr_hi; - uint32_t reserved_126; - uint32_t reserved_127; - uint32_t cp_mqd_base_addr_lo; - uint32_t cp_mqd_base_addr_hi; - uint32_t cp_hqd_active; - uint32_t cp_hqd_vmid; - uint32_t cp_hqd_persistent_state; - uint32_t cp_hqd_pipe_priority; - uint32_t cp_hqd_queue_priority; - uint32_t cp_hqd_quantum; - uint32_t cp_hqd_pq_base_lo; - uint32_t cp_hqd_pq_base_hi; - uint32_t cp_hqd_pq_rptr; - uint32_t cp_hqd_pq_rptr_report_addr_lo; - uint32_t cp_hqd_pq_rptr_report_addr_hi; - uint32_t cp_hqd_pq_wptr_poll_addr_lo; - uint32_t cp_hqd_pq_wptr_poll_addr_hi; - uint32_t cp_hqd_pq_doorbell_control; - uint32_t cp_hqd_pq_wptr; - uint32_t cp_hqd_pq_control; - uint32_t cp_hqd_ib_base_addr_lo; - uint32_t cp_hqd_ib_base_addr_hi; - uint32_t cp_hqd_ib_rptr; - uint32_t cp_hqd_ib_control; - uint32_t cp_hqd_iq_timer; - uint32_t cp_hqd_iq_rptr; - uint32_t cp_hqd_dequeue_request; - uint32_t cp_hqd_dma_offload; - uint32_t cp_hqd_sema_cmd; - uint32_t cp_hqd_msg_type; - uint32_t cp_hqd_atomic0_preop_lo; - uint32_t cp_hqd_atomic0_preop_hi; - uint32_t cp_hqd_atomic1_preop_lo; - uint32_t cp_hqd_atomic1_preop_hi; - uint32_t cp_hqd_hq_status0; - uint32_t cp_hqd_hq_control0; - uint32_t cp_mqd_control; - uint32_t cp_hqd_hq_status1; - uint32_t cp_hqd_hq_control1; - uint32_t cp_hqd_eop_base_addr_lo; - uint32_t cp_hqd_eop_base_addr_hi; - uint32_t cp_hqd_eop_control; - uint32_t cp_hqd_eop_rptr; - uint32_t cp_hqd_eop_wptr; - uint32_t cp_hqd_eop_done_events; - uint32_t cp_hqd_ctx_save_base_addr_lo; - uint32_t cp_hqd_ctx_save_base_addr_hi; - uint32_t cp_hqd_ctx_save_control; - uint32_t cp_hqd_cntl_stack_offset; - uint32_t cp_hqd_cntl_stack_size; - uint32_t cp_hqd_wg_state_offset; - uint32_t cp_hqd_ctx_save_size; - uint32_t cp_hqd_gds_resource_state; - uint32_t cp_hqd_error; - uint32_t cp_hqd_eop_wptr_mem; - uint32_t cp_hqd_eop_dones; - uint32_t reserved_182; - uint32_t reserved_183; - uint32_t reserved_184; - uint32_t reserved_185; - uint32_t reserved_186; - uint32_t reserved_187; - uint32_t reserved_188; - uint32_t reserved_189; - uint32_t reserved_190; - uint32_t reserved_191; - uint32_t iqtimer_pkt_header; - uint32_t iqtimer_pkt_dw0; - uint32_t iqtimer_pkt_dw1; - uint32_t iqtimer_pkt_dw2; - uint32_t iqtimer_pkt_dw3; - uint32_t iqtimer_pkt_dw4; - uint32_t iqtimer_pkt_dw5; - uint32_t iqtimer_pkt_dw6; - uint32_t iqtimer_pkt_dw7; - uint32_t iqtimer_pkt_dw8; - uint32_t iqtimer_pkt_dw9; - uint32_t iqtimer_pkt_dw10; - uint32_t iqtimer_pkt_dw11; - uint32_t iqtimer_pkt_dw12; - uint32_t iqtimer_pkt_dw13; - uint32_t iqtimer_pkt_dw14; - uint32_t iqtimer_pkt_dw15; - uint32_t iqtimer_pkt_dw16; - uint32_t iqtimer_pkt_dw17; - uint32_t iqtimer_pkt_dw18; - uint32_t iqtimer_pkt_dw19; - uint32_t iqtimer_pkt_dw20; - uint32_t iqtimer_pkt_dw21; - uint32_t iqtimer_pkt_dw22; - uint32_t iqtimer_pkt_dw23; - uint32_t iqtimer_pkt_dw24; - uint32_t iqtimer_pkt_dw25; - uint32_t iqtimer_pkt_dw26; - uint32_t iqtimer_pkt_dw27; - uint32_t iqtimer_pkt_dw28; - uint32_t iqtimer_pkt_dw29; - uint32_t iqtimer_pkt_dw30; - uint32_t iqtimer_pkt_dw31; - uint32_t reserved_225; - uint32_t reserved_226; - uint32_t reserved_227; - uint32_t set_resources_header; - uint32_t set_resources_dw1; - uint32_t set_resources_dw2; - uint32_t set_resources_dw3; - uint32_t set_resources_dw4; - uint32_t set_resources_dw5; - uint32_t set_resources_dw6; - uint32_t set_resources_dw7; - uint32_t reserved_236; - uint32_t reserved_237; - uint32_t reserved_238; - uint32_t reserved_239; - uint32_t queue_doorbell_id0; - uint32_t queue_doorbell_id1; - uint32_t queue_doorbell_id2; - uint32_t queue_doorbell_id3; - uint32_t queue_doorbell_id4; - uint32_t queue_doorbell_id5; - uint32_t queue_doorbell_id6; - uint32_t queue_doorbell_id7; - uint32_t queue_doorbell_id8; - uint32_t queue_doorbell_id9; - uint32_t queue_doorbell_id10; - uint32_t queue_doorbell_id11; - uint32_t queue_doorbell_id12; - uint32_t queue_doorbell_id13; - uint32_t queue_doorbell_id14; - uint32_t queue_doorbell_id15; -}; - struct vi_ce_ib_state { uint32_t ce_ib_completion_status; uint32_t ce_constegnine_count; diff --git a/drivers/gpu/drm/amd/lib/Kconfig b/drivers/gpu/drm/amd/lib/Kconfig new file mode 100644 index 0000000..03ee7ad --- /dev/null +++ b/drivers/gpu/drm/amd/lib/Kconfig @@ -0,0 +1,27 @@ +menu "AMD Library routines" + +# +# Closed hash table +# +config CHASH + tristate "Closed hash table" + help + Statically sized closed hash table implementation with low + memory and CPU overhead. + +config CHASH_STATS + bool "Closed hash table performance statistics" + depends on CHASH + default n + help + Enable collection of performance statistics for closed hash tables. + +config CHASH_SELFTEST + bool "Closed hash table self test" + depends on CHASH + default n + help + Runs a selftest during module load. Several module parameters + are available to modify the behaviour of the test. + +endmenu diff --git a/drivers/gpu/drm/amd/lib/Makefile b/drivers/gpu/drm/amd/lib/Makefile new file mode 100644 index 0000000..87cd700 --- /dev/null +++ b/drivers/gpu/drm/amd/lib/Makefile @@ -0,0 +1,11 @@ +# +# Makefile for AMD library routines, which are used by AMD driver +# components. +# +# This is for common library routines that can be shared between AMD +# driver components or later moved to kernel/lib for sharing with +# other drivers. + +ccflags-y := -I$(src)/../include + +obj-$(CONFIG_CHASH) += chash.o diff --git a/drivers/gpu/drm/amd/lib/chash.c b/drivers/gpu/drm/amd/lib/chash.c new file mode 100644 index 0000000..e07e6f3 --- /dev/null +++ b/drivers/gpu/drm/amd/lib/chash.c @@ -0,0 +1,638 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include <linux/types.h> +#include <linux/hash.h> +#include <linux/bug.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/sched/clock.h> +#include <asm/div64.h> +#include <linux/chash.h> + +/** + * chash_table_alloc - Allocate closed hash table + * @table: Pointer to the table structure + * @bits: Table size will be 2^bits entries + * @key_size: Size of hash keys in bytes, 4 or 8 + * @value_size: Size of data values in bytes, can be 0 + */ +int chash_table_alloc(struct chash_table *table, u8 bits, u8 key_size, + unsigned int value_size, gfp_t gfp_mask) +{ + if (bits > 31) + return -EINVAL; + + if (key_size != 4 && key_size != 8) + return -EINVAL; + + table->data = kcalloc(__CHASH_DATA_SIZE(bits, key_size, value_size), + sizeof(long), gfp_mask); + if (!table->data) + return -ENOMEM; + + __CHASH_TABLE_INIT(table->table, table->data, + bits, key_size, value_size); + + return 0; +} +EXPORT_SYMBOL(chash_table_alloc); + +/** + * chash_table_free - Free closed hash table + * @table: Pointer to the table structure + */ +void chash_table_free(struct chash_table *table) +{ + kfree(table->data); +} +EXPORT_SYMBOL(chash_table_free); + +#ifdef CONFIG_CHASH_STATS + +#define DIV_FRAC(nom, denom, quot, frac, frac_digits) do { \ + u64 __nom = (nom); \ + u64 __denom = (denom); \ + u64 __quot, __frac; \ + u32 __rem; \ + \ + while (__denom >> 32) { \ + __nom >>= 1; \ + __denom >>= 1; \ + } \ + __quot = __nom; \ + __rem = do_div(__quot, __denom); \ + __frac = __rem * (frac_digits) + (__denom >> 1); \ + do_div(__frac, __denom); \ + (quot) = __quot; \ + (frac) = __frac; \ + } while (0) + +void __chash_table_dump_stats(struct __chash_table *table) +{ + struct chash_iter iter = CHASH_ITER_INIT(table, 0); + u32 filled = 0, empty = 0, tombstones = 0; + u64 quot1, quot2; + u32 frac1, frac2; + + do { + if (chash_iter_is_valid(iter)) + filled++; + else if (chash_iter_is_empty(iter)) + empty++; + else + tombstones++; + CHASH_ITER_INC(iter); + } while (iter.slot); + + pr_debug("chash: key size %u, value size %u\n", + table->key_size, table->value_size); + pr_debug(" Slots total/filled/empty/tombstones: %u / %u / %u / %u\n", + 1 << table->bits, filled, empty, tombstones); + if (table->hits > 0) { + DIV_FRAC(table->hits_steps, table->hits, quot1, frac1, 1000); + DIV_FRAC(table->hits * 1000, table->hits_time_ns, + quot2, frac2, 1000); + } else { + quot1 = quot2 = 0; + frac1 = frac2 = 0; + } + pr_debug(" Hits (avg.cost, rate): %llu (%llu.%03u, %llu.%03u M/s)\n", + table->hits, quot1, frac1, quot2, frac2); + if (table->miss > 0) { + DIV_FRAC(table->miss_steps, table->miss, quot1, frac1, 1000); + DIV_FRAC(table->miss * 1000, table->miss_time_ns, + quot2, frac2, 1000); + } else { + quot1 = quot2 = 0; + frac1 = frac2 = 0; + } + pr_debug(" Misses (avg.cost, rate): %llu (%llu.%03u, %llu.%03u M/s)\n", + table->miss, quot1, frac1, quot2, frac2); + if (table->hits + table->miss > 0) { + DIV_FRAC(table->hits_steps + table->miss_steps, + table->hits + table->miss, quot1, frac1, 1000); + DIV_FRAC((table->hits + table->miss) * 1000, + (table->hits_time_ns + table->miss_time_ns), + quot2, frac2, 1000); + } else { + quot1 = quot2 = 0; + frac1 = frac2 = 0; + } + pr_debug(" Total (avg.cost, rate): %llu (%llu.%03u, %llu.%03u M/s)\n", + table->hits + table->miss, quot1, frac1, quot2, frac2); + if (table->relocs > 0) { + DIV_FRAC(table->hits + table->miss, table->relocs, + quot1, frac1, 1000); + DIV_FRAC(table->reloc_dist, table->relocs, quot2, frac2, 1000); + pr_debug(" Relocations (freq, avg.dist): %llu (1:%llu.%03u, %llu.%03u)\n", + table->relocs, quot1, frac1, quot2, frac2); + } else { + pr_debug(" No relocations\n"); + } +} +EXPORT_SYMBOL(__chash_table_dump_stats); + +#undef DIV_FRAC +#endif + +#define CHASH_INC(table, a) ((a) = ((a) + 1) & (table)->size_mask) +#define CHASH_ADD(table, a, b) (((a) + (b)) & (table)->size_mask) +#define CHASH_SUB(table, a, b) (((a) - (b)) & (table)->size_mask) +#define CHASH_IN_RANGE(table, slot, first, last) \ + (CHASH_SUB(table, slot, first) <= CHASH_SUB(table, last, first)) + +/*#define CHASH_DEBUG Uncomment this to enable verbose debug output*/ +#ifdef CHASH_DEBUG +static void chash_table_dump(struct __chash_table *table) +{ + struct chash_iter iter = CHASH_ITER_INIT(table, 0); + + do { + if ((iter.slot & 3) == 0) + pr_debug("%04x: ", iter.slot); + + if (chash_iter_is_valid(iter)) + pr_debug("[%016llx] ", chash_iter_key(iter)); + else if (chash_iter_is_empty(iter)) + pr_debug("[ <empty> ] "); + else + pr_debug("[ <tombstone> ] "); + + if ((iter.slot & 3) == 3) + pr_debug("\n"); + + CHASH_ITER_INC(iter); + } while (iter.slot); + + if ((iter.slot & 3) != 0) + pr_debug("\n"); +} + +static int chash_table_check(struct __chash_table *table) +{ + u32 hash; + struct chash_iter iter = CHASH_ITER_INIT(table, 0); + struct chash_iter cur = CHASH_ITER_INIT(table, 0); + + do { + if (!chash_iter_is_valid(iter)) { + CHASH_ITER_INC(iter); + continue; + } + + hash = chash_iter_hash(iter); + CHASH_ITER_SET(cur, hash); + while (cur.slot != iter.slot) { + if (chash_iter_is_empty(cur)) { + pr_err("Path to element at %x with hash %x broken at slot %x\n", + iter.slot, hash, cur.slot); + chash_table_dump(table); + return -EINVAL; + } + CHASH_ITER_INC(cur); + } + + CHASH_ITER_INC(iter); + } while (iter.slot); + + return 0; +} +#endif + +static void chash_iter_relocate(struct chash_iter dst, struct chash_iter src) +{ + BUG_ON(src.table == dst.table && src.slot == dst.slot); + BUG_ON(src.table->key_size != src.table->key_size); + BUG_ON(src.table->value_size != src.table->value_size); + + if (dst.table->key_size == 4) + dst.table->keys32[dst.slot] = src.table->keys32[src.slot]; + else + dst.table->keys64[dst.slot] = src.table->keys64[src.slot]; + + if (dst.table->value_size) + memcpy(chash_iter_value(dst), chash_iter_value(src), + dst.table->value_size); + + chash_iter_set_valid(dst); + chash_iter_set_invalid(src); + +#ifdef CONFIG_CHASH_STATS + if (src.table == dst.table) { + dst.table->relocs++; + dst.table->reloc_dist += + CHASH_SUB(dst.table, src.slot, dst.slot); + } +#endif +} + +/** + * __chash_table_find - Helper for looking up a hash table entry + * @iter: Pointer to hash table iterator + * @key: Key of the entry to find + * @for_removal: set to true if the element will be removed soon + * + * Searches for an entry in the hash table with a given key. iter must + * be initialized by the caller to point to the home position of the + * hypothetical entry, i.e. it must be initialized with the hash table + * and the key's hash as the initial slot for the search. + * + * This function also does some local clean-up to speed up future + * look-ups by relocating entries to better slots and removing + * tombstones that are no longer needed. + * + * If @for_removal is true, the function avoids relocating the entry + * that is being returned. + * + * Returns 0 if the search is successful. In this case iter is updated + * to point to the found entry. Otherwise %-EINVAL is returned and the + * iter is updated to point to the first available slot for the given + * key. If the table is full, the slot is set to -1. + */ +static int chash_table_find(struct chash_iter *iter, u64 key, + bool for_removal) +{ +#ifdef CONFIG_CHASH_STATS + u64 ts1 = local_clock(); +#endif + u32 hash = iter->slot; + struct chash_iter first_redundant = CHASH_ITER_INIT(iter->table, -1); + int first_avail = (for_removal ? -2 : -1); + + while (!chash_iter_is_valid(*iter) || chash_iter_key(*iter) != key) { + if (chash_iter_is_empty(*iter)) { + /* Found an empty slot, which ends the + * search. Clean up any preceding tombstones + * that are no longer needed because they lead + * to no-where + */ + if ((int)first_redundant.slot < 0) + goto not_found; + while (first_redundant.slot != iter->slot) { + if (!chash_iter_is_valid(first_redundant)) + chash_iter_set_empty(first_redundant); + CHASH_ITER_INC(first_redundant); + } +#ifdef CHASH_DEBUG + chash_table_check(iter->table); +#endif + goto not_found; + } else if (!chash_iter_is_valid(*iter)) { + /* Found a tombstone. Remember it as candidate + * for relocating the entry we're looking for + * or for adding a new entry with the given key + */ + if (first_avail == -1) + first_avail = iter->slot; + /* Or mark it as the start of a series of + * potentially redundant tombstones + */ + else if (first_redundant.slot == -1) + CHASH_ITER_SET(first_redundant, iter->slot); + } else if (first_redundant.slot >= 0) { + /* Found a valid, occupied slot with a + * preceding series of tombstones. Relocate it + * to a better position that no longer depends + * on those tombstones + */ + u32 cur_hash = chash_iter_hash(*iter); + + if (!CHASH_IN_RANGE(iter->table, cur_hash, + first_redundant.slot + 1, + iter->slot)) { + /* This entry has a hash at or before + * the first tombstone we found. We + * can relocate it to that tombstone + * and advance to the next tombstone + */ + chash_iter_relocate(first_redundant, *iter); + do { + CHASH_ITER_INC(first_redundant); + } while (chash_iter_is_valid(first_redundant)); + } else if (cur_hash != iter->slot) { + /* Relocate entry to its home position + * or as close as possible so it no + * longer depends on any preceding + * tombstones + */ + struct chash_iter new_iter = + CHASH_ITER_INIT(iter->table, cur_hash); + + while (new_iter.slot != iter->slot && + chash_iter_is_valid(new_iter)) + CHASH_ITER_INC(new_iter); + + if (new_iter.slot != iter->slot) + chash_iter_relocate(new_iter, *iter); + } + } + + CHASH_ITER_INC(*iter); + if (iter->slot == hash) { + iter->slot = -1; + goto not_found; + } + } + +#ifdef CONFIG_CHASH_STATS + iter->table->hits++; + iter->table->hits_steps += CHASH_SUB(iter->table, iter->slot, hash) + 1; +#endif + + if (first_avail >= 0) { + CHASH_ITER_SET(first_redundant, first_avail); + chash_iter_relocate(first_redundant, *iter); + iter->slot = first_redundant.slot; + iter->mask = first_redundant.mask; + } + +#ifdef CONFIG_CHASH_STATS + iter->table->hits_time_ns += local_clock() - ts1; +#endif + + return 0; + +not_found: +#ifdef CONFIG_CHASH_STATS + iter->table->miss++; + iter->table->miss_steps += (iter->slot < 0) ? + (1 << iter->table->bits) : + CHASH_SUB(iter->table, iter->slot, hash) + 1; +#endif + + if (first_avail >= 0) + CHASH_ITER_SET(*iter, first_avail); + +#ifdef CONFIG_CHASH_STATS + iter->table->miss_time_ns += local_clock() - ts1; +#endif + + return -EINVAL; +} + +int __chash_table_copy_in(struct __chash_table *table, u64 key, + const void *value) +{ + u32 hash = (table->key_size == 4) ? + hash_32(key, table->bits) : hash_64(key, table->bits); + struct chash_iter iter = CHASH_ITER_INIT(table, hash); + int r = chash_table_find(&iter, key, false); + + /* Found an existing entry */ + if (!r) { + if (value && table->value_size) + memcpy(chash_iter_value(iter), value, + table->value_size); + return 1; + } + + /* Is there a place to add a new entry? */ + if (iter.slot < 0) { + pr_err("Hash table overflow\n"); + return -ENOMEM; + } + + chash_iter_set_valid(iter); + + if (table->key_size == 4) + table->keys32[iter.slot] = key; + else + table->keys64[iter.slot] = key; + if (value && table->value_size) + memcpy(chash_iter_value(iter), value, table->value_size); + + return 0; +} +EXPORT_SYMBOL(__chash_table_copy_in); + +int __chash_table_copy_out(struct __chash_table *table, u64 key, + void *value, bool remove) +{ + u32 hash = (table->key_size == 4) ? + hash_32(key, table->bits) : hash_64(key, table->bits); + struct chash_iter iter = CHASH_ITER_INIT(table, hash); + int r = chash_table_find(&iter, key, remove); + + if (r < 0) + return r; + + if (value && table->value_size) + memcpy(value, chash_iter_value(iter), table->value_size); + + if (remove) + chash_iter_set_invalid(iter); + + return iter.slot; +} +EXPORT_SYMBOL(__chash_table_copy_out); + +#ifdef CONFIG_CHASH_SELFTEST +/** + * chash_self_test - Run a self-test of the hash table implementation + * @bits: Table size will be 2^bits entries + * @key_size: Size of hash keys in bytes, 4 or 8 + * @min_fill: Minimum fill level during the test + * @max_fill: Maximum fill level during the test + * @iterations: Number of test iterations + * + * The test adds and removes entries from a hash table, cycling the + * fill level between min_fill and max_fill entries. Also tests lookup + * and value retrieval. + */ +static int __init chash_self_test(u8 bits, u8 key_size, + int min_fill, int max_fill, + u64 iterations) +{ + struct chash_table table; + int ret; + u64 add_count, rmv_count; + u64 value; + + if (key_size == 4 && iterations > 0xffffffff) + return -EINVAL; + if (min_fill >= max_fill) + return -EINVAL; + + ret = chash_table_alloc(&table, bits, key_size, sizeof(u64), + GFP_KERNEL); + if (ret) { + pr_err("chash_table_alloc failed: %d\n", ret); + return ret; + } + + for (add_count = 0, rmv_count = 0; add_count < iterations; + add_count++) { + /* When we hit the max_fill level, remove entries down + * to min_fill + */ + if (add_count - rmv_count == max_fill) { + u64 find_count = rmv_count; + + /* First try to find all entries that we're + * about to remove, confirm their value, test + * writing them back a second time. + */ + for (; add_count - find_count > min_fill; + find_count++) { + ret = chash_table_copy_out(&table, find_count, + &value); + if (ret < 0) { + pr_err("chash_table_copy_out failed: %d\n", + ret); + goto out; + } + if (value != ~find_count) { + pr_err("Wrong value retrieved for key 0x%llx, expected 0x%llx got 0x%llx\n", + find_count, ~find_count, value); +#ifdef CHASH_DEBUG + chash_table_dump(&table.table); +#endif + ret = -EFAULT; + goto out; + } + ret = chash_table_copy_in(&table, find_count, + &value); + if (ret != 1) { + pr_err("copy_in second time returned %d, expected 1\n", + ret); + ret = -EFAULT; + goto out; + } + } + /* Remove them until we hit min_fill level */ + for (; add_count - rmv_count > min_fill; rmv_count++) { + ret = chash_table_remove(&table, rmv_count, + NULL); + if (ret < 0) { + pr_err("chash_table_remove failed: %d\n", + ret); + goto out; + } + } + } + + /* Add a new value */ + value = ~add_count; + ret = chash_table_copy_in(&table, add_count, &value); + if (ret != 0) { + pr_err("copy_in first time returned %d, expected 0\n", + ret); + ret = -EFAULT; + goto out; + } + } + + chash_table_dump_stats(&table); + chash_table_reset_stats(&table); + +out: + chash_table_free(&table); + return ret; +} + +static unsigned int chash_test_bits = 10; +MODULE_PARM_DESC(test_bits, + "Selftest number of hash bits ([4..20], default=10)"); +module_param_named(test_bits, chash_test_bits, uint, 0444); + +static unsigned int chash_test_keysize = 8; +MODULE_PARM_DESC(test_keysize, "Selftest keysize (4 or 8, default=8)"); +module_param_named(test_keysize, chash_test_keysize, uint, 0444); + +static unsigned int chash_test_minfill; +MODULE_PARM_DESC(test_minfill, "Selftest minimum #entries (default=50%)"); +module_param_named(test_minfill, chash_test_minfill, uint, 0444); + +static unsigned int chash_test_maxfill; +MODULE_PARM_DESC(test_maxfill, "Selftest maximum #entries (default=80%)"); +module_param_named(test_maxfill, chash_test_maxfill, uint, 0444); + +static unsigned long chash_test_iters; +MODULE_PARM_DESC(test_iters, "Selftest iterations (default=1000 x #entries)"); +module_param_named(test_iters, chash_test_iters, ulong, 0444); + +static int __init chash_init(void) +{ + int ret; + u64 ts1_ns; + + /* Skip self test on user errors */ + if (chash_test_bits < 4 || chash_test_bits > 20) { + pr_err("chash: test_bits out of range [4..20].\n"); + return 0; + } + if (chash_test_keysize != 4 && chash_test_keysize != 8) { + pr_err("chash: test_keysize invalid. Must be 4 or 8.\n"); + return 0; + } + + if (!chash_test_minfill) + chash_test_minfill = (1 << chash_test_bits) / 2; + if (!chash_test_maxfill) + chash_test_maxfill = (1 << chash_test_bits) * 4 / 5; + if (!chash_test_iters) + chash_test_iters = (1 << chash_test_bits) * 1000; + + if (chash_test_minfill >= (1 << chash_test_bits)) { + pr_err("chash: test_minfill too big. Must be < table size.\n"); + return 0; + } + if (chash_test_maxfill >= (1 << chash_test_bits)) { + pr_err("chash: test_maxfill too big. Must be < table size.\n"); + return 0; + } + if (chash_test_minfill >= chash_test_maxfill) { + pr_err("chash: test_minfill must be < test_maxfill.\n"); + return 0; + } + if (chash_test_keysize == 4 && chash_test_iters > 0xffffffff) { + pr_err("chash: test_iters must be < 4G for 4 byte keys.\n"); + return 0; + } + + ts1_ns = local_clock(); + ret = chash_self_test(chash_test_bits, chash_test_keysize, + chash_test_minfill, chash_test_maxfill, + chash_test_iters); + if (!ret) { + u64 ts_delta_us = local_clock() - ts1_ns; + u64 iters_per_second = (u64)chash_test_iters * 1000000; + + do_div(ts_delta_us, 1000); + do_div(iters_per_second, ts_delta_us); + pr_info("chash: self test took %llu us, %llu iterations/s\n", + ts_delta_us, iters_per_second); + } else { + pr_err("chash: self test failed: %d\n", ret); + } + + return ret; +} + +module_init(chash_init); + +#endif /* CONFIG_CHASH_SELFTEST */ + +MODULE_DESCRIPTION("Closed hash table"); +MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/gpu/drm/amd/powerplay/Makefile b/drivers/gpu/drm/amd/powerplay/Makefile index 4e132b9..68b417a 100644 --- a/drivers/gpu/drm/amd/powerplay/Makefile +++ b/drivers/gpu/drm/amd/powerplay/Makefile @@ -4,12 +4,11 @@ subdir-ccflags-y += \ -I$(FULL_AMD_PATH)/include/asic_reg \ -I$(FULL_AMD_PATH)/include \ -I$(FULL_AMD_PATH)/powerplay/smumgr\ - -I$(FULL_AMD_PATH)/powerplay/hwmgr \ - -I$(FULL_AMD_PATH)/powerplay/eventmgr + -I$(FULL_AMD_PATH)/powerplay/hwmgr AMD_PP_PATH = ../powerplay -PP_LIBS = smumgr hwmgr eventmgr +PP_LIBS = smumgr hwmgr AMD_POWERPLAY = $(addsuffix /Makefile,$(addprefix $(FULL_AMD_PATH)/powerplay/,$(PP_LIBS))) diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c index f73e80c..9f3f3b8 100644 --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c @@ -29,22 +29,19 @@ #include "amd_powerplay.h" #include "pp_instance.h" #include "power_state.h" -#include "eventmanager.h" - static inline int pp_check(struct pp_instance *handle) { if (handle == NULL || handle->pp_valid != PP_VALID) return -EINVAL; - if (handle->smu_mgr == NULL || handle->smu_mgr->smumgr_funcs == NULL) + if (handle->hwmgr == NULL || handle->hwmgr->smumgr_funcs == NULL) return -EINVAL; if (handle->pm_en == 0) return PP_DPM_DISABLED; - if (handle->hwmgr == NULL || handle->hwmgr->hwmgr_func == NULL - || handle->eventmgr == NULL) + if (handle->hwmgr->hwmgr_func == NULL) return PP_DPM_DISABLED; return 0; @@ -55,46 +52,32 @@ static int pp_early_init(void *handle) int ret; struct pp_instance *pp_handle = (struct pp_instance *)handle; - ret = smum_early_init(pp_handle); + ret = hwmgr_early_init(pp_handle); if (ret) - return ret; + return -EINVAL; if ((pp_handle->pm_en == 0) || cgs_is_virtualization_enabled(pp_handle->device)) return PP_DPM_DISABLED; - ret = hwmgr_early_init(pp_handle); - if (ret) { - pp_handle->pm_en = 0; - return PP_DPM_DISABLED; - } - - ret = eventmgr_early_init(pp_handle); - if (ret) { - kfree(pp_handle->hwmgr); - pp_handle->hwmgr = NULL; - pp_handle->pm_en = 0; - return PP_DPM_DISABLED; - } - return 0; } static int pp_sw_init(void *handle) { - struct pp_smumgr *smumgr; + struct pp_hwmgr *hwmgr; int ret = 0; struct pp_instance *pp_handle = (struct pp_instance *)handle; ret = pp_check(pp_handle); if (ret == 0 || ret == PP_DPM_DISABLED) { - smumgr = pp_handle->smu_mgr; + hwmgr = pp_handle->hwmgr; - if (smumgr->smumgr_funcs->smu_init == NULL) + if (hwmgr->smumgr_funcs->smu_init == NULL) return -EINVAL; - ret = smumgr->smumgr_funcs->smu_init(smumgr); + ret = hwmgr->smumgr_funcs->smu_init(hwmgr); pr_info("amdgpu: powerplay sw initialized\n"); } @@ -103,40 +86,39 @@ static int pp_sw_init(void *handle) static int pp_sw_fini(void *handle) { - struct pp_smumgr *smumgr; + struct pp_hwmgr *hwmgr; int ret = 0; struct pp_instance *pp_handle = (struct pp_instance *)handle; ret = pp_check(pp_handle); if (ret == 0 || ret == PP_DPM_DISABLED) { - smumgr = pp_handle->smu_mgr; + hwmgr = pp_handle->hwmgr; - if (smumgr->smumgr_funcs->smu_fini == NULL) + if (hwmgr->smumgr_funcs->smu_fini == NULL) return -EINVAL; - ret = smumgr->smumgr_funcs->smu_fini(smumgr); + ret = hwmgr->smumgr_funcs->smu_fini(pp_handle->hwmgr); } return ret; } static int pp_hw_init(void *handle) { - struct pp_smumgr *smumgr; - struct pp_eventmgr *eventmgr; int ret = 0; struct pp_instance *pp_handle = (struct pp_instance *)handle; + struct pp_hwmgr *hwmgr; ret = pp_check(pp_handle); if (ret == 0 || ret == PP_DPM_DISABLED) { - smumgr = pp_handle->smu_mgr; + hwmgr = pp_handle->hwmgr; - if (smumgr->smumgr_funcs->start_smu == NULL) + if (hwmgr->smumgr_funcs->start_smu == NULL) return -EINVAL; - if(smumgr->smumgr_funcs->start_smu(smumgr)) { + if(hwmgr->smumgr_funcs->start_smu(pp_handle->hwmgr)) { pr_err("smc start failed\n"); - smumgr->smumgr_funcs->smu_fini(smumgr); + hwmgr->smumgr_funcs->smu_fini(pp_handle->hwmgr); return -EINVAL;; } if (ret == PP_DPM_DISABLED) @@ -146,38 +128,21 @@ static int pp_hw_init(void *handle) ret = hwmgr_hw_init(pp_handle); if (ret) goto err; - - eventmgr = pp_handle->eventmgr; - if (eventmgr->pp_eventmgr_init == NULL || - eventmgr->pp_eventmgr_init(eventmgr)) - goto err; - return 0; err: pp_handle->pm_en = 0; - kfree(pp_handle->eventmgr); - kfree(pp_handle->hwmgr); - pp_handle->hwmgr = NULL; - pp_handle->eventmgr = NULL; return PP_DPM_DISABLED; } static int pp_hw_fini(void *handle) { - struct pp_eventmgr *eventmgr; struct pp_instance *pp_handle = (struct pp_instance *)handle; int ret = 0; ret = pp_check(pp_handle); - - if (ret == 0) { - eventmgr = pp_handle->eventmgr; - - if (eventmgr->pp_eventmgr_fini != NULL) - eventmgr->pp_eventmgr_fini(eventmgr); - + if (ret == 0) hwmgr_hw_fini(pp_handle); - } + return 0; } @@ -244,8 +209,6 @@ static int pp_set_powergating_state(void *handle, static int pp_suspend(void *handle) { - struct pp_eventmgr *eventmgr; - struct pem_event_data event_data = { {0} }; struct pp_instance *pp_handle = (struct pp_instance *)handle; int ret = 0; @@ -256,17 +219,12 @@ static int pp_suspend(void *handle) else if (ret != 0) return ret; - eventmgr = pp_handle->eventmgr; - pem_handle_event(eventmgr, AMD_PP_EVENT_SUSPEND, &event_data); - - return 0; + return hwmgr_hw_suspend(pp_handle); } static int pp_resume(void *handle) { - struct pp_eventmgr *eventmgr; - struct pem_event_data event_data = { {0} }; - struct pp_smumgr *smumgr; + struct pp_hwmgr *hwmgr; int ret, ret1; struct pp_instance *pp_handle = (struct pp_instance *)handle; @@ -275,26 +233,22 @@ static int pp_resume(void *handle) if (ret1 != 0 && ret1 != PP_DPM_DISABLED) return ret1; - smumgr = pp_handle->smu_mgr; + hwmgr = pp_handle->hwmgr; - if (smumgr->smumgr_funcs->start_smu == NULL) + if (hwmgr->smumgr_funcs->start_smu == NULL) return -EINVAL; - ret = smumgr->smumgr_funcs->start_smu(smumgr); + ret = hwmgr->smumgr_funcs->start_smu(pp_handle->hwmgr); if (ret) { pr_err("smc start failed\n"); - smumgr->smumgr_funcs->smu_fini(smumgr); + hwmgr->smumgr_funcs->smu_fini(pp_handle->hwmgr); return ret; } if (ret1 == PP_DPM_DISABLED) return 0; - eventmgr = pp_handle->eventmgr; - - pem_handle_event(eventmgr, AMD_PP_EVENT_RESUME, &event_data); - - return 0; + return hwmgr_hw_resume(pp_handle); } const struct amd_ip_funcs pp_ip_funcs = { @@ -324,6 +278,42 @@ static int pp_dpm_fw_loading_complete(void *handle) return 0; } +static void pp_dpm_en_umd_pstate(struct pp_hwmgr *hwmgr, + enum amd_dpm_forced_level *level) +{ + uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | + AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | + AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | + AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; + + if (!(hwmgr->dpm_level & profile_mode_mask)) { + /* enter umd pstate, save current level, disable gfx cg*/ + if (*level & profile_mode_mask) { + hwmgr->saved_dpm_level = hwmgr->dpm_level; + hwmgr->en_umd_pstate = true; + cgs_set_clockgating_state(hwmgr->device, + AMD_IP_BLOCK_TYPE_GFX, + AMD_CG_STATE_UNGATE); + cgs_set_powergating_state(hwmgr->device, + AMD_IP_BLOCK_TYPE_GFX, + AMD_PG_STATE_UNGATE); + } + } else { + /* exit umd pstate, restore level, enable gfx cg*/ + if (!(*level & profile_mode_mask)) { + if (*level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT) + *level = hwmgr->saved_dpm_level; + hwmgr->en_umd_pstate = false; + cgs_set_clockgating_state(hwmgr->device, + AMD_IP_BLOCK_TYPE_GFX, + AMD_CG_STATE_GATE); + cgs_set_powergating_state(hwmgr->device, + AMD_IP_BLOCK_TYPE_GFX, + AMD_PG_STATE_GATE); + } + } +} + static int pp_dpm_force_performance_level(void *handle, enum amd_dpm_forced_level level) { @@ -338,13 +328,22 @@ static int pp_dpm_force_performance_level(void *handle, hwmgr = pp_handle->hwmgr; + if (level == hwmgr->dpm_level) + return 0; + if (hwmgr->hwmgr_func->force_dpm_level == NULL) { pr_info("%s was not implemented.\n", __func__); return 0; } mutex_lock(&pp_handle->pp_lock); - hwmgr->hwmgr_func->force_dpm_level(hwmgr, level); + pp_dpm_en_umd_pstate(hwmgr, &level); + hwmgr->request_dpm_level = level; + hwmgr_handle_task(pp_handle, AMD_PP_TASK_READJUST_POWER_STATE, NULL, NULL); + ret = hwmgr->hwmgr_func->force_dpm_level(hwmgr, level); + if (!ret) + hwmgr->dpm_level = hwmgr->request_dpm_level; + mutex_unlock(&pp_handle->pp_lock); return 0; } @@ -369,11 +368,12 @@ static enum amd_dpm_forced_level pp_dpm_get_performance_level( return level; } -static int pp_dpm_get_sclk(void *handle, bool low) +static uint32_t pp_dpm_get_sclk(void *handle, bool low) { struct pp_hwmgr *hwmgr; struct pp_instance *pp_handle = (struct pp_instance *)handle; int ret = 0; + uint32_t clk = 0; ret = pp_check(pp_handle); @@ -387,16 +387,17 @@ static int pp_dpm_get_sclk(void *handle, bool low) return 0; } mutex_lock(&pp_handle->pp_lock); - ret = hwmgr->hwmgr_func->get_sclk(hwmgr, low); + clk = hwmgr->hwmgr_func->get_sclk(hwmgr, low); mutex_unlock(&pp_handle->pp_lock); - return ret; + return clk; } -static int pp_dpm_get_mclk(void *handle, bool low) +static uint32_t pp_dpm_get_mclk(void *handle, bool low) { struct pp_hwmgr *hwmgr; struct pp_instance *pp_handle = (struct pp_instance *)handle; int ret = 0; + uint32_t clk = 0; ret = pp_check(pp_handle); @@ -410,12 +411,12 @@ static int pp_dpm_get_mclk(void *handle, bool low) return 0; } mutex_lock(&pp_handle->pp_lock); - ret = hwmgr->hwmgr_func->get_mclk(hwmgr, low); + clk = hwmgr->hwmgr_func->get_mclk(hwmgr, low); mutex_unlock(&pp_handle->pp_lock); - return ret; + return clk; } -static int pp_dpm_powergate_vce(void *handle, bool gate) +static void pp_dpm_powergate_vce(void *handle, bool gate) { struct pp_hwmgr *hwmgr; struct pp_instance *pp_handle = (struct pp_instance *)handle; @@ -424,21 +425,20 @@ static int pp_dpm_powergate_vce(void *handle, bool gate) ret = pp_check(pp_handle); if (ret != 0) - return ret; + return; hwmgr = pp_handle->hwmgr; if (hwmgr->hwmgr_func->powergate_vce == NULL) { pr_info("%s was not implemented.\n", __func__); - return 0; + return; } mutex_lock(&pp_handle->pp_lock); - ret = hwmgr->hwmgr_func->powergate_vce(hwmgr, gate); + hwmgr->hwmgr_func->powergate_vce(hwmgr, gate); mutex_unlock(&pp_handle->pp_lock); - return ret; } -static int pp_dpm_powergate_uvd(void *handle, bool gate) +static void pp_dpm_powergate_uvd(void *handle, bool gate) { struct pp_hwmgr *hwmgr; struct pp_instance *pp_handle = (struct pp_instance *)handle; @@ -447,74 +447,34 @@ static int pp_dpm_powergate_uvd(void *handle, bool gate) ret = pp_check(pp_handle); if (ret != 0) - return ret; + return; hwmgr = pp_handle->hwmgr; if (hwmgr->hwmgr_func->powergate_uvd == NULL) { pr_info("%s was not implemented.\n", __func__); - return 0; + return; } mutex_lock(&pp_handle->pp_lock); - ret = hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate); + hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate); mutex_unlock(&pp_handle->pp_lock); - return ret; } -static enum PP_StateUILabel power_state_convert(enum amd_pm_state_type state) -{ - switch (state) { - case POWER_STATE_TYPE_BATTERY: - return PP_StateUILabel_Battery; - case POWER_STATE_TYPE_BALANCED: - return PP_StateUILabel_Balanced; - case POWER_STATE_TYPE_PERFORMANCE: - return PP_StateUILabel_Performance; - default: - return PP_StateUILabel_None; - } -} - -static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_event event_id, +static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_task task_id, void *input, void *output) { int ret = 0; - struct pem_event_data data = { {0} }; struct pp_instance *pp_handle = (struct pp_instance *)handle; ret = pp_check(pp_handle); if (ret != 0) return ret; - mutex_lock(&pp_handle->pp_lock); - switch (event_id) { - case AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE: - ret = pem_handle_event(pp_handle->eventmgr, event_id, &data); - break; - case AMD_PP_EVENT_ENABLE_USER_STATE: - { - enum amd_pm_state_type ps; - - if (input == NULL) { - ret = -EINVAL; - break; - } - ps = *(unsigned long *)input; - data.requested_ui_label = power_state_convert(ps); - ret = pem_handle_event(pp_handle->eventmgr, event_id, &data); - break; - } - case AMD_PP_EVENT_COMPLETE_INIT: - ret = pem_handle_event(pp_handle->eventmgr, event_id, &data); - break; - case AMD_PP_EVENT_READJUST_POWER_STATE: - ret = pem_handle_event(pp_handle->eventmgr, event_id, &data); - break; - default: - break; - } + mutex_lock(&pp_handle->pp_lock); + ret = hwmgr_handle_task(pp_handle, task_id, input, output); mutex_unlock(&pp_handle->pp_lock); + return ret; } @@ -562,7 +522,7 @@ static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle) return pm_type; } -static int pp_dpm_set_fan_control_mode(void *handle, uint32_t mode) +static void pp_dpm_set_fan_control_mode(void *handle, uint32_t mode) { struct pp_hwmgr *hwmgr; struct pp_instance *pp_handle = (struct pp_instance *)handle; @@ -571,25 +531,25 @@ static int pp_dpm_set_fan_control_mode(void *handle, uint32_t mode) ret = pp_check(pp_handle); if (ret != 0) - return ret; + return; hwmgr = pp_handle->hwmgr; if (hwmgr->hwmgr_func->set_fan_control_mode == NULL) { pr_info("%s was not implemented.\n", __func__); - return 0; + return; } mutex_lock(&pp_handle->pp_lock); - ret = hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode); + hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode); mutex_unlock(&pp_handle->pp_lock); - return ret; } -static int pp_dpm_get_fan_control_mode(void *handle) +static uint32_t pp_dpm_get_fan_control_mode(void *handle) { struct pp_hwmgr *hwmgr; struct pp_instance *pp_handle = (struct pp_instance *)handle; int ret = 0; + uint32_t mode = 0; ret = pp_check(pp_handle); @@ -603,9 +563,9 @@ static int pp_dpm_get_fan_control_mode(void *handle) return 0; } mutex_lock(&pp_handle->pp_lock); - ret = hwmgr->hwmgr_func->get_fan_control_mode(hwmgr); + mode = hwmgr->hwmgr_func->get_fan_control_mode(hwmgr); mutex_unlock(&pp_handle->pp_lock); - return ret; + return mode; } static int pp_dpm_set_fan_speed_percent(void *handle, uint32_t percent) @@ -1128,7 +1088,7 @@ static int pp_dpm_switch_power_profile(void *handle, return 0; } -const struct amd_powerplay_funcs pp_dpm_funcs = { +const struct amd_pm_funcs pp_dpm_funcs = { .get_temperature = pp_dpm_get_temperature, .load_firmware = pp_dpm_load_fw, .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete, @@ -1189,15 +1149,9 @@ int amd_powerplay_destroy(void *handle) { struct pp_instance *instance = (struct pp_instance *)handle; - if (instance->pm_en) { - kfree(instance->eventmgr); - kfree(instance->hwmgr); - instance->hwmgr = NULL; - instance->eventmgr = NULL; - } + kfree(instance->hwmgr); + instance->hwmgr = NULL; - kfree(instance->smu_mgr); - instance->smu_mgr = NULL; kfree(instance); instance = NULL; return 0; @@ -1206,18 +1160,16 @@ int amd_powerplay_destroy(void *handle) int amd_powerplay_reset(void *handle) { struct pp_instance *instance = (struct pp_instance *)handle; - struct pp_eventmgr *eventmgr; - struct pem_event_data event_data = { {0} }; int ret; - if (cgs_is_virtualization_enabled(instance->smu_mgr->device)) + if (cgs_is_virtualization_enabled(instance->hwmgr->device)) return PP_DPM_DISABLED; ret = pp_check(instance); if (ret != 0) return ret; - ret = pp_hw_fini(handle); + ret = pp_hw_fini(instance); if (ret) return ret; @@ -1225,16 +1177,7 @@ int amd_powerplay_reset(void *handle) if (ret) return PP_DPM_DISABLED; - eventmgr = instance->eventmgr; - - if (eventmgr->pp_eventmgr_init == NULL) - return PP_DPM_DISABLED; - - ret = eventmgr->pp_eventmgr_init(eventmgr); - if (ret) - return ret; - - return pem_handle_event(eventmgr, AMD_PP_EVENT_COMPLETE_INIT, &event_data); + return hwmgr_handle_task(instance, AMD_PP_TASK_COMPLETE_INIT, NULL, NULL); } /* export this function to DAL */ diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/Makefile b/drivers/gpu/drm/amd/powerplay/eventmgr/Makefile deleted file mode 100644 index 7509e38..0000000 --- a/drivers/gpu/drm/amd/powerplay/eventmgr/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# -# Makefile for the 'event manager' sub-component of powerplay. -# It provides the event management services for the driver. - -EVENT_MGR = eventmgr.o eventinit.o eventmanagement.o \ - eventactionchains.o eventsubchains.o eventtasks.o psm.o - -AMD_PP_EVENT = $(addprefix $(AMD_PP_PATH)/eventmgr/,$(EVENT_MGR)) - -AMD_POWERPLAY_FILES += $(AMD_PP_EVENT) - diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.c b/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.c deleted file mode 100644 index 8cee4e0..0000000 --- a/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.c +++ /dev/null @@ -1,291 +0,0 @@ -/* - * Copyright 2015 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 "eventmgr.h" -#include "eventactionchains.h" -#include "eventsubchains.h" - -static const pem_event_action * const initialize_event[] = { - block_adjust_power_state_tasks, - power_budget_tasks, - system_config_tasks, - setup_asic_tasks, - enable_dynamic_state_management_tasks, - get_2d_performance_state_tasks, - set_performance_state_tasks, - initialize_thermal_controller_tasks, - conditionally_force_3d_performance_state_tasks, - process_vbios_eventinfo_tasks, - broadcast_power_policy_tasks, - NULL -}; - -const struct action_chain initialize_action_chain = { - "Initialize", - initialize_event -}; - -static const pem_event_action * const uninitialize_event[] = { - ungate_all_display_phys_tasks, - uninitialize_display_phy_access_tasks, - disable_gfx_voltage_island_power_gating_tasks, - disable_gfx_clock_gating_tasks, - uninitialize_thermal_controller_tasks, - set_boot_state_tasks, - adjust_power_state_tasks, - disable_dynamic_state_management_tasks, - disable_clock_power_gatings_tasks, - cleanup_asic_tasks, - prepare_for_pnp_stop_tasks, - NULL -}; - -const struct action_chain uninitialize_action_chain = { - "Uninitialize", - uninitialize_event -}; - -static const pem_event_action * const power_source_change_event_pp_enabled[] = { - set_power_source_tasks, - set_power_saving_state_tasks, - adjust_power_state_tasks, - enable_disable_fps_tasks, - set_nbmcu_state_tasks, - broadcast_power_policy_tasks, - NULL -}; - -const struct action_chain power_source_change_action_chain_pp_enabled = { - "Power source change - PowerPlay enabled", - power_source_change_event_pp_enabled -}; - -static const pem_event_action * const power_source_change_event_pp_disabled[] = { - set_power_source_tasks, - set_nbmcu_state_tasks, - NULL -}; - -const struct action_chain power_source_changes_action_chain_pp_disabled = { - "Power source change - PowerPlay disabled", - power_source_change_event_pp_disabled -}; - -static const pem_event_action * const power_source_change_event_hardware_dc[] = { - set_power_source_tasks, - set_power_saving_state_tasks, - adjust_power_state_tasks, - enable_disable_fps_tasks, - reset_hardware_dc_notification_tasks, - set_nbmcu_state_tasks, - broadcast_power_policy_tasks, - NULL -}; - -const struct action_chain power_source_change_action_chain_hardware_dc = { - "Power source change - with Hardware DC switching", - power_source_change_event_hardware_dc -}; - -static const pem_event_action * const suspend_event[] = { - reset_display_phy_access_tasks, - unregister_interrupt_tasks, - disable_gfx_voltage_island_power_gating_tasks, - disable_gfx_clock_gating_tasks, - notify_smu_suspend_tasks, - disable_smc_firmware_ctf_tasks, - set_boot_state_tasks, - adjust_power_state_tasks, - disable_fps_tasks, - vari_bright_suspend_tasks, - reset_fan_speed_to_default_tasks, - power_down_asic_tasks, - disable_stutter_mode_tasks, - set_connected_standby_tasks, - block_hw_access_tasks, - NULL -}; - -const struct action_chain suspend_action_chain = { - "Suspend", - suspend_event -}; - -static const pem_event_action * const resume_event[] = { - unblock_hw_access_tasks, - resume_connected_standby_tasks, - notify_smu_resume_tasks, - reset_display_configCounter_tasks, - update_dal_configuration_tasks, - vari_bright_resume_tasks, - setup_asic_tasks, - enable_stutter_mode_tasks, /*must do this in boot state and before SMC is started */ - enable_dynamic_state_management_tasks, - enable_disable_bapm_tasks, - initialize_thermal_controller_tasks, - get_2d_performance_state_tasks, - set_performance_state_tasks, - adjust_power_state_tasks, - enable_disable_fps_tasks, - notify_hw_power_source_tasks, - process_vbios_event_info_tasks, - enable_gfx_clock_gating_tasks, - enable_gfx_voltage_island_power_gating_tasks, - reset_clock_gating_tasks, - notify_smu_vpu_recovery_end_tasks, - disable_vpu_cap_tasks, - execute_escape_sequence_tasks, - NULL -}; - - -const struct action_chain resume_action_chain = { - "resume", - resume_event -}; - -static const pem_event_action * const complete_init_event[] = { - unblock_adjust_power_state_tasks, - adjust_power_state_tasks, - enable_gfx_clock_gating_tasks, - enable_gfx_voltage_island_power_gating_tasks, - notify_power_state_change_tasks, - NULL -}; - -const struct action_chain complete_init_action_chain = { - "complete init", - complete_init_event -}; - -static const pem_event_action * const enable_gfx_clock_gating_event[] = { - enable_gfx_clock_gating_tasks, - NULL -}; - -const struct action_chain enable_gfx_clock_gating_action_chain = { - "enable gfx clock gate", - enable_gfx_clock_gating_event -}; - -static const pem_event_action * const disable_gfx_clock_gating_event[] = { - disable_gfx_clock_gating_tasks, - NULL -}; - -const struct action_chain disable_gfx_clock_gating_action_chain = { - "disable gfx clock gate", - disable_gfx_clock_gating_event -}; - -static const pem_event_action * const enable_cgpg_event[] = { - enable_cgpg_tasks, - NULL -}; - -const struct action_chain enable_cgpg_action_chain = { - "eable cg pg", - enable_cgpg_event -}; - -static const pem_event_action * const disable_cgpg_event[] = { - disable_cgpg_tasks, - NULL -}; - -const struct action_chain disable_cgpg_action_chain = { - "disable cg pg", - disable_cgpg_event -}; - - -/* Enable user _2d performance and activate */ - -static const pem_event_action * const enable_user_state_event[] = { - create_new_user_performance_state_tasks, - adjust_power_state_tasks, - NULL -}; - -const struct action_chain enable_user_state_action_chain = { - "Enable user state", - enable_user_state_event -}; - -static const pem_event_action * const enable_user_2d_performance_event[] = { - enable_user_2d_performance_tasks, - add_user_2d_performance_state_tasks, - set_performance_state_tasks, - adjust_power_state_tasks, - delete_user_2d_performance_state_tasks, - NULL -}; - -const struct action_chain enable_user_2d_performance_action_chain = { - "enable_user_2d_performance_event_activate", - enable_user_2d_performance_event -}; - - -static const pem_event_action * const disable_user_2d_performance_event[] = { - disable_user_2d_performance_tasks, - delete_user_2d_performance_state_tasks, - NULL -}; - -const struct action_chain disable_user_2d_performance_action_chain = { - "disable_user_2d_performance_event", - disable_user_2d_performance_event -}; - - -static const pem_event_action * const display_config_change_event[] = { - /* countDisplayConfigurationChangeEventTasks, */ - unblock_adjust_power_state_tasks, - set_cpu_power_state, - notify_hw_power_source_tasks, - get_2d_performance_state_tasks, - set_performance_state_tasks, - /* updateDALConfigurationTasks, - variBrightDisplayConfigurationChangeTasks, */ - adjust_power_state_tasks, - /*enableDisableFPSTasks, - setNBMCUStateTasks, - notifyPCIEDeviceReadyTasks,*/ - NULL -}; - -const struct action_chain display_config_change_action_chain = { - "Display configuration change", - display_config_change_event -}; - -static const pem_event_action * const readjust_power_state_event[] = { - adjust_power_state_tasks, - NULL -}; - -const struct action_chain readjust_power_state_action_chain = { - "re-adjust power state", - readjust_power_state_event -}; - diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.h b/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.h deleted file mode 100644 index f181e53..0000000 --- a/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2015 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#ifndef _EVENT_ACTION_CHAINS_H_ -#define _EVENT_ACTION_CHAINS_H_ -#include "eventmgr.h" - -extern const struct action_chain initialize_action_chain; - -extern const struct action_chain uninitialize_action_chain; - -extern const struct action_chain power_source_change_action_chain_pp_enabled; - -extern const struct action_chain power_source_changes_action_chain_pp_disabled; - -extern const struct action_chain power_source_change_action_chain_hardware_dc; - -extern const struct action_chain suspend_action_chain; - -extern const struct action_chain resume_action_chain; - -extern const struct action_chain complete_init_action_chain; - -extern const struct action_chain enable_gfx_clock_gating_action_chain; - -extern const struct action_chain disable_gfx_clock_gating_action_chain; - -extern const struct action_chain enable_cgpg_action_chain; - -extern const struct action_chain disable_cgpg_action_chain; - -extern const struct action_chain enable_user_2d_performance_action_chain; - -extern const struct action_chain disable_user_2d_performance_action_chain; - -extern const struct action_chain enable_user_state_action_chain; - -extern const struct action_chain readjust_power_state_action_chain; - -extern const struct action_chain display_config_change_action_chain; - -#endif /*_EVENT_ACTION_CHAINS_H_*/ - diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventinit.c b/drivers/gpu/drm/amd/powerplay/eventmgr/eventinit.c deleted file mode 100644 index a3cd230..0000000 --- a/drivers/gpu/drm/amd/powerplay/eventmgr/eventinit.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright 2015 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 "eventmgr.h" -#include "eventinit.h" -#include "ppinterrupt.h" -#include "hardwaremanager.h" - -void pem_init_feature_info(struct pp_eventmgr *eventmgr) -{ - - /* PowerPlay info */ - eventmgr->ui_state_info[PP_PowerSource_AC].default_ui_lable = - PP_StateUILabel_Performance; - - eventmgr->ui_state_info[PP_PowerSource_AC].current_ui_label = - PP_StateUILabel_Performance; - - eventmgr->ui_state_info[PP_PowerSource_DC].default_ui_lable = - PP_StateUILabel_Battery; - - eventmgr->ui_state_info[PP_PowerSource_DC].current_ui_label = - PP_StateUILabel_Battery; - - if (phm_cap_enabled(eventmgr->platform_descriptor->platformCaps, PHM_PlatformCaps_PowerPlaySupport)) { - eventmgr->features[PP_Feature_PowerPlay].supported = true; - eventmgr->features[PP_Feature_PowerPlay].version = PEM_CURRENT_POWERPLAY_FEATURE_VERSION; - eventmgr->features[PP_Feature_PowerPlay].enabled_default = true; - eventmgr->features[PP_Feature_PowerPlay].enabled = true; - } else { - eventmgr->features[PP_Feature_PowerPlay].supported = false; - eventmgr->features[PP_Feature_PowerPlay].enabled = false; - eventmgr->features[PP_Feature_PowerPlay].enabled_default = false; - } - - eventmgr->features[PP_Feature_Force3DClock].supported = true; - eventmgr->features[PP_Feature_Force3DClock].enabled = false; - eventmgr->features[PP_Feature_Force3DClock].enabled_default = false; - eventmgr->features[PP_Feature_Force3DClock].version = 1; - - /* over drive*/ - eventmgr->features[PP_Feature_User2DPerformance].version = 4; - eventmgr->features[PP_Feature_User3DPerformance].version = 4; - eventmgr->features[PP_Feature_OverdriveTest].version = 4; - - eventmgr->features[PP_Feature_OverDrive].version = 4; - eventmgr->features[PP_Feature_OverDrive].enabled = false; - eventmgr->features[PP_Feature_OverDrive].enabled_default = false; - - eventmgr->features[PP_Feature_User2DPerformance].supported = false; - eventmgr->features[PP_Feature_User2DPerformance].enabled = false; - eventmgr->features[PP_Feature_User2DPerformance].enabled_default = false; - - eventmgr->features[PP_Feature_User3DPerformance].supported = false; - eventmgr->features[PP_Feature_User3DPerformance].enabled = false; - eventmgr->features[PP_Feature_User3DPerformance].enabled_default = false; - - eventmgr->features[PP_Feature_OverdriveTest].supported = false; - eventmgr->features[PP_Feature_OverdriveTest].enabled = false; - eventmgr->features[PP_Feature_OverdriveTest].enabled_default = false; - - eventmgr->features[PP_Feature_OverDrive].supported = false; - - eventmgr->features[PP_Feature_PowerBudgetWaiver].enabled_default = false; - eventmgr->features[PP_Feature_PowerBudgetWaiver].version = 1; - eventmgr->features[PP_Feature_PowerBudgetWaiver].supported = false; - eventmgr->features[PP_Feature_PowerBudgetWaiver].enabled = false; - - /* Multi UVD States support */ - eventmgr->features[PP_Feature_MultiUVDState].supported = false; - eventmgr->features[PP_Feature_MultiUVDState].enabled = false; - eventmgr->features[PP_Feature_MultiUVDState].enabled_default = false; - - /* Dynamic UVD States support */ - eventmgr->features[PP_Feature_DynamicUVDState].supported = false; - eventmgr->features[PP_Feature_DynamicUVDState].enabled = false; - eventmgr->features[PP_Feature_DynamicUVDState].enabled_default = false; - - /* VCE DPM support */ - eventmgr->features[PP_Feature_VCEDPM].supported = false; - eventmgr->features[PP_Feature_VCEDPM].enabled = false; - eventmgr->features[PP_Feature_VCEDPM].enabled_default = false; - - /* ACP PowerGating support */ - eventmgr->features[PP_Feature_ACP_POWERGATING].supported = false; - eventmgr->features[PP_Feature_ACP_POWERGATING].enabled = false; - eventmgr->features[PP_Feature_ACP_POWERGATING].enabled_default = false; - - /* PPM support */ - eventmgr->features[PP_Feature_PPM].version = 1; - eventmgr->features[PP_Feature_PPM].supported = false; - eventmgr->features[PP_Feature_PPM].enabled = false; - - /* FFC support (enables fan and temp settings, Gemini needs temp settings) */ - if (phm_cap_enabled(eventmgr->platform_descriptor->platformCaps, PHM_PlatformCaps_ODFuzzyFanControlSupport) || - phm_cap_enabled(eventmgr->platform_descriptor->platformCaps, PHM_PlatformCaps_GeminiRegulatorFanControlSupport)) { - eventmgr->features[PP_Feature_FFC].version = 1; - eventmgr->features[PP_Feature_FFC].supported = true; - eventmgr->features[PP_Feature_FFC].enabled = true; - eventmgr->features[PP_Feature_FFC].enabled_default = true; - } else { - eventmgr->features[PP_Feature_FFC].supported = false; - eventmgr->features[PP_Feature_FFC].enabled = false; - eventmgr->features[PP_Feature_FFC].enabled_default = false; - } - - eventmgr->features[PP_Feature_VariBright].supported = false; - eventmgr->features[PP_Feature_VariBright].enabled = false; - eventmgr->features[PP_Feature_VariBright].enabled_default = false; - - eventmgr->features[PP_Feature_BACO].supported = false; - eventmgr->features[PP_Feature_BACO].supported = false; - eventmgr->features[PP_Feature_BACO].enabled_default = false; - - /* PowerDown feature support */ - eventmgr->features[PP_Feature_PowerDown].supported = false; - eventmgr->features[PP_Feature_PowerDown].enabled = false; - eventmgr->features[PP_Feature_PowerDown].enabled_default = false; - - eventmgr->features[PP_Feature_FPS].version = 1; - eventmgr->features[PP_Feature_FPS].supported = false; - eventmgr->features[PP_Feature_FPS].enabled_default = false; - eventmgr->features[PP_Feature_FPS].enabled = false; - - eventmgr->features[PP_Feature_ViPG].version = 1; - eventmgr->features[PP_Feature_ViPG].supported = false; - eventmgr->features[PP_Feature_ViPG].enabled_default = false; - eventmgr->features[PP_Feature_ViPG].enabled = false; -} - -static int thermal_interrupt_callback(void *private_data, - unsigned src_id, const uint32_t *iv_entry) -{ - /* TO DO hanle PEM_Event_ThermalNotification (struct pp_eventmgr *)private_data*/ - pr_info("current thermal is out of range \n"); - return 0; -} - -int pem_register_interrupts(struct pp_eventmgr *eventmgr) -{ - int result = 0; - struct pp_interrupt_registration_info info; - - info.call_back = thermal_interrupt_callback; - info.context = eventmgr; - - result = phm_register_thermal_interrupt(eventmgr->hwmgr, &info); - - /* TODO: - * 2. Register CTF event interrupt - * 3. Register for vbios events interrupt - * 4. Register External Throttle Interrupt - * 5. Register Smc To Host Interrupt - * */ - return result; -} - - -int pem_unregister_interrupts(struct pp_eventmgr *eventmgr) -{ - return 0; -} - - -void pem_uninit_featureInfo(struct pp_eventmgr *eventmgr) -{ - eventmgr->features[PP_Feature_MultiUVDState].supported = false; - eventmgr->features[PP_Feature_VariBright].supported = false; - eventmgr->features[PP_Feature_PowerBudgetWaiver].supported = false; - eventmgr->features[PP_Feature_OverDrive].supported = false; - eventmgr->features[PP_Feature_OverdriveTest].supported = false; - eventmgr->features[PP_Feature_User3DPerformance].supported = false; - eventmgr->features[PP_Feature_User2DPerformance].supported = false; - eventmgr->features[PP_Feature_PowerPlay].supported = false; - eventmgr->features[PP_Feature_Force3DClock].supported = false; -} diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventmanagement.c b/drivers/gpu/drm/amd/powerplay/eventmgr/eventmanagement.c deleted file mode 100644 index cd1ca07..0000000 --- a/drivers/gpu/drm/amd/powerplay/eventmgr/eventmanagement.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright 2015 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 "eventmanagement.h" -#include "eventmgr.h" -#include "eventactionchains.h" - -int pem_init_event_action_chains(struct pp_eventmgr *eventmgr) -{ - int i; - - for (i = 0; i < AMD_PP_EVENT_MAX; i++) - eventmgr->event_chain[i] = NULL; - - eventmgr->event_chain[AMD_PP_EVENT_SUSPEND] = pem_get_suspend_action_chain(eventmgr); - eventmgr->event_chain[AMD_PP_EVENT_INITIALIZE] = pem_get_initialize_action_chain(eventmgr); - eventmgr->event_chain[AMD_PP_EVENT_UNINITIALIZE] = pem_get_uninitialize_action_chain(eventmgr); - eventmgr->event_chain[AMD_PP_EVENT_POWER_SOURCE_CHANGE] = pem_get_power_source_change_action_chain(eventmgr); - eventmgr->event_chain[AMD_PP_EVENT_HIBERNATE] = pem_get_hibernate_action_chain(eventmgr); - eventmgr->event_chain[AMD_PP_EVENT_RESUME] = pem_get_resume_action_chain(eventmgr); - eventmgr->event_chain[AMD_PP_EVENT_THERMAL_NOTIFICATION] = pem_get_thermal_notification_action_chain(eventmgr); - eventmgr->event_chain[AMD_PP_EVENT_VBIOS_NOTIFICATION] = pem_get_vbios_notification_action_chain(eventmgr); - eventmgr->event_chain[AMD_PP_EVENT_ENTER_THERMAL_STATE] = pem_get_enter_thermal_state_action_chain(eventmgr); - eventmgr->event_chain[AMD_PP_EVENT_EXIT_THERMAL_STATE] = pem_get_exit_thermal_state_action_chain(eventmgr); - eventmgr->event_chain[AMD_PP_EVENT_ENABLE_POWER_PLAY] = pem_get_enable_powerplay_action_chain(eventmgr); - eventmgr->event_chain[AMD_PP_EVENT_DISABLE_POWER_PLAY] = pem_get_disable_powerplay_action_chain(eventmgr); - eventmgr->event_chain[AMD_PP_EVENT_ENABLE_OVER_DRIVE_TEST] = pem_get_enable_overdrive_test_action_chain(eventmgr); - eventmgr->event_chain[AMD_PP_EVENT_DISABLE_OVER_DRIVE_TEST] = pem_get_disable_overdrive_test_action_chain(eventmgr); - eventmgr->event_chain[AMD_PP_EVENT_ENABLE_GFX_CLOCK_GATING] = pem_get_enable_gfx_clock_gating_action_chain(eventmgr); - eventmgr->event_chain[AMD_PP_EVENT_DISABLE_GFX_CLOCK_GATING] = pem_get_disable_gfx_clock_gating_action_chain(eventmgr); - eventmgr->event_chain[AMD_PP_EVENT_ENABLE_CGPG] = pem_get_enable_cgpg_action_chain(eventmgr); - eventmgr->event_chain[AMD_PP_EVENT_DISABLE_CGPG] = pem_get_disable_cgpg_action_chain(eventmgr); - eventmgr->event_chain[AMD_PP_EVENT_COMPLETE_INIT] = pem_get_complete_init_action_chain(eventmgr); - eventmgr->event_chain[AMD_PP_EVENT_SCREEN_ON] = pem_get_screen_on_action_chain(eventmgr); - eventmgr->event_chain[AMD_PP_EVENT_SCREEN_OFF] = pem_get_screen_off_action_chain(eventmgr); - eventmgr->event_chain[AMD_PP_EVENT_PRE_SUSPEND] = pem_get_pre_suspend_action_chain(eventmgr); - eventmgr->event_chain[AMD_PP_EVENT_PRE_RESUME] = pem_get_pre_resume_action_chain(eventmgr); - eventmgr->event_chain[AMD_PP_EVENT_ENABLE_USER_STATE] = pem_enable_user_state_action_chain(eventmgr); - eventmgr->event_chain[AMD_PP_EVENT_READJUST_POWER_STATE] = pem_readjust_power_state_action_chain(eventmgr); - eventmgr->event_chain[AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE] = pem_display_config_change_action_chain(eventmgr); - return 0; -} - -int pem_excute_event_chain(struct pp_eventmgr *eventmgr, const struct action_chain *event_chain, struct pem_event_data *event_data) -{ - const pem_event_action * const *paction_chain; - const pem_event_action *psub_chain; - int tmp_result = 0; - int result = 0; - - if (eventmgr == NULL || event_chain == NULL || event_data == NULL) - return -EINVAL; - - for (paction_chain = event_chain->action_chain; NULL != *paction_chain; paction_chain++) { - if (0 != result) - return result; - - for (psub_chain = *paction_chain; NULL != *psub_chain; psub_chain++) { - tmp_result = (*psub_chain)(eventmgr, event_data); - if (0 == result) - result = tmp_result; - } - } - - return result; -} - -const struct action_chain *pem_get_suspend_action_chain(struct pp_eventmgr *eventmgr) -{ - return &suspend_action_chain; -} - -const struct action_chain *pem_get_initialize_action_chain(struct pp_eventmgr *eventmgr) -{ - return &initialize_action_chain; -} - -const struct action_chain *pem_get_uninitialize_action_chain(struct pp_eventmgr *eventmgr) -{ - return &uninitialize_action_chain; -} - -const struct action_chain *pem_get_power_source_change_action_chain(struct pp_eventmgr *eventmgr) -{ - return &power_source_change_action_chain_pp_enabled; /* other case base on feature info*/ -} - -const struct action_chain *pem_get_resume_action_chain(struct pp_eventmgr *eventmgr) -{ - return &resume_action_chain; -} - -const struct action_chain *pem_get_hibernate_action_chain(struct pp_eventmgr *eventmgr) -{ - return NULL; -} - -const struct action_chain *pem_get_thermal_notification_action_chain(struct pp_eventmgr *eventmgr) -{ - return NULL; -} - -const struct action_chain *pem_get_vbios_notification_action_chain(struct pp_eventmgr *eventmgr) -{ - return NULL; -} - -const struct action_chain *pem_get_enter_thermal_state_action_chain(struct pp_eventmgr *eventmgr) -{ - return NULL; -} - -const struct action_chain *pem_get_exit_thermal_state_action_chain(struct pp_eventmgr *eventmgr) -{ - return NULL; -} - -const struct action_chain *pem_get_enable_powerplay_action_chain(struct pp_eventmgr *eventmgr) -{ - return NULL; -} - -const struct action_chain *pem_get_disable_powerplay_action_chain(struct pp_eventmgr *eventmgr) -{ - return NULL; -} - -const struct action_chain *pem_get_enable_overdrive_test_action_chain(struct pp_eventmgr *eventmgr) -{ - return NULL; -} - -const struct action_chain *pem_get_disable_overdrive_test_action_chain(struct pp_eventmgr *eventmgr) -{ - return NULL; -} - -const struct action_chain *pem_get_enable_gfx_clock_gating_action_chain(struct pp_eventmgr *eventmgr) -{ - return &enable_gfx_clock_gating_action_chain; -} - -const struct action_chain *pem_get_disable_gfx_clock_gating_action_chain(struct pp_eventmgr *eventmgr) -{ - return &disable_gfx_clock_gating_action_chain; -} - -const struct action_chain *pem_get_enable_cgpg_action_chain(struct pp_eventmgr *eventmgr) -{ - return &enable_cgpg_action_chain; -} - -const struct action_chain *pem_get_disable_cgpg_action_chain(struct pp_eventmgr *eventmgr) -{ - return &disable_cgpg_action_chain; -} - -const struct action_chain *pem_get_complete_init_action_chain(struct pp_eventmgr *eventmgr) -{ - return &complete_init_action_chain; -} - -const struct action_chain *pem_get_screen_on_action_chain(struct pp_eventmgr *eventmgr) -{ - return NULL; -} - -const struct action_chain *pem_get_screen_off_action_chain(struct pp_eventmgr *eventmgr) -{ - return NULL; -} - -const struct action_chain *pem_get_pre_suspend_action_chain(struct pp_eventmgr *eventmgr) -{ - return NULL; -} - -const struct action_chain *pem_get_pre_resume_action_chain(struct pp_eventmgr *eventmgr) -{ - return NULL; -} - -const struct action_chain *pem_enable_user_state_action_chain(struct pp_eventmgr *eventmgr) -{ - return &enable_user_state_action_chain; -} - -const struct action_chain *pem_readjust_power_state_action_chain(struct pp_eventmgr *eventmgr) -{ - return &readjust_power_state_action_chain; -} - -const struct action_chain *pem_display_config_change_action_chain(struct pp_eventmgr *eventmgr) -{ - return &display_config_change_action_chain; -} diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventmanagement.h b/drivers/gpu/drm/amd/powerplay/eventmgr/eventmanagement.h deleted file mode 100644 index 383d4b2..0000000 --- a/drivers/gpu/drm/amd/powerplay/eventmgr/eventmanagement.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2015 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#ifndef _EVENT_MANAGEMENT_H_ -#define _EVENT_MANAGEMENT_H_ - -#include "eventmgr.h" - -int pem_init_event_action_chains(struct pp_eventmgr *eventmgr); -int pem_excute_event_chain(struct pp_eventmgr *eventmgr, const struct action_chain *event_chain, struct pem_event_data *event_data); -const struct action_chain *pem_get_suspend_action_chain(struct pp_eventmgr *eventmgr); -const struct action_chain *pem_get_initialize_action_chain(struct pp_eventmgr *eventmgr); -const struct action_chain *pem_get_uninitialize_action_chain(struct pp_eventmgr *eventmgr); -const struct action_chain *pem_get_power_source_change_action_chain(struct pp_eventmgr *eventmgr); -const struct action_chain *pem_get_resume_action_chain(struct pp_eventmgr *eventmgr); -const struct action_chain *pem_get_hibernate_action_chain(struct pp_eventmgr *eventmgr); -const struct action_chain *pem_get_thermal_notification_action_chain(struct pp_eventmgr *eventmgr); -const struct action_chain *pem_get_vbios_notification_action_chain(struct pp_eventmgr *eventmgr); -const struct action_chain *pem_get_enter_thermal_state_action_chain(struct pp_eventmgr *eventmgr); -const struct action_chain *pem_get_exit_thermal_state_action_chain(struct pp_eventmgr *eventmgr); -const struct action_chain *pem_get_enable_powerplay_action_chain(struct pp_eventmgr *eventmgr); -const struct action_chain *pem_get_disable_powerplay_action_chain(struct pp_eventmgr *eventmgr); -const struct action_chain *pem_get_enable_overdrive_test_action_chain(struct pp_eventmgr *eventmgr); -const struct action_chain *pem_get_disable_overdrive_test_action_chain(struct pp_eventmgr *eventmgr); -const struct action_chain *pem_get_enable_gfx_clock_gating_action_chain(struct pp_eventmgr *eventmgr); -const struct action_chain *pem_get_disable_gfx_clock_gating_action_chain(struct pp_eventmgr *eventmgr); -const struct action_chain *pem_get_enable_cgpg_action_chain(struct pp_eventmgr *eventmgr); -const struct action_chain *pem_get_disable_cgpg_action_chain(struct pp_eventmgr *eventmgr); -const struct action_chain *pem_get_complete_init_action_chain(struct pp_eventmgr *eventmgr); -const struct action_chain *pem_get_screen_on_action_chain(struct pp_eventmgr *eventmgr); -const struct action_chain *pem_get_screen_off_action_chain(struct pp_eventmgr *eventmgr); -const struct action_chain *pem_get_pre_suspend_action_chain(struct pp_eventmgr *eventmgr); -const struct action_chain *pem_get_pre_resume_action_chain(struct pp_eventmgr *eventmgr); - -extern const struct action_chain *pem_enable_user_state_action_chain(struct pp_eventmgr *eventmgr); -extern const struct action_chain *pem_readjust_power_state_action_chain(struct pp_eventmgr *eventmgr); -const struct action_chain *pem_display_config_change_action_chain(struct pp_eventmgr *eventmgr); - - -#endif /* _EVENT_MANAGEMENT_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventmgr.c b/drivers/gpu/drm/amd/powerplay/eventmgr/eventmgr.c deleted file mode 100644 index 3e3ca03..0000000 --- a/drivers/gpu/drm/amd/powerplay/eventmgr/eventmgr.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2015 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include "eventmgr.h" -#include "hwmgr.h" -#include "eventinit.h" -#include "eventmanagement.h" - -static int pem_init(struct pp_eventmgr *eventmgr) -{ - int result = 0; - struct pem_event_data event_data = { {0} }; - - /* Initialize PowerPlay feature info */ - pem_init_feature_info(eventmgr); - - /* Initialize event action chains */ - pem_init_event_action_chains(eventmgr); - - /* Call initialization event */ - result = pem_handle_event(eventmgr, AMD_PP_EVENT_INITIALIZE, &event_data); - - /* if (0 != result) - return result; */ - - /* Register interrupt callback functions */ - result = pem_register_interrupts(eventmgr); - return 0; -} - -static void pem_fini(struct pp_eventmgr *eventmgr) -{ - struct pem_event_data event_data = { {0} }; - - pem_uninit_featureInfo(eventmgr); - pem_unregister_interrupts(eventmgr); - - pem_handle_event(eventmgr, AMD_PP_EVENT_UNINITIALIZE, &event_data); -} - -int eventmgr_early_init(struct pp_instance *handle) -{ - struct pp_eventmgr *eventmgr; - - if (handle == NULL) - return -EINVAL; - - eventmgr = kzalloc(sizeof(struct pp_eventmgr), GFP_KERNEL); - if (eventmgr == NULL) - return -ENOMEM; - - eventmgr->hwmgr = handle->hwmgr; - handle->eventmgr = eventmgr; - - eventmgr->platform_descriptor = &(eventmgr->hwmgr->platform_descriptor); - eventmgr->pp_eventmgr_init = pem_init; - eventmgr->pp_eventmgr_fini = pem_fini; - - return 0; -} - -static int pem_handle_event_unlocked(struct pp_eventmgr *eventmgr, enum amd_pp_event event, struct pem_event_data *data) -{ - if (eventmgr == NULL || event >= AMD_PP_EVENT_MAX || data == NULL) - return -EINVAL; - - return pem_excute_event_chain(eventmgr, eventmgr->event_chain[event], data); -} - -int pem_handle_event(struct pp_eventmgr *eventmgr, enum amd_pp_event event, struct pem_event_data *event_data) -{ - int r = 0; - - r = pem_handle_event_unlocked(eventmgr, event, event_data); - - return r; -} - -bool pem_is_hw_access_blocked(struct pp_eventmgr *eventmgr) -{ - return (eventmgr->block_adjust_power_state || phm_is_hw_access_blocked(eventmgr->hwmgr)); -} diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventsubchains.c b/drivers/gpu/drm/amd/powerplay/eventmgr/eventsubchains.c deleted file mode 100644 index b82c43a..0000000 --- a/drivers/gpu/drm/amd/powerplay/eventmgr/eventsubchains.c +++ /dev/null @@ -1,410 +0,0 @@ -/* - * Copyright 2015 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 "eventmgr.h" -#include "eventsubchains.h" -#include "eventtasks.h" -#include "hardwaremanager.h" - -const pem_event_action reset_display_phy_access_tasks[] = { - pem_task_reset_display_phys_access, - NULL -}; - -const pem_event_action broadcast_power_policy_tasks[] = { - /* PEM_Task_BroadcastPowerPolicyChange, */ - NULL -}; - -const pem_event_action unregister_interrupt_tasks[] = { - pem_task_unregister_interrupts, - NULL -}; - -/* Disable GFX Voltage Islands Power Gating */ -const pem_event_action disable_gfx_voltage_island_powergating_tasks[] = { - pem_task_disable_voltage_island_power_gating, - NULL -}; - -const pem_event_action disable_gfx_clockgating_tasks[] = { - pem_task_disable_gfx_clock_gating, - NULL -}; - -const pem_event_action block_adjust_power_state_tasks[] = { - pem_task_block_adjust_power_state, - NULL -}; - - -const pem_event_action unblock_adjust_power_state_tasks[] = { - pem_task_unblock_adjust_power_state, - NULL -}; - -const pem_event_action set_performance_state_tasks[] = { - pem_task_set_performance_state, - NULL -}; - -const pem_event_action get_2d_performance_state_tasks[] = { - pem_task_get_2D_performance_state_id, - NULL -}; - -const pem_event_action conditionally_force3D_performance_state_tasks[] = { - pem_task_conditionally_force_3d_performance_state, - NULL -}; - -const pem_event_action process_vbios_eventinfo_tasks[] = { - /* PEM_Task_ProcessVbiosEventInfo,*/ - NULL -}; - -const pem_event_action enable_dynamic_state_management_tasks[] = { - /* PEM_Task_ResetBAPMPolicyChangedFlag,*/ - pem_task_get_boot_state_id, - pem_task_enable_dynamic_state_management, - pem_task_register_interrupts, - NULL -}; - -const pem_event_action enable_clock_power_gatings_tasks[] = { - pem_task_enable_clock_power_gatings_tasks, - pem_task_powerdown_uvd_tasks, - pem_task_powerdown_vce_tasks, - NULL -}; - -const pem_event_action setup_asic_tasks[] = { - pem_task_setup_asic, - NULL -}; - -const pem_event_action power_budget_tasks[] = { - /* TODO - * PEM_Task_PowerBudgetWaiverAvailable, - * PEM_Task_PowerBudgetWarningMessage, - * PEM_Task_PruneStatesBasedOnPowerBudget, - */ - NULL -}; - -const pem_event_action system_config_tasks[] = { - /* PEM_Task_PruneStatesBasedOnSystemConfig,*/ - NULL -}; - - -const pem_event_action conditionally_force_3d_performance_state_tasks[] = { - pem_task_conditionally_force_3d_performance_state, - NULL -}; - -const pem_event_action ungate_all_display_phys_tasks[] = { - /* PEM_Task_GetDisplayPhyAccessInfo */ - NULL -}; - -const pem_event_action uninitialize_display_phy_access_tasks[] = { - /* PEM_Task_UninitializeDisplayPhysAccess, */ - NULL -}; - -const pem_event_action disable_gfx_voltage_island_power_gating_tasks[] = { - /* PEM_Task_DisableVoltageIslandPowerGating, */ - NULL -}; - -const pem_event_action disable_gfx_clock_gating_tasks[] = { - pem_task_disable_gfx_clock_gating, - NULL -}; - -const pem_event_action set_boot_state_tasks[] = { - pem_task_get_boot_state_id, - pem_task_set_boot_state, - NULL -}; - -const pem_event_action adjust_power_state_tasks[] = { - pem_task_notify_hw_mgr_display_configuration_change, - pem_task_adjust_power_state, - pem_task_notify_smc_display_config_after_power_state_adjustment, - pem_task_update_allowed_performance_levels, - /* to do pem_task_Enable_disable_bapm, */ - NULL -}; - -const pem_event_action disable_dynamic_state_management_tasks[] = { - pem_task_unregister_interrupts, - pem_task_get_boot_state_id, - pem_task_disable_dynamic_state_management, - NULL -}; - -const pem_event_action disable_clock_power_gatings_tasks[] = { - pem_task_disable_clock_power_gatings_tasks, - NULL -}; - -const pem_event_action cleanup_asic_tasks[] = { - /* PEM_Task_DisableFPS,*/ - pem_task_cleanup_asic, - NULL -}; - -const pem_event_action prepare_for_pnp_stop_tasks[] = { - /* PEM_Task_PrepareForPnpStop,*/ - NULL -}; - -const pem_event_action set_power_source_tasks[] = { - pem_task_set_power_source, - pem_task_notify_hw_of_power_source, - NULL -}; - -const pem_event_action set_power_saving_state_tasks[] = { - pem_task_reset_power_saving_state, - pem_task_get_power_saving_state, - pem_task_set_power_saving_state, - /* PEM_Task_ResetODDCState, - * PEM_Task_GetODDCState, - * PEM_Task_SetODDCState,*/ - NULL -}; - -const pem_event_action enable_disable_fps_tasks[] = { - /* PEM_Task_EnableDisableFPS,*/ - NULL -}; - -const pem_event_action set_nbmcu_state_tasks[] = { - /* PEM_Task_NBMCUStateChange,*/ - NULL -}; - -const pem_event_action reset_hardware_dc_notification_tasks[] = { - /* PEM_Task_ResetHardwareDCNotification,*/ - NULL -}; - - -const pem_event_action notify_smu_suspend_tasks[] = { - /* PEM_Task_NotifySMUSuspend,*/ - NULL -}; - -const pem_event_action disable_smc_firmware_ctf_tasks[] = { - pem_task_disable_smc_firmware_ctf, - NULL -}; - -const pem_event_action disable_fps_tasks[] = { - /* PEM_Task_DisableFPS,*/ - NULL -}; - -const pem_event_action vari_bright_suspend_tasks[] = { - /* PEM_Task_VariBright_Suspend,*/ - NULL -}; - -const pem_event_action reset_fan_speed_to_default_tasks[] = { - /* PEM_Task_ResetFanSpeedToDefault,*/ - NULL -}; - -const pem_event_action power_down_asic_tasks[] = { - /* PEM_Task_DisableFPS,*/ - pem_task_power_down_asic, - NULL -}; - -const pem_event_action disable_stutter_mode_tasks[] = { - /* PEM_Task_DisableStutterMode,*/ - NULL -}; - -const pem_event_action set_connected_standby_tasks[] = { - /* PEM_Task_SetConnectedStandby,*/ - NULL -}; - -const pem_event_action block_hw_access_tasks[] = { - pem_task_block_hw_access, - NULL -}; - -const pem_event_action unblock_hw_access_tasks[] = { - pem_task_un_block_hw_access, - NULL -}; - -const pem_event_action resume_connected_standby_tasks[] = { - /* PEM_Task_ResumeConnectedStandby,*/ - NULL -}; - -const pem_event_action notify_smu_resume_tasks[] = { - /* PEM_Task_NotifySMUResume,*/ - NULL -}; - -const pem_event_action reset_display_configCounter_tasks[] = { - pem_task_reset_display_phys_access, - NULL -}; - -const pem_event_action update_dal_configuration_tasks[] = { - /* PEM_Task_CheckVBlankTime,*/ - NULL -}; - -const pem_event_action vari_bright_resume_tasks[] = { - /* PEM_Task_VariBright_Resume,*/ - NULL -}; - -const pem_event_action notify_hw_power_source_tasks[] = { - pem_task_notify_hw_of_power_source, - NULL -}; - -const pem_event_action process_vbios_event_info_tasks[] = { - /* PEM_Task_ProcessVbiosEventInfo,*/ - NULL -}; - -const pem_event_action enable_gfx_clock_gating_tasks[] = { - pem_task_enable_gfx_clock_gating, - NULL -}; - -const pem_event_action enable_gfx_voltage_island_power_gating_tasks[] = { - pem_task_enable_voltage_island_power_gating, - NULL -}; - -const pem_event_action reset_clock_gating_tasks[] = { - /* PEM_Task_ResetClockGating*/ - NULL -}; - -const pem_event_action notify_smu_vpu_recovery_end_tasks[] = { - /* PEM_Task_NotifySmuVPURecoveryEnd,*/ - NULL -}; - -const pem_event_action disable_vpu_cap_tasks[] = { - /* PEM_Task_DisableVPUCap,*/ - NULL -}; - -const pem_event_action execute_escape_sequence_tasks[] = { - /* PEM_Task_ExecuteEscapesequence,*/ - NULL -}; - -const pem_event_action notify_power_state_change_tasks[] = { - pem_task_notify_power_state_change, - NULL -}; - -const pem_event_action enable_cgpg_tasks[] = { - pem_task_enable_cgpg, - NULL -}; - -const pem_event_action disable_cgpg_tasks[] = { - pem_task_disable_cgpg, - NULL -}; - -const pem_event_action enable_user_2d_performance_tasks[] = { - /* PEM_Task_SetUser2DPerformanceFlag,*/ - /* PEM_Task_UpdateUser2DPerformanceEnableEvents,*/ - NULL -}; - -const pem_event_action add_user_2d_performance_state_tasks[] = { - /* PEM_Task_Get2DPerformanceTemplate,*/ - /* PEM_Task_AllocateNewPowerStateMemory,*/ - /* PEM_Task_CopyNewPowerStateInfo,*/ - /* PEM_Task_UpdateNewPowerStateClocks,*/ - /* PEM_Task_UpdateNewPowerStateUser2DPerformanceFlag,*/ - /* PEM_Task_AddPowerState,*/ - /* PEM_Task_ReleaseNewPowerStateMemory,*/ - NULL -}; - -const pem_event_action delete_user_2d_performance_state_tasks[] = { - /* PEM_Task_GetCurrentUser2DPerformanceStateID,*/ - /* PEM_Task_DeletePowerState,*/ - /* PEM_Task_SetCurrentUser2DPerformanceStateID,*/ - NULL -}; - -const pem_event_action disable_user_2d_performance_tasks[] = { - /* PEM_Task_ResetUser2DPerformanceFlag,*/ - /* PEM_Task_UpdateUser2DPerformanceDisableEvents,*/ - NULL -}; - -const pem_event_action enable_stutter_mode_tasks[] = { - pem_task_enable_stutter_mode, - NULL -}; - -const pem_event_action enable_disable_bapm_tasks[] = { - /*PEM_Task_EnableDisableBAPM,*/ - NULL -}; - -const pem_event_action reset_boot_state_tasks[] = { - pem_task_reset_boot_state, - NULL -}; - -const pem_event_action create_new_user_performance_state_tasks[] = { - pem_task_create_user_performance_state, - NULL -}; - -const pem_event_action initialize_thermal_controller_tasks[] = { - pem_task_initialize_thermal_controller, - NULL -}; - -const pem_event_action uninitialize_thermal_controller_tasks[] = { - pem_task_uninitialize_thermal_controller, - NULL -}; - -const pem_event_action set_cpu_power_state[] = { - pem_task_set_cpu_power_state, - NULL -};
\ No newline at end of file diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventsubchains.h b/drivers/gpu/drm/amd/powerplay/eventmgr/eventsubchains.h deleted file mode 100644 index 7714cb92..0000000 --- a/drivers/gpu/drm/amd/powerplay/eventmgr/eventsubchains.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2015 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef _EVENT_SUB_CHAINS_H_ -#define _EVENT_SUB_CHAINS_H_ - -#include "eventmgr.h" - -extern const pem_event_action reset_display_phy_access_tasks[]; -extern const pem_event_action broadcast_power_policy_tasks[]; -extern const pem_event_action unregister_interrupt_tasks[]; -extern const pem_event_action disable_GFX_voltage_island_powergating_tasks[]; -extern const pem_event_action disable_GFX_clockgating_tasks[]; -extern const pem_event_action block_adjust_power_state_tasks[]; -extern const pem_event_action unblock_adjust_power_state_tasks[]; -extern const pem_event_action set_performance_state_tasks[]; -extern const pem_event_action get_2D_performance_state_tasks[]; -extern const pem_event_action conditionally_force3D_performance_state_tasks[]; -extern const pem_event_action process_vbios_eventinfo_tasks[]; -extern const pem_event_action enable_dynamic_state_management_tasks[]; -extern const pem_event_action enable_clock_power_gatings_tasks[]; -extern const pem_event_action conditionally_force3D_performance_state_tasks[]; -extern const pem_event_action setup_asic_tasks[]; -extern const pem_event_action power_budget_tasks[]; -extern const pem_event_action system_config_tasks[]; -extern const pem_event_action get_2d_performance_state_tasks[]; -extern const pem_event_action conditionally_force_3d_performance_state_tasks[]; -extern const pem_event_action ungate_all_display_phys_tasks[]; -extern const pem_event_action uninitialize_display_phy_access_tasks[]; -extern const pem_event_action disable_gfx_voltage_island_power_gating_tasks[]; -extern const pem_event_action disable_gfx_clock_gating_tasks[]; -extern const pem_event_action set_boot_state_tasks[]; -extern const pem_event_action adjust_power_state_tasks[]; -extern const pem_event_action disable_dynamic_state_management_tasks[]; -extern const pem_event_action disable_clock_power_gatings_tasks[]; -extern const pem_event_action cleanup_asic_tasks[]; -extern const pem_event_action prepare_for_pnp_stop_tasks[]; -extern const pem_event_action set_power_source_tasks[]; -extern const pem_event_action set_power_saving_state_tasks[]; -extern const pem_event_action enable_disable_fps_tasks[]; -extern const pem_event_action set_nbmcu_state_tasks[]; -extern const pem_event_action reset_hardware_dc_notification_tasks[]; -extern const pem_event_action notify_smu_suspend_tasks[]; -extern const pem_event_action disable_smc_firmware_ctf_tasks[]; -extern const pem_event_action disable_fps_tasks[]; -extern const pem_event_action vari_bright_suspend_tasks[]; -extern const pem_event_action reset_fan_speed_to_default_tasks[]; -extern const pem_event_action power_down_asic_tasks[]; -extern const pem_event_action disable_stutter_mode_tasks[]; -extern const pem_event_action set_connected_standby_tasks[]; -extern const pem_event_action block_hw_access_tasks[]; -extern const pem_event_action unblock_hw_access_tasks[]; -extern const pem_event_action resume_connected_standby_tasks[]; -extern const pem_event_action notify_smu_resume_tasks[]; -extern const pem_event_action reset_display_configCounter_tasks[]; -extern const pem_event_action update_dal_configuration_tasks[]; -extern const pem_event_action vari_bright_resume_tasks[]; -extern const pem_event_action notify_hw_power_source_tasks[]; -extern const pem_event_action process_vbios_event_info_tasks[]; -extern const pem_event_action enable_gfx_clock_gating_tasks[]; -extern const pem_event_action enable_gfx_voltage_island_power_gating_tasks[]; -extern const pem_event_action reset_clock_gating_tasks[]; -extern const pem_event_action notify_smu_vpu_recovery_end_tasks[]; -extern const pem_event_action disable_vpu_cap_tasks[]; -extern const pem_event_action execute_escape_sequence_tasks[]; -extern const pem_event_action notify_power_state_change_tasks[]; -extern const pem_event_action enable_cgpg_tasks[]; -extern const pem_event_action disable_cgpg_tasks[]; -extern const pem_event_action enable_user_2d_performance_tasks[]; -extern const pem_event_action add_user_2d_performance_state_tasks[]; -extern const pem_event_action delete_user_2d_performance_state_tasks[]; -extern const pem_event_action disable_user_2d_performance_tasks[]; -extern const pem_event_action enable_stutter_mode_tasks[]; -extern const pem_event_action enable_disable_bapm_tasks[]; -extern const pem_event_action reset_boot_state_tasks[]; -extern const pem_event_action create_new_user_performance_state_tasks[]; -extern const pem_event_action initialize_thermal_controller_tasks[]; -extern const pem_event_action uninitialize_thermal_controller_tasks[]; -extern const pem_event_action set_cpu_power_state[]; -#endif /* _EVENT_SUB_CHAINS_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.c b/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.c deleted file mode 100644 index 8c4ebaa..0000000 --- a/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.c +++ /dev/null @@ -1,445 +0,0 @@ -/* - * Copyright 2015 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 "eventmgr.h" -#include "eventinit.h" -#include "eventmanagement.h" -#include "eventmanager.h" -#include "hardwaremanager.h" -#include "eventtasks.h" -#include "power_state.h" -#include "hwmgr.h" -#include "amd_powerplay.h" -#include "psm.h" - -#define TEMP_RANGE_MIN (90 * 1000) -#define TEMP_RANGE_MAX (120 * 1000) - -int pem_task_update_allowed_performance_levels(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - - if (eventmgr == NULL || eventmgr->hwmgr == NULL) - return -EINVAL; - - if (pem_is_hw_access_blocked(eventmgr)) - return 0; - - phm_force_dpm_levels(eventmgr->hwmgr, eventmgr->hwmgr->dpm_level); - - return 0; -} - -/* eventtasks_generic.c */ -int pem_task_adjust_power_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - struct pp_hwmgr *hwmgr; - - if (pem_is_hw_access_blocked(eventmgr)) - return 0; - - hwmgr = eventmgr->hwmgr; - if (event_data->pnew_power_state != NULL) - hwmgr->request_ps = event_data->pnew_power_state; - - if (phm_cap_enabled(eventmgr->platform_descriptor->platformCaps, PHM_PlatformCaps_DynamicPatchPowerState)) - psm_adjust_power_state_dynamic(eventmgr, event_data->skip_state_adjust_rules); - else - psm_adjust_power_state_static(eventmgr, event_data->skip_state_adjust_rules); - - return 0; -} - -int pem_task_power_down_asic(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - return phm_power_down_asic(eventmgr->hwmgr); -} - -int pem_task_set_boot_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - if (pem_is_event_data_valid(event_data->valid_fields, PEM_EventDataValid_RequestedStateID)) - return psm_set_states(eventmgr, &(event_data->requested_state_id)); - - return 0; -} - -int pem_task_reset_boot_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - /* TODO */ - return 0; -} - -int pem_task_update_new_power_state_clocks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - /* TODO */ - return 0; -} - -int pem_task_system_shutdown(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - /* TODO */ - return 0; -} - -int pem_task_register_interrupts(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - /* TODO */ - return 0; -} - -int pem_task_unregister_interrupts(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - return pem_unregister_interrupts(eventmgr); -} - -int pem_task_get_boot_state_id(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - int result; - - result = psm_get_state_by_classification(eventmgr, - PP_StateClassificationFlag_Boot, - &(event_data->requested_state_id) - ); - - if (0 == result) - pem_set_event_data_valid(event_data->valid_fields, PEM_EventDataValid_RequestedStateID); - else - pem_unset_event_data_valid(event_data->valid_fields, PEM_EventDataValid_RequestedStateID); - - return result; -} - -int pem_task_enable_dynamic_state_management(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - return phm_enable_dynamic_state_management(eventmgr->hwmgr); -} - -int pem_task_disable_dynamic_state_management(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - return phm_disable_dynamic_state_management(eventmgr->hwmgr); -} - -int pem_task_enable_clock_power_gatings_tasks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - return phm_enable_clock_power_gatings(eventmgr->hwmgr); -} - -int pem_task_powerdown_uvd_tasks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - return phm_powerdown_uvd(eventmgr->hwmgr); -} - -int pem_task_powerdown_vce_tasks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - phm_powergate_uvd(eventmgr->hwmgr, true); - phm_powergate_vce(eventmgr->hwmgr, true); - return 0; -} - -int pem_task_disable_clock_power_gatings_tasks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - phm_disable_clock_power_gatings(eventmgr->hwmgr); - return 0; -} - -int pem_task_start_asic_block_usage(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - /* TODO */ - return 0; -} - -int pem_task_stop_asic_block_usage(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - /* TODO */ - return 0; -} - -int pem_task_disable_smc_firmware_ctf(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - return phm_disable_smc_firmware_ctf(eventmgr->hwmgr); -} - -int pem_task_setup_asic(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - return phm_setup_asic(eventmgr->hwmgr); -} - -int pem_task_cleanup_asic(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - /* TODO */ - return 0; -} - -int pem_task_store_dal_configuration(struct pp_eventmgr *eventmgr, const struct amd_display_configuration *display_config) -{ - /* TODO */ - return 0; - /*phm_store_dal_configuration_data(eventmgr->hwmgr, display_config) */ -} - -int pem_task_notify_hw_mgr_display_configuration_change(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - if (pem_is_hw_access_blocked(eventmgr)) - return 0; - - return phm_display_configuration_changed(eventmgr->hwmgr); -} - -int pem_task_notify_hw_mgr_pre_display_configuration_change(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - return 0; -} - -int pem_task_notify_smc_display_config_after_power_state_adjustment(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - if (pem_is_hw_access_blocked(eventmgr)) - return 0; - - return phm_notify_smc_display_config_after_ps_adjustment(eventmgr->hwmgr); -} - -int pem_task_block_adjust_power_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - eventmgr->block_adjust_power_state = true; - /* to do PHM_ResetIPSCounter(pEventMgr->pHwMgr);*/ - return 0; -} - -int pem_task_unblock_adjust_power_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - eventmgr->block_adjust_power_state = false; - return 0; -} - -int pem_task_notify_power_state_change(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - /* TODO */ - return 0; -} - -int pem_task_block_hw_access(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - /* TODO */ - return 0; -} - -int pem_task_un_block_hw_access(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - /* TODO */ - return 0; -} - -int pem_task_reset_display_phys_access(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - /* TODO */ - return 0; -} - -int pem_task_set_cpu_power_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - return phm_set_cpu_power_state(eventmgr->hwmgr); -} - -/*powersaving*/ - -int pem_task_set_power_source(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - /* TODO */ - return 0; -} - -int pem_task_notify_hw_of_power_source(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - /* TODO */ - return 0; -} - -int pem_task_get_power_saving_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - /* TODO */ - return 0; -} - -int pem_task_reset_power_saving_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - /* TODO */ - return 0; -} - -int pem_task_set_power_saving_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - /* TODO */ - return 0; -} - -int pem_task_set_screen_state_on(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - /* TODO */ - return 0; -} - -int pem_task_set_screen_state_off(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - /* TODO */ - return 0; -} - -int pem_task_enable_voltage_island_power_gating(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - /* TODO */ - return 0; -} - -int pem_task_disable_voltage_island_power_gating(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - /* TODO */ - return 0; -} - -int pem_task_enable_cgpg(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - /* TODO */ - return 0; -} - -int pem_task_disable_cgpg(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - /* TODO */ - return 0; -} - -int pem_task_enable_clock_power_gating(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - /* TODO */ - return 0; -} - - -int pem_task_enable_gfx_clock_gating(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - /* TODO */ - return 0; -} - -int pem_task_disable_gfx_clock_gating(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - /* TODO */ - return 0; -} - - -/* performance */ -int pem_task_set_performance_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - if (pem_is_event_data_valid(event_data->valid_fields, PEM_EventDataValid_RequestedStateID)) - return psm_set_states(eventmgr, &(event_data->requested_state_id)); - - return 0; -} - -int pem_task_conditionally_force_3d_performance_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - /* TODO */ - return 0; -} - -int pem_task_enable_stutter_mode(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - /* TODO */ - return 0; -} - -int pem_task_get_2D_performance_state_id(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - int result; - - if (eventmgr->features[PP_Feature_PowerPlay].supported && - !(eventmgr->features[PP_Feature_PowerPlay].enabled)) - result = psm_get_state_by_classification(eventmgr, - PP_StateClassificationFlag_Boot, - &(event_data->requested_state_id)); - else if (eventmgr->features[PP_Feature_User2DPerformance].enabled) - result = psm_get_state_by_classification(eventmgr, - PP_StateClassificationFlag_User2DPerformance, - &(event_data->requested_state_id)); - else - result = psm_get_ui_state(eventmgr, PP_StateUILabel_Performance, - &(event_data->requested_state_id)); - - if (0 == result) - pem_set_event_data_valid(event_data->valid_fields, PEM_EventDataValid_RequestedStateID); - else - pem_unset_event_data_valid(event_data->valid_fields, PEM_EventDataValid_RequestedStateID); - - return result; -} - -int pem_task_create_user_performance_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - struct pp_power_state *state; - int table_entries; - struct pp_hwmgr *hwmgr = eventmgr->hwmgr; - int i; - - table_entries = hwmgr->num_ps; - state = hwmgr->ps; - -restart_search: - for (i = 0; i < table_entries; i++) { - if (state->classification.ui_label & event_data->requested_ui_label) { - event_data->pnew_power_state = state; - return 0; - } - state = (struct pp_power_state *)((unsigned long)state + hwmgr->ps_size); - } - - switch (event_data->requested_ui_label) { - case PP_StateUILabel_Battery: - case PP_StateUILabel_Balanced: - event_data->requested_ui_label = PP_StateUILabel_Performance; - goto restart_search; - default: - break; - } - return -1; -} - -int pem_task_initialize_thermal_controller(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - struct PP_TemperatureRange range; - - range.max = TEMP_RANGE_MAX; - range.min = TEMP_RANGE_MIN; - - if (eventmgr == NULL || eventmgr->platform_descriptor == NULL) - return -EINVAL; - - if (phm_cap_enabled(eventmgr->platform_descriptor->platformCaps, PHM_PlatformCaps_ThermalController)) - return phm_start_thermal_controller(eventmgr->hwmgr, &range); - - return 0; -} - -int pem_task_uninitialize_thermal_controller(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) -{ - return phm_stop_thermal_controller(eventmgr->hwmgr); -} diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.h b/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.h deleted file mode 100644 index 37e7ca5..0000000 --- a/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2015 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef _EVENT_TASKS_H_ -#define _EVENT_TASKS_H_ -#include "eventmgr.h" - -struct amd_display_configuration; - -/* eventtasks_generic.c */ -int pem_task_adjust_power_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_power_down_asic(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_get_boot_state_id(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_set_boot_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_reset_boot_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_update_new_power_state_clocks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_system_shutdown(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_register_interrupts(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_unregister_interrupts(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_enable_dynamic_state_management(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_disable_dynamic_state_management(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_enable_clock_power_gatings_tasks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_powerdown_uvd_tasks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_powerdown_vce_tasks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_disable_clock_power_gatings_tasks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_start_asic_block_usage(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_stop_asic_block_usage(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_setup_asic(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_cleanup_asic(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_store_dal_configuration (struct pp_eventmgr *eventmgr, const struct amd_display_configuration *display_config); -int pem_task_notify_hw_mgr_display_configuration_change(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_notify_hw_mgr_pre_display_configuration_change(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_block_adjust_power_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_unblock_adjust_power_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_notify_power_state_change(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_block_hw_access(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_un_block_hw_access(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_reset_display_phys_access(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_set_cpu_power_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_notify_smc_display_config_after_power_state_adjustment(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -/*powersaving*/ - -int pem_task_set_power_source(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_notify_hw_of_power_source(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_get_power_saving_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_reset_power_saving_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_set_power_saving_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_set_screen_state_on(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_set_screen_state_off(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_enable_voltage_island_power_gating(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_disable_voltage_island_power_gating(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_enable_cgpg(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_disable_cgpg(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_enable_gfx_clock_gating(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_disable_gfx_clock_gating(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_enable_stutter_mode(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); - -/* performance */ -int pem_task_set_performance_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_conditionally_force_3d_performance_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_get_2D_performance_state_id(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_create_user_performance_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_update_allowed_performance_levels(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -/*thermal */ -int pem_task_initialize_thermal_controller(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_uninitialize_thermal_controller(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); -int pem_task_disable_smc_firmware_ctf(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); - -#endif /* _EVENT_TASKS_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/psm.c b/drivers/gpu/drm/amd/powerplay/eventmgr/psm.c deleted file mode 100644 index 4899088..0000000 --- a/drivers/gpu/drm/amd/powerplay/eventmgr/psm.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2015 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 "psm.h" - -int psm_get_ui_state(struct pp_eventmgr *eventmgr, enum PP_StateUILabel ui_label, unsigned long *state_id) -{ - struct pp_power_state *state; - int table_entries; - struct pp_hwmgr *hwmgr = eventmgr->hwmgr; - int i; - - table_entries = hwmgr->num_ps; - state = hwmgr->ps; - - for (i = 0; i < table_entries; i++) { - if (state->classification.ui_label & ui_label) { - *state_id = state->id; - return 0; - } - state = (struct pp_power_state *)((unsigned long)state + hwmgr->ps_size); - } - return -1; -} - -int psm_get_state_by_classification(struct pp_eventmgr *eventmgr, enum PP_StateClassificationFlag flag, unsigned long *state_id) -{ - struct pp_power_state *state; - int table_entries; - struct pp_hwmgr *hwmgr = eventmgr->hwmgr; - int i; - - table_entries = hwmgr->num_ps; - state = hwmgr->ps; - - for (i = 0; i < table_entries; i++) { - if (state->classification.flags & flag) { - *state_id = state->id; - return 0; - } - state = (struct pp_power_state *)((unsigned long)state + hwmgr->ps_size); - } - return -1; -} - -int psm_set_states(struct pp_eventmgr *eventmgr, unsigned long *state_id) -{ - struct pp_power_state *state; - int table_entries; - struct pp_hwmgr *hwmgr = eventmgr->hwmgr; - int i; - - table_entries = hwmgr->num_ps; - - state = hwmgr->ps; - - for (i = 0; i < table_entries; i++) { - if (state->id == *state_id) { - memcpy(hwmgr->request_ps, state, hwmgr->ps_size); - return 0; - } - state = (struct pp_power_state *)((unsigned long)state + hwmgr->ps_size); - } - return -1; -} - -int psm_adjust_power_state_dynamic(struct pp_eventmgr *eventmgr, bool skip) -{ - - struct pp_power_state *pcurrent; - struct pp_power_state *requested; - struct pp_hwmgr *hwmgr; - bool equal; - - if (skip) - return 0; - - hwmgr = eventmgr->hwmgr; - pcurrent = hwmgr->current_ps; - requested = hwmgr->request_ps; - - if (requested == NULL) - return 0; - - phm_apply_state_adjust_rules(hwmgr, requested, pcurrent); - - if (pcurrent == NULL || (0 != phm_check_states_equal(hwmgr, &pcurrent->hardware, &requested->hardware, &equal))) - equal = false; - - if (!equal || phm_check_smc_update_required_for_display_configuration(hwmgr)) { - phm_set_power_state(hwmgr, &pcurrent->hardware, &requested->hardware); - memcpy(hwmgr->current_ps, hwmgr->request_ps, hwmgr->ps_size); - } - return 0; -} - -int psm_adjust_power_state_static(struct pp_eventmgr *eventmgr, bool skip) -{ - return 0; -} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile b/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile index f0277c1..dc4bbcf 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile @@ -2,14 +2,15 @@ # Makefile for the 'hw manager' sub-component of powerplay. # It provides the hardware management services for the driver. -HARDWARE_MGR = hwmgr.o processpptables.o functiontables.o \ +HARDWARE_MGR = hwmgr.o processpptables.o \ hardwaremanager.o pp_acpi.o cz_hwmgr.o \ cz_clockpowergating.o pppcielanes.o\ process_pptables_v1_0.o ppatomctrl.o ppatomfwctrl.o \ smu7_hwmgr.o smu7_powertune.o smu7_thermal.o \ smu7_clockpowergating.o \ vega10_processpptables.o vega10_hwmgr.o vega10_powertune.o \ - vega10_thermal.o pp_overdriver.o rv_hwmgr.o + vega10_thermal.o rv_hwmgr.o pp_psm.o\ + pp_overdriver.o AMD_PP_HWMGR = $(addprefix $(AMD_PP_PATH)/hwmgr/,$(HARDWARE_MGR)) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c index b33935f..44de087 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c @@ -103,16 +103,6 @@ int cz_phm_ungate_all_display_phys(struct pp_hwmgr *hwmgr) return 0; } -static int cz_tf_uvd_power_gating_initialize(struct pp_hwmgr *hwmgr, void *pInput, void *pOutput, void *pStorage, int Result) -{ - return 0; -} - -static int cz_tf_vce_power_gating_initialize(struct pp_hwmgr *hwmgr, void *pInput, void *pOutput, void *pStorage, int Result) -{ - return 0; -} - int cz_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable) { struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); @@ -123,12 +113,12 @@ int cz_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable) PHM_PlatformCaps_UVDDPM)) { cz_hwmgr->dpm_flags |= DPMFlags_UVD_Enabled; dpm_features |= UVD_DPM_MASK; - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_EnableAllSmuFeatures, dpm_features); } else { dpm_features |= UVD_DPM_MASK; cz_hwmgr->dpm_flags &= ~DPMFlags_UVD_Enabled; - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_DisableAllSmuFeatures, dpm_features); } return 0; @@ -144,12 +134,12 @@ int cz_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable) PHM_PlatformCaps_VCEDPM)) { cz_hwmgr->dpm_flags |= DPMFlags_VCE_Enabled; dpm_features |= VCE_DPM_MASK; - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_EnableAllSmuFeatures, dpm_features); } else { dpm_features |= VCE_DPM_MASK; cz_hwmgr->dpm_flags &= ~DPMFlags_VCE_Enabled; - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_DisableAllSmuFeatures, dpm_features); } @@ -157,7 +147,7 @@ int cz_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable) } -int cz_dpm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate) +void cz_dpm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate) { struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); @@ -183,10 +173,9 @@ int cz_dpm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate) cz_dpm_update_uvd_dpm(hwmgr, false); } - return 0; } -int cz_dpm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate) +void cz_dpm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate) { struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); @@ -215,29 +204,6 @@ int cz_dpm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate) AMD_CG_STATE_UNGATE); cz_dpm_update_vce_dpm(hwmgr); cz_enable_disable_vce_dpm(hwmgr, true); - return 0; } - - return 0; } - -static const struct phm_master_table_item cz_enable_clock_power_gatings_list[] = { - /*we don't need an exit table here, because there is only D3 cold on Kv*/ - { - .isFunctionNeededInRuntimeTable = phm_cf_want_uvd_power_gating, - .tableFunction = cz_tf_uvd_power_gating_initialize - }, - { - .isFunctionNeededInRuntimeTable = phm_cf_want_vce_power_gating, - .tableFunction = cz_tf_vce_power_gating_initialize - }, - /* to do { NULL, cz_tf_xdma_power_gating_enable }, */ - { } -}; - -const struct phm_master_table_header cz_phm_enable_clock_power_gatings_master = { - 0, - PHM_MasterTableFlag_None, - cz_enable_clock_power_gatings_list -}; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.h b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.h index 1954cea..92f707b 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.h @@ -29,8 +29,8 @@ extern int cz_phm_set_asic_block_gating(struct pp_hwmgr *hwmgr, enum PHM_AsicBlock block, enum PHM_ClockGateSetting gating); extern const struct phm_master_table_header cz_phm_enable_clock_power_gatings_master; -extern int cz_dpm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate); -extern int cz_dpm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate); +extern void cz_dpm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate); +extern void cz_dpm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate); extern int cz_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable); extern int cz_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable); #endif /* _CZ_CLOCK_POWER_GATING_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c index bc839ff..73bb99d 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c @@ -162,8 +162,8 @@ static uint32_t cz_get_max_sclk_level(struct pp_hwmgr *hwmgr) struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); if (cz_hwmgr->max_sclk_level == 0) { - smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_GetMaxSclkLevel); - cz_hwmgr->max_sclk_level = smum_get_argument(hwmgr->smumgr) + 1; + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxSclkLevel); + cz_hwmgr->max_sclk_level = smum_get_argument(hwmgr) + 1; } return cz_hwmgr->max_sclk_level; @@ -440,14 +440,7 @@ static int cz_construct_boot_state(struct pp_hwmgr *hwmgr) return 0; } -static int cz_tf_reset_active_process_mask(struct pp_hwmgr *hwmgr, void *input, - void *output, void *storage, int result) -{ - return 0; -} - -static int cz_tf_upload_pptable_to_smu(struct pp_hwmgr *hwmgr, void *input, - void *output, void *storage, int result) +static int cz_upload_pptable_to_smu(struct pp_hwmgr *hwmgr) { struct SMU8_Fusion_ClkTable *clock_table; int ret; @@ -469,7 +462,7 @@ static int cz_tf_upload_pptable_to_smu(struct pp_hwmgr *hwmgr, void *input, if (!hwmgr->need_pp_table_upload) return 0; - ret = smum_download_powerplay_table(hwmgr->smumgr, &table); + ret = smum_download_powerplay_table(hwmgr, &table); PP_ASSERT_WITH_CODE((0 == ret && NULL != table), "Fail to get clock table from SMU!", return -EINVAL;); @@ -561,13 +554,12 @@ static int cz_tf_upload_pptable_to_smu(struct pp_hwmgr *hwmgr, void *input, (uint8_t)dividers.pll_post_divider; } - ret = smum_upload_powerplay_table(hwmgr->smumgr); + ret = smum_upload_powerplay_table(hwmgr); return ret; } -static int cz_tf_init_sclk_limit(struct pp_hwmgr *hwmgr, void *input, - void *output, void *storage, int result) +static int cz_init_sclk_limit(struct pp_hwmgr *hwmgr) { struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); struct phm_clock_voltage_dependency_table *table = @@ -593,8 +585,7 @@ static int cz_tf_init_sclk_limit(struct pp_hwmgr *hwmgr, void *input, return 0; } -static int cz_tf_init_uvd_limit(struct pp_hwmgr *hwmgr, void *input, - void *output, void *storage, int result) +static int cz_init_uvd_limit(struct pp_hwmgr *hwmgr) { struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); struct phm_uvd_clock_voltage_dependency_table *table = @@ -607,8 +598,8 @@ static int cz_tf_init_uvd_limit(struct pp_hwmgr *hwmgr, void *input, cz_hwmgr->uvd_dpm.soft_min_clk = 0; cz_hwmgr->uvd_dpm.hard_min_clk = 0; - smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_GetMaxUvdLevel); - level = smum_get_argument(hwmgr->smumgr); + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxUvdLevel); + level = smum_get_argument(hwmgr); if (level < table->count) clock = table->entries[level].vclk; @@ -621,8 +612,7 @@ static int cz_tf_init_uvd_limit(struct pp_hwmgr *hwmgr, void *input, return 0; } -static int cz_tf_init_vce_limit(struct pp_hwmgr *hwmgr, void *input, - void *output, void *storage, int result) +static int cz_init_vce_limit(struct pp_hwmgr *hwmgr) { struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); struct phm_vce_clock_voltage_dependency_table *table = @@ -635,8 +625,8 @@ static int cz_tf_init_vce_limit(struct pp_hwmgr *hwmgr, void *input, cz_hwmgr->vce_dpm.soft_min_clk = 0; cz_hwmgr->vce_dpm.hard_min_clk = 0; - smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_GetMaxEclkLevel); - level = smum_get_argument(hwmgr->smumgr); + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxEclkLevel); + level = smum_get_argument(hwmgr); if (level < table->count) clock = table->entries[level].ecclk; @@ -649,8 +639,7 @@ static int cz_tf_init_vce_limit(struct pp_hwmgr *hwmgr, void *input, return 0; } -static int cz_tf_init_acp_limit(struct pp_hwmgr *hwmgr, void *input, - void *output, void *storage, int result) +static int cz_init_acp_limit(struct pp_hwmgr *hwmgr) { struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); struct phm_acp_clock_voltage_dependency_table *table = @@ -663,8 +652,8 @@ static int cz_tf_init_acp_limit(struct pp_hwmgr *hwmgr, void *input, cz_hwmgr->acp_dpm.soft_min_clk = 0; cz_hwmgr->acp_dpm.hard_min_clk = 0; - smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_GetMaxAclkLevel); - level = smum_get_argument(hwmgr->smumgr); + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxAclkLevel); + level = smum_get_argument(hwmgr); if (level < table->count) clock = table->entries[level].acpclk; @@ -676,8 +665,7 @@ static int cz_tf_init_acp_limit(struct pp_hwmgr *hwmgr, void *input, return 0; } -static int cz_tf_init_power_gate_state(struct pp_hwmgr *hwmgr, void *input, - void *output, void *storage, int result) +static void cz_init_power_gate_state(struct pp_hwmgr *hwmgr) { struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); @@ -686,22 +674,16 @@ static int cz_tf_init_power_gate_state(struct pp_hwmgr *hwmgr, void *input, cz_hwmgr->samu_power_gated = false; cz_hwmgr->acp_power_gated = false; cz_hwmgr->pgacpinit = true; - - return 0; } -static int cz_tf_init_sclk_threshold(struct pp_hwmgr *hwmgr, void *input, - void *output, void *storage, int result) +static void cz_init_sclk_threshold(struct pp_hwmgr *hwmgr) { struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); cz_hwmgr->low_sclk_interrupt_threshold = 0; - - return 0; } -static int cz_tf_update_sclk_limit(struct pp_hwmgr *hwmgr, - void *input, void *output, - void *storage, int result) + +static int cz_update_sclk_limit(struct pp_hwmgr *hwmgr) { struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); struct phm_clock_voltage_dependency_table *table = @@ -727,7 +709,7 @@ static int cz_tf_update_sclk_limit(struct pp_hwmgr *hwmgr, if (cz_hwmgr->sclk_dpm.hard_min_clk != clock) { cz_hwmgr->sclk_dpm.hard_min_clk = clock; - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetSclkHardMin, cz_get_sclk_level(hwmgr, cz_hwmgr->sclk_dpm.hard_min_clk, @@ -753,7 +735,7 @@ static int cz_tf_update_sclk_limit(struct pp_hwmgr *hwmgr, if (cz_hwmgr->sclk_dpm.soft_min_clk != clock) { cz_hwmgr->sclk_dpm.soft_min_clk = clock; - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetSclkSoftMin, cz_get_sclk_level(hwmgr, cz_hwmgr->sclk_dpm.soft_min_clk, @@ -764,7 +746,7 @@ static int cz_tf_update_sclk_limit(struct pp_hwmgr *hwmgr, PHM_PlatformCaps_StablePState) && cz_hwmgr->sclk_dpm.soft_max_clk != clock) { cz_hwmgr->sclk_dpm.soft_max_clk = clock; - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetSclkSoftMax, cz_get_sclk_level(hwmgr, cz_hwmgr->sclk_dpm.soft_max_clk, @@ -774,9 +756,7 @@ static int cz_tf_update_sclk_limit(struct pp_hwmgr *hwmgr, return 0; } -static int cz_tf_set_deep_sleep_sclk_threshold(struct pp_hwmgr *hwmgr, - void *input, void *output, - void *storage, int result) +static int cz_set_deep_sleep_sclk_threshold(struct pp_hwmgr *hwmgr) { if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) { @@ -786,7 +766,7 @@ static int cz_tf_set_deep_sleep_sclk_threshold(struct pp_hwmgr *hwmgr, PP_DBG_LOG("Setting Deep Sleep Clock: %d\n", clks); - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetMinDeepSleepSclk, clks); } @@ -794,77 +774,84 @@ static int cz_tf_set_deep_sleep_sclk_threshold(struct pp_hwmgr *hwmgr, return 0; } -static int cz_tf_set_watermark_threshold(struct pp_hwmgr *hwmgr, - void *input, void *output, - void *storage, int result) +static int cz_set_watermark_threshold(struct pp_hwmgr *hwmgr) { struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetWatermarkFrequency, cz_hwmgr->sclk_dpm.soft_max_clk); return 0; } -static int cz_tf_set_enabled_levels(struct pp_hwmgr *hwmgr, - void *input, void *output, - void *storage, int result) +static int cz_nbdpm_pstate_enable_disable(struct pp_hwmgr *hwmgr, bool enable, bool lock) { + struct cz_hwmgr *hw_data = (struct cz_hwmgr *)(hwmgr->backend); + + if (hw_data->is_nb_dpm_enabled) { + if (enable) { + PP_DBG_LOG("enable Low Memory PState.\n"); + + return smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_EnableLowMemoryPstate, + (lock ? 1 : 0)); + } else { + PP_DBG_LOG("disable Low Memory PState.\n"); + + return smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DisableLowMemoryPstate, + (lock ? 1 : 0)); + } + } + return 0; } - -static int cz_tf_enable_nb_dpm(struct pp_hwmgr *hwmgr, - void *input, void *output, - void *storage, int result) +static int cz_disable_nb_dpm(struct pp_hwmgr *hwmgr) { int ret = 0; struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); unsigned long dpm_features = 0; - if (!cz_hwmgr->is_nb_dpm_enabled) { - PP_DBG_LOG("enabling ALL SMU features.\n"); + if (cz_hwmgr->is_nb_dpm_enabled) { + cz_nbdpm_pstate_enable_disable(hwmgr, true, true); dpm_features |= NB_DPM_MASK; ret = smum_send_msg_to_smc_with_parameter( - hwmgr->smumgr, - PPSMC_MSG_EnableAllSmuFeatures, + hwmgr, + PPSMC_MSG_DisableAllSmuFeatures, dpm_features); if (ret == 0) - cz_hwmgr->is_nb_dpm_enabled = true; + cz_hwmgr->is_nb_dpm_enabled = false; } return ret; } -static int cz_nbdpm_pstate_enable_disable(struct pp_hwmgr *hwmgr, bool enable, bool lock) +static int cz_enable_nb_dpm(struct pp_hwmgr *hwmgr) { - struct cz_hwmgr *hw_data = (struct cz_hwmgr *)(hwmgr->backend); - - if (hw_data->is_nb_dpm_enabled) { - if (enable) { - PP_DBG_LOG("enable Low Memory PState.\n"); + int ret = 0; - return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, - PPSMC_MSG_EnableLowMemoryPstate, - (lock ? 1 : 0)); - } else { - PP_DBG_LOG("disable Low Memory PState.\n"); + struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); + unsigned long dpm_features = 0; - return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, - PPSMC_MSG_DisableLowMemoryPstate, - (lock ? 1 : 0)); - } + if (!cz_hwmgr->is_nb_dpm_enabled) { + PP_DBG_LOG("enabling ALL SMU features.\n"); + dpm_features |= NB_DPM_MASK; + ret = smum_send_msg_to_smc_with_parameter( + hwmgr, + PPSMC_MSG_EnableAllSmuFeatures, + dpm_features); + if (ret == 0) + cz_hwmgr->is_nb_dpm_enabled = true; } - return 0; + return ret; } -static int cz_tf_update_low_mem_pstate(struct pp_hwmgr *hwmgr, - void *input, void *output, - void *storage, int result) +static int cz_update_low_mem_pstate(struct pp_hwmgr *hwmgr, const void *input) { bool disable_switch; bool enable_low_mem_state; @@ -886,64 +873,64 @@ static int cz_tf_update_low_mem_pstate(struct pp_hwmgr *hwmgr, return 0; } -static const struct phm_master_table_item cz_set_power_state_list[] = { - { .tableFunction = cz_tf_update_sclk_limit }, - { .tableFunction = cz_tf_set_deep_sleep_sclk_threshold }, - { .tableFunction = cz_tf_set_watermark_threshold }, - { .tableFunction = cz_tf_set_enabled_levels }, - { .tableFunction = cz_tf_enable_nb_dpm }, - { .tableFunction = cz_tf_update_low_mem_pstate }, - { } -}; +static int cz_set_power_state_tasks(struct pp_hwmgr *hwmgr, const void *input) +{ + int ret = 0; -static const struct phm_master_table_header cz_set_power_state_master = { - 0, - PHM_MasterTableFlag_None, - cz_set_power_state_list -}; + cz_update_sclk_limit(hwmgr); + cz_set_deep_sleep_sclk_threshold(hwmgr); + cz_set_watermark_threshold(hwmgr); + ret = cz_enable_nb_dpm(hwmgr); + if (ret) + return ret; + cz_update_low_mem_pstate(hwmgr, input); -static const struct phm_master_table_item cz_setup_asic_list[] = { - { .tableFunction = cz_tf_reset_active_process_mask }, - { .tableFunction = cz_tf_upload_pptable_to_smu }, - { .tableFunction = cz_tf_init_sclk_limit }, - { .tableFunction = cz_tf_init_uvd_limit }, - { .tableFunction = cz_tf_init_vce_limit }, - { .tableFunction = cz_tf_init_acp_limit }, - { .tableFunction = cz_tf_init_power_gate_state }, - { .tableFunction = cz_tf_init_sclk_threshold }, - { } + return 0; }; -static const struct phm_master_table_header cz_setup_asic_master = { - 0, - PHM_MasterTableFlag_None, - cz_setup_asic_list -}; -static int cz_tf_power_up_display_clock_sys_pll(struct pp_hwmgr *hwmgr, - void *input, void *output, - void *storage, int result) +static int cz_setup_asic_task(struct pp_hwmgr *hwmgr) +{ + int ret; + + ret = cz_upload_pptable_to_smu(hwmgr); + if (ret) + return ret; + ret = cz_init_sclk_limit(hwmgr); + if (ret) + return ret; + ret = cz_init_uvd_limit(hwmgr); + if (ret) + return ret; + ret = cz_init_vce_limit(hwmgr); + if (ret) + return ret; + ret = cz_init_acp_limit(hwmgr); + if (ret) + return ret; + + cz_init_power_gate_state(hwmgr); + cz_init_sclk_threshold(hwmgr); + + return 0; +} + +static void cz_power_up_display_clock_sys_pll(struct pp_hwmgr *hwmgr) { struct cz_hwmgr *hw_data = (struct cz_hwmgr *)(hwmgr->backend); + hw_data->disp_clk_bypass_pending = false; hw_data->disp_clk_bypass = false; - - return 0; } -static int cz_tf_clear_nb_dpm_flag(struct pp_hwmgr *hwmgr, - void *input, void *output, - void *storage, int result) +static void cz_clear_nb_dpm_flag(struct pp_hwmgr *hwmgr) { struct cz_hwmgr *hw_data = (struct cz_hwmgr *)(hwmgr->backend); - hw_data->is_nb_dpm_enabled = false; - return 0; + hw_data->is_nb_dpm_enabled = false; } -static int cz_tf_reset_cc6_data(struct pp_hwmgr *hwmgr, - void *input, void *output, - void *storage, int result) +static void cz_reset_cc6_data(struct pp_hwmgr *hwmgr) { struct cz_hwmgr *hw_data = (struct cz_hwmgr *)(hwmgr->backend); @@ -951,63 +938,73 @@ static int cz_tf_reset_cc6_data(struct pp_hwmgr *hwmgr, hw_data->cc6_settings.cpu_pstate_separation_time = 0; hw_data->cc6_settings.cpu_cc6_disable = false; hw_data->cc6_settings.cpu_pstate_disable = false; - - return 0; } -static const struct phm_master_table_item cz_power_down_asic_list[] = { - { .tableFunction = cz_tf_power_up_display_clock_sys_pll }, - { .tableFunction = cz_tf_clear_nb_dpm_flag }, - { .tableFunction = cz_tf_reset_cc6_data }, - { } -}; - -static const struct phm_master_table_header cz_power_down_asic_master = { - 0, - PHM_MasterTableFlag_None, - cz_power_down_asic_list +static int cz_power_off_asic(struct pp_hwmgr *hwmgr) +{ + cz_power_up_display_clock_sys_pll(hwmgr); + cz_clear_nb_dpm_flag(hwmgr); + cz_reset_cc6_data(hwmgr); + return 0; }; -static int cz_tf_program_voting_clients(struct pp_hwmgr *hwmgr, void *input, - void *output, void *storage, int result) +static void cz_program_voting_clients(struct pp_hwmgr *hwmgr) { PHMCZ_WRITE_SMC_REGISTER(hwmgr->device, CG_FREQ_TRAN_VOTING_0, PPCZ_VOTINGRIGHTSCLIENTS_DFLT0); - return 0; } -static int cz_tf_start_dpm(struct pp_hwmgr *hwmgr, void *input, void *output, - void *storage, int result) +static void cz_clear_voting_clients(struct pp_hwmgr *hwmgr) +{ + PHMCZ_WRITE_SMC_REGISTER(hwmgr->device, CG_FREQ_TRAN_VOTING_0, 0); +} + +static int cz_start_dpm(struct pp_hwmgr *hwmgr) { - int res = 0xff; + int ret = 0; struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); unsigned long dpm_features = 0; cz_hwmgr->dpm_flags |= DPMFlags_SCLK_Enabled; dpm_features |= SCLK_DPM_MASK; - res = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + ret = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_EnableAllSmuFeatures, dpm_features); - return res; + return ret; } -static int cz_tf_program_bootup_state(struct pp_hwmgr *hwmgr, void *input, - void *output, void *storage, int result) +static int cz_stop_dpm(struct pp_hwmgr *hwmgr) +{ + int ret = 0; + struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); + unsigned long dpm_features = 0; + + if (cz_hwmgr->dpm_flags & DPMFlags_SCLK_Enabled) { + dpm_features |= SCLK_DPM_MASK; + cz_hwmgr->dpm_flags &= ~DPMFlags_SCLK_Enabled; + ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DisableAllSmuFeatures, + dpm_features); + } + return ret; +} + +static int cz_program_bootup_state(struct pp_hwmgr *hwmgr) { struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); cz_hwmgr->sclk_dpm.soft_min_clk = cz_hwmgr->sys_info.bootup_engine_clock; cz_hwmgr->sclk_dpm.soft_max_clk = cz_hwmgr->sys_info.bootup_engine_clock; - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetSclkSoftMin, cz_get_sclk_level(hwmgr, cz_hwmgr->sclk_dpm.soft_min_clk, PPSMC_MSG_SetSclkSoftMin)); - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetSclkSoftMax, cz_get_sclk_level(hwmgr, cz_hwmgr->sclk_dpm.soft_max_clk, @@ -1016,13 +1013,11 @@ static int cz_tf_program_bootup_state(struct pp_hwmgr *hwmgr, void *input, return 0; } -static int cz_tf_reset_acp_boot_level(struct pp_hwmgr *hwmgr, void *input, - void *output, void *storage, int result) +static void cz_reset_acp_boot_level(struct pp_hwmgr *hwmgr) { struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); cz_hwmgr->acp_boot_level = 0xff; - return 0; } static bool cz_dpm_check_smu_features(struct pp_hwmgr *hwmgr, @@ -1031,67 +1026,52 @@ static bool cz_dpm_check_smu_features(struct pp_hwmgr *hwmgr, int result; unsigned long features; - result = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_GetFeatureStatus, 0); + result = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetFeatureStatus, 0); if (result == 0) { - features = smum_get_argument(hwmgr->smumgr); + features = smum_get_argument(hwmgr); if (features & check_feature) return true; } - return result; + return false; } -static int cz_tf_check_for_dpm_disabled(struct pp_hwmgr *hwmgr, void *input, - void *output, void *storage, int result) +static bool cz_check_for_dpm_enabled(struct pp_hwmgr *hwmgr) { if (cz_dpm_check_smu_features(hwmgr, SMU_EnabledFeatureScoreboard_SclkDpmOn)) - return PP_Result_TableImmediateExit; - return 0; + return true; + return false; } -static int cz_tf_enable_didt(struct pp_hwmgr *hwmgr, void *input, - void *output, void *storage, int result) +static int cz_disable_dpm_tasks(struct pp_hwmgr *hwmgr) { - /* TO DO */ - return 0; -} + if (!cz_check_for_dpm_enabled(hwmgr)) { + pr_info("dpm has been disabled\n"); + return 0; + } + cz_disable_nb_dpm(hwmgr); -static int cz_tf_check_for_dpm_enabled(struct pp_hwmgr *hwmgr, - void *input, void *output, - void *storage, int result) -{ - if (!cz_dpm_check_smu_features(hwmgr, - SMU_EnabledFeatureScoreboard_SclkDpmOn)) - return PP_Result_TableImmediateExit; - return 0; -} + cz_clear_voting_clients(hwmgr); + if (cz_stop_dpm(hwmgr)) + return -EINVAL; -static const struct phm_master_table_item cz_disable_dpm_list[] = { - { .tableFunction = cz_tf_check_for_dpm_enabled }, - { }, + return 0; }; +static int cz_enable_dpm_tasks(struct pp_hwmgr *hwmgr) +{ + if (cz_check_for_dpm_enabled(hwmgr)) { + pr_info("dpm has been enabled\n"); + return 0; + } -static const struct phm_master_table_header cz_disable_dpm_master = { - 0, - PHM_MasterTableFlag_None, - cz_disable_dpm_list -}; - -static const struct phm_master_table_item cz_enable_dpm_list[] = { - { .tableFunction = cz_tf_check_for_dpm_disabled }, - { .tableFunction = cz_tf_program_voting_clients }, - { .tableFunction = cz_tf_start_dpm }, - { .tableFunction = cz_tf_program_bootup_state }, - { .tableFunction = cz_tf_enable_didt }, - { .tableFunction = cz_tf_reset_acp_boot_level }, - { }, -}; + cz_program_voting_clients(hwmgr); + if (cz_start_dpm(hwmgr)) + return -EINVAL; + cz_program_bootup_state(hwmgr); + cz_reset_acp_boot_level(hwmgr); -static const struct phm_master_table_header cz_enable_dpm_master = { - 0, - PHM_MasterTableFlag_None, - cz_enable_dpm_list + return 0; }; static int cz_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, @@ -1138,7 +1118,11 @@ static int cz_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, cz_ps->action = cz_current_ps->action; - if (!force_high && (cz_ps->action == FORCE_HIGH)) + if (hwmgr->request_dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) + cz_nbdpm_pstate_enable_disable(hwmgr, false, false); + else if (hwmgr->request_dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD) + cz_nbdpm_pstate_enable_disable(hwmgr, false, true); + else if (!force_high && (cz_ps->action == FORCE_HIGH)) cz_ps->action = CANCEL_FORCE_HIGH; else if (force_high && (cz_ps->action != FORCE_HIGH)) cz_ps->action = FORCE_HIGH; @@ -1173,62 +1157,16 @@ static int cz_hwmgr_backend_init(struct pp_hwmgr *hwmgr) cz_construct_boot_state(hwmgr); - result = phm_construct_table(hwmgr, &cz_setup_asic_master, - &(hwmgr->setup_asic)); - if (result != 0) { - pr_err("Fail to construct setup ASIC\n"); - return result; - } - - result = phm_construct_table(hwmgr, &cz_power_down_asic_master, - &(hwmgr->power_down_asic)); - if (result != 0) { - pr_err("Fail to construct power down ASIC\n"); - return result; - } - - result = phm_construct_table(hwmgr, &cz_disable_dpm_master, - &(hwmgr->disable_dynamic_state_management)); - if (result != 0) { - pr_err("Fail to disable_dynamic_state\n"); - return result; - } - result = phm_construct_table(hwmgr, &cz_enable_dpm_master, - &(hwmgr->enable_dynamic_state_management)); - if (result != 0) { - pr_err("Fail to enable_dynamic_state\n"); - return result; - } - result = phm_construct_table(hwmgr, &cz_set_power_state_master, - &(hwmgr->set_power_state)); - if (result != 0) { - pr_err("Fail to construct set_power_state\n"); - return result; - } hwmgr->platform_descriptor.hardwareActivityPerformanceLevels = CZ_MAX_HARDWARE_POWERLEVELS; - result = phm_construct_table(hwmgr, &cz_phm_enable_clock_power_gatings_master, &(hwmgr->enable_clock_power_gatings)); - if (result != 0) { - pr_err("Fail to construct enable_clock_power_gatings\n"); - return result; - } return result; } static int cz_hwmgr_backend_fini(struct pp_hwmgr *hwmgr) { if (hwmgr != NULL) { - phm_destroy_table(hwmgr, &(hwmgr->enable_clock_power_gatings)); - phm_destroy_table(hwmgr, &(hwmgr->set_power_state)); - phm_destroy_table(hwmgr, &(hwmgr->enable_dynamic_state_management)); - phm_destroy_table(hwmgr, &(hwmgr->disable_dynamic_state_management)); - phm_destroy_table(hwmgr, &(hwmgr->power_down_asic)); - phm_destroy_table(hwmgr, &(hwmgr->setup_asic)); - - if (NULL != hwmgr->dyn_state.vddc_dep_on_dal_pwrl) { - kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl); - hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL; - } + kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl); + hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL; kfree(hwmgr->backend); hwmgr->backend = NULL; @@ -1240,13 +1178,13 @@ static int cz_phm_force_dpm_highest(struct pp_hwmgr *hwmgr) { struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetSclkSoftMin, cz_get_sclk_level(hwmgr, cz_hwmgr->sclk_dpm.soft_max_clk, PPSMC_MSG_SetSclkSoftMin)); - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetSclkSoftMax, cz_get_sclk_level(hwmgr, cz_hwmgr->sclk_dpm.soft_max_clk, @@ -1278,13 +1216,13 @@ static int cz_phm_unforce_dpm_levels(struct pp_hwmgr *hwmgr) cz_hwmgr->sclk_dpm.soft_max_clk = clock; cz_hwmgr->sclk_dpm.hard_max_clk = clock; - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetSclkSoftMin, cz_get_sclk_level(hwmgr, cz_hwmgr->sclk_dpm.soft_min_clk, PPSMC_MSG_SetSclkSoftMin)); - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetSclkSoftMax, cz_get_sclk_level(hwmgr, cz_hwmgr->sclk_dpm.soft_max_clk, @@ -1297,13 +1235,13 @@ static int cz_phm_force_dpm_lowest(struct pp_hwmgr *hwmgr) { struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetSclkSoftMax, cz_get_sclk_level(hwmgr, cz_hwmgr->sclk_dpm.soft_min_clk, PPSMC_MSG_SetSclkSoftMax)); - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetSclkSoftMin, cz_get_sclk_level(hwmgr, cz_hwmgr->sclk_dpm.soft_min_clk, @@ -1312,106 +1250,25 @@ static int cz_phm_force_dpm_lowest(struct pp_hwmgr *hwmgr) return 0; } -static int cz_phm_force_dpm_sclk(struct pp_hwmgr *hwmgr, uint32_t sclk) -{ - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, - PPSMC_MSG_SetSclkSoftMin, - cz_get_sclk_level(hwmgr, - sclk, - PPSMC_MSG_SetSclkSoftMin)); - - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, - PPSMC_MSG_SetSclkSoftMax, - cz_get_sclk_level(hwmgr, - sclk, - PPSMC_MSG_SetSclkSoftMax)); - return 0; -} - -static int cz_get_profiling_clk(struct pp_hwmgr *hwmgr, uint32_t *sclk) -{ - struct phm_clock_voltage_dependency_table *table = - hwmgr->dyn_state.vddc_dependency_on_sclk; - int32_t tmp_sclk; - int32_t count; - - tmp_sclk = table->entries[table->count-1].clk * 70 / 100; - - for (count = table->count-1; count >= 0; count--) { - if (tmp_sclk >= table->entries[count].clk) { - tmp_sclk = table->entries[count].clk; - *sclk = tmp_sclk; - break; - } - } - if (count < 0) - *sclk = table->entries[0].clk; - - return 0; -} - static int cz_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level) { - uint32_t sclk = 0; int ret = 0; - uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | - AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | - AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; - - if (level == hwmgr->dpm_level) - return ret; - - if (!(hwmgr->dpm_level & profile_mode_mask)) { - /* enter profile mode, save current level, disable gfx cg*/ - if (level & profile_mode_mask) { - hwmgr->saved_dpm_level = hwmgr->dpm_level; - cgs_set_clockgating_state(hwmgr->device, - AMD_IP_BLOCK_TYPE_GFX, - AMD_CG_STATE_UNGATE); - } - } else { - /* exit profile mode, restore level, enable gfx cg*/ - if (!(level & profile_mode_mask)) { - if (level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT) - level = hwmgr->saved_dpm_level; - cgs_set_clockgating_state(hwmgr->device, - AMD_IP_BLOCK_TYPE_GFX, - AMD_CG_STATE_GATE); - } - } switch (level) { case AMD_DPM_FORCED_LEVEL_HIGH: case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: ret = cz_phm_force_dpm_highest(hwmgr); - if (ret) - return ret; - hwmgr->dpm_level = level; break; case AMD_DPM_FORCED_LEVEL_LOW: case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: + case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: ret = cz_phm_force_dpm_lowest(hwmgr); - if (ret) - return ret; - hwmgr->dpm_level = level; break; case AMD_DPM_FORCED_LEVEL_AUTO: ret = cz_phm_unforce_dpm_levels(hwmgr); - if (ret) - return ret; - hwmgr->dpm_level = level; - break; - case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: - ret = cz_get_profiling_clk(hwmgr, &sclk); - if (ret) - return ret; - hwmgr->dpm_level = level; - cz_phm_force_dpm_sclk(hwmgr, sclk); break; case AMD_DPM_FORCED_LEVEL_MANUAL: - hwmgr->dpm_level = level; - break; case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: default: break; @@ -1424,7 +1281,7 @@ int cz_dpm_powerdown_uvd(struct pp_hwmgr *hwmgr) { if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UVDPowerGating)) - return smum_send_msg_to_smc(hwmgr->smumgr, + return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_UVDPowerOFF); return 0; } @@ -1436,11 +1293,11 @@ int cz_dpm_powerup_uvd(struct pp_hwmgr *hwmgr) if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UVDDynamicPowerGating)) { return smum_send_msg_to_smc_with_parameter( - hwmgr->smumgr, + hwmgr, PPSMC_MSG_UVDPowerON, 1); } else { return smum_send_msg_to_smc_with_parameter( - hwmgr->smumgr, + hwmgr, PPSMC_MSG_UVDPowerON, 0); } } @@ -1457,11 +1314,12 @@ int cz_dpm_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate) if (!bgate) { /* Stable Pstate is enabled and we need to set the UVD DPM to highest level */ if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StablePState)) { + PHM_PlatformCaps_StablePState) + || hwmgr->en_umd_pstate) { cz_hwmgr->uvd_dpm.hard_min_clk = ptable->entries[ptable->count - 1].vclk; - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetUvdHardMin, cz_get_uvd_level(hwmgr, cz_hwmgr->uvd_dpm.hard_min_clk, @@ -1486,11 +1344,12 @@ int cz_dpm_update_vce_dpm(struct pp_hwmgr *hwmgr) /* Stable Pstate is enabled and we need to set the VCE DPM to highest level */ if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StablePState)) { + PHM_PlatformCaps_StablePState) + || hwmgr->en_umd_pstate) { cz_hwmgr->vce_dpm.hard_min_clk = ptable->entries[ptable->count - 1].ecclk; - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetEclkHardMin, cz_get_eclk_level(hwmgr, cz_hwmgr->vce_dpm.hard_min_clk, @@ -1498,15 +1357,15 @@ int cz_dpm_update_vce_dpm(struct pp_hwmgr *hwmgr) } else { /*Program HardMin based on the vce_arbiter.ecclk */ if (hwmgr->vce_arbiter.ecclk == 0) { - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetEclkHardMin, 0); /* disable ECLK DPM 0. Otherwise VCE could hang if * switching SCLK from DPM 0 to 6/7 */ - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetEclkSoftMin, 1); } else { cz_hwmgr->vce_dpm.hard_min_clk = hwmgr->vce_arbiter.ecclk; - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetEclkHardMin, cz_get_eclk_level(hwmgr, cz_hwmgr->vce_dpm.hard_min_clk, @@ -1520,7 +1379,7 @@ int cz_dpm_powerdown_vce(struct pp_hwmgr *hwmgr) { if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VCEPowerGating)) - return smum_send_msg_to_smc(hwmgr->smumgr, + return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_VCEPowerOFF); return 0; } @@ -1529,19 +1388,19 @@ int cz_dpm_powerup_vce(struct pp_hwmgr *hwmgr) { if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VCEPowerGating)) - return smum_send_msg_to_smc(hwmgr->smumgr, + return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_VCEPowerON); return 0; } -static int cz_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) +static uint32_t cz_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) { struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); return cz_hwmgr->sys_info.bootup_uma_clock; } -static int cz_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low) +static uint32_t cz_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low) { struct pp_power_state *ps; struct cz_power_state *cz_ps; @@ -1679,7 +1538,7 @@ static void cz_hw_print_display_cfg( PP_DBG_LOG("SetDisplaySizePowerParams data: 0x%X\n", data); - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetDisplaySizePowerParams, data); } @@ -1744,10 +1603,10 @@ static int cz_force_clock_level(struct pp_hwmgr *hwmgr, switch (type) { case PP_SCLK: - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetSclkSoftMin, mask); - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetSclkSoftMax, mask); break; @@ -1989,7 +1848,7 @@ static int cz_read_sensor(struct pp_hwmgr *hwmgr, int idx, *((uint32_t *)value) = 0; return 0; case AMDGPU_PP_SENSOR_GPU_LOAD: - result = smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_GetAverageGraphicsActivity); + result = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetAverageGraphicsActivity); if (0 == result) { activity_percent = cgs_read_register(hwmgr->device, mmSMU_MP1_SRBM2P_ARG_0); activity_percent = activity_percent > 100 ? 100 : activity_percent; @@ -2015,7 +1874,6 @@ static int cz_read_sensor(struct pp_hwmgr *hwmgr, int idx, static const struct pp_hwmgr_func cz_hwmgr_funcs = { .backend_init = cz_hwmgr_backend_init, .backend_fini = cz_hwmgr_backend_fini, - .asic_setup = NULL, .apply_state_adjust_rules = cz_apply_state_adjust_rules, .force_dpm_level = cz_dpm_force_dpm_level, .get_power_state_size = cz_get_power_state_size, @@ -2037,6 +1895,11 @@ static const struct pp_hwmgr_func cz_hwmgr_funcs = { .get_clock_by_type = cz_get_clock_by_type, .get_max_high_clocks = cz_get_max_high_clocks, .read_sensor = cz_read_sensor, + .power_off_asic = cz_power_off_asic, + .asic_setup = cz_setup_asic_task, + .dynamic_state_management_enable = cz_enable_dpm_tasks, + .power_state_set = cz_set_power_state_tasks, + .dynamic_state_management_disable = cz_disable_dpm_tasks, }; int cz_init_function_pointers(struct pp_hwmgr *hwmgr) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/functiontables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/functiontables.c deleted file mode 100644 index bc7d8bd..0000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/functiontables.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright 2015 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include "hwmgr.h" - -static int phm_run_table(struct pp_hwmgr *hwmgr, - struct phm_runtime_table_header *rt_table, - void *input, - void *output, - void *temp_storage) -{ - int result = 0; - phm_table_function *function; - - if (rt_table->function_list == NULL) { - pr_debug("this function not implement!\n"); - return 0; - } - - for (function = rt_table->function_list; NULL != *function; function++) { - int tmp = (*function)(hwmgr, input, output, temp_storage, result); - - if (tmp == PP_Result_TableImmediateExit) - break; - if (tmp) { - if (0 == result) - result = tmp; - if (rt_table->exit_error) - break; - } - } - - return result; -} - -int phm_dispatch_table(struct pp_hwmgr *hwmgr, - struct phm_runtime_table_header *rt_table, - void *input, void *output) -{ - int result; - void *temp_storage; - - if (hwmgr == NULL || rt_table == NULL) { - pr_err("Invalid Parameter!\n"); - return -EINVAL; - } - - if (0 != rt_table->storage_size) { - temp_storage = kzalloc(rt_table->storage_size, GFP_KERNEL); - if (temp_storage == NULL) { - pr_err("Could not allocate table temporary storage\n"); - return -ENOMEM; - } - } else { - temp_storage = NULL; - } - - result = phm_run_table(hwmgr, rt_table, input, output, temp_storage); - - kfree(temp_storage); - - return result; -} - -int phm_construct_table(struct pp_hwmgr *hwmgr, - const struct phm_master_table_header *master_table, - struct phm_runtime_table_header *rt_table) -{ - uint32_t function_count = 0; - const struct phm_master_table_item *table_item; - uint32_t size; - phm_table_function *run_time_list; - phm_table_function *rtf; - - if (hwmgr == NULL || master_table == NULL || rt_table == NULL) { - pr_err("Invalid Parameter!\n"); - return -EINVAL; - } - - for (table_item = master_table->master_list; - NULL != table_item->tableFunction; table_item++) { - if ((NULL == table_item->isFunctionNeededInRuntimeTable) || - (table_item->isFunctionNeededInRuntimeTable(hwmgr))) - function_count++; - } - - size = (function_count + 1) * sizeof(phm_table_function); - run_time_list = kzalloc(size, GFP_KERNEL); - - if (NULL == run_time_list) - return -ENOMEM; - - rtf = run_time_list; - for (table_item = master_table->master_list; - NULL != table_item->tableFunction; table_item++) { - if ((rtf - run_time_list) > function_count) { - pr_err("Check function results have changed\n"); - kfree(run_time_list); - return -EINVAL; - } - - if ((NULL == table_item->isFunctionNeededInRuntimeTable) || - (table_item->isFunctionNeededInRuntimeTable(hwmgr))) { - *(rtf++) = table_item->tableFunction; - } - } - - if ((rtf - run_time_list) > function_count) { - pr_err("Check function results have changed\n"); - kfree(run_time_list); - return -EINVAL; - } - - *rtf = NULL; - rt_table->function_list = run_time_list; - rt_table->exit_error = (0 != (master_table->flags & PHM_MasterTableFlag_ExitOnError)); - rt_table->storage_size = master_table->storage_size; - return 0; -} - -int phm_destroy_table(struct pp_hwmgr *hwmgr, - struct phm_runtime_table_header *rt_table) -{ - if (hwmgr == NULL || rt_table == NULL) { - pr_err("Invalid Parameter\n"); - return -EINVAL; - } - - if (NULL == rt_table->function_list) - return 0; - - kfree(rt_table->function_list); - - rt_table->function_list = NULL; - rt_table->storage_size = 0; - rt_table->exit_error = false; - - return 0; -} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c index fcc722e..623cff9 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c @@ -26,35 +26,22 @@ #include "hardwaremanager.h" #include "power_state.h" + +#define TEMP_RANGE_MIN (0) +#define TEMP_RANGE_MAX (80 * 1000) + #define PHM_FUNC_CHECK(hw) \ do { \ if ((hw) == NULL || (hw)->hwmgr_func == NULL) \ return -EINVAL; \ } while (0) -bool phm_is_hw_access_blocked(struct pp_hwmgr *hwmgr) -{ - return hwmgr->block_hw_access; -} - -int phm_block_hw_access(struct pp_hwmgr *hwmgr, bool block) -{ - hwmgr->block_hw_access = block; - return 0; -} - int phm_setup_asic(struct pp_hwmgr *hwmgr) { PHM_FUNC_CHECK(hwmgr); - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TablelessHardwareInterface)) { - if (NULL != hwmgr->hwmgr_func->asic_setup) - return hwmgr->hwmgr_func->asic_setup(hwmgr); - } else { - return phm_dispatch_table(hwmgr, &(hwmgr->setup_asic), - NULL, NULL); - } + if (NULL != hwmgr->hwmgr_func->asic_setup) + return hwmgr->hwmgr_func->asic_setup(hwmgr); return 0; } @@ -63,14 +50,8 @@ int phm_power_down_asic(struct pp_hwmgr *hwmgr) { PHM_FUNC_CHECK(hwmgr); - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TablelessHardwareInterface)) { - if (NULL != hwmgr->hwmgr_func->power_off_asic) - return hwmgr->hwmgr_func->power_off_asic(hwmgr); - } else { - return phm_dispatch_table(hwmgr, &(hwmgr->power_down_asic), - NULL, NULL); - } + if (NULL != hwmgr->hwmgr_func->power_off_asic) + return hwmgr->hwmgr_func->power_off_asic(hwmgr); return 0; } @@ -86,13 +67,8 @@ int phm_set_power_state(struct pp_hwmgr *hwmgr, states.pcurrent_state = pcurrent_state; states.pnew_state = pnew_power_state; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TablelessHardwareInterface)) { - if (NULL != hwmgr->hwmgr_func->power_state_set) - return hwmgr->hwmgr_func->power_state_set(hwmgr, &states); - } else { - return phm_dispatch_table(hwmgr, &(hwmgr->set_power_state), &states, NULL); - } + if (NULL != hwmgr->hwmgr_func->power_state_set) + return hwmgr->hwmgr_func->power_state_set(hwmgr, &states); return 0; } @@ -103,15 +79,8 @@ int phm_enable_dynamic_state_management(struct pp_hwmgr *hwmgr) bool enabled; PHM_FUNC_CHECK(hwmgr); - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TablelessHardwareInterface)) { - if (NULL != hwmgr->hwmgr_func->dynamic_state_management_enable) - ret = hwmgr->hwmgr_func->dynamic_state_management_enable(hwmgr); - } else { - ret = phm_dispatch_table(hwmgr, - &(hwmgr->enable_dynamic_state_management), - NULL, NULL); - } + if (NULL != hwmgr->hwmgr_func->dynamic_state_management_enable) + ret = hwmgr->hwmgr_func->dynamic_state_management_enable(hwmgr); enabled = ret == 0; @@ -127,15 +96,8 @@ int phm_disable_dynamic_state_management(struct pp_hwmgr *hwmgr) PHM_FUNC_CHECK(hwmgr); - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TablelessHardwareInterface)) { - if (hwmgr->hwmgr_func->dynamic_state_management_disable) - ret = hwmgr->hwmgr_func->dynamic_state_management_disable(hwmgr); - } else { - ret = phm_dispatch_table(hwmgr, - &(hwmgr->disable_dynamic_state_management), - NULL, NULL); - } + if (hwmgr->hwmgr_func->dynamic_state_management_disable) + ret = hwmgr->hwmgr_func->dynamic_state_management_disable(hwmgr); enabled = ret == 0 ? false : true; @@ -193,35 +155,13 @@ int phm_powerdown_uvd(struct pp_hwmgr *hwmgr) return 0; } -int phm_powergate_uvd(struct pp_hwmgr *hwmgr, bool gate) -{ - PHM_FUNC_CHECK(hwmgr); - - if (hwmgr->hwmgr_func->powergate_uvd != NULL) - return hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate); - return 0; -} - -int phm_powergate_vce(struct pp_hwmgr *hwmgr, bool gate) -{ - PHM_FUNC_CHECK(hwmgr); - - if (hwmgr->hwmgr_func->powergate_vce != NULL) - return hwmgr->hwmgr_func->powergate_vce(hwmgr, gate); - return 0; -} - int phm_enable_clock_power_gatings(struct pp_hwmgr *hwmgr) { PHM_FUNC_CHECK(hwmgr); - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TablelessHardwareInterface)) { - if (NULL != hwmgr->hwmgr_func->enable_clock_power_gating) - return hwmgr->hwmgr_func->enable_clock_power_gating(hwmgr); - } else { - return phm_dispatch_table(hwmgr, &(hwmgr->enable_clock_power_gatings), NULL, NULL); - } + if (NULL != hwmgr->hwmgr_func->enable_clock_power_gating) + return hwmgr->hwmgr_func->enable_clock_power_gating(hwmgr); + return 0; } @@ -229,11 +169,9 @@ int phm_disable_clock_power_gatings(struct pp_hwmgr *hwmgr) { PHM_FUNC_CHECK(hwmgr); - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TablelessHardwareInterface)) { - if (NULL != hwmgr->hwmgr_func->disable_clock_power_gating) - return hwmgr->hwmgr_func->disable_clock_power_gating(hwmgr); - } + if (NULL != hwmgr->hwmgr_func->disable_clock_power_gating) + return hwmgr->hwmgr_func->disable_clock_power_gating(hwmgr); + return 0; } @@ -242,12 +180,9 @@ int phm_display_configuration_changed(struct pp_hwmgr *hwmgr) { PHM_FUNC_CHECK(hwmgr); - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TablelessHardwareInterface)) { - if (NULL != hwmgr->hwmgr_func->display_config_changed) - hwmgr->hwmgr_func->display_config_changed(hwmgr); - } else - return phm_dispatch_table(hwmgr, &hwmgr->display_configuration_changed, NULL, NULL); + if (NULL != hwmgr->hwmgr_func->display_config_changed) + hwmgr->hwmgr_func->display_config_changed(hwmgr); + return 0; } @@ -255,9 +190,7 @@ int phm_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr) { PHM_FUNC_CHECK(hwmgr); - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TablelessHardwareInterface)) - if (NULL != hwmgr->hwmgr_func->notify_smc_display_config_after_ps_adjustment) + if (NULL != hwmgr->hwmgr_func->notify_smc_display_config_after_ps_adjustment) hwmgr->hwmgr_func->notify_smc_display_config_after_ps_adjustment(hwmgr); return 0; @@ -277,10 +210,10 @@ int phm_register_thermal_interrupt(struct pp_hwmgr *hwmgr, const void *info) { PHM_FUNC_CHECK(hwmgr); - if (hwmgr->hwmgr_func->register_internal_thermal_interrupt == NULL) - return -EINVAL; + if (hwmgr->hwmgr_func->register_internal_thermal_interrupt != NULL) + return hwmgr->hwmgr_func->register_internal_thermal_interrupt(hwmgr, info); - return hwmgr->hwmgr_func->register_internal_thermal_interrupt(hwmgr, info); + return 0; } /** @@ -292,7 +225,21 @@ int phm_register_thermal_interrupt(struct pp_hwmgr *hwmgr, const void *info) */ int phm_start_thermal_controller(struct pp_hwmgr *hwmgr, struct PP_TemperatureRange *temperature_range) { - return phm_dispatch_table(hwmgr, &(hwmgr->start_thermal_controller), temperature_range, NULL); + struct PP_TemperatureRange range; + + if (temperature_range == NULL) { + range.max = TEMP_RANGE_MAX; + range.min = TEMP_RANGE_MIN; + } else { + range.max = temperature_range->max; + range.min = temperature_range->min; + } + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ThermalController) + && hwmgr->hwmgr_func->start_thermal_controller != NULL) + return hwmgr->hwmgr_func->start_thermal_controller(hwmgr, &range); + + return 0; } @@ -323,6 +270,9 @@ int phm_check_states_equal(struct pp_hwmgr *hwmgr, int phm_store_dal_configuration_data(struct pp_hwmgr *hwmgr, const struct amd_pp_display_configuration *display_config) { + int index = 0; + int number_of_active_display = 0; + PHM_FUNC_CHECK(hwmgr); if (display_config == NULL) @@ -330,6 +280,17 @@ int phm_store_dal_configuration_data(struct pp_hwmgr *hwmgr, hwmgr->display_config = *display_config; + if (NULL != hwmgr->hwmgr_func->set_deep_sleep_dcefclk) + hwmgr->hwmgr_func->set_deep_sleep_dcefclk(hwmgr, hwmgr->display_config.min_dcef_deep_sleep_set_clk); + + for (index = 0; index < hwmgr->display_config.num_path_including_non_display; index++) { + if (hwmgr->display_config.displays[index].controller_id != 0) + number_of_active_display++; + } + + if (NULL != hwmgr->hwmgr_func->set_active_display_count) + hwmgr->hwmgr_func->set_active_display_count(hwmgr, number_of_active_display); + if (hwmgr->hwmgr_func->store_cc6_data == NULL) return -EINVAL; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c index 9547f26..35e80c9 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c @@ -26,8 +26,8 @@ #include <linux/kernel.h> #include <linux/slab.h> #include <linux/types.h> +#include <linux/pci.h> #include <drm/amdgpu_drm.h> -#include "cgs_common.h" #include "power_state.h" #include "hwmgr.h" #include "pppcielanes.h" @@ -35,21 +35,100 @@ #include "ppsmc.h" #include "pp_acpi.h" #include "amd_acpi.h" +#include "pp_psm.h" -extern int cz_init_function_pointers(struct pp_hwmgr *hwmgr); +extern const struct pp_smumgr_func ci_smu_funcs; +extern const struct pp_smumgr_func cz_smu_funcs; +extern const struct pp_smumgr_func iceland_smu_funcs; +extern const struct pp_smumgr_func tonga_smu_funcs; +extern const struct pp_smumgr_func fiji_smu_funcs; +extern const struct pp_smumgr_func polaris10_smu_funcs; +extern const struct pp_smumgr_func vega10_smu_funcs; +extern const struct pp_smumgr_func rv_smu_funcs; +extern int cz_init_function_pointers(struct pp_hwmgr *hwmgr); static int polaris_set_asic_special_caps(struct pp_hwmgr *hwmgr); static void hwmgr_init_default_caps(struct pp_hwmgr *hwmgr); static int hwmgr_set_user_specify_caps(struct pp_hwmgr *hwmgr); static int fiji_set_asic_special_caps(struct pp_hwmgr *hwmgr); static int tonga_set_asic_special_caps(struct pp_hwmgr *hwmgr); static int topaz_set_asic_special_caps(struct pp_hwmgr *hwmgr); +static int ci_set_asic_special_caps(struct pp_hwmgr *hwmgr); uint8_t convert_to_vid(uint16_t vddc) { return (uint8_t) ((6200 - (vddc * VOLTAGE_SCALE)) / 25); } +static int phm_get_pci_bus_devfn(struct pp_hwmgr *hwmgr, + struct cgs_system_info *sys_info) +{ + sys_info->size = sizeof(struct cgs_system_info); + sys_info->info_id = CGS_SYSTEM_INFO_PCIE_BUS_DEVFN; + + return cgs_query_system_info(hwmgr->device, sys_info); +} + +static int phm_thermal_l2h_irq(void *private_data, + unsigned src_id, const uint32_t *iv_entry) +{ + struct pp_hwmgr *hwmgr = (struct pp_hwmgr *)private_data; + struct cgs_system_info sys_info = {0}; + int result; + + result = phm_get_pci_bus_devfn(hwmgr, &sys_info); + if (result) + return -EINVAL; + + pr_warn("GPU over temperature range detected on PCIe %lld:%lld.%lld!\n", + PCI_BUS_NUM(sys_info.value), + PCI_SLOT(sys_info.value), + PCI_FUNC(sys_info.value)); + return 0; +} + +static int phm_thermal_h2l_irq(void *private_data, + unsigned src_id, const uint32_t *iv_entry) +{ + struct pp_hwmgr *hwmgr = (struct pp_hwmgr *)private_data; + struct cgs_system_info sys_info = {0}; + int result; + + result = phm_get_pci_bus_devfn(hwmgr, &sys_info); + if (result) + return -EINVAL; + + pr_warn("GPU under temperature range detected on PCIe %lld:%lld.%lld!\n", + PCI_BUS_NUM(sys_info.value), + PCI_SLOT(sys_info.value), + PCI_FUNC(sys_info.value)); + return 0; +} + +static int phm_ctf_irq(void *private_data, + unsigned src_id, const uint32_t *iv_entry) +{ + struct pp_hwmgr *hwmgr = (struct pp_hwmgr *)private_data; + struct cgs_system_info sys_info = {0}; + int result; + + result = phm_get_pci_bus_devfn(hwmgr, &sys_info); + if (result) + return -EINVAL; + + pr_warn("GPU Critical Temperature Fault detected on PCIe %lld:%lld.%lld!\n", + PCI_BUS_NUM(sys_info.value), + PCI_SLOT(sys_info.value), + PCI_FUNC(sys_info.value)); + return 0; +} + +static const struct cgs_irq_src_funcs thermal_irq_src[3] = { + { .handler = phm_thermal_l2h_irq }, + { .handler = phm_thermal_h2l_irq }, + { .handler = phm_ctf_irq } +}; + int hwmgr_early_init(struct pp_instance *handle) { struct pp_hwmgr *hwmgr; @@ -62,7 +141,6 @@ int hwmgr_early_init(struct pp_instance *handle) return -ENOMEM; handle->hwmgr = hwmgr; - hwmgr->smumgr = handle->smu_mgr; hwmgr->device = handle->device; hwmgr->chip_family = handle->chip_family; hwmgr->chip_id = handle->chip_id; @@ -73,24 +151,38 @@ int hwmgr_early_init(struct pp_instance *handle) hwmgr->dpm_level = AMD_DPM_FORCED_LEVEL_AUTO; hwmgr_init_default_caps(hwmgr); hwmgr_set_user_specify_caps(hwmgr); + hwmgr->fan_ctrl_is_in_default_mode = true; + hwmgr->reload_fw = 1; switch (hwmgr->chip_family) { + case AMDGPU_FAMILY_CI: + hwmgr->smumgr_funcs = &ci_smu_funcs; + ci_set_asic_special_caps(hwmgr); + hwmgr->feature_mask &= ~(PP_VBI_TIME_SUPPORT_MASK | + PP_ENABLE_GFX_CG_THRU_SMU); + hwmgr->pp_table_version = PP_TABLE_V0; + smu7_init_function_pointers(hwmgr); + break; case AMDGPU_FAMILY_CZ: + hwmgr->smumgr_funcs = &cz_smu_funcs; cz_init_function_pointers(hwmgr); break; case AMDGPU_FAMILY_VI: switch (hwmgr->chip_id) { case CHIP_TOPAZ: + hwmgr->smumgr_funcs = &iceland_smu_funcs; topaz_set_asic_special_caps(hwmgr); hwmgr->feature_mask &= ~ (PP_VBI_TIME_SUPPORT_MASK | PP_ENABLE_GFX_CG_THRU_SMU); hwmgr->pp_table_version = PP_TABLE_V0; break; case CHIP_TONGA: + hwmgr->smumgr_funcs = &tonga_smu_funcs; tonga_set_asic_special_caps(hwmgr); hwmgr->feature_mask &= ~PP_VBI_TIME_SUPPORT_MASK; break; case CHIP_FIJI: + hwmgr->smumgr_funcs = &fiji_smu_funcs; fiji_set_asic_special_caps(hwmgr); hwmgr->feature_mask &= ~ (PP_VBI_TIME_SUPPORT_MASK | PP_ENABLE_GFX_CG_THRU_SMU); @@ -98,6 +190,7 @@ int hwmgr_early_init(struct pp_instance *handle) case CHIP_POLARIS11: case CHIP_POLARIS10: case CHIP_POLARIS12: + hwmgr->smumgr_funcs = &polaris10_smu_funcs; polaris_set_asic_special_caps(hwmgr); hwmgr->feature_mask &= ~(PP_UVD_HANDSHAKE_MASK); break; @@ -109,6 +202,7 @@ int hwmgr_early_init(struct pp_instance *handle) case AMDGPU_FAMILY_AI: switch (hwmgr->chip_id) { case CHIP_VEGA10: + hwmgr->smumgr_funcs = &vega10_smu_funcs; vega10_hwmgr_init(hwmgr); break; default: @@ -118,6 +212,7 @@ int hwmgr_early_init(struct pp_instance *handle) case AMDGPU_FAMILY_RV: switch (hwmgr->chip_id) { case CHIP_RAVEN: + hwmgr->smumgr_funcs = &rv_smu_funcs; rv_init_function_pointers(hwmgr); break; default: @@ -131,80 +226,6 @@ int hwmgr_early_init(struct pp_instance *handle) return 0; } -static int hw_init_power_state_table(struct pp_hwmgr *hwmgr) -{ - int result; - unsigned int i; - unsigned int table_entries; - struct pp_power_state *state; - int size; - - if (hwmgr->hwmgr_func->get_num_of_pp_table_entries == NULL) - return -EINVAL; - - if (hwmgr->hwmgr_func->get_power_state_size == NULL) - return -EINVAL; - - hwmgr->num_ps = table_entries = hwmgr->hwmgr_func->get_num_of_pp_table_entries(hwmgr); - - hwmgr->ps_size = size = hwmgr->hwmgr_func->get_power_state_size(hwmgr) + - sizeof(struct pp_power_state); - - hwmgr->ps = kzalloc(size * table_entries, GFP_KERNEL); - if (hwmgr->ps == NULL) - return -ENOMEM; - - hwmgr->request_ps = kzalloc(size, GFP_KERNEL); - if (hwmgr->request_ps == NULL) { - kfree(hwmgr->ps); - hwmgr->ps = NULL; - return -ENOMEM; - } - - hwmgr->current_ps = kzalloc(size, GFP_KERNEL); - if (hwmgr->current_ps == NULL) { - kfree(hwmgr->request_ps); - kfree(hwmgr->ps); - hwmgr->request_ps = NULL; - hwmgr->ps = NULL; - return -ENOMEM; - } - - state = hwmgr->ps; - - for (i = 0; i < table_entries; i++) { - result = hwmgr->hwmgr_func->get_pp_table_entry(hwmgr, i, state); - - if (state->classification.flags & PP_StateClassificationFlag_Boot) { - hwmgr->boot_ps = state; - memcpy(hwmgr->current_ps, state, size); - memcpy(hwmgr->request_ps, state, size); - } - - state->id = i + 1; /* assigned unique num for every power state id */ - - if (state->classification.flags & PP_StateClassificationFlag_Uvd) - hwmgr->uvd_ps = state; - state = (struct pp_power_state *)((unsigned long)state + size); - } - - return 0; -} - -static int hw_fini_power_state_table(struct pp_hwmgr *hwmgr) -{ - if (hwmgr == NULL) - return -EINVAL; - - kfree(hwmgr->current_ps); - kfree(hwmgr->request_ps); - kfree(hwmgr->ps); - hwmgr->request_ps = NULL; - hwmgr->ps = NULL; - hwmgr->current_ps = NULL; - return 0; -} - int hwmgr_hw_init(struct pp_instance *handle) { struct pp_hwmgr *hwmgr; @@ -228,9 +249,26 @@ int hwmgr_hw_init(struct pp_instance *handle) if (ret) goto err1; - ret = hw_init_power_state_table(hwmgr); + ret = psm_init_power_state_table(hwmgr); + if (ret) + goto err2; + + ret = phm_setup_asic(hwmgr); if (ret) goto err2; + + ret = phm_enable_dynamic_state_management(hwmgr); + if (ret) + goto err2; + ret = phm_start_thermal_controller(hwmgr, NULL); + ret |= psm_set_performance_states(hwmgr); + if (ret) + goto err2; + + ret = phm_register_thermal_interrupt(hwmgr, &thermal_irq_src); + if (ret) + goto err2; + return 0; err2: if (hwmgr->hwmgr_func->backend_fini) @@ -247,19 +285,138 @@ int hwmgr_hw_fini(struct pp_instance *handle) { struct pp_hwmgr *hwmgr; - if (handle == NULL) + if (handle == NULL || handle->hwmgr == NULL) return -EINVAL; hwmgr = handle->hwmgr; + phm_stop_thermal_controller(hwmgr); + psm_set_boot_states(hwmgr); + phm_display_configuration_changed(hwmgr); + psm_adjust_power_state_dynamic(hwmgr, false, NULL); + phm_disable_dynamic_state_management(hwmgr); + phm_disable_clock_power_gatings(hwmgr); + if (hwmgr->hwmgr_func->backend_fini) hwmgr->hwmgr_func->backend_fini(hwmgr); if (hwmgr->pptable_func->pptable_fini) hwmgr->pptable_func->pptable_fini(hwmgr); - return hw_fini_power_state_table(hwmgr); + return psm_fini_power_state_table(hwmgr); } +int hwmgr_hw_suspend(struct pp_instance *handle) +{ + struct pp_hwmgr *hwmgr; + int ret = 0; + + if (handle == NULL || handle->hwmgr == NULL) + return -EINVAL; + + hwmgr = handle->hwmgr; + phm_disable_smc_firmware_ctf(hwmgr); + ret = psm_set_boot_states(hwmgr); + if (ret) + return ret; + ret = psm_adjust_power_state_dynamic(hwmgr, false, NULL); + if (ret) + return ret; + ret = phm_power_down_asic(hwmgr); + + return ret; +} +int hwmgr_hw_resume(struct pp_instance *handle) +{ + struct pp_hwmgr *hwmgr; + int ret = 0; + + if (handle == NULL || handle->hwmgr == NULL) + return -EINVAL; + + hwmgr = handle->hwmgr; + ret = phm_setup_asic(hwmgr); + if (ret) + return ret; + + ret = phm_enable_dynamic_state_management(hwmgr); + if (ret) + return ret; + ret = phm_start_thermal_controller(hwmgr, NULL); + if (ret) + return ret; + + ret |= psm_set_performance_states(hwmgr); + if (ret) + return ret; + + ret = psm_adjust_power_state_dynamic(hwmgr, false, NULL); + + return ret; +} + +static enum PP_StateUILabel power_state_convert(enum amd_pm_state_type state) +{ + switch (state) { + case POWER_STATE_TYPE_BATTERY: + return PP_StateUILabel_Battery; + case POWER_STATE_TYPE_BALANCED: + return PP_StateUILabel_Balanced; + case POWER_STATE_TYPE_PERFORMANCE: + return PP_StateUILabel_Performance; + default: + return PP_StateUILabel_None; + } +} + +int hwmgr_handle_task(struct pp_instance *handle, enum amd_pp_task task_id, + void *input, void *output) +{ + int ret = 0; + struct pp_hwmgr *hwmgr; + + if (handle == NULL || handle->hwmgr == NULL) + return -EINVAL; + + hwmgr = handle->hwmgr; + + switch (task_id) { + case AMD_PP_TASK_DISPLAY_CONFIG_CHANGE: + ret = phm_set_cpu_power_state(hwmgr); + if (ret) + return ret; + ret = psm_set_performance_states(hwmgr); + if (ret) + return ret; + ret = psm_adjust_power_state_dynamic(hwmgr, false, NULL); + break; + case AMD_PP_TASK_ENABLE_USER_STATE: + { + enum amd_pm_state_type ps; + enum PP_StateUILabel requested_ui_label; + struct pp_power_state *requested_ps = NULL; + + if (input == NULL) { + ret = -EINVAL; + break; + } + ps = *(unsigned long *)input; + + requested_ui_label = power_state_convert(ps); + ret = psm_set_user_performance_state(hwmgr, requested_ui_label, &requested_ps); + if (ret) + return ret; + ret = psm_adjust_power_state_dynamic(hwmgr, false, requested_ps); + break; + } + case AMD_PP_TASK_COMPLETE_INIT: + case AMD_PP_TASK_READJUST_POWER_STATE: + ret = psm_adjust_power_state_dynamic(hwmgr, false, NULL); + break; + default: + break; + } + return ret; +} /** * Returns once the part of the register indicated by the mask has * reached the given value. @@ -294,7 +451,7 @@ int phm_wait_on_register(struct pp_hwmgr *hwmgr, uint32_t index, * reached the given value.The indirect space is described by giving * the memory-mapped index of the indirect index register. */ -void phm_wait_on_indirect_register(struct pp_hwmgr *hwmgr, +int phm_wait_on_indirect_register(struct pp_hwmgr *hwmgr, uint32_t indirect_port, uint32_t index, uint32_t value, @@ -302,14 +459,50 @@ void phm_wait_on_indirect_register(struct pp_hwmgr *hwmgr, { if (hwmgr == NULL || hwmgr->device == NULL) { pr_err("Invalid Hardware Manager!"); - return; + return -EINVAL; } cgs_write_register(hwmgr->device, indirect_port, index); - phm_wait_on_register(hwmgr, indirect_port + 1, mask, value); + return phm_wait_on_register(hwmgr, indirect_port + 1, mask, value); +} + +int phm_wait_for_register_unequal(struct pp_hwmgr *hwmgr, + uint32_t index, + uint32_t value, uint32_t mask) +{ + uint32_t i; + uint32_t cur_value; + + if (hwmgr == NULL || hwmgr->device == NULL) + return -EINVAL; + + for (i = 0; i < hwmgr->usec_timeout; i++) { + cur_value = cgs_read_register(hwmgr->device, + index); + if ((cur_value & mask) != (value & mask)) + break; + udelay(1); + } + + /* timeout means wrong logic */ + if (i == hwmgr->usec_timeout) + return -ETIME; + return 0; } +int phm_wait_for_indirect_register_unequal(struct pp_hwmgr *hwmgr, + uint32_t indirect_port, + uint32_t index, + uint32_t value, + uint32_t mask) +{ + if (hwmgr == NULL || hwmgr->device == NULL) + return -EINVAL; + cgs_write_register(hwmgr->device, indirect_port, index); + return phm_wait_for_register_unequal(hwmgr, indirect_port + 1, + value, mask); +} bool phm_cf_want_uvd_power_gating(struct pp_hwmgr *hwmgr) { @@ -678,7 +871,7 @@ void phm_apply_dal_min_voltage_request(struct pp_hwmgr *hwmgr) for (i = 0; i < vddc_table->count; i++) { if (req_vddc <= vddc_table->entries[i].vddc) { req_volt = (((uint32_t)vddc_table->entries[i].vddc) * VOLTAGE_SCALE); - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_VddC_Request, req_volt); return; } @@ -689,28 +882,8 @@ void phm_apply_dal_min_voltage_request(struct pp_hwmgr *hwmgr) void hwmgr_init_default_caps(struct pp_hwmgr *hwmgr) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableVoltageTransition); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableEngineTransition); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMemoryTransition); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMGClockGating); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMGCGTSSM); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableLSClockGating); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_Force3DClockSupport); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableLightSleep); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMCLS); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisablePowerGating); - - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableDPM); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableSMUUVDHandshake); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_ThermalAutoThrottling); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PCIEPerformanceRequest); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_NoOD5Support); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UserMaxClockForMultiDisplays); - - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VpuRecoveryInProgress); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UVDDPM); phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VCEDPM); @@ -735,7 +908,6 @@ void hwmgr_init_default_caps(struct pp_hwmgr *hwmgr) phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_FanSpeedInTableIsRPM); - return; } @@ -784,7 +956,8 @@ int phm_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type, int polaris_set_asic_special_caps(struct pp_hwmgr *hwmgr) { - + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EVV); phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SQRamping); phm_cap_set(hwmgr->platform_descriptor.platformCaps, @@ -793,10 +966,6 @@ int polaris_set_asic_special_caps(struct pp_hwmgr *hwmgr) phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_AutomaticDCTransition); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TablelessHardwareInterface); - - if (hwmgr->chip_id != CHIP_POLARIS10) phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SPLLShutdownSupport); @@ -814,6 +983,8 @@ int polaris_set_asic_special_caps(struct pp_hwmgr *hwmgr) int fiji_set_asic_special_caps(struct pp_hwmgr *hwmgr) { + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EVV); phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SQRamping); phm_cap_unset(hwmgr->platform_descriptor.platformCaps, @@ -822,15 +993,13 @@ int fiji_set_asic_special_caps(struct pp_hwmgr *hwmgr) PHM_PlatformCaps_TDRamping); phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TCPRamping); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TablelessHardwareInterface); - return 0; } int tonga_set_asic_special_caps(struct pp_hwmgr *hwmgr) { + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EVV); phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SQRamping); phm_cap_unset(hwmgr->platform_descriptor.platformCaps, @@ -844,14 +1013,25 @@ int tonga_set_asic_special_caps(struct pp_hwmgr *hwmgr) PHM_PlatformCaps_UVDPowerGating); phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VCEPowerGating); + return 0; +} +int topaz_set_asic_special_caps(struct pp_hwmgr *hwmgr) +{ phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TablelessHardwareInterface); - + PHM_PlatformCaps_EVV); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SQRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DBRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TDRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TCPRamping); return 0; } -int topaz_set_asic_special_caps(struct pp_hwmgr *hwmgr) +int ci_set_asic_special_caps(struct pp_hwmgr *hwmgr) { phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SQRamping); @@ -862,8 +1042,8 @@ int topaz_set_asic_special_caps(struct pp_hwmgr *hwmgr) phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TCPRamping); phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TablelessHardwareInterface); + PHM_PlatformCaps_MemorySpreadSpectrumSupport); phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_EVV); + PHM_PlatformCaps_EngineSpreadSpectrumSupport); return 0; } diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.c b/drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.c new file mode 100644 index 0000000..167cdc3 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.c @@ -0,0 +1,246 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include "pp_psm.h" + +int psm_init_power_state_table(struct pp_hwmgr *hwmgr) +{ + int result; + unsigned int i; + unsigned int table_entries; + struct pp_power_state *state; + int size; + + if (hwmgr->hwmgr_func->get_num_of_pp_table_entries == NULL) + return -EINVAL; + + if (hwmgr->hwmgr_func->get_power_state_size == NULL) + return -EINVAL; + + hwmgr->num_ps = table_entries = hwmgr->hwmgr_func->get_num_of_pp_table_entries(hwmgr); + + hwmgr->ps_size = size = hwmgr->hwmgr_func->get_power_state_size(hwmgr) + + sizeof(struct pp_power_state); + + hwmgr->ps = kzalloc(size * table_entries, GFP_KERNEL); + if (hwmgr->ps == NULL) + return -ENOMEM; + + hwmgr->request_ps = kzalloc(size, GFP_KERNEL); + if (hwmgr->request_ps == NULL) { + kfree(hwmgr->ps); + hwmgr->ps = NULL; + return -ENOMEM; + } + + hwmgr->current_ps = kzalloc(size, GFP_KERNEL); + if (hwmgr->current_ps == NULL) { + kfree(hwmgr->request_ps); + kfree(hwmgr->ps); + hwmgr->request_ps = NULL; + hwmgr->ps = NULL; + return -ENOMEM; + } + + state = hwmgr->ps; + + for (i = 0; i < table_entries; i++) { + result = hwmgr->hwmgr_func->get_pp_table_entry(hwmgr, i, state); + + if (state->classification.flags & PP_StateClassificationFlag_Boot) { + hwmgr->boot_ps = state; + memcpy(hwmgr->current_ps, state, size); + memcpy(hwmgr->request_ps, state, size); + } + + state->id = i + 1; /* assigned unique num for every power state id */ + + if (state->classification.flags & PP_StateClassificationFlag_Uvd) + hwmgr->uvd_ps = state; + state = (struct pp_power_state *)((unsigned long)state + size); + } + + return 0; +} + +int psm_fini_power_state_table(struct pp_hwmgr *hwmgr) +{ + if (hwmgr == NULL) + return -EINVAL; + + kfree(hwmgr->current_ps); + kfree(hwmgr->request_ps); + kfree(hwmgr->ps); + hwmgr->request_ps = NULL; + hwmgr->ps = NULL; + hwmgr->current_ps = NULL; + return 0; +} + +static int psm_get_ui_state(struct pp_hwmgr *hwmgr, + enum PP_StateUILabel ui_label, + unsigned long *state_id) +{ + struct pp_power_state *state; + int table_entries; + int i; + + table_entries = hwmgr->num_ps; + state = hwmgr->ps; + + for (i = 0; i < table_entries; i++) { + if (state->classification.ui_label & ui_label) { + *state_id = state->id; + return 0; + } + state = (struct pp_power_state *)((unsigned long)state + hwmgr->ps_size); + } + return -EINVAL; +} + +static int psm_get_state_by_classification(struct pp_hwmgr *hwmgr, + enum PP_StateClassificationFlag flag, + unsigned long *state_id) +{ + struct pp_power_state *state; + int table_entries; + int i; + + table_entries = hwmgr->num_ps; + state = hwmgr->ps; + + for (i = 0; i < table_entries; i++) { + if (state->classification.flags & flag) { + *state_id = state->id; + return 0; + } + state = (struct pp_power_state *)((unsigned long)state + hwmgr->ps_size); + } + return -EINVAL; +} + +static int psm_set_states(struct pp_hwmgr *hwmgr, unsigned long state_id) +{ + struct pp_power_state *state; + int table_entries; + int i; + + table_entries = hwmgr->num_ps; + + state = hwmgr->ps; + + for (i = 0; i < table_entries; i++) { + if (state->id == state_id) { + memcpy(hwmgr->request_ps, state, hwmgr->ps_size); + return 0; + } + state = (struct pp_power_state *)((unsigned long)state + hwmgr->ps_size); + } + return -EINVAL; +} + +int psm_set_boot_states(struct pp_hwmgr *hwmgr) +{ + unsigned long state_id; + int ret = -EINVAL; + + if (!psm_get_state_by_classification(hwmgr, PP_StateClassificationFlag_Boot, + &state_id)) + ret = psm_set_states(hwmgr, state_id); + + return ret; +} + +int psm_set_performance_states(struct pp_hwmgr *hwmgr) +{ + unsigned long state_id; + int ret = -EINVAL; + + if (!psm_get_ui_state(hwmgr, PP_StateUILabel_Performance, + &state_id)) + ret = psm_set_states(hwmgr, state_id); + + return ret; +} + +int psm_set_user_performance_state(struct pp_hwmgr *hwmgr, + enum PP_StateUILabel label_id, + struct pp_power_state **state) +{ + int table_entries; + int i; + + table_entries = hwmgr->num_ps; + *state = hwmgr->ps; + +restart_search: + for (i = 0; i < table_entries; i++) { + if ((*state)->classification.ui_label & label_id) + return 0; + *state = (struct pp_power_state *)((uintptr_t)*state + hwmgr->ps_size); + } + + switch (label_id) { + case PP_StateUILabel_Battery: + case PP_StateUILabel_Balanced: + label_id = PP_StateUILabel_Performance; + goto restart_search; + default: + break; + } + return -EINVAL; +} + +int psm_adjust_power_state_dynamic(struct pp_hwmgr *hwmgr, bool skip, + struct pp_power_state *new_ps) +{ + struct pp_power_state *pcurrent; + struct pp_power_state *requested; + bool equal; + + if (skip) + return 0; + + if (new_ps != NULL) + requested = new_ps; + else + requested = hwmgr->request_ps; + + pcurrent = hwmgr->current_ps; + + phm_apply_state_adjust_rules(hwmgr, requested, pcurrent); + + if (pcurrent == NULL || (0 != phm_check_states_equal(hwmgr, + &pcurrent->hardware, &requested->hardware, &equal))) + equal = false; + + if (!equal || phm_check_smc_update_required_for_display_configuration(hwmgr)) { + phm_set_power_state(hwmgr, &pcurrent->hardware, &requested->hardware); + memcpy(hwmgr->current_ps, hwmgr->request_ps, hwmgr->ps_size); + } + return 0; +} + diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventinit.h b/drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.h index 9ef96aa..fa1b682 100644 --- a/drivers/gpu/drm/amd/powerplay/eventmgr/eventinit.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.h @@ -1,5 +1,5 @@ /* - * Copyright 2015 Advanced Micro Devices, Inc. + * Copyright 2017 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"), @@ -21,14 +21,20 @@ * */ -#ifndef _EVENTINIT_H_ -#define _EVENTINIT_H_ +#ifndef PP_PSM_H +#define PP_PSM_H -#define PEM_CURRENT_POWERPLAY_FEATURE_VERSION 4 +#include "hwmgr.h" -void pem_init_feature_info(struct pp_eventmgr *eventmgr); -void pem_uninit_featureInfo(struct pp_eventmgr *eventmgr); -int pem_register_interrupts(struct pp_eventmgr *eventmgr); -int pem_unregister_interrupts(struct pp_eventmgr *eventmgr); +int psm_init_power_state_table(struct pp_hwmgr *hwmgr); +int psm_fini_power_state_table(struct pp_hwmgr *hwmgr); +int psm_set_boot_states(struct pp_hwmgr *hwmgr); +int psm_set_performance_states(struct pp_hwmgr *hwmgr); +int psm_set_user_performance_state(struct pp_hwmgr *hwmgr, + enum PP_StateUILabel label_id, + struct pp_power_state **state); +int psm_adjust_power_state_dynamic(struct pp_hwmgr *hwmgr, + bool skip, + struct pp_power_state *new_ps); -#endif /* _EVENTINIT_H_ */ +#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c index 953e0c9..a129bc5 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c @@ -470,7 +470,7 @@ uint32_t atomctrl_get_reference_clock(struct pp_hwmgr *hwmgr) * SET_VOLTAGE_TYPE_ASIC_MVDDC, SET_VOLTAGE_TYPE_ASIC_MVDDQ. * voltage_mode is one of ATOM_SET_VOLTAGE, ATOM_SET_VOLTAGE_PHASE */ -bool atomctrl_is_voltage_controled_by_gpio_v3( +bool atomctrl_is_voltage_controlled_by_gpio_v3( struct pp_hwmgr *hwmgr, uint8_t voltage_type, uint8_t voltage_mode) @@ -1100,10 +1100,10 @@ int atomctrl_get_voltage_evv(struct pp_hwmgr *hwmgr, } } - PP_ASSERT_WITH_CODE(entry_id < hwmgr->dyn_state.vddc_dependency_on_sclk->count, - "Can't find requested voltage id in vddc_dependency_on_sclk table!", + if (entry_id >= hwmgr->dyn_state.vddc_dependency_on_sclk->count) { + pr_debug("Can't find requested voltage id in vddc_dependency_on_sclk table!\n"); return -EINVAL; - ); + } get_voltage_info_param_space.ucVoltageType = VOLTAGE_TYPE_VDDC; get_voltage_info_param_space.ucVoltageMode = ATOM_GET_VOLTAGE_EVV_VOLTAGE; @@ -1418,3 +1418,83 @@ int atomctrl_get_svi2_info(struct pp_hwmgr *hwmgr, uint8_t voltage_type, return 0; } + +int atomctrl_get_leakage_id_from_efuse(struct pp_hwmgr *hwmgr, uint16_t *virtual_voltage_id) +{ + int result; + SET_VOLTAGE_PS_ALLOCATION allocation; + SET_VOLTAGE_PARAMETERS_V1_3 *voltage_parameters = + (SET_VOLTAGE_PARAMETERS_V1_3 *)&allocation.sASICSetVoltage; + + voltage_parameters->ucVoltageMode = ATOM_GET_LEAKAGE_ID; + + result = cgs_atom_exec_cmd_table(hwmgr->device, + GetIndexIntoMasterTable(COMMAND, SetVoltage), + voltage_parameters); + + *virtual_voltage_id = voltage_parameters->usVoltageLevel; + + return result; +} + +int atomctrl_get_leakage_vddc_base_on_leakage(struct pp_hwmgr *hwmgr, + uint16_t *vddc, uint16_t *vddci, + uint16_t virtual_voltage_id, + uint16_t efuse_voltage_id) +{ + int i, j; + int ix; + u16 *leakage_bin, *vddc_id_buf, *vddc_buf, *vddci_id_buf, *vddci_buf; + ATOM_ASIC_PROFILING_INFO_V2_1 *profile; + + *vddc = 0; + *vddci = 0; + + ix = GetIndexIntoMasterTable(DATA, ASIC_ProfilingInfo); + + profile = (ATOM_ASIC_PROFILING_INFO_V2_1 *) + cgs_atom_get_data_table(hwmgr->device, + ix, + NULL, NULL, NULL); + if (!profile) + return -EINVAL; + + if ((profile->asHeader.ucTableFormatRevision >= 2) && + (profile->asHeader.ucTableContentRevision >= 1) && + (profile->asHeader.usStructureSize >= sizeof(ATOM_ASIC_PROFILING_INFO_V2_1))) { + leakage_bin = (u16 *)((char *)profile + profile->usLeakageBinArrayOffset); + vddc_id_buf = (u16 *)((char *)profile + profile->usElbVDDC_IdArrayOffset); + vddc_buf = (u16 *)((char *)profile + profile->usElbVDDC_LevelArrayOffset); + if (profile->ucElbVDDC_Num > 0) { + for (i = 0; i < profile->ucElbVDDC_Num; i++) { + if (vddc_id_buf[i] == virtual_voltage_id) { + for (j = 0; j < profile->ucLeakageBinNum; j++) { + if (efuse_voltage_id <= leakage_bin[j]) { + *vddc = vddc_buf[j * profile->ucElbVDDC_Num + i]; + break; + } + } + break; + } + } + } + + vddci_id_buf = (u16 *)((char *)profile + profile->usElbVDDCI_IdArrayOffset); + vddci_buf = (u16 *)((char *)profile + profile->usElbVDDCI_LevelArrayOffset); + if (profile->ucElbVDDCI_Num > 0) { + for (i = 0; i < profile->ucElbVDDCI_Num; i++) { + if (vddci_id_buf[i] == virtual_voltage_id) { + for (j = 0; j < profile->ucLeakageBinNum; j++) { + if (efuse_voltage_id <= leakage_bin[j]) { + *vddci = vddci_buf[j * profile->ucElbVDDC_Num + i]; + break; + } + } + break; + } + } + } + } + + return 0; +} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h index e9fe2e8..c44a920 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h @@ -291,7 +291,7 @@ extern uint32_t atomctrl_get_reference_clock(struct pp_hwmgr *hwmgr); extern int atomctrl_get_memory_pll_dividers_si(struct pp_hwmgr *hwmgr, uint32_t clock_value, pp_atomctrl_memory_clock_param *mpll_param, bool strobe_mode); extern int atomctrl_get_engine_pll_dividers_vi(struct pp_hwmgr *hwmgr, uint32_t clock_value, pp_atomctrl_clock_dividers_vi *dividers); extern int atomctrl_get_dfs_pll_dividers_vi(struct pp_hwmgr *hwmgr, uint32_t clock_value, pp_atomctrl_clock_dividers_vi *dividers); -extern bool atomctrl_is_voltage_controled_by_gpio_v3(struct pp_hwmgr *hwmgr, uint8_t voltage_type, uint8_t voltage_mode); +extern bool atomctrl_is_voltage_controlled_by_gpio_v3(struct pp_hwmgr *hwmgr, uint8_t voltage_type, uint8_t voltage_mode); extern int atomctrl_get_voltage_table_v3(struct pp_hwmgr *hwmgr, uint8_t voltage_type, uint8_t voltage_mode, pp_atomctrl_voltage_table *voltage_table); extern int atomctrl_get_memory_pll_dividers_vi(struct pp_hwmgr *hwmgr, uint32_t clock_value, pp_atomctrl_memory_clock_param *mpll_param); @@ -314,5 +314,11 @@ extern int atomctrl_get_avfs_information(struct pp_hwmgr *hwmgr, struct pp_atom_ extern int atomctrl_get_svi2_info(struct pp_hwmgr *hwmgr, uint8_t voltage_type, uint8_t *svd_gpio_id, uint8_t *svc_gpio_id, uint16_t *load_line); + +extern int atomctrl_get_leakage_vddc_base_on_leakage(struct pp_hwmgr *hwmgr, + uint16_t *vddc, uint16_t *vddci, + uint16_t virtual_voltage_id, + uint16_t efuse_voltage_id); +extern int atomctrl_get_leakage_id_from_efuse(struct pp_hwmgr *hwmgr, uint16_t *virtual_voltage_id); #endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c b/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c index 84f01fd3..d1af148 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c @@ -173,8 +173,6 @@ static int get_vddc_lookup_table( if (NULL == table) return -ENOMEM; - memset(table, 0x00, table_size); - table->count = vddc_lookup_pp_tables->ucNumEntries; for (i = 0; i < vddc_lookup_pp_tables->ucNumEntries; i++) { @@ -335,8 +333,6 @@ static int get_valid_clk( if (NULL == table) return -ENOMEM; - memset(table, 0x00, table_size); - table->count = (uint32_t)clk_volt_pp_table->count; for (i = 0; i < table->count; i++) { @@ -390,8 +386,6 @@ static int get_mclk_voltage_dependency_table( if (NULL == mclk_table) return -ENOMEM; - memset(mclk_table, 0x00, table_size); - mclk_table->count = (uint32_t)mclk_dep_table->ucNumEntries; for (i = 0; i < mclk_dep_table->ucNumEntries; i++) { @@ -439,8 +433,6 @@ static int get_sclk_voltage_dependency_table( if (NULL == sclk_table) return -ENOMEM; - memset(sclk_table, 0x00, table_size); - sclk_table->count = (uint32_t)tonga_table->ucNumEntries; for (i = 0; i < tonga_table->ucNumEntries; i++) { @@ -473,8 +465,6 @@ static int get_sclk_voltage_dependency_table( if (NULL == sclk_table) return -ENOMEM; - memset(sclk_table, 0x00, table_size); - sclk_table->count = (uint32_t)polaris_table->ucNumEntries; for (i = 0; i < polaris_table->ucNumEntries; i++) { @@ -525,8 +515,6 @@ static int get_pcie_table( if (pcie_table == NULL) return -ENOMEM; - memset(pcie_table, 0x00, table_size); - /* * Make sure the number of pcie entries are less than or equal to sclk dpm levels. * Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1. @@ -567,8 +555,6 @@ static int get_pcie_table( if (pcie_table == NULL) return -ENOMEM; - memset(pcie_table, 0x00, table_size); - /* * Make sure the number of pcie entries are less than or equal to sclk dpm levels. * Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1. @@ -615,8 +601,6 @@ static int get_cac_tdp_table( if (NULL == tdp_table) return -ENOMEM; - memset(tdp_table, 0x00, table_size); - hwmgr->dyn_state.cac_dtp_table = kzalloc(table_size, GFP_KERNEL); if (NULL == hwmgr->dyn_state.cac_dtp_table) { @@ -624,8 +608,6 @@ static int get_cac_tdp_table( return -ENOMEM; } - memset(hwmgr->dyn_state.cac_dtp_table, 0x00, table_size); - if (table->ucRevId < 3) { const ATOM_Tonga_PowerTune_Table *tonga_table = (ATOM_Tonga_PowerTune_Table *)table; @@ -725,8 +707,6 @@ static int get_mm_clock_voltage_table( if (NULL == mm_table) return -ENOMEM; - memset(mm_table, 0x00, table_size); - mm_table->count = mm_dependency_table->ucNumEntries; for (i = 0; i < mm_dependency_table->ucNumEntries; i++) { diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c index 2716721..485f7eb 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c @@ -24,7 +24,7 @@ #include <linux/types.h> #include <linux/kernel.h> #include <linux/slab.h> - +#include <drm/amdgpu_drm.h> #include "processpptables.h" #include <atom-types.h> #include <atombios.h> @@ -790,6 +790,39 @@ static const ATOM_PPLIB_STATE_V2 *get_state_entry_v2( return pstate; } +static unsigned char soft_dummy_pp_table[] = { + 0xe1, 0x01, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x4a, 0x00, 0x6c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x42, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x4e, 0x00, 0x88, 0x00, 0x00, 0x9e, 0x00, 0x17, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x18, 0x05, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x8e, 0x01, 0x00, 0x00, 0xb8, 0x01, 0x00, 0x00, 0x08, 0x30, 0x75, 0x00, 0x80, 0x00, 0xa0, 0x8c, + 0x00, 0x7e, 0x00, 0x71, 0xa5, 0x00, 0x7c, 0x00, 0xe5, 0xc8, 0x00, 0x70, 0x00, 0x91, 0xf4, 0x00, + 0x64, 0x00, 0x40, 0x19, 0x01, 0x5a, 0x00, 0x0e, 0x28, 0x01, 0x52, 0x00, 0x80, 0x38, 0x01, 0x4a, + 0x00, 0x00, 0x09, 0x30, 0x75, 0x00, 0x30, 0x75, 0x00, 0x40, 0x9c, 0x00, 0x40, 0x9c, 0x00, 0x59, + 0xd8, 0x00, 0x59, 0xd8, 0x00, 0x91, 0xf4, 0x00, 0x91, 0xf4, 0x00, 0x0e, 0x28, 0x01, 0x0e, 0x28, + 0x01, 0x90, 0x5f, 0x01, 0x90, 0x5f, 0x01, 0x00, 0x77, 0x01, 0x00, 0x77, 0x01, 0xca, 0x91, 0x01, + 0xca, 0x91, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x7e, 0x00, 0x01, + 0x7c, 0x00, 0x02, 0x70, 0x00, 0x03, 0x64, 0x00, 0x04, 0x5a, 0x00, 0x05, 0x52, 0x00, 0x06, 0x4a, + 0x00, 0x07, 0x08, 0x08, 0x00, 0x08, 0x00, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x03, + 0x02, 0x04, 0x02, 0x00, 0x08, 0x40, 0x9c, 0x00, 0x30, 0x75, 0x00, 0x74, 0xb5, 0x00, 0xa0, 0x8c, + 0x00, 0x60, 0xea, 0x00, 0x74, 0xb5, 0x00, 0x0e, 0x28, 0x01, 0x60, 0xea, 0x00, 0x90, 0x5f, 0x01, + 0x40, 0x19, 0x01, 0xb2, 0xb0, 0x01, 0x90, 0x5f, 0x01, 0xc0, 0xd4, 0x01, 0x00, 0x77, 0x01, 0x5e, + 0xff, 0x01, 0xca, 0x91, 0x01, 0x08, 0x80, 0x00, 0x00, 0x7e, 0x00, 0x01, 0x7c, 0x00, 0x02, 0x70, + 0x00, 0x03, 0x64, 0x00, 0x04, 0x5a, 0x00, 0x05, 0x52, 0x00, 0x06, 0x4a, 0x00, 0x07, 0x00, 0x08, + 0x80, 0x00, 0x30, 0x75, 0x00, 0x7e, 0x00, 0x40, 0x9c, 0x00, 0x7c, 0x00, 0x59, 0xd8, 0x00, 0x70, + 0x00, 0xdc, 0x0b, 0x01, 0x64, 0x00, 0x80, 0x38, 0x01, 0x5a, 0x00, 0x80, 0x38, 0x01, 0x52, 0x00, + 0x80, 0x38, 0x01, 0x4a, 0x00, 0x80, 0x38, 0x01, 0x08, 0x30, 0x75, 0x00, 0x80, 0x00, 0xa0, 0x8c, + 0x00, 0x7e, 0x00, 0x71, 0xa5, 0x00, 0x7c, 0x00, 0xe5, 0xc8, 0x00, 0x74, 0x00, 0x91, 0xf4, 0x00, + 0x66, 0x00, 0x40, 0x19, 0x01, 0x58, 0x00, 0x0e, 0x28, 0x01, 0x52, 0x00, 0x80, 0x38, 0x01, 0x4a, + 0x00 +}; static const ATOM_PPLIB_POWERPLAYTABLE *get_powerplay_table( struct pp_hwmgr *hwmgr) @@ -799,12 +832,17 @@ static const ATOM_PPLIB_POWERPLAYTABLE *get_powerplay_table( uint16_t size; if (!table_addr) { - table_addr = cgs_atom_get_data_table(hwmgr->device, - GetIndexIntoMasterTable(DATA, PowerPlayInfo), - &size, &frev, &crev); - - hwmgr->soft_pp_table = table_addr; - hwmgr->soft_pp_table_size = size; + if (hwmgr->chip_id == CHIP_RAVEN) { + table_addr = &soft_dummy_pp_table[0]; + hwmgr->soft_pp_table = &soft_dummy_pp_table[0]; + hwmgr->soft_pp_table_size = sizeof(soft_dummy_pp_table); + } else { + table_addr = cgs_atom_get_data_table(hwmgr->device, + GetIndexIntoMasterTable(DATA, PowerPlayInfo), + &size, &frev, &crev); + hwmgr->soft_pp_table = table_addr; + hwmgr->soft_pp_table_size = size; + } } return (const ATOM_PPLIB_POWERPLAYTABLE *)table_addr; @@ -924,15 +962,14 @@ int pp_tables_get_entry(struct pp_hwmgr *hwmgr, } } - if ((0 == result) && - (0 != (ps->classification.flags & PP_StateClassificationFlag_Boot))) - result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(ps->hardware)); + if ((0 == result) && (0 != (ps->classification.flags & PP_StateClassificationFlag_Boot))) { + if (hwmgr->chip_family < AMDGPU_FAMILY_RV) + result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(ps->hardware)); + } return result; } - - static int init_powerplay_tables( struct pp_hwmgr *hwmgr, const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table @@ -1615,85 +1652,53 @@ static int pp_tables_uninitialize(struct pp_hwmgr *hwmgr) if (hwmgr->chip_id == CHIP_RAVEN) return 0; - if (NULL != hwmgr->dyn_state.vddc_dependency_on_sclk) { - kfree(hwmgr->dyn_state.vddc_dependency_on_sclk); - hwmgr->dyn_state.vddc_dependency_on_sclk = NULL; - } + kfree(hwmgr->dyn_state.vddc_dependency_on_sclk); + hwmgr->dyn_state.vddc_dependency_on_sclk = NULL; - if (NULL != hwmgr->dyn_state.vddci_dependency_on_mclk) { - kfree(hwmgr->dyn_state.vddci_dependency_on_mclk); - hwmgr->dyn_state.vddci_dependency_on_mclk = NULL; - } + kfree(hwmgr->dyn_state.vddci_dependency_on_mclk); + hwmgr->dyn_state.vddci_dependency_on_mclk = NULL; - if (NULL != hwmgr->dyn_state.vddc_dependency_on_mclk) { - kfree(hwmgr->dyn_state.vddc_dependency_on_mclk); - hwmgr->dyn_state.vddc_dependency_on_mclk = NULL; - } + kfree(hwmgr->dyn_state.vddc_dependency_on_mclk); + hwmgr->dyn_state.vddc_dependency_on_mclk = NULL; - if (NULL != hwmgr->dyn_state.mvdd_dependency_on_mclk) { - kfree(hwmgr->dyn_state.mvdd_dependency_on_mclk); - hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL; - } + kfree(hwmgr->dyn_state.mvdd_dependency_on_mclk); + hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL; - if (NULL != hwmgr->dyn_state.valid_mclk_values) { - kfree(hwmgr->dyn_state.valid_mclk_values); - hwmgr->dyn_state.valid_mclk_values = NULL; - } + kfree(hwmgr->dyn_state.valid_mclk_values); + hwmgr->dyn_state.valid_mclk_values = NULL; - if (NULL != hwmgr->dyn_state.valid_sclk_values) { - kfree(hwmgr->dyn_state.valid_sclk_values); - hwmgr->dyn_state.valid_sclk_values = NULL; - } + kfree(hwmgr->dyn_state.valid_sclk_values); + hwmgr->dyn_state.valid_sclk_values = NULL; - if (NULL != hwmgr->dyn_state.cac_leakage_table) { - kfree(hwmgr->dyn_state.cac_leakage_table); - hwmgr->dyn_state.cac_leakage_table = NULL; - } + kfree(hwmgr->dyn_state.cac_leakage_table); + hwmgr->dyn_state.cac_leakage_table = NULL; - if (NULL != hwmgr->dyn_state.vddc_phase_shed_limits_table) { - kfree(hwmgr->dyn_state.vddc_phase_shed_limits_table); - hwmgr->dyn_state.vddc_phase_shed_limits_table = NULL; - } + kfree(hwmgr->dyn_state.vddc_phase_shed_limits_table); + hwmgr->dyn_state.vddc_phase_shed_limits_table = NULL; - if (NULL != hwmgr->dyn_state.vce_clock_voltage_dependency_table) { - kfree(hwmgr->dyn_state.vce_clock_voltage_dependency_table); - hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL; - } + kfree(hwmgr->dyn_state.vce_clock_voltage_dependency_table); + hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL; - if (NULL != hwmgr->dyn_state.uvd_clock_voltage_dependency_table) { - kfree(hwmgr->dyn_state.uvd_clock_voltage_dependency_table); - hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL; - } + kfree(hwmgr->dyn_state.uvd_clock_voltage_dependency_table); + hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL; - if (NULL != hwmgr->dyn_state.samu_clock_voltage_dependency_table) { - kfree(hwmgr->dyn_state.samu_clock_voltage_dependency_table); - hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL; - } + kfree(hwmgr->dyn_state.samu_clock_voltage_dependency_table); + hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL; - if (NULL != hwmgr->dyn_state.acp_clock_voltage_dependency_table) { - kfree(hwmgr->dyn_state.acp_clock_voltage_dependency_table); - hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL; - } + kfree(hwmgr->dyn_state.acp_clock_voltage_dependency_table); + hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL; - if (NULL != hwmgr->dyn_state.cac_dtp_table) { - kfree(hwmgr->dyn_state.cac_dtp_table); - hwmgr->dyn_state.cac_dtp_table = NULL; - } + kfree(hwmgr->dyn_state.cac_dtp_table); + hwmgr->dyn_state.cac_dtp_table = NULL; - if (NULL != hwmgr->dyn_state.ppm_parameter_table) { - kfree(hwmgr->dyn_state.ppm_parameter_table); - hwmgr->dyn_state.ppm_parameter_table = NULL; - } + kfree(hwmgr->dyn_state.ppm_parameter_table); + hwmgr->dyn_state.ppm_parameter_table = NULL; - if (NULL != hwmgr->dyn_state.vdd_gfx_dependency_on_sclk) { - kfree(hwmgr->dyn_state.vdd_gfx_dependency_on_sclk); - hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL; - } + kfree(hwmgr->dyn_state.vdd_gfx_dependency_on_sclk); + hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL; - if (NULL != hwmgr->dyn_state.vq_budgeting_table) { - kfree(hwmgr->dyn_state.vq_budgeting_table); - hwmgr->dyn_state.vq_budgeting_table = NULL; - } + kfree(hwmgr->dyn_state.vq_budgeting_table); + hwmgr->dyn_state.vq_budgeting_table = NULL; return 0; } diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/rv_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/rv_hwmgr.c index 2c3e6ba..9186b07 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/rv_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/rv_hwmgr.c @@ -38,20 +38,17 @@ #include "pp_soc15.h" #define RAVEN_MAX_DEEPSLEEP_DIVIDER_ID 5 -#define RAVEN_MINIMUM_ENGINE_CLOCK 800 //8Mhz, the low boundary of engine clock allowed on this chip +#define RAVEN_MINIMUM_ENGINE_CLOCK 800 /* 8Mhz, the low boundary of engine clock allowed on this chip */ #define SCLK_MIN_DIV_INTV_SHIFT 12 -#define RAVEN_DISPCLK_BYPASS_THRESHOLD 10000 //100mhz +#define RAVEN_DISPCLK_BYPASS_THRESHOLD 10000 /* 100Mhz */ #define SMC_RAM_END 0x40000 static const unsigned long PhwRaven_Magic = (unsigned long) PHM_Rv_Magic; + + int rv_display_clock_voltage_request(struct pp_hwmgr *hwmgr, struct pp_display_clock_request *clock_req); -struct phm_vq_budgeting_record rv_vqtable[] = { - /* _TBD - * CUs, SSP low, SSP High, Min Sclk Low, Min Sclk, High, AWD/non-AWD, DCLK, ECLK, Sustainable Sclk, Sustainable CUs */ - { 8, 0, 45, 0, 0, VQ_DisplayConfig_NoneAWD, 80000, 120000, 4, 0 }, -}; static struct rv_power_state *cast_rv_ps(struct pp_hw_power_state *hw_ps) { @@ -70,101 +67,27 @@ static const struct rv_power_state *cast_const_rv_ps( return (struct rv_power_state *)hw_ps; } -static int rv_init_vq_budget_table(struct pp_hwmgr *hwmgr) -{ - uint32_t table_size, i; - struct phm_vq_budgeting_table *ptable; - uint32_t num_entries = ARRAY_SIZE(rv_vqtable); - - if (hwmgr->dyn_state.vq_budgeting_table != NULL) - return 0; - - table_size = sizeof(struct phm_vq_budgeting_table) + - sizeof(struct phm_vq_budgeting_record) * (num_entries - 1); - - ptable = kzalloc(table_size, GFP_KERNEL); - if (NULL == ptable) - return -ENOMEM; - - ptable->numEntries = (uint8_t) num_entries; - - for (i = 0; i < ptable->numEntries; i++) { - ptable->entries[i].ulCUs = rv_vqtable[i].ulCUs; - ptable->entries[i].ulSustainableSOCPowerLimitLow = rv_vqtable[i].ulSustainableSOCPowerLimitLow; - ptable->entries[i].ulSustainableSOCPowerLimitHigh = rv_vqtable[i].ulSustainableSOCPowerLimitHigh; - ptable->entries[i].ulMinSclkLow = rv_vqtable[i].ulMinSclkLow; - ptable->entries[i].ulMinSclkHigh = rv_vqtable[i].ulMinSclkHigh; - ptable->entries[i].ucDispConfig = rv_vqtable[i].ucDispConfig; - ptable->entries[i].ulDClk = rv_vqtable[i].ulDClk; - ptable->entries[i].ulEClk = rv_vqtable[i].ulEClk; - ptable->entries[i].ulSustainableSclk = rv_vqtable[i].ulSustainableSclk; - ptable->entries[i].ulSustainableCUs = rv_vqtable[i].ulSustainableCUs; - } - - hwmgr->dyn_state.vq_budgeting_table = ptable; - - return 0; -} - static int rv_initialize_dpm_defaults(struct pp_hwmgr *hwmgr) { struct rv_hwmgr *rv_hwmgr = (struct rv_hwmgr *)(hwmgr->backend); - struct cgs_system_info sys_info = {0}; - int result; - rv_hwmgr->ddi_power_gating_disabled = 0; - rv_hwmgr->bapm_enabled = 1; rv_hwmgr->dce_slow_sclk_threshold = 30000; - rv_hwmgr->disable_driver_thermal_policy = 1; rv_hwmgr->thermal_auto_throttling_treshold = 0; rv_hwmgr->is_nb_dpm_enabled = 1; rv_hwmgr->dpm_flags = 1; - rv_hwmgr->disable_smu_acp_s3_handshake = 1; - rv_hwmgr->disable_notify_smu_vpu_recovery = 0; rv_hwmgr->gfx_off_controled_by_driver = false; - - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DynamicM3Arbiter); - - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_UVDPowerGating); - - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_UVDDynamicPowerGating); - - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_VCEPowerGating); - - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SamuPowerGating); - - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ACP); + rv_hwmgr->need_min_deep_sleep_dcefclk = true; + rv_hwmgr->num_active_display = 0; + rv_hwmgr->deep_sleep_dcefclk = 0; phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep); phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_GFXDynamicMGPowerGating); - - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkThrottleLowNotification); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DisableVoltageIsland); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DynamicUVDState); - - sys_info.size = sizeof(struct cgs_system_info); - sys_info.info_id = CGS_SYSTEM_INFO_PG_FLAGS; - result = cgs_query_system_info(hwmgr->device, &sys_info); - if (!result) { - if (sys_info.value & AMD_PG_SUPPORT_GFX_DMG) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_GFXDynamicMGPowerGating); - } - + PHM_PlatformCaps_PowerPlaySupport); return 0; } @@ -234,102 +157,88 @@ static int rv_construct_boot_state(struct pp_hwmgr *hwmgr) return 0; } -static int rv_tf_set_clock_limit(struct pp_hwmgr *hwmgr, void *input, - void *output, void *storage, int result) +static int rv_set_clock_limit(struct pp_hwmgr *hwmgr, const void *input) { struct rv_hwmgr *rv_data = (struct rv_hwmgr *)(hwmgr->backend); struct PP_Clocks clocks = {0}; struct pp_display_clock_request clock_req; clocks.dcefClock = hwmgr->display_config.min_dcef_set_clk; - clocks.dcefClockInSR = hwmgr->display_config.min_dcef_deep_sleep_set_clk; clock_req.clock_type = amd_pp_dcf_clock; clock_req.clock_freq_in_khz = clocks.dcefClock * 10; - if (clocks.dcefClock == 0 && clocks.dcefClockInSR == 0) - clock_req.clock_freq_in_khz = rv_data->dcf_actual_hard_min_freq; - PP_ASSERT_WITH_CODE(!rv_display_clock_voltage_request(hwmgr, &clock_req), "Attempt to set DCF Clock Failed!", return -EINVAL); - if(rv_data->need_min_deep_sleep_dcefclk && 0 != clocks.dcefClockInSR) - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, - PPSMC_MSG_SetMinDeepSleepDcefclk, - clocks.dcefClockInSR / 100); - /* - if(!rv_data->isp_tileA_power_gated || !rv_data->isp_tileB_power_gated) { - if ((hwmgr->ispArbiter.iclk != 0) && (rv_data->ISPActualHardMinFreq != (hwmgr->ispArbiter.iclk / 100) )) { - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, - PPSMC_MSG_SetHardMinIspclkByFreq, hwmgr->ispArbiter.iclk / 100); - rv_read_arg_from_smc(hwmgr->smumgr, &rv_data->ISPActualHardMinFreq), - } - } */ - if (((hwmgr->uvd_arbiter.vclk_soft_min / 100) != rv_data->vclk_soft_min) || ((hwmgr->uvd_arbiter.dclk_soft_min / 100) != rv_data->dclk_soft_min)) { rv_data->vclk_soft_min = hwmgr->uvd_arbiter.vclk_soft_min / 100; rv_data->dclk_soft_min = hwmgr->uvd_arbiter.dclk_soft_min / 100; - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetSoftMinVcn, (rv_data->vclk_soft_min << 16) | rv_data->vclk_soft_min); } if((hwmgr->gfx_arbiter.sclk_hard_min != 0) && ((hwmgr->gfx_arbiter.sclk_hard_min / 100) != rv_data->soc_actual_hard_min_freq)) { - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetHardMinSocclkByFreq, hwmgr->gfx_arbiter.sclk_hard_min / 100); - rv_read_arg_from_smc(hwmgr->smumgr, &rv_data->soc_actual_hard_min_freq); + rv_read_arg_from_smc(hwmgr, &rv_data->soc_actual_hard_min_freq); } if ((hwmgr->gfx_arbiter.gfxclk != 0) && (rv_data->gfx_actual_soft_min_freq != (hwmgr->gfx_arbiter.gfxclk))) { - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetMinVideoGfxclkFreq, hwmgr->gfx_arbiter.gfxclk / 100); - rv_read_arg_from_smc(hwmgr->smumgr, &rv_data->gfx_actual_soft_min_freq); + rv_read_arg_from_smc(hwmgr, &rv_data->gfx_actual_soft_min_freq); } if ((hwmgr->gfx_arbiter.fclk != 0) && (rv_data->fabric_actual_soft_min_freq != (hwmgr->gfx_arbiter.fclk / 100))) { - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetMinVideoFclkFreq, hwmgr->gfx_arbiter.fclk / 100); - rv_read_arg_from_smc(hwmgr->smumgr, &rv_data->fabric_actual_soft_min_freq); + rv_read_arg_from_smc(hwmgr, &rv_data->fabric_actual_soft_min_freq); } return 0; } -static int rv_tf_set_num_active_display(struct pp_hwmgr *hwmgr, void *input, - void *output, void *storage, int result) +static int rv_set_deep_sleep_dcefclk(struct pp_hwmgr *hwmgr, uint32_t clock) { - uint32_t num_of_active_displays = 0; - struct cgs_display_info info = {0}; + struct rv_hwmgr *rv_data = (struct rv_hwmgr *)(hwmgr->backend); - cgs_get_active_displays_info(hwmgr->device, &info); - num_of_active_displays = info.display_count; + if (rv_data->need_min_deep_sleep_dcefclk && rv_data->deep_sleep_dcefclk != clock/100) { + rv_data->deep_sleep_dcefclk = clock/100; + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetMinDeepSleepDcefclk, + rv_data->deep_sleep_dcefclk); + } + return 0; +} - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, +static int rv_set_active_display_count(struct pp_hwmgr *hwmgr, uint32_t count) +{ + struct rv_hwmgr *rv_data = (struct rv_hwmgr *)(hwmgr->backend); + + if (rv_data->num_active_display != count) { + rv_data->num_active_display = count; + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetDisplayCount, - num_of_active_displays); + rv_data->num_active_display); + } + return 0; } -static const struct phm_master_table_item rv_set_power_state_list[] = { - { .tableFunction = rv_tf_set_clock_limit }, - { .tableFunction = rv_tf_set_num_active_display }, - { } -}; - -static const struct phm_master_table_header rv_set_power_state_master = { - 0, - PHM_MasterTableFlag_None, - rv_set_power_state_list -}; +static int rv_set_power_state_tasks(struct pp_hwmgr *hwmgr, const void *input) +{ + return rv_set_clock_limit(hwmgr, input); +} -static int rv_tf_init_power_gate_state(struct pp_hwmgr *hwmgr, void *input, - void *output, void *storage, int result) +static int rv_init_power_gate_state(struct pp_hwmgr *hwmgr) { struct rv_hwmgr *rv_data = (struct rv_hwmgr *)(hwmgr->backend); @@ -340,20 +249,13 @@ static int rv_tf_init_power_gate_state(struct pp_hwmgr *hwmgr, void *input, return 0; } -static const struct phm_master_table_item rv_setup_asic_list[] = { - { .tableFunction = rv_tf_init_power_gate_state }, - { } -}; -static const struct phm_master_table_header rv_setup_asic_master = { - 0, - PHM_MasterTableFlag_None, - rv_setup_asic_list -}; +static int rv_setup_asic_task(struct pp_hwmgr *hwmgr) +{ + return rv_init_power_gate_state(hwmgr); +} -static int rv_tf_reset_cc6_data(struct pp_hwmgr *hwmgr, - void *input, void *output, - void *storage, int result) +static int rv_reset_cc6_data(struct pp_hwmgr *hwmgr) { struct rv_hwmgr *rv_data = (struct rv_hwmgr *)(hwmgr->backend); @@ -365,66 +267,42 @@ static int rv_tf_reset_cc6_data(struct pp_hwmgr *hwmgr, return 0; } -static const struct phm_master_table_item rv_power_down_asic_list[] = { - { .tableFunction = rv_tf_reset_cc6_data }, - { } -}; - -static const struct phm_master_table_header rv_power_down_asic_master = { - 0, - PHM_MasterTableFlag_None, - rv_power_down_asic_list -}; - +static int rv_power_off_asic(struct pp_hwmgr *hwmgr) +{ + return rv_reset_cc6_data(hwmgr); +} -static int rv_tf_disable_gfx_off(struct pp_hwmgr *hwmgr, - void *input, void *output, - void *storage, int result) +static int rv_disable_gfx_off(struct pp_hwmgr *hwmgr) { struct rv_hwmgr *rv_data = (struct rv_hwmgr *)(hwmgr->backend); if (rv_data->gfx_off_controled_by_driver) - smum_send_msg_to_smc(hwmgr->smumgr, + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisableGfxOff); return 0; } -static const struct phm_master_table_item rv_disable_dpm_list[] = { - { .tableFunction = rv_tf_disable_gfx_off }, - { }, -}; - - -static const struct phm_master_table_header rv_disable_dpm_master = { - 0, - PHM_MasterTableFlag_None, - rv_disable_dpm_list -}; +static int rv_disable_dpm_tasks(struct pp_hwmgr *hwmgr) +{ + return rv_disable_gfx_off(hwmgr); +} -static int rv_tf_enable_gfx_off(struct pp_hwmgr *hwmgr, - void *input, void *output, - void *storage, int result) +static int rv_enable_gfx_off(struct pp_hwmgr *hwmgr) { struct rv_hwmgr *rv_data = (struct rv_hwmgr *)(hwmgr->backend); if (rv_data->gfx_off_controled_by_driver) - smum_send_msg_to_smc(hwmgr->smumgr, + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableGfxOff); return 0; } -static const struct phm_master_table_item rv_enable_dpm_list[] = { - { .tableFunction = rv_tf_enable_gfx_off }, - { }, -}; - -static const struct phm_master_table_header rv_enable_dpm_master = { - 0, - PHM_MasterTableFlag_None, - rv_enable_dpm_list -}; +static int rv_enable_dpm_tasks(struct pp_hwmgr *hwmgr) +{ + return rv_enable_gfx_off(hwmgr); +} static int rv_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, struct pp_power_state *prequest_ps, @@ -505,7 +383,7 @@ static int rv_populate_clock_table(struct pp_hwmgr *hwmgr) DpmClocks_t *table = &(rv_data->clock_table); struct rv_clock_voltage_information *pinfo = &(rv_data->clock_vol_info); - result = rv_copy_table_from_smc(hwmgr->smumgr, (uint8_t *)table, CLOCKTABLE); + result = rv_copy_table_from_smc(hwmgr, (uint8_t *)table, CLOCKTABLE); PP_ASSERT_WITH_CODE((0 == result), "Attempt to copy clock table from smc failed", @@ -563,9 +441,6 @@ static int rv_hwmgr_backend_init(struct pp_hwmgr *hwmgr) return result; } - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerPlaySupport); - rv_populate_clock_table(hwmgr); result = rv_get_system_info_data(hwmgr); @@ -576,40 +451,6 @@ static int rv_hwmgr_backend_init(struct pp_hwmgr *hwmgr) rv_construct_boot_state(hwmgr); - result = phm_construct_table(hwmgr, &rv_setup_asic_master, - &(hwmgr->setup_asic)); - if (result != 0) { - pr_err("Fail to construct setup ASIC\n"); - return result; - } - - result = phm_construct_table(hwmgr, &rv_power_down_asic_master, - &(hwmgr->power_down_asic)); - if (result != 0) { - pr_err("Fail to construct power down ASIC\n"); - return result; - } - - result = phm_construct_table(hwmgr, &rv_set_power_state_master, - &(hwmgr->set_power_state)); - if (result != 0) { - pr_err("Fail to construct set_power_state\n"); - return result; - } - - result = phm_construct_table(hwmgr, &rv_disable_dpm_master, - &(hwmgr->disable_dynamic_state_management)); - if (result != 0) { - pr_err("Fail to disable_dynamic_state\n"); - return result; - } - result = phm_construct_table(hwmgr, &rv_enable_dpm_master, - &(hwmgr->enable_dynamic_state_management)); - if (result != 0) { - pr_err("Fail to enable_dynamic_state\n"); - return result; - } - hwmgr->platform_descriptor.hardwareActivityPerformanceLevels = RAVEN_MAX_HARDWARE_POWERLEVELS; @@ -624,8 +465,6 @@ static int rv_hwmgr_backend_init(struct pp_hwmgr *hwmgr) hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50; - rv_init_vq_budget_table(hwmgr); - return result; } @@ -634,46 +473,21 @@ static int rv_hwmgr_backend_fini(struct pp_hwmgr *hwmgr) struct rv_hwmgr *rv_data = (struct rv_hwmgr *)(hwmgr->backend); struct rv_clock_voltage_information *pinfo = &(rv_data->clock_vol_info); - phm_destroy_table(hwmgr, &(hwmgr->set_power_state)); - phm_destroy_table(hwmgr, &(hwmgr->enable_dynamic_state_management)); - phm_destroy_table(hwmgr, &(hwmgr->disable_dynamic_state_management)); - phm_destroy_table(hwmgr, &(hwmgr->power_down_asic)); - phm_destroy_table(hwmgr, &(hwmgr->setup_asic)); - - if (pinfo->vdd_dep_on_dcefclk) { - kfree(pinfo->vdd_dep_on_dcefclk); - pinfo->vdd_dep_on_dcefclk = NULL; - } - if (pinfo->vdd_dep_on_socclk) { - kfree(pinfo->vdd_dep_on_socclk); - pinfo->vdd_dep_on_socclk = NULL; - } - if (pinfo->vdd_dep_on_fclk) { - kfree(pinfo->vdd_dep_on_fclk); - pinfo->vdd_dep_on_fclk = NULL; - } - if (pinfo->vdd_dep_on_dispclk) { - kfree(pinfo->vdd_dep_on_dispclk); - pinfo->vdd_dep_on_dispclk = NULL; - } - if (pinfo->vdd_dep_on_dppclk) { - kfree(pinfo->vdd_dep_on_dppclk); - pinfo->vdd_dep_on_dppclk = NULL; - } - if (pinfo->vdd_dep_on_phyclk) { - kfree(pinfo->vdd_dep_on_phyclk); - pinfo->vdd_dep_on_phyclk = NULL; - } - - if (NULL != hwmgr->dyn_state.vddc_dep_on_dal_pwrl) { - kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl); - hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL; - } - - if (NULL != hwmgr->dyn_state.vq_budgeting_table) { - kfree(hwmgr->dyn_state.vq_budgeting_table); - hwmgr->dyn_state.vq_budgeting_table = NULL; - } + kfree(pinfo->vdd_dep_on_dcefclk); + pinfo->vdd_dep_on_dcefclk = NULL; + kfree(pinfo->vdd_dep_on_socclk); + pinfo->vdd_dep_on_socclk = NULL; + kfree(pinfo->vdd_dep_on_fclk); + pinfo->vdd_dep_on_fclk = NULL; + kfree(pinfo->vdd_dep_on_dispclk); + pinfo->vdd_dep_on_dispclk = NULL; + kfree(pinfo->vdd_dep_on_dppclk); + pinfo->vdd_dep_on_dppclk = NULL; + kfree(pinfo->vdd_dep_on_phyclk); + pinfo->vdd_dep_on_phyclk = NULL; + + kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl); + hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL; kfree(hwmgr->backend); hwmgr->backend = NULL; @@ -687,12 +501,12 @@ static int rv_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, return 0; } -static int rv_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) +static uint32_t rv_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) { return 0; } -static int rv_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low) +static uint32_t rv_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low) { return 0; } @@ -711,18 +525,9 @@ static int rv_dpm_get_pp_table_entry_callback( { struct rv_power_state *rv_ps = cast_rv_ps(hw_ps); - const ATOM_PPLIB_CZ_CLOCK_INFO *rv_clock_info = clock_info; - - struct phm_clock_voltage_dependency_table *table = - hwmgr->dyn_state.vddc_dependency_on_sclk; - uint8_t clock_info_index = rv_clock_info->index; - - if (clock_info_index > (uint8_t)(hwmgr->platform_descriptor.hardwareActivityPerformanceLevels - 1)) - clock_info_index = (uint8_t)(hwmgr->platform_descriptor.hardwareActivityPerformanceLevels - 1); - - rv_ps->levels[index].engine_clock = table->entries[clock_info_index].clk; - rv_ps->levels[index].vddc_index = (uint8_t)table->entries[clock_info_index].v; + rv_ps->levels[index].engine_clock = 0; + rv_ps->levels[index].vddc_index = 0; rv_ps->level = index + 1; if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) { @@ -814,12 +619,12 @@ static int rv_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_p ps = cast_const_rv_ps(state); level_index = index > ps->level - 1 ? ps->level - 1 : index; - level->coreClock = ps->levels[level_index].engine_clock; + level->coreClock = 30000; if (designation == PHM_PerformanceLevelDesignation_PowerContainment) { for (i = 1; i < ps->level; i++) { if (ps->levels[i].engine_clock > data->dce_slow_sclk_threshold) { - level->coreClock = ps->levels[i].engine_clock; + level->coreClock = 30000; break; } } @@ -829,8 +634,9 @@ static int rv_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_p vol_dep_record_index = data->clock_vol_info.vdd_dep_on_fclk->count - 1; level->memory_clock = data->clock_vol_info.vdd_dep_on_fclk->entries[vol_dep_record_index].clk; - } else + } else { level->memory_clock = data->clock_vol_info.vdd_dep_on_fclk->entries[0].clk; + } level->nonLocalMemoryFreq = 0; level->nonLocalMemoryWidth = 0; @@ -993,7 +799,7 @@ int rv_display_clock_voltage_request(struct pp_hwmgr *hwmgr, return -EINVAL; } - result = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, + result = smum_send_msg_to_smc_with_parameter(hwmgr, msg, clk_freq); return result; @@ -1001,7 +807,8 @@ int rv_display_clock_voltage_request(struct pp_hwmgr *hwmgr, static int rv_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_info *clocks) { - return -EINVAL; + clocks->engine_max_clock = 80000; /* driver can't get engine clock, temp hard code to 800MHz */ + return 0; } static int rv_thermal_get_temperature(struct pp_hwmgr *hwmgr) @@ -1058,6 +865,13 @@ static const struct pp_hwmgr_func rv_hwmgr_funcs = { .get_clock_by_type_with_voltage = rv_get_clock_by_type_with_voltage, .get_max_high_clocks = rv_get_max_high_clocks, .read_sensor = rv_read_sensor, + .set_active_display_count = rv_set_active_display_count, + .set_deep_sleep_dcefclk = rv_set_deep_sleep_dcefclk, + .dynamic_state_management_enable = rv_enable_dpm_tasks, + .power_off_asic = rv_power_off_asic, + .asic_setup = rv_setup_asic_task, + .power_state_set = rv_set_power_state_tasks, + .dynamic_state_management_disable = rv_disable_dpm_tasks, }; int rv_init_function_pointers(struct pp_hwmgr *hwmgr) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/rv_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/rv_hwmgr.h index 2472b50..68d61bd 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/rv_hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/rv_hwmgr.h @@ -293,7 +293,9 @@ struct rv_hwmgr { DpmClocks_t clock_table; uint32_t active_process_mask; - bool need_min_deep_sleep_dcefclk; /* disabled by default */ + bool need_min_deep_sleep_dcefclk; + uint32_t deep_sleep_dcefclk; + uint32_t num_active_display; }; struct pp_hwmgr; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c index 261b828..69a0678 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c @@ -27,21 +27,21 @@ static int smu7_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable) { - return smum_send_msg_to_smc(hwmgr->smumgr, enable ? + return smum_send_msg_to_smc(hwmgr, enable ? PPSMC_MSG_UVDDPM_Enable : PPSMC_MSG_UVDDPM_Disable); } static int smu7_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable) { - return smum_send_msg_to_smc(hwmgr->smumgr, enable ? + return smum_send_msg_to_smc(hwmgr, enable ? PPSMC_MSG_VCEDPM_Enable : PPSMC_MSG_VCEDPM_Disable); } static int smu7_enable_disable_samu_dpm(struct pp_hwmgr *hwmgr, bool enable) { - return smum_send_msg_to_smc(hwmgr->smumgr, enable ? + return smum_send_msg_to_smc(hwmgr, enable ? PPSMC_MSG_SAMUDPM_Enable : PPSMC_MSG_SAMUDPM_Disable); } @@ -70,7 +70,7 @@ static int smu7_update_samu_dpm(struct pp_hwmgr *hwmgr, bool bgate) int smu7_powerdown_uvd(struct pp_hwmgr *hwmgr) { if (phm_cf_want_uvd_power_gating(hwmgr)) - return smum_send_msg_to_smc(hwmgr->smumgr, + return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_UVDPowerOFF); return 0; } @@ -80,10 +80,10 @@ static int smu7_powerup_uvd(struct pp_hwmgr *hwmgr) if (phm_cf_want_uvd_power_gating(hwmgr)) { if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UVDDynamicPowerGating)) { - return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + return smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_UVDPowerON, 1); } else { - return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + return smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_UVDPowerON, 0); } } @@ -94,7 +94,7 @@ static int smu7_powerup_uvd(struct pp_hwmgr *hwmgr) static int smu7_powerdown_vce(struct pp_hwmgr *hwmgr) { if (phm_cf_want_vce_power_gating(hwmgr)) - return smum_send_msg_to_smc(hwmgr->smumgr, + return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_VCEPowerOFF); return 0; } @@ -102,7 +102,7 @@ static int smu7_powerdown_vce(struct pp_hwmgr *hwmgr) static int smu7_powerup_vce(struct pp_hwmgr *hwmgr) { if (phm_cf_want_vce_power_gating(hwmgr)) - return smum_send_msg_to_smc(hwmgr->smumgr, + return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_VCEPowerON); return 0; } @@ -111,7 +111,7 @@ static int smu7_powerdown_samu(struct pp_hwmgr *hwmgr) { if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SamuPowerGating)) - return smum_send_msg_to_smc(hwmgr->smumgr, + return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SAMPowerOFF); return 0; } @@ -120,7 +120,7 @@ static int smu7_powerup_samu(struct pp_hwmgr *hwmgr) { if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SamuPowerGating)) - return smum_send_msg_to_smc(hwmgr->smumgr, + return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SAMPowerON); return 0; } @@ -140,7 +140,7 @@ int smu7_disable_clock_power_gating(struct pp_hwmgr *hwmgr) return 0; } -int smu7_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate) +void smu7_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); @@ -166,10 +166,9 @@ int smu7_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate) smu7_update_uvd_dpm(hwmgr, false); } - return 0; } -int smu7_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate) +void smu7_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); @@ -194,7 +193,6 @@ int smu7_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate) AMD_PG_STATE_UNGATE); smu7_update_vce_dpm(hwmgr, false); } - return 0; } int smu7_powergate_samu(struct pp_hwmgr *hwmgr, bool bgate) @@ -237,7 +235,7 @@ int smu7_update_clock_gatings(struct pp_hwmgr *hwmgr, value = CG_GFX_CGCG_MASK; if (smum_send_msg_to_smc_with_parameter( - hwmgr->smumgr, msg, value)) + hwmgr, msg, value)) return -EINVAL; } if (PP_STATE_SUPPORT_LS & *msg_id) { @@ -247,7 +245,7 @@ int smu7_update_clock_gatings(struct pp_hwmgr *hwmgr, value = CG_GFX_CGLS_MASK; if (smum_send_msg_to_smc_with_parameter( - hwmgr->smumgr, msg, value)) + hwmgr, msg, value)) return -EINVAL; } break; @@ -260,7 +258,7 @@ int smu7_update_clock_gatings(struct pp_hwmgr *hwmgr, value = CG_GFX_3DCG_MASK; if (smum_send_msg_to_smc_with_parameter( - hwmgr->smumgr, msg, value)) + hwmgr, msg, value)) return -EINVAL; } @@ -271,7 +269,7 @@ int smu7_update_clock_gatings(struct pp_hwmgr *hwmgr, value = CG_GFX_3DLS_MASK; if (smum_send_msg_to_smc_with_parameter( - hwmgr->smumgr, msg, value)) + hwmgr, msg, value)) return -EINVAL; } break; @@ -284,7 +282,7 @@ int smu7_update_clock_gatings(struct pp_hwmgr *hwmgr, value = CG_GFX_RLC_LS_MASK; if (smum_send_msg_to_smc_with_parameter( - hwmgr->smumgr, msg, value)) + hwmgr, msg, value)) return -EINVAL; } break; @@ -297,7 +295,7 @@ int smu7_update_clock_gatings(struct pp_hwmgr *hwmgr, value = CG_GFX_CP_LS_MASK; if (smum_send_msg_to_smc_with_parameter( - hwmgr->smumgr, msg, value)) + hwmgr, msg, value)) return -EINVAL; } break; @@ -311,7 +309,7 @@ int smu7_update_clock_gatings(struct pp_hwmgr *hwmgr, CG_GFX_OTHERS_MGCG_MASK); if (smum_send_msg_to_smc_with_parameter( - hwmgr->smumgr, msg, value)) + hwmgr, msg, value)) return -EINVAL; } break; @@ -331,7 +329,7 @@ int smu7_update_clock_gatings(struct pp_hwmgr *hwmgr, value = CG_SYS_BIF_MGCG_MASK; if (smum_send_msg_to_smc_with_parameter( - hwmgr->smumgr, msg, value)) + hwmgr, msg, value)) return -EINVAL; } if (PP_STATE_SUPPORT_LS & *msg_id) { @@ -341,7 +339,7 @@ int smu7_update_clock_gatings(struct pp_hwmgr *hwmgr, value = CG_SYS_BIF_MGLS_MASK; if (smum_send_msg_to_smc_with_parameter( - hwmgr->smumgr, msg, value)) + hwmgr, msg, value)) return -EINVAL; } break; @@ -354,7 +352,7 @@ int smu7_update_clock_gatings(struct pp_hwmgr *hwmgr, value = CG_SYS_MC_MGCG_MASK; if (smum_send_msg_to_smc_with_parameter( - hwmgr->smumgr, msg, value)) + hwmgr, msg, value)) return -EINVAL; } @@ -365,7 +363,7 @@ int smu7_update_clock_gatings(struct pp_hwmgr *hwmgr, value = CG_SYS_MC_MGLS_MASK; if (smum_send_msg_to_smc_with_parameter( - hwmgr->smumgr, msg, value)) + hwmgr, msg, value)) return -EINVAL; } break; @@ -378,7 +376,7 @@ int smu7_update_clock_gatings(struct pp_hwmgr *hwmgr, value = CG_SYS_DRM_MGCG_MASK; if (smum_send_msg_to_smc_with_parameter( - hwmgr->smumgr, msg, value)) + hwmgr, msg, value)) return -EINVAL; } if (PP_STATE_SUPPORT_LS & *msg_id) { @@ -388,7 +386,7 @@ int smu7_update_clock_gatings(struct pp_hwmgr *hwmgr, value = CG_SYS_DRM_MGLS_MASK; if (smum_send_msg_to_smc_with_parameter( - hwmgr->smumgr, msg, value)) + hwmgr, msg, value)) return -EINVAL; } break; @@ -401,7 +399,7 @@ int smu7_update_clock_gatings(struct pp_hwmgr *hwmgr, value = CG_SYS_HDP_MGCG_MASK; if (smum_send_msg_to_smc_with_parameter( - hwmgr->smumgr, msg, value)) + hwmgr, msg, value)) return -EINVAL; } @@ -412,7 +410,7 @@ int smu7_update_clock_gatings(struct pp_hwmgr *hwmgr, value = CG_SYS_HDP_MGLS_MASK; if (smum_send_msg_to_smc_with_parameter( - hwmgr->smumgr, msg, value)) + hwmgr, msg, value)) return -EINVAL; } break; @@ -425,7 +423,7 @@ int smu7_update_clock_gatings(struct pp_hwmgr *hwmgr, value = CG_SYS_SDMA_MGCG_MASK; if (smum_send_msg_to_smc_with_parameter( - hwmgr->smumgr, msg, value)) + hwmgr, msg, value)) return -EINVAL; } @@ -436,7 +434,7 @@ int smu7_update_clock_gatings(struct pp_hwmgr *hwmgr, value = CG_SYS_SDMA_MGLS_MASK; if (smum_send_msg_to_smc_with_parameter( - hwmgr->smumgr, msg, value)) + hwmgr, msg, value)) return -EINVAL; } break; @@ -449,7 +447,7 @@ int smu7_update_clock_gatings(struct pp_hwmgr *hwmgr, value = CG_SYS_ROM_MASK; if (smum_send_msg_to_smc_with_parameter( - hwmgr->smumgr, msg, value)) + hwmgr, msg, value)) return -EINVAL; } break; @@ -489,9 +487,9 @@ int smu7_enable_per_cu_power_gating(struct pp_hwmgr *hwmgr, bool enable) active_cus = sys_info.value; if (enable) - return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + return smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GFX_CU_PG_ENABLE, active_cus); else - return smum_send_msg_to_smc(hwmgr->smumgr, + return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GFX_CU_PG_DISABLE); } diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.h b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.h index c96ed9e..7b54d48 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.h @@ -27,8 +27,8 @@ #include "smu7_hwmgr.h" #include "pp_asicblocks.h" -int smu7_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate); -int smu7_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate); +void smu7_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate); +void smu7_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate); int smu7_powerdown_uvd(struct pp_hwmgr *hwmgr); int smu7_powergate_samu(struct pp_hwmgr *hwmgr, bool bgate); int smu7_powergate_acp(struct pp_hwmgr *hwmgr, bool bgate); diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c index c274323..8dbe914 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c @@ -26,6 +26,7 @@ #include <linux/module.h> #include <linux/slab.h> #include <asm/div64.h> +#include <drm/amdgpu_drm.h> #include "pp_acpi.h" #include "ppatomctrl.h" #include "atombios.h" @@ -163,7 +164,7 @@ static int smu7_get_current_pcie_lane_number(struct pp_hwmgr *hwmgr) static int smu7_enable_smc_voltage_controller(struct pp_hwmgr *hwmgr) { if (hwmgr->feature_mask & PP_SMC_VOLTAGE_CONTROL_MASK) - smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_Voltage_Cntl_Enable); + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_Voltage_Cntl_Enable); return 0; } @@ -300,28 +301,28 @@ static int smu7_construct_voltage_tables(struct pp_hwmgr *hwmgr) "Failed to retrieve SVI2 VDDC table from dependancy table.", return result;); } - tmp = smum_get_mac_definition(hwmgr->smumgr, SMU_MAX_LEVELS_VDDC); + tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_VDDC); PP_ASSERT_WITH_CODE( (data->vddc_voltage_table.count <= tmp), "Too many voltage values for VDDC. Trimming to fit state table.", phm_trim_voltage_table_to_fit_state_table(tmp, &(data->vddc_voltage_table))); - tmp = smum_get_mac_definition(hwmgr->smumgr, SMU_MAX_LEVELS_VDDGFX); + tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_VDDGFX); PP_ASSERT_WITH_CODE( (data->vddgfx_voltage_table.count <= tmp), "Too many voltage values for VDDC. Trimming to fit state table.", phm_trim_voltage_table_to_fit_state_table(tmp, &(data->vddgfx_voltage_table))); - tmp = smum_get_mac_definition(hwmgr->smumgr, SMU_MAX_LEVELS_VDDCI); + tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_VDDCI); PP_ASSERT_WITH_CODE( (data->vddci_voltage_table.count <= tmp), "Too many voltage values for VDDCI. Trimming to fit state table.", phm_trim_voltage_table_to_fit_state_table(tmp, &(data->vddci_voltage_table))); - tmp = smum_get_mac_definition(hwmgr->smumgr, SMU_MAX_LEVELS_MVDD); + tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_MVDD); PP_ASSERT_WITH_CODE( (data->mvdd_voltage_table.count <= tmp), "Too many voltage values for MVDD. Trimming to fit state table.", @@ -387,6 +388,7 @@ static int smu7_enable_display_gap(struct pp_hwmgr *hwmgr) static int smu7_program_voting_clients(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + int i; /* Clear reset for voting clients before enabling DPM */ PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, @@ -394,50 +396,26 @@ static int smu7_program_voting_clients(struct pp_hwmgr *hwmgr) PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL, RESET_BUSY_CNT, 0); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_FREQ_TRAN_VOTING_0, data->voting_rights_clients0); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_FREQ_TRAN_VOTING_1, data->voting_rights_clients1); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_FREQ_TRAN_VOTING_2, data->voting_rights_clients2); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_FREQ_TRAN_VOTING_3, data->voting_rights_clients3); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_FREQ_TRAN_VOTING_4, data->voting_rights_clients4); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_FREQ_TRAN_VOTING_5, data->voting_rights_clients5); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_FREQ_TRAN_VOTING_6, data->voting_rights_clients6); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_FREQ_TRAN_VOTING_7, data->voting_rights_clients7); - + for (i = 0; i < 8; i++) + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_0 + i * 4, + data->voting_rights_clients[i]); return 0; } static int smu7_clear_voting_clients(struct pp_hwmgr *hwmgr) { + int i; + /* Reset voting clients before disabling DPM */ PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL, RESET_SCLK_CNT, 1); PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL, RESET_BUSY_CNT, 1); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_FREQ_TRAN_VOTING_0, 0); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_FREQ_TRAN_VOTING_1, 0); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_FREQ_TRAN_VOTING_2, 0); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_FREQ_TRAN_VOTING_3, 0); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_FREQ_TRAN_VOTING_4, 0); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_FREQ_TRAN_VOTING_5, 0); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_FREQ_TRAN_VOTING_6, 0); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_FREQ_TRAN_VOTING_7, 0); + for (i = 0; i < 8; i++) + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_0 + i * 4, 0); return 0; } @@ -493,7 +471,7 @@ static int smu7_copy_and_switch_arb_sets(struct pp_hwmgr *hwmgr, static int smu7_reset_to_default(struct pp_hwmgr *hwmgr) { - return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_ResetToDefaults); + return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ResetToDefaults); } /** @@ -551,7 +529,7 @@ static int smu7_setup_default_pcie_table(struct pp_hwmgr *hwmgr) data->pcie_gen_performance = data->pcie_gen_power_saving; data->pcie_lane_performance = data->pcie_lane_power_saving; } - tmp = smum_get_mac_definition(hwmgr->smumgr, SMU_MAX_LEVELS_LINK); + tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_LINK); phm_reset_single_dpm_table(&data->dpm_table.pcie_speed_table, tmp, MAX_REGULAR_DPM_NUMBER); @@ -607,13 +585,20 @@ static int smu7_setup_default_pcie_table(struct pp_hwmgr *hwmgr) data->dpm_table.pcie_speed_table.count = 6; } /* Populate last level for boot PCIE level, but do not increment count. */ - phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, + if (hwmgr->chip_family == AMDGPU_FAMILY_CI) { + for (i = 0; i <= data->dpm_table.pcie_speed_table.count; i++) + phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, i, + get_pcie_gen_support(data->pcie_gen_cap, + PP_Max_PCIEGen), + data->vbios_boot_state.pcie_lane_bootup_value); + } else { + phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, data->dpm_table.pcie_speed_table.count, get_pcie_gen_support(data->pcie_gen_cap, PP_Min_PCIEGen), get_pcie_lane_support(data->pcie_lane_cap, PP_Max_PCIELane)); - + } return 0; } @@ -625,27 +610,27 @@ static int smu7_reset_dpm_tables(struct pp_hwmgr *hwmgr) phm_reset_single_dpm_table( &data->dpm_table.sclk_table, - smum_get_mac_definition(hwmgr->smumgr, + smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_GRAPHICS), MAX_REGULAR_DPM_NUMBER); phm_reset_single_dpm_table( &data->dpm_table.mclk_table, - smum_get_mac_definition(hwmgr->smumgr, + smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_MEMORY), MAX_REGULAR_DPM_NUMBER); phm_reset_single_dpm_table( &data->dpm_table.vddc_table, - smum_get_mac_definition(hwmgr->smumgr, + smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_VDDC), MAX_REGULAR_DPM_NUMBER); phm_reset_single_dpm_table( &data->dpm_table.vddci_table, - smum_get_mac_definition(hwmgr->smumgr, + smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_VDDCI), MAX_REGULAR_DPM_NUMBER); phm_reset_single_dpm_table( &data->dpm_table.mvdd_table, - smum_get_mac_definition(hwmgr->smumgr, + smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_MVDD), MAX_REGULAR_DPM_NUMBER); return 0; @@ -689,7 +674,7 @@ static int smu7_setup_dpm_tables_v0(struct pp_hwmgr *hwmgr) allowed_vdd_sclk_table->entries[i].clk) { data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].value = allowed_vdd_sclk_table->entries[i].clk; - data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].enabled = 1; /*(i==0) ? 1 : 0; to do */ + data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].enabled = (i == 0) ? 1 : 0; data->dpm_table.sclk_table.count++; } } @@ -703,7 +688,7 @@ static int smu7_setup_dpm_tables_v0(struct pp_hwmgr *hwmgr) allowed_vdd_mclk_table->entries[i].clk) { data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].value = allowed_vdd_mclk_table->entries[i].clk; - data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].enabled = 1; /*(i==0) ? 1 : 0; */ + data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].enabled = (i == 0) ? 1 : 0; data->dpm_table.mclk_table.count++; } } @@ -855,7 +840,7 @@ static int smu7_enable_vrhot_gpio_interrupt(struct pp_hwmgr *hwmgr) if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_RegulatorHot)) - return smum_send_msg_to_smc(hwmgr->smumgr, + return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableVRHotGPIOInterrupt); return 0; @@ -873,7 +858,7 @@ static int smu7_enable_ulv(struct pp_hwmgr *hwmgr) struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); if (data->ulv_supported) - return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_EnableULV); + return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableULV); return 0; } @@ -883,7 +868,7 @@ static int smu7_disable_ulv(struct pp_hwmgr *hwmgr) struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); if (data->ulv_supported) - return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_DisableULV); + return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisableULV); return 0; } @@ -892,12 +877,12 @@ static int smu7_enable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr) { if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) { - if (smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_MASTER_DeepSleep_ON)) + if (smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MASTER_DeepSleep_ON)) PP_ASSERT_WITH_CODE(false, "Attempt to enable Master Deep Sleep switch failed!", return -EINVAL); } else { - if (smum_send_msg_to_smc(hwmgr->smumgr, + if (smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MASTER_DeepSleep_OFF)) { PP_ASSERT_WITH_CODE(false, "Attempt to disable Master Deep Sleep switch failed!", @@ -912,7 +897,7 @@ static int smu7_disable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr) { if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) { - if (smum_send_msg_to_smc(hwmgr->smumgr, + if (smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MASTER_DeepSleep_OFF)) { PP_ASSERT_WITH_CODE(false, "Attempt to disable Master Deep Sleep switch failed!", @@ -928,12 +913,12 @@ static int smu7_disable_handshake_uvd(struct pp_hwmgr *hwmgr) struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); uint32_t soft_register_value = 0; uint32_t handshake_disables_offset = data->soft_regs_start - + smum_get_offsetof(hwmgr->smumgr, + + smum_get_offsetof(hwmgr, SMU_SoftRegisters, HandshakeDisables); soft_register_value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, handshake_disables_offset); - soft_register_value |= smum_get_mac_definition(hwmgr->smumgr, + soft_register_value |= smum_get_mac_definition(hwmgr, SMU_UVD_MCLK_HANDSHAKE_DISABLE); cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, handshake_disables_offset, soft_register_value); @@ -947,7 +932,7 @@ static int smu7_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) /* enable SCLK dpm */ if (!data->sclk_dpm_key_disabled) PP_ASSERT_WITH_CODE( - (0 == smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_DPM_Enable)), + (0 == smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DPM_Enable)), "Failed to enable SCLK DPM during DPM Start Function!", return -EINVAL); @@ -956,20 +941,31 @@ static int smu7_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) if (!(hwmgr->feature_mask & PP_UVD_HANDSHAKE_MASK)) smu7_disable_handshake_uvd(hwmgr); PP_ASSERT_WITH_CODE( - (0 == smum_send_msg_to_smc(hwmgr->smumgr, + (0 == smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_Enable)), "Failed to enable MCLK DPM during DPM Start Function!", return -EINVAL); PHM_WRITE_FIELD(hwmgr->device, MC_SEQ_CNTL_3, CAC_EN, 0x1); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC0_CNTL, 0x5); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC1_CNTL, 0x5); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_CPL_CNTL, 0x100005); - udelay(10); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC0_CNTL, 0x400005); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC1_CNTL, 0x400005); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_CPL_CNTL, 0x500005); + + if (hwmgr->chip_family == AMDGPU_FAMILY_CI) { + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d30, 0x5); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d3c, 0x5); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d80, 0x100005); + udelay(10); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d30, 0x400005); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d3c, 0x400005); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d80, 0x500005); + } else { + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC0_CNTL, 0x5); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC1_CNTL, 0x5); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_CPL_CNTL, 0x100005); + udelay(10); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC0_CNTL, 0x400005); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC1_CNTL, 0x400005); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_CPL_CNTL, 0x500005); + } } return 0; @@ -993,11 +989,15 @@ static int smu7_start_dpm(struct pp_hwmgr *hwmgr) cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, data->soft_regs_start + - smum_get_offsetof(hwmgr->smumgr, SMU_SoftRegisters, + smum_get_offsetof(hwmgr, SMU_SoftRegisters, VoltageChangeTimeout), 0x1000); PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__PCIE, SWRST_COMMAND_1, RESETLC, 0x0); + if (hwmgr->chip_family == AMDGPU_FAMILY_CI) + cgs_write_register(hwmgr->device, 0x1488, + (cgs_read_register(hwmgr->device, 0x1488) & ~0x1)); + if (smu7_enable_sclk_mclk_dpm(hwmgr)) { pr_err("Failed to enable Sclk DPM and Mclk DPM!"); return -EINVAL; @@ -1006,7 +1006,7 @@ static int smu7_start_dpm(struct pp_hwmgr *hwmgr) /* enable PCIE dpm */ if (0 == data->pcie_dpm_key_disabled) { PP_ASSERT_WITH_CODE( - (0 == smum_send_msg_to_smc(hwmgr->smumgr, + (0 == smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PCIeDPM_Enable)), "Failed to enable pcie DPM during DPM Start Function!", return -EINVAL); @@ -1014,7 +1014,7 @@ static int smu7_start_dpm(struct pp_hwmgr *hwmgr) if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_Falcon_QuickTransition)) { - PP_ASSERT_WITH_CODE((0 == smum_send_msg_to_smc(hwmgr->smumgr, + PP_ASSERT_WITH_CODE((0 == smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableACDCGPIOInterrupt)), "Failed to enable AC DC GPIO Interrupt!", ); @@ -1032,7 +1032,7 @@ static int smu7_disable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), "Trying to disable SCLK DPM when DPM is disabled", return 0); - smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_DPM_Disable); + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DPM_Disable); } /* disable MCLK dpm */ @@ -1040,7 +1040,7 @@ static int smu7_disable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), "Trying to disable MCLK DPM when DPM is disabled", return 0); - smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_MCLKDPM_Disable); + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_Disable); } return 0; @@ -1060,7 +1060,7 @@ static int smu7_stop_dpm(struct pp_hwmgr *hwmgr) /* disable PCIE dpm */ if (!data->pcie_dpm_key_disabled) { PP_ASSERT_WITH_CODE( - (smum_send_msg_to_smc(hwmgr->smumgr, + (smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PCIeDPM_Disable) == 0), "Failed to disable pcie DPM during DPM Stop Function!", return -EINVAL); @@ -1072,7 +1072,7 @@ static int smu7_stop_dpm(struct pp_hwmgr *hwmgr) "Trying to disable voltage DPM when DPM is disabled", return 0); - smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_Voltage_Cntl_Disable); + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_Voltage_Cntl_Disable); return 0; } @@ -1226,7 +1226,7 @@ static int smu7_enable_dpm_tasks(struct pp_hwmgr *hwmgr) PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to enable VR hot GPIO interrupt!", result = tmp_result); - smum_send_msg_to_smc(hwmgr->smumgr, (PPSMC_Msg)PPSMC_NoDisplay); + smum_send_msg_to_smc(hwmgr, (PPSMC_Msg)PPSMC_NoDisplay); tmp_result = smu7_enable_sclk_control(hwmgr); PP_ASSERT_WITH_CODE((0 == tmp_result), @@ -1361,14 +1361,14 @@ static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr) data->vddc_vddgfx_delta = 300; data->static_screen_threshold = SMU7_STATICSCREENTHRESHOLD_DFLT; data->static_screen_threshold_unit = SMU7_STATICSCREENTHRESHOLDUNIT_DFLT; - data->voting_rights_clients0 = SMU7_VOTINGRIGHTSCLIENTS_DFLT0; - data->voting_rights_clients1 = SMU7_VOTINGRIGHTSCLIENTS_DFLT1; - data->voting_rights_clients2 = SMU7_VOTINGRIGHTSCLIENTS_DFLT2; - data->voting_rights_clients3 = SMU7_VOTINGRIGHTSCLIENTS_DFLT3; - data->voting_rights_clients4 = SMU7_VOTINGRIGHTSCLIENTS_DFLT4; - data->voting_rights_clients5 = SMU7_VOTINGRIGHTSCLIENTS_DFLT5; - data->voting_rights_clients6 = SMU7_VOTINGRIGHTSCLIENTS_DFLT6; - data->voting_rights_clients7 = SMU7_VOTINGRIGHTSCLIENTS_DFLT7; + data->voting_rights_clients[0] = SMU7_VOTINGRIGHTSCLIENTS_DFLT0; + data->voting_rights_clients[1]= SMU7_VOTINGRIGHTSCLIENTS_DFLT1; + data->voting_rights_clients[2] = SMU7_VOTINGRIGHTSCLIENTS_DFLT2; + data->voting_rights_clients[3]= SMU7_VOTINGRIGHTSCLIENTS_DFLT3; + data->voting_rights_clients[4]= SMU7_VOTINGRIGHTSCLIENTS_DFLT4; + data->voting_rights_clients[5]= SMU7_VOTINGRIGHTSCLIENTS_DFLT5; + data->voting_rights_clients[6]= SMU7_VOTINGRIGHTSCLIENTS_DFLT6; + data->voting_rights_clients[7]= SMU7_VOTINGRIGHTSCLIENTS_DFLT7; data->mclk_dpm_key_disabled = hwmgr->feature_mask & PP_MCLK_DPM_MASK ? false : true; data->sclk_dpm_key_disabled = hwmgr->feature_mask & PP_SCLK_DPM_MASK ? false : true; @@ -1382,23 +1382,40 @@ static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr) data->force_pcie_gen = PP_PCIEGenInvalid; data->ulv_supported = hwmgr->feature_mask & PP_ULV_MASK ? true : false; - if (hwmgr->chip_id == CHIP_POLARIS12 || hwmgr->smumgr->is_kicker) { + if (hwmgr->chip_id == CHIP_POLARIS12 || hwmgr->is_kicker) { uint8_t tmp1, tmp2; uint16_t tmp3 = 0; atomctrl_get_svi2_info(hwmgr, VOLTAGE_TYPE_VDDC, &tmp1, &tmp2, &tmp3); tmp3 = (tmp3 >> 5) & 0x3; data->vddc_phase_shed_control = ((tmp3 << 1) | (tmp3 >> 1)) & 0x3; + } else if (hwmgr->chip_family == AMDGPU_FAMILY_CI) { + data->vddc_phase_shed_control = 1; + } else { + data->vddc_phase_shed_control = 0; + } + + if (hwmgr->chip_id == CHIP_HAWAII) { + data->thermal_temp_setting.temperature_low = 94500; + data->thermal_temp_setting.temperature_high = 95000; + data->thermal_temp_setting.temperature_shutdown = 104000; + } else { + data->thermal_temp_setting.temperature_low = 99500; + data->thermal_temp_setting.temperature_high = 100000; + data->thermal_temp_setting.temperature_shutdown = 104000; } data->fast_watermark_threshold = 100; - if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr, + if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr, VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2)) data->voltage_control = SMU7_VOLTAGE_CONTROL_BY_SVID2; + else if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr, + VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_GPIO_LUT)) + data->voltage_control = SMU7_VOLTAGE_CONTROL_BY_GPIO; if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_ControlVDDGFX)) { - if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr, + if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr, VOLTAGE_TYPE_VDDGFX, VOLTAGE_OBJ_SVID2)) { data->vdd_gfx_control = SMU7_VOLTAGE_CONTROL_BY_SVID2; } @@ -1406,25 +1423,24 @@ static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr) if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_EnableMVDDControl)) { - if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr, + if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr, VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_GPIO_LUT)) data->mvdd_control = SMU7_VOLTAGE_CONTROL_BY_GPIO; - else if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr, + else if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr, VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_SVID2)) data->mvdd_control = SMU7_VOLTAGE_CONTROL_BY_SVID2; } - if (SMU7_VOLTAGE_CONTROL_NONE == data->vdd_gfx_control) { + if (SMU7_VOLTAGE_CONTROL_NONE == data->vdd_gfx_control) phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_ControlVDDGFX); - } if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_ControlVDDCI)) { - if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr, + if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr, VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_GPIO_LUT)) data->vddci_control = SMU7_VOLTAGE_CONTROL_BY_GPIO; - else if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr, + else if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr, VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_SVID2)) data->vddci_control = SMU7_VOLTAGE_CONTROL_BY_SVID2; } @@ -1543,7 +1559,7 @@ static int smu7_get_evv_voltages(struct pp_hwmgr *hwmgr) if (vddc >= 2000 || vddc == 0) return -EINVAL; } else { - pr_warn("failed to retrieving EVV voltage!\n"); + pr_debug("failed to retrieving EVV voltage!\n"); continue; } @@ -1676,7 +1692,7 @@ static int phm_add_voltage(struct pp_hwmgr *hwmgr, PP_ASSERT_WITH_CODE((0 != look_up_table->count), "Lookup Table empty.", return -EINVAL); - i = smum_get_mac_definition(hwmgr->smumgr, SMU_MAX_LEVELS_VDDGFX); + i = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_VDDGFX); PP_ASSERT_WITH_CODE((i >= look_up_table->count), "Lookup Table is full.", return -EINVAL); @@ -2274,7 +2290,7 @@ static int smu7_set_private_data_based_on_pptable_v0(struct pp_hwmgr *hwmgr) data->max_vddci_in_pptable = (uint16_t)allowed_mclk_vddci_table->entries[allowed_mclk_vddci_table->count - 1].v; } - if (hwmgr->dyn_state.vddci_dependency_on_mclk != NULL && hwmgr->dyn_state.vddci_dependency_on_mclk->count > 1) + if (hwmgr->dyn_state.vddci_dependency_on_mclk != NULL && hwmgr->dyn_state.vddci_dependency_on_mclk->count >= 1) hwmgr->dyn_state.max_clock_voltage_on_ac.vddci = hwmgr->dyn_state.vddci_dependency_on_mclk->entries[hwmgr->dyn_state.vddci_dependency_on_mclk->count - 1].v; return 0; @@ -2282,40 +2298,65 @@ static int smu7_set_private_data_based_on_pptable_v0(struct pp_hwmgr *hwmgr) static int smu7_hwmgr_backend_fini(struct pp_hwmgr *hwmgr) { - if (NULL != hwmgr->dyn_state.vddc_dep_on_dal_pwrl) { - kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl); - hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL; - } - pp_smu7_thermal_fini(hwmgr); - if (NULL != hwmgr->backend) { - kfree(hwmgr->backend); - hwmgr->backend = NULL; - } + kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl); + hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL; + kfree(hwmgr->backend); + hwmgr->backend = NULL; + + return 0; +} + +static int smu7_get_elb_voltages(struct pp_hwmgr *hwmgr) +{ + uint16_t virtual_voltage_id, vddc, vddci, efuse_voltage_id; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + int i; + if (atomctrl_get_leakage_id_from_efuse(hwmgr, &efuse_voltage_id) == 0) { + for (i = 0; i < SMU7_MAX_LEAKAGE_COUNT; i++) { + virtual_voltage_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i; + if (atomctrl_get_leakage_vddc_base_on_leakage(hwmgr, &vddc, &vddci, + virtual_voltage_id, + efuse_voltage_id) == 0) { + if (vddc != 0 && vddc != virtual_voltage_id) { + data->vddc_leakage.actual_voltage[data->vddc_leakage.count] = vddc; + data->vddc_leakage.leakage_id[data->vddc_leakage.count] = virtual_voltage_id; + data->vddc_leakage.count++; + } + if (vddci != 0 && vddci != virtual_voltage_id) { + data->vddci_leakage.actual_voltage[data->vddci_leakage.count] = vddci; + data->vddci_leakage.leakage_id[data->vddci_leakage.count] = virtual_voltage_id; + data->vddci_leakage.count++; + } + } + } + } return 0; } static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data; - int result; + int result = 0; data = kzalloc(sizeof(struct smu7_hwmgr), GFP_KERNEL); if (data == NULL) return -ENOMEM; hwmgr->backend = data; - pp_smu7_thermal_initialize(hwmgr); - smu7_patch_voltage_workaround(hwmgr); smu7_init_dpm_defaults(hwmgr); /* Get leakage voltage based on leakage ID. */ - result = smu7_get_evv_voltages(hwmgr); - - if (result) { - pr_info("Get EVV Voltage Failed. Abort Driver loading!\n"); - return -EINVAL; + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EVV)) { + result = smu7_get_evv_voltages(hwmgr); + if (result) { + pr_info("Get EVV Voltage Failed. Abort Driver loading!\n"); + return -EINVAL; + } + } else { + smu7_get_elb_voltages(hwmgr); } if (hwmgr->pp_table_version == PP_TABLE_V1) { @@ -2382,7 +2423,7 @@ static int smu7_force_dpm_highest(struct pp_hwmgr *hwmgr) level++; if (level) - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_PCIeDPM_ForceLevel, level); } } @@ -2395,7 +2436,7 @@ static int smu7_force_dpm_highest(struct pp_hwmgr *hwmgr) level++; if (level) - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SCLKDPM_SetEnabledMask, (1 << level)); } @@ -2409,7 +2450,7 @@ static int smu7_force_dpm_highest(struct pp_hwmgr *hwmgr) level++; if (level) - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_MCLKDPM_SetEnabledMask, (1 << level)); } @@ -2428,14 +2469,14 @@ static int smu7_upload_dpm_level_enable_mask(struct pp_hwmgr *hwmgr) if (!data->sclk_dpm_key_disabled) { if (data->dpm_level_enable_mask.sclk_dpm_enable_mask) - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SCLKDPM_SetEnabledMask, data->dpm_level_enable_mask.sclk_dpm_enable_mask); } if (!data->mclk_dpm_key_disabled) { if (data->dpm_level_enable_mask.mclk_dpm_enable_mask) - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_MCLKDPM_SetEnabledMask, data->dpm_level_enable_mask.mclk_dpm_enable_mask); } @@ -2451,7 +2492,7 @@ static int smu7_unforce_dpm_levels(struct pp_hwmgr *hwmgr) return -EINVAL; if (!data->pcie_dpm_key_disabled) { - smum_send_msg_to_smc(hwmgr->smumgr, + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PCIeDPM_UnForceLevel); } @@ -2468,7 +2509,7 @@ static int smu7_force_dpm_lowest(struct pp_hwmgr *hwmgr) if (data->dpm_level_enable_mask.sclk_dpm_enable_mask) { level = phm_get_lowest_enabled_level(hwmgr, data->dpm_level_enable_mask.sclk_dpm_enable_mask); - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SCLKDPM_SetEnabledMask, (1 << level)); @@ -2478,7 +2519,7 @@ static int smu7_force_dpm_lowest(struct pp_hwmgr *hwmgr) if (data->dpm_level_enable_mask.mclk_dpm_enable_mask) { level = phm_get_lowest_enabled_level(hwmgr, data->dpm_level_enable_mask.mclk_dpm_enable_mask); - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_MCLKDPM_SetEnabledMask, (1 << level)); } @@ -2488,7 +2529,7 @@ static int smu7_force_dpm_lowest(struct pp_hwmgr *hwmgr) if (data->dpm_level_enable_mask.pcie_dpm_enable_mask) { level = phm_get_lowest_enabled_level(hwmgr, data->dpm_level_enable_mask.pcie_dpm_enable_mask); - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_PCIeDPM_ForceLevel, (level)); } @@ -2572,51 +2613,16 @@ static int smu7_force_dpm_level(struct pp_hwmgr *hwmgr, uint32_t sclk_mask = 0; uint32_t mclk_mask = 0; uint32_t pcie_mask = 0; - uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | - AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | - AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | - AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; - - if (level == hwmgr->dpm_level) - return ret; - - if (!(hwmgr->dpm_level & profile_mode_mask)) { - /* enter profile mode, save current level, disable gfx cg*/ - if (level & profile_mode_mask) { - hwmgr->saved_dpm_level = hwmgr->dpm_level; - cgs_set_clockgating_state(hwmgr->device, - AMD_IP_BLOCK_TYPE_GFX, - AMD_CG_STATE_UNGATE); - } - } else { - /* exit profile mode, restore level, enable gfx cg*/ - if (!(level & profile_mode_mask)) { - if (level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT) - level = hwmgr->saved_dpm_level; - cgs_set_clockgating_state(hwmgr->device, - AMD_IP_BLOCK_TYPE_GFX, - AMD_CG_STATE_GATE); - } - } switch (level) { case AMD_DPM_FORCED_LEVEL_HIGH: ret = smu7_force_dpm_highest(hwmgr); - if (ret) - return ret; - hwmgr->dpm_level = level; break; case AMD_DPM_FORCED_LEVEL_LOW: ret = smu7_force_dpm_lowest(hwmgr); - if (ret) - return ret; - hwmgr->dpm_level = level; break; case AMD_DPM_FORCED_LEVEL_AUTO: ret = smu7_unforce_dpm_levels(hwmgr); - if (ret) - return ret; - hwmgr->dpm_level = level; break; case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: @@ -2625,26 +2631,23 @@ static int smu7_force_dpm_level(struct pp_hwmgr *hwmgr, ret = smu7_get_profiling_clk(hwmgr, level, &sclk_mask, &mclk_mask, &pcie_mask); if (ret) return ret; - hwmgr->dpm_level = level; smu7_force_clock_level(hwmgr, PP_SCLK, 1<<sclk_mask); smu7_force_clock_level(hwmgr, PP_MCLK, 1<<mclk_mask); smu7_force_clock_level(hwmgr, PP_PCIE, 1<<pcie_mask); - break; case AMD_DPM_FORCED_LEVEL_MANUAL: - hwmgr->dpm_level = level; - break; case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: default: break; } - if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->saved_dpm_level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) - smu7_fan_ctrl_set_fan_speed_percent(hwmgr, 100); - else if (level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->saved_dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) - smu7_fan_ctrl_reset_fan_speed_to_default(hwmgr); - - return 0; + if (!ret) { + if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) + smu7_fan_ctrl_set_fan_speed_percent(hwmgr, 100); + else if (level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) + smu7_fan_ctrl_reset_fan_speed_to_default(hwmgr); + } + return ret; } static int smu7_get_power_state_size(struct pp_hwmgr *hwmgr) @@ -2843,7 +2846,7 @@ static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, } -static int smu7_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) +static uint32_t smu7_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) { struct pp_power_state *ps; struct smu7_power_state *smu7_ps; @@ -2865,7 +2868,7 @@ static int smu7_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) [smu7_ps->performance_level_count-1].memory_clock; } -static int smu7_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low) +static uint32_t smu7_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low) { struct pp_power_state *ps; struct smu7_power_state *smu7_ps; @@ -3002,7 +3005,7 @@ static int smu7_get_pp_table_entry_callback_func_v1(struct pp_hwmgr *hwmgr, [smu7_power_state->performance_level_count++]); PP_ASSERT_WITH_CODE( - (smu7_power_state->performance_level_count < smum_get_mac_definition(hwmgr->smumgr, SMU_MAX_LEVELS_GRAPHICS)), + (smu7_power_state->performance_level_count < smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_GRAPHICS)), "Performance levels exceeds SMC limit!", return -EINVAL); @@ -3071,11 +3074,11 @@ static int smu7_get_pp_table_entry_v1(struct pp_hwmgr *hwmgr, if (dep_mclk_table != NULL && dep_mclk_table->count == 1) { if (dep_mclk_table->entries[0].clk != data->vbios_boot_state.mclk_bootup_value) - pr_err("Single MCLK entry VDDCI/MCLK dependency table " + pr_debug("Single MCLK entry VDDCI/MCLK dependency table " "does not match VBIOS boot MCLK level"); if (dep_mclk_table->entries[0].vddci != data->vbios_boot_state.vddci_bootup_value) - pr_err("Single VDDCI entry VDDCI/MCLK dependency table " + pr_debug("Single VDDCI entry VDDCI/MCLK dependency table " "does not match VBIOS boot VDDCI level"); } @@ -3166,7 +3169,7 @@ static int smu7_get_pp_table_entry_callback_func_v0(struct pp_hwmgr *hwmgr, data->highest_mclk = memory_clock; PP_ASSERT_WITH_CODE( - (ps->performance_level_count < smum_get_mac_definition(hwmgr->smumgr, SMU_MAX_LEVELS_GRAPHICS)), + (ps->performance_level_count < smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_GRAPHICS)), "Performance levels exceeds SMC limit!", return -EINVAL); @@ -3219,11 +3222,11 @@ static int smu7_get_pp_table_entry_v0(struct pp_hwmgr *hwmgr, if (dep_mclk_table != NULL && dep_mclk_table->count == 1) { if (dep_mclk_table->entries[0].clk != data->vbios_boot_state.mclk_bootup_value) - pr_err("Single MCLK entry VDDCI/MCLK dependency table " + pr_debug("Single MCLK entry VDDCI/MCLK dependency table " "does not match VBIOS boot MCLK level"); if (dep_mclk_table->entries[0].v != data->vbios_boot_state.vddci_bootup_value) - pr_err("Single VDDCI entry VDDCI/MCLK dependency table " + pr_debug("Single VDDCI entry VDDCI/MCLK dependency table " "does not match VBIOS boot VDDCI level"); } @@ -3312,14 +3315,14 @@ static int smu7_get_pp_table_entry(struct pp_hwmgr *hwmgr, static int smu7_get_gpu_power(struct pp_hwmgr *hwmgr, struct pp_gpu_power *query) { - PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PmStatusLogStart), "Failed to start pm status log!", return -1); msleep_interruptible(20); - PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PmStatusLogSample), "Failed to sample pm status log!", return -1); @@ -3353,19 +3356,19 @@ static int smu7_read_sensor(struct pp_hwmgr *hwmgr, int idx, switch (idx) { case AMDGPU_PP_SENSOR_GFX_SCLK: - smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_API_GetSclkFrequency); + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_API_GetSclkFrequency); sclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0); *((uint32_t *)value) = sclk; *size = 4; return 0; case AMDGPU_PP_SENSOR_GFX_MCLK: - smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_API_GetMclkFrequency); + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_API_GetMclkFrequency); mclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0); *((uint32_t *)value) = mclk; *size = 4; return 0; case AMDGPU_PP_SENSOR_GPU_LOAD: - offset = data->soft_regs_start + smum_get_offsetof(hwmgr->smumgr, + offset = data->soft_regs_start + smum_get_offsetof(hwmgr, SMU_SoftRegisters, AverageGraphicsActivity); @@ -3532,7 +3535,7 @@ static int smu7_freeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), "Trying to freeze SCLK DPM when DPM is disabled", ); - PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_FreezeLevel), "Failed to freeze SCLK DPM during FreezeSclkMclkDPM Function!", return -EINVAL); @@ -3544,7 +3547,7 @@ static int smu7_freeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), "Trying to freeze MCLK DPM when DPM is disabled", ); - PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_FreezeLevel), "Failed to freeze MCLK DPM during FreezeSclkMclkDPM Function!", return -EINVAL); @@ -3762,7 +3765,7 @@ static int smu7_unfreeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), "Trying to Unfreeze SCLK DPM when DPM is disabled", ); - PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_UnfreezeLevel), "Failed to unfreeze SCLK DPM during UnFreezeSclkMclkDPM Function!", return -EINVAL); @@ -3774,7 +3777,7 @@ static int smu7_unfreeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), "Trying to Unfreeze MCLK DPM when DPM is disabled", ); - PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_UnfreezeLevel), "Failed to unfreeze MCLK DPM during UnFreezeSclkMclkDPM Function!", return -EINVAL); @@ -3822,11 +3825,14 @@ static int smu7_notify_link_speed_change_after_state_change( static int smu7_notify_smc_display(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + int ret = 0; - if (hwmgr->feature_mask & PP_VBI_TIME_SUPPORT_MASK) - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + if (hwmgr->feature_mask & PP_VBI_TIME_SUPPORT_MASK) { + smum_send_msg_to_smc_with_parameter(hwmgr, (PPSMC_Msg)PPSMC_MSG_SetVBITimeout, data->frame_time_x2); - return (smum_send_msg_to_smc(hwmgr->smumgr, (PPSMC_Msg)PPSMC_HasDisplay) == 0) ? 0 : -EINVAL; + ret = (smum_send_msg_to_smc(hwmgr, (PPSMC_Msg)PPSMC_HasDisplay) == 0) ? 0 : -EINVAL; + } + return ret; } static int smu7_set_power_state_tasks(struct pp_hwmgr *hwmgr, const void *input) @@ -3899,10 +3905,7 @@ static int smu7_set_max_fan_pwm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_f hwmgr->thermal_controller. advanceFanControlParameters.usMaxFanPWM = us_max_fan_pwm; - if (phm_is_hw_access_blocked(hwmgr)) - return 0; - - return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + return smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetFanPwmMax, us_max_fan_pwm); } @@ -3911,7 +3914,7 @@ smu7_notify_smc_display_change(struct pp_hwmgr *hwmgr, bool has_display) { PPSMC_Msg msg = has_display ? (PPSMC_Msg)PPSMC_HasDisplay : (PPSMC_Msg)PPSMC_NoDisplay; - return (smum_send_msg_to_smc(hwmgr->smumgr, msg) == 0) ? 0 : -1; + return (smum_send_msg_to_smc(hwmgr, msg) == 0) ? 0 : -1; } static int @@ -3974,12 +3977,12 @@ static int smu7_program_display_gap(struct pp_hwmgr *hwmgr) cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL2, display_gap2); cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - data->soft_regs_start + smum_get_offsetof(hwmgr->smumgr, + data->soft_regs_start + smum_get_offsetof(hwmgr, SMU_SoftRegisters, PreVBlankGap), 0x64); cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - data->soft_regs_start + smum_get_offsetof(hwmgr->smumgr, + data->soft_regs_start + smum_get_offsetof(hwmgr, SMU_SoftRegisters, VBlankTimeout), (frame_time_in_us - pre_vbi_time_in_us)); @@ -4004,10 +4007,7 @@ static int smu7_set_max_fan_rpm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_f hwmgr->thermal_controller. advanceFanControlParameters.usMaxFanRPM = us_max_fan_rpm; - if (phm_is_hw_access_blocked(hwmgr)) - return 0; - - return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + return smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetFanRpmMax, us_max_fan_rpm); } @@ -4249,21 +4249,21 @@ static int smu7_force_clock_level(struct pp_hwmgr *hwmgr, { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - if (hwmgr->dpm_level & (AMD_DPM_FORCED_LEVEL_AUTO | - AMD_DPM_FORCED_LEVEL_LOW | - AMD_DPM_FORCED_LEVEL_HIGH)) + if (hwmgr->request_dpm_level & (AMD_DPM_FORCED_LEVEL_AUTO | + AMD_DPM_FORCED_LEVEL_LOW | + AMD_DPM_FORCED_LEVEL_HIGH)) return -EINVAL; switch (type) { case PP_SCLK: if (!data->sclk_dpm_key_disabled) - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SCLKDPM_SetEnabledMask, data->dpm_level_enable_mask.sclk_dpm_enable_mask & mask); break; case PP_MCLK: if (!data->mclk_dpm_key_disabled) - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_MCLKDPM_SetEnabledMask, data->dpm_level_enable_mask.mclk_dpm_enable_mask & mask); break; @@ -4276,7 +4276,7 @@ static int smu7_force_clock_level(struct pp_hwmgr *hwmgr, level++; if (!data->pcie_dpm_key_disabled) - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_PCIeDPM_ForceLevel, level); break; @@ -4300,7 +4300,7 @@ static int smu7_print_clock_levels(struct pp_hwmgr *hwmgr, switch (type) { case PP_SCLK: - smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_API_GetSclkFrequency); + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_API_GetSclkFrequency); clock = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0); for (i = 0; i < sclk_table->count; i++) { @@ -4316,7 +4316,7 @@ static int smu7_print_clock_levels(struct pp_hwmgr *hwmgr, (i == now) ? "*" : ""); break; case PP_MCLK: - smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_API_GetMclkFrequency); + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_API_GetMclkFrequency); clock = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0); for (i = 0; i < mclk_table->count; i++) { @@ -4353,31 +4353,27 @@ static int smu7_print_clock_levels(struct pp_hwmgr *hwmgr, return size; } -static int smu7_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode) +static void smu7_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode) { - int result = 0; - switch (mode) { case AMD_FAN_CTRL_NONE: - result = smu7_fan_ctrl_set_fan_speed_percent(hwmgr, 100); + smu7_fan_ctrl_set_fan_speed_percent(hwmgr, 100); break; case AMD_FAN_CTRL_MANUAL: if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl)) - result = smu7_fan_ctrl_stop_smc_fan_control(hwmgr); + smu7_fan_ctrl_stop_smc_fan_control(hwmgr); break; case AMD_FAN_CTRL_AUTO: - result = smu7_fan_ctrl_set_static_mode(hwmgr, mode); - if (!result) - result = smu7_fan_ctrl_start_smc_fan_control(hwmgr); + if (!smu7_fan_ctrl_set_static_mode(hwmgr, mode)) + smu7_fan_ctrl_start_smc_fan_control(hwmgr); break; default: break; } - return result; } -static int smu7_get_fan_control_mode(struct pp_hwmgr *hwmgr) +static uint32_t smu7_get_fan_control_mode(struct pp_hwmgr *hwmgr) { return hwmgr->fan_ctrl_enabled ? AMD_FAN_CTRL_AUTO : AMD_FAN_CTRL_MANUAL; } @@ -4606,7 +4602,7 @@ static int smu7_set_power_profile_state(struct pp_hwmgr *hwmgr, if (sclk_mask) { if (!data->sclk_dpm_key_disabled) - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SCLKDPM_SetEnabledMask, data->dpm_level_enable_mask. sclk_dpm_enable_mask & @@ -4615,7 +4611,7 @@ static int smu7_set_power_profile_state(struct pp_hwmgr *hwmgr, if (mclk_mask) { if (!data->mclk_dpm_key_disabled) - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_MCLKDPM_SetEnabledMask, data->dpm_level_enable_mask. mclk_dpm_enable_mask & @@ -4627,8 +4623,7 @@ static int smu7_set_power_profile_state(struct pp_hwmgr *hwmgr, static int smu7_avfs_control(struct pp_hwmgr *hwmgr, bool enable) { - struct pp_smumgr *smumgr = (struct pp_smumgr *)(hwmgr->smumgr); - struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(smumgr->backend); + struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); if (smu_data == NULL) return -EINVAL; @@ -4640,13 +4635,13 @@ static int smu7_avfs_control(struct pp_hwmgr *hwmgr, bool enable) if (!PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, FEATURE_STATUS, AVS_ON)) PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc( - hwmgr->smumgr, PPSMC_MSG_EnableAvfs), + hwmgr, PPSMC_MSG_EnableAvfs), "Failed to enable AVFS!", return -EINVAL); } else if (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, FEATURE_STATUS, AVS_ON)) PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc( - hwmgr->smumgr, PPSMC_MSG_DisableAvfs), + hwmgr, PPSMC_MSG_DisableAvfs), "Failed to disable AVFS!", return -EINVAL); @@ -4703,6 +4698,7 @@ static const struct pp_hwmgr_func smu7_hwmgr_funcs = { .set_power_profile_state = smu7_set_power_profile_state, .avfs_control = smu7_avfs_control, .disable_smc_firmware_ctf = smu7_thermal_disable_alert, + .start_thermal_controller = smu7_start_thermal_controller, }; uint8_t smu7_get_sleep_divider_id_from_clock(uint32_t clock, diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.h index f221e17..e021154 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.h @@ -182,14 +182,7 @@ struct smu7_hwmgr { struct smu7_dpm_table dpm_table; struct smu7_dpm_table golden_dpm_table; - uint32_t voting_rights_clients0; - uint32_t voting_rights_clients1; - uint32_t voting_rights_clients2; - uint32_t voting_rights_clients3; - uint32_t voting_rights_clients4; - uint32_t voting_rights_clients5; - uint32_t voting_rights_clients6; - uint32_t voting_rights_clients7; + uint32_t voting_rights_clients[8]; uint32_t static_screen_threshold_unit; uint32_t static_screen_threshold; uint32_t voltage_control; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c index 1dc31aa..85ca16a 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c @@ -629,51 +629,38 @@ static int smu7_enable_didt(struct pp_hwmgr *hwmgr, const bool enable) uint32_t block_en = 0; int32_t result = 0; uint32_t didt_block; - uint32_t data; if (hwmgr->chip_id == CHIP_POLARIS11) didt_block = Polaris11_DIDTBlock_Info; else didt_block = DIDTBlock_Info; - block_en = phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SQRamping) ? en : 0; - - data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_SQ_CTRL0); - data &= ~DIDT_SQ_CTRL0__DIDT_CTRL_EN_MASK; - data |= ((block_en << DIDT_SQ_CTRL0__DIDT_CTRL_EN__SHIFT) & DIDT_SQ_CTRL0__DIDT_CTRL_EN_MASK); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_SQ_CTRL0, data); + block_en = PP_CAP(PHM_PlatformCaps_SQRamping) ? en : 0; + CGS_WREG32_FIELD_IND(hwmgr->device, CGS_IND_REG__DIDT, + DIDT_SQ_CTRL0, DIDT_CTRL_EN, block_en); didt_block &= ~SQ_Enable_MASK; didt_block |= block_en << SQ_Enable_SHIFT; - block_en = phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRamping) ? en : 0; - - data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_DB_CTRL0); - data &= ~DIDT_DB_CTRL0__DIDT_CTRL_EN_MASK; - data |= ((block_en << DIDT_DB_CTRL0__DIDT_CTRL_EN__SHIFT) & DIDT_DB_CTRL0__DIDT_CTRL_EN_MASK); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_DB_CTRL0, data); + block_en = PP_CAP(PHM_PlatformCaps_DBRamping) ? en : 0; + CGS_WREG32_FIELD_IND(hwmgr->device, CGS_IND_REG__DIDT, + DIDT_DB_CTRL0, DIDT_CTRL_EN, block_en); didt_block &= ~DB_Enable_MASK; didt_block |= block_en << DB_Enable_SHIFT; - block_en = phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TDRamping) ? en : 0; - data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_TD_CTRL0); - data &= ~DIDT_TD_CTRL0__DIDT_CTRL_EN_MASK; - data |= ((block_en << DIDT_TD_CTRL0__DIDT_CTRL_EN__SHIFT) & DIDT_TD_CTRL0__DIDT_CTRL_EN_MASK); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_TD_CTRL0, data); + block_en = PP_CAP(PHM_PlatformCaps_TDRamping) ? en : 0; + CGS_WREG32_FIELD_IND(hwmgr->device, CGS_IND_REG__DIDT, + DIDT_TD_CTRL0, DIDT_CTRL_EN, block_en); didt_block &= ~TD_Enable_MASK; didt_block |= block_en << TD_Enable_SHIFT; - block_en = phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TCPRamping) ? en : 0; - - data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_TCP_CTRL0); - data &= ~DIDT_TCP_CTRL0__DIDT_CTRL_EN_MASK; - data |= ((block_en << DIDT_TCP_CTRL0__DIDT_CTRL_EN__SHIFT) & DIDT_TCP_CTRL0__DIDT_CTRL_EN_MASK); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_TCP_CTRL0, data); + block_en = PP_CAP(PHM_PlatformCaps_TCPRamping) ? en : 0; + CGS_WREG32_FIELD_IND(hwmgr->device, CGS_IND_REG__DIDT, + DIDT_TCP_CTRL0, DIDT_CTRL_EN, block_en); didt_block &= ~TCP_Enable_MASK; didt_block |= block_en << TCP_Enable_SHIFT; - if (enable) - result = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_Didt_Block_Function, didt_block); + result = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_Didt_Block_Function, didt_block); return result; } @@ -753,12 +740,13 @@ int smu7_enable_didt_config(struct pp_hwmgr *hwmgr) if (result == 0) num_se = sys_info.value; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SQRamping) || - phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRamping) || - phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TDRamping) || - phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TCPRamping)) { + if (PP_CAP(PHM_PlatformCaps_SQRamping) || + PP_CAP(PHM_PlatformCaps_DBRamping) || + PP_CAP(PHM_PlatformCaps_TDRamping) || + PP_CAP(PHM_PlatformCaps_TCPRamping)) { cgs_enter_safe_mode(hwmgr->device, true); + cgs_lock_grbm_idx(hwmgr->device, true); value = 0; value2 = cgs_read_register(hwmgr->device, mmGRBM_GFX_INDEX); for (count = 0; count < num_se; count++) { @@ -775,7 +763,7 @@ int smu7_enable_didt_config(struct pp_hwmgr *hwmgr) } else if (hwmgr->chip_id == CHIP_POLARIS11) { result = smu7_program_pt_config_registers(hwmgr, GCCACConfig_Polaris11); PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", return result); - if (hwmgr->smumgr->is_kicker) + if (hwmgr->is_kicker) result = smu7_program_pt_config_registers(hwmgr, DIDTConfig_Polaris11_Kicker); else result = smu7_program_pt_config_registers(hwmgr, DIDTConfig_Polaris11); @@ -793,11 +781,12 @@ int smu7_enable_didt_config(struct pp_hwmgr *hwmgr) PP_ASSERT_WITH_CODE((result == 0), "EnableDiDt failed.", return result); if (hwmgr->chip_id == CHIP_POLARIS11) { - result = smum_send_msg_to_smc(hwmgr->smumgr, + result = smum_send_msg_to_smc(hwmgr, (uint16_t)(PPSMC_MSG_EnableDpmDidt)); PP_ASSERT_WITH_CODE((0 == result), "Failed to enable DPM DIDT.", return result); } + cgs_lock_grbm_idx(hwmgr->device, false); cgs_enter_safe_mode(hwmgr->device, false); } @@ -808,10 +797,10 @@ int smu7_disable_didt_config(struct pp_hwmgr *hwmgr) { int result; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SQRamping) || - phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRamping) || - phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TDRamping) || - phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TCPRamping)) { + if (PP_CAP(PHM_PlatformCaps_SQRamping) || + PP_CAP(PHM_PlatformCaps_DBRamping) || + PP_CAP(PHM_PlatformCaps_TDRamping) || + PP_CAP(PHM_PlatformCaps_TCPRamping)) { cgs_enter_safe_mode(hwmgr->device, true); @@ -820,7 +809,7 @@ int smu7_disable_didt_config(struct pp_hwmgr *hwmgr) "Post DIDT enable clock gating failed.", return result); if (hwmgr->chip_id == CHIP_POLARIS11) { - result = smum_send_msg_to_smc(hwmgr->smumgr, + result = smum_send_msg_to_smc(hwmgr, (uint16_t)(PPSMC_MSG_DisableDpmDidt)); PP_ASSERT_WITH_CODE((0 == result), "Failed to disable DPM DIDT.", return result); @@ -836,10 +825,9 @@ int smu7_enable_smc_cac(struct pp_hwmgr *hwmgr) struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); int result = 0; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_CAC)) { + if (PP_CAP(PHM_PlatformCaps_CAC)) { int smc_result; - smc_result = smum_send_msg_to_smc(hwmgr->smumgr, + smc_result = smum_send_msg_to_smc(hwmgr, (uint16_t)(PPSMC_MSG_EnableCac)); PP_ASSERT_WITH_CODE((0 == smc_result), "Failed to enable CAC in SMC.", result = -1); @@ -854,9 +842,8 @@ int smu7_disable_smc_cac(struct pp_hwmgr *hwmgr) struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); int result = 0; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_CAC) && data->cac_enabled) { - int smc_result = smum_send_msg_to_smc(hwmgr->smumgr, + if (PP_CAP(PHM_PlatformCaps_CAC) && data->cac_enabled) { + int smc_result = smum_send_msg_to_smc(hwmgr, (uint16_t)(PPSMC_MSG_DisableCac)); PP_ASSERT_WITH_CODE((smc_result == 0), "Failed to disable CAC in SMC.", result = -1); @@ -872,7 +859,7 @@ int smu7_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n) if (data->power_containment_features & POWERCONTAINMENT_FEATURE_PkgPwrLimit) - return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + return smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_PkgPwrSetLimit, n); return 0; } @@ -880,7 +867,7 @@ int smu7_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n) static int smu7_set_overdriver_target_tdp(struct pp_hwmgr *hwmgr, uint32_t target_tdp) { - return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + return smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_OverDriveSetTargetTdp, target_tdp); } @@ -899,11 +886,9 @@ int smu7_enable_power_containment(struct pp_hwmgr *hwmgr) else cac_table = hwmgr->dyn_state.cac_dtp_table; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerContainment)) { - + if (PP_CAP(PHM_PlatformCaps_PowerContainment)) { if (data->enable_tdc_limit_feature) { - smc_result = smum_send_msg_to_smc(hwmgr->smumgr, + smc_result = smum_send_msg_to_smc(hwmgr, (uint16_t)(PPSMC_MSG_TDCLimitEnable)); PP_ASSERT_WITH_CODE((0 == smc_result), "Failed to enable TDCLimit in SMC.", result = -1;); @@ -913,14 +898,13 @@ int smu7_enable_power_containment(struct pp_hwmgr *hwmgr) } if (data->enable_pkg_pwr_tracking_feature) { - smc_result = smum_send_msg_to_smc(hwmgr->smumgr, + smc_result = smum_send_msg_to_smc(hwmgr, (uint16_t)(PPSMC_MSG_PkgPwrLimitEnable)); PP_ASSERT_WITH_CODE((0 == smc_result), "Failed to enable PkgPwrTracking in SMC.", result = -1;); if (0 == smc_result) { uint32_t default_limit = (uint32_t)(cac_table->usMaximumPowerDeliveryLimit * 256); - data->power_containment_features |= POWERCONTAINMENT_FEATURE_PkgPwrLimit; @@ -937,14 +921,13 @@ int smu7_disable_power_containment(struct pp_hwmgr *hwmgr) struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); int result = 0; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerContainment) && - data->power_containment_features) { + if (PP_CAP(PHM_PlatformCaps_PowerContainment) && + data->power_containment_features) { int smc_result; if (data->power_containment_features & POWERCONTAINMENT_FEATURE_TDCLimit) { - smc_result = smum_send_msg_to_smc(hwmgr->smumgr, + smc_result = smum_send_msg_to_smc(hwmgr, (uint16_t)(PPSMC_MSG_TDCLimitDisable)); PP_ASSERT_WITH_CODE((smc_result == 0), "Failed to disable TDCLimit in SMC.", @@ -953,7 +936,7 @@ int smu7_disable_power_containment(struct pp_hwmgr *hwmgr) if (data->power_containment_features & POWERCONTAINMENT_FEATURE_DTE) { - smc_result = smum_send_msg_to_smc(hwmgr->smumgr, + smc_result = smum_send_msg_to_smc(hwmgr, (uint16_t)(PPSMC_MSG_DisableDTE)); PP_ASSERT_WITH_CODE((smc_result == 0), "Failed to disable DTE in SMC.", @@ -962,7 +945,7 @@ int smu7_disable_power_containment(struct pp_hwmgr *hwmgr) if (data->power_containment_features & POWERCONTAINMENT_FEATURE_PkgPwrLimit) { - smc_result = smum_send_msg_to_smc(hwmgr->smumgr, + smc_result = smum_send_msg_to_smc(hwmgr, (uint16_t)(PPSMC_MSG_PkgPwrLimitDisable)); PP_ASSERT_WITH_CODE((smc_result == 0), "Failed to disable PkgPwrTracking in SMC.", @@ -987,16 +970,17 @@ int smu7_power_control_set_level(struct pp_hwmgr *hwmgr) cac_table = table_info->cac_dtp_table; else cac_table = hwmgr->dyn_state.cac_dtp_table; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerContainment)) { + if (PP_CAP(PHM_PlatformCaps_PowerContainment)) { /* adjustment percentage has already been validated */ adjust_percent = hwmgr->platform_descriptor.TDPAdjustmentPolarity ? hwmgr->platform_descriptor.TDPAdjustment : (-1 * hwmgr->platform_descriptor.TDPAdjustment); - /* SMC requested that target_tdp to be 7 bit fraction in DPM table - * but message to be 8 bit fraction for messages - */ - target_tdp = ((100 + adjust_percent) * (int)(cac_table->usTDP * 256)) / 100; + + if (hwmgr->chip_id > CHIP_TONGA) + target_tdp = ((100 + adjust_percent) * (int)(cac_table->usTDP * 256)) / 100; + else + target_tdp = ((100 + adjust_percent) * (int)(cac_table->usConfigurableTDP * 256)) / 100; + result = smu7_set_overdriver_target_tdp(hwmgr, (uint32_t)target_tdp); } diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.c index baddb56..d7aa643 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.c @@ -37,9 +37,8 @@ int smu7_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, fan_speed_info->min_percent = 0; fan_speed_info->max_percent = 100; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_FanSpeedInTableIsRPM) && - hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution) { + if (PP_CAP(PHM_PlatformCaps_FanSpeedInTableIsRPM) && + hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution) { fan_speed_info->supports_rpm_read = true; fan_speed_info->supports_rpm_write = true; fan_speed_info->min_rpm = hwmgr->thermal_controller.fanInfo.ulMinRPM; @@ -87,8 +86,7 @@ int smu7_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed) uint32_t crystal_clock_freq; if (hwmgr->thermal_controller.fanInfo.bNoFan || - (hwmgr->thermal_controller.fanInfo. - ucTachometerPulsesPerRevolution == 0)) + !hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution) return -ENODEV; tach_period = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, @@ -152,13 +150,11 @@ int smu7_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr) { int result; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ODFuzzyFanControlSupport)) { + if (PP_CAP(PHM_PlatformCaps_ODFuzzyFanControlSupport)) { cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, FAN_CONTROL_FUZZY); - result = smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_StartFanControl); + result = smum_send_msg_to_smc(hwmgr, PPSMC_StartFanControl); - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_FanSpeedInTableIsRPM)) + if (PP_CAP(PHM_PlatformCaps_FanSpeedInTableIsRPM)) hwmgr->hwmgr_func->set_max_fan_rpm_output(hwmgr, hwmgr->thermal_controller. advanceFanControlParameters.usMaxFanRPM); @@ -169,12 +165,12 @@ int smu7_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr) } else { cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, FAN_CONTROL_TABLE); - result = smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_StartFanControl); + result = smum_send_msg_to_smc(hwmgr, PPSMC_StartFanControl); } if (!result && hwmgr->thermal_controller. advanceFanControlParameters.ucTargetTemperature) - result = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + result = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetFanTemperatureTarget, hwmgr->thermal_controller. advanceFanControlParameters.ucTargetTemperature); @@ -187,7 +183,7 @@ int smu7_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr) int smu7_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr) { hwmgr->fan_ctrl_enabled = false; - return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_StopFanControl); + return smum_send_msg_to_smc(hwmgr, PPSMC_StopFanControl); } /** @@ -209,8 +205,7 @@ int smu7_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, if (speed > 100) speed = 100; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl)) + if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) smu7_fan_ctrl_stop_smc_fan_control(hwmgr); duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, @@ -241,8 +236,7 @@ int smu7_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr) if (hwmgr->thermal_controller.fanInfo.bNoFan) return 0; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl)) { + if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) { result = smu7_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC); if (!result) result = smu7_fan_ctrl_start_smc_fan_control(hwmgr); @@ -270,8 +264,7 @@ int smu7_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed) (speed > hwmgr->thermal_controller.fanInfo.ulMaxRPM)) return 0; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl)) + if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) smu7_fan_ctrl_stop_smc_fan_control(hwmgr); crystal_clock_freq = smu7_get_xclk(hwmgr); @@ -367,7 +360,7 @@ static int smu7_thermal_initialize(struct pp_hwmgr *hwmgr) * * @param hwmgr The address of the hardware manager. */ -int smu7_thermal_enable_alert(struct pp_hwmgr *hwmgr) +static void smu7_thermal_enable_alert(struct pp_hwmgr *hwmgr) { uint32_t alert; @@ -378,7 +371,7 @@ int smu7_thermal_enable_alert(struct pp_hwmgr *hwmgr) CG_THERMAL_INT, THERM_INT_MASK, alert); /* send message to SMU to enable internal thermal interrupts */ - return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_Thermal_Cntl_Enable); + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_Thermal_Cntl_Enable); } /** @@ -396,7 +389,7 @@ int smu7_thermal_disable_alert(struct pp_hwmgr *hwmgr) CG_THERMAL_INT, THERM_INT_MASK, alert); /* send message to SMU to disable internal thermal interrupts */ - return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_Thermal_Cntl_Disable); + return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_Thermal_Cntl_Disable); } /** @@ -423,16 +416,14 @@ int smu7_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr) * @param Result the last failure code * @return result from set temperature range routine */ -static int tf_smu7_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr, - void *input, void *output, void *storage, int result) +static int smu7_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr) { /* If the fantable setup has failed we could have disabled * PHM_PlatformCaps_MicrocodeFanControl even after * this function was included in the table. * Make sure that we still think controlling the fan is OK. */ - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl)) { + if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) { smu7_fan_ctrl_start_smc_fan_control(hwmgr); smu7_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC); } @@ -440,108 +431,34 @@ static int tf_smu7_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr, return 0; } -/** -* Set temperature range for high and low alerts -* @param hwmgr the address of the powerplay hardware manager. -* @param pInput the pointer to input data -* @param pOutput the pointer to output data -* @param pStorage the pointer to temporary storage -* @param Result the last failure code -* @return result from set temperature range routine -*/ -static int tf_smu7_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, - void *input, void *output, void *storage, int result) +int smu7_start_thermal_controller(struct pp_hwmgr *hwmgr, + struct PP_TemperatureRange *range) { - struct PP_TemperatureRange *range = (struct PP_TemperatureRange *)input; + int ret = 0; if (range == NULL) return -EINVAL; - return smu7_thermal_set_temperature_range(hwmgr, range->min, range->max); -} - -/** -* Programs one-time setting registers -* @param hwmgr the address of the powerplay hardware manager. -* @param pInput the pointer to input data -* @param pOutput the pointer to output data -* @param pStorage the pointer to temporary storage -* @param Result the last failure code -* @return result from initialize thermal controller routine -*/ -static int tf_smu7_thermal_initialize(struct pp_hwmgr *hwmgr, - void *input, void *output, void *storage, int result) -{ - return smu7_thermal_initialize(hwmgr); -} - -/** -* Enable high and low alerts -* @param hwmgr the address of the powerplay hardware manager. -* @param pInput the pointer to input data -* @param pOutput the pointer to output data -* @param pStorage the pointer to temporary storage -* @param Result the last failure code -* @return result from enable alert routine -*/ -static int tf_smu7_thermal_enable_alert(struct pp_hwmgr *hwmgr, - void *input, void *output, void *storage, int result) -{ - return smu7_thermal_enable_alert(hwmgr); -} - -/** -* Disable high and low alerts -* @param hwmgr the address of the powerplay hardware manager. -* @param pInput the pointer to input data -* @param pOutput the pointer to output data -* @param pStorage the pointer to temporary storage -* @param Result the last failure code -* @return result from disable alert routine -*/ -static int tf_smu7_thermal_disable_alert(struct pp_hwmgr *hwmgr, - void *input, void *output, void *storage, int result) -{ - return smu7_thermal_disable_alert(hwmgr); -} + smu7_thermal_initialize(hwmgr); + ret = smu7_thermal_set_temperature_range(hwmgr, range->min, range->max); + if (ret) + return -EINVAL; + smu7_thermal_enable_alert(hwmgr); + ret = smum_thermal_avfs_enable(hwmgr); + if (ret) + return -EINVAL; -static const struct phm_master_table_item -phm_thermal_start_thermal_controller_master_list[] = { - { .tableFunction = tf_smu7_thermal_initialize }, - { .tableFunction = tf_smu7_thermal_set_temperature_range }, - { .tableFunction = tf_smu7_thermal_enable_alert }, - { .tableFunction = smum_thermal_avfs_enable }, /* We should restrict performance levels to low before we halt the SMC. * On the other hand we are still in boot state when we do this * so it would be pointless. * If this assumption changes we have to revisit this table. */ - { .tableFunction = smum_thermal_setup_fan_table }, - { .tableFunction = tf_smu7_thermal_start_smc_fan_control }, - { } -}; - -static const struct phm_master_table_header -phm_thermal_start_thermal_controller_master = { - 0, - PHM_MasterTableFlag_None, - phm_thermal_start_thermal_controller_master_list -}; - -static const struct phm_master_table_item -phm_thermal_set_temperature_range_master_list[] = { - { .tableFunction = tf_smu7_thermal_disable_alert }, - { .tableFunction = tf_smu7_thermal_set_temperature_range }, - { .tableFunction = tf_smu7_thermal_enable_alert }, - { } -}; - -static const struct phm_master_table_header -phm_thermal_set_temperature_range_master = { - 0, - PHM_MasterTableFlag_None, - phm_thermal_set_temperature_range_master_list -}; + smum_thermal_setup_fan_table(hwmgr); + smu7_thermal_start_smc_fan_control(hwmgr); + return 0; +} + + int smu7_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr) { @@ -550,35 +467,3 @@ int smu7_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr) return 0; } -/** -* Initializes the thermal controller related functions in the Hardware Manager structure. -* @param hwmgr The address of the hardware manager. -* @exception Any error code from the low-level communication. -*/ -int pp_smu7_thermal_initialize(struct pp_hwmgr *hwmgr) -{ - int result; - - result = phm_construct_table(hwmgr, - &phm_thermal_set_temperature_range_master, - &(hwmgr->set_temperature_range)); - - if (!result) { - result = phm_construct_table(hwmgr, - &phm_thermal_start_thermal_controller_master, - &(hwmgr->start_thermal_controller)); - if (result) - phm_destroy_table(hwmgr, &(hwmgr->set_temperature_range)); - } - - if (!result) - hwmgr->fan_ctrl_is_in_default_mode = true; - return result; -} - -void pp_smu7_thermal_fini(struct pp_hwmgr *hwmgr) -{ - phm_destroy_table(hwmgr, &(hwmgr->set_temperature_range)); - phm_destroy_table(hwmgr, &(hwmgr->start_thermal_controller)); - return; -}
\ No newline at end of file diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.h b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.h index ba71b60..42c1ba0 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.h @@ -46,14 +46,13 @@ extern int smu7_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr); extern int smu7_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode); extern int smu7_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, uint32_t speed); extern int smu7_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr); -extern int pp_smu7_thermal_initialize(struct pp_hwmgr *hwmgr); -extern void pp_smu7_thermal_fini(struct pp_hwmgr *hwmgr); extern int smu7_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr); extern int smu7_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed); extern int smu7_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed); extern int smu7_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr); -extern int smu7_thermal_enable_alert(struct pp_hwmgr *hwmgr); extern int smu7_thermal_disable_alert(struct pp_hwmgr *hwmgr); extern int smu7_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr); +extern int smu7_start_thermal_controller(struct pp_hwmgr *hwmgr, + struct PP_TemperatureRange *temperature_range); #endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c index f8f02e7..a59d282 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c @@ -201,9 +201,6 @@ static int vega10_set_features_platform_caps(struct pp_hwmgr *hwmgr) PHM_PlatformCaps_ControlVDDCI); phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TablelessHardwareInterface); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_EnableSMU7ThermalManagement); sys_info.size = sizeof(struct cgs_system_info); @@ -381,12 +378,10 @@ static void vega10_init_dpm_defaults(struct pp_hwmgr *hwmgr) if (!data->registry_data.socclk_dpm_key_disabled) data->smu_features[GNLD_DPM_SOCCLK].supported = true; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_UVDDPM)) + if (PP_CAP(PHM_PlatformCaps_UVDDPM)) data->smu_features[GNLD_DPM_UVD].supported = true; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_VCEDPM)) + if (PP_CAP(PHM_PlatformCaps_VCEDPM)) data->smu_features[GNLD_DPM_VCE].supported = true; if (!data->registry_data.pcie_dpm_key_disabled) @@ -395,9 +390,8 @@ static void vega10_init_dpm_defaults(struct pp_hwmgr *hwmgr) if (!data->registry_data.dcefclk_dpm_key_disabled) data->smu_features[GNLD_DPM_DCEFCLK].supported = true; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SclkDeepSleep) && - data->registry_data.sclk_deep_sleep_support) { + if (PP_CAP(PHM_PlatformCaps_SclkDeepSleep) && + data->registry_data.sclk_deep_sleep_support) { data->smu_features[GNLD_DS_GFXCLK].supported = true; data->smu_features[GNLD_DS_SOCCLK].supported = true; data->smu_features[GNLD_DS_LCLK].supported = true; @@ -431,8 +425,8 @@ static void vega10_init_dpm_defaults(struct pp_hwmgr *hwmgr) if (data->registry_data.vr0hot_enabled) data->smu_features[GNLD_VR0HOT].supported = true; - smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_GetSmuVersion); - vega10_read_arg_from_smc(hwmgr->smumgr, &(data->smu_version)); + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetSmuVersion); + vega10_read_arg_from_smc(hwmgr, &(data->smu_version)); /* ACG firmware has major version 5 */ if ((data->smu_version & 0xff000000) == 0x5000000) data->smu_features[GNLD_ACG].supported = true; @@ -497,8 +491,7 @@ static int vega10_get_evv_voltages(struct pp_hwmgr *hwmgr) if (!vega10_get_socclk_for_voltage_evv(hwmgr, table_info->vddc_lookup_table, vv_id, &sclk)) { - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ClockStretcher)) { + if (PP_CAP(PHM_PlatformCaps_ClockStretcher)) { for (j = 1; j < socclk_table->count; j++) { if (socclk_table->entries[j].clk == sclk && socclk_table->entries[j].cks_enable == 0) { @@ -591,61 +584,37 @@ static int vega10_patch_clock_voltage_limits_with_vddc_leakage( static int vega10_patch_voltage_dependency_tables_with_lookup_table( struct pp_hwmgr *hwmgr) { - uint8_t entry_id; - uint8_t voltage_id; + uint8_t entry_id, voltage_id; + unsigned i; struct phm_ppt_v2_information *table_info = (struct phm_ppt_v2_information *)(hwmgr->pptable); - struct phm_ppt_v1_clock_voltage_dependency_table *socclk_table = - table_info->vdd_dep_on_socclk; - struct phm_ppt_v1_clock_voltage_dependency_table *gfxclk_table = - table_info->vdd_dep_on_sclk; - struct phm_ppt_v1_clock_voltage_dependency_table *dcefclk_table = - table_info->vdd_dep_on_dcefclk; - struct phm_ppt_v1_clock_voltage_dependency_table *pixclk_table = - table_info->vdd_dep_on_pixclk; - struct phm_ppt_v1_clock_voltage_dependency_table *dspclk_table = - table_info->vdd_dep_on_dispclk; - struct phm_ppt_v1_clock_voltage_dependency_table *phyclk_table = - table_info->vdd_dep_on_phyclk; - struct phm_ppt_v1_clock_voltage_dependency_table *mclk_table = - table_info->vdd_dep_on_mclk; struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = table_info->mm_dep_table; + struct phm_ppt_v1_clock_voltage_dependency_table *mclk_table = + table_info->vdd_dep_on_mclk; - for (entry_id = 0; entry_id < socclk_table->count; entry_id++) { - voltage_id = socclk_table->entries[entry_id].vddInd; - socclk_table->entries[entry_id].vddc = - table_info->vddc_lookup_table->entries[voltage_id].us_vdd; - } - - for (entry_id = 0; entry_id < gfxclk_table->count; entry_id++) { - voltage_id = gfxclk_table->entries[entry_id].vddInd; - gfxclk_table->entries[entry_id].vddc = - table_info->vddc_lookup_table->entries[voltage_id].us_vdd; - } - - for (entry_id = 0; entry_id < dcefclk_table->count; entry_id++) { - voltage_id = dcefclk_table->entries[entry_id].vddInd; - dcefclk_table->entries[entry_id].vddc = - table_info->vddc_lookup_table->entries[voltage_id].us_vdd; - } - - for (entry_id = 0; entry_id < pixclk_table->count; entry_id++) { - voltage_id = pixclk_table->entries[entry_id].vddInd; - pixclk_table->entries[entry_id].vddc = - table_info->vddc_lookup_table->entries[voltage_id].us_vdd; - } + for (i = 0; i < 6; i++) { + struct phm_ppt_v1_clock_voltage_dependency_table *vdt; + switch (i) { + case 0: vdt = table_info->vdd_dep_on_socclk; break; + case 1: vdt = table_info->vdd_dep_on_sclk; break; + case 2: vdt = table_info->vdd_dep_on_dcefclk; break; + case 3: vdt = table_info->vdd_dep_on_pixclk; break; + case 4: vdt = table_info->vdd_dep_on_dispclk; break; + case 5: vdt = table_info->vdd_dep_on_phyclk; break; + } - for (entry_id = 0; entry_id < dspclk_table->count; entry_id++) { - voltage_id = dspclk_table->entries[entry_id].vddInd; - dspclk_table->entries[entry_id].vddc = - table_info->vddc_lookup_table->entries[voltage_id].us_vdd; + for (entry_id = 0; entry_id < vdt->count; entry_id++) { + voltage_id = vdt->entries[entry_id].vddInd; + vdt->entries[entry_id].vddc = + table_info->vddc_lookup_table->entries[voltage_id].us_vdd; + } } - for (entry_id = 0; entry_id < phyclk_table->count; entry_id++) { - voltage_id = phyclk_table->entries[entry_id].vddInd; - phyclk_table->entries[entry_id].vddc = - table_info->vddc_lookup_table->entries[voltage_id].us_vdd; + for (entry_id = 0; entry_id < mm_table->count; ++entry_id) { + voltage_id = mm_table->entries[entry_id].vddcInd; + mm_table->entries[entry_id].vddc = + table_info->vddc_lookup_table->entries[voltage_id].us_vdd; } for (entry_id = 0; entry_id < mclk_table->count; ++entry_id) { @@ -660,11 +629,6 @@ static int vega10_patch_voltage_dependency_tables_with_lookup_table( table_info->vddmem_lookup_table->entries[voltage_id].us_vdd; } - for (entry_id = 0; entry_id < mm_table->count; ++entry_id) { - voltage_id = mm_table->entries[entry_id].vddcInd; - mm_table->entries[entry_id].vddc = - table_info->vddc_lookup_table->entries[voltage_id].us_vdd; - } return 0; @@ -838,8 +802,7 @@ static int vega10_hwmgr_backend_init(struct pp_hwmgr *hwmgr) } /* VDDCI_MEM */ - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ControlVDDCI)) { + if (PP_CAP(PHM_PlatformCaps_ControlVDDCI)) { if (pp_atomfwctrl_is_voltage_controlled_by_gpio_v4(hwmgr, VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_GPIO_LUT)) data->vddci_control = VEGA10_VOLTAGE_CONTROL_BY_GPIO; @@ -959,7 +922,7 @@ static bool vega10_is_dpm_running(struct pp_hwmgr *hwmgr) { uint32_t features_enabled; - if (!vega10_get_smc_features(hwmgr->smumgr, &features_enabled)) { + if (!vega10_get_smc_features(hwmgr, &features_enabled)) { if (features_enabled & SMC_DPM_FEATURES) return true; } @@ -1411,10 +1374,8 @@ static int vega10_setup_default_dpm_tables(struct pp_hwmgr *hwmgr) memcpy(&(data->golden_dpm_table), &(data->dpm_table), sizeof(struct vega10_dpm_table)); - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ODNinACSupport) || - phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ODNinDCSupport)) { + if (PP_CAP(PHM_PlatformCaps_ODNinACSupport) || + PP_CAP(PHM_PlatformCaps_ODNinDCSupport)) { data->odn_dpm_table.odn_core_clock_dpm_levels. number_of_performance_levels = data->dpm_table.gfx_table.count; for (i = 0; i < data->dpm_table.gfx_table.count; i++) { @@ -2311,21 +2272,21 @@ static int vega10_acg_enable(struct pp_hwmgr *hwmgr) uint32_t agc_btc_response; if (data->smu_features[GNLD_ACG].supported) { - if (0 == vega10_enable_smc_features(hwmgr->smumgr, true, + if (0 == vega10_enable_smc_features(hwmgr, true, data->smu_features[GNLD_DPM_PREFETCHER].smu_feature_bitmap)) data->smu_features[GNLD_DPM_PREFETCHER].enabled = true; - smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_InitializeAcg); + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_InitializeAcg); - smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_RunAcgBtc); - vega10_read_arg_from_smc(hwmgr->smumgr, &agc_btc_response); + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAcgBtc); + vega10_read_arg_from_smc(hwmgr, &agc_btc_response); if (1 == agc_btc_response) { if (1 == data->acg_loop_state) - smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_RunAcgInClosedLoop); + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAcgInClosedLoop); else if (2 == data->acg_loop_state) - smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_RunAcgInOpenLoop); - if (0 == vega10_enable_smc_features(hwmgr->smumgr, true, + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAcgInOpenLoop); + if (0 == vega10_enable_smc_features(hwmgr, true, data->smu_features[GNLD_ACG].smu_feature_bitmap)) data->smu_features[GNLD_ACG].enabled = true; } else { @@ -2342,13 +2303,11 @@ static int vega10_acg_disable(struct pp_hwmgr *hwmgr) struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend); - if (data->smu_features[GNLD_ACG].supported) { - if (data->smu_features[GNLD_ACG].enabled) { - if (0 == vega10_enable_smc_features(hwmgr->smumgr, false, - data->smu_features[GNLD_ACG].smu_feature_bitmap)) + if (data->smu_features[GNLD_ACG].supported && + data->smu_features[GNLD_ACG].enabled) + if (!vega10_enable_smc_features(hwmgr, false, + data->smu_features[GNLD_ACG].smu_feature_bitmap)) data->smu_features[GNLD_ACG].enabled = false; - } - } return 0; } @@ -2363,9 +2322,8 @@ static int vega10_populate_gpio_parameters(struct pp_hwmgr *hwmgr) result = pp_atomfwctrl_get_gpio_information(hwmgr, &gpio_params); if (!result) { - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_RegulatorHot) && - (data->registry_data.regulator_hot_gpio_support)) { + if (PP_CAP(PHM_PlatformCaps_RegulatorHot) && + data->registry_data.regulator_hot_gpio_support) { pp_table->VR0HotGpio = gpio_params.ucVR0HotGpio; pp_table->VR0HotPolarity = gpio_params.ucVR0HotPolarity; pp_table->VR1HotGpio = gpio_params.ucVR1HotGpio; @@ -2377,9 +2335,8 @@ static int vega10_populate_gpio_parameters(struct pp_hwmgr *hwmgr) pp_table->VR1HotPolarity = 0; } - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition) && - (data->registry_data.ac_dc_switch_gpio_support)) { + if (PP_CAP(PHM_PlatformCaps_AutomaticDCTransition) && + data->registry_data.ac_dc_switch_gpio_support) { pp_table->AcDcGpio = gpio_params.ucAcDcGpio; pp_table->AcDcPolarity = gpio_params.ucAcDcPolarity; } else { @@ -2398,14 +2355,14 @@ static int vega10_avfs_enable(struct pp_hwmgr *hwmgr, bool enable) if (data->smu_features[GNLD_AVFS].supported) { if (enable) { - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, true, data->smu_features[GNLD_AVFS].smu_feature_bitmap), "[avfs_control] Attempt to Enable AVFS feature Failed!", return -1); data->smu_features[GNLD_AVFS].enabled = true; } else { - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, false, data->smu_features[GNLD_AVFS].smu_feature_id), "[avfs_control] Attempt to Disable AVFS feature Failed!", @@ -2428,11 +2385,11 @@ static int vega10_populate_and_upload_avfs_fuse_override(struct pp_hwmgr *hwmgr) struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend); AvfsFuseOverride_t *avfs_fuse_table = &(data->smc_state_table.avfs_fuse_override_table); - smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_ReadSerialNumTop32); - vega10_read_arg_from_smc(hwmgr->smumgr, &top32); + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumTop32); + vega10_read_arg_from_smc(hwmgr, &top32); - smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_ReadSerialNumBottom32); - vega10_read_arg_from_smc(hwmgr->smumgr, &bottom32); + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumBottom32); + vega10_read_arg_from_smc(hwmgr, &bottom32); serial_number = ((uint64_t)bottom32 << 32) | top32; @@ -2446,7 +2403,7 @@ static int vega10_populate_and_upload_avfs_fuse_override(struct pp_hwmgr *hwmgr) avfs_fuse_table->VFT2_b = fuse.VFT2_b; avfs_fuse_table->VFT2_m1 = fuse.VFT2_m1; avfs_fuse_table->VFT2_m2 = fuse.VFT2_m2; - result = vega10_copy_table_to_smc(hwmgr->smumgr, + result = vega10_copy_table_to_smc(hwmgr, (uint8_t *)avfs_fuse_table, AVFSFUSETABLE); PP_ASSERT_WITH_CODE(!result, "Failed to upload FuseOVerride!", @@ -2585,14 +2542,14 @@ static int vega10_init_smc_table(struct pp_hwmgr *hwmgr) data->vbios_boot_state.soc_clock = boot_up_values.ulSocClk; data->vbios_boot_state.dcef_clock = boot_up_values.ulDCEFClk; if (0 != boot_up_values.usVddc) { - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetFloorSocVoltage, (boot_up_values.usVddc * 4)); data->vbios_boot_state.bsoc_vddc_lock = true; } else { data->vbios_boot_state.bsoc_vddc_lock = false; } - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetMinDeepSleepDcefclk, (uint32_t)(data->vbios_boot_state.dcef_clock / 100)); } @@ -2618,7 +2575,7 @@ static int vega10_init_smc_table(struct pp_hwmgr *hwmgr) vega10_populate_and_upload_avfs_fuse_override(hwmgr); - result = vega10_copy_table_to_smc(hwmgr->smumgr, + result = vega10_copy_table_to_smc(hwmgr, (uint8_t *)pp_table, PPTABLE); PP_ASSERT_WITH_CODE(!result, "Failed to upload PPtable!", return result); @@ -2641,7 +2598,7 @@ static int vega10_enable_thermal_protection(struct pp_hwmgr *hwmgr) pr_info("THERMAL Feature Already enabled!"); PP_ASSERT_WITH_CODE( - !vega10_enable_smc_features(hwmgr->smumgr, + !vega10_enable_smc_features(hwmgr, true, data->smu_features[GNLD_THERMAL].smu_feature_bitmap), "Enable THERMAL Feature Failed!", @@ -2661,7 +2618,7 @@ static int vega10_disable_thermal_protection(struct pp_hwmgr *hwmgr) pr_info("THERMAL Feature Already disabled!"); PP_ASSERT_WITH_CODE( - !vega10_enable_smc_features(hwmgr->smumgr, + !vega10_enable_smc_features(hwmgr, false, data->smu_features[GNLD_THERMAL].smu_feature_bitmap), "disable THERMAL Feature Failed!", @@ -2677,11 +2634,10 @@ static int vega10_enable_vrhot_feature(struct pp_hwmgr *hwmgr) struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend); - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_RegulatorHot)) { + if (PP_CAP(PHM_PlatformCaps_RegulatorHot)) { if (data->smu_features[GNLD_VR0HOT].supported) { PP_ASSERT_WITH_CODE( - !vega10_enable_smc_features(hwmgr->smumgr, + !vega10_enable_smc_features(hwmgr, true, data->smu_features[GNLD_VR0HOT].smu_feature_bitmap), "Attempt to Enable VR0 Hot feature Failed!", @@ -2690,7 +2646,7 @@ static int vega10_enable_vrhot_feature(struct pp_hwmgr *hwmgr) } else { if (data->smu_features[GNLD_VR1HOT].supported) { PP_ASSERT_WITH_CODE( - !vega10_enable_smc_features(hwmgr->smumgr, + !vega10_enable_smc_features(hwmgr, true, data->smu_features[GNLD_VR1HOT].smu_feature_bitmap), "Attempt to Enable VR0 Hot feature Failed!", @@ -2708,7 +2664,7 @@ static int vega10_enable_ulv(struct pp_hwmgr *hwmgr) (struct vega10_hwmgr *)(hwmgr->backend); if (data->registry_data.ulv_support) { - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, true, data->smu_features[GNLD_ULV].smu_feature_bitmap), "Enable ULV Feature Failed!", return -1); @@ -2724,7 +2680,7 @@ static int vega10_disable_ulv(struct pp_hwmgr *hwmgr) (struct vega10_hwmgr *)(hwmgr->backend); if (data->registry_data.ulv_support) { - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, false, data->smu_features[GNLD_ULV].smu_feature_bitmap), "disable ULV Feature Failed!", return -EINVAL); @@ -2740,7 +2696,7 @@ static int vega10_enable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr) (struct vega10_hwmgr *)(hwmgr->backend); if (data->smu_features[GNLD_DS_GFXCLK].supported) { - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, true, data->smu_features[GNLD_DS_GFXCLK].smu_feature_bitmap), "Attempt to Enable DS_GFXCLK Feature Failed!", return -EINVAL); @@ -2748,7 +2704,7 @@ static int vega10_enable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr) } if (data->smu_features[GNLD_DS_SOCCLK].supported) { - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, true, data->smu_features[GNLD_DS_SOCCLK].smu_feature_bitmap), "Attempt to Enable DS_SOCCLK Feature Failed!", return -EINVAL); @@ -2756,7 +2712,7 @@ static int vega10_enable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr) } if (data->smu_features[GNLD_DS_LCLK].supported) { - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, true, data->smu_features[GNLD_DS_LCLK].smu_feature_bitmap), "Attempt to Enable DS_LCLK Feature Failed!", return -EINVAL); @@ -2764,7 +2720,7 @@ static int vega10_enable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr) } if (data->smu_features[GNLD_DS_DCEFCLK].supported) { - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, true, data->smu_features[GNLD_DS_DCEFCLK].smu_feature_bitmap), "Attempt to Enable DS_DCEFCLK Feature Failed!", return -EINVAL); @@ -2780,7 +2736,7 @@ static int vega10_disable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr) (struct vega10_hwmgr *)(hwmgr->backend); if (data->smu_features[GNLD_DS_GFXCLK].supported) { - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, false, data->smu_features[GNLD_DS_GFXCLK].smu_feature_bitmap), "Attempt to disable DS_GFXCLK Feature Failed!", return -EINVAL); @@ -2788,7 +2744,7 @@ static int vega10_disable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr) } if (data->smu_features[GNLD_DS_SOCCLK].supported) { - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, false, data->smu_features[GNLD_DS_SOCCLK].smu_feature_bitmap), "Attempt to disable DS_ Feature Failed!", return -EINVAL); @@ -2796,7 +2752,7 @@ static int vega10_disable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr) } if (data->smu_features[GNLD_DS_LCLK].supported) { - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, false, data->smu_features[GNLD_DS_LCLK].smu_feature_bitmap), "Attempt to disable DS_LCLK Feature Failed!", return -EINVAL); @@ -2804,7 +2760,7 @@ static int vega10_disable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr) } if (data->smu_features[GNLD_DS_DCEFCLK].supported) { - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, false, data->smu_features[GNLD_DS_DCEFCLK].smu_feature_bitmap), "Attempt to disable DS_DCEFCLK Feature Failed!", return -EINVAL); @@ -2822,7 +2778,7 @@ static int vega10_stop_dpm(struct pp_hwmgr *hwmgr, uint32_t bitmap) if(data->smu_features[GNLD_LED_DISPLAY].supported == true){ - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, false, data->smu_features[GNLD_LED_DISPLAY].smu_feature_bitmap), "Attempt to disable LED DPM feature failed!", return -EINVAL); data->smu_features[GNLD_LED_DISPLAY].enabled = false; @@ -2840,7 +2796,7 @@ static int vega10_stop_dpm(struct pp_hwmgr *hwmgr, uint32_t bitmap) } } - vega10_enable_smc_features(hwmgr->smumgr, false, feature_mask); + vega10_enable_smc_features(hwmgr, false, feature_mask); return 0; } @@ -2870,7 +2826,7 @@ static int vega10_start_dpm(struct pp_hwmgr *hwmgr, uint32_t bitmap) } } - if (vega10_enable_smc_features(hwmgr->smumgr, + if (vega10_enable_smc_features(hwmgr, true, feature_mask)) { for (i = 0; i < GNLD_DPM_MAX; i++) { if (data->smu_features[i].smu_feature_bitmap & @@ -2880,22 +2836,21 @@ static int vega10_start_dpm(struct pp_hwmgr *hwmgr, uint32_t bitmap) } if(data->smu_features[GNLD_LED_DISPLAY].supported == true){ - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, true, data->smu_features[GNLD_LED_DISPLAY].smu_feature_bitmap), "Attempt to Enable LED DPM feature Failed!", return -EINVAL); data->smu_features[GNLD_LED_DISPLAY].enabled = true; } if (data->vbios_boot_state.bsoc_vddc_lock) { - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetFloorSocVoltage, 0); data->vbios_boot_state.bsoc_vddc_lock = false; } - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_Falcon_QuickTransition)) { + if (PP_CAP(PHM_PlatformCaps_Falcon_QuickTransition)) { if (data->smu_features[GNLD_ACDC].supported) { - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, true, data->smu_features[GNLD_ACDC].smu_feature_bitmap), "Attempt to Enable DS_GFXCLK Feature Failed!", return -1); @@ -2912,13 +2867,13 @@ static int vega10_enable_dpm_tasks(struct pp_hwmgr *hwmgr) (struct vega10_hwmgr *)(hwmgr->backend); int tmp_result, result = 0; - tmp_result = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + tmp_result = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ConfigureTelemetry, data->config_telemetry); PP_ASSERT_WITH_CODE(!tmp_result, "Failed to configure telemetry!", return tmp_result); - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_NumOfDisplays, 0); tmp_result = (!vega10_is_dpm_running(hwmgr)) ? 0 : -1; @@ -2936,8 +2891,7 @@ static int vega10_enable_dpm_tasks(struct pp_hwmgr *hwmgr) "Failed to initialize SMC table!", result = tmp_result); - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ThermalController)) { + if (PP_CAP(PHM_PlatformCaps_ThermalController)) { tmp_result = vega10_enable_thermal_protection(hwmgr); PP_ASSERT_WITH_CODE(!tmp_result, "Failed to enable thermal protection!", @@ -3172,8 +3126,7 @@ static int vega10_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, minimum_clocks.engineClock = hwmgr->display_config.min_core_set_clock; minimum_clocks.memoryClock = hwmgr->display_config.min_mem_set_clock; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StablePState)) { + if (PP_CAP(PHM_PlatformCaps_StablePState)) { PP_ASSERT_WITH_CODE( data->registry_data.stable_pstate_sclk_dpm_percentage >= 1 && data->registry_data.stable_pstate_sclk_dpm_percentage <= 100, @@ -3238,10 +3191,8 @@ static int vega10_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, disable_mclk_switching_for_frame_lock = phm_cap_enabled( hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMclkSwitchingForFrameLock); - disable_mclk_switching_for_vr = phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DisableMclkSwitchForVR); - force_mclk_high = phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ForceMclkHigh); + disable_mclk_switching_for_vr = PP_CAP(PHM_PlatformCaps_DisableMclkSwitchForVR); + force_mclk_high = PP_CAP(PHM_PlatformCaps_ForceMclkHigh); disable_mclk_switching = (info.display_count > 1) || disable_mclk_switching_for_frame_lock || @@ -3292,8 +3243,7 @@ static int vega10_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, vega10_ps->performance_levels[1].mem_clock; } - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StablePState)) { + if (PP_CAP(PHM_PlatformCaps_StablePState)) { for (i = 0; i < vega10_ps->performance_level_count; i++) { vega10_ps->performance_levels[i].gfx_clock = stable_pstate_sclk; vega10_ps->performance_levels[i].mem_clock = stable_pstate_mclk; @@ -3325,10 +3275,8 @@ static int vega10_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, co data->need_update_dpm_table = 0; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ODNinACSupport) || - phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ODNinDCSupport)) { + if (PP_CAP(PHM_PlatformCaps_ODNinACSupport) || + PP_CAP(PHM_PlatformCaps_ODNinDCSupport)) { for (i = 0; i < sclk_table->count; i++) { if (sclk == sclk_table->dpm_levels[i].value) break; @@ -3412,10 +3360,8 @@ static int vega10_populate_and_upload_sclk_mclk_dpm_levels( uint32_t dpm_count, clock_percent; uint32_t i; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ODNinACSupport) || - phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ODNinDCSupport)) { + if (PP_CAP(PHM_PlatformCaps_ODNinACSupport) || + PP_CAP(PHM_PlatformCaps_ODNinDCSupport)) { if (!data->need_update_dpm_table && !data->apply_optimized_settings && @@ -3480,10 +3426,8 @@ static int vega10_populate_and_upload_sclk_mclk_dpm_levels( dpm_table-> gfx_table.dpm_levels[dpm_table->gfx_table.count - 1]. value = sclk; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_OD6PlusinACSupport) || - phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_OD6PlusinDCSupport)) { + if (PP_CAP(PHM_PlatformCaps_OD6PlusinACSupport) || + PP_CAP(PHM_PlatformCaps_OD6PlusinDCSupport)) { /* Need to do calculation based on the golden DPM table * as the Heatmap GPU Clock axis is also based on * the default values @@ -3537,10 +3481,8 @@ static int vega10_populate_and_upload_sclk_mclk_dpm_levels( mem_table.dpm_levels[dpm_table->mem_table.count - 1]. value = mclk; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_OD6PlusinACSupport) || - phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_OD6PlusinDCSupport)) { + if (PP_CAP(PHM_PlatformCaps_OD6PlusinACSupport) || + PP_CAP(PHM_PlatformCaps_OD6PlusinDCSupport)) { PP_ASSERT_WITH_CODE( golden_dpm_table->mem_table.dpm_levels @@ -3732,7 +3674,7 @@ static int vega10_upload_dpm_bootup_level(struct pp_hwmgr *hwmgr) if (data->smc_state_table.gfx_boot_level != data->dpm_table.gfx_table.dpm_state.soft_min_level) { PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc_with_parameter( - hwmgr->smumgr, + hwmgr, PPSMC_MSG_SetSoftMinGfxclkByIndex, data->smc_state_table.gfx_boot_level), "Failed to set soft min sclk index!", @@ -3748,14 +3690,14 @@ static int vega10_upload_dpm_bootup_level(struct pp_hwmgr *hwmgr) if (data->smc_state_table.mem_boot_level == NUM_UCLK_DPM_LEVELS - 1) { socclk_idx = vega10_get_soc_index_for_max_uclk(hwmgr); PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc_with_parameter( - hwmgr->smumgr, + hwmgr, PPSMC_MSG_SetSoftMinSocclkByIndex, socclk_idx), "Failed to set soft min uclk index!", return -EINVAL); } else { PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc_with_parameter( - hwmgr->smumgr, + hwmgr, PPSMC_MSG_SetSoftMinUclkByIndex, data->smc_state_table.mem_boot_level), "Failed to set soft min uclk index!", @@ -3780,7 +3722,7 @@ static int vega10_upload_dpm_max_level(struct pp_hwmgr *hwmgr) if (data->smc_state_table.gfx_max_level != data->dpm_table.gfx_table.dpm_state.soft_max_level) { PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc_with_parameter( - hwmgr->smumgr, + hwmgr, PPSMC_MSG_SetSoftMaxGfxclkByIndex, data->smc_state_table.gfx_max_level), "Failed to set soft max sclk index!", @@ -3794,7 +3736,7 @@ static int vega10_upload_dpm_max_level(struct pp_hwmgr *hwmgr) if (data->smc_state_table.mem_max_level != data->dpm_table.mem_table.dpm_state.soft_max_level) { PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc_with_parameter( - hwmgr->smumgr, + hwmgr, PPSMC_MSG_SetSoftMaxUclkByIndex, data->smc_state_table.mem_max_level), "Failed to set soft max mclk index!", @@ -3853,7 +3795,7 @@ int vega10_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable) (struct vega10_hwmgr *)(hwmgr->backend); if (data->smu_features[GNLD_DPM_VCE].supported) { - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, enable, data->smu_features[GNLD_DPM_VCE].smu_feature_bitmap), "Attempt to Enable/Disable DPM VCE Failed!", @@ -3871,9 +3813,8 @@ static int vega10_update_sclk_threshold(struct pp_hwmgr *hwmgr) int result = 0; uint32_t low_sclk_interrupt_threshold = 0; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SclkThrottleLowNotification) - && (hwmgr->gfx_arbiter.sclk_threshold != + if (PP_CAP(PHM_PlatformCaps_SclkThrottleLowNotification) && + (hwmgr->gfx_arbiter.sclk_threshold != data->low_sclk_interrupt_threshold)) { data->low_sclk_interrupt_threshold = hwmgr->gfx_arbiter.sclk_threshold; @@ -3884,7 +3825,7 @@ static int vega10_update_sclk_threshold(struct pp_hwmgr *hwmgr) cpu_to_le32(low_sclk_interrupt_threshold); /* This message will also enable SmcToHost Interrupt */ - result = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + result = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetLowGfxclkInterruptThreshold, (uint32_t)low_sclk_interrupt_threshold); } @@ -3920,7 +3861,7 @@ static int vega10_set_power_state_tasks(struct pp_hwmgr *hwmgr, "Failed to update SCLK threshold!", result = tmp_result); - result = vega10_copy_table_to_smc(hwmgr->smumgr, + result = vega10_copy_table_to_smc(hwmgr, (uint8_t *)pp_table, PPTABLE); PP_ASSERT_WITH_CODE(!result, "Failed to upload PPtable!", return result); @@ -3931,7 +3872,7 @@ static int vega10_set_power_state_tasks(struct pp_hwmgr *hwmgr, return 0; } -static int vega10_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low) +static uint32_t vega10_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low) { struct pp_power_state *ps; struct vega10_power_state *vega10_ps; @@ -3953,7 +3894,7 @@ static int vega10_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low) [vega10_ps->performance_level_count - 1].gfx_clock; } -static int vega10_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) +static uint32_t vega10_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) { struct pp_power_state *ps; struct vega10_power_state *vega10_ps; @@ -3980,12 +3921,12 @@ static int vega10_get_gpu_power(struct pp_hwmgr *hwmgr, { uint32_t value; - PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrPkgPwr), "Failed to get current package power!", return -EINVAL); - vega10_read_arg_from_smc(hwmgr->smumgr, &value); + vega10_read_arg_from_smc(hwmgr, &value); /* power value is an integer */ query->average_gpu_power = value << 8; @@ -4002,25 +3943,25 @@ static int vega10_read_sensor(struct pp_hwmgr *hwmgr, int idx, switch (idx) { case AMDGPU_PP_SENSOR_GFX_SCLK: - ret = smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_GetCurrentGfxclkIndex); + ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentGfxclkIndex); if (!ret) { - vega10_read_arg_from_smc(hwmgr->smumgr, &sclk_idx); + vega10_read_arg_from_smc(hwmgr, &sclk_idx); *((uint32_t *)value) = dpm_table->gfx_table.dpm_levels[sclk_idx].value; *size = 4; } break; case AMDGPU_PP_SENSOR_GFX_MCLK: - ret = smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_GetCurrentUclkIndex); + ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentUclkIndex); if (!ret) { - vega10_read_arg_from_smc(hwmgr->smumgr, &mclk_idx); + vega10_read_arg_from_smc(hwmgr, &mclk_idx); *((uint32_t *)value) = dpm_table->mem_table.dpm_levels[mclk_idx].value; *size = 4; } break; case AMDGPU_PP_SENSOR_GPU_LOAD: - ret = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_GetAverageGfxActivity, 0); + ret = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetAverageGfxActivity, 0); if (!ret) { - vega10_read_arg_from_smc(hwmgr->smumgr, &activity_percent); + vega10_read_arg_from_smc(hwmgr, &activity_percent); *((uint32_t *)value) = activity_percent > 100 ? 100 : activity_percent; *size = 4; } @@ -4055,7 +3996,7 @@ static int vega10_read_sensor(struct pp_hwmgr *hwmgr, int idx, static int vega10_notify_smc_display_change(struct pp_hwmgr *hwmgr, bool has_disp) { - return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + return smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetUclkFastSwitch, has_disp ? 0 : 1); } @@ -4090,7 +4031,7 @@ int vega10_display_clock_voltage_request(struct pp_hwmgr *hwmgr, if (!result) { clk_request = (clk_freq << 16) | clk_select; - result = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + result = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_RequestDisplayClockByFreq, clk_request); } @@ -4160,7 +4101,7 @@ static int vega10_notify_smc_display_config_after_ps_adjustment( clock_req.clock_freq_in_khz = dpm_table->dpm_levels[i].value; if (!vega10_display_clock_voltage_request(hwmgr, &clock_req)) { PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc_with_parameter( - hwmgr->smumgr, PPSMC_MSG_SetMinDeepSleepDcefclk, + hwmgr, PPSMC_MSG_SetMinDeepSleepDcefclk, min_clocks.dcefClockInSR /100), "Attempt to set divider for DCEFCLK Failed!",); } else { @@ -4172,7 +4113,7 @@ static int vega10_notify_smc_display_config_after_ps_adjustment( if (min_clocks.memoryClock != 0) { idx = vega10_get_uclk_index(hwmgr, mclk_table, min_clocks.memoryClock); - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_SetSoftMinUclkByIndex, idx); + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetSoftMinUclkByIndex, idx); data->dpm_table.mem_table.dpm_state.soft_min_level= idx; } @@ -4275,28 +4216,23 @@ static int vega10_get_profiling_clk_mask(struct pp_hwmgr *hwmgr, enum amd_dpm_fo return 0; } -static int vega10_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode) +static void vega10_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode) { - int result = 0; - switch (mode) { case AMD_FAN_CTRL_NONE: - result = vega10_fan_ctrl_set_fan_speed_percent(hwmgr, 100); + vega10_fan_ctrl_set_fan_speed_percent(hwmgr, 100); break; case AMD_FAN_CTRL_MANUAL: - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl)) - result = vega10_fan_ctrl_stop_smc_fan_control(hwmgr); + if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) + vega10_fan_ctrl_stop_smc_fan_control(hwmgr); break; case AMD_FAN_CTRL_AUTO: - result = vega10_fan_ctrl_set_static_mode(hwmgr, mode); - if (!result) - result = vega10_fan_ctrl_start_smc_fan_control(hwmgr); + if (!vega10_fan_ctrl_set_static_mode(hwmgr, mode)) + vega10_fan_ctrl_start_smc_fan_control(hwmgr); break; default: break; } - return result; } static int vega10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, @@ -4306,51 +4242,16 @@ static int vega10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, uint32_t sclk_mask = 0; uint32_t mclk_mask = 0; uint32_t soc_mask = 0; - uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | - AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | - AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | - AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; - - if (level == hwmgr->dpm_level) - return ret; - - if (!(hwmgr->dpm_level & profile_mode_mask)) { - /* enter profile mode, save current level, disable gfx cg*/ - if (level & profile_mode_mask) { - hwmgr->saved_dpm_level = hwmgr->dpm_level; - cgs_set_clockgating_state(hwmgr->device, - AMD_IP_BLOCK_TYPE_GFX, - AMD_CG_STATE_UNGATE); - } - } else { - /* exit profile mode, restore level, enable gfx cg*/ - if (!(level & profile_mode_mask)) { - if (level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT) - level = hwmgr->saved_dpm_level; - cgs_set_clockgating_state(hwmgr->device, - AMD_IP_BLOCK_TYPE_GFX, - AMD_CG_STATE_GATE); - } - } switch (level) { case AMD_DPM_FORCED_LEVEL_HIGH: ret = vega10_force_dpm_highest(hwmgr); - if (ret) - return ret; - hwmgr->dpm_level = level; break; case AMD_DPM_FORCED_LEVEL_LOW: ret = vega10_force_dpm_lowest(hwmgr); - if (ret) - return ret; - hwmgr->dpm_level = level; break; case AMD_DPM_FORCED_LEVEL_AUTO: ret = vega10_unforce_dpm_levels(hwmgr); - if (ret) - return ret; - hwmgr->dpm_level = level; break; case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: @@ -4359,27 +4260,25 @@ static int vega10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, ret = vega10_get_profiling_clk_mask(hwmgr, level, &sclk_mask, &mclk_mask, &soc_mask); if (ret) return ret; - hwmgr->dpm_level = level; vega10_force_clock_level(hwmgr, PP_SCLK, 1<<sclk_mask); vega10_force_clock_level(hwmgr, PP_MCLK, 1<<mclk_mask); break; case AMD_DPM_FORCED_LEVEL_MANUAL: - hwmgr->dpm_level = level; - break; case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: default: break; } - if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->saved_dpm_level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) - vega10_set_fan_control_mode(hwmgr, AMD_FAN_CTRL_NONE); - else if (level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->saved_dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) - vega10_set_fan_control_mode(hwmgr, AMD_FAN_CTRL_AUTO); - - return 0; + if (!ret) { + if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) + vega10_set_fan_control_mode(hwmgr, AMD_FAN_CTRL_NONE); + else if (level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) + vega10_set_fan_control_mode(hwmgr, AMD_FAN_CTRL_AUTO); + } + return ret; } -static int vega10_get_fan_control_mode(struct pp_hwmgr *hwmgr) +static uint32_t vega10_get_fan_control_mode(struct pp_hwmgr *hwmgr) { struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend); @@ -4624,7 +4523,7 @@ static int vega10_force_clock_level(struct pp_hwmgr *hwmgr, struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend); int i; - if (hwmgr->dpm_level & (AMD_DPM_FORCED_LEVEL_AUTO | + if (hwmgr->request_dpm_level & (AMD_DPM_FORCED_LEVEL_AUTO | AMD_DPM_FORCED_LEVEL_LOW | AMD_DPM_FORCED_LEVEL_HIGH)) return -EINVAL; @@ -4697,11 +4596,11 @@ static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr, if (data->registry_data.sclk_dpm_key_disabled) break; - PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentGfxclkIndex), "Attempt to get current sclk index Failed!", return -1); - PP_ASSERT_WITH_CODE(!vega10_read_arg_from_smc(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!vega10_read_arg_from_smc(hwmgr, &now), "Attempt to read sclk index Failed!", return -1); @@ -4715,11 +4614,11 @@ static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr, if (data->registry_data.mclk_dpm_key_disabled) break; - PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentUclkIndex), "Attempt to get current mclk index Failed!", return -1); - PP_ASSERT_WITH_CODE(!vega10_read_arg_from_smc(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!vega10_read_arg_from_smc(hwmgr, &now), "Attempt to read mclk index Failed!", return -1); @@ -4730,11 +4629,11 @@ static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr, (i == now) ? "*" : ""); break; case PP_PCIE: - PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentLinkIndex), "Attempt to get current mclk index Failed!", return -1); - PP_ASSERT_WITH_CODE(!vega10_read_arg_from_smc(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!vega10_read_arg_from_smc(hwmgr, &now), "Attempt to read mclk index Failed!", return -1); @@ -4762,7 +4661,7 @@ static int vega10_display_configuration_changed_task(struct pp_hwmgr *hwmgr) if ((data->water_marks_bitmap & WaterMarksExist) && !(data->water_marks_bitmap & WaterMarksLoaded)) { - result = vega10_copy_table_to_smc(hwmgr->smumgr, + result = vega10_copy_table_to_smc(hwmgr, (uint8_t *)wm_table, WMTABLE); PP_ASSERT_WITH_CODE(result, "Failed to update WMTABLE!", return EINVAL); data->water_marks_bitmap |= WaterMarksLoaded; @@ -4771,7 +4670,7 @@ static int vega10_display_configuration_changed_task(struct pp_hwmgr *hwmgr) if (data->water_marks_bitmap & WaterMarksLoaded) { cgs_get_active_displays_info(hwmgr->device, &info); num_turned_on_displays = info.display_count; - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_NumOfDisplays, num_turned_on_displays); } @@ -4784,7 +4683,7 @@ int vega10_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable) (struct vega10_hwmgr *)(hwmgr->backend); if (data->smu_features[GNLD_DPM_UVD].supported) { - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, enable, data->smu_features[GNLD_DPM_UVD].smu_feature_bitmap), "Attempt to Enable/Disable DPM UVD Failed!", @@ -4794,20 +4693,20 @@ int vega10_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable) return 0; } -static int vega10_power_gate_vce(struct pp_hwmgr *hwmgr, bool bgate) +static void vega10_power_gate_vce(struct pp_hwmgr *hwmgr, bool bgate) { struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend); data->vce_power_gated = bgate; - return vega10_enable_disable_vce_dpm(hwmgr, !bgate); + vega10_enable_disable_vce_dpm(hwmgr, !bgate); } -static int vega10_power_gate_uvd(struct pp_hwmgr *hwmgr, bool bgate) +static void vega10_power_gate_uvd(struct pp_hwmgr *hwmgr, bool bgate) { struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend); data->uvd_power_gated = bgate; - return vega10_enable_disable_uvd_dpm(hwmgr, !bgate); + vega10_enable_disable_uvd_dpm(hwmgr, !bgate); } static inline bool vega10_are_power_levels_equal( @@ -4866,7 +4765,7 @@ vega10_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmg if (data->display_timing.num_existing_displays != info.display_count) is_update_required = true; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) { + if (PP_CAP(PHM_PlatformCaps_SclkDeepSleep)) { if (data->display_timing.min_clock_in_sr != hwmgr->display_config.min_core_set_clock_in_sr) is_update_required = true; } @@ -4883,8 +4782,7 @@ static int vega10_disable_dpm_tasks(struct pp_hwmgr *hwmgr) "DPM is not running right now, no need to disable DPM!", return 0); - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ThermalController)) + if (PP_CAP(PHM_PlatformCaps_ThermalController)) vega10_disable_thermal_protection(hwmgr); tmp_result = vega10_disable_power_containment(hwmgr); @@ -4972,7 +4870,7 @@ static int vega10_set_power_profile_state(struct pp_hwmgr *hwmgr, if (!data->registry_data.sclk_dpm_key_disabled) PP_ASSERT_WITH_CODE( !smum_send_msg_to_smc_with_parameter( - hwmgr->smumgr, + hwmgr, PPSMC_MSG_SetSoftMinGfxclkByIndex, sclk_idx), "Failed to set soft min sclk index!", @@ -4983,7 +4881,7 @@ static int vega10_set_power_profile_state(struct pp_hwmgr *hwmgr, if (!data->registry_data.mclk_dpm_key_disabled) PP_ASSERT_WITH_CODE( !smum_send_msg_to_smc_with_parameter( - hwmgr->smumgr, + hwmgr, PPSMC_MSG_SetSoftMinUclkByIndex, mclk_idx), "Failed to set soft min mclk index!", @@ -5096,6 +4994,38 @@ static int vega10_set_mclk_od(struct pp_hwmgr *hwmgr, uint32_t value) return 0; } +static int vega10_register_thermal_interrupt(struct pp_hwmgr *hwmgr, + const void *info) +{ + struct cgs_irq_src_funcs *irq_src = + (struct cgs_irq_src_funcs *)info; + + if (hwmgr->thermal_controller.ucType == + ATOM_VEGA10_PP_THERMALCONTROLLER_VEGA10 || + hwmgr->thermal_controller.ucType == + ATOM_VEGA10_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL) { + PP_ASSERT_WITH_CODE(!cgs_add_irq_source(hwmgr->device, + 0xf, /* AMDGPU_IH_CLIENTID_THM */ + 0, 0, irq_src[0].set, irq_src[0].handler, hwmgr), + "Failed to register high thermal interrupt!", + return -EINVAL); + PP_ASSERT_WITH_CODE(!cgs_add_irq_source(hwmgr->device, + 0xf, /* AMDGPU_IH_CLIENTID_THM */ + 1, 0, irq_src[1].set, irq_src[1].handler, hwmgr), + "Failed to register low thermal interrupt!", + return -EINVAL); + } + + /* Register CTF(GPIO_19) interrupt */ + PP_ASSERT_WITH_CODE(!cgs_add_irq_source(hwmgr->device, + 0x16, /* AMDGPU_IH_CLIENTID_ROM_SMUIO, */ + 83, 0, irq_src[2].set, irq_src[2].handler, hwmgr), + "Failed to register CTF thermal interrupt!", + return -EINVAL); + + return 0; +} + static const struct pp_hwmgr_func vega10_hwmgr_funcs = { .backend_init = vega10_hwmgr_backend_init, .backend_fini = vega10_hwmgr_backend_fini, @@ -5149,12 +5079,13 @@ static const struct pp_hwmgr_func vega10_hwmgr_funcs = { .get_mclk_od = vega10_get_mclk_od, .set_mclk_od = vega10_set_mclk_od, .avfs_control = vega10_avfs_enable, + .register_internal_thermal_interrupt = vega10_register_thermal_interrupt, }; int vega10_hwmgr_init(struct pp_hwmgr *hwmgr) { hwmgr->hwmgr_func = &vega10_hwmgr_funcs; hwmgr->pptable_func = &vega10_pptable_funcs; - pp_vega10_thermal_initialize(hwmgr); + return 0; } diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c index e7fa670..d2f6956 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c @@ -854,99 +854,79 @@ static void vega10_didt_set_mask(struct pp_hwmgr *hwmgr, const bool enable) uint32_t en = (enable ? 1 : 0); uint32_t didt_block_info = SQ_IR_MASK | TCP_IR_MASK | TD_PCC_MASK; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SQRamping)) { - data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_SQ_CTRL0); - data &= ~DIDT_SQ_CTRL0__DIDT_CTRL_EN_MASK; - data |= ((en << DIDT_SQ_CTRL0__DIDT_CTRL_EN__SHIFT) & DIDT_SQ_CTRL0__DIDT_CTRL_EN_MASK); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_SQ_CTRL0, data); + if (PP_CAP(PHM_PlatformCaps_SQRamping)) { + CGS_WREG32_FIELD_IND(hwmgr->device, CGS_IND_REG__DIDT, + DIDT_SQ_CTRL0, DIDT_CTRL_EN, en); didt_block_info &= ~SQ_Enable_MASK; didt_block_info |= en << SQ_Enable_SHIFT; } - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRamping)) { - data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_DB_CTRL0); - data &= ~DIDT_DB_CTRL0__DIDT_CTRL_EN_MASK; - data |= ((en << DIDT_DB_CTRL0__DIDT_CTRL_EN__SHIFT) & DIDT_DB_CTRL0__DIDT_CTRL_EN_MASK); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_DB_CTRL0, data); + if (PP_CAP(PHM_PlatformCaps_DBRamping)) { + CGS_WREG32_FIELD_IND(hwmgr->device, CGS_IND_REG__DIDT, + DIDT_DB_CTRL0, DIDT_CTRL_EN, en); didt_block_info &= ~DB_Enable_MASK; didt_block_info |= en << DB_Enable_SHIFT; } - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TDRamping)) { - data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_TD_CTRL0); - data &= ~DIDT_TD_CTRL0__DIDT_CTRL_EN_MASK; - data |= ((en << DIDT_TD_CTRL0__DIDT_CTRL_EN__SHIFT) & DIDT_TD_CTRL0__DIDT_CTRL_EN_MASK); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_TD_CTRL0, data); + if (PP_CAP(PHM_PlatformCaps_TDRamping)) { + CGS_WREG32_FIELD_IND(hwmgr->device, CGS_IND_REG__DIDT, + DIDT_TD_CTRL0, DIDT_CTRL_EN, en); didt_block_info &= ~TD_Enable_MASK; didt_block_info |= en << TD_Enable_SHIFT; } - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TCPRamping)) { - data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_TCP_CTRL0); - data &= ~DIDT_TCP_CTRL0__DIDT_CTRL_EN_MASK; - data |= ((en << DIDT_TCP_CTRL0__DIDT_CTRL_EN__SHIFT) & DIDT_TCP_CTRL0__DIDT_CTRL_EN_MASK); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_TCP_CTRL0, data); + if (PP_CAP(PHM_PlatformCaps_TCPRamping)) { + CGS_WREG32_FIELD_IND(hwmgr->device, CGS_IND_REG__DIDT, + DIDT_TCP_CTRL0, DIDT_CTRL_EN, en); didt_block_info &= ~TCP_Enable_MASK; didt_block_info |= en << TCP_Enable_SHIFT; } - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRRamping)) { - data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_DBR_CTRL0); - data &= ~DIDT_DBR_CTRL0__DIDT_CTRL_EN_MASK; - data |= ((en << DIDT_DBR_CTRL0__DIDT_CTRL_EN__SHIFT) & DIDT_DBR_CTRL0__DIDT_CTRL_EN_MASK); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_DBR_CTRL0, data); + if (PP_CAP(PHM_PlatformCaps_DBRRamping)) { + CGS_WREG32_FIELD_IND(hwmgr->device, CGS_IND_REG__DIDT, + DIDT_DBR_CTRL0, DIDT_CTRL_EN, en); } - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DiDtEDCEnable)) { - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SQRamping)) { + if (PP_CAP(PHM_PlatformCaps_DiDtEDCEnable)) { + if (PP_CAP(PHM_PlatformCaps_SQRamping)) { data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_SQ_EDC_CTRL); - data &= ~DIDT_SQ_EDC_CTRL__EDC_EN_MASK; - data |= ((en << DIDT_SQ_EDC_CTRL__EDC_EN__SHIFT) & DIDT_SQ_EDC_CTRL__EDC_EN_MASK); - data &= ~DIDT_SQ_EDC_CTRL__EDC_SW_RST_MASK; - data |= ((~en << DIDT_SQ_EDC_CTRL__EDC_SW_RST__SHIFT) & DIDT_SQ_EDC_CTRL__EDC_SW_RST_MASK); + data = CGS_REG_SET_FIELD(data, DIDT_SQ_EDC_CTRL, EDC_EN, en); + data = CGS_REG_SET_FIELD(data, DIDT_SQ_EDC_CTRL, EDC_SW_RST, ~en); cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_SQ_EDC_CTRL, data); } - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRamping)) { + if (PP_CAP(PHM_PlatformCaps_DBRamping)) { data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_DB_EDC_CTRL); - data &= ~DIDT_DB_EDC_CTRL__EDC_EN_MASK; - data |= ((en << DIDT_DB_EDC_CTRL__EDC_EN__SHIFT) & DIDT_DB_EDC_CTRL__EDC_EN_MASK); - data &= ~DIDT_DB_EDC_CTRL__EDC_SW_RST_MASK; - data |= ((~en << DIDT_DB_EDC_CTRL__EDC_SW_RST__SHIFT) & DIDT_DB_EDC_CTRL__EDC_SW_RST_MASK); + data = CGS_REG_SET_FIELD(data, DIDT_DB_EDC_CTRL, EDC_EN, en); + data = CGS_REG_SET_FIELD(data, DIDT_DB_EDC_CTRL, EDC_SW_RST, ~en); cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_DB_EDC_CTRL, data); } - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TDRamping)) { + if (PP_CAP(PHM_PlatformCaps_TDRamping)) { data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_TD_EDC_CTRL); - data &= ~DIDT_TD_EDC_CTRL__EDC_EN_MASK; - data |= ((en << DIDT_TD_EDC_CTRL__EDC_EN__SHIFT) & DIDT_TD_EDC_CTRL__EDC_EN_MASK); - data &= ~DIDT_TD_EDC_CTRL__EDC_SW_RST_MASK; - data |= ((~en << DIDT_TD_EDC_CTRL__EDC_SW_RST__SHIFT) & DIDT_TD_EDC_CTRL__EDC_SW_RST_MASK); + data = CGS_REG_SET_FIELD(data, DIDT_TD_EDC_CTRL, EDC_EN, en); + data = CGS_REG_SET_FIELD(data, DIDT_TD_EDC_CTRL, EDC_SW_RST, ~en); cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_TD_EDC_CTRL, data); } - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TCPRamping)) { + if (PP_CAP(PHM_PlatformCaps_TCPRamping)) { data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_TCP_EDC_CTRL); - data &= ~DIDT_TCP_EDC_CTRL__EDC_EN_MASK; - data |= ((en << DIDT_TCP_EDC_CTRL__EDC_EN__SHIFT) & DIDT_TCP_EDC_CTRL__EDC_EN_MASK); - data &= ~DIDT_TCP_EDC_CTRL__EDC_SW_RST_MASK; - data |= ((~en << DIDT_TCP_EDC_CTRL__EDC_SW_RST__SHIFT) & DIDT_TCP_EDC_CTRL__EDC_SW_RST_MASK); + data = CGS_REG_SET_FIELD(data, DIDT_TCP_EDC_CTRL, EDC_EN, en); + data = CGS_REG_SET_FIELD(data, DIDT_TCP_EDC_CTRL, EDC_SW_RST, ~en); cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_TCP_EDC_CTRL, data); } - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRRamping)) { + if (PP_CAP(PHM_PlatformCaps_DBRRamping)) { data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_DBR_EDC_CTRL); - data &= ~DIDT_DBR_EDC_CTRL__EDC_EN_MASK; - data |= ((en << DIDT_DBR_EDC_CTRL__EDC_EN__SHIFT) & DIDT_DBR_EDC_CTRL__EDC_EN_MASK); - data &= ~DIDT_DBR_EDC_CTRL__EDC_SW_RST_MASK; - data |= ((~en << DIDT_DBR_EDC_CTRL__EDC_SW_RST__SHIFT) & DIDT_DBR_EDC_CTRL__EDC_SW_RST_MASK); + data = CGS_REG_SET_FIELD(data, DIDT_DBR_EDC_CTRL, EDC_EN, en); + data = CGS_REG_SET_FIELD(data, DIDT_DBR_EDC_CTRL, EDC_SW_RST, ~en); cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_DBR_EDC_CTRL, data); } } if (enable) { /* For Vega10, SMC does not support any mask yet. */ - result = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_ConfigureGfxDidt, didt_block_info); + result = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ConfigureGfxDidt, didt_block_info); PP_ASSERT((0 == result), "[EnableDiDtConfig] SMC Configure Gfx Didt Failed!"); } } @@ -1040,10 +1020,10 @@ static int vega10_enable_psm_gc_didt_config(struct pp_hwmgr *hwmgr) cgs_enter_safe_mode(hwmgr->device, false); vega10_program_gc_didt_config_registers(hwmgr, GCDiDtDroopCtrlConfig_vega10); - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_GCEDC)) + if (PP_CAP(PHM_PlatformCaps_GCEDC)) vega10_program_gc_didt_config_registers(hwmgr, GCDiDtCtrl0Config_vega10); - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PSM)) + if (PP_CAP(PHM_PlatformCaps_PSM)) vega10_program_gc_didt_config_registers(hwmgr, AvfsPSMInitConfig_vega10); return 0; @@ -1059,12 +1039,12 @@ static int vega10_disable_psm_gc_didt_config(struct pp_hwmgr *hwmgr) cgs_enter_safe_mode(hwmgr->device, false); - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_GCEDC)) { + if (PP_CAP(PHM_PlatformCaps_GCEDC)) { data = 0x00000000; cgs_write_register(hwmgr->device, mmGC_DIDT_CTRL0, data); } - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PSM)) + if (PP_CAP(PHM_PlatformCaps_PSM)) vega10_program_gc_didt_config_registers(hwmgr, AvfsPSMResetConfig_vega10); return 0; @@ -1159,12 +1139,12 @@ static int vega10_enable_psm_gc_edc_config(struct pp_hwmgr *hwmgr) vega10_program_gc_didt_config_registers(hwmgr, PSMGCEDCDroopCtrlConfig_vega10); - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_GCEDC)) { + if (PP_CAP(PHM_PlatformCaps_GCEDC)) { vega10_program_gc_didt_config_registers(hwmgr, PSMGCEDCCtrlResetConfig_vega10); vega10_program_gc_didt_config_registers(hwmgr, PSMGCEDCCtrlConfig_vega10); } - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PSM)) + if (PP_CAP(PHM_PlatformCaps_PSM)) vega10_program_gc_didt_config_registers(hwmgr, AvfsPSMInitConfig_vega10); return 0; @@ -1180,12 +1160,12 @@ static int vega10_disable_psm_gc_edc_config(struct pp_hwmgr *hwmgr) cgs_enter_safe_mode(hwmgr->device, false); - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_GCEDC)) { + if (PP_CAP(PHM_PlatformCaps_GCEDC)) { data = 0x00000000; cgs_write_register(hwmgr->device, mmGC_EDC_CTRL, data); } - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PSM)) + if (PP_CAP(PHM_PlatformCaps_PSM)) vega10_program_gc_didt_config_registers(hwmgr, AvfsPSMResetConfig_vega10); return 0; @@ -1263,7 +1243,7 @@ int vega10_enable_didt_config(struct pp_hwmgr *hwmgr) } if (0 == result) { - PP_ASSERT_WITH_CODE((!vega10_enable_smc_features(hwmgr->smumgr, true, data->smu_features[GNLD_DIDT].smu_feature_bitmap)), + PP_ASSERT_WITH_CODE((!vega10_enable_smc_features(hwmgr, true, data->smu_features[GNLD_DIDT].smu_feature_bitmap)), "[EnableDiDtConfig] Attempt to Enable DiDt feature Failed!", return result); data->smu_features[GNLD_DIDT].enabled = true; } @@ -1310,7 +1290,7 @@ int vega10_disable_didt_config(struct pp_hwmgr *hwmgr) } if (0 == result) { - PP_ASSERT_WITH_CODE((0 != vega10_enable_smc_features(hwmgr->smumgr, false, data->smu_features[GNLD_DIDT].smu_feature_bitmap)), + PP_ASSERT_WITH_CODE((0 != vega10_enable_smc_features(hwmgr, false, data->smu_features[GNLD_DIDT].smu_feature_bitmap)), "[DisableDiDtConfig] Attempt to Disable DiDt feature Failed!", return result); data->smu_features[GNLD_DIDT].enabled = false; } @@ -1364,7 +1344,7 @@ int vega10_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n) (struct vega10_hwmgr *)(hwmgr->backend); if (data->registry_data.enable_pkg_pwr_tracking_feature) - return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + return smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetPptLimit, n); return 0; @@ -1381,16 +1361,15 @@ int vega10_enable_power_containment(struct pp_hwmgr *hwmgr) (uint32_t)(tdp_table->usMaximumPowerDeliveryLimit); int result = 0; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerContainment)) { + if (PP_CAP(PHM_PlatformCaps_PowerContainment)) { if (data->smu_features[GNLD_PPT].supported) - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, true, data->smu_features[GNLD_PPT].smu_feature_bitmap), "Attempt to enable PPT feature Failed!", data->smu_features[GNLD_PPT].supported = false); if (data->smu_features[GNLD_TDC].supported) - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, true, data->smu_features[GNLD_TDC].smu_feature_bitmap), "Attempt to enable PPT feature Failed!", data->smu_features[GNLD_TDC].supported = false); @@ -1409,16 +1388,15 @@ int vega10_disable_power_containment(struct pp_hwmgr *hwmgr) struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend); - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerContainment)) { + if (PP_CAP(PHM_PlatformCaps_PowerContainment)) { if (data->smu_features[GNLD_PPT].supported) - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, false, data->smu_features[GNLD_PPT].smu_feature_bitmap), "Attempt to disable PPT feature Failed!", data->smu_features[GNLD_PPT].supported = false); if (data->smu_features[GNLD_TDC].supported) - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, false, data->smu_features[GNLD_TDC].smu_feature_bitmap), "Attempt to disable PPT feature Failed!", data->smu_features[GNLD_TDC].supported = false); @@ -1430,7 +1408,7 @@ int vega10_disable_power_containment(struct pp_hwmgr *hwmgr) static int vega10_set_overdrive_target_percentage(struct pp_hwmgr *hwmgr, uint32_t adjust_percent) { - return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + return smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_OverDriveSetPercentage, adjust_percent); } @@ -1438,8 +1416,7 @@ int vega10_power_control_set_level(struct pp_hwmgr *hwmgr) { int adjust_percent, result = 0; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerContainment)) { + if (PP_CAP(PHM_PlatformCaps_PowerContainment)) { adjust_percent = hwmgr->platform_descriptor.TDPAdjustmentPolarity ? hwmgr->platform_descriptor.TDPAdjustment : diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c index d442434..1feefac 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c @@ -31,11 +31,11 @@ static int vega10_get_current_rpm(struct pp_hwmgr *hwmgr, uint32_t *current_rpm) { - PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentRpm), "Attempt to get current RPM from SMC Failed!", return -1); - PP_ASSERT_WITH_CODE(!vega10_read_arg_from_smc(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!vega10_read_arg_from_smc(hwmgr, current_rpm), "Attempt to read current RPM from SMC Failed!", return -1); @@ -54,8 +54,7 @@ int vega10_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, fan_speed_info->min_percent = 0; fan_speed_info->max_percent = 100; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_FanSpeedInTableIsRPM) && + if (PP_CAP(PHM_PlatformCaps_FanSpeedInTableIsRPM) && hwmgr->thermal_controller.fanInfo. ucTachometerPulsesPerRevolution) { fan_speed_info->supports_rpm_read = true; @@ -105,14 +104,15 @@ int vega10_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed) if (hwmgr->thermal_controller.fanInfo.bNoFan) return -1; - if (data->smu_features[GNLD_FAN_CONTROL].supported) + if (data->smu_features[GNLD_FAN_CONTROL].supported) { result = vega10_get_current_rpm(hwmgr, speed); - else { + } else { uint32_t reg = soc15_get_register_offset(THM_HWID, 0, mmCG_TACH_STATUS_BASE_IDX, mmCG_TACH_STATUS); - tach_period = (cgs_read_register(hwmgr->device, - reg) & CG_TACH_STATUS__TACH_PERIOD_MASK) >> - CG_TACH_STATUS__TACH_PERIOD__SHIFT; + tach_period = + CGS_REG_GET_FIELD(cgs_read_register(hwmgr->device, reg), + CG_TACH_STATUS, + TACH_PERIOD); if (tach_period == 0) return -EINVAL; @@ -141,23 +141,20 @@ int vega10_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode) if (hwmgr->fan_ctrl_is_in_default_mode) { hwmgr->fan_ctrl_default_mode = - (cgs_read_register(hwmgr->device, reg) & - CG_FDO_CTRL2__FDO_PWM_MODE_MASK) >> - CG_FDO_CTRL2__FDO_PWM_MODE__SHIFT; - hwmgr->tmin = (cgs_read_register(hwmgr->device, reg) & - CG_FDO_CTRL2__TMIN_MASK) >> - CG_FDO_CTRL2__TMIN__SHIFT; + CGS_REG_GET_FIELD(cgs_read_register(hwmgr->device, reg), + CG_FDO_CTRL2, FDO_PWM_MODE); + hwmgr->tmin = + CGS_REG_GET_FIELD(cgs_read_register(hwmgr->device, reg), + CG_FDO_CTRL2, TMIN); hwmgr->fan_ctrl_is_in_default_mode = false; } cgs_write_register(hwmgr->device, reg, - (cgs_read_register(hwmgr->device, reg) & - ~CG_FDO_CTRL2__TMIN_MASK) | - (0 << CG_FDO_CTRL2__TMIN__SHIFT)); + CGS_REG_SET_FIELD(cgs_read_register(hwmgr->device, reg), + CG_FDO_CTRL2, TMIN, 0)); cgs_write_register(hwmgr->device, reg, - (cgs_read_register(hwmgr->device, reg) & - ~CG_FDO_CTRL2__FDO_PWM_MODE_MASK) | - (mode << CG_FDO_CTRL2__FDO_PWM_MODE__SHIFT)); + CGS_REG_SET_FIELD(cgs_read_register(hwmgr->device, reg), + CG_FDO_CTRL2, FDO_PWM_MODE, mode)); return 0; } @@ -176,14 +173,13 @@ int vega10_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr) if (!hwmgr->fan_ctrl_is_in_default_mode) { cgs_write_register(hwmgr->device, reg, - (cgs_read_register(hwmgr->device, reg) & - ~CG_FDO_CTRL2__FDO_PWM_MODE_MASK) | - (hwmgr->fan_ctrl_default_mode << - CG_FDO_CTRL2__FDO_PWM_MODE__SHIFT)); + CGS_REG_SET_FIELD(cgs_read_register(hwmgr->device, reg), + CG_FDO_CTRL2, FDO_PWM_MODE, + hwmgr->fan_ctrl_default_mode)); cgs_write_register(hwmgr->device, reg, - (cgs_read_register(hwmgr->device, reg) & - ~CG_FDO_CTRL2__TMIN_MASK) | - (hwmgr->tmin << CG_FDO_CTRL2__TMIN__SHIFT)); + CGS_REG_SET_FIELD(cgs_read_register(hwmgr->device, reg), + CG_FDO_CTRL2, TMIN, + hwmgr->tmin << CG_FDO_CTRL2__TMIN__SHIFT)); hwmgr->fan_ctrl_is_in_default_mode = true; } @@ -203,7 +199,7 @@ static int vega10_enable_fan_control_feature(struct pp_hwmgr *hwmgr) if (data->smu_features[GNLD_FAN_CONTROL].supported) { PP_ASSERT_WITH_CODE(!vega10_enable_smc_features( - hwmgr->smumgr, true, + hwmgr, true, data->smu_features[GNLD_FAN_CONTROL]. smu_feature_bitmap), "Attempt to Enable FAN CONTROL feature Failed!", @@ -220,7 +216,7 @@ static int vega10_disable_fan_control_feature(struct pp_hwmgr *hwmgr) if (data->smu_features[GNLD_FAN_CONTROL].supported) { PP_ASSERT_WITH_CODE(!vega10_enable_smc_features( - hwmgr->smumgr, false, + hwmgr, false, data->smu_features[GNLD_FAN_CONTROL]. smu_feature_bitmap), "Attempt to Enable FAN CONTROL feature Failed!", @@ -279,16 +275,14 @@ int vega10_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, if (speed > 100) speed = 100; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl)) + if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) vega10_fan_ctrl_stop_smc_fan_control(hwmgr); reg = soc15_get_register_offset(THM_HWID, 0, mmCG_FDO_CTRL1_BASE_IDX, mmCG_FDO_CTRL1); - duty100 = (cgs_read_register(hwmgr->device, reg) & - CG_FDO_CTRL1__FMAX_DUTY100_MASK) >> - CG_FDO_CTRL1__FMAX_DUTY100__SHIFT; + duty100 = CGS_REG_GET_FIELD(cgs_read_register(hwmgr->device, reg), + CG_FDO_CTRL1, FMAX_DUTY100); if (duty100 == 0) return -EINVAL; @@ -300,9 +294,8 @@ int vega10_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, reg = soc15_get_register_offset(THM_HWID, 0, mmCG_FDO_CTRL0_BASE_IDX, mmCG_FDO_CTRL0); cgs_write_register(hwmgr->device, reg, - (cgs_read_register(hwmgr->device, reg) & - ~CG_FDO_CTRL0__FDO_STATIC_DUTY_MASK) | - (duty << CG_FDO_CTRL0__FDO_STATIC_DUTY__SHIFT)); + CGS_REG_SET_FIELD(cgs_read_register(hwmgr->device, reg), + CG_FDO_CTRL0, FDO_STATIC_DUTY, duty)); return vega10_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC); } @@ -314,18 +307,13 @@ int vega10_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, */ int vega10_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr) { - int result; - if (hwmgr->thermal_controller.fanInfo.bNoFan) return 0; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl)) { - result = vega10_fan_ctrl_start_smc_fan_control(hwmgr); - } else - result = vega10_fan_ctrl_set_default_mode(hwmgr); - - return result; + if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) + return vega10_fan_ctrl_start_smc_fan_control(hwmgr); + else + return vega10_fan_ctrl_set_default_mode(hwmgr); } /** @@ -342,12 +330,11 @@ int vega10_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed) uint32_t reg; if (hwmgr->thermal_controller.fanInfo.bNoFan || - (speed < hwmgr->thermal_controller.fanInfo.ulMinRPM) || - (speed > hwmgr->thermal_controller.fanInfo.ulMaxRPM)) + (speed < hwmgr->thermal_controller.fanInfo.ulMinRPM) || + (speed > hwmgr->thermal_controller.fanInfo.ulMaxRPM)) return -1; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl)) + if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) result = vega10_fan_ctrl_stop_smc_fan_control(hwmgr); if (!result) { @@ -356,9 +343,9 @@ int vega10_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed) reg = soc15_get_register_offset(THM_HWID, 0, mmCG_TACH_STATUS_BASE_IDX, mmCG_TACH_STATUS); cgs_write_register(hwmgr->device, reg, - (cgs_read_register(hwmgr->device, reg) & - ~CG_TACH_STATUS__TACH_PERIOD_MASK) | - (tach_period << CG_TACH_STATUS__TACH_PERIOD__SHIFT)); + CGS_REG_SET_FIELD(cgs_read_register(hwmgr->device, reg), + CG_TACH_STATUS, TACH_PERIOD, + tach_period)); } return vega10_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC_RPM); } @@ -374,7 +361,7 @@ int vega10_thermal_get_temperature(struct pp_hwmgr *hwmgr) uint32_t reg; reg = soc15_get_register_offset(THM_HWID, 0, - mmCG_TACH_STATUS_BASE_IDX, mmCG_MULT_THERMAL_STATUS); + mmCG_MULT_THERMAL_STATUS_BASE_IDX, mmCG_MULT_THERMAL_STATUS); temp = cgs_read_register(hwmgr->device, reg); @@ -418,20 +405,10 @@ static int vega10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, val = cgs_read_register(hwmgr->device, reg); - val &= (~THM_THERMAL_INT_CTRL__MAX_IH_CREDIT_MASK); - val |= (5 << THM_THERMAL_INT_CTRL__MAX_IH_CREDIT__SHIFT); - - val &= (~THM_THERMAL_INT_CTRL__THERM_IH_HW_ENA_MASK); - val |= (1 << THM_THERMAL_INT_CTRL__THERM_IH_HW_ENA__SHIFT); - - val &= (~THM_THERMAL_INT_CTRL__DIG_THERM_INTH_MASK); - val |= ((high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES) - << THM_THERMAL_INT_CTRL__DIG_THERM_INTH__SHIFT); - - val &= (~THM_THERMAL_INT_CTRL__DIG_THERM_INTL_MASK); - val |= ((low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES) - << THM_THERMAL_INT_CTRL__DIG_THERM_INTL__SHIFT); - + val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5); + val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1); + val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); + val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK); cgs_write_register(hwmgr->device, reg, val); @@ -452,19 +429,16 @@ static int vega10_thermal_initialize(struct pp_hwmgr *hwmgr) reg = soc15_get_register_offset(THM_HWID, 0, mmCG_TACH_CTRL_BASE_IDX, mmCG_TACH_CTRL); cgs_write_register(hwmgr->device, reg, - (cgs_read_register(hwmgr->device, reg) & - ~CG_TACH_CTRL__EDGE_PER_REV_MASK) | - ((hwmgr->thermal_controller.fanInfo. - ucTachometerPulsesPerRevolution - 1) << - CG_TACH_CTRL__EDGE_PER_REV__SHIFT)); + CGS_REG_SET_FIELD(cgs_read_register(hwmgr->device, reg), + CG_TACH_CTRL, EDGE_PER_REV, + hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution - 1)); } reg = soc15_get_register_offset(THM_HWID, 0, mmCG_FDO_CTRL2_BASE_IDX, mmCG_FDO_CTRL2); cgs_write_register(hwmgr->device, reg, - (cgs_read_register(hwmgr->device, reg) & - ~CG_FDO_CTRL2__TACH_PWM_RESP_RATE_MASK) | - (0x28 << CG_FDO_CTRL2__TACH_PWM_RESP_RATE__SHIFT)); + CGS_REG_SET_FIELD(cgs_read_register(hwmgr->device, reg), + CG_FDO_CTRL2, TACH_PWM_RESP_RATE, 0x28)); return 0; } @@ -484,7 +458,7 @@ static int vega10_thermal_enable_alert(struct pp_hwmgr *hwmgr) if (data->smu_features[GNLD_FW_CTF].enabled) printk("[Thermal_EnableAlert] FW CTF Already Enabled!\n"); - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, true, data->smu_features[GNLD_FW_CTF].smu_feature_bitmap), "Attempt to Enable FW CTF feature Failed!", @@ -516,7 +490,7 @@ int vega10_thermal_disable_alert(struct pp_hwmgr *hwmgr) printk("[Thermal_EnableAlert] FW CTF Already disabled!\n"); - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr, + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, false, data->smu_features[GNLD_FW_CTF].smu_feature_bitmap), "Attempt to disable FW CTF feature Failed!", @@ -554,8 +528,7 @@ int vega10_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr) * @param Result the last failure code * @return result from set temperature range routine */ -int tf_vega10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr, - void *input, void *output, void *storage, int result) +int vega10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) { int ret; struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend); @@ -573,7 +546,7 @@ int tf_vega10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr, table->FanTargetTemperature = hwmgr->thermal_controller. advanceFanControlParameters.usTMax; - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetFanTemperatureTarget, (uint32_t)table->FanTargetTemperature); @@ -602,7 +575,7 @@ int tf_vega10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr, table->FanStartTemp = hwmgr->thermal_controller. advanceFanControlParameters.usZeroRPMStartTemperature; - ret = vega10_copy_table_to_smc(hwmgr->smumgr, + ret = vega10_copy_table_to_smc(hwmgr, (uint8_t *)(&(data->smc_state_table.pp_table)), PPTABLE); if (ret) pr_info("Failed to update Fan Control Table in PPTable!"); @@ -619,123 +592,50 @@ int tf_vega10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr, * @param Result the last failure code * @return result from set temperature range routine */ -int tf_vega10_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr, - void *input, void *output, void *storage, int result) +int vega10_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr) { /* If the fantable setup has failed we could have disabled * PHM_PlatformCaps_MicrocodeFanControl even after * this function was included in the table. * Make sure that we still think controlling the fan is OK. */ - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl)) { + if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) vega10_fan_ctrl_start_smc_fan_control(hwmgr); - } return 0; } -/** -* Set temperature range for high and low alerts -* @param hwmgr the address of the powerplay hardware manager. -* @param pInput the pointer to input data -* @param pOutput the pointer to output data -* @param pStorage the pointer to temporary storage -* @param Result the last failure code -* @return result from set temperature range routine -*/ -int tf_vega10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, - void *input, void *output, void *storage, int result) + +int vega10_start_thermal_controller(struct pp_hwmgr *hwmgr, + struct PP_TemperatureRange *range) { - struct PP_TemperatureRange *range = (struct PP_TemperatureRange *)input; + int ret = 0; if (range == NULL) return -EINVAL; - return vega10_thermal_set_temperature_range(hwmgr, range); -} - -/** -* Programs one-time setting registers -* @param hwmgr the address of the powerplay hardware manager. -* @param pInput the pointer to input data -* @param pOutput the pointer to output data -* @param pStorage the pointer to temporary storage -* @param Result the last failure code -* @return result from initialize thermal controller routine -*/ -int tf_vega10_thermal_initialize(struct pp_hwmgr *hwmgr, - void *input, void *output, void *storage, int result) -{ - return vega10_thermal_initialize(hwmgr); -} - -/** -* Enable high and low alerts -* @param hwmgr the address of the powerplay hardware manager. -* @param pInput the pointer to input data -* @param pOutput the pointer to output data -* @param pStorage the pointer to temporary storage -* @param Result the last failure code -* @return result from enable alert routine -*/ -int tf_vega10_thermal_enable_alert(struct pp_hwmgr *hwmgr, - void *input, void *output, void *storage, int result) -{ - return vega10_thermal_enable_alert(hwmgr); -} - -/** -* Disable high and low alerts -* @param hwmgr the address of the powerplay hardware manager. -* @param pInput the pointer to input data -* @param pOutput the pointer to output data -* @param pStorage the pointer to temporary storage -* @param Result the last failure code -* @return result from disable alert routine -*/ -static int tf_vega10_thermal_disable_alert(struct pp_hwmgr *hwmgr, - void *input, void *output, void *storage, int result) -{ - return vega10_thermal_disable_alert(hwmgr); -} + vega10_thermal_initialize(hwmgr); + ret = vega10_thermal_set_temperature_range(hwmgr, range); + if (ret) + return -EINVAL; -static struct phm_master_table_item -vega10_thermal_start_thermal_controller_master_list[] = { - { .tableFunction = tf_vega10_thermal_initialize }, - { .tableFunction = tf_vega10_thermal_set_temperature_range }, - { .tableFunction = tf_vega10_thermal_enable_alert }, + vega10_thermal_enable_alert(hwmgr); /* We should restrict performance levels to low before we halt the SMC. * On the other hand we are still in boot state when we do this * so it would be pointless. * If this assumption changes we have to revisit this table. */ - { .tableFunction = tf_vega10_thermal_setup_fan_table }, - { .tableFunction = tf_vega10_thermal_start_smc_fan_control }, - { } -}; + ret = vega10_thermal_setup_fan_table(hwmgr); + if (ret) + return -EINVAL; -static struct phm_master_table_header -vega10_thermal_start_thermal_controller_master = { - 0, - PHM_MasterTableFlag_None, - vega10_thermal_start_thermal_controller_master_list -}; + vega10_thermal_start_smc_fan_control(hwmgr); -static struct phm_master_table_item -vega10_thermal_set_temperature_range_master_list[] = { - { .tableFunction = tf_vega10_thermal_disable_alert }, - { .tableFunction = tf_vega10_thermal_set_temperature_range }, - { .tableFunction = tf_vega10_thermal_enable_alert }, - { } + return 0; }; -struct phm_master_table_header -vega10_thermal_set_temperature_range_master = { - 0, - PHM_MasterTableFlag_None, - vega10_thermal_set_temperature_range_master_list -}; + + int vega10_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr) { @@ -745,32 +645,3 @@ int vega10_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr) } return 0; } - -/** -* Initializes the thermal controller related functions -* in the Hardware Manager structure. -* @param hwmgr The address of the hardware manager. -* @exception Any error code from the low-level communication. -*/ -int pp_vega10_thermal_initialize(struct pp_hwmgr *hwmgr) -{ - int result; - - result = phm_construct_table(hwmgr, - &vega10_thermal_set_temperature_range_master, - &(hwmgr->set_temperature_range)); - - if (!result) { - result = phm_construct_table(hwmgr, - &vega10_thermal_start_thermal_controller_master, - &(hwmgr->start_thermal_controller)); - if (result) - phm_destroy_table(hwmgr, - &(hwmgr->set_temperature_range)); - } - - if (!result) - hwmgr->fan_ctrl_is_in_default_mode = true; - return result; -} - diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h index 776f3a2..f34ce04 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h @@ -50,13 +50,6 @@ struct vega10_temperature { #define FDO_PWM_MODE_STATIC_RPM 5 -extern int tf_vega10_thermal_initialize(struct pp_hwmgr *hwmgr, - void *input, void *output, void *storage, int result); -extern int tf_vega10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, - void *input, void *output, void *storage, int result); -extern int tf_vega10_thermal_enable_alert(struct pp_hwmgr *hwmgr, - void *input, void *output, void *storage, int result); - extern int vega10_thermal_get_temperature(struct pp_hwmgr *hwmgr); extern int vega10_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr); extern int vega10_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, @@ -69,7 +62,6 @@ extern int vega10_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, extern int vega10_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, uint32_t speed); extern int vega10_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr); -extern int pp_vega10_thermal_initialize(struct pp_hwmgr *hwmgr); extern int vega10_thermal_ctrl_uninitialize_thermal_controller( struct pp_hwmgr *hwmgr); extern int vega10_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, @@ -77,9 +69,10 @@ extern int vega10_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, extern int vega10_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed); extern int vega10_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr); -extern uint32_t smu7_get_xclk(struct pp_hwmgr *hwmgr); extern int vega10_thermal_disable_alert(struct pp_hwmgr *hwmgr); -int vega10_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr); +extern int vega10_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr); + +extern uint32_t smu7_get_xclk(struct pp_hwmgr *hwmgr); #endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h index 07e9c0b..435da26 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h +++ b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h @@ -31,7 +31,7 @@ #include "dm_pp_interface.h" extern const struct amd_ip_funcs pp_ip_funcs; -extern const struct amd_powerplay_funcs pp_dpm_funcs; +extern const struct amd_pm_funcs pp_dpm_funcs; #define PP_DPM_DISABLED 0xCCCC @@ -50,94 +50,12 @@ enum amd_pp_sensors { AMDGPU_PP_SENSOR_GPU_POWER, }; -enum amd_pp_event { - AMD_PP_EVENT_INITIALIZE = 0, - AMD_PP_EVENT_UNINITIALIZE, - AMD_PP_EVENT_POWER_SOURCE_CHANGE, - AMD_PP_EVENT_SUSPEND, - AMD_PP_EVENT_RESUME, - AMD_PP_EVENT_ENTER_REST_STATE, - AMD_PP_EVENT_EXIT_REST_STATE, - AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE, - AMD_PP_EVENT_THERMAL_NOTIFICATION, - AMD_PP_EVENT_VBIOS_NOTIFICATION, - AMD_PP_EVENT_ENTER_THERMAL_STATE, - AMD_PP_EVENT_EXIT_THERMAL_STATE, - AMD_PP_EVENT_ENTER_FORCED_STATE, - AMD_PP_EVENT_EXIT_FORCED_STATE, - AMD_PP_EVENT_ENTER_EXCLUSIVE_MODE, - AMD_PP_EVENT_EXIT_EXCLUSIVE_MODE, - AMD_PP_EVENT_ENTER_SCREEN_SAVER, - AMD_PP_EVENT_EXIT_SCREEN_SAVER, - AMD_PP_EVENT_VPU_RECOVERY_BEGIN, - AMD_PP_EVENT_VPU_RECOVERY_END, - AMD_PP_EVENT_ENABLE_POWER_PLAY, - AMD_PP_EVENT_DISABLE_POWER_PLAY, - AMD_PP_EVENT_CHANGE_POWER_SOURCE_UI_LABEL, - AMD_PP_EVENT_ENABLE_USER2D_PERFORMANCE, - AMD_PP_EVENT_DISABLE_USER2D_PERFORMANCE, - AMD_PP_EVENT_ENABLE_USER3D_PERFORMANCE, - AMD_PP_EVENT_DISABLE_USER3D_PERFORMANCE, - AMD_PP_EVENT_ENABLE_OVER_DRIVE_TEST, - AMD_PP_EVENT_DISABLE_OVER_DRIVE_TEST, - AMD_PP_EVENT_ENABLE_REDUCED_REFRESH_RATE, - AMD_PP_EVENT_DISABLE_REDUCED_REFRESH_RATE, - AMD_PP_EVENT_ENABLE_GFX_CLOCK_GATING, - AMD_PP_EVENT_DISABLE_GFX_CLOCK_GATING, - AMD_PP_EVENT_ENABLE_CGPG, - AMD_PP_EVENT_DISABLE_CGPG, - AMD_PP_EVENT_ENTER_TEXT_MODE, - AMD_PP_EVENT_EXIT_TEXT_MODE, - AMD_PP_EVENT_VIDEO_START, - AMD_PP_EVENT_VIDEO_STOP, - AMD_PP_EVENT_ENABLE_USER_STATE, - AMD_PP_EVENT_DISABLE_USER_STATE, - AMD_PP_EVENT_READJUST_POWER_STATE, - AMD_PP_EVENT_START_INACTIVITY, - AMD_PP_EVENT_STOP_INACTIVITY, - AMD_PP_EVENT_LINKED_ADAPTERS_READY, - AMD_PP_EVENT_ADAPTER_SAFE_TO_DISABLE, - AMD_PP_EVENT_COMPLETE_INIT, - AMD_PP_EVENT_CRITICAL_THERMAL_FAULT, - AMD_PP_EVENT_BACKLIGHT_CHANGED, - AMD_PP_EVENT_ENABLE_VARI_BRIGHT, - AMD_PP_EVENT_DISABLE_VARI_BRIGHT, - AMD_PP_EVENT_ENABLE_VARI_BRIGHT_ON_POWER_XPRESS, - AMD_PP_EVENT_DISABLE_VARI_BRIGHT_ON_POWER_XPRESS, - AMD_PP_EVENT_SET_VARI_BRIGHT_LEVEL, - AMD_PP_EVENT_VARI_BRIGHT_MONITOR_MEASUREMENT, - AMD_PP_EVENT_SCREEN_ON, - AMD_PP_EVENT_SCREEN_OFF, - AMD_PP_EVENT_PRE_DISPLAY_CONFIG_CHANGE, - AMD_PP_EVENT_ENTER_ULP_STATE, - AMD_PP_EVENT_EXIT_ULP_STATE, - AMD_PP_EVENT_REGISTER_IP_STATE, - AMD_PP_EVENT_UNREGISTER_IP_STATE, - AMD_PP_EVENT_ENTER_MGPU_MODE, - AMD_PP_EVENT_EXIT_MGPU_MODE, - AMD_PP_EVENT_ENTER_MULTI_GPU_MODE, - AMD_PP_EVENT_PRE_SUSPEND, - AMD_PP_EVENT_PRE_RESUME, - AMD_PP_EVENT_ENTER_BACOS, - AMD_PP_EVENT_EXIT_BACOS, - AMD_PP_EVENT_RESUME_BACO, - AMD_PP_EVENT_RESET_BACO, - AMD_PP_EVENT_PRE_DISPLAY_PHY_ACCESS, - AMD_PP_EVENT_POST_DISPLAY_PHY_CCESS, - AMD_PP_EVENT_START_COMPUTE_APPLICATION, - AMD_PP_EVENT_STOP_COMPUTE_APPLICATION, - AMD_PP_EVENT_REDUCE_POWER_LIMIT, - AMD_PP_EVENT_ENTER_FRAME_LOCK, - AMD_PP_EVENT_EXIT_FRAME_LOOCK, - AMD_PP_EVENT_LONG_IDLE_REQUEST_BACO, - AMD_PP_EVENT_LONG_IDLE_ENTER_BACO, - AMD_PP_EVENT_LONG_IDLE_EXIT_BACO, - AMD_PP_EVENT_HIBERNATE, - AMD_PP_EVENT_CONNECTED_STANDBY, - AMD_PP_EVENT_ENTER_SELF_REFRESH, - AMD_PP_EVENT_EXIT_SELF_REFRESH, - AMD_PP_EVENT_START_AVFS_BTC, - AMD_PP_EVENT_MAX +enum amd_pp_task { + AMD_PP_TASK_DISPLAY_CONFIG_CHANGE, + AMD_PP_TASK_ENABLE_USER_STATE, + AMD_PP_TASK_READJUST_POWER_STATE, + AMD_PP_TASK_COMPLETE_INIT, + AMD_PP_TASK_MAX }; struct amd_pp_init { @@ -295,12 +213,6 @@ enum { PP_GROUP_MAX }; -enum pp_clock_type { - PP_SCLK, - PP_MCLK, - PP_PCIE, -}; - struct pp_states_info { uint32_t nums; uint32_t states[16]; @@ -355,49 +267,10 @@ struct pp_display_clock_request { support << PP_STATE_SUPPORT_SHIFT |\ state << PP_STATE_SHIFT) -struct amd_powerplay_funcs { - int (*get_temperature)(void *handle); - int (*load_firmware)(void *handle); - int (*wait_for_fw_loading_complete)(void *handle); - int (*force_performance_level)(void *handle, enum amd_dpm_forced_level level); - enum amd_dpm_forced_level (*get_performance_level)(void *handle); - enum amd_pm_state_type (*get_current_power_state)(void *handle); - int (*get_sclk)(void *handle, bool low); - int (*get_mclk)(void *handle, bool low); - int (*powergate_vce)(void *handle, bool gate); - int (*powergate_uvd)(void *handle, bool gate); - int (*dispatch_tasks)(void *handle, enum amd_pp_event event_id, - void *input, void *output); - int (*set_fan_control_mode)(void *handle, uint32_t mode); - int (*get_fan_control_mode)(void *handle); - int (*set_fan_speed_percent)(void *handle, uint32_t percent); - int (*get_fan_speed_percent)(void *handle, uint32_t *speed); - int (*get_fan_speed_rpm)(void *handle, uint32_t *rpm); - int (*get_pp_num_states)(void *handle, struct pp_states_info *data); - int (*get_pp_table)(void *handle, char **table); - int (*set_pp_table)(void *handle, const char *buf, size_t size); - int (*force_clock_level)(void *handle, enum pp_clock_type type, uint32_t mask); - int (*print_clock_levels)(void *handle, enum pp_clock_type type, char *buf); - int (*get_sclk_od)(void *handle); - int (*set_sclk_od)(void *handle, uint32_t value); - int (*get_mclk_od)(void *handle); - int (*set_mclk_od)(void *handle, uint32_t value); - int (*read_sensor)(void *handle, int idx, void *value, int *size); - struct amd_vce_state* (*get_vce_clock_state)(void *handle, unsigned idx); - int (*reset_power_profile_state)(void *handle, - struct amd_pp_profile *request); - int (*get_power_profile_state)(void *handle, - struct amd_pp_profile *query); - int (*set_power_profile_state)(void *handle, - struct amd_pp_profile *request); - int (*switch_power_profile)(void *handle, - enum amd_pp_profile_type type); -}; - struct amd_powerplay { void *pp_handle; const struct amd_ip_funcs *ip_funcs; - const struct amd_powerplay_funcs *pp_funcs; + const struct amd_pm_funcs *pp_funcs; }; int amd_powerplay_create(struct amd_pp_init *pp_init, diff --git a/drivers/gpu/drm/amd/powerplay/inc/eventmanager.h b/drivers/gpu/drm/amd/powerplay/inc/eventmanager.h deleted file mode 100644 index b9d84de..0000000 --- a/drivers/gpu/drm/amd/powerplay/inc/eventmanager.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2015 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#ifndef _EVENT_MANAGER_H_ -#define _EVENT_MANAGER_H_ - -#include "power_state.h" -#include "pp_power_source.h" -#include "hardwaremanager.h" -#include "pp_asicblocks.h" - -struct pp_eventmgr; -enum amd_pp_event; - -enum PEM_EventDataValid { - PEM_EventDataValid_RequestedStateID = 0, - PEM_EventDataValid_RequestedUILabel, - PEM_EventDataValid_NewPowerState, - PEM_EventDataValid_RequestedPowerSource, - PEM_EventDataValid_RequestedClocks, - PEM_EventDataValid_CurrentTemperature, - PEM_EventDataValid_AsicBlocks, - PEM_EventDataValid_ODParameters, - PEM_EventDataValid_PXAdapterPrefs, - PEM_EventDataValid_PXUserPrefs, - PEM_EventDataValid_PXSwitchReason, - PEM_EventDataValid_PXSwitchPhase, - PEM_EventDataValid_HdVideo, - PEM_EventDataValid_BacklightLevel, - PEM_EventDatavalid_VariBrightParams, - PEM_EventDataValid_VariBrightLevel, - PEM_EventDataValid_VariBrightImmediateChange, - PEM_EventDataValid_PercentWhite, - PEM_EventDataValid_SdVideo, - PEM_EventDataValid_HTLinkChangeReason, - PEM_EventDataValid_HWBlocks, - PEM_EventDataValid_RequestedThermalState, - PEM_EventDataValid_MvcVideo, - PEM_EventDataValid_Max -}; - -typedef enum PEM_EventDataValid PEM_EventDataValid; - -/* Number of bits in ULONG variable */ -#define PEM_MAX_NUM_EVENTDATAVALID_BITS_PER_FIELD (sizeof(unsigned long)*8) - -/* Number of ULONG entries used by event data valid bits */ -#define PEM_MAX_NUM_EVENTDATAVALID_ULONG_ENTRIES \ - ((PEM_EventDataValid_Max + PEM_MAX_NUM_EVENTDATAVALID_BITS_PER_FIELD - 1) / \ - PEM_MAX_NUM_EVENTDATAVALID_BITS_PER_FIELD) - -static inline void pem_set_event_data_valid(unsigned long *fields, PEM_EventDataValid valid_field) -{ - fields[valid_field / PEM_MAX_NUM_EVENTDATAVALID_BITS_PER_FIELD] |= - (1UL << (valid_field % PEM_MAX_NUM_EVENTDATAVALID_BITS_PER_FIELD)); -} - -static inline void pem_unset_event_data_valid(unsigned long *fields, PEM_EventDataValid valid_field) -{ - fields[valid_field / PEM_MAX_NUM_EVENTDATAVALID_BITS_PER_FIELD] &= - ~(1UL << (valid_field % PEM_MAX_NUM_EVENTDATAVALID_BITS_PER_FIELD)); -} - -static inline unsigned long pem_is_event_data_valid(const unsigned long *fields, PEM_EventDataValid valid_field) -{ - return fields[valid_field / PEM_MAX_NUM_EVENTDATAVALID_BITS_PER_FIELD] & - (1UL << (valid_field % PEM_MAX_NUM_EVENTDATAVALID_BITS_PER_FIELD)); -} - -struct pem_event_data { - unsigned long valid_fields[100]; - unsigned long requested_state_id; - enum PP_StateUILabel requested_ui_label; - struct pp_power_state *pnew_power_state; - enum pp_power_source requested_power_source; - struct PP_Clocks requested_clocks; - bool skip_state_adjust_rules; - struct phm_asic_blocks asic_blocks; - /* to doPP_ThermalState requestedThermalState; - enum ThermalStateRequestSrc requestThermalStateSrc; - PP_Temperature currentTemperature;*/ - -}; - -int pem_handle_event(struct pp_eventmgr *eventmgr, enum amd_pp_event event, - struct pem_event_data *event_data); - -bool pem_is_hw_access_blocked(struct pp_eventmgr *eventmgr); - -#endif /* _EVENT_MANAGER_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/inc/eventmgr.h b/drivers/gpu/drm/amd/powerplay/inc/eventmgr.h deleted file mode 100644 index 7bd8a7e..0000000 --- a/drivers/gpu/drm/amd/powerplay/inc/eventmgr.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2015 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef _EVENTMGR_H_ -#define _EVENTMGR_H_ - -#include <linux/mutex.h> -#include "pp_instance.h" -#include "hardwaremanager.h" -#include "eventmanager.h" -#include "pp_feature.h" -#include "pp_power_source.h" -#include "power_state.h" - -typedef int (*pem_event_action)(struct pp_eventmgr *eventmgr, - struct pem_event_data *event_data); - -struct action_chain { - const char *description; /* action chain description for debugging purpose */ - const pem_event_action * const *action_chain; /* pointer to chain of event actions */ -}; - -struct pem_power_source_ui_state_info { - enum PP_StateUILabel current_ui_label; - enum PP_StateUILabel default_ui_lable; - unsigned long configurable_ui_mapping; -}; - -struct pp_clock_range { - uint32_t min_sclk_khz; - uint32_t max_sclk_khz; - - uint32_t min_mclk_khz; - uint32_t max_mclk_khz; - - uint32_t min_vclk_khz; - uint32_t max_vclk_khz; - - uint32_t min_dclk_khz; - uint32_t max_dclk_khz; - - uint32_t min_aclk_khz; - uint32_t max_aclk_khz; - - uint32_t min_eclk_khz; - uint32_t max_eclk_khz; -}; - -enum pp_state { - UNINITIALIZED, - INACTIVE, - ACTIVE -}; - -enum pp_ring_index { - PP_RING_TYPE_GFX_INDEX = 0, - PP_RING_TYPE_DMA_INDEX, - PP_RING_TYPE_DMA1_INDEX, - PP_RING_TYPE_UVD_INDEX, - PP_RING_TYPE_VCE0_INDEX, - PP_RING_TYPE_VCE1_INDEX, - PP_RING_TYPE_CP1_INDEX, - PP_RING_TYPE_CP2_INDEX, - PP_NUM_RINGS, -}; - -struct pp_request { - uint32_t flags; - uint32_t sclk; - uint32_t sclk_throttle; - uint32_t mclk; - uint32_t vclk; - uint32_t dclk; - uint32_t eclk; - uint32_t aclk; - uint32_t iclk; - uint32_t vp8clk; - uint32_t rsv[32]; -}; - -struct pp_eventmgr { - struct pp_hwmgr *hwmgr; - struct pp_smumgr *smumgr; - - struct pp_feature_info features[PP_Feature_Max]; - const struct action_chain *event_chain[AMD_PP_EVENT_MAX]; - struct phm_platform_descriptor *platform_descriptor; - struct pp_clock_range clock_range; - enum pp_power_source current_power_source; - struct pem_power_source_ui_state_info ui_state_info[PP_PowerSource_Max]; - enum pp_state states[PP_NUM_RINGS]; - struct pp_request hi_req; - struct list_head context_list; - struct mutex lock; - bool block_adjust_power_state; - bool enable_cg; - bool enable_gfx_cgpg; - int (*pp_eventmgr_init)(struct pp_eventmgr *eventmgr); - void (*pp_eventmgr_fini)(struct pp_eventmgr *eventmgr); -}; - -int eventmgr_early_init(struct pp_instance *handle); - -#endif /* _EVENTMGR_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h b/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h index a4c8b09..57a0467 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h @@ -283,6 +283,8 @@ static inline bool phm_cap_enabled(const uint32_t *caps, enum phm_platform_caps (1UL << (c & (PHM_MAX_NUM_CAPS_BITS_PER_FIELD - 1))))); } +#define PP_CAP(c) phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, (c)) + #define PP_PCIEGenInvalid 0xffff enum PP_PCIEGen { PP_PCIEGen1 = 0, /* PCIE 1.0 - Transfer rate of 2.5 GT/s */ @@ -295,7 +297,7 @@ typedef enum PP_PCIEGen PP_PCIEGen; #define PP_Min_PCIEGen PP_PCIEGen1 #define PP_Max_PCIEGen PP_PCIEGen3 #define PP_Min_PCIELane 1 -#define PP_Max_PCIELane 32 +#define PP_Max_PCIELane 16 enum phm_clock_Type { PHM_DispClock = 1, @@ -373,8 +375,6 @@ struct phm_odn_clock_levels { extern int phm_disable_clock_power_gatings(struct pp_hwmgr *hwmgr); extern int phm_enable_clock_power_gatings(struct pp_hwmgr *hwmgr); -extern int phm_powergate_uvd(struct pp_hwmgr *hwmgr, bool gate); -extern int phm_powergate_vce(struct pp_hwmgr *hwmgr, bool gate); extern int phm_powerdown_uvd(struct pp_hwmgr *hwmgr); extern int phm_setup_asic(struct pp_hwmgr *hwmgr); extern int phm_enable_dynamic_state_management(struct pp_hwmgr *hwmgr); diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h index 91b0105..126b44d 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h @@ -32,6 +32,7 @@ #include "ppatomctrl.h" #include "hwmgr_ppt.h" #include "power_state.h" +#include "cgs_linux.h" struct pp_instance; struct pp_hwmgr; @@ -61,10 +62,6 @@ struct vi_dpm_table { struct vi_dpm_level dpm_level[1]; }; -enum PP_Result { - PP_Result_TableImmediateExit = 0x13, -}; - #define PCIE_PERF_REQ_REMOVE_REGISTRY 0 #define PCIE_PERF_REQ_FORCE_LOWPOWER 1 #define PCIE_PERF_REQ_GEN1 2 @@ -103,17 +100,6 @@ enum PHM_BackEnd_Magic { PHM_Rv_Magic = 0x20161121 }; - -#define PHM_PCIE_POWERGATING_TARGET_GFX 0 -#define PHM_PCIE_POWERGATING_TARGET_DDI 1 -#define PHM_PCIE_POWERGATING_TARGET_PLLCASCADE 2 -#define PHM_PCIE_POWERGATING_TARGET_PHY 3 - -typedef int (*phm_table_function)(struct pp_hwmgr *hwmgr, void *input, - void *output, void *storage, int result); - -typedef bool (*phm_check_function)(struct pp_hwmgr *hwmgr); - struct phm_set_power_state_input { const struct pp_hw_power_state *pcurrent_state; const struct pp_hw_power_state *pnew_state; @@ -149,30 +135,6 @@ struct phm_gfx_arbiter { uint32_t fclk; }; -/* Entries in the master tables */ -struct phm_master_table_item { - phm_check_function isFunctionNeededInRuntimeTable; - phm_table_function tableFunction; -}; - -enum phm_master_table_flag { - PHM_MasterTableFlag_None = 0, - PHM_MasterTableFlag_ExitOnError = 1, -}; - -/* The header of the master tables */ -struct phm_master_table_header { - uint32_t storage_size; - uint32_t flags; - const struct phm_master_table_item *master_list; -}; - -struct phm_runtime_table_header { - uint32_t storage_size; - bool exit_error; - phm_table_function *function_list; -}; - struct phm_clock_array { uint32_t count; uint32_t values[1]; @@ -216,19 +178,6 @@ struct phm_phase_shedding_limits_record { uint32_t Mclk; }; - -extern int phm_dispatch_table(struct pp_hwmgr *hwmgr, - struct phm_runtime_table_header *rt_table, - void *input, void *output); - -extern int phm_construct_table(struct pp_hwmgr *hwmgr, - const struct phm_master_table_header *master_table, - struct phm_runtime_table_header *rt_table); - -extern int phm_destroy_table(struct pp_hwmgr *hwmgr, - struct phm_runtime_table_header *rt_table); - - struct phm_uvd_clock_voltage_dependency_record { uint32_t vclk; uint32_t dclk; @@ -286,6 +235,39 @@ struct phm_vce_clock_voltage_dependency_table { struct phm_vce_clock_voltage_dependency_record entries[1]; }; +struct pp_smumgr_func { + int (*smu_init)(struct pp_hwmgr *hwmgr); + int (*smu_fini)(struct pp_hwmgr *hwmgr); + int (*start_smu)(struct pp_hwmgr *hwmgr); + int (*check_fw_load_finish)(struct pp_hwmgr *hwmgr, + uint32_t firmware); + int (*request_smu_load_fw)(struct pp_hwmgr *hwmgr); + int (*request_smu_load_specific_fw)(struct pp_hwmgr *hwmgr, + uint32_t firmware); + int (*get_argument)(struct pp_hwmgr *hwmgr); + int (*send_msg_to_smc)(struct pp_hwmgr *hwmgr, uint16_t msg); + int (*send_msg_to_smc_with_parameter)(struct pp_hwmgr *hwmgr, + uint16_t msg, uint32_t parameter); + int (*download_pptable_settings)(struct pp_hwmgr *hwmgr, + void **table); + int (*upload_pptable_settings)(struct pp_hwmgr *hwmgr); + int (*update_smc_table)(struct pp_hwmgr *hwmgr, uint32_t type); + int (*process_firmware_header)(struct pp_hwmgr *hwmgr); + int (*update_sclk_threshold)(struct pp_hwmgr *hwmgr); + int (*thermal_setup_fan_table)(struct pp_hwmgr *hwmgr); + int (*thermal_avfs_enable)(struct pp_hwmgr *hwmgr); + int (*init_smc_table)(struct pp_hwmgr *hwmgr); + int (*populate_all_graphic_levels)(struct pp_hwmgr *hwmgr); + int (*populate_all_memory_levels)(struct pp_hwmgr *hwmgr); + int (*initialize_mc_reg_table)(struct pp_hwmgr *hwmgr); + uint32_t (*get_offsetof)(uint32_t type, uint32_t member); + uint32_t (*get_mac_definition)(uint32_t value); + bool (*is_dpm_running)(struct pp_hwmgr *hwmgr); + int (*populate_requested_graphic_levels)(struct pp_hwmgr *hwmgr, + struct amd_pp_profile *request); + bool (*is_hw_avfs_present)(struct pp_hwmgr *hwmgr); +}; + struct pp_hwmgr_func { int (*backend_init)(struct pp_hwmgr *hw_mgr); int (*backend_fini)(struct pp_hwmgr *hw_mgr); @@ -311,10 +293,10 @@ struct pp_hwmgr_func { unsigned long, struct pp_power_state *); int (*get_num_of_pp_table_entries)(struct pp_hwmgr *hwmgr); int (*powerdown_uvd)(struct pp_hwmgr *hwmgr); - int (*powergate_vce)(struct pp_hwmgr *hwmgr, bool bgate); - int (*powergate_uvd)(struct pp_hwmgr *hwmgr, bool bgate); - int (*get_mclk)(struct pp_hwmgr *hwmgr, bool low); - int (*get_sclk)(struct pp_hwmgr *hwmgr, bool low); + void (*powergate_vce)(struct pp_hwmgr *hwmgr, bool bgate); + void (*powergate_uvd)(struct pp_hwmgr *hwmgr, bool bgate); + uint32_t (*get_mclk)(struct pp_hwmgr *hwmgr, bool low); + uint32_t (*get_sclk)(struct pp_hwmgr *hwmgr, bool low); int (*power_state_set)(struct pp_hwmgr *hwmgr, const void *state); int (*enable_clock_power_gating)(struct pp_hwmgr *hwmgr); @@ -328,8 +310,8 @@ struct pp_hwmgr_func { int (*get_temperature)(struct pp_hwmgr *hwmgr); int (*stop_thermal_controller)(struct pp_hwmgr *hwmgr); int (*get_fan_speed_info)(struct pp_hwmgr *hwmgr, struct phm_fan_speed_info *fan_speed_info); - int (*set_fan_control_mode)(struct pp_hwmgr *hwmgr, uint32_t mode); - int (*get_fan_control_mode)(struct pp_hwmgr *hwmgr); + void (*set_fan_control_mode)(struct pp_hwmgr *hwmgr, uint32_t mode); + uint32_t (*get_fan_control_mode)(struct pp_hwmgr *hwmgr); int (*set_fan_speed_percent)(struct pp_hwmgr *hwmgr, uint32_t percent); int (*get_fan_speed_percent)(struct pp_hwmgr *hwmgr, uint32_t *speed); int (*set_fan_speed_rpm)(struct pp_hwmgr *hwmgr, uint32_t percent); @@ -378,6 +360,9 @@ struct pp_hwmgr_func { struct amd_pp_profile *request); int (*avfs_control)(struct pp_hwmgr *hwmgr, bool enable); int (*disable_smc_firmware_ctf)(struct pp_hwmgr *hwmgr); + int (*set_active_display_count)(struct pp_hwmgr *hwmgr, uint32_t count); + int (*set_deep_sleep_dcefclk)(struct pp_hwmgr *hwmgr, uint32_t clock); + int (*start_thermal_controller)(struct pp_hwmgr *hwmgr, struct PP_TemperatureRange *range); }; struct pp_table_func { @@ -745,7 +730,7 @@ struct pp_hwmgr { enum amd_dpm_forced_level dpm_level; enum amd_dpm_forced_level saved_dpm_level; - bool block_hw_access; + enum amd_dpm_forced_level request_dpm_level; struct phm_gfx_arbiter gfx_arbiter; struct phm_acp_arbiter acp_arbiter; struct phm_uvd_arbiter uvd_arbiter; @@ -754,19 +739,17 @@ struct pp_hwmgr { void *pptable; struct phm_platform_descriptor platform_descriptor; void *backend; + + void *smu_backend; + const struct pp_smumgr_func *smumgr_funcs; + bool is_kicker; + bool reload_fw; + enum PP_DAL_POWERLEVEL dal_power_level; struct phm_dynamic_state_info dyn_state; - struct phm_runtime_table_header setup_asic; - struct phm_runtime_table_header power_down_asic; - struct phm_runtime_table_header disable_dynamic_state_management; - struct phm_runtime_table_header enable_dynamic_state_management; - struct phm_runtime_table_header set_power_state; - struct phm_runtime_table_header enable_clock_power_gatings; - struct phm_runtime_table_header display_configuration_changed; - struct phm_runtime_table_header start_thermal_controller; - struct phm_runtime_table_header set_temperature_range; const struct pp_hwmgr_func *hwmgr_func; const struct pp_table_func *pptable_func; + struct pp_power_state *ps; enum pp_power_source power_source; uint32_t num_ps; @@ -784,26 +767,44 @@ struct pp_hwmgr { struct amd_pp_display_configuration display_config; uint32_t feature_mask; - /* power profile */ + /* UMD Pstate */ struct amd_pp_profile gfx_power_profile; struct amd_pp_profile compute_power_profile; struct amd_pp_profile default_gfx_power_profile; struct amd_pp_profile default_compute_power_profile; enum amd_pp_profile_type current_power_profile; + bool en_umd_pstate; +}; + +struct cgs_irq_src_funcs { + cgs_irq_source_set_func_t set; + cgs_irq_handler_func_t handler; }; extern int hwmgr_early_init(struct pp_instance *handle); extern int hwmgr_hw_init(struct pp_instance *handle); extern int hwmgr_hw_fini(struct pp_instance *handle); +extern int hwmgr_hw_suspend(struct pp_instance *handle); +extern int hwmgr_hw_resume(struct pp_instance *handle); +extern int hwmgr_handle_task(struct pp_instance *handle, + enum amd_pp_task task_id, + void *input, void *output); extern int phm_wait_on_register(struct pp_hwmgr *hwmgr, uint32_t index, uint32_t value, uint32_t mask); -extern void phm_wait_on_indirect_register(struct pp_hwmgr *hwmgr, +extern int phm_wait_on_indirect_register(struct pp_hwmgr *hwmgr, uint32_t indirect_port, uint32_t index, uint32_t value, uint32_t mask); +extern int phm_wait_for_register_unequal(struct pp_hwmgr *hwmgr, + uint32_t index, + uint32_t value, uint32_t mask); +extern int phm_wait_for_indirect_register_unequal( + struct pp_hwmgr *hwmgr, + uint32_t indirect_port, uint32_t index, + uint32_t value, uint32_t mask); extern bool phm_cf_want_uvd_power_gating(struct pp_hwmgr *hwmgr); @@ -888,5 +889,58 @@ extern int phm_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_t PHM_WAIT_INDIRECT_REGISTER(hwmgr, port, reg, (fieldval) \ << PHM_FIELD_SHIFT(reg, field), PHM_FIELD_MASK(reg, field)) +#define PHM_WAIT_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, index, value, mask) \ + phm_wait_for_indirect_register_unequal(hwmgr, \ + mm##port##_INDEX, index, value, mask) + +#define PHM_WAIT_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, value, mask) \ + PHM_WAIT_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask) + +#define PHM_WAIT_INDIRECT_FIELD_UNEQUAL(hwmgr, port, reg, field, fieldval) \ + PHM_WAIT_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, \ + (fieldval) << PHM_FIELD_SHIFT(reg, field), \ + PHM_FIELD_MASK(reg, field) ) + + +#define PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, \ + port, index, value, mask) \ + phm_wait_for_indirect_register_unequal(hwmgr, \ + mm##port##_INDEX_11, index, value, mask) + +#define PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, value, mask) \ + PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask) + +#define PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, port, reg, field, fieldval) \ + PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, \ + (fieldval) << PHM_FIELD_SHIFT(reg, field), \ + PHM_FIELD_MASK(reg, field)) + + +#define PHM_WAIT_VFPF_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, \ + port, index, value, mask) \ + phm_wait_on_indirect_register(hwmgr, \ + mm##port##_INDEX_11, index, value, mask) + +#define PHM_WAIT_VFPF_INDIRECT_REGISTER(hwmgr, port, reg, value, mask) \ + PHM_WAIT_VFPF_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask) + +#define PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, port, reg, field, fieldval) \ + PHM_WAIT_VFPF_INDIRECT_REGISTER(hwmgr, port, reg, \ + (fieldval) << PHM_FIELD_SHIFT(reg, field), \ + PHM_FIELD_MASK(reg, field)) + +#define PHM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, \ + index, value, mask) \ + phm_wait_for_register_unequal(hwmgr, \ + index, value, mask) + +#define PHM_WAIT_REGISTER_UNEQUAL(hwmgr, reg, value, mask) \ + PHM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, \ + mm##reg, value, mask) + +#define PHM_WAIT_FIELD_UNEQUAL(hwmgr, reg, field, fieldval) \ + PHM_WAIT_REGISTER_UNEQUAL(hwmgr, reg, \ + (fieldval) << PHM_FIELD_SHIFT(reg, field), \ + PHM_FIELD_MASK(reg, field)) #endif /* _HWMGR_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/inc/pp_instance.h b/drivers/gpu/drm/amd/powerplay/inc/pp_instance.h index 4c3b537..25fb146 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/pp_instance.h +++ b/drivers/gpu/drm/amd/powerplay/inc/pp_instance.h @@ -23,9 +23,7 @@ #ifndef _PP_INSTANCE_H_ #define _PP_INSTANCE_H_ -#include "smumgr.h" #include "hwmgr.h" -#include "eventmgr.h" #define PP_VALID 0x1F1F1F1F @@ -36,9 +34,7 @@ struct pp_instance { bool pm_en; uint32_t feature_mask; void *device; - struct pp_smumgr *smu_mgr; struct pp_hwmgr *hwmgr; - struct pp_eventmgr *eventmgr; struct mutex pp_lock; }; diff --git a/drivers/gpu/drm/amd/powerplay/inc/smumgr.h b/drivers/gpu/drm/amd/powerplay/inc/smumgr.h index 5d61cc9..7c9aba8 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smumgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smumgr.h @@ -23,23 +23,13 @@ #ifndef _SMUMGR_H_ #define _SMUMGR_H_ #include <linux/types.h> -#include "pp_instance.h" #include "amd_powerplay.h" - -struct pp_smumgr; -struct pp_instance; -struct pp_hwmgr; +#include "hwmgr.h" #define smu_lower_32_bits(n) ((uint32_t)(n)) #define smu_upper_32_bits(n) ((uint32_t)(((n)>>16)>>16)) -extern const struct pp_smumgr_func cz_smu_funcs; -extern const struct pp_smumgr_func iceland_smu_funcs; -extern const struct pp_smumgr_func tonga_smu_funcs; -extern const struct pp_smumgr_func fiji_smu_funcs; -extern const struct pp_smumgr_func polaris10_smu_funcs; -extern const struct pp_smumgr_func vega10_smu_funcs; -extern const struct pp_smumgr_func rv_smu_funcs; + enum AVFS_BTC_STATUS { AVFS_BTC_BOOT = 0, @@ -100,216 +90,44 @@ enum SMU_MAC_DEFINITION { SMU_UVD_MCLK_HANDSHAKE_DISABLE, }; +extern int smum_get_argument(struct pp_hwmgr *hwmgr); -struct pp_smumgr_func { - int (*smu_init)(struct pp_smumgr *smumgr); - int (*smu_fini)(struct pp_smumgr *smumgr); - int (*start_smu)(struct pp_smumgr *smumgr); - int (*check_fw_load_finish)(struct pp_smumgr *smumgr, - uint32_t firmware); - int (*request_smu_load_fw)(struct pp_smumgr *smumgr); - int (*request_smu_load_specific_fw)(struct pp_smumgr *smumgr, - uint32_t firmware); - int (*get_argument)(struct pp_smumgr *smumgr); - int (*send_msg_to_smc)(struct pp_smumgr *smumgr, uint16_t msg); - int (*send_msg_to_smc_with_parameter)(struct pp_smumgr *smumgr, - uint16_t msg, uint32_t parameter); - int (*download_pptable_settings)(struct pp_smumgr *smumgr, - void **table); - int (*upload_pptable_settings)(struct pp_smumgr *smumgr); - int (*update_smc_table)(struct pp_hwmgr *hwmgr, uint32_t type); - int (*process_firmware_header)(struct pp_hwmgr *hwmgr); - int (*update_sclk_threshold)(struct pp_hwmgr *hwmgr); - int (*thermal_setup_fan_table)(struct pp_hwmgr *hwmgr); - int (*thermal_avfs_enable)(struct pp_hwmgr *hwmgr); - int (*init_smc_table)(struct pp_hwmgr *hwmgr); - int (*populate_all_graphic_levels)(struct pp_hwmgr *hwmgr); - int (*populate_all_memory_levels)(struct pp_hwmgr *hwmgr); - int (*initialize_mc_reg_table)(struct pp_hwmgr *hwmgr); - uint32_t (*get_offsetof)(uint32_t type, uint32_t member); - uint32_t (*get_mac_definition)(uint32_t value); - bool (*is_dpm_running)(struct pp_hwmgr *hwmgr); - int (*populate_requested_graphic_levels)(struct pp_hwmgr *hwmgr, - struct amd_pp_profile *request); - bool (*is_hw_avfs_present)(struct pp_smumgr *smumgr); -}; - -struct pp_smumgr { - uint32_t chip_family; - uint32_t chip_id; - void *device; - void *backend; - uint32_t usec_timeout; - bool reload_fw; - const struct pp_smumgr_func *smumgr_funcs; - bool is_kicker; -}; - -extern int smum_early_init(struct pp_instance *handle); +extern int smum_download_powerplay_table(struct pp_hwmgr *hwmgr, void **table); -extern int smum_get_argument(struct pp_smumgr *smumgr); +extern int smum_upload_powerplay_table(struct pp_hwmgr *hwmgr); -extern int smum_download_powerplay_table(struct pp_smumgr *smumgr, void **table); +extern int smum_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg); -extern int smum_upload_powerplay_table(struct pp_smumgr *smumgr); - -extern int smum_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg); - -extern int smum_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr, +extern int smum_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, uint16_t msg, uint32_t parameter); -extern int smum_wait_on_register(struct pp_smumgr *smumgr, - uint32_t index, uint32_t value, uint32_t mask); - -extern int smum_wait_for_register_unequal(struct pp_smumgr *smumgr, - uint32_t index, uint32_t value, uint32_t mask); - -extern int smum_wait_on_indirect_register(struct pp_smumgr *smumgr, - uint32_t indirect_port, uint32_t index, - uint32_t value, uint32_t mask); - - -extern void smum_wait_for_indirect_register_unequal( - struct pp_smumgr *smumgr, - uint32_t indirect_port, uint32_t index, - uint32_t value, uint32_t mask); - extern int smu_allocate_memory(void *device, uint32_t size, enum cgs_gpu_mem_type type, uint32_t byte_align, uint64_t *mc_addr, void **kptr, void *handle); extern int smu_free_memory(void *device, void *handle); -extern int vega10_smum_init(struct pp_smumgr *smumgr); extern int smum_update_sclk_threshold(struct pp_hwmgr *hwmgr); extern int smum_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type); extern int smum_process_firmware_header(struct pp_hwmgr *hwmgr); -extern int smum_thermal_avfs_enable(struct pp_hwmgr *hwmgr, - void *input, void *output, void *storage, int result); -extern int smum_thermal_setup_fan_table(struct pp_hwmgr *hwmgr, - void *input, void *output, void *storage, int result); +extern int smum_thermal_avfs_enable(struct pp_hwmgr *hwmgr); +extern int smum_thermal_setup_fan_table(struct pp_hwmgr *hwmgr); extern int smum_init_smc_table(struct pp_hwmgr *hwmgr); extern int smum_populate_all_graphic_levels(struct pp_hwmgr *hwmgr); extern int smum_populate_all_memory_levels(struct pp_hwmgr *hwmgr); extern int smum_initialize_mc_reg_table(struct pp_hwmgr *hwmgr); -extern uint32_t smum_get_offsetof(struct pp_smumgr *smumgr, +extern uint32_t smum_get_offsetof(struct pp_hwmgr *hwmgr, uint32_t type, uint32_t member); -extern uint32_t smum_get_mac_definition(struct pp_smumgr *smumgr, uint32_t value); +extern uint32_t smum_get_mac_definition(struct pp_hwmgr *hwmgr, uint32_t value); extern bool smum_is_dpm_running(struct pp_hwmgr *hwmgr); extern int smum_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr, struct amd_pp_profile *request); -extern bool smum_is_hw_avfs_present(struct pp_smumgr *smumgr); - -#define SMUM_FIELD_SHIFT(reg, field) reg##__##field##__SHIFT - -#define SMUM_FIELD_MASK(reg, field) reg##__##field##_MASK - -#define SMUM_WAIT_INDIRECT_REGISTER_GIVEN_INDEX(smumgr, \ - port, index, value, mask) \ - smum_wait_on_indirect_register(smumgr, \ - mm##port##_INDEX, index, value, mask) - -#define SMUM_WAIT_INDIRECT_REGISTER(smumgr, port, reg, value, mask) \ - SMUM_WAIT_INDIRECT_REGISTER_GIVEN_INDEX(smumgr, port, ix##reg, value, mask) - -#define SMUM_WAIT_INDIRECT_FIELD(smumgr, port, reg, field, fieldval) \ - SMUM_WAIT_INDIRECT_REGISTER(smumgr, port, reg, (fieldval) << SMUM_FIELD_SHIFT(reg, field), \ - SMUM_FIELD_MASK(reg, field) ) - -#define SMUM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(smumgr, \ - index, value, mask) \ - smum_wait_for_register_unequal(smumgr, \ - index, value, mask) - -#define SMUM_WAIT_REGISTER_UNEQUAL(smumgr, reg, value, mask) \ - SMUM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(smumgr, \ - mm##reg, value, mask) - -#define SMUM_WAIT_FIELD_UNEQUAL(smumgr, reg, field, fieldval) \ - SMUM_WAIT_REGISTER_UNEQUAL(smumgr, reg, \ - (fieldval) << SMUM_FIELD_SHIFT(reg, field), \ - SMUM_FIELD_MASK(reg, field)) - -#define SMUM_GET_FIELD(value, reg, field) \ - (((value) & SMUM_FIELD_MASK(reg, field)) \ - >> SMUM_FIELD_SHIFT(reg, field)) - -#define SMUM_READ_FIELD(device, reg, field) \ - SMUM_GET_FIELD(cgs_read_register(device, mm##reg), reg, field) - -#define SMUM_SET_FIELD(value, reg, field, field_val) \ - (((value) & ~SMUM_FIELD_MASK(reg, field)) | \ - (SMUM_FIELD_MASK(reg, field) & ((field_val) << \ - SMUM_FIELD_SHIFT(reg, field)))) - -#define SMUM_READ_INDIRECT_FIELD(device, port, reg, field) \ - SMUM_GET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ - reg, field) - -#define SMUM_WAIT_VFPF_INDIRECT_REGISTER_GIVEN_INDEX(smumgr, \ - port, index, value, mask) \ - smum_wait_on_indirect_register(smumgr, \ - mm##port##_INDEX_0, index, value, mask) - -#define SMUM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(smumgr, \ - port, index, value, mask) \ - smum_wait_for_indirect_register_unequal(smumgr, \ - mm##port##_INDEX_0, index, value, mask) - - -#define SMUM_WAIT_VFPF_INDIRECT_REGISTER(smumgr, port, reg, value, mask) \ - SMUM_WAIT_VFPF_INDIRECT_REGISTER_GIVEN_INDEX(smumgr, port, ix##reg, value, mask) - -#define SMUM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL(smumgr, port, reg, value, mask) \ - SMUM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(smumgr, port, ix##reg, value, mask) - - -/*Operations on named fields.*/ - -#define SMUM_READ_VFPF_INDIRECT_FIELD(device, port, reg, field) \ - SMUM_GET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ - reg, field) - -#define SMUM_WRITE_FIELD(device, reg, field, fieldval) \ - cgs_write_register(device, mm##reg, \ - SMUM_SET_FIELD(cgs_read_register(device, mm##reg), reg, field, fieldval)) - -#define SMUM_WRITE_VFPF_INDIRECT_FIELD(device, port, reg, field, fieldval) \ - cgs_write_ind_register(device, port, ix##reg, \ - SMUM_SET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ - reg, field, fieldval)) - - -#define SMUM_WRITE_INDIRECT_FIELD(device, port, reg, field, fieldval) \ - cgs_write_ind_register(device, port, ix##reg, \ - SMUM_SET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ - reg, field, fieldval)) - - -#define SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, port, reg, field, fieldval) \ - SMUM_WAIT_VFPF_INDIRECT_REGISTER(smumgr, port, reg, \ - (fieldval) << SMUM_FIELD_SHIFT(reg, field), \ - SMUM_FIELD_MASK(reg, field)) - -#define SMUM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(smumgr, port, reg, field, fieldval) \ - SMUM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL(smumgr, port, reg, \ - (fieldval) << SMUM_FIELD_SHIFT(reg, field), \ - SMUM_FIELD_MASK(reg, field)) - -#define SMUM_WAIT_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(smumgr, port, index, value, mask) \ - smum_wait_for_indirect_register_unequal(smumgr, \ - mm##port##_INDEX, index, value, mask) - -#define SMUM_WAIT_INDIRECT_REGISTER_UNEQUAL(smumgr, port, reg, value, mask) \ - SMUM_WAIT_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(smumgr, port, ix##reg, value, mask) +extern bool smum_is_hw_avfs_present(struct pp_hwmgr *hwmgr); -#define SMUM_WAIT_INDIRECT_FIELD_UNEQUAL(smumgr, port, reg, field, fieldval) \ - SMUM_WAIT_INDIRECT_REGISTER_UNEQUAL(smumgr, port, reg, (fieldval) << SMUM_FIELD_SHIFT(reg, field), \ - SMUM_FIELD_MASK(reg, field) ) #endif diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/Makefile b/drivers/gpu/drm/amd/powerplay/smumgr/Makefile index 1703bbe..a423c0a 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/Makefile +++ b/drivers/gpu/drm/amd/powerplay/smumgr/Makefile @@ -4,7 +4,7 @@ SMU_MGR = smumgr.o cz_smumgr.o tonga_smumgr.o fiji_smumgr.o fiji_smc.o \ polaris10_smumgr.o iceland_smumgr.o polaris10_smc.o tonga_smc.o \ - smu7_smumgr.o iceland_smc.o vega10_smumgr.o rv_smumgr.o + smu7_smumgr.o iceland_smc.o vega10_smumgr.o rv_smumgr.o ci_smc.o ci_smumgr.o AMD_PP_SMUMGR = $(addprefix $(AMD_PP_PATH)/smumgr/,$(SMU_MGR)) diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smc.c b/drivers/gpu/drm/amd/powerplay/smumgr/ci_smc.c new file mode 100644 index 0000000..9ee1431 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/smumgr/ci_smc.c @@ -0,0 +1,2753 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/fb.h> +#include "linux/delay.h" +#include <linux/types.h> + +#include "smumgr.h" +#include "pp_debug.h" +#include "ci_smc.h" +#include "ci_smumgr.h" +#include "ppsmc.h" +#include "smu7_hwmgr.h" +#include "hardwaremanager.h" +#include "ppatomctrl.h" +#include "cgs_common.h" +#include "atombios.h" +#include "pppcielanes.h" + +#include "smu/smu_7_0_1_d.h" +#include "smu/smu_7_0_1_sh_mask.h" + +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + +#include "bif/bif_4_1_d.h" +#include "bif/bif_4_1_sh_mask.h" + +#include "gca/gfx_7_2_d.h" +#include "gca/gfx_7_2_sh_mask.h" + +#include "gmc/gmc_7_1_d.h" +#include "gmc/gmc_7_1_sh_mask.h" + +#include "processpptables.h" + +#define MC_CG_ARB_FREQ_F0 0x0a +#define MC_CG_ARB_FREQ_F1 0x0b +#define MC_CG_ARB_FREQ_F2 0x0c +#define MC_CG_ARB_FREQ_F3 0x0d + +#define SMC_RAM_END 0x40000 + +#define VOLTAGE_SCALE 4 +#define VOLTAGE_VID_OFFSET_SCALE1 625 +#define VOLTAGE_VID_OFFSET_SCALE2 100 +#define CISLAND_MINIMUM_ENGINE_CLOCK 800 +#define CISLAND_MAX_DEEPSLEEP_DIVIDER_ID 5 + +static const struct ci_pt_defaults defaults_hawaii_xt = { + 1, 0xF, 0xFD, 0x19, 5, 0x14, 0, 0xB0000, + { 0x2E, 0x00, 0x00, 0x88, 0x00, 0x00, 0x72, 0x60, 0x51, 0xA7, 0x79, 0x6B, 0x90, 0xBD, 0x79 }, + { 0x217, 0x217, 0x217, 0x242, 0x242, 0x242, 0x269, 0x269, 0x269, 0x2A1, 0x2A1, 0x2A1, 0x2C9, 0x2C9, 0x2C9 } +}; + +static const struct ci_pt_defaults defaults_hawaii_pro = { + 1, 0xF, 0xFD, 0x19, 5, 0x14, 0, 0x65062, + { 0x2E, 0x00, 0x00, 0x88, 0x00, 0x00, 0x72, 0x60, 0x51, 0xA7, 0x79, 0x6B, 0x90, 0xBD, 0x79 }, + { 0x217, 0x217, 0x217, 0x242, 0x242, 0x242, 0x269, 0x269, 0x269, 0x2A1, 0x2A1, 0x2A1, 0x2C9, 0x2C9, 0x2C9 } +}; + +static const struct ci_pt_defaults defaults_bonaire_xt = { + 1, 0xF, 0xFD, 0x19, 5, 45, 0, 0xB0000, + { 0x79, 0x253, 0x25D, 0xAE, 0x72, 0x80, 0x83, 0x86, 0x6F, 0xC8, 0xC9, 0xC9, 0x2F, 0x4D, 0x61 }, + { 0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203, 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4 } +}; + + +static const struct ci_pt_defaults defaults_saturn_xt = { + 1, 0xF, 0xFD, 0x19, 5, 55, 0, 0x70000, + { 0x8C, 0x247, 0x249, 0xA6, 0x80, 0x81, 0x8B, 0x89, 0x86, 0xC9, 0xCA, 0xC9, 0x4D, 0x4D, 0x4D }, + { 0x187, 0x187, 0x187, 0x1C7, 0x1C7, 0x1C7, 0x210, 0x210, 0x210, 0x266, 0x266, 0x266, 0x2C9, 0x2C9, 0x2C9 } +}; + + +static int ci_set_smc_sram_address(struct pp_hwmgr *hwmgr, + uint32_t smc_addr, uint32_t limit) +{ + if ((0 != (3 & smc_addr)) + || ((smc_addr + 3) >= limit)) { + pr_err("smc_addr invalid \n"); + return -EINVAL; + } + + cgs_write_register(hwmgr->device, mmSMC_IND_INDEX_0, smc_addr); + PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 0); + return 0; +} + +static int ci_copy_bytes_to_smc(struct pp_hwmgr *hwmgr, uint32_t smc_start_address, + const uint8_t *src, uint32_t byte_count, uint32_t limit) +{ + int result; + uint32_t data = 0; + uint32_t original_data; + uint32_t addr = 0; + uint32_t extra_shift; + + if ((3 & smc_start_address) + || ((smc_start_address + byte_count) >= limit)) { + pr_err("smc_start_address invalid \n"); + return -EINVAL; + } + + addr = smc_start_address; + + while (byte_count >= 4) { + /* Bytes are written into the SMC address space with the MSB first. */ + data = src[0] * 0x1000000 + src[1] * 0x10000 + src[2] * 0x100 + src[3]; + + result = ci_set_smc_sram_address(hwmgr, addr, limit); + + if (0 != result) + return result; + + cgs_write_register(hwmgr->device, mmSMC_IND_DATA_0, data); + + src += 4; + byte_count -= 4; + addr += 4; + } + + if (0 != byte_count) { + + data = 0; + + result = ci_set_smc_sram_address(hwmgr, addr, limit); + + if (0 != result) + return result; + + + original_data = cgs_read_register(hwmgr->device, mmSMC_IND_DATA_0); + + extra_shift = 8 * (4 - byte_count); + + while (byte_count > 0) { + /* Bytes are written into the SMC addres space with the MSB first. */ + data = (0x100 * data) + *src++; + byte_count--; + } + + data <<= extra_shift; + + data |= (original_data & ~((~0UL) << extra_shift)); + + result = ci_set_smc_sram_address(hwmgr, addr, limit); + + if (0 != result) + return result; + + cgs_write_register(hwmgr->device, mmSMC_IND_DATA_0, data); + } + + return 0; +} + + +static int ci_program_jump_on_start(struct pp_hwmgr *hwmgr) +{ + static const unsigned char data[4] = { 0xE0, 0x00, 0x80, 0x40 }; + + ci_copy_bytes_to_smc(hwmgr, 0x0, data, 4, sizeof(data)+1); + + return 0; +} + +bool ci_is_smc_ram_running(struct pp_hwmgr *hwmgr) +{ + return ((0 == PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable)) + && (0x20100 <= cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, ixSMC_PC_C))); +} + +static int ci_read_smc_sram_dword(struct pp_hwmgr *hwmgr, uint32_t smc_addr, + uint32_t *value, uint32_t limit) +{ + int result; + + result = ci_set_smc_sram_address(hwmgr, smc_addr, limit); + + if (result) + return result; + + *value = cgs_read_register(hwmgr->device, mmSMC_IND_DATA_0); + return 0; +} + +int ci_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg) +{ + int ret; + + if (!ci_is_smc_ram_running(hwmgr)) + return -EINVAL; + + cgs_write_register(hwmgr->device, mmSMC_MESSAGE_0, msg); + + PHM_WAIT_FIELD_UNEQUAL(hwmgr, SMC_RESP_0, SMC_RESP, 0); + + ret = PHM_READ_FIELD(hwmgr->device, SMC_RESP_0, SMC_RESP); + + if (ret != 1) + pr_info("\n failed to send message %x ret is %d\n", msg, ret); + + return 0; +} + +int ci_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, + uint16_t msg, uint32_t parameter) +{ + cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, parameter); + return ci_send_msg_to_smc(hwmgr, msg); +} + +static void ci_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) +{ + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + struct cgs_system_info sys_info = {0}; + uint32_t dev_id; + + sys_info.size = sizeof(struct cgs_system_info); + sys_info.info_id = CGS_SYSTEM_INFO_PCIE_DEV; + cgs_query_system_info(hwmgr->device, &sys_info); + dev_id = (uint32_t)sys_info.value; + + switch (dev_id) { + case 0x67BA: + case 0x66B1: + smu_data->power_tune_defaults = &defaults_hawaii_pro; + break; + case 0x67B8: + case 0x66B0: + smu_data->power_tune_defaults = &defaults_hawaii_xt; + break; + case 0x6640: + case 0x6641: + case 0x6646: + case 0x6647: + smu_data->power_tune_defaults = &defaults_saturn_xt; + break; + case 0x6649: + case 0x6650: + case 0x6651: + case 0x6658: + case 0x665C: + case 0x665D: + case 0x67A0: + case 0x67A1: + case 0x67A2: + case 0x67A8: + case 0x67A9: + case 0x67AA: + case 0x67B9: + case 0x67BE: + default: + smu_data->power_tune_defaults = &defaults_bonaire_xt; + break; + } +} + +static int ci_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr, + struct phm_clock_voltage_dependency_table *allowed_clock_voltage_table, + uint32_t clock, uint32_t *vol) +{ + uint32_t i = 0; + + if (allowed_clock_voltage_table->count == 0) + return -EINVAL; + + for (i = 0; i < allowed_clock_voltage_table->count; i++) { + if (allowed_clock_voltage_table->entries[i].clk >= clock) { + *vol = allowed_clock_voltage_table->entries[i].v; + return 0; + } + } + + *vol = allowed_clock_voltage_table->entries[i - 1].v; + return 0; +} + +static int ci_calculate_sclk_params(struct pp_hwmgr *hwmgr, + uint32_t clock, struct SMU7_Discrete_GraphicsLevel *sclk) +{ + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct pp_atomctrl_clock_dividers_vi dividers; + uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; + uint32_t spll_func_cntl_3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; + uint32_t spll_func_cntl_4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; + uint32_t cg_spll_spread_spectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; + uint32_t cg_spll_spread_spectrum_2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; + uint32_t ref_clock; + uint32_t ref_divider; + uint32_t fbdiv; + int result; + + /* get the engine clock dividers for this clock value */ + result = atomctrl_get_engine_pll_dividers_vi(hwmgr, clock, ÷rs); + + PP_ASSERT_WITH_CODE(result == 0, + "Error retrieving Engine Clock dividers from VBIOS.", + return result); + + /* To get FBDIV we need to multiply this by 16384 and divide it by Fref. */ + ref_clock = atomctrl_get_reference_clock(hwmgr); + ref_divider = 1 + dividers.uc_pll_ref_div; + + /* low 14 bits is fraction and high 12 bits is divider */ + fbdiv = dividers.ul_fb_div.ul_fb_divider & 0x3FFFFFF; + + /* SPLL_FUNC_CNTL setup */ + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, + SPLL_REF_DIV, dividers.uc_pll_ref_div); + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, + SPLL_PDIV_A, dividers.uc_pll_post_div); + + /* SPLL_FUNC_CNTL_3 setup*/ + spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, CG_SPLL_FUNC_CNTL_3, + SPLL_FB_DIV, fbdiv); + + /* set to use fractional accumulation*/ + spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, CG_SPLL_FUNC_CNTL_3, + SPLL_DITHEN, 1); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EngineSpreadSpectrumSupport)) { + struct pp_atomctrl_internal_ss_info ss_info; + uint32_t vco_freq = clock * dividers.uc_pll_post_div; + + if (!atomctrl_get_engine_clock_spread_spectrum(hwmgr, + vco_freq, &ss_info)) { + uint32_t clk_s = ref_clock * 5 / + (ref_divider * ss_info.speed_spectrum_rate); + uint32_t clk_v = 4 * ss_info.speed_spectrum_percentage * + fbdiv / (clk_s * 10000); + + cg_spll_spread_spectrum = PHM_SET_FIELD(cg_spll_spread_spectrum, + CG_SPLL_SPREAD_SPECTRUM, CLKS, clk_s); + cg_spll_spread_spectrum = PHM_SET_FIELD(cg_spll_spread_spectrum, + CG_SPLL_SPREAD_SPECTRUM, SSEN, 1); + cg_spll_spread_spectrum_2 = PHM_SET_FIELD(cg_spll_spread_spectrum_2, + CG_SPLL_SPREAD_SPECTRUM_2, CLKV, clk_v); + } + } + + sclk->SclkFrequency = clock; + sclk->CgSpllFuncCntl3 = spll_func_cntl_3; + sclk->CgSpllFuncCntl4 = spll_func_cntl_4; + sclk->SpllSpreadSpectrum = cg_spll_spread_spectrum; + sclk->SpllSpreadSpectrum2 = cg_spll_spread_spectrum_2; + sclk->SclkDid = (uint8_t)dividers.pll_post_divider; + + return 0; +} + +static void ci_populate_phase_value_based_on_sclk(struct pp_hwmgr *hwmgr, + const struct phm_phase_shedding_limits_table *pl, + uint32_t sclk, uint32_t *p_shed) +{ + unsigned int i; + + /* use the minimum phase shedding */ + *p_shed = 1; + + for (i = 0; i < pl->count; i++) { + if (sclk < pl->entries[i].Sclk) { + *p_shed = i; + break; + } + } +} + +static uint8_t ci_get_sleep_divider_id_from_clock(uint32_t clock, + uint32_t clock_insr) +{ + uint8_t i; + uint32_t temp; + uint32_t min = min_t(uint32_t, clock_insr, CISLAND_MINIMUM_ENGINE_CLOCK); + + if (clock < min) { + pr_info("Engine clock can't satisfy stutter requirement!\n"); + return 0; + } + for (i = CISLAND_MAX_DEEPSLEEP_DIVIDER_ID; ; i--) { + temp = clock >> i; + + if (temp >= min || i == 0) + break; + } + return i; +} + +static int ci_populate_single_graphic_level(struct pp_hwmgr *hwmgr, + uint32_t clock, uint16_t sclk_al_threshold, + struct SMU7_Discrete_GraphicsLevel *level) +{ + int result; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + + result = ci_calculate_sclk_params(hwmgr, clock, level); + + /* populate graphics levels */ + result = ci_get_dependency_volt_by_clk(hwmgr, + hwmgr->dyn_state.vddc_dependency_on_sclk, clock, + (uint32_t *)(&level->MinVddc)); + if (result) { + pr_err("vdd_dep_on_sclk table is NULL\n"); + return result; + } + + level->SclkFrequency = clock; + level->MinVddcPhases = 1; + + if (data->vddc_phase_shed_control) + ci_populate_phase_value_based_on_sclk(hwmgr, + hwmgr->dyn_state.vddc_phase_shed_limits_table, + clock, + &level->MinVddcPhases); + + level->ActivityLevel = sclk_al_threshold; + level->CcPwrDynRm = 0; + level->CcPwrDynRm1 = 0; + level->EnabledForActivity = 0; + /* this level can be used for throttling.*/ + level->EnabledForThrottle = 1; + level->UpH = 0; + level->DownH = 0; + level->VoltageDownH = 0; + level->PowerThrottle = 0; + + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkDeepSleep)) + level->DeepSleepDivId = + ci_get_sleep_divider_id_from_clock(clock, + CISLAND_MINIMUM_ENGINE_CLOCK); + + /* Default to slow, highest DPM level will be set to PPSMC_DISPLAY_WATERMARK_LOW later.*/ + level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + + if (0 == result) { + level->MinVddc = PP_HOST_TO_SMC_UL(level->MinVddc * VOLTAGE_SCALE); + CONVERT_FROM_HOST_TO_SMC_UL(level->MinVddcPhases); + CONVERT_FROM_HOST_TO_SMC_UL(level->SclkFrequency); + CONVERT_FROM_HOST_TO_SMC_US(level->ActivityLevel); + CONVERT_FROM_HOST_TO_SMC_UL(level->CgSpllFuncCntl3); + CONVERT_FROM_HOST_TO_SMC_UL(level->CgSpllFuncCntl4); + CONVERT_FROM_HOST_TO_SMC_UL(level->SpllSpreadSpectrum); + CONVERT_FROM_HOST_TO_SMC_UL(level->SpllSpreadSpectrum2); + CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm1); + } + + return result; +} + +int ci_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + struct smu7_dpm_table *dpm_table = &data->dpm_table; + int result = 0; + uint32_t array = smu_data->dpm_table_start + + offsetof(SMU7_Discrete_DpmTable, GraphicsLevel); + uint32_t array_size = sizeof(struct SMU7_Discrete_GraphicsLevel) * + SMU7_MAX_LEVELS_GRAPHICS; + struct SMU7_Discrete_GraphicsLevel *levels = + smu_data->smc_state_table.GraphicsLevel; + uint32_t i; + + for (i = 0; i < dpm_table->sclk_table.count; i++) { + result = ci_populate_single_graphic_level(hwmgr, + dpm_table->sclk_table.dpm_levels[i].value, + (uint16_t)smu_data->activity_target[i], + &levels[i]); + if (result) + return result; + if (i > 1) + smu_data->smc_state_table.GraphicsLevel[i].DeepSleepDivId = 0; + if (i == (dpm_table->sclk_table.count - 1)) + smu_data->smc_state_table.GraphicsLevel[i].DisplayWatermark = + PPSMC_DISPLAY_WATERMARK_HIGH; + } + + smu_data->smc_state_table.GraphicsLevel[0].EnabledForActivity = 1; + + smu_data->smc_state_table.GraphicsDpmLevelCount = (u8)dpm_table->sclk_table.count; + data->dpm_level_enable_mask.sclk_dpm_enable_mask = + phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table); + + result = ci_copy_bytes_to_smc(hwmgr, array, + (u8 *)levels, array_size, + SMC_RAM_END); + + return result; + +} + +static int ci_populate_svi_load_line(struct pp_hwmgr *hwmgr) +{ + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + const struct ci_pt_defaults *defaults = smu_data->power_tune_defaults; + + smu_data->power_tune_table.SviLoadLineEn = defaults->svi_load_line_en; + smu_data->power_tune_table.SviLoadLineVddC = defaults->svi_load_line_vddc; + smu_data->power_tune_table.SviLoadLineTrimVddC = 3; + smu_data->power_tune_table.SviLoadLineOffsetVddC = 0; + + return 0; +} + +static int ci_populate_tdc_limit(struct pp_hwmgr *hwmgr) +{ + uint16_t tdc_limit; + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + const struct ci_pt_defaults *defaults = smu_data->power_tune_defaults; + + tdc_limit = (uint16_t)(hwmgr->dyn_state.cac_dtp_table->usTDC * 256); + smu_data->power_tune_table.TDC_VDDC_PkgLimit = + CONVERT_FROM_HOST_TO_SMC_US(tdc_limit); + smu_data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc = + defaults->tdc_vddc_throttle_release_limit_perc; + smu_data->power_tune_table.TDC_MAWt = defaults->tdc_mawt; + + return 0; +} + +static int ci_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) +{ + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + const struct ci_pt_defaults *defaults = smu_data->power_tune_defaults; + uint32_t temp; + + if (ci_read_smc_sram_dword(hwmgr, + fuse_table_offset + + offsetof(SMU7_Discrete_PmFuses, TdcWaterfallCtl), + (uint32_t *)&temp, SMC_RAM_END)) + PP_ASSERT_WITH_CODE(false, + "Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!", + return -EINVAL); + else + smu_data->power_tune_table.TdcWaterfallCtl = defaults->tdc_waterfall_ctl; + + return 0; +} + +static int ci_populate_fuzzy_fan(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) +{ + uint16_t tmp; + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + + if ((hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity & (1 << 15)) + || 0 == hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity) + tmp = hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity; + else + tmp = hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity; + + smu_data->power_tune_table.FuzzyFan_PwmSetDelta = CONVERT_FROM_HOST_TO_SMC_US(tmp); + + return 0; +} + +static int ci_populate_bapm_vddc_vid_sidd(struct pp_hwmgr *hwmgr) +{ + int i; + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + uint8_t *hi_vid = smu_data->power_tune_table.BapmVddCVidHiSidd; + uint8_t *lo_vid = smu_data->power_tune_table.BapmVddCVidLoSidd; + uint8_t *hi2_vid = smu_data->power_tune_table.BapmVddCVidHiSidd2; + + PP_ASSERT_WITH_CODE(NULL != hwmgr->dyn_state.cac_leakage_table, + "The CAC Leakage table does not exist!", return -EINVAL); + PP_ASSERT_WITH_CODE(hwmgr->dyn_state.cac_leakage_table->count <= 8, + "There should never be more than 8 entries for BapmVddcVid!!!", return -EINVAL); + PP_ASSERT_WITH_CODE(hwmgr->dyn_state.cac_leakage_table->count == hwmgr->dyn_state.vddc_dependency_on_sclk->count, + "CACLeakageTable->count and VddcDependencyOnSCLk->count not equal", return -EINVAL); + + for (i = 0; (uint32_t) i < hwmgr->dyn_state.cac_leakage_table->count; i++) { + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_EVV)) { + lo_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc1); + hi_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc2); + hi2_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc3); + } else { + lo_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc); + hi_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Leakage); + } + } + + return 0; +} + +static int ci_populate_vddc_vid(struct pp_hwmgr *hwmgr) +{ + int i; + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + uint8_t *vid = smu_data->power_tune_table.VddCVid; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + PP_ASSERT_WITH_CODE(data->vddc_voltage_table.count <= 8, + "There should never be more than 8 entries for VddcVid!!!", + return -EINVAL); + + for (i = 0; i < (int)data->vddc_voltage_table.count; i++) + vid[i] = convert_to_vid(data->vddc_voltage_table.entries[i].value); + + return 0; +} + +static int ci_min_max_v_gnbl_pm_lid_from_bapm_vddc(struct pp_hwmgr *hwmgr) +{ + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + u8 *hi_vid = smu_data->power_tune_table.BapmVddCVidHiSidd; + u8 *lo_vid = smu_data->power_tune_table.BapmVddCVidLoSidd; + int i, min, max; + + min = max = hi_vid[0]; + for (i = 0; i < 8; i++) { + if (0 != hi_vid[i]) { + if (min > hi_vid[i]) + min = hi_vid[i]; + if (max < hi_vid[i]) + max = hi_vid[i]; + } + + if (0 != lo_vid[i]) { + if (min > lo_vid[i]) + min = lo_vid[i]; + if (max < lo_vid[i]) + max = lo_vid[i]; + } + } + + if ((min == 0) || (max == 0)) + return -EINVAL; + smu_data->power_tune_table.GnbLPMLMaxVid = (u8)max; + smu_data->power_tune_table.GnbLPMLMinVid = (u8)min; + + return 0; +} + +static int ci_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) +{ + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + uint16_t HiSidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd; + uint16_t LoSidd = smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd; + struct phm_cac_tdp_table *cac_table = hwmgr->dyn_state.cac_dtp_table; + + HiSidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256); + LoSidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256); + + smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd = + CONVERT_FROM_HOST_TO_SMC_US(HiSidd); + smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd = + CONVERT_FROM_HOST_TO_SMC_US(LoSidd); + + return 0; +} + +static int ci_populate_pm_fuses(struct pp_hwmgr *hwmgr) +{ + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + uint32_t pm_fuse_table_offset; + int ret = 0; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment)) { + if (ci_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU7_Firmware_Header, PmFuseTable), + &pm_fuse_table_offset, SMC_RAM_END)) { + pr_err("Attempt to get pm_fuse_table_offset Failed!\n"); + return -EINVAL; + } + + /* DW0 - DW3 */ + ret = ci_populate_bapm_vddc_vid_sidd(hwmgr); + /* DW4 - DW5 */ + ret |= ci_populate_vddc_vid(hwmgr); + /* DW6 */ + ret |= ci_populate_svi_load_line(hwmgr); + /* DW7 */ + ret |= ci_populate_tdc_limit(hwmgr); + /* DW8 */ + ret |= ci_populate_dw8(hwmgr, pm_fuse_table_offset); + + ret |= ci_populate_fuzzy_fan(hwmgr, pm_fuse_table_offset); + + ret |= ci_min_max_v_gnbl_pm_lid_from_bapm_vddc(hwmgr); + + ret |= ci_populate_bapm_vddc_base_leakage_sidd(hwmgr); + if (ret) + return ret; + + ret = ci_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset, + (uint8_t *)&smu_data->power_tune_table, + sizeof(struct SMU7_Discrete_PmFuses), SMC_RAM_END); + } + return ret; +} + +static int ci_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) +{ + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + const struct ci_pt_defaults *defaults = smu_data->power_tune_defaults; + SMU7_Discrete_DpmTable *dpm_table = &(smu_data->smc_state_table); + struct phm_cac_tdp_table *cac_dtp_table = hwmgr->dyn_state.cac_dtp_table; + struct phm_ppm_table *ppm = hwmgr->dyn_state.ppm_parameter_table; + const uint16_t *def1, *def2; + int i, j, k; + + dpm_table->DefaultTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usTDP * 256)); + dpm_table->TargetTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usConfigurableTDP * 256)); + + dpm_table->DTETjOffset = 0; + dpm_table->GpuTjMax = (uint8_t)(data->thermal_temp_setting.temperature_high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES); + dpm_table->GpuTjHyst = 8; + + dpm_table->DTEAmbientTempBase = defaults->dte_ambient_temp_base; + + if (ppm) { + dpm_table->PPM_PkgPwrLimit = (uint16_t)ppm->dgpu_tdp * 256 / 1000; + dpm_table->PPM_TemperatureLimit = (uint16_t)ppm->tj_max * 256; + } else { + dpm_table->PPM_PkgPwrLimit = 0; + dpm_table->PPM_TemperatureLimit = 0; + } + + CONVERT_FROM_HOST_TO_SMC_US(dpm_table->PPM_PkgPwrLimit); + CONVERT_FROM_HOST_TO_SMC_US(dpm_table->PPM_TemperatureLimit); + + dpm_table->BAPM_TEMP_GRADIENT = PP_HOST_TO_SMC_UL(defaults->bapm_temp_gradient); + def1 = defaults->bapmti_r; + def2 = defaults->bapmti_rc; + + for (i = 0; i < SMU7_DTE_ITERATIONS; i++) { + for (j = 0; j < SMU7_DTE_SOURCES; j++) { + for (k = 0; k < SMU7_DTE_SINKS; k++) { + dpm_table->BAPMTI_R[i][j][k] = PP_HOST_TO_SMC_US(*def1); + dpm_table->BAPMTI_RC[i][j][k] = PP_HOST_TO_SMC_US(*def2); + def1++; + def2++; + } + } + } + + return 0; +} + +static int ci_get_std_voltage_value_sidd(struct pp_hwmgr *hwmgr, + pp_atomctrl_voltage_table_entry *tab, uint16_t *hi, + uint16_t *lo) +{ + uint16_t v_index; + bool vol_found = false; + *hi = tab->value * VOLTAGE_SCALE; + *lo = tab->value * VOLTAGE_SCALE; + + PP_ASSERT_WITH_CODE(NULL != hwmgr->dyn_state.vddc_dependency_on_sclk, + "The SCLK/VDDC Dependency Table does not exist.\n", + return -EINVAL); + + if (NULL == hwmgr->dyn_state.cac_leakage_table) { + pr_warn("CAC Leakage Table does not exist, using vddc.\n"); + return 0; + } + + for (v_index = 0; (uint32_t)v_index < hwmgr->dyn_state.vddc_dependency_on_sclk->count; v_index++) { + if (tab->value == hwmgr->dyn_state.vddc_dependency_on_sclk->entries[v_index].v) { + vol_found = true; + if ((uint32_t)v_index < hwmgr->dyn_state.cac_leakage_table->count) { + *lo = hwmgr->dyn_state.cac_leakage_table->entries[v_index].Vddc * VOLTAGE_SCALE; + *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[v_index].Leakage * VOLTAGE_SCALE); + } else { + pr_warn("Index from SCLK/VDDC Dependency Table exceeds the CAC Leakage Table index, using maximum index from CAC table.\n"); + *lo = hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Vddc * VOLTAGE_SCALE; + *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Leakage * VOLTAGE_SCALE); + } + break; + } + } + + if (!vol_found) { + for (v_index = 0; (uint32_t)v_index < hwmgr->dyn_state.vddc_dependency_on_sclk->count; v_index++) { + if (tab->value <= hwmgr->dyn_state.vddc_dependency_on_sclk->entries[v_index].v) { + vol_found = true; + if ((uint32_t)v_index < hwmgr->dyn_state.cac_leakage_table->count) { + *lo = hwmgr->dyn_state.cac_leakage_table->entries[v_index].Vddc * VOLTAGE_SCALE; + *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[v_index].Leakage) * VOLTAGE_SCALE; + } else { + pr_warn("Index from SCLK/VDDC Dependency Table exceeds the CAC Leakage Table index in second look up, using maximum index from CAC table."); + *lo = hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Vddc * VOLTAGE_SCALE; + *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Leakage * VOLTAGE_SCALE); + } + break; + } + } + + if (!vol_found) + pr_warn("Unable to get std_vddc from SCLK/VDDC Dependency Table, using vddc.\n"); + } + + return 0; +} + +static int ci_populate_smc_voltage_table(struct pp_hwmgr *hwmgr, + pp_atomctrl_voltage_table_entry *tab, + SMU7_Discrete_VoltageLevel *smc_voltage_tab) +{ + int result; + + result = ci_get_std_voltage_value_sidd(hwmgr, tab, + &smc_voltage_tab->StdVoltageHiSidd, + &smc_voltage_tab->StdVoltageLoSidd); + if (result) { + smc_voltage_tab->StdVoltageHiSidd = tab->value * VOLTAGE_SCALE; + smc_voltage_tab->StdVoltageLoSidd = tab->value * VOLTAGE_SCALE; + } + + smc_voltage_tab->Voltage = PP_HOST_TO_SMC_US(tab->value * VOLTAGE_SCALE); + CONVERT_FROM_HOST_TO_SMC_US(smc_voltage_tab->StdVoltageHiSidd); + CONVERT_FROM_HOST_TO_SMC_US(smc_voltage_tab->StdVoltageLoSidd); + + return 0; +} + +static int ci_populate_smc_vddc_table(struct pp_hwmgr *hwmgr, + SMU7_Discrete_DpmTable *table) +{ + unsigned int count; + int result; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + table->VddcLevelCount = data->vddc_voltage_table.count; + for (count = 0; count < table->VddcLevelCount; count++) { + result = ci_populate_smc_voltage_table(hwmgr, + &(data->vddc_voltage_table.entries[count]), + &(table->VddcLevel[count])); + PP_ASSERT_WITH_CODE(0 == result, "do not populate SMC VDDC voltage table", return -EINVAL); + + /* GPIO voltage control */ + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->voltage_control) + table->VddcLevel[count].Smio |= data->vddc_voltage_table.entries[count].smio_low; + else + table->VddcLevel[count].Smio = 0; + } + + CONVERT_FROM_HOST_TO_SMC_UL(table->VddcLevelCount); + + return 0; +} + +static int ci_populate_smc_vdd_ci_table(struct pp_hwmgr *hwmgr, + SMU7_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t count; + int result; + + table->VddciLevelCount = data->vddci_voltage_table.count; + + for (count = 0; count < table->VddciLevelCount; count++) { + result = ci_populate_smc_voltage_table(hwmgr, + &(data->vddci_voltage_table.entries[count]), + &(table->VddciLevel[count])); + PP_ASSERT_WITH_CODE(result == 0, "do not populate SMC VDDCI voltage table", return -EINVAL); + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) + table->VddciLevel[count].Smio |= data->vddci_voltage_table.entries[count].smio_low; + else + table->VddciLevel[count].Smio |= 0; + } + + CONVERT_FROM_HOST_TO_SMC_UL(table->VddciLevelCount); + + return 0; +} + +static int ci_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr, + SMU7_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t count; + int result; + + table->MvddLevelCount = data->mvdd_voltage_table.count; + + for (count = 0; count < table->MvddLevelCount; count++) { + result = ci_populate_smc_voltage_table(hwmgr, + &(data->mvdd_voltage_table.entries[count]), + &table->MvddLevel[count]); + PP_ASSERT_WITH_CODE(result == 0, "do not populate SMC mvdd voltage table", return -EINVAL); + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) + table->MvddLevel[count].Smio |= data->mvdd_voltage_table.entries[count].smio_low; + else + table->MvddLevel[count].Smio |= 0; + } + + CONVERT_FROM_HOST_TO_SMC_UL(table->MvddLevelCount); + + return 0; +} + + +static int ci_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr, + SMU7_Discrete_DpmTable *table) +{ + int result; + + result = ci_populate_smc_vddc_table(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "can not populate VDDC voltage table to SMC", return -EINVAL); + + result = ci_populate_smc_vdd_ci_table(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "can not populate VDDCI voltage table to SMC", return -EINVAL); + + result = ci_populate_smc_mvdd_table(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "can not populate MVDD voltage table to SMC", return -EINVAL); + + return 0; +} + +static int ci_populate_ulv_level(struct pp_hwmgr *hwmgr, + struct SMU7_Discrete_Ulv *state) +{ + uint32_t voltage_response_time, ulv_voltage; + int result; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + state->CcPwrDynRm = 0; + state->CcPwrDynRm1 = 0; + + result = pp_tables_get_response_times(hwmgr, &voltage_response_time, &ulv_voltage); + PP_ASSERT_WITH_CODE((0 == result), "can not get ULV voltage value", return result;); + + if (ulv_voltage == 0) { + data->ulv_supported = false; + return 0; + } + + if (data->voltage_control != SMU7_VOLTAGE_CONTROL_BY_SVID2) { + /* use minimum voltage if ulv voltage in pptable is bigger than minimum voltage */ + if (ulv_voltage > hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v) + state->VddcOffset = 0; + else + /* used in SMIO Mode. not implemented for now. this is backup only for CI. */ + state->VddcOffset = (uint16_t)(hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v - ulv_voltage); + } else { + /* use minimum voltage if ulv voltage in pptable is bigger than minimum voltage */ + if (ulv_voltage > hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v) + state->VddcOffsetVid = 0; + else /* used in SVI2 Mode */ + state->VddcOffsetVid = (uint8_t)( + (hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v - ulv_voltage) + * VOLTAGE_VID_OFFSET_SCALE2 + / VOLTAGE_VID_OFFSET_SCALE1); + } + state->VddcPhase = 1; + + CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1); + CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset); + + return 0; +} + +static int ci_populate_ulv_state(struct pp_hwmgr *hwmgr, + SMU7_Discrete_Ulv *ulv_level) +{ + return ci_populate_ulv_level(hwmgr, ulv_level); +} + +static int ci_populate_smc_link_level(struct pp_hwmgr *hwmgr, SMU7_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct smu7_dpm_table *dpm_table = &data->dpm_table; + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + uint32_t i; + +/* Index dpm_table->pcie_speed_table.count is reserved for PCIE boot level.*/ + for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) { + table->LinkLevel[i].PcieGenSpeed = + (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value; + table->LinkLevel[i].PcieLaneCount = + (uint8_t)encode_pcie_lane_width(dpm_table->pcie_speed_table.dpm_levels[i].param1); + table->LinkLevel[i].EnabledForActivity = 1; + table->LinkLevel[i].DownT = PP_HOST_TO_SMC_UL(5); + table->LinkLevel[i].UpT = PP_HOST_TO_SMC_UL(30); + } + + smu_data->smc_state_table.LinkLevelCount = + (uint8_t)dpm_table->pcie_speed_table.count; + data->dpm_level_enable_mask.pcie_dpm_enable_mask = + phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table); + + return 0; +} + +static int ci_calculate_mclk_params( + struct pp_hwmgr *hwmgr, + uint32_t memory_clock, + SMU7_Discrete_MemoryLevel *mclk, + bool strobe_mode, + bool dllStateOn + ) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t dll_cntl = data->clock_registers.vDLL_CNTL; + uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL; + uint32_t mpll_ad_func_cntl = data->clock_registers.vMPLL_AD_FUNC_CNTL; + uint32_t mpll_dq_func_cntl = data->clock_registers.vMPLL_DQ_FUNC_CNTL; + uint32_t mpll_func_cntl = data->clock_registers.vMPLL_FUNC_CNTL; + uint32_t mpll_func_cntl_1 = data->clock_registers.vMPLL_FUNC_CNTL_1; + uint32_t mpll_func_cntl_2 = data->clock_registers.vMPLL_FUNC_CNTL_2; + uint32_t mpll_ss1 = data->clock_registers.vMPLL_SS1; + uint32_t mpll_ss2 = data->clock_registers.vMPLL_SS2; + + pp_atomctrl_memory_clock_param mpll_param; + int result; + + result = atomctrl_get_memory_pll_dividers_si(hwmgr, + memory_clock, &mpll_param, strobe_mode); + PP_ASSERT_WITH_CODE(0 == result, + "Error retrieving Memory Clock Parameters from VBIOS.", return result); + + mpll_func_cntl = PHM_SET_FIELD(mpll_func_cntl, MPLL_FUNC_CNTL, BWCTRL, mpll_param.bw_ctrl); + + mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, + MPLL_FUNC_CNTL_1, CLKF, mpll_param.mpll_fb_divider.cl_kf); + mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, + MPLL_FUNC_CNTL_1, CLKFRAC, mpll_param.mpll_fb_divider.clk_frac); + mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, + MPLL_FUNC_CNTL_1, VCO_MODE, mpll_param.vco_mode); + + mpll_ad_func_cntl = PHM_SET_FIELD(mpll_ad_func_cntl, + MPLL_AD_FUNC_CNTL, YCLK_POST_DIV, mpll_param.mpll_post_divider); + + if (data->is_memory_gddr5) { + mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl, + MPLL_DQ_FUNC_CNTL, YCLK_SEL, mpll_param.yclk_sel); + mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl, + MPLL_DQ_FUNC_CNTL, YCLK_POST_DIV, mpll_param.mpll_post_divider); + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MemorySpreadSpectrumSupport)) { + pp_atomctrl_internal_ss_info ss_info; + uint32_t freq_nom; + uint32_t tmp; + uint32_t reference_clock = atomctrl_get_mpll_reference_clock(hwmgr); + + /* for GDDR5 for all modes and DDR3 */ + if (1 == mpll_param.qdr) + freq_nom = memory_clock * 4 * (1 << mpll_param.mpll_post_divider); + else + freq_nom = memory_clock * 2 * (1 << mpll_param.mpll_post_divider); + + /* tmp = (freq_nom / reference_clock * reference_divider) ^ 2 Note: S.I. reference_divider = 1*/ + tmp = (freq_nom / reference_clock); + tmp = tmp * tmp; + + if (0 == atomctrl_get_memory_clock_spread_spectrum(hwmgr, freq_nom, &ss_info)) { + uint32_t clks = reference_clock * 5 / ss_info.speed_spectrum_rate; + uint32_t clkv = + (uint32_t)((((131 * ss_info.speed_spectrum_percentage * + ss_info.speed_spectrum_rate) / 100) * tmp) / freq_nom); + + mpll_ss1 = PHM_SET_FIELD(mpll_ss1, MPLL_SS1, CLKV, clkv); + mpll_ss2 = PHM_SET_FIELD(mpll_ss2, MPLL_SS2, CLKS, clks); + } + } + + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, DLL_SPEED, mpll_param.dll_speed); + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK0_PDNB, dllStateOn); + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK1_PDNB, dllStateOn); + + + mclk->MclkFrequency = memory_clock; + mclk->MpllFuncCntl = mpll_func_cntl; + mclk->MpllFuncCntl_1 = mpll_func_cntl_1; + mclk->MpllFuncCntl_2 = mpll_func_cntl_2; + mclk->MpllAdFuncCntl = mpll_ad_func_cntl; + mclk->MpllDqFuncCntl = mpll_dq_func_cntl; + mclk->MclkPwrmgtCntl = mclk_pwrmgt_cntl; + mclk->DllCntl = dll_cntl; + mclk->MpllSs1 = mpll_ss1; + mclk->MpllSs2 = mpll_ss2; + + return 0; +} + +static uint8_t ci_get_mclk_frequency_ratio(uint32_t memory_clock, + bool strobe_mode) +{ + uint8_t mc_para_index; + + if (strobe_mode) { + if (memory_clock < 12500) + mc_para_index = 0x00; + else if (memory_clock > 47500) + mc_para_index = 0x0f; + else + mc_para_index = (uint8_t)((memory_clock - 10000) / 2500); + } else { + if (memory_clock < 65000) + mc_para_index = 0x00; + else if (memory_clock > 135000) + mc_para_index = 0x0f; + else + mc_para_index = (uint8_t)((memory_clock - 60000) / 5000); + } + + return mc_para_index; +} + +static uint8_t ci_get_ddr3_mclk_frequency_ratio(uint32_t memory_clock) +{ + uint8_t mc_para_index; + + if (memory_clock < 10000) + mc_para_index = 0; + else if (memory_clock >= 80000) + mc_para_index = 0x0f; + else + mc_para_index = (uint8_t)((memory_clock - 10000) / 5000 + 1); + + return mc_para_index; +} + +static int ci_populate_phase_value_based_on_mclk(struct pp_hwmgr *hwmgr, const struct phm_phase_shedding_limits_table *pl, + uint32_t memory_clock, uint32_t *p_shed) +{ + unsigned int i; + + *p_shed = 1; + + for (i = 0; i < pl->count; i++) { + if (memory_clock < pl->entries[i].Mclk) { + *p_shed = i; + break; + } + } + + return 0; +} + +static int ci_populate_single_memory_level( + struct pp_hwmgr *hwmgr, + uint32_t memory_clock, + SMU7_Discrete_MemoryLevel *memory_level + ) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + int result = 0; + bool dll_state_on; + struct cgs_display_info info = {0}; + uint32_t mclk_edc_wr_enable_threshold = 40000; + uint32_t mclk_edc_enable_threshold = 40000; + uint32_t mclk_strobe_mode_threshold = 40000; + + if (hwmgr->dyn_state.vddc_dependency_on_mclk != NULL) { + result = ci_get_dependency_volt_by_clk(hwmgr, + hwmgr->dyn_state.vddc_dependency_on_mclk, memory_clock, &memory_level->MinVddc); + PP_ASSERT_WITH_CODE((0 == result), + "can not find MinVddc voltage value from memory VDDC voltage dependency table", return result); + } + + if (NULL != hwmgr->dyn_state.vddci_dependency_on_mclk) { + result = ci_get_dependency_volt_by_clk(hwmgr, + hwmgr->dyn_state.vddci_dependency_on_mclk, + memory_clock, + &memory_level->MinVddci); + PP_ASSERT_WITH_CODE((0 == result), + "can not find MinVddci voltage value from memory VDDCI voltage dependency table", return result); + } + + if (NULL != hwmgr->dyn_state.mvdd_dependency_on_mclk) { + result = ci_get_dependency_volt_by_clk(hwmgr, + hwmgr->dyn_state.mvdd_dependency_on_mclk, + memory_clock, + &memory_level->MinMvdd); + PP_ASSERT_WITH_CODE((0 == result), + "can not find MinVddci voltage value from memory MVDD voltage dependency table", return result); + } + + memory_level->MinVddcPhases = 1; + + if (data->vddc_phase_shed_control) { + ci_populate_phase_value_based_on_mclk(hwmgr, hwmgr->dyn_state.vddc_phase_shed_limits_table, + memory_clock, &memory_level->MinVddcPhases); + } + + memory_level->EnabledForThrottle = 1; + memory_level->EnabledForActivity = 1; + memory_level->UpH = 0; + memory_level->DownH = 100; + memory_level->VoltageDownH = 0; + + /* Indicates maximum activity level for this performance level.*/ + memory_level->ActivityLevel = (uint16_t)data->mclk_activity_target; + memory_level->StutterEnable = 0; + memory_level->StrobeEnable = 0; + memory_level->EdcReadEnable = 0; + memory_level->EdcWriteEnable = 0; + memory_level->RttEnable = 0; + + /* default set to low watermark. Highest level will be set to high later.*/ + memory_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + + cgs_get_active_displays_info(hwmgr->device, &info); + data->display_timing.num_existing_displays = info.display_count; + + /* stutter mode not support on ci */ + + /* decide strobe mode*/ + memory_level->StrobeEnable = (mclk_strobe_mode_threshold != 0) && + (memory_clock <= mclk_strobe_mode_threshold); + + /* decide EDC mode and memory clock ratio*/ + if (data->is_memory_gddr5) { + memory_level->StrobeRatio = ci_get_mclk_frequency_ratio(memory_clock, + memory_level->StrobeEnable); + + if ((mclk_edc_enable_threshold != 0) && + (memory_clock > mclk_edc_enable_threshold)) { + memory_level->EdcReadEnable = 1; + } + + if ((mclk_edc_wr_enable_threshold != 0) && + (memory_clock > mclk_edc_wr_enable_threshold)) { + memory_level->EdcWriteEnable = 1; + } + + if (memory_level->StrobeEnable) { + if (ci_get_mclk_frequency_ratio(memory_clock, 1) >= + ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC7) >> 16) & 0xf)) + dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0; + else + dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC6) >> 1) & 0x1) ? 1 : 0; + } else + dll_state_on = data->dll_default_on; + } else { + memory_level->StrobeRatio = + ci_get_ddr3_mclk_frequency_ratio(memory_clock); + dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0; + } + + result = ci_calculate_mclk_params(hwmgr, + memory_clock, memory_level, memory_level->StrobeEnable, dll_state_on); + + if (0 == result) { + memory_level->MinVddc = PP_HOST_TO_SMC_UL(memory_level->MinVddc * VOLTAGE_SCALE); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MinVddcPhases); + memory_level->MinVddci = PP_HOST_TO_SMC_UL(memory_level->MinVddci * VOLTAGE_SCALE); + memory_level->MinMvdd = PP_HOST_TO_SMC_UL(memory_level->MinMvdd * VOLTAGE_SCALE); + /* MCLK frequency in units of 10KHz*/ + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkFrequency); + /* Indicates maximum activity level for this performance level.*/ + CONVERT_FROM_HOST_TO_SMC_US(memory_level->ActivityLevel); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_1); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_2); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllAdFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllDqFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkPwrmgtCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->DllCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs1); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs2); + } + + return result; +} + +int ci_populate_all_memory_levels(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + struct smu7_dpm_table *dpm_table = &data->dpm_table; + int result; + struct cgs_system_info sys_info = {0}; + uint32_t dev_id; + + uint32_t level_array_address = smu_data->dpm_table_start + offsetof(SMU7_Discrete_DpmTable, MemoryLevel); + uint32_t level_array_size = sizeof(SMU7_Discrete_MemoryLevel) * SMU7_MAX_LEVELS_MEMORY; + SMU7_Discrete_MemoryLevel *levels = smu_data->smc_state_table.MemoryLevel; + uint32_t i; + + memset(levels, 0x00, level_array_size); + + for (i = 0; i < dpm_table->mclk_table.count; i++) { + PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value), + "can not populate memory level as memory clock is zero", return -EINVAL); + result = ci_populate_single_memory_level(hwmgr, dpm_table->mclk_table.dpm_levels[i].value, + &(smu_data->smc_state_table.MemoryLevel[i])); + if (0 != result) + return result; + } + + smu_data->smc_state_table.MemoryLevel[0].EnabledForActivity = 1; + + sys_info.size = sizeof(struct cgs_system_info); + sys_info.info_id = CGS_SYSTEM_INFO_PCIE_DEV; + cgs_query_system_info(hwmgr->device, &sys_info); + dev_id = (uint32_t)sys_info.value; + + if ((dpm_table->mclk_table.count >= 2) + && ((dev_id == 0x67B0) || (dev_id == 0x67B1))) { + smu_data->smc_state_table.MemoryLevel[1].MinVddci = + smu_data->smc_state_table.MemoryLevel[0].MinVddci; + smu_data->smc_state_table.MemoryLevel[1].MinMvdd = + smu_data->smc_state_table.MemoryLevel[0].MinMvdd; + } + smu_data->smc_state_table.MemoryLevel[0].ActivityLevel = 0x1F; + CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.MemoryLevel[0].ActivityLevel); + + smu_data->smc_state_table.MemoryDpmLevelCount = (uint8_t)dpm_table->mclk_table.count; + data->dpm_level_enable_mask.mclk_dpm_enable_mask = phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table); + smu_data->smc_state_table.MemoryLevel[dpm_table->mclk_table.count-1].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH; + + result = ci_copy_bytes_to_smc(hwmgr, + level_array_address, (uint8_t *)levels, (uint32_t)level_array_size, + SMC_RAM_END); + + return result; +} + +static int ci_populate_mvdd_value(struct pp_hwmgr *hwmgr, uint32_t mclk, + SMU7_Discrete_VoltageLevel *voltage) +{ + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + uint32_t i = 0; + + if (SMU7_VOLTAGE_CONTROL_NONE != data->mvdd_control) { + /* find mvdd value which clock is more than request */ + for (i = 0; i < hwmgr->dyn_state.mvdd_dependency_on_mclk->count; i++) { + if (mclk <= hwmgr->dyn_state.mvdd_dependency_on_mclk->entries[i].clk) { + /* Always round to higher voltage. */ + voltage->Voltage = data->mvdd_voltage_table.entries[i].value; + break; + } + } + + PP_ASSERT_WITH_CODE(i < hwmgr->dyn_state.mvdd_dependency_on_mclk->count, + "MVDD Voltage is outside the supported range.", return -EINVAL); + + } else { + return -EINVAL; + } + + return 0; +} + +static int ci_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, + SMU7_Discrete_DpmTable *table) +{ + int result = 0; + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct pp_atomctrl_clock_dividers_vi dividers; + + SMU7_Discrete_VoltageLevel voltage_level; + uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; + uint32_t spll_func_cntl_2 = data->clock_registers.vCG_SPLL_FUNC_CNTL_2; + uint32_t dll_cntl = data->clock_registers.vDLL_CNTL; + uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL; + + + /* The ACPI state should not do DPM on DC (or ever).*/ + table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC; + + if (data->acpi_vddc) + table->ACPILevel.MinVddc = PP_HOST_TO_SMC_UL(data->acpi_vddc * VOLTAGE_SCALE); + else + table->ACPILevel.MinVddc = PP_HOST_TO_SMC_UL(data->min_vddc_in_pptable * VOLTAGE_SCALE); + + table->ACPILevel.MinVddcPhases = data->vddc_phase_shed_control ? 0 : 1; + /* assign zero for now*/ + table->ACPILevel.SclkFrequency = atomctrl_get_reference_clock(hwmgr); + + /* get the engine clock dividers for this clock value*/ + result = atomctrl_get_engine_pll_dividers_vi(hwmgr, + table->ACPILevel.SclkFrequency, ÷rs); + + PP_ASSERT_WITH_CODE(result == 0, + "Error retrieving Engine Clock dividers from VBIOS.", return result); + + /* divider ID for required SCLK*/ + table->ACPILevel.SclkDid = (uint8_t)dividers.pll_post_divider; + table->ACPILevel.DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + table->ACPILevel.DeepSleepDivId = 0; + + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, + CG_SPLL_FUNC_CNTL, SPLL_PWRON, 0); + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, + CG_SPLL_FUNC_CNTL, SPLL_RESET, 1); + spll_func_cntl_2 = PHM_SET_FIELD(spll_func_cntl_2, + CG_SPLL_FUNC_CNTL_2, SCLK_MUX_SEL, 4); + + table->ACPILevel.CgSpllFuncCntl = spll_func_cntl; + table->ACPILevel.CgSpllFuncCntl2 = spll_func_cntl_2; + table->ACPILevel.CgSpllFuncCntl3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; + table->ACPILevel.CgSpllFuncCntl4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; + table->ACPILevel.SpllSpreadSpectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; + table->ACPILevel.SpllSpreadSpectrum2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; + table->ACPILevel.CcPwrDynRm = 0; + table->ACPILevel.CcPwrDynRm1 = 0; + + /* For various features to be enabled/disabled while this level is active.*/ + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags); + /* SCLK frequency in units of 10KHz*/ + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl2); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl3); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl4); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum2); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1); + + + /* table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases;*/ + table->MemoryACPILevel.MinVddc = table->ACPILevel.MinVddc; + table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases; + + if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) + table->MemoryACPILevel.MinVddci = table->MemoryACPILevel.MinVddc; + else { + if (data->acpi_vddci != 0) + table->MemoryACPILevel.MinVddci = PP_HOST_TO_SMC_UL(data->acpi_vddci * VOLTAGE_SCALE); + else + table->MemoryACPILevel.MinVddci = PP_HOST_TO_SMC_UL(data->min_vddci_in_pptable * VOLTAGE_SCALE); + } + + if (0 == ci_populate_mvdd_value(hwmgr, 0, &voltage_level)) + table->MemoryACPILevel.MinMvdd = + PP_HOST_TO_SMC_UL(voltage_level.Voltage * VOLTAGE_SCALE); + else + table->MemoryACPILevel.MinMvdd = 0; + + /* Force reset on DLL*/ + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK0_RESET, 0x1); + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK1_RESET, 0x1); + + /* Disable DLL in ACPIState*/ + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK0_PDNB, 0); + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK1_PDNB, 0); + + /* Enable DLL bypass signal*/ + dll_cntl = PHM_SET_FIELD(dll_cntl, + DLL_CNTL, MRDCK0_BYPASS, 0); + dll_cntl = PHM_SET_FIELD(dll_cntl, + DLL_CNTL, MRDCK1_BYPASS, 0); + + table->MemoryACPILevel.DllCntl = + PP_HOST_TO_SMC_UL(dll_cntl); + table->MemoryACPILevel.MclkPwrmgtCntl = + PP_HOST_TO_SMC_UL(mclk_pwrmgt_cntl); + table->MemoryACPILevel.MpllAdFuncCntl = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_AD_FUNC_CNTL); + table->MemoryACPILevel.MpllDqFuncCntl = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_DQ_FUNC_CNTL); + table->MemoryACPILevel.MpllFuncCntl = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL); + table->MemoryACPILevel.MpllFuncCntl_1 = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_1); + table->MemoryACPILevel.MpllFuncCntl_2 = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_2); + table->MemoryACPILevel.MpllSs1 = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS1); + table->MemoryACPILevel.MpllSs2 = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS2); + + table->MemoryACPILevel.EnabledForThrottle = 0; + table->MemoryACPILevel.EnabledForActivity = 0; + table->MemoryACPILevel.UpH = 0; + table->MemoryACPILevel.DownH = 100; + table->MemoryACPILevel.VoltageDownH = 0; + /* Indicates maximum activity level for this performance level.*/ + table->MemoryACPILevel.ActivityLevel = PP_HOST_TO_SMC_US((uint16_t)data->mclk_activity_target); + + table->MemoryACPILevel.StutterEnable = 0; + table->MemoryACPILevel.StrobeEnable = 0; + table->MemoryACPILevel.EdcReadEnable = 0; + table->MemoryACPILevel.EdcWriteEnable = 0; + table->MemoryACPILevel.RttEnable = 0; + + return result; +} + +static int ci_populate_smc_uvd_level(struct pp_hwmgr *hwmgr, + SMU7_Discrete_DpmTable *table) +{ + int result = 0; + uint8_t count; + struct pp_atomctrl_clock_dividers_vi dividers; + struct phm_uvd_clock_voltage_dependency_table *uvd_table = + hwmgr->dyn_state.uvd_clock_voltage_dependency_table; + + table->UvdLevelCount = (uint8_t)(uvd_table->count); + + for (count = 0; count < table->UvdLevelCount; count++) { + table->UvdLevel[count].VclkFrequency = + uvd_table->entries[count].vclk; + table->UvdLevel[count].DclkFrequency = + uvd_table->entries[count].dclk; + table->UvdLevel[count].MinVddc = + uvd_table->entries[count].v * VOLTAGE_SCALE; + table->UvdLevel[count].MinVddcPhases = 1; + + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->UvdLevel[count].VclkFrequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for Vclk clock", return result); + + table->UvdLevel[count].VclkDivider = (uint8_t)dividers.pll_post_divider; + + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->UvdLevel[count].DclkFrequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for Dclk clock", return result); + + table->UvdLevel[count].DclkDivider = (uint8_t)dividers.pll_post_divider; + CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency); + CONVERT_FROM_HOST_TO_SMC_US(table->UvdLevel[count].MinVddc); + } + + return result; +} + +static int ci_populate_smc_vce_level(struct pp_hwmgr *hwmgr, + SMU7_Discrete_DpmTable *table) +{ + int result = -EINVAL; + uint8_t count; + struct pp_atomctrl_clock_dividers_vi dividers; + struct phm_vce_clock_voltage_dependency_table *vce_table = + hwmgr->dyn_state.vce_clock_voltage_dependency_table; + + table->VceLevelCount = (uint8_t)(vce_table->count); + table->VceBootLevel = 0; + + for (count = 0; count < table->VceLevelCount; count++) { + table->VceLevel[count].Frequency = vce_table->entries[count].evclk; + table->VceLevel[count].MinVoltage = + vce_table->entries[count].v * VOLTAGE_SCALE; + table->VceLevel[count].MinPhases = 1; + + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->VceLevel[count].Frequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for VCE engine clock", + return result); + + table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency); + CONVERT_FROM_HOST_TO_SMC_US(table->VceLevel[count].MinVoltage); + } + return result; +} + +static int ci_populate_smc_acp_level(struct pp_hwmgr *hwmgr, + SMU7_Discrete_DpmTable *table) +{ + int result = -EINVAL; + uint8_t count; + struct pp_atomctrl_clock_dividers_vi dividers; + struct phm_acp_clock_voltage_dependency_table *acp_table = + hwmgr->dyn_state.acp_clock_voltage_dependency_table; + + table->AcpLevelCount = (uint8_t)(acp_table->count); + table->AcpBootLevel = 0; + + for (count = 0; count < table->AcpLevelCount; count++) { + table->AcpLevel[count].Frequency = acp_table->entries[count].acpclk; + table->AcpLevel[count].MinVoltage = acp_table->entries[count].v; + table->AcpLevel[count].MinPhases = 1; + + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->AcpLevel[count].Frequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for engine clock", return result); + + table->AcpLevel[count].Divider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->AcpLevel[count].Frequency); + CONVERT_FROM_HOST_TO_SMC_US(table->AcpLevel[count].MinVoltage); + } + return result; +} + +static int ci_populate_smc_samu_level(struct pp_hwmgr *hwmgr, + SMU7_Discrete_DpmTable *table) +{ + int result = -EINVAL; + uint8_t count; + struct pp_atomctrl_clock_dividers_vi dividers; + struct phm_samu_clock_voltage_dependency_table *samu_table = + hwmgr->dyn_state.samu_clock_voltage_dependency_table; + + table->SamuBootLevel = 0; + table->SamuLevelCount = (uint8_t)(samu_table->count); + + for (count = 0; count < table->SamuLevelCount; count++) { + table->SamuLevel[count].Frequency = samu_table->entries[count].samclk; + table->SamuLevel[count].MinVoltage = samu_table->entries[count].v * VOLTAGE_SCALE; + table->SamuLevel[count].MinPhases = 1; + + /* retrieve divider value for VBIOS */ + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->SamuLevel[count].Frequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for samu clock", return result); + + table->SamuLevel[count].Divider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].Frequency); + CONVERT_FROM_HOST_TO_SMC_US(table->SamuLevel[count].MinVoltage); + } + return result; +} + +static int ci_populate_memory_timing_parameters( + struct pp_hwmgr *hwmgr, + uint32_t engine_clock, + uint32_t memory_clock, + struct SMU7_Discrete_MCArbDramTimingTableEntry *arb_regs + ) +{ + uint32_t dramTiming; + uint32_t dramTiming2; + uint32_t burstTime; + int result; + + result = atomctrl_set_engine_dram_timings_rv770(hwmgr, + engine_clock, memory_clock); + + PP_ASSERT_WITH_CODE(result == 0, + "Error calling VBIOS to set DRAM_TIMING.", return result); + + dramTiming = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING); + dramTiming2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2); + burstTime = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0); + + arb_regs->McArbDramTiming = PP_HOST_TO_SMC_UL(dramTiming); + arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dramTiming2); + arb_regs->McArbBurstTime = (uint8_t)burstTime; + + return 0; +} + +static int ci_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + int result = 0; + SMU7_Discrete_MCArbDramTimingTable arb_regs; + uint32_t i, j; + + memset(&arb_regs, 0x00, sizeof(SMU7_Discrete_MCArbDramTimingTable)); + + for (i = 0; i < data->dpm_table.sclk_table.count; i++) { + for (j = 0; j < data->dpm_table.mclk_table.count; j++) { + result = ci_populate_memory_timing_parameters + (hwmgr, data->dpm_table.sclk_table.dpm_levels[i].value, + data->dpm_table.mclk_table.dpm_levels[j].value, + &arb_regs.entries[i][j]); + + if (0 != result) + break; + } + } + + if (0 == result) { + result = ci_copy_bytes_to_smc( + hwmgr, + smu_data->arb_table_start, + (uint8_t *)&arb_regs, + sizeof(SMU7_Discrete_MCArbDramTimingTable), + SMC_RAM_END + ); + } + + return result; +} + +static int ci_populate_smc_boot_level(struct pp_hwmgr *hwmgr, + SMU7_Discrete_DpmTable *table) +{ + int result = 0; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + + table->GraphicsBootLevel = 0; + table->MemoryBootLevel = 0; + + /* find boot level from dpm table*/ + result = phm_find_boot_level(&(data->dpm_table.sclk_table), + data->vbios_boot_state.sclk_bootup_value, + (uint32_t *)&(smu_data->smc_state_table.GraphicsBootLevel)); + + if (0 != result) { + smu_data->smc_state_table.GraphicsBootLevel = 0; + pr_err("VBIOS did not find boot engine clock value \ + in dependency table. Using Graphics DPM level 0!"); + result = 0; + } + + result = phm_find_boot_level(&(data->dpm_table.mclk_table), + data->vbios_boot_state.mclk_bootup_value, + (uint32_t *)&(smu_data->smc_state_table.MemoryBootLevel)); + + if (0 != result) { + smu_data->smc_state_table.MemoryBootLevel = 0; + pr_err("VBIOS did not find boot engine clock value \ + in dependency table. Using Memory DPM level 0!"); + result = 0; + } + + table->BootVddc = data->vbios_boot_state.vddc_bootup_value; + table->BootVddci = data->vbios_boot_state.vddci_bootup_value; + table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value; + + return result; +} + +static int ci_populate_mc_reg_address(struct pp_hwmgr *hwmgr, + SMU7_Discrete_MCRegisters *mc_reg_table) +{ + const struct ci_smumgr *smu_data = (struct ci_smumgr *)hwmgr->smu_backend; + + uint32_t i, j; + + for (i = 0, j = 0; j < smu_data->mc_reg_table.last; j++) { + if (smu_data->mc_reg_table.validflag & 1<<j) { + PP_ASSERT_WITH_CODE(i < SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE, + "Index of mc_reg_table->address[] array out of boundary", return -EINVAL); + mc_reg_table->address[i].s0 = + PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s0); + mc_reg_table->address[i].s1 = + PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s1); + i++; + } + } + + mc_reg_table->last = (uint8_t)i; + + return 0; +} + +static void ci_convert_mc_registers( + const struct ci_mc_reg_entry *entry, + SMU7_Discrete_MCRegisterSet *data, + uint32_t num_entries, uint32_t valid_flag) +{ + uint32_t i, j; + + for (i = 0, j = 0; j < num_entries; j++) { + if (valid_flag & 1<<j) { + data->value[i] = PP_HOST_TO_SMC_UL(entry->mc_data[j]); + i++; + } + } +} + +static int ci_convert_mc_reg_table_entry_to_smc( + struct pp_hwmgr *hwmgr, + const uint32_t memory_clock, + SMU7_Discrete_MCRegisterSet *mc_reg_table_data + ) +{ + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + uint32_t i = 0; + + for (i = 0; i < smu_data->mc_reg_table.num_entries; i++) { + if (memory_clock <= + smu_data->mc_reg_table.mc_reg_table_entry[i].mclk_max) { + break; + } + } + + if ((i == smu_data->mc_reg_table.num_entries) && (i > 0)) + --i; + + ci_convert_mc_registers(&smu_data->mc_reg_table.mc_reg_table_entry[i], + mc_reg_table_data, smu_data->mc_reg_table.last, + smu_data->mc_reg_table.validflag); + + return 0; +} + +static int ci_convert_mc_reg_table_to_smc(struct pp_hwmgr *hwmgr, + SMU7_Discrete_MCRegisters *mc_regs) +{ + int result = 0; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + int res; + uint32_t i; + + for (i = 0; i < data->dpm_table.mclk_table.count; i++) { + res = ci_convert_mc_reg_table_entry_to_smc( + hwmgr, + data->dpm_table.mclk_table.dpm_levels[i].value, + &mc_regs->data[i] + ); + + if (0 != res) + result = res; + } + + return result; +} + +static int ci_update_and_upload_mc_reg_table(struct pp_hwmgr *hwmgr) +{ + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t address; + int32_t result; + + if (0 == (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK)) + return 0; + + + memset(&smu_data->mc_regs, 0, sizeof(SMU7_Discrete_MCRegisters)); + + result = ci_convert_mc_reg_table_to_smc(hwmgr, &(smu_data->mc_regs)); + + if (result != 0) + return result; + + address = smu_data->mc_reg_table_start + (uint32_t)offsetof(SMU7_Discrete_MCRegisters, data[0]); + + return ci_copy_bytes_to_smc(hwmgr, address, + (uint8_t *)&smu_data->mc_regs.data[0], + sizeof(SMU7_Discrete_MCRegisterSet) * data->dpm_table.mclk_table.count, + SMC_RAM_END); +} + +static int ci_populate_initial_mc_reg_table(struct pp_hwmgr *hwmgr) +{ + int result; + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + + memset(&smu_data->mc_regs, 0x00, sizeof(SMU7_Discrete_MCRegisters)); + result = ci_populate_mc_reg_address(hwmgr, &(smu_data->mc_regs)); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize MCRegTable for the MC register addresses!", return result;); + + result = ci_convert_mc_reg_table_to_smc(hwmgr, &smu_data->mc_regs); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize MCRegTable for driver state!", return result;); + + return ci_copy_bytes_to_smc(hwmgr, smu_data->mc_reg_table_start, + (uint8_t *)&smu_data->mc_regs, sizeof(SMU7_Discrete_MCRegisters), SMC_RAM_END); +} + +static int ci_populate_smc_initial_state(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + uint8_t count, level; + + count = (uint8_t)(hwmgr->dyn_state.vddc_dependency_on_sclk->count); + + for (level = 0; level < count; level++) { + if (hwmgr->dyn_state.vddc_dependency_on_sclk->entries[level].clk + >= data->vbios_boot_state.sclk_bootup_value) { + smu_data->smc_state_table.GraphicsBootLevel = level; + break; + } + } + + count = (uint8_t)(hwmgr->dyn_state.vddc_dependency_on_mclk->count); + + for (level = 0; level < count; level++) { + if (hwmgr->dyn_state.vddc_dependency_on_mclk->entries[level].clk + >= data->vbios_boot_state.mclk_bootup_value) { + smu_data->smc_state_table.MemoryBootLevel = level; + break; + } + } + + return 0; +} + +static int ci_populate_smc_svi2_config(struct pp_hwmgr *hwmgr, + SMU7_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) + table->SVI2Enable = 1; + else + table->SVI2Enable = 0; + return 0; +} + +static int ci_start_smc(struct pp_hwmgr *hwmgr) +{ + /* set smc instruct start point at 0x0 */ + ci_program_jump_on_start(hwmgr); + + /* enable smc clock */ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); + + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_RESET_CNTL, rst_reg, 0); + + PHM_WAIT_INDIRECT_FIELD(hwmgr, SMC_IND, FIRMWARE_FLAGS, + INTERRUPTS_ENABLED, 1); + + return 0; +} + +int ci_init_smc_table(struct pp_hwmgr *hwmgr) +{ + int result; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + SMU7_Discrete_DpmTable *table = &(smu_data->smc_state_table); + struct pp_atomctrl_gpio_pin_assignment gpio_pin; + u32 i; + + ci_initialize_power_tune_defaults(hwmgr); + memset(&(smu_data->smc_state_table), 0x00, sizeof(smu_data->smc_state_table)); + + if (SMU7_VOLTAGE_CONTROL_NONE != data->voltage_control) + ci_populate_smc_voltage_tables(hwmgr, table); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition)) + table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC; + + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StepVddc)) + table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC; + + if (data->is_memory_gddr5) + table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5; + + if (data->ulv_supported) { + result = ci_populate_ulv_state(hwmgr, &(table->Ulv)); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize ULV state!", return result); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_ULV_PARAMETER, 0x40035); + } + + result = ci_populate_all_graphic_levels(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Graphics Level!", return result); + + result = ci_populate_all_memory_levels(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Memory Level!", return result); + + result = ci_populate_smc_link_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Link Level!", return result); + + result = ci_populate_smc_acpi_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize ACPI Level!", return result); + + result = ci_populate_smc_vce_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize VCE Level!", return result); + + result = ci_populate_smc_acp_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize ACP Level!", return result); + + result = ci_populate_smc_samu_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize SAMU Level!", return result); + + /* Since only the initial state is completely set up at this point (the other states are just copies of the boot state) we only */ + /* need to populate the ARB settings for the initial state. */ + result = ci_program_memory_timing_parameters(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to Write ARB settings for the initial state.", return result); + + result = ci_populate_smc_uvd_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize UVD Level!", return result); + + table->UvdBootLevel = 0; + table->VceBootLevel = 0; + table->AcpBootLevel = 0; + table->SamuBootLevel = 0; + + table->GraphicsBootLevel = 0; + table->MemoryBootLevel = 0; + + result = ci_populate_smc_boot_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Boot Level!", return result); + + result = ci_populate_smc_initial_state(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, "Failed to initialize Boot State!", return result); + + result = ci_populate_bapm_parameters_in_dpm_table(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, "Failed to populate BAPM Parameters!", return result); + + table->UVDInterval = 1; + table->VCEInterval = 1; + table->ACPInterval = 1; + table->SAMUInterval = 1; + table->GraphicsVoltageChangeEnable = 1; + table->GraphicsThermThrottleEnable = 1; + table->GraphicsInterval = 1; + table->VoltageInterval = 1; + table->ThermalInterval = 1; + + table->TemperatureLimitHigh = + (data->thermal_temp_setting.temperature_high * + SMU7_Q88_FORMAT_CONVERSION_UNIT) / PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + table->TemperatureLimitLow = + (data->thermal_temp_setting.temperature_low * + SMU7_Q88_FORMAT_CONVERSION_UNIT) / PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + + table->MemoryVoltageChangeEnable = 1; + table->MemoryInterval = 1; + table->VoltageResponseTime = 0; + table->VddcVddciDelta = 4000; + table->PhaseResponseTime = 0; + table->MemoryThermThrottleEnable = 1; + + PP_ASSERT_WITH_CODE((1 <= data->dpm_table.pcie_speed_table.count), + "There must be 1 or more PCIE levels defined in PPTable.", + return -EINVAL); + + table->PCIeBootLinkLevel = (uint8_t)data->dpm_table.pcie_speed_table.count; + table->PCIeGenInterval = 1; + + ci_populate_smc_svi2_config(hwmgr, table); + + for (i = 0; i < SMU7_MAX_ENTRIES_SMIO; i++) + CONVERT_FROM_HOST_TO_SMC_UL(table->Smio[i]); + + table->ThermGpio = 17; + table->SclkStepSize = 0x4000; + if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_VRHOT_GPIO_PINID, &gpio_pin)) { + table->VRHotGpio = gpio_pin.uc_gpio_pin_bit_shift; + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot); + } else { + table->VRHotGpio = SMU7_UNUSED_GPIO_PIN; + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot); + } + + table->AcDcGpio = SMU7_UNUSED_GPIO_PIN; + + CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddcVid); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddcPhase); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddciVid); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskMvddVid); + CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize); + CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh); + CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow); + table->VddcVddciDelta = PP_HOST_TO_SMC_US(table->VddcVddciDelta); + CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime); + CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime); + + table->BootVddc = PP_HOST_TO_SMC_US(table->BootVddc * VOLTAGE_SCALE); + table->BootVddci = PP_HOST_TO_SMC_US(table->BootVddci * VOLTAGE_SCALE); + table->BootMVdd = PP_HOST_TO_SMC_US(table->BootMVdd * VOLTAGE_SCALE); + + /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */ + result = ci_copy_bytes_to_smc(hwmgr, smu_data->dpm_table_start + + offsetof(SMU7_Discrete_DpmTable, SystemFlags), + (uint8_t *)&(table->SystemFlags), + sizeof(SMU7_Discrete_DpmTable)-3 * sizeof(SMU7_PIDController), + SMC_RAM_END); + + PP_ASSERT_WITH_CODE(0 == result, + "Failed to upload dpm data to SMC memory!", return result;); + + result = ci_populate_initial_mc_reg_table(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to populate initialize MC Reg table!", return result); + + result = ci_populate_pm_fuses(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to populate PM fuses to SMC memory!", return result); + + ci_start_smc(hwmgr); + + return 0; +} + +int ci_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) +{ + struct ci_smumgr *ci_data = (struct ci_smumgr *)(hwmgr->smu_backend); + SMU7_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE }; + uint32_t duty100; + uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2; + uint16_t fdo_min, slope1, slope2; + uint32_t reference_clock; + int res; + uint64_t tmp64; + + if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl)) + return 0; + + if (hwmgr->thermal_controller.fanInfo.bNoFan) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + if (0 == ci_data->fan_table_start) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL1, FMAX_DUTY100); + + if (0 == duty100) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + tmp64 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin * duty100; + do_div(tmp64, 10000); + fdo_min = (uint16_t)tmp64; + + t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed - hwmgr->thermal_controller.advanceFanControlParameters.usTMin; + t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - hwmgr->thermal_controller.advanceFanControlParameters.usTMed; + + pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin; + pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed; + + slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100); + slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100); + + fan_table.TempMin = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMin) / 100); + fan_table.TempMed = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMed) / 100); + fan_table.TempMax = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMax) / 100); + + fan_table.Slope1 = cpu_to_be16(slope1); + fan_table.Slope2 = cpu_to_be16(slope2); + + fan_table.FdoMin = cpu_to_be16(fdo_min); + + fan_table.HystDown = cpu_to_be16(hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst); + + fan_table.HystUp = cpu_to_be16(1); + + fan_table.HystSlope = cpu_to_be16(1); + + fan_table.TempRespLim = cpu_to_be16(5); + + reference_clock = smu7_get_xclk(hwmgr); + + fan_table.RefreshPeriod = cpu_to_be32((hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay * reference_clock) / 1600); + + fan_table.FdoMax = cpu_to_be16((uint16_t)duty100); + + fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_MULT_THERMAL_CTRL, TEMP_SEL); + + res = ci_copy_bytes_to_smc(hwmgr, ci_data->fan_table_start, (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table), SMC_RAM_END); + + return 0; +} + +static int ci_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (data->need_update_smu7_dpm_table & + (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK)) + return ci_program_memory_timing_parameters(hwmgr); + + return 0; +} + +int ci_update_sclk_threshold(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + + int result = 0; + uint32_t low_sclk_interrupt_threshold = 0; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkThrottleLowNotification) + && (hwmgr->gfx_arbiter.sclk_threshold != + data->low_sclk_interrupt_threshold)) { + data->low_sclk_interrupt_threshold = + hwmgr->gfx_arbiter.sclk_threshold; + low_sclk_interrupt_threshold = + data->low_sclk_interrupt_threshold; + + CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold); + + result = ci_copy_bytes_to_smc( + hwmgr, + smu_data->dpm_table_start + + offsetof(SMU7_Discrete_DpmTable, + LowSclkInterruptT), + (uint8_t *)&low_sclk_interrupt_threshold, + sizeof(uint32_t), + SMC_RAM_END); + } + + result = ci_update_and_upload_mc_reg_table(hwmgr); + + PP_ASSERT_WITH_CODE((0 == result), "Failed to upload MC reg table!", return result); + + result = ci_program_mem_timing_parameters(hwmgr); + PP_ASSERT_WITH_CODE((result == 0), + "Failed to program memory timing parameters!", + ); + + return result; +} + +uint32_t ci_get_offsetof(uint32_t type, uint32_t member) +{ + switch (type) { + case SMU_SoftRegisters: + switch (member) { + case HandshakeDisables: + return offsetof(SMU7_SoftRegisters, HandshakeDisables); + case VoltageChangeTimeout: + return offsetof(SMU7_SoftRegisters, VoltageChangeTimeout); + case AverageGraphicsActivity: + return offsetof(SMU7_SoftRegisters, AverageGraphicsA); + case PreVBlankGap: + return offsetof(SMU7_SoftRegisters, PreVBlankGap); + case VBlankTimeout: + return offsetof(SMU7_SoftRegisters, VBlankTimeout); + } + case SMU_Discrete_DpmTable: + switch (member) { + case LowSclkInterruptThreshold: + return offsetof(SMU7_Discrete_DpmTable, LowSclkInterruptT); + } + } + pr_debug("can't get the offset of type %x member %x\n", type, member); + return 0; +} + +uint32_t ci_get_mac_definition(uint32_t value) +{ + switch (value) { + case SMU_MAX_LEVELS_GRAPHICS: + return SMU7_MAX_LEVELS_GRAPHICS; + case SMU_MAX_LEVELS_MEMORY: + return SMU7_MAX_LEVELS_MEMORY; + case SMU_MAX_LEVELS_LINK: + return SMU7_MAX_LEVELS_LINK; + case SMU_MAX_ENTRIES_SMIO: + return SMU7_MAX_ENTRIES_SMIO; + case SMU_MAX_LEVELS_VDDC: + return SMU7_MAX_LEVELS_VDDC; + case SMU_MAX_LEVELS_VDDCI: + return SMU7_MAX_LEVELS_VDDCI; + case SMU_MAX_LEVELS_MVDD: + return SMU7_MAX_LEVELS_MVDD; + } + + pr_debug("can't get the mac of %x\n", value); + return 0; +} + +static int ci_load_smc_ucode(struct pp_hwmgr *hwmgr) +{ + uint32_t byte_count, start_addr; + uint8_t *src; + uint32_t data; + + struct cgs_firmware_info info = {0}; + + cgs_get_firmware_info(hwmgr->device, CGS_UCODE_ID_SMU, &info); + + hwmgr->is_kicker = info.is_kicker; + byte_count = info.image_size; + src = (uint8_t *)info.kptr; + start_addr = info.ucode_start_address; + + if (byte_count > SMC_RAM_END) { + pr_err("SMC address is beyond the SMC RAM area.\n"); + return -EINVAL; + } + + cgs_write_register(hwmgr->device, mmSMC_IND_INDEX_0, start_addr); + PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 1); + + for (; byte_count >= 4; byte_count -= 4) { + data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3]; + cgs_write_register(hwmgr->device, mmSMC_IND_DATA_0, data); + src += 4; + } + PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 0); + + if (0 != byte_count) { + pr_err("SMC size must be dividable by 4\n"); + return -EINVAL; + } + + return 0; +} + +static int ci_upload_firmware(struct pp_hwmgr *hwmgr) +{ + if (ci_is_smc_ram_running(hwmgr)) { + pr_info("smc is running, no need to load smc firmware\n"); + return 0; + } + PHM_WAIT_INDIRECT_FIELD(hwmgr, SMC_IND, RCU_UC_EVENTS, + boot_seq_done, 1); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_MISC_CNTL, + pre_fetcher_en, 1); + + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 1); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_RESET_CNTL, rst_reg, 1); + return ci_load_smc_ucode(hwmgr); +} + +int ci_process_firmware_header(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct ci_smumgr *ci_data = (struct ci_smumgr *)(hwmgr->smu_backend); + + uint32_t tmp = 0; + int result; + bool error = false; + + if (ci_upload_firmware(hwmgr)) + return -EINVAL; + + result = ci_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU7_Firmware_Header, DpmTable), + &tmp, SMC_RAM_END); + + if (0 == result) + ci_data->dpm_table_start = tmp; + + error |= (0 != result); + + result = ci_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU7_Firmware_Header, SoftRegisters), + &tmp, SMC_RAM_END); + + if (0 == result) { + data->soft_regs_start = tmp; + ci_data->soft_regs_start = tmp; + } + + error |= (0 != result); + + result = ci_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU7_Firmware_Header, mcRegisterTable), + &tmp, SMC_RAM_END); + + if (0 == result) + ci_data->mc_reg_table_start = tmp; + + result = ci_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU7_Firmware_Header, FanTable), + &tmp, SMC_RAM_END); + + if (0 == result) + ci_data->fan_table_start = tmp; + + error |= (0 != result); + + result = ci_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU7_Firmware_Header, mcArbDramTimingTable), + &tmp, SMC_RAM_END); + + if (0 == result) + ci_data->arb_table_start = tmp; + + error |= (0 != result); + + result = ci_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU7_Firmware_Header, Version), + &tmp, SMC_RAM_END); + + if (0 == result) + hwmgr->microcode_version_info.SMC = tmp; + + error |= (0 != result); + + return error ? 1 : 0; +} + +static uint8_t ci_get_memory_modile_index(struct pp_hwmgr *hwmgr) +{ + return (uint8_t) (0xFF & (cgs_read_register(hwmgr->device, mmBIOS_SCRATCH_4) >> 16)); +} + +static bool ci_check_s0_mc_reg_index(uint16_t in_reg, uint16_t *out_reg) +{ + bool result = true; + + switch (in_reg) { + case mmMC_SEQ_RAS_TIMING: + *out_reg = mmMC_SEQ_RAS_TIMING_LP; + break; + + case mmMC_SEQ_DLL_STBY: + *out_reg = mmMC_SEQ_DLL_STBY_LP; + break; + + case mmMC_SEQ_G5PDX_CMD0: + *out_reg = mmMC_SEQ_G5PDX_CMD0_LP; + break; + + case mmMC_SEQ_G5PDX_CMD1: + *out_reg = mmMC_SEQ_G5PDX_CMD1_LP; + break; + + case mmMC_SEQ_G5PDX_CTRL: + *out_reg = mmMC_SEQ_G5PDX_CTRL_LP; + break; + + case mmMC_SEQ_CAS_TIMING: + *out_reg = mmMC_SEQ_CAS_TIMING_LP; + break; + + case mmMC_SEQ_MISC_TIMING: + *out_reg = mmMC_SEQ_MISC_TIMING_LP; + break; + + case mmMC_SEQ_MISC_TIMING2: + *out_reg = mmMC_SEQ_MISC_TIMING2_LP; + break; + + case mmMC_SEQ_PMG_DVS_CMD: + *out_reg = mmMC_SEQ_PMG_DVS_CMD_LP; + break; + + case mmMC_SEQ_PMG_DVS_CTL: + *out_reg = mmMC_SEQ_PMG_DVS_CTL_LP; + break; + + case mmMC_SEQ_RD_CTL_D0: + *out_reg = mmMC_SEQ_RD_CTL_D0_LP; + break; + + case mmMC_SEQ_RD_CTL_D1: + *out_reg = mmMC_SEQ_RD_CTL_D1_LP; + break; + + case mmMC_SEQ_WR_CTL_D0: + *out_reg = mmMC_SEQ_WR_CTL_D0_LP; + break; + + case mmMC_SEQ_WR_CTL_D1: + *out_reg = mmMC_SEQ_WR_CTL_D1_LP; + break; + + case mmMC_PMG_CMD_EMRS: + *out_reg = mmMC_SEQ_PMG_CMD_EMRS_LP; + break; + + case mmMC_PMG_CMD_MRS: + *out_reg = mmMC_SEQ_PMG_CMD_MRS_LP; + break; + + case mmMC_PMG_CMD_MRS1: + *out_reg = mmMC_SEQ_PMG_CMD_MRS1_LP; + break; + + case mmMC_SEQ_PMG_TIMING: + *out_reg = mmMC_SEQ_PMG_TIMING_LP; + break; + + case mmMC_PMG_CMD_MRS2: + *out_reg = mmMC_SEQ_PMG_CMD_MRS2_LP; + break; + + case mmMC_SEQ_WR_CTL_2: + *out_reg = mmMC_SEQ_WR_CTL_2_LP; + break; + + default: + result = false; + break; + } + + return result; +} + +static int ci_set_s0_mc_reg_index(struct ci_mc_reg_table *table) +{ + uint32_t i; + uint16_t address; + + for (i = 0; i < table->last; i++) { + table->mc_reg_address[i].s0 = + ci_check_s0_mc_reg_index(table->mc_reg_address[i].s1, &address) + ? address : table->mc_reg_address[i].s1; + } + return 0; +} + +static int ci_copy_vbios_smc_reg_table(const pp_atomctrl_mc_reg_table *table, + struct ci_mc_reg_table *ni_table) +{ + uint8_t i, j; + + PP_ASSERT_WITH_CODE((table->last <= SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + PP_ASSERT_WITH_CODE((table->num_entries <= MAX_AC_TIMING_ENTRIES), + "Invalid VramInfo table.", return -EINVAL); + + for (i = 0; i < table->last; i++) + ni_table->mc_reg_address[i].s1 = table->mc_reg_address[i].s1; + + ni_table->last = table->last; + + for (i = 0; i < table->num_entries; i++) { + ni_table->mc_reg_table_entry[i].mclk_max = + table->mc_reg_table_entry[i].mclk_max; + for (j = 0; j < table->last; j++) { + ni_table->mc_reg_table_entry[i].mc_data[j] = + table->mc_reg_table_entry[i].mc_data[j]; + } + } + + ni_table->num_entries = table->num_entries; + + return 0; +} + +static int ci_set_mc_special_registers(struct pp_hwmgr *hwmgr, + struct ci_mc_reg_table *table) +{ + uint8_t i, j, k; + uint32_t temp_reg; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + for (i = 0, j = table->last; i < table->last; i++) { + PP_ASSERT_WITH_CODE((j < SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + + switch (table->mc_reg_address[i].s1) { + + case mmMC_SEQ_MISC1: + temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS); + table->mc_reg_address[j].s1 = mmMC_PMG_CMD_EMRS; + table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_EMRS_LP; + for (k = 0; k < table->num_entries; k++) { + table->mc_reg_table_entry[k].mc_data[j] = + ((temp_reg & 0xffff0000)) | + ((table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16); + } + j++; + PP_ASSERT_WITH_CODE((j < SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + + temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS); + table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS; + table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS_LP; + for (k = 0; k < table->num_entries; k++) { + table->mc_reg_table_entry[k].mc_data[j] = + (temp_reg & 0xffff0000) | + (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); + + if (!data->is_memory_gddr5) + table->mc_reg_table_entry[k].mc_data[j] |= 0x100; + } + j++; + PP_ASSERT_WITH_CODE((j <= SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + + if (!data->is_memory_gddr5 && j < SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE) { + table->mc_reg_address[j].s1 = mmMC_PMG_AUTO_CMD; + table->mc_reg_address[j].s0 = mmMC_PMG_AUTO_CMD; + for (k = 0; k < table->num_entries; k++) { + table->mc_reg_table_entry[k].mc_data[j] = + (table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16; + } + j++; + PP_ASSERT_WITH_CODE((j <= SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + } + + break; + + case mmMC_SEQ_RESERVE_M: + temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1); + table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS1; + table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS1_LP; + for (k = 0; k < table->num_entries; k++) { + table->mc_reg_table_entry[k].mc_data[j] = + (temp_reg & 0xffff0000) | + (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); + } + j++; + PP_ASSERT_WITH_CODE((j <= SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + break; + + default: + break; + } + + } + + table->last = j; + + return 0; +} + +static int ci_set_valid_flag(struct ci_mc_reg_table *table) +{ + uint8_t i, j; + + for (i = 0; i < table->last; i++) { + for (j = 1; j < table->num_entries; j++) { + if (table->mc_reg_table_entry[j-1].mc_data[i] != + table->mc_reg_table_entry[j].mc_data[i]) { + table->validflag |= (1 << i); + break; + } + } + } + + return 0; +} + +int ci_initialize_mc_reg_table(struct pp_hwmgr *hwmgr) +{ + int result; + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + pp_atomctrl_mc_reg_table *table; + struct ci_mc_reg_table *ni_table = &smu_data->mc_reg_table; + uint8_t module_index = ci_get_memory_modile_index(hwmgr); + + table = kzalloc(sizeof(pp_atomctrl_mc_reg_table), GFP_KERNEL); + + if (NULL == table) + return -ENOMEM; + + /* Program additional LP registers that are no longer programmed by VBIOS */ + cgs_write_register(hwmgr->device, mmMC_SEQ_RAS_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RAS_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_CAS_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_CAS_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_DLL_STBY_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_DLL_STBY)); + cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0)); + cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL)); + cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_EMRS_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS1_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0)); + cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0)); + cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS2_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS2)); + cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_2_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_2)); + + memset(table, 0x00, sizeof(pp_atomctrl_mc_reg_table)); + + result = atomctrl_initialize_mc_reg_table(hwmgr, module_index, table); + + if (0 == result) + result = ci_copy_vbios_smc_reg_table(table, ni_table); + + if (0 == result) { + ci_set_s0_mc_reg_index(ni_table); + result = ci_set_mc_special_registers(hwmgr, ni_table); + } + + if (0 == result) + ci_set_valid_flag(ni_table); + + kfree(table); + + return result; +} + +bool ci_is_dpm_running(struct pp_hwmgr *hwmgr) +{ + return ci_is_smc_ram_running(hwmgr); +} + +int ci_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr, + struct amd_pp_profile *request) +{ + struct ci_smumgr *smu_data = (struct ci_smumgr *) + (hwmgr->smu_backend); + struct SMU7_Discrete_GraphicsLevel *levels = + smu_data->smc_state_table.GraphicsLevel; + uint32_t array = smu_data->dpm_table_start + + offsetof(SMU7_Discrete_DpmTable, GraphicsLevel); + uint32_t array_size = sizeof(struct SMU7_Discrete_GraphicsLevel) * + SMU7_MAX_LEVELS_GRAPHICS; + uint32_t i; + + for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) { + levels[i].ActivityLevel = + cpu_to_be16(request->activity_threshold); + levels[i].EnabledForActivity = 1; + levels[i].UpH = request->up_hyst; + levels[i].DownH = request->down_hyst; + } + + return ci_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, + array_size, SMC_RAM_END); +} diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smc.h b/drivers/gpu/drm/amd/powerplay/smumgr/ci_smc.h new file mode 100644 index 0000000..cc4176d --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/smumgr/ci_smc.h @@ -0,0 +1,52 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef CI_SMC_H +#define CI_SMC_H + +#include <linux/types.h> + + +struct pp_smumgr; +struct pp_hwmgr; +struct amd_pp_profile; + +int ci_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, + uint16_t msg, uint32_t parameter); +int ci_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg); +int ci_populate_all_graphic_levels(struct pp_hwmgr *hwmgr); +int ci_populate_all_memory_levels(struct pp_hwmgr *hwmgr); +int ci_init_smc_table(struct pp_hwmgr *hwmgr); +int ci_thermal_setup_fan_table(struct pp_hwmgr *hwmgr); +int ci_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type); +int ci_update_sclk_threshold(struct pp_hwmgr *hwmgr); +uint32_t ci_get_offsetof(uint32_t type, uint32_t member); +uint32_t ci_get_mac_definition(uint32_t value); +int ci_process_firmware_header(struct pp_hwmgr *hwmgr); +int ci_initialize_mc_reg_table(struct pp_hwmgr *hwmgr); +bool ci_is_dpm_running(struct pp_hwmgr *hwmgr); +int ci_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr, + struct amd_pp_profile *request); + + +#endif + diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c new file mode 100644 index 0000000..f265f42 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c @@ -0,0 +1,86 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/fb.h> +#include "linux/delay.h" + +#include "smumgr.h" +#include "ci_smumgr.h" +#include "cgs_common.h" +#include "ci_smc.h" + +static int ci_smu_init(struct pp_hwmgr *hwmgr) +{ + int i; + struct ci_smumgr *ci_priv = NULL; + + ci_priv = kzalloc(sizeof(struct ci_smumgr), GFP_KERNEL); + + if (ci_priv == NULL) + return -ENOMEM; + + for (i = 0; i < SMU7_MAX_LEVELS_GRAPHICS; i++) + ci_priv->activity_target[i] = 30; + + hwmgr->smu_backend = ci_priv; + + return 0; +} + +static int ci_smu_fini(struct pp_hwmgr *hwmgr) +{ + kfree(hwmgr->smu_backend); + hwmgr->smu_backend = NULL; + cgs_rel_firmware(hwmgr->device, CGS_UCODE_ID_SMU); + return 0; +} + +static int ci_start_smu(struct pp_hwmgr *hwmgr) +{ + return 0; +} + +const struct pp_smumgr_func ci_smu_funcs = { + .smu_init = ci_smu_init, + .smu_fini = ci_smu_fini, + .start_smu = ci_start_smu, + .check_fw_load_finish = NULL, + .request_smu_load_fw = NULL, + .request_smu_load_specific_fw = NULL, + .send_msg_to_smc = ci_send_msg_to_smc, + .send_msg_to_smc_with_parameter = ci_send_msg_to_smc_with_parameter, + .download_pptable_settings = NULL, + .upload_pptable_settings = NULL, + .get_offsetof = ci_get_offsetof, + .process_firmware_header = ci_process_firmware_header, + .init_smc_table = ci_init_smc_table, + .update_sclk_threshold = ci_update_sclk_threshold, + .thermal_setup_fan_table = ci_thermal_setup_fan_table, + .populate_all_graphic_levels = ci_populate_all_graphic_levels, + .populate_all_memory_levels = ci_populate_all_memory_levels, + .get_mac_definition = ci_get_mac_definition, + .initialize_mc_reg_table = ci_initialize_mc_reg_table, + .is_dpm_running = ci_is_dpm_running, + .populate_requested_graphic_levels = ci_populate_requested_graphic_levels, +}; diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.h new file mode 100644 index 0000000..8189cfa --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.h @@ -0,0 +1,78 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef _CI_SMUMANAGER_H_ +#define _CI_SMUMANAGER_H_ + +#define SMU__NUM_SCLK_DPM_STATE 8 +#define SMU__NUM_MCLK_DPM_LEVELS 6 +#define SMU__NUM_LCLK_DPM_LEVELS 8 +#define SMU__NUM_PCIE_DPM_LEVELS 8 + +#include "smu7_discrete.h" +#include <pp_endian.h> +#include "ppatomctrl.h" + +struct ci_pt_defaults { + u8 svi_load_line_en; + u8 svi_load_line_vddc; + u8 tdc_vddc_throttle_release_limit_perc; + u8 tdc_mawt; + u8 tdc_waterfall_ctl; + u8 dte_ambient_temp_base; + u32 display_cac; + u32 bapm_temp_gradient; + u16 bapmti_r[SMU7_DTE_ITERATIONS * SMU7_DTE_SOURCES * SMU7_DTE_SINKS]; + u16 bapmti_rc[SMU7_DTE_ITERATIONS * SMU7_DTE_SOURCES * SMU7_DTE_SINKS]; +}; + +struct ci_mc_reg_entry { + uint32_t mclk_max; + uint32_t mc_data[SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE]; +}; + +struct ci_mc_reg_table { + uint8_t last; + uint8_t num_entries; + uint16_t validflag; + struct ci_mc_reg_entry mc_reg_table_entry[MAX_AC_TIMING_ENTRIES]; + SMU7_Discrete_MCRegisterAddress mc_reg_address[SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE]; +}; + +struct ci_smumgr { + uint32_t soft_regs_start; + uint32_t dpm_table_start; + uint32_t mc_reg_table_start; + uint32_t fan_table_start; + uint32_t arb_table_start; + uint32_t ulv_setting_starts; + struct SMU7_Discrete_DpmTable smc_state_table; + struct SMU7_Discrete_PmFuses power_tune_table; + const struct ci_pt_defaults *power_tune_defaults; + SMU7_Discrete_MCRegisters mc_regs; + struct ci_mc_reg_table mc_reg_table; + uint32_t activity_target[SMU7_MAX_LEVELS_GRAPHICS]; + +}; + +#endif + diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c index 652aaa4..78ab055 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c @@ -52,53 +52,52 @@ static const enum cz_scratch_entry firmware_list[] = { CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G, }; -static int cz_smum_get_argument(struct pp_smumgr *smumgr) +static int cz_smum_get_argument(struct pp_hwmgr *hwmgr) { - if (smumgr == NULL || smumgr->device == NULL) + if (hwmgr == NULL || hwmgr->device == NULL) return -EINVAL; - return cgs_read_register(smumgr->device, + return cgs_read_register(hwmgr->device, mmSMU_MP1_SRBM2P_ARG_0); } -static int cz_send_msg_to_smc_async(struct pp_smumgr *smumgr, - uint16_t msg) +static int cz_send_msg_to_smc_async(struct pp_hwmgr *hwmgr, uint16_t msg) { int result = 0; - if (smumgr == NULL || smumgr->device == NULL) + if (hwmgr == NULL || hwmgr->device == NULL) return -EINVAL; - result = SMUM_WAIT_FIELD_UNEQUAL(smumgr, + result = PHM_WAIT_FIELD_UNEQUAL(hwmgr, SMU_MP1_SRBM2P_RESP_0, CONTENT, 0); if (result != 0) { pr_err("cz_send_msg_to_smc_async (0x%04x) failed\n", msg); return result; } - cgs_write_register(smumgr->device, mmSMU_MP1_SRBM2P_RESP_0, 0); - cgs_write_register(smumgr->device, mmSMU_MP1_SRBM2P_MSG_0, msg); + cgs_write_register(hwmgr->device, mmSMU_MP1_SRBM2P_RESP_0, 0); + cgs_write_register(hwmgr->device, mmSMU_MP1_SRBM2P_MSG_0, msg); return 0; } /* Send a message to the SMC, and wait for its response.*/ -static int cz_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg) +static int cz_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg) { int result = 0; - result = cz_send_msg_to_smc_async(smumgr, msg); + result = cz_send_msg_to_smc_async(hwmgr, msg); if (result != 0) return result; - return SMUM_WAIT_FIELD_UNEQUAL(smumgr, + return PHM_WAIT_FIELD_UNEQUAL(hwmgr, SMU_MP1_SRBM2P_RESP_0, CONTENT, 0); } -static int cz_set_smc_sram_address(struct pp_smumgr *smumgr, +static int cz_set_smc_sram_address(struct pp_hwmgr *hwmgr, uint32_t smc_address, uint32_t limit) { - if (smumgr == NULL || smumgr->device == NULL) + if (hwmgr == NULL || hwmgr->device == NULL) return -EINVAL; if (0 != (3 & smc_address)) { @@ -111,39 +110,39 @@ static int cz_set_smc_sram_address(struct pp_smumgr *smumgr, return -EINVAL; } - cgs_write_register(smumgr->device, mmMP0PUB_IND_INDEX_0, + cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX_0, SMN_MP1_SRAM_START_ADDR + smc_address); return 0; } -static int cz_write_smc_sram_dword(struct pp_smumgr *smumgr, +static int cz_write_smc_sram_dword(struct pp_hwmgr *hwmgr, uint32_t smc_address, uint32_t value, uint32_t limit) { int result; - if (smumgr == NULL || smumgr->device == NULL) + if (hwmgr == NULL || hwmgr->device == NULL) return -EINVAL; - result = cz_set_smc_sram_address(smumgr, smc_address, limit); + result = cz_set_smc_sram_address(hwmgr, smc_address, limit); if (!result) - cgs_write_register(smumgr->device, mmMP0PUB_IND_DATA_0, value); + cgs_write_register(hwmgr->device, mmMP0PUB_IND_DATA_0, value); return result; } -static int cz_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr, +static int cz_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, uint16_t msg, uint32_t parameter) { - if (smumgr == NULL || smumgr->device == NULL) + if (hwmgr == NULL || hwmgr->device == NULL) return -EINVAL; - cgs_write_register(smumgr->device, mmSMU_MP1_SRBM2P_ARG_0, parameter); + cgs_write_register(hwmgr->device, mmSMU_MP1_SRBM2P_ARG_0, parameter); - return cz_send_msg_to_smc(smumgr, msg); + return cz_send_msg_to_smc(hwmgr, msg); } -static int cz_check_fw_load_finish(struct pp_smumgr *smumgr, +static int cz_check_fw_load_finish(struct pp_hwmgr *hwmgr, uint32_t firmware) { int i; @@ -151,19 +150,19 @@ static int cz_check_fw_load_finish(struct pp_smumgr *smumgr, SMU8_FIRMWARE_HEADER_LOCATION + offsetof(struct SMU8_Firmware_Header, UcodeLoadStatus); - if (smumgr == NULL || smumgr->device == NULL) + if (hwmgr == NULL || hwmgr->device == NULL) return -EINVAL; - cgs_write_register(smumgr->device, mmMP0PUB_IND_INDEX, index); + cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX, index); - for (i = 0; i < smumgr->usec_timeout; i++) { + for (i = 0; i < hwmgr->usec_timeout; i++) { if (firmware == - (cgs_read_register(smumgr->device, mmMP0PUB_IND_DATA) & firmware)) + (cgs_read_register(hwmgr->device, mmMP0PUB_IND_DATA) & firmware)) break; udelay(1); } - if (i >= smumgr->usec_timeout) { + if (i >= hwmgr->usec_timeout) { pr_err("SMU check loaded firmware failed.\n"); return -EINVAL; } @@ -171,7 +170,7 @@ static int cz_check_fw_load_finish(struct pp_smumgr *smumgr, return 0; } -static int cz_load_mec_firmware(struct pp_smumgr *smumgr) +static int cz_load_mec_firmware(struct pp_hwmgr *hwmgr) { uint32_t reg_data; uint32_t tmp; @@ -179,44 +178,44 @@ static int cz_load_mec_firmware(struct pp_smumgr *smumgr) struct cgs_firmware_info info = {0}; struct cz_smumgr *cz_smu; - if (smumgr == NULL || smumgr->device == NULL) + if (hwmgr == NULL || hwmgr->device == NULL) return -EINVAL; - cz_smu = (struct cz_smumgr *)smumgr->backend; - ret = cgs_get_firmware_info(smumgr->device, + cz_smu = (struct cz_smumgr *)hwmgr->smu_backend; + ret = cgs_get_firmware_info(hwmgr->device, CGS_UCODE_ID_CP_MEC, &info); if (ret) return -EINVAL; /* Disable MEC parsing/prefetching */ - tmp = cgs_read_register(smumgr->device, + tmp = cgs_read_register(hwmgr->device, mmCP_MEC_CNTL); - tmp = SMUM_SET_FIELD(tmp, CP_MEC_CNTL, MEC_ME1_HALT, 1); - tmp = SMUM_SET_FIELD(tmp, CP_MEC_CNTL, MEC_ME2_HALT, 1); - cgs_write_register(smumgr->device, mmCP_MEC_CNTL, tmp); + tmp = PHM_SET_FIELD(tmp, CP_MEC_CNTL, MEC_ME1_HALT, 1); + tmp = PHM_SET_FIELD(tmp, CP_MEC_CNTL, MEC_ME2_HALT, 1); + cgs_write_register(hwmgr->device, mmCP_MEC_CNTL, tmp); - tmp = cgs_read_register(smumgr->device, + tmp = cgs_read_register(hwmgr->device, mmCP_CPC_IC_BASE_CNTL); - tmp = SMUM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, VMID, 0); - tmp = SMUM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, ATC, 0); - tmp = SMUM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, CACHE_POLICY, 0); - tmp = SMUM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, MTYPE, 1); - cgs_write_register(smumgr->device, mmCP_CPC_IC_BASE_CNTL, tmp); + tmp = PHM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, VMID, 0); + tmp = PHM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, ATC, 0); + tmp = PHM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, CACHE_POLICY, 0); + tmp = PHM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, MTYPE, 1); + cgs_write_register(hwmgr->device, mmCP_CPC_IC_BASE_CNTL, tmp); reg_data = smu_lower_32_bits(info.mc_addr) & - SMUM_FIELD_MASK(CP_CPC_IC_BASE_LO, IC_BASE_LO); - cgs_write_register(smumgr->device, mmCP_CPC_IC_BASE_LO, reg_data); + PHM_FIELD_MASK(CP_CPC_IC_BASE_LO, IC_BASE_LO); + cgs_write_register(hwmgr->device, mmCP_CPC_IC_BASE_LO, reg_data); reg_data = smu_upper_32_bits(info.mc_addr) & - SMUM_FIELD_MASK(CP_CPC_IC_BASE_HI, IC_BASE_HI); - cgs_write_register(smumgr->device, mmCP_CPC_IC_BASE_HI, reg_data); + PHM_FIELD_MASK(CP_CPC_IC_BASE_HI, IC_BASE_HI); + cgs_write_register(hwmgr->device, mmCP_CPC_IC_BASE_HI, reg_data); return 0; } -static uint8_t cz_translate_firmware_enum_to_arg(struct pp_smumgr *smumgr, +static uint8_t cz_translate_firmware_enum_to_arg(struct pp_hwmgr *hwmgr, enum cz_scratch_entry firmware_enum) { uint8_t ret = 0; @@ -226,7 +225,7 @@ static uint8_t cz_translate_firmware_enum_to_arg(struct pp_smumgr *smumgr, ret = UCODE_ID_SDMA0; break; case CZ_SCRATCH_ENTRY_UCODE_ID_SDMA1: - if (smumgr->chip_id == CHIP_STONEY) + if (hwmgr->chip_id == CHIP_STONEY) ret = UCODE_ID_SDMA0; else ret = UCODE_ID_SDMA1; @@ -244,7 +243,7 @@ static uint8_t cz_translate_firmware_enum_to_arg(struct pp_smumgr *smumgr, ret = UCODE_ID_CP_MEC_JT1; break; case CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2: - if (smumgr->chip_id == CHIP_STONEY) + if (hwmgr->chip_id == CHIP_STONEY) ret = UCODE_ID_CP_MEC_JT1; else ret = UCODE_ID_CP_MEC_JT2; @@ -326,17 +325,17 @@ static enum cgs_ucode_id cz_convert_fw_type_to_cgs(uint32_t fw_type) } static int cz_smu_populate_single_scratch_task( - struct pp_smumgr *smumgr, + struct pp_hwmgr *hwmgr, enum cz_scratch_entry fw_enum, uint8_t type, bool is_last) { uint8_t i; - struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; + struct cz_smumgr *cz_smu = (struct cz_smumgr *)hwmgr->smu_backend; struct TOC *toc = (struct TOC *)cz_smu->toc_buffer.kaddr; struct SMU_Task *task = &toc->tasks[cz_smu->toc_entry_used_count++]; task->type = type; - task->arg = cz_translate_firmware_enum_to_arg(smumgr, fw_enum); + task->arg = cz_translate_firmware_enum_to_arg(hwmgr, fw_enum); task->next = is_last ? END_OF_TASK_LIST : cz_smu->toc_entry_used_count; for (i = 0; i < cz_smu->scratch_buffer_length; i++) @@ -363,17 +362,17 @@ static int cz_smu_populate_single_scratch_task( } static int cz_smu_populate_single_ucode_load_task( - struct pp_smumgr *smumgr, + struct pp_hwmgr *hwmgr, enum cz_scratch_entry fw_enum, bool is_last) { uint8_t i; - struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; + struct cz_smumgr *cz_smu = (struct cz_smumgr *)hwmgr->smu_backend; struct TOC *toc = (struct TOC *)cz_smu->toc_buffer.kaddr; struct SMU_Task *task = &toc->tasks[cz_smu->toc_entry_used_count++]; task->type = TASK_TYPE_UCODE_LOAD; - task->arg = cz_translate_firmware_enum_to_arg(smumgr, fw_enum); + task->arg = cz_translate_firmware_enum_to_arg(hwmgr, fw_enum); task->next = is_last ? END_OF_TASK_LIST : cz_smu->toc_entry_used_count; for (i = 0; i < cz_smu->driver_buffer_length; i++) @@ -392,22 +391,22 @@ static int cz_smu_populate_single_ucode_load_task( return 0; } -static int cz_smu_construct_toc_for_rlc_aram_save(struct pp_smumgr *smumgr) +static int cz_smu_construct_toc_for_rlc_aram_save(struct pp_hwmgr *hwmgr) { - struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; + struct cz_smumgr *cz_smu = (struct cz_smumgr *)hwmgr->smu_backend; cz_smu->toc_entry_aram = cz_smu->toc_entry_used_count; - cz_smu_populate_single_scratch_task(smumgr, + cz_smu_populate_single_scratch_task(hwmgr, CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM, TASK_TYPE_UCODE_SAVE, true); return 0; } -static int cz_smu_initialize_toc_empty_job_list(struct pp_smumgr *smumgr) +static int cz_smu_initialize_toc_empty_job_list(struct pp_hwmgr *hwmgr) { int i; - struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; + struct cz_smumgr *cz_smu = (struct cz_smumgr *)hwmgr->smu_backend; struct TOC *toc = (struct TOC *)cz_smu->toc_buffer.kaddr; for (i = 0; i < NUM_JOBLIST_ENTRIES; i++) @@ -416,17 +415,17 @@ static int cz_smu_initialize_toc_empty_job_list(struct pp_smumgr *smumgr) return 0; } -static int cz_smu_construct_toc_for_vddgfx_enter(struct pp_smumgr *smumgr) +static int cz_smu_construct_toc_for_vddgfx_enter(struct pp_hwmgr *hwmgr) { - struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; + struct cz_smumgr *cz_smu = (struct cz_smumgr *)hwmgr->smu_backend; struct TOC *toc = (struct TOC *)cz_smu->toc_buffer.kaddr; toc->JobList[JOB_GFX_SAVE] = (uint8_t)cz_smu->toc_entry_used_count; - cz_smu_populate_single_scratch_task(smumgr, + cz_smu_populate_single_scratch_task(hwmgr, CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH, TASK_TYPE_UCODE_SAVE, false); - cz_smu_populate_single_scratch_task(smumgr, + cz_smu_populate_single_scratch_task(hwmgr, CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM, TASK_TYPE_UCODE_SAVE, true); @@ -434,121 +433,120 @@ static int cz_smu_construct_toc_for_vddgfx_enter(struct pp_smumgr *smumgr) } -static int cz_smu_construct_toc_for_vddgfx_exit(struct pp_smumgr *smumgr) +static int cz_smu_construct_toc_for_vddgfx_exit(struct pp_hwmgr *hwmgr) { - struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; + struct cz_smumgr *cz_smu = (struct cz_smumgr *)hwmgr->smu_backend; struct TOC *toc = (struct TOC *)cz_smu->toc_buffer.kaddr; toc->JobList[JOB_GFX_RESTORE] = (uint8_t)cz_smu->toc_entry_used_count; - cz_smu_populate_single_ucode_load_task(smumgr, + cz_smu_populate_single_ucode_load_task(hwmgr, CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE, false); - cz_smu_populate_single_ucode_load_task(smumgr, + cz_smu_populate_single_ucode_load_task(hwmgr, CZ_SCRATCH_ENTRY_UCODE_ID_CP_PFP, false); - cz_smu_populate_single_ucode_load_task(smumgr, + cz_smu_populate_single_ucode_load_task(hwmgr, CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME, false); - cz_smu_populate_single_ucode_load_task(smumgr, + cz_smu_populate_single_ucode_load_task(hwmgr, CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false); - if (smumgr->chip_id == CHIP_STONEY) - cz_smu_populate_single_ucode_load_task(smumgr, + if (hwmgr->chip_id == CHIP_STONEY) + cz_smu_populate_single_ucode_load_task(hwmgr, CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false); else - cz_smu_populate_single_ucode_load_task(smumgr, + cz_smu_populate_single_ucode_load_task(hwmgr, CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, false); - cz_smu_populate_single_ucode_load_task(smumgr, + cz_smu_populate_single_ucode_load_task(hwmgr, CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G, false); /* populate scratch */ - cz_smu_populate_single_scratch_task(smumgr, + cz_smu_populate_single_scratch_task(hwmgr, CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH, TASK_TYPE_UCODE_LOAD, false); - cz_smu_populate_single_scratch_task(smumgr, + cz_smu_populate_single_scratch_task(hwmgr, CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM, TASK_TYPE_UCODE_LOAD, false); - cz_smu_populate_single_scratch_task(smumgr, + cz_smu_populate_single_scratch_task(hwmgr, CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM, TASK_TYPE_UCODE_LOAD, true); return 0; } -static int cz_smu_construct_toc_for_power_profiling( - struct pp_smumgr *smumgr) +static int cz_smu_construct_toc_for_power_profiling(struct pp_hwmgr *hwmgr) { - struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; + struct cz_smumgr *cz_smu = (struct cz_smumgr *)hwmgr->smu_backend; cz_smu->toc_entry_power_profiling_index = cz_smu->toc_entry_used_count; - cz_smu_populate_single_scratch_task(smumgr, + cz_smu_populate_single_scratch_task(hwmgr, CZ_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING, TASK_TYPE_INITIALIZE, true); return 0; } -static int cz_smu_construct_toc_for_bootup(struct pp_smumgr *smumgr) +static int cz_smu_construct_toc_for_bootup(struct pp_hwmgr *hwmgr) { - struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; + struct cz_smumgr *cz_smu = (struct cz_smumgr *)hwmgr->smu_backend; cz_smu->toc_entry_initialize_index = cz_smu->toc_entry_used_count; - cz_smu_populate_single_ucode_load_task(smumgr, + cz_smu_populate_single_ucode_load_task(hwmgr, CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0, false); - if (smumgr->chip_id != CHIP_STONEY) - cz_smu_populate_single_ucode_load_task(smumgr, + if (hwmgr->chip_id != CHIP_STONEY) + cz_smu_populate_single_ucode_load_task(hwmgr, CZ_SCRATCH_ENTRY_UCODE_ID_SDMA1, false); - cz_smu_populate_single_ucode_load_task(smumgr, + cz_smu_populate_single_ucode_load_task(hwmgr, CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE, false); - cz_smu_populate_single_ucode_load_task(smumgr, + cz_smu_populate_single_ucode_load_task(hwmgr, CZ_SCRATCH_ENTRY_UCODE_ID_CP_PFP, false); - cz_smu_populate_single_ucode_load_task(smumgr, + cz_smu_populate_single_ucode_load_task(hwmgr, CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME, false); - cz_smu_populate_single_ucode_load_task(smumgr, + cz_smu_populate_single_ucode_load_task(hwmgr, CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false); - if (smumgr->chip_id != CHIP_STONEY) - cz_smu_populate_single_ucode_load_task(smumgr, + if (hwmgr->chip_id != CHIP_STONEY) + cz_smu_populate_single_ucode_load_task(hwmgr, CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, false); - cz_smu_populate_single_ucode_load_task(smumgr, + cz_smu_populate_single_ucode_load_task(hwmgr, CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G, true); return 0; } -static int cz_smu_construct_toc_for_clock_table(struct pp_smumgr *smumgr) +static int cz_smu_construct_toc_for_clock_table(struct pp_hwmgr *hwmgr) { - struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; + struct cz_smumgr *cz_smu = (struct cz_smumgr *)hwmgr->smu_backend; cz_smu->toc_entry_clock_table = cz_smu->toc_entry_used_count; - cz_smu_populate_single_scratch_task(smumgr, + cz_smu_populate_single_scratch_task(hwmgr, CZ_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE, TASK_TYPE_INITIALIZE, true); return 0; } -static int cz_smu_construct_toc(struct pp_smumgr *smumgr) +static int cz_smu_construct_toc(struct pp_hwmgr *hwmgr) { - struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; + struct cz_smumgr *cz_smu = (struct cz_smumgr *)hwmgr->smu_backend; cz_smu->toc_entry_used_count = 0; - cz_smu_initialize_toc_empty_job_list(smumgr); - cz_smu_construct_toc_for_rlc_aram_save(smumgr); - cz_smu_construct_toc_for_vddgfx_enter(smumgr); - cz_smu_construct_toc_for_vddgfx_exit(smumgr); - cz_smu_construct_toc_for_power_profiling(smumgr); - cz_smu_construct_toc_for_bootup(smumgr); - cz_smu_construct_toc_for_clock_table(smumgr); + cz_smu_initialize_toc_empty_job_list(hwmgr); + cz_smu_construct_toc_for_rlc_aram_save(hwmgr); + cz_smu_construct_toc_for_vddgfx_enter(hwmgr); + cz_smu_construct_toc_for_vddgfx_exit(hwmgr); + cz_smu_construct_toc_for_power_profiling(hwmgr); + cz_smu_construct_toc_for_bootup(hwmgr); + cz_smu_construct_toc_for_clock_table(hwmgr); return 0; } -static int cz_smu_populate_firmware_entries(struct pp_smumgr *smumgr) +static int cz_smu_populate_firmware_entries(struct pp_hwmgr *hwmgr) { - struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; + struct cz_smumgr *cz_smu = (struct cz_smumgr *)hwmgr->smu_backend; uint32_t firmware_type; uint32_t i; int ret; @@ -559,12 +557,12 @@ static int cz_smu_populate_firmware_entries(struct pp_smumgr *smumgr) for (i = 0; i < ARRAY_SIZE(firmware_list); i++) { - firmware_type = cz_translate_firmware_enum_to_arg(smumgr, + firmware_type = cz_translate_firmware_enum_to_arg(hwmgr, firmware_list[i]); ucode_id = cz_convert_fw_type_to_cgs(firmware_type); - ret = cgs_get_firmware_info(smumgr->device, + ret = cgs_get_firmware_info(hwmgr->device, ucode_id, &info); if (ret == 0) { @@ -585,12 +583,12 @@ static int cz_smu_populate_firmware_entries(struct pp_smumgr *smumgr) } static int cz_smu_populate_single_scratch_entry( - struct pp_smumgr *smumgr, + struct pp_hwmgr *hwmgr, enum cz_scratch_entry scratch_type, uint32_t ulsize_byte, struct cz_buffer_entry *entry) { - struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; + struct cz_smumgr *cz_smu = (struct cz_smumgr *)hwmgr->smu_backend; long long mc_addr = ((long long)(cz_smu->smu_buffer.mc_addr_high) << 32) | cz_smu->smu_buffer.mc_addr_low; @@ -611,9 +609,9 @@ static int cz_smu_populate_single_scratch_entry( return 0; } -static int cz_download_pptable_settings(struct pp_smumgr *smumgr, void **table) +static int cz_download_pptable_settings(struct pp_hwmgr *hwmgr, void **table) { - struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; + struct cz_smumgr *cz_smu = (struct cz_smumgr *)hwmgr->smu_backend; unsigned long i; for (i = 0; i < cz_smu->scratch_buffer_length; i++) { @@ -624,25 +622,25 @@ static int cz_download_pptable_settings(struct pp_smumgr *smumgr, void **table) *table = (struct SMU8_Fusion_ClkTable *)cz_smu->scratch_buffer[i].kaddr; - cz_send_msg_to_smc_with_parameter(smumgr, + cz_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetClkTableAddrHi, cz_smu->scratch_buffer[i].mc_addr_high); - cz_send_msg_to_smc_with_parameter(smumgr, + cz_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetClkTableAddrLo, cz_smu->scratch_buffer[i].mc_addr_low); - cz_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_ExecuteJob, + cz_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ExecuteJob, cz_smu->toc_entry_clock_table); - cz_send_msg_to_smc(smumgr, PPSMC_MSG_ClkTableXferToDram); + cz_send_msg_to_smc(hwmgr, PPSMC_MSG_ClkTableXferToDram); return 0; } -static int cz_upload_pptable_settings(struct pp_smumgr *smumgr) +static int cz_upload_pptable_settings(struct pp_hwmgr *hwmgr) { - struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; + struct cz_smumgr *cz_smu = (struct cz_smumgr *)hwmgr->smu_backend; unsigned long i; for (i = 0; i < cz_smu->scratch_buffer_length; i++) { @@ -651,63 +649,63 @@ static int cz_upload_pptable_settings(struct pp_smumgr *smumgr) break; } - cz_send_msg_to_smc_with_parameter(smumgr, + cz_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetClkTableAddrHi, cz_smu->scratch_buffer[i].mc_addr_high); - cz_send_msg_to_smc_with_parameter(smumgr, + cz_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetClkTableAddrLo, cz_smu->scratch_buffer[i].mc_addr_low); - cz_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_ExecuteJob, + cz_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ExecuteJob, cz_smu->toc_entry_clock_table); - cz_send_msg_to_smc(smumgr, PPSMC_MSG_ClkTableXferToSmu); + cz_send_msg_to_smc(hwmgr, PPSMC_MSG_ClkTableXferToSmu); return 0; } -static int cz_request_smu_load_fw(struct pp_smumgr *smumgr) +static int cz_request_smu_load_fw(struct pp_hwmgr *hwmgr) { - struct cz_smumgr *cz_smu = (struct cz_smumgr *)(smumgr->backend); + struct cz_smumgr *cz_smu = (struct cz_smumgr *)(hwmgr->smu_backend); uint32_t smc_address; - if (!smumgr->reload_fw) { + if (!hwmgr->reload_fw) { pr_info("skip reloading...\n"); return 0; } - cz_smu_populate_firmware_entries(smumgr); + cz_smu_populate_firmware_entries(hwmgr); - cz_smu_construct_toc(smumgr); + cz_smu_construct_toc(hwmgr); smc_address = SMU8_FIRMWARE_HEADER_LOCATION + offsetof(struct SMU8_Firmware_Header, UcodeLoadStatus); - cz_write_smc_sram_dword(smumgr, smc_address, 0, smc_address+4); + cz_write_smc_sram_dword(hwmgr, smc_address, 0, smc_address+4); - cz_send_msg_to_smc_with_parameter(smumgr, + cz_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_DriverDramAddrHi, cz_smu->toc_buffer.mc_addr_high); - cz_send_msg_to_smc_with_parameter(smumgr, + cz_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_DriverDramAddrLo, cz_smu->toc_buffer.mc_addr_low); - cz_send_msg_to_smc(smumgr, PPSMC_MSG_InitJobs); + cz_send_msg_to_smc(hwmgr, PPSMC_MSG_InitJobs); - cz_send_msg_to_smc_with_parameter(smumgr, + cz_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ExecuteJob, cz_smu->toc_entry_aram); - cz_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_ExecuteJob, + cz_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ExecuteJob, cz_smu->toc_entry_power_profiling_index); - return cz_send_msg_to_smc_with_parameter(smumgr, + return cz_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ExecuteJob, cz_smu->toc_entry_initialize_index); } -static int cz_start_smu(struct pp_smumgr *smumgr) +static int cz_start_smu(struct pp_hwmgr *hwmgr) { int ret = 0; uint32_t fw_to_check = 0; @@ -721,23 +719,23 @@ static int cz_start_smu(struct pp_smumgr *smumgr) UCODE_ID_CP_MEC_JT1_MASK | UCODE_ID_CP_MEC_JT2_MASK; - if (smumgr->chip_id == CHIP_STONEY) + if (hwmgr->chip_id == CHIP_STONEY) fw_to_check &= ~(UCODE_ID_SDMA1_MASK | UCODE_ID_CP_MEC_JT2_MASK); - ret = cz_request_smu_load_fw(smumgr); + ret = cz_request_smu_load_fw(hwmgr); if (ret) pr_err("SMU firmware load failed\n"); - cz_check_fw_load_finish(smumgr, fw_to_check); + cz_check_fw_load_finish(hwmgr, fw_to_check); - ret = cz_load_mec_firmware(smumgr); + ret = cz_load_mec_firmware(hwmgr); if (ret) pr_err("Mec Firmware load failed\n"); return ret; } -static int cz_smu_init(struct pp_smumgr *smumgr) +static int cz_smu_init(struct pp_hwmgr *hwmgr) { uint64_t mc_addr = 0; int ret = 0; @@ -747,7 +745,7 @@ static int cz_smu_init(struct pp_smumgr *smumgr) if (cz_smu == NULL) return -ENOMEM; - smumgr->backend = cz_smu; + hwmgr->smu_backend = cz_smu; cz_smu->toc_buffer.data_size = 4096; cz_smu->smu_buffer.data_size = @@ -757,7 +755,7 @@ static int cz_smu_init(struct pp_smumgr *smumgr) ALIGN(sizeof(struct SMU8_MultimediaPowerLogData), 32) + ALIGN(sizeof(struct SMU8_Fusion_ClkTable), 32); - ret = smu_allocate_memory(smumgr->device, + ret = smu_allocate_memory(hwmgr->device, cz_smu->toc_buffer.data_size, CGS_GPU_MEM_TYPE__GART_CACHEABLE, PAGE_SIZE, @@ -770,7 +768,7 @@ static int cz_smu_init(struct pp_smumgr *smumgr) cz_smu->toc_buffer.mc_addr_high = smu_upper_32_bits(mc_addr); cz_smu->toc_buffer.mc_addr_low = smu_lower_32_bits(mc_addr); - ret = smu_allocate_memory(smumgr->device, + ret = smu_allocate_memory(hwmgr->device, cz_smu->smu_buffer.data_size, CGS_GPU_MEM_TYPE__GART_CACHEABLE, PAGE_SIZE, @@ -783,7 +781,7 @@ static int cz_smu_init(struct pp_smumgr *smumgr) cz_smu->smu_buffer.mc_addr_high = smu_upper_32_bits(mc_addr); cz_smu->smu_buffer.mc_addr_low = smu_lower_32_bits(mc_addr); - if (0 != cz_smu_populate_single_scratch_entry(smumgr, + if (0 != cz_smu_populate_single_scratch_entry(hwmgr, CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH, UCODE_ID_RLC_SCRATCH_SIZE_BYTE, &cz_smu->scratch_buffer[cz_smu->scratch_buffer_length++])) { @@ -791,14 +789,14 @@ static int cz_smu_init(struct pp_smumgr *smumgr) return -1; } - if (0 != cz_smu_populate_single_scratch_entry(smumgr, + if (0 != cz_smu_populate_single_scratch_entry(hwmgr, CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM, UCODE_ID_RLC_SRM_ARAM_SIZE_BYTE, &cz_smu->scratch_buffer[cz_smu->scratch_buffer_length++])) { pr_err("Error when Populate Firmware Entry.\n"); return -1; } - if (0 != cz_smu_populate_single_scratch_entry(smumgr, + if (0 != cz_smu_populate_single_scratch_entry(hwmgr, CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM, UCODE_ID_RLC_SRM_DRAM_SIZE_BYTE, &cz_smu->scratch_buffer[cz_smu->scratch_buffer_length++])) { @@ -806,7 +804,7 @@ static int cz_smu_init(struct pp_smumgr *smumgr) return -1; } - if (0 != cz_smu_populate_single_scratch_entry(smumgr, + if (0 != cz_smu_populate_single_scratch_entry(hwmgr, CZ_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING, sizeof(struct SMU8_MultimediaPowerLogData), &cz_smu->scratch_buffer[cz_smu->scratch_buffer_length++])) { @@ -814,7 +812,7 @@ static int cz_smu_init(struct pp_smumgr *smumgr) return -1; } - if (0 != cz_smu_populate_single_scratch_entry(smumgr, + if (0 != cz_smu_populate_single_scratch_entry(hwmgr, CZ_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE, sizeof(struct SMU8_Fusion_ClkTable), &cz_smu->scratch_buffer[cz_smu->scratch_buffer_length++])) { @@ -825,18 +823,18 @@ static int cz_smu_init(struct pp_smumgr *smumgr) return 0; } -static int cz_smu_fini(struct pp_smumgr *smumgr) +static int cz_smu_fini(struct pp_hwmgr *hwmgr) { struct cz_smumgr *cz_smu; - if (smumgr == NULL || smumgr->device == NULL) + if (hwmgr == NULL || hwmgr->device == NULL) return -EINVAL; - cz_smu = (struct cz_smumgr *)smumgr->backend; + cz_smu = (struct cz_smumgr *)hwmgr->smu_backend; if (cz_smu) { - cgs_free_gpu_mem(smumgr->device, + cgs_free_gpu_mem(hwmgr->device, cz_smu->toc_buffer.handle); - cgs_free_gpu_mem(smumgr->device, + cgs_free_gpu_mem(hwmgr->device, cz_smu->smu_buffer.handle); kfree(cz_smu); } diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c index 8712f09..b1a66b5 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c @@ -198,7 +198,7 @@ static void get_scl_sda_value(uint8_t line, uint8_t *scl, uint8_t *sda) static void fiji_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) { - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smumgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); @@ -216,7 +216,7 @@ static void fiji_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) static int fiji_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) { - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smumgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); const struct fiji_pt_defaults *defaults = smu_data->power_tune_defaults; SMU73_Discrete_DpmTable *dpm_table = &(smu_data->smc_state_table); @@ -299,7 +299,7 @@ static int fiji_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) static int fiji_populate_svi_load_line(struct pp_hwmgr *hwmgr) { - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smumgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); const struct fiji_pt_defaults *defaults = smu_data->power_tune_defaults; smu_data->power_tune_table.SviLoadLineEn = defaults->SviLoadLineEn; @@ -314,7 +314,7 @@ static int fiji_populate_svi_load_line(struct pp_hwmgr *hwmgr) static int fiji_populate_tdc_limit(struct pp_hwmgr *hwmgr) { uint16_t tdc_limit; - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smumgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); const struct fiji_pt_defaults *defaults = smu_data->power_tune_defaults; @@ -334,11 +334,11 @@ static int fiji_populate_tdc_limit(struct pp_hwmgr *hwmgr) static int fiji_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) { - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smumgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); const struct fiji_pt_defaults *defaults = smu_data->power_tune_defaults; uint32_t temp; - if (smu7_read_smc_sram_dword(hwmgr->smumgr, + if (smu7_read_smc_sram_dword(hwmgr, fuse_table_offset + offsetof(SMU73_Discrete_PmFuses, TdcWaterfallCtl), (uint32_t *)&temp, SMC_RAM_END)) @@ -359,7 +359,7 @@ static int fiji_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) static int fiji_populate_temperature_scaler(struct pp_hwmgr *hwmgr) { int i; - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smumgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); /* Currently not used. Set all to zero. */ for (i = 0; i < 16; i++) @@ -370,7 +370,7 @@ static int fiji_populate_temperature_scaler(struct pp_hwmgr *hwmgr) static int fiji_populate_fuzzy_fan(struct pp_hwmgr *hwmgr) { - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smumgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); if ((hwmgr->thermal_controller.advanceFanControlParameters. usFanOutputSensitivity & (1 << 15)) || @@ -389,7 +389,7 @@ static int fiji_populate_fuzzy_fan(struct pp_hwmgr *hwmgr) static int fiji_populate_gnb_lpml(struct pp_hwmgr *hwmgr) { int i; - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smumgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); /* Currently not used. Set all to zero. */ for (i = 0; i < 16; i++) @@ -398,14 +398,9 @@ static int fiji_populate_gnb_lpml(struct pp_hwmgr *hwmgr) return 0; } -static int fiji_min_max_vgnb_lpml_id_from_bapm_vddc(struct pp_hwmgr *hwmgr) -{ - return 0; -} - static int fiji_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) { - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smumgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); uint16_t HiSidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd; @@ -426,11 +421,11 @@ static int fiji_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) static int fiji_populate_pm_fuses(struct pp_hwmgr *hwmgr) { uint32_t pm_fuse_table_offset; - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smumgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PowerContainment)) { - if (smu7_read_smc_sram_dword(hwmgr->smumgr, + if (smu7_read_smc_sram_dword(hwmgr, SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU73_Firmware_Header, PmFuseTable), &pm_fuse_table_offset, SMC_RAM_END)) @@ -472,19 +467,13 @@ static int fiji_populate_pm_fuses(struct pp_hwmgr *hwmgr) "Attempt to populate GnbLPML Failed!", return -EINVAL); - /* DW19 */ - if (fiji_min_max_vgnb_lpml_id_from_bapm_vddc(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate GnbLPML Min and Max Vid Failed!", - return -EINVAL); - /* DW20 */ if (fiji_populate_bapm_vddc_base_leakage_sidd(hwmgr)) PP_ASSERT_WITH_CODE(false, "Attempt to populate BapmVddCBaseLeakage Hi and Lo " "Sidd Failed!", return -EINVAL); - if (smu7_copy_bytes_to_smc(hwmgr->smumgr, pm_fuse_table_offset, + if (smu7_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset, (uint8_t *)&smu_data->power_tune_table, sizeof(struct SMU73_Discrete_PmFuses), SMC_RAM_END)) PP_ASSERT_WITH_CODE(false, @@ -586,7 +575,7 @@ static int fiji_populate_smc_link_level(struct pp_hwmgr *hwmgr, { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); struct smu7_dpm_table *dpm_table = &data->dpm_table; - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smumgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); int i; /* Index (dpm_table->pcie_speed_table.count) @@ -774,7 +763,7 @@ static int fiji_populate_single_graphic_level(struct pp_hwmgr *hwmgr, int fiji_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smumgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); struct smu7_dpm_table *dpm_table = &data->dpm_table; struct phm_ppt_v1_information *table_info = @@ -859,7 +848,7 @@ int fiji_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) levels[1].pcieDpmLevel = mid_pcie_level_enabled; } /* level count will send to smc once at init smc table and never change */ - result = smu7_copy_bytes_to_smc(hwmgr->smumgr, array, (uint8_t *)levels, + result = smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, (uint32_t)array_size, SMC_RAM_END); return result; @@ -1000,7 +989,7 @@ static int fiji_populate_single_memory_level(struct pp_hwmgr *hwmgr, int fiji_populate_all_memory_levels(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smumgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); struct smu7_dpm_table *dpm_table = &data->dpm_table; int result; /* populate MCLK dpm table to SMU7 */ @@ -1043,7 +1032,7 @@ int fiji_populate_all_memory_levels(struct pp_hwmgr *hwmgr) PPSMC_DISPLAY_WATERMARK_HIGH; /* level count will send to smc once at init smc table and never change */ - result = smu7_copy_bytes_to_smc(hwmgr->smumgr, array, (uint8_t *)levels, + result = smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, (uint32_t)array_size, SMC_RAM_END); return result; @@ -1352,7 +1341,7 @@ static int fiji_populate_memory_timing_parameters(struct pp_hwmgr *hwmgr, static int fiji_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smumgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); struct SMU73_Discrete_MCArbDramTimingTable arb_regs; uint32_t i, j; int result = 0; @@ -1370,7 +1359,7 @@ static int fiji_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) if (!result) result = smu7_copy_bytes_to_smc( - hwmgr->smumgr, + hwmgr, smu_data->smu7_data.arb_table_start, (uint8_t *)&arb_regs, sizeof(SMU73_Discrete_MCArbDramTimingTable), @@ -1460,7 +1449,7 @@ static int fiji_populate_smc_boot_level(struct pp_hwmgr *hwmgr, static int fiji_populate_smc_initailial_state(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smumgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); uint8_t count, level; @@ -1491,7 +1480,7 @@ static int fiji_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr) uint32_t ro, efuse, efuse2, clock_freq, volt_without_cks, volt_with_cks, value; uint16_t clock_freq_u16; - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smumgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); uint8_t type, i, j, cks_setting, stretch_amount, stretch_amount2, volt_offset = 0; struct phm_ppt_v1_information *table_info = @@ -1694,9 +1683,9 @@ static int fiji_populate_vr_config(struct pp_hwmgr *hwmgr, return 0; } -static int fiji_init_arb_table_index(struct pp_smumgr *smumgr) +static int fiji_init_arb_table_index(struct pp_hwmgr *hwmgr) { - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(smumgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); uint32_t tmp; int result; @@ -1708,7 +1697,7 @@ static int fiji_init_arb_table_index(struct pp_smumgr *smumgr) * In reality this field should not be in that structure * but in a soft register. */ - result = smu7_read_smc_sram_dword(smumgr, + result = smu7_read_smc_sram_dword(hwmgr, smu_data->smu7_data.arb_table_start, &tmp, SMC_RAM_END); if (result) @@ -1717,13 +1706,13 @@ static int fiji_init_arb_table_index(struct pp_smumgr *smumgr) tmp &= 0x00FFFFFF; tmp |= ((uint32_t)MC_CG_ARB_FREQ_F1) << 24; - return smu7_write_smc_sram_dword(smumgr, + return smu7_write_smc_sram_dword(hwmgr, smu_data->smu7_data.arb_table_start, tmp, SMC_RAM_END); } static int fiji_save_default_power_profile(struct pp_hwmgr *hwmgr) { - struct fiji_smumgr *data = (struct fiji_smumgr *)(hwmgr->smumgr->backend); + struct fiji_smumgr *data = (struct fiji_smumgr *)(hwmgr->smu_backend); struct SMU73_Discrete_GraphicsLevel *levels = data->smc_state_table.GraphicsLevel; unsigned min_level = 1; @@ -1782,7 +1771,7 @@ static int fiji_setup_dpm_led_config(struct pp_hwmgr *hwmgr) } } if (mask) - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_LedConfig, mask); return 0; @@ -1799,7 +1788,7 @@ int fiji_init_smc_table(struct pp_hwmgr *hwmgr) { int result; struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smumgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); struct SMU73_Discrete_DpmTable *table = &(smu_data->smc_state_table); @@ -1985,7 +1974,7 @@ int fiji_init_smc_table(struct pp_hwmgr *hwmgr) CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime); /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */ - result = smu7_copy_bytes_to_smc(hwmgr->smumgr, + result = smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.dpm_table_start + offsetof(SMU73_Discrete_DpmTable, SystemFlags), (uint8_t *)&(table->SystemFlags), @@ -1994,7 +1983,7 @@ int fiji_init_smc_table(struct pp_hwmgr *hwmgr) PP_ASSERT_WITH_CODE(0 == result, "Failed to upload dpm data to SMC memory!", return result); - result = fiji_init_arb_table_index(hwmgr->smumgr); + result = fiji_init_arb_table_index(hwmgr); PP_ASSERT_WITH_CODE(0 == result, "Failed to upload arb data to SMC memory!", return result); @@ -2022,7 +2011,7 @@ int fiji_init_smc_table(struct pp_hwmgr *hwmgr) */ int fiji_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) { - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smumgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); SMU73_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE }; uint32_t duty100; @@ -2104,20 +2093,20 @@ int fiji_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) hwmgr->device, CGS_IND_REG__SMC, CG_MULT_THERMAL_CTRL, TEMP_SEL); - res = smu7_copy_bytes_to_smc(hwmgr->smumgr, smu_data->smu7_data.fan_table_start, + res = smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.fan_table_start, (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table), SMC_RAM_END); if (!res && hwmgr->thermal_controller. advanceFanControlParameters.ucMinimumPWMLimit) - res = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + res = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetFanMinPwm, hwmgr->thermal_controller. advanceFanControlParameters.ucMinimumPWMLimit); if (!res && hwmgr->thermal_controller. advanceFanControlParameters.ulMinFanSCLKAcousticLimit) - res = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + res = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetFanSclkTarget, hwmgr->thermal_controller. advanceFanControlParameters.ulMinFanSCLKAcousticLimit); @@ -2133,13 +2122,12 @@ int fiji_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) int fiji_thermal_avfs_enable(struct pp_hwmgr *hwmgr) { int ret; - struct pp_smumgr *smumgr = (struct pp_smumgr *)(hwmgr->smumgr); - struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(smumgr->backend); + struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); if (smu_data->avfs.avfs_btc_status != AVFS_BTC_ENABLEAVFS) return 0; - ret = smum_send_msg_to_smc(smumgr, PPSMC_MSG_EnableAvfs); + ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableAvfs); if (!ret) /* If this param is not changed, this function could fire unnecessarily */ @@ -2162,7 +2150,7 @@ static int fiji_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) int fiji_update_sclk_threshold(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smumgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); int result = 0; uint32_t low_sclk_interrupt_threshold = 0; @@ -2179,7 +2167,7 @@ int fiji_update_sclk_threshold(struct pp_hwmgr *hwmgr) CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold); result = smu7_copy_bytes_to_smc( - hwmgr->smumgr, + hwmgr, smu_data->smu7_data.dpm_table_start + offsetof(SMU73_Discrete_DpmTable, LowSclkInterruptThreshold), @@ -2256,7 +2244,7 @@ uint32_t fiji_get_mac_definition(uint32_t value) static int fiji_update_uvd_smc_table(struct pp_hwmgr *hwmgr) { - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smumgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); uint32_t mm_boot_level_offset, mm_boot_level_value; struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); @@ -2280,7 +2268,7 @@ static int fiji_update_uvd_smc_table(struct pp_hwmgr *hwmgr) PHM_PlatformCaps_UVDDPM) || phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_UVDDPM_SetEnabledMask, (uint32_t)(1 << smu_data->smc_state_table.UvdBootLevel)); return 0; @@ -2288,7 +2276,7 @@ static int fiji_update_uvd_smc_table(struct pp_hwmgr *hwmgr) static int fiji_update_vce_smc_table(struct pp_hwmgr *hwmgr) { - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smumgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); uint32_t mm_boot_level_offset, mm_boot_level_value; struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); @@ -2312,7 +2300,7 @@ static int fiji_update_vce_smc_table(struct pp_hwmgr *hwmgr) CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_VCEDPM_SetEnabledMask, (uint32_t)1 << smu_data->smc_state_table.VceBootLevel); return 0; @@ -2320,7 +2308,7 @@ static int fiji_update_vce_smc_table(struct pp_hwmgr *hwmgr) static int fiji_update_samu_smc_table(struct pp_hwmgr *hwmgr) { - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smumgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); uint32_t mm_boot_level_offset, mm_boot_level_value; @@ -2339,7 +2327,7 @@ static int fiji_update_samu_smc_table(struct pp_hwmgr *hwmgr) if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SAMUDPM_SetEnabledMask, (uint32_t)(1 << smu_data->smc_state_table.SamuBootLevel)); return 0; @@ -2373,12 +2361,12 @@ int fiji_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type) int fiji_process_firmware_header(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smumgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); uint32_t tmp; int result; bool error = false; - result = smu7_read_smc_sram_dword(hwmgr->smumgr, + result = smu7_read_smc_sram_dword(hwmgr, SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU73_Firmware_Header, DpmTable), &tmp, SMC_RAM_END); @@ -2388,7 +2376,7 @@ int fiji_process_firmware_header(struct pp_hwmgr *hwmgr) error |= (0 != result); - result = smu7_read_smc_sram_dword(hwmgr->smumgr, + result = smu7_read_smc_sram_dword(hwmgr, SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU73_Firmware_Header, SoftRegisters), &tmp, SMC_RAM_END); @@ -2400,7 +2388,7 @@ int fiji_process_firmware_header(struct pp_hwmgr *hwmgr) error |= (0 != result); - result = smu7_read_smc_sram_dword(hwmgr->smumgr, + result = smu7_read_smc_sram_dword(hwmgr, SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU73_Firmware_Header, mcRegisterTable), &tmp, SMC_RAM_END); @@ -2408,7 +2396,7 @@ int fiji_process_firmware_header(struct pp_hwmgr *hwmgr) if (!result) smu_data->smu7_data.mc_reg_table_start = tmp; - result = smu7_read_smc_sram_dword(hwmgr->smumgr, + result = smu7_read_smc_sram_dword(hwmgr, SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU73_Firmware_Header, FanTable), &tmp, SMC_RAM_END); @@ -2418,7 +2406,7 @@ int fiji_process_firmware_header(struct pp_hwmgr *hwmgr) error |= (0 != result); - result = smu7_read_smc_sram_dword(hwmgr->smumgr, + result = smu7_read_smc_sram_dword(hwmgr, SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU73_Firmware_Header, mcArbDramTimingTable), &tmp, SMC_RAM_END); @@ -2428,7 +2416,7 @@ int fiji_process_firmware_header(struct pp_hwmgr *hwmgr) error |= (0 != result); - result = smu7_read_smc_sram_dword(hwmgr->smumgr, + result = smu7_read_smc_sram_dword(hwmgr, SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU73_Firmware_Header, Version), &tmp, SMC_RAM_END); @@ -2476,7 +2464,7 @@ int fiji_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr, struct amd_pp_profile *request) { struct fiji_smumgr *smu_data = (struct fiji_smumgr *) - (hwmgr->smumgr->backend); + (hwmgr->smu_backend); struct SMU73_Discrete_GraphicsLevel *levels = smu_data->smc_state_table.GraphicsLevel; uint32_t array = smu_data->smu7_data.dpm_table_start + @@ -2493,6 +2481,6 @@ int fiji_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr, levels[i].DownHyst = request->down_hyst; } - return smu7_copy_bytes_to_smc(hwmgr->smumgr, array, (uint8_t *)levels, + return smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, array_size, SMC_RAM_END); } diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c index 6ae948f..5b25e06 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c @@ -58,122 +58,122 @@ static const struct SMU73_Discrete_GraphicsLevel avfs_graphics_level[8] = { { 0xf811d047, 0x80380100, 0x01, 0x00, 0x1e00, 0x00000610, 0x87020000, 0x21680000, 0x12000000, 0, 0, 0x0c, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 } }; -static int fiji_start_smu_in_protection_mode(struct pp_smumgr *smumgr) +static int fiji_start_smu_in_protection_mode(struct pp_hwmgr *hwmgr) { int result = 0; /* Wait for smc boot up */ - /* SMUM_WAIT_INDIRECT_FIELD_UNEQUAL(smumgr, SMC_IND, + /* PHM_WAIT_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND, RCU_UC_EVENTS, boot_seq_done, 0); */ - SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_RESET_CNTL, rst_reg, 1); - result = smu7_upload_smu_firmware_image(smumgr); + result = smu7_upload_smu_firmware_image(hwmgr); if (result) return result; /* Clear status */ - cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC, + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMU_STATUS, 0); - SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); /* De-assert reset */ - SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_RESET_CNTL, rst_reg, 0); /* Wait for ROM firmware to initialize interrupt hendler */ - /*SMUM_WAIT_VFPF_INDIRECT_REGISTER(smumgr, SMC_IND, + /*SMUM_WAIT_VFPF_INDIRECT_REGISTER(hwmgr, SMC_IND, SMC_INTR_CNTL_MASK_0, 0x10040, 0xFFFFFFFF); */ /* Set SMU Auto Start */ - SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMU_INPUT_DATA, AUTO_START, 1); /* Clear firmware interrupt enable flag */ - cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC, + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixFIRMWARE_FLAGS, 0); - SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, SMC_IND, RCU_UC_EVENTS, + PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, RCU_UC_EVENTS, INTERRUPTS_ENABLED, 1); - cgs_write_register(smumgr->device, mmSMC_MSG_ARG_0, 0x20000); - cgs_write_register(smumgr->device, mmSMC_MESSAGE_0, PPSMC_MSG_Test); - SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0); + cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, 0x20000); + cgs_write_register(hwmgr->device, mmSMC_MESSAGE_0, PPSMC_MSG_Test); + PHM_WAIT_FIELD_UNEQUAL(hwmgr, SMC_RESP_0, SMC_RESP, 0); /* Wait for done bit to be set */ - SMUM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(smumgr, SMC_IND, + PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND, SMU_STATUS, SMU_DONE, 0); /* Check pass/failed indicator */ - if (SMUM_READ_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + if (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMU_STATUS, SMU_PASS) != 1) { PP_ASSERT_WITH_CODE(false, "SMU Firmware start failed!", return -1); } /* Wait for firmware to initialize */ - SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, SMC_IND, + PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1); return result; } -static int fiji_start_smu_in_non_protection_mode(struct pp_smumgr *smumgr) +static int fiji_start_smu_in_non_protection_mode(struct pp_hwmgr *hwmgr) { int result = 0; /* wait for smc boot up */ - SMUM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(smumgr, SMC_IND, + PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND, RCU_UC_EVENTS, boot_seq_done, 0); /* Clear firmware interrupt enable flag */ - cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC, + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixFIRMWARE_FLAGS, 0); /* Assert reset */ - SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_RESET_CNTL, rst_reg, 1); - result = smu7_upload_smu_firmware_image(smumgr); + result = smu7_upload_smu_firmware_image(hwmgr); if (result) return result; /* Set smc instruct start point at 0x0 */ - smu7_program_jump_on_start(smumgr); + smu7_program_jump_on_start(hwmgr); /* Enable clock */ - SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); /* De-assert reset */ - SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_RESET_CNTL, rst_reg, 0); /* Wait for firmware to initialize */ - SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, SMC_IND, + PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1); return result; } -static int fiji_setup_pwr_virus(struct pp_smumgr *smumgr) +static int fiji_setup_pwr_virus(struct pp_hwmgr *hwmgr) { int i; int result = -EINVAL; uint32_t reg, data; const PWR_Command_Table *pvirus = PwrVirusTable; - struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(smumgr->backend); + struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); for (i = 0; i < PWR_VIRUS_TABLE_SIZE; i++) { switch (pvirus->command) { case PwrCmdWrite: reg = pvirus->reg; data = pvirus->data; - cgs_write_register(smumgr->device, reg, data); + cgs_write_register(hwmgr->device, reg, data); break; case PwrCmdEnd: @@ -192,13 +192,13 @@ static int fiji_setup_pwr_virus(struct pp_smumgr *smumgr) return result; } -static int fiji_start_avfs_btc(struct pp_smumgr *smumgr) +static int fiji_start_avfs_btc(struct pp_hwmgr *hwmgr) { int result = 0; - struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(smumgr->backend); + struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); if (0 != smu_data->avfs.avfs_btc_param) { - if (0 != smu7_send_msg_to_smc_with_parameter(smumgr, + if (0 != smu7_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_PerformBtc, smu_data->avfs.avfs_btc_param)) { pr_info("[AVFS][Fiji_PerformBtc] PerformBTC SMU msg failed"); result = -EINVAL; @@ -206,23 +206,23 @@ static int fiji_start_avfs_btc(struct pp_smumgr *smumgr) } /* Soft-Reset to reset the engine before loading uCode */ /* halt */ - cgs_write_register(smumgr->device, mmCP_MEC_CNTL, 0x50000000); + cgs_write_register(hwmgr->device, mmCP_MEC_CNTL, 0x50000000); /* reset everything */ - cgs_write_register(smumgr->device, mmGRBM_SOFT_RESET, 0xffffffff); + cgs_write_register(hwmgr->device, mmGRBM_SOFT_RESET, 0xffffffff); /* clear reset */ - cgs_write_register(smumgr->device, mmGRBM_SOFT_RESET, 0); + cgs_write_register(hwmgr->device, mmGRBM_SOFT_RESET, 0); return result; } -static int fiji_setup_graphics_level_structure(struct pp_smumgr *smumgr) +static int fiji_setup_graphics_level_structure(struct pp_hwmgr *hwmgr) { int32_t vr_config; uint32_t table_start; uint32_t level_addr, vr_config_addr; uint32_t level_size = sizeof(avfs_graphics_level); - PP_ASSERT_WITH_CODE(0 == smu7_read_smc_sram_dword(smumgr, + PP_ASSERT_WITH_CODE(0 == smu7_read_smc_sram_dword(hwmgr, SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU73_Firmware_Header, DpmTable), &table_start, 0x40000), @@ -237,7 +237,7 @@ static int fiji_setup_graphics_level_structure(struct pp_smumgr *smumgr) vr_config_addr = table_start + offsetof(SMU73_Discrete_DpmTable, VRConfig); - PP_ASSERT_WITH_CODE(0 == smu7_copy_bytes_to_smc(smumgr, vr_config_addr, + PP_ASSERT_WITH_CODE(0 == smu7_copy_bytes_to_smc(hwmgr, vr_config_addr, (uint8_t *)&vr_config, sizeof(int32_t), 0x40000), "[AVFS][Fiji_SetupGfxLvlStruct] Problems copying " "vr_config value over to SMC", @@ -245,7 +245,7 @@ static int fiji_setup_graphics_level_structure(struct pp_smumgr *smumgr) level_addr = table_start + offsetof(SMU73_Discrete_DpmTable, GraphicsLevel); - PP_ASSERT_WITH_CODE(0 == smu7_copy_bytes_to_smc(smumgr, level_addr, + PP_ASSERT_WITH_CODE(0 == smu7_copy_bytes_to_smc(hwmgr, level_addr, (uint8_t *)(&avfs_graphics_level), level_size, 0x40000), "[AVFS][Fiji_SetupGfxLvlStruct] Copying of DPM table failed!", return -1;); @@ -253,9 +253,9 @@ static int fiji_setup_graphics_level_structure(struct pp_smumgr *smumgr) return 0; } -static int fiji_avfs_event_mgr(struct pp_smumgr *smumgr, bool smu_started) +static int fiji_avfs_event_mgr(struct pp_hwmgr *hwmgr, bool smu_started) { - struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(smumgr->backend); + struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); switch (smu_data->avfs.avfs_btc_status) { case AVFS_BTC_COMPLETED_PREVIOUSLY: @@ -265,17 +265,17 @@ static int fiji_avfs_event_mgr(struct pp_smumgr *smumgr, bool smu_started) if (!smu_started) break; smu_data->avfs.avfs_btc_status = AVFS_BTC_FAILED; - PP_ASSERT_WITH_CODE(0 == fiji_setup_graphics_level_structure(smumgr), + PP_ASSERT_WITH_CODE(0 == fiji_setup_graphics_level_structure(hwmgr), "[AVFS][fiji_avfs_event_mgr] Could not Copy Graphics Level" " table over to SMU", return -EINVAL;); smu_data->avfs.avfs_btc_status = AVFS_BTC_VIRUS_FAIL; - PP_ASSERT_WITH_CODE(0 == fiji_setup_pwr_virus(smumgr), + PP_ASSERT_WITH_CODE(0 == fiji_setup_pwr_virus(hwmgr), "[AVFS][fiji_avfs_event_mgr] Could not setup " "Pwr Virus for AVFS ", return -EINVAL;); smu_data->avfs.avfs_btc_status = AVFS_BTC_FAILED; - PP_ASSERT_WITH_CODE(0 == fiji_start_avfs_btc(smumgr), + PP_ASSERT_WITH_CODE(0 == fiji_start_avfs_btc(hwmgr), "[AVFS][fiji_avfs_event_mgr] Failure at " "fiji_start_avfs_btc. AVFS Disabled", return -EINVAL;); @@ -293,64 +293,64 @@ static int fiji_avfs_event_mgr(struct pp_smumgr *smumgr, bool smu_started) return 0; } -static int fiji_start_smu(struct pp_smumgr *smumgr) +static int fiji_start_smu(struct pp_hwmgr *hwmgr) { int result = 0; - struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend); + struct fiji_smumgr *priv = (struct fiji_smumgr *)(hwmgr->smu_backend); /* Only start SMC if SMC RAM is not running */ - if (!(smu7_is_smc_ram_running(smumgr) - || cgs_is_virtualization_enabled(smumgr->device))) { - fiji_avfs_event_mgr(smumgr, false); + if (!(smu7_is_smc_ram_running(hwmgr) + || cgs_is_virtualization_enabled(hwmgr->device))) { + fiji_avfs_event_mgr(hwmgr, false); /* Check if SMU is running in protected mode */ - if (0 == SMUM_READ_VFPF_INDIRECT_FIELD(smumgr->device, + if (0 == PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMU_FIRMWARE, SMU_MODE)) { - result = fiji_start_smu_in_non_protection_mode(smumgr); + result = fiji_start_smu_in_non_protection_mode(hwmgr); if (result) return result; } else { - result = fiji_start_smu_in_protection_mode(smumgr); + result = fiji_start_smu_in_protection_mode(hwmgr); if (result) return result; } - fiji_avfs_event_mgr(smumgr, true); + fiji_avfs_event_mgr(hwmgr, true); } /* To initialize all clock gating before RLC loaded and running.*/ - cgs_set_clockgating_state(smumgr->device, + cgs_set_clockgating_state(hwmgr->device, AMD_IP_BLOCK_TYPE_GFX, AMD_CG_STATE_GATE); - cgs_set_clockgating_state(smumgr->device, + cgs_set_clockgating_state(hwmgr->device, AMD_IP_BLOCK_TYPE_GMC, AMD_CG_STATE_GATE); - cgs_set_clockgating_state(smumgr->device, + cgs_set_clockgating_state(hwmgr->device, AMD_IP_BLOCK_TYPE_SDMA, AMD_CG_STATE_GATE); - cgs_set_clockgating_state(smumgr->device, + cgs_set_clockgating_state(hwmgr->device, AMD_IP_BLOCK_TYPE_COMMON, AMD_CG_STATE_GATE); /* Setup SoftRegsStart here for register lookup in case * DummyBackEnd is used and ProcessFirmwareHeader is not executed */ - smu7_read_smc_sram_dword(smumgr, + smu7_read_smc_sram_dword(hwmgr, SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU73_Firmware_Header, SoftRegisters), &(priv->smu7_data.soft_regs_start), 0x40000); - result = smu7_request_smu_load_fw(smumgr); + result = smu7_request_smu_load_fw(hwmgr); return result; } -static bool fiji_is_hw_avfs_present(struct pp_smumgr *smumgr) +static bool fiji_is_hw_avfs_present(struct pp_hwmgr *hwmgr) { uint32_t efuse = 0; uint32_t mask = (1 << ((AVFS_EN_MSB - AVFS_EN_LSB) + 1)) - 1; - if (cgs_is_virtualization_enabled(smumgr->device)) + if (cgs_is_virtualization_enabled(hwmgr->device)) return 0; - if (!atomctrl_read_efuse(smumgr->device, AVFS_EN_LSB, AVFS_EN_MSB, + if (!atomctrl_read_efuse(hwmgr->device, AVFS_EN_LSB, AVFS_EN_MSB, mask, &efuse)) { if (efuse) return true; @@ -365,7 +365,7 @@ static bool fiji_is_hw_avfs_present(struct pp_smumgr *smumgr) * @param smc_addr the address in the SMC RAM to access. * @param value to write to the SMC SRAM. */ -static int fiji_smu_init(struct pp_smumgr *smumgr) +static int fiji_smu_init(struct pp_hwmgr *hwmgr) { int i; struct fiji_smumgr *fiji_priv = NULL; @@ -375,9 +375,9 @@ static int fiji_smu_init(struct pp_smumgr *smumgr) if (fiji_priv == NULL) return -ENOMEM; - smumgr->backend = fiji_priv; + hwmgr->smu_backend = fiji_priv; - if (smu7_init(smumgr)) + if (smu7_init(hwmgr)) return -EINVAL; for (i = 0; i < SMU73_MAX_LEVELS_GRAPHICS; i++) diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.c b/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.c index 51adf04..efb0fc0 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.c @@ -101,7 +101,7 @@ static const struct iceland_pt_defaults defaults_icelandpro = { static void iceland_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) { - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); struct cgs_system_info sys_info = {0}; uint32_t dev_id; @@ -130,7 +130,7 @@ static void iceland_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) static int iceland_populate_svi_load_line(struct pp_hwmgr *hwmgr) { - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); const struct iceland_pt_defaults *defaults = smu_data->power_tune_defaults; smu_data->power_tune_table.SviLoadLineEn = defaults->svi_load_line_en; @@ -144,7 +144,7 @@ static int iceland_populate_svi_load_line(struct pp_hwmgr *hwmgr) static int iceland_populate_tdc_limit(struct pp_hwmgr *hwmgr) { uint16_t tdc_limit; - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); const struct iceland_pt_defaults *defaults = smu_data->power_tune_defaults; tdc_limit = (uint16_t)(hwmgr->dyn_state.cac_dtp_table->usTDC * 256); @@ -159,11 +159,11 @@ static int iceland_populate_tdc_limit(struct pp_hwmgr *hwmgr) static int iceland_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) { - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); const struct iceland_pt_defaults *defaults = smu_data->power_tune_defaults; uint32_t temp; - if (smu7_read_smc_sram_dword(hwmgr->smumgr, + if (smu7_read_smc_sram_dword(hwmgr, fuse_table_offset + offsetof(SMU71_Discrete_PmFuses, TdcWaterfallCtl), (uint32_t *)&temp, SMC_RAM_END)) @@ -184,7 +184,7 @@ static int iceland_populate_temperature_scaler(struct pp_hwmgr *hwmgr) static int iceland_populate_gnb_lpml(struct pp_hwmgr *hwmgr) { int i; - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); /* Currently not used. Set all to zero. */ for (i = 0; i < 8; i++) @@ -193,14 +193,9 @@ static int iceland_populate_gnb_lpml(struct pp_hwmgr *hwmgr) return 0; } -static int iceland_min_max_vgnb_lpml_id_from_bapm_vddc(struct pp_hwmgr *hwmgr) -{ - return 0; -} - static int iceland_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) { - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); uint16_t HiSidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd; uint16_t LoSidd = smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd; struct phm_cac_tdp_table *cac_table = hwmgr->dyn_state.cac_dtp_table; @@ -219,7 +214,7 @@ static int iceland_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) static int iceland_populate_bapm_vddc_vid_sidd(struct pp_hwmgr *hwmgr) { int i; - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); uint8_t *hi_vid = smu_data->power_tune_table.BapmVddCVidHiSidd; uint8_t *lo_vid = smu_data->power_tune_table.BapmVddCVidLoSidd; @@ -245,7 +240,7 @@ static int iceland_populate_bapm_vddc_vid_sidd(struct pp_hwmgr *hwmgr) static int iceland_populate_vddc_vid(struct pp_hwmgr *hwmgr) { int i; - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); uint8_t *vid = smu_data->power_tune_table.VddCVid; struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); @@ -264,12 +259,12 @@ static int iceland_populate_vddc_vid(struct pp_hwmgr *hwmgr) static int iceland_populate_pm_fuses(struct pp_hwmgr *hwmgr) { - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); uint32_t pm_fuse_table_offset; if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PowerContainment)) { - if (smu7_read_smc_sram_dword(hwmgr->smumgr, + if (smu7_read_smc_sram_dword(hwmgr, SMU71_FIRMWARE_HEADER_LOCATION + offsetof(SMU71_Firmware_Header, PmFuseTable), &pm_fuse_table_offset, SMC_RAM_END)) @@ -317,19 +312,13 @@ static int iceland_populate_pm_fuses(struct pp_hwmgr *hwmgr) "Attempt to populate GnbLPML Failed!", return -EINVAL); - /* DW17 */ - if (iceland_min_max_vgnb_lpml_id_from_bapm_vddc(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate GnbLPML Min and Max Vid Failed!", - return -EINVAL); - /* DW18 */ if (iceland_populate_bapm_vddc_base_leakage_sidd(hwmgr)) PP_ASSERT_WITH_CODE(false, "Attempt to populate BapmVddCBaseLeakage Hi and Lo Sidd Failed!", return -EINVAL); - if (smu7_copy_bytes_to_smc(hwmgr->smumgr, pm_fuse_table_offset, + if (smu7_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset, (uint8_t *)&smu_data->power_tune_table, sizeof(struct SMU71_Discrete_PmFuses), SMC_RAM_END)) PP_ASSERT_WITH_CODE(false, @@ -339,7 +328,7 @@ static int iceland_populate_pm_fuses(struct pp_hwmgr *hwmgr) return 0; } -static int iceland_get_dependecy_volt_by_clk(struct pp_hwmgr *hwmgr, +static int iceland_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr, struct phm_clock_voltage_dependency_table *allowed_clock_voltage_table, uint32_t clock, uint32_t *vol) { @@ -601,7 +590,7 @@ static int iceland_populate_smc_link_level(struct pp_hwmgr *hwmgr, SMU71_Discret { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); struct smu7_dpm_table *dpm_table = &data->dpm_table; - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); uint32_t i; /* Index (dpm_table->pcie_speed_table.count) is reserved for PCIE boot level. */ @@ -749,7 +738,7 @@ static int iceland_populate_single_graphic_level(struct pp_hwmgr *hwmgr, result = iceland_calculate_sclk_params(hwmgr, engine_clock, graphic_level); /* populate graphics levels*/ - result = iceland_get_dependecy_volt_by_clk(hwmgr, + result = iceland_get_dependency_volt_by_clk(hwmgr, hwmgr->dyn_state.vddc_dependency_on_sclk, engine_clock, &graphic_level->MinVddc); PP_ASSERT_WITH_CODE((0 == result), @@ -816,7 +805,7 @@ static int iceland_populate_single_graphic_level(struct pp_hwmgr *hwmgr, int iceland_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); struct smu7_dpm_table *dpm_table = &data->dpm_table; uint32_t level_array_adress = smu_data->smu7_data.dpm_table_start + offsetof(SMU71_Discrete_DpmTable, GraphicsLevel); @@ -892,7 +881,7 @@ int iceland_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) smu_data->smc_state_table.GraphicsLevel[1].pcieDpmLevel = mid_pcie_level_enabled; /* level count will send to smc once at init smc table and never change*/ - result = smu7_copy_bytes_to_smc(hwmgr->smumgr, level_array_adress, + result = smu7_copy_bytes_to_smc(hwmgr, level_array_adress, (uint8_t *)levels, (uint32_t)level_array_size, SMC_RAM_END); @@ -1104,7 +1093,7 @@ static int iceland_populate_single_memory_level( uint32_t mclk_strobe_mode_threshold = 40000; if (hwmgr->dyn_state.vddc_dependency_on_mclk != NULL) { - result = iceland_get_dependecy_volt_by_clk(hwmgr, + result = iceland_get_dependency_volt_by_clk(hwmgr, hwmgr->dyn_state.vddc_dependency_on_mclk, memory_clock, &memory_level->MinVddc); PP_ASSERT_WITH_CODE((0 == result), "can not find MinVddc voltage value from memory VDDC voltage dependency table", return result); @@ -1113,7 +1102,7 @@ static int iceland_populate_single_memory_level( if (data->vddci_control == SMU7_VOLTAGE_CONTROL_NONE) { memory_level->MinVddci = memory_level->MinVddc; } else if (NULL != hwmgr->dyn_state.vddci_dependency_on_mclk) { - result = iceland_get_dependecy_volt_by_clk(hwmgr, + result = iceland_get_dependency_volt_by_clk(hwmgr, hwmgr->dyn_state.vddci_dependency_on_mclk, memory_clock, &memory_level->MinVddci); @@ -1218,7 +1207,7 @@ static int iceland_populate_single_memory_level( int iceland_populate_all_memory_levels(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); struct smu7_dpm_table *dpm_table = &data->dpm_table; int result; @@ -1257,7 +1246,7 @@ int iceland_populate_all_memory_levels(struct pp_hwmgr *hwmgr) smu_data->smc_state_table.MemoryLevel[dpm_table->mclk_table.count-1].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH; /* level count will send to smc once at init smc table and never change*/ - result = smu7_copy_bytes_to_smc(hwmgr->smumgr, + result = smu7_copy_bytes_to_smc(hwmgr, level_array_adress, (uint8_t *)levels, (uint32_t)level_array_size, SMC_RAM_END); @@ -1496,7 +1485,7 @@ static int iceland_populate_memory_timing_parameters( static int iceland_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); int result = 0; SMU71_Discrete_MCArbDramTimingTable arb_regs; uint32_t i, j; @@ -1518,7 +1507,7 @@ static int iceland_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) if (0 == result) { result = smu7_copy_bytes_to_smc( - hwmgr->smumgr, + hwmgr, smu_data->smu7_data.arb_table_start, (uint8_t *)&arb_regs, sizeof(SMU71_Discrete_MCArbDramTimingTable), @@ -1534,7 +1523,7 @@ static int iceland_populate_smc_boot_level(struct pp_hwmgr *hwmgr, { int result = 0; struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); table->GraphicsBootLevel = 0; table->MemoryBootLevel = 0; @@ -1572,10 +1561,10 @@ static int iceland_populate_smc_boot_level(struct pp_hwmgr *hwmgr, return result; } -static int iceland_populate_mc_reg_address(struct pp_smumgr *smumgr, +static int iceland_populate_mc_reg_address(struct pp_hwmgr *hwmgr, SMU71_Discrete_MCRegisters *mc_reg_table) { - const struct iceland_smumgr *smu_data = (struct iceland_smumgr *)smumgr->backend; + const struct iceland_smumgr *smu_data = (struct iceland_smumgr *)hwmgr->smu_backend; uint32_t i, j; @@ -1612,13 +1601,12 @@ static void iceland_convert_mc_registers( } } -static int iceland_convert_mc_reg_table_entry_to_smc( - struct pp_smumgr *smumgr, +static int iceland_convert_mc_reg_table_entry_to_smc(struct pp_hwmgr *hwmgr, const uint32_t memory_clock, SMU71_Discrete_MCRegisterSet *mc_reg_table_data ) { - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(smumgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); uint32_t i = 0; for (i = 0; i < smu_data->mc_reg_table.num_entries; i++) { @@ -1648,7 +1636,7 @@ static int iceland_convert_mc_reg_table_to_smc(struct pp_hwmgr *hwmgr, for (i = 0; i < data->dpm_table.mclk_table.count; i++) { res = iceland_convert_mc_reg_table_entry_to_smc( - hwmgr->smumgr, + hwmgr, data->dpm_table.mclk_table.dpm_levels[i].value, &mc_regs->data[i] ); @@ -1662,8 +1650,7 @@ static int iceland_convert_mc_reg_table_to_smc(struct pp_hwmgr *hwmgr, static int iceland_update_and_upload_mc_reg_table(struct pp_hwmgr *hwmgr) { - struct pp_smumgr *smumgr = hwmgr->smumgr; - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(smumgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); uint32_t address; int32_t result; @@ -1682,7 +1669,7 @@ static int iceland_update_and_upload_mc_reg_table(struct pp_hwmgr *hwmgr) address = smu_data->smu7_data.mc_reg_table_start + (uint32_t)offsetof(SMU71_Discrete_MCRegisters, data[0]); - return smu7_copy_bytes_to_smc(hwmgr->smumgr, address, + return smu7_copy_bytes_to_smc(hwmgr, address, (uint8_t *)&smu_data->mc_regs.data[0], sizeof(SMU71_Discrete_MCRegisterSet) * data->dpm_table.mclk_table.count, SMC_RAM_END); @@ -1691,11 +1678,10 @@ static int iceland_update_and_upload_mc_reg_table(struct pp_hwmgr *hwmgr) static int iceland_populate_initial_mc_reg_table(struct pp_hwmgr *hwmgr) { int result; - struct pp_smumgr *smumgr = hwmgr->smumgr; - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(smumgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); memset(&smu_data->mc_regs, 0x00, sizeof(SMU71_Discrete_MCRegisters)); - result = iceland_populate_mc_reg_address(smumgr, &(smu_data->mc_regs)); + result = iceland_populate_mc_reg_address(hwmgr, &(smu_data->mc_regs)); PP_ASSERT_WITH_CODE(0 == result, "Failed to initialize MCRegTable for the MC register addresses!", return result;); @@ -1703,14 +1689,14 @@ static int iceland_populate_initial_mc_reg_table(struct pp_hwmgr *hwmgr) PP_ASSERT_WITH_CODE(0 == result, "Failed to initialize MCRegTable for driver state!", return result;); - return smu7_copy_bytes_to_smc(smumgr, smu_data->smu7_data.mc_reg_table_start, + return smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.mc_reg_table_start, (uint8_t *)&smu_data->mc_regs, sizeof(SMU71_Discrete_MCRegisters), SMC_RAM_END); } static int iceland_populate_smc_initial_state(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); uint8_t count, level; count = (uint8_t)(hwmgr->dyn_state.vddc_dependency_on_sclk->count); @@ -1739,7 +1725,7 @@ static int iceland_populate_smc_initial_state(struct pp_hwmgr *hwmgr) static int iceland_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); const struct iceland_pt_defaults *defaults = smu_data->power_tune_defaults; SMU71_Discrete_DpmTable *dpm_table = &(smu_data->smc_state_table); struct phm_cac_tdp_table *cac_dtp_table = hwmgr->dyn_state.cac_dtp_table; @@ -1776,7 +1762,7 @@ static int iceland_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) CONVERT_FROM_HOST_TO_SMC_US(dpm_table->PPM_PkgPwrLimit); CONVERT_FROM_HOST_TO_SMC_US(dpm_table->PPM_TemperatureLimit); - dpm_table->BAPM_TEMP_GRADIENT = PP_HOST_TO_SMC_UL(defaults->bamp_temp_gradient); + dpm_table->BAPM_TEMP_GRADIENT = PP_HOST_TO_SMC_UL(defaults->bapm_temp_gradient); def1 = defaults->bapmti_r; def2 = defaults->bapmti_rc; @@ -1827,7 +1813,7 @@ int iceland_init_smc_table(struct pp_hwmgr *hwmgr) { int result; struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); SMU71_Discrete_DpmTable *table = &(smu_data->smc_state_table); @@ -1955,7 +1941,7 @@ int iceland_init_smc_table(struct pp_hwmgr *hwmgr) table->BootMVdd = PP_HOST_TO_SMC_US(table->BootMVdd * VOLTAGE_SCALE); /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */ - result = smu7_copy_bytes_to_smc(hwmgr->smumgr, smu_data->smu7_data.dpm_table_start + + result = smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.dpm_table_start + offsetof(SMU71_Discrete_DpmTable, SystemFlags), (uint8_t *)&(table->SystemFlags), sizeof(SMU71_Discrete_DpmTable)-3 * sizeof(SMU71_PIDController), @@ -1965,7 +1951,7 @@ int iceland_init_smc_table(struct pp_hwmgr *hwmgr) "Failed to upload dpm data to SMC memory!", return result;); /* Upload all ulv setting to SMC memory.(dpm level, dpm level count etc) */ - result = smu7_copy_bytes_to_smc(hwmgr->smumgr, + result = smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.ulv_setting_starts, (uint8_t *)&(smu_data->ulv_setting), sizeof(SMU71_Discrete_Ulv), @@ -1994,7 +1980,7 @@ int iceland_init_smc_table(struct pp_hwmgr *hwmgr) */ int iceland_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) { - struct smu7_smumgr *smu7_data = (struct smu7_smumgr *)(hwmgr->smumgr->backend); + struct smu7_smumgr *smu7_data = (struct smu7_smumgr *)(hwmgr->smu_backend); SMU71_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE }; uint32_t duty100; uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2; @@ -2064,7 +2050,7 @@ int iceland_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) /* fan_table.FanControl_GL_Flag = 1; */ - res = smu7_copy_bytes_to_smc(hwmgr->smumgr, smu7_data->fan_table_start, (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table), SMC_RAM_END); + res = smu7_copy_bytes_to_smc(hwmgr, smu7_data->fan_table_start, (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table), SMC_RAM_END); return 0; } @@ -2084,7 +2070,7 @@ static int iceland_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) int iceland_update_sclk_threshold(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); int result = 0; uint32_t low_sclk_interrupt_threshold = 0; @@ -2101,7 +2087,7 @@ int iceland_update_sclk_threshold(struct pp_hwmgr *hwmgr) CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold); result = smu7_copy_bytes_to_smc( - hwmgr->smumgr, + hwmgr, smu_data->smu7_data.dpm_table_start + offsetof(SMU71_Discrete_DpmTable, LowSclkInterruptThreshold), @@ -2182,13 +2168,13 @@ uint32_t iceland_get_mac_definition(uint32_t value) int iceland_process_firmware_header(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct smu7_smumgr *smu7_data = (struct smu7_smumgr *)(hwmgr->smumgr->backend); + struct smu7_smumgr *smu7_data = (struct smu7_smumgr *)(hwmgr->smu_backend); uint32_t tmp; int result; bool error = false; - result = smu7_read_smc_sram_dword(hwmgr->smumgr, + result = smu7_read_smc_sram_dword(hwmgr, SMU71_FIRMWARE_HEADER_LOCATION + offsetof(SMU71_Firmware_Header, DpmTable), &tmp, SMC_RAM_END); @@ -2199,7 +2185,7 @@ int iceland_process_firmware_header(struct pp_hwmgr *hwmgr) error |= (0 != result); - result = smu7_read_smc_sram_dword(hwmgr->smumgr, + result = smu7_read_smc_sram_dword(hwmgr, SMU71_FIRMWARE_HEADER_LOCATION + offsetof(SMU71_Firmware_Header, SoftRegisters), &tmp, SMC_RAM_END); @@ -2212,7 +2198,7 @@ int iceland_process_firmware_header(struct pp_hwmgr *hwmgr) error |= (0 != result); - result = smu7_read_smc_sram_dword(hwmgr->smumgr, + result = smu7_read_smc_sram_dword(hwmgr, SMU71_FIRMWARE_HEADER_LOCATION + offsetof(SMU71_Firmware_Header, mcRegisterTable), &tmp, SMC_RAM_END); @@ -2221,7 +2207,7 @@ int iceland_process_firmware_header(struct pp_hwmgr *hwmgr) smu7_data->mc_reg_table_start = tmp; } - result = smu7_read_smc_sram_dword(hwmgr->smumgr, + result = smu7_read_smc_sram_dword(hwmgr, SMU71_FIRMWARE_HEADER_LOCATION + offsetof(SMU71_Firmware_Header, FanTable), &tmp, SMC_RAM_END); @@ -2232,7 +2218,7 @@ int iceland_process_firmware_header(struct pp_hwmgr *hwmgr) error |= (0 != result); - result = smu7_read_smc_sram_dword(hwmgr->smumgr, + result = smu7_read_smc_sram_dword(hwmgr, SMU71_FIRMWARE_HEADER_LOCATION + offsetof(SMU71_Firmware_Header, mcArbDramTimingTable), &tmp, SMC_RAM_END); @@ -2244,7 +2230,7 @@ int iceland_process_firmware_header(struct pp_hwmgr *hwmgr) error |= (0 != result); - result = smu7_read_smc_sram_dword(hwmgr->smumgr, + result = smu7_read_smc_sram_dword(hwmgr, SMU71_FIRMWARE_HEADER_LOCATION + offsetof(SMU71_Firmware_Header, Version), &tmp, SMC_RAM_END); @@ -2255,7 +2241,7 @@ int iceland_process_firmware_header(struct pp_hwmgr *hwmgr) error |= (0 != result); - result = smu7_read_smc_sram_dword(hwmgr->smumgr, + result = smu7_read_smc_sram_dword(hwmgr, SMU71_FIRMWARE_HEADER_LOCATION + offsetof(SMU71_Firmware_Header, UlvSettings), &tmp, SMC_RAM_END); @@ -2522,7 +2508,7 @@ static int iceland_set_valid_flag(struct iceland_mc_reg_table *table) int iceland_initialize_mc_reg_table(struct pp_hwmgr *hwmgr) { int result; - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); pp_atomctrl_mc_reg_table *table; struct iceland_mc_reg_table *ni_table = &smu_data->mc_reg_table; uint8_t module_index = iceland_get_memory_modile_index(hwmgr); diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.c index 0bf2def..78aa112 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.c @@ -39,55 +39,55 @@ #define ICELAND_SMC_SIZE 0x20000 -static int iceland_start_smc(struct pp_smumgr *smumgr) +static int iceland_start_smc(struct pp_hwmgr *hwmgr) { - SMUM_WRITE_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_RESET_CNTL, rst_reg, 0); return 0; } -static void iceland_reset_smc(struct pp_smumgr *smumgr) +static void iceland_reset_smc(struct pp_hwmgr *hwmgr) { - SMUM_WRITE_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_RESET_CNTL, rst_reg, 1); } -static void iceland_stop_smc_clock(struct pp_smumgr *smumgr) +static void iceland_stop_smc_clock(struct pp_hwmgr *hwmgr) { - SMUM_WRITE_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 1); } -static void iceland_start_smc_clock(struct pp_smumgr *smumgr) +static void iceland_start_smc_clock(struct pp_hwmgr *hwmgr) { - SMUM_WRITE_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); } -static int iceland_smu_start_smc(struct pp_smumgr *smumgr) +static int iceland_smu_start_smc(struct pp_hwmgr *hwmgr) { /* set smc instruct start point at 0x0 */ - smu7_program_jump_on_start(smumgr); + smu7_program_jump_on_start(hwmgr); /* enable smc clock */ - iceland_start_smc_clock(smumgr); + iceland_start_smc_clock(hwmgr); /* de-assert reset */ - iceland_start_smc(smumgr); + iceland_start_smc(hwmgr); - SMUM_WAIT_INDIRECT_FIELD(smumgr, SMC_IND, FIRMWARE_FLAGS, + PHM_WAIT_INDIRECT_FIELD(hwmgr, SMC_IND, FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1); return 0; } -static int iceland_upload_smc_firmware_data(struct pp_smumgr *smumgr, +static int iceland_upload_smc_firmware_data(struct pp_hwmgr *hwmgr, uint32_t length, const uint8_t *src, uint32_t limit, uint32_t start_addr) { @@ -96,17 +96,17 @@ static int iceland_upload_smc_firmware_data(struct pp_smumgr *smumgr, PP_ASSERT_WITH_CODE((limit >= byte_count), "SMC address is beyond the SMC RAM area.", return -EINVAL); - cgs_write_register(smumgr->device, mmSMC_IND_INDEX_0, start_addr); - SMUM_WRITE_FIELD(smumgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 1); + cgs_write_register(hwmgr->device, mmSMC_IND_INDEX_0, start_addr); + PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 1); while (byte_count >= 4) { data = src[0] * 0x1000000 + src[1] * 0x10000 + src[2] * 0x100 + src[3]; - cgs_write_register(smumgr->device, mmSMC_IND_DATA_0, data); + cgs_write_register(hwmgr->device, mmSMC_IND_DATA_0, data); src += 4; byte_count -= 4; } - SMUM_WRITE_FIELD(smumgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 0); + PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 0); PP_ASSERT_WITH_CODE((0 == byte_count), "SMC size must be dividable by 4.", return -EINVAL); @@ -114,16 +114,16 @@ static int iceland_upload_smc_firmware_data(struct pp_smumgr *smumgr, } -static int iceland_smu_upload_firmware_image(struct pp_smumgr *smumgr) +static int iceland_smu_upload_firmware_image(struct pp_hwmgr *hwmgr) { uint32_t val; struct cgs_firmware_info info = {0}; - if (smumgr == NULL || smumgr->device == NULL) + if (hwmgr == NULL || hwmgr->device == NULL) return -EINVAL; /* load SMC firmware */ - cgs_get_firmware_info(smumgr->device, + cgs_get_firmware_info(hwmgr->device, smu7_convert_fw_type_to_cgs(UCODE_ID_SMU), &info); if (info.image_size & 3) { @@ -137,56 +137,56 @@ static int iceland_smu_upload_firmware_image(struct pp_smumgr *smumgr) } /* wait for smc boot up */ - SMUM_WAIT_INDIRECT_FIELD_UNEQUAL(smumgr, SMC_IND, + PHM_WAIT_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND, RCU_UC_EVENTS, boot_seq_done, 0); /* clear firmware interrupt enable flag */ - val = cgs_read_ind_register(smumgr->device, CGS_IND_REG__SMC, + val = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMC_SYSCON_MISC_CNTL); - cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC, + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMC_SYSCON_MISC_CNTL, val | 1); /* stop smc clock */ - iceland_stop_smc_clock(smumgr); + iceland_stop_smc_clock(hwmgr); /* reset smc */ - iceland_reset_smc(smumgr); - iceland_upload_smc_firmware_data(smumgr, info.image_size, + iceland_reset_smc(hwmgr); + iceland_upload_smc_firmware_data(hwmgr, info.image_size, (uint8_t *)info.kptr, ICELAND_SMC_SIZE, info.ucode_start_address); return 0; } -static int iceland_request_smu_load_specific_fw(struct pp_smumgr *smumgr, +static int iceland_request_smu_load_specific_fw(struct pp_hwmgr *hwmgr, uint32_t firmwareType) { return 0; } -static int iceland_start_smu(struct pp_smumgr *smumgr) +static int iceland_start_smu(struct pp_hwmgr *hwmgr) { int result; - result = iceland_smu_upload_firmware_image(smumgr); + result = iceland_smu_upload_firmware_image(hwmgr); if (result) return result; - result = iceland_smu_start_smc(smumgr); + result = iceland_smu_start_smc(hwmgr); if (result) return result; - if (!smu7_is_smc_ram_running(smumgr)) { + if (!smu7_is_smc_ram_running(hwmgr)) { pr_info("smu not running, upload firmware again \n"); - result = iceland_smu_upload_firmware_image(smumgr); + result = iceland_smu_upload_firmware_image(hwmgr); if (result) return result; - result = iceland_smu_start_smc(smumgr); + result = iceland_smu_start_smc(hwmgr); if (result) return result; } - result = smu7_request_smu_load_fw(smumgr); + result = smu7_request_smu_load_fw(hwmgr); return result; } @@ -198,7 +198,7 @@ static int iceland_start_smu(struct pp_smumgr *smumgr) * @param smcAddress the address in the SMC RAM to access. * @param value to write to the SMC SRAM. */ -static int iceland_smu_init(struct pp_smumgr *smumgr) +static int iceland_smu_init(struct pp_hwmgr *hwmgr) { int i; struct iceland_smumgr *iceland_priv = NULL; @@ -208,9 +208,9 @@ static int iceland_smu_init(struct pp_smumgr *smumgr) if (iceland_priv == NULL) return -ENOMEM; - smumgr->backend = iceland_priv; + hwmgr->smu_backend = iceland_priv; - if (smu7_init(smumgr)) + if (smu7_init(hwmgr)) return -EINVAL; for (i = 0; i < SMU71_MAX_LEVELS_GRAPHICS; i++) diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.h index 8eae01b..8024725 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.h +++ b/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.h @@ -39,7 +39,7 @@ struct iceland_pt_defaults { uint8_t tdc_waterfall_ctl; uint8_t dte_ambient_temp_base; uint32_t display_cac; - uint32_t bamp_temp_gradient; + uint32_t bapm_temp_gradient; uint16_t bapmti_r[SMU71_DTE_ITERATIONS * SMU71_DTE_SOURCES * SMU71_DTE_SINKS]; uint16_t bapmti_rc[SMU71_DTE_ITERATIONS * SMU71_DTE_SOURCES * SMU71_DTE_SINKS]; }; diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.c b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.c index 99a00bd..c92ea38 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.c @@ -148,7 +148,7 @@ static uint16_t scale_fan_gain_settings(uint16_t raw_setting) static int polaris10_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) { - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); const struct polaris10_pt_defaults *defaults = smu_data->power_tune_defaults; SMU74_Discrete_DpmTable *table = &(smu_data->smc_state_table); @@ -196,7 +196,7 @@ static int polaris10_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmg static int polaris10_populate_svi_load_line(struct pp_hwmgr *hwmgr) { - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); const struct polaris10_pt_defaults *defaults = smu_data->power_tune_defaults; smu_data->power_tune_table.SviLoadLineEn = defaults->SviLoadLineEn; @@ -210,7 +210,7 @@ static int polaris10_populate_svi_load_line(struct pp_hwmgr *hwmgr) static int polaris10_populate_tdc_limit(struct pp_hwmgr *hwmgr) { uint16_t tdc_limit; - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); const struct polaris10_pt_defaults *defaults = smu_data->power_tune_defaults; @@ -227,11 +227,11 @@ static int polaris10_populate_tdc_limit(struct pp_hwmgr *hwmgr) static int polaris10_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) { - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); const struct polaris10_pt_defaults *defaults = smu_data->power_tune_defaults; uint32_t temp; - if (smu7_read_smc_sram_dword(hwmgr->smumgr, + if (smu7_read_smc_sram_dword(hwmgr, fuse_table_offset + offsetof(SMU74_Discrete_PmFuses, TdcWaterfallCtl), (uint32_t *)&temp, SMC_RAM_END)) @@ -252,7 +252,7 @@ static int polaris10_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_of static int polaris10_populate_temperature_scaler(struct pp_hwmgr *hwmgr) { int i; - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); /* Currently not used. Set all to zero. */ for (i = 0; i < 16; i++) @@ -263,7 +263,7 @@ static int polaris10_populate_temperature_scaler(struct pp_hwmgr *hwmgr) static int polaris10_populate_fuzzy_fan(struct pp_hwmgr *hwmgr) { - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); /* TO DO move to hwmgr */ if ((hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity & (1 << 15)) @@ -279,7 +279,7 @@ static int polaris10_populate_fuzzy_fan(struct pp_hwmgr *hwmgr) static int polaris10_populate_gnb_lpml(struct pp_hwmgr *hwmgr) { int i; - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); /* Currently not used. Set all to zero. */ for (i = 0; i < 16; i++) @@ -288,14 +288,9 @@ static int polaris10_populate_gnb_lpml(struct pp_hwmgr *hwmgr) return 0; } -static int polaris10_min_max_vgnb_lpml_id_from_bapm_vddc(struct pp_hwmgr *hwmgr) -{ - return 0; -} - static int polaris10_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) { - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); uint16_t hi_sidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd; @@ -315,12 +310,12 @@ static int polaris10_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr static int polaris10_populate_pm_fuses(struct pp_hwmgr *hwmgr) { - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); uint32_t pm_fuse_table_offset; if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PowerContainment)) { - if (smu7_read_smc_sram_dword(hwmgr->smumgr, + if (smu7_read_smc_sram_dword(hwmgr, SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, PmFuseTable), &pm_fuse_table_offset, SMC_RAM_END)) @@ -358,17 +353,12 @@ static int polaris10_populate_pm_fuses(struct pp_hwmgr *hwmgr) "Attempt to populate GnbLPML Failed!", return -EINVAL); - if (polaris10_min_max_vgnb_lpml_id_from_bapm_vddc(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate GnbLPML Min and Max Vid Failed!", - return -EINVAL); - if (polaris10_populate_bapm_vddc_base_leakage_sidd(hwmgr)) PP_ASSERT_WITH_CODE(false, "Attempt to populate BapmVddCBaseLeakage Hi and Lo " "Sidd Failed!", return -EINVAL); - if (smu7_copy_bytes_to_smc(hwmgr->smumgr, pm_fuse_table_offset, + if (smu7_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset, (uint8_t *)&smu_data->power_tune_table, (sizeof(struct SMU74_Discrete_PmFuses) - 92), SMC_RAM_END)) PP_ASSERT_WITH_CODE(false, @@ -494,7 +484,6 @@ static int polaris10_populate_ulv_level(struct pp_hwmgr *hwmgr, struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct pp_smumgr *smumgr = hwmgr->smumgr; state->CcPwrDynRm = 0; state->CcPwrDynRm1 = 0; @@ -503,7 +492,7 @@ static int polaris10_populate_ulv_level(struct pp_hwmgr *hwmgr, state->VddcOffsetVid = (uint8_t)(table_info->us_ulv_voltage_offset * VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1); - if (smumgr->chip_id == CHIP_POLARIS12 || smumgr->is_kicker) + if (hwmgr->chip_id == CHIP_POLARIS12 || hwmgr->is_kicker) state->VddcPhase = data->vddc_phase_shed_control ^ 0x3; else state->VddcPhase = (data->vddc_phase_shed_control) ? 0 : 1; @@ -525,7 +514,7 @@ static int polaris10_populate_smc_link_level(struct pp_hwmgr *hwmgr, struct SMU74_Discrete_DpmTable *table) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); struct smu7_dpm_table *dpm_table = &data->dpm_table; int i; @@ -556,8 +545,7 @@ static int polaris10_populate_smc_link_level(struct pp_hwmgr *hwmgr, static void polaris10_get_sclk_range_table(struct pp_hwmgr *hwmgr, SMU74_Discrete_DpmTable *table) { - struct pp_smumgr *smumgr = hwmgr->smumgr; - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); uint32_t i, ref_clk; struct pp_atom_ctrl_sclk_range_table range_table_from_vbios = { { {0} } }; @@ -607,8 +595,7 @@ static void polaris10_get_sclk_range_table(struct pp_hwmgr *hwmgr, static int polaris10_calculate_sclk_params(struct pp_hwmgr *hwmgr, uint32_t clock, SMU_SclkSetting *sclk_setting) { - struct pp_smumgr *smumgr = hwmgr->smumgr; - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); const SMU74_Discrete_DpmTable *table = &(smu_data->smc_state_table); struct pp_atomctrl_clock_dividers_ai dividers; uint32_t ref_clock; @@ -751,9 +738,8 @@ static int polaris10_populate_single_graphic_level(struct pp_hwmgr *hwmgr, */ int polaris10_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) { - struct pp_smumgr *smumgr = hwmgr->smumgr; struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); struct smu7_dpm_table *dpm_table = &hw_data->dpm_table; struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); @@ -838,7 +824,7 @@ int polaris10_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) levels[1].pcieDpmLevel = mid_pcie_level_enabled; } /* level count will send to smc once at init smc table and never change */ - result = smu7_copy_bytes_to_smc(smumgr, array, (uint8_t *)levels, + result = smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, (uint32_t)array_size, SMC_RAM_END); return result; @@ -880,7 +866,7 @@ static int polaris10_populate_single_memory_level(struct pp_hwmgr *hwmgr, if (mclk_stutter_mode_threshold && (clock <= mclk_stutter_mode_threshold) && - (SMUM_READ_FIELD(hwmgr->device, DPG_PIPE_STUTTER_CONTROL, + (PHM_READ_FIELD(hwmgr->device, DPG_PIPE_STUTTER_CONTROL, STUTTER_ENABLE) & 0x1)) mem_level->StutterEnable = true; @@ -900,9 +886,8 @@ static int polaris10_populate_single_memory_level(struct pp_hwmgr *hwmgr, */ int polaris10_populate_all_memory_levels(struct pp_hwmgr *hwmgr) { - struct pp_smumgr *smumgr = hwmgr->smumgr; struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); struct smu7_dpm_table *dpm_table = &hw_data->dpm_table; int result; /* populate MCLK dpm table to SMU7 */ @@ -943,7 +928,7 @@ int polaris10_populate_all_memory_levels(struct pp_hwmgr *hwmgr) phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table); /* level count will send to smc once at init smc table and never change */ - result = smu7_copy_bytes_to_smc(hwmgr->smumgr, array, (uint8_t *)levels, + result = smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, (uint32_t)array_size, SMC_RAM_END); return result; @@ -1201,9 +1186,8 @@ static int polaris10_populate_memory_timing_parameters(struct pp_hwmgr *hwmgr, static int polaris10_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) { - struct pp_smumgr *smumgr = hwmgr->smumgr; struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); struct SMU74_Discrete_MCArbDramTimingTable arb_regs; uint32_t i, j; int result = 0; @@ -1222,7 +1206,7 @@ static int polaris10_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) } result = smu7_copy_bytes_to_smc( - hwmgr->smumgr, + hwmgr, smu_data->smu7_data.arb_table_start, (uint8_t *)&arb_regs, sizeof(SMU74_Discrete_MCArbDramTimingTable), @@ -1321,9 +1305,8 @@ static int polaris10_populate_smc_boot_level(struct pp_hwmgr *hwmgr, static int polaris10_populate_smc_initailial_state(struct pp_hwmgr *hwmgr) { - struct pp_smumgr *smumgr = hwmgr->smumgr; struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); uint8_t count, level; @@ -1354,8 +1337,7 @@ static int polaris10_populate_smc_initailial_state(struct pp_hwmgr *hwmgr) static int polaris10_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr) { uint32_t ro, efuse, volt_without_cks, volt_with_cks, value, max, min; - struct pp_smumgr *smumgr = hwmgr->smumgr; - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); uint8_t i, stretch_amount, stretch_amount2, volt_offset = 0; struct phm_ppt_v1_information *table_info = @@ -1438,7 +1420,7 @@ static int polaris10_populate_vr_config(struct pp_hwmgr *hwmgr, struct SMU74_Discrete_DpmTable *table) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); uint16_t config; config = VR_MERGED_WITH_VDDC; @@ -1482,8 +1464,7 @@ static int polaris10_populate_vr_config(struct pp_hwmgr *hwmgr, static int polaris10_populate_avfs_parameters(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct pp_smumgr *smumgr = hwmgr->smumgr; - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); SMU74_Discrete_DpmTable *table = &(smu_data->smc_state_table); int result = 0; @@ -1534,20 +1515,20 @@ static int polaris10_populate_avfs_parameters(struct pp_hwmgr *hwmgr) AVFS_SclkOffset.Sclk_Offset[i] = PP_HOST_TO_SMC_US((uint16_t)(sclk_table->entries[i].sclk_offset) / 100); } - result = smu7_read_smc_sram_dword(smumgr, + result = smu7_read_smc_sram_dword(hwmgr, SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, AvfsMeanNSigma), &tmp, SMC_RAM_END); - smu7_copy_bytes_to_smc(smumgr, + smu7_copy_bytes_to_smc(hwmgr, tmp, (uint8_t *)&AVFS_meanNsigma, sizeof(AVFS_meanNsigma_t), SMC_RAM_END); - result = smu7_read_smc_sram_dword(smumgr, + result = smu7_read_smc_sram_dword(hwmgr, SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, AvfsSclkOffsetTable), &tmp, SMC_RAM_END); - smu7_copy_bytes_to_smc(smumgr, + smu7_copy_bytes_to_smc(hwmgr, tmp, (uint8_t *)&AVFS_SclkOffset, sizeof(AVFS_Sclk_Offset_t), @@ -1569,9 +1550,9 @@ static int polaris10_populate_avfs_parameters(struct pp_hwmgr *hwmgr) * @param hwmgr the address of the powerplay hardware manager. * @return always 0 */ -static int polaris10_init_arb_table_index(struct pp_smumgr *smumgr) +static int polaris10_init_arb_table_index(struct pp_hwmgr *hwmgr) { - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); uint32_t tmp; int result; @@ -1583,7 +1564,7 @@ static int polaris10_init_arb_table_index(struct pp_smumgr *smumgr) * In reality this field should not be in that structure * but in a soft register. */ - result = smu7_read_smc_sram_dword(smumgr, + result = smu7_read_smc_sram_dword(hwmgr, smu_data->smu7_data.arb_table_start, &tmp, SMC_RAM_END); if (result) @@ -1592,13 +1573,13 @@ static int polaris10_init_arb_table_index(struct pp_smumgr *smumgr) tmp &= 0x00FFFFFF; tmp |= ((uint32_t)MC_CG_ARB_FREQ_F1) << 24; - return smu7_write_smc_sram_dword(smumgr, + return smu7_write_smc_sram_dword(hwmgr, smu_data->smu7_data.arb_table_start, tmp, SMC_RAM_END); } static void polaris10_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) { - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); @@ -1615,7 +1596,7 @@ static void polaris10_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) static void polaris10_save_default_power_profile(struct pp_hwmgr *hwmgr) { - struct polaris10_smumgr *data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend); + struct polaris10_smumgr *data = (struct polaris10_smumgr *)(hwmgr->smu_backend); struct SMU74_Discrete_GraphicsLevel *levels = data->smc_state_table.GraphicsLevel; unsigned min_level = 1; @@ -1658,9 +1639,9 @@ static void polaris10_save_default_power_profile(struct pp_hwmgr *hwmgr) int polaris10_init_smc_table(struct pp_hwmgr *hwmgr) { int result; - struct pp_smumgr *smumgr = hwmgr->smumgr; struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); struct SMU74_Discrete_DpmTable *table = &(smu_data->smc_state_table); @@ -1852,7 +1833,7 @@ int polaris10_init_smc_table(struct pp_hwmgr *hwmgr) CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime); /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */ - result = smu7_copy_bytes_to_smc(hwmgr->smumgr, + result = smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.dpm_table_start + offsetof(SMU74_Discrete_DpmTable, SystemFlags), (uint8_t *)&(table->SystemFlags), @@ -1861,7 +1842,7 @@ int polaris10_init_smc_table(struct pp_hwmgr *hwmgr) PP_ASSERT_WITH_CODE(0 == result, "Failed to upload dpm data to SMC memory!", return result); - result = polaris10_init_arb_table_index(hwmgr->smumgr); + result = polaris10_init_arb_table_index(hwmgr); PP_ASSERT_WITH_CODE(0 == result, "Failed to upload arb data to SMC memory!", return result); @@ -1888,17 +1869,16 @@ static int polaris10_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) int polaris10_thermal_avfs_enable(struct pp_hwmgr *hwmgr) { int ret; - struct pp_smumgr *smumgr = (struct pp_smumgr *)(hwmgr->smumgr); - struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(smumgr->backend); + struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); if (smu_data->avfs.avfs_btc_status == AVFS_BTC_NOTSUPPORTED) return 0; - ret = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + ret = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetGBDroopSettings, data->avfs_vdroop_override_setting); - ret = (smum_send_msg_to_smc(smumgr, PPSMC_MSG_EnableAvfs) == 0) ? + ret = (smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableAvfs) == 0) ? 0 : -1; if (!ret) @@ -1919,7 +1899,7 @@ int polaris10_thermal_avfs_enable(struct pp_hwmgr *hwmgr) */ int polaris10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) { - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); SMU74_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE }; uint32_t duty100; uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2; @@ -2000,20 +1980,20 @@ int polaris10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) hwmgr->device, CGS_IND_REG__SMC, CG_MULT_THERMAL_CTRL, TEMP_SEL); - res = smu7_copy_bytes_to_smc(hwmgr->smumgr, smu_data->smu7_data.fan_table_start, + res = smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.fan_table_start, (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table), SMC_RAM_END); if (!res && hwmgr->thermal_controller. advanceFanControlParameters.ucMinimumPWMLimit) - res = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + res = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetFanMinPwm, hwmgr->thermal_controller. advanceFanControlParameters.ucMinimumPWMLimit); if (!res && hwmgr->thermal_controller. advanceFanControlParameters.ulMinFanSCLKAcousticLimit) - res = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + res = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetFanSclkTarget, hwmgr->thermal_controller. advanceFanControlParameters.ulMinFanSCLKAcousticLimit); @@ -2027,7 +2007,7 @@ int polaris10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) static int polaris10_update_uvd_smc_table(struct pp_hwmgr *hwmgr) { - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); uint32_t mm_boot_level_offset, mm_boot_level_value; struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); @@ -2051,7 +2031,7 @@ static int polaris10_update_uvd_smc_table(struct pp_hwmgr *hwmgr) PHM_PlatformCaps_UVDDPM) || phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_UVDDPM_SetEnabledMask, (uint32_t)(1 << smu_data->smc_state_table.UvdBootLevel)); return 0; @@ -2059,7 +2039,7 @@ static int polaris10_update_uvd_smc_table(struct pp_hwmgr *hwmgr) static int polaris10_update_vce_smc_table(struct pp_hwmgr *hwmgr) { - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); uint32_t mm_boot_level_offset, mm_boot_level_value; struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); @@ -2083,7 +2063,7 @@ static int polaris10_update_vce_smc_table(struct pp_hwmgr *hwmgr) CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_VCEDPM_SetEnabledMask, (uint32_t)1 << smu_data->smc_state_table.VceBootLevel); return 0; @@ -2091,7 +2071,7 @@ static int polaris10_update_vce_smc_table(struct pp_hwmgr *hwmgr) static int polaris10_update_samu_smc_table(struct pp_hwmgr *hwmgr) { - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); uint32_t mm_boot_level_offset, mm_boot_level_value; @@ -2110,7 +2090,7 @@ static int polaris10_update_samu_smc_table(struct pp_hwmgr *hwmgr) if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SAMUDPM_SetEnabledMask, (uint32_t)(1 << smu_data->smc_state_table.SamuBootLevel)); return 0; @@ -2119,7 +2099,7 @@ static int polaris10_update_samu_smc_table(struct pp_hwmgr *hwmgr) static int polaris10_update_bif_smc_table(struct pp_hwmgr *hwmgr) { - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); struct phm_ppt_v1_pcie_table *pcie_table = table_info->pcie_table; @@ -2157,7 +2137,7 @@ int polaris10_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type) int polaris10_update_sclk_threshold(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); int result = 0; uint32_t low_sclk_interrupt_threshold = 0; @@ -2174,7 +2154,7 @@ int polaris10_update_sclk_threshold(struct pp_hwmgr *hwmgr) CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold); result = smu7_copy_bytes_to_smc( - hwmgr->smumgr, + hwmgr, smu_data->smu7_data.dpm_table_start + offsetof(SMU74_Discrete_DpmTable, LowSclkInterruptThreshold), @@ -2262,13 +2242,13 @@ uint32_t polaris10_get_mac_definition(uint32_t value) */ int polaris10_process_firmware_header(struct pp_hwmgr *hwmgr) { - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); uint32_t tmp; int result; bool error = false; - result = smu7_read_smc_sram_dword(hwmgr->smumgr, + result = smu7_read_smc_sram_dword(hwmgr, SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, DpmTable), &tmp, SMC_RAM_END); @@ -2278,7 +2258,7 @@ int polaris10_process_firmware_header(struct pp_hwmgr *hwmgr) error |= (0 != result); - result = smu7_read_smc_sram_dword(hwmgr->smumgr, + result = smu7_read_smc_sram_dword(hwmgr, SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, SoftRegisters), &tmp, SMC_RAM_END); @@ -2290,7 +2270,7 @@ int polaris10_process_firmware_header(struct pp_hwmgr *hwmgr) error |= (0 != result); - result = smu7_read_smc_sram_dword(hwmgr->smumgr, + result = smu7_read_smc_sram_dword(hwmgr, SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, mcRegisterTable), &tmp, SMC_RAM_END); @@ -2298,7 +2278,7 @@ int polaris10_process_firmware_header(struct pp_hwmgr *hwmgr) if (!result) smu_data->smu7_data.mc_reg_table_start = tmp; - result = smu7_read_smc_sram_dword(hwmgr->smumgr, + result = smu7_read_smc_sram_dword(hwmgr, SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, FanTable), &tmp, SMC_RAM_END); @@ -2308,7 +2288,7 @@ int polaris10_process_firmware_header(struct pp_hwmgr *hwmgr) error |= (0 != result); - result = smu7_read_smc_sram_dword(hwmgr->smumgr, + result = smu7_read_smc_sram_dword(hwmgr, SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, mcArbDramTimingTable), &tmp, SMC_RAM_END); @@ -2318,7 +2298,7 @@ int polaris10_process_firmware_header(struct pp_hwmgr *hwmgr) error |= (0 != result); - result = smu7_read_smc_sram_dword(hwmgr->smumgr, + result = smu7_read_smc_sram_dword(hwmgr, SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, Version), &tmp, SMC_RAM_END); @@ -2342,7 +2322,7 @@ int polaris10_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr, struct amd_pp_profile *request) { struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *) - (hwmgr->smumgr->backend); + (hwmgr->smu_backend); struct SMU74_Discrete_GraphicsLevel *levels = smu_data->smc_state_table.GraphicsLevel; uint32_t array = smu_data->smu7_data.dpm_table_start + @@ -2359,6 +2339,6 @@ int polaris10_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr, levels[i].DownHyst = request->down_hyst; } - return smu7_copy_bytes_to_smc(hwmgr->smumgr, array, (uint8_t *)levels, + return smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, array_size, SMC_RAM_END); } diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c index 75f43da..22b8ecb 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c @@ -60,21 +60,21 @@ static const SMU74_Discrete_GraphicsLevel avfs_graphics_level_polaris10[8] = { static const SMU74_Discrete_MemoryLevel avfs_memory_level_polaris10 = { 0x100ea446, 0, 0x30750000, 0x01, 0x01, 0x01, 0x00, 0x00, 0x64, 0x00, 0x00, 0x1f00, 0x00, 0x00}; -static int polaris10_setup_pwr_virus(struct pp_smumgr *smumgr) +static int polaris10_setup_pwr_virus(struct pp_hwmgr *hwmgr) { int i; int result = -EINVAL; uint32_t reg, data; const PWR_Command_Table *pvirus = pwr_virus_table; - struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(smumgr->backend); + struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); for (i = 0; i < PWR_VIRUS_TABLE_SIZE; i++) { switch (pvirus->command) { case PwrCmdWrite: reg = pvirus->reg; data = pvirus->data; - cgs_write_register(smumgr->device, reg, data); + cgs_write_register(hwmgr->device, reg, data); break; case PwrCmdEnd: @@ -93,13 +93,13 @@ static int polaris10_setup_pwr_virus(struct pp_smumgr *smumgr) return result; } -static int polaris10_perform_btc(struct pp_smumgr *smumgr) +static int polaris10_perform_btc(struct pp_hwmgr *hwmgr) { int result = 0; - struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(smumgr->backend); + struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); if (0 != smu_data->avfs.avfs_btc_param) { - if (0 != smu7_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_PerformBtc, smu_data->avfs.avfs_btc_param)) { + if (0 != smu7_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_PerformBtc, smu_data->avfs.avfs_btc_param)) { pr_info("[AVFS][SmuPolaris10_PerformBtc] PerformBTC SMU msg failed"); result = -1; } @@ -107,16 +107,16 @@ static int polaris10_perform_btc(struct pp_smumgr *smumgr) if (smu_data->avfs.avfs_btc_param > 1) { /* Soft-Reset to reset the engine before loading uCode */ /* halt */ - cgs_write_register(smumgr->device, mmCP_MEC_CNTL, 0x50000000); + cgs_write_register(hwmgr->device, mmCP_MEC_CNTL, 0x50000000); /* reset everything */ - cgs_write_register(smumgr->device, mmGRBM_SOFT_RESET, 0xffffffff); - cgs_write_register(smumgr->device, mmGRBM_SOFT_RESET, 0); + cgs_write_register(hwmgr->device, mmGRBM_SOFT_RESET, 0xffffffff); + cgs_write_register(hwmgr->device, mmGRBM_SOFT_RESET, 0); } return result; } -static int polaris10_setup_graphics_level_structure(struct pp_smumgr *smumgr) +static int polaris10_setup_graphics_level_structure(struct pp_hwmgr *hwmgr) { uint32_t vr_config; uint32_t dpm_table_start; @@ -127,7 +127,7 @@ static int polaris10_setup_graphics_level_structure(struct pp_smumgr *smumgr) graphics_level_size = sizeof(avfs_graphics_level_polaris10); u16_boot_mvdd = PP_HOST_TO_SMC_US(1300 * VOLTAGE_SCALE); - PP_ASSERT_WITH_CODE(0 == smu7_read_smc_sram_dword(smumgr, + PP_ASSERT_WITH_CODE(0 == smu7_read_smc_sram_dword(hwmgr, SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, DpmTable), &dpm_table_start, 0x40000), "[AVFS][Polaris10_SetupGfxLvlStruct] SMU could not communicate starting address of DPM table", @@ -138,14 +138,14 @@ static int polaris10_setup_graphics_level_structure(struct pp_smumgr *smumgr) vr_config_address = dpm_table_start + offsetof(SMU74_Discrete_DpmTable, VRConfig); - PP_ASSERT_WITH_CODE(0 == smu7_copy_bytes_to_smc(smumgr, vr_config_address, + PP_ASSERT_WITH_CODE(0 == smu7_copy_bytes_to_smc(hwmgr, vr_config_address, (uint8_t *)&vr_config, sizeof(uint32_t), 0x40000), "[AVFS][Polaris10_SetupGfxLvlStruct] Problems copying VRConfig value over to SMC", return -1); graphics_level_address = dpm_table_start + offsetof(SMU74_Discrete_DpmTable, GraphicsLevel); - PP_ASSERT_WITH_CODE(0 == smu7_copy_bytes_to_smc(smumgr, graphics_level_address, + PP_ASSERT_WITH_CODE(0 == smu7_copy_bytes_to_smc(hwmgr, graphics_level_address, (uint8_t *)(&avfs_graphics_level_polaris10), graphics_level_size, 0x40000), "[AVFS][Polaris10_SetupGfxLvlStruct] Copying of SCLK DPM table failed!", @@ -153,7 +153,7 @@ static int polaris10_setup_graphics_level_structure(struct pp_smumgr *smumgr) graphics_level_address = dpm_table_start + offsetof(SMU74_Discrete_DpmTable, MemoryLevel); - PP_ASSERT_WITH_CODE(0 == smu7_copy_bytes_to_smc(smumgr, graphics_level_address, + PP_ASSERT_WITH_CODE(0 == smu7_copy_bytes_to_smc(hwmgr, graphics_level_address, (uint8_t *)(&avfs_memory_level_polaris10), sizeof(avfs_memory_level_polaris10), 0x40000), "[AVFS][Polaris10_SetupGfxLvlStruct] Copying of MCLK DPM table failed!", return -1); @@ -162,7 +162,7 @@ static int polaris10_setup_graphics_level_structure(struct pp_smumgr *smumgr) graphics_level_address = dpm_table_start + offsetof(SMU74_Discrete_DpmTable, BootMVdd); - PP_ASSERT_WITH_CODE(0 == smu7_copy_bytes_to_smc(smumgr, graphics_level_address, + PP_ASSERT_WITH_CODE(0 == smu7_copy_bytes_to_smc(hwmgr, graphics_level_address, (uint8_t *)(&u16_boot_mvdd), sizeof(u16_boot_mvdd), 0x40000), "[AVFS][Polaris10_SetupGfxLvlStruct] Copying of DPM table failed!", return -1); @@ -172,9 +172,9 @@ static int polaris10_setup_graphics_level_structure(struct pp_smumgr *smumgr) static int -polaris10_avfs_event_mgr(struct pp_smumgr *smumgr, bool SMU_VFT_INTACT) +polaris10_avfs_event_mgr(struct pp_hwmgr *hwmgr, bool SMU_VFT_INTACT) { - struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(smumgr->backend); + struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); switch (smu_data->avfs.avfs_btc_status) { case AVFS_BTC_COMPLETED_PREVIOUSLY: @@ -183,20 +183,20 @@ polaris10_avfs_event_mgr(struct pp_smumgr *smumgr, bool SMU_VFT_INTACT) case AVFS_BTC_BOOT: /* Cold Boot State - Post SMU Start */ smu_data->avfs.avfs_btc_status = AVFS_BTC_DPMTABLESETUP_FAILED; - PP_ASSERT_WITH_CODE(0 == polaris10_setup_graphics_level_structure(smumgr), + PP_ASSERT_WITH_CODE(0 == polaris10_setup_graphics_level_structure(hwmgr), "[AVFS][Polaris10_AVFSEventMgr] Could not Copy Graphics Level table over to SMU", return -EINVAL); if (smu_data->avfs.avfs_btc_param > 1) { pr_info("[AVFS][Polaris10_AVFSEventMgr] AC BTC has not been successfully verified on Fiji. There may be in this setting."); smu_data->avfs.avfs_btc_status = AVFS_BTC_VIRUS_FAIL; - PP_ASSERT_WITH_CODE(0 == polaris10_setup_pwr_virus(smumgr), + PP_ASSERT_WITH_CODE(0 == polaris10_setup_pwr_virus(hwmgr), "[AVFS][Polaris10_AVFSEventMgr] Could not setup Pwr Virus for AVFS ", return -EINVAL); } smu_data->avfs.avfs_btc_status = AVFS_BTC_FAILED; - PP_ASSERT_WITH_CODE(0 == polaris10_perform_btc(smumgr), + PP_ASSERT_WITH_CODE(0 == polaris10_perform_btc(hwmgr), "[AVFS][Polaris10_AVFSEventMgr] Failure at SmuPolaris10_PerformBTC. AVFS Disabled", return -EINVAL); smu_data->avfs.avfs_btc_status = AVFS_BTC_ENABLEAVFS; @@ -215,146 +215,146 @@ polaris10_avfs_event_mgr(struct pp_smumgr *smumgr, bool SMU_VFT_INTACT) return 0; } -static int polaris10_start_smu_in_protection_mode(struct pp_smumgr *smumgr) +static int polaris10_start_smu_in_protection_mode(struct pp_hwmgr *hwmgr) { int result = 0; /* Wait for smc boot up */ - /* SMUM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(smumgr, SMC_IND, RCU_UC_EVENTS, boot_seq_done, 0) */ + /* PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(smumgr, SMC_IND, RCU_UC_EVENTS, boot_seq_done, 0) */ /* Assert reset */ - SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_RESET_CNTL, rst_reg, 1); - result = smu7_upload_smu_firmware_image(smumgr); + result = smu7_upload_smu_firmware_image(hwmgr); if (result != 0) return result; /* Clear status */ - cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC, ixSMU_STATUS, 0); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMU_STATUS, 0); - SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); /* De-assert reset */ - SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_RESET_CNTL, rst_reg, 0); - SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, SMC_IND, RCU_UC_EVENTS, INTERRUPTS_ENABLED, 1); + PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, RCU_UC_EVENTS, INTERRUPTS_ENABLED, 1); /* Call Test SMU message with 0x20000 offset to trigger SMU start */ - smu7_send_msg_to_smc_offset(smumgr); + smu7_send_msg_to_smc_offset(hwmgr); /* Wait done bit to be set */ /* Check pass/failed indicator */ - SMUM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(smumgr, SMC_IND, SMU_STATUS, SMU_DONE, 0); + PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND, SMU_STATUS, SMU_DONE, 0); - if (1 != SMUM_READ_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + if (1 != PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMU_STATUS, SMU_PASS)) PP_ASSERT_WITH_CODE(false, "SMU Firmware start failed!", return -1); - cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC, ixFIRMWARE_FLAGS, 0); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixFIRMWARE_FLAGS, 0); - SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_RESET_CNTL, rst_reg, 1); - SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_RESET_CNTL, rst_reg, 0); /* Wait for firmware to initialize */ - SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, SMC_IND, FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1); + PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1); return result; } -static int polaris10_start_smu_in_non_protection_mode(struct pp_smumgr *smumgr) +static int polaris10_start_smu_in_non_protection_mode(struct pp_hwmgr *hwmgr) { int result = 0; /* wait for smc boot up */ - SMUM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(smumgr, SMC_IND, RCU_UC_EVENTS, boot_seq_done, 0); + PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND, RCU_UC_EVENTS, boot_seq_done, 0); /* Clear firmware interrupt enable flag */ - /* SMUM_WRITE_VFPF_INDIRECT_FIELD(pSmuMgr, SMC_IND, SMC_SYSCON_MISC_CNTL, pre_fetcher_en, 1); */ - cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC, + /* PHM_WRITE_VFPF_INDIRECT_FIELD(pSmuMgr, SMC_IND, SMC_SYSCON_MISC_CNTL, pre_fetcher_en, 1); */ + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixFIRMWARE_FLAGS, 0); - SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_RESET_CNTL, rst_reg, 1); - result = smu7_upload_smu_firmware_image(smumgr); + result = smu7_upload_smu_firmware_image(hwmgr); if (result != 0) return result; /* Set smc instruct start point at 0x0 */ - smu7_program_jump_on_start(smumgr); + smu7_program_jump_on_start(hwmgr); - SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); - SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_RESET_CNTL, rst_reg, 0); /* Wait for firmware to initialize */ - SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, SMC_IND, + PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1); return result; } -static int polaris10_start_smu(struct pp_smumgr *smumgr) +static int polaris10_start_smu(struct pp_hwmgr *hwmgr) { int result = 0; - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); bool SMU_VFT_INTACT; /* Only start SMC if SMC RAM is not running */ - if (!smu7_is_smc_ram_running(smumgr)) { + if (!smu7_is_smc_ram_running(hwmgr)) { SMU_VFT_INTACT = false; - smu_data->protected_mode = (uint8_t) (SMUM_READ_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, SMU_FIRMWARE, SMU_MODE)); - smu_data->smu7_data.security_hard_key = (uint8_t) (SMUM_READ_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, SMU_FIRMWARE, SMU_SEL)); + smu_data->protected_mode = (uint8_t) (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMU_FIRMWARE, SMU_MODE)); + smu_data->smu7_data.security_hard_key = (uint8_t) (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMU_FIRMWARE, SMU_SEL)); /* Check if SMU is running in protected mode */ if (smu_data->protected_mode == 0) { - result = polaris10_start_smu_in_non_protection_mode(smumgr); + result = polaris10_start_smu_in_non_protection_mode(hwmgr); } else { - result = polaris10_start_smu_in_protection_mode(smumgr); + result = polaris10_start_smu_in_protection_mode(hwmgr); /* If failed, try with different security Key. */ if (result != 0) { smu_data->smu7_data.security_hard_key ^= 1; - cgs_rel_firmware(smumgr->device, CGS_UCODE_ID_SMU); - result = polaris10_start_smu_in_protection_mode(smumgr); + cgs_rel_firmware(hwmgr->device, CGS_UCODE_ID_SMU); + result = polaris10_start_smu_in_protection_mode(hwmgr); } } if (result != 0) PP_ASSERT_WITH_CODE(0, "Failed to load SMU ucode.", return result); - polaris10_avfs_event_mgr(smumgr, true); + polaris10_avfs_event_mgr(hwmgr, true); } else SMU_VFT_INTACT = true; /*Driver went offline but SMU was still alive and contains the VFT table */ - polaris10_avfs_event_mgr(smumgr, SMU_VFT_INTACT); + polaris10_avfs_event_mgr(hwmgr, SMU_VFT_INTACT); /* Setup SoftRegsStart here for register lookup in case DummyBackEnd is used and ProcessFirmwareHeader is not executed */ - smu7_read_smc_sram_dword(smumgr, SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, SoftRegisters), + smu7_read_smc_sram_dword(hwmgr, SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, SoftRegisters), &(smu_data->smu7_data.soft_regs_start), 0x40000); - result = smu7_request_smu_load_fw(smumgr); + result = smu7_request_smu_load_fw(hwmgr); return result; } -static bool polaris10_is_hw_avfs_present(struct pp_smumgr *smumgr) +static bool polaris10_is_hw_avfs_present(struct pp_hwmgr *hwmgr) { uint32_t efuse; - efuse = cgs_read_ind_register(smumgr->device, CGS_IND_REG__SMC, ixSMU_EFUSE_0 + (49*4)); + efuse = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMU_EFUSE_0 + (49*4)); efuse &= 0x00000001; if (efuse) return true; @@ -362,7 +362,7 @@ static bool polaris10_is_hw_avfs_present(struct pp_smumgr *smumgr) return false; } -static int polaris10_smu_init(struct pp_smumgr *smumgr) +static int polaris10_smu_init(struct pp_hwmgr *hwmgr) { struct polaris10_smumgr *smu_data; int i; @@ -371,9 +371,9 @@ static int polaris10_smu_init(struct pp_smumgr *smumgr) if (smu_data == NULL) return -ENOMEM; - smumgr->backend = smu_data; + hwmgr->smu_backend = smu_data; - if (smu7_init(smumgr)) + if (smu7_init(hwmgr)) return -EINVAL; for (i = 0; i < SMU74_MAX_LEVELS_GRAPHICS; i++) diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/rv_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/rv_smumgr.c index ce0a303..b98ade6 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/rv_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/rv_smumgr.c @@ -48,20 +48,20 @@ #define smnMP1_FIRMWARE_FLAGS 0x3010028 -bool rv_is_smc_ram_running(struct pp_smumgr *smumgr) +bool rv_is_smc_ram_running(struct pp_hwmgr *hwmgr) { uint32_t mp1_fw_flags, reg; reg = soc15_get_register_offset(NBIF_HWID, 0, mmPCIE_INDEX2_BASE_IDX, mmPCIE_INDEX2); - cgs_write_register(smumgr->device, reg, + cgs_write_register(hwmgr->device, reg, (MP1_Public | (smnMP1_FIRMWARE_FLAGS & 0xffffffff))); reg = soc15_get_register_offset(NBIF_HWID, 0, mmPCIE_DATA2_BASE_IDX, mmPCIE_DATA2); - mp1_fw_flags = cgs_read_register(smumgr->device, reg); + mp1_fw_flags = cgs_read_register(hwmgr->device, reg); if (mp1_fw_flags & MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK) return true; @@ -69,97 +69,97 @@ bool rv_is_smc_ram_running(struct pp_smumgr *smumgr) return false; } -static uint32_t rv_wait_for_response(struct pp_smumgr *smumgr) +static uint32_t rv_wait_for_response(struct pp_hwmgr *hwmgr) { uint32_t reg; - if (!rv_is_smc_ram_running(smumgr)) + if (!rv_is_smc_ram_running(hwmgr)) return -EINVAL; reg = soc15_get_register_offset(MP1_HWID, 0, mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90); - smum_wait_for_register_unequal(smumgr, reg, + phm_wait_for_register_unequal(hwmgr, reg, 0, MP1_C2PMSG_90__CONTENT_MASK); - return cgs_read_register(smumgr->device, reg); + return cgs_read_register(hwmgr->device, reg); } -int rv_send_msg_to_smc_without_waiting(struct pp_smumgr *smumgr, +int rv_send_msg_to_smc_without_waiting(struct pp_hwmgr *hwmgr, uint16_t msg) { uint32_t reg; - if (!rv_is_smc_ram_running(smumgr)) + if (!rv_is_smc_ram_running(hwmgr)) return -EINVAL; reg = soc15_get_register_offset(MP1_HWID, 0, mmMP1_SMN_C2PMSG_66_BASE_IDX, mmMP1_SMN_C2PMSG_66); - cgs_write_register(smumgr->device, reg, msg); + cgs_write_register(hwmgr->device, reg, msg); return 0; } -int rv_read_arg_from_smc(struct pp_smumgr *smumgr, uint32_t *arg) +int rv_read_arg_from_smc(struct pp_hwmgr *hwmgr, uint32_t *arg) { uint32_t reg; reg = soc15_get_register_offset(MP1_HWID, 0, mmMP1_SMN_C2PMSG_82_BASE_IDX, mmMP1_SMN_C2PMSG_82); - *arg = cgs_read_register(smumgr->device, reg); + *arg = cgs_read_register(hwmgr->device, reg); return 0; } -int rv_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg) +int rv_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg) { uint32_t reg; - rv_wait_for_response(smumgr); + rv_wait_for_response(hwmgr); reg = soc15_get_register_offset(MP1_HWID, 0, mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90); - cgs_write_register(smumgr->device, reg, 0); + cgs_write_register(hwmgr->device, reg, 0); - rv_send_msg_to_smc_without_waiting(smumgr, msg); + rv_send_msg_to_smc_without_waiting(hwmgr, msg); - if (rv_wait_for_response(smumgr) == 0) + if (rv_wait_for_response(hwmgr) == 0) printk("Failed to send Message %x.\n", msg); return 0; } -int rv_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr, +int rv_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, uint16_t msg, uint32_t parameter) { uint32_t reg; - rv_wait_for_response(smumgr); + rv_wait_for_response(hwmgr); reg = soc15_get_register_offset(MP1_HWID, 0, mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90); - cgs_write_register(smumgr->device, reg, 0); + cgs_write_register(hwmgr->device, reg, 0); reg = soc15_get_register_offset(MP1_HWID, 0, mmMP1_SMN_C2PMSG_82_BASE_IDX, mmMP1_SMN_C2PMSG_82); - cgs_write_register(smumgr->device, reg, parameter); + cgs_write_register(hwmgr->device, reg, parameter); - rv_send_msg_to_smc_without_waiting(smumgr, msg); + rv_send_msg_to_smc_without_waiting(hwmgr, msg); - if (rv_wait_for_response(smumgr) == 0) + if (rv_wait_for_response(hwmgr) == 0) printk("Failed to send Message %x.\n", msg); return 0; } -int rv_copy_table_from_smc(struct pp_smumgr *smumgr, +int rv_copy_table_from_smc(struct pp_hwmgr *hwmgr, uint8_t *table, int16_t table_id) { struct rv_smumgr *priv = - (struct rv_smumgr *)(smumgr->backend); + (struct rv_smumgr *)(hwmgr->smu_backend); PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE, "Invalid SMU Table ID!", return -EINVAL;); @@ -167,16 +167,16 @@ int rv_copy_table_from_smc(struct pp_smumgr *smumgr, "Invalid SMU Table version!", return -EINVAL;); PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0, "Invalid SMU Table Length!", return -EINVAL;); - PP_ASSERT_WITH_CODE(rv_send_msg_to_smc_with_parameter(smumgr, + PP_ASSERT_WITH_CODE(rv_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetDriverDramAddrHigh, priv->smu_tables.entry[table_id].table_addr_high) == 0, "[CopyTableFromSMC] Attempt to Set Dram Addr High Failed!", return -EINVAL;); - PP_ASSERT_WITH_CODE(rv_send_msg_to_smc_with_parameter(smumgr, + PP_ASSERT_WITH_CODE(rv_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetDriverDramAddrLow, priv->smu_tables.entry[table_id].table_addr_low) == 0, "[CopyTableFromSMC] Attempt to Set Dram Addr Low Failed!", return -EINVAL;); - PP_ASSERT_WITH_CODE(rv_send_msg_to_smc_with_parameter(smumgr, + PP_ASSERT_WITH_CODE(rv_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_TransferTableSmu2Dram, priv->smu_tables.entry[table_id].table_id) == 0, "[CopyTableFromSMC] Attempt to Transfer Table From SMU Failed!", @@ -188,11 +188,11 @@ int rv_copy_table_from_smc(struct pp_smumgr *smumgr, return 0; } -int rv_copy_table_to_smc(struct pp_smumgr *smumgr, +int rv_copy_table_to_smc(struct pp_hwmgr *hwmgr, uint8_t *table, int16_t table_id) { struct rv_smumgr *priv = - (struct rv_smumgr *)(smumgr->backend); + (struct rv_smumgr *)(hwmgr->smu_backend); PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE, "Invalid SMU Table ID!", return -EINVAL;); @@ -204,17 +204,17 @@ int rv_copy_table_to_smc(struct pp_smumgr *smumgr, memcpy(priv->smu_tables.entry[table_id].table, table, priv->smu_tables.entry[table_id].size); - PP_ASSERT_WITH_CODE(rv_send_msg_to_smc_with_parameter(smumgr, + PP_ASSERT_WITH_CODE(rv_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetDriverDramAddrHigh, priv->smu_tables.entry[table_id].table_addr_high) == 0, "[CopyTableToSMC] Attempt to Set Dram Addr High Failed!", return -EINVAL;); - PP_ASSERT_WITH_CODE(rv_send_msg_to_smc_with_parameter(smumgr, + PP_ASSERT_WITH_CODE(rv_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetDriverDramAddrLow, priv->smu_tables.entry[table_id].table_addr_low) == 0, "[CopyTableToSMC] Attempt to Set Dram Addr Low Failed!", return -EINVAL;); - PP_ASSERT_WITH_CODE(rv_send_msg_to_smc_with_parameter(smumgr, + PP_ASSERT_WITH_CODE(rv_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_TransferTableDram2Smu, priv->smu_tables.entry[table_id].table_id) == 0, "[CopyTableToSMC] Attempt to Transfer Table To SMU Failed!", @@ -223,15 +223,15 @@ int rv_copy_table_to_smc(struct pp_smumgr *smumgr, return 0; } -static int rv_verify_smc_interface(struct pp_smumgr *smumgr) +static int rv_verify_smc_interface(struct pp_hwmgr *hwmgr) { uint32_t smc_driver_if_version; - PP_ASSERT_WITH_CODE(!rv_send_msg_to_smc(smumgr, + PP_ASSERT_WITH_CODE(!rv_send_msg_to_smc(hwmgr, PPSMC_MSG_GetDriverIfVersion), "Attempt to get SMC IF Version Number Failed!", return -EINVAL); - PP_ASSERT_WITH_CODE(!rv_read_arg_from_smc(smumgr, + PP_ASSERT_WITH_CODE(!rv_read_arg_from_smc(hwmgr, &smc_driver_if_version), "Attempt to read SMC IF Version Number Failed!", return -EINVAL); @@ -243,9 +243,9 @@ static int rv_verify_smc_interface(struct pp_smumgr *smumgr) } /* sdma is disabled by default in vbios, need to re-enable in driver */ -static int rv_smc_enable_sdma(struct pp_smumgr *smumgr) +static int rv_smc_enable_sdma(struct pp_hwmgr *hwmgr) { - PP_ASSERT_WITH_CODE(!rv_send_msg_to_smc(smumgr, + PP_ASSERT_WITH_CODE(!rv_send_msg_to_smc(hwmgr, PPSMC_MSG_PowerUpSdma), "Attempt to power up sdma Failed!", return -EINVAL); @@ -253,9 +253,9 @@ static int rv_smc_enable_sdma(struct pp_smumgr *smumgr) return 0; } -static int rv_smc_disable_sdma(struct pp_smumgr *smumgr) +static int rv_smc_disable_sdma(struct pp_hwmgr *hwmgr) { - PP_ASSERT_WITH_CODE(!rv_send_msg_to_smc(smumgr, + PP_ASSERT_WITH_CODE(!rv_send_msg_to_smc(hwmgr, PPSMC_MSG_PowerDownSdma), "Attempt to power down sdma Failed!", return -EINVAL); @@ -264,9 +264,9 @@ static int rv_smc_disable_sdma(struct pp_smumgr *smumgr) } /* vcn is disabled by default in vbios, need to re-enable in driver */ -static int rv_smc_enable_vcn(struct pp_smumgr *smumgr) +static int rv_smc_enable_vcn(struct pp_hwmgr *hwmgr) { - PP_ASSERT_WITH_CODE(!rv_send_msg_to_smc_with_parameter(smumgr, + PP_ASSERT_WITH_CODE(!rv_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_PowerUpVcn, 0), "Attempt to power up vcn Failed!", return -EINVAL); @@ -274,9 +274,9 @@ static int rv_smc_enable_vcn(struct pp_smumgr *smumgr) return 0; } -static int rv_smc_disable_vcn(struct pp_smumgr *smumgr) +static int rv_smc_disable_vcn(struct pp_hwmgr *hwmgr) { - PP_ASSERT_WITH_CODE(!rv_send_msg_to_smc_with_parameter(smumgr, + PP_ASSERT_WITH_CODE(!rv_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_PowerDownVcn, 0), "Attempt to power down vcn Failed!", return -EINVAL); @@ -284,38 +284,38 @@ static int rv_smc_disable_vcn(struct pp_smumgr *smumgr) return 0; } -static int rv_smu_fini(struct pp_smumgr *smumgr) +static int rv_smu_fini(struct pp_hwmgr *hwmgr) { struct rv_smumgr *priv = - (struct rv_smumgr *)(smumgr->backend); + (struct rv_smumgr *)(hwmgr->smu_backend); if (priv) { - rv_smc_disable_sdma(smumgr); - rv_smc_disable_vcn(smumgr); - cgs_free_gpu_mem(smumgr->device, + rv_smc_disable_sdma(hwmgr); + rv_smc_disable_vcn(hwmgr); + cgs_free_gpu_mem(hwmgr->device, priv->smu_tables.entry[WMTABLE].handle); - cgs_free_gpu_mem(smumgr->device, + cgs_free_gpu_mem(hwmgr->device, priv->smu_tables.entry[CLOCKTABLE].handle); - kfree(smumgr->backend); - smumgr->backend = NULL; + kfree(hwmgr->smu_backend); + hwmgr->smu_backend = NULL; } return 0; } -static int rv_start_smu(struct pp_smumgr *smumgr) +static int rv_start_smu(struct pp_hwmgr *hwmgr) { - if (rv_verify_smc_interface(smumgr)) + if (rv_verify_smc_interface(hwmgr)) return -EINVAL; - if (rv_smc_enable_sdma(smumgr)) + if (rv_smc_enable_sdma(hwmgr)) return -EINVAL; - if (rv_smc_enable_vcn(smumgr)) + if (rv_smc_enable_vcn(hwmgr)) return -EINVAL; return 0; } -static int rv_smu_init(struct pp_smumgr *smumgr) +static int rv_smu_init(struct pp_hwmgr *hwmgr) { struct rv_smumgr *priv; uint64_t mc_addr; @@ -327,10 +327,10 @@ static int rv_smu_init(struct pp_smumgr *smumgr) if (!priv) return -ENOMEM; - smumgr->backend = priv; + hwmgr->smu_backend = priv; /* allocate space for watermarks table */ - smu_allocate_memory(smumgr->device, + smu_allocate_memory(hwmgr->device, sizeof(Watermarks_t), CGS_GPU_MEM_TYPE__GART_CACHEABLE, PAGE_SIZE, @@ -340,8 +340,8 @@ static int rv_smu_init(struct pp_smumgr *smumgr) PP_ASSERT_WITH_CODE(kaddr, "[rv_smu_init] Out of memory for wmtable.", - kfree(smumgr->backend); - smumgr->backend = NULL; + kfree(hwmgr->smu_backend); + hwmgr->smu_backend = NULL; return -EINVAL); priv->smu_tables.entry[WMTABLE].version = 0x01; @@ -355,7 +355,7 @@ static int rv_smu_init(struct pp_smumgr *smumgr) priv->smu_tables.entry[WMTABLE].handle = handle; /* allocate space for watermarks table */ - smu_allocate_memory(smumgr->device, + smu_allocate_memory(hwmgr->device, sizeof(DpmClocks_t), CGS_GPU_MEM_TYPE__GART_CACHEABLE, PAGE_SIZE, @@ -365,10 +365,10 @@ static int rv_smu_init(struct pp_smumgr *smumgr) PP_ASSERT_WITH_CODE(kaddr, "[rv_smu_init] Out of memory for CLOCKTABLE.", - cgs_free_gpu_mem(smumgr->device, + cgs_free_gpu_mem(hwmgr->device, (cgs_handle_t)priv->smu_tables.entry[WMTABLE].handle); - kfree(smumgr->backend); - smumgr->backend = NULL; + kfree(hwmgr->smu_backend); + hwmgr->smu_backend = NULL; return -EINVAL); priv->smu_tables.entry[CLOCKTABLE].version = 0x01; diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/rv_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/rv_smumgr.h index 262c8de..5888840 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/rv_smumgr.h +++ b/drivers/gpu/drm/amd/powerplay/smumgr/rv_smumgr.h @@ -51,11 +51,11 @@ struct rv_smumgr { struct smu_table_array smu_tables; }; -int rv_read_arg_from_smc(struct pp_smumgr *smumgr, uint32_t *arg); -bool rv_is_smc_ram_running(struct pp_smumgr *smumgr); -int rv_copy_table_from_smc(struct pp_smumgr *smumgr, +int rv_read_arg_from_smc(struct pp_hwmgr *hwmgr, uint32_t *arg); +bool rv_is_smc_ram_running(struct pp_hwmgr *hwmgr); +int rv_copy_table_from_smc(struct pp_hwmgr *hwmgr, uint8_t *table, int16_t table_id); -int rv_copy_table_to_smc(struct pp_smumgr *smumgr, +int rv_copy_table_to_smc(struct pp_hwmgr *hwmgr, uint8_t *table, int16_t table_id); diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c index c49a6f2..2ae05bb 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c @@ -34,18 +34,18 @@ #define SMU7_SMC_SIZE 0x20000 -static int smu7_set_smc_sram_address(struct pp_smumgr *smumgr, uint32_t smc_addr, uint32_t limit) +static int smu7_set_smc_sram_address(struct pp_hwmgr *hwmgr, uint32_t smc_addr, uint32_t limit) { PP_ASSERT_WITH_CODE((0 == (3 & smc_addr)), "SMC address must be 4 byte aligned.", return -EINVAL); PP_ASSERT_WITH_CODE((limit > (smc_addr + 3)), "SMC addr is beyond the SMC RAM area.", return -EINVAL); - cgs_write_register(smumgr->device, mmSMC_IND_INDEX_11, smc_addr); - SMUM_WRITE_FIELD(smumgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_11, 0); /* on ci, SMC_IND_ACCESS_CNTL is different */ + cgs_write_register(hwmgr->device, mmSMC_IND_INDEX_11, smc_addr); + PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_11, 0); /* on ci, SMC_IND_ACCESS_CNTL is different */ return 0; } -int smu7_copy_bytes_from_smc(struct pp_smumgr *smumgr, uint32_t smc_start_address, uint32_t *dest, uint32_t byte_count, uint32_t limit) +int smu7_copy_bytes_from_smc(struct pp_hwmgr *hwmgr, uint32_t smc_start_address, uint32_t *dest, uint32_t byte_count, uint32_t limit) { uint32_t data; uint32_t addr; @@ -59,7 +59,7 @@ int smu7_copy_bytes_from_smc(struct pp_smumgr *smumgr, uint32_t smc_start_addres addr = smc_start_address; while (byte_count >= 4) { - smu7_read_smc_sram_dword(smumgr, addr, &data, limit); + smu7_read_smc_sram_dword(hwmgr, addr, &data, limit); *dest = PP_SMC_TO_HOST_UL(data); @@ -69,7 +69,7 @@ int smu7_copy_bytes_from_smc(struct pp_smumgr *smumgr, uint32_t smc_start_addres } if (byte_count) { - smu7_read_smc_sram_dword(smumgr, addr, &data, limit); + smu7_read_smc_sram_dword(hwmgr, addr, &data, limit); *pdata = PP_SMC_TO_HOST_UL(data); /* Cast dest into byte type in dest_byte. This way, we don't overflow if the allocated memory is not 4-byte aligned. */ dest_byte = (uint8_t *)dest; @@ -81,7 +81,7 @@ int smu7_copy_bytes_from_smc(struct pp_smumgr *smumgr, uint32_t smc_start_addres } -int smu7_copy_bytes_to_smc(struct pp_smumgr *smumgr, uint32_t smc_start_address, +int smu7_copy_bytes_to_smc(struct pp_hwmgr *hwmgr, uint32_t smc_start_address, const uint8_t *src, uint32_t byte_count, uint32_t limit) { int result; @@ -99,12 +99,12 @@ int smu7_copy_bytes_to_smc(struct pp_smumgr *smumgr, uint32_t smc_start_address, /* Bytes are written into the SMC addres space with the MSB first. */ data = src[0] * 0x1000000 + src[1] * 0x10000 + src[2] * 0x100 + src[3]; - result = smu7_set_smc_sram_address(smumgr, addr, limit); + result = smu7_set_smc_sram_address(hwmgr, addr, limit); if (0 != result) return result; - cgs_write_register(smumgr->device, mmSMC_IND_DATA_11, data); + cgs_write_register(hwmgr->device, mmSMC_IND_DATA_11, data); src += 4; byte_count -= 4; @@ -115,13 +115,13 @@ int smu7_copy_bytes_to_smc(struct pp_smumgr *smumgr, uint32_t smc_start_address, data = 0; - result = smu7_set_smc_sram_address(smumgr, addr, limit); + result = smu7_set_smc_sram_address(hwmgr, addr, limit); if (0 != result) return result; - original_data = cgs_read_register(smumgr->device, mmSMC_IND_DATA_11); + original_data = cgs_read_register(hwmgr->device, mmSMC_IND_DATA_11); extra_shift = 8 * (4 - byte_count); @@ -135,53 +135,53 @@ int smu7_copy_bytes_to_smc(struct pp_smumgr *smumgr, uint32_t smc_start_address, data |= (original_data & ~((~0UL) << extra_shift)); - result = smu7_set_smc_sram_address(smumgr, addr, limit); + result = smu7_set_smc_sram_address(hwmgr, addr, limit); if (0 != result) return result; - cgs_write_register(smumgr->device, mmSMC_IND_DATA_11, data); + cgs_write_register(hwmgr->device, mmSMC_IND_DATA_11, data); } return 0; } -int smu7_program_jump_on_start(struct pp_smumgr *smumgr) +int smu7_program_jump_on_start(struct pp_hwmgr *hwmgr) { static const unsigned char data[4] = { 0xE0, 0x00, 0x80, 0x40 }; - smu7_copy_bytes_to_smc(smumgr, 0x0, data, 4, sizeof(data)+1); + smu7_copy_bytes_to_smc(hwmgr, 0x0, data, 4, sizeof(data)+1); return 0; } -bool smu7_is_smc_ram_running(struct pp_smumgr *smumgr) +bool smu7_is_smc_ram_running(struct pp_hwmgr *hwmgr) { - return ((0 == SMUM_READ_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable)) - && (0x20100 <= cgs_read_ind_register(smumgr->device, CGS_IND_REG__SMC, ixSMC_PC_C))); + return ((0 == PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable)) + && (0x20100 <= cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMC_PC_C))); } -int smu7_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg) +int smu7_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg) { int ret; - if (!smu7_is_smc_ram_running(smumgr)) + if (!smu7_is_smc_ram_running(hwmgr)) return -EINVAL; - SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0); + PHM_WAIT_FIELD_UNEQUAL(hwmgr, SMC_RESP_0, SMC_RESP, 0); - ret = SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP); + ret = PHM_READ_FIELD(hwmgr->device, SMC_RESP_0, SMC_RESP); if (ret != 1) pr_info("\n failed to send pre message %x ret is %d \n", msg, ret); - cgs_write_register(smumgr->device, mmSMC_MESSAGE_0, msg); + cgs_write_register(hwmgr->device, mmSMC_MESSAGE_0, msg); - SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0); + PHM_WAIT_FIELD_UNEQUAL(hwmgr, SMC_RESP_0, SMC_RESP, 0); - ret = SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP); + ret = PHM_READ_FIELD(hwmgr->device, SMC_RESP_0, SMC_RESP); if (ret != 1) pr_info("\n failed to send message %x ret is %d \n", msg, ret); @@ -189,53 +189,53 @@ int smu7_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg) return 0; } -int smu7_send_msg_to_smc_without_waiting(struct pp_smumgr *smumgr, uint16_t msg) +int smu7_send_msg_to_smc_without_waiting(struct pp_hwmgr *hwmgr, uint16_t msg) { - cgs_write_register(smumgr->device, mmSMC_MESSAGE_0, msg); + cgs_write_register(hwmgr->device, mmSMC_MESSAGE_0, msg); return 0; } -int smu7_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr, uint16_t msg, uint32_t parameter) +int smu7_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, uint16_t msg, uint32_t parameter) { - if (!smu7_is_smc_ram_running(smumgr)) { + if (!smu7_is_smc_ram_running(hwmgr)) { return -EINVAL; } - SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0); + PHM_WAIT_FIELD_UNEQUAL(hwmgr, SMC_RESP_0, SMC_RESP, 0); - cgs_write_register(smumgr->device, mmSMC_MSG_ARG_0, parameter); + cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, parameter); - return smu7_send_msg_to_smc(smumgr, msg); + return smu7_send_msg_to_smc(hwmgr, msg); } -int smu7_send_msg_to_smc_with_parameter_without_waiting(struct pp_smumgr *smumgr, uint16_t msg, uint32_t parameter) +int smu7_send_msg_to_smc_with_parameter_without_waiting(struct pp_hwmgr *hwmgr, uint16_t msg, uint32_t parameter) { - cgs_write_register(smumgr->device, mmSMC_MSG_ARG_0, parameter); + cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, parameter); - return smu7_send_msg_to_smc_without_waiting(smumgr, msg); + return smu7_send_msg_to_smc_without_waiting(hwmgr, msg); } -int smu7_send_msg_to_smc_offset(struct pp_smumgr *smumgr) +int smu7_send_msg_to_smc_offset(struct pp_hwmgr *hwmgr) { - cgs_write_register(smumgr->device, mmSMC_MSG_ARG_0, 0x20000); + cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, 0x20000); - cgs_write_register(smumgr->device, mmSMC_MESSAGE_0, PPSMC_MSG_Test); + cgs_write_register(hwmgr->device, mmSMC_MESSAGE_0, PPSMC_MSG_Test); - SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0); + PHM_WAIT_FIELD_UNEQUAL(hwmgr, SMC_RESP_0, SMC_RESP, 0); - if (1 != SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP)) + if (1 != PHM_READ_FIELD(hwmgr->device, SMC_RESP_0, SMC_RESP)) pr_info("Failed to send Message.\n"); return 0; } -int smu7_wait_for_smc_inactive(struct pp_smumgr *smumgr) +int smu7_wait_for_smc_inactive(struct pp_hwmgr *hwmgr) { - if (!smu7_is_smc_ram_running(smumgr)) + if (!smu7_is_smc_ram_running(hwmgr)) return -EINVAL; - SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, SMC_IND, SMC_SYSCON_CLOCK_CNTL_0, cken, 0); + PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, SMC_SYSCON_CLOCK_CNTL_0, cken, 0); return 0; } @@ -289,29 +289,29 @@ enum cgs_ucode_id smu7_convert_fw_type_to_cgs(uint32_t fw_type) } -int smu7_read_smc_sram_dword(struct pp_smumgr *smumgr, uint32_t smc_addr, uint32_t *value, uint32_t limit) +int smu7_read_smc_sram_dword(struct pp_hwmgr *hwmgr, uint32_t smc_addr, uint32_t *value, uint32_t limit) { int result; - result = smu7_set_smc_sram_address(smumgr, smc_addr, limit); + result = smu7_set_smc_sram_address(hwmgr, smc_addr, limit); if (result) return result; - *value = cgs_read_register(smumgr->device, mmSMC_IND_DATA_11); + *value = cgs_read_register(hwmgr->device, mmSMC_IND_DATA_11); return 0; } -int smu7_write_smc_sram_dword(struct pp_smumgr *smumgr, uint32_t smc_addr, uint32_t value, uint32_t limit) +int smu7_write_smc_sram_dword(struct pp_hwmgr *hwmgr, uint32_t smc_addr, uint32_t value, uint32_t limit) { int result; - result = smu7_set_smc_sram_address(smumgr, smc_addr, limit); + result = smu7_set_smc_sram_address(hwmgr, smc_addr, limit); if (result) return result; - cgs_write_register(smumgr->device, mmSMC_IND_DATA_11, value); + cgs_write_register(hwmgr->device, mmSMC_IND_DATA_11, value); return 0; } @@ -354,14 +354,14 @@ static uint32_t smu7_get_mask_for_firmware_type(uint32_t fw_type) return result; } -static int smu7_populate_single_firmware_entry(struct pp_smumgr *smumgr, +static int smu7_populate_single_firmware_entry(struct pp_hwmgr *hwmgr, uint32_t fw_type, struct SMU_Entry *entry) { int result = 0; struct cgs_firmware_info info = {0}; - result = cgs_get_firmware_info(smumgr->device, + result = cgs_get_firmware_info(hwmgr->device, smu7_convert_fw_type_to_cgs(fw_type), &info); @@ -374,7 +374,7 @@ static int smu7_populate_single_firmware_entry(struct pp_smumgr *smumgr, entry->meta_data_addr_low = 0; /* digest need be excluded out */ - if (cgs_is_virtualization_enabled(smumgr->device)) + if (cgs_is_virtualization_enabled(hwmgr->device)) info.image_size -= 20; entry->data_size_byte = info.image_size; entry->num_register_entries = 0; @@ -389,30 +389,30 @@ static int smu7_populate_single_firmware_entry(struct pp_smumgr *smumgr, return 0; } -int smu7_request_smu_load_fw(struct pp_smumgr *smumgr) +int smu7_request_smu_load_fw(struct pp_hwmgr *hwmgr) { - struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(smumgr->backend); + struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); uint32_t fw_to_load; int result = 0; struct SMU_DRAMData_TOC *toc; - if (!smumgr->reload_fw) { + if (!hwmgr->reload_fw) { pr_info("skip reloading...\n"); return 0; } if (smu_data->soft_regs_start) - cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC, - smu_data->soft_regs_start + smum_get_offsetof(smumgr, + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + smu_data->soft_regs_start + smum_get_offsetof(hwmgr, SMU_SoftRegisters, UcodeLoadStatus), 0x0); - if (smumgr->chip_id > CHIP_TOPAZ) { /* add support for Topaz */ - if (!cgs_is_virtualization_enabled(smumgr->device)) { - smu7_send_msg_to_smc_with_parameter(smumgr, + if (hwmgr->chip_id > CHIP_TOPAZ) { /* add support for Topaz */ + if (!cgs_is_virtualization_enabled(hwmgr->device)) { + smu7_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SMU_DRAM_ADDR_HI, smu_data->smu_buffer.mc_addr_high); - smu7_send_msg_to_smc_with_parameter(smumgr, + smu7_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SMU_DRAM_ADDR_LO, smu_data->smu_buffer.mc_addr_low); } @@ -439,80 +439,79 @@ int smu7_request_smu_load_fw(struct pp_smumgr *smumgr) toc->num_entries = 0; toc->structure_version = 1; - PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(smumgr, + PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr, UCODE_ID_RLC_G, &toc->entry[toc->num_entries++]), "Failed to Get Firmware Entry.", return -EINVAL); - PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(smumgr, + PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr, UCODE_ID_CP_CE, &toc->entry[toc->num_entries++]), "Failed to Get Firmware Entry.", return -EINVAL); - PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(smumgr, + PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr, UCODE_ID_CP_PFP, &toc->entry[toc->num_entries++]), "Failed to Get Firmware Entry.", return -EINVAL); - PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(smumgr, + PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr, UCODE_ID_CP_ME, &toc->entry[toc->num_entries++]), "Failed to Get Firmware Entry.", return -EINVAL); - PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(smumgr, + PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr, UCODE_ID_CP_MEC, &toc->entry[toc->num_entries++]), "Failed to Get Firmware Entry.", return -EINVAL); - PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(smumgr, + PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr, UCODE_ID_CP_MEC_JT1, &toc->entry[toc->num_entries++]), "Failed to Get Firmware Entry.", return -EINVAL); - PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(smumgr, + PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr, UCODE_ID_CP_MEC_JT2, &toc->entry[toc->num_entries++]), "Failed to Get Firmware Entry.", return -EINVAL); - PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(smumgr, + PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr, UCODE_ID_SDMA0, &toc->entry[toc->num_entries++]), "Failed to Get Firmware Entry.", return -EINVAL); - PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(smumgr, + PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr, UCODE_ID_SDMA1, &toc->entry[toc->num_entries++]), "Failed to Get Firmware Entry.", return -EINVAL); - if (cgs_is_virtualization_enabled(smumgr->device)) - PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(smumgr, + if (cgs_is_virtualization_enabled(hwmgr->device)) + PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr, UCODE_ID_MEC_STORAGE, &toc->entry[toc->num_entries++]), "Failed to Get Firmware Entry.", return -EINVAL); - smu7_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_DRV_DRAM_ADDR_HI, smu_data->header_buffer.mc_addr_high); - smu7_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_DRV_DRAM_ADDR_LO, smu_data->header_buffer.mc_addr_low); + smu7_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_DRV_DRAM_ADDR_HI, smu_data->header_buffer.mc_addr_high); + smu7_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_DRV_DRAM_ADDR_LO, smu_data->header_buffer.mc_addr_low); - if (smu7_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_LoadUcodes, fw_to_load)) + if (smu7_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_LoadUcodes, fw_to_load)) pr_err("Fail to Request SMU Load uCode"); return result; } /* Check if the FW has been loaded, SMU will not return if loading has not finished. */ -int smu7_check_fw_load_finish(struct pp_smumgr *smumgr, uint32_t fw_type) +int smu7_check_fw_load_finish(struct pp_hwmgr *hwmgr, uint32_t fw_type) { - struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(smumgr->backend); + struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); uint32_t fw_mask = smu7_get_mask_for_firmware_type(fw_type); uint32_t ret; - ret = smum_wait_on_indirect_register(smumgr, mmSMC_IND_INDEX_11, - smu_data->soft_regs_start + smum_get_offsetof(smumgr, + ret = phm_wait_on_indirect_register(hwmgr, mmSMC_IND_INDEX_11, + smu_data->soft_regs_start + smum_get_offsetof(hwmgr, SMU_SoftRegisters, UcodeLoadStatus), fw_mask, fw_mask); - return ret; } -int smu7_reload_firmware(struct pp_smumgr *smumgr) +int smu7_reload_firmware(struct pp_hwmgr *hwmgr) { - return smumgr->smumgr_funcs->start_smu(smumgr); + return hwmgr->smumgr_funcs->start_smu(hwmgr); } -static int smu7_upload_smc_firmware_data(struct pp_smumgr *smumgr, uint32_t length, uint32_t *src, uint32_t limit) +static int smu7_upload_smc_firmware_data(struct pp_hwmgr *hwmgr, uint32_t length, uint32_t *src, uint32_t limit) { uint32_t byte_count = length; PP_ASSERT_WITH_CODE((limit >= byte_count), "SMC address is beyond the SMC RAM area.", return -EINVAL); - cgs_write_register(smumgr->device, mmSMC_IND_INDEX_11, 0x20000); - SMUM_WRITE_FIELD(smumgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_11, 1); + cgs_write_register(hwmgr->device, mmSMC_IND_INDEX_11, 0x20000); + PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_11, 1); for (; byte_count >= 4; byte_count -= 4) - cgs_write_register(smumgr->device, mmSMC_IND_DATA_11, *src++); + cgs_write_register(hwmgr->device, mmSMC_IND_DATA_11, *src++); - SMUM_WRITE_FIELD(smumgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_11, 0); + PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_11, 0); PP_ASSERT_WITH_CODE((0 == byte_count), "SMC size must be dividable by 4.", return -EINVAL); @@ -520,41 +519,41 @@ static int smu7_upload_smc_firmware_data(struct pp_smumgr *smumgr, uint32_t leng } -int smu7_upload_smu_firmware_image(struct pp_smumgr *smumgr) +int smu7_upload_smu_firmware_image(struct pp_hwmgr *hwmgr) { int result = 0; - struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(smumgr->backend); + struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); struct cgs_firmware_info info = {0}; if (smu_data->security_hard_key == 1) - cgs_get_firmware_info(smumgr->device, + cgs_get_firmware_info(hwmgr->device, smu7_convert_fw_type_to_cgs(UCODE_ID_SMU), &info); else - cgs_get_firmware_info(smumgr->device, + cgs_get_firmware_info(hwmgr->device, smu7_convert_fw_type_to_cgs(UCODE_ID_SMU_SK), &info); - smumgr->is_kicker = info.is_kicker; + hwmgr->is_kicker = info.is_kicker; - result = smu7_upload_smc_firmware_data(smumgr, info.image_size, (uint32_t *)info.kptr, SMU7_SMC_SIZE); + result = smu7_upload_smc_firmware_data(hwmgr, info.image_size, (uint32_t *)info.kptr, SMU7_SMC_SIZE); return result; } -int smu7_init(struct pp_smumgr *smumgr) +int smu7_init(struct pp_hwmgr *hwmgr) { struct smu7_smumgr *smu_data; uint8_t *internal_buf; uint64_t mc_addr = 0; /* Allocate memory for backend private data */ - smu_data = (struct smu7_smumgr *)(smumgr->backend); + smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); smu_data->header_buffer.data_size = ((sizeof(struct SMU_DRAMData_TOC) / 4096) + 1) * 4096; /* Allocate FW image data structure and header buffer and * send the header buffer address to SMU */ - smu_allocate_memory(smumgr->device, + smu_allocate_memory(hwmgr->device, smu_data->header_buffer.data_size, CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB, PAGE_SIZE, @@ -568,16 +567,16 @@ int smu7_init(struct pp_smumgr *smumgr) PP_ASSERT_WITH_CODE((NULL != smu_data->header), "Out of memory.", - kfree(smumgr->backend); - cgs_free_gpu_mem(smumgr->device, + kfree(hwmgr->smu_backend); + cgs_free_gpu_mem(hwmgr->device, (cgs_handle_t)smu_data->header_buffer.handle); return -EINVAL); - if (cgs_is_virtualization_enabled(smumgr->device)) + if (cgs_is_virtualization_enabled(hwmgr->device)) return 0; smu_data->smu_buffer.data_size = 200*4096; - smu_allocate_memory(smumgr->device, + smu_allocate_memory(hwmgr->device, smu_data->smu_buffer.data_size, CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB, PAGE_SIZE, @@ -591,12 +590,12 @@ int smu7_init(struct pp_smumgr *smumgr) PP_ASSERT_WITH_CODE((NULL != internal_buf), "Out of memory.", - kfree(smumgr->backend); - cgs_free_gpu_mem(smumgr->device, + kfree(hwmgr->smu_backend); + cgs_free_gpu_mem(hwmgr->device, (cgs_handle_t)smu_data->smu_buffer.handle); return -EINVAL); - if (smum_is_hw_avfs_present(smumgr)) + if (smum_is_hw_avfs_present(hwmgr)) smu_data->avfs.avfs_btc_status = AVFS_BTC_BOOT; else smu_data->avfs.avfs_btc_status = AVFS_BTC_NOTSUPPORTED; @@ -605,12 +604,10 @@ int smu7_init(struct pp_smumgr *smumgr) } -int smu7_smu_fini(struct pp_smumgr *smumgr) +int smu7_smu_fini(struct pp_hwmgr *hwmgr) { - if (smumgr->backend) { - kfree(smumgr->backend); - smumgr->backend = NULL; - } - cgs_rel_firmware(smumgr->device, CGS_UCODE_ID_SMU); + kfree(hwmgr->smu_backend); + hwmgr->smu_backend = NULL; + cgs_rel_firmware(hwmgr->device, CGS_UCODE_ID_SMU); return 0; } diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h index ee5e32d..0b63c5c 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h +++ b/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h @@ -60,32 +60,32 @@ struct smu7_smumgr { }; -int smu7_copy_bytes_from_smc(struct pp_smumgr *smumgr, uint32_t smc_start_address, +int smu7_copy_bytes_from_smc(struct pp_hwmgr *hwmgr, uint32_t smc_start_address, uint32_t *dest, uint32_t byte_count, uint32_t limit); -int smu7_copy_bytes_to_smc(struct pp_smumgr *smumgr, uint32_t smc_start_address, +int smu7_copy_bytes_to_smc(struct pp_hwmgr *hwmgr, uint32_t smc_start_address, const uint8_t *src, uint32_t byte_count, uint32_t limit); -int smu7_program_jump_on_start(struct pp_smumgr *smumgr); -bool smu7_is_smc_ram_running(struct pp_smumgr *smumgr); -int smu7_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg); -int smu7_send_msg_to_smc_without_waiting(struct pp_smumgr *smumgr, uint16_t msg); -int smu7_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr, uint16_t msg, +int smu7_program_jump_on_start(struct pp_hwmgr *hwmgr); +bool smu7_is_smc_ram_running(struct pp_hwmgr *hwmgr); +int smu7_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg); +int smu7_send_msg_to_smc_without_waiting(struct pp_hwmgr *hwmgr, uint16_t msg); +int smu7_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, uint16_t msg, uint32_t parameter); -int smu7_send_msg_to_smc_with_parameter_without_waiting(struct pp_smumgr *smumgr, +int smu7_send_msg_to_smc_with_parameter_without_waiting(struct pp_hwmgr *hwmgr, uint16_t msg, uint32_t parameter); -int smu7_send_msg_to_smc_offset(struct pp_smumgr *smumgr); -int smu7_wait_for_smc_inactive(struct pp_smumgr *smumgr); +int smu7_send_msg_to_smc_offset(struct pp_hwmgr *hwmgr); +int smu7_wait_for_smc_inactive(struct pp_hwmgr *hwmgr); enum cgs_ucode_id smu7_convert_fw_type_to_cgs(uint32_t fw_type); -int smu7_read_smc_sram_dword(struct pp_smumgr *smumgr, uint32_t smc_addr, +int smu7_read_smc_sram_dword(struct pp_hwmgr *hwmgr, uint32_t smc_addr, uint32_t *value, uint32_t limit); -int smu7_write_smc_sram_dword(struct pp_smumgr *smumgr, uint32_t smc_addr, +int smu7_write_smc_sram_dword(struct pp_hwmgr *hwmgr, uint32_t smc_addr, uint32_t value, uint32_t limit); -int smu7_request_smu_load_fw(struct pp_smumgr *smumgr); -int smu7_check_fw_load_finish(struct pp_smumgr *smumgr, uint32_t fw_type); -int smu7_reload_firmware(struct pp_smumgr *smumgr); -int smu7_upload_smu_firmware_image(struct pp_smumgr *smumgr); -int smu7_init(struct pp_smumgr *smumgr); -int smu7_smu_fini(struct pp_smumgr *smumgr); +int smu7_request_smu_load_fw(struct pp_hwmgr *hwmgr); +int smu7_check_fw_load_finish(struct pp_hwmgr *hwmgr, uint32_t fw_type); +int smu7_reload_firmware(struct pp_hwmgr *hwmgr); +int smu7_upload_smu_firmware_image(struct pp_hwmgr *hwmgr); +int smu7_init(struct pp_hwmgr *hwmgr); +int smu7_smu_fini(struct pp_hwmgr *hwmgr); #endif
\ No newline at end of file diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c index 3bdf647..8673884 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c @@ -27,7 +27,6 @@ #include <linux/slab.h> #include <linux/types.h> #include <drm/amdgpu_drm.h> -#include "pp_instance.h" #include "smumgr.h" #include "cgs_common.h" @@ -46,88 +45,18 @@ MODULE_FIRMWARE("amdgpu/polaris12_smc.bin"); MODULE_FIRMWARE("amdgpu/vega10_smc.bin"); MODULE_FIRMWARE("amdgpu/vega10_acg_smc.bin"); -int smum_early_init(struct pp_instance *handle) +int smum_thermal_avfs_enable(struct pp_hwmgr *hwmgr) { - struct pp_smumgr *smumgr; - - if (handle == NULL) - return -EINVAL; - - smumgr = kzalloc(sizeof(struct pp_smumgr), GFP_KERNEL); - if (smumgr == NULL) - return -ENOMEM; - - smumgr->device = handle->device; - smumgr->chip_family = handle->chip_family; - smumgr->chip_id = handle->chip_id; - smumgr->usec_timeout = AMD_MAX_USEC_TIMEOUT; - smumgr->reload_fw = 1; - handle->smu_mgr = smumgr; - - switch (smumgr->chip_family) { - case AMDGPU_FAMILY_CZ: - smumgr->smumgr_funcs = &cz_smu_funcs; - break; - case AMDGPU_FAMILY_VI: - switch (smumgr->chip_id) { - case CHIP_TOPAZ: - smumgr->smumgr_funcs = &iceland_smu_funcs; - break; - case CHIP_TONGA: - smumgr->smumgr_funcs = &tonga_smu_funcs; - break; - case CHIP_FIJI: - smumgr->smumgr_funcs = &fiji_smu_funcs; - break; - case CHIP_POLARIS11: - case CHIP_POLARIS10: - case CHIP_POLARIS12: - smumgr->smumgr_funcs = &polaris10_smu_funcs; - break; - default: - return -EINVAL; - } - break; - case AMDGPU_FAMILY_AI: - switch (smumgr->chip_id) { - case CHIP_VEGA10: - smumgr->smumgr_funcs = &vega10_smu_funcs; - break; - default: - return -EINVAL; - } - break; - case AMDGPU_FAMILY_RV: - switch (smumgr->chip_id) { - case CHIP_RAVEN: - smumgr->smumgr_funcs = &rv_smu_funcs; - break; - default: - return -EINVAL; - } - break; - default: - kfree(smumgr); - return -EINVAL; - } - - return 0; -} - -int smum_thermal_avfs_enable(struct pp_hwmgr *hwmgr, - void *input, void *output, void *storage, int result) -{ - if (NULL != hwmgr->smumgr->smumgr_funcs->thermal_avfs_enable) - return hwmgr->smumgr->smumgr_funcs->thermal_avfs_enable(hwmgr); + if (NULL != hwmgr->smumgr_funcs->thermal_avfs_enable) + return hwmgr->smumgr_funcs->thermal_avfs_enable(hwmgr); return 0; } -int smum_thermal_setup_fan_table(struct pp_hwmgr *hwmgr, - void *input, void *output, void *storage, int result) +int smum_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) { - if (NULL != hwmgr->smumgr->smumgr_funcs->thermal_setup_fan_table) - return hwmgr->smumgr->smumgr_funcs->thermal_setup_fan_table(hwmgr); + if (NULL != hwmgr->smumgr_funcs->thermal_setup_fan_table) + return hwmgr->smumgr_funcs->thermal_setup_fan_table(hwmgr); return 0; } @@ -135,8 +64,8 @@ int smum_thermal_setup_fan_table(struct pp_hwmgr *hwmgr, int smum_update_sclk_threshold(struct pp_hwmgr *hwmgr) { - if (NULL != hwmgr->smumgr->smumgr_funcs->update_sclk_threshold) - return hwmgr->smumgr->smumgr_funcs->update_sclk_threshold(hwmgr); + if (NULL != hwmgr->smumgr_funcs->update_sclk_threshold) + return hwmgr->smumgr_funcs->update_sclk_threshold(hwmgr); return 0; } @@ -144,163 +73,75 @@ int smum_update_sclk_threshold(struct pp_hwmgr *hwmgr) int smum_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type) { - if (NULL != hwmgr->smumgr->smumgr_funcs->update_smc_table) - return hwmgr->smumgr->smumgr_funcs->update_smc_table(hwmgr, type); + if (NULL != hwmgr->smumgr_funcs->update_smc_table) + return hwmgr->smumgr_funcs->update_smc_table(hwmgr, type); return 0; } -uint32_t smum_get_offsetof(struct pp_smumgr *smumgr, uint32_t type, uint32_t member) +uint32_t smum_get_offsetof(struct pp_hwmgr *hwmgr, uint32_t type, uint32_t member) { - if (NULL != smumgr->smumgr_funcs->get_offsetof) - return smumgr->smumgr_funcs->get_offsetof(type, member); + if (NULL != hwmgr->smumgr_funcs->get_offsetof) + return hwmgr->smumgr_funcs->get_offsetof(type, member); return 0; } int smum_process_firmware_header(struct pp_hwmgr *hwmgr) { - if (NULL != hwmgr->smumgr->smumgr_funcs->process_firmware_header) - return hwmgr->smumgr->smumgr_funcs->process_firmware_header(hwmgr); + if (NULL != hwmgr->smumgr_funcs->process_firmware_header) + return hwmgr->smumgr_funcs->process_firmware_header(hwmgr); return 0; } -int smum_get_argument(struct pp_smumgr *smumgr) +int smum_get_argument(struct pp_hwmgr *hwmgr) { - if (NULL != smumgr->smumgr_funcs->get_argument) - return smumgr->smumgr_funcs->get_argument(smumgr); + if (NULL != hwmgr->smumgr_funcs->get_argument) + return hwmgr->smumgr_funcs->get_argument(hwmgr); return 0; } -uint32_t smum_get_mac_definition(struct pp_smumgr *smumgr, uint32_t value) +uint32_t smum_get_mac_definition(struct pp_hwmgr *hwmgr, uint32_t value) { - if (NULL != smumgr->smumgr_funcs->get_mac_definition) - return smumgr->smumgr_funcs->get_mac_definition(value); + if (NULL != hwmgr->smumgr_funcs->get_mac_definition) + return hwmgr->smumgr_funcs->get_mac_definition(value); return 0; } -int smum_download_powerplay_table(struct pp_smumgr *smumgr, - void **table) +int smum_download_powerplay_table(struct pp_hwmgr *hwmgr, void **table) { - if (NULL != smumgr->smumgr_funcs->download_pptable_settings) - return smumgr->smumgr_funcs->download_pptable_settings(smumgr, + if (NULL != hwmgr->smumgr_funcs->download_pptable_settings) + return hwmgr->smumgr_funcs->download_pptable_settings(hwmgr, table); return 0; } -int smum_upload_powerplay_table(struct pp_smumgr *smumgr) +int smum_upload_powerplay_table(struct pp_hwmgr *hwmgr) { - if (NULL != smumgr->smumgr_funcs->upload_pptable_settings) - return smumgr->smumgr_funcs->upload_pptable_settings(smumgr); + if (NULL != hwmgr->smumgr_funcs->upload_pptable_settings) + return hwmgr->smumgr_funcs->upload_pptable_settings(hwmgr); return 0; } -int smum_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg) +int smum_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg) { - if (smumgr == NULL || smumgr->smumgr_funcs->send_msg_to_smc == NULL) + if (hwmgr == NULL || hwmgr->smumgr_funcs->send_msg_to_smc == NULL) return -EINVAL; - return smumgr->smumgr_funcs->send_msg_to_smc(smumgr, msg); + return hwmgr->smumgr_funcs->send_msg_to_smc(hwmgr, msg); } -int smum_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr, +int smum_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, uint16_t msg, uint32_t parameter) { - if (smumgr == NULL || - smumgr->smumgr_funcs->send_msg_to_smc_with_parameter == NULL) - return -EINVAL; - return smumgr->smumgr_funcs->send_msg_to_smc_with_parameter( - smumgr, msg, parameter); -} - -/* - * Returns once the part of the register indicated by the mask has - * reached the given value. - */ -int smum_wait_on_register(struct pp_smumgr *smumgr, - uint32_t index, - uint32_t value, uint32_t mask) -{ - uint32_t i; - uint32_t cur_value; - - if (smumgr == NULL || smumgr->device == NULL) - return -EINVAL; - - for (i = 0; i < smumgr->usec_timeout; i++) { - cur_value = cgs_read_register(smumgr->device, index); - if ((cur_value & mask) == (value & mask)) - break; - udelay(1); - } - - /* timeout means wrong logic*/ - if (i == smumgr->usec_timeout) - return -1; - - return 0; -} - -int smum_wait_for_register_unequal(struct pp_smumgr *smumgr, - uint32_t index, - uint32_t value, uint32_t mask) -{ - uint32_t i; - uint32_t cur_value; - - if (smumgr == NULL) + if (hwmgr == NULL || + hwmgr->smumgr_funcs->send_msg_to_smc_with_parameter == NULL) return -EINVAL; - - for (i = 0; i < smumgr->usec_timeout; i++) { - cur_value = cgs_read_register(smumgr->device, - index); - if ((cur_value & mask) != (value & mask)) - break; - udelay(1); - } - - /* timeout means wrong logic */ - if (i == smumgr->usec_timeout) - return -1; - - return 0; -} - - -/* - * Returns once the part of the register indicated by the mask - * has reached the given value.The indirect space is described by - * giving the memory-mapped index of the indirect index register. - */ -int smum_wait_on_indirect_register(struct pp_smumgr *smumgr, - uint32_t indirect_port, - uint32_t index, - uint32_t value, - uint32_t mask) -{ - if (smumgr == NULL || smumgr->device == NULL) - return -EINVAL; - - cgs_write_register(smumgr->device, indirect_port, index); - return smum_wait_on_register(smumgr, indirect_port + 1, - mask, value); -} - -void smum_wait_for_indirect_register_unequal( - struct pp_smumgr *smumgr, - uint32_t indirect_port, - uint32_t index, - uint32_t value, - uint32_t mask) -{ - if (smumgr == NULL || smumgr->device == NULL) - return; - cgs_write_register(smumgr->device, indirect_port, index); - smum_wait_for_register_unequal(smumgr, indirect_port + 1, - value, mask); + return hwmgr->smumgr_funcs->send_msg_to_smc_with_parameter( + hwmgr, msg, parameter); } int smu_allocate_memory(void *device, uint32_t size, @@ -316,7 +157,7 @@ int smu_allocate_memory(void *device, uint32_t size, return -EINVAL; ret = cgs_alloc_gpu_mem(device, type, size, byte_align, - 0, 0, (cgs_handle_t *)handle); + (cgs_handle_t *)handle); if (ret) return -ENOMEM; @@ -356,24 +197,24 @@ int smu_free_memory(void *device, void *handle) int smum_init_smc_table(struct pp_hwmgr *hwmgr) { - if (NULL != hwmgr->smumgr->smumgr_funcs->init_smc_table) - return hwmgr->smumgr->smumgr_funcs->init_smc_table(hwmgr); + if (NULL != hwmgr->smumgr_funcs->init_smc_table) + return hwmgr->smumgr_funcs->init_smc_table(hwmgr); return 0; } int smum_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) { - if (NULL != hwmgr->smumgr->smumgr_funcs->populate_all_graphic_levels) - return hwmgr->smumgr->smumgr_funcs->populate_all_graphic_levels(hwmgr); + if (NULL != hwmgr->smumgr_funcs->populate_all_graphic_levels) + return hwmgr->smumgr_funcs->populate_all_graphic_levels(hwmgr); return 0; } int smum_populate_all_memory_levels(struct pp_hwmgr *hwmgr) { - if (NULL != hwmgr->smumgr->smumgr_funcs->populate_all_memory_levels) - return hwmgr->smumgr->smumgr_funcs->populate_all_memory_levels(hwmgr); + if (NULL != hwmgr->smumgr_funcs->populate_all_memory_levels) + return hwmgr->smumgr_funcs->populate_all_memory_levels(hwmgr); return 0; } @@ -381,16 +222,16 @@ int smum_populate_all_memory_levels(struct pp_hwmgr *hwmgr) /*this interface is needed by island ci/vi */ int smum_initialize_mc_reg_table(struct pp_hwmgr *hwmgr) { - if (NULL != hwmgr->smumgr->smumgr_funcs->initialize_mc_reg_table) - return hwmgr->smumgr->smumgr_funcs->initialize_mc_reg_table(hwmgr); + if (NULL != hwmgr->smumgr_funcs->initialize_mc_reg_table) + return hwmgr->smumgr_funcs->initialize_mc_reg_table(hwmgr); return 0; } bool smum_is_dpm_running(struct pp_hwmgr *hwmgr) { - if (NULL != hwmgr->smumgr->smumgr_funcs->is_dpm_running) - return hwmgr->smumgr->smumgr_funcs->is_dpm_running(hwmgr); + if (NULL != hwmgr->smumgr_funcs->is_dpm_running) + return hwmgr->smumgr_funcs->is_dpm_running(hwmgr); return true; } @@ -398,17 +239,17 @@ bool smum_is_dpm_running(struct pp_hwmgr *hwmgr) int smum_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr, struct amd_pp_profile *request) { - if (hwmgr->smumgr->smumgr_funcs->populate_requested_graphic_levels) - return hwmgr->smumgr->smumgr_funcs->populate_requested_graphic_levels( + if (hwmgr->smumgr_funcs->populate_requested_graphic_levels) + return hwmgr->smumgr_funcs->populate_requested_graphic_levels( hwmgr, request); return 0; } -bool smum_is_hw_avfs_present(struct pp_smumgr *smumgr) +bool smum_is_hw_avfs_present(struct pp_hwmgr *hwmgr) { - if (smumgr->smumgr_funcs->is_hw_avfs_present) - return smumgr->smumgr_funcs->is_hw_avfs_present(smumgr); + if (hwmgr->smumgr_funcs->is_hw_avfs_present) + return hwmgr->smumgr_funcs->is_hw_avfs_present(hwmgr); return false; } diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smc.c b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smc.c index 65d3a48..1f720cc 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smc.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smc.c @@ -97,7 +97,7 @@ static const uint8_t tonga_clock_stretch_amount_conversion[2][6] = { */ -static int tonga_get_dependecy_volt_by_clk(struct pp_hwmgr *hwmgr, +static int tonga_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr, phm_ppt_v1_clock_voltage_dependency_table *allowed_clock_voltage_table, uint32_t clock, SMU_VoltageLevel *voltage, uint32_t *mvdd) { @@ -406,7 +406,7 @@ static int tonga_populate_smc_link_level(struct pp_hwmgr *hwmgr, SMU72_Discrete_ { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); struct smu7_dpm_table *dpm_table = &data->dpm_table; - struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smumgr->backend); + struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); uint32_t i; /* Index (dpm_table->pcie_speed_table.count) is reserved for PCIE boot level. */ @@ -539,7 +539,7 @@ static int tonga_populate_single_graphic_level(struct pp_hwmgr *hwmgr, result = tonga_calculate_sclk_params(hwmgr, engine_clock, graphic_level); /* populate graphics levels*/ - result = tonga_get_dependecy_volt_by_clk(hwmgr, + result = tonga_get_dependency_volt_by_clk(hwmgr, pptable_info->vdd_dep_on_sclk, engine_clock, &graphic_level->MinVoltage, &mvdd); PP_ASSERT_WITH_CODE((!result), @@ -598,7 +598,7 @@ static int tonga_populate_single_graphic_level(struct pp_hwmgr *hwmgr, int tonga_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smumgr->backend); + struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); struct smu7_dpm_table *dpm_table = &data->dpm_table; struct phm_ppt_v1_pcie_table *pcie_table = pptable_info->pcie_table; @@ -690,7 +690,7 @@ int tonga_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) smu_data->smc_state_table.GraphicsLevel[1].pcieDpmLevel = mid_pcie_level_enabled; } /* level count will send to smc once at init smc table and never change*/ - result = smu7_copy_bytes_to_smc(hwmgr->smumgr, level_array_address, + result = smu7_copy_bytes_to_smc(hwmgr, level_array_address, (uint8_t *)levels, (uint32_t)level_array_size, SMC_RAM_END); @@ -895,7 +895,7 @@ static int tonga_populate_single_memory_level( uint32_t mclk_strobe_mode_threshold = 40000; if (NULL != pptable_info->vdd_dep_on_mclk) { - result = tonga_get_dependecy_volt_by_clk(hwmgr, + result = tonga_get_dependency_volt_by_clk(hwmgr, pptable_info->vdd_dep_on_mclk, memory_clock, &memory_level->MinVoltage, &mvdd); @@ -1002,7 +1002,7 @@ int tonga_populate_all_memory_levels(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smumgr->backend); + (struct tonga_smumgr *)(hwmgr->smu_backend); struct smu7_dpm_table *dpm_table = &data->dpm_table; int result; @@ -1048,7 +1048,7 @@ int tonga_populate_all_memory_levels(struct pp_hwmgr *hwmgr) smu_data->smc_state_table.MemoryLevel[dpm_table->mclk_table.count-1].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH; /* level count will send to smc once at init smc table and never change*/ - result = smu7_copy_bytes_to_smc(hwmgr->smumgr, + result = smu7_copy_bytes_to_smc(hwmgr, level_array_address, (uint8_t *)levels, (uint32_t)level_array_size, SMC_RAM_END); @@ -1090,7 +1090,7 @@ static int tonga_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, { int result = 0; struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smumgr->backend); + (struct tonga_smumgr *)(hwmgr->smu_backend); const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); struct pp_atomctrl_clock_dividers_vi dividers; @@ -1454,7 +1454,7 @@ static int tonga_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smumgr->backend); + (struct tonga_smumgr *)(hwmgr->smu_backend); int result = 0; SMU72_Discrete_MCArbDramTimingTable arb_regs; uint32_t i, j; @@ -1475,7 +1475,7 @@ static int tonga_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) if (!result) { result = smu7_copy_bytes_to_smc( - hwmgr->smumgr, + hwmgr, smu_data->smu7_data.arb_table_start, (uint8_t *)&arb_regs, sizeof(SMU72_Discrete_MCArbDramTimingTable), @@ -1492,7 +1492,7 @@ static int tonga_populate_smc_boot_level(struct pp_hwmgr *hwmgr, int result = 0; struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smumgr->backend); + (struct tonga_smumgr *)(hwmgr->smu_backend); table->GraphicsBootLevel = 0; table->MemoryBootLevel = 0; @@ -1543,7 +1543,7 @@ static int tonga_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr) volt_with_cks, value; uint16_t clock_freq_u16; struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smumgr->backend); + (struct tonga_smumgr *)(hwmgr->smu_backend); uint8_t type, i, j, cks_setting, stretch_amount, stretch_amount2, volt_offset = 0; struct phm_ppt_v1_information *table_info = @@ -1782,9 +1782,9 @@ static int tonga_populate_vr_config(struct pp_hwmgr *hwmgr, * @param hwmgr the address of the powerplay hardware manager. * @return always 0 */ -static int tonga_init_arb_table_index(struct pp_smumgr *smumgr) +static int tonga_init_arb_table_index(struct pp_hwmgr *hwmgr) { - struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(smumgr->backend); + struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); uint32_t tmp; int result; @@ -1797,7 +1797,7 @@ static int tonga_init_arb_table_index(struct pp_smumgr *smumgr) * In reality this field should not be in that structure * but in a soft register. */ - result = smu7_read_smc_sram_dword(smumgr, + result = smu7_read_smc_sram_dword(hwmgr, smu_data->smu7_data.arb_table_start, &tmp, SMC_RAM_END); if (result != 0) @@ -1806,7 +1806,7 @@ static int tonga_init_arb_table_index(struct pp_smumgr *smumgr) tmp &= 0x00FFFFFF; tmp |= ((uint32_t)MC_CG_ARB_FREQ_F1) << 24; - return smu7_write_smc_sram_dword(smumgr, + return smu7_write_smc_sram_dword(hwmgr, smu_data->smu7_data.arb_table_start, tmp, SMC_RAM_END); } @@ -1814,7 +1814,7 @@ static int tonga_init_arb_table_index(struct pp_smumgr *smumgr) static int tonga_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) { struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smumgr->backend); + (struct tonga_smumgr *)(hwmgr->smu_backend); const struct tonga_pt_defaults *defaults = smu_data->power_tune_defaults; SMU72_Discrete_DpmTable *dpm_table = &(smu_data->smc_state_table); struct phm_ppt_v1_information *table_info = @@ -1838,7 +1838,7 @@ static int tonga_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) dpm_table->DTEAmbientTempBase = defaults->dte_ambient_temp_base; dpm_table->BAPM_TEMP_GRADIENT = - PP_HOST_TO_SMC_UL(defaults->bamp_temp_gradient); + PP_HOST_TO_SMC_UL(defaults->bapm_temp_gradient); pdef1 = defaults->bapmti_r; pdef2 = defaults->bapmti_rc; @@ -1861,7 +1861,7 @@ static int tonga_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) static int tonga_populate_svi_load_line(struct pp_hwmgr *hwmgr) { struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smumgr->backend); + (struct tonga_smumgr *)(hwmgr->smu_backend); const struct tonga_pt_defaults *defaults = smu_data->power_tune_defaults; smu_data->power_tune_table.SviLoadLineEn = defaults->svi_load_line_en; @@ -1876,7 +1876,7 @@ static int tonga_populate_tdc_limit(struct pp_hwmgr *hwmgr) { uint16_t tdc_limit; struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smumgr->backend); + (struct tonga_smumgr *)(hwmgr->smu_backend); const struct tonga_pt_defaults *defaults = smu_data->power_tune_defaults; struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); @@ -1897,11 +1897,11 @@ static int tonga_populate_tdc_limit(struct pp_hwmgr *hwmgr) static int tonga_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) { struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smumgr->backend); + (struct tonga_smumgr *)(hwmgr->smu_backend); const struct tonga_pt_defaults *defaults = smu_data->power_tune_defaults; uint32_t temp; - if (smu7_read_smc_sram_dword(hwmgr->smumgr, + if (smu7_read_smc_sram_dword(hwmgr, fuse_table_offset + offsetof(SMU72_Discrete_PmFuses, TdcWaterfallCtl), (uint32_t *)&temp, SMC_RAM_END)) @@ -1919,7 +1919,7 @@ static int tonga_populate_temperature_scaler(struct pp_hwmgr *hwmgr) { int i; struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smumgr->backend); + (struct tonga_smumgr *)(hwmgr->smu_backend); /* Currently not used. Set all to zero. */ for (i = 0; i < 16; i++) @@ -1930,7 +1930,7 @@ static int tonga_populate_temperature_scaler(struct pp_hwmgr *hwmgr) static int tonga_populate_fuzzy_fan(struct pp_hwmgr *hwmgr) { - struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smumgr->backend); + struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); if ((hwmgr->thermal_controller.advanceFanControlParameters. usFanOutputSensitivity & (1 << 15)) || @@ -1949,7 +1949,7 @@ static int tonga_populate_gnb_lpml(struct pp_hwmgr *hwmgr) { int i; struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smumgr->backend); + (struct tonga_smumgr *)(hwmgr->smu_backend); /* Currently not used. Set all to zero. */ for (i = 0; i < 16; i++) @@ -1958,15 +1958,10 @@ static int tonga_populate_gnb_lpml(struct pp_hwmgr *hwmgr) return 0; } -static int tonga_min_max_vgnb_lpml_id_from_bapm_vddc(struct pp_hwmgr *hwmgr) -{ - return 0; -} - static int tonga_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) { struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smumgr->backend); + (struct tonga_smumgr *)(hwmgr->smu_backend); struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); uint16_t hi_sidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd; @@ -1987,12 +1982,12 @@ static int tonga_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) static int tonga_populate_pm_fuses(struct pp_hwmgr *hwmgr) { struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smumgr->backend); + (struct tonga_smumgr *)(hwmgr->smu_backend); uint32_t pm_fuse_table_offset; if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PowerContainment)) { - if (smu7_read_smc_sram_dword(hwmgr->smumgr, + if (smu7_read_smc_sram_dword(hwmgr, SMU72_FIRMWARE_HEADER_LOCATION + offsetof(SMU72_Firmware_Header, PmFuseTable), &pm_fuse_table_offset, SMC_RAM_END)) @@ -2035,13 +2030,6 @@ static int tonga_populate_pm_fuses(struct pp_hwmgr *hwmgr) "Attempt to populate GnbLPML Failed !", return -EINVAL); - /* DW19 */ - if (tonga_min_max_vgnb_lpml_id_from_bapm_vddc(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate GnbLPML " - "Min and Max Vid Failed !", - return -EINVAL); - /* DW20 */ if (tonga_populate_bapm_vddc_base_leakage_sidd(hwmgr)) PP_ASSERT_WITH_CODE( @@ -2050,7 +2038,7 @@ static int tonga_populate_pm_fuses(struct pp_hwmgr *hwmgr) "Hi and Lo Sidd Failed !", return -EINVAL); - if (smu7_copy_bytes_to_smc(hwmgr->smumgr, pm_fuse_table_offset, + if (smu7_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset, (uint8_t *)&smu_data->power_tune_table, sizeof(struct SMU72_Discrete_PmFuses), SMC_RAM_END)) PP_ASSERT_WITH_CODE(false, @@ -2060,10 +2048,10 @@ static int tonga_populate_pm_fuses(struct pp_hwmgr *hwmgr) return 0; } -static int tonga_populate_mc_reg_address(struct pp_smumgr *smumgr, +static int tonga_populate_mc_reg_address(struct pp_hwmgr *hwmgr, SMU72_Discrete_MCRegisters *mc_reg_table) { - const struct tonga_smumgr *smu_data = (struct tonga_smumgr *)smumgr->backend; + const struct tonga_smumgr *smu_data = (struct tonga_smumgr *)hwmgr->smu_backend; uint32_t i, j; @@ -2104,12 +2092,12 @@ static void tonga_convert_mc_registers( } static int tonga_convert_mc_reg_table_entry_to_smc( - struct pp_smumgr *smumgr, + struct pp_hwmgr *hwmgr, const uint32_t memory_clock, SMU72_Discrete_MCRegisterSet *mc_reg_table_data ) { - struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(smumgr->backend); + struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); uint32_t i = 0; for (i = 0; i < smu_data->mc_reg_table.num_entries; i++) { @@ -2139,7 +2127,7 @@ static int tonga_convert_mc_reg_table_to_smc(struct pp_hwmgr *hwmgr, for (i = 0; i < data->dpm_table.mclk_table.count; i++) { res = tonga_convert_mc_reg_table_entry_to_smc( - hwmgr->smumgr, + hwmgr, data->dpm_table.mclk_table.dpm_levels[i].value, &mc_regs->data[i] ); @@ -2153,8 +2141,7 @@ static int tonga_convert_mc_reg_table_to_smc(struct pp_hwmgr *hwmgr, static int tonga_update_and_upload_mc_reg_table(struct pp_hwmgr *hwmgr) { - struct pp_smumgr *smumgr = hwmgr->smumgr; - struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(smumgr->backend); + struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); uint32_t address; int32_t result; @@ -2175,7 +2162,7 @@ static int tonga_update_and_upload_mc_reg_table(struct pp_hwmgr *hwmgr) (uint32_t)offsetof(SMU72_Discrete_MCRegisters, data[0]); return smu7_copy_bytes_to_smc( - hwmgr->smumgr, address, + hwmgr, address, (uint8_t *)&smu_data->mc_regs.data[0], sizeof(SMU72_Discrete_MCRegisterSet) * data->dpm_table.mclk_table.count, @@ -2185,11 +2172,10 @@ static int tonga_update_and_upload_mc_reg_table(struct pp_hwmgr *hwmgr) static int tonga_populate_initial_mc_reg_table(struct pp_hwmgr *hwmgr) { int result; - struct pp_smumgr *smumgr = hwmgr->smumgr; - struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(smumgr->backend); + struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); memset(&smu_data->mc_regs, 0x00, sizeof(SMU72_Discrete_MCRegisters)); - result = tonga_populate_mc_reg_address(smumgr, &(smu_data->mc_regs)); + result = tonga_populate_mc_reg_address(hwmgr, &(smu_data->mc_regs)); PP_ASSERT_WITH_CODE(!result, "Failed to initialize MCRegTable for the MC register addresses !", return result;); @@ -2199,13 +2185,13 @@ static int tonga_populate_initial_mc_reg_table(struct pp_hwmgr *hwmgr) "Failed to initialize MCRegTable for driver state !", return result;); - return smu7_copy_bytes_to_smc(smumgr, smu_data->smu7_data.mc_reg_table_start, + return smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.mc_reg_table_start, (uint8_t *)&smu_data->mc_regs, sizeof(SMU72_Discrete_MCRegisters), SMC_RAM_END); } static void tonga_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) { - struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smumgr->backend); + struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); @@ -2221,7 +2207,7 @@ static void tonga_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) static void tonga_save_default_power_profile(struct pp_hwmgr *hwmgr) { - struct tonga_smumgr *data = (struct tonga_smumgr *)(hwmgr->smumgr->backend); + struct tonga_smumgr *data = (struct tonga_smumgr *)(hwmgr->smu_backend); struct SMU72_Discrete_GraphicsLevel *levels = data->smc_state_table.GraphicsLevel; unsigned min_level = 1; @@ -2267,7 +2253,7 @@ int tonga_init_smc_table(struct pp_hwmgr *hwmgr) int result; struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smumgr->backend); + (struct tonga_smumgr *)(hwmgr->smu_backend); SMU72_Discrete_DpmTable *table = &(smu_data->smc_state_table); struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); @@ -2483,7 +2469,7 @@ int tonga_init_smc_table(struct pp_hwmgr *hwmgr) /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */ result = smu7_copy_bytes_to_smc( - hwmgr->smumgr, + hwmgr, smu_data->smu7_data.dpm_table_start + offsetof(SMU72_Discrete_DpmTable, SystemFlags), (uint8_t *)&(table->SystemFlags), sizeof(SMU72_Discrete_DpmTable) - 3 * sizeof(SMU72_PIDController), @@ -2492,7 +2478,7 @@ int tonga_init_smc_table(struct pp_hwmgr *hwmgr) PP_ASSERT_WITH_CODE(!result, "Failed to upload dpm data to SMC memory !", return result;); - result = tonga_init_arb_table_index(hwmgr->smumgr); + result = tonga_init_arb_table_index(hwmgr); PP_ASSERT_WITH_CODE(!result, "Failed to upload arb data to SMC memory !", return result); @@ -2521,7 +2507,7 @@ int tonga_init_smc_table(struct pp_hwmgr *hwmgr) int tonga_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) { struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smumgr->backend); + (struct tonga_smumgr *)(hwmgr->smu_backend); SMU72_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE }; uint32_t duty100; uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2; @@ -2600,7 +2586,7 @@ int tonga_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) fan_table.FanControl_GL_Flag = 1; - res = smu7_copy_bytes_to_smc(hwmgr->smumgr, + res = smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.fan_table_start, (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table), @@ -2625,7 +2611,7 @@ int tonga_update_sclk_threshold(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smumgr->backend); + (struct tonga_smumgr *)(hwmgr->smu_backend); int result = 0; uint32_t low_sclk_interrupt_threshold = 0; @@ -2642,7 +2628,7 @@ int tonga_update_sclk_threshold(struct pp_hwmgr *hwmgr) CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold); result = smu7_copy_bytes_to_smc( - hwmgr->smumgr, + hwmgr, smu_data->smu7_data.dpm_table_start + offsetof(SMU72_Discrete_DpmTable, LowSclkInterruptThreshold), @@ -2728,7 +2714,7 @@ uint32_t tonga_get_mac_definition(uint32_t value) static int tonga_update_uvd_smc_table(struct pp_hwmgr *hwmgr) { struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smumgr->backend); + (struct tonga_smumgr *)(hwmgr->smu_backend); uint32_t mm_boot_level_offset, mm_boot_level_value; struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); @@ -2753,7 +2739,7 @@ static int tonga_update_uvd_smc_table(struct pp_hwmgr *hwmgr) PHM_PlatformCaps_UVDDPM) || phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_UVDDPM_SetEnabledMask, (uint32_t)(1 << smu_data->smc_state_table.UvdBootLevel)); return 0; @@ -2762,7 +2748,7 @@ static int tonga_update_uvd_smc_table(struct pp_hwmgr *hwmgr) static int tonga_update_vce_smc_table(struct pp_hwmgr *hwmgr) { struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smumgr->backend); + (struct tonga_smumgr *)(hwmgr->smu_backend); uint32_t mm_boot_level_offset, mm_boot_level_value; struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); @@ -2784,7 +2770,7 @@ static int tonga_update_vce_smc_table(struct pp_hwmgr *hwmgr) if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_VCEDPM_SetEnabledMask, (uint32_t)1 << smu_data->smc_state_table.VceBootLevel); return 0; @@ -2792,7 +2778,7 @@ static int tonga_update_vce_smc_table(struct pp_hwmgr *hwmgr) static int tonga_update_samu_smc_table(struct pp_hwmgr *hwmgr) { - struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smumgr->backend); + struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); uint32_t mm_boot_level_offset, mm_boot_level_value; smu_data->smc_state_table.SamuBootLevel = 0; @@ -2810,7 +2796,7 @@ static int tonga_update_samu_smc_table(struct pp_hwmgr *hwmgr) if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SAMUDPM_SetEnabledMask, (uint32_t)(1 << smu_data->smc_state_table.SamuBootLevel)); return 0; @@ -2844,13 +2830,13 @@ int tonga_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type) int tonga_process_firmware_header(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smumgr->backend); + struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); uint32_t tmp; int result; bool error = false; - result = smu7_read_smc_sram_dword(hwmgr->smumgr, + result = smu7_read_smc_sram_dword(hwmgr, SMU72_FIRMWARE_HEADER_LOCATION + offsetof(SMU72_Firmware_Header, DpmTable), &tmp, SMC_RAM_END); @@ -2860,7 +2846,7 @@ int tonga_process_firmware_header(struct pp_hwmgr *hwmgr) error |= (result != 0); - result = smu7_read_smc_sram_dword(hwmgr->smumgr, + result = smu7_read_smc_sram_dword(hwmgr, SMU72_FIRMWARE_HEADER_LOCATION + offsetof(SMU72_Firmware_Header, SoftRegisters), &tmp, SMC_RAM_END); @@ -2873,7 +2859,7 @@ int tonga_process_firmware_header(struct pp_hwmgr *hwmgr) error |= (result != 0); - result = smu7_read_smc_sram_dword(hwmgr->smumgr, + result = smu7_read_smc_sram_dword(hwmgr, SMU72_FIRMWARE_HEADER_LOCATION + offsetof(SMU72_Firmware_Header, mcRegisterTable), &tmp, SMC_RAM_END); @@ -2881,7 +2867,7 @@ int tonga_process_firmware_header(struct pp_hwmgr *hwmgr) if (!result) smu_data->smu7_data.mc_reg_table_start = tmp; - result = smu7_read_smc_sram_dword(hwmgr->smumgr, + result = smu7_read_smc_sram_dword(hwmgr, SMU72_FIRMWARE_HEADER_LOCATION + offsetof(SMU72_Firmware_Header, FanTable), &tmp, SMC_RAM_END); @@ -2891,7 +2877,7 @@ int tonga_process_firmware_header(struct pp_hwmgr *hwmgr) error |= (result != 0); - result = smu7_read_smc_sram_dword(hwmgr->smumgr, + result = smu7_read_smc_sram_dword(hwmgr, SMU72_FIRMWARE_HEADER_LOCATION + offsetof(SMU72_Firmware_Header, mcArbDramTimingTable), &tmp, SMC_RAM_END); @@ -2901,7 +2887,7 @@ int tonga_process_firmware_header(struct pp_hwmgr *hwmgr) error |= (result != 0); - result = smu7_read_smc_sram_dword(hwmgr->smumgr, + result = smu7_read_smc_sram_dword(hwmgr, SMU72_FIRMWARE_HEADER_LOCATION + offsetof(SMU72_Firmware_Header, Version), &tmp, SMC_RAM_END); @@ -3170,7 +3156,7 @@ static int tonga_set_valid_flag(struct tonga_mc_reg_table *table) int tonga_initialize_mc_reg_table(struct pp_hwmgr *hwmgr) { int result; - struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smumgr->backend); + struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); pp_atomctrl_mc_reg_table *table; struct tonga_mc_reg_table *ni_table = &smu_data->mc_reg_table; uint8_t module_index = tonga_get_memory_modile_index(hwmgr); @@ -3253,7 +3239,7 @@ int tonga_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr, struct amd_pp_profile *request) { struct tonga_smumgr *smu_data = (struct tonga_smumgr *) - (hwmgr->smumgr->backend); + (hwmgr->smu_backend); struct SMU72_Discrete_GraphicsLevel *levels = smu_data->smc_state_table.GraphicsLevel; uint32_t array = smu_data->smu7_data.dpm_table_start + @@ -3270,6 +3256,6 @@ int tonga_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr, levels[i].DownHyst = request->down_hyst; } - return smu7_copy_bytes_to_smc(hwmgr->smumgr, array, (uint8_t *)levels, + return smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, array_size, SMC_RAM_END); } diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smc.h b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smc.h index 962860f..9d6a78a 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smc.h +++ b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smc.h @@ -40,7 +40,7 @@ struct tonga_pt_defaults { uint8_t tdc_waterfall_ctl; uint8_t dte_ambient_temp_base; uint32_t display_cac; - uint32_t bamp_temp_gradient; + uint32_t bapm_temp_gradient; uint16_t bapmti_r[SMU72_DTE_ITERATIONS * SMU72_DTE_SOURCES * SMU72_DTE_SINKS]; uint16_t bapmti_rc[SMU72_DTE_ITERATIONS * SMU72_DTE_SOURCES * SMU72_DTE_SINKS]; }; diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c index c35f4c3..d22cf21 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c @@ -37,125 +37,125 @@ #include "smu7_smumgr.h" -static int tonga_start_in_protection_mode(struct pp_smumgr *smumgr) +static int tonga_start_in_protection_mode(struct pp_hwmgr *hwmgr) { int result; /* Assert reset */ - SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_RESET_CNTL, rst_reg, 1); - result = smu7_upload_smu_firmware_image(smumgr); + result = smu7_upload_smu_firmware_image(hwmgr); if (result) return result; /* Clear status */ - cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC, + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMU_STATUS, 0); /* Enable clock */ - SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); /* De-assert reset */ - SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_RESET_CNTL, rst_reg, 0); /* Set SMU Auto Start */ - SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMU_INPUT_DATA, AUTO_START, 1); /* Clear firmware interrupt enable flag */ - cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC, + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixFIRMWARE_FLAGS, 0); - SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, SMC_IND, + PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, RCU_UC_EVENTS, INTERRUPTS_ENABLED, 1); /** * Call Test SMU message with 0x20000 offset to trigger SMU start */ - smu7_send_msg_to_smc_offset(smumgr); + smu7_send_msg_to_smc_offset(hwmgr); /* Wait for done bit to be set */ - SMUM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(smumgr, SMC_IND, + PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND, SMU_STATUS, SMU_DONE, 0); /* Check pass/failed indicator */ - if (1 != SMUM_READ_VFPF_INDIRECT_FIELD(smumgr->device, + if (1 != PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMU_STATUS, SMU_PASS)) { pr_err("SMU Firmware start failed\n"); return -EINVAL; } /* Wait for firmware to initialize */ - SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, SMC_IND, + PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1); return 0; } -static int tonga_start_in_non_protection_mode(struct pp_smumgr *smumgr) +static int tonga_start_in_non_protection_mode(struct pp_hwmgr *hwmgr) { int result = 0; /* wait for smc boot up */ - SMUM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(smumgr, SMC_IND, + PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND, RCU_UC_EVENTS, boot_seq_done, 0); /*Clear firmware interrupt enable flag*/ - cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC, + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixFIRMWARE_FLAGS, 0); - SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_RESET_CNTL, rst_reg, 1); - result = smu7_upload_smu_firmware_image(smumgr); + result = smu7_upload_smu_firmware_image(hwmgr); if (result != 0) return result; /* Set smc instruct start point at 0x0 */ - smu7_program_jump_on_start(smumgr); + smu7_program_jump_on_start(hwmgr); - SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); /*De-assert reset*/ - SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_RESET_CNTL, rst_reg, 0); /* Wait for firmware to initialize */ - SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, SMC_IND, + PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1); return result; } -static int tonga_start_smu(struct pp_smumgr *smumgr) +static int tonga_start_smu(struct pp_hwmgr *hwmgr) { int result; /* Only start SMC if SMC RAM is not running */ - if (!(smu7_is_smc_ram_running(smumgr) || - cgs_is_virtualization_enabled(smumgr->device))) { + if (!(smu7_is_smc_ram_running(hwmgr) || + cgs_is_virtualization_enabled(hwmgr->device))) { /*Check if SMU is running in protected mode*/ - if (0 == SMUM_READ_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + if (0 == PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMU_FIRMWARE, SMU_MODE)) { - result = tonga_start_in_non_protection_mode(smumgr); + result = tonga_start_in_non_protection_mode(hwmgr); if (result) return result; } else { - result = tonga_start_in_protection_mode(smumgr); + result = tonga_start_in_protection_mode(hwmgr); if (result) return result; } } - result = smu7_request_smu_load_fw(smumgr); + result = smu7_request_smu_load_fw(hwmgr); return result; } @@ -167,7 +167,7 @@ static int tonga_start_smu(struct pp_smumgr *smumgr) * @param smcAddress the address in the SMC RAM to access. * @param value to write to the SMC SRAM. */ -static int tonga_smu_init(struct pp_smumgr *smumgr) +static int tonga_smu_init(struct pp_hwmgr *hwmgr) { struct tonga_smumgr *tonga_priv = NULL; int i; @@ -176,9 +176,9 @@ static int tonga_smu_init(struct pp_smumgr *smumgr) if (tonga_priv == NULL) return -ENOMEM; - smumgr->backend = tonga_priv; + hwmgr->smu_backend = tonga_priv; - if (smu7_init(smumgr)) + if (smu7_init(hwmgr)) return -EINVAL; for (i = 0; i < SMU72_MAX_LEVELS_GRAPHICS; i++) diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c index 408514c..2f979fb 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c @@ -53,20 +53,20 @@ #define smnMP0_FW_INTF 0x3010104 #define smnMP1_PUB_CTRL 0x3010b14 -static bool vega10_is_smc_ram_running(struct pp_smumgr *smumgr) +static bool vega10_is_smc_ram_running(struct pp_hwmgr *hwmgr) { uint32_t mp1_fw_flags, reg; reg = soc15_get_register_offset(NBIF_HWID, 0, mmPCIE_INDEX2_BASE_IDX, mmPCIE_INDEX2); - cgs_write_register(smumgr->device, reg, + cgs_write_register(hwmgr->device, reg, (MP1_Public | (smnMP1_FIRMWARE_FLAGS & 0xffffffff))); reg = soc15_get_register_offset(NBIF_HWID, 0, mmPCIE_DATA2_BASE_IDX, mmPCIE_DATA2); - mp1_fw_flags = cgs_read_register(smumgr->device, reg); + mp1_fw_flags = cgs_read_register(hwmgr->device, reg); if (mp1_fw_flags & MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK) return true; @@ -80,20 +80,20 @@ static bool vega10_is_smc_ram_running(struct pp_smumgr *smumgr) * @param smumgr the address of the powerplay hardware manager. * @return TRUE SMC has responded, FALSE otherwise. */ -static uint32_t vega10_wait_for_response(struct pp_smumgr *smumgr) +static uint32_t vega10_wait_for_response(struct pp_hwmgr *hwmgr) { uint32_t reg; - if (!vega10_is_smc_ram_running(smumgr)) + if (!vega10_is_smc_ram_running(hwmgr)) return -EINVAL; reg = soc15_get_register_offset(MP1_HWID, 0, mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90); - smum_wait_for_register_unequal(smumgr, reg, + phm_wait_for_register_unequal(hwmgr, reg, 0, MP1_C2PMSG_90__CONTENT_MASK); - return cgs_read_register(smumgr->device, reg); + return cgs_read_register(hwmgr->device, reg); } /* @@ -102,43 +102,43 @@ static uint32_t vega10_wait_for_response(struct pp_smumgr *smumgr) * @param msg the message to send. * @return Always return 0. */ -int vega10_send_msg_to_smc_without_waiting(struct pp_smumgr *smumgr, +int vega10_send_msg_to_smc_without_waiting(struct pp_hwmgr *hwmgr, uint16_t msg) { uint32_t reg; - if (!vega10_is_smc_ram_running(smumgr)) + if (!vega10_is_smc_ram_running(hwmgr)) return -EINVAL; reg = soc15_get_register_offset(MP1_HWID, 0, mmMP1_SMN_C2PMSG_66_BASE_IDX, mmMP1_SMN_C2PMSG_66); - cgs_write_register(smumgr->device, reg, msg); + cgs_write_register(hwmgr->device, reg, msg); return 0; } /* * Send a message to the SMC, and wait for its response. - * @param smumgr the address of the powerplay hardware manager. + * @param hwmgr the address of the powerplay hardware manager. * @param msg the message to send. * @return Always return 0. */ -int vega10_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg) +int vega10_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg) { uint32_t reg; - if (!vega10_is_smc_ram_running(smumgr)) + if (!vega10_is_smc_ram_running(hwmgr)) return -EINVAL; - vega10_wait_for_response(smumgr); + vega10_wait_for_response(hwmgr); reg = soc15_get_register_offset(MP1_HWID, 0, mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90); - cgs_write_register(smumgr->device, reg, 0); + cgs_write_register(hwmgr->device, reg, 0); - vega10_send_msg_to_smc_without_waiting(smumgr, msg); + vega10_send_msg_to_smc_without_waiting(hwmgr, msg); - if (vega10_wait_for_response(smumgr) != 1) + if (vega10_wait_for_response(hwmgr) != 1) pr_err("Failed to send message: 0x%x\n", msg); return 0; @@ -146,32 +146,32 @@ int vega10_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg) /* * Send a message to the SMC with parameter - * @param smumgr: the address of the powerplay hardware manager. + * @param hwmgr: the address of the powerplay hardware manager. * @param msg: the message to send. * @param parameter: the parameter to send * @return Always return 0. */ -int vega10_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr, +int vega10_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, uint16_t msg, uint32_t parameter) { uint32_t reg; - if (!vega10_is_smc_ram_running(smumgr)) + if (!vega10_is_smc_ram_running(hwmgr)) return -EINVAL; - vega10_wait_for_response(smumgr); + vega10_wait_for_response(hwmgr); reg = soc15_get_register_offset(MP1_HWID, 0, mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90); - cgs_write_register(smumgr->device, reg, 0); + cgs_write_register(hwmgr->device, reg, 0); reg = soc15_get_register_offset(MP1_HWID, 0, mmMP1_SMN_C2PMSG_82_BASE_IDX, mmMP1_SMN_C2PMSG_82); - cgs_write_register(smumgr->device, reg, parameter); + cgs_write_register(hwmgr->device, reg, parameter); - vega10_send_msg_to_smc_without_waiting(smumgr, msg); + vega10_send_msg_to_smc_without_waiting(hwmgr, msg); - if (vega10_wait_for_response(smumgr) != 1) + if (vega10_wait_for_response(hwmgr) != 1) pr_err("Failed to send message: 0x%x\n", msg); return 0; @@ -180,51 +180,51 @@ int vega10_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr, /* * Send a message to the SMC with parameter, do not wait for response - * @param smumgr: the address of the powerplay hardware manager. + * @param hwmgr: the address of the powerplay hardware manager. * @param msg: the message to send. * @param parameter: the parameter to send * @return The response that came from the SMC. */ int vega10_send_msg_to_smc_with_parameter_without_waiting( - struct pp_smumgr *smumgr, uint16_t msg, uint32_t parameter) + struct pp_hwmgr *hwmgr, uint16_t msg, uint32_t parameter) { uint32_t reg; reg = soc15_get_register_offset(MP1_HWID, 0, mmMP1_SMN_C2PMSG_82_BASE_IDX, mmMP1_SMN_C2PMSG_82); - cgs_write_register(smumgr->device, reg, parameter); + cgs_write_register(hwmgr->device, reg, parameter); - return vega10_send_msg_to_smc_without_waiting(smumgr, msg); + return vega10_send_msg_to_smc_without_waiting(hwmgr, msg); } /* * Retrieve an argument from SMC. - * @param smumgr the address of the powerplay hardware manager. + * @param hwmgr the address of the powerplay hardware manager. * @param arg pointer to store the argument from SMC. * @return Always return 0. */ -int vega10_read_arg_from_smc(struct pp_smumgr *smumgr, uint32_t *arg) +int vega10_read_arg_from_smc(struct pp_hwmgr *hwmgr, uint32_t *arg) { uint32_t reg; reg = soc15_get_register_offset(MP1_HWID, 0, mmMP1_SMN_C2PMSG_82_BASE_IDX, mmMP1_SMN_C2PMSG_82); - *arg = cgs_read_register(smumgr->device, reg); + *arg = cgs_read_register(hwmgr->device, reg); return 0; } /* * Copy table from SMC into driver FB - * @param smumgr the address of the SMC manager + * @param hwmgr the address of the HW manager * @param table_id the driver's table ID to copy from */ -int vega10_copy_table_from_smc(struct pp_smumgr *smumgr, +int vega10_copy_table_from_smc(struct pp_hwmgr *hwmgr, uint8_t *table, int16_t table_id) { struct vega10_smumgr *priv = - (struct vega10_smumgr *)(smumgr->backend); + (struct vega10_smumgr *)(hwmgr->smu_backend); PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE, "Invalid SMU Table ID!", return -EINVAL); @@ -232,16 +232,16 @@ int vega10_copy_table_from_smc(struct pp_smumgr *smumgr, "Invalid SMU Table version!", return -EINVAL); PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0, "Invalid SMU Table Length!", return -EINVAL); - PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(smumgr, + PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetDriverDramAddrHigh, priv->smu_tables.entry[table_id].table_addr_high) == 0, "[CopyTableFromSMC] Attempt to Set Dram Addr High Failed!", return -EINVAL); - PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(smumgr, + PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetDriverDramAddrLow, priv->smu_tables.entry[table_id].table_addr_low) == 0, "[CopyTableFromSMC] Attempt to Set Dram Addr Low Failed!", return -EINVAL); - PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(smumgr, + PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_TransferTableSmu2Dram, priv->smu_tables.entry[table_id].table_id) == 0, "[CopyTableFromSMC] Attempt to Transfer Table From SMU Failed!", @@ -255,14 +255,14 @@ int vega10_copy_table_from_smc(struct pp_smumgr *smumgr, /* * Copy table from Driver FB into SMC - * @param smumgr the address of the SMC manager + * @param hwmgr the address of the HW manager * @param table_id the table to copy from */ -int vega10_copy_table_to_smc(struct pp_smumgr *smumgr, +int vega10_copy_table_to_smc(struct pp_hwmgr *hwmgr, uint8_t *table, int16_t table_id) { struct vega10_smumgr *priv = - (struct vega10_smumgr *)(smumgr->backend); + (struct vega10_smumgr *)(hwmgr->smu_backend); PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE, "Invalid SMU Table ID!", return -EINVAL); @@ -274,17 +274,17 @@ int vega10_copy_table_to_smc(struct pp_smumgr *smumgr, memcpy(priv->smu_tables.entry[table_id].table, table, priv->smu_tables.entry[table_id].size); - PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(smumgr, + PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetDriverDramAddrHigh, priv->smu_tables.entry[table_id].table_addr_high) == 0, "[CopyTableToSMC] Attempt to Set Dram Addr High Failed!", return -EINVAL;); - PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(smumgr, + PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetDriverDramAddrLow, priv->smu_tables.entry[table_id].table_addr_low) == 0, "[CopyTableToSMC] Attempt to Set Dram Addr Low Failed!", return -EINVAL); - PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(smumgr, + PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_TransferTableDram2Smu, priv->smu_tables.entry[table_id].table_id) == 0, "[CopyTableToSMC] Attempt to Transfer Table To SMU Failed!", @@ -293,87 +293,87 @@ int vega10_copy_table_to_smc(struct pp_smumgr *smumgr, return 0; } -int vega10_save_vft_table(struct pp_smumgr *smumgr, uint8_t *avfs_table) +int vega10_save_vft_table(struct pp_hwmgr *hwmgr, uint8_t *avfs_table) { PP_ASSERT_WITH_CODE(avfs_table, "No access to SMC AVFS Table", return -EINVAL); - return vega10_copy_table_from_smc(smumgr, avfs_table, AVFSTABLE); + return vega10_copy_table_from_smc(hwmgr, avfs_table, AVFSTABLE); } -int vega10_restore_vft_table(struct pp_smumgr *smumgr, uint8_t *avfs_table) +int vega10_restore_vft_table(struct pp_hwmgr *hwmgr, uint8_t *avfs_table) { PP_ASSERT_WITH_CODE(avfs_table, "No access to SMC AVFS Table", return -EINVAL); - return vega10_copy_table_to_smc(smumgr, avfs_table, AVFSTABLE); + return vega10_copy_table_to_smc(hwmgr, avfs_table, AVFSTABLE); } -int vega10_enable_smc_features(struct pp_smumgr *smumgr, +int vega10_enable_smc_features(struct pp_hwmgr *hwmgr, bool enable, uint32_t feature_mask) { int msg = enable ? PPSMC_MSG_EnableSmuFeatures : PPSMC_MSG_DisableSmuFeatures; - return vega10_send_msg_to_smc_with_parameter(smumgr, + return vega10_send_msg_to_smc_with_parameter(hwmgr, msg, feature_mask); } -int vega10_get_smc_features(struct pp_smumgr *smumgr, +int vega10_get_smc_features(struct pp_hwmgr *hwmgr, uint32_t *features_enabled) { if (features_enabled == NULL) return -EINVAL; - if (!vega10_send_msg_to_smc(smumgr, + if (!vega10_send_msg_to_smc(hwmgr, PPSMC_MSG_GetEnabledSmuFeatures)) { - vega10_read_arg_from_smc(smumgr, features_enabled); + vega10_read_arg_from_smc(hwmgr, features_enabled); return 0; } return -EINVAL; } -int vega10_set_tools_address(struct pp_smumgr *smumgr) +int vega10_set_tools_address(struct pp_hwmgr *hwmgr) { struct vega10_smumgr *priv = - (struct vega10_smumgr *)(smumgr->backend); + (struct vega10_smumgr *)(hwmgr->smu_backend); if (priv->smu_tables.entry[TOOLSTABLE].table_addr_high || priv->smu_tables.entry[TOOLSTABLE].table_addr_low) { - if (!vega10_send_msg_to_smc_with_parameter(smumgr, + if (!vega10_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetToolsDramAddrHigh, priv->smu_tables.entry[TOOLSTABLE].table_addr_high)) - vega10_send_msg_to_smc_with_parameter(smumgr, + vega10_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetToolsDramAddrLow, priv->smu_tables.entry[TOOLSTABLE].table_addr_low); } return 0; } -static int vega10_verify_smc_interface(struct pp_smumgr *smumgr) +static int vega10_verify_smc_interface(struct pp_hwmgr *hwmgr) { uint32_t smc_driver_if_version; struct cgs_system_info sys_info = {0}; uint32_t dev_id; uint32_t rev_id; - PP_ASSERT_WITH_CODE(!vega10_send_msg_to_smc(smumgr, + PP_ASSERT_WITH_CODE(!vega10_send_msg_to_smc(hwmgr, PPSMC_MSG_GetDriverIfVersion), "Attempt to get SMC IF Version Number Failed!", return -EINVAL); - vega10_read_arg_from_smc(smumgr, &smc_driver_if_version); + vega10_read_arg_from_smc(hwmgr, &smc_driver_if_version); sys_info.size = sizeof(struct cgs_system_info); sys_info.info_id = CGS_SYSTEM_INFO_PCIE_DEV; - cgs_query_system_info(smumgr->device, &sys_info); + cgs_query_system_info(hwmgr->device, &sys_info); dev_id = (uint32_t)sys_info.value; sys_info.size = sizeof(struct cgs_system_info); sys_info.info_id = CGS_SYSTEM_INFO_PCIE_REV; - cgs_query_system_info(smumgr->device, &sys_info); + cgs_query_system_info(hwmgr->device, &sys_info); rev_id = (uint32_t)sys_info.value; if (!((dev_id == 0x687f) && @@ -392,7 +392,7 @@ static int vega10_verify_smc_interface(struct pp_smumgr *smumgr) return 0; } -static int vega10_smu_init(struct pp_smumgr *smumgr) +static int vega10_smu_init(struct pp_hwmgr *hwmgr) { struct vega10_smumgr *priv; uint64_t mc_addr; @@ -401,7 +401,7 @@ static int vega10_smu_init(struct pp_smumgr *smumgr) int ret; struct cgs_firmware_info info = {0}; - ret = cgs_get_firmware_info(smumgr->device, + ret = cgs_get_firmware_info(hwmgr->device, smu7_convert_fw_type_to_cgs(UCODE_ID_SMU), &info); if (ret || !info.kptr) @@ -412,10 +412,10 @@ static int vega10_smu_init(struct pp_smumgr *smumgr) if (!priv) return -ENOMEM; - smumgr->backend = priv; + hwmgr->smu_backend = priv; /* allocate space for pptable */ - smu_allocate_memory(smumgr->device, + smu_allocate_memory(hwmgr->device, sizeof(PPTable_t), CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB, PAGE_SIZE, @@ -425,8 +425,8 @@ static int vega10_smu_init(struct pp_smumgr *smumgr) PP_ASSERT_WITH_CODE(kaddr, "[vega10_smu_init] Out of memory for pptable.", - kfree(smumgr->backend); - cgs_free_gpu_mem(smumgr->device, + kfree(hwmgr->smu_backend); + cgs_free_gpu_mem(hwmgr->device, (cgs_handle_t)handle); return -EINVAL); @@ -441,7 +441,7 @@ static int vega10_smu_init(struct pp_smumgr *smumgr) priv->smu_tables.entry[PPTABLE].handle = handle; /* allocate space for watermarks table */ - smu_allocate_memory(smumgr->device, + smu_allocate_memory(hwmgr->device, sizeof(Watermarks_t), CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB, PAGE_SIZE, @@ -451,10 +451,10 @@ static int vega10_smu_init(struct pp_smumgr *smumgr) PP_ASSERT_WITH_CODE(kaddr, "[vega10_smu_init] Out of memory for wmtable.", - kfree(smumgr->backend); - cgs_free_gpu_mem(smumgr->device, + kfree(hwmgr->smu_backend); + cgs_free_gpu_mem(hwmgr->device, (cgs_handle_t)priv->smu_tables.entry[PPTABLE].handle); - cgs_free_gpu_mem(smumgr->device, + cgs_free_gpu_mem(hwmgr->device, (cgs_handle_t)handle); return -EINVAL); @@ -469,7 +469,7 @@ static int vega10_smu_init(struct pp_smumgr *smumgr) priv->smu_tables.entry[WMTABLE].handle = handle; /* allocate space for AVFS table */ - smu_allocate_memory(smumgr->device, + smu_allocate_memory(hwmgr->device, sizeof(AvfsTable_t), CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB, PAGE_SIZE, @@ -479,12 +479,12 @@ static int vega10_smu_init(struct pp_smumgr *smumgr) PP_ASSERT_WITH_CODE(kaddr, "[vega10_smu_init] Out of memory for avfs table.", - kfree(smumgr->backend); - cgs_free_gpu_mem(smumgr->device, + kfree(hwmgr->smu_backend); + cgs_free_gpu_mem(hwmgr->device, (cgs_handle_t)priv->smu_tables.entry[PPTABLE].handle); - cgs_free_gpu_mem(smumgr->device, + cgs_free_gpu_mem(hwmgr->device, (cgs_handle_t)priv->smu_tables.entry[WMTABLE].handle); - cgs_free_gpu_mem(smumgr->device, + cgs_free_gpu_mem(hwmgr->device, (cgs_handle_t)handle); return -EINVAL); @@ -500,7 +500,7 @@ static int vega10_smu_init(struct pp_smumgr *smumgr) tools_size = 0x19000; if (tools_size) { - smu_allocate_memory(smumgr->device, + smu_allocate_memory(hwmgr->device, tools_size, CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB, PAGE_SIZE, @@ -522,7 +522,7 @@ static int vega10_smu_init(struct pp_smumgr *smumgr) } /* allocate space for AVFS Fuse table */ - smu_allocate_memory(smumgr->device, + smu_allocate_memory(hwmgr->device, sizeof(AvfsFuseOverride_t), CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB, PAGE_SIZE, @@ -532,16 +532,16 @@ static int vega10_smu_init(struct pp_smumgr *smumgr) PP_ASSERT_WITH_CODE(kaddr, "[vega10_smu_init] Out of memory for avfs fuse table.", - kfree(smumgr->backend); - cgs_free_gpu_mem(smumgr->device, + kfree(hwmgr->smu_backend); + cgs_free_gpu_mem(hwmgr->device, (cgs_handle_t)priv->smu_tables.entry[PPTABLE].handle); - cgs_free_gpu_mem(smumgr->device, + cgs_free_gpu_mem(hwmgr->device, (cgs_handle_t)priv->smu_tables.entry[WMTABLE].handle); - cgs_free_gpu_mem(smumgr->device, + cgs_free_gpu_mem(hwmgr->device, (cgs_handle_t)priv->smu_tables.entry[AVFSTABLE].handle); - cgs_free_gpu_mem(smumgr->device, + cgs_free_gpu_mem(hwmgr->device, (cgs_handle_t)priv->smu_tables.entry[TOOLSTABLE].handle); - cgs_free_gpu_mem(smumgr->device, + cgs_free_gpu_mem(hwmgr->device, (cgs_handle_t)handle); return -EINVAL); @@ -558,36 +558,36 @@ static int vega10_smu_init(struct pp_smumgr *smumgr) return 0; } -static int vega10_smu_fini(struct pp_smumgr *smumgr) +static int vega10_smu_fini(struct pp_hwmgr *hwmgr) { struct vega10_smumgr *priv = - (struct vega10_smumgr *)(smumgr->backend); + (struct vega10_smumgr *)(hwmgr->smu_backend); if (priv) { - cgs_free_gpu_mem(smumgr->device, + cgs_free_gpu_mem(hwmgr->device, (cgs_handle_t)priv->smu_tables.entry[PPTABLE].handle); - cgs_free_gpu_mem(smumgr->device, + cgs_free_gpu_mem(hwmgr->device, (cgs_handle_t)priv->smu_tables.entry[WMTABLE].handle); - cgs_free_gpu_mem(smumgr->device, + cgs_free_gpu_mem(hwmgr->device, (cgs_handle_t)priv->smu_tables.entry[AVFSTABLE].handle); if (priv->smu_tables.entry[TOOLSTABLE].table) - cgs_free_gpu_mem(smumgr->device, + cgs_free_gpu_mem(hwmgr->device, (cgs_handle_t)priv->smu_tables.entry[TOOLSTABLE].handle); - cgs_free_gpu_mem(smumgr->device, + cgs_free_gpu_mem(hwmgr->device, (cgs_handle_t)priv->smu_tables.entry[AVFSFUSETABLE].handle); - kfree(smumgr->backend); - smumgr->backend = NULL; + kfree(hwmgr->smu_backend); + hwmgr->smu_backend = NULL; } return 0; } -static int vega10_start_smu(struct pp_smumgr *smumgr) +static int vega10_start_smu(struct pp_hwmgr *hwmgr) { - PP_ASSERT_WITH_CODE(!vega10_verify_smc_interface(smumgr), + PP_ASSERT_WITH_CODE(!vega10_verify_smc_interface(hwmgr), "Failed to verify SMC interface!", return -EINVAL); - vega10_set_tools_address(smumgr); + vega10_set_tools_address(hwmgr); return 0; } diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.h index 821425c..0695455 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.h +++ b/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.h @@ -52,19 +52,19 @@ struct vega10_smumgr { struct smu_table_array smu_tables; }; -int vega10_read_arg_from_smc(struct pp_smumgr *smumgr, uint32_t *arg); -int vega10_copy_table_from_smc(struct pp_smumgr *smumgr, +int vega10_read_arg_from_smc(struct pp_hwmgr *hwmgr, uint32_t *arg); +int vega10_copy_table_from_smc(struct pp_hwmgr *hwmgr, uint8_t *table, int16_t table_id); -int vega10_copy_table_to_smc(struct pp_smumgr *smumgr, +int vega10_copy_table_to_smc(struct pp_hwmgr *hwmgr, uint8_t *table, int16_t table_id); -int vega10_enable_smc_features(struct pp_smumgr *smumgr, +int vega10_enable_smc_features(struct pp_hwmgr *hwmgr, bool enable, uint32_t feature_mask); -int vega10_get_smc_features(struct pp_smumgr *smumgr, +int vega10_get_smc_features(struct pp_hwmgr *hwmgr, uint32_t *features_enabled); -int vega10_save_vft_table(struct pp_smumgr *smumgr, uint8_t *avfs_table); -int vega10_restore_vft_table(struct pp_smumgr *smumgr, uint8_t *avfs_table); +int vega10_save_vft_table(struct pp_hwmgr *hwmgr, uint8_t *avfs_table); +int vega10_restore_vft_table(struct pp_hwmgr *hwmgr, uint8_t *avfs_table); -int vega10_set_tools_address(struct pp_smumgr *smumgr); +int vega10_set_tools_address(struct pp_hwmgr *hwmgr); #endif diff --git a/drivers/gpu/drm/arc/arcpgu_drv.c b/drivers/gpu/drm/arc/arcpgu_drv.c index 289eda5..074fd4e 100644 --- a/drivers/gpu/drm/arc/arcpgu_drv.c +++ b/drivers/gpu/drm/arc/arcpgu_drv.c @@ -18,6 +18,7 @@ #include <drm/drm_crtc_helper.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_atomic_helper.h> #include <linux/of_reserved_mem.h> @@ -32,7 +33,7 @@ static void arcpgu_fb_output_poll_changed(struct drm_device *dev) } static const struct drm_mode_config_funcs arcpgu_drm_modecfg_funcs = { - .fb_create = drm_fb_cma_create, + .fb_create = drm_gem_fb_create, .output_poll_changed = arcpgu_fb_output_poll_changed, .atomic_check = drm_atomic_helper_check, .atomic_commit = drm_atomic_helper_commit, diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c index f9bda7b..764d0c8 100644 --- a/drivers/gpu/drm/arm/hdlcd_drv.c +++ b/drivers/gpu/drm/arm/hdlcd_drv.c @@ -25,6 +25,7 @@ #include <drm/drm_fb_helper.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_of.h> #include "hdlcd_drv.h" @@ -106,7 +107,7 @@ static void hdlcd_fb_output_poll_changed(struct drm_device *drm) } static const struct drm_mode_config_funcs hdlcd_mode_config_funcs = { - .fb_create = drm_fb_cma_create, + .fb_create = drm_gem_fb_create, .output_poll_changed = hdlcd_fb_output_poll_changed, .atomic_check = drm_atomic_helper_check, .atomic_commit = drm_atomic_helper_commit, diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c index 1a57cc2..b894466 100644 --- a/drivers/gpu/drm/arm/malidp_drv.c +++ b/drivers/gpu/drm/arm/malidp_drv.c @@ -26,6 +26,7 @@ #include <drm/drm_crtc_helper.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_of.h> #include "malidp_drv.h" @@ -249,7 +250,7 @@ static const struct drm_mode_config_helper_funcs malidp_mode_config_helpers = { }; static const struct drm_mode_config_funcs malidp_mode_config_funcs = { - .fb_create = drm_fb_cma_create, + .fb_create = drm_gem_fb_create, .output_poll_changed = malidp_output_poll_changed, .atomic_check = drm_atomic_helper_check, .atomic_commit = drm_atomic_helper_commit, diff --git a/drivers/gpu/drm/armada/Makefile b/drivers/gpu/drm/armada/Makefile index 64c0b45..a18f156 100644 --- a/drivers/gpu/drm/armada/Makefile +++ b/drivers/gpu/drm/armada/Makefile @@ -4,5 +4,3 @@ armada-y += armada_510.o armada-$(CONFIG_DEBUG_FS) += armada_debugfs.o obj-$(CONFIG_DRM_ARMADA) := armada.o - -CFLAGS_armada_trace.o := -I$(src) diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c index 0b3227c..2fbd9d3 100644 --- a/drivers/gpu/drm/armada/armada_drv.c +++ b/drivers/gpu/drm/armada/armada_drv.c @@ -70,8 +70,6 @@ static struct drm_driver armada_drm_driver = { .gem_prime_export = armada_gem_prime_export, .gem_prime_import = armada_gem_prime_import, .dumb_create = armada_gem_dumb_create, - .dumb_map_offset = armada_gem_dumb_map_offset, - .dumb_destroy = armada_gem_dumb_destroy, .gem_vm_ops = &armada_gem_vm_ops, .major = 1, .minor = 0, diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c index a76ca21..7983538 100644 --- a/drivers/gpu/drm/armada/armada_gem.c +++ b/drivers/gpu/drm/armada/armada_gem.c @@ -270,42 +270,6 @@ int armada_gem_dumb_create(struct drm_file *file, struct drm_device *dev, return ret; } -int armada_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev, - uint32_t handle, uint64_t *offset) -{ - struct armada_gem_object *obj; - int ret = 0; - - obj = armada_gem_object_lookup(file, handle); - if (!obj) { - DRM_ERROR("failed to lookup gem object\n"); - return -EINVAL; - } - - /* Don't allow imported objects to be mapped */ - if (obj->obj.import_attach) { - ret = -EINVAL; - goto err_unref; - } - - ret = drm_gem_create_mmap_offset(&obj->obj); - if (ret == 0) { - *offset = drm_vma_node_offset_addr(&obj->obj.vma_node); - DRM_DEBUG_DRIVER("handle %#x offset %llx\n", handle, *offset); - } - - err_unref: - drm_gem_object_unreference_unlocked(&obj->obj); - - return ret; -} - -int armada_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev, - uint32_t handle) -{ - return drm_gem_handle_delete(file, handle); -} - /* Private driver gem ioctls */ int armada_gem_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file) diff --git a/drivers/gpu/drm/armada/armada_gem.h b/drivers/gpu/drm/armada/armada_gem.h index 6e524e0..1ac9079 100644 --- a/drivers/gpu/drm/armada/armada_gem.h +++ b/drivers/gpu/drm/armada/armada_gem.h @@ -35,10 +35,6 @@ struct armada_gem_object *armada_gem_alloc_private_object(struct drm_device *, size_t); int armada_gem_dumb_create(struct drm_file *, struct drm_device *, struct drm_mode_create_dumb *); -int armada_gem_dumb_map_offset(struct drm_file *, struct drm_device *, - uint32_t, uint64_t *); -int armada_gem_dumb_destroy(struct drm_file *, struct drm_device *, - uint32_t); struct dma_buf *armada_gem_prime_export(struct drm_device *dev, struct drm_gem_object *obj, int flags); struct drm_gem_object *armada_gem_prime_import(struct drm_device *, diff --git a/drivers/gpu/drm/armada/armada_trace.h b/drivers/gpu/drm/armada/armada_trace.h index dc0cba7..be245a2 100644 --- a/drivers/gpu/drm/armada/armada_trace.h +++ b/drivers/gpu/drm/armada/armada_trace.h @@ -62,5 +62,5 @@ TRACE_EVENT(armada_ovl_plane_work, /* This part must be outside protection */ #undef TRACE_INCLUDE_PATH -#define TRACE_INCLUDE_PATH . +#define TRACE_INCLUDE_PATH ../../drivers/gpu/drm/armada #include <trace/define_trace.h> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c index 74d66e1..c6e8061 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c @@ -458,7 +458,7 @@ static irqreturn_t atmel_hlcdc_dc_irq_handler(int irq, void *data) static struct drm_framebuffer *atmel_hlcdc_fb_create(struct drm_device *dev, struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd) { - return drm_fb_cma_create(dev, file_priv, mode_cmd); + return drm_gem_fb_create(dev, file_priv, mode_cmd); } static void atmel_hlcdc_fb_output_poll_changed(struct drm_device *dev) diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h index 4237b04..6833ee2 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h @@ -34,6 +34,7 @@ #include <drm/drm_crtc_helper.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_panel.h> #include <drm/drm_plane_helper.h> #include <drm/drmP.h> diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511.h b/drivers/gpu/drm/bridge/adv7511/adv7511.h index fe18a5d..12ef2d8 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511.h +++ b/drivers/gpu/drm/bridge/adv7511/adv7511.h @@ -328,8 +328,6 @@ struct adv7511 { enum adv7511_sync_polarity hsync_polarity; bool rgb; - struct edid *edid; - struct gpio_desc *gpio_pd; struct regulator_bulk_data *supplies; diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c b/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c index 67469c2..1b4783d 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c @@ -210,7 +210,7 @@ static const struct hdmi_codec_ops adv7511_codec_ops = { .get_dai_id = adv7511_hdmi_i2s_get_dai_id, }; -static struct hdmi_codec_pdata codec_data = { +static const struct hdmi_codec_pdata codec_data = { .ops = &adv7511_codec_ops, .max_i2s_channels = 2, .i2s = 1, diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c index b2431ae..bd7dbae 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c @@ -199,17 +199,14 @@ static const uint16_t adv7511_csc_ycbcr_to_rgb[] = { static void adv7511_set_config_csc(struct adv7511 *adv7511, struct drm_connector *connector, - bool rgb) + bool rgb, bool hdmi_mode) { struct adv7511_video_config config; bool output_format_422, output_format_ycbcr; unsigned int mode; uint8_t infoframe[17]; - if (adv7511->edid) - config.hdmi_mode = drm_detect_hdmi_monitor(adv7511->edid); - else - config.hdmi_mode = false; + config.hdmi_mode = hdmi_mode; hdmi_avi_infoframe_init(&config.avi_infoframe); @@ -589,15 +586,14 @@ static int adv7511_get_modes(struct adv7511 *adv7511, if (!adv7511->powered) __adv7511_power_off(adv7511); - kfree(adv7511->edid); - adv7511->edid = edid; - if (!edid) - return 0; drm_mode_connector_update_edid_property(connector, edid); count = drm_add_edid_modes(connector, edid); - adv7511_set_config_csc(adv7511, connector, adv7511->rgb); + adv7511_set_config_csc(adv7511, connector, adv7511->rgb, + drm_detect_hdmi_monitor(edid)); + + kfree(edid); return count; } @@ -833,7 +829,11 @@ static int adv7511_bridge_attach(struct drm_bridge *bridge) return -ENODEV; } - adv->connector.polled = DRM_CONNECTOR_POLL_HPD; + if (adv->i2c_main->irq) + adv->connector.polled = DRM_CONNECTOR_POLL_HPD; + else + adv->connector.polled = DRM_CONNECTOR_POLL_CONNECT | + DRM_CONNECTOR_POLL_DISCONNECT; ret = drm_connector_init(bridge->dev, &adv->connector, &adv7511_connector_funcs, @@ -1158,8 +1158,6 @@ static int adv7511_remove(struct i2c_client *i2c) i2c_unregister_device(adv7511->i2c_edid); - kfree(adv7511->edid); - return 0; } diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c index 63c7a01..f4f633a 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c @@ -30,19 +30,20 @@ #include <video/mipi_display.h> #define DSI_VERSION 0x00 + #define DSI_PWR_UP 0x04 #define RESET 0 #define POWERUP BIT(0) #define DSI_CLKMGR_CFG 0x08 -#define TO_CLK_DIVIDSION(div) (((div) & 0xff) << 8) -#define TX_ESC_CLK_DIVIDSION(div) (((div) & 0xff) << 0) +#define TO_CLK_DIVISION(div) (((div) & 0xff) << 8) +#define TX_ESC_CLK_DIVISION(div) ((div) & 0xff) #define DSI_DPI_VCID 0x0c -#define DPI_VID(vid) (((vid) & 0x3) << 0) +#define DPI_VCID(vcid) ((vcid) & 0x3) #define DSI_DPI_COLOR_CODING 0x10 -#define EN18_LOOSELY BIT(8) +#define LOOSELY18_EN BIT(8) #define DPI_COLOR_CODING_16BIT_1 0x0 #define DPI_COLOR_CODING_16BIT_2 0x1 #define DPI_COLOR_CODING_16BIT_3 0x2 @@ -61,22 +62,25 @@ #define OUTVACT_LPCMD_TIME(p) (((p) & 0xff) << 16) #define INVACT_LPCMD_TIME(p) ((p) & 0xff) +#define DSI_DBI_VCID 0x1c #define DSI_DBI_CFG 0x20 +#define DSI_DBI_PARTITIONING_EN 0x24 #define DSI_DBI_CMDSIZE 0x28 #define DSI_PCKHDL_CFG 0x2c -#define EN_CRC_RX BIT(4) -#define EN_ECC_RX BIT(3) -#define EN_BTA BIT(2) -#define EN_EOTP_RX BIT(1) -#define EN_EOTP_TX BIT(0) +#define CRC_RX_EN BIT(4) +#define ECC_RX_EN BIT(3) +#define BTA_EN BIT(2) +#define EOTP_RX_EN BIT(1) +#define EOTP_TX_EN BIT(0) + +#define DSI_GEN_VCID 0x30 #define DSI_MODE_CFG 0x34 #define ENABLE_VIDEO_MODE 0 #define ENABLE_CMD_MODE BIT(0) #define DSI_VID_MODE_CFG 0x38 -#define FRAME_BTA_ACK BIT(14) #define ENABLE_LOW_POWER (0x3f << 8) #define ENABLE_LOW_POWER_MASK (0x3f << 8) #define VID_MODE_TYPE_NON_BURST_SYNC_PULSES 0x0 @@ -85,8 +89,13 @@ #define VID_MODE_TYPE_MASK 0x3 #define DSI_VID_PKT_SIZE 0x3c -#define VID_PKT_SIZE(p) (((p) & 0x3fff) << 0) -#define VID_PKT_MAX_SIZE 0x3fff +#define VID_PKT_SIZE(p) ((p) & 0x3fff) + +#define DSI_VID_NUM_CHUNKS 0x40 +#define VID_NUM_CHUNKS(c) ((c) & 0x1fff) + +#define DSI_VID_NULL_SIZE 0x44 +#define VID_NULL_SIZE(b) ((b) & 0x1fff) #define DSI_VID_HSA_TIME 0x48 #define DSI_VID_HBP_TIME 0x4c @@ -95,6 +104,8 @@ #define DSI_VID_VBP_LINES 0x58 #define DSI_VID_VFP_LINES 0x5c #define DSI_VID_VACTIVE_LINES 0x60 +#define DSI_EDPI_CMD_SIZE 0x64 + #define DSI_CMD_MODE_CFG 0x68 #define MAX_RD_PKT_SIZE_LP BIT(24) #define DCS_LW_TX_LP BIT(19) @@ -108,8 +119,8 @@ #define GEN_SW_2P_TX_LP BIT(10) #define GEN_SW_1P_TX_LP BIT(9) #define GEN_SW_0P_TX_LP BIT(8) -#define EN_ACK_RQST BIT(1) -#define EN_TEAR_FX BIT(0) +#define ACK_RQST_EN BIT(1) +#define TEAR_FX_EN BIT(0) #define CMD_MODE_ALL_LP (MAX_RD_PKT_SIZE_LP | \ DCS_LW_TX_LP | \ @@ -125,27 +136,31 @@ GEN_SW_0P_TX_LP) #define DSI_GEN_HDR 0x6c +/* TODO These 2 defines will be reworked thanks to mipi_dsi_create_packet() */ #define GEN_HDATA(data) (((data) & 0xffff) << 8) -#define GEN_HDATA_MASK (0xffff << 8) #define GEN_HTYPE(type) (((type) & 0xff) << 0) -#define GEN_HTYPE_MASK 0xff #define DSI_GEN_PLD_DATA 0x70 #define DSI_CMD_PKT_STATUS 0x74 -#define GEN_CMD_EMPTY BIT(0) -#define GEN_CMD_FULL BIT(1) -#define GEN_PLD_W_EMPTY BIT(2) -#define GEN_PLD_W_FULL BIT(3) -#define GEN_PLD_R_EMPTY BIT(4) -#define GEN_PLD_R_FULL BIT(5) #define GEN_RD_CMD_BUSY BIT(6) +#define GEN_PLD_R_FULL BIT(5) +#define GEN_PLD_R_EMPTY BIT(4) +#define GEN_PLD_W_FULL BIT(3) +#define GEN_PLD_W_EMPTY BIT(2) +#define GEN_CMD_FULL BIT(1) +#define GEN_CMD_EMPTY BIT(0) #define DSI_TO_CNT_CFG 0x78 #define HSTX_TO_CNT(p) (((p) & 0xffff) << 16) #define LPRX_TO_CNT(p) ((p) & 0xffff) +#define DSI_HS_RD_TO_CNT 0x7c +#define DSI_LP_RD_TO_CNT 0x80 +#define DSI_HS_WR_TO_CNT 0x84 +#define DSI_LP_WR_TO_CNT 0x88 #define DSI_BTA_TO_CNT 0x8c + #define DSI_LPCLK_CTRL 0x94 #define AUTO_CLKLANE_CTRL BIT(1) #define PHY_TXREQUESTCLKHS BIT(0) @@ -154,6 +169,7 @@ #define PHY_CLKHS2LP_TIME(lbcc) (((lbcc) & 0x3ff) << 16) #define PHY_CLKLP2HS_TIME(lbcc) ((lbcc) & 0x3ff) +/* TODO Next register is slightly different between 1.30 & 1.31 IP version */ #define DSI_PHY_TMR_CFG 0x9c #define PHY_HS2LP_TIME(lbcc) (((lbcc) & 0xff) << 24) #define PHY_LP2HS_TIME(lbcc) (((lbcc) & 0xff) << 16) @@ -170,12 +186,15 @@ #define PHY_UNSHUTDOWNZ BIT(0) #define DSI_PHY_IF_CFG 0xa4 -#define N_LANES(n) ((((n) - 1) & 0x3) << 0) #define PHY_STOP_WAIT_TIME(cycle) (((cycle) & 0xff) << 8) +#define N_LANES(n) (((n) - 1) & 0x3) + +#define DSI_PHY_ULPS_CTRL 0xa8 +#define DSI_PHY_TX_TRIGGERS 0xac #define DSI_PHY_STATUS 0xb0 -#define LOCK BIT(0) -#define STOP_STATE_CLK_LANE BIT(2) +#define PHY_STOP_STATE_CLK_LANE BIT(2) +#define PHY_LOCK BIT(0) #define DSI_PHY_TST_CTRL0 0xb4 #define PHY_TESTCLK BIT(1) @@ -187,12 +206,13 @@ #define PHY_TESTEN BIT(16) #define PHY_UNTESTEN 0 #define PHY_TESTDOUT(n) (((n) & 0xff) << 8) -#define PHY_TESTDIN(n) (((n) & 0xff) << 0) +#define PHY_TESTDIN(n) ((n) & 0xff) #define DSI_INT_ST0 0xbc #define DSI_INT_ST1 0xc0 #define DSI_INT_MSK0 0xc4 #define DSI_INT_MSK1 0xc8 +#define DSI_PHY_TMR_RD_CFG 0xf4 #define PHY_STATUS_TIMEOUT_US 10000 #define CMD_PKT_STATUS_TIMEOUT_US 20000 @@ -307,7 +327,7 @@ static void dw_mipi_message_config(struct dw_mipi_dsi *dsi, u32 val = 0; if (msg->flags & MIPI_DSI_MSG_REQ_ACK) - val |= EN_ACK_RQST; + val |= ACK_RQST_EN; if (lpm) val |= CMD_MODE_ALL_LP; @@ -506,8 +526,8 @@ static void dw_mipi_dsi_init(struct dw_mipi_dsi *dsi) * timeout clock division should be computed with the * high speed transmission counter timeout and byte lane... */ - dsi_write(dsi, DSI_CLKMGR_CFG, TO_CLK_DIVIDSION(10) | - TX_ESC_CLK_DIVIDSION(esc_clk_division)); + dsi_write(dsi, DSI_CLKMGR_CFG, TO_CLK_DIVISION(10) | + TX_ESC_CLK_DIVISION(esc_clk_division)); } static void dw_mipi_dsi_dpi_config(struct dw_mipi_dsi *dsi, @@ -520,7 +540,7 @@ static void dw_mipi_dsi_dpi_config(struct dw_mipi_dsi *dsi, color = DPI_COLOR_CODING_24BIT; break; case MIPI_DSI_FMT_RGB666: - color = DPI_COLOR_CODING_18BIT_2 | EN18_LOOSELY; + color = DPI_COLOR_CODING_18BIT_2 | LOOSELY18_EN; break; case MIPI_DSI_FMT_RGB666_PACKED: color = DPI_COLOR_CODING_18BIT_1; @@ -535,7 +555,7 @@ static void dw_mipi_dsi_dpi_config(struct dw_mipi_dsi *dsi, if (mode->flags & DRM_MODE_FLAG_NHSYNC) val |= HSYNC_ACTIVE_LOW; - dsi_write(dsi, DSI_DPI_VCID, DPI_VID(dsi->channel)); + dsi_write(dsi, DSI_DPI_VCID, DPI_VCID(dsi->channel)); dsi_write(dsi, DSI_DPI_COLOR_CODING, color); dsi_write(dsi, DSI_DPI_CFG_POL, val); /* @@ -550,7 +570,7 @@ static void dw_mipi_dsi_dpi_config(struct dw_mipi_dsi *dsi, static void dw_mipi_dsi_packet_handler_config(struct dw_mipi_dsi *dsi) { - dsi_write(dsi, DSI_PCKHDL_CFG, EN_CRC_RX | EN_ECC_RX | EN_BTA); + dsi_write(dsi, DSI_PCKHDL_CFG, CRC_RX_EN | ECC_RX_EN | BTA_EN); } static void dw_mipi_dsi_video_packet_config(struct dw_mipi_dsi *dsi, @@ -571,7 +591,7 @@ static void dw_mipi_dsi_command_mode_config(struct dw_mipi_dsi *dsi) /* * TODO dw drv improvements * compute high speed transmission counter timeout according - * to the timeout clock division (TO_CLK_DIVIDSION) and byte lane... + * to the timeout clock division (TO_CLK_DIVISION) and byte lane... */ dsi_write(dsi, DSI_TO_CNT_CFG, HSTX_TO_CNT(1000) | LPRX_TO_CNT(1000)); /* @@ -684,13 +704,13 @@ static void dw_mipi_dsi_dphy_enable(struct dw_mipi_dsi *dsi) dsi_write(dsi, DSI_PHY_RSTZ, PHY_ENFORCEPLL | PHY_ENABLECLK | PHY_UNRSTZ | PHY_UNSHUTDOWNZ); - ret = readl_poll_timeout(dsi->base + DSI_PHY_STATUS, - val, val & LOCK, 1000, PHY_STATUS_TIMEOUT_US); + ret = readl_poll_timeout(dsi->base + DSI_PHY_STATUS, val, + val & PHY_LOCK, 1000, PHY_STATUS_TIMEOUT_US); if (ret < 0) DRM_DEBUG_DRIVER("failed to wait phy lock state\n"); ret = readl_poll_timeout(dsi->base + DSI_PHY_STATUS, - val, val & STOP_STATE_CLK_LANE, 1000, + val, val & PHY_STOP_STATE_CLK_LANE, 1000, PHY_STATUS_TIMEOUT_US); if (ret < 0) DRM_DEBUG_DRIVER("failed to wait phy clk lane stop state\n"); @@ -865,15 +885,14 @@ __dw_mipi_dsi_probe(struct platform_device *pdev, * Note that the reset was not defined in the initial device tree, so * we have to be prepared for it not being found. */ - apb_rst = devm_reset_control_get(dev, "apb"); + apb_rst = devm_reset_control_get_optional_exclusive(dev, "apb"); if (IS_ERR(apb_rst)) { ret = PTR_ERR(apb_rst); - if (ret == -ENOENT) { - apb_rst = NULL; - } else { + + if (ret != -EPROBE_DEFER) dev_err(dev, "Unable to get reset control: %d\n", ret); - return ERR_PTR(ret); - } + + return ERR_PTR(ret); } if (apb_rst) { diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 2fd383d..366c56f 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -163,13 +163,6 @@ void drm_atomic_state_default_clear(struct drm_atomic_state *state) crtc->funcs->atomic_destroy_state(crtc, state->crtcs[i].state); - if (state->crtcs[i].commit) { - kfree(state->crtcs[i].commit->event); - state->crtcs[i].commit->event = NULL; - drm_crtc_commit_put(state->crtcs[i].commit); - } - - state->crtcs[i].commit = NULL; state->crtcs[i].ptr = NULL; state->crtcs[i].state = NULL; } @@ -199,6 +192,10 @@ void drm_atomic_state_default_clear(struct drm_atomic_state *state) } state->num_private_objs = 0; + if (state->fake_commit) { + drm_crtc_commit_put(state->fake_commit); + state->fake_commit = NULL; + } } EXPORT_SYMBOL(drm_atomic_state_default_clear); @@ -2237,7 +2234,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, (arg->flags & DRM_MODE_PAGE_FLIP_EVENT)) return -EINVAL; - drm_modeset_acquire_init(&ctx, 0); + drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE); state = drm_atomic_state_alloc(dev); if (!state) @@ -2350,8 +2347,9 @@ out: if (ret == -EDEADLK) { drm_atomic_state_clear(state); - drm_modeset_backoff(&ctx); - goto retry; + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry; } drm_atomic_state_put(state); diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 4e53aae..01c34bc 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1262,12 +1262,12 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_vblanks); void drm_atomic_helper_wait_for_flip_done(struct drm_device *dev, struct drm_atomic_state *old_state) { - struct drm_crtc_state *unused; + struct drm_crtc_state *new_crtc_state; struct drm_crtc *crtc; int i; - for_each_new_crtc_in_state(old_state, crtc, unused, i) { - struct drm_crtc_commit *commit = old_state->crtcs[i].commit; + for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) { + struct drm_crtc_commit *commit = new_crtc_state->commit; int ret; if (!commit) @@ -1388,35 +1388,31 @@ int drm_atomic_helper_async_check(struct drm_device *dev, { struct drm_crtc *crtc; struct drm_crtc_state *crtc_state; - struct drm_crtc_commit *commit; - struct drm_plane *__plane, *plane = NULL; - struct drm_plane_state *__plane_state, *plane_state = NULL; + struct drm_plane *plane; + struct drm_plane_state *old_plane_state, *new_plane_state; const struct drm_plane_helper_funcs *funcs; - int i, j, n_planes = 0; + int i, n_planes = 0; for_each_new_crtc_in_state(state, crtc, crtc_state, i) { if (drm_atomic_crtc_needs_modeset(crtc_state)) return -EINVAL; } - for_each_new_plane_in_state(state, __plane, __plane_state, i) { + for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) n_planes++; - plane = __plane; - plane_state = __plane_state; - } /* FIXME: we support only single plane updates for now */ - if (!plane || n_planes != 1) + if (n_planes != 1) return -EINVAL; - if (!plane_state->crtc) + if (!new_plane_state->crtc) return -EINVAL; funcs = plane->helper_private; if (!funcs->atomic_async_update) return -EINVAL; - if (plane_state->fence) + if (new_plane_state->fence) return -EINVAL; /* @@ -1424,31 +1420,11 @@ int drm_atomic_helper_async_check(struct drm_device *dev, * the plane. This prevents our async update's changes from getting * overridden by a previous synchronous update's state. */ - for_each_new_crtc_in_state(state, crtc, crtc_state, i) { - if (plane->crtc != crtc) - continue; + if (old_plane_state->commit && + !try_wait_for_completion(&old_plane_state->commit->hw_done)) + return -EBUSY; - spin_lock(&crtc->commit_lock); - commit = list_first_entry_or_null(&crtc->commit_list, - struct drm_crtc_commit, - commit_entry); - if (!commit) { - spin_unlock(&crtc->commit_lock); - continue; - } - spin_unlock(&crtc->commit_lock); - - if (!crtc->state->state) - continue; - - for_each_plane_in_state(crtc->state->state, __plane, - __plane_state, j) { - if (__plane == plane) - return -EINVAL; - } - } - - return funcs->atomic_async_check(plane, plane_state); + return funcs->atomic_async_check(plane, new_plane_state); } EXPORT_SYMBOL(drm_atomic_helper_async_check); @@ -1633,8 +1609,7 @@ static int stall_checks(struct drm_crtc *crtc, bool nonblock) return -EBUSY; } } else if (i == 1) { - stall_commit = commit; - drm_crtc_commit_get(stall_commit); + stall_commit = drm_crtc_commit_get(commit); break; } @@ -1668,6 +1643,38 @@ static void release_crtc_commit(struct completion *completion) drm_crtc_commit_put(commit); } +static void init_commit(struct drm_crtc_commit *commit, struct drm_crtc *crtc) +{ + init_completion(&commit->flip_done); + init_completion(&commit->hw_done); + init_completion(&commit->cleanup_done); + INIT_LIST_HEAD(&commit->commit_entry); + kref_init(&commit->ref); + commit->crtc = crtc; +} + +static struct drm_crtc_commit * +crtc_or_fake_commit(struct drm_atomic_state *state, struct drm_crtc *crtc) +{ + if (crtc) { + struct drm_crtc_state *new_crtc_state; + + new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + + return new_crtc_state->commit; + } + + if (!state->fake_commit) { + state->fake_commit = kzalloc(sizeof(*state->fake_commit), GFP_KERNEL); + if (!state->fake_commit) + return NULL; + + init_commit(state->fake_commit, NULL); + } + + return state->fake_commit; +} + /** * drm_atomic_helper_setup_commit - setup possibly nonblocking commit * @state: new modeset state to be committed @@ -1716,6 +1723,10 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state, { struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state, *new_crtc_state; + struct drm_connector *conn; + struct drm_connector_state *old_conn_state, *new_conn_state; + struct drm_plane *plane; + struct drm_plane_state *old_plane_state, *new_plane_state; struct drm_crtc_commit *commit; int i, ret; @@ -1724,14 +1735,9 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state, if (!commit) return -ENOMEM; - init_completion(&commit->flip_done); - init_completion(&commit->hw_done); - init_completion(&commit->cleanup_done); - INIT_LIST_HEAD(&commit->commit_entry); - kref_init(&commit->ref); - commit->crtc = crtc; + init_commit(commit, crtc); - state->crtcs[i].commit = commit; + new_crtc_state->commit = commit; ret = stall_checks(crtc, nonblock); if (ret) @@ -1765,25 +1771,46 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state, drm_crtc_commit_get(commit); } - return 0; -} -EXPORT_SYMBOL(drm_atomic_helper_setup_commit); + for_each_oldnew_connector_in_state(state, conn, old_conn_state, new_conn_state, i) { + /* commit tracked through new_crtc_state->commit, no need to do it explicitly */ + if (new_conn_state->crtc) + continue; + /* Userspace is not allowed to get ahead of the previous + * commit with nonblocking ones. */ + if (nonblock && old_conn_state->commit && + !try_wait_for_completion(&old_conn_state->commit->flip_done)) + return -EBUSY; -static struct drm_crtc_commit *preceeding_commit(struct drm_crtc *crtc) -{ - struct drm_crtc_commit *commit; - int i = 0; + commit = crtc_or_fake_commit(state, old_conn_state->crtc); + if (!commit) + return -ENOMEM; - list_for_each_entry(commit, &crtc->commit_list, commit_entry) { - /* skip the first entry, that's the current commit */ - if (i == 1) - return commit; - i++; + new_conn_state->commit = drm_crtc_commit_get(commit); + } + + for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { + /* + * Unlike connectors, always track planes explicitly for + * async pageflip support. + */ + + /* Userspace is not allowed to get ahead of the previous + * commit with nonblocking ones. */ + if (nonblock && old_plane_state->commit && + !try_wait_for_completion(&old_plane_state->commit->flip_done)) + return -EBUSY; + + commit = crtc_or_fake_commit(state, old_plane_state->crtc); + if (!commit) + return -ENOMEM; + + new_plane_state->commit = drm_crtc_commit_get(commit); } - return NULL; + return 0; } +EXPORT_SYMBOL(drm_atomic_helper_setup_commit); /** * drm_atomic_helper_wait_for_dependencies - wait for required preceeding commits @@ -1800,17 +1827,17 @@ static struct drm_crtc_commit *preceeding_commit(struct drm_crtc *crtc) void drm_atomic_helper_wait_for_dependencies(struct drm_atomic_state *old_state) { struct drm_crtc *crtc; - struct drm_crtc_state *new_crtc_state; + struct drm_crtc_state *old_crtc_state; + struct drm_plane *plane; + struct drm_plane_state *old_plane_state; + struct drm_connector *conn; + struct drm_connector_state *old_conn_state; struct drm_crtc_commit *commit; int i; long ret; - for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) { - spin_lock(&crtc->commit_lock); - commit = preceeding_commit(crtc); - if (commit) - drm_crtc_commit_get(commit); - spin_unlock(&crtc->commit_lock); + for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) { + commit = old_crtc_state->commit; if (!commit) continue; @@ -1828,8 +1855,48 @@ void drm_atomic_helper_wait_for_dependencies(struct drm_atomic_state *old_state) if (ret == 0) DRM_ERROR("[CRTC:%d:%s] flip_done timed out\n", crtc->base.id, crtc->name); + } + + for_each_old_connector_in_state(old_state, conn, old_conn_state, i) { + commit = old_conn_state->commit; - drm_crtc_commit_put(commit); + if (!commit) + continue; + + ret = wait_for_completion_timeout(&commit->hw_done, + 10*HZ); + if (ret == 0) + DRM_ERROR("[CONNECTOR:%d:%s] hw_done timed out\n", + conn->base.id, conn->name); + + /* Currently no support for overwriting flips, hence + * stall for previous one to execute completely. */ + ret = wait_for_completion_timeout(&commit->flip_done, + 10*HZ); + if (ret == 0) + DRM_ERROR("[CONNECTOR:%d:%s] flip_done timed out\n", + conn->base.id, conn->name); + } + + for_each_old_plane_in_state(old_state, plane, old_plane_state, i) { + commit = old_plane_state->commit; + + if (!commit) + continue; + + ret = wait_for_completion_timeout(&commit->hw_done, + 10*HZ); + if (ret == 0) + DRM_ERROR("[PLANE:%d:%s] hw_done timed out\n", + plane->base.id, plane->name); + + /* Currently no support for overwriting flips, hence + * stall for previous one to execute completely. */ + ret = wait_for_completion_timeout(&commit->flip_done, + 10*HZ); + if (ret == 0) + DRM_ERROR("[PLANE:%d:%s] flip_done timed out\n", + plane->base.id, plane->name); } } EXPORT_SYMBOL(drm_atomic_helper_wait_for_dependencies); @@ -1852,19 +1919,34 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_dependencies); void drm_atomic_helper_commit_hw_done(struct drm_atomic_state *old_state) { struct drm_crtc *crtc; - struct drm_crtc_state *new_crtc_state; + struct drm_crtc_state *old_crtc_state, *new_crtc_state; struct drm_crtc_commit *commit; int i; - for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) { - commit = old_state->crtcs[i].commit; + for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) { + commit = new_crtc_state->commit; if (!commit) continue; + /* + * copy new_crtc_state->commit to old_crtc_state->commit, + * it's unsafe to touch new_crtc_state after hw_done, + * but we still need to do so in cleanup_done(). + */ + if (old_crtc_state->commit) + drm_crtc_commit_put(old_crtc_state->commit); + + old_crtc_state->commit = drm_crtc_commit_get(commit); + /* backend must have consumed any event by now */ WARN_ON(new_crtc_state->event); complete_all(&commit->hw_done); } + + if (old_state->fake_commit) { + complete_all(&old_state->fake_commit->hw_done); + complete_all(&old_state->fake_commit->flip_done); + } } EXPORT_SYMBOL(drm_atomic_helper_commit_hw_done); @@ -1882,39 +1964,25 @@ EXPORT_SYMBOL(drm_atomic_helper_commit_hw_done); void drm_atomic_helper_commit_cleanup_done(struct drm_atomic_state *old_state) { struct drm_crtc *crtc; - struct drm_crtc_state *new_crtc_state; + struct drm_crtc_state *old_crtc_state; struct drm_crtc_commit *commit; int i; - long ret; - for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) { - commit = old_state->crtcs[i].commit; + for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) { + commit = old_crtc_state->commit; if (WARN_ON(!commit)) continue; complete_all(&commit->cleanup_done); WARN_ON(!try_wait_for_completion(&commit->hw_done)); - /* commit_list borrows our reference, need to remove before we - * clean up our drm_atomic_state. But only after it actually - * completed, otherwise subsequent commits won't stall properly. */ - if (try_wait_for_completion(&commit->flip_done)) - goto del_commit; - - /* We must wait for the vblank event to signal our completion - * before releasing our reference, since the vblank work does - * not hold a reference of its own. */ - ret = wait_for_completion_timeout(&commit->flip_done, - 10*HZ); - if (ret == 0) - DRM_ERROR("[CRTC:%d:%s] flip_done timed out\n", - crtc->base.id, crtc->name); - -del_commit: spin_lock(&crtc->commit_lock); list_del(&commit->commit_entry); spin_unlock(&crtc->commit_lock); } + + if (old_state->fake_commit) + complete_all(&old_state->fake_commit->cleanup_done); } EXPORT_SYMBOL(drm_atomic_helper_commit_cleanup_done); @@ -2294,20 +2362,44 @@ int drm_atomic_helper_swap_state(struct drm_atomic_state *state, struct drm_private_state *old_obj_state, *new_obj_state; if (stall) { - for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { - spin_lock(&crtc->commit_lock); - commit = list_first_entry_or_null(&crtc->commit_list, - struct drm_crtc_commit, commit_entry); - if (commit) - drm_crtc_commit_get(commit); - spin_unlock(&crtc->commit_lock); + /* + * We have to stall for hw_done here before + * drm_atomic_helper_wait_for_dependencies() because flip + * depth > 1 is not yet supported by all drivers. As long as + * obj->state is directly dereferenced anywhere in the drivers + * atomic_commit_tail function, then it's unsafe to swap state + * before drm_atomic_helper_commit_hw_done() is called. + */ + + for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) { + commit = old_crtc_state->commit; + + if (!commit) + continue; + + ret = wait_for_completion_interruptible(&commit->hw_done); + if (ret) + return ret; + } + + for_each_old_connector_in_state(state, connector, old_conn_state, i) { + commit = old_conn_state->commit; if (!commit) continue; ret = wait_for_completion_interruptible(&commit->hw_done); - drm_crtc_commit_put(commit); + if (ret) + return ret; + } + for_each_old_plane_in_state(state, plane, old_plane_state, i) { + commit = old_plane_state->commit; + + if (!commit) + continue; + + ret = wait_for_completion_interruptible(&commit->hw_done); if (ret) return ret; } @@ -2332,13 +2424,13 @@ int drm_atomic_helper_swap_state(struct drm_atomic_state *state, state->crtcs[i].state = old_crtc_state; crtc->state = new_crtc_state; - if (state->crtcs[i].commit) { + if (new_crtc_state->commit) { spin_lock(&crtc->commit_lock); - list_add(&state->crtcs[i].commit->commit_entry, + list_add(&new_crtc_state->commit->commit_entry, &crtc->commit_list); spin_unlock(&crtc->commit_lock); - state->crtcs[i].commit->event = NULL; + new_crtc_state->commit->event = NULL; } } @@ -3186,6 +3278,7 @@ void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc, state->connectors_changed = false; state->color_mgmt_changed = false; state->zpos_changed = false; + state->commit = NULL; state->event = NULL; state->pageflip_flags = 0; } @@ -3224,6 +3317,12 @@ EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state); */ void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state) { + if (state->commit) { + kfree(state->commit->event); + state->commit->event = NULL; + drm_crtc_commit_put(state->commit); + } + drm_property_blob_put(state->mode_blob); drm_property_blob_put(state->degamma_lut); drm_property_blob_put(state->ctm); @@ -3286,6 +3385,7 @@ void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane, drm_framebuffer_get(state->fb); state->fence = NULL; + state->commit = NULL; } EXPORT_SYMBOL(__drm_atomic_helper_plane_duplicate_state); @@ -3327,6 +3427,9 @@ void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state) if (state->fence) dma_fence_put(state->fence); + + if (state->commit) + drm_crtc_commit_put(state->commit); } EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state); @@ -3405,6 +3508,7 @@ __drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector, memcpy(state, connector->state, sizeof(*state)); if (state->crtc) drm_connector_get(connector); + state->commit = NULL; } EXPORT_SYMBOL(__drm_atomic_helper_connector_duplicate_state); @@ -3531,6 +3635,9 @@ __drm_atomic_helper_connector_destroy_state(struct drm_connector_state *state) { if (state->crtc) drm_connector_put(state->connector); + + if (state->commit) + drm_crtc_commit_put(state->commit); } EXPORT_SYMBOL(__drm_atomic_helper_connector_destroy_state); diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index dc8cdfe..1638bfe 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -67,17 +67,12 @@ static LIST_HEAD(bridge_list); * drm_bridge_add - add the given bridge to the global bridge list * * @bridge: bridge control structure - * - * RETURNS: - * Unconditionally returns Zero. */ -int drm_bridge_add(struct drm_bridge *bridge) +void drm_bridge_add(struct drm_bridge *bridge) { mutex_lock(&bridge_lock); list_add_tail(&bridge->list, &bridge_list); mutex_unlock(&bridge_lock); - - return 0; } EXPORT_SYMBOL(drm_bridge_add); diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index ba9f36c..bb2e60f 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -615,7 +615,6 @@ static const struct drm_prop_enum_list drm_link_status_enum_list[] = { { DRM_MODE_LINK_STATUS_GOOD, "Good" }, { DRM_MODE_LINK_STATUS_BAD, "Bad" }, }; -DRM_ENUM_NAME_FN(drm_get_link_status_name, drm_link_status_enum_list) /** * drm_display_info_set_bus_formats - set the supported bus formats diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 5af25ce..68b4e97 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -577,7 +577,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name); mutex_lock(&crtc->dev->mode_config.mutex); - drm_modeset_acquire_init(&ctx, 0); + drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE); retry: ret = drm_modeset_lock_all_ctx(crtc->dev, &ctx); if (ret) @@ -717,8 +717,9 @@ out: kfree(connector_set); drm_mode_destroy(dev, mode); if (ret == -EDEADLK) { - drm_modeset_backoff(&ctx); - goto retry; + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry; } drm_modeset_drop_locks(&ctx); drm_modeset_acquire_fini(&ctx); diff --git a/drivers/gpu/drm/drm_debugfs_crc.c b/drivers/gpu/drm/drm_debugfs_crc.c index f9e26dd..9dd8795 100644 --- a/drivers/gpu/drm/drm_debugfs_crc.c +++ b/drivers/gpu/drm/drm_debugfs_crc.c @@ -155,7 +155,7 @@ static int crtc_crc_open(struct inode *inode, struct file *filep) int ret = 0; if (drm_drv_uses_atomic_modeset(crtc->dev)) { - ret = drm_modeset_lock_interruptible(&crtc->mutex, NULL); + ret = drm_modeset_lock_single_interruptible(&crtc->mutex); if (ret) return ret; diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 41b492f..70dcfa5 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -294,6 +294,12 @@ static void drm_dp_encode_sideband_req(struct drm_dp_sideband_msg_req_body *req, memcpy(&buf[idx], req->u.i2c_write.bytes, req->u.i2c_write.num_bytes); idx += req->u.i2c_write.num_bytes; break; + + case DP_POWER_DOWN_PHY: + case DP_POWER_UP_PHY: + buf[idx] = (req->u.port_num.port_number & 0xf) << 4; + idx++; + break; } raw->cur_len = idx; } @@ -538,6 +544,21 @@ fail_len: return false; } +static bool drm_dp_sideband_parse_power_updown_phy_ack(struct drm_dp_sideband_msg_rx *raw, + struct drm_dp_sideband_msg_reply_body *repmsg) +{ + int idx = 1; + + repmsg->u.port_number.port_number = (raw->msg[idx] >> 4) & 0xf; + idx++; + if (idx > raw->curlen) { + DRM_DEBUG_KMS("power up/down phy parse length fail %d %d\n", + idx, raw->curlen); + return false; + } + return true; +} + static bool drm_dp_sideband_parse_reply(struct drm_dp_sideband_msg_rx *raw, struct drm_dp_sideband_msg_reply_body *msg) { @@ -567,6 +588,9 @@ static bool drm_dp_sideband_parse_reply(struct drm_dp_sideband_msg_rx *raw, return drm_dp_sideband_parse_enum_path_resources_ack(raw, msg); case DP_ALLOCATE_PAYLOAD: return drm_dp_sideband_parse_allocate_payload_ack(raw, msg); + case DP_POWER_DOWN_PHY: + case DP_POWER_UP_PHY: + return drm_dp_sideband_parse_power_updown_phy_ack(raw, msg); default: DRM_ERROR("Got unknown reply 0x%02x\n", msg->req_type); return false; @@ -693,6 +717,22 @@ static int build_allocate_payload(struct drm_dp_sideband_msg_tx *msg, int port_n return 0; } +static int build_power_updown_phy(struct drm_dp_sideband_msg_tx *msg, + int port_num, bool power_up) +{ + struct drm_dp_sideband_msg_req_body req; + + if (power_up) + req.req_type = DP_POWER_UP_PHY; + else + req.req_type = DP_POWER_DOWN_PHY; + + req.u.port_num.port_number = port_num; + drm_dp_encode_sideband_req(&req, msg); + msg->path_msg = true; + return 0; +} + static int drm_dp_mst_assign_payload_id(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_vcpi *vcpi) { @@ -1724,6 +1764,40 @@ fail_put: return ret; } +int drm_dp_send_power_updown_phy(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_port *port, bool power_up) +{ + struct drm_dp_sideband_msg_tx *txmsg; + int len, ret; + + port = drm_dp_get_validated_port_ref(mgr, port); + if (!port) + return -EINVAL; + + txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL); + if (!txmsg) { + drm_dp_put_port(port); + return -ENOMEM; + } + + txmsg->dst = port->parent; + len = build_power_updown_phy(txmsg, port->port_num, power_up); + drm_dp_queue_down_tx(mgr, txmsg); + + ret = drm_dp_mst_wait_tx_reply(port->parent, txmsg); + if (ret > 0) { + if (txmsg->reply.reply_type == 1) + ret = -EINVAL; + else + ret = 0; + } + kfree(txmsg); + drm_dp_put_port(port); + + return ret; +} +EXPORT_SYMBOL(drm_dp_send_power_updown_phy); + static int drm_dp_create_payload_step1(struct drm_dp_mst_topology_mgr *mgr, int id, struct drm_dp_payload *payload) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 6bb6337..00ddabf 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1533,6 +1533,10 @@ static void connector_bad_edid(struct drm_connector *connector, * level, drivers must make all reasonable efforts to expose it as an I2C * adapter and use drm_get_edid() instead of abusing this function. * + * The EDID may be overridden using debugfs override_edid or firmare EDID + * (drm_load_edid_firmware() and drm.edid_firmware parameter), in this priority + * order. Having either of them bypasses actual EDID reads. + * * Return: Pointer to valid EDID or NULL if we couldn't find any. */ struct edid *drm_do_get_edid(struct drm_connector *connector, @@ -1542,6 +1546,17 @@ struct edid *drm_do_get_edid(struct drm_connector *connector, { int i, j = 0, valid_extensions = 0; u8 *edid, *new; + struct edid *override = NULL; + + if (connector->override_edid) + override = drm_edid_duplicate((const struct edid *) + connector->edid_blob_ptr->data); + + if (!override) + override = drm_load_edid_firmware(connector); + + if (!IS_ERR_OR_NULL(override)) + return override; if ((edid = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL) return NULL; diff --git a/drivers/gpu/drm/drm_edid_load.c b/drivers/gpu/drm/drm_edid_load.c index 1c0495a..a491509 100644 --- a/drivers/gpu/drm/drm_edid_load.c +++ b/drivers/gpu/drm/drm_edid_load.c @@ -31,6 +31,22 @@ module_param_string(edid_firmware, edid_firmware, sizeof(edid_firmware), 0644); MODULE_PARM_DESC(edid_firmware, "Do not probe monitor, use specified EDID blob " "from built-in data or /lib/firmware instead. "); +/* Use only for backward compatibility with drm_kms_helper.edid_firmware */ +int __drm_set_edid_firmware_path(const char *path) +{ + scnprintf(edid_firmware, sizeof(edid_firmware), "%s", path); + + return 0; +} +EXPORT_SYMBOL(__drm_set_edid_firmware_path); + +/* Use only for backward compatibility with drm_kms_helper.edid_firmware */ +int __drm_get_edid_firmware_path(char *buf, size_t bufsize) +{ + return scnprintf(buf, bufsize, "%s", edid_firmware); +} +EXPORT_SYMBOL(__drm_get_edid_firmware_path); + #define GENERIC_EDIDS 6 static const char * const generic_edid_name[GENERIC_EDIDS] = { "edid/800x600.bin", diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 1b8f013..6a31d13 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -910,6 +910,9 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper) if (!drm_fbdev_emulation || !fb_helper) return; + cancel_work_sync(&fb_helper->resume_work); + cancel_work_sync(&fb_helper->dirty_work); + info = fb_helper->fbdev; if (info) { if (info->cmap.len) @@ -918,9 +921,6 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper) } fb_helper->fbdev = NULL; - cancel_work_sync(&fb_helper->resume_work); - cancel_work_sync(&fb_helper->dirty_work); - mutex_lock(&kernel_fb_helper_lock); if (!list_empty(&fb_helper->kernel_fb_list)) { list_del(&fb_helper->kernel_fb_list); diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index c55f338..7199bba 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -334,6 +334,12 @@ int drm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev, if (!obj) return -ENOENT; + /* Don't allow imported objects to be mapped */ + if (obj->import_attach) { + ret = -EINVAL; + goto out; + } + ret = drm_gem_create_mmap_offset(obj); if (ret) goto out; diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c index d54a083..fc7e995 100644 --- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c +++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c @@ -154,7 +154,7 @@ drm_gem_fb_create_with_funcs(struct drm_device *dev, struct drm_file *file, objs[i] = drm_gem_object_lookup(file, mode_cmd->handles[i]); if (!objs[i]) { - DRM_DEV_ERROR(dev->dev, "Failed to lookup GEM\n"); + DRM_DEBUG_KMS("Failed to lookup GEM object\n"); ret = -ENOENT; goto err_gem_object_put; } @@ -232,7 +232,7 @@ int drm_gem_fb_prepare_fb(struct drm_plane *plane, struct dma_buf *dma_buf; struct dma_fence *fence; - if ((plane->state->fb == state->fb) || !state->fb) + if (plane->state->fb == state->fb || !state->fb) return 0; dma_buf = drm_gem_fb_get_obj(state->fb, 0)->dma_buf; diff --git a/drivers/gpu/drm/drm_kms_helper_common.c b/drivers/gpu/drm/drm_kms_helper_common.c index 6e35a56..93e2b30 100644 --- a/drivers/gpu/drm/drm_kms_helper_common.c +++ b/drivers/gpu/drm/drm_kms_helper_common.c @@ -26,6 +26,7 @@ */ #include <linux/module.h> +#include <drm/drmP.h> #include "drm_crtc_helper_internal.h" @@ -33,6 +34,33 @@ MODULE_AUTHOR("David Airlie, Jesse Barnes"); MODULE_DESCRIPTION("DRM KMS helper"); MODULE_LICENSE("GPL and additional rights"); +#if IS_ENABLED(CONFIG_DRM_LOAD_EDID_FIRMWARE) + +/* Backward compatibility for drm_kms_helper.edid_firmware */ +static int edid_firmware_set(const char *val, const struct kernel_param *kp) +{ + DRM_NOTE("drm_kms_firmware.edid_firmware is deprecated, please use drm.edid_firmware intead.\n"); + + return __drm_set_edid_firmware_path(val); +} + +static int edid_firmware_get(char *buffer, const struct kernel_param *kp) +{ + return __drm_get_edid_firmware_path(buffer, PAGE_SIZE); +} + +static const struct kernel_param_ops edid_firmware_ops = { + .set = edid_firmware_set, + .get = edid_firmware_get, +}; + +module_param_cb(edid_firmware, &edid_firmware_ops, NULL, 0644); +__MODULE_PARM_TYPE(edid_firmware, "charp"); +MODULE_PARM_DESC(edid_firmware, + "DEPRECATED. Use drm.edid_firmware module parameter instead."); + +#endif + static int __init drm_kms_helper_init(void) { int ret; diff --git a/drivers/gpu/drm/drm_mode_object.c b/drivers/gpu/drm/drm_mode_object.c index 1055533..7a1ea91 100644 --- a/drivers/gpu/drm/drm_mode_object.c +++ b/drivers/gpu/drm/drm_mode_object.c @@ -247,8 +247,9 @@ int drm_object_property_set_value(struct drm_mode_object *obj, } EXPORT_SYMBOL(drm_object_property_set_value); -int __drm_object_property_get_value(struct drm_mode_object *obj, - struct drm_property *property, uint64_t *val) +static int __drm_object_property_get_value(struct drm_mode_object *obj, + struct drm_property *property, + uint64_t *val) { int i; diff --git a/drivers/gpu/drm/drm_modeset_lock.c b/drivers/gpu/drm/drm_modeset_lock.c index af4e906..e123497 100644 --- a/drivers/gpu/drm/drm_modeset_lock.c +++ b/drivers/gpu/drm/drm_modeset_lock.c @@ -39,23 +39,28 @@ * * The basic usage pattern is to:: * - * drm_modeset_acquire_init(&ctx) + * drm_modeset_acquire_init(ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE) * retry: * foreach (lock in random_ordered_set_of_locks) { - * ret = drm_modeset_lock(lock, &ctx) + * ret = drm_modeset_lock(lock, ctx) * if (ret == -EDEADLK) { - * drm_modeset_backoff(&ctx); - * goto retry; + * ret = drm_modeset_backoff(ctx); + * if (!ret) + * goto retry; * } + * if (ret) + * goto out; * } * ... do stuff ... - * drm_modeset_drop_locks(&ctx); - * drm_modeset_acquire_fini(&ctx); + * out: + * drm_modeset_drop_locks(ctx); + * drm_modeset_acquire_fini(ctx); * * If all that is needed is a single modeset lock, then the &struct * drm_modeset_acquire_ctx is not needed and the locking can be simplified - * by passing a NULL instead of ctx in the drm_modeset_lock() - * call and, when done, by calling drm_modeset_unlock(). + * by passing a NULL instead of ctx in the drm_modeset_lock() call or + * calling drm_modeset_lock_single_interruptible(). To unlock afterwards + * call drm_modeset_unlock(). * * On top of these per-object locks using &ww_mutex there's also an overall * &drm_mode_config.mutex, for protecting everything else. Mostly this means @@ -178,7 +183,11 @@ EXPORT_SYMBOL(drm_warn_on_modeset_not_all_locked); /** * drm_modeset_acquire_init - initialize acquire context * @ctx: the acquire context - * @flags: for future + * @flags: 0 or %DRM_MODESET_ACQUIRE_INTERRUPTIBLE + * + * When passing %DRM_MODESET_ACQUIRE_INTERRUPTIBLE to @flags, + * all calls to drm_modeset_lock() will perform an interruptible + * wait. */ void drm_modeset_acquire_init(struct drm_modeset_acquire_ctx *ctx, uint32_t flags) @@ -186,6 +195,9 @@ void drm_modeset_acquire_init(struct drm_modeset_acquire_ctx *ctx, memset(ctx, 0, sizeof(*ctx)); ww_acquire_init(&ctx->ww_ctx, &crtc_ww_class); INIT_LIST_HEAD(&ctx->locked); + + if (flags & DRM_MODESET_ACQUIRE_INTERRUPTIBLE) + ctx->interruptible = true; } EXPORT_SYMBOL(drm_modeset_acquire_init); @@ -261,8 +273,19 @@ static inline int modeset_lock(struct drm_modeset_lock *lock, return ret; } -static int modeset_backoff(struct drm_modeset_acquire_ctx *ctx, - bool interruptible) +/** + * drm_modeset_backoff - deadlock avoidance backoff + * @ctx: the acquire context + * + * If deadlock is detected (ie. drm_modeset_lock() returns -EDEADLK), + * you must call this function to drop all currently held locks and + * block until the contended lock becomes available. + * + * This function returns 0 on success, or -ERESTARTSYS if this context + * is initialized with %DRM_MODESET_ACQUIRE_INTERRUPTIBLE and the + * wait has been interrupted. + */ +int drm_modeset_backoff(struct drm_modeset_acquire_ctx *ctx) { struct drm_modeset_lock *contended = ctx->contended; @@ -273,36 +296,11 @@ static int modeset_backoff(struct drm_modeset_acquire_ctx *ctx, drm_modeset_drop_locks(ctx); - return modeset_lock(contended, ctx, interruptible, true); -} - -/** - * drm_modeset_backoff - deadlock avoidance backoff - * @ctx: the acquire context - * - * If deadlock is detected (ie. drm_modeset_lock() returns -EDEADLK), - * you must call this function to drop all currently held locks and - * block until the contended lock becomes available. - */ -void drm_modeset_backoff(struct drm_modeset_acquire_ctx *ctx) -{ - modeset_backoff(ctx, false); + return modeset_lock(contended, ctx, ctx->interruptible, true); } EXPORT_SYMBOL(drm_modeset_backoff); /** - * drm_modeset_backoff_interruptible - deadlock avoidance backoff - * @ctx: the acquire context - * - * Interruptible version of drm_modeset_backoff() - */ -int drm_modeset_backoff_interruptible(struct drm_modeset_acquire_ctx *ctx) -{ - return modeset_backoff(ctx, true); -} -EXPORT_SYMBOL(drm_modeset_backoff_interruptible); - -/** * drm_modeset_lock_init - initialize lock * @lock: lock to init */ @@ -324,14 +322,18 @@ EXPORT_SYMBOL(drm_modeset_lock_init); * deadlock scenario has been detected and it is an error to attempt * to take any more locks without first calling drm_modeset_backoff(). * + * If the @ctx is not NULL and initialized with + * %DRM_MODESET_ACQUIRE_INTERRUPTIBLE, this function will fail with + * -ERESTARTSYS when interrupted. + * * If @ctx is NULL then the function call behaves like a normal, - * non-nesting mutex_lock() call. + * uninterruptible non-nesting mutex_lock() call. */ int drm_modeset_lock(struct drm_modeset_lock *lock, struct drm_modeset_acquire_ctx *ctx) { if (ctx) - return modeset_lock(lock, ctx, false, false); + return modeset_lock(lock, ctx, ctx->interruptible, false); ww_mutex_lock(&lock->mutex, NULL); return 0; @@ -339,21 +341,19 @@ int drm_modeset_lock(struct drm_modeset_lock *lock, EXPORT_SYMBOL(drm_modeset_lock); /** - * drm_modeset_lock_interruptible - take modeset lock + * drm_modeset_lock_single_interruptible - take a single modeset lock * @lock: lock to take - * @ctx: acquire ctx * - * Interruptible version of drm_modeset_lock() + * This function behaves as drm_modeset_lock() with a NULL context, + * but performs interruptible waits. + * + * This function returns 0 on success, or -ERESTARTSYS when interrupted. */ -int drm_modeset_lock_interruptible(struct drm_modeset_lock *lock, - struct drm_modeset_acquire_ctx *ctx) +int drm_modeset_lock_single_interruptible(struct drm_modeset_lock *lock) { - if (ctx) - return modeset_lock(lock, ctx, true, false); - return ww_mutex_lock_interruptible(&lock->mutex, NULL); } -EXPORT_SYMBOL(drm_modeset_lock_interruptible); +EXPORT_SYMBOL(drm_modeset_lock_single_interruptible); /** * drm_modeset_unlock - drop modeset lock diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c index 7a00351..72cba98 100644 --- a/drivers/gpu/drm/drm_plane.c +++ b/drivers/gpu/drm/drm_plane.c @@ -667,7 +667,7 @@ static int setplane_internal(struct drm_plane *plane, struct drm_modeset_acquire_ctx ctx; int ret; - drm_modeset_acquire_init(&ctx, 0); + drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE); retry: ret = drm_modeset_lock_all_ctx(plane->dev, &ctx); if (ret) @@ -678,8 +678,9 @@ retry: fail: if (ret == -EDEADLK) { - drm_modeset_backoff(&ctx); - goto retry; + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry; } drm_modeset_drop_locks(&ctx); drm_modeset_acquire_fini(&ctx); @@ -834,7 +835,7 @@ static int drm_mode_cursor_common(struct drm_device *dev, return -ENOENT; } - drm_modeset_acquire_init(&ctx, 0); + drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE); retry: ret = drm_modeset_lock(&crtc->mutex, &ctx); if (ret) @@ -876,8 +877,9 @@ retry: } out: if (ret == -EDEADLK) { - drm_modeset_backoff(&ctx); - goto retry; + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry; } drm_modeset_drop_locks(&ctx); @@ -985,7 +987,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, return -EINVAL; } - drm_modeset_acquire_init(&ctx, 0); + drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE); retry: ret = drm_modeset_lock(&crtc->mutex, &ctx); if (ret) @@ -1074,8 +1076,9 @@ out: crtc->primary->old_fb = NULL; if (ret == -EDEADLK) { - drm_modeset_backoff(&ctx); - goto retry; + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry; } drm_modeset_drop_locks(&ctx); diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index 904966c..5840aab 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -353,8 +353,6 @@ EXPORT_SYMBOL(drm_helper_probe_detect); * drm_mode_probed_add(). New modes start their life with status as OK. * Modes are added from a single source using the following priority order. * - * - debugfs 'override_edid' (used for testing only) - * - firmware EDID (drm_load_edid_firmware()) * - &drm_connector_helper_funcs.get_modes vfunc * - if the connector status is connector_status_connected, standard * VESA DMT modes up to 1024x768 are automatically added @@ -483,22 +481,7 @@ retry: goto prune; } - if (connector->override_edid) { - struct edid *edid = (struct edid *) connector->edid_blob_ptr->data; - - count = drm_add_edid_modes(connector, edid); - drm_edid_to_eld(connector, edid); - } else { - struct edid *edid = drm_load_edid_firmware(connector); - if (!IS_ERR_OR_NULL(edid)) { - drm_mode_connector_update_edid_property(connector, edid); - count = drm_add_edid_modes(connector, edid); - drm_edid_to_eld(connector, edid); - kfree(edid); - } - if (count == 0) - count = (*connector_funcs->get_modes)(connector); - } + count = (*connector_funcs->get_modes)(connector); if (count == 0 && connector->status == connector_status_connected) count = drm_add_modes_noedid(connector, 1024, 768); diff --git a/drivers/gpu/drm/drm_scdc_helper.c b/drivers/gpu/drm/drm_scdc_helper.c index 935653e..657ea5a 100644 --- a/drivers/gpu/drm/drm_scdc_helper.c +++ b/drivers/gpu/drm/drm_scdc_helper.c @@ -134,7 +134,6 @@ EXPORT_SYMBOL(drm_scdc_write); * Returns: * True if the scrambling is enabled, false otherwise. */ - bool drm_scdc_get_scrambling_status(struct i2c_adapter *adapter) { u8 status; @@ -142,7 +141,7 @@ bool drm_scdc_get_scrambling_status(struct i2c_adapter *adapter) ret = drm_scdc_readb(adapter, SCDC_SCRAMBLER_STATUS, &status); if (ret < 0) { - DRM_ERROR("Failed to read scrambling status, error %d\n", ret); + DRM_ERROR("Failed to read scrambling status: %d\n", ret); return false; } @@ -162,7 +161,6 @@ EXPORT_SYMBOL(drm_scdc_get_scrambling_status); * Returns: * True if scrambling is set/reset successfully, false otherwise. */ - bool drm_scdc_set_scrambling(struct i2c_adapter *adapter, bool enable) { u8 config; @@ -170,7 +168,7 @@ bool drm_scdc_set_scrambling(struct i2c_adapter *adapter, bool enable) ret = drm_scdc_readb(adapter, SCDC_TMDS_CONFIG, &config); if (ret < 0) { - DRM_ERROR("Failed to read tmds config, err=%d\n", ret); + DRM_ERROR("Failed to read TMDS config: %d\n", ret); return false; } @@ -181,7 +179,7 @@ bool drm_scdc_set_scrambling(struct i2c_adapter *adapter, bool enable) ret = drm_scdc_writeb(adapter, SCDC_TMDS_CONFIG, config); if (ret < 0) { - DRM_ERROR("Failed to enable scrambling, error %d\n", ret); + DRM_ERROR("Failed to enable scrambling: %d\n", ret); return false; } @@ -225,7 +223,7 @@ bool drm_scdc_set_high_tmds_clock_ratio(struct i2c_adapter *adapter, bool set) ret = drm_scdc_readb(adapter, SCDC_TMDS_CONFIG, &config); if (ret < 0) { - DRM_ERROR("Failed to read tmds config, err=%d\n", ret); + DRM_ERROR("Failed to read TMDS config: %d\n", ret); return false; } @@ -236,7 +234,7 @@ bool drm_scdc_set_high_tmds_clock_ratio(struct i2c_adapter *adapter, bool set) ret = drm_scdc_writeb(adapter, SCDC_TMDS_CONFIG, config); if (ret < 0) { - DRM_ERROR("Failed to set TMDS clock ratio, error %d\n", ret); + DRM_ERROR("Failed to set TMDS clock ratio: %d\n", ret); return false; } diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c index 0422b8c..26d6061 100644 --- a/drivers/gpu/drm/drm_syncobj.c +++ b/drivers/gpu/drm/drm_syncobj.c @@ -417,8 +417,8 @@ static int drm_syncobj_fd_to_handle(struct drm_file *file_private, return 0; } -int drm_syncobj_import_sync_file_fence(struct drm_file *file_private, - int fd, int handle) +static int drm_syncobj_import_sync_file_fence(struct drm_file *file_private, + int fd, int handle) { struct dma_fence *fence = sync_file_get_fence(fd); struct drm_syncobj *syncobj; @@ -438,8 +438,8 @@ int drm_syncobj_import_sync_file_fence(struct drm_file *file_private, return 0; } -int drm_syncobj_export_sync_file(struct drm_file *file_private, - int handle, int *p_fd) +static int drm_syncobj_export_sync_file(struct drm_file *file_private, + int handle, int *p_fd) { int ret; struct dma_fence *fence; diff --git a/drivers/gpu/drm/drm_trace.h b/drivers/gpu/drm/drm_trace.h index 14c5a77..16c64d0 100644 --- a/drivers/gpu/drm/drm_trace.h +++ b/drivers/gpu/drm/drm_trace.h @@ -61,5 +61,5 @@ TRACE_EVENT(drm_vblank_event_delivered, /* This part must be outside protection */ #undef TRACE_INCLUDE_PATH -#define TRACE_INCLUDE_PATH . +#define TRACE_INCLUDE_PATH ../../drivers/gpu/drm #include <trace/define_trace.h> diff --git a/drivers/gpu/drm/exynos/exynos_drm_mic.c b/drivers/gpu/drm/exynos/exynos_drm_mic.c index ba4a32b..2174814 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_mic.c +++ b/drivers/gpu/drm/exynos/exynos_drm_mic.c @@ -420,11 +420,7 @@ static int exynos_mic_probe(struct platform_device *pdev) mic->bridge.funcs = &mic_bridge_funcs; mic->bridge.of_node = dev->of_node; - ret = drm_bridge_add(&mic->bridge); - if (ret) { - DRM_ERROR("mic: Failed to add MIC to the global bridge list\n"); - return ret; - } + drm_bridge_add(&mic->bridge); pm_runtime_enable(dev); diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c index c52f9ad..a4bb89b 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_dp.c +++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c @@ -1901,10 +1901,8 @@ cdv_intel_dp_destroy(struct drm_connector *connector) if (is_edp(gma_encoder)) { /* cdv_intel_panel_destroy_backlight(connector->dev); */ - if (intel_dp->panel_fixed_mode) { - kfree(intel_dp->panel_fixed_mode); - intel_dp->panel_fixed_mode = NULL; - } + kfree(intel_dp->panel_fixed_mode); + intel_dp->panel_fixed_mode = NULL; } i2c_del_adapter(&intel_dp->adapter); drm_connector_unregister(connector); diff --git a/drivers/gpu/drm/gma500/mdfld_intel_display.c b/drivers/gpu/drm/gma500/mdfld_intel_display.c index 531e4450..5c06644 100644 --- a/drivers/gpu/drm/gma500/mdfld_intel_display.c +++ b/drivers/gpu/drm/gma500/mdfld_intel_display.c @@ -99,7 +99,7 @@ void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe) /* Wait for for the pipe enable to take effect. */ for (count = 0; count < COUNT_MAX; count++) { temp = REG_READ(map->conf); - if ((temp & PIPEACONF_PIPE_STATE) == 1) + if (temp & PIPEACONF_PIPE_STATE) break; } } diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c b/drivers/gpu/drm/i2c/ch7006_drv.c index e9e8ae2..544a8a2 100644 --- a/drivers/gpu/drm/i2c/ch7006_drv.c +++ b/drivers/gpu/drm/i2c/ch7006_drv.c @@ -485,7 +485,7 @@ static int ch7006_encoder_init(struct i2c_client *client, return 0; } -static struct i2c_device_id ch7006_ids[] = { +static const struct i2c_device_id ch7006_ids[] = { { "ch7006", 0 }, { } }; diff --git a/drivers/gpu/drm/i2c/sil164_drv.c b/drivers/gpu/drm/i2c/sil164_drv.c index db0b03f..ecaa587 100644 --- a/drivers/gpu/drm/i2c/sil164_drv.c +++ b/drivers/gpu/drm/i2c/sil164_drv.c @@ -415,7 +415,7 @@ sil164_encoder_init(struct i2c_client *client, return 0; } -static struct i2c_device_id sil164_ids[] = { +static const struct i2c_device_id sil164_ids[] = { { "sil164", 0 }, { } }; diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index 54e3255..4d1f45a 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -1746,7 +1746,7 @@ static const struct of_device_id tda998x_dt_ids[] = { MODULE_DEVICE_TABLE(of, tda998x_dt_ids); #endif -static struct i2c_device_id tda998x_ids[] = { +static const struct i2c_device_id tda998x_ids[] = { { "tda998x", 0 }, { } }; diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 892f52b..1cb8059 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -150,5 +150,3 @@ endif i915-y += intel_lpe_audio.o obj-$(CONFIG_DRM_I915) += i915.o - -CFLAGS_i915_trace_points.o := -I$(src) diff --git a/drivers/gpu/drm/i915/gvt/aperture_gm.c b/drivers/gpu/drm/i915/gvt/aperture_gm.c index ca3d192..7c9ec4f 100644 --- a/drivers/gpu/drm/i915/gvt/aperture_gm.c +++ b/drivers/gpu/drm/i915/gvt/aperture_gm.c @@ -173,8 +173,8 @@ static void free_vgpu_fence(struct intel_vgpu *vgpu) _clear_vgpu_fence(vgpu); for (i = 0; i < vgpu_fence_sz(vgpu); i++) { reg = vgpu->fence.regs[i]; - list_add_tail(®->link, - &dev_priv->mm.fence_list); + i915_unreserve_fence(reg); + vgpu->fence.regs[i] = NULL; } mutex_unlock(&dev_priv->drm.struct_mutex); @@ -187,24 +187,19 @@ static int alloc_vgpu_fence(struct intel_vgpu *vgpu) struct drm_i915_private *dev_priv = gvt->dev_priv; struct drm_i915_fence_reg *reg; int i; - struct list_head *pos, *q; intel_runtime_pm_get(dev_priv); /* Request fences from host */ mutex_lock(&dev_priv->drm.struct_mutex); - i = 0; - list_for_each_safe(pos, q, &dev_priv->mm.fence_list) { - reg = list_entry(pos, struct drm_i915_fence_reg, link); - if (reg->pin_count || reg->vma) - continue; - list_del(pos); + + for (i = 0; i < vgpu_fence_sz(vgpu); i++) { + reg = i915_reserve_fence(dev_priv); + if (IS_ERR(reg)) + goto out_free_fence; + vgpu->fence.regs[i] = reg; - if (++i == vgpu_fence_sz(vgpu)) - break; } - if (i != vgpu_fence_sz(vgpu)) - goto out_free_fence; _clear_vgpu_fence(vgpu); @@ -212,13 +207,14 @@ static int alloc_vgpu_fence(struct intel_vgpu *vgpu) intel_runtime_pm_put(dev_priv); return 0; out_free_fence: + gvt_vgpu_err("Failed to alloc fences\n"); /* Return fences to host, if fail */ for (i = 0; i < vgpu_fence_sz(vgpu); i++) { reg = vgpu->fence.regs[i]; if (!reg) continue; - list_add_tail(®->link, - &dev_priv->mm.fence_list); + i915_unreserve_fence(reg); + vgpu->fence.regs[i] = NULL; } mutex_unlock(&dev_priv->drm.struct_mutex); intel_runtime_pm_put(dev_priv); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 9f45cfe..ff70fc4 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -239,7 +239,8 @@ static void intel_detect_pch(struct drm_i915_private *dev_priv) dev_priv->pch_type = PCH_KBP; DRM_DEBUG_KMS("Found Kaby Lake PCH (KBP)\n"); WARN_ON(!IS_SKYLAKE(dev_priv) && - !IS_KABYLAKE(dev_priv)); + !IS_KABYLAKE(dev_priv) && + !IS_COFFEELAKE(dev_priv)); } else if (id == INTEL_PCH_CNP_DEVICE_ID_TYPE) { dev_priv->pch_type = PCH_CNP; DRM_DEBUG_KMS("Found Cannon Lake PCH (CNP)\n"); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 18d9da5..b1fa813 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -80,8 +80,8 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20170818" -#define DRIVER_TIMESTAMP 1503088845 +#define DRIVER_DATE "20170907" +#define DRIVER_TIMESTAMP 1504772900 /* Use I915_STATE_WARN(x) and I915_STATE_WARN_ON() (rather than WARN() and * WARN_ON()) for hw state sanity checks to check for unexpected conditions @@ -569,6 +569,24 @@ struct i915_hotplug { (__i)++) \ for_each_if (plane_state) +#define for_each_new_intel_crtc_in_state(__state, crtc, new_crtc_state, __i) \ + for ((__i) = 0; \ + (__i) < (__state)->base.dev->mode_config.num_crtc && \ + ((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \ + (new_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].new_state), 1); \ + (__i)++) \ + for_each_if (crtc) + + +#define for_each_oldnew_intel_plane_in_state(__state, plane, old_plane_state, new_plane_state, __i) \ + for ((__i) = 0; \ + (__i) < (__state)->base.dev->mode_config.num_total_plane && \ + ((plane) = to_intel_plane((__state)->base.planes[__i].ptr), \ + (old_plane_state) = to_intel_plane_state((__state)->base.planes[__i].old_state), \ + (new_plane_state) = to_intel_plane_state((__state)->base.planes[__i].new_state), 1); \ + (__i)++) \ + for_each_if (plane) + struct drm_i915_private; struct i915_mm_struct; struct i915_mmu_object; @@ -707,8 +725,7 @@ struct drm_i915_display_funcs { struct drm_atomic_state *old_state); void (*crtc_disable)(struct intel_crtc_state *old_crtc_state, struct drm_atomic_state *old_state); - void (*update_crtcs)(struct drm_atomic_state *state, - unsigned int *crtc_vblank_mask); + void (*update_crtcs)(struct drm_atomic_state *state); void (*audio_codec_enable)(struct drm_connector *connector, struct intel_encoder *encoder, const struct drm_display_mode *adjusted_mode); @@ -842,6 +859,7 @@ struct intel_device_info { u8 gen; u16 gen_mask; enum intel_platform platform; + u8 gt; /* GT number, 0 if undefined */ u8 ring_mask; /* Rings supported by the HW */ u8 num_rings; #define DEFINE_FLAG(name) u8 name:1 @@ -1107,6 +1125,7 @@ struct intel_fbc { } fb; int cfb_size; + unsigned int gen9_wa_cfb_stride; } params; struct intel_fbc_work { @@ -1465,6 +1484,11 @@ struct i915_gem_mm { struct llist_head free_list; struct work_struct free_work; + /** + * Small stash of WC pages + */ + struct pagevec wc_stash; + /** Usable portion of the GTT for GEM */ dma_addr_t stolen_base; /* limited to low memory (32-bit) */ @@ -1718,7 +1742,7 @@ struct intel_vbt_data { int crt_ddc_pin; int child_dev_num; - union child_device_config *child_dev; + struct child_device_config *child_dev; struct ddi_vbt_port_info ddi_port_info[I915_MAX_PORTS]; struct sdvo_device_mapping sdvo_mappings[2]; @@ -2329,7 +2353,8 @@ struct drm_i915_private { struct mutex dpll_lock; unsigned int active_crtcs; - unsigned int min_pixclk[I915_MAX_PIPES]; + /* minimum acceptable cdclk for each pipe */ + int min_cdclk[I915_MAX_PIPES]; int dpio_phy_iosf_port[I915_NUM_PHYS_VLV]; @@ -2862,9 +2887,8 @@ intel_info(const struct drm_i915_private *dev_priv) #define IS_G33(dev_priv) ((dev_priv)->info.platform == INTEL_G33) #define IS_IRONLAKE_M(dev_priv) (INTEL_DEVID(dev_priv) == 0x0046) #define IS_IVYBRIDGE(dev_priv) ((dev_priv)->info.platform == INTEL_IVYBRIDGE) -#define IS_IVB_GT1(dev_priv) (INTEL_DEVID(dev_priv) == 0x0156 || \ - INTEL_DEVID(dev_priv) == 0x0152 || \ - INTEL_DEVID(dev_priv) == 0x015a) +#define IS_IVB_GT1(dev_priv) (IS_IVYBRIDGE(dev_priv) && \ + (dev_priv)->info.gt == 1) #define IS_VALLEYVIEW(dev_priv) ((dev_priv)->info.platform == INTEL_VALLEYVIEW) #define IS_CHERRYVIEW(dev_priv) ((dev_priv)->info.platform == INTEL_CHERRYVIEW) #define IS_HASWELL(dev_priv) ((dev_priv)->info.platform == INTEL_HASWELL) @@ -2886,11 +2910,11 @@ intel_info(const struct drm_i915_private *dev_priv) #define IS_BDW_ULX(dev_priv) (IS_BROADWELL(dev_priv) && \ (INTEL_DEVID(dev_priv) & 0xf) == 0xe) #define IS_BDW_GT3(dev_priv) (IS_BROADWELL(dev_priv) && \ - (INTEL_DEVID(dev_priv) & 0x00F0) == 0x0020) + (dev_priv)->info.gt == 3) #define IS_HSW_ULT(dev_priv) (IS_HASWELL(dev_priv) && \ (INTEL_DEVID(dev_priv) & 0xFF00) == 0x0A00) #define IS_HSW_GT3(dev_priv) (IS_HASWELL(dev_priv) && \ - (INTEL_DEVID(dev_priv) & 0x00F0) == 0x0020) + (dev_priv)->info.gt == 3) /* ULX machines are also considered ULT. */ #define IS_HSW_ULX(dev_priv) (INTEL_DEVID(dev_priv) == 0x0A0E || \ INTEL_DEVID(dev_priv) == 0x0A1E) @@ -2911,15 +2935,15 @@ intel_info(const struct drm_i915_private *dev_priv) INTEL_DEVID(dev_priv) == 0x5915 || \ INTEL_DEVID(dev_priv) == 0x591E) #define IS_SKL_GT2(dev_priv) (IS_SKYLAKE(dev_priv) && \ - (INTEL_DEVID(dev_priv) & 0x00F0) == 0x0010) + (dev_priv)->info.gt == 2) #define IS_SKL_GT3(dev_priv) (IS_SKYLAKE(dev_priv) && \ - (INTEL_DEVID(dev_priv) & 0x00F0) == 0x0020) + (dev_priv)->info.gt == 3) #define IS_SKL_GT4(dev_priv) (IS_SKYLAKE(dev_priv) && \ - (INTEL_DEVID(dev_priv) & 0x00F0) == 0x0030) + (dev_priv)->info.gt == 4) #define IS_KBL_GT2(dev_priv) (IS_KABYLAKE(dev_priv) && \ - (INTEL_DEVID(dev_priv) & 0x00F0) == 0x0010) + (dev_priv)->info.gt == 2) #define IS_KBL_GT3(dev_priv) (IS_KABYLAKE(dev_priv) && \ - (INTEL_DEVID(dev_priv) & 0x00F0) == 0x0020) + (dev_priv)->info.gt == 3) #define IS_CFL_ULT(dev_priv) (IS_COFFEELAKE(dev_priv) && \ (INTEL_DEVID(dev_priv) & 0x00F0) == 0x00A0) @@ -3648,6 +3672,9 @@ i915_vm_to_ppgtt(struct i915_address_space *vm) /* i915_gem_fence_reg.c */ int __must_check i915_vma_get_fence(struct i915_vma *vma); int __must_check i915_vma_put_fence(struct i915_vma *vma); +struct drm_i915_fence_reg * +i915_reserve_fence(struct drm_i915_private *dev_priv); +void i915_unreserve_fence(struct drm_i915_fence_reg *fence); void i915_gem_revoke_fences(struct drm_i915_private *dev_priv); void i915_gem_restore_fences(struct drm_i915_private *dev_priv); @@ -4333,11 +4360,4 @@ int remap_io_mapping(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn, unsigned long size, struct io_mapping *iomap); -static inline bool -intel_engine_can_store_dword(struct intel_engine_cs *engine) -{ - return __intel_engine_can_store_dword(INTEL_GEN(engine->i915), - engine->class); -} - #endif diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 19404c9..8f074c7f 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1013,17 +1013,20 @@ gtt_user_read(struct io_mapping *mapping, loff_t base, int offset, char __user *user_data, int length) { - void *vaddr; + void __iomem *vaddr; unsigned long unwritten; /* We can use the cpu mem copy function because this is X86. */ - vaddr = (void __force *)io_mapping_map_atomic_wc(mapping, base); - unwritten = __copy_to_user_inatomic(user_data, vaddr + offset, length); + vaddr = io_mapping_map_atomic_wc(mapping, base); + unwritten = __copy_to_user_inatomic(user_data, + (void __force *)vaddr + offset, + length); io_mapping_unmap_atomic(vaddr); if (unwritten) { - vaddr = (void __force *) - io_mapping_map_wc(mapping, base, PAGE_SIZE); - unwritten = copy_to_user(user_data, vaddr + offset, length); + vaddr = io_mapping_map_wc(mapping, base, PAGE_SIZE); + unwritten = copy_to_user(user_data, + (void __force *)vaddr + offset, + length); io_mapping_unmap(vaddr); } return unwritten; @@ -1189,18 +1192,18 @@ ggtt_write(struct io_mapping *mapping, loff_t base, int offset, char __user *user_data, int length) { - void *vaddr; + void __iomem *vaddr; unsigned long unwritten; /* We can use the cpu mem copy function because this is X86. */ - vaddr = (void __force *)io_mapping_map_atomic_wc(mapping, base); - unwritten = __copy_from_user_inatomic_nocache(vaddr + offset, + vaddr = io_mapping_map_atomic_wc(mapping, base); + unwritten = __copy_from_user_inatomic_nocache((void __force *)vaddr + offset, user_data, length); io_mapping_unmap_atomic(vaddr); if (unwritten) { - vaddr = (void __force *) - io_mapping_map_wc(mapping, base, PAGE_SIZE); - unwritten = copy_from_user(vaddr + offset, user_data, length); + vaddr = io_mapping_map_wc(mapping, base, PAGE_SIZE); + unwritten = copy_from_user((void __force *)vaddr + offset, + user_data, length); io_mapping_unmap(vaddr); } @@ -2476,8 +2479,6 @@ static int ____i915_gem_object_get_pages(struct drm_i915_gem_object *obj) { struct sg_table *pages; - GEM_BUG_ON(i915_gem_object_has_pinned_pages(obj)); - if (unlikely(obj->mm.madv != I915_MADV_WILLNEED)) { DRM_DEBUG("Attempting to obtain a purgeable object\n"); return -EFAULT; @@ -2507,6 +2508,8 @@ int __i915_gem_object_get_pages(struct drm_i915_gem_object *obj) return err; if (unlikely(IS_ERR_OR_NULL(obj->mm.pages))) { + GEM_BUG_ON(i915_gem_object_has_pinned_pages(obj)); + err = ____i915_gem_object_get_pages(obj); if (err) goto unlock; @@ -2590,6 +2593,8 @@ void *i915_gem_object_pin_map(struct drm_i915_gem_object *obj, if (!atomic_inc_not_zero(&obj->mm.pages_pin_count)) { if (unlikely(IS_ERR_OR_NULL(obj->mm.pages))) { + GEM_BUG_ON(i915_gem_object_has_pinned_pages(obj)); + ret = ____i915_gem_object_get_pages(obj); if (ret) goto err_unlock; @@ -3257,11 +3262,11 @@ void i915_gem_close_object(struct drm_gem_object *gem, struct drm_file *file) struct i915_gem_context *ctx = lut->ctx; struct i915_vma *vma; + GEM_BUG_ON(ctx->file_priv == ERR_PTR(-EBADF)); if (ctx->file_priv != fpriv) continue; vma = radix_tree_delete(&ctx->handles_vma, lut->handle); - GEM_BUG_ON(vma->obj != obj); /* We allow the process to have multiple handles to the same @@ -3375,24 +3380,12 @@ static int wait_for_timeline(struct i915_gem_timeline *tl, unsigned int flags) return 0; } -static int wait_for_engine(struct intel_engine_cs *engine, int timeout_ms) -{ - return wait_for(intel_engine_is_idle(engine), timeout_ms); -} - static int wait_for_engines(struct drm_i915_private *i915) { - struct intel_engine_cs *engine; - enum intel_engine_id id; - - for_each_engine(engine, i915, id) { - if (GEM_WARN_ON(wait_for_engine(engine, 50))) { - i915_gem_set_wedged(i915); - return -EIO; - } - - GEM_BUG_ON(intel_engine_get_seqno(engine) != - intel_engine_last_submit(engine)); + if (wait_for(intel_engines_are_idle(i915), 50)) { + DRM_ERROR("Failed to idle engines, declaring wedged!\n"); + i915_gem_set_wedged(i915); + return -EIO; } return 0; @@ -4426,6 +4419,7 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915, llist_for_each_entry_safe(obj, on, freed, freed) { GEM_BUG_ON(obj->bind_count); GEM_BUG_ON(atomic_read(&obj->frontbuffer_bits)); + GEM_BUG_ON(!list_empty(&obj->lut_list)); if (obj->ops->release) obj->ops->release(obj); @@ -4533,6 +4527,12 @@ static void assert_kernel_context_is_current(struct drm_i915_private *dev_priv) void i915_gem_sanitize(struct drm_i915_private *i915) { + if (i915_terminally_wedged(&i915->gpu_error)) { + mutex_lock(&i915->drm.struct_mutex); + i915_gem_unset_wedged(i915); + mutex_unlock(&i915->drm.struct_mutex); + } + /* * If we inherit context state from the BIOS or earlier occupants * of the GPU, the GPU may be in an inconsistent state when we @@ -4572,7 +4572,7 @@ int i915_gem_suspend(struct drm_i915_private *dev_priv) ret = i915_gem_wait_for_idle(dev_priv, I915_WAIT_INTERRUPTIBLE | I915_WAIT_LOCKED); - if (ret) + if (ret && ret != -EIO) goto err_unlock; assert_kernel_context_is_current(dev_priv); @@ -4594,7 +4594,8 @@ int i915_gem_suspend(struct drm_i915_private *dev_priv) * reset the GPU back to its idle, low power state. */ WARN_ON(dev_priv->gt.awake); - WARN_ON(!intel_engines_are_idle(dev_priv)); + if (WARN_ON(!intel_engines_are_idle(dev_priv))) + i915_gem_set_wedged(dev_priv); /* no hope, discard everything */ /* * Neither the BIOS, ourselves or any other kernel @@ -4616,11 +4617,12 @@ int i915_gem_suspend(struct drm_i915_private *dev_priv) * machine in an unusable condition. */ i915_gem_sanitize(dev_priv); - goto out_rpm_put; + + intel_runtime_pm_put(dev_priv); + return 0; err_unlock: mutex_unlock(&dev->struct_mutex); -out_rpm_put: intel_runtime_pm_put(dev_priv); return ret; } diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 92437f4..ca0eab3 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -268,6 +268,11 @@ static inline u64 gen8_noncanonical_addr(u64 address) return address & GENMASK_ULL(GEN8_HIGH_ADDRESS_BIT, 0); } +static inline bool eb_use_cmdparser(const struct i915_execbuffer *eb) +{ + return eb->engine->needs_cmd_parser && eb->batch_len; +} + static int eb_create(struct i915_execbuffer *eb) { if (!(eb->args->flags & I915_EXEC_HANDLE_LUT)) { @@ -1159,6 +1164,13 @@ static u32 *reloc_gpu(struct i915_execbuffer *eb, if (unlikely(!cache->rq)) { int err; + /* If we need to copy for the cmdparser, we will stall anyway */ + if (eb_use_cmdparser(eb)) + return ERR_PTR(-EWOULDBLOCK); + + if (!intel_engine_can_store_dword(eb->engine)) + return ERR_PTR(-ENODEV); + err = __reloc_gpu_alloc(eb, vma, len); if (unlikely(err)) return ERR_PTR(err); @@ -1183,9 +1195,7 @@ relocate_entry(struct i915_vma *vma, if (!eb->reloc_cache.vaddr && (DBG_FORCE_RELOC == FORCE_GPU_RELOC || - !reservation_object_test_signaled_rcu(vma->resv, true)) && - __intel_engine_can_store_dword(eb->reloc_cache.gen, - eb->engine->class)) { + !reservation_object_test_signaled_rcu(vma->resv, true))) { const unsigned int gen = eb->reloc_cache.gen; unsigned int len; u32 *batch; @@ -2291,7 +2301,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, goto err_vma; } - if (eb.engine->needs_cmd_parser && eb.batch_len) { + if (eb_use_cmdparser(&eb)) { struct i915_vma *vma; vma = eb_parse(&eb, drm_is_current_master(file)); diff --git a/drivers/gpu/drm/i915/i915_gem_fence_reg.c b/drivers/gpu/drm/i915/i915_gem_fence_reg.c index 5fe2cd8..2783d63 100644 --- a/drivers/gpu/drm/i915/i915_gem_fence_reg.c +++ b/drivers/gpu/drm/i915/i915_gem_fence_reg.c @@ -360,6 +360,57 @@ i915_vma_get_fence(struct i915_vma *vma) } /** + * i915_reserve_fence - Reserve a fence for vGPU + * @dev_priv: i915 device private + * + * This function walks the fence regs looking for a free one and remove + * it from the fence_list. It is used to reserve fence for vGPU to use. + */ +struct drm_i915_fence_reg * +i915_reserve_fence(struct drm_i915_private *dev_priv) +{ + struct drm_i915_fence_reg *fence; + int count; + int ret; + + lockdep_assert_held(&dev_priv->drm.struct_mutex); + + /* Keep at least one fence available for the display engine. */ + count = 0; + list_for_each_entry(fence, &dev_priv->mm.fence_list, link) + count += !fence->pin_count; + if (count <= 1) + return ERR_PTR(-ENOSPC); + + fence = fence_find(dev_priv); + if (IS_ERR(fence)) + return fence; + + if (fence->vma) { + /* Force-remove fence from VMA */ + ret = fence_update(fence, NULL); + if (ret) + return ERR_PTR(ret); + } + + list_del(&fence->link); + return fence; +} + +/** + * i915_unreserve_fence - Reclaim a reserved fence + * @fence: the fence reg + * + * This function add a reserved fence register from vGPU to the fence_list. + */ +void i915_unreserve_fence(struct drm_i915_fence_reg *fence) +{ + lockdep_assert_held(&fence->i915->drm.struct_mutex); + + list_add(&fence->link, &fence->i915->mm.fence_list); +} + +/** * i915_gem_revoke_fences - revoke fence state * @dev_priv: i915 device private * diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index e2410eb..40d446b 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -356,39 +356,86 @@ static gen6_pte_t iris_pte_encode(dma_addr_t addr, static struct page *vm_alloc_page(struct i915_address_space *vm, gfp_t gfp) { - struct page *page; + struct pagevec *pvec = &vm->free_pages; if (I915_SELFTEST_ONLY(should_fail(&vm->fault_attr, 1))) i915_gem_shrink_all(vm->i915); - if (vm->free_pages.nr) - return vm->free_pages.pages[--vm->free_pages.nr]; + if (likely(pvec->nr)) + return pvec->pages[--pvec->nr]; + + if (!vm->pt_kmap_wc) + return alloc_page(gfp); + + /* A placeholder for a specific mutex to guard the WC stash */ + lockdep_assert_held(&vm->i915->drm.struct_mutex); + + /* Look in our global stash of WC pages... */ + pvec = &vm->i915->mm.wc_stash; + if (likely(pvec->nr)) + return pvec->pages[--pvec->nr]; - page = alloc_page(gfp); - if (!page) + /* Otherwise batch allocate pages to amoritize cost of set_pages_wc. */ + do { + struct page *page; + + page = alloc_page(gfp); + if (unlikely(!page)) + break; + + pvec->pages[pvec->nr++] = page; + } while (pagevec_space(pvec)); + + if (unlikely(!pvec->nr)) return NULL; - if (vm->pt_kmap_wc) - set_pages_array_wc(&page, 1); + set_pages_array_wc(pvec->pages, pvec->nr); - return page; + return pvec->pages[--pvec->nr]; } -static void vm_free_pages_release(struct i915_address_space *vm) +static void vm_free_pages_release(struct i915_address_space *vm, + bool immediate) { - GEM_BUG_ON(!pagevec_count(&vm->free_pages)); + struct pagevec *pvec = &vm->free_pages; + + GEM_BUG_ON(!pagevec_count(pvec)); + + if (vm->pt_kmap_wc) { + struct pagevec *stash = &vm->i915->mm.wc_stash; - if (vm->pt_kmap_wc) - set_pages_array_wb(vm->free_pages.pages, - pagevec_count(&vm->free_pages)); + /* When we use WC, first fill up the global stash and then + * only if full immediately free the overflow. + */ + + lockdep_assert_held(&vm->i915->drm.struct_mutex); + if (pagevec_space(stash)) { + do { + stash->pages[stash->nr++] = + pvec->pages[--pvec->nr]; + if (!pvec->nr) + return; + } while (pagevec_space(stash)); + + /* As we have made some room in the VM's free_pages, + * we can wait for it to fill again. Unless we are + * inside i915_address_space_fini() and must + * immediately release the pages! + */ + if (!immediate) + return; + } + + set_pages_array_wb(pvec->pages, pvec->nr); + } - __pagevec_release(&vm->free_pages); + __pagevec_release(pvec); } static void vm_free_page(struct i915_address_space *vm, struct page *page) { if (!pagevec_add(&vm->free_pages, page)) - vm_free_pages_release(vm); + vm_free_pages_release(vm, false); } static int __setup_page_dma(struct i915_address_space *vm, @@ -452,12 +499,31 @@ static void fill_page_dma_32(struct i915_address_space *vm, static int setup_scratch_page(struct i915_address_space *vm, gfp_t gfp) { - return __setup_page_dma(vm, &vm->scratch_page, gfp | __GFP_ZERO); + struct page *page; + dma_addr_t addr; + + page = alloc_page(gfp | __GFP_ZERO); + if (unlikely(!page)) + return -ENOMEM; + + addr = dma_map_page(vm->dma, page, 0, PAGE_SIZE, + PCI_DMA_BIDIRECTIONAL); + if (unlikely(dma_mapping_error(vm->dma, addr))) { + __free_page(page); + return -ENOMEM; + } + + vm->scratch_page.page = page; + vm->scratch_page.daddr = addr; + return 0; } static void cleanup_scratch_page(struct i915_address_space *vm) { - cleanup_page_dma(vm, &vm->scratch_page); + struct i915_page_dma *p = &vm->scratch_page; + + dma_unmap_page(vm->dma, p->daddr, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + __free_page(p->page); } static struct i915_page_table *alloc_pt(struct i915_address_space *vm) @@ -1337,18 +1403,18 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt) 1ULL << 48 : 1ULL << 32; - ret = gen8_init_scratch(&ppgtt->base); - if (ret) { - ppgtt->base.total = 0; - return ret; - } - /* There are only few exceptions for gen >=6. chv and bxt. * And we are not sure about the latter so play safe for now. */ if (IS_CHERRYVIEW(dev_priv) || IS_BROXTON(dev_priv)) ppgtt->base.pt_kmap_wc = true; + ret = gen8_init_scratch(&ppgtt->base); + if (ret) { + ppgtt->base.total = 0; + return ret; + } + if (use_4lvl(vm)) { ret = setup_px(&ppgtt->base, &ppgtt->pml4); if (ret) @@ -1872,7 +1938,7 @@ static void i915_address_space_init(struct i915_address_space *vm, static void i915_address_space_fini(struct i915_address_space *vm) { if (pagevec_count(&vm->free_pages)) - vm_free_pages_release(vm); + vm_free_pages_release(vm, true); i915_gem_timeline_fini(&vm->timeline); drm_mm_takedown(&vm->mm); @@ -1885,12 +1951,12 @@ static void gtt_write_workarounds(struct drm_i915_private *dev_priv) * called on driver load and after a GPU reset, so you can place * workarounds here even if they get overwritten by GPU reset. */ - /* WaIncreaseDefaultTLBEntries:chv,bdw,skl,bxt,kbl,glk,cfl */ + /* WaIncreaseDefaultTLBEntries:chv,bdw,skl,bxt,kbl,glk,cfl,cnl */ if (IS_BROADWELL(dev_priv)) I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_BDW); else if (IS_CHERRYVIEW(dev_priv)) I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_CHV); - else if (IS_GEN9_BC(dev_priv)) + else if (IS_GEN9_BC(dev_priv) || IS_GEN10(dev_priv)) I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_SKL); else if (IS_GEN9_LP(dev_priv)) I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_BXT); @@ -2598,6 +2664,7 @@ void i915_ggtt_cleanup_hw(struct drm_i915_private *dev_priv) { struct i915_ggtt *ggtt = &dev_priv->ggtt; struct i915_vma *vma, *vn; + struct pagevec *pvec; ggtt->base.closed = true; @@ -2621,6 +2688,13 @@ void i915_ggtt_cleanup_hw(struct drm_i915_private *dev_priv) } ggtt->base.cleanup(&ggtt->base); + + pvec = &dev_priv->mm.wc_stash; + if (pvec->nr) { + set_pages_array_wb(pvec->pages, pvec->nr); + __pagevec_release(pvec); + } + mutex_unlock(&dev_priv->drm.struct_mutex); arch_phys_wc_del(ggtt->mtrr); @@ -2716,13 +2790,13 @@ static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size) phys_addr = pci_resource_start(pdev, 0) + pci_resource_len(pdev, 0) / 2; /* - * On BXT writes larger than 64 bit to the GTT pagetable range will be - * dropped. For WC mappings in general we have 64 byte burst writes - * when the WC buffer is flushed, so we can't use it, but have to + * On BXT+/CNL+ writes larger than 64 bit to the GTT pagetable range + * will be dropped. For WC mappings in general we have 64 byte burst + * writes when the WC buffer is flushed, so we can't use it, but have to * resort to an uncached mapping. The WC issue is easily caught by the * readback check when writing GTT PTE entries. */ - if (IS_GEN9_LP(dev_priv)) + if (IS_GEN9_LP(dev_priv) || INTEL_GEN(dev_priv) >= 10) ggtt->gsm = ioremap_nocache(phys_addr, size); else ggtt->gsm = ioremap_wc(phys_addr, size); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index b63893e..2fe92d2 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -336,7 +336,7 @@ void gen6_mask_pm_irq(struct drm_i915_private *dev_priv, u32 mask) __gen6_mask_pm_irq(dev_priv, mask); } -void gen6_reset_pm_iir(struct drm_i915_private *dev_priv, u32 reset_mask) +static void gen6_reset_pm_iir(struct drm_i915_private *dev_priv, u32 reset_mask) { i915_reg_t reg = gen6_pm_iir(dev_priv); @@ -347,7 +347,7 @@ void gen6_reset_pm_iir(struct drm_i915_private *dev_priv, u32 reset_mask) POSTING_READ(reg); } -void gen6_enable_pm_irq(struct drm_i915_private *dev_priv, u32 enable_mask) +static void gen6_enable_pm_irq(struct drm_i915_private *dev_priv, u32 enable_mask) { lockdep_assert_held(&dev_priv->irq_lock); @@ -357,7 +357,7 @@ void gen6_enable_pm_irq(struct drm_i915_private *dev_priv, u32 enable_mask) /* unmask_pm_irq provides an implicit barrier (POSTING_READ) */ } -void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, u32 disable_mask) +static void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, u32 disable_mask) { lockdep_assert_held(&dev_priv->irq_lock); @@ -405,7 +405,7 @@ void gen6_disable_rps_interrupts(struct drm_i915_private *dev_priv) synchronize_irq(dev_priv->drm.irq); /* Now that we will not be generating any more work, flush any - * outsanding tasks. As we are called on the RPS idle path, + * outstanding tasks. As we are called on the RPS idle path, * we will reset the GPU to minimum frequencies, so the current * state of the worker can be discarded. */ diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 09d97e0..881b5d6 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -63,22 +63,23 @@ .hws_needs_physical = 1, \ .unfenced_needs_alignment = 1, \ .ring_mask = RENDER_RING, \ + .has_snoop = true, \ GEN_DEFAULT_PIPEOFFSETS, \ CURSOR_OFFSETS -static const struct intel_device_info intel_i830_info = { +static const struct intel_device_info intel_i830_info __initconst = { GEN2_FEATURES, .platform = INTEL_I830, .is_mobile = 1, .cursor_needs_physical = 1, .num_pipes = 2, /* legal, last one wins */ }; -static const struct intel_device_info intel_i845g_info = { +static const struct intel_device_info intel_i845g_info __initconst = { GEN2_FEATURES, .platform = INTEL_I845G, }; -static const struct intel_device_info intel_i85x_info = { +static const struct intel_device_info intel_i85x_info __initconst = { GEN2_FEATURES, .platform = INTEL_I85X, .is_mobile = 1, .num_pipes = 2, /* legal, last one wins */ @@ -86,7 +87,7 @@ static const struct intel_device_info intel_i85x_info = { .has_fbc = 1, }; -static const struct intel_device_info intel_i865g_info = { +static const struct intel_device_info intel_i865g_info __initconst = { GEN2_FEATURES, .platform = INTEL_I865G, }; @@ -95,10 +96,11 @@ static const struct intel_device_info intel_i865g_info = { .gen = 3, .num_pipes = 2, \ .has_gmch_display = 1, \ .ring_mask = RENDER_RING, \ + .has_snoop = true, \ GEN_DEFAULT_PIPEOFFSETS, \ CURSOR_OFFSETS -static const struct intel_device_info intel_i915g_info = { +static const struct intel_device_info intel_i915g_info __initconst = { GEN3_FEATURES, .platform = INTEL_I915G, .cursor_needs_physical = 1, .has_overlay = 1, .overlay_needs_physical = 1, @@ -106,7 +108,7 @@ static const struct intel_device_info intel_i915g_info = { .unfenced_needs_alignment = 1, }; -static const struct intel_device_info intel_i915gm_info = { +static const struct intel_device_info intel_i915gm_info __initconst = { GEN3_FEATURES, .platform = INTEL_I915GM, .is_mobile = 1, @@ -118,7 +120,7 @@ static const struct intel_device_info intel_i915gm_info = { .unfenced_needs_alignment = 1, }; -static const struct intel_device_info intel_i945g_info = { +static const struct intel_device_info intel_i945g_info __initconst = { GEN3_FEATURES, .platform = INTEL_I945G, .has_hotplug = 1, .cursor_needs_physical = 1, @@ -127,7 +129,7 @@ static const struct intel_device_info intel_i945g_info = { .unfenced_needs_alignment = 1, }; -static const struct intel_device_info intel_i945gm_info = { +static const struct intel_device_info intel_i945gm_info __initconst = { GEN3_FEATURES, .platform = INTEL_I945GM, .is_mobile = 1, .has_hotplug = 1, .cursor_needs_physical = 1, @@ -138,14 +140,14 @@ static const struct intel_device_info intel_i945gm_info = { .unfenced_needs_alignment = 1, }; -static const struct intel_device_info intel_g33_info = { +static const struct intel_device_info intel_g33_info __initconst = { GEN3_FEATURES, .platform = INTEL_G33, .has_hotplug = 1, .has_overlay = 1, }; -static const struct intel_device_info intel_pineview_info = { +static const struct intel_device_info intel_pineview_info __initconst = { GEN3_FEATURES, .platform = INTEL_PINEVIEW, .is_mobile = 1, .has_hotplug = 1, @@ -157,17 +159,18 @@ static const struct intel_device_info intel_pineview_info = { .has_hotplug = 1, \ .has_gmch_display = 1, \ .ring_mask = RENDER_RING, \ + .has_snoop = true, \ GEN_DEFAULT_PIPEOFFSETS, \ CURSOR_OFFSETS -static const struct intel_device_info intel_i965g_info = { +static const struct intel_device_info intel_i965g_info __initconst = { GEN4_FEATURES, .platform = INTEL_I965G, .has_overlay = 1, .hws_needs_physical = 1, }; -static const struct intel_device_info intel_i965gm_info = { +static const struct intel_device_info intel_i965gm_info __initconst = { GEN4_FEATURES, .platform = INTEL_I965GM, .is_mobile = 1, .has_fbc = 1, @@ -176,14 +179,14 @@ static const struct intel_device_info intel_i965gm_info = { .hws_needs_physical = 1, }; -static const struct intel_device_info intel_g45_info = { +static const struct intel_device_info intel_g45_info __initconst = { GEN4_FEATURES, .platform = INTEL_G45, .has_pipe_cxsr = 1, .ring_mask = RENDER_RING | BSD_RING, }; -static const struct intel_device_info intel_gm45_info = { +static const struct intel_device_info intel_gm45_info __initconst = { GEN4_FEATURES, .platform = INTEL_GM45, .is_mobile = 1, .has_fbc = 1, @@ -197,15 +200,16 @@ static const struct intel_device_info intel_gm45_info = { .has_hotplug = 1, \ .has_gmbus_irq = 1, \ .ring_mask = RENDER_RING | BSD_RING, \ + .has_snoop = true, \ GEN_DEFAULT_PIPEOFFSETS, \ CURSOR_OFFSETS -static const struct intel_device_info intel_ironlake_d_info = { +static const struct intel_device_info intel_ironlake_d_info __initconst = { GEN5_FEATURES, .platform = INTEL_IRONLAKE, }; -static const struct intel_device_info intel_ironlake_m_info = { +static const struct intel_device_info intel_ironlake_m_info __initconst = { GEN5_FEATURES, .platform = INTEL_IRONLAKE, .is_mobile = 1, .has_fbc = 1, @@ -224,15 +228,34 @@ static const struct intel_device_info intel_ironlake_m_info = { GEN_DEFAULT_PIPEOFFSETS, \ CURSOR_OFFSETS -static const struct intel_device_info intel_sandybridge_d_info = { - GEN6_FEATURES, - .platform = INTEL_SANDYBRIDGE, +#define SNB_D_PLATFORM \ + GEN6_FEATURES, \ + .platform = INTEL_SANDYBRIDGE + +static const struct intel_device_info intel_sandybridge_d_gt1_info __initconst = { + SNB_D_PLATFORM, + .gt = 1, }; -static const struct intel_device_info intel_sandybridge_m_info = { - GEN6_FEATURES, - .platform = INTEL_SANDYBRIDGE, - .is_mobile = 1, +static const struct intel_device_info intel_sandybridge_d_gt2_info __initconst = { + SNB_D_PLATFORM, + .gt = 2, +}; + +#define SNB_M_PLATFORM \ + GEN6_FEATURES, \ + .platform = INTEL_SANDYBRIDGE, \ + .is_mobile = 1 + + +static const struct intel_device_info intel_sandybridge_m_gt1_info __initconst = { + SNB_M_PLATFORM, + .gt = 1, +}; + +static const struct intel_device_info intel_sandybridge_m_gt2_info __initconst = { + SNB_M_PLATFORM, + .gt = 2, }; #define GEN7_FEATURES \ @@ -249,27 +272,46 @@ static const struct intel_device_info intel_sandybridge_m_info = { GEN_DEFAULT_PIPEOFFSETS, \ IVB_CURSOR_OFFSETS -static const struct intel_device_info intel_ivybridge_d_info = { - GEN7_FEATURES, - .platform = INTEL_IVYBRIDGE, - .has_l3_dpf = 1, +#define IVB_D_PLATFORM \ + GEN7_FEATURES, \ + .platform = INTEL_IVYBRIDGE, \ + .has_l3_dpf = 1 + +static const struct intel_device_info intel_ivybridge_d_gt1_info __initconst = { + IVB_D_PLATFORM, + .gt = 1, }; -static const struct intel_device_info intel_ivybridge_m_info = { - GEN7_FEATURES, - .platform = INTEL_IVYBRIDGE, - .is_mobile = 1, - .has_l3_dpf = 1, +static const struct intel_device_info intel_ivybridge_d_gt2_info __initconst = { + IVB_D_PLATFORM, + .gt = 2, +}; + +#define IVB_M_PLATFORM \ + GEN7_FEATURES, \ + .platform = INTEL_IVYBRIDGE, \ + .is_mobile = 1, \ + .has_l3_dpf = 1 + +static const struct intel_device_info intel_ivybridge_m_gt1_info __initconst = { + IVB_M_PLATFORM, + .gt = 1, +}; + +static const struct intel_device_info intel_ivybridge_m_gt2_info __initconst = { + IVB_M_PLATFORM, + .gt = 2, }; -static const struct intel_device_info intel_ivybridge_q_info = { +static const struct intel_device_info intel_ivybridge_q_info __initconst = { GEN7_FEATURES, .platform = INTEL_IVYBRIDGE, + .gt = 2, .num_pipes = 0, /* legal, last one wins */ .has_l3_dpf = 1, }; -static const struct intel_device_info intel_valleyview_info = { +static const struct intel_device_info intel_valleyview_info __initconst = { .platform = INTEL_VALLEYVIEW, .gen = 7, .is_lp = 1, @@ -282,6 +324,7 @@ static const struct intel_device_info intel_valleyview_info = { .has_hotplug = 1, .has_aliasing_ppgtt = 1, .has_full_ppgtt = 1, + .has_snoop = true, .ring_mask = RENDER_RING | BSD_RING | BLT_RING, .display_mmio_offset = VLV_DISPLAY_BASE, GEN_DEFAULT_PIPEOFFSETS, @@ -299,10 +342,24 @@ static const struct intel_device_info intel_valleyview_info = { .has_rc6p = 0 /* RC6p removed-by HSW */, \ .has_runtime_pm = 1 -static const struct intel_device_info intel_haswell_info = { - HSW_FEATURES, - .platform = INTEL_HASWELL, - .has_l3_dpf = 1, +#define HSW_PLATFORM \ + HSW_FEATURES, \ + .platform = INTEL_HASWELL, \ + .has_l3_dpf = 1 + +static const struct intel_device_info intel_haswell_gt1_info __initconst = { + HSW_PLATFORM, + .gt = 1, +}; + +static const struct intel_device_info intel_haswell_gt2_info __initconst = { + HSW_PLATFORM, + .gt = 2, +}; + +static const struct intel_device_info intel_haswell_gt3_info __initconst = { + HSW_PLATFORM, + .gt = 3, }; #define BDW_FEATURES \ @@ -318,16 +375,31 @@ static const struct intel_device_info intel_haswell_info = { .gen = 8, \ .platform = INTEL_BROADWELL -static const struct intel_device_info intel_broadwell_info = { +static const struct intel_device_info intel_broadwell_gt1_info __initconst = { BDW_PLATFORM, + .gt = 1, }; -static const struct intel_device_info intel_broadwell_gt3_info = { +static const struct intel_device_info intel_broadwell_gt2_info __initconst = { BDW_PLATFORM, + .gt = 2, +}; + +static const struct intel_device_info intel_broadwell_rsvd_info __initconst = { + BDW_PLATFORM, + .gt = 3, + /* According to the device ID those devices are GT3, they were + * previously treated as not GT3, keep it like that. + */ +}; + +static const struct intel_device_info intel_broadwell_gt3_info __initconst = { + BDW_PLATFORM, + .gt = 3, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING, }; -static const struct intel_device_info intel_cherryview_info = { +static const struct intel_device_info intel_cherryview_info __initconst = { .gen = 8, .num_pipes = 3, .has_hotplug = 1, .is_lp = 1, @@ -344,6 +416,7 @@ static const struct intel_device_info intel_cherryview_info = { .has_aliasing_ppgtt = 1, .has_full_ppgtt = 1, .has_reset_engine = 1, + .has_snoop = true, .display_mmio_offset = VLV_DISPLAY_BASE, GEN_CHV_PIPEOFFSETS, CURSOR_OFFSETS, @@ -358,13 +431,29 @@ static const struct intel_device_info intel_cherryview_info = { .has_guc = 1, \ .ddb_size = 896 -static const struct intel_device_info intel_skylake_info = { +static const struct intel_device_info intel_skylake_gt1_info __initconst = { SKL_PLATFORM, + .gt = 1, }; -static const struct intel_device_info intel_skylake_gt3_info = { +static const struct intel_device_info intel_skylake_gt2_info __initconst = { SKL_PLATFORM, - .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING, + .gt = 2, +}; + +#define SKL_GT3_PLUS_PLATFORM \ + SKL_PLATFORM, \ + .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING + + +static const struct intel_device_info intel_skylake_gt3_info __initconst = { + SKL_GT3_PLUS_PLATFORM, + .gt = 3, +}; + +static const struct intel_device_info intel_skylake_gt4_info __initconst = { + SKL_GT3_PLUS_PLATFORM, + .gt = 4, }; #define GEN9_LP_FEATURES \ @@ -390,18 +479,18 @@ static const struct intel_device_info intel_skylake_gt3_info = { .has_full_ppgtt = 1, \ .has_full_48bit_ppgtt = 1, \ .has_reset_engine = 1, \ + .has_snoop = true, \ GEN_DEFAULT_PIPEOFFSETS, \ IVB_CURSOR_OFFSETS, \ BDW_COLORS -static const struct intel_device_info intel_broxton_info = { +static const struct intel_device_info intel_broxton_info __initconst = { GEN9_LP_FEATURES, .platform = INTEL_BROXTON, .ddb_size = 512, - .has_reset_engine = false, }; -static const struct intel_device_info intel_geminilake_info = { +static const struct intel_device_info intel_geminilake_info __initconst = { GEN9_LP_FEATURES, .platform = INTEL_GEMINILAKE, .ddb_size = 1024, @@ -416,12 +505,19 @@ static const struct intel_device_info intel_geminilake_info = { .has_guc = 1, \ .ddb_size = 896 -static const struct intel_device_info intel_kabylake_info = { +static const struct intel_device_info intel_kabylake_gt1_info __initconst = { KBL_PLATFORM, + .gt = 1, }; -static const struct intel_device_info intel_kabylake_gt3_info = { +static const struct intel_device_info intel_kabylake_gt2_info __initconst = { KBL_PLATFORM, + .gt = 2, +}; + +static const struct intel_device_info intel_kabylake_gt3_info __initconst = { + KBL_PLATFORM, + .gt = 3, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING, }; @@ -434,20 +530,28 @@ static const struct intel_device_info intel_kabylake_gt3_info = { .has_guc = 1, \ .ddb_size = 896 -static const struct intel_device_info intel_coffeelake_info = { +static const struct intel_device_info intel_coffeelake_gt1_info __initconst = { + CFL_PLATFORM, + .gt = 1, +}; + +static const struct intel_device_info intel_coffeelake_gt2_info __initconst = { CFL_PLATFORM, + .gt = 2, }; -static const struct intel_device_info intel_coffeelake_gt3_info = { +static const struct intel_device_info intel_coffeelake_gt3_info __initconst = { CFL_PLATFORM, + .gt = 3, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING, }; -static const struct intel_device_info intel_cannonlake_info = { +static const struct intel_device_info intel_cannonlake_gt2_info __initconst = { BDW_FEATURES, .is_alpha_support = 1, .platform = INTEL_CANNONLAKE, .gen = 10, + .gt = 2, .ddb_size = 1024, .has_csr = 1, .color = { .degamma_lut_size = 0, .gamma_lut_size = 1024 } @@ -476,31 +580,40 @@ static const struct pci_device_id pciidlist[] = { INTEL_PINEVIEW_IDS(&intel_pineview_info), INTEL_IRONLAKE_D_IDS(&intel_ironlake_d_info), INTEL_IRONLAKE_M_IDS(&intel_ironlake_m_info), - INTEL_SNB_D_IDS(&intel_sandybridge_d_info), - INTEL_SNB_M_IDS(&intel_sandybridge_m_info), + INTEL_SNB_D_GT1_IDS(&intel_sandybridge_d_gt1_info), + INTEL_SNB_D_GT2_IDS(&intel_sandybridge_d_gt2_info), + INTEL_SNB_M_GT1_IDS(&intel_sandybridge_m_gt1_info), + INTEL_SNB_M_GT2_IDS(&intel_sandybridge_m_gt2_info), INTEL_IVB_Q_IDS(&intel_ivybridge_q_info), /* must be first IVB */ - INTEL_IVB_M_IDS(&intel_ivybridge_m_info), - INTEL_IVB_D_IDS(&intel_ivybridge_d_info), - INTEL_HSW_IDS(&intel_haswell_info), + INTEL_IVB_M_GT1_IDS(&intel_ivybridge_m_gt1_info), + INTEL_IVB_M_GT2_IDS(&intel_ivybridge_m_gt2_info), + INTEL_IVB_D_GT1_IDS(&intel_ivybridge_d_gt1_info), + INTEL_IVB_D_GT2_IDS(&intel_ivybridge_d_gt2_info), + INTEL_HSW_GT1_IDS(&intel_haswell_gt1_info), + INTEL_HSW_GT2_IDS(&intel_haswell_gt2_info), + INTEL_HSW_GT3_IDS(&intel_haswell_gt3_info), INTEL_VLV_IDS(&intel_valleyview_info), - INTEL_BDW_GT12_IDS(&intel_broadwell_info), + INTEL_BDW_GT1_IDS(&intel_broadwell_gt1_info), + INTEL_BDW_GT2_IDS(&intel_broadwell_gt2_info), INTEL_BDW_GT3_IDS(&intel_broadwell_gt3_info), - INTEL_BDW_RSVD_IDS(&intel_broadwell_info), + INTEL_BDW_RSVD_IDS(&intel_broadwell_rsvd_info), INTEL_CHV_IDS(&intel_cherryview_info), - INTEL_SKL_GT1_IDS(&intel_skylake_info), - INTEL_SKL_GT2_IDS(&intel_skylake_info), + INTEL_SKL_GT1_IDS(&intel_skylake_gt1_info), + INTEL_SKL_GT2_IDS(&intel_skylake_gt2_info), INTEL_SKL_GT3_IDS(&intel_skylake_gt3_info), - INTEL_SKL_GT4_IDS(&intel_skylake_gt3_info), + INTEL_SKL_GT4_IDS(&intel_skylake_gt4_info), INTEL_BXT_IDS(&intel_broxton_info), INTEL_GLK_IDS(&intel_geminilake_info), - INTEL_KBL_GT1_IDS(&intel_kabylake_info), - INTEL_KBL_GT2_IDS(&intel_kabylake_info), + INTEL_KBL_GT1_IDS(&intel_kabylake_gt1_info), + INTEL_KBL_GT2_IDS(&intel_kabylake_gt2_info), INTEL_KBL_GT3_IDS(&intel_kabylake_gt3_info), INTEL_KBL_GT4_IDS(&intel_kabylake_gt3_info), - INTEL_CFL_S_IDS(&intel_coffeelake_info), - INTEL_CFL_H_IDS(&intel_coffeelake_info), - INTEL_CFL_U_IDS(&intel_coffeelake_gt3_info), - INTEL_CNL_IDS(&intel_cannonlake_info), + INTEL_CFL_S_GT1_IDS(&intel_coffeelake_gt1_info), + INTEL_CFL_S_GT2_IDS(&intel_coffeelake_gt2_info), + INTEL_CFL_H_GT2_IDS(&intel_coffeelake_gt2_info), + INTEL_CFL_U_GT3_IDS(&intel_coffeelake_gt3_info), + INTEL_CNL_U_GT2_IDS(&intel_cannonlake_gt2_info), + INTEL_CNL_Y_GT2_IDS(&intel_cannonlake_gt2_info), {0, 0, 0} }; MODULE_DEVICE_TABLE(pci, pciidlist); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index ed7cd9e..2eff98cd 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2373,6 +2373,7 @@ enum i915_power_well_id { #define GAMT_CHKN_BIT_REG _MMIO(0x4ab8) #define GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING (1<<28) +#define GAMT_CHKN_DISABLE_I2M_CYCLE_ON_WR_PORT (1<<24) #if 0 #define PRB0_TAIL _MMIO(0x2030) @@ -2491,6 +2492,7 @@ enum i915_power_well_id { # define _3D_CHICKEN2_WM_READ_PIPELINED (1 << 14) #define _3D_CHICKEN3 _MMIO(0x2090) #define _3D_CHICKEN_SF_DISABLE_OBJEND_CULL (1 << 10) +#define _3D_CHICKEN3_AA_LINE_QUALITY_FIX_ENABLE (1 << 5) #define _3D_CHICKEN3_SF_DISABLE_FASTCLIP_CULL (1 << 5) #define _3D_CHICKEN_SDE_LIMIT_FIFO_POLY_DEPTH(x) ((x)<<1) /* gen8+ */ #define _3D_CHICKEN3_SF_DISABLE_PIPELINED_ATTR_FETCH (1 << 1) /* gen6 */ @@ -2938,6 +2940,9 @@ enum i915_power_well_id { #define ILK_DPFC_CHICKEN _MMIO(0x43224) #define ILK_DPFC_DISABLE_DUMMY0 (1<<8) #define ILK_DPFC_NUKE_ON_ANY_MODIFICATION (1<<23) +#define GLK_SKIP_SEG_EN (1<<12) +#define GLK_SKIP_SEG_COUNT_MASK (3<<10) +#define GLK_SKIP_SEG_COUNT(x) ((x)<<10) #define ILK_FBC_RT_BASE _MMIO(0x2128) #define ILK_FBC_RT_VALID (1<<0) #define SNB_FBC_FRONT_BUFFER (1<<1) @@ -3807,6 +3812,12 @@ enum { #define PWM1_GATING_DIS (1 << 13) /* + * GEN10 clock gating regs + */ +#define SLICE_UNIT_LEVEL_CLKGATE _MMIO(0x94d4) +#define SARBUNIT_CLKGATE_DIS (1 << 5) + +/* * Display engine regs */ @@ -6916,6 +6927,10 @@ enum { #define GLK_CL1_PWR_DOWN (1 << 11) #define GLK_CL0_PWR_DOWN (1 << 10) +#define CHICKEN_MISC_4 _MMIO(0x4208c) +#define FBC_STRIDE_OVERRIDE (1 << 13) +#define FBC_STRIDE_MASK 0x1FFF + #define _CHICKEN_PIPESL_1_A 0x420b0 #define _CHICKEN_PIPESL_1_B 0x420b4 #define HSW_FBCQ_DIS (1 << 22) @@ -7017,6 +7032,7 @@ enum { /* GEN8 chicken */ #define HDC_CHICKEN0 _MMIO(0x7300) +#define CNL_HDC_CHICKEN0 _MMIO(0xE5F0) #define HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE (1<<15) #define HDC_FENCE_DEST_SLM_DISABLE (1<<14) #define HDC_DONOT_FETCH_MEM_WHEN_MASKED (1<<11) @@ -7470,6 +7486,7 @@ enum { #define PCH_DPLUNIT_CLOCK_GATE_DISABLE (1<<30) #define PCH_DPLSUNIT_CLOCK_GATE_DISABLE (1<<29) #define PCH_CPUNIT_CLOCK_GATE_DISABLE (1<<14) +#define CNP_PWM_CGE_GATING_DISABLE (1<<13) #define PCH_LP_PARTITION_LEVEL_DISABLE (1<<12) /* CPU: FDI_TX */ @@ -8044,10 +8061,12 @@ enum { #define FLOW_CONTROL_ENABLE (1<<15) #define PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE (1<<8) #define STALL_DOP_GATING_DISABLE (1<<5) +#define THROTTLE_12_5 (7<<2) #define GEN7_ROW_CHICKEN2 _MMIO(0xe4f4) #define GEN7_ROW_CHICKEN2_GT2 _MMIO(0xf4f4) #define DOP_CLOCK_GATING_DISABLE (1<<0) +#define PUSH_CONSTANT_DEREF_DISABLE (1<<8) #define HSW_ROW_CHICKEN3 _MMIO(0xe49c) #define HSW_ROW_CHICKEN3_L3_GLOBAL_ATOMICS_DISABLE (1 << 6) @@ -8059,6 +8078,7 @@ enum { #define HSW_SAMPLE_C_PERFORMANCE (1<<9) #define GEN8_CENTROID_PIXEL_OPT_DIS (1<<8) #define GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC (1<<5) +#define CNL_FAST_ANISO_L1_BANKING_FIX (1<<4) #define GEN8_SAMPLER_POWER_BYPASS_DIS (1<<1) #define GEN9_HALF_SLICE_CHICKEN7 _MMIO(0xe194) diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index 6fd5c57..92f4c5b 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h @@ -1031,5 +1031,5 @@ TRACE_EVENT(switch_mm, /* This part must be outside protection */ #undef TRACE_INCLUDE_PATH -#define TRACE_INCLUDE_PATH . +#define TRACE_INCLUDE_PATH ../../drivers/gpu/drm/i915 #include <trace/define_trace.h> diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c index ee76fab..8e6dc15 100644 --- a/drivers/gpu/drm/i915/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c @@ -107,7 +107,9 @@ intel_plane_destroy_state(struct drm_plane *plane, drm_atomic_helper_plane_destroy_state(plane, state); } -int intel_plane_atomic_check_with_state(struct intel_crtc_state *crtc_state, +int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_state, + struct intel_crtc_state *crtc_state, + const struct intel_plane_state *old_plane_state, struct intel_plane_state *intel_state) { struct drm_plane *plane = intel_state->base.plane; @@ -124,7 +126,7 @@ int intel_plane_atomic_check_with_state(struct intel_crtc_state *crtc_state, * anything driver-specific we need to test in that case, so * just return success. */ - if (!intel_state->base.crtc && !plane->state->crtc) + if (!intel_state->base.crtc && !old_plane_state->base.crtc) return 0; /* Clip all planes to CRTC size, or 0x0 if CRTC is disabled */ @@ -194,16 +196,21 @@ int intel_plane_atomic_check_with_state(struct intel_crtc_state *crtc_state, else crtc_state->active_planes &= ~BIT(intel_plane->id); - return intel_plane_atomic_calc_changes(&crtc_state->base, state); + return intel_plane_atomic_calc_changes(old_crtc_state, + &crtc_state->base, + old_plane_state, + state); } static int intel_plane_atomic_check(struct drm_plane *plane, - struct drm_plane_state *state) + struct drm_plane_state *new_plane_state) { - struct drm_crtc *crtc = state->crtc; - struct drm_crtc_state *drm_crtc_state; - - crtc = crtc ? crtc : plane->state->crtc; + struct drm_atomic_state *state = new_plane_state->state; + const struct drm_plane_state *old_plane_state = + drm_atomic_get_old_plane_state(state, plane); + struct drm_crtc *crtc = new_plane_state->crtc ?: old_plane_state->crtc; + const struct drm_crtc_state *old_crtc_state; + struct drm_crtc_state *new_crtc_state; /* * Both crtc and plane->crtc could be NULL if we're updating a @@ -214,29 +221,33 @@ static int intel_plane_atomic_check(struct drm_plane *plane, if (!crtc) return 0; - drm_crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc); - if (WARN_ON(!drm_crtc_state)) - return -EINVAL; + old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc); + new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc); - return intel_plane_atomic_check_with_state(to_intel_crtc_state(drm_crtc_state), - to_intel_plane_state(state)); + return intel_plane_atomic_check_with_state(to_intel_crtc_state(old_crtc_state), + to_intel_crtc_state(new_crtc_state), + to_intel_plane_state(old_plane_state), + to_intel_plane_state(new_plane_state)); } static void intel_plane_atomic_update(struct drm_plane *plane, struct drm_plane_state *old_state) { + struct intel_atomic_state *state = to_intel_atomic_state(old_state->state); struct intel_plane *intel_plane = to_intel_plane(plane); - struct intel_plane_state *intel_state = - to_intel_plane_state(plane->state); - struct drm_crtc *crtc = plane->state->crtc ?: old_state->crtc; + const struct intel_plane_state *new_plane_state = + intel_atomic_get_new_plane_state(state, intel_plane); + struct drm_crtc *crtc = new_plane_state->base.crtc ?: old_state->crtc; + + if (new_plane_state->base.visible) { + const struct intel_crtc_state *new_crtc_state = + intel_atomic_get_new_crtc_state(state, to_intel_crtc(crtc)); - if (intel_state->base.visible) { trace_intel_update_plane(plane, to_intel_crtc(crtc)); intel_plane->update_plane(intel_plane, - to_intel_crtc_state(crtc->state), - intel_state); + new_crtc_state, new_plane_state); } else { trace_intel_disable_plane(plane, to_intel_crtc(crtc)); diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 183e87e..5949750 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -452,24 +452,24 @@ parse_general_definitions(struct drm_i915_private *dev_priv, } } -static const union child_device_config * -child_device_ptr(const struct bdb_general_definitions *p_defs, int i) +static const struct child_device_config * +child_device_ptr(const struct bdb_general_definitions *defs, int i) { - return (const void *) &p_defs->devices[i * p_defs->child_dev_size]; + return (const void *) &defs->devices[i * defs->child_dev_size]; } static void parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, const struct bdb_header *bdb) { - struct sdvo_device_mapping *p_mapping; - const struct bdb_general_definitions *p_defs; - const struct old_child_dev_config *child; /* legacy */ + struct sdvo_device_mapping *mapping; + const struct bdb_general_definitions *defs; + const struct child_device_config *child; int i, child_device_num, count; u16 block_size; - p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); - if (!p_defs) { + defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); + if (!defs) { DRM_DEBUG_KMS("No general definition block is found, unable to construct sdvo mapping.\n"); return; } @@ -479,18 +479,17 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, * device size matches that of the *legacy* child device config * struct. Thus, SDVO mapping will be skipped for newer VBT. */ - if (p_defs->child_dev_size != sizeof(*child)) { + if (defs->child_dev_size != LEGACY_CHILD_DEVICE_CONFIG_SIZE) { DRM_DEBUG_KMS("Unsupported child device size for SDVO mapping.\n"); return; } /* get the block size of general definitions */ - block_size = get_blocksize(p_defs); + block_size = get_blocksize(defs); /* get the number of child device */ - child_device_num = (block_size - sizeof(*p_defs)) / - p_defs->child_dev_size; + child_device_num = (block_size - sizeof(*defs)) / defs->child_dev_size; count = 0; for (i = 0; i < child_device_num; i++) { - child = &child_device_ptr(p_defs, i)->old; + child = child_device_ptr(defs, i); if (!child->device_type) { /* skip the device block if device type is invalid */ continue; @@ -514,20 +513,20 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, child->slave_addr, (child->dvo_port == DEVICE_PORT_DVOB) ? "SDVOB" : "SDVOC"); - p_mapping = &dev_priv->vbt.sdvo_mappings[child->dvo_port - 1]; - if (!p_mapping->initialized) { - p_mapping->dvo_port = child->dvo_port; - p_mapping->slave_addr = child->slave_addr; - p_mapping->dvo_wiring = child->dvo_wiring; - p_mapping->ddc_pin = child->ddc_pin; - p_mapping->i2c_pin = child->i2c_pin; - p_mapping->initialized = 1; + mapping = &dev_priv->vbt.sdvo_mappings[child->dvo_port - 1]; + if (!mapping->initialized) { + mapping->dvo_port = child->dvo_port; + mapping->slave_addr = child->slave_addr; + mapping->dvo_wiring = child->dvo_wiring; + mapping->ddc_pin = child->ddc_pin; + mapping->i2c_pin = child->i2c_pin; + mapping->initialized = 1; DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d\n", - p_mapping->dvo_port, - p_mapping->slave_addr, - p_mapping->dvo_wiring, - p_mapping->ddc_pin, - p_mapping->i2c_pin); + mapping->dvo_port, + mapping->slave_addr, + mapping->dvo_wiring, + mapping->ddc_pin, + mapping->i2c_pin); } else { DRM_DEBUG_KMS("Maybe one SDVO port is shared by " "two SDVO device.\n"); @@ -577,7 +576,7 @@ parse_edp(struct drm_i915_private *dev_priv, const struct bdb_header *bdb) { const struct bdb_edp *edp; const struct edp_power_seq *edp_pps; - const struct edp_link_params *edp_link_params; + const struct edp_fast_link_params *edp_link_params; int panel_type = dev_priv->vbt.panel_type; edp = find_section(bdb, BDB_EDP); @@ -601,7 +600,7 @@ parse_edp(struct drm_i915_private *dev_priv, const struct bdb_header *bdb) /* Get the eDP sequencing and link info */ edp_pps = &edp->power_seqs[panel_type]; - edp_link_params = &edp->link_params[panel_type]; + edp_link_params = &edp->fast_link_params[panel_type]; dev_priv->vbt.edp.pps = *edp_pps; @@ -1113,7 +1112,7 @@ static void sanitize_aux_ch(struct drm_i915_private *dev_priv, static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, const struct bdb_header *bdb) { - union child_device_config *it, *child = NULL; + struct child_device_config *it, *child = NULL; struct ddi_vbt_port_info *info = &dev_priv->vbt.ddi_port_info[port]; uint8_t hdmi_level_shift; int i, j; @@ -1141,7 +1140,7 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, if (dvo_ports[port][j] == -1) break; - if (it->common.dvo_port == dvo_ports[port][j]) { + if (it->dvo_port == dvo_ports[port][j]) { if (child) { DRM_DEBUG_KMS("More than one child device for port %c in VBT, using the first.\n", port_name(port)); @@ -1154,14 +1153,14 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, if (!child) return; - aux_channel = child->common.aux_channel; - ddc_pin = child->common.ddc_pin; + aux_channel = child->aux_channel; + ddc_pin = child->ddc_pin; - is_dvi = child->common.device_type & DEVICE_TYPE_TMDS_DVI_SIGNALING; - is_dp = child->common.device_type & DEVICE_TYPE_DISPLAYPORT_OUTPUT; - is_crt = child->common.device_type & DEVICE_TYPE_ANALOG_OUTPUT; - is_hdmi = is_dvi && (child->common.device_type & DEVICE_TYPE_NOT_HDMI_OUTPUT) == 0; - is_edp = is_dp && (child->common.device_type & DEVICE_TYPE_INTERNAL_CONNECTOR); + is_dvi = child->device_type & DEVICE_TYPE_TMDS_DVI_SIGNALING; + is_dp = child->device_type & DEVICE_TYPE_DISPLAYPORT_OUTPUT; + is_crt = child->device_type & DEVICE_TYPE_ANALOG_OUTPUT; + is_hdmi = is_dvi && (child->device_type & DEVICE_TYPE_NOT_HDMI_OUTPUT) == 0; + is_edp = is_dp && (child->device_type & DEVICE_TYPE_INTERNAL_CONNECTOR); info->supports_dvi = is_dvi; info->supports_hdmi = is_hdmi; @@ -1210,7 +1209,7 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, if (bdb->version >= 158) { /* The VBT HDMI level shift values match the table we have. */ - hdmi_level_shift = child->raw[7] & 0xF; + hdmi_level_shift = child->hdmi_level_shifter_value; DRM_DEBUG_KMS("VBT HDMI level shift for port %c: %d\n", port_name(port), hdmi_level_shift); @@ -1218,11 +1217,11 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, } /* Parse the I_boost config for SKL and above */ - if (bdb->version >= 196 && child->common.iboost) { - info->dp_boost_level = translate_iboost(child->common.iboost_level & 0xF); + if (bdb->version >= 196 && child->iboost) { + info->dp_boost_level = translate_iboost(child->dp_iboost_level); DRM_DEBUG_KMS("VBT (e)DP boost level for port %c: %d\n", port_name(port), info->dp_boost_level); - info->hdmi_boost_level = translate_iboost(child->common.iboost_level >> 4); + info->hdmi_boost_level = translate_iboost(child->hdmi_iboost_level); DRM_DEBUG_KMS("VBT HDMI boost level for port %c: %d\n", port_name(port), info->hdmi_boost_level); } @@ -1250,15 +1249,15 @@ static void parse_device_mapping(struct drm_i915_private *dev_priv, const struct bdb_header *bdb) { - const struct bdb_general_definitions *p_defs; - const union child_device_config *p_child; - union child_device_config *child_dev_ptr; + const struct bdb_general_definitions *defs; + const struct child_device_config *child; + struct child_device_config *child_dev_ptr; int i, child_device_num, count; u8 expected_size; u16 block_size; - p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); - if (!p_defs) { + defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); + if (!defs) { DRM_DEBUG_KMS("No general definition block is found, no devices defined.\n"); return; } @@ -1267,41 +1266,39 @@ parse_device_mapping(struct drm_i915_private *dev_priv, } else if (bdb->version < 111) { expected_size = 27; } else if (bdb->version < 195) { - BUILD_BUG_ON(sizeof(struct old_child_dev_config) != 33); - expected_size = sizeof(struct old_child_dev_config); + expected_size = LEGACY_CHILD_DEVICE_CONFIG_SIZE; } else if (bdb->version == 195) { expected_size = 37; } else if (bdb->version <= 197) { expected_size = 38; } else { expected_size = 38; - BUILD_BUG_ON(sizeof(*p_child) < 38); + BUILD_BUG_ON(sizeof(*child) < 38); DRM_DEBUG_DRIVER("Expected child device config size for VBT version %u not known; assuming %u\n", bdb->version, expected_size); } /* Flag an error for unexpected size, but continue anyway. */ - if (p_defs->child_dev_size != expected_size) + if (defs->child_dev_size != expected_size) DRM_ERROR("Unexpected child device config size %u (expected %u for VBT version %u)\n", - p_defs->child_dev_size, expected_size, bdb->version); + defs->child_dev_size, expected_size, bdb->version); /* The legacy sized child device config is the minimum we need. */ - if (p_defs->child_dev_size < sizeof(struct old_child_dev_config)) { + if (defs->child_dev_size < LEGACY_CHILD_DEVICE_CONFIG_SIZE) { DRM_DEBUG_KMS("Child device config size %u is too small.\n", - p_defs->child_dev_size); + defs->child_dev_size); return; } /* get the block size of general definitions */ - block_size = get_blocksize(p_defs); + block_size = get_blocksize(defs); /* get the number of child device */ - child_device_num = (block_size - sizeof(*p_defs)) / - p_defs->child_dev_size; + child_device_num = (block_size - sizeof(*defs)) / defs->child_dev_size; count = 0; /* get the number of child device that is present */ for (i = 0; i < child_device_num; i++) { - p_child = child_device_ptr(p_defs, i); - if (!p_child->common.device_type) { + child = child_device_ptr(defs, i); + if (!child->device_type) { /* skip the device block if device type is invalid */ continue; } @@ -1311,7 +1308,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv, DRM_DEBUG_KMS("no child dev is parsed from VBT\n"); return; } - dev_priv->vbt.child_dev = kcalloc(count, sizeof(*p_child), GFP_KERNEL); + dev_priv->vbt.child_dev = kcalloc(count, sizeof(*child), GFP_KERNEL); if (!dev_priv->vbt.child_dev) { DRM_DEBUG_KMS("No memory space for child device\n"); return; @@ -1320,8 +1317,8 @@ parse_device_mapping(struct drm_i915_private *dev_priv, dev_priv->vbt.child_dev_num = count; count = 0; for (i = 0; i < child_device_num; i++) { - p_child = child_device_ptr(p_defs, i); - if (!p_child->common.device_type) { + child = child_device_ptr(defs, i); + if (!child->device_type) { /* skip the device block if device type is invalid */ continue; } @@ -1334,8 +1331,8 @@ parse_device_mapping(struct drm_i915_private *dev_priv, * (child_dev_size) of the child device. Accessing the data must * depend on VBT version. */ - memcpy(child_dev_ptr, p_child, - min_t(size_t, p_defs->child_dev_size, sizeof(*p_child))); + memcpy(child_dev_ptr, child, + min_t(size_t, defs->child_dev_size, sizeof(*child))); /* * copied full block, now init values when they are not @@ -1343,12 +1340,12 @@ parse_device_mapping(struct drm_i915_private *dev_priv, */ if (bdb->version < 196) { /* Set default values for bits added from v196 */ - child_dev_ptr->common.iboost = 0; - child_dev_ptr->common.hpd_invert = 0; + child_dev_ptr->iboost = 0; + child_dev_ptr->hpd_invert = 0; } if (bdb->version < 192) - child_dev_ptr->common.lspcon = 0; + child_dev_ptr->lspcon = 0; } return; } @@ -1559,7 +1556,7 @@ out: */ bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv) { - union child_device_config *p_child; + const struct child_device_config *child; int i; if (!dev_priv->vbt.int_tv_support) @@ -1569,11 +1566,11 @@ bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv) return true; for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { - p_child = dev_priv->vbt.child_dev + i; + child = dev_priv->vbt.child_dev + i; /* * If the device type is not TV, continue. */ - switch (p_child->old.device_type) { + switch (child->device_type) { case DEVICE_TYPE_INT_TV: case DEVICE_TYPE_TV: case DEVICE_TYPE_TV_SVIDEO_COMPOSITE: @@ -1584,7 +1581,7 @@ bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv) /* Only when the addin_offset is non-zero, it is regarded * as present. */ - if (p_child->old.addin_offset) + if (child->addin_offset) return true; } @@ -1601,14 +1598,14 @@ bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv) */ bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin) { + const struct child_device_config *child; int i; if (!dev_priv->vbt.child_dev_num) return true; for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { - union child_device_config *uchild = dev_priv->vbt.child_dev + i; - struct old_child_dev_config *child = &uchild->old; + child = dev_priv->vbt.child_dev + i; /* If the device type is not LFP, continue. * We have to check both the new identifiers as well as the @@ -1650,6 +1647,7 @@ bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin) */ bool intel_bios_is_port_present(struct drm_i915_private *dev_priv, enum port port) { + const struct child_device_config *child; static const struct { u16 dp, hdmi; } port_mapping[] = { @@ -1668,12 +1666,12 @@ bool intel_bios_is_port_present(struct drm_i915_private *dev_priv, enum port por return false; for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { - const union child_device_config *p_child = - &dev_priv->vbt.child_dev[i]; - if ((p_child->common.dvo_port == port_mapping[port].dp || - p_child->common.dvo_port == port_mapping[port].hdmi) && - (p_child->common.device_type & (DEVICE_TYPE_TMDS_DVI_SIGNALING | - DEVICE_TYPE_DISPLAYPORT_OUTPUT))) + child = dev_priv->vbt.child_dev + i; + + if ((child->dvo_port == port_mapping[port].dp || + child->dvo_port == port_mapping[port].hdmi) && + (child->device_type & (DEVICE_TYPE_TMDS_DVI_SIGNALING | + DEVICE_TYPE_DISPLAYPORT_OUTPUT))) return true; } @@ -1689,7 +1687,7 @@ bool intel_bios_is_port_present(struct drm_i915_private *dev_priv, enum port por */ bool intel_bios_is_port_edp(struct drm_i915_private *dev_priv, enum port port) { - union child_device_config *p_child; + const struct child_device_config *child; static const short port_mapping[] = { [PORT_B] = DVO_PORT_DPB, [PORT_C] = DVO_PORT_DPC, @@ -1705,10 +1703,10 @@ bool intel_bios_is_port_edp(struct drm_i915_private *dev_priv, enum port port) return false; for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { - p_child = dev_priv->vbt.child_dev + i; + child = dev_priv->vbt.child_dev + i; - if (p_child->common.dvo_port == port_mapping[port] && - (p_child->common.device_type & DEVICE_TYPE_eDP_BITS) == + if (child->dvo_port == port_mapping[port] && + (child->device_type & DEVICE_TYPE_eDP_BITS) == (DEVICE_TYPE_eDP & DEVICE_TYPE_eDP_BITS)) return true; } @@ -1716,7 +1714,7 @@ bool intel_bios_is_port_edp(struct drm_i915_private *dev_priv, enum port port) return false; } -static bool child_dev_is_dp_dual_mode(const union child_device_config *p_child, +static bool child_dev_is_dp_dual_mode(const struct child_device_config *child, enum port port) { static const struct { @@ -1735,16 +1733,16 @@ static bool child_dev_is_dp_dual_mode(const union child_device_config *p_child, if (port == PORT_A || port >= ARRAY_SIZE(port_mapping)) return false; - if ((p_child->common.device_type & DEVICE_TYPE_DP_DUAL_MODE_BITS) != + if ((child->device_type & DEVICE_TYPE_DP_DUAL_MODE_BITS) != (DEVICE_TYPE_DP_DUAL_MODE & DEVICE_TYPE_DP_DUAL_MODE_BITS)) return false; - if (p_child->common.dvo_port == port_mapping[port].dp) + if (child->dvo_port == port_mapping[port].dp) return true; /* Only accept a HDMI dvo_port as DP++ if it has an AUX channel */ - if (p_child->common.dvo_port == port_mapping[port].hdmi && - p_child->common.aux_channel != 0) + if (child->dvo_port == port_mapping[port].hdmi && + child->aux_channel != 0) return true; return false; @@ -1753,13 +1751,13 @@ static bool child_dev_is_dp_dual_mode(const union child_device_config *p_child, bool intel_bios_is_port_dp_dual_mode(struct drm_i915_private *dev_priv, enum port port) { + const struct child_device_config *child; int i; for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { - const union child_device_config *p_child = - &dev_priv->vbt.child_dev[i]; + child = dev_priv->vbt.child_dev + i; - if (child_dev_is_dp_dual_mode(p_child, port)) + if (child_dev_is_dp_dual_mode(child, port)) return true; } @@ -1776,17 +1774,17 @@ bool intel_bios_is_port_dp_dual_mode(struct drm_i915_private *dev_priv, bool intel_bios_is_dsi_present(struct drm_i915_private *dev_priv, enum port *port) { - union child_device_config *p_child; + const struct child_device_config *child; u8 dvo_port; int i; for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { - p_child = dev_priv->vbt.child_dev + i; + child = dev_priv->vbt.child_dev + i; - if (!(p_child->common.device_type & DEVICE_TYPE_MIPI_OUTPUT)) + if (!(child->device_type & DEVICE_TYPE_MIPI_OUTPUT)) continue; - dvo_port = p_child->common.dvo_port; + dvo_port = child->dvo_port; switch (dvo_port) { case DVO_PORT_MIPIA: @@ -1816,16 +1814,19 @@ bool intel_bios_is_port_hpd_inverted(struct drm_i915_private *dev_priv, enum port port) { + const struct child_device_config *child; int i; if (WARN_ON_ONCE(!IS_GEN9_LP(dev_priv))) return false; for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { - if (!dev_priv->vbt.child_dev[i].common.hpd_invert) + child = dev_priv->vbt.child_dev + i; + + if (!child->hpd_invert) continue; - switch (dev_priv->vbt.child_dev[i].common.dvo_port) { + switch (child->dvo_port) { case DVO_PORT_DPA: case DVO_PORT_HDMIA: if (port == PORT_A) @@ -1860,16 +1861,19 @@ bool intel_bios_is_lspcon_present(struct drm_i915_private *dev_priv, enum port port) { + const struct child_device_config *child; int i; if (!HAS_LSPCON(dev_priv)) return false; for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { - if (!dev_priv->vbt.child_dev[i].common.lspcon) + child = dev_priv->vbt.child_dev + i; + + if (!child->lspcon) continue; - switch (dev_priv->vbt.child_dev[i].common.dvo_port) { + switch (child->dvo_port) { case DVO_PORT_DPA: case DVO_PORT_HDMIA: if (port == PORT_A) diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c index 1241e58..d329118 100644 --- a/drivers/gpu/drm/i915/intel_cdclk.c +++ b/drivers/gpu/drm/i915/intel_cdclk.c @@ -417,24 +417,21 @@ static void hsw_get_cdclk(struct drm_i915_private *dev_priv, cdclk_state->cdclk = 540000; } -static int vlv_calc_cdclk(struct drm_i915_private *dev_priv, - int max_pixclk) +static int vlv_calc_cdclk(struct drm_i915_private *dev_priv, int min_cdclk) { int freq_320 = (dev_priv->hpll_freq << 1) % 320000 != 0 ? 333333 : 320000; - int limit = IS_CHERRYVIEW(dev_priv) ? 95 : 90; /* * We seem to get an unstable or solid color picture at 200MHz. * Not sure what's wrong. For now use 200MHz only when all pipes * are off. */ - if (!IS_CHERRYVIEW(dev_priv) && - max_pixclk > freq_320*limit/100) + if (IS_VALLEYVIEW(dev_priv) && min_cdclk > freq_320) return 400000; - else if (max_pixclk > 266667*limit/100) + else if (min_cdclk > 266667) return freq_320; - else if (max_pixclk > 0) + else if (min_cdclk > 0) return 266667; else return 200000; @@ -612,13 +609,13 @@ static void chv_set_cdclk(struct drm_i915_private *dev_priv, intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A); } -static int bdw_calc_cdclk(int max_pixclk) +static int bdw_calc_cdclk(int min_cdclk) { - if (max_pixclk > 540000) + if (min_cdclk > 540000) return 675000; - else if (max_pixclk > 450000) + else if (min_cdclk > 450000) return 540000; - else if (max_pixclk > 337500) + else if (min_cdclk > 337500) return 450000; else return 337500; @@ -724,23 +721,23 @@ static void bdw_set_cdclk(struct drm_i915_private *dev_priv, cdclk, dev_priv->cdclk.hw.cdclk); } -static int skl_calc_cdclk(int max_pixclk, int vco) +static int skl_calc_cdclk(int min_cdclk, int vco) { if (vco == 8640000) { - if (max_pixclk > 540000) + if (min_cdclk > 540000) return 617143; - else if (max_pixclk > 432000) + else if (min_cdclk > 432000) return 540000; - else if (max_pixclk > 308571) + else if (min_cdclk > 308571) return 432000; else return 308571; } else { - if (max_pixclk > 540000) + if (min_cdclk > 540000) return 675000; - else if (max_pixclk > 450000) + else if (min_cdclk > 450000) return 540000; - else if (max_pixclk > 337500) + else if (min_cdclk > 337500) return 450000; else return 337500; @@ -1075,31 +1072,25 @@ void skl_uninit_cdclk(struct drm_i915_private *dev_priv) skl_set_cdclk(dev_priv, &cdclk_state); } -static int bxt_calc_cdclk(int max_pixclk) +static int bxt_calc_cdclk(int min_cdclk) { - if (max_pixclk > 576000) + if (min_cdclk > 576000) return 624000; - else if (max_pixclk > 384000) + else if (min_cdclk > 384000) return 576000; - else if (max_pixclk > 288000) + else if (min_cdclk > 288000) return 384000; - else if (max_pixclk > 144000) + else if (min_cdclk > 144000) return 288000; else return 144000; } -static int glk_calc_cdclk(int max_pixclk) +static int glk_calc_cdclk(int min_cdclk) { - /* - * FIXME: Avoid using a pixel clock that is more than 99% of the cdclk - * as a temporary workaround. Use a higher cdclk instead. (Note that - * intel_compute_max_dotclk() limits the max pixel clock to 99% of max - * cdclk.) - */ - if (max_pixclk > DIV_ROUND_UP(2 * 158400 * 99, 100)) + if (min_cdclk > 158400) return 316800; - else if (max_pixclk > DIV_ROUND_UP(2 * 79200 * 99, 100)) + else if (min_cdclk > 79200) return 158400; else return 79200; @@ -1420,11 +1411,11 @@ void bxt_uninit_cdclk(struct drm_i915_private *dev_priv) bxt_set_cdclk(dev_priv, &cdclk_state); } -static int cnl_calc_cdclk(int max_pixclk) +static int cnl_calc_cdclk(int min_cdclk) { - if (max_pixclk > 336000) + if (min_cdclk > 336000) return 528000; - else if (max_pixclk > 168000) + else if (min_cdclk > 168000) return 336000; else return 168000; @@ -1732,104 +1723,119 @@ void intel_set_cdclk(struct drm_i915_private *dev_priv, dev_priv->display.set_cdclk(dev_priv, cdclk_state); } -static int bdw_adjust_min_pipe_pixel_rate(struct intel_crtc_state *crtc_state, - int pixel_rate) +static int intel_pixel_rate_to_cdclk(struct drm_i915_private *dev_priv, + int pixel_rate) +{ + if (INTEL_GEN(dev_priv) >= 10) + /* + * FIXME: Switch to DIV_ROUND_UP(pixel_rate, 2) + * once DDI clock voltage requirements are + * handled correctly. + */ + return pixel_rate; + else if (IS_GEMINILAKE(dev_priv)) + /* + * FIXME: Avoid using a pixel clock that is more than 99% of the cdclk + * as a temporary workaround. Use a higher cdclk instead. (Note that + * intel_compute_max_dotclk() limits the max pixel clock to 99% of max + * cdclk.) + */ + return DIV_ROUND_UP(pixel_rate * 100, 2 * 99); + else if (IS_GEN9(dev_priv) || + IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) + return pixel_rate; + else if (IS_CHERRYVIEW(dev_priv)) + return DIV_ROUND_UP(pixel_rate * 100, 95); + else + return DIV_ROUND_UP(pixel_rate * 100, 90); +} + +int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + int min_cdclk; + + if (!crtc_state->base.enable) + return 0; + + min_cdclk = intel_pixel_rate_to_cdclk(dev_priv, crtc_state->pixel_rate); /* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */ if (IS_BROADWELL(dev_priv) && crtc_state->ips_enabled) - pixel_rate = DIV_ROUND_UP(pixel_rate * 100, 95); + min_cdclk = DIV_ROUND_UP(min_cdclk * 100, 95); /* BSpec says "Do not use DisplayPort with CDCLK less than 432 MHz, * audio enabled, port width x4, and link rate HBR2 (5.4 GHz), or else * there may be audio corruption or screen corruption." This cdclk - * restriction for GLK is 316.8 MHz and since GLK can output two - * pixels per clock, the pixel rate becomes 2 * 316.8 MHz. + * restriction for GLK is 316.8 MHz. */ if (intel_crtc_has_dp_encoder(crtc_state) && crtc_state->has_audio && crtc_state->port_clock >= 540000 && crtc_state->lane_count == 4) { - if (IS_CANNONLAKE(dev_priv)) - pixel_rate = max(316800, pixel_rate); - else if (IS_GEMINILAKE(dev_priv)) - pixel_rate = max(2 * 316800, pixel_rate); - else - pixel_rate = max(432000, pixel_rate); + if (IS_CANNONLAKE(dev_priv) || IS_GEMINILAKE(dev_priv)) { + /* Display WA #1145: glk,cnl */ + min_cdclk = max(316800, min_cdclk); + } else if (IS_GEN9(dev_priv) || IS_BROADWELL(dev_priv)) { + /* Display WA #1144: skl,bxt */ + min_cdclk = max(432000, min_cdclk); + } } /* According to BSpec, "The CD clock frequency must be at least twice * the frequency of the Azalia BCLK." and BCLK is 96 MHz by default. - * The check for GLK has to be adjusted as the platform can output - * two pixels per clock. */ - if (crtc_state->has_audio && INTEL_GEN(dev_priv) >= 9) { - if (IS_GEMINILAKE(dev_priv)) - pixel_rate = max(2 * 2 * 96000, pixel_rate); - else - pixel_rate = max(2 * 96000, pixel_rate); + if (crtc_state->has_audio && INTEL_GEN(dev_priv) >= 9) + min_cdclk = max(2 * 96000, min_cdclk); + + if (min_cdclk > dev_priv->max_cdclk_freq) { + DRM_DEBUG_KMS("required cdclk (%d kHz) exceeds max (%d kHz)\n", + min_cdclk, dev_priv->max_cdclk_freq); + return -EINVAL; } - return pixel_rate; + return min_cdclk; } -/* compute the max rate for new configuration */ -static int intel_max_pixel_rate(struct drm_atomic_state *state) +static int intel_compute_min_cdclk(struct drm_atomic_state *state) { struct intel_atomic_state *intel_state = to_intel_atomic_state(state); struct drm_i915_private *dev_priv = to_i915(state->dev); - struct drm_crtc *crtc; - struct drm_crtc_state *cstate; + struct intel_crtc *crtc; struct intel_crtc_state *crtc_state; - unsigned int max_pixel_rate = 0, i; + int min_cdclk, i; enum pipe pipe; - memcpy(intel_state->min_pixclk, dev_priv->min_pixclk, - sizeof(intel_state->min_pixclk)); + memcpy(intel_state->min_cdclk, dev_priv->min_cdclk, + sizeof(intel_state->min_cdclk)); - for_each_new_crtc_in_state(state, crtc, cstate, i) { - int pixel_rate; + for_each_new_intel_crtc_in_state(intel_state, crtc, crtc_state, i) { + min_cdclk = intel_crtc_compute_min_cdclk(crtc_state); + if (min_cdclk < 0) + return min_cdclk; - crtc_state = to_intel_crtc_state(cstate); - if (!crtc_state->base.enable) { - intel_state->min_pixclk[i] = 0; - continue; - } - - pixel_rate = crtc_state->pixel_rate; - - if (IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) >= 9) - pixel_rate = - bdw_adjust_min_pipe_pixel_rate(crtc_state, - pixel_rate); - - intel_state->min_pixclk[i] = pixel_rate; + intel_state->min_cdclk[i] = min_cdclk; } + min_cdclk = 0; for_each_pipe(dev_priv, pipe) - max_pixel_rate = max(intel_state->min_pixclk[pipe], - max_pixel_rate); + min_cdclk = max(intel_state->min_cdclk[pipe], min_cdclk); - return max_pixel_rate; + return min_cdclk; } static int vlv_modeset_calc_cdclk(struct drm_atomic_state *state) { struct drm_i915_private *dev_priv = to_i915(state->dev); - int max_pixclk = intel_max_pixel_rate(state); - struct intel_atomic_state *intel_state = - to_intel_atomic_state(state); - int cdclk; + struct intel_atomic_state *intel_state = to_intel_atomic_state(state); + int min_cdclk, cdclk; - cdclk = vlv_calc_cdclk(dev_priv, max_pixclk); + min_cdclk = intel_compute_min_cdclk(state); + if (min_cdclk < 0) + return min_cdclk; - if (cdclk > dev_priv->max_cdclk_freq) { - DRM_DEBUG_KMS("requested cdclk (%d kHz) exceeds max (%d kHz)\n", - cdclk, dev_priv->max_cdclk_freq); - return -EINVAL; - } + cdclk = vlv_calc_cdclk(dev_priv, min_cdclk); intel_state->cdclk.logical.cdclk = cdclk; @@ -1847,22 +1853,18 @@ static int vlv_modeset_calc_cdclk(struct drm_atomic_state *state) static int bdw_modeset_calc_cdclk(struct drm_atomic_state *state) { - struct drm_i915_private *dev_priv = to_i915(state->dev); struct intel_atomic_state *intel_state = to_intel_atomic_state(state); - int max_pixclk = intel_max_pixel_rate(state); - int cdclk; + int min_cdclk, cdclk; + + min_cdclk = intel_compute_min_cdclk(state); + if (min_cdclk < 0) + return min_cdclk; /* * FIXME should also account for plane ratio * once 64bpp pixel formats are supported. */ - cdclk = bdw_calc_cdclk(max_pixclk); - - if (cdclk > dev_priv->max_cdclk_freq) { - DRM_DEBUG_KMS("requested cdclk (%d kHz) exceeds max (%d kHz)\n", - cdclk, dev_priv->max_cdclk_freq); - return -EINVAL; - } + cdclk = bdw_calc_cdclk(min_cdclk); intel_state->cdclk.logical.cdclk = cdclk; @@ -1880,10 +1882,13 @@ static int bdw_modeset_calc_cdclk(struct drm_atomic_state *state) static int skl_modeset_calc_cdclk(struct drm_atomic_state *state) { - struct intel_atomic_state *intel_state = to_intel_atomic_state(state); struct drm_i915_private *dev_priv = to_i915(state->dev); - const int max_pixclk = intel_max_pixel_rate(state); - int cdclk, vco; + struct intel_atomic_state *intel_state = to_intel_atomic_state(state); + int min_cdclk, cdclk, vco; + + min_cdclk = intel_compute_min_cdclk(state); + if (min_cdclk < 0) + return min_cdclk; vco = intel_state->cdclk.logical.vco; if (!vco) @@ -1893,13 +1898,7 @@ static int skl_modeset_calc_cdclk(struct drm_atomic_state *state) * FIXME should also account for plane ratio * once 64bpp pixel formats are supported. */ - cdclk = skl_calc_cdclk(max_pixclk, vco); - - if (cdclk > dev_priv->max_cdclk_freq) { - DRM_DEBUG_KMS("requested cdclk (%d kHz) exceeds max (%d kHz)\n", - cdclk, dev_priv->max_cdclk_freq); - return -EINVAL; - } + cdclk = skl_calc_cdclk(min_cdclk, vco); intel_state->cdclk.logical.vco = vco; intel_state->cdclk.logical.cdclk = cdclk; @@ -1920,25 +1919,21 @@ static int skl_modeset_calc_cdclk(struct drm_atomic_state *state) static int bxt_modeset_calc_cdclk(struct drm_atomic_state *state) { struct drm_i915_private *dev_priv = to_i915(state->dev); - int max_pixclk = intel_max_pixel_rate(state); - struct intel_atomic_state *intel_state = - to_intel_atomic_state(state); - int cdclk, vco; + struct intel_atomic_state *intel_state = to_intel_atomic_state(state); + int min_cdclk, cdclk, vco; + + min_cdclk = intel_compute_min_cdclk(state); + if (min_cdclk < 0) + return min_cdclk; if (IS_GEMINILAKE(dev_priv)) { - cdclk = glk_calc_cdclk(max_pixclk); + cdclk = glk_calc_cdclk(min_cdclk); vco = glk_de_pll_vco(dev_priv, cdclk); } else { - cdclk = bxt_calc_cdclk(max_pixclk); + cdclk = bxt_calc_cdclk(min_cdclk); vco = bxt_de_pll_vco(dev_priv, cdclk); } - if (cdclk > dev_priv->max_cdclk_freq) { - DRM_DEBUG_KMS("requested cdclk (%d kHz) exceeds max (%d kHz)\n", - cdclk, dev_priv->max_cdclk_freq); - return -EINVAL; - } - intel_state->cdclk.logical.vco = vco; intel_state->cdclk.logical.cdclk = cdclk; @@ -1964,19 +1959,15 @@ static int bxt_modeset_calc_cdclk(struct drm_atomic_state *state) static int cnl_modeset_calc_cdclk(struct drm_atomic_state *state) { struct drm_i915_private *dev_priv = to_i915(state->dev); - struct intel_atomic_state *intel_state = - to_intel_atomic_state(state); - int max_pixclk = intel_max_pixel_rate(state); - int cdclk, vco; + struct intel_atomic_state *intel_state = to_intel_atomic_state(state); + int min_cdclk, cdclk, vco; - cdclk = cnl_calc_cdclk(max_pixclk); - vco = cnl_cdclk_pll_vco(dev_priv, cdclk); + min_cdclk = intel_compute_min_cdclk(state); + if (min_cdclk < 0) + return min_cdclk; - if (cdclk > dev_priv->max_cdclk_freq) { - DRM_DEBUG_KMS("requested cdclk (%d kHz) exceeds max (%d kHz)\n", - cdclk, dev_priv->max_cdclk_freq); - return -EINVAL; - } + cdclk = cnl_calc_cdclk(min_cdclk); + vco = cnl_cdclk_pll_vco(dev_priv, cdclk); intel_state->cdclk.logical.vco = vco; intel_state->cdclk.logical.cdclk = cdclk; @@ -1999,14 +1990,21 @@ static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv) { int max_cdclk_freq = dev_priv->max_cdclk_freq; - if (IS_GEMINILAKE(dev_priv)) + if (INTEL_GEN(dev_priv) >= 10) + /* + * FIXME: Allow '2 * max_cdclk_freq' + * once DDI clock voltage requirements are + * handled correctly. + */ + return max_cdclk_freq; + else if (IS_GEMINILAKE(dev_priv)) /* * FIXME: Limiting to 99% as a temporary workaround. See - * glk_calc_cdclk() for details. + * intel_min_cdclk() for details. */ return 2 * max_cdclk_freq * 99 / 100; - else if (INTEL_INFO(dev_priv)->gen >= 9 || - IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) + else if (IS_GEN9(dev_priv) || + IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) return max_cdclk_freq; else if (IS_CHERRYVIEW(dev_priv)) return max_cdclk_freq*95/100; diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 70e0ff4..a77dd80 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -143,7 +143,7 @@ static void hsw_crt_get_config(struct intel_encoder *encoder, /* Note: The caller is required to filter out dpms modes not supported by the * platform. */ static void intel_crt_set_dpms(struct intel_encoder *encoder, - struct intel_crtc_state *crtc_state, + const struct intel_crtc_state *crtc_state, int mode) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); @@ -194,28 +194,28 @@ static void intel_crt_set_dpms(struct intel_encoder *encoder, } static void intel_disable_crt(struct intel_encoder *encoder, - struct intel_crtc_state *old_crtc_state, - struct drm_connector_state *old_conn_state) + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) { intel_crt_set_dpms(encoder, old_crtc_state, DRM_MODE_DPMS_OFF); } static void pch_disable_crt(struct intel_encoder *encoder, - struct intel_crtc_state *old_crtc_state, - struct drm_connector_state *old_conn_state) + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) { } static void pch_post_disable_crt(struct intel_encoder *encoder, - struct intel_crtc_state *old_crtc_state, - struct drm_connector_state *old_conn_state) + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) { intel_disable_crt(encoder, old_crtc_state, old_conn_state); } static void hsw_post_disable_crt(struct intel_encoder *encoder, - struct intel_crtc_state *old_crtc_state, - struct drm_connector_state *old_conn_state) + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); @@ -228,8 +228,8 @@ static void hsw_post_disable_crt(struct intel_encoder *encoder, } static void intel_enable_crt(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { intel_crt_set_dpms(encoder, pipe_config, DRM_MODE_DPMS_ON); } diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 4b4fd1f..1da3bb2 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -588,6 +588,67 @@ skl_get_buf_trans_hdmi(struct drm_i915_private *dev_priv, int *n_entries) } } +static const struct cnl_ddi_buf_trans * +cnl_get_buf_trans_hdmi(struct drm_i915_private *dev_priv, int *n_entries) +{ + u32 voltage = I915_READ(CNL_PORT_COMP_DW3) & VOLTAGE_INFO_MASK; + + if (voltage == VOLTAGE_INFO_0_85V) { + *n_entries = ARRAY_SIZE(cnl_ddi_translations_hdmi_0_85V); + return cnl_ddi_translations_hdmi_0_85V; + } else if (voltage == VOLTAGE_INFO_0_95V) { + *n_entries = ARRAY_SIZE(cnl_ddi_translations_hdmi_0_95V); + return cnl_ddi_translations_hdmi_0_95V; + } else if (voltage == VOLTAGE_INFO_1_05V) { + *n_entries = ARRAY_SIZE(cnl_ddi_translations_hdmi_1_05V); + return cnl_ddi_translations_hdmi_1_05V; + } else + MISSING_CASE(voltage); + return NULL; +} + +static const struct cnl_ddi_buf_trans * +cnl_get_buf_trans_dp(struct drm_i915_private *dev_priv, int *n_entries) +{ + u32 voltage = I915_READ(CNL_PORT_COMP_DW3) & VOLTAGE_INFO_MASK; + + if (voltage == VOLTAGE_INFO_0_85V) { + *n_entries = ARRAY_SIZE(cnl_ddi_translations_dp_0_85V); + return cnl_ddi_translations_dp_0_85V; + } else if (voltage == VOLTAGE_INFO_0_95V) { + *n_entries = ARRAY_SIZE(cnl_ddi_translations_dp_0_95V); + return cnl_ddi_translations_dp_0_95V; + } else if (voltage == VOLTAGE_INFO_1_05V) { + *n_entries = ARRAY_SIZE(cnl_ddi_translations_dp_1_05V); + return cnl_ddi_translations_dp_1_05V; + } else + MISSING_CASE(voltage); + return NULL; +} + +static const struct cnl_ddi_buf_trans * +cnl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries) +{ + u32 voltage = I915_READ(CNL_PORT_COMP_DW3) & VOLTAGE_INFO_MASK; + + if (dev_priv->vbt.edp.low_vswing) { + if (voltage == VOLTAGE_INFO_0_85V) { + *n_entries = ARRAY_SIZE(cnl_ddi_translations_edp_0_85V); + return cnl_ddi_translations_edp_0_85V; + } else if (voltage == VOLTAGE_INFO_0_95V) { + *n_entries = ARRAY_SIZE(cnl_ddi_translations_edp_0_95V); + return cnl_ddi_translations_edp_0_95V; + } else if (voltage == VOLTAGE_INFO_1_05V) { + *n_entries = ARRAY_SIZE(cnl_ddi_translations_edp_1_05V); + return cnl_ddi_translations_edp_1_05V; + } else + MISSING_CASE(voltage); + return NULL; + } else { + return cnl_get_buf_trans_dp(dev_priv, n_entries); + } +} + static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port port) { int n_hdmi_entries; @@ -599,7 +660,10 @@ static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port por if (IS_GEN9_LP(dev_priv)) return hdmi_level; - if (IS_GEN9_BC(dev_priv)) { + if (IS_CANNONLAKE(dev_priv)) { + cnl_get_buf_trans_hdmi(dev_priv, &n_hdmi_entries); + hdmi_default_entry = n_hdmi_entries - 1; + } else if (IS_GEN9_BC(dev_priv)) { skl_get_buf_trans_hdmi(dev_priv, &n_hdmi_entries); hdmi_default_entry = 8; } else if (IS_BROADWELL(dev_priv)) { @@ -688,9 +752,6 @@ static void intel_prepare_dp_ddi_buffers(struct intel_encoder *encoder) enum port port = intel_ddi_get_encoder_port(encoder); const struct ddi_buf_trans *ddi_translations; - if (IS_GEN9_LP(dev_priv)) - return; - switch (encoder->type) { case INTEL_OUTPUT_EDP: ddi_translations = intel_ddi_get_buf_trans_edp(dev_priv, @@ -741,9 +802,6 @@ static void intel_prepare_hdmi_ddi_buffers(struct intel_encoder *encoder) enum port port = intel_ddi_get_encoder_port(encoder); const struct ddi_buf_trans *ddi_translations_hdmi; - if (IS_GEN9_LP(dev_priv)) - return; - hdmi_level = intel_ddi_hdmi_level(dev_priv, port); if (IS_GEN9_BC(dev_priv)) { @@ -785,7 +843,7 @@ static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv, DRM_ERROR("Timeout waiting for DDI BUF %c idle bit\n", port_name(port)); } -static uint32_t hsw_pll_to_ddi_pll_sel(struct intel_shared_dpll *pll) +static uint32_t hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll) { switch (pll->id) { case DPLL_ID_WRPLL1: @@ -1821,10 +1879,17 @@ u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder) struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); int n_entries; - if (encoder->type == INTEL_OUTPUT_EDP) - intel_ddi_get_buf_trans_edp(dev_priv, &n_entries); - else - intel_ddi_get_buf_trans_dp(dev_priv, &n_entries); + if (IS_CANNONLAKE(dev_priv)) { + if (encoder->type == INTEL_OUTPUT_EDP) + cnl_get_buf_trans_edp(dev_priv, &n_entries); + else + cnl_get_buf_trans_dp(dev_priv, &n_entries); + } else { + if (encoder->type == INTEL_OUTPUT_EDP) + intel_ddi_get_buf_trans_edp(dev_priv, &n_entries); + else + intel_ddi_get_buf_trans_dp(dev_priv, &n_entries); + } if (WARN_ON(n_entries < 1)) n_entries = 1; @@ -1835,90 +1900,23 @@ u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder) DP_TRAIN_VOLTAGE_SWING_MASK; } -static const struct cnl_ddi_buf_trans * -cnl_get_buf_trans_hdmi(struct drm_i915_private *dev_priv, - u32 voltage, int *n_entries) -{ - if (voltage == VOLTAGE_INFO_0_85V) { - *n_entries = ARRAY_SIZE(cnl_ddi_translations_hdmi_0_85V); - return cnl_ddi_translations_hdmi_0_85V; - } else if (voltage == VOLTAGE_INFO_0_95V) { - *n_entries = ARRAY_SIZE(cnl_ddi_translations_hdmi_0_95V); - return cnl_ddi_translations_hdmi_0_95V; - } else if (voltage == VOLTAGE_INFO_1_05V) { - *n_entries = ARRAY_SIZE(cnl_ddi_translations_hdmi_1_05V); - return cnl_ddi_translations_hdmi_1_05V; - } - return NULL; -} - -static const struct cnl_ddi_buf_trans * -cnl_get_buf_trans_dp(struct drm_i915_private *dev_priv, - u32 voltage, int *n_entries) -{ - if (voltage == VOLTAGE_INFO_0_85V) { - *n_entries = ARRAY_SIZE(cnl_ddi_translations_dp_0_85V); - return cnl_ddi_translations_dp_0_85V; - } else if (voltage == VOLTAGE_INFO_0_95V) { - *n_entries = ARRAY_SIZE(cnl_ddi_translations_dp_0_95V); - return cnl_ddi_translations_dp_0_95V; - } else if (voltage == VOLTAGE_INFO_1_05V) { - *n_entries = ARRAY_SIZE(cnl_ddi_translations_dp_1_05V); - return cnl_ddi_translations_dp_1_05V; - } - return NULL; -} - -static const struct cnl_ddi_buf_trans * -cnl_get_buf_trans_edp(struct drm_i915_private *dev_priv, - u32 voltage, int *n_entries) -{ - if (dev_priv->vbt.edp.low_vswing) { - if (voltage == VOLTAGE_INFO_0_85V) { - *n_entries = ARRAY_SIZE(cnl_ddi_translations_edp_0_85V); - return cnl_ddi_translations_edp_0_85V; - } else if (voltage == VOLTAGE_INFO_0_95V) { - *n_entries = ARRAY_SIZE(cnl_ddi_translations_edp_0_95V); - return cnl_ddi_translations_edp_0_95V; - } else if (voltage == VOLTAGE_INFO_1_05V) { - *n_entries = ARRAY_SIZE(cnl_ddi_translations_edp_1_05V); - return cnl_ddi_translations_edp_1_05V; - } - return NULL; - } else { - return cnl_get_buf_trans_dp(dev_priv, voltage, n_entries); - } -} - static void cnl_ddi_vswing_program(struct drm_i915_private *dev_priv, u32 level, enum port port, int type) { const struct cnl_ddi_buf_trans *ddi_translations = NULL; - u32 n_entries, val, voltage; + u32 n_entries, val; int ln; - /* - * Values for each port type are listed in - * voltage swing programming tables. - * Vccio voltage found in PORT_COMP_DW3. - */ - voltage = I915_READ(CNL_PORT_COMP_DW3) & VOLTAGE_INFO_MASK; - if (type == INTEL_OUTPUT_HDMI) { - ddi_translations = cnl_get_buf_trans_hdmi(dev_priv, - voltage, &n_entries); + ddi_translations = cnl_get_buf_trans_hdmi(dev_priv, &n_entries); } else if (type == INTEL_OUTPUT_DP) { - ddi_translations = cnl_get_buf_trans_dp(dev_priv, - voltage, &n_entries); + ddi_translations = cnl_get_buf_trans_dp(dev_priv, &n_entries); } else if (type == INTEL_OUTPUT_EDP) { - ddi_translations = cnl_get_buf_trans_edp(dev_priv, - voltage, &n_entries); + ddi_translations = cnl_get_buf_trans_edp(dev_priv, &n_entries); } - if (ddi_translations == NULL) { - MISSING_CASE(voltage); + if (WARN_ON(ddi_translations == NULL)) return; - } if (level >= n_entries) { DRM_DEBUG_KMS("DDI translation not found for level %d. Using %d instead.", level, n_entries - 1); @@ -2054,33 +2052,46 @@ static uint32_t translate_signal_level(int signal_levels) return 0; } -uint32_t ddi_signal_levels(struct intel_dp *intel_dp) +static uint32_t intel_ddi_dp_level(struct intel_dp *intel_dp) { - struct intel_digital_port *dport = dp_to_dig_port(intel_dp); - struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev); - struct intel_encoder *encoder = &dport->base; uint8_t train_set = intel_dp->train_set[0]; int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK | DP_TRAIN_PRE_EMPHASIS_MASK); + + return translate_signal_level(signal_levels); +} + +u32 bxt_signal_levels(struct intel_dp *intel_dp) +{ + struct intel_digital_port *dport = dp_to_dig_port(intel_dp); + struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev); + struct intel_encoder *encoder = &dport->base; enum port port = dport->port; - uint32_t level; + u32 level = intel_ddi_dp_level(intel_dp); - level = translate_signal_level(signal_levels); + if (IS_CANNONLAKE(dev_priv)) + cnl_ddi_vswing_sequence(encoder, level); + else + bxt_ddi_vswing_sequence(dev_priv, level, port, encoder->type); + + return 0; +} + +uint32_t ddi_signal_levels(struct intel_dp *intel_dp) +{ + struct intel_digital_port *dport = dp_to_dig_port(intel_dp); + struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev); + struct intel_encoder *encoder = &dport->base; + uint32_t level = intel_ddi_dp_level(intel_dp); if (IS_GEN9_BC(dev_priv)) - skl_ddi_set_iboost(encoder, level); - else if (IS_GEN9_LP(dev_priv)) - bxt_ddi_vswing_sequence(dev_priv, level, port, encoder->type); - else if (IS_CANNONLAKE(dev_priv)) { - cnl_ddi_vswing_sequence(encoder, level); - /* DDI_BUF_CTL bits 27:24 are reserved on CNL */ - return 0; - } + skl_ddi_set_iboost(encoder, level); + return DDI_BUF_TRANS_SELECT(level); } static void intel_ddi_clk_select(struct intel_encoder *encoder, - struct intel_shared_dpll *pll) + const struct intel_shared_dpll *pll) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); enum port port = intel_ddi_get_encoder_port(encoder); @@ -2129,6 +2140,7 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder, struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); enum port port = intel_ddi_get_encoder_port(encoder); struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base); + uint32_t level = intel_ddi_dp_level(intel_dp); WARN_ON(link_mst && (port == PORT_A || port == PORT_E)); @@ -2141,7 +2153,13 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder, intel_display_power_get(dev_priv, dig_port->ddi_io_power_domain); - intel_prepare_dp_ddi_buffers(encoder); + if (IS_CANNONLAKE(dev_priv)) + cnl_ddi_vswing_sequence(encoder, level); + else if (IS_GEN9_LP(dev_priv)) + bxt_ddi_vswing_sequence(dev_priv, level, port, encoder->type); + else + intel_prepare_dp_ddi_buffers(encoder); + intel_ddi_init_dp_buf_reg(encoder); intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); intel_dp_start_link_train(intel_dp); @@ -2150,14 +2168,14 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder, } static void intel_ddi_pre_enable_hdmi(struct intel_encoder *encoder, - bool has_hdmi_sink, + bool has_infoframe, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state, - struct intel_shared_dpll *pll) + const struct intel_shared_dpll *pll) { - struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); + struct intel_digital_port *intel_dig_port = enc_to_dig_port(&encoder->base); + struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi; struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct drm_encoder *drm_encoder = &encoder->base; enum port port = intel_ddi_get_encoder_port(encoder); int level = intel_ddi_hdmi_level(dev_priv, port); struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base); @@ -2167,23 +2185,25 @@ static void intel_ddi_pre_enable_hdmi(struct intel_encoder *encoder, intel_display_power_get(dev_priv, dig_port->ddi_io_power_domain); - intel_prepare_hdmi_ddi_buffers(encoder); - if (IS_GEN9_BC(dev_priv)) - skl_ddi_set_iboost(encoder, level); + if (IS_CANNONLAKE(dev_priv)) + cnl_ddi_vswing_sequence(encoder, level); else if (IS_GEN9_LP(dev_priv)) bxt_ddi_vswing_sequence(dev_priv, level, port, INTEL_OUTPUT_HDMI); - else if (IS_CANNONLAKE(dev_priv)) - cnl_ddi_vswing_sequence(encoder, level); + else + intel_prepare_hdmi_ddi_buffers(encoder); + + if (IS_GEN9_BC(dev_priv)) + skl_ddi_set_iboost(encoder, level); - intel_hdmi->set_infoframes(drm_encoder, - has_hdmi_sink, - crtc_state, conn_state); + intel_dig_port->set_infoframes(&encoder->base, + has_infoframe, + crtc_state, conn_state); } static void intel_ddi_pre_enable(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { int type = encoder->type; @@ -2197,21 +2217,20 @@ static void intel_ddi_pre_enable(struct intel_encoder *encoder, } if (type == INTEL_OUTPUT_HDMI) { intel_ddi_pre_enable_hdmi(encoder, - pipe_config->has_hdmi_sink, + pipe_config->has_infoframe, pipe_config, conn_state, pipe_config->shared_dpll); } } static void intel_ddi_post_disable(struct intel_encoder *intel_encoder, - struct intel_crtc_state *old_crtc_state, - struct drm_connector_state *old_conn_state) + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) { struct drm_encoder *encoder = &intel_encoder->base; struct drm_i915_private *dev_priv = to_i915(encoder->dev); enum port port = intel_ddi_get_encoder_port(intel_encoder); struct intel_digital_port *dig_port = enc_to_dig_port(encoder); - struct intel_dp *intel_dp = NULL; int type = intel_encoder->type; uint32_t val; bool wait = false; @@ -2219,7 +2238,8 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder, /* old_crtc_state and old_conn_state are NULL when called from DP_MST */ if (type == INTEL_OUTPUT_DP || type == INTEL_OUTPUT_EDP) { - intel_dp = enc_to_intel_dp(encoder); + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); } @@ -2238,7 +2258,14 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder, if (wait) intel_wait_ddi_buf_idle(dev_priv, port); - if (intel_dp) { + if (type == INTEL_OUTPUT_HDMI) { + dig_port->set_infoframes(encoder, false, + old_crtc_state, old_conn_state); + } + + if (type == INTEL_OUTPUT_DP || type == INTEL_OUTPUT_EDP) { + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + intel_edp_panel_vdd_on(intel_dp); intel_edp_panel_off(intel_dp); } @@ -2263,8 +2290,8 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder, } void intel_ddi_fdi_post_disable(struct intel_encoder *encoder, - struct intel_crtc_state *old_crtc_state, - struct drm_connector_state *old_conn_state) + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); uint32_t val; @@ -2296,8 +2323,8 @@ void intel_ddi_fdi_post_disable(struct intel_encoder *encoder, } static void intel_enable_ddi(struct intel_encoder *intel_encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { struct drm_encoder *encoder = &intel_encoder->base; struct drm_i915_private *dev_priv = to_i915(encoder->dev); @@ -2328,7 +2355,7 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder, intel_dp_stop_link_train(intel_dp); intel_edp_backlight_on(pipe_config, conn_state); - intel_psr_enable(intel_dp); + intel_psr_enable(intel_dp, pipe_config); intel_edp_drrs_enable(intel_dp, pipe_config); } @@ -2337,8 +2364,8 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder, } static void intel_disable_ddi(struct intel_encoder *intel_encoder, - struct intel_crtc_state *old_crtc_state, - struct drm_connector_state *old_conn_state) + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) { struct drm_encoder *encoder = &intel_encoder->base; int type = intel_encoder->type; @@ -2356,14 +2383,14 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder, struct intel_dp *intel_dp = enc_to_intel_dp(encoder); intel_edp_drrs_disable(intel_dp, old_crtc_state); - intel_psr_disable(intel_dp); + intel_psr_disable(intel_dp, old_crtc_state); intel_edp_backlight_off(old_conn_state); } } static void bxt_ddi_pre_pll_enable(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { uint8_t mask = pipe_config->lane_lat_optim_mask; @@ -2435,7 +2462,7 @@ void intel_ddi_get_config(struct intel_encoder *encoder, struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); enum transcoder cpu_transcoder = pipe_config->cpu_transcoder; - struct intel_hdmi *intel_hdmi; + struct intel_digital_port *intel_dig_port; u32 temp, flags = 0; /* XXX: DSI transcoder paranoia */ @@ -2474,9 +2501,9 @@ void intel_ddi_get_config(struct intel_encoder *encoder, switch (temp & TRANS_DDI_MODE_SELECT_MASK) { case TRANS_DDI_MODE_SELECT_HDMI: pipe_config->has_hdmi_sink = true; - intel_hdmi = enc_to_intel_hdmi(&encoder->base); + intel_dig_port = enc_to_dig_port(&encoder->base); - if (intel_hdmi->infoframe_enabled(&encoder->base, pipe_config)) + if (intel_dig_port->infoframe_enabled(&encoder->base, pipe_config)) pipe_config->has_infoframe = true; if ((temp & TRANS_DDI_HDMI_SCRAMBLING_MASK) == @@ -2729,6 +2756,8 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); intel_encoder->cloneable = 0; + intel_infoframe_init(intel_dig_port); + if (init_dp) { if (!intel_ddi_init_dp_connector(intel_dig_port)) goto err; diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index 5f91ddc..b17f704 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -412,7 +412,7 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv) else if (INTEL_INFO(dev_priv)->gen >= 9) gen9_sseu_info_init(dev_priv); - info->has_snoop = !info->has_llc; + WARN_ON(info->has_snoop != !info->has_llc); DRM_DEBUG_DRIVER("slice mask: %04x\n", info->sseu.slice_mask); DRM_DEBUG_DRIVER("slice total: %u\n", hweight8(info->sseu.slice_mask)); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 00cd17c..f780f39 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3770,8 +3770,8 @@ void intel_finish_reset(struct drm_i915_private *dev_priv) if (!gpu_reset_clobbers_display(dev_priv)) { /* for testing only restore the display */ ret = __intel_display_resume(dev, state, ctx); - if (ret) - DRM_ERROR("Restoring old state failed with %i\n", ret); + if (ret) + DRM_ERROR("Restoring old state failed with %i\n", ret); } else { /* * The display has been reset as well, @@ -3804,15 +3804,14 @@ unlock: clear_bit(I915_RESET_MODESET, &dev_priv->gpu_error.flags); } -static void intel_update_pipe_config(struct intel_crtc *crtc, - struct intel_crtc_state *old_crtc_state) +static void intel_update_pipe_config(const struct intel_crtc_state *old_crtc_state, + const struct intel_crtc_state *new_crtc_state) { + struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - struct intel_crtc_state *pipe_config = - to_intel_crtc_state(crtc->base.state); /* drm_atomic_helper_update_legacy_modeset_state might not be called. */ - crtc->base.mode = crtc->base.state->mode; + crtc->base.mode = new_crtc_state->base.mode; /* * Update pipe size and adjust fitter if needed: the reason for this is @@ -3824,17 +3823,17 @@ static void intel_update_pipe_config(struct intel_crtc *crtc, */ I915_WRITE(PIPESRC(crtc->pipe), - ((pipe_config->pipe_src_w - 1) << 16) | - (pipe_config->pipe_src_h - 1)); + ((new_crtc_state->pipe_src_w - 1) << 16) | + (new_crtc_state->pipe_src_h - 1)); /* on skylake this is done by detaching scalers */ if (INTEL_GEN(dev_priv) >= 9) { skl_detach_scalers(crtc); - if (pipe_config->pch_pfit.enabled) + if (new_crtc_state->pch_pfit.enabled) skylake_pfit_enable(crtc); } else if (HAS_PCH_SPLIT(dev_priv)) { - if (pipe_config->pch_pfit.enabled) + if (new_crtc_state->pch_pfit.enabled) ironlake_pfit_enable(crtc); else if (old_crtc_state->pch_pfit.enabled) ironlake_pfit_disable(crtc, true); @@ -5118,7 +5117,8 @@ static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state) struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); struct drm_atomic_state *old_state = old_crtc_state->base.state; struct intel_crtc_state *pipe_config = - to_intel_crtc_state(crtc->base.state); + intel_atomic_get_new_crtc_state(to_intel_atomic_state(old_state), + crtc); struct drm_plane *primary = crtc->base.primary; struct drm_plane_state *old_pri_state = drm_atomic_get_existing_plane_state(old_state, primary); @@ -5130,7 +5130,8 @@ static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state) if (old_pri_state) { struct intel_plane_state *primary_state = - to_intel_plane_state(primary->state); + intel_atomic_get_new_plane_state(to_intel_atomic_state(old_state), + to_intel_plane(primary)); struct intel_plane_state *old_primary_state = to_intel_plane_state(old_pri_state); @@ -5159,7 +5160,8 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state, if (old_pri_state) { struct intel_plane_state *primary_state = - to_intel_plane_state(primary->state); + intel_atomic_get_new_plane_state(old_intel_state, + to_intel_plane(primary)); struct intel_plane_state *old_primary_state = to_intel_plane_state(old_pri_state); @@ -6038,7 +6040,7 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc, intel_crtc->enabled_power_domains = 0; dev_priv->active_crtcs &= ~(1 << intel_crtc->pipe); - dev_priv->min_pixclk[intel_crtc->pipe] = 0; + dev_priv->min_cdclk[intel_crtc->pipe] = 0; } /* @@ -6283,6 +6285,9 @@ retry: static bool pipe_config_supports_ips(struct drm_i915_private *dev_priv, struct intel_crtc_state *pipe_config) { + if (pipe_config->ips_force_disable) + return false; + if (pipe_config->pipe_bpp > 24) return false; @@ -9039,7 +9044,7 @@ static void cannonlake_get_ddi_pll(struct drm_i915_private *dev_priv, u32 temp; temp = I915_READ(DPCLKA_CFGCR0) & DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port); - id = temp >> (port * 2); + id = temp >> DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(port); if (WARN_ON(id < SKL_DPLL0 || id > SKL_DPLL2)) return; @@ -9753,7 +9758,7 @@ static void i9xx_disable_cursor(struct intel_plane *plane, /* VESA 640x480x72Hz mode to set on the pipe */ -static struct drm_display_mode load_detect_mode = { +static const struct drm_display_mode load_detect_mode = { DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 31500, 640, 664, 704, 832, 0, 480, 489, 491, 520, 0, DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), }; @@ -9788,7 +9793,7 @@ intel_framebuffer_pitch_for_width(int width, int bpp) } static u32 -intel_framebuffer_size_for_mode(struct drm_display_mode *mode, int bpp) +intel_framebuffer_size_for_mode(const struct drm_display_mode *mode, int bpp) { u32 pitch = intel_framebuffer_pitch_for_width(mode->hdisplay, bpp); return PAGE_ALIGN(pitch * mode->vdisplay); @@ -9796,7 +9801,7 @@ intel_framebuffer_size_for_mode(struct drm_display_mode *mode, int bpp) static struct drm_framebuffer * intel_framebuffer_create_for_mode(struct drm_device *dev, - struct drm_display_mode *mode, + const struct drm_display_mode *mode, int depth, int bpp) { struct drm_framebuffer *fb; @@ -9823,7 +9828,7 @@ intel_framebuffer_create_for_mode(struct drm_device *dev, static struct drm_framebuffer * mode_fits_in_fbdev(struct drm_device *dev, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { #ifdef CONFIG_DRM_FBDEV_EMULATION struct drm_i915_private *dev_priv = to_i915(dev); @@ -9856,7 +9861,7 @@ mode_fits_in_fbdev(struct drm_device *dev, static int intel_modeset_setup_plane_state(struct drm_atomic_state *state, struct drm_crtc *crtc, - struct drm_display_mode *mode, + const struct drm_display_mode *mode, struct drm_framebuffer *fb, int x, int y) { @@ -9890,7 +9895,7 @@ static int intel_modeset_setup_plane_state(struct drm_atomic_state *state, } int intel_get_load_detect_pipe(struct drm_connector *connector, - struct drm_display_mode *mode, + const struct drm_display_mode *mode, struct intel_load_detect_pipe *old, struct drm_modeset_acquire_ctx *ctx) { @@ -10337,7 +10342,7 @@ static bool intel_wm_need_update(struct drm_plane *plane, return false; } -static bool needs_scaling(struct intel_plane_state *state) +static bool needs_scaling(const struct intel_plane_state *state) { int src_w = drm_rect_width(&state->base.src) >> 16; int src_h = drm_rect_height(&state->base.src) >> 16; @@ -10347,7 +10352,9 @@ static bool needs_scaling(struct intel_plane_state *state) return (src_w != dst_w || src_h != dst_h); } -int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, +int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_crtc_state, + struct drm_crtc_state *crtc_state, + const struct intel_plane_state *old_plane_state, struct drm_plane_state *plane_state) { struct intel_crtc_state *pipe_config = to_intel_crtc_state(crtc_state); @@ -10356,10 +10363,8 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, struct intel_plane *plane = to_intel_plane(plane_state->plane); struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_plane_state *old_plane_state = - to_intel_plane_state(plane->base.state); bool mode_changed = needs_modeset(crtc_state); - bool was_crtc_enabled = crtc->state->active; + bool was_crtc_enabled = old_crtc_state->base.active; bool is_crtc_enabled = crtc_state->active; bool turn_off, turn_on, visible, was_visible; struct drm_framebuffer *fb = plane_state->fb; @@ -10850,7 +10855,7 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state) struct intel_dpll_hw_state dpll_hw_state; struct intel_shared_dpll *shared_dpll; struct intel_crtc_wm_state wm_state; - bool force_thru; + bool force_thru, ips_force_disable; /* FIXME: before the switch to atomic started, a new pipe_config was * kzalloc'd. Code that depends on any field being zero should be @@ -10861,6 +10866,7 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state) shared_dpll = crtc_state->shared_dpll; dpll_hw_state = crtc_state->dpll_hw_state; force_thru = crtc_state->pch_pfit.force_thru; + ips_force_disable = crtc_state->ips_force_disable; if (IS_G4X(dev_priv) || IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) wm_state = crtc_state->wm; @@ -10874,6 +10880,7 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state) crtc_state->shared_dpll = shared_dpll; crtc_state->dpll_hw_state = dpll_hw_state; crtc_state->pch_pfit.force_thru = force_thru; + crtc_state->ips_force_disable = ips_force_disable; if (IS_G4X(dev_priv) || IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) crtc_state->wm = wm_state; @@ -12129,73 +12136,10 @@ u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc) return dev->driver->get_vblank_counter(dev, crtc->pipe); } -static void intel_atomic_wait_for_vblanks(struct drm_device *dev, - struct drm_i915_private *dev_priv, - unsigned crtc_mask) -{ - unsigned last_vblank_count[I915_MAX_PIPES]; - enum pipe pipe; - int ret; - - if (!crtc_mask) - return; - - for_each_pipe(dev_priv, pipe) { - struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, - pipe); - - if (!((1 << pipe) & crtc_mask)) - continue; - - ret = drm_crtc_vblank_get(&crtc->base); - if (WARN_ON(ret != 0)) { - crtc_mask &= ~(1 << pipe); - continue; - } - - last_vblank_count[pipe] = drm_crtc_vblank_count(&crtc->base); - } - - for_each_pipe(dev_priv, pipe) { - struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, - pipe); - long lret; - - if (!((1 << pipe) & crtc_mask)) - continue; - - lret = wait_event_timeout(dev->vblank[pipe].queue, - last_vblank_count[pipe] != - drm_crtc_vblank_count(&crtc->base), - msecs_to_jiffies(50)); - - WARN(!lret, "pipe %c vblank wait timed out\n", pipe_name(pipe)); - - drm_crtc_vblank_put(&crtc->base); - } -} - -static bool needs_vblank_wait(struct intel_crtc_state *crtc_state) -{ - /* fb updated, need to unpin old fb */ - if (crtc_state->fb_changed) - return true; - - /* wm changes, need vblank before final wm's */ - if (crtc_state->update_wm_post) - return true; - - if (crtc_state->wm.need_postvbl_update) - return true; - - return false; -} - static void intel_update_crtc(struct drm_crtc *crtc, struct drm_atomic_state *state, struct drm_crtc_state *old_crtc_state, - struct drm_crtc_state *new_crtc_state, - unsigned int *crtc_vblank_mask) + struct drm_crtc_state *new_crtc_state) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = to_i915(dev); @@ -12218,13 +12162,9 @@ static void intel_update_crtc(struct drm_crtc *crtc, } drm_atomic_helper_commit_planes_on_crtc(old_crtc_state); - - if (needs_vblank_wait(pipe_config)) - *crtc_vblank_mask |= drm_crtc_mask(crtc); } -static void intel_update_crtcs(struct drm_atomic_state *state, - unsigned int *crtc_vblank_mask) +static void intel_update_crtcs(struct drm_atomic_state *state) { struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state, *new_crtc_state; @@ -12235,12 +12175,11 @@ static void intel_update_crtcs(struct drm_atomic_state *state, continue; intel_update_crtc(crtc, state, old_crtc_state, - new_crtc_state, crtc_vblank_mask); + new_crtc_state); } } -static void skl_update_crtcs(struct drm_atomic_state *state, - unsigned int *crtc_vblank_mask) +static void skl_update_crtcs(struct drm_atomic_state *state) { struct drm_i915_private *dev_priv = to_i915(state->dev); struct intel_atomic_state *intel_state = to_intel_atomic_state(state); @@ -12274,7 +12213,7 @@ static void skl_update_crtcs(struct drm_atomic_state *state, unsigned int cmask = drm_crtc_mask(crtc); intel_crtc = to_intel_crtc(crtc); - cstate = to_intel_crtc_state(crtc->state); + cstate = to_intel_crtc_state(new_crtc_state); pipe = intel_crtc->pipe; if (updated & cmask || !cstate->base.active) @@ -12299,7 +12238,7 @@ static void skl_update_crtcs(struct drm_atomic_state *state, vbl_wait = true; intel_update_crtc(crtc, state, old_crtc_state, - new_crtc_state, crtc_vblank_mask); + new_crtc_state); if (vbl_wait) intel_wait_for_vblank(dev_priv, pipe); @@ -12361,7 +12300,6 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) struct intel_crtc_state *intel_cstate; bool hw_check = intel_state->modeset; u64 put_domains[I915_MAX_PIPES] = {}; - unsigned crtc_vblank_mask = 0; int i; intel_atomic_commit_fence_wait(intel_state); @@ -12403,7 +12341,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) intel_check_cpu_fifo_underruns(dev_priv); intel_check_pch_fifo_underruns(dev_priv); - if (!crtc->state->active) { + if (!new_crtc_state->active) { /* * Make sure we don't call initial_watermarks * for ILK-style watermark updates. @@ -12412,7 +12350,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) */ if (INTEL_GEN(dev_priv) >= 9) dev_priv->display.initial_watermarks(intel_state, - to_intel_crtc_state(crtc->state)); + to_intel_crtc_state(new_crtc_state)); } } } @@ -12451,7 +12389,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) } /* Now enable the clocks, plane, pipe, and connectors that we set up. */ - dev_priv->display.update_crtcs(state, &crtc_vblank_mask); + dev_priv->display.update_crtcs(state); /* FIXME: We should call drm_atomic_helper_commit_hw_done() here * already, but still need the state for the delayed optimization. To @@ -12462,8 +12400,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) * - switch over to the vblank wait helper in the core after that since * we don't need out special handling any more. */ - if (!state->legacy_cursor_update) - intel_atomic_wait_for_vblanks(dev, dev_priv, crtc_vblank_mask); + drm_atomic_helper_wait_for_flip_done(dev, state); /* * Now that the vblank has passed, we can go ahead and program the @@ -12626,8 +12563,8 @@ static int intel_atomic_commit(struct drm_device *dev, intel_atomic_track_fbs(state); if (intel_state->modeset) { - memcpy(dev_priv->min_pixclk, intel_state->min_pixclk, - sizeof(intel_state->min_pixclk)); + memcpy(dev_priv->min_cdclk, intel_state->min_cdclk, + sizeof(intel_state->min_cdclk)); dev_priv->active_crtcs = intel_state->active_crtcs; dev_priv->cdclk.logical = intel_state->cdclk.logical; dev_priv->cdclk.actual = intel_state->cdclk.actual; @@ -12656,6 +12593,58 @@ static const struct drm_crtc_funcs intel_crtc_funcs = { .set_crc_source = intel_crtc_set_crc_source, }; +struct wait_rps_boost { + struct wait_queue_entry wait; + + struct drm_crtc *crtc; + struct drm_i915_gem_request *request; +}; + +static int do_rps_boost(struct wait_queue_entry *_wait, + unsigned mode, int sync, void *key) +{ + struct wait_rps_boost *wait = container_of(_wait, typeof(*wait), wait); + struct drm_i915_gem_request *rq = wait->request; + + gen6_rps_boost(rq, NULL); + i915_gem_request_put(rq); + + drm_crtc_vblank_put(wait->crtc); + + list_del(&wait->wait.entry); + kfree(wait); + return 1; +} + +static void add_rps_boost_after_vblank(struct drm_crtc *crtc, + struct dma_fence *fence) +{ + struct wait_rps_boost *wait; + + if (!dma_fence_is_i915(fence)) + return; + + if (INTEL_GEN(to_i915(crtc->dev)) < 6) + return; + + if (drm_crtc_vblank_get(crtc)) + return; + + wait = kmalloc(sizeof(*wait), GFP_KERNEL); + if (!wait) { + drm_crtc_vblank_put(crtc); + return; + } + + wait->request = to_request(dma_fence_get(fence)); + wait->crtc = crtc; + + wait->wait.func = do_rps_boost; + wait->wait.flags = 0; + + add_wait_queue(drm_crtc_vblank_waitqueue(crtc), &wait->wait); +} + /** * intel_prepare_plane_fb - Prepare fb for usage on plane * @plane: drm plane to prepare for @@ -12753,12 +12742,22 @@ intel_prepare_plane_fb(struct drm_plane *plane, return ret; if (!new_state->fence) { /* implicit fencing */ + struct dma_fence *fence; + ret = i915_sw_fence_await_reservation(&intel_state->commit_ready, obj->resv, NULL, false, I915_FENCE_TIMEOUT, GFP_KERNEL); if (ret < 0) return ret; + + fence = reservation_object_get_excl_rcu(obj->resv); + if (fence) { + add_rps_boost_after_vblank(new_state->crtc, fence); + dma_fence_put(fence); + } + } else { + add_rps_boost_after_vblank(new_state->crtc, new_state->fence); } return 0; @@ -12875,29 +12874,29 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc, struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct intel_crtc_state *intel_cstate = - to_intel_crtc_state(crtc->state); struct intel_crtc_state *old_intel_cstate = to_intel_crtc_state(old_crtc_state); struct intel_atomic_state *old_intel_state = to_intel_atomic_state(old_crtc_state->state); - bool modeset = needs_modeset(crtc->state); + struct intel_crtc_state *intel_cstate = + intel_atomic_get_new_crtc_state(old_intel_state, intel_crtc); + bool modeset = needs_modeset(&intel_cstate->base); if (!modeset && (intel_cstate->base.color_mgmt_changed || intel_cstate->update_pipe)) { - intel_color_set_csc(crtc->state); - intel_color_load_luts(crtc->state); + intel_color_set_csc(&intel_cstate->base); + intel_color_load_luts(&intel_cstate->base); } /* Perform vblank evasion around commit operation */ - intel_pipe_update_start(intel_crtc); + intel_pipe_update_start(intel_cstate); if (modeset) goto out; if (intel_cstate->update_pipe) - intel_update_pipe_config(intel_crtc, old_intel_cstate); + intel_update_pipe_config(old_intel_cstate, intel_cstate); else if (INTEL_GEN(dev_priv) >= 9) skl_detach_scalers(intel_crtc); @@ -12911,8 +12910,12 @@ static void intel_finish_crtc_commit(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_atomic_state *old_intel_state = + to_intel_atomic_state(old_crtc_state->state); + struct intel_crtc_state *new_crtc_state = + intel_atomic_get_new_crtc_state(old_intel_state, intel_crtc); - intel_pipe_update_end(intel_crtc); + intel_pipe_update_end(new_crtc_state); } /** @@ -13061,6 +13064,14 @@ intel_legacy_cursor_update(struct drm_plane *plane, goto slow; old_plane_state = plane->state; + /* + * Don't do an async update if there is an outstanding commit modifying + * the plane. This prevents our async update's changes from getting + * overridden by a previous synchronous update's state. + */ + if (old_plane_state->commit && + !try_wait_for_completion(&old_plane_state->commit->hw_done)) + goto slow; /* * If any parameters change that may affect watermarks, @@ -13091,6 +13102,8 @@ intel_legacy_cursor_update(struct drm_plane *plane, new_plane_state->crtc_h = crtc_h; ret = intel_plane_atomic_check_with_state(to_intel_crtc_state(crtc->state), + to_intel_crtc_state(crtc->state), /* FIXME need a new crtc state? */ + to_intel_plane_state(plane->state), to_intel_plane_state(new_plane_state)); if (ret) goto out_free; @@ -13120,17 +13133,12 @@ intel_legacy_cursor_update(struct drm_plane *plane, } old_fb = old_plane_state->fb; - old_vma = to_intel_plane_state(old_plane_state)->vma; i915_gem_track_fb(intel_fb_obj(old_fb), intel_fb_obj(fb), intel_plane->frontbuffer_bit); /* Swap plane state */ - new_plane_state->fence = old_plane_state->fence; - *to_intel_plane_state(old_plane_state) = *to_intel_plane_state(new_plane_state); - new_plane_state->fence = NULL; - new_plane_state->fb = old_fb; - to_intel_plane_state(new_plane_state)->vma = NULL; + plane->state = new_plane_state; if (plane->state->visible) { trace_intel_update_plane(plane, to_intel_crtc(crtc)); @@ -13142,13 +13150,17 @@ intel_legacy_cursor_update(struct drm_plane *plane, intel_plane->disable_plane(intel_plane, to_intel_crtc(crtc)); } + old_vma = fetch_and_zero(&to_intel_plane_state(old_plane_state)->vma); if (old_vma) intel_unpin_fb_vma(old_vma); out_unlock: mutex_unlock(&dev_priv->drm.struct_mutex); out_free: - intel_plane_destroy_state(plane, new_plane_state); + if (ret) + intel_plane_destroy_state(plane, new_plane_state); + else + intel_plane_destroy_state(plane, old_plane_state); return ret; slow: @@ -13663,7 +13675,7 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv) } else if (HAS_PCH_SPLIT(dev_priv)) { int found; - dpd_is_edp = intel_dp_is_edp(dev_priv, PORT_D); + dpd_is_edp = intel_dp_is_port_edp(dev_priv, PORT_D); if (has_edp_a(dev_priv)) intel_dp_init(dev_priv, DP_A, PORT_A); @@ -13706,14 +13718,14 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv) * trust the port type the VBT declares as we've seen at least * HDMI ports that the VBT claim are DP or eDP. */ - has_edp = intel_dp_is_edp(dev_priv, PORT_B); + has_edp = intel_dp_is_port_edp(dev_priv, PORT_B); has_port = intel_bios_is_port_present(dev_priv, PORT_B); if (I915_READ(VLV_DP_B) & DP_DETECTED || has_port) has_edp &= intel_dp_init(dev_priv, VLV_DP_B, PORT_B); if ((I915_READ(VLV_HDMIB) & SDVO_DETECTED || has_port) && !has_edp) intel_hdmi_init(dev_priv, VLV_HDMIB, PORT_B); - has_edp = intel_dp_is_edp(dev_priv, PORT_C); + has_edp = intel_dp_is_port_edp(dev_priv, PORT_C); has_port = intel_bios_is_port_present(dev_priv, PORT_C); if (I915_READ(VLV_DP_C) & DP_DETECTED || has_port) has_edp &= intel_dp_init(dev_priv, VLV_DP_C, PORT_C); @@ -15030,7 +15042,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) for_each_intel_crtc(dev, crtc) { struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); - int pixclk = 0; + int min_cdclk = 0; memset(&crtc->base.mode, 0, sizeof(crtc->base.mode)); if (crtc_state->base.active) { @@ -15051,22 +15063,18 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) intel_crtc_compute_pixel_rate(crtc_state); - if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv) || - IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) - pixclk = crtc_state->pixel_rate; - else - WARN_ON(dev_priv->display.modeset_calc_cdclk); - - /* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */ - if (IS_BROADWELL(dev_priv) && crtc_state->ips_enabled) - pixclk = DIV_ROUND_UP(pixclk * 100, 95); + if (dev_priv->display.modeset_calc_cdclk) { + min_cdclk = intel_crtc_compute_min_cdclk(crtc_state); + if (WARN_ON(min_cdclk < 0)) + min_cdclk = 0; + } drm_calc_timestamping_constants(&crtc->base, &crtc_state->base.adjusted_mode); update_scanline_offset(crtc); } - dev_priv->min_pixclk[crtc->pipe] = pixclk; + dev_priv->min_cdclk[crtc->pipe] = min_cdclk; intel_pipe_config_sanity_check(dev_priv, crtc_state); } diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 6413494..887953c 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -103,13 +103,13 @@ static const int cnl_rates[] = { 162000, 216000, 270000, static const int default_rates[] = { 162000, 270000, 540000 }; /** - * is_edp - is the given port attached to an eDP panel (either CPU or PCH) + * intel_dp_is_edp - is the given port attached to an eDP panel (either CPU or PCH) * @intel_dp: DP struct * * If a CPU or PCH DP output is attached to an eDP panel, this function * will return true, and false otherwise. */ -static bool is_edp(struct intel_dp *intel_dp) +bool intel_dp_is_edp(struct intel_dp *intel_dp) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); @@ -388,7 +388,7 @@ intel_dp_mode_valid(struct drm_connector *connector, max_dotclk = intel_dp_downstream_max_dotclock(intel_dp); - if (is_edp(intel_dp) && fixed_mode) { + if (intel_dp_is_edp(intel_dp) && fixed_mode) { if (mode->hdisplay > fixed_mode->hdisplay) return MODE_PANEL; @@ -597,7 +597,7 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp) lockdep_assert_held(&dev_priv->pps_mutex); /* We should never land here with regular DP ports */ - WARN_ON(!is_edp(intel_dp)); + WARN_ON(!intel_dp_is_edp(intel_dp)); WARN_ON(intel_dp->active_pipe != INVALID_PIPE && intel_dp->active_pipe != intel_dp->pps_pipe); @@ -644,7 +644,7 @@ bxt_power_sequencer_idx(struct intel_dp *intel_dp) lockdep_assert_held(&dev_priv->pps_mutex); /* We should never land here with regular DP ports */ - WARN_ON(!is_edp(intel_dp)); + WARN_ON(!intel_dp_is_edp(intel_dp)); /* * TODO: BXT has 2 PPS instances. The correct port->PPS instance @@ -847,7 +847,7 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code, struct drm_device *dev = intel_dp_to_dev(intel_dp); struct drm_i915_private *dev_priv = to_i915(dev); - if (!is_edp(intel_dp) || code != SYS_RESTART) + if (!intel_dp_is_edp(intel_dp) || code != SYS_RESTART) return 0; pps_lock(intel_dp); @@ -907,7 +907,7 @@ intel_dp_check_edp(struct intel_dp *intel_dp) struct drm_device *dev = intel_dp_to_dev(intel_dp); struct drm_i915_private *dev_priv = to_i915(dev); - if (!is_edp(intel_dp)) + if (!intel_dp_is_edp(intel_dp)) return; if (!edp_have_panel_power(intel_dp) && !edp_have_panel_vdd(intel_dp)) { @@ -1681,7 +1681,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, else pipe_config->has_audio = intel_conn_state->force_audio == HDMI_AUDIO_ON; - if (is_edp(intel_dp) && intel_connector->panel.fixed_mode) { + if (intel_dp_is_edp(intel_dp) && intel_connector->panel.fixed_mode) { struct drm_display_mode *panel_mode = intel_connector->panel.alt_fixed_mode; struct drm_display_mode *req_mode = &pipe_config->base.mode; @@ -1736,7 +1736,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, /* Walk through all bpp values. Luckily they're all nicely spaced with 2 * bpc in between. */ bpp = intel_dp_compute_bpp(intel_dp, pipe_config); - if (is_edp(intel_dp)) { + if (intel_dp_is_edp(intel_dp)) { /* Get bpp from vbt only for panels that dont have bpp in edid */ if (intel_connector->base.display_info.bpc == 0 && @@ -1829,7 +1829,7 @@ found: * DPLL0 VCO may need to be adjusted to get the correct * clock for eDP. This will affect cdclk as well. */ - if (is_edp(intel_dp) && IS_GEN9_BC(dev_priv)) { + if (intel_dp_is_edp(intel_dp) && IS_GEN9_BC(dev_priv)) { int vco; switch (pipe_config->port_clock / 2) { @@ -1861,7 +1861,7 @@ void intel_dp_set_link_params(struct intel_dp *intel_dp, } static void intel_dp_prepare(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config) + const struct intel_crtc_state *pipe_config) { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); @@ -2069,7 +2069,7 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp) lockdep_assert_held(&dev_priv->pps_mutex); - if (!is_edp(intel_dp)) + if (!intel_dp_is_edp(intel_dp)) return false; cancel_delayed_work(&intel_dp->panel_vdd_work); @@ -2119,7 +2119,7 @@ void intel_edp_panel_vdd_on(struct intel_dp *intel_dp) { bool vdd; - if (!is_edp(intel_dp)) + if (!intel_dp_is_edp(intel_dp)) return; pps_lock(intel_dp); @@ -2203,7 +2203,7 @@ static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync) lockdep_assert_held(&dev_priv->pps_mutex); - if (!is_edp(intel_dp)) + if (!intel_dp_is_edp(intel_dp)) return; I915_STATE_WARN(!intel_dp->want_panel_vdd, "eDP port %c VDD not forced on", @@ -2226,7 +2226,7 @@ static void edp_panel_on(struct intel_dp *intel_dp) lockdep_assert_held(&dev_priv->pps_mutex); - if (!is_edp(intel_dp)) + if (!intel_dp_is_edp(intel_dp)) return; DRM_DEBUG_KMS("Turn eDP port %c panel power on\n", @@ -2267,7 +2267,7 @@ static void edp_panel_on(struct intel_dp *intel_dp) void intel_edp_panel_on(struct intel_dp *intel_dp) { - if (!is_edp(intel_dp)) + if (!intel_dp_is_edp(intel_dp)) return; pps_lock(intel_dp); @@ -2285,7 +2285,7 @@ static void edp_panel_off(struct intel_dp *intel_dp) lockdep_assert_held(&dev_priv->pps_mutex); - if (!is_edp(intel_dp)) + if (!intel_dp_is_edp(intel_dp)) return; DRM_DEBUG_KMS("Turn eDP port %c panel power off\n", @@ -2316,7 +2316,7 @@ static void edp_panel_off(struct intel_dp *intel_dp) void intel_edp_panel_off(struct intel_dp *intel_dp) { - if (!is_edp(intel_dp)) + if (!intel_dp_is_edp(intel_dp)) return; pps_lock(intel_dp); @@ -2360,7 +2360,7 @@ void intel_edp_backlight_on(const struct intel_crtc_state *crtc_state, { struct intel_dp *intel_dp = enc_to_intel_dp(conn_state->best_encoder); - if (!is_edp(intel_dp)) + if (!intel_dp_is_edp(intel_dp)) return; DRM_DEBUG_KMS("\n"); @@ -2377,7 +2377,7 @@ static void _intel_edp_backlight_off(struct intel_dp *intel_dp) u32 pp; i915_reg_t pp_ctrl_reg; - if (!is_edp(intel_dp)) + if (!intel_dp_is_edp(intel_dp)) return; pps_lock(intel_dp); @@ -2401,7 +2401,7 @@ void intel_edp_backlight_off(const struct drm_connector_state *old_conn_state) { struct intel_dp *intel_dp = enc_to_intel_dp(old_conn_state->best_encoder); - if (!is_edp(intel_dp)) + if (!intel_dp_is_edp(intel_dp)) return; DRM_DEBUG_KMS("\n"); @@ -2461,7 +2461,7 @@ static void assert_edp_pll(struct drm_i915_private *dev_priv, bool state) #define assert_edp_pll_disabled(d) assert_edp_pll((d), false) static void ironlake_edp_pll_on(struct intel_dp *intel_dp, - struct intel_crtc_state *pipe_config) + const struct intel_crtc_state *pipe_config) { struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); @@ -2666,7 +2666,7 @@ static void intel_dp_get_config(struct intel_encoder *encoder, intel_dotclock_calculate(pipe_config->port_clock, &pipe_config->dp_m_n); - if (is_edp(intel_dp) && dev_priv->vbt.edp.bpp && + if (intel_dp_is_edp(intel_dp) && dev_priv->vbt.edp.bpp && pipe_config->pipe_bpp > dev_priv->vbt.edp.bpp) { /* * This is a big fat ugly hack. @@ -2688,8 +2688,8 @@ static void intel_dp_get_config(struct intel_encoder *encoder, } static void intel_disable_dp(struct intel_encoder *encoder, - struct intel_crtc_state *old_crtc_state, - struct drm_connector_state *old_conn_state) + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) { struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); @@ -2698,7 +2698,7 @@ static void intel_disable_dp(struct intel_encoder *encoder, intel_audio_codec_disable(encoder); if (HAS_PSR(dev_priv) && !HAS_DDI(dev_priv)) - intel_psr_disable(intel_dp); + intel_psr_disable(intel_dp, old_crtc_state); /* Make sure the panel is off before trying to change the mode. But also * ensure that we have vdd while we switch off the panel. */ @@ -2713,8 +2713,8 @@ static void intel_disable_dp(struct intel_encoder *encoder, } static void ilk_post_disable_dp(struct intel_encoder *encoder, - struct intel_crtc_state *old_crtc_state, - struct drm_connector_state *old_conn_state) + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) { struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); enum port port = dp_to_dig_port(intel_dp)->port; @@ -2727,8 +2727,8 @@ static void ilk_post_disable_dp(struct intel_encoder *encoder, } static void vlv_post_disable_dp(struct intel_encoder *encoder, - struct intel_crtc_state *old_crtc_state, - struct drm_connector_state *old_conn_state) + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) { struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); @@ -2736,8 +2736,8 @@ static void vlv_post_disable_dp(struct intel_encoder *encoder, } static void chv_post_disable_dp(struct intel_encoder *encoder, - struct intel_crtc_state *old_crtc_state, - struct drm_connector_state *old_conn_state) + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) { struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); struct drm_device *dev = encoder->base.dev; @@ -2842,7 +2842,7 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp, } static void intel_dp_enable_port(struct intel_dp *intel_dp, - struct intel_crtc_state *old_crtc_state) + const struct intel_crtc_state *old_crtc_state) { struct drm_device *dev = intel_dp_to_dev(intel_dp); struct drm_i915_private *dev_priv = to_i915(dev); @@ -2866,8 +2866,8 @@ static void intel_dp_enable_port(struct intel_dp *intel_dp, } static void intel_enable_dp(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); struct drm_device *dev = encoder->base.dev; @@ -2914,26 +2914,26 @@ static void intel_enable_dp(struct intel_encoder *encoder, } static void g4x_enable_dp(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { intel_enable_dp(encoder, pipe_config, conn_state); intel_edp_backlight_on(pipe_config, conn_state); } static void vlv_enable_dp(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); intel_edp_backlight_on(pipe_config, conn_state); - intel_psr_enable(intel_dp); + intel_psr_enable(intel_dp, pipe_config); } static void g4x_pre_enable_dp(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); enum port port = dp_to_dig_port(intel_dp)->port; @@ -3040,7 +3040,7 @@ static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp) intel_dp->active_pipe = crtc->pipe; - if (!is_edp(intel_dp)) + if (!intel_dp_is_edp(intel_dp)) return; /* now it's all ours */ @@ -3055,8 +3055,8 @@ static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp) } static void vlv_pre_enable_dp(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { vlv_phy_pre_encoder_enable(encoder); @@ -3064,8 +3064,8 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder, } static void vlv_dp_pre_pll_enable(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { intel_dp_prepare(encoder, pipe_config); @@ -3073,8 +3073,8 @@ static void vlv_dp_pre_pll_enable(struct intel_encoder *encoder, } static void chv_pre_enable_dp(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { chv_phy_pre_encoder_enable(encoder); @@ -3085,8 +3085,8 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder, } static void chv_dp_pre_pll_enable(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { intel_dp_prepare(encoder, pipe_config); @@ -3094,8 +3094,8 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder, } static void chv_dp_post_pll_disable(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { chv_phy_post_pll_disable(encoder); } @@ -3506,13 +3506,11 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp) uint32_t signal_levels, mask = 0; uint8_t train_set = intel_dp->train_set[0]; - if (HAS_DDI(dev_priv)) { + if (IS_GEN9_LP(dev_priv) || IS_CANNONLAKE(dev_priv)) { + signal_levels = bxt_signal_levels(intel_dp); + } else if (HAS_DDI(dev_priv)) { signal_levels = ddi_signal_levels(intel_dp); - - if (IS_GEN9_LP(dev_priv) || IS_CANNONLAKE(dev_priv)) - signal_levels = 0; - else - mask = DDI_BUF_EMP_MASK; + mask = DDI_BUF_EMP_MASK; } else if (IS_CHERRYVIEW(dev_priv)) { signal_levels = chv_signal_levels(intel_dp); } else if (IS_VALLEYVIEW(dev_priv)) { @@ -3784,7 +3782,7 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) return false; /* Don't clobber cached eDP rates. */ - if (!is_edp(intel_dp)) { + if (!intel_dp_is_edp(intel_dp)) { intel_dp_set_sink_rates(intel_dp); intel_dp_set_common_rates(intel_dp); } @@ -3806,7 +3804,7 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) * downstream port information. So, an early return here saves * time from performing other operations which are not required. */ - if (!is_edp(intel_dp) && !intel_dp->sink_count) + if (!intel_dp_is_edp(intel_dp) && !intel_dp->sink_count) return false; if (!drm_dp_is_branch(intel_dp->dpcd)) @@ -4396,7 +4394,7 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp) if (!intel_dp_get_dpcd(intel_dp)) return connector_status_disconnected; - if (is_edp(intel_dp)) + if (intel_dp_is_edp(intel_dp)) return connector_status_connected; /* if there's no downstream port, we're done */ @@ -4712,7 +4710,7 @@ intel_dp_long_pulse(struct intel_connector *intel_connector) intel_display_power_get(to_i915(dev), intel_dp->aux_power_domain); /* Can't disconnect eDP, but you can close the lid... */ - if (is_edp(intel_dp)) + if (intel_dp_is_edp(intel_dp)) status = edp_detect(intel_dp); else if (intel_digital_port_connected(to_i915(dev), dp_to_dig_port(intel_dp))) @@ -4792,7 +4790,7 @@ intel_dp_long_pulse(struct intel_connector *intel_connector) intel_dp->aux.i2c_defer_count = 0; intel_dp_set_edid(intel_dp); - if (is_edp(intel_dp) || intel_connector->detect_edid) + if (intel_dp_is_edp(intel_dp) || intel_connector->detect_edid) status = connector_status_connected; intel_dp->detect_done = true; @@ -4876,7 +4874,7 @@ static int intel_dp_get_modes(struct drm_connector *connector) } /* if eDP has no EDID, fall back to fixed mode */ - if (is_edp(intel_attached_dp(connector)) && + if (intel_dp_is_edp(intel_attached_dp(connector)) && intel_connector->panel.fixed_mode) { struct drm_display_mode *mode; @@ -4927,8 +4925,10 @@ intel_dp_connector_destroy(struct drm_connector *connector) if (!IS_ERR_OR_NULL(intel_connector->edid)) kfree(intel_connector->edid); - /* Can't call is_edp() since the encoder may have been destroyed - * already. */ + /* + * Can't call intel_dp_is_edp() since the encoder may have been + * destroyed already. + */ if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) intel_panel_fini(&intel_connector->panel); @@ -4942,7 +4942,7 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder) struct intel_dp *intel_dp = &intel_dig_port->dp; intel_dp_mst_encoder_cleanup(intel_dig_port); - if (is_edp(intel_dp)) { + if (intel_dp_is_edp(intel_dp)) { cancel_delayed_work_sync(&intel_dp->panel_vdd_work); /* * vdd might still be enabled do to the delayed vdd off. @@ -4968,7 +4968,7 @@ void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder) { struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base); - if (!is_edp(intel_dp)) + if (!intel_dp_is_edp(intel_dp)) return; /* @@ -5036,7 +5036,7 @@ void intel_dp_encoder_reset(struct drm_encoder *encoder) if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) intel_dp->active_pipe = vlv_active_pipe(intel_dp); - if (is_edp(intel_dp)) { + if (intel_dp_is_edp(intel_dp)) { /* Reinit the power sequencer, in case BIOS did something with it. */ intel_dp_pps_init(encoder->dev, intel_dp); intel_edp_panel_vdd_sanitize(intel_dp); @@ -5137,7 +5137,7 @@ put_power: } /* check the VBT to see whether the eDP is on another port */ -bool intel_dp_is_edp(struct drm_i915_private *dev_priv, enum port port) +bool intel_dp_is_port_edp(struct drm_i915_private *dev_priv, enum port port) { /* * eDP not supported on g4x. so bail out early just @@ -5160,7 +5160,7 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect intel_attach_force_audio_property(connector); intel_attach_broadcast_rgb_property(connector); - if (is_edp(intel_dp)) { + if (intel_dp_is_edp(intel_dp)) { u32 allowed_scalers; allowed_scalers = BIT(DRM_MODE_SCALE_ASPECT) | BIT(DRM_MODE_SCALE_FULLSCREEN); @@ -5448,7 +5448,7 @@ static void intel_dp_pps_init(struct drm_device *dev, * The caller of this function needs to take a lock on dev_priv->drrs. */ static void intel_dp_set_drrs_state(struct drm_i915_private *dev_priv, - struct intel_crtc_state *crtc_state, + const struct intel_crtc_state *crtc_state, int refresh_rate) { struct intel_encoder *encoder; @@ -5545,7 +5545,7 @@ static void intel_dp_set_drrs_state(struct drm_i915_private *dev_priv, * Initializes frontbuffer_bits and drrs.dp */ void intel_edp_drrs_enable(struct intel_dp *intel_dp, - struct intel_crtc_state *crtc_state) + const struct intel_crtc_state *crtc_state) { struct drm_device *dev = intel_dp_to_dev(intel_dp); struct drm_i915_private *dev_priv = to_i915(dev); @@ -5576,7 +5576,7 @@ unlock: * */ void intel_edp_drrs_disable(struct intel_dp *intel_dp, - struct intel_crtc_state *old_crtc_state) + const struct intel_crtc_state *old_crtc_state) { struct drm_device *dev = intel_dp_to_dev(intel_dp); struct drm_i915_private *dev_priv = to_i915(dev); @@ -5826,7 +5826,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, struct edid *edid; enum pipe pipe = INVALID_PIPE; - if (!is_edp(intel_dp)) + if (!intel_dp_is_edp(intel_dp)) return true; /* @@ -6042,7 +6042,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, intel_dp->DP = I915_READ(intel_dp->output_reg); intel_dp->attached_connector = intel_connector; - if (intel_dp_is_edp(dev_priv, port)) + if (intel_dp_is_port_edp(dev_priv, port)) type = DRM_MODE_CONNECTOR_eDP; else type = DRM_MODE_CONNECTOR_DisplayPort; @@ -6060,7 +6060,8 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, /* eDP only on port B and/or C on vlv/chv */ if (WARN_ON((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && - is_edp(intel_dp) && port != PORT_B && port != PORT_C)) + intel_dp_is_edp(intel_dp) && + port != PORT_B && port != PORT_C)) return false; DRM_DEBUG_KMS("Adding %s connector on port %c\n", @@ -6088,7 +6089,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, intel_connector->get_hw_state = intel_connector_get_hw_state; /* init MST on ports that can support it */ - if (HAS_DP_MST(dev_priv) && !is_edp(intel_dp) && + if (HAS_DP_MST(dev_priv) && !intel_dp_is_edp(intel_dp) && (port == PORT_B || port == PORT_C || port == PORT_D)) intel_dp_mst_encoder_init(intel_dig_port, intel_connector->base.base.id); @@ -6186,6 +6187,9 @@ bool intel_dp_init(struct drm_i915_private *dev_priv, intel_dig_port->hpd_pulse = intel_dp_hpd_pulse; dev_priv->hotplug.irq_port[port] = intel_dig_port; + if (port != PORT_A) + intel_infoframe_init(intel_dig_port); + if (!intel_dp_init_connector(intel_dig_port, intel_connector)) goto err_init_connector; diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 93fc8ab..8e3aad0 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -123,8 +123,8 @@ static int intel_dp_mst_atomic_check(struct drm_connector *connector, } static void intel_mst_disable_dp(struct intel_encoder *encoder, - struct intel_crtc_state *old_crtc_state, - struct drm_connector_state *old_conn_state) + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) { struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base); struct intel_digital_port *intel_dig_port = intel_mst->primary; @@ -146,8 +146,8 @@ static void intel_mst_disable_dp(struct intel_encoder *encoder, } static void intel_mst_post_disable_dp(struct intel_encoder *encoder, - struct intel_crtc_state *old_crtc_state, - struct drm_connector_state *old_conn_state) + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) { struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base); struct intel_digital_port *intel_dig_port = intel_mst->primary; @@ -176,8 +176,8 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder, } static void intel_mst_pre_enable_dp(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base); struct intel_digital_port *intel_dig_port = intel_mst->primary; @@ -219,8 +219,8 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder, } static void intel_mst_enable_dp(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base); struct intel_digital_port *intel_dig_port = intel_mst->primary; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index fa47285..463ed15 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -220,23 +220,23 @@ struct intel_encoder { struct intel_crtc_state *, struct drm_connector_state *); void (*pre_pll_enable)(struct intel_encoder *, - struct intel_crtc_state *, - struct drm_connector_state *); + const struct intel_crtc_state *, + const struct drm_connector_state *); void (*pre_enable)(struct intel_encoder *, - struct intel_crtc_state *, - struct drm_connector_state *); + const struct intel_crtc_state *, + const struct drm_connector_state *); void (*enable)(struct intel_encoder *, - struct intel_crtc_state *, - struct drm_connector_state *); + const struct intel_crtc_state *, + const struct drm_connector_state *); void (*disable)(struct intel_encoder *, - struct intel_crtc_state *, - struct drm_connector_state *); + const struct intel_crtc_state *, + const struct drm_connector_state *); void (*post_disable)(struct intel_encoder *, - struct intel_crtc_state *, - struct drm_connector_state *); + const struct intel_crtc_state *, + const struct drm_connector_state *); void (*post_pll_disable)(struct intel_encoder *, - struct intel_crtc_state *, - struct drm_connector_state *); + const struct intel_crtc_state *, + const struct drm_connector_state *); /* Read out the current hw state of this connector, returning true if * the encoder is active. If the encoder is enabled it also set the pipe * it is connected to in the pipe parameter. */ @@ -384,7 +384,8 @@ struct intel_atomic_state { unsigned int active_pipe_changes; unsigned int active_crtcs; - unsigned int min_pixclk[I915_MAX_PIPES]; + /* minimum acceptable cdclk for each pipe */ + int min_cdclk[I915_MAX_PIPES]; struct intel_shared_dpll_state shared_dpll[I915_NUM_PLLS]; @@ -753,6 +754,7 @@ struct intel_crtc_state { struct intel_link_m_n fdi_m_n; bool ips_enabled; + bool ips_force_disable; bool enable_fbc; @@ -909,16 +911,6 @@ struct intel_hdmi { bool has_audio; bool rgb_quant_range_selectable; struct intel_connector *attached_connector; - void (*write_infoframe)(struct drm_encoder *encoder, - const struct intel_crtc_state *crtc_state, - enum hdmi_infoframe_type type, - const void *frame, ssize_t len); - void (*set_infoframes)(struct drm_encoder *encoder, - bool enable, - const struct intel_crtc_state *crtc_state, - const struct drm_connector_state *conn_state); - bool (*infoframe_enabled)(struct drm_encoder *encoder, - const struct intel_crtc_state *pipe_config); }; struct intel_dp_mst_encoder; @@ -1069,6 +1061,17 @@ struct intel_digital_port { bool release_cl2_override; uint8_t max_lanes; enum intel_display_power_domain ddi_io_power_domain; + + void (*write_infoframe)(struct drm_encoder *encoder, + const struct intel_crtc_state *crtc_state, + enum hdmi_infoframe_type type, + const void *frame, ssize_t len); + void (*set_infoframes)(struct drm_encoder *encoder, + bool enable, + const struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state); + bool (*infoframe_enabled)(struct drm_encoder *encoder, + const struct intel_crtc_state *pipe_config); }; struct intel_dp_mst_encoder { @@ -1189,6 +1192,30 @@ hdmi_to_dig_port(struct intel_hdmi *intel_hdmi) return container_of(intel_hdmi, struct intel_digital_port, hdmi); } +static inline struct intel_plane_state * +intel_atomic_get_new_plane_state(struct intel_atomic_state *state, + struct intel_plane *plane) +{ + return to_intel_plane_state(drm_atomic_get_new_plane_state(&state->base, + &plane->base)); +} + +static inline struct intel_crtc_state * +intel_atomic_get_old_crtc_state(struct intel_atomic_state *state, + struct intel_crtc *crtc) +{ + return to_intel_crtc_state(drm_atomic_get_old_crtc_state(&state->base, + &crtc->base)); +} + +static inline struct intel_crtc_state * +intel_atomic_get_new_crtc_state(struct intel_atomic_state *state, + struct intel_crtc *crtc) +{ + return to_intel_crtc_state(drm_atomic_get_new_crtc_state(&state->base, + &crtc->base)); +} + /* intel_fifo_underrun.c */ bool intel_set_cpu_fifo_underrun_reporting(struct drm_i915_private *dev_priv, enum pipe pipe, bool enable); @@ -1205,11 +1232,8 @@ void intel_check_pch_fifo_underruns(struct drm_i915_private *dev_priv); /* i915_irq.c */ void gen5_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask); void gen5_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask); -void gen6_reset_pm_iir(struct drm_i915_private *dev_priv, u32 mask); void gen6_mask_pm_irq(struct drm_i915_private *dev_priv, u32 mask); void gen6_unmask_pm_irq(struct drm_i915_private *dev_priv, u32 mask); -void gen6_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask); -void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask); void gen6_reset_rps_interrupts(struct drm_i915_private *dev_priv); void gen6_enable_rps_interrupts(struct drm_i915_private *dev_priv); void gen6_disable_rps_interrupts(struct drm_i915_private *dev_priv); @@ -1246,8 +1270,8 @@ void intel_crt_reset(struct drm_encoder *encoder); /* intel_ddi.c */ void intel_ddi_fdi_post_disable(struct intel_encoder *intel_encoder, - struct intel_crtc_state *old_crtc_state, - struct drm_connector_state *old_conn_state); + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state); void hsw_fdi_link_train(struct intel_crtc *crtc, const struct intel_crtc_state *crtc_state); void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port); @@ -1272,6 +1296,7 @@ void intel_ddi_clock_get(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config); void intel_ddi_set_vc_payload_alloc(const struct intel_crtc_state *crtc_state, bool state); +u32 bxt_signal_levels(struct intel_dp *intel_dp); uint32_t ddi_signal_levels(struct intel_dp *intel_dp); u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder); @@ -1290,6 +1315,7 @@ void intel_audio_init(struct drm_i915_private *dev_priv); void intel_audio_deinit(struct drm_i915_private *dev_priv); /* intel_cdclk.c */ +int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state); void skl_init_cdclk(struct drm_i915_private *dev_priv); void skl_uninit_cdclk(struct drm_i915_private *dev_priv); void cnl_init_cdclk(struct drm_i915_private *dev_priv); @@ -1377,7 +1403,7 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv, struct intel_digital_port *dport, unsigned int expected_mask); int intel_get_load_detect_pipe(struct drm_connector *connector, - struct drm_display_mode *mode, + const struct drm_display_mode *mode, struct intel_load_detect_pipe *old, struct drm_modeset_acquire_ctx *ctx); void intel_release_load_detect_pipe(struct drm_connector *connector, @@ -1401,7 +1427,9 @@ int intel_plane_atomic_set_property(struct drm_plane *plane, struct drm_plane_state *state, struct drm_property *property, uint64_t val); -int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, +int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_crtc_state, + struct drm_crtc_state *crtc_state, + const struct intel_plane_state *old_plane_state, struct drm_plane_state *plane_state); void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv, @@ -1499,7 +1527,8 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc); bool intel_dp_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state); -bool intel_dp_is_edp(struct drm_i915_private *dev_priv, enum port port); +bool intel_dp_is_edp(struct intel_dp *intel_dp); +bool intel_dp_is_port_edp(struct drm_i915_private *dev_priv, enum port port); enum irqreturn intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd); void intel_edp_backlight_on(const struct intel_crtc_state *crtc_state, @@ -1518,9 +1547,9 @@ void intel_power_sequencer_reset(struct drm_i915_private *dev_priv); uint32_t intel_dp_pack_aux(const uint8_t *src, int src_bytes); void intel_plane_destroy(struct drm_plane *plane); void intel_edp_drrs_enable(struct intel_dp *intel_dp, - struct intel_crtc_state *crtc_state); + const struct intel_crtc_state *crtc_state); void intel_edp_drrs_disable(struct intel_dp *intel_dp, - struct intel_crtc_state *crtc_state); + const struct intel_crtc_state *crtc_state); void intel_edp_drrs_invalidate(struct drm_i915_private *dev_priv, unsigned int frontbuffer_bits); void intel_edp_drrs_flush(struct drm_i915_private *dev_priv, @@ -1648,6 +1677,7 @@ void intel_hdmi_handle_sink_scrambling(struct intel_encoder *intel_encoder, bool high_tmds_clock_ratio, bool scrambling); void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable); +void intel_infoframe_init(struct intel_digital_port *intel_dig_port); /* intel_lvds.c */ @@ -1719,8 +1749,10 @@ static inline void intel_backlight_device_unregister(struct intel_connector *con /* intel_psr.c */ -void intel_psr_enable(struct intel_dp *intel_dp); -void intel_psr_disable(struct intel_dp *intel_dp); +void intel_psr_enable(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state); +void intel_psr_disable(struct intel_dp *intel_dp, + const struct intel_crtc_state *old_crtc_state); void intel_psr_invalidate(struct drm_i915_private *dev_priv, unsigned frontbuffer_bits); void intel_psr_flush(struct drm_i915_private *dev_priv, @@ -1844,7 +1876,6 @@ void gen6_rps_reset_ei(struct drm_i915_private *dev_priv); void gen6_rps_idle(struct drm_i915_private *dev_priv); void gen6_rps_boost(struct drm_i915_gem_request *rq, struct intel_rps_client *rps); -void intel_queue_rps_boost_for_request(struct drm_i915_gem_request *req); void g4x_wm_get_hw_state(struct drm_device *dev); void vlv_wm_get_hw_state(struct drm_device *dev); void ilk_wm_get_hw_state(struct drm_device *dev); @@ -1884,8 +1915,8 @@ struct intel_plane *intel_sprite_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe, int plane); int intel_sprite_set_colorkey(struct drm_device *dev, void *data, struct drm_file *file_priv); -void intel_pipe_update_start(struct intel_crtc *crtc); -void intel_pipe_update_end(struct intel_crtc *crtc); +void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state); +void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state); /* intel_tv.c */ void intel_tv_init(struct drm_i915_private *dev_priv); @@ -1957,7 +1988,9 @@ struct drm_plane_state *intel_plane_duplicate_state(struct drm_plane *plane); void intel_plane_destroy_state(struct drm_plane *plane, struct drm_plane_state *state); extern const struct drm_plane_helper_funcs intel_plane_helper_funcs; -int intel_plane_atomic_check_with_state(struct intel_crtc_state *crtc_state, +int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_state, + struct intel_crtc_state *crtc_state, + const struct intel_plane_state *old_plane_state, struct intel_plane_state *intel_state); /* intel_color.c */ diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 7442891..fc25d7d 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -731,7 +731,7 @@ static void intel_dsi_port_disable(struct intel_encoder *encoder) } static void intel_dsi_prepare(struct intel_encoder *intel_encoder, - struct intel_crtc_state *pipe_config); + const struct intel_crtc_state *pipe_config); static void intel_dsi_unprepare(struct intel_encoder *encoder); static void intel_dsi_msleep(struct intel_dsi *intel_dsi, int msec) @@ -783,8 +783,8 @@ static void intel_dsi_msleep(struct intel_dsi *intel_dsi, int msec) */ static void intel_dsi_pre_enable(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); @@ -878,8 +878,8 @@ static void intel_dsi_pre_enable(struct intel_encoder *encoder, * the pre_enable hook. */ static void intel_dsi_enable_nop(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { DRM_DEBUG_KMS("\n"); } @@ -889,8 +889,8 @@ static void intel_dsi_enable_nop(struct intel_encoder *encoder, * the post_disable hook. */ static void intel_dsi_disable(struct intel_encoder *encoder, - struct intel_crtc_state *old_crtc_state, - struct drm_connector_state *old_conn_state) + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) { struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); enum port port; @@ -925,8 +925,8 @@ static void intel_dsi_clear_device_ready(struct intel_encoder *encoder) } static void intel_dsi_post_disable(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); @@ -1066,7 +1066,7 @@ out_put_power: } static void bxt_dsi_get_pipe_config(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config) + struct intel_crtc_state *pipe_config) { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); @@ -1370,7 +1370,7 @@ static u32 pixel_format_to_reg(enum mipi_dsi_pixel_format fmt) } static void intel_dsi_prepare(struct intel_encoder *intel_encoder, - struct intel_crtc_state *pipe_config) + const struct intel_crtc_state *pipe_config) { struct drm_encoder *encoder = &intel_encoder->base; struct drm_device *dev = encoder->dev; diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index c0a0272..5c562e1 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -175,8 +175,8 @@ static void intel_dvo_get_config(struct intel_encoder *encoder, } static void intel_disable_dvo(struct intel_encoder *encoder, - struct intel_crtc_state *old_crtc_state, - struct drm_connector_state *old_conn_state) + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dvo *intel_dvo = enc_to_dvo(encoder); @@ -189,8 +189,8 @@ static void intel_disable_dvo(struct intel_encoder *encoder, } static void intel_enable_dvo(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dvo *intel_dvo = enc_to_dvo(encoder); @@ -258,8 +258,8 @@ static bool intel_dvo_compute_config(struct intel_encoder *encoder, } static void intel_dvo_pre_enable(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 9ab5969..b8e9a23 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -1065,6 +1065,51 @@ static int bxt_init_workarounds(struct intel_engine_cs *engine) return 0; } +static int cnl_init_workarounds(struct intel_engine_cs *engine) +{ + struct drm_i915_private *dev_priv = engine->i915; + int ret; + + /* WaDisableI2mCycleOnWRPort: cnl (pre-prod) */ + if (IS_CNL_REVID(dev_priv, CNL_REVID_B0, CNL_REVID_B0)) + WA_SET_BIT(GAMT_CHKN_BIT_REG, + GAMT_CHKN_DISABLE_I2M_CYCLE_ON_WR_PORT); + + /* WaForceContextSaveRestoreNonCoherent:cnl */ + WA_SET_BIT_MASKED(CNL_HDC_CHICKEN0, + HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT); + + /* WaThrottleEUPerfToAvoidTDBackPressure:cnl(pre-prod) */ + if (IS_CNL_REVID(dev_priv, CNL_REVID_B0, CNL_REVID_B0)) + WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, THROTTLE_12_5); + + /* WaDisableReplayBufferBankArbitrationOptimization:cnl */ + WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, + GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); + + /* WaDisableEnhancedSBEVertexCaching:cnl (pre-prod) */ + if (IS_CNL_REVID(dev_priv, 0, CNL_REVID_B0)) + WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, + GEN8_CSC2_SBE_VUE_CACHE_CONSERVATIVE); + + /* WaInPlaceDecompressionHang:cnl */ + WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA, + GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); + + /* WaPushConstantDereferenceHoldDisable:cnl */ + WA_SET_BIT(GEN7_ROW_CHICKEN2, PUSH_CONSTANT_DEREF_DISABLE); + + /* FtrEnableFastAnisoL1BankingFix: cnl */ + WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, CNL_FAST_ANISO_L1_BANKING_FIX); + + /* WaEnablePreemptionGranularityControlByUMD:cnl */ + ret= wa_ring_whitelist_reg(engine, GEN8_CS_CHICKEN1); + if (ret) + return ret; + + return 0; +} + static int kbl_init_workarounds(struct intel_engine_cs *engine) { struct drm_i915_private *dev_priv = engine->i915; @@ -1185,6 +1230,8 @@ int init_workarounds_ring(struct intel_engine_cs *engine) err = glk_init_workarounds(engine); else if (IS_COFFEELAKE(dev_priv)) err = cfl_init_workarounds(engine); + else if (IS_CANNONLAKE(dev_priv)) + err = cnl_init_workarounds(engine); else err = 0; if (err) @@ -1335,6 +1382,21 @@ void intel_engines_mark_idle(struct drm_i915_private *i915) } } +bool intel_engine_can_store_dword(struct intel_engine_cs *engine) +{ + switch (INTEL_GEN(engine->i915)) { + case 2: + return false; /* uses physical not virtual addresses */ + case 3: + /* maybe only uses physical not virtual addresses */ + return !(IS_I915G(engine->i915) || IS_I915GM(engine->i915)); + case 6: + return engine->class != VIDEO_DECODE_CLASS; /* b0rked */ + default: + return true; + } +} + #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) #include "selftests/mock_engine.c" #endif diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 8c8ead2..58a772d 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -291,6 +291,19 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv) u32 dpfc_ctl; int threshold = dev_priv->fbc.threshold; + /* Display WA #0529: skl, kbl, bxt. */ + if (IS_GEN9(dev_priv) && !IS_GEMINILAKE(dev_priv)) { + u32 val = I915_READ(CHICKEN_MISC_4); + + val &= ~(FBC_STRIDE_OVERRIDE | FBC_STRIDE_MASK); + + if (i915_gem_object_get_tiling(params->vma->obj) != + I915_TILING_X) + val |= FBC_STRIDE_OVERRIDE | params->gen9_wa_cfb_stride; + + I915_WRITE(CHICKEN_MISC_4, val); + } + dpfc_ctl = 0; if (IS_IVYBRIDGE(dev_priv)) dpfc_ctl |= IVB_DPFC_CTL_PLANE(params->crtc.plane); @@ -881,6 +894,10 @@ static void intel_fbc_get_reg_params(struct intel_crtc *crtc, params->fb.stride = cache->fb.stride; params->cfb_size = intel_fbc_calculate_cfb_size(dev_priv, cache); + + if (IS_GEN9(dev_priv) && !IS_GEMINILAKE(dev_priv)) + params->gen9_wa_cfb_stride = DIV_ROUND_UP(cache->plane.src_w, + 32 * fbc->threshold) * 8; } static bool intel_fbc_reg_params_equal(struct intel_fbc_reg_params *params1, diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index 262e75c..f2bb811 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -206,6 +206,7 @@ static int intelfb_create(struct drm_fb_helper *helper, } mutex_lock(&dev->struct_mutex); + intel_runtime_pm_get(dev_priv); /* Pin the GGTT vma for our access via info->screen_base. * This also validates that any existing fb inherited from the @@ -269,6 +270,7 @@ static int intelfb_create(struct drm_fb_helper *helper, fb->width, fb->height, i915_ggtt_offset(vma)); ifbdev->vma = vma; + intel_runtime_pm_put(dev_priv); mutex_unlock(&dev->struct_mutex); vga_switcheroo_client_fb_set(pdev, info); return 0; @@ -276,6 +278,7 @@ static int intelfb_create(struct drm_fb_helper *helper, out_unpin: intel_unpin_fb_vma(vma); out_unlock: + intel_runtime_pm_put(dev_priv); mutex_unlock(&dev->struct_mutex); return ret; } diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index e8abea7..e6f8f30 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -434,7 +434,7 @@ static void intel_write_infoframe(struct drm_encoder *encoder, const struct intel_crtc_state *crtc_state, union hdmi_infoframe *frame) { - struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); + struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); uint8_t buffer[VIDEO_DIP_DATA_SIZE]; ssize_t len; @@ -450,7 +450,7 @@ static void intel_write_infoframe(struct drm_encoder *encoder, buffer[3] = 0; len++; - intel_hdmi->write_infoframe(encoder, crtc_state, frame->any.type, buffer, len); + intel_dig_port->write_infoframe(encoder, crtc_state, frame->any.type, buffer, len); } static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, @@ -945,6 +945,7 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) { struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); + struct intel_digital_port *intel_dig_port = hdmi_to_dig_port(intel_hdmi); struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); u32 tmp, flags = 0; @@ -965,7 +966,7 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder, if (tmp & HDMI_MODE_SELECT_HDMI) pipe_config->has_hdmi_sink = true; - if (intel_hdmi->infoframe_enabled(&encoder->base, pipe_config)) + if (intel_dig_port->infoframe_enabled(&encoder->base, pipe_config)) pipe_config->has_infoframe = true; if (tmp & SDVO_AUDIO_ENABLE) @@ -991,8 +992,8 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder, } static void intel_enable_hdmi_audio(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); @@ -1003,8 +1004,8 @@ static void intel_enable_hdmi_audio(struct intel_encoder *encoder, } static void g4x_enable_hdmi(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); @@ -1025,8 +1026,8 @@ static void g4x_enable_hdmi(struct intel_encoder *encoder, } static void ibx_enable_hdmi(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); @@ -1075,8 +1076,8 @@ static void ibx_enable_hdmi(struct intel_encoder *encoder, } static void cpt_enable_hdmi(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); @@ -1130,18 +1131,20 @@ static void cpt_enable_hdmi(struct intel_encoder *encoder, } static void vlv_enable_hdmi(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { } static void intel_disable_hdmi(struct intel_encoder *encoder, - struct intel_crtc_state *old_crtc_state, - struct drm_connector_state *old_conn_state) + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); + struct intel_digital_port *intel_dig_port = + hdmi_to_dig_port(intel_hdmi); struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); u32 temp; @@ -1184,14 +1187,15 @@ static void intel_disable_hdmi(struct intel_encoder *encoder, intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true); } - intel_hdmi->set_infoframes(&encoder->base, false, old_crtc_state, old_conn_state); + intel_dig_port->set_infoframes(&encoder->base, false, + old_crtc_state, old_conn_state); intel_dp_dual_mode_set_tmds_output(intel_hdmi, false); } static void g4x_disable_hdmi(struct intel_encoder *encoder, - struct intel_crtc_state *old_crtc_state, - struct drm_connector_state *old_conn_state) + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) { if (old_crtc_state->has_audio) intel_audio_codec_disable(encoder); @@ -1200,16 +1204,16 @@ static void g4x_disable_hdmi(struct intel_encoder *encoder, } static void pch_disable_hdmi(struct intel_encoder *encoder, - struct intel_crtc_state *old_crtc_state, - struct drm_connector_state *old_conn_state) + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) { if (old_crtc_state->has_audio) intel_audio_codec_disable(encoder); } static void pch_post_disable_hdmi(struct intel_encoder *encoder, - struct intel_crtc_state *old_crtc_state, - struct drm_connector_state *old_conn_state) + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) { intel_disable_hdmi(encoder, old_crtc_state, old_conn_state); } @@ -1314,7 +1318,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector, return status; } -static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state) +static bool hdmi_12bpc_possible(const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); @@ -1642,24 +1646,24 @@ static int intel_hdmi_get_modes(struct drm_connector *connector) } static void intel_hdmi_pre_enable(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { - struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); + struct intel_digital_port *intel_dig_port = + enc_to_dig_port(&encoder->base); intel_hdmi_prepare(encoder, pipe_config); - intel_hdmi->set_infoframes(&encoder->base, - pipe_config->has_hdmi_sink, - pipe_config, conn_state); + intel_dig_port->set_infoframes(&encoder->base, + pipe_config->has_infoframe, + pipe_config, conn_state); } static void vlv_hdmi_pre_enable(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); - struct intel_hdmi *intel_hdmi = &dport->hdmi; struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); @@ -1669,9 +1673,9 @@ static void vlv_hdmi_pre_enable(struct intel_encoder *encoder, vlv_set_phy_signal_level(encoder, 0x2b245f5f, 0x00002000, 0x5578b83a, 0x2b247878); - intel_hdmi->set_infoframes(&encoder->base, - pipe_config->has_hdmi_sink, - pipe_config, conn_state); + dport->set_infoframes(&encoder->base, + pipe_config->has_infoframe, + pipe_config, conn_state); g4x_enable_hdmi(encoder, pipe_config, conn_state); @@ -1679,8 +1683,8 @@ static void vlv_hdmi_pre_enable(struct intel_encoder *encoder, } static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { intel_hdmi_prepare(encoder, pipe_config); @@ -1688,8 +1692,8 @@ static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder, } static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { intel_hdmi_prepare(encoder, pipe_config); @@ -1697,23 +1701,23 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder, } static void chv_hdmi_post_pll_disable(struct intel_encoder *encoder, - struct intel_crtc_state *old_crtc_state, - struct drm_connector_state *old_conn_state) + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) { chv_phy_post_pll_disable(encoder); } static void vlv_hdmi_post_disable(struct intel_encoder *encoder, - struct intel_crtc_state *old_crtc_state, - struct drm_connector_state *old_conn_state) + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) { /* Reset lanes to avoid HDMI flicker (VLV w/a) */ vlv_phy_reset_lanes(encoder); } static void chv_hdmi_post_disable(struct intel_encoder *encoder, - struct intel_crtc_state *old_crtc_state, - struct drm_connector_state *old_conn_state) + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); @@ -1727,11 +1731,10 @@ static void chv_hdmi_post_disable(struct intel_encoder *encoder, } static void chv_hdmi_pre_enable(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); - struct intel_hdmi *intel_hdmi = &dport->hdmi; struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); @@ -1741,9 +1744,9 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder, /* Use 800mV-0dB */ chv_set_phy_signal_level(encoder, 128, 102, false); - intel_hdmi->set_infoframes(&encoder->base, - pipe_config->has_hdmi_sink, - pipe_config, conn_state); + dport->set_infoframes(&encoder->base, + pipe_config->has_infoframe, + pipe_config, conn_state); g4x_enable_hdmi(encoder, pipe_config, conn_state); @@ -1958,6 +1961,34 @@ static u8 intel_hdmi_ddc_pin(struct drm_i915_private *dev_priv, return ddc_pin; } +void intel_infoframe_init(struct intel_digital_port *intel_dig_port) +{ + struct drm_i915_private *dev_priv = + to_i915(intel_dig_port->base.base.dev); + + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { + intel_dig_port->write_infoframe = vlv_write_infoframe; + intel_dig_port->set_infoframes = vlv_set_infoframes; + intel_dig_port->infoframe_enabled = vlv_infoframe_enabled; + } else if (IS_G4X(dev_priv)) { + intel_dig_port->write_infoframe = g4x_write_infoframe; + intel_dig_port->set_infoframes = g4x_set_infoframes; + intel_dig_port->infoframe_enabled = g4x_infoframe_enabled; + } else if (HAS_DDI(dev_priv)) { + intel_dig_port->write_infoframe = hsw_write_infoframe; + intel_dig_port->set_infoframes = hsw_set_infoframes; + intel_dig_port->infoframe_enabled = hsw_infoframe_enabled; + } else if (HAS_PCH_IBX(dev_priv)) { + intel_dig_port->write_infoframe = ibx_write_infoframe; + intel_dig_port->set_infoframes = ibx_set_infoframes; + intel_dig_port->infoframe_enabled = ibx_infoframe_enabled; + } else { + intel_dig_port->write_infoframe = cpt_write_infoframe; + intel_dig_port->set_infoframes = cpt_set_infoframes; + intel_dig_port->infoframe_enabled = cpt_infoframe_enabled; + } +} + void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, struct intel_connector *intel_connector) { @@ -1993,28 +2024,6 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, return; intel_encoder->hpd_pin = intel_hpd_pin(port); - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { - intel_hdmi->write_infoframe = vlv_write_infoframe; - intel_hdmi->set_infoframes = vlv_set_infoframes; - intel_hdmi->infoframe_enabled = vlv_infoframe_enabled; - } else if (IS_G4X(dev_priv)) { - intel_hdmi->write_infoframe = g4x_write_infoframe; - intel_hdmi->set_infoframes = g4x_set_infoframes; - intel_hdmi->infoframe_enabled = g4x_infoframe_enabled; - } else if (HAS_DDI(dev_priv)) { - intel_hdmi->write_infoframe = hsw_write_infoframe; - intel_hdmi->set_infoframes = hsw_set_infoframes; - intel_hdmi->infoframe_enabled = hsw_infoframe_enabled; - } else if (HAS_PCH_IBX(dev_priv)) { - intel_hdmi->write_infoframe = ibx_write_infoframe; - intel_hdmi->set_infoframes = ibx_set_infoframes; - intel_hdmi->infoframe_enabled = ibx_infoframe_enabled; - } else { - intel_hdmi->write_infoframe = cpt_write_infoframe; - intel_hdmi->set_infoframes = cpt_set_infoframes; - intel_hdmi->infoframe_enabled = cpt_infoframe_enabled; - } - if (HAS_DDI(dev_priv)) intel_connector->get_hw_state = intel_ddi_connector_get_hw_state; else @@ -2113,5 +2122,7 @@ void intel_hdmi_init(struct drm_i915_private *dev_priv, intel_dig_port->dp.output_reg = INVALID_MMIO_REG; intel_dig_port->max_lanes = 4; + intel_infoframe_init(intel_dig_port); + intel_hdmi_init_connector(intel_dig_port, intel_connector); } diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 6f972e6..d89e1b8 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1175,6 +1175,8 @@ static int intel_init_workaround_bb(struct intel_engine_cs *engine) return -EINVAL; switch (INTEL_GEN(engine->i915)) { + case 10: + return 0; case 9: wa_bb_fn[0] = gen9_init_indirectctx_bb; wa_bb_fn[1] = gen9_init_perctx_bb; diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 8e21577..a9813ae 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -229,8 +229,8 @@ static void intel_lvds_pps_init_hw(struct drm_i915_private *dev_priv, } static void intel_pre_enable_lvds(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); @@ -306,8 +306,8 @@ static void intel_pre_enable_lvds(struct intel_encoder *encoder, * Sets the power state for the panel. */ static void intel_enable_lvds(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { struct drm_device *dev = encoder->base.dev; struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); @@ -324,8 +324,8 @@ static void intel_enable_lvds(struct intel_encoder *encoder, } static void intel_disable_lvds(struct intel_encoder *encoder, - struct intel_crtc_state *old_crtc_state, - struct drm_connector_state *old_conn_state) + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) { struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); @@ -339,8 +339,8 @@ static void intel_disable_lvds(struct intel_encoder *encoder, } static void gmch_disable_lvds(struct intel_encoder *encoder, - struct intel_crtc_state *old_crtc_state, - struct drm_connector_state *old_conn_state) + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) { intel_panel_disable_backlight(old_conn_state); @@ -349,15 +349,15 @@ static void gmch_disable_lvds(struct intel_encoder *encoder, } static void pch_disable_lvds(struct intel_encoder *encoder, - struct intel_crtc_state *old_crtc_state, - struct drm_connector_state *old_conn_state) + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) { intel_panel_disable_backlight(old_conn_state); } static void pch_post_disable_lvds(struct intel_encoder *encoder, - struct intel_crtc_state *old_crtc_state, - struct drm_connector_state *old_conn_state) + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) { intel_disable_lvds(encoder, old_crtc_state, old_conn_state); } diff --git a/drivers/gpu/drm/i915/intel_pipe_crc.c b/drivers/gpu/drm/i915/intel_pipe_crc.c index 8fbd2bd..96043a5 100644 --- a/drivers/gpu/drm/i915/intel_pipe_crc.c +++ b/drivers/gpu/drm/i915/intel_pipe_crc.c @@ -506,8 +506,8 @@ static int ilk_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source, return 0; } -static void hsw_trans_edp_pipe_A_crc_wa(struct drm_i915_private *dev_priv, - bool enable) +static void hsw_pipe_A_crc_wa(struct drm_i915_private *dev_priv, + bool enable) { struct drm_device *dev = &dev_priv->drm; struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, PIPE_A); @@ -533,10 +533,24 @@ retry: goto put_state; } - pipe_config->pch_pfit.force_thru = enable; - if (pipe_config->cpu_transcoder == TRANSCODER_EDP && - pipe_config->pch_pfit.enabled != enable) - pipe_config->base.connectors_changed = true; + if (HAS_IPS(dev_priv)) { + /* + * When IPS gets enabled, the pipe CRC changes. Since IPS gets + * enabled and disabled dynamically based on package C states, + * user space can't make reliable use of the CRCs, so let's just + * completely disable it. + */ + pipe_config->ips_force_disable = enable; + if (pipe_config->ips_enabled == enable) + pipe_config->base.connectors_changed = true; + } + + if (IS_HASWELL(dev_priv)) { + pipe_config->pch_pfit.force_thru = enable; + if (pipe_config->cpu_transcoder == TRANSCODER_EDP && + pipe_config->pch_pfit.enabled != enable) + pipe_config->base.connectors_changed = true; + } ret = drm_atomic_commit(state); @@ -570,8 +584,9 @@ static int ivb_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv, *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_SPRITE_IVB; break; case INTEL_PIPE_CRC_SOURCE_PF: - if (IS_HASWELL(dev_priv) && pipe == PIPE_A) - hsw_trans_edp_pipe_A_crc_wa(dev_priv, true); + if ((IS_HASWELL(dev_priv) || + IS_BROADWELL(dev_priv)) && pipe == PIPE_A) + hsw_pipe_A_crc_wa(dev_priv, true); *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PF_IVB; break; @@ -606,7 +621,6 @@ static int pipe_crc_set_source(struct drm_i915_private *dev_priv, enum intel_pipe_crc_source source) { struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; - struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe); enum intel_display_power_domain power_domain; u32 val = 0; /* shut up gcc */ int ret; @@ -643,14 +657,6 @@ static int pipe_crc_set_source(struct drm_i915_private *dev_priv, goto out; } - /* - * When IPS gets enabled, the pipe CRC changes. Since IPS gets - * enabled and disabled dynamically based on package C states, - * user space can't make reliable use of the CRCs, so let's just - * completely disable it. - */ - hsw_disable_ips(crtc); - spin_lock_irq(&pipe_crc->lock); kfree(pipe_crc->entries); pipe_crc->entries = entries; @@ -691,10 +697,9 @@ static int pipe_crc_set_source(struct drm_i915_private *dev_priv, g4x_undo_pipe_scramble_reset(dev_priv, pipe); else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) vlv_undo_pipe_scramble_reset(dev_priv, pipe); - else if (IS_HASWELL(dev_priv) && pipe == PIPE_A) - hsw_trans_edp_pipe_A_crc_wa(dev_priv, false); - - hsw_enable_ips(crtc); + else if ((IS_HASWELL(dev_priv) || + IS_BROADWELL(dev_priv)) && pipe == PIPE_A) + hsw_pipe_A_crc_wa(dev_priv, false); } ret = 0; @@ -914,7 +919,6 @@ int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name, { struct drm_i915_private *dev_priv = crtc->dev->dev_private; struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[crtc->index]; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); enum intel_display_power_domain power_domain; enum intel_pipe_crc_source source; u32 val = 0; /* shut up gcc */ @@ -935,16 +939,6 @@ int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name, if (ret != 0) goto out; - if (source) { - /* - * When IPS gets enabled, the pipe CRC changes. Since IPS gets - * enabled and disabled dynamically based on package C states, - * user space can't make reliable use of the CRCs, so let's just - * completely disable it. - */ - hsw_disable_ips(intel_crtc); - } - I915_WRITE(PIPE_CRC_CTL(crtc->index), val); POSTING_READ(PIPE_CRC_CTL(crtc->index)); @@ -953,10 +947,9 @@ int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name, g4x_undo_pipe_scramble_reset(dev_priv, crtc->index); else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) vlv_undo_pipe_scramble_reset(dev_priv, crtc->index); - else if (IS_HASWELL(dev_priv) && crtc->index == PIPE_A) - hsw_trans_edp_pipe_A_crc_wa(dev_priv, false); - - hsw_enable_ips(intel_crtc); + else if ((IS_HASWELL(dev_priv) || + IS_BROADWELL(dev_priv)) && crtc->index == PIPE_A) + hsw_pipe_A_crc_wa(dev_priv, false); } pipe_crc->skipped = 0; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index ed66293..0201816 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -125,6 +125,7 @@ static void bxt_init_clock_gating(struct drm_i915_private *dev_priv) static void glk_init_clock_gating(struct drm_i915_private *dev_priv) { + u32 val; gen9_init_clock_gating(dev_priv); /* @@ -144,6 +145,11 @@ static void glk_init_clock_gating(struct drm_i915_private *dev_priv) I915_WRITE(CHICKEN_MISC_2, val); } + /* Display WA #1133: WaFbcSkipSegments:glk */ + val = I915_READ(ILK_DPFC_CHICKEN); + val &= ~GLK_SKIP_SEG_COUNT_MASK; + val |= GLK_SKIP_SEG_EN | GLK_SKIP_SEG_COUNT(1); + I915_WRITE(ILK_DPFC_CHICKEN, val); } static void i915_pineview_get_mem_freq(struct drm_i915_private *dev_priv) @@ -1322,21 +1328,21 @@ static int g4x_compute_pipe_wm(struct intel_crtc_state *crtc_state) int num_active_planes = hweight32(crtc_state->active_planes & ~BIT(PLANE_CURSOR)); const struct g4x_pipe_wm *raw; - struct intel_plane_state *plane_state; + const struct intel_plane_state *old_plane_state; + const struct intel_plane_state *new_plane_state; struct intel_plane *plane; enum plane_id plane_id; int i, level; unsigned int dirty = 0; - for_each_intel_plane_in_state(state, plane, plane_state, i) { - const struct intel_plane_state *old_plane_state = - to_intel_plane_state(plane->base.state); - - if (plane_state->base.crtc != &crtc->base && + for_each_oldnew_intel_plane_in_state(state, plane, + old_plane_state, + new_plane_state, i) { + if (new_plane_state->base.crtc != &crtc->base && old_plane_state->base.crtc != &crtc->base) continue; - if (g4x_raw_plane_wm_compute(crtc_state, plane_state)) + if (g4x_raw_plane_wm_compute(crtc_state, new_plane_state)) dirty |= BIT(plane->id); } @@ -1831,21 +1837,21 @@ static int vlv_compute_pipe_wm(struct intel_crtc_state *crtc_state) int num_active_planes = hweight32(crtc_state->active_planes & ~BIT(PLANE_CURSOR)); bool needs_modeset = drm_atomic_crtc_needs_modeset(&crtc_state->base); - struct intel_plane_state *plane_state; + const struct intel_plane_state *old_plane_state; + const struct intel_plane_state *new_plane_state; struct intel_plane *plane; enum plane_id plane_id; int level, ret, i; unsigned int dirty = 0; - for_each_intel_plane_in_state(state, plane, plane_state, i) { - const struct intel_plane_state *old_plane_state = - to_intel_plane_state(plane->base.state); - - if (plane_state->base.crtc != &crtc->base && + for_each_oldnew_intel_plane_in_state(state, plane, + old_plane_state, + new_plane_state, i) { + if (new_plane_state->base.crtc != &crtc->base && old_plane_state->base.crtc != &crtc->base) continue; - if (vlv_raw_plane_wm_compute(crtc_state, plane_state)) + if (vlv_raw_plane_wm_compute(crtc_state, new_plane_state)) dirty |= BIT(plane->id); } @@ -1864,7 +1870,7 @@ static int vlv_compute_pipe_wm(struct intel_crtc_state *crtc_state) /* cursor changes don't warrant a FIFO recompute */ if (dirty & ~BIT(PLANE_CURSOR)) { const struct intel_crtc_state *old_crtc_state = - to_intel_crtc_state(crtc->base.state); + intel_atomic_get_old_crtc_state(state, crtc); const struct vlv_fifo_state *old_fifo_state = &old_crtc_state->wm.vlv.fifo_state; @@ -6169,6 +6175,7 @@ void gen6_rps_boost(struct drm_i915_gem_request *rq, struct intel_rps_client *rps) { struct drm_i915_private *i915 = rq->i915; + unsigned long flags; bool boost; /* This is intentionally racy! We peek at the state here, then @@ -6178,13 +6185,13 @@ void gen6_rps_boost(struct drm_i915_gem_request *rq, return; boost = false; - spin_lock_irq(&rq->lock); + spin_lock_irqsave(&rq->lock, flags); if (!rq->waitboost && !i915_gem_request_completed(rq)) { atomic_inc(&i915->rps.num_waiters); rq->waitboost = true; boost = true; } - spin_unlock_irq(&rq->lock); + spin_unlock_irqrestore(&rq->lock, flags); if (!boost) return; @@ -7980,7 +7987,7 @@ static void ilk_init_lp_watermarks(struct drm_i915_private *dev_priv) */ } -static void ironlake_init_clock_gating(struct drm_i915_private *dev_priv) +static void ilk_init_clock_gating(struct drm_i915_private *dev_priv) { uint32_t dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE; @@ -8263,7 +8270,56 @@ static void gen8_set_l3sqc_credits(struct drm_i915_private *dev_priv, I915_WRITE(GEN7_MISCCPCTL, misccpctl); } -static void kabylake_init_clock_gating(struct drm_i915_private *dev_priv) +static void cnp_init_clock_gating(struct drm_i915_private *dev_priv) +{ + if (!HAS_PCH_CNP(dev_priv)) + return; + + /* Wa #1181 */ + I915_WRITE(SOUTH_DSPCLK_GATE_D, CNP_PWM_CGE_GATING_DISABLE); +} + +static void cnl_init_clock_gating(struct drm_i915_private *dev_priv) +{ + u32 val; + cnp_init_clock_gating(dev_priv); + + /* This is not an Wa. Enable for better image quality */ + I915_WRITE(_3D_CHICKEN3, + _MASKED_BIT_ENABLE(_3D_CHICKEN3_AA_LINE_QUALITY_FIX_ENABLE)); + + /* WaEnableChickenDCPR:cnl */ + I915_WRITE(GEN8_CHICKEN_DCPR_1, + I915_READ(GEN8_CHICKEN_DCPR_1) | MASK_WAKEMEM); + + /* WaFbcWakeMemOn:cnl */ + I915_WRITE(DISP_ARB_CTL, I915_READ(DISP_ARB_CTL) | + DISP_FBC_MEMORY_WAKE); + + /* WaSarbUnitClockGatingDisable:cnl (pre-prod) */ + if (IS_CNL_REVID(dev_priv, CNL_REVID_A0, CNL_REVID_B0)) + I915_WRITE(SLICE_UNIT_LEVEL_CLKGATE, + I915_READ(SLICE_UNIT_LEVEL_CLKGATE) | + SARBUNIT_CLKGATE_DIS); + + /* Display WA #1133: WaFbcSkipSegments:cnl */ + val = I915_READ(ILK_DPFC_CHICKEN); + val &= ~GLK_SKIP_SEG_COUNT_MASK; + val |= GLK_SKIP_SEG_EN | GLK_SKIP_SEG_COUNT(1); + I915_WRITE(ILK_DPFC_CHICKEN, val); +} + +static void cfl_init_clock_gating(struct drm_i915_private *dev_priv) +{ + cnp_init_clock_gating(dev_priv); + gen9_init_clock_gating(dev_priv); + + /* WaFbcNukeOnHostModify:cfl */ + I915_WRITE(ILK_DPFC_CHICKEN, I915_READ(ILK_DPFC_CHICKEN) | + ILK_DPFC_NUKE_ON_ANY_MODIFICATION); +} + +static void kbl_init_clock_gating(struct drm_i915_private *dev_priv) { gen9_init_clock_gating(dev_priv); @@ -8277,12 +8333,12 @@ static void kabylake_init_clock_gating(struct drm_i915_private *dev_priv) I915_WRITE(GEN6_UCGCTL1, I915_READ(GEN6_UCGCTL1) | GEN6_GAMUNIT_CLOCK_GATE_DISABLE); - /* WaFbcNukeOnHostModify:kbl,cfl */ + /* WaFbcNukeOnHostModify:kbl */ I915_WRITE(ILK_DPFC_CHICKEN, I915_READ(ILK_DPFC_CHICKEN) | ILK_DPFC_NUKE_ON_ANY_MODIFICATION); } -static void skylake_init_clock_gating(struct drm_i915_private *dev_priv) +static void skl_init_clock_gating(struct drm_i915_private *dev_priv) { gen9_init_clock_gating(dev_priv); @@ -8295,7 +8351,7 @@ static void skylake_init_clock_gating(struct drm_i915_private *dev_priv) ILK_DPFC_NUKE_ON_ANY_MODIFICATION); } -static void broadwell_init_clock_gating(struct drm_i915_private *dev_priv) +static void bdw_init_clock_gating(struct drm_i915_private *dev_priv) { enum pipe pipe; @@ -8353,7 +8409,7 @@ static void broadwell_init_clock_gating(struct drm_i915_private *dev_priv) I915_READ(GEN6_UCGCTL1) | GEN6_EU_TCUNIT_CLOCK_GATE_DISABLE); } -static void haswell_init_clock_gating(struct drm_i915_private *dev_priv) +static void hsw_init_clock_gating(struct drm_i915_private *dev_priv) { ilk_init_lp_watermarks(dev_priv); @@ -8407,7 +8463,7 @@ static void haswell_init_clock_gating(struct drm_i915_private *dev_priv) lpt_init_clock_gating(dev_priv); } -static void ivybridge_init_clock_gating(struct drm_i915_private *dev_priv) +static void ivb_init_clock_gating(struct drm_i915_private *dev_priv) { uint32_t snpcr; @@ -8504,7 +8560,7 @@ static void ivybridge_init_clock_gating(struct drm_i915_private *dev_priv) gen6_check_mch_setup(dev_priv); } -static void valleyview_init_clock_gating(struct drm_i915_private *dev_priv) +static void vlv_init_clock_gating(struct drm_i915_private *dev_priv) { /* WaDisableEarlyCull:vlv */ I915_WRITE(_3D_CHICKEN3, @@ -8584,7 +8640,7 @@ static void valleyview_init_clock_gating(struct drm_i915_private *dev_priv) I915_WRITE(VLV_GUNIT_CLOCK_GATE, GCFG_DIS); } -static void cherryview_init_clock_gating(struct drm_i915_private *dev_priv) +static void chv_init_clock_gating(struct drm_i915_private *dev_priv) { /* WaVSRefCountFullforceMissDisable:chv */ /* WaDSRefCountFullforceMissDisable:chv */ @@ -8644,7 +8700,7 @@ static void g4x_init_clock_gating(struct drm_i915_private *dev_priv) g4x_disable_trickle_feed(dev_priv); } -static void crestline_init_clock_gating(struct drm_i915_private *dev_priv) +static void i965gm_init_clock_gating(struct drm_i915_private *dev_priv) { I915_WRITE(RENCLK_GATE_D1, I965_RCC_CLOCK_GATE_DISABLE); I915_WRITE(RENCLK_GATE_D2, 0); @@ -8658,7 +8714,7 @@ static void crestline_init_clock_gating(struct drm_i915_private *dev_priv) I915_WRITE(CACHE_MODE_0, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE)); } -static void broadwater_init_clock_gating(struct drm_i915_private *dev_priv) +static void i965g_init_clock_gating(struct drm_i915_private *dev_priv) { I915_WRITE(RENCLK_GATE_D1, I965_RCZ_CLOCK_GATE_DISABLE | I965_RCC_CLOCK_GATE_DISABLE | @@ -8743,34 +8799,38 @@ static void nop_init_clock_gating(struct drm_i915_private *dev_priv) */ void intel_init_clock_gating_hooks(struct drm_i915_private *dev_priv) { - if (IS_SKYLAKE(dev_priv)) - dev_priv->display.init_clock_gating = skylake_init_clock_gating; - else if (IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) - dev_priv->display.init_clock_gating = kabylake_init_clock_gating; + if (IS_CANNONLAKE(dev_priv)) + dev_priv->display.init_clock_gating = cnl_init_clock_gating; + else if (IS_COFFEELAKE(dev_priv)) + dev_priv->display.init_clock_gating = cfl_init_clock_gating; + else if (IS_SKYLAKE(dev_priv)) + dev_priv->display.init_clock_gating = skl_init_clock_gating; + else if (IS_KABYLAKE(dev_priv)) + dev_priv->display.init_clock_gating = kbl_init_clock_gating; else if (IS_BROXTON(dev_priv)) dev_priv->display.init_clock_gating = bxt_init_clock_gating; else if (IS_GEMINILAKE(dev_priv)) dev_priv->display.init_clock_gating = glk_init_clock_gating; else if (IS_BROADWELL(dev_priv)) - dev_priv->display.init_clock_gating = broadwell_init_clock_gating; + dev_priv->display.init_clock_gating = bdw_init_clock_gating; else if (IS_CHERRYVIEW(dev_priv)) - dev_priv->display.init_clock_gating = cherryview_init_clock_gating; + dev_priv->display.init_clock_gating = chv_init_clock_gating; else if (IS_HASWELL(dev_priv)) - dev_priv->display.init_clock_gating = haswell_init_clock_gating; + dev_priv->display.init_clock_gating = hsw_init_clock_gating; else if (IS_IVYBRIDGE(dev_priv)) - dev_priv->display.init_clock_gating = ivybridge_init_clock_gating; + dev_priv->display.init_clock_gating = ivb_init_clock_gating; else if (IS_VALLEYVIEW(dev_priv)) - dev_priv->display.init_clock_gating = valleyview_init_clock_gating; + dev_priv->display.init_clock_gating = vlv_init_clock_gating; else if (IS_GEN6(dev_priv)) dev_priv->display.init_clock_gating = gen6_init_clock_gating; else if (IS_GEN5(dev_priv)) - dev_priv->display.init_clock_gating = ironlake_init_clock_gating; + dev_priv->display.init_clock_gating = ilk_init_clock_gating; else if (IS_G4X(dev_priv)) dev_priv->display.init_clock_gating = g4x_init_clock_gating; else if (IS_I965GM(dev_priv)) - dev_priv->display.init_clock_gating = crestline_init_clock_gating; + dev_priv->display.init_clock_gating = i965gm_init_clock_gating; else if (IS_I965G(dev_priv)) - dev_priv->display.init_clock_gating = broadwater_init_clock_gating; + dev_priv->display.init_clock_gating = i965g_init_clock_gating; else if (IS_GEN3(dev_priv)) dev_priv->display.init_clock_gating = gen3_init_clock_gating; else if (IS_I85X(dev_priv) || IS_I865G(dev_priv)) @@ -9132,43 +9192,6 @@ int intel_freq_opcode(struct drm_i915_private *dev_priv, int val) return DIV_ROUND_CLOSEST(val, GT_FREQUENCY_MULTIPLIER); } -struct request_boost { - struct work_struct work; - struct drm_i915_gem_request *req; -}; - -static void __intel_rps_boost_work(struct work_struct *work) -{ - struct request_boost *boost = container_of(work, struct request_boost, work); - struct drm_i915_gem_request *req = boost->req; - - if (!i915_gem_request_completed(req)) - gen6_rps_boost(req, NULL); - - i915_gem_request_put(req); - kfree(boost); -} - -void intel_queue_rps_boost_for_request(struct drm_i915_gem_request *req) -{ - struct request_boost *boost; - - if (req == NULL || INTEL_GEN(req->i915) < 6) - return; - - if (i915_gem_request_completed(req)) - return; - - boost = kmalloc(sizeof(*boost), GFP_ATOMIC); - if (boost == NULL) - return; - - boost->req = i915_gem_request_get(req); - - INIT_WORK(&boost->work, __intel_rps_boost_work); - queue_work(req->i915->wq, &boost->work); -} - void intel_pm_setup(struct drm_i915_private *dev_priv) { mutex_init(&dev_priv->rps.hw_lock); diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 1b31ab0..f62ab05 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -103,28 +103,26 @@ static void intel_psr_write_vsc(struct intel_dp *intel_dp, POSTING_READ(ctl_reg); } -static void vlv_psr_setup_vsc(struct intel_dp *intel_dp) +static void vlv_psr_setup_vsc(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) { - struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); - struct drm_device *dev = intel_dig_port->base.base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct drm_crtc *crtc = intel_dig_port->base.base.crtc; - enum pipe pipe = to_intel_crtc(crtc)->pipe; + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); uint32_t val; /* VLV auto-generate VSC package as per EDP 1.3 spec, Table 3.10 */ - val = I915_READ(VLV_VSCSDP(pipe)); + val = I915_READ(VLV_VSCSDP(crtc->pipe)); val &= ~VLV_EDP_PSR_SDP_FREQ_MASK; val |= VLV_EDP_PSR_SDP_FREQ_EVFRAME; - I915_WRITE(VLV_VSCSDP(pipe), val); + I915_WRITE(VLV_VSCSDP(crtc->pipe), val); } -static void skl_psr_setup_su_vsc(struct intel_dp *intel_dp) +static void skl_psr_setup_su_vsc(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) { - struct edp_vsc_psr psr_vsc; struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); - struct drm_device *dev = intel_dig_port->base.base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev); + struct edp_vsc_psr psr_vsc; /* Prepare VSC Header for SU as per EDP 1.4 spec, Table 6.11 */ memset(&psr_vsc, 0, sizeof(psr_vsc)); @@ -145,7 +143,8 @@ static void skl_psr_setup_su_vsc(struct intel_dp *intel_dp) intel_psr_write_vsc(intel_dp, &psr_vsc); } -static void hsw_psr_setup_vsc(struct intel_dp *intel_dp) +static void hsw_psr_setup_vsc(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) { struct edp_vsc_psr psr_vsc; @@ -233,16 +232,15 @@ static void hsw_psr_enable_sink(struct intel_dp *intel_dp) I915_WRITE(aux_ctl_reg, aux_ctl); } -static void vlv_psr_enable_source(struct intel_dp *intel_dp) +static void vlv_psr_enable_source(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - struct drm_device *dev = dig_port->base.base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct drm_crtc *crtc = dig_port->base.base.crtc; - enum pipe pipe = to_intel_crtc(crtc)->pipe; + struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); /* Transition from PSR_state 0 to PSR_state 1, i.e. PSR Inactive */ - I915_WRITE(VLV_PSRCTL(pipe), + I915_WRITE(VLV_PSRCTL(crtc->pipe), VLV_EDP_PSR_MODE_SW_TIMER | VLV_EDP_PSR_SRC_TRANSMITTER_STATE | VLV_EDP_PSR_ENABLE); @@ -485,16 +483,17 @@ static void intel_psr_activate(struct intel_dp *intel_dp) /** * intel_psr_enable - Enable PSR * @intel_dp: Intel DP + * @crtc_state: new CRTC state * * This function can only be called after the pipe is fully trained and enabled. */ -void intel_psr_enable(struct intel_dp *intel_dp) +void intel_psr_enable(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = intel_dig_port->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *crtc = to_intel_crtc(intel_dig_port->base.base.crtc); - enum transcoder cpu_transcoder = crtc->config->cpu_transcoder; + enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; u32 chicken; if (!HAS_PSR(dev_priv)) { @@ -520,11 +519,13 @@ void intel_psr_enable(struct intel_dp *intel_dp) if (HAS_DDI(dev_priv)) { if (dev_priv->psr.psr2_support) { - skl_psr_setup_su_vsc(intel_dp); + skl_psr_setup_su_vsc(intel_dp, crtc_state); + chicken = PSR2_VSC_ENABLE_PROG_HEADER; if (dev_priv->psr.y_cord_support) chicken |= PSR2_ADD_VERTICAL_LINE_COUNT; I915_WRITE(CHICKEN_TRANS(cpu_transcoder), chicken); + I915_WRITE(EDP_PSR_DEBUG_CTL, EDP_PSR_DEBUG_MASK_MEMUP | EDP_PSR_DEBUG_MASK_HPD | @@ -533,7 +534,8 @@ void intel_psr_enable(struct intel_dp *intel_dp) EDP_PSR_DEBUG_MASK_DISP_REG_WRITE); } else { /* set up vsc header for psr1 */ - hsw_psr_setup_vsc(intel_dp); + hsw_psr_setup_vsc(intel_dp, crtc_state); + /* * Per Spec: Avoid continuous PSR exit by masking MEMUP * and HPD. also mask LPSP to avoid dependency on other @@ -553,7 +555,7 @@ void intel_psr_enable(struct intel_dp *intel_dp) if (INTEL_GEN(dev_priv) >= 9) intel_psr_activate(intel_dp); } else { - vlv_psr_setup_vsc(intel_dp); + vlv_psr_setup_vsc(intel_dp, crtc_state); /* Enable PSR on the panel */ vlv_psr_enable_sink(intel_dp); @@ -564,7 +566,7 @@ void intel_psr_enable(struct intel_dp *intel_dp) * but let it on inactive state. So we might do this prior * to active transition, i.e. here. */ - vlv_psr_enable_source(intel_dp); + vlv_psr_enable_source(intel_dp, crtc_state); } /* @@ -585,37 +587,38 @@ unlock: mutex_unlock(&dev_priv->psr.lock); } -static void vlv_psr_disable(struct intel_dp *intel_dp) +static void vlv_psr_disable(struct intel_dp *intel_dp, + const struct intel_crtc_state *old_crtc_state) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = intel_dig_port->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *intel_crtc = - to_intel_crtc(intel_dig_port->base.base.crtc); + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); uint32_t val; if (dev_priv->psr.active) { /* Put VLV PSR back to PSR_state 0 that is PSR Disabled. */ if (intel_wait_for_register(dev_priv, - VLV_PSRSTAT(intel_crtc->pipe), + VLV_PSRSTAT(crtc->pipe), VLV_EDP_PSR_IN_TRANS, 0, 1)) WARN(1, "PSR transition took longer than expected\n"); - val = I915_READ(VLV_PSRCTL(intel_crtc->pipe)); + val = I915_READ(VLV_PSRCTL(crtc->pipe)); val &= ~VLV_EDP_PSR_ACTIVE_ENTRY; val &= ~VLV_EDP_PSR_ENABLE; val &= ~VLV_EDP_PSR_MODE_MASK; - I915_WRITE(VLV_PSRCTL(intel_crtc->pipe), val); + I915_WRITE(VLV_PSRCTL(crtc->pipe), val); dev_priv->psr.active = false; } else { - WARN_ON(vlv_is_psr_active_on_pipe(dev, intel_crtc->pipe)); + WARN_ON(vlv_is_psr_active_on_pipe(dev, crtc->pipe)); } } -static void hsw_psr_disable(struct intel_dp *intel_dp) +static void hsw_psr_disable(struct intel_dp *intel_dp, + const struct intel_crtc_state *old_crtc_state) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = intel_dig_port->base.base.dev; @@ -664,10 +667,12 @@ static void hsw_psr_disable(struct intel_dp *intel_dp) /** * intel_psr_disable - Disable PSR * @intel_dp: Intel DP + * @old_crtc_state: old CRTC state * * This function needs to be called before disabling pipe. */ -void intel_psr_disable(struct intel_dp *intel_dp) +void intel_psr_disable(struct intel_dp *intel_dp, + const struct intel_crtc_state *old_crtc_state) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = intel_dig_port->base.base.dev; @@ -681,9 +686,9 @@ void intel_psr_disable(struct intel_dp *intel_dp) /* Disable PSR on Source */ if (HAS_DDI(dev_priv)) - hsw_psr_disable(intel_dp); + hsw_psr_disable(intel_dp, old_crtc_state); else - vlv_psr_disable(intel_dp); + vlv_psr_disable(intel_dp, old_crtc_state); /* Disable PSR on Sink */ drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 02d8974..79c0021 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -735,16 +735,6 @@ bool intel_engines_are_idle(struct drm_i915_private *dev_priv); void intel_engines_mark_idle(struct drm_i915_private *i915); void intel_engines_reset_default_submission(struct drm_i915_private *i915); -static inline bool -__intel_engine_can_store_dword(unsigned int gen, unsigned int class) -{ - if (gen <= 2) - return false; /* uses physical not virtual addresses */ - - if (gen == 6 && class == VIDEO_DECODE_CLASS) - return false; /* b0rked */ - - return true; -} +bool intel_engine_can_store_dword(struct intel_engine_cs *engine); #endif /* _INTEL_RINGBUFFER_H_ */ diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index b66d8e1..a3bfb9f 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -2707,30 +2707,67 @@ void bxt_display_core_uninit(struct drm_i915_private *dev_priv) usleep_range(10, 30); /* 10 us delay per Bspec */ } -#define CNL_PROCMON_IDX(val) \ - (((val) & (PROCESS_INFO_MASK | VOLTAGE_INFO_MASK)) >> VOLTAGE_INFO_SHIFT) -#define NUM_CNL_PROCMON \ - (CNL_PROCMON_IDX(VOLTAGE_INFO_MASK | PROCESS_INFO_MASK) + 1) +enum { + PROCMON_0_85V_DOT_0, + PROCMON_0_95V_DOT_0, + PROCMON_0_95V_DOT_1, + PROCMON_1_05V_DOT_0, + PROCMON_1_05V_DOT_1, +}; static const struct cnl_procmon { u32 dw1, dw9, dw10; -} cnl_procmon_values[NUM_CNL_PROCMON] = { - [CNL_PROCMON_IDX(VOLTAGE_INFO_0_85V | PROCESS_INFO_DOT_0)] = - { .dw1 = 0x00 << 16, .dw9 = 0x62AB67BB, .dw10 = 0x51914F96, }, - [CNL_PROCMON_IDX(VOLTAGE_INFO_0_95V | PROCESS_INFO_DOT_0)] = - { .dw1 = 0x00 << 16, .dw9 = 0x86E172C7, .dw10 = 0x77CA5EAB, }, - [CNL_PROCMON_IDX(VOLTAGE_INFO_0_95V | PROCESS_INFO_DOT_1)] = - { .dw1 = 0x00 << 16, .dw9 = 0x93F87FE1, .dw10 = 0x8AE871C5, }, - [CNL_PROCMON_IDX(VOLTAGE_INFO_1_05V | PROCESS_INFO_DOT_0)] = - { .dw1 = 0x00 << 16, .dw9 = 0x98FA82DD, .dw10 = 0x89E46DC1, }, - [CNL_PROCMON_IDX(VOLTAGE_INFO_1_05V | PROCESS_INFO_DOT_1)] = - { .dw1 = 0x44 << 16, .dw9 = 0x9A00AB25, .dw10 = 0x8AE38FF1, }, +} cnl_procmon_values[] = { + [PROCMON_0_85V_DOT_0] = + { .dw1 = 0x00000000, .dw9 = 0x62AB67BB, .dw10 = 0x51914F96, }, + [PROCMON_0_95V_DOT_0] = + { .dw1 = 0x00000000, .dw9 = 0x86E172C7, .dw10 = 0x77CA5EAB, }, + [PROCMON_0_95V_DOT_1] = + { .dw1 = 0x00000000, .dw9 = 0x93F87FE1, .dw10 = 0x8AE871C5, }, + [PROCMON_1_05V_DOT_0] = + { .dw1 = 0x00000000, .dw9 = 0x98FA82DD, .dw10 = 0x89E46DC1, }, + [PROCMON_1_05V_DOT_1] = + { .dw1 = 0x00440000, .dw9 = 0x9A00AB25, .dw10 = 0x8AE38FF1, }, }; +static void cnl_set_procmon_ref_values(struct drm_i915_private *dev_priv) +{ + const struct cnl_procmon *procmon; + u32 val; + + val = I915_READ(CNL_PORT_COMP_DW3); + switch (val & (PROCESS_INFO_MASK | VOLTAGE_INFO_MASK)) { + default: + MISSING_CASE(val); + case VOLTAGE_INFO_0_85V | PROCESS_INFO_DOT_0: + procmon = &cnl_procmon_values[PROCMON_0_85V_DOT_0]; + break; + case VOLTAGE_INFO_0_95V | PROCESS_INFO_DOT_0: + procmon = &cnl_procmon_values[PROCMON_0_95V_DOT_0]; + break; + case VOLTAGE_INFO_0_95V | PROCESS_INFO_DOT_1: + procmon = &cnl_procmon_values[PROCMON_0_95V_DOT_1]; + break; + case VOLTAGE_INFO_1_05V | PROCESS_INFO_DOT_0: + procmon = &cnl_procmon_values[PROCMON_1_05V_DOT_0]; + break; + case VOLTAGE_INFO_1_05V | PROCESS_INFO_DOT_1: + procmon = &cnl_procmon_values[PROCMON_1_05V_DOT_1]; + break; + } + + val = I915_READ(CNL_PORT_COMP_DW1); + val &= ~((0xff << 16) | 0xff); + val |= procmon->dw1; + I915_WRITE(CNL_PORT_COMP_DW1, val); + + I915_WRITE(CNL_PORT_COMP_DW9, procmon->dw9); + I915_WRITE(CNL_PORT_COMP_DW10, procmon->dw10); +} + static void cnl_display_core_init(struct drm_i915_private *dev_priv, bool resume) { struct i915_power_domains *power_domains = &dev_priv->power_domains; - const struct cnl_procmon *procmon; struct i915_power_well *well; u32 val; @@ -2746,18 +2783,7 @@ static void cnl_display_core_init(struct drm_i915_private *dev_priv, bool resume val &= ~CNL_COMP_PWR_DOWN; I915_WRITE(CHICKEN_MISC_2, val); - val = I915_READ(CNL_PORT_COMP_DW3); - procmon = &cnl_procmon_values[CNL_PROCMON_IDX(val)]; - - WARN_ON(procmon->dw10 == 0); - - val = I915_READ(CNL_PORT_COMP_DW1); - val &= ~((0xff << 16) | 0xff); - val |= procmon->dw1; - I915_WRITE(CNL_PORT_COMP_DW1, val); - - I915_WRITE(CNL_PORT_COMP_DW9, procmon->dw9); - I915_WRITE(CNL_PORT_COMP_DW10, procmon->dw10); + cnl_set_procmon_ref_values(dev_priv); val = I915_READ(CNL_PORT_COMP_DW0); val |= COMP_INIT; @@ -2784,9 +2810,6 @@ static void cnl_display_core_init(struct drm_i915_private *dev_priv, bool resume gen9_dbuf_enable(dev_priv); } -#undef CNL_PROCMON_IDX -#undef NUM_CNL_PROCMON - static void cnl_display_core_uninit(struct drm_i915_private *dev_priv) { struct i915_power_domains *power_domains = &dev_priv->power_domains; diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 29a3b0f..7437944 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -201,11 +201,8 @@ to_intel_sdvo_connector(struct drm_connector *connector) return container_of(connector, struct intel_sdvo_connector, base.base); } -static struct intel_sdvo_connector_state * -to_intel_sdvo_connector_state(struct drm_connector_state *conn_state) -{ - return container_of(conn_state, struct intel_sdvo_connector_state, base.base); -} +#define to_intel_sdvo_connector_state(conn_state) \ + container_of((conn_state), struct intel_sdvo_connector_state, base.base) static bool intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, uint16_t flags); @@ -998,7 +995,7 @@ static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo, } static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo, - struct intel_crtc_state *pipe_config) + const struct intel_crtc_state *pipe_config) { uint8_t sdvo_data[HDMI_INFOFRAME_SIZE(AVI)]; union hdmi_infoframe frame; @@ -1032,7 +1029,7 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo, } static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo, - struct drm_connector_state *conn_state) + const struct drm_connector_state *conn_state) { struct intel_sdvo_tv_format format; uint32_t format_map; @@ -1202,9 +1199,9 @@ static bool intel_sdvo_compute_config(struct intel_encoder *encoder, } while (0) static void intel_sdvo_update_props(struct intel_sdvo *intel_sdvo, - struct intel_sdvo_connector_state *sdvo_state) + const struct intel_sdvo_connector_state *sdvo_state) { - struct drm_connector_state *conn_state = &sdvo_state->base.base; + const struct drm_connector_state *conn_state = &sdvo_state->base.base; struct intel_sdvo_connector *intel_sdvo_conn = to_intel_sdvo_connector(conn_state->connector); uint16_t val; @@ -1258,14 +1255,15 @@ static void intel_sdvo_update_props(struct intel_sdvo *intel_sdvo, } static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder, - struct intel_crtc_state *crtc_state, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev); struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); const struct drm_display_mode *adjusted_mode = &crtc_state->base.adjusted_mode; - struct intel_sdvo_connector_state *sdvo_state = to_intel_sdvo_connector_state(conn_state); - struct drm_display_mode *mode = &crtc_state->base.mode; + const struct intel_sdvo_connector_state *sdvo_state = + to_intel_sdvo_connector_state(conn_state); + const struct drm_display_mode *mode = &crtc_state->base.mode; struct intel_sdvo *intel_sdvo = to_sdvo(intel_encoder); u32 sdvox; struct intel_sdvo_in_out_map in_out; @@ -1507,8 +1505,8 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder, } static void intel_disable_sdvo(struct intel_encoder *encoder, - struct intel_crtc_state *old_crtc_state, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_sdvo *intel_sdvo = to_sdvo(encoder); @@ -1552,21 +1550,21 @@ static void intel_disable_sdvo(struct intel_encoder *encoder, } static void pch_disable_sdvo(struct intel_encoder *encoder, - struct intel_crtc_state *old_crtc_state, - struct drm_connector_state *old_conn_state) + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) { } static void pch_post_disable_sdvo(struct intel_encoder *encoder, - struct intel_crtc_state *old_crtc_state, - struct drm_connector_state *old_conn_state) + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) { intel_disable_sdvo(encoder, old_crtc_state, old_conn_state); } static void intel_enable_sdvo(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 524933b..b0d6e3e 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -70,8 +70,7 @@ int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, /** * intel_pipe_update_start() - start update of a set of display registers - * @crtc: the crtc of which the registers are going to be updated - * @start_vbl_count: vblank counter return pointer used for error checking + * @new_crtc_state: the new crtc state * * Mark the start of an update to pipe registers that should be updated * atomically regarding vblank. If the next vblank will happens within @@ -79,18 +78,18 @@ int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, * * After a successful call to this function, interrupts will be disabled * until a subsequent call to intel_pipe_update_end(). That is done to - * avoid random delays. The value written to @start_vbl_count should be - * supplied to intel_pipe_update_end() for error checking. + * avoid random delays. */ -void intel_pipe_update_start(struct intel_crtc *crtc) +void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state) { + struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; + const struct drm_display_mode *adjusted_mode = &new_crtc_state->base.adjusted_mode; long timeout = msecs_to_jiffies_timeout(1); int scanline, min, max, vblank_start; wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base); bool need_vlv_dsi_wa = (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && - intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DSI); + intel_crtc_has_type(new_crtc_state, INTEL_OUTPUT_DSI); DEFINE_WAIT(wait); vblank_start = adjusted_mode->crtc_vblank_start; @@ -170,15 +169,15 @@ void intel_pipe_update_start(struct intel_crtc *crtc) /** * intel_pipe_update_end() - end update of a set of display registers - * @crtc: the crtc of which the registers were updated - * @start_vbl_count: start vblank counter (used for error checking) + * @new_crtc_state: the new crtc state * * Mark the end of an update started with intel_pipe_update_start(). This * re-enables interrupts and verifies the update was actually completed - * before a vblank using the value of @start_vbl_count. + * before a vblank. */ -void intel_pipe_update_end(struct intel_crtc *crtc) +void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state) { + struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc); enum pipe pipe = crtc->pipe; int scanline_end = intel_get_crtc_scanline(crtc); u32 end_vbl_count = intel_crtc_get_vblank_counter(crtc); @@ -191,14 +190,14 @@ void intel_pipe_update_end(struct intel_crtc *crtc) * Would be slightly nice to just grab the vblank count and arm the * event outside of the critical section - the spinlock might spin for a * while ... */ - if (crtc->base.state->event) { + if (new_crtc_state->base.event) { WARN_ON(drm_crtc_vblank_get(&crtc->base) != 0); spin_lock(&crtc->base.dev->event_lock); - drm_crtc_arm_vblank_event(&crtc->base, crtc->base.state->event); + drm_crtc_arm_vblank_event(&crtc->base, new_crtc_state->base.event); spin_unlock(&crtc->base.dev->event_lock); - crtc->base.state->event = NULL; + new_crtc_state->base.event = NULL; } local_irq_enable(); diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 906893c..0cc999f 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -814,8 +814,8 @@ intel_tv_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe) static void intel_enable_tv(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); @@ -829,8 +829,8 @@ intel_enable_tv(struct intel_encoder *encoder, static void intel_disable_tv(struct intel_encoder *encoder, - struct intel_crtc_state *old_crtc_state, - struct drm_connector_state *old_conn_state) + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); @@ -838,7 +838,7 @@ intel_disable_tv(struct intel_encoder *encoder, I915_WRITE(TV_CTL, I915_READ(TV_CTL) & ~TV_ENC_ENABLE); } -static const struct tv_mode *intel_tv_mode_find(struct drm_connector_state *conn_state) +static const struct tv_mode *intel_tv_mode_find(const struct drm_connector_state *conn_state) { int format = conn_state->tv.mode; @@ -976,8 +976,8 @@ static void set_color_conversion(struct drm_i915_private *dev_priv, } static void intel_tv_pre_enable(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 1d7b879..0529af7 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -1251,7 +1251,7 @@ static const struct register_whitelist { } whitelist[] = { { .offset_ldw = RING_TIMESTAMP(RENDER_RING_BASE), .offset_udw = RING_TIMESTAMP_UDW(RENDER_RING_BASE), - .size = 8, .gen_bitmask = GEN_RANGE(4, 9) }, + .size = 8, .gen_bitmask = GEN_RANGE(4, 10) }, }; int i915_reg_read_ioctl(struct drm_device *dev, diff --git a/drivers/gpu/drm/i915/intel_vbt_defs.h b/drivers/gpu/drm/i915/intel_vbt_defs.h index a92e776..404569c 100644 --- a/drivers/gpu/drm/i915/intel_vbt_defs.h +++ b/drivers/gpu/drm/i915/intel_vbt_defs.h @@ -149,16 +149,19 @@ struct bdb_general_features { u8 ssc_freq:1; u8 enable_lfp_on_override:1; u8 disable_ssc_ddt:1; - u8 rsvd7:1; + u8 underscan_vga_timings:1; u8 display_clock_mode:1; - u8 rsvd8:1; /* finish byte */ + u8 vbios_hotplug_support:1; /* bits 3 */ u8 disable_smooth_vision:1; u8 single_dvi:1; - u8 rsvd9:1; + u8 rotate_180:1; /* 181 */ u8 fdi_rx_polarity_inverted:1; - u8 rsvd10:4; /* finish byte */ + u8 vbios_extended_mode:1; /* 160 */ + u8 copy_ilfp_dtd_to_sdvo_lvds_dtd:1; /* 160 */ + u8 panel_best_fit_timing:1; /* 160 */ + u8 ignore_strap_state:1; /* 160 */ /* bits 4 */ u8 legacy_monitor_detect; @@ -167,9 +170,10 @@ struct bdb_general_features { u8 int_crt_support:1; u8 int_tv_support:1; u8 int_efp_support:1; - u8 dp_ssc_enb:1; /* PCH attached eDP supports SSC */ + u8 dp_ssc_enable:1; /* PCH attached eDP supports SSC */ u8 dp_ssc_freq:1; /* SSC freq for PCH attached eDP */ - u8 rsvd11:3; /* finish byte */ + u8 dp_ssc_dongle_supported:1; + u8 rsvd11:2; /* finish byte */ } __packed; /* pre-915 */ @@ -206,6 +210,56 @@ struct bdb_general_features { #define DEVICE_TYPE_LFP_LVDS_DUAL 0x5162 #define DEVICE_TYPE_LFP_LVDS_DUAL_HDCP 0x51e2 +/* Add the device class for LFP, TV, HDMI */ +#define DEVICE_TYPE_INT_LFP 0x1022 +#define DEVICE_TYPE_INT_TV 0x1009 +#define DEVICE_TYPE_HDMI 0x60D2 +#define DEVICE_TYPE_DP 0x68C6 +#define DEVICE_TYPE_DP_DUAL_MODE 0x60D6 +#define DEVICE_TYPE_eDP 0x78C6 + +#define DEVICE_TYPE_CLASS_EXTENSION (1 << 15) +#define DEVICE_TYPE_POWER_MANAGEMENT (1 << 14) +#define DEVICE_TYPE_HOTPLUG_SIGNALING (1 << 13) +#define DEVICE_TYPE_INTERNAL_CONNECTOR (1 << 12) +#define DEVICE_TYPE_NOT_HDMI_OUTPUT (1 << 11) +#define DEVICE_TYPE_MIPI_OUTPUT (1 << 10) +#define DEVICE_TYPE_COMPOSITE_OUTPUT (1 << 9) +#define DEVICE_TYPE_DUAL_CHANNEL (1 << 8) +#define DEVICE_TYPE_HIGH_SPEED_LINK (1 << 6) +#define DEVICE_TYPE_LVDS_SINGALING (1 << 5) +#define DEVICE_TYPE_TMDS_DVI_SIGNALING (1 << 4) +#define DEVICE_TYPE_VIDEO_SIGNALING (1 << 3) +#define DEVICE_TYPE_DISPLAYPORT_OUTPUT (1 << 2) +#define DEVICE_TYPE_DIGITAL_OUTPUT (1 << 1) +#define DEVICE_TYPE_ANALOG_OUTPUT (1 << 0) + +/* + * Bits we care about when checking for DEVICE_TYPE_eDP. Depending on the + * system, the other bits may or may not be set for eDP outputs. + */ +#define DEVICE_TYPE_eDP_BITS \ + (DEVICE_TYPE_INTERNAL_CONNECTOR | \ + DEVICE_TYPE_MIPI_OUTPUT | \ + DEVICE_TYPE_COMPOSITE_OUTPUT | \ + DEVICE_TYPE_DUAL_CHANNEL | \ + DEVICE_TYPE_LVDS_SINGALING | \ + DEVICE_TYPE_TMDS_DVI_SIGNALING | \ + DEVICE_TYPE_VIDEO_SIGNALING | \ + DEVICE_TYPE_DISPLAYPORT_OUTPUT | \ + DEVICE_TYPE_ANALOG_OUTPUT) + +#define DEVICE_TYPE_DP_DUAL_MODE_BITS \ + (DEVICE_TYPE_INTERNAL_CONNECTOR | \ + DEVICE_TYPE_MIPI_OUTPUT | \ + DEVICE_TYPE_COMPOSITE_OUTPUT | \ + DEVICE_TYPE_LVDS_SINGALING | \ + DEVICE_TYPE_TMDS_DVI_SIGNALING | \ + DEVICE_TYPE_VIDEO_SIGNALING | \ + DEVICE_TYPE_DISPLAYPORT_OUTPUT | \ + DEVICE_TYPE_DIGITAL_OUTPUT | \ + DEVICE_TYPE_ANALOG_OUTPUT) + #define DEVICE_CFG_NONE 0x00 #define DEVICE_CFG_12BIT_DVOB 0x01 #define DEVICE_CFG_12BIT_DVOC 0x02 @@ -226,77 +280,126 @@ struct bdb_general_features { #define DEVICE_WIRE_DVOB_MASTER 0x0d #define DEVICE_WIRE_DVOC_MASTER 0x0e +/* dvo_port pre BDB 155 */ #define DEVICE_PORT_DVOA 0x00 /* none on 845+ */ #define DEVICE_PORT_DVOB 0x01 #define DEVICE_PORT_DVOC 0x02 +/* dvo_port BDB 155+ */ +#define DVO_PORT_HDMIA 0 +#define DVO_PORT_HDMIB 1 +#define DVO_PORT_HDMIC 2 +#define DVO_PORT_HDMID 3 +#define DVO_PORT_LVDS 4 +#define DVO_PORT_TV 5 +#define DVO_PORT_CRT 6 +#define DVO_PORT_DPB 7 +#define DVO_PORT_DPC 8 +#define DVO_PORT_DPD 9 +#define DVO_PORT_DPA 10 +#define DVO_PORT_DPE 11 /* 193 */ +#define DVO_PORT_HDMIE 12 /* 193 */ +#define DVO_PORT_MIPIA 21 /* 171 */ +#define DVO_PORT_MIPIB 22 /* 171 */ +#define DVO_PORT_MIPIC 23 /* 171 */ +#define DVO_PORT_MIPID 24 /* 171 */ + +#define LEGACY_CHILD_DEVICE_CONFIG_SIZE 33 + /* - * We used to keep this struct but without any version control. We should avoid - * using it in the future, but it should be safe to keep using it in the old - * code. Do not change; we rely on its size. + * The child device config, aka the display device data structure, provides a + * description of a port and its configuration on the platform. + * + * The child device config size has been increased, and fields have been added + * and their meaning has changed over time. Care must be taken when accessing + * basically any of the fields to ensure the correct interpretation for the BDB + * version in question. + * + * When we copy the child device configs to dev_priv->vbt.child_dev, we reserve + * space for the full structure below, and initialize the tail not actually + * present in VBT to zeros. Accessing those fields is fine, as long as the + * default zero is taken into account, again according to the BDB version. + * + * BDB versions 155 and below are considered legacy, and version 155 seems to be + * a baseline for some of the VBT documentation. When adding new fields, please + * include the BDB version when the field was added, if it's above that. */ -struct old_child_dev_config { +struct child_device_config { u16 handle; - u16 device_type; - u8 device_id[10]; /* ascii string */ - u16 addin_offset; - u8 dvo_port; /* See Device_PORT_* above */ - u8 i2c_pin; - u8 slave_addr; - u8 ddc_pin; - u16 edid_ptr; - u8 dvo_cfg; /* See DEVICE_CFG_* above */ - u8 dvo2_port; - u8 i2c2_pin; - u8 slave2_addr; - u8 ddc2_pin; - u8 capabilities; - u8 dvo_wiring;/* See DEVICE_WIRE_* above */ - u8 dvo2_wiring; - u16 extended_type; - u8 dvo_function; -} __packed; + u16 device_type; /* See DEVICE_TYPE_* above */ + + union { + u8 device_id[10]; /* ascii string */ + struct { + u8 i2c_speed; + u8 dp_onboard_redriver; /* 158 */ + u8 dp_ondock_redriver; /* 158 */ + u8 hdmi_level_shifter_value:4; /* 169 */ + u8 hdmi_max_data_rate:4; /* 204 */ + u16 dtd_buf_ptr; /* 161 */ + u8 edidless_efp:1; /* 161 */ + u8 compression_enable:1; /* 198 */ + u8 compression_method:1; /* 198 */ + u8 ganged_edp:1; /* 202 */ + u8 reserved0:4; + u8 compression_structure_index:4; /* 198 */ + u8 reserved1:4; + u8 slave_port; /* 202 */ + u8 reserved2; + } __packed; + } __packed; -/* This one contains field offsets that are known to be common for all BDB - * versions. Notice that the meaning of the contents contents may still change, - * but at least the offsets are consistent. */ - -struct common_child_dev_config { - u16 handle; - u16 device_type; - u8 not_common1[12]; - u8 dvo_port; - u8 not_common2[2]; + u16 addin_offset; + u8 dvo_port; /* See DEVICE_PORT_* and DVO_PORT_* above */ + u8 i2c_pin; + u8 slave_addr; u8 ddc_pin; u16 edid_ptr; u8 dvo_cfg; /* See DEVICE_CFG_* above */ - u8 efp_routed:1; - u8 lane_reversal:1; - u8 lspcon:1; - u8 iboost:1; - u8 hpd_invert:1; - u8 flag_reserved:3; - u8 hdmi_support:1; - u8 dp_support:1; - u8 tmds_support:1; - u8 support_reserved:5; - u8 aux_channel; - u8 not_common3[11]; - u8 iboost_level; -} __packed; + union { + struct { + u8 dvo2_port; + u8 i2c2_pin; + u8 slave2_addr; + u8 ddc2_pin; + } __packed; + struct { + u8 efp_routed:1; /* 158 */ + u8 lane_reversal:1; /* 184 */ + u8 lspcon:1; /* 192 */ + u8 iboost:1; /* 196 */ + u8 hpd_invert:1; /* 196 */ + u8 flag_reserved:3; + u8 hdmi_support:1; /* 158 */ + u8 dp_support:1; /* 158 */ + u8 tmds_support:1; /* 158 */ + u8 support_reserved:5; + u8 aux_channel; + u8 dongle_detect; + } __packed; + } __packed; + + u8 pipe_cap:2; + u8 sdvo_stall:1; /* 158 */ + u8 hpd_status:2; + u8 integrated_encoder:1; + u8 capabilities_reserved:2; + u8 dvo_wiring; /* See DEVICE_WIRE_* above */ + + union { + u8 dvo2_wiring; + u8 mipi_bridge_type; /* 171 */ + } __packed; -/* This field changes depending on the BDB version, so the most reliable way to - * read it is by checking the BDB version and reading the raw pointer. */ -union child_device_config { - /* This one is safe to be used anywhere, but the code should still check - * the BDB version. */ - u8 raw[33]; - /* This one should only be kept for legacy code. */ - struct old_child_dev_config old; - /* This one should also be safe to use anywhere, even without version - * checks. */ - struct common_child_dev_config common; + u16 extended_type; + u8 dvo_function; + u8 dp_usb_type_c:1; /* 195 */ + u8 flags2_reserved:7; /* 195 */ + u8 dp_gpio_index; /* 195 */ + u16 dp_gpio_pin_num; /* 195 */ + u8 dp_iboost_level:4; /* 196 */ + u8 hdmi_iboost_level:4; /* 196 */ } __packed; struct bdb_general_definitions { @@ -585,23 +688,38 @@ struct bdb_driver_features { #define EDP_VSWING_1_2V 3 -struct edp_link_params { +struct edp_fast_link_params { u8 rate:4; u8 lanes:4; u8 preemphasis:4; u8 vswing:4; } __packed; +struct edp_pwm_delays { + u16 pwm_on_to_backlight_enable; + u16 backlight_disable_to_pwm_off; +} __packed; + +struct edp_full_link_params { + u8 preemphasis:4; + u8 vswing:4; +} __packed; + struct bdb_edp { struct edp_power_seq power_seqs[16]; u32 color_depth; - struct edp_link_params link_params[16]; + struct edp_fast_link_params fast_link_params[16]; u32 sdrrs_msa_timing_delay; /* ith bit indicates enabled/disabled for (i+1)th panel */ - u16 edp_s3d_feature; - u16 edp_t3_optimization; - u64 edp_vswing_preemph; /* v173 */ + u16 edp_s3d_feature; /* 162 */ + u16 edp_t3_optimization; /* 165 */ + u64 edp_vswing_preemph; /* 173 */ + u16 fast_link_training; /* 182 */ + u16 dpcd_600h_write_required; /* 185 */ + struct edp_pwm_delays pwm_delays[16]; /* 186 */ + u16 full_link_params_provided; /* 199 */ + struct edp_full_link_params full_link_params[16]; /* 199 */ } __packed; struct psr_table { @@ -745,81 +863,6 @@ struct bdb_psr { #define SWF14_APM_STANDBY 0x1 #define SWF14_APM_RESTORE 0x0 -/* Add the device class for LFP, TV, HDMI */ -#define DEVICE_TYPE_INT_LFP 0x1022 -#define DEVICE_TYPE_INT_TV 0x1009 -#define DEVICE_TYPE_HDMI 0x60D2 -#define DEVICE_TYPE_DP 0x68C6 -#define DEVICE_TYPE_DP_DUAL_MODE 0x60D6 -#define DEVICE_TYPE_eDP 0x78C6 - -#define DEVICE_TYPE_CLASS_EXTENSION (1 << 15) -#define DEVICE_TYPE_POWER_MANAGEMENT (1 << 14) -#define DEVICE_TYPE_HOTPLUG_SIGNALING (1 << 13) -#define DEVICE_TYPE_INTERNAL_CONNECTOR (1 << 12) -#define DEVICE_TYPE_NOT_HDMI_OUTPUT (1 << 11) -#define DEVICE_TYPE_MIPI_OUTPUT (1 << 10) -#define DEVICE_TYPE_COMPOSITE_OUTPUT (1 << 9) -#define DEVICE_TYPE_DUAL_CHANNEL (1 << 8) -#define DEVICE_TYPE_HIGH_SPEED_LINK (1 << 6) -#define DEVICE_TYPE_LVDS_SINGALING (1 << 5) -#define DEVICE_TYPE_TMDS_DVI_SIGNALING (1 << 4) -#define DEVICE_TYPE_VIDEO_SIGNALING (1 << 3) -#define DEVICE_TYPE_DISPLAYPORT_OUTPUT (1 << 2) -#define DEVICE_TYPE_DIGITAL_OUTPUT (1 << 1) -#define DEVICE_TYPE_ANALOG_OUTPUT (1 << 0) - -/* - * Bits we care about when checking for DEVICE_TYPE_eDP - * Depending on the system, the other bits may or may not - * be set for eDP outputs. - */ -#define DEVICE_TYPE_eDP_BITS \ - (DEVICE_TYPE_INTERNAL_CONNECTOR | \ - DEVICE_TYPE_MIPI_OUTPUT | \ - DEVICE_TYPE_COMPOSITE_OUTPUT | \ - DEVICE_TYPE_DUAL_CHANNEL | \ - DEVICE_TYPE_LVDS_SINGALING | \ - DEVICE_TYPE_TMDS_DVI_SIGNALING | \ - DEVICE_TYPE_VIDEO_SIGNALING | \ - DEVICE_TYPE_DISPLAYPORT_OUTPUT | \ - DEVICE_TYPE_ANALOG_OUTPUT) - -#define DEVICE_TYPE_DP_DUAL_MODE_BITS \ - (DEVICE_TYPE_INTERNAL_CONNECTOR | \ - DEVICE_TYPE_MIPI_OUTPUT | \ - DEVICE_TYPE_COMPOSITE_OUTPUT | \ - DEVICE_TYPE_LVDS_SINGALING | \ - DEVICE_TYPE_TMDS_DVI_SIGNALING | \ - DEVICE_TYPE_VIDEO_SIGNALING | \ - DEVICE_TYPE_DISPLAYPORT_OUTPUT | \ - DEVICE_TYPE_DIGITAL_OUTPUT | \ - DEVICE_TYPE_ANALOG_OUTPUT) - -/* define the DVO port for HDMI output type */ -#define DVO_B 1 -#define DVO_C 2 -#define DVO_D 3 - -/* Possible values for the "DVO Port" field for versions >= 155: */ -#define DVO_PORT_HDMIA 0 -#define DVO_PORT_HDMIB 1 -#define DVO_PORT_HDMIC 2 -#define DVO_PORT_HDMID 3 -#define DVO_PORT_LVDS 4 -#define DVO_PORT_TV 5 -#define DVO_PORT_CRT 6 -#define DVO_PORT_DPB 7 -#define DVO_PORT_DPC 8 -#define DVO_PORT_DPD 9 -#define DVO_PORT_DPA 10 -#define DVO_PORT_DPE 11 -#define DVO_PORT_HDMIE 12 -#define DVO_PORT_MIPIA 21 -#define DVO_PORT_MIPIB 22 -#define DVO_PORT_MIPIC 23 -#define DVO_PORT_MIPID 24 - /* Block 52 contains MIPI configuration block * 6 * bdb_mipi_config, followed by 6 pps data block * block below diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c index f91cb72..93c7e3f 100644 --- a/drivers/gpu/drm/imx/imx-drm-core.c +++ b/drivers/gpu/drm/imx/imx-drm-core.c @@ -24,6 +24,7 @@ #include <drm/drm_fb_helper.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_plane_helper.h> #include <drm/drm_of.h> @@ -105,7 +106,7 @@ static int imx_drm_atomic_check(struct drm_device *dev, } static const struct drm_mode_config_funcs imx_drm_mode_config_funcs = { - .fb_create = drm_fb_cma_create, + .fb_create = drm_gem_fb_create, .output_poll_changed = imx_drm_output_poll_changed, .atomic_check = imx_drm_atomic_check, .atomic_commit = drm_atomic_helper_commit, diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index cf98596..247c60e 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -18,6 +18,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_plane_helper.h> #include "video/imx-ipu-v3.h" @@ -690,7 +691,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, } static const struct drm_plane_helper_funcs ipu_plane_helper_funcs = { - .prepare_fb = drm_fb_cma_prepare_fb, + .prepare_fb = drm_gem_fb_prepare_fb, .atomic_check = ipu_plane_atomic_check, .atomic_disable = ipu_plane_atomic_disable, .atomic_update = ipu_plane_atomic_update, diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c index 690c675..3ff5027 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c @@ -1696,11 +1696,7 @@ static int mtk_drm_hdmi_probe(struct platform_device *pdev) hdmi->bridge.funcs = &mtk_hdmi_bridge_funcs; hdmi->bridge.of_node = pdev->dev.of_node; - ret = drm_bridge_add(&hdmi->bridge); - if (ret) { - dev_err(dev, "failed to add bridge, ret = %d\n", ret); - return ret; - } + drm_bridge_add(&hdmi->bridge); ret = mtk_hdmi_clk_enable_audio(hdmi); if (ret) { diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index d84a031..718d8ce 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -63,6 +63,15 @@ config DRM_PANEL_LG_LG4573 Say Y here if you want to enable support for LG4573 RGB panel. To compile this driver as a module, choose M here. +config DRM_PANEL_ORISETECH_OTM8009A + tristate "Orise Technology otm8009a 480x800 dsi 2dl panel" + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y here if you want to enable support for Orise Technology + otm8009a 480x800 dsi 2dl panel. + config DRM_PANEL_PANASONIC_VVX10F034N00 tristate "Panasonic VVX10F034N00 1920x1200 video mode panel" depends on OF @@ -80,12 +89,28 @@ config DRM_PANEL_SAMSUNG_S6E3HA2 depends on BACKLIGHT_CLASS_DEVICE select VIDEOMODE_HELPERS +config DRM_PANEL_SAMSUNG_S6E63J0X03 + tristate "Samsung S6E63J0X03 DSI command mode panel" + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + select VIDEOMODE_HELPERS + config DRM_PANEL_SAMSUNG_S6E8AA0 tristate "Samsung S6E8AA0 DSI video mode panel" depends on OF select DRM_MIPI_DSI select VIDEOMODE_HELPERS +config DRM_PANEL_SEIKO_43WVF1G + tristate "Seiko 43WVF1G panel" + depends on OF + depends on BACKLIGHT_CLASS_DEVICE + select VIDEOMODE_HELPERS + help + Say Y here if you want to enable support for the Seiko + 43WVF1G controller for 800x480 LCD panels + config DRM_PANEL_SHARP_LQ101R1SX01 tristate "Sharp LQ101R1SX01 panel" depends on OF diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index 9f6610d..c8483fd 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -3,10 +3,13 @@ obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o obj-$(CONFIG_DRM_PANEL_INNOLUX_P079ZCA) += panel-innolux-p079zca.o obj-$(CONFIG_DRM_PANEL_JDI_LT070ME05000) += panel-jdi-lt070me05000.o obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o +obj-$(CONFIG_DRM_PANEL_ORISETECH_OTM8009A) += panel-orisetech-otm8009a.o obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += panel-panasonic-vvx10f034n00.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2) += panel-samsung-s6e3ha2.o +obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03) += panel-samsung-s6e63j0x03.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0) += panel-samsung-s6e8aa0.o +obj-$(CONFIG_DRM_PANEL_SEIKO_43WVF1G) += panel-seiko-43wvf1g.o obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) += panel-sharp-lq101r1sx01.o obj-$(CONFIG_DRM_PANEL_SHARP_LS043T1LE01) += panel-sharp-ls043t1le01.o obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7789V) += panel-sitronix-st7789v.o diff --git a/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c b/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c new file mode 100644 index 0000000..c189cd6 --- /dev/null +++ b/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c @@ -0,0 +1,491 @@ +/* + * Copyright (C) STMicroelectronics SA 2017 + * + * Authors: Philippe Cornu <philippe.cornu@st.com> + * Yannick Fertre <yannick.fertre@st.com> + * + * License terms: GNU General Public License (GPL), version 2 + */ +#include <drm/drmP.h> +#include <drm/drm_mipi_dsi.h> +#include <drm/drm_panel.h> +#include <linux/backlight.h> +#include <linux/gpio/consumer.h> +#include <video/mipi_display.h> + +#define DRV_NAME "orisetech_otm8009a" + +#define OTM8009A_BACKLIGHT_DEFAULT 240 +#define OTM8009A_BACKLIGHT_MAX 255 + +/* Manufacturer Command Set */ +#define MCS_ADRSFT 0x0000 /* Address Shift Function */ +#define MCS_PANSET 0xB3A6 /* Panel Type Setting */ +#define MCS_SD_CTRL 0xC0A2 /* Source Driver Timing Setting */ +#define MCS_P_DRV_M 0xC0B4 /* Panel Driving Mode */ +#define MCS_OSC_ADJ 0xC181 /* Oscillator Adjustment for Idle/Normal mode */ +#define MCS_RGB_VID_SET 0xC1A1 /* RGB Video Mode Setting */ +#define MCS_SD_PCH_CTRL 0xC480 /* Source Driver Precharge Control */ +#define MCS_NO_DOC1 0xC48A /* Command not documented */ +#define MCS_PWR_CTRL1 0xC580 /* Power Control Setting 1 */ +#define MCS_PWR_CTRL2 0xC590 /* Power Control Setting 2 for Normal Mode */ +#define MCS_PWR_CTRL4 0xC5B0 /* Power Control Setting 4 for DC Voltage */ +#define MCS_PANCTRLSET1 0xCB80 /* Panel Control Setting 1 */ +#define MCS_PANCTRLSET2 0xCB90 /* Panel Control Setting 2 */ +#define MCS_PANCTRLSET3 0xCBA0 /* Panel Control Setting 3 */ +#define MCS_PANCTRLSET4 0xCBB0 /* Panel Control Setting 4 */ +#define MCS_PANCTRLSET5 0xCBC0 /* Panel Control Setting 5 */ +#define MCS_PANCTRLSET6 0xCBD0 /* Panel Control Setting 6 */ +#define MCS_PANCTRLSET7 0xCBE0 /* Panel Control Setting 7 */ +#define MCS_PANCTRLSET8 0xCBF0 /* Panel Control Setting 8 */ +#define MCS_PANU2D1 0xCC80 /* Panel U2D Setting 1 */ +#define MCS_PANU2D2 0xCC90 /* Panel U2D Setting 2 */ +#define MCS_PANU2D3 0xCCA0 /* Panel U2D Setting 3 */ +#define MCS_PAND2U1 0xCCB0 /* Panel D2U Setting 1 */ +#define MCS_PAND2U2 0xCCC0 /* Panel D2U Setting 2 */ +#define MCS_PAND2U3 0xCCD0 /* Panel D2U Setting 3 */ +#define MCS_GOAVST 0xCE80 /* GOA VST Setting */ +#define MCS_GOACLKA1 0xCEA0 /* GOA CLKA1 Setting */ +#define MCS_GOACLKA3 0xCEB0 /* GOA CLKA3 Setting */ +#define MCS_GOAECLK 0xCFC0 /* GOA ECLK Setting */ +#define MCS_NO_DOC2 0xCFD0 /* Command not documented */ +#define MCS_GVDDSET 0xD800 /* GVDD/NGVDD */ +#define MCS_VCOMDC 0xD900 /* VCOM Voltage Setting */ +#define MCS_GMCT2_2P 0xE100 /* Gamma Correction 2.2+ Setting */ +#define MCS_GMCT2_2N 0xE200 /* Gamma Correction 2.2- Setting */ +#define MCS_NO_DOC3 0xF5B6 /* Command not documented */ +#define MCS_CMD2_ENA1 0xFF00 /* Enable Access Command2 "CMD2" */ +#define MCS_CMD2_ENA2 0xFF80 /* Enable Access Orise Command2 */ + +struct otm8009a { + struct device *dev; + struct drm_panel panel; + struct backlight_device *bl_dev; + struct gpio_desc *reset_gpio; + bool prepared; + bool enabled; +}; + +static const struct drm_display_mode default_mode = { + .clock = 32729, + .hdisplay = 480, + .hsync_start = 480 + 120, + .hsync_end = 480 + 120 + 63, + .htotal = 480 + 120 + 63 + 120, + .vdisplay = 800, + .vsync_start = 800 + 12, + .vsync_end = 800 + 12 + 12, + .vtotal = 800 + 12 + 12 + 12, + .vrefresh = 50, + .flags = 0, + .width_mm = 52, + .height_mm = 86, +}; + +static inline struct otm8009a *panel_to_otm8009a(struct drm_panel *panel) +{ + return container_of(panel, struct otm8009a, panel); +} + +static void otm8009a_dcs_write_buf(struct otm8009a *ctx, const void *data, + size_t len) +{ + struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); + + if (mipi_dsi_dcs_write_buffer(dsi, data, len) < 0) + DRM_WARN("mipi dsi dcs write buffer failed\n"); +} + +#define dcs_write_seq(ctx, seq...) \ +({ \ + static const u8 d[] = { seq }; \ + otm8009a_dcs_write_buf(ctx, d, ARRAY_SIZE(d)); \ +}) + +#define dcs_write_cmd_at(ctx, cmd, seq...) \ +({ \ + dcs_write_seq(ctx, MCS_ADRSFT, (cmd) & 0xFF); \ + dcs_write_seq(ctx, (cmd) >> 8, seq); \ +}) + +static int otm8009a_init_sequence(struct otm8009a *ctx) +{ + struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); + int ret; + + /* Enter CMD2 */ + dcs_write_cmd_at(ctx, MCS_CMD2_ENA1, 0x80, 0x09, 0x01); + + /* Enter Orise Command2 */ + dcs_write_cmd_at(ctx, MCS_CMD2_ENA2, 0x80, 0x09); + + dcs_write_cmd_at(ctx, MCS_SD_PCH_CTRL, 0x30); + mdelay(10); + + dcs_write_cmd_at(ctx, MCS_NO_DOC1, 0x40); + mdelay(10); + + dcs_write_cmd_at(ctx, MCS_PWR_CTRL4 + 1, 0xA9); + dcs_write_cmd_at(ctx, MCS_PWR_CTRL2 + 1, 0x34); + dcs_write_cmd_at(ctx, MCS_P_DRV_M, 0x50); + dcs_write_cmd_at(ctx, MCS_VCOMDC, 0x4E); + dcs_write_cmd_at(ctx, MCS_OSC_ADJ, 0x66); /* 65Hz */ + dcs_write_cmd_at(ctx, MCS_PWR_CTRL2 + 2, 0x01); + dcs_write_cmd_at(ctx, MCS_PWR_CTRL2 + 5, 0x34); + dcs_write_cmd_at(ctx, MCS_PWR_CTRL2 + 4, 0x33); + dcs_write_cmd_at(ctx, MCS_GVDDSET, 0x79, 0x79); + dcs_write_cmd_at(ctx, MCS_SD_CTRL + 1, 0x1B); + dcs_write_cmd_at(ctx, MCS_PWR_CTRL1 + 2, 0x83); + dcs_write_cmd_at(ctx, MCS_SD_PCH_CTRL + 1, 0x83); + dcs_write_cmd_at(ctx, MCS_RGB_VID_SET, 0x0E); + dcs_write_cmd_at(ctx, MCS_PANSET, 0x00, 0x01); + + dcs_write_cmd_at(ctx, MCS_GOAVST, 0x85, 0x01, 0x00, 0x84, 0x01, 0x00); + dcs_write_cmd_at(ctx, MCS_GOACLKA1, 0x18, 0x04, 0x03, 0x39, 0x00, 0x00, + 0x00, 0x18, 0x03, 0x03, 0x3A, 0x00, 0x00, 0x00); + dcs_write_cmd_at(ctx, MCS_GOACLKA3, 0x18, 0x02, 0x03, 0x3B, 0x00, 0x00, + 0x00, 0x18, 0x01, 0x03, 0x3C, 0x00, 0x00, 0x00); + dcs_write_cmd_at(ctx, MCS_GOAECLK, 0x01, 0x01, 0x20, 0x20, 0x00, 0x00, + 0x01, 0x02, 0x00, 0x00); + + dcs_write_cmd_at(ctx, MCS_NO_DOC2, 0x00); + + dcs_write_cmd_at(ctx, MCS_PANCTRLSET1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + dcs_write_cmd_at(ctx, MCS_PANCTRLSET2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0); + dcs_write_cmd_at(ctx, MCS_PANCTRLSET3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0); + dcs_write_cmd_at(ctx, MCS_PANCTRLSET4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + dcs_write_cmd_at(ctx, MCS_PANCTRLSET5, 0, 4, 4, 4, 4, 4, 0, 0, 0, 0, + 0, 0, 0, 0, 0); + dcs_write_cmd_at(ctx, MCS_PANCTRLSET6, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, + 4, 0, 0, 0, 0); + dcs_write_cmd_at(ctx, MCS_PANCTRLSET7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + dcs_write_cmd_at(ctx, MCS_PANCTRLSET8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + + dcs_write_cmd_at(ctx, MCS_PANU2D1, 0x00, 0x26, 0x09, 0x0B, 0x01, 0x25, + 0x00, 0x00, 0x00, 0x00); + dcs_write_cmd_at(ctx, MCS_PANU2D2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x0A, 0x0C, 0x02); + dcs_write_cmd_at(ctx, MCS_PANU2D3, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + dcs_write_cmd_at(ctx, MCS_PAND2U1, 0x00, 0x25, 0x0C, 0x0A, 0x02, 0x26, + 0x00, 0x00, 0x00, 0x00); + dcs_write_cmd_at(ctx, MCS_PAND2U2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x0B, 0x09, 0x01); + dcs_write_cmd_at(ctx, MCS_PAND2U3, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + + dcs_write_cmd_at(ctx, MCS_PWR_CTRL1 + 1, 0x66); + + dcs_write_cmd_at(ctx, MCS_NO_DOC3, 0x06); + + dcs_write_cmd_at(ctx, MCS_GMCT2_2P, 0x00, 0x09, 0x0F, 0x0E, 0x07, 0x10, + 0x0B, 0x0A, 0x04, 0x07, 0x0B, 0x08, 0x0F, 0x10, 0x0A, + 0x01); + dcs_write_cmd_at(ctx, MCS_GMCT2_2N, 0x00, 0x09, 0x0F, 0x0E, 0x07, 0x10, + 0x0B, 0x0A, 0x04, 0x07, 0x0B, 0x08, 0x0F, 0x10, 0x0A, + 0x01); + + /* Exit CMD2 */ + dcs_write_cmd_at(ctx, MCS_CMD2_ENA1, 0xFF, 0xFF, 0xFF); + + ret = mipi_dsi_dcs_nop(dsi); + if (ret) + return ret; + + ret = mipi_dsi_dcs_exit_sleep_mode(dsi); + if (ret) + return ret; + + /* Wait for sleep out exit */ + mdelay(120); + + /* Default portrait 480x800 rgb24 */ + dcs_write_seq(ctx, MIPI_DCS_SET_ADDRESS_MODE, 0x00); + + ret = mipi_dsi_dcs_set_column_address(dsi, 0, + default_mode.hdisplay - 1); + if (ret) + return ret; + + ret = mipi_dsi_dcs_set_page_address(dsi, 0, default_mode.vdisplay - 1); + if (ret) + return ret; + + /* See otm8009a driver documentation for pixel format descriptions */ + ret = mipi_dsi_dcs_set_pixel_format(dsi, MIPI_DCS_PIXEL_FMT_24BIT | + MIPI_DCS_PIXEL_FMT_24BIT << 4); + if (ret) + return ret; + + /* Disable CABC feature */ + dcs_write_seq(ctx, MIPI_DCS_WRITE_POWER_SAVE, 0x00); + + ret = mipi_dsi_dcs_set_display_on(dsi); + if (ret) + return ret; + + ret = mipi_dsi_dcs_nop(dsi); + if (ret) + return ret; + + /* Send Command GRAM memory write (no parameters) */ + dcs_write_seq(ctx, MIPI_DCS_WRITE_MEMORY_START); + + return 0; +} + +static int otm8009a_disable(struct drm_panel *panel) +{ + struct otm8009a *ctx = panel_to_otm8009a(panel); + struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); + int ret; + + if (!ctx->enabled) + return 0; /* This is not an issue so we return 0 here */ + + /* Power off the backlight. Note: end-user still controls brightness */ + ctx->bl_dev->props.power = FB_BLANK_POWERDOWN; + ret = backlight_update_status(ctx->bl_dev); + if (ret) + return ret; + + ret = mipi_dsi_dcs_set_display_off(dsi); + if (ret) + return ret; + + ret = mipi_dsi_dcs_enter_sleep_mode(dsi); + if (ret) + return ret; + + msleep(120); + + ctx->enabled = false; + + return 0; +} + +static int otm8009a_unprepare(struct drm_panel *panel) +{ + struct otm8009a *ctx = panel_to_otm8009a(panel); + + if (!ctx->prepared) + return 0; + + if (ctx->reset_gpio) { + gpiod_set_value_cansleep(ctx->reset_gpio, 1); + msleep(20); + } + + ctx->prepared = false; + + return 0; +} + +static int otm8009a_prepare(struct drm_panel *panel) +{ + struct otm8009a *ctx = panel_to_otm8009a(panel); + int ret; + + if (ctx->prepared) + return 0; + + if (ctx->reset_gpio) { + gpiod_set_value_cansleep(ctx->reset_gpio, 0); + gpiod_set_value_cansleep(ctx->reset_gpio, 1); + msleep(20); + gpiod_set_value_cansleep(ctx->reset_gpio, 0); + msleep(100); + } + + ret = otm8009a_init_sequence(ctx); + if (ret) + return ret; + + ctx->prepared = true; + + /* + * Power on the backlight. Note: end-user still controls brightness + * Note: ctx->prepared must be true before updating the backlight. + */ + ctx->bl_dev->props.power = FB_BLANK_UNBLANK; + backlight_update_status(ctx->bl_dev); + + return 0; +} + +static int otm8009a_enable(struct drm_panel *panel) +{ + struct otm8009a *ctx = panel_to_otm8009a(panel); + + ctx->enabled = true; + + return 0; +} + +static int otm8009a_get_modes(struct drm_panel *panel) +{ + struct drm_display_mode *mode; + + mode = drm_mode_duplicate(panel->drm, &default_mode); + if (!mode) { + DRM_ERROR("failed to add mode %ux%ux@%u\n", + default_mode.hdisplay, default_mode.vdisplay, + default_mode.vrefresh); + return -ENOMEM; + } + + drm_mode_set_name(mode); + + mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; + drm_mode_probed_add(panel->connector, mode); + + panel->connector->display_info.width_mm = mode->width_mm; + panel->connector->display_info.height_mm = mode->height_mm; + + return 1; +} + +static const struct drm_panel_funcs otm8009a_drm_funcs = { + .disable = otm8009a_disable, + .unprepare = otm8009a_unprepare, + .prepare = otm8009a_prepare, + .enable = otm8009a_enable, + .get_modes = otm8009a_get_modes, +}; + +/* + * DSI-BASED BACKLIGHT + */ + +static int otm8009a_backlight_update_status(struct backlight_device *bd) +{ + struct otm8009a *ctx = bl_get_data(bd); + u8 data[2]; + + if (!ctx->prepared) { + DRM_DEBUG("lcd not ready yet for setting its backlight!\n"); + return -ENXIO; + } + + if (bd->props.power <= FB_BLANK_NORMAL) { + /* Power on the backlight with the requested brightness + * Note We can not use mipi_dsi_dcs_set_display_brightness() + * as otm8009a driver support only 8-bit brightness (1 param). + */ + data[0] = MIPI_DCS_SET_DISPLAY_BRIGHTNESS; + data[1] = bd->props.brightness; + otm8009a_dcs_write_buf(ctx, data, ARRAY_SIZE(data)); + + /* set Brightness Control & Backlight on */ + data[1] = 0x24; + + } else { + /* Power off the backlight: set Brightness Control & Bl off */ + data[1] = 0; + } + + /* Update Brightness Control & Backlight */ + data[0] = MIPI_DCS_WRITE_CONTROL_DISPLAY; + otm8009a_dcs_write_buf(ctx, data, ARRAY_SIZE(data)); + + return 0; +} + +static const struct backlight_ops otm8009a_backlight_ops = { + .update_status = otm8009a_backlight_update_status, +}; + +static int otm8009a_probe(struct mipi_dsi_device *dsi) +{ + struct device *dev = &dsi->dev; + struct otm8009a *ctx; + int ret; + + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + ctx->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(ctx->reset_gpio)) { + dev_err(dev, "cannot get reset-gpio\n"); + return PTR_ERR(ctx->reset_gpio); + } + + mipi_dsi_set_drvdata(dsi, ctx); + + ctx->dev = dev; + + dsi->lanes = 2; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | + MIPI_DSI_MODE_LPM; + + drm_panel_init(&ctx->panel); + ctx->panel.dev = dev; + ctx->panel.funcs = &otm8009a_drm_funcs; + + ctx->bl_dev = backlight_device_register(DRV_NAME "_backlight", dev, ctx, + &otm8009a_backlight_ops, NULL); + if (IS_ERR(ctx->bl_dev)) { + dev_err(dev, "failed to register backlight device\n"); + return PTR_ERR(ctx->bl_dev); + } + + ctx->bl_dev->props.max_brightness = OTM8009A_BACKLIGHT_MAX; + ctx->bl_dev->props.brightness = OTM8009A_BACKLIGHT_DEFAULT; + ctx->bl_dev->props.power = FB_BLANK_POWERDOWN; + ctx->bl_dev->props.type = BACKLIGHT_RAW; + + drm_panel_add(&ctx->panel); + + ret = mipi_dsi_attach(dsi); + if (ret < 0) { + dev_err(dev, "mipi_dsi_attach failed. Is host ready?\n"); + drm_panel_remove(&ctx->panel); + backlight_device_unregister(ctx->bl_dev); + return ret; + } + + DRM_INFO(DRV_NAME "_panel %ux%u@%u %ubpp dsi %udl - ready\n", + default_mode.hdisplay, default_mode.vdisplay, + default_mode.vrefresh, + mipi_dsi_pixel_format_to_bpp(dsi->format), dsi->lanes); + + return 0; +} + +static int otm8009a_remove(struct mipi_dsi_device *dsi) +{ + struct otm8009a *ctx = mipi_dsi_get_drvdata(dsi); + + mipi_dsi_detach(dsi); + drm_panel_remove(&ctx->panel); + + backlight_device_unregister(ctx->bl_dev); + + return 0; +} + +static const struct of_device_id orisetech_otm8009a_of_match[] = { + { .compatible = "orisetech,otm8009a" }, + { } +}; +MODULE_DEVICE_TABLE(of, orisetech_otm8009a_of_match); + +static struct mipi_dsi_driver orisetech_otm8009a_driver = { + .probe = otm8009a_probe, + .remove = otm8009a_remove, + .driver = { + .name = DRV_NAME "_panel", + .of_match_table = orisetech_otm8009a_of_match, + }, +}; +module_mipi_dsi_driver(orisetech_otm8009a_driver); + +MODULE_AUTHOR("Philippe Cornu <philippe.cornu@st.com>"); +MODULE_AUTHOR("Yannick Fertre <yannick.fertre@st.com>"); +MODULE_DESCRIPTION("DRM driver for Orise Tech OTM8009A MIPI DSI panel"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63j0x03.c b/drivers/gpu/drm/panel/panel-samsung-s6e63j0x03.c new file mode 100644 index 0000000..aeb32aa --- /dev/null +++ b/drivers/gpu/drm/panel/panel-samsung-s6e63j0x03.c @@ -0,0 +1,532 @@ +/* + * MIPI-DSI based S6E63J0X03 AMOLED lcd 1.63 inch panel driver. + * + * Copyright (c) 2014-2017 Samsung Electronics Co., Ltd + * + * Inki Dae <inki.dae@samsung.com> + * Hoegeun Kwon <hoegeun.kwon@samsung.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <drm/drmP.h> +#include <drm/drm_mipi_dsi.h> +#include <drm/drm_panel.h> +#include <linux/backlight.h> +#include <linux/gpio/consumer.h> +#include <linux/regulator/consumer.h> +#include <video/mipi_display.h> + +#define MCS_LEVEL2_KEY 0xf0 +#define MCS_MTP_KEY 0xf1 +#define MCS_MTP_SET3 0xd4 + +#define MAX_BRIGHTNESS 100 +#define DEFAULT_BRIGHTNESS 80 + +#define NUM_GAMMA_STEPS 9 +#define GAMMA_CMD_CNT 28 + +#define FIRST_COLUMN 20 + +struct s6e63j0x03 { + struct device *dev; + struct drm_panel panel; + struct backlight_device *bl_dev; + + struct regulator_bulk_data supplies[2]; + struct gpio_desc *reset_gpio; +}; + +static const struct drm_display_mode default_mode = { + .clock = 4649, + .hdisplay = 320, + .hsync_start = 320 + 1, + .hsync_end = 320 + 1 + 1, + .htotal = 320 + 1 + 1 + 1, + .vdisplay = 320, + .vsync_start = 320 + 150, + .vsync_end = 320 + 150 + 1, + .vtotal = 320 + 150 + 1 + 2, + .vrefresh = 30, + .flags = 0, +}; + +static const unsigned char gamma_tbl[NUM_GAMMA_STEPS][GAMMA_CMD_CNT] = { + { /* Gamma 10 */ + MCS_MTP_SET3, + 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x7f, 0x52, 0x6b, 0x6f, 0x26, + 0x28, 0x2d, 0x28, 0x26, 0x27, 0x33, 0x34, 0x32, 0x36, 0x36, + 0x35, 0x00, 0xab, 0x00, 0xae, 0x00, 0xbf + }, + { /* gamma 30 */ + MCS_MTP_SET3, + 0x00, 0x00, 0x00, 0x70, 0x7f, 0x7f, 0x4e, 0x64, 0x69, 0x26, + 0x27, 0x2a, 0x28, 0x29, 0x27, 0x31, 0x32, 0x31, 0x35, 0x34, + 0x35, 0x00, 0xc4, 0x00, 0xca, 0x00, 0xdc + }, + { /* gamma 60 */ + MCS_MTP_SET3, + 0x00, 0x00, 0x00, 0x65, 0x7b, 0x7d, 0x5f, 0x67, 0x68, 0x2a, + 0x28, 0x29, 0x28, 0x2a, 0x27, 0x31, 0x2f, 0x30, 0x34, 0x33, + 0x34, 0x00, 0xd9, 0x00, 0xe4, 0x00, 0xf5 + }, + { /* gamma 90 */ + MCS_MTP_SET3, + 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x71, 0x67, 0x6a, 0x6c, 0x29, + 0x28, 0x28, 0x28, 0x29, 0x27, 0x30, 0x2e, 0x30, 0x32, 0x31, + 0x31, 0x00, 0xea, 0x00, 0xf6, 0x01, 0x09 + }, + { /* gamma 120 */ + MCS_MTP_SET3, + 0x00, 0x00, 0x00, 0x3d, 0x66, 0x68, 0x69, 0x69, 0x69, 0x28, + 0x28, 0x27, 0x28, 0x28, 0x27, 0x30, 0x2e, 0x2f, 0x31, 0x31, + 0x30, 0x00, 0xf9, 0x01, 0x05, 0x01, 0x1b + }, + { /* gamma 150 */ + MCS_MTP_SET3, + 0x00, 0x00, 0x00, 0x31, 0x51, 0x53, 0x66, 0x66, 0x67, 0x28, + 0x29, 0x27, 0x28, 0x27, 0x27, 0x2e, 0x2d, 0x2e, 0x31, 0x31, + 0x30, 0x01, 0x04, 0x01, 0x11, 0x01, 0x29 + }, + { /* gamma 200 */ + MCS_MTP_SET3, + 0x00, 0x00, 0x00, 0x2f, 0x4f, 0x51, 0x67, 0x65, 0x65, 0x29, + 0x2a, 0x28, 0x27, 0x25, 0x26, 0x2d, 0x2c, 0x2c, 0x30, 0x30, + 0x30, 0x01, 0x14, 0x01, 0x23, 0x01, 0x3b + }, + { /* gamma 240 */ + MCS_MTP_SET3, + 0x00, 0x00, 0x00, 0x2c, 0x4d, 0x50, 0x65, 0x63, 0x64, 0x2a, + 0x2c, 0x29, 0x26, 0x24, 0x25, 0x2c, 0x2b, 0x2b, 0x30, 0x30, + 0x30, 0x01, 0x1e, 0x01, 0x2f, 0x01, 0x47 + }, + { /* gamma 300 */ + MCS_MTP_SET3, + 0x00, 0x00, 0x00, 0x38, 0x61, 0x64, 0x65, 0x63, 0x64, 0x28, + 0x2a, 0x27, 0x26, 0x23, 0x25, 0x2b, 0x2b, 0x2a, 0x30, 0x2f, + 0x30, 0x01, 0x2d, 0x01, 0x3f, 0x01, 0x57 + } +}; + +static inline struct s6e63j0x03 *panel_to_s6e63j0x03(struct drm_panel *panel) +{ + return container_of(panel, struct s6e63j0x03, panel); +} + +static inline ssize_t s6e63j0x03_dcs_write_seq(struct s6e63j0x03 *ctx, + const void *seq, size_t len) +{ + struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); + + return mipi_dsi_dcs_write_buffer(dsi, seq, len); +} + +#define s6e63j0x03_dcs_write_seq_static(ctx, seq...) \ + ({ \ + static const u8 d[] = { seq }; \ + s6e63j0x03_dcs_write_seq(ctx, d, ARRAY_SIZE(d)); \ + }) + +static inline int s6e63j0x03_enable_lv2_command(struct s6e63j0x03 *ctx) +{ + return s6e63j0x03_dcs_write_seq_static(ctx, MCS_LEVEL2_KEY, 0x5a, 0x5a); +} + +static inline int s6e63j0x03_apply_mtp_key(struct s6e63j0x03 *ctx, bool on) +{ + if (on) + return s6e63j0x03_dcs_write_seq_static(ctx, + MCS_MTP_KEY, 0x5a, 0x5a); + + return s6e63j0x03_dcs_write_seq_static(ctx, MCS_MTP_KEY, 0xa5, 0xa5); +} + +static int s6e63j0x03_power_on(struct s6e63j0x03 *ctx) +{ + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); + if (ret < 0) + return ret; + + msleep(30); + + gpiod_set_value(ctx->reset_gpio, 1); + usleep_range(1000, 2000); + gpiod_set_value(ctx->reset_gpio, 0); + usleep_range(5000, 6000); + + return 0; +} + +static int s6e63j0x03_power_off(struct s6e63j0x03 *ctx) +{ + return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); +} + +static unsigned int s6e63j0x03_get_brightness_index(unsigned int brightness) +{ + unsigned int index; + + index = brightness / (MAX_BRIGHTNESS / NUM_GAMMA_STEPS); + + if (index >= NUM_GAMMA_STEPS) + index = NUM_GAMMA_STEPS - 1; + + return index; +} + +static int s6e63j0x03_update_gamma(struct s6e63j0x03 *ctx, + unsigned int brightness) +{ + struct backlight_device *bl_dev = ctx->bl_dev; + unsigned int index = s6e63j0x03_get_brightness_index(brightness); + int ret; + + ret = s6e63j0x03_apply_mtp_key(ctx, true); + if (ret < 0) + return ret; + + ret = s6e63j0x03_dcs_write_seq(ctx, gamma_tbl[index], GAMMA_CMD_CNT); + if (ret < 0) + return ret; + + ret = s6e63j0x03_apply_mtp_key(ctx, false); + if (ret < 0) + return ret; + + bl_dev->props.brightness = brightness; + + return 0; +} + +static int s6e63j0x03_set_brightness(struct backlight_device *bl_dev) +{ + struct s6e63j0x03 *ctx = bl_get_data(bl_dev); + unsigned int brightness = bl_dev->props.brightness; + + return s6e63j0x03_update_gamma(ctx, brightness); +} + +static const struct backlight_ops s6e63j0x03_bl_ops = { + .update_status = s6e63j0x03_set_brightness, +}; + +static int s6e63j0x03_disable(struct drm_panel *panel) +{ + struct s6e63j0x03 *ctx = panel_to_s6e63j0x03(panel); + struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); + int ret; + + ret = mipi_dsi_dcs_set_display_off(dsi); + if (ret < 0) + return ret; + + ctx->bl_dev->props.power = FB_BLANK_NORMAL; + + ret = mipi_dsi_dcs_enter_sleep_mode(dsi); + if (ret < 0) + return ret; + + msleep(120); + + return 0; +} + +static int s6e63j0x03_unprepare(struct drm_panel *panel) +{ + struct s6e63j0x03 *ctx = panel_to_s6e63j0x03(panel); + int ret; + + ret = s6e63j0x03_power_off(ctx); + if (ret < 0) + return ret; + + ctx->bl_dev->props.power = FB_BLANK_POWERDOWN; + + return 0; +} + +static int s6e63j0x03_panel_init(struct s6e63j0x03 *ctx) +{ + struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); + int ret; + + ret = s6e63j0x03_enable_lv2_command(ctx); + if (ret < 0) + return ret; + + ret = s6e63j0x03_apply_mtp_key(ctx, true); + if (ret < 0) + return ret; + + /* set porch adjustment */ + ret = s6e63j0x03_dcs_write_seq_static(ctx, 0xf2, 0x1c, 0x28); + if (ret < 0) + return ret; + + /* set frame freq */ + ret = s6e63j0x03_dcs_write_seq_static(ctx, 0xb5, 0x00, 0x02, 0x00); + if (ret < 0) + return ret; + + /* set caset, paset */ + ret = mipi_dsi_dcs_set_column_address(dsi, FIRST_COLUMN, + default_mode.hdisplay - 1 + FIRST_COLUMN); + if (ret < 0) + return ret; + + ret = mipi_dsi_dcs_set_page_address(dsi, 0, default_mode.vdisplay - 1); + if (ret < 0) + return ret; + + /* set ltps timming 0, 1 */ + ret = s6e63j0x03_dcs_write_seq_static(ctx, 0xf8, 0x08, 0x08, 0x08, 0x17, + 0x00, 0x2a, 0x02, 0x26, 0x00, 0x00, 0x02, 0x00, 0x00); + if (ret < 0) + return ret; + + ret = s6e63j0x03_dcs_write_seq_static(ctx, 0xf7, 0x02); + if (ret < 0) + return ret; + + /* set param pos te_edge */ + ret = s6e63j0x03_dcs_write_seq_static(ctx, 0xb0, 0x01); + if (ret < 0) + return ret; + + /* set te rising edge */ + ret = s6e63j0x03_dcs_write_seq_static(ctx, 0xe2, 0x0f); + if (ret < 0) + return ret; + + /* set param pos default */ + ret = s6e63j0x03_dcs_write_seq_static(ctx, 0xb0, 0x00); + if (ret < 0) + return ret; + + ret = mipi_dsi_dcs_exit_sleep_mode(dsi); + if (ret < 0) + return ret; + + ret = s6e63j0x03_apply_mtp_key(ctx, false); + if (ret < 0) + return ret; + + return 0; +} + +static int s6e63j0x03_prepare(struct drm_panel *panel) +{ + struct s6e63j0x03 *ctx = panel_to_s6e63j0x03(panel); + int ret; + + ret = s6e63j0x03_power_on(ctx); + if (ret < 0) + return ret; + + ret = s6e63j0x03_panel_init(ctx); + if (ret < 0) + goto err; + + ctx->bl_dev->props.power = FB_BLANK_NORMAL; + + return 0; + +err: + s6e63j0x03_power_off(ctx); + return ret; +} + +static int s6e63j0x03_enable(struct drm_panel *panel) +{ + struct s6e63j0x03 *ctx = panel_to_s6e63j0x03(panel); + struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); + int ret; + + msleep(120); + + ret = s6e63j0x03_apply_mtp_key(ctx, true); + if (ret < 0) + return ret; + + /* set elvss_cond */ + ret = s6e63j0x03_dcs_write_seq_static(ctx, 0xb1, 0x00, 0x09); + if (ret < 0) + return ret; + + /* set pos */ + ret = s6e63j0x03_dcs_write_seq_static(ctx, + MIPI_DCS_SET_ADDRESS_MODE, 0x40); + if (ret < 0) + return ret; + + /* set default white brightness */ + ret = mipi_dsi_dcs_set_display_brightness(dsi, 0x00ff); + if (ret < 0) + return ret; + + /* set white ctrl */ + ret = s6e63j0x03_dcs_write_seq_static(ctx, + MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x20); + if (ret < 0) + return ret; + + /* set acl off */ + ret = s6e63j0x03_dcs_write_seq_static(ctx, + MIPI_DCS_WRITE_POWER_SAVE, 0x00); + if (ret < 0) + return ret; + + ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK); + if (ret < 0) + return ret; + + ret = s6e63j0x03_apply_mtp_key(ctx, false); + if (ret < 0) + return ret; + + ret = mipi_dsi_dcs_set_display_on(dsi); + if (ret < 0) + return ret; + + ctx->bl_dev->props.power = FB_BLANK_UNBLANK; + + return 0; +} + +static int s6e63j0x03_get_modes(struct drm_panel *panel) +{ + struct drm_connector *connector = panel->connector; + struct drm_display_mode *mode; + + mode = drm_mode_duplicate(panel->drm, &default_mode); + if (!mode) { + DRM_ERROR("failed to add mode %ux%ux@%u\n", + default_mode.hdisplay, default_mode.vdisplay, + default_mode.vrefresh); + return -ENOMEM; + } + + drm_mode_set_name(mode); + + mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; + drm_mode_probed_add(connector, mode); + + connector->display_info.width_mm = 29; + connector->display_info.height_mm = 29; + + return 1; +} + +static const struct drm_panel_funcs s6e63j0x03_funcs = { + .disable = s6e63j0x03_disable, + .unprepare = s6e63j0x03_unprepare, + .prepare = s6e63j0x03_prepare, + .enable = s6e63j0x03_enable, + .get_modes = s6e63j0x03_get_modes, +}; + +static int s6e63j0x03_probe(struct mipi_dsi_device *dsi) +{ + struct device *dev = &dsi->dev; + struct s6e63j0x03 *ctx; + int ret; + + ctx = devm_kzalloc(dev, sizeof(struct s6e63j0x03), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + mipi_dsi_set_drvdata(dsi, ctx); + + ctx->dev = dev; + + dsi->lanes = 1; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->mode_flags = MIPI_DSI_MODE_EOT_PACKET; + + ctx->supplies[0].supply = "vdd3"; + ctx->supplies[1].supply = "vci"; + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies), + ctx->supplies); + if (ret < 0) { + dev_err(dev, "failed to get regulators: %d\n", ret); + return ret; + } + + ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(ctx->reset_gpio)) { + dev_err(dev, "cannot get reset-gpio: %ld\n", + PTR_ERR(ctx->reset_gpio)); + return PTR_ERR(ctx->reset_gpio); + } + + drm_panel_init(&ctx->panel); + ctx->panel.dev = dev; + ctx->panel.funcs = &s6e63j0x03_funcs; + + ctx->bl_dev = backlight_device_register("s6e63j0x03", dev, ctx, + &s6e63j0x03_bl_ops, NULL); + if (IS_ERR(ctx->bl_dev)) { + dev_err(dev, "failed to register backlight device\n"); + return PTR_ERR(ctx->bl_dev); + } + + ctx->bl_dev->props.max_brightness = MAX_BRIGHTNESS; + ctx->bl_dev->props.brightness = DEFAULT_BRIGHTNESS; + ctx->bl_dev->props.power = FB_BLANK_POWERDOWN; + + ret = drm_panel_add(&ctx->panel); + if (ret < 0) + goto unregister_backlight; + + ret = mipi_dsi_attach(dsi); + if (ret < 0) + goto remove_panel; + + return ret; + +remove_panel: + drm_panel_remove(&ctx->panel); + +unregister_backlight: + backlight_device_unregister(ctx->bl_dev); + + return ret; +} + +static int s6e63j0x03_remove(struct mipi_dsi_device *dsi) +{ + struct s6e63j0x03 *ctx = mipi_dsi_get_drvdata(dsi); + + mipi_dsi_detach(dsi); + drm_panel_remove(&ctx->panel); + + backlight_device_unregister(ctx->bl_dev); + + return 0; +} + +static const struct of_device_id s6e63j0x03_of_match[] = { + { .compatible = "samsung,s6e63j0x03" }, + { } +}; +MODULE_DEVICE_TABLE(of, s6e63j0x03_of_match); + +static struct mipi_dsi_driver s6e63j0x03_driver = { + .probe = s6e63j0x03_probe, + .remove = s6e63j0x03_remove, + .driver = { + .name = "panel_samsung_s6e63j0x03", + .of_match_table = s6e63j0x03_of_match, + }, +}; +module_mipi_dsi_driver(s6e63j0x03_driver); + +MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>"); +MODULE_AUTHOR("Hoegeun Kwon <hoegeun.kwon@samsung.com>"); +MODULE_DESCRIPTION("MIPI-DSI based s6e63j0x03 AMOLED LCD Panel Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c b/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c new file mode 100644 index 0000000..71c09ed --- /dev/null +++ b/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c @@ -0,0 +1,372 @@ +/* + * Copyright (C) 2017 NXP Semiconductors. + * Author: Marco Franchi <marco.franchi@nxp.com> + * + * Based on Panel Simple driver by Thierry Reding <treding@nvidia.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + */ + +#include <linux/backlight.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/regulator/consumer.h> + +#include <drm/drmP.h> +#include <drm/drm_crtc.h> +#include <drm/drm_panel.h> + +#include <video/display_timing.h> +#include <video/videomode.h> + +struct seiko_panel_desc { + const struct drm_display_mode *modes; + unsigned int num_modes; + const struct display_timing *timings; + unsigned int num_timings; + + unsigned int bpc; + + /** + * @width: width (in millimeters) of the panel's active display area + * @height: height (in millimeters) of the panel's active display area + */ + struct { + unsigned int width; + unsigned int height; + } size; + + u32 bus_format; + u32 bus_flags; +}; + +struct seiko_panel { + struct drm_panel base; + bool prepared; + bool enabled; + const struct seiko_panel_desc *desc; + struct backlight_device *backlight; + struct regulator *dvdd; + struct regulator *avdd; +}; + +static inline struct seiko_panel *to_seiko_panel(struct drm_panel *panel) +{ + return container_of(panel, struct seiko_panel, base); +} + +static int seiko_panel_get_fixed_modes(struct seiko_panel *panel) +{ + struct drm_connector *connector = panel->base.connector; + struct drm_device *drm = panel->base.drm; + struct drm_display_mode *mode; + unsigned int i, num = 0; + + if (!panel->desc) + return 0; + + for (i = 0; i < panel->desc->num_timings; i++) { + const struct display_timing *dt = &panel->desc->timings[i]; + struct videomode vm; + + videomode_from_timing(dt, &vm); + mode = drm_mode_create(drm); + if (!mode) { + dev_err(drm->dev, "failed to add mode %ux%u\n", + dt->hactive.typ, dt->vactive.typ); + continue; + } + + drm_display_mode_from_videomode(&vm, mode); + + mode->type |= DRM_MODE_TYPE_DRIVER; + + if (panel->desc->num_timings == 1) + mode->type |= DRM_MODE_TYPE_PREFERRED; + + drm_mode_probed_add(connector, mode); + num++; + } + + for (i = 0; i < panel->desc->num_modes; i++) { + const struct drm_display_mode *m = &panel->desc->modes[i]; + + mode = drm_mode_duplicate(drm, m); + if (!mode) { + dev_err(drm->dev, "failed to add mode %ux%u@%u\n", + m->hdisplay, m->vdisplay, m->vrefresh); + continue; + } + + mode->type |= DRM_MODE_TYPE_DRIVER; + + if (panel->desc->num_modes == 1) + mode->type |= DRM_MODE_TYPE_PREFERRED; + + drm_mode_set_name(mode); + + drm_mode_probed_add(connector, mode); + num++; + } + + connector->display_info.bpc = panel->desc->bpc; + connector->display_info.width_mm = panel->desc->size.width; + connector->display_info.height_mm = panel->desc->size.height; + if (panel->desc->bus_format) + drm_display_info_set_bus_formats(&connector->display_info, + &panel->desc->bus_format, 1); + connector->display_info.bus_flags = panel->desc->bus_flags; + + return num; +} + +static int seiko_panel_disable(struct drm_panel *panel) +{ + struct seiko_panel *p = to_seiko_panel(panel); + + if (!p->enabled) + return 0; + + if (p->backlight) { + p->backlight->props.power = FB_BLANK_POWERDOWN; + p->backlight->props.state |= BL_CORE_FBBLANK; + backlight_update_status(p->backlight); + } + + p->enabled = false; + + return 0; +} + +static int seiko_panel_unprepare(struct drm_panel *panel) +{ + struct seiko_panel *p = to_seiko_panel(panel); + + if (!p->prepared) + return 0; + + regulator_disable(p->avdd); + + /* Add a 100ms delay as per the panel datasheet */ + msleep(100); + + regulator_disable(p->dvdd); + + p->prepared = false; + + return 0; +} + +static int seiko_panel_prepare(struct drm_panel *panel) +{ + struct seiko_panel *p = to_seiko_panel(panel); + int err; + + if (p->prepared) + return 0; + + err = regulator_enable(p->dvdd); + if (err < 0) { + dev_err(panel->dev, "failed to enable dvdd: %d\n", err); + return err; + } + + /* Add a 100ms delay as per the panel datasheet */ + msleep(100); + + err = regulator_enable(p->avdd); + if (err < 0) { + dev_err(panel->dev, "failed to enable avdd: %d\n", err); + goto disable_dvdd; + } + + p->prepared = true; + + return 0; + +disable_dvdd: + regulator_disable(p->dvdd); + return err; +} + +static int seiko_panel_enable(struct drm_panel *panel) +{ + struct seiko_panel *p = to_seiko_panel(panel); + + if (p->enabled) + return 0; + + if (p->backlight) { + p->backlight->props.state &= ~BL_CORE_FBBLANK; + p->backlight->props.power = FB_BLANK_UNBLANK; + backlight_update_status(p->backlight); + } + + p->enabled = true; + + return 0; +} + +static int seiko_panel_get_modes(struct drm_panel *panel) +{ + struct seiko_panel *p = to_seiko_panel(panel); + + /* add hard-coded panel modes */ + return seiko_panel_get_fixed_modes(p); +} + +static int seiko_panel_get_timings(struct drm_panel *panel, + unsigned int num_timings, + struct display_timing *timings) +{ + struct seiko_panel *p = to_seiko_panel(panel); + unsigned int i; + + if (p->desc->num_timings < num_timings) + num_timings = p->desc->num_timings; + + if (timings) + for (i = 0; i < num_timings; i++) + timings[i] = p->desc->timings[i]; + + return p->desc->num_timings; +} + +static const struct drm_panel_funcs seiko_panel_funcs = { + .disable = seiko_panel_disable, + .unprepare = seiko_panel_unprepare, + .prepare = seiko_panel_prepare, + .enable = seiko_panel_enable, + .get_modes = seiko_panel_get_modes, + .get_timings = seiko_panel_get_timings, +}; + +static int seiko_panel_probe(struct device *dev, + const struct seiko_panel_desc *desc) +{ + struct device_node *backlight; + struct seiko_panel *panel; + int err; + + panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL); + if (!panel) + return -ENOMEM; + + panel->enabled = false; + panel->prepared = false; + panel->desc = desc; + + panel->dvdd = devm_regulator_get(dev, "dvdd"); + if (IS_ERR(panel->dvdd)) + return PTR_ERR(panel->dvdd); + + panel->avdd = devm_regulator_get(dev, "avdd"); + if (IS_ERR(panel->avdd)) + return PTR_ERR(panel->avdd); + + backlight = of_parse_phandle(dev->of_node, "backlight", 0); + if (backlight) { + panel->backlight = of_find_backlight_by_node(backlight); + of_node_put(backlight); + + if (!panel->backlight) + return -EPROBE_DEFER; + } + + drm_panel_init(&panel->base); + panel->base.dev = dev; + panel->base.funcs = &seiko_panel_funcs; + + err = drm_panel_add(&panel->base); + if (err < 0) + return err; + + dev_set_drvdata(dev, panel); + + return 0; +} + +static int seiko_panel_remove(struct platform_device *pdev) +{ + struct seiko_panel *panel = dev_get_drvdata(&pdev->dev); + + drm_panel_detach(&panel->base); + drm_panel_remove(&panel->base); + + seiko_panel_disable(&panel->base); + + if (panel->backlight) + put_device(&panel->backlight->dev); + + return 0; +} + +static void seiko_panel_shutdown(struct platform_device *pdev) +{ + struct seiko_panel *panel = dev_get_drvdata(&pdev->dev); + + seiko_panel_disable(&panel->base); +} + +static const struct display_timing seiko_43wvf1g_timing = { + .pixelclock = { 33500000, 33500000, 33500000 }, + .hactive = { 800, 800, 800 }, + .hfront_porch = { 164, 164, 164 }, + .hback_porch = { 89, 89, 89 }, + .hsync_len = { 10, 10, 10 }, + .vactive = { 480, 480, 480 }, + .vfront_porch = { 10, 10, 10 }, + .vback_porch = { 23, 23, 23 }, + .vsync_len = { 10, 10, 10 }, + .flags = DISPLAY_FLAGS_DE_LOW, +}; + +static const struct seiko_panel_desc seiko_43wvf1g = { + .timings = &seiko_43wvf1g_timing, + .num_timings = 1, + .bpc = 8, + .size = { + .width = 93, + .height = 57, + }, + .bus_format = MEDIA_BUS_FMT_RGB888_1X24, + .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_NEGEDGE, +}; + +static const struct of_device_id platform_of_match[] = { + { + .compatible = "sii,43wvf1g", + .data = &seiko_43wvf1g, + }, { + /* sentinel */ + } +}; +MODULE_DEVICE_TABLE(of, platform_of_match); + +static int seiko_panel_platform_probe(struct platform_device *pdev) +{ + const struct of_device_id *id; + + id = of_match_node(platform_of_match, pdev->dev.of_node); + if (!id) + return -ENODEV; + + return seiko_panel_probe(&pdev->dev, id->data); +} + +static struct platform_driver seiko_panel_platform_driver = { + .driver = { + .name = "seiko_panel", + .of_match_table = platform_of_match, + }, + .probe = seiko_panel_platform_probe, + .remove = seiko_panel_remove, + .shutdown = seiko_panel_shutdown, +}; +module_platform_driver(seiko_panel_platform_driver); + +MODULE_AUTHOR("Marco Franchi <marco.franchi@nxp.com"); +MODULE_DESCRIPTION("Seiko 43WVF1G panel driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 474fa75..a3c96d2 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -187,8 +187,7 @@ static int panel_simple_unprepare(struct drm_panel *panel) if (!p->prepared) return 0; - if (p->enable_gpio) - gpiod_set_value_cansleep(p->enable_gpio, 0); + gpiod_set_value_cansleep(p->enable_gpio, 0); regulator_disable(p->supply); @@ -214,8 +213,7 @@ static int panel_simple_prepare(struct drm_panel *panel) return err; } - if (p->enable_gpio) - gpiod_set_value_cansleep(p->enable_gpio, 1); + gpiod_set_value_cansleep(p->enable_gpio, 1); if (p->desc->delay.prepare) msleep(p->desc->delay.prepare); @@ -315,7 +313,8 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc) GPIOD_OUT_LOW); if (IS_ERR(panel->enable_gpio)) { err = PTR_ERR(panel->enable_gpio); - dev_err(dev, "failed to request GPIO: %d\n", err); + if (err != -EPROBE_DEFER) + dev_err(dev, "failed to request GPIO: %d\n", err); return err; } @@ -369,6 +368,7 @@ static int panel_simple_remove(struct device *dev) drm_panel_remove(&panel->base); panel_simple_disable(&panel->base); + panel_simple_unprepare(&panel->base); if (panel->ddc) put_device(&panel->ddc->dev); @@ -384,6 +384,7 @@ static void panel_simple_shutdown(struct device *dev) struct panel_simple *panel = dev_get_drvdata(dev); panel_simple_disable(&panel->base); + panel_simple_unprepare(&panel->base); } static const struct drm_display_mode ampire_am_480272h3tmqw_t01h_mode = { @@ -1522,8 +1523,8 @@ static const struct panel_desc olimex_lcd_olinuxino_43ts = { .modes = &olimex_lcd_olinuxino_43ts_mode, .num_modes = 1, .size = { - .width = 105, - .height = 67, + .width = 95, + .height = 54, }, .bus_format = MEDIA_BUS_FMT_RGB888_1X24, }; diff --git a/drivers/gpu/drm/pl111/Kconfig b/drivers/gpu/drm/pl111/Kconfig index bbfba87..e5e2abd 100644 --- a/drivers/gpu/drm/pl111/Kconfig +++ b/drivers/gpu/drm/pl111/Kconfig @@ -6,7 +6,8 @@ config DRM_PL111 select DRM_KMS_HELPER select DRM_KMS_CMA_HELPER select DRM_GEM_CMA_HELPER - select DRM_PANEL + select DRM_BRIDGE + select DRM_PANEL_BRIDGE select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE help Choose this option for DRM support for the PL111 CLCD controller. diff --git a/drivers/gpu/drm/pl111/Makefile b/drivers/gpu/drm/pl111/Makefile index 59483d6..fce1453 100644 --- a/drivers/gpu/drm/pl111/Makefile +++ b/drivers/gpu/drm/pl111/Makefile @@ -1,5 +1,5 @@ -pl111_drm-y += pl111_connector.o \ - pl111_display.o \ +pl111_drm-y += pl111_display.o \ + pl111_versatile.o \ pl111_drv.o pl111_drm-$(CONFIG_DEBUG_FS) += pl111_debugfs.o diff --git a/drivers/gpu/drm/pl111/pl111_connector.c b/drivers/gpu/drm/pl111/pl111_connector.c deleted file mode 100644 index d335f9a..0000000 --- a/drivers/gpu/drm/pl111/pl111_connector.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * (C) COPYRIGHT 2012-2013 ARM Limited. All rights reserved. - * - * Parts of this file were based on sources as follows: - * - * Copyright (c) 2006-2008 Intel Corporation - * Copyright (c) 2007 Dave Airlie <airlied@linux.ie> - * Copyright (C) 2011 Texas Instruments - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms of - * such GNU licence. - * - */ - -/** - * pl111_drm_connector.c - * Implementation of the connector functions for PL111 DRM - */ -#include <linux/amba/clcd-regs.h> -#include <linux/version.h> -#include <linux/shmem_fs.h> -#include <linux/dma-buf.h> - -#include <drm/drmP.h> -#include <drm/drm_atomic_helper.h> -#include <drm/drm_crtc_helper.h> -#include <drm/drm_of.h> -#include <drm/drm_panel.h> - -#include "pl111_drm.h" - -static void pl111_connector_destroy(struct drm_connector *connector) -{ - struct pl111_drm_connector *pl111_connector = - to_pl111_connector(connector); - - if (pl111_connector->panel) - drm_panel_detach(pl111_connector->panel); - - drm_connector_unregister(connector); - drm_connector_cleanup(connector); -} - -static enum drm_connector_status pl111_connector_detect(struct drm_connector - *connector, bool force) -{ - struct pl111_drm_connector *pl111_connector = - to_pl111_connector(connector); - - return (pl111_connector->panel ? - connector_status_connected : - connector_status_disconnected); -} - -static int pl111_connector_helper_get_modes(struct drm_connector *connector) -{ - struct pl111_drm_connector *pl111_connector = - to_pl111_connector(connector); - - if (!pl111_connector->panel) - return 0; - - return drm_panel_get_modes(pl111_connector->panel); -} - -const struct drm_connector_funcs connector_funcs = { - .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = pl111_connector_destroy, - .detect = pl111_connector_detect, - .reset = drm_atomic_helper_connector_reset, - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, -}; - -const struct drm_connector_helper_funcs connector_helper_funcs = { - .get_modes = pl111_connector_helper_get_modes, -}; - -/* Walks the OF graph to find the panel node and then asks DRM to look - * up the panel. - */ -static struct drm_panel *pl111_get_panel(struct device *dev) -{ - struct device_node *endpoint, *panel_node; - struct device_node *np = dev->of_node; - struct drm_panel *panel; - - endpoint = of_graph_get_next_endpoint(np, NULL); - if (!endpoint) { - dev_err(dev, "no endpoint to fetch panel\n"); - return NULL; - } - - /* don't proceed if we have an endpoint but no panel_node tied to it */ - panel_node = of_graph_get_remote_port_parent(endpoint); - of_node_put(endpoint); - if (!panel_node) { - dev_err(dev, "no valid panel node\n"); - return NULL; - } - - panel = of_drm_find_panel(panel_node); - of_node_put(panel_node); - - return panel; -} - -int pl111_connector_init(struct drm_device *dev) -{ - struct pl111_drm_dev_private *priv = dev->dev_private; - struct pl111_drm_connector *pl111_connector = &priv->connector; - struct drm_connector *connector = &pl111_connector->connector; - - drm_connector_init(dev, connector, &connector_funcs, - DRM_MODE_CONNECTOR_DPI); - drm_connector_helper_add(connector, &connector_helper_funcs); - - pl111_connector->panel = pl111_get_panel(dev->dev); - if (pl111_connector->panel) - drm_panel_attach(pl111_connector->panel, connector); - - return 0; -} - diff --git a/drivers/gpu/drm/pl111/pl111_debugfs.c b/drivers/gpu/drm/pl111/pl111_debugfs.c index 0d9dee1..7ddc7e3 100644 --- a/drivers/gpu/drm/pl111/pl111_debugfs.c +++ b/drivers/gpu/drm/pl111/pl111_debugfs.c @@ -22,8 +22,14 @@ static const struct { REGDEF(CLCD_TIM2), REGDEF(CLCD_TIM3), REGDEF(CLCD_UBAS), + REGDEF(CLCD_LBAS), REGDEF(CLCD_PL111_CNTL), REGDEF(CLCD_PL111_IENB), + REGDEF(CLCD_PL111_RIS), + REGDEF(CLCD_PL111_MIS), + REGDEF(CLCD_PL111_ICR), + REGDEF(CLCD_PL111_UCUR), + REGDEF(CLCD_PL111_LCUR), }; int pl111_debugfs_regs(struct seq_file *m, void *unused) diff --git a/drivers/gpu/drm/pl111/pl111_display.c b/drivers/gpu/drm/pl111/pl111_display.c index b58c988..06c4bf7 100644 --- a/drivers/gpu/drm/pl111/pl111_display.c +++ b/drivers/gpu/drm/pl111/pl111_display.c @@ -21,7 +21,6 @@ #include <linux/of_graph.h> #include <drm/drmP.h> -#include <drm/drm_panel.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_fb_cma_helper.h> @@ -94,7 +93,7 @@ static void pl111_display_enable(struct drm_simple_display_pipe *pipe, struct pl111_drm_dev_private *priv = drm->dev_private; const struct drm_display_mode *mode = &cstate->mode; struct drm_framebuffer *fb = plane->state->fb; - struct drm_connector *connector = &priv->connector.connector; + struct drm_connector *connector = priv->connector; u32 cntl; u32 ppl, hsw, hfp, hbp; u32 lpp, vsw, vfp, vbp; @@ -156,10 +155,8 @@ static void pl111_display_enable(struct drm_simple_display_pipe *pipe, writel(0, priv->regs + CLCD_TIM3); - drm_panel_prepare(priv->connector.panel); - - /* Enable and Power Up */ - cntl = CNTL_LCDEN | CNTL_LCDTFT | CNTL_LCDPWR | CNTL_LCDVCOMP(1); + /* Hard-code TFT panel */ + cntl = CNTL_LCDEN | CNTL_LCDTFT | CNTL_LCDVCOMP(1); /* Note that the the hardware's format reader takes 'r' from * the low bit, while DRM formats list channels from high bit @@ -202,9 +199,21 @@ static void pl111_display_enable(struct drm_simple_display_pipe *pipe, break; } - writel(cntl, priv->regs + CLCD_PL111_CNTL); + /* Power sequence: first enable and chill */ + writel(cntl, priv->regs + priv->ctrl); + + /* + * We expect this delay to stabilize the contrast + * voltage Vee as stipulated by the manual + */ + msleep(20); + + if (priv->variant_display_enable) + priv->variant_display_enable(drm, fb->format->format); - drm_panel_enable(priv->connector.panel); + /* Power Up */ + cntl |= CNTL_LCDPWR; + writel(cntl, priv->regs + priv->ctrl); drm_crtc_vblank_on(crtc); } @@ -214,15 +223,28 @@ void pl111_display_disable(struct drm_simple_display_pipe *pipe) struct drm_crtc *crtc = &pipe->crtc; struct drm_device *drm = crtc->dev; struct pl111_drm_dev_private *priv = drm->dev_private; + u32 cntl; drm_crtc_vblank_off(crtc); - drm_panel_disable(priv->connector.panel); + /* Power Down */ + cntl = readl(priv->regs + priv->ctrl); + if (cntl & CNTL_LCDPWR) { + cntl &= ~CNTL_LCDPWR; + writel(cntl, priv->regs + priv->ctrl); + } + + /* + * We expect this delay to stabilize the contrast voltage Vee as + * stipulated by the manual + */ + msleep(20); - /* Disable and Power Down */ - writel(0, priv->regs + CLCD_PL111_CNTL); + if (priv->variant_display_disable) + priv->variant_display_disable(drm); - drm_panel_unprepare(priv->connector.panel); + /* Disable */ + writel(0, priv->regs + priv->ctrl); clk_disable_unprepare(priv->clk); } @@ -260,7 +282,7 @@ int pl111_enable_vblank(struct drm_device *drm, unsigned int crtc) { struct pl111_drm_dev_private *priv = drm->dev_private; - writel(CLCD_IRQ_NEXTBASE_UPDATE, priv->regs + CLCD_PL111_IENB); + writel(CLCD_IRQ_NEXTBASE_UPDATE, priv->regs + priv->ienb); return 0; } @@ -269,7 +291,7 @@ void pl111_disable_vblank(struct drm_device *drm, unsigned int crtc) { struct pl111_drm_dev_private *priv = drm->dev_private; - writel(0, priv->regs + CLCD_PL111_IENB); + writel(0, priv->regs + priv->ienb); } static int pl111_display_prepare_fb(struct drm_simple_display_pipe *pipe, @@ -413,22 +435,6 @@ int pl111_display_init(struct drm_device *drm) struct device_node *endpoint; u32 tft_r0b0g0[3]; int ret; - static const u32 formats[] = { - DRM_FORMAT_ABGR8888, - DRM_FORMAT_XBGR8888, - DRM_FORMAT_ARGB8888, - DRM_FORMAT_XRGB8888, - DRM_FORMAT_BGR565, - DRM_FORMAT_RGB565, - DRM_FORMAT_ABGR1555, - DRM_FORMAT_XBGR1555, - DRM_FORMAT_ARGB1555, - DRM_FORMAT_XRGB1555, - DRM_FORMAT_ABGR4444, - DRM_FORMAT_XBGR4444, - DRM_FORMAT_ARGB4444, - DRM_FORMAT_XRGB4444, - }; endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); if (!endpoint) @@ -444,21 +450,16 @@ int pl111_display_init(struct drm_device *drm) } of_node_put(endpoint); - if (tft_r0b0g0[0] != 0 || - tft_r0b0g0[1] != 8 || - tft_r0b0g0[2] != 16) { - dev_err(dev, "arm,pl11x,tft-r0g0b0-pads != [0,8,16] not yet supported\n"); - return -EINVAL; - } - ret = pl111_init_clock_divider(drm); if (ret) return ret; ret = drm_simple_display_pipe_init(drm, &priv->pipe, &pl111_display_funcs, - formats, ARRAY_SIZE(formats), - NULL, &priv->connector.connector); + priv->variant->formats, + priv->variant->nformats, + NULL, + priv->connector); if (ret) return ret; diff --git a/drivers/gpu/drm/pl111/pl111_drm.h b/drivers/gpu/drm/pl111/pl111_drm.h index 5c685bf..440f53e 100644 --- a/drivers/gpu/drm/pl111/pl111_drm.h +++ b/drivers/gpu/drm/pl111/pl111_drm.h @@ -21,25 +21,43 @@ #include <drm/drm_gem.h> #include <drm/drm_simple_kms_helper.h> +#include <drm/drm_connector.h> +#include <drm/drm_encoder.h> +#include <drm/drm_panel.h> +#include <drm/drm_bridge.h> #include <linux/clk-provider.h> +#include <linux/interrupt.h> #define CLCD_IRQ_NEXTBASE_UPDATE BIT(2) struct drm_minor; -struct pl111_drm_connector { - struct drm_connector connector; - struct drm_panel *panel; +/** + * struct pl111_variant_data - encodes IP differences + * @name: the name of this variant + * @is_pl110: this is the early PL110 variant + * @formats: array of supported pixel formats on this variant + * @nformats: the length of the array of supported pixel formats + */ +struct pl111_variant_data { + const char *name; + bool is_pl110; + const u32 *formats; + unsigned int nformats; }; struct pl111_drm_dev_private { struct drm_device *drm; - struct pl111_drm_connector connector; + struct drm_connector *connector; + struct drm_panel *panel; + struct drm_bridge *bridge; struct drm_simple_display_pipe pipe; struct drm_fbdev_cma *fbdev; void *regs; + u32 ienb; + u32 ctrl; /* The pixel clock (a reference to our clock divider off of CLCDCLK). */ struct clk *clk; /* pl111's internal clock divider. */ @@ -48,20 +66,15 @@ struct pl111_drm_dev_private { * subsystem and pl111_display_enable(). */ spinlock_t tim2_lock; + const struct pl111_variant_data *variant; + void (*variant_display_enable) (struct drm_device *drm, u32 format); + void (*variant_display_disable) (struct drm_device *drm); }; -#define to_pl111_connector(x) \ - container_of(x, struct pl111_drm_connector, connector) - int pl111_display_init(struct drm_device *dev); int pl111_enable_vblank(struct drm_device *drm, unsigned int crtc); void pl111_disable_vblank(struct drm_device *drm, unsigned int crtc); irqreturn_t pl111_irq(int irq, void *data); -int pl111_connector_init(struct drm_device *dev); -int pl111_encoder_init(struct drm_device *dev); -int pl111_dumb_create(struct drm_file *file_priv, - struct drm_device *dev, - struct drm_mode_create_dumb *args); int pl111_debugfs_init(struct drm_minor *minor); #endif /* _PL111_DRM_H_ */ diff --git a/drivers/gpu/drm/pl111/pl111_drv.c b/drivers/gpu/drm/pl111/pl111_drv.c index 581c452..201d57d 100644 --- a/drivers/gpu/drm/pl111/pl111_drv.c +++ b/drivers/gpu/drm/pl111/pl111_drv.c @@ -41,9 +41,6 @@ * - Fix race between setting plane base address and getting IRQ for * vsync firing the pageflip completion. * - * - Expose the correct set of formats we can support based on the - * "arm,pl11x,tft-r0g0b0-pads" DT property. - * * - Use the "max-memory-bandwidth" DT property to filter the * supported formats. * @@ -68,8 +65,12 @@ #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_fb_cma_helper.h> +#include <drm/drm_of.h> +#include <drm/drm_bridge.h> +#include <drm/drm_panel.h> #include "pl111_drm.h" +#include "pl111_versatile.h" #define DRIVER_DESC "DRM module for PL111" @@ -83,6 +84,8 @@ static int pl111_modeset_init(struct drm_device *dev) { struct drm_mode_config *mode_config; struct pl111_drm_dev_private *priv = dev->dev_private; + struct drm_panel *panel; + struct drm_bridge *bridge; int ret = 0; drm_mode_config_init(dev); @@ -93,34 +96,43 @@ static int pl111_modeset_init(struct drm_device *dev) mode_config->min_height = 1; mode_config->max_height = 768; - ret = pl111_connector_init(dev); - if (ret) { - dev_err(dev->dev, "Failed to create pl111_drm_connector\n"); - goto out_config; - } - - /* Don't actually attach if we didn't find a drm_panel - * attached to us. This will allow a kernel to include both - * the fbdev pl111 driver and this one, and choose between - * them based on which subsystem has support for the panel. - */ - if (!priv->connector.panel) { - dev_info(dev->dev, - "Disabling due to lack of DRM panel device.\n"); - ret = -ENODEV; - goto out_config; + ret = drm_of_find_panel_or_bridge(dev->dev->of_node, + 0, 0, &panel, &bridge); + if (ret && ret != -ENODEV) + return ret; + if (panel) { + bridge = drm_panel_bridge_add(panel, + DRM_MODE_CONNECTOR_Unknown); + if (IS_ERR(bridge)) { + ret = PTR_ERR(bridge); + goto out_config; + } + /* + * TODO: when we are using a different bridge than a panel + * (such as a dumb VGA connector) we need to devise a different + * method to get the connector out of the bridge. + */ } ret = pl111_display_init(dev); if (ret != 0) { dev_err(dev->dev, "Failed to init display\n"); - goto out_config; + goto out_bridge; } + ret = drm_simple_display_pipe_attach_bridge(&priv->pipe, + bridge); + if (ret) + return ret; + + priv->bridge = bridge; + priv->panel = panel; + priv->connector = panel->connector; + ret = drm_vblank_init(dev, 1); if (ret != 0) { dev_err(dev->dev, "Failed to init vblank\n"); - goto out_config; + goto out_bridge; } drm_mode_config_reset(dev); @@ -132,6 +144,9 @@ static int pl111_modeset_init(struct drm_device *dev) goto finish; +out_bridge: + if (panel) + drm_panel_bridge_remove(bridge); out_config: drm_mode_config_cleanup(dev); finish: @@ -183,6 +198,7 @@ static int pl111_amba_probe(struct amba_device *amba_dev, { struct device *dev = &amba_dev->dev; struct pl111_drm_dev_private *priv; + struct pl111_variant_data *variant = id->data; struct drm_device *drm; int ret; @@ -196,6 +212,33 @@ static int pl111_amba_probe(struct amba_device *amba_dev, amba_set_drvdata(amba_dev, drm); priv->drm = drm; drm->dev_private = priv; + priv->variant = variant; + + /* + * The PL110 and PL111 variants have two registers + * swapped: interrupt enable and control. For this reason + * we use offsets that we can change per variant. + */ + if (variant->is_pl110) { + /* + * The ARM Versatile boards are even more special: + * their PrimeCell ID say they are PL110 but the + * control and interrupt enable registers are anyway + * swapped to the PL111 order so they are not following + * the PL110 datasheet. + */ + if (of_machine_is_compatible("arm,versatile-ab") || + of_machine_is_compatible("arm,versatile-pb")) { + priv->ienb = CLCD_PL111_IENB; + priv->ctrl = CLCD_PL111_CNTL; + } else { + priv->ienb = CLCD_PL110_IENB; + priv->ctrl = CLCD_PL110_CNTL; + } + } else { + priv->ienb = CLCD_PL111_IENB; + priv->ctrl = CLCD_PL111_CNTL; + } priv->regs = devm_ioremap_resource(dev, &amba_dev->res); if (IS_ERR(priv->regs)) { @@ -204,15 +247,19 @@ static int pl111_amba_probe(struct amba_device *amba_dev, } /* turn off interrupts before requesting the irq */ - writel(0, priv->regs + CLCD_PL111_IENB); + writel(0, priv->regs + priv->ienb); ret = devm_request_irq(dev, amba_dev->irq[0], pl111_irq, 0, - "pl111", priv); + variant->name, priv); if (ret != 0) { dev_err(dev, "%s failed irq %d\n", __func__, ret); return ret; } + ret = pl111_versatile_init(dev, priv); + if (ret) + goto dev_unref; + ret = pl111_modeset_init(drm); if (ret != 0) goto dev_unref; @@ -236,16 +283,70 @@ static int pl111_amba_remove(struct amba_device *amba_dev) drm_dev_unregister(drm); if (priv->fbdev) drm_fbdev_cma_fini(priv->fbdev); + if (priv->panel) + drm_panel_bridge_remove(priv->bridge); drm_mode_config_cleanup(drm); drm_dev_unref(drm); return 0; } -static struct amba_id pl111_id_table[] = { +/* + * This variant exist in early versions like the ARM Integrator + * and this version lacks the 565 and 444 pixel formats. + */ +static const u32 pl110_pixel_formats[] = { + DRM_FORMAT_ABGR8888, + DRM_FORMAT_XBGR8888, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_ABGR1555, + DRM_FORMAT_XBGR1555, + DRM_FORMAT_ARGB1555, + DRM_FORMAT_XRGB1555, +}; + +static const struct pl111_variant_data pl110_variant = { + .name = "PL110", + .is_pl110 = true, + .formats = pl110_pixel_formats, + .nformats = ARRAY_SIZE(pl110_pixel_formats), +}; + +/* RealView, Versatile Express etc use this modern variant */ +static const u32 pl111_pixel_formats[] = { + DRM_FORMAT_ABGR8888, + DRM_FORMAT_XBGR8888, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_BGR565, + DRM_FORMAT_RGB565, + DRM_FORMAT_ABGR1555, + DRM_FORMAT_XBGR1555, + DRM_FORMAT_ARGB1555, + DRM_FORMAT_XRGB1555, + DRM_FORMAT_ABGR4444, + DRM_FORMAT_XBGR4444, + DRM_FORMAT_ARGB4444, + DRM_FORMAT_XRGB4444, +}; + +static const struct pl111_variant_data pl111_variant = { + .name = "PL111", + .formats = pl111_pixel_formats, + .nformats = ARRAY_SIZE(pl111_pixel_formats), +}; + +static const struct amba_id pl111_id_table[] = { + { + .id = 0x00041110, + .mask = 0x000fffff, + .data = (void*)&pl110_variant, + }, { .id = 0x00041111, .mask = 0x000fffff, + .data = (void*)&pl111_variant, }, {0, 0}, }; diff --git a/drivers/gpu/drm/pl111/pl111_versatile.c b/drivers/gpu/drm/pl111/pl111_versatile.c new file mode 100644 index 0000000..97d4af6 --- /dev/null +++ b/drivers/gpu/drm/pl111/pl111_versatile.c @@ -0,0 +1,270 @@ +#include <linux/device.h> +#include <linux/of.h> +#include <linux/regmap.h> +#include <linux/mfd/syscon.h> +#include <linux/bitops.h> +#include <linux/module.h> +#include <drm/drmP.h> +#include "pl111_versatile.h" +#include "pl111_drm.h" + +static struct regmap *versatile_syscon_map; + +/* + * We detect the different syscon types from the compatible strings. + */ +enum versatile_clcd { + INTEGRATOR_CLCD_CM, + VERSATILE_CLCD, + REALVIEW_CLCD_EB, + REALVIEW_CLCD_PB1176, + REALVIEW_CLCD_PB11MP, + REALVIEW_CLCD_PBA8, + REALVIEW_CLCD_PBX, +}; + +static const struct of_device_id versatile_clcd_of_match[] = { + { + .compatible = "arm,core-module-integrator", + .data = (void *)INTEGRATOR_CLCD_CM, + }, + { + .compatible = "arm,versatile-sysreg", + .data = (void *)VERSATILE_CLCD, + }, + { + .compatible = "arm,realview-eb-syscon", + .data = (void *)REALVIEW_CLCD_EB, + }, + { + .compatible = "arm,realview-pb1176-syscon", + .data = (void *)REALVIEW_CLCD_PB1176, + }, + { + .compatible = "arm,realview-pb11mp-syscon", + .data = (void *)REALVIEW_CLCD_PB11MP, + }, + { + .compatible = "arm,realview-pba8-syscon", + .data = (void *)REALVIEW_CLCD_PBA8, + }, + { + .compatible = "arm,realview-pbx-syscon", + .data = (void *)REALVIEW_CLCD_PBX, + }, + {}, +}; + +/* + * Core module CLCD control on the Integrator/CP, bits + * 8 thru 19 of the CM_CONTROL register controls a bunch + * of CLCD settings. + */ +#define INTEGRATOR_HDR_CTRL_OFFSET 0x0C +#define INTEGRATOR_CLCD_LCDBIASEN BIT(8) +#define INTEGRATOR_CLCD_LCDBIASUP BIT(9) +#define INTEGRATOR_CLCD_LCDBIASDN BIT(10) +/* Bits 11,12,13 controls the LCD type */ +#define INTEGRATOR_CLCD_LCDMUX_MASK (BIT(11)|BIT(12)|BIT(13)) +#define INTEGRATOR_CLCD_LCDMUX_LCD24 BIT(11) +#define INTEGRATOR_CLCD_LCDMUX_VGA565 BIT(12) +#define INTEGRATOR_CLCD_LCDMUX_SHARP (BIT(11)|BIT(12)) +#define INTEGRATOR_CLCD_LCDMUX_VGA555 BIT(13) +#define INTEGRATOR_CLCD_LCDMUX_VGA24 (BIT(11)|BIT(12)|BIT(13)) +#define INTEGRATOR_CLCD_LCD0_EN BIT(14) +#define INTEGRATOR_CLCD_LCD1_EN BIT(15) +/* R/L flip on Sharp */ +#define INTEGRATOR_CLCD_LCD_STATIC1 BIT(16) +/* U/D flip on Sharp */ +#define INTEGRATOR_CLCD_LCD_STATIC2 BIT(17) +/* No connection on Sharp */ +#define INTEGRATOR_CLCD_LCD_STATIC BIT(18) +/* 0 = 24bit VGA, 1 = 18bit VGA */ +#define INTEGRATOR_CLCD_LCD_N24BITEN BIT(19) + +#define INTEGRATOR_CLCD_MASK (INTEGRATOR_CLCD_LCDBIASEN | \ + INTEGRATOR_CLCD_LCDBIASUP | \ + INTEGRATOR_CLCD_LCDBIASDN | \ + INTEGRATOR_CLCD_LCDMUX_MASK | \ + INTEGRATOR_CLCD_LCD0_EN | \ + INTEGRATOR_CLCD_LCD1_EN | \ + INTEGRATOR_CLCD_LCD_STATIC1 | \ + INTEGRATOR_CLCD_LCD_STATIC2 | \ + INTEGRATOR_CLCD_LCD_STATIC | \ + INTEGRATOR_CLCD_LCD_N24BITEN) + +static void pl111_integrator_enable(struct drm_device *drm, u32 format) +{ + u32 val; + + dev_info(drm->dev, "enable Integrator CLCD connectors\n"); + + /* FIXME: really needed? */ + val = INTEGRATOR_CLCD_LCD_STATIC1 | INTEGRATOR_CLCD_LCD_STATIC2 | + INTEGRATOR_CLCD_LCD0_EN | INTEGRATOR_CLCD_LCD1_EN; + + switch (format) { + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_XRGB8888: + break; + case DRM_FORMAT_BGR565: + case DRM_FORMAT_RGB565: + /* truecolor RGB565 */ + val |= INTEGRATOR_CLCD_LCDMUX_VGA565; + break; + case DRM_FORMAT_XBGR1555: + case DRM_FORMAT_XRGB1555: + /* Pseudocolor, RGB555, BGR555 */ + val |= INTEGRATOR_CLCD_LCDMUX_VGA555; + break; + default: + dev_err(drm->dev, "unhandled format on Integrator 0x%08x\n", + format); + break; + } + + regmap_update_bits(versatile_syscon_map, + INTEGRATOR_HDR_CTRL_OFFSET, + INTEGRATOR_CLCD_MASK, + val); +} + +/* + * This configuration register in the Versatile and RealView + * family is uniformly present but appears more and more + * unutilized starting with the RealView series. + */ +#define SYS_CLCD 0x50 +#define SYS_CLCD_MODE_MASK (BIT(0)|BIT(1)) +#define SYS_CLCD_MODE_888 0 +#define SYS_CLCD_MODE_5551 BIT(0) +#define SYS_CLCD_MODE_565_R_LSB BIT(1) +#define SYS_CLCD_MODE_565_B_LSB (BIT(0)|BIT(1)) +#define SYS_CLCD_CONNECTOR_MASK (BIT(2)|BIT(3)|BIT(4)|BIT(5)) +#define SYS_CLCD_NLCDIOON BIT(2) +#define SYS_CLCD_VDDPOSSWITCH BIT(3) +#define SYS_CLCD_PWR3V5SWITCH BIT(4) +#define SYS_CLCD_VDDNEGSWITCH BIT(5) + +static void pl111_versatile_disable(struct drm_device *drm) +{ + dev_info(drm->dev, "disable Versatile CLCD connectors\n"); + regmap_update_bits(versatile_syscon_map, + SYS_CLCD, + SYS_CLCD_CONNECTOR_MASK, + 0); +} + +static void pl111_versatile_enable(struct drm_device *drm, u32 format) +{ + u32 val = 0; + + dev_info(drm->dev, "enable Versatile CLCD connectors\n"); + + switch (format) { + case DRM_FORMAT_ABGR8888: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_XRGB8888: + val |= SYS_CLCD_MODE_888; + break; + case DRM_FORMAT_BGR565: + val |= SYS_CLCD_MODE_565_R_LSB; + break; + case DRM_FORMAT_RGB565: + val |= SYS_CLCD_MODE_565_B_LSB; + break; + case DRM_FORMAT_ABGR1555: + case DRM_FORMAT_XBGR1555: + case DRM_FORMAT_ARGB1555: + case DRM_FORMAT_XRGB1555: + val |= SYS_CLCD_MODE_5551; + break; + default: + dev_err(drm->dev, "unhandled format on Versatile 0x%08x\n", + format); + break; + } + + /* Set up the MUX */ + regmap_update_bits(versatile_syscon_map, + SYS_CLCD, + SYS_CLCD_MODE_MASK, + val); + + /* Then enable the display */ + regmap_update_bits(versatile_syscon_map, + SYS_CLCD, + SYS_CLCD_CONNECTOR_MASK, + SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH); +} + +static void pl111_realview_clcd_disable(struct drm_device *drm) +{ + dev_info(drm->dev, "disable RealView CLCD connectors\n"); + regmap_update_bits(versatile_syscon_map, + SYS_CLCD, + SYS_CLCD_CONNECTOR_MASK, + 0); +} + +static void pl111_realview_clcd_enable(struct drm_device *drm, u32 format) +{ + dev_info(drm->dev, "enable RealView CLCD connectors\n"); + regmap_update_bits(versatile_syscon_map, + SYS_CLCD, + SYS_CLCD_CONNECTOR_MASK, + SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH); +} + +int pl111_versatile_init(struct device *dev, struct pl111_drm_dev_private *priv) +{ + const struct of_device_id *clcd_id; + enum versatile_clcd versatile_clcd_type; + struct device_node *np; + struct regmap *map; + + np = of_find_matching_node_and_match(NULL, versatile_clcd_of_match, + &clcd_id); + if (!np) { + /* Non-ARM reference designs, just bail out */ + return 0; + } + versatile_clcd_type = (enum versatile_clcd)clcd_id->data; + + map = syscon_node_to_regmap(np); + if (IS_ERR(map)) { + dev_err(dev, "no Versatile syscon regmap\n"); + return PTR_ERR(map); + } + + switch (versatile_clcd_type) { + case INTEGRATOR_CLCD_CM: + versatile_syscon_map = map; + priv->variant_display_enable = pl111_integrator_enable; + dev_info(dev, "set up callbacks for Integrator PL110\n"); + break; + case VERSATILE_CLCD: + versatile_syscon_map = map; + priv->variant_display_enable = pl111_versatile_enable; + priv->variant_display_disable = pl111_versatile_disable; + dev_info(dev, "set up callbacks for Versatile PL110+\n"); + break; + case REALVIEW_CLCD_EB: + case REALVIEW_CLCD_PB1176: + case REALVIEW_CLCD_PB11MP: + case REALVIEW_CLCD_PBA8: + case REALVIEW_CLCD_PBX: + versatile_syscon_map = map; + priv->variant_display_enable = pl111_realview_clcd_enable; + priv->variant_display_disable = pl111_realview_clcd_disable; + dev_info(dev, "set up callbacks for RealView PL111\n"); + break; + default: + dev_info(dev, "unknown Versatile system controller\n"); + break; + } + + return 0; +} +EXPORT_SYMBOL_GPL(pl111_versatile_init); diff --git a/drivers/gpu/drm/pl111/pl111_versatile.h b/drivers/gpu/drm/pl111/pl111_versatile.h new file mode 100644 index 0000000..41aa6d9 --- /dev/null +++ b/drivers/gpu/drm/pl111/pl111_versatile.h @@ -0,0 +1,9 @@ +#include <linux/device.h> +#include "pl111_drm.h" + +#ifndef PL111_VERSATILE_H +#define PL111_VERSATILE_H + +int pl111_versatile_init(struct device *dev, struct pl111_drm_dev_private *priv); + +#endif diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile index 4acbb94..be16c63 100644 --- a/drivers/gpu/drm/radeon/Makefile +++ b/drivers/gpu/drm/radeon/Makefile @@ -109,5 +109,3 @@ radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o radeon-$(CONFIG_ACPI) += radeon_acpi.o obj-$(CONFIG_DRM_RADEON)+= radeon.o - -CFLAGS_radeon_trace_points.o := -I$(src) diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index e82a99c..ab32830 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c @@ -58,7 +58,7 @@ enum r600_hdmi_iec_status_bits { static struct r600_audio_pin r600_audio_status(struct radeon_device *rdev) { - struct r600_audio_pin status; + struct r600_audio_pin status = {}; uint32_t value; value = RREG32(R600_AUDIO_RATE_BPS_CHANNEL); diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index fd25361..2fcf805 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c @@ -322,10 +322,10 @@ static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfb if (rfb->obj) { radeonfb_destroy_pinned_object(rfb->obj); rfb->obj = NULL; + drm_framebuffer_unregister_private(&rfb->base); + drm_framebuffer_cleanup(&rfb->base); } drm_fb_helper_fini(&rfbdev->helper); - drm_framebuffer_unregister_private(&rfb->base); - drm_framebuffer_cleanup(&rfb->base); return 0; } diff --git a/drivers/gpu/drm/radeon/radeon_kfd.c b/drivers/gpu/drm/radeon/radeon_kfd.c index f6578c9..a2ac8ac 100644 --- a/drivers/gpu/drm/radeon/radeon_kfd.c +++ b/drivers/gpu/drm/radeon/radeon_kfd.c @@ -58,6 +58,10 @@ static uint64_t get_vmem_size(struct kgd_dev *kgd); static uint64_t get_gpu_clock_counter(struct kgd_dev *kgd); static uint32_t get_max_engine_clock_in_mhz(struct kgd_dev *kgd); + +static int alloc_pasid(unsigned int bits); +static void free_pasid(unsigned int pasid); + static uint16_t get_fw_version(struct kgd_dev *kgd, enum kgd_engine_type type); /* @@ -112,6 +116,8 @@ static const struct kfd2kgd_calls kfd2kgd = { .get_vmem_size = get_vmem_size, .get_gpu_clock_counter = get_gpu_clock_counter, .get_max_engine_clock_in_mhz = get_max_engine_clock_in_mhz, + .alloc_pasid = alloc_pasid, + .free_pasid = free_pasid, .program_sh_mem_settings = kgd_program_sh_mem_settings, .set_pasid_vmid_mapping = kgd_set_pasid_vmid_mapping, .init_pipeline = kgd_init_pipeline, @@ -341,6 +347,31 @@ static uint32_t get_max_engine_clock_in_mhz(struct kgd_dev *kgd) return rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.sclk / 100; } +/* + * PASID manager + */ +static DEFINE_IDA(pasid_ida); + +int alloc_pasid(unsigned int bits) +{ + int pasid = -EINVAL; + + for (bits = min(bits, 31U); bits > 0; bits--) { + pasid = ida_simple_get(&pasid_ida, + 1U << (bits - 1), 1U << bits, + GFP_KERNEL); + if (pasid != -ENOSPC) + break; + } + + return pasid; +} + +void free_pasid(unsigned int pasid) +{ + ida_simple_remove(&pasid_ida, pasid); +} + static inline struct radeon_device *get_radeon_device(struct kgd_dev *kgd) { return (struct radeon_device *)kgd; diff --git a/drivers/gpu/drm/radeon/radeon_trace.h b/drivers/gpu/drm/radeon/radeon_trace.h index fdce406..815eaa8 100644 --- a/drivers/gpu/drm/radeon/radeon_trace.h +++ b/drivers/gpu/drm/radeon/radeon_trace.h @@ -204,5 +204,5 @@ DEFINE_EVENT(radeon_semaphore_request, radeon_semaphore_wait, /* This part must be outside protection */ #undef TRACE_INCLUDE_PATH -#define TRACE_INCLUDE_PATH . +#define TRACE_INCLUDE_PATH ../../drivers/gpu/drm/radeon #include <trace/define_trace.h> diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index bf69bf9..8032da5 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -725,8 +725,6 @@ static int radeon_ttm_tt_populate(struct ttm_tt *ttm) { struct radeon_ttm_tt *gtt = radeon_ttm_tt_to_gtt(ttm); struct radeon_device *rdev; - unsigned i; - int r; bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); if (ttm->state != tt_unpopulated) @@ -762,33 +760,13 @@ static int radeon_ttm_tt_populate(struct ttm_tt *ttm) } #endif - r = ttm_pool_populate(ttm); - if (r) { - return r; - } - - for (i = 0; i < ttm->num_pages; i++) { - gtt->ttm.dma_address[i] = pci_map_page(rdev->pdev, ttm->pages[i], - 0, PAGE_SIZE, - PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(rdev->pdev, gtt->ttm.dma_address[i])) { - while (i--) { - pci_unmap_page(rdev->pdev, gtt->ttm.dma_address[i], - PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - gtt->ttm.dma_address[i] = 0; - } - ttm_pool_unpopulate(ttm); - return -EFAULT; - } - } - return 0; + return ttm_populate_and_map_pages(rdev->dev, >t->ttm); } static void radeon_ttm_tt_unpopulate(struct ttm_tt *ttm) { struct radeon_device *rdev; struct radeon_ttm_tt *gtt = radeon_ttm_tt_to_gtt(ttm); - unsigned i; bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); if (gtt && gtt->userptr) { @@ -815,14 +793,7 @@ static void radeon_ttm_tt_unpopulate(struct ttm_tt *ttm) } #endif - for (i = 0; i < ttm->num_pages; i++) { - if (gtt->ttm.dma_address[i]) { - pci_unmap_page(rdev->pdev, gtt->ttm.dma_address[i], - PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - } - } - - ttm_pool_unpopulate(ttm); + ttm_unmap_and_unpopulate_pages(rdev->dev, >t->ttm); } int radeon_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr, diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig index dcc539b..0c31f0a 100644 --- a/drivers/gpu/drm/rockchip/Kconfig +++ b/drivers/gpu/drm/rockchip/Kconfig @@ -57,4 +57,12 @@ config ROCKCHIP_INNO_HDMI for the Innosilicon HDMI driver. If you want to enable HDMI on RK3036 based SoC, you should select this option. +config ROCKCHIP_LVDS + bool "Rockchip LVDS support" + depends on DRM_ROCKCHIP + help + Choose this option to enable support for Rockchip LVDS controllers. + Rockchip rk3288 SoC has LVDS TX Controller can be used, and it + support LVDS, rgb, dual LVDS output mode. say Y to enable its + driver. endif diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile index fa8dc9d..a881d2c 100644 --- a/drivers/gpu/drm/rockchip/Makefile +++ b/drivers/gpu/drm/rockchip/Makefile @@ -12,5 +12,6 @@ rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o rockchipdrm-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o rockchipdrm-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o +rockchipdrm-$(CONFIG_ROCKCHIP_LVDS) += rockchip_lvds.o obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 9606121..4d3f6ad 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -88,7 +88,7 @@ static void analogix_dp_psr_set(struct drm_encoder *encoder, bool enabled) if (!analogix_dp_psr_supported(dp->dev)) return; - dev_dbg(dp->dev, "%s PSR...\n", enabled ? "Entry" : "Exit"); + DRM_DEV_DEBUG(dp->dev, "%s PSR...\n", enabled ? "Entry" : "Exit"); spin_lock_irqsave(&dp->psr_lock, flags); if (enabled) @@ -110,7 +110,7 @@ static void analogix_dp_psr_work(struct work_struct *work) ret = rockchip_drm_wait_vact_end(dp->encoder.crtc, PSR_WAIT_LINE_FLAG_TIMEOUT_MS); if (ret) { - dev_err(dp->dev, "line flag interrupt did not arrive\n"); + DRM_DEV_ERROR(dp->dev, "line flag interrupt did not arrive\n"); return; } @@ -140,13 +140,13 @@ static int rockchip_dp_poweron(struct analogix_dp_plat_data *plat_data) ret = clk_prepare_enable(dp->pclk); if (ret < 0) { - dev_err(dp->dev, "failed to enable pclk %d\n", ret); + DRM_DEV_ERROR(dp->dev, "failed to enable pclk %d\n", ret); return ret; } ret = rockchip_dp_pre_init(dp); if (ret < 0) { - dev_err(dp->dev, "failed to dp pre init %d\n", ret); + DRM_DEV_ERROR(dp->dev, "failed to dp pre init %d\n", ret); clk_disable_unprepare(dp->pclk); return ret; } @@ -211,17 +211,17 @@ static void rockchip_dp_drm_encoder_enable(struct drm_encoder *encoder) else val = dp->data->lcdsel_big; - dev_dbg(dp->dev, "vop %s output to dp\n", (ret) ? "LIT" : "BIG"); + DRM_DEV_DEBUG(dp->dev, "vop %s output to dp\n", (ret) ? "LIT" : "BIG"); ret = clk_prepare_enable(dp->grfclk); if (ret < 0) { - dev_err(dp->dev, "failed to enable grfclk %d\n", ret); + DRM_DEV_ERROR(dp->dev, "failed to enable grfclk %d\n", ret); return; } ret = regmap_write(dp->grf, dp->data->lcdsel_grf_reg, val); if (ret != 0) - dev_err(dp->dev, "Could not write to GRF: %d\n", ret); + DRM_DEV_ERROR(dp->dev, "Could not write to GRF: %d\n", ret); clk_disable_unprepare(dp->grfclk); } @@ -277,7 +277,7 @@ static int rockchip_dp_init(struct rockchip_dp_device *dp) dp->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); if (IS_ERR(dp->grf)) { - dev_err(dev, "failed to get rockchip,grf property\n"); + DRM_DEV_ERROR(dev, "failed to get rockchip,grf property\n"); return PTR_ERR(dp->grf); } @@ -287,31 +287,31 @@ static int rockchip_dp_init(struct rockchip_dp_device *dp) } else if (PTR_ERR(dp->grfclk) == -EPROBE_DEFER) { return -EPROBE_DEFER; } else if (IS_ERR(dp->grfclk)) { - dev_err(dev, "failed to get grf clock\n"); + DRM_DEV_ERROR(dev, "failed to get grf clock\n"); return PTR_ERR(dp->grfclk); } dp->pclk = devm_clk_get(dev, "pclk"); if (IS_ERR(dp->pclk)) { - dev_err(dev, "failed to get pclk property\n"); + DRM_DEV_ERROR(dev, "failed to get pclk property\n"); return PTR_ERR(dp->pclk); } dp->rst = devm_reset_control_get(dev, "dp"); if (IS_ERR(dp->rst)) { - dev_err(dev, "failed to get dp reset control\n"); + DRM_DEV_ERROR(dev, "failed to get dp reset control\n"); return PTR_ERR(dp->rst); } ret = clk_prepare_enable(dp->pclk); if (ret < 0) { - dev_err(dp->dev, "failed to enable pclk %d\n", ret); + DRM_DEV_ERROR(dp->dev, "failed to enable pclk %d\n", ret); return ret; } ret = rockchip_dp_pre_init(dp); if (ret < 0) { - dev_err(dp->dev, "failed to pre init %d\n", ret); + DRM_DEV_ERROR(dp->dev, "failed to pre init %d\n", ret); clk_disable_unprepare(dp->pclk); return ret; } diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c b/drivers/gpu/drm/rockchip/cdn-dp-reg.c index b14d211..eb3042c 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-reg.c +++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.c @@ -323,7 +323,7 @@ int cdn_dp_load_firmware(struct cdn_dp_device *dp, const u32 *i_mem, reg = readl(dp->regs + VER_LIB_H_ADDR) & 0xff; dp->fw_version |= reg << 24; - dev_dbg(dp->dev, "firmware version: %x\n", dp->fw_version); + DRM_DEV_DEBUG(dp->dev, "firmware version: %x\n", dp->fw_version); return 0; } diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c index 9a20b9d..b15755b 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c @@ -430,9 +430,9 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi) testdin = max_mbps_to_testdin(dsi->lane_mbps); if (testdin < 0) { - dev_err(dsi->dev, - "failed to get testdin for %dmbps lane clock\n", - dsi->lane_mbps); + DRM_DEV_ERROR(dsi->dev, + "failed to get testdin for %dmbps lane clock\n", + dsi->lane_mbps); return testdin; } @@ -443,7 +443,7 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi) ret = clk_prepare_enable(dsi->phy_cfg_clk); if (ret) { - dev_err(dsi->dev, "Failed to enable phy_cfg_clk\n"); + DRM_DEV_ERROR(dsi->dev, "Failed to enable phy_cfg_clk\n"); return ret; } @@ -501,7 +501,7 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi) ret = readl_poll_timeout(dsi->base + DSI_PHY_STATUS, val, val & LOCK, 1000, PHY_STATUS_TIMEOUT_US); if (ret < 0) { - dev_err(dsi->dev, "failed to wait for phy lock state\n"); + DRM_DEV_ERROR(dsi->dev, "failed to wait for phy lock state\n"); goto phy_init_end; } @@ -509,8 +509,8 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi) val, val & STOP_STATE_CLK_LANE, 1000, PHY_STATUS_TIMEOUT_US); if (ret < 0) - dev_err(dsi->dev, - "failed to wait for phy clk lane stop state\n"); + DRM_DEV_ERROR(dsi->dev, + "failed to wait for phy clk lane stop state\n"); phy_init_end: clk_disable_unprepare(dsi->phy_cfg_clk); @@ -529,8 +529,9 @@ static int dw_mipi_dsi_get_lane_bps(struct dw_mipi_dsi *dsi, bpp = mipi_dsi_pixel_format_to_bpp(dsi->format); if (bpp < 0) { - dev_err(dsi->dev, "failed to get bpp for pixel format %d\n", - dsi->format); + DRM_DEV_ERROR(dsi->dev, + "failed to get bpp for pixel format %d\n", + dsi->format); return bpp; } @@ -541,7 +542,8 @@ static int dw_mipi_dsi_get_lane_bps(struct dw_mipi_dsi *dsi, if (tmp < max_mbps) target_mbps = tmp; else - dev_err(dsi->dev, "DPHY clock frequency is out of range\n"); + DRM_DEV_ERROR(dsi->dev, + "DPHY clock frequency is out of range\n"); } pllref = DIV_ROUND_UP(clk_get_rate(dsi->pllref_clk), USEC_PER_SEC); @@ -582,8 +584,9 @@ static int dw_mipi_dsi_host_attach(struct mipi_dsi_host *host, struct dw_mipi_dsi *dsi = host_to_dsi(host); if (device->lanes > dsi->pdata->max_data_lanes) { - dev_err(dsi->dev, "the number of data lanes(%u) is too many\n", - device->lanes); + DRM_DEV_ERROR(dsi->dev, + "the number of data lanes(%u) is too many\n", + device->lanes); return -EINVAL; } @@ -632,7 +635,8 @@ static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 hdr_val) val, !(val & GEN_CMD_FULL), 1000, CMD_PKT_STATUS_TIMEOUT_US); if (ret < 0) { - dev_err(dsi->dev, "failed to get available command FIFO\n"); + DRM_DEV_ERROR(dsi->dev, + "failed to get available command FIFO\n"); return ret; } @@ -643,7 +647,7 @@ static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 hdr_val) val, (val & mask) == mask, 1000, CMD_PKT_STATUS_TIMEOUT_US); if (ret < 0) { - dev_err(dsi->dev, "failed to write command FIFO\n"); + DRM_DEV_ERROR(dsi->dev, "failed to write command FIFO\n"); return ret; } @@ -663,8 +667,9 @@ static int dw_mipi_dsi_dcs_short_write(struct dw_mipi_dsi *dsi, data |= tx_buf[1] << 8; if (msg->tx_len > 2) { - dev_err(dsi->dev, "too long tx buf length %zu for short write\n", - msg->tx_len); + DRM_DEV_ERROR(dsi->dev, + "too long tx buf length %zu for short write\n", + msg->tx_len); return -EINVAL; } @@ -682,8 +687,9 @@ static int dw_mipi_dsi_dcs_long_write(struct dw_mipi_dsi *dsi, u32 val; if (msg->tx_len < 3) { - dev_err(dsi->dev, "wrong tx buf length %zu for long write\n", - msg->tx_len); + DRM_DEV_ERROR(dsi->dev, + "wrong tx buf length %zu for long write\n", + msg->tx_len); return -EINVAL; } @@ -704,8 +710,8 @@ static int dw_mipi_dsi_dcs_long_write(struct dw_mipi_dsi *dsi, val, !(val & GEN_PLD_W_FULL), 1000, CMD_PKT_STATUS_TIMEOUT_US); if (ret < 0) { - dev_err(dsi->dev, - "failed to get available write payload FIFO\n"); + DRM_DEV_ERROR(dsi->dev, + "failed to get available write payload FIFO\n"); return ret; } } @@ -731,8 +737,8 @@ static ssize_t dw_mipi_dsi_host_transfer(struct mipi_dsi_host *host, ret = dw_mipi_dsi_dcs_long_write(dsi, msg); break; default: - dev_err(dsi->dev, "unsupported message type 0x%02x\n", - msg->type); + DRM_DEV_ERROR(dsi->dev, "unsupported message type 0x%02x\n", + msg->type); ret = -EINVAL; } @@ -935,7 +941,7 @@ static void dw_mipi_dsi_encoder_disable(struct drm_encoder *encoder) return; if (clk_prepare_enable(dsi->pclk)) { - dev_err(dsi->dev, "%s: Failed to enable pclk\n", __func__); + DRM_DEV_ERROR(dsi->dev, "Failed to enable pclk\n"); return; } @@ -967,7 +973,7 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder) return; if (clk_prepare_enable(dsi->pclk)) { - dev_err(dsi->dev, "%s: Failed to enable pclk\n", __func__); + DRM_DEV_ERROR(dsi->dev, "Failed to enable pclk\n"); return; } @@ -991,7 +997,7 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder) */ ret = clk_prepare_enable(dsi->grf_clk); if (ret) { - dev_err(dsi->dev, "Failed to enable grf_clk: %d\n", ret); + DRM_DEV_ERROR(dsi->dev, "Failed to enable grf_clk: %d\n", ret); return; } @@ -1004,7 +1010,7 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder) dw_mipi_dsi_set_mode(dsi, DW_MIPI_DSI_CMD_MODE); if (drm_panel_prepare(dsi->panel)) - dev_err(dsi->dev, "failed to prepare panel\n"); + DRM_DEV_ERROR(dsi->dev, "failed to prepare panel\n"); dw_mipi_dsi_set_mode(dsi, DW_MIPI_DSI_VID_MODE); drm_panel_enable(dsi->panel); @@ -1017,7 +1023,8 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder) val = pdata->dsi0_en_bit << 16; regmap_write(dsi->grf_regmap, pdata->grf_switch_reg, val); - dev_dbg(dsi->dev, "vop %s output to dsi0\n", (mux) ? "LIT" : "BIG"); + DRM_DEV_DEBUG(dsi->dev, + "vop %s output to dsi0\n", (mux) ? "LIT" : "BIG"); dsi->dpms_mode = DRM_MODE_DPMS_ON; clk_disable_unprepare(dsi->grf_clk); @@ -1111,7 +1118,7 @@ static int dw_mipi_dsi_register(struct drm_device *drm, ret = drm_encoder_init(drm, &dsi->encoder, &dw_mipi_dsi_encoder_funcs, DRM_MODE_ENCODER_DSI, NULL); if (ret) { - dev_err(dev, "Failed to initialize encoder with drm\n"); + DRM_DEV_ERROR(dev, "Failed to initialize encoder with drm\n"); return ret; } @@ -1133,7 +1140,7 @@ static int rockchip_mipi_parse_dt(struct dw_mipi_dsi *dsi) dsi->grf_regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); if (IS_ERR(dsi->grf_regmap)) { - dev_err(dsi->dev, "Unable to get rockchip,grf\n"); + DRM_DEV_ERROR(dsi->dev, "Unable to get rockchip,grf\n"); return PTR_ERR(dsi->grf_regmap); } @@ -1205,14 +1212,15 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, dsi->pllref_clk = devm_clk_get(dev, "ref"); if (IS_ERR(dsi->pllref_clk)) { ret = PTR_ERR(dsi->pllref_clk); - dev_err(dev, "Unable to get pll reference clock: %d\n", ret); + DRM_DEV_ERROR(dev, + "Unable to get pll reference clock: %d\n", ret); return ret; } dsi->pclk = devm_clk_get(dev, "pclk"); if (IS_ERR(dsi->pclk)) { ret = PTR_ERR(dsi->pclk); - dev_err(dev, "Unable to get pclk: %d\n", ret); + DRM_DEV_ERROR(dev, "Unable to get pclk: %d\n", ret); return ret; } @@ -1226,7 +1234,8 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, if (ret == -ENOENT) { apb_rst = NULL; } else { - dev_err(dev, "Unable to get reset control: %d\n", ret); + DRM_DEV_ERROR(dev, + "Unable to get reset control: %d\n", ret); return ret; } } @@ -1234,7 +1243,7 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, if (apb_rst) { ret = clk_prepare_enable(dsi->pclk); if (ret) { - dev_err(dev, "%s: Failed to enable pclk\n", __func__); + DRM_DEV_ERROR(dev, "Failed to enable pclk\n"); return ret; } @@ -1249,7 +1258,8 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, dsi->phy_cfg_clk = devm_clk_get(dev, "phy_cfg"); if (IS_ERR(dsi->phy_cfg_clk)) { ret = PTR_ERR(dsi->phy_cfg_clk); - dev_err(dev, "Unable to get phy_cfg_clk: %d\n", ret); + DRM_DEV_ERROR(dev, + "Unable to get phy_cfg_clk: %d\n", ret); return ret; } } @@ -1258,20 +1268,20 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, dsi->grf_clk = devm_clk_get(dev, "grf"); if (IS_ERR(dsi->grf_clk)) { ret = PTR_ERR(dsi->grf_clk); - dev_err(dev, "Unable to get grf_clk: %d\n", ret); + DRM_DEV_ERROR(dev, "Unable to get grf_clk: %d\n", ret); return ret; } } ret = clk_prepare_enable(dsi->pllref_clk); if (ret) { - dev_err(dev, "%s: Failed to enable pllref_clk\n", __func__); + DRM_DEV_ERROR(dev, "Failed to enable pllref_clk\n"); return ret; } ret = dw_mipi_dsi_register(drm, dsi); if (ret) { - dev_err(dev, "Failed to register mipi_dsi: %d\n", ret); + DRM_DEV_ERROR(dev, "Failed to register mipi_dsi: %d\n", ret); goto err_pllref; } @@ -1281,7 +1291,7 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, dsi->dsi_host.dev = dev; ret = mipi_dsi_host_register(&dsi->dsi_host); if (ret) { - dev_err(dev, "Failed to register MIPI host: %d\n", ret); + DRM_DEV_ERROR(dev, "Failed to register MIPI host: %d\n", ret); goto err_cleanup; } diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index ccd5d59..1eb02a8 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -168,7 +168,7 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); if (IS_ERR(hdmi->regmap)) { - dev_err(hdmi->dev, "Unable to get rockchip,grf\n"); + DRM_DEV_ERROR(hdmi->dev, "Unable to get rockchip,grf\n"); return PTR_ERR(hdmi->regmap); } @@ -178,7 +178,7 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) } else if (PTR_ERR(hdmi->vpll_clk) == -EPROBE_DEFER) { return -EPROBE_DEFER; } else if (IS_ERR(hdmi->vpll_clk)) { - dev_err(hdmi->dev, "failed to get grf clock\n"); + DRM_DEV_ERROR(hdmi->dev, "failed to get grf clock\n"); return PTR_ERR(hdmi->vpll_clk); } @@ -188,13 +188,14 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) } else if (PTR_ERR(hdmi->grf_clk) == -EPROBE_DEFER) { return -EPROBE_DEFER; } else if (IS_ERR(hdmi->grf_clk)) { - dev_err(hdmi->dev, "failed to get grf clock\n"); + DRM_DEV_ERROR(hdmi->dev, "failed to get grf clock\n"); return PTR_ERR(hdmi->grf_clk); } ret = clk_prepare_enable(hdmi->vpll_clk); if (ret) { - dev_err(hdmi->dev, "Failed to enable HDMI vpll: %d\n", ret); + DRM_DEV_ERROR(hdmi->dev, + "Failed to enable HDMI vpll: %d\n", ret); return ret; } @@ -259,17 +260,17 @@ static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder) ret = clk_prepare_enable(hdmi->grf_clk); if (ret < 0) { - dev_err(hdmi->dev, "failed to enable grfclk %d\n", ret); + DRM_DEV_ERROR(hdmi->dev, "failed to enable grfclk %d\n", ret); return; } ret = regmap_write(hdmi->regmap, hdmi->chip_data->lcdsel_grf_reg, val); if (ret != 0) - dev_err(hdmi->dev, "Could not write to GRF: %d\n", ret); + DRM_DEV_ERROR(hdmi->dev, "Could not write to GRF: %d\n", ret); clk_disable_unprepare(hdmi->grf_clk); - dev_dbg(hdmi->dev, "vop %s output to hdmi\n", - ret ? "LIT" : "BIG"); + DRM_DEV_DEBUG(hdmi->dev, "vop %s output to hdmi\n", + ret ? "LIT" : "BIG"); } static int @@ -368,7 +369,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, ret = rockchip_hdmi_parse_dt(hdmi); if (ret) { - dev_err(hdmi->dev, "Unable to parse OF data\n"); + DRM_DEV_ERROR(hdmi->dev, "Unable to parse OF data\n"); return ret; } diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index 7a251a5..ee584d8 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -224,7 +224,7 @@ static void inno_hdmi_set_pwr_mode(struct inno_hdmi *hdmi, int mode) break; default: - dev_err(hdmi->dev, "Unknown power mode %d\n", mode); + DRM_DEV_ERROR(hdmi->dev, "Unknown power mode %d\n", mode); } } @@ -742,8 +742,9 @@ static int inno_hdmi_i2c_xfer(struct i2c_adapter *adap, hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY); for (i = 0; i < num; i++) { - dev_dbg(hdmi->dev, "xfer: num: %d/%d, len: %d, flags: %#x\n", - i + 1, num, msgs[i].len, msgs[i].flags); + DRM_DEV_DEBUG(hdmi->dev, + "xfer: num: %d/%d, len: %d, flags: %#x\n", + i + 1, num, msgs[i].len, msgs[i].flags); if (msgs[i].flags & I2C_M_RD) ret = inno_hdmi_i2c_read(hdmi, &msgs[i]); @@ -806,7 +807,7 @@ static struct i2c_adapter *inno_hdmi_i2c_adapter(struct inno_hdmi *hdmi) hdmi->i2c = i2c; - dev_info(hdmi->dev, "registered %s I2C bus driver\n", adap->name); + DRM_DEV_INFO(hdmi->dev, "registered %s I2C bus driver\n", adap->name); return adap; } @@ -838,13 +839,14 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, hdmi->pclk = devm_clk_get(hdmi->dev, "pclk"); if (IS_ERR(hdmi->pclk)) { - dev_err(hdmi->dev, "Unable to get HDMI pclk clk\n"); + DRM_DEV_ERROR(hdmi->dev, "Unable to get HDMI pclk clk\n"); return PTR_ERR(hdmi->pclk); } ret = clk_prepare_enable(hdmi->pclk); if (ret) { - dev_err(hdmi->dev, "Cannot enable HDMI pclk clock: %d\n", ret); + DRM_DEV_ERROR(hdmi->dev, + "Cannot enable HDMI pclk clock: %d\n", ret); return ret; } diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index ff3d0f5..76d63de 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -58,7 +58,7 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev, ret = iommu_attach_device(private->domain, dev); if (ret) { - dev_err(dev, "Failed to attach iommu device\n"); + DRM_DEV_ERROR(dev, "Failed to attach iommu device\n"); return ret; } @@ -373,8 +373,9 @@ static int rockchip_drm_platform_of_probe(struct device *dev) iommu = of_parse_phandle(port->parent, "iommus", 0); if (!iommu || !of_device_is_available(iommu->parent)) { - dev_dbg(dev, "no iommu attached for %pOF, using non-iommu buffers\n", - port->parent); + DRM_DEV_DEBUG(dev, + "no iommu attached for %pOF, using non-iommu buffers\n", + port->parent); /* * if there is a crtc not support iommu, force set all * crtc use non-iommu buffer. @@ -389,12 +390,13 @@ static int rockchip_drm_platform_of_probe(struct device *dev) } if (i == 0) { - dev_err(dev, "missing 'ports' property\n"); + DRM_DEV_ERROR(dev, "missing 'ports' property\n"); return -ENODEV; } if (!found) { - dev_err(dev, "No available vop found for display-subsystem.\n"); + DRM_DEV_ERROR(dev, + "No available vop found for display-subsystem.\n"); return -ENODEV; } @@ -453,6 +455,8 @@ static int __init rockchip_drm_init(void) num_rockchip_sub_drivers = 0; ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_DRM_ROCKCHIP); + ADD_ROCKCHIP_SUB_DRIVER(rockchip_lvds_driver, + CONFIG_ROCKCHIP_LVDS); ADD_ROCKCHIP_SUB_DRIVER(rockchip_dp_driver, CONFIG_ROCKCHIP_ANALOGIX_DP); ADD_ROCKCHIP_SUB_DRIVER(cdn_dp_driver, CONFIG_ROCKCHIP_CDN_DP); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index c7e96b8..498dfbc 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -69,5 +69,6 @@ extern struct platform_driver dw_hdmi_rockchip_pltfm_driver; extern struct platform_driver dw_mipi_dsi_driver; extern struct platform_driver inno_hdmi_driver; extern struct platform_driver rockchip_dp_driver; +extern struct platform_driver rockchip_lvds_driver; extern struct platform_driver vop_platform_driver; #endif /* _ROCKCHIP_DRM_DRV_H_ */ diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c index 7077304..cd2ace0 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c @@ -100,8 +100,9 @@ rockchip_fb_alloc(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode_cm ret = drm_framebuffer_init(dev, &rockchip_fb->fb, &rockchip_drm_fb_funcs); if (ret) { - dev_err(dev->dev, "Failed to initialize framebuffer: %d\n", - ret); + DRM_DEV_ERROR(dev->dev, + "Failed to initialize framebuffer: %d\n", + ret); kfree(rockchip_fb); return ERR_PTR(ret); } @@ -134,7 +135,8 @@ rockchip_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[i]); if (!obj) { - dev_err(dev->dev, "Failed to lookup GEM object\n"); + DRM_DEV_ERROR(dev->dev, + "Failed to lookup GEM object\n"); ret = -ENXIO; goto err_gem_object_unreference; } diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c b/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c index 724579e..e665055 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c @@ -76,7 +76,7 @@ static int rockchip_drm_fbdev_create(struct drm_fb_helper *helper, fbi = drm_fb_helper_alloc_fbi(helper); if (IS_ERR(fbi)) { - dev_err(dev->dev, "Failed to create framebuffer info.\n"); + DRM_DEV_ERROR(dev->dev, "Failed to create framebuffer info.\n"); ret = PTR_ERR(fbi); goto out; } @@ -84,7 +84,8 @@ static int rockchip_drm_fbdev_create(struct drm_fb_helper *helper, helper->fb = rockchip_drm_framebuffer_init(dev, &mode_cmd, private->fbdev_bo); if (IS_ERR(helper->fb)) { - dev_err(dev->dev, "Failed to allocate DRM framebuffer.\n"); + DRM_DEV_ERROR(dev->dev, + "Failed to allocate DRM framebuffer.\n"); ret = PTR_ERR(helper->fb); goto out; } @@ -138,21 +139,24 @@ int rockchip_drm_fbdev_init(struct drm_device *dev) ret = drm_fb_helper_init(dev, helper, ROCKCHIP_MAX_CONNECTOR); if (ret < 0) { - dev_err(dev->dev, "Failed to initialize drm fb helper - %d.\n", - ret); + DRM_DEV_ERROR(dev->dev, + "Failed to initialize drm fb helper - %d.\n", + ret); return ret; } ret = drm_fb_helper_single_add_all_connectors(helper); if (ret < 0) { - dev_err(dev->dev, "Failed to add connectors - %d.\n", ret); + DRM_DEV_ERROR(dev->dev, + "Failed to add connectors - %d.\n", ret); goto err_drm_fb_helper_fini; } ret = drm_fb_helper_initial_config(helper, PREFERRED_BPP); if (ret < 0) { - dev_err(dev->dev, "Failed to set initial hw config - %d.\n", - ret); + DRM_DEV_ERROR(dev->dev, + "Failed to set initial hw config - %d.\n", + ret); goto err_drm_fb_helper_fini; } diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index bf9ed0e..19128b4 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -160,7 +160,7 @@ static void vop_reg_set(struct vop *vop, const struct vop_reg *reg, int offset, mask, shift; if (!reg || !reg->mask) { - dev_dbg(vop->dev, "Warning: not support %s\n", reg_name); + DRM_DEV_DEBUG(vop->dev, "Warning: not support %s\n", reg_name); return; } @@ -499,7 +499,7 @@ static int vop_enable(struct drm_crtc *crtc) ret = pm_runtime_get_sync(vop->dev); if (ret < 0) { - dev_err(vop->dev, "failed to get pm runtime: %d\n", ret); + DRM_DEV_ERROR(vop->dev, "failed to get pm runtime: %d\n", ret); return ret; } @@ -523,7 +523,8 @@ static int vop_enable(struct drm_crtc *crtc) */ ret = rockchip_drm_dma_attach_device(vop->drm_dev, vop->dev); if (ret) { - dev_err(vop->dev, "failed to attach dma mapping, %d\n", ret); + DRM_DEV_ERROR(vop->dev, + "failed to attach dma mapping, %d\n", ret); goto err_disable_aclk; } @@ -1361,42 +1362,42 @@ static int vop_initial(struct vop *vop) vop->hclk = devm_clk_get(vop->dev, "hclk_vop"); if (IS_ERR(vop->hclk)) { - dev_err(vop->dev, "failed to get hclk source\n"); + DRM_DEV_ERROR(vop->dev, "failed to get hclk source\n"); return PTR_ERR(vop->hclk); } vop->aclk = devm_clk_get(vop->dev, "aclk_vop"); if (IS_ERR(vop->aclk)) { - dev_err(vop->dev, "failed to get aclk source\n"); + DRM_DEV_ERROR(vop->dev, "failed to get aclk source\n"); return PTR_ERR(vop->aclk); } vop->dclk = devm_clk_get(vop->dev, "dclk_vop"); if (IS_ERR(vop->dclk)) { - dev_err(vop->dev, "failed to get dclk source\n"); + DRM_DEV_ERROR(vop->dev, "failed to get dclk source\n"); return PTR_ERR(vop->dclk); } ret = pm_runtime_get_sync(vop->dev); if (ret < 0) { - dev_err(vop->dev, "failed to get pm runtime: %d\n", ret); + DRM_DEV_ERROR(vop->dev, "failed to get pm runtime: %d\n", ret); return ret; } ret = clk_prepare(vop->dclk); if (ret < 0) { - dev_err(vop->dev, "failed to prepare dclk\n"); + DRM_DEV_ERROR(vop->dev, "failed to prepare dclk\n"); goto err_put_pm_runtime; } /* Enable both the hclk and aclk to setup the vop */ ret = clk_prepare_enable(vop->hclk); if (ret < 0) { - dev_err(vop->dev, "failed to prepare/enable hclk\n"); + DRM_DEV_ERROR(vop->dev, "failed to prepare/enable hclk\n"); goto err_unprepare_dclk; } ret = clk_prepare_enable(vop->aclk); if (ret < 0) { - dev_err(vop->dev, "failed to prepare/enable aclk\n"); + DRM_DEV_ERROR(vop->dev, "failed to prepare/enable aclk\n"); goto err_disable_hclk; } @@ -1405,7 +1406,7 @@ static int vop_initial(struct vop *vop) */ ahb_rst = devm_reset_control_get(vop->dev, "ahb"); if (IS_ERR(ahb_rst)) { - dev_err(vop->dev, "failed to get ahb reset\n"); + DRM_DEV_ERROR(vop->dev, "failed to get ahb reset\n"); ret = PTR_ERR(ahb_rst); goto err_disable_aclk; } @@ -1434,7 +1435,7 @@ static int vop_initial(struct vop *vop) */ vop->dclk_rst = devm_reset_control_get(vop->dev, "dclk"); if (IS_ERR(vop->dclk_rst)) { - dev_err(vop->dev, "failed to get dclk reset\n"); + DRM_DEV_ERROR(vop->dev, "failed to get dclk reset\n"); ret = PTR_ERR(vop->dclk_rst); goto err_disable_aclk; } @@ -1511,7 +1512,7 @@ int rockchip_drm_wait_vact_end(struct drm_crtc *crtc, unsigned int mstimeout) vop_line_flag_irq_disable(vop); if (jiffies_left == 0) { - dev_err(vop->dev, "Timeout waiting for IRQ\n"); + DRM_DEV_ERROR(vop->dev, "Timeout waiting for IRQ\n"); return -ETIMEDOUT; } @@ -1558,7 +1559,7 @@ static int vop_bind(struct device *dev, struct device *master, void *data) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(dev, "cannot find irq for vop\n"); + DRM_DEV_ERROR(dev, "cannot find irq for vop\n"); return irq; } vop->irq = (unsigned int)irq; @@ -1584,7 +1585,8 @@ static int vop_bind(struct device *dev, struct device *master, void *data) ret = vop_initial(vop); if (ret < 0) { - dev_err(&pdev->dev, "cannot initial vop dev - err %d\n", ret); + DRM_DEV_ERROR(&pdev->dev, + "cannot initial vop dev - err %d\n", ret); goto err_disable_pm_runtime; } diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c new file mode 100644 index 0000000..c5fbe53 --- /dev/null +++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c @@ -0,0 +1,581 @@ +/* + * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd + * Author: + * Mark Yao <mark.yao@rock-chips.com> + * Sandy Huang <hjc@rock-chips.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <drm/drmP.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_crtc_helper.h> +#include <drm/drm_dp_helper.h> +#include <drm/drm_panel.h> +#include <drm/drm_of.h> + +#include <linux/component.h> +#include <linux/clk.h> +#include <linux/mfd/syscon.h> +#include <linux/of_graph.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> +#include <linux/reset.h> + +#include "rockchip_drm_drv.h" +#include "rockchip_drm_vop.h" +#include "rockchip_lvds.h" + +#define DISPLAY_OUTPUT_RGB 0 +#define DISPLAY_OUTPUT_LVDS 1 +#define DISPLAY_OUTPUT_DUAL_LVDS 2 + +#define connector_to_lvds(c) \ + container_of(c, struct rockchip_lvds, connector) + +#define encoder_to_lvds(c) \ + container_of(c, struct rockchip_lvds, encoder) + +/** + * rockchip_lvds_soc_data - rockchip lvds Soc private data + * @ch1_offset: lvds channel 1 registe offset + * grf_soc_con6: general registe offset for LVDS contrl + * grf_soc_con7: general registe offset for LVDS contrl + * has_vop_sel: to indicate whether need to choose from different VOP. + */ +struct rockchip_lvds_soc_data { + u32 ch1_offset; + int grf_soc_con6; + int grf_soc_con7; + bool has_vop_sel; +}; + +struct rockchip_lvds { + struct device *dev; + void __iomem *regs; + struct regmap *grf; + struct clk *pclk; + const struct rockchip_lvds_soc_data *soc_data; + int output; /* rgb lvds or dual lvds output */ + int format; /* vesa or jeida format */ + struct drm_device *drm_dev; + struct drm_panel *panel; + struct drm_bridge *bridge; + struct drm_connector connector; + struct drm_encoder encoder; + struct dev_pin_info *pins; +}; + +static inline void lvds_writel(struct rockchip_lvds *lvds, u32 offset, u32 val) +{ + writel_relaxed(val, lvds->regs + offset); + if (lvds->output == DISPLAY_OUTPUT_LVDS) + return; + writel_relaxed(val, lvds->regs + offset + lvds->soc_data->ch1_offset); +} + +static inline int lvds_name_to_format(const char *s) +{ + if (strncmp(s, "jeida-18", 8) == 0) + return LVDS_JEIDA_18; + else if (strncmp(s, "jeida-24", 8) == 0) + return LVDS_JEIDA_24; + else if (strncmp(s, "vesa-24", 7) == 0) + return LVDS_VESA_24; + + return -EINVAL; +} + +static inline int lvds_name_to_output(const char *s) +{ + if (strncmp(s, "rgb", 3) == 0) + return DISPLAY_OUTPUT_RGB; + else if (strncmp(s, "lvds", 4) == 0) + return DISPLAY_OUTPUT_LVDS; + else if (strncmp(s, "duallvds", 8) == 0) + return DISPLAY_OUTPUT_DUAL_LVDS; + + return -EINVAL; +} + +static int rockchip_lvds_poweron(struct rockchip_lvds *lvds) +{ + int ret; + u32 val; + + ret = clk_enable(lvds->pclk); + if (ret < 0) { + DRM_DEV_ERROR(lvds->dev, "failed to enable lvds pclk %d\n", ret); + return ret; + } + ret = pm_runtime_get_sync(lvds->dev); + if (ret < 0) { + DRM_DEV_ERROR(lvds->dev, "failed to get pm runtime: %d\n", ret); + clk_disable(lvds->pclk); + return ret; + } + val = RK3288_LVDS_CH0_REG0_LANE4_EN | RK3288_LVDS_CH0_REG0_LANE3_EN | + RK3288_LVDS_CH0_REG0_LANE2_EN | RK3288_LVDS_CH0_REG0_LANE1_EN | + RK3288_LVDS_CH0_REG0_LANE0_EN; + if (lvds->output == DISPLAY_OUTPUT_RGB) { + val |= RK3288_LVDS_CH0_REG0_TTL_EN | + RK3288_LVDS_CH0_REG0_LANECK_EN; + lvds_writel(lvds, RK3288_LVDS_CH0_REG0, val); + lvds_writel(lvds, RK3288_LVDS_CH0_REG2, + RK3288_LVDS_PLL_FBDIV_REG2(0x46)); + lvds_writel(lvds, RK3288_LVDS_CH0_REG4, + RK3288_LVDS_CH0_REG4_LANECK_TTL_MODE | + RK3288_LVDS_CH0_REG4_LANE4_TTL_MODE | + RK3288_LVDS_CH0_REG4_LANE3_TTL_MODE | + RK3288_LVDS_CH0_REG4_LANE2_TTL_MODE | + RK3288_LVDS_CH0_REG4_LANE1_TTL_MODE | + RK3288_LVDS_CH0_REG4_LANE0_TTL_MODE); + lvds_writel(lvds, RK3288_LVDS_CH0_REG5, + RK3288_LVDS_CH0_REG5_LANECK_TTL_DATA | + RK3288_LVDS_CH0_REG5_LANE4_TTL_DATA | + RK3288_LVDS_CH0_REG5_LANE3_TTL_DATA | + RK3288_LVDS_CH0_REG5_LANE2_TTL_DATA | + RK3288_LVDS_CH0_REG5_LANE1_TTL_DATA | + RK3288_LVDS_CH0_REG5_LANE0_TTL_DATA); + } else { + val |= RK3288_LVDS_CH0_REG0_LVDS_EN | + RK3288_LVDS_CH0_REG0_LANECK_EN; + lvds_writel(lvds, RK3288_LVDS_CH0_REG0, val); + lvds_writel(lvds, RK3288_LVDS_CH0_REG1, + RK3288_LVDS_CH0_REG1_LANECK_BIAS | + RK3288_LVDS_CH0_REG1_LANE4_BIAS | + RK3288_LVDS_CH0_REG1_LANE3_BIAS | + RK3288_LVDS_CH0_REG1_LANE2_BIAS | + RK3288_LVDS_CH0_REG1_LANE1_BIAS | + RK3288_LVDS_CH0_REG1_LANE0_BIAS); + lvds_writel(lvds, RK3288_LVDS_CH0_REG2, + RK3288_LVDS_CH0_REG2_RESERVE_ON | + RK3288_LVDS_CH0_REG2_LANECK_LVDS_MODE | + RK3288_LVDS_CH0_REG2_LANE4_LVDS_MODE | + RK3288_LVDS_CH0_REG2_LANE3_LVDS_MODE | + RK3288_LVDS_CH0_REG2_LANE2_LVDS_MODE | + RK3288_LVDS_CH0_REG2_LANE1_LVDS_MODE | + RK3288_LVDS_CH0_REG2_LANE0_LVDS_MODE | + RK3288_LVDS_PLL_FBDIV_REG2(0x46)); + lvds_writel(lvds, RK3288_LVDS_CH0_REG4, 0x00); + lvds_writel(lvds, RK3288_LVDS_CH0_REG5, 0x00); + } + lvds_writel(lvds, RK3288_LVDS_CH0_REG3, RK3288_LVDS_PLL_FBDIV_REG3(0x46)); + lvds_writel(lvds, RK3288_LVDS_CH0_REGD, RK3288_LVDS_PLL_PREDIV_REGD(0x0a)); + lvds_writel(lvds, RK3288_LVDS_CH0_REG20, RK3288_LVDS_CH0_REG20_LSB); + + lvds_writel(lvds, RK3288_LVDS_CFG_REGC, RK3288_LVDS_CFG_REGC_PLL_ENABLE); + lvds_writel(lvds, RK3288_LVDS_CFG_REG21, RK3288_LVDS_CFG_REG21_TX_ENABLE); + + return 0; +} + +static void rockchip_lvds_poweroff(struct rockchip_lvds *lvds) +{ + int ret; + u32 val; + + lvds_writel(lvds, RK3288_LVDS_CFG_REG21, RK3288_LVDS_CFG_REG21_TX_ENABLE); + lvds_writel(lvds, RK3288_LVDS_CFG_REGC, RK3288_LVDS_CFG_REGC_PLL_ENABLE); + val = LVDS_DUAL | LVDS_TTL_EN | LVDS_CH0_EN | LVDS_CH1_EN | LVDS_PWRDN; + val |= val << 16; + ret = regmap_write(lvds->grf, lvds->soc_data->grf_soc_con7, val); + if (ret != 0) + DRM_DEV_ERROR(lvds->dev, "Could not write to GRF: %d\n", ret); + + pm_runtime_put(lvds->dev); + clk_disable(lvds->pclk); +} + +static const struct drm_connector_funcs rockchip_lvds_connector_funcs = { + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = drm_connector_cleanup, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +static int rockchip_lvds_connector_get_modes(struct drm_connector *connector) +{ + struct rockchip_lvds *lvds = connector_to_lvds(connector); + struct drm_panel *panel = lvds->panel; + + return drm_panel_get_modes(panel); +} + +static const +struct drm_connector_helper_funcs rockchip_lvds_connector_helper_funcs = { + .get_modes = rockchip_lvds_connector_get_modes, +}; + +static void rockchip_lvds_grf_config(struct drm_encoder *encoder, + struct drm_display_mode *mode) +{ + struct rockchip_lvds *lvds = encoder_to_lvds(encoder); + u8 pin_hsync = (mode->flags & DRM_MODE_FLAG_PHSYNC) ? 1 : 0; + u8 pin_dclk = (mode->flags & DRM_MODE_FLAG_PCSYNC) ? 1 : 0; + u32 val; + int ret; + + /* iomux to LCD data/sync mode */ + if (lvds->output == DISPLAY_OUTPUT_RGB) + if (lvds->pins && !IS_ERR(lvds->pins->default_state)) + pinctrl_select_state(lvds->pins->p, + lvds->pins->default_state); + val = lvds->format | LVDS_CH0_EN; + if (lvds->output == DISPLAY_OUTPUT_RGB) + val |= LVDS_TTL_EN | LVDS_CH1_EN; + else if (lvds->output == DISPLAY_OUTPUT_DUAL_LVDS) + val |= LVDS_DUAL | LVDS_CH1_EN; + + if ((mode->htotal - mode->hsync_start) & 0x01) + val |= LVDS_START_PHASE_RST_1; + + val |= (pin_dclk << 8) | (pin_hsync << 9); + val |= (0xffff << 16); + ret = regmap_write(lvds->grf, lvds->soc_data->grf_soc_con7, val); + if (ret != 0) { + DRM_DEV_ERROR(lvds->dev, "Could not write to GRF: %d\n", ret); + return; + } +} + +static int rockchip_lvds_set_vop_source(struct rockchip_lvds *lvds, + struct drm_encoder *encoder) +{ + u32 val; + int ret; + + if (!lvds->soc_data->has_vop_sel) + return 0; + + ret = drm_of_encoder_active_endpoint_id(lvds->dev->of_node, encoder); + if (ret < 0) + return ret; + + val = RK3288_LVDS_SOC_CON6_SEL_VOP_LIT << 16; + if (ret) + val |= RK3288_LVDS_SOC_CON6_SEL_VOP_LIT; + + ret = regmap_write(lvds->grf, lvds->soc_data->grf_soc_con6, val); + if (ret < 0) + return ret; + + return 0; +} + +static int +rockchip_lvds_encoder_atomic_check(struct drm_encoder *encoder, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); + + s->output_mode = ROCKCHIP_OUT_MODE_P888; + s->output_type = DRM_MODE_CONNECTOR_LVDS; + + return 0; +} + +static void rockchip_lvds_encoder_enable(struct drm_encoder *encoder) +{ + struct rockchip_lvds *lvds = encoder_to_lvds(encoder); + struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; + int ret; + + drm_panel_prepare(lvds->panel); + ret = rockchip_lvds_poweron(lvds); + if (ret < 0) { + DRM_DEV_ERROR(lvds->dev, "failed to power on lvds: %d\n", ret); + drm_panel_unprepare(lvds->panel); + } + rockchip_lvds_grf_config(encoder, mode); + rockchip_lvds_set_vop_source(lvds, encoder); + drm_panel_enable(lvds->panel); +} + +static void rockchip_lvds_encoder_disable(struct drm_encoder *encoder) +{ + struct rockchip_lvds *lvds = encoder_to_lvds(encoder); + + drm_panel_disable(lvds->panel); + rockchip_lvds_poweroff(lvds); + drm_panel_unprepare(lvds->panel); +} + +static const +struct drm_encoder_helper_funcs rockchip_lvds_encoder_helper_funcs = { + .enable = rockchip_lvds_encoder_enable, + .disable = rockchip_lvds_encoder_disable, + .atomic_check = rockchip_lvds_encoder_atomic_check, +}; + +static const struct drm_encoder_funcs rockchip_lvds_encoder_funcs = { + .destroy = drm_encoder_cleanup, +}; + +static const struct rockchip_lvds_soc_data rk3288_lvds_data = { + .ch1_offset = 0x100, + .grf_soc_con6 = 0x025c, + .grf_soc_con7 = 0x0260, + .has_vop_sel = true, +}; + +static const struct of_device_id rockchip_lvds_dt_ids[] = { + { + .compatible = "rockchip,rk3288-lvds", + .data = &rk3288_lvds_data + }, + {} +}; +MODULE_DEVICE_TABLE(of, rockchip_lvds_dt_ids); + +static int rockchip_lvds_bind(struct device *dev, struct device *master, + void *data) +{ + struct rockchip_lvds *lvds = dev_get_drvdata(dev); + struct drm_device *drm_dev = data; + struct drm_encoder *encoder; + struct drm_connector *connector; + struct device_node *remote = NULL; + struct device_node *port, *endpoint; + int ret; + const char *name; + u32 endpoint_id; + + lvds->drm_dev = drm_dev; + port = of_graph_get_port_by_id(dev->of_node, 1); + if (!port) { + DRM_DEV_ERROR(dev, + "can't found port point, please init lvds panel port!\n"); + return -EINVAL; + } + for_each_child_of_node(port, endpoint) { + of_property_read_u32(endpoint, "reg", &endpoint_id); + ret = drm_of_find_panel_or_bridge(dev->of_node, 1, endpoint_id, + &lvds->panel, &lvds->bridge); + if (!ret) + break; + } + if (ret) { + DRM_DEV_ERROR(dev, "failed to find panel and bridge node\n"); + ret = -EPROBE_DEFER; + goto err_put_port; + } + if (lvds->panel) + remote = lvds->panel->dev->of_node; + else + remote = lvds->bridge->of_node; + if (of_property_read_string(dev->of_node, "rockchip,output", &name)) + /* default set it as output rgb */ + lvds->output = DISPLAY_OUTPUT_RGB; + else + lvds->output = lvds_name_to_output(name); + + if (lvds->output < 0) { + DRM_DEV_ERROR(dev, "invalid output type [%s]\n", name); + ret = lvds->output; + goto err_put_remote; + } + + if (of_property_read_string(remote, "data-mapping", &name)) + /* default set it as format vesa 18 */ + lvds->format = LVDS_VESA_18; + else + lvds->format = lvds_name_to_format(name); + + if (lvds->format < 0) { + DRM_DEV_ERROR(dev, "invalid data-mapping format [%s]\n", name); + ret = lvds->format; + goto err_put_remote; + } + + encoder = &lvds->encoder; + encoder->possible_crtcs = drm_of_find_possible_crtcs(drm_dev, + dev->of_node); + + ret = drm_encoder_init(drm_dev, encoder, &rockchip_lvds_encoder_funcs, + DRM_MODE_ENCODER_LVDS, NULL); + if (ret < 0) { + DRM_DEV_ERROR(drm_dev->dev, + "failed to initialize encoder: %d\n", ret); + goto err_put_remote; + } + + drm_encoder_helper_add(encoder, &rockchip_lvds_encoder_helper_funcs); + + if (lvds->panel) { + connector = &lvds->connector; + connector->dpms = DRM_MODE_DPMS_OFF; + ret = drm_connector_init(drm_dev, connector, + &rockchip_lvds_connector_funcs, + DRM_MODE_CONNECTOR_LVDS); + if (ret < 0) { + DRM_DEV_ERROR(drm_dev->dev, + "failed to initialize connector: %d\n", ret); + goto err_free_encoder; + } + + drm_connector_helper_add(connector, + &rockchip_lvds_connector_helper_funcs); + + ret = drm_mode_connector_attach_encoder(connector, encoder); + if (ret < 0) { + DRM_DEV_ERROR(drm_dev->dev, + "failed to attach encoder: %d\n", ret); + goto err_free_connector; + } + + ret = drm_panel_attach(lvds->panel, connector); + if (ret < 0) { + DRM_DEV_ERROR(drm_dev->dev, + "failed to attach panel: %d\n", ret); + goto err_free_connector; + } + } else { + lvds->bridge->encoder = encoder; + ret = drm_bridge_attach(encoder, lvds->bridge, NULL); + if (ret) { + DRM_DEV_ERROR(drm_dev->dev, + "failed to attach bridge: %d\n", ret); + goto err_free_encoder; + } + encoder->bridge = lvds->bridge; + } + + pm_runtime_enable(dev); + of_node_put(remote); + of_node_put(port); + + return 0; + +err_free_connector: + drm_connector_cleanup(connector); +err_free_encoder: + drm_encoder_cleanup(encoder); +err_put_remote: + of_node_put(remote); +err_put_port: + of_node_put(port); + + return ret; +} + +static void rockchip_lvds_unbind(struct device *dev, struct device *master, + void *data) +{ + struct rockchip_lvds *lvds = dev_get_drvdata(dev); + + rockchip_lvds_encoder_disable(&lvds->encoder); + if (lvds->panel) + drm_panel_detach(lvds->panel); + pm_runtime_disable(dev); + drm_connector_cleanup(&lvds->connector); + drm_encoder_cleanup(&lvds->encoder); +} + +static const struct component_ops rockchip_lvds_component_ops = { + .bind = rockchip_lvds_bind, + .unbind = rockchip_lvds_unbind, +}; + +static int rockchip_lvds_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct rockchip_lvds *lvds; + const struct of_device_id *match; + struct resource *res; + int ret; + + if (!dev->of_node) + return -ENODEV; + + lvds = devm_kzalloc(&pdev->dev, sizeof(*lvds), GFP_KERNEL); + if (!lvds) + return -ENOMEM; + + lvds->dev = dev; + match = of_match_node(rockchip_lvds_dt_ids, dev->of_node); + if (!match) + return -ENODEV; + lvds->soc_data = match->data; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + lvds->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(lvds->regs)) + return PTR_ERR(lvds->regs); + + lvds->pclk = devm_clk_get(&pdev->dev, "pclk_lvds"); + if (IS_ERR(lvds->pclk)) { + DRM_DEV_ERROR(dev, "could not get pclk_lvds\n"); + return PTR_ERR(lvds->pclk); + } + + lvds->pins = devm_kzalloc(lvds->dev, sizeof(*lvds->pins), + GFP_KERNEL); + if (!lvds->pins) + return -ENOMEM; + + lvds->pins->p = devm_pinctrl_get(lvds->dev); + if (IS_ERR(lvds->pins->p)) { + DRM_DEV_ERROR(dev, "no pinctrl handle\n"); + devm_kfree(lvds->dev, lvds->pins); + lvds->pins = NULL; + } else { + lvds->pins->default_state = + pinctrl_lookup_state(lvds->pins->p, "lcdc"); + if (IS_ERR(lvds->pins->default_state)) { + DRM_DEV_ERROR(dev, "no default pinctrl state\n"); + devm_kfree(lvds->dev, lvds->pins); + lvds->pins = NULL; + } + } + + lvds->grf = syscon_regmap_lookup_by_phandle(dev->of_node, + "rockchip,grf"); + if (IS_ERR(lvds->grf)) { + DRM_DEV_ERROR(dev, "missing rockchip,grf property\n"); + return PTR_ERR(lvds->grf); + } + + dev_set_drvdata(dev, lvds); + + ret = clk_prepare(lvds->pclk); + if (ret < 0) { + DRM_DEV_ERROR(dev, "failed to prepare pclk_lvds\n"); + return ret; + } + ret = component_add(&pdev->dev, &rockchip_lvds_component_ops); + if (ret < 0) { + DRM_DEV_ERROR(dev, "failed to add component\n"); + clk_unprepare(lvds->pclk); + } + + return ret; +} + +static int rockchip_lvds_remove(struct platform_device *pdev) +{ + struct rockchip_lvds *lvds = dev_get_drvdata(&pdev->dev); + + component_del(&pdev->dev, &rockchip_lvds_component_ops); + clk_unprepare(lvds->pclk); + + return 0; +} + +struct platform_driver rockchip_lvds_driver = { + .probe = rockchip_lvds_probe, + .remove = rockchip_lvds_remove, + .driver = { + .name = "rockchip-lvds", + .of_match_table = of_match_ptr(rockchip_lvds_dt_ids), + }, +}; diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.h b/drivers/gpu/drm/rockchip/rockchip_lvds.h new file mode 100644 index 0000000..15810b7 --- /dev/null +++ b/drivers/gpu/drm/rockchip/rockchip_lvds.h @@ -0,0 +1,114 @@ +/* + * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd + * Author: + * Sandy Huang <hjc@rock-chips.com> + * Mark Yao <mark.yao@rock-chips.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _ROCKCHIP_LVDS_ +#define _ROCKCHIP_LVDS_ + +#define RK3288_LVDS_CH0_REG0 0x00 +#define RK3288_LVDS_CH0_REG0_LVDS_EN BIT(7) +#define RK3288_LVDS_CH0_REG0_TTL_EN BIT(6) +#define RK3288_LVDS_CH0_REG0_LANECK_EN BIT(5) +#define RK3288_LVDS_CH0_REG0_LANE4_EN BIT(4) +#define RK3288_LVDS_CH0_REG0_LANE3_EN BIT(3) +#define RK3288_LVDS_CH0_REG0_LANE2_EN BIT(2) +#define RK3288_LVDS_CH0_REG0_LANE1_EN BIT(1) +#define RK3288_LVDS_CH0_REG0_LANE0_EN BIT(0) + +#define RK3288_LVDS_CH0_REG1 0x04 +#define RK3288_LVDS_CH0_REG1_LANECK_BIAS BIT(5) +#define RK3288_LVDS_CH0_REG1_LANE4_BIAS BIT(4) +#define RK3288_LVDS_CH0_REG1_LANE3_BIAS BIT(3) +#define RK3288_LVDS_CH0_REG1_LANE2_BIAS BIT(2) +#define RK3288_LVDS_CH0_REG1_LANE1_BIAS BIT(1) +#define RK3288_LVDS_CH0_REG1_LANE0_BIAS BIT(0) + +#define RK3288_LVDS_CH0_REG2 0x08 +#define RK3288_LVDS_CH0_REG2_RESERVE_ON BIT(7) +#define RK3288_LVDS_CH0_REG2_LANECK_LVDS_MODE BIT(6) +#define RK3288_LVDS_CH0_REG2_LANE4_LVDS_MODE BIT(5) +#define RK3288_LVDS_CH0_REG2_LANE3_LVDS_MODE BIT(4) +#define RK3288_LVDS_CH0_REG2_LANE2_LVDS_MODE BIT(3) +#define RK3288_LVDS_CH0_REG2_LANE1_LVDS_MODE BIT(2) +#define RK3288_LVDS_CH0_REG2_LANE0_LVDS_MODE BIT(1) +#define RK3288_LVDS_CH0_REG2_PLL_FBDIV8 BIT(0) + +#define RK3288_LVDS_CH0_REG3 0x0c +#define RK3288_LVDS_CH0_REG3_PLL_FBDIV_MASK 0xff + +#define RK3288_LVDS_CH0_REG4 0x10 +#define RK3288_LVDS_CH0_REG4_LANECK_TTL_MODE BIT(5) +#define RK3288_LVDS_CH0_REG4_LANE4_TTL_MODE BIT(4) +#define RK3288_LVDS_CH0_REG4_LANE3_TTL_MODE BIT(3) +#define RK3288_LVDS_CH0_REG4_LANE2_TTL_MODE BIT(2) +#define RK3288_LVDS_CH0_REG4_LANE1_TTL_MODE BIT(1) +#define RK3288_LVDS_CH0_REG4_LANE0_TTL_MODE BIT(0) + +#define RK3288_LVDS_CH0_REG5 0x14 +#define RK3288_LVDS_CH0_REG5_LANECK_TTL_DATA BIT(5) +#define RK3288_LVDS_CH0_REG5_LANE4_TTL_DATA BIT(4) +#define RK3288_LVDS_CH0_REG5_LANE3_TTL_DATA BIT(3) +#define RK3288_LVDS_CH0_REG5_LANE2_TTL_DATA BIT(2) +#define RK3288_LVDS_CH0_REG5_LANE1_TTL_DATA BIT(1) +#define RK3288_LVDS_CH0_REG5_LANE0_TTL_DATA BIT(0) + +#define RK3288_LVDS_CFG_REGC 0x30 +#define RK3288_LVDS_CFG_REGC_PLL_ENABLE 0x00 +#define RK3288_LVDS_CFG_REGC_PLL_DISABLE 0xff + +#define RK3288_LVDS_CH0_REGD 0x34 +#define RK3288_LVDS_CH0_REGD_PLL_PREDIV_MASK 0x1f + +#define RK3288_LVDS_CH0_REG20 0x80 +#define RK3288_LVDS_CH0_REG20_MSB 0x45 +#define RK3288_LVDS_CH0_REG20_LSB 0x44 + +#define RK3288_LVDS_CFG_REG21 0x84 +#define RK3288_LVDS_CFG_REG21_TX_ENABLE 0x92 +#define RK3288_LVDS_CFG_REG21_TX_DISABLE 0x00 +#define RK3288_LVDS_CH1_OFFSET 0x100 + +/* fbdiv value is split over 2 registers, with bit8 in reg2 */ +#define RK3288_LVDS_PLL_FBDIV_REG2(_fbd) \ + (_fbd & BIT(8) ? RK3288_LVDS_CH0_REG2_PLL_FBDIV8 : 0) +#define RK3288_LVDS_PLL_FBDIV_REG3(_fbd) \ + (_fbd & RK3288_LVDS_CH0_REG3_PLL_FBDIV_MASK) +#define RK3288_LVDS_PLL_PREDIV_REGD(_pd) \ + (_pd & RK3288_LVDS_CH0_REGD_PLL_PREDIV_MASK) + +#define RK3288_LVDS_SOC_CON6_SEL_VOP_LIT BIT(3) + +#define LVDS_FMT_MASK (0x07 << 16) +#define LVDS_MSB BIT(3) +#define LVDS_DUAL BIT(4) +#define LVDS_FMT_1 BIT(5) +#define LVDS_TTL_EN BIT(6) +#define LVDS_START_PHASE_RST_1 BIT(7) +#define LVDS_DCLK_INV BIT(8) +#define LVDS_CH0_EN BIT(11) +#define LVDS_CH1_EN BIT(12) +#define LVDS_PWRDN BIT(15) + +#define LVDS_24BIT (0 << 1) +#define LVDS_18BIT (1 << 1) +#define LVDS_FORMAT_VESA (0 << 0) +#define LVDS_FORMAT_JEIDA (1 << 0) + +#define LVDS_VESA_24 0 +#define LVDS_JEIDA_24 1 +#define LVDS_VESA_18 2 +#define LVDS_JEIDA_18 3 + +#endif /* _ROCKCHIP_LVDS_ */ diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index 94de7b9..4a39049 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c @@ -533,7 +533,7 @@ static int vop_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; if (!dev->of_node) { - dev_err(dev, "can't find vop devices\n"); + DRM_DEV_ERROR(dev, "can't find vop devices\n"); return -ENODEV; } diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c index 1700c54..9e93431 100644 --- a/drivers/gpu/drm/sti/sti_drv.c +++ b/drivers/gpu/drm/sti/sti_drv.c @@ -16,6 +16,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_of.h> @@ -145,7 +146,7 @@ static void sti_output_poll_changed(struct drm_device *ddev) } static const struct drm_mode_config_funcs sti_mode_config_funcs = { - .fb_create = drm_fb_cma_create, + .fb_create = drm_gem_fb_create, .output_poll_changed = sti_output_poll_changed, .atomic_check = sti_atomic_check, .atomic_commit = drm_atomic_helper_commit, diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c index 852bf22..83314ae 100644 --- a/drivers/gpu/drm/sti/sti_dvo.c +++ b/drivers/gpu/drm/sti/sti_dvo.c @@ -463,11 +463,7 @@ static int sti_dvo_bind(struct device *dev, struct device *master, void *data) bridge->driver_private = dvo; bridge->funcs = &sti_dvo_bridge_funcs; bridge->of_node = dvo->dev.of_node; - err = drm_bridge_add(bridge); - if (err) { - DRM_ERROR("Failed to add bridge\n"); - return err; - } + drm_bridge_add(bridge); err = drm_bridge_attach(encoder, bridge, NULL); if (err) { diff --git a/drivers/gpu/drm/stm/drv.c b/drivers/gpu/drm/stm/drv.c index b333b37..c857663 100644 --- a/drivers/gpu/drm/stm/drv.c +++ b/drivers/gpu/drm/stm/drv.c @@ -17,6 +17,7 @@ #include <drm/drm_crtc_helper.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_framebuffer_helper.h> #include "ltdc.h" @@ -31,7 +32,7 @@ static void drv_output_poll_changed(struct drm_device *ddev) } static const struct drm_mode_config_funcs drv_mode_config_funcs = { - .fb_create = drm_fb_cma_create, + .fb_create = drm_gem_fb_create, .output_poll_changed = drv_output_poll_changed, .atomic_check = drm_atomic_helper_check, .atomic_commit = drm_atomic_helper_commit, diff --git a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c index 568c5d0..e5b6310 100644 --- a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c +++ b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c @@ -113,11 +113,13 @@ static enum dsi_color dsi_color_from_mipi(enum mipi_dsi_pixel_format fmt) static int dsi_pll_get_clkout_khz(int clkin_khz, int idf, int ndiv, int odf) { + int divisor = idf * odf; + /* prevent from division by 0 */ - if (idf * odf) - return DIV_ROUND_CLOSEST(clkin_khz * ndiv, idf * odf); + if (!divisor) + return 0; - return 0; + return DIV_ROUND_CLOSEST(clkin_khz * ndiv, divisor); } static int dsi_pll_get_params(int clkin_khz, int clkout_khz, diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c index ace5965..a201263 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c @@ -106,11 +106,6 @@ static int sun4i_drv_bind(struct device *dev) goto free_drm; } - /* drm_vblank_init calls kcalloc, which can fail */ - ret = drm_vblank_init(drm, 1); - if (ret) - goto free_mem_region; - drm_mode_config_init(drm); ret = component_bind_all(drm->dev, drm); @@ -119,6 +114,11 @@ static int sun4i_drv_bind(struct device *dev) goto cleanup_mode_config; } + /* drm_vblank_init calls kcalloc, which can fail */ + ret = drm_vblank_init(drm, drm->mode_config.num_crtc); + if (ret) + goto free_mem_region; + drm->irq_enabled = true; /* Remove early framebuffers (ie. simplefb) */ @@ -200,11 +200,39 @@ static int compare_of(struct device *dev, void *data) return dev->of_node == data; } +/* + * The encoder drivers use drm_of_find_possible_crtcs to get upstream + * crtcs from the device tree using of_graph. For the results to be + * correct, encoders must be probed/bound after _all_ crtcs have been + * created. The existing code uses a depth first recursive traversal + * of the of_graph, which means the encoders downstream of the TCON + * get add right after the first TCON. The second TCON or CRTC will + * never be properly associated with encoders connected to it. + * + * Also, in a dual display pipeline setup, both frontends can feed + * either backend, and both backends can feed either TCON, we want + * all components of the same type to be added before the next type + * in the pipeline. Fortunately, the pipelines are perfectly symmetric, + * i.e. components of the same type are at the same depth when counted + * from the frontend. The only exception is the third pipeline in + * the A80 SoC, which we do not support anyway. + * + * Hence we can use a breadth first search traversal order to add + * components. We do not need to check for duplicates. The component + * matching system handles this for us. + */ +struct endpoint_list { + struct device_node *node; + struct list_head list; +}; + static int sun4i_drv_add_endpoints(struct device *dev, + struct list_head *endpoints, struct component_match **match, struct device_node *node) { struct device_node *port, *ep, *remote; + struct endpoint_list *endpoint; int count = 0; /* @@ -264,10 +292,15 @@ static int sun4i_drv_add_endpoints(struct device *dev, } } - /* Walk down our tree */ - count += sun4i_drv_add_endpoints(dev, match, remote); + /* Add downstream nodes to the queue */ + endpoint = kzalloc(sizeof(*endpoint), GFP_KERNEL); + if (!endpoint) { + of_node_put(remote); + return -ENOMEM; + } - of_node_put(remote); + endpoint->node = remote; + list_add_tail(&endpoint->list, endpoints); } return count; @@ -277,7 +310,9 @@ static int sun4i_drv_probe(struct platform_device *pdev) { struct component_match *match = NULL; struct device_node *np = pdev->dev.of_node; - int i, count = 0; + struct endpoint_list *endpoint, *endpoint_temp; + int i, ret, count = 0; + LIST_HEAD(endpoints); for (i = 0;; i++) { struct device_node *pipeline = of_parse_phandle(np, @@ -286,12 +321,31 @@ static int sun4i_drv_probe(struct platform_device *pdev) if (!pipeline) break; - count += sun4i_drv_add_endpoints(&pdev->dev, &match, - pipeline); - of_node_put(pipeline); + endpoint = kzalloc(sizeof(*endpoint), GFP_KERNEL); + if (!endpoint) { + ret = -ENOMEM; + goto err_free_endpoints; + } - DRM_DEBUG_DRIVER("Queued %d outputs on pipeline %d\n", - count, i); + endpoint->node = pipeline; + list_add_tail(&endpoint->list, &endpoints); + } + + list_for_each_entry_safe(endpoint, endpoint_temp, &endpoints, list) { + /* process this endpoint */ + ret = sun4i_drv_add_endpoints(&pdev->dev, &endpoints, &match, + endpoint->node); + + /* sun4i_drv_add_endpoints can fail to allocate memory */ + if (ret < 0) + goto err_free_endpoints; + + count += ret; + + /* delete and cleanup the current entry */ + list_del(&endpoint->list); + of_node_put(endpoint->node); + kfree(endpoint); } if (count) @@ -300,6 +354,15 @@ static int sun4i_drv_probe(struct platform_device *pdev) match); else return 0; + +err_free_endpoints: + list_for_each_entry_safe(endpoint, endpoint_temp, &endpoints, list) { + list_del(&endpoint->list); + of_node_put(endpoint->node); + kfree(endpoint); + } + + return ret; } static int sun4i_drv_remove(struct platform_device *pdev) diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index d979129..e853dfe5 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -463,42 +463,170 @@ static int sun4i_tcon_init_regmap(struct device *dev, * function in fact searches the corresponding engine, and the ID is * requested via the get_id function of the engine. */ -static struct sunxi_engine *sun4i_tcon_find_engine(struct sun4i_drv *drv, - struct device_node *node) +static struct sunxi_engine * +sun4i_tcon_find_engine_traverse(struct sun4i_drv *drv, + struct device_node *node) { struct device_node *port, *ep, *remote; - struct sunxi_engine *engine; + struct sunxi_engine *engine = ERR_PTR(-EINVAL); port = of_graph_get_port_by_id(node, 0); if (!port) return ERR_PTR(-EINVAL); + /* + * This only works if there is only one path from the TCON + * to any display engine. Otherwise the probe order of the + * TCONs and display engines is not guaranteed. They may + * either bind to the wrong one, or worse, bind to the same + * one if additional checks are not done. + * + * Bail out if there are multiple input connections. + */ + if (of_get_available_child_count(port) != 1) + goto out_put_port; + + /* Get the first connection without specifying an ID */ + ep = of_get_next_available_child(port, NULL); + if (!ep) + goto out_put_port; + + remote = of_graph_get_remote_port_parent(ep); + if (!remote) + goto out_put_ep; + + /* does this node match any registered engines? */ + list_for_each_entry(engine, &drv->engine_list, list) + if (remote == engine->node) + goto out_put_remote; + + /* keep looking through upstream ports */ + engine = sun4i_tcon_find_engine_traverse(drv, remote); + +out_put_remote: + of_node_put(remote); +out_put_ep: + of_node_put(ep); +out_put_port: + of_node_put(port); + + return engine; +} + +/* + * The device tree binding says that the remote endpoint ID of any + * connection between components, up to and including the TCON, of + * the display pipeline should be equal to the actual ID of the local + * component. Thus we can look at any one of the input connections of + * the TCONs, and use that connection's remote endpoint ID as our own. + * + * Since the user of this function already finds the input port, + * the port is passed in directly without further checks. + */ +static int sun4i_tcon_of_get_id_from_port(struct device_node *port) +{ + struct device_node *ep; + int ret = -EINVAL; + + /* try finding an upstream endpoint */ for_each_available_child_of_node(port, ep) { - remote = of_graph_get_remote_port_parent(ep); + struct device_node *remote; + u32 reg; + + remote = of_graph_get_remote_endpoint(ep); if (!remote) continue; - /* does this node match any registered engines? */ - list_for_each_entry(engine, &drv->engine_list, list) { - if (remote == engine->node) { - of_node_put(remote); - of_node_put(port); - return engine; - } - } + ret = of_property_read_u32(remote, "reg", ®); + if (ret) + continue; - /* keep looking through upstream ports */ - engine = sun4i_tcon_find_engine(drv, remote); - if (!IS_ERR(engine)) { - of_node_put(remote); - of_node_put(port); - return engine; - } + ret = reg; } + return ret; +} + +/* + * Once we know the TCON's id, we can look through the list of + * engines to find a matching one. We assume all engines have + * been probed and added to the list. + */ +static struct sunxi_engine *sun4i_tcon_get_engine_by_id(struct sun4i_drv *drv, + int id) +{ + struct sunxi_engine *engine; + + list_for_each_entry(engine, &drv->engine_list, list) + if (engine->id == id) + return engine; + return ERR_PTR(-EINVAL); } +/* + * On SoCs with the old display pipeline design (Display Engine 1.0), + * we assumed the TCON was always tied to just one backend. However + * this proved not to be the case. On the A31, the TCON can select + * either backend as its source. On the A20 (and likely on the A10), + * the backend can choose which TCON to output to. + * + * The device tree binding says that the remote endpoint ID of any + * connection between components, up to and including the TCON, of + * the display pipeline should be equal to the actual ID of the local + * component. Thus we should be able to look at any one of the input + * connections of the TCONs, and use that connection's remote endpoint + * ID as our own. + * + * However the connections between the backend and TCON were assumed + * to be always singular, and their endpoit IDs were all incorrectly + * set to 0. This means for these old device trees, we cannot just look + * up the remote endpoint ID of a TCON input endpoint. TCON1 would be + * incorrectly identified as TCON0. + * + * This function first checks if the TCON node has 2 input endpoints. + * If so, then the device tree is a corrected version, and it will use + * sun4i_tcon_of_get_id() and sun4i_tcon_get_engine_by_id() from above + * to fetch the ID and engine directly. If not, then it is likely an + * old device trees, where the endpoint IDs were incorrect, but did not + * have endpoint connections between the backend and TCON across + * different display pipelines. It will fall back to the old method of + * traversing the of_graph to try and find a matching engine by device + * node. + * + * In the case of single display pipeline device trees, either method + * works. + */ +static struct sunxi_engine *sun4i_tcon_find_engine(struct sun4i_drv *drv, + struct device_node *node) +{ + struct device_node *port; + struct sunxi_engine *engine; + + port = of_graph_get_port_by_id(node, 0); + if (!port) + return ERR_PTR(-EINVAL); + + /* + * Is this a corrected device tree with cross pipeline + * connections between the backend and TCON? + */ + if (of_get_child_count(port) > 1) { + /* Get our ID directly from an upstream endpoint */ + int id = sun4i_tcon_of_get_id_from_port(port); + + /* Get our engine by matching our ID */ + engine = sun4i_tcon_get_engine_by_id(drv, id); + + of_node_put(port); + return engine; + } + + /* Fallback to old method by traversing input endpoints */ + of_node_put(port); + return sun4i_tcon_find_engine_traverse(drv, node); +} + static int sun4i_tcon_bind(struct device *dev, struct device *master, void *data) { @@ -530,10 +658,7 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, } /* Make sure our TCON is reset */ - if (!reset_control_status(tcon->lcd_rst)) - reset_control_assert(tcon->lcd_rst); - - ret = reset_control_deassert(tcon->lcd_rst); + ret = reset_control_reset(tcon->lcd_rst); if (ret) { dev_err(dev, "Couldn't deassert our reset line\n"); return ret; @@ -574,6 +699,25 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, if (ret < 0) goto err_free_clocks; + if (tcon->quirks->needs_de_be_mux) { + /* + * We assume there is no dynamic muxing of backends + * and TCONs, so we select the backend with same ID. + * + * While dynamic selection might be interesting, since + * the CRTC is tied to the TCON, while the layers are + * tied to the backends, this means, we will need to + * switch between groups of layers. There might not be + * a way to represent this constraint in DRM. + */ + regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG, + SUN4I_TCON0_CTL_SRC_SEL_MASK, + tcon->id); + regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG, + SUN4I_TCON1_CTL_SRC_SEL_MASK, + tcon->id); + } + list_add_tail(&tcon->list, &drv->tcon_list); return 0; @@ -629,11 +773,13 @@ static const struct sun4i_tcon_quirks sun5i_a13_quirks = { }; static const struct sun4i_tcon_quirks sun6i_a31_quirks = { - .has_channel_1 = true, + .has_channel_1 = true, + .needs_de_be_mux = true, }; static const struct sun4i_tcon_quirks sun6i_a31s_quirks = { - .has_channel_1 = true, + .has_channel_1 = true, + .needs_de_be_mux = true, }; static const struct sun4i_tcon_quirks sun8i_a33_quirks = { diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h index 552c88e..5a219d1 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.h +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h @@ -37,6 +37,7 @@ #define SUN4I_TCON0_CTL_TCON_ENABLE BIT(31) #define SUN4I_TCON0_CTL_CLK_DELAY_MASK GENMASK(8, 4) #define SUN4I_TCON0_CTL_CLK_DELAY(delay) ((delay << 4) & SUN4I_TCON0_CTL_CLK_DELAY_MASK) +#define SUN4I_TCON0_CTL_SRC_SEL_MASK GENMASK(2, 0) #define SUN4I_TCON0_DCLK_REG 0x44 #define SUN4I_TCON0_DCLK_GATE_BIT (31) @@ -85,6 +86,7 @@ #define SUN4I_TCON1_CTL_INTERLACE_ENABLE BIT(20) #define SUN4I_TCON1_CTL_CLK_DELAY_MASK GENMASK(8, 4) #define SUN4I_TCON1_CTL_CLK_DELAY(delay) ((delay << 4) & SUN4I_TCON1_CTL_CLK_DELAY_MASK) +#define SUN4I_TCON1_CTL_SRC_SEL_MASK GENMASK(1, 0) #define SUN4I_TCON1_BASIC0_REG 0x94 #define SUN4I_TCON1_BASIC0_X(width) ((((width) - 1) & 0xfff) << 16) @@ -146,6 +148,7 @@ struct sun4i_tcon_quirks { bool has_unknown_mux; /* sun5i has undocumented mux */ bool has_channel_1; /* a33 does not have channel 1 */ + bool needs_de_be_mux; /* sun6i needs mux to select backend */ }; struct sun4i_tcon { diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index b0d70f9..146ac9a 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -23,6 +23,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_gem_framebuffer_helper.h> #include "tilcdc_drv.h" #include "tilcdc_regs.h" @@ -65,7 +66,7 @@ static struct of_device_id tilcdc_of_match[]; static struct drm_framebuffer *tilcdc_fb_create(struct drm_device *dev, struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd) { - return drm_fb_cma_create(dev, file_priv, mode_cmd); + return drm_gem_fb_create(dev, file_priv, mode_cmd); } static void tilcdc_fb_output_poll_changed(struct drm_device *dev) diff --git a/drivers/gpu/drm/tinydrm/mi0283qt.c b/drivers/gpu/drm/tinydrm/mi0283qt.c index 7e5bb7d..7fd2691 100644 --- a/drivers/gpu/drm/tinydrm/mi0283qt.c +++ b/drivers/gpu/drm/tinydrm/mi0283qt.c @@ -163,7 +163,6 @@ MODULE_DEVICE_TABLE(spi, mi0283qt_id); static int mi0283qt_probe(struct spi_device *spi) { struct device *dev = &spi->dev; - struct tinydrm_device *tdev; struct mipi_dbi *mipi; struct gpio_desc *dc; u32 rotation = 0; @@ -215,20 +214,9 @@ static int mi0283qt_probe(struct spi_device *spi) return ret; } - tdev = &mipi->tinydrm; - - ret = devm_tinydrm_register(tdev); - if (ret) - return ret; - spi_set_drvdata(spi, mipi); - DRM_DEBUG_DRIVER("Initialized %s:%s @%uMHz on minor %d\n", - tdev->drm->driver->name, dev_name(dev), - spi->max_speed_hz / 1000000, - tdev->drm->primary->index); - - return 0; + return devm_tinydrm_register(&mipi->tinydrm); } static void mi0283qt_shutdown(struct spi_device *spi) diff --git a/drivers/gpu/drm/tinydrm/mipi-dbi.c b/drivers/gpu/drm/tinydrm/mipi-dbi.c index 2caeabc..f0dedc2 100644 --- a/drivers/gpu/drm/tinydrm/mipi-dbi.c +++ b/drivers/gpu/drm/tinydrm/mipi-dbi.c @@ -842,6 +842,8 @@ int mipi_dbi_spi_init(struct spi_device *spi, struct mipi_dbi *mipi, return -ENOMEM; } + DRM_DEBUG_DRIVER("SPI speed: %uMHz\n", spi->max_speed_hz / 1000000); + return 0; } EXPORT_SYMBOL(mipi_dbi_spi_init); diff --git a/drivers/gpu/drm/tinydrm/repaper.c b/drivers/gpu/drm/tinydrm/repaper.c index 30dc97b..5fbe147 100644 --- a/drivers/gpu/drm/tinydrm/repaper.c +++ b/drivers/gpu/drm/tinydrm/repaper.c @@ -1078,19 +1078,11 @@ static int repaper_probe(struct spi_device *spi) return ret; drm_mode_config_reset(tdev->drm); - - ret = devm_tinydrm_register(tdev); - if (ret) - return ret; - spi_set_drvdata(spi, tdev); - DRM_DEBUG_DRIVER("Initialized %s:%s @%uMHz on minor %d\n", - tdev->drm->driver->name, dev_name(dev), - spi->max_speed_hz / 1000000, - tdev->drm->primary->index); + DRM_DEBUG_DRIVER("SPI speed: %uMHz\n", spi->max_speed_hz / 1000000); - return 0; + return devm_tinydrm_register(tdev); } static void repaper_shutdown(struct spi_device *spi) diff --git a/drivers/gpu/drm/tinydrm/st7586.c b/drivers/gpu/drm/tinydrm/st7586.c index b439956..07b4d31 100644 --- a/drivers/gpu/drm/tinydrm/st7586.c +++ b/drivers/gpu/drm/tinydrm/st7586.c @@ -343,7 +343,6 @@ MODULE_DEVICE_TABLE(spi, st7586_id); static int st7586_probe(struct spi_device *spi) { struct device *dev = &spi->dev; - struct tinydrm_device *tdev; struct mipi_dbi *mipi; struct gpio_desc *a0; u32 rotation = 0; @@ -388,20 +387,9 @@ static int st7586_probe(struct spi_device *spi) if (ret) return ret; - tdev = &mipi->tinydrm; - - ret = devm_tinydrm_register(tdev); - if (ret) - return ret; - spi_set_drvdata(spi, mipi); - DRM_DEBUG_DRIVER("Initialized %s:%s @%uMHz on minor %d\n", - tdev->drm->driver->name, dev_name(dev), - spi->max_speed_hz / 1000000, - tdev->drm->primary->index); - - return 0; + return devm_tinydrm_register(&mipi->tinydrm); } static void st7586_shutdown(struct spi_device *spi) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 180ce62..d79607a 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -440,28 +440,29 @@ static void ttm_bo_cleanup_refs_or_queue(struct ttm_buffer_object *bo) struct ttm_bo_global *glob = bo->glob; int ret; + ret = ttm_bo_individualize_resv(bo); + if (ret) { + /* Last resort, if we fail to allocate memory for the + * fences block for the BO to become idle + */ + reservation_object_wait_timeout_rcu(bo->resv, true, false, + 30 * HZ); + spin_lock(&glob->lru_lock); + goto error; + } + spin_lock(&glob->lru_lock); ret = __ttm_bo_reserve(bo, false, true, NULL); - if (!ret) { - if (!ttm_bo_wait(bo, false, true)) { + if (reservation_object_test_signaled_rcu(&bo->ttm_resv, true)) { ttm_bo_del_from_lru(bo); spin_unlock(&glob->lru_lock); + if (bo->resv != &bo->ttm_resv) + reservation_object_unlock(&bo->ttm_resv); ttm_bo_cleanup_memtype_use(bo); - return; } - ret = ttm_bo_individualize_resv(bo); - if (ret) { - /* Last resort, if we fail to allocate memory for the - * fences block for the BO to become idle and free it. - */ - spin_unlock(&glob->lru_lock); - ttm_bo_wait(bo, true, true); - ttm_bo_cleanup_memtype_use(bo); - return; - } ttm_bo_flush_all_fences(bo); /* @@ -474,11 +475,12 @@ static void ttm_bo_cleanup_refs_or_queue(struct ttm_buffer_object *bo) ttm_bo_add_to_lru(bo); } - if (bo->resv != &bo->ttm_resv) - reservation_object_unlock(&bo->ttm_resv); __ttm_bo_unreserve(bo); } + if (bo->resv != &bo->ttm_resv) + reservation_object_unlock(&bo->ttm_resv); +error: kref_get(&bo->list_kref); list_add_tail(&bo->ddestroy, &bdev->ddestroy); spin_unlock(&glob->lru_lock); @@ -555,6 +557,8 @@ static int ttm_bo_cleanup_refs_and_unlock(struct ttm_buffer_object *bo, } ttm_bo_del_from_lru(bo); + if (!list_empty(&bo->ddestroy) && (bo->resv != &bo->ttm_resv)) + reservation_object_fini(&bo->ttm_resv); list_del_init(&bo->ddestroy); kref_put(&bo->list_kref, ttm_bo_ref_bug); diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index c934ad5..78cb99b 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -587,7 +587,6 @@ int ttm_bo_kmap(struct ttm_buffer_object *bo, unsigned long offset, size; int ret; - BUG_ON(!list_empty(&bo->swap)); map->virtual = NULL; map->bo = bo; if (num_pages > bo->num_pages) diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c index 8715998..052e1f1 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c @@ -920,6 +920,49 @@ void ttm_pool_unpopulate(struct ttm_tt *ttm) } EXPORT_SYMBOL(ttm_pool_unpopulate); +#if defined(CONFIG_SWIOTLB) || defined(CONFIG_INTEL_IOMMU) +int ttm_populate_and_map_pages(struct device *dev, struct ttm_dma_tt *tt) +{ + unsigned i; + int r; + + r = ttm_pool_populate(&tt->ttm); + if (r) + return r; + + for (i = 0; i < tt->ttm.num_pages; i++) { + tt->dma_address[i] = dma_map_page(dev, tt->ttm.pages[i], + 0, PAGE_SIZE, + DMA_BIDIRECTIONAL); + if (dma_mapping_error(dev, tt->dma_address[i])) { + while (i--) { + dma_unmap_page(dev, tt->dma_address[i], + PAGE_SIZE, DMA_BIDIRECTIONAL); + tt->dma_address[i] = 0; + } + ttm_pool_unpopulate(&tt->ttm); + return -EFAULT; + } + } + return 0; +} +EXPORT_SYMBOL(ttm_populate_and_map_pages); + +void ttm_unmap_and_unpopulate_pages(struct device *dev, struct ttm_dma_tt *tt) +{ + unsigned i; + + for (i = 0; i < tt->ttm.num_pages; i++) { + if (tt->dma_address[i]) { + dma_unmap_page(dev, tt->dma_address[i], + PAGE_SIZE, DMA_BIDIRECTIONAL); + } + } + ttm_pool_unpopulate(&tt->ttm); +} +EXPORT_SYMBOL(ttm_unmap_and_unpopulate_pages); +#endif + int ttm_page_alloc_debugfs(struct seq_file *m, void *data) { struct ttm_page_pool *p; diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c index 90ddbdc..06bc14b 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c @@ -60,22 +60,15 @@ #define NUM_PAGES_TO_ALLOC (PAGE_SIZE/sizeof(struct page *)) #define SMALL_ALLOCATION 4 #define FREE_ALL_PAGES (~0U) -/* times are in msecs */ -#define IS_UNDEFINED (0) -#define IS_WC (1<<1) -#define IS_UC (1<<2) -#define IS_CACHED (1<<3) -#define IS_DMA32 (1<<4) enum pool_type { - POOL_IS_UNDEFINED, - POOL_IS_WC = IS_WC, - POOL_IS_UC = IS_UC, - POOL_IS_CACHED = IS_CACHED, - POOL_IS_WC_DMA32 = IS_WC | IS_DMA32, - POOL_IS_UC_DMA32 = IS_UC | IS_DMA32, - POOL_IS_CACHED_DMA32 = IS_CACHED | IS_DMA32, + IS_UNDEFINED = 0, + IS_WC = 1 << 1, + IS_UC = 1 << 2, + IS_CACHED = 1 << 3, + IS_DMA32 = 1 << 4 }; + /* * The pool structure. There are usually six pools: * - generic (not restricted to DMA32): @@ -86,11 +79,9 @@ enum pool_type { * The other ones can be shrunk by the shrinker API if neccessary. * @pools: The 'struct device->dma_pools' link. * @type: Type of the pool - * @lock: Protects the inuse_list and free_list from concurrnet access. Must be + * @lock: Protects the free_list from concurrnet access. Must be * used with irqsave/irqrestore variants because pool allocator maybe called * from delayed work. - * @inuse_list: Pool of pages that are in use. The order is very important and - * it is in the order that the TTM pages that are put back are in. * @free_list: Pool of pages that are free to be used. No order requirements. * @dev: The device that is associated with these pools. * @size: Size used during DMA allocation. @@ -107,7 +98,6 @@ struct dma_pool { struct list_head pools; /* The 'struct device->dma_pools link */ enum pool_type type; spinlock_t lock; - struct list_head inuse_list; struct list_head free_list; struct device *dev; unsigned size; @@ -609,7 +599,6 @@ static struct dma_pool *ttm_dma_pool_init(struct device *dev, gfp_t flags, sec_pool->pool = pool; INIT_LIST_HEAD(&pool->free_list); - INIT_LIST_HEAD(&pool->inuse_list); INIT_LIST_HEAD(&pool->pools); spin_lock_init(&pool->lock); pool->dev = dev; @@ -882,22 +871,23 @@ int ttm_dma_populate(struct ttm_dma_tt *ttm_dma, struct device *dev) struct dma_pool *pool; enum pool_type type; unsigned i; - gfp_t gfp_flags; int ret; if (ttm->state != tt_unpopulated) return 0; type = ttm_to_type(ttm->page_flags, ttm->caching_state); - if (ttm->page_flags & TTM_PAGE_FLAG_DMA32) - gfp_flags = GFP_USER | GFP_DMA32; - else - gfp_flags = GFP_HIGHUSER; - if (ttm->page_flags & TTM_PAGE_FLAG_ZERO_ALLOC) - gfp_flags |= __GFP_ZERO; - pool = ttm_dma_find_pool(dev, type); if (!pool) { + gfp_t gfp_flags; + + if (ttm->page_flags & TTM_PAGE_FLAG_DMA32) + gfp_flags = GFP_USER | GFP_DMA32; + else + gfp_flags = GFP_HIGHUSER; + if (ttm->page_flags & TTM_PAGE_FLAG_ZERO_ALLOC) + gfp_flags |= __GFP_ZERO; + pool = ttm_dma_pool_init(dev, gfp_flags, type); if (IS_ERR_OR_NULL(pool)) { return -ENOMEM; diff --git a/drivers/gpu/drm/tve200/Kconfig b/drivers/gpu/drm/tve200/Kconfig new file mode 100644 index 0000000..c5f03bf --- /dev/null +++ b/drivers/gpu/drm/tve200/Kconfig @@ -0,0 +1,16 @@ +config DRM_TVE200 + tristate "DRM Support for Faraday TV Encoder TVE200" + depends on DRM + depends on CMA + depends on ARM || COMPILE_TEST + depends on OF + select DRM_BRIDGE + select DRM_PANEL_BRIDGE + select DRM_KMS_HELPER + select DRM_KMS_CMA_HELPER + select DRM_GEM_CMA_HELPER + select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE + help + Choose this option for DRM support for the Faraday TV Encoder + TVE200 Controller. + If M is selected the module will be called tve200_drm. diff --git a/drivers/gpu/drm/tve200/Makefile b/drivers/gpu/drm/tve200/Makefile new file mode 100644 index 0000000..6b7a6a1 --- /dev/null +++ b/drivers/gpu/drm/tve200/Makefile @@ -0,0 +1,4 @@ +tve200_drm-y += tve200_display.o \ + tve200_drv.o + +obj-$(CONFIG_DRM_TVE200) += tve200_drm.o diff --git a/drivers/gpu/drm/tve200/tve200_display.c b/drivers/gpu/drm/tve200/tve200_display.c new file mode 100644 index 0000000..18457de --- /dev/null +++ b/drivers/gpu/drm/tve200/tve200_display.c @@ -0,0 +1,337 @@ +/* + * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org> + * Parts of this file were based on sources as follows: + * + * Copyright (C) 2006-2008 Intel Corporation + * Copyright (C) 2007 Amos Lee <amos_lee@storlinksemi.com> + * Copyright (C) 2007 Dave Airlie <airlied@linux.ie> + * Copyright (C) 2011 Texas Instruments + * Copyright (C) 2017 Eric Anholt + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms of + * such GNU licence. + */ +#include <linux/clk.h> +#include <linux/version.h> +#include <linux/dma-buf.h> +#include <linux/of_graph.h> + +#include <drm/drmP.h> +#include <drm/drm_panel.h> +#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_fb_cma_helper.h> + +#include "tve200_drm.h" + +irqreturn_t tve200_irq(int irq, void *data) +{ + struct tve200_drm_dev_private *priv = data; + u32 stat; + u32 val; + + stat = readl(priv->regs + TVE200_INT_STAT); + + if (!stat) + return IRQ_NONE; + + /* + * Vblank IRQ + * + * The hardware is a bit tilted: the line stays high after clearing + * the vblank IRQ, firing many more interrupts. We counter this + * by toggling the IRQ back and forth from firing at vblank and + * firing at start of active image, which works around the problem + * since those occur strictly in sequence, and we get two IRQs for each + * frame, one at start of Vblank (that we make call into the CRTC) and + * another one at the start of the image (that we discard). + */ + if (stat & TVE200_INT_V_STATUS) { + val = readl(priv->regs + TVE200_CTRL); + /* We have an actual start of vsync */ + if (!(val & TVE200_VSTSTYPE_BITS)) { + drm_crtc_handle_vblank(&priv->pipe.crtc); + /* Toggle trigger to start of active image */ + val |= TVE200_VSTSTYPE_VAI; + } else { + /* Toggle trigger back to start of vsync */ + val &= ~TVE200_VSTSTYPE_BITS; + } + writel(val, priv->regs + TVE200_CTRL); + } else + dev_err(priv->drm->dev, "stray IRQ %08x\n", stat); + + /* Clear the interrupt once done */ + writel(stat, priv->regs + TVE200_INT_CLR); + + return IRQ_HANDLED; +} + +static int tve200_display_check(struct drm_simple_display_pipe *pipe, + struct drm_plane_state *pstate, + struct drm_crtc_state *cstate) +{ + const struct drm_display_mode *mode = &cstate->mode; + struct drm_framebuffer *old_fb = pipe->plane.state->fb; + struct drm_framebuffer *fb = pstate->fb; + + /* + * We support these specific resolutions and nothing else. + */ + if (!(mode->hdisplay == 352 && mode->vdisplay == 240) && /* SIF(525) */ + !(mode->hdisplay == 352 && mode->vdisplay == 288) && /* CIF(625) */ + !(mode->hdisplay == 640 && mode->vdisplay == 480) && /* VGA */ + !(mode->hdisplay == 720 && mode->vdisplay == 480) && /* D1 */ + !(mode->hdisplay == 720 && mode->vdisplay == 576)) { /* D1 */ + DRM_DEBUG_KMS("unsupported display mode (%u x %u)\n", + mode->hdisplay, mode->vdisplay); + return -EINVAL; + } + + if (fb) { + u32 offset = drm_fb_cma_get_gem_addr(fb, pstate, 0); + + /* FB base address must be dword aligned. */ + if (offset & 3) { + DRM_DEBUG_KMS("FB not 32-bit aligned\n"); + return -EINVAL; + } + + /* + * There's no pitch register, the mode's hdisplay + * controls this. + */ + if (fb->pitches[0] != mode->hdisplay * fb->format->cpp[0]) { + DRM_DEBUG_KMS("can't handle pitches\n"); + return -EINVAL; + } + + /* + * We can't change the FB format in a flicker-free + * manner (and only update it during CRTC enable). + */ + if (old_fb && old_fb->format != fb->format) + cstate->mode_changed = true; + } + + return 0; +} + +static void tve200_display_enable(struct drm_simple_display_pipe *pipe, + struct drm_crtc_state *cstate) +{ + struct drm_crtc *crtc = &pipe->crtc; + struct drm_plane *plane = &pipe->plane; + struct drm_device *drm = crtc->dev; + struct tve200_drm_dev_private *priv = drm->dev_private; + const struct drm_display_mode *mode = &cstate->mode; + struct drm_framebuffer *fb = plane->state->fb; + struct drm_connector *connector = priv->connector; + u32 format = fb->format->format; + u32 ctrl1 = 0; + + clk_prepare_enable(priv->clk); + + /* Function 1 */ + ctrl1 |= TVE200_CTRL_CSMODE; + /* Interlace mode for CCIR656: parameterize? */ + ctrl1 |= TVE200_CTRL_NONINTERLACE; + /* 32 words per burst */ + ctrl1 |= TVE200_CTRL_BURST_32_WORDS; + /* 16 retries */ + ctrl1 |= TVE200_CTRL_RETRYCNT_16; + /* NTSC mode: parametrize? */ + ctrl1 |= TVE200_CTRL_NTSC; + + /* Vsync IRQ at start of Vsync at first */ + ctrl1 |= TVE200_VSTSTYPE_VSYNC; + + if (connector->display_info.bus_flags & DRM_BUS_FLAG_PIXDATA_NEGEDGE) + ctrl1 |= TVE200_CTRL_TVCLKP; + + if ((mode->hdisplay == 352 && mode->vdisplay == 240) || /* SIF(525) */ + (mode->hdisplay == 352 && mode->vdisplay == 288)) { /* CIF(625) */ + ctrl1 |= TVE200_CTRL_IPRESOL_CIF; + dev_info(drm->dev, "CIF mode\n"); + } else if (mode->hdisplay == 640 && mode->vdisplay == 480) { + ctrl1 |= TVE200_CTRL_IPRESOL_VGA; + dev_info(drm->dev, "VGA mode\n"); + } else if ((mode->hdisplay == 720 && mode->vdisplay == 480) || + (mode->hdisplay == 720 && mode->vdisplay == 576)) { + ctrl1 |= TVE200_CTRL_IPRESOL_D1; + dev_info(drm->dev, "D1 mode\n"); + } + + if (format & DRM_FORMAT_BIG_ENDIAN) { + ctrl1 |= TVE200_CTRL_BBBP; + format &= ~DRM_FORMAT_BIG_ENDIAN; + } + + switch (format) { + case DRM_FORMAT_XRGB8888: + ctrl1 |= TVE200_IPDMOD_RGB888; + break; + case DRM_FORMAT_RGB565: + ctrl1 |= TVE200_IPDMOD_RGB565; + break; + case DRM_FORMAT_XRGB1555: + ctrl1 |= TVE200_IPDMOD_RGB555; + break; + case DRM_FORMAT_XBGR8888: + ctrl1 |= TVE200_IPDMOD_RGB888 | TVE200_BGR; + break; + case DRM_FORMAT_BGR565: + ctrl1 |= TVE200_IPDMOD_RGB565 | TVE200_BGR; + break; + case DRM_FORMAT_XBGR1555: + ctrl1 |= TVE200_IPDMOD_RGB555 | TVE200_BGR; + break; + case DRM_FORMAT_YUYV: + ctrl1 |= TVE200_IPDMOD_YUV422; + ctrl1 |= TVE200_CTRL_YCBCRODR_CR0Y1CB0Y0; + break; + case DRM_FORMAT_YVYU: + ctrl1 |= TVE200_IPDMOD_YUV422; + ctrl1 |= TVE200_CTRL_YCBCRODR_CB0Y1CR0Y0; + break; + case DRM_FORMAT_UYVY: + ctrl1 |= TVE200_IPDMOD_YUV422; + ctrl1 |= TVE200_CTRL_YCBCRODR_Y1CR0Y0CB0; + break; + case DRM_FORMAT_VYUY: + ctrl1 |= TVE200_IPDMOD_YUV422; + ctrl1 |= TVE200_CTRL_YCBCRODR_Y1CB0Y0CR0; + break; + case DRM_FORMAT_YUV420: + ctrl1 |= TVE200_CTRL_YUV420; + ctrl1 |= TVE200_IPDMOD_YUV420; + break; + default: + dev_err(drm->dev, "Unknown FB format 0x%08x\n", + fb->format->format); + break; + } + + ctrl1 |= TVE200_TVEEN; + + /* Turn it on */ + writel(ctrl1, priv->regs + TVE200_CTRL); + + drm_crtc_vblank_on(crtc); +} + +void tve200_display_disable(struct drm_simple_display_pipe *pipe) +{ + struct drm_crtc *crtc = &pipe->crtc; + struct drm_device *drm = crtc->dev; + struct tve200_drm_dev_private *priv = drm->dev_private; + + drm_crtc_vblank_off(crtc); + + /* Disable and Power Down */ + writel(0, priv->regs + TVE200_CTRL); + + clk_disable_unprepare(priv->clk); +} + +static void tve200_display_update(struct drm_simple_display_pipe *pipe, + struct drm_plane_state *old_pstate) +{ + struct drm_crtc *crtc = &pipe->crtc; + struct drm_device *drm = crtc->dev; + struct tve200_drm_dev_private *priv = drm->dev_private; + struct drm_pending_vblank_event *event = crtc->state->event; + struct drm_plane *plane = &pipe->plane; + struct drm_plane_state *pstate = plane->state; + struct drm_framebuffer *fb = pstate->fb; + + if (fb) { + /* For RGB, the Y component is used as base address */ + writel(drm_fb_cma_get_gem_addr(fb, pstate, 0), + priv->regs + TVE200_Y_FRAME_BASE_ADDR); + + /* For three plane YUV we need two more addresses */ + if (fb->format->format == DRM_FORMAT_YUV420) { + writel(drm_fb_cma_get_gem_addr(fb, pstate, 1), + priv->regs + TVE200_U_FRAME_BASE_ADDR); + writel(drm_fb_cma_get_gem_addr(fb, pstate, 2), + priv->regs + TVE200_V_FRAME_BASE_ADDR); + } + } + + if (event) { + crtc->state->event = NULL; + + spin_lock_irq(&crtc->dev->event_lock); + if (crtc->state->active && drm_crtc_vblank_get(crtc) == 0) + drm_crtc_arm_vblank_event(crtc, event); + else + drm_crtc_send_vblank_event(crtc, event); + spin_unlock_irq(&crtc->dev->event_lock); + } +} + +int tve200_enable_vblank(struct drm_device *drm, unsigned int crtc) +{ + struct tve200_drm_dev_private *priv = drm->dev_private; + + writel(TVE200_INT_V_STATUS, priv->regs + TVE200_INT_EN); + return 0; +} + +void tve200_disable_vblank(struct drm_device *drm, unsigned int crtc) +{ + struct tve200_drm_dev_private *priv = drm->dev_private; + + writel(0, priv->regs + TVE200_INT_EN); +} + +static int tve200_display_prepare_fb(struct drm_simple_display_pipe *pipe, + struct drm_plane_state *plane_state) +{ + return drm_fb_cma_prepare_fb(&pipe->plane, plane_state); +} + +const struct drm_simple_display_pipe_funcs tve200_display_funcs = { + .check = tve200_display_check, + .enable = tve200_display_enable, + .disable = tve200_display_disable, + .update = tve200_display_update, + .prepare_fb = tve200_display_prepare_fb, +}; + +int tve200_display_init(struct drm_device *drm) +{ + struct tve200_drm_dev_private *priv = drm->dev_private; + int ret; + static const u32 formats[] = { + DRM_FORMAT_XRGB8888, + DRM_FORMAT_XBGR8888, + DRM_FORMAT_RGB565, + DRM_FORMAT_BGR565, + DRM_FORMAT_XRGB1555, + DRM_FORMAT_XBGR1555, + /* + * The controller actually supports any YCbCr ordering, + * for packed YCbCr. This just lists the orderings that + * DRM supports. + */ + DRM_FORMAT_YUYV, + DRM_FORMAT_YVYU, + DRM_FORMAT_UYVY, + DRM_FORMAT_VYUY, + /* This uses three planes */ + DRM_FORMAT_YUV420, + }; + + ret = drm_simple_display_pipe_init(drm, &priv->pipe, + &tve200_display_funcs, + formats, ARRAY_SIZE(formats), + NULL, + priv->connector); + if (ret) + return ret; + + return 0; +} diff --git a/drivers/gpu/drm/tve200/tve200_drm.h b/drivers/gpu/drm/tve200/tve200_drm.h new file mode 100644 index 0000000..628b793 --- /dev/null +++ b/drivers/gpu/drm/tve200/tve200_drm.h @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org> + * Parts of this file were based on sources as follows: + * + * Copyright (C) 2006-2008 Intel Corporation + * Copyright (C) 2007 Amos Lee <amos_lee@storlinksemi.com> + * Copyright (C) 2007 Dave Airlie <airlied@linux.ie> + * Copyright (C) 2011 Texas Instruments + * Copyright (C) 2017 Eric Anholt + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms of + * such GNU licence. + */ + +#ifndef _TVE200_DRM_H_ +#define _TVE200_DRM_H_ + +/* Bits 2-31 are valid physical base addresses */ +#define TVE200_Y_FRAME_BASE_ADDR 0x00 +#define TVE200_U_FRAME_BASE_ADDR 0x04 +#define TVE200_V_FRAME_BASE_ADDR 0x08 + +#define TVE200_INT_EN 0x0C +#define TVE200_INT_CLR 0x10 +#define TVE200_INT_STAT 0x14 +#define TVE200_INT_BUS_ERR BIT(7) +#define TVE200_INT_V_STATUS BIT(6) /* vertical blank */ +#define TVE200_INT_V_NEXT_FRAME BIT(5) +#define TVE200_INT_U_NEXT_FRAME BIT(4) +#define TVE200_INT_Y_NEXT_FRAME BIT(3) +#define TVE200_INT_V_FIFO_UNDERRUN BIT(2) +#define TVE200_INT_U_FIFO_UNDERRUN BIT(1) +#define TVE200_INT_Y_FIFO_UNDERRUN BIT(0) +#define TVE200_FIFO_UNDERRUNS (TVE200_INT_V_FIFO_UNDERRUN | \ + TVE200_INT_U_FIFO_UNDERRUN | \ + TVE200_INT_Y_FIFO_UNDERRUN) + +#define TVE200_CTRL 0x18 +#define TVE200_CTRL_YUV420 BIT(31) +#define TVE200_CTRL_CSMODE BIT(30) +#define TVE200_CTRL_NONINTERLACE BIT(28) /* 0 = non-interlace CCIR656 */ +#define TVE200_CTRL_TVCLKP BIT(27) /* Inverted clock phase */ +/* Bits 24..26 define the burst size after arbitration on the bus */ +#define TVE200_CTRL_BURST_4_WORDS (0 << 24) +#define TVE200_CTRL_BURST_8_WORDS (1 << 24) +#define TVE200_CTRL_BURST_16_WORDS (2 << 24) +#define TVE200_CTRL_BURST_32_WORDS (3 << 24) +#define TVE200_CTRL_BURST_64_WORDS (4 << 24) +#define TVE200_CTRL_BURST_128_WORDS (5 << 24) +#define TVE200_CTRL_BURST_256_WORDS (6 << 24) +#define TVE200_CTRL_BURST_0_WORDS (7 << 24) /* ? */ +/* + * Bits 16..23 is the retry count*16 before issueing a new AHB transfer + * on the AHB bus. + */ +#define TVE200_CTRL_RETRYCNT_MASK GENMASK(23, 16) +#define TVE200_CTRL_RETRYCNT_16 (1 << 16) +#define TVE200_CTRL_BBBP BIT(15) /* 0 = little-endian */ +/* Bits 12..14 define the YCbCr ordering */ +#define TVE200_CTRL_YCBCRODR_CB0Y0CR0Y1 (0 << 12) +#define TVE200_CTRL_YCBCRODR_Y0CB0Y1CR0 (1 << 12) +#define TVE200_CTRL_YCBCRODR_CR0Y0CB0Y1 (2 << 12) +#define TVE200_CTRL_YCBCRODR_Y1CB0Y0CR0 (3 << 12) +#define TVE200_CTRL_YCBCRODR_CR0Y1CB0Y0 (4 << 12) +#define TVE200_CTRL_YCBCRODR_Y1CR0Y0CB0 (5 << 12) +#define TVE200_CTRL_YCBCRODR_CB0Y1CR0Y0 (6 << 12) +#define TVE200_CTRL_YCBCRODR_Y0CR0Y1CB0 (7 << 12) +/* Bits 10..11 define the input resolution (framebuffer size) */ +#define TVE200_CTRL_IPRESOL_CIF (0 << 10) +#define TVE200_CTRL_IPRESOL_VGA (1 << 10) +#define TVE200_CTRL_IPRESOL_D1 (2 << 10) +#define TVE200_CTRL_NTSC BIT(9) /* 0 = PAL, 1 = NTSC */ +#define TVE200_CTRL_INTERLACE BIT(8) /* 1 = interlace, only for D1 */ +#define TVE200_IPDMOD_RGB555 (0 << 6) /* TVE200_CTRL_YUV420 = 0 */ +#define TVE200_IPDMOD_RGB565 (1 << 6) +#define TVE200_IPDMOD_RGB888 (2 << 6) +#define TVE200_IPDMOD_YUV420 (2 << 6) /* TVE200_CTRL_YUV420 = 1 */ +#define TVE200_IPDMOD_YUV422 (3 << 6) +/* Bits 4 & 5 define when to fire the vblank IRQ */ +#define TVE200_VSTSTYPE_VSYNC (0 << 4) /* start of vsync */ +#define TVE200_VSTSTYPE_VBP (1 << 4) /* start of v back porch */ +#define TVE200_VSTSTYPE_VAI (2 << 4) /* start of v active image */ +#define TVE200_VSTSTYPE_VFP (3 << 4) /* start of v front porch */ +#define TVE200_VSTSTYPE_BITS (BIT(4) | BIT(5)) +#define TVE200_BGR BIT(1) /* 0 = RGB, 1 = BGR */ +#define TVE200_TVEEN BIT(0) /* Enable TVE block */ + +#define TVE200_CTRL_2 0x1c +#define TVE200_CTRL_3 0x20 + +#define TVE200_CTRL_4 0x24 +#define TVE200_CTRL_4_RESET BIT(0) /* triggers reset of TVE200 */ + +#include <drm/drm_gem.h> +#include <drm/drm_simple_kms_helper.h> + +struct tve200_drm_dev_private { + struct drm_device *drm; + + struct drm_connector *connector; + struct drm_panel *panel; + struct drm_bridge *bridge; + struct drm_simple_display_pipe pipe; + struct drm_fbdev_cma *fbdev; + + void *regs; + struct clk *pclk; + struct clk *clk; +}; + +#define to_tve200_connector(x) \ + container_of(x, struct tve200_drm_connector, connector) + +int tve200_display_init(struct drm_device *dev); +int tve200_enable_vblank(struct drm_device *drm, unsigned int crtc); +void tve200_disable_vblank(struct drm_device *drm, unsigned int crtc); +irqreturn_t tve200_irq(int irq, void *data); +int tve200_connector_init(struct drm_device *dev); +int tve200_encoder_init(struct drm_device *dev); +int tve200_dumb_create(struct drm_file *file_priv, + struct drm_device *dev, + struct drm_mode_create_dumb *args); + +#endif /* _TVE200_DRM_H_ */ diff --git a/drivers/gpu/drm/tve200/tve200_drv.c b/drivers/gpu/drm/tve200/tve200_drv.c new file mode 100644 index 0000000..eae38b6 --- /dev/null +++ b/drivers/gpu/drm/tve200/tve200_drv.c @@ -0,0 +1,302 @@ +/* + * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org> + * Parts of this file were based on sources as follows: + * + * Copyright (C) 2006-2008 Intel Corporation + * Copyright (C) 2007 Amos Lee <amos_lee@storlinksemi.com> + * Copyright (C) 2007 Dave Airlie <airlied@linux.ie> + * Copyright (C) 2011 Texas Instruments + * Copyright (C) 2017 Eric Anholt + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms of + * such GNU licence. + */ + +/** + * DOC: Faraday TV Encoder TVE200 DRM Driver + * + * The Faraday TV Encoder TVE200 is also known as the Gemini TV Interface + * Controller (TVC) and is found in the Gemini Chipset from Storlink + * Semiconductor (later Storm Semiconductor, later Cortina Systems) + * but also in the Grain Media GM8180 chipset. On the Gemini the module + * is connected to 8 data lines and a single clock line, comprising an + * 8-bit BT.656 interface. + * + * This is a very basic YUV display driver. The datasheet specifies that + * it supports the ITU BT.656 standard. It requires a 27 MHz clock which is + * the hallmark of any TV encoder supporting both PAL and NTSC. + * + * This driver exposes a standard KMS interface for this TV encoder. + */ + +#include <linux/clk.h> +#include <linux/dma-buf.h> +#include <linux/irq.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/shmem_fs.h> +#include <linux/slab.h> +#include <linux/version.h> + +#include <drm/drmP.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_crtc_helper.h> +#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_panel.h> +#include <drm/drm_of.h> +#include <drm/drm_bridge.h> + +#include "tve200_drm.h" + +#define DRIVER_DESC "DRM module for Faraday TVE200" + +static const struct drm_mode_config_funcs mode_config_funcs = { + .fb_create = drm_fb_cma_create, + .atomic_check = drm_atomic_helper_check, + .atomic_commit = drm_atomic_helper_commit, +}; + +static int tve200_modeset_init(struct drm_device *dev) +{ + struct drm_mode_config *mode_config; + struct tve200_drm_dev_private *priv = dev->dev_private; + struct drm_panel *panel; + struct drm_bridge *bridge; + int ret = 0; + + drm_mode_config_init(dev); + mode_config = &dev->mode_config; + mode_config->funcs = &mode_config_funcs; + mode_config->min_width = 352; + mode_config->max_width = 720; + mode_config->min_height = 240; + mode_config->max_height = 576; + + ret = drm_of_find_panel_or_bridge(dev->dev->of_node, + 0, 0, &panel, &bridge); + if (ret && ret != -ENODEV) + return ret; + if (panel) { + bridge = drm_panel_bridge_add(panel, + DRM_MODE_CONNECTOR_Unknown); + if (IS_ERR(bridge)) { + ret = PTR_ERR(bridge); + goto out_bridge; + } + } else { + /* + * TODO: when we are using a different bridge than a panel + * (such as a dumb VGA connector) we need to devise a different + * method to get the connector out of the bridge. + */ + dev_err(dev->dev, "the bridge is not a panel\n"); + goto out_bridge; + } + + ret = tve200_display_init(dev); + if (ret) { + dev_err(dev->dev, "failed to init display\n"); + goto out_bridge; + } + + ret = drm_simple_display_pipe_attach_bridge(&priv->pipe, + bridge); + if (ret) { + dev_err(dev->dev, "failed to attach bridge\n"); + goto out_bridge; + } + + priv->panel = panel; + priv->connector = panel->connector; + priv->bridge = bridge; + + dev_info(dev->dev, "attached to panel %s\n", + dev_name(panel->dev)); + + ret = drm_vblank_init(dev, 1); + if (ret) { + dev_err(dev->dev, "failed to init vblank\n"); + goto out_bridge; + } + + drm_mode_config_reset(dev); + + /* + * Passing in 16 here will make the RGB656 mode the default + * Passing in 32 will use XRGB8888 mode + */ + priv->fbdev = drm_fbdev_cma_init(dev, 16, + dev->mode_config.num_connector); + drm_kms_helper_poll_init(dev); + + goto finish; + +out_bridge: + if (panel) + drm_panel_bridge_remove(bridge); + drm_mode_config_cleanup(dev); +finish: + return ret; +} + +DEFINE_DRM_GEM_CMA_FOPS(drm_fops); + +static void tve200_lastclose(struct drm_device *dev) +{ + struct tve200_drm_dev_private *priv = dev->dev_private; + + drm_fbdev_cma_restore_mode(priv->fbdev); +} + +static struct drm_driver tve200_drm_driver = { + .driver_features = + DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_ATOMIC, + .lastclose = tve200_lastclose, + .ioctls = NULL, + .fops = &drm_fops, + .name = "tve200", + .desc = DRIVER_DESC, + .date = "20170703", + .major = 1, + .minor = 0, + .patchlevel = 0, + .dumb_create = drm_gem_cma_dumb_create, + .gem_free_object_unlocked = drm_gem_cma_free_object, + .gem_vm_ops = &drm_gem_cma_vm_ops, + + .enable_vblank = tve200_enable_vblank, + .disable_vblank = tve200_disable_vblank, + + .prime_handle_to_fd = drm_gem_prime_handle_to_fd, + .prime_fd_to_handle = drm_gem_prime_fd_to_handle, + .gem_prime_import = drm_gem_prime_import, + .gem_prime_export = drm_gem_prime_export, + .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, + .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, + .gem_prime_vmap = drm_gem_cma_prime_vmap, + .gem_prime_vunmap = drm_gem_cma_prime_vunmap, + .gem_prime_mmap = drm_gem_cma_prime_mmap, +}; + +static int tve200_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct tve200_drm_dev_private *priv; + struct drm_device *drm; + struct resource *res; + int irq; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + drm = drm_dev_alloc(&tve200_drm_driver, dev); + if (IS_ERR(drm)) + return PTR_ERR(drm); + platform_set_drvdata(pdev, drm); + priv->drm = drm; + drm->dev_private = priv; + + /* Clock the silicon so we can access the registers */ + priv->pclk = devm_clk_get(dev, "PCLK"); + if (IS_ERR(priv->pclk)) { + dev_err(dev, "unable to get PCLK\n"); + ret = PTR_ERR(priv->pclk); + goto dev_unref; + } + ret = clk_prepare_enable(priv->pclk); + if (ret) { + dev_err(dev, "failed to enable PCLK\n"); + goto dev_unref; + } + + /* This clock is for the pixels (27MHz) */ + priv->clk = devm_clk_get(dev, "TVE"); + if (IS_ERR(priv->clk)) { + dev_err(dev, "unable to get TVE clock\n"); + ret = PTR_ERR(priv->clk); + goto clk_disable; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + priv->regs = devm_ioremap_resource(dev, res); + if (!priv->regs) { + dev_err(dev, "%s failed mmio\n", __func__); + ret = -EINVAL; + goto clk_disable; + } + + irq = platform_get_irq(pdev, 0); + if (!irq) { + ret = -EINVAL; + goto clk_disable; + } + + /* turn off interrupts before requesting the irq */ + writel(0, priv->regs + TVE200_INT_EN); + + ret = devm_request_irq(dev, irq, tve200_irq, 0, "tve200", priv); + if (ret) { + dev_err(dev, "failed to request irq %d\n", ret); + goto clk_disable; + } + + ret = tve200_modeset_init(drm); + if (ret) + goto clk_disable; + + ret = drm_dev_register(drm, 0); + if (ret < 0) + goto clk_disable; + + return 0; + +clk_disable: + clk_disable_unprepare(priv->pclk); +dev_unref: + drm_dev_unref(drm); + return ret; +} + +static int tve200_remove(struct platform_device *pdev) +{ + struct drm_device *drm = platform_get_drvdata(pdev); + struct tve200_drm_dev_private *priv = drm->dev_private; + + drm_dev_unregister(drm); + if (priv->fbdev) + drm_fbdev_cma_fini(priv->fbdev); + if (priv->panel) + drm_panel_bridge_remove(priv->bridge); + drm_mode_config_cleanup(drm); + clk_disable_unprepare(priv->pclk); + drm_dev_unref(drm); + + return 0; +} + +static const struct of_device_id tve200_of_match[] = { + { + .compatible = "faraday,tve200", + }, + {}, +}; + +static struct platform_driver tve200_driver = { + .driver = { + .name = "tve200", + .of_match_table = of_match_ptr(tve200_of_match), + }, + .probe = tve200_probe, + .remove = tve200_remove, +}; +module_platform_driver(tve200_driver); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/vc4/Makefile b/drivers/gpu/drm/vc4/Makefile index 25bd5d3..719a771 100644 --- a/drivers/gpu/drm/vc4/Makefile +++ b/drivers/gpu/drm/vc4/Makefile @@ -24,5 +24,3 @@ vc4-y := \ vc4-$(CONFIG_DEBUG_FS) += vc4_debugfs.o obj-$(CONFIG_DRM_VC4) += vc4.o - -CFLAGS_vc4_trace_points.o := -I$(src) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 937da8d..fa37a1c 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -309,16 +309,13 @@ static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs = static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev, struct drm_encoder *encoder) { - struct drm_connector *connector = NULL; + struct drm_connector *connector; struct vc4_hdmi_connector *hdmi_connector; - int ret = 0; hdmi_connector = devm_kzalloc(dev->dev, sizeof(*hdmi_connector), GFP_KERNEL); - if (!hdmi_connector) { - ret = -ENOMEM; - goto fail; - } + if (!hdmi_connector) + return ERR_PTR(-ENOMEM); connector = &hdmi_connector->base; hdmi_connector->encoder = encoder; @@ -336,12 +333,6 @@ static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev, drm_mode_connector_attach_encoder(connector, encoder); return connector; - - fail: - if (connector) - vc4_hdmi_connector_destroy(connector); - - return ERR_PTR(ret); } static void vc4_hdmi_encoder_destroy(struct drm_encoder *encoder) diff --git a/drivers/gpu/drm/vc4/vc4_trace.h b/drivers/gpu/drm/vc4/vc4_trace.h index ad7b1ea..deafb32 100644 --- a/drivers/gpu/drm/vc4/vc4_trace.h +++ b/drivers/gpu/drm/vc4/vc4_trace.h @@ -59,5 +59,5 @@ TRACE_EVENT(vc4_wait_for_seqno_end, /* This part must be outside protection */ #undef TRACE_INCLUDE_PATH -#define TRACE_INCLUDE_PATH . +#define TRACE_INCLUDE_PATH ../../drivers/gpu/drm/vc4 #include <trace/define_trace.h> diff --git a/drivers/gpu/drm/zte/zx_drm_drv.c b/drivers/gpu/drm/zte/zx_drm_drv.c index 4524482..e8b8266 100644 --- a/drivers/gpu/drm/zte/zx_drm_drv.c +++ b/drivers/gpu/drm/zte/zx_drm_drv.c @@ -22,6 +22,7 @@ #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_of.h> #include <drm/drmP.h> @@ -40,7 +41,7 @@ static void zx_drm_fb_output_poll_changed(struct drm_device *drm) } static const struct drm_mode_config_funcs zx_drm_mode_config_funcs = { - .fb_create = drm_fb_cma_create, + .fb_create = drm_gem_fb_create, .output_poll_changed = zx_drm_fb_output_poll_changed, .atomic_check = drm_atomic_helper_check, .atomic_commit = drm_atomic_helper_commit, |