@@ -657,9 +657,9 @@ static int vc4_crtc_bind(struct device *dev, struct device *master, void *data)
657
657
struct vc4_dev * vc4 = to_vc4_dev (drm );
658
658
struct vc4_crtc * vc4_crtc ;
659
659
struct drm_crtc * crtc ;
660
- struct drm_plane * primary_plane , * cursor_plane ;
660
+ struct drm_plane * primary_plane , * cursor_plane , * destroy_plane , * temp ;
661
661
const struct of_device_id * match ;
662
- int ret ;
662
+ int ret , i ;
663
663
664
664
vc4_crtc = devm_kzalloc (dev , sizeof (* vc4_crtc ), GFP_KERNEL );
665
665
if (!vc4_crtc )
@@ -688,38 +688,62 @@ static int vc4_crtc_bind(struct device *dev, struct device *master, void *data)
688
688
goto err ;
689
689
}
690
690
691
- cursor_plane = vc4_plane_init (drm , DRM_PLANE_TYPE_CURSOR );
692
- if (IS_ERR (cursor_plane )) {
693
- dev_err (dev , "failed to construct cursor plane\n" );
694
- ret = PTR_ERR (cursor_plane );
695
- goto err_primary ;
696
- }
697
-
698
- drm_crtc_init_with_planes (drm , crtc , primary_plane , cursor_plane ,
691
+ drm_crtc_init_with_planes (drm , crtc , primary_plane , NULL ,
699
692
& vc4_crtc_funcs , NULL );
700
693
drm_crtc_helper_add (crtc , & vc4_crtc_helper_funcs );
701
694
primary_plane -> crtc = crtc ;
702
- cursor_plane -> crtc = crtc ;
703
695
vc4 -> crtc [drm_crtc_index (crtc )] = vc4_crtc ;
704
696
vc4_crtc -> channel = vc4_crtc -> data -> hvs_channel ;
705
697
698
+ /* Set up some arbitrary number of planes. We're not limited
699
+ * by a set number of physical registers, just the space in
700
+ * the HVS (16k) and how small an plane can be (28 bytes).
701
+ * However, each plane we set up takes up some memory, and
702
+ * increases the cost of looping over planes, which atomic
703
+ * modesetting does quite a bit. As a result, we pick a
704
+ * modest number of planes to expose, that should hopefully
705
+ * still cover any sane usecase.
706
+ */
707
+ for (i = 0 ; i < 8 ; i ++ ) {
708
+ struct drm_plane * plane =
709
+ vc4_plane_init (drm , DRM_PLANE_TYPE_OVERLAY );
710
+
711
+ if (IS_ERR (plane ))
712
+ continue ;
713
+
714
+ plane -> possible_crtcs = 1 << drm_crtc_index (crtc );
715
+ }
716
+
717
+ /* Set up the legacy cursor after overlay initialization,
718
+ * since we overlay planes on the CRTC in the order they were
719
+ * initialized.
720
+ */
721
+ cursor_plane = vc4_plane_init (drm , DRM_PLANE_TYPE_CURSOR );
722
+ if (!IS_ERR (cursor_plane )) {
723
+ cursor_plane -> possible_crtcs = 1 << drm_crtc_index (crtc );
724
+ cursor_plane -> crtc = crtc ;
725
+ crtc -> cursor = cursor_plane ;
726
+ }
727
+
706
728
CRTC_WRITE (PV_INTEN , 0 );
707
729
CRTC_WRITE (PV_INTSTAT , PV_INT_VFP_START );
708
730
ret = devm_request_irq (dev , platform_get_irq (pdev , 0 ),
709
731
vc4_crtc_irq_handler , 0 , "vc4 crtc" , vc4_crtc );
710
732
if (ret )
711
- goto err_cursor ;
733
+ goto err_destroy_planes ;
712
734
713
735
vc4_set_crtc_possible_masks (drm , crtc );
714
736
715
737
platform_set_drvdata (pdev , vc4_crtc );
716
738
717
739
return 0 ;
718
740
719
- err_cursor :
720
- cursor_plane -> funcs -> destroy (cursor_plane );
721
- err_primary :
722
- primary_plane -> funcs -> destroy (primary_plane );
741
+ err_destroy_planes :
742
+ list_for_each_entry_safe (destroy_plane , temp ,
743
+ & drm -> mode_config .plane_list , head ) {
744
+ if (destroy_plane -> possible_crtcs == 1 << drm_crtc_index (crtc ))
745
+ destroy_plane -> funcs -> destroy (destroy_plane );
746
+ }
723
747
err :
724
748
return ret ;
725
749
}
0 commit comments