diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/r520.c')
-rw-r--r-- | drivers/gpu/drm/radeon/r520.c | 267 |
1 files changed, 162 insertions, 105 deletions
diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c index 2723486ad380..0bf13fccdaf2 100644 --- a/drivers/gpu/drm/radeon/r520.c +++ b/drivers/gpu/drm/radeon/r520.c | |||
@@ -26,107 +26,13 @@ | |||
26 | * Jerome Glisse | 26 | * Jerome Glisse |
27 | */ | 27 | */ |
28 | #include "drmP.h" | 28 | #include "drmP.h" |
29 | #include "radeon_reg.h" | ||
30 | #include "radeon.h" | 29 | #include "radeon.h" |
30 | #include "atom.h" | ||
31 | #include "r520d.h" | ||
31 | 32 | ||
32 | /* r520,rv530,rv560,rv570,r580 depends on : */ | 33 | /* This files gather functions specifics to: r520,rv530,rv560,rv570,r580 */ |
33 | void r100_hdp_reset(struct radeon_device *rdev); | ||
34 | void r420_pipes_init(struct radeon_device *rdev); | ||
35 | void rs600_mc_disable_clients(struct radeon_device *rdev); | ||
36 | int rv515_debugfs_pipes_info_init(struct radeon_device *rdev); | ||
37 | int rv515_debugfs_ga_info_init(struct radeon_device *rdev); | ||
38 | 34 | ||
39 | /* This files gather functions specifics to: | 35 | static int r520_mc_wait_for_idle(struct radeon_device *rdev) |
40 | * r520,rv530,rv560,rv570,r580 | ||
41 | * | ||
42 | * Some of these functions might be used by newer ASICs. | ||
43 | */ | ||
44 | void r520_gpu_init(struct radeon_device *rdev); | ||
45 | int r520_mc_wait_for_idle(struct radeon_device *rdev); | ||
46 | |||
47 | |||
48 | /* | ||
49 | * MC | ||
50 | */ | ||
51 | int r520_mc_init(struct radeon_device *rdev) | ||
52 | { | ||
53 | uint32_t tmp; | ||
54 | int r; | ||
55 | |||
56 | if (r100_debugfs_rbbm_init(rdev)) { | ||
57 | DRM_ERROR("Failed to register debugfs file for RBBM !\n"); | ||
58 | } | ||
59 | if (rv515_debugfs_pipes_info_init(rdev)) { | ||
60 | DRM_ERROR("Failed to register debugfs file for pipes !\n"); | ||
61 | } | ||
62 | if (rv515_debugfs_ga_info_init(rdev)) { | ||
63 | DRM_ERROR("Failed to register debugfs file for pipes !\n"); | ||
64 | } | ||
65 | |||
66 | r520_gpu_init(rdev); | ||
67 | rv370_pcie_gart_disable(rdev); | ||
68 | |||
69 | /* Setup GPU memory space */ | ||
70 | rdev->mc.vram_location = 0xFFFFFFFFUL; | ||
71 | rdev->mc.gtt_location = 0xFFFFFFFFUL; | ||
72 | if (rdev->flags & RADEON_IS_AGP) { | ||
73 | r = radeon_agp_init(rdev); | ||
74 | if (r) { | ||
75 | printk(KERN_WARNING "[drm] Disabling AGP\n"); | ||
76 | rdev->flags &= ~RADEON_IS_AGP; | ||
77 | rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; | ||
78 | } else { | ||
79 | rdev->mc.gtt_location = rdev->mc.agp_base; | ||
80 | } | ||
81 | } | ||
82 | r = radeon_mc_setup(rdev); | ||
83 | if (r) { | ||
84 | return r; | ||
85 | } | ||
86 | |||
87 | /* Program GPU memory space */ | ||
88 | rs600_mc_disable_clients(rdev); | ||
89 | if (r520_mc_wait_for_idle(rdev)) { | ||
90 | printk(KERN_WARNING "Failed to wait MC idle while " | ||
91 | "programming pipes. Bad things might happen.\n"); | ||
92 | } | ||
93 | /* Write VRAM size in case we are limiting it */ | ||
94 | WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); | ||
95 | tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1; | ||
96 | tmp = REG_SET(R520_MC_FB_TOP, tmp >> 16); | ||
97 | tmp |= REG_SET(R520_MC_FB_START, rdev->mc.vram_location >> 16); | ||
98 | WREG32_MC(R520_MC_FB_LOCATION, tmp); | ||
99 | WREG32(RS690_HDP_FB_LOCATION, rdev->mc.vram_location >> 16); | ||
100 | WREG32(0x310, rdev->mc.vram_location); | ||
101 | if (rdev->flags & RADEON_IS_AGP) { | ||
102 | tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1; | ||
103 | tmp = REG_SET(R520_MC_AGP_TOP, tmp >> 16); | ||
104 | tmp |= REG_SET(R520_MC_AGP_START, rdev->mc.gtt_location >> 16); | ||
105 | WREG32_MC(R520_MC_AGP_LOCATION, tmp); | ||
106 | WREG32_MC(R520_MC_AGP_BASE, rdev->mc.agp_base); | ||
107 | WREG32_MC(R520_MC_AGP_BASE_2, 0); | ||
108 | } else { | ||
109 | WREG32_MC(R520_MC_AGP_LOCATION, 0x0FFFFFFF); | ||
110 | WREG32_MC(R520_MC_AGP_BASE, 0); | ||
111 | WREG32_MC(R520_MC_AGP_BASE_2, 0); | ||
112 | } | ||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | void r520_mc_fini(struct radeon_device *rdev) | ||
117 | { | ||
118 | } | ||
119 | |||
120 | |||
121 | /* | ||
122 | * Global GPU functions | ||
123 | */ | ||
124 | void r520_errata(struct radeon_device *rdev) | ||
125 | { | ||
126 | rdev->pll_errata = 0; | ||
127 | } | ||
128 | |||
129 | int r520_mc_wait_for_idle(struct radeon_device *rdev) | ||
130 | { | 36 | { |
131 | unsigned i; | 37 | unsigned i; |
132 | uint32_t tmp; | 38 | uint32_t tmp; |
@@ -142,7 +48,7 @@ int r520_mc_wait_for_idle(struct radeon_device *rdev) | |||
142 | return -1; | 48 | return -1; |
143 | } | 49 | } |
144 | 50 | ||
145 | void r520_gpu_init(struct radeon_device *rdev) | 51 | static void r520_gpu_init(struct radeon_device *rdev) |
146 | { | 52 | { |
147 | unsigned pipe_select_current, gb_pipe_select, tmp; | 53 | unsigned pipe_select_current, gb_pipe_select, tmp; |
148 | 54 | ||
@@ -185,10 +91,6 @@ void r520_gpu_init(struct radeon_device *rdev) | |||
185 | } | 91 | } |
186 | } | 92 | } |
187 | 93 | ||
188 | |||
189 | /* | ||
190 | * VRAM info | ||
191 | */ | ||
192 | static void r520_vram_get_type(struct radeon_device *rdev) | 94 | static void r520_vram_get_type(struct radeon_device *rdev) |
193 | { | 95 | { |
194 | uint32_t tmp; | 96 | uint32_t tmp; |
@@ -232,13 +134,168 @@ void r520_vram_info(struct radeon_device *rdev) | |||
232 | rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a); | 134 | rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a); |
233 | } | 135 | } |
234 | 136 | ||
235 | void r520_bandwidth_update(struct radeon_device *rdev) | 137 | void r520_mc_program(struct radeon_device *rdev) |
138 | { | ||
139 | struct rv515_mc_save save; | ||
140 | |||
141 | /* Stops all mc clients */ | ||
142 | rv515_mc_stop(rdev, &save); | ||
143 | |||
144 | /* Wait for mc idle */ | ||
145 | if (r520_mc_wait_for_idle(rdev)) | ||
146 | dev_warn(rdev->dev, "Wait MC idle timeout before updating MC.\n"); | ||
147 | /* Write VRAM size in case we are limiting it */ | ||
148 | WREG32(R_0000F8_CONFIG_MEMSIZE, rdev->mc.real_vram_size); | ||
149 | /* Program MC, should be a 32bits limited address space */ | ||
150 | WREG32_MC(R_000004_MC_FB_LOCATION, | ||
151 | S_000004_MC_FB_START(rdev->mc.vram_start >> 16) | | ||
152 | S_000004_MC_FB_TOP(rdev->mc.vram_end >> 16)); | ||
153 | WREG32(R_000134_HDP_FB_LOCATION, | ||
154 | S_000134_HDP_FB_START(rdev->mc.vram_start >> 16)); | ||
155 | if (rdev->flags & RADEON_IS_AGP) { | ||
156 | WREG32_MC(R_000005_MC_AGP_LOCATION, | ||
157 | S_000005_MC_AGP_START(rdev->mc.gtt_start >> 16) | | ||
158 | S_000005_MC_AGP_TOP(rdev->mc.gtt_end >> 16)); | ||
159 | WREG32_MC(R_000006_AGP_BASE, lower_32_bits(rdev->mc.agp_base)); | ||
160 | WREG32_MC(R_000007_AGP_BASE_2, | ||
161 | S_000007_AGP_BASE_ADDR_2(upper_32_bits(rdev->mc.agp_base))); | ||
162 | } else { | ||
163 | WREG32_MC(R_000005_MC_AGP_LOCATION, 0xFFFFFFFF); | ||
164 | WREG32_MC(R_000006_AGP_BASE, 0); | ||
165 | WREG32_MC(R_000007_AGP_BASE_2, 0); | ||
166 | } | ||
167 | |||
168 | rv515_mc_resume(rdev, &save); | ||
169 | } | ||
170 | |||
171 | static int r520_startup(struct radeon_device *rdev) | ||
172 | { | ||
173 | int r; | ||
174 | |||
175 | r520_mc_program(rdev); | ||
176 | /* Resume clock */ | ||
177 | rv515_clock_startup(rdev); | ||
178 | /* Initialize GPU configuration (# pipes, ...) */ | ||
179 | r520_gpu_init(rdev); | ||
180 | /* Initialize GART (initialize after TTM so we can allocate | ||
181 | * memory through TTM but finalize after TTM) */ | ||
182 | if (rdev->flags & RADEON_IS_PCIE) { | ||
183 | r = rv370_pcie_gart_enable(rdev); | ||
184 | if (r) | ||
185 | return r; | ||
186 | } | ||
187 | /* Enable IRQ */ | ||
188 | rdev->irq.sw_int = true; | ||
189 | r100_irq_set(rdev); | ||
190 | /* 1M ring buffer */ | ||
191 | r = r100_cp_init(rdev, 1024 * 1024); | ||
192 | if (r) { | ||
193 | dev_err(rdev->dev, "failled initializing CP (%d).\n", r); | ||
194 | return r; | ||
195 | } | ||
196 | r = r100_wb_init(rdev); | ||
197 | if (r) | ||
198 | dev_err(rdev->dev, "failled initializing WB (%d).\n", r); | ||
199 | r = r100_ib_init(rdev); | ||
200 | if (r) { | ||
201 | dev_err(rdev->dev, "failled initializing IB (%d).\n", r); | ||
202 | return r; | ||
203 | } | ||
204 | return 0; | ||
205 | } | ||
206 | |||
207 | int r520_resume(struct radeon_device *rdev) | ||
236 | { | 208 | { |
237 | rv515_bandwidth_avivo_update(rdev); | 209 | /* Make sur GART are not working */ |
210 | if (rdev->flags & RADEON_IS_PCIE) | ||
211 | rv370_pcie_gart_disable(rdev); | ||
212 | /* Resume clock before doing reset */ | ||
213 | rv515_clock_startup(rdev); | ||
214 | /* Reset gpu before posting otherwise ATOM will enter infinite loop */ | ||
215 | if (radeon_gpu_reset(rdev)) { | ||
216 | dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", | ||
217 | RREG32(R_000E40_RBBM_STATUS), | ||
218 | RREG32(R_0007C0_CP_STAT)); | ||
219 | } | ||
220 | /* post */ | ||
221 | atom_asic_init(rdev->mode_info.atom_context); | ||
222 | /* Resume clock after posting */ | ||
223 | rv515_clock_startup(rdev); | ||
224 | return r520_startup(rdev); | ||
238 | } | 225 | } |
239 | 226 | ||
240 | int r520_init(struct radeon_device *rdev) | 227 | int r520_init(struct radeon_device *rdev) |
241 | { | 228 | { |
229 | int r; | ||
230 | |||
231 | rdev->new_init_path = true; | ||
232 | /* Initialize scratch registers */ | ||
233 | radeon_scratch_init(rdev); | ||
234 | /* Initialize surface registers */ | ||
235 | radeon_surface_init(rdev); | ||
236 | /* TODO: disable VGA need to use VGA request */ | ||
237 | /* BIOS*/ | ||
238 | if (!radeon_get_bios(rdev)) { | ||
239 | if (ASIC_IS_AVIVO(rdev)) | ||
240 | return -EINVAL; | ||
241 | } | ||
242 | if (rdev->is_atom_bios) { | ||
243 | r = radeon_atombios_init(rdev); | ||
244 | if (r) | ||
245 | return r; | ||
246 | } else { | ||
247 | dev_err(rdev->dev, "Expecting atombios for RV515 GPU\n"); | ||
248 | return -EINVAL; | ||
249 | } | ||
250 | /* Reset gpu before posting otherwise ATOM will enter infinite loop */ | ||
251 | if (radeon_gpu_reset(rdev)) { | ||
252 | dev_warn(rdev->dev, | ||
253 | "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", | ||
254 | RREG32(R_000E40_RBBM_STATUS), | ||
255 | RREG32(R_0007C0_CP_STAT)); | ||
256 | } | ||
257 | /* check if cards are posted or not */ | ||
258 | if (!radeon_card_posted(rdev) && rdev->bios) { | ||
259 | DRM_INFO("GPU not posted. posting now...\n"); | ||
260 | atom_asic_init(rdev->mode_info.atom_context); | ||
261 | } | ||
262 | /* Initialize clocks */ | ||
263 | radeon_get_clock_info(rdev->ddev); | ||
264 | /* Get vram informations */ | ||
265 | r520_vram_info(rdev); | ||
266 | /* Initialize memory controller (also test AGP) */ | ||
267 | r = r420_mc_init(rdev); | ||
268 | if (r) | ||
269 | return r; | ||
270 | rv515_debugfs(rdev); | ||
271 | /* Fence driver */ | ||
272 | r = radeon_fence_driver_init(rdev); | ||
273 | if (r) | ||
274 | return r; | ||
275 | r = radeon_irq_kms_init(rdev); | ||
276 | if (r) | ||
277 | return r; | ||
278 | /* Memory manager */ | ||
279 | r = radeon_object_init(rdev); | ||
280 | if (r) | ||
281 | return r; | ||
282 | r = rv370_pcie_gart_init(rdev); | ||
283 | if (r) | ||
284 | return r; | ||
242 | rv515_set_safe_registers(rdev); | 285 | rv515_set_safe_registers(rdev); |
286 | rdev->accel_working = true; | ||
287 | r = r520_startup(rdev); | ||
288 | if (r) { | ||
289 | /* Somethings want wront with the accel init stop accel */ | ||
290 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); | ||
291 | rv515_suspend(rdev); | ||
292 | r100_cp_fini(rdev); | ||
293 | r100_wb_fini(rdev); | ||
294 | r100_ib_fini(rdev); | ||
295 | rv370_pcie_gart_fini(rdev); | ||
296 | radeon_agp_fini(rdev); | ||
297 | radeon_irq_kms_fini(rdev); | ||
298 | rdev->accel_working = false; | ||
299 | } | ||
243 | return 0; | 300 | return 0; |
244 | } | 301 | } |