mirror of https://gitee.com/openkylin/linux.git
Merge branch 'drm-next-4.2' of git://people.freedesktop.org/~agd5f/linux into drm-next
for amdgpu separately next week. Highlights for radeon: - VCE1 support - Bug fixes and misc cleanups * 'drm-next-4.2' of git://people.freedesktop.org/~agd5f/linux: radeon: Deinline indirect register accessor functions drm/radeon: Fix max_vblank_count value for current display engines drm/radeon: stop using addr to check for BO move drm/radeon: clean up radeon_audio_enable drm/radeon: take the mode_config mutex when dealing with hpds (v2) drm/radeon: make dpcd parameters const drm/radeon: Use DECLARE_BITMAP drm/radeon/tn/si: enable/disable vce cg when encoding v2 drm/radeon: add support for vce 1.0 clock gating drm/radeon: add VCE 1.0 support v4 drm/radeon/dpm: add vce support for SI drm/radeon/dpm: add vce dpm support for TN drm/radeon: implement tn_set_vce_clocks drm/radeon: implement si_set_vce_clocks v2 drm/radeon: allow some more VCE firmware versions drm/radeon: rework VCE FW size calculation drm/radeon: add a GPU reset counter queryable by userspace
This commit is contained in:
commit
a8a7cf0264
|
@ -253,7 +253,7 @@ void radeon_dp_aux_init(struct radeon_connector *radeon_connector)
|
|||
#define DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_LEVEL_3
|
||||
#define DP_PRE_EMPHASIS_MAX DP_TRAIN_PRE_EMPH_LEVEL_3
|
||||
|
||||
static void dp_get_adjust_train(u8 link_status[DP_LINK_STATUS_SIZE],
|
||||
static void dp_get_adjust_train(const u8 link_status[DP_LINK_STATUS_SIZE],
|
||||
int lane_count,
|
||||
u8 train_set[4])
|
||||
{
|
||||
|
@ -311,7 +311,7 @@ static int dp_get_max_dp_pix_clock(int link_rate,
|
|||
/***** radeon specific DP functions *****/
|
||||
|
||||
int radeon_dp_get_max_link_rate(struct drm_connector *connector,
|
||||
u8 dpcd[DP_DPCD_SIZE])
|
||||
const u8 dpcd[DP_DPCD_SIZE])
|
||||
{
|
||||
int max_link_rate;
|
||||
|
||||
|
@ -328,7 +328,7 @@ int radeon_dp_get_max_link_rate(struct drm_connector *connector,
|
|||
* if the max lane# < low rate lane# then use max lane# instead.
|
||||
*/
|
||||
static int radeon_dp_get_dp_lane_number(struct drm_connector *connector,
|
||||
u8 dpcd[DP_DPCD_SIZE],
|
||||
const u8 dpcd[DP_DPCD_SIZE],
|
||||
int pix_clock)
|
||||
{
|
||||
int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector));
|
||||
|
@ -347,7 +347,7 @@ static int radeon_dp_get_dp_lane_number(struct drm_connector *connector,
|
|||
}
|
||||
|
||||
static int radeon_dp_get_dp_link_clock(struct drm_connector *connector,
|
||||
u8 dpcd[DP_DPCD_SIZE],
|
||||
const u8 dpcd[DP_DPCD_SIZE],
|
||||
int pix_clock)
|
||||
{
|
||||
int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector));
|
||||
|
|
|
@ -174,6 +174,31 @@ int cik_get_allowed_info_register(struct radeon_device *rdev,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Indirect registers accessor
|
||||
*/
|
||||
u32 cik_didt_rreg(struct radeon_device *rdev, u32 reg)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 r;
|
||||
|
||||
spin_lock_irqsave(&rdev->didt_idx_lock, flags);
|
||||
WREG32(CIK_DIDT_IND_INDEX, (reg));
|
||||
r = RREG32(CIK_DIDT_IND_DATA);
|
||||
spin_unlock_irqrestore(&rdev->didt_idx_lock, flags);
|
||||
return r;
|
||||
}
|
||||
|
||||
void cik_didt_wreg(struct radeon_device *rdev, u32 reg, u32 v)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&rdev->didt_idx_lock, flags);
|
||||
WREG32(CIK_DIDT_IND_INDEX, (reg));
|
||||
WREG32(CIK_DIDT_IND_DATA, (v));
|
||||
spin_unlock_irqrestore(&rdev->didt_idx_lock, flags);
|
||||
}
|
||||
|
||||
/* get temperature in millidegrees */
|
||||
int ci_get_temp(struct radeon_device *rdev)
|
||||
{
|
||||
|
|
|
@ -35,6 +35,75 @@
|
|||
#include "evergreen_blit_shaders.h"
|
||||
#include "radeon_ucode.h"
|
||||
|
||||
/*
|
||||
* Indirect registers accessor
|
||||
*/
|
||||
u32 eg_cg_rreg(struct radeon_device *rdev, u32 reg)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 r;
|
||||
|
||||
spin_lock_irqsave(&rdev->cg_idx_lock, flags);
|
||||
WREG32(EVERGREEN_CG_IND_ADDR, ((reg) & 0xffff));
|
||||
r = RREG32(EVERGREEN_CG_IND_DATA);
|
||||
spin_unlock_irqrestore(&rdev->cg_idx_lock, flags);
|
||||
return r;
|
||||
}
|
||||
|
||||
void eg_cg_wreg(struct radeon_device *rdev, u32 reg, u32 v)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&rdev->cg_idx_lock, flags);
|
||||
WREG32(EVERGREEN_CG_IND_ADDR, ((reg) & 0xffff));
|
||||
WREG32(EVERGREEN_CG_IND_DATA, (v));
|
||||
spin_unlock_irqrestore(&rdev->cg_idx_lock, flags);
|
||||
}
|
||||
|
||||
u32 eg_pif_phy0_rreg(struct radeon_device *rdev, u32 reg)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 r;
|
||||
|
||||
spin_lock_irqsave(&rdev->pif_idx_lock, flags);
|
||||
WREG32(EVERGREEN_PIF_PHY0_INDEX, ((reg) & 0xffff));
|
||||
r = RREG32(EVERGREEN_PIF_PHY0_DATA);
|
||||
spin_unlock_irqrestore(&rdev->pif_idx_lock, flags);
|
||||
return r;
|
||||
}
|
||||
|
||||
void eg_pif_phy0_wreg(struct radeon_device *rdev, u32 reg, u32 v)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&rdev->pif_idx_lock, flags);
|
||||
WREG32(EVERGREEN_PIF_PHY0_INDEX, ((reg) & 0xffff));
|
||||
WREG32(EVERGREEN_PIF_PHY0_DATA, (v));
|
||||
spin_unlock_irqrestore(&rdev->pif_idx_lock, flags);
|
||||
}
|
||||
|
||||
u32 eg_pif_phy1_rreg(struct radeon_device *rdev, u32 reg)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 r;
|
||||
|
||||
spin_lock_irqsave(&rdev->pif_idx_lock, flags);
|
||||
WREG32(EVERGREEN_PIF_PHY1_INDEX, ((reg) & 0xffff));
|
||||
r = RREG32(EVERGREEN_PIF_PHY1_DATA);
|
||||
spin_unlock_irqrestore(&rdev->pif_idx_lock, flags);
|
||||
return r;
|
||||
}
|
||||
|
||||
void eg_pif_phy1_wreg(struct radeon_device *rdev, u32 reg, u32 v)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&rdev->pif_idx_lock, flags);
|
||||
WREG32(EVERGREEN_PIF_PHY1_INDEX, ((reg) & 0xffff));
|
||||
WREG32(EVERGREEN_PIF_PHY1_DATA, (v));
|
||||
spin_unlock_irqrestore(&rdev->pif_idx_lock, flags);
|
||||
}
|
||||
|
||||
static const u32 crtc_offsets[6] =
|
||||
{
|
||||
EVERGREEN_CRTC0_REGISTER_OFFSET,
|
||||
|
|
|
@ -36,6 +36,31 @@
|
|||
#include "radeon_ucode.h"
|
||||
#include "clearstate_cayman.h"
|
||||
|
||||
/*
|
||||
* Indirect registers accessor
|
||||
*/
|
||||
u32 tn_smc_rreg(struct radeon_device *rdev, u32 reg)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 r;
|
||||
|
||||
spin_lock_irqsave(&rdev->smc_idx_lock, flags);
|
||||
WREG32(TN_SMC_IND_INDEX_0, (reg));
|
||||
r = RREG32(TN_SMC_IND_DATA_0);
|
||||
spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
|
||||
return r;
|
||||
}
|
||||
|
||||
void tn_smc_wreg(struct radeon_device *rdev, u32 reg, u32 v)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&rdev->smc_idx_lock, flags);
|
||||
WREG32(TN_SMC_IND_INDEX_0, (reg));
|
||||
WREG32(TN_SMC_IND_DATA_0, (v));
|
||||
spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
|
||||
}
|
||||
|
||||
static const u32 tn_rlc_save_restore_register_list[] =
|
||||
{
|
||||
0x98fc,
|
||||
|
@ -2041,6 +2066,25 @@ static int cayman_startup(struct radeon_device *rdev)
|
|||
if (r)
|
||||
rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
|
||||
|
||||
if (rdev->family == CHIP_ARUBA) {
|
||||
r = radeon_vce_resume(rdev);
|
||||
if (!r)
|
||||
r = vce_v1_0_resume(rdev);
|
||||
|
||||
if (!r)
|
||||
r = radeon_fence_driver_start_ring(rdev,
|
||||
TN_RING_TYPE_VCE1_INDEX);
|
||||
if (!r)
|
||||
r = radeon_fence_driver_start_ring(rdev,
|
||||
TN_RING_TYPE_VCE2_INDEX);
|
||||
|
||||
if (r) {
|
||||
dev_err(rdev->dev, "VCE init error (%d).\n", r);
|
||||
rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size = 0;
|
||||
rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_CP1_INDEX);
|
||||
if (r) {
|
||||
dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);
|
||||
|
@ -2118,6 +2162,19 @@ static int cayman_startup(struct radeon_device *rdev)
|
|||
DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
|
||||
}
|
||||
|
||||
ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
|
||||
if (ring->ring_size)
|
||||
r = radeon_ring_init(rdev, ring, ring->ring_size, 0, 0x0);
|
||||
|
||||
ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
|
||||
if (ring->ring_size)
|
||||
r = radeon_ring_init(rdev, ring, ring->ring_size, 0, 0x0);
|
||||
|
||||
if (!r)
|
||||
r = vce_v1_0_init(rdev);
|
||||
else if (r != -ENOENT)
|
||||
DRM_ERROR("radeon: failed initializing VCE (%d).\n", r);
|
||||
|
||||
r = radeon_ib_pool_init(rdev);
|
||||
if (r) {
|
||||
dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
|
||||
|
@ -2273,6 +2330,19 @@ int cayman_init(struct radeon_device *rdev)
|
|||
r600_ring_init(rdev, ring, 4096);
|
||||
}
|
||||
|
||||
if (rdev->family == CHIP_ARUBA) {
|
||||
r = radeon_vce_init(rdev);
|
||||
if (!r) {
|
||||
ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
|
||||
ring->ring_obj = NULL;
|
||||
r600_ring_init(rdev, ring, 4096);
|
||||
|
||||
ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
|
||||
ring->ring_obj = NULL;
|
||||
r600_ring_init(rdev, ring, 4096);
|
||||
}
|
||||
}
|
||||
|
||||
rdev->ih.ring_obj = NULL;
|
||||
r600_ih_ring_init(rdev, 64 * 1024);
|
||||
|
||||
|
@ -2326,6 +2396,7 @@ void cayman_fini(struct radeon_device *rdev)
|
|||
radeon_irq_kms_fini(rdev);
|
||||
uvd_v1_0_fini(rdev);
|
||||
radeon_uvd_fini(rdev);
|
||||
radeon_vce_fini(rdev);
|
||||
cayman_pcie_gart_fini(rdev);
|
||||
r600_vram_scratch_fini(rdev);
|
||||
radeon_gem_fini(rdev);
|
||||
|
@ -2554,3 +2625,34 @@ void cayman_vm_flush(struct radeon_device *rdev, struct radeon_ring *ring,
|
|||
radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0));
|
||||
radeon_ring_write(ring, 0x0);
|
||||
}
|
||||
|
||||
int tn_set_vce_clocks(struct radeon_device *rdev, u32 evclk, u32 ecclk)
|
||||
{
|
||||
struct atom_clock_dividers dividers;
|
||||
int r, i;
|
||||
|
||||
r = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
|
||||
ecclk, false, ÷rs);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
for (i = 0; i < 100; i++) {
|
||||
if (RREG32(CG_ECLK_STATUS) & ECLK_STATUS)
|
||||
break;
|
||||
mdelay(10);
|
||||
}
|
||||
if (i == 100)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
WREG32_P(CG_ECLK_CNTL, dividers.post_div, ~(ECLK_DIR_CNTL_EN|ECLK_DIVIDER_MASK));
|
||||
|
||||
for (i = 0; i < 100; i++) {
|
||||
if (RREG32(CG_ECLK_STATUS) & ECLK_STATUS)
|
||||
break;
|
||||
mdelay(10);
|
||||
}
|
||||
if (i == 100)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -46,6 +46,13 @@
|
|||
|
||||
#define DMIF_ADDR_CONFIG 0xBD4
|
||||
|
||||
/* fusion vce clocks */
|
||||
#define CG_ECLK_CNTL 0x620
|
||||
# define ECLK_DIVIDER_MASK 0x7f
|
||||
# define ECLK_DIR_CNTL_EN (1 << 8)
|
||||
#define CG_ECLK_STATUS 0x624
|
||||
# define ECLK_STATUS (1 << 0)
|
||||
|
||||
/* DCE6 only */
|
||||
#define DMIF_ADDR_CALC 0xC00
|
||||
|
||||
|
|
|
@ -4090,6 +4090,28 @@ int r100_init(struct radeon_device *rdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint32_t r100_mm_rreg_slow(struct radeon_device *rdev, uint32_t reg)
|
||||
{
|
||||
unsigned long flags;
|
||||
uint32_t ret;
|
||||
|
||||
spin_lock_irqsave(&rdev->mmio_idx_lock, flags);
|
||||
writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
|
||||
ret = readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
|
||||
spin_unlock_irqrestore(&rdev->mmio_idx_lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void r100_mm_wreg_slow(struct radeon_device *rdev, uint32_t reg, uint32_t v)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&rdev->mmio_idx_lock, flags);
|
||||
writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
|
||||
writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
|
||||
spin_unlock_irqrestore(&rdev->mmio_idx_lock, flags);
|
||||
}
|
||||
|
||||
u32 r100_io_rreg(struct radeon_device *rdev, u32 reg)
|
||||
{
|
||||
if (reg < rdev->rio_mem_size)
|
||||
|
|
|
@ -49,6 +49,31 @@
|
|||
* tell. (Jerome Glisse)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Indirect registers accessor
|
||||
*/
|
||||
uint32_t rv370_pcie_rreg(struct radeon_device *rdev, uint32_t reg)
|
||||
{
|
||||
unsigned long flags;
|
||||
uint32_t r;
|
||||
|
||||
spin_lock_irqsave(&rdev->pcie_idx_lock, flags);
|
||||
WREG32(RADEON_PCIE_INDEX, ((reg) & rdev->pcie_reg_mask));
|
||||
r = RREG32(RADEON_PCIE_DATA);
|
||||
spin_unlock_irqrestore(&rdev->pcie_idx_lock, flags);
|
||||
return r;
|
||||
}
|
||||
|
||||
void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&rdev->pcie_idx_lock, flags);
|
||||
WREG32(RADEON_PCIE_INDEX, ((reg) & rdev->pcie_reg_mask));
|
||||
WREG32(RADEON_PCIE_DATA, (v));
|
||||
spin_unlock_irqrestore(&rdev->pcie_idx_lock, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* rv370,rv380 PCIE GART
|
||||
*/
|
||||
|
|
|
@ -108,6 +108,53 @@ static void r600_pcie_gen2_enable(struct radeon_device *rdev);
|
|||
extern int evergreen_rlc_resume(struct radeon_device *rdev);
|
||||
extern void rv770_set_clk_bypass_mode(struct radeon_device *rdev);
|
||||
|
||||
/*
|
||||
* Indirect registers accessor
|
||||
*/
|
||||
u32 r600_rcu_rreg(struct radeon_device *rdev, u32 reg)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 r;
|
||||
|
||||
spin_lock_irqsave(&rdev->rcu_idx_lock, flags);
|
||||
WREG32(R600_RCU_INDEX, ((reg) & 0x1fff));
|
||||
r = RREG32(R600_RCU_DATA);
|
||||
spin_unlock_irqrestore(&rdev->rcu_idx_lock, flags);
|
||||
return r;
|
||||
}
|
||||
|
||||
void r600_rcu_wreg(struct radeon_device *rdev, u32 reg, u32 v)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&rdev->rcu_idx_lock, flags);
|
||||
WREG32(R600_RCU_INDEX, ((reg) & 0x1fff));
|
||||
WREG32(R600_RCU_DATA, (v));
|
||||
spin_unlock_irqrestore(&rdev->rcu_idx_lock, flags);
|
||||
}
|
||||
|
||||
u32 r600_uvd_ctx_rreg(struct radeon_device *rdev, u32 reg)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 r;
|
||||
|
||||
spin_lock_irqsave(&rdev->uvd_idx_lock, flags);
|
||||
WREG32(R600_UVD_CTX_INDEX, ((reg) & 0x1ff));
|
||||
r = RREG32(R600_UVD_CTX_DATA);
|
||||
spin_unlock_irqrestore(&rdev->uvd_idx_lock, flags);
|
||||
return r;
|
||||
}
|
||||
|
||||
void r600_uvd_ctx_wreg(struct radeon_device *rdev, u32 reg, u32 v)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&rdev->uvd_idx_lock, flags);
|
||||
WREG32(R600_UVD_CTX_INDEX, ((reg) & 0x1ff));
|
||||
WREG32(R600_UVD_CTX_DATA, (v));
|
||||
spin_unlock_irqrestore(&rdev->uvd_idx_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* r600_get_allowed_info_register - fetch the register for the info ioctl
|
||||
*
|
||||
|
|
|
@ -467,7 +467,6 @@ struct radeon_bo_va {
|
|||
/* protected by bo being reserved */
|
||||
struct list_head bo_list;
|
||||
uint32_t flags;
|
||||
uint64_t addr;
|
||||
struct radeon_fence *last_pt_update;
|
||||
unsigned ref_count;
|
||||
|
||||
|
@ -719,7 +718,7 @@ struct radeon_doorbell {
|
|||
resource_size_t size;
|
||||
u32 __iomem *ptr;
|
||||
u32 num_doorbells; /* Number of doorbells actually reserved for radeon. */
|
||||
unsigned long used[DIV_ROUND_UP(RADEON_MAX_DOORBELLS, BITS_PER_LONG)];
|
||||
DECLARE_BITMAP(used, RADEON_MAX_DOORBELLS);
|
||||
};
|
||||
|
||||
int radeon_doorbell_get(struct radeon_device *rdev, u32 *page);
|
||||
|
@ -941,6 +940,9 @@ struct radeon_vm {
|
|||
/* BOs freed, but not yet updated in the PT */
|
||||
struct list_head freed;
|
||||
|
||||
/* BOs cleared in the PT */
|
||||
struct list_head cleared;
|
||||
|
||||
/* contains the page directory */
|
||||
struct radeon_bo *page_directory;
|
||||
unsigned max_pde_used;
|
||||
|
@ -1709,8 +1711,6 @@ int radeon_uvd_send_upll_ctlreq(struct radeon_device *rdev,
|
|||
* VCE
|
||||
*/
|
||||
#define RADEON_MAX_VCE_HANDLES 16
|
||||
#define RADEON_VCE_STACK_SIZE (1024*1024)
|
||||
#define RADEON_VCE_HEAP_SIZE (4*1024*1024)
|
||||
|
||||
struct radeon_vce {
|
||||
struct radeon_bo *vcpu_bo;
|
||||
|
@ -1721,6 +1721,7 @@ struct radeon_vce {
|
|||
struct drm_file *filp[RADEON_MAX_VCE_HANDLES];
|
||||
unsigned img_size[RADEON_MAX_VCE_HANDLES];
|
||||
struct delayed_work idle_work;
|
||||
uint32_t keyselect;
|
||||
};
|
||||
|
||||
int radeon_vce_init(struct radeon_device *rdev);
|
||||
|
@ -2435,6 +2436,7 @@ struct radeon_device {
|
|||
atomic64_t vram_usage;
|
||||
atomic64_t gtt_usage;
|
||||
atomic64_t num_bytes_moved;
|
||||
atomic_t gpu_reset_counter;
|
||||
/* ACPI interface */
|
||||
struct radeon_atif atif;
|
||||
struct radeon_atcs atcs;
|
||||
|
@ -2472,38 +2474,24 @@ int radeon_gpu_wait_for_idle(struct radeon_device *rdev);
|
|||
|
||||
#define RADEON_MIN_MMIO_SIZE 0x10000
|
||||
|
||||
uint32_t r100_mm_rreg_slow(struct radeon_device *rdev, uint32_t reg);
|
||||
void r100_mm_wreg_slow(struct radeon_device *rdev, uint32_t reg, uint32_t v);
|
||||
static inline uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg,
|
||||
bool always_indirect)
|
||||
{
|
||||
/* The mmio size is 64kb at minimum. Allows the if to be optimized out. */
|
||||
if ((reg < rdev->rmmio_size || reg < RADEON_MIN_MMIO_SIZE) && !always_indirect)
|
||||
return readl(((void __iomem *)rdev->rmmio) + reg);
|
||||
else {
|
||||
unsigned long flags;
|
||||
uint32_t ret;
|
||||
|
||||
spin_lock_irqsave(&rdev->mmio_idx_lock, flags);
|
||||
writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
|
||||
ret = readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
|
||||
spin_unlock_irqrestore(&rdev->mmio_idx_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
return r100_mm_rreg_slow(rdev, reg);
|
||||
}
|
||||
|
||||
static inline void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v,
|
||||
bool always_indirect)
|
||||
{
|
||||
if ((reg < rdev->rmmio_size || reg < RADEON_MIN_MMIO_SIZE) && !always_indirect)
|
||||
writel(v, ((void __iomem *)rdev->rmmio) + reg);
|
||||
else {
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&rdev->mmio_idx_lock, flags);
|
||||
writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
|
||||
writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
|
||||
spin_unlock_irqrestore(&rdev->mmio_idx_lock, flags);
|
||||
}
|
||||
else
|
||||
r100_mm_wreg_slow(rdev, reg, v);
|
||||
}
|
||||
|
||||
u32 r100_io_rreg(struct radeon_device *rdev, u32 reg);
|
||||
|
@ -2579,6 +2567,13 @@ static inline struct radeon_fence *to_radeon_fence(struct fence *f)
|
|||
tmp_ |= ((val) & ~(mask)); \
|
||||
WREG32_PLL(reg, tmp_); \
|
||||
} while (0)
|
||||
#define WREG32_SMC_P(reg, val, mask) \
|
||||
do { \
|
||||
uint32_t tmp_ = RREG32_SMC(reg); \
|
||||
tmp_ &= (mask); \
|
||||
tmp_ |= ((val) & ~(mask)); \
|
||||
WREG32_SMC(reg, tmp_); \
|
||||
} while (0)
|
||||
#define DREG32_SYS(sqf, rdev, reg) seq_printf((sqf), #reg " : 0x%08X\n", r100_mm_rreg((rdev), (reg), false))
|
||||
#define RREG32_IO(reg) r100_io_rreg(rdev, (reg))
|
||||
#define WREG32_IO(reg, v) r100_io_wreg(rdev, (reg), (v))
|
||||
|
@ -2587,184 +2582,29 @@ static inline struct radeon_fence *to_radeon_fence(struct fence *f)
|
|||
#define WDOORBELL32(index, v) cik_mm_wdoorbell(rdev, (index), (v))
|
||||
|
||||
/*
|
||||
* Indirect registers accessor
|
||||
* Indirect registers accessors.
|
||||
* They used to be inlined, but this increases code size by ~65 kbytes.
|
||||
* Since each performs a pair of MMIO ops
|
||||
* within a spin_lock_irqsave/spin_unlock_irqrestore region,
|
||||
* the cost of call+ret is almost negligible. MMIO and locking
|
||||
* costs several dozens of cycles each at best, call+ret is ~5 cycles.
|
||||
*/
|
||||
static inline uint32_t rv370_pcie_rreg(struct radeon_device *rdev, uint32_t reg)
|
||||
{
|
||||
unsigned long flags;
|
||||
uint32_t r;
|
||||
|
||||
spin_lock_irqsave(&rdev->pcie_idx_lock, flags);
|
||||
WREG32(RADEON_PCIE_INDEX, ((reg) & rdev->pcie_reg_mask));
|
||||
r = RREG32(RADEON_PCIE_DATA);
|
||||
spin_unlock_irqrestore(&rdev->pcie_idx_lock, flags);
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&rdev->pcie_idx_lock, flags);
|
||||
WREG32(RADEON_PCIE_INDEX, ((reg) & rdev->pcie_reg_mask));
|
||||
WREG32(RADEON_PCIE_DATA, (v));
|
||||
spin_unlock_irqrestore(&rdev->pcie_idx_lock, flags);
|
||||
}
|
||||
|
||||
static inline u32 tn_smc_rreg(struct radeon_device *rdev, u32 reg)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 r;
|
||||
|
||||
spin_lock_irqsave(&rdev->smc_idx_lock, flags);
|
||||
WREG32(TN_SMC_IND_INDEX_0, (reg));
|
||||
r = RREG32(TN_SMC_IND_DATA_0);
|
||||
spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void tn_smc_wreg(struct radeon_device *rdev, u32 reg, u32 v)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&rdev->smc_idx_lock, flags);
|
||||
WREG32(TN_SMC_IND_INDEX_0, (reg));
|
||||
WREG32(TN_SMC_IND_DATA_0, (v));
|
||||
spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
|
||||
}
|
||||
|
||||
static inline u32 r600_rcu_rreg(struct radeon_device *rdev, u32 reg)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 r;
|
||||
|
||||
spin_lock_irqsave(&rdev->rcu_idx_lock, flags);
|
||||
WREG32(R600_RCU_INDEX, ((reg) & 0x1fff));
|
||||
r = RREG32(R600_RCU_DATA);
|
||||
spin_unlock_irqrestore(&rdev->rcu_idx_lock, flags);
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void r600_rcu_wreg(struct radeon_device *rdev, u32 reg, u32 v)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&rdev->rcu_idx_lock, flags);
|
||||
WREG32(R600_RCU_INDEX, ((reg) & 0x1fff));
|
||||
WREG32(R600_RCU_DATA, (v));
|
||||
spin_unlock_irqrestore(&rdev->rcu_idx_lock, flags);
|
||||
}
|
||||
|
||||
static inline u32 eg_cg_rreg(struct radeon_device *rdev, u32 reg)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 r;
|
||||
|
||||
spin_lock_irqsave(&rdev->cg_idx_lock, flags);
|
||||
WREG32(EVERGREEN_CG_IND_ADDR, ((reg) & 0xffff));
|
||||
r = RREG32(EVERGREEN_CG_IND_DATA);
|
||||
spin_unlock_irqrestore(&rdev->cg_idx_lock, flags);
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void eg_cg_wreg(struct radeon_device *rdev, u32 reg, u32 v)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&rdev->cg_idx_lock, flags);
|
||||
WREG32(EVERGREEN_CG_IND_ADDR, ((reg) & 0xffff));
|
||||
WREG32(EVERGREEN_CG_IND_DATA, (v));
|
||||
spin_unlock_irqrestore(&rdev->cg_idx_lock, flags);
|
||||
}
|
||||
|
||||
static inline u32 eg_pif_phy0_rreg(struct radeon_device *rdev, u32 reg)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 r;
|
||||
|
||||
spin_lock_irqsave(&rdev->pif_idx_lock, flags);
|
||||
WREG32(EVERGREEN_PIF_PHY0_INDEX, ((reg) & 0xffff));
|
||||
r = RREG32(EVERGREEN_PIF_PHY0_DATA);
|
||||
spin_unlock_irqrestore(&rdev->pif_idx_lock, flags);
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void eg_pif_phy0_wreg(struct radeon_device *rdev, u32 reg, u32 v)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&rdev->pif_idx_lock, flags);
|
||||
WREG32(EVERGREEN_PIF_PHY0_INDEX, ((reg) & 0xffff));
|
||||
WREG32(EVERGREEN_PIF_PHY0_DATA, (v));
|
||||
spin_unlock_irqrestore(&rdev->pif_idx_lock, flags);
|
||||
}
|
||||
|
||||
static inline u32 eg_pif_phy1_rreg(struct radeon_device *rdev, u32 reg)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 r;
|
||||
|
||||
spin_lock_irqsave(&rdev->pif_idx_lock, flags);
|
||||
WREG32(EVERGREEN_PIF_PHY1_INDEX, ((reg) & 0xffff));
|
||||
r = RREG32(EVERGREEN_PIF_PHY1_DATA);
|
||||
spin_unlock_irqrestore(&rdev->pif_idx_lock, flags);
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void eg_pif_phy1_wreg(struct radeon_device *rdev, u32 reg, u32 v)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&rdev->pif_idx_lock, flags);
|
||||
WREG32(EVERGREEN_PIF_PHY1_INDEX, ((reg) & 0xffff));
|
||||
WREG32(EVERGREEN_PIF_PHY1_DATA, (v));
|
||||
spin_unlock_irqrestore(&rdev->pif_idx_lock, flags);
|
||||
}
|
||||
|
||||
static inline u32 r600_uvd_ctx_rreg(struct radeon_device *rdev, u32 reg)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 r;
|
||||
|
||||
spin_lock_irqsave(&rdev->uvd_idx_lock, flags);
|
||||
WREG32(R600_UVD_CTX_INDEX, ((reg) & 0x1ff));
|
||||
r = RREG32(R600_UVD_CTX_DATA);
|
||||
spin_unlock_irqrestore(&rdev->uvd_idx_lock, flags);
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void r600_uvd_ctx_wreg(struct radeon_device *rdev, u32 reg, u32 v)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&rdev->uvd_idx_lock, flags);
|
||||
WREG32(R600_UVD_CTX_INDEX, ((reg) & 0x1ff));
|
||||
WREG32(R600_UVD_CTX_DATA, (v));
|
||||
spin_unlock_irqrestore(&rdev->uvd_idx_lock, flags);
|
||||
}
|
||||
|
||||
|
||||
static inline u32 cik_didt_rreg(struct radeon_device *rdev, u32 reg)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 r;
|
||||
|
||||
spin_lock_irqsave(&rdev->didt_idx_lock, flags);
|
||||
WREG32(CIK_DIDT_IND_INDEX, (reg));
|
||||
r = RREG32(CIK_DIDT_IND_DATA);
|
||||
spin_unlock_irqrestore(&rdev->didt_idx_lock, flags);
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void cik_didt_wreg(struct radeon_device *rdev, u32 reg, u32 v)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&rdev->didt_idx_lock, flags);
|
||||
WREG32(CIK_DIDT_IND_INDEX, (reg));
|
||||
WREG32(CIK_DIDT_IND_DATA, (v));
|
||||
spin_unlock_irqrestore(&rdev->didt_idx_lock, flags);
|
||||
}
|
||||
uint32_t rv370_pcie_rreg(struct radeon_device *rdev, uint32_t reg);
|
||||
void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
|
||||
u32 tn_smc_rreg(struct radeon_device *rdev, u32 reg);
|
||||
void tn_smc_wreg(struct radeon_device *rdev, u32 reg, u32 v);
|
||||
u32 r600_rcu_rreg(struct radeon_device *rdev, u32 reg);
|
||||
void r600_rcu_wreg(struct radeon_device *rdev, u32 reg, u32 v);
|
||||
u32 eg_cg_rreg(struct radeon_device *rdev, u32 reg);
|
||||
void eg_cg_wreg(struct radeon_device *rdev, u32 reg, u32 v);
|
||||
u32 eg_pif_phy0_rreg(struct radeon_device *rdev, u32 reg);
|
||||
void eg_pif_phy0_wreg(struct radeon_device *rdev, u32 reg, u32 v);
|
||||
u32 eg_pif_phy1_rreg(struct radeon_device *rdev, u32 reg);
|
||||
void eg_pif_phy1_wreg(struct radeon_device *rdev, u32 reg, u32 v);
|
||||
u32 r600_uvd_ctx_rreg(struct radeon_device *rdev, u32 reg);
|
||||
void r600_uvd_ctx_wreg(struct radeon_device *rdev, u32 reg, u32 v);
|
||||
u32 cik_didt_rreg(struct radeon_device *rdev, u32 reg);
|
||||
void cik_didt_wreg(struct radeon_device *rdev, u32 reg, u32 v);
|
||||
|
||||
void r100_pll_errata_after_index(struct radeon_device *rdev);
|
||||
|
||||
|
|
|
@ -1761,6 +1761,19 @@ static struct radeon_asic cayman_asic = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct radeon_asic_ring trinity_vce_ring = {
|
||||
.ib_execute = &radeon_vce_ib_execute,
|
||||
.emit_fence = &radeon_vce_fence_emit,
|
||||
.emit_semaphore = &radeon_vce_semaphore_emit,
|
||||
.cs_parse = &radeon_vce_cs_parse,
|
||||
.ring_test = &radeon_vce_ring_test,
|
||||
.ib_test = &radeon_vce_ib_test,
|
||||
.is_lockup = &radeon_ring_test_lockup,
|
||||
.get_rptr = &vce_v1_0_get_rptr,
|
||||
.get_wptr = &vce_v1_0_get_wptr,
|
||||
.set_wptr = &vce_v1_0_set_wptr,
|
||||
};
|
||||
|
||||
static struct radeon_asic trinity_asic = {
|
||||
.init = &cayman_init,
|
||||
.fini = &cayman_fini,
|
||||
|
@ -1794,6 +1807,8 @@ static struct radeon_asic trinity_asic = {
|
|||
[R600_RING_TYPE_DMA_INDEX] = &cayman_dma_ring,
|
||||
[CAYMAN_RING_TYPE_DMA1_INDEX] = &cayman_dma_ring,
|
||||
[R600_RING_TYPE_UVD_INDEX] = &cayman_uvd_ring,
|
||||
[TN_RING_TYPE_VCE1_INDEX] = &trinity_vce_ring,
|
||||
[TN_RING_TYPE_VCE2_INDEX] = &trinity_vce_ring,
|
||||
},
|
||||
.irq = {
|
||||
.set = &evergreen_irq_set,
|
||||
|
@ -1838,6 +1853,7 @@ static struct radeon_asic trinity_asic = {
|
|||
.set_pcie_lanes = NULL,
|
||||
.set_clock_gating = NULL,
|
||||
.set_uvd_clocks = &sumo_set_uvd_clocks,
|
||||
.set_vce_clocks = &tn_set_vce_clocks,
|
||||
.get_temperature = &tn_get_temp,
|
||||
},
|
||||
.dpm = {
|
||||
|
@ -1929,6 +1945,8 @@ static struct radeon_asic si_asic = {
|
|||
[R600_RING_TYPE_DMA_INDEX] = &si_dma_ring,
|
||||
[CAYMAN_RING_TYPE_DMA1_INDEX] = &si_dma_ring,
|
||||
[R600_RING_TYPE_UVD_INDEX] = &cayman_uvd_ring,
|
||||
[TN_RING_TYPE_VCE1_INDEX] = &trinity_vce_ring,
|
||||
[TN_RING_TYPE_VCE2_INDEX] = &trinity_vce_ring,
|
||||
},
|
||||
.irq = {
|
||||
.set = &si_irq_set,
|
||||
|
@ -1973,6 +1991,7 @@ static struct radeon_asic si_asic = {
|
|||
.set_pcie_lanes = &r600_set_pcie_lanes,
|
||||
.set_clock_gating = NULL,
|
||||
.set_uvd_clocks = &si_set_uvd_clocks,
|
||||
.set_vce_clocks = &si_set_vce_clocks,
|
||||
.get_temperature = &si_get_temp,
|
||||
},
|
||||
.dpm = {
|
||||
|
@ -2436,6 +2455,8 @@ int radeon_asic_init(struct radeon_device *rdev)
|
|||
/* set num crtcs */
|
||||
rdev->num_crtc = 4;
|
||||
rdev->has_uvd = true;
|
||||
rdev->cg_flags =
|
||||
RADEON_CG_SUPPORT_VCE_MGCG;
|
||||
break;
|
||||
case CHIP_TAHITI:
|
||||
case CHIP_PITCAIRN:
|
||||
|
|
|
@ -694,6 +694,7 @@ int trinity_dpm_force_performance_level(struct radeon_device *rdev,
|
|||
void trinity_dpm_enable_bapm(struct radeon_device *rdev, bool enable);
|
||||
u32 trinity_dpm_get_current_sclk(struct radeon_device *rdev);
|
||||
u32 trinity_dpm_get_current_mclk(struct radeon_device *rdev);
|
||||
int tn_set_vce_clocks(struct radeon_device *rdev, u32 evclk, u32 ecclk);
|
||||
|
||||
/* DCE6 - SI */
|
||||
void dce6_bandwidth_update(struct radeon_device *rdev);
|
||||
|
@ -745,6 +746,7 @@ void si_dma_vm_flush(struct radeon_device *rdev, struct radeon_ring *ring,
|
|||
u32 si_get_xclk(struct radeon_device *rdev);
|
||||
uint64_t si_get_gpu_clock_counter(struct radeon_device *rdev);
|
||||
int si_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
|
||||
int si_set_vce_clocks(struct radeon_device *rdev, u32 evclk, u32 ecclk);
|
||||
int si_get_temp(struct radeon_device *rdev);
|
||||
int si_get_allowed_info_register(struct radeon_device *rdev,
|
||||
u32 reg, u32 *val);
|
||||
|
@ -970,10 +972,14 @@ uint32_t vce_v1_0_get_wptr(struct radeon_device *rdev,
|
|||
struct radeon_ring *ring);
|
||||
void vce_v1_0_set_wptr(struct radeon_device *rdev,
|
||||
struct radeon_ring *ring);
|
||||
int vce_v1_0_load_fw(struct radeon_device *rdev, uint32_t *data);
|
||||
unsigned vce_v1_0_bo_size(struct radeon_device *rdev);
|
||||
int vce_v1_0_resume(struct radeon_device *rdev);
|
||||
int vce_v1_0_init(struct radeon_device *rdev);
|
||||
int vce_v1_0_start(struct radeon_device *rdev);
|
||||
|
||||
/* vce v2.0 */
|
||||
unsigned vce_v2_0_bo_size(struct radeon_device *rdev);
|
||||
int vce_v2_0_resume(struct radeon_device *rdev);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -242,6 +242,13 @@ static struct radeon_audio_funcs dce6_dp_funcs = {
|
|||
.dpms = evergreen_dp_enable,
|
||||
};
|
||||
|
||||
static void radeon_audio_enable(struct radeon_device *rdev,
|
||||
struct r600_audio_pin *pin, u8 enable_mask)
|
||||
{
|
||||
if (rdev->audio.funcs->enable)
|
||||
rdev->audio.funcs->enable(rdev, pin, enable_mask);
|
||||
}
|
||||
|
||||
static void radeon_audio_interface_init(struct radeon_device *rdev)
|
||||
{
|
||||
if (ASIC_IS_DCE6(rdev)) {
|
||||
|
@ -307,7 +314,7 @@ int radeon_audio_init(struct radeon_device *rdev)
|
|||
|
||||
/* disable audio. it will be set up later */
|
||||
for (i = 0; i < rdev->audio.num_pins; i++)
|
||||
radeon_audio_enable(rdev, &rdev->audio.pin[i], false);
|
||||
radeon_audio_enable(rdev, &rdev->audio.pin[i], 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -443,13 +450,6 @@ static void radeon_audio_select_pin(struct drm_encoder *encoder)
|
|||
radeon_encoder->audio->select_pin(encoder);
|
||||
}
|
||||
|
||||
void radeon_audio_enable(struct radeon_device *rdev,
|
||||
struct r600_audio_pin *pin, u8 enable_mask)
|
||||
{
|
||||
if (rdev->audio.funcs->enable)
|
||||
rdev->audio.funcs->enable(rdev, pin, enable_mask);
|
||||
}
|
||||
|
||||
void radeon_audio_detect(struct drm_connector *connector,
|
||||
enum drm_connector_status status)
|
||||
{
|
||||
|
@ -505,7 +505,7 @@ void radeon_audio_fini(struct radeon_device *rdev)
|
|||
return;
|
||||
|
||||
for (i = 0; i < rdev->audio.num_pins; i++)
|
||||
radeon_audio_enable(rdev, &rdev->audio.pin[i], false);
|
||||
radeon_audio_enable(rdev, &rdev->audio.pin[i], 0);
|
||||
|
||||
rdev->audio.enabled = false;
|
||||
}
|
||||
|
|
|
@ -74,8 +74,6 @@ u32 radeon_audio_endpoint_rreg(struct radeon_device *rdev,
|
|||
void radeon_audio_endpoint_wreg(struct radeon_device *rdev,
|
||||
u32 offset, u32 reg, u32 v);
|
||||
struct r600_audio_pin *radeon_audio_get_pin(struct drm_encoder *encoder);
|
||||
void radeon_audio_enable(struct radeon_device *rdev,
|
||||
struct r600_audio_pin *pin, u8 enable_mask);
|
||||
void radeon_audio_fini(struct radeon_device *rdev);
|
||||
void radeon_audio_mode_set(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode);
|
||||
|
|
|
@ -1725,6 +1725,8 @@ int radeon_gpu_reset(struct radeon_device *rdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
atomic_inc(&rdev->gpu_reset_counter);
|
||||
|
||||
radeon_save_bios_scratch_regs(rdev);
|
||||
/* block TTM */
|
||||
resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev);
|
||||
|
|
|
@ -90,9 +90,10 @@
|
|||
* CS to GPU on >= r600
|
||||
* 2.41.0 - evergreen/cayman: Add SET_BASE/DRAW_INDIRECT command parsing support
|
||||
* 2.42.0 - Add VCE/VUI (Video Usability Information) support
|
||||
* 2.43.0 - RADEON_INFO_GPU_RESET_COUNTER
|
||||
*/
|
||||
#define KMS_DRIVER_MAJOR 2
|
||||
#define KMS_DRIVER_MINOR 42
|
||||
#define KMS_DRIVER_MINOR 43
|
||||
#define KMS_DRIVER_PATCHLEVEL 0
|
||||
int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
|
||||
int radeon_driver_unload_kms(struct drm_device *dev);
|
||||
|
|
|
@ -79,10 +79,12 @@ static void radeon_hotplug_work_func(struct work_struct *work)
|
|||
struct drm_mode_config *mode_config = &dev->mode_config;
|
||||
struct drm_connector *connector;
|
||||
|
||||
mutex_lock(&mode_config->mutex);
|
||||
if (mode_config->num_connector) {
|
||||
list_for_each_entry(connector, &mode_config->connector_list, head)
|
||||
radeon_connector_hotplug(connector);
|
||||
}
|
||||
mutex_unlock(&mode_config->mutex);
|
||||
/* Just fire off a uevent and let userspace tell us what to do */
|
||||
drm_helper_hpd_irq_event(dev);
|
||||
}
|
||||
|
@ -143,7 +145,13 @@ void radeon_driver_irq_preinstall_kms(struct drm_device *dev)
|
|||
*/
|
||||
int radeon_driver_irq_postinstall_kms(struct drm_device *dev)
|
||||
{
|
||||
dev->max_vblank_count = 0x001fffff;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
|
||||
if (ASIC_IS_AVIVO(rdev))
|
||||
dev->max_vblank_count = 0x00ffffff;
|
||||
else
|
||||
dev->max_vblank_count = 0x001fffff;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -576,6 +576,9 @@ static int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file
|
|||
if (radeon_get_allowed_info_register(rdev, *value, value))
|
||||
return -EINVAL;
|
||||
break;
|
||||
case RADEON_INFO_GPU_RESET_COUNTER:
|
||||
*value = atomic_read(&rdev->gpu_reset_counter);
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG_KMS("Invalid request %d\n", info->request);
|
||||
return -EINVAL;
|
||||
|
|
|
@ -754,7 +754,7 @@ extern bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector);
|
|||
extern int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
|
||||
struct drm_connector *connector);
|
||||
int radeon_dp_get_max_link_rate(struct drm_connector *connector,
|
||||
u8 *dpcd);
|
||||
const u8 *dpcd);
|
||||
extern void radeon_dp_set_rx_power_state(struct drm_connector *connector,
|
||||
u8 power_state);
|
||||
extern void radeon_dp_aux_init(struct radeon_connector *radeon_connector);
|
||||
|
|
|
@ -38,8 +38,10 @@
|
|||
#define VCE_IDLE_TIMEOUT_MS 1000
|
||||
|
||||
/* Firmware Names */
|
||||
#define FIRMWARE_TAHITI "radeon/TAHITI_vce.bin"
|
||||
#define FIRMWARE_BONAIRE "radeon/BONAIRE_vce.bin"
|
||||
|
||||
MODULE_FIRMWARE(FIRMWARE_TAHITI);
|
||||
MODULE_FIRMWARE(FIRMWARE_BONAIRE);
|
||||
|
||||
static void radeon_vce_idle_work_handler(struct work_struct *work);
|
||||
|
@ -63,6 +65,14 @@ int radeon_vce_init(struct radeon_device *rdev)
|
|||
INIT_DELAYED_WORK(&rdev->vce.idle_work, radeon_vce_idle_work_handler);
|
||||
|
||||
switch (rdev->family) {
|
||||
case CHIP_TAHITI:
|
||||
case CHIP_PITCAIRN:
|
||||
case CHIP_VERDE:
|
||||
case CHIP_OLAND:
|
||||
case CHIP_ARUBA:
|
||||
fw_name = FIRMWARE_TAHITI;
|
||||
break;
|
||||
|
||||
case CHIP_BONAIRE:
|
||||
case CHIP_KAVERI:
|
||||
case CHIP_KABINI:
|
||||
|
@ -118,13 +128,17 @@ int radeon_vce_init(struct radeon_device *rdev)
|
|||
rdev->vce.fw_version = (start << 24) | (mid << 16) | (end << 8);
|
||||
|
||||
/* we can only work with this fw version for now */
|
||||
if (rdev->vce.fw_version != ((40 << 24) | (2 << 16) | (2 << 8)))
|
||||
if ((rdev->vce.fw_version != ((40 << 24) | (2 << 16) | (2 << 8))) &&
|
||||
(rdev->vce.fw_version != ((50 << 24) | (0 << 16) | (1 << 8))) &&
|
||||
(rdev->vce.fw_version != ((50 << 24) | (1 << 16) | (2 << 8))))
|
||||
return -EINVAL;
|
||||
|
||||
/* allocate firmware, stack and heap BO */
|
||||
|
||||
size = RADEON_GPU_PAGE_ALIGN(rdev->vce_fw->size) +
|
||||
RADEON_VCE_STACK_SIZE + RADEON_VCE_HEAP_SIZE;
|
||||
if (rdev->family < CHIP_BONAIRE)
|
||||
size = vce_v1_0_bo_size(rdev);
|
||||
else
|
||||
size = vce_v2_0_bo_size(rdev);
|
||||
r = radeon_bo_create(rdev, size, PAGE_SIZE, true,
|
||||
RADEON_GEM_DOMAIN_VRAM, 0, NULL, NULL,
|
||||
&rdev->vce.vcpu_bo);
|
||||
|
@ -225,13 +239,17 @@ int radeon_vce_resume(struct radeon_device *rdev)
|
|||
return r;
|
||||
}
|
||||
|
||||
memcpy(cpu_addr, rdev->vce_fw->data, rdev->vce_fw->size);
|
||||
memset(cpu_addr, 0, radeon_bo_size(rdev->vce.vcpu_bo));
|
||||
if (rdev->family < CHIP_BONAIRE)
|
||||
r = vce_v1_0_load_fw(rdev, cpu_addr);
|
||||
else
|
||||
memcpy(cpu_addr, rdev->vce_fw->data, rdev->vce_fw->size);
|
||||
|
||||
radeon_bo_kunmap(rdev->vce.vcpu_bo);
|
||||
|
||||
radeon_bo_unreserve(rdev->vce.vcpu_bo);
|
||||
|
||||
return 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -331,7 +331,6 @@ struct radeon_bo_va *radeon_vm_bo_add(struct radeon_device *rdev,
|
|||
bo_va->it.start = 0;
|
||||
bo_va->it.last = 0;
|
||||
bo_va->flags = 0;
|
||||
bo_va->addr = 0;
|
||||
bo_va->ref_count = 1;
|
||||
INIT_LIST_HEAD(&bo_va->bo_list);
|
||||
INIT_LIST_HEAD(&bo_va->vm_status);
|
||||
|
@ -491,9 +490,11 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev,
|
|||
}
|
||||
|
||||
if (bo_va->it.start || bo_va->it.last) {
|
||||
if (bo_va->addr) {
|
||||
spin_lock(&vm->status_lock);
|
||||
if (list_empty(&bo_va->vm_status)) {
|
||||
/* add a clone of the bo_va to clear the old address */
|
||||
struct radeon_bo_va *tmp;
|
||||
spin_unlock(&vm->status_lock);
|
||||
tmp = kzalloc(sizeof(struct radeon_bo_va), GFP_KERNEL);
|
||||
if (!tmp) {
|
||||
mutex_unlock(&vm->mutex);
|
||||
|
@ -502,14 +503,11 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev,
|
|||
tmp->it.start = bo_va->it.start;
|
||||
tmp->it.last = bo_va->it.last;
|
||||
tmp->vm = vm;
|
||||
tmp->addr = bo_va->addr;
|
||||
tmp->bo = radeon_bo_ref(bo_va->bo);
|
||||
spin_lock(&vm->status_lock);
|
||||
list_add(&tmp->vm_status, &vm->freed);
|
||||
spin_unlock(&vm->status_lock);
|
||||
|
||||
bo_va->addr = 0;
|
||||
}
|
||||
spin_unlock(&vm->status_lock);
|
||||
|
||||
interval_tree_remove(&bo_va->it, &vm->va);
|
||||
bo_va->it.start = 0;
|
||||
|
@ -520,10 +518,12 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev,
|
|||
bo_va->it.start = soffset;
|
||||
bo_va->it.last = eoffset - 1;
|
||||
interval_tree_insert(&bo_va->it, &vm->va);
|
||||
spin_lock(&vm->status_lock);
|
||||
list_add(&bo_va->vm_status, &vm->cleared);
|
||||
spin_unlock(&vm->status_lock);
|
||||
}
|
||||
|
||||
bo_va->flags = flags;
|
||||
bo_va->addr = 0;
|
||||
|
||||
soffset >>= radeon_vm_block_size;
|
||||
eoffset >>= radeon_vm_block_size;
|
||||
|
@ -921,7 +921,16 @@ int radeon_vm_bo_update(struct radeon_device *rdev,
|
|||
}
|
||||
|
||||
spin_lock(&vm->status_lock);
|
||||
list_del_init(&bo_va->vm_status);
|
||||
if (mem) {
|
||||
if (list_empty(&bo_va->vm_status)) {
|
||||
spin_unlock(&vm->status_lock);
|
||||
return 0;
|
||||
}
|
||||
list_del_init(&bo_va->vm_status);
|
||||
} else {
|
||||
list_del(&bo_va->vm_status);
|
||||
list_add(&bo_va->vm_status, &vm->cleared);
|
||||
}
|
||||
spin_unlock(&vm->status_lock);
|
||||
|
||||
bo_va->flags &= ~RADEON_VM_PAGE_VALID;
|
||||
|
@ -947,10 +956,6 @@ int radeon_vm_bo_update(struct radeon_device *rdev,
|
|||
addr = 0;
|
||||
}
|
||||
|
||||
if (addr == bo_va->addr)
|
||||
return 0;
|
||||
bo_va->addr = addr;
|
||||
|
||||
trace_radeon_vm_bo_update(bo_va);
|
||||
|
||||
nptes = bo_va->it.last - bo_va->it.start + 1;
|
||||
|
@ -1038,7 +1043,7 @@ int radeon_vm_clear_freed(struct radeon_device *rdev,
|
|||
struct radeon_vm *vm)
|
||||
{
|
||||
struct radeon_bo_va *bo_va;
|
||||
int r;
|
||||
int r = 0;
|
||||
|
||||
spin_lock(&vm->status_lock);
|
||||
while (!list_empty(&vm->freed)) {
|
||||
|
@ -1049,14 +1054,15 @@ int radeon_vm_clear_freed(struct radeon_device *rdev,
|
|||
r = radeon_vm_bo_update(rdev, bo_va, NULL);
|
||||
radeon_bo_unref(&bo_va->bo);
|
||||
radeon_fence_unref(&bo_va->last_pt_update);
|
||||
spin_lock(&vm->status_lock);
|
||||
list_del(&bo_va->vm_status);
|
||||
kfree(bo_va);
|
||||
if (r)
|
||||
return r;
|
||||
break;
|
||||
|
||||
spin_lock(&vm->status_lock);
|
||||
}
|
||||
spin_unlock(&vm->status_lock);
|
||||
return 0;
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
|
@ -1114,14 +1120,14 @@ void radeon_vm_bo_rmv(struct radeon_device *rdev,
|
|||
mutex_lock(&vm->mutex);
|
||||
if (bo_va->it.start || bo_va->it.last)
|
||||
interval_tree_remove(&bo_va->it, &vm->va);
|
||||
spin_lock(&vm->status_lock);
|
||||
list_del(&bo_va->vm_status);
|
||||
|
||||
if (bo_va->addr) {
|
||||
spin_lock(&vm->status_lock);
|
||||
if (list_empty(&bo_va->vm_status)) {
|
||||
bo_va->bo = radeon_bo_ref(bo_va->bo);
|
||||
list_add(&bo_va->vm_status, &vm->freed);
|
||||
} else {
|
||||
radeon_fence_unref(&bo_va->last_pt_update);
|
||||
list_del(&bo_va->vm_status);
|
||||
kfree(bo_va);
|
||||
}
|
||||
spin_unlock(&vm->status_lock);
|
||||
|
@ -1144,12 +1150,10 @@ void radeon_vm_bo_invalidate(struct radeon_device *rdev,
|
|||
struct radeon_bo_va *bo_va;
|
||||
|
||||
list_for_each_entry(bo_va, &bo->va, bo_list) {
|
||||
if (bo_va->addr) {
|
||||
spin_lock(&bo_va->vm->status_lock);
|
||||
list_del(&bo_va->vm_status);
|
||||
spin_lock(&bo_va->vm->status_lock);
|
||||
if (list_empty(&bo_va->vm_status))
|
||||
list_add(&bo_va->vm_status, &bo_va->vm->invalidated);
|
||||
spin_unlock(&bo_va->vm->status_lock);
|
||||
}
|
||||
spin_unlock(&bo_va->vm->status_lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1179,6 +1183,7 @@ int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm)
|
|||
spin_lock_init(&vm->status_lock);
|
||||
INIT_LIST_HEAD(&vm->invalidated);
|
||||
INIT_LIST_HEAD(&vm->freed);
|
||||
INIT_LIST_HEAD(&vm->cleared);
|
||||
|
||||
pd_size = radeon_vm_directory_size(rdev);
|
||||
pd_entries = radeon_vm_num_pdes(rdev);
|
||||
|
|
|
@ -6907,6 +6907,22 @@ static int si_startup(struct radeon_device *rdev)
|
|||
rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
|
||||
}
|
||||
|
||||
r = radeon_vce_resume(rdev);
|
||||
if (!r) {
|
||||
r = vce_v1_0_resume(rdev);
|
||||
if (!r)
|
||||
r = radeon_fence_driver_start_ring(rdev,
|
||||
TN_RING_TYPE_VCE1_INDEX);
|
||||
if (!r)
|
||||
r = radeon_fence_driver_start_ring(rdev,
|
||||
TN_RING_TYPE_VCE2_INDEX);
|
||||
}
|
||||
if (r) {
|
||||
dev_err(rdev->dev, "VCE init error (%d).\n", r);
|
||||
rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size = 0;
|
||||
rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_size = 0;
|
||||
}
|
||||
|
||||
/* Enable IRQ */
|
||||
if (!rdev->irq.installed) {
|
||||
r = radeon_irq_kms_init(rdev);
|
||||
|
@ -6975,6 +6991,23 @@ static int si_startup(struct radeon_device *rdev)
|
|||
}
|
||||
}
|
||||
|
||||
r = -ENOENT;
|
||||
|
||||
ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
|
||||
if (ring->ring_size)
|
||||
r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
|
||||
VCE_CMD_NO_OP);
|
||||
|
||||
ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
|
||||
if (ring->ring_size)
|
||||
r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
|
||||
VCE_CMD_NO_OP);
|
||||
|
||||
if (!r)
|
||||
r = vce_v1_0_init(rdev);
|
||||
else if (r != -ENOENT)
|
||||
DRM_ERROR("radeon: failed initializing VCE (%d).\n", r);
|
||||
|
||||
r = radeon_ib_pool_init(rdev);
|
||||
if (r) {
|
||||
dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
|
||||
|
@ -7033,6 +7066,7 @@ int si_suspend(struct radeon_device *rdev)
|
|||
if (rdev->has_uvd) {
|
||||
uvd_v1_0_fini(rdev);
|
||||
radeon_uvd_suspend(rdev);
|
||||
radeon_vce_suspend(rdev);
|
||||
}
|
||||
si_fini_pg(rdev);
|
||||
si_fini_cg(rdev);
|
||||
|
@ -7140,6 +7174,17 @@ int si_init(struct radeon_device *rdev)
|
|||
}
|
||||
}
|
||||
|
||||
r = radeon_vce_init(rdev);
|
||||
if (!r) {
|
||||
ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
|
||||
ring->ring_obj = NULL;
|
||||
r600_ring_init(rdev, ring, 4096);
|
||||
|
||||
ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
|
||||
ring->ring_obj = NULL;
|
||||
r600_ring_init(rdev, ring, 4096);
|
||||
}
|
||||
|
||||
rdev->ih.ring_obj = NULL;
|
||||
r600_ih_ring_init(rdev, 64 * 1024);
|
||||
|
||||
|
@ -7191,6 +7236,7 @@ void si_fini(struct radeon_device *rdev)
|
|||
if (rdev->has_uvd) {
|
||||
uvd_v1_0_fini(rdev);
|
||||
radeon_uvd_fini(rdev);
|
||||
radeon_vce_fini(rdev);
|
||||
}
|
||||
si_pcie_gart_fini(rdev);
|
||||
r600_vram_scratch_fini(rdev);
|
||||
|
@ -7675,3 +7721,124 @@ static void si_program_aspm(struct radeon_device *rdev)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
int si_vce_send_vcepll_ctlreq(struct radeon_device *rdev)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
/* make sure VCEPLL_CTLREQ is deasserted */
|
||||
WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL, 0, ~UPLL_CTLREQ_MASK);
|
||||
|
||||
mdelay(10);
|
||||
|
||||
/* assert UPLL_CTLREQ */
|
||||
WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL, UPLL_CTLREQ_MASK, ~UPLL_CTLREQ_MASK);
|
||||
|
||||
/* wait for CTLACK and CTLACK2 to get asserted */
|
||||
for (i = 0; i < 100; ++i) {
|
||||
uint32_t mask = UPLL_CTLACK_MASK | UPLL_CTLACK2_MASK;
|
||||
if ((RREG32_SMC(CG_VCEPLL_FUNC_CNTL) & mask) == mask)
|
||||
break;
|
||||
mdelay(10);
|
||||
}
|
||||
|
||||
/* deassert UPLL_CTLREQ */
|
||||
WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL, 0, ~UPLL_CTLREQ_MASK);
|
||||
|
||||
if (i == 100) {
|
||||
DRM_ERROR("Timeout setting UVD clocks!\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int si_set_vce_clocks(struct radeon_device *rdev, u32 evclk, u32 ecclk)
|
||||
{
|
||||
unsigned fb_div = 0, evclk_div = 0, ecclk_div = 0;
|
||||
int r;
|
||||
|
||||
/* bypass evclk and ecclk with bclk */
|
||||
WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL_2,
|
||||
EVCLK_SRC_SEL(1) | ECCLK_SRC_SEL(1),
|
||||
~(EVCLK_SRC_SEL_MASK | ECCLK_SRC_SEL_MASK));
|
||||
|
||||
/* put PLL in bypass mode */
|
||||
WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL, VCEPLL_BYPASS_EN_MASK,
|
||||
~VCEPLL_BYPASS_EN_MASK);
|
||||
|
||||
if (!evclk || !ecclk) {
|
||||
/* keep the Bypass mode, put PLL to sleep */
|
||||
WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL, VCEPLL_SLEEP_MASK,
|
||||
~VCEPLL_SLEEP_MASK);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = radeon_uvd_calc_upll_dividers(rdev, evclk, ecclk, 125000, 250000,
|
||||
16384, 0x03FFFFFF, 0, 128, 5,
|
||||
&fb_div, &evclk_div, &ecclk_div);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* set RESET_ANTI_MUX to 0 */
|
||||
WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL_5, 0, ~RESET_ANTI_MUX_MASK);
|
||||
|
||||
/* set VCO_MODE to 1 */
|
||||
WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL, VCEPLL_VCO_MODE_MASK,
|
||||
~VCEPLL_VCO_MODE_MASK);
|
||||
|
||||
/* toggle VCEPLL_SLEEP to 1 then back to 0 */
|
||||
WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL, VCEPLL_SLEEP_MASK,
|
||||
~VCEPLL_SLEEP_MASK);
|
||||
WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL, 0, ~VCEPLL_SLEEP_MASK);
|
||||
|
||||
/* deassert VCEPLL_RESET */
|
||||
WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL, 0, ~VCEPLL_RESET_MASK);
|
||||
|
||||
mdelay(1);
|
||||
|
||||
r = si_vce_send_vcepll_ctlreq(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* assert VCEPLL_RESET again */
|
||||
WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL, VCEPLL_RESET_MASK, ~VCEPLL_RESET_MASK);
|
||||
|
||||
/* disable spread spectrum. */
|
||||
WREG32_SMC_P(CG_VCEPLL_SPREAD_SPECTRUM, 0, ~SSEN_MASK);
|
||||
|
||||
/* set feedback divider */
|
||||
WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL_3, VCEPLL_FB_DIV(fb_div), ~VCEPLL_FB_DIV_MASK);
|
||||
|
||||
/* set ref divider to 0 */
|
||||
WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL, 0, ~VCEPLL_REF_DIV_MASK);
|
||||
|
||||
/* set PDIV_A and PDIV_B */
|
||||
WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL_2,
|
||||
VCEPLL_PDIV_A(evclk_div) | VCEPLL_PDIV_B(ecclk_div),
|
||||
~(VCEPLL_PDIV_A_MASK | VCEPLL_PDIV_B_MASK));
|
||||
|
||||
/* give the PLL some time to settle */
|
||||
mdelay(15);
|
||||
|
||||
/* deassert PLL_RESET */
|
||||
WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL, 0, ~VCEPLL_RESET_MASK);
|
||||
|
||||
mdelay(15);
|
||||
|
||||
/* switch from bypass mode to normal mode */
|
||||
WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL, 0, ~VCEPLL_BYPASS_EN_MASK);
|
||||
|
||||
r = si_vce_send_vcepll_ctlreq(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* switch VCLK and DCLK selection */
|
||||
WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL_2,
|
||||
EVCLK_SRC_SEL(16) | ECCLK_SRC_SEL(16),
|
||||
~(EVCLK_SRC_SEL_MASK | ECCLK_SRC_SEL_MASK));
|
||||
|
||||
mdelay(100);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1740,6 +1740,7 @@ struct ni_power_info *ni_get_pi(struct radeon_device *rdev);
|
|||
struct ni_ps *ni_get_ps(struct radeon_ps *rps);
|
||||
|
||||
extern int si_mc_load_microcode(struct radeon_device *rdev);
|
||||
extern void vce_v1_0_enable_mgcg(struct radeon_device *rdev, bool enable);
|
||||
|
||||
static int si_populate_voltage_value(struct radeon_device *rdev,
|
||||
const struct atom_voltage_table *table,
|
||||
|
@ -2928,6 +2929,56 @@ static struct si_dpm_quirk si_dpm_quirk_list[] = {
|
|||
{ 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
static u16 si_get_lower_of_leakage_and_vce_voltage(struct radeon_device *rdev,
|
||||
u16 vce_voltage)
|
||||
{
|
||||
u16 highest_leakage = 0;
|
||||
struct si_power_info *si_pi = si_get_pi(rdev);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < si_pi->leakage_voltage.count; i++){
|
||||
if (highest_leakage < si_pi->leakage_voltage.entries[i].voltage)
|
||||
highest_leakage = si_pi->leakage_voltage.entries[i].voltage;
|
||||
}
|
||||
|
||||
if (si_pi->leakage_voltage.count && (highest_leakage < vce_voltage))
|
||||
return highest_leakage;
|
||||
|
||||
return vce_voltage;
|
||||
}
|
||||
|
||||
static int si_get_vce_clock_voltage(struct radeon_device *rdev,
|
||||
u32 evclk, u32 ecclk, u16 *voltage)
|
||||
{
|
||||
u32 i;
|
||||
int ret = -EINVAL;
|
||||
struct radeon_vce_clock_voltage_dependency_table *table =
|
||||
&rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table;
|
||||
|
||||
if (((evclk == 0) && (ecclk == 0)) ||
|
||||
(table && (table->count == 0))) {
|
||||
*voltage = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < table->count; i++) {
|
||||
if ((evclk <= table->entries[i].evclk) &&
|
||||
(ecclk <= table->entries[i].ecclk)) {
|
||||
*voltage = table->entries[i].v;
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* if no match return the highest voltage */
|
||||
if (ret)
|
||||
*voltage = table->entries[table->count - 1].v;
|
||||
|
||||
*voltage = si_get_lower_of_leakage_and_vce_voltage(rdev, *voltage);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void si_apply_state_adjust_rules(struct radeon_device *rdev,
|
||||
struct radeon_ps *rps)
|
||||
{
|
||||
|
@ -2936,7 +2987,7 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
|
|||
bool disable_mclk_switching = false;
|
||||
bool disable_sclk_switching = false;
|
||||
u32 mclk, sclk;
|
||||
u16 vddc, vddci;
|
||||
u16 vddc, vddci, min_vce_voltage = 0;
|
||||
u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc;
|
||||
u32 max_sclk = 0, max_mclk = 0;
|
||||
int i;
|
||||
|
@ -2955,6 +3006,16 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
|
|||
++p;
|
||||
}
|
||||
|
||||
if (rps->vce_active) {
|
||||
rps->evclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].evclk;
|
||||
rps->ecclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].ecclk;
|
||||
si_get_vce_clock_voltage(rdev, rps->evclk, rps->ecclk,
|
||||
&min_vce_voltage);
|
||||
} else {
|
||||
rps->evclk = 0;
|
||||
rps->ecclk = 0;
|
||||
}
|
||||
|
||||
if ((rdev->pm.dpm.new_active_crtc_count > 1) ||
|
||||
ni_dpm_vblank_too_short(rdev))
|
||||
disable_mclk_switching = true;
|
||||
|
@ -3035,6 +3096,13 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
|
|||
vddc = ps->performance_levels[0].vddc;
|
||||
}
|
||||
|
||||
if (rps->vce_active) {
|
||||
if (sclk < rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk)
|
||||
sclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk;
|
||||
if (mclk < rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].mclk)
|
||||
mclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].mclk;
|
||||
}
|
||||
|
||||
/* adjusted low state */
|
||||
ps->performance_levels[0].sclk = sclk;
|
||||
ps->performance_levels[0].mclk = mclk;
|
||||
|
@ -3084,6 +3152,8 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
|
|||
&ps->performance_levels[i]);
|
||||
|
||||
for (i = 0; i < ps->performance_level_count; i++) {
|
||||
if (ps->performance_levels[i].vddc < min_vce_voltage)
|
||||
ps->performance_levels[i].vddc = min_vce_voltage;
|
||||
btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk,
|
||||
ps->performance_levels[i].sclk,
|
||||
max_limits->vddc, &ps->performance_levels[i].vddc);
|
||||
|
@ -3110,7 +3180,6 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
|
|||
if (ps->performance_levels[i].vddc > rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc)
|
||||
ps->dc_compatible = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -5859,6 +5928,21 @@ static void si_set_pcie_lane_width_in_smc(struct radeon_device *rdev,
|
|||
}
|
||||
}
|
||||
|
||||
static void si_set_vce_clock(struct radeon_device *rdev,
|
||||
struct radeon_ps *new_rps,
|
||||
struct radeon_ps *old_rps)
|
||||
{
|
||||
if ((old_rps->evclk != new_rps->evclk) ||
|
||||
(old_rps->ecclk != new_rps->ecclk)) {
|
||||
/* turn the clocks on when encoding, off otherwise */
|
||||
if (new_rps->evclk || new_rps->ecclk)
|
||||
vce_v1_0_enable_mgcg(rdev, false);
|
||||
else
|
||||
vce_v1_0_enable_mgcg(rdev, true);
|
||||
radeon_set_vce_clocks(rdev, new_rps->evclk, new_rps->ecclk);
|
||||
}
|
||||
}
|
||||
|
||||
void si_dpm_setup_asic(struct radeon_device *rdev)
|
||||
{
|
||||
int r;
|
||||
|
@ -6547,6 +6631,7 @@ int si_dpm_set_power_state(struct radeon_device *rdev)
|
|||
return ret;
|
||||
}
|
||||
ni_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
|
||||
si_set_vce_clock(rdev, new_ps, old_ps);
|
||||
if (eg_pi->pcie_performance_request)
|
||||
si_notify_link_speed_change_after_state_change(rdev, new_ps, old_ps);
|
||||
ret = si_set_power_state_conditionally_enable_ulv(rdev, new_ps);
|
||||
|
@ -6793,6 +6878,21 @@ static int si_parse_power_table(struct radeon_device *rdev)
|
|||
power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
|
||||
}
|
||||
rdev->pm.dpm.num_ps = state_array->ucNumEntries;
|
||||
|
||||
/* fill in the vce power states */
|
||||
for (i = 0; i < RADEON_MAX_VCE_LEVELS; i++) {
|
||||
u32 sclk, mclk;
|
||||
clock_array_index = rdev->pm.dpm.vce_states[i].clk_idx;
|
||||
clock_info = (union pplib_clock_info *)
|
||||
&clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize];
|
||||
sclk = le16_to_cpu(clock_info->si.usEngineClockLow);
|
||||
sclk |= clock_info->si.ucEngineClockHigh << 16;
|
||||
mclk = le16_to_cpu(clock_info->si.usMemoryClockLow);
|
||||
mclk |= clock_info->si.ucMemoryClockHigh << 16;
|
||||
rdev->pm.dpm.vce_states[i].sclk = sclk;
|
||||
rdev->pm.dpm.vce_states[i].mclk = mclk;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -6837,10 +6937,11 @@ int si_dpm_init(struct radeon_device *rdev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = si_parse_power_table(rdev);
|
||||
ret = r600_parse_extended_power_table(rdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = r600_parse_extended_power_table(rdev);
|
||||
|
||||
ret = si_parse_power_table(rdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -1879,6 +1879,7 @@
|
|||
#define VCE_VCPU_CACHE_SIZE1 0x20030
|
||||
#define VCE_VCPU_CACHE_OFFSET2 0x20034
|
||||
#define VCE_VCPU_CACHE_SIZE2 0x20038
|
||||
#define VCE_VCPU_SCRATCH7 0x200dc
|
||||
#define VCE_SOFT_RESET 0x20120
|
||||
#define VCE_ECPU_SOFT_RESET (1 << 0)
|
||||
#define VCE_FME_SOFT_RESET (1 << 2)
|
||||
|
@ -1893,6 +1894,7 @@
|
|||
#define VCE_RB_RPTR 0x2018c
|
||||
#define VCE_RB_WPTR 0x20190
|
||||
#define VCE_CLOCK_GATING_A 0x202f8
|
||||
# define CGC_DYN_CLOCK_MODE (1 << 16)
|
||||
#define VCE_CLOCK_GATING_B 0x202fc
|
||||
#define VCE_UENC_CLOCK_GATING 0x205bc
|
||||
#define VCE_UENC_REG_CLOCK_GATING 0x205c0
|
||||
|
@ -1917,4 +1919,31 @@
|
|||
#define VCE_CMD_IB_AUTO 0x00000005
|
||||
#define VCE_CMD_SEMAPHORE 0x00000006
|
||||
|
||||
/* discrete vce clocks */
|
||||
#define CG_VCEPLL_FUNC_CNTL 0xc0030600
|
||||
# define VCEPLL_RESET_MASK 0x00000001
|
||||
# define VCEPLL_SLEEP_MASK 0x00000002
|
||||
# define VCEPLL_BYPASS_EN_MASK 0x00000004
|
||||
# define VCEPLL_CTLREQ_MASK 0x00000008
|
||||
# define VCEPLL_VCO_MODE_MASK 0x00000600
|
||||
# define VCEPLL_REF_DIV_MASK 0x003F0000
|
||||
# define VCEPLL_CTLACK_MASK 0x40000000
|
||||
# define VCEPLL_CTLACK2_MASK 0x80000000
|
||||
#define CG_VCEPLL_FUNC_CNTL_2 0xc0030601
|
||||
# define VCEPLL_PDIV_A(x) ((x) << 0)
|
||||
# define VCEPLL_PDIV_A_MASK 0x0000007F
|
||||
# define VCEPLL_PDIV_B(x) ((x) << 8)
|
||||
# define VCEPLL_PDIV_B_MASK 0x00007F00
|
||||
# define EVCLK_SRC_SEL(x) ((x) << 20)
|
||||
# define EVCLK_SRC_SEL_MASK 0x01F00000
|
||||
# define ECCLK_SRC_SEL(x) ((x) << 25)
|
||||
# define ECCLK_SRC_SEL_MASK 0x3E000000
|
||||
#define CG_VCEPLL_FUNC_CNTL_3 0xc0030602
|
||||
# define VCEPLL_FB_DIV(x) ((x) << 0)
|
||||
# define VCEPLL_FB_DIV_MASK 0x01FFFFFF
|
||||
#define CG_VCEPLL_FUNC_CNTL_4 0xc0030603
|
||||
#define CG_VCEPLL_FUNC_CNTL_5 0xc0030604
|
||||
#define CG_VCEPLL_SPREAD_SPECTRUM 0xc0030606
|
||||
# define VCEPLL_SSEN_MASK 0x00000001
|
||||
|
||||
#endif
|
||||
|
|
|
@ -336,6 +336,7 @@ static const u32 trinity_override_mgpg_sequences[] =
|
|||
0x00000204, 0x00000000,
|
||||
};
|
||||
|
||||
extern void vce_v1_0_enable_mgcg(struct radeon_device *rdev, bool enable);
|
||||
static void trinity_program_clk_gating_hw_sequence(struct radeon_device *rdev,
|
||||
const u32 *seq, u32 count);
|
||||
static void trinity_override_dynamic_mg_powergating(struct radeon_device *rdev);
|
||||
|
@ -985,6 +986,21 @@ static void trinity_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev
|
|||
trinity_setup_uvd_clocks(rdev, new_rps, old_rps);
|
||||
}
|
||||
|
||||
static void trinity_set_vce_clock(struct radeon_device *rdev,
|
||||
struct radeon_ps *new_rps,
|
||||
struct radeon_ps *old_rps)
|
||||
{
|
||||
if ((old_rps->evclk != new_rps->evclk) ||
|
||||
(old_rps->ecclk != new_rps->ecclk)) {
|
||||
/* turn the clocks on when encoding, off otherwise */
|
||||
if (new_rps->evclk || new_rps->ecclk)
|
||||
vce_v1_0_enable_mgcg(rdev, false);
|
||||
else
|
||||
vce_v1_0_enable_mgcg(rdev, true);
|
||||
radeon_set_vce_clocks(rdev, new_rps->evclk, new_rps->ecclk);
|
||||
}
|
||||
}
|
||||
|
||||
static void trinity_program_ttt(struct radeon_device *rdev)
|
||||
{
|
||||
struct trinity_power_info *pi = trinity_get_pi(rdev);
|
||||
|
@ -1246,6 +1262,7 @@ int trinity_dpm_set_power_state(struct radeon_device *rdev)
|
|||
trinity_force_level_0(rdev);
|
||||
trinity_unforce_levels(rdev);
|
||||
trinity_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
|
||||
trinity_set_vce_clock(rdev, new_ps, old_ps);
|
||||
}
|
||||
trinity_release_mutex(rdev);
|
||||
|
||||
|
@ -1483,7 +1500,35 @@ static void trinity_adjust_uvd_state(struct radeon_device *rdev,
|
|||
}
|
||||
}
|
||||
|
||||
static int trinity_get_vce_clock_voltage(struct radeon_device *rdev,
|
||||
u32 evclk, u32 ecclk, u16 *voltage)
|
||||
{
|
||||
u32 i;
|
||||
int ret = -EINVAL;
|
||||
struct radeon_vce_clock_voltage_dependency_table *table =
|
||||
&rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table;
|
||||
|
||||
if (((evclk == 0) && (ecclk == 0)) ||
|
||||
(table && (table->count == 0))) {
|
||||
*voltage = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < table->count; i++) {
|
||||
if ((evclk <= table->entries[i].evclk) &&
|
||||
(ecclk <= table->entries[i].ecclk)) {
|
||||
*voltage = table->entries[i].v;
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* if no match return the highest voltage */
|
||||
if (ret)
|
||||
*voltage = table->entries[table->count - 1].v;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void trinity_apply_state_adjust_rules(struct radeon_device *rdev,
|
||||
struct radeon_ps *new_rps,
|
||||
|
@ -1496,6 +1541,7 @@ static void trinity_apply_state_adjust_rules(struct radeon_device *rdev,
|
|||
u32 min_sclk = pi->sys_info.min_sclk; /* XXX check against disp reqs */
|
||||
u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */
|
||||
u32 i;
|
||||
u16 min_vce_voltage;
|
||||
bool force_high;
|
||||
u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count;
|
||||
|
||||
|
@ -1504,6 +1550,14 @@ static void trinity_apply_state_adjust_rules(struct radeon_device *rdev,
|
|||
|
||||
trinity_adjust_uvd_state(rdev, new_rps);
|
||||
|
||||
if (new_rps->vce_active) {
|
||||
new_rps->evclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].evclk;
|
||||
new_rps->ecclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].ecclk;
|
||||
} else {
|
||||
new_rps->evclk = 0;
|
||||
new_rps->ecclk = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < ps->num_levels; i++) {
|
||||
if (ps->levels[i].vddc_index < min_voltage)
|
||||
ps->levels[i].vddc_index = min_voltage;
|
||||
|
@ -1512,6 +1566,17 @@ static void trinity_apply_state_adjust_rules(struct radeon_device *rdev,
|
|||
ps->levels[i].sclk =
|
||||
trinity_get_valid_engine_clock(rdev, min_sclk);
|
||||
|
||||
/* patch in vce limits */
|
||||
if (new_rps->vce_active) {
|
||||
/* sclk */
|
||||
if (ps->levels[i].sclk < rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk)
|
||||
ps->levels[i].sclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk;
|
||||
/* vddc */
|
||||
trinity_get_vce_clock_voltage(rdev, new_rps->evclk, new_rps->ecclk, &min_vce_voltage);
|
||||
if (ps->levels[i].vddc_index < min_vce_voltage)
|
||||
ps->levels[i].vddc_index = min_vce_voltage;
|
||||
}
|
||||
|
||||
ps->levels[i].ds_divider_index =
|
||||
sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[i].sclk, sclk_in_sr);
|
||||
|
||||
|
@ -1733,6 +1798,19 @@ static int trinity_parse_power_table(struct radeon_device *rdev)
|
|||
power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
|
||||
}
|
||||
rdev->pm.dpm.num_ps = state_array->ucNumEntries;
|
||||
|
||||
/* fill in the vce power states */
|
||||
for (i = 0; i < RADEON_MAX_VCE_LEVELS; i++) {
|
||||
u32 sclk;
|
||||
clock_array_index = rdev->pm.dpm.vce_states[i].clk_idx;
|
||||
clock_info = (union pplib_clock_info *)
|
||||
&clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize];
|
||||
sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow);
|
||||
sclk |= clock_info->sumo.ucEngineClockHigh << 16;
|
||||
rdev->pm.dpm.vce_states[i].sclk = sclk;
|
||||
rdev->pm.dpm.vce_states[i].mclk = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1914,6 +1992,10 @@ int trinity_dpm_init(struct radeon_device *rdev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = r600_parse_extended_power_table(rdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = trinity_parse_power_table(rdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -2000,6 +2082,7 @@ void trinity_dpm_fini(struct radeon_device *rdev)
|
|||
}
|
||||
kfree(rdev->pm.dpm.ps);
|
||||
kfree(rdev->pm.dpm.priv);
|
||||
r600_free_extended_power_table(rdev);
|
||||
}
|
||||
|
||||
u32 trinity_dpm_get_sclk(struct radeon_device *rdev, bool low)
|
||||
|
|
|
@ -31,6 +31,23 @@
|
|||
#include "radeon_asic.h"
|
||||
#include "sid.h"
|
||||
|
||||
#define VCE_V1_0_FW_SIZE (256 * 1024)
|
||||
#define VCE_V1_0_STACK_SIZE (64 * 1024)
|
||||
#define VCE_V1_0_DATA_SIZE (7808 * (RADEON_MAX_VCE_HANDLES + 1))
|
||||
|
||||
struct vce_v1_0_fw_signature
|
||||
{
|
||||
int32_t off;
|
||||
uint32_t len;
|
||||
int32_t num;
|
||||
struct {
|
||||
uint32_t chip_id;
|
||||
uint32_t keyselect;
|
||||
uint32_t nonce[4];
|
||||
uint32_t sigval[4];
|
||||
} val[8];
|
||||
};
|
||||
|
||||
/**
|
||||
* vce_v1_0_get_rptr - get read pointer
|
||||
*
|
||||
|
@ -82,6 +99,186 @@ void vce_v1_0_set_wptr(struct radeon_device *rdev,
|
|||
WREG32(VCE_RB_WPTR2, ring->wptr);
|
||||
}
|
||||
|
||||
void vce_v1_0_enable_mgcg(struct radeon_device *rdev, bool enable)
|
||||
{
|
||||
u32 tmp;
|
||||
|
||||
if (enable && (rdev->cg_flags & RADEON_CG_SUPPORT_VCE_MGCG)) {
|
||||
tmp = RREG32(VCE_CLOCK_GATING_A);
|
||||
tmp |= CGC_DYN_CLOCK_MODE;
|
||||
WREG32(VCE_CLOCK_GATING_A, tmp);
|
||||
|
||||
tmp = RREG32(VCE_UENC_CLOCK_GATING);
|
||||
tmp &= ~0x1ff000;
|
||||
tmp |= 0xff800000;
|
||||
WREG32(VCE_UENC_CLOCK_GATING, tmp);
|
||||
|
||||
tmp = RREG32(VCE_UENC_REG_CLOCK_GATING);
|
||||
tmp &= ~0x3ff;
|
||||
WREG32(VCE_UENC_REG_CLOCK_GATING, tmp);
|
||||
} else {
|
||||
tmp = RREG32(VCE_CLOCK_GATING_A);
|
||||
tmp &= ~CGC_DYN_CLOCK_MODE;
|
||||
WREG32(VCE_CLOCK_GATING_A, tmp);
|
||||
|
||||
tmp = RREG32(VCE_UENC_CLOCK_GATING);
|
||||
tmp |= 0x1ff000;
|
||||
tmp &= ~0xff800000;
|
||||
WREG32(VCE_UENC_CLOCK_GATING, tmp);
|
||||
|
||||
tmp = RREG32(VCE_UENC_REG_CLOCK_GATING);
|
||||
tmp |= 0x3ff;
|
||||
WREG32(VCE_UENC_REG_CLOCK_GATING, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
static void vce_v1_0_init_cg(struct radeon_device *rdev)
|
||||
{
|
||||
u32 tmp;
|
||||
|
||||
tmp = RREG32(VCE_CLOCK_GATING_A);
|
||||
tmp |= CGC_DYN_CLOCK_MODE;
|
||||
WREG32(VCE_CLOCK_GATING_A, tmp);
|
||||
|
||||
tmp = RREG32(VCE_CLOCK_GATING_B);
|
||||
tmp |= 0x1e;
|
||||
tmp &= ~0xe100e1;
|
||||
WREG32(VCE_CLOCK_GATING_B, tmp);
|
||||
|
||||
tmp = RREG32(VCE_UENC_CLOCK_GATING);
|
||||
tmp &= ~0xff9ff000;
|
||||
WREG32(VCE_UENC_CLOCK_GATING, tmp);
|
||||
|
||||
tmp = RREG32(VCE_UENC_REG_CLOCK_GATING);
|
||||
tmp &= ~0x3ff;
|
||||
WREG32(VCE_UENC_REG_CLOCK_GATING, tmp);
|
||||
}
|
||||
|
||||
int vce_v1_0_load_fw(struct radeon_device *rdev, uint32_t *data)
|
||||
{
|
||||
struct vce_v1_0_fw_signature *sign = (void*)rdev->vce_fw->data;
|
||||
uint32_t chip_id;
|
||||
int i;
|
||||
|
||||
switch (rdev->family) {
|
||||
case CHIP_TAHITI:
|
||||
chip_id = 0x01000014;
|
||||
break;
|
||||
case CHIP_VERDE:
|
||||
chip_id = 0x01000015;
|
||||
break;
|
||||
case CHIP_PITCAIRN:
|
||||
case CHIP_OLAND:
|
||||
chip_id = 0x01000016;
|
||||
break;
|
||||
case CHIP_ARUBA:
|
||||
chip_id = 0x01000017;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < sign->num; ++i) {
|
||||
if (sign->val[i].chip_id == chip_id)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == sign->num)
|
||||
return -EINVAL;
|
||||
|
||||
data += (256 - 64) / 4;
|
||||
data[0] = sign->val[i].nonce[0];
|
||||
data[1] = sign->val[i].nonce[1];
|
||||
data[2] = sign->val[i].nonce[2];
|
||||
data[3] = sign->val[i].nonce[3];
|
||||
data[4] = sign->len + 64;
|
||||
|
||||
memset(&data[5], 0, 44);
|
||||
memcpy(&data[16], &sign[1], rdev->vce_fw->size - sizeof(*sign));
|
||||
|
||||
data += data[4] / 4;
|
||||
data[0] = sign->val[i].sigval[0];
|
||||
data[1] = sign->val[i].sigval[1];
|
||||
data[2] = sign->val[i].sigval[2];
|
||||
data[3] = sign->val[i].sigval[3];
|
||||
|
||||
rdev->vce.keyselect = sign->val[i].keyselect;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned vce_v1_0_bo_size(struct radeon_device *rdev)
|
||||
{
|
||||
WARN_ON(VCE_V1_0_FW_SIZE < rdev->vce_fw->size);
|
||||
return VCE_V1_0_FW_SIZE + VCE_V1_0_STACK_SIZE + VCE_V1_0_DATA_SIZE;
|
||||
}
|
||||
|
||||
int vce_v1_0_resume(struct radeon_device *rdev)
|
||||
{
|
||||
uint64_t addr = rdev->vce.gpu_addr;
|
||||
uint32_t size;
|
||||
int i;
|
||||
|
||||
WREG32_P(VCE_CLOCK_GATING_A, 0, ~(1 << 16));
|
||||
WREG32_P(VCE_UENC_CLOCK_GATING, 0x1FF000, ~0xFF9FF000);
|
||||
WREG32_P(VCE_UENC_REG_CLOCK_GATING, 0x3F, ~0x3F);
|
||||
WREG32(VCE_CLOCK_GATING_B, 0);
|
||||
|
||||
WREG32_P(VCE_LMI_FW_PERIODIC_CTRL, 0x4, ~0x4);
|
||||
|
||||
WREG32(VCE_LMI_CTRL, 0x00398000);
|
||||
WREG32_P(VCE_LMI_CACHE_CTRL, 0x0, ~0x1);
|
||||
WREG32(VCE_LMI_SWAP_CNTL, 0);
|
||||
WREG32(VCE_LMI_SWAP_CNTL1, 0);
|
||||
WREG32(VCE_LMI_VM_CTRL, 0);
|
||||
|
||||
WREG32(VCE_VCPU_SCRATCH7, RADEON_MAX_VCE_HANDLES);
|
||||
|
||||
addr += 256;
|
||||
size = VCE_V1_0_FW_SIZE;
|
||||
WREG32(VCE_VCPU_CACHE_OFFSET0, addr & 0x7fffffff);
|
||||
WREG32(VCE_VCPU_CACHE_SIZE0, size);
|
||||
|
||||
addr += size;
|
||||
size = VCE_V1_0_STACK_SIZE;
|
||||
WREG32(VCE_VCPU_CACHE_OFFSET1, addr & 0x7fffffff);
|
||||
WREG32(VCE_VCPU_CACHE_SIZE1, size);
|
||||
|
||||
addr += size;
|
||||
size = VCE_V1_0_DATA_SIZE;
|
||||
WREG32(VCE_VCPU_CACHE_OFFSET2, addr & 0x7fffffff);
|
||||
WREG32(VCE_VCPU_CACHE_SIZE2, size);
|
||||
|
||||
WREG32_P(VCE_LMI_CTRL2, 0x0, ~0x100);
|
||||
|
||||
WREG32(VCE_LMI_FW_START_KEYSEL, rdev->vce.keyselect);
|
||||
|
||||
for (i = 0; i < 10; ++i) {
|
||||
mdelay(10);
|
||||
if (RREG32(VCE_FW_REG_STATUS) & VCE_FW_REG_STATUS_DONE)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == 10)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
if (!(RREG32(VCE_FW_REG_STATUS) & VCE_FW_REG_STATUS_PASS))
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < 10; ++i) {
|
||||
mdelay(10);
|
||||
if (!(RREG32(VCE_FW_REG_STATUS) & VCE_FW_REG_STATUS_BUSY))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == 10)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
vce_v1_0_init_cg(rdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* vce_v1_0_start - start VCE block
|
||||
*
|
||||
|
|
|
@ -31,6 +31,10 @@
|
|||
#include "radeon_asic.h"
|
||||
#include "cikd.h"
|
||||
|
||||
#define VCE_V2_0_FW_SIZE (256 * 1024)
|
||||
#define VCE_V2_0_STACK_SIZE (64 * 1024)
|
||||
#define VCE_V2_0_DATA_SIZE (23552 * RADEON_MAX_VCE_HANDLES)
|
||||
|
||||
static void vce_v2_0_set_sw_cg(struct radeon_device *rdev, bool gated)
|
||||
{
|
||||
u32 tmp;
|
||||
|
@ -140,6 +144,12 @@ static void vce_v2_0_init_cg(struct radeon_device *rdev)
|
|||
WREG32(VCE_CLOCK_GATING_B, tmp);
|
||||
}
|
||||
|
||||
unsigned vce_v2_0_bo_size(struct radeon_device *rdev)
|
||||
{
|
||||
WARN_ON(rdev->vce_fw->size > VCE_V2_0_FW_SIZE);
|
||||
return VCE_V2_0_FW_SIZE + VCE_V2_0_STACK_SIZE + VCE_V2_0_DATA_SIZE;
|
||||
}
|
||||
|
||||
int vce_v2_0_resume(struct radeon_device *rdev)
|
||||
{
|
||||
uint64_t addr = rdev->vce.gpu_addr;
|
||||
|
@ -159,17 +169,17 @@ int vce_v2_0_resume(struct radeon_device *rdev)
|
|||
WREG32(VCE_LMI_VCPU_CACHE_40BIT_BAR, addr >> 8);
|
||||
|
||||
addr &= 0xff;
|
||||
size = RADEON_GPU_PAGE_ALIGN(rdev->vce_fw->size);
|
||||
size = VCE_V2_0_FW_SIZE;
|
||||
WREG32(VCE_VCPU_CACHE_OFFSET0, addr & 0x7fffffff);
|
||||
WREG32(VCE_VCPU_CACHE_SIZE0, size);
|
||||
|
||||
addr += size;
|
||||
size = RADEON_VCE_STACK_SIZE;
|
||||
size = VCE_V2_0_STACK_SIZE;
|
||||
WREG32(VCE_VCPU_CACHE_OFFSET1, addr & 0x7fffffff);
|
||||
WREG32(VCE_VCPU_CACHE_SIZE1, size);
|
||||
|
||||
addr += size;
|
||||
size = RADEON_VCE_HEAP_SIZE;
|
||||
size = VCE_V2_0_DATA_SIZE;
|
||||
WREG32(VCE_VCPU_CACHE_OFFSET2, addr & 0x7fffffff);
|
||||
WREG32(VCE_VCPU_CACHE_SIZE2, size);
|
||||
|
||||
|
|
|
@ -1038,6 +1038,7 @@ struct drm_radeon_cs {
|
|||
#define RADEON_INFO_CURRENT_GPU_SCLK 0x22
|
||||
#define RADEON_INFO_CURRENT_GPU_MCLK 0x23
|
||||
#define RADEON_INFO_READ_REG 0x24
|
||||
#define RADEON_INFO_GPU_RESET_COUNTER 0x25
|
||||
|
||||
struct drm_radeon_info {
|
||||
uint32_t request;
|
||||
|
|
Loading…
Reference in New Issue