Commit 762043aa authored by Dave Airlie's avatar Dave Airlie

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

Some amdgpu fixes.

* 'drm-fixes-4.2' of git://people.freedesktop.org/~agd5f/linux:
  drm/amdgpu/cz/dpm: properly report UVD and VCE clock levels
  drm/amdgpu/cz: implement voltage validation properly
  drm/amdgpu: add VCE harvesting instance query
  drm/amdgpu: implement VCE 3.0 harvesting support (v4)
  drm/amdgpu/dce10: Re-set VBLANK interrupt state when enabling a CRTC
  drm/amdgpu/dce11: Re-set VBLANK interrupt state when enabling a CRTC
parents f135b978 acc6a1a6
...@@ -1614,6 +1614,9 @@ struct amdgpu_uvd { ...@@ -1614,6 +1614,9 @@ struct amdgpu_uvd {
#define AMDGPU_MAX_VCE_HANDLES 16 #define AMDGPU_MAX_VCE_HANDLES 16
#define AMDGPU_VCE_FIRMWARE_OFFSET 256 #define AMDGPU_VCE_FIRMWARE_OFFSET 256
#define AMDGPU_VCE_HARVEST_VCE0 (1 << 0)
#define AMDGPU_VCE_HARVEST_VCE1 (1 << 1)
struct amdgpu_vce { struct amdgpu_vce {
struct amdgpu_bo *vcpu_bo; struct amdgpu_bo *vcpu_bo;
uint64_t gpu_addr; uint64_t gpu_addr;
...@@ -1626,6 +1629,7 @@ struct amdgpu_vce { ...@@ -1626,6 +1629,7 @@ struct amdgpu_vce {
const struct firmware *fw; /* VCE firmware */ const struct firmware *fw; /* VCE firmware */
struct amdgpu_ring ring[AMDGPU_MAX_VCE_RINGS]; struct amdgpu_ring ring[AMDGPU_MAX_VCE_RINGS];
struct amdgpu_irq_src irq; struct amdgpu_irq_src irq;
unsigned harvest_config;
}; };
/* /*
......
...@@ -459,6 +459,7 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file ...@@ -459,6 +459,7 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
memcpy(&dev_info.cu_bitmap[0], &cu_info.bitmap[0], sizeof(cu_info.bitmap)); memcpy(&dev_info.cu_bitmap[0], &cu_info.bitmap[0], sizeof(cu_info.bitmap));
dev_info.vram_type = adev->mc.vram_type; dev_info.vram_type = adev->mc.vram_type;
dev_info.vram_bit_width = adev->mc.vram_width; dev_info.vram_bit_width = adev->mc.vram_width;
dev_info.vce_harvest_config = adev->vce.harvest_config;
return copy_to_user(out, &dev_info, return copy_to_user(out, &dev_info,
min((size_t)size, sizeof(dev_info))) ? -EFAULT : 0; min((size_t)size, sizeof(dev_info))) ? -EFAULT : 0;
......
...@@ -494,29 +494,67 @@ static void cz_dpm_fini(struct amdgpu_device *adev) ...@@ -494,29 +494,67 @@ static void cz_dpm_fini(struct amdgpu_device *adev)
amdgpu_free_extended_power_table(adev); amdgpu_free_extended_power_table(adev);
} }
#define ixSMUSVI_NB_CURRENTVID 0xD8230044
#define CURRENT_NB_VID_MASK 0xff000000
#define CURRENT_NB_VID__SHIFT 24
#define ixSMUSVI_GFX_CURRENTVID 0xD8230048
#define CURRENT_GFX_VID_MASK 0xff000000
#define CURRENT_GFX_VID__SHIFT 24
static void static void
cz_dpm_debugfs_print_current_performance_level(struct amdgpu_device *adev, cz_dpm_debugfs_print_current_performance_level(struct amdgpu_device *adev,
struct seq_file *m) struct seq_file *m)
{ {
struct cz_power_info *pi = cz_get_pi(adev);
struct amdgpu_clock_voltage_dependency_table *table = struct amdgpu_clock_voltage_dependency_table *table =
&adev->pm.dpm.dyn_state.vddc_dependency_on_sclk; &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk;
u32 current_index = struct amdgpu_uvd_clock_voltage_dependency_table *uvd_table =
(RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX) & &adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table;
TARGET_AND_CURRENT_PROFILE_INDEX__CURR_SCLK_INDEX_MASK) >> struct amdgpu_vce_clock_voltage_dependency_table *vce_table =
TARGET_AND_CURRENT_PROFILE_INDEX__CURR_SCLK_INDEX__SHIFT; &adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table;
u32 sclk, tmp; u32 sclk_index = REG_GET_FIELD(RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX),
u16 vddc; TARGET_AND_CURRENT_PROFILE_INDEX, CURR_SCLK_INDEX);
u32 uvd_index = REG_GET_FIELD(RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX_2),
if (current_index >= NUM_SCLK_LEVELS) { TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_UVD_INDEX);
seq_printf(m, "invalid dpm profile %d\n", current_index); u32 vce_index = REG_GET_FIELD(RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX_2),
TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_VCE_INDEX);
u32 sclk, vclk, dclk, ecclk, tmp;
u16 vddnb, vddgfx;
if (sclk_index >= NUM_SCLK_LEVELS) {
seq_printf(m, "invalid sclk dpm profile %d\n", sclk_index);
} else { } else {
sclk = table->entries[current_index].clk; sclk = table->entries[sclk_index].clk;
tmp = (RREG32_SMC(ixSMU_VOLTAGE_STATUS) & seq_printf(m, "%u sclk: %u\n", sclk_index, sclk);
SMU_VOLTAGE_STATUS__SMU_VOLTAGE_CURRENT_LEVEL_MASK) >> }
SMU_VOLTAGE_STATUS__SMU_VOLTAGE_CURRENT_LEVEL__SHIFT;
vddc = cz_convert_8bit_index_to_voltage(adev, (u16)tmp); tmp = (RREG32_SMC(ixSMUSVI_NB_CURRENTVID) &
seq_printf(m, "power level %d sclk: %u vddc: %u\n", CURRENT_NB_VID_MASK) >> CURRENT_NB_VID__SHIFT;
current_index, sclk, vddc); vddnb = cz_convert_8bit_index_to_voltage(adev, (u16)tmp);
tmp = (RREG32_SMC(ixSMUSVI_GFX_CURRENTVID) &
CURRENT_GFX_VID_MASK) >> CURRENT_GFX_VID__SHIFT;
vddgfx = cz_convert_8bit_index_to_voltage(adev, (u16)tmp);
seq_printf(m, "vddnb: %u vddgfx: %u\n", vddnb, vddgfx);
seq_printf(m, "uvd %sabled\n", pi->uvd_power_gated ? "dis" : "en");
if (!pi->uvd_power_gated) {
if (uvd_index >= CZ_MAX_HARDWARE_POWERLEVELS) {
seq_printf(m, "invalid uvd dpm level %d\n", uvd_index);
} else {
vclk = uvd_table->entries[uvd_index].vclk;
dclk = uvd_table->entries[uvd_index].dclk;
seq_printf(m, "%u uvd vclk: %u dclk: %u\n", uvd_index, vclk, dclk);
}
}
seq_printf(m, "vce %sabled\n", pi->vce_power_gated ? "dis" : "en");
if (!pi->vce_power_gated) {
if (vce_index >= CZ_MAX_HARDWARE_POWERLEVELS) {
seq_printf(m, "invalid vce dpm level %d\n", vce_index);
} else {
ecclk = vce_table->entries[vce_index].ecclk;
seq_printf(m, "%u vce ecclk: %u\n", vce_index, ecclk);
}
} }
} }
......
...@@ -2632,6 +2632,7 @@ static void dce_v10_0_crtc_dpms(struct drm_crtc *crtc, int mode) ...@@ -2632,6 +2632,7 @@ static void dce_v10_0_crtc_dpms(struct drm_crtc *crtc, int mode)
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct amdgpu_device *adev = dev->dev_private; struct amdgpu_device *adev = dev->dev_private;
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
unsigned type;
switch (mode) { switch (mode) {
case DRM_MODE_DPMS_ON: case DRM_MODE_DPMS_ON:
...@@ -2640,6 +2641,9 @@ static void dce_v10_0_crtc_dpms(struct drm_crtc *crtc, int mode) ...@@ -2640,6 +2641,9 @@ static void dce_v10_0_crtc_dpms(struct drm_crtc *crtc, int mode)
dce_v10_0_vga_enable(crtc, true); dce_v10_0_vga_enable(crtc, true);
amdgpu_atombios_crtc_blank(crtc, ATOM_DISABLE); amdgpu_atombios_crtc_blank(crtc, ATOM_DISABLE);
dce_v10_0_vga_enable(crtc, false); dce_v10_0_vga_enable(crtc, false);
/* Make sure VBLANK interrupt is still enabled */
type = amdgpu_crtc_idx_to_irq_type(adev, amdgpu_crtc->crtc_id);
amdgpu_irq_update(adev, &adev->crtc_irq, type);
drm_vblank_post_modeset(dev, amdgpu_crtc->crtc_id); drm_vblank_post_modeset(dev, amdgpu_crtc->crtc_id);
dce_v10_0_crtc_load_lut(crtc); dce_v10_0_crtc_load_lut(crtc);
break; break;
......
...@@ -2631,6 +2631,7 @@ static void dce_v11_0_crtc_dpms(struct drm_crtc *crtc, int mode) ...@@ -2631,6 +2631,7 @@ static void dce_v11_0_crtc_dpms(struct drm_crtc *crtc, int mode)
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct amdgpu_device *adev = dev->dev_private; struct amdgpu_device *adev = dev->dev_private;
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
unsigned type;
switch (mode) { switch (mode) {
case DRM_MODE_DPMS_ON: case DRM_MODE_DPMS_ON:
...@@ -2639,6 +2640,9 @@ static void dce_v11_0_crtc_dpms(struct drm_crtc *crtc, int mode) ...@@ -2639,6 +2640,9 @@ static void dce_v11_0_crtc_dpms(struct drm_crtc *crtc, int mode)
dce_v11_0_vga_enable(crtc, true); dce_v11_0_vga_enable(crtc, true);
amdgpu_atombios_crtc_blank(crtc, ATOM_DISABLE); amdgpu_atombios_crtc_blank(crtc, ATOM_DISABLE);
dce_v11_0_vga_enable(crtc, false); dce_v11_0_vga_enable(crtc, false);
/* Make sure VBLANK interrupt is still enabled */
type = amdgpu_crtc_idx_to_irq_type(adev, amdgpu_crtc->crtc_id);
amdgpu_irq_update(adev, &adev->crtc_irq, type);
drm_vblank_post_modeset(dev, amdgpu_crtc->crtc_id); drm_vblank_post_modeset(dev, amdgpu_crtc->crtc_id);
dce_v11_0_crtc_load_lut(crtc); dce_v11_0_crtc_load_lut(crtc);
break; break;
......
...@@ -35,6 +35,8 @@ ...@@ -35,6 +35,8 @@
#include "oss/oss_2_0_d.h" #include "oss/oss_2_0_d.h"
#include "oss/oss_2_0_sh_mask.h" #include "oss/oss_2_0_sh_mask.h"
#include "gca/gfx_8_0_d.h" #include "gca/gfx_8_0_d.h"
#include "smu/smu_7_1_2_d.h"
#include "smu/smu_7_1_2_sh_mask.h"
#define GRBM_GFX_INDEX__VCE_INSTANCE__SHIFT 0x04 #define GRBM_GFX_INDEX__VCE_INSTANCE__SHIFT 0x04
#define GRBM_GFX_INDEX__VCE_INSTANCE_MASK 0x10 #define GRBM_GFX_INDEX__VCE_INSTANCE_MASK 0x10
...@@ -112,6 +114,10 @@ static int vce_v3_0_start(struct amdgpu_device *adev) ...@@ -112,6 +114,10 @@ static int vce_v3_0_start(struct amdgpu_device *adev)
mutex_lock(&adev->grbm_idx_mutex); mutex_lock(&adev->grbm_idx_mutex);
for (idx = 0; idx < 2; ++idx) { for (idx = 0; idx < 2; ++idx) {
if (adev->vce.harvest_config & (1 << idx))
continue;
if(idx == 0) if(idx == 0)
WREG32_P(mmGRBM_GFX_INDEX, 0, WREG32_P(mmGRBM_GFX_INDEX, 0,
~GRBM_GFX_INDEX__VCE_INSTANCE_MASK); ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK);
...@@ -190,10 +196,52 @@ static int vce_v3_0_start(struct amdgpu_device *adev) ...@@ -190,10 +196,52 @@ static int vce_v3_0_start(struct amdgpu_device *adev)
return 0; return 0;
} }
#define ixVCE_HARVEST_FUSE_MACRO__ADDRESS 0xC0014074
#define VCE_HARVEST_FUSE_MACRO__SHIFT 27
#define VCE_HARVEST_FUSE_MACRO__MASK 0x18000000
static unsigned vce_v3_0_get_harvest_config(struct amdgpu_device *adev)
{
u32 tmp;
unsigned ret;
if (adev->flags & AMDGPU_IS_APU)
tmp = (RREG32_SMC(ixVCE_HARVEST_FUSE_MACRO__ADDRESS) &
VCE_HARVEST_FUSE_MACRO__MASK) >>
VCE_HARVEST_FUSE_MACRO__SHIFT;
else
tmp = (RREG32_SMC(ixCC_HARVEST_FUSES) &
CC_HARVEST_FUSES__VCE_DISABLE_MASK) >>
CC_HARVEST_FUSES__VCE_DISABLE__SHIFT;
switch (tmp) {
case 1:
ret = AMDGPU_VCE_HARVEST_VCE0;
break;
case 2:
ret = AMDGPU_VCE_HARVEST_VCE1;
break;
case 3:
ret = AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1;
break;
default:
ret = 0;
}
return ret;
}
static int vce_v3_0_early_init(void *handle) static int vce_v3_0_early_init(void *handle)
{ {
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
adev->vce.harvest_config = vce_v3_0_get_harvest_config(adev);
if ((adev->vce.harvest_config &
(AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1)) ==
(AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1))
return -ENOENT;
vce_v3_0_set_ring_funcs(adev); vce_v3_0_set_ring_funcs(adev);
vce_v3_0_set_irq_funcs(adev); vce_v3_0_set_irq_funcs(adev);
......
...@@ -614,6 +614,8 @@ struct drm_amdgpu_info_device { ...@@ -614,6 +614,8 @@ struct drm_amdgpu_info_device {
uint32_t vram_type; uint32_t vram_type;
/** video memory bit width*/ /** video memory bit width*/
uint32_t vram_bit_width; uint32_t vram_bit_width;
/* vce harvesting instance */
uint32_t vce_harvest_config;
}; };
struct drm_amdgpu_info_hw_ip { struct drm_amdgpu_info_hw_ip {
......
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