diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/r100.c')
-rw-r--r-- | drivers/gpu/drm/radeon/r100.c | 89 |
1 files changed, 75 insertions, 14 deletions
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 8e10aa9f74b0..46da5142b131 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c | |||
@@ -68,6 +68,56 @@ MODULE_FIRMWARE(FIRMWARE_R520); | |||
68 | * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 | 68 | * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 |
69 | */ | 69 | */ |
70 | 70 | ||
71 | void r100_pre_page_flip(struct radeon_device *rdev, int crtc) | ||
72 | { | ||
73 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; | ||
74 | u32 tmp; | ||
75 | |||
76 | /* make sure flip is at vb rather than hb */ | ||
77 | tmp = RREG32(RADEON_CRTC_OFFSET_CNTL + radeon_crtc->crtc_offset); | ||
78 | tmp &= ~RADEON_CRTC_OFFSET_FLIP_CNTL; | ||
79 | /* make sure pending bit is asserted */ | ||
80 | tmp |= RADEON_CRTC_GUI_TRIG_OFFSET_LEFT_EN; | ||
81 | WREG32(RADEON_CRTC_OFFSET_CNTL + radeon_crtc->crtc_offset, tmp); | ||
82 | |||
83 | /* set pageflip to happen as late as possible in the vblank interval. | ||
84 | * same field for crtc1/2 | ||
85 | */ | ||
86 | tmp = RREG32(RADEON_CRTC_GEN_CNTL); | ||
87 | tmp &= ~RADEON_CRTC_VSTAT_MODE_MASK; | ||
88 | WREG32(RADEON_CRTC_GEN_CNTL, tmp); | ||
89 | |||
90 | /* enable the pflip int */ | ||
91 | radeon_irq_kms_pflip_irq_get(rdev, crtc); | ||
92 | } | ||
93 | |||
94 | void r100_post_page_flip(struct radeon_device *rdev, int crtc) | ||
95 | { | ||
96 | /* disable the pflip int */ | ||
97 | radeon_irq_kms_pflip_irq_put(rdev, crtc); | ||
98 | } | ||
99 | |||
100 | u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) | ||
101 | { | ||
102 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; | ||
103 | u32 tmp = ((u32)crtc_base) | RADEON_CRTC_OFFSET__OFFSET_LOCK; | ||
104 | |||
105 | /* Lock the graphics update lock */ | ||
106 | /* update the scanout addresses */ | ||
107 | WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp); | ||
108 | |||
109 | /* Wait for update_pending to go high. */ | ||
110 | while (!(RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET)); | ||
111 | DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); | ||
112 | |||
113 | /* Unlock the lock, so double-buffering can take place inside vblank */ | ||
114 | tmp &= ~RADEON_CRTC_OFFSET__OFFSET_LOCK; | ||
115 | WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp); | ||
116 | |||
117 | /* Return current update_pending status: */ | ||
118 | return RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET; | ||
119 | } | ||
120 | |||
71 | void r100_pm_get_dynpm_state(struct radeon_device *rdev) | 121 | void r100_pm_get_dynpm_state(struct radeon_device *rdev) |
72 | { | 122 | { |
73 | int i; | 123 | int i; |
@@ -526,10 +576,12 @@ int r100_irq_set(struct radeon_device *rdev) | |||
526 | if (rdev->irq.gui_idle) { | 576 | if (rdev->irq.gui_idle) { |
527 | tmp |= RADEON_GUI_IDLE_MASK; | 577 | tmp |= RADEON_GUI_IDLE_MASK; |
528 | } | 578 | } |
529 | if (rdev->irq.crtc_vblank_int[0]) { | 579 | if (rdev->irq.crtc_vblank_int[0] || |
580 | rdev->irq.pflip[0]) { | ||
530 | tmp |= RADEON_CRTC_VBLANK_MASK; | 581 | tmp |= RADEON_CRTC_VBLANK_MASK; |
531 | } | 582 | } |
532 | if (rdev->irq.crtc_vblank_int[1]) { | 583 | if (rdev->irq.crtc_vblank_int[1] || |
584 | rdev->irq.pflip[1]) { | ||
533 | tmp |= RADEON_CRTC2_VBLANK_MASK; | 585 | tmp |= RADEON_CRTC2_VBLANK_MASK; |
534 | } | 586 | } |
535 | if (rdev->irq.hpd[0]) { | 587 | if (rdev->irq.hpd[0]) { |
@@ -600,14 +652,22 @@ int r100_irq_process(struct radeon_device *rdev) | |||
600 | } | 652 | } |
601 | /* Vertical blank interrupts */ | 653 | /* Vertical blank interrupts */ |
602 | if (status & RADEON_CRTC_VBLANK_STAT) { | 654 | if (status & RADEON_CRTC_VBLANK_STAT) { |
603 | drm_handle_vblank(rdev->ddev, 0); | 655 | if (rdev->irq.crtc_vblank_int[0]) { |
604 | rdev->pm.vblank_sync = true; | 656 | drm_handle_vblank(rdev->ddev, 0); |
605 | wake_up(&rdev->irq.vblank_queue); | 657 | rdev->pm.vblank_sync = true; |
658 | wake_up(&rdev->irq.vblank_queue); | ||
659 | } | ||
660 | if (rdev->irq.pflip[0]) | ||
661 | radeon_crtc_handle_flip(rdev, 0); | ||
606 | } | 662 | } |
607 | if (status & RADEON_CRTC2_VBLANK_STAT) { | 663 | if (status & RADEON_CRTC2_VBLANK_STAT) { |
608 | drm_handle_vblank(rdev->ddev, 1); | 664 | if (rdev->irq.crtc_vblank_int[1]) { |
609 | rdev->pm.vblank_sync = true; | 665 | drm_handle_vblank(rdev->ddev, 1); |
610 | wake_up(&rdev->irq.vblank_queue); | 666 | rdev->pm.vblank_sync = true; |
667 | wake_up(&rdev->irq.vblank_queue); | ||
668 | } | ||
669 | if (rdev->irq.pflip[1]) | ||
670 | radeon_crtc_handle_flip(rdev, 1); | ||
611 | } | 671 | } |
612 | if (status & RADEON_FP_DETECT_STAT) { | 672 | if (status & RADEON_FP_DETECT_STAT) { |
613 | queue_hotplug = true; | 673 | queue_hotplug = true; |
@@ -622,7 +682,7 @@ int r100_irq_process(struct radeon_device *rdev) | |||
622 | /* reset gui idle ack. the status bit is broken */ | 682 | /* reset gui idle ack. the status bit is broken */ |
623 | rdev->irq.gui_idle_acked = false; | 683 | rdev->irq.gui_idle_acked = false; |
624 | if (queue_hotplug) | 684 | if (queue_hotplug) |
625 | queue_work(rdev->wq, &rdev->hotplug_work); | 685 | schedule_work(&rdev->hotplug_work); |
626 | if (rdev->msi_enabled) { | 686 | if (rdev->msi_enabled) { |
627 | switch (rdev->family) { | 687 | switch (rdev->family) { |
628 | case CHIP_RS400: | 688 | case CHIP_RS400: |
@@ -2026,12 +2086,13 @@ int r100_asic_reset(struct radeon_device *rdev) | |||
2026 | { | 2086 | { |
2027 | struct r100_mc_save save; | 2087 | struct r100_mc_save save; |
2028 | u32 status, tmp; | 2088 | u32 status, tmp; |
2089 | int ret = 0; | ||
2029 | 2090 | ||
2030 | r100_mc_stop(rdev, &save); | ||
2031 | status = RREG32(R_000E40_RBBM_STATUS); | 2091 | status = RREG32(R_000E40_RBBM_STATUS); |
2032 | if (!G_000E40_GUI_ACTIVE(status)) { | 2092 | if (!G_000E40_GUI_ACTIVE(status)) { |
2033 | return 0; | 2093 | return 0; |
2034 | } | 2094 | } |
2095 | r100_mc_stop(rdev, &save); | ||
2035 | status = RREG32(R_000E40_RBBM_STATUS); | 2096 | status = RREG32(R_000E40_RBBM_STATUS); |
2036 | dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status); | 2097 | dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status); |
2037 | /* stop CP */ | 2098 | /* stop CP */ |
@@ -2071,11 +2132,11 @@ int r100_asic_reset(struct radeon_device *rdev) | |||
2071 | G_000E40_TAM_BUSY(status) || G_000E40_PB_BUSY(status)) { | 2132 | G_000E40_TAM_BUSY(status) || G_000E40_PB_BUSY(status)) { |
2072 | dev_err(rdev->dev, "failed to reset GPU\n"); | 2133 | dev_err(rdev->dev, "failed to reset GPU\n"); |
2073 | rdev->gpu_lockup = true; | 2134 | rdev->gpu_lockup = true; |
2074 | return -1; | 2135 | ret = -1; |
2075 | } | 2136 | } else |
2137 | dev_info(rdev->dev, "GPU reset succeed\n"); | ||
2076 | r100_mc_resume(rdev, &save); | 2138 | r100_mc_resume(rdev, &save); |
2077 | dev_info(rdev->dev, "GPU reset succeed\n"); | 2139 | return ret; |
2078 | return 0; | ||
2079 | } | 2140 | } |
2080 | 2141 | ||
2081 | void r100_set_common_regs(struct radeon_device *rdev) | 2142 | void r100_set_common_regs(struct radeon_device *rdev) |