/* * Copyright 2013 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: Christian König <christian.koenig@amd.com>
*/
/** * uvd_v1_0_init - start and test UVD block * * @rdev: radeon_device pointer * * Initialize the hardware, boot up the VCPU and do some testing
*/ int uvd_v1_0_init(struct radeon_device *rdev)
{ struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
uint32_t tmp; int r;
/* raise clocks while booting up the VCPU */ if (rdev->family < CHIP_RV740)
radeon_set_uvd_clocks(rdev, 10000, 10000); else
radeon_set_uvd_clocks(rdev, 53300, 40000);
r = uvd_v1_0_start(rdev); if (r) goto done;
ring->ready = true;
r = radeon_ring_test(rdev, R600_RING_TYPE_UVD_INDEX, ring); if (r) {
ring->ready = false; goto done;
}
r = radeon_ring_lock(rdev, ring, 10); if (r) {
DRM_ERROR("radeon: ring failed to lock UVD ring (%d).\n", r); goto done;
}
/** * uvd_v1_0_fini - stop the hardware block * * @rdev: radeon_device pointer * * Stop the UVD block, mark ring as not ready any more
*/ void uvd_v1_0_fini(struct radeon_device *rdev)
{ struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
uvd_v1_0_stop(rdev);
ring->ready = false;
}
/** * uvd_v1_0_start - start UVD block * * @rdev: radeon_device pointer * * Setup and start the UVD block
*/ int uvd_v1_0_start(struct radeon_device *rdev)
{ struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
uint32_t rb_bufsz; int i, j, r;
/* boot up the VCPU */
WREG32(UVD_SOFT_RESET, 0);
mdelay(10);
for (i = 0; i < 10; ++i) {
uint32_t status; for (j = 0; j < 100; ++j) {
status = RREG32(UVD_STATUS); if (status & 2) break;
mdelay(10);
}
r = 0; if (status & 2) break;
DRM_ERROR("UVD not responding, trying to reset the VCPU!!!\n");
WREG32_P(UVD_SOFT_RESET, VCPU_SOFT_RESET, ~VCPU_SOFT_RESET);
mdelay(10);
WREG32_P(UVD_SOFT_RESET, 0, ~VCPU_SOFT_RESET);
mdelay(10);
r = -1;
}
if (r) {
DRM_ERROR("UVD not responding, giving up!!!\n"); return r;
}
/* Unstall UMC and register bus */
WREG32_P(UVD_LMI_CTRL2, 0, ~(1 << 8));
WREG32_P(UVD_RB_ARB_CTRL, 0, ~(1 << 3));
}
/** * uvd_v1_0_ring_test - register write test * * @rdev: radeon_device pointer * @ring: radeon_ring pointer * * Test if we can successfully write to the context register
*/ int uvd_v1_0_ring_test(struct radeon_device *rdev, struct radeon_ring *ring)
{
uint32_t tmp = 0; unsigned i; int r;
WREG32(UVD_CONTEXT_ID, 0xCAFEDEAD);
r = radeon_ring_lock(rdev, ring, 3); if (r) {
DRM_ERROR("radeon: cp failed to lock ring %d (%d).\n",
ring->idx, r); return r;
}
radeon_ring_write(ring, PACKET0(UVD_CONTEXT_ID, 0));
radeon_ring_write(ring, 0xDEADBEEF);
radeon_ring_unlock_commit(rdev, ring, false); for (i = 0; i < rdev->usec_timeout; i++) {
tmp = RREG32(UVD_CONTEXT_ID); if (tmp == 0xDEADBEEF) break;
udelay(1);
}
if (i < rdev->usec_timeout) {
DRM_INFO("ring test on %d succeeded in %d usecs\n",
ring->idx, i);
} else {
DRM_ERROR("radeon: ring %d test failed (0x%08X)\n",
ring->idx, tmp);
r = -EINVAL;
} return r;
}
/** * uvd_v1_0_semaphore_emit - emit semaphore command * * @rdev: radeon_device pointer * @ring: radeon_ring pointer * @semaphore: semaphore to emit commands for * @emit_wait: true if we should emit a wait command * * Emit a semaphore command (either wait or signal) to the UVD ring.
*/ bool uvd_v1_0_semaphore_emit(struct radeon_device *rdev, struct radeon_ring *ring, struct radeon_semaphore *semaphore, bool emit_wait)
{ /* disable semaphores for UVD V1 hardware */ returnfalse;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.