@@ -33,6 +33,7 @@ static const struct hvs_format {
33
33
u32 hvs ; /* HVS_FORMAT_* */
34
34
u32 pixel_order ;
35
35
u32 pixel_order_hvs5 ;
36
+ bool hvs5_only ;
36
37
} hvs_formats [] = {
37
38
{
38
39
.drm = DRM_FORMAT_XRGB8888 ,
@@ -128,6 +129,12 @@ static const struct hvs_format {
128
129
.hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_2PLANE ,
129
130
.pixel_order = HVS_PIXEL_ORDER_XYCRCB ,
130
131
},
132
+ {
133
+ .drm = DRM_FORMAT_P030 ,
134
+ .hvs = HVS_PIXEL_FORMAT_YCBCR_10BIT ,
135
+ .pixel_order = HVS_PIXEL_ORDER_XYCBCR ,
136
+ .hvs5_only = true,
137
+ },
131
138
};
132
139
133
140
static const struct hvs_format * vc4_get_hvs_format (u32 drm_format )
@@ -762,47 +769,90 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
762
769
case DRM_FORMAT_MOD_BROADCOM_SAND128 :
763
770
case DRM_FORMAT_MOD_BROADCOM_SAND256 : {
764
771
uint32_t param = fourcc_mod_broadcom_param (fb -> modifier );
765
- u32 tile_w , tile , x_off , pix_per_tile ;
766
-
767
- hvs_format = HVS_PIXEL_FORMAT_H264 ;
768
-
769
- switch (base_format_mod ) {
770
- case DRM_FORMAT_MOD_BROADCOM_SAND64 :
771
- tiling = SCALER_CTL0_TILING_64B ;
772
- tile_w = 64 ;
773
- break ;
774
- case DRM_FORMAT_MOD_BROADCOM_SAND128 :
775
- tiling = SCALER_CTL0_TILING_128B ;
776
- tile_w = 128 ;
777
- break ;
778
- case DRM_FORMAT_MOD_BROADCOM_SAND256 :
779
- tiling = SCALER_CTL0_TILING_256B_OR_T ;
780
- tile_w = 256 ;
781
- break ;
782
- default :
783
- break ;
784
- }
785
772
786
773
if (param > SCALER_TILE_HEIGHT_MASK ) {
787
- DRM_DEBUG_KMS ("SAND height too large (%d)\n" , param );
774
+ DRM_DEBUG_KMS ("SAND height too large (%d)\n" ,
775
+ param );
788
776
return - EINVAL ;
789
777
}
790
778
791
- pix_per_tile = tile_w / fb -> format -> cpp [0 ];
792
- tile = vc4_state -> src_x / pix_per_tile ;
793
- x_off = vc4_state -> src_x % pix_per_tile ;
779
+ if (fb -> format -> format == DRM_FORMAT_P030 ) {
780
+ hvs_format = HVS_PIXEL_FORMAT_YCBCR_10BIT ;
781
+ tiling = SCALER_CTL0_TILING_128B ;
782
+ } else {
783
+ hvs_format = HVS_PIXEL_FORMAT_H264 ;
784
+
785
+ switch (base_format_mod ) {
786
+ case DRM_FORMAT_MOD_BROADCOM_SAND64 :
787
+ tiling = SCALER_CTL0_TILING_64B ;
788
+ break ;
789
+ case DRM_FORMAT_MOD_BROADCOM_SAND128 :
790
+ tiling = SCALER_CTL0_TILING_128B ;
791
+ break ;
792
+ case DRM_FORMAT_MOD_BROADCOM_SAND256 :
793
+ tiling = SCALER_CTL0_TILING_256B_OR_T ;
794
+ break ;
795
+ default :
796
+ return - EINVAL ;
797
+ }
798
+ }
794
799
795
800
/* Adjust the base pointer to the first pixel to be scanned
796
801
* out.
802
+ *
803
+ * For P030, y_ptr [31:4] is the 128bit word for the start pixel
804
+ * y_ptr [3:0] is the pixel (0-11) contained within that 128bit
805
+ * word that should be taken as the first pixel.
806
+ * Ditto uv_ptr [31:4] vs [3:0], however [3:0] contains the
807
+ * element within the 128bit word, eg for pixel 3 the value
808
+ * should be 6.
797
809
*/
798
810
for (i = 0 ; i < num_planes ; i ++ ) {
811
+ u32 tile_w , tile , x_off , pix_per_tile ;
812
+
813
+ if (fb -> format -> format == DRM_FORMAT_P030 ) {
814
+ /*
815
+ * Spec says: bits [31:4] of the given address
816
+ * should point to the 128-bit word containing
817
+ * the desired starting pixel, and bits[3:0]
818
+ * should be between 0 and 11, indicating which
819
+ * of the 12-pixels in that 128-bit word is the
820
+ * first pixel to be used
821
+ */
822
+ u32 remaining_pixels = vc4_state -> src_x % 96 ;
823
+ u32 aligned = remaining_pixels / 12 ;
824
+ u32 last_bits = remaining_pixels % 12 ;
825
+
826
+ x_off = aligned * 16 + last_bits ;
827
+ tile_w = 128 ;
828
+ pix_per_tile = 96 ;
829
+ } else {
830
+ switch (base_format_mod ) {
831
+ case DRM_FORMAT_MOD_BROADCOM_SAND64 :
832
+ tile_w = 64 ;
833
+ break ;
834
+ case DRM_FORMAT_MOD_BROADCOM_SAND128 :
835
+ tile_w = 128 ;
836
+ break ;
837
+ case DRM_FORMAT_MOD_BROADCOM_SAND256 :
838
+ tile_w = 256 ;
839
+ break ;
840
+ default :
841
+ return - EINVAL ;
842
+ }
843
+ pix_per_tile = tile_w / fb -> format -> cpp [0 ];
844
+ x_off = (vc4_state -> src_x % pix_per_tile ) /
845
+ (i ? h_subsample : 1 ) *
846
+ fb -> format -> cpp [i ];
847
+ }
848
+
849
+ tile = vc4_state -> src_x / pix_per_tile ;
850
+
799
851
vc4_state -> offsets [i ] += param * tile_w * tile ;
800
852
vc4_state -> offsets [i ] += src_y /
801
853
(i ? v_subsample : 1 ) *
802
854
tile_w ;
803
- vc4_state -> offsets [i ] += x_off /
804
- (i ? h_subsample : 1 ) *
805
- fb -> format -> cpp [i ];
855
+ vc4_state -> offsets [i ] += x_off & ~(i ? 1 : 0 );
806
856
}
807
857
808
858
pitch0 = VC4_SET_FIELD (param , SCALER_TILE_HEIGHT );
@@ -955,7 +1005,8 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
955
1005
956
1006
/* Pitch word 1/2 */
957
1007
for (i = 1 ; i < num_planes ; i ++ ) {
958
- if (hvs_format != HVS_PIXEL_FORMAT_H264 ) {
1008
+ if (hvs_format != HVS_PIXEL_FORMAT_H264 &&
1009
+ hvs_format != HVS_PIXEL_FORMAT_YCBCR_10BIT ) {
959
1010
vc4_dlist_write (vc4_state ,
960
1011
VC4_SET_FIELD (fb -> pitches [i ],
961
1012
SCALER_SRC_PITCH ));
@@ -1315,6 +1366,13 @@ static bool vc4_format_mod_supported(struct drm_plane *plane,
1315
1366
default :
1316
1367
return false;
1317
1368
}
1369
+ case DRM_FORMAT_P030 :
1370
+ switch (fourcc_mod_broadcom_mod (modifier )) {
1371
+ case DRM_FORMAT_MOD_BROADCOM_SAND128 :
1372
+ return true;
1373
+ default :
1374
+ return false;
1375
+ }
1318
1376
case DRM_FORMAT_RGBX1010102 :
1319
1377
case DRM_FORMAT_BGRX1010102 :
1320
1378
case DRM_FORMAT_RGBA1010102 :
@@ -1347,8 +1405,11 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev,
1347
1405
struct drm_plane * plane = NULL ;
1348
1406
struct vc4_plane * vc4_plane ;
1349
1407
u32 formats [ARRAY_SIZE (hvs_formats )];
1408
+ int num_formats = 0 ;
1350
1409
int ret = 0 ;
1351
1410
unsigned i ;
1411
+ bool hvs5 = of_device_is_compatible (dev -> dev -> of_node ,
1412
+ "brcm,bcm2711-vc5" );
1352
1413
static const uint64_t modifiers [] = {
1353
1414
DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED ,
1354
1415
DRM_FORMAT_MOD_BROADCOM_SAND128 ,
@@ -1363,13 +1424,17 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev,
1363
1424
if (!vc4_plane )
1364
1425
return ERR_PTR (- ENOMEM );
1365
1426
1366
- for (i = 0 ; i < ARRAY_SIZE (hvs_formats ); i ++ )
1367
- formats [i ] = hvs_formats [i ].drm ;
1427
+ for (i = 0 ; i < ARRAY_SIZE (hvs_formats ); i ++ ) {
1428
+ if (!hvs_formats [i ].hvs5_only || hvs5 ) {
1429
+ formats [num_formats ] = hvs_formats [i ].drm ;
1430
+ num_formats ++ ;
1431
+ }
1432
+ }
1368
1433
1369
1434
plane = & vc4_plane -> base ;
1370
1435
ret = drm_universal_plane_init (dev , plane , 0 ,
1371
1436
& vc4_plane_funcs ,
1372
- formats , ARRAY_SIZE ( formats ) ,
1437
+ formats , num_formats ,
1373
1438
modifiers , type , NULL );
1374
1439
if (ret )
1375
1440
return ERR_PTR (ret );
0 commit comments