linux/drivers/gpu/drm/radeon/btc_dpm.c

/*
 * Copyright 2011 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * Authors: Alex Deucher
 */

#include <linux/pci.h>
#include <linux/seq_file.h>

#include "atom.h"
#include "btc_dpm.h"
#include "btcd.h"
#include "cypress_dpm.h"
#include "evergreen.h"
#include "r600_dpm.h"
#include "rv770.h"
#include "radeon.h"
#include "radeon_asic.h"

#define MC_CG_ARB_FREQ_F0
#define MC_CG_ARB_FREQ_F1
#define MC_CG_ARB_FREQ_F2
#define MC_CG_ARB_FREQ_F3

#define MC_CG_SEQ_DRAMCONF_S0
#define MC_CG_SEQ_DRAMCONF_S1
#define MC_CG_SEQ_YCLK_SUSPEND
#define MC_CG_SEQ_YCLK_RESUME

#define SMC_RAM_END

#ifndef BTC_MGCG_SEQUENCE
#define BTC_MGCG_SEQUENCE

extern int ni_mc_load_microcode(struct radeon_device *rdev);

//********* BARTS **************//
static const u32 barts_cgcg_cgls_default[] =;
#define BARTS_CGCG_CGLS_DEFAULT_LENGTH

static const u32 barts_cgcg_cgls_disable[] =;
#define BARTS_CGCG_CGLS_DISABLE_LENGTH

static const u32 barts_cgcg_cgls_enable[] =;
#define BARTS_CGCG_CGLS_ENABLE_LENGTH

static const u32 barts_mgcg_default[] =;
#define BARTS_MGCG_DEFAULT_LENGTH

static const u32 barts_mgcg_disable[] =;
#define BARTS_MGCG_DISABLE_LENGTH

static const u32 barts_mgcg_enable[] =;
#define BARTS_MGCG_ENABLE_LENGTH

//********* CAICOS **************//
static const u32 caicos_cgcg_cgls_default[] =;
#define CAICOS_CGCG_CGLS_DEFAULT_LENGTH

static const u32 caicos_cgcg_cgls_disable[] =;
#define CAICOS_CGCG_CGLS_DISABLE_LENGTH

static const u32 caicos_cgcg_cgls_enable[] =;
#define CAICOS_CGCG_CGLS_ENABLE_LENGTH

static const u32 caicos_mgcg_default[] =;
#define CAICOS_MGCG_DEFAULT_LENGTH

static const u32 caicos_mgcg_disable[] =;
#define CAICOS_MGCG_DISABLE_LENGTH

static const u32 caicos_mgcg_enable[] =;
#define CAICOS_MGCG_ENABLE_LENGTH

//********* TURKS **************//
static const u32 turks_cgcg_cgls_default[] =;
#define TURKS_CGCG_CGLS_DEFAULT_LENGTH

static const u32 turks_cgcg_cgls_disable[] =;
#define TURKS_CGCG_CGLS_DISABLE_LENGTH

static const u32 turks_cgcg_cgls_enable[] =;
#define TURKS_CGCG_CGLS_ENABLE_LENGTH

// These are the sequences for turks_mgcg_shls
static const u32 turks_mgcg_default[] =;
#define TURKS_MGCG_DEFAULT_LENGTH

static const u32 turks_mgcg_disable[] =;
#define TURKS_MGCG_DISABLE_LENGTH

static const u32 turks_mgcg_enable[] =;
#define TURKS_MGCG_ENABLE_LENGTH

#endif

#ifndef BTC_SYSLS_SEQUENCE
#define BTC_SYSLS_SEQUENCE


//********* BARTS **************//
static const u32 barts_sysls_default[] =;
#define BARTS_SYSLS_DEFAULT_LENGTH

static const u32 barts_sysls_disable[] =;
#define BARTS_SYSLS_DISABLE_LENGTH

static const u32 barts_sysls_enable[] =;
#define BARTS_SYSLS_ENABLE_LENGTH

//********* CAICOS **************//
static const u32 caicos_sysls_default[] =;
#define CAICOS_SYSLS_DEFAULT_LENGTH

static const u32 caicos_sysls_disable[] =;
#define CAICOS_SYSLS_DISABLE_LENGTH

static const u32 caicos_sysls_enable[] =;
#define CAICOS_SYSLS_ENABLE_LENGTH

//********* TURKS **************//
static const u32 turks_sysls_default[] =;
#define TURKS_SYSLS_DEFAULT_LENGTH

static const u32 turks_sysls_disable[] =;
#define TURKS_SYSLS_DISABLE_LENGTH

static const u32 turks_sysls_enable[] =;
#define TURKS_SYSLS_ENABLE_LENGTH

#endif

u32 btc_valid_sclk[40] =;

static const struct radeon_blacklist_clocks btc_blacklist_clocks[] =;

void btc_get_max_clock_from_voltage_dependency_table(struct radeon_clock_voltage_dependency_table *table,
						     u32 *max_clock)
{}

void btc_apply_voltage_dependency_rules(struct radeon_clock_voltage_dependency_table *table,
					u32 clock, u16 max_voltage, u16 *voltage)
{}

static u32 btc_find_valid_clock(struct radeon_clock_array *clocks,
				u32 max_clock, u32 requested_clock)
{}

static u32 btc_get_valid_mclk(struct radeon_device *rdev,
			      u32 max_mclk, u32 requested_mclk)
{}

static u32 btc_get_valid_sclk(struct radeon_device *rdev,
			      u32 max_sclk, u32 requested_sclk)
{}

void btc_skip_blacklist_clocks(struct radeon_device *rdev,
			       const u32 max_sclk, const u32 max_mclk,
			       u32 *sclk, u32 *mclk)
{}

void btc_adjust_clock_combinations(struct radeon_device *rdev,
				   const struct radeon_clock_and_voltage_limits *max_limits,
				   struct rv7xx_pl *pl)
{}

static u16 btc_find_voltage(struct atom_voltage_table *table, u16 voltage)
{}

void btc_apply_voltage_delta_rules(struct radeon_device *rdev,
				   u16 max_vddc, u16 max_vddci,
				   u16 *vddc, u16 *vddci)
{}

static void btc_enable_bif_dynamic_pcie_gen2(struct radeon_device *rdev,
					     bool enable)
{}

static void btc_enable_dynamic_pcie_gen2(struct radeon_device *rdev,
					 bool enable)
{}

static int btc_disable_ulv(struct radeon_device *rdev)
{}

static int btc_populate_ulv_state(struct radeon_device *rdev,
				  RV770_SMC_STATETABLE *table)
{}

static int btc_populate_smc_acpi_state(struct radeon_device *rdev,
				       RV770_SMC_STATETABLE *table)
{}

void btc_program_mgcg_hw_sequence(struct radeon_device *rdev,
				  const u32 *sequence, u32 count)
{}

static void btc_cg_clock_gating_default(struct radeon_device *rdev)
{}

static void btc_cg_clock_gating_enable(struct radeon_device *rdev,
				       bool enable)
{}

static void btc_mg_clock_gating_default(struct radeon_device *rdev)
{}

static void btc_mg_clock_gating_enable(struct radeon_device *rdev,
				       bool enable)
{}

static void btc_ls_clock_gating_default(struct radeon_device *rdev)
{}

static void btc_ls_clock_gating_enable(struct radeon_device *rdev,
				       bool enable)
{}

bool btc_dpm_enabled(struct radeon_device *rdev)
{}

static int btc_init_smc_table(struct radeon_device *rdev,
			      struct radeon_ps *radeon_boot_state)
{}

static void btc_set_at_for_uvd(struct radeon_device *rdev,
			       struct radeon_ps *radeon_new_state)
{}

void btc_notify_uvd_to_smc(struct radeon_device *rdev,
			   struct radeon_ps *radeon_new_state)
{}

int btc_reset_to_default(struct radeon_device *rdev)
{}

static void btc_stop_smc(struct radeon_device *rdev)
{}

void btc_read_arb_registers(struct radeon_device *rdev)
{}


static void btc_set_arb0_registers(struct radeon_device *rdev,
				   struct evergreen_arb_registers *arb_registers)
{}

static void btc_set_boot_state_timing(struct radeon_device *rdev)
{}

static bool btc_is_state_ulv_compatible(struct radeon_device *rdev,
					struct radeon_ps *radeon_state)
{}


static int btc_set_ulv_dram_timing(struct radeon_device *rdev)
{}

static int btc_enable_ulv(struct radeon_device *rdev)
{}

static int btc_set_power_state_conditionally_enable_ulv(struct radeon_device *rdev,
							struct radeon_ps *radeon_new_state)
{}

static bool btc_check_s0_mc_reg_index(u16 in_reg, u16 *out_reg)
{}

static void btc_set_valid_flag(struct evergreen_mc_reg_table *table)
{}

static int btc_set_mc_special_registers(struct radeon_device *rdev,
					struct evergreen_mc_reg_table *table)
{}

static void btc_set_s0_mc_reg_index(struct evergreen_mc_reg_table *table)
{}

static int btc_copy_vbios_mc_reg_table(struct atom_mc_reg_table *table,
				       struct evergreen_mc_reg_table *eg_table)
{}

static int btc_initialize_mc_reg_table(struct radeon_device *rdev)
{}

static void btc_init_stutter_mode(struct radeon_device *rdev)
{}

bool btc_dpm_vblank_too_short(struct radeon_device *rdev)
{}

static void btc_apply_state_adjust_rules(struct radeon_device *rdev,
					 struct radeon_ps *rps)
{}

static void btc_update_current_ps(struct radeon_device *rdev,
				  struct radeon_ps *rps)
{}

static void btc_update_requested_ps(struct radeon_device *rdev,
				    struct radeon_ps *rps)
{}

#if 0
void btc_dpm_reset_asic(struct radeon_device *rdev)
{
	rv770_restrict_performance_levels_before_switch(rdev);
	btc_disable_ulv(rdev);
	btc_set_boot_state_timing(rdev);
	rv770_set_boot_state(rdev);
}
#endif

int btc_dpm_pre_set_power_state(struct radeon_device *rdev)
{}

int btc_dpm_set_power_state(struct radeon_device *rdev)
{}

void btc_dpm_post_set_power_state(struct radeon_device *rdev)
{}

int btc_dpm_enable(struct radeon_device *rdev)
{
	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
	struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
	int ret;

	if (pi->gfx_clock_gating)
		btc_cg_clock_gating_default(rdev);

	if (btc_dpm_enabled(rdev))
		return -EINVAL;

	if (pi->mg_clock_gating)
		btc_mg_clock_gating_default(rdev);

	if (eg_pi->ls_clock_gating)
		btc_ls_clock_gating_default(rdev);

	if (pi->voltage_control) {
		rv770_enable_voltage_control(rdev, true);
		ret = cypress_construct_voltage_tables(rdev);
		if (ret) {
			DRM_ERROR("cypress_construct_voltage_tables failed\n");
			return ret;
		}
	}

	if (pi->mvdd_control) {
		ret = cypress_get_mvdd_configuration(rdev);
		if (ret) {
			DRM_ERROR("cypress_get_mvdd_configuration failed\n");
			return ret;
		}
	}

	if (eg_pi->dynamic_ac_timing) {
		ret = btc_initialize_mc_reg_table(rdev);
		if (ret)
			eg_pi->dynamic_ac_timing = false;
	}

	if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_BACKBIAS)
		rv770_enable_backbias(rdev, true);

	if (pi->dynamic_ss)
		cypress_enable_spread_spectrum(rdev, true);

	if (pi->thermal_protection)
		rv770_enable_thermal_protection(rdev, true);

	rv770_setup_bsp(rdev);
	rv770_program_git(rdev);
	rv770_program_tp(rdev);
	rv770_program_tpp(rdev);
	rv770_program_sstp(rdev);
	rv770_program_engine_speed_parameters(rdev);
	cypress_enable_display_gap(rdev);
	rv770_program_vc(rdev);

	if (pi->dynamic_pcie_gen2)
		btc_enable_dynamic_pcie_gen2(rdev, true);

	ret = rv770_upload_firmware(rdev);
	if (ret) {
		DRM_ERROR("rv770_upload_firmware failed\n");
		return ret;
	}
	ret = cypress_get_table_locations(rdev);
	if (ret) {
		DRM_ERROR("cypress_get_table_locations failed\n");
		return ret;
	}
	ret = btc_init_smc_table(rdev, boot_ps);
	if (ret)
		return ret;

	if (eg_pi->dynamic_ac_timing) {
		ret = cypress_populate_mc_reg_table(rdev, boot_ps);
		if (ret) {
			DRM_ERROR("cypress_populate_mc_reg_table failed\n");
			return ret;
		}
	}

	cypress_program_response_times(rdev);
	r7xx_start_smc(rdev);
	ret = cypress_notify_smc_display_change(rdev, false);
	if (ret) {
		DRM_ERROR("cypress_notify_smc_display_change failed\n");
		return ret;
	}
	cypress_enable_sclk_control(rdev, true);

	if (eg_pi->memory_transition)
		cypress_enable_mclk_control(rdev, true);

	cypress_start_dpm(rdev);

	if (pi->gfx_clock_gating)
		btc_cg_clock_gating_enable(rdev, true);

	if (pi->mg_clock_gating)
		btc_mg_clock_gating_enable(rdev, true);

	if (eg_pi->ls_clock_gating)
		btc_ls_clock_gating_enable(rdev, true);

	rv770_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true);

	btc_init_stutter_mode(rdev);

	btc_update_current_ps(rdev, rdev->pm.dpm.boot_ps);

	return 0;
};

void btc_dpm_disable(struct radeon_device *rdev)
{}

void btc_dpm_setup_asic(struct radeon_device *rdev)
{}

int btc_dpm_init(struct radeon_device *rdev)
{}

void btc_dpm_fini(struct radeon_device *rdev)
{}

void btc_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
						     struct seq_file *m)
{}

u32 btc_dpm_get_current_sclk(struct radeon_device *rdev)
{}

u32 btc_dpm_get_current_mclk(struct radeon_device *rdev)
{}

u32 btc_dpm_get_sclk(struct radeon_device *rdev, bool low)
{}

u32 btc_dpm_get_mclk(struct radeon_device *rdev, bool low)
{}