Rev 1125 | Rev 1128 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1125 | Rev 1126 | ||
---|---|---|---|
1 | /* |
1 | /* |
2 | * Copyright 2008 Advanced Micro Devices, Inc. |
2 | * Copyright 2008 Advanced Micro Devices, Inc. |
3 | * Copyright 2008 Red Hat Inc. |
3 | * Copyright 2008 Red Hat Inc. |
4 | * Copyright 2009 Jerome Glisse. |
4 | * Copyright 2009 Jerome Glisse. |
5 | * |
5 | * |
6 | * Permission is hereby granted, free of charge, to any person obtaining a |
6 | * Permission is hereby granted, free of charge, to any person obtaining a |
7 | * copy of this software and associated documentation files (the "Software"), |
7 | * copy of this software and associated documentation files (the "Software"), |
8 | * to deal in the Software without restriction, including without limitation |
8 | * to deal in the Software without restriction, including without limitation |
9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
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 |
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: |
11 | * Software is furnished to do so, subject to the following conditions: |
12 | * |
12 | * |
13 | * The above copyright notice and this permission notice shall be included in |
13 | * The above copyright notice and this permission notice shall be included in |
14 | * all copies or substantial portions of the Software. |
14 | * all copies or substantial portions of the Software. |
15 | * |
15 | * |
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
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, |
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
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 |
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, |
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 |
21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
22 | * OTHER DEALINGS IN THE SOFTWARE. |
22 | * OTHER DEALINGS IN THE SOFTWARE. |
23 | * |
23 | * |
24 | * Authors: Dave Airlie |
24 | * Authors: Dave Airlie |
25 | * Alex Deucher |
25 | * Alex Deucher |
26 | * Jerome Glisse |
26 | * Jerome Glisse |
27 | */ |
27 | */ |
28 | //#include |
28 | //#include |
29 | 29 | ||
30 | #include |
30 | #include |
31 | //#include |
31 | #include |
32 | #include "radeon_drm.h" |
32 | #include "radeon_drm.h" |
33 | #include "radeon_reg.h" |
33 | #include "radeon_reg.h" |
34 | #include "radeon.h" |
34 | #include "radeon.h" |
35 | #include "radeon_asic.h" |
35 | #include "radeon_asic.h" |
36 | #include "atom.h" |
36 | #include "atom.h" |
37 | 37 | ||
38 | #include |
38 | #include |
39 | 39 | ||
40 | int radeon_dynclks = -1; |
40 | int radeon_dynclks = -1; |
41 | int radeon_r4xx_atom = 0; |
41 | int radeon_r4xx_atom = 0; |
42 | int radeon_agpmode = -1; |
42 | int radeon_agpmode = -1; |
43 | int radeon_gart_size = 512; /* default gart size */ |
43 | int radeon_gart_size = 512; /* default gart size */ |
44 | int radeon_benchmarking = 0; |
44 | int radeon_benchmarking = 0; |
45 | int radeon_connector_table = 0; |
45 | int radeon_connector_table = 0; |
46 | 46 | ||
47 | 47 | ||
48 | /* |
48 | /* |
49 | * Clear GPU surface registers. |
49 | * Clear GPU surface registers. |
50 | */ |
50 | */ |
51 | static void radeon_surface_init(struct radeon_device *rdev) |
51 | static void radeon_surface_init(struct radeon_device *rdev) |
52 | { |
52 | { |
53 | dbgprintf("%s\n",__FUNCTION__); |
53 | dbgprintf("%s\n",__FUNCTION__); |
54 | 54 | ||
55 | /* FIXME: check this out */ |
55 | /* FIXME: check this out */ |
56 | if (rdev->family < CHIP_R600) { |
56 | if (rdev->family < CHIP_R600) { |
57 | int i; |
57 | int i; |
58 | 58 | ||
59 | for (i = 0; i < 8; i++) { |
59 | for (i = 0; i < 8; i++) { |
60 | WREG32(RADEON_SURFACE0_INFO + |
60 | WREG32(RADEON_SURFACE0_INFO + |
61 | i * (RADEON_SURFACE1_INFO - RADEON_SURFACE0_INFO), |
61 | i * (RADEON_SURFACE1_INFO - RADEON_SURFACE0_INFO), |
62 | 0); |
62 | 0); |
63 | } |
63 | } |
64 | } |
64 | } |
65 | } |
65 | } |
66 | 66 | ||
67 | /* |
67 | /* |
68 | * GPU scratch registers helpers function. |
68 | * GPU scratch registers helpers function. |
69 | */ |
69 | */ |
70 | static void radeon_scratch_init(struct radeon_device *rdev) |
70 | static void radeon_scratch_init(struct radeon_device *rdev) |
71 | { |
71 | { |
72 | int i; |
72 | int i; |
73 | 73 | ||
74 | /* FIXME: check this out */ |
74 | /* FIXME: check this out */ |
75 | if (rdev->family < CHIP_R300) { |
75 | if (rdev->family < CHIP_R300) { |
76 | rdev->scratch.num_reg = 5; |
76 | rdev->scratch.num_reg = 5; |
77 | } else { |
77 | } else { |
78 | rdev->scratch.num_reg = 7; |
78 | rdev->scratch.num_reg = 7; |
79 | } |
79 | } |
80 | for (i = 0; i < rdev->scratch.num_reg; i++) { |
80 | for (i = 0; i < rdev->scratch.num_reg; i++) { |
81 | rdev->scratch.free[i] = true; |
81 | rdev->scratch.free[i] = true; |
82 | rdev->scratch.reg[i] = RADEON_SCRATCH_REG0 + (i * 4); |
82 | rdev->scratch.reg[i] = RADEON_SCRATCH_REG0 + (i * 4); |
83 | } |
83 | } |
84 | } |
84 | } |
85 | 85 | ||
86 | int radeon_scratch_get(struct radeon_device *rdev, uint32_t *reg) |
86 | int radeon_scratch_get(struct radeon_device *rdev, uint32_t *reg) |
87 | { |
87 | { |
88 | int i; |
88 | int i; |
89 | 89 | ||
90 | for (i = 0; i < rdev->scratch.num_reg; i++) { |
90 | for (i = 0; i < rdev->scratch.num_reg; i++) { |
91 | if (rdev->scratch.free[i]) { |
91 | if (rdev->scratch.free[i]) { |
92 | rdev->scratch.free[i] = false; |
92 | rdev->scratch.free[i] = false; |
93 | *reg = rdev->scratch.reg[i]; |
93 | *reg = rdev->scratch.reg[i]; |
94 | return 0; |
94 | return 0; |
95 | } |
95 | } |
96 | } |
96 | } |
97 | return -EINVAL; |
97 | return -EINVAL; |
98 | } |
98 | } |
99 | 99 | ||
100 | void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg) |
100 | void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg) |
101 | { |
101 | { |
102 | int i; |
102 | int i; |
103 | 103 | ||
104 | for (i = 0; i < rdev->scratch.num_reg; i++) { |
104 | for (i = 0; i < rdev->scratch.num_reg; i++) { |
105 | if (rdev->scratch.reg[i] == reg) { |
105 | if (rdev->scratch.reg[i] == reg) { |
106 | rdev->scratch.free[i] = true; |
106 | rdev->scratch.free[i] = true; |
107 | return; |
107 | return; |
108 | } |
108 | } |
109 | } |
109 | } |
110 | } |
110 | } |
111 | 111 | ||
112 | /* |
112 | /* |
113 | * MC common functions |
113 | * MC common functions |
114 | */ |
114 | */ |
115 | int radeon_mc_setup(struct radeon_device *rdev) |
115 | int radeon_mc_setup(struct radeon_device *rdev) |
116 | { |
116 | { |
117 | uint32_t tmp; |
117 | uint32_t tmp; |
118 | 118 | ||
119 | /* Some chips have an "issue" with the memory controller, the |
119 | /* Some chips have an "issue" with the memory controller, the |
120 | * location must be aligned to the size. We just align it down, |
120 | * location must be aligned to the size. We just align it down, |
121 | * too bad if we walk over the top of system memory, we don't |
121 | * too bad if we walk over the top of system memory, we don't |
122 | * use DMA without a remapped anyway. |
122 | * use DMA without a remapped anyway. |
123 | * Affected chips are rv280, all r3xx, and all r4xx, but not IGP |
123 | * Affected chips are rv280, all r3xx, and all r4xx, but not IGP |
124 | */ |
124 | */ |
125 | /* FGLRX seems to setup like this, VRAM a 0, then GART. |
125 | /* FGLRX seems to setup like this, VRAM a 0, then GART. |
126 | */ |
126 | */ |
127 | /* |
127 | /* |
128 | * Note: from R6xx the address space is 40bits but here we only |
128 | * Note: from R6xx the address space is 40bits but here we only |
129 | * use 32bits (still have to see a card which would exhaust 4G |
129 | * use 32bits (still have to see a card which would exhaust 4G |
130 | * address space). |
130 | * address space). |
131 | */ |
131 | */ |
132 | if (rdev->mc.vram_location != 0xFFFFFFFFUL) { |
132 | if (rdev->mc.vram_location != 0xFFFFFFFFUL) { |
133 | /* vram location was already setup try to put gtt after |
133 | /* vram location was already setup try to put gtt after |
134 | * if it fits */ |
134 | * if it fits */ |
135 | tmp = rdev->mc.vram_location + rdev->mc.vram_size; |
135 | tmp = rdev->mc.vram_location + rdev->mc.vram_size; |
136 | tmp = (tmp + rdev->mc.gtt_size - 1) & ~(rdev->mc.gtt_size - 1); |
136 | tmp = (tmp + rdev->mc.gtt_size - 1) & ~(rdev->mc.gtt_size - 1); |
137 | if ((0xFFFFFFFFUL - tmp) >= rdev->mc.gtt_size) { |
137 | if ((0xFFFFFFFFUL - tmp) >= rdev->mc.gtt_size) { |
138 | rdev->mc.gtt_location = tmp; |
138 | rdev->mc.gtt_location = tmp; |
139 | } else { |
139 | } else { |
140 | if (rdev->mc.gtt_size >= rdev->mc.vram_location) { |
140 | if (rdev->mc.gtt_size >= rdev->mc.vram_location) { |
141 | printk(KERN_ERR "[drm] GTT too big to fit " |
141 | printk(KERN_ERR "[drm] GTT too big to fit " |
142 | "before or after vram location.\n"); |
142 | "before or after vram location.\n"); |
143 | return -EINVAL; |
143 | return -EINVAL; |
144 | } |
144 | } |
145 | rdev->mc.gtt_location = 0; |
145 | rdev->mc.gtt_location = 0; |
146 | } |
146 | } |
147 | } else if (rdev->mc.gtt_location != 0xFFFFFFFFUL) { |
147 | } else if (rdev->mc.gtt_location != 0xFFFFFFFFUL) { |
148 | /* gtt location was already setup try to put vram before |
148 | /* gtt location was already setup try to put vram before |
149 | * if it fits */ |
149 | * if it fits */ |
150 | if (rdev->mc.vram_size < rdev->mc.gtt_location) { |
150 | if (rdev->mc.vram_size < rdev->mc.gtt_location) { |
151 | rdev->mc.vram_location = 0; |
151 | rdev->mc.vram_location = 0; |
152 | } else { |
152 | } else { |
153 | tmp = rdev->mc.gtt_location + rdev->mc.gtt_size; |
153 | tmp = rdev->mc.gtt_location + rdev->mc.gtt_size; |
154 | tmp += (rdev->mc.vram_size - 1); |
154 | tmp += (rdev->mc.vram_size - 1); |
155 | tmp &= ~(rdev->mc.vram_size - 1); |
155 | tmp &= ~(rdev->mc.vram_size - 1); |
156 | if ((0xFFFFFFFFUL - tmp) >= rdev->mc.vram_size) { |
156 | if ((0xFFFFFFFFUL - tmp) >= rdev->mc.vram_size) { |
157 | rdev->mc.vram_location = tmp; |
157 | rdev->mc.vram_location = tmp; |
158 | } else { |
158 | } else { |
159 | printk(KERN_ERR "[drm] vram too big to fit " |
159 | printk(KERN_ERR "[drm] vram too big to fit " |
160 | "before or after GTT location.\n"); |
160 | "before or after GTT location.\n"); |
161 | return -EINVAL; |
161 | return -EINVAL; |
162 | } |
162 | } |
163 | } |
163 | } |
164 | } else { |
164 | } else { |
165 | rdev->mc.vram_location = 0; |
165 | rdev->mc.vram_location = 0; |
166 | rdev->mc.gtt_location = rdev->mc.vram_size; |
166 | rdev->mc.gtt_location = rdev->mc.vram_size; |
167 | } |
167 | } |
168 | DRM_INFO("radeon: VRAM %uM\n", rdev->mc.vram_size >> 20); |
168 | DRM_INFO("radeon: VRAM %uM\n", rdev->mc.vram_size >> 20); |
169 | DRM_INFO("radeon: VRAM from 0x%08X to 0x%08X\n", |
169 | DRM_INFO("radeon: VRAM from 0x%08X to 0x%08X\n", |
170 | rdev->mc.vram_location, |
170 | rdev->mc.vram_location, |
171 | rdev->mc.vram_location + rdev->mc.vram_size - 1); |
171 | rdev->mc.vram_location + rdev->mc.vram_size - 1); |
172 | DRM_INFO("radeon: GTT %uM\n", rdev->mc.gtt_size >> 20); |
172 | DRM_INFO("radeon: GTT %uM\n", rdev->mc.gtt_size >> 20); |
173 | DRM_INFO("radeon: GTT from 0x%08X to 0x%08X\n", |
173 | DRM_INFO("radeon: GTT from 0x%08X to 0x%08X\n", |
174 | rdev->mc.gtt_location, |
174 | rdev->mc.gtt_location, |
175 | rdev->mc.gtt_location + rdev->mc.gtt_size - 1); |
175 | rdev->mc.gtt_location + rdev->mc.gtt_size - 1); |
176 | return 0; |
176 | return 0; |
177 | } |
177 | } |
178 | 178 | ||
179 | 179 | ||
180 | /* |
180 | /* |
181 | * GPU helpers function. |
181 | * GPU helpers function. |
182 | */ |
182 | */ |
183 | static bool radeon_card_posted(struct radeon_device *rdev) |
183 | static bool radeon_card_posted(struct radeon_device *rdev) |
184 | { |
184 | { |
185 | uint32_t reg; |
185 | uint32_t reg; |
186 | 186 | ||
187 | dbgprintf("%s\n",__FUNCTION__); |
187 | dbgprintf("%s\n",__FUNCTION__); |
188 | 188 | ||
189 | /* first check CRTCs */ |
189 | /* first check CRTCs */ |
190 | if (ASIC_IS_AVIVO(rdev)) { |
190 | if (ASIC_IS_AVIVO(rdev)) { |
191 | reg = RREG32(AVIVO_D1CRTC_CONTROL) | |
191 | reg = RREG32(AVIVO_D1CRTC_CONTROL) | |
192 | RREG32(AVIVO_D2CRTC_CONTROL); |
192 | RREG32(AVIVO_D2CRTC_CONTROL); |
193 | if (reg & AVIVO_CRTC_EN) { |
193 | if (reg & AVIVO_CRTC_EN) { |
194 | return true; |
194 | return true; |
195 | } |
195 | } |
196 | } else { |
196 | } else { |
197 | reg = RREG32(RADEON_CRTC_GEN_CNTL) | |
197 | reg = RREG32(RADEON_CRTC_GEN_CNTL) | |
198 | RREG32(RADEON_CRTC2_GEN_CNTL); |
198 | RREG32(RADEON_CRTC2_GEN_CNTL); |
199 | if (reg & RADEON_CRTC_EN) { |
199 | if (reg & RADEON_CRTC_EN) { |
200 | return true; |
200 | return true; |
201 | } |
201 | } |
202 | } |
202 | } |
203 | 203 | ||
204 | /* then check MEM_SIZE, in case the crtcs are off */ |
204 | /* then check MEM_SIZE, in case the crtcs are off */ |
205 | if (rdev->family >= CHIP_R600) |
205 | if (rdev->family >= CHIP_R600) |
206 | reg = RREG32(R600_CONFIG_MEMSIZE); |
206 | reg = RREG32(R600_CONFIG_MEMSIZE); |
207 | else |
207 | else |
208 | reg = RREG32(RADEON_CONFIG_MEMSIZE); |
208 | reg = RREG32(RADEON_CONFIG_MEMSIZE); |