11
11
#include <drm/drm_fourcc.h>
12
12
#include <drm/drm_framebuffer.h>
13
13
#include <drm/drm_gem_atomic_helper.h>
14
+ #include <linux/align.h>
14
15
15
16
#include "mtk_drm_crtc.h"
16
17
#include "mtk_drm_ddp_comp.h"
@@ -32,6 +33,14 @@ static const u32 formats[] = {
32
33
DRM_FORMAT_YUYV ,
33
34
};
34
35
36
+ static const u64 modifiers [] = {
37
+ DRM_FORMAT_MOD_LINEAR ,
38
+ DRM_FORMAT_MOD_ARM_AFBC (AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
39
+ AFBC_FORMAT_MOD_SPLIT |
40
+ AFBC_FORMAT_MOD_SPARSE ),
41
+ DRM_FORMAT_MOD_INVALID ,
42
+ };
43
+
35
44
static void mtk_plane_reset (struct drm_plane * plane )
36
45
{
37
46
struct mtk_plane_state * state ;
@@ -51,6 +60,7 @@ static void mtk_plane_reset(struct drm_plane *plane)
51
60
52
61
state -> base .plane = plane ;
53
62
state -> pending .format = DRM_FORMAT_RGB565 ;
63
+ state -> pending .modifier = DRM_FORMAT_MOD_LINEAR ;
54
64
}
55
65
56
66
static struct drm_plane_state * mtk_plane_duplicate_state (struct drm_plane * plane )
@@ -71,6 +81,32 @@ static struct drm_plane_state *mtk_plane_duplicate_state(struct drm_plane *plane
71
81
return & state -> base ;
72
82
}
73
83
84
+ static bool mtk_plane_format_mod_supported (struct drm_plane * plane ,
85
+ uint32_t format ,
86
+ uint64_t modifier )
87
+ {
88
+ if (modifier == DRM_FORMAT_MOD_LINEAR )
89
+ return true;
90
+
91
+ if (modifier != DRM_FORMAT_MOD_ARM_AFBC (
92
+ AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
93
+ AFBC_FORMAT_MOD_SPLIT |
94
+ AFBC_FORMAT_MOD_SPARSE ))
95
+ return false;
96
+
97
+ if (format != DRM_FORMAT_XRGB8888 &&
98
+ format != DRM_FORMAT_ARGB8888 &&
99
+ format != DRM_FORMAT_BGRX8888 &&
100
+ format != DRM_FORMAT_BGRA8888 &&
101
+ format != DRM_FORMAT_ABGR8888 &&
102
+ format != DRM_FORMAT_XBGR8888 &&
103
+ format != DRM_FORMAT_RGB888 &&
104
+ format != DRM_FORMAT_BGR888 )
105
+ return false;
106
+
107
+ return true;
108
+ }
109
+
74
110
static void mtk_drm_plane_destroy_state (struct drm_plane * plane ,
75
111
struct drm_plane_state * state )
76
112
{
@@ -119,21 +155,52 @@ static void mtk_plane_update_new_state(struct drm_plane_state *new_state,
119
155
struct drm_gem_object * gem ;
120
156
struct mtk_drm_gem_obj * mtk_gem ;
121
157
unsigned int pitch , format ;
158
+ u64 modifier ;
122
159
dma_addr_t addr ;
160
+ dma_addr_t hdr_addr = 0 ;
161
+ unsigned int hdr_pitch = 0 ;
123
162
124
163
gem = fb -> obj [0 ];
125
164
mtk_gem = to_mtk_gem_obj (gem );
126
165
addr = mtk_gem -> dma_addr ;
127
166
pitch = fb -> pitches [0 ];
128
167
format = fb -> format -> format ;
168
+ modifier = fb -> modifier ;
129
169
130
- addr += (new_state -> src .x1 >> 16 ) * fb -> format -> cpp [0 ];
131
- addr += (new_state -> src .y1 >> 16 ) * pitch ;
170
+ if (modifier == DRM_FORMAT_MOD_LINEAR ) {
171
+ addr += (new_state -> src .x1 >> 16 ) * fb -> format -> cpp [0 ];
172
+ addr += (new_state -> src .y1 >> 16 ) * pitch ;
173
+ } else {
174
+ int width_in_blocks = ALIGN (fb -> width , AFBC_DATA_BLOCK_WIDTH )
175
+ / AFBC_DATA_BLOCK_WIDTH ;
176
+ int height_in_blocks = ALIGN (fb -> height , AFBC_DATA_BLOCK_HEIGHT )
177
+ / AFBC_DATA_BLOCK_HEIGHT ;
178
+ int x_offset_in_blocks = (new_state -> src .x1 >> 16 ) / AFBC_DATA_BLOCK_WIDTH ;
179
+ int y_offset_in_blocks = (new_state -> src .y1 >> 16 ) / AFBC_DATA_BLOCK_HEIGHT ;
180
+ int hdr_size ;
181
+
182
+ hdr_pitch = width_in_blocks * AFBC_HEADER_BLOCK_SIZE ;
183
+ pitch = width_in_blocks * AFBC_DATA_BLOCK_WIDTH *
184
+ AFBC_DATA_BLOCK_HEIGHT * fb -> format -> cpp [0 ];
185
+
186
+ hdr_size = ALIGN (hdr_pitch * height_in_blocks , AFBC_HEADER_ALIGNMENT );
187
+
188
+ hdr_addr = addr + hdr_pitch * y_offset_in_blocks +
189
+ AFBC_HEADER_BLOCK_SIZE * x_offset_in_blocks ;
190
+ /* The data plane is offset by 1 additional block. */
191
+ addr = addr + hdr_size +
192
+ pitch * y_offset_in_blocks +
193
+ AFBC_DATA_BLOCK_WIDTH * AFBC_DATA_BLOCK_HEIGHT *
194
+ fb -> format -> cpp [0 ] * (x_offset_in_blocks + 1 );
195
+ }
132
196
133
197
mtk_plane_state -> pending .enable = true;
134
198
mtk_plane_state -> pending .pitch = pitch ;
199
+ mtk_plane_state -> pending .hdr_pitch = hdr_pitch ;
135
200
mtk_plane_state -> pending .format = format ;
201
+ mtk_plane_state -> pending .modifier = modifier ;
136
202
mtk_plane_state -> pending .addr = addr ;
203
+ mtk_plane_state -> pending .hdr_addr = hdr_addr ;
137
204
mtk_plane_state -> pending .x = new_state -> dst .x1 ;
138
205
mtk_plane_state -> pending .y = new_state -> dst .y1 ;
139
206
mtk_plane_state -> pending .width = drm_rect_width (& new_state -> dst );
@@ -172,6 +239,7 @@ static const struct drm_plane_funcs mtk_plane_funcs = {
172
239
.reset = mtk_plane_reset ,
173
240
.atomic_duplicate_state = mtk_plane_duplicate_state ,
174
241
.atomic_destroy_state = mtk_drm_plane_destroy_state ,
242
+ .format_mod_supported = mtk_plane_format_mod_supported ,
175
243
};
176
244
177
245
static int mtk_plane_atomic_check (struct drm_plane * plane ,
@@ -253,7 +321,7 @@ int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane,
253
321
254
322
err = drm_universal_plane_init (dev , plane , possible_crtcs ,
255
323
& mtk_plane_funcs , formats ,
256
- ARRAY_SIZE (formats ), NULL , type , NULL );
324
+ ARRAY_SIZE (formats ), modifiers , type , NULL );
257
325
if (err ) {
258
326
DRM_ERROR ("failed to initialize plane\n" );
259
327
return err ;
0 commit comments