drm/amdgpu: use begin/end_use for VCE power/clock gating
This fixes turning power and clock on when it is actually needed. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Edward O'Callaghan <funfunctor@folklore1984.net> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
c4120d55ff
commit
ebff485e93
@ -1702,6 +1702,7 @@ struct amdgpu_vce {
|
|||||||
struct drm_file *filp[AMDGPU_MAX_VCE_HANDLES];
|
struct drm_file *filp[AMDGPU_MAX_VCE_HANDLES];
|
||||||
uint32_t img_size[AMDGPU_MAX_VCE_HANDLES];
|
uint32_t img_size[AMDGPU_MAX_VCE_HANDLES];
|
||||||
struct delayed_work idle_work;
|
struct delayed_work idle_work;
|
||||||
|
struct mutex idle_mutex;
|
||||||
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;
|
||||||
|
@ -85,8 +85,6 @@ int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size)
|
|||||||
unsigned ucode_version, version_major, version_minor, binary_id;
|
unsigned ucode_version, version_major, version_minor, binary_id;
|
||||||
int i, r;
|
int i, r;
|
||||||
|
|
||||||
INIT_DELAYED_WORK(&adev->vce.idle_work, amdgpu_vce_idle_work_handler);
|
|
||||||
|
|
||||||
switch (adev->asic_type) {
|
switch (adev->asic_type) {
|
||||||
#ifdef CONFIG_DRM_AMDGPU_CIK
|
#ifdef CONFIG_DRM_AMDGPU_CIK
|
||||||
case CHIP_BONAIRE:
|
case CHIP_BONAIRE:
|
||||||
@ -197,6 +195,9 @@ int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size)
|
|||||||
adev->vce.filp[i] = NULL;
|
adev->vce.filp[i] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INIT_DELAYED_WORK(&adev->vce.idle_work, amdgpu_vce_idle_work_handler);
|
||||||
|
mutex_init(&adev->vce.idle_mutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,6 +221,7 @@ int amdgpu_vce_sw_fini(struct amdgpu_device *adev)
|
|||||||
amdgpu_ring_fini(&adev->vce.ring[1]);
|
amdgpu_ring_fini(&adev->vce.ring[1]);
|
||||||
|
|
||||||
release_firmware(adev->vce.fw);
|
release_firmware(adev->vce.fw);
|
||||||
|
mutex_destroy(&adev->vce.idle_mutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -315,19 +317,19 @@ static void amdgpu_vce_idle_work_handler(struct work_struct *work)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* amdgpu_vce_note_usage - power up VCE
|
* amdgpu_vce_ring_begin_use - power up VCE
|
||||||
*
|
*
|
||||||
* @adev: amdgpu_device pointer
|
* @ring: amdgpu ring
|
||||||
*
|
*
|
||||||
* Make sure VCE is powerd up when we want to use it
|
* Make sure VCE is powerd up when we want to use it
|
||||||
*/
|
*/
|
||||||
static void amdgpu_vce_note_usage(struct amdgpu_device *adev)
|
void amdgpu_vce_ring_begin_use(struct amdgpu_ring *ring)
|
||||||
{
|
{
|
||||||
bool set_clocks = !cancel_delayed_work_sync(&adev->vce.idle_work);
|
struct amdgpu_device *adev = ring->adev;
|
||||||
|
bool set_clocks;
|
||||||
set_clocks &= schedule_delayed_work(&adev->vce.idle_work,
|
|
||||||
VCE_IDLE_TIMEOUT);
|
|
||||||
|
|
||||||
|
mutex_lock(&adev->vce.idle_mutex);
|
||||||
|
set_clocks = !cancel_delayed_work_sync(&adev->vce.idle_work);
|
||||||
if (set_clocks) {
|
if (set_clocks) {
|
||||||
if (adev->pm.dpm_enabled) {
|
if (adev->pm.dpm_enabled) {
|
||||||
amdgpu_dpm_enable_vce(adev, true);
|
amdgpu_dpm_enable_vce(adev, true);
|
||||||
@ -335,6 +337,19 @@ static void amdgpu_vce_note_usage(struct amdgpu_device *adev)
|
|||||||
amdgpu_asic_set_vce_clocks(adev, 53300, 40000);
|
amdgpu_asic_set_vce_clocks(adev, 53300, 40000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mutex_unlock(&adev->vce.idle_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* amdgpu_vce_ring_end_use - power VCE down
|
||||||
|
*
|
||||||
|
* @ring: amdgpu ring
|
||||||
|
*
|
||||||
|
* Schedule work to power VCE down again
|
||||||
|
*/
|
||||||
|
void amdgpu_vce_ring_end_use(struct amdgpu_ring *ring)
|
||||||
|
{
|
||||||
|
schedule_delayed_work(&ring->adev->vce.idle_work, VCE_IDLE_TIMEOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -355,8 +370,6 @@ void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp)
|
|||||||
if (!handle || adev->vce.filp[i] != filp)
|
if (!handle || adev->vce.filp[i] != filp)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
amdgpu_vce_note_usage(adev);
|
|
||||||
|
|
||||||
r = amdgpu_vce_get_destroy_msg(ring, handle, false, NULL);
|
r = amdgpu_vce_get_destroy_msg(ring, handle, false, NULL);
|
||||||
if (r)
|
if (r)
|
||||||
DRM_ERROR("Error destroying VCE handle (%d)!\n", r);
|
DRM_ERROR("Error destroying VCE handle (%d)!\n", r);
|
||||||
@ -622,8 +635,6 @@ int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx)
|
|||||||
uint32_t *size = &tmp;
|
uint32_t *size = &tmp;
|
||||||
int i, r = 0, idx = 0;
|
int i, r = 0, idx = 0;
|
||||||
|
|
||||||
amdgpu_vce_note_usage(p->adev);
|
|
||||||
|
|
||||||
while (idx < ib->length_dw) {
|
while (idx < ib->length_dw) {
|
||||||
uint32_t len = amdgpu_get_ib_value(p, ib_idx, idx);
|
uint32_t len = amdgpu_get_ib_value(p, ib_idx, idx);
|
||||||
uint32_t cmd = amdgpu_get_ib_value(p, ib_idx, idx + 1);
|
uint32_t cmd = amdgpu_get_ib_value(p, ib_idx, idx + 1);
|
||||||
|
@ -40,5 +40,7 @@ void amdgpu_vce_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,
|
|||||||
unsigned flags);
|
unsigned flags);
|
||||||
int amdgpu_vce_ring_test_ring(struct amdgpu_ring *ring);
|
int amdgpu_vce_ring_test_ring(struct amdgpu_ring *ring);
|
||||||
int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring);
|
int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring);
|
||||||
|
void amdgpu_vce_ring_begin_use(struct amdgpu_ring *ring);
|
||||||
|
void amdgpu_vce_ring_end_use(struct amdgpu_ring *ring);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -594,6 +594,8 @@ static const struct amdgpu_ring_funcs vce_v2_0_ring_funcs = {
|
|||||||
.test_ib = amdgpu_vce_ring_test_ib,
|
.test_ib = amdgpu_vce_ring_test_ib,
|
||||||
.insert_nop = amdgpu_ring_insert_nop,
|
.insert_nop = amdgpu_ring_insert_nop,
|
||||||
.pad_ib = amdgpu_ring_generic_pad_ib,
|
.pad_ib = amdgpu_ring_generic_pad_ib,
|
||||||
|
.begin_use = amdgpu_vce_ring_begin_use,
|
||||||
|
.end_use = amdgpu_vce_ring_end_use,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void vce_v2_0_set_ring_funcs(struct amdgpu_device *adev)
|
static void vce_v2_0_set_ring_funcs(struct amdgpu_device *adev)
|
||||||
|
@ -767,6 +767,8 @@ static const struct amdgpu_ring_funcs vce_v3_0_ring_funcs = {
|
|||||||
.test_ib = amdgpu_vce_ring_test_ib,
|
.test_ib = amdgpu_vce_ring_test_ib,
|
||||||
.insert_nop = amdgpu_ring_insert_nop,
|
.insert_nop = amdgpu_ring_insert_nop,
|
||||||
.pad_ib = amdgpu_ring_generic_pad_ib,
|
.pad_ib = amdgpu_ring_generic_pad_ib,
|
||||||
|
.begin_use = amdgpu_vce_ring_begin_use,
|
||||||
|
.end_use = amdgpu_vce_ring_end_use,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev)
|
static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev)
|
||||||
|
Loading…
Reference in New Issue
Block a user