]> Pileus Git - ~andy/linux/commitdiff
Merge tag 'drm-intel-fixes-2013-08-08' of git://people.freedesktop.org/~danvet/drm...
authorDave Airlie <airlied@redhat.com>
Thu, 8 Aug 2013 23:09:37 +0000 (09:09 +1000)
committerDave Airlie <airlied@redhat.com>
Thu, 8 Aug 2013 23:09:37 +0000 (09:09 +1000)
Daniel writes:
A few bugfixes for serious stuff and regressions. Highlight is the
reinstated hack to keep the i915 backlight on when running on an optimus
machine, this prevents black screens especially with some radeon muxed
platforms. And the patch to quiet dmesg on Linus' old mac mini ;-)

* tag 'drm-intel-fixes-2013-08-08' of git://people.freedesktop.org/~danvet/drm-intel:
  drm/i915: do not disable backlight on vgaswitcheroo switch off
  drm/i915: Don't call encoder's get_config unless encoder is active
  drm/i915: avoid brightness overflow when doing scale
  drm/i915: update last_vblank when disabling the power well
  drm/i915: fix gen4 digital port hotplug definitions

28 files changed:
drivers/gpu/drm/ast/ast_ttm.c
drivers/gpu/drm/cirrus/cirrus_ttm.c
drivers/gpu/drm/drm_irq.c
drivers/gpu/drm/mgag200/mgag200_ttm.c
drivers/gpu/drm/radeon/btc_dpm.c
drivers/gpu/drm/radeon/cik.c
drivers/gpu/drm/radeon/cypress_dpm.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreen_hdmi.c
drivers/gpu/drm/radeon/evergreend.h
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/ni_dpm.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/r600_hdmi.c
drivers/gpu/drm/radeon/r600d.h
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_asic.h
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_fence.c
drivers/gpu/drm/radeon/radeon_gart.c
drivers/gpu/drm/radeon/radeon_pm.c
drivers/gpu/drm/radeon/radeon_uvd.c
drivers/gpu/drm/radeon/rv6xx_dpm.c
drivers/gpu/drm/radeon/rv770.c
drivers/gpu/drm/radeon/rv770_dpm.c
drivers/gpu/drm/radeon/rv770_dpm.h
drivers/gpu/drm/radeon/si.c
drivers/gpu/drm/radeon/si_dpm.c

index 98d670825a1a115a43fd5c6d49bd494ce839c94b..6e8887fe6c1b44fb83d09df82d10d50483924de5 100644 (file)
@@ -323,6 +323,7 @@ int ast_bo_create(struct drm_device *dev, int size, int align,
 
        astbo->gem.driver_private = NULL;
        astbo->bo.bdev = &ast->ttm.bdev;
+       astbo->bo.bdev->dev_mapping = dev->dev_mapping;
 
        ast_ttm_placement(astbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM);
 
index 0047012045c27cff7cfa8dbd386ca239d850e4be..69fd8f1ac8df192729c89f4dd981a5bb5b7611db 100644 (file)
@@ -328,6 +328,7 @@ int cirrus_bo_create(struct drm_device *dev, int size, int align,
 
        cirrusbo->gem.driver_private = NULL;
        cirrusbo->bo.bdev = &cirrus->ttm.bdev;
+       cirrusbo->bo.bdev->dev_mapping = dev->dev_mapping;
 
        cirrus_ttm_placement(cirrusbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM);
 
index 8bcce7866d368e12df7c86edb17ff235ba58f4a7..f92da0a32f0d30d02fe8afeb09f5272a16b8a060 100644 (file)
@@ -708,7 +708,10 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
        /* Subtract time delta from raw timestamp to get final
         * vblank_time timestamp for end of vblank.
         */
-       etime = ktime_sub_ns(etime, delta_ns);
+       if (delta_ns < 0)
+               etime = ktime_add_ns(etime, -delta_ns);
+       else
+               etime = ktime_sub_ns(etime, delta_ns);
        *vblank_time = ktime_to_timeval(etime);
 
        DRM_DEBUG("crtc %d : v %d p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n",
index 13878d5de063f4b08b97ee2f5735dc2e3e7cb37b..d70e4a92773bfda96079b1406ffffa9a2f65a0e7 100644 (file)
@@ -323,6 +323,7 @@ int mgag200_bo_create(struct drm_device *dev, int size, int align,
 
        mgabo->gem.driver_private = NULL;
        mgabo->bo.bdev = &mdev->ttm.bdev;
+       mgabo->bo.bdev->dev_mapping = dev->dev_mapping;
 
        mgag200_ttm_placement(mgabo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM);
 
index 0bfd55e088201d79e3499b8c98585895f2c736c8..9953e1fbc46d74e53adf50eab2eb05e602287f54 100644 (file)
@@ -2548,9 +2548,6 @@ int btc_dpm_init(struct radeon_device *rdev)
 {
        struct rv7xx_power_info *pi;
        struct evergreen_power_info *eg_pi;
-       int index = GetIndexIntoMasterTable(DATA, ASIC_InternalSS_Info);
-       u16 data_offset, size;
-       u8 frev, crev;
        struct atom_clock_dividers dividers;
        int ret;
 
@@ -2633,16 +2630,7 @@ int btc_dpm_init(struct radeon_device *rdev)
        eg_pi->vddci_control =
                radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDCI, 0);
 
-       if (atom_parse_data_header(rdev->mode_info.atom_context, index, &size,
-                                   &frev, &crev, &data_offset)) {
-               pi->sclk_ss = true;
-               pi->mclk_ss = true;
-               pi->dynamic_ss = true;
-       } else {
-               pi->sclk_ss = false;
-               pi->mclk_ss = false;
-               pi->dynamic_ss = true;
-       }
+       rv770_get_engine_memory_ss(rdev);
 
        pi->asi = RV770_ASI_DFLT;
        pi->pasi = CYPRESS_HASI_DFLT;
@@ -2659,8 +2647,7 @@ int btc_dpm_init(struct radeon_device *rdev)
 
        pi->dynamic_pcie_gen2 = true;
 
-       if (pi->gfx_clock_gating &&
-           (rdev->pm.int_thermal_type != THERMAL_TYPE_NONE))
+       if (rdev->pm.int_thermal_type != THERMAL_TYPE_NONE)
                pi->thermal_protection = true;
        else
                pi->thermal_protection = false;
index 6dacec4e20901bd1f12e428a387434a8db8a91a8..8928bd109c1647b684293cb49ed91198419eb33c 100644 (file)
@@ -2587,9 +2587,11 @@ u32 cik_compute_ring_get_rptr(struct radeon_device *rdev,
        if (rdev->wb.enabled) {
                rptr = le32_to_cpu(rdev->wb.wb[ring->rptr_offs/4]);
        } else {
+               mutex_lock(&rdev->srbm_mutex);
                cik_srbm_select(rdev, ring->me, ring->pipe, ring->queue, 0);
                rptr = RREG32(CP_HQD_PQ_RPTR);
                cik_srbm_select(rdev, 0, 0, 0, 0);
+               mutex_unlock(&rdev->srbm_mutex);
        }
        rptr = (rptr & ring->ptr_reg_mask) >> ring->ptr_reg_shift;
 
@@ -2604,9 +2606,11 @@ u32 cik_compute_ring_get_wptr(struct radeon_device *rdev,
        if (rdev->wb.enabled) {
                wptr = le32_to_cpu(rdev->wb.wb[ring->wptr_offs/4]);
        } else {
+               mutex_lock(&rdev->srbm_mutex);
                cik_srbm_select(rdev, ring->me, ring->pipe, ring->queue, 0);
                wptr = RREG32(CP_HQD_PQ_WPTR);
                cik_srbm_select(rdev, 0, 0, 0, 0);
+               mutex_unlock(&rdev->srbm_mutex);
        }
        wptr = (wptr & ring->ptr_reg_mask) >> ring->ptr_reg_shift;
 
@@ -2897,6 +2901,7 @@ static int cik_cp_compute_resume(struct radeon_device *rdev)
        WREG32(CP_CPF_DEBUG, tmp);
 
        /* init the pipes */
+       mutex_lock(&rdev->srbm_mutex);
        for (i = 0; i < (rdev->mec.num_pipe * rdev->mec.num_mec); i++) {
                int me = (i < 4) ? 1 : 2;
                int pipe = (i < 4) ? i : (i - 4);
@@ -2919,6 +2924,7 @@ static int cik_cp_compute_resume(struct radeon_device *rdev)
                WREG32(CP_HPD_EOP_CONTROL, tmp);
        }
        cik_srbm_select(rdev, 0, 0, 0, 0);
+       mutex_unlock(&rdev->srbm_mutex);
 
        /* init the queues.  Just two for now. */
        for (i = 0; i < 2; i++) {
@@ -2972,6 +2978,7 @@ static int cik_cp_compute_resume(struct radeon_device *rdev)
                mqd->static_thread_mgmt23[0] = 0xffffffff;
                mqd->static_thread_mgmt23[1] = 0xffffffff;
 
+               mutex_lock(&rdev->srbm_mutex);
                cik_srbm_select(rdev, rdev->ring[idx].me,
                                rdev->ring[idx].pipe,
                                rdev->ring[idx].queue, 0);
@@ -3099,6 +3106,7 @@ static int cik_cp_compute_resume(struct radeon_device *rdev)
                WREG32(CP_HQD_ACTIVE, mqd->queue_state.cp_hqd_active);
 
                cik_srbm_select(rdev, 0, 0, 0, 0);
+               mutex_unlock(&rdev->srbm_mutex);
 
                radeon_bo_kunmap(rdev->ring[idx].mqd_obj);
                radeon_bo_unreserve(rdev->ring[idx].mqd_obj);
@@ -4320,6 +4328,7 @@ static int cik_pcie_gart_enable(struct radeon_device *rdev)
 
        /* XXX SH_MEM regs */
        /* where to put LDS, scratch, GPUVM in FSA64 space */
+       mutex_lock(&rdev->srbm_mutex);
        for (i = 0; i < 16; i++) {
                cik_srbm_select(rdev, 0, 0, 0, i);
                /* CP and shaders */
@@ -4335,6 +4344,7 @@ static int cik_pcie_gart_enable(struct radeon_device *rdev)
                /* XXX SDMA RLC - todo */
        }
        cik_srbm_select(rdev, 0, 0, 0, 0);
+       mutex_unlock(&rdev->srbm_mutex);
 
        cik_pcie_gart_tlb_flush(rdev);
        DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
@@ -5954,6 +5964,8 @@ static int cik_startup(struct radeon_device *rdev)
        struct radeon_ring *ring;
        int r;
 
+       cik_mc_program(rdev);
+
        if (rdev->flags & RADEON_IS_IGP) {
                if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw ||
                    !rdev->mec_fw || !rdev->sdma_fw || !rdev->rlc_fw) {
@@ -5985,7 +5997,6 @@ static int cik_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
-       cik_mc_program(rdev);
        r = cik_pcie_gart_enable(rdev);
        if (r)
                return r;
@@ -6194,7 +6205,7 @@ int cik_suspend(struct radeon_device *rdev)
        radeon_vm_manager_fini(rdev);
        cik_cp_enable(rdev, false);
        cik_sdma_enable(rdev, false);
-       r600_uvd_rbc_stop(rdev);
+       r600_uvd_stop(rdev);
        radeon_uvd_suspend(rdev);
        cik_irq_suspend(rdev);
        radeon_wb_disable(rdev);
@@ -6358,6 +6369,7 @@ void cik_fini(struct radeon_device *rdev)
        radeon_vm_manager_fini(rdev);
        radeon_ib_pool_fini(rdev);
        radeon_irq_kms_fini(rdev);
+       r600_uvd_stop(rdev);
        radeon_uvd_fini(rdev);
        cik_pcie_gart_fini(rdev);
        r600_vram_scratch_fini(rdev);
@@ -6978,7 +6990,7 @@ int cik_uvd_resume(struct radeon_device *rdev)
 
        /* programm the VCPU memory controller bits 0-27 */
        addr = rdev->uvd.gpu_addr >> 3;
-       size = RADEON_GPU_PAGE_ALIGN(rdev->uvd.fw_size + 4) >> 3;
+       size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 4) >> 3;
        WREG32(UVD_VCPU_CACHE_OFFSET0, addr);
        WREG32(UVD_VCPU_CACHE_SIZE0, size);
 
index 9bcdd174780f2a8ec618cf255ad2c37690a2237f..7e5d0b570a30531a8752e6b4f29bb732528bb7fe 100644 (file)
@@ -2038,9 +2038,6 @@ int cypress_dpm_init(struct radeon_device *rdev)
 {
        struct rv7xx_power_info *pi;
        struct evergreen_power_info *eg_pi;
-       int index = GetIndexIntoMasterTable(DATA, ASIC_InternalSS_Info);
-       uint16_t data_offset, size;
-       uint8_t frev, crev;
        struct atom_clock_dividers dividers;
        int ret;
 
@@ -2092,16 +2089,7 @@ int cypress_dpm_init(struct radeon_device *rdev)
        eg_pi->vddci_control =
                radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDCI, 0);
 
-       if (atom_parse_data_header(rdev->mode_info.atom_context, index, &size,
-                                   &frev, &crev, &data_offset)) {
-               pi->sclk_ss = true;
-               pi->mclk_ss = true;
-               pi->dynamic_ss = true;
-       } else {
-               pi->sclk_ss = false;
-               pi->mclk_ss = false;
-               pi->dynamic_ss = true;
-       }
+       rv770_get_engine_memory_ss(rdev);
 
        pi->asi = RV770_ASI_DFLT;
        pi->pasi = CYPRESS_HASI_DFLT;
@@ -2122,8 +2110,7 @@ int cypress_dpm_init(struct radeon_device *rdev)
 
        pi->dynamic_pcie_gen2 = true;
 
-       if (pi->gfx_clock_gating &&
-           (rdev->pm.int_thermal_type != THERMAL_TYPE_NONE))
+       if (rdev->pm.int_thermal_type != THERMAL_TYPE_NONE)
                pi->thermal_protection = true;
        else
                pi->thermal_protection = false;
index 038dcac7670cf540950d4ce64a26830da6325e0d..d5b49e33315e299aa4b2a2085d0fdd3d1c8a99bc 100644 (file)
@@ -5106,6 +5106,8 @@ static int evergreen_startup(struct radeon_device *rdev)
        /* enable aspm */
        evergreen_program_aspm(rdev);
 
+       evergreen_mc_program(rdev);
+
        if (ASIC_IS_DCE5(rdev)) {
                if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) {
                        r = ni_init_microcode(rdev);
@@ -5133,7 +5135,6 @@ static int evergreen_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
-       evergreen_mc_program(rdev);
        if (rdev->flags & RADEON_IS_AGP) {
                evergreen_agp_enable(rdev);
        } else {
@@ -5291,10 +5292,10 @@ int evergreen_resume(struct radeon_device *rdev)
 int evergreen_suspend(struct radeon_device *rdev)
 {
        r600_audio_fini(rdev);
+       r600_uvd_stop(rdev);
        radeon_uvd_suspend(rdev);
        r700_cp_stop(rdev);
        r600_dma_stop(rdev);
-       r600_uvd_rbc_stop(rdev);
        evergreen_irq_suspend(rdev);
        radeon_wb_disable(rdev);
        evergreen_pcie_gart_disable(rdev);
@@ -5429,6 +5430,7 @@ void evergreen_fini(struct radeon_device *rdev)
        radeon_ib_pool_fini(rdev);
        radeon_irq_kms_fini(rdev);
        evergreen_pcie_gart_fini(rdev);
+       r600_uvd_stop(rdev);
        radeon_uvd_fini(rdev);
        r600_vram_scratch_fini(rdev);
        radeon_gem_fini(rdev);
index bb9ea3641312af1a8da0aff84486a124c629704a..b0e280058b9b09ea22eb75f5c13ab6395e1698ba 100644 (file)
@@ -148,18 +148,40 @@ static void evergreen_audio_set_dto(struct drm_encoder *encoder, u32 clock)
        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
        struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
        u32 base_rate = 24000;
+       u32 max_ratio = clock / base_rate;
+       u32 dto_phase;
+       u32 dto_modulo = clock;
+       u32 wallclock_ratio;
+       u32 dto_cntl;
 
        if (!dig || !dig->afmt)
                return;
 
+       if (max_ratio >= 8) {
+               dto_phase = 192 * 1000;
+               wallclock_ratio = 3;
+       } else if (max_ratio >= 4) {
+               dto_phase = 96 * 1000;
+               wallclock_ratio = 2;
+       } else if (max_ratio >= 2) {
+               dto_phase = 48 * 1000;
+               wallclock_ratio = 1;
+       } else {
+               dto_phase = 24 * 1000;
+               wallclock_ratio = 0;
+       }
+       dto_cntl = RREG32(DCCG_AUDIO_DTO0_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK;
+       dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio);
+       WREG32(DCCG_AUDIO_DTO0_CNTL, dto_cntl);
+
        /* XXX two dtos; generally use dto0 for hdmi */
        /* Express [24MHz / target pixel clock] as an exact rational
         * number (coefficient of two integer numbers.  DCCG_AUDIO_DTOx_PHASE
         * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
         */
        WREG32(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL(radeon_crtc->crtc_id));
-       WREG32(DCCG_AUDIO_DTO0_PHASE, base_rate * 100);
-       WREG32(DCCG_AUDIO_DTO0_MODULE, clock * 100);
+       WREG32(DCCG_AUDIO_DTO0_PHASE, dto_phase);
+       WREG32(DCCG_AUDIO_DTO0_MODULE, dto_modulo);
 }
 
 
index a7baf67aef6cae99eacdd958b1aa00e2fd925841..0d582ac1dc31841b0844df7cfe4b186bd7b6da0e 100644 (file)
 #define DCCG_AUDIO_DTO0_MODULE            0x05b4
 #define DCCG_AUDIO_DTO0_LOAD              0x05b8
 #define DCCG_AUDIO_DTO0_CNTL              0x05bc
+#       define DCCG_AUDIO_DTO_WALLCLOCK_RATIO(x) (((x) & 7) << 0)
+#       define DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK 7
+#       define DCCG_AUDIO_DTO_WALLCLOCK_RATIO_SHIFT 0
 
 #define DCCG_AUDIO_DTO1_PHASE             0x05c0
 #define DCCG_AUDIO_DTO1_MODULE            0x05c4
index 56bd4f3be4febfe75522deb222a0218c7792b248..ccb4f8b548524b46900f6d88444179c9f6a3069f 100644 (file)
@@ -794,9 +794,13 @@ int ni_init_microcode(struct radeon_device *rdev)
        if ((rdev->family >= CHIP_BARTS) && (rdev->family <= CHIP_CAYMAN)) {
                snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", chip_name);
                err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev);
-               if (err)
-                       goto out;
-               if (rdev->smc_fw->size != smc_req_size) {
+               if (err) {
+                       printk(KERN_ERR
+                              "smc: error loading firmware \"%s\"\n",
+                              fw_name);
+                       release_firmware(rdev->smc_fw);
+                       rdev->smc_fw = NULL;
+               } else if (rdev->smc_fw->size != smc_req_size) {
                        printk(KERN_ERR
                               "ni_mc: Bogus length %zu in firmware \"%s\"\n",
                               rdev->mc_fw->size, fw_name);
@@ -2079,6 +2083,8 @@ static int cayman_startup(struct radeon_device *rdev)
        /* enable aspm */
        evergreen_program_aspm(rdev);
 
+       evergreen_mc_program(rdev);
+
        if (rdev->flags & RADEON_IS_IGP) {
                if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
                        r = ni_init_microcode(rdev);
@@ -2107,7 +2113,6 @@ static int cayman_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
-       evergreen_mc_program(rdev);
        r = cayman_pcie_gart_enable(rdev);
        if (r)
                return r;
@@ -2286,7 +2291,7 @@ int cayman_suspend(struct radeon_device *rdev)
        radeon_vm_manager_fini(rdev);
        cayman_cp_enable(rdev, false);
        cayman_dma_stop(rdev);
-       r600_uvd_rbc_stop(rdev);
+       r600_uvd_stop(rdev);
        radeon_uvd_suspend(rdev);
        evergreen_irq_suspend(rdev);
        radeon_wb_disable(rdev);
@@ -2418,6 +2423,7 @@ void cayman_fini(struct radeon_device *rdev)
        radeon_vm_manager_fini(rdev);
        radeon_ib_pool_fini(rdev);
        radeon_irq_kms_fini(rdev);
+       r600_uvd_stop(rdev);
        radeon_uvd_fini(rdev);
        cayman_pcie_gart_fini(rdev);
        r600_vram_scratch_fini(rdev);
index 4f9b9bc20daaccde2911de65882c5a9c32d23f15..f0f5f748938ad6c30292d2b109bef4c3a2f8fc29 100644 (file)
@@ -4067,9 +4067,6 @@ int ni_dpm_init(struct radeon_device *rdev)
        struct rv7xx_power_info *pi;
        struct evergreen_power_info *eg_pi;
        struct ni_power_info *ni_pi;
-       int index = GetIndexIntoMasterTable(DATA, ASIC_InternalSS_Info);
-       u16 data_offset, size;
-       u8 frev, crev;
        struct atom_clock_dividers dividers;
        int ret;
 
@@ -4162,16 +4159,7 @@ int ni_dpm_init(struct radeon_device *rdev)
        eg_pi->vddci_control =
                radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDCI, 0);
 
-       if (atom_parse_data_header(rdev->mode_info.atom_context, index, &size,
-                                   &frev, &crev, &data_offset)) {
-               pi->sclk_ss = true;
-               pi->mclk_ss = true;
-               pi->dynamic_ss = true;
-       } else {
-               pi->sclk_ss = false;
-               pi->mclk_ss = false;
-               pi->dynamic_ss = true;
-       }
+       rv770_get_engine_memory_ss(rdev);
 
        pi->asi = RV770_ASI_DFLT;
        pi->pasi = CYPRESS_HASI_DFLT;
@@ -4188,8 +4176,7 @@ int ni_dpm_init(struct radeon_device *rdev)
 
        pi->dynamic_pcie_gen2 = true;
 
-       if (pi->gfx_clock_gating &&
-           (rdev->pm.int_thermal_type != THERMAL_TYPE_NONE))
+       if (rdev->pm.int_thermal_type != THERMAL_TYPE_NONE)
                pi->thermal_protection = true;
        else
                pi->thermal_protection = false;
index 10f712e37003030e81a7770e94ca696c4c8f2c08..e66e7207735036e2ffab5e18f37854384595bf80 100644 (file)
@@ -2299,9 +2299,13 @@ int r600_init_microcode(struct radeon_device *rdev)
        if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_HEMLOCK)) {
                snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", smc_chip_name);
                err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev);
-               if (err)
-                       goto out;
-               if (rdev->smc_fw->size != smc_req_size) {
+               if (err) {
+                       printk(KERN_ERR
+                              "smc: error loading firmware \"%s\"\n",
+                              fw_name);
+                       release_firmware(rdev->smc_fw);
+                       rdev->smc_fw = NULL;
+               } else if (rdev->smc_fw->size != smc_req_size) {
                        printk(KERN_ERR
                               "smc: Bogus length %zu in firmware \"%s\"\n",
                               rdev->smc_fw->size, fw_name);
@@ -2697,12 +2701,29 @@ int r600_uvd_rbc_start(struct radeon_device *rdev)
        return 0;
 }
 
-void r600_uvd_rbc_stop(struct radeon_device *rdev)
+void r600_uvd_stop(struct radeon_device *rdev)
 {
        struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
 
        /* force RBC into idle state */
        WREG32(UVD_RBC_RB_CNTL, 0x11010101);
+
+       /* Stall UMC and register bus before resetting VCPU */
+       WREG32_P(UVD_LMI_CTRL2, 1 << 8, ~(1 << 8));
+       WREG32_P(UVD_RB_ARB_CTRL, 1 << 3, ~(1 << 3));
+       mdelay(1);
+
+       /* put VCPU into reset */
+       WREG32(UVD_SOFT_RESET, VCPU_SOFT_RESET);
+       mdelay(5);
+
+       /* disable VCPU clock */
+       WREG32(UVD_VCPU_CNTL, 0x0);
+
+       /* Unstall UMC and register bus */
+       WREG32_P(UVD_LMI_CTRL2, 0, ~(1 << 8));
+       WREG32_P(UVD_RB_ARB_CTRL, 0, ~(1 << 3));
+
        ring->ready = false;
 }
 
@@ -2722,6 +2743,11 @@ int r600_uvd_init(struct radeon_device *rdev)
        /* disable interupt */
        WREG32_P(UVD_MASTINT_EN, 0, ~(1 << 1));
 
+       /* Stall UMC and register bus before resetting VCPU */
+       WREG32_P(UVD_LMI_CTRL2, 1 << 8, ~(1 << 8));
+       WREG32_P(UVD_RB_ARB_CTRL, 1 << 3, ~(1 << 3));
+       mdelay(1);
+
        /* put LMI, VCPU, RBC etc... into reset */
        WREG32(UVD_SOFT_RESET, LMI_SOFT_RESET | VCPU_SOFT_RESET |
               LBSI_SOFT_RESET | RBC_SOFT_RESET | CSM_SOFT_RESET |
@@ -2751,10 +2777,6 @@ int r600_uvd_init(struct radeon_device *rdev)
        WREG32(UVD_MPC_SET_ALU, 0);
        WREG32(UVD_MPC_SET_MUX, 0x88);
 
-       /* Stall UMC */
-       WREG32_P(UVD_LMI_CTRL2, 1 << 8, ~(1 << 8));
-       WREG32_P(UVD_RB_ARB_CTRL, 1 << 3, ~(1 << 3));
-
        /* take all subblocks out of reset, except VCPU */
        WREG32(UVD_SOFT_RESET, VCPU_SOFT_RESET);
        mdelay(5);
@@ -3312,6 +3334,8 @@ static int r600_startup(struct radeon_device *rdev)
        /* enable pcie gen2 link */
        r600_pcie_gen2_enable(rdev);
 
+       r600_mc_program(rdev);
+
        if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
                r = r600_init_microcode(rdev);
                if (r) {
@@ -3324,7 +3348,6 @@ static int r600_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
-       r600_mc_program(rdev);
        if (rdev->flags & RADEON_IS_AGP) {
                r600_agp_enable(rdev);
        } else {
index f48240bb8c5640badff804e97dce556e31f86bd9..f264df5470f7fd6bd0ba0cabf3d31e7396829c2b 100644 (file)
@@ -226,10 +226,29 @@ void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
        u32 base_rate = 24000;
+       u32 max_ratio = clock / base_rate;
+       u32 dto_phase;
+       u32 dto_modulo = clock;
+       u32 wallclock_ratio;
+       u32 dto_cntl;
 
        if (!dig || !dig->afmt)
                return;
 
+       if (max_ratio >= 8) {
+               dto_phase = 192 * 1000;
+               wallclock_ratio = 3;
+       } else if (max_ratio >= 4) {
+               dto_phase = 96 * 1000;
+               wallclock_ratio = 2;
+       } else if (max_ratio >= 2) {
+               dto_phase = 48 * 1000;
+               wallclock_ratio = 1;
+       } else {
+               dto_phase = 24 * 1000;
+               wallclock_ratio = 0;
+       }
+
        /* there are two DTOs selected by DCCG_AUDIO_DTO_SELECT.
         * doesn't matter which one you use.  Just use the first one.
         */
@@ -242,9 +261,21 @@ void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
                /* according to the reg specs, this should DCE3.2 only, but in
                 * practice it seems to cover DCE3.0 as well.
                 */
-               WREG32(DCCG_AUDIO_DTO0_PHASE, base_rate * 100);
-               WREG32(DCCG_AUDIO_DTO0_MODULE, clock * 100);
-               WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */
+               if (dig->dig_encoder == 0) {
+                       dto_cntl = RREG32(DCCG_AUDIO_DTO0_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK;
+                       dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio);
+                       WREG32(DCCG_AUDIO_DTO0_CNTL, dto_cntl);
+                       WREG32(DCCG_AUDIO_DTO0_PHASE, dto_phase);
+                       WREG32(DCCG_AUDIO_DTO0_MODULE, dto_modulo);
+                       WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */
+               } else {
+                       dto_cntl = RREG32(DCCG_AUDIO_DTO1_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK;
+                       dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio);
+                       WREG32(DCCG_AUDIO_DTO1_CNTL, dto_cntl);
+                       WREG32(DCCG_AUDIO_DTO1_PHASE, dto_phase);
+                       WREG32(DCCG_AUDIO_DTO1_MODULE, dto_modulo);
+                       WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */
+               }
        } else {
                /* according to the reg specs, this should be DCE2.0 and DCE3.0 */
                WREG32(AUDIO_DTO, AUDIO_DTO_PHASE(base_rate / 10) |
index 8e3fe815edab3224492e126bf7e47d5193be448f..7c780839a7f43858395bdb4ec309bc6a9b1e37fd 100644 (file)
 #define DCCG_AUDIO_DTO0_LOAD              0x051c
 #       define DTO_LOAD                   (1 << 31)
 #define DCCG_AUDIO_DTO0_CNTL              0x0520
+#       define DCCG_AUDIO_DTO_WALLCLOCK_RATIO(x) (((x) & 7) << 0)
+#       define DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK 7
+#       define DCCG_AUDIO_DTO_WALLCLOCK_RATIO_SHIFT 0
 
 #define DCCG_AUDIO_DTO1_PHASE             0x0524
 #define DCCG_AUDIO_DTO1_MODULE            0x0528
index 2f08219c39b617d67ab07f83e7aaff7072bd51b7..274b8e1b889fd0fbbe1dde2a71492e975f00a711 100644 (file)
@@ -1468,7 +1468,6 @@ struct radeon_uvd {
        void                    *cpu_addr;
        uint64_t                gpu_addr;
        void                    *saved_bo;
-       unsigned                fw_size;
        atomic_t                handles[RADEON_MAX_UVD_HANDLES];
        struct drm_file         *filp[RADEON_MAX_UVD_HANDLES];
        struct delayed_work     idle_work;
@@ -2066,6 +2065,7 @@ struct radeon_device {
        const struct firmware *mec_fw;  /* CIK MEC firmware */
        const struct firmware *sdma_fw; /* CIK SDMA firmware */
        const struct firmware *smc_fw;  /* SMC firmware */
+       const struct firmware *uvd_fw;  /* UVD firmware */
        struct r600_blit r600_blit;
        struct r600_vram_scratch vram_scratch;
        int msi_enabled; /* msi enabled */
@@ -2095,6 +2095,8 @@ struct radeon_device {
        /* ACPI interface */
        struct radeon_atif              atif;
        struct radeon_atcs              atcs;
+       /* srbm instance registers */
+       struct mutex                    srbm_mutex;
 };
 
 int radeon_device_init(struct radeon_device *rdev,
index 902479fa737ff62c1b2917b4d0bfce0c34176d74..3d61d5aac18ff4e01d3f89934807d9abb261dcdc 100644 (file)
@@ -441,7 +441,7 @@ void rs780_dpm_debugfs_print_current_performance_level(struct radeon_device *rde
 /* uvd */
 int r600_uvd_init(struct radeon_device *rdev);
 int r600_uvd_rbc_start(struct radeon_device *rdev);
-void r600_uvd_rbc_stop(struct radeon_device *rdev);
+void r600_uvd_stop(struct radeon_device *rdev);
 int r600_uvd_ib_test(struct radeon_device *rdev, struct radeon_ring *ring);
 void r600_uvd_fence_emit(struct radeon_device *rdev,
                         struct radeon_fence *fence);
index 82335e38ec4f268e05f9d4bc1cbd875eae8523a5..63398ae1dbf51fb682fe7e51623de255c58ae0c7 100644 (file)
@@ -1163,6 +1163,7 @@ int radeon_device_init(struct radeon_device *rdev,
        mutex_init(&rdev->gem.mutex);
        mutex_init(&rdev->pm.mutex);
        mutex_init(&rdev->gpu_clock_mutex);
+       mutex_init(&rdev->srbm_mutex);
        init_rwsem(&rdev->pm.mclk_lock);
        init_rwsem(&rdev->exclusive_lock);
        init_waitqueue_head(&rdev->irq.vblank_queue);
@@ -1519,6 +1520,7 @@ int radeon_gpu_reset(struct radeon_device *rdev)
        radeon_save_bios_scratch_regs(rdev);
        /* block TTM */
        resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev);
+       radeon_pm_suspend(rdev);
        radeon_suspend(rdev);
 
        for (i = 0; i < RADEON_NUM_RINGS; ++i) {
@@ -1564,6 +1566,7 @@ retry:
                }
        }
 
+       radeon_pm_resume(rdev);
        drm_helper_resume_force_mode(rdev->ddev);
 
        ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
index 7ddb0efe2408cadc2de230109689a159cdbf0fbd..ddb8f8e04eb549f4fd264b2f704cdd407bcc65e0 100644 (file)
@@ -782,7 +782,7 @@ int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring)
 
                } else {
                        /* put fence directly behind firmware */
-                       index = ALIGN(rdev->uvd.fw_size, 8);
+                       index = ALIGN(rdev->uvd_fw->size, 8);
                        rdev->fence_drv[ring].cpu_addr = rdev->uvd.cpu_addr + index;
                        rdev->fence_drv[ring].gpu_addr = rdev->uvd.gpu_addr + index;
                }
index 6a51d943ccf44d8301758a4b99e3aba35e4c2668..b990b1a2bd50af523e93a7715050a534ba84d987 100644 (file)
@@ -207,7 +207,6 @@ void radeon_gart_table_vram_free(struct radeon_device *rdev)
        if (rdev->gart.robj == NULL) {
                return;
        }
-       radeon_gart_table_vram_unpin(rdev);
        radeon_bo_unref(&rdev->gart.robj);
 }
 
index f374c467aacaf57c9a46c7c655250ef91a44516c..c557850cd3450a5b0f363f24315d3051cb96cf3c 100644 (file)
@@ -1176,7 +1176,14 @@ int radeon_pm_init(struct radeon_device *rdev)
        case CHIP_VERDE:
        case CHIP_OLAND:
        case CHIP_HAINAN:
-               if (radeon_dpm == 1)
+               /* DPM requires the RLC, RV770+ dGPU requires SMC */
+               if (!rdev->rlc_fw)
+                       rdev->pm.pm_method = PM_METHOD_PROFILE;
+               else if ((rdev->family >= CHIP_RV770) &&
+                        (!(rdev->flags & RADEON_IS_IGP)) &&
+                        (!rdev->smc_fw))
+                       rdev->pm.pm_method = PM_METHOD_PROFILE;
+               else if (radeon_dpm == 1)
                        rdev->pm.pm_method = PM_METHOD_DPM;
                else
                        rdev->pm.pm_method = PM_METHOD_PROFILE;
index 414fd145d20eee458ebf8e0a5c1dfb1940ae2589..f1c15754e73ca6d933d6ea1e0877b839cecab4b6 100644 (file)
@@ -56,7 +56,6 @@ static void radeon_uvd_idle_work_handler(struct work_struct *work);
 
 int radeon_uvd_init(struct radeon_device *rdev)
 {
-       const struct firmware *fw;
        unsigned long bo_size;
        const char *fw_name;
        int i, r;
@@ -105,14 +104,14 @@ int radeon_uvd_init(struct radeon_device *rdev)
                return -EINVAL;
        }
 
-       r = request_firmware(&fw, fw_name, rdev->dev);
+       r = request_firmware(&rdev->uvd_fw, fw_name, rdev->dev);
        if (r) {
                dev_err(rdev->dev, "radeon_uvd: Can't load firmware \"%s\"\n",
                        fw_name);
                return r;
        }
 
-       bo_size = RADEON_GPU_PAGE_ALIGN(fw->size + 8) +
+       bo_size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 8) +
                  RADEON_UVD_STACK_SIZE + RADEON_UVD_HEAP_SIZE;
        r = radeon_bo_create(rdev, bo_size, PAGE_SIZE, true,
                             RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->uvd.vcpu_bo);
@@ -145,12 +144,6 @@ int radeon_uvd_init(struct radeon_device *rdev)
 
        radeon_bo_unreserve(rdev->uvd.vcpu_bo);
 
-       rdev->uvd.fw_size = fw->size;
-       memset(rdev->uvd.cpu_addr, 0, bo_size);
-       memcpy(rdev->uvd.cpu_addr, fw->data, fw->size);
-
-       release_firmware(fw);
-
        for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
                atomic_set(&rdev->uvd.handles[i], 0);
                rdev->uvd.filp[i] = NULL;
@@ -174,33 +167,60 @@ void radeon_uvd_fini(struct radeon_device *rdev)
        }
 
        radeon_bo_unref(&rdev->uvd.vcpu_bo);
+
+       release_firmware(rdev->uvd_fw);
 }
 
 int radeon_uvd_suspend(struct radeon_device *rdev)
 {
        unsigned size;
+       void *ptr;
+       int i;
 
        if (rdev->uvd.vcpu_bo == NULL)
                return 0;
 
+       for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i)
+               if (atomic_read(&rdev->uvd.handles[i]))
+                       break;
+
+       if (i == RADEON_MAX_UVD_HANDLES)
+               return 0;
+
        size = radeon_bo_size(rdev->uvd.vcpu_bo);
+       size -= rdev->uvd_fw->size;
+
+       ptr = rdev->uvd.cpu_addr;
+       ptr += rdev->uvd_fw->size;
+
        rdev->uvd.saved_bo = kmalloc(size, GFP_KERNEL);
-       memcpy(rdev->uvd.saved_bo, rdev->uvd.cpu_addr, size);
+       memcpy(rdev->uvd.saved_bo, ptr, size);
 
        return 0;
 }
 
 int radeon_uvd_resume(struct radeon_device *rdev)
 {
+       unsigned size;
+       void *ptr;
+
        if (rdev->uvd.vcpu_bo == NULL)
                return -EINVAL;
 
+       memcpy(rdev->uvd.cpu_addr, rdev->uvd_fw->data, rdev->uvd_fw->size);
+
+       size = radeon_bo_size(rdev->uvd.vcpu_bo);
+       size -= rdev->uvd_fw->size;
+
+       ptr = rdev->uvd.cpu_addr;
+       ptr += rdev->uvd_fw->size;
+
        if (rdev->uvd.saved_bo != NULL) {
-               unsigned size = radeon_bo_size(rdev->uvd.vcpu_bo);
-               memcpy(rdev->uvd.cpu_addr, rdev->uvd.saved_bo, size);
+               memcpy(ptr, rdev->uvd.saved_bo, size);
                kfree(rdev->uvd.saved_bo);
                rdev->uvd.saved_bo = NULL;
-       }
+       } else
+               memset(ptr, 0, size);
 
        return 0;
 }
@@ -215,8 +235,8 @@ void radeon_uvd_free_handles(struct radeon_device *rdev, struct drm_file *filp)
 {
        int i, r;
        for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
-               if (rdev->uvd.filp[i] == filp) {
-                       uint32_t handle = atomic_read(&rdev->uvd.handles[i]);
+               uint32_t handle = atomic_read(&rdev->uvd.handles[i]);
+               if (handle != 0 && rdev->uvd.filp[i] == filp) {
                        struct radeon_fence *fence;
 
                        r = radeon_uvd_get_destroy_msg(rdev,
@@ -337,8 +357,10 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
        }
 
        r = radeon_bo_kmap(bo, &ptr);
-       if (r)
+       if (r) {
+               DRM_ERROR("Failed mapping the UVD message (%d)!\n", r);
                return r;
+       }
 
        msg = ptr + offset;
 
@@ -364,8 +386,14 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
                radeon_bo_kunmap(bo);
                return 0;
        } else {
-               /* it's a create msg, no special handling needed */
                radeon_bo_kunmap(bo);
+
+               if (msg_type != 0) {
+                       DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type);
+                       return -EINVAL;
+               }
+
+               /* it's a create msg, no special handling needed */
        }
 
        /* create or decode, validate the handle */
@@ -388,7 +416,7 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
 
 static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p,
                               int data0, int data1,
-                              unsigned buf_sizes[])
+                              unsigned buf_sizes[], bool *has_msg_cmd)
 {
        struct radeon_cs_chunk *relocs_chunk;
        struct radeon_cs_reloc *reloc;
@@ -417,7 +445,7 @@ static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p,
 
        if (cmd < 0x4) {
                if ((end - start) < buf_sizes[cmd]) {
-                       DRM_ERROR("buffer to small (%d / %d)!\n",
+                       DRM_ERROR("buffer (%d) to small (%d / %d)!\n", cmd,
                                  (unsigned)(end - start), buf_sizes[cmd]);
                        return -EINVAL;
                }
@@ -442,9 +470,17 @@ static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p,
        }
 
        if (cmd == 0) {
+               if (*has_msg_cmd) {
+                       DRM_ERROR("More than one message in a UVD-IB!\n");
+                       return -EINVAL;
+               }
+               *has_msg_cmd = true;
                r = radeon_uvd_cs_msg(p, reloc->robj, offset, buf_sizes);
                if (r)
                        return r;
+       } else if (!*has_msg_cmd) {
+               DRM_ERROR("Message needed before other commands are send!\n");
+               return -EINVAL;
        }
 
        return 0;
@@ -453,7 +489,8 @@ static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p,
 static int radeon_uvd_cs_reg(struct radeon_cs_parser *p,
                             struct radeon_cs_packet *pkt,
                             int *data0, int *data1,
-                            unsigned buf_sizes[])
+                            unsigned buf_sizes[],
+                            bool *has_msg_cmd)
 {
        int i, r;
 
@@ -467,7 +504,8 @@ static int radeon_uvd_cs_reg(struct radeon_cs_parser *p,
                        *data1 = p->idx;
                        break;
                case UVD_GPCOM_VCPU_CMD:
-                       r = radeon_uvd_cs_reloc(p, *data0, *data1, buf_sizes);
+                       r = radeon_uvd_cs_reloc(p, *data0, *data1,
+                                               buf_sizes, has_msg_cmd);
                        if (r)
                                return r;
                        break;
@@ -488,6 +526,9 @@ int radeon_uvd_cs_parse(struct radeon_cs_parser *p)
        struct radeon_cs_packet pkt;
        int r, data0 = 0, data1 = 0;
 
+       /* does the IB has a msg command */
+       bool has_msg_cmd = false;
+
        /* minimum buffer sizes */
        unsigned buf_sizes[] = {
                [0x00000000]    =       2048,
@@ -514,8 +555,8 @@ int radeon_uvd_cs_parse(struct radeon_cs_parser *p)
                        return r;
                switch (pkt.type) {
                case RADEON_PACKET_TYPE0:
-                       r = radeon_uvd_cs_reg(p, &pkt, &data0,
-                                             &data1, buf_sizes);
+                       r = radeon_uvd_cs_reg(p, &pkt, &data0, &data1,
+                                             buf_sizes, &has_msg_cmd);
                        if (r)
                                return r;
                        break;
@@ -527,6 +568,12 @@ int radeon_uvd_cs_parse(struct radeon_cs_parser *p)
                        return -EINVAL;
                }
        } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
+
+       if (!has_msg_cmd) {
+               DRM_ERROR("UVD-IBs need a msg command!\n");
+               return -EINVAL;
+       }
+
        return 0;
 }
 
index 363018c60412c1d7374ee60a176abe2f5c49dce7..bdd888b4db2bbc7bf4f6f2cc718512fa999e223f 100644 (file)
@@ -1944,9 +1944,7 @@ static int rv6xx_parse_power_table(struct radeon_device *rdev)
 
 int rv6xx_dpm_init(struct radeon_device *rdev)
 {
-       int index = GetIndexIntoMasterTable(DATA, ASIC_InternalSS_Info);
-       uint16_t data_offset, size;
-       uint8_t frev, crev;
+       struct radeon_atom_ss ss;
        struct atom_clock_dividers dividers;
        struct rv6xx_power_info *pi;
        int ret;
@@ -1989,16 +1987,18 @@ int rv6xx_dpm_init(struct radeon_device *rdev)
 
        pi->gfx_clock_gating = true;
 
-       if (atom_parse_data_header(rdev->mode_info.atom_context, index, &size,
-                                   &frev, &crev, &data_offset)) {
-               pi->sclk_ss = true;
-               pi->mclk_ss = true;
+       pi->sclk_ss = radeon_atombios_get_asic_ss_info(rdev, &ss,
+                                                      ASIC_INTERNAL_ENGINE_SS, 0);
+       pi->mclk_ss = radeon_atombios_get_asic_ss_info(rdev, &ss,
+                                                      ASIC_INTERNAL_MEMORY_SS, 0);
+
+       /* Disable sclk ss, causes hangs on a lot of systems */
+       pi->sclk_ss = false;
+
+       if (pi->sclk_ss || pi->mclk_ss)
                pi->dynamic_ss = true;
-       } else {
-               pi->sclk_ss = false;
-               pi->mclk_ss = false;
+       else
                pi->dynamic_ss = false;
-       }
 
        pi->dynamic_pcie_gen2 = true;
 
index 30ea14e8854c465add9148cb4099142a3295fbd0..bcc68ec204adeb7582a536cd3125ab28d00bce6d 100644 (file)
@@ -813,7 +813,7 @@ int rv770_uvd_resume(struct radeon_device *rdev)
 
        /* programm the VCPU memory controller bits 0-27 */
        addr = rdev->uvd.gpu_addr >> 3;
-       size = RADEON_GPU_PAGE_ALIGN(rdev->uvd.fw_size + 4) >> 3;
+       size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 4) >> 3;
        WREG32(UVD_VCPU_CACHE_OFFSET0, addr);
        WREG32(UVD_VCPU_CACHE_SIZE0, size);
 
@@ -1829,6 +1829,8 @@ static int rv770_startup(struct radeon_device *rdev)
        /* enable pcie gen2 link */
        rv770_pcie_gen2_enable(rdev);
 
+       rv770_mc_program(rdev);
+
        if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
                r = r600_init_microcode(rdev);
                if (r) {
@@ -1841,7 +1843,6 @@ static int rv770_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
-       rv770_mc_program(rdev);
        if (rdev->flags & RADEON_IS_AGP) {
                rv770_agp_enable(rdev);
        } else {
@@ -1983,6 +1984,7 @@ int rv770_resume(struct radeon_device *rdev)
 int rv770_suspend(struct radeon_device *rdev)
 {
        r600_audio_fini(rdev);
+       r600_uvd_stop(rdev);
        radeon_uvd_suspend(rdev);
        r700_cp_stop(rdev);
        r600_dma_stop(rdev);
@@ -2098,6 +2100,7 @@ void rv770_fini(struct radeon_device *rdev)
        radeon_ib_pool_fini(rdev);
        radeon_irq_kms_fini(rdev);
        rv770_pcie_gart_fini(rdev);
+       r600_uvd_stop(rdev);
        radeon_uvd_fini(rdev);
        r600_vram_scratch_fini(rdev);
        radeon_gem_fini(rdev);
index 2d347925f77d6d116c95c01cc3045c148ac446b1..094c67a29d0deb7789d6b0d38a1d0a718515b81b 100644 (file)
@@ -2319,12 +2319,25 @@ int rv7xx_parse_power_table(struct radeon_device *rdev)
        return 0;
 }
 
+void rv770_get_engine_memory_ss(struct radeon_device *rdev)
+{
+       struct rv7xx_power_info *pi = rv770_get_pi(rdev);
+       struct radeon_atom_ss ss;
+
+       pi->sclk_ss = radeon_atombios_get_asic_ss_info(rdev, &ss,
+                                                      ASIC_INTERNAL_ENGINE_SS, 0);
+       pi->mclk_ss = radeon_atombios_get_asic_ss_info(rdev, &ss,
+                                                      ASIC_INTERNAL_MEMORY_SS, 0);
+
+       if (pi->sclk_ss || pi->mclk_ss)
+               pi->dynamic_ss = true;
+       else
+               pi->dynamic_ss = false;
+}
+
 int rv770_dpm_init(struct radeon_device *rdev)
 {
        struct rv7xx_power_info *pi;
-       int index = GetIndexIntoMasterTable(DATA, ASIC_InternalSS_Info);
-       uint16_t data_offset, size;
-       uint8_t frev, crev;
        struct atom_clock_dividers dividers;
        int ret;
 
@@ -2369,16 +2382,7 @@ int rv770_dpm_init(struct radeon_device *rdev)
        pi->mvdd_control =
                radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_MVDDC, 0);
 
-       if (atom_parse_data_header(rdev->mode_info.atom_context, index, &size,
-                                   &frev, &crev, &data_offset)) {
-               pi->sclk_ss = true;
-               pi->mclk_ss = true;
-               pi->dynamic_ss = true;
-       } else {
-               pi->sclk_ss = false;
-               pi->mclk_ss = false;
-               pi->dynamic_ss = false;
-       }
+       rv770_get_engine_memory_ss(rdev);
 
        pi->asi = RV770_ASI_DFLT;
        pi->pasi = RV770_HASI_DFLT;
@@ -2393,8 +2397,7 @@ int rv770_dpm_init(struct radeon_device *rdev)
 
        pi->dynamic_pcie_gen2 = true;
 
-       if (pi->gfx_clock_gating &&
-           (rdev->pm.int_thermal_type != THERMAL_TYPE_NONE))
+       if (rdev->pm.int_thermal_type != THERMAL_TYPE_NONE)
                pi->thermal_protection = true;
        else
                pi->thermal_protection = false;
index 96b1b2a62a8a2a0d5950574788d0936aba6ec730..9244effc6b59e2e69c6882b0d4dc35dd2517379c 100644 (file)
@@ -275,6 +275,7 @@ void rv770_set_uvd_clock_before_set_eng_clock(struct radeon_device *rdev,
 void rv770_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev,
                                             struct radeon_ps *new_ps,
                                             struct radeon_ps *old_ps);
+void rv770_get_engine_memory_ss(struct radeon_device *rdev);
 
 /* smc */
 int rv770_read_smc_soft_register(struct radeon_device *rdev,
index 6ca904673a4fa7046cee901d26c2b049546f2234..daa8d2df8ec502ca72a5b9897be75ae59a9a797c 100644 (file)
@@ -1663,9 +1663,13 @@ static int si_init_microcode(struct radeon_device *rdev)
 
        snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", chip_name);
        err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev);
-       if (err)
-               goto out;
-       if (rdev->smc_fw->size != smc_req_size) {
+       if (err) {
+               printk(KERN_ERR
+                      "smc: error loading firmware \"%s\"\n",
+                      fw_name);
+               release_firmware(rdev->smc_fw);
+               rdev->smc_fw = NULL;
+       } else if (rdev->smc_fw->size != smc_req_size) {
                printk(KERN_ERR
                       "si_smc: Bogus length %zu in firmware \"%s\"\n",
                       rdev->smc_fw->size, fw_name);
@@ -6418,6 +6422,8 @@ static int si_startup(struct radeon_device *rdev)
        /* enable aspm */
        si_program_aspm(rdev);
 
+       si_mc_program(rdev);
+
        if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw ||
            !rdev->rlc_fw || !rdev->mc_fw) {
                r = si_init_microcode(rdev);
@@ -6437,7 +6443,6 @@ static int si_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
-       si_mc_program(rdev);
        r = si_pcie_gart_enable(rdev);
        if (r)
                return r;
@@ -6621,7 +6626,7 @@ int si_suspend(struct radeon_device *rdev)
        si_cp_enable(rdev, false);
        cayman_dma_stop(rdev);
        if (rdev->has_uvd) {
-               r600_uvd_rbc_stop(rdev);
+               r600_uvd_stop(rdev);
                radeon_uvd_suspend(rdev);
        }
        si_irq_suspend(rdev);
@@ -6763,8 +6768,10 @@ void si_fini(struct radeon_device *rdev)
        radeon_vm_manager_fini(rdev);
        radeon_ib_pool_fini(rdev);
        radeon_irq_kms_fini(rdev);
-       if (rdev->has_uvd)
+       if (rdev->has_uvd) {
+               r600_uvd_stop(rdev);
                radeon_uvd_fini(rdev);
+       }
        si_pcie_gart_fini(rdev);
        r600_vram_scratch_fini(rdev);
        radeon_gem_fini(rdev);
index 41825575b403bab2b5e16b3fba33a33d3187f4f7..88699e3cd868047555ce426ecb2251c7f9f3850e 100644 (file)
@@ -2903,7 +2903,8 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
 {
        struct ni_ps *ps = ni_get_ps(rps);
        struct radeon_clock_and_voltage_limits *max_limits;
-       bool disable_mclk_switching;
+       bool disable_mclk_switching = false;
+       bool disable_sclk_switching = false;
        u32 mclk, sclk;
        u16 vddc, vddci;
        int i;
@@ -2911,8 +2912,11 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
        if ((rdev->pm.dpm.new_active_crtc_count > 1) ||
            ni_dpm_vblank_too_short(rdev))
                disable_mclk_switching = true;
-       else
-               disable_mclk_switching = false;
+
+       if (rps->vclk || rps->dclk) {
+               disable_mclk_switching = true;
+               disable_sclk_switching = true;
+       }
 
        if (rdev->pm.dpm.ac_power)
                max_limits = &rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac;
@@ -2940,27 +2944,43 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
 
        if (disable_mclk_switching) {
                mclk  = ps->performance_levels[ps->performance_level_count - 1].mclk;
-               sclk = ps->performance_levels[0].sclk;
-               vddc = ps->performance_levels[0].vddc;
                vddci = ps->performance_levels[ps->performance_level_count - 1].vddci;
        } else {
-               sclk = ps->performance_levels[0].sclk;
                mclk = ps->performance_levels[0].mclk;
-               vddc = ps->performance_levels[0].vddc;
                vddci = ps->performance_levels[0].vddci;
        }
 
+       if (disable_sclk_switching) {
+               sclk = ps->performance_levels[ps->performance_level_count - 1].sclk;
+               vddc = ps->performance_levels[ps->performance_level_count - 1].vddc;
+       } else {
+               sclk = ps->performance_levels[0].sclk;
+               vddc = ps->performance_levels[0].vddc;
+       }
+
        /* adjusted low state */
        ps->performance_levels[0].sclk = sclk;
        ps->performance_levels[0].mclk = mclk;
        ps->performance_levels[0].vddc = vddc;
        ps->performance_levels[0].vddci = vddci;
 
-       for (i = 1; i < ps->performance_level_count; i++) {
-               if (ps->performance_levels[i].sclk < ps->performance_levels[i - 1].sclk)
-                       ps->performance_levels[i].sclk = ps->performance_levels[i - 1].sclk;
-               if (ps->performance_levels[i].vddc < ps->performance_levels[i - 1].vddc)
-                       ps->performance_levels[i].vddc = ps->performance_levels[i - 1].vddc;
+       if (disable_sclk_switching) {
+               sclk = ps->performance_levels[0].sclk;
+               for (i = 1; i < ps->performance_level_count; i++) {
+                       if (sclk < ps->performance_levels[i].sclk)
+                               sclk = ps->performance_levels[i].sclk;
+               }
+               for (i = 0; i < ps->performance_level_count; i++) {
+                       ps->performance_levels[i].sclk = sclk;
+                       ps->performance_levels[i].vddc = vddc;
+               }
+       } else {
+               for (i = 1; i < ps->performance_level_count; i++) {
+                       if (ps->performance_levels[i].sclk < ps->performance_levels[i - 1].sclk)
+                               ps->performance_levels[i].sclk = ps->performance_levels[i - 1].sclk;
+                       if (ps->performance_levels[i].vddc < ps->performance_levels[i - 1].vddc)
+                               ps->performance_levels[i].vddc = ps->performance_levels[i - 1].vddc;
+               }
        }
 
        if (disable_mclk_switching) {
@@ -6253,9 +6273,6 @@ int si_dpm_init(struct radeon_device *rdev)
        struct evergreen_power_info *eg_pi;
        struct ni_power_info *ni_pi;
        struct si_power_info *si_pi;
-       int index = GetIndexIntoMasterTable(DATA, ASIC_InternalSS_Info);
-       u16 data_offset, size;
-       u8 frev, crev;
        struct atom_clock_dividers dividers;
        int ret;
        u32 mask;
@@ -6346,16 +6363,7 @@ int si_dpm_init(struct radeon_device *rdev)
        si_pi->vddc_phase_shed_control =
                radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC, VOLTAGE_OBJ_PHASE_LUT);
 
-       if (atom_parse_data_header(rdev->mode_info.atom_context, index, &size,
-                                   &frev, &crev, &data_offset)) {
-               pi->sclk_ss = true;
-               pi->mclk_ss = true;
-               pi->dynamic_ss = true;
-       } else {
-               pi->sclk_ss = false;
-               pi->mclk_ss = false;
-               pi->dynamic_ss = true;
-       }
+       rv770_get_engine_memory_ss(rdev);
 
        pi->asi = RV770_ASI_DFLT;
        pi->pasi = CYPRESS_HASI_DFLT;
@@ -6366,8 +6374,7 @@ int si_dpm_init(struct radeon_device *rdev)
        eg_pi->sclk_deep_sleep = true;
        si_pi->sclk_deep_sleep_above_low = false;
 
-       if (pi->gfx_clock_gating &&
-           (rdev->pm.int_thermal_type != THERMAL_TYPE_NONE))
+       if (rdev->pm.int_thermal_type != THERMAL_TYPE_NONE)
                pi->thermal_protection = true;
        else
                pi->thermal_protection = false;