@@ -6261,6 +6261,197 @@ void intel_prepare_page_flip(struct drm_device *dev, int plane)
62616261 spin_unlock_irqrestore (& dev -> event_lock , flags );
62626262}
62636263
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+
62646455static int intel_crtc_page_flip (struct drm_crtc * crtc ,
62656456 struct drm_framebuffer * fb ,
62666457 struct drm_pending_vblank_event * event )
@@ -6271,9 +6462,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
62716462 struct drm_i915_gem_object * obj ;
62726463 struct intel_crtc * intel_crtc = to_intel_crtc (crtc );
62736464 struct intel_unpin_work * work ;
6274- unsigned long flags , offset ;
6275- int pipe = intel_crtc -> pipe ;
6276- u32 pf , pipesrc ;
6465+ unsigned long flags ;
62776466 int ret ;
62786467
62796468 work = kzalloc (sizeof * work , GFP_KERNEL );
@@ -6302,9 +6491,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
63026491 obj = intel_fb -> obj ;
63036492
63046493 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 ;
63086494
63096495 /* Reference the objects for the scheduled work. */
63106496 drm_gem_object_reference (& work -> old_fb_obj -> base );
@@ -6316,102 +6502,30 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
63166502 if (ret )
63176503 goto cleanup_objs ;
63186504
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-
63386505 work -> pending_flip_obj = obj ;
63396506
63406507 work -> enable_stall_check = true;
63416508
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-
63496509 /* Block clients from rendering to the new back buffer until
63506510 * the flip occurs and the object is no longer visible.
63516511 */
63526512 atomic_add (1 << intel_crtc -> plane , & work -> old_fb_obj -> pending_flip );
63536513
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 ;
64046517
64056518 mutex_unlock (& dev -> struct_mutex );
64066519
64076520 trace_i915_flip_request (intel_crtc -> plane , obj );
64086521
64096522 return 0 ;
64106523
6524+ cleanup_pending :
6525+ atomic_sub (1 << intel_crtc -> plane , & work -> old_fb_obj -> pending_flip );
64116526cleanup_objs :
64126527 drm_gem_object_unreference (& work -> old_fb_obj -> base );
64136528 drm_gem_object_unreference (& obj -> base );
6414- cleanup_work :
64156529 mutex_unlock (& dev -> struct_mutex );
64166530
64176531 spin_lock_irqsave (& dev -> event_lock , flags );
@@ -7656,6 +7770,31 @@ static void intel_init_display(struct drm_device *dev)
76567770 else
76577771 dev_priv -> display .get_fifo_size = i830_get_fifo_size ;
76587772 }
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+ }
76597798}
76607799
76617800/*
0 commit comments