drm/radeon/kms/pm: add additional asic callbacks
authorAlex Deucher <alexdeucher@gmail.com>
Fri, 23 Apr 2010 21:57:27 +0000 (17:57 -0400)
committerDave Airlie <airlied@redhat.com>
Tue, 18 May 2010 08:21:12 +0000 (18:21 +1000)
- 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: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
12 files changed:
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreen_reg.h
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/r100d.h
drivers/gpu/drm/radeon/r500_reg.h
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_asic.c
drivers/gpu/drm/radeon/radeon_asic.h
drivers/gpu/drm/radeon/rs600.c
drivers/gpu/drm/radeon/rs600d.h
drivers/gpu/drm/radeon/rv770.c

index 0137a4c..8d86d05 100644 (file)
 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;
index 9dba6d9..93aab2e 100644 (file)
 /* 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
 
index 6443d9e..2106ac6 100644 (file)
@@ -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)
index de8abd1..d016b16 100644 (file)
 #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
index 0cf2ad2..f5adf42 100644 (file)
 
 #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
index 4f7f318..38f75f5 100644 (file)
@@ -304,6 +304,11 @@ void r600_set_power_state(struct radeon_device *rdev)
                DRM_INFO("GUI not idle!!!\n");
 }
 
+void r600_pm_misc(struct radeon_device *rdev)
+{
+
+}
+
 bool r600_gui_idle(struct radeon_device *rdev)
 {
        if (RREG32(GRBM_STATUS) & GUI_ACTIVE)
index 5ffb295..16f0ea7 100644 (file)
@@ -815,6 +815,9 @@ struct radeon_asic {
        bool (*gui_idle)(struct radeon_device *rdev);
        void (*get_power_state)(struct radeon_device *rdev, enum radeon_pm_action action);
        void (*set_power_state)(struct radeon_device *rdev);
+       void (*pm_misc)(struct radeon_device *rdev);
+       void (*pm_prepare)(struct radeon_device *rdev);
+       void (*pm_finish)(struct radeon_device *rdev);
 };
 
 /*
index 1053115..1e6f17b 100644 (file)
@@ -168,6 +168,9 @@ static struct radeon_asic r100_asic = {
        .gui_idle = &r100_gui_idle,
        .get_power_state = &r100_get_power_state,
        .set_power_state = &r100_set_power_state,
+       .pm_misc = &r100_pm_misc,
+       .pm_prepare = &r100_pm_prepare,
+       .pm_finish = &r100_pm_finish,
 };
 
 static struct radeon_asic r200_asic = {
@@ -209,6 +212,9 @@ static struct radeon_asic r200_asic = {
        .gui_idle = &r100_gui_idle,
        .get_power_state = &r100_get_power_state,
        .set_power_state = &r100_set_power_state,
+       .pm_misc = &r100_pm_misc,
+       .pm_prepare = &r100_pm_prepare,
+       .pm_finish = &r100_pm_finish,
 };
 
 static struct radeon_asic r300_asic = {
@@ -251,6 +257,9 @@ static struct radeon_asic r300_asic = {
        .gui_idle = &r100_gui_idle,
        .get_power_state = &r100_get_power_state,
        .set_power_state = &r100_set_power_state,
+       .pm_misc = &r100_pm_misc,
+       .pm_prepare = &r100_pm_prepare,
+       .pm_finish = &r100_pm_finish,
 };
 
 static struct radeon_asic r300_asic_pcie = {
@@ -292,6 +301,9 @@ static struct radeon_asic r300_asic_pcie = {
        .gui_idle = &r100_gui_idle,
        .get_power_state = &r100_get_power_state,
        .set_power_state = &r100_set_power_state,
+       .pm_misc = &r100_pm_misc,
+       .pm_prepare = &r100_pm_prepare,
+       .pm_finish = &r100_pm_finish,
 };
 
 static struct radeon_asic r420_asic = {
@@ -334,6 +346,9 @@ static struct radeon_asic r420_asic = {
        .gui_idle = &r100_gui_idle,
        .get_power_state = &r100_get_power_state,
        .set_power_state = &r100_set_power_state,
+       .pm_misc = &r100_pm_misc,
+       .pm_prepare = &r100_pm_prepare,
+       .pm_finish = &r100_pm_finish,
 };
 
 static struct radeon_asic rs400_asic = {
@@ -376,6 +391,9 @@ static struct radeon_asic rs400_asic = {
        .gui_idle = &r100_gui_idle,
        .get_power_state = &r100_get_power_state,
        .set_power_state = &r100_set_power_state,
+       .pm_misc = &r100_pm_misc,
+       .pm_prepare = &r100_pm_prepare,
+       .pm_finish = &r100_pm_finish,
 };
 
 static struct radeon_asic rs600_asic = {
@@ -418,6 +436,9 @@ static struct radeon_asic rs600_asic = {
        .gui_idle = &r100_gui_idle,
        .get_power_state = &r100_get_power_state,
        .set_power_state = &r100_set_power_state,
+       .pm_misc = &rs600_pm_misc,
+       .pm_prepare = &rs600_pm_prepare,
+       .pm_finish = &rs600_pm_finish,
 };
 
 static struct radeon_asic rs690_asic = {
@@ -460,6 +481,9 @@ static struct radeon_asic rs690_asic = {
        .gui_idle = &r100_gui_idle,
        .get_power_state = &r100_get_power_state,
        .set_power_state = &r100_set_power_state,
+       .pm_misc = &rs600_pm_misc,
+       .pm_prepare = &rs600_pm_prepare,
+       .pm_finish = &rs600_pm_finish,
 };
 
 static struct radeon_asic rv515_asic = {
@@ -502,6 +526,9 @@ static struct radeon_asic rv515_asic = {
        .gui_idle = &r100_gui_idle,
        .get_power_state = &r100_get_power_state,
        .set_power_state = &r100_set_power_state,
+       .pm_misc = &rs600_pm_misc,
+       .pm_prepare = &rs600_pm_prepare,
+       .pm_finish = &rs600_pm_finish,
 };
 
 static struct radeon_asic r520_asic = {
@@ -544,6 +571,9 @@ static struct radeon_asic r520_asic = {
        .gui_idle = &r100_gui_idle,
        .get_power_state = &r100_get_power_state,
        .set_power_state = &r100_set_power_state,
+       .pm_misc = &rs600_pm_misc,
+       .pm_prepare = &rs600_pm_prepare,
+       .pm_finish = &rs600_pm_finish,
 };
 
 static struct radeon_asic r600_asic = {
@@ -585,6 +615,9 @@ static struct radeon_asic r600_asic = {
        .gui_idle = &r600_gui_idle,
        .get_power_state = &r600_get_power_state,
        .set_power_state = &r600_set_power_state,
+       .pm_misc = &r600_pm_misc,
+       .pm_prepare = &rs600_pm_prepare,
+       .pm_finish = &rs600_pm_finish,
 };
 
 static struct radeon_asic rs780_asic = {
@@ -626,6 +659,9 @@ static struct radeon_asic rs780_asic = {
        .gui_idle = &r600_gui_idle,
        .get_power_state = &r600_get_power_state,
        .set_power_state = &r600_set_power_state,
+       .pm_misc = &r600_pm_misc,
+       .pm_prepare = &rs600_pm_prepare,
+       .pm_finish = &rs600_pm_finish,
 };
 
 static struct radeon_asic rv770_asic = {
@@ -667,6 +703,9 @@ static struct radeon_asic rv770_asic = {
        .gui_idle = &r600_gui_idle,
        .get_power_state = &r600_get_power_state,
        .set_power_state = &r600_set_power_state,
+       .pm_misc = &rv770_pm_misc,
+       .pm_prepare = &rs600_pm_prepare,
+       .pm_finish = &rs600_pm_finish,
 };
 
 static struct radeon_asic evergreen_asic = {
@@ -706,6 +745,9 @@ static struct radeon_asic evergreen_asic = {
        .gui_idle = &r600_gui_idle,
        .get_power_state = &r600_get_power_state,
        .set_power_state = &r600_set_power_state,
+       .pm_misc = &evergreen_pm_misc,
+       .pm_prepare = &evergreen_pm_prepare,
+       .pm_finish = &evergreen_pm_finish,
 };
 
 int radeon_asic_init(struct radeon_device *rdev)
index 71b21bb..378db67 100644 (file)
@@ -130,6 +130,9 @@ extern bool r100_gui_idle(struct radeon_device *rdev);
 extern void r100_set_power_state(struct radeon_device *rdev);
 extern void r100_get_power_state(struct radeon_device *rdev,
                                 enum radeon_pm_action action);
+extern void r100_pm_misc(struct radeon_device *rdev);
+extern void r100_pm_prepare(struct radeon_device *rdev);
+extern void r100_pm_finish(struct radeon_device *rdev);
 
 /*
  * r200,rv250,rs300,rv280
@@ -201,6 +204,9 @@ void rs600_hpd_fini(struct radeon_device *rdev);
 bool rs600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd);
 void rs600_hpd_set_polarity(struct radeon_device *rdev,
                            enum radeon_hpd_id hpd);
+extern void rs600_pm_misc(struct radeon_device *rdev);
+extern void rs600_pm_prepare(struct radeon_device *rdev);
+extern void rs600_pm_finish(struct radeon_device *rdev);
 
 /*
  * rs690,rs740
@@ -278,6 +284,7 @@ extern bool r600_gui_idle(struct radeon_device *rdev);
 extern void r600_set_power_state(struct radeon_device *rdev);
 extern void r600_get_power_state(struct radeon_device *rdev,
                                 enum radeon_pm_action action);
+extern void r600_pm_misc(struct radeon_device *rdev);
 
 /*
  * rv770,rv730,rv710,rv740
@@ -286,6 +293,7 @@ int rv770_init(struct radeon_device *rdev);
 void rv770_fini(struct radeon_device *rdev);
 int rv770_suspend(struct radeon_device *rdev);
 int rv770_resume(struct radeon_device *rdev);
+extern void rv770_pm_misc(struct radeon_device *rdev);
 
 /*
  * evergreen
@@ -306,5 +314,8 @@ void evergreen_hpd_set_polarity(struct radeon_device *rdev,
 u32 evergreen_get_vblank_counter(struct radeon_device *rdev, int crtc);
 int evergreen_irq_set(struct radeon_device *rdev);
 int evergreen_irq_process(struct radeon_device *rdev);
+extern void evergreen_pm_misc(struct radeon_device *rdev);
+extern void evergreen_pm_prepare(struct radeon_device *rdev);
+extern void evergreen_pm_finish(struct radeon_device *rdev);
 
 #endif
index b312b72..c3890b7 100644 (file)
 void rs600_gpu_init(struct radeon_device *rdev);
 int rs600_mc_wait_for_idle(struct radeon_device *rdev);
 
+void rs600_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, dyn_pwrmgt_sclk_length, dyn_sclk_vol_cntl;
+       u32 hdp_dyn_cntl, mc_host_dyn_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);
+               }
+       }
+
+       dyn_pwrmgt_sclk_length = RREG32_PLL(DYN_PWRMGT_SCLK_LENGTH);
+       dyn_pwrmgt_sclk_length &= ~REDUCED_POWER_SCLK_HILEN(0xf);
+       dyn_pwrmgt_sclk_length &= ~REDUCED_POWER_SCLK_LOLEN(0xf);
+       if (ps->misc & ATOM_PM_MISCINFO_ASIC_REDUCED_SPEED_SCLK_EN) {
+               if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_CLOCK_DIVIDER_BY_2) {
+                       dyn_pwrmgt_sclk_length |= REDUCED_POWER_SCLK_HILEN(2);
+                       dyn_pwrmgt_sclk_length |= REDUCED_POWER_SCLK_LOLEN(2);
+               } else if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_CLOCK_DIVIDER_BY_4) {
+                       dyn_pwrmgt_sclk_length |= REDUCED_POWER_SCLK_HILEN(4);
+                       dyn_pwrmgt_sclk_length |= REDUCED_POWER_SCLK_LOLEN(4);
+               }
+       } else {
+               dyn_pwrmgt_sclk_length |= REDUCED_POWER_SCLK_HILEN(1);
+               dyn_pwrmgt_sclk_length |= REDUCED_POWER_SCLK_LOLEN(1);
+       }
+       WREG32_PLL(DYN_PWRMGT_SCLK_LENGTH, dyn_pwrmgt_sclk_length);
+
+       dyn_sclk_vol_cntl = RREG32_PLL(DYN_SCLK_VOL_CNTL);
+       if (ps->misc & ATOM_PM_MISCINFO_ASIC_DYNAMIC_VOLTAGE_EN) {
+               dyn_sclk_vol_cntl |= IO_CG_VOLTAGE_DROP;
+               if (voltage->delay) {
+                       dyn_sclk_vol_cntl |= VOLTAGE_DROP_SYNC;
+                       dyn_sclk_vol_cntl |= VOLTAGE_DELAY_SEL(voltage->delay);
+               } else
+                       dyn_sclk_vol_cntl &= ~VOLTAGE_DROP_SYNC;
+       } else
+               dyn_sclk_vol_cntl &= ~IO_CG_VOLTAGE_DROP;
+       WREG32_PLL(DYN_SCLK_VOL_CNTL, dyn_sclk_vol_cntl);
+
+       hdp_dyn_cntl = RREG32_PLL(HDP_DYN_CNTL);
+       if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_HDP_BLOCK_EN)
+               hdp_dyn_cntl &= ~HDP_FORCEON;
+       else
+               hdp_dyn_cntl |= HDP_FORCEON;
+       WREG32_PLL(HDP_DYN_CNTL, hdp_dyn_cntl);
+
+       mc_host_dyn_cntl = RREG32_PLL(MC_HOST_DYN_CNTL);
+       if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_MC_HOST_BLOCK_EN)
+               mc_host_dyn_cntl &= ~MC_HOST_FORCEON;
+       else
+               mc_host_dyn_cntl |= MC_HOST_FORCEON;
+       WREG32_PLL(MC_HOST_DYN_CNTL, mc_host_dyn_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 rs600_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(AVIVO_D1CRTC_CONTROL + radeon_crtc->crtc_offset);
+                       tmp |= AVIVO_CRTC_DISP_READ_REQUEST_DISABLE;
+                       WREG32(AVIVO_D1CRTC_CONTROL + radeon_crtc->crtc_offset, tmp);
+               }
+       }
+}
+
+void rs600_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(AVIVO_D1CRTC_CONTROL + radeon_crtc->crtc_offset);
+                       tmp &= ~AVIVO_CRTC_DISP_READ_REQUEST_DISABLE;
+                       WREG32(AVIVO_D1CRTC_CONTROL + radeon_crtc->crtc_offset, tmp);
+               }
+       }
+}
+
 /* hpd for digital panel detect/disconnect */
 bool rs600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd)
 {
index 08c4beb..8f62434 100644 (file)
 #define   G_006D4C_D2MODE_PRIORITY_B_FORCE_MASK(x)     (((x) >> 24) & 0x1)
 #define   C_006D4C_D2MODE_PRIORITY_B_FORCE_MASK        0xFEFFFFFF
 
+/* PLL regs */
+#define GENERAL_PWRMGT                                 0x8
+#define   GLOBAL_PWRMGT_EN                             (1 << 0)
+#define   MOBILE_SU                                    (1 << 2)
+#define DYN_PWRMGT_SCLK_LENGTH                         0xc
+#define   NORMAL_POWER_SCLK_HILEN(x)                   ((x) << 0)
+#define   NORMAL_POWER_SCLK_LOLEN(x)                   ((x) << 4)
+#define   REDUCED_POWER_SCLK_HILEN(x)                  ((x) << 8)
+#define   REDUCED_POWER_SCLK_LOLEN(x)                  ((x) << 12)
+#define   POWER_D1_SCLK_HILEN(x)                       ((x) << 16)
+#define   POWER_D1_SCLK_LOLEN(x)                       ((x) << 20)
+#define   STATIC_SCREEN_HILEN(x)                       ((x) << 24)
+#define   STATIC_SCREEN_LOLEN(x)                       ((x) << 28)
+#define DYN_SCLK_VOL_CNTL                              0xe
+#define   IO_CG_VOLTAGE_DROP                           (1 << 0)
+#define   VOLTAGE_DROP_SYNC                            (1 << 2)
+#define   VOLTAGE_DELAY_SEL(x)                         ((x) << 3)
+#define HDP_DYN_CNTL                                   0x10
+#define   HDP_FORCEON                                  (1 << 0)
+#define MC_HOST_DYN_CNTL                               0x1e
+#define   MC_HOST_FORCEON                              (1 << 0)
+
+/* mmreg */
+#define DOUT_POWER_MANAGEMENT_CNTL                     0x7ee0
+#define   PWRDN_WAIT_BUSY_OFF                          (1 << 0)
+#define   PWRDN_WAIT_PWRSEQ_OFF                        (1 << 4)
+#define   PWRDN_WAIT_PPLL_OFF                          (1 << 8)
+#define   PWRUP_WAIT_PPLL_ON                           (1 << 12)
+#define   PWRUP_WAIT_MEM_INIT_DONE                     (1 << 16)
+#define   PM_ASSERT_RESET                              (1 << 20)
+#define   PM_PWRDN_PPLL                                (1 << 24)
+
 #endif
index a74683e..7c55182 100644 (file)
 static void rv770_gpu_init(struct radeon_device *rdev);
 void rv770_fini(struct radeon_device *rdev);
 
+void rv770_pm_misc(struct radeon_device *rdev)
+{
+
+}
 
 /*
  * GART