diff options
| -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 | ||
