Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 49e02b73 authored by Alex Deucher's avatar Alex Deucher Committed by Dave Airlie
Browse files

drm/radeon/kms/pm: add additional asic callbacks



- pm_misc() - handles voltage, pcie lanes, and other non
clock related power mode settings.  Currently disabled.
Needs further debugging

- pm_prepare() - disables crtc mem requests right now.
All memory clients need to be disabled when changing
memory clocks.  This function can be expanded to include
disabling fb access as well.

- pm_finish() - enable active memory clients.

Signed-off-by: default avatarAlex Deucher <alexdeucher@gmail.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 58e21dff
Loading
Loading
Loading
Loading
+41 −0
Original line number Diff line number Diff line
@@ -39,6 +39,47 @@
static void evergreen_gpu_init(struct radeon_device *rdev);
void evergreen_fini(struct radeon_device *rdev);

void evergreen_pm_misc(struct radeon_device *rdev)
{

}

void evergreen_pm_prepare(struct radeon_device *rdev)
{
	struct drm_device *ddev = rdev->ddev;
	struct drm_crtc *crtc;
	struct radeon_crtc *radeon_crtc;
	u32 tmp;

	/* disable any active CRTCs */
	list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) {
		radeon_crtc = to_radeon_crtc(crtc);
		if (radeon_crtc->enabled) {
			tmp = RREG32(EVERGREEN_CRTC_CONTROL + radeon_crtc->crtc_offset);
			tmp |= EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE;
			WREG32(EVERGREEN_CRTC_CONTROL + radeon_crtc->crtc_offset, tmp);
		}
	}
}

void evergreen_pm_finish(struct radeon_device *rdev)
{
	struct drm_device *ddev = rdev->ddev;
	struct drm_crtc *crtc;
	struct radeon_crtc *radeon_crtc;
	u32 tmp;

	/* enable any active CRTCs */
	list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) {
		radeon_crtc = to_radeon_crtc(crtc);
		if (radeon_crtc->enabled) {
			tmp = RREG32(EVERGREEN_CRTC_CONTROL + radeon_crtc->crtc_offset);
			tmp &= ~EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE;
			WREG32(EVERGREEN_CRTC_CONTROL + radeon_crtc->crtc_offset, tmp);
		}
	}
}

bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd)
{
	bool connected = false;
+1 −0
Original line number Diff line number Diff line
@@ -166,6 +166,7 @@
/* CRTC blocks at 0x6df0, 0x79f0, 0x105f0, 0x111f0, 0x11df0, 0x129f0 */
#define EVERGREEN_CRTC_CONTROL                          0x6e70
#       define EVERGREEN_CRTC_MASTER_EN                 (1 << 0)
#       define EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE (1 << 24)
#define EVERGREEN_CRTC_STATUS                           0x6e8c
#define EVERGREEN_CRTC_UPDATE_LOCK                      0x6ed4

+142 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
#include "rs100d.h"
#include "rv200d.h"
#include "rv250d.h"
#include "atom.h"

#include <linux/firmware.h>
#include <linux/platform_device.h>
@@ -200,6 +201,147 @@ void r100_set_power_state(struct radeon_device *rdev)
		DRM_INFO("GUI not idle!!!\n");
}

void r100_pm_misc(struct radeon_device *rdev)
{
#if 0
	int requested_index = rdev->pm.requested_power_state_index;
	struct radeon_power_state *ps = &rdev->pm.power_state[requested_index];
	struct radeon_voltage *voltage = &ps->clock_info[0].voltage;
	u32 tmp, sclk_cntl, sclk_cntl2, sclk_more_cntl;

	if ((voltage->type == VOLTAGE_GPIO) && (voltage->gpio.valid)) {
		if (ps->misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) {
			tmp = RREG32(voltage->gpio.reg);
			if (voltage->active_high)
				tmp |= voltage->gpio.mask;
			else
				tmp &= ~(voltage->gpio.mask);
			WREG32(voltage->gpio.reg, tmp);
			if (voltage->delay)
				udelay(voltage->delay);
		} else {
			tmp = RREG32(voltage->gpio.reg);
			if (voltage->active_high)
				tmp &= ~voltage->gpio.mask;
			else
				tmp |= voltage->gpio.mask;
			WREG32(voltage->gpio.reg, tmp);
			if (voltage->delay)
				udelay(voltage->delay);
		}
	}

	sclk_cntl = RREG32_PLL(SCLK_CNTL);
	sclk_cntl2 = RREG32_PLL(SCLK_CNTL2);
	sclk_cntl2 &= ~REDUCED_SPEED_SCLK_SEL(3);
	sclk_more_cntl = RREG32_PLL(SCLK_MORE_CNTL);
	sclk_more_cntl &= ~VOLTAGE_DELAY_SEL(3);
	if (ps->misc & ATOM_PM_MISCINFO_ASIC_REDUCED_SPEED_SCLK_EN) {
		sclk_more_cntl |= REDUCED_SPEED_SCLK_EN;
		if (ps->misc & ATOM_PM_MISCINFO_DYN_CLK_3D_IDLE)
			sclk_cntl2 |= REDUCED_SPEED_SCLK_MODE;
		else
			sclk_cntl2 &= ~REDUCED_SPEED_SCLK_MODE;
		if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_CLOCK_DIVIDER_BY_2)
			sclk_cntl2 |= REDUCED_SPEED_SCLK_SEL(0);
		else if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_CLOCK_DIVIDER_BY_4)
			sclk_cntl2 |= REDUCED_SPEED_SCLK_SEL(2);
	} else
		sclk_more_cntl &= ~REDUCED_SPEED_SCLK_EN;

	if (ps->misc & ATOM_PM_MISCINFO_ASIC_DYNAMIC_VOLTAGE_EN) {
		sclk_more_cntl |= IO_CG_VOLTAGE_DROP;
		if (voltage->delay) {
			sclk_more_cntl |= VOLTAGE_DROP_SYNC;
			switch (voltage->delay) {
			case 33:
				sclk_more_cntl |= VOLTAGE_DELAY_SEL(0);
				break;
			case 66:
				sclk_more_cntl |= VOLTAGE_DELAY_SEL(1);
				break;
			case 99:
				sclk_more_cntl |= VOLTAGE_DELAY_SEL(2);
				break;
			case 132:
				sclk_more_cntl |= VOLTAGE_DELAY_SEL(3);
				break;
			}
		} else
			sclk_more_cntl &= ~VOLTAGE_DROP_SYNC;
	} else
		sclk_more_cntl &= ~IO_CG_VOLTAGE_DROP;

	if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_HDP_BLOCK_EN)
		sclk_cntl &= ~FORCE_HDP;
	else
		sclk_cntl |= FORCE_HDP;

	WREG32_PLL(SCLK_CNTL, sclk_cntl);
	WREG32_PLL(SCLK_CNTL2, sclk_cntl2);
	WREG32_PLL(SCLK_MORE_CNTL, sclk_more_cntl);

	/* set pcie lanes */
	if ((rdev->flags & RADEON_IS_PCIE) &&
	    !(rdev->flags & RADEON_IS_IGP) &&
	    rdev->asic->set_pcie_lanes &&
	    (ps->pcie_lanes !=
	     rdev->pm.power_state[rdev->pm.current_power_state_index].pcie_lanes)) {
		radeon_set_pcie_lanes(rdev,
				      ps->pcie_lanes);
		DRM_INFO("Setting: p: %d\n", ps->pcie_lanes);
	}
#endif
}

void r100_pm_prepare(struct radeon_device *rdev)
{
	struct drm_device *ddev = rdev->ddev;
	struct drm_crtc *crtc;
	struct radeon_crtc *radeon_crtc;
	u32 tmp;

	/* disable any active CRTCs */
	list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) {
		radeon_crtc = to_radeon_crtc(crtc);
		if (radeon_crtc->enabled) {
			if (radeon_crtc->crtc_id) {
				tmp = RREG32(RADEON_CRTC2_GEN_CNTL);
				tmp |= RADEON_CRTC2_DISP_REQ_EN_B;
				WREG32(RADEON_CRTC2_GEN_CNTL, tmp);
			} else {
				tmp = RREG32(RADEON_CRTC_GEN_CNTL);
				tmp |= RADEON_CRTC_DISP_REQ_EN_B;
				WREG32(RADEON_CRTC_GEN_CNTL, tmp);
			}
		}
	}
}

void r100_pm_finish(struct radeon_device *rdev)
{
	struct drm_device *ddev = rdev->ddev;
	struct drm_crtc *crtc;
	struct radeon_crtc *radeon_crtc;
	u32 tmp;

	/* enable any active CRTCs */
	list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) {
		radeon_crtc = to_radeon_crtc(crtc);
		if (radeon_crtc->enabled) {
			if (radeon_crtc->crtc_id) {
				tmp = RREG32(RADEON_CRTC2_GEN_CNTL);
				tmp &= ~RADEON_CRTC2_DISP_REQ_EN_B;
				WREG32(RADEON_CRTC2_GEN_CNTL, tmp);
			} else {
				tmp = RREG32(RADEON_CRTC_GEN_CNTL);
				tmp &= ~RADEON_CRTC_DISP_REQ_EN_B;
				WREG32(RADEON_CRTC_GEN_CNTL, tmp);
			}
		}
	}
}

bool r100_gui_idle(struct radeon_device *rdev)
{
	if (RREG32(RADEON_RBBM_STATUS) & RADEON_RBBM_ACTIVE)
+36 −0
Original line number Diff line number Diff line
@@ -838,5 +838,41 @@
#define   G_00000D_FORCE_RB(x)                         (((x) >> 28) & 0x1)
#define   C_00000D_FORCE_RB                            0xEFFFFFFF

/* PLL regs */
#define SCLK_CNTL                                      0xd
#define   FORCE_HDP                                    (1 << 17)
#define CLK_PWRMGT_CNTL                                0x14
#define   GLOBAL_PMAN_EN                               (1 << 10)
#define   DISP_PM                                      (1 << 20)
#define PLL_PWRMGT_CNTL                                0x15
#define   MPLL_TURNOFF                                 (1 << 0)
#define   SPLL_TURNOFF                                 (1 << 1)
#define   PPLL_TURNOFF                                 (1 << 2)
#define   P2PLL_TURNOFF                                (1 << 3)
#define   TVPLL_TURNOFF                                (1 << 4)
#define   MOBILE_SU                                    (1 << 16)
#define   SU_SCLK_USE_BCLK                             (1 << 17)
#define SCLK_CNTL2                                     0x1e
#define   REDUCED_SPEED_SCLK_MODE                      (1 << 16)
#define   REDUCED_SPEED_SCLK_SEL(x)                    ((x) << 17)
#define MCLK_MISC                                      0x1f
#define   EN_MCLK_TRISTATE_IN_SUSPEND                  (1 << 18)
#define SCLK_MORE_CNTL                                 0x35
#define   REDUCED_SPEED_SCLK_EN                        (1 << 16)
#define   IO_CG_VOLTAGE_DROP                           (1 << 17)
#define   VOLTAGE_DELAY_SEL(x)                         ((x) << 20)
#define   VOLTAGE_DROP_SYNC                            (1 << 19)

/* mmreg */
#define DISP_PWR_MAN                                   0xd08
#define   DISP_D3_GRPH_RST                             (1 << 18)
#define   DISP_D3_SUBPIC_RST                           (1 << 19)
#define   DISP_D3_OV0_RST                              (1 << 20)
#define   DISP_D1D2_GRPH_RST                           (1 << 21)
#define   DISP_D1D2_SUBPIC_RST                         (1 << 22)
#define   DISP_D1D2_OV0_RST                            (1 << 23)
#define   DISP_DVO_ENABLE_RST                          (1 << 24)
#define   TV_ENABLE_RST                                (1 << 25)
#define   AUTO_PWRUP_EN                                (1 << 26)

#endif
+1 −0
Original line number Diff line number Diff line
@@ -347,6 +347,7 @@

#define AVIVO_D1CRTC_CONTROL                                    0x6080
#       define AVIVO_CRTC_EN                                    (1 << 0)
#       define AVIVO_CRTC_DISP_READ_REQUEST_DISABLE             (1 << 24)
#define AVIVO_D1CRTC_BLANK_CONTROL                              0x6084
#define AVIVO_D1CRTC_INTERLACE_CONTROL                          0x6088
#define AVIVO_D1CRTC_INTERLACE_STATUS                           0x608c
Loading