diff options
Diffstat (limited to 'drivers/char/drm/i915_dma.c')
-rw-r--r-- | drivers/char/drm/i915_dma.c | 160 |
1 files changed, 41 insertions, 119 deletions
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c index f47e46e3529f..88974342933c 100644 --- a/drivers/char/drm/i915_dma.c +++ b/drivers/char/drm/i915_dma.c | |||
@@ -415,13 +415,10 @@ static void i915_emit_breadcrumb(struct drm_device *dev) | |||
415 | drm_i915_private_t *dev_priv = dev->dev_private; | 415 | drm_i915_private_t *dev_priv = dev->dev_private; |
416 | RING_LOCALS; | 416 | RING_LOCALS; |
417 | 417 | ||
418 | if (++dev_priv->counter > BREADCRUMB_MASK) { | 418 | dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter; |
419 | dev_priv->counter = 1; | ||
420 | DRM_DEBUG("Breadcrumb counter wrapped around\n"); | ||
421 | } | ||
422 | 419 | ||
423 | if (dev_priv->sarea_priv) | 420 | if (dev_priv->counter > 0x7FFFFFFFUL) |
424 | dev_priv->sarea_priv->last_enqueue = dev_priv->counter; | 421 | dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1; |
425 | 422 | ||
426 | BEGIN_LP_RING(4); | 423 | BEGIN_LP_RING(4); |
427 | OUT_RING(CMD_STORE_DWORD_IDX); | 424 | OUT_RING(CMD_STORE_DWORD_IDX); |
@@ -431,26 +428,6 @@ static void i915_emit_breadcrumb(struct drm_device *dev) | |||
431 | ADVANCE_LP_RING(); | 428 | ADVANCE_LP_RING(); |
432 | } | 429 | } |
433 | 430 | ||
434 | int i915_emit_mi_flush(struct drm_device *dev, uint32_t flush) | ||
435 | { | ||
436 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
437 | uint32_t flush_cmd = CMD_MI_FLUSH; | ||
438 | RING_LOCALS; | ||
439 | |||
440 | flush_cmd |= flush; | ||
441 | |||
442 | i915_kernel_lost_context(dev); | ||
443 | |||
444 | BEGIN_LP_RING(4); | ||
445 | OUT_RING(flush_cmd); | ||
446 | OUT_RING(0); | ||
447 | OUT_RING(0); | ||
448 | OUT_RING(0); | ||
449 | ADVANCE_LP_RING(); | ||
450 | |||
451 | return 0; | ||
452 | } | ||
453 | |||
454 | static int i915_dispatch_cmdbuffer(struct drm_device * dev, | 431 | static int i915_dispatch_cmdbuffer(struct drm_device * dev, |
455 | drm_i915_cmdbuffer_t * cmd) | 432 | drm_i915_cmdbuffer_t * cmd) |
456 | { | 433 | { |
@@ -534,74 +511,52 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev, | |||
534 | return 0; | 511 | return 0; |
535 | } | 512 | } |
536 | 513 | ||
537 | static void i915_do_dispatch_flip(struct drm_device * dev, int plane, int sync) | 514 | static int i915_dispatch_flip(struct drm_device * dev) |
538 | { | 515 | { |
539 | drm_i915_private_t *dev_priv = dev->dev_private; | 516 | drm_i915_private_t *dev_priv = dev->dev_private; |
540 | u32 num_pages, current_page, next_page, dspbase; | ||
541 | int shift = 2 * plane, x, y; | ||
542 | RING_LOCALS; | 517 | RING_LOCALS; |
543 | 518 | ||
544 | /* Calculate display base offset */ | 519 | DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n", |
545 | num_pages = dev_priv->sarea_priv->third_handle ? 3 : 2; | 520 | __FUNCTION__, |
546 | current_page = (dev_priv->sarea_priv->pf_current_page >> shift) & 0x3; | 521 | dev_priv->current_page, |
547 | next_page = (current_page + 1) % num_pages; | 522 | dev_priv->sarea_priv->pf_current_page); |
548 | 523 | ||
549 | switch (next_page) { | 524 | i915_kernel_lost_context(dev); |
550 | default: | 525 | |
551 | case 0: | 526 | BEGIN_LP_RING(2); |
552 | dspbase = dev_priv->sarea_priv->front_offset; | 527 | OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE); |
553 | break; | 528 | OUT_RING(0); |
554 | case 1: | 529 | ADVANCE_LP_RING(); |
555 | dspbase = dev_priv->sarea_priv->back_offset; | ||
556 | break; | ||
557 | case 2: | ||
558 | dspbase = dev_priv->sarea_priv->third_offset; | ||
559 | break; | ||
560 | } | ||
561 | 530 | ||
562 | if (plane == 0) { | 531 | BEGIN_LP_RING(6); |
563 | x = dev_priv->sarea_priv->planeA_x; | 532 | OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP); |
564 | y = dev_priv->sarea_priv->planeA_y; | 533 | OUT_RING(0); |
534 | if (dev_priv->current_page == 0) { | ||
535 | OUT_RING(dev_priv->back_offset); | ||
536 | dev_priv->current_page = 1; | ||
565 | } else { | 537 | } else { |
566 | x = dev_priv->sarea_priv->planeB_x; | 538 | OUT_RING(dev_priv->front_offset); |
567 | y = dev_priv->sarea_priv->planeB_y; | 539 | dev_priv->current_page = 0; |
568 | } | 540 | } |
541 | OUT_RING(0); | ||
542 | ADVANCE_LP_RING(); | ||
569 | 543 | ||
570 | dspbase += (y * dev_priv->sarea_priv->pitch + x) * dev_priv->cpp; | 544 | BEGIN_LP_RING(2); |
545 | OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP); | ||
546 | OUT_RING(0); | ||
547 | ADVANCE_LP_RING(); | ||
571 | 548 | ||
572 | DRM_DEBUG("plane=%d current_page=%d dspbase=0x%x\n", plane, current_page, | 549 | dev_priv->sarea_priv->last_enqueue = dev_priv->counter++; |
573 | dspbase); | ||
574 | 550 | ||
575 | BEGIN_LP_RING(4); | 551 | BEGIN_LP_RING(4); |
576 | OUT_RING(sync ? 0 : | 552 | OUT_RING(CMD_STORE_DWORD_IDX); |
577 | (MI_WAIT_FOR_EVENT | (plane ? MI_WAIT_FOR_PLANE_B_FLIP : | 553 | OUT_RING(20); |
578 | MI_WAIT_FOR_PLANE_A_FLIP))); | 554 | OUT_RING(dev_priv->counter); |
579 | OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | (sync ? 0 : ASYNC_FLIP) | | 555 | OUT_RING(0); |
580 | (plane ? DISPLAY_PLANE_B : DISPLAY_PLANE_A)); | ||
581 | OUT_RING(dev_priv->sarea_priv->pitch * dev_priv->cpp); | ||
582 | OUT_RING(dspbase); | ||
583 | ADVANCE_LP_RING(); | 556 | ADVANCE_LP_RING(); |
584 | 557 | ||
585 | dev_priv->sarea_priv->pf_current_page &= ~(0x3 << shift); | 558 | dev_priv->sarea_priv->pf_current_page = dev_priv->current_page; |
586 | dev_priv->sarea_priv->pf_current_page |= next_page << shift; | 559 | return 0; |
587 | } | ||
588 | |||
589 | void i915_dispatch_flip(struct drm_device * dev, int planes, int sync) | ||
590 | { | ||
591 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
592 | int i; | ||
593 | |||
594 | DRM_DEBUG("planes=0x%x pfCurrentPage=%d\n", | ||
595 | planes, dev_priv->sarea_priv->pf_current_page); | ||
596 | |||
597 | i915_emit_mi_flush(dev, MI_READ_FLUSH | MI_EXE_FLUSH); | ||
598 | |||
599 | for (i = 0; i < 2; i++) | ||
600 | if (planes & (1 << i)) | ||
601 | i915_do_dispatch_flip(dev, i, sync); | ||
602 | |||
603 | i915_emit_breadcrumb(dev); | ||
604 | |||
605 | } | 560 | } |
606 | 561 | ||
607 | static int i915_quiescent(struct drm_device * dev) | 562 | static int i915_quiescent(struct drm_device * dev) |
@@ -624,6 +579,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data, | |||
624 | struct drm_file *file_priv) | 579 | struct drm_file *file_priv) |
625 | { | 580 | { |
626 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 581 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
582 | u32 *hw_status = dev_priv->hw_status_page; | ||
627 | drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) | 583 | drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) |
628 | dev_priv->sarea_priv; | 584 | dev_priv->sarea_priv; |
629 | drm_i915_batchbuffer_t *batch = data; | 585 | drm_i915_batchbuffer_t *batch = data; |
@@ -646,7 +602,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data, | |||
646 | 602 | ||
647 | ret = i915_dispatch_batchbuffer(dev, batch); | 603 | ret = i915_dispatch_batchbuffer(dev, batch); |
648 | 604 | ||
649 | sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); | 605 | sarea_priv->last_dispatch = (int)hw_status[5]; |
650 | return ret; | 606 | return ret; |
651 | } | 607 | } |
652 | 608 | ||
@@ -654,6 +610,7 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, | |||
654 | struct drm_file *file_priv) | 610 | struct drm_file *file_priv) |
655 | { | 611 | { |
656 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 612 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
613 | u32 *hw_status = dev_priv->hw_status_page; | ||
657 | drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) | 614 | drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) |
658 | dev_priv->sarea_priv; | 615 | dev_priv->sarea_priv; |
659 | drm_i915_cmdbuffer_t *cmdbuf = data; | 616 | drm_i915_cmdbuffer_t *cmdbuf = data; |
@@ -678,51 +635,18 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, | |||
678 | return ret; | 635 | return ret; |
679 | } | 636 | } |
680 | 637 | ||
681 | sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); | 638 | sarea_priv->last_dispatch = (int)hw_status[5]; |
682 | return 0; | ||
683 | } | ||
684 | |||
685 | static int i915_do_cleanup_pageflip(struct drm_device * dev) | ||
686 | { | ||
687 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
688 | int i, planes, num_pages = dev_priv->sarea_priv->third_handle ? 3 : 2; | ||
689 | |||
690 | DRM_DEBUG("\n"); | ||
691 | |||
692 | for (i = 0, planes = 0; i < 2; i++) | ||
693 | if (dev_priv->sarea_priv->pf_current_page & (0x3 << (2 * i))) { | ||
694 | dev_priv->sarea_priv->pf_current_page = | ||
695 | (dev_priv->sarea_priv->pf_current_page & | ||
696 | ~(0x3 << (2 * i))) | ((num_pages - 1) << (2 * i)); | ||
697 | |||
698 | planes |= 1 << i; | ||
699 | } | ||
700 | |||
701 | if (planes) | ||
702 | i915_dispatch_flip(dev, planes, 0); | ||
703 | |||
704 | return 0; | 639 | return 0; |
705 | } | 640 | } |
706 | 641 | ||
707 | static int i915_flip_bufs(struct drm_device *dev, void *data, | 642 | static int i915_flip_bufs(struct drm_device *dev, void *data, |
708 | struct drm_file *file_priv) | 643 | struct drm_file *file_priv) |
709 | { | 644 | { |
710 | drm_i915_flip_t *param = data; | 645 | DRM_DEBUG("%s\n", __FUNCTION__); |
711 | |||
712 | DRM_DEBUG("\n"); | ||
713 | 646 | ||
714 | LOCK_TEST_WITH_RETURN(dev, file_priv); | 647 | LOCK_TEST_WITH_RETURN(dev, file_priv); |
715 | 648 | ||
716 | /* This is really planes */ | 649 | return i915_dispatch_flip(dev); |
717 | if (param->pipes & ~0x3) { | ||
718 | DRM_ERROR("Invalid planes 0x%x, only <= 0x3 is valid\n", | ||
719 | param->pipes); | ||
720 | return -EINVAL; | ||
721 | } | ||
722 | |||
723 | i915_dispatch_flip(dev, param->pipes, 0); | ||
724 | |||
725 | return 0; | ||
726 | } | 650 | } |
727 | 651 | ||
728 | static int i915_getparam(struct drm_device *dev, void *data, | 652 | static int i915_getparam(struct drm_device *dev, void *data, |
@@ -883,8 +807,6 @@ void i915_driver_lastclose(struct drm_device * dev) | |||
883 | if (!dev_priv) | 807 | if (!dev_priv) |
884 | return; | 808 | return; |
885 | 809 | ||
886 | if (drm_getsarea(dev) && dev_priv->sarea_priv) | ||
887 | i915_do_cleanup_pageflip(dev); | ||
888 | if (dev_priv->agp_heap) | 810 | if (dev_priv->agp_heap) |
889 | i915_mem_takedown(&(dev_priv->agp_heap)); | 811 | i915_mem_takedown(&(dev_priv->agp_heap)); |
890 | 812 | ||