Commit a8a7cf02 authored by Dave Airlie's avatar Dave Airlie

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
parents c6e7e4bb 9e5acbc2
...@@ -253,7 +253,7 @@ void radeon_dp_aux_init(struct radeon_connector *radeon_connector) ...@@ -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_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_LEVEL_3
#define DP_PRE_EMPHASIS_MAX DP_TRAIN_PRE_EMPH_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, int lane_count,
u8 train_set[4]) u8 train_set[4])
{ {
...@@ -311,7 +311,7 @@ static int dp_get_max_dp_pix_clock(int link_rate, ...@@ -311,7 +311,7 @@ static int dp_get_max_dp_pix_clock(int link_rate,
/***** radeon specific DP functions *****/ /***** radeon specific DP functions *****/
int radeon_dp_get_max_link_rate(struct drm_connector *connector, 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; int max_link_rate;
...@@ -328,7 +328,7 @@ int radeon_dp_get_max_link_rate(struct drm_connector *connector, ...@@ -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. * if the max lane# < low rate lane# then use max lane# instead.
*/ */
static int radeon_dp_get_dp_lane_number(struct drm_connector *connector, 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 pix_clock)
{ {
int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector)); 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, ...@@ -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, 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 pix_clock)
{ {
int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector)); 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, ...@@ -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 */ /* get temperature in millidegrees */
int ci_get_temp(struct radeon_device *rdev) int ci_get_temp(struct radeon_device *rdev)
{ {
......
...@@ -35,6 +35,75 @@ ...@@ -35,6 +35,75 @@
#include "evergreen_blit_shaders.h" #include "evergreen_blit_shaders.h"
#include "radeon_ucode.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] = static const u32 crtc_offsets[6] =
{ {
EVERGREEN_CRTC0_REGISTER_OFFSET, EVERGREEN_CRTC0_REGISTER_OFFSET,
......
...@@ -36,6 +36,31 @@ ...@@ -36,6 +36,31 @@
#include "radeon_ucode.h" #include "radeon_ucode.h"
#include "clearstate_cayman.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[] = static const u32 tn_rlc_save_restore_register_list[] =
{ {
0x98fc, 0x98fc,
...@@ -2041,6 +2066,25 @@ static int cayman_startup(struct radeon_device *rdev) ...@@ -2041,6 +2066,25 @@ static int cayman_startup(struct radeon_device *rdev)
if (r) if (r)
rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0; 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); r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_CP1_INDEX);
if (r) { if (r) {
dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);
...@@ -2118,6 +2162,19 @@ static int cayman_startup(struct radeon_device *rdev) ...@@ -2118,6 +2162,19 @@ static int cayman_startup(struct radeon_device *rdev)
DRM_ERROR("radeon: failed initializing UVD (%d).\n", r); 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); r = radeon_ib_pool_init(rdev);
if (r) { if (r) {
dev_err(rdev->dev, "IB initialization failed (%d).\n", r); dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
...@@ -2273,6 +2330,19 @@ int cayman_init(struct radeon_device *rdev) ...@@ -2273,6 +2330,19 @@ int cayman_init(struct radeon_device *rdev)
r600_ring_init(rdev, ring, 4096); 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; rdev->ih.ring_obj = NULL;
r600_ih_ring_init(rdev, 64 * 1024); r600_ih_ring_init(rdev, 64 * 1024);
...@@ -2326,6 +2396,7 @@ void cayman_fini(struct radeon_device *rdev) ...@@ -2326,6 +2396,7 @@ void cayman_fini(struct radeon_device *rdev)
radeon_irq_kms_fini(rdev); radeon_irq_kms_fini(rdev);
uvd_v1_0_fini(rdev); uvd_v1_0_fini(rdev);
radeon_uvd_fini(rdev); radeon_uvd_fini(rdev);
radeon_vce_fini(rdev);
cayman_pcie_gart_fini(rdev); cayman_pcie_gart_fini(rdev);
r600_vram_scratch_fini(rdev); r600_vram_scratch_fini(rdev);
radeon_gem_fini(rdev); radeon_gem_fini(rdev);
...@@ -2554,3 +2625,34 @@ void cayman_vm_flush(struct radeon_device *rdev, struct radeon_ring *ring, ...@@ -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, PACKET3(PACKET3_PFP_SYNC_ME, 0));
radeon_ring_write(ring, 0x0); 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, &dividers);
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 @@ ...@@ -46,6 +46,13 @@
#define DMIF_ADDR_CONFIG 0xBD4 #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 */ /* DCE6 only */
#define DMIF_ADDR_CALC 0xC00 #define DMIF_ADDR_CALC 0xC00
......
...@@ -4090,6 +4090,28 @@ int r100_init(struct radeon_device *rdev) ...@@ -4090,6 +4090,28 @@ int r100_init(struct radeon_device *rdev)
return 0; 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) u32 r100_io_rreg(struct radeon_device *rdev, u32 reg)
{ {
if (reg < rdev->rio_mem_size) if (reg < rdev->rio_mem_size)
......
...@@ -49,6 +49,31 @@ ...@@ -49,6 +49,31 @@
* tell. (Jerome Glisse) * 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 * rv370,rv380 PCIE GART
*/ */
......
...@@ -108,6 +108,53 @@ static void r600_pcie_gen2_enable(struct radeon_device *rdev); ...@@ -108,6 +108,53 @@ static void r600_pcie_gen2_enable(struct radeon_device *rdev);
extern int evergreen_rlc_resume(struct radeon_device *rdev); extern int evergreen_rlc_resume(struct radeon_device *rdev);
extern void rv770_set_clk_bypass_mode(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 * r600_get_allowed_info_register - fetch the register for the info ioctl
* *
......
This diff is collapsed.
...@@ -1761,6 +1761,19 @@ static struct radeon_asic cayman_asic = { ...@@ -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 = { static struct radeon_asic trinity_asic = {
.init = &cayman_init, .init = &cayman_init,
.fini = &cayman_fini, .fini = &cayman_fini,
...@@ -1794,6 +1807,8 @@ static struct radeon_asic trinity_asic = { ...@@ -1794,6 +1807,8 @@ static struct radeon_asic trinity_asic = {
[R600_RING_TYPE_DMA_INDEX] = &cayman_dma_ring, [R600_RING_TYPE_DMA_INDEX] = &cayman_dma_ring,
[CAYMAN_RING_TYPE_DMA1_INDEX] = &cayman_dma_ring, [CAYMAN_RING_TYPE_DMA1_INDEX] = &cayman_dma_ring,
[R600_RING_TYPE_UVD_INDEX] = &cayman_uvd_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 = { .irq = {
.set = &evergreen_irq_set, .set = &evergreen_irq_set,
...@@ -1838,6 +1853,7 @@ static struct radeon_asic trinity_asic = { ...@@ -1838,6 +1853,7 @@ static struct radeon_asic trinity_asic = {
.set_pcie_lanes = NULL, .set_pcie_lanes = NULL,
.set_clock_gating = NULL, .set_clock_gating = NULL,
.set_uvd_clocks = &sumo_set_uvd_clocks, .set_uvd_clocks = &sumo_set_uvd_clocks,
.set_vce_clocks = &tn_set_vce_clocks,
.get_temperature = &tn_get_temp, .get_temperature = &tn_get_temp,
}, },
.dpm = { .dpm = {
...@@ -1929,6 +1945,8 @@ static struct radeon_asic si_asic = { ...@@ -1929,6 +1945,8 @@ static struct radeon_asic si_asic = {
[R600_RING_TYPE_DMA_INDEX] = &si_dma_ring, [R600_RING_TYPE_DMA_INDEX] = &si_dma_ring,
[CAYMAN_RING_TYPE_DMA1_INDEX] = &si_dma_ring, [CAYMAN_RING_TYPE_DMA1_INDEX] = &si_dma_ring,
[R600_RING_TYPE_UVD_INDEX] = &cayman_uvd_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 = { .irq = {
.set = &si_irq_set, .set = &si_irq_set,
...@@ -1973,6 +1991,7 @@ static struct radeon_asic si_asic = { ...@@ -1973,6 +1991,7 @@ static struct radeon_asic si_asic = {
.set_pcie_lanes = &r600_set_pcie_lanes, .set_pcie_lanes = &r600_set_pcie_lanes,
.set_clock_gating = NULL, .set_clock_gating = NULL,
.set_uvd_clocks = &si_set_uvd_clocks, .set_uvd_clocks = &si_set_uvd_clocks,
.set_vce_clocks = &si_set_vce_clocks,
.get_temperature = &si_get_temp, .get_temperature = &si_get_temp,
}, },
.dpm = { .dpm = {
...@@ -2436,6 +2455,8 @@ int radeon_asic_init(struct radeon_device *rdev) ...@@ -2436,6 +2455,8 @@ int radeon_asic_init(struct radeon_device *rdev)
/* set num crtcs */ /* set num crtcs */
rdev->num_crtc = 4; rdev->num_crtc = 4;
rdev->has_uvd = true; rdev->has_uvd = true;
rdev->cg_flags =
RADEON_CG_SUPPORT_VCE_MGCG;
break; break;
case CHIP_TAHITI: case CHIP_TAHITI:
case CHIP_PITCAIRN: case CHIP_PITCAIRN:
......
...@@ -694,6 +694,7 @@ int trinity_dpm_force_performance_level(struct radeon_device *rdev, ...@@ -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); 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_sclk(struct radeon_device *rdev);
u32 trinity_dpm_get_current_mclk(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 */ /* DCE6 - SI */
void dce6_bandwidth_update(struct radeon_device *rdev); 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, ...@@ -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); u32 si_get_xclk(struct radeon_device *rdev);
uint64_t si_get_gpu_clock_counter(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_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_temp(struct radeon_device *rdev);
int si_get_allowed_info_register(struct radeon_device *rdev, int si_get_allowed_info_register(struct radeon_device *rdev,
u32 reg, u32 *val); u32 reg, u32 *val);
...@@ -970,10 +972,14 @@ uint32_t vce_v1_0_get_wptr(struct radeon_device *rdev, ...@@ -970,10 +972,14 @@ uint32_t vce_v1_0_get_wptr(struct radeon_device *rdev,
struct radeon_ring *ring); struct radeon_ring *ring);
void vce_v1_0_set_wptr(struct radeon_device *rdev, void vce_v1_0_set_wptr(struct radeon_device *rdev,
struct radeon_ring *ring); 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_init(struct radeon_device *rdev);
int vce_v1_0_start(struct radeon_device *rdev); int vce_v1_0_start(struct radeon_device *rdev);
/* vce v2.0 */ /* vce v2.0 */
unsigned vce_v2_0_bo_size(struct radeon_device *rdev);
int vce_v2_0_resume(struct radeon_device *rdev); int vce_v2_0_resume(struct radeon_device *rdev);
#endif #endif
...@@ -242,6 +242,13 @@ static struct radeon_audio_funcs dce6_dp_funcs = { ...@@ -242,6 +242,13 @@ static struct radeon_audio_funcs dce6_dp_funcs = {
.dpms = evergreen_dp_enable, .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) static void radeon_audio_interface_init(struct radeon_device *rdev)
{ {
if (ASIC_IS_DCE6(rdev)) { if (ASIC_IS_DCE6(rdev)) {
...@@ -307,7 +314,7 @@ int radeon_audio_init(struct radeon_device *rdev) ...@@ -307,7 +314,7 @@ int radeon_audio_init(struct radeon_device *rdev)
/* disable audio. it will be set up later */ /* disable audio. it will be set up later */
for (i = 0; i < rdev->audio.num_pins; i++) 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; return 0;
} }
...@@ -443,13 +450,6 @@ static void radeon_audio_select_pin(struct drm_encoder *encoder) ...@@ -443,13 +450,6 @@ static void radeon_audio_select_pin(struct drm_encoder *encoder)
radeon_encoder->audio->select_pin(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, void radeon_audio_detect(struct drm_connector *connector,
enum drm_connector_status status) enum drm_connector_status status)
{ {
...@@ -505,7 +505,7 @@ void radeon_audio_fini(struct radeon_device *rdev) ...@@ -505,7 +505,7 @@ void radeon_audio_fini(struct radeon_device *rdev)
return; return;
for (i = 0; i < rdev->audio.num_pins; i++) 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; rdev->audio.enabled = false;
} }
......
...@@ -74,8 +74,6 @@ u32 radeon_audio_endpoint_rreg(struct radeon_device *rdev, ...@@ -74,8 +74,6 @@ u32 radeon_audio_endpoint_rreg(struct radeon_device *rdev,
void radeon_audio_endpoint_wreg(struct radeon_device *rdev, void radeon_audio_endpoint_wreg(struct radeon_device *rdev,
u32 offset, u32 reg, u32 v); u32 offset, u32 reg, u32 v);
struct r600_audio_pin *radeon_audio_get_pin(struct drm_encoder *encoder); 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_fini(struct radeon_device *rdev);
void radeon_audio_mode_set(struct drm_encoder *encoder, void radeon_audio_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode); struct drm_display_mode *mode);
......
...@@ -1725,6 +1725,8 @@ int radeon_gpu_reset(struct radeon_device *rdev) ...@@ -1725,6 +1725,8 @@ int radeon_gpu_reset(struct radeon_device *rdev)
return 0; return 0;
} }
atomic_inc(&rdev->gpu_reset_counter);
radeon_save_bios_scratch_regs(rdev); radeon_save_bios_scratch_regs(rdev);
/* block TTM */ /* block TTM */
resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev); resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev);
......
...@@ -90,9 +90,10 @@ ...@@ -90,9 +90,10 @@
* CS to GPU on >= r600 * CS to GPU on >= r600
* 2.41.0 - evergreen/cayman: Add SET_BASE/DRAW_INDIRECT command parsing support * 2.41.0 - evergreen/cayman: Add SET_BASE/DRAW_INDIRECT command parsing support
* 2.42.0 - Add VCE/VUI (Video Usability Information) 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_MAJOR 2
#define KMS_DRIVER_MINOR 42 #define KMS_DRIVER_MINOR 43
#define KMS_DRIVER_PATCHLEVEL 0 #define KMS_DRIVER_PATCHLEVEL 0
int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
int radeon_driver_unload_kms(struct drm_device *dev); int radeon_driver_unload_kms(struct drm_device *dev);
......
...@@ -79,10 +79,12 @@ static void radeon_hotplug_work_func(struct work_struct *work) ...@@ -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_mode_config *mode_config = &dev->mode_config;
struct drm_connector *connector; struct drm_connector *connector;
mutex_lock(&mode_config->mutex);
if (mode_config->num_connector) { if (mode_config->num_connector) {
list_for_each_entry(connector, &mode_config->connector_list, head) list_for_each_entry(connector, &mode_config->connector_list, head)
radeon_connector_hotplug(connector); radeon_connector_hotplug(connector);
} }
mutex_unlock(&mode_config->mutex);
/* Just fire off a uevent and let userspace tell us what to do */ /* Just fire off a uevent and let userspace tell us what to do */
drm_helper_hpd_irq_event(dev); drm_helper_hpd_irq_event(dev);
} }
...@@ -143,7 +145,13 @@ void radeon_driver_irq_preinstall_kms(struct drm_device *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) 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; return 0;
} }
......
...@@ -576,6 +576,9 @@ static int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file ...@@ -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)) if (radeon_get_allowed_info_register(rdev, *value, value))
return -EINVAL; return -EINVAL;
break; break;
case RADEON_INFO_GPU_RESET_COUNTER:
*value = atomic_read(&rdev->gpu_reset_counter);
break;
default: default:
DRM_DEBUG_KMS("Invalid request %d\n", info->request); DRM_DEBUG_KMS("Invalid request %d\n", info->request);
return -EINVAL; return -EINVAL;
......
...@@ -754,7 +754,7 @@ extern bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector); ...@@ -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, extern int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
struct drm_connector *connector); struct drm_connector *connector);
int radeon_dp_get_max_link_rate(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, extern void radeon_dp_set_rx_power_state(struct drm_connector *connector,
u8 power_state); u8 power_state);
extern void radeon_dp_aux_init(struct radeon_connector *radeon_connector); extern void radeon_dp_aux_init(struct radeon_connector *radeon_connector);
......
...@@ -38,8 +38,10 @@ ...@@ -38,8 +38,10 @@
#define VCE_IDLE_TIMEOUT_MS 1000 #define VCE_IDLE_TIMEOUT_MS 1000
/* Firmware Names */ /* Firmware Names */
#define FIRMWARE_TAHITI "radeon/TAHITI_vce.bin"
#define FIRMWARE_BONAIRE "radeon/BONAIRE_vce.bin" #define FIRMWARE_BONAIRE "radeon/BONAIRE_vce.bin"
MODULE_FIRMWARE(FIRMWARE_TAHITI);
MODULE_FIRMWARE(FIRMWARE_BONAIRE); MODULE_FIRMWARE(FIRMWARE_BONAIRE);
static void radeon_vce_idle_work_handler(struct work_struct *work); static void radeon_vce_idle_work_handler(struct work_struct *work);
...@@ -63,6 +65,14 @@ int radeon_vce_init(struct radeon_device *rdev) ...@@ -63,6 +65,14 @@ int radeon_vce_init(struct radeon_device *rdev)
INIT_DELAYED_WORK(&rdev->vce.idle_work, radeon_vce_idle_work_handler); INIT_DELAYED_WORK(&rdev->vce.idle_work, radeon_vce_idle_work_handler);
switch (rdev->family) { 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_BONAIRE:
case CHIP_KAVERI: case CHIP_KAVERI:
case CHIP_KABINI: case CHIP_KABINI:
...@@ -118,13 +128,17 @@ int radeon_vce_init(struct radeon_device *rdev) ...@@ -118,13 +128,17 @@ int radeon_vce_init(struct radeon_device *rdev)
rdev->vce.fw_version = (start << 24) | (mid << 16) | (end << 8); rdev->vce.fw_version = (start << 24) | (mid << 16) | (end << 8);
/* we can only work with this fw version for now */ /* 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; return -EINVAL;
/* allocate firmware, stack and heap BO */ /* allocate firmware, stack and heap BO */
size = RADEON_GPU_PAGE_ALIGN(rdev->vce_fw->size) + if (rdev->family < CHIP_BONAIRE)
RADEON_VCE_STACK_SIZE + RADEON_VCE_HEAP_SIZE; size = vce_v1_0_bo_size(rdev);
else
size = vce_v2_0_bo_size(rdev);
r = radeon_bo_create(rdev, size, PAGE_SIZE, true, r = radeon_bo_create(rdev, size, PAGE_SIZE, true,
RADEON_GEM_DOMAIN_VRAM, 0, NULL, NULL, RADEON_GEM_DOMAIN_VRAM, 0, NULL, NULL,
&rdev->vce.vcpu_bo); &rdev->vce.vcpu_bo);
...@@ -225,13 +239,17 @@ int radeon_vce_resume(struct radeon_device *rdev) ...@@ -225,13 +239,17 @@ int radeon_vce_resume(struct radeon_device *rdev)
return r; 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_kunmap(rdev->vce.vcpu_bo);
radeon_bo_unreserve(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, ...@@ -331,7 +331,6 @@ struct radeon_bo_va *radeon_vm_bo_add(struct radeon_device *rdev,
bo_va->it.start = 0; bo_va->it.start = 0;
bo_va->it.last = 0; bo_va->it.last = 0;
bo_va->flags = 0; bo_va->flags = 0;
bo_va->addr = 0;
bo_va->ref_count = 1; bo_va->ref_count = 1;
INIT_LIST_HEAD(&bo_va->bo_list); INIT_LIST_HEAD(&bo_va->bo_list);
INIT_LIST_HEAD(&bo_va->vm_status); INIT_LIST_HEAD(&bo_va->vm_status);
...@@ -491,9 +490,11 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev, ...@@ -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->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 */ /* add a clone of the bo_va to clear the old address */
struct radeon_bo_va *tmp; struct radeon_bo_va *tmp;
spin_unlock(&vm->status_lock);
tmp = kzalloc(sizeof(struct radeon_bo_va), GFP_KERNEL); tmp = kzalloc(sizeof(struct radeon_bo_va), GFP_KERNEL);
if (!tmp) { if (!tmp) {
mutex_unlock(&vm->mutex); mutex_unlock(&vm->mutex);
...@@ -502,14 +503,11 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev, ...@@ -502,14 +503,11 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev,
tmp->it.start = bo_va->it.start; tmp->it.start = bo_va->it.start;
tmp->it.last = bo_va->it.last; tmp->it.last = bo_va->it.last;
tmp->vm = vm; tmp->vm = vm;
tmp->addr = bo_va->addr;
tmp->bo = radeon_bo_ref(bo_va->bo); tmp->bo = radeon_bo_ref(bo_va->bo);
spin_lock(&vm->status_lock); spin_lock(&vm->status_lock);
list_add(&tmp->vm_status, &vm->freed); 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); interval_tree_remove(&bo_va->it, &vm->va);
bo_va->it.start = 0; bo_va->it.start = 0;
...@@ -520,10 +518,12 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev, ...@@ -520,10 +518,12 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev,
bo_va->it.start = soffset; bo_va->it.start = soffset;
bo_va->it.last = eoffset - 1; bo_va->it.last = eoffset - 1;
interval_tree_insert(&bo_va->it, &vm->va); 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->flags = flags;
bo_va->addr = 0;
soffset >>= radeon_vm_block_size; soffset >>= radeon_vm_block_size;
eoffset >>= radeon_vm_block_size; eoffset >>= radeon_vm_block_size;
...@@ -921,7 +921,16 @@ int radeon_vm_bo_update(struct radeon_device *rdev, ...@@ -921,7 +921,16 @@ int radeon_vm_bo_update(struct radeon_device *rdev,
} }
spin_lock(&vm->status_lock); 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); spin_unlock(&vm->status_lock);
bo_va->flags &= ~RADEON_VM_PAGE_VALID; bo_va->flags &= ~RADEON_VM_PAGE_VALID;
...@@ -947,10 +956,6 @@ int radeon_vm_bo_update(struct radeon_device *rdev, ...@@ -947,10 +956,6 @@ int radeon_vm_bo_update(struct radeon_device *rdev,
addr = 0; addr = 0;
} }
if (addr == bo_va->addr)
return 0;
bo_va->addr = addr;
trace_radeon_vm_bo_update(bo_va); trace_radeon_vm_bo_update(bo_va);
nptes = bo_va->it.last - bo_va->it.start + 1; nptes = bo_va->it.last - bo_va->it.start + 1;
...@@ -1038,7 +1043,7 @@ int radeon_vm_clear_freed(struct radeon_device *rdev, ...@@ -1038,7 +1043,7 @@ int radeon_vm_clear_freed(struct radeon_device *rdev,
struct radeon_vm *vm) struct radeon_vm *vm)
{ {
struct radeon_bo_va *bo_va; struct radeon_bo_va *bo_va;
int r; int r = 0;
spin_lock(&vm->status_lock); spin_lock(&vm->status_lock);
while (!list_empty(&vm->freed)) { while (!list_empty(&vm->freed)) {
...@@ -1049,14 +1054,15 @@ int radeon_vm_clear_freed(struct radeon_device *rdev, ...@@ -1049,14 +1054,15 @@ int radeon_vm_clear_freed(struct radeon_device *rdev,
r = radeon_vm_bo_update(rdev, bo_va, NULL); r = radeon_vm_bo_update(rdev, bo_va, NULL);
radeon_bo_unref(&bo_va->bo); radeon_bo_unref(&bo_va->bo);
radeon_fence_unref(&bo_va->last_pt_update); radeon_fence_unref(&bo_va->last_pt_update);
spin_lock(&vm->status_lock);
list_del(&bo_va->vm_status);
kfree(bo_va); kfree(bo_va);
if (r) if (r)
return r; break;
spin_lock(&vm->status_lock);
} }
spin_unlock(&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, ...@@ -1114,14 +1120,14 @@ void radeon_vm_bo_rmv(struct radeon_device *rdev,
mutex_lock(&vm->mutex); mutex_lock(&vm->mutex);
if (bo_va->it.start || bo_va->it.last) if (bo_va->it.start || bo_va->it.last)
interval_tree_remove(&bo_va->it, &vm->va); 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); bo_va->bo = radeon_bo_ref(bo_va->bo);
list_add(&bo_va->vm_status, &vm->freed); list_add(&bo_va->vm_status, &vm->freed);
} else { } else {
radeon_fence_unref(&bo_va->last_pt_update); radeon_fence_unref(&bo_va->last_pt_update);
list_del(&bo_va->vm_status);
kfree(bo_va); kfree(bo_va);
} }
spin_unlock(&vm->status_lock); spin_unlock(&vm->status_lock);
...@@ -1144,12 +1150,10 @@ void radeon_vm_bo_invalidate(struct radeon_device *rdev, ...@@ -1144,12 +1150,10 @@ void radeon_vm_bo_invalidate(struct radeon_device *rdev,
struct radeon_bo_va *bo_va; struct radeon_bo_va *bo_va;
list_for_each_entry(bo_va, &bo->va, bo_list) { list_for_each_entry(bo_va, &bo->va, bo_list) {
if (bo_va->addr) { spin_lock(&bo_va->vm->status_lock);
spin_lock(&bo_va->vm->status_lock); if (list_empty(&bo_va->vm_status))
list_del(&bo_va->vm_status);
list_add(&bo_va->vm_status, &bo_va->vm->invalidated); 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) ...@@ -1179,6 +1183,7 @@ int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm)
spin_lock_init(&vm->status_lock); spin_lock_init(&vm->status_lock);
INIT_LIST_HEAD(&vm->invalidated); INIT_LIST_HEAD(&vm->invalidated);
INIT_LIST_HEAD(&vm->freed); INIT_LIST_HEAD(&vm->freed);
INIT_LIST_HEAD(&vm->cleared);
pd_size = radeon_vm_directory_size(rdev); pd_size = radeon_vm_directory_size(rdev);
pd_entries = radeon_vm_num_pdes(rdev); pd_entries = radeon_vm_num_pdes(rdev);
......
...@@ -6907,6 +6907,22 @@ static int si_startup(struct radeon_device *rdev) ...@@ -6907,6 +6907,22 @@ static int si_startup(struct radeon_device *rdev)
rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0; 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 */ /* Enable IRQ */
if (!rdev->irq.installed) { if (!rdev->irq.installed) {
r = radeon_irq_kms_init(rdev); r = radeon_irq_kms_init(rdev);
...@@ -6975,6 +6991,23 @@ static int si_startup(struct radeon_device *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); r = radeon_ib_pool_init(rdev);
if (r) { if (r) {
dev_err(rdev->dev, "IB initialization failed (%d).\n", r); dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
...@@ -7033,6 +7066,7 @@ int si_suspend(struct radeon_device *rdev) ...@@ -7033,6 +7066,7 @@ int si_suspend(struct radeon_device *rdev)
if (rdev->has_uvd) { if (rdev->has_uvd) {
uvd_v1_0_fini(rdev); uvd_v1_0_fini(rdev);
radeon_uvd_suspend(rdev); radeon_uvd_suspend(rdev);
radeon_vce_suspend(rdev);
} }
si_fini_pg(rdev); si_fini_pg(rdev);
si_fini_cg(rdev); si_fini_cg(rdev);
...@@ -7140,6 +7174,17 @@ int si_init(struct radeon_device *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; rdev->ih.ring_obj = NULL;
r600_ih_ring_init(rdev, 64 * 1024); r600_ih_ring_init(rdev, 64 * 1024);
...@@ -7191,6 +7236,7 @@ void si_fini(struct radeon_device *rdev) ...@@ -7191,6 +7236,7 @@ void si_fini(struct radeon_device *rdev)
if (rdev->has_uvd) { if (rdev->has_uvd) {
uvd_v1_0_fini(rdev); uvd_v1_0_fini(rdev);
radeon_uvd_fini(rdev); radeon_uvd_fini(rdev);
radeon_vce_fini(rdev);
} }
si_pcie_gart_fini(rdev); si_pcie_gart_fini(rdev);
r600_vram_scratch_fini(rdev); r600_vram_scratch_fini(rdev);
...@@ -7675,3 +7721,124 @@ static void si_program_aspm(struct radeon_device *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); ...@@ -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); struct ni_ps *ni_get_ps(struct radeon_ps *rps);
extern int si_mc_load_microcode(struct radeon_device *rdev); 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, static int si_populate_voltage_value(struct radeon_device *rdev,
const struct atom_voltage_table *table, const struct atom_voltage_table *table,
...@@ -2928,6 +2929,56 @@ static struct si_dpm_quirk si_dpm_quirk_list[] = { ...@@ -2928,6 +2929,56 @@ static struct si_dpm_quirk si_dpm_quirk_list[] = {
{ 0, 0, 0, 0 }, { 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, static void si_apply_state_adjust_rules(struct radeon_device *rdev,
struct radeon_ps *rps) struct radeon_ps *rps)
{ {
...@@ -2936,7 +2987,7 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev, ...@@ -2936,7 +2987,7 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
bool disable_mclk_switching = false; bool disable_mclk_switching = false;
bool disable_sclk_switching = false; bool disable_sclk_switching = false;
u32 mclk, sclk; 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_vddc, max_mclk_vddci, max_mclk_vddc;
u32 max_sclk = 0, max_mclk = 0; u32 max_sclk = 0, max_mclk = 0;
int i; int i;
...@@ -2955,6 +3006,16 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev, ...@@ -2955,6 +3006,16 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
++p; ++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) || if ((rdev->pm.dpm.new_active_crtc_count > 1) ||
ni_dpm_vblank_too_short(rdev)) ni_dpm_vblank_too_short(rdev))
disable_mclk_switching = true; disable_mclk_switching = true;
...@@ -3035,6 +3096,13 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev, ...@@ -3035,6 +3096,13 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
vddc = ps->performance_levels[0].vddc; 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 */ /* adjusted low state */
ps->performance_levels[0].sclk = sclk; ps->performance_levels[0].sclk = sclk;
ps->performance_levels[0].mclk = mclk; ps->performance_levels[0].mclk = mclk;
...@@ -3084,6 +3152,8 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev, ...@@ -3084,6 +3152,8 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
&ps->performance_levels[i]); &ps->performance_levels[i]);
for (i = 0; i < ps->performance_level_count; 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, btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk,
ps->performance_levels[i].sclk, ps->performance_levels[i].sclk,
max_limits->vddc, &ps->performance_levels[i].vddc); max_limits->vddc, &ps->performance_levels[i].vddc);
...@@ -3110,7 +3180,6 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev, ...@@ -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) if (ps->performance_levels[i].vddc > rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc)
ps->dc_compatible = false; ps->dc_compatible = false;
} }
} }
#if 0 #if 0
...@@ -5859,6 +5928,21 @@ static void si_set_pcie_lane_width_in_smc(struct radeon_device *rdev, ...@@ -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) void si_dpm_setup_asic(struct radeon_device *rdev)
{ {
int r; int r;
...@@ -6547,6 +6631,7 @@ int si_dpm_set_power_state(struct radeon_device *rdev) ...@@ -6547,6 +6631,7 @@ int si_dpm_set_power_state(struct radeon_device *rdev)
return ret; return ret;
} }
ni_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps); 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) if (eg_pi->pcie_performance_request)
si_notify_link_speed_change_after_state_change(rdev, new_ps, old_ps); si_notify_link_speed_change_after_state_change(rdev, new_ps, old_ps);
ret = si_set_power_state_conditionally_enable_ulv(rdev, new_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) ...@@ -6793,6 +6878,21 @@ static int si_parse_power_table(struct radeon_device *rdev)
power_state_offset += 2 + power_state->v2.ucNumDPMLevels; power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
} }
rdev->pm.dpm.num_ps = state_array->ucNumEntries; 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; return 0;
} }
...@@ -6837,10 +6937,11 @@ int si_dpm_init(struct radeon_device *rdev) ...@@ -6837,10 +6937,11 @@ int si_dpm_init(struct radeon_device *rdev)
if (ret) if (ret)
return ret; return ret;
ret = si_parse_power_table(rdev); ret = r600_parse_extended_power_table(rdev);
if (ret) if (ret)
return ret; return ret;
ret = r600_parse_extended_power_table(rdev);
ret = si_parse_power_table(rdev);
if (ret) if (ret)
return ret; return ret;
......
...@@ -1879,6 +1879,7 @@ ...@@ -1879,6 +1879,7 @@
#define VCE_VCPU_CACHE_SIZE1 0x20030 #define VCE_VCPU_CACHE_SIZE1 0x20030
#define VCE_VCPU_CACHE_OFFSET2 0x20034 #define VCE_VCPU_CACHE_OFFSET2 0x20034
#define VCE_VCPU_CACHE_SIZE2 0x20038 #define VCE_VCPU_CACHE_SIZE2 0x20038
#define VCE_VCPU_SCRATCH7 0x200dc
#define VCE_SOFT_RESET 0x20120 #define VCE_SOFT_RESET 0x20120
#define VCE_ECPU_SOFT_RESET (1 << 0) #define VCE_ECPU_SOFT_RESET (1 << 0)
#define VCE_FME_SOFT_RESET (1 << 2) #define VCE_FME_SOFT_RESET (1 << 2)
...@@ -1893,6 +1894,7 @@ ...@@ -1893,6 +1894,7 @@
#define VCE_RB_RPTR 0x2018c #define VCE_RB_RPTR 0x2018c
#define VCE_RB_WPTR 0x20190 #define VCE_RB_WPTR 0x20190
#define VCE_CLOCK_GATING_A 0x202f8 #define VCE_CLOCK_GATING_A 0x202f8
# define CGC_DYN_CLOCK_MODE (1 << 16)
#define VCE_CLOCK_GATING_B 0x202fc #define VCE_CLOCK_GATING_B 0x202fc
#define VCE_UENC_CLOCK_GATING 0x205bc #define VCE_UENC_CLOCK_GATING 0x205bc
#define VCE_UENC_REG_CLOCK_GATING 0x205c0 #define VCE_UENC_REG_CLOCK_GATING 0x205c0
...@@ -1917,4 +1919,31 @@ ...@@ -1917,4 +1919,31 @@
#define VCE_CMD_IB_AUTO 0x00000005 #define VCE_CMD_IB_AUTO 0x00000005
#define VCE_CMD_SEMAPHORE 0x00000006 #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 #endif
...@@ -336,6 +336,7 @@ static const u32 trinity_override_mgpg_sequences[] = ...@@ -336,6 +336,7 @@ static const u32 trinity_override_mgpg_sequences[] =
0x00000204, 0x00000000, 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, static void trinity_program_clk_gating_hw_sequence(struct radeon_device *rdev,
const u32 *seq, u32 count); const u32 *seq, u32 count);
static void trinity_override_dynamic_mg_powergating(struct radeon_device *rdev); 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 ...@@ -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); 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) static void trinity_program_ttt(struct radeon_device *rdev)
{ {
struct trinity_power_info *pi = trinity_get_pi(rdev); struct trinity_power_info *pi = trinity_get_pi(rdev);
...@@ -1246,6 +1262,7 @@ int trinity_dpm_set_power_state(struct radeon_device *rdev) ...@@ -1246,6 +1262,7 @@ int trinity_dpm_set_power_state(struct radeon_device *rdev)
trinity_force_level_0(rdev); trinity_force_level_0(rdev);
trinity_unforce_levels(rdev); trinity_unforce_levels(rdev);
trinity_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps); 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); trinity_release_mutex(rdev);
...@@ -1483,7 +1500,35 @@ static void trinity_adjust_uvd_state(struct radeon_device *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, static void trinity_apply_state_adjust_rules(struct radeon_device *rdev,
struct radeon_ps *new_rps, struct radeon_ps *new_rps,
...@@ -1496,6 +1541,7 @@ static void trinity_apply_state_adjust_rules(struct radeon_device *rdev, ...@@ -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 min_sclk = pi->sys_info.min_sclk; /* XXX check against disp reqs */
u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */ u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */
u32 i; u32 i;
u16 min_vce_voltage;
bool force_high; bool force_high;
u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count; 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, ...@@ -1504,6 +1550,14 @@ static void trinity_apply_state_adjust_rules(struct radeon_device *rdev,
trinity_adjust_uvd_state(rdev, new_rps); 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++) { for (i = 0; i < ps->num_levels; i++) {
if (ps->levels[i].vddc_index < min_voltage) if (ps->levels[i].vddc_index < min_voltage)
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, ...@@ -1512,6 +1566,17 @@ static void trinity_apply_state_adjust_rules(struct radeon_device *rdev,
ps->levels[i].sclk = ps->levels[i].sclk =
trinity_get_valid_engine_clock(rdev, min_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 = ps->levels[i].ds_divider_index =
sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[i].sclk, sclk_in_sr); 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) ...@@ -1733,6 +1798,19 @@ static int trinity_parse_power_table(struct radeon_device *rdev)
power_state_offset += 2 + power_state->v2.ucNumDPMLevels; power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
} }
rdev->pm.dpm.num_ps = state_array->ucNumEntries; 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; return 0;
} }
...@@ -1914,6 +1992,10 @@ int trinity_dpm_init(struct radeon_device *rdev) ...@@ -1914,6 +1992,10 @@ int trinity_dpm_init(struct radeon_device *rdev)
if (ret) if (ret)
return ret; return ret;
ret = r600_parse_extended_power_table(rdev);
if (ret)
return ret;
ret = trinity_parse_power_table(rdev); ret = trinity_parse_power_table(rdev);
if (ret) if (ret)
return ret; return ret;
...@@ -2000,6 +2082,7 @@ void trinity_dpm_fini(struct radeon_device *rdev) ...@@ -2000,6 +2082,7 @@ void trinity_dpm_fini(struct radeon_device *rdev)
} }
kfree(rdev->pm.dpm.ps); kfree(rdev->pm.dpm.ps);
kfree(rdev->pm.dpm.priv); kfree(rdev->pm.dpm.priv);
r600_free_extended_power_table(rdev);
} }
u32 trinity_dpm_get_sclk(struct radeon_device *rdev, bool low) u32 trinity_dpm_get_sclk(struct radeon_device *rdev, bool low)
......
...@@ -31,6 +31,23 @@ ...@@ -31,6 +31,23 @@
#include "radeon_asic.h" #include "radeon_asic.h"
#include "sid.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 * vce_v1_0_get_rptr - get read pointer
* *
...@@ -82,6 +99,186 @@ void vce_v1_0_set_wptr(struct radeon_device *rdev, ...@@ -82,6 +99,186 @@ void vce_v1_0_set_wptr(struct radeon_device *rdev,
WREG32(VCE_RB_WPTR2, ring->wptr); 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 * vce_v1_0_start - start VCE block
* *
......
...@@ -31,6 +31,10 @@ ...@@ -31,6 +31,10 @@
#include "radeon_asic.h" #include "radeon_asic.h"
#include "cikd.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) static void vce_v2_0_set_sw_cg(struct radeon_device *rdev, bool gated)
{ {
u32 tmp; u32 tmp;
...@@ -140,6 +144,12 @@ static void vce_v2_0_init_cg(struct radeon_device *rdev) ...@@ -140,6 +144,12 @@ static void vce_v2_0_init_cg(struct radeon_device *rdev)
WREG32(VCE_CLOCK_GATING_B, tmp); 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) int vce_v2_0_resume(struct radeon_device *rdev)
{ {
uint64_t addr = rdev->vce.gpu_addr; uint64_t addr = rdev->vce.gpu_addr;
...@@ -159,17 +169,17 @@ int vce_v2_0_resume(struct radeon_device *rdev) ...@@ -159,17 +169,17 @@ int vce_v2_0_resume(struct radeon_device *rdev)
WREG32(VCE_LMI_VCPU_CACHE_40BIT_BAR, addr >> 8); WREG32(VCE_LMI_VCPU_CACHE_40BIT_BAR, addr >> 8);
addr &= 0xff; 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_OFFSET0, addr & 0x7fffffff);
WREG32(VCE_VCPU_CACHE_SIZE0, size); WREG32(VCE_VCPU_CACHE_SIZE0, size);
addr += 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_OFFSET1, addr & 0x7fffffff);
WREG32(VCE_VCPU_CACHE_SIZE1, size); WREG32(VCE_VCPU_CACHE_SIZE1, size);
addr += 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_OFFSET2, addr & 0x7fffffff);
WREG32(VCE_VCPU_CACHE_SIZE2, size); WREG32(VCE_VCPU_CACHE_SIZE2, size);
......
...@@ -1038,6 +1038,7 @@ struct drm_radeon_cs { ...@@ -1038,6 +1038,7 @@ struct drm_radeon_cs {
#define RADEON_INFO_CURRENT_GPU_SCLK 0x22 #define RADEON_INFO_CURRENT_GPU_SCLK 0x22
#define RADEON_INFO_CURRENT_GPU_MCLK 0x23 #define RADEON_INFO_CURRENT_GPU_MCLK 0x23
#define RADEON_INFO_READ_REG 0x24 #define RADEON_INFO_READ_REG 0x24
#define RADEON_INFO_GPU_RESET_COUNTER 0x25
struct drm_radeon_info { struct drm_radeon_info {
uint32_t request; uint32_t request;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment