Rev 1129 | Rev 1221 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1117 | serge | 1 | /* |
2 | * Copyright 2008 Advanced Micro Devices, Inc. |
||
3 | * Copyright 2008 Red Hat Inc. |
||
4 | * Copyright 2009 Jerome Glisse. |
||
5 | * |
||
6 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
7 | * copy of this software and associated documentation files (the "Software"), |
||
8 | * to deal in the Software without restriction, including without limitation |
||
9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||
10 | * and/or sell copies of the Software, and to permit persons to whom the |
||
11 | * Software is furnished to do so, subject to the following conditions: |
||
12 | * |
||
13 | * The above copyright notice and this permission notice shall be included in |
||
14 | * all copies or substantial portions of the Software. |
||
15 | * |
||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||
19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR |
||
20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
||
21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
||
22 | * OTHER DEALINGS IN THE SOFTWARE. |
||
23 | * |
||
24 | * Authors: Dave Airlie |
||
25 | * Alex Deucher |
||
26 | * Jerome Glisse |
||
27 | */ |
||
1179 | serge | 28 | #include |
1125 | serge | 29 | #include "drmP.h" |
30 | #include "drm.h" |
||
1117 | serge | 31 | #include "radeon_drm.h" |
32 | #include "radeon_microcode.h" |
||
33 | #include "radeon_reg.h" |
||
34 | #include "radeon.h" |
||
1179 | serge | 35 | #include "r100d.h" |
1117 | serge | 36 | |
1179 | serge | 37 | #include "r100_reg_safe.h" |
38 | #include "rn50_reg_safe.h" |
||
1117 | serge | 39 | /* This files gather functions specifics to: |
40 | * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 |
||
41 | * |
||
42 | * Some of these functions might be used by newer ASICs. |
||
43 | */ |
||
1179 | serge | 44 | int r200_init(struct radeon_device *rdev); |
1117 | serge | 45 | void r100_hdp_reset(struct radeon_device *rdev); |
46 | void r100_gpu_init(struct radeon_device *rdev); |
||
47 | int r100_gui_wait_for_idle(struct radeon_device *rdev); |
||
48 | int r100_mc_wait_for_idle(struct radeon_device *rdev); |
||
49 | void r100_gpu_wait_for_vsync(struct radeon_device *rdev); |
||
50 | void r100_gpu_wait_for_vsync2(struct radeon_device *rdev); |
||
51 | int r100_debugfs_mc_info_init(struct radeon_device *rdev); |
||
52 | |||
1179 | serge | 53 | |
1117 | serge | 54 | /* |
55 | * PCI GART |
||
56 | */ |
||
57 | void r100_pci_gart_tlb_flush(struct radeon_device *rdev) |
||
58 | { |
||
59 | /* TODO: can we do somethings here ? */ |
||
60 | /* It seems hw only cache one entry so we should discard this |
||
61 | * entry otherwise if first GPU GART read hit this entry it |
||
62 | * could end up in wrong address. */ |
||
63 | } |
||
64 | |||
1179 | serge | 65 | int r100_pci_gart_init(struct radeon_device *rdev) |
1117 | serge | 66 | { |
67 | int r; |
||
68 | |||
1179 | serge | 69 | if (rdev->gart.table.ram.ptr) { |
70 | WARN(1, "R100 PCI GART already initialized.\n"); |
||
71 | return 0; |
||
72 | } |
||
1117 | serge | 73 | /* Initialize common gart structure */ |
74 | r = radeon_gart_init(rdev); |
||
1179 | serge | 75 | if (r) |
1117 | serge | 76 | return r; |
77 | rdev->gart.table_size = rdev->gart.num_gpu_pages * 4; |
||
1179 | serge | 78 | rdev->asic->gart_tlb_flush = &r100_pci_gart_tlb_flush; |
79 | rdev->asic->gart_set_page = &r100_pci_gart_set_page; |
||
80 | return radeon_gart_table_ram_alloc(rdev); |
||
81 | } |
||
82 | |||
83 | int r100_pci_gart_enable(struct radeon_device *rdev) |
||
84 | { |
||
85 | uint32_t tmp; |
||
86 | |||
1117 | serge | 87 | /* discard memory request outside of configured range */ |
88 | tmp = RREG32(RADEON_AIC_CNTL) | RADEON_DIS_OUT_OF_PCI_GART_ACCESS; |
||
89 | WREG32(RADEON_AIC_CNTL, tmp); |
||
90 | /* set address range for PCI address translate */ |
||
91 | WREG32(RADEON_AIC_LO_ADDR, rdev->mc.gtt_location); |
||
92 | tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1; |
||
93 | WREG32(RADEON_AIC_HI_ADDR, tmp); |
||
94 | /* Enable bus mastering */ |
||
95 | tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; |
||
96 | WREG32(RADEON_BUS_CNTL, tmp); |
||
97 | /* set PCI GART page-table base address */ |
||
98 | WREG32(RADEON_AIC_PT_BASE, rdev->gart.table_addr); |
||
99 | tmp = RREG32(RADEON_AIC_CNTL) | RADEON_PCIGART_TRANSLATE_EN; |
||
100 | WREG32(RADEON_AIC_CNTL, tmp); |
||
101 | r100_pci_gart_tlb_flush(rdev); |
||
102 | rdev->gart.ready = true; |
||
103 | return 0; |
||
104 | } |
||
105 | |||
106 | void r100_pci_gart_disable(struct radeon_device *rdev) |
||
107 | { |
||
108 | uint32_t tmp; |
||
109 | |||
110 | /* discard memory request outside of configured range */ |
||
111 | tmp = RREG32(RADEON_AIC_CNTL) | RADEON_DIS_OUT_OF_PCI_GART_ACCESS; |
||
112 | WREG32(RADEON_AIC_CNTL, tmp & ~RADEON_PCIGART_TRANSLATE_EN); |
||
113 | WREG32(RADEON_AIC_LO_ADDR, 0); |
||
114 | WREG32(RADEON_AIC_HI_ADDR, 0); |
||
115 | } |
||
116 | |||
117 | int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) |
||
118 | { |
||
119 | if (i < 0 || i > rdev->gart.num_gpu_pages) { |
||
120 | return -EINVAL; |
||
121 | } |
||
1179 | serge | 122 | rdev->gart.table.ram.ptr[i] = cpu_to_le32(lower_32_bits(addr)); |
1117 | serge | 123 | return 0; |
124 | } |
||
125 | |||
1179 | serge | 126 | void r100_pci_gart_fini(struct radeon_device *rdev) |
1117 | serge | 127 | { |
128 | r100_pci_gart_disable(rdev); |
||
1179 | serge | 129 | radeon_gart_table_ram_free(rdev); |
130 | radeon_gart_fini(rdev); |
||
1117 | serge | 131 | } |
132 | |||
133 | |||
134 | /* |
||
135 | * MC |
||
136 | */ |
||
137 | void r100_mc_disable_clients(struct radeon_device *rdev) |
||
138 | { |
||
139 | uint32_t ov0_scale_cntl, crtc_ext_cntl, crtc_gen_cntl, crtc2_gen_cntl; |
||
140 | |||
141 | /* FIXME: is this function correct for rs100,rs200,rs300 ? */ |
||
1128 | serge | 142 | if (r100_gui_wait_for_idle(rdev)) { |
143 | printk(KERN_WARNING "Failed to wait GUI idle while " |
||
144 | "programming pipes. Bad things might happen.\n"); |
||
145 | } |
||
1117 | serge | 146 | |
147 | /* stop display and memory access */ |
||
148 | ov0_scale_cntl = RREG32(RADEON_OV0_SCALE_CNTL); |
||
149 | WREG32(RADEON_OV0_SCALE_CNTL, ov0_scale_cntl & ~RADEON_SCALER_ENABLE); |
||
150 | crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); |
||
151 | WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl | RADEON_CRTC_DISPLAY_DIS); |
||
152 | crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL); |
||
153 | |||
154 | r100_gpu_wait_for_vsync(rdev); |
||
155 | |||
156 | WREG32(RADEON_CRTC_GEN_CNTL, |
||
157 | (crtc_gen_cntl & ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_ICON_EN)) | |
||
158 | RADEON_CRTC_DISP_REQ_EN_B | RADEON_CRTC_EXT_DISP_EN); |
||
159 | |||
160 | if (!(rdev->flags & RADEON_SINGLE_CRTC)) { |
||
161 | crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); |
||
162 | |||
163 | r100_gpu_wait_for_vsync2(rdev); |
||
164 | WREG32(RADEON_CRTC2_GEN_CNTL, |
||
165 | (crtc2_gen_cntl & |
||
166 | ~(RADEON_CRTC2_CUR_EN | RADEON_CRTC2_ICON_EN)) | |
||
167 | RADEON_CRTC2_DISP_REQ_EN_B); |
||
168 | } |
||
169 | |||
170 | udelay(500); |
||
171 | } |
||
172 | |||
173 | void r100_mc_setup(struct radeon_device *rdev) |
||
174 | { |
||
175 | uint32_t tmp; |
||
176 | int r; |
||
177 | |||
1129 | serge | 178 | r = r100_debugfs_mc_info_init(rdev); |
179 | if (r) { |
||
180 | DRM_ERROR("Failed to register debugfs file for R100 MC !\n"); |
||
181 | } |
||
1117 | serge | 182 | /* Write VRAM size in case we are limiting it */ |
1179 | serge | 183 | WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); |
184 | /* Novell bug 204882 for RN50/M6/M7 with 8/16/32MB VRAM, |
||
185 | * if the aperture is 64MB but we have 32MB VRAM |
||
186 | * we report only 32MB VRAM but we have to set MC_FB_LOCATION |
||
187 | * to 64MB, otherwise the gpu accidentially dies */ |
||
188 | tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1; |
||
1117 | serge | 189 | tmp = REG_SET(RADEON_MC_FB_TOP, tmp >> 16); |
190 | tmp |= REG_SET(RADEON_MC_FB_START, rdev->mc.vram_location >> 16); |
||
191 | WREG32(RADEON_MC_FB_LOCATION, tmp); |
||
192 | |||
193 | /* Enable bus mastering */ |
||
194 | tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; |
||
195 | WREG32(RADEON_BUS_CNTL, tmp); |
||
196 | |||
197 | if (rdev->flags & RADEON_IS_AGP) { |
||
1179 | serge | 198 | tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1; |
1117 | serge | 199 | tmp = REG_SET(RADEON_MC_AGP_TOP, tmp >> 16); |
200 | tmp |= REG_SET(RADEON_MC_AGP_START, rdev->mc.gtt_location >> 16); |
||
201 | WREG32(RADEON_MC_AGP_LOCATION, tmp); |
||
202 | WREG32(RADEON_AGP_BASE, rdev->mc.agp_base); |
||
203 | } else { |
||
204 | WREG32(RADEON_MC_AGP_LOCATION, 0x0FFFFFFF); |
||
205 | WREG32(RADEON_AGP_BASE, 0); |
||
206 | } |
||
207 | |||
208 | tmp = RREG32(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL; |
||
209 | tmp |= (7 << 28); |
||
210 | WREG32(RADEON_HOST_PATH_CNTL, tmp | RADEON_HDP_SOFT_RESET | RADEON_HDP_READ_BUFFER_INVALIDATE); |
||
211 | (void)RREG32(RADEON_HOST_PATH_CNTL); |
||
212 | WREG32(RADEON_HOST_PATH_CNTL, tmp); |
||
213 | (void)RREG32(RADEON_HOST_PATH_CNTL); |
||
214 | } |
||
215 | |||
216 | int r100_mc_init(struct radeon_device *rdev) |
||
217 | { |
||
218 | int r; |
||
219 | |||
1129 | serge | 220 | if (r100_debugfs_rbbm_init(rdev)) { |
221 | DRM_ERROR("Failed to register debugfs file for RBBM !\n"); |
||
222 | } |
||
1117 | serge | 223 | |
224 | r100_gpu_init(rdev); |
||
225 | /* Disable gart which also disable out of gart access */ |
||
226 | r100_pci_gart_disable(rdev); |
||
227 | |||
228 | /* Setup GPU memory space */ |
||
229 | rdev->mc.gtt_location = 0xFFFFFFFFUL; |
||
230 | r = radeon_mc_setup(rdev); |
||
231 | if (r) { |
||
232 | return r; |
||
233 | } |
||
234 | |||
235 | r100_mc_disable_clients(rdev); |
||
236 | if (r100_mc_wait_for_idle(rdev)) { |
||
237 | printk(KERN_WARNING "Failed to wait MC idle while |