diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_overlay.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_overlay.c | 72 |
1 files changed, 15 insertions, 57 deletions
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index ebff850a9ab6..495625914e4a 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c | |||
| @@ -209,7 +209,6 @@ static void intel_overlay_unmap_regs(struct intel_overlay *overlay, | |||
| 209 | } | 209 | } |
| 210 | 210 | ||
| 211 | static int intel_overlay_do_wait_request(struct intel_overlay *overlay, | 211 | static int intel_overlay_do_wait_request(struct intel_overlay *overlay, |
| 212 | struct drm_i915_gem_request *request, | ||
| 213 | void (*tail)(struct intel_overlay *)) | 212 | void (*tail)(struct intel_overlay *)) |
| 214 | { | 213 | { |
| 215 | struct drm_device *dev = overlay->dev; | 214 | struct drm_device *dev = overlay->dev; |
| @@ -218,12 +217,10 @@ static int intel_overlay_do_wait_request(struct intel_overlay *overlay, | |||
| 218 | int ret; | 217 | int ret; |
| 219 | 218 | ||
| 220 | BUG_ON(overlay->last_flip_req); | 219 | BUG_ON(overlay->last_flip_req); |
| 221 | ret = i915_add_request(ring, NULL, request); | 220 | ret = i915_add_request(ring, NULL, &overlay->last_flip_req); |
| 222 | if (ret) { | 221 | if (ret) |
| 223 | kfree(request); | 222 | return ret; |
| 224 | return ret; | 223 | |
| 225 | } | ||
| 226 | overlay->last_flip_req = request->seqno; | ||
| 227 | overlay->flip_tail = tail; | 224 | overlay->flip_tail = tail; |
| 228 | ret = i915_wait_seqno(ring, overlay->last_flip_req); | 225 | ret = i915_wait_seqno(ring, overlay->last_flip_req); |
| 229 | if (ret) | 226 | if (ret) |
| @@ -240,7 +237,6 @@ static int intel_overlay_on(struct intel_overlay *overlay) | |||
| 240 | struct drm_device *dev = overlay->dev; | 237 | struct drm_device *dev = overlay->dev; |
| 241 | struct drm_i915_private *dev_priv = dev->dev_private; | 238 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 242 | struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; | 239 | struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; |
| 243 | struct drm_i915_gem_request *request; | ||
| 244 | int ret; | 240 | int ret; |
| 245 | 241 | ||
| 246 | BUG_ON(overlay->active); | 242 | BUG_ON(overlay->active); |
| @@ -248,17 +244,9 @@ static int intel_overlay_on(struct intel_overlay *overlay) | |||
| 248 | 244 | ||
| 249 | WARN_ON(IS_I830(dev) && !(dev_priv->quirks & QUIRK_PIPEA_FORCE)); | 245 | WARN_ON(IS_I830(dev) && !(dev_priv->quirks & QUIRK_PIPEA_FORCE)); |
| 250 | 246 | ||
| 251 | request = kzalloc(sizeof(*request), GFP_KERNEL); | ||
| 252 | if (request == NULL) { | ||
| 253 | ret = -ENOMEM; | ||
| 254 | goto out; | ||
| 255 | } | ||
| 256 | |||
| 257 | ret = intel_ring_begin(ring, 4); | 247 | ret = intel_ring_begin(ring, 4); |
| 258 | if (ret) { | 248 | if (ret) |
| 259 | kfree(request); | 249 | return ret; |
| 260 | goto out; | ||
| 261 | } | ||
| 262 | 250 | ||
| 263 | intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_ON); | 251 | intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_ON); |
| 264 | intel_ring_emit(ring, overlay->flip_addr | OFC_UPDATE); | 252 | intel_ring_emit(ring, overlay->flip_addr | OFC_UPDATE); |
| @@ -266,9 +254,7 @@ static int intel_overlay_on(struct intel_overlay *overlay) | |||
| 266 | intel_ring_emit(ring, MI_NOOP); | 254 | intel_ring_emit(ring, MI_NOOP); |
| 267 | intel_ring_advance(ring); | 255 | intel_ring_advance(ring); |
| 268 | 256 | ||
| 269 | ret = intel_overlay_do_wait_request(overlay, request, NULL); | 257 | return intel_overlay_do_wait_request(overlay, NULL); |
| 270 | out: | ||
| 271 | return ret; | ||
| 272 | } | 258 | } |
| 273 | 259 | ||
| 274 | /* overlay needs to be enabled in OCMD reg */ | 260 | /* overlay needs to be enabled in OCMD reg */ |
| @@ -278,17 +264,12 @@ static int intel_overlay_continue(struct intel_overlay *overlay, | |||
| 278 | struct drm_device *dev = overlay->dev; | 264 | struct drm_device *dev = overlay->dev; |
| 279 | drm_i915_private_t *dev_priv = dev->dev_private; | 265 | drm_i915_private_t *dev_priv = dev->dev_private; |
| 280 | struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; | 266 | struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; |
| 281 | struct drm_i915_gem_request *request; | ||
| 282 | u32 flip_addr = overlay->flip_addr; | 267 | u32 flip_addr = overlay->flip_addr; |
| 283 | u32 tmp; | 268 | u32 tmp; |
| 284 | int ret; | 269 | int ret; |
| 285 | 270 | ||
| 286 | BUG_ON(!overlay->active); | 271 | BUG_ON(!overlay->active); |
| 287 | 272 | ||
| 288 | request = kzalloc(sizeof(*request), GFP_KERNEL); | ||
| 289 | if (request == NULL) | ||
| 290 | return -ENOMEM; | ||
| 291 | |||
| 292 | if (load_polyphase_filter) | 273 | if (load_polyphase_filter) |
| 293 | flip_addr |= OFC_UPDATE; | 274 | flip_addr |= OFC_UPDATE; |
| 294 | 275 | ||
| @@ -298,22 +279,14 @@ static int intel_overlay_continue(struct intel_overlay *overlay, | |||
| 298 | DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp); | 279 | DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp); |
| 299 | 280 | ||
| 300 | ret = intel_ring_begin(ring, 2); | 281 | ret = intel_ring_begin(ring, 2); |
| 301 | if (ret) { | 282 | if (ret) |
| 302 | kfree(request); | ||
| 303 | return ret; | 283 | return ret; |
| 304 | } | 284 | |
| 305 | intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE); | 285 | intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE); |
| 306 | intel_ring_emit(ring, flip_addr); | 286 | intel_ring_emit(ring, flip_addr); |
| 307 | intel_ring_advance(ring); | 287 | intel_ring_advance(ring); |
| 308 | 288 | ||
| 309 | ret = i915_add_request(ring, NULL, request); | 289 | return i915_add_request(ring, NULL, &overlay->last_flip_req); |
| 310 | if (ret) { | ||
| 311 | kfree(request); | ||
| 312 | return ret; | ||
| 313 | } | ||
| 314 | |||
| 315 | overlay->last_flip_req = request->seqno; | ||
| 316 | return 0; | ||
| 317 | } | 290 | } |
| 318 | 291 | ||
| 319 | static void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay) | 292 | static void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay) |
| @@ -349,15 +322,10 @@ static int intel_overlay_off(struct intel_overlay *overlay) | |||
| 349 | struct drm_i915_private *dev_priv = dev->dev_private; | 322 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 350 | struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; | 323 | struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; |
| 351 | u32 flip_addr = overlay->flip_addr; | 324 | u32 flip_addr = overlay->flip_addr; |
| 352 | struct drm_i915_gem_request *request; | ||
| 353 | int ret; | 325 | int ret; |
| 354 | 326 | ||
| 355 | BUG_ON(!overlay->active); | 327 | BUG_ON(!overlay->active); |
| 356 | 328 | ||
| 357 | request = kzalloc(sizeof(*request), GFP_KERNEL); | ||
| 358 | if (request == NULL) | ||
| 359 | return -ENOMEM; | ||
| 360 | |||
| 361 | /* According to intel docs the overlay hw may hang (when switching | 329 | /* According to intel docs the overlay hw may hang (when switching |
| 362 | * off) without loading the filter coeffs. It is however unclear whether | 330 | * off) without loading the filter coeffs. It is however unclear whether |
| 363 | * this applies to the disabling of the overlay or to the switching off | 331 | * this applies to the disabling of the overlay or to the switching off |
| @@ -365,10 +333,9 @@ static int intel_overlay_off(struct intel_overlay *overlay) | |||
| 365 | flip_addr |= OFC_UPDATE; | 333 | flip_addr |= OFC_UPDATE; |
| 366 | 334 | ||
| 367 | ret = intel_ring_begin(ring, 6); | 335 | ret = intel_ring_begin(ring, 6); |
| 368 | if (ret) { | 336 | if (ret) |
| 369 | kfree(request); | ||
| 370 | return ret; | 337 | return ret; |
| 371 | } | 338 | |
| 372 | /* wait for overlay to go idle */ | 339 | /* wait for overlay to go idle */ |
| 373 | intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE); | 340 | intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE); |
| 374 | intel_ring_emit(ring, flip_addr); | 341 | intel_ring_emit(ring, flip_addr); |
| @@ -379,8 +346,7 @@ static int intel_overlay_off(struct intel_overlay *overlay) | |||
| 379 | intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); | 346 | intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); |
| 380 | intel_ring_advance(ring); | 347 | intel_ring_advance(ring); |
| 381 | 348 | ||
| 382 | return intel_overlay_do_wait_request(overlay, request, | 349 | return intel_overlay_do_wait_request(overlay, intel_overlay_off_tail); |
| 383 | intel_overlay_off_tail); | ||
| 384 | } | 350 | } |
| 385 | 351 | ||
| 386 | /* recover from an interruption due to a signal | 352 | /* recover from an interruption due to a signal |
| @@ -425,24 +391,16 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay) | |||
| 425 | return 0; | 391 | return 0; |
| 426 | 392 | ||
| 427 | if (I915_READ(ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT) { | 393 | if (I915_READ(ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT) { |
| 428 | struct drm_i915_gem_request *request; | ||
| 429 | |||
| 430 | /* synchronous slowpath */ | 394 | /* synchronous slowpath */ |
| 431 | request = kzalloc(sizeof(*request), GFP_KERNEL); | ||
| 432 | if (request == NULL) | ||
| 433 | return -ENOMEM; | ||
| 434 | |||
| 435 | ret = intel_ring_begin(ring, 2); | 395 | ret = intel_ring_begin(ring, 2); |
| 436 | if (ret) { | 396 | if (ret) |
| 437 | kfree(request); | ||
| 438 | return ret; | 397 | return ret; |
| 439 | } | ||
| 440 | 398 | ||
| 441 | intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); | 399 | intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); |
| 442 | intel_ring_emit(ring, MI_NOOP); | 400 | intel_ring_emit(ring, MI_NOOP); |
| 443 | intel_ring_advance(ring); | 401 | intel_ring_advance(ring); |
| 444 | 402 | ||
| 445 | ret = intel_overlay_do_wait_request(overlay, request, | 403 | ret = intel_overlay_do_wait_request(overlay, |
| 446 | intel_overlay_release_old_vid_tail); | 404 | intel_overlay_release_old_vid_tail); |
| 447 | if (ret) | 405 | if (ret) |
| 448 | return ret; | 406 | return ret; |
