summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-05-23 11:48:48 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2016-05-23 11:48:48 -0700
commit1d6da87a3241deb13d073c4125d19ed0e5a0c62c (patch)
tree42b7a9842618dad2afe7db9709cc6217ced03120 /drivers/gpu/drm/radeon
parent1f40c49570eb01436786a9b5845c4469a9a1f362 (diff)
parenta39ed680bddb1ead592e22ed812c7e47286bfc03 (diff)
downloadop-kernel-dev-1d6da87a3241deb13d073c4125d19ed0e5a0c62c.zip
op-kernel-dev-1d6da87a3241deb13d073c4125d19ed0e5a0c62c.tar.gz
Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
Pull drm updates from Dave Airlie: "Here's the main drm pull request for 4.7, it's been a busy one, and I've been a bit more distracted in real life this merge window. Lots more ARM drivers, not sure if it'll ever end. I think I've at least one more coming the next merge window. But changes are all over the place, support for AMD Polaris GPUs is in here, some missing GM108 support for nouveau (found in some Lenovos), a bunch of MST and skylake fixes. I've also noticed a few fixes from Arnd in my inbox, that I'll try and get in asap, but I didn't think they should hold this up. New drivers: - Hisilicon kirin display driver - Mediatek MT8173 display driver - ARC PGU - bitstreamer on Synopsys ARC SDP boards - Allwinner A13 initial RGB output driver - Analogix driver for DisplayPort IP found in exynos and rockchip DRM Core: - UAPI headers fixes and C++ safety - DRM connector reference counting - DisplayID mode parsing for Dell 5K monitors - Removal of struct_mutex from drivers - Connector registration cleanups - MST robustness fixes - MAINTAINERS updates - Lockless GEM object freeing - Generic fbdev deferred IO support panel: - Support for a bunch of new panels i915: - VBT refactoring - PLL computation cleanups - DSI support for BXT - Color manager support - More atomic patches - GEM improvements - GuC fw loading fixes - DP detection fixes - SKL GPU hang fixes - Lots of BXT fixes radeon/amdgpu: - Initial Polaris support - GPUVM/Scheduler/Clock/Power improvements - ASYNC pageflip support - New mesa feature support nouveau: - GM108 support - Power sensor support improvements - GR init + ucode fixes. - Use GPU provided topology information vmwgfx: - Add host messaging support gma500: - Some cleanups and fixes atmel: - Bridge support - Async atomic commit support fsl-dcu: - Timing controller for LCD support - Pixel clock polarity support rcar-du: - Misc fixes exynos: - Pipeline clock support - Exynoss4533 SoC support - HW trigger mode support - export HDMI_PHY clock - DECON5433 fixes - Use generic prime functions - use DMA mapping APIs rockchip: - Lots of little fixes vc4: - Render node support - Gamma ramp support - DPI output support msm: - Mostly cleanups and fixes - Conversion to generic struct fence etnaviv: - Fix for prime buffer handling - Allow hangcheck to be coalesced with other wakeups tegra: - Gamme table size fix" * 'drm-next' of git://people.freedesktop.org/~airlied/linux: (1050 commits) drm/edid: add displayid detailed 1 timings to the modelist. (v1.1) drm/edid: move displayid validation to it's own function. drm/displayid: Iterate over all DisplayID blocks drm/edid: move displayid tiled block parsing into separate function. drm: Nuke ->vblank_disable_allowed drm/vmwgfx: Report vmwgfx version to vmware.log drm/vmwgfx: Add VMWare host messaging capability drm/vmwgfx: Kill some lockdep warnings drm/nouveau/gr/gf100-: fix race condition in fecs/gpccs ucode drm/nouveau/core: recognise GM108 chipsets drm/nouveau/gr/gm107-: fix touching non-existent ppcs in attrib cb setup drm/nouveau/gr/gk104-: share implementation of ppc exception init drm/nouveau/gr/gk104-: move rop_active_fbps init to nonctx drm/nouveau/bios/pll: check BIT table version before trying to parse it drm/nouveau/bios/pll: prevent oops when limits table can't be parsed drm/nouveau/volt/gk104: round up in gk104_volt_set drm/nouveau/fb/gm200: setup mmu debug buffer registers at init() drm/nouveau/fb/gk20a,gm20b: setup mmu debug buffer registers at init() drm/nouveau/fb/gf100-: allocate mmu debug buffers drm/nouveau/fb: allow chipset-specific actions for oneinit() ...
Diffstat (limited to 'drivers/gpu/drm/radeon')
-rw-r--r--drivers/gpu/drm/radeon/atombios_crtc.c24
-rw-r--r--drivers/gpu/drm/radeon/cik.c252
-rw-r--r--drivers/gpu/drm/radeon/cikd.h1
-rw-r--r--drivers/gpu/drm/radeon/evergreen.c120
-rw-r--r--drivers/gpu/drm/radeon/evergreen_cs.c66
-rw-r--r--drivers/gpu/drm/radeon/evergreend.h43
-rw-r--r--drivers/gpu/drm/radeon/ni.c246
-rw-r--r--drivers/gpu/drm/radeon/r100.c10
-rw-r--r--drivers/gpu/drm/radeon/r300.c2
-rw-r--r--drivers/gpu/drm/radeon/r600.c112
-rw-r--r--drivers/gpu/drm/radeon/radeon.h26
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.c16
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.h25
-rw-r--r--drivers/gpu/drm/radeon/radeon_cs.c3
-rw-r--r--drivers/gpu/drm/radeon/radeon_cursor.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c10
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c10
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.c25
-rw-r--r--drivers/gpu/drm/radeon/radeon_gem.c16
-rw-r--r--drivers/gpu/drm/radeon/radeon_irq_kms.c1
-rw-r--r--drivers/gpu/drm/radeon/radeon_object.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_object.h2
-rw-r--r--drivers/gpu/drm/radeon/radeon_ttm.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_uvd.c88
-rw-r--r--drivers/gpu/drm/radeon/rs600.c12
-rw-r--r--drivers/gpu/drm/radeon/rv770.c106
-rw-r--r--drivers/gpu/drm/radeon/si.c250
-rw-r--r--drivers/gpu/drm/radeon/uvd_v1_0.c5
-rw-r--r--drivers/gpu/drm/radeon/uvd_v2_2.c5
-rw-r--r--drivers/gpu/drm/radeon/uvd_v4_2.c16
30 files changed, 1077 insertions, 423 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index 532127c..2e216e2 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -1375,6 +1375,11 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
break;
}
+ /* Make sure surface address is updated at vertical blank rather than
+ * horizontal blank
+ */
+ WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, 0);
+
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
upper_32_bits(fb_location));
WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
@@ -1427,12 +1432,6 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
(viewport_w << 16) | viewport_h);
- /* pageflip setup */
- /* make sure flip is at vb rather than hb */
- tmp = RREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset);
- tmp &= ~EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN;
- WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp);
-
/* set pageflip to happen only at start of vblank interval (front porch) */
WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 3);
@@ -1466,7 +1465,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
uint64_t fb_location;
uint32_t fb_format, fb_pitch_pixels, tiling_flags;
u32 fb_swap = R600_D1GRPH_SWAP_ENDIAN_NONE;
- u32 tmp, viewport_w, viewport_h;
+ u32 viewport_w, viewport_h;
int r;
bool bypass_lut = false;
@@ -1581,6 +1580,11 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
else
WREG32(AVIVO_D2VGA_CONTROL, 0);
+ /* Make sure surface address is update at vertical blank rather than
+ * horizontal blank
+ */
+ WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, 0);
+
if (rdev->family >= CHIP_RV770) {
if (radeon_crtc->crtc_id) {
WREG32(R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location));
@@ -1627,12 +1631,6 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
(viewport_w << 16) | viewport_h);
- /* pageflip setup */
- /* make sure flip is at vb rather than hb */
- tmp = RREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset);
- tmp &= ~AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN;
- WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp);
-
/* set pageflip to happen only at start of vblank interval (front porch) */
WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 3);
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index 8ac82df..ba192a3 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -5261,15 +5261,21 @@ static void cik_gpu_pci_config_reset(struct radeon_device *rdev)
* cik_asic_reset - soft reset GPU
*
* @rdev: radeon_device pointer
+ * @hard: force hard reset
*
* Look up which blocks are hung and attempt
* to reset them.
* Returns 0 for success.
*/
-int cik_asic_reset(struct radeon_device *rdev)
+int cik_asic_reset(struct radeon_device *rdev, bool hard)
{
u32 reset_mask;
+ if (hard) {
+ cik_gpu_pci_config_reset(rdev);
+ return 0;
+ }
+
reset_mask = cik_gpu_check_soft_reset(rdev);
if (reset_mask)
@@ -8137,6 +8143,164 @@ restart_ih:
/*
* startup/shutdown callbacks
*/
+static void cik_uvd_init(struct radeon_device *rdev)
+{
+ int r;
+
+ if (!rdev->has_uvd)
+ return;
+
+ r = radeon_uvd_init(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failed UVD (%d) init.\n", r);
+ /*
+ * At this point rdev->uvd.vcpu_bo is NULL which trickles down
+ * to early fails cik_uvd_start() and thus nothing happens
+ * there. So it is pointless to try to go through that code
+ * hence why we disable uvd here.
+ */
+ rdev->has_uvd = 0;
+ return;
+ }
+ rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_obj = NULL;
+ r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX], 4096);
+}
+
+static void cik_uvd_start(struct radeon_device *rdev)
+{
+ int r;
+
+ if (!rdev->has_uvd)
+ return;
+
+ r = radeon_uvd_resume(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failed UVD resume (%d).\n", r);
+ goto error;
+ }
+ r = uvd_v4_2_resume(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failed UVD 4.2 resume (%d).\n", r);
+ goto error;
+ }
+ 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);
+ goto error;
+ }
+ return;
+
+error:
+ rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
+}
+
+static void cik_uvd_resume(struct radeon_device *rdev)
+{
+ struct radeon_ring *ring;
+ int r;
+
+ if (!rdev->has_uvd || !rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size)
+ return;
+
+ ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
+ r = radeon_ring_init(rdev, ring, ring->ring_size, 0, RADEON_CP_PACKET2);
+ if (r) {
+ dev_err(rdev->dev, "failed initializing UVD ring (%d).\n", r);
+ return;
+ }
+ r = uvd_v1_0_init(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failed initializing UVD (%d).\n", r);
+ return;
+ }
+}
+
+static void cik_vce_init(struct radeon_device *rdev)
+{
+ int r;
+
+ if (!rdev->has_vce)
+ return;
+
+ r = radeon_vce_init(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failed VCE (%d) init.\n", r);
+ /*
+ * At this point rdev->vce.vcpu_bo is NULL which trickles down
+ * to early fails cik_vce_start() and thus nothing happens
+ * there. So it is pointless to try to go through that code
+ * hence why we disable vce here.
+ */
+ rdev->has_vce = 0;
+ return;
+ }
+ rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_obj = NULL;
+ r600_ring_init(rdev, &rdev->ring[TN_RING_TYPE_VCE1_INDEX], 4096);
+ rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_obj = NULL;
+ r600_ring_init(rdev, &rdev->ring[TN_RING_TYPE_VCE2_INDEX], 4096);
+}
+
+static void cik_vce_start(struct radeon_device *rdev)
+{
+ int r;
+
+ if (!rdev->has_vce)
+ return;
+
+ r = radeon_vce_resume(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failed VCE resume (%d).\n", r);
+ goto error;
+ }
+ r = vce_v2_0_resume(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failed VCE resume (%d).\n", r);
+ goto error;
+ }
+ r = radeon_fence_driver_start_ring(rdev, TN_RING_TYPE_VCE1_INDEX);
+ if (r) {
+ dev_err(rdev->dev, "failed initializing VCE1 fences (%d).\n", r);
+ goto error;
+ }
+ r = radeon_fence_driver_start_ring(rdev, TN_RING_TYPE_VCE2_INDEX);
+ if (r) {
+ dev_err(rdev->dev, "failed initializing VCE2 fences (%d).\n", r);
+ goto error;
+ }
+ return;
+
+error:
+ rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size = 0;
+ rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_size = 0;
+}
+
+static void cik_vce_resume(struct radeon_device *rdev)
+{
+ struct radeon_ring *ring;
+ int r;
+
+ if (!rdev->has_vce || !rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size)
+ return;
+
+ ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
+ r = radeon_ring_init(rdev, ring, ring->ring_size, 0, VCE_CMD_NO_OP);
+ if (r) {
+ dev_err(rdev->dev, "failed initializing VCE1 ring (%d).\n", r);
+ return;
+ }
+ ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
+ r = radeon_ring_init(rdev, ring, ring->ring_size, 0, VCE_CMD_NO_OP);
+ if (r) {
+ dev_err(rdev->dev, "failed initializing VCE1 ring (%d).\n", r);
+ return;
+ }
+ r = vce_v1_0_init(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failed initializing VCE (%d).\n", r);
+ return;
+ }
+}
+
/**
* cik_startup - program the asic to a functional state
*
@@ -8239,34 +8403,8 @@ 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_start(rdev);
+ cik_vce_start(rdev);
/* Enable IRQ */
if (!rdev->irq.installed) {
@@ -8342,32 +8480,8 @@ 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_resume(rdev);
+ cik_vce_resume(rdev);
r = radeon_ib_pool_init(rdev);
if (r) {
@@ -8443,9 +8557,12 @@ 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);
+ }
+ if (rdev->has_vce)
+ radeon_vce_suspend(rdev);
cik_fini_pg(rdev);
cik_fini_cg(rdev);
cik_irq_suspend(rdev);
@@ -8571,23 +8688,8 @@ 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_init(rdev);
+ cik_vce_init(rdev);
rdev->ih.ring_obj = NULL;
r600_ih_ring_init(rdev, 64 * 1024);
diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h
index 391ff9d..cead228 100644
--- a/drivers/gpu/drm/radeon/cikd.h
+++ b/drivers/gpu/drm/radeon/cikd.h
@@ -2071,6 +2071,7 @@
#define UVD_UDEC_DBW_ADDR_CONFIG 0xef54
#define UVD_LMI_EXT40_ADDR 0xf498
+#define UVD_GP_SCRATCH4 0xf4e0
#define UVD_LMI_ADDR_EXT 0xf594
#define UVD_VCPU_CACHE_OFFSET0 0xf608
#define UVD_VCPU_CACHE_SIZE0 0xf60c
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 34f7a29..db275b7 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -1407,11 +1407,14 @@ void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc)
* Triggers the actual pageflip by updating the primary
* surface base address (evergreen+).
*/
-void evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
+void evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base,
+ bool async)
{
struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
/* update the scanout addresses */
+ WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset,
+ async ? EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN : 0);
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
upper_32_bits(crtc_base));
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
@@ -1864,7 +1867,8 @@ void evergreen_hpd_init(struct radeon_device *rdev)
break;
}
radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
- enabled |= 1 << radeon_connector->hpd.hpd;
+ if (radeon_connector->hpd.hpd != RADEON_HPD_NONE)
+ enabled |= 1 << radeon_connector->hpd.hpd;
}
radeon_irq_kms_enable_hpd(rdev, enabled);
}
@@ -1907,7 +1911,8 @@ void evergreen_hpd_fini(struct radeon_device *rdev)
default:
break;
}
- disabled |= 1 << radeon_connector->hpd.hpd;
+ if (radeon_connector->hpd.hpd != RADEON_HPD_NONE)
+ disabled |= 1 << radeon_connector->hpd.hpd;
}
radeon_irq_kms_disable_hpd(rdev, disabled);
}
@@ -4136,10 +4141,15 @@ void evergreen_gpu_pci_config_reset(struct radeon_device *rdev)
}
}
-int evergreen_asic_reset(struct radeon_device *rdev)
+int evergreen_asic_reset(struct radeon_device *rdev, bool hard)
{
u32 reset_mask;
+ if (hard) {
+ evergreen_gpu_pci_config_reset(rdev);
+ return 0;
+ }
+
reset_mask = evergreen_gpu_check_soft_reset(rdev);
if (reset_mask)
@@ -5515,6 +5525,73 @@ restart_ih:
return IRQ_HANDLED;
}
+static void evergreen_uvd_init(struct radeon_device *rdev)
+{
+ int r;
+
+ if (!rdev->has_uvd)
+ return;
+
+ r = radeon_uvd_init(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failed UVD (%d) init.\n", r);
+ /*
+ * At this point rdev->uvd.vcpu_bo is NULL which trickles down
+ * to early fails uvd_v2_2_resume() and thus nothing happens
+ * there. So it is pointless to try to go through that code
+ * hence why we disable uvd here.
+ */
+ rdev->has_uvd = 0;
+ return;
+ }
+ rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_obj = NULL;
+ r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX], 4096);
+}
+
+static void evergreen_uvd_start(struct radeon_device *rdev)
+{
+ int r;
+
+ if (!rdev->has_uvd)
+ return;
+
+ r = uvd_v2_2_resume(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failed UVD resume (%d).\n", r);
+ goto error;
+ }
+ 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);
+ goto error;
+ }
+ return;
+
+error:
+ rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
+}
+
+static void evergreen_uvd_resume(struct radeon_device *rdev)
+{
+ struct radeon_ring *ring;
+ int r;
+
+ if (!rdev->has_uvd || !rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size)
+ return;
+
+ ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
+ r = radeon_ring_init(rdev, ring, ring->ring_size, 0, RADEON_CP_PACKET2);
+ if (r) {
+ dev_err(rdev->dev, "failed initializing UVD ring (%d).\n", r);
+ return;
+ }
+ r = uvd_v1_0_init(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failed initializing UVD (%d).\n", r);
+ return;
+ }
+}
+
static int evergreen_startup(struct radeon_device *rdev)
{
struct radeon_ring *ring;
@@ -5579,16 +5656,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_start(rdev);
/* Enable IRQ */
if (!rdev->irq.installed) {
@@ -5627,16 +5695,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) {
@@ -5691,8 +5750,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);
@@ -5793,12 +5854,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);
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c
index 9e93205..0d3f744 100644
--- a/drivers/gpu/drm/radeon/evergreen_cs.c
+++ b/drivers/gpu/drm/radeon/evergreen_cs.c
@@ -2608,6 +2608,51 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
}
}
break;
+ case PACKET3_SET_APPEND_CNT:
+ {
+ uint32_t areg;
+ uint32_t allowed_reg_base;
+ uint32_t source_sel;
+ if (pkt->count != 2) {
+ DRM_ERROR("bad SET_APPEND_CNT (invalid count)\n");
+ return -EINVAL;
+ }
+
+ allowed_reg_base = GDS_APPEND_COUNT_0;
+ allowed_reg_base -= PACKET3_SET_CONTEXT_REG_START;
+ allowed_reg_base >>= 2;
+
+ areg = idx_value >> 16;
+ if (areg < allowed_reg_base || areg > (allowed_reg_base + 11)) {
+ dev_warn(p->dev, "forbidden register for append cnt 0x%08x at %d\n",
+ areg, idx);
+ return -EINVAL;
+ }
+
+ source_sel = G_PACKET3_SET_APPEND_CNT_SRC_SELECT(idx_value);
+ if (source_sel == PACKET3_SAC_SRC_SEL_MEM) {
+ uint64_t offset;
+ uint32_t swap;
+ r = radeon_cs_packet_next_reloc(p, &reloc, 0);
+ if (r) {
+ DRM_ERROR("bad SET_APPEND_CNT (missing reloc)\n");
+ return -EINVAL;
+ }
+ offset = radeon_get_ib_value(p, idx + 1);
+ swap = offset & 0x3;
+ offset &= ~0x3;
+
+ offset += ((u64)(radeon_get_ib_value(p, idx + 2) & 0xff)) << 32;
+
+ offset += reloc->gpu_offset;
+ ib[idx+1] = (offset & 0xfffffffc) | swap;
+ ib[idx+2] = upper_32_bits(offset) & 0xff;
+ } else {
+ DRM_ERROR("bad SET_APPEND_CNT (unsupported operation)\n");
+ return -EINVAL;
+ }
+ break;
+ }
case PACKET3_NOP:
break;
default:
@@ -3438,6 +3483,27 @@ static int evergreen_vm_packet3_check(struct radeon_device *rdev,
}
}
break;
+ case PACKET3_SET_APPEND_CNT: {
+ uint32_t areg;
+ uint32_t allowed_reg_base;
+
+ if (pkt->count != 2) {
+ DRM_ERROR("bad SET_APPEND_CNT (invalid count)\n");
+ return -EINVAL;
+ }
+
+ allowed_reg_base = GDS_APPEND_COUNT_0;
+ allowed_reg_base -= PACKET3_SET_CONTEXT_REG_START;
+ allowed_reg_base >>= 2;
+
+ areg = idx_value >> 16;
+ if (areg < allowed_reg_base || areg > (allowed_reg_base + 11)) {
+ DRM_ERROR("forbidden register for append cnt 0x%08x at %d\n",
+ areg, idx);
+ return -EINVAL;
+ }
+ break;
+ }
default:
return -EINVAL;
}
diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h
index 13b6029..0b174e1 100644
--- a/drivers/gpu/drm/radeon/evergreend.h
+++ b/drivers/gpu/drm/radeon/evergreend.h
@@ -1689,6 +1689,36 @@
#define PACKET3_SET_CONTEXT_REG_INDIRECT 0x73
#define PACKET3_SET_RESOURCE_INDIRECT 0x74
#define PACKET3_SET_APPEND_CNT 0x75
+/* SET_APPEND_CNT - documentation
+ * 1. header
+ * 2. COMMAND
+ * 1:0 - SOURCE SEL
+ * 15:2 - Reserved
+ * 31:16 - WR_REG_OFFSET - context register to write source data to.
+ * (one of R_02872C_GDS_APPEND_COUNT_0-11)
+ * 3. CONTROL
+ * (for source == mem)
+ * 31:2 SRC_ADDRESS_LO
+ * 0:1 SWAP
+ * (for source == GDS)
+ * 31:0 GDS offset
+ * (for source == DATA)
+ * 31:0 DATA
+ * (for source == REG)
+ * 31:0 REG
+ * 4. SRC_ADDRESS_HI[7:0]
+ * kernel driver 2.44 only supports SRC == MEM.
+ */
+#define PACKET3_SET_APPEND_CNT_SRC_SELECT(x) ((x) << 0)
+#define G_PACKET3_SET_APPEND_CNT_SRC_SELECT(x) ((x & 0x3) >> 0)
+/* source is from the data in CONTROL */
+#define PACKET3_SAC_SRC_SEL_DATA 0x0
+/* source is from register */
+#define PACKET3_SAC_SRC_SEL_REG 0x1
+/* source is from GDS offset in CONTROL */
+#define PACKET3_SAC_SRC_SEL_GDS 0x2
+/* source is from memory address */
+#define PACKET3_SAC_SRC_SEL_MEM 0x3
#define SQ_RESOURCE_CONSTANT_WORD7_0 0x3001c
#define S__SQ_CONSTANT_TYPE(x) (((x) & 3) << 30)
@@ -2005,6 +2035,19 @@
#define GDS_ADDR_BASE 0x28720
+#define GDS_APPEND_COUNT_0 0x2872C
+#define GDS_APPEND_COUNT_1 0x28730
+#define GDS_APPEND_COUNT_2 0x28734
+#define GDS_APPEND_COUNT_3 0x28738
+#define GDS_APPEND_COUNT_4 0x2873C
+#define GDS_APPEND_COUNT_5 0x28740
+#define GDS_APPEND_COUNT_6 0x28744
+#define GDS_APPEND_COUNT_7 0x28748
+#define GDS_APPEND_COUNT_8 0x2874c
+#define GDS_APPEND_COUNT_9 0x28750
+#define GDS_APPEND_COUNT_10 0x28754
+#define GDS_APPEND_COUNT_11 0x28758
+
#define CB_IMMED0_BASE 0x28b9c
#define CB_IMMED1_BASE 0x28ba0
#define CB_IMMED2_BASE 0x28ba4
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index b88d63c9..4a3d7ca 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -1959,10 +1959,15 @@ static void cayman_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
evergreen_print_gpu_status_regs(rdev);
}
-int cayman_asic_reset(struct radeon_device *rdev)
+int cayman_asic_reset(struct radeon_device *rdev, bool hard)
{
u32 reset_mask;
+ if (hard) {
+ evergreen_gpu_pci_config_reset(rdev);
+ return 0;
+ }
+
reset_mask = cayman_gpu_check_soft_reset(rdev);
if (reset_mask)
@@ -2002,6 +2007,160 @@ bool cayman_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
return radeon_ring_test_lockup(rdev, ring);
}
+static void cayman_uvd_init(struct radeon_device *rdev)
+{
+ int r;
+
+ if (!rdev->has_uvd)
+ return;
+
+ r = radeon_uvd_init(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failed UVD (%d) init.\n", r);
+ /*
+ * At this point rdev->uvd.vcpu_bo is NULL which trickles down
+ * to early fails uvd_v2_2_resume() and thus nothing happens
+ * there. So it is pointless to try to go through that code
+ * hence why we disable uvd here.
+ */
+ rdev->has_uvd = 0;
+ return;
+ }
+ rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_obj = NULL;
+ r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX], 4096);
+}
+
+static void cayman_uvd_start(struct radeon_device *rdev)
+{
+ int r;
+
+ if (!rdev->has_uvd)
+ return;
+
+ r = uvd_v2_2_resume(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failed UVD resume (%d).\n", r);
+ goto error;
+ }
+ 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);
+ goto error;
+ }
+ return;
+
+error:
+ rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
+}
+
+static void cayman_uvd_resume(struct radeon_device *rdev)
+{
+ struct radeon_ring *ring;
+ int r;
+
+ if (!rdev->has_uvd || !rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size)
+ return;
+
+ ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
+ r = radeon_ring_init(rdev, ring, ring->ring_size, 0, RADEON_CP_PACKET2);
+ if (r) {
+ dev_err(rdev->dev, "failed initializing UVD ring (%d).\n", r);
+ return;
+ }
+ r = uvd_v1_0_init(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failed initializing UVD (%d).\n", r);
+ return;
+ }
+}
+
+static void cayman_vce_init(struct radeon_device *rdev)
+{
+ int r;
+
+ /* Only set for CHIP_ARUBA */
+ if (!rdev->has_vce)
+ return;
+
+ r = radeon_vce_init(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failed VCE (%d) init.\n", r);
+ /*
+ * At this point rdev->vce.vcpu_bo is NULL which trickles down
+ * to early fails cayman_vce_start() and thus nothing happens
+ * there. So it is pointless to try to go through that code
+ * hence why we disable vce here.
+ */
+ rdev->has_vce = 0;
+ return;
+ }
+ rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_obj = NULL;
+ r600_ring_init(rdev, &rdev->ring[TN_RING_TYPE_VCE1_INDEX], 4096);
+ rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_obj = NULL;
+ r600_ring_init(rdev, &rdev->ring[TN_RING_TYPE_VCE2_INDEX], 4096);
+}
+
+static void cayman_vce_start(struct radeon_device *rdev)
+{
+ int r;
+
+ if (!rdev->has_vce)
+ return;
+
+ r = radeon_vce_resume(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failed VCE resume (%d).\n", r);
+ goto error;
+ }
+ r = vce_v1_0_resume(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failed VCE resume (%d).\n", r);
+ goto error;
+ }
+ r = radeon_fence_driver_start_ring(rdev, TN_RING_TYPE_VCE1_INDEX);
+ if (r) {
+ dev_err(rdev->dev, "failed initializing VCE1 fences (%d).\n", r);
+ goto error;
+ }
+ r = radeon_fence_driver_start_ring(rdev, TN_RING_TYPE_VCE2_INDEX);
+ if (r) {
+ dev_err(rdev->dev, "failed initializing VCE2 fences (%d).\n", r);
+ goto error;
+ }
+ return;
+
+error:
+ rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size = 0;
+ rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_size = 0;
+}
+
+static void cayman_vce_resume(struct radeon_device *rdev)
+{
+ struct radeon_ring *ring;
+ int r;
+
+ if (!rdev->has_vce || !rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size)
+ return;
+
+ ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
+ r = radeon_ring_init(rdev, ring, ring->ring_size, 0, 0x0);
+ if (r) {
+ dev_err(rdev->dev, "failed initializing VCE1 ring (%d).\n", r);
+ return;
+ }
+ ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
+ r = radeon_ring_init(rdev, ring, ring->ring_size, 0, 0x0);
+ if (r) {
+ dev_err(rdev->dev, "failed initializing VCE1 ring (%d).\n", r);
+ return;
+ }
+ r = vce_v1_0_init(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failed initializing VCE (%d).\n", r);
+ return;
+ }
+}
+
static int cayman_startup(struct radeon_device *rdev)
{
struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
@@ -2056,34 +2215,8 @@ 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_start(rdev);
+ cayman_vce_start(rdev);
r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_CP1_INDEX);
if (r) {
@@ -2152,30 +2285,8 @@ 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_resume(rdev);
+ cayman_vce_resume(rdev);
r = radeon_ib_pool_init(rdev);
if (r) {
@@ -2230,8 +2341,10 @@ 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);
+ }
evergreen_irq_suspend(rdev);
radeon_wb_disable(rdev);
cayman_pcie_gart_disable(rdev);
@@ -2325,25 +2438,8 @@ 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_init(rdev);
+ cayman_vce_init(rdev);
rdev->ih.ring_obj = NULL;
r600_ih_ring_init(rdev, 64 * 1024);
@@ -2398,7 +2494,7 @@ void cayman_fini(struct radeon_device *rdev)
radeon_irq_kms_fini(rdev);
uvd_v1_0_fini(rdev);
radeon_uvd_fini(rdev);
- if (rdev->family == CHIP_ARUBA)
+ if (rdev->has_vce)
radeon_vce_fini(rdev);
cayman_pcie_gart_fini(rdev);
r600_vram_scratch_fini(rdev);
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 6e478a2..f25994b 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -153,7 +153,7 @@ void r100_wait_for_vblank(struct radeon_device *rdev, int crtc)
* bit to go high, when it does, we release the lock, and allow the
* double buffered update to take place.
*/
-void r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
+void r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base, bool async)
{
struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
u32 tmp = ((u32)crtc_base) | RADEON_CRTC_OFFSET__OFFSET_LOCK;
@@ -592,7 +592,8 @@ void r100_hpd_init(struct radeon_device *rdev)
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
- enable |= 1 << radeon_connector->hpd.hpd;
+ if (radeon_connector->hpd.hpd != RADEON_HPD_NONE)
+ enable |= 1 << radeon_connector->hpd.hpd;
radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
}
radeon_irq_kms_enable_hpd(rdev, enable);
@@ -614,7 +615,8 @@ void r100_hpd_fini(struct radeon_device *rdev)
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
- disable |= 1 << radeon_connector->hpd.hpd;
+ if (radeon_connector->hpd.hpd != RADEON_HPD_NONE)
+ disable |= 1 << radeon_connector->hpd.hpd;
}
radeon_irq_kms_disable_hpd(rdev, disable);
}
@@ -2555,7 +2557,7 @@ void r100_bm_disable(struct radeon_device *rdev)
mdelay(1);
}
-int r100_asic_reset(struct radeon_device *rdev)
+int r100_asic_reset(struct radeon_device *rdev, bool hard)
{
struct r100_mc_save save;
u32 status, tmp;
diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c
index 718b12b..7e417d8 100644
--- a/drivers/gpu/drm/radeon/r300.c
+++ b/drivers/gpu/drm/radeon/r300.c
@@ -410,7 +410,7 @@ static void r300_gpu_init(struct radeon_device *rdev)
rdev->num_gb_pipes, rdev->num_z_pipes);
}
-int r300_asic_reset(struct radeon_device *rdev)
+int r300_asic_reset(struct radeon_device *rdev, bool hard)
{
struct r100_mc_save save;
u32 status, tmp;
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index f86ab69..9247e7d 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -1002,7 +1002,8 @@ void r600_hpd_init(struct radeon_device *rdev)
break;
}
}
- enable |= 1 << radeon_connector->hpd.hpd;
+ if (radeon_connector->hpd.hpd != RADEON_HPD_NONE)
+ enable |= 1 << radeon_connector->hpd.hpd;
radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
}
radeon_irq_kms_enable_hpd(rdev, enable);
@@ -1055,7 +1056,8 @@ void r600_hpd_fini(struct radeon_device *rdev)
break;
}
}
- disable |= 1 << radeon_connector->hpd.hpd;
+ if (radeon_connector->hpd.hpd != RADEON_HPD_NONE)
+ disable |= 1 << radeon_connector->hpd.hpd;
}
radeon_irq_kms_disable_hpd(rdev, disable);
}
@@ -1871,10 +1873,15 @@ static void r600_gpu_pci_config_reset(struct radeon_device *rdev)
}
}
-int r600_asic_reset(struct radeon_device *rdev)
+int r600_asic_reset(struct radeon_device *rdev, bool hard)
{
u32 reset_mask;
+ if (hard) {
+ r600_gpu_pci_config_reset(rdev);
+ return 0;
+ }
+
reset_mask = r600_gpu_check_soft_reset(rdev);
if (reset_mask)
@@ -3035,6 +3042,73 @@ void r600_clear_surface_reg(struct radeon_device *rdev, int reg)
/* FIXME: implement */
}
+static void r600_uvd_init(struct radeon_device *rdev)
+{
+ int r;
+
+ if (!rdev->has_uvd)
+ return;
+
+ r = radeon_uvd_init(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failed UVD (%d) init.\n", r);
+ /*
+ * At this point rdev->uvd.vcpu_bo is NULL which trickles down
+ * to early fails uvd_v1_0_resume() and thus nothing happens
+ * there. So it is pointless to try to go through that code
+ * hence why we disable uvd here.
+ */
+ rdev->has_uvd = 0;
+ return;
+ }
+ rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_obj = NULL;
+ r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX], 4096);
+}
+
+static void r600_uvd_start(struct radeon_device *rdev)
+{
+ int r;
+
+ if (!rdev->has_uvd)
+ return;
+
+ r = uvd_v1_0_resume(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failed UVD resume (%d).\n", r);
+ goto error;
+ }
+ 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);
+ goto error;
+ }
+ return;
+
+error:
+ rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
+}
+
+static void r600_uvd_resume(struct radeon_device *rdev)
+{
+ struct radeon_ring *ring;
+ int r;
+
+ if (!rdev->has_uvd || !rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size)
+ return;
+
+ ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
+ r = radeon_ring_init(rdev, ring, ring->ring_size, 0, RADEON_CP_PACKET2);
+ if (r) {
+ dev_err(rdev->dev, "failed initializing UVD ring (%d).\n", r);
+ return;
+ }
+ r = uvd_v1_0_init(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failed initializing UVD (%d).\n", r);
+ return;
+ }
+}
+
static int r600_startup(struct radeon_device *rdev)
{
struct radeon_ring *ring;
@@ -3070,17 +3144,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_start(rdev);
/* Enable IRQ */
if (!rdev->irq.installed) {
@@ -3110,17 +3174,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 +3318,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/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 007be29..80b24a4 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -113,6 +113,8 @@ extern int radeon_bapm;
extern int radeon_backlight;
extern int radeon_auxch;
extern int radeon_mst;
+extern int radeon_uvd;
+extern int radeon_vce;
/*
* Copy from radeon_drv.h so we don't have to include both and have conflicting
@@ -744,6 +746,7 @@ struct radeon_flip_work {
struct drm_pending_vblank_event *event;
struct radeon_bo *old_rbo;
struct fence *fence;
+ bool async;
};
struct r500_irq_stat_regs {
@@ -1671,14 +1674,18 @@ int radeon_pm_get_type_index(struct radeon_device *rdev,
/*
* UVD
*/
-#define RADEON_MAX_UVD_HANDLES 10
-#define RADEON_UVD_STACK_SIZE (1024*1024)
-#define RADEON_UVD_HEAP_SIZE (1024*1024)
+#define RADEON_DEFAULT_UVD_HANDLES 10
+#define RADEON_MAX_UVD_HANDLES 30
+#define RADEON_UVD_STACK_SIZE (200*1024)
+#define RADEON_UVD_HEAP_SIZE (256*1024)
+#define RADEON_UVD_SESSION_SIZE (50*1024)
struct radeon_uvd {
+ bool fw_header_present;
struct radeon_bo *vcpu_bo;
void *cpu_addr;
uint64_t gpu_addr;
+ unsigned max_handles;
atomic_t handles[RADEON_MAX_UVD_HANDLES];
struct drm_file *filp[RADEON_MAX_UVD_HANDLES];
unsigned img_size[RADEON_MAX_UVD_HANDLES];
@@ -1852,7 +1859,7 @@ struct radeon_asic {
int (*resume)(struct radeon_device *rdev);
int (*suspend)(struct radeon_device *rdev);
void (*vga_set_state)(struct radeon_device *rdev, bool state);
- int (*asic_reset)(struct radeon_device *rdev);
+ int (*asic_reset)(struct radeon_device *rdev, bool hard);
/* Flush the HDP cache via MMIO */
void (*mmio_hdp_flush)(struct radeon_device *rdev);
/* check if 3D engine is idle */
@@ -1998,7 +2005,7 @@ struct radeon_asic {
} dpm;
/* pageflipping */
struct {
- void (*page_flip)(struct radeon_device *rdev, int crtc, u64 crtc_base);
+ void (*page_flip)(struct radeon_device *rdev, int crtc, u64 crtc_base, bool async);
bool (*page_flip_pending)(struct radeon_device *rdev, int crtc);
} pflip;
};
@@ -2394,7 +2401,6 @@ struct radeon_device {
struct radeon_wb wb;
struct radeon_dummy_page dummy_page;
bool shutdown;
- bool suspend;
bool need_dma32;
bool accel_working;
bool fastfb_working; /* IGP feature*/
@@ -2423,6 +2429,7 @@ struct radeon_device {
int num_crtc; /* number of crtcs */
struct mutex dc_hw_i2c_mutex; /* display controller hw i2c mutex */
bool has_uvd;
+ bool has_vce;
struct r600_audio audio; /* audio stuff */
struct notifier_block acpi_nb;
/* only one userspace can use Hyperz features or CMASK at a time */
@@ -2717,7 +2724,7 @@ static inline void radeon_ring_write(struct radeon_ring *ring, uint32_t v)
#define radeon_suspend(rdev) (rdev)->asic->suspend((rdev))
#define radeon_cs_parse(rdev, r, p) (rdev)->asic->ring[(r)]->cs_parse((p))
#define radeon_vga_set_state(rdev, state) (rdev)->asic->vga_set_state((rdev), (state))
-#define radeon_asic_reset(rdev) (rdev)->asic->asic_reset((rdev))
+#define radeon_asic_reset(rdev) (rdev)->asic->asic_reset((rdev), false)
#define radeon_gart_tlb_flush(rdev) (rdev)->asic->gart.tlb_flush((rdev))
#define radeon_gart_get_page_entry(a, f) (rdev)->asic->gart.get_page_entry((a), (f))
#define radeon_gart_set_page(rdev, i, e) (rdev)->asic->gart.set_page((rdev), (i), (e))
@@ -2775,7 +2782,7 @@ static inline void radeon_ring_write(struct radeon_ring *ring, uint32_t v)
#define radeon_pm_finish(rdev) (rdev)->asic->pm.finish((rdev))
#define radeon_pm_init_profile(rdev) (rdev)->asic->pm.init_profile((rdev))
#define radeon_pm_get_dynpm_state(rdev) (rdev)->asic->pm.get_dynpm_state((rdev))
-#define radeon_page_flip(rdev, crtc, base) (rdev)->asic->pflip.page_flip((rdev), (crtc), (base))
+#define radeon_page_flip(rdev, crtc, base, async) (rdev)->asic->pflip.page_flip((rdev), (crtc), (base), (async))
#define radeon_page_flip_pending(rdev, crtc) (rdev)->asic->pflip.page_flip_pending((rdev), (crtc))
#define radeon_wait_for_vblank(rdev, crtc) (rdev)->asic->display.wait_for_vblank((rdev), (crtc))
#define radeon_mc_wait_for_idle(rdev) (rdev)->asic->mc_wait_for_idle((rdev))
@@ -2832,7 +2839,8 @@ extern bool radeon_ttm_tt_is_readonly(struct ttm_tt *ttm);
extern void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 base);
extern void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc);
extern int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon);
-extern int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon);
+extern int radeon_suspend_kms(struct drm_device *dev, bool suspend,
+ bool fbcon, bool freeze);
extern void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size);
extern void radeon_program_register_sequence(struct radeon_device *rdev,
const u32 *registers,
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
index 7d5a36d..bc5121d 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -2324,6 +2324,7 @@ int radeon_asic_init(struct radeon_device *rdev)
rdev->num_crtc = 2;
rdev->has_uvd = false;
+ rdev->has_vce = false;
switch (rdev->family) {
case CHIP_R100:
@@ -2454,6 +2455,7 @@ int radeon_asic_init(struct radeon_device *rdev)
/* set num crtcs */
rdev->num_crtc = 4;
rdev->has_uvd = true;
+ rdev->has_vce = true;
rdev->cg_flags =
RADEON_CG_SUPPORT_VCE_MGCG;
break;
@@ -2470,10 +2472,13 @@ int radeon_asic_init(struct radeon_device *rdev)
rdev->num_crtc = 2;
else
rdev->num_crtc = 6;
- if (rdev->family == CHIP_HAINAN)
+ if (rdev->family == CHIP_HAINAN) {
rdev->has_uvd = false;
- else
+ rdev->has_vce = false;
+ } else {
rdev->has_uvd = true;
+ rdev->has_vce = true;
+ }
switch (rdev->family) {
case CHIP_TAHITI:
rdev->cg_flags =
@@ -2578,6 +2583,7 @@ int radeon_asic_init(struct radeon_device *rdev)
rdev->asic = &ci_asic;
rdev->num_crtc = 6;
rdev->has_uvd = true;
+ rdev->has_vce = true;
if (rdev->family == CHIP_BONAIRE) {
rdev->cg_flags =
RADEON_CG_SUPPORT_GFX_MGCG |
@@ -2678,6 +2684,7 @@ int radeon_asic_init(struct radeon_device *rdev)
RADEON_PG_SUPPORT_SAMU;*/
}
rdev->has_uvd = true;
+ rdev->has_vce = true;
break;
default:
/* FIXME: not supported yet */
@@ -2689,6 +2696,11 @@ int radeon_asic_init(struct radeon_device *rdev)
rdev->asic->pm.set_memory_clock = NULL;
}
+ if (!radeon_uvd)
+ rdev->has_uvd = false;
+ if (!radeon_vce)
+ rdev->has_vce = false;
+
return 0;
}
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
index e0aa332..e3f036c 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -64,7 +64,7 @@ int r100_suspend(struct radeon_device *rdev);
int r100_resume(struct radeon_device *rdev);
void r100_vga_set_state(struct radeon_device *rdev, bool state);
bool r100_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp);
-int r100_asic_reset(struct radeon_device *rdev);
+int r100_asic_reset(struct radeon_device *rdev, bool hard);
u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc);
void r100_pci_gart_tlb_flush(struct radeon_device *rdev);
uint64_t r100_pci_gart_get_page_entry(uint64_t addr, uint32_t flags);
@@ -138,7 +138,7 @@ extern void r100_pm_finish(struct radeon_device *rdev);
extern void r100_pm_init_profile(struct radeon_device *rdev);
extern void r100_pm_get_dynpm_state(struct radeon_device *rdev);
extern void r100_page_flip(struct radeon_device *rdev, int crtc,
- u64 crtc_base);
+ u64 crtc_base, bool async);
extern bool r100_page_flip_pending(struct radeon_device *rdev, int crtc);
extern void r100_wait_for_vblank(struct radeon_device *rdev, int crtc);
extern int r100_mc_wait_for_idle(struct radeon_device *rdev);
@@ -167,7 +167,7 @@ extern int r300_init(struct radeon_device *rdev);
extern void r300_fini(struct radeon_device *rdev);
extern int r300_suspend(struct radeon_device *rdev);
extern int r300_resume(struct radeon_device *rdev);
-extern int r300_asic_reset(struct radeon_device *rdev);
+extern int r300_asic_reset(struct radeon_device *rdev, bool hard);
extern void r300_ring_start(struct radeon_device *rdev, struct radeon_ring *ring);
extern void r300_fence_ring_emit(struct radeon_device *rdev,
struct radeon_fence *fence);
@@ -225,7 +225,7 @@ extern int rs400_mc_wait_for_idle(struct radeon_device *rdev);
/*
* rs600.
*/
-extern int rs600_asic_reset(struct radeon_device *rdev);
+extern int rs600_asic_reset(struct radeon_device *rdev, bool hard);
extern int rs600_init(struct radeon_device *rdev);
extern void rs600_fini(struct radeon_device *rdev);
extern int rs600_suspend(struct radeon_device *rdev);
@@ -250,7 +250,7 @@ extern void rs600_pm_misc(struct radeon_device *rdev);
extern void rs600_pm_prepare(struct radeon_device *rdev);
extern void rs600_pm_finish(struct radeon_device *rdev);
extern void rs600_page_flip(struct radeon_device *rdev, int crtc,
- u64 crtc_base);
+ u64 crtc_base, bool async);
extern bool rs600_page_flip_pending(struct radeon_device *rdev, int crtc);
void rs600_set_safe_registers(struct radeon_device *rdev);
extern void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc);
@@ -334,7 +334,7 @@ bool r600_dma_semaphore_ring_emit(struct radeon_device *rdev,
void r600_dma_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
bool r600_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring);
bool r600_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp);
-int r600_asic_reset(struct radeon_device *rdev);
+int r600_asic_reset(struct radeon_device *rdev, bool hard);
int r600_set_surface_reg(struct radeon_device *rdev, int reg,
uint32_t tiling_flags, uint32_t pitch,
uint32_t offset, uint32_t obj_size);
@@ -464,7 +464,8 @@ void rv770_fini(struct radeon_device *rdev);
int rv770_suspend(struct radeon_device *rdev);
int rv770_resume(struct radeon_device *rdev);
void rv770_pm_misc(struct radeon_device *rdev);
-void rv770_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base);
+void rv770_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base,
+ bool async);
bool rv770_page_flip_pending(struct radeon_device *rdev, int crtc);
void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc);
void r700_cp_stop(struct radeon_device *rdev);
@@ -513,7 +514,7 @@ int evergreen_suspend(struct radeon_device *rdev);
int evergreen_resume(struct radeon_device *rdev);
bool evergreen_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp);
bool evergreen_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp);
-int evergreen_asic_reset(struct radeon_device *rdev);
+int evergreen_asic_reset(struct radeon_device *rdev, bool hard);
void evergreen_bandwidth_update(struct radeon_device *rdev);
void evergreen_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
void evergreen_hpd_init(struct radeon_device *rdev);
@@ -534,7 +535,7 @@ extern void btc_pm_init_profile(struct radeon_device *rdev);
int sumo_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
int evergreen_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
extern void evergreen_page_flip(struct radeon_device *rdev, int crtc,
- u64 crtc_base);
+ u64 crtc_base, bool async);
extern bool evergreen_page_flip_pending(struct radeon_device *rdev, int crtc);
extern void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc);
void evergreen_disable_interrupt_state(struct radeon_device *rdev);
@@ -606,7 +607,7 @@ int cayman_init(struct radeon_device *rdev);
void cayman_fini(struct radeon_device *rdev);
int cayman_suspend(struct radeon_device *rdev);
int cayman_resume(struct radeon_device *rdev);
-int cayman_asic_reset(struct radeon_device *rdev);
+int cayman_asic_reset(struct radeon_device *rdev, bool hard);
void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
int cayman_vm_init(struct radeon_device *rdev);
void cayman_vm_fini(struct radeon_device *rdev);
@@ -712,7 +713,7 @@ int si_suspend(struct radeon_device *rdev);
int si_resume(struct radeon_device *rdev);
bool si_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp);
bool si_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp);
-int si_asic_reset(struct radeon_device *rdev);
+int si_asic_reset(struct radeon_device *rdev, bool hard);
void si_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
int si_irq_set(struct radeon_device *rdev);
int si_irq_process(struct radeon_device *rdev);
@@ -817,7 +818,7 @@ void cik_fini(struct radeon_device *rdev);
int cik_suspend(struct radeon_device *rdev);
int cik_resume(struct radeon_device *rdev);
bool cik_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp);
-int cik_asic_reset(struct radeon_device *rdev);
+int cik_asic_reset(struct radeon_device *rdev, bool hard);
void cik_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
int cik_ring_test(struct radeon_device *rdev, struct radeon_ring *ring);
int cik_ib_test(struct radeon_device *rdev, struct radeon_ring *ring);
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c
index ab39b85..510ea37 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -74,7 +74,6 @@ static void radeon_cs_buckets_get_list(struct radeon_cs_buckets *b,
static int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
{
- struct drm_device *ddev = p->rdev->ddev;
struct radeon_cs_chunk *chunk;
struct radeon_cs_buckets buckets;
unsigned i;
@@ -101,7 +100,7 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
unsigned priority;
r = (struct drm_radeon_cs_reloc *)&chunk->kdata[i*4];
- gobj = drm_gem_object_lookup(ddev, p->filp, r->handle);
+ gobj = drm_gem_object_lookup(p->filp, r->handle);
if (gobj == NULL) {
DRM_ERROR("gem object lookup failed 0x%x\n",
r->handle);
diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c
index afaf346..2a10e24 100644
--- a/drivers/gpu/drm/radeon/radeon_cursor.c
+++ b/drivers/gpu/drm/radeon/radeon_cursor.c
@@ -274,7 +274,7 @@ int radeon_crtc_cursor_set2(struct drm_crtc *crtc,
return -EINVAL;
}
- obj = drm_gem_object_lookup(crtc->dev, file_priv, handle);
+ obj = drm_gem_object_lookup(file_priv, handle);
if (!obj) {
DRM_ERROR("Cannot find cursor object %x for crtc %d\n", handle, radeon_crtc->crtc_id);
return -ENOENT;
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index d0826fb..e721e6b 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -1230,7 +1230,7 @@ static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero
printk(KERN_INFO "radeon: switched off\n");
drm_kms_helper_poll_disable(dev);
dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
- radeon_suspend_kms(dev, true, true);
+ radeon_suspend_kms(dev, true, true, false);
dev->switch_power_state = DRM_SWITCH_POWER_OFF;
}
}
@@ -1555,7 +1555,8 @@ void radeon_device_fini(struct radeon_device *rdev)
* Returns 0 for success or an error on failure.
* Called at driver suspend.
*/
-int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon)
+int radeon_suspend_kms(struct drm_device *dev, bool suspend,
+ bool fbcon, bool freeze)
{
struct radeon_device *rdev;
struct drm_crtc *crtc;
@@ -1630,7 +1631,10 @@ int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon)
radeon_agp_suspend(rdev);
pci_save_state(dev->pdev);
- if (suspend) {
+ if (freeze && rdev->family >= CHIP_R600) {
+ rdev->asic->asic_reset(rdev, true);
+ pci_restore_state(dev->pdev);
+ } else if (suspend) {
/* Shut down the device */
pci_disable_device(dev->pdev);
pci_set_power_state(dev->pdev, PCI_D3hot);
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index fcc7483..6a41b49 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -377,7 +377,7 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
/* wakeup userspace */
if (work->event)
- drm_send_vblank_event(rdev->ddev, crtc_id, work->event);
+ drm_crtc_send_vblank_event(&radeon_crtc->base, work->event);
spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
@@ -490,7 +490,7 @@ static void radeon_flip_work_func(struct work_struct *__work)
vblank->linedur_ns / 1000, stat, vpos, hpos);
/* do the flip (mmio) */
- radeon_page_flip(rdev, radeon_crtc->crtc_id, work->base);
+ radeon_page_flip(rdev, radeon_crtc->crtc_id, work->base, work->async);
radeon_crtc->flip_status = RADEON_FLIP_SUBMITTED;
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
@@ -525,6 +525,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
work->rdev = rdev;
work->crtc_id = radeon_crtc->crtc_id;
work->event = event;
+ work->async = (page_flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0;
/* schedule unpin of the old buffer */
old_radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
@@ -1367,7 +1368,7 @@ radeon_user_framebuffer_create(struct drm_device *dev,
struct radeon_framebuffer *radeon_fb;
int ret;
- obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
+ obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[0]);
if (obj == NULL) {
dev_err(&dev->pdev->dev, "No GEM object associated to handle 0x%08X, "
"can't create framebuffer\n", mode_cmd->handles[0]);
@@ -1630,6 +1631,9 @@ int radeon_modeset_init(struct radeon_device *rdev)
rdev->ddev->mode_config.funcs = &radeon_mode_funcs;
+ if (radeon_use_pflipirq == 2 && rdev->family >= CHIP_R600)
+ rdev->ddev->mode_config.async_page_flip = true;
+
if (ASIC_IS_DCE5(rdev)) {
rdev->ddev->mode_config.max_width = 16384;
rdev->ddev->mode_config.max_height = 16384;
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index ccd4ad4..b55aa74 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -93,9 +93,11 @@
* 2.41.0 - evergreen/cayman: Add SET_BASE/DRAW_INDIRECT command parsing support
* 2.42.0 - Add VCE/VUI (Video Usability Information) support
* 2.43.0 - RADEON_INFO_GPU_RESET_COUNTER
+ * 2.44.0 - SET_APPEND_CNT packet3 support
+ * 2.45.0 - Allow setting shader registers using DMA/COPY packet3 on SI
*/
#define KMS_DRIVER_MAJOR 2
-#define KMS_DRIVER_MINOR 43
+#define KMS_DRIVER_MINOR 45
#define KMS_DRIVER_PATCHLEVEL 0
int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
int radeon_driver_unload_kms(struct drm_device *dev);
@@ -105,7 +107,8 @@ void radeon_driver_postclose_kms(struct drm_device *dev,
struct drm_file *file_priv);
void radeon_driver_preclose_kms(struct drm_device *dev,
struct drm_file *file_priv);
-int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon);
+int radeon_suspend_kms(struct drm_device *dev, bool suspend,
+ bool fbcon, bool freeze);
int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon);
u32 radeon_get_vblank_counter_kms(struct drm_device *dev, unsigned int pipe);
int radeon_enable_vblank_kms(struct drm_device *dev, unsigned int pipe);
@@ -196,6 +199,8 @@ int radeon_bapm = -1;
int radeon_backlight = -1;
int radeon_auxch = -1;
int radeon_mst = 0;
+int radeon_uvd = 1;
+int radeon_vce = 1;
MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
module_param_named(no_wb, radeon_no_wb, int, 0444);
@@ -287,6 +292,12 @@ module_param_named(auxch, radeon_auxch, int, 0444);
MODULE_PARM_DESC(mst, "DisplayPort MST experimental support (1 = enable, 0 = disable)");
module_param_named(mst, radeon_mst, int, 0444);
+MODULE_PARM_DESC(uvd, "uvd enable/disable uvd support (1 = enable, 0 = disable)");
+module_param_named(uvd, radeon_uvd, int, 0444);
+
+MODULE_PARM_DESC(vce, "vce enable/disable vce support (1 = enable, 0 = disable)");
+module_param_named(vce, radeon_vce, int, 0444);
+
static struct pci_device_id pciidlist[] = {
radeon_PCI_IDS
};
@@ -358,7 +369,7 @@ static int radeon_pmops_suspend(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct drm_device *drm_dev = pci_get_drvdata(pdev);
- return radeon_suspend_kms(drm_dev, true, true);
+ return radeon_suspend_kms(drm_dev, true, true, false);
}
static int radeon_pmops_resume(struct device *dev)
@@ -372,7 +383,7 @@ static int radeon_pmops_freeze(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct drm_device *drm_dev = pci_get_drvdata(pdev);
- return radeon_suspend_kms(drm_dev, false, true);
+ return radeon_suspend_kms(drm_dev, false, true, true);
}
static int radeon_pmops_thaw(struct device *dev)
@@ -397,7 +408,7 @@ static int radeon_pmops_runtime_suspend(struct device *dev)
drm_kms_helper_poll_disable(drm_dev);
vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_OFF);
- ret = radeon_suspend_kms(drm_dev, false, false);
+ ret = radeon_suspend_kms(drm_dev, false, false, false);
pci_save_state(pdev);
pci_disable_device(pdev);
pci_ignore_hotplug(pdev);
@@ -525,7 +536,7 @@ static struct drm_driver kms_driver = {
.irq_uninstall = radeon_driver_irq_uninstall_kms,
.irq_handler = radeon_driver_irq_handler_kms,
.ioctls = radeon_ioctls_kms,
- .gem_free_object = radeon_gem_object_free,
+ .gem_free_object_unlocked = radeon_gem_object_free,
.gem_open_object = radeon_gem_object_open,
.gem_close_object = radeon_gem_object_close,
.dumb_create = radeon_mode_dumb_create,
@@ -566,12 +577,10 @@ static struct pci_driver radeon_kms_pci_driver = {
static int __init radeon_init(void)
{
-#ifdef CONFIG_VGA_CONSOLE
if (vgacon_text_force() && radeon_modeset == -1) {
DRM_INFO("VGACON disable radeon kernel modesetting.\n");
radeon_modeset = 0;
}
-#endif
/* set to modesetting by default if not nomodeset */
if (radeon_modeset == -1)
radeon_modeset = 1;
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c
index e26c963..deb9511 100644
--- a/drivers/gpu/drm/radeon/radeon_gem.c
+++ b/drivers/gpu/drm/radeon/radeon_gem.c
@@ -382,7 +382,7 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data,
down_read(&rdev->exclusive_lock);
/* just do a BO wait for now */
- gobj = drm_gem_object_lookup(dev, filp, args->handle);
+ gobj = drm_gem_object_lookup(filp, args->handle);
if (gobj == NULL) {
up_read(&rdev->exclusive_lock);
return -ENOENT;
@@ -404,7 +404,7 @@ int radeon_mode_dumb_mmap(struct drm_file *filp,
struct drm_gem_object *gobj;
struct radeon_bo *robj;
- gobj = drm_gem_object_lookup(dev, filp, handle);
+ gobj = drm_gem_object_lookup(filp, handle);
if (gobj == NULL) {
return -ENOENT;
}
@@ -435,7 +435,7 @@ int radeon_gem_busy_ioctl(struct drm_device *dev, void *data,
int r;
uint32_t cur_placement = 0;
- gobj = drm_gem_object_lookup(dev, filp, args->handle);
+ gobj = drm_gem_object_lookup(filp, args->handle);
if (gobj == NULL) {
return -ENOENT;
}
@@ -464,7 +464,7 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data,
uint32_t cur_placement = 0;
long ret;
- gobj = drm_gem_object_lookup(dev, filp, args->handle);
+ gobj = drm_gem_object_lookup(filp, args->handle);
if (gobj == NULL) {
return -ENOENT;
}
@@ -495,7 +495,7 @@ int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data,
int r = 0;
DRM_DEBUG("%d \n", args->handle);
- gobj = drm_gem_object_lookup(dev, filp, args->handle);
+ gobj = drm_gem_object_lookup(filp, args->handle);
if (gobj == NULL)
return -ENOENT;
robj = gem_to_radeon_bo(gobj);
@@ -513,7 +513,7 @@ int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data,
int r = 0;
DRM_DEBUG("\n");
- gobj = drm_gem_object_lookup(dev, filp, args->handle);
+ gobj = drm_gem_object_lookup(filp, args->handle);
if (gobj == NULL)
return -ENOENT;
rbo = gem_to_radeon_bo(gobj);
@@ -648,7 +648,7 @@ int radeon_gem_va_ioctl(struct drm_device *dev, void *data,
return -EINVAL;
}
- gobj = drm_gem_object_lookup(dev, filp, args->handle);
+ gobj = drm_gem_object_lookup(filp, args->handle);
if (gobj == NULL) {
args->operation = RADEON_VA_RESULT_ERROR;
return -ENOENT;
@@ -703,7 +703,7 @@ int radeon_gem_op_ioctl(struct drm_device *dev, void *data,
struct radeon_bo *robj;
int r;
- gobj = drm_gem_object_lookup(dev, filp, args->handle);
+ gobj = drm_gem_object_lookup(filp, args->handle);
if (gobj == NULL) {
return -ENOENT;
}
diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c
index 1e9304d..c084cad 100644
--- a/drivers/gpu/drm/radeon/radeon_irq_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c
@@ -291,7 +291,6 @@ int radeon_irq_kms_init(struct radeon_device *rdev)
if (r) {
return r;
}
- rdev->ddev->vblank_disable_allowed = true;
/* enable msi */
rdev->msi_enabled = 0;
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c
index 2d901bf..be30861 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -832,13 +832,13 @@ int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type, bool no_wait)
{
int r;
- r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, NULL);
+ r = ttm_bo_reserve(&bo->tbo, true, no_wait, NULL);
if (unlikely(r != 0))
return r;
if (mem_type)
*mem_type = bo->tbo.mem.mem_type;
- r = ttm_bo_wait(&bo->tbo, true, true, no_wait);
+ r = ttm_bo_wait(&bo->tbo, true, no_wait);
ttm_bo_unreserve(&bo->tbo);
return r;
}
diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h
index d8d295e..a10bb3d 100644
--- a/drivers/gpu/drm/radeon/radeon_object.h
+++ b/drivers/gpu/drm/radeon/radeon_object.h
@@ -65,7 +65,7 @@ static inline int radeon_bo_reserve(struct radeon_bo *bo, bool no_intr)
{
int r;
- r = ttm_bo_reserve(&bo->tbo, !no_intr, false, false, NULL);
+ r = ttm_bo_reserve(&bo->tbo, !no_intr, false, NULL);
if (unlikely(r != 0)) {
if (r != -ERESTARTSYS)
dev_err(bo->rdev->dev, "%p reserve failed\n", bo);
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
index 90f7394..590b037 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -865,6 +865,8 @@ static struct ttm_bo_driver radeon_bo_driver = {
.fault_reserve_notify = &radeon_bo_fault_reserve_notify,
.io_mem_reserve = &radeon_ttm_io_mem_reserve,
.io_mem_free = &radeon_ttm_io_mem_free,
+ .lru_tail = &ttm_bo_default_lru_tail,
+ .swap_lru_tail = &ttm_bo_default_swap_lru_tail,
};
int radeon_ttm_init(struct radeon_device *rdev)
diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c
index 6fe9e4e..73dfe01 100644
--- a/drivers/gpu/drm/radeon/radeon_uvd.c
+++ b/drivers/gpu/drm/radeon/radeon_uvd.c
@@ -34,6 +34,7 @@
#include <drm/drm.h>
#include "radeon.h"
+#include "radeon_ucode.h"
#include "r600d.h"
/* 1 second timeout */
@@ -47,7 +48,8 @@
#define FIRMWARE_CYPRESS "radeon/CYPRESS_uvd.bin"
#define FIRMWARE_SUMO "radeon/SUMO_uvd.bin"
#define FIRMWARE_TAHITI "radeon/TAHITI_uvd.bin"
-#define FIRMWARE_BONAIRE "radeon/BONAIRE_uvd.bin"
+#define FIRMWARE_BONAIRE_LEGACY "radeon/BONAIRE_uvd.bin"
+#define FIRMWARE_BONAIRE "radeon/bonaire_uvd.bin"
MODULE_FIRMWARE(FIRMWARE_R600);
MODULE_FIRMWARE(FIRMWARE_RS780);
@@ -56,6 +58,7 @@ MODULE_FIRMWARE(FIRMWARE_RV710);
MODULE_FIRMWARE(FIRMWARE_CYPRESS);
MODULE_FIRMWARE(FIRMWARE_SUMO);
MODULE_FIRMWARE(FIRMWARE_TAHITI);
+MODULE_FIRMWARE(FIRMWARE_BONAIRE_LEGACY);
MODULE_FIRMWARE(FIRMWARE_BONAIRE);
static void radeon_uvd_idle_work_handler(struct work_struct *work);
@@ -63,7 +66,7 @@ static void radeon_uvd_idle_work_handler(struct work_struct *work);
int radeon_uvd_init(struct radeon_device *rdev)
{
unsigned long bo_size;
- const char *fw_name;
+ const char *fw_name = NULL, *legacy_fw_name = NULL;
int i, r;
INIT_DELAYED_WORK(&rdev->uvd.idle_work, radeon_uvd_idle_work_handler);
@@ -74,22 +77,22 @@ int radeon_uvd_init(struct radeon_device *rdev)
case CHIP_RV670:
case CHIP_RV620:
case CHIP_RV635:
- fw_name = FIRMWARE_R600;
+ legacy_fw_name = FIRMWARE_R600;
break;
case CHIP_RS780:
case CHIP_RS880:
- fw_name = FIRMWARE_RS780;
+ legacy_fw_name = FIRMWARE_RS780;
break;
case CHIP_RV770:
- fw_name = FIRMWARE_RV770;
+ legacy_fw_name = FIRMWARE_RV770;
break;
case CHIP_RV710:
case CHIP_RV730:
case CHIP_RV740:
- fw_name = FIRMWARE_RV710;
+ legacy_fw_name = FIRMWARE_RV710;
break;
case CHIP_CYPRESS:
@@ -97,7 +100,7 @@ int radeon_uvd_init(struct radeon_device *rdev)
case CHIP_JUNIPER:
case CHIP_REDWOOD:
case CHIP_CEDAR:
- fw_name = FIRMWARE_CYPRESS;
+ legacy_fw_name = FIRMWARE_CYPRESS;
break;
case CHIP_SUMO:
@@ -107,7 +110,7 @@ int radeon_uvd_init(struct radeon_device *rdev)
case CHIP_BARTS:
case CHIP_TURKS:
case CHIP_CAICOS:
- fw_name = FIRMWARE_SUMO;
+ legacy_fw_name = FIRMWARE_SUMO;
break;
case CHIP_TAHITI:
@@ -115,7 +118,7 @@ int radeon_uvd_init(struct radeon_device *rdev)
case CHIP_PITCAIRN:
case CHIP_ARUBA:
case CHIP_OLAND:
- fw_name = FIRMWARE_TAHITI;
+ legacy_fw_name = FIRMWARE_TAHITI;
break;
case CHIP_BONAIRE:
@@ -123,6 +126,7 @@ int radeon_uvd_init(struct radeon_device *rdev)
case CHIP_KAVERI:
case CHIP_HAWAII:
case CHIP_MULLINS:
+ legacy_fw_name = FIRMWARE_BONAIRE_LEGACY;
fw_name = FIRMWARE_BONAIRE;
break;
@@ -130,16 +134,56 @@ int radeon_uvd_init(struct radeon_device *rdev)
return -EINVAL;
}
- r = request_firmware(&rdev->uvd_fw, fw_name, rdev->dev);
- if (r) {
- dev_err(rdev->dev, "radeon_uvd: Can't load firmware \"%s\"\n",
- fw_name);
- return r;
+ rdev->uvd.fw_header_present = false;
+ rdev->uvd.max_handles = RADEON_DEFAULT_UVD_HANDLES;
+ if (fw_name) {
+ /* Let's try to load the newer firmware first */
+ r = request_firmware(&rdev->uvd_fw, fw_name, rdev->dev);
+ if (r) {
+ dev_err(rdev->dev, "radeon_uvd: Can't load firmware \"%s\"\n",
+ fw_name);
+ } else {
+ struct common_firmware_header *hdr = (void *)rdev->uvd_fw->data;
+ unsigned version_major, version_minor, family_id;
+
+ r = radeon_ucode_validate(rdev->uvd_fw);
+ if (r)
+ return r;
+
+ rdev->uvd.fw_header_present = true;
+
+ family_id = le32_to_cpu(hdr->ucode_version) & 0xff;
+ version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff;
+ version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff;
+ DRM_INFO("Found UVD firmware Version: %hu.%hu Family ID: %hu\n",
+ version_major, version_minor, family_id);
+
+ /*
+ * Limit the number of UVD handles depending on
+ * microcode major and minor versions.
+ */
+ if ((version_major >= 0x01) && (version_minor >= 0x37))
+ rdev->uvd.max_handles = RADEON_MAX_UVD_HANDLES;
+ }
+ }
+
+ /*
+ * In case there is only legacy firmware, or we encounter an error
+ * while loading the new firmware, we fall back to loading the legacy
+ * firmware now.
+ */
+ if (!fw_name || r) {
+ r = request_firmware(&rdev->uvd_fw, legacy_fw_name, rdev->dev);
+ if (r) {
+ dev_err(rdev->dev, "radeon_uvd: Can't load firmware \"%s\"\n",
+ legacy_fw_name);
+ return r;
+ }
}
bo_size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 8) +
RADEON_UVD_STACK_SIZE + RADEON_UVD_HEAP_SIZE +
- RADEON_GPU_PAGE_SIZE;
+ RADEON_UVD_SESSION_SIZE * rdev->uvd.max_handles;
r = radeon_bo_create(rdev, bo_size, PAGE_SIZE, true,
RADEON_GEM_DOMAIN_VRAM, 0, NULL,
NULL, &rdev->uvd.vcpu_bo);
@@ -172,7 +216,7 @@ int radeon_uvd_init(struct radeon_device *rdev)
radeon_bo_unreserve(rdev->uvd.vcpu_bo);
- for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
+ for (i = 0; i < rdev->uvd.max_handles; ++i) {
atomic_set(&rdev->uvd.handles[i], 0);
rdev->uvd.filp[i] = NULL;
rdev->uvd.img_size[i] = 0;
@@ -209,7 +253,7 @@ int radeon_uvd_suspend(struct radeon_device *rdev)
if (rdev->uvd.vcpu_bo == NULL)
return 0;
- for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
+ for (i = 0; i < rdev->uvd.max_handles; ++i) {
uint32_t handle = atomic_read(&rdev->uvd.handles[i]);
if (handle != 0) {
struct radeon_fence *fence;
@@ -284,7 +328,7 @@ void radeon_uvd_force_into_uvd_segment(struct radeon_bo *rbo,
void radeon_uvd_free_handles(struct radeon_device *rdev, struct drm_file *filp)
{
int i, r;
- for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
+ for (i = 0; i < rdev->uvd.max_handles; ++i) {
uint32_t handle = atomic_read(&rdev->uvd.handles[i]);
if (handle != 0 && rdev->uvd.filp[i] == filp) {
struct radeon_fence *fence;
@@ -469,7 +513,7 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
return r;
/* try to alloc a new handle */
- for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
+ for (i = 0; i < p->rdev->uvd.max_handles; ++i) {
if (atomic_read(&p->rdev->uvd.handles[i]) == handle) {
DRM_ERROR("Handle 0x%x already in use!\n", handle);
return -EINVAL;
@@ -495,7 +539,7 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
return r;
/* validate the handle */
- for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
+ for (i = 0; i < p->rdev->uvd.max_handles; ++i) {
if (atomic_read(&p->rdev->uvd.handles[i]) == handle) {
if (p->rdev->uvd.filp[i] != p->filp) {
DRM_ERROR("UVD handle collision detected!\n");
@@ -510,7 +554,7 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
case 2:
/* it's a destroy msg, free the handle */
- for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i)
+ for (i = 0; i < p->rdev->uvd.max_handles; ++i)
atomic_cmpxchg(&p->rdev->uvd.handles[i], handle, 0);
radeon_bo_kunmap(bo);
return 0;
@@ -809,7 +853,7 @@ static void radeon_uvd_count_handles(struct radeon_device *rdev,
*sd = 0;
*hd = 0;
- for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
+ for (i = 0; i < rdev->uvd.max_handles; ++i) {
if (!atomic_read(&rdev->uvd.handles[i]))
continue;
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c
index 6244f4e..f16af11 100644
--- a/drivers/gpu/drm/radeon/rs600.c
+++ b/drivers/gpu/drm/radeon/rs600.c
@@ -110,7 +110,7 @@ void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc)
}
}
-void rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
+void rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base, bool async)
{
struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset);
@@ -121,6 +121,8 @@ void rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
/* update the scanout addresses */
+ WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset,
+ async ? AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN : 0);
WREG32(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
(u32)crtc_base);
WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
@@ -413,7 +415,8 @@ void rs600_hpd_init(struct radeon_device *rdev)
default:
break;
}
- enable |= 1 << radeon_connector->hpd.hpd;
+ if (radeon_connector->hpd.hpd != RADEON_HPD_NONE)
+ enable |= 1 << radeon_connector->hpd.hpd;
radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
}
radeon_irq_kms_enable_hpd(rdev, enable);
@@ -439,12 +442,13 @@ void rs600_hpd_fini(struct radeon_device *rdev)
default:
break;
}
- disable |= 1 << radeon_connector->hpd.hpd;
+ if (radeon_connector->hpd.hpd != RADEON_HPD_NONE)
+ disable |= 1 << radeon_connector->hpd.hpd;
}
radeon_irq_kms_disable_hpd(rdev, disable);
}
-int rs600_asic_reset(struct radeon_device *rdev)
+int rs600_asic_reset(struct radeon_device *rdev, bool hard)
{
struct rv515_mc_save save;
u32 status, tmp;
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index 01ee96a..1c120a4 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -801,7 +801,7 @@ u32 rv770_get_xclk(struct radeon_device *rdev)
return reference_clock;
}
-void rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
+void rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base, bool async)
{
struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset);
@@ -812,6 +812,8 @@ void rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
/* update the scanout addresses */
+ WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset,
+ async ? AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN : 0);
if (radeon_crtc->crtc_id) {
WREG32(D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base));
WREG32(D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base));
@@ -1681,6 +1683,73 @@ static int rv770_mc_init(struct radeon_device *rdev)
return 0;
}
+static void rv770_uvd_init(struct radeon_device *rdev)
+{
+ int r;
+
+ if (!rdev->has_uvd)
+ return;
+
+ r = radeon_uvd_init(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failed UVD (%d) init.\n", r);
+ /*
+ * At this point rdev->uvd.vcpu_bo is NULL which trickles down
+ * to early fails uvd_v2_2_resume() and thus nothing happens
+ * there. So it is pointless to try to go through that code
+ * hence why we disable uvd here.
+ */
+ rdev->has_uvd = 0;
+ return;
+ }
+ rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_obj = NULL;
+ r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX], 4096);
+}
+
+static void rv770_uvd_start(struct radeon_device *rdev)
+{
+ int r;
+
+ if (!rdev->has_uvd)
+ return;
+
+ r = uvd_v2_2_resume(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failed UVD resume (%d).\n", r);
+ goto error;
+ }
+ 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);
+ goto error;
+ }
+ return;
+
+error:
+ rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
+}
+
+static void rv770_uvd_resume(struct radeon_device *rdev)
+{
+ struct radeon_ring *ring;
+ int r;
+
+ if (!rdev->has_uvd || !rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size)
+ return;
+
+ ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
+ r = radeon_ring_init(rdev, ring, ring->ring_size, 0, RADEON_CP_PACKET2);
+ if (r) {
+ dev_err(rdev->dev, "failed initializing UVD ring (%d).\n", r);
+ return;
+ }
+ r = uvd_v1_0_init(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failed initializing UVD (%d).\n", r);
+ return;
+ }
+}
+
static int rv770_startup(struct radeon_device *rdev)
{
struct radeon_ring *ring;
@@ -1723,16 +1792,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_start(rdev);
/* Enable IRQ */
if (!rdev->irq.installed) {
@@ -1772,16 +1832,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 +1882,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 +1970,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);
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index ae21550..b30e719 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -4034,10 +4034,15 @@ static void si_gpu_pci_config_reset(struct radeon_device *rdev)
}
}
-int si_asic_reset(struct radeon_device *rdev)
+int si_asic_reset(struct radeon_device *rdev, bool hard)
{
u32 reset_mask;
+ if (hard) {
+ si_gpu_pci_config_reset(rdev);
+ return 0;
+ }
+
reset_mask = si_gpu_check_soft_reset(rdev);
if (reset_mask)
@@ -4359,6 +4364,10 @@ static bool si_vm_reg_valid(u32 reg)
if (reg >= 0x28000)
return true;
+ /* shader regs are also fine */
+ if (reg >= 0xB000 && reg < 0xC000)
+ return true;
+
/* check config regs */
switch (reg) {
case GRBM_GFX_INDEX:
@@ -6821,6 +6830,159 @@ restart_ih:
/*
* startup/shutdown callbacks
*/
+static void si_uvd_init(struct radeon_device *rdev)
+{
+ int r;
+
+ if (!rdev->has_uvd)
+ return;
+
+ r = radeon_uvd_init(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failed UVD (%d) init.\n", r);
+ /*
+ * At this point rdev->uvd.vcpu_bo is NULL which trickles down
+ * to early fails uvd_v2_2_resume() and thus nothing happens
+ * there. So it is pointless to try to go through that code
+ * hence why we disable uvd here.
+ */
+ rdev->has_uvd = 0;
+ return;
+ }
+ rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_obj = NULL;
+ r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX], 4096);
+}
+
+static void si_uvd_start(struct radeon_device *rdev)
+{
+ int r;
+
+ if (!rdev->has_uvd)
+ return;
+
+ r = uvd_v2_2_resume(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failed UVD resume (%d).\n", r);
+ goto error;
+ }
+ 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);
+ goto error;
+ }
+ return;
+
+error:
+ rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
+}
+
+static void si_uvd_resume(struct radeon_device *rdev)
+{
+ struct radeon_ring *ring;
+ int r;
+
+ if (!rdev->has_uvd || !rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size)
+ return;
+
+ ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
+ r = radeon_ring_init(rdev, ring, ring->ring_size, 0, RADEON_CP_PACKET2);
+ if (r) {
+ dev_err(rdev->dev, "failed initializing UVD ring (%d).\n", r);
+ return;
+ }
+ r = uvd_v1_0_init(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failed initializing UVD (%d).\n", r);
+ return;
+ }
+}
+
+static void si_vce_init(struct radeon_device *rdev)
+{
+ int r;
+
+ if (!rdev->has_vce)
+ return;
+
+ r = radeon_vce_init(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failed VCE (%d) init.\n", r);
+ /*
+ * At this point rdev->vce.vcpu_bo is NULL which trickles down
+ * to early fails si_vce_start() and thus nothing happens
+ * there. So it is pointless to try to go through that code
+ * hence why we disable vce here.
+ */
+ rdev->has_vce = 0;
+ return;
+ }
+ rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_obj = NULL;
+ r600_ring_init(rdev, &rdev->ring[TN_RING_TYPE_VCE1_INDEX], 4096);
+ rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_obj = NULL;
+ r600_ring_init(rdev, &rdev->ring[TN_RING_TYPE_VCE2_INDEX], 4096);
+}
+
+static void si_vce_start(struct radeon_device *rdev)
+{
+ int r;
+
+ if (!rdev->has_vce)
+ return;
+
+ r = radeon_vce_resume(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failed VCE resume (%d).\n", r);
+ goto error;
+ }
+ r = vce_v1_0_resume(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failed VCE resume (%d).\n", r);
+ goto error;
+ }
+ r = radeon_fence_driver_start_ring(rdev, TN_RING_TYPE_VCE1_INDEX);
+ if (r) {
+ dev_err(rdev->dev, "failed initializing VCE1 fences (%d).\n", r);
+ goto error;
+ }
+ r = radeon_fence_driver_start_ring(rdev, TN_RING_TYPE_VCE2_INDEX);
+ if (r) {
+ dev_err(rdev->dev, "failed initializing VCE2 fences (%d).\n", r);
+ goto error;
+ }
+ return;
+
+error:
+ rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size = 0;
+ rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_size = 0;
+}
+
+static void si_vce_resume(struct radeon_device *rdev)
+{
+ struct radeon_ring *ring;
+ int r;
+
+ if (!rdev->has_vce || !rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size)
+ return;
+
+ ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
+ r = radeon_ring_init(rdev, ring, ring->ring_size, 0, VCE_CMD_NO_OP);
+ if (r) {
+ dev_err(rdev->dev, "failed initializing VCE1 ring (%d).\n", r);
+ return;
+ }
+ ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
+ r = radeon_ring_init(rdev, ring, ring->ring_size, 0, VCE_CMD_NO_OP);
+ if (r) {
+ dev_err(rdev->dev, "failed initializing VCE1 ring (%d).\n", r);
+ return;
+ }
+ r = vce_v1_0_init(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failed initializing VCE (%d).\n", r);
+ return;
+ }
+}
+
static int si_startup(struct radeon_device *rdev)
{
struct radeon_ring *ring;
@@ -6899,33 +7061,8 @@ 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_start(rdev);
+ si_vce_start(rdev);
/* Enable IRQ */
if (!rdev->irq.installed) {
@@ -6983,34 +7120,8 @@ 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_resume(rdev);
+ si_vce_resume(rdev);
r = radeon_ib_pool_init(rdev);
if (r) {
@@ -7070,8 +7181,9 @@ int si_suspend(struct radeon_device *rdev)
if (rdev->has_uvd) {
uvd_v1_0_fini(rdev);
radeon_uvd_suspend(rdev);
- radeon_vce_suspend(rdev);
}
+ if (rdev->has_vce)
+ radeon_vce_suspend(rdev);
si_fini_pg(rdev);
si_fini_cg(rdev);
si_irq_suspend(rdev);
@@ -7169,25 +7281,8 @@ 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_init(rdev);
+ si_vce_init(rdev);
rdev->ih.ring_obj = NULL;
r600_ih_ring_init(rdev, 64 * 1024);
@@ -7240,8 +7335,9 @@ void si_fini(struct radeon_device *rdev)
if (rdev->has_uvd) {
uvd_v1_0_fini(rdev);
radeon_uvd_fini(rdev);
- radeon_vce_fini(rdev);
}
+ if (rdev->has_vce)
+ radeon_vce_fini(rdev);
si_pcie_gart_fini(rdev);
r600_vram_scratch_fini(rdev);
radeon_gem_fini(rdev);
diff --git a/drivers/gpu/drm/radeon/uvd_v1_0.c b/drivers/gpu/drm/radeon/uvd_v1_0.c
index 12ddcfa..0dbeb50 100644
--- a/drivers/gpu/drm/radeon/uvd_v1_0.c
+++ b/drivers/gpu/drm/radeon/uvd_v1_0.c
@@ -124,12 +124,13 @@ int uvd_v1_0_resume(struct radeon_device *rdev)
WREG32(UVD_VCPU_CACHE_SIZE0, size);
addr += size;
- size = RADEON_UVD_STACK_SIZE >> 3;
+ size = RADEON_UVD_HEAP_SIZE >> 3;
WREG32(UVD_VCPU_CACHE_OFFSET1, addr);
WREG32(UVD_VCPU_CACHE_SIZE1, size);
addr += size;
- size = RADEON_UVD_HEAP_SIZE >> 3;
+ size = (RADEON_UVD_STACK_SIZE +
+ (RADEON_UVD_SESSION_SIZE * rdev->uvd.max_handles)) >> 3;
WREG32(UVD_VCPU_CACHE_OFFSET2, addr);
WREG32(UVD_VCPU_CACHE_SIZE2, size);
diff --git a/drivers/gpu/drm/radeon/uvd_v2_2.c b/drivers/gpu/drm/radeon/uvd_v2_2.c
index 7ed778c..9071e65 100644
--- a/drivers/gpu/drm/radeon/uvd_v2_2.c
+++ b/drivers/gpu/drm/radeon/uvd_v2_2.c
@@ -116,12 +116,13 @@ int uvd_v2_2_resume(struct radeon_device *rdev)
WREG32(UVD_VCPU_CACHE_SIZE0, size);
addr += size;
- size = RADEON_UVD_STACK_SIZE >> 3;
+ size = RADEON_UVD_HEAP_SIZE >> 3;
WREG32(UVD_VCPU_CACHE_OFFSET1, addr);
WREG32(UVD_VCPU_CACHE_SIZE1, size);
addr += size;
- size = RADEON_UVD_HEAP_SIZE >> 3;
+ size = (RADEON_UVD_STACK_SIZE +
+ (RADEON_UVD_SESSION_SIZE * rdev->uvd.max_handles)) >> 3;
WREG32(UVD_VCPU_CACHE_OFFSET2, addr);
WREG32(UVD_VCPU_CACHE_SIZE2, size);
diff --git a/drivers/gpu/drm/radeon/uvd_v4_2.c b/drivers/gpu/drm/radeon/uvd_v4_2.c
index d04d507..91613b8 100644
--- a/drivers/gpu/drm/radeon/uvd_v4_2.c
+++ b/drivers/gpu/drm/radeon/uvd_v4_2.c
@@ -41,18 +41,25 @@ int uvd_v4_2_resume(struct radeon_device *rdev)
uint32_t size;
/* programm the VCPU memory controller bits 0-27 */
- addr = rdev->uvd.gpu_addr >> 3;
+
+ /* skip over the header of the new firmware format */
+ if (rdev->uvd.fw_header_present)
+ addr = (rdev->uvd.gpu_addr + 0x200) >> 3;
+ else
+ addr = rdev->uvd.gpu_addr >> 3;
+
size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 4) >> 3;
WREG32(UVD_VCPU_CACHE_OFFSET0, addr);
WREG32(UVD_VCPU_CACHE_SIZE0, size);
addr += size;
- size = RADEON_UVD_STACK_SIZE >> 3;
+ size = RADEON_UVD_HEAP_SIZE >> 3;
WREG32(UVD_VCPU_CACHE_OFFSET1, addr);
WREG32(UVD_VCPU_CACHE_SIZE1, size);
addr += size;
- size = RADEON_UVD_HEAP_SIZE >> 3;
+ size = (RADEON_UVD_STACK_SIZE +
+ (RADEON_UVD_SESSION_SIZE * rdev->uvd.max_handles)) >> 3;
WREG32(UVD_VCPU_CACHE_OFFSET2, addr);
WREG32(UVD_VCPU_CACHE_SIZE2, size);
@@ -64,5 +71,8 @@ int uvd_v4_2_resume(struct radeon_device *rdev)
addr = (rdev->uvd.gpu_addr >> 32) & 0xFF;
WREG32(UVD_LMI_EXT40_ADDR, addr | (0x9 << 16) | (0x1 << 31));
+ if (rdev->uvd.fw_header_present)
+ WREG32(UVD_GP_SCRATCH4, rdev->uvd.max_handles);
+
return 0;
}
OpenPOWER on IntegriCloud