drm/radeon: Update to Linux 3.9
authorMichael Neumann <mneumann@ntecs.de>
Tue, 24 Feb 2015 10:59:55 +0000 (11:59 +0100)
committerMichael Neumann <mneumann@ntecs.de>
Tue, 24 Feb 2015 11:09:33 +0000 (12:09 +0100)
* Add support for Oland chip family
* Add support for Richland APUs
* Misc refactoring (e.g. CS parsing)
* Misc stabilization work (e.g. GPU resetting)

56 files changed:
sys/dev/drm/radeon/Makefile
sys/dev/drm/radeon/atom.c
sys/dev/drm/radeon/atombios_crtc.c
sys/dev/drm/radeon/evergreen.c
sys/dev/drm/radeon/evergreen_cs.c
sys/dev/drm/radeon/evergreen_hdmi.c
sys/dev/drm/radeon/evergreen_reg.h
sys/dev/drm/radeon/evergreend.h
sys/dev/drm/radeon/ni.c
sys/dev/drm/radeon/nid.h
sys/dev/drm/radeon/r100.c
sys/dev/drm/radeon/r100_track.h
sys/dev/drm/radeon/r100d.h
sys/dev/drm/radeon/r200.c
sys/dev/drm/radeon/r300.c
sys/dev/drm/radeon/r300_cmdbuf.c
sys/dev/drm/radeon/r300d.h
sys/dev/drm/radeon/r500_reg.h
sys/dev/drm/radeon/r600.c
sys/dev/drm/radeon/r600_blit.c
sys/dev/drm/radeon/r600_blit_kms.c
sys/dev/drm/radeon/r600_cp.c
sys/dev/drm/radeon/r600_cs.c
sys/dev/drm/radeon/r600_hdmi.c
sys/dev/drm/radeon/r600d.h
sys/dev/drm/radeon/radeon.h
sys/dev/drm/radeon/radeon_asic.c
sys/dev/drm/radeon/radeon_asic.h
sys/dev/drm/radeon/radeon_atpx_handler.c
sys/dev/drm/radeon/radeon_benchmark.c
sys/dev/drm/radeon/radeon_bios.c
sys/dev/drm/radeon/radeon_combios.c
sys/dev/drm/radeon/radeon_cp.c
sys/dev/drm/radeon/radeon_cs.c
sys/dev/drm/radeon/radeon_cursor.c
sys/dev/drm/radeon/radeon_device.c
sys/dev/drm/radeon/radeon_display.c
sys/dev/drm/radeon/radeon_drv.c
sys/dev/drm/radeon/radeon_drv.h
sys/dev/drm/radeon/radeon_family.h
sys/dev/drm/radeon/radeon_fb.c
sys/dev/drm/radeon/radeon_gart.c
sys/dev/drm/radeon/radeon_irq.c
sys/dev/drm/radeon/radeon_irq_kms.c
sys/dev/drm/radeon/radeon_kms.c
sys/dev/drm/radeon/radeon_mem.c
sys/dev/drm/radeon/radeon_pm.c
sys/dev/drm/radeon/radeon_prime.c
sys/dev/drm/radeon/radeon_reg.h
sys/dev/drm/radeon/radeon_ring.c
sys/dev/drm/radeon/radeon_state.c
sys/dev/drm/radeon/rv515d.h
sys/dev/drm/radeon/rv770.c
sys/dev/drm/radeon/rv770d.h
sys/dev/drm/radeon/si.c
sys/dev/drm/radeon/sid.h

index a092fe2..0499b60 100644 (file)
@@ -23,7 +23,6 @@ SRCS  +=                                                              \
        radeon_clocks.c                                                 \
        radeon_combios.c                                                \
        radeon_connectors.c                                             \
-       radeon_cp.c                                                     \
        radeon_cs.c                                                     \
        radeon_cursor.c                                                 \
        radeon_device.c                                                 \
@@ -35,19 +34,16 @@ SRCS        +=                                                              \
        radeon_gart.c                                                   \
        radeon_gem.c                                                    \
        radeon_i2c.c                                                    \
-       radeon_irq.c                                                    \
        radeon_irq_kms.c                                                \
        radeon_kms.c                                                    \
        radeon_legacy_crtc.c                                            \
        radeon_legacy_encoders.c                                        \
        radeon_legacy_tv.c                                              \
-       radeon_mem.c                                                    \
        radeon_object.c                                                 \
        radeon_pm.c                                                     \
        radeon_ring.c                                                   \
        radeon_sa.c                                                     \
        radeon_semaphore.c                                              \
-       radeon_state.c                                                  \
        radeon_test.c                                                   \
        radeon_ttm.c                                                    \
        atom.c                                                          \
@@ -58,7 +54,6 @@ SRCS  +=                                                              \
        r100.c                                                          \
        r200.c                                                          \
        r300.c                                                          \
-       r300_cmdbuf.c                                                   \
        r420.c                                                          \
        rs400.c                                                         \
        rs600.c                                                         \
@@ -67,10 +62,8 @@ SRCS +=                                                              \
        r520.c                                                          \
        r600.c                                                          \
        r600_audio.c                                                    \
-       r600_blit.c                                                     \
        r600_blit_kms.c                                                 \
        r600_blit_shaders.c                                             \
-       r600_cp.c                                                       \
        r600_cs.c                                                       \
        r600_hdmi.c                                                     \
        rv770.c                                                         \
@@ -84,6 +77,17 @@ SRCS +=                                                              \
        si.c                                                            \
        si_blit_shaders.c
 
+
+# UMS driver
+#SRCS  +=                                                              \
+       radeon_cp.c                                                     \
+       radeon_state.c                                                  \
+       radeon_mem.c                                                    \
+       radeon_irq.c                                                    \
+       r300_cmdbuf.c                                                   \
+       r600_blit.c                                                     \
+       r600_cp.c
+
 #radeon_ioc32.c
 #radeon_prime.c
 #--radeon_trace_points.c
index c2b2607..a3807bb 100644 (file)
@@ -1235,6 +1235,8 @@ static int atom_iio_len[] = { 1, 2, 3, 3, 3, 3, 4, 4, 4, 3 };
 static void atom_index_iio(struct atom_context *ctx, int base)
 {
        ctx->iio = kmalloc(2 * 256, M_DRM, M_ZERO | M_WAITOK);
+       if (!ctx->iio)
+               return;
        while (CU8(base) == ATOM_IIO_START) {
                ctx->iio[CU8(base + 1)] = base + 2;
                base += 2;
@@ -1285,6 +1287,10 @@ struct atom_context *atom_parse(struct card_info *card, void *bios)
        ctx->cmd_table = CU16(base + ATOM_ROM_CMD_PTR);
        ctx->data_table = CU16(base + ATOM_ROM_DATA_PTR);
        atom_index_iio(ctx, CU16(ctx->data_table + ATOM_DATA_IIO_PTR) + 4);
+       if (!ctx->iio) {
+               atom_destroy(ctx);
+               return NULL;
+       }
 
        str = CSTR(CU16(base + ATOM_ROM_MSG_PTR));
        while (*str && ((*str == '\n') || (*str == '\r')))
@@ -1333,8 +1339,7 @@ int atom_asic_init(struct atom_context *ctx)
 
 void atom_destroy(struct atom_context *ctx)
 {
-       if (ctx->iio)
-               drm_free(ctx->iio, M_DRM);
+       drm_free(ctx->iio, M_DRM);
        drm_free(ctx, M_DRM);
 }
 
index 7828d79..3d40f32 100644 (file)
@@ -255,8 +255,6 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)
                radeon_crtc->enabled = true;
                /* adjust pm to dpms changes BEFORE enabling crtcs */
                radeon_pm_compute_clocks(rdev);
-               if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set)
-                       atombios_powergate_crtc(crtc, ATOM_DISABLE);
                atombios_enable_crtc(crtc, ATOM_ENABLE);
                if (ASIC_IS_DCE3(rdev) && !ASIC_IS_DCE6(rdev))
                        atombios_enable_crtc_memreq(crtc, ATOM_ENABLE);
@@ -274,8 +272,6 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)
                        atombios_enable_crtc_memreq(crtc, ATOM_DISABLE);
                atombios_enable_crtc(crtc, ATOM_DISABLE);
                radeon_crtc->enabled = false;
-               if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set)
-                       atombios_powergate_crtc(crtc, ATOM_ENABLE);
                /* adjust pm to dpms changes AFTER disabling crtcs */
                radeon_pm_compute_clocks(rdev);
                break;
@@ -1847,6 +1843,8 @@ static void atombios_crtc_disable(struct drm_crtc *crtc)
        int i;
 
        atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
+       if (ASIC_IS_DCE6(rdev))
+               atombios_powergate_crtc(crtc, ATOM_ENABLE);
 
        for (i = 0; i < rdev->num_crtc; i++) {
                if (rdev->mode_info.crtcs[i] &&
index dc23844..7cd3e5b 100644 (file)
@@ -49,6 +49,8 @@ static const u32 crtc_offsets[6] =
 
 static void evergreen_gpu_init(struct radeon_device *rdev);
 void evergreen_pcie_gen2_enable(struct radeon_device *rdev);
+void evergreen_print_gpu_status_regs(struct radeon_device *rdev);
+bool evergreen_is_display_hung(struct radeon_device *rdev);
 
 void evergreen_tiling_fields(unsigned tiling_flags, unsigned *bankw,
                             unsigned *bankh, unsigned *mtaspect,
@@ -404,6 +406,19 @@ void evergreen_pm_misc(struct radeon_device *rdev)
                        rdev->pm.current_vddc = voltage->voltage;
                        DRM_DEBUG("Setting: vddc: %d\n", voltage->voltage);
                }
+
+               /* starting with BTC, there is one state that is used for both
+                * MH and SH.  Difference is that we always use the high clock index for
+                * mclk and vddci.
+                */
+               if ((rdev->pm.pm_method == PM_METHOD_PROFILE) &&
+                   (rdev->family >= CHIP_BARTS) &&
+                   rdev->pm.active_crtc_count &&
+                   ((rdev->pm.profile_index == PM_PROFILE_MID_MH_IDX) ||
+                    (rdev->pm.profile_index == PM_PROFILE_LOW_MH_IDX)))
+                       voltage = &rdev->pm.power_state[req_ps_idx].
+                               clock_info[rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx].voltage;
+
                /* 0xff01 is a flag rather then an actual voltage */
                if (voltage->vddci == 0xff01)
                        return;
@@ -2309,32 +2324,8 @@ int evergreen_mc_init(struct radeon_device *rdev)
        return 0;
 }
 
-bool evergreen_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
-{
-       u32 srbm_status;
-       u32 grbm_status;
-       u32 grbm_status_se0, grbm_status_se1;
-
-       srbm_status = RREG32(SRBM_STATUS);
-       grbm_status = RREG32(GRBM_STATUS);
-       grbm_status_se0 = RREG32(GRBM_STATUS_SE0);
-       grbm_status_se1 = RREG32(GRBM_STATUS_SE1);
-       if (!(grbm_status & GUI_ACTIVE)) {
-               radeon_ring_lockup_update(ring);
-               return false;
-       }
-       /* force CP activities */
-       radeon_ring_force_activity(rdev, ring);
-       return radeon_ring_test_lockup(rdev, ring);
-}
-
-static void evergreen_gpu_soft_reset_gfx(struct radeon_device *rdev)
+void evergreen_print_gpu_status_regs(struct radeon_device *rdev)
 {
-       u32 grbm_reset = 0;
-
-       if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
-               return;
-
        dev_info(rdev->dev, "  GRBM_STATUS               = 0x%08X\n",
                RREG32(GRBM_STATUS));
        dev_info(rdev->dev, "  GRBM_STATUS_SE0           = 0x%08X\n",
@@ -2343,6 +2334,8 @@ static void evergreen_gpu_soft_reset_gfx(struct radeon_device *rdev)
                RREG32(GRBM_STATUS_SE1));
        dev_info(rdev->dev, "  SRBM_STATUS               = 0x%08X\n",
                RREG32(SRBM_STATUS));
+       dev_info(rdev->dev, "  SRBM_STATUS2              = 0x%08X\n",
+               RREG32(SRBM_STATUS2));
        dev_info(rdev->dev, "  R_008674_CP_STALLED_STAT1 = 0x%08X\n",
                RREG32(CP_STALLED_STAT1));
        dev_info(rdev->dev, "  R_008678_CP_STALLED_STAT2 = 0x%08X\n",
@@ -2351,112 +2344,289 @@ static void evergreen_gpu_soft_reset_gfx(struct radeon_device *rdev)
                RREG32(CP_BUSY_STAT));
        dev_info(rdev->dev, "  R_008680_CP_STAT          = 0x%08X\n",
                RREG32(CP_STAT));
+       dev_info(rdev->dev, "  R_00D034_DMA_STATUS_REG   = 0x%08X\n",
+               RREG32(DMA_STATUS_REG));
+       if (rdev->family >= CHIP_CAYMAN) {
+               dev_info(rdev->dev, "  R_00D834_DMA_STATUS_REG   = 0x%08X\n",
+                        RREG32(DMA_STATUS_REG + 0x800));
+       }
+}
 
-       /* Disable CP parsing/prefetching */
-       WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT);
+bool evergreen_is_display_hung(struct radeon_device *rdev)
+{
+       u32 crtc_hung = 0;
+       u32 crtc_status[6];
+       u32 i, j, tmp;
 
-       /* reset all the gfx blocks */
-       grbm_reset = (SOFT_RESET_CP |
-                     SOFT_RESET_CB |
-                     SOFT_RESET_DB |
-                     SOFT_RESET_PA |
-                     SOFT_RESET_SC |
-                     SOFT_RESET_SPI |
-                     SOFT_RESET_SH |
-                     SOFT_RESET_SX |
-                     SOFT_RESET_TC |
-                     SOFT_RESET_TA |
-                     SOFT_RESET_VC |
-                     SOFT_RESET_VGT);
-
-       dev_info(rdev->dev, "  GRBM_SOFT_RESET=0x%08X\n", grbm_reset);
-       WREG32(GRBM_SOFT_RESET, grbm_reset);
-       (void)RREG32(GRBM_SOFT_RESET);
-       DRM_UDELAY(50);
-       WREG32(GRBM_SOFT_RESET, 0);
-       (void)RREG32(GRBM_SOFT_RESET);
+       for (i = 0; i < rdev->num_crtc; i++) {
+               if (RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]) & EVERGREEN_CRTC_MASTER_EN) {
+                       crtc_status[i] = RREG32(EVERGREEN_CRTC_STATUS_HV_COUNT + crtc_offsets[i]);
+                       crtc_hung |= (1 << i);
+               }
+       }
 
-       dev_info(rdev->dev, "  GRBM_STATUS               = 0x%08X\n",
-               RREG32(GRBM_STATUS));
-       dev_info(rdev->dev, "  GRBM_STATUS_SE0           = 0x%08X\n",
-               RREG32(GRBM_STATUS_SE0));
-       dev_info(rdev->dev, "  GRBM_STATUS_SE1           = 0x%08X\n",
-               RREG32(GRBM_STATUS_SE1));
-       dev_info(rdev->dev, "  SRBM_STATUS               = 0x%08X\n",
-               RREG32(SRBM_STATUS));
-       dev_info(rdev->dev, "  R_008674_CP_STALLED_STAT1 = 0x%08X\n",
-               RREG32(CP_STALLED_STAT1));
-       dev_info(rdev->dev, "  R_008678_CP_STALLED_STAT2 = 0x%08X\n",
-               RREG32(CP_STALLED_STAT2));
-       dev_info(rdev->dev, "  R_00867C_CP_BUSY_STAT     = 0x%08X\n",
-               RREG32(CP_BUSY_STAT));
-       dev_info(rdev->dev, "  R_008680_CP_STAT          = 0x%08X\n",
-               RREG32(CP_STAT));
+       for (j = 0; j < 10; j++) {
+               for (i = 0; i < rdev->num_crtc; i++) {
+                       if (crtc_hung & (1 << i)) {
+                               tmp = RREG32(EVERGREEN_CRTC_STATUS_HV_COUNT + crtc_offsets[i]);
+                               if (tmp != crtc_status[i])
+                                       crtc_hung &= ~(1 << i);
+                       }
+               }
+               if (crtc_hung == 0)
+                       return false;
+               DRM_UDELAY(100);
+       }
+
+       return true;
 }
 
-static void evergreen_gpu_soft_reset_dma(struct radeon_device *rdev)
+static u32 evergreen_gpu_check_soft_reset(struct radeon_device *rdev)
 {
+       u32 reset_mask = 0;
        u32 tmp;
 
-       if (RREG32(DMA_STATUS_REG) & DMA_IDLE)
-               return;
+       /* GRBM_STATUS */
+       tmp = RREG32(GRBM_STATUS);
+       if (tmp & (PA_BUSY | SC_BUSY |
+                  SH_BUSY | SX_BUSY |
+                  TA_BUSY | VGT_BUSY |
+                  DB_BUSY | CB_BUSY |
+                  SPI_BUSY | VGT_BUSY_NO_DMA))
+               reset_mask |= RADEON_RESET_GFX;
 
-       dev_info(rdev->dev, "  R_00D034_DMA_STATUS_REG   = 0x%08X\n",
-               RREG32(DMA_STATUS_REG));
+       if (tmp & (CF_RQ_PENDING | PF_RQ_PENDING |
+                  CP_BUSY | CP_COHERENCY_BUSY))
+               reset_mask |= RADEON_RESET_CP;
 
-       /* Disable DMA */
-       tmp = RREG32(DMA_RB_CNTL);
-       tmp &= ~DMA_RB_ENABLE;
-       WREG32(DMA_RB_CNTL, tmp);
+       if (tmp & GRBM_EE_BUSY)
+               reset_mask |= RADEON_RESET_GRBM | RADEON_RESET_GFX | RADEON_RESET_CP;
 
-       /* Reset dma */
-       WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA);
-       RREG32(SRBM_SOFT_RESET);
-       DRM_UDELAY(50);
-       WREG32(SRBM_SOFT_RESET, 0);
+       /* DMA_STATUS_REG */
+       tmp = RREG32(DMA_STATUS_REG);
+       if (!(tmp & DMA_IDLE))
+               reset_mask |= RADEON_RESET_DMA;
 
-       dev_info(rdev->dev, "  R_00D034_DMA_STATUS_REG   = 0x%08X\n",
-               RREG32(DMA_STATUS_REG));
+       /* SRBM_STATUS2 */
+       tmp = RREG32(SRBM_STATUS2);
+       if (tmp & DMA_BUSY)
+               reset_mask |= RADEON_RESET_DMA;
+
+       /* SRBM_STATUS */
+       tmp = RREG32(SRBM_STATUS);
+       if (tmp & (RLC_RQ_PENDING | RLC_BUSY))
+               reset_mask |= RADEON_RESET_RLC;
+
+       if (tmp & IH_BUSY)
+               reset_mask |= RADEON_RESET_IH;
+
+       if (tmp & SEM_BUSY)
+               reset_mask |= RADEON_RESET_SEM;
+
+       if (tmp & GRBM_RQ_PENDING)
+               reset_mask |= RADEON_RESET_GRBM;
+
+       if (tmp & VMC_BUSY)
+               reset_mask |= RADEON_RESET_VMC;
+
+       if (tmp & (MCB_BUSY | MCB_NON_DISPLAY_BUSY |
+                  MCC_BUSY | MCD_BUSY))
+               reset_mask |= RADEON_RESET_MC;
+
+       if (evergreen_is_display_hung(rdev))
+               reset_mask |= RADEON_RESET_DISPLAY;
+
+       /* VM_L2_STATUS */
+       tmp = RREG32(VM_L2_STATUS);
+       if (tmp & L2_BUSY)
+               reset_mask |= RADEON_RESET_VMC;
+
+       /* Skip MC reset as it's mostly likely not hung, just busy */
+       if (reset_mask & RADEON_RESET_MC) {
+               DRM_DEBUG("MC busy: 0x%08X, clearing.\n", reset_mask);
+               reset_mask &= ~RADEON_RESET_MC;
+       }
+
+       return reset_mask;
 }
 
-static int evergreen_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
+static void evergreen_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
 {
        struct evergreen_mc_save save;
-
-       if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
-               reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE);
-
-       if (RREG32(DMA_STATUS_REG) & DMA_IDLE)
-               reset_mask &= ~RADEON_RESET_DMA;
+       u32 grbm_soft_reset = 0, srbm_soft_reset = 0;
+       u32 tmp;
 
        if (reset_mask == 0)
-               return 0;
+               return;
 
        dev_info(rdev->dev, "GPU softreset: 0x%08X\n", reset_mask);
 
+       evergreen_print_gpu_status_regs(rdev);
+
+       /* Disable CP parsing/prefetching */
+       WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT);
+
+       if (reset_mask & RADEON_RESET_DMA) {
+               /* Disable DMA */
+               tmp = RREG32(DMA_RB_CNTL);
+               tmp &= ~DMA_RB_ENABLE;
+               WREG32(DMA_RB_CNTL, tmp);
+       }
+
+       DRM_UDELAY(50);
+
        evergreen_mc_stop(rdev, &save);
        if (evergreen_mc_wait_for_idle(rdev)) {
                dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
        }
 
-       if (reset_mask & (RADEON_RESET_GFX | RADEON_RESET_COMPUTE))
-               evergreen_gpu_soft_reset_gfx(rdev);
+       if (reset_mask & (RADEON_RESET_GFX | RADEON_RESET_COMPUTE)) {
+               grbm_soft_reset |= SOFT_RESET_DB |
+                       SOFT_RESET_CB |
+                       SOFT_RESET_PA |
+                       SOFT_RESET_SC |
+                       SOFT_RESET_SPI |
+                       SOFT_RESET_SX |
+                       SOFT_RESET_SH |
+                       SOFT_RESET_TC |
+                       SOFT_RESET_TA |
+                       SOFT_RESET_VC |
+                       SOFT_RESET_VGT;
+       }
+
+       if (reset_mask & RADEON_RESET_CP) {
+               grbm_soft_reset |= SOFT_RESET_CP |
+                       SOFT_RESET_VGT;
+
+               srbm_soft_reset |= SOFT_RESET_GRBM;
+       }
 
        if (reset_mask & RADEON_RESET_DMA)
-               evergreen_gpu_soft_reset_dma(rdev);
+               srbm_soft_reset |= SOFT_RESET_DMA;
+
+       if (reset_mask & RADEON_RESET_DISPLAY)
+               srbm_soft_reset |= SOFT_RESET_DC;
+
+       if (reset_mask & RADEON_RESET_RLC)
+               srbm_soft_reset |= SOFT_RESET_RLC;
+
+       if (reset_mask & RADEON_RESET_SEM)
+               srbm_soft_reset |= SOFT_RESET_SEM;
+
+       if (reset_mask & RADEON_RESET_IH)
+               srbm_soft_reset |= SOFT_RESET_IH;
+
+       if (reset_mask & RADEON_RESET_GRBM)
+               srbm_soft_reset |= SOFT_RESET_GRBM;
+
+       if (reset_mask & RADEON_RESET_VMC)
+               srbm_soft_reset |= SOFT_RESET_VMC;
+
+       if (!(rdev->flags & RADEON_IS_IGP)) {
+               if (reset_mask & RADEON_RESET_MC)
+                       srbm_soft_reset |= SOFT_RESET_MC;
+       }
+
+       if (grbm_soft_reset) {
+               tmp = RREG32(GRBM_SOFT_RESET);
+               tmp |= grbm_soft_reset;
+               dev_info(rdev->dev, "GRBM_SOFT_RESET=0x%08X\n", tmp);
+               WREG32(GRBM_SOFT_RESET, tmp);
+               tmp = RREG32(GRBM_SOFT_RESET);
+
+               DRM_UDELAY(50);
+
+               tmp &= ~grbm_soft_reset;
+               WREG32(GRBM_SOFT_RESET, tmp);
+               tmp = RREG32(GRBM_SOFT_RESET);
+       }
+
+       if (srbm_soft_reset) {
+               tmp = RREG32(SRBM_SOFT_RESET);
+               tmp |= srbm_soft_reset;
+               dev_info(rdev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp);
+               WREG32(SRBM_SOFT_RESET, tmp);
+               tmp = RREG32(SRBM_SOFT_RESET);
+
+               DRM_UDELAY(50);
+
+               tmp &= ~srbm_soft_reset;
+               WREG32(SRBM_SOFT_RESET, tmp);
+               tmp = RREG32(SRBM_SOFT_RESET);
+       }
 
        /* Wait a little for things to settle down */
        DRM_UDELAY(50);
 
        evergreen_mc_resume(rdev, &save);
-       return 0;
+       DRM_UDELAY(50);
+
+       evergreen_print_gpu_status_regs(rdev);
 }
 
 int evergreen_asic_reset(struct radeon_device *rdev)
 {
-       return evergreen_gpu_soft_reset(rdev, (RADEON_RESET_GFX |
-                                              RADEON_RESET_COMPUTE |
-                                              RADEON_RESET_DMA));
+       u32 reset_mask;
+
+       reset_mask = evergreen_gpu_check_soft_reset(rdev);
+
+       if (reset_mask)
+               r600_set_bios_scratch_engine_hung(rdev, true);
+
+       evergreen_gpu_soft_reset(rdev, reset_mask);
+
+       reset_mask = evergreen_gpu_check_soft_reset(rdev);
+
+       if (!reset_mask)
+               r600_set_bios_scratch_engine_hung(rdev, false);
+
+       return 0;
+}
+
+/**
+ * evergreen_gfx_is_lockup - Check if the GFX engine is locked up
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon_ring structure holding ring information
+ *
+ * Check if the GFX engine is locked up.
+ * Returns true if the engine appears to be locked up, false if not.
+ */
+bool evergreen_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
+{
+       u32 reset_mask = evergreen_gpu_check_soft_reset(rdev);
+
+       if (!(reset_mask & (RADEON_RESET_GFX |
+                           RADEON_RESET_COMPUTE |
+                           RADEON_RESET_CP))) {
+               radeon_ring_lockup_update(ring);
+               return false;
+       }
+       /* force CP activities */
+       radeon_ring_force_activity(rdev, ring);
+       return radeon_ring_test_lockup(rdev, ring);
+}
+
+/**
+ * evergreen_dma_is_lockup - Check if the DMA engine is locked up
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon_ring structure holding ring information
+ *
+ * Check if the async DMA engine is locked up.
+ * Returns true if the engine appears to be locked up, false if not.
+ */
+bool evergreen_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
+{
+       u32 reset_mask = evergreen_gpu_check_soft_reset(rdev);
+
+       if (!(reset_mask & RADEON_RESET_DMA)) {
+               radeon_ring_lockup_update(ring);
+               return false;
+       }
+       /* force ring activities */
+       radeon_ring_force_activity(rdev, ring);
+       return radeon_ring_test_lockup(rdev, ring);
 }
 
 /* Interrupts */
@@ -3281,14 +3451,14 @@ void evergreen_dma_fence_ring_emit(struct radeon_device *rdev,
        struct radeon_ring *ring = &rdev->ring[fence->ring];
        u64 addr = rdev->fence_drv[fence->ring].gpu_addr;
        /* write the fence */
-       radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_FENCE, 0, 0, 0));
+       radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_FENCE, 0, 0));
        radeon_ring_write(ring, addr & 0xfffffffc);
        radeon_ring_write(ring, (upper_32_bits(addr) & 0xff));
        radeon_ring_write(ring, fence->seq);
        /* generate an interrupt */
-       radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_TRAP, 0, 0, 0));
+       radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_TRAP, 0, 0));
        /* flush HDP */
-       radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_SRBM_WRITE, 0, 0, 0));
+       radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_SRBM_WRITE, 0, 0));
        radeon_ring_write(ring, (0xf << 16) | (HDP_MEM_COHERENCY_FLUSH_CNTL >> 2));
        radeon_ring_write(ring, 1);
 }
@@ -3311,7 +3481,7 @@ void evergreen_dma_ring_ib_execute(struct radeon_device *rdev,
                while ((next_rptr & 7) != 5)
                        next_rptr++;
                next_rptr += 3;
-               radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_WRITE, 0, 0, 1));
+               radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_WRITE, 0, 1));
                radeon_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc);
                radeon_ring_write(ring, upper_32_bits(ring->next_rptr_gpu_addr) & 0xff);
                radeon_ring_write(ring, next_rptr);
@@ -3321,8 +3491,8 @@ void evergreen_dma_ring_ib_execute(struct radeon_device *rdev,
         * Pad as necessary with NOPs.
         */
        while ((ring->wptr & 7) != 5)
-               radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0));
-       radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_INDIRECT_BUFFER, 0, 0, 0));
+               radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_NOP, 0, 0));
+       radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_INDIRECT_BUFFER, 0, 0));
        radeon_ring_write(ring, (ib->gpu_addr & 0xFFFFFFE0));
        radeon_ring_write(ring, (ib->length_dw << 12) | (upper_32_bits(ib->gpu_addr) & 0xFF));
 
@@ -3381,7 +3551,7 @@ int evergreen_copy_dma(struct radeon_device *rdev,
                if (cur_size_in_dw > 0xFFFFF)
                        cur_size_in_dw = 0xFFFFF;
                size_in_dw -= cur_size_in_dw;
-               radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_COPY, 0, 0, cur_size_in_dw));
+               radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_COPY, 0, cur_size_in_dw));
                radeon_ring_write(ring, dst_offset & 0xfffffffc);
                radeon_ring_write(ring, src_offset & 0xfffffffc);
                radeon_ring_write(ring, upper_32_bits(dst_offset) & 0xff);
@@ -3489,7 +3659,7 @@ static int evergreen_startup(struct radeon_device *rdev)
        ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET,
                             DMA_RB_RPTR, DMA_RB_WPTR,
-                            2, 0x3fffc, DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0));
+                            2, 0x3fffc, DMA_PACKET(DMA_PACKET_NOP, 0, 0));
        if (r)
                return r;
 
index ea3902c..f0e4f57 100644 (file)
@@ -39,9 +39,6 @@
 #define MAX(a,b)                   (((a)>(b))?(a):(b))
 #define MIN(a,b)                   (((a)<(b))?(a):(b))
 
-static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p,
-                                         struct radeon_cs_reloc **cs_reloc);
-
 struct evergreen_cs_track {
        u32                     group_size;
        u32                     nbanks;
@@ -840,7 +837,7 @@ static int evergreen_cs_track_validate_texture(struct radeon_cs_parser *p,
                         __func__, __LINE__, toffset, surf.base_align);
                return -EINVAL;
        }
-       if (moffset & (surf.base_align - 1)) {
+       if (surf.nsamples <= 1 && moffset & (surf.base_align - 1)) {
                dev_warn(p->dev, "%s:%d mipmap bo base %ld not aligned with %ld\n",
                         __func__, __LINE__, moffset, surf.base_align);
                return -EINVAL;
@@ -1012,223 +1009,35 @@ static int evergreen_cs_track_check(struct radeon_cs_parser *p)
 }
 
 /**
- * evergreen_cs_packet_parse() - parse cp packet and point ib index to next packet
- * @parser:    parser structure holding parsing context.
- * @pkt:       where to store packet informations
- *
- * Assume that chunk_ib_index is properly set. Will return -EINVAL
- * if packet is bigger than remaining ib size. or if packets is unknown.
- **/
-static int evergreen_cs_packet_parse(struct radeon_cs_parser *p,
-                             struct radeon_cs_packet *pkt,
-                             unsigned idx)
-{
-       struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx];
-       uint32_t header;
-
-       if (idx >= ib_chunk->length_dw) {
-               DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
-                         idx, ib_chunk->length_dw);
-               return -EINVAL;
-       }
-       header = radeon_get_ib_value(p, idx);
-       pkt->idx = idx;
-       pkt->type = CP_PACKET_GET_TYPE(header);
-       pkt->count = CP_PACKET_GET_COUNT(header);
-       pkt->one_reg_wr = 0;
-       switch (pkt->type) {
-       case PACKET_TYPE0:
-               pkt->reg = CP_PACKET0_GET_REG(header);
-               break;
-       case PACKET_TYPE3:
-               pkt->opcode = CP_PACKET3_GET_OPCODE(header);
-               break;
-       case PACKET_TYPE2:
-               pkt->count = -1;
-               break;
-       default:
-               DRM_ERROR("Unknown packet type %d at %d !\n", pkt->type, idx);
-               return -EINVAL;
-       }
-       if ((pkt->count + 1 + pkt->idx) >= ib_chunk->length_dw) {
-               DRM_ERROR("Packet (%d:%d:%d) end after CS buffer (%d) !\n",
-                         pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw);
-               return -EINVAL;
-       }
-       return 0;
-}
-
-/**
- * evergreen_cs_packet_next_reloc() - parse next packet which should be reloc packet3
+ * evergreen_cs_packet_parse_vline() - parse userspace VLINE packet
  * @parser:            parser structure holding parsing context.
- * @data:              pointer to relocation data
- * @offset_start:      starting offset
- * @offset_mask:       offset mask (to align start offset on)
- * @reloc:             reloc informations
  *
- * Check next packet is relocation packet3, do bo validation and compute
- * GPU offset using the provided start.
- **/
-static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p,
-                                         struct radeon_cs_reloc **cs_reloc)
-{
-       struct radeon_cs_chunk *relocs_chunk;
-       struct radeon_cs_packet p3reloc;
-       unsigned idx;
-       int r;
-
-       if (p->chunk_relocs_idx == -1) {
-               DRM_ERROR("No relocation chunk !\n");
-               return -EINVAL;
-       }
-       *cs_reloc = NULL;
-       relocs_chunk = &p->chunks[p->chunk_relocs_idx];
-       r = evergreen_cs_packet_parse(p, &p3reloc, p->idx);
-       if (r) {
-               return r;
-       }
-       p->idx += p3reloc.count + 2;
-       if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
-               DRM_ERROR("No packet3 for relocation for packet at %d.\n",
-                         p3reloc.idx);
-               return -EINVAL;
-       }
-       idx = radeon_get_ib_value(p, p3reloc.idx + 1);
-       if (idx >= relocs_chunk->length_dw) {
-               DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
-                         idx, relocs_chunk->length_dw);
-               return -EINVAL;
-       }
-       /* FIXME: we assume reloc size is 4 dwords */
-       *cs_reloc = p->relocs_ptr[(idx / 4)];
-       return 0;
-}
-
-/**
- * evergreen_cs_packet_next_is_pkt3_nop() - test if the next packet is NOP
- * @p:         structure holding the parser context.
- *
- * Check if the next packet is a relocation packet3.
- **/
-static bool evergreen_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p)
-{
-       struct radeon_cs_packet p3reloc;
-       int r;
-
-       r = evergreen_cs_packet_parse(p, &p3reloc, p->idx);
-       if (r) {
-               return false;
-       }
-       if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
-               return false;
-       }
-       return true;
-}
-
-/**
- * evergreen_cs_packet_next_vline() - parse userspace VLINE packet
- * @parser:            parser structure holding parsing context.
- *
- * Userspace sends a special sequence for VLINE waits.
- * PACKET0 - VLINE_START_END + value
- * PACKET3 - WAIT_REG_MEM poll vline status reg
- * RELOC (P3) - crtc_id in reloc.
- *
- * This function parses this and relocates the VLINE START END
- * and WAIT_REG_MEM packets to the correct crtc.
- * It also detects a switched off crtc and nulls out the
- * wait in that case.
+ * This is an Evergreen(+)-specific function for parsing VLINE packets.
+ * Real work is done by r600_cs_common_vline_parse function.
+ * Here we just set up ASIC-specific register table and call
+ * the common implementation function.
  */
 static int evergreen_cs_packet_parse_vline(struct radeon_cs_parser *p)
 {
-       struct drm_mode_object *obj;
-       struct drm_crtc *crtc;
-       struct radeon_crtc *radeon_crtc;
-       struct radeon_cs_packet p3reloc, wait_reg_mem;
-       int crtc_id;
-       int r;
-       uint32_t header, h_idx, reg, wait_reg_mem_info;
-       volatile uint32_t *ib;
-
-       ib = p->ib.ptr;
-
-       /* parse the WAIT_REG_MEM */
-       r = evergreen_cs_packet_parse(p, &wait_reg_mem, p->idx);
-       if (r)
-               return r;
-
-       /* check its a WAIT_REG_MEM */
-       if (wait_reg_mem.type != PACKET_TYPE3 ||
-           wait_reg_mem.opcode != PACKET3_WAIT_REG_MEM) {
-               DRM_ERROR("vline wait missing WAIT_REG_MEM segment\n");
-               return -EINVAL;
-       }
-
-       wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1);
-       /* bit 4 is reg (0) or mem (1) */
-       if (wait_reg_mem_info & 0x10) {
-               DRM_ERROR("vline WAIT_REG_MEM waiting on MEM rather than REG\n");
-               return -EINVAL;
-       }
-       /* waiting for value to be equal */
-       if ((wait_reg_mem_info & 0x7) != 0x3) {
-               DRM_ERROR("vline WAIT_REG_MEM function not equal\n");
-               return -EINVAL;
-       }
-       if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != EVERGREEN_VLINE_STATUS) {
-               DRM_ERROR("vline WAIT_REG_MEM bad reg\n");
-               return -EINVAL;
-       }
-
-       if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != EVERGREEN_VLINE_STAT) {
-               DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n");
-               return -EINVAL;
-       }
-
-       /* jump over the NOP */
-       r = evergreen_cs_packet_parse(p, &p3reloc, p->idx + wait_reg_mem.count + 2);
-       if (r)
-               return r;
 
-       h_idx = p->idx - 2;
-       p->idx += wait_reg_mem.count + 2;
-       p->idx += p3reloc.count + 2;
-
-       header = radeon_get_ib_value(p, h_idx);
-       crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1);
-       reg = CP_PACKET0_GET_REG(header);
-       obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
-       if (!obj) {
-               DRM_ERROR("cannot find crtc %d\n", crtc_id);
-               return -EINVAL;
-       }
-       crtc = obj_to_crtc(obj);
-       radeon_crtc = to_radeon_crtc(crtc);
-       crtc_id = radeon_crtc->crtc_id;
-
-       if (!crtc->enabled) {
-               /* if the CRTC isn't enabled - we need to nop out the WAIT_REG_MEM */
-               ib[h_idx + 2] = PACKET2(0);
-               ib[h_idx + 3] = PACKET2(0);
-               ib[h_idx + 4] = PACKET2(0);
-               ib[h_idx + 5] = PACKET2(0);
-               ib[h_idx + 6] = PACKET2(0);
-               ib[h_idx + 7] = PACKET2(0);
-               ib[h_idx + 8] = PACKET2(0);
-       } else {
-               switch (reg) {
-               case EVERGREEN_VLINE_START_END:
-                       header &= ~R600_CP_PACKET0_REG_MASK;
-                       header |= (EVERGREEN_VLINE_START_END + radeon_crtc->crtc_offset) >> 2;
-                       ib[h_idx] = header;
-                       ib[h_idx + 4] = (EVERGREEN_VLINE_STATUS + radeon_crtc->crtc_offset) >> 2;
-                       break;
-               default:
-                       DRM_ERROR("unknown crtc reloc\n");
-                       return -EINVAL;
-               }
-       }
-       return 0;
+       static uint32_t vline_start_end[6] = {
+               EVERGREEN_VLINE_START_END + EVERGREEN_CRTC0_REGISTER_OFFSET,
+               EVERGREEN_VLINE_START_END + EVERGREEN_CRTC1_REGISTER_OFFSET,
+               EVERGREEN_VLINE_START_END + EVERGREEN_CRTC2_REGISTER_OFFSET,
+               EVERGREEN_VLINE_START_END + EVERGREEN_CRTC3_REGISTER_OFFSET,
+               EVERGREEN_VLINE_START_END + EVERGREEN_CRTC4_REGISTER_OFFSET,
+               EVERGREEN_VLINE_START_END + EVERGREEN_CRTC5_REGISTER_OFFSET
+       };
+       static uint32_t vline_status[6] = {
+               EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET,
+               EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET,
+               EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET,
+               EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET,
+               EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET,
+               EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET
+       };
+
+       return r600_cs_common_vline_parse(p, vline_start_end, vline_status);
 }
 
 static int evergreen_packet0_check(struct radeon_cs_parser *p,
@@ -1350,7 +1159,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
        case SQ_LSTMP_RING_BASE:
        case SQ_PSTMP_RING_BASE:
        case SQ_VSTMP_RING_BASE:
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
@@ -1379,7 +1188,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
        case DB_Z_INFO:
                track->db_z_info = radeon_get_ib_value(p, idx);
                if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
-                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                        if (r) {
                                dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                                "0x%04X\n", reg);
@@ -1421,7 +1230,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                track->db_dirty = true;
                break;
        case DB_Z_READ_BASE:
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
@@ -1433,7 +1242,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                track->db_dirty = true;
                break;
        case DB_Z_WRITE_BASE:
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
@@ -1445,7 +1254,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                track->db_dirty = true;
                break;
        case DB_STENCIL_READ_BASE:
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
@@ -1457,7 +1266,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                track->db_dirty = true;
                break;
        case DB_STENCIL_WRITE_BASE:
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
@@ -1480,7 +1289,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
        case VGT_STRMOUT_BUFFER_BASE_1:
        case VGT_STRMOUT_BUFFER_BASE_2:
        case VGT_STRMOUT_BUFFER_BASE_3:
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
@@ -1502,7 +1311,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                track->streamout_dirty = true;
                break;
        case CP_COHER_BASE:
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_warn(p->dev, "missing reloc for CP_COHER_BASE "
                                        "0x%04X\n", reg);
@@ -1566,7 +1375,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                tmp = (reg - CB_COLOR0_INFO) / 0x3c;
                track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
                if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
-                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                        if (r) {
                                dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                                "0x%04X\n", reg);
@@ -1584,7 +1393,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                tmp = ((reg - CB_COLOR8_INFO) / 0x1c) + 8;
                track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
                if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
-                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                        if (r) {
                                dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                                "0x%04X\n", reg);
@@ -1645,7 +1454,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
        case CB_COLOR5_ATTRIB:
        case CB_COLOR6_ATTRIB:
        case CB_COLOR7_ATTRIB:
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
@@ -1673,7 +1482,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
        case CB_COLOR9_ATTRIB:
        case CB_COLOR10_ATTRIB:
        case CB_COLOR11_ATTRIB:
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
@@ -1706,7 +1515,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
        case CB_COLOR6_FMASK:
        case CB_COLOR7_FMASK:
                tmp = (reg - CB_COLOR0_FMASK) / 0x3c;
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
                        return -EINVAL;
@@ -1723,7 +1532,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
        case CB_COLOR6_CMASK:
        case CB_COLOR7_CMASK:
                tmp = (reg - CB_COLOR0_CMASK) / 0x3c;
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
                        return -EINVAL;
@@ -1761,7 +1570,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
        case CB_COLOR5_BASE:
        case CB_COLOR6_BASE:
        case CB_COLOR7_BASE:
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
@@ -1777,7 +1586,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
        case CB_COLOR9_BASE:
        case CB_COLOR10_BASE:
        case CB_COLOR11_BASE:
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
@@ -1790,7 +1599,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                track->cb_dirty = true;
                break;
        case DB_HTILE_DATA_BASE:
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
@@ -1908,7 +1717,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
        case SQ_ALU_CONST_CACHE_LS_13:
        case SQ_ALU_CONST_CACHE_LS_14:
        case SQ_ALU_CONST_CACHE_LS_15:
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
@@ -1922,7 +1731,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                                 "0x%04X\n", reg);
                        return -EINVAL;
                }
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONFIG_REG "
                                        "0x%04X\n", reg);
@@ -1936,7 +1745,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                                 "0x%04X\n", reg);
                        return -EINVAL;
                }
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
@@ -2021,7 +1830,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
                        return -EINVAL;
                }
 
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("bad SET PREDICATION\n");
                        return -EINVAL;
@@ -2067,7 +1876,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
                        DRM_ERROR("bad INDEX_BASE\n");
                        return -EINVAL;
                }
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("bad INDEX_BASE\n");
                        return -EINVAL;
@@ -2094,7 +1903,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
                        DRM_ERROR("bad DRAW_INDEX\n");
                        return -EINVAL;
                }
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("bad DRAW_INDEX\n");
                        return -EINVAL;
@@ -2122,7 +1931,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
                        DRM_ERROR("bad DRAW_INDEX_2\n");
                        return -EINVAL;
                }
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("bad DRAW_INDEX_2\n");
                        return -EINVAL;
@@ -2213,7 +2022,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
                        DRM_ERROR("bad DISPATCH_INDIRECT\n");
                        return -EINVAL;
                }
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("bad DISPATCH_INDIRECT\n");
                        return -EINVAL;
@@ -2234,7 +2043,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
                if (idx_value & 0x10) {
                        uint64_t offset;
 
-                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                        if (r) {
                                DRM_ERROR("bad WAIT_REG_MEM\n");
                                return -EINVAL;
@@ -2246,6 +2055,9 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
 
                        ib[idx+1] = (ib[idx+1] & 0x3) | (offset & 0xfffffffc);
                        ib[idx+2] = upper_32_bits(offset) & 0xff;
+               } else if (idx_value & 0x100) {
+                       DRM_ERROR("cannot use PFP on REG wait\n");
+                       return -EINVAL;
                }
                break;
        case PACKET3_CP_DMA:
@@ -2285,7 +2097,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
                        }
                        /* src address space is memory */
                        if (((info & 0x60000000) >> 29) == 0) {
-                               r = evergreen_cs_packet_next_reloc(p, &reloc);
+                               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                                if (r) {
                                        DRM_ERROR("bad CP DMA SRC\n");
                                        return -EINVAL;
@@ -2323,7 +2135,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
                                return -EINVAL;
                        }
                        if (((info & 0x00300000) >> 20) == 0) {
-                               r = evergreen_cs_packet_next_reloc(p, &reloc);
+                               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                                if (r) {
                                        DRM_ERROR("bad CP DMA DST\n");
                                        return -EINVAL;
@@ -2357,7 +2169,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
                /* 0xffffffff/0x0 is flush all cache flag */
                if (radeon_get_ib_value(p, idx + 1) != 0xffffffff ||
                    radeon_get_ib_value(p, idx + 2) != 0) {
-                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                        if (r) {
                                DRM_ERROR("bad SURFACE_SYNC\n");
                                return -EINVAL;
@@ -2373,7 +2185,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
                if (pkt->count) {
                        uint64_t offset;
 
-                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                        if (r) {
                                DRM_ERROR("bad EVENT_WRITE\n");
                                return -EINVAL;
@@ -2394,7 +2206,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
                        DRM_ERROR("bad EVENT_WRITE_EOP\n");
                        return -EINVAL;
                }
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("bad EVENT_WRITE_EOP\n");
                        return -EINVAL;
@@ -2416,7 +2228,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
                        DRM_ERROR("bad EVENT_WRITE_EOS\n");
                        return -EINVAL;
                }
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("bad EVENT_WRITE_EOS\n");
                        return -EINVAL;
@@ -2483,7 +2295,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
                        switch (G__SQ_CONSTANT_TYPE(radeon_get_ib_value(p, idx+1+(i*8)+7))) {
                        case SQ_TEX_VTX_VALID_TEXTURE:
                                /* tex base */
-                               r = evergreen_cs_packet_next_reloc(p, &reloc);
+                               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                                if (r) {
                                        DRM_ERROR("bad SET_RESOURCE (tex)\n");
                                        return -EINVAL;
@@ -2514,13 +2326,13 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
 
                                if ((tex_dim == SQ_TEX_DIM_2D_MSAA || tex_dim == SQ_TEX_DIM_2D_ARRAY_MSAA) &&
                                    !mip_address &&
-                                   !evergreen_cs_packet_next_is_pkt3_nop(p)) {
+                                   !radeon_cs_packet_next_is_pkt3_nop(p)) {
                                        /* MIP_ADDRESS should point to FMASK for an MSAA texture.
                                         * It should be 0 if FMASK is disabled. */
                                        moffset = 0;
                                        mipmap = NULL;
                                } else {
-                                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                                       r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                                        if (r) {
                                                DRM_ERROR("bad SET_RESOURCE (tex)\n");
                                                return -EINVAL;
@@ -2539,7 +2351,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
                        {
                                uint64_t offset64;
                                /* vtx base */
-                               r = evergreen_cs_packet_next_reloc(p, &reloc);
+                               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                                if (r) {
                                        DRM_ERROR("bad SET_RESOURCE (vtx)\n");
                                        return -EINVAL;
@@ -2621,7 +2433,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
                /* Updating memory at DST_ADDRESS. */
                if (idx_value & 0x1) {
                        u64 offset;
-                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                        if (r) {
                                DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing dst reloc)\n");
                                return -EINVAL;
@@ -2640,7 +2452,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
                /* Reading data from SRC_ADDRESS. */
                if (((idx_value >> 1) & 0x3) == 2) {
                        u64 offset;
-                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                        if (r) {
                                DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing src reloc)\n");
                                return -EINVAL;
@@ -2665,7 +2477,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
                        DRM_ERROR("bad MEM_WRITE (invalid count)\n");
                        return -EINVAL;
                }
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("bad MEM_WRITE (missing reloc)\n");
                        return -EINVAL;
@@ -2694,7 +2506,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
                if (idx_value & 0x1) {
                        u64 offset;
                        /* SRC is memory. */
-                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                        if (r) {
                                DRM_ERROR("bad COPY_DW (missing src reloc)\n");
                                return -EINVAL;
@@ -2718,7 +2530,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
                if (idx_value & 0x2) {
                        u64 offset;
                        /* DST is memory. */
-                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                        if (r) {
                                DRM_ERROR("bad COPY_DW (missing dst reloc)\n");
                                return -EINVAL;
@@ -2823,7 +2635,7 @@ int evergreen_cs_parse(struct radeon_cs_parser *p)
                p->track = track;
        }
        do {
-               r = evergreen_cs_packet_parse(p, &pkt, p->idx);
+               r = radeon_cs_packet_parse(p, &pkt, p->idx);
                if (r) {
                        drm_free(p->track, M_DRM);
                        p->track = NULL;
@@ -2831,12 +2643,12 @@ int evergreen_cs_parse(struct radeon_cs_parser *p)
                }
                p->idx += pkt.count + 2;
                switch (pkt.type) {
-               case PACKET_TYPE0:
+               case RADEON_PACKET_TYPE0:
                        r = evergreen_cs_parse_packet0(p, &pkt);
                        break;
-               case PACKET_TYPE2:
+               case RADEON_PACKET_TYPE2:
                        break;
-               case PACKET_TYPE3:
+               case RADEON_PACKET_TYPE3:
                        r = evergreen_packet3_check(p, &pkt);
                        break;
                default:
@@ -2862,16 +2674,6 @@ int evergreen_cs_parse(struct radeon_cs_parser *p)
        return 0;
 }
 
-/*
- *  DMA
- */
-
-#define GET_DMA_CMD(h) (((h) & 0xf0000000) >> 28)
-#define GET_DMA_COUNT(h) ((h) & 0x000fffff)
-#define GET_DMA_T(h) (((h) & 0x00800000) >> 23)
-#define GET_DMA_NEW(h) (((h) & 0x04000000) >> 26)
-#define GET_DMA_MISC(h) (((h) & 0x0700000) >> 20)
-
 /**
  * evergreen_dma_cs_parse() - parse the DMA IB
  * @p:         parser structure holding parsing context.
@@ -2885,9 +2687,9 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
 {
        struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx];
        struct radeon_cs_reloc *src_reloc, *dst_reloc, *dst2_reloc;
-       u32 header, cmd, count, tiled, new_cmd, misc;
+       u32 header, cmd, count, sub_cmd;
        volatile u32 *ib = p->ib.ptr;
-       u32 idx, idx_value;
+       u32 idx;
        u64 src_offset, dst_offset, dst2_offset;
        int r;
 
@@ -2901,9 +2703,7 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
                header = radeon_get_ib_value(p, idx);
                cmd = GET_DMA_CMD(header);
                count = GET_DMA_COUNT(header);
-               tiled = GET_DMA_T(header);
-               new_cmd = GET_DMA_NEW(header);
-               misc = GET_DMA_MISC(header);
+               sub_cmd = GET_DMA_SUB_CMD(header);
 
                switch (cmd) {
                case DMA_PACKET_WRITE:
@@ -2912,19 +2712,27 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
                                DRM_ERROR("bad DMA_PACKET_WRITE\n");
                                return -EINVAL;
                        }
-                       if (tiled) {
-                               dst_offset = radeon_get_ib_value(p, idx+1);
+                       switch (sub_cmd) {
+                       /* tiled */
+                       case 8:
+                               dst_offset = ib[idx+1];
                                dst_offset <<= 8;
 
                                ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
                                p->idx += count + 7;
-                       } else {
-                               dst_offset = radeon_get_ib_value(p, idx+1);
-                               dst_offset |= ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32;
+                               break;
+                       /* linear */
+                       case 0:
+                               dst_offset = ib[idx+1];
+                               dst_offset |= ((u64)(ib[idx+2] & 0xff)) << 32;
 
                                ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
                                ib[idx+2] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
                                p->idx += count + 3;
+                               break;
+                       default:
+                               DRM_ERROR("bad DMA_PACKET_WRITE [%6d] 0x%08x sub cmd is not 0 or 8\n", idx, ib[idx+0]);
+                               return -EINVAL;
                        }
                        if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
                                dev_warn(p->dev, "DMA write buffer too small (%ju %lu)\n",
@@ -2943,338 +2751,330 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
                                DRM_ERROR("bad DMA_PACKET_COPY\n");
                                return -EINVAL;
                        }
-                       if (tiled) {
-                               idx_value = radeon_get_ib_value(p, idx + 2);
-                               if (new_cmd) {
-                                       switch (misc) {
-                                       case 0:
-                                               /* L2T, frame to fields */
-                                               if (idx_value & (1 << 31)) {
-                                                       DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n");
-                                                       return -EINVAL;
-                                               }
-                                               r = r600_dma_cs_next_reloc(p, &dst2_reloc);
-                                               if (r) {
-                                                       DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n");
-                                                       return -EINVAL;
-                                               }
-                                               dst_offset = radeon_get_ib_value(p, idx+1);
-                                               dst_offset <<= 8;
-                                               dst2_offset = radeon_get_ib_value(p, idx+2);
-                                               dst2_offset <<= 8;
-                                               src_offset = radeon_get_ib_value(p, idx+8);
-                                               src_offset |= ((u64)(radeon_get_ib_value(p, idx+9) & 0xff)) << 32;
-                                               if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2T, frame to fields src buffer too small (%ju %lu)\n",
-                                                                (uintmax_t)src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2T, frame to fields buffer too small (%ju %lu)\n",
-                                                                (uintmax_t)dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2T, frame to fields buffer too small (%ju %lu)\n",
-                                                                (uintmax_t)dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
-                                               ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8);
-                                               ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
-                                               ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
-                                               p->idx += 10;
-                                               break;
-                                       case 1:
-                                               /* L2T, T2L partial */
-                                               if (p->family < CHIP_CAYMAN) {
-                                                       DRM_ERROR("L2T, T2L Partial is cayman only !\n");
-                                                       return -EINVAL;
-                                               }
-                                               /* detile bit */
-                                               if (idx_value & (1 << 31)) {
-                                                       /* tiled src, linear dst */
-                                                       ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
-
-                                                       ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
-                                                       ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
-                                               } else {
-                                                       /* linear src, tiled dst */
-                                                       ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
-                                                       ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
-
-                                                       ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
-                                               }
-                                               p->idx += 12;
-                                               break;
-                                       case 3:
-                                               /* L2T, broadcast */
-                                               if (idx_value & (1 << 31)) {
-                                                       DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
-                                                       return -EINVAL;
-                                               }
-                                               r = r600_dma_cs_next_reloc(p, &dst2_reloc);
-                                               if (r) {
-                                                       DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
-                                                       return -EINVAL;
-                                               }
-                                               dst_offset = radeon_get_ib_value(p, idx+1);
-                                               dst_offset <<= 8;
-                                               dst2_offset = radeon_get_ib_value(p, idx+2);
-                                               dst2_offset <<= 8;
-                                               src_offset = radeon_get_ib_value(p, idx+8);
-                                               src_offset |= ((u64)(radeon_get_ib_value(p, idx+9) & 0xff)) << 32;
-                                               if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%ju %lu)\n",
-                                                                (uintmax_t)src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%ju %lu)\n",
-                                                                (uintmax_t)dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2T, broadcast dst2 buffer too small (%ju %lu)\n",
-                                                                (uintmax_t)dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
-                                               ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8);
-                                               ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
-                                               ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
-                                               p->idx += 10;
-                                               break;
-                                       case 4:
-                                               /* L2T, T2L */
-                                               /* detile bit */
-                                               if (idx_value & (1 << 31)) {
-                                                       /* tiled src, linear dst */
-                                                       src_offset = radeon_get_ib_value(p, idx+1);
-                                                       src_offset <<= 8;
-                                                       ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
-
-                                                       dst_offset = radeon_get_ib_value(p, idx+7);
-                                                       dst_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32;
-                                                       ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
-                                                       ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
-                                               } else {
-                                                       /* linear src, tiled dst */
-                                                       src_offset = radeon_get_ib_value(p, idx+7);
-                                                       src_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32;
-                                                       ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
-                                                       ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
-
-                                                       dst_offset = radeon_get_ib_value(p, idx+1);
-                                                       dst_offset <<= 8;
-                                                       ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
-                                               }
-                                               if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2T, T2L src buffer too small (%ju %lu)\n",
-                                                                (uintmax_t)src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2T, T2L dst buffer too small (%ju %lu)\n",
-                                                                (uintmax_t)dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               p->idx += 9;
-                                               break;
-                                       case 5:
-                                               /* T2T partial */
-                                               if (p->family < CHIP_CAYMAN) {
-                                                       DRM_ERROR("L2T, T2L Partial is cayman only !\n");
-                                                       return -EINVAL;
-                                               }
-                                               ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
-                                               ib[idx+4] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
-                                               p->idx += 13;
-                                               break;
-                                       case 7:
-                                               /* L2T, broadcast */
-                                               if (idx_value & (1 << 31)) {
-                                                       DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
-                                                       return -EINVAL;
-                                               }
-                                               r = r600_dma_cs_next_reloc(p, &dst2_reloc);
-                                               if (r) {
-                                                       DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
-                                                       return -EINVAL;
-                                               }
-                                               dst_offset = radeon_get_ib_value(p, idx+1);
-                                               dst_offset <<= 8;
-                                               dst2_offset = radeon_get_ib_value(p, idx+2);
-                                               dst2_offset <<= 8;
-                                               src_offset = radeon_get_ib_value(p, idx+8);
-                                               src_offset |= ((u64)(radeon_get_ib_value(p, idx+9) & 0xff)) << 32;
-                                               if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%ju %lu)\n",
-                                                                (uintmax_t)src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%ju %lu)\n",
-                                                                (uintmax_t)dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2T, broadcast dst2 buffer too small (%ju %lu)\n",
-                                                                (uintmax_t)dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
-                                               ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8);
-                                               ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
-                                               ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
-                                               p->idx += 10;
-                                               break;
-                                       default:
-                                               DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
-                                               return -EINVAL;
-                                       }
+                       switch (sub_cmd) {
+                       /* Copy L2L, DW aligned */
+                       case 0x00:
+                               /* L2L, dw */
+                               src_offset = ib[idx+2];
+                               src_offset |= ((u64)(ib[idx+4] & 0xff)) << 32;
+                               dst_offset = ib[idx+1];
+                               dst_offset |= ((u64)(ib[idx+3] & 0xff)) << 32;
+                               if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2L, dw src buffer too small (%ju %lu)\n",
+                                                       (uintmax_t)src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2L, dw dst buffer too small (%ju %lu)\n",
+                                                       (uintmax_t)dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
+                               ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
+                               ib[idx+3] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
+                               ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
+                               p->idx += 5;
+                               break;
+                       /* Copy L2T/T2L */
+                       case 0x08:
+                               /* detile bit */
+                               if (ib[idx + 2] & (1 << 31)) {
+                                       /* tiled src, linear dst */
+                                       src_offset = ib[idx+1];
+                                       src_offset <<= 8;
+                                       ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
+
+                                       dst_offset = radeon_get_ib_value(p, idx + 7);
+                                       dst_offset |= ((u64)(ib[idx+8] & 0xff)) << 32;
+                                       ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
+                                       ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
                                } else {
-                                       switch (misc) {
-                                       case 0:
-                                               /* detile bit */
-                                               if (idx_value & (1 << 31)) {
-                                                       /* tiled src, linear dst */
-                                                       src_offset = radeon_get_ib_value(p, idx+1);
-                                                       src_offset <<= 8;
-                                                       ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
-
-                                                       dst_offset = radeon_get_ib_value(p, idx+7);
-                                                       dst_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32;
-                                                       ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
-                                                       ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
-                                               } else {
-                                                       /* linear src, tiled dst */
-                                                       src_offset = radeon_get_ib_value(p, idx+7);
-                                                       src_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32;
-                                                       ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
-                                                       ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
-
-                                                       dst_offset = radeon_get_ib_value(p, idx+1);
-                                                       dst_offset <<= 8;
-                                                       ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
-                                               }
-                                               if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%ju %lu)\n",
-                                                                (uintmax_t)src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%ju %lu)\n",
-                                                                (uintmax_t)dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               p->idx += 9;
-                                               break;
-                                       default:
-                                               DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
-                                               return -EINVAL;
-                                       }
+                                       /* linear src, tiled dst */
+                                       src_offset = ib[idx+7];
+                                       src_offset |= ((u64)(ib[idx+8] & 0xff)) << 32;
+                                       ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
+                                       ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
+
+                                       dst_offset = ib[idx+1];
+                                       dst_offset <<= 8;
+                                       ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
                                }
-                       } else {
-                               if (new_cmd) {
-                                       switch (misc) {
-                                       case 0:
-                                               /* L2L, byte */
-                                               src_offset = radeon_get_ib_value(p, idx+2);
-                                               src_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
-                                               dst_offset = radeon_get_ib_value(p, idx+1);
-                                               dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32;
-                                               if ((src_offset + count) > radeon_bo_size(src_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2L, byte src buffer too small (%ju %lu)\n",
-                                                                (uintmax_t)src_offset + count, radeon_bo_size(src_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               if ((dst_offset + count) > radeon_bo_size(dst_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2L, byte dst buffer too small (%ju %lu)\n",
-                                                                (uintmax_t)dst_offset + count, radeon_bo_size(dst_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xffffffff);
-                                               ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xffffffff);
-                                               ib[idx+3] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
-                                               ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
-                                               p->idx += 5;
-                                               break;
-                                       case 1:
-                                               /* L2L, partial */
-                                               if (p->family < CHIP_CAYMAN) {
-                                                       DRM_ERROR("L2L Partial is cayman only !\n");
-                                                       return -EINVAL;
-                                               }
-                                               ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset & 0xffffffff);
-                                               ib[idx+2] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
-                                               ib[idx+4] += (u32)(dst_reloc->lobj.gpu_offset & 0xffffffff);
-                                               ib[idx+5] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
-
-                                               p->idx += 9;
-                                               break;
-                                       case 4:
-                                               /* L2L, dw, broadcast */
-                                               r = r600_dma_cs_next_reloc(p, &dst2_reloc);
-                                               if (r) {
-                                                       DRM_ERROR("bad L2L, dw, broadcast DMA_PACKET_COPY\n");
-                                                       return -EINVAL;
-                                               }
-                                               dst_offset = radeon_get_ib_value(p, idx+1);
-                                               dst_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
-                                               dst2_offset = radeon_get_ib_value(p, idx+2);
-                                               dst2_offset |= ((u64)(radeon_get_ib_value(p, idx+5) & 0xff)) << 32;
-                                               src_offset = radeon_get_ib_value(p, idx+3);
-                                               src_offset |= ((u64)(radeon_get_ib_value(p, idx+6) & 0xff)) << 32;
-                                               if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2L, dw, broadcast src buffer too small (%ju %lu)\n",
-                                                                (uintmax_t)src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2L, dw, broadcast dst buffer too small (%ju %lu)\n",
-                                                                (uintmax_t)dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2L, dw, broadcast dst2 buffer too small (%ju %lu)\n",
-                                                                (uintmax_t)dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
-                                               ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset & 0xfffffffc);
-                                               ib[idx+3] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
-                                               ib[idx+4] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
-                                               ib[idx+5] += upper_32_bits(dst2_reloc->lobj.gpu_offset) & 0xff;
-                                               ib[idx+6] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
-                                               p->idx += 7;
-                                               break;
-                                       default:
-                                               DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
-                                               return -EINVAL;
-                                       }
+                               if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2T, src buffer too small (%ju %lu)\n",
+                                                       (uintmax_t)src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2T, dst buffer too small (%ju %lu)\n",
+                                                       (uintmax_t)dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               p->idx += 9;
+                               break;
+                       /* Copy L2L, byte aligned */
+                       case 0x40:
+                               /* L2L, byte */
+                               src_offset = ib[idx+2];
+                               src_offset |= ((u64)(ib[idx+4] & 0xff)) << 32;
+                               dst_offset = ib[idx+1];
+                               dst_offset |= ((u64)(ib[idx+3] & 0xff)) << 32;
+                               if ((src_offset + count) > radeon_bo_size(src_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2L, byte src buffer too small (%ju %lu)\n",
+                                                       (uintmax_t)src_offset + count, radeon_bo_size(src_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               if ((dst_offset + count) > radeon_bo_size(dst_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2L, byte dst buffer too small (%ju %lu)\n",
+                                                       (uintmax_t)dst_offset + count, radeon_bo_size(dst_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xffffffff);
+                               ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xffffffff);
+                               ib[idx+3] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
+                               ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
+                               p->idx += 5;
+                               break;
+                       /* Copy L2L, partial */
+                       case 0x41:
+                               /* L2L, partial */
+                               if (p->family < CHIP_CAYMAN) {
+                                       DRM_ERROR("L2L Partial is cayman only !\n");
+                                       return -EINVAL;
+                               }
+                               ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset & 0xffffffff);
+                               ib[idx+2] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
+                               ib[idx+4] += (u32)(dst_reloc->lobj.gpu_offset & 0xffffffff);
+                               ib[idx+5] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
+
+                               p->idx += 9;
+                               break;
+                       /* Copy L2L, DW aligned, broadcast */
+                       case 0x44:
+                               /* L2L, dw, broadcast */
+                               r = r600_dma_cs_next_reloc(p, &dst2_reloc);
+                               if (r) {
+                                       DRM_ERROR("bad L2L, dw, broadcast DMA_PACKET_COPY\n");
+                                       return -EINVAL;
+                               }
+                               dst_offset = ib[idx+1];
+                               dst_offset |= ((u64)(ib[idx+4] & 0xff)) << 32;
+                               dst2_offset = ib[idx+2];
+                               dst2_offset |= ((u64)(ib[idx+5] & 0xff)) << 32;
+                               src_offset = ib[idx+3];
+                               src_offset |= ((u64)(ib[idx+6] & 0xff)) << 32;
+                               if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2L, dw, broadcast src buffer too small (%ju %lu)\n",
+                                                       (uintmax_t)src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2L, dw, broadcast dst buffer too small (%ju %lu)\n",
+                                                       (uintmax_t)dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2L, dw, broadcast dst2 buffer too small (%ju %lu)\n",
+                                                       (uintmax_t)dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
+                               ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset & 0xfffffffc);
+                               ib[idx+3] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
+                               ib[idx+4] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
+                               ib[idx+5] += upper_32_bits(dst2_reloc->lobj.gpu_offset) & 0xff;
+                               ib[idx+6] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
+                               p->idx += 7;
+                               break;
+                       /* Copy L2T Frame to Field */
+                       case 0x48:
+                               if (ib[idx + 2] & (1 << 31)) {
+                                       DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n");
+                                       return -EINVAL;
+                               }
+                               r = r600_dma_cs_next_reloc(p, &dst2_reloc);
+                               if (r) {
+                                       DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n");
+                                       return -EINVAL;
+                               }
+                               dst_offset = ib[idx+1];
+                               dst_offset <<= 8;
+                               dst2_offset = ib[idx+2];
+                               dst2_offset <<= 8;
+                               src_offset = ib[idx+8];
+                               src_offset |= ((u64)(ib[idx+9] & 0xff)) << 32;
+                               if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2T, frame to fields src buffer too small (%ju %lu)\n",
+                                                       (uintmax_t)src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2T, frame to fields buffer too small (%ju %lu)\n",
+                                                       (uintmax_t)dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2T, frame to fields buffer too small (%ju %lu)\n",
+                                                       (uintmax_t)dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
+                               ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8);
+                               ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
+                               ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
+                               p->idx += 10;
+                               break;
+                       /* Copy L2T/T2L, partial */
+                       case 0x49:
+                               /* L2T, T2L partial */
+                               if (p->family < CHIP_CAYMAN) {
+                                       DRM_ERROR("L2T, T2L Partial is cayman only !\n");
+                                       return -EINVAL;
+                               }
+                               /* detile bit */
+                               if (ib[idx + 2 ] & (1 << 31)) {
+                                       /* tiled src, linear dst */
+                                       ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
+
+                                       ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
+                                       ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
                                } else {
-                                       /* L2L, dw */
-                                       src_offset = radeon_get_ib_value(p, idx+2);
-                                       src_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
-                                       dst_offset = radeon_get_ib_value(p, idx+1);
-                                       dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32;
-                                       if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
-                                               dev_warn(p->dev, "DMA L2L, dw src buffer too small (%ju %lu)\n",
-                                                        (uintmax_t)src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
-                                               return -EINVAL;
-                                       }
-                                       if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
-                                               dev_warn(p->dev, "DMA L2L, dw dst buffer too small (%ju %lu)\n",
-                                                        (uintmax_t)dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
-                                               return -EINVAL;
-                                       }
-                                       ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
-                                       ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
-                                       ib[idx+3] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
-                                       ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
-                                       p->idx += 5;
+                                       /* linear src, tiled dst */
+                                       ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
+                                       ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
+
+                                       ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
                                }
+                               p->idx += 12;
+                               break;
+                       /* Copy L2T broadcast */
+                       case 0x4b:
+                               /* L2T, broadcast */
+                               if (ib[idx + 2] & (1 << 31)) {
+                                       DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
+                                       return -EINVAL;
+                               }
+                               r = r600_dma_cs_next_reloc(p, &dst2_reloc);
+                               if (r) {
+                                       DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
+                                       return -EINVAL;
+                               }
+                               dst_offset = ib[idx+1];
+                               dst_offset <<= 8;
+                               dst2_offset = ib[idx+2];
+                               dst2_offset <<= 8;
+                               src_offset = ib[idx+8];
+                               src_offset |= ((u64)(ib[idx+9] & 0xff)) << 32;
+                               if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%ju %lu)\n",
+                                                       (uintmax_t)src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%ju %lu)\n",
+                                                       (uintmax_t)dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2T, broadcast dst2 buffer too small (%ju %lu)\n",
+                                                       (uintmax_t)dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
+                               ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8);
+                               ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
+                               ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
+                               p->idx += 10;
+                               break;
+                       /* Copy L2T/T2L (tile units) */
+                       case 0x4c:
+                               /* L2T, T2L */
+                               /* detile bit */
+                               if (ib[idx + 2] & (1 << 31)) {
+                                       /* tiled src, linear dst */
+                                       src_offset = ib[idx+1];
+                                       src_offset <<= 8;
+                                       ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
+
+                                       dst_offset = ib[idx+7];
+                                       dst_offset |= ((u64)(ib[idx+8] & 0xff)) << 32;
+                                       ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
+                                       ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
+                               } else {
+                                       /* linear src, tiled dst */
+                                       src_offset = ib[idx+7];
+                                       src_offset |= ((u64)(ib[idx+8] & 0xff)) << 32;
+                                       ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
+                                       ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
+
+                                       dst_offset = ib[idx+1];
+                                       dst_offset <<= 8;
+                                       ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
+                               }
+                               if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2T, T2L src buffer too small (%ju %lu)\n",
+                                                       (uintmax_t)src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2T, T2L dst buffer too small (%ju %lu)\n",
+                                                       (uintmax_t)dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               p->idx += 9;
+                               break;
+                       /* Copy T2T, partial (tile units) */
+                       case 0x4d:
+                               /* T2T partial */
+                               if (p->family < CHIP_CAYMAN) {
+                                       DRM_ERROR("L2T, T2L Partial is cayman only !\n");
+                                       return -EINVAL;
+                               }
+                               ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
+                               ib[idx+4] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
+                               p->idx += 13;
+                               break;
+                       /* Copy L2T broadcast (tile units) */
+                       case 0x4f:
+                               /* L2T, broadcast */
+                               if (ib[idx + 2] & (1 << 31)) {
+                                       DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
+                                       return -EINVAL;
+                               }
+                               r = r600_dma_cs_next_reloc(p, &dst2_reloc);
+                               if (r) {
+                                       DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
+                                       return -EINVAL;
+                               }
+                               dst_offset = ib[idx+1];
+                               dst_offset <<= 8;
+                               dst2_offset = ib[idx+2];
+                               dst2_offset <<= 8;
+                               src_offset = ib[idx+8];
+                               src_offset |= ((u64)(ib[idx+9] & 0xff)) << 32;
+                               if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%ju %lu)\n",
+                                                       (uintmax_t)src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%ju %lu)\n",
+                                                       (uintmax_t)dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2T, broadcast dst2 buffer too small (%ju %lu)\n",
+                                                       (uintmax_t)dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
+                               ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8);
+                               ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
+                               ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
+                               p->idx += 10;
+                               break;
+                       default:
+                               DRM_ERROR("bad DMA_PACKET_COPY [%6d] 0x%08x invalid sub cmd\n", idx, ib[idx+0]);
+                               return -EINVAL;
                        }
                        break;
                case DMA_PACKET_CONSTANT_FILL:
@@ -3587,19 +3387,19 @@ int evergreen_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib)
 
        do {
                pkt.idx = idx;
-               pkt.type = CP_PACKET_GET_TYPE(ib->ptr[idx]);
-               pkt.count = CP_PACKET_GET_COUNT(ib->ptr[idx]);
+               pkt.type = RADEON_CP_PACKET_GET_TYPE(ib->ptr[idx]);
+               pkt.count = RADEON_CP_PACKET_GET_COUNT(ib->ptr[idx]);
                pkt.one_reg_wr = 0;
                switch (pkt.type) {
-               case PACKET_TYPE0:
+               case RADEON_PACKET_TYPE0:
                        dev_err(rdev->dev, "Packet0 not allowed!\n");
                        ret = -EINVAL;
                        break;
-               case PACKET_TYPE2:
+               case RADEON_PACKET_TYPE2:
                        idx += 1;
                        break;
-               case PACKET_TYPE3:
-                       pkt.opcode = CP_PACKET3_GET_OPCODE(ib->ptr[idx]);
+               case RADEON_PACKET_TYPE3:
+                       pkt.opcode = RADEON_CP_PACKET3_GET_OPCODE(ib->ptr[idx]);
                        ret = evergreen_vm_packet3_check(rdev, ib->ptr, &pkt);
                        idx += pkt.count + 2;
                        break;
@@ -3627,88 +3427,79 @@ int evergreen_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib)
 int evergreen_dma_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib)
 {
        u32 idx = 0;
-       u32 header, cmd, count, tiled, new_cmd, misc;
+       u32 header, cmd, count, sub_cmd;
 
        do {
                header = ib->ptr[idx];
                cmd = GET_DMA_CMD(header);
                count = GET_DMA_COUNT(header);
-               tiled = GET_DMA_T(header);
-               new_cmd = GET_DMA_NEW(header);
-               misc = GET_DMA_MISC(header);
+               sub_cmd = GET_DMA_SUB_CMD(header);
 
                switch (cmd) {
                case DMA_PACKET_WRITE:
-                       if (tiled)
+                       switch (sub_cmd) {
+                       /* tiled */
+                       case 8:
                                idx += count + 7;
-                       else
+                               break;
+                       /* linear */
+                       case 0:
                                idx += count + 3;
+                               break;
+                       default:
+                               DRM_ERROR("bad DMA_PACKET_WRITE [%6d] 0x%08x sub cmd is not 0 or 8\n", idx, ib->ptr[idx]);
+                               return -EINVAL;
+                       }
                        break;
                case DMA_PACKET_COPY:
-                       if (tiled) {
-                               if (new_cmd) {
-                                       switch (misc) {
-                                       case 0:
-                                               /* L2T, frame to fields */
-                                               idx += 10;
-                                               break;
-                                       case 1:
-                                               /* L2T, T2L partial */
-                                               idx += 12;
-                                               break;
-                                       case 3:
-                                               /* L2T, broadcast */
-                                               idx += 10;
-                                               break;
-                                       case 4:
-                                               /* L2T, T2L */
-                                               idx += 9;
-                                               break;
-                                       case 5:
-                                               /* T2T partial */
-                                               idx += 13;
-                                               break;
-                                       case 7:
-                                               /* L2T, broadcast */
-                                               idx += 10;
-                                               break;
-                                       default:
-                                               DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
-                                               return -EINVAL;
-                                       }
-                               } else {
-                                       switch (misc) {
-                                       case 0:
-                                               idx += 9;
-                                               break;
-                                       default:
-                                               DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
-                                               return -EINVAL;
-                                       }
-                               }
-                       } else {
-                               if (new_cmd) {
-                                       switch (misc) {
-                                       case 0:
-                                               /* L2L, byte */
-                                               idx += 5;
-                                               break;
-                                       case 1:
-                                               /* L2L, partial */
-                                               idx += 9;
-                                               break;
-                                       case 4:
-                                               /* L2L, dw, broadcast */
-                                               idx += 7;
-                                               break;
-                                       default:
-                                               DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
-                                               return -EINVAL;
-                                       }
-                               } else {
-                                       /* L2L, dw */
-                                       idx += 5;
-                               }
+                       switch (sub_cmd) {
+                       /* Copy L2L, DW aligned */
+                       case 0x00:
+                               idx += 5;
+                               break;
+                       /* Copy L2T/T2L */
+                       case 0x08:
+                               idx += 9;
+                               break;
+                       /* Copy L2L, byte aligned */
+                       case 0x40:
+                               idx += 5;
+                               break;
+                       /* Copy L2L, partial */
+                       case 0x41:
+                               idx += 9;
+                               break;
+                       /* Copy L2L, DW aligned, broadcast */
+                       case 0x44:
+                               idx += 7;
+                               break;
+                       /* Copy L2T Frame to Field */
+                       case 0x48:
+                               idx += 10;
+                               break;
+                       /* Copy L2T/T2L, partial */
+                       case 0x49:
+                               idx += 12;
+                               break;
+                       /* Copy L2T broadcast */
+                       case 0x4b:
+                               idx += 10;
+                               break;
+                       /* Copy L2T/T2L (tile units) */
+                       case 0x4c:
+                               idx += 9;
+                               break;
+                       /* Copy T2T, partial (tile units) */
+                       case 0x4d:
+                               idx += 13;
+                               break;
+                       /* Copy L2T broadcast (tile units) */
+                       case 0x4f:
+                               idx += 10;
+                               break;
+                       default:
+                               DRM_ERROR("bad DMA_PACKET_COPY [%6d] 0x%08x invalid sub cmd\n", idx, ib->ptr[idx]);
+                               return -EINVAL;
                        }
                        break;
                case DMA_PACKET_CONSTANT_FILL:
index 10a54a3..777c788 100644 (file)
@@ -27,6 +27,7 @@
  * $FreeBSD: head/sys/dev/drm2/radeon/evergreen_hdmi.c 254885 2013-08-25 19:37:15Z dumbbell $
  */
 
+#include <linux/hdmi.h>
 #include <drm/drmP.h>
 #include <uapi_drm/radeon_drm.h>
 #include "radeon.h"
@@ -56,80 +57,19 @@ static void evergreen_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t cloc
        WREG32(HDMI_ACR_48_1 + offset, acr.n_48khz);
 }
 
-/*
- * calculate the crc for a given info frame
- */
-static void evergreen_hdmi_infoframe_checksum(uint8_t packetType,
-                                        uint8_t versionNumber,
-                                        uint8_t length,
-                                        uint8_t *frame)
-{
-       int i;
-       frame[0] = packetType + versionNumber + length;
-       for (i = 1; i <= length; i++)
-               frame[0] += frame[i];
-       frame[0] = 0x100 - frame[0];
-}
-
 /*
  * build a HDMI Video Info Frame
  */
-static void evergreen_hdmi_videoinfoframe(
-       struct drm_encoder *encoder,
-       uint8_t color_format,
-       int active_information_present,
-       uint8_t active_format_aspect_ratio,
-       uint8_t scan_information,
-       uint8_t colorimetry,
-       uint8_t ex_colorimetry,
-       uint8_t quantization,
-       int ITC,
-       uint8_t picture_aspect_ratio,
-       uint8_t video_format_identification,
-       uint8_t pixel_repetition,
-       uint8_t non_uniform_picture_scaling,
-       uint8_t bar_info_data_valid,
-       uint16_t top_bar,
-       uint16_t bottom_bar,
-       uint16_t left_bar,
-       uint16_t right_bar
-)
+static void evergreen_hdmi_update_avi_infoframe(struct drm_encoder *encoder,
+                                               void *buffer, size_t size)
 {
        struct drm_device *dev = encoder->dev;
        struct radeon_device *rdev = dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
        uint32_t offset = dig->afmt->offset;
+       uint8_t *frame = (uint8_t*)buffer + 3;
 
-       uint8_t frame[14];
-
-       frame[0x0] = 0;
-       frame[0x1] =
-               (scan_information & 0x3) |
-               ((bar_info_data_valid & 0x3) << 2) |
-               ((active_information_present & 0x1) << 4) |
-               ((color_format & 0x3) << 5);
-       frame[0x2] =
-               (active_format_aspect_ratio & 0xF) |
-               ((picture_aspect_ratio & 0x3) << 4) |
-               ((colorimetry & 0x3) << 6);
-       frame[0x3] =
-               (non_uniform_picture_scaling & 0x3) |
-               ((quantization & 0x3) << 2) |
-               ((ex_colorimetry & 0x7) << 4) |
-               ((ITC & 0x1) << 7);
-       frame[0x4] = (video_format_identification & 0x7F);
-       frame[0x5] = (pixel_repetition & 0xF);
-       frame[0x6] = (top_bar & 0xFF);
-       frame[0x7] = (top_bar >> 8);
-       frame[0x8] = (bottom_bar & 0xFF);
-       frame[0x9] = (bottom_bar >> 8);
-       frame[0xA] = (left_bar & 0xFF);
-       frame[0xB] = (left_bar >> 8);
-       frame[0xC] = (right_bar & 0xFF);
-       frame[0xD] = (right_bar >> 8);
-
-       evergreen_hdmi_infoframe_checksum(0x82, 0x02, 0x0D, frame);
        /* Our header values (type, version, length) should be alright, Intel
         * is using the same. Checksum function also seems to be OK, it works
         * fine for audio infoframe. However calculated value is always lower
@@ -157,7 +97,10 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode
        struct radeon_device *rdev = dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+       u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
+       struct hdmi_avi_infoframe frame;
        uint32_t offset;
+       ssize_t err;
 
        /* Silent, r600_hdmi_enable will raise WARN for us */
        if (!dig->afmt->enabled)
@@ -203,9 +146,19 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode
 
        WREG32(HDMI_GC + offset, 0); /* unset HDMI_GC_AVMUTE */
 
-       evergreen_hdmi_videoinfoframe(encoder, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                                     0, 0, 0, 0, 0, 0);
+       err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
+       if (err < 0) {
+               DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
+               return;
+       }
+
+       err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
+       if (err < 0) {
+               DRM_ERROR("failed to pack AVI infoframe: %zd\n", err);
+               return;
+       }
 
+       evergreen_hdmi_update_avi_infoframe(encoder, buffer, sizeof(buffer));
        evergreen_hdmi_update_ACR(encoder, mode->clock);
 
        /* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */
index beda5d8..58a2868 100644 (file)
 #define EVERGREEN_CRTC_STATUS                           0x6e8c
 #       define EVERGREEN_CRTC_V_BLANK                   (1 << 0)
 #define EVERGREEN_CRTC_STATUS_POSITION                  0x6e90
+#define EVERGREEN_CRTC_STATUS_HV_COUNT                  0x6ea0
 #define EVERGREEN_MASTER_UPDATE_MODE                    0x6ef8
 #define EVERGREEN_CRTC_UPDATE_LOCK                      0x6ed4
 
index d8514e1..5dbabac 100644 (file)
 #define        WAIT_UNTIL                                      0x8040
 
 #define        SRBM_STATUS                                     0x0E50
+#define                RLC_RQ_PENDING                          (1 << 3)
+#define                GRBM_RQ_PENDING                         (1 << 5)
+#define                VMC_BUSY                                (1 << 8)
+#define                MCB_BUSY                                (1 << 9)
+#define                MCB_NON_DISPLAY_BUSY                    (1 << 10)
+#define                MCC_BUSY                                (1 << 11)
+#define                MCD_BUSY                                (1 << 12)
+#define                SEM_BUSY                                (1 << 14)
+#define                RLC_BUSY                                (1 << 15)
+#define                IH_BUSY                                 (1 << 17)
+#define        SRBM_STATUS2                                    0x0EC4
+#define                DMA_BUSY                                (1 << 5)
 #define        SRBM_SOFT_RESET                                 0x0E60
 #define                SRBM_SOFT_RESET_ALL_MASK                0x00FEEFA6
 #define                SOFT_RESET_BIF                          (1 << 1)
 #define CAYMAN_DMA1_CNTL                                  0xd82c
 
 /* async DMA packets */
-#define DMA_PACKET(cmd, t, s, n)       ((((cmd) & 0xF) << 28) |        \
-                                        (((t) & 0x1) << 23) |          \
-                                        (((s) & 0x1) << 22) |          \
-                                        (((n) & 0xFFFFF) << 0))
+#define DMA_PACKET(cmd, sub_cmd, n) ((((cmd) & 0xF) << 28) |    \
+                                    (((sub_cmd) & 0xFF) << 20) |\
+                                    (((n) & 0xFFFFF) << 0))
+#define GET_DMA_CMD(h) (((h) & 0xf0000000) >> 28)
+#define GET_DMA_COUNT(h) ((h) & 0x000fffff)
+#define GET_DMA_SUB_CMD(h) (((h) & 0x0ff00000) >> 20)
+
 /* async DMA Packet types */
-#define        DMA_PACKET_WRITE                                  0x2
-#define        DMA_PACKET_COPY                                   0x3
-#define        DMA_PACKET_INDIRECT_BUFFER                        0x4
-#define        DMA_PACKET_SEMAPHORE                              0x5
-#define        DMA_PACKET_FENCE                                  0x6
-#define        DMA_PACKET_TRAP                                   0x7
-#define        DMA_PACKET_SRBM_WRITE                             0x9
-#define        DMA_PACKET_CONSTANT_FILL                          0xd
-#define        DMA_PACKET_NOP                                    0xf
+#define        DMA_PACKET_WRITE                        0x2
+#define        DMA_PACKET_COPY                         0x3
+#define        DMA_PACKET_INDIRECT_BUFFER              0x4
+#define        DMA_PACKET_SEMAPHORE                    0x5
+#define        DMA_PACKET_FENCE                        0x6
+#define        DMA_PACKET_TRAP                         0x7
+#define        DMA_PACKET_SRBM_WRITE                   0x9
+#define        DMA_PACKET_CONSTANT_FILL                0xd
+#define        DMA_PACKET_NOP                          0xf
 
 /* PCIE link stuff */
 #define PCIE_LC_TRAINING_CNTL                             0xa1 /* PCIE_P */
 /*
  * PM4
  */
-#define        PACKET_TYPE0    0
-#define        PACKET_TYPE1    1
-#define        PACKET_TYPE2    2
-#define        PACKET_TYPE3    3
-
-#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3)
-#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF)
-#define CP_PACKET0_GET_REG(h) (((h) & 0xFFFF) << 2)
-#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF)
-#define PACKET0(reg, n)        ((PACKET_TYPE0 << 30) |                         \
+#define PACKET0(reg, n)        ((RADEON_PACKET_TYPE0 << 30) |                  \
                         (((reg) >> 2) & 0xFFFF) |                      \
                         ((n) & 0x3FFF) << 16)
 #define CP_PACKET2                     0x80000000
 
 #define PACKET2(v)     (CP_PACKET2 | REG_SET(PACKET2_PAD, (v)))
 
-#define PACKET3(op, n) ((PACKET_TYPE3 << 30) |                         \
+#define PACKET3(op, n) ((RADEON_PACKET_TYPE3 << 30) |                  \
                         (((op) & 0xFF) << 8) |                         \
                         ((n) & 0x3FFF) << 16)
 
index 38f018c..4dc7828 100644 (file)
@@ -32,6 +32,8 @@
 #include "ni_reg.h"
 #include "cayman_blit_shaders.h"
 
+extern bool evergreen_is_display_hung(struct radeon_device *rdev);
+extern void evergreen_print_gpu_status_regs(struct radeon_device *rdev);
 extern void evergreen_pcie_gen2_enable(struct radeon_device *rdev);
 
 #define EVERGREEN_PFP_UCODE_SIZE 1120
@@ -478,13 +480,19 @@ static void cayman_gpu_init(struct radeon_device *rdev)
                    (rdev->ddev->pci_device == 0x9907) ||
                    (rdev->ddev->pci_device == 0x9908) ||
                    (rdev->ddev->pci_device == 0x9909) ||
+                   (rdev->ddev->pci_device == 0x990B) ||
+                   (rdev->ddev->pci_device == 0x990C) ||
+                   (rdev->ddev->pci_device == 0x990F) ||
                    (rdev->ddev->pci_device == 0x9910) ||
-                   (rdev->ddev->pci_device == 0x9917)) {
+                   (rdev->ddev->pci_device == 0x9917) ||
+                   (rdev->ddev->pci_device == 0x9999)) {
                        rdev->config.cayman.max_simds_per_se = 6;
                        rdev->config.cayman.max_backends_per_se = 2;
                } else if ((rdev->ddev->pci_device == 0x9903) ||
                           (rdev->ddev->pci_device == 0x9904) ||
                           (rdev->ddev->pci_device == 0x990A) ||
+                          (rdev->ddev->pci_device == 0x990D) ||
+                          (rdev->ddev->pci_device == 0x990E) ||
                           (rdev->ddev->pci_device == 0x9913) ||
                           (rdev->ddev->pci_device == 0x9918)) {
                        rdev->config.cayman.max_simds_per_se = 4;
@@ -493,6 +501,9 @@ static void cayman_gpu_init(struct radeon_device *rdev)
                           (rdev->ddev->pci_device == 0x9990) ||
                           (rdev->ddev->pci_device == 0x9991) ||
                           (rdev->ddev->pci_device == 0x9994) ||
+                          (rdev->ddev->pci_device == 0x9995) ||
+                          (rdev->ddev->pci_device == 0x9996) ||
+                          (rdev->ddev->pci_device == 0x999A) ||
                           (rdev->ddev->pci_device == 0x99A0)) {
                        rdev->config.cayman.max_simds_per_se = 3;
                        rdev->config.cayman.max_backends_per_se = 1;
@@ -626,11 +637,22 @@ static void cayman_gpu_init(struct radeon_device *rdev)
        WREG32(DMA_TILING_CONFIG + DMA0_REGISTER_OFFSET, gb_addr_config);
        WREG32(DMA_TILING_CONFIG + DMA1_REGISTER_OFFSET, gb_addr_config);
 
-       tmp = gb_addr_config & NUM_PIPES_MASK;
-       tmp = r6xx_remap_render_backend(rdev, tmp,
-                                       rdev->config.cayman.max_backends_per_se *
-                                       rdev->config.cayman.max_shader_engines,
-                                       CAYMAN_MAX_BACKENDS, disabled_rb_mask);
+       if ((rdev->config.cayman.max_backends_per_se == 1) &&
+           (rdev->flags & RADEON_IS_IGP)) {
+               if ((disabled_rb_mask & 3) == 1) {
+                       /* RB0 disabled, RB1 enabled */
+                       tmp = 0x11111111;
+               } else {
+                       /* RB1 disabled, RB0 enabled */
+                       tmp = 0x00000000;
+               }
+       } else {
+               tmp = gb_addr_config & NUM_PIPES_MASK;
+               tmp = r6xx_remap_render_backend(rdev, tmp,
+                                               rdev->config.cayman.max_backends_per_se *
+                                               rdev->config.cayman.max_shader_engines,
+                                               CAYMAN_MAX_BACKENDS, disabled_rb_mask);
+       }
        WREG32(GB_BACKEND_MAP, tmp);
 
        cgts_tcc_disable = 0xffff0000;
@@ -1322,120 +1344,96 @@ void cayman_dma_fini(struct radeon_device *rdev)
        radeon_ring_fini(rdev, &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX]);
 }
 
-static void cayman_gpu_soft_reset_gfx(struct radeon_device *rdev)
-{
-       u32 grbm_reset = 0;
-
-       if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
-               return;
-
-       dev_info(rdev->dev, "  GRBM_STATUS               = 0x%08X\n",
-               RREG32(GRBM_STATUS));
-       dev_info(rdev->dev, "  GRBM_STATUS_SE0           = 0x%08X\n",
-               RREG32(GRBM_STATUS_SE0));
-       dev_info(rdev->dev, "  GRBM_STATUS_SE1           = 0x%08X\n",
-               RREG32(GRBM_STATUS_SE1));
-       dev_info(rdev->dev, "  SRBM_STATUS               = 0x%08X\n",
-               RREG32(SRBM_STATUS));
-       dev_info(rdev->dev, "  R_008674_CP_STALLED_STAT1 = 0x%08X\n",
-               RREG32(CP_STALLED_STAT1));
-       dev_info(rdev->dev, "  R_008678_CP_STALLED_STAT2 = 0x%08X\n",
-               RREG32(CP_STALLED_STAT2));
-       dev_info(rdev->dev, "  R_00867C_CP_BUSY_STAT     = 0x%08X\n",
-               RREG32(CP_BUSY_STAT));
-       dev_info(rdev->dev, "  R_008680_CP_STAT          = 0x%08X\n",
-               RREG32(CP_STAT));
-
-       /* Disable CP parsing/prefetching */
-       WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT);
-
-       /* reset all the gfx blocks */
-       grbm_reset = (SOFT_RESET_CP |
-                     SOFT_RESET_CB |
-                     SOFT_RESET_DB |
-                     SOFT_RESET_GDS |
-                     SOFT_RESET_PA |
-                     SOFT_RESET_SC |
-                     SOFT_RESET_SPI |
-                     SOFT_RESET_SH |
-                     SOFT_RESET_SX |
-                     SOFT_RESET_TC |
-                     SOFT_RESET_TA |
-                     SOFT_RESET_VGT |
-                     SOFT_RESET_IA);
-
-       dev_info(rdev->dev, "  GRBM_SOFT_RESET=0x%08X\n", grbm_reset);
-       WREG32(GRBM_SOFT_RESET, grbm_reset);
-       (void)RREG32(GRBM_SOFT_RESET);
-       DRM_UDELAY(50);
-       WREG32(GRBM_SOFT_RESET, 0);
-       (void)RREG32(GRBM_SOFT_RESET);
-
-       dev_info(rdev->dev, "  GRBM_STATUS               = 0x%08X\n",
-               RREG32(GRBM_STATUS));
-       dev_info(rdev->dev, "  GRBM_STATUS_SE0           = 0x%08X\n",
-               RREG32(GRBM_STATUS_SE0));
-       dev_info(rdev->dev, "  GRBM_STATUS_SE1           = 0x%08X\n",
-               RREG32(GRBM_STATUS_SE1));
-       dev_info(rdev->dev, "  SRBM_STATUS               = 0x%08X\n",
-               RREG32(SRBM_STATUS));
-       dev_info(rdev->dev, "  R_008674_CP_STALLED_STAT1 = 0x%08X\n",
-               RREG32(CP_STALLED_STAT1));
-       dev_info(rdev->dev, "  R_008678_CP_STALLED_STAT2 = 0x%08X\n",
-               RREG32(CP_STALLED_STAT2));
-       dev_info(rdev->dev, "  R_00867C_CP_BUSY_STAT     = 0x%08X\n",
-               RREG32(CP_BUSY_STAT));
-       dev_info(rdev->dev, "  R_008680_CP_STAT          = 0x%08X\n",
-               RREG32(CP_STAT));
-
-}
-
-static void cayman_gpu_soft_reset_dma(struct radeon_device *rdev)
+static u32 cayman_gpu_check_soft_reset(struct radeon_device *rdev)
 {
+       u32 reset_mask = 0;
        u32 tmp;
 
-       if (RREG32(DMA_STATUS_REG) & DMA_IDLE)
-               return;
-
-       dev_info(rdev->dev, "  R_00D034_DMA_STATUS_REG   = 0x%08X\n",
-               RREG32(DMA_STATUS_REG));
-
-       /* dma0 */
-       tmp = RREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET);
-       tmp &= ~DMA_RB_ENABLE;
-       WREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET, tmp);
-
-       /* dma1 */
-       tmp = RREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET);
-       tmp &= ~DMA_RB_ENABLE;
-       WREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET, tmp);
-
-       /* Reset dma */
-       WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA | SOFT_RESET_DMA1);
-       RREG32(SRBM_SOFT_RESET);
-       DRM_UDELAY(50);
-       WREG32(SRBM_SOFT_RESET, 0);
-
-       dev_info(rdev->dev, "  R_00D034_DMA_STATUS_REG   = 0x%08X\n",
-               RREG32(DMA_STATUS_REG));
+       /* GRBM_STATUS */
+       tmp = RREG32(GRBM_STATUS);
+       if (tmp & (PA_BUSY | SC_BUSY |
+                  SH_BUSY | SX_BUSY |
+                  TA_BUSY | VGT_BUSY |
+                  DB_BUSY | CB_BUSY |
+                  GDS_BUSY | SPI_BUSY |
+                  IA_BUSY | IA_BUSY_NO_DMA))
+               reset_mask |= RADEON_RESET_GFX;
+
+       if (tmp & (CF_RQ_PENDING | PF_RQ_PENDING |
+                  CP_BUSY | CP_COHERENCY_BUSY))
+               reset_mask |= RADEON_RESET_CP;
+
+       if (tmp & GRBM_EE_BUSY)
+               reset_mask |= RADEON_RESET_GRBM | RADEON_RESET_GFX | RADEON_RESET_CP;
+
+       /* DMA_STATUS_REG 0 */
+       tmp = RREG32(DMA_STATUS_REG + DMA0_REGISTER_OFFSET);
+       if (!(tmp & DMA_IDLE))
+               reset_mask |= RADEON_RESET_DMA;
+
+       /* DMA_STATUS_REG 1 */
+       tmp = RREG32(DMA_STATUS_REG + DMA1_REGISTER_OFFSET);
+       if (!(tmp & DMA_IDLE))
+               reset_mask |= RADEON_RESET_DMA1;
+
+       /* SRBM_STATUS2 */
+       tmp = RREG32(SRBM_STATUS2);
+       if (tmp & DMA_BUSY)
+               reset_mask |= RADEON_RESET_DMA;
+
+       if (tmp & DMA1_BUSY)
+               reset_mask |= RADEON_RESET_DMA1;
+
+       /* SRBM_STATUS */
+       tmp = RREG32(SRBM_STATUS);
+       if (tmp & (RLC_RQ_PENDING | RLC_BUSY))
+               reset_mask |= RADEON_RESET_RLC;
+
+       if (tmp & IH_BUSY)
+               reset_mask |= RADEON_RESET_IH;
+
+       if (tmp & SEM_BUSY)
+               reset_mask |= RADEON_RESET_SEM;
+
+       if (tmp & GRBM_RQ_PENDING)
+               reset_mask |= RADEON_RESET_GRBM;
+
+       if (tmp & VMC_BUSY)
+               reset_mask |= RADEON_RESET_VMC;
+
+       if (tmp & (MCB_BUSY | MCB_NON_DISPLAY_BUSY |
+                  MCC_BUSY | MCD_BUSY))
+               reset_mask |= RADEON_RESET_MC;
+
+       if (evergreen_is_display_hung(rdev))
+               reset_mask |= RADEON_RESET_DISPLAY;
+
+       /* VM_L2_STATUS */
+       tmp = RREG32(VM_L2_STATUS);
+       if (tmp & L2_BUSY)
+               reset_mask |= RADEON_RESET_VMC;
+
+       /* Skip MC reset as it's mostly likely not hung, just busy */
+       if (reset_mask & RADEON_RESET_MC) {
+               DRM_DEBUG("MC busy: 0x%08X, clearing.\n", reset_mask);
+               reset_mask &= ~RADEON_RESET_MC;
+       }
 
+       return reset_mask;
 }
 
-static int cayman_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
+static void cayman_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
 {
        struct evergreen_mc_save save;
-
-       if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
-               reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE);
-
-       if (RREG32(DMA_STATUS_REG) & DMA_IDLE)
-               reset_mask &= ~RADEON_RESET_DMA;
+       u32 grbm_soft_reset = 0, srbm_soft_reset = 0;
+       u32 tmp;
 
        if (reset_mask == 0)
-               return 0;
+               return;
 
        dev_info(rdev->dev, "GPU softreset: 0x%08X\n", reset_mask);
 
+       evergreen_print_gpu_status_regs(rdev);
        dev_info(rdev->dev, "  VM_CONTEXT0_PROTECTION_FAULT_ADDR   0x%08X\n",
                 RREG32(0x14F8));
        dev_info(rdev->dev, "  VM_CONTEXT0_PROTECTION_FAULT_STATUS 0x%08X\n",
@@ -1445,29 +1443,158 @@ static int cayman_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
        dev_info(rdev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n",
                 RREG32(0x14DC));
 
+       /* Disable CP parsing/prefetching */
+       WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT);
+
+       if (reset_mask & RADEON_RESET_DMA) {
+               /* dma0 */
+               tmp = RREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET);
+               tmp &= ~DMA_RB_ENABLE;
+               WREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET, tmp);
+       }
+
+       if (reset_mask & RADEON_RESET_DMA1) {
+               /* dma1 */
+               tmp = RREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET);
+               tmp &= ~DMA_RB_ENABLE;
+               WREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET, tmp);
+       }
+
+       DRM_UDELAY(50);
+
        evergreen_mc_stop(rdev, &save);
        if (evergreen_mc_wait_for_idle(rdev)) {
                dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
        }
 
-       if (reset_mask & (RADEON_RESET_GFX | RADEON_RESET_COMPUTE))
-               cayman_gpu_soft_reset_gfx(rdev);
+       if (reset_mask & (RADEON_RESET_GFX | RADEON_RESET_COMPUTE)) {
+               grbm_soft_reset = SOFT_RESET_CB |
+                       SOFT_RESET_DB |
+                       SOFT_RESET_GDS |
+                       SOFT_RESET_PA |
+                       SOFT_RESET_SC |
+                       SOFT_RESET_SPI |
+                       SOFT_RESET_SH |
+                       SOFT_RESET_SX |
+                       SOFT_RESET_TC |
+                       SOFT_RESET_TA |
+                       SOFT_RESET_VGT |
+                       SOFT_RESET_IA;
+       }
+
+       if (reset_mask & RADEON_RESET_CP) {
+               grbm_soft_reset |= SOFT_RESET_CP | SOFT_RESET_VGT;
+
+               srbm_soft_reset |= SOFT_RESET_GRBM;
+       }
 
        if (reset_mask & RADEON_RESET_DMA)
-               cayman_gpu_soft_reset_dma(rdev);
+               srbm_soft_reset |= SOFT_RESET_DMA;
+
+       if (reset_mask & RADEON_RESET_DMA1)
+               srbm_soft_reset |= SOFT_RESET_DMA1;
+
+       if (reset_mask & RADEON_RESET_DISPLAY)
+               srbm_soft_reset |= SOFT_RESET_DC;
+
+       if (reset_mask & RADEON_RESET_RLC)
+               srbm_soft_reset |= SOFT_RESET_RLC;
+
+       if (reset_mask & RADEON_RESET_SEM)
+               srbm_soft_reset |= SOFT_RESET_SEM;
+
+       if (reset_mask & RADEON_RESET_IH)
+               srbm_soft_reset |= SOFT_RESET_IH;
+
+       if (reset_mask & RADEON_RESET_GRBM)
+               srbm_soft_reset |= SOFT_RESET_GRBM;
+
+       if (reset_mask & RADEON_RESET_VMC)
+               srbm_soft_reset |= SOFT_RESET_VMC;
+
+       if (!(rdev->flags & RADEON_IS_IGP)) {
+               if (reset_mask & RADEON_RESET_MC)
+                       srbm_soft_reset |= SOFT_RESET_MC;
+       }
+
+       if (grbm_soft_reset) {
+               tmp = RREG32(GRBM_SOFT_RESET);
+               tmp |= grbm_soft_reset;
+               dev_info(rdev->dev, "GRBM_SOFT_RESET=0x%08X\n", tmp);
+               WREG32(GRBM_SOFT_RESET, tmp);
+               tmp = RREG32(GRBM_SOFT_RESET);
+
+               DRM_UDELAY(50);
+
+               tmp &= ~grbm_soft_reset;
+               WREG32(GRBM_SOFT_RESET, tmp);
+               tmp = RREG32(GRBM_SOFT_RESET);
+       }
+
+       if (srbm_soft_reset) {
+               tmp = RREG32(SRBM_SOFT_RESET);
+               tmp |= srbm_soft_reset;
+               dev_info(rdev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp);
+               WREG32(SRBM_SOFT_RESET, tmp);
+               tmp = RREG32(SRBM_SOFT_RESET);
+
+               DRM_UDELAY(50);
+
+               tmp &= ~srbm_soft_reset;
+               WREG32(SRBM_SOFT_RESET, tmp);
+               tmp = RREG32(SRBM_SOFT_RESET);
+       }
 
        /* Wait a little for things to settle down */
        DRM_UDELAY(50);
 
        evergreen_mc_resume(rdev, &save);
-       return 0;
+       DRM_UDELAY(50);
+
+       evergreen_print_gpu_status_regs(rdev);
 }
 
 int cayman_asic_reset(struct radeon_device *rdev)
 {
-       return cayman_gpu_soft_reset(rdev, (RADEON_RESET_GFX |
-                                           RADEON_RESET_COMPUTE |
-                                           RADEON_RESET_DMA));
+       u32 reset_mask;
+
+       reset_mask = cayman_gpu_check_soft_reset(rdev);
+
+       if (reset_mask)
+               r600_set_bios_scratch_engine_hung(rdev, true);
+
+       cayman_gpu_soft_reset(rdev, reset_mask);
+
+       reset_mask = cayman_gpu_check_soft_reset(rdev);
+
+       if (!reset_mask)
+               r600_set_bios_scratch_engine_hung(rdev, false);
+
+       return 0;
+}
+
+/**
+ * cayman_gfx_is_lockup - Check if the GFX engine is locked up
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon_ring structure holding ring information
+ *
+ * Check if the GFX engine is locked up.
+ * Returns true if the engine appears to be locked up, false if not.
+ */
+bool cayman_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
+{
+       u32 reset_mask = cayman_gpu_check_soft_reset(rdev);
+
+       if (!(reset_mask & (RADEON_RESET_GFX |
+                           RADEON_RESET_COMPUTE |
+                           RADEON_RESET_CP))) {
+               radeon_ring_lockup_update(ring);
+               return false;
+       }
+       /* force CP activities */
+       radeon_ring_force_activity(rdev, ring);
+       return radeon_ring_test_lockup(rdev, ring);
 }
 
 /**
@@ -1476,18 +1603,20 @@ int cayman_asic_reset(struct radeon_device *rdev)
  * @rdev: radeon_device pointer
  * @ring: radeon_ring structure holding ring information
  *
- * Check if the async DMA engine is locked up (cayman-SI).
+ * Check if the async DMA engine is locked up.
  * Returns true if the engine appears to be locked up, false if not.
  */
 bool cayman_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
 {
-       u32 dma_status_reg;
+       u32 reset_mask = cayman_gpu_check_soft_reset(rdev);
+       u32 mask;
 
        if (ring->idx == R600_RING_TYPE_DMA_INDEX)
-               dma_status_reg = RREG32(DMA_STATUS_REG + DMA0_REGISTER_OFFSET);
+               mask = RADEON_RESET_DMA;
        else
-               dma_status_reg = RREG32(DMA_STATUS_REG + DMA1_REGISTER_OFFSET);
-       if (dma_status_reg & DMA_IDLE) {
+               mask = RADEON_RESET_DMA1;
+
+       if (!(reset_mask & mask)) {
                radeon_ring_lockup_update(ring);
                return false;
        }
@@ -1674,6 +1803,7 @@ int cayman_resume(struct radeon_device *rdev)
 int cayman_suspend(struct radeon_device *rdev)
 {
        r600_audio_fini(rdev);
+       radeon_vm_manager_fini(rdev);
        cayman_cp_enable(rdev, false);
        cayman_dma_stop(rdev);
        evergreen_irq_suspend(rdev);
@@ -1856,19 +1986,21 @@ uint32_t cayman_vm_page_flags(struct radeon_device *rdev, uint32_t flags)
  * cayman_vm_set_page - update the page tables using the CP
  *
  * @rdev: radeon_device pointer
+ * @ib: indirect buffer to fill with commands
  * @pe: addr of the page entry
  * @addr: dst addr to write into pe
  * @count: number of page entries to update
  * @incr: increase next addr by incr bytes
  * @flags: access flags
  *
- * Update the page tables using the CP (cayman-si).
+ * Update the page tables using the CP (cayman/TN).
  */
-void cayman_vm_set_page(struct radeon_device *rdev, uint64_t pe,
+void cayman_vm_set_page(struct radeon_device *rdev,
+                       struct radeon_ib *ib,
+                       uint64_t pe,
                        uint64_t addr, unsigned count,
                        uint32_t incr, uint32_t flags)
 {
-       struct radeon_ring *ring = &rdev->ring[rdev->asic->vm.pt_ring_index];
        uint32_t r600_flags = cayman_vm_page_flags(rdev, flags);
        uint64_t value;
        unsigned ndw;
@@ -1879,9 +2011,9 @@ void cayman_vm_set_page(struct radeon_device *rdev, uint64_t pe,
                        if (ndw > 0x3FFF)
                                ndw = 0x3FFF;
 
-                       radeon_ring_write(ring, PACKET3(PACKET3_ME_WRITE, ndw));
-                       radeon_ring_write(ring, pe);
-                       radeon_ring_write(ring, upper_32_bits(pe) & 0xff);
+                       ib->ptr[ib->length_dw++] = PACKET3(PACKET3_ME_WRITE, ndw);
+                       ib->ptr[ib->length_dw++] = pe;
+                       ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff;
                        for (; ndw > 1; ndw -= 2, --count, pe += 8) {
                                if (flags & RADEON_VM_PAGE_SYSTEM) {
                                        value = radeon_vm_map_gart(rdev, addr);
@@ -1893,8 +2025,8 @@ void cayman_vm_set_page(struct radeon_device *rdev, uint64_t pe,
                                }
                                addr += incr;
                                value |= r600_flags;
-                               radeon_ring_write(ring, value);
-                               radeon_ring_write(ring, upper_32_bits(value));
+                               ib->ptr[ib->length_dw++] = value;
+                               ib->ptr[ib->length_dw++] = upper_32_bits(value);
                        }
                }
        } else {
@@ -1904,9 +2036,9 @@ void cayman_vm_set_page(struct radeon_device *rdev, uint64_t pe,
                                ndw = 0xFFFFE;
 
                        /* for non-physically contiguous pages (system) */
-                       radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_WRITE, 0, 0, ndw));
-                       radeon_ring_write(ring, pe);
-                       radeon_ring_write(ring, upper_32_bits(pe) & 0xff);
+                       ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_WRITE, 0, 0, ndw);
+                       ib->ptr[ib->length_dw++] = pe;
+                       ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff;
                        for (; ndw > 0; ndw -= 2, --count, pe += 8) {
                                if (flags & RADEON_VM_PAGE_SYSTEM) {
                                        value = radeon_vm_map_gart(rdev, addr);
@@ -1918,10 +2050,12 @@ void cayman_vm_set_page(struct radeon_device *rdev, uint64_t pe,
                                }
                                addr += incr;
                                value |= r600_flags;
-                               radeon_ring_write(ring, value);
-                               radeon_ring_write(ring, upper_32_bits(value));
+                               ib->ptr[ib->length_dw++] = value;
+                               ib->ptr[ib->length_dw++] = upper_32_bits(value);
                        }
                }
+               while (ib->length_dw & 0x7)
+                       ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0);
        }
 }
 
index 1ac6da2..8007b97 100644 (file)
 #define                RINGID(x)                                       (((x) & 0x3) << 0)
 #define                VMID(x)                                         (((x) & 0x7) << 0)
 #define        SRBM_STATUS                                     0x0E50
+#define                RLC_RQ_PENDING                          (1 << 3)
+#define                GRBM_RQ_PENDING                         (1 << 5)
+#define                VMC_BUSY                                (1 << 8)
+#define                MCB_BUSY                                (1 << 9)
+#define                MCB_NON_DISPLAY_BUSY                    (1 << 10)
+#define                MCC_BUSY                                (1 << 11)
+#define                MCD_BUSY                                (1 << 12)
+#define                SEM_BUSY                                (1 << 14)
+#define                RLC_BUSY                                (1 << 15)
+#define                IH_BUSY                                 (1 << 17)
 
 #define        SRBM_SOFT_RESET                                 0x0E60
 #define                SOFT_RESET_BIF                          (1 << 1)
 #define                SOFT_RESET_REGBB                        (1 << 22)
 #define                SOFT_RESET_ORB                          (1 << 23)
 
+#define        SRBM_STATUS2                                    0x0EC4
+#define                DMA_BUSY                                (1 << 5)
+#define                DMA1_BUSY                               (1 << 6)
+
 #define VM_CONTEXT0_REQUEST_RESPONSE                   0x1470
 #define                REQUEST_TYPE(x)                                 (((x) & 0xf) << 0)
 #define                RESPONSE_TYPE_MASK                              0x000000F0
 /*
  * PM4
  */
-#define        PACKET_TYPE0    0
-#define        PACKET_TYPE1    1
-#define        PACKET_TYPE2    2
-#define        PACKET_TYPE3    3
-
-#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3)
-#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF)
-#define CP_PACKET0_GET_REG(h) (((h) & 0xFFFF) << 2)
-#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF)
-#define PACKET0(reg, n)        ((PACKET_TYPE0 << 30) |                         \
+#define PACKET0(reg, n)        ((RADEON_PACKET_TYPE0 << 30) |                  \
                         (((reg) >> 2) & 0xFFFF) |                      \
                         ((n) & 0x3FFF) << 16)
 #define CP_PACKET2                     0x80000000
 
 #define PACKET2(v)     (CP_PACKET2 | REG_SET(PACKET2_PAD, (v)))
 
-#define PACKET3(op, n) ((PACKET_TYPE3 << 30) |                         \
+#define PACKET3(op, n) ((RADEON_PACKET_TYPE3 << 30) |                  \
                         (((op) & 0xFF) << 8) |                         \
                         ((n) & 0x3FFF) << 16)
 
index f107d9b..3fd9dc0 100644 (file)
@@ -1215,11 +1215,11 @@ int r100_reloc_pitch_offset(struct radeon_cs_parser *p,
        struct radeon_cs_reloc *reloc;
        u32 value;
 
-       r = r100_cs_packet_next_reloc(p, &reloc);
+       r = radeon_cs_packet_next_reloc(p, &reloc, 0);
        if (r) {
                DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
                          idx, reg);
-               r100_cs_dump_packet(p, pkt);
+               radeon_cs_dump_packet(p, pkt);
                return r;
        }
 
@@ -1233,7 +1233,7 @@ int r100_reloc_pitch_offset(struct radeon_cs_parser *p,
                if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
                        if (reg == RADEON_SRC_PITCH_OFFSET) {
                                DRM_ERROR("Cannot src blit from microtiled surface\n");
-                               r100_cs_dump_packet(p, pkt);
+                               radeon_cs_dump_packet(p, pkt);
                                return -EINVAL;
                        }
                        tile_flags |= RADEON_DST_TILE_MICRO;
@@ -1263,16 +1263,16 @@ int r100_packet3_load_vbpntr(struct radeon_cs_parser *p,
        if (c > 16) {
            DRM_ERROR("Only 16 vertex buffers are allowed %d\n",
                      pkt->opcode);
-           r100_cs_dump_packet(p, pkt);
+           radeon_cs_dump_packet(p, pkt);
            return -EINVAL;
        }
        track->num_arrays = c;
        for (i = 0; i < (c - 1); i+=2, idx+=3) {
-               r = r100_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("No reloc for packet3 %d\n",
                                  pkt->opcode);
-                       r100_cs_dump_packet(p, pkt);
+                       radeon_cs_dump_packet(p, pkt);
                        return r;
                }
                idx_value = radeon_get_ib_value(p, idx);
@@ -1281,11 +1281,11 @@ int r100_packet3_load_vbpntr(struct radeon_cs_parser *p,
                track->arrays[i + 0].esize = idx_value >> 8;
                track->arrays[i + 0].robj = reloc->robj;
                track->arrays[i + 0].esize &= 0x7F;
-               r = r100_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("No reloc for packet3 %d\n",
                                  pkt->opcode);
-                       r100_cs_dump_packet(p, pkt);
+                       radeon_cs_dump_packet(p, pkt);
                        return r;
                }
                ib[idx+2] = radeon_get_ib_value(p, idx + 2) + ((u32)reloc->lobj.gpu_offset);
@@ -1294,11 +1294,11 @@ int r100_packet3_load_vbpntr(struct radeon_cs_parser *p,
                track->arrays[i + 1].esize &= 0x7F;
        }
        if (c & 1) {
-               r = r100_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("No reloc for packet3 %d\n",
                                          pkt->opcode);
-                       r100_cs_dump_packet(p, pkt);
+                       radeon_cs_dump_packet(p, pkt);
                        return r;
                }
                idx_value = radeon_get_ib_value(p, idx);
@@ -1355,67 +1355,6 @@ int r100_cs_parse_packet0(struct radeon_cs_parser *p,
        return 0;
 }
 
-void r100_cs_dump_packet(struct radeon_cs_parser *p,
-                        struct radeon_cs_packet *pkt)
-{
-       volatile uint32_t *ib;
-       unsigned i;
-       unsigned idx;
-
-       ib = p->ib.ptr;
-       idx = pkt->idx;
-       for (i = 0; i <= (pkt->count + 1); i++, idx++) {
-               DRM_INFO("ib[%d]=0x%08X\n", idx, ib[idx]);
-       }
-}
-
-/**
- * r100_cs_packet_parse() - parse cp packet and point ib index to next packet
- * @parser:    parser structure holding parsing context.
- * @pkt:       where to store packet informations
- *
- * Assume that chunk_ib_index is properly set. Will return -EINVAL
- * if packet is bigger than remaining ib size. or if packets is unknown.
- **/
-int r100_cs_packet_parse(struct radeon_cs_parser *p,
-                        struct radeon_cs_packet *pkt,
-                        unsigned idx)
-{
-       struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx];
-       uint32_t header;
-
-       if (idx >= ib_chunk->length_dw) {
-               DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
-                         idx, ib_chunk->length_dw);
-               return -EINVAL;
-       }
-       header = radeon_get_ib_value(p, idx);
-       pkt->idx = idx;
-       pkt->type = CP_PACKET_GET_TYPE(header);
-       pkt->count = CP_PACKET_GET_COUNT(header);
-       switch (pkt->type) {
-       case PACKET_TYPE0:
-               pkt->reg = CP_PACKET0_GET_REG(header);
-               pkt->one_reg_wr = CP_PACKET0_GET_ONE_REG_WR(header);
-               break;
-       case PACKET_TYPE3:
-               pkt->opcode = CP_PACKET3_GET_OPCODE(header);
-               break;
-       case PACKET_TYPE2:
-               pkt->count = -1;
-               break;
-       default:
-               DRM_ERROR("Unknown packet type %d at %d !\n", pkt->type, idx);
-               return -EINVAL;
-       }
-       if ((pkt->count + 1 + pkt->idx) >= ib_chunk->length_dw) {
-               DRM_ERROR("Packet (%d:%d:%d) end after CS buffer (%d) !\n",
-                         pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw);
-               return -EINVAL;
-       }
-       return 0;
-}
-
 /**
  * r100_cs_packet_next_vline() - parse userspace VLINE packet
  * @parser:            parser structure holding parsing context.
@@ -1444,7 +1383,7 @@ int r100_cs_packet_parse_vline(struct radeon_cs_parser *p)
        ib = p->ib.ptr;
 
        /* parse the wait until */
-       r = r100_cs_packet_parse(p, &waitreloc, p->idx);
+       r = radeon_cs_packet_parse(p, &waitreloc, p->idx);
        if (r)
                return r;
 
@@ -1461,7 +1400,7 @@ int r100_cs_packet_parse_vline(struct radeon_cs_parser *p)
        }
 
        /* jump over the NOP */
-       r = r100_cs_packet_parse(p, &p3reloc, p->idx + waitreloc.count + 2);
+       r = radeon_cs_packet_parse(p, &p3reloc, p->idx + waitreloc.count + 2);
        if (r)
                return r;
 
@@ -1471,7 +1410,7 @@ int r100_cs_packet_parse_vline(struct radeon_cs_parser *p)
 
        header = radeon_get_ib_value(p, h_idx);
        crtc_id = radeon_get_ib_value(p, h_idx + 5);
-       reg = CP_PACKET0_GET_REG(header);
+       reg = R100_CP_PACKET0_GET_REG(header);
        obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
        if (!obj) {
                DRM_ERROR("cannot find crtc %d\n", crtc_id);
@@ -1506,54 +1445,6 @@ int r100_cs_packet_parse_vline(struct radeon_cs_parser *p)
        return 0;
 }
 
-/**
- * r100_cs_packet_next_reloc() - parse next packet which should be reloc packet3
- * @parser:            parser structure holding parsing context.
- * @data:              pointer to relocation data
- * @offset_start:      starting offset
- * @offset_mask:       offset mask (to align start offset on)
- * @reloc:             reloc informations
- *
- * Check next packet is relocation packet3, do bo validation and compute
- * GPU offset using the provided start.
- **/
-int r100_cs_packet_next_reloc(struct radeon_cs_parser *p,
-                             struct radeon_cs_reloc **cs_reloc)
-{
-       struct radeon_cs_chunk *relocs_chunk;
-       struct radeon_cs_packet p3reloc;
-       unsigned idx;
-       int r;
-
-       if (p->chunk_relocs_idx == -1) {
-               DRM_ERROR("No relocation chunk !\n");
-               return -EINVAL;
-       }
-       *cs_reloc = NULL;
-       relocs_chunk = &p->chunks[p->chunk_relocs_idx];
-       r = r100_cs_packet_parse(p, &p3reloc, p->idx);
-       if (r) {
-               return r;
-       }
-       p->idx += p3reloc.count + 2;
-       if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
-               DRM_ERROR("No packet3 for relocation for packet at %d.\n",
-                         p3reloc.idx);
-               r100_cs_dump_packet(p, &p3reloc);
-               return -EINVAL;
-       }
-       idx = radeon_get_ib_value(p, p3reloc.idx + 1);
-       if (idx >= relocs_chunk->length_dw) {
-               DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
-                         idx, relocs_chunk->length_dw);
-               r100_cs_dump_packet(p, &p3reloc);
-               return -EINVAL;
-       }
-       /* FIXME: we assume reloc size is 4 dwords */
-       *cs_reloc = p->relocs_ptr[(idx / 4)];
-       return 0;
-}
-
 static int r100_get_vtx_size(uint32_t vtx_fmt)
 {
        int vtx_size;
@@ -1631,7 +1522,7 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
                if (r) {
                        DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
                                  idx, reg);
-                       r100_cs_dump_packet(p, pkt);
+                       radeon_cs_dump_packet(p, pkt);
                        return r;
                }
                break;
@@ -1644,11 +1535,11 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
                        return r;
                break;
        case RADEON_RB3D_DEPTHOFFSET:
-               r = r100_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
                                  idx, reg);
-                       r100_cs_dump_packet(p, pkt);
+                       radeon_cs_dump_packet(p, pkt);
                        return r;
                }
                track->zb.robj = reloc->robj;
@@ -1657,11 +1548,11 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
                ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
                break;
        case RADEON_RB3D_COLOROFFSET:
-               r = r100_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
                                  idx, reg);
-                       r100_cs_dump_packet(p, pkt);
+                       radeon_cs_dump_packet(p, pkt);
                        return r;
                }
                track->cb[0].robj = reloc->robj;
@@ -1673,11 +1564,11 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
        case RADEON_PP_TXOFFSET_1:
        case RADEON_PP_TXOFFSET_2:
                i = (reg - RADEON_PP_TXOFFSET_0) / 24;
-               r = r100_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
                                  idx, reg);
-                       r100_cs_dump_packet(p, pkt);
+                       radeon_cs_dump_packet(p, pkt);
                        return r;
                }
                if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
@@ -1700,11 +1591,11 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
        case RADEON_PP_CUBIC_OFFSET_T0_3:
        case RADEON_PP_CUBIC_OFFSET_T0_4:
                i = (reg - RADEON_PP_CUBIC_OFFSET_T0_0) / 4;
-               r = r100_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
                                  idx, reg);
-                       r100_cs_dump_packet(p, pkt);
+                       radeon_cs_dump_packet(p, pkt);
                        return r;
                }
                track->textures[0].cube_info[i].offset = idx_value;
@@ -1718,11 +1609,11 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
        case RADEON_PP_CUBIC_OFFSET_T1_3:
        case RADEON_PP_CUBIC_OFFSET_T1_4:
                i = (reg - RADEON_PP_CUBIC_OFFSET_T1_0) / 4;
-               r = r100_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
                                  idx, reg);
-                       r100_cs_dump_packet(p, pkt);
+                       radeon_cs_dump_packet(p, pkt);
                        return r;
                }
                track->textures[1].cube_info[i].offset = idx_value;
@@ -1736,11 +1627,11 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
        case RADEON_PP_CUBIC_OFFSET_T2_3:
        case RADEON_PP_CUBIC_OFFSET_T2_4:
                i = (reg - RADEON_PP_CUBIC_OFFSET_T2_0) / 4;
-               r = r100_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
                                  idx, reg);
-                       r100_cs_dump_packet(p, pkt);
+                       radeon_cs_dump_packet(p, pkt);
                        return r;
                }
                track->textures[2].cube_info[i].offset = idx_value;
@@ -1754,11 +1645,11 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
                track->zb_dirty = true;
                break;
        case RADEON_RB3D_COLORPITCH:
-               r = r100_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
                                  idx, reg);
-                       r100_cs_dump_packet(p, pkt);
+                       radeon_cs_dump_packet(p, pkt);
                        return r;
                }
                if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
@@ -1825,11 +1716,11 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
                track->zb_dirty = true;
                break;
        case RADEON_RB3D_ZPASS_ADDR:
-               r = r100_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
                                  idx, reg);
-                       r100_cs_dump_packet(p, pkt);
+                       radeon_cs_dump_packet(p, pkt);
                        return r;
                }
                ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
@@ -1986,10 +1877,10 @@ static int r100_packet3_check(struct radeon_cs_parser *p,
                        return r;
                break;
        case PACKET3_INDX_BUFFER:
-               r = r100_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("No reloc for packet3 %d\n", pkt->opcode);
-                       r100_cs_dump_packet(p, pkt);
+                       radeon_cs_dump_packet(p, pkt);
                        return r;
                }
                ib[idx+1] = radeon_get_ib_value(p, idx+1) + ((u32)reloc->lobj.gpu_offset);
@@ -2000,10 +1891,10 @@ static int r100_packet3_check(struct radeon_cs_parser *p,
                break;
        case 0x23:
                /* 3D_RNDR_GEN_INDX_PRIM on r100/r200 */
-               r = r100_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("No reloc for packet3 %d\n", pkt->opcode);
-                       r100_cs_dump_packet(p, pkt);
+                       radeon_cs_dump_packet(p, pkt);
                        return r;
                }
                ib[idx] = radeon_get_ib_value(p, idx) + ((u32)reloc->lobj.gpu_offset);
@@ -2100,7 +1991,7 @@ int r100_cs_parse(struct radeon_cs_parser *p)
        r100_cs_track_clear(p->rdev, track);
        p->track = track;
        do {
-               r = r100_cs_packet_parse(p, &pkt, p->idx);
+               r = radeon_cs_packet_parse(p, &pkt, p->idx);
                if (r) {
                        drm_free(p->track, M_DRM);
                        p->track = NULL;
@@ -2108,29 +1999,29 @@ int r100_cs_parse(struct radeon_cs_parser *p)
                }
                p->idx += pkt.count + 2;
                switch (pkt.type) {
-                       case PACKET_TYPE0:
-                               if (p->rdev->family >= CHIP_R200)
-                                       r = r100_cs_parse_packet0(p, &pkt,
-                                                                 p->rdev->config.r100.reg_safe_bm,
-                                                                 p->rdev->config.r100.reg_safe_bm_size,
-                                                                 &r200_packet0_check);
-                               else
-                                       r = r100_cs_parse_packet0(p, &pkt,
-                                                                 p->rdev->config.r100.reg_safe_bm,
-                                                                 p->rdev->config.r100.reg_safe_bm_size,
-                                                                 &r100_packet0_check);
-                               break;
-                       case PACKET_TYPE2:
-                               break;
-                       case PACKET_TYPE3:
-                               r = r100_packet3_check(p, &pkt);
-                               break;
-                       default:
-                               DRM_ERROR("Unknown packet type %d !\n",
-                                         pkt.type);
-                               drm_free(p->track, M_DRM);
-                               p->track = NULL;
-                               return -EINVAL;
+               case RADEON_PACKET_TYPE0:
+                       if (p->rdev->family >= CHIP_R200)
+                               r = r100_cs_parse_packet0(p, &pkt,
+                                       p->rdev->config.r100.reg_safe_bm,
+                                       p->rdev->config.r100.reg_safe_bm_size,
+                                       &r200_packet0_check);
+                       else
+                               r = r100_cs_parse_packet0(p, &pkt,
+                                       p->rdev->config.r100.reg_safe_bm,
+                                       p->rdev->config.r100.reg_safe_bm_size,
+                                       &r100_packet0_check);
+                       break;
+               case RADEON_PACKET_TYPE2:
+                       break;
+               case RADEON_PACKET_TYPE3:
+                       r = r100_packet3_check(p, &pkt);
+                       break;
+               default:
+                       DRM_ERROR("Unknown packet type %d !\n",
+                                 pkt.type);
+                       drm_free(p->track, M_DRM);
+                       p->track = NULL;
+                       return -EINVAL;
                }
                if (r) {
                        drm_free(p->track, M_DRM);
index f36e16d..3547d1b 100644 (file)
@@ -82,10 +82,6 @@ struct r100_cs_track {
 
 int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track);
 void r100_cs_track_clear(struct radeon_device *rdev, struct r100_cs_track *track);
-int r100_cs_packet_next_reloc(struct radeon_cs_parser *p,
-                             struct radeon_cs_reloc **cs_reloc);
-void r100_cs_dump_packet(struct radeon_cs_parser *p,
-                        struct radeon_cs_packet *pkt);
 
 int r100_cs_packet_parse_vline(struct radeon_cs_parser *p);
 
index 3e357c9..873676f 100644 (file)
                         REG_SET(PACKET3_IT_OPCODE, (op)) |             \
                         REG_SET(PACKET3_COUNT, (n)))
 
-#define        PACKET_TYPE0    0
-#define        PACKET_TYPE1    1
-#define        PACKET_TYPE2    2
-#define        PACKET_TYPE3    3
-
-#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3)
-#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF)
-#define CP_PACKET0_GET_REG(h) (((h) & 0x1FFF) << 2)
-#define CP_PACKET0_GET_ONE_REG_WR(h) (((h) >> 15) & 1)
-#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF)
-
 /* Registers */
 #define R_0000F0_RBBM_SOFT_RESET                     0x0000F0
 #define   S_0000F0_SOFT_RESET_CP(x)                    (((x) & 0x1) << 0)
index 174ce93..a052d5f 100644 (file)
@@ -165,7 +165,7 @@ int r200_packet0_check(struct radeon_cs_parser *p,
                if (r) {
                        DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
                                  idx, reg);
-                       r100_cs_dump_packet(p, pkt);
+                       radeon_cs_dump_packet(p, pkt);
                        return r;
                }
                break;
@@ -178,11 +178,11 @@ int r200_packet0_check(struct radeon_cs_parser *p,
                        return r;
                break;
        case RADEON_RB3D_DEPTHOFFSET:
-               r = r100_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
                                  idx, reg);
-                       r100_cs_dump_packet(p, pkt);
+                       radeon_cs_dump_packet(p, pkt);
                        return r;
                }
                track->zb.robj = reloc->robj;
@@ -191,11 +191,11 @@ int r200_packet0_check(struct radeon_cs_parser *p,
                ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
                break;
        case RADEON_RB3D_COLOROFFSET:
-               r = r100_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
                                  idx, reg);
-                       r100_cs_dump_packet(p, pkt);
+                       radeon_cs_dump_packet(p, pkt);
                        return r;
                }
                track->cb[0].robj = reloc->robj;
@@ -210,11 +210,11 @@ int r200_packet0_check(struct radeon_cs_parser *p,
        case R200_PP_TXOFFSET_4:
        case R200_PP_TXOFFSET_5:
                i = (reg - R200_PP_TXOFFSET_0) / 24;
-               r = r100_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
                                  idx, reg);
-                       r100_cs_dump_packet(p, pkt);
+                       radeon_cs_dump_packet(p, pkt);
                        return r;
                }
                if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
@@ -263,11 +263,11 @@ int r200_packet0_check(struct radeon_cs_parser *p,
        case R200_PP_CUBIC_OFFSET_F5_5:
                i = (reg - R200_PP_TXOFFSET_0) / 24;
                face = (reg - ((i * 24) + R200_PP_TXOFFSET_0)) / 4;
-               r = r100_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
                                  idx, reg);
-                       r100_cs_dump_packet(p, pkt);
+                       radeon_cs_dump_packet(p, pkt);
                        return r;
                }
                track->textures[i].cube_info[face - 1].offset = idx_value;
@@ -281,11 +281,11 @@ int r200_packet0_check(struct radeon_cs_parser *p,
                track->zb_dirty = true;
                break;
        case RADEON_RB3D_COLORPITCH:
-               r = r100_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
                                  idx, reg);
-                       r100_cs_dump_packet(p, pkt);
+                       radeon_cs_dump_packet(p, pkt);
                        return r;
                }
 
@@ -358,11 +358,11 @@ int r200_packet0_check(struct radeon_cs_parser *p,
                track->zb_dirty = true;
                break;
        case RADEON_RB3D_ZPASS_ADDR:
-               r = r100_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
                                  idx, reg);
-                       r100_cs_dump_packet(p, pkt);
+                       radeon_cs_dump_packet(p, pkt);
                        return r;
                }
                ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
index 13e47ef..f926599 100644 (file)
@@ -617,7 +617,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
                if (r) {
                        DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
                                        idx, reg);
-                       r100_cs_dump_packet(p, pkt);
+                       radeon_cs_dump_packet(p, pkt);
                        return r;
                }
                break;
@@ -632,11 +632,11 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
        case R300_RB3D_COLOROFFSET2:
        case R300_RB3D_COLOROFFSET3:
                i = (reg - R300_RB3D_COLOROFFSET0) >> 2;
-               r = r100_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
                                        idx, reg);
-                       r100_cs_dump_packet(p, pkt);
+                       radeon_cs_dump_packet(p, pkt);
                        return r;
                }
                track->cb[i].robj = reloc->robj;
@@ -645,11 +645,11 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
                ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
                break;
        case R300_ZB_DEPTHOFFSET:
-               r = r100_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
                                        idx, reg);
-                       r100_cs_dump_packet(p, pkt);
+                       radeon_cs_dump_packet(p, pkt);
                        return r;
                }
                track->zb.robj = reloc->robj;
@@ -674,11 +674,11 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
        case R300_TX_OFFSET_0+56:
        case R300_TX_OFFSET_0+60:
                i = (reg - R300_TX_OFFSET_0) >> 2;
-               r = r100_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
                                        idx, reg);
-                       r100_cs_dump_packet(p, pkt);
+                       radeon_cs_dump_packet(p, pkt);
                        return r;
                }
 
@@ -747,11 +747,11 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
                /* RB3D_COLORPITCH2 */
                /* RB3D_COLORPITCH3 */
                if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
-                       r = r100_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                        if (r) {
                                DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
                                          idx, reg);
-                               r100_cs_dump_packet(p, pkt);
+                               radeon_cs_dump_packet(p, pkt);
                                return r;
                        }
 
@@ -832,11 +832,11 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
        case 0x4F24:
                /* ZB_DEPTHPITCH */
                if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
-                       r = r100_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                        if (r) {
                                DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
                                          idx, reg);
-                               r100_cs_dump_packet(p, pkt);
+                               radeon_cs_dump_packet(p, pkt);
                                return r;
                        }
 
@@ -1047,11 +1047,11 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
                track->tex_dirty = true;
                break;
        case R300_ZB_ZPASS_ADDR:
-               r = r100_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
                                        idx, reg);
-                       r100_cs_dump_packet(p, pkt);
+                       radeon_cs_dump_packet(p, pkt);
                        return r;
                }
                ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
@@ -1089,11 +1089,11 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
                track->cb_dirty = true;
                break;
        case R300_RB3D_AARESOLVE_OFFSET:
-               r = r100_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
                                  idx, reg);
-                       r100_cs_dump_packet(p, pkt);
+                       radeon_cs_dump_packet(p, pkt);
                        return r;
                }
                track->aa.robj = reloc->robj;
@@ -1158,10 +1158,10 @@ static int r300_packet3_check(struct radeon_cs_parser *p,
                        return r;
                break;
        case PACKET3_INDX_BUFFER:
-               r = r100_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("No reloc for packet3 %d\n", pkt->opcode);
-                       r100_cs_dump_packet(p, pkt);
+                       radeon_cs_dump_packet(p, pkt);
                        return r;
                }
                ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset);
@@ -1259,7 +1259,7 @@ int r300_cs_parse(struct radeon_cs_parser *p)
        r100_cs_track_clear(p->rdev, track);
        p->track = track;
        do {
-               r = r100_cs_packet_parse(p, &pkt, p->idx);
+               r = radeon_cs_packet_parse(p, &pkt, p->idx);
                if (r) {
                        drm_free(p->track, M_DRM);
                        p->track = NULL;
@@ -1267,15 +1267,15 @@ int r300_cs_parse(struct radeon_cs_parser *p)
                }
                p->idx += pkt.count + 2;
                switch (pkt.type) {
-               case PACKET_TYPE0:
+               case RADEON_PACKET_TYPE0:
                        r = r100_cs_parse_packet0(p, &pkt,
                                                  p->rdev->config.r300.reg_safe_bm,
                                                  p->rdev->config.r300.reg_safe_bm_size,
                                                  &r300_packet0_check);
                        break;
-               case PACKET_TYPE2:
+               case RADEON_PACKET_TYPE2:
                        break;
-               case PACKET_TYPE3:
+               case RADEON_PACKET_TYPE3:
                        r = r300_packet3_check(p, &pkt);
                        break;
                default:
index 522375d..cf97438 100644 (file)
@@ -30,6 +30,8 @@
  * Authors:
  *    Nicolai Haehnle <prefect_@gmx.net>
  *
+ * ------------------------ This file is DEPRECATED! -------------------------
+ *
  * $FreeBSD: head/sys/dev/drm2/radeon/r300_cmdbuf.c 254885 2013-08-25 19:37:15Z dumbbell $
  */
 
index e49183b..c7debad 100644 (file)
                         REG_SET(PACKET3_IT_OPCODE, (op)) |             \
                         REG_SET(PACKET3_COUNT, (n)))
 
-#define        PACKET_TYPE0    0
-#define        PACKET_TYPE1    1
-#define        PACKET_TYPE2    2
-#define        PACKET_TYPE3    3
-
-#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3)
-#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF)
-#define CP_PACKET0_GET_REG(h) (((h) & 0x1FFF) << 2)
-#define CP_PACKET0_GET_ONE_REG_WR(h) (((h) >> 15) & 1)
-#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF)
-
 /* Registers */
 #define R_000148_MC_FB_LOCATION                      0x000148
 #define   S_000148_MC_FB_START(x)                      (((x) & 0xFFFF) << 0)
index 5365486..952d81c 100644 (file)
 #       define AVIVO_D1CRTC_V_BLANK                             (1 << 0)
 #define AVIVO_D1CRTC_STATUS_POSITION                            0x60a0
 #define AVIVO_D1CRTC_FRAME_COUNT                                0x60a4
+#define AVIVO_D1CRTC_STATUS_HV_COUNT                            0x60ac
 #define AVIVO_D1CRTC_STEREO_CONTROL                             0x60c4
 
 #define AVIVO_D1MODE_MASTER_UPDATE_MODE                         0x60e4
index 25de552..fd4227e 100644 (file)
@@ -92,8 +92,19 @@ MODULE_FIRMWARE("radeon/SUMO_pfp.bin");
 MODULE_FIRMWARE("radeon/SUMO_me.bin");
 MODULE_FIRMWARE("radeon/SUMO2_pfp.bin");
 MODULE_FIRMWARE("radeon/SUMO2_me.bin");
+MODULE_FIRMWARE("radeon/OLAND_pfp.bin");
+MODULE_FIRMWARE("radeon/OLAND_me.bin");
+MODULE_FIRMWARE("radeon/OLAND_ce.bin");
+MODULE_FIRMWARE("radeon/OLAND_mc.bin");
+MODULE_FIRMWARE("radeon/OLAND_rlc.bin");
 #endif /* DUMBBELL_WIP */
 
+static const u32 crtc_offsets[2] =
+{
+       0,
+       AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL
+};
+
 int r600_debugfs_mc_info_init(struct radeon_device *rdev);
 
 /* r600,rv610,rv630,rv620,rv635,rv670 */
@@ -101,6 +112,19 @@ static void r600_gpu_init(struct radeon_device *rdev);
 void r600_irq_disable(struct radeon_device *rdev);
 static void r600_pcie_gen2_enable(struct radeon_device *rdev);
 
+/**
+ * r600_get_xclk - get the xclk
+ *
+ * @rdev: radeon_device pointer
+ *
+ * Returns the reference clock used by the gfx engine
+ * (r6xx, IGPs, APUs).
+ */
+u32 r600_get_xclk(struct radeon_device *rdev)
+{
+       return rdev->clock.spll.reference_freq;
+}
+
 /* get temperature in millidegrees */
 int rv6xx_get_temp(struct radeon_device *rdev)
 {
@@ -1259,169 +1283,307 @@ void r600_vram_scratch_fini(struct radeon_device *rdev)
        radeon_bo_unref(&rdev->vram_scratch.robj);
 }
 
-/* We doesn't check that the GPU really needs a reset we simply do the
- * reset, it's up to the caller to determine if the GPU needs one. We
- * might add an helper function to check that.
- */
-static void r600_gpu_soft_reset_gfx(struct radeon_device *rdev)
+void r600_set_bios_scratch_engine_hung(struct radeon_device *rdev, bool hung)
 {
-       u32 grbm_busy_mask = S_008010_VC_BUSY(1) | S_008010_VGT_BUSY_NO_DMA(1) |
-                               S_008010_VGT_BUSY(1) | S_008010_TA03_BUSY(1) |
-                               S_008010_TC_BUSY(1) | S_008010_SX_BUSY(1) |
-                               S_008010_SH_BUSY(1) | S_008010_SPI03_BUSY(1) |
-                               S_008010_SMX_BUSY(1) | S_008010_SC_BUSY(1) |
-                               S_008010_PA_BUSY(1) | S_008010_DB03_BUSY(1) |
-                               S_008010_CR_BUSY(1) | S_008010_CB03_BUSY(1) |
-                               S_008010_GUI_ACTIVE(1);
-       u32 grbm2_busy_mask = S_008014_SPI0_BUSY(1) | S_008014_SPI1_BUSY(1) |
-                       S_008014_SPI2_BUSY(1) | S_008014_SPI3_BUSY(1) |
-                       S_008014_TA0_BUSY(1) | S_008014_TA1_BUSY(1) |
-                       S_008014_TA2_BUSY(1) | S_008014_TA3_BUSY(1) |
-                       S_008014_DB0_BUSY(1) | S_008014_DB1_BUSY(1) |
-                       S_008014_DB2_BUSY(1) | S_008014_DB3_BUSY(1) |
-                       S_008014_CB0_BUSY(1) | S_008014_CB1_BUSY(1) |
-                       S_008014_CB2_BUSY(1) | S_008014_CB3_BUSY(1);
-       u32 tmp;
+       u32 tmp = RREG32(R600_BIOS_3_SCRATCH);
 
-       if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
-               return;
+       if (hung)
+               tmp |= ATOM_S3_ASIC_GUI_ENGINE_HUNG;
+       else
+               tmp &= ~ATOM_S3_ASIC_GUI_ENGINE_HUNG;
+
+       WREG32(R600_BIOS_3_SCRATCH, tmp);
+}
 
+static void r600_print_gpu_status_regs(struct radeon_device *rdev)
+{
        dev_info(rdev->dev, "  R_008010_GRBM_STATUS      = 0x%08X\n",
-               RREG32(R_008010_GRBM_STATUS));
+                RREG32(R_008010_GRBM_STATUS));
        dev_info(rdev->dev, "  R_008014_GRBM_STATUS2     = 0x%08X\n",
-               RREG32(R_008014_GRBM_STATUS2));
+                RREG32(R_008014_GRBM_STATUS2));
        dev_info(rdev->dev, "  R_000E50_SRBM_STATUS      = 0x%08X\n",
-               RREG32(R_000E50_SRBM_STATUS));
+                RREG32(R_000E50_SRBM_STATUS));
        dev_info(rdev->dev, "  R_008674_CP_STALLED_STAT1 = 0x%08X\n",
-               RREG32(CP_STALLED_STAT1));
+                RREG32(CP_STALLED_STAT1));
        dev_info(rdev->dev, "  R_008678_CP_STALLED_STAT2 = 0x%08X\n",
-               RREG32(CP_STALLED_STAT2));
+                RREG32(CP_STALLED_STAT2));
        dev_info(rdev->dev, "  R_00867C_CP_BUSY_STAT     = 0x%08X\n",
-               RREG32(CP_BUSY_STAT));
+                RREG32(CP_BUSY_STAT));
        dev_info(rdev->dev, "  R_008680_CP_STAT          = 0x%08X\n",
-               RREG32(CP_STAT));
-
-       /* Disable CP parsing/prefetching */
-       WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1));
+                RREG32(CP_STAT));
+       dev_info(rdev->dev, "  R_00D034_DMA_STATUS_REG   = 0x%08X\n",
+               RREG32(DMA_STATUS_REG));
+}
 
-       /* Check if any of the rendering block is busy and reset it */
-       if ((RREG32(R_008010_GRBM_STATUS) & grbm_busy_mask) ||
-           (RREG32(R_008014_GRBM_STATUS2) & grbm2_busy_mask)) {
-               tmp = S_008020_SOFT_RESET_CR(1) |
-                       S_008020_SOFT_RESET_DB(1) |
-                       S_008020_SOFT_RESET_CB(1) |
-                       S_008020_SOFT_RESET_PA(1) |
-                       S_008020_SOFT_RESET_SC(1) |
-                       S_008020_SOFT_RESET_SMX(1) |
-                       S_008020_SOFT_RESET_SPI(1) |
-                       S_008020_SOFT_RESET_SX(1) |
-                       S_008020_SOFT_RESET_SH(1) |
-                       S_008020_SOFT_RESET_TC(1) |
-                       S_008020_SOFT_RESET_TA(1) |
-                       S_008020_SOFT_RESET_VC(1) |
-                       S_008020_SOFT_RESET_VGT(1);
-               dev_info(rdev->dev, "  R_008020_GRBM_SOFT_RESET=0x%08X\n", tmp);
-               WREG32(R_008020_GRBM_SOFT_RESET, tmp);
-               RREG32(R_008020_GRBM_SOFT_RESET);
-               DRM_MDELAY(15);
-               WREG32(R_008020_GRBM_SOFT_RESET, 0);
+static bool r600_is_display_hung(struct radeon_device *rdev)
+{
+       u32 crtc_hung = 0;
+       u32 crtc_status[2];
+       u32 i, j, tmp;
+
+       for (i = 0; i < rdev->num_crtc; i++) {
+               if (RREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i]) & AVIVO_CRTC_EN) {
+                       crtc_status[i] = RREG32(AVIVO_D1CRTC_STATUS_HV_COUNT + crtc_offsets[i]);
+                       crtc_hung |= (1 << i);
+               }
        }
-       /* Reset CP (we always reset CP) */
-       tmp = S_008020_SOFT_RESET_CP(1);
-       dev_info(rdev->dev, "R_008020_GRBM_SOFT_RESET=0x%08X\n", tmp);
-       WREG32(R_008020_GRBM_SOFT_RESET, tmp);
-       RREG32(R_008020_GRBM_SOFT_RESET);
-       DRM_MDELAY(15);
-       WREG32(R_008020_GRBM_SOFT_RESET, 0);
 
-       dev_info(rdev->dev, "  R_008010_GRBM_STATUS      = 0x%08X\n",
-               RREG32(R_008010_GRBM_STATUS));
-       dev_info(rdev->dev, "  R_008014_GRBM_STATUS2     = 0x%08X\n",
-               RREG32(R_008014_GRBM_STATUS2));
-       dev_info(rdev->dev, "  R_000E50_SRBM_STATUS      = 0x%08X\n",
-               RREG32(R_000E50_SRBM_STATUS));
-       dev_info(rdev->dev, "  R_008674_CP_STALLED_STAT1 = 0x%08X\n",
-               RREG32(CP_STALLED_STAT1));
-       dev_info(rdev->dev, "  R_008678_CP_STALLED_STAT2 = 0x%08X\n",
-               RREG32(CP_STALLED_STAT2));
-       dev_info(rdev->dev, "  R_00867C_CP_BUSY_STAT     = 0x%08X\n",
-               RREG32(CP_BUSY_STAT));
-       dev_info(rdev->dev, "  R_008680_CP_STAT          = 0x%08X\n",
-               RREG32(CP_STAT));
+       for (j = 0; j < 10; j++) {
+               for (i = 0; i < rdev->num_crtc; i++) {
+                       if (crtc_hung & (1 << i)) {
+                               tmp = RREG32(AVIVO_D1CRTC_STATUS_HV_COUNT + crtc_offsets[i]);
+                               if (tmp != crtc_status[i])
+                                       crtc_hung &= ~(1 << i);
+                       }
+               }
+               if (crtc_hung == 0)
+                       return false;
+               DRM_UDELAY(100);
+       }
 
+       return true;
 }
 
-static void r600_gpu_soft_reset_dma(struct radeon_device *rdev)
+static u32 r600_gpu_check_soft_reset(struct radeon_device *rdev)
 {
+       u32 reset_mask = 0;
        u32 tmp;
 
-       if (RREG32(DMA_STATUS_REG) & DMA_IDLE)
-               return;
+       /* GRBM_STATUS */
+       tmp = RREG32(R_008010_GRBM_STATUS);
+       if (rdev->family >= CHIP_RV770) {
+               if (G_008010_PA_BUSY(tmp) | G_008010_SC_BUSY(tmp) |
+                   G_008010_SH_BUSY(tmp) | G_008010_SX_BUSY(tmp) |
+                   G_008010_TA_BUSY(tmp) | G_008010_VGT_BUSY(tmp) |
+                   G_008010_DB03_BUSY(tmp) | G_008010_CB03_BUSY(tmp) |
+                   G_008010_SPI03_BUSY(tmp) | G_008010_VGT_BUSY_NO_DMA(tmp))
+                       reset_mask |= RADEON_RESET_GFX;
+       } else {
+               if (G_008010_PA_BUSY(tmp) | G_008010_SC_BUSY(tmp) |
+                   G_008010_SH_BUSY(tmp) | G_008010_SX_BUSY(tmp) |
+                   G_008010_TA03_BUSY(tmp) | G_008010_VGT_BUSY(tmp) |
+                   G_008010_DB03_BUSY(tmp) | G_008010_CB03_BUSY(tmp) |
+                   G_008010_SPI03_BUSY(tmp) | G_008010_VGT_BUSY_NO_DMA(tmp))
+                       reset_mask |= RADEON_RESET_GFX;
+       }
 
-       dev_info(rdev->dev, "  R_00D034_DMA_STATUS_REG   = 0x%08X\n",
-               RREG32(DMA_STATUS_REG));
+       if (G_008010_CF_RQ_PENDING(tmp) | G_008010_PF_RQ_PENDING(tmp) |
+           G_008010_CP_BUSY(tmp) | G_008010_CP_COHERENCY_BUSY(tmp))
+               reset_mask |= RADEON_RESET_CP;
 
-       /* Disable DMA */
-       tmp = RREG32(DMA_RB_CNTL);
-       tmp &= ~DMA_RB_ENABLE;
-       WREG32(DMA_RB_CNTL, tmp);
+       if (G_008010_GRBM_EE_BUSY(tmp))
+               reset_mask |= RADEON_RESET_GRBM | RADEON_RESET_GFX | RADEON_RESET_CP;
 
-       /* Reset dma */
-       if (rdev->family >= CHIP_RV770)
-               WREG32(SRBM_SOFT_RESET, RV770_SOFT_RESET_DMA);
-       else
-               WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA);
-       RREG32(SRBM_SOFT_RESET);
-       DRM_UDELAY(50);
-       WREG32(SRBM_SOFT_RESET, 0);
+       /* DMA_STATUS_REG */
+       tmp = RREG32(DMA_STATUS_REG);
+       if (!(tmp & DMA_IDLE))
+               reset_mask |= RADEON_RESET_DMA;
 
-       dev_info(rdev->dev, "  R_00D034_DMA_STATUS_REG   = 0x%08X\n",
-               RREG32(DMA_STATUS_REG));
+       /* SRBM_STATUS */
+       tmp = RREG32(R_000E50_SRBM_STATUS);
+       if (G_000E50_RLC_RQ_PENDING(tmp) | G_000E50_RLC_BUSY(tmp))
+               reset_mask |= RADEON_RESET_RLC;
+
+       if (G_000E50_IH_BUSY(tmp))
+               reset_mask |= RADEON_RESET_IH;
+
+       if (G_000E50_SEM_BUSY(tmp))
+               reset_mask |= RADEON_RESET_SEM;
+
+       if (G_000E50_GRBM_RQ_PENDING(tmp))
+               reset_mask |= RADEON_RESET_GRBM;
+
+       if (G_000E50_VMC_BUSY(tmp))
+               reset_mask |= RADEON_RESET_VMC;
+
+       if (G_000E50_MCB_BUSY(tmp) | G_000E50_MCDZ_BUSY(tmp) |
+           G_000E50_MCDY_BUSY(tmp) | G_000E50_MCDX_BUSY(tmp) |
+           G_000E50_MCDW_BUSY(tmp))
+               reset_mask |= RADEON_RESET_MC;
+
+       if (r600_is_display_hung(rdev))
+               reset_mask |= RADEON_RESET_DISPLAY;
+
+       /* Skip MC reset as it's mostly likely not hung, just busy */
+       if (reset_mask & RADEON_RESET_MC) {
+               DRM_DEBUG("MC busy: 0x%08X, clearing.\n", reset_mask);
+               reset_mask &= ~RADEON_RESET_MC;
+       }
+
+       return reset_mask;
 }
 
-static int r600_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
+static void r600_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
 {
        struct rv515_mc_save save;
-
-       if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
-               reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE);
-
-       if (RREG32(DMA_STATUS_REG) & DMA_IDLE)
-               reset_mask &= ~RADEON_RESET_DMA;
+       u32 grbm_soft_reset = 0, srbm_soft_reset = 0;
+       u32 tmp;
 
        if (reset_mask == 0)
-               return 0;
+               return;
 
        dev_info(rdev->dev, "GPU softreset: 0x%08X\n", reset_mask);
 
+       r600_print_gpu_status_regs(rdev);
+
+       /* Disable CP parsing/prefetching */
+       if (rdev->family >= CHIP_RV770)
+               WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1) | S_0086D8_CP_PFP_HALT(1));
+       else
+               WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1));
+
+       /* disable the RLC */
+       WREG32(RLC_CNTL, 0);
+
+       if (reset_mask & RADEON_RESET_DMA) {
+               /* Disable DMA */
+               tmp = RREG32(DMA_RB_CNTL);
+               tmp &= ~DMA_RB_ENABLE;
+               WREG32(DMA_RB_CNTL, tmp);
+       }
+
+       DRM_MDELAY(50);
+
        rv515_mc_stop(rdev, &save);
        if (r600_mc_wait_for_idle(rdev)) {
                dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
        }
 
-       if (reset_mask & (RADEON_RESET_GFX | RADEON_RESET_COMPUTE))
-               r600_gpu_soft_reset_gfx(rdev);
+       if (reset_mask & (RADEON_RESET_GFX | RADEON_RESET_COMPUTE)) {
+               if (rdev->family >= CHIP_RV770)
+                       grbm_soft_reset |= S_008020_SOFT_RESET_DB(1) |
+                               S_008020_SOFT_RESET_CB(1) |
+                               S_008020_SOFT_RESET_PA(1) |
+                               S_008020_SOFT_RESET_SC(1) |
+                               S_008020_SOFT_RESET_SPI(1) |
+                               S_008020_SOFT_RESET_SX(1) |
+                               S_008020_SOFT_RESET_SH(1) |
+                               S_008020_SOFT_RESET_TC(1) |
+                               S_008020_SOFT_RESET_TA(1) |
+                               S_008020_SOFT_RESET_VC(1) |
+                               S_008020_SOFT_RESET_VGT(1);
+               else
+                       grbm_soft_reset |= S_008020_SOFT_RESET_CR(1) |
+                               S_008020_SOFT_RESET_DB(1) |
+                               S_008020_SOFT_RESET_CB(1) |
+                               S_008020_SOFT_RESET_PA(1) |
+                               S_008020_SOFT_RESET_SC(1) |
+                               S_008020_SOFT_RESET_SMX(1) |
+                               S_008020_SOFT_RESET_SPI(1) |
+                               S_008020_SOFT_RESET_SX(1) |
+                               S_008020_SOFT_RESET_SH(1) |
+                               S_008020_SOFT_RESET_TC(1) |
+                               S_008020_SOFT_RESET_TA(1) |
+                               S_008020_SOFT_RESET_VC(1) |
+                               S_008020_SOFT_RESET_VGT(1);
+       }
+
+       if (reset_mask & RADEON_RESET_CP) {
+               grbm_soft_reset |= S_008020_SOFT_RESET_CP(1) |
+                       S_008020_SOFT_RESET_VGT(1);
+
+               srbm_soft_reset |= S_000E60_SOFT_RESET_GRBM(1);
+       }
+
+       if (reset_mask & RADEON_RESET_DMA) {
+               if (rdev->family >= CHIP_RV770)
+                       srbm_soft_reset |= RV770_SOFT_RESET_DMA;
+               else
+                       srbm_soft_reset |= SOFT_RESET_DMA;
+       }
+
+       if (reset_mask & RADEON_RESET_RLC)
+               srbm_soft_reset |= S_000E60_SOFT_RESET_RLC(1);
+
+       if (reset_mask & RADEON_RESET_SEM)
+               srbm_soft_reset |= S_000E60_SOFT_RESET_SEM(1);
+
+       if (reset_mask & RADEON_RESET_IH)
+               srbm_soft_reset |= S_000E60_SOFT_RESET_IH(1);
+
+       if (reset_mask & RADEON_RESET_GRBM)
+               srbm_soft_reset |= S_000E60_SOFT_RESET_GRBM(1);
+
+       if (!(rdev->flags & RADEON_IS_IGP)) {
+               if (reset_mask & RADEON_RESET_MC)
+                       srbm_soft_reset |= S_000E60_SOFT_RESET_MC(1);
+       }
+
+       if (reset_mask & RADEON_RESET_VMC)
+               srbm_soft_reset |= S_000E60_SOFT_RESET_VMC(1);
+
+       if (grbm_soft_reset) {
+               tmp = RREG32(R_008020_GRBM_SOFT_RESET);
+               tmp |= grbm_soft_reset;
+               dev_info(rdev->dev, "R_008020_GRBM_SOFT_RESET=0x%08X\n", tmp);
+               WREG32(R_008020_GRBM_SOFT_RESET, tmp);
+               tmp = RREG32(R_008020_GRBM_SOFT_RESET);
 
-       if (reset_mask & RADEON_RESET_DMA)
-               r600_gpu_soft_reset_dma(rdev);
+               DRM_UDELAY(50);
+
+               tmp &= ~grbm_soft_reset;
+               WREG32(R_008020_GRBM_SOFT_RESET, tmp);
+               tmp = RREG32(R_008020_GRBM_SOFT_RESET);
+       }
+
+       if (srbm_soft_reset) {
+               tmp = RREG32(SRBM_SOFT_RESET);
+               tmp |= srbm_soft_reset;
+               dev_info(rdev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp);
+               WREG32(SRBM_SOFT_RESET, tmp);
+               tmp = RREG32(SRBM_SOFT_RESET);
+
+               DRM_UDELAY(50);
+
+               tmp &= ~srbm_soft_reset;
+               WREG32(SRBM_SOFT_RESET, tmp);
+               tmp = RREG32(SRBM_SOFT_RESET);
+       }
 
        /* Wait a little for things to settle down */
        DRM_MDELAY(1);
 
        rv515_mc_resume(rdev, &save);
+       DRM_UDELAY(50);
+
+       r600_print_gpu_status_regs(rdev);
+}
+
+int r600_asic_reset(struct radeon_device *rdev)
+{
+       u32 reset_mask;
+
+       reset_mask = r600_gpu_check_soft_reset(rdev);
+
+       if (reset_mask)
+               r600_set_bios_scratch_engine_hung(rdev, true);
+
+       r600_gpu_soft_reset(rdev, reset_mask);
+
+       reset_mask = r600_gpu_check_soft_reset(rdev);
+
+       if (!reset_mask)
+               r600_set_bios_scratch_engine_hung(rdev, false);
+
        return 0;
 }
 
-bool r600_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
+/**
+ * r600_gfx_is_lockup - Check if the GFX engine is locked up
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon_ring structure holding ring information
+ *
+ * Check if the GFX engine is locked up.
+ * Returns true if the engine appears to be locked up, false if not.
+ */
+bool r600_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
 {
-       u32 srbm_status;
-       u32 grbm_status;
-       u32 grbm_status2;
-
-       srbm_status = RREG32(R_000E50_SRBM_STATUS);
-       grbm_status = RREG32(R_008010_GRBM_STATUS);
-       grbm_status2 = RREG32(R_008014_GRBM_STATUS2);
-       if (!G_008010_GUI_ACTIVE(grbm_status)) {
+       u32 reset_mask = r600_gpu_check_soft_reset(rdev);
+
+       if (!(reset_mask & (RADEON_RESET_GFX |
+                           RADEON_RESET_COMPUTE |
+                           RADEON_RESET_CP))) {
                radeon_ring_lockup_update(ring);
                return false;
        }
@@ -1436,15 +1598,14 @@ bool r600_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
  * @rdev: radeon_device pointer
  * @ring: radeon_ring structure holding ring information
  *
- * Check if the async DMA engine is locked up (r6xx-evergreen).
+ * Check if the async DMA engine is locked up.
  * Returns true if the engine appears to be locked up, false if not.
  */
 bool r600_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
 {
-       u32 dma_status_reg;
+       u32 reset_mask = r600_gpu_check_soft_reset(rdev);
 
-       dma_status_reg = RREG32(DMA_STATUS_REG);
-       if (dma_status_reg & DMA_IDLE) {
+       if (!(reset_mask & RADEON_RESET_DMA)) {
                radeon_ring_lockup_update(ring);
                return false;
        }
@@ -1453,13 +1614,6 @@ bool r600_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
        return radeon_ring_test_lockup(rdev, ring);
 }
 
-int r600_asic_reset(struct radeon_device *rdev)
-{
-       return r600_gpu_soft_reset(rdev, (RADEON_RESET_GFX |
-                                         RADEON_RESET_COMPUTE |
-                                         RADEON_RESET_DMA));
-}
-
 u32 r6xx_remap_render_backend(struct radeon_device *rdev,
                              u32 tiling_pipe_num,
                              u32 max_rb_num,
@@ -4364,14 +4518,14 @@ static void r600_pcie_gen2_enable(struct radeon_device *rdev)
 }
 
 /**
- * r600_get_gpu_clock - return GPU clock counter snapshot
+ * r600_get_gpu_clock_counter - return GPU clock counter snapshot
  *
  * @rdev: radeon_device pointer
  *
  * Fetches a GPU clock counter snapshot (R6xx-cayman).
  * Returns the 64 bit clock counter snapshot.
  */
-uint64_t r600_get_gpu_clock(struct radeon_device *rdev)
+uint64_t r600_get_gpu_clock_counter(struct radeon_device *rdev)
 {
        uint64_t clock;
 
index 943bb3a..895d952 100644 (file)
@@ -23,6 +23,8 @@
  * Authors:
  *     Alex Deucher <alexander.deucher@amd.com>
  *
+ * ------------------------ This file is DEPRECATED! -------------------------
+ *
  * $FreeBSD: head/sys/dev/drm2/radeon/r600_blit.c 254885 2013-08-25 19:37:15Z dumbbell $
  */
 
@@ -491,37 +493,6 @@ set_default_state(drm_radeon_private_t *dev_priv)
        ADVANCE_RING();
 }
 
-/* 23 bits of float fractional data */
-#define I2F_FRAC_BITS  23
-#define I2F_MASK ((1 << I2F_FRAC_BITS) - 1)
-
-/*
- * Converts unsigned integer into 32-bit IEEE floating point representation.
- * Will be exact from 0 to 2^24.  Above that, we round towards zero
- * as the fractional bits will not fit in a float.  (It would be better to
- * round towards even as the fpu does, but that is slower.)
- */
-__pure uint32_t int2float(uint32_t x)
-{
-       uint32_t msb, exponent, fraction;
-
-       /* Zero is special */
-       if (!x) return 0;
-
-       /* Get location of the most significant bit */
-       msb = fls(x);
-
-       /*
-        * Use a rotate instead of a shift because that works both leftwards
-        * and rightwards due to the mod(32) behaviour.  This means we don't
-        * need to check to see if we are above 2^24 or not.
-        */
-       fraction = ror32(x, (msb - I2F_FRAC_BITS) & 0x1f) & I2F_MASK;
-       exponent = (127 + msb) << I2F_FRAC_BITS;
-
-       return fraction + exponent;
-}
-
 static int r600_nomm_get_vb(struct drm_device *dev)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
index 8e6309f..0e8ac6f 100644 (file)
 #include "r600_blit_shaders.h"
 #include "radeon_blit_common.h"
 
+/* 23 bits of float fractional data */
+#define I2F_FRAC_BITS  23
+#define I2F_MASK ((1 << I2F_FRAC_BITS) - 1)
+
+/*
+ * Converts unsigned integer into 32-bit IEEE floating point representation.
+ * Will be exact from 0 to 2^24.  Above that, we round towards zero
+ * as the fractional bits will not fit in a float.  (It would be better to
+ * round towards even as the fpu does, but that is slower.)
+ */
+__pure uint32_t int2float(uint32_t x)
+{
+       uint32_t msb, exponent, fraction;
+
+       /* Zero is special */
+       if (!x) return 0;
+
+       /* Get location of the most significant bit */
+       msb = fls(x);
+
+       /*
+        * Use a rotate instead of a shift because that works both leftwards
+        * and rightwards due to the mod(32) behaviour.  This means we don't
+        * need to check to see if we are above 2^24 or not.
+        */
+       fraction = ror32(x, (msb - I2F_FRAC_BITS) & 0x1f) & I2F_MASK;
+       exponent = (127 + msb) << I2F_FRAC_BITS;
+
+       return fraction + exponent;
+}
+
 /* emits 21 on rv770+, 23 on r600 */
 static void
 set_render_target(struct radeon_device *rdev, int format,
index a7fe4b6..4787091 100644 (file)
@@ -25,6 +25,8 @@
  *     Dave Airlie <airlied@redhat.com>
  *     Alex Deucher <alexander.deucher@amd.com>
  *
+ * ------------------------ This file is DEPRECATED! -------------------------
+ *
  * $FreeBSD: head/sys/dev/drm2/radeon/r600_cp.c 254885 2013-08-25 19:37:15Z dumbbell $
  */
 
index d83505d..8c6061e 100644 (file)
 #include "r600_cp.h"
 #include "r600_cs.h"
 
-static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p,
-                                       struct radeon_cs_reloc **cs_reloc);
-static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p,
-                                       struct radeon_cs_reloc **cs_reloc);
-typedef int (*next_reloc_t)(struct radeon_cs_parser*, struct radeon_cs_reloc**);
-static next_reloc_t r600_cs_packet_next_reloc = &r600_cs_packet_next_reloc_mm;
-
+static int r600_nomm;
 
 struct r600_cs_track {
        /* configuration we miror so that we use same code btw kms/ums */
@@ -788,170 +782,29 @@ static int r600_cs_track_check(struct radeon_cs_parser *p)
 }
 
 /**
- * r600_cs_packet_parse() - parse cp packet and point ib index to next packet
- * @parser:    parser structure holding parsing context.
- * @pkt:       where to store packet informations
- *
- * Assume that chunk_ib_index is properly set. Will return -EINVAL
- * if packet is bigger than remaining ib size. or if packets is unknown.
- **/
-static int r600_cs_packet_parse(struct radeon_cs_parser *p,
-                       struct radeon_cs_packet *pkt,
-                       unsigned idx)
-{
-       struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx];
-       uint32_t header;
-
-       if (idx >= ib_chunk->length_dw) {
-               DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
-                         idx, ib_chunk->length_dw);
-               return -EINVAL;
-       }
-       header = radeon_get_ib_value(p, idx);
-       pkt->idx = idx;
-       pkt->type = CP_PACKET_GET_TYPE(header);
-       pkt->count = CP_PACKET_GET_COUNT(header);
-       pkt->one_reg_wr = 0;
-       switch (pkt->type) {
-       case PACKET_TYPE0:
-               pkt->reg = CP_PACKET0_GET_REG(header);
-               break;
-       case PACKET_TYPE3:
-               pkt->opcode = CP_PACKET3_GET_OPCODE(header);
-               break;
-       case PACKET_TYPE2:
-               pkt->count = -1;
-               break;
-       default:
-               DRM_ERROR("Unknown packet type %d at %d !\n", pkt->type, idx);
-               return -EINVAL;
-       }
-       if ((pkt->count + 1 + pkt->idx) >= ib_chunk->length_dw) {
-               DRM_ERROR("Packet (%d:%d:%d) end after CS buffer (%d) !\n",
-                         pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw);
-               return -EINVAL;
-       }
-       return 0;
-}
-
-/**
- * r600_cs_packet_next_reloc_mm() - parse next packet which should be reloc packet3
- * @parser:            parser structure holding parsing context.
- * @data:              pointer to relocation data
- * @offset_start:      starting offset
- * @offset_mask:       offset mask (to align start offset on)
- * @reloc:             reloc informations
- *
- * Check next packet is relocation packet3, do bo validation and compute
- * GPU offset using the provided start.
- **/
-static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p,
-                                       struct radeon_cs_reloc **cs_reloc)
-{
-       struct radeon_cs_chunk *relocs_chunk;
-       struct radeon_cs_packet p3reloc;
-       unsigned idx;
-       int r;
-
-       if (p->chunk_relocs_idx == -1) {
-               DRM_ERROR("No relocation chunk !\n");
-               return -EINVAL;
-       }
-       *cs_reloc = NULL;
-       relocs_chunk = &p->chunks[p->chunk_relocs_idx];
-       r = r600_cs_packet_parse(p, &p3reloc, p->idx);
-       if (r) {
-               return r;
-       }
-       p->idx += p3reloc.count + 2;
-       if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
-               DRM_ERROR("No packet3 for relocation for packet at %d.\n",
-                         p3reloc.idx);
-               return -EINVAL;
-       }
-       idx = radeon_get_ib_value(p, p3reloc.idx + 1);
-       if (idx >= relocs_chunk->length_dw) {
-               DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
-                         idx, relocs_chunk->length_dw);
-               return -EINVAL;
-       }
-       /* FIXME: we assume reloc size is 4 dwords */
-       *cs_reloc = p->relocs_ptr[(idx / 4)];
-       return 0;
-}
-
-/**
- * r600_cs_packet_next_reloc_nomm() - parse next packet which should be reloc packet3
- * @parser:            parser structure holding parsing context.
- * @data:              pointer to relocation data
- * @offset_start:      starting offset
- * @offset_mask:       offset mask (to align start offset on)
- * @reloc:             reloc informations
- *
- * Check next packet is relocation packet3, do bo validation and compute
- * GPU offset using the provided start.
- **/
-static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p,
-                                       struct radeon_cs_reloc **cs_reloc)
-{
-       struct radeon_cs_chunk *relocs_chunk;
-       struct radeon_cs_packet p3reloc;
-       unsigned idx;
-       int r;
-
-       if (p->chunk_relocs_idx == -1) {
-               DRM_ERROR("No relocation chunk !\n");
-               return -EINVAL;
-       }
-       *cs_reloc = NULL;
-       relocs_chunk = &p->chunks[p->chunk_relocs_idx];
-       r = r600_cs_packet_parse(p, &p3reloc, p->idx);
-       if (r) {
-               return r;
-       }
-       p->idx += p3reloc.count + 2;
-       if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
-               DRM_ERROR("No packet3 for relocation for packet at %d.\n",
-                         p3reloc.idx);
-               return -EINVAL;
-       }
-       idx = radeon_get_ib_value(p, p3reloc.idx + 1);
-       if (idx >= relocs_chunk->length_dw) {
-               DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
-                         idx, relocs_chunk->length_dw);
-               return -EINVAL;
-       }
-       *cs_reloc = p->relocs;
-       (*cs_reloc)->lobj.gpu_offset = (u64)relocs_chunk->kdata[idx + 3] << 32;
-       (*cs_reloc)->lobj.gpu_offset |= relocs_chunk->kdata[idx + 0];
-       return 0;
-}
-
-/**
- * r600_cs_packet_next_is_pkt3_nop() - test if next packet is packet3 nop for reloc
+ * r600_cs_packet_parse_vline() - parse userspace VLINE packet
  * @parser:            parser structure holding parsing context.
  *
- * Check next packet is relocation packet3, do bo validation and compute
- * GPU offset using the provided start.
- **/
-static int r600_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p)
+ * This is an R600-specific function for parsing VLINE packets.
+ * Real work is done by r600_cs_common_vline_parse function.
+ * Here we just set up ASIC-specific register table and call
+ * the common implementation function.
+ */
+static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
 {
-       struct radeon_cs_packet p3reloc;
-       int r;
+       static uint32_t vline_start_end[2] = {AVIVO_D1MODE_VLINE_START_END,
+                                             AVIVO_D2MODE_VLINE_START_END};
+       static uint32_t vline_status[2] = {AVIVO_D1MODE_VLINE_STATUS,
+                                          AVIVO_D2MODE_VLINE_STATUS};
 
-       r = r600_cs_packet_parse(p, &p3reloc, p->idx);
-       if (r) {
-               return 0;
-       }
-       if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
-               return 0;
-       }
-       return 1;
+       return r600_cs_common_vline_parse(p, vline_start_end, vline_status);
 }
 
 /**
- * r600_cs_packet_next_vline() - parse userspace VLINE packet
+ * r600_cs_common_vline_parse() - common vline parser
  * @parser:            parser structure holding parsing context.
+ * @vline_start_end:    table of vline_start_end registers
+ * @vline_status:       table of vline_status registers
  *
  * Userspace sends a special sequence for VLINE waits.
  * PACKET0 - VLINE_START_END + value
@@ -961,9 +814,16 @@ static int r600_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p)
  * This function parses this and relocates the VLINE START END
  * and WAIT_REG_MEM packets to the correct crtc.
  * It also detects a switched off crtc and nulls out the
- * wait in that case.
+ * wait in that case. This function is common for all ASICs that
+ * are R600 and newer. The parsing algorithm is the same, and only
+ * differs in which registers are used.
+ *
+ * Caller is the ASIC-specific function which passes the parser
+ * context and ASIC-specific register table
  */
-static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
+int r600_cs_common_vline_parse(struct radeon_cs_parser *p,
+                              uint32_t *vline_start_end,
+                              uint32_t *vline_status)
 {
        struct drm_mode_object *obj;
        struct drm_crtc *crtc;
@@ -977,12 +837,12 @@ static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
        ib = p->ib.ptr;
 
        /* parse the WAIT_REG_MEM */
-       r = r600_cs_packet_parse(p, &wait_reg_mem, p->idx);
+       r = radeon_cs_packet_parse(p, &wait_reg_mem, p->idx);
        if (r)
                return r;
 
        /* check its a WAIT_REG_MEM */
-       if (wait_reg_mem.type != PACKET_TYPE3 ||
+       if (wait_reg_mem.type != RADEON_PACKET_TYPE3 ||
            wait_reg_mem.opcode != PACKET3_WAIT_REG_MEM) {
                DRM_ERROR("vline wait missing WAIT_REG_MEM segment\n");
                return -EINVAL;
@@ -991,7 +851,12 @@ static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
        wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1);
        /* bit 4 is reg (0) or mem (1) */
        if (wait_reg_mem_info & 0x10) {
-               DRM_ERROR("vline WAIT_REG_MEM waiting on MEM rather than REG\n");
+               DRM_ERROR("vline WAIT_REG_MEM waiting on MEM instead of REG\n");
+               return -EINVAL;
+       }
+       /* bit 8 is me (0) or pfp (1) */
+       if (wait_reg_mem_info & 0x100) {
+               DRM_ERROR("vline WAIT_REG_MEM waiting on PFP instead of ME\n");
                return -EINVAL;
        }
        /* waiting for value to be equal */
@@ -999,18 +864,18 @@ static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
                DRM_ERROR("vline WAIT_REG_MEM function not equal\n");
                return -EINVAL;
        }
-       if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != AVIVO_D1MODE_VLINE_STATUS) {
+       if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != vline_status[0]) {
                DRM_ERROR("vline WAIT_REG_MEM bad reg\n");
                return -EINVAL;
        }
 
-       if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != AVIVO_D1MODE_VLINE_STAT) {
+       if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != RADEON_VLINE_STAT) {
                DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n");
                return -EINVAL;
        }
 
        /* jump over the NOP */
-       r = r600_cs_packet_parse(p, &p3reloc, p->idx + wait_reg_mem.count + 2);
+       r = radeon_cs_packet_parse(p, &p3reloc, p->idx + wait_reg_mem.count + 2);
        if (r)
                return r;
 
@@ -1020,7 +885,7 @@ static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
 
        header = radeon_get_ib_value(p, h_idx);
        crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1);
-       reg = CP_PACKET0_GET_REG(header);
+       reg = R600_CP_PACKET0_GET_REG(header);
 
        obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
        if (!obj) {
@@ -1032,7 +897,7 @@ static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
        crtc_id = radeon_crtc->crtc_id;
 
        if (!crtc->enabled) {
-               /* if the CRTC isn't enabled - we need to nop out the WAIT_REG_MEM */
+               /* CRTC isn't enabled - we need to nop out the WAIT_REG_MEM */
                ib[h_idx + 2] = PACKET2(0);
                ib[h_idx + 3] = PACKET2(0);
                ib[h_idx + 4] = PACKET2(0);
@@ -1040,20 +905,15 @@ static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
                ib[h_idx + 6] = PACKET2(0);
                ib[h_idx + 7] = PACKET2(0);
                ib[h_idx + 8] = PACKET2(0);
-       } else if (crtc_id == 1) {
-               switch (reg) {
-               case AVIVO_D1MODE_VLINE_START_END:
-                       header &= ~R600_CP_PACKET0_REG_MASK;
-                       header |= AVIVO_D2MODE_VLINE_START_END >> 2;
-                       break;
-               default:
-                       DRM_ERROR("unknown crtc reloc\n");
-                       return -EINVAL;
-               }
+       } else if (reg == vline_start_end[0]) {
+               header &= ~R600_CP_PACKET0_REG_MASK;
+               header |= vline_start_end[crtc_id] >> 2;
                ib[h_idx] = header;
-               ib[h_idx + 4] = AVIVO_D2MODE_VLINE_STATUS >> 2;
+               ib[h_idx + 4] = vline_status[crtc_id] >> 2;
+       } else {
+               DRM_ERROR("unknown crtc reloc\n");
+               return -EINVAL;
        }
-
        return 0;
 }
 
@@ -1159,8 +1019,8 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                break;
        case R_028010_DB_DEPTH_INFO:
                if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS) &&
-                   r600_cs_packet_next_is_pkt3_nop(p)) {
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                   radeon_cs_packet_next_is_pkt3_nop(p)) {
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                         "0x%04X\n", reg);
@@ -1202,7 +1062,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
        case VGT_STRMOUT_BUFFER_BASE_1:
        case VGT_STRMOUT_BUFFER_BASE_2:
        case VGT_STRMOUT_BUFFER_BASE_3:
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
@@ -1225,7 +1085,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                track->streamout_dirty = true;
                break;
        case CP_COHER_BASE:
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        dev_warn(p->dev, "missing reloc for CP_COHER_BASE "
                                        "0x%04X\n", reg);
@@ -1260,8 +1120,8 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
        case R_0280B8_CB_COLOR6_INFO:
        case R_0280BC_CB_COLOR7_INFO:
                if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS) &&
-                    r600_cs_packet_next_is_pkt3_nop(p)) {
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                    radeon_cs_packet_next_is_pkt3_nop(p)) {
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
                                return -EINVAL;
@@ -1324,7 +1184,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
        case R_0280F8_CB_COLOR6_FRAG:
        case R_0280FC_CB_COLOR7_FRAG:
                tmp = (reg - R_0280E0_CB_COLOR0_FRAG) / 4;
-               if (!r600_cs_packet_next_is_pkt3_nop(p)) {
+               if (!radeon_cs_packet_next_is_pkt3_nop(p)) {
                        if (!track->cb_color_base_last[tmp]) {
                                dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg);
                                return -EINVAL;
@@ -1333,7 +1193,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                        track->cb_color_frag_offset[tmp] = track->cb_color_bo_offset[tmp];
                        ib[idx] = track->cb_color_base_last[tmp];
                } else {
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
                                return -EINVAL;
@@ -1355,7 +1215,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
        case R_0280D8_CB_COLOR6_TILE:
        case R_0280DC_CB_COLOR7_TILE:
                tmp = (reg - R_0280C0_CB_COLOR0_TILE) / 4;
-               if (!r600_cs_packet_next_is_pkt3_nop(p)) {
+               if (!radeon_cs_packet_next_is_pkt3_nop(p)) {
                        if (!track->cb_color_base_last[tmp]) {
                                dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg);
                                return -EINVAL;
@@ -1364,7 +1224,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                        track->cb_color_tile_offset[tmp] = track->cb_color_bo_offset[tmp];
                        ib[idx] = track->cb_color_base_last[tmp];
                } else {
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
                                return -EINVAL;
@@ -1399,7 +1259,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
        case CB_COLOR5_BASE:
        case CB_COLOR6_BASE:
        case CB_COLOR7_BASE:
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
@@ -1414,7 +1274,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                track->cb_dirty = true;
                break;
        case DB_DEPTH_BASE:
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
@@ -1427,7 +1287,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                track->db_dirty = true;
                break;
        case DB_HTILE_DATA_BASE:
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
@@ -1497,7 +1357,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
        case SQ_ALU_CONST_CACHE_VS_13:
        case SQ_ALU_CONST_CACHE_VS_14:
        case SQ_ALU_CONST_CACHE_VS_15:
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
@@ -1506,7 +1366,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
                break;
        case SX_MEMORY_EXPORT_BASE:
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONFIG_REG "
                                        "0x%04X\n", reg);
@@ -1792,7 +1652,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                        return -EINVAL;
                }
 
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        DRM_ERROR("bad SET PREDICATION\n");
                        return -EINVAL;
@@ -1833,7 +1693,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                        DRM_ERROR("bad DRAW_INDEX\n");
                        return -EINVAL;
                }
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        DRM_ERROR("bad DRAW_INDEX\n");
                        return -EINVAL;
@@ -1885,7 +1745,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                if (idx_value & 0x10) {
                        uint64_t offset;
 
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                DRM_ERROR("bad WAIT_REG_MEM\n");
                                return -EINVAL;
@@ -1897,6 +1757,9 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
 
                        ib[idx+1] = (ib[idx+1] & 0x3) | (offset & 0xfffffff0);
                        ib[idx+2] = upper_32_bits(offset) & 0xff;
+               } else if (idx_value & 0x100) {
+                       DRM_ERROR("cannot use PFP on REG wait\n");
+                       return -EINVAL;
                }
                break;
        case PACKET3_CP_DMA:
@@ -1919,7 +1782,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                                return -EINVAL;
                        }
                        /* src address space is memory */
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                DRM_ERROR("bad CP DMA SRC\n");
                                return -EINVAL;
@@ -1949,7 +1812,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                                DRM_ERROR("CP DMA DAIC only supported for registers\n");
                                return -EINVAL;
                        }
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                DRM_ERROR("bad CP DMA DST\n");
                                return -EINVAL;
@@ -1979,7 +1842,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                /* 0xffffffff/0x0 is flush all cache flag */
                if (radeon_get_ib_value(p, idx + 1) != 0xffffffff ||
                    radeon_get_ib_value(p, idx + 2) != 0) {
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                DRM_ERROR("bad SURFACE_SYNC\n");
                                return -EINVAL;
@@ -1995,7 +1858,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                if (pkt->count) {
                        uint64_t offset;
 
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                DRM_ERROR("bad EVENT_WRITE\n");
                                return -EINVAL;
@@ -2016,7 +1879,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                        DRM_ERROR("bad EVENT_WRITE_EOP\n");
                        return -EINVAL;
                }
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        DRM_ERROR("bad EVENT_WRITE\n");
                        return -EINVAL;
@@ -2082,7 +1945,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                        switch (G__SQ_VTX_CONSTANT_TYPE(radeon_get_ib_value(p, idx+(i*7)+6+1))) {
                        case SQ_TEX_VTX_VALID_TEXTURE:
                                /* tex base */
-                               r = r600_cs_packet_next_reloc(p, &reloc);
+                               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                                if (r) {
                                        DRM_ERROR("bad SET_RESOURCE\n");
                                        return -EINVAL;
@@ -2096,7 +1959,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                                }
                                texture = reloc->robj;
                                /* tex mip base */
-                               r = r600_cs_packet_next_reloc(p, &reloc);
+                               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                                if (r) {
                                        DRM_ERROR("bad SET_RESOURCE\n");
                                        return -EINVAL;
@@ -2117,7 +1980,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                        {
                                uint64_t offset64;
                                /* vtx base */
-                               r = r600_cs_packet_next_reloc(p, &reloc);
+                               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                                if (r) {
                                        DRM_ERROR("bad SET_RESOURCE\n");
                                        return -EINVAL;
@@ -2218,7 +2081,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                {
                        u64 offset;
 
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                DRM_ERROR("bad STRMOUT_BASE_UPDATE reloc\n");
                                return -EINVAL;
@@ -2262,7 +2125,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                /* Updating memory at DST_ADDRESS. */
                if (idx_value & 0x1) {
                        u64 offset;
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing dst reloc)\n");
                                return -EINVAL;
@@ -2281,7 +2144,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                /* Reading data from SRC_ADDRESS. */
                if (((idx_value >> 1) & 0x3) == 2) {
                        u64 offset;
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing src reloc)\n");
                                return -EINVAL;
@@ -2306,7 +2169,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                        DRM_ERROR("bad MEM_WRITE (invalid count)\n");
                        return -EINVAL;
                }
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        DRM_ERROR("bad MEM_WRITE (missing reloc)\n");
                        return -EINVAL;
@@ -2335,7 +2198,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                if (idx_value & 0x1) {
                        u64 offset;
                        /* SRC is memory. */
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                DRM_ERROR("bad COPY_DW (missing src reloc)\n");
                                return -EINVAL;
@@ -2359,7 +2222,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                if (idx_value & 0x2) {
                        u64 offset;
                        /* DST is memory. */
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                DRM_ERROR("bad COPY_DW (missing dst reloc)\n");
                                return -EINVAL;
@@ -2415,7 +2278,7 @@ int r600_cs_parse(struct radeon_cs_parser *p)
                p->track = track;
        }
        do {
-               r = r600_cs_packet_parse(p, &pkt, p->idx);
+               r = radeon_cs_packet_parse(p, &pkt, p->idx);
                if (r) {
                        drm_free(p->track, M_DRM);
                        p->track = NULL;
@@ -2423,12 +2286,12 @@ int r600_cs_parse(struct radeon_cs_parser *p)
                }
                p->idx += pkt.count + 2;
                switch (pkt.type) {
-               case PACKET_TYPE0:
+               case RADEON_PACKET_TYPE0:
                        r = r600_cs_parse_packet0(p, &pkt);
                        break;
-               case PACKET_TYPE2:
+               case RADEON_PACKET_TYPE2:
                        break;
-               case PACKET_TYPE3:
+               case RADEON_PACKET_TYPE3:
                        r = r600_packet3_check(p, &pkt);
                        break;
                default:
@@ -2454,18 +2317,7 @@ int r600_cs_parse(struct radeon_cs_parser *p)
        return 0;
 }
 
-static int r600_cs_parser_relocs_legacy(struct radeon_cs_parser *p)
-{
-       if (p->chunk_relocs_idx == -1) {
-               return 0;
-       }
-       p->relocs = kmalloc(sizeof(struct radeon_cs_reloc), M_DRM,
-                           M_ZERO | M_WAITOK);
-       if (p->relocs == NULL) {
-               return -ENOMEM;
-       }
-       return 0;
-}
+#ifdef CONFIG_DRM_RADEON_UMS
 
 /**
  * cs_parser_fini() - clean parser states
@@ -2492,6 +2344,18 @@ static void r600_cs_parser_fini(struct radeon_cs_parser *parser, int error)
        drm_free(parser->track, M_DRM);
 }
 
+static int r600_cs_parser_relocs_legacy(struct radeon_cs_parser *p)
+{
+       if (p->chunk_relocs_idx == -1) {
+               return 0;
+       }
+       p->relocs = kzalloc(sizeof(struct radeon_cs_reloc), GFP_KERNEL);
+       if (p->relocs == NULL) {
+               return -ENOMEM;
+       }
+       return 0;
+}
+
 int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp,
                        unsigned family, u32 *ib, int *l)
 {
@@ -2550,9 +2414,11 @@ int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp,
 
 void r600_cs_legacy_init(void)
 {
-       r600_cs_packet_next_reloc = &r600_cs_packet_next_reloc_nomm;
+       r600_nomm = 1;
 }
 
+#endif
+
 /*
  *  DMA
  */
index 839d33f..e2fa18f 100644 (file)
@@ -26,6 +26,7 @@
  * $FreeBSD: head/sys/dev/drm2/radeon/r600_hdmi.c 254885 2013-08-25 19:37:15Z dumbbell $
  */
 
+#include <linux/hdmi.h>
 #include <drm/drmP.h>
 #include <uapi_drm/radeon_drm.h>
 #include "radeon.h"
@@ -123,80 +124,19 @@ static void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock)
        WREG32(HDMI0_ACR_48_1 + offset, acr.n_48khz);
 }
 
-/*
- * calculate the crc for a given info frame
- */
-static void r600_hdmi_infoframe_checksum(uint8_t packetType,
-                                        uint8_t versionNumber,
-                                        uint8_t length,
-                                        uint8_t *frame)
-{
-       int i;
-       frame[0] = packetType + versionNumber + length;
-       for (i = 1; i <= length; i++)
-               frame[0] += frame[i];
-       frame[0] = 0x100 - frame[0];
-}
-
 /*
  * build a HDMI Video Info Frame
  */
-static void r600_hdmi_videoinfoframe(
-&