diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/r420.c')
-rw-r--r-- | drivers/gpu/drm/radeon/r420.c | 301 |
1 files changed, 231 insertions, 70 deletions
diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index 97426a6f370f..49a2fdc57d27 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c | |||
@@ -29,47 +29,13 @@ | |||
29 | #include "drmP.h" | 29 | #include "drmP.h" |
30 | #include "radeon_reg.h" | 30 | #include "radeon_reg.h" |
31 | #include "radeon.h" | 31 | #include "radeon.h" |
32 | #include "atom.h" | ||
33 | #include "r420d.h" | ||
32 | 34 | ||
33 | /* r420,r423,rv410 depends on : */ | ||
34 | void r100_pci_gart_disable(struct radeon_device *rdev); | ||
35 | void r100_hdp_reset(struct radeon_device *rdev); | ||
36 | void r100_mc_setup(struct radeon_device *rdev); | ||
37 | int r100_gui_wait_for_idle(struct radeon_device *rdev); | ||
38 | void r100_mc_disable_clients(struct radeon_device *rdev); | ||
39 | void r300_vram_info(struct radeon_device *rdev); | ||
40 | int r300_mc_wait_for_idle(struct radeon_device *rdev); | ||
41 | int rv370_pcie_gart_enable(struct radeon_device *rdev); | ||
42 | void rv370_pcie_gart_disable(struct radeon_device *rdev); | ||
43 | |||
44 | /* This files gather functions specifics to : | ||
45 | * r420,r423,rv410 | ||
46 | * | ||
47 | * Some of these functions might be used by newer ASICs. | ||
48 | */ | ||
49 | void r420_gpu_init(struct radeon_device *rdev); | ||
50 | int r420_debugfs_pipes_info_init(struct radeon_device *rdev); | ||
51 | |||
52 | |||
53 | /* | ||
54 | * MC | ||
55 | */ | ||
56 | int r420_mc_init(struct radeon_device *rdev) | 35 | int r420_mc_init(struct radeon_device *rdev) |
57 | { | 36 | { |
58 | int r; | 37 | int r; |
59 | 38 | ||
60 | if (r100_debugfs_rbbm_init(rdev)) { | ||
61 | DRM_ERROR("Failed to register debugfs file for RBBM !\n"); | ||
62 | } | ||
63 | if (r420_debugfs_pipes_info_init(rdev)) { | ||
64 | DRM_ERROR("Failed to register debugfs file for pipes !\n"); | ||
65 | } | ||
66 | |||
67 | r420_gpu_init(rdev); | ||
68 | r100_pci_gart_disable(rdev); | ||
69 | if (rdev->flags & RADEON_IS_PCIE) { | ||
70 | rv370_pcie_gart_disable(rdev); | ||
71 | } | ||
72 | |||
73 | /* Setup GPU memory space */ | 39 | /* Setup GPU memory space */ |
74 | rdev->mc.vram_location = 0xFFFFFFFFUL; | 40 | rdev->mc.vram_location = 0xFFFFFFFFUL; |
75 | rdev->mc.gtt_location = 0xFFFFFFFFUL; | 41 | rdev->mc.gtt_location = 0xFFFFFFFFUL; |
@@ -87,33 +53,9 @@ int r420_mc_init(struct radeon_device *rdev) | |||
87 | if (r) { | 53 | if (r) { |
88 | return r; | 54 | return r; |
89 | } | 55 | } |
90 | |||
91 | /* Program GPU memory space */ | ||
92 | r100_mc_disable_clients(rdev); | ||
93 | if (r300_mc_wait_for_idle(rdev)) { | ||
94 | printk(KERN_WARNING "Failed to wait MC idle while " | ||
95 | "programming pipes. Bad things might happen.\n"); | ||
96 | } | ||
97 | r100_mc_setup(rdev); | ||
98 | return 0; | 56 | return 0; |
99 | } | 57 | } |
100 | 58 | ||
101 | void r420_mc_fini(struct radeon_device *rdev) | ||
102 | { | ||
103 | rv370_pcie_gart_disable(rdev); | ||
104 | radeon_gart_table_vram_free(rdev); | ||
105 | radeon_gart_fini(rdev); | ||
106 | } | ||
107 | |||
108 | |||
109 | /* | ||
110 | * Global GPU functions | ||
111 | */ | ||
112 | void r420_errata(struct radeon_device *rdev) | ||
113 | { | ||
114 | rdev->pll_errata = 0; | ||
115 | } | ||
116 | |||
117 | void r420_pipes_init(struct radeon_device *rdev) | 59 | void r420_pipes_init(struct radeon_device *rdev) |
118 | { | 60 | { |
119 | unsigned tmp; | 61 | unsigned tmp; |
@@ -122,6 +64,11 @@ void r420_pipes_init(struct radeon_device *rdev) | |||
122 | 64 | ||
123 | /* GA_ENHANCE workaround TCL deadlock issue */ | 65 | /* GA_ENHANCE workaround TCL deadlock issue */ |
124 | WREG32(0x4274, (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)); | 66 | WREG32(0x4274, (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)); |
67 | /* add idle wait as per freedesktop.org bug 24041 */ | ||
68 | if (r100_gui_wait_for_idle(rdev)) { | ||
69 | printk(KERN_WARNING "Failed to wait GUI idle while " | ||
70 | "programming pipes. Bad things might happen.\n"); | ||
71 | } | ||
125 | /* get max number of pipes */ | 72 | /* get max number of pipes */ |
126 | gb_pipe_select = RREG32(0x402C); | 73 | gb_pipe_select = RREG32(0x402C); |
127 | num_pipes = ((gb_pipe_select >> 12) & 3) + 1; | 74 | num_pipes = ((gb_pipe_select >> 12) & 3) + 1; |
@@ -179,25 +126,239 @@ void r420_pipes_init(struct radeon_device *rdev) | |||
179 | rdev->num_gb_pipes, rdev->num_z_pipes); | 126 | rdev->num_gb_pipes, rdev->num_z_pipes); |
180 | } | 127 | } |
181 | 128 | ||
182 | void r420_gpu_init(struct radeon_device *rdev) | 129 | u32 r420_mc_rreg(struct radeon_device *rdev, u32 reg) |
130 | { | ||
131 | u32 r; | ||
132 | |||
133 | WREG32(R_0001F8_MC_IND_INDEX, S_0001F8_MC_IND_ADDR(reg)); | ||
134 | r = RREG32(R_0001FC_MC_IND_DATA); | ||
135 | return r; | ||
136 | } | ||
137 | |||
138 | void r420_mc_wreg(struct radeon_device *rdev, u32 reg, u32 v) | ||
139 | { | ||
140 | WREG32(R_0001F8_MC_IND_INDEX, S_0001F8_MC_IND_ADDR(reg) | | ||
141 | S_0001F8_MC_IND_WR_EN(1)); | ||
142 | WREG32(R_0001FC_MC_IND_DATA, v); | ||
143 | } | ||
144 | |||
145 | static void r420_debugfs(struct radeon_device *rdev) | ||
146 | { | ||
147 | if (r100_debugfs_rbbm_init(rdev)) { | ||
148 | DRM_ERROR("Failed to register debugfs file for RBBM !\n"); | ||
149 | } | ||
150 | if (r420_debugfs_pipes_info_init(rdev)) { | ||
151 | DRM_ERROR("Failed to register debugfs file for pipes !\n"); | ||
152 | } | ||
153 | } | ||
154 | |||
155 | static void r420_clock_resume(struct radeon_device *rdev) | ||
156 | { | ||
157 | u32 sclk_cntl; | ||
158 | sclk_cntl = RREG32_PLL(R_00000D_SCLK_CNTL); | ||
159 | sclk_cntl |= S_00000D_FORCE_CP(1) | S_00000D_FORCE_VIP(1); | ||
160 | if (rdev->family == CHIP_R420) | ||
161 | sclk_cntl |= S_00000D_FORCE_PX(1) | S_00000D_FORCE_TX(1); | ||
162 | WREG32_PLL(R_00000D_SCLK_CNTL, sclk_cntl); | ||
163 | } | ||
164 | |||
165 | static int r420_startup(struct radeon_device *rdev) | ||
183 | { | 166 | { |
184 | r100_hdp_reset(rdev); | 167 | int r; |
168 | |||
169 | r300_mc_program(rdev); | ||
170 | /* Initialize GART (initialize after TTM so we can allocate | ||
171 | * memory through TTM but finalize after TTM) */ | ||
172 | if (rdev->flags & RADEON_IS_PCIE) { | ||
173 | r = rv370_pcie_gart_enable(rdev); | ||
174 | if (r) | ||
175 | return r; | ||
176 | } | ||
177 | if (rdev->flags & RADEON_IS_PCI) { | ||
178 | r = r100_pci_gart_enable(rdev); | ||
179 | if (r) | ||
180 | return r; | ||
181 | } | ||
185 | r420_pipes_init(rdev); | 182 | r420_pipes_init(rdev); |
186 | if (r300_mc_wait_for_idle(rdev)) { | 183 | /* Enable IRQ */ |
187 | printk(KERN_WARNING "Failed to wait MC idle while " | 184 | rdev->irq.sw_int = true; |
188 | "programming pipes. Bad things might happen.\n"); | 185 | r100_irq_set(rdev); |
186 | /* 1M ring buffer */ | ||
187 | r = r100_cp_init(rdev, 1024 * 1024); | ||
188 | if (r) { | ||
189 | dev_err(rdev->dev, "failled initializing CP (%d).\n", r); | ||
190 | return r; | ||
191 | } | ||
192 | r = r100_wb_init(rdev); | ||
193 | if (r) { | ||
194 | dev_err(rdev->dev, "failled initializing WB (%d).\n", r); | ||
195 | } | ||
196 | r = r100_ib_init(rdev); | ||
197 | if (r) { | ||
198 | dev_err(rdev->dev, "failled initializing IB (%d).\n", r); | ||
199 | return r; | ||
189 | } | 200 | } |
201 | return 0; | ||
190 | } | 202 | } |
191 | 203 | ||
204 | int r420_resume(struct radeon_device *rdev) | ||
205 | { | ||
206 | /* Make sur GART are not working */ | ||
207 | if (rdev->flags & RADEON_IS_PCIE) | ||
208 | rv370_pcie_gart_disable(rdev); | ||
209 | if (rdev->flags & RADEON_IS_PCI) | ||
210 | r100_pci_gart_disable(rdev); | ||
211 | /* Resume clock before doing reset */ | ||
212 | r420_clock_resume(rdev); | ||
213 | /* Reset gpu before posting otherwise ATOM will enter infinite loop */ | ||
214 | if (radeon_gpu_reset(rdev)) { | ||
215 | dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", | ||
216 | RREG32(R_000E40_RBBM_STATUS), | ||
217 | RREG32(R_0007C0_CP_STAT)); | ||
218 | } | ||
219 | /* check if cards are posted or not */ | ||
220 | if (rdev->is_atom_bios) { | ||
221 | atom_asic_init(rdev->mode_info.atom_context); | ||
222 | } else { | ||
223 | radeon_combios_asic_init(rdev->ddev); | ||
224 | } | ||
225 | /* Resume clock after posting */ | ||
226 | r420_clock_resume(rdev); | ||
192 | 227 | ||
193 | /* | 228 | return r420_startup(rdev); |
194 | * r420,r423,rv410 VRAM info | 229 | } |
195 | */ | 230 | |
196 | void r420_vram_info(struct radeon_device *rdev) | 231 | int r420_suspend(struct radeon_device *rdev) |
197 | { | 232 | { |
198 | r300_vram_info(rdev); | 233 | r100_cp_disable(rdev); |
234 | r100_wb_disable(rdev); | ||
235 | r100_irq_disable(rdev); | ||
236 | if (rdev->flags & RADEON_IS_PCIE) | ||
237 | rv370_pcie_gart_disable(rdev); | ||
238 | if (rdev->flags & RADEON_IS_PCI) | ||
239 | r100_pci_gart_disable(rdev); | ||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | void r420_fini(struct radeon_device *rdev) | ||
244 | { | ||
245 | r100_cp_fini(rdev); | ||
246 | r100_wb_fini(rdev); | ||
247 | r100_ib_fini(rdev); | ||
248 | radeon_gem_fini(rdev); | ||
249 | if (rdev->flags & RADEON_IS_PCIE) | ||
250 | rv370_pcie_gart_fini(rdev); | ||
251 | if (rdev->flags & RADEON_IS_PCI) | ||
252 | r100_pci_gart_fini(rdev); | ||
253 | radeon_agp_fini(rdev); | ||
254 | radeon_irq_kms_fini(rdev); | ||
255 | radeon_fence_driver_fini(rdev); | ||
256 | radeon_object_fini(rdev); | ||
257 | if (rdev->is_atom_bios) { | ||
258 | radeon_atombios_fini(rdev); | ||
259 | } else { | ||
260 | radeon_combios_fini(rdev); | ||
261 | } | ||
262 | kfree(rdev->bios); | ||
263 | rdev->bios = NULL; | ||
199 | } | 264 | } |
200 | 265 | ||
266 | int r420_init(struct radeon_device *rdev) | ||
267 | { | ||
268 | int r; | ||
269 | |||
270 | rdev->new_init_path = true; | ||
271 | /* Initialize scratch registers */ | ||
272 | radeon_scratch_init(rdev); | ||
273 | /* Initialize surface registers */ | ||
274 | radeon_surface_init(rdev); | ||
275 | /* TODO: disable VGA need to use VGA request */ | ||
276 | /* BIOS*/ | ||
277 | if (!radeon_get_bios(rdev)) { | ||
278 | if (ASIC_IS_AVIVO(rdev)) | ||
279 | return -EINVAL; | ||
280 | } | ||
281 | if (rdev->is_atom_bios) { | ||
282 | r = radeon_atombios_init(rdev); | ||
283 | if (r) { | ||
284 | return r; | ||
285 | } | ||
286 | } else { | ||
287 | r = radeon_combios_init(rdev); | ||
288 | if (r) { | ||
289 | return r; | ||
290 | } | ||
291 | } | ||
292 | /* Reset gpu before posting otherwise ATOM will enter infinite loop */ | ||
293 | if (radeon_gpu_reset(rdev)) { | ||
294 | dev_warn(rdev->dev, | ||
295 | "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", | ||
296 | RREG32(R_000E40_RBBM_STATUS), | ||
297 | RREG32(R_0007C0_CP_STAT)); | ||
298 | } | ||
299 | /* check if cards are posted or not */ | ||
300 | if (!radeon_card_posted(rdev) && rdev->bios) { | ||
301 | DRM_INFO("GPU not posted. posting now...\n"); | ||
302 | if (rdev->is_atom_bios) { | ||
303 | atom_asic_init(rdev->mode_info.atom_context); | ||
304 | } else { | ||
305 | radeon_combios_asic_init(rdev->ddev); | ||
306 | } | ||
307 | } | ||
308 | /* Initialize clocks */ | ||
309 | radeon_get_clock_info(rdev->ddev); | ||
310 | /* Get vram informations */ | ||
311 | r300_vram_info(rdev); | ||
312 | /* Initialize memory controller (also test AGP) */ | ||
313 | r = r420_mc_init(rdev); | ||
314 | if (r) { | ||
315 | return r; | ||
316 | } | ||
317 | r420_debugfs(rdev); | ||
318 | /* Fence driver */ | ||
319 | r = radeon_fence_driver_init(rdev); | ||
320 | if (r) { | ||
321 | return r; | ||
322 | } | ||
323 | r = radeon_irq_kms_init(rdev); | ||
324 | if (r) { | ||
325 | return r; | ||
326 | } | ||
327 | /* Memory manager */ | ||
328 | r = radeon_object_init(rdev); | ||
329 | if (r) { | ||
330 | return r; | ||
331 | } | ||
332 | if (rdev->flags & RADEON_IS_PCIE) { | ||
333 | r = rv370_pcie_gart_init(rdev); | ||
334 | if (r) | ||
335 | return r; | ||
336 | } | ||
337 | if (rdev->flags & RADEON_IS_PCI) { | ||
338 | r = r100_pci_gart_init(rdev); | ||
339 | if (r) | ||
340 | return r; | ||
341 | } | ||
342 | r300_set_reg_safe(rdev); | ||
343 | rdev->accel_working = true; | ||
344 | r = r420_startup(rdev); | ||
345 | if (r) { | ||
346 | /* Somethings want wront with the accel init stop accel */ | ||
347 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); | ||
348 | r420_suspend(rdev); | ||
349 | r100_cp_fini(rdev); | ||
350 | r100_wb_fini(rdev); | ||
351 | r100_ib_fini(rdev); | ||
352 | if (rdev->flags & RADEON_IS_PCIE) | ||
353 | rv370_pcie_gart_fini(rdev); | ||
354 | if (rdev->flags & RADEON_IS_PCI) | ||
355 | r100_pci_gart_fini(rdev); | ||
356 | radeon_agp_fini(rdev); | ||
357 | radeon_irq_kms_fini(rdev); | ||
358 | rdev->accel_working = false; | ||
359 | } | ||
360 | return 0; | ||
361 | } | ||
201 | 362 | ||
202 | /* | 363 | /* |
203 | * Debugfs info | 364 | * Debugfs info |