提交 e9c3ddee 编写于 作者: D Dave Airlie

Merge branch 'drm-next-4.9' of git://people.freedesktop.org/~agd5f/linux into drm-next

First drm-next pull for radeon and amdgpu for 4.9.  Highlights:
- powerplay support for iceland asics
- improved GPU reset (both full asic and per block)
- UVD and VCE powergating for CZ and ST
- VCE clockgating for CZ and ST
- Support for pre-initialized (e.g., zeroed) vram buffers
- ttm cleanups
- virtual display support
- core and radeon/amdgpu support for page_flip_target
- lots of bug fixes and clean ups

* 'drm-next-4.9' of git://people.freedesktop.org/~agd5f/linux: (171 commits)
  drm/amdgpu: use memcpy_toio for VCE firmware upload
  drm/amdgpu: use memcpy_to/fromio for UVD fw upload
  drm/amd/powerplay: delete useless code in iceland_hwmgr.c.
  drm/radeon: switch UVD code to use UVD_NO_OP for padding
  drm/amdgpu: switch UVD code to use UVD_NO_OP for padding
  drm/radeon: add support for UVD_NO_OP register
  drm/amdgpu: add support for UVD_NO_OP register
  drm/amdgpu: fix VCE ib alignment value
  drm/amdgpu: fix IB alignment for UVD
  drm/amd/amdgpu: Print ring name in amdgpu_ib_schedule()
  drm/radeon: remove dead code, si_mc_load_microcode (v2)
  drm/radeon/cik: remove dead code (v2)
  drm/amd/powerplay: avoid NULL dereference, cz_hwmgr.c
  drm/amd/powerplay: avoid NULL pointer dereference
  drm/amdgpu/gmc8: remove dead code (v2)
  drm/amdgpu/gmc7: remove dead code (v2)
  drm/amdgpu: Fix indentation in dce_v8_0_audio_write_sad_regs()
  drm/amdgpu: Use correct mask in dce_v8_0_afmt_setmode() and fix comment typos.
  drm/amdgpu: cleanup amdgpu_vm_bo_update params
  drm/amdgpu: stop adding dummy entry in amdgpu_ttm_placement_init
  ...
......@@ -163,9 +163,6 @@ config DRM_AMDGPU
If M is selected, the module will be called amdgpu.
source "drivers/gpu/drm/amd/amdgpu/Kconfig"
source "drivers/gpu/drm/amd/powerplay/Kconfig"
source "drivers/gpu/drm/amd/acp/Kconfig"
source "drivers/gpu/drm/nouveau/Kconfig"
......
......@@ -25,3 +25,5 @@ config DRM_AMDGPU_GART_DEBUGFS
Selecting this option creates a debugfs file to inspect the mapped
pages. Uses more memory for housekeeping, enable only for debugging.
source "drivers/gpu/drm/amd/powerplay/Kconfig"
source "drivers/gpu/drm/amd/acp/Kconfig"
......@@ -58,7 +58,8 @@ amdgpu-y += \
# add DCE block
amdgpu-y += \
dce_v10_0.o \
dce_v11_0.o
dce_v11_0.o \
dce_virtual.o
# add GFX block
amdgpu-y += \
......
......@@ -90,6 +90,7 @@
#define ENCODER_OBJECT_ID_INTERNAL_VCE 0x24
#define ENCODER_OBJECT_ID_INTERNAL_UNIPHY3 0x25
#define ENCODER_OBJECT_ID_INTERNAL_AMCLK 0x27
#define ENCODER_OBJECT_ID_VIRTUAL 0x28
#define ENCODER_OBJECT_ID_GENERAL_EXTERNAL_DVO 0xFF
......@@ -119,6 +120,7 @@
#define CONNECTOR_OBJECT_ID_eDP 0x14
#define CONNECTOR_OBJECT_ID_MXM 0x15
#define CONNECTOR_OBJECT_ID_LVDS_eDP 0x16
#define CONNECTOR_OBJECT_ID_VIRTUAL 0x17
/* deleted */
......@@ -147,6 +149,7 @@
#define GRAPH_OBJECT_ENUM_ID5 0x05
#define GRAPH_OBJECT_ENUM_ID6 0x06
#define GRAPH_OBJECT_ENUM_ID7 0x07
#define GRAPH_OBJECT_ENUM_VIRTUAL 0x08
/****************************************************/
/* Graphics Object ID Bit definition */
......@@ -408,6 +411,10 @@
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_HDMI_ANX9805 << OBJECT_ID_SHIFT)
#define ENCODER_VIRTUAL_ENUM_VIRTUAL ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_VIRTUAL << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_VIRTUAL << OBJECT_ID_SHIFT)
/****************************************************/
/* Connector Object ID definition - Shared with BIOS */
/****************************************************/
......
......@@ -51,6 +51,7 @@
#include "amdgpu_ih.h"
#include "amdgpu_irq.h"
#include "amdgpu_ucode.h"
#include "amdgpu_ttm.h"
#include "amdgpu_gds.h"
#include "amd_powerplay.h"
#include "amdgpu_acp.h"
......@@ -91,6 +92,8 @@ extern unsigned amdgpu_pcie_lane_cap;
extern unsigned amdgpu_cg_mask;
extern unsigned amdgpu_pg_mask;
extern char *amdgpu_disable_cu;
extern int amdgpu_sclk_deep_sleep_en;
extern char *amdgpu_virtual_display;
#define AMDGPU_WAIT_IDLE_TIMEOUT_IN_MS 3000
#define AMDGPU_MAX_USEC_TIMEOUT 100000 /* 100 ms */
......@@ -248,10 +251,9 @@ struct amdgpu_vm_pte_funcs {
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,
const dma_addr_t *pages_addr, uint64_t pe,
uint64_t addr, unsigned count,
uint32_t incr, uint32_t flags);
void (*write_pte)(struct amdgpu_ib *ib, uint64_t pe,
uint64_t value, unsigned count,
uint32_t incr);
/* for linear pte/pde updates without addr mapping */
void (*set_pte_pde)(struct amdgpu_ib *ib,
uint64_t pe,
......@@ -396,46 +398,9 @@ int amdgpu_fence_wait_empty(struct amdgpu_ring *ring);
unsigned amdgpu_fence_count_emitted(struct amdgpu_ring *ring);
/*
* TTM.
* BO.
*/
#define AMDGPU_TTM_LRU_SIZE 20
struct amdgpu_mman_lru {
struct list_head *lru[TTM_NUM_MEM_TYPES];
struct list_head *swap_lru;
};
struct amdgpu_mman {
struct ttm_bo_global_ref bo_global_ref;
struct drm_global_reference mem_global_ref;
struct ttm_bo_device bdev;
bool mem_global_referenced;
bool initialized;
#if defined(CONFIG_DEBUG_FS)
struct dentry *vram;
struct dentry *gtt;
#endif
/* buffer handling */
const struct amdgpu_buffer_funcs *buffer_funcs;
struct amdgpu_ring *buffer_funcs_ring;
/* Scheduler entity for buffer moves */
struct amd_sched_entity entity;
/* custom LRU management */
struct amdgpu_mman_lru log2_size[AMDGPU_TTM_LRU_SIZE];
};
int amdgpu_copy_buffer(struct amdgpu_ring *ring,
uint64_t src_offset,
uint64_t dst_offset,
uint32_t byte_count,
struct reservation_object *resv,
struct fence **fence);
int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma);
struct amdgpu_bo_list_entry {
struct amdgpu_bo *robj;
struct ttm_validate_buffer tv;
......@@ -498,10 +463,12 @@ struct amdgpu_bo {
struct amdgpu_device *adev;
struct drm_gem_object gem_base;
struct amdgpu_bo *parent;
struct amdgpu_bo *shadow;
struct ttm_bo_kmap_obj dma_buf_vmap;
struct amdgpu_mn *mn;
struct list_head mn_list;
struct list_head shadow_list;
};
#define gem_to_amdgpu_bo(gobj) container_of((gobj), struct amdgpu_bo, gem_base)
......@@ -677,6 +644,8 @@ struct amdgpu_mc {
uint32_t fw_version;
struct amdgpu_irq_src vm_fault;
uint32_t vram_type;
uint32_t srbm_soft_reset;
struct amdgpu_mode_mc_save save;
};
/*
......@@ -721,10 +690,11 @@ void amdgpu_doorbell_get_kfd_info(struct amdgpu_device *adev,
*/
struct amdgpu_flip_work {
struct work_struct flip_work;
struct delayed_work flip_work;
struct work_struct unpin_work;
struct amdgpu_device *adev;
int crtc_id;
u32 target_vblank;
uint64_t base;
struct drm_pending_vblank_event *event;
struct amdgpu_bo *old_rbo;
......@@ -815,13 +785,17 @@ struct amdgpu_ring {
/* maximum number of VMIDs */
#define AMDGPU_NUM_VM 16
/* Maximum number of PTEs the hardware can write with one command */
#define AMDGPU_VM_MAX_UPDATE_SIZE 0x3FFFF
/* number of entries in page table */
#define AMDGPU_VM_PTE_COUNT (1 << amdgpu_vm_block_size)
/* PTBs (Page Table Blocks) need to be aligned to 32K */
#define AMDGPU_VM_PTB_ALIGN_SIZE 32768
#define AMDGPU_VM_PTB_ALIGN_MASK (AMDGPU_VM_PTB_ALIGN_SIZE - 1)
#define AMDGPU_VM_PTB_ALIGN(a) (((a) + AMDGPU_VM_PTB_ALIGN_MASK) & ~AMDGPU_VM_PTB_ALIGN_MASK)
/* LOG2 number of continuous pages for the fragment field */
#define AMDGPU_LOG2_PAGES_PER_FRAG 4
#define AMDGPU_PTE_VALID (1 << 0)
#define AMDGPU_PTE_SYSTEM (1 << 1)
......@@ -833,10 +807,7 @@ struct amdgpu_ring {
#define AMDGPU_PTE_READABLE (1 << 5)
#define AMDGPU_PTE_WRITEABLE (1 << 6)
/* PTE (Page Table Entry) fragment field for different page sizes */
#define AMDGPU_PTE_FRAG_4KB (0 << 7)
#define AMDGPU_PTE_FRAG_64KB (4 << 7)
#define AMDGPU_LOG2_PAGES_PER_FRAG 4
#define AMDGPU_PTE_FRAG(x) ((x & 0x1f) << 7)
/* How to programm VM fault handling */
#define AMDGPU_VM_FAULT_STOP_NEVER 0
......@@ -846,6 +817,7 @@ struct amdgpu_ring {
struct amdgpu_vm_pt {
struct amdgpu_bo_list_entry entry;
uint64_t addr;
uint64_t shadow_addr;
};
struct amdgpu_vm {
......@@ -948,7 +920,6 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
struct amdgpu_job *job);
int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job);
void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vm_id);
uint64_t amdgpu_vm_map_gart(const dma_addr_t *pages_addr, uint64_t addr);
int amdgpu_vm_update_page_directory(struct amdgpu_device *adev,
struct amdgpu_vm *vm);
int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
......@@ -957,7 +928,7 @@ int amdgpu_vm_clear_invalids(struct amdgpu_device *adev, struct amdgpu_vm *vm,
struct amdgpu_sync *sync);
int amdgpu_vm_bo_update(struct amdgpu_device *adev,
struct amdgpu_bo_va *bo_va,
struct ttm_mem_reg *mem);
bool clear);
void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev,
struct amdgpu_bo *bo);
struct amdgpu_bo_va *amdgpu_vm_bo_find(struct amdgpu_vm *vm,
......@@ -1195,6 +1166,10 @@ struct amdgpu_gfx {
unsigned ce_ram_size;
struct amdgpu_cu_info cu_info;
const struct amdgpu_gfx_funcs *funcs;
/* reset mask */
uint32_t grbm_soft_reset;
uint32_t srbm_soft_reset;
};
int amdgpu_ib_get(struct amdgpu_device *adev, struct amdgpu_vm *vm,
......@@ -1683,6 +1658,7 @@ struct amdgpu_uvd {
bool address_64_bit;
bool use_ctx_buf;
struct amd_sched_entity entity;
uint32_t srbm_soft_reset;
};
/*
......@@ -1709,6 +1685,7 @@ struct amdgpu_vce {
struct amdgpu_irq_src irq;
unsigned harvest_config;
struct amd_sched_entity entity;
uint32_t srbm_soft_reset;
};
/*
......@@ -1729,6 +1706,7 @@ struct amdgpu_sdma {
struct amdgpu_irq_src trap_irq;
struct amdgpu_irq_src illegal_inst_irq;
int num_instances;
uint32_t srbm_soft_reset;
};
/*
......@@ -1956,6 +1934,7 @@ struct amdgpu_ip_block_status {
bool valid;
bool sw;
bool hw;
bool hang;
};
struct amdgpu_device {
......@@ -2055,6 +2034,7 @@ struct amdgpu_device {
atomic_t gpu_reset_counter;
/* display */
bool enable_virtual_display;
struct amdgpu_mode_info mode_info;
struct work_struct hotplug_work;
struct amdgpu_irq_src crtc_irq;
......@@ -2117,6 +2097,10 @@ struct amdgpu_device {
struct kfd_dev *kfd;
struct amdgpu_virtualization virtualization;
/* link all shadow bo */
struct list_head shadow_list;
struct mutex shadow_list_lock;
};
bool amdgpu_device_is_px(struct drm_device *dev);
......@@ -2192,6 +2176,9 @@ void amdgpu_mm_wdoorbell(struct amdgpu_device *adev, u32 index, u32 v);
#define REG_GET_FIELD(value, reg, field) \
(((value) & REG_FIELD_MASK(reg, field)) >> REG_FIELD_SHIFT(reg, field))
#define WREG32_FIELD(reg, field, val) \
WREG32(mm##reg, (RREG32(mm##reg) & ~REG_FIELD_MASK(reg, field)) | (val) << REG_FIELD_SHIFT(reg, field))
/*
* BIOS helpers.
*/
......@@ -2242,7 +2229,7 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring)
#define amdgpu_gart_flush_gpu_tlb(adev, vmid) (adev)->gart.gart_funcs->flush_gpu_tlb((adev), (vmid))
#define amdgpu_gart_set_pte_pde(adev, pt, idx, addr, flags) (adev)->gart.gart_funcs->set_pte_pde((adev), (pt), (idx), (addr), (flags))
#define amdgpu_vm_copy_pte(adev, ib, pe, src, count) ((adev)->vm_manager.vm_pte_funcs->copy_pte((ib), (pe), (src), (count)))
#define amdgpu_vm_write_pte(adev, ib, pa, pe, addr, count, incr, flags) ((adev)->vm_manager.vm_pte_funcs->write_pte((ib), (pa), (pe), (addr), (count), (incr), (flags)))
#define amdgpu_vm_write_pte(adev, ib, pe, value, count, incr) ((adev)->vm_manager.vm_pte_funcs->write_pte((ib), (pe), (value), (count), (incr)))
#define amdgpu_vm_set_pte_pde(adev, ib, pe, addr, count, incr, flags) ((adev)->vm_manager.vm_pte_funcs->set_pte_pde((ib), (pe), (addr), (count), (incr), (flags)))
#define amdgpu_ring_parse_cs(r, p, ib) ((r)->funcs->parse_cs((p), (ib)))
#define amdgpu_ring_test_ring(r) (r)->funcs->test_ring((r))
......@@ -2387,6 +2374,7 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring)
/* Common functions */
int amdgpu_gpu_reset(struct amdgpu_device *adev);
bool amdgpu_need_backup(struct amdgpu_device *adev);
void amdgpu_pci_config_reset(struct amdgpu_device *adev);
bool amdgpu_card_posted(struct amdgpu_device *adev);
void amdgpu_update_display_priority(struct amdgpu_device *adev);
......@@ -2412,6 +2400,8 @@ uint32_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm,
void amdgpu_vram_location(struct amdgpu_device *adev, struct amdgpu_mc *mc, u64 base);
void amdgpu_gtt_location(struct amdgpu_device *adev, struct amdgpu_mc *mc);
void amdgpu_ttm_set_active_vram_size(struct amdgpu_device *adev, u64 size);
u64 amdgpu_ttm_get_gtt_mem_size(struct amdgpu_device *adev);
int amdgpu_ttm_global_init(struct amdgpu_device *adev);
void amdgpu_program_register_sequence(struct amdgpu_device *adev,
const u32 *registers,
const u32 array_size);
......
......@@ -259,6 +259,33 @@ static const int object_connector_convert[] = {
DRM_MODE_CONNECTOR_Unknown
};
bool amdgpu_atombios_has_dce_engine_info(struct amdgpu_device *adev)
{
struct amdgpu_mode_info *mode_info = &adev->mode_info;
struct atom_context *ctx = mode_info->atom_context;
int index = GetIndexIntoMasterTable(DATA, Object_Header);
u16 size, data_offset;
u8 frev, crev;
ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj;
ATOM_OBJECT_HEADER *obj_header;
if (!amdgpu_atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset))
return false;
if (crev < 2)
return false;
obj_header = (ATOM_OBJECT_HEADER *) (ctx->bios + data_offset);
path_obj = (ATOM_DISPLAY_OBJECT_PATH_TABLE *)
(ctx->bios + data_offset +
le16_to_cpu(obj_header->usDisplayPathTableOffset));
if (path_obj->ucNumOfDispPath)
return true;
else
return false;
}
bool amdgpu_atombios_get_connector_info_from_object_table(struct amdgpu_device *adev)
{
struct amdgpu_mode_info *mode_info = &adev->mode_info;
......
......@@ -140,6 +140,8 @@ struct amdgpu_i2c_bus_rec amdgpu_atombios_lookup_i2c_gpio(struct amdgpu_device *
uint8_t id);
void amdgpu_atombios_i2c_init(struct amdgpu_device *adev);
bool amdgpu_atombios_has_dce_engine_info(struct amdgpu_device *adev);
bool amdgpu_atombios_get_connector_info_from_object_table(struct amdgpu_device *adev);
int amdgpu_atombios_get_clock_info(struct amdgpu_device *adev);
......
......@@ -39,7 +39,8 @@ static int amdgpu_benchmark_do_move(struct amdgpu_device *adev, unsigned size,
start_jiffies = jiffies;
for (i = 0; i < n; i++) {
struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring;
r = amdgpu_copy_buffer(ring, saddr, daddr, size, NULL, &fence);
r = amdgpu_copy_buffer(ring, saddr, daddr, size, NULL, &fence,
false);
if (r)
goto exit_do_move;
r = fence_wait(fence, false);
......
......@@ -1504,6 +1504,86 @@ static const struct drm_connector_funcs amdgpu_connector_edp_funcs = {
.force = amdgpu_connector_dvi_force,
};
static struct drm_encoder *
amdgpu_connector_virtual_encoder(struct drm_connector *connector)
{
int enc_id = connector->encoder_ids[0];
struct drm_encoder *encoder;
int i;
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
if (connector->encoder_ids[i] == 0)
break;
encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]);
if (!encoder)
continue;
if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL)
return encoder;
}
/* pick the first one */
if (enc_id)
return drm_encoder_find(connector->dev, enc_id);
return NULL;
}
static int amdgpu_connector_virtual_get_modes(struct drm_connector *connector)
{
struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
if (encoder) {
amdgpu_connector_add_common_modes(encoder, connector);
}
return 0;
}
static int amdgpu_connector_virtual_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
return MODE_OK;
}
int amdgpu_connector_virtual_dpms(struct drm_connector *connector, int mode)
{
return 0;
}
static enum drm_connector_status
amdgpu_connector_virtual_detect(struct drm_connector *connector, bool force)
{
return connector_status_connected;
}
int amdgpu_connector_virtual_set_property(struct drm_connector *connector,
struct drm_property *property,
uint64_t val)
{
return 0;
}
static void amdgpu_connector_virtual_force(struct drm_connector *connector)
{
return;
}
static const struct drm_connector_helper_funcs amdgpu_connector_virtual_helper_funcs = {
.get_modes = amdgpu_connector_virtual_get_modes,
.mode_valid = amdgpu_connector_virtual_mode_valid,
.best_encoder = amdgpu_connector_virtual_encoder,
};
static const struct drm_connector_funcs amdgpu_connector_virtual_funcs = {
.dpms = amdgpu_connector_virtual_dpms,
.detect = amdgpu_connector_virtual_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.set_property = amdgpu_connector_virtual_set_property,
.destroy = amdgpu_connector_destroy,
.force = amdgpu_connector_virtual_force,
};
void
amdgpu_connector_add(struct amdgpu_device *adev,
uint32_t connector_id,
......@@ -1888,6 +1968,17 @@ amdgpu_connector_add(struct amdgpu_device *adev,
connector->interlace_allowed = false;
connector->doublescan_allowed = false;
break;
case DRM_MODE_CONNECTOR_VIRTUAL:
amdgpu_dig_connector = kzalloc(sizeof(struct amdgpu_connector_atom_dig), GFP_KERNEL);
if (!amdgpu_dig_connector)
goto failed;
amdgpu_connector->con_priv = amdgpu_dig_connector;
drm_connector_init(dev, &amdgpu_connector->base, &amdgpu_connector_virtual_funcs, connector_type);
drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_virtual_helper_funcs);
subpixel_order = SubPixelHorizontalRGB;
connector->interlace_allowed = false;
connector->doublescan_allowed = false;
break;
}
}
......
......@@ -287,18 +287,56 @@ static u64 amdgpu_cs_get_threshold_for_moves(struct amdgpu_device *adev)
return max(bytes_moved_threshold, 1024*1024ull);
}
static int amdgpu_cs_bo_validate(struct amdgpu_cs_parser *p,
struct amdgpu_bo *bo)
{
u64 initial_bytes_moved;
uint32_t domain;
int r;
if (bo->pin_count)
return 0;
/* Avoid moving this one if we have moved too many buffers
* for this IB already.
*
* Note that this allows moving at least one buffer of
* any size, because it doesn't take the current "bo"
* into account. We don't want to disallow buffer moves
* completely.
*/
if (p->bytes_moved <= p->bytes_moved_threshold)
domain = bo->prefered_domains;
else
domain = bo->allowed_domains;
retry:
amdgpu_ttm_placement_from_domain(bo, domain);
initial_bytes_moved = atomic64_read(&bo->adev->num_bytes_moved);
r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false);
p->bytes_moved += atomic64_read(&bo->adev->num_bytes_moved) -
initial_bytes_moved;
if (unlikely(r)) {
if (r != -ERESTARTSYS && domain != bo->allowed_domains) {
domain = bo->allowed_domains;
goto retry;
}
}
return r;
}
int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p,
struct list_head *validated)
{
struct amdgpu_bo_list_entry *lobj;
u64 initial_bytes_moved;
int r;
list_for_each_entry(lobj, validated, tv.head) {
struct amdgpu_bo *bo = lobj->robj;
bool binding_userptr = false;
struct mm_struct *usermm;
uint32_t domain;
usermm = amdgpu_ttm_tt_get_usermm(bo->tbo.ttm);
if (usermm && usermm != current->mm)
......@@ -313,35 +351,13 @@ int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p,
binding_userptr = true;
}
if (bo->pin_count)
continue;
/* Avoid moving this one if we have moved too many buffers
* for this IB already.
*
* Note that this allows moving at least one buffer of
* any size, because it doesn't take the current "bo"
* into account. We don't want to disallow buffer moves
* completely.
*/
if (p->bytes_moved <= p->bytes_moved_threshold)
domain = bo->prefered_domains;
else
domain = bo->allowed_domains;
retry:
amdgpu_ttm_placement_from_domain(bo, domain);
initial_bytes_moved = atomic64_read(&bo->adev->num_bytes_moved);
r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false);
p->bytes_moved += atomic64_read(&bo->adev->num_bytes_moved) -
initial_bytes_moved;
if (unlikely(r)) {
if (r != -ERESTARTSYS && domain != bo->allowed_domains) {
domain = bo->allowed_domains;
goto retry;
}
r = amdgpu_cs_bo_validate(p, bo);
if (r)
return r;
if (bo->shadow) {
r = amdgpu_cs_bo_validate(p, bo);
if (r)
return r;
}
if (binding_userptr) {
......@@ -386,8 +402,10 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
r = ttm_eu_reserve_buffers(&p->ticket, &p->validated, true,
&duplicates);
if (unlikely(r != 0))
if (unlikely(r != 0)) {
DRM_ERROR("ttm_eu_reserve_buffers failed.\n");
goto error_free_pages;
}
/* Without a BO list we don't have userptr BOs */
if (!p->bo_list)
......@@ -427,9 +445,10 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
/* Unreserve everything again. */
ttm_eu_backoff_reservation(&p->ticket, &p->validated);
/* We tried to often, just abort */
/* We tried too many times, just abort */
if (!--tries) {
r = -EDEADLK;
DRM_ERROR("deadlock in %s\n", __func__);
goto error_free_pages;
}
......@@ -441,11 +460,13 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
sizeof(struct page*));
if (!e->user_pages) {
r = -ENOMEM;
DRM_ERROR("calloc failure in %s\n", __func__);
goto error_free_pages;
}
r = amdgpu_ttm_tt_get_user_pages(ttm, e->user_pages);
if (r) {
DRM_ERROR("amdgpu_ttm_tt_get_user_pages failed.\n");
drm_free_large(e->user_pages);
e->user_pages = NULL;
goto error_free_pages;
......@@ -462,12 +483,16 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
p->bytes_moved = 0;
r = amdgpu_cs_list_validate(p, &duplicates);
if (r)
if (r) {
DRM_ERROR("amdgpu_cs_list_validate(duplicates) failed.\n");
goto error_validate;
}
r = amdgpu_cs_list_validate(p, &p->validated);
if (r)
if (r) {
DRM_ERROR("amdgpu_cs_list_validate(validated) failed.\n");
goto error_validate;
}
fpriv->vm.last_eviction_counter =
atomic64_read(&p->adev->num_evictions);
......@@ -617,7 +642,7 @@ static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p,
if (bo_va == NULL)
continue;
r = amdgpu_vm_bo_update(adev, bo_va, &bo->tbo.mem);
r = amdgpu_vm_bo_update(adev, bo_va, false);
if (r)
return r;
......
......@@ -46,6 +46,7 @@
#endif
#include "vi.h"
#include "bif/bif_4_1_d.h"
#include <linux/pci.h>
static int amdgpu_debugfs_regs_init(struct amdgpu_device *adev);
static void amdgpu_debugfs_regs_cleanup(struct amdgpu_device *adev);
......@@ -1181,10 +1182,38 @@ int amdgpu_ip_block_version_cmp(struct amdgpu_device *adev,
return 1;
}
static void amdgpu_whether_enable_virtual_display(struct amdgpu_device *adev)
{
adev->enable_virtual_display = false;
if (amdgpu_virtual_display) {
struct drm_device *ddev = adev->ddev;
const char *pci_address_name = pci_name(ddev->pdev);
char *pciaddstr, *pciaddstr_tmp, *pciaddname;
pciaddstr = kstrdup(amdgpu_virtual_display, GFP_KERNEL);
pciaddstr_tmp = pciaddstr;
while ((pciaddname = strsep(&pciaddstr_tmp, ";"))) {
if (!strcmp(pci_address_name, pciaddname)) {
adev->enable_virtual_display = true;
break;
}
}
DRM_INFO("virtual display string:%s, %s:virtual_display:%d\n",
amdgpu_virtual_display, pci_address_name,
adev->enable_virtual_display);
kfree(pciaddstr);
}
}
static int amdgpu_early_init(struct amdgpu_device *adev)
{
int i, r;
amdgpu_whether_enable_virtual_display(adev);
switch (adev->asic_type) {
case CHIP_TOPAZ:
case CHIP_TONGA:
......@@ -1521,6 +1550,9 @@ int amdgpu_device_init(struct amdgpu_device *adev,
spin_lock_init(&adev->gc_cac_idx_lock);
spin_lock_init(&adev->audio_endpt_idx_lock);
INIT_LIST_HEAD(&adev->shadow_list);
mutex_init(&adev->shadow_list_lock);
adev->rmmio_base = pci_resource_start(adev->pdev, 5);
adev->rmmio_size = pci_resource_len(adev->pdev, 5);
adev->rmmio = ioremap(adev->rmmio_base, adev->rmmio_size);
......@@ -1937,6 +1969,126 @@ int amdgpu_resume_kms(struct drm_device *dev, bool resume, bool fbcon)
return 0;
}
static bool amdgpu_check_soft_reset(struct amdgpu_device *adev)
{
int i;
bool asic_hang = false;
for (i = 0; i < adev->num_ip_blocks; i++) {
if (!adev->ip_block_status[i].valid)
continue;
if (adev->ip_blocks[i].funcs->check_soft_reset)
adev->ip_blocks[i].funcs->check_soft_reset(adev);
if (adev->ip_block_status[i].hang) {
DRM_INFO("IP block:%d is hang!\n", i);
asic_hang = true;
}
}
return asic_hang;
}
int amdgpu_pre_soft_reset(struct amdgpu_device *adev)
{
int i, r = 0;
for (i = 0; i < adev->num_ip_blocks; i++) {
if (!adev->ip_block_status[i].valid)
continue;
if (adev->ip_block_status[i].hang &&
adev->ip_blocks[i].funcs->pre_soft_reset) {
r = adev->ip_blocks[i].funcs->pre_soft_reset(adev);
if (r)
return r;
}
}
return 0;
}
static bool amdgpu_need_full_reset(struct amdgpu_device *adev)
{
if (adev->ip_block_status[AMD_IP_BLOCK_TYPE_GMC].hang ||
adev->ip_block_status[AMD_IP_BLOCK_TYPE_SMC].hang ||
adev->ip_block_status[AMD_IP_BLOCK_TYPE_ACP].hang ||
adev->ip_block_status[AMD_IP_BLOCK_TYPE_DCE].hang) {
DRM_INFO("Some block need full reset!\n");
return true;
}
return false;
}
static int amdgpu_soft_reset(struct amdgpu_device *adev)
{
int i, r = 0;
for (i = 0; i < adev->num_ip_blocks; i++) {
if (!adev->ip_block_status[i].valid)
continue;
if (adev->ip_block_status[i].hang &&
adev->ip_blocks[i].funcs->soft_reset) {
r = adev->ip_blocks[i].funcs->soft_reset(adev);
if (r)
return r;
}
}
return 0;
}
static int amdgpu_post_soft_reset(struct amdgpu_device *adev)
{
int i, r = 0;
for (i = 0; i < adev->num_ip_blocks; i++) {
if (!adev->ip_block_status[i].valid)
continue;
if (adev->ip_block_status[i].hang &&
adev->ip_blocks[i].funcs->post_soft_reset)
r = adev->ip_blocks[i].funcs->post_soft_reset(adev);
if (r)
return r;
}
return 0;
}
bool amdgpu_need_backup(struct amdgpu_device *adev)
{
if (adev->flags & AMD_IS_APU)
return false;
return amdgpu_lockup_timeout > 0 ? true : false;
}
static int amdgpu_recover_vram_from_shadow(struct amdgpu_device *adev,
struct amdgpu_ring *ring,
struct amdgpu_bo *bo,
struct fence **fence)
{
uint32_t domain;
int r;
if (!bo->shadow)
return 0;
r = amdgpu_bo_reserve(bo, false);
if (r)
return r;
domain = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type);
/* if bo has been evicted, then no need to recover */
if (domain == AMDGPU_GEM_DOMAIN_VRAM) {
r = amdgpu_bo_restore_from_shadow(adev, ring, bo,
NULL, fence, true);
if (r) {
DRM_ERROR("recover page table failed!\n");
goto err;
}
}
err:
amdgpu_bo_unreserve(bo);
return r;
}
/**
* amdgpu_gpu_reset - reset the asic
*
......@@ -1949,6 +2101,12 @@ int amdgpu_gpu_reset(struct amdgpu_device *adev)
{
int i, r;
int resched;
bool need_full_reset;
if (!amdgpu_check_soft_reset(adev)) {
DRM_INFO("No hardware hang detected. Did some blocks stall?\n");
return 0;
}
atomic_inc(&adev->gpu_reset_counter);
......@@ -1967,40 +2125,88 @@ int amdgpu_gpu_reset(struct amdgpu_device *adev)
/* after all hw jobs are reset, hw fence is meaningless, so force_completion */
amdgpu_fence_driver_force_completion(adev);
/* save scratch */
amdgpu_atombios_scratch_regs_save(adev);
r = amdgpu_suspend(adev);
need_full_reset = amdgpu_need_full_reset(adev);
retry:
/* Disable fb access */
if (adev->mode_info.num_crtc) {
struct amdgpu_mode_mc_save save;
amdgpu_display_stop_mc_access(adev, &save);
amdgpu_wait_for_idle(adev, AMD_IP_BLOCK_TYPE_GMC);
if (!need_full_reset) {
amdgpu_pre_soft_reset(adev);
r = amdgpu_soft_reset(adev);
amdgpu_post_soft_reset(adev);
if (r || amdgpu_check_soft_reset(adev)) {
DRM_INFO("soft reset failed, will fallback to full reset!\n");
need_full_reset = true;
}
}
r = amdgpu_asic_reset(adev);
/* post card */
amdgpu_atom_asic_init(adev->mode_info.atom_context);
if (need_full_reset) {
/* save scratch */
amdgpu_atombios_scratch_regs_save(adev);
r = amdgpu_suspend(adev);
if (!r) {
dev_info(adev->dev, "GPU reset succeeded, trying to resume\n");
r = amdgpu_resume(adev);
retry:
/* Disable fb access */
if (adev->mode_info.num_crtc) {
struct amdgpu_mode_mc_save save;
amdgpu_display_stop_mc_access(adev, &save);
amdgpu_wait_for_idle(adev, AMD_IP_BLOCK_TYPE_GMC);
}
r = amdgpu_asic_reset(adev);
/* post card */
amdgpu_atom_asic_init(adev->mode_info.atom_context);
if (!r) {
dev_info(adev->dev, "GPU reset succeeded, trying to resume\n");
r = amdgpu_resume(adev);
}
/* restore scratch */
amdgpu_atombios_scratch_regs_restore(adev);
}
/* restore scratch */
amdgpu_atombios_scratch_regs_restore(adev);
if (!r) {
amdgpu_irq_gpu_reset_resume_helper(adev);
r = amdgpu_ib_ring_tests(adev);
if (r) {
dev_err(adev->dev, "ib ring test failed (%d).\n", r);
r = amdgpu_suspend(adev);
need_full_reset = true;
goto retry;
}
/**
* recovery vm page tables, since we cannot depend on VRAM is
* consistent after gpu full reset.
*/
if (need_full_reset && amdgpu_need_backup(adev)) {
struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring;
struct amdgpu_bo *bo, *tmp;
struct fence *fence = NULL, *next = NULL;
DRM_INFO("recover vram bo from shadow\n");
mutex_lock(&adev->shadow_list_lock);
list_for_each_entry_safe(bo, tmp, &adev->shadow_list, shadow_list) {
amdgpu_recover_vram_from_shadow(adev, ring, bo, &next);
if (fence) {
r = fence_wait(fence, false);
if (r) {
WARN(r, "recovery from shadow isn't comleted\n");
break;
}
}
fence_put(fence);
fence = next;
}
mutex_unlock(&adev->shadow_list_lock);
if (fence) {
r = fence_wait(fence, false);
if (r)
WARN(r, "recovery from shadow isn't comleted\n");
}
fence_put(fence);
}
for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
struct amdgpu_ring *ring = adev->rings[i];
if (!ring)
continue;
amd_sched_job_recovery(&ring->sched);
kthread_unpark(ring->sched.thread);
}
......@@ -2020,7 +2226,6 @@ int amdgpu_gpu_reset(struct amdgpu_device *adev)
/* bad news, how to tell it to userspace ? */
dev_info(adev->dev, "GPU reset failed\n");
}
amdgpu_irq_gpu_reset_resume_helper(adev);
return r;
}
......@@ -2178,22 +2383,26 @@ static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf,
struct amdgpu_device *adev = f->f_inode->i_private;
ssize_t result = 0;
int r;
bool use_bank;
bool pm_pg_lock, use_bank;
unsigned instance_bank, sh_bank, se_bank;
if (size & 0x3 || *pos & 0x3)
return -EINVAL;
/* are we reading registers for which a PG lock is necessary? */
pm_pg_lock = (*pos >> 23) & 1;
if (*pos & (1ULL << 62)) {
se_bank = (*pos >> 24) & 0x3FF;
sh_bank = (*pos >> 34) & 0x3FF;
instance_bank = (*pos >> 44) & 0x3FF;
use_bank = 1;
*pos &= 0xFFFFFF;
} else {
use_bank = 0;
}
*pos &= 0x3FFFF;
if (use_bank) {
if (sh_bank >= adev->gfx.config.max_sh_per_se ||
se_bank >= adev->gfx.config.max_shader_engines)
......@@ -2203,6 +2412,9 @@ static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf,
sh_bank, instance_bank);
}
if (pm_pg_lock)
mutex_lock(&adev->pm.mutex);
while (size) {
uint32_t value;
......@@ -2228,6 +2440,9 @@ static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf,
mutex_unlock(&adev->grbm_idx_mutex);
}
if (pm_pg_lock)
mutex_unlock(&adev->pm.mutex);
return result;
}
......@@ -2443,7 +2658,7 @@ static ssize_t amdgpu_debugfs_gca_config_read(struct file *f, char __user *buf,
return -ENOMEM;
/* version, increment each time something is added */
config[no_regs++] = 0;
config[no_regs++] = 2;
config[no_regs++] = adev->gfx.config.max_shader_engines;
config[no_regs++] = adev->gfx.config.max_tile_pipes;
config[no_regs++] = adev->gfx.config.max_cu_per_sh;
......@@ -2468,6 +2683,15 @@ static ssize_t amdgpu_debugfs_gca_config_read(struct file *f, char __user *buf,
config[no_regs++] = adev->gfx.config.gb_addr_config;
config[no_regs++] = adev->gfx.config.num_rbs;
/* rev==1 */
config[no_regs++] = adev->rev_id;
config[no_regs++] = adev->pg_flags;
config[no_regs++] = adev->cg_flags;
/* rev==2 */
config[no_regs++] = adev->family;
config[no_regs++] = adev->external_rev_id;
while (size && (*pos < no_regs * 4)) {
uint32_t value;
......
......@@ -41,7 +41,7 @@ static void amdgpu_flip_callback(struct fence *f, struct fence_cb *cb)
container_of(cb, struct amdgpu_flip_work, cb);
fence_put(f);
schedule_work(&work->flip_work);
schedule_work(&work->flip_work.work);
}
static bool amdgpu_flip_handle_fence(struct amdgpu_flip_work *work,
......@@ -63,16 +63,17 @@ static bool amdgpu_flip_handle_fence(struct amdgpu_flip_work *work,
static void amdgpu_flip_work_func(struct work_struct *__work)
{
struct delayed_work *delayed_work =
container_of(__work, struct delayed_work, work);
struct amdgpu_flip_work *work =
container_of(__work, struct amdgpu_flip_work, flip_work);
container_of(delayed_work, struct amdgpu_flip_work, flip_work);
struct amdgpu_device *adev = work->adev;
struct amdgpu_crtc *amdgpuCrtc = adev->mode_info.crtcs[work->crtc_id];
struct drm_crtc *crtc = &amdgpuCrtc->base;
unsigned long flags;
unsigned i, repcnt = 4;
int vpos, hpos, stat, min_udelay = 0;
struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id];
unsigned i;
int vpos, hpos;
if (amdgpu_flip_handle_fence(work, &work->excl))
return;
......@@ -81,55 +82,23 @@ static void amdgpu_flip_work_func(struct work_struct *__work)
if (amdgpu_flip_handle_fence(work, &work->shared[i]))
return;
/* We borrow the event spin lock for protecting flip_status */
spin_lock_irqsave(&crtc->dev->event_lock, flags);
/* If this happens to execute within the "virtually extended" vblank
* interval before the start of the real vblank interval then it needs
* to delay programming the mmio flip until the real vblank is entered.
* This prevents completing a flip too early due to the way we fudge
* our vblank counter and vblank timestamps in order to work around the
* problem that the hw fires vblank interrupts before actual start of
* vblank (when line buffer refilling is done for a frame). It
* complements the fudging logic in amdgpu_get_crtc_scanoutpos() for
* timestamping and amdgpu_get_vblank_counter_kms() for vblank counts.
*
* In practice this won't execute very often unless on very fast
* machines because the time window for this to happen is very small.
/* Wait until we're out of the vertical blank period before the one
* targeted by the flip
*/
while (amdgpuCrtc->enabled && --repcnt) {
/* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank
* start in hpos, and to the "fudged earlier" vblank start in
* vpos.
*/
stat = amdgpu_get_crtc_scanoutpos(adev->ddev, work->crtc_id,
GET_DISTANCE_TO_VBLANKSTART,
&vpos, &hpos, NULL, NULL,
&crtc->hwmode);
if ((stat & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE)) !=
(DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE) ||
!(vpos >= 0 && hpos <= 0))
break;
/* Sleep at least until estimated real start of hw vblank */
min_udelay = (-hpos + 1) * max(vblank->linedur_ns / 1000, 5);
if (min_udelay > vblank->framedur_ns / 2000) {
/* Don't wait ridiculously long - something is wrong */
repcnt = 0;
break;
}
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
usleep_range(min_udelay, 2 * min_udelay);
spin_lock_irqsave(&crtc->dev->event_lock, flags);
if (amdgpuCrtc->enabled &&
(amdgpu_get_crtc_scanoutpos(adev->ddev, work->crtc_id, 0,
&vpos, &hpos, NULL, NULL,
&crtc->hwmode)
& (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK)) ==
(DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK) &&
(int)(work->target_vblank -
amdgpu_get_vblank_counter_kms(adev->ddev, amdgpuCrtc->crtc_id)) > 0) {
schedule_delayed_work(&work->flip_work, usecs_to_jiffies(1000));
return;
}
if (!repcnt)
DRM_DEBUG_DRIVER("Delay problem on crtc %d: min_udelay %d, "
"framedur %d, linedur %d, stat %d, vpos %d, "
"hpos %d\n", work->crtc_id, min_udelay,
vblank->framedur_ns / 1000,
vblank->linedur_ns / 1000, stat, vpos, hpos);
/* We borrow the event spin lock for protecting flip_status */
spin_lock_irqsave(&crtc->dev->event_lock, flags);
/* Do the flip (mmio) */
adev->mode_info.funcs->page_flip(adev, work->crtc_id, work->base, work->async);
......@@ -169,10 +138,10 @@ static void amdgpu_unpin_work_func(struct work_struct *__work)
kfree(work);
}
int amdgpu_crtc_page_flip(struct drm_crtc *crtc,
struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event,
uint32_t page_flip_flags)
int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc,
struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event,
uint32_t page_flip_flags, uint32_t target)
{
struct drm_device *dev = crtc->dev;
struct amdgpu_device *adev = dev->dev_private;
......@@ -191,7 +160,7 @@ int amdgpu_crtc_page_flip(struct drm_crtc *crtc,
if (work == NULL)
return -ENOMEM;
INIT_WORK(&work->flip_work, amdgpu_flip_work_func);
INIT_DELAYED_WORK(&work->flip_work, amdgpu_flip_work_func);
INIT_WORK(&work->unpin_work, amdgpu_unpin_work_func);
work->event = event;
......@@ -237,12 +206,8 @@ int amdgpu_crtc_page_flip(struct drm_crtc *crtc,
amdgpu_bo_unreserve(new_rbo);
work->base = base;
r = drm_crtc_vblank_get(crtc);
if (r) {
DRM_ERROR("failed to get vblank before flip\n");
goto pflip_cleanup;
}
work->target_vblank = target - drm_crtc_vblank_count(crtc) +
amdgpu_get_vblank_counter_kms(dev, work->crtc_id);
/* we borrow the event spin lock for protecting flip_wrok */
spin_lock_irqsave(&crtc->dev->event_lock, flags);
......@@ -250,7 +215,7 @@ int amdgpu_crtc_page_flip(struct drm_crtc *crtc,
DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
r = -EBUSY;
goto vblank_cleanup;
goto pflip_cleanup;
}
amdgpu_crtc->pflip_status = AMDGPU_FLIP_PENDING;
......@@ -262,12 +227,9 @@ int amdgpu_crtc_page_flip(struct drm_crtc *crtc,
/* update crtc fb */
crtc->primary->fb = fb;
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
amdgpu_flip_work_func(&work->flip_work);
amdgpu_flip_work_func(&work->flip_work.work);
return 0;
vblank_cleanup:
drm_crtc_vblank_put(crtc);
pflip_cleanup:
if (unlikely(amdgpu_bo_reserve(new_rbo, false) != 0)) {
DRM_ERROR("failed to reserve new rbo in error path\n");
......@@ -335,7 +297,7 @@ int amdgpu_crtc_set_config(struct drm_mode_set *set)
return ret;
}
static const char *encoder_names[38] = {
static const char *encoder_names[41] = {
"NONE",
"INTERNAL_LVDS",
"INTERNAL_TMDS1",
......@@ -374,6 +336,9 @@ static const char *encoder_names[38] = {
"TRAVIS",
"INTERNAL_VCE",
"INTERNAL_UNIPHY3",
"HDMI_ANX9805",
"INTERNAL_AMCLK",
"VIRTUAL",
};
static const char *hpd_names[6] = {
......
......@@ -53,9 +53,11 @@
* - 3.2.0 - GFX8: Uses EOP_TC_WB_ACTION_EN, so UMDs don't have to do the same
* at the end of IBs.
* - 3.3.0 - Add VM support for UVD on supported hardware.
* - 3.4.0 - Add AMDGPU_INFO_NUM_EVICTIONS.
* - 3.5.0 - Add support for new UVD_NO_OP register.
*/
#define KMS_DRIVER_MAJOR 3
#define KMS_DRIVER_MINOR 3
#define KMS_DRIVER_MINOR 5
#define KMS_DRIVER_PATCHLEVEL 0
int amdgpu_vram_limit = 0;
......@@ -84,11 +86,13 @@ int amdgpu_sched_jobs = 32;
int amdgpu_sched_hw_submission = 2;
int amdgpu_powerplay = -1;
int amdgpu_powercontainment = 1;
int amdgpu_sclk_deep_sleep_en = 1;
unsigned amdgpu_pcie_gen_cap = 0;
unsigned amdgpu_pcie_lane_cap = 0;
unsigned amdgpu_cg_mask = 0xffffffff;
unsigned amdgpu_pg_mask = 0xffffffff;
char *amdgpu_disable_cu = NULL;
char *amdgpu_virtual_display = NULL;
MODULE_PARM_DESC(vramlimit, "Restrict VRAM for testing, in megabytes");
module_param_named(vramlimit, amdgpu_vram_limit, int, 0600);
......@@ -170,6 +174,9 @@ MODULE_PARM_DESC(powercontainment, "Power Containment (1 = enable (default), 0 =
module_param_named(powercontainment, amdgpu_powercontainment, int, 0444);
#endif
MODULE_PARM_DESC(sclkdeepsleep, "SCLK Deep Sleep (1 = enable (default), 0 = disable)");
module_param_named(sclkdeepsleep, amdgpu_sclk_deep_sleep_en, int, 0444);
MODULE_PARM_DESC(pcie_gen_cap, "PCIE Gen Caps (0: autodetect (default))");
module_param_named(pcie_gen_cap, amdgpu_pcie_gen_cap, uint, 0444);
......@@ -185,6 +192,9 @@ module_param_named(pg_mask, amdgpu_pg_mask, uint, 0444);
MODULE_PARM_DESC(disable_cu, "Disable CUs (se.sh.cu,...)");
module_param_named(disable_cu, amdgpu_disable_cu, charp, 0444);
MODULE_PARM_DESC(virtual_display, "Enable virtual display feature (the virtual_display will be set like xxxx:xx:xx.x;xxxx:xx:xx.x)");
module_param_named(virtual_display, amdgpu_virtual_display, charp, 0444);
static const struct pci_device_id pciidlist[] = {
#ifdef CONFIG_DRM_AMDGPU_CIK
/* Kaveri */
......
......@@ -31,14 +31,6 @@
#define AMDGPU_GWS_SHIFT PAGE_SHIFT
#define AMDGPU_OA_SHIFT PAGE_SHIFT
#define AMDGPU_PL_GDS TTM_PL_PRIV0
#define AMDGPU_PL_GWS TTM_PL_PRIV1
#define AMDGPU_PL_OA TTM_PL_PRIV2
#define AMDGPU_PL_FLAG_GDS TTM_PL_FLAG_PRIV0
#define AMDGPU_PL_FLAG_GWS TTM_PL_FLAG_PRIV1
#define AMDGPU_PL_FLAG_OA TTM_PL_FLAG_PRIV2
struct amdgpu_ring;
struct amdgpu_bo;
......
......@@ -186,10 +186,8 @@ struct amdgpu_i2c_chan *amdgpu_i2c_create(struct drm_device *dev,
"AMDGPU i2c hw bus %s", name);
i2c->adapter.algo = &amdgpu_atombios_i2c_algo;
ret = i2c_add_adapter(&i2c->adapter);
if (ret) {
DRM_ERROR("Failed to register hw i2c %s\n", name);
if (ret)
goto out_free;
}
} else {
/* set the amdgpu bit adapter */
snprintf(i2c->adapter.name, sizeof(i2c->adapter.name),
......
......@@ -142,7 +142,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
}
if (!ring->ready) {
dev_err(adev->dev, "couldn't schedule ib\n");
dev_err(adev->dev, "couldn't schedule ib on ring <%s>\n", ring->name);
return -EINVAL;
}
......
......@@ -40,32 +40,15 @@ static int amdgpu_ih_ring_alloc(struct amdgpu_device *adev)
/* Allocate ring buffer */
if (adev->irq.ih.ring_obj == NULL) {
r = amdgpu_bo_create(adev, adev->irq.ih.ring_size,
PAGE_SIZE, true,
AMDGPU_GEM_DOMAIN_GTT, 0,
NULL, NULL, &adev->irq.ih.ring_obj);
r = amdgpu_bo_create_kernel(adev, adev->irq.ih.ring_size,
PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT,
&adev->irq.ih.ring_obj,
&adev->irq.ih.gpu_addr,
(void **)&adev->irq.ih.ring);
if (r) {
DRM_ERROR("amdgpu: failed to create ih ring buffer (%d).\n", r);
return r;
}
r = amdgpu_bo_reserve(adev->irq.ih.ring_obj, false);
if (unlikely(r != 0))
return r;
r = amdgpu_bo_pin(adev->irq.ih.ring_obj,
AMDGPU_GEM_DOMAIN_GTT,
&adev->irq.ih.gpu_addr);
if (r) {
amdgpu_bo_unreserve(adev->irq.ih.ring_obj);
DRM_ERROR("amdgpu: failed to pin ih ring buffer (%d).\n", r);
return r;
}
r = amdgpu_bo_kmap(adev->irq.ih.ring_obj,
(void **)&adev->irq.ih.ring);
amdgpu_bo_unreserve(adev->irq.ih.ring_obj);
if (r) {
DRM_ERROR("amdgpu: failed to map ih ring buffer (%d).\n", r);
return r;
}
}
return 0;
}
......
......@@ -70,6 +70,7 @@ struct amdgpu_irq {
/* gen irq stuff */
struct irq_domain *domain; /* GPU irq controller domain */
unsigned virq[AMDGPU_MAX_IRQ_SRC_ID];
uint32_t srbm_soft_reset;
};
void amdgpu_irq_preinstall(struct drm_device *dev);
......
......@@ -292,14 +292,14 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
type = AMD_IP_BLOCK_TYPE_UVD;
ring_mask = adev->uvd.ring.ready ? 1 : 0;
ib_start_alignment = AMDGPU_GPU_PAGE_SIZE;
ib_size_alignment = 8;
ib_size_alignment = 16;
break;
case AMDGPU_HW_IP_VCE:
type = AMD_IP_BLOCK_TYPE_VCE;
for (i = 0; i < AMDGPU_MAX_VCE_RINGS; i++)
ring_mask |= ((adev->vce.ring[i].ready ? 1 : 0) << i);
ib_start_alignment = AMDGPU_GPU_PAGE_SIZE;
ib_size_alignment = 8;
ib_size_alignment = 1;
break;
default:
return -EINVAL;
......@@ -373,6 +373,9 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
case AMDGPU_INFO_NUM_BYTES_MOVED:
ui64 = atomic64_read(&adev->num_bytes_moved);
return copy_to_user(out, &ui64, min(size, 8u)) ? -EFAULT : 0;
case AMDGPU_INFO_NUM_EVICTIONS:
ui64 = atomic64_read(&adev->num_evictions);
return copy_to_user(out, &ui64, min(size, 8u)) ? -EFAULT : 0;
case AMDGPU_INFO_VRAM_USAGE:
ui64 = atomic64_read(&adev->vram_usage);
return copy_to_user(out, &ui64, min(size, 8u)) ? -EFAULT : 0;
......
......@@ -39,6 +39,8 @@
#include <drm/drm_plane_helper.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <linux/hrtimer.h>
#include "amdgpu_irq.h"
struct amdgpu_bo;
struct amdgpu_device;
......@@ -339,6 +341,8 @@ struct amdgpu_mode_info {
int num_dig; /* number of dig blocks */
int disp_priority;
const struct amdgpu_display_funcs *funcs;
struct hrtimer vblank_timer;
enum amdgpu_interrupt_state vsync_timer_enabled;
};
#define AMDGPU_MAX_BL_LEVEL 0xFF
......@@ -587,10 +591,10 @@ int amdgpu_align_pitch(struct amdgpu_device *adev, int width, int bpp, bool tile
void amdgpu_print_display_setup(struct drm_device *dev);
int amdgpu_modeset_create_props(struct amdgpu_device *adev);
int amdgpu_crtc_set_config(struct drm_mode_set *set);
int amdgpu_crtc_page_flip(struct drm_crtc *crtc,
struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event,
uint32_t page_flip_flags);
int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc,
struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event,
uint32_t page_flip_flags, uint32_t target);
extern const struct drm_mode_config_funcs amdgpu_mode_funcs;
#endif
......@@ -44,14 +44,13 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev);
static u64 amdgpu_get_vis_part_size(struct amdgpu_device *adev,
struct ttm_mem_reg *mem)
{
u64 ret = 0;
if (mem->start << PAGE_SHIFT < adev->mc.visible_vram_size) {
ret = (u64)((mem->start << PAGE_SHIFT) + mem->size) >
adev->mc.visible_vram_size ?
adev->mc.visible_vram_size - (mem->start << PAGE_SHIFT) :
mem->size;
}
return ret;
if (mem->start << PAGE_SHIFT >= adev->mc.visible_vram_size)
return 0;
return ((mem->start << PAGE_SHIFT) + mem->size) >
adev->mc.visible_vram_size ?
adev->mc.visible_vram_size - (mem->start << PAGE_SHIFT) :
mem->size;
}
static void amdgpu_update_memory_usage(struct amdgpu_device *adev,
......@@ -99,6 +98,11 @@ static void amdgpu_ttm_bo_destroy(struct ttm_buffer_object *tbo)
drm_gem_object_release(&bo->gem_base);
amdgpu_bo_unref(&bo->parent);
if (!list_empty(&bo->shadow_list)) {
mutex_lock(&bo->adev->shadow_list_lock);
list_del_init(&bo->shadow_list);
mutex_unlock(&bo->adev->shadow_list_lock);
}
kfree(bo->metadata);
kfree(bo);
}
......@@ -112,84 +116,93 @@ bool amdgpu_ttm_bo_is_amdgpu_bo(struct ttm_buffer_object *bo)
static void amdgpu_ttm_placement_init(struct amdgpu_device *adev,
struct ttm_placement *placement,
struct ttm_place *placements,
struct ttm_place *places,
u32 domain, u64 flags)
{
u32 c = 0, i;
placement->placement = placements;
placement->busy_placement = placements;
u32 c = 0;
if (domain & AMDGPU_GEM_DOMAIN_VRAM) {
unsigned visible_pfn = adev->mc.visible_vram_size >> PAGE_SHIFT;
if (flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS &&
adev->mc.visible_vram_size < adev->mc.real_vram_size) {
placements[c].fpfn =
adev->mc.visible_vram_size >> PAGE_SHIFT;
placements[c++].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED |
TTM_PL_FLAG_VRAM | TTM_PL_FLAG_TOPDOWN;
!(flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) &&
adev->mc.visible_vram_size < adev->mc.real_vram_size) {
places[c].fpfn = visible_pfn;
places[c].lpfn = 0;
places[c].flags = TTM_PL_FLAG_WC |
TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM |
TTM_PL_FLAG_TOPDOWN;
c++;
}
placements[c].fpfn = 0;
placements[c++].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED |
places[c].fpfn = 0;
places[c].lpfn = 0;
places[c].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED |
TTM_PL_FLAG_VRAM;
if (!(flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED))
placements[c - 1].flags |= TTM_PL_FLAG_TOPDOWN;
if (flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED)
places[c].lpfn = visible_pfn;
else
places[c].flags |= TTM_PL_FLAG_TOPDOWN;
c++;
}
if (domain & AMDGPU_GEM_DOMAIN_GTT) {
if (flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC) {
placements[c].fpfn = 0;
placements[c++].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_TT |
places[c].fpfn = 0;
places[c].lpfn = 0;
places[c].flags = TTM_PL_FLAG_TT;
if (flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC)
places[c].flags |= TTM_PL_FLAG_WC |
TTM_PL_FLAG_UNCACHED;
} else {
placements[c].fpfn = 0;
placements[c++].flags = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_TT;
}
else
places[c].flags |= TTM_PL_FLAG_CACHED;
c++;
}
if (domain & AMDGPU_GEM_DOMAIN_CPU) {
if (flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC) {
placements[c].fpfn = 0;
placements[c++].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_SYSTEM |
places[c].fpfn = 0;
places[c].lpfn = 0;
places[c].flags = TTM_PL_FLAG_SYSTEM;
if (flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC)
places[c].flags |= TTM_PL_FLAG_WC |
TTM_PL_FLAG_UNCACHED;
} else {
placements[c].fpfn = 0;
placements[c++].flags = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_SYSTEM;
}
else
places[c].flags |= TTM_PL_FLAG_CACHED;
c++;
}
if (domain & AMDGPU_GEM_DOMAIN_GDS) {
placements[c].fpfn = 0;
placements[c++].flags = TTM_PL_FLAG_UNCACHED |
AMDGPU_PL_FLAG_GDS;
places[c].fpfn = 0;
places[c].lpfn = 0;
places[c].flags = TTM_PL_FLAG_UNCACHED | AMDGPU_PL_FLAG_GDS;
c++;
}
if (domain & AMDGPU_GEM_DOMAIN_GWS) {
placements[c].fpfn = 0;
placements[c++].flags = TTM_PL_FLAG_UNCACHED |
AMDGPU_PL_FLAG_GWS;
places[c].fpfn = 0;
places[c].lpfn = 0;
places[c].flags = TTM_PL_FLAG_UNCACHED | AMDGPU_PL_FLAG_GWS;
c++;
}
if (domain & AMDGPU_GEM_DOMAIN_OA) {
placements[c].fpfn = 0;
placements[c++].flags = TTM_PL_FLAG_UNCACHED |
AMDGPU_PL_FLAG_OA;
places[c].fpfn = 0;
places[c].lpfn = 0;
places[c].flags = TTM_PL_FLAG_UNCACHED | AMDGPU_PL_FLAG_OA;
c++;
}
if (!c) {
placements[c].fpfn = 0;
placements[c++].flags = TTM_PL_MASK_CACHING |
TTM_PL_FLAG_SYSTEM;
places[c].fpfn = 0;
places[c].lpfn = 0;
places[c].flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
c++;
}
placement->num_placement = c;
placement->num_busy_placement = c;
placement->placement = places;
for (i = 0; i < c; i++) {
if ((flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) &&
(placements[i].flags & TTM_PL_FLAG_VRAM) &&
!placements[i].fpfn)
placements[i].lpfn =
adev->mc.visible_vram_size >> PAGE_SHIFT;
else
placements[i].lpfn = 0;
}
placement->num_busy_placement = c;
placement->busy_placement = places;
}
void amdgpu_ttm_placement_from_domain(struct amdgpu_bo *rbo, u32 domain)
......@@ -211,6 +224,69 @@ static void amdgpu_fill_placement_to_bo(struct amdgpu_bo *bo,
bo->placement.busy_placement = bo->placements;
}
/**
* amdgpu_bo_create_kernel - create BO for kernel use
*
* @adev: amdgpu device object
* @size: size for the new BO
* @align: alignment for the new BO
* @domain: where to place it
* @bo_ptr: resulting BO
* @gpu_addr: GPU addr of the pinned BO
* @cpu_addr: optional CPU address mapping
*
* Allocates and pins a BO for kernel internal use.
*
* Returns 0 on success, negative error code otherwise.
*/
int amdgpu_bo_create_kernel(struct amdgpu_device *adev,
unsigned long size, int align,
u32 domain, struct amdgpu_bo **bo_ptr,
u64 *gpu_addr, void **cpu_addr)
{
int r;
r = amdgpu_bo_create(adev, size, align, true, domain,
AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
NULL, NULL, bo_ptr);
if (r) {
dev_err(adev->dev, "(%d) failed to allocate kernel bo\n", r);
return r;
}
r = amdgpu_bo_reserve(*bo_ptr, false);
if (r) {
dev_err(adev->dev, "(%d) failed to reserve kernel bo\n", r);
goto error_free;
}
r = amdgpu_bo_pin(*bo_ptr, domain, gpu_addr);
if (r) {
dev_err(adev->dev, "(%d) kernel bo pin failed\n", r);
goto error_unreserve;
}
if (cpu_addr) {
r = amdgpu_bo_kmap(*bo_ptr, cpu_addr);
if (r) {
dev_err(adev->dev, "(%d) kernel bo map failed\n", r);
goto error_unreserve;
}
}
amdgpu_bo_unreserve(*bo_ptr);
return 0;
error_unreserve:
amdgpu_bo_unreserve(*bo_ptr);
error_free:
amdgpu_bo_unref(bo_ptr);
return r;
}
int amdgpu_bo_create_restricted(struct amdgpu_device *adev,
unsigned long size, int byte_align,
bool kernel, u32 domain, u64 flags,
......@@ -250,6 +326,7 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev,
}
bo->adev = adev;
INIT_LIST_HEAD(&bo->list);
INIT_LIST_HEAD(&bo->shadow_list);
INIT_LIST_HEAD(&bo->va);
bo->prefered_domains = domain & (AMDGPU_GEM_DOMAIN_VRAM |
AMDGPU_GEM_DOMAIN_GTT |
......@@ -277,11 +354,79 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev,
if (unlikely(r != 0)) {
return r;
}
if (flags & AMDGPU_GEM_CREATE_VRAM_CLEARED &&
bo->tbo.mem.placement & TTM_PL_FLAG_VRAM) {
struct fence *fence;
if (adev->mman.buffer_funcs_ring == NULL ||
!adev->mman.buffer_funcs_ring->ready) {
r = -EBUSY;
goto fail_free;
}
r = amdgpu_bo_reserve(bo, false);
if (unlikely(r != 0))
goto fail_free;
amdgpu_ttm_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_VRAM);
r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
if (unlikely(r != 0))
goto fail_unreserve;
amdgpu_fill_buffer(bo, 0, bo->tbo.resv, &fence);
amdgpu_bo_fence(bo, fence, false);
amdgpu_bo_unreserve(bo);
fence_put(bo->tbo.moving);
bo->tbo.moving = fence_get(fence);
fence_put(fence);
}
*bo_ptr = bo;
trace_amdgpu_bo_create(bo);
return 0;
fail_unreserve:
amdgpu_bo_unreserve(bo);
fail_free:
amdgpu_bo_unref(&bo);
return r;
}
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;
bo->flags |= AMDGPU_GEM_CREATE_SHADOW;
memset(&placements, 0,
(AMDGPU_GEM_DOMAIN_MAX + 1) * sizeof(struct ttm_place));
amdgpu_ttm_placement_init(adev, &placement,
placements, AMDGPU_GEM_DOMAIN_GTT,
AMDGPU_GEM_CREATE_CPU_GTT_USWC);
r = amdgpu_bo_create_restricted(adev, size, byte_align, true,
AMDGPU_GEM_DOMAIN_GTT,
AMDGPU_GEM_CREATE_CPU_GTT_USWC,
NULL, &placement,
bo->tbo.resv,
&bo->shadow);
if (!r) {
bo->shadow->parent = amdgpu_bo_ref(bo);
mutex_lock(&adev->shadow_list_lock);
list_add_tail(&bo->shadow_list, &adev->shadow_list);
mutex_unlock(&adev->shadow_list_lock);
}
return r;
}
int amdgpu_bo_create(struct amdgpu_device *adev,
......@@ -293,6 +438,7 @@ int amdgpu_bo_create(struct amdgpu_device *adev,
{
struct ttm_placement placement = {0};
struct ttm_place placements[AMDGPU_GEM_DOMAIN_MAX + 1];
int r;
memset(&placements, 0,
(AMDGPU_GEM_DOMAIN_MAX + 1) * sizeof(struct ttm_place));
......@@ -300,9 +446,83 @@ int amdgpu_bo_create(struct amdgpu_device *adev,
amdgpu_ttm_placement_init(adev, &placement,
placements, domain, flags);
return amdgpu_bo_create_restricted(adev, size, byte_align, kernel,
domain, flags, sg, &placement,
resv, bo_ptr);
r = amdgpu_bo_create_restricted(adev, size, byte_align, kernel,
domain, flags, sg, &placement,
resv, bo_ptr);
if (r)
return r;
if (amdgpu_need_backup(adev) && (flags & AMDGPU_GEM_CREATE_SHADOW)) {
r = amdgpu_bo_create_shadow(adev, size, byte_align, (*bo_ptr));
if (r)
amdgpu_bo_unref(bo_ptr);
}
return r;
}
int amdgpu_bo_backup_to_shadow(struct amdgpu_device *adev,
struct amdgpu_ring *ring,
struct amdgpu_bo *bo,
struct reservation_object *resv,
struct fence **fence,
bool direct)
{
struct amdgpu_bo *shadow = bo->shadow;
uint64_t bo_addr, shadow_addr;
int r;
if (!shadow)
return -EINVAL;
bo_addr = amdgpu_bo_gpu_offset(bo);
shadow_addr = amdgpu_bo_gpu_offset(bo->shadow);
r = reservation_object_reserve_shared(bo->tbo.resv);
if (r)
goto err;
r = amdgpu_copy_buffer(ring, bo_addr, shadow_addr,
amdgpu_bo_size(bo), resv, fence,
direct);
if (!r)
amdgpu_bo_fence(bo, *fence, true);
err:
return r;
}
int amdgpu_bo_restore_from_shadow(struct amdgpu_device *adev,
struct amdgpu_ring *ring,
struct amdgpu_bo *bo,
struct reservation_object *resv,
struct fence **fence,
bool direct)
{
struct amdgpu_bo *shadow = bo->shadow;
uint64_t bo_addr, shadow_addr;
int r;
if (!shadow)
return -EINVAL;
bo_addr = amdgpu_bo_gpu_offset(bo);
shadow_addr = amdgpu_bo_gpu_offset(bo->shadow);
r = reservation_object_reserve_shared(bo->tbo.resv);
if (r)
goto err;
r = amdgpu_copy_buffer(ring, shadow_addr, bo_addr,
amdgpu_bo_size(bo), resv, fence,
direct);
if (!r)
amdgpu_bo_fence(bo, *fence, true);
err:
return r;
}
int amdgpu_bo_kmap(struct amdgpu_bo *bo, void **ptr)
......@@ -380,16 +600,17 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
return -EINVAL;
if (bo->pin_count) {
uint32_t mem_type = bo->tbo.mem.mem_type;
if (domain != amdgpu_mem_type_to_domain(mem_type))
return -EINVAL;
bo->pin_count++;
if (gpu_addr)
*gpu_addr = amdgpu_bo_gpu_offset(bo);
if (max_offset != 0) {
u64 domain_start;
if (domain == AMDGPU_GEM_DOMAIN_VRAM)
domain_start = bo->adev->mc.vram_start;
else
domain_start = bo->adev->mc.gtt_start;
u64 domain_start = bo->tbo.bdev->man[mem_type].gpu_offset;
WARN_ON_ONCE(max_offset <
(amdgpu_bo_gpu_offset(bo) - domain_start));
}
......@@ -401,7 +622,8 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
/* 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 > bo->adev->mc.visible_vram_size)) {
(!max_offset || max_offset >
bo->adev->mc.visible_vram_size)) {
if (WARN_ON_ONCE(min_offset >
bo->adev->mc.visible_vram_size))
return -EINVAL;
......@@ -420,19 +642,23 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
}
r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
if (likely(r == 0)) {
bo->pin_count = 1;
if (gpu_addr != NULL)
*gpu_addr = amdgpu_bo_gpu_offset(bo);
if (domain == AMDGPU_GEM_DOMAIN_VRAM) {
bo->adev->vram_pin_size += amdgpu_bo_size(bo);
if (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)
bo->adev->invisible_pin_size += amdgpu_bo_size(bo);
} else
bo->adev->gart_pin_size += amdgpu_bo_size(bo);
} else {
if (unlikely(r)) {
dev_err(bo->adev->dev, "%p pin failed\n", bo);
goto error;
}
bo->pin_count = 1;
if (gpu_addr != NULL)
*gpu_addr = amdgpu_bo_gpu_offset(bo);
if (domain == AMDGPU_GEM_DOMAIN_VRAM) {
bo->adev->vram_pin_size += amdgpu_bo_size(bo);
if (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)
bo->adev->invisible_pin_size += amdgpu_bo_size(bo);
} else if (domain == AMDGPU_GEM_DOMAIN_GTT) {
bo->adev->gart_pin_size += amdgpu_bo_size(bo);
}
error:
return r;
}
......@@ -457,16 +683,20 @@ int amdgpu_bo_unpin(struct amdgpu_bo *bo)
bo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT;
}
r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
if (likely(r == 0)) {
if (bo->tbo.mem.mem_type == TTM_PL_VRAM) {
bo->adev->vram_pin_size -= amdgpu_bo_size(bo);
if (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)
bo->adev->invisible_pin_size -= amdgpu_bo_size(bo);
} else
bo->adev->gart_pin_size -= amdgpu_bo_size(bo);
} else {
if (unlikely(r)) {
dev_err(bo->adev->dev, "%p validate failed for unpin\n", bo);
goto error;
}
if (bo->tbo.mem.mem_type == TTM_PL_VRAM) {
bo->adev->vram_pin_size -= amdgpu_bo_size(bo);
if (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)
bo->adev->invisible_pin_size -= amdgpu_bo_size(bo);
} else {
bo->adev->gart_pin_size -= amdgpu_bo_size(bo);
}
error:
return r;
}
......@@ -637,7 +867,8 @@ int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
for (i = 0; i < abo->placement.num_placement; i++) {
/* Force into visible VRAM */
if ((abo->placements[i].flags & TTM_PL_FLAG_VRAM) &&
(!abo->placements[i].lpfn || abo->placements[i].lpfn > lpfn))
(!abo->placements[i].lpfn ||
abo->placements[i].lpfn > lpfn))
abo->placements[i].lpfn = lpfn;
}
r = ttm_bo_validate(bo, &abo->placement, false, false);
......@@ -674,3 +905,21 @@ void amdgpu_bo_fence(struct amdgpu_bo *bo, struct fence *fence,
else
reservation_object_add_excl_fence(resv, fence);
}
/**
* amdgpu_bo_gpu_offset - return GPU offset of bo
* @bo: amdgpu object for which we query the offset
*
* Returns current GPU offset of the object.
*
* Note: object should either be pinned or reserved when calling this
* function, it might be useful to add check for this for debugging.
*/
u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo)
{
WARN_ON_ONCE(bo->tbo.mem.mem_type == TTM_PL_SYSTEM);
WARN_ON_ONCE(!ww_mutex_is_locked(&bo->tbo.resv->lock) &&
!bo->pin_count);
return bo->tbo.offset;
}
......@@ -85,21 +85,6 @@ static inline void amdgpu_bo_unreserve(struct amdgpu_bo *bo)
ttm_bo_unreserve(&bo->tbo);
}
/**
* amdgpu_bo_gpu_offset - return GPU offset of bo
* @bo: amdgpu object for which we query the offset
*
* Returns current GPU offset of the object.
*
* Note: object should either be pinned or reserved when calling this
* function, it might be useful to add check for this for debugging.
*/
static inline u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo)
{
WARN_ON_ONCE(bo->tbo.mem.mem_type == TTM_PL_SYSTEM);
return bo->tbo.offset;
}
static inline unsigned long amdgpu_bo_size(struct amdgpu_bo *bo)
{
return bo->tbo.num_pages << PAGE_SHIFT;
......@@ -139,6 +124,10 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev,
struct ttm_placement *placement,
struct reservation_object *resv,
struct amdgpu_bo **bo_ptr);
int amdgpu_bo_create_kernel(struct amdgpu_device *adev,
unsigned long size, int align,
u32 domain, struct amdgpu_bo **bo_ptr,
u64 *gpu_addr, void **cpu_addr);
int amdgpu_bo_kmap(struct amdgpu_bo *bo, void **ptr);
void amdgpu_bo_kunmap(struct amdgpu_bo *bo);
struct amdgpu_bo *amdgpu_bo_ref(struct amdgpu_bo *bo);
......@@ -165,6 +154,19 @@ void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo);
void amdgpu_bo_fence(struct amdgpu_bo *bo, struct fence *fence,
bool shared);
u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo);
int amdgpu_bo_backup_to_shadow(struct amdgpu_device *adev,
struct amdgpu_ring *ring,
struct amdgpu_bo *bo,
struct reservation_object *resv,
struct fence **fence, bool direct);
int amdgpu_bo_restore_from_shadow(struct amdgpu_device *adev,
struct amdgpu_ring *ring,
struct amdgpu_bo *bo,
struct reservation_object *resv,
struct fence **fence,
bool direct);
/*
* sub allocation
......
......@@ -1103,54 +1103,46 @@ 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)
if (adev->pp_enabled || adev->pm.funcs->powergate_uvd) {
/* enable/disable UVD */
mutex_lock(&adev->pm.mutex);
amdgpu_dpm_powergate_uvd(adev, !enable);
else {
if (adev->pm.funcs->powergate_uvd) {
mutex_unlock(&adev->pm.mutex);
} else {
if (enable) {
mutex_lock(&adev->pm.mutex);
/* enable/disable UVD */
amdgpu_dpm_powergate_uvd(adev, !enable);
adev->pm.dpm.uvd_active = true;
adev->pm.dpm.state = POWER_STATE_TYPE_INTERNAL_UVD;
mutex_unlock(&adev->pm.mutex);
} else {
if (enable) {
mutex_lock(&adev->pm.mutex);
adev->pm.dpm.uvd_active = true;
adev->pm.dpm.state = POWER_STATE_TYPE_INTERNAL_UVD;
mutex_unlock(&adev->pm.mutex);
} else {
mutex_lock(&adev->pm.mutex);
adev->pm.dpm.uvd_active = false;
mutex_unlock(&adev->pm.mutex);
}
amdgpu_pm_compute_clocks(adev);
mutex_lock(&adev->pm.mutex);
adev->pm.dpm.uvd_active = false;
mutex_unlock(&adev->pm.mutex);
}
amdgpu_pm_compute_clocks(adev);
}
}
void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable)
{
if (adev->pp_enabled)
if (adev->pp_enabled || adev->pm.funcs->powergate_vce) {
/* enable/disable VCE */
mutex_lock(&adev->pm.mutex);
amdgpu_dpm_powergate_vce(adev, !enable);
else {
if (adev->pm.funcs->powergate_vce) {
mutex_unlock(&adev->pm.mutex);
} else {
if (enable) {
mutex_lock(&adev->pm.mutex);
amdgpu_dpm_powergate_vce(adev, !enable);
adev->pm.dpm.vce_active = true;
/* XXX select vce level based on ring/task */
adev->pm.dpm.vce_level = AMDGPU_VCE_LEVEL_AC_ALL;
mutex_unlock(&adev->pm.mutex);
} else {
if (enable) {
mutex_lock(&adev->pm.mutex);
adev->pm.dpm.vce_active = true;
/* XXX select vce level based on ring/task */
adev->pm.dpm.vce_level = AMDGPU_VCE_LEVEL_AC_ALL;
mutex_unlock(&adev->pm.mutex);
} else {
mutex_lock(&adev->pm.mutex);
adev->pm.dpm.vce_active = false;
mutex_unlock(&adev->pm.mutex);
}
amdgpu_pm_compute_clocks(adev);
mutex_lock(&adev->pm.mutex);
adev->pm.dpm.vce_active = false;
mutex_unlock(&adev->pm.mutex);
}
amdgpu_pm_compute_clocks(adev);
}
}
......
......@@ -52,7 +52,9 @@ static int amdgpu_powerplay_init(struct amdgpu_device *adev)
pp_init->chip_family = adev->family;
pp_init->chip_id = adev->asic_type;
pp_init->device = amdgpu_cgs_create_device(adev);
pp_init->powercontainment_enabled = amdgpu_powercontainment;
pp_init->rev_id = adev->pdev->revision;
pp_init->sub_sys_id = adev->pdev->subsystem_device;
pp_init->sub_vendor_id = adev->pdev->subsystem_vendor;
ret = amd_powerplay_init(pp_init, amd_pp);
kfree(pp_init);
......@@ -106,11 +108,10 @@ static int amdgpu_pp_early_init(void *handle)
break;
case CHIP_TONGA:
case CHIP_FIJI:
adev->pp_enabled = (amdgpu_powerplay == 0) ? false : true;
break;
case CHIP_TOPAZ:
case CHIP_CARRIZO:
case CHIP_STONEY:
adev->pp_enabled = (amdgpu_powerplay > 0) ? true : false;
adev->pp_enabled = (amdgpu_powerplay == 0) ? false : true;
break;
/* These chips don't have powerplay implemenations */
case CHIP_BONAIRE:
......@@ -118,7 +119,6 @@ static int amdgpu_pp_early_init(void *handle)
case CHIP_KABINI:
case CHIP_MULLINS:
case CHIP_KAVERI:
case CHIP_TOPAZ:
default:
adev->pp_enabled = false;
break;
......
......@@ -222,33 +222,16 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
/* Allocate ring buffer */
if (ring->ring_obj == NULL) {
r = amdgpu_bo_create(adev, ring->ring_size, PAGE_SIZE, true,
AMDGPU_GEM_DOMAIN_GTT, 0,
NULL, NULL, &ring->ring_obj);
r = amdgpu_bo_create_kernel(adev, ring->ring_size, PAGE_SIZE,
AMDGPU_GEM_DOMAIN_GTT,
&ring->ring_obj,
&ring->gpu_addr,
(void **)&ring->ring);
if (r) {
dev_err(adev->dev, "(%d) ring create failed\n", r);
return r;
}
r = amdgpu_bo_reserve(ring->ring_obj, false);
if (unlikely(r != 0))
return r;
r = amdgpu_bo_pin(ring->ring_obj, AMDGPU_GEM_DOMAIN_GTT,
&ring->gpu_addr);
if (r) {
amdgpu_bo_unreserve(ring->ring_obj);
dev_err(adev->dev, "(%d) ring pin failed\n", r);
return r;
}
r = amdgpu_bo_kmap(ring->ring_obj,
(void **)&ring->ring);
memset((void *)ring->ring, 0, ring->ring_size);
amdgpu_bo_unreserve(ring->ring_obj);
if (r) {
dev_err(adev->dev, "(%d) ring map failed\n", r);
return r;
}
}
ring->ptr_mask = (ring->ring_size / 4) - 1;
ring->max_dw = max_dw;
......
......@@ -111,7 +111,7 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev)
amdgpu_bo_kunmap(gtt_obj[i]);
r = amdgpu_copy_buffer(ring, gtt_addr, vram_addr,
size, NULL, &fence);
size, NULL, &fence, false);
if (r) {
DRM_ERROR("Failed GTT->VRAM copy %d\n", i);
......@@ -156,7 +156,7 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev)
amdgpu_bo_kunmap(vram_obj);
r = amdgpu_copy_buffer(ring, vram_addr, gtt_addr,
size, NULL, &fence);
size, NULL, &fence, false);
if (r) {
DRM_ERROR("Failed VRAM->GTT copy %d\n", i);
......
......@@ -34,6 +34,7 @@
#include <ttm/ttm_placement.h>
#include <ttm/ttm_module.h>
#include <ttm/ttm_page_alloc.h>
#include <ttm/ttm_memory.h>
#include <drm/drmP.h>
#include <drm/amdgpu_drm.h>
#include <linux/seq_file.h>
......@@ -74,7 +75,7 @@ static void amdgpu_ttm_mem_global_release(struct drm_global_reference *ref)
ttm_mem_global_release(ref->object);
}
static int amdgpu_ttm_global_init(struct amdgpu_device *adev)
int amdgpu_ttm_global_init(struct amdgpu_device *adev)
{
struct drm_global_reference *global_ref;
struct amdgpu_ring *ring;
......@@ -256,10 +257,8 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo,
switch (old_mem->mem_type) {
case TTM_PL_VRAM:
old_start += adev->mc.vram_start;
break;
case TTM_PL_TT:
old_start += adev->mc.gtt_start;
old_start += bo->bdev->man[old_mem->mem_type].gpu_offset;
break;
default:
DRM_ERROR("Unknown placement %d\n", old_mem->mem_type);
......@@ -267,10 +266,8 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo,
}
switch (new_mem->mem_type) {
case TTM_PL_VRAM:
new_start += adev->mc.vram_start;
break;
case TTM_PL_TT:
new_start += adev->mc.gtt_start;
new_start += bo->bdev->man[new_mem->mem_type].gpu_offset;
break;
default:
DRM_ERROR("Unknown placement %d\n", old_mem->mem_type);
......@@ -285,7 +282,7 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo,
r = amdgpu_copy_buffer(ring, old_start, new_start,
new_mem->num_pages * PAGE_SIZE, /* bytes */
bo->resv, &fence);
bo->resv, &fence, false);
if (r)
return r;
......@@ -335,7 +332,7 @@ static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo,
if (unlikely(r)) {
goto out_cleanup;
}
r = ttm_bo_move_ttm(bo, true, interruptible, no_wait_gpu, new_mem);
r = ttm_bo_move_ttm(bo, interruptible, no_wait_gpu, new_mem);
out_cleanup:
ttm_bo_mem_put(bo, &tmp_mem);
return r;
......@@ -368,7 +365,7 @@ static int amdgpu_move_ram_vram(struct ttm_buffer_object *bo,
if (unlikely(r)) {
return r;
}
r = ttm_bo_move_ttm(bo, true, interruptible, no_wait_gpu, &tmp_mem);
r = ttm_bo_move_ttm(bo, interruptible, no_wait_gpu, &tmp_mem);
if (unlikely(r)) {
goto out_cleanup;
}
......@@ -435,8 +432,7 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo,
if (r) {
memcpy:
r = ttm_bo_move_memcpy(bo, evict, interruptible,
no_wait_gpu, new_mem);
r = ttm_bo_move_memcpy(bo, interruptible, no_wait_gpu, new_mem);
if (r) {
return r;
}
......@@ -950,6 +946,8 @@ static struct list_head *amdgpu_ttm_lru_tail(struct ttm_buffer_object *tbo)
struct list_head *res = lru->lru[tbo->mem.mem_type];
lru->lru[tbo->mem.mem_type] = &tbo->lru;
while ((++lru)->lru[tbo->mem.mem_type] == res)
lru->lru[tbo->mem.mem_type] = &tbo->lru;
return res;
}
......@@ -960,6 +958,8 @@ static struct list_head *amdgpu_ttm_swap_lru_tail(struct ttm_buffer_object *tbo)
struct list_head *res = lru->swap_lru;
lru->swap_lru = &tbo->swap;
while ((++lru)->swap_lru == res)
lru->swap_lru = &tbo->swap;
return res;
}
......@@ -987,10 +987,6 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
unsigned i, j;
int r;
r = amdgpu_ttm_global_init(adev);
if (r) {
return r;
}
/* No others user of address space so set it to 0 */
r = ttm_bo_device_init(&adev->mman.bdev,
adev->mman.bo_global_ref.ref.object,
......@@ -1011,6 +1007,10 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
lru->swap_lru = &adev->mman.bdev.glob->swap_lru;
}
for (j = 0; j < TTM_NUM_MEM_TYPES; ++j)
adev->mman.guard.lru[j] = NULL;
adev->mman.guard.swap_lru = NULL;
adev->mman.initialized = true;
r = ttm_bo_init_mm(&adev->mman.bdev, TTM_PL_VRAM,
adev->mc.real_vram_size >> PAGE_SHIFT);
......@@ -1151,7 +1151,7 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring,
uint64_t dst_offset,
uint32_t byte_count,
struct reservation_object *resv,
struct fence **fence)
struct fence **fence, bool direct_submit)
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_job *job;
......@@ -1193,10 +1193,81 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring,
byte_count -= cur_size_in_bytes;
}
amdgpu_ring_pad_ib(ring, &job->ibs[0]);
WARN_ON(job->ibs[0].length_dw > num_dw);
if (direct_submit) {
r = amdgpu_ib_schedule(ring, job->num_ibs, job->ibs,
NULL, NULL, fence);
job->fence = fence_get(*fence);
if (r)
DRM_ERROR("Error scheduling IBs (%d)\n", r);
amdgpu_job_free(job);
} else {
r = amdgpu_job_submit(job, ring, &adev->mman.entity,
AMDGPU_FENCE_OWNER_UNDEFINED, fence);
if (r)
goto error_free;
}
return r;
error_free:
amdgpu_job_free(job);
return r;
}
int amdgpu_fill_buffer(struct amdgpu_bo *bo,
uint32_t src_data,
struct reservation_object *resv,
struct fence **fence)
{
struct amdgpu_device *adev = bo->adev;
struct amdgpu_job *job;
struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring;
uint32_t max_bytes, byte_count;
uint64_t dst_offset;
unsigned int num_loops, num_dw;
unsigned int i;
int r;
byte_count = bo->tbo.num_pages << PAGE_SHIFT;
max_bytes = adev->mman.buffer_funcs->fill_max_bytes;
num_loops = DIV_ROUND_UP(byte_count, max_bytes);
num_dw = num_loops * adev->mman.buffer_funcs->fill_num_dw;
/* for IB padding */
while (num_dw & 0x7)
num_dw++;
r = amdgpu_job_alloc_with_ib(adev, num_dw * 4, &job);
if (r)
return r;
if (resv) {
r = amdgpu_sync_resv(adev, &job->sync, resv,
AMDGPU_FENCE_OWNER_UNDEFINED);
if (r) {
DRM_ERROR("sync failed (%d).\n", r);
goto error_free;
}
}
dst_offset = bo->tbo.mem.start << PAGE_SHIFT;
for (i = 0; i < num_loops; i++) {
uint32_t cur_size_in_bytes = min(byte_count, max_bytes);
amdgpu_emit_fill_buffer(adev, &job->ibs[0], src_data,
dst_offset, cur_size_in_bytes);
dst_offset += cur_size_in_bytes;
byte_count -= cur_size_in_bytes;
}
amdgpu_ring_pad_ib(ring, &job->ibs[0]);
WARN_ON(job->ibs[0].length_dw > num_dw);
r = amdgpu_job_submit(job, ring, &adev->mman.entity,
AMDGPU_FENCE_OWNER_UNDEFINED, fence);
AMDGPU_FENCE_OWNER_UNDEFINED, fence);
if (r)
goto error_free;
......@@ -1387,3 +1458,8 @@ static void amdgpu_ttm_debugfs_fini(struct amdgpu_device *adev)
#endif
}
u64 amdgpu_ttm_get_gtt_mem_size(struct amdgpu_device *adev)
{
return ttm_get_kernel_zone_memory_size(adev->mman.mem_global_ref.object);
}
/*
* Copyright 2016 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 __AMDGPU_TTM_H__
#define __AMDGPU_TTM_H__
#include "gpu_scheduler.h"
#define AMDGPU_PL_GDS TTM_PL_PRIV0
#define AMDGPU_PL_GWS TTM_PL_PRIV1
#define AMDGPU_PL_OA TTM_PL_PRIV2
#define AMDGPU_PL_FLAG_GDS TTM_PL_FLAG_PRIV0
#define AMDGPU_PL_FLAG_GWS TTM_PL_FLAG_PRIV1
#define AMDGPU_PL_FLAG_OA TTM_PL_FLAG_PRIV2
#define AMDGPU_TTM_LRU_SIZE 20
struct amdgpu_mman_lru {
struct list_head *lru[TTM_NUM_MEM_TYPES];
struct list_head *swap_lru;
};
struct amdgpu_mman {
struct ttm_bo_global_ref bo_global_ref;
struct drm_global_reference mem_global_ref;
struct ttm_bo_device bdev;
bool mem_global_referenced;
bool initialized;
#if defined(CONFIG_DEBUG_FS)
struct dentry *vram;
struct dentry *gtt;
#endif
/* buffer handling */
const struct amdgpu_buffer_funcs *buffer_funcs;
struct amdgpu_ring *buffer_funcs_ring;
/* Scheduler entity for buffer moves */
struct amd_sched_entity entity;
/* custom LRU management */
struct amdgpu_mman_lru log2_size[AMDGPU_TTM_LRU_SIZE];
/* guard for log2_size array, don't add anything in between */
struct amdgpu_mman_lru guard;
};
int amdgpu_copy_buffer(struct amdgpu_ring *ring,
uint64_t src_offset,
uint64_t dst_offset,
uint32_t byte_count,
struct reservation_object *resv,
struct fence **fence, bool direct_submit);
int amdgpu_fill_buffer(struct amdgpu_bo *bo,
uint32_t src_data,
struct reservation_object *resv,
struct fence **fence);
int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma);
#endif
......@@ -201,39 +201,14 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
bo_size = AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8)
+ AMDGPU_UVD_STACK_SIZE + AMDGPU_UVD_HEAP_SIZE
+ AMDGPU_UVD_SESSION_SIZE * adev->uvd.max_handles;
r = amdgpu_bo_create(adev, bo_size, PAGE_SIZE, true,
AMDGPU_GEM_DOMAIN_VRAM,
AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
NULL, NULL, &adev->uvd.vcpu_bo);
r = amdgpu_bo_create_kernel(adev, bo_size, PAGE_SIZE,
AMDGPU_GEM_DOMAIN_VRAM, &adev->uvd.vcpu_bo,
&adev->uvd.gpu_addr, &adev->uvd.cpu_addr);
if (r) {
dev_err(adev->dev, "(%d) failed to allocate UVD bo\n", r);
return r;
}
r = amdgpu_bo_reserve(adev->uvd.vcpu_bo, false);
if (r) {
amdgpu_bo_unref(&adev->uvd.vcpu_bo);
dev_err(adev->dev, "(%d) failed to reserve UVD bo\n", r);
return r;
}
r = amdgpu_bo_pin(adev->uvd.vcpu_bo, AMDGPU_GEM_DOMAIN_VRAM,
&adev->uvd.gpu_addr);
if (r) {
amdgpu_bo_unreserve(adev->uvd.vcpu_bo);
amdgpu_bo_unref(&adev->uvd.vcpu_bo);
dev_err(adev->dev, "(%d) UVD bo pin failed\n", r);
return r;
}
r = amdgpu_bo_kmap(adev->uvd.vcpu_bo, &adev->uvd.cpu_addr);
if (r) {
dev_err(adev->dev, "(%d) UVD map failed\n", r);
return r;
}
amdgpu_bo_unreserve(adev->uvd.vcpu_bo);
ring = &adev->uvd.ring;
rq = &ring->sched.sched_rq[AMD_SCHED_PRIORITY_NORMAL];
r = amd_sched_entity_init(&ring->sched, &adev->uvd.entity,
......@@ -323,7 +298,7 @@ int amdgpu_uvd_suspend(struct amdgpu_device *adev)
if (!adev->uvd.saved_bo)
return -ENOMEM;
memcpy(adev->uvd.saved_bo, ptr, size);
memcpy_fromio(adev->uvd.saved_bo, ptr, size);
return 0;
}
......@@ -340,7 +315,7 @@ int amdgpu_uvd_resume(struct amdgpu_device *adev)
ptr = adev->uvd.cpu_addr;
if (adev->uvd.saved_bo != NULL) {
memcpy(ptr, adev->uvd.saved_bo, size);
memcpy_toio(ptr, adev->uvd.saved_bo, size);
kfree(adev->uvd.saved_bo);
adev->uvd.saved_bo = NULL;
} else {
......@@ -349,11 +324,11 @@ int amdgpu_uvd_resume(struct amdgpu_device *adev)
hdr = (const struct common_firmware_header *)adev->uvd.fw->data;
offset = le32_to_cpu(hdr->ucode_array_offset_bytes);
memcpy(adev->uvd.cpu_addr, (adev->uvd.fw->data) + offset,
(adev->uvd.fw->size) - offset);
memcpy_toio(adev->uvd.cpu_addr, adev->uvd.fw->data + offset,
le32_to_cpu(hdr->ucode_size_bytes));
size -= le32_to_cpu(hdr->ucode_size_bytes);
ptr += le32_to_cpu(hdr->ucode_size_bytes);
memset(ptr, 0, size);
memset_io(ptr, 0, size);
}
return 0;
......@@ -843,6 +818,7 @@ static int amdgpu_uvd_cs_reg(struct amdgpu_uvd_cs_ctx *ctx,
return r;
break;
case mmUVD_ENGINE_CNTL:
case mmUVD_NO_OP:
break;
default:
DRM_ERROR("Invalid reg 0x%X!\n", reg);
......@@ -981,8 +957,10 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo,
ib->ptr[3] = addr >> 32;
ib->ptr[4] = PACKET0(mmUVD_GPCOM_VCPU_CMD, 0);
ib->ptr[5] = 0;
for (i = 6; i < 16; ++i)
ib->ptr[i] = PACKET2(0);
for (i = 6; i < 16; i += 2) {
ib->ptr[i] = PACKET0(mmUVD_NO_OP, 0);
ib->ptr[i+1] = 0;
}
ib->length_dw = 16;
if (direct) {
......@@ -1114,15 +1092,9 @@ static void amdgpu_uvd_idle_work_handler(struct work_struct *work)
{
struct amdgpu_device *adev =
container_of(work, struct amdgpu_device, uvd.idle_work.work);
unsigned i, fences, handles = 0;
fences = amdgpu_fence_count_emitted(&adev->uvd.ring);
for (i = 0; i < adev->uvd.max_handles; ++i)
if (atomic_read(&adev->uvd.handles[i]))
++handles;
unsigned fences = amdgpu_fence_count_emitted(&adev->uvd.ring);
if (fences == 0 && handles == 0) {
if (fences == 0) {
if (adev->pm.dpm_enabled) {
amdgpu_dpm_enable_uvd(adev, false);
} else {
......
......@@ -282,8 +282,8 @@ int amdgpu_vce_resume(struct amdgpu_device *adev)
hdr = (const struct common_firmware_header *)adev->vce.fw->data;
offset = le32_to_cpu(hdr->ucode_array_offset_bytes);
memcpy(cpu_addr, (adev->vce.fw->data) + offset,
(adev->vce.fw->size) - offset);
memcpy_toio(cpu_addr, adev->vce.fw->data + offset,
adev->vce.fw->size - offset);
amdgpu_bo_kunmap(adev->vce.vcpu_bo);
......
......@@ -88,7 +88,6 @@ static int amdgpu_atombios_dp_process_aux_ch(struct amdgpu_i2c_chan *chan,
/* timeout */
if (args.v2.ucReplyStatus == 1) {
DRM_DEBUG_KMS("dp_aux_ch timeout\n");
r = -ETIMEDOUT;
goto done;
}
......@@ -339,22 +338,21 @@ int amdgpu_atombios_dp_get_dpcd(struct amdgpu_connector *amdgpu_connector)
{
struct amdgpu_connector_atom_dig *dig_connector = amdgpu_connector->con_priv;
u8 msg[DP_DPCD_SIZE];
int ret, i;
int ret;
for (i = 0; i < 7; i++) {
ret = drm_dp_dpcd_read(&amdgpu_connector->ddc_bus->aux, DP_DPCD_REV, msg,
DP_DPCD_SIZE);
if (ret == DP_DPCD_SIZE) {
memcpy(dig_connector->dpcd, msg, DP_DPCD_SIZE);
ret = drm_dp_dpcd_read(&amdgpu_connector->ddc_bus->aux, DP_DPCD_REV,
msg, DP_DPCD_SIZE);
if (ret == DP_DPCD_SIZE) {
memcpy(dig_connector->dpcd, msg, DP_DPCD_SIZE);
DRM_DEBUG_KMS("DPCD: %*ph\n", (int)sizeof(dig_connector->dpcd),
dig_connector->dpcd);
DRM_DEBUG_KMS("DPCD: %*ph\n", (int)sizeof(dig_connector->dpcd),
dig_connector->dpcd);
amdgpu_atombios_dp_probe_oui(amdgpu_connector);
amdgpu_atombios_dp_probe_oui(amdgpu_connector);
return 0;
}
return 0;
}
dig_connector->dpcd[0] = 0;
return -EINVAL;
}
......
......@@ -5874,7 +5874,10 @@ static int ci_dpm_init(struct amdgpu_device *adev)
pi->pcie_dpm_key_disabled = 0;
pi->thermal_sclk_dpm_enabled = 0;
pi->caps_sclk_ds = true;
if (amdgpu_sclk_deep_sleep_en)
pi->caps_sclk_ds = true;
else
pi->caps_sclk_ds = false;
pi->mclk_strobe_mode_threshold = 40000;
pi->mclk_stutter_mode_threshold = 40000;
......
......@@ -67,6 +67,7 @@
#include "amdgpu_amdkfd.h"
#include "amdgpu_powerplay.h"
#include "dce_virtual.h"
/*
* Indirect registers accessor
......@@ -1708,6 +1709,74 @@ static const struct amdgpu_ip_block_version bonaire_ip_blocks[] =
},
};
static const struct amdgpu_ip_block_version bonaire_ip_blocks_vd[] =
{
/* ORDER MATTERS! */
{
.type = AMD_IP_BLOCK_TYPE_COMMON,
.major = 1,
.minor = 0,
.rev = 0,
.funcs = &cik_common_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_GMC,
.major = 7,
.minor = 0,
.rev = 0,
.funcs = &gmc_v7_0_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_IH,
.major = 2,
.minor = 0,
.rev = 0,
.funcs = &cik_ih_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_SMC,
.major = 7,
.minor = 0,
.rev = 0,
.funcs = &amdgpu_pp_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_DCE,
.major = 8,
.minor = 2,
.rev = 0,
.funcs = &dce_virtual_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_GFX,
.major = 7,
.minor = 2,
.rev = 0,
.funcs = &gfx_v7_0_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_SDMA,
.major = 2,
.minor = 0,
.rev = 0,
.funcs = &cik_sdma_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_UVD,
.major = 4,
.minor = 2,
.rev = 0,
.funcs = &uvd_v4_2_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_VCE,
.major = 2,
.minor = 0,
.rev = 0,
.funcs = &vce_v2_0_ip_funcs,
},
};
static const struct amdgpu_ip_block_version hawaii_ip_blocks[] =
{
/* ORDER MATTERS! */
......@@ -1776,6 +1845,74 @@ static const struct amdgpu_ip_block_version hawaii_ip_blocks[] =
},
};
static const struct amdgpu_ip_block_version hawaii_ip_blocks_vd[] =
{
/* ORDER MATTERS! */
{
.type = AMD_IP_BLOCK_TYPE_COMMON,
.major = 1,
.minor = 0,
.rev = 0,
.funcs = &cik_common_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_GMC,
.major = 7,
.minor = 0,
.rev = 0,
.funcs = &gmc_v7_0_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_IH,
.major = 2,
.minor = 0,
.rev = 0,
.funcs = &cik_ih_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_SMC,
.major = 7,
.minor = 0,
.rev = 0,
.funcs = &amdgpu_pp_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_DCE,
.major = 8,
.minor = 5,
.rev = 0,
.funcs = &dce_virtual_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_GFX,
.major = 7,
.minor = 3,
.rev = 0,
.funcs = &gfx_v7_0_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_SDMA,
.major = 2,
.minor = 0,
.rev = 0,
.funcs = &cik_sdma_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_UVD,
.major = 4,
.minor = 2,
.rev = 0,
.funcs = &uvd_v4_2_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_VCE,
.major = 2,
.minor = 0,
.rev = 0,
.funcs = &vce_v2_0_ip_funcs,
},
};
static const struct amdgpu_ip_block_version kabini_ip_blocks[] =
{
/* ORDER MATTERS! */
......@@ -1844,6 +1981,74 @@ static const struct amdgpu_ip_block_version kabini_ip_blocks[] =
},
};
static const struct amdgpu_ip_block_version kabini_ip_blocks_vd[] =
{
/* ORDER MATTERS! */
{
.type = AMD_IP_BLOCK_TYPE_COMMON,
.major = 1,
.minor = 0,
.rev = 0,
.funcs = &cik_common_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_GMC,
.major = 7,
.minor = 0,
.rev = 0,
.funcs = &gmc_v7_0_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_IH,
.major = 2,
.minor = 0,
.rev = 0,
.funcs = &cik_ih_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_SMC,
.major = 7,
.minor = 0,
.rev = 0,
.funcs = &amdgpu_pp_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_DCE,
.major = 8,
.minor = 3,
.rev = 0,
.funcs = &dce_virtual_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_GFX,
.major = 7,
.minor = 2,
.rev = 0,
.funcs = &gfx_v7_0_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_SDMA,
.major = 2,
.minor = 0,
.rev = 0,
.funcs = &cik_sdma_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_UVD,
.major = 4,
.minor = 2,
.rev = 0,
.funcs = &uvd_v4_2_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_VCE,
.major = 2,
.minor = 0,
.rev = 0,
.funcs = &vce_v2_0_ip_funcs,
},
};
static const struct amdgpu_ip_block_version mullins_ip_blocks[] =
{
/* ORDER MATTERS! */
......@@ -1912,6 +2117,74 @@ static const struct amdgpu_ip_block_version mullins_ip_blocks[] =
},
};
static const struct amdgpu_ip_block_version mullins_ip_blocks_vd[] =
{
/* ORDER MATTERS! */
{
.type = AMD_IP_BLOCK_TYPE_COMMON,
.major = 1,
.minor = 0,
.rev = 0,
.funcs = &cik_common_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_GMC,
.major = 7,
.minor = 0,
.rev = 0,
.funcs = &gmc_v7_0_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_IH,
.major = 2,
.minor = 0,
.rev = 0,
.funcs = &cik_ih_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_SMC,
.major = 7,
.minor = 0,
.rev = 0,
.funcs = &amdgpu_pp_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_DCE,
.major = 8,
.minor = 3,
.rev = 0,
.funcs = &dce_virtual_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_GFX,
.major = 7,
.minor = 2,
.rev = 0,
.funcs = &gfx_v7_0_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_SDMA,
.major = 2,
.minor = 0,
.rev = 0,
.funcs = &cik_sdma_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_UVD,
.major = 4,
.minor = 2,
.rev = 0,
.funcs = &uvd_v4_2_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_VCE,
.major = 2,
.minor = 0,
.rev = 0,
.funcs = &vce_v2_0_ip_funcs,
},
};
static const struct amdgpu_ip_block_version kaveri_ip_blocks[] =
{
/* ORDER MATTERS! */
......@@ -1980,32 +2253,128 @@ static const struct amdgpu_ip_block_version kaveri_ip_blocks[] =
},
};
static const struct amdgpu_ip_block_version kaveri_ip_blocks_vd[] =
{
/* ORDER MATTERS! */
{
.type = AMD_IP_BLOCK_TYPE_COMMON,
.major = 1,
.minor = 0,
.rev = 0,
.funcs = &cik_common_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_GMC,
.major = 7,
.minor = 0,
.rev = 0,
.funcs = &gmc_v7_0_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_IH,
.major = 2,
.minor = 0,
.rev = 0,
.funcs = &cik_ih_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_SMC,
.major = 7,
.minor = 0,
.rev = 0,
.funcs = &amdgpu_pp_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_DCE,
.major = 8,
.minor = 1,
.rev = 0,
.funcs = &dce_virtual_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_GFX,
.major = 7,
.minor = 1,
.rev = 0,
.funcs = &gfx_v7_0_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_SDMA,
.major = 2,
.minor = 0,
.rev = 0,
.funcs = &cik_sdma_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_UVD,
.major = 4,
.minor = 2,
.rev = 0,
.funcs = &uvd_v4_2_ip_funcs,
},
{
.type = AMD_IP_BLOCK_TYPE_VCE,
.major = 2,
.minor = 0,
.rev = 0,
.funcs = &vce_v2_0_ip_funcs,
},
};
int cik_set_ip_blocks(struct amdgpu_device *adev)
{
switch (adev->asic_type) {
case CHIP_BONAIRE:
adev->ip_blocks = bonaire_ip_blocks;
adev->num_ip_blocks = ARRAY_SIZE(bonaire_ip_blocks);
break;
case CHIP_HAWAII:
adev->ip_blocks = hawaii_ip_blocks;
adev->num_ip_blocks = ARRAY_SIZE(hawaii_ip_blocks);
break;
case CHIP_KAVERI:
adev->ip_blocks = kaveri_ip_blocks;
adev->num_ip_blocks = ARRAY_SIZE(kaveri_ip_blocks);
break;
case CHIP_KABINI:
adev->ip_blocks = kabini_ip_blocks;
adev->num_ip_blocks = ARRAY_SIZE(kabini_ip_blocks);
break;
case CHIP_MULLINS:
adev->ip_blocks = mullins_ip_blocks;
adev->num_ip_blocks = ARRAY_SIZE(mullins_ip_blocks);
break;
default:
/* FIXME: not supported yet */
return -EINVAL;
if (adev->enable_virtual_display) {
switch (adev->asic_type) {
case CHIP_BONAIRE:
adev->ip_blocks = bonaire_ip_blocks_vd;
adev->num_ip_blocks = ARRAY_SIZE(bonaire_ip_blocks_vd);
break;
case CHIP_HAWAII:
adev->ip_blocks = hawaii_ip_blocks_vd;
adev->num_ip_blocks = ARRAY_SIZE(hawaii_ip_blocks_vd);
break;
case CHIP_KAVERI:
adev->ip_blocks = kaveri_ip_blocks_vd;
adev->num_ip_blocks = ARRAY_SIZE(kaveri_ip_blocks_vd);
break;
case CHIP_KABINI:
adev->ip_blocks = kabini_ip_blocks_vd;
adev->num_ip_blocks = ARRAY_SIZE(kabini_ip_blocks_vd);
break;
case CHIP_MULLINS:
adev->ip_blocks = mullins_ip_blocks_vd;
adev->num_ip_blocks = ARRAY_SIZE(mullins_ip_blocks_vd);
break;
default:
/* FIXME: not supported yet */
return -EINVAL;
}
} else {
switch (adev->asic_type) {
case CHIP_BONAIRE:
adev->ip_blocks = bonaire_ip_blocks;
adev->num_ip_blocks = ARRAY_SIZE(bonaire_ip_blocks);
break;
case CHIP_HAWAII:
adev->ip_blocks = hawaii_ip_blocks;
adev->num_ip_blocks = ARRAY_SIZE(hawaii_ip_blocks);
break;
case CHIP_KAVERI:
adev->ip_blocks = kaveri_ip_blocks;
adev->num_ip_blocks = ARRAY_SIZE(kaveri_ip_blocks);
break;
case CHIP_KABINI:
adev->ip_blocks = kabini_ip_blocks;
adev->num_ip_blocks = ARRAY_SIZE(kabini_ip_blocks);
break;
case CHIP_MULLINS:
adev->ip_blocks = mullins_ip_blocks;
adev->num_ip_blocks = ARRAY_SIZE(mullins_ip_blocks);
break;
default:
/* FIXME: not supported yet */
return -EINVAL;
}
}
return 0;
......
......@@ -694,24 +694,16 @@ static void cik_sdma_vm_copy_pte(struct amdgpu_ib *ib,
uint64_t pe, uint64_t src,
unsigned count)
{
while (count) {
unsigned bytes = count * 8;
if (bytes > 0x1FFFF8)
bytes = 0x1FFFF8;
ib->ptr[ib->length_dw++] = SDMA_PACKET(SDMA_OPCODE_COPY,
SDMA_WRITE_SUB_OPCODE_LINEAR, 0);
ib->ptr[ib->length_dw++] = bytes;
ib->ptr[ib->length_dw++] = 0; /* src/dst endian swap */
ib->ptr[ib->length_dw++] = lower_32_bits(src);
ib->ptr[ib->length_dw++] = upper_32_bits(src);
ib->ptr[ib->length_dw++] = lower_32_bits(pe);
ib->ptr[ib->length_dw++] = upper_32_bits(pe);
pe += bytes;
src += bytes;
count -= bytes / 8;
}
unsigned bytes = count * 8;
ib->ptr[ib->length_dw++] = SDMA_PACKET(SDMA_OPCODE_COPY,
SDMA_WRITE_SUB_OPCODE_LINEAR, 0);
ib->ptr[ib->length_dw++] = bytes;
ib->ptr[ib->length_dw++] = 0; /* src/dst endian swap */
ib->ptr[ib->length_dw++] = lower_32_bits(src);
ib->ptr[ib->length_dw++] = upper_32_bits(src);
ib->ptr[ib->length_dw++] = lower_32_bits(pe);
ib->ptr[ib->length_dw++] = upper_32_bits(pe);
}
/**
......@@ -719,39 +711,27 @@ static void cik_sdma_vm_copy_pte(struct amdgpu_ib *ib,
*
* @ib: indirect buffer to fill with commands
* @pe: addr of the page entry
* @addr: dst addr to write into pe
* @value: dst addr to write into pe
* @count: number of page entries to update
* @incr: increase next addr by incr bytes
* @flags: access flags
*
* Update PTEs by writing them manually using sDMA (CIK).
*/
static void cik_sdma_vm_write_pte(struct amdgpu_ib *ib,
const dma_addr_t *pages_addr, uint64_t pe,
uint64_t addr, unsigned count,
uint32_t incr, uint32_t flags)
static void cik_sdma_vm_write_pte(struct amdgpu_ib *ib, uint64_t pe,
uint64_t value, unsigned count,
uint32_t incr)
{
uint64_t value;
unsigned ndw;
while (count) {
ndw = count * 2;
if (ndw > 0xFFFFE)
ndw = 0xFFFFE;
/* for non-physically contiguous pages (system) */
ib->ptr[ib->length_dw++] = SDMA_PACKET(SDMA_OPCODE_WRITE,
SDMA_WRITE_SUB_OPCODE_LINEAR, 0);
ib->ptr[ib->length_dw++] = pe;
ib->ptr[ib->length_dw++] = upper_32_bits(pe);
ib->ptr[ib->length_dw++] = ndw;
for (; ndw > 0; ndw -= 2, --count, pe += 8) {
value = amdgpu_vm_map_gart(pages_addr, addr);
addr += incr;
value |= flags;
ib->ptr[ib->length_dw++] = value;
ib->ptr[ib->length_dw++] = upper_32_bits(value);
}
unsigned ndw = count * 2;
ib->ptr[ib->length_dw++] = SDMA_PACKET(SDMA_OPCODE_WRITE,
SDMA_WRITE_SUB_OPCODE_LINEAR, 0);
ib->ptr[ib->length_dw++] = lower_32_bits(pe);
ib->ptr[ib->length_dw++] = upper_32_bits(pe);
ib->ptr[ib->length_dw++] = ndw;
for (; ndw > 0; ndw -= 2) {
ib->ptr[ib->length_dw++] = lower_32_bits(value);
ib->ptr[ib->length_dw++] = upper_32_bits(value);
value += incr;
}
}
......@@ -767,40 +747,21 @@ static void cik_sdma_vm_write_pte(struct amdgpu_ib *ib,
*
* Update the page tables using sDMA (CIK).
*/
static void cik_sdma_vm_set_pte_pde(struct amdgpu_ib *ib,
uint64_t pe,
static void cik_sdma_vm_set_pte_pde(struct amdgpu_ib *ib, uint64_t pe,
uint64_t addr, unsigned count,
uint32_t incr, uint32_t flags)
{
uint64_t value;
unsigned ndw;
while (count) {
ndw = count;
if (ndw > 0x7FFFF)
ndw = 0x7FFFF;
if (flags & AMDGPU_PTE_VALID)
value = addr;
else
value = 0;
/* for physically contiguous pages (vram) */
ib->ptr[ib->length_dw++] = SDMA_PACKET(SDMA_OPCODE_GENERATE_PTE_PDE, 0, 0);
ib->ptr[ib->length_dw++] = pe; /* dst addr */
ib->ptr[ib->length_dw++] = upper_32_bits(pe);
ib->ptr[ib->length_dw++] = flags; /* mask */
ib->ptr[ib->length_dw++] = 0;
ib->ptr[ib->length_dw++] = value; /* value */
ib->ptr[ib->length_dw++] = upper_32_bits(value);
ib->ptr[ib->length_dw++] = incr; /* increment size */
ib->ptr[ib->length_dw++] = 0;
ib->ptr[ib->length_dw++] = ndw; /* number of entries */
pe += ndw * 8;
addr += ndw * incr;
count -= ndw;
}
/* for physically contiguous pages (vram) */
ib->ptr[ib->length_dw++] = SDMA_PACKET(SDMA_OPCODE_GENERATE_PTE_PDE, 0, 0);
ib->ptr[ib->length_dw++] = lower_32_bits(pe); /* dst addr */
ib->ptr[ib->length_dw++] = upper_32_bits(pe);
ib->ptr[ib->length_dw++] = flags; /* mask */
ib->ptr[ib->length_dw++] = 0;
ib->ptr[ib->length_dw++] = lower_32_bits(addr); /* value */
ib->ptr[ib->length_dw++] = upper_32_bits(addr);
ib->ptr[ib->length_dw++] = incr; /* increment size */
ib->ptr[ib->length_dw++] = 0;
ib->ptr[ib->length_dw++] = count; /* number of entries */
}
/**
......
......@@ -435,7 +435,11 @@ static int cz_dpm_init(struct amdgpu_device *adev)
pi->caps_td_ramping = true;
pi->caps_tcp_ramping = true;
}
pi->caps_sclk_ds = true;
if (amdgpu_sclk_deep_sleep_en)
pi->caps_sclk_ds = true;
else
pi->caps_sclk_ds = false;
pi->voting_clients = 0x00c00033;
pi->auto_thermal_throttling_enabled = true;
pi->bapm_enabled = false;
......@@ -2108,29 +2112,58 @@ static void cz_dpm_powergate_uvd(struct amdgpu_device *adev, bool gate)
/* disable clockgating so we can properly shut down the block */
ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
AMD_CG_STATE_UNGATE);
if (ret) {
DRM_ERROR("UVD DPM Power Gating failed to set clockgating state\n");
return;
}
/* shutdown the UVD block */
ret = amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
AMD_PG_STATE_GATE);
/* XXX: check for errors */
if (ret) {
DRM_ERROR("UVD DPM Power Gating failed to set powergating state\n");
return;
}
}
cz_update_uvd_dpm(adev, gate);
if (pi->caps_uvd_pg)
if (pi->caps_uvd_pg) {
/* power off the UVD block */
cz_send_msg_to_smc(adev, PPSMC_MSG_UVDPowerOFF);
ret = cz_send_msg_to_smc(adev, PPSMC_MSG_UVDPowerOFF);
if (ret) {
DRM_ERROR("UVD DPM Power Gating failed to send SMU PowerOFF message\n");
return;
}
}
} else {
if (pi->caps_uvd_pg) {
/* power on the UVD block */
if (pi->uvd_dynamic_pg)
cz_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_UVDPowerON, 1);
ret = cz_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_UVDPowerON, 1);
else
cz_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_UVDPowerON, 0);
ret = cz_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_UVDPowerON, 0);
if (ret) {
DRM_ERROR("UVD DPM Power Gating Failed to send SMU PowerON message\n");
return;
}
/* re-init the UVD block */
ret = amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
AMD_PG_STATE_UNGATE);
if (ret) {
DRM_ERROR("UVD DPM Power Gating Failed to set powergating state\n");
return;
}
/* enable clockgating. hw will dynamically gate/ungate clocks on the fly */
ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
AMD_CG_STATE_GATE);
/* XXX: check for errors */
if (ret) {
DRM_ERROR("UVD DPM Power Gating Failed to set clockgating state\n");
return;
}
}
cz_update_uvd_dpm(adev, gate);
}
......
......@@ -646,8 +646,8 @@ static void dce_v10_0_resume_mc_access(struct amdgpu_device *adev,
if (save->crtc_enabled[i]) {
tmp = RREG32(mmMASTER_UPDATE_MODE + crtc_offsets[i]);
if (REG_GET_FIELD(tmp, MASTER_UPDATE_MODE, MASTER_UPDATE_MODE) != 3) {
tmp = REG_SET_FIELD(tmp, MASTER_UPDATE_MODE, MASTER_UPDATE_MODE, 3);
if (REG_GET_FIELD(tmp, MASTER_UPDATE_MODE, MASTER_UPDATE_MODE) != 0) {
tmp = REG_SET_FIELD(tmp, MASTER_UPDATE_MODE, MASTER_UPDATE_MODE, 0);
WREG32(mmMASTER_UPDATE_MODE + crtc_offsets[i], tmp);
}
tmp = RREG32(mmGRPH_UPDATE + crtc_offsets[i]);
......@@ -712,6 +712,45 @@ static void dce_v10_0_set_vga_render_state(struct amdgpu_device *adev,
WREG32(mmVGA_RENDER_CONTROL, tmp);
}
static int dce_v10_0_get_num_crtc(struct amdgpu_device *adev)
{
int num_crtc = 0;
switch (adev->asic_type) {
case CHIP_FIJI:
case CHIP_TONGA:
num_crtc = 6;
break;
default:
num_crtc = 0;
}
return num_crtc;
}
void dce_v10_0_disable_dce(struct amdgpu_device *adev)
{
/*Disable VGA render and enabled crtc, if has DCE engine*/
if (amdgpu_atombios_has_dce_engine_info(adev)) {
u32 tmp;
int crtc_enabled, i;
dce_v10_0_set_vga_render_state(adev, false);
/*Disable crtc*/
for (i = 0; i < dce_v10_0_get_num_crtc(adev); i++) {
crtc_enabled = REG_GET_FIELD(RREG32(mmCRTC_CONTROL + crtc_offsets[i]),
CRTC_CONTROL, CRTC_MASTER_EN);
if (crtc_enabled) {
WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 1);
tmp = RREG32(mmCRTC_CONTROL + crtc_offsets[i]);
tmp = REG_SET_FIELD(tmp, CRTC_CONTROL, CRTC_MASTER_EN, 0);
WREG32(mmCRTC_CONTROL + crtc_offsets[i], tmp);
WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 0);
}
}
}
}
static void dce_v10_0_program_fmt(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
......@@ -2277,8 +2316,8 @@ static int dce_v10_0_crtc_do_set_base(struct drm_crtc *crtc,
WREG32(mmVIEWPORT_SIZE + amdgpu_crtc->crtc_offset,
(viewport_w << 16) | viewport_h);
/* set pageflip to happen only at start of vblank interval (front porch) */
WREG32(mmMASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 3);
/* set pageflip to happen anywhere in vblank interval */
WREG32(mmMASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 0);
if (!atomic && fb && fb != crtc->primary->fb) {
amdgpu_fb = to_amdgpu_framebuffer(fb);
......@@ -2700,7 +2739,7 @@ static const struct drm_crtc_funcs dce_v10_0_crtc_funcs = {
.gamma_set = dce_v10_0_crtc_gamma_set,
.set_config = amdgpu_crtc_set_config,
.destroy = dce_v10_0_crtc_destroy,
.page_flip = amdgpu_crtc_page_flip,
.page_flip_target = amdgpu_crtc_page_flip_target,
};
static void dce_v10_0_crtc_dpms(struct drm_crtc *crtc, int mode)
......@@ -2964,10 +3003,11 @@ static int dce_v10_0_early_init(void *handle)
dce_v10_0_set_display_funcs(adev);
dce_v10_0_set_irq_funcs(adev);
adev->mode_info.num_crtc = dce_v10_0_get_num_crtc(adev);
switch (adev->asic_type) {
case CHIP_FIJI:
case CHIP_TONGA:
adev->mode_info.num_crtc = 6; /* XXX 7??? */
adev->mode_info.num_hpd = 6;
adev->mode_info.num_dig = 7;
break;
......@@ -3143,11 +3183,26 @@ static int dce_v10_0_wait_for_idle(void *handle)
return 0;
}
static int dce_v10_0_check_soft_reset(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
if (dce_v10_0_is_display_hung(adev))
adev->ip_block_status[AMD_IP_BLOCK_TYPE_DCE].hang = true;
else
adev->ip_block_status[AMD_IP_BLOCK_TYPE_DCE].hang = false;
return 0;
}
static int dce_v10_0_soft_reset(void *handle)
{
u32 srbm_soft_reset = 0, tmp;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_DCE].hang)
return 0;
if (dce_v10_0_is_display_hung(adev))
srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_DC_MASK;
......@@ -3514,6 +3569,7 @@ const struct amd_ip_funcs dce_v10_0_ip_funcs = {
.resume = dce_v10_0_resume,
.is_idle = dce_v10_0_is_idle,
.wait_for_idle = dce_v10_0_wait_for_idle,
.check_soft_reset = dce_v10_0_check_soft_reset,
.soft_reset = dce_v10_0_soft_reset,
.set_clockgating_state = dce_v10_0_set_clockgating_state,
.set_powergating_state = dce_v10_0_set_powergating_state,
......
......@@ -26,4 +26,6 @@
extern const struct amd_ip_funcs dce_v10_0_ip_funcs;
void dce_v10_0_disable_dce(struct amdgpu_device *adev);
#endif
......@@ -673,6 +673,53 @@ static void dce_v11_0_set_vga_render_state(struct amdgpu_device *adev,
WREG32(mmVGA_RENDER_CONTROL, tmp);
}
static int dce_v11_0_get_num_crtc (struct amdgpu_device *adev)
{
int num_crtc = 0;
switch (adev->asic_type) {
case CHIP_CARRIZO:
num_crtc = 3;
break;
case CHIP_STONEY:
num_crtc = 2;
break;
case CHIP_POLARIS10:
num_crtc = 6;
break;
case CHIP_POLARIS11:
num_crtc = 5;
break;
default:
num_crtc = 0;
}
return num_crtc;
}
void dce_v11_0_disable_dce(struct amdgpu_device *adev)
{
/*Disable VGA render and enabled crtc, if has DCE engine*/
if (amdgpu_atombios_has_dce_engine_info(adev)) {
u32 tmp;
int crtc_enabled, i;
dce_v11_0_set_vga_render_state(adev, false);
/*Disable crtc*/
for (i = 0; i < dce_v11_0_get_num_crtc(adev); i++) {
crtc_enabled = REG_GET_FIELD(RREG32(mmCRTC_CONTROL + crtc_offsets[i]),
CRTC_CONTROL, CRTC_MASTER_EN);
if (crtc_enabled) {
WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 1);
tmp = RREG32(mmCRTC_CONTROL + crtc_offsets[i]);
tmp = REG_SET_FIELD(tmp, CRTC_CONTROL, CRTC_MASTER_EN, 0);
WREG32(mmCRTC_CONTROL + crtc_offsets[i], tmp);
WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 0);
}
}
}
}
static void dce_v11_0_program_fmt(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
......@@ -2252,8 +2299,8 @@ static int dce_v11_0_crtc_do_set_base(struct drm_crtc *crtc,
WREG32(mmVIEWPORT_SIZE + amdgpu_crtc->crtc_offset,
(viewport_w << 16) | viewport_h);
/* set pageflip to happen only at start of vblank interval (front porch) */
WREG32(mmCRTC_MASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 3);
/* set pageflip to happen anywhere in vblank interval */
WREG32(mmCRTC_MASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 0);
if (!atomic && fb && fb != crtc->primary->fb) {
amdgpu_fb = to_amdgpu_framebuffer(fb);
......@@ -2710,7 +2757,7 @@ static const struct drm_crtc_funcs dce_v11_0_crtc_funcs = {
.gamma_set = dce_v11_0_crtc_gamma_set,
.set_config = amdgpu_crtc_set_config,
.destroy = dce_v11_0_crtc_destroy,
.page_flip = amdgpu_crtc_page_flip,
.page_flip_target = amdgpu_crtc_page_flip_target,
};
static void dce_v11_0_crtc_dpms(struct drm_crtc *crtc, int mode)
......@@ -3001,24 +3048,22 @@ static int dce_v11_0_early_init(void *handle)
dce_v11_0_set_display_funcs(adev);
dce_v11_0_set_irq_funcs(adev);
adev->mode_info.num_crtc = dce_v11_0_get_num_crtc(adev);
switch (adev->asic_type) {
case CHIP_CARRIZO:
adev->mode_info.num_crtc = 3;
adev->mode_info.num_hpd = 6;
adev->mode_info.num_dig = 9;
break;
case CHIP_STONEY:
adev->mode_info.num_crtc = 2;
adev->mode_info.num_hpd = 6;
adev->mode_info.num_dig = 9;
break;
case CHIP_POLARIS10:
adev->mode_info.num_crtc = 6;
adev->mode_info.num_hpd = 6;
adev->mode_info.num_dig = 6;
break;
case CHIP_POLARIS11:
adev->mode_info.num_crtc = 5;
adev->mode_info.num_hpd = 5;
adev->mode_info.num_dig = 5;
break;
......
......@@ -26,4 +26,6 @@
extern const struct amd_ip_funcs dce_v11_0_ip_funcs;
void dce_v11_0_disable_dce(struct amdgpu_device *adev);
#endif
......@@ -604,6 +604,52 @@ static void dce_v8_0_set_vga_render_state(struct amdgpu_device *adev,
WREG32(mmVGA_RENDER_CONTROL, tmp);
}
static int dce_v8_0_get_num_crtc(struct amdgpu_device *adev)
{
int num_crtc = 0;
switch (adev->asic_type) {
case CHIP_BONAIRE:
case CHIP_HAWAII:
num_crtc = 6;
break;
case CHIP_KAVERI:
num_crtc = 4;
break;
case CHIP_KABINI:
case CHIP_MULLINS:
num_crtc = 2;
break;
default:
num_crtc = 0;
}
return num_crtc;
}
void dce_v8_0_disable_dce(struct amdgpu_device *adev)
{
/*Disable VGA render and enabled crtc, if has DCE engine*/
if (amdgpu_atombios_has_dce_engine_info(adev)) {
u32 tmp;
int crtc_enabled, i;
dce_v8_0_set_vga_render_state(adev, false);
/*Disable crtc*/
for (i = 0; i < dce_v8_0_get_num_crtc(adev); i++) {
crtc_enabled = REG_GET_FIELD(RREG32(mmCRTC_CONTROL + crtc_offsets[i]),
CRTC_CONTROL, CRTC_MASTER_EN);
if (crtc_enabled) {
WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 1);
tmp = RREG32(mmCRTC_CONTROL + crtc_offsets[i]);
tmp = REG_SET_FIELD(tmp, CRTC_CONTROL, CRTC_MASTER_EN, 0);
WREG32(mmCRTC_CONTROL + crtc_offsets[i], tmp);
WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 0);
}
}
}
}
static void dce_v8_0_program_fmt(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
......@@ -1501,13 +1547,13 @@ static void dce_v8_0_audio_write_sad_regs(struct drm_encoder *encoder)
if (sad->format == eld_reg_to_type[i][1]) {
if (sad->channels > max_channels) {
value = (sad->channels <<
AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0__MAX_CHANNELS__SHIFT) |
(sad->byte2 <<
AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0__DESCRIPTOR_BYTE_2__SHIFT) |
(sad->freq <<
AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0__SUPPORTED_FREQUENCIES__SHIFT);
max_channels = sad->channels;
value = (sad->channels <<
AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0__MAX_CHANNELS__SHIFT) |
(sad->byte2 <<
AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0__DESCRIPTOR_BYTE_2__SHIFT) |
(sad->freq <<
AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0__SUPPORTED_FREQUENCIES__SHIFT);
max_channels = sad->channels;
}
if (sad->format == HDMI_AUDIO_CODING_TYPE_PCM)
......@@ -1613,7 +1659,7 @@ static void dce_v8_0_afmt_update_ACR(struct drm_encoder *encoder, uint32_t clock
struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv;
uint32_t offset = dig->afmt->offset;
WREG32(mmHDMI_ACR_32_0 + offset, (acr.cts_32khz << HDMI_ACR_44_0__HDMI_ACR_CTS_44__SHIFT));
WREG32(mmHDMI_ACR_32_0 + offset, (acr.cts_32khz << HDMI_ACR_32_0__HDMI_ACR_CTS_32__SHIFT));
WREG32(mmHDMI_ACR_32_1 + offset, acr.n_32khz);
WREG32(mmHDMI_ACR_44_0 + offset, (acr.cts_44_1khz << HDMI_ACR_44_0__HDMI_ACR_CTS_44__SHIFT));
......@@ -1693,6 +1739,7 @@ static void dce_v8_0_afmt_setmode(struct drm_encoder *encoder,
/* Silent, r600_hdmi_enable will raise WARN for us */
if (!dig->afmt->enabled)
return;
offset = dig->afmt->offset;
/* hdmi deep color mode general control packets setup, if bpc > 8 */
......@@ -1817,7 +1864,7 @@ static void dce_v8_0_afmt_setmode(struct drm_encoder *encoder,
WREG32_OR(mmHDMI_INFOFRAME_CONTROL0 + offset,
HDMI_INFOFRAME_CONTROL0__HDMI_AVI_INFO_SEND_MASK | /* enable AVI info frames */
HDMI_INFOFRAME_CONTROL0__HDMI_AVI_INFO_SEND_MASK); /* required for audio info values to be updated */
HDMI_INFOFRAME_CONTROL0__HDMI_AVI_INFO_CONT_MASK); /* required for audio info values to be updated */
WREG32_P(mmHDMI_INFOFRAME_CONTROL1 + offset,
(2 << HDMI_INFOFRAME_CONTROL1__HDMI_AVI_INFO_LINE__SHIFT), /* anything other than 0 */
......@@ -1826,13 +1873,12 @@ static void dce_v8_0_afmt_setmode(struct drm_encoder *encoder,
WREG32_OR(mmAFMT_AUDIO_PACKET_CONTROL + offset,
AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_SAMPLE_SEND_MASK); /* send audio packets */
/* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */
WREG32(mmAFMT_RAMP_CONTROL0 + offset, 0x00FFFFFF);
WREG32(mmAFMT_RAMP_CONTROL1 + offset, 0x007FFFFF);
WREG32(mmAFMT_RAMP_CONTROL2 + offset, 0x00000001);
WREG32(mmAFMT_RAMP_CONTROL3 + offset, 0x00000001);
/* enable audio after to setting up hw */
/* enable audio after setting up hw */
dce_v8_0_audio_enable(adev, dig->afmt->pin, true);
}
......@@ -2000,7 +2046,7 @@ static int dce_v8_0_crtc_do_set_base(struct drm_crtc *crtc,
case DRM_FORMAT_XRGB4444:
case DRM_FORMAT_ARGB4444:
fb_format = ((GRPH_DEPTH_16BPP << GRPH_CONTROL__GRPH_DEPTH__SHIFT) |
(GRPH_FORMAT_ARGB1555 << GRPH_CONTROL__GRPH_FORMAT__SHIFT));
(GRPH_FORMAT_ARGB4444 << GRPH_CONTROL__GRPH_FORMAT__SHIFT));
#ifdef __BIG_ENDIAN
fb_swap = (GRPH_ENDIAN_8IN16 << GRPH_SWAP_CNTL__GRPH_ENDIAN_SWAP__SHIFT);
#endif
......@@ -2139,8 +2185,8 @@ static int dce_v8_0_crtc_do_set_base(struct drm_crtc *crtc,
WREG32(mmVIEWPORT_SIZE + amdgpu_crtc->crtc_offset,
(viewport_w << 16) | viewport_h);
/* set pageflip to happen only at start of vblank interval (front porch) */
WREG32(mmMASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 3);
/* set pageflip to happen anywhere in vblank interval */
WREG32(mmMASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 0);
if (!atomic && fb && fb != crtc->primary->fb) {
amdgpu_fb = to_amdgpu_framebuffer(fb);
......@@ -2554,7 +2600,7 @@ static const struct drm_crtc_funcs dce_v8_0_crtc_funcs = {
.gamma_set = dce_v8_0_crtc_gamma_set,
.set_config = amdgpu_crtc_set_config,
.destroy = dce_v8_0_crtc_destroy,
.page_flip = amdgpu_crtc_page_flip,
.page_flip_target = amdgpu_crtc_page_flip_target,
};
static void dce_v8_0_crtc_dpms(struct drm_crtc *crtc, int mode)
......@@ -2655,7 +2701,7 @@ static void dce_v8_0_crtc_disable(struct drm_crtc *crtc)
case ATOM_PPLL2:
/* disable the ppll */
amdgpu_atombios_crtc_program_pll(crtc, amdgpu_crtc->crtc_id, amdgpu_crtc->pll_id,
0, 0, ATOM_DISABLE, 0, 0, 0, 0, 0, false, &ss);
0, 0, ATOM_DISABLE, 0, 0, 0, 0, 0, false, &ss);
break;
case ATOM_PPLL0:
/* disable the ppll */
......@@ -2805,21 +2851,20 @@ static int dce_v8_0_early_init(void *handle)
dce_v8_0_set_display_funcs(adev);
dce_v8_0_set_irq_funcs(adev);
adev->mode_info.num_crtc = dce_v8_0_get_num_crtc(adev);
switch (adev->asic_type) {
case CHIP_BONAIRE:
case CHIP_HAWAII:
adev->mode_info.num_crtc = 6;
adev->mode_info.num_hpd = 6;
adev->mode_info.num_dig = 6;
break;
case CHIP_KAVERI:
adev->mode_info.num_crtc = 4;
adev->mode_info.num_hpd = 6;
adev->mode_info.num_dig = 7;
break;
case CHIP_KABINI:
case CHIP_MULLINS:
adev->mode_info.num_crtc = 2;
adev->mode_info.num_hpd = 6;
adev->mode_info.num_dig = 6; /* ? */
break;
......@@ -3238,7 +3283,6 @@ static int dce_v8_0_crtc_irq(struct amdgpu_device *adev,
drm_handle_vblank(adev->ddev, crtc);
}
DRM_DEBUG("IH: D%d vblank\n", crtc + 1);
break;
case 1: /* vline */
if (disp_int & interrupt_status_offsets[crtc].vline)
......@@ -3247,7 +3291,6 @@ static int dce_v8_0_crtc_irq(struct amdgpu_device *adev,
DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
DRM_DEBUG("IH: D%d vline\n", crtc + 1);
break;
default:
DRM_DEBUG("Unhandled interrupt: %d %d\n", entry->src_id, entry->src_data);
......
......@@ -26,4 +26,6 @@
extern const struct amd_ip_funcs dce_v8_0_ip_funcs;
void dce_v8_0_disable_dce(struct amdgpu_device *adev);
#endif
此差异已折叠。
/*
* Copyright 2014 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 __DCE_VIRTUAL_H__
#define __DCE_VIRTUAL_H__
extern const struct amd_ip_funcs dce_virtual_ip_funcs;
#define DCE_VIRTUAL_VBLANK_PERIOD 16666666
#endif
......@@ -4465,24 +4465,21 @@ static int gfx_v7_0_sw_init(void *handle)
}
/* reserve GDS, GWS and OA resource for gfx */
r = amdgpu_bo_create(adev, adev->gds.mem.gfx_partition_size,
PAGE_SIZE, true,
AMDGPU_GEM_DOMAIN_GDS, 0,
NULL, NULL, &adev->gds.gds_gfx_bo);
r = amdgpu_bo_create_kernel(adev, adev->gds.mem.gfx_partition_size,
PAGE_SIZE, AMDGPU_GEM_DOMAIN_GDS,
&adev->gds.gds_gfx_bo, NULL, NULL);
if (r)
return r;
r = amdgpu_bo_create(adev, adev->gds.gws.gfx_partition_size,
PAGE_SIZE, true,
AMDGPU_GEM_DOMAIN_GWS, 0,
NULL, NULL, &adev->gds.gws_gfx_bo);
r = amdgpu_bo_create_kernel(adev, adev->gds.gws.gfx_partition_size,
PAGE_SIZE, AMDGPU_GEM_DOMAIN_GWS,
&adev->gds.gws_gfx_bo, NULL, NULL);
if (r)
return r;
r = amdgpu_bo_create(adev, adev->gds.oa.gfx_partition_size,
PAGE_SIZE, true,
AMDGPU_GEM_DOMAIN_OA, 0,
NULL, NULL, &adev->gds.oa_gfx_bo);
r = amdgpu_bo_create_kernel(adev, adev->gds.oa.gfx_partition_size,
PAGE_SIZE, AMDGPU_GEM_DOMAIN_OA,
&adev->gds.oa_gfx_bo, NULL, NULL);
if (r)
return r;
......
......@@ -26,6 +26,4 @@
extern const struct amd_ip_funcs gfx_v8_0_ip_funcs;
void gfx_v8_0_select_se_sh(struct amdgpu_device *adev, u32 se_num, u32 sh_num);
#endif
......@@ -183,7 +183,7 @@ static int gmc_v7_0_mc_load_microcode(struct amdgpu_device *adev)
const struct mc_firmware_header_v1_0 *hdr;
const __le32 *fw_data = NULL;
const __le32 *io_mc_regs = NULL;
u32 running, blackout = 0;
u32 running;
int i, ucode_size, regs_size;
if (!adev->mc.fw)
......@@ -203,11 +203,6 @@ static int gmc_v7_0_mc_load_microcode(struct amdgpu_device *adev)
running = REG_GET_FIELD(RREG32(mmMC_SEQ_SUP_CNTL), MC_SEQ_SUP_CNTL, RUN);
if (running == 0) {
if (running) {
blackout = RREG32(mmMC_SHARED_BLACKOUT_CNTL);
WREG32(mmMC_SHARED_BLACKOUT_CNTL, blackout | 1);
}
/* reset the engine and set to writable */
WREG32(mmMC_SEQ_SUP_CNTL, 0x00000008);
WREG32(mmMC_SEQ_SUP_CNTL, 0x00000010);
......@@ -239,9 +234,6 @@ static int gmc_v7_0_mc_load_microcode(struct amdgpu_device *adev)
break;
udelay(1);
}
if (running)
WREG32(mmMC_SHARED_BLACKOUT_CNTL, blackout);
}
return 0;
......@@ -393,7 +385,7 @@ static int gmc_v7_0_mc_init(struct amdgpu_device *adev)
* size equal to the 1024 or vram, whichever is larger.
*/
if (amdgpu_gart_size == -1)
adev->mc.gtt_size = max((1024ULL << 20), adev->mc.mc_vram_size);
adev->mc.gtt_size = amdgpu_ttm_get_gtt_mem_size(adev);
else
adev->mc.gtt_size = (uint64_t)amdgpu_gart_size << 20;
......@@ -953,6 +945,11 @@ static int gmc_v7_0_sw_init(void *handle)
return r;
}
r = amdgpu_ttm_global_init(adev);
if (r) {
return r;
}
r = gmc_v7_0_mc_init(adev);
if (r)
return r;
......
......@@ -261,7 +261,7 @@ static int gmc_v8_0_mc_load_microcode(struct amdgpu_device *adev)
const struct mc_firmware_header_v1_0 *hdr;
const __le32 *fw_data = NULL;
const __le32 *io_mc_regs = NULL;
u32 running, blackout = 0;
u32 running;
int i, ucode_size, regs_size;
if (!adev->mc.fw)
......@@ -287,11 +287,6 @@ static int gmc_v8_0_mc_load_microcode(struct amdgpu_device *adev)
running = REG_GET_FIELD(RREG32(mmMC_SEQ_SUP_CNTL), MC_SEQ_SUP_CNTL, RUN);
if (running == 0) {
if (running) {
blackout = RREG32(mmMC_SHARED_BLACKOUT_CNTL);
WREG32(mmMC_SHARED_BLACKOUT_CNTL, blackout | 1);
}
/* reset the engine and set to writable */
WREG32(mmMC_SEQ_SUP_CNTL, 0x00000008);
WREG32(mmMC_SEQ_SUP_CNTL, 0x00000010);
......@@ -323,9 +318,6 @@ static int gmc_v8_0_mc_load_microcode(struct amdgpu_device *adev)
break;
udelay(1);
}
if (running)
WREG32(mmMC_SHARED_BLACKOUT_CNTL, blackout);
}
return 0;
......@@ -477,7 +469,7 @@ static int gmc_v8_0_mc_init(struct amdgpu_device *adev)
* size equal to the 1024 or vram, whichever is larger.
*/
if (amdgpu_gart_size == -1)
adev->mc.gtt_size = max((1024ULL << 20), adev->mc.mc_vram_size);
adev->mc.gtt_size = amdgpu_ttm_get_gtt_mem_size(adev);
else
adev->mc.gtt_size = (uint64_t)amdgpu_gart_size << 20;
......@@ -957,6 +949,11 @@ static int gmc_v8_0_sw_init(void *handle)
return r;
}
r = amdgpu_ttm_global_init(adev);
if (r) {
return r;
}
r = gmc_v8_0_mc_init(adev);
if (r)
return r;
......@@ -1100,9 +1097,8 @@ static int gmc_v8_0_wait_for_idle(void *handle)
}
static int gmc_v8_0_soft_reset(void *handle)
static int gmc_v8_0_check_soft_reset(void *handle)
{
struct amdgpu_mode_mc_save save;
u32 srbm_soft_reset = 0;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
u32 tmp = RREG32(mmSRBM_STATUS);
......@@ -1117,13 +1113,42 @@ static int gmc_v8_0_soft_reset(void *handle)
srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset,
SRBM_SOFT_RESET, SOFT_RESET_MC, 1);
}
if (srbm_soft_reset) {
gmc_v8_0_mc_stop(adev, &save);
if (gmc_v8_0_wait_for_idle((void *)adev)) {
dev_warn(adev->dev, "Wait for GMC idle timed out !\n");
}
adev->ip_block_status[AMD_IP_BLOCK_TYPE_GMC].hang = true;
adev->mc.srbm_soft_reset = srbm_soft_reset;
} else {
adev->ip_block_status[AMD_IP_BLOCK_TYPE_GMC].hang = false;
adev->mc.srbm_soft_reset = 0;
}
return 0;
}
static int gmc_v8_0_pre_soft_reset(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_GMC].hang)
return 0;
gmc_v8_0_mc_stop(adev, &adev->mc.save);
if (gmc_v8_0_wait_for_idle(adev)) {
dev_warn(adev->dev, "Wait for GMC idle timed out !\n");
}
return 0;
}
static int gmc_v8_0_soft_reset(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
u32 srbm_soft_reset;
if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_GMC].hang)
return 0;
srbm_soft_reset = adev->mc.srbm_soft_reset;
if (srbm_soft_reset) {
u32 tmp;
tmp = RREG32(mmSRBM_SOFT_RESET);
tmp |= srbm_soft_reset;
......@@ -1139,14 +1164,22 @@ static int gmc_v8_0_soft_reset(void *handle)
/* Wait a little for things to settle down */
udelay(50);
gmc_v8_0_mc_resume(adev, &save);
udelay(50);
}
return 0;
}
static int gmc_v8_0_post_soft_reset(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_GMC].hang)
return 0;
gmc_v8_0_mc_resume(adev, &adev->mc.save);
return 0;
}
static int gmc_v8_0_vm_fault_interrupt_state(struct amdgpu_device *adev,
struct amdgpu_irq_src *src,
unsigned type,
......@@ -1414,7 +1447,10 @@ const struct amd_ip_funcs gmc_v8_0_ip_funcs = {
.resume = gmc_v8_0_resume,
.is_idle = gmc_v8_0_is_idle,
.wait_for_idle = gmc_v8_0_wait_for_idle,
.check_soft_reset = gmc_v8_0_check_soft_reset,
.pre_soft_reset = gmc_v8_0_pre_soft_reset,
.soft_reset = gmc_v8_0_soft_reset,
.post_soft_reset = gmc_v8_0_post_soft_reset,
.set_clockgating_state = gmc_v8_0_set_clockgating_state,
.set_powergating_state = gmc_v8_0_set_powergating_state,
};
......
......@@ -2845,7 +2845,11 @@ static int kv_dpm_init(struct amdgpu_device *adev)
pi->caps_tcp_ramping = true;
}
pi->caps_sclk_ds = true;
if (amdgpu_sclk_deep_sleep_en)
pi->caps_sclk_ds = true;
else
pi->caps_sclk_ds = false;
pi->enable_auto_thermal_throttling = true;
pi->disable_nb_ps3_in_battery = false;
if (amdgpu_bapm == 0)
......
......@@ -749,24 +749,16 @@ static void sdma_v2_4_vm_copy_pte(struct amdgpu_ib *ib,
uint64_t pe, uint64_t src,
unsigned count)
{
while (count) {
unsigned bytes = count * 8;
if (bytes > 0x1FFFF8)
bytes = 0x1FFFF8;
ib->ptr[ib->length_dw++] = SDMA_PKT_HEADER_OP(SDMA_OP_COPY) |
SDMA_PKT_HEADER_SUB_OP(SDMA_SUBOP_COPY_LINEAR);
ib->ptr[ib->length_dw++] = bytes;
ib->ptr[ib->length_dw++] = 0; /* src/dst endian swap */
ib->ptr[ib->length_dw++] = lower_32_bits(src);
ib->ptr[ib->length_dw++] = upper_32_bits(src);
ib->ptr[ib->length_dw++] = lower_32_bits(pe);
ib->ptr[ib->length_dw++] = upper_32_bits(pe);
pe += bytes;
src += bytes;
count -= bytes / 8;
}
unsigned bytes = count * 8;
ib->ptr[ib->length_dw++] = SDMA_PKT_HEADER_OP(SDMA_OP_COPY) |
SDMA_PKT_HEADER_SUB_OP(SDMA_SUBOP_COPY_LINEAR);
ib->ptr[ib->length_dw++] = bytes;
ib->ptr[ib->length_dw++] = 0; /* src/dst endian swap */
ib->ptr[ib->length_dw++] = lower_32_bits(src);
ib->ptr[ib->length_dw++] = upper_32_bits(src);
ib->ptr[ib->length_dw++] = lower_32_bits(pe);
ib->ptr[ib->length_dw++] = upper_32_bits(pe);
}
/**
......@@ -774,39 +766,27 @@ static void sdma_v2_4_vm_copy_pte(struct amdgpu_ib *ib,
*
* @ib: indirect buffer to fill with commands
* @pe: addr of the page entry
* @addr: dst addr to write into pe
* @value: dst addr to write into pe
* @count: number of page entries to update
* @incr: increase next addr by incr bytes
* @flags: access flags
*
* Update PTEs by writing them manually using sDMA (CIK).
*/
static void sdma_v2_4_vm_write_pte(struct amdgpu_ib *ib,
const dma_addr_t *pages_addr, uint64_t pe,
uint64_t addr, unsigned count,
uint32_t incr, uint32_t flags)
static void sdma_v2_4_vm_write_pte(struct amdgpu_ib *ib, uint64_t pe,
uint64_t value, unsigned count,
uint32_t incr)
{
uint64_t value;
unsigned ndw;
while (count) {
ndw = count * 2;
if (ndw > 0xFFFFE)
ndw = 0xFFFFE;
/* for non-physically contiguous pages (system) */
ib->ptr[ib->length_dw++] = SDMA_PKT_HEADER_OP(SDMA_OP_WRITE) |
SDMA_PKT_HEADER_SUB_OP(SDMA_SUBOP_COPY_LINEAR);
ib->ptr[ib->length_dw++] = pe;
ib->ptr[ib->length_dw++] = upper_32_bits(pe);
ib->ptr[ib->length_dw++] = ndw;
for (; ndw > 0; ndw -= 2, --count, pe += 8) {
value = amdgpu_vm_map_gart(pages_addr, addr);
addr += incr;
value |= flags;
ib->ptr[ib->length_dw++] = value;
ib->ptr[ib->length_dw++] = upper_32_bits(value);
}
unsigned ndw = count * 2;
ib->ptr[ib->length_dw++] = SDMA_PKT_HEADER_OP(SDMA_OP_WRITE) |
SDMA_PKT_HEADER_SUB_OP(SDMA_SUBOP_COPY_LINEAR);
ib->ptr[ib->length_dw++] = pe;
ib->ptr[ib->length_dw++] = upper_32_bits(pe);
ib->ptr[ib->length_dw++] = ndw;
for (; ndw > 0; ndw -= 2, --count, pe += 8) {
ib->ptr[ib->length_dw++] = lower_32_bits(value);
ib->ptr[ib->length_dw++] = upper_32_bits(value);
value += incr;
}
}
......@@ -822,40 +802,21 @@ static void sdma_v2_4_vm_write_pte(struct amdgpu_ib *ib,
*
* Update the page tables using sDMA (CIK).
*/
static void sdma_v2_4_vm_set_pte_pde(struct amdgpu_ib *ib,
uint64_t pe,
static void sdma_v2_4_vm_set_pte_pde(struct amdgpu_ib *ib, uint64_t pe,
uint64_t addr, unsigned count,
uint32_t incr, uint32_t flags)
{
uint64_t value;
unsigned ndw;
while (count) {
ndw = count;
if (ndw > 0x7FFFF)
ndw = 0x7FFFF;
if (flags & AMDGPU_PTE_VALID)
value = addr;
else
value = 0;
/* for physically contiguous pages (vram) */
ib->ptr[ib->length_dw++] = SDMA_PKT_HEADER_OP(SDMA_OP_GEN_PTEPDE);
ib->ptr[ib->length_dw++] = pe; /* dst addr */
ib->ptr[ib->length_dw++] = upper_32_bits(pe);
ib->ptr[ib->length_dw++] = flags; /* mask */
ib->ptr[ib->length_dw++] = 0;
ib->ptr[ib->length_dw++] = value; /* value */
ib->ptr[ib->length_dw++] = upper_32_bits(value);
ib->ptr[ib->length_dw++] = incr; /* increment size */
ib->ptr[ib->length_dw++] = 0;
ib->ptr[ib->length_dw++] = ndw; /* number of entries */
pe += ndw * 8;
addr += ndw * incr;
count -= ndw;
}
/* for physically contiguous pages (vram) */
ib->ptr[ib->length_dw++] = SDMA_PKT_HEADER_OP(SDMA_OP_GEN_PTEPDE);
ib->ptr[ib->length_dw++] = lower_32_bits(pe); /* dst addr */
ib->ptr[ib->length_dw++] = upper_32_bits(pe);
ib->ptr[ib->length_dw++] = flags; /* mask */
ib->ptr[ib->length_dw++] = 0;
ib->ptr[ib->length_dw++] = lower_32_bits(addr); /* value */
ib->ptr[ib->length_dw++] = upper_32_bits(addr);
ib->ptr[ib->length_dw++] = incr; /* increment size */
ib->ptr[ib->length_dw++] = 0;
ib->ptr[ib->length_dw++] = count; /* number of entries */
}
/**
......
......@@ -373,10 +373,10 @@ static int tonga_ih_wait_for_idle(void *handle)
return -ETIMEDOUT;
}
static int tonga_ih_soft_reset(void *handle)
static int tonga_ih_check_soft_reset(void *handle)
{
u32 srbm_soft_reset = 0;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
u32 srbm_soft_reset = 0;
u32 tmp = RREG32(mmSRBM_STATUS);
if (tmp & SRBM_STATUS__IH_BUSY_MASK)
......@@ -384,6 +384,48 @@ static int tonga_ih_soft_reset(void *handle)
SOFT_RESET_IH, 1);
if (srbm_soft_reset) {
adev->ip_block_status[AMD_IP_BLOCK_TYPE_IH].hang = true;
adev->irq.srbm_soft_reset = srbm_soft_reset;
} else {
adev->ip_block_status[AMD_IP_BLOCK_TYPE_IH].hang = false;
adev->irq.srbm_soft_reset = 0;
}
return 0;
}
static int tonga_ih_pre_soft_reset(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_IH].hang)
return 0;
return tonga_ih_hw_fini(adev);
}
static int tonga_ih_post_soft_reset(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_IH].hang)
return 0;
return tonga_ih_hw_init(adev);
}
static int tonga_ih_soft_reset(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
u32 srbm_soft_reset;
if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_IH].hang)
return 0;
srbm_soft_reset = adev->irq.srbm_soft_reset;
if (srbm_soft_reset) {
u32 tmp;
tmp = RREG32(mmSRBM_SOFT_RESET);
tmp |= srbm_soft_reset;
dev_info(adev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp);
......@@ -427,7 +469,10 @@ const struct amd_ip_funcs tonga_ih_ip_funcs = {
.resume = tonga_ih_resume,
.is_idle = tonga_ih_is_idle,
.wait_for_idle = tonga_ih_wait_for_idle,
.check_soft_reset = tonga_ih_check_soft_reset,
.pre_soft_reset = tonga_ih_pre_soft_reset,
.soft_reset = tonga_ih_soft_reset,
.post_soft_reset = tonga_ih_post_soft_reset,
.set_clockgating_state = tonga_ih_set_clockgating_state,
.set_powergating_state = tonga_ih_set_powergating_state,
};
......
......@@ -116,7 +116,7 @@ static int uvd_v4_2_sw_init(void *handle)
ring = &adev->uvd.ring;
sprintf(ring->name, "uvd");
r = amdgpu_ring_init(adev, ring, 512, CP_PACKET2, 0xf,
r = amdgpu_ring_init(adev, ring, 512, PACKET0(mmUVD_NO_OP, 0), 0xf,
&adev->uvd.irq, 0, AMDGPU_RING_TYPE_UVD);
return r;
......
......@@ -112,7 +112,7 @@ static int uvd_v5_0_sw_init(void *handle)
ring = &adev->uvd.ring;
sprintf(ring->name, "uvd");
r = amdgpu_ring_init(adev, ring, 512, CP_PACKET2, 0xf,
r = amdgpu_ring_init(adev, ring, 512, PACKET0(mmUVD_NO_OP, 0), 0xf,
&adev->uvd.irq, 0, AMDGPU_RING_TYPE_UVD);
return r;
......
此差异已折叠。
......@@ -159,8 +159,14 @@ struct amd_ip_funcs {
bool (*is_idle)(void *handle);
/* poll for idle */
int (*wait_for_idle)(void *handle);
/* check soft reset the IP block */
int (*check_soft_reset)(void *handle);
/* pre soft reset the IP block */
int (*pre_soft_reset)(void *handle);
/* soft reset the IP block */
int (*soft_reset)(void *handle);
/* post soft reset the IP block */
int (*post_soft_reset)(void *handle);
/* enable/disable cg for the IP block */
int (*set_clockgating_state)(void *handle,
enum amd_clockgating_state state);
......
......@@ -34,6 +34,7 @@
#define mmUVD_UDEC_ADDR_CONFIG 0x3bd3
#define mmUVD_UDEC_DB_ADDR_CONFIG 0x3bd4
#define mmUVD_UDEC_DBW_ADDR_CONFIG 0x3bd5
#define mmUVD_NO_OP 0x3bff
#define mmUVD_SEMA_CNTL 0x3d00
#define mmUVD_LMI_EXT40_ADDR 0x3d26
#define mmUVD_CTX_INDEX 0x3d28
......
......@@ -34,6 +34,7 @@
#define mmUVD_UDEC_ADDR_CONFIG 0x3bd3
#define mmUVD_UDEC_DB_ADDR_CONFIG 0x3bd4
#define mmUVD_UDEC_DBW_ADDR_CONFIG 0x3bd5
#define mmUVD_NO_OP 0x3bff
#define mmUVD_LMI_RBC_RB_64BIT_BAR_LOW 0x3c69
#define mmUVD_LMI_RBC_RB_64BIT_BAR_HIGH 0x3c68
#define mmUVD_LMI_RBC_IB_64BIT_BAR_LOW 0x3c67
......
......@@ -35,6 +35,7 @@
#define mmUVD_UDEC_DB_ADDR_CONFIG 0x3bd4
#define mmUVD_UDEC_DBW_ADDR_CONFIG 0x3bd5
#define mmUVD_POWER_STATUS_U 0x3bfd
#define mmUVD_NO_OP 0x3bff
#define mmUVD_LMI_RBC_RB_64BIT_BAR_LOW 0x3c69
#define mmUVD_LMI_RBC_RB_64BIT_BAR_HIGH 0x3c68
#define mmUVD_LMI_RBC_IB_64BIT_BAR_LOW 0x3c67
......
......@@ -31,6 +31,7 @@
#include "eventmanager.h"
#include "pp_debug.h"
#define PP_CHECK(handle) \
do { \
if ((handle) == NULL || (handle)->pp_valid != PP_VALID) \
......@@ -162,12 +163,12 @@ static int pp_hw_fini(void *handle)
pp_handle = (struct pp_instance *)handle;
eventmgr = pp_handle->eventmgr;
if (eventmgr != NULL || eventmgr->pp_eventmgr_fini != NULL)
if (eventmgr != NULL && eventmgr->pp_eventmgr_fini != NULL)
eventmgr->pp_eventmgr_fini(eventmgr);
smumgr = pp_handle->smu_mgr;
if (smumgr != NULL || smumgr->smumgr_funcs != NULL ||
if (smumgr != NULL && smumgr->smumgr_funcs != NULL &&
smumgr->smumgr_funcs->smu_fini != NULL)
smumgr->smumgr_funcs->smu_fini(smumgr);
......
......@@ -4,13 +4,15 @@
HARDWARE_MGR = hwmgr.o processpptables.o functiontables.o \
hardwaremanager.o pp_acpi.o cz_hwmgr.o \
cz_clockpowergating.o \
cz_clockpowergating.o tonga_powertune.o\
tonga_processpptables.o ppatomctrl.o \
tonga_hwmgr.o pppcielanes.o tonga_thermal.o\
fiji_powertune.o fiji_hwmgr.o tonga_clockpowergating.o \
fiji_clockpowergating.o fiji_thermal.o \
polaris10_hwmgr.o polaris10_powertune.o polaris10_thermal.o \
polaris10_clockpowergating.o
polaris10_clockpowergating.o iceland_hwmgr.o \
iceland_clockpowergating.o iceland_thermal.o \
iceland_powertune.o
AMD_PP_HWMGR = $(addprefix $(AMD_PP_PATH)/hwmgr/,$(HARDWARE_MGR))
......
......@@ -618,9 +618,6 @@ static int fiji_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_TablelessHardwareInterface);
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_SclkDeepSleep);
data->gpio_debug = 0;
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
......
......@@ -56,8 +56,6 @@ void fiji_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr)
fiji_hwmgr->power_tune_defaults = &fiji_power_tune_data_set_array[0];
/* Assume disabled */
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_PowerContainment);
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_CAC);
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
......@@ -77,9 +75,8 @@ void fiji_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr)
fiji_hwmgr->fast_watermark_threshold = 100;
if (hwmgr->powercontainment_enabled) {
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_PowerContainment);
if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_PowerContainment)) {
tmp = 1;
fiji_hwmgr->enable_dte_feature = tmp ? false : true;
fiji_hwmgr->enable_tdc_limit_feature = tmp ? true : false;
......
/*
* Copyright 2016 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.
*
* Author: Huang Rui <ray.huang@amd.com>
*
*/
#ifndef _ICELAND_CLOCK_POWER_GATING_H_
#define _ICELAND_CLOCK_POWER_GATING_H_
#include "iceland_hwmgr.h"
#include "pp_asicblocks.h"
extern int iceland_phm_set_asic_block_gating(struct pp_hwmgr *hwmgr, enum PHM_AsicBlock block, enum PHM_ClockGateSetting gating);
extern int iceland_phm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate);
extern int iceland_phm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate);
extern int iceland_phm_powerdown_uvd(struct pp_hwmgr *hwmgr);
extern int iceland_phm_disable_clock_power_gating(struct pp_hwmgr *hwmgr);
extern int iceland_phm_update_clock_gatings(struct pp_hwmgr *hwmgr, const uint32_t *msg_id);
#endif /* _ICELAND_CLOCK_POWER_GATING_H_ */
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -132,8 +132,10 @@ struct amd_pp_init {
uint32_t chip_family;
uint32_t chip_id;
uint32_t rev_id;
bool powercontainment_enabled;
uint16_t sub_sys_id;
uint16_t sub_vendor_id;
};
enum amd_pp_display_config_type{
AMD_PP_DisplayConfigType_None = 0,
AMD_PP_DisplayConfigType_DP54 ,
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册