diff options
Diffstat (limited to 'drivers/gpu/drm/radeon')
82 files changed, 1944 insertions, 843 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 0b9621c9aeea..a9338c85630f 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -209,6 +209,16 @@ static void atombios_enable_crtc_memreq(struct drm_crtc *crtc, int state) atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); } +static const u32 vga_control_regs[6] = +{ + AVIVO_D1VGA_CONTROL, + AVIVO_D2VGA_CONTROL, + EVERGREEN_D3VGA_CONTROL, + EVERGREEN_D4VGA_CONTROL, + EVERGREEN_D5VGA_CONTROL, + EVERGREEN_D6VGA_CONTROL, +}; + static void atombios_blank_crtc(struct drm_crtc *crtc, int state) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); @@ -216,13 +226,23 @@ static void atombios_blank_crtc(struct drm_crtc *crtc, int state) struct radeon_device *rdev = dev->dev_private; int index = GetIndexIntoMasterTable(COMMAND, BlankCRTC); BLANK_CRTC_PS_ALLOCATION args; + u32 vga_control = 0; memset(&args, 0, sizeof(args)); + if (ASIC_IS_DCE8(rdev)) { + vga_control = RREG32(vga_control_regs[radeon_crtc->crtc_id]); + WREG32(vga_control_regs[radeon_crtc->crtc_id], vga_control | 1); + } + args.ucCRTC = radeon_crtc->crtc_id; args.ucBlanking = state; atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + + if (ASIC_IS_DCE8(rdev)) { + WREG32(vga_control_regs[radeon_crtc->crtc_id], vga_control); + } } static void atombios_powergate_crtc(struct drm_crtc *crtc, int state) @@ -423,7 +443,17 @@ static void atombios_crtc_program_ss(struct radeon_device *rdev, int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL); union atom_enable_ss args; - if (!enable) { + if (enable) { + /* Don't mess with SS if percentage is 0 or external ss. + * SS is already disabled previously, and disabling it + * again can cause display problems if the pll is already + * programmed. + */ + if (ss->percentage == 0) + return; + if (ss->type & ATOM_EXTERNAL_SS_MASK) + return; + } else { for (i = 0; i < rdev->num_crtc; i++) { if (rdev->mode_info.crtcs[i] && rdev->mode_info.crtcs[i]->enabled && @@ -459,8 +489,6 @@ static void atombios_crtc_program_ss(struct radeon_device *rdev, args.v3.usSpreadSpectrumAmount = cpu_to_le16(ss->amount); args.v3.usSpreadSpectrumStep = cpu_to_le16(ss->step); args.v3.ucEnable = enable; - if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK) || ASIC_IS_DCE61(rdev)) - args.v3.ucEnable = ATOM_DISABLE; } else if (ASIC_IS_DCE4(rdev)) { args.v2.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage); args.v2.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK; @@ -480,8 +508,6 @@ static void atombios_crtc_program_ss(struct radeon_device *rdev, args.v2.usSpreadSpectrumAmount = cpu_to_le16(ss->amount); args.v2.usSpreadSpectrumStep = cpu_to_le16(ss->step); args.v2.ucEnable = enable; - if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK) || ASIC_IS_DCE41(rdev)) - args.v2.ucEnable = ATOM_DISABLE; } else if (ASIC_IS_DCE3(rdev)) { args.v1.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage); args.v1.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK; @@ -503,8 +529,7 @@ static void atombios_crtc_program_ss(struct radeon_device *rdev, args.lvds_ss_2.ucSpreadSpectrumRange = ss->range; args.lvds_ss_2.ucEnable = enable; } else { - if ((enable == ATOM_DISABLE) || (ss->percentage == 0) || - (ss->type & ATOM_EXTERNAL_SS_MASK)) { + if (enable == ATOM_DISABLE) { atombios_disable_ss(rdev, pll_id); return; } @@ -938,11 +963,14 @@ static bool atombios_crtc_prepare_pll(struct drm_crtc *crtc, struct drm_display_ radeon_atombios_get_ppll_ss_info(rdev, &radeon_crtc->ss, ATOM_DP_SS_ID1); - } else + } else { radeon_crtc->ss_enabled = radeon_atombios_get_ppll_ss_info(rdev, &radeon_crtc->ss, ATOM_DP_SS_ID1); + } + /* disable spread spectrum on DCE3 DP */ + radeon_crtc->ss_enabled = false; } break; case ATOM_ENCODER_MODE_LVDS: @@ -1039,15 +1067,17 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode /* calculate ss amount and step size */ if (ASIC_IS_DCE4(rdev)) { u32 step_size; - u32 amount = (((fb_div * 10) + frac_fb_div) * radeon_crtc->ss.percentage) / 10000; + u32 amount = (((fb_div * 10) + frac_fb_div) * + (u32)radeon_crtc->ss.percentage) / + (100 * (u32)radeon_crtc->ss.percentage_divider); radeon_crtc->ss.amount = (amount / 10) & ATOM_PPLL_SS_AMOUNT_V2_FBDIV_MASK; radeon_crtc->ss.amount |= ((amount - (amount / 10)) << ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT) & ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK; if (radeon_crtc->ss.type & ATOM_PPLL_SS_TYPE_V2_CENTRE_SPREAD) - step_size = (4 * amount * ref_div * (radeon_crtc->ss.rate * 2048)) / + step_size = (4 * amount * ref_div * ((u32)radeon_crtc->ss.rate * 2048)) / (125 * 25 * pll->reference_freq / 100); else - step_size = (2 * amount * ref_div * (radeon_crtc->ss.rate * 2048)) / + step_size = (2 * amount * ref_div * ((u32)radeon_crtc->ss.rate * 2048)) / (125 * 25 * pll->reference_freq / 100); radeon_crtc->ss.step = step_size; } diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index fb3ae07a1469..4ad7643fce5f 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -157,21 +157,22 @@ static int radeon_dp_aux_native_write(struct radeon_connector *radeon_connector, msg[0] = address; msg[1] = address >> 8; - msg[2] = AUX_NATIVE_WRITE << 4; + msg[2] = DP_AUX_NATIVE_WRITE << 4; msg[3] = (msg_bytes << 4) | (send_bytes - 1); memcpy(&msg[4], send, send_bytes); - for (retry = 0; retry < 4; retry++) { + for (retry = 0; retry < 7; retry++) { ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus, msg, msg_bytes, NULL, 0, delay, &ack); if (ret == -EBUSY) continue; else if (ret < 0) return ret; - if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) + ack >>= 4; + if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK) return send_bytes; - else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) - udelay(400); + else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER) + usleep_range(400, 500); else return -EIO; } @@ -191,20 +192,21 @@ static int radeon_dp_aux_native_read(struct radeon_connector *radeon_connector, msg[0] = address; msg[1] = address >> 8; - msg[2] = AUX_NATIVE_READ << 4; + msg[2] = DP_AUX_NATIVE_READ << 4; msg[3] = (msg_bytes << 4) | (recv_bytes - 1); - for (retry = 0; retry < 4; retry++) { + for (retry = 0; retry < 7; retry++) { ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus, msg, msg_bytes, recv, recv_bytes, delay, &ack); if (ret == -EBUSY) continue; else if (ret < 0) return ret; - if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) + ack >>= 4; + if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK) return ret; - else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) - udelay(400); + else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER) + usleep_range(400, 500); else if (ret == 0) return -EPROTO; else @@ -246,12 +248,12 @@ int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, /* Set up the command byte */ if (mode & MODE_I2C_READ) - msg[2] = AUX_I2C_READ << 4; + msg[2] = DP_AUX_I2C_READ << 4; else - msg[2] = AUX_I2C_WRITE << 4; + msg[2] = DP_AUX_I2C_WRITE << 4; if (!(mode & MODE_I2C_STOP)) - msg[2] |= AUX_I2C_MOT << 4; + msg[2] |= DP_AUX_I2C_MOT << 4; msg[0] = address; msg[1] = address >> 8; @@ -272,7 +274,7 @@ int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, break; } - for (retry = 0; retry < 4; retry++) { + for (retry = 0; retry < 7; retry++) { ret = radeon_process_aux_ch(auxch, msg, msg_bytes, reply, reply_bytes, 0, &ack); if (ret == -EBUSY) @@ -282,35 +284,35 @@ int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, return ret; } - switch (ack & AUX_NATIVE_REPLY_MASK) { - case AUX_NATIVE_REPLY_ACK: + switch ((ack >> 4) & DP_AUX_NATIVE_REPLY_MASK) { + case DP_AUX_NATIVE_REPLY_ACK: /* I2C-over-AUX Reply field is only valid * when paired with AUX ACK. */ break; - case AUX_NATIVE_REPLY_NACK: + case DP_AUX_NATIVE_REPLY_NACK: DRM_DEBUG_KMS("aux_ch native nack\n"); return -EREMOTEIO; - case AUX_NATIVE_REPLY_DEFER: + case DP_AUX_NATIVE_REPLY_DEFER: DRM_DEBUG_KMS("aux_ch native defer\n"); - udelay(400); + usleep_range(500, 600); continue; default: DRM_ERROR("aux_ch invalid native reply 0x%02x\n", ack); return -EREMOTEIO; } - switch (ack & AUX_I2C_REPLY_MASK) { - case AUX_I2C_REPLY_ACK: + switch ((ack >> 4) & DP_AUX_I2C_REPLY_MASK) { + case DP_AUX_I2C_REPLY_ACK: if (mode == MODE_I2C_READ) *read_byte = reply[0]; return ret; - case AUX_I2C_REPLY_NACK: + case DP_AUX_I2C_REPLY_NACK: DRM_DEBUG_KMS("aux_i2c nack\n"); return -EREMOTEIO; - case AUX_I2C_REPLY_DEFER: + case DP_AUX_I2C_REPLY_DEFER: DRM_DEBUG_KMS("aux_i2c defer\n"); - udelay(400); + usleep_range(400, 500); break; default: DRM_ERROR("aux_i2c invalid reply 0x%02x\n", ack); @@ -671,9 +673,11 @@ static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info) u8 tmp; /* power up the sink */ - if (dp_info->dpcd[0] >= 0x11) + if (dp_info->dpcd[0] >= 0x11) { radeon_write_dpcd_reg(dp_info->radeon_connector, DP_SET_POWER, DP_SET_POWER_D0); + usleep_range(1000, 2000); + } /* possibly enable downspread on the sink */ if (dp_info->dpcd[3] & 0x1) diff --git a/drivers/gpu/drm/radeon/atombios_i2c.c b/drivers/gpu/drm/radeon/atombios_i2c.c index f685035dbe39..b5162c3b6111 100644 --- a/drivers/gpu/drm/radeon/atombios_i2c.c +++ b/drivers/gpu/drm/radeon/atombios_i2c.c @@ -27,8 +27,6 @@ #include "radeon.h" #include "atom.h" -extern void radeon_atom_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le); - #define TARGET_HW_I2C_CLOCK 50 /* these are a limitation of ProcessI2cChannelTransaction not the hw */ diff --git a/drivers/gpu/drm/radeon/btc_dpm.c b/drivers/gpu/drm/radeon/btc_dpm.c index 9b6950d9b3c0..0fbd36f3d4e9 100644 --- a/drivers/gpu/drm/radeon/btc_dpm.c +++ b/drivers/gpu/drm/radeon/btc_dpm.c @@ -49,6 +49,7 @@ struct rv7xx_ps *rv770_get_ps(struct radeon_ps *rps); struct rv7xx_power_info *rv770_get_pi(struct radeon_device *rdev); struct evergreen_power_info *evergreen_get_pi(struct radeon_device *rdev); +extern int ni_mc_load_microcode(struct radeon_device *rdev); //********* BARTS **************// static const u32 barts_cgcg_cgls_default[] = @@ -2510,21 +2511,6 @@ int btc_dpm_enable(struct radeon_device *rdev) if (eg_pi->ls_clock_gating) btc_ls_clock_gating_enable(rdev, true); - if (rdev->irq.installed && - r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) { - PPSMC_Result result; - - ret = rv770_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX); - if (ret) - return ret; - rdev->irq.dpm_thermal = true; - radeon_irq_set(rdev); - result = rv770_send_msg_to_smc(rdev, PPSMC_MSG_EnableThermalInterrupt); - - if (result != PPSMC_Result_OK) - DRM_DEBUG_KMS("Could not enable thermal interrupts.\n"); - } - rv770_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true); btc_init_stutter_mode(rdev); @@ -2576,7 +2562,11 @@ void btc_dpm_disable(struct radeon_device *rdev) void btc_dpm_setup_asic(struct radeon_device *rdev) { struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev); + int r; + r = ni_mc_load_microcode(rdev); + if (r) + DRM_ERROR("Failed to load MC firmware!\n"); rv770_get_memory_type(rdev); rv740_read_clock_registers(rdev); btc_read_arb_registers(rdev); diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index 1ed479976358..8d49104ca6c2 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -171,8 +171,7 @@ extern void si_trim_voltage_table_to_fit_state_table(struct radeon_device *rdev, struct atom_voltage_table *voltage_table); extern void cik_enter_rlc_safe_mode(struct radeon_device *rdev); extern void cik_exit_rlc_safe_mode(struct radeon_device *rdev); -extern void cik_update_cg(struct radeon_device *rdev, - u32 block, bool enable); +extern int ci_mc_load_microcode(struct radeon_device *rdev); static int ci_get_std_voltage_value_sidd(struct radeon_device *rdev, struct atom_voltage_table_entry *voltage_table, @@ -4503,8 +4502,8 @@ static void ci_get_memory_type(struct radeon_device *rdev) } -void ci_update_current_ps(struct radeon_device *rdev, - struct radeon_ps *rps) +static void ci_update_current_ps(struct radeon_device *rdev, + struct radeon_ps *rps) { struct ci_ps *new_ps = ci_get_ps(rps); struct ci_power_info *pi = ci_get_pi(rdev); @@ -4514,8 +4513,8 @@ void ci_update_current_ps(struct radeon_device *rdev, pi->current_rps.ps_priv = &pi->current_ps; } -void ci_update_requested_ps(struct radeon_device *rdev, - struct radeon_ps *rps) +static void ci_update_requested_ps(struct radeon_device *rdev, + struct radeon_ps *rps) { struct ci_ps *new_ps = ci_get_ps(rps); struct ci_power_info *pi = ci_get_pi(rdev); @@ -4549,6 +4548,11 @@ void ci_dpm_post_set_power_state(struct radeon_device *rdev) void ci_dpm_setup_asic(struct radeon_device *rdev) { + int r; + + r = ci_mc_load_microcode(rdev); + if (r) + DRM_ERROR("Failed to load MC firmware!\n"); ci_read_clock_registers(rdev); ci_get_memory_type(rdev); ci_enable_acpi_power_management(rdev); @@ -4561,13 +4565,6 @@ int ci_dpm_enable(struct radeon_device *rdev) struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps; int ret; - cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX | - RADEON_CG_BLOCK_MC | - RADEON_CG_BLOCK_SDMA | - RADEON_CG_BLOCK_BIF | - RADEON_CG_BLOCK_UVD | - RADEON_CG_BLOCK_HDP), false); - if (ci_is_smc_running(rdev)) return -EINVAL; if (pi->voltage_control != CISLANDS_VOLTAGE_CONTROL_NONE) { @@ -4665,6 +4662,18 @@ int ci_dpm_enable(struct radeon_device *rdev) DRM_ERROR("ci_enable_power_containment failed\n"); return ret; } + + ci_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true); + + ci_update_current_ps(rdev, boot_ps); + + return 0; +} + +int ci_dpm_late_enable(struct radeon_device *rdev) +{ + int ret; + if (rdev->irq.installed && r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) { #if 0 @@ -4685,19 +4694,8 @@ int ci_dpm_enable(struct radeon_device *rdev) #endif } - ci_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true); - ci_dpm_powergate_uvd(rdev, true); - cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX | - RADEON_CG_BLOCK_MC | - RADEON_CG_BLOCK_SDMA | - RADEON_CG_BLOCK_BIF | - RADEON_CG_BLOCK_UVD | - RADEON_CG_BLOCK_HDP), true); - - ci_update_current_ps(rdev, boot_ps); - return 0; } @@ -4706,12 +4704,6 @@ void ci_dpm_disable(struct radeon_device *rdev) struct ci_power_info *pi = ci_get_pi(rdev); struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps; - cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX | - RADEON_CG_BLOCK_MC | - RADEON_CG_BLOCK_SDMA | - RADEON_CG_BLOCK_UVD | - RADEON_CG_BLOCK_HDP), false); - ci_dpm_powergate_uvd(rdev, false); if (!ci_is_smc_running(rdev)) @@ -4742,13 +4734,6 @@ int ci_dpm_set_power_state(struct radeon_device *rdev) struct radeon_ps *old_ps = &pi->current_rps; int ret; - cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX | - RADEON_CG_BLOCK_MC | - RADEON_CG_BLOCK_SDMA | - RADEON_CG_BLOCK_BIF | - RADEON_CG_BLOCK_UVD | - RADEON_CG_BLOCK_HDP), false); - ci_find_dpm_states_clocks_in_dpm_table(rdev, new_ps); if (pi->pcie_performance_request) ci_request_link_speed_change_before_state_change(rdev, new_ps, old_ps); @@ -4804,13 +4789,6 @@ int ci_dpm_set_power_state(struct radeon_device *rdev) if (pi->pcie_performance_request) ci_notify_link_speed_change_after_state_change(rdev, new_ps, old_ps); - cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX | - RADEON_CG_BLOCK_MC | - RADEON_CG_BLOCK_SDMA | - RADEON_CG_BLOCK_BIF | - RADEON_CG_BLOCK_UVD | - RADEON_CG_BLOCK_HDP), true); - return 0; } @@ -5023,8 +5001,8 @@ static int ci_parse_power_table(struct radeon_device *rdev) return 0; } -int ci_get_vbios_boot_values(struct radeon_device *rdev, - struct ci_vbios_boot_state *boot_state) +static int ci_get_vbios_boot_values(struct radeon_device *rdev, + struct ci_vbios_boot_state *boot_state) { struct radeon_mode_info *mode_info = &rdev->mode_info; int index = GetIndexIntoMasterTable(DATA, FirmwareInfo); diff --git a/drivers/gpu/drm/radeon/ci_smc.c b/drivers/gpu/drm/radeon/ci_smc.c index 9c745dd22438..8debc9d47362 100644 --- a/drivers/gpu/drm/radeon/ci_smc.c +++ b/drivers/gpu/drm/radeon/ci_smc.c @@ -28,6 +28,7 @@ #include "cikd.h" #include "ppsmc.h" #include "radeon_ucode.h" +#include "ci_dpm.h" static int ci_set_smc_sram_address(struct radeon_device *rdev, u32 smc_address, u32 limit) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index e950fabd7f5e..e6419ca7cd37 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -1697,7 +1697,7 @@ static void cik_srbm_select(struct radeon_device *rdev, * Load the GDDR MC ucode into the hw (CIK). * Returns 0 on success, error on failure. */ -static int ci_mc_load_microcode(struct radeon_device *rdev) +int ci_mc_load_microcode(struct radeon_device *rdev) { const __be32 *fw_data; u32 running, blackout = 0; @@ -3487,6 +3487,51 @@ int cik_ring_test(struct radeon_device *rdev, struct radeon_ring *ring) } /** + * cik_hdp_flush_cp_ring_emit - emit an hdp flush on the cp + * + * @rdev: radeon_device pointer + * @ridx: radeon ring index + * + * Emits an hdp flush on the cp. + */ +static void cik_hdp_flush_cp_ring_emit(struct radeon_device *rdev, + int ridx) +{ + struct radeon_ring *ring = &rdev->ring[ridx]; + u32 ref_and_mask; + + switch (ring->idx) { + case CAYMAN_RING_TYPE_CP1_INDEX: + case CAYMAN_RING_TYPE_CP2_INDEX: + default: + switch (ring->me) { + case 0: + ref_and_mask = CP2 << ring->pipe; + break; + case 1: + ref_and_mask = CP6 << ring->pipe; + break; + default: + return; + } + break; + case RADEON_RING_TYPE_GFX_INDEX: + ref_and_mask = CP0; + break; + } + + radeon_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5)); + radeon_ring_write(ring, (WAIT_REG_MEM_OPERATION(1) | /* write, wait, write */ + WAIT_REG_MEM_FUNCTION(3) | /* == */ + WAIT_REG_MEM_ENGINE(1))); /* pfp */ + radeon_ring_write(ring, GPU_HDP_FLUSH_REQ >> 2); + radeon_ring_write(ring, GPU_HDP_FLUSH_DONE >> 2); + radeon_ring_write(ring, ref_and_mask); + radeon_ring_write(ring, ref_and_mask); + radeon_ring_write(ring, 0x20); /* poll interval */ +} + +/** * cik_fence_gfx_ring_emit - emit a fence on the gfx ring * * @rdev: radeon_device pointer @@ -3512,15 +3557,7 @@ void cik_fence_gfx_ring_emit(struct radeon_device *rdev, radeon_ring_write(ring, fence->seq); radeon_ring_write(ring, 0); /* HDP flush */ - /* We should be using the new WAIT_REG_MEM special op packet here - * but it causes the CP to hang - */ - radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); - radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) | - WRITE_DATA_DST_SEL(0))); - radeon_ring_write(ring, HDP_MEM_COHERENCY_FLUSH_CNTL >> 2); - radeon_ring_write(ring, 0); - radeon_ring_write(ring, 0); + cik_hdp_flush_cp_ring_emit(rdev, fence->ring); } /** @@ -3550,15 +3587,7 @@ void cik_fence_compute_ring_emit(struct radeon_device *rdev, radeon_ring_write(ring, fence->seq); radeon_ring_write(ring, 0); /* HDP flush */ - /* We should be using the new WAIT_REG_MEM special op packet here - * but it causes the CP to hang - */ - radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); - radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) | - WRITE_DATA_DST_SEL(0))); - radeon_ring_write(ring, HDP_MEM_COHERENCY_FLUSH_CNTL >> 2); - radeon_ring_write(ring, 0); - radeon_ring_write(ring, 0); + cik_hdp_flush_cp_ring_emit(rdev, fence->ring); } bool cik_semaphore_ring_emit(struct radeon_device *rdev, @@ -3566,8 +3595,6 @@ bool cik_semaphore_ring_emit(struct radeon_device *rdev, struct radeon_semaphore *semaphore, bool emit_wait) { -/* TODO: figure out why semaphore cause lockups */ -#if 0 uint64_t addr = semaphore->gpu_addr; unsigned sel = emit_wait ? PACKET3_SEM_SEL_WAIT : PACKET3_SEM_SEL_SIGNAL; @@ -3576,9 +3603,6 @@ bool cik_semaphore_ring_emit(struct radeon_device *rdev, radeon_ring_write(ring, (upper_32_bits(addr) & 0xffff) | sel); return true; -#else - return false; -#endif } /** @@ -3816,6 +3840,8 @@ static void cik_cp_gfx_enable(struct radeon_device *rdev, bool enable) if (enable) WREG32(CP_ME_CNTL, 0); else { + if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX) + radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT)); rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; } @@ -4014,18 +4040,50 @@ static int cik_cp_gfx_resume(struct radeon_device *rdev) rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; return r; } + + if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX) + radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); + return 0; } -u32 cik_compute_ring_get_rptr(struct radeon_device *rdev, - struct radeon_ring *ring) +u32 cik_gfx_get_rptr(struct radeon_device *rdev, + struct radeon_ring *ring) { u32 rptr; + if (rdev->wb.enabled) + rptr = rdev->wb.wb[ring->rptr_offs/4]; + else + rptr = RREG32(CP_RB0_RPTR); + + return rptr; +} + +u32 cik_gfx_get_wptr(struct radeon_device *rdev, + struct radeon_ring *ring) +{ + u32 wptr; + + wptr = RREG32(CP_RB0_WPTR); + + return wptr; +} +void cik_gfx_set_wptr(struct radeon_device *rdev, + struct radeon_ring *ring) +{ + WREG32(CP_RB0_WPTR, ring->wptr); + (void)RREG32(CP_RB0_WPTR); +} + +u32 cik_compute_get_rptr(struct radeon_device *rdev, + struct radeon_ring *ring) +{ + u32 rptr; if (rdev->wb.enabled) { - rptr = le32_to_cpu(rdev->wb.wb[ring->rptr_offs/4]); + rptr = rdev->wb.wb[ring->rptr_offs/4]; } else { mutex_lock(&rdev->srbm_mutex); cik_srbm_select(rdev, ring->me, ring->pipe, ring->queue, 0); @@ -4037,13 +4095,14 @@ u32 cik_compute_ring_get_rptr(struct radeon_device *rdev, return rptr; } -u32 cik_compute_ring_get_wptr(struct radeon_device *rdev, - struct radeon_ring *ring) +u32 cik_compute_get_wptr(struct radeon_device *rdev, + struct radeon_ring *ring) { u32 wptr; if (rdev->wb.enabled) { - wptr = le32_to_cpu(rdev->wb.wb[ring->wptr_offs/4]); + /* XXX check if swapping is necessary on BE */ + wptr = rdev->wb.wb[ring->wptr_offs/4]; } else { mutex_lock(&rdev->srbm_mutex); cik_srbm_select(rdev, ring->me, ring->pipe, ring->queue, 0); @@ -4055,10 +4114,11 @@ u32 cik_compute_ring_get_wptr(struct radeon_device *rdev, return wptr; } -void cik_compute_ring_set_wptr(struct radeon_device *rdev, - struct radeon_ring *ring) +void cik_compute_set_wptr(struct radeon_device *rdev, + struct radeon_ring *ring) { - rdev->wb.wb[ring->wptr_offs/4] = cpu_to_le32(ring->wptr); + /* XXX check if swapping is necessary on BE */ + rdev->wb.wb[ring->wptr_offs/4] = ring->wptr; WDOORBELL32(ring->doorbell_index, ring->wptr); } @@ -4852,6 +4912,160 @@ static void cik_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) cik_print_gpu_status_regs(rdev); } +struct kv_reset_save_regs { + u32 gmcon_reng_execute; + u32 gmcon_misc; + u32 gmcon_misc3; +}; + +static void kv_save_regs_for_reset(struct radeon_device *rdev, + struct kv_reset_save_regs *save) +{ + save->gmcon_reng_execute = RREG32(GMCON_RENG_EXECUTE); + save->gmcon_misc = RREG32(GMCON_MISC); + save->gmcon_misc3 = RREG32(GMCON_MISC3); + + WREG32(GMCON_RENG_EXECUTE, save->gmcon_reng_execute & ~RENG_EXECUTE_ON_PWR_UP); + WREG32(GMCON_MISC, save->gmcon_misc & ~(RENG_EXECUTE_ON_REG_UPDATE | + STCTRL_STUTTER_EN)); +} + +static void kv_restore_regs_for_reset(struct radeon_device *rdev, + struct kv_reset_save_regs *save) +{ + int i; + + WREG32(GMCON_PGFSM_WRITE, 0); + WREG32(GMCON_PGFSM_CONFIG, 0x200010ff); + + for (i = 0; i < 5; i++) + WREG32(GMCON_PGFSM_WRITE, 0); + + WREG32(GMCON_PGFSM_WRITE, 0); + WREG32(GMCON_PGFSM_CONFIG, 0x300010ff); + + for (i = 0; i < 5; i++) + WREG32(GMCON_PGFSM_WRITE, 0); + + WREG32(GMCON_PGFSM_WRITE, 0x210000); + WREG32(GMCON_PGFSM_CONFIG, 0xa00010ff); + + for (i = 0; i < 5; i++) + WREG32(GMCON_PGFSM_WRITE, 0); + + WREG32(GMCON_PGFSM_WRITE, 0x21003); + WREG32(GMCON_PGFSM_CONFIG, 0xb00010ff); + + for (i = 0; i < 5; i++) + WREG32(GMCON_PGFSM_WRITE, 0); + + WREG32(GMCON_PGFSM_WRITE, 0x2b00); + WREG32(GMCON_PGFSM_CONFIG, 0xc00010ff); + + for (i = 0; i < 5; i++) + WREG32(GMCON_PGFSM_WRITE, 0); + + WREG32(GMCON_PGFSM_WRITE, 0); + WREG32(GMCON_PGFSM_CONFIG, 0xd00010ff); + + for (i = 0; i < 5; i++) + WREG32(GMCON_PGFSM_WRITE, 0); + + WREG32(GMCON_PGFSM_WRITE, 0x420000); + WREG32(GMCON_PGFSM_CONFIG, 0x100010ff); + + for (i = 0; i < 5; i++) + WREG32(GMCON_PGFSM_WRITE, 0); + + WREG32(GMCON_PGFSM_WRITE, 0x120202); + WREG32(GMCON_PGFSM_CONFIG, 0x500010ff); + + for (i = 0; i < 5; i++) + WREG32(GMCON_PGFSM_WRITE, 0); + + WREG32(GMCON_PGFSM_WRITE, 0x3e3e36); + WREG32(GMCON_PGFSM_CONFIG, 0x600010ff); + + for (i = 0; i < 5; i++) + WREG32(GMCON_PGFSM_WRITE, 0); + + WREG32(GMCON_PGFSM_WRITE, 0x373f3e); + WREG32(GMCON_PGFSM_CONFIG, 0x700010ff); + + for (i = 0; i < 5; i++) + WREG32(GMCON_PGFSM_WRITE, 0); + + WREG32(GMCON_PGFSM_WRITE, 0x3e1332); + WREG32(GMCON_PGFSM_CONFIG, 0xe00010ff); + + WREG32(GMCON_MISC3, save->gmcon_misc3); + WREG32(GMCON_MISC, save->gmcon_misc); + WREG32(GMCON_RENG_EXECUTE, save->gmcon_reng_execute); +} + +static void cik_gpu_pci_config_reset(struct radeon_device *rdev) +{ + struct evergreen_mc_save save; + struct kv_reset_save_regs kv_save = { 0 }; + u32 tmp, i; + + dev_info(rdev->dev, "GPU pci config reset\n"); + + /* disable dpm? */ + + /* disable cg/pg */ + cik_fini_pg(rdev); + cik_fini_cg(rdev); + + /* Disable GFX parsing/prefetching */ + WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT); + + /* Disable MEC parsing/prefetching */ + WREG32(CP_MEC_CNTL, MEC_ME1_HALT | MEC_ME2_HALT); + + /* sdma0 */ + tmp = RREG32(SDMA0_ME_CNTL + SDMA0_REGISTER_OFFSET); + tmp |= SDMA_HALT; + WREG32(SDMA0_ME_CNTL + SDMA0_REGISTER_OFFSET, tmp); + /* sdma1 */ + tmp = RREG32(SDMA0_ME_CNTL + SDMA1_REGISTER_OFFSET); + tmp |= SDMA_HALT; + WREG32(SDMA0_ME_CNTL + SDMA1_REGISTER_OFFSET, tmp); + /* XXX other engines? */ + + /* halt the rlc, disable cp internal ints */ + cik_rlc_stop(rdev); + + udelay(50); + + /* disable mem access */ + evergreen_mc_stop(rdev, &save); + if (evergreen_mc_wait_for_idle(rdev)) { + dev_warn(rdev->dev, "Wait for MC idle timed out !\n"); + } + + if (rdev->flags & RADEON_IS_IGP) + kv_save_regs_for_reset(rdev, &kv_save); + + /* disable BM */ + pci_clear_master(rdev->pdev); + /* reset */ + radeon_pci_config_reset(rdev); + + udelay(100); + + /* wait for asic to come out of reset */ + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(CONFIG_MEMSIZE) != 0xffffffff) + break; + udelay(1); + } + + /* does asic init need to be run first??? */ + if (rdev->flags & RADEON_IS_IGP) + kv_restore_regs_for_reset(rdev, &kv_save); +} + /** * cik_asic_reset - soft reset GPU * @@ -4870,10 +5084,17 @@ int cik_asic_reset(struct radeon_device *rdev) if (reset_mask) r600_set_bios_scratch_engine_hung(rdev, true); + /* try soft reset */ cik_gpu_soft_reset(rdev, reset_mask); reset_mask = cik_gpu_check_soft_reset(rdev); + /* try pci config reset */ + if (reset_mask && radeon_hard_reset) + cik_gpu_pci_config_reset(rdev); + + reset_mask = cik_gpu_check_soft_reset(rdev); + if (!reset_mask) r600_set_bios_scratch_engine_hung(rdev, false); @@ -5138,20 +5359,6 @@ static int cik_pcie_gart_enable(struct radeon_device *rdev) WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT | WRITE_PROTECTION_FAULT_ENABLE_DEFAULT); - /* TC cache setup ??? */ - WREG32(TC_CFG_L1_LOAD_POLICY0, 0); - WREG32(TC_CFG_L1_LOAD_POLICY1, 0); - WREG32(TC_CFG_L1_STORE_POLICY, 0); - - WREG32(TC_CFG_L2_LOAD_POLICY0, 0); - WREG32(TC_CFG_L2_LOAD_POLICY1, 0); - WREG32(TC_CFG_L2_STORE_POLICY0, 0); - WREG32(TC_CFG_L2_STORE_POLICY1, 0); - WREG32(TC_CFG_L2_ATOMIC_POLICY, 0); - - WREG32(TC_CFG_L1_VOLATILE, 0); - WREG32(TC_CFG_L2_VOLATILE, 0); - if (rdev->family == CHIP_KAVERI) { u32 tmp = RREG32(CHUB_CONTROL); tmp &= ~BYPASS_VM; @@ -5367,16 +5574,7 @@ void cik_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm) radeon_ring_write(ring, VMID(0)); /* HDP flush */ - /* We should be using the WAIT_REG_MEM packet here like in - * cik_fence_ring_emit(), but it causes the CP to hang in this - * context... - */ - radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); - radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) | - WRITE_DATA_DST_SEL(0))); - radeon_ring_write(ring, HDP_MEM_COHERENCY_FLUSH_CNTL >> 2); - radeon_ring_write(ring, 0); - radeon_ring_write(ring, 0); + cik_hdp_flush_cp_ring_emit(rdev, ridx); /* bits 0-15 are the VM contexts0-15 */ radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); @@ -7503,26 +7701,7 @@ static int cik_startup(struct radeon_device *rdev) 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) { - r = cik_init_microcode(rdev); - if (r) { - DRM_ERROR("Failed to load firmware!\n"); - return r; - } - } - } else { - if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw || - !rdev->mec_fw || !rdev->sdma_fw || !rdev->rlc_fw || - !rdev->mc_fw) { - r = cik_init_microcode(rdev); - if (r) { - DRM_ERROR("Failed to load firmware!\n"); - return r; - } - } - + if (!(rdev->flags & RADEON_IS_IGP) && !rdev->pm.dpm_enabled) { r = ci_mc_load_microcode(rdev); if (r) { DRM_ERROR("Failed to load MC firmware!\n"); @@ -7627,7 +7806,6 @@ static int cik_startup(struct radeon_device *rdev) ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET, - CP_RB0_RPTR, CP_RB0_WPTR, PACKET3(PACKET3_NOP, 0x3FFF)); if (r) return r; @@ -7636,7 +7814,6 @@ static int cik_startup(struct radeon_device *rdev) /* type-2 packets are deprecated on MEC, use type-3 instead */ ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]; r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP1_RPTR_OFFSET, - CP_HQD_PQ_RPTR, CP_HQD_PQ_WPTR, PACKET3(PACKET3_NOP, 0x3FFF)); if (r) return r; @@ -7648,7 +7825,6 @@ static int cik_startup(struct radeon_device *rdev) /* type-2 packets are deprecated on MEC, use type-3 instead */ ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]; r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP2_RPTR_OFFSET, - CP_HQD_PQ_RPTR, CP_HQD_PQ_WPTR, PACKET3(PACKET3_NOP, 0x3FFF)); if (r) return r; @@ -7660,16 +7836,12 @@ static int cik_startup(struct radeon_device *rdev) ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX]; r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET, - SDMA0_GFX_RB_RPTR + SDMA0_REGISTER_OFFSET, - SDMA0_GFX_RB_WPTR + SDMA0_REGISTER_OFFSET, SDMA_PACKET(SDMA_OPCODE_NOP, 0, 0)); if (r) return r; ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX]; r = radeon_ring_init(rdev, ring, ring->ring_size, CAYMAN_WB_DMA1_RPTR_OFFSET, - SDMA0_GFX_RB_RPTR + SDMA1_REGISTER_OFFSET, - SDMA0_GFX_RB_WPTR + SDMA1_REGISTER_OFFSET, SDMA_PACKET(SDMA_OPCODE_NOP, 0, 0)); if (r) return r; @@ -7685,7 +7857,6 @@ static int cik_startup(struct radeon_device *rdev) ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; if (ring->ring_size) { r = radeon_ring_init(rdev, ring, ring->ring_size, 0, - UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR, RADEON_CP_PACKET2); if (!r) r = uvd_v1_0_init(rdev); @@ -7731,6 +7902,8 @@ int cik_resume(struct radeon_device *rdev) /* init golden registers */ cik_init_golden_registers(rdev); + radeon_pm_resume(rdev); + rdev->accel_working = true; r = cik_startup(rdev); if (r) { @@ -7754,6 +7927,7 @@ int cik_resume(struct radeon_device *rdev) */ int cik_suspend(struct radeon_device *rdev) { + radeon_pm_suspend(rdev); dce6_audio_fini(rdev); radeon_vm_manager_fini(rdev); cik_cp_enable(rdev, false); @@ -7835,6 +8009,30 @@ int cik_init(struct radeon_device *rdev) if (r) return r; + 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) { + r = cik_init_microcode(rdev); + if (r) { + DRM_ERROR("Failed to load firmware!\n"); + return r; + } + } + } else { + if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw || + !rdev->mec_fw || !rdev->sdma_fw || !rdev->rlc_fw || + !rdev->mc_fw) { + r = cik_init_microcode(rdev); + if (r) { + DRM_ERROR("Failed to load firmware!\n"); + return r; + } + } + } + + /* Initialize power management */ + radeon_pm_init(rdev); + ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; ring->ring_obj = NULL; r600_ring_init(rdev, ring, 1024 * 1024); @@ -7915,6 +8113,7 @@ int cik_init(struct radeon_device *rdev) */ void cik_fini(struct radeon_device *rdev) { + radeon_pm_fini(rdev); cik_cp_fini(rdev); cik_sdma_fini(rdev); cik_fini_pg(rdev); diff --git a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c index d08b83c6267b..1ecb3f1070e3 100644 --- a/drivers/gpu/drm/radeon/cik_sdma.c +++ b/drivers/gpu/drm/radeon/cik_sdma.c @@ -52,6 +52,75 @@ u32 cik_gpu_check_soft_reset(struct radeon_device *rdev); */ /** + * cik_sdma_get_rptr - get the current read pointer + * + * @rdev: radeon_device pointer + * @ring: radeon ring pointer + * + * Get the current rptr from the hardware (CIK+). + */ +uint32_t cik_sdma_get_rptr(struct radeon_device *rdev, + struct radeon_ring *ring) +{ + u32 rptr, reg; + + if (rdev->wb.enabled) { + rptr = rdev->wb.wb[ring->rptr_offs/4]; + } else { + if (ring->idx == R600_RING_TYPE_DMA_INDEX) + reg = SDMA0_GFX_RB_RPTR + SDMA0_REGISTER_OFFSET; + else + reg = SDMA0_GFX_RB_RPTR + SDMA1_REGISTER_OFFSET; + + rptr = RREG32(reg); + } + + return (rptr & 0x3fffc) >> 2; +} + +/** + * cik_sdma_get_wptr - get the current write pointer + * + * @rdev: radeon_device pointer + * @ring: radeon ring pointer + * + * Get the current wptr from the hardware (CIK+). + */ +uint32_t cik_sdma_get_wptr(struct radeon_device *rdev, + struct radeon_ring *ring) +{ + u32 reg; + + if (ring->idx == R600_RING_TYPE_DMA_INDEX) + reg = SDMA0_GFX_RB_WPTR + SDMA0_REGISTER_OFFSET; + else + reg = SDMA0_GFX_RB_WPTR + SDMA1_REGISTER_OFFSET; + + return (RREG32(reg) & 0x3fffc) >> 2; +} + +/** + * cik_sdma_set_wptr - commit the write pointer + * + * @rdev: radeon_device pointer + * @ring: radeon ring pointer + * + * Write the wptr back to the hardware (CIK+). + */ +void cik_sdma_set_wptr(struct radeon_device *rdev, + struct radeon_ring *ring) +{ + u32 reg; + + if (ring->idx == R600_RING_TYPE_DMA_INDEX) + reg = SDMA0_GFX_RB_WPTR + SDMA0_REGISTER_OFFSET; + else + reg = SDMA0_GFX_RB_WPTR + SDMA1_REGISTER_OFFSET; + + WREG32(reg, (ring->wptr << 2) & 0x3fffc); +} + +/** * cik_sdma_ring_ib_execute - Schedule an IB on the DMA engine * * @rdev: radeon_device pointer @@ -88,6 +157,35 @@ void cik_sdma_ring_ib_execute(struct radeon_device *rdev, } /** + * cik_sdma_hdp_flush_ring_emit - emit an hdp flush on the DMA ring + * + * @rdev: radeon_device pointer + * @ridx: radeon ring index + * + * Emit an hdp flush packet on the requested DMA ring. + */ +static void cik_sdma_hdp_flush_ring_emit(struct radeon_device *rdev, + int ridx) +{ + struct radeon_ring *ring = &rdev->ring[ridx]; + u32 extra_bits = (SDMA_POLL_REG_MEM_EXTRA_OP(1) | + SDMA_POLL_REG_MEM_EXTRA_FUNC(3)); /* == */ + u32 ref_and_mask; + + if (ridx == R600_RING_TYPE_DMA_INDEX) + ref_and_mask = SDMA0; + else + ref_and_mask = SDMA1; + + radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_POLL_REG_MEM, 0, extra_bits)); + radeon_ring_write(ring, GPU_HDP_FLUSH_DONE); + radeon_ring_write(ring, GPU_HDP_FLUSH_REQ); + radeon_ring_write(ring, ref_and_mask); /* reference */ + radeon_ring_write(ring, ref_and_mask); /* mask */ + radeon_ring_write(ring, (0xfff << 16) | 10); /* retry count, poll interval */ +} + +/** * cik_sdma_fence_ring_emit - emit a fence on the DMA ring * * @rdev: radeon_device pointer @@ -111,12 +209,7 @@ void cik_sdma_fence_ring_emit(struct radeon_device *rdev, /* generate an interrupt */ radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_TRAP, 0, 0)); /* flush HDP */ - /* We should be using the new POLL_REG_MEM special op packet here - * but it causes sDMA to hang sometimes - */ - radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 0xf000)); - radeon_ring_write(ring, HDP_MEM_COHERENCY_FLUSH_CNTL >> 2); - radeon_ring_write(ring, 0); + cik_sdma_hdp_flush_ring_emit(rdev, fence->ring); } /** @@ -157,7 +250,9 @@ static void cik_sdma_gfx_stop(struct radeon_device *rdev) u32 rb_cntl, reg_offset; int i; - radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); + if ((rdev->asic->copy.copy_ring_index == R600_RING_TYPE_DMA_INDEX) || + (rdev->asic->copy.copy_ring_index == CAYMAN_RING_TYPE_DMA1_INDEX)) + radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); for (i = 0; i < 2; i++) { if (i == 0) @@ -288,7 +383,9 @@ static int cik_sdma_gfx_resume(struct radeon_device *rdev) } } - radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); + if ((rdev->asic->copy.copy_ring_index == R600_RING_TYPE_DMA_INDEX) || + (rdev->asic->copy.copy_ring_index == CAYMAN_RING_TYPE_DMA1_INDEX)) + radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); return 0; } @@ -747,12 +844,7 @@ void cik_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm radeon_ring_write(ring, VMID(0)); /* flush HDP */ - /* We should be using the new POLL_REG_MEM special op packet here - * but it causes sDMA to hang sometimes - */ - radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 0xf000)); - radeon_ring_write(ring, HDP_MEM_COHERENCY_FLUSH_CNTL >> 2); - radeon_ring_write(ring, 0); + cik_sdma_hdp_flush_ring_emit(rdev, ridx); /* flush TLB */ radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 0xf000)); diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h index 5964af5e5b2d..98bae9d7b74d 100644 --- a/drivers/gpu/drm/radeon/cikd.h +++ b/drivers/gpu/drm/radeon/cikd.h @@ -724,6 +724,17 @@ #define ATC_MISC_CG 0x3350 +#define GMCON_RENG_EXECUTE 0x3508 +#define RENG_EXECUTE_ON_PWR_UP (1 << 0) +#define GMCON_MISC 0x350c +#define RENG_EXECUTE_ON_REG_UPDATE (1 << 11) +#define STCTRL_STUTTER_EN (1 << 16) + +#define GMCON_PGFSM_CONFIG 0x3538 +#define GMCON_PGFSM_WRITE 0x353c +#define GMCON_PGFSM_READ 0x3540 +#define GMCON_MISC3 0x3544 + #define MC_SEQ_CNTL_3 0x3600 # define CAC_EN (1 << 31) #define MC_SEQ_G5PDX_CTRL 0x3604 diff --git a/drivers/gpu/drm/radeon/cypress_dpm.c b/drivers/gpu/drm/radeon/cypress_dpm.c index 920e1e4a52c5..cf783fc0ef21 100644 --- a/drivers/gpu/drm/radeon/cypress_dpm.c +++ b/drivers/gpu/drm/radeon/cypress_dpm.c @@ -1905,21 +1905,6 @@ int cypress_dpm_enable(struct radeon_device *rdev) if (pi->mg_clock_gating) cypress_mg_clock_gating_enable(rdev, true); - if (rdev->irq.installed && - r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) { - PPSMC_Result result; - - ret = rv770_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX); - if (ret) - return ret; - rdev->irq.dpm_thermal = true; - radeon_irq_set(rdev); - result = rv770_send_msg_to_smc(rdev, PPSMC_MSG_EnableThermalInterrupt); - - if (result != PPSMC_Result_OK) - DRM_DEBUG_KMS("Could not enable thermal interrupts.\n"); - } - rv770_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true); return 0; diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 9702e55e924e..f2b9e21ce4da 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -146,6 +146,7 @@ extern u32 si_get_csb_size(struct radeon_device *rdev); extern void si_get_csb_buffer(struct radeon_device *rdev, volatile u32 *buffer); extern u32 cik_get_csb_size(struct radeon_device *rdev); extern void cik_get_csb_buffer(struct radeon_device *rdev, volatile u32 *buffer); +extern void rv770_set_clk_bypass_mode(struct radeon_device *rdev); static const u32 evergreen_golden_registers[] = { @@ -3867,6 +3868,48 @@ static void evergreen_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) evergreen_print_gpu_status_regs(rdev); } +void evergreen_gpu_pci_config_reset(struct radeon_device *rdev) +{ + struct evergreen_mc_save save; + u32 tmp, i; + + dev_info(rdev->dev, "GPU pci config reset\n"); + + /* disable dpm? */ + + /* Disable CP parsing/prefetching */ + WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT); + udelay(50); + /* Disable DMA */ + tmp = RREG32(DMA_RB_CNTL); + tmp &= ~DMA_RB_ENABLE; + WREG32(DMA_RB_CNTL, tmp); + /* XXX other engines? */ + + /* halt the rlc */ + r600_rlc_stop(rdev); + + udelay(50); + + /* set mclk/sclk to bypass */ + rv770_set_clk_bypass_mode(rdev); + /* disable BM */ + pci_clear_master(rdev->pdev); + /* disable mem access */ + evergreen_mc_stop(rdev, &save); + if (evergreen_mc_wait_for_idle(rdev)) { + dev_warn(rdev->dev, "Wait for MC idle timed out !\n"); + } + /* reset */ + radeon_pci_config_reset(rdev); + /* wait for asic to come out of reset */ + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(CONFIG_MEMSIZE) != 0xffffffff) + break; + udelay(1); + } +} + int evergreen_asic_reset(struct radeon_device *rdev) { u32 reset_mask; @@ -3876,10 +3919,17 @@ int evergreen_asic_reset(struct radeon_device *rdev) if (reset_mask) r600_set_bios_scratch_engine_hung(rdev, true); + /* try soft reset */ evergreen_gpu_soft_reset(rdev, reset_mask); reset_mask = evergreen_gpu_check_soft_reset(rdev); + /* try pci config reset */ + if (reset_mask && radeon_hard_reset) + evergreen_gpu_pci_config_reset(rdev); + + reset_mask = evergreen_gpu_check_soft_reset(rdev); + if (!reset_mask) r600_set_bios_scratch_engine_hung(rdev, false); @@ -4298,8 +4348,8 @@ void evergreen_disable_interrupt_state(struct radeon_device *rdev) WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); } - /* only one DAC on DCE6 */ - if (!ASIC_IS_DCE6(rdev)) + /* only one DAC on DCE5 */ + if (!ASIC_IS_DCE5(rdev)) WREG32(DACA_AUTODETECT_INT_CONTROL, 0); WREG32(DACB_AUTODETECT_INT_CONTROL, 0); @@ -5109,27 +5159,12 @@ static int evergreen_startup(struct radeon_device *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); - if (r) { - DRM_ERROR("Failed to load firmware!\n"); - return r; - } - } + if (ASIC_IS_DCE5(rdev) && !rdev->pm.dpm_enabled) { r = ni_mc_load_microcode(rdev); if (r) { DRM_ERROR("Failed to load MC firmware!\n"); return r; } - } else { - if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { - r = r600_init_microcode(rdev); - if (r) { - DRM_ERROR("Failed to load firmware!\n"); - return r; - } - } } if (rdev->flags & RADEON_IS_AGP) { @@ -5199,14 +5234,12 @@ static int evergreen_startup(struct radeon_device *rdev) ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET, - R600_CP_RB_RPTR, R600_CP_RB_WPTR, RADEON_CP_PACKET2); if (r) return r; ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX]; r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET, - DMA_RB_RPTR, DMA_RB_WPTR, DMA_PACKET(DMA_PACKET_NOP, 0, 0)); if (r) return r; @@ -5224,7 +5257,6 @@ static int evergreen_startup(struct radeon_device *rdev) ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; if (ring->ring_size) { r = radeon_ring_init(rdev, ring, ring->ring_size, 0, - UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR, RADEON_CP_PACKET2); if (!r) r = uvd_v1_0_init(rdev); @@ -5267,6 +5299,8 @@ int evergreen_resume(struct radeon_device *rdev) /* init golden registers */ evergreen_init_golden_registers(rdev); + radeon_pm_resume(rdev); + rdev->accel_working = true; r = evergreen_startup(rdev); if (r) { @@ -5281,6 +5315,7 @@ int evergreen_resume(struct radeon_device *rdev) int evergreen_suspend(struct radeon_device *rdev) { + radeon_pm_suspend(rdev); r600_audio_fini(rdev); uvd_v1_0_fini(rdev); radeon_uvd_suspend(rdev); @@ -5357,6 +5392,27 @@ int evergreen_init(struct radeon_device *rdev) if (r) return r; + if (ASIC_IS_DCE5(rdev)) { + if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) { + r = ni_init_microcode(rdev); + if (r) { + DRM_ERROR("Failed to load firmware!\n"); + return r; + } + } + } else { + if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { + r = r600_init_microcode(rdev); + if (r) { + DRM_ERROR("Failed to load firmware!\n"); + return r; + } + } + } + + /* Initialize power management */ + radeon_pm_init(rdev); + rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL; r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024); @@ -5409,6 +5465,7 @@ int evergreen_init(struct radeon_device *rdev) void evergreen_fini(struct radeon_device *rdev) { + radeon_pm_fini(rdev); r600_audio_fini(rdev); r700_cp_fini(rdev); r600_dma_fini(rdev); diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index eb8ac315f92f..c7cac07f139b 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -967,7 +967,10 @@ static int evergreen_cs_track_check(struct radeon_cs_parser *p) if (track->cb_dirty) { tmp = track->cb_target_mask; for (i = 0; i < 8; i++) { - if ((tmp >> (i * 4)) & 0xF) { + u32 format = G_028C70_FORMAT(track->cb_color_info[i]); + + if (format != V_028C70_COLOR_INVALID && + (tmp >> (i * 4)) & 0xF) { /* at least one component is enabled */ if (track->cb_color_bo[i] == NULL) { dev_warn(p->dev, "%s:%d mask 0x%08X | 0x%08X no cb for %d\n", diff --git a/drivers/gpu/drm/radeon/evergreen_reg.h b/drivers/gpu/drm/radeon/evergreen_reg.h index 8a4e641f0e3c..a0f63ff5a5e9 100644 --- a/drivers/gpu/drm/radeon/evergreen_reg.h +++ b/drivers/gpu/drm/radeon/evergreen_reg.h @@ -33,6 +33,7 @@ #define EVERGREEN_PIF_PHY0_DATA 0xc #define EVERGREEN_PIF_PHY1_INDEX 0x10 #define EVERGREEN_PIF_PHY1_DATA 0x14 +#define EVERGREEN_MM_INDEX_HI 0x18 #define EVERGREEN_VGA_MEMORY_BASE_ADDRESS 0x310 #define EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH 0x324 diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index 17f990798992..f9c7963b3ee6 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -82,12 +82,16 @@ #define CG_SPLL_FUNC_CNTL_2 0x604 #define SCLK_MUX_SEL(x) ((x) << 0) #define SCLK_MUX_SEL_MASK (0x1ff << 0) +#define SCLK_MUX_UPDATE (1 << 26) #define CG_SPLL_FUNC_CNTL_3 0x608 #define SPLL_FB_DIV(x) ((x) << 0) #define SPLL_FB_DIV_MASK (0x3ffffff << 0) #define SPLL_DITHEN (1 << 28) +#define CG_SPLL_STATUS 0x60c +#define SPLL_CHG_STATUS (1 << 1) #define MPLL_CNTL_MODE 0x61c +# define MPLL_MCLK_SEL (1 << 11) # define SS_SSEN (1 << 24) # define SS_DSMODE_EN (1 << 25) diff --git a/drivers/gpu/drm/radeon/kv_dpm.c b/drivers/gpu/drm/radeon/kv_dpm.c index b41905573cd2..b6e01d5d2cce 100644 --- a/drivers/gpu/drm/radeon/kv_dpm.c +++ b/drivers/gpu/drm/radeon/kv_dpm.c @@ -1126,11 +1126,6 @@ int kv_dpm_enable(struct radeon_device *rdev) struct kv_power_info *pi = kv_get_pi(rdev); int ret; - cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX | - RADEON_CG_BLOCK_SDMA | - RADEON_CG_BLOCK_BIF | - RADEON_CG_BLOCK_HDP), false); - ret = kv_process_firmware_header(rdev); if (ret) { DRM_ERROR("kv_process_firmware_header failed\n"); @@ -1215,6 +1210,21 @@ int kv_dpm_enable(struct radeon_device *rdev) kv_reset_acp_boot_level(rdev); + ret = kv_smc_bapm_enable(rdev, false); + if (ret) { + DRM_ERROR("kv_smc_bapm_enable failed\n"); + return ret; + } + + kv_update_current_ps(rdev, rdev->pm.dpm.boot_ps); + + return ret; +} + +int kv_dpm_late_enable(struct radeon_device *rdev) +{ + int ret; + if (rdev->irq.installed && r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) { ret = kv_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX); @@ -1226,35 +1236,17 @@ int kv_dpm_enable(struct radeon_device *rdev) radeon_irq_set(rdev); } - ret = kv_smc_bapm_enable(rdev, false); - if (ret) { - DRM_ERROR("kv_smc_bapm_enable failed\n"); - return ret; - } - /* powerdown unused blocks for now */ kv_dpm_powergate_acp(rdev, true); kv_dpm_powergate_samu(rdev, true); kv_dpm_powergate_vce(rdev, true); kv_dpm_powergate_uvd(rdev, true); - cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX | - RADEON_CG_BLOCK_SDMA | - RADEON_CG_BLOCK_BIF | - RADEON_CG_BLOCK_HDP), true); - - kv_update_current_ps(rdev, rdev->pm.dpm.boot_ps); - return ret; } void kv_dpm_disable(struct radeon_device *rdev) { - cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX | - RADEON_CG_BLOCK_SDMA | - RADEON_CG_BLOCK_BIF | - RADEON_CG_BLOCK_HDP), false); - kv_smc_bapm_enable(rdev, false); /* powerup blocks */ @@ -1779,11 +1771,6 @@ int kv_dpm_set_power_state(struct radeon_device *rdev) /*struct radeon_ps *old_ps = &pi->current_rps;*/ int ret; - cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX | - RADEON_CG_BLOCK_SDMA | - RADEON_CG_BLOCK_BIF | - RADEON_CG_BLOCK_HDP), false); - if (pi->bapm_enable) { ret = kv_smc_bapm_enable(rdev, rdev->pm.dpm.ac_power); if (ret) { @@ -1849,11 +1836,6 @@ int kv_dpm_set_power_state(struct radeon_device *rdev) } } - cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX | - RADEON_CG_BLOCK_SDMA | - RADEON_CG_BLOCK_BIF | - RADEON_CG_BLOCK_HDP), true); - return 0; } diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index f59a9e9fccf8..ea932ac66fc6 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -174,6 +174,7 @@ extern void evergreen_pcie_gen2_enable(struct radeon_device *rdev); extern void evergreen_program_aspm(struct radeon_device *rdev); extern void sumo_rlc_fini(struct radeon_device *rdev); extern int sumo_rlc_init(struct radeon_device *rdev); +extern void evergreen_gpu_pci_config_reset(struct radeon_device *rdev); /* Firmware Names */ MODULE_FIRMWARE("radeon/BARTS_pfp.bin"); @@ -1330,13 +1331,12 @@ void cayman_fence_ring_emit(struct radeon_device *rdev, { struct radeon_ring *ring = &rdev->ring[fence->ring]; u64 addr = rdev->fence_drv[fence->ring].gpu_addr; + u32 cp_coher_cntl = PACKET3_FULL_CACHE_ENA | PACKET3_TC_ACTION_ENA | + PACKET3_SH_ACTION_ENA; /* flush read cache over gart for this vmid */ - radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); - radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2); - radeon_ring_write(ring, 0); radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); - radeon_ring_write(ring, PACKET3_TC_ACTION_ENA | PACKET3_SH_ACTION_ENA); + radeon_ring_write(ring, PACKET3_ENGINE_ME | cp_coher_cntl); radeon_ring_write(ring, 0xFFFFFFFF); radeon_ring_write(ring, 0); radeon_ring_write(ring, 10); /* poll interval */ @@ -1352,6 +1352,8 @@ void cayman_fence_ring_emit(struct radeon_device *rdev, void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) { struct radeon_ring *ring = &rdev->ring[ib->ring]; + u32 cp_coher_cntl = PACKET3_FULL_CACHE_ENA | PACKET3_TC_ACTION_ENA | + PACKET3_SH_ACTION_ENA; /* set to DX10/11 mode */ radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0)); @@ -1376,14 +1378,11 @@ void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) (ib->vm ? (ib->vm->id << 24) : 0)); /* flush read cache over gart for this vmid */ - radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); - radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2); - radeon_ring_write(ring, ib->vm ? ib->vm->id : 0); radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); - radeon_ring_write(ring, PACKET3_TC_ACTION_ENA | PACKET3_SH_ACTION_ENA); + radeon_ring_write(ring, PACKET3_ENGINE_ME | cp_coher_cntl); radeon_ring_write(ring, 0xFFFFFFFF); radeon_ring_write(ring, 0); - radeon_ring_write(ring, 10); /* poll interval */ + radeon_ring_write(ring, ((ib->vm ? ib->vm->id : 0) << 24) | 10); /* poll interval */ } static void cayman_cp_enable(struct radeon_device *rdev, bool enable) @@ -1391,13 +1390,63 @@ static void cayman_cp_enable(struct radeon_device *rdev, bool enable) if (enable) WREG32(CP_ME_CNTL, 0); else { - radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); + if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX) + radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT)); WREG32(SCRATCH_UMSK, 0); rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; } } +u32 cayman_gfx_get_rptr(struct radeon_device *rdev, + struct radeon_ring *ring) +{ + u32 rptr; + + if (rdev->wb.enabled) + rptr = rdev->wb.wb[ring->rptr_offs/4]; + else { + if (ring->idx == RADEON_RING_TYPE_GFX_INDEX) + rptr = RREG32(CP_RB0_RPTR); + else if (ring->idx == CAYMAN_RING_TYPE_CP1_INDEX) + rptr = RREG32(CP_RB1_RPTR); + else + rptr = RREG32(CP_RB2_RPTR); + } + + return rptr; +} + +u32 cayman_gfx_get_wptr(struct radeon_device *rdev, + struct radeon_ring *ring) +{ + u32 wptr; + + if (ring->idx == RADEON_RING_TYPE_GFX_INDEX) + wptr = RREG32(CP_RB0_WPTR); + else if (ring->idx == CAYMAN_RING_TYPE_CP1_INDEX) + wptr = RREG32(CP_RB1_WPTR); + else + wptr = RREG32(CP_RB2_WPTR); + + return wptr; +} + +void cayman_gfx_set_wptr(struct radeon_device *rdev, + struct radeon_ring *ring) +{ + if (ring->idx == RADEON_RING_TYPE_GFX_INDEX) { + WREG32(CP_RB0_WPTR, ring->wptr); + (void)RREG32(CP_RB0_WPTR); + } else if (ring->idx == CAYMAN_RING_TYPE_CP1_INDEX) { + WREG32(CP_RB1_WPTR, ring->wptr); + (void)RREG32(CP_RB1_WPTR); + } else { + WREG32(CP_RB2_WPTR, ring->wptr); + (void)RREG32(CP_RB2_WPTR); + } +} + static int cayman_cp_load_microcode(struct radeon_device *rdev) { const __be32 *fw_data; @@ -1526,6 +1575,16 @@ static int cayman_cp_resume(struct radeon_device *rdev) CP_RB1_BASE, CP_RB2_BASE }; + static const unsigned cp_rb_rptr[] = { + CP_RB0_RPTR, + CP_RB1_RPTR, + CP_RB2_RPTR + }; + static const unsigned cp_rb_wptr[] = { + CP_RB0_WPTR, + CP_RB1_WPTR, + CP_RB2_WPTR + }; struct radeon_ring *ring; int i, r; @@ -1584,8 +1643,8 @@ static int cayman_cp_resume(struct radeon_device *rdev) WREG32_P(cp_rb_cntl[i], RB_RPTR_WR_ENA, ~RB_RPTR_WR_ENA); ring->rptr = ring->wptr = 0; - WREG32(ring->rptr_reg, ring->rptr); - WREG32(ring->wptr_reg, ring->wptr); + WREG32(cp_rb_rptr[i], ring->rptr); + WREG32(cp_rb_wptr[i], ring->wptr); mdelay(1); WREG32_P(cp_rb_cntl[i], 0, ~RB_RPTR_WR_ENA); @@ -1605,6 +1664,9 @@ static int cayman_cp_resume(struct radeon_device *rdev) return r; } + if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX) + radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); + return 0; } @@ -1831,8 +1893,10 @@ int cayman_asic_reset(struct radeon_device *rdev) reset_mask = cayman_gpu_check_soft_reset(rdev); - if (!reset_mask) - r600_set_bios_scratch_engine_hung(rdev, false); + if (reset_mask) + evergreen_gpu_pci_config_reset(rdev); + + r600_set_bios_scratch_engine_hung(rdev, false); return 0; } @@ -1878,23 +1942,7 @@ static int cayman_startup(struct radeon_device *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); - if (r) { - DRM_ERROR("Failed to load firmware!\n"); - return r; - } - } - } else { - if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) { - r = ni_init_microcode(rdev); - if (r) { - DRM_ERROR("Failed to load firmware!\n"); - return r; - } - } - + if (!(rdev->flags & RADEON_IS_IGP) && !rdev->pm.dpm_enabled) { r = ni_mc_load_microcode(rdev); if (r) { DRM_ERROR("Failed to load MC firmware!\n"); @@ -1981,23 +2029,18 @@ static int cayman_startup(struct radeon_device *rdev) evergreen_irq_set(rdev); r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET, - CP_RB0_RPTR, CP_RB0_WPTR, RADEON_CP_PACKET2); if (r) return r; ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX]; r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET, - DMA_RB_RPTR + DMA0_REGISTER_OFFSET, - DMA_RB_WPTR + DMA0_REGISTER_OFFSET, DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0)); if (r) return r; ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX]; r = radeon_ring_init(rdev, ring, ring->ring_size, CAYMAN_WB_DMA1_RPTR_OFFSET, - DMA_RB_RPTR + DMA1_REGISTER_OFFSET, - DMA_RB_WPTR + DMA1_REGISTER_OFFSET, DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0)); if (r) return r; @@ -2016,7 +2059,6 @@ static int cayman_startup(struct radeon_device *rdev) ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; if (ring->ring_size) { r = radeon_ring_init(rdev, ring, ring->ring_size, 0, - UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR, RADEON_CP_PACKET2); if (!r) r = uvd_v1_0_init(rdev); @@ -2063,6 +2105,8 @@ int cayman_resume(struct radeon_device *rdev) /* init golden registers */ ni_init_golden_registers(rdev); + radeon_pm_resume(rdev); + rdev->accel_working = true; r = cayman_startup(rdev); if (r) { @@ -2075,6 +2119,7 @@ int cayman_resume(struct radeon_device *rdev) int cayman_suspend(struct radeon_device *rdev) { + radeon_pm_suspend(rdev); if (ASIC_IS_DCE6(rdev)) dce6_audio_fini(rdev); else @@ -2145,6 +2190,27 @@ int cayman_init(struct radeon_device *rdev) if (r) return r; + if (rdev->flags & RADEON_IS_IGP) { + if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { + r = ni_init_microcode(rdev); + if (r) { + DRM_ERROR("Failed to load firmware!\n"); + return r; + } + } + } else { + if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) { + r = ni_init_microcode(rdev); + if (r) { + DRM_ERROR("Failed to load firmware!\n"); + return r; + } + } + } + + /* Initialize power management */ + radeon_pm_init(rdev); + ring->ring_obj = NULL; r600_ring_init(rdev, ring, 1024 * 1024); @@ -2204,6 +2270,7 @@ int cayman_init(struct radeon_device *rdev) void cayman_fini(struct radeon_device *rdev) { + radeon_pm_fini(rdev); cayman_cp_fini(rdev); cayman_dma_fini(rdev); r600_irq_fini(rdev); diff --git a/drivers/gpu/drm/radeon/ni_dma.c b/drivers/gpu/drm/radeon/ni_dma.c index bdeb65ed3658..7cf96b15377f 100644 --- a/drivers/gpu/drm/radeon/ni_dma.c +++ b/drivers/gpu/drm/radeon/ni_dma.c @@ -43,6 +43,75 @@ u32 cayman_gpu_check_soft_reset(struct radeon_device *rdev); */ /** + * cayman_dma_get_rptr - get the current read pointer + * + * @rdev: radeon_device pointer + * @ring: radeon ring pointer + * + * Get the current rptr from the hardware (cayman+). + */ +uint32_t cayman_dma_get_rptr(struct radeon_device *rdev, + struct radeon_ring *ring) +{ + u32 rptr, reg; + + if (rdev->wb.enabled) { + rptr = rdev->wb.wb[ring->rptr_offs/4]; + } else { + if (ring->idx == R600_RING_TYPE_DMA_INDEX) + reg = DMA_RB_RPTR + DMA0_REGISTER_OFFSET; + else + reg = DMA_RB_RPTR + DMA1_REGISTER_OFFSET; + + rptr = RREG32(reg); + } + + return (rptr & 0x3fffc) >> 2; +} + +/** + * cayman_dma_get_wptr - get the current write pointer + * + * @rdev: radeon_device pointer + * @ring: radeon ring pointer + * + * Get the current wptr from the hardware (cayman+). + */ +uint32_t cayman_dma_get_wptr(struct radeon_device *rdev, + struct radeon_ring *ring) +{ + u32 reg; + + if (ring->idx == R600_RING_TYPE_DMA_INDEX) + reg = DMA_RB_WPTR + DMA0_REGISTER_OFFSET; + else + reg = DMA_RB_WPTR + DMA1_REGISTER_OFFSET; + + return (RREG32(reg) & 0x3fffc) >> 2; +} + +/** + * cayman_dma_set_wptr - commit the write pointer + * + * @rdev: radeon_device pointer + * @ring: radeon ring pointer + * + * Write the wptr back to the hardware (cayman+). + */ +void cayman_dma_set_wptr(struct radeon_device *rdev, + struct radeon_ring *ring) +{ + u32 reg; + + if (ring->idx == R600_RING_TYPE_DMA_INDEX) + reg = DMA_RB_WPTR + DMA0_REGISTER_OFFSET; + else + reg = DMA_RB_WPTR + DMA1_REGISTER_OFFSET; + + WREG32(reg, (ring->wptr << 2) & 0x3fffc); +} + +/** * cayman_dma_ring_ib_execute - Schedule an IB on the DMA engine * * @rdev: radeon_device pointer @@ -88,7 +157,9 @@ void cayman_dma_stop(struct radeon_device *rdev) { u32 rb_cntl; - radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); + if ((rdev->asic->copy.copy_ring_index == R600_RING_TYPE_DMA_INDEX) || + (rdev->asic->copy.copy_ring_index == CAYMAN_RING_TYPE_DMA1_INDEX)) + radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); /* dma0 */ rb_cntl = RREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET); @@ -190,7 +261,9 @@ int cayman_dma_resume(struct radeon_device *rdev) } } - radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); + if ((rdev->asic->copy.copy_ring_index == R600_RING_TYPE_DMA_INDEX) || + (rdev->asic->copy.copy_ring_index == CAYMAN_RING_TYPE_DMA1_INDEX)) + radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); return 0; } diff --git a/drivers/gpu/drm/radeon/ni_dpm.c b/drivers/gpu/drm/radeon/ni_dpm.c index 49c4d48f54d6..c351226ecb31 100644 --- a/drivers/gpu/drm/radeon/ni_dpm.c +++ b/drivers/gpu/drm/radeon/ni_dpm.c @@ -720,6 +720,8 @@ static const u32 cayman_sysls_enable[] = struct rv7xx_power_info *rv770_get_pi(struct radeon_device *rdev); struct evergreen_power_info *evergreen_get_pi(struct radeon_device *rdev); +extern int ni_mc_load_microcode(struct radeon_device *rdev); + struct ni_power_info *ni_get_pi(struct radeon_device *rdev) { struct ni_power_info *pi = rdev->pm.dpm.priv; @@ -3565,7 +3567,11 @@ void ni_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev, void ni_dpm_setup_asic(struct radeon_device *rdev) { struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev); + int r; + r = ni_mc_load_microcode(rdev); + if (r) + DRM_ERROR("Failed to load MC firmware!\n"); ni_read_clock_registers(rdev); btc_read_arb_registers(rdev); rv770_get_memory_type(rdev); @@ -3710,21 +3716,6 @@ int ni_dpm_enable(struct radeon_device *rdev) if (eg_pi->ls_clock_gating) ni_ls_clockgating_enable(rdev, true); - if (rdev->irq.installed && - r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) { - PPSMC_Result result; - - ret = rv770_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, 0xff * 1000); - if (ret) - return ret; - rdev->irq.dpm_thermal = true; - radeon_irq_set(rdev); - result = rv770_send_msg_to_smc(rdev, PPSMC_MSG_EnableThermalInterrupt); - - if (result != PPSMC_Result_OK) - DRM_DEBUG_KMS("Could not enable thermal interrupts.\n"); - } - rv770_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true); ni_update_current_ps(rdev, boot_ps); diff --git a/drivers/gpu/drm/radeon/nid.h b/drivers/gpu/drm/radeon/nid.h index 22421bc80c0d..d996033c243e 100644 --- a/drivers/gpu/drm/radeon/nid.h +++ b/drivers/gpu/drm/radeon/nid.h @@ -1154,6 +1154,7 @@ # define PACKET3_DB_ACTION_ENA (1 << 26) # define PACKET3_SH_ACTION_ENA (1 << 27) # define PACKET3_SX_ACTION_ENA (1 << 28) +# define PACKET3_ENGINE_ME (1 << 31) #define PACKET3_ME_INITIALIZE 0x44 #define PACKET3_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16) #define PACKET3_COND_WRITE 0x45 diff --git a/drivers/gpu/drm/radeon/pptable.h b/drivers/gpu/drm/radeon/pptable.h index da43ab328833..2d532996c697 100644 --- a/drivers/gpu/drm/radeon/pptable.h +++ b/drivers/gpu/drm/radeon/pptable.h @@ -23,7 +23,7 @@ #ifndef _PPTABLE_H #define _PPTABLE_H -#pragma pack(push, 1) +#pragma pack(1) typedef struct _ATOM_PPLIB_THERMALCONTROLLER @@ -677,6 +677,6 @@ typedef struct _ATOM_PPLIB_PPM_Table ULONG ulTjmax; } ATOM_PPLIB_PPM_Table; -#pragma pack(pop) +#pragma pack() #endif diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 10abc4d5a6cc..ef024ce3f7cc 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -1050,6 +1050,36 @@ static int r100_cp_init_microcode(struct radeon_device *rdev) return err; } +u32 r100_gfx_get_rptr(struct radeon_device *rdev, + struct radeon_ring *ring) +{ + u32 rptr; + + if (rdev->wb.enabled) + rptr = le32_to_cpu(rdev->wb.wb[ring->rptr_offs/4]); + else + rptr = RREG32(RADEON_CP_RB_RPTR); + + return rptr; +} + +u32 r100_gfx_get_wptr(struct radeon_device *rdev, + struct radeon_ring *ring) +{ + u32 wptr; + + wptr = RREG32(RADEON_CP_RB_WPTR); + + return wptr; +} + +void r100_gfx_set_wptr(struct radeon_device *rdev, + struct radeon_ring *ring) +{ + WREG32(RADEON_CP_RB_WPTR, ring->wptr); + (void)RREG32(RADEON_CP_RB_WPTR); +} + static void r100_cp_load_microcode(struct radeon_device *rdev) { const __be32 *fw_data; @@ -1102,7 +1132,6 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size) ring_size = (1 << (rb_bufsz + 1)) * 4; r100_cp_load_microcode(rdev); r = radeon_ring_init(rdev, ring, ring_size, RADEON_WB_CP_RPTR_OFFSET, - RADEON_CP_RB_RPTR, RADEON_CP_RB_WPTR, RADEON_CP_PACKET2); if (r) { return r; @@ -3913,6 +3942,8 @@ int r100_resume(struct radeon_device *rdev) /* Initialize surface registers */ radeon_surface_init(rdev); + radeon_pm_resume(rdev); + rdev->accel_working = true; r = r100_startup(rdev); if (r) { @@ -3923,6 +3954,7 @@ int r100_resume(struct radeon_device *rdev) int r100_suspend(struct radeon_device *rdev) { + radeon_pm_suspend(rdev); r100_cp_disable(rdev); radeon_wb_disable(rdev); r100_irq_disable(rdev); @@ -3933,6 +3965,7 @@ int r100_suspend(struct radeon_device *rdev) void r100_fini(struct radeon_device *rdev) { + radeon_pm_fini(rdev); r100_cp_fini(rdev); radeon_wb_fini(rdev); radeon_ib_pool_fini(rdev); @@ -4039,6 +4072,9 @@ int r100_init(struct radeon_device *rdev) } r100_set_safe_registers(rdev); + /* Initialize power management */ + radeon_pm_init(rdev); + rdev->accel_working = true; r = r100_startup(rdev); if (r) { diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index d8dd269b9159..7c63ef840e86 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -1430,6 +1430,8 @@ int r300_resume(struct radeon_device *rdev) /* Initialize surface registers */ radeon_surface_init(rdev); + radeon_pm_resume(rdev); + rdev->accel_working = true; r = r300_startup(rdev); if (r) { @@ -1440,6 +1442,7 @@ int r300_resume(struct radeon_device *rdev) int r300_suspend(struct radeon_device *rdev) { + radeon_pm_suspend(rdev); r100_cp_disable(rdev); radeon_wb_disable(rdev); r100_irq_disable(rdev); @@ -1452,6 +1455,7 @@ int r300_suspend(struct radeon_device *rdev) void r300_fini(struct radeon_device *rdev) { + radeon_pm_fini(rdev); r100_cp_fini(rdev); radeon_wb_fini(rdev); radeon_ib_pool_fini(rdev); @@ -1538,6 +1542,9 @@ int r300_init(struct radeon_device *rdev) } r300_set_reg_safe(rdev); + /* Initialize power management */ + radeon_pm_init(rdev); + rdev->accel_working = true; r = r300_startup(rdev); if (r) { diff --git a/drivers/gpu/drm/radeon/r300_cmdbuf.c b/drivers/gpu/drm/radeon/r300_cmdbuf.c index 60170ea5e3a2..84b1d5367a11 100644 --- a/drivers/gpu/drm/radeon/r300_cmdbuf.c +++ b/drivers/gpu/drm/radeon/r300_cmdbuf.c @@ -75,7 +75,7 @@ static int r300_emit_cliprects(drm_radeon_private_t *dev_priv, OUT_RING(CP_PACKET0(R300_RE_CLIPRECT_TL_0, nr * 2 - 1)); for (i = 0; i < nr; ++i) { - if (DRM_COPY_FROM_USER + if (copy_from_user (&box, &cmdbuf->boxes[n + i], sizeof(box))) { DRM_ERROR("copy cliprect faulted\n"); return -EFAULT; @@ -928,12 +928,12 @@ static int r300_scratch(drm_radeon_private_t *dev_priv, buf_idx = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0); *buf_idx *= 2; /* 8 bytes per buf */ - if (DRM_COPY_TO_USER(ref_age_base + *buf_idx, + if (copy_to_user(ref_age_base + *buf_idx, &dev_priv->scratch_ages[header.scratch.reg], sizeof(u32))) return -EINVAL; - if (DRM_COPY_FROM_USER(&h_pending, + if (copy_from_user(&h_pending, ref_age_base + *buf_idx + 1, sizeof(u32))) return -EINVAL; @@ -943,7 +943,7 @@ static int r300_scratch(drm_radeon_private_t *dev_priv, h_pending--; - if (DRM_COPY_TO_USER(ref_age_base + *buf_idx + 1, + if (copy_to_user(ref_age_base + *buf_idx + 1, &h_pending, sizeof(u32))) return -EINVAL; diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index 6edf2b3a52b4..3768aab2710b 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c @@ -325,6 +325,8 @@ int r420_resume(struct radeon_device *rdev) /* Initialize surface registers */ radeon_surface_init(rdev); + radeon_pm_resume(rdev); + rdev->accel_working = true; r = r420_startup(rdev); if (r) { @@ -335,6 +337,7 @@ int r420_resume(struct radeon_device *rdev) int r420_suspend(struct radeon_device *rdev) { + radeon_pm_suspend(rdev); r420_cp_errata_fini(rdev); r100_cp_disable(rdev); radeon_wb_disable(rdev); @@ -348,6 +351,7 @@ int r420_suspend(struct radeon_device *rdev) void r420_fini(struct radeon_device *rdev) { + radeon_pm_fini(rdev); r100_cp_fini(rdev); radeon_wb_fini(rdev); radeon_ib_pool_fini(rdev); @@ -444,6 +448,9 @@ int r420_init(struct radeon_device *rdev) } r420_set_reg_safe(rdev); + /* Initialize power management */ + radeon_pm_init(rdev); + rdev->accel_working = true; r = r420_startup(rdev); if (r) { diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c index e1aece73b370..e209eb75024f 100644 --- a/drivers/gpu/drm/radeon/r520.c +++ b/drivers/gpu/drm/radeon/r520.c @@ -240,6 +240,8 @@ int r520_resume(struct radeon_device *rdev) /* Initialize surface registers */ radeon_surface_init(rdev); + radeon_pm_resume(rdev); + rdev->accel_working = true; r = r520_startup(rdev); if (r) { @@ -312,6 +314,9 @@ int r520_init(struct radeon_device *rdev) return r; rv515_set_safe_registers(rdev); + /* Initialize power management */ + radeon_pm_init(rdev); + rdev->accel_working = true; r = r520_startup(rdev); if (r) { diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 9ad06732a78b..56140b4e5bb2 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -105,6 +105,7 @@ void r600_fini(struct radeon_device *rdev); void r600_irq_disable(struct radeon_device *rdev); static void r600_pcie_gen2_enable(struct radeon_device *rdev); extern int evergreen_rlc_resume(struct radeon_device *rdev); +extern void rv770_set_clk_bypass_mode(struct radeon_device *rdev); /** * r600_get_xclk - get the xclk @@ -1644,6 +1645,67 @@ static void r600_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) r600_print_gpu_status_regs(rdev); } +static void r600_gpu_pci_config_reset(struct radeon_device *rdev) +{ + struct rv515_mc_save save; + u32 tmp, i; + + dev_info(rdev->dev, "GPU pci config reset\n"); + + /* disable dpm? */ + + /* Disable CP parsing/prefetching */ + if (rdev->family >= CHIP_RV770) + WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1) | S_0086D8_CP_PFP_HALT(1)); + else + WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1)); + + /* disable the RLC */ + WREG32(RLC_CNTL, 0); + + /* Disable DMA */ + tmp = RREG32(DMA_RB_CNTL); + tmp &= ~DMA_RB_ENABLE; + WREG32(DMA_RB_CNTL, tmp); + + mdelay(50); + + /* set mclk/sclk to bypass */ + if (rdev->family >= CHIP_RV770) + rv770_set_clk_bypass_mode(rdev); + /* disable BM */ + pci_clear_master(rdev->pdev); + /* disable mem access */ + rv515_mc_stop(rdev, &save); + if (r600_mc_wait_for_idle(rdev)) { + dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); + } + + /* BIF reset workaround. Not sure if this is needed on 6xx */ + tmp = RREG32(BUS_CNTL); + tmp |= VGA_COHE_SPEC_TIMER_DIS; + WREG32(BUS_CNTL, tmp); + + tmp = RREG32(BIF_SCRATCH0); + + /* reset */ + radeon_pci_config_reset(rdev); + mdelay(1); + + /* BIF reset workaround. Not sure if this is needed on 6xx */ + tmp = SOFT_RESET_BIF; + WREG32(SRBM_SOFT_RESET, tmp); + mdelay(1); + WREG32(SRBM_SOFT_RESET, 0); + + /* wait for asic to come out of reset */ + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(CONFIG_MEMSIZE) != 0xffffffff) + break; + udelay(1); + } +} + int r600_asic_reset(struct radeon_device *rdev) { u32 reset_mask; @@ -1653,10 +1715,17 @@ int r600_asic_reset(struct radeon_device *rdev) if (reset_mask) r600_set_bios_scratch_engine_hung(rdev, true); + /* try soft reset */ r600_gpu_soft_reset(rdev, reset_mask); reset_mask = r600_gpu_check_soft_reset(rdev); + /* try pci config reset */ + if (reset_mask && radeon_hard_reset) + r600_gpu_pci_config_reset(rdev); + + reset_mask = r600_gpu_check_soft_reset(rdev); + if (!reset_mask) r600_set_bios_scratch_engine_hung(rdev, false); @@ -2185,7 +2254,8 @@ void r600_pciep_wreg(struct radeon_device *rdev, u32 reg, u32 v) */ void r600_cp_stop(struct radeon_device *rdev) { - radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); + if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX) + radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1)); WREG32(SCRATCH_UMSK, 0); rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; @@ -2382,6 +2452,36 @@ out: return err; } +u32 r600_gfx_get_rptr(struct radeon_device *rdev, + struct radeon_ring *ring) +{ + u32 rptr; + + if (rdev->wb.enabled) + rptr = rdev->wb.wb[ring->rptr_offs/4]; + else + rptr = RREG32(R600_CP_RB_RPTR); + + return rptr; +} + +u32 r600_gfx_get_wptr(struct radeon_device *rdev, + struct radeon_ring *ring) +{ + u32 wptr; + + wptr = RREG32(R600_CP_RB_WPTR); + + return wptr; +} + +void r600_gfx_set_wptr(struct radeon_device *rdev, + struct radeon_ring *ring) +{ + WREG32(R600_CP_RB_WPTR, ring->wptr); + (void)RREG32(R600_CP_RB_WPTR); +} + static int r600_cp_load_microcode(struct radeon_device *rdev) { const __be32 *fw_data; @@ -2513,6 +2613,10 @@ int r600_cp_resume(struct radeon_device *rdev) ring->ready = false; return r; } + + if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX) + radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); + return 0; } @@ -2607,14 +2711,17 @@ void r600_fence_ring_emit(struct radeon_device *rdev, struct radeon_fence *fence) { struct radeon_ring *ring = &rdev->ring[fence->ring]; + u32 cp_coher_cntl = PACKET3_TC_ACTION_ENA | PACKET3_VC_ACTION_ENA | + PACKET3_SH_ACTION_ENA; + + if (rdev->family >= CHIP_RV770) + cp_coher_cntl |= PACKET3_FULL_CACHE_ENA; if (rdev->wb.use_event) { u64 addr = rdev->fence_drv[fence->ring].gpu_addr; /* flush read cache over gart */ radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); - radeon_ring_write(ring, PACKET3_TC_ACTION_ENA | - PACKET3_VC_ACTION_ENA | - PACKET3_SH_ACTION_ENA); + radeon_ring_write(ring, cp_coher_cntl); radeon_ring_write(ring, 0xFFFFFFFF); radeon_ring_write(ring, 0); radeon_ring_write(ring, 10); /* poll interval */ @@ -2628,9 +2735,7 @@ void r600_fence_ring_emit(struct radeon_device *rdev, } else { /* flush read cache over gart */ radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); - radeon_ring_write(ring, PACKET3_TC_ACTION_ENA | - PACKET3_VC_ACTION_ENA | - PACKET3_SH_ACTION_ENA); + radeon_ring_write(ring, cp_coher_cntl); radeon_ring_write(ring, 0xFFFFFFFF); radeon_ring_write(ring, 0); radeon_ring_write(ring, 10); /* poll interval */ @@ -2775,14 +2880,6 @@ static int r600_startup(struct radeon_device *rdev) r600_mc_program(rdev); - if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { - r = r600_init_microcode(rdev); - if (r) { - DRM_ERROR("Failed to load firmware!\n"); - return r; - } - } - if (rdev->flags & RADEON_IS_AGP) { r600_agp_enable(rdev); } else { @@ -2803,12 +2900,6 @@ static int r600_startup(struct radeon_device *rdev) return r; } - r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_DMA_INDEX); - if (r) { - dev_err(rdev->dev, "failed initializing DMA fences (%d).\n", r); - return r; - } - /* Enable IRQ */ if (!rdev->irq.installed) { r = radeon_irq_kms_init(rdev); @@ -2826,18 +2917,10 @@ static int r600_startup(struct radeon_device *rdev) ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET, - R600_CP_RB_RPTR, R600_CP_RB_WPTR, RADEON_CP_PACKET2); if (r) return r; - ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX]; - r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET, - DMA_RB_RPTR, DMA_RB_WPTR, - DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0)); - if (r) - return r; - r = r600_cp_load_microcode(rdev); if (r) return r; @@ -2845,10 +2928,6 @@ static int r600_startup(struct radeon_device *rdev) if (r) return r; - r = r600_dma_resume(rdev); - if (r) - return r; - r = radeon_ib_pool_init(rdev); if (r) { dev_err(rdev->dev, "IB initialization failed (%d).\n", r); @@ -2889,6 +2968,8 @@ int r600_resume(struct radeon_device *rdev) /* post card */ atom_asic_init(rdev->mode_info.atom_context); + radeon_pm_resume(rdev); + rdev->accel_working = true; r = r600_startup(rdev); if (r) { @@ -2902,9 +2983,9 @@ int r600_resume(struct radeon_device *rdev) int r600_suspend(struct radeon_device *rdev) { + radeon_pm_suspend(rdev); r600_audio_fini(rdev); r600_cp_stop(rdev); - r600_dma_stop(rdev); r600_irq_suspend(rdev); radeon_wb_disable(rdev); r600_pcie_gart_disable(rdev); @@ -2970,12 +3051,20 @@ int r600_init(struct radeon_device *rdev) if (r) return r; + if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { + r = r600_init_microcode(rdev); + if (r) { + DRM_ERROR("Failed to load firmware!\n"); + return r; + } + } + + /* Initialize power management */ + radeon_pm_init(rdev); + rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL; r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024); - rdev->ring[R600_RING_TYPE_DMA_INDEX].ring_obj = NULL; - r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX], 64 * 1024); - rdev->ih.ring_obj = NULL; r600_ih_ring_init(rdev, 64 * 1024); @@ -2988,7 +3077,6 @@ int r600_init(struct radeon_device *rdev) if (r) { dev_err(rdev->dev, "disabling GPU acceleration\n"); r600_cp_fini(rdev); - r600_dma_fini(rdev); r600_irq_fini(rdev); radeon_wb_fini(rdev); radeon_ib_pool_fini(rdev); @@ -3002,9 +3090,9 @@ int r600_init(struct radeon_device *rdev) void r600_fini(struct radeon_device *rdev) { + radeon_pm_fini(rdev); r600_audio_fini(rdev); r600_cp_fini(rdev); - r600_dma_fini(rdev); r600_irq_fini(rdev); radeon_wb_fini(rdev); radeon_ib_pool_fini(rdev); diff --git a/drivers/gpu/drm/radeon/r600_cp.c b/drivers/gpu/drm/radeon/r600_cp.c index d8eb48bff0ed..8c9b7e26533c 100644 --- a/drivers/gpu/drm/radeon/r600_cp.c +++ b/drivers/gpu/drm/radeon/r600_cp.c @@ -2515,7 +2515,7 @@ int r600_cp_dispatch_texture(struct drm_device *dev, buf = radeon_freelist_get(dev); if (!buf) { DRM_DEBUG("EAGAIN\n"); - if (DRM_COPY_TO_USER(tex->image, image, sizeof(*image))) + if (copy_to_user(tex->image, image, sizeof(*image))) return -EFAULT; return -EAGAIN; } @@ -2528,7 +2528,7 @@ int r600_cp_dispatch_texture(struct drm_device *dev, buffer = (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset); - if (DRM_COPY_FROM_USER(buffer, data, pass_size)) { + if (copy_from_user(buffer, data, pass_size)) { DRM_ERROR("EFAULT on pad, %d bytes\n", pass_size); return -EFAULT; } diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 5dceea6f71ae..7b399dc5fd54 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -749,7 +749,10 @@ static int r600_cs_track_check(struct radeon_cs_parser *p) } for (i = 0; i < 8; i++) { - if ((tmp >> (i * 4)) & 0xF) { + u32 format = G_0280A0_FORMAT(track->cb_color_info[i]); + + if (format != V_0280A0_COLOR_INVALID && + (tmp >> (i * 4)) & 0xF) { /* at least one component is enabled */ if (track->cb_color_bo[i] == NULL) { dev_warn(p->dev, "%s:%d mask 0x%08X | 0x%08X no cb for %d\n", @@ -2386,7 +2389,7 @@ int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp, ib_chunk = &parser.chunks[parser.chunk_ib_idx]; parser.ib.length_dw = ib_chunk->length_dw; *l = parser.ib.length_dw; - if (DRM_COPY_FROM_USER(ib, ib_chunk->user_ptr, ib_chunk->length_dw * 4)) { + if (copy_from_user(ib, ib_chunk->user_ptr, ib_chunk->length_dw * 4)) { r = -EFAULT; r600_cs_parser_fini(&parser, r); return r; diff --git a/drivers/gpu/drm/radeon/r600_dma.c b/drivers/gpu/drm/radeon/r600_dma.c index 7844d15c139f..b2d4c91e6272 100644 --- a/drivers/gpu/drm/radeon/r600_dma.c +++ b/drivers/gpu/drm/radeon/r600_dma.c @@ -51,7 +51,14 @@ u32 r600_gpu_check_soft_reset(struct radeon_device *rdev); uint32_t r600_dma_get_rptr(struct radeon_device *rdev, struct radeon_ring *ring) { - return (radeon_ring_generic_get_rptr(rdev, ring) & 0x3fffc) >> 2; + u32 rptr; + + if (rdev->wb.enabled) + rptr = rdev->wb.wb[ring->rptr_offs/4]; + else + rptr = RREG32(DMA_RB_RPTR); + + return (rptr & 0x3fffc) >> 2; } /** @@ -65,7 +72,7 @@ uint32_t r600_dma_get_rptr(struct radeon_device *rdev, uint32_t r600_dma_get_wptr(struct radeon_device *rdev, struct radeon_ring *ring) { - return (RREG32(ring->wptr_reg) & 0x3fffc) >> 2; + return (RREG32(DMA_RB_WPTR) & 0x3fffc) >> 2; } /** @@ -79,7 +86,7 @@ uint32_t r600_dma_get_wptr(struct radeon_device *rdev, void r600_dma_set_wptr(struct radeon_device *rdev, struct radeon_ring *ring) { - WREG32(ring->wptr_reg, (ring->wptr << 2) & 0x3fffc); + WREG32(DMA_RB_WPTR, (ring->wptr << 2) & 0x3fffc); } /** @@ -93,7 +100,8 @@ void r600_dma_stop(struct radeon_device *rdev) { u32 rb_cntl = RREG32(DMA_RB_CNTL); - radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); + if (rdev->asic->copy.copy_ring_index == R600_RING_TYPE_DMA_INDEX) + radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); rb_cntl &= ~DMA_RB_ENABLE; WREG32(DMA_RB_CNTL, rb_cntl); @@ -180,7 +188,8 @@ int r600_dma_resume(struct radeon_device *rdev) return r; } - radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); + if (rdev->asic->copy.copy_ring_index == R600_RING_TYPE_DMA_INDEX) + radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); return 0; } diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c index 5513d8f06252..e4cc9b314ce9 100644 --- a/drivers/gpu/drm/radeon/r600_dpm.c +++ b/drivers/gpu/drm/radeon/r600_dpm.c @@ -729,8 +729,8 @@ bool r600_is_uvd_state(u32 class, u32 class2) return false; } -int r600_set_thermal_temperature_range(struct radeon_device *rdev, - int min_temp, int max_temp) +static int r600_set_thermal_temperature_range(struct radeon_device *rdev, + int min_temp, int max_temp) { int low_temp = 0 * 1000; int high_temp = 255 * 1000; @@ -777,6 +777,22 @@ bool r600_is_internal_thermal_sensor(enum radeon_int_thermal_type sensor) } } +int r600_dpm_late_enable(struct radeon_device *rdev) +{ + int ret; + + if (rdev->irq.installed && + r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) { + ret = r600_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX); + if (ret) + return ret; + rdev->irq.dpm_thermal = true; + radeon_irq_set(rdev); + } + + return 0; +} + union power_info { struct _ATOM_POWERPLAY_INFO info; struct _ATOM_POWERPLAY_INFO_V2 info_2; diff --git a/drivers/gpu/drm/radeon/r600_dpm.h b/drivers/gpu/drm/radeon/r600_dpm.h index 1000bf9719f2..07eab2b04e81 100644 --- a/drivers/gpu/drm/radeon/r600_dpm.h +++ b/drivers/gpu/drm/radeon/r600_dpm.h @@ -213,8 +213,6 @@ void r600_wait_for_power_level(struct radeon_device *rdev, void r600_start_dpm(struct radeon_device *rdev); void r600_stop_dpm(struct radeon_device *rdev); -int r600_set_thermal_temperature_range(struct radeon_device *rdev, - int min_temp, int max_temp); bool r600_is_internal_thermal_sensor(enum radeon_int_thermal_type sensor); int r600_parse_extended_power_table(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index b7d3ecba43e3..3016fc14f502 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c @@ -250,7 +250,7 @@ static void r600_hdmi_audio_workaround(struct drm_encoder *encoder) value, ~HDMI0_AUDIO_TEST_EN); } -void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock) +static void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock) { struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index ebe38724a976..37455f65107f 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -701,11 +701,18 @@ #define RLC_UCODE_DATA 0x3f30 #define SRBM_SOFT_RESET 0xe60 +# define SOFT_RESET_BIF (1 << 1) # define SOFT_RESET_DMA (1 << 12) # define SOFT_RESET_RLC (1 << 13) # define SOFT_RESET_UVD (1 << 18) # define RV770_SOFT_RESET_DMA (1 << 20) +#define BIF_SCRATCH0 0x5438 + +#define BUS_CNTL 0x5420 +# define BIOS_ROM_DIS (1 << 1) +# define VGA_COHE_SPEC_TIMER_DIS (1 << 9) + #define CP_INT_CNTL 0xc124 # define CNTX_BUSY_INT_ENABLE (1 << 19) # define CNTX_EMPTY_INT_ENABLE (1 << 20) @@ -1575,6 +1582,7 @@ # define PACKET3_CP_DMA_CMD_DAIC (1 << 29) #define PACKET3_SURFACE_SYNC 0x43 # define PACKET3_CB0_DEST_BASE_ENA (1 << 6) +# define PACKET3_FULL_CACHE_ENA (1 << 20) /* r7xx+ only */ # define PACKET3_TC_ACTION_ENA (1 << 23) # define PACKET3_VC_ACTION_ENA (1 << 24) # define PACKET3_CB_ACTION_ENA (1 << 25) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 45e1f447bc79..4a8ac1cd6b4c 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -99,6 +99,7 @@ extern int radeon_fastfb; extern int radeon_dpm; extern int radeon_aspm; extern int radeon_runtime_pm; +extern int radeon_hard_reset; /* * Copy from radeon_drv.h so we don't have to include both and have conflicting @@ -139,6 +140,9 @@ extern int radeon_runtime_pm; #define RADEON_VA_RESERVED_SIZE (8 << 20) #define RADEON_IB_VM_MAX_SIZE (64 << 10) +/* hard reset data */ +#define RADEON_ASIC_RESET_DATA 0x39d5e86b + /* reset flags */ #define RADEON_RESET_GFX (1 << 0) #define RADEON_RESET_COMPUTE (1 << 1) @@ -252,6 +256,7 @@ struct radeon_clock { * Power management */ int radeon_pm_init(struct radeon_device *rdev); +int radeon_pm_late_init(struct radeon_device *rdev); void radeon_pm_fini(struct radeon_device *rdev); void radeon_pm_compute_clocks(struct radeon_device *rdev); void radeon_pm_suspend(struct radeon_device *rdev); @@ -413,6 +418,11 @@ struct radeon_mman { struct ttm_bo_device bdev; bool mem_global_referenced; bool initialized; + +#if defined(CONFIG_DEBUG_FS) + struct dentry *vram; + struct dentry *gtt; +#endif }; /* bo virtual address in a specific vm */ @@ -779,13 +789,11 @@ struct radeon_ring { volatile uint32_t *ring; unsigned rptr; unsigned rptr_offs; - unsigned rptr_reg; unsigned rptr_save_reg; u64 next_rptr_gpu_addr; volatile u32 *next_rptr_cpu_addr; unsigned wptr; unsigned wptr_old; - unsigned wptr_reg; unsigned ring_size; unsigned ring_free_dw; int count_dw; @@ -859,6 +867,8 @@ struct radeon_vm { struct radeon_fence *fence; /* last flush or NULL if we still need to flush */ struct radeon_fence *last_flush; + /* last use of vmid */ + struct radeon_fence *last_id_use; }; struct radeon_vm_manager { @@ -949,7 +959,7 @@ unsigned radeon_ring_backup(struct radeon_device *rdev, struct radeon_ring *ring int radeon_ring_restore(struct radeon_device *rdev, struct radeon_ring *ring, unsigned size, uint32_t *data); int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ring_size, - unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg, u32 nop); + unsigned rptr_offs, u32 nop); void radeon_ring_fini(struct radeon_device *rdev, struct radeon_ring *cp); @@ -1775,6 +1785,7 @@ struct radeon_asic { int (*init)(struct radeon_device *rdev); void (*setup_asic)(struct radeon_device *rdev); int (*enable)(struct radeon_device *rdev); + int (*late_enable)(struct radeon_device *rdev); void (*disable)(struct radeon_device *rdev); int (*pre_set_power_state)(struct radeon_device *rdev); int (*set_power_state)(struct radeon_device *rdev); @@ -2650,6 +2661,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v); #define radeon_dpm_init(rdev) rdev->asic->dpm.init((rdev)) #define radeon_dpm_setup_asic(rdev) rdev->asic->dpm.setup_asic((rdev)) #define radeon_dpm_enable(rdev) rdev->asic->dpm.enable((rdev)) +#define radeon_dpm_late_enable(rdev) rdev->asic->dpm.late_enable((rdev)) #define radeon_dpm_disable(rdev) rdev->asic->dpm.disable((rdev)) #define radeon_dpm_pre_set_power_state(rdev) rdev->asic->dpm.pre_set_power_state((rdev)) #define radeon_dpm_set_power_state(rdev) rdev->asic->dpm.set_power_state((rdev)) @@ -2668,6 +2680,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v); /* Common functions */ /* AGP */ extern int radeon_gpu_reset(struct radeon_device *rdev); +extern void radeon_pci_config_reset(struct radeon_device *rdev); extern void r600_set_bios_scratch_engine_hung(struct radeon_device *rdev, bool hung); extern void radeon_agp_disable(struct radeon_device *rdev); extern int radeon_modeset_init(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index c0425bb6223a..f74db43346fd 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -182,9 +182,9 @@ static struct radeon_asic_ring r100_gfx_ring = { .ring_test = &r100_ring_test, .ib_test = &r100_ib_test, .is_lockup = &r100_gpu_is_lockup, - .get_rptr = &radeon_ring_generic_get_rptr, - .get_wptr = &radeon_ring_generic_get_wptr, - .set_wptr = &radeon_ring_generic_set_wptr, + .get_rptr = &r100_gfx_get_rptr, + .get_wptr = &r100_gfx_get_wptr, + .set_wptr = &r100_gfx_set_wptr, }; static struct radeon_asic r100_asic = { @@ -330,9 +330,9 @@ static struct radeon_asic_ring r300_gfx_ring = { .ring_test = &r100_ring_test, .ib_test = &r100_ib_test, .is_lockup = &r100_gpu_is_lockup, - .get_rptr = &radeon_ring_generic_get_rptr, - .get_wptr = &radeon_ring_generic_get_wptr, - .set_wptr = &radeon_ring_generic_set_wptr, + .get_rptr = &r100_gfx_get_rptr, + .get_wptr = &r100_gfx_get_wptr, + .set_wptr = &r100_gfx_set_wptr, }; static struct radeon_asic r300_asic = { @@ -883,9 +883,9 @@ static struct radeon_asic_ring r600_gfx_ring = { .ring_test = &r600_ring_test, .ib_test = &r600_ib_test, .is_lockup = &r600_gfx_is_lockup, - .get_rptr = &radeon_ring_generic_get_rptr, - .get_wptr = &radeon_ring_generic_get_wptr, - .set_wptr = &radeon_ring_generic_set_wptr, + .get_rptr = &r600_gfx_get_rptr, + .get_wptr = &r600_gfx_get_wptr, + .set_wptr = &r600_gfx_set_wptr, }; static struct radeon_asic_ring r600_dma_ring = { @@ -1045,6 +1045,7 @@ static struct radeon_asic rv6xx_asic = { .init = &rv6xx_dpm_init, .setup_asic = &rv6xx_setup_asic, .enable = &rv6xx_dpm_enable, + .late_enable = &r600_dpm_late_enable, .disable = &rv6xx_dpm_disable, .pre_set_power_state = &r600_dpm_pre_set_power_state, .set_power_state = &rv6xx_dpm_set_power_state, @@ -1135,6 +1136,7 @@ static struct radeon_asic rs780_asic = { .init = &rs780_dpm_init, .setup_asic = &rs780_dpm_setup_asic, .enable = &rs780_dpm_enable, + .late_enable = &r600_dpm_late_enable, .disable = &rs780_dpm_disable, .pre_set_power_state = &r600_dpm_pre_set_power_state, .set_power_state = &rs780_dpm_set_power_state, @@ -1239,6 +1241,7 @@ static struct radeon_asic rv770_asic = { .init = &rv770_dpm_init, .setup_asic = &rv770_dpm_setup_asic, .enable = &rv770_dpm_enable, + .late_enable = &rv770_dpm_late_enable, .disable = &rv770_dpm_disable, .pre_set_power_state = &r600_dpm_pre_set_power_state, .set_power_state = &rv770_dpm_set_power_state, @@ -1267,9 +1270,9 @@ static struct radeon_asic_ring evergreen_gfx_ring = { .ring_test = &r600_ring_test, .ib_test = &r600_ib_test, .is_lockup = &evergreen_gfx_is_lockup, - .get_rptr = &radeon_ring_generic_get_rptr, - .get_wptr = &radeon_ring_generic_get_wptr, - .set_wptr = &radeon_ring_generic_set_wptr, + .get_rptr = &r600_gfx_get_rptr, + .get_wptr = &r600_gfx_get_wptr, + .set_wptr = &r600_gfx_set_wptr, }; static struct radeon_asic_ring evergreen_dma_ring = { @@ -1357,6 +1360,7 @@ static struct radeon_asic evergreen_asic = { .init = &cypress_dpm_init, .setup_asic = &cypress_dpm_setup_asic, .enable = &cypress_dpm_enable, + .late_enable = &rv770_dpm_late_enable, .disable = &cypress_dpm_disable, .pre_set_power_state = &r600_dpm_pre_set_power_state, .set_power_state = &cypress_dpm_set_power_state, @@ -1449,6 +1453,7 @@ static struct radeon_asic sumo_asic = { .init = &sumo_dpm_init, .setup_asic = &sumo_dpm_setup_asic, .enable = &sumo_dpm_enable, + .late_enable = &sumo_dpm_late_enable, .disable = &sumo_dpm_disable, .pre_set_power_state = &sumo_dpm_pre_set_power_state, .set_power_state = &sumo_dpm_set_power_state, @@ -1540,6 +1545,7 @@ static struct radeon_asic btc_asic = { .init = &btc_dpm_init, .setup_asic = &btc_dpm_setup_asic, .enable = &btc_dpm_enable, + .late_enable = &rv770_dpm_late_enable, .disable = &btc_dpm_disable, .pre_set_power_state = &btc_dpm_pre_set_power_state, .set_power_state = &btc_dpm_set_power_state, @@ -1570,9 +1576,9 @@ static struct radeon_asic_ring cayman_gfx_ring = { .ib_test = &r600_ib_test, .is_lockup = &cayman_gfx_is_lockup, .vm_flush = &cayman_vm_flush, - .get_rptr = &radeon_ring_generic_get_rptr, - .get_wptr = &radeon_ring_generic_get_wptr, - .set_wptr = &radeon_ring_generic_set_wptr, + .get_rptr = &cayman_gfx_get_rptr, + .get_wptr = &cayman_gfx_get_wptr, + .set_wptr = &cayman_gfx_set_wptr, }; static struct radeon_asic_ring cayman_dma_ring = { @@ -1585,9 +1591,9 @@ static struct radeon_asic_ring cayman_dma_ring = { .ib_test = &r600_dma_ib_test, .is_lockup = &cayman_dma_is_lockup, .vm_flush = &cayman_dma_vm_flush, - .get_rptr = &r600_dma_get_rptr, - .get_wptr = &r600_dma_get_wptr, - .set_wptr = &r600_dma_set_wptr + .get_rptr = &cayman_dma_get_rptr, + .get_wptr = &cayman_dma_get_wptr, + .set_wptr = &cayman_dma_set_wptr }; static struct radeon_asic_ring cayman_uvd_ring = { @@ -1683,6 +1689,7 @@ static struct radeon_asic cayman_asic = { .init = &ni_dpm_init, .setup_asic = &ni_dpm_setup_asic, .enable = &ni_dpm_enable, + .late_enable = &rv770_dpm_late_enable, .disable = &ni_dpm_disable, .pre_set_power_state = &ni_dpm_pre_set_power_state, .set_power_state = &ni_dpm_set_power_state, @@ -1783,6 +1790,7 @@ static struct radeon_asic trinity_asic = { .init = &trinity_dpm_init, .setup_asic = &trinity_dpm_setup_asic, .enable = &trinity_dpm_enable, + .late_enable = &trinity_dpm_late_enable, .disable = &trinity_dpm_disable, .pre_set_power_state = &trinity_dpm_pre_set_power_state, .set_power_state = &trinity_dpm_set_power_state, @@ -1813,9 +1821,9 @@ static struct radeon_asic_ring si_gfx_ring = { .ib_test = &r600_ib_test, .is_lockup = &si_gfx_is_lockup, .vm_flush = &si_vm_flush, - .get_rptr = &radeon_ring_generic_get_rptr, - .get_wptr = &radeon_ring_generic_get_wptr, - .set_wptr = &radeon_ring_generic_set_wptr, + .get_rptr = &cayman_gfx_get_rptr, + .get_wptr = &cayman_gfx_get_wptr, + .set_wptr = &cayman_gfx_set_wptr, }; static struct radeon_asic_ring si_dma_ring = { @@ -1828,9 +1836,9 @@ static struct radeon_asic_ring si_dma_ring = { .ib_test = &r600_dma_ib_test, .is_lockup = &si_dma_is_lockup, .vm_flush = &si_dma_vm_flush, - .get_rptr = &r600_dma_get_rptr, - .get_wptr = &r600_dma_get_wptr, - .set_wptr = &r600_dma_set_wptr, + .get_rptr = &cayman_dma_get_rptr, + .get_wptr = &cayman_dma_get_wptr, + .set_wptr = &cayman_dma_set_wptr, }; static struct radeon_asic si_asic = { @@ -1913,6 +1921,7 @@ static struct radeon_asic si_asic = { .init = &si_dpm_init, .setup_asic = &si_dpm_setup_asic, .enable = &si_dpm_enable, + .late_enable = &si_dpm_late_enable, .disable = &si_dpm_disable, .pre_set_power_state = &si_dpm_pre_set_power_state, .set_power_state = &si_dpm_set_power_state, @@ -1943,9 +1952,9 @@ static struct radeon_asic_ring ci_gfx_ring = { .ib_test = &cik_ib_test, .is_lockup = &cik_gfx_is_lockup, .vm_flush = &cik_vm_flush, - .get_rptr = &radeon_ring_generic_get_rptr, - .get_wptr = &radeon_ring_generic_get_wptr, - .set_wptr = &radeon_ring_generic_set_wptr, + .get_rptr = &cik_gfx_get_rptr, + .get_wptr = &cik_gfx_get_wptr, + .set_wptr = &cik_gfx_set_wptr, }; static struct radeon_asic_ring ci_cp_ring = { @@ -1958,9 +1967,9 @@ static struct radeon_asic_ring ci_cp_ring = { .ib_test = &cik_ib_test, .is_lockup = &cik_gfx_is_lockup, .vm_flush = &cik_vm_flush, - .get_rptr = &cik_compute_ring_get_rptr, - .get_wptr = &cik_compute_ring_get_wptr, - .set_wptr = &cik_compute_ring_set_wptr, + .get_rptr = &cik_compute_get_rptr, + .get_wptr = &cik_compute_get_wptr, + .set_wptr = &cik_compute_set_wptr, }; static struct radeon_asic_ring ci_dma_ring = { @@ -1973,9 +1982,9 @@ static struct radeon_asic_ring ci_dma_ring = { .ib_test = &cik_sdma_ib_test, .is_lockup = &cik_sdma_is_lockup, .vm_flush = &cik_dma_vm_flush, - .get_rptr = &r600_dma_get_rptr, - .get_wptr = &r600_dma_get_wptr, - .set_wptr = &r600_dma_set_wptr, + .get_rptr = &cik_sdma_get_rptr, + .get_wptr = &cik_sdma_get_wptr, + .set_wptr = &cik_sdma_set_wptr, }; static struct radeon_asic ci_asic = { @@ -2058,6 +2067,7 @@ static struct radeon_asic ci_asic = { .init = &ci_dpm_init, .setup_asic = &ci_dpm_setup_asic, .enable = &ci_dpm_enable, + .late_enable = &ci_dpm_late_enable, .disable = &ci_dpm_disable, .pre_set_power_state = &ci_dpm_pre_set_power_state, .set_power_state = &ci_dpm_set_power_state, @@ -2159,6 +2169,7 @@ static struct radeon_asic kv_asic = { .init = &kv_dpm_init, .setup_asic = &kv_dpm_setup_asic, .enable = &kv_dpm_enable, + .late_enable = &kv_dpm_late_enable, .disable = &kv_dpm_disable, .pre_set_power_state = &kv_dpm_pre_set_power_state, .set_power_state = &kv_dpm_set_power_state, @@ -2449,7 +2460,7 @@ int radeon_asic_init(struct radeon_device *rdev) rdev->cg_flags = RADEON_CG_SUPPORT_GFX_MGCG | RADEON_CG_SUPPORT_GFX_MGLS | - /*RADEON_CG_SUPPORT_GFX_CGCG |*/ + RADEON_CG_SUPPORT_GFX_CGCG | RADEON_CG_SUPPORT_GFX_CGLS | RADEON_CG_SUPPORT_GFX_CGTS | RADEON_CG_SUPPORT_GFX_CGTS_LS | @@ -2468,7 +2479,7 @@ int radeon_asic_init(struct radeon_device *rdev) rdev->cg_flags = RADEON_CG_SUPPORT_GFX_MGCG | RADEON_CG_SUPPORT_GFX_MGLS | - /*RADEON_CG_SUPPORT_GFX_CGCG |*/ + RADEON_CG_SUPPORT_GFX_CGCG | RADEON_CG_SUPPORT_GFX_CGLS | RADEON_CG_SUPPORT_GFX_CGTS | RADEON_CG_SUPPORT_GFX_CP_LS | @@ -2493,7 +2504,7 @@ int radeon_asic_init(struct radeon_device *rdev) rdev->cg_flags = RADEON_CG_SUPPORT_GFX_MGCG | RADEON_CG_SUPPORT_GFX_MGLS | - /*RADEON_CG_SUPPORT_GFX_CGCG |*/ + RADEON_CG_SUPPORT_GFX_CGCG | RADEON_CG_SUPPORT_GFX_CGLS | RADEON_CG_SUPPORT_GFX_CGTS | RADEON_CG_SUPPORT_GFX_CGTS_LS | @@ -2521,7 +2532,7 @@ int radeon_asic_init(struct radeon_device *rdev) rdev->cg_flags = RADEON_CG_SUPPORT_GFX_MGCG | RADEON_CG_SUPPORT_GFX_MGLS | - /*RADEON_CG_SUPPORT_GFX_CGCG |*/ + RADEON_CG_SUPPORT_GFX_CGCG | RADEON_CG_SUPPORT_GFX_CGLS | RADEON_CG_SUPPORT_GFX_CGTS | RADEON_CG_SUPPORT_GFX_CGTS_LS | diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index c9fd97b58076..b3bc433eed4c 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -47,13 +47,6 @@ u8 atombios_get_backlight_level(struct radeon_encoder *radeon_encoder); void radeon_legacy_set_backlight_level(struct radeon_encoder *radeon_encoder, u8 level); u8 radeon_legacy_get_backlight_level(struct radeon_encoder *radeon_encoder); -u32 radeon_ring_generic_get_rptr(struct radeon_device *rdev, - struct radeon_ring *ring); -u32 radeon_ring_generic_get_wptr(struct radeon_device *rdev, - struct radeon_ring *ring); -void radeon_ring_generic_set_wptr(struct radeon_device *rdev, - struct radeon_ring *ring); - /* * r100,rv100,rs100,rv200,rs200 */ @@ -148,6 +141,13 @@ extern void r100_post_page_flip(struct radeon_device *rdev, int crtc); extern void r100_wait_for_vblank(struct radeon_device *rdev, int crtc); extern int r100_mc_wait_for_idle(struct radeon_device *rdev); +u32 r100_gfx_get_rptr(struct radeon_device *rdev, + struct radeon_ring *ring); +u32 r100_gfx_get_wptr(struct radeon_device *rdev, + struct radeon_ring *ring); +void r100_gfx_set_wptr(struct radeon_device *rdev, + struct radeon_ring *ring); + /* * r200,rv250,rs300,rv280 */ @@ -368,6 +368,12 @@ int r600_mc_wait_for_idle(struct radeon_device *rdev); int r600_pcie_gart_init(struct radeon_device *rdev); void r600_scratch_init(struct radeon_device *rdev); int r600_init_microcode(struct radeon_device *rdev); +u32 r600_gfx_get_rptr(struct radeon_device *rdev, + struct radeon_ring *ring); +u32 r600_gfx_get_wptr(struct radeon_device *rdev, + struct radeon_ring *ring); +void r600_gfx_set_wptr(struct radeon_device *rdev, + struct radeon_ring *ring); /* r600 irq */ int r600_irq_process(struct radeon_device *rdev); int r600_irq_init(struct radeon_device *rdev); @@ -392,6 +398,7 @@ int rv6xx_get_temp(struct radeon_device *rdev); int r600_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk); int r600_dpm_pre_set_power_state(struct radeon_device *rdev); void r600_dpm_post_set_power_state(struct radeon_device *rdev); +int r600_dpm_late_enable(struct radeon_device *rdev); /* r600 dma */ uint32_t r600_dma_get_rptr(struct radeon_device *rdev, struct radeon_ring *ring); @@ -454,6 +461,7 @@ int rv770_get_temp(struct radeon_device *rdev); /* rv7xx pm */ int rv770_dpm_init(struct radeon_device *rdev); int rv770_dpm_enable(struct radeon_device *rdev); +int rv770_dpm_late_enable(struct radeon_device *rdev); void rv770_dpm_disable(struct radeon_device *rdev); int rv770_dpm_set_power_state(struct radeon_device *rdev); void rv770_dpm_setup_asic(struct radeon_device *rdev); @@ -545,6 +553,7 @@ u32 btc_dpm_get_mclk(struct radeon_device *rdev, bool low); bool btc_dpm_vblank_too_short(struct radeon_device *rdev); int sumo_dpm_init(struct radeon_device *rdev); int sumo_dpm_enable(struct radeon_device *rdev); +int sumo_dpm_late_enable(struct radeon_device *rdev); void sumo_dpm_disable(struct radeon_device *rdev); int sumo_dpm_pre_set_power_state(struct radeon_device *rdev); int sumo_dpm_set_power_state(struct radeon_device *rdev); @@ -591,6 +600,19 @@ void cayman_dma_vm_set_page(struct radeon_device *rdev, void cayman_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm); +u32 cayman_gfx_get_rptr(struct radeon_device *rdev, + struct radeon_ring *ring); +u32 cayman_gfx_get_wptr(struct radeon_device *rdev, + struct radeon_ring *ring); +void cayman_gfx_set_wptr(struct radeon_device *rdev, + struct radeon_ring *ring); +uint32_t cayman_dma_get_rptr(struct radeon_device *rdev, + struct radeon_ring *ring); +uint32_t cayman_dma_get_wptr(struct radeon_device *rdev, + struct radeon_ring *ring); +void cayman_dma_set_wptr(struct radeon_device *rdev, + struct radeon_ring *ring); + int ni_dpm_init(struct radeon_device *rdev); void ni_dpm_setup_asic(struct radeon_device *rdev); int ni_dpm_enable(struct radeon_device *rdev); @@ -610,6 +632,7 @@ int ni_dpm_force_performance_level(struct radeon_device *rdev, bool ni_dpm_vblank_too_short(struct radeon_device *rdev); int trinity_dpm_init(struct radeon_device *rdev); int trinity_dpm_enable(struct radeon_device *rdev); +int trinity_dpm_late_enable(struct radeon_device *rdev); void trinity_dpm_disable(struct radeon_device *rdev); int trinity_dpm_pre_set_power_state(struct radeon_device *rdev); int trinity_dpm_set_power_state(struct radeon_device *rdev); @@ -669,6 +692,7 @@ int si_get_temp(struct radeon_device *rdev); int si_dpm_init(struct radeon_device *rdev); void si_dpm_setup_asic(struct radeon_device *rdev); int si_dpm_enable(struct radeon_device *rdev); +int si_dpm_late_enable(struct radeon_device *rdev); void si_dpm_disable(struct radeon_device *rdev); int si_dpm_pre_set_power_state(struct radeon_device *rdev); int si_dpm_set_power_state(struct radeon_device *rdev); @@ -739,17 +763,30 @@ void cik_sdma_vm_set_page(struct radeon_device *rdev, uint32_t incr, uint32_t flags); void cik_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm); int cik_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib); -u32 cik_compute_ring_get_rptr(struct radeon_device *rdev, - struct radeon_ring *ring); -u32 cik_compute_ring_get_wptr(struct radeon_device *rdev, - struct radeon_ring *ring); -void cik_compute_ring_set_wptr(struct radeon_device *rdev, - struct radeon_ring *ring); +u32 cik_gfx_get_rptr(struct radeon_device *rdev, + struct radeon_ring *ring); +u32 cik_gfx_get_wptr(struct radeon_device *rdev, + struct radeon_ring *ring); +void cik_gfx_set_wptr(struct radeon_device *rdev, + struct radeon_ring *ring); +u32 cik_compute_get_rptr(struct radeon_device *rdev, + struct radeon_ring *ring); +u32 cik_compute_get_wptr(struct radeon_device *rdev, + struct radeon_ring *ring); +void cik_compute_set_wptr(struct radeon_device *rdev, + struct radeon_ring *ring); +u32 cik_sdma_get_rptr(struct radeon_device *rdev, + struct radeon_ring *ring); +u32 cik_sdma_get_wptr(struct radeon_device *rdev, + struct radeon_ring *ring); +void cik_sdma_set_wptr(struct radeon_device *rdev, + struct radeon_ring *ring); int ci_get_temp(struct radeon_device *rdev); int kv_get_temp(struct radeon_device *rdev); int ci_dpm_init(struct radeon_device *rdev); int ci_dpm_enable(struct radeon_device *rdev); +int ci_dpm_late_enable(struct radeon_device *rdev); void ci_dpm_disable(struct radeon_device *rdev); int ci_dpm_pre_set_power_state(struct radeon_device *rdev); int ci_dpm_set_power_state(struct radeon_device *rdev); @@ -770,6 +807,7 @@ void ci_dpm_powergate_uvd(struct radeon_device *rdev, bool gate); int kv_dpm_init(struct radeon_device *rdev); int kv_dpm_enable(struct radeon_device *rdev); +int kv_dpm_late_enable(struct radeon_device *rdev); void kv_dpm_disable(struct radeon_device *rdev); int kv_dpm_pre_set_power_state(struct radeon_device *rdev); int kv_dpm_set_power_state(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 5c39bf7c3d88..30844814c25a 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -30,27 +30,10 @@ #include "atom.h" #include "atom-bits.h" -/* from radeon_encoder.c */ -extern uint32_t -radeon_get_encoder_enum(struct drm_device *dev, uint32_t supported_device, - uint8_t dac); -extern void radeon_link_encoder_connector(struct drm_device *dev); extern void radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_enum, uint32_t supported_device, u16 caps); -/* from radeon_connector.c */ -extern void -radeon_add_atom_connector(struct drm_device *dev, - uint32_t connector_id, - uint32_t supported_device, - int connector_type, - struct radeon_i2c_bus_rec *i2c_bus, - uint32_t igp_lane_info, - uint16_t connector_object_id, - struct radeon_hpd *hpd, - struct radeon_router *router); - /* from radeon_legacy_encoder.c */ extern void radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_enum, @@ -1528,6 +1511,7 @@ bool radeon_atombios_get_asic_ss_info(struct radeon_device *rdev, le16_to_cpu(ss_assign->v1.usSpreadSpectrumPercentage); ss->type = ss_assign->v1.ucSpreadSpectrumMode; ss->rate = le16_to_cpu(ss_assign->v1.usSpreadRateInKhz); + ss->percentage_divider = 100; return true; } ss_assign = (union asic_ss_assignment *) @@ -1545,6 +1529,7 @@ bool radeon_atombios_get_asic_ss_info(struct radeon_device *rdev, le16_to_cpu(ss_assign->v2.usSpreadSpectrumPercentage); ss->type = ss_assign->v2.ucSpreadSpectrumMode; ss->rate = le16_to_cpu(ss_assign->v2.usSpreadRateIn10Hz); + ss->percentage_divider = 100; if ((crev == 2) && ((id == ASIC_INTERNAL_ENGINE_SS) || (id == ASIC_INTERNAL_MEMORY_SS))) @@ -1566,6 +1551,11 @@ bool radeon_atombios_get_asic_ss_info(struct radeon_device *rdev, le16_to_cpu(ss_assign->v3.usSpreadSpectrumPercentage); ss->type = ss_assign->v3.ucSpreadSpectrumMode; ss->rate = le16_to_cpu(ss_assign->v3.usSpreadRateIn10Hz); + if (ss_assign->v3.ucSpreadSpectrumMode & + SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK) + ss->percentage_divider = 1000; + else + ss->percentage_divider = 100; if ((id == ASIC_INTERNAL_ENGINE_SS) || (id == ASIC_INTERNAL_MEMORY_SS)) ss->rate /= 100; @@ -1809,7 +1799,8 @@ bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index, if (misc & ATOM_DOUBLE_CLOCK_MODE) mode->flags |= DRM_MODE_FLAG_DBLSCAN; - mode->clock = le16_to_cpu(tv_info->aModeTimings[index].usPixelClock) * 10; + mode->crtc_clock = mode->clock = + le16_to_cpu(tv_info->aModeTimings[index].usPixelClock) * 10; if (index == 1) { /* PAL timings appear to have wrong values for totals */ @@ -1852,7 +1843,8 @@ bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index, if (misc & ATOM_DOUBLE_CLOCK_MODE) mode->flags |= DRM_MODE_FLAG_DBLSCAN; - mode->clock = le16_to_cpu(dtd_timings->usPixClk) * 10; + mode->crtc_clock = mode->clock = + le16_to_cpu(dtd_timings->usPixClk) * 10; break; } return true; @@ -3884,16 +3876,18 @@ int radeon_atom_init_mc_reg_table(struct radeon_device *rdev, ((u8 *)format + sizeof(ATOM_INIT_REG_INDEX_FORMAT)); } reg_table->last = i; - while ((*(u32 *)reg_data != END_OF_REG_DATA_BLOCK) && + while ((le32_to_cpu(*(u32 *)reg_data) != END_OF_REG_DATA_BLOCK) && (num_ranges < VBIOS_MAX_AC_TIMING_ENTRIES)) { - t_mem_id = (u8)((*(u32 *)reg_data & MEM_ID_MASK) >> MEM_ID_SHIFT); + t_mem_id = (u8)((le32_to_cpu(*(u32 *)reg_data) & MEM_ID_MASK) + >> MEM_ID_SHIFT); if (module_index == t_mem_id) { reg_table->mc_reg_table_entry[num_ranges].mclk_max = - (u32)((*(u32 *)reg_data & CLOCK_RANGE_MASK) >> CLOCK_RANGE_SHIFT); + (u32)((le32_to_cpu(*(u32 *)reg_data) & CLOCK_RANGE_MASK) + >> CLOCK_RANGE_SHIFT); for (i = 0, j = 1; i < reg_table->last; i++) { if ((reg_table->mc_reg_address[i].pre_reg_data & LOW_NIBBLE_MASK) == DATA_FROM_TABLE) { reg_table->mc_reg_table_entry[num_ranges].mc_data[i] = - (u32)*((u32 *)reg_data + j); + (u32)le32_to_cpu(*((u32 *)reg_data + j)); j++; } else if ((reg_table->mc_reg_address[i].pre_reg_data & LOW_NIBBLE_MASK) == DATA_EQU_PREV) { reg_table->mc_reg_table_entry[num_ranges].mc_data[i] = @@ -3905,7 +3899,7 @@ int radeon_atom_init_mc_reg_table(struct radeon_device *rdev, reg_data = (ATOM_MEMORY_SETTING_DATA_BLOCK *) ((u8 *)reg_data + le16_to_cpu(reg_block->usRegDataBlkSize)); } - if (*(u32 *)reg_data != END_OF_REG_DATA_BLOCK) + if (le32_to_cpu(*(u32 *)reg_data) != END_OF_REG_DATA_BLOCK) return -EINVAL; reg_table->num_entries = num_ranges; } else @@ -3944,6 +3938,10 @@ void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev) /* tell the bios not to handle mode switching */ bios_6_scratch |= ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH; + /* clear the vbios dpms state */ + if (ASIC_IS_DCE4(rdev)) + bios_2_scratch &= ~ATOM_S2_DEVICE_DPMS_STATE; + if (rdev->family >= CHIP_R600) { WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch); WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch); diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 68ce36056019..6651177110f0 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -37,22 +37,6 @@ #include <asm/pci-bridge.h> #endif /* CONFIG_PPC_PMAC */ -/* from radeon_encoder.c */ -extern uint32_t -radeon_get_encoder_enum(struct drm_device *dev, uint32_t supported_device, - uint8_t dac); -extern void radeon_link_encoder_connector(struct drm_device *dev); - -/* from radeon_connector.c */ -extern void -radeon_add_legacy_connector(struct drm_device *dev, - uint32_t connector_id, - uint32_t supported_device, - int connector_type, - struct radeon_i2c_bus_rec *i2c_bus, - uint16_t connector_object_id, - struct radeon_hpd *hpd); - /* from radeon_legacy_encoder.c */ extern void radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_enum, diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 20a768ac89a8..82d4f865546e 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -33,15 +33,6 @@ #include <linux/pm_runtime.h> -extern void -radeon_combios_connected_scratch_regs(struct drm_connector *connector, - struct drm_encoder *encoder, - bool connected); -extern void -radeon_atombios_connected_scratch_regs(struct drm_connector *connector, - struct drm_encoder *encoder, - bool connected); - void radeon_connector_hotplug(struct drm_connector *connector) { struct drm_device *dev = connector->dev; diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c index 3cae2bbc1854..bb0d5c3a8311 100644 --- a/drivers/gpu/drm/radeon/radeon_cp.c +++ b/drivers/gpu/drm/radeon/radeon_cp.c @@ -2020,10 +2020,10 @@ static int radeon_cp_get_buffers(struct drm_device *dev, buf->file_priv = file_priv; - if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx, + if (copy_to_user(&d->request_indices[i], &buf->idx, sizeof(buf->idx))) return -EFAULT; - if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total, + if (copy_to_user(&d->request_sizes[i], &buf->total, sizeof(buf->total))) return -EFAULT; @@ -2228,7 +2228,7 @@ void radeon_commit_ring(drm_radeon_private_t *dev_priv) dev_priv->ring.tail &= dev_priv->ring.tail_mask; - DRM_MEMORYBARRIER(); + mb(); GET_RING_HEAD( dev_priv ); if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) { diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 0b366169d64d..dfb5a1db87d4 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -138,7 +138,7 @@ static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority p->ring = R600_RING_TYPE_DMA_INDEX; else p->ring = CAYMAN_RING_TYPE_DMA1_INDEX; - } else if (p->rdev->family >= CHIP_R600) { + } else if (p->rdev->family >= CHIP_RV770) { p->ring = R600_RING_TYPE_DMA_INDEX; } else { return -EINVAL; @@ -192,7 +192,7 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) return -ENOMEM; } chunk_array_ptr = (uint64_t *)(unsigned long)(cs->chunks); - if (DRM_COPY_FROM_USER(p->chunks_array, chunk_array_ptr, + if (copy_from_user(p->chunks_array, chunk_array_ptr, sizeof(uint64_t)*cs->num_chunks)) { return -EFAULT; } @@ -208,7 +208,7 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) uint32_t __user *cdata; chunk_ptr = (void __user*)(unsigned long)p->chunks_array[i]; - if (DRM_COPY_FROM_USER(&user_chunk, chunk_ptr, + if (copy_from_user(&user_chunk, chunk_ptr, sizeof(struct drm_radeon_cs_chunk))) { return -EFAULT; } @@ -252,7 +252,7 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) if (p->chunks[i].kdata == NULL) { return -ENOMEM; } - if (DRM_COPY_FROM_USER(p->chunks[i].kdata, cdata, size)) { + if (copy_from_user(p->chunks[i].kdata, cdata, size)) { return -EFAULT; } if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_FLAGS) { @@ -472,7 +472,7 @@ static int radeon_cs_ib_fill(struct radeon_device *rdev, struct radeon_cs_parser } parser->const_ib.is_const_ib = true; parser->const_ib.length_dw = ib_chunk->length_dw; - if (DRM_COPY_FROM_USER(parser->const_ib.ptr, + if (copy_from_user(parser->const_ib.ptr, ib_chunk->user_ptr, ib_chunk->length_dw * 4)) return -EFAULT; @@ -495,7 +495,7 @@ static int radeon_cs_ib_fill(struct radeon_device *rdev, struct radeon_cs_parser parser->ib.length_dw = ib_chunk->length_dw; if (ib_chunk->kdata) memcpy(parser->ib.ptr, ib_chunk->kdata, ib_chunk->length_dw * 4); - else if (DRM_COPY_FROM_USER(parser->ib.ptr, ib_chunk->user_ptr, ib_chunk->length_dw * 4)) + else if (copy_from_user(parser->ib.ptr, ib_chunk->user_ptr, ib_chunk->length_dw * 4)) return -EFAULT; return 0; } diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 39b033b441d2..b012cbbc3ed5 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -144,6 +144,11 @@ void radeon_program_register_sequence(struct radeon_device *rdev, } } +void radeon_pci_config_reset(struct radeon_device *rdev) +{ + pci_write_config_dword(rdev->pdev, 0x7c, RADEON_ASIC_RESET_DATA); +} + /** * radeon_surface_init - Clear GPU surface registers. * @@ -249,7 +254,7 @@ void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg) * Init doorbell driver information (CIK) * Returns 0 on success, error on failure. */ -int radeon_doorbell_init(struct radeon_device *rdev) +static int radeon_doorbell_init(struct radeon_device *rdev) { /* doorbell bar mapping */ rdev->doorbell.base = pci_resource_start(rdev->pdev, 2); @@ -278,7 +283,7 @@ int radeon_doorbell_init(struct radeon_device *rdev) * * Tear down doorbell driver information (CIK) */ -void radeon_doorbell_fini(struct radeon_device *rdev) +static void radeon_doorbell_fini(struct radeon_device *rdev) { iounmap(rdev->doorbell.ptr); rdev->doorbell.ptr = NULL; @@ -1330,6 +1335,7 @@ int radeon_device_init(struct radeon_device *rdev, if (r) return r; } + if ((radeon_testing & 1)) { if (rdev->accel_working) radeon_test_moves(rdev); @@ -1455,7 +1461,6 @@ int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon) radeon_save_bios_scratch_regs(rdev); - radeon_pm_suspend(rdev); radeon_suspend(rdev); radeon_hpd_fini(rdev); /* evict remaining vram memory */ @@ -1516,14 +1521,22 @@ int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon) if (r) DRM_ERROR("ib ring test failed (%d).\n", r); - radeon_pm_resume(rdev); + if (rdev->pm.dpm_enabled) { + /* do dpm late init */ + r = radeon_pm_late_init(rdev); + if (r) { + rdev->pm.dpm_enabled = false; + DRM_ERROR("radeon_pm_late_init failed, disabling dpm\n"); + } + } + radeon_restore_bios_scratch_regs(rdev); if (fbcon) { radeon_fbdev_set_suspend(rdev, 0); console_unlock(); } - + /* init dig PHYs, disp eng pll */ if (rdev->is_atom_bios) { radeon_atom_encoder_init(rdev); diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 7b253815a323..d680608f6f5b 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -306,7 +306,7 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) * to complete in this vblank? */ if (update_pending && - (DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, crtc_id, + (DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, crtc_id, 0, &vpos, &hpos, NULL, NULL)) && ((vpos >= (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100) || (vpos < 0 && !ASIC_IS_AVIVO(rdev)))) { @@ -1464,12 +1464,22 @@ int radeon_modeset_init(struct radeon_device *rdev) /* setup afmt */ radeon_afmt_init(rdev); - /* Initialize power management */ - radeon_pm_init(rdev); - radeon_fbdev_init(rdev); drm_kms_helper_poll_init(rdev->ddev); + if (rdev->pm.dpm_enabled) { + /* do dpm late init */ + ret = radeon_pm_late_init(rdev); + if (ret) { + rdev->pm.dpm_enabled = false; + DRM_ERROR("radeon_pm_late_init failed, disabling dpm\n"); + } + /* set the dpm state for PX since there won't be + * a modeset to call this. + */ + radeon_pm_compute_clocks(rdev); + } + return 0; } @@ -1477,7 +1487,6 @@ void radeon_modeset_fini(struct radeon_device *rdev) { radeon_fbdev_fini(rdev); kfree(rdev->mode_info.bios_hardcoded_edid); - radeon_pm_fini(rdev); if (rdev->mode_info.mode_config_initialized) { radeon_afmt_fini(rdev); @@ -1601,6 +1610,7 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, * * \param dev Device to query. * \param crtc Crtc to query. + * \param flags Flags from caller (DRM_CALLED_FROM_VBLIRQ or 0). * \param *vpos Location where vertical scanout position should be stored. * \param *hpos Location where horizontal scanout position should go. * \param *stime Target location for timestamp taken immediately before @@ -1622,8 +1632,8 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, * unknown small number of scanlines wrt. real scanout position. * */ -int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, int *vpos, int *hpos, - ktime_t *stime, ktime_t *etime) +int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int flags, + int *vpos, int *hpos, ktime_t *stime, ktime_t *etime) { u32 stat_crtc = 0, vbl = 0, position = 0; int vbl_start, vbl_end, vtotal, ret = 0; @@ -1765,5 +1775,27 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, int *vpos, int if (in_vbl) ret |= DRM_SCANOUTPOS_INVBL; + /* Is vpos outside nominal vblank area, but less than + * 1/100 of a frame height away from start of vblank? + * If so, assume this isn't a massively delayed vblank + * interrupt, but a vblank interrupt that fired a few + * microseconds before true start of vblank. Compensate + * by adding a full frame duration to the final timestamp. + * Happens, e.g., on ATI R500, R600. + * + * We only do this if DRM_CALLED_FROM_VBLIRQ. + */ + if ((flags & DRM_CALLED_FROM_VBLIRQ) && !in_vbl) { + vbl_start = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vdisplay; + vtotal = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vtotal; + + if (vbl_start - *vpos < vtotal / 100) { + *vpos -= vtotal; + + /* Signal this correction as "applied". */ + ret |= 0x8; + } + } + return ret; } diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index db39ea36bf22..ec8c388eec17 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -102,13 +102,14 @@ int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc, void radeon_driver_irq_preinstall_kms(struct drm_device *dev); int radeon_driver_irq_postinstall_kms(struct drm_device *dev); void radeon_driver_irq_uninstall_kms(struct drm_device *dev); -irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS); +irqreturn_t radeon_driver_irq_handler_kms(int irq, void *arg); void radeon_gem_object_free(struct drm_gem_object *obj); int radeon_gem_object_open(struct drm_gem_object *obj, struct drm_file *file_priv); void radeon_gem_object_close(struct drm_gem_object *obj, struct drm_file *file_priv); extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, + unsigned int flags, int *vpos, int *hpos, ktime_t *stime, ktime_t *etime); extern const struct drm_ioctl_desc radeon_ioctls_kms[]; @@ -168,6 +169,7 @@ int radeon_fastfb = 0; int radeon_dpm = -1; int radeon_aspm = -1; int radeon_runtime_pm = -1; +int radeon_hard_reset = 0; MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers"); module_param_named(no_wb, radeon_no_wb, int, 0444); @@ -232,6 +234,9 @@ module_param_named(aspm, radeon_aspm, int, 0444); MODULE_PARM_DESC(runpm, "PX runtime pm (1 = force enable, 0 = disable, -1 = PX only default)"); module_param_named(runpm, radeon_runtime_pm, int, 0444); +MODULE_PARM_DESC(hard_reset, "PCI config reset (1 = force enable, 0 = disable (default))"); +module_param_named(hard_reset, radeon_hard_reset, int, 0444); + static struct pci_device_id pciidlist[] = { radeon_PCI_IDS }; @@ -400,6 +405,9 @@ static int radeon_pmops_runtime_suspend(struct device *dev) if (radeon_runtime_pm == 0) return -EINVAL; + if (radeon_runtime_pm == -1 && !radeon_is_px()) + return -EINVAL; + drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; drm_kms_helper_poll_disable(drm_dev); vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_OFF); @@ -422,6 +430,9 @@ static int radeon_pmops_runtime_resume(struct device *dev) if (radeon_runtime_pm == 0) return -EINVAL; + if (radeon_runtime_pm == -1 && !radeon_is_px()) + return -EINVAL; + drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; pci_set_power_state(pdev, PCI_D0); diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h index 00e0d449021c..dafd812e4571 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.h +++ b/drivers/gpu/drm/radeon/radeon_drv.h @@ -405,7 +405,7 @@ extern void radeon_do_release(struct drm_device * dev); extern u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc); extern int radeon_enable_vblank(struct drm_device *dev, int crtc); extern void radeon_disable_vblank(struct drm_device *dev, int crtc); -extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS); +extern irqreturn_t radeon_driver_irq_handler(int irq, void *arg); extern void radeon_driver_irq_preinstall(struct drm_device * dev); extern int radeon_driver_irq_postinstall(struct drm_device *dev); extern void radeon_driver_irq_uninstall(struct drm_device * dev); diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index d3a86e43c012..c37cb79a9489 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c @@ -121,7 +121,7 @@ int radeon_fence_emit(struct radeon_device *rdev, (*fence)->seq = ++rdev->fence_drv[ring].sync_seq[ring]; (*fence)->ring = ring; radeon_fence_ring_emit(rdev, ring, *fence); - trace_radeon_fence_emit(rdev->ddev, (*fence)->seq); + trace_radeon_fence_emit(rdev->ddev, ring, (*fence)->seq); return 0; } @@ -313,7 +313,7 @@ static int radeon_fence_wait_seq(struct radeon_device *rdev, u64 *target_seq, continue; last_seq[i] = atomic64_read(&rdev->fence_drv[i].last_seq); - trace_radeon_fence_wait_begin(rdev->ddev, target_seq[i]); + trace_radeon_fence_wait_begin(rdev->ddev, i, target_seq[i]); radeon_irq_kms_sw_irq_get(rdev, i); } @@ -332,7 +332,7 @@ static int radeon_fence_wait_seq(struct radeon_device *rdev, u64 *target_seq, continue; radeon_irq_kms_sw_irq_put(rdev, i); - trace_radeon_fence_wait_end(rdev->ddev, target_seq[i]); + trace_radeon_fence_wait_end(rdev->ddev, i, target_seq[i]); } if (unlikely(r < 0)) @@ -841,6 +841,8 @@ static int radeon_debugfs_fence_info(struct seq_file *m, void *data) if (!rdev->fence_drv[i].initialized) continue; + radeon_fence_process(rdev, i); + seq_printf(m, "--- ring %d ---\n", i); seq_printf(m, "Last signaled fence 0x%016llx\n", (unsigned long long)atomic64_read(&rdev->fence_drv[i].last_seq)); diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index 96e440061bdb..a8f9b463bf2a 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -713,7 +713,7 @@ struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev, unsigned i; /* check if the id is still valid */ - if (vm->fence && vm->fence == rdev->vm_manager.active[vm->id]) + if (vm->last_id_use && vm->last_id_use == rdev->vm_manager.active[vm->id]) return NULL; /* we definately need to flush */ @@ -726,6 +726,7 @@ struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev, if (fence == NULL) { /* found a free one */ vm->id = i; + trace_radeon_vm_grab_id(vm->id, ring); return NULL; } @@ -769,6 +770,9 @@ void radeon_vm_fence(struct radeon_device *rdev, radeon_fence_unref(&vm->fence); vm->fence = radeon_fence_ref(fence); + + radeon_fence_unref(&vm->last_id_use); + vm->last_id_use = radeon_fence_ref(fence); } /** @@ -1303,6 +1307,8 @@ void radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm) { vm->id = 0; vm->fence = NULL; + vm->last_flush = NULL; + vm->last_id_use = NULL; mutex_init(&vm->mutex); INIT_LIST_HEAD(&vm->list); INIT_LIST_HEAD(&vm->va); @@ -1341,5 +1347,6 @@ void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm) } radeon_fence_unref(&vm->fence); radeon_fence_unref(&vm->last_flush); + radeon_fence_unref(&vm->last_id_use); mutex_unlock(&vm->mutex); } diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index 805c5e566b9a..b96c819024b3 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -86,7 +86,7 @@ retry: return 0; } -int radeon_gem_set_domain(struct drm_gem_object *gobj, +static int radeon_gem_set_domain(struct drm_gem_object *gobj, uint32_t rdomain, uint32_t wdomain) { struct radeon_bo *robj; diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c index fc60b74ee304..e24ca6ab96de 100644 --- a/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/drivers/gpu/drm/radeon/radeon_i2c.c @@ -1020,6 +1020,9 @@ void radeon_i2c_destroy(struct radeon_i2c_chan *i2c) /* Add the default buses */ void radeon_i2c_init(struct radeon_device *rdev) { + if (radeon_hw_i2c) + DRM_INFO("hw_i2c forced on, you may experience display detection problems!\n"); + if (rdev->is_atom_bios) radeon_atombios_i2c_init(rdev); else diff --git a/drivers/gpu/drm/radeon/radeon_irq.c b/drivers/gpu/drm/radeon/radeon_irq.c index 8d68e972789a..244b19bab2e7 100644 --- a/drivers/gpu/drm/radeon/radeon_irq.c +++ b/drivers/gpu/drm/radeon/radeon_irq.c @@ -181,7 +181,7 @@ static u32 radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv, u32 *r500_dis * tied to dma at all, this is just a hangover from dri prehistory. */ -irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS) +irqreturn_t radeon_driver_irq_handler(int irq, void *arg) { struct drm_device *dev = (struct drm_device *) arg; drm_radeon_private_t *dev_priv = @@ -203,7 +203,7 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS) /* SW interrupt */ if (stat & RADEON_SW_INT_TEST) - DRM_WAKEUP(&dev_priv->swi_queue); + wake_up(&dev_priv->swi_queue); /* VBLANK interrupt */ if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) { @@ -249,7 +249,7 @@ static int radeon_wait_irq(struct drm_device * dev, int swi_nr) dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; - DRM_WAIT_ON(ret, dev_priv->swi_queue, 3 * DRM_HZ, + DRM_WAIT_ON(ret, dev_priv->swi_queue, 3 * HZ, RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr); return ret; @@ -302,7 +302,7 @@ int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_pr result = radeon_emit_irq(dev); - if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) { + if (copy_to_user(emit->irq_seq, &result, sizeof(int))) { DRM_ERROR("copy_to_user\n"); return -EFAULT; } @@ -354,7 +354,7 @@ int radeon_driver_irq_postinstall(struct drm_device *dev) (drm_radeon_private_t *) dev->dev_private; atomic_set(&dev_priv->swi_emitted, 0); - DRM_INIT_WAITQUEUE(&dev_priv->swi_queue); + init_waitqueue_head(&dev_priv->swi_queue); dev->max_vblank_count = 0x001fffff; diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index ec6240b00469..089c9ffb0aa9 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c @@ -39,13 +39,13 @@ /** * radeon_driver_irq_handler_kms - irq handler for KMS * - * @DRM_IRQ_ARGS: args + * @int irq, void *arg: args * * This is the irq handler for the radeon KMS driver (all asics). * radeon_irq_process is a macro that points to the per-asic * irq handler callback. */ -irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS) +irqreturn_t radeon_driver_irq_handler_kms(int irq, void *arg) { struct drm_device *dev = (struct drm_device *) arg; struct radeon_device *rdev = dev->dev_private; diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 21d593c0ecaf..114d1672d616 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -191,7 +191,7 @@ static void radeon_set_filp_rights(struct drm_device *dev, * etc. (all asics). * Returns 0 on success, -EINVAL on failure. */ -int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) +static int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { struct radeon_device *rdev = dev->dev_private; struct drm_radeon_info *info = data; @@ -223,7 +223,7 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) *value = rdev->accel_working; break; case RADEON_INFO_CRTC_FROM_ID: - if (DRM_COPY_FROM_USER(value, value_ptr, sizeof(uint32_t))) { + if (copy_from_user(value, value_ptr, sizeof(uint32_t))) { DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__); return -EFAULT; } @@ -269,7 +269,7 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) * * When returning, the value is 1 if filp owns hyper-z access, * 0 otherwise. */ - if (DRM_COPY_FROM_USER(value, value_ptr, sizeof(uint32_t))) { + if (copy_from_user(value, value_ptr, sizeof(uint32_t))) { DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__); return -EFAULT; } @@ -281,7 +281,7 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) break; case RADEON_INFO_WANT_CMASK: /* The same logic as Hyper-Z. */ - if (DRM_COPY_FROM_USER(value, value_ptr, sizeof(uint32_t))) { + if (copy_from_user(value, value_ptr, sizeof(uint32_t))) { DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__); return -EFAULT; } @@ -417,7 +417,7 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) *value = rdev->fastfb_working; break; case RADEON_INFO_RING_WORKING: - if (DRM_COPY_FROM_USER(value, value_ptr, sizeof(uint32_t))) { + if (copy_from_user(value, value_ptr, sizeof(uint32_t))) { DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__); return -EFAULT; } @@ -470,11 +470,18 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) DRM_DEBUG_KMS("BACKEND_ENABLED_MASK is si+ only!\n"); } break; + case RADEON_INFO_MAX_SCLK: + if ((rdev->pm.pm_method == PM_METHOD_DPM) && + rdev->pm.dpm_enabled) + *value = rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.sclk * 10; + else + *value = rdev->pm.default_sclk * 10; + break; default: DRM_DEBUG_KMS("Invalid request %d\n", info->request); return -EINVAL; } - if (DRM_COPY_TO_USER(value_ptr, (char*)value, value_size)) { + if (copy_to_user(value_ptr, (char*)value, value_size)) { DRM_ERROR("copy_to_user %s:%u\n", __func__, __LINE__); return -EFAULT; } @@ -712,11 +719,12 @@ int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc, /* Helper routine in DRM core does all the work: */ return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc, max_error, vblank_time, flags, - drmcrtc); + drmcrtc, &drmcrtc->hwmode); } #define KMS_INVALID_IOCTL(name) \ -int name(struct drm_device *dev, void *data, struct drm_file *file_priv)\ +static int name(struct drm_device *dev, void *data, struct drm_file \ + *file_priv) \ { \ DRM_ERROR("invalid ioctl with kms %s\n", __func__); \ return -EINVAL; \ diff --git a/drivers/gpu/drm/radeon/radeon_mem.c b/drivers/gpu/drm/radeon/radeon_mem.c index d54d2d7c9031..146d253f1131 100644 --- a/drivers/gpu/drm/radeon/radeon_mem.c +++ b/drivers/gpu/drm/radeon/radeon_mem.c @@ -243,7 +243,7 @@ int radeon_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_p if (!block) return -ENOMEM; - if (DRM_COPY_TO_USER(alloc->region_offset, &block->start, + if (copy_to_user(alloc->region_offset, &block->start, sizeof(int))) { DRM_ERROR("copy_to_user\n"); return -EFAULT; diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 3f0dd664af90..402dbe32c234 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -291,6 +291,7 @@ struct radeon_tv_regs { struct radeon_atom_ss { uint16_t percentage; + uint16_t percentage_divider; uint8_t type; uint16_t step; uint8_t delay; @@ -624,6 +625,30 @@ struct atom_voltage_table struct atom_voltage_table_entry entries[MAX_VOLTAGE_ENTRIES]; }; + +extern void +radeon_add_atom_connector(struct drm_device *dev, + uint32_t connector_id, + uint32_t supported_device, + int connector_type, + struct radeon_i2c_bus_rec *i2c_bus, + uint32_t igp_lane_info, + uint16_t connector_object_id, + struct radeon_hpd *hpd, + struct radeon_router *router); +extern void +radeon_add_legacy_connector(struct drm_device *dev, + uint32_t connector_id, + uint32_t supported_device, + int connector_type, + struct radeon_i2c_bus_rec *i2c_bus, + uint16_t connector_object_id, + struct radeon_hpd *hpd); +extern uint32_t +radeon_get_encoder_enum(struct drm_device *dev, uint32_t supported_device, + uint8_t dac); +extern void radeon_link_encoder_connector(struct drm_device *dev); + extern enum radeon_tv_std radeon_combios_get_tv_info(struct radeon_device *rdev); extern enum radeon_tv_std @@ -631,6 +656,15 @@ radeon_atombios_get_tv_info(struct radeon_device *rdev); extern void radeon_atombios_get_default_voltages(struct radeon_device *rdev, u16 *vddc, u16 *vddci, u16 *mvdd); +extern void +radeon_combios_connected_scratch_regs(struct drm_connector *connector, + struct drm_encoder *encoder, + bool connected); +extern void +radeon_atombios_connected_scratch_regs(struct drm_connector *connector, + struct drm_encoder *encoder, + bool connected); + extern struct drm_connector * radeon_get_connector_for_encoder(struct drm_encoder *encoder); extern struct drm_connector * @@ -666,6 +700,7 @@ extern void radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder); extern struct drm_encoder *radeon_get_external_encoder(struct drm_encoder *encoder); extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, u8 write_byte, u8 *read_byte); +void radeon_atom_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le); extern void radeon_i2c_init(struct radeon_device *rdev); extern void radeon_i2c_fini(struct radeon_device *rdev); @@ -766,6 +801,7 @@ extern int radeon_crtc_cursor_move(struct drm_crtc *crtc, int x, int y); extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, + unsigned int flags, int *vpos, int *hpos, ktime_t *stime, ktime_t *etime); diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index c0fa4aa9ceea..08595cf90b01 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -46,7 +46,7 @@ static void radeon_bo_clear_surface_reg(struct radeon_bo *bo); * function are calling it. */ -void radeon_bo_clear_va(struct radeon_bo *bo) +static void radeon_bo_clear_va(struct radeon_bo *bo) { struct radeon_bo_va *bo_va, *tmp; diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 984097b907ef..8e8153e471c2 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -924,6 +924,10 @@ void radeon_dpm_enable_uvd(struct radeon_device *rdev, bool enable) if (rdev->asic->dpm.powergate_uvd) { mutex_lock(&rdev->pm.mutex); + /* don't powergate anything if we + have active but pause streams */ + enable |= rdev->pm.dpm.sd > 0; + enable |= rdev->pm.dpm.hd > 0; /* enable/disable UVD */ radeon_dpm_powergate_uvd(rdev, !enable); mutex_unlock(&rdev->pm.mutex); @@ -1010,8 +1014,10 @@ static void radeon_pm_resume_old(struct radeon_device *rdev) rdev->pm.current_clock_mode_index = 0; rdev->pm.current_sclk = rdev->pm.default_sclk; rdev->pm.current_mclk = rdev->pm.default_mclk; - rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage; - rdev->pm.current_vddci = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.vddci; + if (rdev->pm.power_state) { + rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage; + rdev->pm.current_vddci = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.vddci; + } if (rdev->pm.pm_method == PM_METHOD_DYNPM && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) { rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE; @@ -1032,25 +1038,27 @@ static void radeon_pm_resume_dpm(struct radeon_device *rdev) radeon_dpm_setup_asic(rdev); ret = radeon_dpm_enable(rdev); mutex_unlock(&rdev->pm.mutex); - if (ret) { - DRM_ERROR("radeon: dpm resume failed\n"); - if ((rdev->family >= CHIP_BARTS) && - (rdev->family <= CHIP_CAYMAN) && - rdev->mc_fw) { - if (rdev->pm.default_vddc) - radeon_atom_set_voltage(rdev, rdev->pm.default_vddc, - SET_VOLTAGE_TYPE_ASIC_VDDC); - if (rdev->pm.default_vddci) - radeon_atom_set_voltage(rdev, rdev->pm.default_vddci, - SET_VOLTAGE_TYPE_ASIC_VDDCI); - if (rdev->pm.default_sclk) - radeon_set_engine_clock(rdev, rdev->pm.default_sclk); - if (rdev->pm.default_mclk) - radeon_set_memory_clock(rdev, rdev->pm.default_mclk); - } - } else { - rdev->pm.dpm_enabled = true; - radeon_pm_compute_clocks(rdev); + if (ret) + goto dpm_resume_fail; + rdev->pm.dpm_enabled = true; + radeon_pm_compute_clocks(rdev); + return; + +dpm_resume_fail: + DRM_ERROR("radeon: dpm resume failed\n"); + if ((rdev->family >= CHIP_BARTS) && + (rdev->family <= CHIP_CAYMAN) && + rdev->mc_fw) { + if (rdev->pm.default_vddc) + radeon_atom_set_voltage(rdev, rdev->pm.default_vddc, + SET_VOLTAGE_TYPE_ASIC_VDDC); + if (rdev->pm.default_vddci) + radeon_atom_set_voltage(rdev, rdev->pm.default_vddci, + SET_VOLTAGE_TYPE_ASIC_VDDCI); + if (rdev->pm.default_sclk) + radeon_set_engine_clock(rdev, rdev->pm.default_sclk); + if (rdev->pm.default_mclk) + radeon_set_memory_clock(rdev, rdev->pm.default_mclk); } } @@ -1170,51 +1178,50 @@ static int radeon_pm_init_dpm(struct radeon_device *rdev) radeon_dpm_setup_asic(rdev); ret = radeon_dpm_enable(rdev); mutex_unlock(&rdev->pm.mutex); - if (ret) { - rdev->pm.dpm_enabled = false; - if ((rdev->family >= CHIP_BARTS) && - (rdev->family <= CHIP_CAYMAN) && - rdev->mc_fw) { - if (rdev->pm.default_vddc) - radeon_atom_set_voltage(rdev, rdev->pm.default_vddc, - SET_VOLTAGE_TYPE_ASIC_VDDC); - if (rdev->pm.default_vddci) - radeon_atom_set_voltage(rdev, rdev->pm.default_vddci, - SET_VOLTAGE_TYPE_ASIC_VDDCI); - if (rdev->pm.default_sclk) - radeon_set_engine_clock(rdev, rdev->pm.default_sclk); - if (rdev->pm.default_mclk) - radeon_set_memory_clock(rdev, rdev->pm.default_mclk); - } - DRM_ERROR("radeon: dpm initialization failed\n"); - return ret; - } + if (ret) + goto dpm_failed; rdev->pm.dpm_enabled = true; - radeon_pm_compute_clocks(rdev); - if (rdev->pm.num_power_states > 1) { - ret = device_create_file(rdev->dev, &dev_attr_power_dpm_state); - if (ret) - DRM_ERROR("failed to create device file for dpm state\n"); - ret = device_create_file(rdev->dev, &dev_attr_power_dpm_force_performance_level); - if (ret) - DRM_ERROR("failed to create device file for dpm state\n"); - /* XXX: these are noops for dpm but are here for backwards compat */ - ret = device_create_file(rdev->dev, &dev_attr_power_profile); - if (ret) - DRM_ERROR("failed to create device file for power profile\n"); - ret = device_create_file(rdev->dev, &dev_attr_power_method); - if (ret) - DRM_ERROR("failed to create device file for power method\n"); - - if (radeon_debugfs_pm_init(rdev)) { - DRM_ERROR("Failed to register debugfs file for dpm!\n"); - } + ret = device_create_file(rdev->dev, &dev_attr_power_dpm_state); + if (ret) + DRM_ERROR("failed to create device file for dpm state\n"); + ret = device_create_file(rdev->dev, &dev_attr_power_dpm_force_performance_level); + if (ret) + DRM_ERROR("failed to create device file for dpm state\n"); + /* XXX: these are noops for dpm but are here for backwards compat */ + ret = device_create_file(rdev->dev, &dev_attr_power_profile); + if (ret) + DRM_ERROR("failed to create device file for power profile\n"); + ret = device_create_file(rdev->dev, &dev_attr_power_method); + if (ret) + DRM_ERROR("failed to create device file for power method\n"); - DRM_INFO("radeon: dpm initialized\n"); + if (radeon_debugfs_pm_init(rdev)) { + DRM_ERROR("Failed to register debugfs file for dpm!\n"); } + DRM_INFO("radeon: dpm initialized\n"); + return 0; + +dpm_failed: + rdev->pm.dpm_enabled = false; + if ((rdev->family >= CHIP_BARTS) && + (rdev->family <= CHIP_CAYMAN) && + rdev->mc_fw) { + if (rdev->pm.default_vddc) + radeon_atom_set_voltage(rdev, rdev->pm.default_vddc, + SET_VOLTAGE_TYPE_ASIC_VDDC); + if (rdev->pm.default_vddci) + radeon_atom_set_voltage(rdev, rdev->pm.default_vddci, + SET_VOLTAGE_TYPE_ASIC_VDDCI); + if (rdev->pm.default_sclk) + radeon_set_engine_clock(rdev, rdev->pm.default_sclk); + if (rdev->pm.default_mclk) + radeon_set_memory_clock(rdev, rdev->pm.default_mclk); + } + DRM_ERROR("radeon: dpm initialization failed\n"); + return ret; } int radeon_pm_init(struct radeon_device *rdev) @@ -1228,11 +1235,10 @@ int radeon_pm_init(struct radeon_device *rdev) case CHIP_RV670: case CHIP_RS780: case CHIP_RS880: + case CHIP_BARTS: + case CHIP_TURKS: + case CHIP_CAICOS: case CHIP_CAYMAN: - case CHIP_BONAIRE: - case CHIP_KABINI: - case CHIP_KAVERI: - case CHIP_HAWAII: /* DPM requires the RLC, RV770+ dGPU requires SMC */ if (!rdev->rlc_fw) rdev->pm.pm_method = PM_METHOD_PROFILE; @@ -1257,15 +1263,16 @@ int radeon_pm_init(struct radeon_device *rdev) case CHIP_PALM: case CHIP_SUMO: case CHIP_SUMO2: - case CHIP_BARTS: - case CHIP_TURKS: - case CHIP_CAICOS: case CHIP_ARUBA: case CHIP_TAHITI: case CHIP_PITCAIRN: case CHIP_VERDE: case CHIP_OLAND: case CHIP_HAINAN: + case CHIP_BONAIRE: + case CHIP_KABINI: + case CHIP_KAVERI: + case CHIP_HAWAII: /* DPM requires the RLC, RV770+ dGPU requires SMC */ if (!rdev->rlc_fw) rdev->pm.pm_method = PM_METHOD_PROFILE; @@ -1290,6 +1297,18 @@ int radeon_pm_init(struct radeon_device *rdev) return radeon_pm_init_old(rdev); } +int radeon_pm_late_init(struct radeon_device *rdev) +{ + int ret = 0; + + if (rdev->pm.pm_method == PM_METHOD_DPM) { + mutex_lock(&rdev->pm.mutex); + ret = radeon_dpm_late_enable(rdev); + mutex_unlock(&rdev->pm.mutex); + } + return ret; +} + static void radeon_pm_fini_old(struct radeon_device *rdev) { if (rdev->pm.num_power_states > 1) { @@ -1420,6 +1439,9 @@ static void radeon_pm_compute_clocks_dpm(struct radeon_device *rdev) struct drm_crtc *crtc; struct radeon_crtc *radeon_crtc; + if (!rdev->pm.dpm_enabled) + return; + mutex_lock(&rdev->pm.mutex); /* update active crtc counts */ @@ -1464,7 +1486,7 @@ static bool radeon_pm_in_vbl(struct radeon_device *rdev) */ for (crtc = 0; (crtc < rdev->num_crtc) && in_vbl; crtc++) { if (rdev->pm.active_crtcs & (1 << crtc)) { - vbl_status = radeon_get_crtc_scanoutpos(rdev->ddev, crtc, &vpos, &hpos, NULL, NULL); + vbl_status = radeon_get_crtc_scanoutpos(rdev->ddev, crtc, 0, &vpos, &hpos, NULL, NULL); if ((vbl_status & DRM_SCANOUTPOS_VALID) && !(vbl_status & DRM_SCANOUTPOS_INVBL)) in_vbl = false; diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index 9214403ae173..1b783f0e6d3a 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c @@ -332,36 +332,6 @@ bool radeon_ring_supports_scratch_reg(struct radeon_device *rdev, } } -u32 radeon_ring_generic_get_rptr(struct radeon_device *rdev, - struct radeon_ring *ring) -{ - u32 rptr; - - if (rdev->wb.enabled) - rptr = le32_to_cpu(rdev->wb.wb[ring->rptr_offs/4]); - else - rptr = RREG32(ring->rptr_reg); - - return rptr; -} - -u32 radeon_ring_generic_get_wptr(struct radeon_device *rdev, - struct radeon_ring *ring) -{ - u32 wptr; - - wptr = RREG32(ring->wptr_reg); - - return wptr; -} - -void radeon_ring_generic_set_wptr(struct radeon_device *rdev, - struct radeon_ring *ring) -{ - WREG32(ring->wptr_reg, ring->wptr); - (void)RREG32(ring->wptr_reg); -} - /** * radeon_ring_free_size - update the free size * @@ -463,7 +433,7 @@ void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *ring) while (ring->wptr & ring->align_mask) { radeon_ring_write(ring, ring->nop); } - DRM_MEMORYBARRIER(); + mb(); radeon_ring_set_wptr(rdev, ring); } @@ -689,22 +659,18 @@ int radeon_ring_restore(struct radeon_device *rdev, struct radeon_ring *ring, * @ring: radeon_ring structure holding ring information * @ring_size: size of the ring * @rptr_offs: offset of the rptr writeback location in the WB buffer - * @rptr_reg: MMIO offset of the rptr register - * @wptr_reg: MMIO offset of the wptr register * @nop: nop packet for this ring * * Initialize the driver information for the selected ring (all asics). * Returns 0 on success, error on failure. */ int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size, - unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg, u32 nop) + unsigned rptr_offs, u32 nop) { int r; ring->ring_size = ring_size; ring->rptr_offs = rptr_offs; - ring->rptr_reg = rptr_reg; - ring->wptr_reg = wptr_reg; ring->nop = nop; /* Allocate ring buffer */ if (ring->ring_obj == NULL) { @@ -790,34 +756,54 @@ static int radeon_debugfs_ring_info(struct seq_file *m, void *data) struct radeon_device *rdev = dev->dev_private; int ridx = *(int*)node->info_ent->data; struct radeon_ring *ring = &rdev->ring[ridx]; + + uint32_t rptr, wptr, rptr_next; unsigned count, i, j; - u32 tmp; radeon_ring_free_size(rdev, ring); count = (ring->ring_size / 4) - ring->ring_free_dw; - tmp = radeon_ring_get_wptr(rdev, ring); - seq_printf(m, "wptr(0x%04x): 0x%08x [%5d]\n", ring->wptr_reg, tmp, tmp); - tmp = radeon_ring_get_rptr(rdev, ring); - seq_printf(m, "rptr(0x%04x): 0x%08x [%5d]\n", ring->rptr_reg, tmp, tmp); + + wptr = radeon_ring_get_wptr(rdev, ring); + seq_printf(m, "wptr: 0x%08x [%5d]\n", + wptr, wptr); + + rptr = radeon_ring_get_rptr(rdev, ring); + seq_printf(m, "rptr: 0x%08x [%5d]\n", + rptr, rptr); + if (ring->rptr_save_reg) { - seq_printf(m, "rptr next(0x%04x): 0x%08x\n", ring->rptr_save_reg, - RREG32(ring->rptr_save_reg)); - } - seq_printf(m, "driver's copy of the wptr: 0x%08x [%5d]\n", ring->wptr, ring->wptr); - seq_printf(m, "driver's copy of the rptr: 0x%08x [%5d]\n", ring->rptr, ring->rptr); - seq_printf(m, "last semaphore signal addr : 0x%016llx\n", ring->last_semaphore_signal_addr); - seq_printf(m, "last semaphore wait addr : 0x%016llx\n", ring->last_semaphore_wait_addr); + rptr_next = RREG32(ring->rptr_save_reg); + seq_printf(m, "rptr next(0x%04x): 0x%08x [%5d]\n", + ring->rptr_save_reg, rptr_next, rptr_next); + } else + rptr_next = ~0; + + seq_printf(m, "driver's copy of the wptr: 0x%08x [%5d]\n", + ring->wptr, ring->wptr); + seq_printf(m, "driver's copy of the rptr: 0x%08x [%5d]\n", + ring->rptr, ring->rptr); + seq_printf(m, "last semaphore signal addr : 0x%016llx\n", + ring->last_semaphore_signal_addr); + seq_printf(m, "last semaphore wait addr : 0x%016llx\n", + ring->last_semaphore_wait_addr); seq_printf(m, "%u free dwords in ring\n", ring->ring_free_dw); seq_printf(m, "%u dwords in ring\n", count); + + if (!ring->ready) + return 0; + /* print 8 dw before current rptr as often it's the last executed * packet that is the root issue */ - i = (ring->rptr + ring->ptr_mask + 1 - 32) & ring->ptr_mask; - if (ring->ready) { - for (j = 0; j <= (count + 32); j++) { - seq_printf(m, "r[%5d]=0x%08x\n", i, ring->ring[i]); - i = (i + 1) & ring->ptr_mask; - } + i = (rptr + ring->ptr_mask + 1 - 32) & ring->ptr_mask; + for (j = 0; j <= (count + 32); j++) { + seq_printf(m, "r[%5d]=0x%08x", i, ring->ring[i]); + if (rptr == i) + seq_puts(m, " *"); + if (rptr_next == i) + seq_puts(m, " #"); + seq_puts(m, "\n"); + i = (i + 1) & ring->ptr_mask; } return 0; } diff --git a/drivers/gpu/drm/radeon/radeon_sa.c b/drivers/gpu/drm/radeon/radeon_sa.c index f0bac68254b7..c0625805cdd7 100644 --- a/drivers/gpu/drm/radeon/radeon_sa.c +++ b/drivers/gpu/drm/radeon/radeon_sa.c @@ -402,13 +402,15 @@ void radeon_sa_bo_dump_debug_info(struct radeon_sa_manager *sa_manager, spin_lock(&sa_manager->wq.lock); list_for_each_entry(i, &sa_manager->olist, olist) { + uint64_t soffset = i->soffset + sa_manager->gpu_addr; + uint64_t eoffset = i->eoffset + sa_manager->gpu_addr; if (&i->olist == sa_manager->hole) { seq_printf(m, ">"); } else { seq_printf(m, " "); } - seq_printf(m, "[0x%08x 0x%08x] size %8d", - i->soffset, i->eoffset, i->eoffset - i->soffset); + seq_printf(m, "[0x%010llx 0x%010llx] size %8lld", + soffset, eoffset, eoffset - soffset); if (i->fence) { seq_printf(m, " protected by 0x%016llx on ring %d", i->fence->seq, i->fence->ring); diff --git a/drivers/gpu/drm/radeon/radeon_state.c b/drivers/gpu/drm/radeon/radeon_state.c index 4d20910899d4..956ab7f14e16 100644 --- a/drivers/gpu/drm/radeon/radeon_state.c +++ b/drivers/gpu/drm/radeon/radeon_state.c @@ -1810,7 +1810,7 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev, } if (!buf) { DRM_DEBUG("EAGAIN\n"); - if (DRM_COPY_TO_USER(tex->image, image, sizeof(*image))) + if (copy_to_user(tex->image, image, sizeof(*image))) return -EFAULT; return -EAGAIN; } @@ -1823,7 +1823,7 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev, #define RADEON_COPY_MT(_buf, _data, _width) \ do { \ - if (DRM_COPY_FROM_USER(_buf, _data, (_width))) {\ + if (copy_from_user(_buf, _data, (_width))) {\ DRM_ERROR("EFAULT on pad, %d bytes\n", (_width)); \ return -EFAULT; \ } \ @@ -2168,7 +2168,7 @@ static int radeon_cp_clear(struct drm_device *dev, void *data, struct drm_file * if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS) sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS; - if (DRM_COPY_FROM_USER(&depth_boxes, clear->depth_boxes, + if (copy_from_user(&depth_boxes, clear->depth_boxes, sarea_priv->nbox * sizeof(depth_boxes[0]))) return -EFAULT; @@ -2436,7 +2436,7 @@ static int radeon_cp_texture(struct drm_device *dev, void *data, struct drm_file return -EINVAL; } - if (DRM_COPY_FROM_USER(&image, + if (copy_from_user(&image, (drm_radeon_tex_image_t __user *) tex->image, sizeof(image))) return -EFAULT; @@ -2460,7 +2460,7 @@ static int radeon_cp_stipple(struct drm_device *dev, void *data, struct drm_file LOCK_TEST_WITH_RETURN(dev, file_priv); - if (DRM_COPY_FROM_USER(&mask, stipple->mask, 32 * sizeof(u32))) + if (copy_from_user(&mask, stipple->mask, 32 * sizeof(u32))) return -EFAULT; RING_SPACE_TEST_WITH_RETURN(dev_priv); @@ -2585,13 +2585,13 @@ static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file drm_radeon_prim_t prim; drm_radeon_tcl_prim_t tclprim; - if (DRM_COPY_FROM_USER(&prim, &vertex->prim[i], sizeof(prim))) + if (copy_from_user(&prim, &vertex->prim[i], sizeof(prim))) return -EFAULT; if (prim.stateidx != laststate) { drm_radeon_state_t state; - if (DRM_COPY_FROM_USER(&state, + if (copy_from_user(&state, &vertex->state[prim.stateidx], sizeof(state))) return -EFAULT; @@ -2799,7 +2799,7 @@ static int radeon_emit_packet3_cliprect(struct drm_device *dev, do { if (i < cmdbuf->nbox) { - if (DRM_COPY_FROM_USER(&box, &boxes[i], sizeof(box))) + if (copy_from_user(&box, &boxes[i], sizeof(box))) return -EFAULT; /* FIXME The second and subsequent times round * this loop, send a WAIT_UNTIL_3D_IDLE before @@ -3116,7 +3116,7 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil return -EINVAL; } - if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) { + if (copy_to_user(param->value, &value, sizeof(int))) { DRM_ERROR("copy_to_user\n"); return -EFAULT; } diff --git a/drivers/gpu/drm/radeon/radeon_trace.h b/drivers/gpu/drm/radeon/radeon_trace.h index 0473257d4078..f749f2c3bbdb 100644 --- a/drivers/gpu/drm/radeon/radeon_trace.h +++ b/drivers/gpu/drm/radeon/radeon_trace.h @@ -106,42 +106,45 @@ TRACE_EVENT(radeon_vm_set_page, DECLARE_EVENT_CLASS(radeon_fence_request, - TP_PROTO(struct drm_device *dev, u32 seqno), + TP_PROTO(struct drm_device *dev, int ring, u32 seqno), - TP_ARGS(dev, seqno), + TP_ARGS(dev, ring, seqno), TP_STRUCT__entry( __field(u32, dev) + __field(int, ring) __field(u32, seqno) ), TP_fast_assign( __entry->dev = dev->primary->index; + __entry->ring = ring; __entry->seqno = seqno; ), - TP_printk("dev=%u, seqno=%u", __entry->dev, __entry->seqno) + TP_printk("dev=%u, ring=%d, seqno=%u", + __entry->dev, __entry->ring, __entry->seqno) ); DEFINE_EVENT(radeon_fence_request, radeon_fence_emit, - TP_PROTO(struct drm_device *dev, u32 seqno), + TP_PROTO(struct drm_device *dev, int ring, u32 seqno), - TP_ARGS(dev, seqno) + TP_ARGS(dev, ring, seqno) ); DEFINE_EVENT(radeon_fence_request, radeon_fence_wait_begin, - TP_PROTO(struct drm_device *dev, u32 seqno), + TP_PROTO(struct drm_device *dev, int ring, u32 seqno), - TP_ARGS(dev, seqno) + TP_ARGS(dev, ring, seqno) ); DEFINE_EVENT(radeon_fence_request, radeon_fence_wait_end, - TP_PROTO(struct drm_device *dev, u32 seqno), + TP_PROTO(struct drm_device *dev, int ring, u32 seqno), - TP_ARGS(dev, seqno) + TP_ARGS(dev, ring, seqno) ); DECLARE_EVENT_CLASS(radeon_semaphore_request, diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 71245d6f34a2..77f5b0c3edb8 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -39,12 +39,14 @@ #include <linux/seq_file.h> #include <linux/slab.h> #include <linux/swiotlb.h> +#include <linux/debugfs.h> #include "radeon_reg.h" #include "radeon.h" #define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) static int radeon_ttm_debugfs_init(struct radeon_device *rdev); +static void radeon_ttm_debugfs_fini(struct radeon_device *rdev); static struct radeon_device *radeon_get_rdev(struct ttm_bo_device *bdev) { @@ -142,7 +144,7 @@ static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, man->flags = TTM_MEMTYPE_FLAG_MAPPABLE | TTM_MEMTYPE_FLAG_CMA; #if __OS_HAS_AGP if (rdev->flags & RADEON_IS_AGP) { - if (!(drm_core_has_AGP(rdev->ddev) && rdev->ddev->agp)) { + if (!rdev->ddev->agp) { DRM_ERROR("AGP is not enabled for memory type %u\n", (unsigned)type); return -EINVAL; @@ -753,6 +755,7 @@ void radeon_ttm_fini(struct radeon_device *rdev) if (!rdev->mman.initialized) return; + radeon_ttm_debugfs_fini(rdev); if (rdev->stollen_vga_memory) { r = radeon_bo_reserve(rdev->stollen_vga_memory, false); if (r == 0) { @@ -832,16 +835,15 @@ int radeon_mmap(struct file *filp, struct vm_area_struct *vma) return 0; } - -#define RADEON_DEBUGFS_MEM_TYPES 2 - #if defined(CONFIG_DEBUG_FS) + static int radeon_mm_dump_table(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *)m->private; - struct drm_mm *mm = (struct drm_mm *)node->info_ent->data; + unsigned ttm_pl = *(int *)node->info_ent->data; struct drm_device *dev = node->minor->dev; struct radeon_device *rdev = dev->dev_private; + struct drm_mm *mm = (struct drm_mm *)rdev->mman.bdev.man[ttm_pl].priv; int ret; struct ttm_bo_global *glob = rdev->mman.bdev.glob; @@ -850,46 +852,169 @@ static int radeon_mm_dump_table(struct seq_file *m, void *data) spin_unlock(&glob->lru_lock); return ret; } + +static int ttm_pl_vram = TTM_PL_VRAM; +static int ttm_pl_tt = TTM_PL_TT; + +static struct drm_info_list radeon_ttm_debugfs_list[] = { + {"radeon_vram_mm", radeon_mm_dump_table, 0, &ttm_pl_vram}, + {"radeon_gtt_mm", radeon_mm_dump_table, 0, &ttm_pl_tt}, + {"ttm_page_pool", ttm_page_alloc_debugfs, 0, NULL}, +#ifdef CONFIG_SWIOTLB + {"ttm_dma_page_pool", ttm_dma_page_alloc_debugfs, 0, NULL} #endif +}; -static int radeon_ttm_debugfs_init(struct radeon_device *rdev) +static int radeon_ttm_vram_open(struct inode *inode, struct file *filep) { -#if defined(CONFIG_DEBUG_FS) - static struct drm_info_list radeon_mem_types_list[RADEON_DEBUGFS_MEM_TYPES+2]; - static char radeon_mem_types_names[RADEON_DEBUGFS_MEM_TYPES+2][32]; - unsigned i; + struct radeon_device *rdev = inode->i_private; + i_size_write(inode, rdev->mc.mc_vram_size); + filep->private_data = inode->i_private; + return 0; +} - for (i = 0; i < RADEON_DEBUGFS_MEM_TYPES; i++) { - if (i == 0) - sprintf(radeon_mem_types_names[i], "radeon_vram_mm"); - else - sprintf(radeon_mem_types_names[i], "radeon_gtt_mm"); - radeon_mem_types_list[i].name = radeon_mem_types_names[i]; - radeon_mem_types_list[i].show = &radeon_mm_dump_table; - radeon_mem_types_list[i].driver_features = 0; - if (i == 0) - radeon_mem_types_list[i].data = rdev->mman.bdev.man[TTM_PL_VRAM].priv; - else - radeon_mem_types_list[i].data = rdev->mman.bdev.man[TTM_PL_TT].priv; +static ssize_t radeon_ttm_vram_read(struct file *f, char __user *buf, + size_t size, loff_t *pos) +{ + struct radeon_device *rdev = f->private_data; + ssize_t result = 0; + int r; + if (size & 0x3 || *pos & 0x3) + return -EINVAL; + + while (size) { + unsigned long flags; + uint32_t value; + + if (*pos >= rdev->mc.mc_vram_size) + return result; + + spin_lock_irqsave(&rdev->mmio_idx_lock, flags); + WREG32(RADEON_MM_INDEX, ((uint32_t)*pos) | 0x80000000); + if (rdev->family >= CHIP_CEDAR) + WREG32(EVERGREEN_MM_INDEX_HI, *pos >> 31); + value = RREG32(RADEON_MM_DATA); + spin_unlock_irqrestore(&rdev->mmio_idx_lock, flags); + + r = put_user(value, (uint32_t *)buf); + if (r) + return r; + + result += 4; + buf += 4; + *pos += 4; + size -= 4; } - /* Add ttm page pool to debugfs */ - sprintf(radeon_mem_types_names[i], "ttm_page_pool"); - radeon_mem_types_list[i].name = radeon_mem_types_names[i]; - radeon_mem_types_list[i].show = &ttm_page_alloc_debugfs; - radeon_mem_types_list[i].driver_features = 0; - radeon_mem_types_list[i++].data = NULL; -#ifdef CONFIG_SWIOTLB - if (swiotlb_nr_tbl()) { - sprintf(radeon_mem_types_names[i], "ttm_dma_page_pool"); - radeon_mem_types_list[i].name = radeon_mem_types_names[i]; - radeon_mem_types_list[i].show = &ttm_dma_page_alloc_debugfs; - radeon_mem_types_list[i].driver_features = 0; - radeon_mem_types_list[i++].data = NULL; + + return result; +} + +static const struct file_operations radeon_ttm_vram_fops = { + .owner = THIS_MODULE, + .open = radeon_ttm_vram_open, + .read = radeon_ttm_vram_read, + .llseek = default_llseek +}; + +static int radeon_ttm_gtt_open(struct inode *inode, struct file *filep) +{ + struct radeon_device *rdev = inode->i_private; + i_size_write(inode, rdev->mc.gtt_size); + filep->private_data = inode->i_private; + return 0; +} + +static ssize_t radeon_ttm_gtt_read(struct file *f, char __user *buf, + size_t size, loff_t *pos) +{ + struct radeon_device *rdev = f->private_data; + ssize_t result = 0; + int r; + + while (size) { + loff_t p = *pos / PAGE_SIZE; + unsigned off = *pos & ~PAGE_MASK; + ssize_t cur_size = min(size, PAGE_SIZE - off); + struct page *page; + void *ptr; + + if (p >= rdev->gart.num_cpu_pages) + return result; + + page = rdev->gart.pages[p]; + if (page) { + ptr = kmap(page); + ptr += off; + + r = copy_to_user(buf, ptr, cur_size); + kunmap(rdev->gart.pages[p]); + } else + r = clear_user(buf, cur_size); + + if (r) + return -EFAULT; + + result += cur_size; + buf += cur_size; + *pos += cur_size; + size -= cur_size; } + + return result; +} + +static const struct file_operations radeon_ttm_gtt_fops = { + .owner = THIS_MODULE, + .open = radeon_ttm_gtt_open, + .read = radeon_ttm_gtt_read, + .llseek = default_llseek +}; + #endif - return radeon_debugfs_add_files(rdev, radeon_mem_types_list, i); +static int radeon_ttm_debugfs_init(struct radeon_device *rdev) +{ +#if defined(CONFIG_DEBUG_FS) + unsigned count; + + struct drm_minor *minor = rdev->ddev->primary; + struct dentry *ent, *root = minor->debugfs_root; + + ent = debugfs_create_file("radeon_vram", S_IFREG | S_IRUGO, root, + rdev, &radeon_ttm_vram_fops); + if (IS_ERR(ent)) + return PTR_ERR(ent); + rdev->mman.vram = ent; + + ent = debugfs_create_file("radeon_gtt", S_IFREG | S_IRUGO, root, + rdev, &radeon_ttm_gtt_fops); + if (IS_ERR(ent)) + return PTR_ERR(ent); + rdev->mman.gtt = ent; + + count = ARRAY_SIZE(radeon_ttm_debugfs_list); + +#ifdef CONFIG_SWIOTLB + if (!swiotlb_nr_tbl()) + --count; #endif + + return radeon_debugfs_add_files(rdev, radeon_ttm_debugfs_list, count); +#else + return 0; +#endif +} + +static void radeon_ttm_debugfs_fini(struct radeon_device *rdev) +{ +#if defined(CONFIG_DEBUG_FS) + + debugfs_remove(rdev->mman.vram); + rdev->mman.vram = NULL; + + debugfs_remove(rdev->mman.gtt); + rdev->mman.gtt = NULL; +#endif } diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c index b9c0529b4a2e..6781fee1eaad 100644 --- a/drivers/gpu/drm/radeon/radeon_uvd.c +++ b/drivers/gpu/drm/radeon/radeon_uvd.c @@ -91,6 +91,7 @@ int radeon_uvd_init(struct radeon_device *rdev) case CHIP_VERDE: case CHIP_PITCAIRN: case CHIP_ARUBA: + case CHIP_OLAND: fw_name = FIRMWARE_TAHITI; break; @@ -778,6 +779,8 @@ static void radeon_uvd_idle_work_handler(struct work_struct *work) if (radeon_fence_count_emitted(rdev, R600_RING_TYPE_UVD_INDEX) == 0) { if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) { + radeon_uvd_count_handles(rdev, &rdev->pm.dpm.sd, + &rdev->pm.dpm.hd); radeon_dpm_enable_uvd(rdev, false); } else { radeon_set_uvd_clocks(rdev, 0, 0); diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index 9566b5940a5a..b5c2369cda2f 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c @@ -474,6 +474,8 @@ int rs400_resume(struct radeon_device *rdev) /* Initialize surface registers */ radeon_surface_init(rdev); + radeon_pm_resume(rdev); + rdev->accel_working = true; r = rs400_startup(rdev); if (r) { @@ -484,6 +486,7 @@ int rs400_resume(struct radeon_device *rdev) int rs400_suspend(struct radeon_device *rdev) { + radeon_pm_suspend(rdev); r100_cp_disable(rdev); radeon_wb_disable(rdev); r100_irq_disable(rdev); @@ -493,6 +496,7 @@ int rs400_suspend(struct radeon_device *rdev) void rs400_fini(struct radeon_device *rdev) { + radeon_pm_fini(rdev); r100_cp_fini(rdev); radeon_wb_fini(rdev); radeon_ib_pool_fini(rdev); @@ -560,6 +564,9 @@ int rs400_init(struct radeon_device *rdev) return r; r300_set_reg_safe(rdev); + /* Initialize power management */ + radeon_pm_init(rdev); + rdev->accel_working = true; r = rs400_startup(rdev); if (r) { diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 76cc8d3aafec..fdcde7693032 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -1048,6 +1048,8 @@ int rs600_resume(struct radeon_device *rdev) /* Initialize surface registers */ radeon_surface_init(rdev); + radeon_pm_resume(rdev); + rdev->accel_working = true; r = rs600_startup(rdev); if (r) { @@ -1058,6 +1060,7 @@ int rs600_resume(struct radeon_device *rdev) int rs600_suspend(struct radeon_device *rdev) { + radeon_pm_suspend(rdev); r600_audio_fini(rdev); r100_cp_disable(rdev); radeon_wb_disable(rdev); @@ -1068,6 +1071,7 @@ int rs600_suspend(struct radeon_device *rdev) void rs600_fini(struct radeon_device *rdev) { + radeon_pm_fini(rdev); r600_audio_fini(rdev); r100_cp_fini(rdev); radeon_wb_fini(rdev); @@ -1136,6 +1140,9 @@ int rs600_init(struct radeon_device *rdev) return r; rs600_set_safe_registers(rdev); + /* Initialize power management */ + radeon_pm_init(rdev); + rdev->accel_working = true; r = rs600_startup(rdev); if (r) { diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index e7dab069cccf..35950738bd5e 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c @@ -756,6 +756,8 @@ int rs690_resume(struct radeon_device *rdev) /* Initialize surface registers */ radeon_surface_init(rdev); + radeon_pm_resume(rdev); + rdev->accel_working = true; r = rs690_startup(rdev); if (r) { @@ -766,6 +768,7 @@ int rs690_resume(struct radeon_device *rdev) int rs690_suspend(struct radeon_device *rdev) { + radeon_pm_suspend(rdev); r600_audio_fini(rdev); r100_cp_disable(rdev); radeon_wb_disable(rdev); @@ -776,6 +779,7 @@ int rs690_suspend(struct radeon_device *rdev) void rs690_fini(struct radeon_device *rdev) { + radeon_pm_fini(rdev); r600_audio_fini(rdev); r100_cp_fini(rdev); radeon_wb_fini(rdev); @@ -845,6 +849,9 @@ int rs690_init(struct radeon_device *rdev) return r; rs600_set_safe_registers(rdev); + /* Initialize power management */ + radeon_pm_init(rdev); + rdev->accel_working = true; r = rs690_startup(rdev); if (r) { diff --git a/drivers/gpu/drm/radeon/rs780_dpm.c b/drivers/gpu/drm/radeon/rs780_dpm.c index 6af8505cf4d2..8512085b0aef 100644 --- a/drivers/gpu/drm/radeon/rs780_dpm.c +++ b/drivers/gpu/drm/radeon/rs780_dpm.c @@ -623,14 +623,6 @@ int rs780_dpm_enable(struct radeon_device *rdev) if (pi->gfx_clock_gating) r600_gfx_clockgating_enable(rdev, true); - if (rdev->irq.installed && (rdev->pm.int_thermal_type == THERMAL_TYPE_RV6XX)) { - ret = r600_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX); - if (ret) - return ret; - rdev->irq.dpm_thermal = true; - radeon_irq_set(rdev); - } - return 0; } diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index 5d1c316115ef..98e8138ff779 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c @@ -586,6 +586,8 @@ int rv515_resume(struct radeon_device *rdev) /* Initialize surface registers */ radeon_surface_init(rdev); + radeon_pm_resume(rdev); + rdev->accel_working = true; r = rv515_startup(rdev); if (r) { @@ -596,6 +598,7 @@ int rv515_resume(struct radeon_device *rdev) int rv515_suspend(struct radeon_device *rdev) { + radeon_pm_suspend(rdev); r100_cp_disable(rdev); radeon_wb_disable(rdev); rs600_irq_disable(rdev); @@ -612,6 +615,7 @@ void rv515_set_safe_registers(struct radeon_device *rdev) void rv515_fini(struct radeon_device *rdev) { + radeon_pm_fini(rdev); r100_cp_fini(rdev); radeon_wb_fini(rdev); radeon_ib_pool_fini(rdev); @@ -685,6 +689,9 @@ int rv515_init(struct radeon_device *rdev) return r; rv515_set_safe_registers(rdev); + /* Initialize power management */ + radeon_pm_init(rdev); + rdev->accel_working = true; r = rv515_startup(rdev); if (r) { diff --git a/drivers/gpu/drm/radeon/rv6xx_dpm.c b/drivers/gpu/drm/radeon/rv6xx_dpm.c index 26633a025252..bebf31c4d841 100644 --- a/drivers/gpu/drm/radeon/rv6xx_dpm.c +++ b/drivers/gpu/drm/radeon/rv6xx_dpm.c @@ -1546,7 +1546,6 @@ int rv6xx_dpm_enable(struct radeon_device *rdev) { struct rv6xx_power_info *pi = rv6xx_get_pi(rdev); struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps; - int ret; if (r600_dynamicpm_enabled(rdev)) return -EINVAL; @@ -1594,15 +1593,6 @@ int rv6xx_dpm_enable(struct radeon_device *rdev) r600_power_level_enable(rdev, R600_POWER_LEVEL_MEDIUM, true); r600_power_level_enable(rdev, R600_POWER_LEVEL_HIGH, true); - if (rdev->irq.installed && - r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) { - ret = r600_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX); - if (ret) - return ret; - rdev->irq.dpm_thermal = true; - radeon_irq_set(rdev); - } - rv6xx_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true); r600_start_dpm(rdev); diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 9f5846743c9e..6c772e58c784 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -1071,7 +1071,8 @@ static void rv770_mc_program(struct radeon_device *rdev) */ void r700_cp_stop(struct radeon_device *rdev) { - radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); + if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX) + radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT)); WREG32(SCRATCH_UMSK, 0); rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; @@ -1123,6 +1124,35 @@ void r700_cp_fini(struct radeon_device *rdev) radeon_scratch_free(rdev, ring->rptr_save_reg); } +void rv770_set_clk_bypass_mode(struct radeon_device *rdev) +{ + u32 tmp, i; + + if (rdev->flags & RADEON_IS_IGP) + return; + + tmp = RREG32(CG_SPLL_FUNC_CNTL_2); + tmp &= SCLK_MUX_SEL_MASK; + tmp |= SCLK_MUX_SEL(1) | SCLK_MUX_UPDATE; + WREG32(CG_SPLL_FUNC_CNTL_2, tmp); + + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(CG_SPLL_STATUS) & SPLL_CHG_STATUS) + break; + udelay(1); + } + + tmp &= ~SCLK_MUX_UPDATE; + WREG32(CG_SPLL_FUNC_CNTL_2, tmp); + + tmp = RREG32(MPLL_CNTL_MODE); + if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730)) + tmp &= ~RV730_MPLL_MCLK_SEL; + else + tmp &= ~MPLL_MCLK_SEL; + WREG32(MPLL_CNTL_MODE, tmp); +} + /* * Core functions */ @@ -1665,14 +1695,6 @@ static int rv770_startup(struct radeon_device *rdev) rv770_mc_program(rdev); - if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { - r = r600_init_microcode(rdev); - if (r) { - DRM_ERROR("Failed to load firmware!\n"); - return r; - } - } - if (rdev->flags & RADEON_IS_AGP) { rv770_agp_enable(rdev); } else { @@ -1728,14 +1750,12 @@ static int rv770_startup(struct radeon_device *rdev) ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET, - R600_CP_RB_RPTR, R600_CP_RB_WPTR, RADEON_CP_PACKET2); if (r) return r; ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX]; r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET, - DMA_RB_RPTR, DMA_RB_WPTR, DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0)); if (r) return r; @@ -1754,7 +1774,6 @@ static int rv770_startup(struct radeon_device *rdev) ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; if (ring->ring_size) { r = radeon_ring_init(rdev, ring, ring->ring_size, 0, - UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR, RADEON_CP_PACKET2); if (!r) r = uvd_v1_0_init(rdev); @@ -1792,6 +1811,8 @@ int rv770_resume(struct radeon_device *rdev) /* init golden registers */ rv770_init_golden_registers(rdev); + radeon_pm_resume(rdev); + rdev->accel_working = true; r = rv770_startup(rdev); if (r) { @@ -1806,6 +1827,7 @@ int rv770_resume(struct radeon_device *rdev) int rv770_suspend(struct radeon_device *rdev) { + radeon_pm_suspend(rdev); r600_audio_fini(rdev); uvd_v1_0_fini(rdev); radeon_uvd_suspend(rdev); @@ -1876,6 +1898,17 @@ int rv770_init(struct radeon_device *rdev) if (r) return r; + if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { + r = r600_init_microcode(rdev); + if (r) { + DRM_ERROR("Failed to load firmware!\n"); + return r; + } + } + + /* Initialize power management */ + radeon_pm_init(rdev); + rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL; r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024); @@ -1915,6 +1948,7 @@ int rv770_init(struct radeon_device *rdev) void rv770_fini(struct radeon_device *rdev) { + radeon_pm_fini(rdev); r700_cp_fini(rdev); r600_dma_fini(rdev); r600_irq_fini(rdev); diff --git a/drivers/gpu/drm/radeon/rv770_dpm.c b/drivers/gpu/drm/radeon/rv770_dpm.c index 374499db20c7..80c595aba359 100644 --- a/drivers/gpu/drm/radeon/rv770_dpm.c +++ b/drivers/gpu/drm/radeon/rv770_dpm.c @@ -1863,8 +1863,8 @@ void rv770_enable_auto_throttle_source(struct radeon_device *rdev, } } -int rv770_set_thermal_temperature_range(struct radeon_device *rdev, - int min_temp, int max_temp) +static int rv770_set_thermal_temperature_range(struct radeon_device *rdev, + int min_temp, int max_temp) { int low_temp = 0 * 1000; int high_temp = 255 * 1000; @@ -1966,6 +1966,15 @@ int rv770_dpm_enable(struct radeon_device *rdev) if (pi->mg_clock_gating) rv770_mg_clock_gating_enable(rdev, true); + rv770_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true); + + return 0; +} + +int rv770_dpm_late_enable(struct radeon_device *rdev) +{ + int ret; + if (rdev->irq.installed && r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) { PPSMC_Result result; @@ -1981,8 +1990,6 @@ int rv770_dpm_enable(struct radeon_device *rdev) DRM_DEBUG_KMS("Could not enable thermal interrupts.\n"); } - rv770_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true); - return 0; } @@ -2244,14 +2251,12 @@ static void rv7xx_parse_pplib_clock_info(struct radeon_device *rdev, pl->vddci = vddci; } - if (rdev->family >= CHIP_BARTS) { - if ((rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == - ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) { - rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.sclk = pl->sclk; - rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.mclk = pl->mclk; - rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddc = pl->vddc; - rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddci = pl->vddci; - } + if ((rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == + ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) { + rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.sclk = pl->sclk; + rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.mclk = pl->mclk; + rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddc = pl->vddc; + rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddci = pl->vddci; } } @@ -2531,6 +2536,12 @@ bool rv770_dpm_vblank_too_short(struct radeon_device *rdev) (rdev->pdev->subsystem_device == 0x1c42)) switch_limit = 200; + /* RV770 */ + /* mclk switching doesn't seem to work reliably on desktop RV770s */ + if ((rdev->family == CHIP_RV770) && + !(rdev->flags & RADEON_IS_MOBILITY)) + switch_limit = 0xffffffff; /* disable mclk switching */ + if (vblank_time < switch_limit) return true; else diff --git a/drivers/gpu/drm/radeon/rv770_dpm.h b/drivers/gpu/drm/radeon/rv770_dpm.h index 9244effc6b59..f776634840c9 100644 --- a/drivers/gpu/drm/radeon/rv770_dpm.h +++ b/drivers/gpu/drm/radeon/rv770_dpm.h @@ -283,8 +283,4 @@ int rv770_read_smc_soft_register(struct radeon_device *rdev, int rv770_write_smc_soft_register(struct radeon_device *rdev, u16 reg_offset, u32 value); -/* thermal */ -int rv770_set_thermal_temperature_range(struct radeon_device *rdev, - int min_temp, int max_temp); - #endif diff --git a/drivers/gpu/drm/radeon/rv770d.h b/drivers/gpu/drm/radeon/rv770d.h index 1ae277152cc7..3cf1e2921545 100644 --- a/drivers/gpu/drm/radeon/rv770d.h +++ b/drivers/gpu/drm/radeon/rv770d.h @@ -100,14 +100,21 @@ #define CG_SPLL_FUNC_CNTL_2 0x604 #define SCLK_MUX_SEL(x) ((x) << 0) #define SCLK_MUX_SEL_MASK (0x1ff << 0) +#define SCLK_MUX_UPDATE (1 << 26) #define CG_SPLL_FUNC_CNTL_3 0x608 #define SPLL_FB_DIV(x) ((x) << 0) #define SPLL_FB_DIV_MASK (0x3ffffff << 0) #define SPLL_DITHEN (1 << 28) +#define CG_SPLL_STATUS 0x60c +#define SPLL_CHG_STATUS (1 << 1) #define SPLL_CNTL_MODE 0x610 #define SPLL_DIV_SYNC (1 << 5) +#define MPLL_CNTL_MODE 0x61c +# define MPLL_MCLK_SEL (1 << 11) +# define RV730_MPLL_MCLK_SEL (1 << 25) + #define MPLL_AD_FUNC_CNTL 0x624 #define CLKF(x) ((x) << 0) #define CLKF_MASK (0x7f << 0) diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 85e1edfaa3be..09ec4f6c53bb 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -80,6 +80,8 @@ extern void evergreen_print_gpu_status_regs(struct radeon_device *rdev); extern bool evergreen_is_display_hung(struct radeon_device *rdev); static void si_enable_gui_idle_interrupt(struct radeon_device *rdev, bool enable); +static void si_init_pg(struct radeon_device *rdev); +static void si_init_cg(struct radeon_device *rdev); static void si_fini_pg(struct radeon_device *rdev); static void si_fini_cg(struct radeon_device *rdev); static void si_rlc_stop(struct radeon_device *rdev); @@ -1460,7 +1462,7 @@ static const u32 hainan_io_mc_regs[TAHITI_IO_MC_REGS_SIZE][2] = { }; /* ucode loading */ -static int si_mc_load_microcode(struct radeon_device *rdev) +int si_mc_load_microcode(struct radeon_device *rdev) { const __be32 *fw_data; u32 running, blackout = 0; @@ -3247,7 +3249,8 @@ static void si_cp_enable(struct radeon_device *rdev, bool enable) if (enable) WREG32(CP_ME_CNTL, 0); else { - radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); + if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX) + radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT)); WREG32(SCRATCH_UMSK, 0); rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; @@ -3508,6 +3511,9 @@ static int si_cp_resume(struct radeon_device *rdev) si_enable_gui_idle_interrupt(rdev, true); + if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX) + radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); + return 0; } @@ -3724,6 +3730,106 @@ static void si_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) evergreen_print_gpu_status_regs(rdev); } +static void si_set_clk_bypass_mode(struct radeon_device *rdev) +{ + u32 tmp, i; + + tmp = RREG32(CG_SPLL_FUNC_CNTL); + tmp |= SPLL_BYPASS_EN; + WREG32(CG_SPLL_FUNC_CNTL, tmp); + + tmp = RREG32(CG_SPLL_FUNC_CNTL_2); + tmp |= SPLL_CTLREQ_CHG; + WREG32(CG_SPLL_FUNC_CNTL_2, tmp); + + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(SPLL_STATUS) & SPLL_CHG_STATUS) + break; + udelay(1); + } + + tmp = RREG32(CG_SPLL_FUNC_CNTL_2); + tmp &= ~(SPLL_CTLREQ_CHG | SCLK_MUX_UPDATE); + WREG32(CG_SPLL_FUNC_CNTL_2, tmp); + + tmp = RREG32(MPLL_CNTL_MODE); + tmp &= ~MPLL_MCLK_SEL; + WREG32(MPLL_CNTL_MODE, tmp); +} + +static void si_spll_powerdown(struct radeon_device *rdev) +{ + u32 tmp; + + tmp = RREG32(SPLL_CNTL_MODE); + tmp |= SPLL_SW_DIR_CONTROL; + WREG32(SPLL_CNTL_MODE, tmp); + + tmp = RREG32(CG_SPLL_FUNC_CNTL); + tmp |= SPLL_RESET; + WREG32(CG_SPLL_FUNC_CNTL, tmp); + + tmp = RREG32(CG_SPLL_FUNC_CNTL); + tmp |= SPLL_SLEEP; + WREG32(CG_SPLL_FUNC_CNTL, tmp); + + tmp = RREG32(SPLL_CNTL_MODE); + tmp &= ~SPLL_SW_DIR_CONTROL; + WREG32(SPLL_CNTL_MODE, tmp); +} + +static void si_gpu_pci_config_reset(struct radeon_device *rdev) +{ + struct evergreen_mc_save save; + u32 tmp, i; + + dev_info(rdev->dev, "GPU pci config reset\n"); + + /* disable dpm? */ + + /* disable cg/pg */ + si_fini_pg(rdev); + si_fini_cg(rdev); + + /* Disable CP parsing/prefetching */ + WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT); + /* dma0 */ + tmp = RREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET); + tmp &= ~DMA_RB_ENABLE; + WREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET, tmp); + /* dma1 */ + tmp = RREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET); + tmp &= ~DMA_RB_ENABLE; + WREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET, tmp); + /* XXX other engines? */ + + /* halt the rlc, disable cp internal ints */ + si_rlc_stop(rdev); + + udelay(50); + + /* disable mem access */ + evergreen_mc_stop(rdev, &save); + if (evergreen_mc_wait_for_idle(rdev)) { + dev_warn(rdev->dev, "Wait for MC idle timed out !\n"); + } + + /* set mclk/sclk to bypass */ + si_set_clk_bypass_mode(rdev); + /* powerdown spll */ + si_spll_powerdown(rdev); + /* disable BM */ + pci_clear_master(rdev->pdev); + /* reset */ + radeon_pci_config_reset(rdev); + /* wait for asic to come out of reset */ + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(CONFIG_MEMSIZE) != 0xffffffff) + break; + udelay(1); + } +} + int si_asic_reset(struct radeon_device *rdev) { u32 reset_mask; @@ -3733,10 +3839,17 @@ int si_asic_reset(struct radeon_device *rdev) if (reset_mask) r600_set_bios_scratch_engine_hung(rdev, true); + /* try soft reset */ si_gpu_soft_reset(rdev, reset_mask); reset_mask = si_gpu_check_soft_reset(rdev); + /* try pci config reset */ + if (reset_mask && radeon_hard_reset) + si_gpu_pci_config_reset(rdev); + + reset_mask = si_gpu_check_soft_reset(rdev); + if (!reset_mask) r600_set_bios_scratch_engine_hung(rdev, false); @@ -5212,8 +5325,8 @@ static void si_enable_hdp_ls(struct radeon_device *rdev, WREG32(HDP_MEM_POWER_LS, data); } -void si_update_cg(struct radeon_device *rdev, - u32 block, bool enable) +static void si_update_cg(struct radeon_device *rdev, + u32 block, bool enable) { if (block & RADEON_CG_BLOCK_GFX) { si_enable_gui_idle_interrupt(rdev, false); @@ -5379,6 +5492,9 @@ static void si_init_pg(struct radeon_device *rdev) si_init_ao_cu_mask(rdev); if (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_PG) { si_init_gfx_cgpg(rdev); + } else { + WREG32(RLC_SAVE_AND_RESTORE_BASE, rdev->rlc.save_restore_gpu_addr >> 8); + WREG32(RLC_CLEAR_STATE_RESTORE_BASE, rdev->rlc.clear_state_gpu_addr >> 8); } si_enable_dma_pg(rdev, true); si_enable_gfx_cgpg(rdev, true); @@ -5566,7 +5682,7 @@ static void si_disable_interrupt_state(struct radeon_device *rdev) } if (!ASIC_IS_NODCE(rdev)) { - WREG32(DACA_AUTODETECT_INT_CONTROL, 0); + WREG32(DAC_AUTODETECT_INT_CONTROL, 0); tmp = RREG32(DC_HPD1_INT_CONTROL) & DC_HPDx_INT_POLARITY; WREG32(DC_HPD1_INT_CONTROL, tmp); @@ -6324,21 +6440,14 @@ static int si_startup(struct radeon_device *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); + if (!rdev->pm.dpm_enabled) { + r = si_mc_load_microcode(rdev); if (r) { - DRM_ERROR("Failed to load firmware!\n"); + DRM_ERROR("Failed to load MC firmware!\n"); return r; } } - r = si_mc_load_microcode(rdev); - if (r) { - DRM_ERROR("Failed to load MC firmware!\n"); - return r; - } - r = si_pcie_gart_enable(rdev); if (r) return r; @@ -6421,37 +6530,30 @@ static int si_startup(struct radeon_device *rdev) ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET, - CP_RB0_RPTR, CP_RB0_WPTR, RADEON_CP_PACKET2); if (r) return r; ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]; r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP1_RPTR_OFFSET, - CP_RB1_RPTR, CP_RB1_WPTR, RADEON_CP_PACKET2); if (r) return r; ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]; r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP2_RPTR_OFFSET, - CP_RB2_RPTR, CP_RB2_WPTR, RADEON_CP_PACKET2); if (r) return r; ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX]; r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET, - DMA_RB_RPTR + DMA0_REGISTER_OFFSET, - DMA_RB_WPTR + DMA0_REGISTER_OFFSET, DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0)); if (r) return r; ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX]; r = radeon_ring_init(rdev, ring, ring->ring_size, CAYMAN_WB_DMA1_RPTR_OFFSET, - DMA_RB_RPTR + DMA1_REGISTER_OFFSET, - DMA_RB_WPTR + DMA1_REGISTER_OFFSET, DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0)); if (r) return r; @@ -6471,7 +6573,6 @@ static int si_startup(struct radeon_device *rdev) ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; if (ring->ring_size) { r = radeon_ring_init(rdev, ring, ring->ring_size, 0, - UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR, RADEON_CP_PACKET2); if (!r) r = uvd_v1_0_init(rdev); @@ -6513,6 +6614,8 @@ int si_resume(struct radeon_device *rdev) /* init golden registers */ si_init_golden_registers(rdev); + radeon_pm_resume(rdev); + rdev->accel_working = true; r = si_startup(rdev); if (r) { @@ -6527,6 +6630,7 @@ int si_resume(struct radeon_device *rdev) int si_suspend(struct radeon_device *rdev) { + radeon_pm_suspend(rdev); dce6_audio_fini(rdev); radeon_vm_manager_fini(rdev); si_cp_enable(rdev, false); @@ -6600,6 +6704,18 @@ int si_init(struct radeon_device *rdev) if (r) return r; + if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw || + !rdev->rlc_fw || !rdev->mc_fw) { + r = si_init_microcode(rdev); + if (r) { + DRM_ERROR("Failed to load firmware!\n"); + return r; + } + } + + /* Initialize power management */ + radeon_pm_init(rdev); + ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; ring->ring_obj = NULL; r600_ring_init(rdev, ring, 1024 * 1024); @@ -6666,6 +6782,7 @@ int si_init(struct radeon_device *rdev) void si_fini(struct radeon_device *rdev) { + radeon_pm_fini(rdev); si_cp_fini(rdev); cayman_dma_fini(rdev); si_fini_pg(rdev); diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c index 0b00c790fb77..0471501338fb 100644 --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c @@ -1738,6 +1738,8 @@ struct evergreen_power_info *evergreen_get_pi(struct radeon_device *rdev); struct ni_power_info *ni_get_pi(struct radeon_device *rdev); struct ni_ps *ni_get_ps(struct radeon_ps *rps); +extern int si_mc_load_microcode(struct radeon_device *rdev); + static int si_populate_voltage_value(struct radeon_device *rdev, const struct atom_voltage_table *table, u16 value, SISLANDS_SMC_VOLTAGE_VALUE *voltage); @@ -1753,9 +1755,6 @@ static int si_calculate_sclk_params(struct radeon_device *rdev, u32 engine_clock, SISLANDS_SMC_SCLK_VALUE *sclk); -extern void si_update_cg(struct radeon_device *rdev, - u32 block, bool enable); - static struct si_power_info *si_get_pi(struct radeon_device *rdev) { struct si_power_info *pi = rdev->pm.dpm.priv; @@ -2396,7 +2395,7 @@ static int si_populate_sq_ramping_values(struct radeon_device *rdev, if (SISLANDS_DPM2_SQ_RAMP_STI_SIZE > (STI_SIZE_MASK >> STI_SIZE_SHIFT)) enable_sq_ramping = false; - if (NISLANDS_DPM2_SQ_RAMP_LTI_RATIO <= (LTI_RATIO_MASK >> LTI_RATIO_SHIFT)) + if (SISLANDS_DPM2_SQ_RAMP_LTI_RATIO <= (LTI_RATIO_MASK >> LTI_RATIO_SHIFT)) enable_sq_ramping = false; for (i = 0; i < state->performance_level_count; i++) { @@ -3591,10 +3590,9 @@ static void si_program_display_gap(struct radeon_device *rdev) /* Setting this to false forces the performance state to low if the crtcs are disabled. * This can be a problem on PowerXpress systems or if you want to use the card - * for offscreen rendering or compute if there are no crtcs enabled. Set it to - * true for now so that performance scales even if the displays are off. + * for offscreen rendering or compute if there are no crtcs enabled. */ - si_notify_smc_display_change(rdev, true /*rdev->pm.dpm.new_active_crtc_count > 0*/); + si_notify_smc_display_change(rdev, rdev->pm.dpm.new_active_crtc_count > 0); } static void si_enable_spread_spectrum(struct radeon_device *rdev, bool enable) @@ -5414,7 +5412,7 @@ static void si_populate_mc_reg_addresses(struct radeon_device *rdev, for (i = 0, j = 0; j < si_pi->mc_reg_table.last; j++) { if (si_pi->mc_reg_table.valid_flag & (1 << j)) { - if (i >= SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE) + if (i >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE) break; mc_reg_table->address[i].s0 = cpu_to_be16(si_pi->mc_reg_table.mc_reg_address[j].s0); @@ -5754,6 +5752,11 @@ static void si_set_pcie_lane_width_in_smc(struct radeon_device *rdev, void si_dpm_setup_asic(struct radeon_device *rdev) { + int r; + + r = si_mc_load_microcode(rdev); + if (r) + DRM_ERROR("Failed to load MC firmware!\n"); rv770_get_memory_type(rdev); si_read_clock_registers(rdev); si_enable_acpi_power_management(rdev); @@ -5791,13 +5794,6 @@ int si_dpm_enable(struct radeon_device *rdev) struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps; int ret; - si_update_cg(rdev, (RADEON_CG_BLOCK_GFX | - RADEON_CG_BLOCK_MC | - RADEON_CG_BLOCK_SDMA | - RADEON_CG_BLOCK_BIF | - RADEON_CG_BLOCK_UVD | - RADEON_CG_BLOCK_HDP), false); - if (si_is_smc_running(rdev)) return -EINVAL; if (pi->voltage_control) @@ -5900,6 +5896,17 @@ int si_dpm_enable(struct radeon_device *rdev) si_enable_sclk_control(rdev, true); si_start_dpm(rdev); + si_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true); + + ni_update_current_ps(rdev, boot_ps); + + return 0; +} + +int si_dpm_late_enable(struct radeon_device *rdev) +{ + int ret; + if (rdev->irq.installed && r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) { PPSMC_Result result; @@ -5915,17 +5922,6 @@ int si_dpm_enable(struct radeon_device *rdev) DRM_DEBUG_KMS("Could not enable thermal interrupts.\n"); } - si_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true); - - si_update_cg(rdev, (RADEON_CG_BLOCK_GFX | - RADEON_CG_BLOCK_MC | - RADEON_CG_BLOCK_SDMA | - RADEON_CG_BLOCK_BIF | - RADEON_CG_BLOCK_UVD | - RADEON_CG_BLOCK_HDP), true); - - ni_update_current_ps(rdev, boot_ps); - return 0; } @@ -5934,13 +5930,6 @@ void si_dpm_disable(struct radeon_device *rdev) struct rv7xx_power_info *pi = rv770_get_pi(rdev); struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps; - si_update_cg(rdev, (RADEON_CG_BLOCK_GFX | - RADEON_CG_BLOCK_MC | - RADEON_CG_BLOCK_SDMA | - RADEON_CG_BLOCK_BIF | - RADEON_CG_BLOCK_UVD | - RADEON_CG_BLOCK_HDP), false); - if (!si_is_smc_running(rdev)) return; si_disable_ulv(rdev); @@ -6005,13 +5994,6 @@ int si_dpm_set_power_state(struct radeon_device *rdev) struct radeon_ps *old_ps = &eg_pi->current_rps; int ret; - si_update_cg(rdev, (RADEON_CG_BLOCK_GFX | - RADEON_CG_BLOCK_MC | - RADEON_CG_BLOCK_SDMA | - RADEON_CG_BLOCK_BIF | - RADEON_CG_BLOCK_UVD | - RADEON_CG_BLOCK_HDP), false); - ret = si_disable_ulv(rdev); if (ret) { DRM_ERROR("si_disable_ulv failed\n"); @@ -6104,13 +6086,6 @@ int si_dpm_set_power_state(struct radeon_device *rdev) return ret; } - si_update_cg(rdev, (RADEON_CG_BLOCK_GFX | - RADEON_CG_BLOCK_MC | - RADEON_CG_BLOCK_SDMA | - RADEON_CG_BLOCK_BIF | - RADEON_CG_BLOCK_UVD | - RADEON_CG_BLOCK_HDP), true); - return 0; } diff --git a/drivers/gpu/drm/radeon/si_smc.c b/drivers/gpu/drm/radeon/si_smc.c index d422a1cbf727..e80efcf0c230 100644 --- a/drivers/gpu/drm/radeon/si_smc.c +++ b/drivers/gpu/drm/radeon/si_smc.c @@ -28,6 +28,7 @@ #include "sid.h" #include "ppsmc.h" #include "radeon_ucode.h" +#include "sislands_smc.h" static int si_set_smc_sram_address(struct radeon_device *rdev, u32 smc_address, u32 limit) diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index b322acc48097..9239a6d29128 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h @@ -94,6 +94,8 @@ #define CG_SPLL_FUNC_CNTL_2 0x604 #define SCLK_MUX_SEL(x) ((x) << 0) #define SCLK_MUX_SEL_MASK (0x1ff << 0) +#define SPLL_CTLREQ_CHG (1 << 23) +#define SCLK_MUX_UPDATE (1 << 26) #define CG_SPLL_FUNC_CNTL_3 0x608 #define SPLL_FB_DIV(x) ((x) << 0) #define SPLL_FB_DIV_MASK (0x3ffffff << 0) @@ -101,7 +103,10 @@ #define SPLL_DITHEN (1 << 28) #define CG_SPLL_FUNC_CNTL_4 0x60c +#define SPLL_STATUS 0x614 +#define SPLL_CHG_STATUS (1 << 1) #define SPLL_CNTL_MODE 0x618 +#define SPLL_SW_DIR_CONTROL (1 << 0) # define SPLL_REFCLK_SEL(x) ((x) << 8) # define SPLL_REFCLK_SEL_MASK 0xFF00 @@ -559,6 +564,8 @@ # define MRDCK0_BYPASS (1 << 24) # define MRDCK1_BYPASS (1 << 25) +#define MPLL_CNTL_MODE 0x2bb0 +# define MPLL_MCLK_SEL (1 << 11) #define MPLL_FUNC_CNTL 0x2bb4 #define BWCTRL(x) ((x) << 20) #define BWCTRL_MASK (0xff << 20) @@ -815,7 +822,7 @@ # define GRPH_PFLIP_INT_MASK (1 << 0) # define GRPH_PFLIP_INT_TYPE (1 << 8) -#define DACA_AUTODETECT_INT_CONTROL 0x66c8 +#define DAC_AUTODETECT_INT_CONTROL 0x67c8 #define DC_HPD1_INT_STATUS 0x601c #define DC_HPD2_INT_STATUS 0x6028 diff --git a/drivers/gpu/drm/radeon/sislands_smc.h b/drivers/gpu/drm/radeon/sislands_smc.h index 5578e9837026..10e945a49479 100644 --- a/drivers/gpu/drm/radeon/sislands_smc.h +++ b/drivers/gpu/drm/radeon/sislands_smc.h @@ -374,8 +374,6 @@ typedef struct Smc_SIslands_DTE_Configuration Smc_SIslands_DTE_Configuration; #pragma pack(pop) -int si_set_smc_sram_address(struct radeon_device *rdev, - u32 smc_address, u32 limit); int si_copy_bytes_to_smc(struct radeon_device *rdev, u32 smc_start_address, const u8 *src, u32 byte_count, u32 limit); diff --git a/drivers/gpu/drm/radeon/sumo_dpm.c b/drivers/gpu/drm/radeon/sumo_dpm.c index 96ea6db8bf57..f121efe12dc5 100644 --- a/drivers/gpu/drm/radeon/sumo_dpm.c +++ b/drivers/gpu/drm/radeon/sumo_dpm.c @@ -71,7 +71,7 @@ static const u32 sumo_dtc[SUMO_PM_NUMBER_OF_TC] = SUMO_DTC_DFLT_14, }; -struct sumo_ps *sumo_get_ps(struct radeon_ps *rps) +static struct sumo_ps *sumo_get_ps(struct radeon_ps *rps) { struct sumo_ps *ps = rps->ps_priv; @@ -1202,14 +1202,10 @@ static void sumo_update_requested_ps(struct radeon_device *rdev, int sumo_dpm_enable(struct radeon_device *rdev) { struct sumo_power_info *pi = sumo_get_pi(rdev); - int ret; if (sumo_dpm_enabled(rdev)) return -EINVAL; - ret = sumo_enable_clock_power_gating(rdev); - if (ret) - return ret; sumo_program_bootup_state(rdev); sumo_init_bsp(rdev); sumo_reset_am(rdev); @@ -1233,6 +1229,19 @@ int sumo_dpm_enable(struct radeon_device *rdev) if (pi->enable_boost) sumo_enable_boost_timer(rdev); + sumo_update_current_ps(rdev, rdev->pm.dpm.boot_ps); + + return 0; +} + +int sumo_dpm_late_enable(struct radeon_device *rdev) +{ + int ret; + + ret = sumo_enable_clock_power_gating(rdev); + if (ret) + return ret; + if (rdev->irq.installed && r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) { ret = sumo_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX); @@ -1242,8 +1251,6 @@ int sumo_dpm_enable(struct radeon_device *rdev) radeon_irq_set(rdev); } - sumo_update_current_ps(rdev, rdev->pm.dpm.boot_ps); - return 0; } diff --git a/drivers/gpu/drm/radeon/sumo_smc.c b/drivers/gpu/drm/radeon/sumo_smc.c index 18abba5b5810..fb081d2ae374 100644 --- a/drivers/gpu/drm/radeon/sumo_smc.c +++ b/drivers/gpu/drm/radeon/sumo_smc.c @@ -31,7 +31,6 @@ #define SUMO_SMU_SERVICE_ROUTINE_ALTVDDNB_NOTIFY 27 #define SUMO_SMU_SERVICE_ROUTINE_GFX_SRV_ID_20 20 -struct sumo_ps *sumo_get_ps(struct radeon_ps *rps); struct sumo_power_info *sumo_get_pi(struct radeon_device *rdev); static void sumo_send_msg_to_smu(struct radeon_device *rdev, u32 id) diff --git a/drivers/gpu/drm/radeon/trinity_dpm.c b/drivers/gpu/drm/radeon/trinity_dpm.c index d700698a1f22..2d447192d6f7 100644 --- a/drivers/gpu/drm/radeon/trinity_dpm.c +++ b/drivers/gpu/drm/radeon/trinity_dpm.c @@ -342,14 +342,14 @@ static void trinity_apply_state_adjust_rules(struct radeon_device *rdev, struct radeon_ps *new_rps, struct radeon_ps *old_rps); -struct trinity_ps *trinity_get_ps(struct radeon_ps *rps) +static struct trinity_ps *trinity_get_ps(struct radeon_ps *rps) { struct trinity_ps *ps = rps->ps_priv; return ps; } -struct trinity_power_info *trinity_get_pi(struct radeon_device *rdev) +static struct trinity_power_info *trinity_get_pi(struct radeon_device *rdev) { struct trinity_power_info *pi = rdev->pm.dpm.priv; @@ -1082,7 +1082,6 @@ void trinity_dpm_enable_bapm(struct radeon_device *rdev, bool enable) int trinity_dpm_enable(struct radeon_device *rdev) { struct trinity_power_info *pi = trinity_get_pi(rdev); - int ret; trinity_acquire_mutex(rdev); @@ -1091,7 +1090,6 @@ int trinity_dpm_enable(struct radeon_device *rdev) return -EINVAL; } - trinity_enable_clock_power_gating(rdev); trinity_program_bootup_state(rdev); sumo_program_vc(rdev, 0x00C00033); trinity_start_am(rdev); @@ -1105,6 +1103,18 @@ int trinity_dpm_enable(struct radeon_device *rdev) trinity_dpm_bapm_enable(rdev, false); trinity_release_mutex(rdev); + trinity_update_current_ps(rdev, rdev->pm.dpm.boot_ps); + + return 0; +} + +int trinity_dpm_late_enable(struct radeon_device *rdev) +{ + int ret; + + trinity_acquire_mutex(rdev); + trinity_enable_clock_power_gating(rdev); + if (rdev->irq.installed && r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) { ret = trinity_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX); @@ -1115,8 +1125,7 @@ int trinity_dpm_enable(struct radeon_device *rdev) rdev->irq.dpm_thermal = true; radeon_irq_set(rdev); } - - trinity_update_current_ps(rdev, rdev->pm.dpm.boot_ps); + trinity_release_mutex(rdev); return 0; } diff --git a/drivers/gpu/drm/radeon/trinity_smc.c b/drivers/gpu/drm/radeon/trinity_smc.c index 9672bcbc7312..99dd0455334d 100644 --- a/drivers/gpu/drm/radeon/trinity_smc.c +++ b/drivers/gpu/drm/radeon/trinity_smc.c @@ -27,9 +27,6 @@ #include "trinity_dpm.h" #include "ppsmc.h" -struct trinity_ps *trinity_get_ps(struct radeon_ps *rps); -struct trinity_power_info *trinity_get_pi(struct radeon_device *rdev); - static int trinity_notify_message_to_smu(struct radeon_device *rdev, u32 id) { int i; diff --git a/drivers/gpu/drm/radeon/uvd_v2_2.c b/drivers/gpu/drm/radeon/uvd_v2_2.c index b19ef4951085..824550db3fed 100644 --- a/drivers/gpu/drm/radeon/uvd_v2_2.c +++ b/drivers/gpu/drm/radeon/uvd_v2_2.c @@ -153,6 +153,7 @@ int uvd_v2_2_resume(struct radeon_device *rdev) chip_id = 0x01000015; break; case CHIP_PITCAIRN: + case CHIP_OLAND: chip_id = 0x01000016; break; case CHIP_ARUBA: |