@@ -6261,6 +6261,197 @@ void intel_prepare_page_flip(struct drm_device *dev, int plane)
6261
6261
spin_unlock_irqrestore (& dev -> event_lock , flags );
6262
6262
}
6263
6263
6264
+ static int intel_gen2_queue_flip (struct drm_device * dev ,
6265
+ struct drm_crtc * crtc ,
6266
+ struct drm_framebuffer * fb ,
6267
+ struct drm_i915_gem_object * obj )
6268
+ {
6269
+ struct drm_i915_private * dev_priv = dev -> dev_private ;
6270
+ struct intel_crtc * intel_crtc = to_intel_crtc (crtc );
6271
+ unsigned long offset ;
6272
+ u32 flip_mask ;
6273
+ int ret ;
6274
+
6275
+ ret = intel_pin_and_fence_fb_obj (dev , obj , LP_RING (dev_priv ));
6276
+ if (ret )
6277
+ goto out ;
6278
+
6279
+ /* Offset into the new buffer for cases of shared fbs between CRTCs */
6280
+ offset = crtc -> y * fb -> pitch + crtc -> x * fb -> bits_per_pixel /8 ;
6281
+
6282
+ ret = BEGIN_LP_RING (6 );
6283
+ if (ret )
6284
+ goto out ;
6285
+
6286
+ /* Can't queue multiple flips, so wait for the previous
6287
+ * one to finish before executing the next.
6288
+ */
6289
+ if (intel_crtc -> plane )
6290
+ flip_mask = MI_WAIT_FOR_PLANE_B_FLIP ;
6291
+ else
6292
+ flip_mask = MI_WAIT_FOR_PLANE_A_FLIP ;
6293
+ OUT_RING (MI_WAIT_FOR_EVENT | flip_mask );
6294
+ OUT_RING (MI_NOOP );
6295
+ OUT_RING (MI_DISPLAY_FLIP |
6296
+ MI_DISPLAY_FLIP_PLANE (intel_crtc -> plane ));
6297
+ OUT_RING (fb -> pitch );
6298
+ OUT_RING (obj -> gtt_offset + offset );
6299
+ OUT_RING (MI_NOOP );
6300
+ ADVANCE_LP_RING ();
6301
+ out :
6302
+ return ret ;
6303
+ }
6304
+
6305
+ static int intel_gen3_queue_flip (struct drm_device * dev ,
6306
+ struct drm_crtc * crtc ,
6307
+ struct drm_framebuffer * fb ,
6308
+ struct drm_i915_gem_object * obj )
6309
+ {
6310
+ struct drm_i915_private * dev_priv = dev -> dev_private ;
6311
+ struct intel_crtc * intel_crtc = to_intel_crtc (crtc );
6312
+ unsigned long offset ;
6313
+ u32 flip_mask ;
6314
+ int ret ;
6315
+
6316
+ ret = intel_pin_and_fence_fb_obj (dev , obj , LP_RING (dev_priv ));
6317
+ if (ret )
6318
+ goto out ;
6319
+
6320
+ /* Offset into the new buffer for cases of shared fbs between CRTCs */
6321
+ offset = crtc -> y * fb -> pitch + crtc -> x * fb -> bits_per_pixel /8 ;
6322
+
6323
+ ret = BEGIN_LP_RING (6 );
6324
+ if (ret )
6325
+ goto out ;
6326
+
6327
+ if (intel_crtc -> plane )
6328
+ flip_mask = MI_WAIT_FOR_PLANE_B_FLIP ;
6329
+ else
6330
+ flip_mask = MI_WAIT_FOR_PLANE_A_FLIP ;
6331
+ OUT_RING (MI_WAIT_FOR_EVENT | flip_mask );
6332
+ OUT_RING (MI_NOOP );
6333
+ OUT_RING (MI_DISPLAY_FLIP_I915 |
6334
+ MI_DISPLAY_FLIP_PLANE (intel_crtc -> plane ));
6335
+ OUT_RING (fb -> pitch );
6336
+ OUT_RING (obj -> gtt_offset + offset );
6337
+ OUT_RING (MI_NOOP );
6338
+
6339
+ ADVANCE_LP_RING ();
6340
+ out :
6341
+ return ret ;
6342
+ }
6343
+
6344
+ static int intel_gen4_queue_flip (struct drm_device * dev ,
6345
+ struct drm_crtc * crtc ,
6346
+ struct drm_framebuffer * fb ,
6347
+ struct drm_i915_gem_object * obj )
6348
+ {
6349
+ struct drm_i915_private * dev_priv = dev -> dev_private ;
6350
+ struct intel_crtc * intel_crtc = to_intel_crtc (crtc );
6351
+ uint32_t pf , pipesrc ;
6352
+ int ret ;
6353
+
6354
+ ret = intel_pin_and_fence_fb_obj (dev , obj , LP_RING (dev_priv ));
6355
+ if (ret )
6356
+ goto out ;
6357
+
6358
+ ret = BEGIN_LP_RING (4 );
6359
+ if (ret )
6360
+ goto out ;
6361
+
6362
+ /* i965+ uses the linear or tiled offsets from the
6363
+ * Display Registers (which do not change across a page-flip)
6364
+ * so we need only reprogram the base address.
6365
+ */
6366
+ OUT_RING (MI_DISPLAY_FLIP |
6367
+ MI_DISPLAY_FLIP_PLANE (intel_crtc -> plane ));
6368
+ OUT_RING (fb -> pitch );
6369
+ OUT_RING (obj -> gtt_offset | obj -> tiling_mode );
6370
+
6371
+ /* XXX Enabling the panel-fitter across page-flip is so far
6372
+ * untested on non-native modes, so ignore it for now.
6373
+ * pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE;
6374
+ */
6375
+ pf = 0 ;
6376
+ pipesrc = I915_READ (PIPESRC (intel_crtc -> pipe )) & 0x0fff0fff ;
6377
+ OUT_RING (pf | pipesrc );
6378
+ ADVANCE_LP_RING ();
6379
+ out :
6380
+ return ret ;
6381
+ }
6382
+
6383
+ static int intel_gen6_queue_flip (struct drm_device * dev ,
6384
+ struct drm_crtc * crtc ,
6385
+ struct drm_framebuffer * fb ,
6386
+ struct drm_i915_gem_object * obj )
6387
+ {
6388
+ struct drm_i915_private * dev_priv = dev -> dev_private ;
6389
+ struct intel_crtc * intel_crtc = to_intel_crtc (crtc );
6390
+ uint32_t pf , pipesrc ;
6391
+ int ret ;
6392
+
6393
+ ret = intel_pin_and_fence_fb_obj (dev , obj , LP_RING (dev_priv ));
6394
+ if (ret )
6395
+ goto out ;
6396
+
6397
+ ret = BEGIN_LP_RING (4 );
6398
+ if (ret )
6399
+ goto out ;
6400
+
6401
+ OUT_RING (MI_DISPLAY_FLIP |
6402
+ MI_DISPLAY_FLIP_PLANE (intel_crtc -> plane ));
6403
+ OUT_RING (fb -> pitch | obj -> tiling_mode );
6404
+ OUT_RING (obj -> gtt_offset );
6405
+
6406
+ pf = I915_READ (PF_CTL (intel_crtc -> pipe )) & PF_ENABLE ;
6407
+ pipesrc = I915_READ (PIPESRC (intel_crtc -> pipe )) & 0x0fff0fff ;
6408
+ OUT_RING (pf | pipesrc );
6409
+ ADVANCE_LP_RING ();
6410
+ out :
6411
+ return ret ;
6412
+ }
6413
+
6414
+ /*
6415
+ * On gen7 we currently use the blit ring because (in early silicon at least)
6416
+ * the render ring doesn't give us interrpts for page flip completion, which
6417
+ * means clients will hang after the first flip is queued. Fortunately the
6418
+ * blit ring generates interrupts properly, so use it instead.
6419
+ */
6420
+ static int intel_gen7_queue_flip (struct drm_device * dev ,
6421
+ struct drm_crtc * crtc ,
6422
+ struct drm_framebuffer * fb ,
6423
+ struct drm_i915_gem_object * obj )
6424
+ {
6425
+ struct drm_i915_private * dev_priv = dev -> dev_private ;
6426
+ struct intel_crtc * intel_crtc = to_intel_crtc (crtc );
6427
+ struct intel_ring_buffer * ring = & dev_priv -> ring [BCS ];
6428
+ int ret ;
6429
+
6430
+ ret = intel_pin_and_fence_fb_obj (dev , obj , ring );
6431
+ if (ret )
6432
+ goto out ;
6433
+
6434
+ ret = intel_ring_begin (ring , 4 );
6435
+ if (ret )
6436
+ goto out ;
6437
+
6438
+ intel_ring_emit (ring , MI_DISPLAY_FLIP_I915 | (intel_crtc -> plane << 19 ));
6439
+ intel_ring_emit (ring , (fb -> pitch | obj -> tiling_mode ));
6440
+ intel_ring_emit (ring , (obj -> gtt_offset ));
6441
+ intel_ring_emit (ring , (MI_NOOP ));
6442
+ intel_ring_advance (ring );
6443
+ out :
6444
+ return ret ;
6445
+ }
6446
+
6447
+ static int intel_default_queue_flip (struct drm_device * dev ,
6448
+ struct drm_crtc * crtc ,
6449
+ struct drm_framebuffer * fb ,
6450
+ struct drm_i915_gem_object * obj )
6451
+ {
6452
+ return - ENODEV ;
6453
+ }
6454
+
6264
6455
static int intel_crtc_page_flip (struct drm_crtc * crtc ,
6265
6456
struct drm_framebuffer * fb ,
6266
6457
struct drm_pending_vblank_event * event )
@@ -6271,9 +6462,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
6271
6462
struct drm_i915_gem_object * obj ;
6272
6463
struct intel_crtc * intel_crtc = to_intel_crtc (crtc );
6273
6464
struct intel_unpin_work * work ;
6274
- unsigned long flags , offset ;
6275
- int pipe = intel_crtc -> pipe ;
6276
- u32 pf , pipesrc ;
6465
+ unsigned long flags ;
6277
6466
int ret ;
6278
6467
6279
6468
work = kzalloc (sizeof * work , GFP_KERNEL );
@@ -6302,9 +6491,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
6302
6491
obj = intel_fb -> obj ;
6303
6492
6304
6493
mutex_lock (& dev -> struct_mutex );
6305
- ret = intel_pin_and_fence_fb_obj (dev , obj , LP_RING (dev_priv ));
6306
- if (ret )
6307
- goto cleanup_work ;
6308
6494
6309
6495
/* Reference the objects for the scheduled work. */
6310
6496
drm_gem_object_reference (& work -> old_fb_obj -> base );
@@ -6316,102 +6502,30 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
6316
6502
if (ret )
6317
6503
goto cleanup_objs ;
6318
6504
6319
- if (IS_GEN3 (dev ) || IS_GEN2 (dev )) {
6320
- u32 flip_mask ;
6321
-
6322
- /* Can't queue multiple flips, so wait for the previous
6323
- * one to finish before executing the next.
6324
- */
6325
- ret = BEGIN_LP_RING (2 );
6326
- if (ret )
6327
- goto cleanup_objs ;
6328
-
6329
- if (intel_crtc -> plane )
6330
- flip_mask = MI_WAIT_FOR_PLANE_B_FLIP ;
6331
- else
6332
- flip_mask = MI_WAIT_FOR_PLANE_A_FLIP ;
6333
- OUT_RING (MI_WAIT_FOR_EVENT | flip_mask );
6334
- OUT_RING (MI_NOOP );
6335
- ADVANCE_LP_RING ();
6336
- }
6337
-
6338
6505
work -> pending_flip_obj = obj ;
6339
6506
6340
6507
work -> enable_stall_check = true;
6341
6508
6342
- /* Offset into the new buffer for cases of shared fbs between CRTCs */
6343
- offset = crtc -> y * fb -> pitch + crtc -> x * fb -> bits_per_pixel /8 ;
6344
-
6345
- ret = BEGIN_LP_RING (4 );
6346
- if (ret )
6347
- goto cleanup_objs ;
6348
-
6349
6509
/* Block clients from rendering to the new back buffer until
6350
6510
* the flip occurs and the object is no longer visible.
6351
6511
*/
6352
6512
atomic_add (1 << intel_crtc -> plane , & work -> old_fb_obj -> pending_flip );
6353
6513
6354
- switch (INTEL_INFO (dev )-> gen ) {
6355
- case 2 :
6356
- OUT_RING (MI_DISPLAY_FLIP |
6357
- MI_DISPLAY_FLIP_PLANE (intel_crtc -> plane ));
6358
- OUT_RING (fb -> pitch );
6359
- OUT_RING (obj -> gtt_offset + offset );
6360
- OUT_RING (MI_NOOP );
6361
- break ;
6362
-
6363
- case 3 :
6364
- OUT_RING (MI_DISPLAY_FLIP_I915 |
6365
- MI_DISPLAY_FLIP_PLANE (intel_crtc -> plane ));
6366
- OUT_RING (fb -> pitch );
6367
- OUT_RING (obj -> gtt_offset + offset );
6368
- OUT_RING (MI_NOOP );
6369
- break ;
6370
-
6371
- case 4 :
6372
- case 5 :
6373
- /* i965+ uses the linear or tiled offsets from the
6374
- * Display Registers (which do not change across a page-flip)
6375
- * so we need only reprogram the base address.
6376
- */
6377
- OUT_RING (MI_DISPLAY_FLIP |
6378
- MI_DISPLAY_FLIP_PLANE (intel_crtc -> plane ));
6379
- OUT_RING (fb -> pitch );
6380
- OUT_RING (obj -> gtt_offset | obj -> tiling_mode );
6381
-
6382
- /* XXX Enabling the panel-fitter across page-flip is so far
6383
- * untested on non-native modes, so ignore it for now.
6384
- * pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE;
6385
- */
6386
- pf = 0 ;
6387
- pipesrc = I915_READ (PIPESRC (pipe )) & 0x0fff0fff ;
6388
- OUT_RING (pf | pipesrc );
6389
- break ;
6390
-
6391
- case 6 :
6392
- case 7 :
6393
- OUT_RING (MI_DISPLAY_FLIP |
6394
- MI_DISPLAY_FLIP_PLANE (intel_crtc -> plane ));
6395
- OUT_RING (fb -> pitch | obj -> tiling_mode );
6396
- OUT_RING (obj -> gtt_offset );
6397
-
6398
- pf = I915_READ (PF_CTL (pipe )) & PF_ENABLE ;
6399
- pipesrc = I915_READ (PIPESRC (pipe )) & 0x0fff0fff ;
6400
- OUT_RING (pf | pipesrc );
6401
- break ;
6402
- }
6403
- ADVANCE_LP_RING ();
6514
+ ret = dev_priv -> display .queue_flip (dev , crtc , fb , obj );
6515
+ if (ret )
6516
+ goto cleanup_pending ;
6404
6517
6405
6518
mutex_unlock (& dev -> struct_mutex );
6406
6519
6407
6520
trace_i915_flip_request (intel_crtc -> plane , obj );
6408
6521
6409
6522
return 0 ;
6410
6523
6524
+ cleanup_pending :
6525
+ atomic_sub (1 << intel_crtc -> plane , & work -> old_fb_obj -> pending_flip );
6411
6526
cleanup_objs :
6412
6527
drm_gem_object_unreference (& work -> old_fb_obj -> base );
6413
6528
drm_gem_object_unreference (& obj -> base );
6414
- cleanup_work :
6415
6529
mutex_unlock (& dev -> struct_mutex );
6416
6530
6417
6531
spin_lock_irqsave (& dev -> event_lock , flags );
@@ -7656,6 +7770,31 @@ static void intel_init_display(struct drm_device *dev)
7656
7770
else
7657
7771
dev_priv -> display .get_fifo_size = i830_get_fifo_size ;
7658
7772
}
7773
+
7774
+ /* Default just returns -ENODEV to indicate unsupported */
7775
+ dev_priv -> display .queue_flip = intel_default_queue_flip ;
7776
+
7777
+ switch (INTEL_INFO (dev )-> gen ) {
7778
+ case 2 :
7779
+ dev_priv -> display .queue_flip = intel_gen2_queue_flip ;
7780
+ break ;
7781
+
7782
+ case 3 :
7783
+ dev_priv -> display .queue_flip = intel_gen3_queue_flip ;
7784
+ break ;
7785
+
7786
+ case 4 :
7787
+ case 5 :
7788
+ dev_priv -> display .queue_flip = intel_gen4_queue_flip ;
7789
+ break ;
7790
+
7791
+ case 6 :
7792
+ dev_priv -> display .queue_flip = intel_gen6_queue_flip ;
7793
+ break ;
7794
+ case 7 :
7795
+ dev_priv -> display .queue_flip = intel_gen7_queue_flip ;
7796
+ break ;
7797
+ }
7659
7798
}
7660
7799
7661
7800
/*
0 commit comments