diff options
Diffstat (limited to 'drivers/gpu/drm/radeon')
-rw-r--r-- | drivers/gpu/drm/radeon/r500_reg.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r600_cs.c | 125 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_reg.h | 1 |
3 files changed, 128 insertions, 1 deletions
diff --git a/drivers/gpu/drm/radeon/r500_reg.h b/drivers/gpu/drm/radeon/r500_reg.h index e1d5e0331e19..868add6e166d 100644 --- a/drivers/gpu/drm/radeon/r500_reg.h +++ b/drivers/gpu/drm/radeon/r500_reg.h | |||
@@ -445,6 +445,8 @@ | |||
445 | #define AVIVO_D1MODE_VBLANK_STATUS 0x6534 | 445 | #define AVIVO_D1MODE_VBLANK_STATUS 0x6534 |
446 | # define AVIVO_VBLANK_ACK (1 << 4) | 446 | # define AVIVO_VBLANK_ACK (1 << 4) |
447 | #define AVIVO_D1MODE_VLINE_START_END 0x6538 | 447 | #define AVIVO_D1MODE_VLINE_START_END 0x6538 |
448 | #define AVIVO_D1MODE_VLINE_STATUS 0x653c | ||
449 | # define AVIVO_D1MODE_VLINE_STAT (1 << 12) | ||
448 | #define AVIVO_DxMODE_INT_MASK 0x6540 | 450 | #define AVIVO_DxMODE_INT_MASK 0x6540 |
449 | # define AVIVO_D1MODE_INT_MASK (1 << 0) | 451 | # define AVIVO_D1MODE_INT_MASK (1 << 0) |
450 | # define AVIVO_D2MODE_INT_MASK (1 << 8) | 452 | # define AVIVO_D2MODE_INT_MASK (1 << 8) |
@@ -502,6 +504,7 @@ | |||
502 | 504 | ||
503 | #define AVIVO_D2MODE_VBLANK_STATUS 0x6d34 | 505 | #define AVIVO_D2MODE_VBLANK_STATUS 0x6d34 |
504 | #define AVIVO_D2MODE_VLINE_START_END 0x6d38 | 506 | #define AVIVO_D2MODE_VLINE_START_END 0x6d38 |
507 | #define AVIVO_D2MODE_VLINE_STATUS 0x6d3c | ||
505 | #define AVIVO_D2MODE_VIEWPORT_START 0x6d80 | 508 | #define AVIVO_D2MODE_VIEWPORT_START 0x6d80 |
506 | #define AVIVO_D2MODE_VIEWPORT_SIZE 0x6d84 | 509 | #define AVIVO_D2MODE_VIEWPORT_SIZE 0x6d84 |
507 | #define AVIVO_D2MODE_EXT_OVERSCAN_LEFT_RIGHT 0x6d88 | 510 | #define AVIVO_D2MODE_EXT_OVERSCAN_LEFT_RIGHT 0x6d88 |
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index dd009da0e7a0..20eb66dbb3a4 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c | |||
@@ -177,13 +177,136 @@ static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p, | |||
177 | return 0; | 177 | return 0; |
178 | } | 178 | } |
179 | 179 | ||
180 | /** | ||
181 | * r600_cs_packet_next_vline() - parse userspace VLINE packet | ||
182 | * @parser: parser structure holding parsing context. | ||
183 | * | ||
184 | * Userspace sends a special sequence for VLINE waits. | ||
185 | * PACKET0 - VLINE_START_END + value | ||
186 | * PACKET3 - WAIT_REG_MEM poll vline status reg | ||
187 | * RELOC (P3) - crtc_id in reloc. | ||
188 | * | ||
189 | * This function parses this and relocates the VLINE START END | ||
190 | * and WAIT_REG_MEM packets to the correct crtc. | ||
191 | * It also detects a switched off crtc and nulls out the | ||
192 | * wait in that case. | ||
193 | */ | ||
194 | static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p) | ||
195 | { | ||
196 | struct drm_mode_object *obj; | ||
197 | struct drm_crtc *crtc; | ||
198 | struct radeon_crtc *radeon_crtc; | ||
199 | struct radeon_cs_packet p3reloc, wait_reg_mem; | ||
200 | int crtc_id; | ||
201 | int r; | ||
202 | uint32_t header, h_idx, reg, wait_reg_mem_info; | ||
203 | volatile uint32_t *ib; | ||
204 | |||
205 | ib = p->ib->ptr; | ||
206 | |||
207 | /* parse the WAIT_REG_MEM */ | ||
208 | r = r600_cs_packet_parse(p, &wait_reg_mem, p->idx); | ||
209 | if (r) | ||
210 | return r; | ||
211 | |||
212 | /* check its a WAIT_REG_MEM */ | ||
213 | if (wait_reg_mem.type != PACKET_TYPE3 || | ||
214 | wait_reg_mem.opcode != PACKET3_WAIT_REG_MEM) { | ||
215 | DRM_ERROR("vline wait missing WAIT_REG_MEM segment\n"); | ||
216 | r = -EINVAL; | ||
217 | return r; | ||
218 | } | ||
219 | |||
220 | wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1); | ||
221 | /* bit 4 is reg (0) or mem (1) */ | ||
222 | if (wait_reg_mem_info & 0x10) { | ||
223 | DRM_ERROR("vline WAIT_REG_MEM waiting on MEM rather than REG\n"); | ||
224 | r = -EINVAL; | ||
225 | return r; | ||
226 | } | ||
227 | /* waiting for value to be equal */ | ||
228 | if ((wait_reg_mem_info & 0x7) != 0x3) { | ||
229 | DRM_ERROR("vline WAIT_REG_MEM function not equal\n"); | ||
230 | r = -EINVAL; | ||
231 | return r; | ||
232 | } | ||
233 | if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != AVIVO_D1MODE_VLINE_STATUS) { | ||
234 | DRM_ERROR("vline WAIT_REG_MEM bad reg\n"); | ||
235 | r = -EINVAL; | ||
236 | return r; | ||
237 | } | ||
238 | |||
239 | if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != AVIVO_D1MODE_VLINE_STAT) { | ||
240 | DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n"); | ||
241 | r = -EINVAL; | ||
242 | return r; | ||
243 | } | ||
244 | |||
245 | /* jump over the NOP */ | ||
246 | r = r600_cs_packet_parse(p, &p3reloc, p->idx + wait_reg_mem.count + 2); | ||
247 | if (r) | ||
248 | return r; | ||
249 | |||
250 | h_idx = p->idx - 2; | ||
251 | p->idx += wait_reg_mem.count + 2; | ||
252 | p->idx += p3reloc.count + 2; | ||
253 | |||
254 | header = radeon_get_ib_value(p, h_idx); | ||
255 | crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1); | ||
256 | reg = header >> 2; | ||
257 | mutex_lock(&p->rdev->ddev->mode_config.mutex); | ||
258 | obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC); | ||
259 | if (!obj) { | ||
260 | DRM_ERROR("cannot find crtc %d\n", crtc_id); | ||
261 | r = -EINVAL; | ||
262 | goto out; | ||
263 | } | ||
264 | crtc = obj_to_crtc(obj); | ||
265 | radeon_crtc = to_radeon_crtc(crtc); | ||
266 | crtc_id = radeon_crtc->crtc_id; | ||
267 | |||
268 | if (!crtc->enabled) { | ||
269 | /* if the CRTC isn't enabled - we need to nop out the WAIT_REG_MEM */ | ||
270 | ib[h_idx + 2] = PACKET2(0); | ||
271 | ib[h_idx + 3] = PACKET2(0); | ||
272 | ib[h_idx + 4] = PACKET2(0); | ||
273 | ib[h_idx + 5] = PACKET2(0); | ||
274 | ib[h_idx + 6] = PACKET2(0); | ||
275 | ib[h_idx + 7] = PACKET2(0); | ||
276 | ib[h_idx + 8] = PACKET2(0); | ||
277 | } else if (crtc_id == 1) { | ||
278 | switch (reg) { | ||
279 | case AVIVO_D1MODE_VLINE_START_END: | ||
280 | header &= ~R600_CP_PACKET0_REG_MASK; | ||
281 | header |= AVIVO_D2MODE_VLINE_START_END >> 2; | ||
282 | break; | ||
283 | default: | ||
284 | DRM_ERROR("unknown crtc reloc\n"); | ||
285 | r = -EINVAL; | ||
286 | goto out; | ||
287 | } | ||
288 | ib[h_idx] = header; | ||
289 | ib[h_idx + 4] = AVIVO_D2MODE_VLINE_STATUS >> 2; | ||
290 | } | ||
291 | out: | ||
292 | mutex_unlock(&p->rdev->ddev->mode_config.mutex); | ||
293 | return r; | ||
294 | } | ||
295 | |||
180 | static int r600_packet0_check(struct radeon_cs_parser *p, | 296 | static int r600_packet0_check(struct radeon_cs_parser *p, |
181 | struct radeon_cs_packet *pkt, | 297 | struct radeon_cs_packet *pkt, |
182 | unsigned idx, unsigned reg) | 298 | unsigned idx, unsigned reg) |
183 | { | 299 | { |
300 | int r; | ||
301 | |||
184 | switch (reg) { | 302 | switch (reg) { |
185 | case AVIVO_D1MODE_VLINE_START_END: | 303 | case AVIVO_D1MODE_VLINE_START_END: |
186 | case AVIVO_D2MODE_VLINE_START_END: | 304 | r = r600_cs_packet_parse_vline(p); |
305 | if (r) { | ||
306 | DRM_ERROR("No reloc for ib[%d]=0x%04X\n", | ||
307 | idx, reg); | ||
308 | return r; | ||
309 | } | ||
187 | break; | 310 | break; |
188 | default: | 311 | default: |
189 | printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n", | 312 | printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n", |
diff --git a/drivers/gpu/drm/radeon/radeon_reg.h b/drivers/gpu/drm/radeon/radeon_reg.h index 21da871a793c..bfa1ab9c93e1 100644 --- a/drivers/gpu/drm/radeon/radeon_reg.h +++ b/drivers/gpu/drm/radeon/radeon_reg.h | |||
@@ -3333,6 +3333,7 @@ | |||
3333 | # define RADEON_CP_PACKET_MAX_DWORDS (1 << 12) | 3333 | # define RADEON_CP_PACKET_MAX_DWORDS (1 << 12) |
3334 | # define RADEON_CP_PACKET0_REG_MASK 0x000007ff | 3334 | # define RADEON_CP_PACKET0_REG_MASK 0x000007ff |
3335 | # define R300_CP_PACKET0_REG_MASK 0x00001fff | 3335 | # define R300_CP_PACKET0_REG_MASK 0x00001fff |
3336 | # define R600_CP_PACKET0_REG_MASK 0x0000ffff | ||
3336 | # define RADEON_CP_PACKET1_REG0_MASK 0x000007ff | 3337 | # define RADEON_CP_PACKET1_REG0_MASK 0x000007ff |
3337 | # define RADEON_CP_PACKET1_REG1_MASK 0x003ff800 | 3338 | # define RADEON_CP_PACKET1_REG1_MASK 0x003ff800 |
3338 | 3339 | ||