forked from luck/tmp_suning_uos_patched
Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
Pull drm fixes from Dave Airlie: "Mostly radeon, more fixes for dynamic power management which is is off by default for this release anyways, but there are a large number of testers, so I'd like to keep merging the fixes. Otherwise, radeon UVD fixes affecting suspend/resume regressions, i915 regression fixes, one for your mac mini, ast, mgag200, cirrus ttm fix and one regression fix in the core" * 'drm-fixes' of git://people.freedesktop.org/~airlied/linux: (25 commits) drm: Don't pass negative delta to ktime_sub_ns() drm/radeon: make missing smc ucode non-fatal drm/radeon/dpm: require rlc for dpm drm/radeon/cik: use a mutex to properly lock srbm instanced registers drm/radeon: remove unnecessary unpin drm/radeon: add more UVD CS checking drm/radeon: stop sending invalid UVD destroy msg drm/radeon: only save UVD bo when we have open handles drm/radeon: always program the MC on startup drm/radeon: fix audio dto calculation on DCE3+ (v3) drm/radeon/dpm: disable sclk ss on rv6xx drm/radeon: fix halting UVD drm/radeon/dpm: adjust power state properly for UVD on SI drm/radeon/dpm: fix spread spectrum setup (v2) drm/radeon/dpm: adjust thermal protection requirements drm/radeon: select audio dto based on encoder id for DCE3 drm/radeon: properly handle pm on gpu reset 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 ...
This commit is contained in:
commit
6a93316661
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -1856,10 +1856,16 @@
|
|||
#define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2)
|
||||
|
||||
#define PORT_HOTPLUG_STAT (dev_priv->info->display_mmio_offset + 0x61114)
|
||||
/* HDMI/DP bits are gen4+ */
|
||||
#define PORTB_HOTPLUG_LIVE_STATUS (1 << 29)
|
||||
/*
|
||||
* HDMI/DP bits are gen4+
|
||||
*
|
||||
* WARNING: Bspec for hpd status bits on gen4 seems to be completely confused.
|
||||
* Please check the detailed lore in the commit message for for experimental
|
||||
* evidence.
|
||||
*/
|
||||
#define PORTD_HOTPLUG_LIVE_STATUS (1 << 29)
|
||||
#define PORTC_HOTPLUG_LIVE_STATUS (1 << 28)
|
||||
#define PORTD_HOTPLUG_LIVE_STATUS (1 << 27)
|
||||
#define PORTB_HOTPLUG_LIVE_STATUS (1 << 27)
|
||||
#define PORTD_HOTPLUG_INT_STATUS (3 << 21)
|
||||
#define PORTC_HOTPLUG_INT_STATUS (3 << 19)
|
||||
#define PORTB_HOTPLUG_INT_STATUS (3 << 17)
|
||||
|
|
|
@ -8269,9 +8269,11 @@ check_crtc_state(struct drm_device *dev)
|
|||
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
|
||||
base.head) {
|
||||
enum pipe pipe;
|
||||
if (encoder->base.crtc != &crtc->base)
|
||||
continue;
|
||||
if (encoder->get_config)
|
||||
if (encoder->get_config &&
|
||||
encoder->get_hw_state(encoder, &pipe))
|
||||
encoder->get_config(encoder, &pipe_config);
|
||||
}
|
||||
|
||||
|
|
|
@ -497,8 +497,11 @@ void intel_panel_set_backlight(struct drm_device *dev, u32 level, u32 max)
|
|||
goto out;
|
||||
}
|
||||
|
||||
/* scale to hardware */
|
||||
level = level * freq / max;
|
||||
/* scale to hardware, but be careful to not overflow */
|
||||
if (freq < max)
|
||||
level = level * freq / max;
|
||||
else
|
||||
level = freq / max * level;
|
||||
|
||||
dev_priv->backlight.level = level;
|
||||
if (dev_priv->backlight.device)
|
||||
|
@ -515,6 +518,17 @@ void intel_panel_disable_backlight(struct drm_device *dev)
|
|||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* Do not disable backlight on the vgaswitcheroo path. When switching
|
||||
* away from i915, the other client may depend on i915 to handle the
|
||||
* backlight. This will leave the backlight on unnecessarily when
|
||||
* another client is not activated.
|
||||
*/
|
||||
if (dev->switch_power_state == DRM_SWITCH_POWER_CHANGING) {
|
||||
DRM_DEBUG_DRIVER("Skipping backlight disable on vga switch\n");
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&dev_priv->backlight.lock, flags);
|
||||
|
||||
dev_priv->backlight.enabled = false;
|
||||
|
|
|
@ -5063,8 +5063,26 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable)
|
|||
}
|
||||
} else {
|
||||
if (enable_requested) {
|
||||
unsigned long irqflags;
|
||||
enum pipe p;
|
||||
|
||||
I915_WRITE(HSW_PWR_WELL_DRIVER, 0);
|
||||
POSTING_READ(HSW_PWR_WELL_DRIVER);
|
||||
DRM_DEBUG_KMS("Requesting to disable the power well\n");
|
||||
|
||||
/*
|
||||
* After this, the registers on the pipes that are part
|
||||
* of the power well will become zero, so we have to
|
||||
* adjust our counters according to that.
|
||||
*
|
||||
* FIXME: Should we do this in general in
|
||||
* drm_vblank_post_modeset?
|
||||
*/
|
||||
spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
||||
for_each_pipe(p)
|
||||
if (p != PIPE_A)
|
||||
dev->last_vblank[p] = 0;
|
||||
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -497,6 +497,9 @@
|
|||
#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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) |
|
||||
|
|
|
@ -933,6 +933,9 @@
|
|||
#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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 @@ int radeon_gpu_reset(struct radeon_device *rdev)
|
|||
}
|
||||
}
|
||||
|
||||
radeon_pm_resume(rdev);
|
||||
drm_helper_resume_force_mode(rdev->ddev);
|
||||
|
||||
ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue
Block a user