diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 62b27be..065ce01 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -733,6 +733,8 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size) udelay(10); rdev->cp.rptr = RREG32(RADEON_CP_RB_RPTR); rdev->cp.wptr = RREG32(RADEON_CP_RB_WPTR); + /* protect against crazy HW on resume */ + rdev->cp.wptr &= rdev->cp.ptr_mask; /* Set cp mode to bus mastering & enable cp*/ WREG32(RADEON_CP_CSQ_MODE, REG_SET(RADEON_INDIRECT2_START, indirect2_start) | @@ -1793,6 +1795,7 @@ int r100_gpu_reset(struct radeon_device *rdev) void r100_set_common_regs(struct radeon_device *rdev) { + u32 tmp; /* set these so they don't interfere with anything */ WREG32(RADEON_OV0_SCALE_CNTL, 0); WREG32(RADEON_SUBPIC_CNTL, 0); @@ -1801,6 +1804,11 @@ void r100_set_common_regs(struct radeon_device *rdev) WREG32(RADEON_DVI_I2C_CNTL_1, 0); WREG32(RADEON_CAP0_TRIG_CNTL, 0); WREG32(RADEON_CAP1_TRIG_CNTL, 0); + + /* switch PM block to ACPI mode */ + tmp = RREG32_PLL(RADEON_PLL_PWRMGT_CNTL); + tmp &= ~RADEON_PM_MODE_SEL; + WREG32_PLL(RADEON_PLL_PWRMGT_CNTL, tmp); } /* @@ -3336,6 +3344,7 @@ static int r100_startup(struct radeon_device *rdev) int r100_resume(struct radeon_device *rdev) { + u32 save, tmp; /* Make sur GART are not working */ if (rdev->flags & RADEON_IS_PCI) r100_pci_gart_disable(rdev); @@ -3347,8 +3356,36 @@ int r100_resume(struct radeon_device *rdev) RREG32(R_000E40_RBBM_STATUS), RREG32(R_0007C0_CP_STAT)); } + printk("SCLK %08x, MCLK %08x, PIN %08x, PLL_PWR %08x, CLK_PWR %08x\n", + RREG32_PLL(RADEON_SCLK_CNTL), RREG32_PLL(RADEON_MCLK_CNTL), + RREG32_PLL(RADEON_CLK_PIN_CNTL), RREG32_PLL(RADEON_PLL_PWRMGT_CNTL), + RREG32_PLL(RADEON_CLK_PWRMGT_CNTL)); + { + save = RREG32_PLL(RADEON_SCLK_CNTL); + tmp = save |= RADEON_SCLK_FORCE_HDP| + RADEON_SCLK_FORCE_DISP1| + RADEON_SCLK_FORCE_DISP2| + RADEON_SCLK_FORCE_TOP| + RADEON_SCLK_FORCE_SE| + RADEON_SCLK_FORCE_IDCT| + RADEON_SCLK_FORCE_VIP| + RADEON_SCLK_FORCE_PB| + RADEON_SCLK_FORCE_RE| + RADEON_SCLK_FORCE_TAM| + RADEON_SCLK_FORCE_TDM| + RADEON_SCLK_FORCE_RB| + RADEON_SCLK_FORCE_TV_SCLK| + RADEON_SCLK_FORCE_SUBPIC| + RADEON_SCLK_FORCE_OV0; + WREG32_PLL(RADEON_SCLK_CNTL, tmp); + } /* post */ radeon_combios_asic_init(rdev->ddev); + printk("SCLK %08x, MCLK %08x, PIN %08x, PLL_PWR %08x, CLK_PWR %08x\n", + RREG32_PLL(RADEON_SCLK_CNTL), RREG32_PLL(RADEON_MCLK_CNTL), + RREG32_PLL(RADEON_CLK_PIN_CNTL), RREG32_PLL(RADEON_PLL_PWRMGT_CNTL), + RREG32_PLL(RADEON_CLK_PWRMGT_CNTL)); + WREG32_PLL(RADEON_SCLK_CNTL, save); /* Resume clock after posting */ r100_clock_startup(rdev); /* Initialize surface registers */ @@ -3358,11 +3395,19 @@ int r100_resume(struct radeon_device *rdev) int r100_suspend(struct radeon_device *rdev) { + struct r100_mc_save save; r100_cp_disable(rdev); r100_wb_disable(rdev); r100_irq_disable(rdev); if (rdev->flags & RADEON_IS_PCI) r100_pci_gart_disable(rdev); + r100_mc_stop(rdev, &save); + + printk("SCLK %08x, MCLK %08x, PIN %08x, PLL_PWR %08x, CLK_PWR %08x\n", + RREG32_PLL(RADEON_SCLK_CNTL), RREG32_PLL(RADEON_MCLK_CNTL), + RREG32_PLL(RADEON_CLK_PIN_CNTL), RREG32_PLL(RADEON_PLL_PWRMGT_CNTL), + RREG32_PLL(RADEON_CLK_PWRMGT_CNTL)); + return 0; } diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 768b150..3290e88 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -728,7 +728,43 @@ void radeon_device_fini(struct radeon_device *rdev) rdev->rmmio = NULL; } +static int radeon_m9_whack_power_state(struct drm_device *dev, pci_power_t state) +{ + u16 pwr_cmd; + struct radeon_device *rdev = dev->dev_private; + u32 tmp; + int pm_reg; + int loop_count = 0; + + pm_reg = pci_find_capability(dev->pdev, PCI_CAP_ID_PM); + if (!pm_reg) + return 0; + + if (state > 3) + return 0; + for (loop_count = 0; loop_count < 20; loop_count++) { + pci_read_config_word(dev->pdev, pm_reg+PCI_PM_CTRL, &pwr_cmd); + printk(KERN_ERR "pwr_cmd is %04x\n", pwr_cmd); + + if ((pwr_cmd & 3) == state) + break; + pwr_cmd = (pwr_cmd & ~PCI_PM_CTRL_STATE_MASK) | state; + pci_write_config_word(dev->pdev, pm_reg+PCI_PM_CTRL, pwr_cmd); + + /* switch PM block to ACPI mode */ + tmp = RREG32_PLL(RADEON_PLL_PWRMGT_CNTL); + tmp &= ~RADEON_PM_MODE_SEL; + WREG32_PLL(RADEON_PLL_PWRMGT_CNTL, tmp); + + msleep(500); + } + if (loop_count >= 20) + printk(KERN_ERR "Unable to whack into D3\n"); + dev->pdev->current_state = state; + __pci_complete_power_transition(dev->pdev, state); + return 0; +} /* * Suspend & resume. */ @@ -779,6 +815,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) if (state.event == PM_EVENT_SUSPEND) { /* Shut down the device */ pci_disable_device(dev->pdev); + radeon_m9_whack_power_state(dev, PCI_D3hot); pci_set_power_state(dev->pdev, PCI_D3hot); } acquire_console_sem(); @@ -791,18 +828,23 @@ int radeon_resume_kms(struct drm_device *dev) { struct radeon_device *rdev = dev->dev_private; - acquire_console_sem(); + printk("in rrk\n"); pci_set_power_state(dev->pdev, PCI_D0); pci_restore_state(dev->pdev); if (pci_enable_device(dev->pdev)) { release_console_sem(); + printk("in rrkfail \n"); return -1; } + printk("in rrksuccess \n"); pci_set_master(dev->pdev); /* resume AGP if in use */ radeon_agp_resume(rdev); + printk("in rrksuccess post agp resume\n"); radeon_resume(rdev); + printk("in rrksuccess post resume\n"); radeon_restore_bios_scratch_regs(rdev); + acquire_console_sem(); fb_set_suspend(rdev->fbdev_info, 0); release_console_sem(); diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index f23b056..c73e52a 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -172,15 +172,34 @@ u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc) int radeon_enable_vblank_kms(struct drm_device *dev, int crtc) { struct radeon_device *rdev = dev->dev_private; - + u32 tmp; if (crtc < 0 || crtc > 1) { DRM_ERROR("Invalid crtc %d\n", crtc); return -EINVAL; } + if (ASIC_IS_AVIVO(rdev)) { + + } else { + switch (crtc) { + case 0: + tmp = RREG32(RADEON_CRTC_GEN_CNTL); + if (!(tmp & RADEON_CRTC_EN)) + goto fail; + break; + case 1: + tmp = RREG32(RADEON_CRTC2_GEN_CNTL); + if (!(tmp & RADEON_CRTC_EN)) + goto fail; + break; + } + } rdev->irq.crtc_vblank_int[crtc] = true; return radeon_irq_set(rdev); +fail: + printk(KERN_ERR "tried to enable vbl on disabled crtc %d\n", crtc); + return -1; } void radeon_disable_vblank_kms(struct drm_device *dev, int crtc) diff --git a/drivers/gpu/drm/radeon/radeon_reg.h b/drivers/gpu/drm/radeon/radeon_reg.h index 6d0a009..b85202c 100644 --- a/drivers/gpu/drm/radeon/radeon_reg.h +++ b/drivers/gpu/drm/radeon/radeon_reg.h @@ -346,6 +346,7 @@ # define RADEON_TVPLL_PWRMGT_OFF (1 << 30) # define RADEON_TVCLK_TURNOFF (1 << 31) #define RADEON_PLL_PWRMGT_CNTL 0x0015 /* PLL */ +# define RADEON_PM_MODE_SEL (1 << 13) # define RADEON_TCL_BYPASS_DISABLE (1 << 20) #define RADEON_CLR_CMP_CLR_3D 0x1a24 #define RADEON_CLR_CMP_CLR_DST 0x15c8