aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h2
-rw-r--r--drivers/gpu/drm/i915/intel_overlay.c458
2 files changed, 236 insertions, 224 deletions
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 64a7c87817d7..72f72f52931d 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -291,7 +291,7 @@ extern void intel_setup_overlay(struct drm_device *dev);
291extern void intel_cleanup_overlay(struct drm_device *dev); 291extern void intel_cleanup_overlay(struct drm_device *dev);
292extern int intel_overlay_switch_off(struct intel_overlay *overlay); 292extern int intel_overlay_switch_off(struct intel_overlay *overlay);
293extern int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay, 293extern int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
294 int interruptible); 294 bool interruptible);
295extern int intel_overlay_put_image(struct drm_device *dev, void *data, 295extern int intel_overlay_put_image(struct drm_device *dev, void *data,
296 struct drm_file *file_priv); 296 struct drm_file *file_priv);
297extern int intel_overlay_attrs(struct drm_device *dev, void *data, 297extern int intel_overlay_attrs(struct drm_device *dev, void *data,
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index a203b5c7ff71..5ed1783a69a0 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -176,7 +176,6 @@ struct overlay_registers {
176#define OVERLAY_NONPHYSICAL(dev) (IS_G33(dev) || IS_I965G(dev)) 176#define OVERLAY_NONPHYSICAL(dev) (IS_G33(dev) || IS_I965G(dev))
177#define OVERLAY_EXISTS(dev) (!IS_G4X(dev) && !IS_IRONLAKE(dev) && !IS_GEN6(dev)) 177#define OVERLAY_EXISTS(dev) (!IS_G4X(dev) && !IS_IRONLAKE(dev) && !IS_GEN6(dev))
178 178
179
180static struct overlay_registers *intel_overlay_map_regs_atomic(struct intel_overlay *overlay) 179static struct overlay_registers *intel_overlay_map_regs_atomic(struct intel_overlay *overlay)
181{ 180{
182 drm_i915_private_t *dev_priv = overlay->dev->dev_private; 181 drm_i915_private_t *dev_priv = overlay->dev->dev_private;
@@ -235,7 +234,8 @@ static int intel_overlay_on(struct intel_overlay *overlay)
235 return -ENOMEM; 234 return -ENOMEM;
236 235
237 ret = i915_do_wait_request(dev, 236 ret = i915_do_wait_request(dev,
238 overlay->last_flip_req, 1, &dev_priv->render_ring); 237 overlay->last_flip_req, true,
238 &dev_priv->render_ring);
239 if (ret != 0) 239 if (ret != 0)
240 return ret; 240 return ret;
241 241
@@ -246,7 +246,7 @@ static int intel_overlay_on(struct intel_overlay *overlay)
246 246
247/* overlay needs to be enabled in OCMD reg */ 247/* overlay needs to be enabled in OCMD reg */
248static void intel_overlay_continue(struct intel_overlay *overlay, 248static void intel_overlay_continue(struct intel_overlay *overlay,
249 bool load_polyphase_filter) 249 bool load_polyphase_filter)
250{ 250{
251 struct drm_device *dev = overlay->dev; 251 struct drm_device *dev = overlay->dev;
252 drm_i915_private_t *dev_priv = dev->dev_private; 252 drm_i915_private_t *dev_priv = dev->dev_private;
@@ -275,13 +275,14 @@ static void intel_overlay_continue(struct intel_overlay *overlay,
275static int intel_overlay_wait_flip(struct intel_overlay *overlay) 275static int intel_overlay_wait_flip(struct intel_overlay *overlay)
276{ 276{
277 struct drm_device *dev = overlay->dev; 277 struct drm_device *dev = overlay->dev;
278 drm_i915_private_t *dev_priv = dev->dev_private; 278 drm_i915_private_t *dev_priv = dev->dev_private;
279 int ret; 279 int ret;
280 u32 tmp; 280 u32 tmp;
281 281
282 if (overlay->last_flip_req != 0) { 282 if (overlay->last_flip_req != 0) {
283 ret = i915_do_wait_request(dev, overlay->last_flip_req, 283 ret = i915_do_wait_request(dev,
284 1, &dev_priv->render_ring); 284 overlay->last_flip_req, true,
285 &dev_priv->render_ring);
285 if (ret == 0) { 286 if (ret == 0) {
286 overlay->last_flip_req = 0; 287 overlay->last_flip_req = 0;
287 288
@@ -296,17 +297,18 @@ static int intel_overlay_wait_flip(struct intel_overlay *overlay)
296 overlay->hw_wedged = RELEASE_OLD_VID; 297 overlay->hw_wedged = RELEASE_OLD_VID;
297 298
298 BEGIN_LP_RING(2); 299 BEGIN_LP_RING(2);
299 OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); 300 OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
300 OUT_RING(MI_NOOP); 301 OUT_RING(MI_NOOP);
301 ADVANCE_LP_RING(); 302 ADVANCE_LP_RING();
302 303
303 overlay->last_flip_req = 304 overlay->last_flip_req =
304 i915_add_request(dev, NULL, &dev_priv->render_ring); 305 i915_add_request(dev, NULL, &dev_priv->render_ring);
305 if (overlay->last_flip_req == 0) 306 if (overlay->last_flip_req == 0)
306 return -ENOMEM; 307 return -ENOMEM;
307 308
308 ret = i915_do_wait_request(dev, overlay->last_flip_req, 309 ret = i915_do_wait_request(dev,
309 1, &dev_priv->render_ring); 310 overlay->last_flip_req, true,
311 &dev_priv->render_ring);
310 if (ret != 0) 312 if (ret != 0)
311 return ret; 313 return ret;
312 314
@@ -337,17 +339,18 @@ static int intel_overlay_off(struct intel_overlay *overlay)
337 BEGIN_LP_RING(4); 339 BEGIN_LP_RING(4);
338 OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE); 340 OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
339 OUT_RING(flip_addr); 341 OUT_RING(flip_addr);
340 OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); 342 OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
341 OUT_RING(MI_NOOP); 343 OUT_RING(MI_NOOP);
342 ADVANCE_LP_RING(); 344 ADVANCE_LP_RING();
343 345
344 overlay->last_flip_req = 346 overlay->last_flip_req =
345 i915_add_request(dev, NULL, &dev_priv->render_ring); 347 i915_add_request(dev, NULL, &dev_priv->render_ring);
346 if (overlay->last_flip_req == 0) 348 if (overlay->last_flip_req == 0)
347 return -ENOMEM; 349 return -ENOMEM;
348 350
349 ret = i915_do_wait_request(dev, overlay->last_flip_req, 351 ret = i915_do_wait_request(dev,
350 1, &dev_priv->render_ring); 352 overlay->last_flip_req, true,
353 &dev_priv->render_ring);
351 if (ret != 0) 354 if (ret != 0)
352 return ret; 355 return ret;
353 356
@@ -355,10 +358,10 @@ static int intel_overlay_off(struct intel_overlay *overlay)
355 overlay->hw_wedged = SWITCH_OFF_STAGE_2; 358 overlay->hw_wedged = SWITCH_OFF_STAGE_2;
356 359
357 BEGIN_LP_RING(4); 360 BEGIN_LP_RING(4);
358 OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF); 361 OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
359 OUT_RING(flip_addr); 362 OUT_RING(flip_addr);
360 OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); 363 OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
361 OUT_RING(MI_NOOP); 364 OUT_RING(MI_NOOP);
362 ADVANCE_LP_RING(); 365 ADVANCE_LP_RING();
363 366
364 overlay->last_flip_req = 367 overlay->last_flip_req =
@@ -366,8 +369,9 @@ static int intel_overlay_off(struct intel_overlay *overlay)
366 if (overlay->last_flip_req == 0) 369 if (overlay->last_flip_req == 0)
367 return -ENOMEM; 370 return -ENOMEM;
368 371
369 ret = i915_do_wait_request(dev, overlay->last_flip_req, 372 ret = i915_do_wait_request(dev,
370 1, &dev_priv->render_ring); 373 overlay->last_flip_req, true,
374 &dev_priv->render_ring);
371 if (ret != 0) 375 if (ret != 0)
372 return ret; 376 return ret;
373 377
@@ -396,7 +400,7 @@ static void intel_overlay_off_tail(struct intel_overlay *overlay)
396/* recover from an interruption due to a signal 400/* recover from an interruption due to a signal
397 * We have to be careful not to repeat work forever an make forward progess. */ 401 * We have to be careful not to repeat work forever an make forward progess. */
398int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay, 402int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
399 int interruptible) 403 bool interruptible)
400{ 404{
401 struct drm_device *dev = overlay->dev; 405 struct drm_device *dev = overlay->dev;
402 struct drm_gem_object *obj; 406 struct drm_gem_object *obj;
@@ -415,46 +419,47 @@ int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
415 } 419 }
416 420
417 ret = i915_do_wait_request(dev, overlay->last_flip_req, 421 ret = i915_do_wait_request(dev, overlay->last_flip_req,
418 interruptible, &dev_priv->render_ring); 422 interruptible, &dev_priv->render_ring);
419 if (ret != 0) 423 if (ret != 0)
420 return ret; 424 return ret;
421 425
422 switch (overlay->hw_wedged) { 426 switch (overlay->hw_wedged) {
423 case RELEASE_OLD_VID: 427 case RELEASE_OLD_VID:
424 obj = &overlay->old_vid_bo->base; 428 obj = &overlay->old_vid_bo->base;
425 i915_gem_object_unpin(obj); 429 i915_gem_object_unpin(obj);
426 drm_gem_object_unreference(obj); 430 drm_gem_object_unreference(obj);
427 overlay->old_vid_bo = NULL; 431 overlay->old_vid_bo = NULL;
428 break; 432 break;
429 case SWITCH_OFF_STAGE_1: 433 case SWITCH_OFF_STAGE_1:
430 flip_addr = overlay->flip_addr; 434 flip_addr = overlay->flip_addr;
431 flip_addr |= OFC_UPDATE; 435 flip_addr |= OFC_UPDATE;
432
433 overlay->hw_wedged = SWITCH_OFF_STAGE_2;
434
435 BEGIN_LP_RING(4);
436 OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
437 OUT_RING(flip_addr);
438 OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
439 OUT_RING(MI_NOOP);
440 ADVANCE_LP_RING();
441
442 overlay->last_flip_req =
443 i915_add_request(dev, NULL,
444 &dev_priv->render_ring);
445 if (overlay->last_flip_req == 0)
446 return -ENOMEM;
447
448 ret = i915_do_wait_request(dev, overlay->last_flip_req,
449 interruptible, &dev_priv->render_ring);
450 if (ret != 0)
451 return ret;
452 436
453 case SWITCH_OFF_STAGE_2: 437 overlay->hw_wedged = SWITCH_OFF_STAGE_2;
454 intel_overlay_off_tail(overlay); 438
455 break; 439 BEGIN_LP_RING(4);
456 default: 440 OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
457 BUG_ON(overlay->hw_wedged != NEEDS_WAIT_FOR_FLIP); 441 OUT_RING(flip_addr);
442 OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
443 OUT_RING(MI_NOOP);
444 ADVANCE_LP_RING();
445
446 overlay->last_flip_req =
447 i915_add_request(dev, NULL,
448 &dev_priv->render_ring);
449 if (overlay->last_flip_req == 0)
450 return -ENOMEM;
451
452 ret = i915_do_wait_request(dev, overlay->last_flip_req,
453 interruptible,
454 &dev_priv->render_ring);
455 if (ret != 0)
456 return ret;
457
458 case SWITCH_OFF_STAGE_2:
459 intel_overlay_off_tail(overlay);
460 break;
461 default:
462 BUG_ON(overlay->hw_wedged != NEEDS_WAIT_FOR_FLIP);
458 } 463 }
459 464
460 overlay->hw_wedged = 0; 465 overlay->hw_wedged = 0;
@@ -507,50 +512,50 @@ struct put_image_params {
507static int packed_depth_bytes(u32 format) 512static int packed_depth_bytes(u32 format)
508{ 513{
509 switch (format & I915_OVERLAY_DEPTH_MASK) { 514 switch (format & I915_OVERLAY_DEPTH_MASK) {
510 case I915_OVERLAY_YUV422: 515 case I915_OVERLAY_YUV422:
511 return 4; 516 return 4;
512 case I915_OVERLAY_YUV411: 517 case I915_OVERLAY_YUV411:
513 /* return 6; not implemented */ 518 /* return 6; not implemented */
514 default: 519 default:
515 return -EINVAL; 520 return -EINVAL;
516 } 521 }
517} 522}
518 523
519static int packed_width_bytes(u32 format, short width) 524static int packed_width_bytes(u32 format, short width)
520{ 525{
521 switch (format & I915_OVERLAY_DEPTH_MASK) { 526 switch (format & I915_OVERLAY_DEPTH_MASK) {
522 case I915_OVERLAY_YUV422: 527 case I915_OVERLAY_YUV422:
523 return width << 1; 528 return width << 1;
524 default: 529 default:
525 return -EINVAL; 530 return -EINVAL;
526 } 531 }
527} 532}
528 533
529static int uv_hsubsampling(u32 format) 534static int uv_hsubsampling(u32 format)
530{ 535{
531 switch (format & I915_OVERLAY_DEPTH_MASK) { 536 switch (format & I915_OVERLAY_DEPTH_MASK) {
532 case I915_OVERLAY_YUV422: 537 case I915_OVERLAY_YUV422:
533 case I915_OVERLAY_YUV420: 538 case I915_OVERLAY_YUV420:
534 return 2; 539 return 2;
535 case I915_OVERLAY_YUV411: 540 case I915_OVERLAY_YUV411:
536 case I915_OVERLAY_YUV410: 541 case I915_OVERLAY_YUV410:
537 return 4; 542 return 4;
538 default: 543 default:
539 return -EINVAL; 544 return -EINVAL;
540 } 545 }
541} 546}
542 547
543static int uv_vsubsampling(u32 format) 548static int uv_vsubsampling(u32 format)
544{ 549{
545 switch (format & I915_OVERLAY_DEPTH_MASK) { 550 switch (format & I915_OVERLAY_DEPTH_MASK) {
546 case I915_OVERLAY_YUV420: 551 case I915_OVERLAY_YUV420:
547 case I915_OVERLAY_YUV410: 552 case I915_OVERLAY_YUV410:
548 return 2; 553 return 2;
549 case I915_OVERLAY_YUV422: 554 case I915_OVERLAY_YUV422:
550 case I915_OVERLAY_YUV411: 555 case I915_OVERLAY_YUV411:
551 return 1; 556 return 1;
552 default: 557 default:
553 return -EINVAL; 558 return -EINVAL;
554 } 559 }
555} 560}
556 561
@@ -588,7 +593,9 @@ static const u16 y_static_hcoeffs[N_HORIZ_Y_TAPS * N_PHASES] = {
588 0x3020, 0xb340, 0x1fb8, 0x34a0, 0xb060, 593 0x3020, 0xb340, 0x1fb8, 0x34a0, 0xb060,
589 0x3020, 0xb240, 0x1fe0, 0x32e0, 0xb040, 594 0x3020, 0xb240, 0x1fe0, 0x32e0, 0xb040,
590 0x3020, 0xb140, 0x1ff8, 0x3160, 0xb020, 595 0x3020, 0xb140, 0x1ff8, 0x3160, 0xb020,
591 0xb000, 0x3000, 0x0800, 0x3000, 0xb000}; 596 0xb000, 0x3000, 0x0800, 0x3000, 0xb000
597};
598
592static const u16 uv_static_hcoeffs[N_HORIZ_UV_TAPS * N_PHASES] = { 599static const u16 uv_static_hcoeffs[N_HORIZ_UV_TAPS * N_PHASES] = {
593 0x3000, 0x1800, 0x1800, 0xb000, 0x18d0, 0x2e60, 600 0x3000, 0x1800, 0x1800, 0xb000, 0x18d0, 0x2e60,
594 0xb000, 0x1990, 0x2ce0, 0xb020, 0x1a68, 0x2b40, 601 0xb000, 0x1990, 0x2ce0, 0xb020, 0x1a68, 0x2b40,
@@ -598,7 +605,8 @@ static const u16 uv_static_hcoeffs[N_HORIZ_UV_TAPS * N_PHASES] = {
598 0xb100, 0x1eb8, 0x3620, 0xb100, 0x1f18, 0x34a0, 605 0xb100, 0x1eb8, 0x3620, 0xb100, 0x1f18, 0x34a0,
599 0xb100, 0x1f68, 0x3360, 0xb0e0, 0x1fa8, 0x3240, 606 0xb100, 0x1f68, 0x3360, 0xb0e0, 0x1fa8, 0x3240,
600 0xb0c0, 0x1fe0, 0x3140, 0xb060, 0x1ff0, 0x30a0, 607 0xb0c0, 0x1fe0, 0x3140, 0xb060, 0x1ff0, 0x30a0,
601 0x3000, 0x0800, 0x3000}; 608 0x3000, 0x0800, 0x3000
609};
602 610
603static void update_polyphase_filter(struct overlay_registers *regs) 611static void update_polyphase_filter(struct overlay_registers *regs)
604{ 612{
@@ -631,29 +639,31 @@ static bool update_scaling_factors(struct intel_overlay *overlay,
631 yscale = 1 << FP_SHIFT; 639 yscale = 1 << FP_SHIFT;
632 640
633 /*if (params->format & I915_OVERLAY_YUV_PLANAR) {*/ 641 /*if (params->format & I915_OVERLAY_YUV_PLANAR) {*/
634 xscale_UV = xscale/uv_hscale; 642 xscale_UV = xscale/uv_hscale;
635 yscale_UV = yscale/uv_vscale; 643 yscale_UV = yscale/uv_vscale;
636 /* make the Y scale to UV scale ratio an exact multiply */ 644 /* make the Y scale to UV scale ratio an exact multiply */
637 xscale = xscale_UV * uv_hscale; 645 xscale = xscale_UV * uv_hscale;
638 yscale = yscale_UV * uv_vscale; 646 yscale = yscale_UV * uv_vscale;
639 /*} else { 647 /*} else {
640 xscale_UV = 0; 648 xscale_UV = 0;
641 yscale_UV = 0; 649 yscale_UV = 0;
642 }*/ 650 }*/
643 651
644 if (xscale != overlay->old_xscale || yscale != overlay->old_yscale) 652 if (xscale != overlay->old_xscale || yscale != overlay->old_yscale)
645 scale_changed = true; 653 scale_changed = true;
646 overlay->old_xscale = xscale; 654 overlay->old_xscale = xscale;
647 overlay->old_yscale = yscale; 655 overlay->old_yscale = yscale;
648 656
649 regs->YRGBSCALE = ((yscale & FRACT_MASK) << 20) 657 regs->YRGBSCALE = (((yscale & FRACT_MASK) << 20) |
650 | ((xscale >> FP_SHIFT) << 16) 658 ((xscale >> FP_SHIFT) << 16) |
651 | ((xscale & FRACT_MASK) << 3); 659 ((xscale & FRACT_MASK) << 3));
652 regs->UVSCALE = ((yscale_UV & FRACT_MASK) << 20) 660
653 | ((xscale_UV >> FP_SHIFT) << 16) 661 regs->UVSCALE = (((yscale_UV & FRACT_MASK) << 20) |
654 | ((xscale_UV & FRACT_MASK) << 3); 662 ((xscale_UV >> FP_SHIFT) << 16) |
655 regs->UVSCALEV = ((yscale >> FP_SHIFT) << 16) 663 ((xscale_UV & FRACT_MASK) << 3));
656 | ((yscale_UV >> FP_SHIFT) << 0); 664
665 regs->UVSCALEV = ((((yscale >> FP_SHIFT) << 16) |
666 ((yscale_UV >> FP_SHIFT) << 0)));
657 667
658 if (scale_changed) 668 if (scale_changed)
659 update_polyphase_filter(regs); 669 update_polyphase_filter(regs);
@@ -666,21 +676,21 @@ static void update_colorkey(struct intel_overlay *overlay,
666{ 676{
667 u32 key = overlay->color_key; 677 u32 key = overlay->color_key;
668 switch (overlay->crtc->base.fb->bits_per_pixel) { 678 switch (overlay->crtc->base.fb->bits_per_pixel) {
669 case 8: 679 case 8:
670 regs->DCLRKV = 0; 680 regs->DCLRKV = 0;
671 regs->DCLRKM = CLK_RGB8I_MASK | DST_KEY_ENABLE; 681 regs->DCLRKM = CLK_RGB8I_MASK | DST_KEY_ENABLE;
672 case 16: 682 case 16:
673 if (overlay->crtc->base.fb->depth == 15) { 683 if (overlay->crtc->base.fb->depth == 15) {
674 regs->DCLRKV = RGB15_TO_COLORKEY(key); 684 regs->DCLRKV = RGB15_TO_COLORKEY(key);
675 regs->DCLRKM = CLK_RGB15_MASK | DST_KEY_ENABLE; 685 regs->DCLRKM = CLK_RGB15_MASK | DST_KEY_ENABLE;
676 } else { 686 } else {
677 regs->DCLRKV = RGB16_TO_COLORKEY(key); 687 regs->DCLRKV = RGB16_TO_COLORKEY(key);
678 regs->DCLRKM = CLK_RGB16_MASK | DST_KEY_ENABLE; 688 regs->DCLRKM = CLK_RGB16_MASK | DST_KEY_ENABLE;
679 } 689 }
680 case 24: 690 case 24:
681 case 32: 691 case 32:
682 regs->DCLRKV = key; 692 regs->DCLRKV = key;
683 regs->DCLRKM = CLK_RGB24_MASK | DST_KEY_ENABLE; 693 regs->DCLRKM = CLK_RGB24_MASK | DST_KEY_ENABLE;
684 } 694 }
685} 695}
686 696
@@ -690,39 +700,39 @@ static u32 overlay_cmd_reg(struct put_image_params *params)
690 700
691 if (params->format & I915_OVERLAY_YUV_PLANAR) { 701 if (params->format & I915_OVERLAY_YUV_PLANAR) {
692 switch (params->format & I915_OVERLAY_DEPTH_MASK) { 702 switch (params->format & I915_OVERLAY_DEPTH_MASK) {
693 case I915_OVERLAY_YUV422: 703 case I915_OVERLAY_YUV422:
694 cmd |= OCMD_YUV_422_PLANAR; 704 cmd |= OCMD_YUV_422_PLANAR;
695 break; 705 break;
696 case I915_OVERLAY_YUV420: 706 case I915_OVERLAY_YUV420:
697 cmd |= OCMD_YUV_420_PLANAR; 707 cmd |= OCMD_YUV_420_PLANAR;
698 break; 708 break;
699 case I915_OVERLAY_YUV411: 709 case I915_OVERLAY_YUV411:
700 case I915_OVERLAY_YUV410: 710 case I915_OVERLAY_YUV410:
701 cmd |= OCMD_YUV_410_PLANAR; 711 cmd |= OCMD_YUV_410_PLANAR;
702 break; 712 break;
703 } 713 }
704 } else { /* YUV packed */ 714 } else { /* YUV packed */
705 switch (params->format & I915_OVERLAY_DEPTH_MASK) { 715 switch (params->format & I915_OVERLAY_DEPTH_MASK) {
706 case I915_OVERLAY_YUV422: 716 case I915_OVERLAY_YUV422:
707 cmd |= OCMD_YUV_422_PACKED; 717 cmd |= OCMD_YUV_422_PACKED;
708 break; 718 break;
709 case I915_OVERLAY_YUV411: 719 case I915_OVERLAY_YUV411:
710 cmd |= OCMD_YUV_411_PACKED; 720 cmd |= OCMD_YUV_411_PACKED;
711 break; 721 break;
712 } 722 }
713 723
714 switch (params->format & I915_OVERLAY_SWAP_MASK) { 724 switch (params->format & I915_OVERLAY_SWAP_MASK) {
715 case I915_OVERLAY_NO_SWAP: 725 case I915_OVERLAY_NO_SWAP:
716 break; 726 break;
717 case I915_OVERLAY_UV_SWAP: 727 case I915_OVERLAY_UV_SWAP:
718 cmd |= OCMD_UV_SWAP; 728 cmd |= OCMD_UV_SWAP;
719 break; 729 break;
720 case I915_OVERLAY_Y_SWAP: 730 case I915_OVERLAY_Y_SWAP:
721 cmd |= OCMD_Y_SWAP; 731 cmd |= OCMD_Y_SWAP;
722 break; 732 break;
723 case I915_OVERLAY_Y_AND_UV_SWAP: 733 case I915_OVERLAY_Y_AND_UV_SWAP:
724 cmd |= OCMD_Y_AND_UV_SWAP; 734 cmd |= OCMD_Y_AND_UV_SWAP;
725 break; 735 break;
726 } 736 }
727 } 737 }
728 738
@@ -789,7 +799,7 @@ int intel_overlay_do_put_image(struct intel_overlay *overlay,
789 799
790 regs->SWIDTH = params->src_w; 800 regs->SWIDTH = params->src_w;
791 regs->SWIDTHSW = calc_swidthsw(overlay->dev, 801 regs->SWIDTHSW = calc_swidthsw(overlay->dev,
792 params->offset_Y, tmp_width); 802 params->offset_Y, tmp_width);
793 regs->SHEIGHT = params->src_h; 803 regs->SHEIGHT = params->src_h;
794 regs->OBUF_0Y = bo_priv->gtt_offset + params-> offset_Y; 804 regs->OBUF_0Y = bo_priv->gtt_offset + params-> offset_Y;
795 regs->OSTRIDE = params->stride_Y; 805 regs->OSTRIDE = params->stride_Y;
@@ -800,9 +810,9 @@ int intel_overlay_do_put_image(struct intel_overlay *overlay,
800 u32 tmp_U, tmp_V; 810 u32 tmp_U, tmp_V;
801 regs->SWIDTH |= (params->src_w/uv_hscale) << 16; 811 regs->SWIDTH |= (params->src_w/uv_hscale) << 16;
802 tmp_U = calc_swidthsw(overlay->dev, params->offset_U, 812 tmp_U = calc_swidthsw(overlay->dev, params->offset_U,
803 params->src_w/uv_hscale); 813 params->src_w/uv_hscale);
804 tmp_V = calc_swidthsw(overlay->dev, params->offset_V, 814 tmp_V = calc_swidthsw(overlay->dev, params->offset_V,
805 params->src_w/uv_hscale); 815 params->src_w/uv_hscale);
806 regs->SWIDTHSW |= max_t(u32, tmp_U, tmp_V) << 16; 816 regs->SWIDTHSW |= max_t(u32, tmp_U, tmp_V) << 16;
807 regs->SHEIGHT |= (params->src_h/uv_vscale) << 16; 817 regs->SHEIGHT |= (params->src_h/uv_vscale) << 16;
808 regs->OBUF_0U = bo_priv->gtt_offset + params->offset_U; 818 regs->OBUF_0U = bo_priv->gtt_offset + params->offset_U;
@@ -868,7 +878,7 @@ int intel_overlay_switch_off(struct intel_overlay *overlay)
868static int check_overlay_possible_on_crtc(struct intel_overlay *overlay, 878static int check_overlay_possible_on_crtc(struct intel_overlay *overlay,
869 struct intel_crtc *crtc) 879 struct intel_crtc *crtc)
870{ 880{
871 drm_i915_private_t *dev_priv = overlay->dev->dev_private; 881 drm_i915_private_t *dev_priv = overlay->dev->dev_private;
872 u32 pipeconf; 882 u32 pipeconf;
873 int pipeconf_reg = (crtc->pipe == 0) ? PIPEACONF : PIPEBCONF; 883 int pipeconf_reg = (crtc->pipe == 0) ? PIPEACONF : PIPEBCONF;
874 884
@@ -887,7 +897,7 @@ static int check_overlay_possible_on_crtc(struct intel_overlay *overlay,
887static void update_pfit_vscale_ratio(struct intel_overlay *overlay) 897static void update_pfit_vscale_ratio(struct intel_overlay *overlay)
888{ 898{
889 struct drm_device *dev = overlay->dev; 899 struct drm_device *dev = overlay->dev;
890 drm_i915_private_t *dev_priv = dev->dev_private; 900 drm_i915_private_t *dev_priv = dev->dev_private;
891 u32 ratio; 901 u32 ratio;
892 u32 pfit_control = I915_READ(PFIT_CONTROL); 902 u32 pfit_control = I915_READ(PFIT_CONTROL);
893 903
@@ -911,12 +921,10 @@ static int check_overlay_dst(struct intel_overlay *overlay,
911{ 921{
912 struct drm_display_mode *mode = &overlay->crtc->base.mode; 922 struct drm_display_mode *mode = &overlay->crtc->base.mode;
913 923
914 if ((rec->dst_x < mode->crtc_hdisplay) 924 if (rec->dst_x < mode->crtc_hdisplay &&
915 && (rec->dst_x + rec->dst_width 925 rec->dst_x + rec->dst_width <= mode->crtc_hdisplay &&
916 <= mode->crtc_hdisplay) 926 rec->dst_y < mode->crtc_vdisplay &&
917 && (rec->dst_y < mode->crtc_vdisplay) 927 rec->dst_y + rec->dst_height <= mode->crtc_vdisplay)
918 && (rec->dst_y + rec->dst_height
919 <= mode->crtc_vdisplay))
920 return 0; 928 return 0;
921 else 929 else
922 return -EINVAL; 930 return -EINVAL;
@@ -949,45 +957,45 @@ static int check_overlay_src(struct drm_device *dev,
949 957
950 /* check src dimensions */ 958 /* check src dimensions */
951 if (IS_845G(dev) || IS_I830(dev)) { 959 if (IS_845G(dev) || IS_I830(dev)) {
952 if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY 960 if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY ||
953 || rec->src_width > IMAGE_MAX_WIDTH_LEGACY) 961 rec->src_width > IMAGE_MAX_WIDTH_LEGACY)
954 return -EINVAL; 962 return -EINVAL;
955 } else { 963 } else {
956 if (rec->src_height > IMAGE_MAX_HEIGHT 964 if (rec->src_height > IMAGE_MAX_HEIGHT ||
957 || rec->src_width > IMAGE_MAX_WIDTH) 965 rec->src_width > IMAGE_MAX_WIDTH)
958 return -EINVAL; 966 return -EINVAL;
959 } 967 }
960 /* better safe than sorry, use 4 as the maximal subsampling ratio */ 968 /* better safe than sorry, use 4 as the maximal subsampling ratio */
961 if (rec->src_height < N_VERT_Y_TAPS*4 969 if (rec->src_height < N_VERT_Y_TAPS*4 ||
962 || rec->src_width < N_HORIZ_Y_TAPS*4) 970 rec->src_width < N_HORIZ_Y_TAPS*4)
963 return -EINVAL; 971 return -EINVAL;
964 972
965 /* check alignment constraints */ 973 /* check alignment constraints */
966 switch (rec->flags & I915_OVERLAY_TYPE_MASK) { 974 switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
967 case I915_OVERLAY_RGB: 975 case I915_OVERLAY_RGB:
968 /* not implemented */ 976 /* not implemented */
977 return -EINVAL;
978 case I915_OVERLAY_YUV_PACKED:
979 depth = packed_depth_bytes(rec->flags);
980 if (uv_vscale != 1)
969 return -EINVAL; 981 return -EINVAL;
970 case I915_OVERLAY_YUV_PACKED: 982 if (depth < 0)
971 depth = packed_depth_bytes(rec->flags); 983 return depth;
972 if (uv_vscale != 1) 984 /* ignore UV planes */
973 return -EINVAL; 985 rec->stride_UV = 0;
974 if (depth < 0) 986 rec->offset_U = 0;
975 return depth; 987 rec->offset_V = 0;
976 /* ignore UV planes */ 988 /* check pixel alignment */
977 rec->stride_UV = 0; 989 if (rec->offset_Y % depth)
978 rec->offset_U = 0; 990 return -EINVAL;
979 rec->offset_V = 0; 991 break;
980 /* check pixel alignment */ 992 case I915_OVERLAY_YUV_PLANAR:
981 if (rec->offset_Y % depth) 993 if (uv_vscale < 0 || uv_hscale < 0)
982 return -EINVAL;
983 break;
984 case I915_OVERLAY_YUV_PLANAR:
985 if (uv_vscale < 0 || uv_hscale < 0)
986 return -EINVAL;
987 /* no offset restrictions for planar formats */
988 break;
989 default:
990 return -EINVAL; 994 return -EINVAL;
995 /* no offset restrictions for planar formats */
996 break;
997 default:
998 return -EINVAL;
991 } 999 }
992 1000
993 if (rec->src_width % uv_hscale) 1001 if (rec->src_width % uv_hscale)
@@ -1011,32 +1019,32 @@ static int check_overlay_src(struct drm_device *dev,
1011 1019
1012 /* check buffer dimensions */ 1020 /* check buffer dimensions */
1013 switch (rec->flags & I915_OVERLAY_TYPE_MASK) { 1021 switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
1014 case I915_OVERLAY_RGB: 1022 case I915_OVERLAY_RGB:
1015 case I915_OVERLAY_YUV_PACKED: 1023 case I915_OVERLAY_YUV_PACKED:
1016 /* always 4 Y values per depth pixels */ 1024 /* always 4 Y values per depth pixels */
1017 if (packed_width_bytes(rec->flags, rec->src_width) 1025 if (packed_width_bytes(rec->flags, rec->src_width) > rec->stride_Y)
1018 > rec->stride_Y) 1026 return -EINVAL;
1019 return -EINVAL; 1027
1020 1028 tmp = rec->stride_Y*rec->src_height;
1021 tmp = rec->stride_Y*rec->src_height; 1029 if (rec->offset_Y + tmp > new_bo->size)
1022 if (rec->offset_Y + tmp > new_bo->size) 1030 return -EINVAL;
1023 return -EINVAL; 1031 break;
1024 break; 1032
1025 case I915_OVERLAY_YUV_PLANAR: 1033 case I915_OVERLAY_YUV_PLANAR:
1026 if (rec->src_width > rec->stride_Y) 1034 if (rec->src_width > rec->stride_Y)
1027 return -EINVAL; 1035 return -EINVAL;
1028 if (rec->src_width/uv_hscale > rec->stride_UV) 1036 if (rec->src_width/uv_hscale > rec->stride_UV)
1029 return -EINVAL; 1037 return -EINVAL;
1030 1038
1031 tmp = rec->stride_Y*rec->src_height; 1039 tmp = rec->stride_Y*rec->src_height;
1032 if (rec->offset_Y + tmp > new_bo->size) 1040 if (rec->offset_Y + tmp > new_bo->size)
1033 return -EINVAL; 1041 return -EINVAL;
1034 tmp = rec->stride_UV*rec->src_height; 1042 tmp = rec->stride_UV*rec->src_height;
1035 tmp /= uv_vscale; 1043 tmp /= uv_vscale;
1036 if (rec->offset_U + tmp > new_bo->size 1044 if (rec->offset_U + tmp > new_bo->size ||
1037 || rec->offset_V + tmp > new_bo->size) 1045 rec->offset_V + tmp > new_bo->size)
1038 return -EINVAL; 1046 return -EINVAL;
1039 break; 1047 break;
1040 } 1048 }
1041 1049
1042 return 0; 1050 return 0;
@@ -1082,7 +1090,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
1082 return -ENOMEM; 1090 return -ENOMEM;
1083 1091
1084 drmmode_obj = drm_mode_object_find(dev, put_image_rec->crtc_id, 1092 drmmode_obj = drm_mode_object_find(dev, put_image_rec->crtc_id,
1085 DRM_MODE_OBJECT_CRTC); 1093 DRM_MODE_OBJECT_CRTC);
1086 if (!drmmode_obj) { 1094 if (!drmmode_obj) {
1087 ret = -ENOENT; 1095 ret = -ENOENT;
1088 goto out_free; 1096 goto out_free;
@@ -1090,7 +1098,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
1090 crtc = to_intel_crtc(obj_to_crtc(drmmode_obj)); 1098 crtc = to_intel_crtc(obj_to_crtc(drmmode_obj));
1091 1099
1092 new_bo = drm_gem_object_lookup(dev, file_priv, 1100 new_bo = drm_gem_object_lookup(dev, file_priv,
1093 put_image_rec->bo_handle); 1101 put_image_rec->bo_handle);
1094 if (!new_bo) { 1102 if (!new_bo) {
1095 ret = -ENOENT; 1103 ret = -ENOENT;
1096 goto out_free; 1104 goto out_free;
@@ -1133,10 +1141,10 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
1133 1141
1134 if (overlay->pfit_active) { 1142 if (overlay->pfit_active) {
1135 params->dst_y = ((((u32)put_image_rec->dst_y) << 12) / 1143 params->dst_y = ((((u32)put_image_rec->dst_y) << 12) /
1136 overlay->pfit_vscale_ratio); 1144 overlay->pfit_vscale_ratio);
1137 /* shifting right rounds downwards, so add 1 */ 1145 /* shifting right rounds downwards, so add 1 */
1138 params->dst_h = ((((u32)put_image_rec->dst_height) << 12) / 1146 params->dst_h = ((((u32)put_image_rec->dst_height) << 12) /
1139 overlay->pfit_vscale_ratio) + 1; 1147 overlay->pfit_vscale_ratio) + 1;
1140 } else { 1148 } else {
1141 params->dst_y = put_image_rec->dst_y; 1149 params->dst_y = put_image_rec->dst_y;
1142 params->dst_h = put_image_rec->dst_height; 1150 params->dst_h = put_image_rec->dst_height;
@@ -1148,8 +1156,8 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
1148 params->src_h = put_image_rec->src_height; 1156 params->src_h = put_image_rec->src_height;
1149 params->src_scan_w = put_image_rec->src_scan_width; 1157 params->src_scan_w = put_image_rec->src_scan_width;
1150 params->src_scan_h = put_image_rec->src_scan_height; 1158 params->src_scan_h = put_image_rec->src_scan_height;
1151 if (params->src_scan_h > params->src_h 1159 if (params->src_scan_h > params->src_h ||
1152 || params->src_scan_w > params->src_w) { 1160 params->src_scan_w > params->src_w) {
1153 ret = -EINVAL; 1161 ret = -EINVAL;
1154 goto out_unlock; 1162 goto out_unlock;
1155 } 1163 }
@@ -1205,7 +1213,7 @@ static bool check_gamma_bounds(u32 gamma1, u32 gamma2)
1205 return false; 1213 return false;
1206 1214
1207 for (i = 0; i < 3; i++) { 1215 for (i = 0; i < 3; i++) {
1208 if (((gamma1 >> i * 8) & 0xff) >= ((gamma2 >> i*8) & 0xff)) 1216 if (((gamma1 >> i*8) & 0xff) >= ((gamma2 >> i*8) & 0xff))
1209 return false; 1217 return false;
1210 } 1218 }
1211 1219
@@ -1226,16 +1234,18 @@ static bool check_gamma5_errata(u32 gamma5)
1226 1234
1227static int check_gamma(struct drm_intel_overlay_attrs *attrs) 1235static int check_gamma(struct drm_intel_overlay_attrs *attrs)
1228{ 1236{
1229 if (!check_gamma_bounds(0, attrs->gamma0) 1237 if (!check_gamma_bounds(0, attrs->gamma0) ||
1230 || !check_gamma_bounds(attrs->gamma0, attrs->gamma1) 1238 !check_gamma_bounds(attrs->gamma0, attrs->gamma1) ||
1231 || !check_gamma_bounds(attrs->gamma1, attrs->gamma2) 1239 !check_gamma_bounds(attrs->gamma1, attrs->gamma2) ||
1232 || !check_gamma_bounds(attrs->gamma2, attrs->gamma3) 1240 !check_gamma_bounds(attrs->gamma2, attrs->gamma3) ||
1233 || !check_gamma_bounds(attrs->gamma3, attrs->gamma4) 1241 !check_gamma_bounds(attrs->gamma3, attrs->gamma4) ||
1234 || !check_gamma_bounds(attrs->gamma4, attrs->gamma5) 1242 !check_gamma_bounds(attrs->gamma4, attrs->gamma5) ||
1235 || !check_gamma_bounds(attrs->gamma5, 0x00ffffff)) 1243 !check_gamma_bounds(attrs->gamma5, 0x00ffffff))
1236 return -EINVAL; 1244 return -EINVAL;
1245
1237 if (!check_gamma5_errata(attrs->gamma5)) 1246 if (!check_gamma5_errata(attrs->gamma5))
1238 return -EINVAL; 1247 return -EINVAL;
1248
1239 return 0; 1249 return 0;
1240} 1250}
1241 1251
@@ -1285,12 +1295,14 @@ int intel_overlay_attrs(struct drm_device *dev, void *data,
1285 ret = -EINVAL; 1295 ret = -EINVAL;
1286 goto out_unlock; 1296 goto out_unlock;
1287 } 1297 }
1298
1288 if (attrs->contrast <= 255) { 1299 if (attrs->contrast <= 255) {
1289 overlay->contrast = attrs->contrast; 1300 overlay->contrast = attrs->contrast;
1290 } else { 1301 } else {
1291 ret = -EINVAL; 1302 ret = -EINVAL;
1292 goto out_unlock; 1303 goto out_unlock;
1293 } 1304 }
1305
1294 if (attrs->saturation <= 1023) { 1306 if (attrs->saturation <= 1023) {
1295 overlay->saturation = attrs->saturation; 1307 overlay->saturation = attrs->saturation;
1296 } else { 1308 } else {
@@ -1409,7 +1421,7 @@ out_free:
1409 1421
1410void intel_cleanup_overlay(struct drm_device *dev) 1422void intel_cleanup_overlay(struct drm_device *dev)
1411{ 1423{
1412 drm_i915_private_t *dev_priv = dev->dev_private; 1424 drm_i915_private_t *dev_priv = dev->dev_private;
1413 1425
1414 if (dev_priv->overlay) { 1426 if (dev_priv->overlay) {
1415 /* The bo's should be free'd by the generic code already. 1427 /* The bo's should be free'd by the generic code already.