c3db8c7319b0cc75734493fa1ba94cb7333c9e83
[openwrt/staging/linusw.git] /
1 From 286cf26ca3f6628a82c8c37e7059585c8389b82a Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.com>
3 Date: Fri, 24 Jan 2020 14:25:41 +0000
4 Subject: [PATCH] drm/vc4: Add support for DRM_FORMAT_P030 to vc4
5 planes
6
7 This currently doesn't handle non-zero source rectangles correctly,
8 but add support for DRM_FORMAT_P030 with DRM_FORMAT_MOD_BROADCOM_SAND128
9 modifier to planes when running on HVS5.
10
11 WIP still for source cropping SAND/P030 formats
12
13 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
14 ---
15 drivers/gpu/drm/vc4/vc4_plane.c | 79 ++++++++++++++++++++++++---------
16 1 file changed, 57 insertions(+), 22 deletions(-)
17
18 --- a/drivers/gpu/drm/vc4/vc4_plane.c
19 +++ b/drivers/gpu/drm/vc4/vc4_plane.c
20 @@ -33,6 +33,7 @@ static const struct hvs_format {
21 u32 hvs; /* HVS_FORMAT_* */
22 u32 pixel_order;
23 u32 pixel_order_hvs5;
24 + bool hvs5_only;
25 } hvs_formats[] = {
26 {
27 .drm = DRM_FORMAT_XRGB8888,
28 @@ -128,6 +129,12 @@ static const struct hvs_format {
29 .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_2PLANE,
30 .pixel_order = HVS_PIXEL_ORDER_XYCRCB,
31 },
32 + {
33 + .drm = DRM_FORMAT_P030,
34 + .hvs = HVS_PIXEL_FORMAT_YCBCR_10BIT,
35 + .pixel_order = HVS_PIXEL_ORDER_XYCBCR,
36 + .hvs5_only = true,
37 + },
38 };
39
40 static const struct hvs_format *vc4_get_hvs_format(u32 drm_format)
41 @@ -769,27 +776,33 @@ static int vc4_plane_mode_set(struct drm
42 uint32_t param = fourcc_mod_broadcom_param(fb->modifier);
43 u32 tile_w, tile, x_off, pix_per_tile;
44
45 - hvs_format = HVS_PIXEL_FORMAT_H264;
46 -
47 - switch (base_format_mod) {
48 - case DRM_FORMAT_MOD_BROADCOM_SAND64:
49 - tiling = SCALER_CTL0_TILING_64B;
50 - tile_w = 64;
51 - break;
52 - case DRM_FORMAT_MOD_BROADCOM_SAND128:
53 + if (fb->format->format == DRM_FORMAT_P030) {
54 + hvs_format = HVS_PIXEL_FORMAT_YCBCR_10BIT;
55 tiling = SCALER_CTL0_TILING_128B;
56 - tile_w = 128;
57 - break;
58 - case DRM_FORMAT_MOD_BROADCOM_SAND256:
59 - tiling = SCALER_CTL0_TILING_256B_OR_T;
60 - tile_w = 256;
61 - break;
62 - default:
63 - break;
64 - }
65 + tile_w = 96;
66 + } else {
67 + hvs_format = HVS_PIXEL_FORMAT_H264;
68
69 + switch (base_format_mod) {
70 + case DRM_FORMAT_MOD_BROADCOM_SAND64:
71 + tiling = SCALER_CTL0_TILING_64B;
72 + tile_w = 64;
73 + break;
74 + case DRM_FORMAT_MOD_BROADCOM_SAND128:
75 + tiling = SCALER_CTL0_TILING_128B;
76 + tile_w = 128;
77 + break;
78 + case DRM_FORMAT_MOD_BROADCOM_SAND256:
79 + tiling = SCALER_CTL0_TILING_256B_OR_T;
80 + tile_w = 256;
81 + break;
82 + default:
83 + break;
84 + }
85 + }
86 if (param > SCALER_TILE_HEIGHT_MASK) {
87 - DRM_DEBUG_KMS("SAND height too large (%d)\n", param);
88 + DRM_DEBUG_KMS("SAND height too large (%d)\n",
89 + param);
90 return -EINVAL;
91 }
92
93 @@ -799,6 +812,13 @@ static int vc4_plane_mode_set(struct drm
94
95 /* Adjust the base pointer to the first pixel to be scanned
96 * out.
97 + *
98 + * For P030, y_ptr [31:4] is the 128bit word for the start pixel
99 + * y_ptr [3:0] is the pixel (0-11) contained within that 128bit
100 + * word that should be taken as the first pixel.
101 + * Ditto uv_ptr [31:4] vs [3:0], however [3:0] contains the
102 + * element within the 128bit word, eg for pixel 3 the value
103 + * should be 6.
104 */
105 for (i = 0; i < num_planes; i++) {
106 vc4_state->offsets[i] += param * tile_w * tile;
107 @@ -960,7 +980,8 @@ static int vc4_plane_mode_set(struct drm
108
109 /* Pitch word 1/2 */
110 for (i = 1; i < num_planes; i++) {
111 - if (hvs_format != HVS_PIXEL_FORMAT_H264) {
112 + if (hvs_format != HVS_PIXEL_FORMAT_H264 &&
113 + hvs_format != HVS_PIXEL_FORMAT_YCBCR_10BIT) {
114 vc4_dlist_write(vc4_state,
115 VC4_SET_FIELD(fb->pitches[i],
116 SCALER_SRC_PITCH));
117 @@ -1320,6 +1341,13 @@ static bool vc4_format_mod_supported(str
118 default:
119 return false;
120 }
121 + case DRM_FORMAT_P030:
122 + switch (fourcc_mod_broadcom_mod(modifier)) {
123 + case DRM_FORMAT_MOD_BROADCOM_SAND128:
124 + return true;
125 + default:
126 + return false;
127 + }
128 case DRM_FORMAT_RGBX1010102:
129 case DRM_FORMAT_BGRX1010102:
130 case DRM_FORMAT_RGBA1010102:
131 @@ -1352,8 +1380,11 @@ struct drm_plane *vc4_plane_init(struct
132 struct drm_plane *plane = NULL;
133 struct vc4_plane *vc4_plane;
134 u32 formats[ARRAY_SIZE(hvs_formats)];
135 + int num_formats = 0;
136 int ret = 0;
137 unsigned i;
138 + bool hvs5 = of_device_is_compatible(dev->dev->of_node,
139 + "brcm,bcm2711-vc5");
140 static const uint64_t modifiers[] = {
141 DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED,
142 DRM_FORMAT_MOD_BROADCOM_SAND128,
143 @@ -1368,13 +1399,17 @@ struct drm_plane *vc4_plane_init(struct
144 if (!vc4_plane)
145 return ERR_PTR(-ENOMEM);
146
147 - for (i = 0; i < ARRAY_SIZE(hvs_formats); i++)
148 - formats[i] = hvs_formats[i].drm;
149 + for (i = 0; i < ARRAY_SIZE(hvs_formats); i++) {
150 + if (!hvs_formats[i].hvs5_only || hvs5) {
151 + formats[num_formats] = hvs_formats[i].drm;
152 + num_formats++;
153 + }
154 + }
155
156 plane = &vc4_plane->base;
157 ret = drm_universal_plane_init(dev, plane, 0,
158 &vc4_plane_funcs,
159 - formats, ARRAY_SIZE(formats),
160 + formats, num_formats,
161 modifiers, type, NULL);
162 if (ret)
163 return ERR_PTR(ret);