@@ -400,14 +400,13 @@ static void radeon_flip_work_func(struct work_struct *__work)
400
400
struct radeon_flip_work * work =
401
401
container_of (__work , struct radeon_flip_work , flip_work );
402
402
struct radeon_device * rdev = work -> rdev ;
403
+ struct drm_device * dev = rdev -> ddev ;
403
404
struct radeon_crtc * radeon_crtc = rdev -> mode_info .crtcs [work -> crtc_id ];
404
405
405
406
struct drm_crtc * crtc = & radeon_crtc -> base ;
406
407
unsigned long flags ;
407
408
int r ;
408
- int vpos , hpos , stat , min_udelay = 0 ;
409
- unsigned repcnt = 4 ;
410
- struct drm_vblank_crtc * vblank = & crtc -> dev -> vblank [work -> crtc_id ];
409
+ int vpos , hpos ;
411
410
412
411
down_read (& rdev -> exclusive_lock );
413
412
if (work -> fence ) {
@@ -438,59 +437,25 @@ static void radeon_flip_work_func(struct work_struct *__work)
438
437
work -> fence = NULL ;
439
438
}
440
439
440
+ /* Wait until we're out of the vertical blank period before the one
441
+ * targeted by the flip
442
+ */
443
+ while (radeon_crtc -> enabled &&
444
+ (radeon_get_crtc_scanoutpos (dev , work -> crtc_id , 0 ,
445
+ & vpos , & hpos , NULL , NULL ,
446
+ & crtc -> hwmode )
447
+ & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK )) ==
448
+ (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK ) &&
449
+ (int )(work -> target_vblank -
450
+ dev -> driver -> get_vblank_counter (dev , work -> crtc_id )) > 0 )
451
+ usleep_range (1000 , 2000 );
452
+
441
453
/* We borrow the event spin lock for protecting flip_status */
442
454
spin_lock_irqsave (& crtc -> dev -> event_lock , flags );
443
455
444
456
/* set the proper interrupt */
445
457
radeon_irq_kms_pflip_irq_get (rdev , radeon_crtc -> crtc_id );
446
458
447
- /* If this happens to execute within the "virtually extended" vblank
448
- * interval before the start of the real vblank interval then it needs
449
- * to delay programming the mmio flip until the real vblank is entered.
450
- * This prevents completing a flip too early due to the way we fudge
451
- * our vblank counter and vblank timestamps in order to work around the
452
- * problem that the hw fires vblank interrupts before actual start of
453
- * vblank (when line buffer refilling is done for a frame). It
454
- * complements the fudging logic in radeon_get_crtc_scanoutpos() for
455
- * timestamping and radeon_get_vblank_counter_kms() for vblank counts.
456
- *
457
- * In practice this won't execute very often unless on very fast
458
- * machines because the time window for this to happen is very small.
459
- */
460
- while (radeon_crtc -> enabled && -- repcnt ) {
461
- /* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank
462
- * start in hpos, and to the "fudged earlier" vblank start in
463
- * vpos.
464
- */
465
- stat = radeon_get_crtc_scanoutpos (rdev -> ddev , work -> crtc_id ,
466
- GET_DISTANCE_TO_VBLANKSTART ,
467
- & vpos , & hpos , NULL , NULL ,
468
- & crtc -> hwmode );
469
-
470
- if ((stat & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE )) !=
471
- (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE ) ||
472
- !(vpos >= 0 && hpos <= 0 ))
473
- break ;
474
-
475
- /* Sleep at least until estimated real start of hw vblank */
476
- min_udelay = (- hpos + 1 ) * max (vblank -> linedur_ns / 1000 , 5 );
477
- if (min_udelay > vblank -> framedur_ns / 2000 ) {
478
- /* Don't wait ridiculously long - something is wrong */
479
- repcnt = 0 ;
480
- break ;
481
- }
482
- spin_unlock_irqrestore (& crtc -> dev -> event_lock , flags );
483
- usleep_range (min_udelay , 2 * min_udelay );
484
- spin_lock_irqsave (& crtc -> dev -> event_lock , flags );
485
- };
486
-
487
- if (!repcnt )
488
- DRM_DEBUG_DRIVER ("Delay problem on crtc %d: min_udelay %d, "
489
- "framedur %d, linedur %d, stat %d, vpos %d, "
490
- "hpos %d\n" , work -> crtc_id , min_udelay ,
491
- vblank -> framedur_ns / 1000 ,
492
- vblank -> linedur_ns / 1000 , stat , vpos , hpos );
493
-
494
459
/* do the flip (mmio) */
495
460
radeon_page_flip (rdev , radeon_crtc -> crtc_id , work -> base , work -> async );
496
461
@@ -499,10 +464,11 @@ static void radeon_flip_work_func(struct work_struct *__work)
499
464
up_read (& rdev -> exclusive_lock );
500
465
}
501
466
502
- static int radeon_crtc_page_flip (struct drm_crtc * crtc ,
503
- struct drm_framebuffer * fb ,
504
- struct drm_pending_vblank_event * event ,
505
- uint32_t page_flip_flags )
467
+ static int radeon_crtc_page_flip_target (struct drm_crtc * crtc ,
468
+ struct drm_framebuffer * fb ,
469
+ struct drm_pending_vblank_event * event ,
470
+ uint32_t page_flip_flags ,
471
+ uint32_t target )
506
472
{
507
473
struct drm_device * dev = crtc -> dev ;
508
474
struct radeon_device * rdev = dev -> dev_private ;
@@ -599,12 +565,8 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
599
565
base &= ~7 ;
600
566
}
601
567
work -> base = base ;
602
-
603
- r = drm_crtc_vblank_get (crtc );
604
- if (r ) {
605
- DRM_ERROR ("failed to get vblank before flip\n" );
606
- goto pflip_cleanup ;
607
- }
568
+ work -> target_vblank = target - drm_crtc_vblank_count (crtc ) +
569
+ dev -> driver -> get_vblank_counter (dev , work -> crtc_id );
608
570
609
571
/* We borrow the event spin lock for protecting flip_work */
610
572
spin_lock_irqsave (& crtc -> dev -> event_lock , flags );
@@ -613,7 +575,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
613
575
DRM_DEBUG_DRIVER ("flip queue: crtc already busy\n" );
614
576
spin_unlock_irqrestore (& crtc -> dev -> event_lock , flags );
615
577
r = - EBUSY ;
616
- goto vblank_cleanup ;
578
+ goto pflip_cleanup ;
617
579
}
618
580
radeon_crtc -> flip_status = RADEON_FLIP_PENDING ;
619
581
radeon_crtc -> flip_work = work ;
@@ -626,9 +588,6 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
626
588
queue_work (radeon_crtc -> flip_queue , & work -> flip_work );
627
589
return 0 ;
628
590
629
- vblank_cleanup :
630
- drm_crtc_vblank_put (crtc );
631
-
632
591
pflip_cleanup :
633
592
if (unlikely (radeon_bo_reserve (new_rbo , false) != 0 )) {
634
593
DRM_ERROR ("failed to reserve new rbo in error path\n" );
@@ -697,7 +656,7 @@ static const struct drm_crtc_funcs radeon_crtc_funcs = {
697
656
.gamma_set = radeon_crtc_gamma_set ,
698
657
.set_config = radeon_crtc_set_config ,
699
658
.destroy = radeon_crtc_destroy ,
700
- .page_flip = radeon_crtc_page_flip ,
659
+ .page_flip_target = radeon_crtc_page_flip_target ,
701
660
};
702
661
703
662
static void radeon_crtc_init (struct drm_device * dev , int index )
0 commit comments