diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/gpu/drm/radeon/radeon_device.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_device.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_device.c | 158 |
1 files changed, 130 insertions, 28 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 256d204a6d24..7cfaa7e2f3b5 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
@@ -81,6 +81,13 @@ static const char radeon_family_name[][16] = { | |||
81 | "JUNIPER", | 81 | "JUNIPER", |
82 | "CYPRESS", | 82 | "CYPRESS", |
83 | "HEMLOCK", | 83 | "HEMLOCK", |
84 | "PALM", | ||
85 | "SUMO", | ||
86 | "SUMO2", | ||
87 | "BARTS", | ||
88 | "TURKS", | ||
89 | "CAICOS", | ||
90 | "CAYMAN", | ||
84 | "LAST", | 91 | "LAST", |
85 | }; | 92 | }; |
86 | 93 | ||
@@ -117,9 +124,10 @@ void radeon_scratch_init(struct radeon_device *rdev) | |||
117 | } else { | 124 | } else { |
118 | rdev->scratch.num_reg = 7; | 125 | rdev->scratch.num_reg = 7; |
119 | } | 126 | } |
127 | rdev->scratch.reg_base = RADEON_SCRATCH_REG0; | ||
120 | for (i = 0; i < rdev->scratch.num_reg; i++) { | 128 | for (i = 0; i < rdev->scratch.num_reg; i++) { |
121 | rdev->scratch.free[i] = true; | 129 | rdev->scratch.free[i] = true; |
122 | rdev->scratch.reg[i] = RADEON_SCRATCH_REG0 + (i * 4); | 130 | rdev->scratch.reg[i] = rdev->scratch.reg_base + (i * 4); |
123 | } | 131 | } |
124 | } | 132 | } |
125 | 133 | ||
@@ -149,6 +157,93 @@ void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg) | |||
149 | } | 157 | } |
150 | } | 158 | } |
151 | 159 | ||
160 | void radeon_wb_disable(struct radeon_device *rdev) | ||
161 | { | ||
162 | int r; | ||
163 | |||
164 | if (rdev->wb.wb_obj) { | ||
165 | r = radeon_bo_reserve(rdev->wb.wb_obj, false); | ||
166 | if (unlikely(r != 0)) | ||
167 | return; | ||
168 | radeon_bo_kunmap(rdev->wb.wb_obj); | ||
169 | radeon_bo_unpin(rdev->wb.wb_obj); | ||
170 | radeon_bo_unreserve(rdev->wb.wb_obj); | ||
171 | } | ||
172 | rdev->wb.enabled = false; | ||
173 | } | ||
174 | |||
175 | void radeon_wb_fini(struct radeon_device *rdev) | ||
176 | { | ||
177 | radeon_wb_disable(rdev); | ||
178 | if (rdev->wb.wb_obj) { | ||
179 | radeon_bo_unref(&rdev->wb.wb_obj); | ||
180 | rdev->wb.wb = NULL; | ||
181 | rdev->wb.wb_obj = NULL; | ||
182 | } | ||
183 | } | ||
184 | |||
185 | int radeon_wb_init(struct radeon_device *rdev) | ||
186 | { | ||
187 | int r; | ||
188 | |||
189 | if (rdev->wb.wb_obj == NULL) { | ||
190 | r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE, PAGE_SIZE, true, | ||
191 | RADEON_GEM_DOMAIN_GTT, &rdev->wb.wb_obj); | ||
192 | if (r) { | ||
193 | dev_warn(rdev->dev, "(%d) create WB bo failed\n", r); | ||
194 | return r; | ||
195 | } | ||
196 | } | ||
197 | r = radeon_bo_reserve(rdev->wb.wb_obj, false); | ||
198 | if (unlikely(r != 0)) { | ||
199 | radeon_wb_fini(rdev); | ||
200 | return r; | ||
201 | } | ||
202 | r = radeon_bo_pin(rdev->wb.wb_obj, RADEON_GEM_DOMAIN_GTT, | ||
203 | &rdev->wb.gpu_addr); | ||
204 | if (r) { | ||
205 | radeon_bo_unreserve(rdev->wb.wb_obj); | ||
206 | dev_warn(rdev->dev, "(%d) pin WB bo failed\n", r); | ||
207 | radeon_wb_fini(rdev); | ||
208 | return r; | ||
209 | } | ||
210 | r = radeon_bo_kmap(rdev->wb.wb_obj, (void **)&rdev->wb.wb); | ||
211 | radeon_bo_unreserve(rdev->wb.wb_obj); | ||
212 | if (r) { | ||
213 | dev_warn(rdev->dev, "(%d) map WB bo failed\n", r); | ||
214 | radeon_wb_fini(rdev); | ||
215 | return r; | ||
216 | } | ||
217 | |||
218 | /* clear wb memory */ | ||
219 | memset((char *)rdev->wb.wb, 0, RADEON_GPU_PAGE_SIZE); | ||
220 | /* disable event_write fences */ | ||
221 | rdev->wb.use_event = false; | ||
222 | /* disabled via module param */ | ||
223 | if (radeon_no_wb == 1) | ||
224 | rdev->wb.enabled = false; | ||
225 | else { | ||
226 | /* often unreliable on AGP */ | ||
227 | if (rdev->flags & RADEON_IS_AGP) { | ||
228 | rdev->wb.enabled = false; | ||
229 | } else { | ||
230 | rdev->wb.enabled = true; | ||
231 | /* event_write fences are only available on r600+ */ | ||
232 | if (rdev->family >= CHIP_R600) | ||
233 | rdev->wb.use_event = true; | ||
234 | } | ||
235 | } | ||
236 | /* always use writeback/events on NI */ | ||
237 | if (ASIC_IS_DCE5(rdev)) { | ||
238 | rdev->wb.enabled = true; | ||
239 | rdev->wb.use_event = true; | ||
240 | } | ||
241 | |||
242 | dev_info(rdev->dev, "WB %sabled\n", rdev->wb.enabled ? "en" : "dis"); | ||
243 | |||
244 | return 0; | ||
245 | } | ||
246 | |||
152 | /** | 247 | /** |
153 | * radeon_vram_location - try to find VRAM location | 248 | * radeon_vram_location - try to find VRAM location |
154 | * @rdev: radeon device structure holding all necessary informations | 249 | * @rdev: radeon device structure holding all necessary informations |
@@ -171,7 +266,7 @@ void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg) | |||
171 | * Note: GTT start, end, size should be initialized before calling this | 266 | * Note: GTT start, end, size should be initialized before calling this |
172 | * function on AGP platform. | 267 | * function on AGP platform. |
173 | * | 268 | * |
174 | * Note: We don't explictly enforce VRAM start to be aligned on VRAM size, | 269 | * Note: We don't explicitly enforce VRAM start to be aligned on VRAM size, |
175 | * this shouldn't be a problem as we are using the PCI aperture as a reference. | 270 | * this shouldn't be a problem as we are using the PCI aperture as a reference. |
176 | * Otherwise this would be needed for rv280, all r3xx, and all r4xx, but | 271 | * Otherwise this would be needed for rv280, all r3xx, and all r4xx, but |
177 | * not IGP. | 272 | * not IGP. |
@@ -205,7 +300,7 @@ void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 | |||
205 | mc->mc_vram_size = mc->aper_size; | 300 | mc->mc_vram_size = mc->aper_size; |
206 | } | 301 | } |
207 | mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; | 302 | mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; |
208 | dev_info(rdev->dev, "VRAM: %lluM 0x%08llX - 0x%08llX (%lluM used)\n", | 303 | dev_info(rdev->dev, "VRAM: %lluM 0x%016llX - 0x%016llX (%lluM used)\n", |
209 | mc->mc_vram_size >> 20, mc->vram_start, | 304 | mc->mc_vram_size >> 20, mc->vram_start, |
210 | mc->vram_end, mc->real_vram_size >> 20); | 305 | mc->vram_end, mc->real_vram_size >> 20); |
211 | } | 306 | } |
@@ -242,7 +337,7 @@ void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) | |||
242 | mc->gtt_start = (mc->vram_end + 1 + mc->gtt_base_align) & ~mc->gtt_base_align; | 337 | mc->gtt_start = (mc->vram_end + 1 + mc->gtt_base_align) & ~mc->gtt_base_align; |
243 | } | 338 | } |
244 | mc->gtt_end = mc->gtt_start + mc->gtt_size - 1; | 339 | mc->gtt_end = mc->gtt_start + mc->gtt_size - 1; |
245 | dev_info(rdev->dev, "GTT: %lluM 0x%08llX - 0x%08llX\n", | 340 | dev_info(rdev->dev, "GTT: %lluM 0x%016llX - 0x%016llX\n", |
246 | mc->gtt_size >> 20, mc->gtt_start, mc->gtt_end); | 341 | mc->gtt_size >> 20, mc->gtt_start, mc->gtt_end); |
247 | } | 342 | } |
248 | 343 | ||
@@ -254,7 +349,12 @@ bool radeon_card_posted(struct radeon_device *rdev) | |||
254 | uint32_t reg; | 349 | uint32_t reg; |
255 | 350 | ||
256 | /* first check CRTCs */ | 351 | /* first check CRTCs */ |
257 | if (ASIC_IS_DCE4(rdev)) { | 352 | if (ASIC_IS_DCE41(rdev)) { |
353 | reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) | | ||
354 | RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET); | ||
355 | if (reg & EVERGREEN_CRTC_MASTER_EN) | ||
356 | return true; | ||
357 | } else if (ASIC_IS_DCE4(rdev)) { | ||
258 | reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) | | 358 | reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) | |
259 | RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET) | | 359 | RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET) | |
260 | RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET) | | 360 | RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET) | |
@@ -555,20 +655,20 @@ void radeon_check_arguments(struct radeon_device *rdev) | |||
555 | static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state) | 655 | static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state) |
556 | { | 656 | { |
557 | struct drm_device *dev = pci_get_drvdata(pdev); | 657 | struct drm_device *dev = pci_get_drvdata(pdev); |
558 | struct radeon_device *rdev = dev->dev_private; | ||
559 | pm_message_t pmm = { .event = PM_EVENT_SUSPEND }; | 658 | pm_message_t pmm = { .event = PM_EVENT_SUSPEND }; |
560 | if (state == VGA_SWITCHEROO_ON) { | 659 | if (state == VGA_SWITCHEROO_ON) { |
561 | printk(KERN_INFO "radeon: switched on\n"); | 660 | printk(KERN_INFO "radeon: switched on\n"); |
562 | /* don't suspend or resume card normally */ | 661 | /* don't suspend or resume card normally */ |
563 | rdev->powered_down = false; | 662 | dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; |
564 | radeon_resume_kms(dev); | 663 | radeon_resume_kms(dev); |
664 | dev->switch_power_state = DRM_SWITCH_POWER_ON; | ||
565 | drm_kms_helper_poll_enable(dev); | 665 | drm_kms_helper_poll_enable(dev); |
566 | } else { | 666 | } else { |
567 | printk(KERN_INFO "radeon: switched off\n"); | 667 | printk(KERN_INFO "radeon: switched off\n"); |
568 | drm_kms_helper_poll_disable(dev); | 668 | drm_kms_helper_poll_disable(dev); |
669 | dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; | ||
569 | radeon_suspend_kms(dev, pmm); | 670 | radeon_suspend_kms(dev, pmm); |
570 | /* don't suspend or resume card normally */ | 671 | dev->switch_power_state = DRM_SWITCH_POWER_OFF; |
571 | rdev->powered_down = true; | ||
572 | } | 672 | } |
573 | } | 673 | } |
574 | 674 | ||
@@ -623,11 +723,6 @@ int radeon_device_init(struct radeon_device *rdev, | |||
623 | init_waitqueue_head(&rdev->irq.vblank_queue); | 723 | init_waitqueue_head(&rdev->irq.vblank_queue); |
624 | init_waitqueue_head(&rdev->irq.idle_queue); | 724 | init_waitqueue_head(&rdev->irq.idle_queue); |
625 | 725 | ||
626 | /* setup workqueue */ | ||
627 | rdev->wq = create_workqueue("radeon"); | ||
628 | if (rdev->wq == NULL) | ||
629 | return -ENOMEM; | ||
630 | |||
631 | /* Set asic functions */ | 726 | /* Set asic functions */ |
632 | r = radeon_asic_init(rdev); | 727 | r = radeon_asic_init(rdev); |
633 | if (r) | 728 | if (r) |
@@ -661,6 +756,7 @@ int radeon_device_init(struct radeon_device *rdev, | |||
661 | dma_bits = rdev->need_dma32 ? 32 : 40; | 756 | dma_bits = rdev->need_dma32 ? 32 : 40; |
662 | r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits)); | 757 | r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits)); |
663 | if (r) { | 758 | if (r) { |
759 | rdev->need_dma32 = true; | ||
664 | printk(KERN_WARNING "radeon: No suitable DMA available.\n"); | 760 | printk(KERN_WARNING "radeon: No suitable DMA available.\n"); |
665 | } | 761 | } |
666 | 762 | ||
@@ -692,6 +788,7 @@ int radeon_device_init(struct radeon_device *rdev, | |||
692 | vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode); | 788 | vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode); |
693 | vga_switcheroo_register_client(rdev->pdev, | 789 | vga_switcheroo_register_client(rdev->pdev, |
694 | radeon_switcheroo_set_state, | 790 | radeon_switcheroo_set_state, |
791 | NULL, | ||
695 | radeon_switcheroo_can_switch); | 792 | radeon_switcheroo_can_switch); |
696 | 793 | ||
697 | r = radeon_init(rdev); | 794 | r = radeon_init(rdev); |
@@ -725,7 +822,6 @@ void radeon_device_fini(struct radeon_device *rdev) | |||
725 | /* evict vram memory */ | 822 | /* evict vram memory */ |
726 | radeon_bo_evict_vram(rdev); | 823 | radeon_bo_evict_vram(rdev); |
727 | radeon_fini(rdev); | 824 | radeon_fini(rdev); |
728 | destroy_workqueue(rdev->wq); | ||
729 | vga_switcheroo_unregister_client(rdev->pdev); | 825 | vga_switcheroo_unregister_client(rdev->pdev); |
730 | vga_client_register(rdev->pdev, NULL, NULL, NULL); | 826 | vga_client_register(rdev->pdev, NULL, NULL, NULL); |
731 | if (rdev->rio_mem) | 827 | if (rdev->rio_mem) |
@@ -754,7 +850,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) | |||
754 | } | 850 | } |
755 | rdev = dev->dev_private; | 851 | rdev = dev->dev_private; |
756 | 852 | ||
757 | if (rdev->powered_down) | 853 | if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) |
758 | return 0; | 854 | return 0; |
759 | 855 | ||
760 | /* turn off display hw */ | 856 | /* turn off display hw */ |
@@ -770,7 +866,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) | |||
770 | if (rfb == NULL || rfb->obj == NULL) { | 866 | if (rfb == NULL || rfb->obj == NULL) { |
771 | continue; | 867 | continue; |
772 | } | 868 | } |
773 | robj = rfb->obj->driver_private; | 869 | robj = gem_to_radeon_bo(rfb->obj); |
774 | /* don't unpin kernel fb objects */ | 870 | /* don't unpin kernel fb objects */ |
775 | if (!radeon_fbdev_robj_is_fb(rdev, robj)) { | 871 | if (!radeon_fbdev_robj_is_fb(rdev, robj)) { |
776 | r = radeon_bo_reserve(robj, false); | 872 | r = radeon_bo_reserve(robj, false); |
@@ -801,9 +897,9 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) | |||
801 | pci_disable_device(dev->pdev); | 897 | pci_disable_device(dev->pdev); |
802 | pci_set_power_state(dev->pdev, PCI_D3hot); | 898 | pci_set_power_state(dev->pdev, PCI_D3hot); |
803 | } | 899 | } |
804 | acquire_console_sem(); | 900 | console_lock(); |
805 | radeon_fbdev_set_suspend(rdev, 1); | 901 | radeon_fbdev_set_suspend(rdev, 1); |
806 | release_console_sem(); | 902 | console_unlock(); |
807 | return 0; | 903 | return 0; |
808 | } | 904 | } |
809 | 905 | ||
@@ -812,14 +908,14 @@ int radeon_resume_kms(struct drm_device *dev) | |||
812 | struct drm_connector *connector; | 908 | struct drm_connector *connector; |
813 | struct radeon_device *rdev = dev->dev_private; | 909 | struct radeon_device *rdev = dev->dev_private; |
814 | 910 | ||
815 | if (rdev->powered_down) | 911 | if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) |
816 | return 0; | 912 | return 0; |
817 | 913 | ||
818 | acquire_console_sem(); | 914 | console_lock(); |
819 | pci_set_power_state(dev->pdev, PCI_D0); | 915 | pci_set_power_state(dev->pdev, PCI_D0); |
820 | pci_restore_state(dev->pdev); | 916 | pci_restore_state(dev->pdev); |
821 | if (pci_enable_device(dev->pdev)) { | 917 | if (pci_enable_device(dev->pdev)) { |
822 | release_console_sem(); | 918 | console_unlock(); |
823 | return -1; | 919 | return -1; |
824 | } | 920 | } |
825 | pci_set_master(dev->pdev); | 921 | pci_set_master(dev->pdev); |
@@ -829,26 +925,31 @@ int radeon_resume_kms(struct drm_device *dev) | |||
829 | radeon_pm_resume(rdev); | 925 | radeon_pm_resume(rdev); |
830 | radeon_restore_bios_scratch_regs(rdev); | 926 | radeon_restore_bios_scratch_regs(rdev); |
831 | 927 | ||
832 | /* turn on display hw */ | ||
833 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
834 | drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); | ||
835 | } | ||
836 | |||
837 | radeon_fbdev_set_suspend(rdev, 0); | 928 | radeon_fbdev_set_suspend(rdev, 0); |
838 | release_console_sem(); | 929 | console_unlock(); |
839 | 930 | ||
931 | /* init dig PHYs */ | ||
932 | if (rdev->is_atom_bios) | ||
933 | radeon_atom_encoder_init(rdev); | ||
840 | /* reset hpd state */ | 934 | /* reset hpd state */ |
841 | radeon_hpd_init(rdev); | 935 | radeon_hpd_init(rdev); |
842 | /* blat the mode back in */ | 936 | /* blat the mode back in */ |
843 | drm_helper_resume_force_mode(dev); | 937 | drm_helper_resume_force_mode(dev); |
938 | /* turn on display hw */ | ||
939 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
940 | drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); | ||
941 | } | ||
844 | return 0; | 942 | return 0; |
845 | } | 943 | } |
846 | 944 | ||
847 | int radeon_gpu_reset(struct radeon_device *rdev) | 945 | int radeon_gpu_reset(struct radeon_device *rdev) |
848 | { | 946 | { |
849 | int r; | 947 | int r; |
948 | int resched; | ||
850 | 949 | ||
851 | radeon_save_bios_scratch_regs(rdev); | 950 | radeon_save_bios_scratch_regs(rdev); |
951 | /* block TTM */ | ||
952 | resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev); | ||
852 | radeon_suspend(rdev); | 953 | radeon_suspend(rdev); |
853 | 954 | ||
854 | r = radeon_asic_reset(rdev); | 955 | r = radeon_asic_reset(rdev); |
@@ -857,6 +958,7 @@ int radeon_gpu_reset(struct radeon_device *rdev) | |||
857 | radeon_resume(rdev); | 958 | radeon_resume(rdev); |
858 | radeon_restore_bios_scratch_regs(rdev); | 959 | radeon_restore_bios_scratch_regs(rdev); |
859 | drm_helper_resume_force_mode(rdev->ddev); | 960 | drm_helper_resume_force_mode(rdev->ddev); |
961 | ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); | ||
860 | return 0; | 962 | return 0; |
861 | } | 963 | } |
862 | /* bad news, how to tell it to userspace ? */ | 964 | /* bad news, how to tell it to userspace ? */ |