[PATCH 3/4] drm/radeon: consolidate uvd/vce initialization, resume and suspend.

Christian König deathsimple at vodafone.de
Wed Mar 16 13:03:58 UTC 2016


Am 16.03.2016 um 13:48 schrieb Jérôme Glisse:
> From: Jérome Glisse <jglisse at redhat.com>
>
> This consolidate uvd/vce into a common shape for all generation. It
> also leverage the rdev->has_uvd flags to know what it is useless to
> try to resume/suspend uvd/vce block.
>
> There is no functional changes when there is no error. On error the
> device driver will behave differently than before after this patch.
> It should now safely ignore uvd/vce errors and keeps normal operation
> of others engine. This is an improvement over current situation where
> we have different behavior depending on GPU generation and on what
> fails.
>
> Finaly this is a preparatory step for a patch which allow to disable
> uvd/vce as a driver option.
>
> This have only been tested on southern island so please test it on
> other generations (i do not have hardware handy for now).
>
> Signed-off-by: Jérôme Glisse <jglisse at redhat.com>
> Cc: Alex Deucher <alexander.deucher at amd.com>
> Cc: Christian König <christian.koenig at amd.com>

NAK, skipping UVD and VCE suspend/resume when initialization fails 
should already be implemented.

There might be some (quite some) bugs in there, but that doesn't justify 
reworking the initialization over all different generations. Especially 
since you don't have hardware to test all of them.

Just make sure that radeon_uvd/vce_fini() is called when something goes 
wrong and/or that the UVD/VCE BO is properly released.

Regards,
Christian.

> ---
>   drivers/gpu/drm/radeon/cik.c       | 226 ++++++++++++++++++++++------------
>   drivers/gpu/drm/radeon/evergreen.c | 122 ++++++++++++++-----
>   drivers/gpu/drm/radeon/ni.c        | 240 +++++++++++++++++++++++++------------
>   drivers/gpu/drm/radeon/r600.c      | 113 ++++++++++++-----
>   drivers/gpu/drm/radeon/rv770.c     | 122 ++++++++++++++-----
>   drivers/gpu/drm/radeon/si.c        | 213 ++++++++++++++++++++------------
>   drivers/gpu/drm/radeon/uvd_v4_2.c  |   5 +
>   7 files changed, 724 insertions(+), 317 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
> index f2a4c0f..489e202 100644
> --- a/drivers/gpu/drm/radeon/cik.c
> +++ b/drivers/gpu/drm/radeon/cik.c
> @@ -8496,6 +8496,142 @@ restart_ih:
>   /*
>    * startup/shutdown callbacks
>    */
> +
> +static void cik_uvd_vce_init(struct radeon_device *rdev)
> +{
> +	struct radeon_ring *ring;
> +	int r;
> +
> +	if (!rdev->has_uvd)
> +		return;
> +
> +	r = radeon_uvd_init(rdev);
> +	if (r)
> +		goto error_uvd;
> +	ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
> +	ring->ring_obj = NULL;
> +	r600_ring_init(rdev, ring, 4096);
> +
> +	r = radeon_vce_init(rdev);
> +	if (r)
> +		goto error_vce;
> +	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);
> +
> +	return;
> +
> +error_vce:
> +	radeon_uvd_fini(rdev);
> +error_uvd:
> +	dev_err(rdev->dev, "UVD/VCE init error (%d).\n", r);
> +	/* On error just disable everything. */
> +	rdev->has_uvd = 0;
> +}
> +
> +static void cik_uvd_vce_startup(struct radeon_device *rdev)
> +{
> +	int r;
> +
> +	if (!rdev->has_uvd)
> +		return;
> +
> +	r = uvd_v4_2_resume(rdev);
> +	if (r)
> +		goto error;
> +	r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_UVD_INDEX);
> +	if (r)
> +		goto error_uvd;
> +
> +	r = radeon_vce_resume(rdev);
> +	if (r)
> +		goto error_uvd;
> +	r = vce_v2_0_resume(rdev);
> +	if (r)
> +		goto error_vce;
> +	r = radeon_fence_driver_start_ring(rdev, TN_RING_TYPE_VCE1_INDEX);
> +	if (r)
> +		goto error_vce;
> +	r = radeon_fence_driver_start_ring(rdev, TN_RING_TYPE_VCE2_INDEX);
> +	if (r)
> +		goto error_vce;
> +
> +	return;
> +
> +error_vce:
> +	radeon_vce_suspend(rdev);
> +error_uvd:
> +	radeon_uvd_suspend(rdev);
> +error:
> +	dev_err(rdev->dev, "UVD/VCE startup error (%d).\n", r);
> +	/* On error just disable everything. */
> +	radeon_vce_fini(rdev);
> +	radeon_uvd_fini(rdev);
> +	rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
> +	rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size = 0;
> +	rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_size = 0;
> +	rdev->has_uvd = 0;
> +}
> +
> +static void cik_uvd_vce_resume(struct radeon_device *rdev)
> +{
> +	struct radeon_ring *ring;
> +	int r;
> +
> +	if (!rdev->has_uvd)
> +		return;
> +
> +	/* On uvd/vce error we disable uvd/vce so we should have bail above. */
> +	BUG_ON(!rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size);
> +	BUG_ON(!rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size);
> +	BUG_ON(!rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_size);
> +
> +	ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
> +	r = radeon_ring_init(rdev, ring, ring->ring_size, 0, RADEON_CP_PACKET2);
> +	if (r)
> +		goto error;
> +	r = uvd_v1_0_init(rdev);
> +	if (r)
> +		goto error_uvd;
> +
> +	ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
> +	r = radeon_ring_init(rdev, ring, ring->ring_size, 0, VCE_CMD_NO_OP);
> +	if (r)
> +		goto error_vce1;
> +	ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
> +	r = radeon_ring_init(rdev, ring, ring->ring_size, 0, VCE_CMD_NO_OP);
> +	if (r)
> +		goto error_vce2;
> +	r = vce_v1_0_init(rdev);
> +	if (r)
> +		goto error_vce;
> +
> +	return;
> +
> +error_vce:
> +	radeon_ring_fini(rdev, &rdev->ring[TN_RING_TYPE_VCE2_INDEX]);
> +error_vce2:
> +	radeon_ring_fini(rdev, &rdev->ring[TN_RING_TYPE_VCE1_INDEX]);
> +error_vce1:
> +	uvd_v1_0_fini(rdev);
> +error_uvd:
> +	radeon_ring_fini(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX]);
> +error:
> +	dev_err(rdev->dev, "UVD/VCE resume error (%d).\n", r);
> +	/* On error just disable everything. */
> +	radeon_uvd_suspend(rdev);
> +	radeon_vce_suspend(rdev);
> +	radeon_uvd_fini(rdev);
> +	radeon_vce_fini(rdev);
> +	rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
> +	rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size = 0;
> +	rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_size = 0;
> +	rdev->has_uvd = 0;
> +}
> +
>   /**
>    * cik_startup - program the asic to a functional state
>    *
> @@ -8598,34 +8734,7 @@ static int cik_startup(struct radeon_device *rdev)
>   		return r;
>   	}
>   
> -	r = radeon_uvd_resume(rdev);
> -	if (!r) {
> -		r = uvd_v4_2_resume(rdev);
> -		if (!r) {
> -			r = radeon_fence_driver_start_ring(rdev,
> -							   R600_RING_TYPE_UVD_INDEX);
> -			if (r)
> -				dev_err(rdev->dev, "UVD fences init error (%d).\n", r);
> -		}
> -	}
> -	if (r)
> -		rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
> -
> -	r = radeon_vce_resume(rdev);
> -	if (!r) {
> -		r = vce_v2_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;
> -	}
> +	cik_uvd_vce_startup(rdev);
>   
>   	/* Enable IRQ */
>   	if (!rdev->irq.installed) {
> @@ -8701,32 +8810,7 @@ static int cik_startup(struct radeon_device *rdev)
>   	if (r)
>   		return r;
>   
> -	ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
> -	if (ring->ring_size) {
> -		r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
> -				     RADEON_CP_PACKET2);
> -		if (!r)
> -			r = uvd_v1_0_init(rdev);
> -		if (r)
> -			DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
> -	}
> -
> -	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);
> +	cik_uvd_vce_resume(rdev);
>   
>   	r = radeon_ib_pool_init(rdev);
>   	if (r) {
> @@ -8802,9 +8886,11 @@ int cik_suspend(struct radeon_device *rdev)
>   	radeon_vm_manager_fini(rdev);
>   	cik_cp_enable(rdev, false);
>   	cik_sdma_enable(rdev, false);
> -	uvd_v1_0_fini(rdev);
> -	radeon_uvd_suspend(rdev);
> -	radeon_vce_suspend(rdev);
> +	if (rdev->has_uvd) {
> +		uvd_v1_0_fini(rdev);
> +		radeon_uvd_suspend(rdev);
> +		radeon_vce_suspend(rdev);
> +	}
>   	cik_fini_pg(rdev);
>   	cik_fini_cg(rdev);
>   	cik_irq_suspend(rdev);
> @@ -8930,23 +9016,7 @@ int cik_init(struct radeon_device *rdev)
>   	ring->ring_obj = NULL;
>   	r600_ring_init(rdev, ring, 256 * 1024);
>   
> -	r = radeon_uvd_init(rdev);
> -	if (!r) {
> -		ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
> -		ring->ring_obj = NULL;
> -		r600_ring_init(rdev, ring, 4096);
> -	}
> -
> -	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);
> -	}
> +	cik_uvd_vce_init(rdev);
>   
>   	rdev->ih.ring_obj = NULL;
>   	r600_ih_ring_init(rdev, 64 * 1024);
> @@ -9007,9 +9077,11 @@ void cik_fini(struct radeon_device *rdev)
>   	radeon_vm_manager_fini(rdev);
>   	radeon_ib_pool_fini(rdev);
>   	radeon_irq_kms_fini(rdev);
> -	uvd_v1_0_fini(rdev);
> -	radeon_uvd_fini(rdev);
> -	radeon_vce_fini(rdev);
> +	if (rdev->has_uvd) {
> +		uvd_v1_0_fini(rdev);
> +		radeon_uvd_fini(rdev);
> +		radeon_vce_fini(rdev);
> +	}
>   	cik_pcie_gart_fini(rdev);
>   	r600_vram_scratch_fini(rdev);
>   	radeon_gem_fini(rdev);
> diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
> index 76c4bdf..22854de 100644
> --- a/drivers/gpu/drm/radeon/evergreen.c
> +++ b/drivers/gpu/drm/radeon/evergreen.c
> @@ -5363,6 +5363,87 @@ restart_ih:
>   	return IRQ_HANDLED;
>   }
>   
> +static void evergreen_uvd_init(struct radeon_device *rdev)
> +{
> +	struct radeon_ring *ring;
> +	int r;
> +
> +	if (!rdev->has_uvd)
> +		return;
> +
> +	r = radeon_uvd_init(rdev);
> +	if (r)
> +		goto error_uvd;
> +	ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
> +	ring->ring_obj = NULL;
> +	r600_ring_init(rdev, ring, 4096);
> +
> +	return;
> +
> +error_uvd:
> +	dev_err(rdev->dev, "UVD init error (%d).\n", r);
> +	/* On error just disable everything. */
> +	rdev->has_uvd = 0;
> +}
> +
> +static void evergreen_uvd_startup(struct radeon_device *rdev)
> +{
> +	int r;
> +
> +	if (!rdev->has_uvd)
> +		return;
> +
> +	r = uvd_v2_2_resume(rdev);
> +	if (r)
> +		goto error;
> +	r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_UVD_INDEX);
> +	if (r)
> +		goto error_uvd;
> +
> +	return;
> +
> +error_uvd:
> +	radeon_uvd_suspend(rdev);
> +error:
> +	dev_err(rdev->dev, "UVD startup error (%d).\n", r);
> +	/* On error just disable everything. */
> +	radeon_uvd_fini(rdev);
> +	rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
> +	rdev->has_uvd = 0;
> +}
> +
> +static void evergreen_uvd_resume(struct radeon_device *rdev)
> +{
> +	struct radeon_ring *ring;
> +	int r;
> +
> +	if (!rdev->has_uvd)
> +		return;
> +
> +	/* On uvd error we disable uvd so we should have bail above. */
> +	BUG_ON(!rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size);
> +
> +	ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
> +	r = radeon_ring_init(rdev, ring, ring->ring_size, 0, RADEON_CP_PACKET2);
> +	if (r)
> +		goto error;
> +	r = uvd_v1_0_init(rdev);
> +	if (r)
> +		goto error_uvd;
> +
> +	return;
> +
> +error_uvd:
> +	radeon_ring_fini(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX]);
> +error:
> +	dev_err(rdev->dev, "UVD resume error (%d).\n", r);
> +	/* On error just disable everything. */
> +	radeon_uvd_suspend(rdev);
> +	radeon_uvd_fini(rdev);
> +	rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
> +	rdev->has_uvd = 0;
> +}
> +
>   static int evergreen_startup(struct radeon_device *rdev)
>   {
>   	struct radeon_ring *ring;
> @@ -5427,16 +5508,7 @@ static int evergreen_startup(struct radeon_device *rdev)
>   		return r;
>   	}
>   
> -	r = uvd_v2_2_resume(rdev);
> -	if (!r) {
> -		r = radeon_fence_driver_start_ring(rdev,
> -						   R600_RING_TYPE_UVD_INDEX);
> -		if (r)
> -			dev_err(rdev->dev, "UVD fences init error (%d).\n", r);
> -	}
> -
> -	if (r)
> -		rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
> +	evergreen_uvd_startup(rdev);
>   
>   	/* Enable IRQ */
>   	if (!rdev->irq.installed) {
> @@ -5475,16 +5547,7 @@ static int evergreen_startup(struct radeon_device *rdev)
>   	if (r)
>   		return r;
>   
> -	ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
> -	if (ring->ring_size) {
> -		r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
> -				     RADEON_CP_PACKET2);
> -		if (!r)
> -			r = uvd_v1_0_init(rdev);
> -
> -		if (r)
> -			DRM_ERROR("radeon: error initializing UVD (%d).\n", r);
> -	}
> +	evergreen_uvd_resume(rdev);
>   
>   	r = radeon_ib_pool_init(rdev);
>   	if (r) {
> @@ -5539,8 +5602,10 @@ int evergreen_suspend(struct radeon_device *rdev)
>   {
>   	radeon_pm_suspend(rdev);
>   	radeon_audio_fini(rdev);
> -	uvd_v1_0_fini(rdev);
> -	radeon_uvd_suspend(rdev);
> +	if (rdev->has_uvd) {
> +		uvd_v1_0_fini(rdev);
> +		radeon_uvd_suspend(rdev);
> +	}
>   	r700_cp_stop(rdev);
>   	r600_dma_stop(rdev);
>   	evergreen_irq_suspend(rdev);
> @@ -5641,12 +5706,7 @@ int evergreen_init(struct radeon_device *rdev)
>   	rdev->ring[R600_RING_TYPE_DMA_INDEX].ring_obj = NULL;
>   	r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX], 64 * 1024);
>   
> -	r = radeon_uvd_init(rdev);
> -	if (!r) {
> -		rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_obj = NULL;
> -		r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX],
> -			       4096);
> -	}
> +	evergreen_uvd_init(rdev);
>   
>   	rdev->ih.ring_obj = NULL;
>   	r600_ih_ring_init(rdev, 64 * 1024);
> @@ -5697,8 +5757,10 @@ void evergreen_fini(struct radeon_device *rdev)
>   	radeon_wb_fini(rdev);
>   	radeon_ib_pool_fini(rdev);
>   	radeon_irq_kms_fini(rdev);
> -	uvd_v1_0_fini(rdev);
> -	radeon_uvd_fini(rdev);
> +	if (rdev->has_uvd) {
> +		uvd_v1_0_fini(rdev);
> +		radeon_uvd_fini(rdev);
> +	}
>   	evergreen_pcie_gart_fini(rdev);
>   	r600_vram_scratch_fini(rdev);
>   	radeon_gem_fini(rdev);
> diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
> index b88d63c9..74f7316 100644
> --- a/drivers/gpu/drm/radeon/ni.c
> +++ b/drivers/gpu/drm/radeon/ni.c
> @@ -2002,6 +2002,154 @@ bool cayman_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
>   	return radeon_ring_test_lockup(rdev, ring);
>   }
>   
> +static void cayman_uvd_vce_init(struct radeon_device *rdev)
> +{
> +	struct radeon_ring *ring;
> +	int r;
> +
> +	if (!rdev->has_uvd)
> +		return;
> +
> +	r = radeon_uvd_init(rdev);
> +	if (r)
> +		goto error_uvd;
> +	ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
> +	ring->ring_obj = NULL;
> +	r600_ring_init(rdev, ring, 4096);
> +
> +	if (rdev->family != CHIP_ARUBA)
> +		return;
> +
> +	r = radeon_vce_init(rdev);
> +	if (r)
> +		goto error_vce;
> +	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);
> +
> +	return;
> +
> +error_vce:
> +	radeon_uvd_fini(rdev);
> +error_uvd:
> +	dev_err(rdev->dev, "UVD/VCE init error (%d).\n", r);
> +	/* On error just disable everything. */
> +	rdev->has_uvd = 0;
> +}
> +
> +static void cayman_uvd_vce_startup(struct radeon_device *rdev)
> +{
> +	int r;
> +
> +	if (!rdev->has_uvd)
> +		return;
> +
> +	r = uvd_v2_2_resume(rdev);
> +	if (r)
> +		goto error;
> +	r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_UVD_INDEX);
> +	if (r)
> +		goto error_uvd;
> +
> +	/* VCE only CHIP_ARUBA */
> +	if (rdev->family != CHIP_ARUBA)
> +		return;
> +	r = radeon_vce_resume(rdev);
> +	if (r)
> +		goto error_uvd;
> +	r = vce_v1_0_resume(rdev);
> +	if (r)
> +		goto error_vce;
> +	r = radeon_fence_driver_start_ring(rdev, TN_RING_TYPE_VCE1_INDEX);
> +	if (r)
> +		goto error_vce;
> +	r = radeon_fence_driver_start_ring(rdev, TN_RING_TYPE_VCE2_INDEX);
> +	if (r)
> +		goto error_vce;
> +
> +	return;
> +
> +error_vce:
> +	radeon_vce_suspend(rdev);
> +error_uvd:
> +	radeon_uvd_suspend(rdev);
> +error:
> +	dev_err(rdev->dev, "UVD/VCE startup error (%d).\n", r);
> +	/* On error just disable everything. */
> +	radeon_uvd_fini(rdev);
> +	rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
> +	if (rdev->family == CHIP_ARUBA) {
> +		radeon_vce_fini(rdev);
> +		rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size = 0;
> +		rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_size = 0;
> +	}
> +	rdev->has_uvd = 0;
> +}
> +
> +static void cayman_uvd_vce_resume(struct radeon_device *rdev)
> +{
> +	struct radeon_ring *ring;
> +	int r;
> +
> +	if (!rdev->has_uvd)
> +		return;
> +
> +	/* On uvd/vce error we disable uvd/vce so we should have bail above. */
> +	BUG_ON(!rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size);
> +
> +	ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
> +	r = radeon_ring_init(rdev, ring, ring->ring_size, 0, RADEON_CP_PACKET2);
> +	if (r)
> +		goto error;
> +	r = uvd_v1_0_init(rdev);
> +	if (r)
> +		goto error_uvd;
> +
> +	/* VCE only CHIP_ARUBA */
> +	if (rdev->family != CHIP_ARUBA)
> +		return;
> +	BUG_ON(!rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size);
> +	BUG_ON(!rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_size);
> +	ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
> +	r = radeon_ring_init(rdev, ring, ring->ring_size, 0, 0x0);
> +	if (r)
> +		goto error_vce1;
> +	ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
> +	r = radeon_ring_init(rdev, ring, ring->ring_size, 0, 0x0);
> +	if (r)
> +		goto error_vce2;
> +	r = vce_v1_0_init(rdev);
> +	if (r)
> +		goto error_vce;
> +
> +	return;
> +
> +error_vce:
> +	radeon_ring_fini(rdev, &rdev->ring[TN_RING_TYPE_VCE2_INDEX]);
> +error_vce2:
> +	radeon_ring_fini(rdev, &rdev->ring[TN_RING_TYPE_VCE1_INDEX]);
> +error_vce1:
> +	uvd_v1_0_fini(rdev);
> +	radeon_vce_suspend(rdev);
> +error_uvd:
> +	radeon_ring_fini(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX]);
> +error:
> +	dev_err(rdev->dev, "UVD/VCE resume error (%d).\n", r);
> +	/* On error just disable everything. */
> +	radeon_uvd_suspend(rdev);
> +	radeon_uvd_fini(rdev);
> +	rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
> +	if (rdev->family == CHIP_ARUBA) {
> +		radeon_vce_fini(rdev);
> +		rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size = 0;
> +		rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_size = 0;
> +	}
> +	rdev->has_uvd = 0;
> +}
> +
>   static int cayman_startup(struct radeon_device *rdev)
>   {
>   	struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
> @@ -2056,34 +2204,7 @@ static int cayman_startup(struct radeon_device *rdev)
>   		return r;
>   	}
>   
> -	r = uvd_v2_2_resume(rdev);
> -	if (!r) {
> -		r = radeon_fence_driver_start_ring(rdev,
> -						   R600_RING_TYPE_UVD_INDEX);
> -		if (r)
> -			dev_err(rdev->dev, "UVD fences init error (%d).\n", r);
> -	}
> -	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;
> -		}
> -	}
> +	cayman_uvd_vce_startup(rdev);
>   
>   	r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_CP1_INDEX);
>   	if (r) {
> @@ -2152,30 +2273,7 @@ static int cayman_startup(struct radeon_device *rdev)
>   	if (r)
>   		return r;
>   
> -	ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
> -	if (ring->ring_size) {
> -		r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
> -				     RADEON_CP_PACKET2);
> -		if (!r)
> -			r = uvd_v1_0_init(rdev);
> -		if (r)
> -			DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
> -	}
> -
> -	if (rdev->family == CHIP_ARUBA) {
> -		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);
> -		if (r)
> -			DRM_ERROR("radeon: failed initializing VCE (%d).\n", r);
> -	}
> +	cayman_uvd_vce_resume(rdev);
>   
>   	r = radeon_ib_pool_init(rdev);
>   	if (r) {
> @@ -2230,8 +2328,12 @@ int cayman_suspend(struct radeon_device *rdev)
>   	radeon_vm_manager_fini(rdev);
>   	cayman_cp_enable(rdev, false);
>   	cayman_dma_stop(rdev);
> -	uvd_v1_0_fini(rdev);
> -	radeon_uvd_suspend(rdev);
> +	if (rdev->has_uvd) {
> +		uvd_v1_0_fini(rdev);
> +		radeon_uvd_suspend(rdev);
> +		if (rdev->family == CHIP_ARUBA)
> +			radeon_vce_suspend(rdev);
> +	}
>   	evergreen_irq_suspend(rdev);
>   	radeon_wb_disable(rdev);
>   	cayman_pcie_gart_disable(rdev);
> @@ -2325,25 +2427,7 @@ int cayman_init(struct radeon_device *rdev)
>   	ring->ring_obj = NULL;
>   	r600_ring_init(rdev, ring, 64 * 1024);
>   
> -	r = radeon_uvd_init(rdev);
> -	if (!r) {
> -		ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
> -		ring->ring_obj = NULL;
> -		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);
> -		}
> -	}
> +	cayman_uvd_vce_init(rdev);
>   
>   	rdev->ih.ring_obj = NULL;
>   	r600_ih_ring_init(rdev, 64 * 1024);
> @@ -2396,10 +2480,12 @@ void cayman_fini(struct radeon_device *rdev)
>   	radeon_vm_manager_fini(rdev);
>   	radeon_ib_pool_fini(rdev);
>   	radeon_irq_kms_fini(rdev);
> -	uvd_v1_0_fini(rdev);
> -	radeon_uvd_fini(rdev);
> -	if (rdev->family == CHIP_ARUBA)
> -		radeon_vce_fini(rdev);
> +	if (rdev->has_uvd) {
> +		uvd_v1_0_fini(rdev);
> +		radeon_uvd_fini(rdev);
> +		if (rdev->family == CHIP_ARUBA)
> +			radeon_vce_fini(rdev);
> +	}
>   	cayman_pcie_gart_fini(rdev);
>   	r600_vram_scratch_fini(rdev);
>   	radeon_gem_fini(rdev);
> diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
> index f86ab69..9d95bee 100644
> --- a/drivers/gpu/drm/radeon/r600.c
> +++ b/drivers/gpu/drm/radeon/r600.c
> @@ -3035,6 +3035,87 @@ void r600_clear_surface_reg(struct radeon_device *rdev, int reg)
>   	/* FIXME: implement */
>   }
>   
> +static void r600_uvd_init(struct radeon_device *rdev)
> +{
> +	struct radeon_ring *ring;
> +	int r;
> +
> +	if (!rdev->has_uvd)
> +		return;
> +
> +	r = radeon_uvd_init(rdev);
> +	if (r)
> +		goto error_uvd;
> +	ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
> +	ring->ring_obj = NULL;
> +	r600_ring_init(rdev, ring, 4096);
> +
> +	return;
> +
> +error_uvd:
> +	dev_err(rdev->dev, "UVD init error (%d).\n", r);
> +	/* On error just disable everything. */
> +	rdev->has_uvd = 0;
> +}
> +
> +static void r600_uvd_startup(struct radeon_device *rdev)
> +{
> +	int r;
> +
> +	if (!rdev->has_uvd)
> +		return;
> +
> +	r = uvd_v1_0_resume(rdev);
> +	if (r)
> +		goto error;
> +	r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_UVD_INDEX);
> +	if (r)
> +		goto error_uvd;
> +
> +	return;
> +
> +error_uvd:
> +	radeon_uvd_suspend(rdev);
> +error:
> +	dev_err(rdev->dev, "UVD startup error (%d).\n", r);
> +	/* On error just disable everything. */
> +	radeon_uvd_fini(rdev);
> +	rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
> +	rdev->has_uvd = 0;
> +}
> +
> +static void r600_uvd_resume(struct radeon_device *rdev)
> +{
> +	struct radeon_ring *ring;
> +	int r;
> +
> +	if (!rdev->has_uvd)
> +		return;
> +
> +	/* On uvd error we disable uvd so we should have bail above. */
> +	BUG_ON(!rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size);
> +
> +	ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
> +	r = radeon_ring_init(rdev, ring, ring->ring_size, 0, RADEON_CP_PACKET2);
> +	if (r)
> +		goto error;
> +	r = uvd_v1_0_init(rdev);
> +	if (r)
> +		goto error_uvd;
> +
> +	return;
> +
> +error_uvd:
> +	radeon_ring_fini(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX]);
> +error:
> +	dev_err(rdev->dev, "UVD resume error (%d).\n", r);
> +	/* On error just disable everything. */
> +	radeon_uvd_suspend(rdev);
> +	radeon_uvd_fini(rdev);
> +	rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
> +	rdev->has_uvd = 0;
> +}
> +
>   static int r600_startup(struct radeon_device *rdev)
>   {
>   	struct radeon_ring *ring;
> @@ -3070,17 +3151,7 @@ static int r600_startup(struct radeon_device *rdev)
>   		return r;
>   	}
>   
> -	if (rdev->has_uvd) {
> -		r = uvd_v1_0_resume(rdev);
> -		if (!r) {
> -			r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_UVD_INDEX);
> -			if (r) {
> -				dev_err(rdev->dev, "failed initializing UVD fences (%d).\n", r);
> -			}
> -		}
> -		if (r)
> -			rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
> -	}
> +	r600_uvd_startup(rdev);
>   
>   	/* Enable IRQ */
>   	if (!rdev->irq.installed) {
> @@ -3110,17 +3181,7 @@ static int r600_startup(struct radeon_device *rdev)
>   	if (r)
>   		return r;
>   
> -	if (rdev->has_uvd) {
> -		ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
> -		if (ring->ring_size) {
> -			r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
> -					     RADEON_CP_PACKET2);
> -			if (!r)
> -				r = uvd_v1_0_init(rdev);
> -			if (r)
> -				DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
> -		}
> -	}
> +	r600_uvd_resume(rdev);
>   
>   	r = radeon_ib_pool_init(rdev);
>   	if (r) {
> @@ -3264,13 +3325,7 @@ int r600_init(struct radeon_device *rdev)
>   	rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL;
>   	r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024);
>   
> -	if (rdev->has_uvd) {
> -		r = radeon_uvd_init(rdev);
> -		if (!r) {
> -			rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_obj = NULL;
> -			r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX], 4096);
> -		}
> -	}
> +	r600_uvd_init(rdev);
>   
>   	rdev->ih.ring_obj = NULL;
>   	r600_ih_ring_init(rdev, 64 * 1024);
> diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
> index 01ee96a..cf6e2ee 100644
> --- a/drivers/gpu/drm/radeon/rv770.c
> +++ b/drivers/gpu/drm/radeon/rv770.c
> @@ -1681,6 +1681,87 @@ static int rv770_mc_init(struct radeon_device *rdev)
>   	return 0;
>   }
>   
> +static void rv770_uvd_init(struct radeon_device *rdev)
> +{
> +	struct radeon_ring *ring;
> +	int r;
> +
> +	if (!rdev->has_uvd)
> +		return;
> +
> +	r = radeon_uvd_init(rdev);
> +	if (r)
> +		goto error_uvd;
> +	ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
> +	ring->ring_obj = NULL;
> +	r600_ring_init(rdev, ring, 4096);
> +
> +	return;
> +
> +error_uvd:
> +	dev_err(rdev->dev, "UVD init error (%d).\n", r);
> +	/* On error just disable everything. */
> +	rdev->has_uvd = 0;
> +}
> +
> +static void rv770_uvd_startup(struct radeon_device *rdev)
> +{
> +	int r;
> +
> +	if (!rdev->has_uvd)
> +		return;
> +
> +	r = uvd_v2_2_resume(rdev);
> +	if (r)
> +		goto error;
> +	r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_UVD_INDEX);
> +	if (r)
> +		goto error_uvd;
> +
> +	return;
> +
> +error_uvd:
> +	radeon_uvd_suspend(rdev);
> +error:
> +	dev_err(rdev->dev, "UVD startup error (%d).\n", r);
> +	/* On error just disable everything. */
> +	radeon_uvd_fini(rdev);
> +	rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
> +	rdev->has_uvd = 0;
> +}
> +
> +static void rv770_uvd_resume(struct radeon_device *rdev)
> +{
> +	struct radeon_ring *ring;
> +	int r;
> +
> +	if (!rdev->has_uvd)
> +		return;
> +
> +	/* On uvd error we disable uvd so we should have bail above. */
> +	BUG_ON(!rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size);
> +
> +	ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
> +	r = radeon_ring_init(rdev, ring, ring->ring_size, 0, RADEON_CP_PACKET2);
> +	if (r)
> +		goto error;
> +	r = uvd_v1_0_init(rdev);
> +	if (r)
> +		goto error_uvd;
> +
> +	return;
> +
> +error_uvd:
> +	radeon_ring_fini(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX]);
> +error:
> +	dev_err(rdev->dev, "UVD resume error (%d).\n", r);
> +	/* On error just disable everything. */
> +	radeon_uvd_suspend(rdev);
> +	radeon_uvd_fini(rdev);
> +	rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
> +	rdev->has_uvd = 0;
> +}
> +
>   static int rv770_startup(struct radeon_device *rdev)
>   {
>   	struct radeon_ring *ring;
> @@ -1723,16 +1804,7 @@ static int rv770_startup(struct radeon_device *rdev)
>   		return r;
>   	}
>   
> -	r = uvd_v2_2_resume(rdev);
> -	if (!r) {
> -		r = radeon_fence_driver_start_ring(rdev,
> -						   R600_RING_TYPE_UVD_INDEX);
> -		if (r)
> -			dev_err(rdev->dev, "UVD fences init error (%d).\n", r);
> -	}
> -
> -	if (r)
> -		rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
> +	rv770_uvd_startup(rdev);
>   
>   	/* Enable IRQ */
>   	if (!rdev->irq.installed) {
> @@ -1772,16 +1844,7 @@ static int rv770_startup(struct radeon_device *rdev)
>   	if (r)
>   		return r;
>   
> -	ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
> -	if (ring->ring_size) {
> -		r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
> -				     RADEON_CP_PACKET2);
> -		if (!r)
> -			r = uvd_v1_0_init(rdev);
> -
> -		if (r)
> -			DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
> -	}
> +	rv770_uvd_resume(rdev);
>   
>   	r = radeon_ib_pool_init(rdev);
>   	if (r) {
> @@ -1831,8 +1894,10 @@ int rv770_suspend(struct radeon_device *rdev)
>   {
>   	radeon_pm_suspend(rdev);
>   	radeon_audio_fini(rdev);
> -	uvd_v1_0_fini(rdev);
> -	radeon_uvd_suspend(rdev);
> +	if (rdev->has_uvd) {
> +		uvd_v1_0_fini(rdev);
> +		radeon_uvd_suspend(rdev);
> +	}
>   	r700_cp_stop(rdev);
>   	r600_dma_stop(rdev);
>   	r600_irq_suspend(rdev);
> @@ -1917,12 +1982,7 @@ int rv770_init(struct radeon_device *rdev)
>   	rdev->ring[R600_RING_TYPE_DMA_INDEX].ring_obj = NULL;
>   	r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX], 64 * 1024);
>   
> -	r = radeon_uvd_init(rdev);
> -	if (!r) {
> -		rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_obj = NULL;
> -		r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX],
> -			       4096);
> -	}
> +	rv770_uvd_init(rdev);
>   
>   	rdev->ih.ring_obj = NULL;
>   	r600_ih_ring_init(rdev, 64 * 1024);
> @@ -1957,8 +2017,10 @@ void rv770_fini(struct radeon_device *rdev)
>   	radeon_wb_fini(rdev);
>   	radeon_ib_pool_fini(rdev);
>   	radeon_irq_kms_fini(rdev);
> -	uvd_v1_0_fini(rdev);
> -	radeon_uvd_fini(rdev);
> +	if (rdev->has_uvd) {
> +		uvd_v1_0_fini(rdev);
> +		radeon_uvd_fini(rdev);
> +	}
>   	rv770_pcie_gart_fini(rdev);
>   	r600_vram_scratch_fini(rdev);
>   	radeon_gem_fini(rdev);
> diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
> index e894be2..7d8d5f5 100644
> --- a/drivers/gpu/drm/radeon/si.c
> +++ b/drivers/gpu/drm/radeon/si.c
> @@ -6868,6 +6868,142 @@ restart_ih:
>   /*
>    * startup/shutdown callbacks
>    */
> +
> +static void si_uvd_vce_init(struct radeon_device *rdev)
> +{
> +	struct radeon_ring *ring;
> +	int r;
> +
> +	if (!rdev->has_uvd)
> +		return;
> +
> +	r = radeon_uvd_init(rdev);
> +	if (r)
> +		goto error_uvd;
> +	ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
> +	ring->ring_obj = NULL;
> +	r600_ring_init(rdev, ring, 4096);
> +
> +	r = radeon_vce_init(rdev);
> +	if (r)
> +		goto error_vce;
> +	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);
> +
> +	return;
> +
> +error_vce:
> +	radeon_uvd_fini(rdev);
> +error_uvd:
> +	dev_err(rdev->dev, "UVD/VCE init error (%d).\n", r);
> +	/* On error just disable everything. */
> +	rdev->has_uvd = 0;
> +}
> +
> +static void si_uvd_vce_startup(struct radeon_device *rdev)
> +{
> +	int r;
> +
> +	if (!rdev->has_uvd)
> +		return;
> +
> +	r = uvd_v2_2_resume(rdev);
> +	if (r)
> +		goto error;
> +	r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_UVD_INDEX);
> +	if (r)
> +		goto error_uvd;
> +
> +	r = radeon_vce_resume(rdev);
> +	if (r)
> +		goto error_uvd;
> +	r = vce_v1_0_resume(rdev);
> +	if (r)
> +		goto error_vce;
> +	r = radeon_fence_driver_start_ring(rdev, TN_RING_TYPE_VCE1_INDEX);
> +	if (r)
> +		goto error_vce;
> +	r = radeon_fence_driver_start_ring(rdev, TN_RING_TYPE_VCE2_INDEX);
> +	if (r)
> +		goto error_vce;
> +
> +	return;
> +
> +error_vce:
> +	radeon_vce_suspend(rdev);
> +error_uvd:
> +	radeon_uvd_suspend(rdev);
> +error:
> +	dev_err(rdev->dev, "UVD/VCE startup error (%d).\n", r);
> +	/* On error just disable everything. */
> +	radeon_vce_fini(rdev);
> +	radeon_uvd_fini(rdev);
> +	rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
> +	rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size = 0;
> +	rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_size = 0;
> +	rdev->has_uvd = 0;
> +}
> +
> +static void si_uvd_vce_resume(struct radeon_device *rdev)
> +{
> +	struct radeon_ring *ring;
> +	int r;
> +
> +	if (!rdev->has_uvd)
> +		return;
> +
> +	/* On uvd/vce error we disable uvd/vce so we should have bail above. */
> +	BUG_ON(!rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size);
> +	BUG_ON(!rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size);
> +	BUG_ON(!rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_size);
> +
> +	ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
> +	r = radeon_ring_init(rdev, ring, ring->ring_size, 0, RADEON_CP_PACKET2);
> +	if (r)
> +		goto error;
> +	r = uvd_v1_0_init(rdev);
> +	if (r)
> +		goto error_uvd;
> +
> +	ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
> +	r = radeon_ring_init(rdev, ring, ring->ring_size, 0, VCE_CMD_NO_OP);
> +	if (r)
> +		goto error_vce1;
> +	ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
> +	r = radeon_ring_init(rdev, ring, ring->ring_size, 0, VCE_CMD_NO_OP);
> +	if (r)
> +		goto error_vce2;
> +	r = vce_v1_0_init(rdev);
> +	if (r)
> +		goto error_vce;
> +
> +	return;
> +
> +error_vce:
> +	radeon_ring_fini(rdev, &rdev->ring[TN_RING_TYPE_VCE2_INDEX]);
> +error_vce2:
> +	radeon_ring_fini(rdev, &rdev->ring[TN_RING_TYPE_VCE1_INDEX]);
> +error_vce1:
> +	uvd_v1_0_fini(rdev);
> +error_uvd:
> +	radeon_ring_fini(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX]);
> +error:
> +	dev_err(rdev->dev, "UVD/VCE resume error (%d).\n", r);
> +	/* On error just disable everything. */
> +	radeon_uvd_suspend(rdev);
> +	radeon_vce_suspend(rdev);
> +	radeon_uvd_fini(rdev);
> +	radeon_vce_fini(rdev);
> +	rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
> +	rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size = 0;
> +	rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_size = 0;
> +	rdev->has_uvd = 0;
> +}
> +
>   static int si_startup(struct radeon_device *rdev)
>   {
>   	struct radeon_ring *ring;
> @@ -6946,33 +7082,7 @@ static int si_startup(struct radeon_device *rdev)
>   		return r;
>   	}
>   
> -	if (rdev->has_uvd) {
> -		r = uvd_v2_2_resume(rdev);
> -		if (!r) {
> -			r = radeon_fence_driver_start_ring(rdev,
> -							   R600_RING_TYPE_UVD_INDEX);
> -			if (r)
> -				dev_err(rdev->dev, "UVD fences init error (%d).\n", r);
> -		}
> -		if (r)
> -			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;
> -	}
> +	si_uvd_vce_startup(rdev);
>   
>   	/* Enable IRQ */
>   	if (!rdev->irq.installed) {
> @@ -7030,34 +7140,7 @@ static int si_startup(struct radeon_device *rdev)
>   	if (r)
>   		return r;
>   
> -	if (rdev->has_uvd) {
> -		ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
> -		if (ring->ring_size) {
> -			r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
> -					     RADEON_CP_PACKET2);
> -			if (!r)
> -				r = uvd_v1_0_init(rdev);
> -			if (r)
> -				DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
> -		}
> -	}
> -
> -	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);
> +	si_uvd_vce_resume(rdev);
>   
>   	r = radeon_ib_pool_init(rdev);
>   	if (r) {
> @@ -7216,25 +7299,7 @@ int si_init(struct radeon_device *rdev)
>   	ring->ring_obj = NULL;
>   	r600_ring_init(rdev, ring, 64 * 1024);
>   
> -	if (rdev->has_uvd) {
> -		r = radeon_uvd_init(rdev);
> -		if (!r) {
> -			ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
> -			ring->ring_obj = NULL;
> -			r600_ring_init(rdev, ring, 4096);
> -		}
> -	}
> -
> -	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);
> -	}
> +	si_uvd_vce_init(rdev);
>   
>   	rdev->ih.ring_obj = NULL;
>   	r600_ih_ring_init(rdev, 64 * 1024);
> diff --git a/drivers/gpu/drm/radeon/uvd_v4_2.c b/drivers/gpu/drm/radeon/uvd_v4_2.c
> index d04d507..d7e4807 100644
> --- a/drivers/gpu/drm/radeon/uvd_v4_2.c
> +++ b/drivers/gpu/drm/radeon/uvd_v4_2.c
> @@ -39,6 +39,11 @@ int uvd_v4_2_resume(struct radeon_device *rdev)
>   {
>   	uint64_t addr;
>   	uint32_t size;
> +	int r;
> +
> +	r = radeon_uvd_resume(rdev);
> +	if (r)
> +		return r;
>   
>   	/* programm the VCPU memory controller bits 0-27 */
>   	addr = rdev->uvd.gpu_addr >> 3;



More information about the dri-devel mailing list